Merge "timekeeping: utilize the suspend-nonstop clocksource to count suspended time"
diff --git a/Documentation/bif-framework.txt b/Documentation/bif-framework.txt
index 3ba500d..9831c80 100644
--- a/Documentation/bif-framework.txt
+++ b/Documentation/bif-framework.txt
@@ -235,10 +235,10 @@
Get/put handle for a BIF slave:
-------------------------------
-int bif_slave_match_count(const struct bif_ctrl *ctrl,
+int bif_slave_match_count(struct bif_ctrl *ctrl,
const struct bif_match_criteria *match_criteria);
-struct bif_slave *bif_slave_match_get(const struct bif_ctrl *ctrl,
+struct bif_slave *bif_slave_match_get(struct bif_ctrl *ctrl,
unsigned int id, const struct bif_match_criteria *match_criteria);
void bif_slave_put(struct bif_slave *slave);
@@ -293,7 +293,6 @@
int bif_ctrl_notifier_unregister(struct bif_ctrl *ctrl,
struct notifier_block *nb);
-
Read or write BIF slave registers:
----------------------------------
@@ -302,6 +301,53 @@
int bif_slave_write(struct bif_slave *slave, u16 addr, u8 *buf, int len);
+BIF slave non-volatile memory manipulation:
+-------------------------------------------
+
+int bif_slave_nvm_raw_read(struct bif_slave *slave, u16 offset, u8 *buf,
+ int len);
+
+int bif_slave_nvm_raw_write(struct bif_slave *slave, u16 offset, u8 *buf,
+ int len);
+
+Raw NVM writing may be needed in order to intialize the NVM BIF object list.
+However, its use can be dangerous as it can overwrite existing objects in the
+list and make the list unparsable.
+
+BIF object search in slave non-volatile memory:
+-----------------------------------------------
+int bif_object_match_count(struct bif_slave *slave,
+ const struct bif_obj_match_criteria *match_criteria);
+
+struct bif_object *bif_object_match_get(struct bif_slave *slave,
+ unsigned int id, const struct bif_obj_match_criteria *match_criteria);
+
+void bif_object_put(struct bif_object *object);
+
+bif_object_match_count() and bif_object_match_get() can be used together in
+order to retrieve the set of BIF objects within a slave which match certain
+criteria. bif_object_put() is used to free the memory allocated by
+bif_object_match_get().
+
+BIF object manipulation in slave non-volatile memory:
+-----------------------------------------------------
+int bif_object_write(struct bif_slave *slave, u8 type, u8 version, u16
+ manufacturer_id, const u8 *data, int data_len);
+
+int bif_object_overwrite(struct bif_slave *slave,
+ struct bif_object *object, u8 type, u8 version,
+ u16 manufacturer_id, const u8 *data, int data_len);
+
+int bif_object_delete(struct bif_slave *slave, const struct bif_object *object);
+
+bif_object_write() can be used to write a new BIF data object into the NVM of
+a given slave. The new object is added to the end of the NVM object list.
+bif_object_overwrite() can be used to overwrite an existing BIF data object
+in the NVM of a slave. The new object data must be the same size as the
+existing object data. bif_object_delete() can be used to delete a object from
+the NVM object list and shift all of the objects after it in order to fill the
+deleted object's space.
+
Get or set the BIF bus state or period:
---------------------------------------
@@ -341,11 +387,17 @@
int bif_task_is_busy(struct bif_slave *slave, unsigned int task);
+int bif_enable_auto_task(struct bif_slave *slave, unsigned int task);
+
+int bif_disable_auto_task(struct bif_slave *slave, unsigned int task);
+
A consumer can request a slave interrupt and specify a notifier to call when the
interrupt is triggered. Once the interrupt is requested the consumer will need
to call bif_trigger_task() in order to start the task associated with the
interrupt (both are identified by the same index). Polling for task completion
-is also supported via the bif_task_is_busy() function.
+is also supported via the bif_task_is_busy() function. Auto task triggered can
+be enabled and disabled for a given task using bif_enable_auto_task() and
+bif_disable_auto_task() respectively.
Raw BIF bus transactions:
-------------------------
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
index f57d928..917ea75 100644
--- a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
@@ -20,6 +20,7 @@
"pc_no_xo_shutdown" - Power Collapse with no XO shutdown
- qcom,l2: The state of L2 cache. Values are:
"l2_cache_pc" - L2 cache in power collapse
+ "l2_cache_pc_no_rpm" - L2 cache in power collapse. This mode wouldn't inform the RPM
"l2_cache_retenetion" - L2 cache in retention
"l2_cache_gdhs" - L2 cache in GDHS
"l2_cache_active" - L2 cache in active mode
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_tspp.txt b/Documentation/devicetree/bindings/arm/msm/msm_tspp.txt
index 5692ad2..4a1fb59 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm_tspp.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm_tspp.txt
@@ -38,7 +38,6 @@
the below optional properties:
- qcom,msm-bus,name
- qcom,msm-bus,num-cases
- - qcom,msm-bus,active-only
- qcom,msm-bus,num-paths
- qcom,msm-bus,vectors-KBps
@@ -85,7 +84,6 @@
qcom,msm-bus,name = "tsif";
qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<82 512 0 0>, /* No vote */
diff --git a/Documentation/devicetree/bindings/coresight/coresight.txt b/Documentation/devicetree/bindings/coresight/coresight.txt
index 17ff3f0..737e262 100644
--- a/Documentation/devicetree/bindings/coresight/coresight.txt
+++ b/Documentation/devicetree/bindings/coresight/coresight.txt
@@ -22,10 +22,24 @@
"arm,coresight-cti" for coresight cti devices,
"qcom,coresight-hwevent" for coresight hardware event devices
"arm,coresight-fuse" for coresight fuse device,
-- reg : physical base address and length of the register set(s) of the component
-- reg-names : names corresponding to each reg property value. The reg-names that
- need to be used with corresponding compatible string for a coresight device
- are:
+ "qcom,coresight-audio-etm" for coresight audio etm trace device,
+ "qcom,coresight-modem-etm" for coresight modem etm trace device,
+ "qcom,coresight-wcn-etm" for coresight wireless etm trace device,
+ "qcom,coresight-rpm-etm" for coresight rpm etm trace device
+- reg : physical base address and length of the register set(s) of the component.
+ Not required for the following compatible strings:
+ - "qcom,coresight-audio-etm",
+ - "qcom,coresight-modem-etm",
+ - "qcom,coresight-wcn-etm",
+ - "qcom,coresight-rpm-etm"
+- reg-names : names corresponding to each reg property value.
+ Not required for the following compatible strings:
+ - "qcom,coresight-audio-etm",
+ - "qcom,coresight-modem-etm",
+ - "qcom,coresight-wcn-etm",
+ - "qcom,coresight-rpm-etm"
+ The reg-names that need to be used with corresponding compatible string
+ for a coresight device are:
- for coresight tmc-etr or tmc-etf device:
compatible : should be "arm,coresight-tmc"
reg-names : should be:
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
index 7187908..cda437a 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
@@ -46,12 +46,6 @@
- qcom,platform-te-gpio: Specifies the gpio used for TE.
- qcom,platform-mode-gpio: Select video/command mode of panel through gpio when it supports
both modes.
-- qcom,platform-reset-sequence: An array that lists the
- sequence of reset gpio values and sleeps
- Each command will have the format defined
- as below:
- --> Reset GPIO value
- --> Sleep value (in ms)
Example:
mdss_dsi0: qcom,mdss_dsi@fd922800 {
@@ -77,7 +71,6 @@
qcom,platform-te-gpio = <&msmgpio 24 0>;
qcom,platform-enable-gpio = <&msmgpio 58 1>;
qcom,platform-mode-gpio = <&msmgpio 7 0>;
- qcom,platform-reset-sequence = <1 25 0 20 1 10>;
qcom,platform-supply-entry1 {
qcom,supply-name = "vdd";
qcom,supply-min-voltage = <2800000>;
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 20ef421..1a44f5a 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -242,6 +242,14 @@
in dsi controller.
"high" = Set GPIO to HIGH
"low" = Set GPIO to LOW
+- qcom,partial-update-enabled: Boolean used to enable partial
+ panel update for command mode panels.
+- qcom,mdss-dsi-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)
Note, if a given optional qcom,* binding is not present, then the driver will configure
@@ -333,5 +341,7 @@
qcom,mdss-pan-physical-width-dimension = <60>;
qcom,mdss-pan-physical-height-dimension = <140>;
qcom,mdss-dsi-panel-mode-gpio-state = "low";
+ qcom,partial-update-enabled;
+ qcom,mdss-dsi-reset-sequence = <1 2>, <0 10>, <1 10>;
};
};
diff --git a/Documentation/devicetree/bindings/fb/mdss-edp.txt b/Documentation/devicetree/bindings/fb/mdss-edp.txt
index 3d7e5a2..e564cd5 100644
--- a/Documentation/devicetree/bindings/fb/mdss-edp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-edp.txt
@@ -3,6 +3,9 @@
MDSS EDP is a edp driver which supports panels that are compatable with
VESA EDP display interface specification.
+When configuring the optional properties for external backlight, one should also
+configure the gpio that drives the pwm to it.
+
Required properties
- compatible : Must be "qcom,mdss-edp".
- reg : Offset and length of the register set for the
@@ -12,8 +15,6 @@
- vdda-supply : Phandle for vdd regulator device node.
- gpio-panel-en : GPIO for supplying power to panel and backlight
driver.
-- qcom,panel-lpg-channel : LPG channel for backlight.
-- qcom,panel-pwm-period : PWM period in microseconds.
- status : A string that has to be set to "okay/ok" to enable
the driver. By default this property will be set to
"disable". Will be set to "ok/okay" status for
@@ -37,4 +38,8 @@
gpio-panel-hpd = <&msmgpio 102 0>;
};
+Optional properties
+- qcom,panel-lpg-channel : LPG channel for backlight.
+- qcom,panel-pwm-period : PWM period in microseconds.
+
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 5a70b6b..a4e61e8 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -106,6 +106,8 @@
- "hdmi"
Optional properties:
+- vdd-cx-supply : Phandle for vdd CX regulator device node.
+- batfet-supply : Phandle for battery FET regulator device node.
- qcom,vbif-settings : Array with key-value pairs of constant VBIF register
settings used to setup MDSS QoS for optimum performance.
The key used should be offset from "vbif_phys" register
@@ -139,6 +141,11 @@
restricted for a source surface pipe. If this
property is not specified, no such restriction
would be applied.
+- qcom,mdss-pipe-rgb-fixed-mmb: Array of indexes describing fixed Memory Macro
+ Blocks (MMBs) for rgb pipes. First value denotes
+ total numbers of MMBs per pipe while values, if
+ any, following first one denotes indexes of MMBs
+ to that RGB pipe.
Optional subnodes:
Child nodes representing the frame buffer virtual devices.
@@ -177,6 +184,8 @@
reg-names = "mdp_phys", "vbif_phys";
interrupts = <0 72 0>;
vdd-supply = <&gdsc_mdss>;
+ vdd-cx-supply = <&pm8841_s2_corner>;
+ batfet-supply = <&pm8941_chg_batif>;
qcom,max-clk-rate = <320000000>;
qcom,vbif-settings = <0x0004 0x00000001>,
<0x00D8 0x00000707>;
@@ -190,6 +199,10 @@
qcom,mdss-pipe-vig-fetch-id = <1 4 7>;
qcom,mdss-pipe-rgb-fetch-id = <16 17 18>;
qcom,mdss-pipe-dma-fetch-id = <10 13>;
+ qcom,mdss-pipe-rgb-fixed-mmb = <2 0 1>,
+ <2 2 3>,
+ <2 4 5>,
+ <2 6 7>;
qcom,mdss-smp-data = <22 4096>;
qcom,mdss-rot-block-size = <64>;
qcom,mdss-smp-mb-per-pipe = <2>;
diff --git a/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
index c563067e..02186c9 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/ft5x06-ts.txt
@@ -23,29 +23,34 @@
- focaltech,display-coords : display coordinates in pixels. It is a four
tuple consisting of min x, min y, max x and
max y values
- - focaltech,name : name of the controller
- focaltech,group-id : group id of this device
+ - focaltech,num-max-touches : maximum number of touches supported
- focaltech,hard-reset-delay-ms : hard reset delay in ms
- focaltech,soft-reset-delay-ms : soft reset delay in ms
-
-Optional properties:
-
- - focaltech,panel-coords : panel coordinates for the chip in pixels.
- It is a four tuple consisting of min x,
- min y, max x and max y values
- - focaltech,i2c-pull-up : to specify pull up is required
- - focaltech,no-force-update : to specify force update is allowed
- - focaltech,button-map : button map of key codes. The number
- of key codes depend on panel
- - focaltech,fw-name : specify the firmware file name
- - focaltech,fw-delay-aa-ms : specify the "aa" delay in ms for firmware upgrade
- - focaltech,fw-delay-55-ms : specify the "55" delay in ms for firmware upgrade
+ - focaltech,fw-delay-aa-ms : specify the delay in ms after programming 0xaa
+ register for firmware upgrade
+ - focaltech,fw-delay-55-ms : specify the delay in ms after programming 0x55
+ register for firmware upgrade
- focaltech,fw-upgrade-id1 : specify the upgrade id1 for firmware upgrade
- focaltech,fw-upgrade-id2 : specify the upgrade id2 for firmware upgrade
- focaltech,fw-delay-readid-ms : specify the read id delay in ms for firmware upgrade
- focaltech,fw-delay-era-flsh-ms : specify the erase flash delay in ms for firmware upgrade
+
+Optional properties:
+
+ - focaltech,name : name of the controller
+ - focaltech,i2c-pull-up : to specify pull up is required
+ - focaltech,no-force-update : to specify force update is allowed
+ - focaltech,button-map : button map of key codes. The number
+ - focaltech,fw-vkey-support : specify if virtual keys are supported through firmware
+ of key codes depend on panel
- focaltech,fw-auto-cal : specify whether calibration is needed after firmware upgrade
- focaltech,fw-vkey-support : specify if virtual keys are supported through firmware
+ - focaltech,ignore-id-check : specify ignore family-id check
+ - focaltech,panel-coords : panel coordinates for the chip in pixels.
+ It is a four tuple consisting of min x,
+ min y, max x and max y values
+ - focaltech,fw-name : specify the firmware file name
Example:
i2c@f9923000{
diff --git a/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt b/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt
index 3e223e6..fdba7c2 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/gt9xx/gt9xx.txt
@@ -7,7 +7,7 @@
- interrupt-parent : Parent of interrupt.
- interrupts : Configuration of touch panel controller interrupt
GPIO.
- - goodix,family-id : Family identification of the controller.
+ - goodix,product-id : Product identification of the controller.
- interrupt-gpios : Interrupt gpio which is to provide interrupts to
host, same as "interrupts" node.
- reset-gpios : Reset gpio to control the reset of chip.
@@ -32,10 +32,24 @@
- goodix,no-force-update : To specify force update is allowed.
- goodix,button-map : Button map of key codes. The number of key codes
depend on panel.
- - goodix,cfg-data : Touchpanel controller configuration data, ask vendor
- to provide that. Default configuration will be
- used if this property is not present.
-
+ - goodix,cfg-data0 : Touch screen controller config data group 0. Ask vendor
+ to provide that.
+ Driver supports maximum six config groups. If more than one
+ groups are defined, driver will select config group depending
+ on hardware configuration. If only config group 0 is defined,
+ it will be used for all hardware configurations.
+ Touch screen controller will use its onchip default config data
+ if this property is not present.
+ - goodix,cfg-data1 : Touch screen controller config data group 1. Ask vendor
+ to provide that.
+ - goodix,cfg-data2 : Touch screen controller config data group 2. Ask vendor
+ to provide that.
+ - goodix,cfg-data3 : Touch screen controller config data group 3. Ask vendor
+ to provide that.
+ - goodix,cfg-data4 : Touch screen controller config data group 4. Ask vendor
+ to provide that.
+ - goodix,cfg-data5 : Touch screen controller config data group 5. Ask vendor
+ to provide that.
Example:
i2c@f9927000 {
goodix@5d {
@@ -49,26 +63,26 @@
goodix,panel-coords = <0 0 720 1200>;
goodix,display-coords = <0 0 720 1080>;
goodix,button-map= <158 102 139>;
- goodix,family-id = <0x0>;
- goodix,cfg-data = [
- 41 D0 02 00 05 0A 05 01 01 08
- 12 58 50 41 03 05 00 00 00 00
- 00 00 00 00 00 00 00 8C 2E 0E
- 28 24 73 13 00 00 00 83 03 1D
- 40 02 00 00 00 03 64 32 00 00
- 00 1A 38 94 C0 02 00 00 00 04
- 9E 1C 00 8D 20 00 7A 26 00 6D
- 2C 00 60 34 00 60 10 38 68 00
- F0 50 35 FF FF 27 00 00 00 00
- 00 01 1B 14 0C 14 00 00 01 00
- 00 00 00 00 00 00 00 00 00 00
- 00 00 02 04 06 08 0A 0C 0E 10
- 12 14 16 18 1A 1C FF FF FF FF
- FF FF FF FF FF FF FF FF FF FF
- FF FF 00 02 04 06 08 0A 0C 0F
- 10 12 13 14 16 18 1C 1D 1E 1F
- 20 21 22 24 26 28 29 2A FF FF
- FF FF FF FF FF FF FF 22 22 22
- 22 22 22 FF 07 01];
+ goodix,product-id = "915";
+ goodix,cfg-data0 = [
+ 41 D0 02 00 05 0A 05 01 01 08
+ 12 58 50 41 03 05 00 00 00 00
+ 00 00 00 00 00 00 00 8C 2E 0E
+ 28 24 73 13 00 00 00 83 03 1D
+ 40 02 00 00 00 03 64 32 00 00
+ 00 1A 38 94 C0 02 00 00 00 04
+ 9E 1C 00 8D 20 00 7A 26 00 6D
+ 2C 00 60 34 00 60 10 38 68 00
+ F0 50 35 FF FF 27 00 00 00 00
+ 00 01 1B 14 0C 14 00 00 01 00
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00 02 04 06 08 0A 0C 0E 10
+ 12 14 16 18 1A 1C FF FF FF FF
+ FF FF FF FF FF FF FF FF FF FF
+ FF FF 00 02 04 06 08 0A 0C 0F
+ 10 12 13 14 16 18 1C 1D 1E 1F
+ 20 21 22 24 26 28 29 2A FF FF
+ FF FF FF FF FF FF FF 22 22 22
+ 22 22 22 FF 07 01];
};
};
diff --git a/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt b/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
index c7c6415..cf21158 100644
--- a/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
+++ b/Documentation/devicetree/bindings/iommu/msm_iommu_v0.txt
@@ -14,6 +14,7 @@
- qcom,needs-alt-core-clk : boolean to enable the secondary core clock for
access to the IOMMU configuration registers
- Bus scaling properties: See msm_bus.txt
+- qcom,msm-enable-remote-spinlock : boolean to enable use of remote spinlock
- List of sub nodes, one for each of the translation context banks supported.
Required properties for each sub-node:
diff --git a/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt b/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt
index d848baf..3b2c44c 100644
--- a/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-camera-flash.txt
@@ -10,6 +10,10 @@
- qcom,flash-type : Should contain type flash device
- 1 for LED flash
- 2 for strobe flash
+ - 3 for simple led flash controlled by one gpio
+ This is a low cost led used for camera flash, the led is driven by
+ system power, and use a transistor controlled by external pin to
+ gate its on/off state.
- qcom,flash-source : Should contain array of phandles to flash source nodes.
- pm8941_flash0 pm8941_flash1
diff --git a/Documentation/devicetree/bindings/media/video/msm-cci.txt b/Documentation/devicetree/bindings/media/video/msm-cci.txt
index c60441f..317c078 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cci.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cci.txt
@@ -49,6 +49,7 @@
Required properties:
- compatible : should be manufacturer name followed by sensor name
- "qcom,s5k3l1yx"
+ - "sne,imx134"
- "qcom,imx135"
- "shinetech,gc0339"
- "shinetech,hi256"
diff --git a/Documentation/devicetree/bindings/media/video/msm-eeprom.txt b/Documentation/devicetree/bindings/media/video/msm-eeprom.txt
index 893c033..c7821f5 100644
--- a/Documentation/devicetree/bindings/media/video/msm-eeprom.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-eeprom.txt
@@ -10,7 +10,7 @@
- cell-index: eeprom hardware core index
- compatible :
- "qcom,eeprom"
-- reg : offset and length of eeprom device registers.
+- reg : offset of eeprom device registers.
- qcom,eeprom-name : should specify relevant names of the eeprom module
library.
- qcom,slave-addr : should specify the slave address of the eeprom.
@@ -29,7 +29,6 @@
data type, delay in ms. size 0 stand for not used.
- address type : 1 byte, 2 word.
- data type : 1 byte, 2 word.
-- cam_vdig-supply : should contain regulator to be used for the digital vdd.
- cam_vio-supply : should contain regulator to be used for the IO vdd.
- qcom,cam-vreg-name : should specify the regulator name to be used for
this eeprom.
@@ -57,6 +56,7 @@
Optional properties:
- qcom,pageen%d : number %d page enable reg size, start address, address type,
data, data type, delay in ms. size 0 stand for not used.
+- cam_vdig-supply : should contain regulator to be used for the digital vdd.
Example:
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index 6f6f68d..d9376e9 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -39,26 +39,26 @@
as "enum cp_mem_usage" in include/linux/msm_ion.h
- qcom,has-ocmem: indicate the target has ocmem if this property exists
- qcom,vidc-iommu-domains: node containing individual domain nodes, each with:
- - a unique domain name for the domain node (e.g vidc,domain-ns)
- - qcom,vidc-domain-phandle: phandle for the domain as defined in
- <target>-iommu-domains.dtsi (e.g msm8974-v1-iommu-domains.dtsi)
- - qcom,vidc-partition-buffer-types: bitmap of buffer types that can
- be mapped into each IOMMU domain partition. There must be exactly
- one buffer bitmap per partition in the domain, with order of the
- bitmaps to be the same as the order of the respective partitions.
- - Buffer types are defined as the following:
- input = 0x1
- output = 0x2
- output2 = 0x2
- extradata input = 0x4
- extradata output = 0x8
- extradata output2 = 0x8
- internal scratch = 0x10
- internal scratch1 = 0x20
- internal scratch2 = 0x40
- internal persist = 0x80
- internal persist1 = 0x100
- internal cmd queue = 0x200
+ - a unique domain name for the domain node (e.g vidc,domain-ns)
+ - qcom,vidc-domain-phandle: phandle for the domain as defined in
+ <target>-iommu-domains.dtsi (e.g msm8974-v1-iommu-domains.dtsi)
+ - qcom,vidc-partition-buffer-types: bitmap of buffer types that can
+ be mapped into each IOMMU domain partition. There must be exactly
+ one buffer bitmap per partition in the domain, with order of the
+ bitmaps to be the same as the order of the respective partitions.
+ - Buffer types are defined as the following:
+ input = 0x1
+ output = 0x2
+ output2 = 0x4
+ extradata input = 0x8
+ extradata output = 0x10
+ extradata output2 = 0x20
+ internal scratch = 0x40
+ internal scratch1 = 0x80
+ internal scratch2 = 0x100
+ internal persist = 0x200
+ internal persist1 = 0x400
+ internal cmd queue = 0x800
Example:
@@ -95,14 +95,14 @@
qcom,vidc-iommu-domains {
qcom,domain-ns {
qcom,vidc-domain-phandle = <&venus_domain_ns>;
- qcom,vidc-partition-buffer-types = <0x1ff>,
- <0x200>;
+ qcom,vidc-partition-buffer-types = <0x7ff>,
+ <0x800>;
};
qcom,domain-cp {
qcom,vidc-domain-phandle = <&venus_domain_cp>;
- qcom,vidc-partition-buffer-types = <0x2>,
- <0x1f1>;
+ qcom,vidc-partition-buffer-types = <0x6>,
+ <0x7c1>;
};
};
};
diff --git a/Documentation/devicetree/bindings/nfc/nfc-nci.txt b/Documentation/devicetree/bindings/nfc/nfc-nci.txt
index f70d90f..cdd1e68 100644
--- a/Documentation/devicetree/bindings/nfc/nfc-nci.txt
+++ b/Documentation/devicetree/bindings/nfc/nfc-nci.txt
@@ -8,6 +8,8 @@
- reg: NCI i2c slave address.
- qcom,dis-gpio: specific gpio for hardware reset.
- qcom,irq-gpio: specific gpio for read interrupt.
+- qcom,clk-src: nfc clock source ("BBCLK2", "RFCLK3", "GPCLK", ...)
+- qcom,clk-en-gpio: msm gpio clock,used ony if clock source is msm gpio
- interrupt-parent: Should be phandle for the interrupt controller
that services interrupts for this device.
- interrupts: should contain the NFC interrupt. NFC has one read interrupt.
@@ -21,6 +23,8 @@
reg = <0x0e>;
qcom,irq-gpio = <&msmgpio 21 0x00>;
qcom,dis-gpio = <&msmgpio 20 0x00>;
+ qcom,clk-src = "BBCLK2";
+ qcom,clk-en-gpio = <&msmgpio 0 0x00>;
interrupt-parent = <&msmgpio>;
interrupts = <21 0>;
qcom,clk-gpio = <&pm8226_gpios 3 0>;
diff --git a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
index 3095b0a..83237f9 100644
--- a/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
+++ b/Documentation/devicetree/bindings/platform/msm/qpnp-power-on.txt
@@ -56,6 +56,7 @@
0 = Not supported
1 = Supported
This property is set to '0' if not specified.
+- qcom,use-bark Specify if this pon type needs to handle bark irq
- qcom,s1-timer The debounce timer for the BARK interrupt for
that reset source. Value is specified in ms.
Supported values are -
@@ -106,6 +107,7 @@
qcom,s2-timer = <2000>;
qcom,s2-type = <1>;
linux,code = <114>;
+ qcom,use-bark;
};
qcom,pon_3 {
@@ -115,5 +117,6 @@
qcom,s2-timer = <2000>;
qcom,s2-type = <7>;
qcom,pull-up = <1>;
+ qcom,use-bark;
};
};
diff --git a/Documentation/devicetree/bindings/power/qpnp-charger.txt b/Documentation/devicetree/bindings/power/qpnp-charger.txt
index b1c4ebb..5425c92 100644
--- a/Documentation/devicetree/bindings/power/qpnp-charger.txt
+++ b/Documentation/devicetree/bindings/power/qpnp-charger.txt
@@ -37,6 +37,9 @@
- qcom,maxinput-usb-ma: Maximum input current USB.
- qcom,maxinput-dc-ma: Maximum input current DC.
- qcom,vbatdet-delta-mv: Battery charging resume delta.
+- qcom,vbatweak-mv: Weak battery voltage threshold in mV, above which
+ fast charging can start. The supported voltage range is
+ from 2100mV to 3600mV with a step size of 100mV.
- qcom,charging-disabled: Set this property to disable charging
by default. This can then be overriden
writing the the module parameter
@@ -86,6 +89,10 @@
that exhibit inaccuracies in battery current readings. This
phandle is used to check the version of the PMIC and apply
necessary software workarounds.
+- qcom,ovp-monitor-en The ovp is enabled on hw by default. If this flag is
+ set, the charger ovp status is monitored in software.
+- qcom,ext-ovp-present Indicates if an external OVP exists which reduces the
+ overall input resistance of the charge path.
Sub node required structure:
- A qcom,chg node must be a child of an SPMI node that has specified
@@ -200,6 +207,7 @@
qcom,ibatmax-ma = <1500>;
qcom,ibatterm-ma = <200>;
qcom,ibatsafe-ma = <1500>;
+ qcom,vbatweak-mv = <3200>;
qcom,thermal-mitigation = <1500 700 600 325>;
qcom,cool-bat-degc = <10>;
qcom,cool-bat-mv = <4100>;
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index 53e912a..a7a646d 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -56,6 +56,8 @@
TX fifo allocation in bytes
- qcom,dwc-usb3-msm-qdss-tx-fifo-size: If present, represent RAM size available
for TX fifo allocation in QDSS composition
+- qcom,dwc-ssphy-deemphasis-value: This property if present represents ss phy
+ deemphasis value to be used for overriding into SSPHY register.
Sub nodes:
- Sub node for "DWC3- USB3 controller".
@@ -82,6 +84,7 @@
qcom,dwc_usb3-adc_tm = <&pm8941_adc_tm>;
qcom,dwc-usb3-msm-tx-fifo-size = <29696>;
qcom,dwc-usb3-msm-qdss-tx-fifo-size = <16384>;
+ qcom,dwc-ssphy-deemphasis-value = <26>;
qcom,msm_bus,name = "usb3";
qcom,msm_bus,num_cases = <2>;
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 1eec990..35e7324 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -45,6 +45,7 @@
samsung Samsung Semiconductor
sbs Smart Battery System
schindler Schindler
+sne Sony
stk Sensortek Technology Corporation.(formerly Sitronix Technology Co., Ltd.)
shinetech Shine Tech Corporation, Ltd.
sil Silicon Image
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index a419f5e..8a20b47 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -26,6 +26,7 @@
- boot_reason [ ARM only ]
- callhome [ S390 only ]
- cap_last_cap
+- cold_boot [ ARM only ]
- core_pattern
- core_pipe_limit
- core_uses_pid
@@ -176,6 +177,16 @@
Highest valid capability of the running kernel. Exports
CAP_LAST_CAP from the kernel.
+===============================================================
+
+cold_boot
+
+ARM -- indicator for system cold boot
+
+A single bit will be set in the unsigned integer value to identify
+whether the device was booted from a cold or warm state. Zero
+indicating a warm boot and one indicating a cold boot.
+
==============================================================
core_pattern:
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index aa37edc..9468df5 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -222,7 +222,8 @@
default DRAM_BASE if REMAP_VECTORS_TO_RAM
default 0x00000000
help
- The base address of exception vectors.
+ The base address of exception vectors. This must be two pages
+ in size.
config ARM_PATCH_PHYS_VIRT
bool "Patch physical to virtual translations at runtime" if EMBEDDED
@@ -1852,13 +1853,36 @@
config ENABLE_DMM
def_bool n
+choice
+ prompt "Virtual Memory Reclaim"
+ default NO_VM_RECLAIM
+ help
+ Select the method of reclaiming virtual memory
+
config DONT_MAP_HOLE_AFTER_MEMBANK0
- def_bool n
- depends on ENABLE_VMALLOC_SAVING=n
+ bool "Map around the largest hole"
+ help
+ Do not map the memory belonging to the largest hole
+ into the virtual space. This results in more lowmem.
+ If multiple holes are present, only the largest hole
+ in the first 256MB of memory is not mapped.
config ENABLE_VMALLOC_SAVING
- def_bool n
- depends on DONT_MAP_HOLE_AFTER_MEMBANK0=n
+ bool "Reclaim memory for each subsystem"
+ help
+ Enable this config to reclaim the virtual space belonging
+ to any subsystem which is expected to have a lifetime of
+ the entire system. This feature allows lowmem to be non-
+ contiguous.
+
+config NO_VM_RECLAIM
+ bool "Do not reclaim memory"
+ help
+ Do not reclaim any memory. This might result in less lowmem
+ and wasting virtual memory space which could otherwise be
+ reclaimed by using any of the other two config options.
+
+endchoice
config HOLES_IN_ZONE
def_bool n
diff --git a/arch/arm/boot/dts/apq8074-dragonboard.dtsi b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
index 60bb518..8afd986 100644
--- a/arch/arm/boot/dts/apq8074-dragonboard.dtsi
+++ b/arch/arm/boot/dts/apq8074-dragonboard.dtsi
@@ -23,9 +23,12 @@
status = "ok";
};
- qcom,mdss_dsi_sharp_qhd_video {
- status = "ok";
- qcom,cont-splash-enabled;
+ qcom,mdss_dsi@fd922800 {
+ qcom,dsi-pref-prim-pan = <&dsi_sharp_qhd_vid>;
+ };
+
+ qcom,mdss_mdp@fd900000 {
+ qcom,mdss-pref-prim-intf = "dsi";
};
qcom,hdmi_tx@fd922100 {
@@ -670,3 +673,7 @@
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
status = "ok";
};
+
+&dsi_sharp_qhd_vid {
+ qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/apq8074-v1-ion.dtsi b/arch/arm/boot/dts/apq8074-v1-ion.dtsi
new file mode 100644
index 0000000..49d7ee1
--- /dev/null
+++ b/arch/arm/boot/dts/apq8074-v1-ion.dtsi
@@ -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.
+ */
+
+&soc {
+ qcom,ion {
+ qcom,ion-heap@23 { /* OTHER PIL HEAP */
+ compatible = "qcom,msm-ion-reserve";
+ reg = <23>;
+ qcom,heap-align = <0x1000>;
+ qcom,memory-fixed = <0x0dc00000 0x1e00000>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/apq8074-v1.dtsi b/arch/arm/boot/dts/apq8074-v1.dtsi
index c4e7b7c..59e7f7f 100644
--- a/arch/arm/boot/dts/apq8074-v1.dtsi
+++ b/arch/arm/boot/dts/apq8074-v1.dtsi
@@ -17,6 +17,7 @@
*/
/include/ "msm8974-v1.dtsi"
+/include/ "apq8074-v1-ion.dtsi"
&soc {
qcom,qseecom@a700000 {
diff --git a/arch/arm/boot/dts/apq8074-v2.0-1-ion.dtsi b/arch/arm/boot/dts/apq8074-v2.0-1-ion.dtsi
new file mode 100644
index 0000000..49d7ee1
--- /dev/null
+++ b/arch/arm/boot/dts/apq8074-v2.0-1-ion.dtsi
@@ -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.
+ */
+
+&soc {
+ qcom,ion {
+ qcom,ion-heap@23 { /* OTHER PIL HEAP */
+ compatible = "qcom,msm-ion-reserve";
+ reg = <23>;
+ qcom,heap-align = <0x1000>;
+ qcom,memory-fixed = <0x0dc00000 0x1e00000>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/apq8074-v2.0-1.dtsi b/arch/arm/boot/dts/apq8074-v2.0-1.dtsi
index 2b75fa2..3575c92 100644
--- a/arch/arm/boot/dts/apq8074-v2.0-1.dtsi
+++ b/arch/arm/boot/dts/apq8074-v2.0-1.dtsi
@@ -17,6 +17,7 @@
*/
/include/ "msm8974-v2.0-1.dtsi"
+/include/ "apq8074-v2.0-1-ion.dtsi"
&soc {
qcom,qseecom@a700000 {
diff --git a/arch/arm/boot/dts/apq8074-v2.2-ion.dtsi b/arch/arm/boot/dts/apq8074-v2.2-ion.dtsi
new file mode 100644
index 0000000..49d7ee1
--- /dev/null
+++ b/arch/arm/boot/dts/apq8074-v2.2-ion.dtsi
@@ -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.
+ */
+
+&soc {
+ qcom,ion {
+ qcom,ion-heap@23 { /* OTHER PIL HEAP */
+ compatible = "qcom,msm-ion-reserve";
+ reg = <23>;
+ qcom,heap-align = <0x1000>;
+ qcom,memory-fixed = <0x0dc00000 0x1e00000>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/apq8074-v2.2.dtsi b/arch/arm/boot/dts/apq8074-v2.2.dtsi
index ddf7ec8..18f00c5 100644
--- a/arch/arm/boot/dts/apq8074-v2.2.dtsi
+++ b/arch/arm/boot/dts/apq8074-v2.2.dtsi
@@ -17,6 +17,7 @@
*/
/include/ "msm8974-v2.2.dtsi"
+/include/ "apq8074-v2.2-ion.dtsi"
&soc {
qcom,qseecom@a700000 {
diff --git a/arch/arm/boot/dts/batterydata-mtp-3000mah.dtsi b/arch/arm/boot/dts/batterydata-mtp-3000mah.dtsi
new file mode 100644
index 0000000..8dc6f71
--- /dev/null
+++ b/arch/arm/boot/dts/batterydata-mtp-3000mah.dtsi
@@ -0,0 +1,108 @@
+/* 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,mtp-3000mah {
+ qcom,fcc-mah = <3000>;
+ qcom,default-rbatt-mohm = <113>;
+ qcom,max-voltage-uv = <4200000>;
+ qcom,rbatt-capacitive-mohm = <50>;
+ qcom,v-cutoff-uv = <3400000>;
+ qcom,chg-term-ua = <200000>;
+ qcom,batt-id-kohm = <300>;
+
+ qcom,fcc-temp-lut {
+ qcom,lut-col-legend = <(-20) 0 25 40 60>;
+ qcom,lut-data = <3030 3033 3037 3035 3031>;
+ };
+
+ qcom,pc-temp-ocv-lut {
+ qcom,lut-col-legend = <(-20) 0 25 40 60>;
+ qcom,lut-row-legend = <100 95 90 85 80>,
+ <75 70 65 60 55>,
+ <50 45 40 35 30>,
+ <25 20 16 13 11>,
+ <10 9 8 7 6>,
+ <5 4 3 2 1>,
+ <0>;
+ qcom,lut-data = <4191 4188 4183 4179 4174>,
+ <4106 4125 4127 4125 4121>,
+ <4046 4082 4082 4080 4077>,
+ <3966 4038 4044 4040 4035>,
+ <3922 3983 3994 3998 3997>,
+ <3886 3949 3966 3966 3962>,
+ <3856 3908 3937 3935 3931>,
+ <3832 3875 3908 3907 3903>,
+ <3814 3847 3874 3878 3875>,
+ <3799 3826 3831 3832 3830>,
+ <3787 3807 3811 3811 3809>,
+ <3775 3793 3795 3795 3793>,
+ <3764 3782 3783 3783 3781>,
+ <3752 3775 3773 3772 3769>,
+ <3739 3768 3766 3762 3755>,
+ <3725 3756 3756 3747 3733>,
+ <3710 3732 3734 3725 3711>,
+ <3696 3707 3705 3697 3684>,
+ <3681 3695 3686 3678 3667>,
+ <3667 3690 3684 3676 3665>,
+ <3658 3688 3683 3675 3664>,
+ <3646 3685 3681 3674 3663>,
+ <3631 3682 3679 3673 3660>,
+ <3612 3677 3676 3669 3655>,
+ <3589 3667 3666 3660 3639>,
+ <3560 3643 3636 3630 3599>,
+ <3523 3600 3586 3581 3546>,
+ <3474 3537 3518 3516 3477>,
+ <3394 3446 3425 3427 3379>,
+ <3257 3306 3273 3283 3213>,
+ <3000 3000 3000 3000 3000>;
+ };
+
+ qcom,rbatt-sf-lut {
+ qcom,lut-col-legend = <(-20) 0 25 40 60>;
+ qcom,lut-row-legend = <100 95 90 85 80>,
+ <75 70 65 60 55>,
+ <50 45 40 35 30>,
+ <25 20 16 13 11>,
+ <10 9 8 7 6>,
+ <5 4 3 2 1>;
+ qcom,lut-data = <1025 208 100 85 80>,
+ <1025 208 100 85 80>,
+ <1032 225 103 87 81>,
+ <959 249 107 91 82>,
+ <954 249 109 92 84>,
+ <953 255 117 94 84>,
+ <957 230 123 98 87>,
+ <968 216 134 102 91>,
+ <983 212 138 112 95>,
+ <1002 213 103 89 82>,
+ <1030 215 100 86 81>,
+ <1066 219 101 89 83>,
+ <1115 224 104 92 85>,
+ <1182 234 106 94 86>,
+ <1263 246 108 92 84>,
+ <1357 257 107 87 81>,
+ <1464 261 102 85 80>,
+ <1564 256 101 84 80>,
+ <1637 268 100 84 80>,
+ <1580 276 102 87 81>,
+ <1617 285 104 87 82>,
+ <1670 298 107 91 82>,
+ <1725 315 108 92 83>,
+ <1785 338 112 92 83>,
+ <1850 361 111 91 82>,
+ <1921 378 108 89 84>,
+ <2000 394 112 92 87>,
+ <2119 430 121 99 94>,
+ <2795 497 144 114 104>,
+ <8769 1035 672 322 234>;
+ };
+};
diff --git a/arch/arm/boot/dts/batterydata-palladium.dtsi b/arch/arm/boot/dts/batterydata-palladium.dtsi
new file mode 100644
index 0000000..95c4ff1
--- /dev/null
+++ b/arch/arm/boot/dts/batterydata-palladium.dtsi
@@ -0,0 +1,111 @@
+/* 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,palladium-batterydata {
+ qcom,fcc-mah = <1500>;
+ qcom,default-rbatt-mohm = <210>;
+ 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 60>;
+ qcom,lut-data = <1467 1470 1473 1473 1470>;
+ };
+
+ qcom,pc-temp-ocv-lut {
+ qcom,lut-col-legend = <(-20) 0 25 40 60>;
+ qcom,lut-row-legend = <100 95 90 85 80>,
+ <75 70 65 60 55>,
+ <50 45 40 35 30>,
+ <25 20 16 13 11>,
+ <10 9 8 7 6>,
+ <5 4 3 2 1>,
+ <0>;
+ qcom,lut-data = <4175 4173 4167 4162 4157>,
+ <4097 4111 4112 4110 4107>,
+ <4039 4075 4072 4068 4064>,
+ <3963 4017 4025 4026 4025>,
+ <3920 3969 3984 3989 3988>,
+ <3887 3932 3957 3958 3955>,
+ <3856 3898 3929 3928 3925>,
+ <3830 3868 3900 3901 3898>,
+ <3808 3843 3858 3863 3862>,
+ <3793 3821 3827 3827 3827>,
+ <3779 3803 3807 3808 3807>,
+ <3768 3788 3792 3793 3792>,
+ <3757 3779 3780 3780 3779>,
+ <3746 3771 3772 3768 3768>,
+ <3734 3762 3765 3759 3749>,
+ <3722 3747 3753 3744 3730>,
+ <3707 3721 3731 3722 3709>,
+ <3693 3705 3704 3696 3683>,
+ <3678 3698 3687 3678 3667>,
+ <3664 3693 3683 3676 3665>,
+ <3656 3690 3682 3675 3664>,
+ <3646 3687 3681 3674 3662>,
+ <3634 3683 3680 3672 3661>,
+ <3618 3677 3676 3668 3656>,
+ <3599 3667 3667 3655 3639>,
+ <3573 3645 3638 3623 3603>,
+ <3541 3607 3591 3575 3554>,
+ <3496 3550 3528 3511 3490>,
+ <3428 3469 3445 3423 3400>,
+ <3312 3342 3308 3280 3250>,
+ <3000 3000 3000 3000 3000>;
+ };
+
+ qcom,rbatt-sf-lut {
+ qcom,lut-col-legend = <(-20) 0 25 40 60>;
+ qcom,lut-row-legend = <100 95 90 85 80>,
+ <75 70 65 60 55>,
+ <50 45 40 35 30>,
+ <25 20 16 13 11>,
+ <10 9 8 7 6>,
+ <5 4 3 2 1>,
+ <0>;
+ qcom,lut-data = <909 216 100 85 84>,
+ <859 238 106 88 86>,
+ <860 237 105 88 86>,
+ <808 239 107 90 88>,
+ <801 234 111 94 90>,
+ <801 230 118 97 92>,
+ <801 224 123 100 95>,
+ <807 221 128 106 99>,
+ <818 221 111 101 97>,
+ <841 225 101 88 87>,
+ <870 229 101 88 87>,
+ <906 235 103 91 90>,
+ <950 243 106 93 93>,
+ <998 253 110 93 96>,
+ <1051 263 113 94 90>,
+ <1116 272 113 91 88>,
+ <1200 275 111 91 88>,
+ <1312 298 108 90 87>,
+ <1430 329 104 88 87>,
+ <1484 351 107 91 89>,
+ <1446 345 110 93 90>,
+ <1398 344 112 94 90>,
+ <1466 358 115 96 91>,
+ <1490 357 117 96 90>,
+ <1589 365 117 94 89>,
+ <1828 379 111 91 88>,
+ <2151 399 111 93 91>,
+ <2621 436 117 98 95>,
+ <3404 496 130 106 100>,
+ <8212 616 150 1906 134>,
+ <135251 124940 59087 49820 29672>;
+ };
+};
diff --git a/arch/arm/boot/dts/dsi-panel-generic-720p-cmd.dtsi b/arch/arm/boot/dts/dsi-panel-generic-720p-cmd.dtsi
index 23091f0..2963d15 100644
--- a/arch/arm/boot/dts/dsi-panel-generic-720p-cmd.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-generic-720p-cmd.dtsi
@@ -76,5 +76,6 @@
qcom,mdss-dsi-dma-trigger = <4>;
qcom,mdss-dsi-mdp-trigger = <0>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 200>, <1 20>;
};
};
diff --git a/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi
index 4230018..23b65f3 100644
--- a/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-hx8379a-wvga-video.dtsi
@@ -118,6 +118,7 @@
qcom,mdss-dsi-dma-trigger = <4>;
qcom,mdss-dsi-mdp-trigger = <0>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
};
};
diff --git a/arch/arm/boot/dts/dsi-panel-hx8389b-qhd-video.dtsi b/arch/arm/boot/dts/dsi-panel-hx8389b-qhd-video.dtsi
new file mode 100755
index 0000000..7e63014
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-hx8389b-qhd-video.dtsi
@@ -0,0 +1,135 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
+&mdss_mdp {
+ dsi_hx8389b_qhd_vid: qcom,mdss_dsi_hx8389b_qhd_video {
+ qcom,mdss-dsi-panel-name = "HX8389b qhd 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 = <96>;
+ qcom,mdss-dsi-h-pulse-width = <96>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-front-porch = <9>;
+ qcom,mdss-dsi-v-pulse-width = <3>;
+ qcom,mdss-dsi-v-back-porch = <13>;
+ 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 89
+ 39 01 00 00 00 00 08
+ BA 41 93 00
+ 16 A4 10 18
+ 23 01 00 00 00 00 02
+ C6 08
+ 39 01 00 00 00 00 03
+ BC 02 00
+ 23 01 00 00 00 00 02
+ CC 02
+ 39 01 00 00 00 00 14
+ B1 00 00 07
+ E8 50 10 11
+ 98 f8 21 29
+ 27 27 43 01
+ 58 F0 00 E6
+ 39 01 00 00 00 00 08
+ B2 00 00 78
+ 0C 07 3F 80
+ 39 01 00 00 00 00 18
+ b4 82 08 00
+ 32 10 04 32
+ 10 00 32 10
+ 00 37 0a 40
+ 08 37 0a 40
+ 14 46 50 0a
+ 39 01 00 00 00 00 39
+ d5 00 00 00
+ 00 01 00 00
+ 00 60 00 99
+ 88 AA BB 88
+ 23 88 01 88
+ 67 88 45 01
+ 23 88 88 88
+ 88 88 88 99
+ BB AA 88 54
+ 88 76 88 10
+ 88 32 32 10
+ 88 88 88 88
+ 88 00 04 00
+ 00 00 00 00
+ 00
+ 39 01 00 00 00 00 03
+ CB 07 07
+ 39 01 00 00 00 00 05
+ BB 00 00 FF
+ 80
+ 39 01 00 00 00 00 04
+ DE 05 58 10
+ 39 01 00 00 00 00 05
+ B6 00 8A 00
+ 8A
+ 39 01 00 00 00 00 23
+ E0 01 08 0C
+ 1F 25 36 12
+ 35 05 09 0D
+ 10 11 0F 0F
+ 1C 1D 01 08
+ 0C 1F 25 36
+ 12 35 05 09
+ 0D 10 11 0F
+ 0F 1C 1D
+ 05 01 00 00 96 00 02
+ 11 00
+ 05 01 00 00 96 00 02
+ 29 00
+ ];
+ qcom,mdss-dsi-off-command = [05 01 00 00 32 00 02 28 00
+ 05 01 00 00 78 00 02 10 00];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-h-sync-pulse = <1>;
+ qcom,mdss-dsi-traffic-mode = <2>;
+ qcom,mdss-dsi-lane-map = <1>;
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-panel-timings = [97 23 17 00 4B 53 1C 27 27 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x04>;
+ qcom,mdss-dsi-t-clk-pre = <0x1b>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <255>;
+ qcom,mdss-dsi-dma-trigger = <4>;
+ qcom,mdss-dsi-mdp-trigger = <0>;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
+
+ };
+};
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 c9d887b..83351ca 100644
--- a/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-hx8394a-720p-video.dtsi
@@ -78,6 +78,7 @@
qcom,mdss-dsi-dma-trigger = <4>;
qcom,mdss-dsi-mdp-trigger = <0>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 1>, <1 20>;
};
};
diff --git a/arch/arm/boot/dts/dsi-panel-jdi-1080p-video.dtsi b/arch/arm/boot/dts/dsi-panel-jdi-1080p-video.dtsi
new file mode 100644
index 0000000..1b64cf7
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-jdi-1080p-video.dtsi
@@ -0,0 +1,72 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*---------------------------------------------------------------------------
+ * This file is autogenerated file using gcdb parser. Please do not edit it.
+ * Update input XML file to add a new entry or update variable in this file
+ * VERSION = "1.0"
+ *---------------------------------------------------------------------------*/
+&mdss_mdp {
+ dsi_jdi_1080_vid: qcom,mdss_dsi_jdi_1080p_video {
+ qcom,mdss-dsi-panel-name = "jdi 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 = <96>;
+ qcom,mdss-dsi-h-back-porch = <64>;
+ qcom,mdss-dsi-h-pulse-width = <16>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <4>;
+ qcom,mdss-dsi-v-front-porch = <3>;
+ 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 = [15 01 00 00 00 00 02 55 00
+ 15 01 00 00 00 00 02 53 2C
+ 15 01 00 00 00 00 02 35 00
+ 05 01 00 00 78 00 02 29 00
+ 05 01 00 00 78 00 02 11 00];
+ qcom,mdss-dsi-off-command = [05 01 00 00 02 00 02 28 00
+ 05 01 00 00 79 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 = <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 = [e1 37 25 00 67 6b 2a 3a 59 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,mdss-dsi-reset-sequence = <1 20>, <0 200>, <1 20>;
+ };
+};
diff --git a/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
index 829197a..9bb11da 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35521-720p-video.dtsi
@@ -268,6 +268,7 @@
qcom,mdss-dsi-dma-trigger = <4>;
qcom,mdss-dsi-mdp-trigger = <0>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 1>, <1 20>;
};
};
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 0918cf4..a24cb58 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-cmd.dtsi
@@ -531,6 +531,9 @@
qcom,mdss-dsi-dma-trigger = <4>;
qcom,mdss-dsi-mdp-trigger = <0>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 1>, <1 20>;
+ qcom,mdss-pan-physical-width-dimension = <59>;
+ qcom,mdss-pan-physical-height-dimension = <104>;
};
};
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 6d68a3e..79618b9 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
@@ -527,6 +527,9 @@
qcom,mdss-dsi-dma-trigger = <4>;
qcom,mdss-dsi-mdp-trigger = <0>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 1>, <1 20>;
+ qcom,mdss-pan-physical-width-dimension = <59>;
+ qcom,mdss-pan-physical-height-dimension = <104>;
};
};
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 49aef24..2312b37 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35596-1080p-video.dtsi
@@ -582,6 +582,7 @@
qcom,mdss-dsi-dma-trigger = <4>;
qcom,mdss-dsi-mdp-trigger = <0>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 1>, <1 20>;
};
};
diff --git a/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi
index 89a5063..9477c56 100644
--- a/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-otm8018b-fwvga-video.dtsi
@@ -261,6 +261,7 @@
qcom,mdss-dsi-dma-trigger = <4>;
qcom,mdss-dsi-mdp-trigger = <0>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
};
};
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 c627e7a..285d8fc 100644
--- a/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-sharp-qhd-video.dtsi
@@ -67,6 +67,7 @@
qcom,mdss-dsi-dma-trigger = <4>;
qcom,mdss-dsi-mdp-trigger = <4>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 200>, <1 20>;
};
};
diff --git a/arch/arm/boot/dts/dsi-panel-sim-video.dtsi b/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
index ccbb659..501fdde 100644
--- a/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-sim-video.dtsi
@@ -39,5 +39,6 @@
qcom,on-cmds-dsi-state = "DSI_LP_MODE";
qcom,panel-off-cmds = [22 01 00 00 00 00 02 00 00];
qcom,off-cmds-dsi-state = "DSI_LP_MODE";
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 200>, <1 20>;
};
};
diff --git a/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
index 7bb414a..bb8389f 100644
--- a/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-ssd2080m-720p-video.dtsi
@@ -115,5 +115,6 @@
qcom,mdss-dsi-dma-trigger = <4>;
qcom,mdss-dsi-mdp-trigger = <0>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 1>, <1 20>;
};
};
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 021ddef..f7de416 100644
--- a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
@@ -92,5 +92,6 @@
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
qcom,mdss-dsi-pan-enable-dynamic-fps;
qcom,mdss-dsi-pan-fps-update = "dfps_suspend_resume_mode";
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 200>, <1 20>;
};
};
diff --git a/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi b/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi
index f6e6df8..d170833 100644
--- a/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-truly-wvga-cmd.dtsi
@@ -166,5 +166,6 @@
qcom,mdss-dsi-dma-trigger = <4>;
qcom,mdss-dsi-mdp-trigger = <2>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
};
};
diff --git a/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi b/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi
index fae4834..546a90f 100644
--- a/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-truly-wvga-video.dtsi
@@ -164,5 +164,6 @@
qcom,mdss-dsi-dma-trigger = <4>;
qcom,mdss-dsi-mdp-trigger = <0>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-reset-sequence = <1 20>, <0 2>, <1 20>;
};
};
diff --git a/arch/arm/boot/dts/msm-iommu-v0.dtsi b/arch/arm/boot/dts/msm-iommu-v0.dtsi
index 8ab9985..8891935 100644
--- a/arch/arm/boot/dts/msm-iommu-v0.dtsi
+++ b/arch/arm/boot/dts/msm-iommu-v0.dtsi
@@ -33,6 +33,7 @@
qcom,msm-bus,vectors-KBps =
<11 512 0 0>,
<11 512 0 1000>;
+ qcom,msm-enable-remote-spinlock;
status = "disabled";
lpass_q6_fw: qcom,iommu-ctx@fd000000 {
diff --git a/arch/arm/boot/dts/msm-pm8110.dtsi b/arch/arm/boot/dts/msm-pm8110.dtsi
index 6969940..8523524 100644
--- a/arch/arm/boot/dts/msm-pm8110.dtsi
+++ b/arch/arm/boot/dts/msm-pm8110.dtsi
@@ -113,7 +113,7 @@
"vdd-loop";
};
- qcom,bat-if@1200 {
+ pm8110_chg_batif: qcom,bat-if@1200 {
status = "disabled";
reg = <0x1200 0x100>;
interrupts = <0x0 0x12 0x0>,
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index ba1bf08..f2ed8b5 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -50,6 +50,10 @@
qcom,pon-type = <1>;
qcom,pull-up = <1>;
linux,code = <114>;
+ qcom,s1-timer = <6720>;
+ qcom,s2-timer = <2000>;
+ qcom,s2-type = <7>;
+ qcom,support-reset = <1>;
};
qcom,pon_3 {
@@ -59,6 +63,7 @@
qcom,s1-timer = <6720>;
qcom,s2-timer = <2000>;
qcom,s2-type = <7>;
+ qcom,use-bark;
};
};
@@ -131,7 +136,7 @@
"vdd-loop";
};
- qcom,bat-if@1200 {
+ pm8226_chg_batif: qcom,bat-if@1200 {
status = "disabled";
reg = <0x1200 0x100>;
interrupts = <0x0 0x12 0x0>,
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 98d2f5e..c4de04c 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -69,6 +69,7 @@
qcom,s2-timer = <2000>;
qcom,s2-type = <1>;
linux,code = <114>;
+ qcom,use-bark;
};
qcom,pon_3 {
@@ -78,6 +79,7 @@
qcom,s2-timer = <2000>;
qcom,s2-type = <7>;
qcom,pull-up = <1>;
+ qcom,use-bark;
};
};
@@ -250,7 +252,7 @@
"vdd-loop";
};
- qcom,bat-if@1200 {
+ pm8941_chg_batif: qcom,bat-if@1200 {
status = "disabled";
reg = <0x1200 0x100>;
interrupts = <0x0 0x12 0x0>,
diff --git a/arch/arm/boot/dts/msm8226-coresight.dtsi b/arch/arm/boot/dts/msm8226-coresight.dtsi
index ec3f248..feef9d5 100644
--- a/arch/arm/boot/dts/msm8226-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8226-coresight.dtsi
@@ -215,12 +215,56 @@
qcom,round-robin;
};
+ audio_etm0 {
+ compatible = "qcom,coresight-audio-etm";
+
+ coresight-id = <14>;
+ coresight-name = "coresight-audio-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <2>;
+ };
+
+ modem_etm0 {
+ compatible = "qcom,coresight-modem-etm";
+
+ coresight-id = <15>;
+ coresight-name = "coresight-modem-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <1>;
+ };
+
+ wcn_etm0 {
+ compatible = "qcom,coresight-wcn-etm";
+
+ coresight-id = <16>;
+ coresight-name = "coresight-wcn-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in1>;
+ coresight-child-ports = <2>;
+ };
+
+ rpm_etm0 {
+ compatible = "qcom,coresight-rpm-etm";
+
+ coresight-id = <17>;
+ coresight-name = "coresight-rpm-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <0>;
+ };
+
csr: csr@fc302000 {
compatible = "qcom,coresight-csr";
reg = <0xfc302000 0x1000>;
reg-names = "csr-base";
- coresight-id = <14>;
+ coresight-id = <18>;
coresight-name = "coresight-csr";
coresight-nr-inports = <0>;
@@ -232,7 +276,7 @@
reg = <0xfc308000 0x1000>;
reg-names = "cti-base";
- coresight-id = <15>;
+ coresight-id = <19>;
coresight-name = "coresight-cti0";
coresight-nr-inports = <0>;
};
@@ -242,7 +286,7 @@
reg = <0xfc309000 0x1000>;
reg-names = "cti-base";
- coresight-id = <16>;
+ coresight-id = <20>;
coresight-name = "coresight-cti1";
coresight-nr-inports = <0>;
};
@@ -252,7 +296,7 @@
reg = <0xfc30a000 0x1000>;
reg-names = "cti-base";
- coresight-id = <17>;
+ coresight-id = <21>;
coresight-name = "coresight-cti2";
coresight-nr-inports = <0>;
};
@@ -262,7 +306,7 @@
reg = <0xfc30b000 0x1000>;
reg-names = "cti-base";
- coresight-id = <18>;
+ coresight-id = <22>;
coresight-name = "coresight-cti3";
coresight-nr-inports = <0>;
};
@@ -272,7 +316,7 @@
reg = <0xfc30c000 0x1000>;
reg-names = "cti-base";
- coresight-id = <19>;
+ coresight-id = <23>;
coresight-name = "coresight-cti4";
coresight-nr-inports = <0>;
};
@@ -282,7 +326,7 @@
reg = <0xfc30d000 0x1000>;
reg-names = "cti-base";
- coresight-id = <20>;
+ coresight-id = <24>;
coresight-name = "coresight-cti5";
coresight-nr-inports = <0>;
};
@@ -292,7 +336,7 @@
reg = <0xfc30e000 0x1000>;
reg-names = "cti-base";
- coresight-id = <21>;
+ coresight-id = <25>;
coresight-name = "coresight-cti6";
coresight-nr-inports = <0>;
};
@@ -302,7 +346,7 @@
reg = <0xfc30f000 0x1000>;
reg-names = "cti-base";
- coresight-id = <22>;
+ coresight-id = <26>;
coresight-name = "coresight-cti7";
coresight-nr-inports = <0>;
};
@@ -312,7 +356,7 @@
reg = <0xfc310000 0x1000>;
reg-names = "cti-base";
- coresight-id = <23>;
+ coresight-id = <27>;
coresight-name = "coresight-cti8";
coresight-nr-inports = <0>;
};
@@ -322,7 +366,7 @@
reg = <0xfc340000 0x1000>;
reg-names = "cti-base";
- coresight-id = <24>;
+ coresight-id = <28>;
coresight-name = "coresight-cti-l2";
coresight-nr-inports = <0>;
};
@@ -332,7 +376,7 @@
reg = <0xfc341000 0x1000>;
reg-names = "cti-base";
- coresight-id = <25>;
+ coresight-id = <29>;
coresight-name = "coresight-cti-cpu0";
coresight-nr-inports = <0>;
};
@@ -342,7 +386,7 @@
reg = <0xfc342000 0x1000>;
reg-names = "cti-base";
- coresight-id = <26>;
+ coresight-id = <30>;
coresight-name = "coresight-cti-cpu1";
coresight-nr-inports = <0>;
};
@@ -352,7 +396,7 @@
reg = <0xfc343000 0x1000>;
reg-names = "cti-base";
- coresight-id = <27>;
+ coresight-id = <31>;
coresight-name = "coresight-cti-cpu2";
coresight-nr-inports = <0>;
};
@@ -362,11 +406,61 @@
reg = <0xfc344000 0x1000>;
reg-names = "cti-base";
- coresight-id = <28>;
+ coresight-id = <32>;
coresight-name = "coresight-cti-cpu3";
coresight-nr-inports = <0>;
};
+ cti_video_cpu0: cti@fc348000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc348000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <33>;
+ coresight-name = "coresight-cti-video-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_wcn_cpu0: cti@fc34d000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc34d000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <34>;
+ coresight-name = "coresight-cti-wcn-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_modem_cpu0: cti@fc350000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc350000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <35>;
+ coresight-name = "coresight-cti-modem-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_audio_cpu0: cti@fc354000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc354000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <36>;
+ coresight-name = "coresight-cti-audio-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_rpm_cpu0: cti@fc358000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc358000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <37>;
+ coresight-name = "coresight-cti-rpm-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
hwevent: hwevent@fd828018 {
compatible = "qcom,coresight-hwevent";
reg = <0xfd828018 0x80>,
@@ -375,7 +469,7 @@
<0xfc401600 0x80>;
reg-names = "mmss-mux", "apcs-mux", "ppss-mux", "gcc-mux";
- coresight-id = <29>;
+ coresight-id = <38>;
coresight-name = "coresight-hwevent";
coresight-nr-inports = <0>;
@@ -387,7 +481,7 @@
reg = <0xfc4be024 0x8>;
reg-names = "fuse-base";
- coresight-id = <30>;
+ coresight-id = <39>;
coresight-name = "coresight-fuse";
coresight-nr-inports = <0>;
};
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index c7a4eee..3e2507ff 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -37,6 +37,7 @@
qcom,mdss-intf-off = <0x00000000 0x00021300>;
qcom,mdss-rot-block-size = <64>;
qcom,mdss-smp-mb-per-pipe = <2>;
+ vdd-cx-supply = <&pm8226_s1_corner>;
qcom,vbif-settings = <0x004 0x00000001>,
<0x0D8 0x00000707>,
@@ -78,7 +79,6 @@
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>;
diff --git a/arch/arm/boot/dts/msm8226-mtp.dtsi b/arch/arm/boot/dts/msm8226-mtp.dtsi
index 318d4fc..a4bd8fd 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8226-mtp.dtsi
@@ -40,6 +40,8 @@
reg = <0x0e>;
qcom,irq-gpio = <&msmgpio 21 0x00>;
qcom,dis-gpio = <&msmgpio 20 0x00>;
+ qcom,clk-src = "BBCLK2";
+ qcom,clk-en-gpio = <&msmgpio 0 0x00>;
interrupt-parent = <&msmgpio>;
interrupts = <21 0>;
qcom,clk-gpio = <&pm8226_gpios 3 0>;
@@ -462,6 +464,16 @@
};
};
+/ {
+ mtp_batterydata: qcom,battery-data {
+ qcom,rpull-up-kohm = <100>;
+ qcom,vref-batt-therm = <1800000>;
+
+ /include/ "batterydata-palladium.dtsi"
+ /include/ "batterydata-mtp-3000mah.dtsi"
+ };
+};
+
&pm8226_bms {
status = "ok";
qcom,enable-fcc-learning;
@@ -469,10 +481,12 @@
qcom,min-fcc-ocv-pc = <30>;
qcom,min-fcc-learning-samples = <5>;
qcom,fcc-resolution = <10>;
+ qcom,battery-data = <&mtp_batterydata>;
};
&pm8226_chg {
qcom,charging-disabled;
+ qcom,battery-data = <&mtp_batterydata>;
};
&slim_msm {
@@ -483,6 +497,7 @@
&mdss_mdp {
qcom,mdss-pref-prim-intf = "dsi";
+ batfet-supply = <&pm8226_chg_batif>;
};
&mdss_dsi0 {
diff --git a/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi b/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi
new file mode 100755
index 0000000..66f5095
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226-qrd-skuf.dtsi
@@ -0,0 +1,215 @@
+/* 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/ "msm8226-qrd.dtsi"
+
+&soc {
+ sound {
+ qcom,model = "msm8226-tapan-skuf-snd-card";
+
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "LDO_H", "MCLK",
+ "SPK_OUT", "MCLK",
+ "SPK_OUT", "EXT_VDD_SPKR",
+ "Lineout_1 amp", "LINEOUT1",
+ "Lineout_2 amp", "LINEOUT2",
+ "AMIC1", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Handset Mic",
+ "AMIC2", "MIC BIAS2 External",
+ "MIC BIAS2 External", "Headset Mic",
+ "AMIC3", "MIC BIAS1 External",
+ "MIC BIAS1 External", "ANCRight Headset Mic",
+ "AMIC4", "MIC BIAS2 External",
+ "MIC BIAS2 External", "ANCLeft Headset Mic";
+
+ qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+ qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
+ qcom,cdc-vdd-spkr-gpios;
+ qcom,cdc-us-euro-gpios;
+ };
+
+ sound-9302 {
+ qcom,model = "msm8226-tapan9302-skuf-snd-card";
+
+ qcom,audio-routing =
+ "RX_BIAS", "MCLK",
+ "LDO_H", "MCLK",
+ "SPK_OUT", "MCLK",
+ "SPK_OUT", "EXT_VDD_SPKR",
+ "Lineout_1 amp", "LINEOUT1",
+ "Lineout_2 amp", "LINEOUT2",
+ "AMIC1", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Handset Mic",
+ "AMIC2", "MIC BIAS2 External",
+ "MIC BIAS2 External", "Headset Mic",
+ "AMIC3", "MIC BIAS1 External",
+ "MIC BIAS1 External", "Handset Mic";
+
+ qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
+ qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
+ qcom,cdc-vdd-spkr-gpios;
+ qcom,cdc-us-euro-gpios;
+ };
+
+ tp_power: regulator-tp {
+ compatible = "regulator-fixed";
+ regulator-name = "tp_power";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ gpio = <&msmgpio 15 0>;
+ startup-delay-us = <20000>;
+ enable-active-high;
+ };
+
+ i2c@f9927000 {
+ goodix@5d {
+ compatible = "goodix,gt9xx";
+ reg = <0x5d>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <17 0x2008>;
+ reset-gpios = <&msmgpio 16 0x00>;
+ interrupt-gpios = <&msmgpio 17 0x00>;
+ avdd-supply = <&tp_power>;
+ goodix,panel-coords = <0 0 720 1200>;
+ goodix,display-coords = <0 0 720 1080>;
+ goodix,button-map= <158 102 139>;
+ goodix,product-id = "915";
+ goodix,cfg-data0 = [
+ 41 D0 02 00 05 05 35 01 01 0F
+ 2D 06 50 32 03 05 00 00 00 00
+ 00 00 05 18 1A 1E 14 8C 0E 0E
+ 3F 3D 2A 09 00 00 00 99 04 1D
+ 00 00 00 00 00 00 00 00 00 00
+ 00 32 6E 94 D5 01 05 00 00 04
+ CE 36 00 B5 3F 00 9E 4A 00 8B
+ 57 00 7C 65 00 7C 10 38 68 00
+ 56 50 35 66 66 27 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00 02 04 06 08 0A 0C 0E 10
+ 12 14 16 18 1A 1C 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 02 04 06 08 0A 0C 0F
+ 10 12 13 14 16 18 1C 1D 1E 1F
+ 20 21 22 24 26 28 29 2A 00 00
+ 00 FF FF FF FF FF FF FF FF FF
+ FF FF FF FF A3 01];
+ goodix,cfg-data1 = [
+ 41 D0 02 00 05 05 35 01 01 C3
+ 2D 06 55 32 03 03 00 00 00 00
+ 00 00 05 0A 0C 0F 0A 8C 0E 0E
+ 30 2E B8 08 00 00 00 8F 03 1D
+ 00 00 00 00 00 00 00 00 00 00
+ 00 2D 62 94 D5 02 05 00 00 04
+ 96 30 00 80 39 00 71 42 00 63
+ 4D 00 56 5A 00 56 10 38 68 00
+ 56 50 35 AA AA 27 00 00 00 00
+ 00 01 1B 14 0C 14 00 00 01 00
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00 02 04 06 08 0A 0C 0E 10
+ 12 14 16 18 1A 1C FF FF FF FF
+ FF FF FF FF FF FF FF FF FF FF
+ FF FF 00 02 04 06 08 0A 0C 0F
+ 10 12 13 14 16 18 1C 1D 1E 1F
+ 20 21 22 24 26 28 29 2A FF FF
+ FF FF FF FF FF FF FF FF FF FF
+ FF FF FF FF 3E 01];
+ };
+ };
+};
+
+&spmi_bus {
+ qcom,pm8226@0 {
+ qcom,leds@a300 {
+ status = "disabled";
+ };
+
+ qcom,leds@a500 {
+ status = "disabled";
+ };
+ };
+
+ qcom,pm8226@1 {
+ qcom,leds@d800 {
+ 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>;
+ };
+};
+
+&qrd_batterydata {
+ qcom,rpull-up-kohm = <100>;
+ qcom,vref-batt-therm = <1800000>;
+
+ /include/ "batterydata-qrd-4v35-2500mah.dtsi"
+};
+
+&pm8226_bms {
+ qcom,battery-data = <&qrd_batterydata>;
+};
+
+&pm8226_chg {
+ qcom,battery-data = <&qrd_batterydata>;
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_nt35521_720_vid>;
+};
+
+&dsi_nt35521_720_vid {
+ qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8226-qrd.dtsi b/arch/arm/boot/dts/msm8226-qrd.dtsi
index 18a1aea..eac0bb6 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8226-qrd.dtsi
@@ -40,6 +40,7 @@
interrupts = <17 0x2>;
vdd-supply = <&pm8226_l19>;
vcc_i2c-supply = <&pm8226_lvs1>;
+ focaltech,name = "ft5x06";
focaltech,family-id = <0x55>;
focaltech,reset-gpio = <&msmgpio 16 0x00>;
focaltech,irq-gpio = <&msmgpio 17 0x00>;
@@ -48,6 +49,17 @@
focaltech,button-map= <139 102 158>;
focaltech,no-force-update;
focaltech,i2c-pull-up;
+ focaltech,group-id = <1>;
+ focaltech,hard-reset-delay-ms = <20>;
+ focaltech,soft-reset-delay-ms = <150>;
+ focaltech,num-max-touches = <5>;
+ focaltech,fw-name = "ft_8226_qrd_1080p_fw.bin";
+ focaltech,fw-delay-aa-ms = <50>;
+ focaltech,fw-delay-55-ms = <30>;
+ focaltech,fw-upgrade-id1 = <0x79>;
+ focaltech,fw-upgrade-id2 = <0x03>;
+ focaltech,fw-delay-readid-ms = <10>;
+ focaltech,fw-delay-era-flsh-ms = <2000>;
};
};
@@ -385,6 +397,7 @@
status = "okay";
qcom,battery-data = <&qrd_batterydata>;
qcom,tchg-mins = <240>;
+ qcom,ovp-monitor-en;
};
&pm8226_gpios {
@@ -481,6 +494,7 @@
&mdss_mdp {
qcom,mdss-pref-prim-intf = "dsi";
+ batfet-supply = <&pm8226_chg_batif>;
};
&mdss_dsi0 {
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 838592c..23a2158 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -491,6 +491,10 @@
otg-parent-supply = <&pm8226_chg_boost>;
};
+&pm8226_chg_batif {
+ regulator-name = "batfet";
+};
+
&pm8226_chg_otg {
regulator-name = "8226_smbbp_otg";
};
diff --git a/arch/arm/boot/dts/msm8226-v1-pm.dtsi b/arch/arm/boot/dts/msm8226-v1-pm.dtsi
index dcf46e6..02feec8 100644
--- a/arch/arm/boot/dts/msm8226-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-v1-pm.dtsi
@@ -99,6 +99,9 @@
qcom,saw2-spm-cmd-pc = [00 32 b0 10 e0 d0 6b c0 42 f0
11 07 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
+ qcom,saw2-spm-cmd-pc-no-rpm = [00 32 b0 10 e0 d0 6b c0 42 f0
+ 11 03 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
+ 50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
qcom,L2-spm-is-apcs-master;
};
@@ -113,8 +116,8 @@
qcom,mode = "wfi";
qcom,l2 = "l2_cache_active";
qcom,latency-us = <1>;
- qcom,ss-power = <784>;
- qcom,energy-overhead = <190000>;
+ qcom,ss-power = <530>;
+ qcom,energy-overhead = <52800>;
qcom,time-overhead = <100>;
};
@@ -122,30 +125,30 @@
reg = <0x1>;
qcom,mode = "standalone_pc";
qcom,l2 = "l2_cache_active";
- qcom,latency-us = <3000>;
- qcom,ss-power = <725>;
- qcom,energy-overhead = <99500>;
- qcom,time-overhead = <3130>;
+ qcom,latency-us = <500>;
+ qcom,ss-power = <410>;
+ qcom,energy-overhead = <603400>;
+ qcom,time-overhead = <1200>;
};
qcom,lpm-level@2 {
reg = <0x2>;
qcom,mode = "pc";
- qcom,l2 = "l2_cache_retention";
- qcom,latency-us = <20000>;
- qcom,ss-power = <138>;
- qcom,energy-overhead = <1208400>;
- qcom,time-overhead = <9200>;
+ qcom,l2 = "l2_cache_pc_no_rpm";
+ qcom,latency-us = <1000>;
+ qcom,ss-power = <315>;
+ qcom,energy-overhead = <1027150>;
+ qcom,time-overhead = <2400>;
};
qcom,lpm-level@3 {
reg = <0x3>;
qcom,mode = "pc";
qcom,l2 = "l2_cache_pc";
- qcom,latency-us = <30000>;
- qcom,ss-power = <110>;
- qcom,energy-overhead = <1250300>;
- qcom,time-overhead = <9500>;
+ qcom,latency-us = <11000>;
+ qcom,ss-power = <315>;
+ qcom,energy-overhead = <1027150>;
+ qcom,time-overhead = <2400>;
};
};
@@ -266,6 +269,7 @@
<38 108>,
<39 109>,
<40 110>,
+ <41 115>,
<54 111>,
<55 113>;
};
diff --git a/arch/arm/boot/dts/msm8974pro-ab-fluid.dts b/arch/arm/boot/dts/msm8226-v1-qrd-skuf-pvt.dts
similarity index 61%
copy from arch/arm/boot/dts/msm8974pro-ab-fluid.dts
copy to arch/arm/boot/dts/msm8226-v1-qrd-skuf-pvt.dts
index 9a31834..43e1e21 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-fluid.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-skuf-pvt.dts
@@ -11,18 +11,12 @@
*/
/dts-v1/;
-
-/include/ "msm8974pro-ab.dtsi"
-/include/ "msm8974-fluid.dtsi"
+/include/ "msm8226-v1.dtsi"
+/include/ "msm8226-qrd-skuf.dtsi"
/ {
- model = "Qualcomm MSM 8974Pro FLUID";
- compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
- qcom,msm-id = <209 3 0x10000>,
- <211 3 0x10000>,
- <212 3 0x10000>,
- <214 3 0x10000>,
- <215 3 0x10000>,
- <217 3 0x10000>,
- <218 3 0x10000>;
+ model = "Qualcomm MSM 8226v1 QRD PVT";
+ compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,skuf", "qcom,qrd";
+ qcom,board-id = <0x2000b 2>;
};
+
diff --git a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
index d12f8c9..b836928 100644
--- a/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v1-qrd-skuf.dts
@@ -12,7 +12,7 @@
/dts-v1/;
/include/ "msm8226-v1.dtsi"
-/include/ "msm8226-qrd.dtsi"
+/include/ "msm8226-qrd-skuf.dtsi"
/ {
model = "Qualcomm MSM 8226v1 QRD";
@@ -20,184 +20,10 @@
qcom,board-id = <11 2>;
};
-&soc {
- sound {
- qcom,model = "msm8226-tapan-skuf-snd-card";
-
- qcom,audio-routing =
- "RX_BIAS", "MCLK",
- "LDO_H", "MCLK",
- "SPK_OUT", "MCLK",
- "SPK_OUT", "EXT_VDD_SPKR",
- "Lineout_1 amp", "LINEOUT1",
- "Lineout_2 amp", "LINEOUT2",
- "AMIC1", "MIC BIAS1 External",
- "MIC BIAS1 External", "Handset Mic",
- "AMIC2", "MIC BIAS2 External",
- "MIC BIAS2 External", "Headset Mic",
- "AMIC3", "MIC BIAS1 External",
- "MIC BIAS1 External", "ANCRight Headset Mic",
- "AMIC4", "MIC BIAS2 External",
- "MIC BIAS2 External", "ANCLeft Headset Mic";
-
- qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
- qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
- qcom,cdc-vdd-spkr-gpios;
- qcom,cdc-us-euro-gpios;
- };
-
- sound-9302 {
- qcom,model = "msm8226-tapan9302-skuf-snd-card";
-
- qcom,audio-routing =
- "RX_BIAS", "MCLK",
- "LDO_H", "MCLK",
- "SPK_OUT", "MCLK",
- "SPK_OUT", "EXT_VDD_SPKR",
- "Lineout_1 amp", "LINEOUT1",
- "Lineout_2 amp", "LINEOUT2",
- "AMIC1", "MIC BIAS1 External",
- "MIC BIAS1 External", "Handset Mic",
- "AMIC2", "MIC BIAS2 External",
- "MIC BIAS2 External", "Headset Mic",
- "AMIC3", "MIC BIAS1 External",
- "MIC BIAS1 External", "Handset Mic";
-
- qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
- qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
- qcom,cdc-vdd-spkr-gpios;
- qcom,cdc-us-euro-gpios;
- };
-
- tp_power: regulator-tp {
- compatible = "regulator-fixed";
- regulator-name = "tp_power";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- gpio = <&msmgpio 15 0>;
- startup-delay-us = <20000>;
- enable-active-high;
- };
-
- i2c@f9927000 {
- goodix@5d {
- compatible = "goodix,gt9xx";
- reg = <0x5d>;
- interrupt-parent = <&msmgpio>;
- interrupts = <17 0x2008>;
- reset-gpios = <&msmgpio 16 0x00>;
- interrupt-gpios = <&msmgpio 17 0x00>;
- avdd-supply = <&tp_power>;
- goodix,panel-coords = <0 0 720 1200>;
- goodix,display-coords = <0 0 720 1080>;
- goodix,button-map= <158 102 139>;
- goodix,family-id = <0x0>;
- goodix,cfg-data = [
- 41 D0 02 00 05 0A 35 01 01 0F
- 2D 08 55 32 03 04 00 00 00 00
- 00 00 05 0A 0C 0F 0A 8C 0E 0E
- 30 2E B8 08 00 00 00 83 03 1D
- 00 00 00 00 00 00 00 00 00 00
- 00 2D 62 94 C5 02 05 00 00 04
- 96 30 00 80 39 00 71 42 00 63
- 4D 00 56 5A 00 56 10 38 68 00
- 56 50 35 AA AA 27 00 00 00 00
- 00 01 1B 14 0C 14 00 00 01 00
- 00 00 00 00 00 00 00 00 00 00
- 00 00 02 04 06 08 0A 0C 0E 10
- 12 14 16 18 1A 1C FF FF FF FF
- FF FF FF FF FF FF FF FF FF FF
- FF FF 00 02 04 06 08 0A 0C 0F
- 10 12 13 14 16 18 1C 1D 1E 1F
- 20 21 22 24 26 28 29 2A FF FF
- FF FF FF FF FF FF FF FF FF FF
- FF FF FF FF 06 01];
- };
- };
-};
-
-&spmi_bus {
- qcom,pm8226@0 {
- qcom,leds@a300 {
- status = "disabled";
- };
-
- qcom,leds@a500 {
- status = "disabled";
- };
- };
-
- qcom,pm8226@1 {
- qcom,leds@d800 {
- 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>;
- };
-};
-
-&qrd_batterydata {
- qcom,rpull-up-kohm = <100>;
- qcom,vref-batt-therm = <1800000>;
-
- /include/ "batterydata-qrd-4v35-2500mah.dtsi"
-};
-
&pm8226_bms {
- qcom,battery-data = <&qrd_batterydata>;
+ qcom,use-external-rsense;
};
-&pm8226_chg {
- qcom,battery-data = <&qrd_batterydata>;
-};
-
-&mdss_dsi0 {
- qcom,dsi-pref-prim-pan = <&dsi_nt35521_720_vid>;
-};
-
-&dsi_nt35521_720_vid {
- qcom,cont-splash-enabled;
+&pm8226_iadc {
+ qcom,rsense = <10000000>;
};
diff --git a/arch/arm/boot/dts/msm8226-v2-cdp.dts b/arch/arm/boot/dts/msm8226-v2-cdp.dts
index 3d40180..3302d26 100644
--- a/arch/arm/boot/dts/msm8226-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-v2-cdp.dts
@@ -20,3 +20,7 @@
compatible = "qcom,msm8226-cdp", "qcom,msm8226", "qcom,cdp";
qcom,board-id = <1 0>;
};
+
+&hsic_host {
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/msm8226-v2-pm.dtsi b/arch/arm/boot/dts/msm8226-v2-pm.dtsi
index 9ee47e2..31d5a8f 100644
--- a/arch/arm/boot/dts/msm8226-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-v2-pm.dtsi
@@ -98,6 +98,9 @@
qcom,saw2-spm-cmd-ret = [00 03 00 0f];
qcom,saw2-spm-cmd-gdhs = [00 20 32 6b c0 e0 d0 42 07 50
4e 02 02 d0 e0 c0 22 6b 02 32 50 0f];
+ qcom,saw2-spm-cmd-pc-no-rpm = [00 32 b0 10 e0 d0 6b c0 42 f0
+ 11 03 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
+ 50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
qcom,saw2-spm-cmd-pc = [00 32 b0 10 e0 d0 6b c0 42 f0
11 07 01 b0 50 4e 02 02 c0 d0 12 e0 6b 02 32
50 f0 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
@@ -115,8 +118,8 @@
qcom,mode = "wfi";
qcom,l2 = "l2_cache_active";
qcom,latency-us = <1>;
- qcom,ss-power = <784>;
- qcom,energy-overhead = <190000>;
+ qcom,ss-power = <530>;
+ qcom,energy-overhead = <52800>;
qcom,time-overhead = <100>;
};
@@ -124,30 +127,40 @@
reg = <0x1>;
qcom,mode = "standalone_pc";
qcom,l2 = "l2_cache_active";
- qcom,latency-us = <3000>;
- qcom,ss-power = <725>;
- qcom,energy-overhead = <99500>;
- qcom,time-overhead = <3130>;
+ qcom,latency-us = <500>;
+ qcom,ss-power = <410>;
+ qcom,energy-overhead = <603400>;
+ qcom,time-overhead = <1200>;
};
qcom,lpm-level@2 {
reg = <0x2>;
qcom,mode = "pc";
qcom,l2 = "l2_cache_gdhs";
- qcom,latency-us = <20000>;
- qcom,ss-power = <138>;
- qcom,energy-overhead = <1208400>;
- qcom,time-overhead = <9200>;
+ qcom,latency-us = <10700>;
+ qcom,ss-power = <372>;
+ qcom,energy-overhead = <738750>;
+ qcom,time-overhead = <1410>;
};
qcom,lpm-level@3 {
reg = <0x3>;
qcom,mode = "pc";
+ qcom,l2 = "l2_cache_pc_no_rpm";
+ qcom,latency-us = <1000>;
+ qcom,ss-power = <315>;
+ qcom,energy-overhead = <1027150>;
+ qcom,time-overhead = <2400>;
+ };
+
+ qcom,lpm-level@4 {
+ reg = <0x4>;
+ qcom,mode = "pc";
qcom,l2 = "l2_cache_pc";
- qcom,latency-us = <30000>;
- qcom,ss-power = <110>;
- qcom,energy-overhead = <1250300>;
- qcom,time-overhead = <9500>;
+ qcom,latency-us = <11000>;
+ qcom,ss-power = <315>;
+ qcom,energy-overhead = <1027150>;
+ qcom,time-overhead = <2400>;
};
};
@@ -268,6 +281,7 @@
<38 108>,
<39 109>,
<40 110>,
+ <41 115>,
<54 111>,
<55 113>;
};
diff --git a/arch/arm/boot/dts/msm8974pro-ab-fluid.dts b/arch/arm/boot/dts/msm8226-v2-qrd-skuf-pvt.dts
similarity index 61%
copy from arch/arm/boot/dts/msm8974pro-ab-fluid.dts
copy to arch/arm/boot/dts/msm8226-v2-qrd-skuf-pvt.dts
index 9a31834..f5ac301 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-fluid.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-skuf-pvt.dts
@@ -11,18 +11,12 @@
*/
/dts-v1/;
-
-/include/ "msm8974pro-ab.dtsi"
-/include/ "msm8974-fluid.dtsi"
+/include/ "msm8226-v2.dtsi"
+/include/ "msm8226-qrd-skuf.dtsi"
/ {
- model = "Qualcomm MSM 8974Pro FLUID";
- compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
- qcom,msm-id = <209 3 0x10000>,
- <211 3 0x10000>,
- <212 3 0x10000>,
- <214 3 0x10000>,
- <215 3 0x10000>,
- <217 3 0x10000>,
- <218 3 0x10000>;
+ model = "Qualcomm MSM 8226v2 QRD PVT";
+ compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,skuf", "qcom,qrd";
+ qcom,board-id = <0x2000b 0x2>;
};
+
diff --git a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
index 9a750ae..9aa12f6 100644
--- a/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
+++ b/arch/arm/boot/dts/msm8226-v2-qrd-skuf.dts
@@ -12,7 +12,7 @@
/dts-v1/;
/include/ "msm8226-v2.dtsi"
-/include/ "msm8226-qrd.dtsi"
+/include/ "msm8226-qrd-skuf.dtsi"
/ {
model = "Qualcomm MSM 8226v2 QRD";
@@ -20,189 +20,10 @@
qcom,board-id = <0xb 0x2>;
};
-&soc {
- sound {
- qcom,model = "msm8226-tapan-skuf-snd-card";
-
- qcom,audio-routing =
- "RX_BIAS", "MCLK",
- "LDO_H", "MCLK",
- "SPK_OUT", "MCLK",
- "SPK_OUT", "EXT_VDD_SPKR",
- "Lineout_1 amp", "LINEOUT1",
- "Lineout_2 amp", "LINEOUT2",
- "AMIC1", "MIC BIAS1 External",
- "MIC BIAS1 External", "Handset Mic",
- "AMIC2", "MIC BIAS2 External",
- "MIC BIAS2 External", "Headset Mic",
- "AMIC3", "MIC BIAS1 External",
- "MIC BIAS1 External", "ANCRight Headset Mic",
- "AMIC4", "MIC BIAS2 External",
- "MIC BIAS2 External", "ANCLeft Headset Mic";
-
- qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
- qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
- qcom,cdc-vdd-spkr-gpios;
- qcom,cdc-us-euro-gpios;
- };
-
- sound-9302 {
- qcom,model = "msm8226-tapan9302-skuf-snd-card";
-
- qcom,audio-routing =
- "RX_BIAS", "MCLK",
- "LDO_H", "MCLK",
- "SPK_OUT", "MCLK",
- "SPK_OUT", "EXT_VDD_SPKR",
- "Lineout_1 amp", "LINEOUT1",
- "Lineout_2 amp", "LINEOUT2",
- "AMIC1", "MIC BIAS1 External",
- "MIC BIAS1 External", "Handset Mic",
- "AMIC2", "MIC BIAS2 External",
- "MIC BIAS2 External", "Headset Mic",
- "AMIC3", "MIC BIAS1 External",
- "MIC BIAS1 External", "Handset Mic";
-
- qcom,cdc-mclk-gpios = <&pm8226_gpios 1 0>;
- qcom,cdc-lineout-spkr-gpios = <&pm8226_gpios 2 0>;
- qcom,cdc-vdd-spkr-gpios;
- qcom,cdc-us-euro-gpios;
- };
-
- tp_power: regulator-tp {
- compatible = "regulator-fixed";
- regulator-name = "tp_power";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- gpio = <&msmgpio 15 0>;
- startup-delay-us = <20000>;
- enable-active-high;
- };
-
- i2c@f9927000 {
- goodix@5d {
- compatible = "goodix,gt9xx";
- reg = <0x5d>;
- interrupt-parent = <&msmgpio>;
- interrupts = <17 0x2008>;
- reset-gpios = <&msmgpio 16 0x00>;
- interrupt-gpios = <&msmgpio 17 0x00>;
- avdd-supply = <&tp_power>;
- goodix,panel-coords = <0 0 720 1200>;
- goodix,display-coords = <0 0 720 1080>;
- goodix,button-map= <158 102 139>;
- goodix,family-id = <0x0>;
- goodix,cfg-data = [
- 41 D0 02 00 05 0A 35 01 01 0F
- 2D 08 55 32 03 04 00 00 00 00
- 00 00 05 0A 0C 0F 0A 8C 0E 0E
- 30 2E B8 08 00 00 00 83 03 1D
- 00 00 00 00 00 00 00 00 00 00
- 00 2D 62 94 C5 02 05 00 00 04
- 96 30 00 80 39 00 71 42 00 63
- 4D 00 56 5A 00 56 10 38 68 00
- 56 50 35 AA AA 27 00 00 00 00
- 00 01 1B 14 0C 14 00 00 01 00
- 00 00 00 00 00 00 00 00 00 00
- 00 00 02 04 06 08 0A 0C 0E 10
- 12 14 16 18 1A 1C FF FF FF FF
- FF FF FF FF FF FF FF FF FF FF
- FF FF 00 02 04 06 08 0A 0C 0F
- 10 12 13 14 16 18 1C 1D 1E 1F
- 20 21 22 24 26 28 29 2A FF FF
- FF FF FF FF FF FF FF FF FF FF
- FF FF FF FF 06 01];
- };
- };
-};
-
-&spmi_bus {
- qcom,pm8226@0 {
- qcom,leds@a300 {
- status = "disabled";
- };
-
- qcom,leds@a500 {
- status = "disabled";
- };
- };
-
- qcom,pm8226@1 {
- qcom,leds@d800 {
- 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>;
- };
-};
-
-&qrd_batterydata {
- qcom,rpull-up-kohm = <100>;
- qcom,vref-batt-therm = <1800000>;
-
- /include/ "batterydata-qrd-4v35-2500mah.dtsi"
-};
-
&pm8226_bms {
qcom,use-external-rsense;
- qcom,battery-data = <&qrd_batterydata>;
-};
-
-&pm8226_chg {
- qcom,battery-data = <&qrd_batterydata>;
};
&pm8226_iadc {
qcom,rsense = <10000000>;
};
-
-&mdss_dsi0 {
- qcom,dsi-pref-prim-pan = <&dsi_nt35521_720_vid>;
-};
-
-&dsi_nt35521_720_vid {
- qcom,cont-splash-enabled;
-};
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index cfb6bed..151b508 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -189,14 +189,14 @@
qcom,vidc-iommu-domains {
qcom,domain-ns {
qcom,vidc-domain-phandle = <&venus_domain_ns>;
- qcom,vidc-partition-buffer-types = <0x1ff>,
- <0x200>;
+ qcom,vidc-partition-buffer-types = <0x7ff>,
+ <0x800>;
};
qcom,domain-cp {
qcom,vidc-domain-phandle = <&venus_domain_cp>;
- qcom,vidc-partition-buffer-types = <0x2>,
- <0x1f1>;
+ qcom,vidc-partition-buffer-types = <0x6>,
+ <0x7c1>;
};
};
};
@@ -299,6 +299,37 @@
qcom,android-usb-swfi-latency = <1>;
};
+ hsic_host: hsic@f9a00000 {
+ status = "disabled";
+ compatible = "qcom,hsic-host";
+ reg = <0xf9a00000 0x400>;
+ #address-cells = <0>;
+ interrupt-parent = <&hsic_host>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 136 0
+ 1 &intc 0 148 0
+ 2 &msmgpio 115 0x8>;
+ interrupt-names = "core_irq", "async_irq", "wakeup";
+ hsic_vdd_dig-supply = <&pm8226_s1_corner>;
+ HSIC_GDSC-supply = <&gdsc_usb_hsic>;
+ hsic,strobe-gpio = <&msmgpio 115 0x00>;
+ hsic,data-gpio = <&msmgpio 116 0x00>;
+ hsic,ignore-cal-pad-config;
+ hsic,strobe-pad-offset = <0x2050>;
+ hsic,data-pad-offset = <0x2054>;
+ qcom,phy-susp-sof-workaround;
+ hsic,vdd-voltage-level = <1 5 7>;
+
+ qcom,msm-bus,name = "hsic";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <85 512 0 0>,
+ <85 512 40000 160000>;
+ };
+
wcd9xxx_intc: wcd9xxx-irq {
compatible = "qcom,wcd9xxx-irq";
interrupt-controller;
@@ -1088,6 +1119,10 @@
qcom,core-limit-temp = <80>;
qcom,core-temp-hysteresis = <10>;
qcom,core-control-mask = <0xe>;
+ qcom,hotplug-temp = <110>;
+ qcom,hotplug-temp-hysteresis = <20>;
+ qcom,cpu-sensors = "tsens_tz_sensor5", "tsens_tz_sensor5",
+ "tsens_tz_sensor2", "tsens_tz_sensor2";
qcom,vdd-restriction-temp = <5>;
qcom,vdd-restriction-temp-hysteresis = <10>;
vdd-dig-supply = <&pm8226_s1_floor_corner>;
diff --git a/arch/arm/boot/dts/msm8610-bus.dtsi b/arch/arm/boot/dts/msm8610-bus.dtsi
index 6b72e66..c6e81d8 100644
--- a/arch/arm/boot/dts/msm8610-bus.dtsi
+++ b/arch/arm/boot/dts/msm8610-bus.dtsi
@@ -56,8 +56,8 @@
qcom,ws = <10000>;
qcom,qport = <2>;
qcom,mas-hw-id = <11>;
- qcom,prio1 = <2>;
- qcom,prio0 = <2>;
+ qcom,prio1 = <3>;
+ qcom,prio0 = <3>;
};
mas-mdpe {
@@ -71,8 +71,8 @@
qcom,ws = <10000>;
qcom,qport = <7>;
qcom,mas-hw-id = <11>;
- qcom,prio1 = <2>;
- qcom,prio0 = <2>;
+ qcom,prio1 = <1>;
+ qcom,prio0 = <1>;
};
fab-bimc {
@@ -913,7 +913,7 @@
qcom,fabclk-dual = "mem_clk";
qcom,fabclk-active = "mem_a_clk";
qcom,ntieredslaves = <0>;
- qcom,qos-freq = <4800>;
+ qcom,qos-freq = <19200>;
qcom,hw-sel = "BIMC";
qcom,rpm-en;
@@ -930,13 +930,19 @@
qcom,masterp = <0>;
qcom,tier = <2>;
qcom,hw-sel = "BIMC";
- qcom,mode = "Fixed";
+ qcom,mode = "Limiter";
qcom,qport = <0>;
qcom,ws = <10000>;
qcom,mas-hw-id = <0>;
qcom,prio-rd = <0>;
qcom,prio-wr = <0>;
qcom,prio-lvl = <0>;
+ qcom,mode-thresh = "Fixed";
+ qcom,thresh = <800000>;
+ qcom,dual-conf;
+ qcom,bimc,bw = <300000>;
+ qcom,bimc,gp = <5>;
+ qcom,bimc,thmp = <50>;
};
mas-mss-proc {
diff --git a/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi b/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
index e133117..bdcab77 100644
--- a/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8610-camera-sensor-cdp-mtp.dtsi
@@ -149,6 +149,44 @@
qcom,cci-master = <0>;
};
+ qcom,camera@34 {
+ compatible = "sne,imx134";
+ reg = <0x34>;
+ qcom,slave-id = <0x34 0x0016 0x0134>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,actuator-src = <&actuator0>;
+ qcom,led-flash-src = <&led_flash0>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "imx134";
+ cam_vdig-supply = <&pm8110_l2>;
+ cam_vana-supply = <&pm8110_l19>;
+ cam_vio-supply = <&pm8110_l14>;
+ cam_vaf-supply = <&pm8110_l16>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 0 0 0>;
+ qcom,cam-vreg-min-voltage = <1200000 1800000 2850000 3000000>;
+ qcom,cam-vreg-max-voltage = <1200000 1800000 2850000 3000000>;
+ qcom,cam-vreg-op-mode = <200000 8000 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 13 0>,
+ <&msmgpio 21 0>,
+ <&msmgpio 20 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET1",
+ "CAM_STANDBY";
+ qcom,csi-lane-assign = <0xe4>;
+ qcom,csi-lane-mask = <0x3>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ };
+
qcom,camera@6d {
compatible = "qcom,ov9724";
reg = <0x6d>;
diff --git a/arch/arm/boot/dts/msm8610-cdp.dtsi b/arch/arm/boot/dts/msm8610-cdp.dtsi
index 452cc2f..1fe7d2f 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8610-cdp.dtsi
@@ -245,7 +245,6 @@
vdd-io-supply = <&pm8110_l6>;
qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 1800000>;
qcom,vdd-io-current-level = <200 60000>;
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
index 78a4b5a..ca4f721 100644
--- a/arch/arm/boot/dts/msm8610-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -205,12 +205,56 @@
qcom,round-robin;
};
+ audio_etm0 {
+ compatible = "qcom,coresight-audio-etm";
+
+ coresight-id = <13>;
+ coresight-name = "coresight-audio-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <2>;
+ };
+
+ modem_etm0 {
+ compatible = "qcom,coresight-modem-etm";
+
+ coresight-id = <14>;
+ coresight-name = "coresight-modem-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <1>;
+ };
+
+ wcn_etm0 {
+ compatible = "qcom,coresight-wcn-etm";
+
+ coresight-id = <15>;
+ coresight-name = "coresight-wcn-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in1>;
+ coresight-child-ports = <0>;
+ };
+
+ rpm_etm0 {
+ compatible = "qcom,coresight-rpm-etm";
+
+ coresight-id = <16>;
+ coresight-name = "coresight-rpm-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <0>;
+ };
+
csr: csr@fc301000 {
compatible = "qcom,coresight-csr";
reg = <0xfc301000 0x1000>;
reg-names = "csr-base";
- coresight-id = <13>;
+ coresight-id = <17>;
coresight-name = "coresight-csr";
coresight-nr-inports = <0>;
@@ -222,7 +266,7 @@
reg = <0xfc310000 0x1000>;
reg-names = "cti-base";
- coresight-id = <14>;
+ coresight-id = <18>;
coresight-name = "coresight-cti0";
coresight-nr-inports = <0>;
};
@@ -232,7 +276,7 @@
reg = <0xfc311000 0x1000>;
reg-names = "cti-base";
- coresight-id = <15>;
+ coresight-id = <19>;
coresight-name = "coresight-cti1";
coresight-nr-inports = <0>;
};
@@ -242,7 +286,7 @@
reg = <0xfc312000 0x1000>;
reg-names = "cti-base";
- coresight-id = <16>;
+ coresight-id = <20>;
coresight-name = "coresight-cti2";
coresight-nr-inports = <0>;
};
@@ -252,7 +296,7 @@
reg = <0xfc313000 0x1000>;
reg-names = "cti-base";
- coresight-id = <17>;
+ coresight-id = <21>;
coresight-name = "coresight-cti3";
coresight-nr-inports = <0>;
};
@@ -262,7 +306,7 @@
reg = <0xfc314000 0x1000>;
reg-names = "cti-base";
- coresight-id = <18>;
+ coresight-id = <22>;
coresight-name = "coresight-cti4";
coresight-nr-inports = <0>;
};
@@ -272,7 +316,7 @@
reg = <0xfc315000 0x1000>;
reg-names = "cti-base";
- coresight-id = <19>;
+ coresight-id = <23>;
coresight-name = "coresight-cti5";
coresight-nr-inports = <0>;
};
@@ -282,7 +326,7 @@
reg = <0xfc316000 0x1000>;
reg-names = "cti-base";
- coresight-id = <20>;
+ coresight-id = <24>;
coresight-name = "coresight-cti6";
coresight-nr-inports = <0>;
};
@@ -292,7 +336,7 @@
reg = <0xfc317000 0x1000>;
reg-names = "cti-base";
- coresight-id = <21>;
+ coresight-id = <25>;
coresight-name = "coresight-cti7";
coresight-nr-inports = <0>;
};
@@ -302,7 +346,7 @@
reg = <0xfc318000 0x1000>;
reg-names = "cti-base";
- coresight-id = <22>;
+ coresight-id = <26>;
coresight-name = "coresight-cti8";
coresight-nr-inports = <0>;
};
@@ -312,7 +356,7 @@
reg = <0xfc351000 0x1000>;
reg-names = "cti-base";
- coresight-id = <23>;
+ coresight-id = <27>;
coresight-name = "coresight-cti-cpu0";
coresight-nr-inports = <0>;
};
@@ -322,7 +366,7 @@
reg = <0xfc352000 0x1000>;
reg-names = "cti-base";
- coresight-id = <24>;
+ coresight-id = <28>;
coresight-name = "coresight-cti-cpu1";
coresight-nr-inports = <0>;
};
@@ -332,7 +376,7 @@
reg = <0xfc353000 0x1000>;
reg-names = "cti-base";
- coresight-id = <25>;
+ coresight-id = <29>;
coresight-name = "coresight-cti-cpu2";
coresight-nr-inports = <0>;
};
@@ -342,11 +386,51 @@
reg = <0xfc354000 0x1000>;
reg-names = "cti-base";
- coresight-id = <26>;
+ coresight-id = <30>;
coresight-name = "coresight-cti-cpu3";
coresight-nr-inports = <0>;
};
+ cti_wcn_cpu0: cti@fc335000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc335000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <31>;
+ coresight-name = "coresight-cti-wcn-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_modem_cpu0: cti@fc338000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc338000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <32>;
+ coresight-name = "coresight-cti-modem-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_audio_cpu0: cti@fc33c000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc33c000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <33>;
+ coresight-name = "coresight-cti-audio-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_rpm_cpu0: cti@fc360000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc360000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <34>;
+ coresight-name = "coresight-cti-rpm-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
hwevent: hwevent@fd820018 {
compatible = "qcom,coresight-hwevent";
reg = <0xfd820018 0x80>,
@@ -355,7 +439,7 @@
<0xfc401600 0x80>;
reg-names = "mmss-mux", "apcs-mux", "ppss-mux", "gcc-mux";
- coresight-id = <27>;
+ coresight-id = <35>;
coresight-name = "coresight-hwevent";
coresight-nr-inports = <0>;
@@ -367,7 +451,7 @@
reg = <0xfc4be024 0x8>;
reg-names = "fuse-base";
- coresight-id = <28>;
+ coresight-id = <36>;
coresight-name = "coresight-fuse";
coresight-nr-inports = <0>;
};
diff --git a/arch/arm/boot/dts/msm8610-mdss-panels.dtsi b/arch/arm/boot/dts/msm8610-mdss-panels.dtsi
index 243d7e8..afc5459 100644
--- a/arch/arm/boot/dts/msm8610-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/msm8610-mdss-panels.dtsi
@@ -15,3 +15,4 @@
/include/ "dsi-panel-nt35590-720p-video.dtsi"
/include/ "dsi-panel-otm8018b-fwvga-video.dtsi"
/include/ "dsi-panel-hx8379a-wvga-video.dtsi"
+/include/ "dsi-panel-hx8389b-qhd-video.dtsi"
diff --git a/arch/arm/boot/dts/msm8610-mdss.dtsi b/arch/arm/boot/dts/msm8610-mdss.dtsi
index de74e52..929659e 100644
--- a/arch/arm/boot/dts/msm8610-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8610-mdss.dtsi
@@ -38,9 +38,6 @@
qcom,platform-reset-gpio = <&msmgpio 41 0>;
qcom,platform-te-gpio = <&msmgpio 12 0>;
qcom,platform-mode-gpio = <&msmgpio 7 0>;
-
- qcom,platform-reset-sequence = <1 20 0 2 1 20 2>;
-
qcom,platform-strength-ctrl = [ff 06];
qcom,platform-bist-ctrl = [03 03 00 00 0f 00];
qcom,platform-regulator-settings = [02 08 05 00 20 03];
diff --git a/arch/arm/boot/dts/msm8610-mtp.dtsi b/arch/arm/boot/dts/msm8610-mtp.dtsi
index 1cc3e61..cad636c 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8610-mtp.dtsi
@@ -131,6 +131,17 @@
capella,ps_conf1_val = <0x0006>;
capella,ps_conf3_val = <0x3010>;
};
+ nfc-nci@0e {
+ compatible = "qcom,nfc-nci";
+ reg = <0x0e>;
+ qcom,irq-gpio = <&msmgpio 77 0x00>;
+ qcom,dis-gpio = <&msmgpio 93 0x00>;
+ qcom,clk-en-gpio = <&msmgpio 78 0x00>;
+ qcom,clk-src = "GPCLK";
+ interrupt-parent = <&msmgpio>;
+ interrupts = <77 0>;
+ qcom,clk-gpio = <&pm8110_gpios 1 0>;
+ };
};
gen-vkeys {
@@ -301,7 +312,6 @@
vdd-io-supply = <&pm8110_l6>;
qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 1800000>;
qcom,vdd-io-current-level = <200 60000>;
@@ -374,6 +384,11 @@
&pm8110_gpios {
gpio@c000 { /* GPIO 1 */
+ qcom,mode = <0>; /* QPNP_PIN_MODE_DIG_IN */
+ qcom,pull = <5>; /* QPNP_PIN_PULL_NO */
+ qcom,vin-sel = <2>; /* QPNP_PIN_VIN2 */
+ qcom,src-sel = <2>; /* QPNP_PIN_SEL_FUNC_1 */
+ qcom,master-en = <1>;
};
gpio@c100 { /* GPIO 2 */
@@ -408,12 +423,28 @@
};
};
+/ {
+ mtp_batterydata: qcom,battery-data {
+ qcom,rpull-up-kohm = <100>;
+ qcom,vref-batt-therm = <1800000>;
+
+ /include/ "batterydata-palladium.dtsi"
+ /include/ "batterydata-mtp-3000mah.dtsi"
+ };
+};
+
&pm8110_bms {
status = "ok";
+ qcom,battery-data = <&mtp_batterydata>;
+};
+
+&pm8110_chg {
+ qcom,battery-data = <&mtp_batterydata>;
};
&mdss_mdp {
qcom,mdss-pref-prim-intf = "dsi";
+ batfet-supply = <&pm8110_chg_batif>;
};
&mdss_dsi0 {
diff --git a/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi b/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
index 17bf329..08e9be5 100644
--- a/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd-skuab.dtsi
@@ -13,6 +13,16 @@
/include/ "msm8610-qrd.dtsi"
&soc {
+ gpio-leds {
+ compatible = "gpio-leds";
+ status = "disabled";
+
+ gpio_flash: gpio-flash {
+ gpios = <&pm8110_gpios 1 0>;
+ label = "gpio-flash";
+ linux,default-trigger = "gpio_flash_trigger";
+ };
+ };
sound {
qcom,model = "msm8x10-skuab-snd-card";
@@ -44,6 +54,40 @@
focaltech,no-force-update;
focaltech,i2c-pull-up;
};
+ goodix@5d {
+ compatible = "goodix,gt9xx";
+ reg = <0x5d>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <1 0x2008>;
+ reset-gpios = <&msmgpio 0 0x00>;
+ interrupt-gpios = <&msmgpio 1 0x00>;
+ vdd-supply = <&pm8110_l19>;
+ vcc-i2c-supply = <&pm8110_l14>;
+ goodix,panel-coords = <0 0 540 980>;
+ goodix,display-coords = <0 0 540 960>;
+ goodix,button-map= <139 102 158>;
+ goodix,product-id = "915";
+ goodix,cfg-data0 = [
+ 46 1C 02 C0 03 0A 05 11 01 08
+ 14 3B 46 32 03 05 00 00 00 00
+ 00 00 00 00 00 00 00 8A 09 0B
+ 39 00 99 0A 00 00 02 83 03 1D
+ 00 08 00 00 00 00 00 00 00 00
+ 00 1D 73 94 C5 02 07 00 00 04
+ 78 21 00 5C 2C 00 48 3A 00 3A
+ 4C 00 2F 65 00 30 10 30 50 00
+ 56 45 35 FF FF 17 00 00 00 00
+ 00 01 1C 15 0C 14 5F 03 02 00
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00 16 14 12 10 0E 0C 0A 08
+ 06 04 02 FF FF FF 00 00 00 00
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00 22 21 20 1F 1E 1D 1C 18
+ 16 12 10 0F 0C 0A 08 06 04 02
+ 00 FF FF FF FF FF FF FF 00 00
+ 00 FF FF FF FF FF FF FF FF FF
+ F8 FF FF FF E4 01];
+ };
};
gen-vkeys {
compatible = "qcom,gen-vkeys";
@@ -55,6 +99,7 @@
qcom,key-codes = <139 102 158>;
qcom,y-offset = <0>;
};
+
i2c@f9925000 {
fsl@1c {
compatible = "fsl,mma8x5x";
diff --git a/arch/arm/boot/dts/msm8610-qrd.dtsi b/arch/arm/boot/dts/msm8610-qrd.dtsi
index 83d84c0..7e191e1 100644
--- a/arch/arm/boot/dts/msm8610-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8610-qrd.dtsi
@@ -367,3 +367,7 @@
qcom,android-usb-cdrom;
qcom,android-usb-internal-ums;
};
+
+&mdss_mdp {
+ batfet-supply = <&pm8110_chg_batif>;
+};
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index eb69678..f97d991 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -391,3 +391,7 @@
};
};
};
+
+&pm8110_chg_batif {
+ regulator-name = "batfet";
+};
diff --git a/arch/arm/boot/dts/msm8610-v1-pm.dtsi b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
index 4a2de1c..6296692 100644
--- a/arch/arm/boot/dts/msm8610-v1-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v1-pm.dtsi
@@ -113,8 +113,8 @@
qcom,mode = "wfi";
qcom,l2 = "l2_cache_active";
qcom,latency-us = <1>;
- qcom,ss-power = <784>;
- qcom,energy-overhead = <190000>;
+ qcom,ss-power = <530>;
+ qcom,energy-overhead = <52800>;
qcom,time-overhead = <100>;
};
@@ -122,30 +122,30 @@
reg = <0x1>;
qcom,mode = "standalone_pc";
qcom,l2 = "l2_cache_active";
- qcom,latency-us = <3000>;
- qcom,ss-power = <725>;
- qcom,energy-overhead = <99500>;
- qcom,time-overhead = <3130>;
+ qcom,latency-us = <500>;
+ qcom,ss-power = <410>;
+ qcom,energy-overhead = <603400>;
+ qcom,time-overhead = <1200>;
};
qcom,lpm-level@2 {
reg = <0x2>;
qcom,mode = "pc";
qcom,l2 = "l2_cache_retention";
- qcom,latency-us = <20000>;
- qcom,ss-power = <138>;
- qcom,energy-overhead = <1208400>;
- qcom,time-overhead = <9200>;
+ qcom,latency-us = <520>;
+ qcom,ss-power = <460>;
+ qcom,energy-overhead = <704900>;
+ qcom,time-overhead = <1300>;
};
qcom,lpm-level@3 {
reg = <0x3>;
qcom,mode = "pc";
qcom,l2 = "l2_cache_pc";
- qcom,latency-us = <30000>;
- qcom,ss-power = <110>;
- qcom,energy-overhead = <1250300>;
- qcom,time-overhead = <9500>;
+ qcom,latency-us = <11700>;
+ qcom,ss-power = <315>;
+ qcom,energy-overhead = <1027150>;
+ qcom,time-overhead = <2400>;
};
};
@@ -180,7 +180,6 @@
<0xff 59>, /* mss_to_apps_irq(2) */
<0xff 60>, /* mss_to_apps_irq(3) */
<0xff 61>, /* mss_a2_bam_irq */
- <0xff 63>, /* wcd9xxx_irq */
<0xff 65>, /* o_gc_sys_irq[0] */
<0xff 74>, /* venus0_mmu_cirpt[1] */
<0xff 75>, /* venus0_mmu_cirpt[0] */
diff --git a/arch/arm/boot/dts/msm8610-v1-qrd-skuab-dvt2.dts b/arch/arm/boot/dts/msm8610-v1-qrd-skuab-dvt2.dts
new file mode 100644
index 0000000..4a08f3f
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v1-qrd-skuab-dvt2.dts
@@ -0,0 +1,35 @@
+/* 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/ "msm8610-v1.dtsi"
+/include/ "msm8610-qrd-skuab.dtsi"
+/include/ "msm8612-qrd-camera-sensor.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610v1 QRD SKUAB DVT2";
+ compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
+ qcom,board-id = <0x2000b 3>;
+};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_hx8389b_qhd_vid>;
+};
+
+&dsi_hx8389b_qhd_vid {
+ qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8610-v2-pm.dtsi b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
index 079f0b1..6c7f2f6 100644
--- a/arch/arm/boot/dts/msm8610-v2-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-v2-pm.dtsi
@@ -115,8 +115,8 @@
qcom,mode = "wfi";
qcom,l2 = "l2_cache_active";
qcom,latency-us = <1>;
- qcom,ss-power = <784>;
- qcom,energy-overhead = <190000>;
+ qcom,ss-power = <530>;
+ qcom,energy-overhead = <52800>;
qcom,time-overhead = <100>;
};
@@ -124,30 +124,30 @@
reg = <0x1>;
qcom,mode = "standalone_pc";
qcom,l2 = "l2_cache_active";
- qcom,latency-us = <3000>;
- qcom,ss-power = <725>;
- qcom,energy-overhead = <99500>;
- qcom,time-overhead = <3130>;
+ qcom,latency-us = <500>;
+ qcom,ss-power = <410>;
+ qcom,energy-overhead = <603400>;
+ qcom,time-overhead = <1200>;
};
qcom,lpm-level@2 {
reg = <0x2>;
qcom,mode = "pc";
qcom,l2 = "l2_cache_gdhs";
- qcom,latency-us = <20000>;
- qcom,ss-power = <138>;
- qcom,energy-overhead = <1208400>;
- qcom,time-overhead = <9200>;
+ qcom,latency-us = <10700>;
+ qcom,ss-power = <325>;
+ qcom,energy-overhead = <441250>;
+ qcom,time-overhead = <1020>;
};
qcom,lpm-level@3 {
reg = <0x3>;
qcom,mode = "pc";
qcom,l2 = "l2_cache_pc";
- qcom,latency-us = <30000>;
- qcom,ss-power = <110>;
- qcom,energy-overhead = <1250300>;
- qcom,time-overhead = <9500>;
+ qcom,latency-us = <11700>;
+ qcom,ss-power = <315>;
+ qcom,energy-overhead = <1027150>;
+ qcom,time-overhead = <2400>;
};
};
@@ -177,7 +177,6 @@
<0xff 59>, /* mss_to_apps_irq(2) */
<0xff 60>, /* mss_to_apps_irq(3) */
<0xff 61>, /* mss_a2_bam_irq */
- <0xff 63>, /* wcd9xxx_irq */
<0xff 173>, /* o_wcss_apss_smd_hi */
<0xff 174>, /* o_wcss_apss_smd_med */
<0xff 175>, /* o_wcss_apss_smd_low */
diff --git a/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts b/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts
new file mode 100644
index 0000000..4735554
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-v2-qrd-skuab-dvt2.dts
@@ -0,0 +1,58 @@
+/* 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/ "msm8610-v2.dtsi"
+/include/ "msm8610-qrd-skuab.dtsi"
+/include/ "msm8612-qrd-camera-sensor.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8610v2 QRD SKUAB DVT2";
+ compatible = "qcom,msm8610-qrd", "qcom,msm8610", "qcom,qrd";
+ qcom,board-id = <0x2000b 3>;
+};
+
+&soc {
+ gpio-leds {
+ status = "ok";
+ };
+};
+
+&pm8110_gpios {
+ gpio@c000 { /* GPIO 1 */
+ reg = <0xc000 0x100>;
+ qcom,pin-num = <1>;
+ };
+};
+
+&led_flash0 {
+ status = "ok";
+};
+
+&i2c {
+ qcom,camera@20 {
+ qcom,led-flash-src = <&led_flash0>;
+ };
+};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_hx8389b_qhd_vid>;
+};
+
+&dsi_hx8389b_qhd_vid {
+ qcom,cont-splash-enabled;
+};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 7dcb985..f6ced20 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -271,7 +271,6 @@
vdd-io-supply = <&pm8110_l6>;
qcom,vdd-io-always-on;
- qcom,vdd-io-lpm-sup;
qcom,vdd-io-voltage-level = <1800000 1800000>;
qcom,vdd-io-current-level = <9000 60000>;
@@ -795,6 +794,10 @@
qcom,core-limit-temp = <80>;
qcom,core-temp-hysteresis = <10>;
qcom,core-control-mask = <0xe>;
+ qcom,hotplug-temp = <110>;
+ qcom,hotplug-temp-hysteresis = <20>;
+ qcom,cpu-sensors = "tsens_tz_sensor5", "tsens_tz_sensor5",
+ "tsens_tz_sensor5", "tsens_tz_sensor5";
qcom,vdd-restriction-temp = <5>;
qcom,vdd-restriction-temp-hysteresis = <10>;
vdd-dig-supply = <&pm8110_s1_floor_corner>;
diff --git a/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi b/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi
index b060abe..205e749 100644
--- a/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi
+++ b/arch/arm/boot/dts/msm8612-qrd-camera-sensor.dtsi
@@ -11,6 +11,17 @@
* GNU General Public License for more details.
*/
+&soc {
+
+ led_flash0: qcom,camera-led-flash {
+ cell-index = <0>;
+ compatible = "qcom,camera-led-flash";
+ qcom,flash-type = <3>;
+ qcom,flash-source = <&gpio_flash>;
+ qcom,torch-source = <&gpio_flash>;
+ status = "disabled";
+ };
+};
&i2c {
qcom,camera@20 {
@@ -67,6 +78,7 @@
gpios = <&msmgpio 14 0>,
<&msmgpio 15 0>,
<&msmgpio 85 0>;
+ qcom,gpio-reset = <1>;
qcom,gpio-standby = <2>;
qcom,gpio-req-tbl-num = <0 1 2>;
qcom,gpio-req-tbl-flags = <1 0 0>;
diff --git a/arch/arm/boot/dts/msm8926-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/msm8926-camera-sensor-qrd.dtsi
index a85e048..9b812da 100644
--- a/arch/arm/boot/dts/msm8926-camera-sensor-qrd.dtsi
+++ b/arch/arm/boot/dts/msm8926-camera-sensor-qrd.dtsi
@@ -31,6 +31,122 @@
qcom,cci-master = <0>;
};
+ eeprom2: qcom,eeprom@6b{
+ cell-index = <2>;
+ reg = <0x6b>;
+ qcom,eeprom-name = "ofilm_oty5f03";
+ compatible = "qcom,eeprom";
+ qcom,slave-addr = <0x6c>;
+ qcom,cci-master = <0>;
+ qcom,num-blocks = <7>;
+
+ qcom,page0 = <1 0x0100 2 0x01 1 1>;
+ qcom,poll0 = <0 0x0 2 0 1 1>;
+ qcom,mem0 = <0 0x0 2 0 1 0>;
+ qcom,page1 = <1 0x3d84 2 0xc0 1 1>;
+ qcom,poll1 = <0 0x0 2 0 1 1>;
+ qcom,mem1 = <0 0x0 2 0 1 0>;
+ qcom,page2 = <1 0x3d85 2 0x00 1 1>;
+ qcom,poll2 = <0 0x0 2 0 1 1>;
+ qcom,mem2 = <0 0x0 2 0 1 0>;
+ qcom,page3 = <1 0x3d86 2 0x0f 1 1>;
+ qcom,pageen3 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll3 = <0 0x0 2 0 1 1>;
+ qcom,mem3 = <16 0x3d00 2 0 1 0>;
+ qcom,page4 = <1 0x3d84 2 0xc0 1 1>;
+ qcom,poll4 = <0 0x0 2 0 1 1>;
+ qcom,mem4 = <0 0x0 2 0 1 0>;
+ qcom,page5 = <1 0x3d85 2 0x10 1 1>;
+ qcom,poll5 = <0 0x0 2 0 1 1>;
+ qcom,mem5 = <0 0x0 2 0 1 0>;
+ qcom,page6 = <1 0x3d86 2 0x1f 1 1>;
+ qcom,pageen6 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll6 = <0 0x0 2 0 1 1>;
+ qcom,mem6 = <16 0x3d00 2 0 1 0>;
+
+ cam_vio-supply = <&pm8226_lvs1>;
+ cam_vana-supply = <&pm8226_l19>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana";
+ qcom,cam-vreg-type = <1 0>;
+ qcom,cam-vreg-min-voltage = <0 2850000>;
+ qcom,cam-vreg-max-voltage = <0 2850000>;
+ qcom,cam-vreg-op-mode = <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,cam-power-seq-type = "sensor_vreg",
+ "sensor_vreg", "sensor_gpio",
+ "sensor_gpio", "sensor_gpio" , "sensor_clk";
+ qcom,cam-power-seq-val = "cam_vio", "cam_vana","sensor_gpio_vdig",
+ "sensor_gpio_reset",
+ "sensor_gpio_standby","sensor_cam_mclk" ;
+ qcom,cam-power-seq-cfg-val = <1 1 1 1 1 24000000>;
+ qcom,cam-power-seq-delay = <1 1 10 10 10 5>;
+ };
+
+ eeprom3: qcom,eeprom@6c {
+ cell-index = <3>;
+ reg = <0x6c>;
+ qcom,eeprom-name = "sunny_q8v18a";
+ compatible = "qcom,eeprom";
+ qcom,slave-addr = <0x20>;
+ qcom,cci-master = <0>;
+ qcom,num-blocks = <4>;
+ qcom,page0 = <1 0x0100 2 0x01 1 1>;
+ qcom,poll0 = <0 0x0 2 0 1 1>;
+ qcom,mem0 = <0 0x0 2 0 1 0>;
+ qcom,page1 = <1 0x3d84 2 0xc0 1 1>;
+ qcom,poll1 = <0 0x0 2 0 1 1>;
+ qcom,mem1 = <0 0x3d00 2 0 1 0>;
+ qcom,page2 = <1 0x3d88 2 0x7010 2 1>;
+ qcom,poll2 = <0 0x0 2 0 1 1>;
+ qcom,mem2 = <0 0x3d00 2 0 1 0>;
+ qcom,page3 = <1 0x3d8A 2 0x70F4 2 1>;
+ qcom,pageen3 = <1 0x3d81 2 0x01 1 10>;
+ qcom,poll3 = <0 0x0 2 0 1 1>;
+ qcom,mem3 = <228 0x7010 2 0 1 1>;
+
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ qcom,cam-vreg-name = "cam_vdig","cam_vana", "cam_vio";
+ qcom,cam-vreg-type = <0 1 2>;
+ qcom,cam-vreg-min-voltage = <1200000 2850000 0>;
+ qcom,cam-vreg-max-voltage = <1200000 2850000 0>;
+ qcom,cam-vreg-op-mode = <200000 80000 0>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 37 0>,
+ <&msmgpio 36 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK",
+ "CAM_RESET1",
+ "CAM_STANDBY";
+ qcom,cam-power-seq-type = "sensor_vreg","sensor_vreg",
+ "sensor_vreg", "sensor_clk",
+ "sensor_gpio", "sensor_gpio";
+ qcom,cam-power-seq-val = "cam_vdig","cam_vana",
+ "cam_vio", "sensor_cam_mclk",
+ "sensor_gpio_reset",
+ "sensor_gpio_standby";
+ qcom,cam-power-seq-cfg-val = <1 1 1 24000000 1 1>;
+ qcom,cam-power-seq-delay = <1 1 1 5 5 10>;
+ };
+
qcom,camera@20 {
compatible = "ovti,ov8865";
reg = <0x20>;
@@ -39,6 +155,7 @@
qcom,csid-sd-index = <0>;
qcom,actuator-src = <&actuator0>;
qcom,led-flash-src = <&led_flash0>;
+ qcom,eeprom-src = <&eeprom3>;
qcom,mount-angle = <90>;
qcom,sensor-name = "ov8865_q8v18a";
cam_vdig-supply = <&pm8226_l5>;
@@ -78,16 +195,16 @@
qcom,slave-id = <0x6c 0x300a 0x5648>;
qcom,csiphy-sd-index = <1>;
qcom,csid-sd-index = <1>;
+ qcom,eeprom-src = <&eeprom2>;
qcom,mount-angle = <270>;
qcom,sensor-name = "ov5648_oty5f03";
- 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,cam-vreg-name = "cam_vio", "cam_vana";
+ qcom,cam-vreg-type = <1 0>;
+ qcom,cam-vreg-min-voltage = <0 2850000>;
+ qcom,cam-vreg-max-voltage = <0 2850000>;
+ qcom,cam-vreg-op-mode = <0 80000>;
qcom,gpio-no-mux = <0>;
gpios = <&msmgpio 26 0>,
<&msmgpio 28 0>,
diff --git a/arch/arm/boot/dts/msm8926-cdp.dts b/arch/arm/boot/dts/msm8926-cdp.dts
index 7d8d6cf..d6e70e6 100644
--- a/arch/arm/boot/dts/msm8926-cdp.dts
+++ b/arch/arm/boot/dts/msm8926-cdp.dts
@@ -32,3 +32,7 @@
};
};
+
+&hsic_host {
+ status = "ok";
+};
diff --git a/arch/arm/boot/dts/msm8926-qrd-skug.dts b/arch/arm/boot/dts/msm8926-qrd-skug.dts
index a366205..6d907ef 100644
--- a/arch/arm/boot/dts/msm8926-qrd-skug.dts
+++ b/arch/arm/boot/dts/msm8926-qrd-skug.dts
@@ -66,6 +66,7 @@
focaltech,fw-delay-readid-ms = <10>;
focaltech,fw-delay-era-flsh-ms = <2000>;
focaltech,fw-auto-cal;
+ focaltech,ignore-id-check;
};
};
@@ -79,6 +80,23 @@
qcom,key-codes = <139 172 158>;
qcom,y-offset = <0>;
};
+
+ gpio-leds {
+ compatible = "gpio-leds";
+ keypad-backlight {
+ gpios = <&msmgpio 34 0>;
+ label = "button-backlight";
+ linux,default-trigger = "none";
+ };
+ };
+};
+
+&spmi_bus {
+ qcom,pm8226@0 {
+ qcom,leds@a100 {
+ status = "disable";
+ };
+ };
};
&mdss_dsi0 {
diff --git a/arch/arm/boot/dts/msm8926.dtsi b/arch/arm/boot/dts/msm8926.dtsi
index 2ab272a..bbddec3 100644
--- a/arch/arm/boot/dts/msm8926.dtsi
+++ b/arch/arm/boot/dts/msm8926.dtsi
@@ -44,6 +44,55 @@
<0xfc4b80b0 0x8>;
reg-names = "rcg_base", "pte_efuse";
};
+
+ qcom,msm-thermal {
+ qcom,cpu-sensors = "tsens_tz_sensor5", "tsens_tz_sensor5",
+ "tsens_tz_sensor1", "tsens_tz_sensor1";
+ };
+
+ qcom,mpm@fc4281d0 {
+ qcom,gpio-map = <3 1>,
+ <4 4 >,
+ <5 5 >,
+ <6 9 >,
+ <7 13>,
+ <8 17>,
+ <9 21>,
+ <10 27>,
+ <11 29>,
+ <12 31>,
+ <13 33>,
+ <14 35>,
+ <15 37>,
+ <16 38>,
+ <17 39>,
+ <18 41>,
+ <19 46>,
+ <20 48>,
+ <21 49>,
+ <22 50>,
+ <23 51>,
+ <24 52>,
+ <25 54>,
+ <26 62>,
+ <27 63>,
+ <28 64>,
+ <29 65>,
+ <30 66>,
+ <31 67>,
+ <32 68>,
+ <33 69>,
+ <34 71>,
+ <35 72>,
+ <36 106>,
+ <37 107>,
+ <38 108>,
+ <39 109>,
+ <40 110>,
+ <41 119>,
+ <54 111>,
+ <55 113>;
+ };
};
&pm8226_l3 {
@@ -89,10 +138,18 @@
};
&msmgpio {
- ngpio = <120>;
+ ngpio = <121>;
};
&memory_hole {
qcom,memblock-remove = <0x08000000 0x7500000
0x0fa00000 0x500000>; /* Address and size of the hole */
};
+
+&hsic_host {
+ interrupt-map = <0 &intc 0 136 0
+ 1 &intc 0 148 0
+ 2 &msmgpio 119 0x8>;
+ hsic,strobe-gpio = <&msmgpio 119 0x00>;
+ hsic,data-gpio = <&msmgpio 120 0x00>;
+};
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
index 9cbd45c..c84dfe5 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
@@ -78,6 +78,7 @@
qcom,mount-angle = <270>;
qcom,sensor-name = "imx135";
qcom,actuator-src = <&actuator1>;
+ qcom,led-flash-src = <&led_flash0>;
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
index 68af4a6..02d2288 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
@@ -78,6 +78,7 @@
qcom,mount-angle = <90>;
qcom,sensor-name = "imx135";
qcom,actuator-src = <&actuator1>;
+ qcom,led-flash-src = <&led_flash0>;
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
diff --git a/arch/arm/boot/dts/msm8974-coresight.dtsi b/arch/arm/boot/dts/msm8974-coresight.dtsi
index a809c2b..b7e64c3 100644
--- a/arch/arm/boot/dts/msm8974-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8974-coresight.dtsi
@@ -219,12 +219,57 @@
qcom,round-robin;
};
+ audio_etm0 {
+ compatible = "qcom,coresight-audio-etm";
+
+ coresight-id = <14>;
+ coresight-name = "coresight-audio-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <2>;
+ };
+
+ modem_etm0 {
+ compatible = "qcom,coresight-modem-etm";
+
+ coresight-id = <15>;
+ coresight-name = "coresight-modem-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <1>;
+ };
+
+ wcn_etm0 {
+ compatible = "qcom,coresight-wcn-etm";
+
+ coresight-id = <16>;
+ coresight-name = "coresight-wcn-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in1>;
+ coresight-child-ports = <2>;
+ };
+
+ rpm_etm0 {
+ compatible = "qcom,coresight-rpm-etm";
+
+ coresight-id = <17>;
+ coresight-name = "coresight-rpm-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <0>;
+ };
+
+
csr: csr@fc302000 {
compatible = "qcom,coresight-csr";
reg = <0xfc302000 0x1000>;
reg-names = "csr-base";
- coresight-id = <14>;
+ coresight-id = <18>;
coresight-name = "coresight-csr";
coresight-nr-inports = <0>;
@@ -236,7 +281,7 @@
reg = <0xfc308000 0x1000>;
reg-names = "cti-base";
- coresight-id = <15>;
+ coresight-id = <19>;
coresight-name = "coresight-cti0";
coresight-nr-inports = <0>;
};
@@ -246,7 +291,7 @@
reg = <0xfc309000 0x1000>;
reg-names = "cti-base";
- coresight-id = <16>;
+ coresight-id = <20>;
coresight-name = "coresight-cti1";
coresight-nr-inports = <0>;
};
@@ -256,7 +301,7 @@
reg = <0xfc30a000 0x1000>;
reg-names = "cti-base";
- coresight-id = <17>;
+ coresight-id = <21>;
coresight-name = "coresight-cti2";
coresight-nr-inports = <0>;
};
@@ -266,7 +311,7 @@
reg = <0xfc30b000 0x1000>;
reg-names = "cti-base";
- coresight-id = <18>;
+ coresight-id = <22>;
coresight-name = "coresight-cti3";
coresight-nr-inports = <0>;
};
@@ -276,7 +321,7 @@
reg = <0xfc30c000 0x1000>;
reg-names = "cti-base";
- coresight-id = <19>;
+ coresight-id = <23>;
coresight-name = "coresight-cti4";
coresight-nr-inports = <0>;
};
@@ -286,7 +331,7 @@
reg = <0xfc30d000 0x1000>;
reg-names = "cti-base";
- coresight-id = <20>;
+ coresight-id = <24>;
coresight-name = "coresight-cti5";
coresight-nr-inports = <0>;
};
@@ -296,7 +341,7 @@
reg = <0xfc30e000 0x1000>;
reg-names = "cti-base";
- coresight-id = <21>;
+ coresight-id = <25>;
coresight-name = "coresight-cti6";
coresight-nr-inports = <0>;
};
@@ -306,7 +351,7 @@
reg = <0xfc30f000 0x1000>;
reg-names = "cti-base";
- coresight-id = <22>;
+ coresight-id = <26>;
coresight-name = "coresight-cti7";
coresight-nr-inports = <0>;
};
@@ -316,7 +361,7 @@
reg = <0xfc310000 0x1000>;
reg-names = "cti-base";
- coresight-id = <23>;
+ coresight-id = <27>;
coresight-name = "coresight-cti8";
coresight-nr-inports = <0>;
};
@@ -326,7 +371,7 @@
reg = <0xfc340000 0x1000>;
reg-names = "cti-base";
- coresight-id = <24>;
+ coresight-id = <28>;
coresight-name = "coresight-cti-l2";
coresight-nr-inports = <0>;
};
@@ -336,7 +381,7 @@
reg = <0xfc341000 0x1000>;
reg-names = "cti-base";
- coresight-id = <25>;
+ coresight-id = <29>;
coresight-name = "coresight-cti-cpu0";
coresight-nr-inports = <0>;
};
@@ -346,7 +391,7 @@
reg = <0xfc342000 0x1000>;
reg-names = "cti-base";
- coresight-id = <26>;
+ coresight-id = <30>;
coresight-name = "coresight-cti-cpu1";
coresight-nr-inports = <0>;
};
@@ -356,7 +401,7 @@
reg = <0xfc343000 0x1000>;
reg-names = "cti-base";
- coresight-id = <27>;
+ coresight-id = <31>;
coresight-name = "coresight-cti-cpu2";
coresight-nr-inports = <0>;
};
@@ -366,11 +411,61 @@
reg = <0xfc344000 0x1000>;
reg-names = "cti-base";
- coresight-id = <28>;
+ coresight-id = <32>;
coresight-name = "coresight-cti-cpu3";
coresight-nr-inports = <0>;
};
+ cti_video_cpu0: cti@fc348000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc348000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <33>;
+ coresight-name = "coresight-cti-video-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_wcn_cpu0: cti@fc34d000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc34d000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <34>;
+ coresight-name = "coresight-cti-wcn-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_modem_cpu0: cti@fc350000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc350000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <35>;
+ coresight-name = "coresight-cti-modem-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_audio_cpu0: cti@fc354000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc354000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <36>;
+ coresight-name = "coresight-cti-audio-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_rpm_cpu0: cti@fc358000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc358000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <37>;
+ coresight-name = "coresight-cti-rpm-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
hwevent: hwevent@fdf30018 {
compatible = "qcom,coresight-hwevent";
reg = <0xfdf30018 0x80>,
@@ -379,7 +474,7 @@
<0xfc401600 0x80>;
reg-names = "mmss-mux", "apcs-mux", "ppss-mux", "gcc-mux";
- coresight-id = <29>;
+ coresight-id = <38>;
coresight-name = "coresight-hwevent";
coresight-nr-inports = <0>;
@@ -391,7 +486,7 @@
reg = <0xfc4be024 0x8>;
reg-names = "fuse-base";
- coresight-id = <30>;
+ coresight-id = <39>;
coresight-name = "coresight-fuse";
coresight-nr-inports = <0>;
};
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index c112bea..d0ca01d 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -30,6 +30,7 @@
qcom,mdss_mdp@fd900000 {
qcom,mdss-pref-prim-intf = "dsi";
+ batfet-supply = <&pm8941_chg_batif>;
};
qcom,hdmi_tx@fd922100 {
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 67e1802..16672fd 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -26,6 +26,8 @@
qcom,mdss_mdp@fd900000 {
qcom,mdss-pref-prim-intf = "edp";
+ qcom,panel-lpg-channel = <7>; /* LPG Channel 8 */
+ qcom,panel-pwm-period = <53>;
};
i2c@f9967000 {
diff --git a/arch/arm/boot/dts/msm8974-mdss-panels.dtsi b/arch/arm/boot/dts/msm8974-mdss-panels.dtsi
index 00fc779..d405bf8 100644
--- a/arch/arm/boot/dts/msm8974-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss-panels.dtsi
@@ -14,3 +14,4 @@
/include/ "dsi-panel-toshiba-720p-video.dtsi"
/include/ "dsi-panel-sharp-qhd-video.dtsi"
/include/ "dsi-panel-generic-720p-cmd.dtsi"
+/include/ "dsi-panel-jdi-1080p-video.dtsi"
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index 7181db2..c866de7 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -90,7 +90,6 @@
qcom,mdss-mdp = <&mdss_mdp>;
qcom,platform-reset-gpio = <&pm8941_gpios 19 0>;
qcom,platform-enable-gpio = <&msmgpio 58 0>;
- qcom,platform-reset-sequence = <1 20 0 200 1 20 2>;
qcom,platform-te-gpio = <&msmgpio 12 0>;
qcom,platform-strength-ctrl = [ff 06];
qcom,platform-bist-ctrl = [00 00 b1 ff 00 00];
@@ -188,9 +187,6 @@
reg-names = "edp_base", "mmss_cc_base";
vdda-supply = <&pm8941_l12>;
gpio-panel-en = <&msmgpio 58 0>;
- gpio-panel-pwm = <&pm8941_gpios 36 0>;
- qcom,panel-lpg-channel = <7>; /* LPG Channel 8 */
- qcom,panel-pwm-period = <53>;
qcom,mdss-fb-map = <&mdss_fb0>;
gpio-panel-hpd = <&msmgpio 102 0>;
};
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index 7a81e64..f73bcdc 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -30,6 +30,7 @@
qcom,mdss_mdp@fd900000 {
qcom,mdss-pref-prim-intf = "dsi";
+ batfet-supply = <&pm8941_chg_batif>;
};
qcom,hdmi_tx@fd922100 {
@@ -374,6 +375,16 @@
qcom,otg-capability;
};
+/ {
+ mtp_batterydata: qcom,battery-data {
+ qcom,rpull-up-kohm = <100>;
+ qcom,vref-batt-therm = <1800000>;
+
+ /include/ "batterydata-palladium.dtsi"
+ /include/ "batterydata-mtp-3000mah.dtsi"
+ };
+};
+
&pm8941_bms {
qcom,enable-fcc-learning;
qcom,min-fcc-learning-soc = <20>;
@@ -381,11 +392,13 @@
qcom,min-fcc-learning-samples = <5>;
qcom,fcc-resolution = <10>;
status = "ok";
+ qcom,battery-data = <&mtp_batterydata>;
};
&pm8941_chg {
status = "ok";
qcom,charging-disabled;
+ qcom,battery-data = <&mtp_batterydata>;
qcom,chgr@1000 {
status = "ok";
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index a88a709..344c26f 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -560,6 +560,10 @@
regulator-name = "8941_smbb_boost";
};
+&pm8941_chg_batif {
+ regulator-name = "batfet";
+};
+
&pm8941_chg_otg {
regulator-name = "8941_smbb_otg";
};
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index f2f73e9..55e18f0 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -140,24 +140,24 @@
<0x42 0x2>,
<0x120 0x3>;
qcom,vidc-iommu-domains {
- qcom,domain-ns {
- qcom,vidc-domain-phandle = <&venus_domain_ns>;
- qcom,vidc-partition-buffer-types = <0x1ff>,
- <0x200>;
- };
- qcom,domain-sec-bs {
- qcom,vidc-domain-phandle = <&venus_domain_sec_bitstream>;
- qcom,vidc-partition-buffer-types = <0x91>;
- };
- qcom,domain-sec-px {
- qcom,vidc-domain-phandle = <&venus_domain_sec_pixel>;
- qcom,vidc-partition-buffer-types = <0x42>;
- };
- qcom,domain-sec-np {
- qcom,vidc-domain-phandle = <&venus_domain_sec_non_pixel>;
- qcom,vidc-partition-buffer-types = <0x120>;
- };
- };
+ qcom,domain-ns {
+ qcom,vidc-domain-phandle = <&venus_domain_ns>;
+ qcom,vidc-partition-buffer-types = <0x7ff>,
+ <0x800>;
+ };
+ qcom,domain-sec-bs {
+ qcom,vidc-domain-phandle = <&venus_domain_sec_bitstream>;
+ qcom,vidc-partition-buffer-types = <0x241>;
+ };
+ qcom,domain-sec-px {
+ qcom,vidc-domain-phandle = <&venus_domain_sec_pixel>;
+ qcom,vidc-partition-buffer-types = <0x106>;
+ };
+ qcom,domain-sec-np {
+ qcom,vidc-domain-phandle = <&venus_domain_sec_non_pixel>;
+ qcom,vidc-partition-buffer-types = <0x480>;
+ };
+ };
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index cc00ce2..8079324 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -659,7 +659,6 @@
qcom,msm-bus,name = "tsif";
qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,active-only = <0>;
qcom,msm-bus,num-paths = <1>;
qcom,msm-bus,vectors-KBps =
<82 512 0 0>, /* No vote */
@@ -915,7 +914,7 @@
qcom,misc-ref = <&pm8941_misc>;
dwc_usb3-adc_tm = <&pm8941_adc_tm>;
qcom,dwc-usb3-msm-tx-fifo-size = <29696>;
- qcom,dwc-usb3-msm-qdss-tx-fifo-size = <16384>;
+ qcom,dwc-usb3-msm-qdss-tx-fifo-size = <8192>;
qcom,msm-bus,name = "usb3";
qcom,msm-bus,num-cases = <2>;
@@ -1485,7 +1484,7 @@
qcom,src-bam-pipe-index = <0>;
qcom,dst-bam-physical-address = <0xf9304000>;
qcom,dst-bam-pipe-index = <2>;
- qcom,data-fifo-offset = <0xf2000>;
+ qcom,data-fifo-offset = <0xf0000>;
qcom,data-fifo-size = <0x1800>;
qcom,descriptor-fifo-offset = <0xf4000>;
qcom,descriptor-fifo-size = <0x1400>;
diff --git a/arch/arm/boot/dts/msm8974pro-ab-cdp.dts b/arch/arm/boot/dts/msm8974pro-ab-pm8941-cdp.dts
similarity index 63%
rename from arch/arm/boot/dts/msm8974pro-ab-cdp.dts
rename to arch/arm/boot/dts/msm8974pro-ab-pm8941-cdp.dts
index fae72fa..b6a6fcb 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-cdp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab-pm8941-cdp.dts
@@ -12,21 +12,11 @@
/dts-v1/;
-/include/ "msm8974pro-ab.dtsi"
+/include/ "msm8974pro-ab-pm8941.dtsi"
/include/ "msm8974-cdp.dtsi"
/ {
- model = "Qualcomm MSM 8974Pro CDP";
+ model = "Qualcomm MSM 8974Pro-AA/AB CDP";
compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
- qcom,msm-id = <209 1 0x10000>,
- <211 1 0x10000>,
- <212 1 0x10000>,
- <214 1 0x10000>,
- <215 1 0x10000>,
- <217 1 0x10000>,
- <218 1 0x10000>,
- <194 1 0x10000>, /* 8974Pro-AC IDs */
- <210 1 0x10000>,
- <213 1 0x10000>,
- <216 1 0x10000>;
+ qcom,board-id = <1 0>;
};
diff --git a/arch/arm/boot/dts/msm8974pro-ab-fluid.dts b/arch/arm/boot/dts/msm8974pro-ab-pm8941-fluid.dts
similarity index 71%
rename from arch/arm/boot/dts/msm8974pro-ab-fluid.dts
rename to arch/arm/boot/dts/msm8974pro-ab-pm8941-fluid.dts
index 9a31834..be298d1 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-fluid.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab-pm8941-fluid.dts
@@ -12,17 +12,11 @@
/dts-v1/;
-/include/ "msm8974pro-ab.dtsi"
+/include/ "msm8974pro-ab-pm8941.dtsi"
/include/ "msm8974-fluid.dtsi"
/ {
- model = "Qualcomm MSM 8974Pro FLUID";
+ model = "Qualcomm MSM 8974Pro-AA/AB FLUID";
compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
- qcom,msm-id = <209 3 0x10000>,
- <211 3 0x10000>,
- <212 3 0x10000>,
- <214 3 0x10000>,
- <215 3 0x10000>,
- <217 3 0x10000>,
- <218 3 0x10000>;
+ qcom,board-id = <3 0>;
};
diff --git a/arch/arm/boot/dts/msm8974pro-ab-liquid.dts b/arch/arm/boot/dts/msm8974pro-ab-pm8941-liquid.dts
similarity index 71%
rename from arch/arm/boot/dts/msm8974pro-ab-liquid.dts
rename to arch/arm/boot/dts/msm8974pro-ab-pm8941-liquid.dts
index 0ec9d8a..49c3df0 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-liquid.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab-pm8941-liquid.dts
@@ -12,17 +12,11 @@
/dts-v1/;
-/include/ "msm8974pro-ab.dtsi"
+/include/ "msm8974pro-ab-pm8941.dtsi"
/include/ "msm8974-liquid.dtsi"
/ {
- model = "Qualcomm MSM 8974Pro LIQUID";
+ model = "Qualcomm MSM 8974Pro-AA/AB LIQUID";
compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
- qcom,msm-id = <209 9 0x10000>,
- <211 9 0x10000>,
- <212 9 0x10000>,
- <214 9 0x10000>,
- <215 9 0x10000>,
- <217 9 0x10000>,
- <218 9 0x10000>;
+ qcom,board-id = <9 0>;
};
diff --git a/arch/arm/boot/dts/msm8974pro-ab-mtp.dts b/arch/arm/boot/dts/msm8974pro-ab-pm8941-mtp.dts
similarity index 71%
rename from arch/arm/boot/dts/msm8974pro-ab-mtp.dts
rename to arch/arm/boot/dts/msm8974pro-ab-pm8941-mtp.dts
index 002baf7..fa313bf 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-mtp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab-pm8941-mtp.dts
@@ -12,17 +12,15 @@
/dts-v1/;
-/include/ "msm8974pro-ab.dtsi"
+/include/ "msm8974pro-ab-pm8941.dtsi"
/include/ "msm8974-mtp.dtsi"
/ {
- model = "Qualcomm MSM 8974Pro MTP";
+ model = "Qualcomm MSM 8974Pro-AA/AB MTP";
compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
- qcom,msm-id = <209 8 0x10000>,
- <211 8 0x10000>,
- <212 8 0x10000>,
- <214 8 0x10000>,
- <215 8 0x10000>,
- <217 8 0x10000>,
- <218 8 0x10000>;
+ qcom,board-id = <8 0>;
+};
+
+&sdhc_1 {
+ qcom,pad-drv-on = <0x4 0x4 0x4>; /* 10mA, 10mA, 10mA */
};
diff --git a/arch/arm/boot/dts/msm8974pro-ab-mtp.dts b/arch/arm/boot/dts/msm8974pro-ab-pm8941.dtsi
similarity index 60%
copy from arch/arm/boot/dts/msm8974pro-ab-mtp.dts
copy to arch/arm/boot/dts/msm8974pro-ab-pm8941.dtsi
index 002baf7..a44bc56 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-mtp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ab-pm8941.dtsi
@@ -10,19 +10,15 @@
* GNU General Public License for more details.
*/
-/dts-v1/;
-
-/include/ "msm8974pro-ab.dtsi"
-/include/ "msm8974-mtp.dtsi"
+/include/ "msm8974pro-pm8941.dtsi"
/ {
- model = "Qualcomm MSM 8974Pro MTP";
- compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
- qcom,msm-id = <209 8 0x10000>,
- <211 8 0x10000>,
- <212 8 0x10000>,
- <214 8 0x10000>,
- <215 8 0x10000>,
- <217 8 0x10000>,
- <218 8 0x10000>;
+ qcom,msm-id = <208 0x10000>,
+ <209 0x10000>,
+ <211 0x10000>,
+ <212 0x10000>,
+ <214 0x10000>,
+ <215 0x10000>,
+ <217 0x10000>,
+ <218 0x10000>;
};
diff --git a/arch/arm/boot/dts/msm8974pro-ab-cdp.dts b/arch/arm/boot/dts/msm8974pro-ac-pm8941-cdp.dts
similarity index 63%
copy from arch/arm/boot/dts/msm8974pro-ab-cdp.dts
copy to arch/arm/boot/dts/msm8974pro-ac-pm8941-cdp.dts
index fae72fa..3e0feda 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-cdp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ac-pm8941-cdp.dts
@@ -12,21 +12,11 @@
/dts-v1/;
-/include/ "msm8974pro-ab.dtsi"
+/include/ "msm8974pro-ac-pm8941.dtsi"
/include/ "msm8974-cdp.dtsi"
/ {
- model = "Qualcomm MSM 8974Pro CDP";
+ model = "Qualcomm MSM 8974Pro-AC CDP";
compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
- qcom,msm-id = <209 1 0x10000>,
- <211 1 0x10000>,
- <212 1 0x10000>,
- <214 1 0x10000>,
- <215 1 0x10000>,
- <217 1 0x10000>,
- <218 1 0x10000>,
- <194 1 0x10000>, /* 8974Pro-AC IDs */
- <210 1 0x10000>,
- <213 1 0x10000>,
- <216 1 0x10000>;
+ qcom,board-id = <1 0>;
};
diff --git a/arch/arm/boot/dts/msm8974pro-ab-liquid.dts b/arch/arm/boot/dts/msm8974pro-ac-pm8941-liquid.dts
similarity index 71%
copy from arch/arm/boot/dts/msm8974pro-ab-liquid.dts
copy to arch/arm/boot/dts/msm8974pro-ac-pm8941-liquid.dts
index 0ec9d8a..7b88abe 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-liquid.dts
+++ b/arch/arm/boot/dts/msm8974pro-ac-pm8941-liquid.dts
@@ -12,17 +12,11 @@
/dts-v1/;
-/include/ "msm8974pro-ab.dtsi"
+/include/ "msm8974pro-ac-pm8941.dtsi"
/include/ "msm8974-liquid.dtsi"
/ {
- model = "Qualcomm MSM 8974Pro LIQUID";
+ model = "Qualcomm MSM 8974Pro-AC LIQUID";
compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
- qcom,msm-id = <209 9 0x10000>,
- <211 9 0x10000>,
- <212 9 0x10000>,
- <214 9 0x10000>,
- <215 9 0x10000>,
- <217 9 0x10000>,
- <218 9 0x10000>;
+ qcom,board-id = <9 0>;
};
diff --git a/arch/arm/boot/dts/msm8974pro-ac-pm8941-mtp.dts b/arch/arm/boot/dts/msm8974pro-ac-pm8941-mtp.dts
new file mode 100644
index 0000000..f79d361
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-ac-pm8941-mtp.dts
@@ -0,0 +1,30 @@
+/* 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/ "msm8974pro-ac-pm8941.dtsi"
+/include/ "msm8974-mtp.dtsi"
+
+/ {
+ model = "Qualcomm MSM 8974Pro-AC MTP";
+ compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
+ qcom,board-id = <8 0>;
+};
+
+&sdhc_1 {
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 192000000 384000000>;
+ qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v";
+
+ qcom,pad-pull-on = <0x0 0x3 0x3 0x1>; /* no-pull, pull-up, pull-up, pull-down */
+ qcom,pad-pull-off = <0x0 0x3 0x3 0x1>; /* no-pull, pull-up, pull-up, pull-down */
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi b/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi
index cc4b6ed..cdcfecb 100644
--- a/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ac-pm8941.dtsi
@@ -10,243 +10,15 @@
* GNU General Public License for more details.
*/
-/include/ "msm8974pro-ac.dtsi"
-&spmi_bus {
- pm8941_lsid0: qcom,pm8941@2 {
- reg = <0x2>;
- };
- pm8941_lsid1: qcom,pm8941@3 {
- reg = <0x3>;
- };
-};
-/include/ "msm-pm8941.dtsi"
+/include/ "msm8974pro-pm8941.dtsi"
-&pm8941_lsid0 {
- qcom,power-on@800 {
- status = "disabled";
- };
-
- clkdiv@5b00 {
- status = "disabled";
- };
-
- clkdiv@5c00 {
- status = "disabled";
- };
-
- clkdiv@5d00 {
- status = "disabled";
- };
-
- qcom,pm8941_rtc {
- status = "disabled";
- };
-
- gpios {
- status = "disabled";
- };
-
- mpps {
- status = "disabled";
- };
+/ {
+ qcom,msm-id = <194 0x10000>,
+ <210 0x10000>,
+ <213 0x10000>,
+ <216 0x10000>;
};
-&pm8941_lsid1 {
- pm8941_boost: regulator@a000 {
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- qcom,enable-time = <500>;
- status = "okay";
- };
-
- pm8941_mvs1: regulator@8300 {
- parent-supply = <&pm8941_chg_otg>;
- qcom,enable-time = <1000>;
- qcom,pull-down-enable = <1>;
- interrupts = <0x3 0x83 0x2>;
- interrupt-names = "ocp";
- qcom,ocp-enable = <1>;
- qcom,ocp-max-retries = <10>;
- qcom,ocp-retry-delay = <30>;
- qcom,soft-start-enable = <1>;
- qcom,vs-soft-start-strength = <0>;
- qcom,hpm-enable = <1>;
- qcom,auto-mode-enable = <0>;
- status = "okay";
- };
-};
-
-&pma8084_mvs1 {
- parent-supply = <&pm8941_boost>;
-};
-
-&pm8941_chg {
- otg-parent-supply = <&pm8941_boost>;
-};
-
-&pm8941_chg_boost {
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- regulator-name = "8941_smbb_boost";
-};
-
-&pm8941_chg_otg {
- regulator-name = "8941_smbb_otg";
-};
-
-&usb3 {
- vbus_dwc3-supply = <&pm8941_mvs1>;
- qcom,misc-ref = <&pm8941_misc>;
- dwc_usb3-adc_tm = <&pm8941_adc_tm>;
- interrupt-map-mask = <0x0 0xffffffff>;
- interrupt-map = <0x0 0 &intc 0 133 0
- 0x0 1 &spmi_bus 0x0 0x2 0x9 0x0>;
- interrupt-names = "hs_phy_irq", "pmic_id_irq";
-};
-
-/* Correct PM8941 local slave ID 0 to use global SID 4 for all interrupts. */
-&pm8941_lsid0 {
- qcom,temp-alarm@2400 {
- interrupts = <0x2 0x24 0x0>;
- };
-
- qcom,power-on@800 {
- interrupts = <0x2 0x8 0x0>,
- <0x2 0x8 0x1>,
- <0x2 0x8 0x4>,
- <0x2 0x8 0x5>;
- interrupt-names = "kpdpwr", "resin",
- "resin-bark", "kpdpwr-resin-bark";
- };
-
- qcom,bsi@1b00 {
- interrupts = <0x2 0x1b 0x0>,
- <0x2 0x1b 0x1>,
- <0x2 0x1b 0x2>,
- <0x2 0x12 0x0>;
- interrupt-names = "err",
- "rx",
- "tx",
- "batt-present";
- };
-
- qcom,bms {
- qcom,bms-bms@4000 {
- interrupts = <0x2 0x40 0x0>,
- <0x2 0x40 0x1>,
- <0x2 0x40 0x2>,
- <0x2 0x40 0x3>,
- <0x2 0x40 0x4>,
- <0x2 0x40 0x5>,
- <0x2 0x40 0x6>,
- <0x2 0x40 0x7>;
- interrupt-names = "cc_thr",
- "ocv_for_r",
- "good_ocv",
- "charge_begin",
- "ocv_thr",
- "sw_cc_thr",
- "vsense_avg",
- "vsense_for_r";
- };
- };
-
- qcom,charger {
- qcom,chgr@1000 {
- interrupts = <0x2 0x10 0x0>,
- <0x2 0x10 0x1>,
- <0x2 0x10 0x2>,
- <0x2 0x10 0x3>,
- <0x2 0x10 0x4>,
- <0x2 0x10 0x5>,
- <0x2 0x10 0x6>,
- <0x2 0x10 0x7>;
- interrupt-names = "vbat-det-lo",
- "vbat-det-hi",
- "chgwdog",
- "state-change",
- "trkl-chg-on",
- "fast-chg-on",
- "chg-failed",
- "chg-done";
- };
-
- qcom,buck@1100 {
- interrupts = <0x2 0x11 0x0>,
- <0x2 0x11 0x1>,
- <0x2 0x11 0x2>,
- <0x2 0x11 0x3>,
- <0x2 0x11 0x4>,
- <0x2 0x11 0x5>,
- <0x2 0x11 0x6>;
- interrupt-names = "vbat-ov",
- "vreg-ov",
- "overtemp",
- "vchg-loop",
- "ichg-loop",
- "ibat-loop",
- "vdd-loop";
- };
-
- qcom,bat-if@1200 {
- interrupts = <0x2 0x12 0x0>,
- <0x2 0x12 0x1>,
- <0x2 0x12 0x2>,
- <0x2 0x12 0x3>,
- <0x2 0x12 0x4>;
- interrupt-names = "batt-pres",
- "bat-temp-ok",
- "bat-fet-on",
- "vcp-on",
- "psi";
- };
-
- qcom,usb-chgpth@1300 {
- interrupts = <0x2 0x13 0x0>,
- <0x2 0x13 0x1>,
- <0x2 0x13 0x2>;
- interrupt-names = "coarse-det-usb",
- "usbin-valid",
- "chg-gone";
- };
-
- qcom,dc-chgpth@1400 {
- interrupts = <0x2 0x14 0x0>,
- <0x2 0x14 0x1>;
- interrupt-names = "coarse-det-dc",
- "dcin-valid";
- };
-
- qcom,boost@1500 {
- interrupts = <0x2 0x15 0x0>,
- <0x2 0x15 0x1>;
- interrupt-names = "boost-pwr-ok",
- "limit-error";
- };
- };
-
- qcom,pm8941_rtc {
- qcom,pm8941_rtc_alarm@6100 {
- interrupts = <0x2 0x61 0x1>;
- };
- };
-
- vadc@3100 {
- interrupts = <0x2 0x31 0x0>;
- interrupt-names = "eoc-int-en-set";
- };
-
- iadc@3600 {
- interrupts = <0x2 0x36 0x0>;
- interrupt-names = "eoc-int-en-set";
- };
-
- qcom,vadc@3400 {
- interrupts = <0x2 0x34 0x0>,
- <0x2 0x34 0x3>,
- <0x2 0x34 0x4>;
- interrupt-names = "eoc-int-en-set",
- "high-thr-en-set",
- "low-thr-en-set";
- };
+&sdhc_1 {
+ reg = <0xf9824900 0x1a0>, <0xf9824000 0x800>;
};
diff --git a/arch/arm/boot/dts/msm8974pro-ac-mtp.dts b/arch/arm/boot/dts/msm8974pro-ac-pma8084-pm8941-mtp.dts
similarity index 82%
rename from arch/arm/boot/dts/msm8974pro-ac-mtp.dts
rename to arch/arm/boot/dts/msm8974pro-ac-pma8084-pm8941-mtp.dts
index 237c9f9..8a4ad45 100644
--- a/arch/arm/boot/dts/msm8974pro-ac-mtp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ac-pma8084-pm8941-mtp.dts
@@ -12,16 +12,13 @@
/dts-v1/;
-/include/ "msm8974pro-ac-pm8941.dtsi"
-/include/ "msm8974pro-ac-mtp.dtsi"
+/include/ "msm8974pro-ac-pma8084-pm8941.dtsi"
+/include/ "msm8974pro-pma8084-mtp.dtsi"
/ {
- model = "Qualcomm MSM 8974Pro-AC MTP";
+ model = "Qualcomm MSM 8974Pro-AC + PMA8084 MTP";
compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
- qcom,msm-id = <194 8 0x10000>,
- <210 8 0x10000>,
- <213 8 0x10000>,
- <216 8 0x10000>;
+ qcom,board-id = <8 1>;
};
&pma8084_vadc {
@@ -123,12 +120,3 @@
qcom,thermal-node;
};
};
-
-&sdhc_1 {
- reg = <0xf9824900 0x1a0>, <0xf9824000 0x800>;
- qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 200000000 400000000>;
- qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v";
-
- qcom,pad-pull-on = <0x0 0x3 0x3 0x1>; /* no-pull, pull-up, pull-up, pull-down */
- qcom,pad-pull-off = <0x0 0x3 0x3 0x1>; /* no-pull, pull-up, pull-up, pull-down */
-};
diff --git a/arch/arm/boot/dts/msm8974pro-ac-pma8084-pm8941.dtsi b/arch/arm/boot/dts/msm8974pro-ac-pma8084-pm8941.dtsi
new file mode 100644
index 0000000..dc438bb
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974pro-ac-pma8084-pm8941.dtsi
@@ -0,0 +1,257 @@
+/* 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/ "msm8974pro-ac-pma8084.dtsi"
+&spmi_bus {
+ pm8941_lsid0: qcom,pm8941@2 {
+ reg = <0x2>;
+ };
+ pm8941_lsid1: qcom,pm8941@3 {
+ reg = <0x3>;
+ };
+};
+/include/ "msm-pm8941.dtsi"
+
+&pm8941_lsid0 {
+ qcom,power-on@800 {
+ status = "disabled";
+ };
+
+ clkdiv@5b00 {
+ status = "disabled";
+ };
+
+ clkdiv@5c00 {
+ status = "disabled";
+ };
+
+ clkdiv@5d00 {
+ status = "disabled";
+ };
+
+ qcom,pm8941_rtc {
+ status = "disabled";
+ };
+
+ gpios {
+ status = "disabled";
+ };
+
+ mpps {
+ status = "disabled";
+ };
+};
+
+&pm8941_lsid1 {
+ pm8941_boost: regulator@a000 {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ qcom,enable-time = <500>;
+ status = "okay";
+ };
+
+ pm8941_mvs1: regulator@8300 {
+ parent-supply = <&pm8941_chg_otg>;
+ qcom,enable-time = <1000>;
+ qcom,pull-down-enable = <1>;
+ interrupts = <0x3 0x83 0x2>;
+ interrupt-names = "ocp";
+ qcom,ocp-enable = <1>;
+ qcom,ocp-max-retries = <10>;
+ qcom,ocp-retry-delay = <30>;
+ qcom,soft-start-enable = <1>;
+ qcom,vs-soft-start-strength = <0>;
+ qcom,hpm-enable = <1>;
+ qcom,auto-mode-enable = <0>;
+ status = "okay";
+ };
+};
+
+&pma8084_mvs1 {
+ parent-supply = <&pm8941_boost>;
+};
+
+&pm8941_chg {
+ otg-parent-supply = <&pm8941_boost>;
+};
+
+&pm8941_chg_boost {
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-name = "8941_smbb_boost";
+};
+
+&pm8941_chg_batif {
+ regulator-name = "batfet";
+};
+
+&pm8941_chg_otg {
+ regulator-name = "8941_smbb_otg";
+};
+
+&usb3 {
+ vbus_dwc3-supply = <&pm8941_mvs1>;
+ qcom,misc-ref = <&pm8941_misc>;
+ dwc_usb3-adc_tm = <&pm8941_adc_tm>;
+ interrupt-map-mask = <0x0 0xffffffff>;
+ interrupt-map = <0x0 0 &intc 0 133 0
+ 0x0 1 &spmi_bus 0x0 0x2 0x9 0x0>;
+ interrupt-names = "hs_phy_irq", "pmic_id_irq";
+ qcom,dwc-ssphy-deemphasis-value = <26>;
+};
+
+/* Correct PM8941 local slave ID 0 to use global SID 4 for all interrupts. */
+&pm8941_lsid0 {
+ qcom,temp-alarm@2400 {
+ interrupts = <0x2 0x24 0x0>;
+ };
+
+ qcom,power-on@800 {
+ interrupts = <0x2 0x8 0x0>,
+ <0x2 0x8 0x1>,
+ <0x2 0x8 0x4>,
+ <0x2 0x8 0x5>;
+ interrupt-names = "kpdpwr", "resin",
+ "resin-bark", "kpdpwr-resin-bark";
+ };
+
+ qcom,bsi@1b00 {
+ interrupts = <0x2 0x1b 0x0>,
+ <0x2 0x1b 0x1>,
+ <0x2 0x1b 0x2>,
+ <0x2 0x12 0x0>;
+ interrupt-names = "err",
+ "rx",
+ "tx",
+ "batt-present";
+ };
+
+ qcom,bms {
+ qcom,bms-bms@4000 {
+ interrupts = <0x2 0x40 0x0>,
+ <0x2 0x40 0x1>,
+ <0x2 0x40 0x2>,
+ <0x2 0x40 0x3>,
+ <0x2 0x40 0x4>,
+ <0x2 0x40 0x5>,
+ <0x2 0x40 0x6>,
+ <0x2 0x40 0x7>;
+ interrupt-names = "cc_thr",
+ "ocv_for_r",
+ "good_ocv",
+ "charge_begin",
+ "ocv_thr",
+ "sw_cc_thr",
+ "vsense_avg",
+ "vsense_for_r";
+ };
+ };
+
+ qcom,charger {
+ qcom,chgr@1000 {
+ interrupts = <0x2 0x10 0x0>,
+ <0x2 0x10 0x1>,
+ <0x2 0x10 0x2>,
+ <0x2 0x10 0x3>,
+ <0x2 0x10 0x4>,
+ <0x2 0x10 0x5>,
+ <0x2 0x10 0x6>,
+ <0x2 0x10 0x7>;
+ interrupt-names = "vbat-det-lo",
+ "vbat-det-hi",
+ "chgwdog",
+ "state-change",
+ "trkl-chg-on",
+ "fast-chg-on",
+ "chg-failed",
+ "chg-done";
+ };
+
+ qcom,buck@1100 {
+ interrupts = <0x2 0x11 0x0>,
+ <0x2 0x11 0x1>,
+ <0x2 0x11 0x2>,
+ <0x2 0x11 0x3>,
+ <0x2 0x11 0x4>,
+ <0x2 0x11 0x5>,
+ <0x2 0x11 0x6>;
+ interrupt-names = "vbat-ov",
+ "vreg-ov",
+ "overtemp",
+ "vchg-loop",
+ "ichg-loop",
+ "ibat-loop",
+ "vdd-loop";
+ };
+
+ qcom,bat-if@1200 {
+ interrupts = <0x2 0x12 0x0>,
+ <0x2 0x12 0x1>,
+ <0x2 0x12 0x2>,
+ <0x2 0x12 0x3>,
+ <0x2 0x12 0x4>;
+ interrupt-names = "batt-pres",
+ "bat-temp-ok",
+ "bat-fet-on",
+ "vcp-on",
+ "psi";
+ };
+
+ qcom,usb-chgpth@1300 {
+ interrupts = <0x2 0x13 0x0>,
+ <0x2 0x13 0x1>,
+ <0x2 0x13 0x2>;
+ interrupt-names = "coarse-det-usb",
+ "usbin-valid",
+ "chg-gone";
+ };
+
+ qcom,dc-chgpth@1400 {
+ interrupts = <0x2 0x14 0x0>,
+ <0x2 0x14 0x1>;
+ interrupt-names = "coarse-det-dc",
+ "dcin-valid";
+ };
+
+ qcom,boost@1500 {
+ interrupts = <0x2 0x15 0x0>,
+ <0x2 0x15 0x1>;
+ interrupt-names = "boost-pwr-ok",
+ "limit-error";
+ };
+ };
+
+ qcom,pm8941_rtc {
+ qcom,pm8941_rtc_alarm@6100 {
+ interrupts = <0x2 0x61 0x1>;
+ };
+ };
+
+ vadc@3100 {
+ interrupts = <0x2 0x31 0x0>;
+ interrupt-names = "eoc-int-en-set";
+ };
+
+ iadc@3600 {
+ interrupts = <0x2 0x36 0x0>;
+ interrupt-names = "eoc-int-en-set";
+ };
+
+ qcom,vadc@3400 {
+ interrupts = <0x2 0x34 0x0>,
+ <0x2 0x34 0x3>,
+ <0x2 0x34 0x4>;
+ interrupt-names = "eoc-int-en-set",
+ "high-thr-en-set",
+ "low-thr-en-set";
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974pro-ab-mtp.dts b/arch/arm/boot/dts/msm8974pro-ac-pma8084.dtsi
similarity index 60%
copy from arch/arm/boot/dts/msm8974pro-ab-mtp.dts
copy to arch/arm/boot/dts/msm8974pro-ac-pma8084.dtsi
index 002baf7..4b7ed1d 100644
--- a/arch/arm/boot/dts/msm8974pro-ab-mtp.dts
+++ b/arch/arm/boot/dts/msm8974pro-ac-pma8084.dtsi
@@ -10,19 +10,15 @@
* GNU General Public License for more details.
*/
-/dts-v1/;
-
-/include/ "msm8974pro-ab.dtsi"
-/include/ "msm8974-mtp.dtsi"
+/include/ "msm8974pro-pma8084.dtsi"
/ {
- model = "Qualcomm MSM 8974Pro MTP";
- compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
- qcom,msm-id = <209 8 0x10000>,
- <211 8 0x10000>,
- <212 8 0x10000>,
- <214 8 0x10000>,
- <215 8 0x10000>,
- <217 8 0x10000>,
- <218 8 0x10000>;
+ qcom,msm-id = <194 0x10000>,
+ <210 0x10000>,
+ <213 0x10000>,
+ <216 0x10000>;
+};
+
+&sdhc_1 {
+ reg = <0xf9824900 0x1a0>, <0xf9824000 0x800>;
};
diff --git a/arch/arm/boot/dts/msm8974pro-ion.dtsi b/arch/arm/boot/dts/msm8974pro-ion.dtsi
index 7faee21..4c427bf 100644
--- a/arch/arm/boot/dts/msm8974pro-ion.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-ion.dtsi
@@ -17,7 +17,7 @@
compatible = "qcom,msm-ion-reserve";
reg = <23>;
qcom,heap-align = <0x1000>;
- qcom,memory-fixed = <0x05400000 0x2700000>;
+ qcom,memory-fixed = <0x05a00000 0x2100000>;
};
qcom,ion-heap@26 { /* MODEM HEAP */
diff --git a/arch/arm/boot/dts/msm8974pro-ab.dtsi b/arch/arm/boot/dts/msm8974pro-pm8941.dtsi
similarity index 84%
rename from arch/arm/boot/dts/msm8974pro-ab.dtsi
rename to arch/arm/boot/dts/msm8974pro-pm8941.dtsi
index 5809069..0f37584 100644
--- a/arch/arm/boot/dts/msm8974pro-ab.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pm8941.dtsi
@@ -36,6 +36,22 @@
qcom,use-phase-switching;
};
+&krait0_vreg {
+ regulator-max-microvolt = <1120000>;
+};
+
+&krait1_vreg {
+ regulator-max-microvolt = <1120000>;
+};
+
+&krait2_vreg {
+ regulator-max-microvolt = <1120000>;
+};
+
+&krait3_vreg {
+ regulator-max-microvolt = <1120000>;
+};
+
&tspp {
vdd_cx-supply = <&pm8841_s2_corner>;
};
diff --git a/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi b/arch/arm/boot/dts/msm8974pro-pma8084-mtp.dtsi
similarity index 95%
rename from arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi
rename to arch/arm/boot/dts/msm8974pro-pma8084-mtp.dtsi
index cdb4ed0..d5c1143 100644
--- a/arch/arm/boot/dts/msm8974pro-ac-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pma8084-mtp.dtsi
@@ -91,6 +91,12 @@
&sdhc_1 {
vdd-supply = <&pma8084_l20>;
vdd-io-supply = <&pma8084_s4>;
+
+ qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 192000000 384000000>;
+ qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v";
+
+ qcom,pad-pull-on = <0x0 0x3 0x3 0x1>; /* no-pull, pull-up, pull-up, pull-down */
+ qcom,pad-pull-off = <0x0 0x3 0x3 0x1>; /* no-pull, pull-up, pull-up, pull-down */
};
&sdhc_2 {
diff --git a/arch/arm/boot/dts/msm8974pro-ac-regulator.dtsi b/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi
similarity index 98%
rename from arch/arm/boot/dts/msm8974pro-ac-regulator.dtsi
rename to arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi
index e0473b7..df00f8a 100644
--- a/arch/arm/boot/dts/msm8974pro-ac-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pma8084-regulator.dtsi
@@ -480,6 +480,7 @@
#size-cells = <1>;
ranges;
qcom,pfm-threshold = <76>;
+ qcom,use-phase-scaling-factor;
krait0_vreg: regulator@f9088000 {
compatible = "qcom,krait-regulator";
@@ -488,7 +489,7 @@
<0xf908a800 0x1000>; /* APCS_ALIAS0_KPSS_MDD */
reg-names = "acs", "mdd";
regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1100000>;
+ regulator-max-microvolt = <1120000>;
qcom,headroom-voltage = <150000>;
qcom,retention-voltage = <675000>;
qcom,ldo-default-voltage = <750000>;
@@ -504,7 +505,7 @@
<0xf909a800 0x1000>; /* APCS_ALIAS1_KPSS_MDD */
reg-names = "acs", "mdd";
regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1100000>;
+ regulator-max-microvolt = <1120000>;
qcom,headroom-voltage = <150000>;
qcom,retention-voltage = <675000>;
qcom,ldo-default-voltage = <750000>;
@@ -520,7 +521,7 @@
<0xf90aa800 0x1000>; /* APCS_ALIAS2_KPSS_MDD */
reg-names = "acs", "mdd";
regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1100000>;
+ regulator-max-microvolt = <1120000>;
qcom,headroom-voltage = <150000>;
qcom,retention-voltage = <675000>;
qcom,ldo-default-voltage = <750000>;
@@ -536,7 +537,7 @@
<0xf90ba800 0x1000>; /* APCS_ALIAS3_KPSS_MDD */
reg-names = "acs", "mdd";
regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1100000>;
+ regulator-max-microvolt = <1120000>;
qcom,headroom-voltage = <150000>;
qcom,retention-voltage = <675000>;
qcom,ldo-default-voltage = <750000>;
diff --git a/arch/arm/boot/dts/msm8974pro-ac.dtsi b/arch/arm/boot/dts/msm8974pro-pma8084.dtsi
similarity index 98%
rename from arch/arm/boot/dts/msm8974pro-ac.dtsi
rename to arch/arm/boot/dts/msm8974pro-pma8084.dtsi
index f8a371d..cd485c5 100644
--- a/arch/arm/boot/dts/msm8974pro-ac.dtsi
+++ b/arch/arm/boot/dts/msm8974pro-pma8084.dtsi
@@ -20,7 +20,7 @@
/include/ "msm-pma8084-rpm-regulator.dtsi"
/include/ "msm-pma8084.dtsi"
-/include/ "msm8974pro-ac-regulator.dtsi"
+/include/ "msm8974pro-pma8084-regulator.dtsi"
/*
* Override PM8841 and PM8941 resources with proper PMA8084 resources for
diff --git a/arch/arm/boot/dts/msm8974pro.dtsi b/arch/arm/boot/dts/msm8974pro.dtsi
index 86f0058..bd58653 100644
--- a/arch/arm/boot/dts/msm8974pro.dtsi
+++ b/arch/arm/boot/dts/msm8974pro.dtsi
@@ -46,6 +46,8 @@
/* Updated chip ID */
qcom,chipid = <0x03030002>;
+ qcom,initial-pwrlevel = <6>;
+
/* Updated bus bandwidth requirements */
qcom,msm-bus,vectors-KBps =
/* Off */
@@ -69,41 +71,69 @@
qcom,gpu-pwrlevel@0 {
reg = <0>;
- qcom,gpu-freq = <550000000>;
+ qcom,gpu-freq = <578000000>;
qcom,bus-freq = <5>;
qcom,io-fraction = <33>;
};
- qcom,gpu-pwrlevel@1 {
- reg = <1>;
- qcom,gpu-freq = <320000000>;
+ qcom,gpu-pwrlevel@1 {
+ reg = <1>;
+ qcom,gpu-freq = <462400000>;
+ qcom,bus-freq = <4>;
+ qcom,io-fraction = <33>;
+ };
+
+ qcom,gpu-pwrlevel@2 {
+ reg = <2>;
+ qcom,gpu-freq = <462400000>;
+ qcom,bus-freq = <3>;
+ qcom,io-fraction = <66>;
+ };
+
+ qcom,gpu-pwrlevel@3 {
+ reg = <3>;
+ qcom,gpu-freq = <389000000>;
+ qcom,bus-freq = <4>;
+ qcom,io-fraction = <66>;
+ };
+
+ qcom,gpu-pwrlevel@4 {
+ reg = <4>;
+ qcom,gpu-freq = <389000000>;
+ qcom,bus-freq = <3>;
+ qcom,io-fraction = <66>;
+ };
+
+ qcom,gpu-pwrlevel@5 {
+ reg = <5>;
+ qcom,gpu-freq = <330000000>;
qcom,bus-freq = <4>;
qcom,io-fraction = <66>;
};
- qcom,gpu-pwrlevel@2 {
- reg = <2>;
- qcom,gpu-freq = <320000000>;
+ qcom,gpu-pwrlevel@6 {
+ reg = <6>;
+ qcom,gpu-freq = <330000000>;
qcom,bus-freq = <3>;
qcom,io-fraction = <66>;
};
- qcom,gpu-pwrlevel@3 {
- reg = <3>;
+ qcom,gpu-pwrlevel@7 {
+ reg = <7>;
qcom,gpu-freq = <200000000>;
qcom,bus-freq = <2>;
qcom,io-fraction = <100>;
};
- qcom,gpu-pwrlevel@4 {
- reg = <4>;
+ qcom,gpu-pwrlevel@8 {
+ reg = <8>;
qcom,gpu-freq = <200000000>;
qcom,bus-freq = <1>;
qcom,io-fraction = <100>;
};
- qcom,gpu-pwrlevel@5 {
- reg = <5>;
+ qcom,gpu-pwrlevel@9 {
+ reg = <9>;
qcom,gpu-freq = <27000000>;
qcom,bus-freq = <0>;
qcom,io-fraction = <0>;
@@ -184,24 +214,25 @@
qcom,vidc-iommu-domains {
qcom,domain-ns {
qcom,vidc-domain-phandle = <&venus_domain_ns>;
- qcom,vidc-partition-buffer-types = <0x1ff>,
- <0x200>;
+ qcom,vidc-partition-buffer-types = <0x7ff>,
+ <0x800>;
};
qcom,domain-sec-bs {
qcom,vidc-domain-phandle = <&venus_domain_sec_bitstream>;
- qcom,vidc-partition-buffer-types = <0x91>;
+ qcom,vidc-partition-buffer-types = <0x241>;
};
qcom,domain-sec-px {
qcom,vidc-domain-phandle = <&venus_domain_sec_pixel>;
- qcom,vidc-partition-buffer-types = <0x42>;
+ qcom,vidc-partition-buffer-types = <0x106>;
};
qcom,domain-sec-np {
qcom,vidc-domain-phandle = <&venus_domain_sec_non_pixel>;
- qcom,vidc-partition-buffer-types = <0x120>;
+ qcom,vidc-partition-buffer-types = <0x480>;
};
};
};
&memory_hole {
- qcom,memblock-remove = <0x05400000 0xab00000>; /* Address and size of the hole */
+ qcom,memblock-remove = <0x05a00000 0x7800000
+ 0x0fa00000 0x500000>; /* Address and size of the hole */
};
diff --git a/arch/arm/boot/dts/msm9625-coresight.dtsi b/arch/arm/boot/dts/msm9625-coresight.dtsi
index 4880f96..05d5238 100644
--- a/arch/arm/boot/dts/msm9625-coresight.dtsi
+++ b/arch/arm/boot/dts/msm9625-coresight.dtsi
@@ -135,12 +135,45 @@
qcom,round-robin;
};
+ audio_etm0 {
+ compatible = "qcom,coresight-audio-etm";
+
+ coresight-id = <9>;
+ coresight-name = "coresight-audio-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <2>;
+ };
+
+ modem_etm0 {
+ compatible = "qcom,coresight-modem-etm";
+
+ coresight-id = <10>;
+ coresight-name = "coresight-modem-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <1>;
+ };
+
+ rpm_etm0 {
+ compatible = "qcom,coresight-rpm-etm";
+
+ coresight-id = <11>;
+ coresight-name = "coresight-rpm-etm0";
+ coresight-nr-inports = <0>;
+ coresight-outports = <0>;
+ coresight-child-list = <&funnel_in0>;
+ coresight-child-ports = <0>;
+ };
+
csr: csr@fc302000 {
compatible = "qcom,coresight-csr";
reg = <0xfc302000 0x1000>;
reg-names = "csr-base";
- coresight-id = <9>;
+ coresight-id = <12>;
coresight-name = "coresight-csr";
coresight-nr-inports = <0>;
@@ -152,7 +185,7 @@
reg = <0xfc308000 0x1000>;
reg-names = "cti-base";
- coresight-id = <10>;
+ coresight-id = <13>;
coresight-name = "coresight-cti0";
coresight-nr-inports = <0>;
};
@@ -162,7 +195,7 @@
reg = <0xfc309000 0x1000>;
reg-names = "cti-base";
- coresight-id = <11>;
+ coresight-id = <14>;
coresight-name = "coresight-cti1";
coresight-nr-inports = <0>;
};
@@ -172,7 +205,7 @@
reg = <0xfc30a000 0x1000>;
reg-names = "cti-base";
- coresight-id = <12>;
+ coresight-id = <15>;
coresight-name = "coresight-cti2";
coresight-nr-inports = <0>;
};
@@ -182,7 +215,7 @@
reg = <0xfc30b000 0x1000>;
reg-names = "cti-base";
- coresight-id = <13>;
+ coresight-id = <16>;
coresight-name = "coresight-cti3";
coresight-nr-inports = <0>;
};
@@ -192,7 +225,7 @@
reg = <0xfc30c000 0x1000>;
reg-names = "cti-base";
- coresight-id = <14>;
+ coresight-id = <17>;
coresight-name = "coresight-cti4";
coresight-nr-inports = <0>;
};
@@ -202,7 +235,7 @@
reg = <0xfc30d000 0x1000>;
reg-names = "cti-base";
- coresight-id = <15>;
+ coresight-id = <18>;
coresight-name = "coresight-cti5";
coresight-nr-inports = <0>;
};
@@ -212,7 +245,7 @@
reg = <0xfc30e000 0x1000>;
reg-names = "cti-base";
- coresight-id = <16>;
+ coresight-id = <19>;
coresight-name = "coresight-cti6";
coresight-nr-inports = <0>;
};
@@ -222,7 +255,7 @@
reg = <0xfc30f000 0x1000>;
reg-names = "cti-base";
- coresight-id = <17>;
+ coresight-id = <20>;
coresight-name = "coresight-cti7";
coresight-nr-inports = <0>;
};
@@ -232,18 +265,48 @@
reg = <0xfc310000 0x1000>;
reg-names = "cti-base";
- coresight-id = <18>;
+ coresight-id = <21>;
coresight-name = "coresight-cti8";
coresight-nr-inports = <0>;
};
- cti_cpu: cti@fc333000 {
+ cti_cpu0: cti@fc333000 {
compatible = "arm,coresight-cti";
reg = <0xfc333000 0x1000>;
reg-names = "cti-base";
- coresight-id = <19>;
- coresight-name = "coresight-cti-cpu";
+ coresight-id = <22>;
+ coresight-name = "coresight-cti-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_modem_cpu0: cti@fc350000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc350000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <23>;
+ coresight-name = "coresight-cti-modem-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_audio_cpu0: cti@fc354000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc354000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <24>;
+ coresight-name = "coresight-cti-audio-cpu0";
+ coresight-nr-inports = <0>;
+ };
+
+ cti_rpm_cpu0: cti@fc358000 {
+ compatible = "arm,coresight-cti";
+ reg = <0xfc358000 0x1000>;
+ reg-names = "cti-base";
+
+ coresight-id = <25>;
+ coresight-name = "coresight-cti-rpm-cpu0";
coresight-nr-inports = <0>;
};
@@ -254,7 +317,7 @@
<0xfc401600 0x80>;
reg-names = "apcs-mux", "ppss-mux", "gcc-mux";
- coresight-id = <20>;
+ coresight-id = <26>;
coresight-name = "coresight-hwevent";
coresight-nr-inports = <0>;
};
@@ -264,7 +327,7 @@
reg = <0xfc4be024 0x8>;
reg-names = "fuse-base";
- coresight-id = <21>;
+ coresight-id = <27>;
coresight-name = "coresight-fuse";
coresight-nr-inports = <0>;
};
diff --git a/arch/arm/configs/apq8084_defconfig b/arch/arm/configs/apq8084_defconfig
index 66d66fc..7c1af1a 100644
--- a/arch/arm/configs/apq8084_defconfig
+++ b/arch/arm/configs/apq8084_defconfig
@@ -268,6 +268,7 @@
CONFIG_GPIO_QPNP_PIN_DEBUG=y
CONFIG_POWER_SUPPLY=y
CONFIG_SMB350_CHARGER=y
+CONFIG_SMB349_USB_CHARGER=y
CONFIG_BATTERY_BQ28400=y
CONFIG_QPNP_CHARGER=y
CONFIG_BATTERY_BCL=y
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index f8369a9..03ed61f 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -234,7 +234,6 @@
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
@@ -350,6 +349,7 @@
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_EHSET=y
CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_MSM_HSIC=y
CONFIG_USB_ACM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_STORAGE_DATAFAB=y
@@ -387,6 +387,7 @@
CONFIG_MMC_MSM_SPS_SUPPORT=y
CONFIG_LEDS_QPNP=y
CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_GPIO=y
CONFIG_SWITCH=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_DRV_MSM is not set
@@ -448,3 +449,4 @@
CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
CONFIG_TOUCHSCREEN_GT9XX=y
CONFIG_GT9XX_TOUCHPANEL_DRIVER=y
+CONFIG_DEFAULT_ROW=y
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index 816b020..8d116f1 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -236,7 +236,6 @@
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
@@ -376,6 +375,7 @@
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_EHSET=y
CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_MSM_HSIC=y
CONFIG_USB_ACM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_STORAGE_DATAFAB=y
@@ -413,6 +413,7 @@
CONFIG_MMC_MSM_SPS_SUPPORT=y
CONFIG_LEDS_QPNP=y
CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_GPIO=y
CONFIG_SWITCH=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_DRV_MSM is not set
@@ -442,6 +443,10 @@
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
+CONFIG_CORESIGHT_AUDIO_ETM=y
+CONFIG_CORESIGHT_MODEM_ETM=y
+CONFIG_CORESIGHT_WCN_ETM=y
+CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_EVENT=m
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
@@ -499,3 +504,4 @@
CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
CONFIG_TOUCHSCREEN_GT9XX=y
CONFIG_GT9XX_TOUCHPANEL_DRIVER=y
+CONFIG_DEFAULT_ROW=y
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 1a197a3..20c6362 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -81,6 +81,7 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_COMPACTION=y
+CONFIG_CC_STACKPROTECTOR=y
CONFIG_CP_ACCESS=y
CONFIG_USE_OF=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
@@ -234,6 +235,8 @@
CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_TOUCHSCREEN_GT9XX=y
+CONFIG_GT9XX_TOUCHPANEL_DRIVER=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=m
@@ -284,6 +287,7 @@
CONFIG_HI256=y
CONFIG_OV12830=y
CONFIG_OV5648=y
+CONFIG_IMX134=y
CONFIG_MSM_CAMERA_SENSOR=y
# CONFIG_MSM_CPP is not set
CONFIG_MSM_EEPROM=y
@@ -411,3 +415,4 @@
CONFIG_SENSORS_MMA8X5X=y
CONFIG_LOGCAT_SIZE=64
CONFIG_SENSORS_CAPELLA_CM36283=y
+CONFIG_NFC_QNCI=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 8238414..0a7faae 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -82,6 +82,7 @@
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
CONFIG_COMPACTION=y
+CONFIG_CC_STACKPROTECTOR=y
CONFIG_CP_ACCESS=y
CONFIG_USE_OF=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
@@ -236,6 +237,8 @@
CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
+CONFIG_TOUCHSCREEN_GT9XX=y
+CONFIG_GT9XX_TOUCHPANEL_DRIVER=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=m
@@ -285,6 +288,7 @@
CONFIG_s5k4e1=y
CONFIG_HI256=y
CONFIG_OV12830=y
+CONFIG_IMX134=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_EEPROM=y
CONFIG_MSM_CCI=y
@@ -398,6 +402,10 @@
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
+CONFIG_CORESIGHT_AUDIO_ETM=y
+CONFIG_CORESIGHT_MODEM_ETM=y
+CONFIG_CORESIGHT_WCN_ETM=y
+CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_EVENT=m
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
@@ -442,6 +450,7 @@
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_ARC4=y
CONFIG_CRYPTO_TWOFISH=y
+CONFIG_NFC_QNCI=y
CONFIG_CRYPTO_DEV_QCRYPTO=m
CONFIG_CRYPTO_DEV_QCE=y
CONFIG_CRYPTO_DEV_QCEDEV=m
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 3224889..fb05a08 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -169,6 +169,7 @@
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
CONFIG_NETFILTER_XT_MATCH_HELPER=y
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
@@ -339,6 +340,7 @@
CONFIG_MT9M114=y
CONFIG_OV2720=y
CONFIG_IMX135=y
+CONFIG_IMX132=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_EEPROM=y
CONFIG_MSM_CPP=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index cd0e638..8f6f52f 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -175,6 +175,7 @@
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
CONFIG_NETFILTER_XT_MATCH_HELPER=y
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
@@ -321,6 +322,7 @@
CONFIG_GPIO_QPNP_PIN_DEBUG=y
CONFIG_POWER_SUPPLY=y
CONFIG_SMB350_CHARGER=y
+CONFIG_SMB349_USB_CHARGER=y
CONFIG_BATTERY_BQ28400=y
CONFIG_QPNP_CHARGER=y
CONFIG_BATTERY_BCL=y
@@ -346,6 +348,7 @@
CONFIG_MT9M114=y
CONFIG_OV2720=y
CONFIG_IMX135=y
+CONFIG_IMX132=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_EEPROM=y
CONFIG_MSM_CPP=y
@@ -472,6 +475,10 @@
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
CONFIG_CORESIGHT_ETM_PCSAVE_DEFAULT_ENABLE=y
+CONFIG_CORESIGHT_AUDIO_ETM=y
+CONFIG_CORESIGHT_MODEM_ETM=y
+CONFIG_CORESIGHT_WCN_ETM=y
+CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_EVENT=m
CONFIG_BIF=y
CONFIG_BIF_QPNP=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 3f34690..d6811df 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -295,6 +295,9 @@
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_HWEVENT=y
CONFIG_CORESIGHT_ETM=y
+CONFIG_CORESIGHT_AUDIO_ETM=y
+CONFIG_CORESIGHT_MODEM_ETM=y
+CONFIG_CORESIGHT_RPM_ETM=y
CONFIG_CORESIGHT_EVENT=m
CONFIG_EXT3_FS=y
CONFIG_VFAT_FS=y
diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index 38050b1..56211f2 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -130,4 +130,10 @@
extern unsigned long arch_randomize_brk(struct mm_struct *mm);
#define arch_randomize_brk arch_randomize_brk
+#ifdef CONFIG_MMU
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
+struct linux_binprm;
+int arch_setup_additional_pages(struct linux_binprm *, int);
+#endif
+
#endif
diff --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h
index febe495..15cb035 100644
--- a/arch/arm/include/asm/mach/irq.h
+++ b/arch/arm/include/asm/mach/irq.h
@@ -17,7 +17,7 @@
/*
* This is internal. Do not use it.
*/
-extern void init_FIQ(void);
+extern void init_FIQ(int);
extern int show_fiq_list(struct seq_file *, int);
#ifdef CONFIG_MULTI_IRQ_HANDLER
diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h
index b8e580a..cf0c81f 100644
--- a/arch/arm/include/asm/mmu.h
+++ b/arch/arm/include/asm/mmu.h
@@ -9,6 +9,7 @@
raw_spinlock_t id_lock;
#endif
unsigned int kvm_seq;
+ unsigned long sigpage;
} mm_context_t;
#ifdef CONFIG_CPU_HAS_ASID
diff --git a/arch/arm/include/asm/page.h b/arch/arm/include/asm/page.h
index afc1ca7..673205e 100644
--- a/arch/arm/include/asm/page.h
+++ b/arch/arm/include/asm/page.h
@@ -151,7 +151,9 @@
#define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
extern void copy_page(void *to, const void *from);
+#ifdef CONFIG_KUSER_HELPERS
#define __HAVE_ARCH_GATE_AREA 1
+#endif
#ifdef CONFIG_ARM_LPAE
#include <asm/pgtable-3level-types.h>
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index 07209d7..3a2cd22 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -30,6 +30,7 @@
#endif
extern unsigned int boot_reason;
+extern unsigned int cold_boot;
struct debug_info {
#ifdef CONFIG_HAVE_HW_BREAKPOINT
diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index 67d6443..2eb0c2c 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -58,7 +58,7 @@
struct cpu_context_save cpu_context; /* cpu context */
__u32 syscall; /* syscall number */
__u8 used_cp[16]; /* thread used copro */
- unsigned long tp_value;
+ unsigned long tp_value[2]; /* TLS registers */
struct crunch_state crunchstate;
union fp_state fpstate __attribute__((aligned(8)));
union vfp_state vfpstate;
diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h
index 73409e6..83259b8 100644
--- a/arch/arm/include/asm/tls.h
+++ b/arch/arm/include/asm/tls.h
@@ -2,27 +2,30 @@
#define __ASMARM_TLS_H
#ifdef __ASSEMBLY__
- .macro set_tls_none, tp, tmp1, tmp2
+#include <asm/asm-offsets.h>
+ .macro switch_tls_none, base, tp, tpuser, tmp1, tmp2
.endm
- .macro set_tls_v6k, tp, tmp1, tmp2
+ .macro switch_tls_v6k, base, tp, tpuser, tmp1, tmp2
+ mrc p15, 0, \tmp2, c13, c0, 2 @ get the user r/w register
mcr p15, 0, \tp, c13, c0, 3 @ set TLS register
- mov \tmp1, #0
- mcr p15, 0, \tmp1, c13, c0, 2 @ clear user r/w TLS register
+ mcr p15, 0, \tpuser, c13, c0, 2 @ and the user r/w register
+ str \tmp2, [\base, #TI_TP_VALUE + 4] @ save it
.endm
- .macro set_tls_v6, tp, tmp1, tmp2
+ .macro switch_tls_v6, base, tp, tpuser, tmp1, tmp2
ldr \tmp1, =elf_hwcap
ldr \tmp1, [\tmp1, #0]
mov \tmp2, #0xffff0fff
tst \tmp1, #HWCAP_TLS @ hardware TLS available?
- mcrne p15, 0, \tp, c13, c0, 3 @ yes, set TLS register
- movne \tmp1, #0
- mcrne p15, 0, \tmp1, c13, c0, 2 @ clear user r/w TLS register
streq \tp, [\tmp2, #-15] @ set TLS value at 0xffff0ff0
+ mrcne p15, 0, \tmp2, c13, c0, 2 @ get the user r/w register
+ mcrne p15, 0, \tp, c13, c0, 3 @ yes, set TLS register
+ mcrne p15, 0, \tpuser, c13, c0, 2 @ set user r/w register
+ strne \tmp2, [\base, #TI_TP_VALUE + 4] @ save it
.endm
- .macro set_tls_software, tp, tmp1, tmp2
+ .macro switch_tls_software, base, tp, tpuser, tmp1, tmp2
mov \tmp1, #0xffff0fff
str \tp, [\tmp1, #-15] @ set TLS value at 0xffff0ff0
.endm
@@ -31,19 +34,30 @@
#ifdef CONFIG_TLS_REG_EMUL
#define tls_emu 1
#define has_tls_reg 1
-#define set_tls set_tls_none
+#define switch_tls switch_tls_none
#elif defined(CONFIG_CPU_V6)
#define tls_emu 0
#define has_tls_reg (elf_hwcap & HWCAP_TLS)
-#define set_tls set_tls_v6
+#define switch_tls switch_tls_v6
#elif defined(CONFIG_CPU_32v6K)
#define tls_emu 0
#define has_tls_reg 1
-#define set_tls set_tls_v6k
+#define switch_tls switch_tls_v6k
#else
#define tls_emu 0
#define has_tls_reg 0
-#define set_tls set_tls_software
+#define switch_tls switch_tls_software
#endif
+#ifndef __ASSEMBLY__
+static inline unsigned long get_tpuser(void)
+{
+ unsigned long reg = 0;
+
+ if (has_tls_reg && !tls_emu)
+ __asm__("mrc p15, 0, %0, c13, c0, 2" : "=r" (reg));
+
+ return reg;
+}
+#endif
#endif /* __ASMARM_TLS_H */
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 9f52940..317400a 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -698,15 +698,16 @@
UNWIND(.fnstart )
UNWIND(.cantunwind )
add ip, r1, #TI_CPU_SAVE
- ldr r3, [r2, #TI_TP_VALUE]
ARM( stmia ip!, {r4 - sl, fp, sp, lr} ) @ Store most regs on stack
THUMB( stmia ip!, {r4 - sl, fp} ) @ Store most regs on stack
THUMB( str sp, [ip], #4 )
THUMB( str lr, [ip], #4 )
+ ldr r4, [r2, #TI_TP_VALUE]
+ ldr r5, [r2, #TI_TP_VALUE + 4]
#ifdef CONFIG_CPU_USE_DOMAINS
ldr r6, [r2, #TI_CPU_DOMAIN]
#endif
- set_tls r3, r4, r5
+ switch_tls r1, r4, r5, r3, r7
#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
ldr r7, [r2, #TI_TASK]
ldr r8, =__stack_chk_guard
@@ -754,6 +755,18 @@
#endif
.endm
+ .macro kuser_pad, sym, size
+ .if (. - \sym) & 3
+ .rept 4 - (. - \sym) & 3
+ .byte 0
+ .endr
+ .endif
+ .rept (\size - (. - \sym)) / 4
+ .word 0xe7fddef1
+ .endr
+ .endm
+
+#ifdef CONFIG_KUSER_HELPERS
.align 5
.globl __kuser_helper_start
__kuser_helper_start:
@@ -935,18 +948,13 @@
#error "incoherent kernel configuration"
#endif
- /* pad to next slot */
- .rept (16 - (. - __kuser_cmpxchg64)/4)
- .word 0
- .endr
-
- .align 5
+ kuser_pad __kuser_cmpxchg64, 64
__kuser_memory_barrier: @ 0xffff0fa0
smp_dmb arm
usr_ret lr
- .align 5
+ kuser_pad __kuser_memory_barrier, 32
__kuser_cmpxchg: @ 0xffff0fc0
@@ -1019,13 +1027,14 @@
#endif
- .align 5
+ kuser_pad __kuser_cmpxchg, 32
__kuser_get_tls: @ 0xffff0fe0
ldr r0, [pc, #(16 - 8)] @ read TLS, set in kuser_get_tls_init
usr_ret lr
mrc p15, 0, r0, c13, c0, 3 @ 0xffff0fe8 hardware TLS code
- .rep 4
+ kuser_pad __kuser_get_tls, 16
+ .rep 3
.word 0 @ 0xffff0ff0 software TLS value, then
.endr @ pad up to __kuser_helper_version
@@ -1035,14 +1044,16 @@
.globl __kuser_helper_end
__kuser_helper_end:
+#endif
+
THUMB( .thumb )
/*
* Vector stubs.
*
- * This code is copied to 0xffff0200 so we can use branches in the
- * vectors, rather than ldr's. Note that this code must not
- * exceed 0x300 bytes.
+ * This code is copied to 0xffff1000 so we can use branches in the
+ * vectors, rather than ldr's. Note that this code must not exceed
+ * a page size.
*
* Common stub entry macro:
* Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
@@ -1101,8 +1112,17 @@
1:
.endm
- .globl __stubs_start
+ .section .stubs, "ax", %progbits
__stubs_start:
+ @ This must be the first word
+ .word vector_swi
+
+vector_rst:
+ ARM( swi SYS_ERROR0 )
+ THUMB( svc #0 )
+ THUMB( nop )
+ b vector_und
+
/*
* Interrupt dispatcher
*/
@@ -1197,6 +1217,16 @@
.align 5
/*=============================================================================
+ * Address exception handler
+ *-----------------------------------------------------------------------------
+ * These aren't too critical.
+ * (they're not supposed to happen, and won't happen in 32-bit data mode).
+ */
+
+vector_addrexcptn:
+ b vector_addrexcptn
+
+/*=============================================================================
* Undefined FIQs
*-----------------------------------------------------------------------------
* Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC
@@ -1209,47 +1239,22 @@
vector_fiq:
subs pc, lr, #4
-/*=============================================================================
- * Address exception handler
- *-----------------------------------------------------------------------------
- * These aren't too critical.
- * (they're not supposed to happen, and won't happen in 32-bit data mode).
- */
-
-vector_addrexcptn:
- b vector_addrexcptn
-
-/*
- * We group all the following data together to optimise
- * for CPUs with separate I & D caches.
- */
- .align 5
-
-.LCvswi:
- .word vector_swi
.krait_fixup:
.word msm_krait_need_wfe_fixup
- .globl __stubs_end
-__stubs_end:
+ .globl vector_fiq_offset
+ .equ vector_fiq_offset, vector_fiq
- .equ stubs_offset, __vectors_start + 0x200 - __stubs_start
-
- .globl __vectors_start
+ .section .vectors, "ax", %progbits
__vectors_start:
- ARM( swi SYS_ERROR0 )
- THUMB( svc #0 )
- THUMB( nop )
- W(b) vector_und + stubs_offset
- W(ldr) pc, .LCvswi + stubs_offset
- W(b) vector_pabt + stubs_offset
- W(b) vector_dabt + stubs_offset
- W(b) vector_addrexcptn + stubs_offset
- W(b) vector_irq + stubs_offset
- W(b) vector_fiq + stubs_offset
-
- .globl __vectors_end
-__vectors_end:
+ W(b) vector_rst
+ W(b) vector_und
+ W(ldr) pc, __vectors_start + 0x1000
+ W(b) vector_pabt
+ W(b) vector_dabt
+ W(b) vector_addrexcptn
+ W(b) vector_irq
+ W(b) vector_fiq
.data
diff --git a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
index ca852c5..f9f16ef 100644
--- a/arch/arm/kernel/fiq.c
+++ b/arch/arm/kernel/fiq.c
@@ -48,6 +48,11 @@
#include <asm/irq.h>
#include <asm/traps.h>
+#define FIQ_OFFSET ({ \
+ extern void *vector_fiq_offset; \
+ (unsigned)&vector_fiq_offset; \
+ })
+
static unsigned long no_fiq_insn;
/* Default reacquire function
@@ -80,14 +85,14 @@
void set_fiq_handler(void *start, unsigned int length)
{
-#if defined(CONFIG_CPU_USE_DOMAINS)
- memcpy((void *)0xffff001c, start, length);
-#else
- memcpy(vectors_page + 0x1c, start, length);
-#endif
- flush_icache_range(0xffff001c, 0xffff001c + length);
- if (!vectors_high())
- flush_icache_range(0x1c, 0x1c + length);
+ void *base = vectors_page;
+ unsigned offset = FIQ_OFFSET;
+
+ memcpy(base + offset, start, length);
+ if (!cache_is_vipt_nonaliasing())
+ flush_icache_range((unsigned long)base + offset, offset +
+ length);
+ flush_icache_range(0xffff0000 + offset, 0xffff0000 + offset + length);
}
int claim_fiq(struct fiq_handler *f)
@@ -123,14 +128,16 @@
while (current_fiq->fiq_op(current_fiq->dev_id, 0));
}
+static int fiq_start;
+
void enable_fiq(int fiq)
{
- enable_irq(fiq + FIQ_START);
+ enable_irq(fiq + fiq_start);
}
void disable_fiq(int fiq)
{
- disable_irq(fiq + FIQ_START);
+ disable_irq(fiq + fiq_start);
}
void fiq_set_type(int fiq, unsigned int type)
@@ -147,7 +154,9 @@
EXPORT_SYMBOL(disable_fiq);
EXPORT_SYMBOL(fiq_set_type);
-void __init init_FIQ(void)
+void __init init_FIQ(int start)
{
- no_fiq_insn = *(unsigned long *)0xffff001c;
+ unsigned offset = FIQ_OFFSET;
+ no_fiq_insn = *(unsigned long *)(0xffff0000 + offset);
+ fiq_start = start;
}
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index 0241da1..2a3ab6e 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -116,7 +116,12 @@
static int
armpmu_map_event(const unsigned (*event_map)[PERF_COUNT_HW_MAX], u64 config)
{
- int mapping = (*event_map)[config];
+ int mapping;
+
+ if (config >= PERF_COUNT_HW_MAX)
+ return -EINVAL;
+
+ mapping = (*event_map)[config];
return mapping == HW_OP_UNSUPPORTED ? -ENOENT : mapping;
}
@@ -341,6 +346,9 @@
struct hw_perf_event fake_event = event->hw;
struct pmu *leader_pmu = event->group_leader->pmu;
+ if (is_software_event(event))
+ return 1;
+
if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF)
return 1;
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index fe97ff2..c5fa883 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -38,6 +38,7 @@
#include <asm/thread_notify.h>
#include <asm/stacktrace.h>
#include <asm/mach/time.h>
+#include <asm/tls.h>
#ifdef CONFIG_CC_STACKPROTECTOR
#include <linux/stackprotector.h>
@@ -534,7 +535,8 @@
clear_ptrace_hw_breakpoint(p);
if (clone_flags & CLONE_SETTLS)
- thread->tp_value = regs->ARM_r3;
+ thread->tp_value[0] = childregs->ARM_r3;
+ thread->tp_value[1] = get_tpuser();
thread_notify(THREAD_NOTIFY_COPY, thread);
@@ -650,10 +652,11 @@
}
#ifdef CONFIG_MMU
+#ifdef CONFIG_KUSER_HELPERS
/*
* The vectors page is always readable from user space for the
- * atomic helpers and the signal restart code. Insert it into the
- * gate_vma so that it is visible through ptrace and /proc/<pid>/mem.
+ * atomic helpers. Insert it into the gate_vma so that it is visible
+ * through ptrace and /proc/<pid>/mem.
*/
static struct vm_area_struct gate_vma;
@@ -682,14 +685,53 @@
{
return in_gate_area(NULL, addr);
}
+#define is_gate_vma(vma) ((vma) == &gate_vma)
+#else
+#define is_gate_vma(vma) 0
+#endif
const char *arch_vma_name(struct vm_area_struct *vma)
{
- if (vma == &gate_vma)
+ if (is_gate_vma(vma))
return "[vectors]";
+ else if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.sigpage)
+ return "[sigpage]";
else if (vma == get_user_timers_vma(NULL))
return "[timers]";
else
return NULL;
}
+
+static struct page *signal_page;
+extern struct page *get_signal_page(void);
+
+int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
+{
+ struct mm_struct *mm = current->mm;
+ unsigned long addr;
+ int ret;
+
+ if (!signal_page)
+ signal_page = get_signal_page();
+ if (!signal_page)
+ return -ENOMEM;
+
+ down_write(&mm->mmap_sem);
+ addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0);
+ if (IS_ERR_VALUE(addr)) {
+ ret = addr;
+ goto up_fail;
+ }
+
+ ret = install_special_mapping(mm, addr, PAGE_SIZE,
+ VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
+ &signal_page);
+
+ if (ret == 0)
+ mm->context.sigpage = addr;
+
+ up_fail:
+ up_write(&mm->mmap_sem);
+ return ret;
+}
#endif
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 9650c14..c6c6be7 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -844,7 +844,7 @@
#endif
case PTRACE_GET_THREAD_AREA:
- ret = put_user(task_thread_info(child)->tp_value,
+ ret = put_user(task_thread_info(child)->tp_value[0],
datap);
break;
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 28b114f..7298f9a 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -107,6 +107,9 @@
unsigned int boot_reason;
EXPORT_SYMBOL(boot_reason);
+unsigned int cold_boot;
+EXPORT_SYMBOL(cold_boot);
+
#ifdef MULTI_CPU
struct processor processor __read_mostly;
#endif
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index d68d1b6..e000e5e 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -8,6 +8,7 @@
* published by the Free Software Foundation.
*/
#include <linux/errno.h>
+#include <linux/random.h>
#include <linux/signal.h>
#include <linux/personality.h>
#include <linux/freezer.h>
@@ -16,10 +17,10 @@
#include <asm/elf.h>
#include <asm/cacheflush.h>
+#include <asm/traps.h>
#include <asm/ucontext.h>
#include <asm/unistd.h>
#include <asm/vfp.h>
-
#include "signal.h"
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -44,7 +45,7 @@
#define SWI_THUMB_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_sigreturn - __NR_SYSCALL_BASE))
#define SWI_THUMB_RT_SIGRETURN (0xdf00 << 16 | 0x2700 | (__NR_rt_sigreturn - __NR_SYSCALL_BASE))
-const unsigned long sigreturn_codes[7] = {
+static const unsigned long sigreturn_codes[7] = {
MOV_R7_NR_SIGRETURN, SWI_SYS_SIGRETURN, SWI_THUMB_SIGRETURN,
MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
};
@@ -112,6 +113,8 @@
return ret;
}
+static unsigned long signal_return_offset;
+
#ifdef CONFIG_CRUNCH
static int preserve_crunch_context(struct crunch_sigframe __user *frame)
{
@@ -460,13 +463,20 @@
__put_user(sigreturn_codes[idx+1], rc+1))
return 1;
+#ifdef CONFIG_MMU
if (cpsr & MODE32_BIT) {
+ struct mm_struct *mm = current->mm;
+
/*
- * 32-bit code can use the new high-page
- * signal return code support.
+ * 32-bit code can use the signal return page
+ * except when the MPU has protected the vectors
+ * page from PL0
*/
- retcode = KERN_SIGRETURN_CODE + (idx << 2) + thumb;
- } else {
+ retcode = mm->context.sigpage + signal_return_offset +
+ (idx << 2) + thumb;
+ } else
+#endif
+ {
/*
* Ensure that the instruction cache sees
* the return code written onto the stack.
@@ -739,3 +749,33 @@
key_replace_session_keyring();
}
}
+
+struct page *get_signal_page(void)
+{
+ unsigned long ptr;
+ unsigned offset;
+ struct page *page;
+ void *addr;
+
+ page = alloc_pages(GFP_KERNEL, 0);
+
+ if (!page)
+ return NULL;
+
+ addr = page_address(page);
+
+ /* Give the signal return code some randomness */
+ offset = 0x200 + (get_random_int() & 0x7fc);
+ signal_return_offset = offset;
+
+ /*
+ * Copy signal return handlers into the vector page, and
+ * set sigreturn to be a pointer to these.
+ */
+ memcpy(addr + offset, sigreturn_codes, sizeof(sigreturn_codes));
+
+ ptr = (unsigned long)addr + offset;
+ flush_icache_range(ptr, ptr + sizeof(sigreturn_codes));
+
+ return page;
+}
diff --git a/arch/arm/kernel/signal.h b/arch/arm/kernel/signal.h
index 6fcfe83..a0dcf5f 100644
--- a/arch/arm/kernel/signal.h
+++ b/arch/arm/kernel/signal.h
@@ -10,5 +10,4 @@
#define KERN_SIGRETURN_CODE (CONFIG_VECTORS_BASE + 0x00000500)
#define KERN_RESTART_CODE (KERN_SIGRETURN_CODE + sizeof(sigreturn_codes))
-extern const unsigned long sigreturn_codes[7];
extern const unsigned long syscall_restart_code[2];
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 1e9504b..bd49b1f 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -35,8 +35,6 @@
#include <asm/tls.h>
#include <asm/system_misc.h>
-#include "signal.h"
-
#include <trace/events/exception.h>
static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
@@ -566,7 +564,7 @@
return regs->ARM_r0;
case NR(set_tls):
- thread->tp_value = regs->ARM_r0;
+ thread->tp_value[0] = regs->ARM_r0;
if (tls_emu)
return 0;
if (has_tls_reg) {
@@ -684,7 +682,7 @@
int reg = (instr >> 12) & 15;
if (reg == 15)
return 1;
- regs->uregs[reg] = current_thread_info()->tp_value;
+ regs->uregs[reg] = current_thread_info()->tp_value[0];
regs->ARM_pc += 4;
return 0;
}
@@ -785,49 +783,55 @@
return;
}
-static void __init kuser_get_tls_init(unsigned long vectors)
+#ifdef CONFIG_KUSER_HELPERS
+static void __init kuser_init(void *vectors)
{
+ extern char __kuser_helper_start[], __kuser_helper_end[];
+ int kuser_sz = __kuser_helper_end - __kuser_helper_start;
+
+ memcpy(vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
+
/*
* vectors + 0xfe0 = __kuser_get_tls
* vectors + 0xfe8 = hardware TLS instruction at 0xffff0fe8
*/
if (tls_emu || has_tls_reg)
- memcpy((void *)vectors + 0xfe0, (void *)vectors + 0xfe8, 4);
+ memcpy(vectors + 0xfe0, vectors + 0xfe8, 4);
}
+#else
+static void __init kuser_init(void *vectors)
+{
+}
+#endif
void __init early_trap_init(void *vectors_base)
{
unsigned long vectors = (unsigned long)vectors_base;
extern char __stubs_start[], __stubs_end[];
extern char __vectors_start[], __vectors_end[];
- extern char __kuser_helper_start[], __kuser_helper_end[];
- int kuser_sz = __kuser_helper_end - __kuser_helper_start;
+ unsigned i;
vectors_page = vectors_base;
/*
+ * Poison the vectors page with an undefined instruction. This
+ * instruction is chosen to be undefined for both ARM and Thumb
+ * ISAs. The Thumb version is an undefined instruction with a
+ * branch back to the undefined instruction.
+ */
+ for (i = 0; i < PAGE_SIZE / sizeof(u32); i++)
+ ((u32 *)vectors_base)[i] = 0xe7fddef1;
+
+ /*
* Copy the vectors, stubs and kuser helpers (in entry-armv.S)
* into the vector page, mapped at 0xffff0000, and ensure these
* are visible to the instruction stream.
*/
memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
- memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);
- memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
+ memcpy((void *)vectors + 0x1000, __stubs_start, __stubs_end - __stubs_start);
- /*
- * Do processor specific fixups for the kuser helpers
- */
- kuser_get_tls_init(vectors);
+ kuser_init(vectors_base);
- /*
- * Copy signal return handlers into the vector page, and
- * set sigreturn to be a pointer to these.
- */
- memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),
- sigreturn_codes, sizeof(sigreturn_codes));
- memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE),
- syscall_restart_code, sizeof(syscall_restart_code));
-
- flush_icache_range(vectors, vectors + PAGE_SIZE);
+ flush_icache_range(vectors, vectors + PAGE_SIZE * 2);
modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
}
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 0bf55ae..68c312b 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -151,6 +151,23 @@
#endif
__init_begin = .;
#endif
+ /*
+ * The vectors and stubs are relocatable code, and the
+ * only thing that matters is their relative offsets
+ */
+ __vectors_start = .;
+ .vectors 0 : AT(__vectors_start) {
+ *(.vectors)
+ }
+ . = __vectors_start + SIZEOF(.vectors);
+ __vectors_end = .;
+
+ __stubs_start = .;
+ .stubs 0x1000 : AT(__stubs_start) {
+ *(.stubs)
+ }
+ . = __stubs_start + SIZEOF(.stubs);
+ __stubs_end = .;
INIT_TEXT_SECTION(8)
.exit.text : {
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 696ddf9..87c2f8c 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -473,6 +473,7 @@
select MSM_JTAG_MM if CORESIGHT_ETM
select MSM_CPR_REGULATOR
select MSM_RPM_LOG
+ select MSM_IOMMU_SYNC
select MSM_RPM_STATS_LOG
config ARCH_MSM8226
diff --git a/arch/arm/mach-msm/Makefile.boot b/arch/arm/mach-msm/Makefile.boot
index 910264e..552ed16 100644
--- a/arch/arm/mach-msm/Makefile.boot
+++ b/arch/arm/mach-msm/Makefile.boot
@@ -67,11 +67,14 @@
dtb-$(CONFIG_ARCH_MSM8974) += msm8974-v2.2-fluid.dtb
dtb-$(CONFIG_ARCH_MSM8974) += msm8974-v2.2-liquid.dtb
dtb-$(CONFIG_ARCH_MSM8974) += msm8974-v2.2-mtp.dtb
- dtb-$(CONFIG_ARCH_MSM8974) += msm8974pro-ab-cdp.dtb
- dtb-$(CONFIG_ARCH_MSM8974) += msm8974pro-ab-fluid.dtb
- dtb-$(CONFIG_ARCH_MSM8974) += msm8974pro-ab-liquid.dtb
- dtb-$(CONFIG_ARCH_MSM8974) += msm8974pro-ab-mtp.dtb
- dtb-$(CONFIG_ARCH_MSM8974) += msm8974pro-ac-mtp.dtb
+ dtb-$(CONFIG_ARCH_MSM8974) += msm8974pro-ab-pm8941-cdp.dtb
+ dtb-$(CONFIG_ARCH_MSM8974) += msm8974pro-ab-pm8941-fluid.dtb
+ dtb-$(CONFIG_ARCH_MSM8974) += msm8974pro-ab-pm8941-liquid.dtb
+ dtb-$(CONFIG_ARCH_MSM8974) += msm8974pro-ab-pm8941-mtp.dtb
+ dtb-$(CONFIG_ARCH_MSM8974) += msm8974pro-ac-pm8941-cdp.dtb
+ dtb-$(CONFIG_ARCH_MSM8974) += msm8974pro-ac-pm8941-liquid.dtb
+ dtb-$(CONFIG_ARCH_MSM8974) += msm8974pro-ac-pm8941-mtp.dtb
+ dtb-$(CONFIG_ARCH_MSM8974) += msm8974pro-ac-pma8084-pm8941-mtp.dtb
# APQ8084
zreladdr-$(CONFIG_ARCH_APQ8084) := 0x00008000
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 8410019..60be20a 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -55,7 +55,7 @@
.hfpll_phys_base = 0xF908A000,
.l2cpmr_iaddr = 0x4501,
.sec_clk_sel = 2,
- .vreg[VREG_CORE] = { "krait0", 1100000 },
+ .vreg[VREG_CORE] = { "krait0", 1120000 },
.vreg[VREG_MEM] = { "krait0_mem", 1050000 },
.vreg[VREG_DIG] = { "krait0_dig", LVL_HIGH },
.vreg[VREG_HFPLL_A] = { "krait0_hfpll", 1800000 },
@@ -64,7 +64,7 @@
.hfpll_phys_base = 0xF909A000,
.l2cpmr_iaddr = 0x5501,
.sec_clk_sel = 2,
- .vreg[VREG_CORE] = { "krait1", 1100000 },
+ .vreg[VREG_CORE] = { "krait1", 1120000 },
.vreg[VREG_MEM] = { "krait1_mem", 1050000 },
.vreg[VREG_DIG] = { "krait1_dig", LVL_HIGH },
.vreg[VREG_HFPLL_A] = { "krait1_hfpll", 1800000 },
@@ -73,7 +73,7 @@
.hfpll_phys_base = 0xF90AA000,
.l2cpmr_iaddr = 0x6501,
.sec_clk_sel = 2,
- .vreg[VREG_CORE] = { "krait2", 1100000 },
+ .vreg[VREG_CORE] = { "krait2", 1120000 },
.vreg[VREG_MEM] = { "krait2_mem", 1050000 },
.vreg[VREG_DIG] = { "krait2_dig", LVL_HIGH },
.vreg[VREG_HFPLL_A] = { "krait2_hfpll", 1800000 },
@@ -82,7 +82,7 @@
.hfpll_phys_base = 0xF90BA000,
.l2cpmr_iaddr = 0x7501,
.sec_clk_sel = 2,
- .vreg[VREG_CORE] = { "krait3", 1100000 },
+ .vreg[VREG_CORE] = { "krait3", 1120000 },
.vreg[VREG_MEM] = { "krait3_mem", 1050000 },
.vreg[VREG_DIG] = { "krait3_dig", LVL_HIGH },
.vreg[VREG_HFPLL_A] = { "krait3_hfpll", 1800000 },
@@ -273,10 +273,10 @@
[10] = { { 1036800, HFPLL, 1, 54 }, LVL_NOM, 950000, 5 },
[11] = { { 1113600, HFPLL, 1, 58 }, LVL_HIGH, 1050000, 6 },
[12] = { { 1190400, HFPLL, 1, 62 }, LVL_HIGH, 1050000, 6 },
- [13] = { { 1267200, HFPLL, 1, 66 }, LVL_HIGH, 1050000, 7 },
- [14] = { { 1344000, HFPLL, 1, 70 }, LVL_HIGH, 1050000, 7 },
- [15] = { { 1420800, HFPLL, 1, 74 }, LVL_HIGH, 1050000, 7 },
- [16] = { { 1497600, HFPLL, 1, 78 }, LVL_HIGH, 1050000, 7 },
+ [13] = { { 1267200, HFPLL, 1, 66 }, LVL_HIGH, 1050000, 6 },
+ [14] = { { 1344000, HFPLL, 1, 70 }, LVL_HIGH, 1050000, 6 },
+ [15] = { { 1420800, HFPLL, 1, 74 }, LVL_HIGH, 1050000, 6 },
+ [16] = { { 1497600, HFPLL, 1, 78 }, LVL_HIGH, 1050000, 6 },
[17] = { { 1574400, HFPLL, 1, 82 }, LVL_HIGH, 1050000, 7 },
[18] = { { 1651200, HFPLL, 1, 86 }, LVL_HIGH, 1050000, 7 },
[19] = { { 1728000, HFPLL, 1, 90 }, LVL_HIGH, 1050000, 8 },
@@ -899,542 +899,1664 @@
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs0[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 72 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 83 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 101 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 780000, 120 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 790000, 139 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 159 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 810000, 180 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 820000, 200 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 830000, 221 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 840000, 242 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 850000, 264 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 865000, 287 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 875000, 308 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 890000, 333 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 900000, 356 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 915000, 380 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 925000, 404 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 940000, 430 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 955000, 456 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 970000, 482 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 985000, 510 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1000000, 538 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1015000, 565 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 596 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 627 },
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 659 },
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 691 },
+static struct acpu_level pro_rev0_2p3g_pvs0[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 74 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 780000, 124 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 790000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 164 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 810000, 184 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 820000, 206 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 830000, 227 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 840000, 249 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 850000, 271 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 865000, 295 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 875000, 318 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 890000, 342 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 900000, 365 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 915000, 392 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 925000, 416 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 940000, 442 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 955000, 469 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 970000, 497 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 985000, 525 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1000000, 554 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1015000, 583 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 613 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 642 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1060000, 663 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 675 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 708 },
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs1[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 72},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 83},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 101},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 120},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 139},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 785000, 159},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 795000, 180},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 805000, 200},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 815000, 221},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 825000, 242},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 835000, 264},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 850000, 287},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 860000, 308},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 870000, 333},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 885000, 356},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 895000, 380},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 905000, 404},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 920000, 430},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 935000, 456},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 950000, 482},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 965000, 510},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 980000, 538},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 995000, 565},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 596},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 627},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 659},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 691},
+static struct acpu_level pro_rev0_2p3g_pvs1[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 74 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 124 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 785000, 164 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 795000, 184 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 805000, 206 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 815000, 227 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 825000, 249 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 835000, 271 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 850000, 295 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 860000, 318 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 870000, 342 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 885000, 365 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 895000, 392 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 905000, 416 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 920000, 442 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 935000, 469 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 950000, 497 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 965000, 525 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 980000, 554 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 995000, 583 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 613 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 642 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1035000, 663 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 675 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 708 },
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs2[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 72 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 83 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 101 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 120 },
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 760000, 139 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 770000, 159 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 780000, 180 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 790000, 200 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 221 },
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 810000, 242 },
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 820000, 264 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 830000, 287 },
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 840000, 308 },
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 850000, 333 },
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 865000, 356 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 875000, 380 },
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 885000, 404 },
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 900000, 430 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 915000, 456 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 930000, 482 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 945000, 510 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 955000, 538 },
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 970000, 565 },
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 980000, 596 },
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 995000, 627 },
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 659 },
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 691 },
+static struct acpu_level pro_rev0_2p3g_pvs2[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 74 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 124 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 760000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 770000, 164 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 780000, 184 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 790000, 206 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 227 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 810000, 249 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 820000, 271 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 830000, 295 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 840000, 318 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 850000, 342 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 865000, 365 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 875000, 392 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 885000, 416 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 900000, 442 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 915000, 469 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 930000, 497 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 945000, 525 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 955000, 554 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 970000, 583 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 980000, 613 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 995000, 642 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1010000, 663 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 675 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 708 },
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs3[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 72},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 83},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 101},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 120},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 139},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 755000, 159},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 765000, 180},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 200},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 785000, 221},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 795000, 242},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 805000, 264},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 815000, 287},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 825000, 308},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 835000, 333},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 850000, 356},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 860000, 380},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 404},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 885000, 430},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 900000, 456},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 910000, 482},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 925000, 510},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 935000, 538},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 945000, 565},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 960000, 596},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 970000, 627},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 985000, 659},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 691},
+static struct acpu_level pro_rev0_2p3g_pvs3[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 74 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 124 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 755000, 164 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 765000, 184 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 206 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 785000, 227 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 795000, 249 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 805000, 271 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 815000, 295 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 825000, 318 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 835000, 342 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 850000, 365 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 860000, 392 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 416 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 885000, 442 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 900000, 469 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 910000, 497 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 925000, 525 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 935000, 554 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 945000, 583 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 960000, 613 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 970000, 642 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 985000, 663 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 985000, 675 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 708 },
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs4[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 72},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 83},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 101},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 120},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 139},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 159},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 755000, 180},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 765000, 200},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 221},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 785000, 242},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 795000, 264},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 805000, 287},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 815000, 308},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 825000, 333},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 835000, 356},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 845000, 380},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 855000, 404},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 870000, 430},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 885000, 456},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 895000, 482},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 905000, 510},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 915000, 538},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 925000, 565},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 935000, 596},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 950000, 627},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 960000, 659},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 975000, 691},
+static struct acpu_level pro_rev0_2p3g_pvs4[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 74 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 124 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 164 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 755000, 184 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 765000, 206 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 227 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 785000, 249 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 795000, 271 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 805000, 295 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 815000, 318 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 825000, 342 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 835000, 365 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 845000, 392 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 855000, 416 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 870000, 442 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 885000, 469 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 895000, 497 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 905000, 525 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 915000, 554 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 925000, 583 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 935000, 613 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 950000, 642 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 960000, 663 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 960000, 675 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 975000, 708 },
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs5[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 725000, 72},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 725000, 83},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 725000, 101},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 725000, 120},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 725000, 139},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 735000, 159},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 745000, 180},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 755000, 200},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 765000, 221},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 242},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 785000, 264},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 795000, 287},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 805000, 308},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 815000, 333},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 825000, 356},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 835000, 380},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 845000, 404},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 855000, 430},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 865000, 456},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 875000, 482},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 885000, 510},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 895000, 538},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 905000, 565},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 915000, 596},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 930000, 627},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 940000, 659},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 950000, 691},
+static struct acpu_level pro_rev0_2p3g_pvs5[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 725000, 74 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 725000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 725000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 725000, 124 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 725000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 735000, 164 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 745000, 184 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 755000, 206 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 765000, 227 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 249 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 785000, 271 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 795000, 295 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 805000, 318 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 815000, 342 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 825000, 365 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 835000, 392 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 845000, 416 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 855000, 442 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 865000, 469 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 875000, 497 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 885000, 525 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 895000, 554 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 905000, 583 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 915000, 613 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 930000, 642 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 940000, 663 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 940000, 675 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 950000, 708 },
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p3g_pvs6[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 725000, 72},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 725000, 83},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 725000, 101},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 725000, 120},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 725000, 139},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 725000, 159},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 735000, 180},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 745000, 200},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 755000, 221},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 765000, 242},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 775000, 264},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 785000, 287},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 795000, 308},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 805000, 333},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 815000, 356},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 825000, 380},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 835000, 404},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 845000, 430},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 850000, 456},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 860000, 482},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 870000, 510},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 880000, 538},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 890000, 565},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 895000, 596},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 905000, 627},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 915000, 659},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 925000, 691},
+static struct acpu_level pro_rev0_2p3g_pvs6[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 725000, 74 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 725000, 85 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 725000, 104 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 725000, 124 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 725000, 144 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 725000, 164 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 735000, 184 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 745000, 206 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 755000, 227 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 765000, 249 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 775000, 271 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 785000, 295 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 795000, 318 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 805000, 342 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 815000, 365 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 825000, 392 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 835000, 416 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 845000, 442 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 850000, 469 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 860000, 497 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 870000, 525 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 880000, 554 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 890000, 583 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 895000, 613 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 905000, 642 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 915000, 663 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 915000, 675 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 925000, 708 },
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs0[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 800000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 800000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 800000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 805000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 815000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 825000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 835000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 845000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 855000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 885000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 900000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 915000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 930000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 945000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 960000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 980000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1000000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1020000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1040000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1060000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1080000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 1100000, 800},
+static struct acpu_level pro_rev0_2p5g_pvs0[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 125 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 145 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 810000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 820000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 830000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 840000, 229 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 850000, 251 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 860000, 273 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 870000, 296 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 880000, 319 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 890000, 342 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 900000, 365 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 910000, 390 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 920000, 415 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 930000, 439 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 945000, 465 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 960000, 493 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 975000, 521 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 990000, 549 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1005000, 579 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1020000, 608 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1035000, 638 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1050000, 667 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1050000, 667 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1065000, 700 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1080000, 734 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1095000, 769 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1100000, 785 },
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs1[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 800000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 800000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 800000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 800000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 805000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 815000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 825000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 835000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 845000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 855000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 870000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 885000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 900000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 915000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 930000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 945000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 960000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 975000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 995000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1015000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1035000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1055000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 1075000, 800},
+static struct acpu_level pro_rev0_2p5g_pvs1[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 125 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 145 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 800000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 805000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 815000, 229 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 825000, 251 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 835000, 273 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 845000, 296 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 855000, 319 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 865000, 342 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 875000, 365 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 885000, 390 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 895000, 415 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 905000, 439 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 920000, 465 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 935000, 493 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 950000, 521 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 965000, 549 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 980000, 579 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 995000, 608 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1010000, 638 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1025000, 667 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1025000, 667 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1040000, 700 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1055000, 734 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1070000, 769 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1075000, 785 },
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs2[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 780000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 790000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 800000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 810000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 820000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 830000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 840000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 850000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 865000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 880000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 895000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 910000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 925000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 940000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 955000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 970000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 990000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1010000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1030000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 1050000, 800},
+static struct acpu_level pro_rev0_2p5g_pvs2[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 125 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 145 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 780000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 790000, 229 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 800000, 251 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 810000, 273 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 820000, 296 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 830000, 319 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 840000, 342 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 850000, 365 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 860000, 390 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 415 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 880000, 439 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 895000, 465 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 910000, 493 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 925000, 521 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 940000, 549 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 955000, 579 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 970000, 608 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 985000, 638 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1000000, 667 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1000000, 667 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1015000, 700 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1030000, 734 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1045000, 769 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1050000, 785 },
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs3[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 775000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 780000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 790000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 800000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 810000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 820000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 830000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 840000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 850000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 865000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 880000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 895000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 910000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 925000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 940000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 955000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 970000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 985000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1005000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 1025000, 800},
+static struct acpu_level pro_rev0_2p5g_pvs3[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 125 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 145 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 229 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 780000, 251 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 785000, 273 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 795000, 296 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 805000, 319 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 815000, 342 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 825000, 365 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 835000, 390 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 845000, 415 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 855000, 439 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 870000, 465 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 885000, 493 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 900000, 521 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 915000, 549 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 930000, 579 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 945000, 608 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 960000, 638 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 975000, 667 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 975000, 667 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 990000, 700 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1005000, 734 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1020000, 769 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1025000, 785 },
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs4[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 750000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 750000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 750000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 750000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 760000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 770000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 780000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 790000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 800000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 810000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 820000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 830000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 840000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 850000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 865000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 880000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 895000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 910000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 925000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 940000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 955000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 970000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 985000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 1000000, 800},
+static struct acpu_level pro_rev0_2p5g_pvs4[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 125 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 145 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 229 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 251 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 775000, 273 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 775000, 296 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 780000, 319 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 790000, 342 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 800000, 365 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 810000, 390 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 820000, 415 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 830000, 439 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 845000, 465 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 860000, 493 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 875000, 521 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 890000, 549 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 905000, 579 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 920000, 608 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 935000, 638 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 950000, 667 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 950000, 667 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 965000, 700 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 980000, 734 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 995000, 769 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1000000, 785 },
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs5[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 750000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 750000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 750000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 750000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 750000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 760000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 770000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 780000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 790000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 800000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 810000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 820000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 830000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 840000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 850000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 860000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 870000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 885000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 900000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 915000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 930000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 945000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 960000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 975000, 800},
+static struct acpu_level pro_rev0_2p5g_pvs5[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 125 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 145 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 750000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 750000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 750000, 229 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 750000, 251 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 750000, 273 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 750000, 296 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 760000, 319 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 770000, 342 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 780000, 365 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 790000, 390 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 800000, 415 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 810000, 439 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 820000, 465 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 835000, 493 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 850000, 521 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 865000, 549 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 880000, 579 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 895000, 608 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 910000, 638 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 925000, 667 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 925000, 667 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 940000, 700 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 955000, 734 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 970000, 769 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 975000, 785 },
{ 0, { 0 } }
};
-static struct acpu_level acpu_ftbl_pro_2p5g_pvs6[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 725000, 76},
- { 0, { 345600, HFPLL, 2, 36 }, L2(1), 725000, 87},
- { 1, { 422400, HFPLL, 2, 44 }, L2(2), 725000, 106},
- { 0, { 499200, HFPLL, 2, 52 }, L2(2), 725000, 125},
- { 0, { 576000, HFPLL, 1, 30 }, L2(3), 725000, 145},
- { 1, { 652800, HFPLL, 1, 34 }, L2(3), 725000, 164},
- { 1, { 729600, HFPLL, 1, 38 }, L2(4), 725000, 183},
- { 0, { 806400, HFPLL, 1, 42 }, L2(4), 725000, 202},
- { 1, { 883200, HFPLL, 1, 46 }, L2(4), 725000, 222},
- { 1, { 960000, HFPLL, 1, 50 }, L2(9), 725000, 241},
- { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 735000, 261},
- { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 745000, 282},
- { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 755000, 305},
- { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 765000, 327},
- { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 775000, 350},
- { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 785000, 373},
- { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 795000, 398},
- { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 805000, 424},
- { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 815000, 449},
- { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 825000, 476},
- { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 835000, 503},
- { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 845000, 530},
- { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 855000, 559},
- { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 865000, 590},
- { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 875000, 621},
- { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 890000, 654},
- { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 905000, 686},
- { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 920000, 723},
- { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 935000, 761},
- { 1, { 2496000, HFPLL, 1, 130 }, L2(19), 950000, 800},
+static struct acpu_level pro_rev0_2p5g_pvs6[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 125 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 145 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 165 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 750000, 186 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 750000, 208 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 750000, 229 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 750000, 251 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 750000, 273 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 750000, 296 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 750000, 319 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 755000, 342 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 765000, 365 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 775000, 390 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 785000, 415 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 795000, 439 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 805000, 465 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 815000, 493 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 825000, 521 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 840000, 549 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 855000, 579 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 870000, 608 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 885000, 638 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 900000, 667 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 900000, 667 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 915000, 700 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 930000, 734 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 945000, 769 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 950000, 785 },
{ 0, { 0 } }
};
-static struct pvs_table pvs_v1[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+static struct acpu_level pro_rev1_2p5g_pvs0[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 810000, 126 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 820000, 147 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 830000, 168 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 840000, 189 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 850000, 211 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 860000, 233 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 870000, 256 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 880000, 278 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 890000, 301 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 900000, 324 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 910000, 348 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 920000, 372 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 930000, 396 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 940000, 421 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 950000, 446 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 965000, 473 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 980000, 501 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 995000, 529 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1010000, 558 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1025000, 588 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1040000, 617 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1055000, 649 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1070000, 682 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1070000, 682 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1085000, 716 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1100000, 751 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1115000, 786 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1120000, 802 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p5g_pvs1[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 126 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 810000, 147 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 820000, 168 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 830000, 189 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 840000, 211 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 850000, 233 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 860000, 256 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 870000, 278 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 880000, 301 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 890000, 324 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 900000, 348 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 910000, 372 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 920000, 396 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 930000, 421 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 940000, 446 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 955000, 473 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 970000, 501 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 985000, 529 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1000000, 558 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1015000, 588 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 617 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 649 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1060000, 682 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 682 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 716 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1090000, 751 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1105000, 786 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1110000, 802 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p5g_pvs2[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 126 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 147 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 810000, 168 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 820000, 189 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 830000, 211 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 840000, 233 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 850000, 256 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 860000, 278 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 870000, 301 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 880000, 324 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 890000, 348 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 900000, 372 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 910000, 396 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 920000, 421 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 930000, 446 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 945000, 473 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 960000, 501 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 975000, 529 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 990000, 558 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1005000, 588 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1020000, 617 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1035000, 649 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1050000, 682 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1050000, 682 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1065000, 716 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1080000, 751 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1095000, 786 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1100000, 802 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p5g_pvs3[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 126 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 147 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 168 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 810000, 189 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 820000, 211 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 830000, 233 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 840000, 256 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 850000, 278 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 860000, 301 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 870000, 324 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 880000, 348 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 890000, 372 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 900000, 396 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 421 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 920000, 446 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 935000, 473 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 950000, 501 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 965000, 529 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 980000, 558 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 995000, 588 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1010000, 617 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1025000, 649 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1040000, 682 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1040000, 682 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1055000, 716 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1070000, 751 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1085000, 786 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1090000, 802 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p5g_pvs4[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 126 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 147 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 168 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 800000, 189 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 810000, 211 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 820000, 233 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 830000, 256 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 840000, 278 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 850000, 301 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 860000, 324 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 870000, 348 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 880000, 372 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 890000, 396 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 900000, 421 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 910000, 446 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 925000, 473 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 940000, 501 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 955000, 529 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 970000, 558 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 985000, 588 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1000000, 617 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1015000, 649 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1030000, 682 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1030000, 682 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1045000, 716 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1060000, 751 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1075000, 786 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1080000, 802 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p5g_pvs5[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 126 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 147 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 168 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 800000, 189 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 800000, 211 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 810000, 233 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 820000, 256 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 830000, 278 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 840000, 301 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 850000, 324 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 860000, 348 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 870000, 372 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 880000, 396 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 890000, 421 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 900000, 446 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 915000, 473 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 930000, 501 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 945000, 529 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 960000, 558 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 975000, 588 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 990000, 617 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1005000, 649 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1020000, 682 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1020000, 682 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1035000, 716 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1050000, 751 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1065000, 786 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1070000, 802 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p5g_pvs6[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 126 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 147 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 168 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 780000, 189 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 790000, 211 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 233 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 810000, 256 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 820000, 278 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 830000, 301 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 840000, 324 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 850000, 348 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 860000, 372 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 870000, 396 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 880000, 421 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 890000, 446 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 905000, 473 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 920000, 501 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 935000, 529 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 950000, 558 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 965000, 588 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 980000, 617 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 995000, 649 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1010000, 682 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 682 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 716 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1040000, 751 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1055000, 786 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1060000, 802 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p5g_pvs7[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 126 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 147 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 168 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 189 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 780000, 211 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 790000, 233 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 800000, 256 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 810000, 278 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 820000, 301 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 830000, 324 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 840000, 348 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 850000, 372 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 860000, 396 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 421 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 880000, 446 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 895000, 473 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 910000, 501 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 925000, 529 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 940000, 558 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 955000, 588 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 970000, 617 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 985000, 649 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1000000, 682 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1000000, 682 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1015000, 716 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1030000, 751 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1045000, 786 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1050000, 802 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p5g_pvs8[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 126 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 147 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 168 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 189 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 211 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 780000, 233 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 790000, 256 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 800000, 278 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 810000, 301 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 820000, 324 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 830000, 348 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 840000, 372 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 850000, 396 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 860000, 421 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 870000, 446 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 885000, 473 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 900000, 501 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 915000, 529 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 930000, 558 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 945000, 588 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 960000, 617 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 975000, 649 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 990000, 682 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 990000, 682 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1005000, 716 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1020000, 751 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1035000, 786 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1040000, 802 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p5g_pvs9[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 126 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 147 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 168 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 189 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 211 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 233 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 780000, 256 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 790000, 278 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 800000, 301 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 810000, 324 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 820000, 348 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 830000, 372 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 840000, 396 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 850000, 421 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 860000, 446 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 875000, 473 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 890000, 501 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 905000, 529 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 920000, 558 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 935000, 588 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 950000, 617 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 965000, 649 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 980000, 682 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 980000, 682 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 995000, 716 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1010000, 751 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1025000, 786 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1030000, 802 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p5g_pvs10[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 126 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 147 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 168 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 189 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 211 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 233 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 256 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 780000, 278 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 790000, 301 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 800000, 324 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 810000, 348 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 820000, 372 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 830000, 396 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 840000, 421 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 850000, 446 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 865000, 473 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 880000, 501 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 895000, 529 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 910000, 558 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 925000, 588 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 940000, 617 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 955000, 649 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 970000, 682 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 970000, 682 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 985000, 716 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 1000000, 751 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1015000, 786 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1020000, 802 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p5g_pvs11[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 126 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 147 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 168 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 189 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 211 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 233 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 256 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 775000, 278 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 780000, 301 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 790000, 324 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 800000, 348 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 810000, 372 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 820000, 396 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 830000, 421 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 840000, 446 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 855000, 473 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 870000, 501 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 885000, 529 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 900000, 558 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 915000, 588 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 930000, 617 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 945000, 649 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 960000, 682 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 960000, 682 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 975000, 716 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 990000, 751 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 1005000, 786 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1010000, 802 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p5g_pvs12[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 126 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 147 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 168 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 189 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 211 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 233 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 256 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 775000, 278 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 775000, 301 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 780000, 324 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 790000, 348 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 800000, 372 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 810000, 396 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 820000, 421 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 830000, 446 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 845000, 473 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 860000, 501 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 875000, 529 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 890000, 558 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 905000, 588 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 920000, 617 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 935000, 649 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 950000, 682 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 950000, 682 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 965000, 716 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 980000, 751 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 995000, 786 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 1000000, 802 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p5g_pvs13[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 126 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 147 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 168 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 189 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 211 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 233 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 256 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 775000, 278 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 775000, 301 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 775000, 324 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 780000, 348 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 790000, 372 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 800000, 396 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 810000, 421 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 820000, 446 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 835000, 473 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 850000, 501 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 865000, 529 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 880000, 558 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 895000, 588 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 910000, 617 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 925000, 649 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 940000, 682 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 940000, 682 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 955000, 716 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 970000, 751 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 985000, 786 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 990000, 802 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p5g_pvs14[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 126 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 147 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 168 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 750000, 189 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 750000, 211 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 750000, 233 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 750000, 256 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 750000, 278 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 750000, 301 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 760000, 324 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 770000, 348 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 780000, 372 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 790000, 396 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 800000, 421 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 810000, 446 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 825000, 473 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 840000, 501 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 855000, 529 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 870000, 558 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 885000, 588 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 900000, 617 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 915000, 649 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 930000, 682 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 930000, 682 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 945000, 716 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 960000, 751 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 975000, 786 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 980000, 802 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p5g_pvs15[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 106 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 126 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 147 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 168 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 750000, 189 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 750000, 211 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 750000, 233 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 750000, 256 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 750000, 278 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 750000, 301 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 750000, 324 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 760000, 348 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 770000, 372 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 780000, 396 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 790000, 421 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 800000, 446 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 815000, 473 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 830000, 501 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 845000, 529 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 860000, 558 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 875000, 588 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 890000, 617 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 905000, 649 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 920000, 682 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 920000, 682 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 935000, 716 },
+ { 0, { 2342400, HFPLL, 1, 122 }, L2(19), 950000, 751 },
+ { 0, { 2419200, HFPLL, 1, 126 }, L2(19), 965000, 786 },
+ { 1, { 2457600, HFPLL, 1, 128 }, L2(19), 970000, 802 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p3g_pvs0[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 810000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 820000, 108 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 830000, 129 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 840000, 150 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 850000, 171 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 860000, 193 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 870000, 215 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 880000, 237 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 890000, 260 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 900000, 282 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 910000, 306 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 920000, 330 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 930000, 354 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 940000, 378 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 955000, 404 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 970000, 431 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 985000, 458 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 1000000, 486 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 1015000, 515 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1030000, 543 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1045000, 572 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1060000, 604 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1075000, 636 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1090000, 669 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1105000, 703 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1105000, 703 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1120000, 738 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p3g_pvs1[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 810000, 108 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 820000, 129 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 830000, 150 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 840000, 171 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 850000, 193 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 860000, 215 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 870000, 237 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 880000, 260 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 890000, 282 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 900000, 306 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 910000, 330 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 920000, 354 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 930000, 378 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 945000, 404 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 960000, 431 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 975000, 458 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 990000, 486 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 1005000, 515 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1020000, 543 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1035000, 572 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1050000, 604 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1065000, 636 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1080000, 669 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1095000, 703 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1095000, 703 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1110000, 738 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p3g_pvs2[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 108 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 810000, 129 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 820000, 150 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 830000, 171 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 840000, 193 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 850000, 215 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 860000, 237 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 870000, 260 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 880000, 282 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 890000, 306 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 900000, 330 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 910000, 354 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 920000, 378 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 935000, 404 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 950000, 431 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 965000, 458 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 980000, 486 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 995000, 515 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1010000, 543 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1025000, 572 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1040000, 604 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1055000, 636 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1070000, 669 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1085000, 703 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1085000, 703 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1100000, 738 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p3g_pvs3[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 108 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 129 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 810000, 150 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 820000, 171 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 830000, 193 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 840000, 215 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 850000, 237 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 860000, 260 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 870000, 282 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 880000, 306 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 890000, 330 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 900000, 354 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 910000, 378 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 925000, 404 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 940000, 431 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 955000, 458 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 970000, 486 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 985000, 515 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1000000, 543 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1015000, 572 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1030000, 604 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1045000, 636 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1060000, 669 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1075000, 703 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1075000, 703 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1090000, 738 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p3g_pvs4[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 108 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 129 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 150 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 810000, 171 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 820000, 193 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 830000, 215 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 840000, 237 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 850000, 260 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 860000, 282 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 870000, 306 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 880000, 330 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 890000, 354 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 900000, 378 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 915000, 404 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 930000, 431 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 945000, 458 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 960000, 486 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 975000, 515 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 990000, 543 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1005000, 572 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 604 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1035000, 636 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1050000, 669 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1065000, 703 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1065000, 703 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1080000, 738 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p3g_pvs5[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 108 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 129 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 150 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 171 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 810000, 193 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 820000, 215 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 830000, 237 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 840000, 260 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 850000, 282 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 860000, 306 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 870000, 330 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 880000, 354 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 890000, 378 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 905000, 404 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 920000, 431 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 935000, 458 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 950000, 486 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 965000, 515 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 980000, 543 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 995000, 572 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1010000, 604 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1025000, 636 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1040000, 669 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1055000, 703 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1055000, 703 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1070000, 738 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p3g_pvs6[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 108 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 129 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 780000, 150 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 790000, 171 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 800000, 193 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 810000, 215 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 820000, 237 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 830000, 260 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 840000, 282 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 850000, 306 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 860000, 330 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 870000, 354 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 880000, 378 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 895000, 404 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 431 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 925000, 458 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 940000, 486 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 955000, 515 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 970000, 543 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 985000, 572 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1000000, 604 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1015000, 636 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1030000, 669 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1045000, 703 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1045000, 703 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1060000, 738 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p3g_pvs7[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 108 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 129 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 150 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 780000, 171 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 790000, 193 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 800000, 215 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 810000, 237 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 820000, 260 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 830000, 282 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 840000, 306 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 850000, 330 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 860000, 354 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 870000, 378 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 885000, 404 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 900000, 431 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 915000, 458 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 930000, 486 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 945000, 515 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 960000, 543 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 975000, 572 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 990000, 604 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 636 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 669 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1035000, 703 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 703 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 738 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p3g_pvs8[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 108 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 129 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 150 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 171 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 780000, 193 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 790000, 215 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 237 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 810000, 260 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 820000, 282 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 830000, 306 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 840000, 330 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 850000, 354 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 860000, 378 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 875000, 404 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 890000, 431 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 905000, 458 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 920000, 486 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 935000, 515 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 950000, 543 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 965000, 572 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 980000, 604 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 995000, 636 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1010000, 669 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1025000, 703 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1025000, 703 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1040000, 738 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p3g_pvs9[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 108 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 129 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 150 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 171 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 193 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 780000, 215 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 790000, 237 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 800000, 260 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 810000, 282 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 820000, 306 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 830000, 330 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 840000, 354 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 850000, 378 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 865000, 404 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 880000, 431 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 895000, 458 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 910000, 486 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 925000, 515 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 940000, 543 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 955000, 572 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 970000, 604 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 985000, 636 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1000000, 669 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1015000, 703 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1015000, 703 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1030000, 738 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p3g_pvs10[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 108 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 129 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 150 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 171 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 193 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 215 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 780000, 237 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 790000, 260 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 800000, 282 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 810000, 306 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 820000, 330 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 830000, 354 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 840000, 378 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 855000, 404 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 431 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 885000, 458 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 900000, 486 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 915000, 515 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 930000, 543 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 945000, 572 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 960000, 604 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 975000, 636 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 990000, 669 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 1005000, 703 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1005000, 703 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1020000, 738 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p3g_pvs11[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 108 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 129 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 150 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 171 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 193 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 215 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 237 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 780000, 260 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 790000, 282 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 800000, 306 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 810000, 330 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 820000, 354 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 830000, 378 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 845000, 404 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 860000, 431 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 875000, 458 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 890000, 486 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 905000, 515 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 920000, 543 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 935000, 572 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 950000, 604 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 965000, 636 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 980000, 669 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 995000, 703 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 995000, 703 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1010000, 738 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p3g_pvs12[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 108 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 129 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 150 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 171 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 193 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 215 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 237 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 260 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 780000, 282 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 790000, 306 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 800000, 330 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 810000, 354 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 820000, 378 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 835000, 404 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 850000, 431 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 865000, 458 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 880000, 486 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 895000, 515 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 910000, 543 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 925000, 572 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 940000, 604 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 955000, 636 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 970000, 669 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 985000, 703 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 985000, 703 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 738 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p3g_pvs13[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 108 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 129 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 150 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 171 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 775000, 193 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 775000, 215 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 775000, 237 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 775000, 260 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 775000, 282 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 780000, 306 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 790000, 330 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 800000, 354 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 810000, 378 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 825000, 404 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 840000, 431 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 855000, 458 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 870000, 486 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 885000, 515 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 900000, 543 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 915000, 572 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 930000, 604 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 945000, 636 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 960000, 669 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 975000, 703 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 975000, 703 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 990000, 738 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p3g_pvs14[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 108 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 129 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 150 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 171 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 750000, 193 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 750000, 215 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 750000, 237 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 750000, 260 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 760000, 282 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 770000, 306 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 780000, 330 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 790000, 354 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 800000, 378 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 815000, 404 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 830000, 431 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 845000, 458 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 860000, 486 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 875000, 515 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 890000, 543 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 905000, 572 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 920000, 604 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 935000, 636 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 950000, 669 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 965000, 703 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 965000, 703 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 980000, 738 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level pro_rev1_2p3g_pvs15[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 76 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 87 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 108 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 129 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 150 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 171 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 750000, 193 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 750000, 215 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 750000, 237 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 750000, 260 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 750000, 282 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 760000, 306 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 770000, 330 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 780000, 354 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 790000, 378 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 805000, 404 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 820000, 431 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 835000, 458 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 850000, 486 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 865000, 515 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 880000, 543 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 895000, 572 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 910000, 604 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 925000, 636 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 940000, 669 },
+ { 0, { 2150400, HFPLL, 1, 112 }, L2(19), 955000, 703 },
+ { 0, { 2188800, HFPLL, 1, 114 }, L2(19), 955000, 703 },
+ { 1, { 2265600, HFPLL, 1, 118 }, L2(19), 970000, 738 },
+ { 0, { 0 } }
+};
+
+static struct pvs_table pvs_v1[NUM_PVS_REVS][NUM_SPEED_BINS][NUM_PVS] __initdata = {
/* 8974v1 1.7GHz Parts */
- [0][0] = { acpu_freq_tbl_v1_pvs0, sizeof(acpu_freq_tbl_v1_pvs0) },
- [0][1] = { acpu_freq_tbl_v1_pvs1, sizeof(acpu_freq_tbl_v1_pvs1) },
- [0][2] = { acpu_freq_tbl_v1_pvs2, sizeof(acpu_freq_tbl_v1_pvs2) },
- [0][3] = { acpu_freq_tbl_v1_pvs3, sizeof(acpu_freq_tbl_v1_pvs3) },
- [0][4] = { acpu_freq_tbl_v1_pvs4, sizeof(acpu_freq_tbl_v1_pvs4) },
+ [0][0][0] = { acpu_freq_tbl_v1_pvs0, sizeof(acpu_freq_tbl_v1_pvs0) },
+ [0][0][1] = { acpu_freq_tbl_v1_pvs1, sizeof(acpu_freq_tbl_v1_pvs1) },
+ [0][0][2] = { acpu_freq_tbl_v1_pvs2, sizeof(acpu_freq_tbl_v1_pvs2) },
+ [0][0][3] = { acpu_freq_tbl_v1_pvs3, sizeof(acpu_freq_tbl_v1_pvs3) },
+ [0][0][4] = { acpu_freq_tbl_v1_pvs4, sizeof(acpu_freq_tbl_v1_pvs4) },
};
-static struct pvs_table pvs_v2[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+static struct pvs_table pvs_v2[NUM_PVS_REVS][NUM_SPEED_BINS][NUM_PVS] __initdata = {
/* 8974v2 2.0GHz Parts */
- [0][0] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
- [0][1] = { acpu_freq_tbl_2g_pvs1, sizeof(acpu_freq_tbl_2g_pvs1) },
- [0][2] = { acpu_freq_tbl_2g_pvs2, sizeof(acpu_freq_tbl_2g_pvs2) },
- [0][3] = { acpu_freq_tbl_2g_pvs3, sizeof(acpu_freq_tbl_2g_pvs3) },
- [0][4] = { acpu_freq_tbl_2g_pvs4, sizeof(acpu_freq_tbl_2g_pvs4) },
- [0][5] = { acpu_freq_tbl_2g_pvs5, sizeof(acpu_freq_tbl_2g_pvs5) },
- [0][6] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
- [0][7] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
+ [0][0][0] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
+ [0][0][1] = { acpu_freq_tbl_2g_pvs1, sizeof(acpu_freq_tbl_2g_pvs1) },
+ [0][0][2] = { acpu_freq_tbl_2g_pvs2, sizeof(acpu_freq_tbl_2g_pvs2) },
+ [0][0][3] = { acpu_freq_tbl_2g_pvs3, sizeof(acpu_freq_tbl_2g_pvs3) },
+ [0][0][4] = { acpu_freq_tbl_2g_pvs4, sizeof(acpu_freq_tbl_2g_pvs4) },
+ [0][0][5] = { acpu_freq_tbl_2g_pvs5, sizeof(acpu_freq_tbl_2g_pvs5) },
+ [0][0][6] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
+ [0][0][7] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
/* 8974v2 2.3GHz Parts */
- [1][0] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
- [1][1] = { acpu_freq_tbl_2p3g_pvs1, sizeof(acpu_freq_tbl_2p3g_pvs1) },
- [1][2] = { acpu_freq_tbl_2p3g_pvs2, sizeof(acpu_freq_tbl_2p3g_pvs2) },
- [1][3] = { acpu_freq_tbl_2p3g_pvs3, sizeof(acpu_freq_tbl_2p3g_pvs3) },
- [1][4] = { acpu_freq_tbl_2p3g_pvs4, sizeof(acpu_freq_tbl_2p3g_pvs4) },
- [1][5] = { acpu_freq_tbl_2p3g_pvs5, sizeof(acpu_freq_tbl_2p3g_pvs5) },
- [1][6] = { acpu_freq_tbl_2p3g_pvs6, sizeof(acpu_freq_tbl_2p3g_pvs6) },
- [1][7] = { acpu_freq_tbl_2p3g_pvs6, sizeof(acpu_freq_tbl_2p3g_pvs6) },
+ [0][1][0] = { acpu_freq_tbl_2p3g_pvs0, sizeof(acpu_freq_tbl_2p3g_pvs0) },
+ [0][1][1] = { acpu_freq_tbl_2p3g_pvs1, sizeof(acpu_freq_tbl_2p3g_pvs1) },
+ [0][1][2] = { acpu_freq_tbl_2p3g_pvs2, sizeof(acpu_freq_tbl_2p3g_pvs2) },
+ [0][1][3] = { acpu_freq_tbl_2p3g_pvs3, sizeof(acpu_freq_tbl_2p3g_pvs3) },
+ [0][1][4] = { acpu_freq_tbl_2p3g_pvs4, sizeof(acpu_freq_tbl_2p3g_pvs4) },
+ [0][1][5] = { acpu_freq_tbl_2p3g_pvs5, sizeof(acpu_freq_tbl_2p3g_pvs5) },
+ [0][1][6] = { acpu_freq_tbl_2p3g_pvs6, sizeof(acpu_freq_tbl_2p3g_pvs6) },
+ [0][1][7] = { acpu_freq_tbl_2p3g_pvs6, sizeof(acpu_freq_tbl_2p3g_pvs6) },
/* 8974v2 2.2GHz Parts */
- [2][0] = { acpu_freq_tbl_2p2g_pvs0, sizeof(acpu_freq_tbl_2p2g_pvs0) },
- [2][1] = { acpu_freq_tbl_2p2g_pvs1, sizeof(acpu_freq_tbl_2p2g_pvs1) },
- [2][2] = { acpu_freq_tbl_2p2g_pvs2, sizeof(acpu_freq_tbl_2p2g_pvs2) },
- [2][3] = { acpu_freq_tbl_2p2g_pvs3, sizeof(acpu_freq_tbl_2p2g_pvs3) },
- [2][4] = { acpu_freq_tbl_2p2g_pvs4, sizeof(acpu_freq_tbl_2p2g_pvs4) },
- [2][5] = { acpu_freq_tbl_2p2g_pvs5, sizeof(acpu_freq_tbl_2p2g_pvs5) },
- [2][6] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
- [2][7] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
+ [0][2][0] = { acpu_freq_tbl_2p2g_pvs0, sizeof(acpu_freq_tbl_2p2g_pvs0) },
+ [0][2][1] = { acpu_freq_tbl_2p2g_pvs1, sizeof(acpu_freq_tbl_2p2g_pvs1) },
+ [0][2][2] = { acpu_freq_tbl_2p2g_pvs2, sizeof(acpu_freq_tbl_2p2g_pvs2) },
+ [0][2][3] = { acpu_freq_tbl_2p2g_pvs3, sizeof(acpu_freq_tbl_2p2g_pvs3) },
+ [0][2][4] = { acpu_freq_tbl_2p2g_pvs4, sizeof(acpu_freq_tbl_2p2g_pvs4) },
+ [0][2][5] = { acpu_freq_tbl_2p2g_pvs5, sizeof(acpu_freq_tbl_2p2g_pvs5) },
+ [0][2][6] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
+ [0][2][7] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
};
-static struct pvs_table pvs_pro[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+static struct pvs_table pvs_pro[NUM_PVS_REVS][NUM_SPEED_BINS][NUM_PVS] __initdata = {
/* 2.0 GHz is not used on 8974Pro */
- [0][0] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
- [0][1] = { acpu_freq_tbl_2g_pvs1, sizeof(acpu_freq_tbl_2g_pvs1) },
- [0][2] = { acpu_freq_tbl_2g_pvs2, sizeof(acpu_freq_tbl_2g_pvs2) },
- [0][3] = { acpu_freq_tbl_2g_pvs3, sizeof(acpu_freq_tbl_2g_pvs3) },
- [0][4] = { acpu_freq_tbl_2g_pvs4, sizeof(acpu_freq_tbl_2g_pvs4) },
- [0][5] = { acpu_freq_tbl_2g_pvs5, sizeof(acpu_freq_tbl_2g_pvs5) },
- [0][6] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
- [0][7] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
+ [0][0][0] = { acpu_freq_tbl_2g_pvs0, sizeof(acpu_freq_tbl_2g_pvs0) },
+ [0][0][1] = { acpu_freq_tbl_2g_pvs1, sizeof(acpu_freq_tbl_2g_pvs1) },
+ [0][0][2] = { acpu_freq_tbl_2g_pvs2, sizeof(acpu_freq_tbl_2g_pvs2) },
+ [0][0][3] = { acpu_freq_tbl_2g_pvs3, sizeof(acpu_freq_tbl_2g_pvs3) },
+ [0][0][4] = { acpu_freq_tbl_2g_pvs4, sizeof(acpu_freq_tbl_2g_pvs4) },
+ [0][0][5] = { acpu_freq_tbl_2g_pvs5, sizeof(acpu_freq_tbl_2g_pvs5) },
+ [0][0][6] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
+ [0][0][7] = { acpu_freq_tbl_2g_pvs6, sizeof(acpu_freq_tbl_2g_pvs6) },
/* 8974Pro AB 2.3GHz */
- [1][0] = { acpu_ftbl_pro_2p3g_pvs0, sizeof(acpu_ftbl_pro_2p3g_pvs0) },
- [1][1] = { acpu_ftbl_pro_2p3g_pvs1, sizeof(acpu_ftbl_pro_2p3g_pvs1) },
- [1][2] = { acpu_ftbl_pro_2p3g_pvs2, sizeof(acpu_ftbl_pro_2p3g_pvs2) },
- [1][3] = { acpu_ftbl_pro_2p3g_pvs3, sizeof(acpu_ftbl_pro_2p3g_pvs3) },
- [1][4] = { acpu_ftbl_pro_2p3g_pvs4, sizeof(acpu_ftbl_pro_2p3g_pvs4) },
- [1][5] = { acpu_ftbl_pro_2p3g_pvs5, sizeof(acpu_ftbl_pro_2p3g_pvs5) },
- [1][6] = { acpu_ftbl_pro_2p3g_pvs6, sizeof(acpu_ftbl_pro_2p3g_pvs6) },
- [1][7] = { acpu_ftbl_pro_2p3g_pvs6, sizeof(acpu_ftbl_pro_2p3g_pvs6) },
+ [0][1][0] = { pro_rev0_2p3g_pvs0, sizeof(pro_rev0_2p3g_pvs0) },
+ [0][1][1] = { pro_rev0_2p3g_pvs1, sizeof(pro_rev0_2p3g_pvs1) },
+ [0][1][2] = { pro_rev0_2p3g_pvs2, sizeof(pro_rev0_2p3g_pvs2) },
+ [0][1][3] = { pro_rev0_2p3g_pvs3, sizeof(pro_rev0_2p3g_pvs3) },
+ [0][1][4] = { pro_rev0_2p3g_pvs4, sizeof(pro_rev0_2p3g_pvs4) },
+ [0][1][5] = { pro_rev0_2p3g_pvs5, sizeof(pro_rev0_2p3g_pvs5) },
+ [0][1][6] = { pro_rev0_2p3g_pvs6, sizeof(pro_rev0_2p3g_pvs6) },
+ [0][1][7] = { pro_rev0_2p3g_pvs6, sizeof(pro_rev0_2p3g_pvs6) },
/* 2.2GHz is not used on 8974Pro */
- [2][0] = { acpu_freq_tbl_2p2g_pvs0, sizeof(acpu_freq_tbl_2p2g_pvs0) },
- [2][1] = { acpu_freq_tbl_2p2g_pvs1, sizeof(acpu_freq_tbl_2p2g_pvs1) },
- [2][2] = { acpu_freq_tbl_2p2g_pvs2, sizeof(acpu_freq_tbl_2p2g_pvs2) },
- [2][3] = { acpu_freq_tbl_2p2g_pvs3, sizeof(acpu_freq_tbl_2p2g_pvs3) },
- [2][4] = { acpu_freq_tbl_2p2g_pvs4, sizeof(acpu_freq_tbl_2p2g_pvs4) },
- [2][5] = { acpu_freq_tbl_2p2g_pvs5, sizeof(acpu_freq_tbl_2p2g_pvs5) },
- [2][6] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
- [2][7] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
+ [0][2][0] = { acpu_freq_tbl_2p2g_pvs0, sizeof(acpu_freq_tbl_2p2g_pvs0) },
+ [0][2][1] = { acpu_freq_tbl_2p2g_pvs1, sizeof(acpu_freq_tbl_2p2g_pvs1) },
+ [0][2][2] = { acpu_freq_tbl_2p2g_pvs2, sizeof(acpu_freq_tbl_2p2g_pvs2) },
+ [0][2][3] = { acpu_freq_tbl_2p2g_pvs3, sizeof(acpu_freq_tbl_2p2g_pvs3) },
+ [0][2][4] = { acpu_freq_tbl_2p2g_pvs4, sizeof(acpu_freq_tbl_2p2g_pvs4) },
+ [0][2][5] = { acpu_freq_tbl_2p2g_pvs5, sizeof(acpu_freq_tbl_2p2g_pvs5) },
+ [0][2][6] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
+ [0][2][7] = { acpu_freq_tbl_2p2g_pvs6, sizeof(acpu_freq_tbl_2p2g_pvs6) },
/* 8974Pro AC 2.5GHz */
- [3][0] = { acpu_ftbl_pro_2p5g_pvs0, sizeof(acpu_ftbl_pro_2p5g_pvs0) },
- [3][1] = { acpu_ftbl_pro_2p5g_pvs1, sizeof(acpu_ftbl_pro_2p5g_pvs1) },
- [3][2] = { acpu_ftbl_pro_2p5g_pvs2, sizeof(acpu_ftbl_pro_2p5g_pvs2) },
- [3][3] = { acpu_ftbl_pro_2p5g_pvs3, sizeof(acpu_ftbl_pro_2p5g_pvs3) },
- [3][4] = { acpu_ftbl_pro_2p5g_pvs4, sizeof(acpu_ftbl_pro_2p5g_pvs4) },
- [3][5] = { acpu_ftbl_pro_2p5g_pvs5, sizeof(acpu_ftbl_pro_2p5g_pvs5) },
- [3][6] = { acpu_ftbl_pro_2p5g_pvs6, sizeof(acpu_ftbl_pro_2p5g_pvs6) },
- [3][7] = { acpu_ftbl_pro_2p5g_pvs6, sizeof(acpu_ftbl_pro_2p5g_pvs6) },
+ [0][3][0] = { pro_rev0_2p5g_pvs0, sizeof(pro_rev0_2p5g_pvs0) },
+ [0][3][1] = { pro_rev0_2p5g_pvs1, sizeof(pro_rev0_2p5g_pvs1) },
+ [0][3][2] = { pro_rev0_2p5g_pvs2, sizeof(pro_rev0_2p5g_pvs2) },
+ [0][3][3] = { pro_rev0_2p5g_pvs3, sizeof(pro_rev0_2p5g_pvs3) },
+ [0][3][4] = { pro_rev0_2p5g_pvs4, sizeof(pro_rev0_2p5g_pvs4) },
+ [0][3][5] = { pro_rev0_2p5g_pvs5, sizeof(pro_rev0_2p5g_pvs5) },
+ [0][3][6] = { pro_rev0_2p5g_pvs6, sizeof(pro_rev0_2p5g_pvs6) },
+ [0][3][7] = { pro_rev0_2p5g_pvs6, sizeof(pro_rev0_2p5g_pvs6) },
+
+ /* 8974Pro AB 2.3GHz */
+ [1][1][0] = { pro_rev1_2p3g_pvs0, sizeof(pro_rev1_2p3g_pvs0) },
+ [1][1][1] = { pro_rev1_2p3g_pvs1, sizeof(pro_rev1_2p3g_pvs1) },
+ [1][1][2] = { pro_rev1_2p3g_pvs2, sizeof(pro_rev1_2p3g_pvs2) },
+ [1][1][3] = { pro_rev1_2p3g_pvs3, sizeof(pro_rev1_2p3g_pvs3) },
+ [1][1][4] = { pro_rev1_2p3g_pvs4, sizeof(pro_rev1_2p3g_pvs4) },
+ [1][1][5] = { pro_rev1_2p3g_pvs5, sizeof(pro_rev1_2p3g_pvs5) },
+ [1][1][6] = { pro_rev1_2p3g_pvs6, sizeof(pro_rev1_2p3g_pvs6) },
+ [1][1][7] = { pro_rev1_2p3g_pvs7, sizeof(pro_rev1_2p3g_pvs7) },
+ [1][1][8] = { pro_rev1_2p3g_pvs8, sizeof(pro_rev1_2p3g_pvs8) },
+ [1][1][9] = { pro_rev1_2p3g_pvs9, sizeof(pro_rev1_2p3g_pvs9) },
+ [1][1][10] = { pro_rev1_2p3g_pvs10, sizeof(pro_rev1_2p3g_pvs10) },
+ [1][1][11] = { pro_rev1_2p3g_pvs11, sizeof(pro_rev1_2p3g_pvs11) },
+ [1][1][12] = { pro_rev1_2p3g_pvs12, sizeof(pro_rev1_2p3g_pvs12) },
+ [1][1][13] = { pro_rev1_2p3g_pvs13, sizeof(pro_rev1_2p3g_pvs13) },
+ [1][1][14] = { pro_rev1_2p3g_pvs14, sizeof(pro_rev1_2p3g_pvs14) },
+ [1][1][15] = { pro_rev1_2p3g_pvs15, sizeof(pro_rev1_2p3g_pvs15) },
+
+ /* 8974Pro AC 2.5GHz */
+ [1][3][0] = { pro_rev1_2p5g_pvs0, sizeof(pro_rev1_2p5g_pvs0) },
+ [1][3][1] = { pro_rev1_2p5g_pvs1, sizeof(pro_rev1_2p5g_pvs1) },
+ [1][3][2] = { pro_rev1_2p5g_pvs2, sizeof(pro_rev1_2p5g_pvs2) },
+ [1][3][3] = { pro_rev1_2p5g_pvs3, sizeof(pro_rev1_2p5g_pvs3) },
+ [1][3][4] = { pro_rev1_2p5g_pvs4, sizeof(pro_rev1_2p5g_pvs4) },
+ [1][3][5] = { pro_rev1_2p5g_pvs5, sizeof(pro_rev1_2p5g_pvs5) },
+ [1][3][6] = { pro_rev1_2p5g_pvs6, sizeof(pro_rev1_2p5g_pvs6) },
+ [1][3][7] = { pro_rev1_2p5g_pvs7, sizeof(pro_rev1_2p5g_pvs7) },
+ [1][3][8] = { pro_rev1_2p5g_pvs8, sizeof(pro_rev1_2p5g_pvs8) },
+ [1][3][9] = { pro_rev1_2p5g_pvs9, sizeof(pro_rev1_2p5g_pvs9) },
+ [1][3][10] = { pro_rev1_2p5g_pvs10, sizeof(pro_rev1_2p5g_pvs10) },
+ [1][3][11] = { pro_rev1_2p5g_pvs11, sizeof(pro_rev1_2p5g_pvs11) },
+ [1][3][12] = { pro_rev1_2p5g_pvs12, sizeof(pro_rev1_2p5g_pvs12) },
+ [1][3][13] = { pro_rev1_2p5g_pvs13, sizeof(pro_rev1_2p5g_pvs13) },
+ [1][3][14] = { pro_rev1_2p5g_pvs14, sizeof(pro_rev1_2p5g_pvs14) },
+ [1][3][15] = { pro_rev1_2p5g_pvs15, sizeof(pro_rev1_2p5g_pvs15) },
};
static struct msm_bus_scale_pdata bus_scale_data __initdata = {
@@ -1470,12 +2592,15 @@
{ }
};
struct acpu_level *l;
- int s, p;
+ int s, p, r;
- for (s = 0; s < NUM_SPEED_BINS; s++)
- for (p = 0; p < NUM_PVS; p++)
- for (l = pvs_v1[s][p].table; l && l->speed.khz; l++)
- l->l2_level = l->l2_level > 5 ? 1 : 0;
+ for (r = 0; r < NUM_PVS_REVS; r++)
+ for (s = 0; s < NUM_SPEED_BINS; s++)
+ for (p = 0; p < NUM_PVS; p++) {
+ l = pvs_v1[r][s][p].table;
+ for (; l && l->speed.khz; l++)
+ l->l2_level = l->l2_level > 5 ? 1 : 0;
+ }
acpuclk_8974_params.l2_freq_tbl = resticted_l2_tbl;
acpuclk_8974_params.l2_freq_tbl_size = sizeof(resticted_l2_tbl);
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index 0479844..cf3fac0 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -1092,15 +1092,17 @@
pte_efuse = readl_relaxed(base);
redundant_sel = (pte_efuse >> 24) & 0x7;
+ bin->pvs_rev = (pte_efuse >> 4) & 0x3;
bin->speed = pte_efuse & 0x7;
- bin->pvs = (pte_efuse >> 6) & 0x7;
+ /* PVS number is in bits 31, 8, 7, 6 */
+ bin->pvs = ((pte_efuse >> 28) & 0x8) | ((pte_efuse >> 6) & 0x7);
switch (redundant_sel) {
case 1:
- bin->speed = (pte_efuse >> 27) & 0x7;
+ bin->speed = (pte_efuse >> 27) & 0xF;
break;
case 2:
- bin->pvs = (pte_efuse >> 27) & 0x7;
+ bin->pvs = (pte_efuse >> 27) & 0xF;
break;
}
bin->speed_valid = true;
@@ -1136,13 +1138,15 @@
if (bin.pvs_valid) {
drv.pvs_bin = bin.pvs;
dev_info(drv.dev, "ACPU PVS: %d\n", drv.pvs_bin);
+ drv.pvs_rev = bin.pvs_rev;
+ dev_info(drv.dev, "ACPU PVS REVISION: %d\n", drv.pvs_rev);
} else {
drv.pvs_bin = 0;
dev_warn(drv.dev, "ACPU PVS: Defaulting to %d\n",
drv.pvs_bin);
}
- return ¶ms->pvs_tables[drv.speed_bin][drv.pvs_bin];
+ return ¶ms->pvs_tables[drv.pvs_rev][drv.speed_bin][drv.pvs_bin];
}
static void __init drv_data_init(struct device *dev,
diff --git a/arch/arm/mach-msm/acpuclock-krait.h b/arch/arm/mach-msm/acpuclock-krait.h
index f02af98..4eff45d 100644
--- a/arch/arm/mach-msm/acpuclock-krait.h
+++ b/arch/arm/mach-msm/acpuclock-krait.h
@@ -50,10 +50,15 @@
PVS_NOMINAL = 1,
PVS_FAST = 3,
PVS_FASTER = 4,
- NUM_PVS = 8
+ NUM_PVS = 16
};
/**
+ * The maximum number of PVS revisions.
+ */
+#define NUM_PVS_REVS (4)
+
+/**
* The maximum number of speed bins.
*/
#define NUM_SPEED_BINS (16)
@@ -236,12 +241,14 @@
* @pvs_valid: @pvs field is valid
* @speed: Speed bin ID
* @pvs: PVS bin ID
+ * @pvs_rev: PVS revision ID
*/
struct bin_info {
bool speed_valid;
bool pvs_valid;
int speed;
int pvs;
+ int pvs_rev;
};
/**
@@ -273,7 +280,7 @@
struct scalable *scalable;
size_t scalable_size;
struct hfpll_data *hfpll_data;
- struct pvs_table (*pvs_tables)[NUM_PVS];
+ struct pvs_table (*pvs_tables)[NUM_SPEED_BINS][NUM_PVS];
struct l2_level *l2_freq_tbl;
size_t l2_freq_tbl_size;
phys_addr_t pte_efuse_phys;
@@ -293,6 +300,7 @@
* @boost_uv: Voltage boost amount
* @speed_bin: Speed bin ID.
* @pvs_bin: PVS bin ID.
+ * @pvs_bin: PVS revision ID.
* @dev: Device.
*/
struct drv_data {
@@ -305,6 +313,7 @@
int boost_uv;
int speed_bin;
int pvs_bin;
+ int pvs_rev;
struct device *dev;
};
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index 5dd9bab..4dcbc3a 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -18,6 +18,38 @@
#include <mach/gpiomux.h>
#include <mach/socinfo.h>
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+static struct gpiomux_setting hsic_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+ .dir = GPIOMUX_OUT_LOW,
+};
+
+static struct gpiomux_setting hsic_act_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_16MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct msm_gpiomux_config msm_hsic_configs[] = {
+ {
+ .gpio = 115, /* HSIC_STROBE */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hsic_act_cfg,
+ [GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
+ },
+ },
+ {
+ .gpio = 116, /* HSIC_DATA */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &hsic_act_cfg,
+ [GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
+ },
+ },
+};
+#endif
+
#define KS8851_IRQ_GPIO 115
#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
@@ -824,4 +856,17 @@
ARRAY_SIZE(usb_otg_sw_configs));
msm_gpiomux_sdc3_install();
+
+ /*
+ * HSIC STROBE gpio is also used by the ethernet. Install HSIC
+ * gpio mux config only when HSIC is enabled. HSIC config will
+ * be disabled when ethernet config is enabled.
+ */
+#ifdef CONFIG_USB_EHCI_MSM_HSIC
+ if (machine_is_msm8926()) {
+ msm_hsic_configs[0].gpio = 119; /* STROBE */
+ msm_hsic_configs[1].gpio = 120; /* DATA */
+ }
+ msm_gpiomux_install(msm_hsic_configs, ARRAY_SIZE(msm_hsic_configs));
+#endif
}
diff --git a/arch/arm/mach-msm/board-8610-gpiomux.c b/arch/arm/mach-msm/board-8610-gpiomux.c
index 87794c4..b5ea3a5 100644
--- a/arch/arm/mach-msm/board-8610-gpiomux.c
+++ b/arch/arm/mach-msm/board-8610-gpiomux.c
@@ -41,6 +41,17 @@
.pull = GPIOMUX_PULL_NONE,
};
+static struct gpiomux_setting gpio_nfc_config = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+static struct gpiomux_setting gpio_nfc_sus_config = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
static struct gpiomux_setting atmel_int_act_cfg = {
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_8MA,
@@ -232,6 +243,13 @@
[GPIOMUX_SUSPENDED] = &gpio_cam_i2c_config,
},
},
+ {
+ .gpio = 78, /* NFC CLK */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &gpio_nfc_config,
+ [GPIOMUX_SUSPENDED] = &gpio_nfc_sus_config,
+ },
+ },
};
static struct msm_gpiomux_config msm_atmel_configs[] __initdata = {
@@ -557,13 +575,6 @@
},
},
{
- .gpio = 78, /*ETH_INT */
- .settings = {
- [GPIOMUX_ACTIVE] = &interrupt_gpio_active,
- [GPIOMUX_SUSPENDED] = &interrupt_gpio_suspend_pullup,
- },
- },
- {
.gpio = 80, /*ALSP_INT */
.settings = {
[GPIOMUX_ACTIVE] = &interrupt_gpio_active,
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 1999379..5b057a8e 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -238,12 +238,6 @@
DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_a1_pin, cxo_a1_a_pin, A1_ID);
DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_a2_pin, cxo_a2_a_pin, A2_ID);
-struct measure_mux_entry {
- struct clk *c;
- int base;
- u32 debug_mux;
-};
-
static struct branch_clk oxilicx_axi_clk;
#define MSS_DEBUG_CLOCK_CTL 0x0078
@@ -328,6 +322,7 @@
#define CAMSS_VFE_VFE_AXI_CBCR (0x36BC)
#define CAMSS_CSI_VFE0_BCR (0x3700)
#define CAMSS_CSI_VFE0_CBCR (0x3704)
+#define CAMSS_MICRO_BCR (0x3490)
#define OXILI_GFX3D_CBCR (0x4028)
#define OXILICX_BCR (0x4030)
#define OXILICX_AXI_CBCR (0x4038)
@@ -1558,6 +1553,13 @@
},
};
+#ifdef CONFIG_DEBUG_FS
+struct measure_mux_entry {
+ struct clk *c;
+ int base;
+ u32 debug_mux;
+};
+
static struct measure_mux_entry measure_mux_GCC[] = {
{ &gcc_mss_cfg_ahb_clk.c, GCC_BASE, 0x0030 },
{ &gcc_mss_q6_bimc_axi_clk.c, GCC_BASE, 0x0031 },
@@ -1613,6 +1615,7 @@
{ &bimc_clk.c, GCC_BASE, 0x155},
{ &dummy_clk, N_BASES, 0x0000},
};
+#endif /* CONFIG_DEBUG_FS */
static struct pll_vote_clk mmpll0_pll = {
.en_reg = (void __iomem *)MMSS_PLL_VOTE_APCS,
@@ -2365,6 +2368,7 @@
static struct branch_clk camss_micro_ahb_clk = {
.cbcr_reg = CAMSS_MICRO_AHB_CBCR,
.has_sibling = 1,
+ .bcr_reg = CAMSS_MICRO_BCR,
.base = &virt_bases[MMSS_BASE],
.c = {
.dbg_name = "camss_micro_ahb_clk",
@@ -2684,6 +2688,7 @@
},
};
+#ifdef CONFIG_DEBUG_FS
static struct measure_mux_entry measure_mux_MMSS[] = {
{ &mmss_mmssnoc_bto_ahb_clk.c, MMSS_BASE, 0x0002 },
{ &mmss_misc_ahb_clk.c, MMSS_BASE, 0x0003 },
@@ -2736,6 +2741,7 @@
{ &mmssnoc_ahb_clk.c, MMSS_BASE, 0x0001 },
{&dummy_clk, N_BASES, 0x0000},
};
+#endif /* CONFIG_DEBUG_FS */
static struct branch_clk q6ss_ahb_lfabif_clk = {
.cbcr_reg = Q6SS_AHB_LFABIF_CBCR,
@@ -2771,12 +2777,14 @@
},
};
+#ifdef CONFIG_DEBUG_FS
static struct measure_mux_entry measure_mux_LPASS[] = {
{ &q6ss_ahbm_clk.c, LPASS_BASE, 0x001d },
{ &q6ss_ahb_lfabif_clk.c, LPASS_BASE, 0x001e },
{ &q6ss_xo_clk.c, LPASS_BASE, 0x002b },
{&dummy_clk, N_BASES, 0x0000},
};
+#endif /* CONFIG_DEBUG_FS */
static DEFINE_CLK_MEASURE(apc0_m_clk);
@@ -2785,6 +2793,7 @@
static DEFINE_CLK_MEASURE(apc3_m_clk);
static DEFINE_CLK_MEASURE(l2_m_clk);
+#ifdef CONFIG_DEBUG_FS
static struct measure_mux_entry measure_mux_APSS[] = {
{&apc0_m_clk, APCS_BASE, 0x00010},
{&apc1_m_clk, APCS_BASE, 0x00114},
@@ -2793,6 +2802,7 @@
{&l2_m_clk, APCS_BASE, 0x01000},
{&dummy_clk, N_BASES, 0x0000}
};
+#endif /* CONFIG_DEBUG_FS */
#define APCS_SH_PLL_MODE (0x000)
#define APCS_SH_PLL_L_VAL (0x004)
@@ -3207,6 +3217,11 @@
CLK_LOOKUP("core_clk", qdss_clk.c, "fc342000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc343000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc344000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc348000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc34d000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc350000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc354000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc358000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fd828018.hwevent"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc322000.tmc"),
@@ -3241,6 +3256,11 @@
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc342000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc343000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc344000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc348000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34d000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc350000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc354000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc358000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fd828018.hwevent"),
CLK_LOOKUP("core_mmss_clk", mmss_misc_ahb_clk.c, "fd828018.hwevent"),
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index 33dcd9f..45a6b89 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -1351,8 +1351,6 @@
.cbcr_reg = LPASS_Q6_AXI_CBCR,
.has_sibling = 1,
.base = &virt_bases[GCC_BASE],
- /* FIXME: Remove this once simulation is fixed. */
- .halt_check = DELAY,
.c = {
.dbg_name = "gcc_lpass_q6_axi_clk",
.ops = &clk_ops_branch,
@@ -1893,14 +1891,10 @@
.cbcr_reg = BIMC_GFX_CBCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
- /* FIXME: Remove this once simulation is fixed. */
- .halt_check = DELAY,
.c = {
.dbg_name = "bimc_gfx_clk",
.ops = &clk_ops_branch,
CLK_INIT(bimc_gfx_clk.c),
- /* FIXME: Remove once kgsl votes on the depends clock. */
- .depends = &gcc_bimc_smmu_clk.c,
},
};
@@ -2267,8 +2261,6 @@
static struct branch_clk mdp_axi_clk = {
.cbcr_reg = MDP_AXI_CBCR,
.base = &virt_bases[MMSS_BASE],
- /* FIXME: Remove this once simulation is fixed. */
- .halt_check = DELAY,
.c = {
.parent = &mdp_axi_clk_src.c,
.dbg_name = "mdp_axi_clk",
@@ -2416,8 +2408,6 @@
.bcr_reg = VFE_AXI_BCR,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
- /* FIXME: Remove this once simulation is fixed. */
- .halt_check = DELAY,
.c = {
.parent = &axi_clk_src.c,
.dbg_name = "vfe_axi_clk",
@@ -2831,6 +2821,10 @@
CLK_LOOKUP("core_clk", qdss_clk.c, "fc352000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc353000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc354000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc335000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc338000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc33c000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc360000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc34c000.jtagmm"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc34d000.jtagmm"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc34e000.jtagmm"),
@@ -2865,6 +2859,10 @@
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc352000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc353000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc354000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc335000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc338000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc33c000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc360000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34c000.jtagmm"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34d000.jtagmm"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34e000.jtagmm"),
@@ -2923,7 +2921,7 @@
CLK_LOOKUP("core_clk", gcc_ce1_clk.c, ""),
CLK_LOOKUP("iface_clk", gcc_copss_smmu_ahb_clk.c, ""),
CLK_LOOKUP("iface_clk", gcc_lpss_smmu_ahb_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_gp1_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_gp1_clk.c, "0-000e"),
CLK_LOOKUP("core_clk", gcc_gp2_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_gp3_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_lpass_q6_axi_clk.c, ""),
@@ -3022,12 +3020,14 @@
/* MM sensor clocks */
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6-006f"),
+ CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6-0034"),
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6-007d"),
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6-006d"),
CLK_LOOKUP("cam_src_clk", mclk1_clk_src.c, "6-0078"),
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6-0020"),
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6-006a"),
CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-006f"),
+ CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-0034"),
CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-007d"),
CLK_LOOKUP("cam_clk", mclk0_clk.c, "6-006d"),
CLK_LOOKUP("cam_clk", mclk1_clk.c, "6-0078"),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 654dbd3..ca7302a 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -777,7 +777,7 @@
.base = &virt_bases[GCC_BASE],
.c = {
.parent = &cxo_clk_src.c,
- .rate = 800000000,
+ .rate = 768000000,
.dbg_name = "gpll4_clk_src",
.ops = &clk_ops_pll_vote,
CLK_INIT(gpll4_clk_src.c),
@@ -1545,6 +1545,24 @@
},
};
+/* This table is for MSM8974Pro AC SDCC1 */
+static struct clk_freq_tbl ftbl_gcc_sdcc1_apps_clk_ac[] = {
+ F( 144000, cxo, 16, 3, 25),
+ F( 400000, cxo, 12, 1, 4),
+ F( 20000000, gpll0, 15, 1, 2),
+ F( 25000000, gpll0, 12, 1, 2),
+ F( 50000000, gpll0, 12, 0, 0),
+ F(100000000, gpll0, 6, 0, 0),
+ F(192000000, gpll4, 4, 0, 0),
+ F(384000000, gpll4, 2, 0, 0),
+ F_END
+};
+
+/*
+ * This table is for:
+ * 1) SDCC[1-4] on MSM8974Pro AB, MSM8974 v2 and before
+ * 2) SDCC[2-4] on MSM8974Pro AC
+ */
static struct clk_freq_tbl ftbl_gcc_sdcc1_4_apps_clk[] = {
F( 144000, cxo, 16, 3, 25),
F( 400000, cxo, 12, 1, 4),
@@ -1553,7 +1571,6 @@
F( 50000000, gpll0, 12, 0, 0),
F(100000000, gpll0, 6, 0, 0),
F(200000000, gpll0, 3, 0, 0),
- F(400000000, gpll4, 2, 0, 0),
F_END
};
@@ -3909,6 +3926,7 @@
static struct branch_clk camss_micro_ahb_clk = {
.cbcr_reg = CAMSS_MICRO_AHB_CBCR,
.has_sibling = 1,
+ .bcr_reg = CAMSS_MICRO_BCR,
.base = &virt_bases[MMSS_BASE],
.c = {
.dbg_name = "camss_micro_ahb_clk",
@@ -5208,26 +5226,56 @@
/* ISPIF clocks */
CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
- "fda0a000.qcom,ispif"),
+ "fda0a000.qcom,ispif"),
- CLK_LOOKUP("vfe0_clk_src", vfe0_clk_src.c, "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("vfe0_clk_src", vfe0_clk_src.c,
+ "fda0a000.qcom,ispif"),
CLK_LOOKUP("camss_vfe_vfe0_clk", camss_vfe_vfe0_clk.c,
- "fda0a000.qcom,ispif"),
+ "fda0a000.qcom,ispif"),
CLK_LOOKUP("camss_csi_vfe0_clk", camss_csi_vfe0_clk.c,
- "fda0a000.qcom,ispif"),
- CLK_LOOKUP("vfe1_clk_src", vfe1_clk_src.c, "fda0a000.qcom,ispif"),
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("vfe1_clk_src", vfe1_clk_src.c,
+ "fda0a000.qcom,ispif"),
CLK_LOOKUP("camss_vfe_vfe1_clk", camss_vfe_vfe1_clk.c,
- "fda0a000.qcom,ispif"),
+ "fda0a000.qcom,ispif"),
CLK_LOOKUP("camss_csi_vfe1_clk", camss_csi_vfe1_clk.c,
- "fda0a000.qcom,ispif"),
+ "fda0a000.qcom,ispif"),
+
CLK_LOOKUP("csi0_src_clk", csi0_clk_src.c,
- "fda0a000.qcom,ispif"),
+ "fda0a000.qcom,ispif"),
CLK_LOOKUP("csi0_clk", camss_csi0_clk.c,
- "fda0a000.qcom,ispif"),
+ "fda0a000.qcom,ispif"),
CLK_LOOKUP("csi0_pix_clk", camss_csi0pix_clk.c,
- "fda0a000.qcom,ispif"),
+ "fda0a000.qcom,ispif"),
CLK_LOOKUP("csi0_rdi_clk", camss_csi0rdi_clk.c,
- "fda0a000.qcom,ispif"),
+ "fda0a000.qcom,ispif"),
+
+ CLK_LOOKUP("csi1_src_clk", csi1_clk_src.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi1_clk", camss_csi1_clk.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi1_pix_clk", camss_csi1pix_clk.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi1_rdi_clk", camss_csi1rdi_clk.c,
+ "fda0a000.qcom,ispif"),
+
+ CLK_LOOKUP("csi2_src_clk", csi2_clk_src.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi2_clk", camss_csi2_clk.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi2_pix_clk", camss_csi2pix_clk.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi2_rdi_clk", camss_csi2rdi_clk.c,
+ "fda0a000.qcom,ispif"),
+
+ CLK_LOOKUP("csi3_src_clk", csi3_clk_src.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi3_clk", camss_csi3_clk.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi3_pix_clk", camss_csi3pix_clk.c,
+ "fda0a000.qcom,ispif"),
+ CLK_LOOKUP("csi3_rdi_clk", camss_csi3rdi_clk.c,
+ "fda0a000.qcom,ispif"),
/*VFE clocks*/
CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
@@ -5413,6 +5461,11 @@
CLK_LOOKUP("core_clk", qdss_clk.c, "fc342000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc343000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc344000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc348000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc34d000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc350000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc354000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc358000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fdf30018.hwevent"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc322000.tmc"),
@@ -5443,6 +5496,11 @@
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc342000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc343000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc344000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc348000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc34d000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc350000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc354000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc358000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fdf30018.hwevent"),
CLK_LOOKUP("core_mmss_clk", mmss_misc_ahb_clk.c, "fdf30018.hwevent"),
@@ -5746,6 +5804,7 @@
if (cpu_is_msm8974pro_ac()) {
sdcc1_apps_clk_src.c.fmax[VDD_DIG_LOW] = 200000000;
sdcc1_apps_clk_src.c.fmax[VDD_DIG_NOMINAL] = 400000000;
+ sdcc1_apps_clk_src.freq_tbl = ftbl_gcc_sdcc1_apps_clk_ac;
}
vfe0_clk_src.c.fmax[VDD_DIG_LOW] = 150000000;
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index 3b07069..0b73ac9 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -1887,6 +1887,9 @@
CLK_LOOKUP("core_clk", qdss_clk.c, "fc30f000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc310000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc333000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc350000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc354000.cti"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc358000.cti"),
CLK_LOOKUP("core_clk", qdss_clk.c, "f9011038.hwevent"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc322000.tmc"),
@@ -1909,6 +1912,9 @@
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc30f000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc310000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc333000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc350000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc354000.cti"),
+ CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "fc358000.cti"),
CLK_LOOKUP("core_a_clk", qdss_a_clk.c, "f9011038.hwevent"),
};
diff --git a/arch/arm/mach-msm/include/mach/gpiomux.h b/arch/arm/mach-msm/include/mach/gpiomux.h
index bd1a4a2..122ffaa 100644
--- a/arch/arm/mach-msm/include/mach/gpiomux.h
+++ b/arch/arm/mach-msm/include/mach/gpiomux.h
@@ -114,6 +114,8 @@
TLMM_ETM_MODE_REG = 0x2014,
TLMM_SDC2_HDRV_PULL_CTL = 0x2048,
TLMM_SPARE_REG = 0x2024,
+ TLMM_CDC_HDRV_CTL = 0x2054,
+ TLMM_CDC_HDRV_PULL_CTL = 0x2058,
};
void msm_tlmm_misc_reg_write(enum msm_tlmm_misc_reg misc_reg, int val);
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 7cfbd93..c4db727 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -101,6 +101,7 @@
* @asid: List of ASID and their usage count (index is ASID value).
* @ctx_attach_count: Count of how many context are attached.
* @bus_client : Bus client needed to vote for bus bandwidth.
+ * @needs_rem_spinlock : 1 if remote spinlock is needed, 0 otherwise
*
* A msm_iommu_drvdata holds the global driver data about a single piece
* of an IOMMU hardware instance.
@@ -125,6 +126,7 @@
int *asid;
unsigned int ctx_attach_count;
unsigned int bus_client;
+ int needs_rem_spinlock;
};
/**
@@ -146,8 +148,8 @@
int (*iommu_clk_on)(struct msm_iommu_drvdata *);
void (*iommu_clk_off)(struct msm_iommu_drvdata *);
void * (*iommu_lock_initialize)(void);
- void (*iommu_lock_acquire)(void);
- void (*iommu_lock_release)(void);
+ void (*iommu_lock_acquire)(unsigned int need_extra_lock);
+ void (*iommu_lock_release)(unsigned int need_extra_lock);
};
void msm_iommu_add_drv(struct msm_iommu_drvdata *drv);
@@ -277,32 +279,21 @@
}
#endif
-#ifdef CONFIG_MSM_IOMMU_GPU_SYNC
-void msm_iommu_remote_p0_spin_lock(void);
-void msm_iommu_remote_p0_spin_unlock(void);
+#ifdef CONFIG_MSM_IOMMU_SYNC
+void msm_iommu_remote_p0_spin_lock(unsigned int need_lock);
+void msm_iommu_remote_p0_spin_unlock(unsigned int need_lock);
#define msm_iommu_remote_lock_init() _msm_iommu_remote_spin_lock_init()
-#define msm_iommu_remote_spin_lock() msm_iommu_remote_p0_spin_lock()
-#define msm_iommu_remote_spin_unlock() msm_iommu_remote_p0_spin_unlock()
+#define msm_iommu_remote_spin_lock(need_lock) \
+ msm_iommu_remote_p0_spin_lock(need_lock)
+#define msm_iommu_remote_spin_unlock(need_lock) \
+ msm_iommu_remote_p0_spin_unlock(need_lock)
#else
#define msm_iommu_remote_lock_init()
-#define msm_iommu_remote_spin_lock()
-#define msm_iommu_remote_spin_unlock()
+#define msm_iommu_remote_spin_lock(need_lock)
+#define msm_iommu_remote_spin_unlock(need_lock)
#endif
-/* Allows kgsl iommu driver to acquire lock */
-#define msm_iommu_lock() \
- do { \
- msm_iommu_mutex_lock(); \
- msm_iommu_remote_spin_lock(); \
- } while (0)
-
-#define msm_iommu_unlock() \
- do { \
- msm_iommu_remote_spin_unlock(); \
- msm_iommu_mutex_unlock(); \
- } while (0)
-
#ifdef CONFIG_MSM_IOMMU
/*
* Look up an IOMMU context device by its context name. NULL if none found.
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8084.h b/arch/arm/mach-msm/include/mach/msm_iomap-8084.h
index 43f1de0..fe68524 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8084.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8084.h
@@ -31,6 +31,9 @@
#define APQ8084_TLMM_PHYS 0xFD510000
#define APQ8084_TLMM_SIZE SZ_16K
+#define APQ8084_QGIC_CPU_PHYS 0xF9002000
+#define APQ8084_QGIC_CPU_SIZE SZ_4K
+
#ifdef CONFIG_DEBUG_APQ8084_UART
#define MSM_DEBUG_UART_BASE IOMEM(0xFA71E000)
#define MSM_DEBUG_UART_PHYS 0xF991E000
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8092.h b/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
index f460a4e..2ae36a5 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8092.h
@@ -28,6 +28,9 @@
#define MPQ8092_QGIC_DIST_PHYS 0xF9000000
#define MPQ8092_QGIC_DIST_SIZE SZ_4K
+#define MPQ8092_QGIC_CPU_PHYS 0xF9002000
+#define MPQ8092_QGIC_CPU_SIZE SZ_4K
+
#define MPQ8092_TLMM_PHYS 0xFD510000
#define MPQ8092_TLMM_SIZE SZ_16K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8226.h b/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
index 327c1ea..adf66ff 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8226.h
@@ -28,6 +28,9 @@
#define MSM8226_QGIC_DIST_PHYS 0xF9000000
#define MSM8226_QGIC_DIST_SIZE SZ_4K
+#define MSM8226_QGIC_CPU_PHYS 0xF9002000
+#define MSM8226_QGIC_CPU_SIZE SZ_4K
+
#define MSM8226_APCS_GCC_PHYS 0xF9011000
#define MSM8226_APCS_GCC_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8610.h b/arch/arm/mach-msm/include/mach/msm_iomap-8610.h
index 18e448d..4431d71 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8610.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8610.h
@@ -27,6 +27,9 @@
#define MSM8610_QGIC_DIST_PHYS 0xF9000000
#define MSM8610_QGIC_DIST_SIZE SZ_4K
+#define MSM8610_QGIC_CPU_PHYS 0xF9002000
+#define MSM8610_QGIC_CPU_SIZE SZ_4K
+
#define MSM8610_APCS_GCC_PHYS 0xF9011000
#define MSM8610_APCS_GCC_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
index ec3c210..4072f2d 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
@@ -28,6 +28,9 @@
#define MSM8974_QGIC_DIST_PHYS 0xF9000000
#define MSM8974_QGIC_DIST_SIZE SZ_4K
+#define MSM8974_QGIC_CPU_PHYS 0xF9002000
+#define MSM8974_QGIC_CPU_SIZE SZ_4K
+
#define MSM8974_TLMM_PHYS 0xFD510000
#define MSM8974_TLMM_SIZE SZ_16K
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
index 31b19b3..ee5a413 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-9625.h
@@ -28,6 +28,9 @@
#define MSM9625_QGIC_DIST_PHYS 0xF9000000
#define MSM9625_QGIC_DIST_SIZE SZ_4K
+#define MSM9625_QGIC_CPU_PHYS 0xF9002000
+#define MSM9625_QGIC_CPU_SIZE SZ_4K
+
#define MSM9625_TMR_PHYS 0xF9021000
#define MSM9625_TMR_SIZE SZ_4K
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index b06189f..6b3d590 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -50,6 +50,7 @@
#define machine_is_msm8610() of_machine_is_compatible("qcom,msm8610")
#define machine_is_msm8226() of_machine_is_compatible("qcom,msm8226")
#define machine_is_apq8074() of_machine_is_compatible("qcom,apq8074")
+#define machine_is_msm8926() of_machine_is_compatible("qcom,msm8926")
#define early_machine_is_msm8610() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8610")
@@ -80,6 +81,7 @@
#define machine_is_msm8610() 0
#define machine_is_msm8226() 0
#define machine_is_apq8074() 0
+#define machine_is_msm8926() 0
#define early_machine_is_msm8610() 0
#define early_machine_is_mpq8092() 0
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index f736b30..d1c8500 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -299,6 +299,7 @@
#ifdef CONFIG_ARCH_MSM8974
static struct map_desc msm_8974_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MSM8974),
+ MSM_CHIP_DEVICE(QGIC_CPU, MSM8974),
MSM_CHIP_DEVICE(TLMM, MSM8974),
MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8974),
{
@@ -322,6 +323,7 @@
#ifdef CONFIG_ARCH_APQ8084
static struct map_desc msm_8084_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, APQ8084),
+ MSM_CHIP_DEVICE(QGIC_CPU, APQ8084),
MSM_CHIP_DEVICE(TLMM, APQ8084),
{
.virtual = (unsigned long) MSM_SHARED_RAM_BASE,
@@ -504,6 +506,7 @@
#ifdef CONFIG_ARCH_MSM9625
static struct map_desc msm9625_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MSM9625),
+ MSM_CHIP_DEVICE(QGIC_CPU, MSM9625),
MSM_CHIP_DEVICE(TLMM, MSM9625),
MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM9625),
MSM_CHIP_DEVICE(TMR, MSM9625),
@@ -547,6 +550,7 @@
#ifdef CONFIG_ARCH_MPQ8092
static struct map_desc mpq8092_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MPQ8092),
+ MSM_CHIP_DEVICE(QGIC_CPU, MPQ8092),
MSM_CHIP_DEVICE(TLMM, MPQ8092),
{
.virtual = (unsigned long) MSM_SHARED_RAM_BASE,
@@ -569,6 +573,7 @@
#ifdef CONFIG_ARCH_MSM8226
static struct map_desc msm_8226_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MSM8226),
+ MSM_CHIP_DEVICE(QGIC_CPU, MSM8226),
MSM_CHIP_DEVICE(APCS_GCC, MSM8226),
MSM_CHIP_DEVICE(TLMM, MSM8226),
MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8226),
@@ -594,6 +599,7 @@
#ifdef CONFIG_ARCH_MSM8610
static struct map_desc msm8610_io_desc[] __initdata = {
MSM_CHIP_DEVICE(QGIC_DIST, MSM8610),
+ MSM_CHIP_DEVICE(QGIC_CPU, MSM8610),
MSM_CHIP_DEVICE(APCS_GCC, MSM8610),
MSM_CHIP_DEVICE(TLMM, MSM8610),
MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8610),
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index 180d277..249a334 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -191,6 +191,9 @@
case MSM_SPM_L2_MODE_GDHS:
msm_pm_set_l2_flush_flag(MSM_SCM_L2_GDHS);
break;
+ case MSM_SPM_L2_MODE_PC_NO_RPM:
+ msm_pm_set_l2_flush_flag(MSM_SCM_L2_OFF);
+ break;
case MSM_SPM_L2_MODE_RETENTION:
case MSM_SPM_L2_MODE_DISABLED:
break;
@@ -448,6 +451,7 @@
int i;
struct lpm_lookup_table l2_mode_lookup[] = {
{MSM_SPM_L2_MODE_POWER_COLLAPSE, "l2_cache_pc"},
+ {MSM_SPM_L2_MODE_PC_NO_RPM, "l2_cache_pc_no_rpm"},
{MSM_SPM_L2_MODE_GDHS, "l2_cache_gdhs"},
{MSM_SPM_L2_MODE_RETENTION, "l2_cache_retention"},
{MSM_SPM_L2_MODE_DISABLED, "l2_cache_active"}
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index ddf747e..7c694a7 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
@@ -766,6 +766,8 @@
pdata = msm_bus_of_get_fab_data(pdev);
if (IS_ERR(pdata) || ZERO_OR_NULL_PTR(pdata)) {
pr_err("Null platform data\n");
+ kfree(fabric->info.node_info);
+ kfree(fabric);
return PTR_ERR(pdata);
}
msm_bus_board_init(pdata);
diff --git a/arch/arm/mach-msm/msm_qmi_interface.c b/arch/arm/mach-msm/msm_qmi_interface.c
index a8fed52..e2ff0f4 100644
--- a/arch/arm/mach-msm/msm_qmi_interface.c
+++ b/arch/arm/mach-msm/msm_qmi_interface.c
@@ -160,6 +160,10 @@
msg_id = ((struct qmi_header *)pend_txn->enc_data)->msg_id;
kfree(pend_txn->enc_data);
if (ret < 0) {
+ pr_err("%s: Sending transaction %d from port %d failed",
+ __func__, pend_txn->txn_id,
+ ((struct msm_ipc_port *)handle->src_port)->
+ this_port.port_id);
if (pend_txn->type == QMI_ASYNC_TXN) {
pend_txn->resp_cb(pend_txn->handle,
msg_id, pend_txn->resp,
@@ -171,10 +175,6 @@
pend_txn->send_stat = ret;
wake_up(&pend_txn->wait_q);
}
- pr_err("%s: Sending transaction %d from port %d failed",
- __func__, pend_txn->txn_id,
- ((struct msm_ipc_port *)handle->src_port)->
- this_port.port_id);
} else {
list_del(&pend_txn->list);
list_add_tail(&pend_txn->list, &handle->txn_list);
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
index 153864d..c186a5e 100644
--- a/arch/arm/mach-msm/ocmem_core.c
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -43,6 +43,8 @@
unsigned int num_macros;
struct ocmem_hw_macro *macro;
struct msm_rpm_request *rpm_req;
+ unsigned long macro_size;
+ unsigned long region_size;
unsigned r_state;
};
@@ -69,6 +71,9 @@
#define NUM_MACROS_MASK (0x3F << 8)
#define NUM_MACROS_SHIFT (8)
+#define LAST_REGN_HALFSIZE_MASK (0x1 << 16)
+#define LAST_REGN_HALFSIZE_SHIFT (16)
+
#define INTERLEAVING_MASK (0x1 << 17)
#define INTERLEAVING_SHIFT (17)
@@ -198,7 +203,13 @@
return state;
}
+
#ifndef CONFIG_MSM_OCMEM_POWER_DISABLE
+static struct ocmem_hw_region *get_ocmem_region(unsigned region_num)
+{
+ return ®ion_ctrl[region_num];
+}
+
static int commit_region_staging(unsigned region_num, unsigned start_m,
unsigned new_state)
{
@@ -933,6 +944,7 @@
unsigned start_m = num_banks;
unsigned end_m = num_banks;
unsigned long region_offset = 0;
+ struct ocmem_hw_region *region;
int rc = 0;
if (offset < 0)
@@ -966,6 +978,7 @@
for (i = region_start; i <= region_end; i++) {
+ region = get_ocmem_region(i);
curr_state = read_region_state(i);
switch (curr_state) {
@@ -981,14 +994,14 @@
break;
}
- if (len >= region_size) {
+ if (len >= region->region_size) {
pr_debug("switch: entire region (%d)\n", i);
start_m = 0;
end_m = num_banks;
} else {
- region_offset = offset - (i * region_size);
- start_m = region_offset / macro_size;
- end_m = (region_offset + len - 1) / macro_size;
+ region_offset = offset - (i * region->region_size);
+ start_m = region_offset / region->macro_size;
+ end_m = (region_offset + len - 1) / region->macro_size;
pr_debug("switch: macro (%u to %u)\n", start_m, end_m);
}
@@ -1002,7 +1015,7 @@
aggregate_region_state(i);
if (rpm_power_control)
commit_region_state(i);
- len -= region_size;
+ len -= region->region_size;
/* If we voted ON/retain the banks must never be OFF */
if (new_state != REGION_DEFAULT_OFF) {
@@ -1123,6 +1136,7 @@
struct device *dev = &pdev->dev;
struct ocmem_plat_data *pdata = NULL;
unsigned hw_ver;
+ bool last_region_halfsize;
bool interleaved;
unsigned i, j, k;
unsigned rsc_type = 0;
@@ -1146,6 +1160,9 @@
goto hw_not_supported;
}
+ last_region_halfsize = (hw_ver & LAST_REGN_HALFSIZE_MASK) >>
+ LAST_REGN_HALFSIZE_SHIFT;
+
interleaved = (hw_ver & INTERLEAVING_MASK) >> INTERLEAVING_SHIFT;
num_regions = pdata->nr_regions;
@@ -1179,6 +1196,14 @@
region->r_state = REGION_DEFAULT_OFF;
region->num_macros = num_banks;
+ if (last_region_halfsize && i == (num_regions - 1)) {
+ region->macro_size = macro_size / 2;
+ region->region_size = region_size / 2;
+ } else {
+ region->macro_size = macro_size;
+ region->region_size = region_size;
+ }
+
region->macro = devm_kzalloc(dev,
sizeof(struct ocmem_hw_macro) *
num_banks, GFP_KERNEL);
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index 620ab5c..69df3ae 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -334,7 +334,7 @@
pr_err("Ignoring wcnss bite irq, restart in progress\n");
return IRQ_HANDLED;
}
- wcnss_pronto_log_debug_regs();
+ wcnss_log_debug_regs_on_bite();
drv->restart_inprogress = true;
restart_wcnss(drv);
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index de15be5..322061d 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -494,7 +494,7 @@
if (!lpass_status) {
pr_err("%s: kobject create failed\n", __func__);
ret = -ENOMEM;
- goto err_notif_modem;
+ goto err_create_kobj;
}
ret = sysfs_create_group(lpass_status, &attr_group);
@@ -507,6 +507,8 @@
return 0;
err_kobj:
kobject_put(lpass_status);
+err_create_kobj:
+ subsys_notif_unregister_notifier(drv->modem_notif_hdle, &mnb);
err_notif_modem:
subsys_notif_unregister_notifier(drv->wcnss_notif_hdle, &wnb);
err_notif_wcnss:
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index da5e67a..00b0b3b 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -481,6 +481,10 @@
bool collapsed = 0;
int ret;
bool save_cpu_regs = !cpu || from_idle;
+ unsigned int saved_gic_cpu_ctrl;
+
+ saved_gic_cpu_ctrl = readl_relaxed(MSM_QGIC_CPU_BASE + GIC_CPU_CTRL);
+ mb();
if (MSM_PM_DEBUG_POWER_COLLAPSE & msm_pm_debug_mask)
pr_info("CPU%u: %s: notify_rpm %d\n",
@@ -503,6 +507,9 @@
if (from_idle && msm_pm_pc_reset_timer)
clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+#ifdef CONFIG_VFP
+ vfp_pm_suspend();
+#endif
collapsed = save_cpu_regs ? msm_pm_collapse() : msm_pm_pc_hotplug();
if (from_idle && msm_pm_pc_reset_timer)
@@ -511,7 +518,14 @@
msm_pm_boot_config_after_pc(cpu);
if (collapsed) {
+#ifdef CONFIG_VFP
+ vfp_pm_resume();
+#endif
cpu_init();
+ writel(0xF0, MSM_QGIC_CPU_BASE + GIC_CPU_PRIMASK);
+ writel_relaxed(saved_gic_cpu_ctrl,
+ MSM_QGIC_CPU_BASE + GIC_CPU_CTRL);
+ mb();
local_fiq_enable();
}
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb.c b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
index 1f04e76..d32dc4f 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
@@ -2,7 +2,7 @@
*
* amrnb audio decoder device
*
- * Copyright (c) 2008-2009, 2011-2012 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2008-2009, 2011-2013 The Linux Foundation. All rights reserved.
*
* Based on the mp3 native driver in arch/arm/mach-msm/qdsp5/audio_mp3.c
*
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c b/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
index 743eee2..0eca74d 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
@@ -2,7 +2,7 @@
*
* amrnb encoder device
*
- * Copyright (c) 2009, 2011-2012 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009, 2011-2013 The Linux Foundation. All rights reserved.
*
* This code is based in part on arch/arm/mach-msm/qdsp5/audio_in.c, which is
* Copyright (C) 2008 Google, Inc.
@@ -742,6 +742,7 @@
MM_DBG("\n");
if (cmd == AUDIO_GET_STATS) {
struct msm_audio_stats stats;
+ memset(&stats, 0, sizeof(stats));
stats.byte_count = atomic_read(&audio->in_bytes);
stats.sample_count = atomic_read(&audio->in_samples);
if (copy_to_user((void *) arg, &stats, sizeof(stats)))
diff --git a/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c b/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
index 83a2633..cfda4b9 100644
--- a/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
@@ -2,7 +2,7 @@
*
* qcelp audio input device
*
- * Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This code is based in part on arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c,
* Copyright (C) 2008 Google, Inc.
@@ -732,6 +732,7 @@
MM_DBG("\n");
if (cmd == AUDIO_GET_STATS) {
struct msm_audio_stats stats;
+ memset(&stats, 0, sizeof(stats));
stats.byte_count = atomic_read(&audio->in_bytes);
stats.sample_count = atomic_read(&audio->in_samples);
if (copy_to_user((void *) arg, &stats, sizeof(stats)))
diff --git a/arch/arm/mach-msm/qdsp5/audio_voicememo.c b/arch/arm/mach-msm/qdsp5/audio_voicememo.c
index ae63f0d..f7295b7 100644
--- a/arch/arm/mach-msm/qdsp5/audio_voicememo.c
+++ b/arch/arm/mach-msm/qdsp5/audio_voicememo.c
@@ -4,7 +4,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
*
* This code is based in part on arch/arm/mach-msm/qdsp5/audio_mp3.c
*
@@ -644,6 +644,7 @@
if (cmd == AUDIO_GET_STATS) {
struct msm_audio_stats stats;
+ memset(&stats, 0, sizeof(stats));
mutex_lock(&audio->dsp_lock);
stats.byte_count = audio->byte_count;
stats.sample_count = audio->frame_count;
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_amrnb_in.c b/arch/arm/mach-msm/qdsp5v2/audio_amrnb_in.c
index 8e66939..cb3c3ea 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_amrnb_in.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_amrnb_in.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -503,6 +503,7 @@
if (cmd == AUDIO_GET_STATS) {
struct msm_audio_stats stats;
+ memset(&stats, 0, sizeof(stats));
stats.byte_count = atomic_read(&audio->in_bytes);
stats.sample_count = atomic_read(&audio->in_samples);
if (copy_to_user((void *) arg, &stats, sizeof(stats)))
diff --git a/arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c b/arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c
index 0f8956f..37a6726 100644
--- a/arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c
+++ b/arch/arm/mach-msm/qdsp5v2/audio_qcelp_in.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2008 Google, Inc.
* Copyright (C) 2008 HTC Corporation
- * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2009-2013, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -778,6 +778,7 @@
MM_DBG("\n");
if (cmd == AUDIO_GET_STATS) {
struct msm_audio_stats stats;
+ memset(&stats, 0, sizeof(stats));
stats.byte_count = atomic_read(&audio->in_bytes);
stats.sample_count = atomic_read(&audio->in_samples);
if (copy_to_user((void *) arg, &stats, sizeof(stats)))
diff --git a/arch/arm/mach-msm/qdsp6/pcm_in.c b/arch/arm/mach-msm/qdsp6/pcm_in.c
index c6bddb8..288e1dc 100644
--- a/arch/arm/mach-msm/qdsp6/pcm_in.c
+++ b/arch/arm/mach-msm/qdsp6/pcm_in.c
@@ -141,6 +141,7 @@
}
case AUDIO_GET_CONFIG: {
struct msm_audio_config config;
+ memset(&config, 0, sizeof(config));
config.buffer_size = pcm->buffer_size;
config.buffer_count = 2;
config.sample_rate = pcm->sample_rate;
diff --git a/arch/arm/mach-msm/qdsp6v2/aac_in.c b/arch/arm/mach-msm/qdsp6v2/aac_in.c
index 5e959b5..865f6f2 100644
--- a/arch/arm/mach-msm/qdsp6v2/aac_in.c
+++ b/arch/arm/mach-msm/qdsp6v2/aac_in.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -58,11 +58,33 @@
break;
}
- rc = audio_in_buf_alloc(audio);
- if (rc < 0) {
- pr_err("%s:session id %d: buffer allocation failed\n",
- __func__, audio->ac->session);
- break;
+ if (audio->opened) {
+ rc = audio_in_buf_alloc(audio);
+ if (rc < 0) {
+ pr_err("%s:session id %d: buffer allocation failed\n",
+ __func__, audio->ac->session);
+ break;
+ }
+ } else {
+ if(audio->feedback == NON_TUNNEL_MODE){
+ pr_debug("%s: starting in non_tunnel mode",__func__);
+ rc = q6asm_open_read_write(audio->ac, FORMAT_MPEG4_AAC,
+ FORMAT_LINEAR_PCM);
+ if (rc < 0) {
+ pr_err("%s:open read write failed\n", __func__);
+ break;
+ }
+ }
+ if(audio->feedback == TUNNEL_MODE){
+ pr_debug("%s: starting in tunnel mode",__func__);
+ rc = q6asm_open_read(audio->ac,FORMAT_MPEG4_AAC);
+
+ if (rc < 0) {
+ pr_err("%s:open read failed\n", __func__);
+ break;
+ }
+ }
+ audio->stopped = 0;
}
pr_debug("%s:sbr_ps_flag = %d, sbr_flag = %d\n", __func__,
@@ -125,6 +147,7 @@
case AUDIO_GET_AAC_ENC_CONFIG: {
struct msm_audio_aac_enc_config cfg;
struct msm_audio_aac_enc_config *enc_cfg;
+ memset(&cfg, 0, sizeof(cfg));
enc_cfg = audio->enc_cfg;
if (enc_cfg->channels == CH_MODE_MONO)
cfg.channels = 1;
diff --git a/arch/arm/mach-msm/qdsp6v2/adsp-loader.c b/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
index 0506e7e..0bd2010 100644
--- a/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
+++ b/arch/arm/mach-msm/qdsp6v2/adsp-loader.c
@@ -54,25 +54,36 @@
int rc = 0;
u32 adsp_state;
+ if (!pdev) {
+ dev_err(&pdev->dev, "%s: Platform device null \n", __func__);
+ goto fail;
+ }
+
+ if (!pdev->dev.of_node) {
+ dev_err(&pdev->dev,
+ "%s: Device tree information missing \n", __func__);
+ goto fail;
+ }
+
rc = of_property_read_u32(pdev->dev.of_node, adsp_dt, &adsp_state);
if (rc) {
dev_err(&pdev->dev,
"%s: ADSP state = %x\n", __func__, adsp_state);
- return;
+ goto fail;
}
if (adsp_state == APR_SUBSYS_DOWN) {
- if (pdev) {
- priv = platform_get_drvdata(pdev);
- } else {
- pr_err("%s: Private data get failed\n", __func__);
+ priv = platform_get_drvdata(pdev);
+ if (!priv) {
+ dev_err(&pdev->dev,
+ " %s: Private data get failed\n", __func__);
goto fail;
}
priv->pil_h = subsystem_get("adsp");
if (IS_ERR(priv->pil_h)) {
- pr_err("%s: pil get failed,\n",
+ dev_err(&pdev->dev, "%s: pil get failed,\n",
__func__);
goto fail;
}
@@ -86,11 +97,11 @@
}
- pr_info("%s: Q6/ADSP image is loaded\n", __func__);
+ dev_info(&pdev->dev, "%s: Q6/ADSP image is loaded\n", __func__);
return;
fail:
- pr_err("%s: Q6/ADSP image loading failed\n", __func__);
+ dev_err(&pdev->dev, "%s: Q6/ADSP image loading failed\n", __func__);
return;
}
@@ -118,9 +129,9 @@
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
if (!priv) {
- pr_err("%s: memory alloc failed\n", __func__);
+ dev_err(&pdev->dev, "%s: memory alloc failed\n", __func__);
ret = -ENOMEM;
- goto error_return;
+ return ret;
}
platform_set_drvdata(pdev, priv);
@@ -131,7 +142,7 @@
sizeof(*(priv->attr_group)),
GFP_KERNEL);
if (!priv->attr_group) {
- pr_err("%s: malloc attr_group failed\n",
+ dev_err(&pdev->dev, "%s: malloc attr_group failed\n",
__func__);
ret = -ENOMEM;
goto error_return;
@@ -141,7 +152,7 @@
priv->boot_adsp_obj = kobject_create_and_add("boot_adsp", kernel_kobj);
if (!priv->boot_adsp_obj) {
- pr_err("%s: sysfs create and add failed\n",
+ dev_err(&pdev->dev, "%s: sysfs create and add failed\n",
__func__);
ret = -ENOMEM;
goto error_return;
@@ -149,7 +160,7 @@
ret = sysfs_create_group(priv->boot_adsp_obj, priv->attr_group);
if (ret) {
- pr_err("%s: sysfs create group failed %d\n", \
+ dev_err(&pdev->dev, "%s: sysfs create group failed %d\n", \
__func__, ret);
goto error_return;
}
@@ -195,7 +206,7 @@
{
int ret = adsp_loader_init_sysfs(pdev);
if (ret != 0) {
- pr_err("%s: Error in initing sysfs\n", __func__);
+ dev_err(&pdev->dev, "%s: Error in initing sysfs\n", __func__);
return ret;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils.c b/arch/arm/mach-msm/qdsp6v2/audio_utils.c
index 33bbac0..85af4a7 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils.c
@@ -197,6 +197,7 @@
if (cmd == AUDIO_GET_STATS) {
struct msm_audio_stats stats;
+ memset(&stats, 0, sizeof(stats));
stats.byte_count = atomic_read(&audio->in_bytes);
stats.sample_count = atomic_read(&audio->in_samples);
if (copy_to_user((void *) arg, &stats, sizeof(stats)))
@@ -259,14 +260,16 @@
}
audio->str_cfg.buffer_size = cfg.buffer_size;
audio->str_cfg.buffer_count = cfg.buffer_count;
- rc = q6asm_audio_client_buf_alloc(OUT, audio->ac,
+ if(audio->opened){
+ rc = q6asm_audio_client_buf_alloc(OUT,audio->ac,
ALIGN_BUF_SIZE(audio->str_cfg.buffer_size),
audio->str_cfg.buffer_count);
- if (rc < 0) {
+ if (rc < 0) {
pr_err("%s: session id %d: Buffer Alloc failed rc=%d\n",
- __func__, audio->ac->session, rc);
+ __func__, audio->ac->session, rc);
rc = -ENOMEM;
break;
+ }
}
audio->buf_alloc |= BUF_ALLOC_OUT;
rc = 0;
@@ -348,14 +351,16 @@
audio->pcm_cfg.buffer_size = cfg.buffer_size;
audio->pcm_cfg.channel_count = cfg.channel_count;
audio->pcm_cfg.sample_rate = cfg.sample_rate;
- rc = q6asm_audio_client_buf_alloc(IN, audio->ac,
- ALIGN_BUF_SIZE(audio->pcm_cfg.buffer_size),
- audio->pcm_cfg.buffer_count);
- if (rc < 0) {
- pr_err("%s:session id %d: Buffer Alloc failed\n",
- __func__, audio->ac->session);
- rc = -ENOMEM;
- break;
+ if(audio->opened && audio->feedback == NON_TUNNEL_MODE){
+ rc = q6asm_audio_client_buf_alloc(IN, audio->ac,
+ ALIGN_BUF_SIZE(audio->pcm_cfg.buffer_size),
+ audio->pcm_cfg.buffer_count);
+ if(rc < 0){
+ pr_err("%s:session id %d: Buffer Alloc failed\n",
+ __func__,audio->ac->session);
+ rc = -ENOMEM;
+ break;
+ }
}
audio->buf_alloc |= BUF_ALLOC_IN;
rc = 0;
diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c
index 266b759..601c42c 100644
--- a/arch/arm/mach-msm/scm.c
+++ b/arch/arm/mach-msm/scm.c
@@ -114,6 +114,7 @@
static int scm_remap_error(int err)
{
+ pr_err("scm_call failed with error code %d\n", err);
switch (err) {
case SCM_ERROR:
return -EIO;
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 888cd5e..8af3890 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -32,6 +32,16 @@
#include "boot_stats.h"
#define BUILD_ID_LENGTH 32
+#define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32
+#define SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE 128
+#define SMEM_IMAGE_VERSION_SIZE 4096
+#define SMEM_IMAGE_VERSION_NAME_SIZE 75
+#define SMEM_IMAGE_VERSION_NAME_OFFSET 3
+#define SMEM_IMAGE_VERSION_VARIANT_SIZE 20
+#define SMEM_IMAGE_VERSION_VARIANT_OFFSET 75
+#define SMEM_IMAGE_VERSION_OEM_SIZE 32
+#define SMEM_IMAGE_VERSION_OEM_OFFSET 96
+#define SMEM_IMAGE_VERSION_PARTITION_APPS 10
enum {
HW_PLATFORM_UNKNOWN = 0,
@@ -421,6 +431,7 @@
};
static enum msm_cpu cur_cpu;
+static int current_image;
static struct socinfo_v1 dummy_socinfo = {
.format = 1,
@@ -503,6 +514,11 @@
: 0;
}
+static char *socinfo_get_image_version_base_address(void)
+{
+ return smem_alloc(SMEM_IMAGE_VERSION_TABLE, SMEM_IMAGE_VERSION_SIZE);
+}
+
static uint32_t socinfo_get_format(void)
{
return socinfo ? socinfo->v1.format : 0;
@@ -829,6 +845,107 @@
socinfo_get_pmic_die_revision());
}
+static ssize_t
+msm_get_image_version(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ char *string_address;
+
+ string_address = socinfo_get_image_version_base_address();
+ if (string_address == NULL) {
+ pr_err("%s : Failed to get image version base address",
+ __func__);
+ return snprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "Unknown");
+ }
+ string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ string_address += SMEM_IMAGE_VERSION_NAME_OFFSET;
+ return snprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.72s\n",
+ string_address);
+}
+
+static ssize_t
+msm_set_image_version(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ char *store_address;
+
+ if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS)
+ return count;
+ store_address = socinfo_get_image_version_base_address();
+ if (store_address == NULL) {
+ pr_err("%s : Failed to get image version base address",
+ __func__);
+ return count;
+ }
+ store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ snprintf(store_address, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.75s", buf);
+ return count;
+}
+
+static ssize_t
+msm_get_image_variant(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ char *string_address;
+
+ string_address = socinfo_get_image_version_base_address();
+ if (string_address == NULL) {
+ pr_err("%s : Failed to get image version base address",
+ __func__);
+ return snprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE,
+ "Unknown");
+ }
+ string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ string_address += SMEM_IMAGE_VERSION_VARIANT_OFFSET;
+ return snprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s\n",
+ string_address);
+}
+
+static ssize_t
+msm_set_image_variant(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ char *store_address;
+
+ if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS)
+ return count;
+ store_address = socinfo_get_image_version_base_address();
+ if (store_address == NULL) {
+ pr_err("%s : Failed to get image version base address",
+ __func__);
+ return count;
+ }
+ store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ store_address += SMEM_IMAGE_VERSION_VARIANT_OFFSET;
+ snprintf(store_address, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s", buf);
+ return count;
+}
+
+static ssize_t
+msm_get_image_crm_version(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ char *string_address;
+
+ string_address = socinfo_get_image_version_base_address();
+ if (string_address == NULL) {
+ pr_err("%s : Failed to get image version base address",
+ __func__);
+ return snprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "Unknown");
+ }
+ string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ string_address += SMEM_IMAGE_VERSION_OEM_OFFSET;
+ return snprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.32s\n",
+ string_address);
+}
+
static struct sysdev_attribute socinfo_v1_files[] = {
_SYSDEV_ATTR(id, 0444, socinfo_show_id, NULL),
_SYSDEV_ATTR(version, 0444, socinfo_show_version, NULL),
@@ -866,6 +983,54 @@
socinfo_show_pmic_die_revision, NULL),
};
+static ssize_t
+msm_set_image_crm_version(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ char *store_address;
+
+ if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS)
+ return count;
+ store_address = socinfo_get_image_version_base_address();
+ if (store_address == NULL) {
+ pr_err("%s : Failed to get image version base address",
+ __func__);
+ return count;
+ }
+ store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE;
+ store_address += SMEM_IMAGE_VERSION_OEM_OFFSET;
+ snprintf(store_address, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.32s", buf);
+ return count;
+}
+
+static ssize_t
+msm_get_image_number(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ current_image);
+}
+
+static ssize_t
+msm_select_image(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret, digit;
+
+ ret = kstrtoint(buf, 10, &digit);
+ if (ret)
+ return ret;
+ if (0 <= digit && digit < SMEM_IMAGE_VERSION_BLOCKS_COUNT)
+ current_image = digit;
+ else
+ current_image = 0;
+ return count;
+}
+
+
static struct device_attribute msm_soc_attr_raw_version =
__ATTR(raw_version, S_IRUGO, msm_get_raw_version, NULL);
@@ -902,6 +1067,22 @@
__ATTR(pmic_die_revision, S_IRUGO,
msm_get_pmic_die_revision, NULL);
+static struct device_attribute image_version =
+ __ATTR(image_version, S_IRUGO | S_IWUSR,
+ msm_get_image_version, msm_set_image_version);
+
+static struct device_attribute image_variant =
+ __ATTR(image_variant, S_IRUGO | S_IWUSR,
+ msm_get_image_variant, msm_set_image_variant);
+
+static struct device_attribute image_crm_version =
+ __ATTR(image_crm_version, S_IRUGO | S_IWUSR,
+ msm_get_image_crm_version, msm_set_image_crm_version);
+
+static struct device_attribute select_image =
+ __ATTR(select_image, S_IRUGO | S_IWUGO,
+ msm_get_image_number, msm_select_image);
+
static struct sysdev_class soc_sysdev_class = {
.name = "soc",
};
@@ -956,6 +1137,10 @@
uint32_t legacy_format = socinfo_get_format();
device_create_file(msm_soc_device, &msm_soc_attr_vendor);
+ device_create_file(msm_soc_device, &image_version);
+ device_create_file(msm_soc_device, &image_variant);
+ device_create_file(msm_soc_device, &image_crm_version);
+ device_create_file(msm_soc_device, &select_image);
switch (legacy_format) {
case 8:
@@ -1035,56 +1220,64 @@
msm_soc_device = soc_device_to_device(soc_dev);
populate_soc_sysfs_files(msm_soc_device);
+
err = sysdev_class_register(&soc_sysdev_class);
if (err) {
pr_err("%s: sysdev_class_register fail (%d)\n",
__func__, err);
- return err;
+ goto socinfo_init_err;
}
+
err = sysdev_register(&soc_sys_device);
if (err) {
pr_err("%s: sysdev_register fail (%d)\n",
__func__, err);
- return err;
+ goto socinfo_init_err;
}
+
socinfo_create_files(&soc_sys_device, socinfo_v1_files,
ARRAY_SIZE(socinfo_v1_files));
if (socinfo->v1.format < 2)
- return err;
+ goto socinfo_init_err;
+
socinfo_create_files(&soc_sys_device, socinfo_v2_files,
ARRAY_SIZE(socinfo_v2_files));
if (socinfo->v1.format < 3)
- return err;
+ goto socinfo_init_err;
socinfo_create_files(&soc_sys_device, socinfo_v3_files,
ARRAY_SIZE(socinfo_v3_files));
if (socinfo->v1.format < 4)
- return err;
+ goto socinfo_init_err;
socinfo_create_files(&soc_sys_device, socinfo_v4_files,
ARRAY_SIZE(socinfo_v4_files));
if (socinfo->v1.format < 5)
- return err;
+ goto socinfo_init_err;
socinfo_create_files(&soc_sys_device, socinfo_v5_files,
ARRAY_SIZE(socinfo_v5_files));
if (socinfo->v1.format < 6)
- return err;
+ goto socinfo_init_err;
socinfo_create_files(&soc_sys_device, socinfo_v6_files,
ARRAY_SIZE(socinfo_v6_files));
if (socinfo->v1.format < 7)
- return err;
+ goto socinfo_init_err;
socinfo_create_files(&soc_sys_device, socinfo_v7_files,
ARRAY_SIZE(socinfo_v7_files));
return 0;
+
+socinfo_init_err:
+ kfree(soc_dev_attr);
+ return err;
}
arch_initcall(socinfo_init_sysdev);
diff --git a/arch/arm/mach-msm/spm.h b/arch/arm/mach-msm/spm.h
index 3207011..1769402 100644
--- a/arch/arm/mach-msm/spm.h
+++ b/arch/arm/mach-msm/spm.h
@@ -24,6 +24,7 @@
MSM_SPM_L2_MODE_DISABLED = MSM_SPM_MODE_DISABLED,
MSM_SPM_L2_MODE_RETENTION,
MSM_SPM_L2_MODE_GDHS,
+ MSM_SPM_L2_MODE_PC_NO_RPM,
MSM_SPM_L2_MODE_POWER_COLLAPSE,
};
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index 3ac1348..19b0b80 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -397,6 +397,7 @@
struct mode_of of_l2_modes[] = {
{"qcom,saw2-spm-cmd-ret", MSM_SPM_L2_MODE_RETENTION, 1},
{"qcom,saw2-spm-cmd-gdhs", MSM_SPM_L2_MODE_GDHS, 1},
+ {"qcom,saw2-spm-cmd-pc-no-rpm", MSM_SPM_L2_MODE_PC_NO_RPM, 1},
{"qcom,saw2-spm-cmd-pc", MSM_SPM_L2_MODE_POWER_COLLAPSE, 1},
};
diff --git a/arch/arm/mach-rpc/irq.c b/arch/arm/mach-rpc/irq.c
index cf0e669..3e4fa84 100644
--- a/arch/arm/mach-rpc/irq.c
+++ b/arch/arm/mach-rpc/irq.c
@@ -163,6 +163,6 @@
}
}
- init_FIQ();
+ init_FIQ(FIQ_START);
}
diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
index 194c5f6..7b9f754 100644
--- a/arch/arm/mm/Kconfig
+++ b/arch/arm/mm/Kconfig
@@ -436,24 +436,28 @@
select TLS_REG_EMUL if SMP || !MMU
select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
select CPU_USE_DOMAINS if MMU
+ select NEED_KUSER_HELPERS
config CPU_32v4
bool
select TLS_REG_EMUL if SMP || !MMU
select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
select CPU_USE_DOMAINS if MMU
+ select NEED_KUSER_HELPERS
config CPU_32v4T
bool
select TLS_REG_EMUL if SMP || !MMU
select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
select CPU_USE_DOMAINS if MMU
+ select NEED_KUSER_HELPERS
config CPU_32v5
bool
select TLS_REG_EMUL if SMP || !MMU
select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
select CPU_USE_DOMAINS if MMU
+ select NEED_KUSER_HELPERS
config CPU_32v6
bool
@@ -792,6 +796,7 @@
config TLS_REG_EMUL
bool
+ select NEED_KUSER_HELPERS
help
An SMP system using a pre-ARMv6 processor (there are apparently
a few prototypes like that in existence) and therefore access to
@@ -799,11 +804,43 @@
config NEEDS_SYSCALL_FOR_CMPXCHG
bool
+ select NEED_KUSER_HELPERS
help
SMP on a pre-ARMv6 processor? Well OK then.
Forget about fast user space cmpxchg support.
It is just not possible.
+config NEED_KUSER_HELPERS
+ bool
+
+config KUSER_HELPERS
+ bool "Enable kuser helpers in vector page" if !NEED_KUSER_HELPERS
+ default y
+ help
+ Warning: disabling this option may break user programs.
+
+ Provide kuser helpers in the vector page. The kernel provides
+ helper code to userspace in read only form at a fixed location
+ in the high vector page to allow userspace to be independent of
+ the CPU type fitted to the system. This permits binaries to be
+ run on ARMv4 through to ARMv7 without modification.
+
+ See Documentation/arm/kernel_user_helpers.txt for details.
+
+ However, the fixed address nature of these helpers can be used
+ by ROP (return orientated programming) authors when creating
+ exploits.
+
+ If all of the binaries and libraries which run on your platform
+ are built specifically for your platform, and make no use of
+ these helpers, then you can turn this option off to hinder
+ such exploits. However, in that case, if a binary or library
+ relying on those helpers is run, it will receive a SIGILL signal,
+ which will terminate the program.
+
+ Say N here only if you are absolutely certain that you do not
+ need these helpers; otherwise, the safe option is to say Y.
+
config DMA_CACHE_RWFO
bool "Enable read/write for ownership DMA cache maintenance"
depends on CPU_V6K && SMP
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 509f59d..a1a2e51 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1203,7 +1203,7 @@
/*
* Allocate the vector page early.
*/
- vectors = early_alloc(PAGE_SIZE);
+ vectors = early_alloc(PAGE_SIZE * 2);
early_trap_init(vectors);
@@ -1248,15 +1248,27 @@
map.pfn = __phys_to_pfn(virt_to_phys(vectors));
map.virtual = 0xffff0000;
map.length = PAGE_SIZE;
+#ifdef CONFIG_KUSER_HELPERS
map.type = MT_HIGH_VECTORS;
+#else
+ map.type = MT_LOW_VECTORS;
+#endif
create_mapping(&map);
if (!vectors_high()) {
map.virtual = 0;
+ map.length = PAGE_SIZE * 2;
map.type = MT_LOW_VECTORS;
create_mapping(&map);
}
+ /* Now create a kernel read-only mapping */
+ map.pfn += 1;
+ map.virtual = 0xffff0000 + PAGE_SIZE;
+ map.length = PAGE_SIZE;
+ map.type = MT_LOW_VECTORS;
+ create_mapping(&map);
+
/*
* Ask the machine support to map in the statically mapped devices.
*/
@@ -1485,7 +1497,7 @@
vm->addr = (void *)(vaddr & PAGE_MASK);
vm->size = PAGE_ALIGN(length + (vaddr & ~PAGE_MASK));
vm->phys_addr = __pfn_to_phys(pfn);
- vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;
+ vm->flags = VM_LOWMEM | VM_ARM_STATIC_MAPPING;
vm->flags |= VM_ARM_MTYPE(type);
vm->caller = map_lowmem;
vm_area_add_early(vm++);
diff --git a/arch/arm/plat-mxc/avic.c b/arch/arm/plat-mxc/avic.c
index 689f81f..9091f03 100644
--- a/arch/arm/plat-mxc/avic.c
+++ b/arch/arm/plat-mxc/avic.c
@@ -199,7 +199,7 @@
#ifdef CONFIG_FIQ
/* Initialize FIQ */
- init_FIQ();
+ init_FIQ(FIQ_START);
#endif
printk(KERN_INFO "MXC IRQ initialized\n");
diff --git a/arch/arm/plat-mxc/tzic.c b/arch/arm/plat-mxc/tzic.c
index 98308ec..5cebccf 100644
--- a/arch/arm/plat-mxc/tzic.c
+++ b/arch/arm/plat-mxc/tzic.c
@@ -180,7 +180,7 @@
#ifdef CONFIG_FIQ
/* Initialize FIQ */
- init_FIQ();
+ init_FIQ(FIQ_START);
#endif
pr_info("TrustZone Interrupt Controller (TZIC) initialized\n");
diff --git a/arch/arm/plat-s3c24xx/irq.c b/arch/arm/plat-s3c24xx/irq.c
index bc42c04..fe57bbb 100644
--- a/arch/arm/plat-s3c24xx/irq.c
+++ b/arch/arm/plat-s3c24xx/irq.c
@@ -533,7 +533,7 @@
int i;
#ifdef CONFIG_FIQ
- init_FIQ();
+ init_FIQ(FIQ_START);
#endif
irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
diff --git a/drivers/base/genlock.c b/drivers/base/genlock.c
index 58b0513..1149dec 100644
--- a/drivers/base/genlock.c
+++ b/drivers/base/genlock.c
@@ -788,6 +788,8 @@
if (ret < 0)
return ret;
+ memset(¶m, 0, sizeof(param));
+
param.fd = ret;
if (copy_to_user((void __user *) arg, ¶m,
diff --git a/drivers/base/sync.c b/drivers/base/sync.c
index abde6d9..645a698 100644
--- a/drivers/base/sync.c
+++ b/drivers/base/sync.c
@@ -92,14 +92,14 @@
void sync_timeline_destroy(struct sync_timeline *obj)
{
obj->destroyed = true;
+ smp_wmb();
/*
- * If this is not the last reference, signal any children
- * that their parent is going away.
+ * signal any children that their parent is going away.
*/
+ sync_timeline_signal(obj);
- if (!kref_put(&obj->kref, sync_timeline_free))
- sync_timeline_signal(obj);
+ kref_put(&obj->kref, sync_timeline_free);
}
EXPORT_SYMBOL(sync_timeline_destroy);
diff --git a/drivers/bif/bif-core.c b/drivers/bif/bif-core.c
index 7bc9af2..4ff7355 100644
--- a/drivers/bif/bif-core.c
+++ b/drivers/bif/bif-core.c
@@ -205,13 +205,14 @@
}
if (sdev->nvm_function) {
- pr_debug(" NVM function: pointer=0x%04X, task=%d, wr_buf_size=%d, nvm_base=0x%04X, nvm_size=%d\n",
+ pr_debug(" NVM function: pointer=0x%04X, task=%d, wr_buf_size=%d, nvm_base=0x%04X, nvm_size=%d, nvm_lock_offset=%d\n",
sdev->nvm_function->nvm_pointer,
sdev->nvm_function->slave_control_channel,
(sdev->nvm_function->write_buffer_size
? sdev->nvm_function->write_buffer_size : 0),
sdev->nvm_function->nvm_base_address,
- sdev->nvm_function->nvm_size);
+ sdev->nvm_function->nvm_size,
+ sdev->nvm_function->nvm_lock_offset);
if (sdev->nvm_function->object_count)
pr_debug(" NVM objects:\n");
i = 0;
@@ -448,8 +449,13 @@
rc = bdev->desc->ops->read_slave_registers(bdev, addr, buf,
len);
if (rc)
- pr_err("read_slave_registers failed, rc=%d\n", rc);
- return rc;
+ pr_debug("read_slave_registers failed, rc=%d\n", rc);
+ else
+ return rc;
+ /*
+ * Fall back on individual transactions if high level register
+ * read failed.
+ */
}
for (i = 0; i < len; i++) {
@@ -521,8 +527,13 @@
rc = bdev->desc->ops->write_slave_registers(bdev, addr, buf,
len);
if (rc)
- pr_err("write_slave_registers failed, rc=%d\n", rc);
- return rc;
+ pr_debug("write_slave_registers failed, rc=%d\n", rc);
+ else
+ return rc;
+ /*
+ * Fall back on individual transactions if high level register
+ * write failed.
+ */
}
rc = bdev->desc->ops->bus_transaction(bdev, BIF_TRANS_ERA, addr >> 8);
@@ -567,6 +578,233 @@
return rc;
}
+/* Perform a read-modify-write sequence on a single BIF slave register. */
+static int _bif_slave_masked_write(struct bif_slave_dev *sdev, u16 addr, u8 val,
+ u8 mask)
+{
+ int rc;
+ u8 reg;
+
+ rc = _bif_slave_read(sdev, addr, ®, 1);
+ if (rc)
+ return rc;
+
+ reg = (reg & ~mask) | (val & mask);
+
+ return _bif_slave_write(sdev, addr, ®, 1);
+}
+
+static int _bif_check_task(struct bif_slave_dev *sdev, unsigned int task)
+{
+ if (IS_ERR_OR_NULL(sdev)) {
+ pr_err("Invalid slave device handle=%ld\n", PTR_ERR(sdev));
+ return -EINVAL;
+ } else if (!sdev->bdev) {
+ pr_err("BIF controller has been removed\n");
+ return -ENXIO;
+ } else if (!sdev->slave_ctrl_function
+ || sdev->slave_ctrl_function->task_count == 0) {
+ pr_err("BIF slave does not support slave control\n");
+ return -ENODEV;
+ } else if (task >= sdev->slave_ctrl_function->task_count) {
+ pr_err("Requested task: %u greater than max: %u for this slave\n",
+ task, sdev->slave_ctrl_function->task_count);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int _bif_task_is_busy(struct bif_slave_dev *sdev, unsigned int task)
+{
+ int rc;
+ u16 addr;
+ u8 reg = 0;
+
+ rc = _bif_check_task(sdev, task);
+ if (rc) {
+ pr_err("Invalid slave device or task, rc=%d\n", rc);
+ return rc;
+ }
+
+ /* Check the task busy state. */
+ addr = SLAVE_CTRL_FUNC_TASK_BUSY_ADDR(
+ sdev->slave_ctrl_function->slave_ctrl_pointer, task);
+ rc = _bif_slave_read(sdev, addr, ®, 1);
+ if (rc) {
+ pr_err("BIF slave register read failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ return (reg & BIT(task % SLAVE_CTRL_TASKS_PER_SET)) ? 1 : 0;
+}
+
+static int _bif_enable_auto_task(struct bif_slave_dev *sdev, unsigned int task)
+{
+ int rc;
+ u16 addr;
+ u8 mask;
+
+ rc = _bif_check_task(sdev, task);
+ if (rc) {
+ pr_err("Invalid slave device or task, rc=%d\n", rc);
+ return rc;
+ }
+
+ /* Enable the auto task within the slave */
+ mask = BIT(task % SLAVE_CTRL_TASKS_PER_SET);
+ addr = SLAVE_CTRL_FUNC_TASK_AUTO_TRIGGER_ADDR(
+ sdev->slave_ctrl_function->slave_ctrl_pointer, task);
+ if (task / SLAVE_CTRL_TASKS_PER_SET == 0) {
+ /* Set global auto task enable. */
+ mask |= BIT(0);
+ }
+ rc = _bif_slave_masked_write(sdev, addr, 0xFF, mask);
+ if (rc) {
+ pr_err("BIF slave register masked write failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ /* Set global auto task enable if task not in set 0. */
+ if (task / SLAVE_CTRL_TASKS_PER_SET != 0) {
+ addr = SLAVE_CTRL_FUNC_TASK_AUTO_TRIGGER_ADDR(
+ sdev->slave_ctrl_function->slave_ctrl_pointer, 0);
+ rc = _bif_slave_masked_write(sdev, addr, 0xFF, BIT(0));
+ if (rc) {
+ pr_err("BIF slave register masked write failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+ }
+
+ return rc;
+}
+
+static int _bif_disable_auto_task(struct bif_slave_dev *sdev, unsigned int task)
+{
+ int rc;
+ u16 addr;
+ u8 mask;
+
+ rc = _bif_check_task(sdev, task);
+ if (rc) {
+ pr_err("Invalid slave or task, rc=%d\n", rc);
+ return rc;
+ }
+
+ /* Disable the auto task within the slave */
+ mask = BIT(task % SLAVE_CTRL_TASKS_PER_SET);
+ addr = SLAVE_CTRL_FUNC_TASK_AUTO_TRIGGER_ADDR(
+ sdev->slave_ctrl_function->slave_ctrl_pointer, task);
+ rc = _bif_slave_masked_write(sdev, addr, 0x00, mask);
+ if (rc) {
+ pr_err("BIF slave register masked write failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ return rc;
+}
+
+/*
+ * The MIPI-BIF spec does not define a maximum time in which an NVM write must
+ * complete. The following delay and recheck count therefore represent
+ * arbitrary but reasonable values.
+ */
+#define NVM_WRITE_POLL_DELAY_MS 20
+#define NVM_WRITE_MAX_POLL_COUNT 50
+
+static int _bif_slave_nvm_raw_write(struct bif_slave_dev *sdev, u16 offset,
+ u8 *buf, int len)
+{
+ int rc = 0;
+ int write_len, poll_count, rc2;
+ u8 write_buf[3];
+
+ if (!sdev->nvm_function) {
+ pr_err("BIF slave has no NVM function\n");
+ return -ENODEV;
+ } else if (offset + len > sdev->nvm_function->nvm_size) {
+ pr_err("write offset + len = %d > NVM size = %d\n",
+ offset + len, sdev->nvm_function->nvm_size);
+ return -EINVAL;
+ } else if (offset < sdev->nvm_function->nvm_lock_offset) {
+ pr_err("write offset = %d < first writable offset = %d\n",
+ offset, sdev->nvm_function->nvm_lock_offset);
+ return -EINVAL;
+ }
+
+ rc = _bif_enable_auto_task(sdev,
+ sdev->nvm_function->slave_control_channel);
+ if (rc) {
+ pr_err("Failed to enable NVM auto task, rc=%d\n", rc);
+ return rc;
+ }
+
+ while (len > 0) {
+ write_len = sdev->nvm_function->write_buffer_size;
+ if (write_len == 0)
+ write_len = 256;
+ write_len = min(write_len, len);
+
+ write_buf[0] = offset >> 8;
+ write_buf[1] = offset;
+ write_buf[2] = (write_len == 256) ? 0 : write_len;
+
+ /* Write offset and size registers. */
+ rc = _bif_slave_write(sdev, sdev->nvm_function->nvm_pointer + 6,
+ write_buf, 3);
+ if (rc) {
+ pr_err("BIF slave write failed, rc=%d\n", rc);
+ goto done;
+ }
+
+ /* Write to NVM write buffer registers. */
+ rc = _bif_slave_write(sdev, sdev->nvm_function->nvm_pointer + 9,
+ buf, write_len);
+ if (rc) {
+ pr_err("BIF slave write failed, rc=%d\n", rc);
+ goto done;
+ }
+
+ /*
+ * Wait for completion of the NVM write which was auto-triggered
+ * by the register write of the last byte in the NVM write
+ * buffer.
+ */
+ poll_count = NVM_WRITE_MAX_POLL_COUNT;
+ do {
+ msleep(NVM_WRITE_POLL_DELAY_MS);
+ rc = _bif_task_is_busy(sdev,
+ sdev->nvm_function->slave_control_channel);
+ poll_count--;
+ } while (rc > 0 && poll_count > 0);
+
+ if (rc < 0) {
+ pr_err("Failed to check task state, rc=%d", rc);
+ goto done;
+ } else if (rc > 0) {
+ pr_err("BIF slave NVM write not completed after %d ms\n",
+ NVM_WRITE_POLL_DELAY_MS * NVM_WRITE_MAX_POLL_COUNT);
+ rc = -ETIMEDOUT;
+ goto done;
+ }
+
+ len -= write_len;
+ offset += write_len;
+ buf += write_len;
+ }
+
+done:
+ rc2 = _bif_disable_auto_task(sdev,
+ sdev->nvm_function->slave_control_channel);
+ if (rc2) {
+ pr_err("Failed to disable NVM auto task, rc=%d\n", rc2);
+ return rc2;
+ }
+
+ return rc;
+}
+
/* Takes a mutex if this consumer is not an exclusive bus user. */
static void bif_ctrl_lock(struct bif_ctrl *ctrl)
{
@@ -595,25 +833,53 @@
bif_ctrl_unlock(&slave->ctrl);
}
+/**
+ * bif_crc_ccitt() - calculate the CRC-CCITT CRC value of the data specified
+ * @buffer: Data to calculate the CRC of
+ * @len: Length of the data buffer in bytes
+ *
+ * MIPI-BIF specifies the usage of CRC-CCITT for BIF data objects. This
+ * function performs the CRC calculation while taking into account the bit
+ * ordering used by BIF.
+ */
+u16 bif_crc_ccitt(const u8 *buffer, unsigned int len)
+{
+ u16 crc = 0xFFFF;
+
+ while (len--) {
+ crc = crc_ccitt_byte(crc, bitrev8(*buffer));
+ buffer++;
+ }
+ return bitrev16(crc);
+}
+EXPORT_SYMBOL(bif_crc_ccitt);
+
+static u16 bif_object_crc_ccitt(const struct bif_object *object)
+{
+ u16 crc = 0xFFFF;
+ int i;
+
+ crc = crc_ccitt_byte(crc, bitrev8(object->type));
+ crc = crc_ccitt_byte(crc, bitrev8(object->version));
+ crc = crc_ccitt_byte(crc, bitrev8(object->manufacturer_id >> 8));
+ crc = crc_ccitt_byte(crc, bitrev8(object->manufacturer_id));
+ crc = crc_ccitt_byte(crc, bitrev8(object->length >> 8));
+ crc = crc_ccitt_byte(crc, bitrev8(object->length));
+
+ for (i = 0; i < object->length - 8; i++)
+ crc = crc_ccitt_byte(crc, bitrev8(object->data[i]));
+
+ return bitrev16(crc);
+}
+
static int bif_check_task(struct bif_slave *slave, unsigned int task)
{
if (IS_ERR_OR_NULL(slave)) {
- pr_err("Invalid slave handle.\n");
- return -EINVAL;
- } else if (!slave->sdev->bdev) {
- pr_err("BIF controller has been removed.\n");
- return -ENXIO;
- } else if (!slave->sdev->slave_ctrl_function
- || slave->sdev->slave_ctrl_function->task_count == 0) {
- pr_err("BIF slave does not support slave control.\n");
- return -ENODEV;
- } else if (task >= slave->sdev->slave_ctrl_function->task_count) {
- pr_err("Requested task: %u greater than max: %u for this slave\n",
- task, slave->sdev->slave_ctrl_function->task_count);
+ pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
return -EINVAL;
}
- return 0;
+ return _bif_check_task(slave->sdev, task);
}
/**
@@ -817,6 +1083,61 @@
EXPORT_SYMBOL(bif_trigger_task);
/**
+ * bif_enable_auto_task() - enable task auto triggering for the specified task
+ * @slave: BIF slave handle
+ * @task: BIF task inside of the slave to configure for automatic
+ * triggering. This corresponds to the slave control channel
+ * specified for a given BIF function inside of the slave.
+ *
+ * Returns 0 for success or errno if an error occurred.
+ */
+int bif_enable_auto_task(struct bif_slave *slave, unsigned int task)
+{
+ int rc;
+
+ if (IS_ERR_OR_NULL(slave)) {
+ pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
+ return -EINVAL;
+ }
+
+ bif_slave_ctrl_lock(slave);
+ rc = _bif_enable_auto_task(slave->sdev, task);
+ bif_slave_ctrl_unlock(slave);
+
+ return rc;
+}
+EXPORT_SYMBOL(bif_enable_auto_task);
+
+/**
+ * bif_disable_auto_task() - disable task auto triggering for the specified task
+ * @slave: BIF slave handle
+ * @task: BIF task inside of the slave to stop automatic triggering on.
+ * This corresponds to the slave control channel specified for a
+ * given BIF function inside of the slave.
+ *
+ * This function should be called after bif_enable_auto_task() in a paired
+ * fashion.
+ *
+ * Returns 0 for success or errno if an error occurred.
+ */
+int bif_disable_auto_task(struct bif_slave *slave, unsigned int task)
+{
+ int rc;
+
+ if (IS_ERR_OR_NULL(slave)) {
+ pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
+ return -EINVAL;
+ }
+
+ bif_slave_ctrl_lock(slave);
+ rc = _bif_disable_auto_task(slave->sdev, task);
+ bif_slave_ctrl_unlock(slave);
+
+ return rc;
+}
+EXPORT_SYMBOL(bif_disable_auto_task);
+
+/**
* bif_task_is_busy() - checks the state of a BIF slave task
* @slave: BIF slave handle
* @task: BIF task inside of the slave to trigger. This corresponds to
@@ -828,28 +1149,14 @@
int bif_task_is_busy(struct bif_slave *slave, unsigned int task)
{
int rc;
- u16 addr;
- u8 reg;
- rc = bif_check_task(slave, task);
- if (rc) {
- pr_err("Invalid slave or task, rc=%d\n", rc);
- return rc;
+ if (IS_ERR_OR_NULL(slave)) {
+ pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
+ return -EINVAL;
}
bif_slave_ctrl_lock(slave);
-
- /* Check the task busy state. */
- addr = SLAVE_CTRL_FUNC_TASK_BUSY_ADDR(
- slave->sdev->slave_ctrl_function->slave_ctrl_pointer, task);
- rc = _bif_slave_read(slave->sdev, addr, ®, 1);
- if (rc) {
- pr_err("BIF slave register read failed, rc=%d\n", rc);
- goto done;
- }
-
- rc = (reg & BIT(task % SLAVE_CTRL_TASKS_PER_SET)) ? 1 : 0;
-done:
+ rc = _bif_task_is_busy(slave->sdev, task);
bif_slave_ctrl_unlock(slave);
return rc;
@@ -1258,16 +1565,29 @@
}
EXPORT_SYMBOL(bif_ctrl_put);
+static bool bif_slave_object_match(const struct bif_object *object,
+ const struct bif_match_criteria *criteria)
+{
+ return (object->type == criteria->obj_type)
+ && (object->version == criteria->obj_version
+ || !(criteria->match_mask & BIF_MATCH_OBJ_VERSION))
+ && (object->manufacturer_id == criteria->obj_manufacturer_id
+ || !(criteria->match_mask & BIF_MATCH_OBJ_MANUFACTURER_ID));
+}
+
/*
* Returns true if all parameters are matched, otherwise false.
* function_type and function_version mean that their exists some function in
* the slave which has the specified type and subtype. ctrl == NULL is treated
* as a wildcard.
*/
-static bool bif_slave_match(const struct bif_ctrl *ctrl,
+static bool bif_slave_match(struct bif_ctrl *ctrl,
struct bif_slave_dev *sdev, const struct bif_match_criteria *criteria)
{
int i, type, version;
+ struct bif_object *object;
+ bool function_found = false;
+ bool object_found = false;
if (ctrl && (ctrl->bdev != sdev->bdev))
return false;
@@ -1295,10 +1615,29 @@
if (type == criteria->function_type &&
(version == criteria->function_version
|| !(criteria->match_mask
- & BIF_MATCH_FUNCTION_VERSION)))
- return true;
+ & BIF_MATCH_FUNCTION_VERSION))) {
+ function_found = true;
+ break;
+ }
}
- return false;
+ if (!function_found)
+ return false;
+ }
+
+ if (criteria->match_mask & BIF_MATCH_OBJ_TYPE) {
+ if (!sdev->nvm_function)
+ return false;
+ bif_ctrl_lock(ctrl);
+ list_for_each_entry(object, &sdev->nvm_function->object_list,
+ list) {
+ if (bif_slave_object_match(object, criteria)) {
+ object_found = true;
+ break;
+ }
+ }
+ bif_ctrl_unlock(ctrl);
+ if (!object_found)
+ return false;
}
return true;
@@ -1311,7 +1650,7 @@
* @ctrl: BIF controller consumer handle
* @match_criteria: Matching criteria used to filter slaves
*/
-int bif_slave_match_count(const struct bif_ctrl *ctrl,
+int bif_slave_match_count(struct bif_ctrl *ctrl,
const struct bif_match_criteria *match_criteria)
{
struct bif_slave_dev *sdev;
@@ -1342,7 +1681,7 @@
*
* Returns a BIF slave handle if successful or an ERR_PTR if not.
*/
-struct bif_slave *bif_slave_match_get(const struct bif_ctrl *ctrl,
+struct bif_slave *bif_slave_match_get(struct bif_ctrl *ctrl,
unsigned int id, const struct bif_match_criteria *match_criteria)
{
struct bif_slave_dev *sdev;
@@ -1431,6 +1770,511 @@
}
EXPORT_SYMBOL(bif_slave_find_function);
+static bool bif_object_match(const struct bif_object *object,
+ const struct bif_obj_match_criteria *criteria)
+{
+ return (object->type == criteria->type
+ || !(criteria->match_mask & BIF_OBJ_MATCH_TYPE))
+ && (object->version == criteria->version
+ || !(criteria->match_mask & BIF_OBJ_MATCH_VERSION))
+ && (object->manufacturer_id == criteria->manufacturer_id
+ || !(criteria->match_mask & BIF_OBJ_MATCH_MANUFACTURER_ID));
+}
+
+/**
+ * bif_object_match_count() - returns the number of objects associated with the
+ * specified BIF slave which fit the matching criteria
+ * @slave: BIF slave handle
+ * @match_criteria: Matching criteria used to filter objects
+ */
+int bif_object_match_count(struct bif_slave *slave,
+ const struct bif_obj_match_criteria *match_criteria)
+{
+ struct bif_object *object;
+ int count = 0;
+
+ if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(match_criteria)) {
+ pr_err("Invalid pointer input.\n");
+ return -EINVAL;
+ }
+
+ if (!slave->sdev->nvm_function)
+ return 0;
+
+ bif_slave_ctrl_lock(slave);
+ list_for_each_entry(object, &slave->sdev->nvm_function->object_list,
+ list) {
+ if (bif_object_match(object, match_criteria))
+ count++;
+ }
+ bif_slave_ctrl_unlock(slave);
+
+ return count;
+}
+EXPORT_SYMBOL(bif_object_match_count);
+
+/**
+ * bif_object_match_get() - get a BIF object handle for the id'th object found
+ * in the non-volatile memory of the specified BIF slave
+ * which fits the matching criteria
+ * @slave: BIF slave handle
+ * @id: Index into the set of matching objects
+ * @match_criteria: Matching criteria used to filter objects
+ *
+ * id must be in range [0, bif_object_match_count(slave, match_criteria) - 1].
+ *
+ * Returns a BIF object handle if successful or an ERR_PTR if not. This handle
+ * must be freed using bif_object_put() when it is no longer needed.
+ */
+struct bif_object *bif_object_match_get(struct bif_slave *slave,
+ unsigned int id, const struct bif_obj_match_criteria *match_criteria)
+{
+ struct bif_object *object;
+ struct bif_object *object_found = NULL;
+ struct bif_object *object_consumer = ERR_PTR(-ENODEV);
+ int count = 0;
+
+ if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(match_criteria)) {
+ pr_err("Invalid pointer input.\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (!slave->sdev->nvm_function)
+ return object_consumer;
+
+ bif_slave_ctrl_lock(slave);
+ list_for_each_entry(object, &slave->sdev->nvm_function->object_list,
+ list) {
+ if (bif_object_match(object, match_criteria))
+ count++;
+ if (count == id + 1) {
+ object_found = object;
+ break;
+ }
+ }
+
+ if (object_found) {
+ object_consumer = kmemdup(object_found,
+ sizeof(*object_consumer), GFP_KERNEL);
+ if (!object_consumer) {
+ pr_err("out of memory\n");
+ object_consumer = ERR_PTR(-ENOMEM);
+ goto done;
+ }
+
+ object_consumer->data = kmemdup(object_found->data,
+ object_found->length - 8, GFP_KERNEL);
+ if (!object_consumer->data) {
+ pr_err("out of memory\n");
+ kfree(object_consumer);
+ object_consumer = ERR_PTR(-ENOMEM);
+ goto done;
+ }
+
+ /*
+ * Use prev pointer in consumer struct to point to original
+ * struct in the internal linked list.
+ */
+ object_consumer->list.prev = &object_found->list;
+ }
+
+done:
+ bif_slave_ctrl_unlock(slave);
+
+ return object_consumer;
+
+}
+EXPORT_SYMBOL(bif_object_match_get);
+
+/**
+ * bif_object_put() - frees the memory allocated for a BIF object pointer
+ * returned by bif_object_match_get()
+ * @object: BIF object to free
+ */
+void bif_object_put(struct bif_object *object)
+{
+ if (object)
+ kfree(object->data);
+ kfree(object);
+}
+EXPORT_SYMBOL(bif_object_put);
+
+/* Copies the contents of object into buf following MIPI-BIF formatting. */
+static void bif_object_flatten(u8 *buf, const struct bif_object *object)
+{
+ buf[0] = object->type;
+ buf[1] = object->version;
+ buf[2] = object->manufacturer_id >> 8;
+ buf[3] = object->manufacturer_id;
+ buf[4] = object->length >> 8;
+ buf[5] = object->length;
+ memcpy(&buf[6], object->data, object->length - 8);
+ buf[object->length - 2] = object->crc >> 8;
+ buf[object->length - 1] = object->crc;
+}
+
+/**
+ * bif_object_write() - writes a new BIF object at the end of the object list in
+ * the non-volatile memory of a slave
+ * @slave: BIF slave handle
+ * @type: Type of the object
+ * @version: Version of the object
+ * @manufacturer_id: Manufacturer ID number allocated by MIPI
+ * @data: Data contained in the object
+ * @data_len: Length of the data
+ *
+ * Returns 0 on success or errno on failure. This function will fail if the NVM
+ * lock points to an offset after the BIF object list terminator (0x00).
+ */
+int bif_object_write(struct bif_slave *slave, u8 type, u8 version,
+ u16 manufacturer_id, const u8 *data, int data_len)
+{
+ struct bif_object *object;
+ struct bif_object *tail_object;
+ struct bif_nvm_function *nvm;
+ int rc;
+ int add_null = 0;
+ u16 offset = 0;
+ u8 *buf;
+
+ if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(data)) {
+ pr_err("Invalid input pointer\n");
+ return -EINVAL;
+ }
+
+ nvm = slave->sdev->nvm_function;
+ if (!nvm) {
+ pr_err("BIF slave has no NVM function\n");
+ return -ENODEV;
+ }
+
+ bif_slave_ctrl_lock(slave);
+ if (nvm->object_count > 0) {
+ tail_object = list_entry(nvm->object_list.prev,
+ struct bif_object, list);
+ offset = tail_object->addr - nvm->nvm_base_address
+ + tail_object->length;
+ }
+
+ if (offset < nvm->nvm_lock_offset) {
+ pr_err("Cannot write BIF object to NVM because the end of the object list is locked (end=%d < lock=%d)\n",
+ offset, nvm->nvm_lock_offset);
+ rc = -EPERM;
+ goto error_unlock;
+ } else if (offset + data_len + 8 > nvm->nvm_size) {
+ pr_err("Cannot write BIF object to NVM because there is not enough remaining space (size=%d > remaining=%d)\n",
+ data_len + 8, nvm->nvm_size - offset);
+ rc = -EINVAL;
+ goto error_unlock;
+ }
+
+ if (offset + data_len + 8 < nvm->nvm_size)
+ add_null = 1;
+ object = kzalloc(sizeof(*object), GFP_KERNEL);
+ if (!object) {
+ pr_err("kzalloc failed\n");
+ rc = -ENOMEM;
+ goto error_unlock;
+ }
+
+ object->data = kzalloc(data_len, GFP_KERNEL);
+ if (!object->data) {
+ pr_err("kzalloc failed\n");
+ rc = -ENOMEM;
+ goto free_object;
+ }
+
+ buf = kzalloc(data_len + 8 + add_null, GFP_KERNEL);
+ if (!buf) {
+ pr_err("kzalloc failed\n");
+ rc = -ENOMEM;
+ goto free_data;
+ }
+
+ object->type = type;
+ object->version = version;
+ object->manufacturer_id = manufacturer_id;
+ object->length = data_len + 8;
+ memcpy(object->data, data, data_len);
+ object->crc = bif_object_crc_ccitt(object);
+ object->addr = offset + nvm->nvm_base_address;
+
+ bif_object_flatten(buf, object);
+ if (add_null)
+ buf[object->length] = BIF_OBJ_END_OF_LIST;
+
+ rc = _bif_slave_nvm_raw_write(slave->sdev, offset, buf,
+ object->length + add_null);
+ if (rc < 0) {
+ pr_err("NVM write failed, rc=%d\n", rc);
+ kfree(buf);
+ goto free_data;
+ }
+ kfree(buf);
+
+ list_add_tail(&object->list, &nvm->object_list);
+ nvm->object_count++;
+
+ bif_slave_ctrl_unlock(slave);
+
+ return rc;
+
+free_data:
+ kfree(object->data);
+free_object:
+ kfree(object);
+error_unlock:
+ bif_slave_ctrl_unlock(slave);
+
+ return rc;
+
+}
+EXPORT_SYMBOL(bif_object_write);
+
+/*
+ * Returns a pointer to the internal object referenced by a consumer object
+ * if it exists. Returns NULL if the internal object cannot be found.
+ */
+static struct bif_object *bif_object_consumer_search(
+ struct bif_nvm_function *nvm, const struct bif_object *consumer_object)
+{
+ struct bif_object *object = NULL;
+ struct bif_object *search_object;
+
+ /*
+ * Internal struct in object linked list is pointed to by consumer
+ * object list.prev.
+ */
+ search_object = list_entry(consumer_object->list.prev,
+ struct bif_object, list);
+
+ list_for_each_entry(object, &nvm->object_list, list) {
+ if (object == search_object)
+ break;
+ }
+
+ if (object != search_object)
+ return NULL;
+
+ return object;
+}
+
+/**
+ * bif_object_overwrite() - overwrites an existing BIF object found in the
+ * non-volatile memory of a slave
+ * @slave: BIF slave handle
+ * @object: Existing object in the slave to overwrite
+ * @type: Type of the object
+ * @version: Version of the object
+ * @manufacturer_id: Manufacturer ID number allocated by MIPI
+ * @data: Data contained in the object
+ * @data_len: Length of the data
+ *
+ * Returns 0 on success or errno on failure. The data stored within 'object'
+ * is updated to the new values upon success. The new data written to the
+ * object must have exactly the same length as the old data (i.e.
+ * data_len == object->length - 8).
+ *
+ * This function will fail if the NVM lock points to an offset after the
+ * beginning of the existing BIF object.
+ */
+int bif_object_overwrite(struct bif_slave *slave,
+ struct bif_object *object, u8 type, u8 version,
+ u16 manufacturer_id, const u8 *data, int data_len)
+{
+ struct bif_object *edit_object = NULL;
+ struct bif_nvm_function *nvm;
+ int rc;
+ u16 crc;
+ u8 *buf;
+
+ if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(object)
+ || IS_ERR_OR_NULL(data)) {
+ pr_err("Invalid input pointer\n");
+ return -EINVAL;
+ }
+
+ nvm = slave->sdev->nvm_function;
+ if (!nvm) {
+ pr_err("BIF slave has no NVM function\n");
+ return -ENODEV;
+ }
+
+ if (data_len + 8 != object->length) {
+ pr_err("New data length=%d is different from existing length=%d\n",
+ data_len, object->length - 8);
+ return -EINVAL;
+ }
+
+ bif_slave_ctrl_lock(slave);
+
+ edit_object = bif_object_consumer_search(nvm, object);
+ if (!edit_object) {
+ pr_err("BIF object not found within slave\n");
+ rc = -EINVAL;
+ goto error_unlock;
+ }
+
+ if (edit_object->addr - nvm->nvm_base_address < nvm->nvm_lock_offset) {
+ pr_err("Cannot overwrite BIF object in NVM because some portion of it is locked\n");
+ rc = -EPERM;
+ goto error_unlock;
+ }
+
+ buf = kzalloc(data_len + 8, GFP_KERNEL);
+ if (!buf) {
+ pr_err("kzalloc failed\n");
+ rc = -ENOMEM;
+ goto error_unlock;
+ }
+
+ buf[0] = type;
+ buf[1] = version;
+ buf[2] = manufacturer_id >> 8;
+ buf[3] = manufacturer_id;
+ buf[4] = (data_len + 8) >> 8;
+ buf[5] = data_len + 8;
+ memcpy(&buf[6], data, data_len);
+ crc = bif_crc_ccitt(buf, data_len + 6);
+ buf[data_len + 6] = crc >> 8;
+ buf[data_len + 7] = crc;
+
+ rc = _bif_slave_nvm_raw_write(slave->sdev,
+ object->addr - nvm->nvm_base_address, buf, data_len + 8);
+ if (rc < 0) {
+ pr_err("NVM write failed, rc=%d\n", rc);
+ kfree(buf);
+ goto error_unlock;
+ }
+ kfree(buf);
+
+ /* Update internal object struct. */
+ edit_object->type = type;
+ edit_object->version = version;
+ edit_object->manufacturer_id = manufacturer_id;
+ edit_object->length = data_len + 8;
+ memcpy(edit_object->data, data, data_len);
+ edit_object->crc = crc;
+
+ /* Update consumer object struct. */
+ object->type = type;
+ object->version = version;
+ object->manufacturer_id = manufacturer_id;
+ object->length = data_len + 8;
+ memcpy(object->data, data, data_len);
+ object->crc = crc;
+
+error_unlock:
+ bif_slave_ctrl_unlock(slave);
+
+ return rc;
+}
+EXPORT_SYMBOL(bif_object_overwrite);
+
+/**
+ * bif_object_delete() - deletes an existing BIF object found in the
+ * non-volatile memory of a slave. Objects found in the
+ * object list in the NVM of the slave are shifted forward
+ * in order to fill the hole left by the deleted object
+ * @slave: BIF slave handle
+ * @object: Existing object in the slave to delete
+ *
+ * Returns 0 on success or errno on failure. bif_object_put() must still be
+ * called after this function in order to free the memory in the consumer
+ * 'object' struct pointer.
+ *
+ * This function will fail if the NVM lock points to an offset after the
+ * beginning of the existing BIF object.
+ */
+int bif_object_delete(struct bif_slave *slave, const struct bif_object *object)
+{
+ struct bif_object *del_object = NULL;
+ struct bif_object *tail_object;
+ struct bif_nvm_function *nvm;
+ bool found = false;
+ int pos = 0;
+ int rc;
+ u8 *buf;
+
+ if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(object)) {
+ pr_err("Invalid input pointer\n");
+ return -EINVAL;
+ }
+
+ nvm = slave->sdev->nvm_function;
+ if (!nvm) {
+ pr_err("BIF slave has no NVM function\n");
+ return -ENODEV;
+ }
+
+ bif_slave_ctrl_lock(slave);
+
+ del_object = bif_object_consumer_search(nvm, object);
+ if (!del_object) {
+ pr_err("BIF object not found within slave\n");
+ rc = -EINVAL;
+ goto error_unlock;
+ }
+
+ if (del_object->addr - nvm->nvm_base_address < nvm->nvm_lock_offset) {
+ pr_err("Cannot delete BIF object in NVM because some portion of it is locked\n");
+ rc = -EPERM;
+ goto error_unlock;
+ }
+
+ buf = kmalloc(nvm->nvm_size, GFP_KERNEL);
+ if (!buf) {
+ pr_err("kzalloc failed\n");
+ rc = -ENOMEM;
+ goto error_unlock;
+ }
+
+ /*
+ * Copy the contents of objects after the one to be deleted into a flat
+ * array.
+ */
+ list_for_each_entry(tail_object, &nvm->object_list, list) {
+ if (found) {
+ bif_object_flatten(&buf[pos], tail_object);
+ pos += tail_object->length;
+ } else if (tail_object == del_object) {
+ found = true;
+ }
+ }
+
+ /* Add the list terminator. */
+ buf[pos++] = BIF_OBJ_END_OF_LIST;
+
+ rc = _bif_slave_nvm_raw_write(slave->sdev,
+ del_object->addr - nvm->nvm_base_address, buf, pos);
+ if (rc < 0) {
+ pr_err("NVM write failed, rc=%d\n", rc);
+ kfree(buf);
+ goto error_unlock;
+ }
+ kfree(buf);
+
+ /* Update the addresses of the objects after the one to be deleted. */
+ found = false;
+ list_for_each_entry(tail_object, &nvm->object_list, list) {
+ if (found)
+ tail_object->addr -= del_object->length;
+ else if (tail_object == del_object)
+ found = true;
+ }
+
+ list_del(&del_object->list);
+ kfree(del_object->data);
+ kfree(del_object);
+ nvm->object_count--;
+
+error_unlock:
+ bif_slave_ctrl_unlock(slave);
+
+ return rc;
+}
+EXPORT_SYMBOL(bif_object_delete);
+
/**
* bif_slave_read() - read contiguous memory values from a BIF slave
* @slave: BIF slave handle
@@ -1492,6 +2336,74 @@
EXPORT_SYMBOL(bif_slave_write);
/**
+ * bif_slave_nvm_raw_read() - read contiguous memory values from a BIF slave's
+ * non-volatile memory (NVM)
+ * @slave: BIF slave handle
+ * @offset: Offset from the beginning of BIF slave NVM to begin reading at
+ * @buf: Buffer to fill with memory values
+ * @len: Number of byte to read
+ *
+ * Returns 0 for success or errno if an error occurred.
+ */
+int bif_slave_nvm_raw_read(struct bif_slave *slave, u16 offset, u8 *buf,
+ int len)
+{
+ if (IS_ERR_OR_NULL(slave)) {
+ pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
+ return -EINVAL;
+ } else if (IS_ERR_OR_NULL(buf)) {
+ pr_err("Invalid buffer pointer=%ld\n", PTR_ERR(buf));
+ return -EINVAL;
+ } else if (!slave->sdev->nvm_function) {
+ pr_err("BIF slave has no NVM function\n");
+ return -ENODEV;
+ } else if (offset + len > slave->sdev->nvm_function->nvm_size) {
+ pr_err("read offset + len = %d > NVM size = %d\n",
+ offset + len, slave->sdev->nvm_function->nvm_size);
+ return -EINVAL;
+ }
+
+ return bif_slave_read(slave,
+ slave->sdev->nvm_function->nvm_base_address + offset, buf, len);
+}
+EXPORT_SYMBOL(bif_slave_nvm_raw_read);
+
+/**
+ * bif_slave_nvm_raw_write() - write contiguous memory values to a BIF slave's
+ * non-volatile memory (NVM)
+ * @slave: BIF slave handle
+ * @offset: Offset from the beginning of BIF slave NVM to begin writing at
+ * @buf: Buffer containing values to write
+ * @len: Number of byte to write
+ *
+ * Note that this function does *not* respect the MIPI-BIF object data
+ * formatting specification. It can cause corruption of the object data list
+ * stored in NVM if used improperly.
+ *
+ * Returns 0 for success or errno if an error occurred.
+ */
+int bif_slave_nvm_raw_write(struct bif_slave *slave, u16 offset, u8 *buf,
+ int len)
+{
+ int rc;
+
+ if (IS_ERR_OR_NULL(slave)) {
+ pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
+ return -EINVAL;
+ } else if (IS_ERR_OR_NULL(buf)) {
+ pr_err("Invalid buffer pointer=%ld\n", PTR_ERR(buf));
+ return -EINVAL;
+ }
+
+ bif_slave_ctrl_lock(slave);
+ rc = _bif_slave_nvm_raw_write(slave->sdev, offset, buf, len);
+ bif_slave_ctrl_unlock(slave);
+
+ return rc;
+}
+EXPORT_SYMBOL(bif_slave_nvm_raw_write);
+
+/**
* bif_slave_is_present() - check if a slave is currently physically present
* in the system
* @slave: BIF slave handle
@@ -2032,45 +2944,6 @@
return rc;
}
-/**
- * bif_crc_ccitt() - calculate the CRC-CCITT CRC value of the data specified
- * @buffer: Data to calculate the CRC of
- * @len: Length of the data buffer in bytes
- *
- * MIPI-BIF specifies the usage of CRC-CCITT for BIF data objects. This
- * function performs the CRC calculation while taking into account the bit
- * ordering used by BIF.
- */
-u16 bif_crc_ccitt(const u8 *buffer, unsigned int len)
-{
- u16 crc = 0xFFFF;
-
- while (len--) {
- crc = crc_ccitt_byte(crc, bitrev8(*buffer));
- buffer++;
- }
- return bitrev16(crc);
-}
-EXPORT_SYMBOL(bif_crc_ccitt);
-
-static u16 bif_object_crc_ccitt(const struct bif_object *object)
-{
- u16 crc = 0xFFFF;
- int i;
-
- crc = crc_ccitt_byte(crc, bitrev8(object->type));
- crc = crc_ccitt_byte(crc, bitrev8(object->version));
- crc = crc_ccitt_byte(crc, bitrev8(object->manufacturer_id >> 8));
- crc = crc_ccitt_byte(crc, bitrev8(object->manufacturer_id));
- crc = crc_ccitt_byte(crc, bitrev8(object->length >> 8));
- crc = crc_ccitt_byte(crc, bitrev8(object->length));
-
- for (i = 0; i < object->length - 8; i++)
- crc = crc_ccitt_byte(crc, bitrev8(object->data[i]));
-
- return bitrev16(crc);
-}
-
/*
* Check if the specified function is an NVM function and if it is, then
* instantiate NVM function data for the slave and read all objects.
@@ -2079,7 +2952,7 @@
struct bif_ddb_l2_data *func)
{
int rc = 0;
- int data_len;
+ int data_len, read_size;
u8 buf[8], object_type;
struct bif_object *object;
struct bif_object *temp;
@@ -2109,12 +2982,21 @@
return rc;
}
- sdev->nvm_function->nvm_pointer = buf[0] << 8 | buf[1];
+ sdev->nvm_function->nvm_pointer = buf[0] << 8 | buf[1];
sdev->nvm_function->slave_control_channel = buf[2];
sdev->nvm_function->write_buffer_size = buf[3];
sdev->nvm_function->nvm_base_address = buf[4] << 8 | buf[5];
sdev->nvm_function->nvm_size = buf[6] << 8 | buf[7];
+ /* Read NVM lock offset */
+ rc = _bif_slave_read(sdev, sdev->nvm_function->nvm_pointer, buf, 2);
+ if (rc) {
+ pr_err("Slave memory read failed, rc=%d\n", rc);
+ return rc;
+ }
+
+ sdev->nvm_function->nvm_lock_offset = buf[0] << 8 | buf[1];
+
INIT_LIST_HEAD(&sdev->nvm_function->object_list);
/* Read object list */
@@ -2125,8 +3007,7 @@
return rc;
}
- /* Object type == 0x00 corresponds to the end of the object list. */
- while (object_type != 0x00) {
+ while (object_type != BIF_OBJ_END_OF_LIST) {
object = kzalloc(sizeof(*object), GFP_KERNEL);
if (!object) {
pr_err("out of memory\n");
@@ -2178,15 +3059,20 @@
goto free_data;
}
- rc = _bif_slave_read(sdev, addr + 6 + data_len, buf, 3);
+ if ((object->length + addr) >= (sdev->nvm_function->nvm_size
+ + sdev->nvm_function->nvm_base_address))
+ read_size = 2;
+ else
+ read_size = 3;
+ rc = _bif_slave_read(sdev, addr + 6 + data_len, buf, read_size);
if (rc) {
pr_err("Slave memory read of object CRC failed; addr=0x%04X, len=%d, rc=%d\n",
- addr + 6 + data_len, 3, rc);
+ addr + 6 + data_len, read_size, rc);
goto free_data;
}
object->crc = buf[0] << 8 | buf[1];
- object_type = buf[2];
+ object_type = (read_size == 3) ? buf[2] : BIF_OBJ_END_OF_LIST;
sdev->nvm_function->object_count++;
crc = bif_object_crc_ccitt(object);
@@ -2336,6 +3222,12 @@
} else if (rc == 1) {
sdev->present = true;
sdev->bdev->selected_sdev = sdev;
+ rc = bif_parse_slave_data(sdev);
+ if (rc) {
+ pr_err("Failed to parse secondary slave data, rc=%d\n",
+ rc);
+ goto free_slave;
+ }
} else {
sdev->present = false;
sdev->bdev->selected_sdev = NULL;
@@ -2459,6 +3351,11 @@
sdev->present = true;
sdev->bdev->selected_sdev = sdev;
rc = bif_parse_slave_data(sdev);
+ if (rc) {
+ pr_err("Failed to parse secondary slave data, rc=%d\n",
+ rc);
+ return rc;
+ }
} else {
pr_err("Slave failed to respond to DILC bus command; its UID is thus unverified.\n");
sdev->unique_id_bits_known = 0;
diff --git a/drivers/bif/qpnp-bsi.c b/drivers/bif/qpnp-bsi.c
index 19a560a..e3f7d2f 100644
--- a/drivers/bif/qpnp-bsi.c
+++ b/drivers/bif/qpnp-bsi.c
@@ -170,7 +170,7 @@
#define QPNP_BSI_DEFAULT_VID_REF_UV 1800000
/* These have units of tau_bif. */
-#define QPNP_BSI_MAX_TRANSMIT_CYCLES 36
+#define QPNP_BSI_MAX_TRANSMIT_CYCLES 46
#define QPNP_BSI_MIN_RECEIVE_CYCLES 24
#define QPNP_BSI_MAX_BUS_QUERY_CYCLES 17
@@ -544,12 +544,6 @@
struct qpnp_bsi_chip *chip = bdev_get_drvdata(bdev);
int rc;
- rc = qpnp_bsi_clear_bsi_error(chip);
- if (rc)
- return rc;
-
- qpnp_bsi_clear_irq_flags(chip);
-
qpnp_bsi_set_com_mode(chip, QPNP_BSI_COM_MODE_IRQ);
rc = qpnp_bsi_set_bus_state(bdev, BIF_BUS_STATE_ACTIVE);
@@ -563,6 +557,12 @@
if (rc)
return rc;
+ rc = qpnp_bsi_clear_bsi_error(chip);
+ if (rc)
+ return rc;
+
+ qpnp_bsi_clear_irq_flags(chip);
+
rc = qpnp_bsi_issue_transaction_wait_for_tx(chip, transaction, data);
if (rc)
return rc;
@@ -578,12 +578,6 @@
struct qpnp_bsi_chip *chip = bdev_get_drvdata(bdev);
int rc, timeout;
- rc = qpnp_bsi_clear_bsi_error(chip);
- if (rc)
- return rc;
-
- qpnp_bsi_clear_irq_flags(chip);
-
qpnp_bsi_set_com_mode(chip, QPNP_BSI_COM_MODE_IRQ);
rc = qpnp_bsi_set_bus_state(bdev, BIF_BUS_STATE_ACTIVE);
@@ -597,6 +591,12 @@
if (rc)
return rc;
+ rc = qpnp_bsi_clear_bsi_error(chip);
+ if (rc)
+ return rc;
+
+ qpnp_bsi_clear_irq_flags(chip);
+
rc = qpnp_bsi_issue_transaction_wait_for_tx(chip, transaction, data);
if (rc)
return rc;
@@ -624,12 +624,6 @@
int rc, timeout;
u8 buf[3];
- rc = qpnp_bsi_clear_bsi_error(chip);
- if (rc)
- return rc;
-
- qpnp_bsi_clear_irq_flags(chip);
-
qpnp_bsi_set_com_mode(chip, QPNP_BSI_COM_MODE_IRQ);
rc = qpnp_bsi_set_bus_state(bdev, BIF_BUS_STATE_ACTIVE);
@@ -643,6 +637,12 @@
if (rc)
return rc;
+ rc = qpnp_bsi_clear_bsi_error(chip);
+ if (rc)
+ return rc;
+
+ qpnp_bsi_clear_irq_flags(chip);
+
rc = qpnp_bsi_issue_transaction_wait_for_tx(chip, transaction, data);
if (rc)
return rc;
@@ -826,10 +826,10 @@
/*
* Send burst read length bus commands according to the following:
*
- * 256 --> RBL0
- * 0-255 = 16 * y + x --> RBEy and RBLx
- * RBE0 does not need to be sent
- * RBL0 does not need to be sent
+ * 1 --> No RBE or RBL
+ * 2 - 15 = x --> RBLx
+ * 16 - 255 = 16 * y + x --> RBEy and RBLx (RBL0 not sent)
+ * 256 --> RBL0
*/
if (burst_len == 256) {
rc = qpnp_bsi_issue_transaction(chip, BIF_TRANS_BC,
@@ -851,7 +851,7 @@
return rc;
}
- if (burst_len % 16) {
+ if (burst_len % 16 && burst_len > 1) {
rc = qpnp_bsi_issue_transaction(chip, BIF_TRANS_BC,
BIF_CMD_RBL + (burst_len % 16));
if (rc)
@@ -906,12 +906,6 @@
int rc, rc2, i, burst_len;
u8 buf[3];
- rc = qpnp_bsi_clear_bsi_error(chip);
- if (rc)
- return rc;
-
- qpnp_bsi_clear_irq_flags(chip);
-
qpnp_bsi_set_com_mode(chip, QPNP_BSI_COM_MODE_POLL);
rc = qpnp_bsi_set_bus_state(bdev, BIF_BUS_STATE_ACTIVE);
@@ -925,6 +919,12 @@
if (rc)
return rc;
+ rc = qpnp_bsi_clear_bsi_error(chip);
+ if (rc)
+ return rc;
+
+ qpnp_bsi_clear_irq_flags(chip);
+
while (len > 0) {
burst_len = min(len, 256);
@@ -1001,12 +1001,6 @@
unsigned long flags;
int rc, rc2, i;
- rc = qpnp_bsi_clear_bsi_error(chip);
- if (rc)
- return rc;
-
- qpnp_bsi_clear_irq_flags(chip);
-
qpnp_bsi_set_com_mode(chip, QPNP_BSI_COM_MODE_POLL);
rc = qpnp_bsi_set_bus_state(bdev, BIF_BUS_STATE_ACTIVE);
@@ -1020,6 +1014,12 @@
if (rc)
return rc;
+ rc = qpnp_bsi_clear_bsi_error(chip);
+ if (rc)
+ return rc;
+
+ qpnp_bsi_clear_irq_flags(chip);
+
rc = qpnp_bsi_issue_transaction(chip, BIF_TRANS_ERA, addr >> 8);
if (rc)
return rc;
@@ -1075,12 +1075,6 @@
struct qpnp_bsi_chip *chip = bdev_get_drvdata(bdev);
int rc;
- rc = qpnp_bsi_clear_bsi_error(chip);
- if (rc)
- return rc;
-
- qpnp_bsi_clear_irq_flags(chip);
-
qpnp_bsi_set_com_mode(chip, QPNP_BSI_COM_MODE_IRQ);
/*
@@ -1105,6 +1099,12 @@
*/
chip->state = BIF_BUS_STATE_INTERRUPT;
+ rc = qpnp_bsi_clear_bsi_error(chip);
+ if (rc)
+ return rc;
+
+ qpnp_bsi_clear_irq_flags(chip);
+
/* Send EINT bus command. */
rc = qpnp_bsi_issue_transaction_wait_for_tx(chip, BIF_TRANS_BC,
BIF_CMD_EINT);
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index c4f762d..beaf75d 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -105,6 +105,9 @@
"RIVA CNTL in_buf_1_size: %d\n"
"Modem DCI in_buf_1_size: %d\n"
"Modem DCI CMD in_buf_1_size: %d\n"
+ "Received Feature mask from Modem: %d\n"
+ "Received Feature mask from LPASS: %d\n"
+ "Received Feature mask from WCNSS: %d\n"
"logging_mode: %d\n"
"real_time_mode: %d\n",
(unsigned int)driver->smd_data[MODEM_DATA].ch,
@@ -171,6 +174,9 @@
(unsigned int)driver->smd_cntl[WCNSS_DATA].buf_in_1_size,
(unsigned int)driver->smd_dci[MODEM_DATA].buf_in_1_size,
(unsigned int)driver->smd_dci_cmd[MODEM_DATA].buf_in_1_size,
+ driver->rcvd_feature_mask[MODEM_DATA],
+ driver->rcvd_feature_mask[LPASS_DATA],
+ driver->rcvd_feature_mask[WCNSS_DATA],
driver->logging_mode,
driver->real_time_mode);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index e0a428d..9d9d89b 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -340,6 +340,7 @@
struct diag_smd_info smd_dci[NUM_SMD_DCI_CHANNELS];
struct diag_smd_info smd_cmd[NUM_SMD_CMD_CHANNELS];
struct diag_smd_info smd_dci_cmd[NUM_SMD_DCI_CMD_CHANNELS];
+ int rcvd_feature_mask[NUM_SMD_CONTROL_CHANNELS];
int separate_cmdrsp[NUM_SMD_CONTROL_CHANNELS];
unsigned char *usb_buf_out;
unsigned char *apps_rsp_buf;
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index c74ab99..1a7b2f8 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -203,11 +203,12 @@
* has registered to respond for polling
*/
return 1;
- else if (!(driver->smd_data[MODEM_DATA].ch) &&
- !(chk_apps_master()))
+ else if (!((driver->smd_data[MODEM_DATA].ch) &&
+ (driver->rcvd_feature_mask[MODEM_DATA])) &&
+ (chk_apps_master()))
/*
* If the apps processor is not the master and the modem
- * is not up
+ * is not up or we did not receive the feature masks from Modem
*/
return 1;
else
@@ -1170,6 +1171,18 @@
return 0;
}
+int diag_apps_responds()
+{
+ if (chk_apps_only()) {
+ if (driver->smd_data[MODEM_DATA].ch &&
+ driver->rcvd_feature_mask[MODEM_DATA]) {
+ return 0;
+ }
+ return 1;
+ }
+ return 0;
+}
+
int diag_process_apps_pkt(unsigned char *buf, int len)
{
uint16_t subsys_cmd_code;
@@ -1204,7 +1217,8 @@
pr_debug("diag: %d %d %d", cmd_code, subsys_id, subsys_cmd_code);
for (i = 0; i < diag_max_reg; i++) {
entry = driver->table[i];
- if (entry.process_id != NO_PROCESS) {
+ if (entry.process_id != NO_PROCESS &&
+ driver->rcvd_feature_mask[entry.client_id]) {
if (entry.cmd_code == cmd_code && entry.subsys_id ==
subsys_id && entry.cmd_code_lo <=
subsys_cmd_code &&
@@ -1250,8 +1264,7 @@
return diag_process_stm_cmd(buf);
}
/* Check for Apps Only & get event mask request */
- else if (!(driver->smd_data[MODEM_DATA].ch) && chk_apps_only() &&
- *buf == 0x81) {
+ else if (diag_apps_responds() && *buf == 0x81) {
driver->apps_rsp_buf[0] = 0x81;
driver->apps_rsp_buf[1] = 0x0;
*(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
@@ -1262,8 +1275,8 @@
return 0;
}
/* Get log ID range & Check for Apps Only */
- else if (!(driver->smd_data[MODEM_DATA].ch) && chk_apps_only()
- && (*buf == 0x73) && *(int *)(buf+4) == 1) {
+ else if (diag_apps_responds() && (*buf == 0x73) &&
+ *(int *)(buf+4) == 1) {
driver->apps_rsp_buf[0] = 0x73;
*(int *)(driver->apps_rsp_buf + 4) = 0x1; /* operation ID */
*(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success code */
@@ -1287,8 +1300,8 @@
return 0;
}
/* Respond to Get SSID Range request message */
- else if (!(driver->smd_data[MODEM_DATA].ch) && chk_apps_only()
- && (*buf == 0x7d) && (*(buf+1) == 0x1)) {
+ else if (diag_apps_responds() && (*buf == 0x7d) &&
+ (*(buf+1) == 0x1)) {
driver->apps_rsp_buf[0] = 0x7d;
driver->apps_rsp_buf[1] = 0x1;
driver->apps_rsp_buf[2] = 0x1;
@@ -1345,8 +1358,8 @@
return 0;
}
/* Check for Apps Only Respond to Get Subsys Build mask */
- else if (!(driver->smd_data[MODEM_DATA].ch) && chk_apps_only()
- && (*buf == 0x7d) && (*(buf+1) == 0x2)) {
+ else if (diag_apps_responds() && (*buf == 0x7d) &&
+ (*(buf+1) == 0x2)) {
ssid_first = *(uint16_t *)(buf + 2);
ssid_last = *(uint16_t *)(buf + 4);
ssid_range = 4 * (ssid_last - ssid_first + 1);
@@ -2444,6 +2457,7 @@
for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++) {
driver->separate_cmdrsp[i] = 0;
driver->peripheral_supports_stm[i] = DISABLE_STM;
+ driver->rcvd_feature_mask[i] = 0;
}
for (i = 0; i < NUM_STM_PROCESSORS; i++) {
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index c6e1273..1a4601a 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -53,6 +53,7 @@
void diag_cmp_logging_modes_diagfwd_bridge(int old_mode, int new_mode);
int diag_process_apps_pkt(unsigned char *buf, int len);
void diag_reset_smd_data(int queue);
+int diag_apps_responds(void);
/* State for diag forwarding */
#ifdef CONFIG_DIAG_OVER_USB
int diagfwd_connect(void);
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index e0deef3..d784678 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -37,6 +37,9 @@
diag_clear_reg(smd_info->peripheral);
reg_dirty ^= smd_info->peripheral_mask;
+ /* Reset the feature mask flag */
+ driver->rcvd_feature_mask[smd_info->peripheral] = 0;
+
smd_info->notify_context = 0;
}
@@ -158,14 +161,21 @@
msg = buf+HDR_SIZ;
range = buf+HDR_SIZ+
sizeof(struct diag_ctrl_msg);
+ if (msg->count_entries == 0) {
+ pr_debug("diag: In %s, received reg tbl with no entries\n",
+ __func__);
+ buf = buf + HDR_SIZ + data_len;
+ continue;
+ }
pkt_params->count = msg->count_entries;
pkt_params->params = kzalloc(pkt_params->count *
sizeof(struct bindpkt_params), GFP_KERNEL);
- if (ZERO_OR_NULL_PTR(pkt_params->params)) {
- pr_alert("diag: In %s, Memory alloc fail\n",
- __func__);
- kfree(pkt_params);
- return flag;
+ if (!pkt_params->params) {
+ pr_alert("diag: In %s, Memory alloc fail for cmd_code: %d, subsys: %d\n",
+ __func__, msg->cmd_code,
+ msg->subsysid);
+ buf = buf + HDR_SIZ + data_len;
+ continue;
}
temp = pkt_params->params;
for (j = 0; j < pkt_params->count; j++) {
@@ -195,6 +205,8 @@
int feature_mask_len = *(int *)(buf+8);
if (feature_mask_len > 0) {
int periph = smd_info->peripheral;
+ driver->rcvd_feature_mask[smd_info->peripheral]
+ = 1;
feature_mask = *(uint8_t *)(buf+12);
if (periph == MODEM_DATA)
driver->log_on_demand_support =
@@ -262,31 +274,39 @@
{
int temp_real_time = MODE_REALTIME, i;
- /* If any of the process is voting for Real time, then Diag
- should be in real time mode irrespective of other clauses. If
- USB is connected, check what the memory device process is
- voting for. If it is voting for Non real time, the final mode
- should be Non real time, real time otherwise. If USB is
- disconncted and no process is voting for real time, the
- resultant mode should be Non Real Time.
- */
- if ((driver->proc_rt_vote_mask & driver->proc_active_mask) &&
- (driver->proc_active_mask != 0))
- temp_real_time = MODE_REALTIME;
- else if (driver->usb_connected)
+ if (driver->proc_active_mask == 0) {
+ /* There are no DCI or Memory Device processes. Diag should
+ * be in Real Time mode irrespective of USB connection
+ */
+ temp_real_time = MODE_REALTIME;
+ } else if (driver->proc_rt_vote_mask & driver->proc_active_mask) {
+ /* Atleast one process is alive and is voting for Real Time
+ * data - Diag should be in real time mode irrespective of USB
+ * connection.
+ */
+ temp_real_time = MODE_REALTIME;
+ } else if (driver->usb_connected) {
+ /* If USB is connected, check individual process. If Memory
+ * Device Mode is active, set the mode requested by Memory
+ * Device process. Set to realtime mode otherwise.
+ */
if ((driver->proc_rt_vote_mask & DIAG_PROC_MEMORY_DEVICE) == 0)
temp_real_time = MODE_NONREALTIME;
else
temp_real_time = MODE_REALTIME;
- else
+ } else {
+ /* We come here if USB is not connected and the active
+ * processes are voting for Non realtime mode.
+ */
temp_real_time = MODE_NONREALTIME;
+ }
if (temp_real_time != driver->real_time_mode) {
for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++)
diag_send_diag_mode_update_by_smd(&driver->smd_cntl[i],
temp_real_time);
} else {
- pr_info("diag: did not update real time mode, already in the req mode %d",
+ pr_debug("diag: did not update real time mode, already in the req mode %d",
temp_real_time);
}
if (driver->real_time_update_busy > 0)
@@ -297,9 +317,15 @@
{
int temp_real_time = MODE_REALTIME, i;
- if (!(driver->proc_rt_vote_mask & driver->proc_active_mask) &&
- (driver->proc_active_mask != 0))
+ if (driver->proc_active_mask == 0) {
+ /* There are no DCI or Memory Device processes. Diag should
+ * be in Real Time mode.
+ */
+ temp_real_time = MODE_REALTIME;
+ } else if (!(driver->proc_rt_vote_mask & driver->proc_active_mask)) {
+ /* No active process is voting for real time mode */
temp_real_time = MODE_NONREALTIME;
+ }
if (temp_real_time != driver->real_time_mode) {
for (i = 0; i < NUM_SMD_CONTROL_CHANNELS; i++)
diff --git a/drivers/coresight/Kconfig b/drivers/coresight/Kconfig
index 5e2acfb..fc6df7b 100644
--- a/drivers/coresight/Kconfig
+++ b/drivers/coresight/Kconfig
@@ -151,6 +151,38 @@
If unsure, say 'N' here to avoid potential power penalty.
+config CORESIGHT_AUDIO_ETM
+ bool "Audio processor ETM trace support"
+ help
+ Enables support for ETM trace collection on audio processor using
+ CoreSight framework. Enabling this will allow turning on ETM tracing
+ on audio processor via sysfs by configuring the required CoreSight
+ components.
+
+config CORESIGHT_MODEM_ETM
+ bool "Modem processor ETM trace support"
+ help
+ Enables support for ETM trace collection on modem processor using
+ CoreSight framework. Enabling this will allow turning on ETM tracing
+ on modem processor via sysfs by configuring the required CoreSight
+ components.
+
+config CORESIGHT_WCN_ETM
+ bool "Wireless subsystem processor ETM trace support"
+ help
+ Enables support for ETM trace collection on wireless subsystem
+ processor using CoreSight framework. Enabling this will allow
+ turning on ETM tracing on wireless subsystem via sysfs by configuring
+ the required CoreSight components.
+
+config CORESIGHT_RPM_ETM
+ bool "RPM processor ETM trace support"
+ help
+ Enables support for ETM trace collection on RPM processor using
+ CoreSight framework. Enabling this will allow turning on ETM
+ tracing on RPM processor via sysfs by configuring the required
+ CoreSight components.
+
endif
config CORESIGHT_EVENT
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 23352a7..9d93a6c 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -13,4 +13,8 @@
obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
obj-$(CONFIG_CORESIGHT_HWEVENT) += coresight-hwevent.o
obj-$(CONFIG_CORESIGHT_ETM) += coresight-etm.o coresight-etm-cp14.o
+obj-$(CONFIG_CORESIGHT_AUDIO_ETM) += coresight-audio-etm.o
+obj-$(CONFIG_CORESIGHT_MODEM_ETM) += coresight-modem-etm.o
+obj-$(CONFIG_CORESIGHT_WCN_ETM) += coresight-wcn-etm.o
+obj-$(CONFIG_CORESIGHT_RPM_ETM) += coresight-rpm-etm.o
obj-$(CONFIG_CORESIGHT_EVENT) += coresight-event.o
diff --git a/drivers/coresight/coresight-audio-etm.c b/drivers/coresight/coresight-audio-etm.c
new file mode 100644
index 0000000..cdf44bf
--- /dev/null
+++ b/drivers/coresight/coresight-audio-etm.c
@@ -0,0 +1,132 @@
+/* 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/of_coresight.h>
+#include <linux/coresight.h>
+
+struct audio_etm_drvdata {
+ struct device *dev;
+ struct coresight_device *csdev;
+};
+
+static int audio_etm_enable(struct coresight_device *csdev)
+{
+ struct audio_etm_drvdata *drvdata =
+ dev_get_drvdata(csdev->dev.parent);
+
+ dev_info(drvdata->dev, "Audio ETM tracing enabled\n");
+ return 0;
+}
+
+
+static void audio_etm_disable(struct coresight_device *csdev)
+{
+ struct audio_etm_drvdata *drvdata =
+ dev_get_drvdata(csdev->dev.parent);
+
+ dev_info(drvdata->dev, "Audio ETM tracing disabled\n");
+}
+
+static const struct coresight_ops_source audio_etm_source_ops = {
+ .enable = audio_etm_enable,
+ .disable = audio_etm_disable,
+};
+
+static const struct coresight_ops audio_cs_ops = {
+ .source_ops = &audio_etm_source_ops,
+};
+
+static int audio_etm_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct coresight_platform_data *pdata;
+ struct audio_etm_drvdata *drvdata;
+ struct coresight_desc *desc;
+
+ if (pdev->dev.of_node) {
+ pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ pdev->dev.platform_data = pdata;
+ }
+
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
+ drvdata->dev = &pdev->dev;
+ platform_set_drvdata(pdev, drvdata);
+
+ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ desc->type = CORESIGHT_DEV_TYPE_SOURCE;
+ desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
+ desc->ops = &audio_cs_ops;
+ desc->pdata = pdev->dev.platform_data;
+ desc->dev = &pdev->dev;
+ desc->owner = THIS_MODULE;
+ drvdata->csdev = coresight_register(desc);
+ if (IS_ERR(drvdata->csdev))
+ return PTR_ERR(drvdata->csdev);
+
+ dev_info(dev, "Audio ETM initialized\n");
+ return 0;
+}
+
+static int audio_etm_remove(struct platform_device *pdev)
+{
+ struct audio_etm_drvdata *drvdata = platform_get_drvdata(pdev);
+
+ coresight_unregister(drvdata->csdev);
+ return 0;
+}
+
+static struct of_device_id audio_etm_match[] = {
+ {.compatible = "qcom,coresight-audio-etm"},
+ {}
+};
+
+static struct platform_driver audio_etm_driver = {
+ .probe = audio_etm_probe,
+ .remove = audio_etm_remove,
+ .driver = {
+ .name = "coresight-audio-etm",
+ .owner = THIS_MODULE,
+ .of_match_table = audio_etm_match,
+ },
+};
+
+int __init audio_etm_init(void)
+{
+ return platform_driver_register(&audio_etm_driver);
+}
+module_init(audio_etm_init);
+
+void __exit audio_etm_exit(void)
+{
+ platform_driver_unregister(&audio_etm_driver);
+}
+module_exit(audio_etm_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Audio ETM driver");
diff --git a/drivers/coresight/coresight-modem-etm.c b/drivers/coresight/coresight-modem-etm.c
new file mode 100644
index 0000000..4c8075c
--- /dev/null
+++ b/drivers/coresight/coresight-modem-etm.c
@@ -0,0 +1,132 @@
+/* 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/of_coresight.h>
+#include <linux/coresight.h>
+
+struct modem_etm_drvdata {
+ struct device *dev;
+ struct coresight_device *csdev;
+};
+
+static int modem_etm_enable(struct coresight_device *csdev)
+{
+ struct modem_etm_drvdata *drvdata =
+ dev_get_drvdata(csdev->dev.parent);
+
+ dev_info(drvdata->dev, "Modem ETM tracing enabled\n");
+ return 0;
+}
+
+
+static void modem_etm_disable(struct coresight_device *csdev)
+{
+ struct modem_etm_drvdata *drvdata =
+ dev_get_drvdata(csdev->dev.parent);
+
+ dev_info(drvdata->dev, "Modem ETM tracing disabled\n");
+}
+
+static const struct coresight_ops_source modem_etm_source_ops = {
+ .enable = modem_etm_enable,
+ .disable = modem_etm_disable,
+};
+
+static const struct coresight_ops modem_cs_ops = {
+ .source_ops = &modem_etm_source_ops,
+};
+
+static int modem_etm_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct coresight_platform_data *pdata;
+ struct modem_etm_drvdata *drvdata;
+ struct coresight_desc *desc;
+
+ if (pdev->dev.of_node) {
+ pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ pdev->dev.platform_data = pdata;
+ }
+
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
+ drvdata->dev = &pdev->dev;
+ platform_set_drvdata(pdev, drvdata);
+
+ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ desc->type = CORESIGHT_DEV_TYPE_SOURCE;
+ desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
+ desc->ops = &modem_cs_ops;
+ desc->pdata = pdev->dev.platform_data;
+ desc->dev = &pdev->dev;
+ desc->owner = THIS_MODULE;
+ drvdata->csdev = coresight_register(desc);
+ if (IS_ERR(drvdata->csdev))
+ return PTR_ERR(drvdata->csdev);
+
+ dev_info(dev, "Modem ETM initialized\n");
+ return 0;
+}
+
+static int modem_etm_remove(struct platform_device *pdev)
+{
+ struct modem_etm_drvdata *drvdata = platform_get_drvdata(pdev);
+
+ coresight_unregister(drvdata->csdev);
+ return 0;
+}
+
+static struct of_device_id modem_etm_match[] = {
+ {.compatible = "qcom,coresight-modem-etm"},
+ {}
+};
+
+static struct platform_driver modem_etm_driver = {
+ .probe = modem_etm_probe,
+ .remove = modem_etm_remove,
+ .driver = {
+ .name = "coresight-modem-etm",
+ .owner = THIS_MODULE,
+ .of_match_table = modem_etm_match,
+ },
+};
+
+int __init modem_etm_init(void)
+{
+ return platform_driver_register(&modem_etm_driver);
+}
+module_init(modem_etm_init);
+
+void __exit modem_etm_exit(void)
+{
+ platform_driver_unregister(&modem_etm_driver);
+}
+module_exit(modem_etm_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Modem ETM driver");
diff --git a/drivers/coresight/coresight-rpm-etm.c b/drivers/coresight/coresight-rpm-etm.c
new file mode 100644
index 0000000..e752e4f
--- /dev/null
+++ b/drivers/coresight/coresight-rpm-etm.c
@@ -0,0 +1,132 @@
+/* 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/of_coresight.h>
+#include <linux/coresight.h>
+
+struct rpm_etm_drvdata {
+ struct device *dev;
+ struct coresight_device *csdev;
+};
+
+static int rpm_etm_enable(struct coresight_device *csdev)
+{
+ struct rpm_etm_drvdata *drvdata =
+ dev_get_drvdata(csdev->dev.parent);
+
+ dev_info(drvdata->dev, "RPM ETM tracing enabled\n");
+ return 0;
+}
+
+
+static void rpm_etm_disable(struct coresight_device *csdev)
+{
+ struct rpm_etm_drvdata *drvdata =
+ dev_get_drvdata(csdev->dev.parent);
+
+ dev_info(drvdata->dev, "RPM ETM tracing disabled\n");
+}
+
+static const struct coresight_ops_source rpm_etm_source_ops = {
+ .enable = rpm_etm_enable,
+ .disable = rpm_etm_disable,
+};
+
+static const struct coresight_ops rpm_cs_ops = {
+ .source_ops = &rpm_etm_source_ops,
+};
+
+static int rpm_etm_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct coresight_platform_data *pdata;
+ struct rpm_etm_drvdata *drvdata;
+ struct coresight_desc *desc;
+
+ if (pdev->dev.of_node) {
+ pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ pdev->dev.platform_data = pdata;
+ }
+
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
+ drvdata->dev = &pdev->dev;
+ platform_set_drvdata(pdev, drvdata);
+
+ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ desc->type = CORESIGHT_DEV_TYPE_SOURCE;
+ desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
+ desc->ops = &rpm_cs_ops;
+ desc->pdata = pdev->dev.platform_data;
+ desc->dev = &pdev->dev;
+ desc->owner = THIS_MODULE;
+ drvdata->csdev = coresight_register(desc);
+ if (IS_ERR(drvdata->csdev))
+ return PTR_ERR(drvdata->csdev);
+
+ dev_info(dev, "RPM ETM initialized\n");
+ return 0;
+}
+
+static int rpm_etm_remove(struct platform_device *pdev)
+{
+ struct rpm_etm_drvdata *drvdata = platform_get_drvdata(pdev);
+
+ coresight_unregister(drvdata->csdev);
+ return 0;
+}
+
+static struct of_device_id rpm_etm_match[] = {
+ {.compatible = "qcom,coresight-rpm-etm"},
+ {}
+};
+
+static struct platform_driver rpm_etm_driver = {
+ .probe = rpm_etm_probe,
+ .remove = rpm_etm_remove,
+ .driver = {
+ .name = "coresight-rpm-etm",
+ .owner = THIS_MODULE,
+ .of_match_table = rpm_etm_match,
+ },
+};
+
+int __init rpm_etm_init(void)
+{
+ return platform_driver_register(&rpm_etm_driver);
+}
+module_init(rpm_etm_init);
+
+void __exit rpm_etm_exit(void)
+{
+ platform_driver_unregister(&rpm_etm_driver);
+}
+module_exit(rpm_etm_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight RPM ETM driver");
diff --git a/drivers/coresight/coresight-wcn-etm.c b/drivers/coresight/coresight-wcn-etm.c
new file mode 100644
index 0000000..44852fb
--- /dev/null
+++ b/drivers/coresight/coresight-wcn-etm.c
@@ -0,0 +1,132 @@
+/* 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/of_coresight.h>
+#include <linux/coresight.h>
+
+struct wcn_etm_drvdata {
+ struct device *dev;
+ struct coresight_device *csdev;
+};
+
+static int wcn_etm_enable(struct coresight_device *csdev)
+{
+ struct wcn_etm_drvdata *drvdata =
+ dev_get_drvdata(csdev->dev.parent);
+
+ dev_info(drvdata->dev, "Wireless ETM tracing enabled\n");
+ return 0;
+}
+
+
+static void wcn_etm_disable(struct coresight_device *csdev)
+{
+ struct wcn_etm_drvdata *drvdata =
+ dev_get_drvdata(csdev->dev.parent);
+
+ dev_info(drvdata->dev, "Wireless ETM tracing disabled\n");
+}
+
+static const struct coresight_ops_source wcn_etm_source_ops = {
+ .enable = wcn_etm_enable,
+ .disable = wcn_etm_disable,
+};
+
+static const struct coresight_ops wcn_cs_ops = {
+ .source_ops = &wcn_etm_source_ops,
+};
+
+static int wcn_etm_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct coresight_platform_data *pdata;
+ struct wcn_etm_drvdata *drvdata;
+ struct coresight_desc *desc;
+
+ if (pdev->dev.of_node) {
+ pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+ if (IS_ERR(pdata))
+ return PTR_ERR(pdata);
+ pdev->dev.platform_data = pdata;
+ }
+
+ drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
+ drvdata->dev = &pdev->dev;
+ platform_set_drvdata(pdev, drvdata);
+
+ desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+ if (!desc)
+ return -ENOMEM;
+
+ desc->type = CORESIGHT_DEV_TYPE_SOURCE;
+ desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
+ desc->ops = &wcn_cs_ops;
+ desc->pdata = pdev->dev.platform_data;
+ desc->dev = &pdev->dev;
+ desc->owner = THIS_MODULE;
+ drvdata->csdev = coresight_register(desc);
+ if (IS_ERR(drvdata->csdev))
+ return PTR_ERR(drvdata->csdev);
+
+ dev_info(dev, "Wireless ETM initialized\n");
+ return 0;
+}
+
+static int wcn_etm_remove(struct platform_device *pdev)
+{
+ struct wcn_etm_drvdata *drvdata = platform_get_drvdata(pdev);
+
+ coresight_unregister(drvdata->csdev);
+ return 0;
+}
+
+static struct of_device_id wcn_etm_match[] = {
+ {.compatible = "qcom,coresight-wcn-etm"},
+ {}
+};
+
+static struct platform_driver wcn_etm_driver = {
+ .probe = wcn_etm_probe,
+ .remove = wcn_etm_remove,
+ .driver = {
+ .name = "coresight-wcn-etm",
+ .owner = THIS_MODULE,
+ .of_match_table = wcn_etm_match,
+ },
+};
+
+int __init wcn_etm_init(void)
+{
+ return platform_driver_register(&wcn_etm_driver);
+}
+module_init(wcn_etm_init);
+
+void __exit wcn_etm_exit(void)
+{
+ platform_driver_unregister(&wcn_etm_driver);
+}
+module_exit(wcn_etm_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Wireless ETM driver");
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 374170d..975a42f 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1114,10 +1114,10 @@
#ifdef CONFIG_HOTPLUG_CPU
strncpy(per_cpu(cpufreq_policy_save, cpu).gov, data->governor->name,
CPUFREQ_NAME_LEN);
- per_cpu(cpufreq_policy_save, cpu).min = data->min;
- per_cpu(cpufreq_policy_save, cpu).max = data->max;
- pr_debug("Saving CPU%d policy min %d and max %d\n",
- cpu, data->min, data->max);
+ per_cpu(cpufreq_policy_save, cpu).min = data->user_policy.min;
+ per_cpu(cpufreq_policy_save, cpu).max = data->user_policy.max;
+ pr_debug("Saving CPU%d user policy min %d and max %d\n",
+ cpu, data->user_policy.min, data->user_policy.max);
#endif
/* if we have other CPUs still registered, we need to unlink them,
@@ -1143,9 +1143,11 @@
#ifdef CONFIG_HOTPLUG_CPU
strncpy(per_cpu(cpufreq_policy_save, j).gov,
data->governor->name, CPUFREQ_NAME_LEN);
- per_cpu(cpufreq_policy_save, j).min = data->min;
- per_cpu(cpufreq_policy_save, j).max = data->max;
- pr_debug("Saving CPU%d policy min %d and max %d\n",
+ per_cpu(cpufreq_policy_save, j).min
+ = data->user_policy.min;
+ per_cpu(cpufreq_policy_save, j).max
+ = data->user_policy.max;
+ pr_debug("Saving CPU%d user policy min %d and max %d\n",
j, data->min, data->max);
#endif
cpu_dev = get_cpu_device(j);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index e6b2a3c..af494c6 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -144,6 +144,7 @@
unsigned int sampling_down_factor;
int powersave_bias;
unsigned int io_is_busy;
+ unsigned int input_boost;
} dbs_tuners_ins = {
.up_threshold_multi_core = DEF_FREQUENCY_UP_THRESHOLD,
.up_threshold = DEF_FREQUENCY_UP_THRESHOLD,
@@ -155,6 +156,7 @@
.powersave_bias = 0,
.sync_freq = 0,
.optimal_freq = 0,
+ .input_boost = 0,
};
static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall)
@@ -319,6 +321,7 @@
show_one(optimal_freq, optimal_freq);
show_one(up_threshold_any_cpu_load, up_threshold_any_cpu_load);
show_one(sync_freq, sync_freq);
+show_one(input_boost, input_boost);
static ssize_t show_powersave_bias
(struct kobject *kobj, struct attribute *attr, char *buf)
@@ -396,6 +399,18 @@
return count;
}
+static ssize_t store_input_boost(struct kobject *a, struct attribute *b,
+ const char *buf, size_t count)
+{
+ unsigned int input;
+ int ret;
+ ret = sscanf(buf, "%u", &input);
+ if (ret != 1)
+ return -EINVAL;
+ dbs_tuners_ins.input_boost = input;
+ return count;
+}
+
static ssize_t store_sync_freq(struct kobject *a, struct attribute *b,
const char *buf, size_t count)
{
@@ -680,6 +695,7 @@
define_one_global_rw(optimal_freq);
define_one_global_rw(up_threshold_any_cpu_load);
define_one_global_rw(sync_freq);
+define_one_global_rw(input_boost);
static struct attribute *dbs_attributes[] = {
&sampling_rate_min.attr,
@@ -694,6 +710,7 @@
&optimal_freq.attr,
&up_threshold_any_cpu_load.attr,
&sync_freq.attr,
+ &input_boost.attr,
NULL
};
@@ -1006,6 +1023,7 @@
struct cpu_dbs_info_s *this_dbs_info;
struct dbs_work_struct *dbs_work;
unsigned int cpu;
+ unsigned int target_freq;
dbs_work = container_of(work, struct dbs_work_struct, work);
cpu = dbs_work->cpu;
@@ -1022,14 +1040,19 @@
goto bail_incorrect_governor;
}
- if (policy->cur < policy->max) {
+ if (dbs_tuners_ins.input_boost)
+ target_freq = dbs_tuners_ins.input_boost;
+ else
+ target_freq = policy->max;
+
+ if (policy->cur < target_freq) {
/*
* Arch specific cpufreq driver may fail.
* Don't update governor frequency upon failure.
*/
- if (__cpufreq_driver_target(policy, policy->max,
+ if (__cpufreq_driver_target(policy, target_freq,
CPUFREQ_RELATION_L) >= 0)
- policy->cur = policy->max;
+ policy->cur = target_freq;
this_dbs_info->prev_cpu_idle = get_cpu_idle_time(cpu,
&this_dbs_info->prev_cpu_wall);
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index c726694..81a90fe 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -79,6 +79,7 @@
uint8_t first_blk;
uint8_t last_blk;
uint8_t authkey[QCEDEV_MAX_SHA_BLOCK_SIZE];
+ bool init_done;
};
struct qcedev_async_req {
@@ -744,6 +745,7 @@
sha_ctxt->diglen = SHA256_DIGEST_SIZE;
}
}
+ sha_ctxt->init_done = true;
return 0;
}
@@ -878,6 +880,11 @@
int num_entries = 0;
uint32_t total = 0;
+ if (handle->sha_ctxt.init_done == false) {
+ pr_err("%s Init was not called\n", __func__);
+ return -EINVAL;
+ }
+
/* verify address src(s) */
for (i = 0; i < qcedev_areq->sha_op_req.entries; i++)
if (!access_ok(VERIFY_READ,
@@ -985,10 +992,19 @@
int err = 0;
struct scatterlist sg_src;
uint32_t total;
-
uint8_t *k_buf_src = NULL;
uint8_t *k_align_src = NULL;
+ if (handle->sha_ctxt.init_done == false) {
+ pr_err("%s Init was not called\n", __func__);
+ return -EINVAL;
+ }
+
+ if (handle->sha_ctxt.trailing_buf_len == 0) {
+ pr_err("%s Incorrect trailng buffer %d\n", __func__,
+ handle->sha_ctxt.trailing_buf_len);
+ return -EINVAL;
+ }
handle->sha_ctxt.last_blk = 1;
total = handle->sha_ctxt.trailing_buf_len;
@@ -1019,6 +1035,7 @@
handle->sha_ctxt.auth_data[0] = 0;
handle->sha_ctxt.auth_data[1] = 0;
handle->sha_ctxt.trailing_buf_len = 0;
+ handle->sha_ctxt.init_done = false;
memset(&handle->sha_ctxt.trailing_buf[0], 0, 64);
kfree(k_buf_src);
@@ -1413,12 +1430,37 @@
return -EFAULT;
/* Verify Destination Address's */
- if (areq->cipher_op_req.in_place_op != 1)
- for (i = 0; i < areq->cipher_op_req.entries; i++)
- if (!access_ok(VERIFY_READ,
- (void __user *)areq->cipher_op_req.vbuf.dst[i].vaddr,
- areq->cipher_op_req.vbuf.dst[i].len))
- return -EFAULT;
+ if (creq->in_place_op != 1) {
+ for (i = 0, total = 0; i < QCEDEV_MAX_BUFFERS; i++) {
+ if ((areq->cipher_op_req.vbuf.dst[i].vaddr != 0) &&
+ (total < creq->data_len)) {
+ if (!access_ok(VERIFY_WRITE,
+ (void __user *)creq->vbuf.dst[i].vaddr,
+ creq->vbuf.dst[i].len)) {
+ pr_err("%s:DST WR_VERIFY err %d=0x%x\n",
+ __func__, i,
+ (u32)creq->vbuf.dst[i].vaddr);
+ return -EFAULT;
+ }
+ total += creq->vbuf.dst[i].len;
+ }
+ }
+ } else {
+ for (i = 0, total = 0; i < creq->entries; i++) {
+ if (total < creq->data_len) {
+ if (!access_ok(VERIFY_WRITE,
+ (void __user *)creq->vbuf.src[i].vaddr,
+ creq->vbuf.src[i].len)) {
+ pr_err("%s:SRC WR_VERIFY err %d=0x%x\n",
+ __func__, i,
+ (u32)creq->vbuf.src[i].vaddr);
+ return -EFAULT;
+ }
+ total += creq->vbuf.src[i].len;
+ }
+ }
+ }
+ total = 0;
if (areq->cipher_op_req.mode == QCEDEV_AES_MODE_CTR)
byteoffset = areq->cipher_op_req.byteoffset;
@@ -1619,6 +1661,9 @@
static int qcedev_check_cipher_params(struct qcedev_cipher_op_req *req,
struct qcedev_control *podev)
{
+ uint32_t total = 0;
+ uint32_t i;
+
if (req->use_pmem) {
pr_err("%s: Use of PMEM is not supported\n", __func__);
goto error;
@@ -1670,7 +1715,22 @@
goto error;
}
}
-
+ /* Check for sum of all dst length is equal to data_len */
+ for (i = 0; (i < QCEDEV_MAX_BUFFERS) && (total < req->data_len); i++)
+ total += req->vbuf.dst[i].len;
+ if (total != req->data_len) {
+ pr_err("%s: Total (i=%d) dst(%d) buf size != data_len (%d)\n",
+ __func__, i, total, req->data_len);
+ goto error;
+ }
+ /* Check for sum of all src length is equal to data_len */
+ for (i = 0, total = 0; i < req->entries; i++)
+ total += req->vbuf.src[i].len;
+ if (total != req->data_len) {
+ pr_err("%s: Total src(%d) buf size != data_len (%d)\n",
+ __func__, total, req->data_len);
+ goto error;
+ }
return 0;
error:
return -EINVAL;
@@ -1680,6 +1740,9 @@
static int qcedev_check_sha_params(struct qcedev_sha_op_req *req,
struct qcedev_control *podev)
{
+ uint32_t total = 0;
+ uint32_t i;
+
if ((req->alg == QCEDEV_ALG_AES_CMAC) &&
(!podev->ce_support.cmac)) {
pr_err("%s: CMAC not supported\n", __func__);
@@ -1717,6 +1780,14 @@
}
}
+ /* Check for sum of all src length is equal to data_len */
+ for (i = 0, total = 0; i < req->entries; i++)
+ total += req->data[i].len;
+ if (total != req->data_len) {
+ pr_err("%s: Total src(%d) buf size != data_len (%d)\n",
+ __func__, total, req->data_len);
+ goto sha_error;
+ }
return 0;
sha_error:
return -EINVAL;
@@ -1805,6 +1876,7 @@
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
}
+ handle->sha_ctxt.init_done = true;
break;
case QCEDEV_IOCTL_GET_CMAC_REQ:
if (!podev->ce_support.cmac)
@@ -1829,6 +1901,10 @@
if (err)
return err;
} else {
+ if (handle->sha_ctxt.init_done == false) {
+ pr_err("%s Init was not called\n", __func__);
+ return -EINVAL;
+ }
err = qcedev_hash_update(&qcedev_areq, handle, &sg_src);
if (err)
return err;
@@ -1845,6 +1921,10 @@
case QCEDEV_IOCTL_SHA_FINAL_REQ:
+ if (handle->sha_ctxt.init_done == false) {
+ pr_err("%s Init was not called\n", __func__);
+ return -EINVAL;
+ }
if (!access_ok(VERIFY_WRITE, (void __user *)arg,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
@@ -1866,6 +1946,7 @@
if (__copy_to_user((void __user *)arg, &qcedev_areq.sha_op_req,
sizeof(struct qcedev_sha_op_req)))
return -EFAULT;
+ handle->sha_ctxt.init_done = false;
break;
case QCEDEV_IOCTL_GET_SHA_REQ:
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index cdf711c..4a9373a 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -632,11 +632,11 @@
kgsl_mmu_unmap(pagetable, &device->memstore);
- kgsl_mmu_unmap(pagetable, &adreno_dev->profile.shared_buffer);
-
kgsl_mmu_unmap(pagetable, &adreno_dev->pwron_fixup);
kgsl_mmu_unmap(pagetable, &device->mmu.setstate_memory);
+
+ kgsl_mmu_unmap(pagetable, &adreno_dev->profile.shared_buffer);
}
static int adreno_setup_pt(struct kgsl_device *device,
@@ -648,6 +648,12 @@
result = kgsl_mmu_map_global(pagetable, &rb->buffer_desc);
+ /*
+ * ALERT: Order of these mapping is important to
+ * Keep the most used entries like memptrs, memstore
+ * and mmu setstate memory by TLB prefetcher.
+ */
+
if (!result)
result = kgsl_mmu_map_global(pagetable, &rb->memptrs_desc);
@@ -656,17 +662,16 @@
if (!result)
result = kgsl_mmu_map_global(pagetable,
- &adreno_dev->profile.shared_buffer);
-
- if (!result)
- result = kgsl_mmu_map_global(pagetable,
&adreno_dev->pwron_fixup);
-
if (!result)
result = kgsl_mmu_map_global(pagetable,
&device->mmu.setstate_memory);
+ if (!result)
+ result = kgsl_mmu_map_global(pagetable,
+ &adreno_dev->profile.shared_buffer);
+
if (result) {
/* On error clean up what we have wrought */
adreno_cleanup_pt(device, pagetable);
@@ -678,8 +683,8 @@
* For the IOMMU, this will be used to restrict access to the
* mapped registers.
*/
- device->mh.mpu_range = device->mmu.setstate_memory.gpuaddr +
- device->mmu.setstate_memory.size;
+ device->mh.mpu_range = adreno_dev->profile.shared_buffer.gpuaddr +
+ adreno_dev->profile.shared_buffer.size;
return 0;
}
@@ -946,8 +951,11 @@
num_iommu_units = kgsl_mmu_get_num_iommu_units(&device->mmu);
context = kgsl_context_get(device, context_id);
- if (context == NULL)
+
+ if (context == NULL) {
+ kgsl_mmu_device_setstate(&device->mmu, KGSL_CONTEXT_INVALID);
return;
+ }
adreno_ctx = ADRENO_CONTEXT(context);
@@ -1697,8 +1705,8 @@
/* Power down the device */
kgsl_pwrctrl_disable(device);
- /* Certain targets need the fixup. You know who you are */
- if (adreno_is_a330v2(adreno_dev))
+ /* Enable the power on shader corruption fix for all A3XX targets */
+ if (adreno_is_a3xx(adreno_dev))
adreno_a3xx_pwron_fixup_init(adreno_dev);
return 0;
@@ -3664,6 +3672,8 @@
}
}
for (i = 0; i < FT_DETECT_REGS_COUNT; i++) {
+ if (ft_detect_regs[i] == 0)
+ continue;
if (curr_reg_val[i] != prev_reg_val[i])
fast_hang_detected = 0;
}
@@ -3725,8 +3735,12 @@
/* If hangs are not detected copy the current reg values
* to previous values and return no hang */
- for (i = 0; i < FT_DETECT_REGS_COUNT; i++)
- prev_reg_val[i] = curr_reg_val[i];
+ for (i = 0; i < FT_DETECT_REGS_COUNT; i++) {
+ if (ft_detect_regs[i] == 0)
+ continue;
+ prev_reg_val[i] = curr_reg_val[i];
+ }
+
return 0;
}
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 6507852..a837574 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -63,7 +63,6 @@
#define ADRENO_DEFAULT_PWRSCALE_POLICY NULL
#endif
-void adreno_debugfs_init(struct kgsl_device *device);
#define ADRENO_ISTORE_START 0x5000 /* Istore offset */
@@ -749,4 +748,11 @@
return ADRENO_REG_REGISTER_MAX;
return adreno_dev->gpudev->reg_offsets->offsets[offset_name];
}
+
+#ifdef CONFIG_DEBUG_FS
+void adreno_debugfs_init(struct kgsl_device *device);
+#else
+static inline void adreno_debugfs_init(struct kgsl_device *device) { }
+#endif
+
#endif /*__ADRENO_H */
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index fc98d86..a7d1b7f 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -23,8 +23,6 @@
#include "a2xx_reg.h"
-unsigned int kgsl_cff_dump_enable;
-
DEFINE_SIMPLE_ATTRIBUTE(kgsl_cff_dump_enable_fops, kgsl_cff_dump_enable_get,
kgsl_cff_dump_enable_set, "%llu\n");
diff --git a/drivers/gpu/msm/adreno_profile.c b/drivers/gpu/msm/adreno_profile.c
index 896b6e8..7d9d63f 100644
--- a/drivers/gpu/msm/adreno_profile.c
+++ b/drivers/gpu/msm/adreno_profile.c
@@ -597,7 +597,7 @@
static char *_parse_next_assignment(struct adreno_device *adreno_dev,
char *str, int *groupid, int *countable, bool *remove)
{
- char *groupid_str, *countable_str;
+ char *groupid_str, *countable_str, *next_str = NULL;
int ret;
*groupid = -EINVAL;
@@ -635,8 +635,15 @@
if (countable_str == str)
return NULL;
- *str = '\0';
- str++;
+ /*
+ * If we have reached the end of the original string then make sure we
+ * return NULL from this function or we could accidently overrun
+ */
+
+ if (*str != '\0') {
+ *str = '\0';
+ next_str = str + 1;
+ }
/* set results */
*groupid = adreno_perfcounter_get_groupid(adreno_dev,
@@ -647,7 +654,7 @@
if (ret)
return NULL;
- return str;
+ return next_str;
}
static ssize_t profile_assignments_write(struct file *filep,
diff --git a/drivers/gpu/msm/adreno_profile.h b/drivers/gpu/msm/adreno_profile.h
index d91b09b..7e1ccb2 100644
--- a/drivers/gpu/msm/adreno_profile.h
+++ b/drivers/gpu/msm/adreno_profile.h
@@ -61,6 +61,7 @@
#define ADRENO_PROFILE_LOG_BUF_SIZE_DWORDS (ADRENO_PROFILE_LOG_BUF_SIZE / \
sizeof(unsigned int))
+#ifdef CONFIG_DEBUG_FS
void adreno_profile_init(struct kgsl_device *device);
void adreno_profile_close(struct kgsl_device *device);
int adreno_profile_process_results(struct kgsl_device *device);
@@ -70,6 +71,22 @@
void adreno_profile_postib_processing(struct kgsl_device *device,
unsigned int *cmd_flags, unsigned int **rbptr,
unsigned int *cmds_gpu);
+#else
+static inline void adreno_profile_init(struct kgsl_device *device) { }
+static inline void adreno_profile_close(struct kgsl_device *device) { }
+static inline int adreno_profile_process_results(struct kgsl_device *device)
+{
+ return 0;
+}
+
+static inline void adreno_profile_preib_processing(struct kgsl_device *device,
+ unsigned int context_id, unsigned int *cmd_flags,
+ unsigned int **rbptr, unsigned int *cmds_gpu) { }
+
+static inline void adreno_profile_postib_processing(struct kgsl_device *device,
+ unsigned int *cmd_flags, unsigned int **rbptr,
+ unsigned int *cmds_gpu) { }
+#endif
static inline bool adreno_profile_enabled(struct adreno_profile *profile)
{
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index ceff923..8aec755 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -1073,7 +1073,7 @@
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
unsigned int *link = 0;
unsigned int *cmds;
- unsigned int i;
+ unsigned int i, cmdflags;
struct adreno_context *drawctxt = NULL;
unsigned int start_index = 0;
int ret;
@@ -1095,6 +1095,8 @@
goto done;
}
+ cmdflags = (flags & KGSL_CMD_FLAGS_EOF);
+
/* process any profiling results that are available into the log_buf */
adreno_profile_process_results(device);
@@ -1161,7 +1163,7 @@
if (test_and_clear_bit(ADRENO_DEVICE_PWRON, &adreno_dev->priv) &&
test_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv))
- flags |= KGSL_CMD_FLAGS_PWRON_FIXUP;
+ cmdflags |= KGSL_CMD_FLAGS_PWRON_FIXUP;
if (drawctxt->flags & CTXT_FLAGS_USER_GENERATED_TS) {
if (timestamp_cmp(drawctxt->timestamp, *timestamp) >= 0) {
@@ -1178,7 +1180,7 @@
ret = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer,
drawctxt,
- flags,
+ cmdflags,
&link[0], (cmds - link));
if (ret)
goto done;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 7da0811..298b36e 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -909,6 +909,9 @@
private = kgsl_find_process_private(cur_dev_priv);
+ if (!private)
+ return NULL;
+
mutex_lock(&private->process_private_mutex);
if (test_bit(KGSL_PROCESS_INIT, &private->priv))
@@ -3049,7 +3052,7 @@
static inline bool
mmap_range_valid(unsigned long addr, unsigned long len)
{
- return (addr + len) > addr && (addr + len) < TASK_SIZE;
+ return ((ULONG_MAX - addr) > len) && ((addr + len) < TASK_SIZE);
}
static unsigned long
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 8d390a9..0525eab 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -267,7 +267,7 @@
size = 1;
/* don't overflow */
- if ((gpuaddr + size) < gpuaddr)
+ if (size > UINT_MAX - gpuaddr)
return 0;
if (gpuaddr >= memdesc->gpuaddr &&
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index ecda5a7..a06ebbf 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -72,16 +72,18 @@
static struct iommu_access_ops *iommu_access_ops;
-static void _iommu_lock(void)
+static void _iommu_lock(struct kgsl_iommu const *iommu)
{
if (iommu_access_ops && iommu_access_ops->iommu_lock_acquire)
- iommu_access_ops->iommu_lock_acquire();
+ iommu_access_ops->iommu_lock_acquire(
+ iommu->sync_lock_initialized);
}
-static void _iommu_unlock(void)
+static void _iommu_unlock(struct kgsl_iommu const *iommu)
{
if (iommu_access_ops && iommu_access_ops->iommu_lock_release)
- iommu_access_ops->iommu_lock_release();
+ iommu_access_ops->iommu_lock_release(
+ iommu->sync_lock_initialized);
}
struct remote_iommu_petersons_spinlock kgsl_iommu_sync_lock_vars;
@@ -906,6 +908,8 @@
return 0;
}
+#ifdef CONFIG_MSM_IOMMU_GPU_SYNC
+
/*
* kgsl_get_sync_lock - Init Sync Lock between GPU and CPU
* @mmu - Pointer to mmu device
@@ -973,6 +977,12 @@
return status;
}
+#else
+static int kgsl_iommu_init_sync_lock(struct kgsl_mmu *mmu)
+{
+ return 0;
+}
+#endif
/*
* kgsl_iommu_sync_lock - Acquire Sync Lock between GPU and CPU
@@ -1643,7 +1653,7 @@
* changing pagetables we can use this lsb value of the pagetable w/o
* having to read it again
*/
- _iommu_lock();
+ _iommu_lock(iommu);
for (i = 0; i < iommu->unit_count; i++) {
struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i];
for (j = 0; j < iommu_unit->dev_count; j++) {
@@ -1682,7 +1692,7 @@
}
}
kgsl_iommu_lock_rb_in_tlb(mmu);
- _iommu_unlock();
+ _iommu_unlock(iommu);
/* For complete CFF */
kgsl_cffdump_setmem(mmu->device, mmu->setstate_memory.gpuaddr +
@@ -1788,12 +1798,12 @@
for (j = 0; j < iommu_unit->dev_count; j++) {
if (iommu_unit->dev[j].fault) {
kgsl_iommu_enable_clk(mmu, j);
- _iommu_lock();
+ _iommu_lock(iommu);
KGSL_IOMMU_SET_CTX_REG(iommu,
iommu_unit,
iommu_unit->dev[j].ctx_id,
RESUME, 1);
- _iommu_unlock();
+ _iommu_unlock(iommu);
iommu_unit->dev[j].fault = 0;
}
}
@@ -1912,7 +1922,7 @@
kgsl_idle(mmu->device);
/* Acquire GPU-CPU sync Lock here */
- _iommu_lock();
+ _iommu_lock(iommu);
if (flags & KGSL_MMUFLAGS_PTUPDATE) {
if (!msm_soc_version_supports_iommu_v0())
@@ -1979,7 +1989,7 @@
}
/* Release GPU-CPU sync Lock here */
- _iommu_unlock();
+ _iommu_unlock(iommu);
/* Disable smmu clock */
kgsl_iommu_disable_clk_on_ts(mmu, 0, false);
diff --git a/drivers/gpu/msm/kgsl_log.h b/drivers/gpu/msm/kgsl_log.h
index a7832e4..94649bd 100644
--- a/drivers/gpu/msm/kgsl_log.h
+++ b/drivers/gpu/msm/kgsl_log.h
@@ -13,8 +13,6 @@
#ifndef __KGSL_LOG_H
#define __KGSL_LOG_H
-extern unsigned int kgsl_cff_dump_enable;
-
#define KGSL_LOG_INFO(dev, lvl, fmt, args...) \
do { \
if ((lvl) >= 6) \
diff --git a/drivers/input/misc/cm36283.c b/drivers/input/misc/cm36283.c
index d850a0e..17127a8 100644
--- a/drivers/input/misc/cm36283.c
+++ b/drivers/input/misc/cm36283.c
@@ -40,8 +40,6 @@
#include <asm/mach-types.h>
#include <asm/setup.h>
-#define D(x...) pr_info(x)
-
#define I2C_RETRY_COUNT 10
#define NEAR_DELAY_TIME ((100 * HZ) / 1000)
@@ -65,8 +63,6 @@
#define CM36283_PS_MAX_POLL_DELAY 1000
#define CM36283_PS_DEFAULT_POLL_DELAY 100
-static int record_init_fail = 0;
-
static const int als_range[] = {
[CM36283_ALS_IT0] = 6554,
[CM36283_ALS_IT1] = 3277,
@@ -156,9 +152,8 @@
static int I2C_RxData(uint16_t slaveAddr, uint8_t cmd, uint8_t *rxData, int length)
{
uint8_t loop_i;
- int val;
struct cm36283_info *lpi = lp_info;
- uint8_t subaddr[1];
+ uint8_t subaddr[1];
struct i2c_msg msgs[] = {
{
@@ -174,24 +169,21 @@
.buf = rxData,
},
};
- subaddr[0] = cmd;
+
+ subaddr[0] = cmd;
for (loop_i = 0; loop_i < I2C_RETRY_COUNT; loop_i++) {
if (i2c_transfer(lp_info->i2c_client->adapter, msgs, 2) > 0)
break;
- val = gpio_get_value(lpi->intr_pin);
- /*check intr GPIO when i2c error*/
- if (loop_i == 0 || loop_i == I2C_RETRY_COUNT -1)
- D("[PS][CM36283 error] %s, i2c err, slaveAddr 0x%x ISR gpio %d = %d, record_init_fail %d \n",
- __func__, slaveAddr, lpi->intr_pin, val, record_init_fail);
-
+ dev_err(&lpi->i2c_client->dev, "%s: I2C error(%d). Retrying.\n",
+ __func__, cmd);
msleep(10);
}
if (loop_i >= I2C_RETRY_COUNT) {
- printk(KERN_ERR "[PS_ERR][CM36283 error] %s retry over %d\n",
- __func__, I2C_RETRY_COUNT);
+ dev_err(&lpi->i2c_client->dev, "%s: Retry count exceeds %d.",
+ __func__, I2C_RETRY_COUNT);
return -EIO;
}
@@ -201,8 +193,8 @@
static int I2C_TxData(uint16_t slaveAddr, uint8_t *txData, int length)
{
uint8_t loop_i;
- int val;
struct cm36283_info *lpi = lp_info;
+
struct i2c_msg msg[] = {
{
.addr = slaveAddr,
@@ -216,18 +208,13 @@
if (i2c_transfer(lp_info->i2c_client->adapter, msg, 1) > 0)
break;
- val = gpio_get_value(lpi->intr_pin);
- /*check intr GPIO when i2c error*/
- if (loop_i == 0 || loop_i == I2C_RETRY_COUNT -1)
- D("[PS][CM36283 error] %s, i2c err, slaveAddr 0x%x, value 0x%x, ISR gpio%d = %d, record_init_fail %d\n",
- __func__, slaveAddr, txData[0], lpi->intr_pin, val, record_init_fail);
-
+ pr_err("%s: I2C error. Retrying...\n", __func__);
msleep(10);
}
if (loop_i >= I2C_RETRY_COUNT) {
- printk(KERN_ERR "[PS_ERR][CM36283 error] %s retry over %d\n",
- __func__, I2C_RETRY_COUNT);
+ dev_err(&lpi->i2c_client->dev, "%s: Retry count exceeds %d.",
+ __func__, I2C_RETRY_COUNT);
return -EIO;
}
@@ -244,18 +231,12 @@
ret = I2C_RxData(slaveAddr, cmd, buffer, 2);
if (ret < 0) {
- pr_err(
- "[PS_ERR][CM3218 error]%s: I2C_RxData fail [0x%x, 0x%x]\n",
- __func__, slaveAddr, cmd);
+ pr_err("%s: I2C RxData fail(%d).\n", __func__, cmd);
return ret;
}
*pdata = (buffer[1]<<8)|buffer[0];
-#if 0
- /* Debug use */
- printk(KERN_DEBUG "[CM3218] %s: I2C_RxData[0x%x, 0x%x] = 0x%x\n",
- __func__, slaveAddr, cmd, *pdata);
-#endif
+
return ret;
}
@@ -263,19 +244,14 @@
{
char buffer[3];
int ret = 0;
-#if 0
- /* Debug use */
- printk(KERN_DEBUG
- "[CM3218] %s: _cm36283_I2C_Write_Word[0x%x, 0x%x, 0x%x]\n",
- __func__, SlaveAddress, cmd, data);
-#endif
+
buffer[0] = cmd;
buffer[1] = (uint8_t)(data&0xff);
buffer[2] = (uint8_t)((data&0xff00)>>8);
ret = I2C_TxData(SlaveAddress, buffer, 3);
if (ret < 0) {
- pr_err("[PS_ERR][CM3218 error]%s: I2C_TxData fail\n", __func__);
+ pr_err("%s: I2C_TxData failed.\n", __func__);
return -EIO;
}
@@ -285,7 +261,7 @@
static int get_ls_adc_value(uint16_t *als_step, bool resume)
{
struct cm36283_info *lpi = lp_info;
- uint32_t tmpResult;
+ uint32_t tmp;
int ret = 0;
if (als_step == NULL)
@@ -294,22 +270,20 @@
/* Read ALS data: */
ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ALS_DATA, als_step);
if (ret < 0) {
- pr_err(
- "[LS][CM3218 error]%s: _cm36283_I2C_Read_Word fail\n",
- __func__);
+ dev_err(&lpi->i2c_client->dev, "%s: I2C read word failed.\n",
+ __func__);
return -EIO;
}
- if (!lpi->ls_calibrate) {
- tmpResult = (uint32_t)(*als_step) * lpi->als_gadc / lpi->als_kadc;
- if (tmpResult > 0xFFFF)
+ if (!lpi->ls_calibrate) {
+ tmp = (uint32_t)(*als_step) * lpi->als_gadc / lpi->als_kadc;
+ if (tmp > 0xFFFF)
*als_step = 0xFFFF;
else
- *als_step = tmpResult;
+ *als_step = tmp;
}
- D("[LS][CM3218] %s: raw adc = 0x%X, ls_calibrate = %d\n",
- __func__, *als_step, lpi->ls_calibrate);
+ dev_dbg(&lpi->i2c_client->dev, "raw adc = 0x%x\n", *als_step);
return ret;
}
@@ -335,18 +309,10 @@
ret = _cm36283_I2C_Read_Word(lpi->slave_addr, PS_DATA, data);
+ if (ret < 0)
+ return ret;
+
(*data) &= 0xFF;
-
- if (ret < 0) {
- pr_err(
- "[PS][CM36283 error]%s: _cm36283_I2C_Read_Word fail\n",
- __func__);
- return -EIO;
- } else {
- pr_err(
- "[PS][CM36283 OK]%s: _cm36283_I2C_Read_Word OK 0x%x\n",
- __func__, *data);
- }
return ret;
}
@@ -383,16 +349,16 @@
msleep(10);
wait_count++;
if (wait_count > 12) {
- pr_err("[PS_ERR][CM36283 error]%s: interrupt GPIO low,"
- " get_ps_adc_value\n", __func__);
+ dev_err(&lpi->i2c_client->dev, "%s: interrupt GPIO low\n",
+ __func__);
return -EIO;
}
}
ret = get_ps_adc_value(&value[i]);
if (ret < 0) {
- pr_err("[PS_ERR][CM36283 error]%s: get_ps_adc_value\n",
- __func__);
+ dev_err(&lpi->i2c_client->dev,
+ "%s: error get ps value\n", __func__);
return -EIO;
}
@@ -402,10 +368,8 @@
wait_count = 0;
}
- /*D("Sta_ps: Before sort, value[0, 1, 2] = [0x%x, 0x%x, 0x%x]",
- value[0], value[1], value[2]);*/
mid_val = mid_value(value, 3);
- D("Sta_ps: After sort, value[0, 1, 2] = [0x%x, 0x%x, 0x%x]",
+ dev_dbg(&lpi->i2c_client->dev, "Sta_ps: After sort, value[0, 1, 2] = [0x%x, 0x%x, 0x%x]",
value[0], value[1], value[2]);
*ps_adc = (mid_val & 0xFF);
@@ -531,14 +495,16 @@
static void psensor_initial_cmd(struct cm36283_info *lpi)
{
- /*must disable p-sensor interrupt befrore IST create*//*disable ALS func*/
- lpi->ps_conf1_val |= CM36283_PS_SD;
- lpi->ps_conf1_val &= CM36283_PS_INT_MASK;
- _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val);
- _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF3, lpi->ps_conf3_val);
- _cm36283_I2C_Write_Word(lpi->slave_addr, PS_THD, (lpi->ps_close_thd_set <<8)| lpi->ps_away_thd_set);
+ /*must disable p-sensor interrupt befrore IST create*/
+ lpi->ps_conf1_val |= CM36283_PS_SD;
+ lpi->ps_conf1_val &= CM36283_PS_INT_MASK;
+ _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val);
+ _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF3, lpi->ps_conf3_val);
+ _cm36283_I2C_Write_Word(lpi->slave_addr, PS_THD,
+ (lpi->ps_close_thd_set << 8) | lpi->ps_away_thd_set);
- D("[PS][CM36283] %s, finish\n", __func__);
+ dev_dbg(&lpi->i2c_client->dev,
+ "%s:send psensor initial command finished\n", __func__);
}
static int psensor_enable(struct cm36283_info *lpi)
@@ -547,10 +513,10 @@
unsigned int delay;
mutex_lock(&ps_enable_mutex);
- D("[PS][CM36283] %s\n", __func__);
+ dev_dbg(&lpi->i2c_client->dev, "psensor enable!\n");
if (lpi->ps_enable) {
- D("[PS][CM36283] %s: already enabled\n", __func__);
+ dev_err(&lpi->i2c_client->dev, "already enabled\n");
ret = 0;
} else {
ret = control_and_report(lpi, CONTROL_PS, 1, 0);
@@ -573,10 +539,10 @@
cancel_delayed_work_sync(&lpi->pdwork);
mutex_lock(&ps_disable_mutex);
- D("[PS][CM36283] %s\n", __func__);
+ dev_dbg(&lpi->i2c_client->dev, "psensor disable!\n");
if (lpi->ps_enable == 0) {
- D("[PS][CM36283] %s: already disabled\n", __func__);
+ dev_err(&lpi->i2c_client->dev, "already disabled\n");
ret = 0;
} else {
ret = control_and_report(lpi, CONTROL_PS, 0, 0);
@@ -590,7 +556,7 @@
{
struct cm36283_info *lpi = lp_info;
- D("[PS][CM36283] %s\n", __func__);
+ dev_dbg(&lpi->i2c_client->dev, "psensor open!");
if (lpi->psensor_opened)
return -EBUSY;
@@ -604,7 +570,7 @@
{
struct cm36283_info *lpi = lp_info;
- D("[PS][CM36283] %s\n", __func__);
+ dev_dbg(&lpi->i2c_client->dev, "psensor release!");
lpi->psensor_opened = 0;
@@ -618,7 +584,7 @@
int val;
struct cm36283_info *lpi = lp_info;
- D("[PS][CM36283] %s cmd %d\n", __func__, _IOC_NR(cmd));
+ dev_dbg(&lpi->i2c_client->dev, "%s cmd %d\n", __func__, _IOC_NR(cmd));
switch (cmd) {
case CAPELLA_CM3602_IOCTL_ENABLE:
@@ -633,7 +599,7 @@
return put_user(lpi->ps_enable, (unsigned long __user *)arg);
break;
default:
- pr_err("[PS][CM36283 error]%s: invalid cmd %d\n",
+ dev_err(&lpi->i2c_client->dev, "%s: invalid cmd %d\n",
__func__, _IOC_NR(cmd));
return -EINVAL;
}
@@ -655,18 +621,19 @@
void lightsensor_set_kvalue(struct cm36283_info *lpi)
{
if (!lpi) {
- pr_err("[LS][CM36283 error]%s: ls_info is empty\n", __func__);
+ pr_err("%s: ls_info is empty\n", __func__);
return;
}
- D("[LS][CM36283] %s: ALS calibrated als_kadc=0x%x\n",
+ dev_dbg(&lpi->i2c_client->dev, "%s: ALS calibrated als_kadc=0x%x\n",
__func__, als_kadc);
if (als_kadc >> 16 == ALS_CALIBRATED)
lpi->als_kadc = als_kadc & 0xFFFF;
else {
lpi->als_kadc = 0;
- D("[LS][CM36283] %s: no ALS calibrated\n", __func__);
+ dev_dbg(&lpi->i2c_client->dev, "%s: no ALS calibrated\n",
+ __func__);
}
if (lpi->als_kadc && lpi->golden_adc > 0) {
@@ -677,25 +644,26 @@
lpi->als_kadc = 1;
lpi->als_gadc = 1;
}
- D("[LS][CM36283] %s: als_kadc=0x%x, als_gadc=0x%x\n",
+ dev_dbg(&lpi->i2c_client->dev, "%s: als_kadc=0x%x, als_gadc=0x%x\n",
__func__, lpi->als_kadc, lpi->als_gadc);
}
static int lightsensor_update_table(struct cm36283_info *lpi)
{
- uint32_t tmpData[10];
+ uint32_t tmp_data[10];
int i;
for (i = 0; i < 10; i++) {
- tmpData[i] = (uint32_t)(*(lpi->adc_table + i))
- * lpi->als_kadc / lpi->als_gadc ;
- if( tmpData[i] <= 0xFFFF ){
- lpi->cali_table[i] = (uint16_t) tmpData[i];
- } else {
- lpi->cali_table[i] = 0xFFFF;
- }
- D("[LS][CM36283] %s: Calibrated adc_table: data[%d], %x\n",
- __func__, i, lpi->cali_table[i]);
+ tmp_data[i] = (uint32_t)(*(lpi->adc_table + i))
+ * lpi->als_kadc / lpi->als_gadc;
+
+ if (tmp_data[i] <= 0xFFFF)
+ lpi->cali_table[i] = (uint16_t) tmp_data[i];
+ else
+ lpi->cali_table[i] = 0xFFFF;
+
+ dev_dbg(&lpi->i2c_client->dev, "%s: Calibrated adc_table: data[%d], %x\n",
+ __func__, i, lpi->cali_table[i]);
}
return 0;
@@ -708,10 +676,10 @@
unsigned int delay;
mutex_lock(&als_enable_mutex);
- D("[LS][CM36283] %s\n", __func__);
if (lpi->als_enable) {
- D("[LS][CM36283] %s: already enabled\n", __func__);
+ dev_err(&lpi->i2c_client->dev, "%s: already enabled\n",
+ __func__);
ret = 0;
} else {
ret = control_and_report(lpi, CONTROL_ALS, 1, 0);
@@ -731,13 +699,13 @@
{
int ret = -EIO;
mutex_lock(&als_disable_mutex);
- D("[LS][CM36283] %s\n", __func__);
+ dev_dbg(&lpi->i2c_client->dev, "disable lightsensor\n");
if (lpi->polling)
cancel_delayed_work_sync(&lpi->ldwork);
if ( lpi->als_enable == 0 ) {
- D("[LS][CM36283] %s: already disabled\n", __func__);
+ dev_err(&lpi->i2c_client->dev, "already disabled\n");
ret = 0;
} else {
ret = control_and_report(lpi, CONTROL_ALS, 0, 0);
@@ -752,9 +720,10 @@
struct cm36283_info *lpi = lp_info;
int rc = 0;
- D("[LS][CM36283] %s\n", __func__);
+ dev_dbg(&lpi->i2c_client->dev, "%s\n", __func__);
if (lpi->lightsensor_opened) {
- pr_err("[LS][CM36283 error]%s: already opened\n", __func__);
+ dev_err(&lpi->i2c_client->dev, "%s: already opened\n",
+ __func__);
rc = -EBUSY;
}
lpi->lightsensor_opened = 1;
@@ -765,7 +734,7 @@
{
struct cm36283_info *lpi = lp_info;
- D("[LS][CM36283] %s\n", __func__);
+ dev_dbg(&lpi->i2c_client->dev, "%s\n", __func__);
lpi->lightsensor_opened = 0;
return 0;
}
@@ -776,22 +745,16 @@
int rc, val;
struct cm36283_info *lpi = lp_info;
- /*D("[CM36283] %s cmd %d\n", __func__, _IOC_NR(cmd));*/
-
switch (cmd) {
case LIGHTSENSOR_IOCTL_ENABLE:
if (get_user(val, (unsigned long __user *)arg)) {
rc = -EFAULT;
break;
}
- D("[LS][CM36283] %s LIGHTSENSOR_IOCTL_ENABLE, value = %d\n",
- __func__, val);
rc = val ? lightsensor_enable(lpi) : lightsensor_disable(lpi);
break;
case LIGHTSENSOR_IOCTL_GET_ENABLED:
val = lpi->als_enable;
- D("[LS][CM36283] %s LIGHTSENSOR_IOCTL_GET_ENABLED, enabled %d\n",
- __func__, val);
rc = put_user(val, (unsigned long __user *)arg);
break;
default:
@@ -850,29 +813,28 @@
&& ps_en != 10 && ps_en != 13 && ps_en != 16)
return -EINVAL;
- if (ps_en) {
- D("[PS][CM36283] %s: ps_en=%d\n",
+ dev_dbg(&lpi->i2c_client->dev, "%s: ps_en=%d\n",
__func__, ps_en);
- psensor_enable(lpi);
- } else
- psensor_disable(lpi);
- D("[PS][CM36283] %s\n", __func__);
+ if (ps_en)
+ psensor_enable(lpi);
+ else
+ psensor_disable(lpi);
return count;
}
static DEVICE_ATTR(ps_adc, 0664, ps_adc_show, ps_enable_store);
-unsigned PS_cmd_test_value;
static ssize_t ps_parameters_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
struct cm36283_info *lpi = lp_info;
- ret = sprintf(buf, "PS_close_thd_set = 0x%x, PS_away_thd_set = 0x%x, PS_cmd_cmd:value = 0x%x\n",
- lpi->ps_close_thd_set, lpi->ps_away_thd_set, PS_cmd_test_value);
+ ret = snprintf(buf, PAGE_SIZE,
+ "PS_close_thd_set = 0x%x, PS_away_thd_set = 0x%x\n",
+ lpi->ps_close_thd_set, lpi->ps_away_thd_set);
return ret;
}
@@ -885,19 +847,23 @@
struct cm36283_info *lpi = lp_info;
char *token[10];
int i;
+ unsigned long tmp;
- printk(KERN_INFO "[PS][CM36283] %s\n", buf);
for (i = 0; i < 3; i++)
token[i] = strsep((char **)&buf, " ");
- lpi->ps_close_thd_set = simple_strtoul(token[0], NULL, 16);
- lpi->ps_away_thd_set = simple_strtoul(token[1], NULL, 16);
- PS_cmd_test_value = simple_strtoul(token[2], NULL, 16);
- printk(KERN_INFO
- "[PS][CM36283]Set PS_close_thd_set = 0x%x, PS_away_thd_set = 0x%x, PS_cmd_cmd:value = 0x%x\n",
- lpi->ps_close_thd_set, lpi->ps_away_thd_set, PS_cmd_test_value);
+ if (kstrtoul(token[0], 16, &tmp))
+ return -EINVAL;
+ lpi->ps_close_thd_set = tmp;
- D("[PS][CM36283] %s\n", __func__);
+ if (kstrtoul(token[1], 16, &tmp))
+ return -EINVAL;
+ lpi->ps_away_thd_set = tmp;
+
+ dev_dbg(&lpi->i2c_client->dev, "ps_close_thd_set:0x%x\n",
+ lpi->ps_close_thd_set);
+ dev_dbg(&lpi->i2c_client->dev, "ps_away_thd_set:0x%x\n",
+ lpi->ps_away_thd_set);
return count;
}
@@ -920,14 +886,14 @@
struct cm36283_info *lpi = lp_info;
sscanf(buf, "0x%x 0x%x", &code1, &code2);
+ dev_dbg(&lpi->i2c_client->dev, "PS_CONF1:0x%x PS_CONF3:0x%x\n",
+ code1, code2);
- D("[PS]%s: store value PS conf1 reg = 0x%x PS conf3 reg = 0x%x\n", __func__, code1, code2);
+ lpi->ps_conf1_val = code1;
+ lpi->ps_conf3_val = code2;
- lpi->ps_conf1_val = code1;
- lpi->ps_conf3_val = code2;
-
- _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF3, lpi->ps_conf3_val );
- _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val );
+ _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF3, lpi->ps_conf3_val);
+ _cm36283_I2C_Write_Word(lpi->slave_addr, PS_CONF1, lpi->ps_conf1_val);
return count;
}
@@ -950,12 +916,13 @@
sscanf(buf, "0x%x", &code);
- D("[PS]%s: store value = 0x%x\n", __func__, code);
-
lpi->ps_away_thd_set = code &0xFF;
- lpi->ps_close_thd_set = (code &0xFF00)>>8;
+ lpi->ps_close_thd_set = (code & 0xFF00)>>8;
- D("[PS]%s: ps_close_thd_set = 0x%x, ps_away_thd_set = 0x%x\n", __func__, lpi->ps_close_thd_set, lpi->ps_away_thd_set);
+ dev_dbg(&lpi->i2c_client->dev, "ps_away_thd_set:0x%x\n",
+ lpi->ps_away_thd_set);
+ dev_dbg(&lpi->i2c_client->dev, "ps_close_thd_set:0x%x\n",
+ lpi->ps_close_thd_set);
return count;
}
@@ -977,12 +944,9 @@
const char *buf, size_t count)
{
int code;
-// struct cm36283_info *lpi = lp_info;
sscanf(buf, "0x%x", &code);
- D("[PS]%s: store value = 0x%x\n", __func__, code);
-
return count;
}
static DEVICE_ATTR(ps_hw, 0664, ps_hw_show, ps_hw_store);
@@ -993,8 +957,6 @@
int ret;
struct cm36283_info *lpi = lp_info;
- D("[LS][CM36283] %s: ADC = 0x%04X, Level = %d \n",
- __func__, lpi->current_adc, lpi->current_level);
ret = sprintf(buf, "ADC[0x%04X] => level %d\n",
lpi->current_adc, lpi->current_level);
@@ -1038,12 +1000,14 @@
ret = lightsensor_disable(lpi);
}
- D("[LS][CM36283] %s: lpi->als_enable = %d, lpi->ls_calibrate = %d, ls_auto=%d\n",
- __func__, lpi->als_enable, lpi->ls_calibrate, ls_auto);
+ dev_dbg(&lpi->i2c_client->dev, "als_enable:0x%x\n",
+ lpi->als_enable);
+ dev_dbg(&lpi->i2c_client->dev, "ls_calibrate:0x%x\n",
+ lpi->ls_calibrate);
+ dev_dbg(&lpi->i2c_client->dev, "ls_auto:0x%x\n", ls_auto);
if (ret < 0)
- pr_err(
- "[LS][CM36283 error]%s: set auto light sensor fail\n",
+ dev_err(&lpi->i2c_client->dev, "%s: set auto light sensor fail\n",
__func__);
return count;
@@ -1074,17 +1038,18 @@
sscanf(buf, "%d", &kadc_temp);
mutex_lock(&als_get_adc_mutex);
- if(kadc_temp != 0) {
+ if (kadc_temp != 0) {
lpi->als_kadc = kadc_temp;
- if( lpi->als_gadc != 0){
- if (lightsensor_update_table(lpi) < 0)
- printk(KERN_ERR "[LS][CM36283 error] %s: update ls table fail\n", __func__);
- } else {
- printk(KERN_INFO "[LS]%s: als_gadc =0x%x wait to be set\n",
- __func__, lpi->als_gadc);
- }
+ if (lpi->als_gadc != 0) {
+ if (lightsensor_update_table(lpi) < 0)
+ dev_err(&lpi->i2c_client->dev, "%s: update ls table fail\n",
+ __func__);
+ else
+ dev_dbg(&lpi->i2c_client->dev, "%s: als_gadc =0x%x wait to be set\n",
+ __func__, lpi->als_gadc);
+ }
} else {
- printk(KERN_INFO "[LS]%s: als_kadc can't be set to zero\n",
+ dev_err(&lpi->i2c_client->dev, "%s: als_kadc can't be set to zero\n",
__func__);
}
@@ -1115,18 +1080,18 @@
sscanf(buf, "%d", &gadc_temp);
mutex_lock(&als_get_adc_mutex);
- if(gadc_temp != 0) {
+ if (gadc_temp != 0) {
lpi->als_gadc = gadc_temp;
- if( lpi->als_kadc != 0){
- if (lightsensor_update_table(lpi) < 0)
- printk(KERN_ERR "[LS][CM36283 error] %s: update ls table fail\n", __func__);
- } else {
- printk(KERN_INFO "[LS]%s: als_kadc =0x%x wait to be set\n",
- __func__, lpi->als_kadc);
- }
+ if (lpi->als_kadc != 0) {
+ if (lightsensor_update_table(lpi) < 0)
+ dev_err(&lpi->i2c_client->dev, "%s: update ls table fail\n",
+ __func__);
+ } else {
+ dev_dbg(&lpi->i2c_client->dev, "als_kadc =0x%x wait to be set\n",
+ lpi->als_kadc);
+ }
} else {
- printk(KERN_INFO "[LS]%s: als_gadc can't be set to zero\n",
- __func__);
+ dev_err(&lpi->i2c_client->dev, "als_gadc can't be set to zero\n");
}
mutex_unlock(&als_get_adc_mutex);
return count;
@@ -1161,29 +1126,24 @@
uint16_t tempdata[10];
int i;
- printk(KERN_INFO "[LS][CM36283]%s\n", buf);
for (i = 0; i < 10; i++) {
token[i] = strsep((char **)&buf, " ");
tempdata[i] = simple_strtoul(token[i], NULL, 16);
if (tempdata[i] < 1 || tempdata[i] > 0xffff) {
- printk(KERN_ERR
- "[LS][CM36283 error] adc_table[%d] = 0x%x Err\n",
+ dev_err(&lpi->i2c_client->dev,
+ "adc_table[%d] = 0x%x error\n",
i, tempdata[i]);
return count;
}
}
mutex_lock(&als_get_adc_mutex);
- for (i = 0; i < 10; i++) {
+ for (i = 0; i < 10; i++)
lpi->adc_table[i] = tempdata[i];
- printk(KERN_INFO
- "[LS][CM36283]Set lpi->adc_table[%d] = 0x%x\n",
- i, *(lp_info->adc_table + i));
- }
+
if (lightsensor_update_table(lpi) < 0)
- printk(KERN_ERR "[LS][CM36283 error] %s: update ls table fail\n",
+ dev_err(&lpi->i2c_client->dev, "%s: update ls table fail\n",
__func__);
mutex_unlock(&als_get_adc_mutex);
- D("[LS][CM36283] %s\n", __func__);
return count;
}
@@ -1206,8 +1166,9 @@
sscanf(buf, "0x%x", &value);
lpi->ls_cmd = value;
- printk(KERN_INFO "[LS]set ALS_CONF = %x\n", lpi->ls_cmd);
-
+
+ dev_dbg(&lpi->i2c_client->dev, "ALS_CONF:0x%x\n", lpi->ls_cmd);
+
_cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);
return count;
}
@@ -1285,7 +1246,6 @@
fLevel=value;
input_report_abs(lpi->ls_input_dev, ABS_MISC, fLevel);
input_sync(lpi->ls_input_dev);
- printk(KERN_INFO "[LS]set fLevel = %d\n", fLevel);
msleep(1000);
fLevel=-1;
@@ -1381,7 +1341,8 @@
uint16_t idReg;
val = gpio_get_value(lpi->intr_pin);
- D("[PS][CM36283] %s, INTERRUPT GPIO val = %d\n", __func__, val);
+ dev_dbg(&lpi->i2c_client->dev, "%s, INTERRUPT GPIO val = %d\n",
+ __func__, val);
ret = _cm36283_I2C_Read_Word(lpi->slave_addr, ID_REG, &idReg);
@@ -1545,15 +1506,10 @@
struct cm36283_info *lpi;
struct cm36283_platform_data *pdata;
- D("[PS][CM36283] %s\n", __func__);
-
-
lpi = kzalloc(sizeof(struct cm36283_info), GFP_KERNEL);
if (!lpi)
return -ENOMEM;
- /*D("[CM36283] %s: client->irq = %d\n", __func__, client->irq);*/
-
lpi->i2c_client = client;
if (client->dev.of_node) {
@@ -1605,7 +1561,7 @@
lpi->record_clear_int_fail=0;
- D("[PS][CM36283] %s: ls_cmd 0x%x\n",
+ dev_dbg(&lpi->i2c_client->dev, "[PS][CM36283] %s: ls_cmd 0x%x\n",
__func__, lpi->ls_cmd);
if (pdata->ls_cmd == 0) {
@@ -1777,7 +1733,7 @@
mutex_init(&wq_lock);
INIT_DELAYED_WORK(&lpi->ldwork, lsensor_delay_work_handler);
INIT_DELAYED_WORK(&lpi->pdwork, psensor_delay_work_handler);
- D("[PS][CM36283] %s: Probe success!\n", __func__);
+ dev_dbg(&lpi->i2c_client->dev, "%s: Probe success!\n", __func__);
return ret;
diff --git a/drivers/input/misc/mma8x5x.c b/drivers/input/misc/mma8x5x.c
index f49ff14..a325d54 100644
--- a/drivers/input/misc/mma8x5x.c
+++ b/drivers/input/misc/mma8x5x.c
@@ -304,6 +304,28 @@
return 0;
}
+static int mma8x5x_device_start(struct i2c_client *client)
+{
+ struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+
+ if (i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, 0))
+ goto err_out;
+ if (i2c_smbus_write_byte_data(client, MMA8X5X_XYZ_DATA_CFG,
+ pdata->mode))
+ goto err_out;
+
+ /* The BT(boot time) for mma8x5x is 1.55ms according to
+ *Freescale mma8450Q document. Document Number:MMA8450Q
+ *Rev: 9.1, 04/2012
+ */
+ usleep_range(1600, 2000);
+ return 0;
+
+err_out:
+ dev_err(&client->dev, "%s:start device failed", __func__);
+ return -EIO;
+}
+
static int mma8x5x_read_data(struct i2c_client *client,
struct mma8x5x_data_axis *data)
{
@@ -381,32 +403,73 @@
int ret;
unsigned long enable;
u8 val = 0;
+
ret = kstrtoul(buf, 10, &enable);
if (ret)
return ret;
mutex_lock(&pdata->data_lock);
enable = (enable > 0) ? 1 : 0;
- if (enable && pdata->active == MMA_STANDBY) {
- val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
- ret = i2c_smbus_write_byte_data(client,
- MMA8X5X_CTRL_REG1, val|0x01);
- if (!ret) {
+ if (enable) {
+ if (pdata->active & MMA_SHUTTEDDOWN) {
+ ret = mma8x5x_config_regulator(client, 1);
+ if (ret)
+ goto err_failed;
+
+ ret = mma8x5x_device_start(client);
+ if (ret)
+ goto err_failed;
+
+ pdata->active &= ~MMA_SHUTTEDDOWN;
+ }
+ if (pdata->active == MMA_STANDBY) {
+ val = i2c_smbus_read_byte_data(client,
+ MMA8X5X_CTRL_REG1);
+ if (val < 0) {
+ dev_err(dev, "read device state failed!");
+ ret = val;
+ goto err_failed;
+ }
+
+ ret = i2c_smbus_write_byte_data(client,
+ MMA8X5X_CTRL_REG1, val | 0x01);
+ if (ret) {
+ dev_err(dev, "change device state failed!");
+ goto err_failed;
+ }
pdata->active = MMA_ACTIVED;
- dev_dbg(dev,
- "%s:mma enable setting active.\n", __func__);
+ dev_dbg(dev, "%s:mma enable setting active.\n",
+ __func__);
}
- } else if (enable == 0 && pdata->active == MMA_ACTIVED) {
- val = i2c_smbus_read_byte_data(client, MMA8X5X_CTRL_REG1);
- ret = i2c_smbus_write_byte_data(client,
- MMA8X5X_CTRL_REG1, val & 0xFE);
- if (!ret) {
+ } else if (enable == 0) {
+ if (pdata->active == MMA_ACTIVED) {
+ val = i2c_smbus_read_byte_data(client,
+ MMA8X5X_CTRL_REG1);
+ if (val < 0) {
+ dev_err(dev, "read device state failed!");
+ ret = val;
+ goto err_failed;
+ }
+
+ ret = i2c_smbus_write_byte_data(client,
+ MMA8X5X_CTRL_REG1, val & 0xFE);
+ if (ret) {
+ dev_err(dev, "change device state failed!");
+ goto err_failed;
+ }
+
pdata->active = MMA_STANDBY;
- dev_dbg(dev,
- "%s:mma enable setting inactive.\n", __func__);
+ dev_dbg(dev, "%s:mma enable setting inactive.\n",
+ __func__);
}
+ if (!mma8x5x_config_regulator(client, 0))
+ pdata->active |= MMA_SHUTTEDDOWN;
}
mutex_unlock(&pdata->data_lock);
return count;
+
+err_failed:
+ mutex_unlock(&pdata->data_lock);
+ return ret;
}
static ssize_t mma8x5x_position_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -617,6 +680,8 @@
struct mma8x5x_data *pdata = i2c_get_clientdata(client);
if (pdata->active == MMA_ACTIVED)
mma8x5x_device_stop(client);
+ if (pdata->active & MMA_SHUTTEDDOWN)
+ return 0;
if (!mma8x5x_config_regulator(client, 0))
/* The highest bit sotres the power state */
pdata->active |= MMA_SHUTTEDDOWN;
@@ -628,22 +693,16 @@
int val = 0;
struct i2c_client *client = to_i2c_client(dev);
struct mma8x5x_data *pdata = i2c_get_clientdata(client);
+
+ /* No need to power on while device is shutdowned from standby state */
+ if (pdata->active == (MMA_SHUTTEDDOWN | MMA_STANDBY))
+ return 0;
if (pdata->active & MMA_SHUTTEDDOWN) {
if (mma8x5x_config_regulator(client, 1))
goto out;
- if (i2c_smbus_write_byte_data(client, MMA8X5X_CTRL_REG1, 0))
+ if (mma8x5x_device_start(client))
goto out;
-
- if (i2c_smbus_write_byte_data(client, MMA8X5X_XYZ_DATA_CFG,
- pdata->mode))
- goto out;
-
- /* The BT(boot time) for mma8x5x is 1.55ms according to
- Freescale mma8450Q document. Document Number:MMA8450Q
- Rev: 9.1, 04/2012
- */
- usleep_range(1600, 2000);
pdata->active &= ~MMA_SHUTTEDDOWN;
}
if (pdata->active == MMA_ACTIVED) {
diff --git a/drivers/input/misc/stk3x1x.c b/drivers/input/misc/stk3x1x.c
index 937bf6c..b753d55 100644
--- a/drivers/input/misc/stk3x1x.c
+++ b/drivers/input/misc/stk3x1x.c
@@ -190,6 +190,7 @@
struct stk3x1x_data {
struct i2c_client *client;
+ struct stk3x1x_platform_data *pdata;
#if (!defined(STK_POLL_PS) || !defined(STK_POLL_ALS))
int32_t irq;
struct work_struct stk_work;
@@ -257,6 +258,7 @@
static int32_t stk3x1x_set_ps_thd_h(struct stk3x1x_data *ps_data, uint16_t thd_h);
static int32_t stk3x1x_set_als_thd_l(struct stk3x1x_data *ps_data, uint16_t thd_l);
static int32_t stk3x1x_set_als_thd_h(struct stk3x1x_data *ps_data, uint16_t thd_h);
+static int stk3x1x_device_ctl(struct stk3x1x_data *ps_data, bool enable);
//static int32_t stk3x1x_set_ps_aoffset(struct stk3x1x_data *ps_data, uint16_t offset);
inline uint32_t stk_alscode2lux(struct stk3x1x_data *ps_data, uint32_t alscode)
@@ -600,6 +602,12 @@
if(curr_ps_enable == enable)
return 0;
+ if (enable) {
+ ret = stk3x1x_device_ctl(ps_data, enable);
+ if (ret)
+ return ret;
+ }
+
ret = i2c_smbus_read_byte_data(ps_data->client, STK_STATE_REG);
if (ret < 0)
{
@@ -662,6 +670,12 @@
#endif
ps_data->ps_enabled = false;
}
+ if (!enable) {
+ ret = stk3x1x_device_ctl(ps_data, enable);
+ if (ret)
+ return ret;
+ }
+
return ret;
}
@@ -674,6 +688,11 @@
if(curr_als_enable == enable)
return 0;
+ if (enable) {
+ ret = stk3x1x_device_ctl(ps_data, enable);
+ if (ret)
+ return ret;
+ }
#ifndef STK_POLL_ALS
if (enable)
{
@@ -724,6 +743,12 @@
disable_irq(ps_data->irq);
#endif
}
+ if (!enable) {
+ ret = stk3x1x_device_ctl(ps_data, enable);
+ if (ret)
+ return ret;
+ }
+
return ret;
}
@@ -1817,11 +1842,6 @@
int32_t ret;
struct stk3x1x_data *ps_data = i2c_get_clientdata(client);
- mutex_lock(&ps_data->io_lock);
- ps_data->als_enabled = false;
- ps_data->ps_enabled = false;
- mutex_unlock(&ps_data->io_lock);
-
ret = stk3x1x_software_reset(ps_data);
if(ret < 0)
return ret;
@@ -1946,7 +1966,7 @@
}
#endif //#ifdef CONFIG_HAS_EARLYSUSPEND
-static int stk3x1x_power_on(struct stk3x1x_data *data, bool on)
+static int stk3x1x_power_ctl(struct stk3x1x_data *data, bool on)
{
int ret = 0;
@@ -1963,7 +1983,11 @@
dev_err(&data->client->dev,
"Regulator vio disable failed ret=%d\n", ret);
regulator_enable(data->vdd);
+ return ret;
}
+ data->power_enabled = on;
+ dev_dbg(&data->client->dev, "stk3x1x_power_ctl on=%d\n",
+ on);
} else if (on && !data->power_enabled) {
ret = regulator_enable(data->vdd);
@@ -1978,7 +2002,11 @@
dev_err(&data->client->dev,
"Regulator vio enable failed ret=%d\n", ret);
regulator_disable(data->vdd);
+ return ret;
}
+ data->power_enabled = on;
+ dev_dbg(&data->client->dev, "stk3x1x_power_ctl on=%d\n",
+ on);
} else {
dev_warn(&data->client->dev,
"Power on=%d. enabled=%d\n",
@@ -2057,6 +2085,43 @@
return ret;
}
+static int stk3x1x_device_ctl(struct stk3x1x_data *ps_data, bool enable)
+{
+ int ret;
+ struct device *dev = &ps_data->client->dev;
+
+ if (enable && !ps_data->power_enabled) {
+ ret = stk3x1x_power_ctl(ps_data, true);
+ if (ret) {
+ dev_err(dev, "Failed to enable device power\n");
+ goto err_exit;
+ }
+ ret = stk3x1x_init_all_setting(ps_data->client, ps_data->pdata);
+ if (ret < 0) {
+ stk3x1x_power_ctl(ps_data, false);
+ dev_err(dev, "Failed to re-init device setting\n");
+ goto err_exit;
+ }
+ } else if (!enable && ps_data->power_enabled) {
+ if (!ps_data->als_enabled && !ps_data->ps_enabled) {
+ ret = stk3x1x_power_ctl(ps_data, false);
+ if (ret) {
+ dev_err(dev, "Failed to disable device power\n");
+ goto err_exit;
+ }
+ } else {
+ dev_dbg(dev, "device control: als_enabled=%d, ps_enabled=%d\n",
+ ps_data->als_enabled, ps_data->ps_enabled);
+ }
+ } else {
+ dev_dbg(dev, "device control: enable=%d, power_enabled=%d\n",
+ enable, ps_data->power_enabled);
+ }
+ return 0;
+
+err_exit:
+ return ret;
+}
#ifdef CONFIG_OF
static int stk3x1x_parse_dt(struct device *dev,
struct stk3x1x_platform_data *pdata)
@@ -2205,6 +2270,7 @@
ps_data->als_transmittance = plat_data->transmittance;
ps_data->int_pin = plat_data->int_pin;
ps_data->use_fir = plat_data->use_fir;
+ ps_data->pdata = plat_data;
if (ps_data->als_transmittance == 0) {
dev_err(&client->dev,
@@ -2285,24 +2351,28 @@
if (err)
goto err_power_init;
- err = stk3x1x_power_on(ps_data, true);
+ err = stk3x1x_power_ctl(ps_data, true);
if (err)
goto err_power_on;
- err = stk3x1x_init_all_setting(client, plat_data);
- if(err < 0)
- goto err_init_all_setting;
+ ps_data->als_enabled = false;
+ ps_data->ps_enabled = false;
#ifdef CONFIG_HAS_EARLYSUSPEND
ps_data->stk_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
ps_data->stk_early_suspend.suspend = stk3x1x_early_suspend;
ps_data->stk_early_suspend.resume = stk3x1x_late_resume;
register_early_suspend(&ps_data->stk_early_suspend);
#endif
- printk(KERN_INFO "%s: probe successfully", __func__);
+ /* enable device power only when it is enabled */
+ err = stk3x1x_power_ctl(ps_data, false);
+ if (err)
+ goto err_init_all_setting;
+
+ dev_dbg(&client->dev, "%s: probe successfully", __func__);
return 0;
err_init_all_setting:
- stk3x1x_power_on(ps_data, false);
+ stk3x1x_power_ctl(ps_data, false);
err_power_on:
stk3x1x_power_init(ps_data, false);
err_power_init:
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 4dbe5c1..3731561 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -1727,7 +1727,7 @@
}
ret = request_firmware(&fw, fn, dev);
- if (ret < 0) {
+ if (ret < 0 || !fw) {
dev_err(dev, "Unable to open firmware %s\n", fn);
goto free_frame;
}
diff --git a/drivers/input/touchscreen/ft5x06_ts.c b/drivers/input/touchscreen/ft5x06_ts.c
index 2f9ea10..aa50d44 100644
--- a/drivers/input/touchscreen/ft5x06_ts.c
+++ b/drivers/input/touchscreen/ft5x06_ts.c
@@ -336,7 +336,6 @@
input_report_abs(ip_dev, ABS_MT_PRESSURE, pressure);
} else {
input_mt_report_slot_state(ip_dev, MT_TOOL_FINGER, 0);
- input_report_abs(ip_dev, ABS_MT_PRESSURE, 0);
}
}
@@ -1247,6 +1246,9 @@
pdata->fw_vkey_support = of_property_read_bool(np,
"focaltech,fw-vkey-support");
+ pdata->ignore_id_check = of_property_read_bool(np,
+ "focaltech,ignore-id-check");
+
rc = of_property_read_u32(np, "focaltech,family-id", &temp_val);
if (!rc)
pdata->family_id = temp_val;
@@ -1447,7 +1449,7 @@
dev_info(&client->dev, "Device ID = 0x%x\n", reg_value);
- if (pdata->family_id != reg_value) {
+ if ((pdata->family_id != reg_value) && (!pdata->ignore_id_check)) {
dev_err(&client->dev, "%s:Unsupported controller\n", __func__);
goto free_reset_gpio;
}
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.c b/drivers/input/touchscreen/gt9xx/gt9xx.c
index 33ef141..8b08ac9 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx.c
+++ b/drivers/input/touchscreen/gt9xx/gt9xx.c
@@ -72,7 +72,8 @@
#define RESET_DELAY_T3_US 200 /* T3: > 100us */
#define RESET_DELAY_T4 20 /* T4: > 5ms */
-#define PHY_BUF_SIZE 32
+#define PHY_BUF_SIZE 32
+#define PROP_NAME_SIZE 24
#define GTP_MAX_TOUCH 5
#define GTP_ESD_CHECK_CIRCLE_MS 2000
@@ -143,8 +144,6 @@
int ret = -EIO;
int retries = 0;
- GTP_DEBUG_FUNC();
-
msgs[0].flags = !I2C_M_RD;
msgs[0].addr = client->addr;
msgs[0].len = GTP_ADDR_LENGTH;
@@ -167,7 +166,6 @@
if (DOZE_ENABLED == doze_status)
return ret;
#endif
- GTP_DEBUG("I2C communication timeout, resetting chip...");
if (init_done)
gtp_reset_guitar(ts, 10);
else
@@ -197,8 +195,6 @@
int ret = -EIO;
int retries = 0;
- GTP_DEBUG_FUNC();
-
msg.flags = !I2C_M_RD;
msg.addr = client->addr;
msg.len = len;
@@ -215,7 +211,6 @@
if (DOZE_ENABLED == doze_status)
return ret;
#endif
- GTP_DEBUG("I2C communication timeout, resetting chip...");
if (init_done)
gtp_reset_guitar(ts, 10);
else
@@ -314,8 +309,6 @@
{
unsigned long irqflags;
- GTP_DEBUG_FUNC();
-
spin_lock_irqsave(&ts->irq_lock, irqflags);
if (!ts->irq_is_disabled) {
ts->irq_is_disabled = true;
@@ -336,8 +329,6 @@
{
unsigned long irqflags = 0;
- GTP_DEBUG_FUNC();
-
spin_lock_irqsave(&ts->irq_lock, irqflags);
if (ts->irq_is_disabled) {
enable_irq(ts->client->irq);
@@ -362,7 +353,7 @@
int w)
{
#if GTP_CHANGE_X2Y
- GTP_SWAP(x, y);
+ swap(x, y);
#endif
input_mt_slot(ts->input_dev, id);
@@ -371,8 +362,6 @@
input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w);
input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w);
-
- GTP_DEBUG("ID:%d, X:%d, Y:%d, W:%d", id, x, y, w);
}
/*******************************************************
@@ -387,7 +376,6 @@
{
input_mt_slot(ts->input_dev, id);
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, false);
- GTP_DEBUG("Touch id[%2d] release!", id);
}
@@ -428,8 +416,6 @@
u8 doze_buf[3] = {0x81, 0x4B};
#endif
- GTP_DEBUG_FUNC();
-
ts = container_of(work, struct goodix_ts_data, work);
#ifdef CONFIG_GT9XX_TOUCHPANEL_UPDATE
if (ts->enter_update)
@@ -439,7 +425,6 @@
#if GTP_SLIDE_WAKEUP
if (DOZE_ENABLED == doze_status) {
ret = gtp_i2c_read(ts->client, doze_buf, 3);
- GTP_DEBUG("0x814B = 0x%02X", doze_buf[2]);
if (ret > 0) {
if (doze_buf[2] == 0xAA) {
dev_dbg(&ts->client->dev,
@@ -516,6 +501,7 @@
if (key_value || pre_key) {
for (i = 0; i < GTP_MAX_KEY_NUM; i++) {
+
#if GTP_DEBUG_ON
for (ret = 0; ret < 4; ++ret) {
if (key_codes[ret] == touch_key_array[i]) {
@@ -537,11 +523,9 @@
#endif
pre_key = key_value;
- GTP_DEBUG("pre_touch:%02x, finger:%02x.", pre_touch, finger);
-
#if GTP_WITH_PEN
if (pre_pen && (touch_num == 0)) {
- GTP_DEBUG("Pen touch UP(Slot)!");
+ dev_dbg(&ts->client->dev, "Pen touch UP(Slot)!");
input_report_key(ts->input_dev, BTN_TOOL_PEN, 0);
input_mt_slot(ts->input_dev, 5);
input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, -1);
@@ -558,7 +542,8 @@
#if GTP_WITH_PEN
id = coor_data[pos];
if (id == 128) {
- GTP_DEBUG("Pen touch DOWN(Slot)!");
+ dev_dbg(&ts->client->dev,
+ "Pen touch DOWN(Slot)!");
input_x = coor_data[pos + 1]
| (coor_data[pos + 2] << 8);
input_y = coor_data[pos + 3]
@@ -577,7 +562,8 @@
ABS_MT_POSITION_Y, input_y);
input_report_abs(ts->input_dev,
ABS_MT_TOUCH_MAJOR, input_w);
- GTP_DEBUG("Pen/Stylus: (%d, %d)[%d]",
+ dev_dbg(&ts->client->dev,
+ "Pen/Stylus: (%d, %d)[%d]",
input_x, input_y, input_w);
pre_pen = 1;
pre_touch = 0;
@@ -587,8 +573,6 @@
touch_index |= (0x01<<id);
}
- GTP_DEBUG("id = %d,touch_index = 0x%x, pre_touch = 0x%x\n",
- id, touch_index, pre_touch);
for (i = 0; i < GTP_MAX_TOUCH; i++) {
#if GTP_WITH_PEN
if (pre_pen == 1)
@@ -644,8 +628,6 @@
struct goodix_ts_data
*ts = container_of(timer, struct goodix_ts_data, timer);
- GTP_DEBUG_FUNC();
-
queue_work(ts->goodix_wq, &ts->work);
hrtimer_start(&ts->timer, ktime_set(0, (GTP_POLL_TIME + 6) * 1000000),
HRTIMER_MODE_REL);
@@ -666,8 +648,6 @@
{
struct goodix_ts_data *ts = dev_id;
- GTP_DEBUG_FUNC();
-
gtp_irq_disable(ts);
queue_work(ts->goodix_wq, &ts->work);
@@ -699,8 +679,6 @@
*******************************************************/
static void gtp_reset_guitar(struct goodix_ts_data *ts, int ms)
{
- GTP_DEBUG_FUNC();
-
/* This reset sequence will selcet I2C slave address */
gpio_direction_output(ts->pdata->reset_gpio, 0);
msleep(ms);
@@ -741,20 +719,17 @@
(u8)(GTP_REG_SLEEP >> 8),
(u8)GTP_REG_SLEEP, 8};
- GTP_DEBUG_FUNC();
-
#if GTP_DBL_CLK_WAKEUP
i2c_control_buf[2] = 0x09;
#endif
gtp_irq_disable(ts);
- GTP_DEBUG("entering doze mode...");
while (retry++ < 5) {
i2c_control_buf[0] = 0x80;
i2c_control_buf[1] = 0x46;
ret = gtp_i2c_write(ts->client, i2c_control_buf, 3);
if (ret < 0) {
- GTP_DEBUG(
+ dev_err(&ts->client->dev,
"failed to set doze flag into 0x8046, %d",
retry);
continue;
@@ -793,8 +768,6 @@
(u8)(GTP_REG_SLEEP >> 8),
(u8)GTP_REG_SLEEP, 5};
- GTP_DEBUG_FUNC();
-
ret = gpio_direction_output(ts->pdata->irq_gpio, 0);
usleep(5000);
while (retry++ < 5) {
@@ -825,8 +798,6 @@
u8 retry = 0;
s8 ret = -1;
- GTP_DEBUG_FUNC();
-
#if GTP_POWER_CTRL_SLEEP
gtp_reset_guitar(ts, 20);
@@ -897,26 +868,9 @@
u8 opr_buf[16];
u8 sensor_id = 0;
- u8 cfg_info_group1[] = CTP_CFG_GROUP1;
- u8 cfg_info_group2[] = CTP_CFG_GROUP2;
- u8 cfg_info_group3[] = CTP_CFG_GROUP3;
- u8 cfg_info_group4[] = CTP_CFG_GROUP4;
- u8 cfg_info_group5[] = CTP_CFG_GROUP5;
- u8 cfg_info_group6[] = CTP_CFG_GROUP6;
- u8 *send_cfg_buf[] = {cfg_info_group1, cfg_info_group2,
- cfg_info_group3, cfg_info_group4,
- cfg_info_group5, cfg_info_group6};
-
- u8 cfg_info_len[] = {CFG_GROUP_LEN(cfg_info_group1),
- CFG_GROUP_LEN(cfg_info_group2),
- CFG_GROUP_LEN(cfg_info_group3),
- CFG_GROUP_LEN(cfg_info_group4),
- CFG_GROUP_LEN(cfg_info_group5),
- CFG_GROUP_LEN(cfg_info_group6)};
-
- GTP_DEBUG("Config Groups\' Lengths: %d, %d, %d, %d, %d, %d",
- cfg_info_len[0], cfg_info_len[1], cfg_info_len[2],
- cfg_info_len[3], cfg_info_len[4], cfg_info_len[5]);
+ for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++)
+ dev_dbg(&client->dev, "Config Groups(%d) Lengths: %d",
+ i, ts->pdata->config_data_len[i]);
ret = gtp_i2c_read_dbl_check(ts->client, 0x41E4, opr_buf, 1);
if (SUCCESS == ret) {
@@ -927,14 +881,18 @@
return -EINVAL;
}
}
- if ((!cfg_info_len[1]) && (!cfg_info_len[2]) && (!cfg_info_len[3])
- && (!cfg_info_len[4]) && (!cfg_info_len[5])) {
+
+ for (i = 1; i < GOODIX_MAX_CFG_GROUP; i++) {
+ if (ts->pdata->config_data_len[i])
+ break;
+ }
+ if (i == GOODIX_MAX_CFG_GROUP) {
sensor_id = 0;
} else {
ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_SENSOR_ID,
&sensor_id, 1);
if (SUCCESS == ret) {
- if (sensor_id >= 0x06) {
+ if (sensor_id >= GOODIX_MAX_CFG_GROUP) {
dev_err(&client->dev,
"Invalid sensor_id(0x%02X), No Config Sent!",
sensor_id);
@@ -946,24 +904,26 @@
return -EINVAL;
}
}
- GTP_DEBUG("Sensor_ID: %d", sensor_id);
- ts->gtp_cfg_len = cfg_info_len[sensor_id];
+ dev_info(&client->dev, "Sensor ID selected: %d", sensor_id);
- if (ts->gtp_cfg_len < GTP_CONFIG_MIN_LENGTH) {
+ if (ts->pdata->config_data_len[sensor_id] < GTP_CONFIG_MIN_LENGTH ||
+ !ts->pdata->config_data[sensor_id]) {
dev_err(&client->dev,
- "Sensor_ID(%d) matches with NULL or INVALID CONFIG GROUP! NO Config Sent! You need to check you header file CFG_GROUP section!\n",
+ "Sensor_ID(%d) matches with NULL or invalid config group!\n",
sensor_id);
return -EINVAL;
}
+
ret = gtp_i2c_read_dbl_check(ts->client, GTP_REG_CONFIG_DATA,
&opr_buf[0], 1);
-
if (ret == SUCCESS) {
if (opr_buf[0] < 90) {
/* backup group config version */
- grp_cfg_version = send_cfg_buf[sensor_id][0];
- send_cfg_buf[sensor_id][0] = 0x00;
+ grp_cfg_version =
+ ts->pdata->config_data[sensor_id][GTP_ADDR_LENGTH];
+ ts->pdata->config_data[sensor_id][GTP_ADDR_LENGTH] =
+ 0x00;
ts->fixed_cfg = 0;
} else {
/* treated as fixed config, not send config */
@@ -978,27 +938,9 @@
return -EINVAL;
}
- if (ts->pdata->gtp_cfg_len) {
- config_data = ts->pdata->config_data;
- ts->config_data = ts->pdata->config_data;
- ts->gtp_cfg_len = ts->pdata->gtp_cfg_len;
- } else {
- config_data = devm_kzalloc(&client->dev,
- GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH,
- GFP_KERNEL);
- if (!config_data) {
- dev_err(&client->dev,
- "Not enough memory for panel config data\n");
- return -ENOMEM;
- }
-
- ts->config_data = config_data;
- config_data[0] = GTP_REG_CONFIG_DATA >> 8;
- config_data[1] = GTP_REG_CONFIG_DATA & 0xff;
- memset(&config_data[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH);
- memcpy(&config_data[GTP_ADDR_LENGTH], send_cfg_buf[sensor_id],
- ts->gtp_cfg_len);
- }
+ config_data = ts->pdata->config_data[sensor_id];
+ ts->config_data = ts->pdata->config_data[sensor_id];
+ ts->gtp_cfg_len = ts->pdata->config_data_len[sensor_id];
#if GTP_CUSTOM_CFG
config_data[RESOLUTION_LOC] =
@@ -1035,7 +977,6 @@
}
#endif /* !DRIVER NOT SEND CONFIG */
- GTP_DEBUG_FUNC();
if ((ts->abs_x_max == 0) && (ts->abs_y_max == 0)) {
ts->abs_x_max = (config_data[RESOLUTION_LOC + 1] << 8)
+ config_data[RESOLUTION_LOC];
@@ -1047,49 +988,79 @@
if (ret < 0)
dev_err(&client->dev, "%s: Send config error.\n", __func__);
- GTP_DEBUG("X_MAX = %d, Y_MAX = %d, TRIGGER = 0x%02x",
- ts->abs_x_max, ts->abs_y_max,
- ts->int_trigger_type);
-
msleep(20);
return ret;
}
/*******************************************************
Function:
- Read chip version.
+ Read firmware version
Input:
client: i2c device
version: buffer to keep ic firmware version
Output:
read operation return.
- 2: succeed, otherwise: failed
+ 0: succeed, otherwise: failed
*******************************************************/
-int gtp_read_version(struct i2c_client *client, u16 *version)
+static int gtp_read_fw_version(struct i2c_client *client, u16 *version)
{
- int ret = -EIO;
- u8 buf[8] = { GTP_REG_VERSION >> 8, GTP_REG_VERSION & 0xff };
-
- GTP_DEBUG_FUNC();
+ int ret = 0;
+ u8 buf[GTP_FW_VERSION_BUFFER_MAXSIZE] = {
+ GTP_REG_FW_VERSION >> 8, GTP_REG_FW_VERSION & 0xff };
ret = gtp_i2c_read(client, buf, sizeof(buf));
if (ret < 0) {
dev_err(&client->dev, "GTP read version failed.\n");
- return ret;
+ return -EIO;
}
if (version)
- *version = (buf[7] << 8) | buf[6];
+ *version = (buf[3] << 8) | buf[2];
+
+ return ret;
+}
+/*******************************************************
+Function:
+ Read and check chip id.
+Input:
+ client: i2c device
+Output:
+ read operation return.
+ 0: succeed, otherwise: failed
+*******************************************************/
+static int gtp_check_product_id(struct i2c_client *client)
+{
+ int ret = 0;
+ char product_id[GTP_PRODUCT_ID_MAXSIZE];
+ struct goodix_ts_data *ts = i2c_get_clientdata(client);
+ /* 04 bytes are used for the Product-id in the register space.*/
+ u8 buf[GTP_PRODUCT_ID_BUFFER_MAXSIZE] = {
+ GTP_REG_PRODUCT_ID >> 8, GTP_REG_PRODUCT_ID & 0xff };
+
+ ret = gtp_i2c_read(client, buf, sizeof(buf));
+ if (ret < 0) {
+ dev_err(&client->dev, "GTP read version failed.\n");
+ return -EIO;
+ }
if (buf[5] == 0x00) {
- dev_dbg(&client->dev, "IC Version: %c%c%c_%02x%02x\n", buf[2],
- buf[3], buf[4], buf[7], buf[6]);
+ /* copy (GTP_PRODUCT_ID_MAXSIZE - 1) from buffer. Ex: 915 */
+ strlcpy(product_id, &buf[2], GTP_PRODUCT_ID_MAXSIZE - 1);
} else {
if (buf[5] == 'S' || buf[5] == 's')
chip_gt9xxs = 1;
- dev_dbg(&client->dev, "IC Version: %c%c%c%c_%02x%02x\n", buf[2],
- buf[3], buf[4], buf[5], buf[7], buf[6]);
+ /* copy GTP_PRODUCT_ID_MAXSIZE from buffer. Ex: 915s */
+ strlcpy(product_id, &buf[2], GTP_PRODUCT_ID_MAXSIZE);
}
+
+ dev_info(&client->dev, "Goodix Product ID = %s\n", product_id);
+
+ if (!IS_ERR(ts->pdata->product_id))
+ ret = strcmp(product_id, ts->pdata->product_id);
+
+ if (ret != 0)
+ return -EINVAL;
+
return ret;
}
@@ -1108,8 +1079,6 @@
int retry = 5;
int ret = -EIO;
- GTP_DEBUG_FUNC();
-
while (retry--) {
ret = gtp_i2c_read(client, buf, 3);
if (ret > 0)
@@ -1198,9 +1167,6 @@
int ret;
const u8 irq_table[] = GTP_IRQ_TAB;
- GTP_DEBUG("INT trigger type:%x, irq=%d", ts->int_trigger_type,
- ts->client->irq);
-
ret = request_irq(ts->client->irq, goodix_ts_irq_handler,
irq_table[ts->int_trigger_type],
ts->client->name, ts);
@@ -1240,8 +1206,6 @@
int index = 0;
#endif
- GTP_DEBUG_FUNC();
-
ts->input_dev = input_allocate_device();
if (ts->input_dev == NULL) {
dev_err(&ts->client->dev,
@@ -1274,7 +1238,7 @@
#endif
#if GTP_CHANGE_X2Y
- GTP_SWAP(ts->abs_x_max, ts->abs_y_max);
+ swap(ts->abs_x_max, ts->abs_y_max);
#endif
input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,
@@ -1556,6 +1520,8 @@
struct property *prop;
u32 temp_val, num_buttons;
u32 button_map[MAX_BUTTONS];
+ char prop_name[PROP_NAME_SIZE];
+ int i, read_cfg_num;
rc = goodix_ts_get_dt_coords(dev, "goodix,panel-coords", pdata);
if (rc && (rc != -EINVAL))
@@ -1581,10 +1547,9 @@
if (pdata->irq_gpio < 0)
return pdata->irq_gpio;
- rc = of_property_read_u32(np, "goodix,family-id", &temp_val);
- if (!rc)
- pdata->family_id = temp_val;
- else
+ rc = of_property_read_string(np, "goodix,product-id",
+ &pdata->product_id);
+ if (rc < 0 || strlen(pdata->product_id) > GTP_PRODUCT_ID_MAXSIZE)
return rc;
prop = of_find_property(np, "goodix,button-map", NULL);
@@ -1602,26 +1567,32 @@
}
}
- prop = of_find_property(np, "goodix,cfg-data", &pdata->gtp_cfg_len);
- if (prop && prop->value) {
- pdata->config_data = devm_kzalloc(dev,
- GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH, GFP_KERNEL);
- if (!pdata->config_data) {
- dev_err(dev, "Not enough memory for panel config data\n");
+ read_cfg_num = 0;
+ for (i = 0; i < GOODIX_MAX_CFG_GROUP; i++) {
+ snprintf(prop_name, sizeof(prop_name), "goodix,cfg-data%d", i);
+ prop = of_find_property(np, prop_name,
+ &pdata->config_data_len[i]);
+ if (!prop || !prop->value) {
+ pdata->config_data_len[i] = 0;
+ pdata->config_data[i] = NULL;
+ continue;
+ }
+ pdata->config_data[i] = devm_kzalloc(dev,
+ GTP_CONFIG_MAX_LENGTH + GTP_ADDR_LENGTH,
+ GFP_KERNEL);
+ if (!pdata->config_data[i]) {
+ dev_err(dev,
+ "Not enough memory for panel config data %d\n",
+ i);
return -ENOMEM;
}
-
- pdata->config_data[0] = GTP_REG_CONFIG_DATA >> 8;
- pdata->config_data[1] = GTP_REG_CONFIG_DATA & 0xff;
- memset(&pdata->config_data[GTP_ADDR_LENGTH], 0,
- GTP_CONFIG_MAX_LENGTH);
- memcpy(&pdata->config_data[GTP_ADDR_LENGTH],
- prop->value, pdata->gtp_cfg_len);
- } else {
- dev_err(dev,
- "Unable to get configure data, default will be used.\n");
- pdata->gtp_cfg_len = 0;
+ pdata->config_data[i][0] = GTP_REG_CONFIG_DATA >> 8;
+ pdata->config_data[i][1] = GTP_REG_CONFIG_DATA & 0xff;
+ memcpy(&pdata->config_data[i][GTP_ADDR_LENGTH],
+ prop->value, pdata->config_data_len[i]);
+ read_cfg_num++;
}
+ dev_dbg(dev, "%d config data read from device tree.\n", read_cfg_num);
return 0;
}
@@ -1764,9 +1735,13 @@
else
dev_info(&client->dev, "GTP works in interrupt mode.\n");
- ret = gtp_read_version(client, &version_info);
- if (ret != 2) {
- dev_err(&client->dev, "Read version failed.\n");
+ ret = gtp_read_fw_version(client, &version_info);
+ if (ret != 0)
+ dev_err(&client->dev, "GTP firmware version read failed.\n");
+
+ ret = gtp_check_product_id(client);
+ if (ret != 0) {
+ dev_err(&client->dev, "GTP Product id doesn't match.\n");
goto exit_free_irq;
}
if (ts->use_irq)
@@ -1831,7 +1806,6 @@
{
struct goodix_ts_data *ts = i2c_get_clientdata(client);
- GTP_DEBUG_FUNC();
#if defined(CONFIG_FB)
if (fb_unregister_client(&ts->fb_notif))
dev_err(&client->dev,
@@ -1894,8 +1868,6 @@
{
int ret = -1, i;
- GTP_DEBUG_FUNC();
-
#if GTP_ESD_PROTECT
ts->gtp_is_suspend = 1;
gtp_esd_switch(ts->client, SWITCH_OFF);
@@ -1936,8 +1908,6 @@
{
int ret = -1;
- GTP_DEBUG_FUNC();
-
ret = gtp_wakeup_sleep(ts);
#if GTP_SLIDE_WAKEUP
@@ -2066,9 +2036,6 @@
int ret;
int retries = 0;
- GTP_DEBUG("Init external watchdog...");
- GTP_DEBUG_FUNC();
-
msg.flags = !I2C_M_RD;
msg.addr = client->addr;
msg.len = 4;
@@ -2101,8 +2068,6 @@
struct goodix_ts_data *ts = NULL;
u8 test[4] = {0x80, 0x40};
- GTP_DEBUG_FUNC();
-
ts = i2c_get_clientdata(i2c_connect_client);
if (ts->gtp_is_suspend) {
@@ -2118,7 +2083,6 @@
for (i = 0; i < 3; i++) {
ret = gtp_i2c_read(ts->client, test, 4);
- GTP_DEBUG("0x8040 = 0x%02X, 0x8041 = 0x%02X", test[2], test[3]);
if ((ret < 0)) {
/* IC works abnormally..*/
continue;
@@ -2190,7 +2154,6 @@
{
int ret;
- GTP_DEBUG_FUNC();
#if GTP_ESD_PROTECT
INIT_DELAYED_WORK(>p_esd_check_work, gtp_esd_check_func);
gtp_esd_check_workqueue = create_workqueue("gtp_esd_check");
@@ -2209,7 +2172,6 @@
********************************************************/
static void __exit goodix_ts_exit(void)
{
- GTP_DEBUG_FUNC();
i2c_del_driver(&goodix_ts_driver);
}
diff --git a/drivers/input/touchscreen/gt9xx/gt9xx.h b/drivers/input/touchscreen/gt9xx/gt9xx.h
index c9b81e7..1fdbfa3 100644
--- a/drivers/input/touchscreen/gt9xx/gt9xx.h
+++ b/drivers/input/touchscreen/gt9xx/gt9xx.h
@@ -45,12 +45,13 @@
#define GOODIX_SUSPEND_LEVEL 1
#endif
+#define GOODIX_MAX_CFG_GROUP 6
struct goodix_ts_platform_data {
int irq_gpio;
u32 irq_gpio_flags;
int reset_gpio;
u32 reset_gpio_flags;
- u32 family_id;
+ const char *product_id;
u32 x_max;
u32 y_max;
u32 x_min;
@@ -61,8 +62,8 @@
u32 panel_maxy;
bool no_force_update;
bool i2c_pull_up;
- int gtp_cfg_len;
- u8 *config_data;
+ size_t config_data_len[GOODIX_MAX_CFG_GROUP];
+ u8 *config_data[GOODIX_MAX_CFG_GROUP];
};
struct goodix_ts_data {
spinlock_t irq_lock;
@@ -122,7 +123,7 @@
/* double-click wakeup, function together with GTP_SLIDE_WAKEUP */
#define GTP_DBL_CLK_WAKEUP 0
-#define GTP_DEBUG_ON 1
+#define GTP_DEBUG_ON 0
#define GTP_DEBUG_ARRAY_ON 0
#define GTP_DEBUG_FUNC_ON 0
@@ -137,54 +138,6 @@
* VDDIO NC/300K 4
* NC NC/300K 5
*/
-/* Define your own default or for Sensor_ID == 0 config here */
-/* The predefined one is just a sample config,
- * which is not suitable for your tp in most cases. */
-#define CTP_CFG_GROUP1 {\
- 0x41, 0x1C, 0x02, 0xC0, 0x03, 0x0A, 0x05, 0x01, 0x01, 0x0F,\
- 0x23, 0x0F, 0x5F, 0x41, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00,\
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x00, 0x0A,\
- 0x28, 0x00, 0xB8, 0x0B, 0x00, 0x00, 0x00, 0x9A, 0x03, 0x25,\
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x64, 0x32, 0x00, 0x00,\
- 0x00, 0x32, 0x8C, 0x94, 0x05, 0x01, 0x05, 0x00, 0x00, 0x96,\
- 0x0C, 0x22, 0xD8, 0x0E, 0x23, 0x56, 0x11, 0x25, 0xFF, 0x13,\
- 0x28, 0xA7, 0x15, 0x2E, 0x00, 0x00, 0x10, 0x30, 0x48, 0x00,\
- 0x56, 0x4A, 0x3A, 0xFF, 0xFF, 0x16, 0x00, 0x00, 0x00, 0x00,\
- 0x00, 0x01, 0x1B, 0x14, 0x0D, 0x19, 0x00, 0x00, 0x01, 0x00,\
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
- 0x00, 0x00, 0x1A, 0x18, 0x16, 0x14, 0x12, 0x10, 0x0E, 0x0C,\
- 0x0A, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\
- 0xFF, 0xFF, 0x1D, 0x1E, 0x1F, 0x20, 0x22, 0x24, 0x28, 0x29,\
- 0x0C, 0x0A, 0x08, 0x00, 0x02, 0x04, 0x05, 0x06, 0x0E, 0xFF,\
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,\
- 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0x01\
- }
-
-/* Define your config for Sensor_ID == 1 here, if needed */
-#define CTP_CFG_GROUP2 {\
- }
-
-/* Define your config for Sensor_ID == 2 here, if needed */
-#define CTP_CFG_GROUP3 {\
- }
-
-/* Define your config for Sensor_ID == 3 here, if needed */
-#define CTP_CFG_GROUP4 {\
- }
-
-/* Define your config for Sensor_ID == 4 here, if needed */
-#define CTP_CFG_GROUP5 {\
- }
-
-/* Define your config for Sensor_ID == 5 here, if needed */
-#define CTP_CFG_GROUP6 {\
- }
#define GTP_IRQ_TAB {\
IRQ_TYPE_EDGE_RISING,\
@@ -206,30 +159,34 @@
#define GTP_INT_TRIGGER GTP_IRQ_TAB_FALLING
#endif
-#define GTP_MAX_TOUCH 5
-#define GTP_ESD_CHECK_CIRCLE 2000 /* jiffy: ms */
+#define GTP_PRODUCT_ID_MAXSIZE 5
+#define GTP_PRODUCT_ID_BUFFER_MAXSIZE 6
+#define GTP_FW_VERSION_BUFFER_MAXSIZE 4
+#define GTP_MAX_TOUCH 5
+#define GTP_ESD_CHECK_CIRCLE 2000 /* jiffy: ms */
/***************************PART3:OTHER define*********************************/
-#define GTP_DRIVER_VERSION "V1.8<2013/06/08>"
-#define GTP_I2C_NAME "Goodix-TS"
-#define GTP_POLL_TIME 10 /* jiffy: ms*/
-#define GTP_ADDR_LENGTH 2
+#define GTP_DRIVER_VERSION "V1.8.1<2013/09/01>"
+#define GTP_I2C_NAME "Goodix-TS"
+#define GTP_POLL_TIME 10 /* jiffy: ms*/
+#define GTP_ADDR_LENGTH 2
#define GTP_CONFIG_MIN_LENGTH 186
#define GTP_CONFIG_MAX_LENGTH 240
-#define FAIL 0
-#define SUCCESS 1
-#define SWITCH_OFF 0
-#define SWITCH_ON 1
+#define FAIL 0
+#define SUCCESS 1
+#define SWITCH_OFF 0
+#define SWITCH_ON 1
/* Registers define */
-#define GTP_READ_COOR_ADDR 0x814E
-#define GTP_REG_SLEEP 0x8040
-#define GTP_REG_SENSOR_ID 0x814A
-#define GTP_REG_CONFIG_DATA 0x8047
-#define GTP_REG_VERSION 0x8140
+#define GTP_READ_COOR_ADDR 0x814E
+#define GTP_REG_SLEEP 0x8040
+#define GTP_REG_SENSOR_ID 0x814A
+#define GTP_REG_CONFIG_DATA 0x8047
+#define GTP_REG_FW_VERSION 0x8144
+#define GTP_REG_PRODUCT_ID 0x8140
-#define RESOLUTION_LOC 3
-#define TRIGGER_LOC 8
+#define RESOLUTION_LOC 3
+#define TRIGGER_LOC 8
#define CFG_GROUP_LEN(p_cfg_grp) (sizeof(p_cfg_grp) / sizeof(p_cfg_grp[0]))
/* Log define */
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index 4e75971..cf43a9c 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -79,9 +79,12 @@
STATUS_DEVICE_FAILURE = 0x03,
STATUS_CONFIG_CRC_FAILURE = 0x04,
STATUS_FIRMWARE_CRC_FAILURE = 0x05,
- STATUS_CRC_IN_PROGRESS = 0x06
+ STATUS_CRC_IN_PROGRESS = 0x06,
+ STATUS_UNCONFIGURED = 0x80
};
+#define DEVICE_CONFIGURED 0x1
+
#define RMI4_VTG_MIN_UV 2700000
#define RMI4_VTG_MAX_UV 3300000
#define RMI4_ACTIVE_LOAD_UA 15000
@@ -172,6 +175,20 @@
};
};
+struct synaptics_rmi4_f01_device_control_0 {
+ union {
+ struct {
+ unsigned char sleep_mode:2;
+ unsigned char nosleep:1;
+ unsigned char reserved:2;
+ unsigned char charger_input:1;
+ unsigned char report_rate:1;
+ unsigned char configured:1;
+ } __packed;
+ unsigned char data[1];
+ };
+};
+
struct synaptics_rmi4_f12_query_5 {
union {
struct {
@@ -2654,8 +2671,6 @@
goto err_reset_gpio_dir;
}
- gpio_set_value(rmi4_data->board->reset_gpio, 0);
- usleep(RMI4_GPIO_SLEEP_LOW_US);
gpio_set_value(rmi4_data->board->reset_gpio, 1);
msleep(rmi4_data->board->reset_delay);
} else
@@ -3088,12 +3103,12 @@
static void synaptics_rmi4_sensor_sleep(struct synaptics_rmi4_data *rmi4_data)
{
int retval;
- unsigned char device_ctrl;
+ struct synaptics_rmi4_f01_device_control_0 device_ctrl;
retval = synaptics_rmi4_i2c_read(rmi4_data,
rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
+ device_ctrl.data,
+ sizeof(device_ctrl.data));
if (retval < 0) {
dev_err(&(rmi4_data->input_dev->dev),
"%s: Failed to enter sleep mode\n",
@@ -3102,13 +3117,13 @@
return;
}
- device_ctrl = (device_ctrl & ~MASK_3BIT);
- device_ctrl = (device_ctrl | NO_SLEEP_OFF | SENSOR_SLEEP);
+ device_ctrl.sleep_mode = SENSOR_SLEEP;
+ device_ctrl.nosleep = NO_SLEEP_OFF;
retval = synaptics_rmi4_i2c_write(rmi4_data,
rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
+ device_ctrl.data,
+ sizeof(device_ctrl.data));
if (retval < 0) {
dev_err(&(rmi4_data->input_dev->dev),
"%s: Failed to enter sleep mode\n",
@@ -3132,12 +3147,12 @@
static void synaptics_rmi4_sensor_wake(struct synaptics_rmi4_data *rmi4_data)
{
int retval;
- unsigned char device_ctrl;
+ struct synaptics_rmi4_f01_device_control_0 device_ctrl;
retval = synaptics_rmi4_i2c_read(rmi4_data,
rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
+ device_ctrl.data,
+ sizeof(device_ctrl.data));
if (retval < 0) {
dev_err(&(rmi4_data->input_dev->dev),
"%s: Failed to wake from sleep mode\n",
@@ -3146,13 +3161,13 @@
return;
}
- device_ctrl = (device_ctrl & ~MASK_3BIT);
- device_ctrl = (device_ctrl | NO_SLEEP_OFF | NORMAL_OPERATION);
+ device_ctrl.sleep_mode = NORMAL_OPERATION;
+ device_ctrl.nosleep = NO_SLEEP_OFF;
retval = synaptics_rmi4_i2c_write(rmi4_data,
rmi4_data->f01_ctrl_base_addr,
- &device_ctrl,
- sizeof(device_ctrl));
+ device_ctrl.data,
+ sizeof(device_ctrl.data));
if (retval < 0) {
dev_err(&(rmi4_data->input_dev->dev),
"%s: Failed to wake from sleep mode\n",
@@ -3365,6 +3380,51 @@
return retval;
}
+static int synaptics_rmi4_check_configuration(struct synaptics_rmi4_data
+ *rmi4_data)
+{
+ int retval;
+ struct synaptics_rmi4_f01_device_control_0 device_control;
+ struct synaptics_rmi4_f01_device_status device_status;
+
+ retval = synaptics_rmi4_i2c_read(rmi4_data,
+ rmi4_data->f01_data_base_addr,
+ device_status.data,
+ sizeof(device_status.data));
+ if (retval < 0) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "Failed to read device status, rc=%d\n", retval);
+ return retval;
+ }
+
+ if (device_status.unconfigured) {
+ retval = synaptics_rmi4_query_device(rmi4_data);
+ if (retval < 0) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "Failed to query device, rc=%d\n", retval);
+ return retval;
+ }
+
+ retval = synaptics_rmi4_i2c_read(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr,
+ device_control.data,
+ sizeof(device_control.data));
+ if (retval < 0)
+ return retval;
+
+ device_control.configured = DEVICE_CONFIGURED;
+
+ retval = synaptics_rmi4_i2c_write(rmi4_data,
+ rmi4_data->f01_ctrl_base_addr,
+ device_control.data,
+ sizeof(device_control.data));
+ if (retval < 0)
+ return retval;
+ }
+
+ return 0;
+}
+
/**
* synaptics_rmi4_suspend()
*
@@ -3447,24 +3507,29 @@
return 0;
}
+ retval = synaptics_rmi4_regulator_lpm(rmi4_data, false);
+ if (retval < 0) {
+ dev_err(dev, "Failed to enter active power mode\n");
+ return retval;
+ }
+
if (rmi4_data->board->disable_gpios) {
retval = synaptics_rmi4_gpio_configure(rmi4_data, true);
if (retval < 0) {
- dev_err(dev, "failed to put gpios in active state\n");
+ dev_err(dev, "Failed to put gpios in active state\n");
return retval;
}
}
- retval = synaptics_rmi4_regulator_lpm(rmi4_data, false);
- if (retval < 0) {
- dev_err(dev, "failed to enter active power mode\n");
- return retval;
- }
-
synaptics_rmi4_sensor_wake(rmi4_data);
rmi4_data->touch_stopped = false;
synaptics_rmi4_irq_enable(rmi4_data, true);
+ retval = synaptics_rmi4_check_configuration(rmi4_data);
+ if (retval < 0) {
+ dev_err(dev, "Failed to check configuration\n");
+ return retval;
+ }
rmi4_data->suspended = false;
return 0;
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 6324dff..8e70129 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -45,10 +45,22 @@
If unsure, say N here.
+# MSM IOMMU sync lock support
+config MSM_IOMMU_SYNC
+ bool "MSM IOMMU Sync Lock Support"
+ depends on (ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_APQ8064 || ARCH_MSM8930 || ARCH_MSM8610) && MSM_IOMMU_V0
+ help
+ Say Y here if you want the IOMMU to grab a remote spinlock to ensure
+ synchronization between IOMMU accesses by CPU and other exectution
+ environments in the SoC.
+
+ If unsure, say N here.
+
# MSM IOMMU CPU-GPU sync programming support
config MSM_IOMMU_GPU_SYNC
bool "MSM IOMMU CPU-GPU Sync Support"
- depends on (ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_APQ8064 || ARCH_MSM8930) && MSM_IOMMU_V0 && MSM_REMOTE_SPINLOCK_SFPB
+ depends on (ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_APQ8064 || ARCH_MSM8930) && MSM_IOMMU_V0
+ select MSM_IOMMU_SYNC
help
Say Y here if you want to synchronize access to IOMMU configuration
port between CPU and GPU. CPU will grab a remote spinlock before
diff --git a/drivers/iommu/msm_iommu-v0.c b/drivers/iommu/msm_iommu-v0.c
index 49bfdb8..99d071b 100644
--- a/drivers/iommu/msm_iommu-v0.c
+++ b/drivers/iommu/msm_iommu-v0.c
@@ -83,7 +83,7 @@
static struct msm_iommu_remote_lock msm_iommu_remote_lock;
-#ifdef CONFIG_MSM_IOMMU_GPU_SYNC
+#ifdef CONFIG_MSM_IOMMU_SYNC
static void _msm_iommu_remote_spin_lock_init(void)
{
msm_iommu_remote_lock.lock = smem_alloc(SMEM_SPINLOCK_ARRAY, 32);
@@ -91,8 +91,11 @@
sizeof(*msm_iommu_remote_lock.lock));
}
-void msm_iommu_remote_p0_spin_lock(void)
+void msm_iommu_remote_p0_spin_lock(unsigned int need_lock)
{
+ if (!need_lock)
+ return;
+
msm_iommu_remote_lock.lock->flag[PROC_APPS] = 1;
msm_iommu_remote_lock.lock->turn = 1;
@@ -103,8 +106,11 @@
cpu_relax();
}
-void msm_iommu_remote_p0_spin_unlock(void)
+void msm_iommu_remote_p0_spin_unlock(unsigned int need_lock)
{
+ if (!need_lock)
+ return;
+
smp_mb();
msm_iommu_remote_lock.lock->flag[PROC_APPS] = 0;
@@ -200,14 +206,16 @@
return msm_iommu_lock_initialize();
}
-static void _iommu_lock_acquire(void)
+static void _iommu_lock_acquire(unsigned int need_extra_lock)
{
- msm_iommu_lock();
+ msm_iommu_mutex_lock();
+ msm_iommu_remote_spin_lock(need_extra_lock);
}
-static void _iommu_lock_release(void)
+static void _iommu_lock_release(unsigned int need_extra_lock)
{
- msm_iommu_unlock();
+ msm_iommu_remote_spin_unlock(need_extra_lock);
+ msm_iommu_mutex_unlock();
}
struct iommu_access_ops iommu_access_ops_v0 = {
@@ -241,7 +249,7 @@
if (ret)
goto fail;
- msm_iommu_remote_spin_lock();
+ msm_iommu_remote_spin_lock(iommu_drvdata->needs_rem_spinlock);
asid = GET_CONTEXTIDR_ASID(iommu_drvdata->base,
ctx_drvdata->num);
@@ -250,7 +258,7 @@
asid | (va & TLBIVA_VA));
mb();
- msm_iommu_remote_spin_unlock();
+ msm_iommu_remote_spin_unlock(iommu_drvdata->needs_rem_spinlock);
__disable_clocks(iommu_drvdata);
}
@@ -278,7 +286,7 @@
if (ret)
goto fail;
- msm_iommu_remote_spin_lock();
+ msm_iommu_remote_spin_lock(iommu_drvdata->needs_rem_spinlock);
asid = GET_CONTEXTIDR_ASID(iommu_drvdata->base,
ctx_drvdata->num);
@@ -286,7 +294,7 @@
SET_TLBIASID(iommu_drvdata->base, ctx_drvdata->num, asid);
mb();
- msm_iommu_remote_spin_unlock();
+ msm_iommu_remote_spin_unlock(iommu_drvdata->needs_rem_spinlock);
__disable_clocks(iommu_drvdata);
}
@@ -318,13 +326,16 @@
mb();
}
-static void __program_context(void __iomem *base, void __iomem *glb_base,
+static void __program_context(struct msm_iommu_drvdata *iommu_drvdata,
int ctx, int ncb, phys_addr_t pgtable,
int redirect, int ttbr_split)
{
+ void __iomem *base = iommu_drvdata->base;
+ void __iomem *glb_base = iommu_drvdata->glb_base;
unsigned int prrr, nmrr;
int i, j, found;
- msm_iommu_remote_spin_lock();
+
+ msm_iommu_remote_spin_lock(iommu_drvdata->needs_rem_spinlock);
__reset_context(base, glb_base, ctx);
@@ -416,7 +427,7 @@
SET_M(base, ctx, 1);
mb();
- msm_iommu_remote_spin_unlock();
+ msm_iommu_remote_spin_unlock(iommu_drvdata->needs_rem_spinlock);
}
static int msm_iommu_domain_init(struct iommu_domain *domain, int flags)
@@ -526,7 +537,7 @@
if (ret)
goto unlock;
- __program_context(iommu_drvdata->base, iommu_drvdata->glb_base,
+ __program_context(iommu_drvdata,
ctx_drvdata->num, iommu_drvdata->ncb,
__pa(priv->pt.fl_table), priv->pt.redirect,
iommu_drvdata->ttbr_split);
@@ -577,7 +588,7 @@
if (ret)
goto unlock;
- msm_iommu_remote_spin_lock();
+ msm_iommu_remote_spin_lock(iommu_drvdata->needs_rem_spinlock);
SET_TLBIASID(iommu_drvdata->base, ctx_drvdata->num,
GET_CONTEXTIDR_ASID(iommu_drvdata->base, ctx_drvdata->num));
@@ -585,7 +596,7 @@
__reset_context(iommu_drvdata->base, iommu_drvdata->glb_base,
ctx_drvdata->num);
- msm_iommu_remote_spin_unlock();
+ msm_iommu_remote_spin_unlock(iommu_drvdata->needs_rem_spinlock);
__disable_clocks(iommu_drvdata);
@@ -1246,7 +1257,7 @@
if (ret)
goto fail;
- msm_iommu_remote_spin_lock();
+ msm_iommu_remote_spin_lock(iommu_drvdata->needs_rem_spinlock);
SET_V2PPR(base, ctx, va & V2Pxx_VA);
@@ -1262,7 +1273,7 @@
if (GET_FAULT(base, ctx))
ret = 0;
- msm_iommu_remote_spin_unlock();
+ msm_iommu_remote_spin_unlock(iommu_drvdata->needs_rem_spinlock);
__disable_clocks(iommu_drvdata);
fail:
@@ -1324,7 +1335,7 @@
if (ret)
goto fail;
- msm_iommu_remote_spin_lock();
+ msm_iommu_remote_spin_lock(drvdata->needs_rem_spinlock);
fsr = GET_FSR(base, num);
@@ -1357,7 +1368,7 @@
} else
ret = IRQ_NONE;
- msm_iommu_remote_spin_unlock();
+ msm_iommu_remote_spin_unlock(drvdata->needs_rem_spinlock);
__disable_clocks(drvdata);
fail:
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index b9c4cae..c81aa0ac 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -123,12 +123,12 @@
clk_disable_unprepare(drvdata->pclk);
}
-static void _iommu_lock_acquire(void)
+static void _iommu_lock_acquire(unsigned int need_extra_lock)
{
mutex_lock(&msm_iommu_lock);
}
-static void _iommu_lock_release(void)
+static void _iommu_lock_release(unsigned int need_extra_lock)
{
mutex_unlock(&msm_iommu_lock);
}
diff --git a/drivers/iommu/msm_iommu_dev-v0.c b/drivers/iommu/msm_iommu_dev-v0.c
index 2d0fba2..9382e52 100644
--- a/drivers/iommu/msm_iommu_dev-v0.c
+++ b/drivers/iommu/msm_iommu_dev-v0.c
@@ -216,6 +216,12 @@
drvdata->sec_id = -1;
drvdata->ttbr_split = 0;
+ drvdata->needs_rem_spinlock = of_property_read_bool(pdev->dev.of_node,
+ "qcom,msm-enable-remote-spinlock");
+
+ if (drvdata->needs_rem_spinlock)
+ pr_info("%s enabled remote spinlock\n", drvdata->name);
+
ret = of_platform_populate(pdev->dev.of_node,
msm_iommu_v0_ctx_match_table,
NULL, &pdev->dev);
diff --git a/drivers/iommu/msm_iommu_perfmon-v0.c b/drivers/iommu/msm_iommu_perfmon-v0.c
index 1073623..b08a9ec 100644
--- a/drivers/iommu/msm_iommu_perfmon-v0.c
+++ b/drivers/iommu/msm_iommu_perfmon-v0.c
@@ -176,9 +176,9 @@
goto out;
}
- iommu->ops->iommu_lock_acquire();
+ iommu->ops->iommu_lock_acquire(1);
iommu_pm_check_for_overflow(pmon);
- iommu->ops->iommu_lock_release();
+ iommu->ops->iommu_lock_release(1);
mutex_unlock(&pmon->lock);
diff --git a/drivers/iommu/msm_iommu_perfmon-v1.c b/drivers/iommu/msm_iommu_perfmon-v1.c
index 7d6dd34..2b55184 100644
--- a/drivers/iommu/msm_iommu_perfmon-v1.c
+++ b/drivers/iommu/msm_iommu_perfmon-v1.c
@@ -151,9 +151,9 @@
goto out;
}
- iommu->ops->iommu_lock_acquire();
+ iommu->ops->iommu_lock_acquire(0);
iommu_pm_check_for_overflow(pmon);
- iommu->ops->iommu_lock_release();
+ iommu->ops->iommu_lock_release(0);
mutex_unlock(&pmon->lock);
diff --git a/drivers/iommu/msm_iommu_perfmon.c b/drivers/iommu/msm_iommu_perfmon.c
index 958c6ca..503d4ab 100644
--- a/drivers/iommu/msm_iommu_perfmon.c
+++ b/drivers/iommu/msm_iommu_perfmon.c
@@ -188,11 +188,11 @@
if (event_class == MSM_IOMMU_PMU_NO_EVENT_CLASS) {
if (iommu->hw_ops->is_hw_access_OK(pmon)) {
- iommu->ops->iommu_lock_acquire();
+ iommu->ops->iommu_lock_acquire(1);
iommu->hw_ops->counter_disable(iommu, counter);
iommu->hw_ops->ovfl_int_disable(iommu, counter);
iommu->hw_ops->set_event_class(pmon, count_no, 0);
- iommu->ops->iommu_lock_release();
+ iommu->ops->iommu_lock_release(1);
}
counter->overflow_count = 0;
counter->value = 0;
@@ -200,12 +200,12 @@
counter->overflow_count = 0;
counter->value = 0;
if (iommu->hw_ops->is_hw_access_OK(pmon)) {
- iommu->ops->iommu_lock_acquire();
+ iommu->ops->iommu_lock_acquire(1);
iommu->hw_ops->set_event_class(pmon, count_no,
event_class);
iommu->hw_ops->ovfl_int_enable(iommu, counter);
iommu->hw_ops->counter_enable(iommu, counter);
- iommu->ops->iommu_lock_release();
+ iommu->ops->iommu_lock_release(1);
}
}
}
@@ -261,9 +261,9 @@
iommu->ops->iommu_clk_on(iommu_drvdata);
/* Reset counters in HW */
- iommu->ops->iommu_lock_acquire();
+ iommu->ops->iommu_lock_acquire(1);
iommu->hw_ops->reset_counters(&pmon->iommu);
- iommu->ops->iommu_lock_release();
+ iommu->ops->iommu_lock_release(1);
/* Reset SW counters */
iommu_pm_reset_counts(pmon);
@@ -272,7 +272,7 @@
iommu_pm_set_all_counters(pmon);
- iommu->ops->iommu_lock_acquire();
+ iommu->ops->iommu_lock_acquire(1);
/* enable all counter group */
for (i = 0; i < pmon->num_groups; ++i)
@@ -280,7 +280,7 @@
/* enable global counters */
iommu->hw_ops->enable_pm(iommu);
- iommu->ops->iommu_lock_release();
+ iommu->ops->iommu_lock_release(1);
pr_info("%s: TLB performance monitoring turned ON\n",
pmon->iommu.iommu_name);
@@ -295,7 +295,7 @@
pmon->enabled = 0;
- iommu->ops->iommu_lock_acquire();
+ iommu->ops->iommu_lock_acquire(1);
/* disable global counters */
iommu->hw_ops->disable_pm(iommu);
@@ -310,7 +310,7 @@
/* Update cached copy of counters before turning off power */
iommu_pm_read_all_counters(pmon);
- iommu->ops->iommu_lock_release();
+ iommu->ops->iommu_lock_release(1);
iommu->ops->iommu_clk_off(iommu_drvdata);
iommu->ops->iommu_bus_vote(iommu_drvdata, 0);
iommu->ops->iommu_power_off(iommu_drvdata);
@@ -341,9 +341,9 @@
mutex_lock(&pmon->lock);
if (iommu->hw_ops->is_hw_access_OK(pmon)) {
- iommu->ops->iommu_lock_acquire();
+ iommu->ops->iommu_lock_acquire(1);
counter->value = iommu->hw_ops->read_counter(counter);
- iommu->ops->iommu_lock_release();
+ iommu->ops->iommu_lock_release(1);
}
full_count = (unsigned long long) counter->value +
((unsigned long long)counter->overflow_count *
@@ -448,9 +448,9 @@
rv = kstrtoul(buf, 10, &cmd);
if (!rv && (cmd == 1)) {
if (iommu->hw_ops->is_hw_access_OK(pmon)) {
- iommu->ops->iommu_lock_acquire();
+ iommu->ops->iommu_lock_acquire(1);
iommu->hw_ops->reset_counters(&pmon->iommu);
- iommu->ops->iommu_lock_release();
+ iommu->ops->iommu_lock_release(1);
}
iommu_pm_reset_counts(pmon);
pr_info("TLB performance counters reset\n");
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index 474efdf..5a1806e 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -194,7 +194,7 @@
struct msm_scm_fault_regs_dump *regs;
int tmp, ret = IRQ_HANDLED;
- iommu_access_ops->iommu_lock_acquire();
+ iommu_access_ops->iommu_lock_acquire(0);
BUG_ON(!pdev);
@@ -266,7 +266,7 @@
free_regs:
kfree(regs);
lock_release:
- iommu_access_ops->iommu_lock_release();
+ iommu_access_ops->iommu_lock_release(0);
return ret;
}
@@ -510,12 +510,12 @@
{
struct msm_iommu_priv *priv;
- iommu_access_ops->iommu_lock_acquire();
+ iommu_access_ops->iommu_lock_acquire(0);
priv = domain->priv;
domain->priv = NULL;
kfree(priv);
- iommu_access_ops->iommu_lock_release();
+ iommu_access_ops->iommu_lock_release(0);
}
static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
@@ -526,7 +526,7 @@
struct msm_iommu_ctx_drvdata *tmp_drvdata;
int ret = 0;
- iommu_access_ops->iommu_lock_acquire();
+ iommu_access_ops->iommu_lock_acquire(0);
priv = domain->priv;
if (!priv || !dev) {
@@ -581,12 +581,12 @@
ctx_drvdata->attached_domain = domain;
++iommu_drvdata->ctx_attach_count;
- iommu_access_ops->iommu_lock_release();
+ iommu_access_ops->iommu_lock_release(0);
msm_iommu_attached(dev->parent);
return ret;
fail:
- iommu_access_ops->iommu_lock_release();
+ iommu_access_ops->iommu_lock_release(0);
return ret;
}
@@ -598,7 +598,7 @@
msm_iommu_detached(dev->parent);
- iommu_access_ops->iommu_lock_acquire();
+ iommu_access_ops->iommu_lock_acquire(0);
if (!dev)
goto fail;
@@ -614,7 +614,7 @@
BUG_ON(iommu_drvdata->ctx_attach_count == 0);
--iommu_drvdata->ctx_attach_count;
fail:
- iommu_access_ops->iommu_lock_release();
+ iommu_access_ops->iommu_lock_release(0);
}
static int get_drvdata(struct iommu_domain *domain,
@@ -644,7 +644,7 @@
struct msm_iommu_ctx_drvdata *ctx_drvdata;
int ret = 0;
- iommu_access_ops->iommu_lock_acquire();
+ iommu_access_ops->iommu_lock_acquire(0);
ret = get_drvdata(domain, &iommu_drvdata, &ctx_drvdata);
if (ret)
@@ -655,7 +655,7 @@
va, pa, len);
iommu_access_ops->iommu_clk_off(iommu_drvdata);
fail:
- iommu_access_ops->iommu_lock_release();
+ iommu_access_ops->iommu_lock_release(0);
return ret;
}
@@ -666,7 +666,7 @@
struct msm_iommu_ctx_drvdata *ctx_drvdata;
int ret = -ENODEV;
- iommu_access_ops->iommu_lock_acquire();
+ iommu_access_ops->iommu_lock_acquire(0);
ret = get_drvdata(domain, &iommu_drvdata, &ctx_drvdata);
if (ret)
@@ -677,7 +677,7 @@
va, len);
iommu_access_ops->iommu_clk_off(iommu_drvdata);
fail:
- iommu_access_ops->iommu_lock_release();
+ iommu_access_ops->iommu_lock_release(0);
/* the IOMMU API requires us to return how many bytes were unmapped */
len = ret ? 0 : len;
@@ -692,7 +692,7 @@
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
- iommu_access_ops->iommu_lock_acquire();
+ iommu_access_ops->iommu_lock_acquire(0);
ret = get_drvdata(domain, &iommu_drvdata, &ctx_drvdata);
if (ret)
@@ -702,7 +702,7 @@
va, sg, len);
iommu_access_ops->iommu_clk_off(iommu_drvdata);
fail:
- iommu_access_ops->iommu_lock_release();
+ iommu_access_ops->iommu_lock_release(0);
return ret;
}
@@ -714,7 +714,7 @@
struct msm_iommu_ctx_drvdata *ctx_drvdata;
int ret;
- iommu_access_ops->iommu_lock_acquire();
+ iommu_access_ops->iommu_lock_acquire(0);
ret = get_drvdata(domain, &iommu_drvdata, &ctx_drvdata);
if (ret)
@@ -725,7 +725,7 @@
iommu_access_ops->iommu_clk_off(iommu_drvdata);
fail:
- iommu_access_ops->iommu_lock_release();
+ iommu_access_ops->iommu_lock_release(0);
return 0;
}
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index bf59d03..cf6c6e2 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -25,6 +25,7 @@
#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
#define WLED_MOD_EN_REG(base, n) (base + 0x60 + n*0x10)
#define WLED_IDAC_DLY_REG(base, n) (WLED_MOD_EN_REG(base, n) + 0x01)
@@ -103,6 +104,7 @@
#define FLASH_LED_TORCH(base) (base + 0xE4)
#define FLASH_FAULT_DETECT(base) (base + 0x51)
#define FLASH_PERIPHERAL_SUBTYPE(base) (base + 0x05)
+#define FLASH_CURRENT_RAMP(base) (base + 0x54)
#define FLASH_MAX_LEVEL 0x4F
#define TORCH_MAX_LEVEL 0x0F
@@ -121,6 +123,7 @@
#define FLASH_HW_VREG_OK 0x40
#define FLASH_VREG_MASK 0xC0
#define FLASH_STARTUP_DLY_MASK 0x02
+#define FLASH_CURRENT_RAMP_MASK 0xBF
#define FLASH_ENABLE_ALL 0xE0
#define FLASH_ENABLE_MODULE 0x80
@@ -131,6 +134,7 @@
#define FLASH_ENABLE_LED_1 0xA0
#define FLASH_INIT_MASK 0xE0
#define FLASH_SELFCHECK_ENABLE 0x80
+#define FLASH_RAMP_STEP_27US 0xBF
#define FLASH_STROBE_SW 0xC0
#define FLASH_STROBE_HW 0x04
@@ -155,6 +159,9 @@
#define FLASH_SUBTYPE_DUAL 0x01
#define FLASH_SUBTYPE_SINGLE 0x02
+#define FLASH_RAMP_UP_DELAY_US 1000
+#define FLASH_RAMP_DN_DELAY_US 2160
+
#define LED_TRIGGER_DEFAULT "none"
#define RGB_LED_SRC_SEL(base) (base + 0x45)
@@ -932,22 +939,6 @@
rc);
goto error_flash_set;
}
-
- /*
- * Write 0x80 to MODULE_ENABLE before writing
- * 0xE0 in order to avoid a hardware bug caused
- * by register value going from 0x00 to 0xE0.
- */
- rc = qpnp_led_masked_write(led,
- FLASH_ENABLE_CONTROL(led->base),
- FLASH_ENABLE_MODULE_MASK,
- FLASH_ENABLE_MODULE);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Enable reg write failed(%d)\n",
- rc);
- return rc;
- }
}
rc = qpnp_led_masked_write(led,
@@ -1064,22 +1055,6 @@
goto error_flash_set;
}
- /*
- * Write 0x80 to MODULE_ENABLE before writing
- * 0xE0 in order to avoid a hardware bug caused
- * by register value going from 0x00 to 0xE0.
- */
- rc = qpnp_led_masked_write(led,
- FLASH_ENABLE_CONTROL(led->base),
- FLASH_ENABLE_MODULE_MASK,
- FLASH_ENABLE_MODULE);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Enable reg write failed(%d)\n",
- rc);
- goto error_flash_set;
- }
-
rc = qpnp_led_masked_write(led,
led->flash_cfg->current_addr,
FLASH_CURRENT_MASK,
@@ -1100,6 +1075,11 @@
goto error_flash_set;
}
+ /*
+ * Add 1ms delay for bharger enter stable state
+ */
+ usleep(FLASH_RAMP_UP_DELAY_US);
+
if (!led->flash_cfg->strobe_type) {
rc = qpnp_led_masked_write(led,
FLASH_LED_STROBE_CTRL(led->base),
@@ -1180,6 +1160,12 @@
}
}
} else {
+ /*
+ * Disable module after ramp down complete for stable
+ * behavior
+ */
+ usleep(FLASH_RAMP_DN_DELAY_US);
+
rc = qpnp_led_masked_write(led,
FLASH_ENABLE_CONTROL(led->base),
led->flash_cfg->enable_module &
@@ -2260,7 +2246,7 @@
/* Disable flash LED module */
rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
- FLASH_ENABLE_MODULE_MASK, FLASH_DISABLE_ALL);
+ FLASH_ENABLE_MASK, FLASH_DISABLE_ALL);
if (rc) {
dev_err(&led->spmi_dev->dev,
"Enable reg write failed(%d)\n", rc);
@@ -2329,6 +2315,15 @@
return rc;
}
+ /* Set current ramp */
+ rc = qpnp_led_masked_write(led, FLASH_CURRENT_RAMP(led->base),
+ FLASH_CURRENT_RAMP_MASK, FLASH_RAMP_STEP_27US);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Current ramp reg write failed(%d)\n", rc);
+ return rc;
+ }
+
led->flash_cfg->strobe_type = 0;
/* dump flash registers */
diff --git a/drivers/media/platform/msm/camera_v2/Kconfig b/drivers/media/platform/msm/camera_v2/Kconfig
index bc7d135..262fb38 100644
--- a/drivers/media/platform/msm/camera_v2/Kconfig
+++ b/drivers/media/platform/msm/camera_v2/Kconfig
@@ -119,6 +119,15 @@
snapshot config = 4208 x 3120 at 24 fps,
Video HDR support.
+config IMX134
+ bool "Sensor IMX134 (BAYER 8M)"
+ depends on MSMB_CAMERA
+ ---help---
+ Sony 8 MP Bayer Sensor with auto focus, uses
+ 4 mipi lanes full resolution @30fps and
+ HFR @60fps and @120fps
+ Video HDR support.
+
config OV2720
bool "Sensor OV2720 (BAYER 2M)"
depends on MSMB_CAMERA
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index 4aa423f..87bffde 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -19,6 +19,7 @@
#include <linux/io.h>
#include <linux/list.h>
#include <linux/delay.h>
+#include <linux/avtimer.h>
#include <media/v4l2-subdev.h>
#include <media/msmb_isp.h>
#include <mach/msm_bus.h>
@@ -35,6 +36,10 @@
#define MAX_INIT_FRAME_DROP 31
#define ISP_Q2 (1 << 2)
+#define AVTIMER_MSW_PHY_ADDR 0xFE05300C
+#define AVTIMER_LSW_PHY_ADDR 0xFE053008
+#define AVTIMER_ITERATION_CTR 16
+
#define VFE_PING_FLAG 0xFFFFFFFF
#define VFE_PONG_FLAG 0x0
@@ -69,6 +74,8 @@
struct msm_isp_timestamp {
/*Monotonic clock for v4l2 buffer*/
struct timeval buf_time;
+ /*Monotonic clock for VT */
+ struct timeval vt_time;
/*Wall clock for userspace event*/
struct timeval event_time;
};
@@ -263,7 +270,7 @@
uint32_t stream_handle;
uint8_t buf_divert;
enum msm_vfe_axi_stream_type stream_type;
-
+ uint32_t vt_enable;
uint32_t frame_based;
uint32_t framedrop_period;
uint32_t framedrop_pattern;
@@ -436,6 +443,9 @@
int dump_reg;
int vfe_clk_idx;
uint32_t vfe_open_cnt;
+ uint8_t vt_enable;
+ void __iomem *p_avtimer_msw;
+ void __iomem *p_avtimer_lsw;
};
#endif
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 a6972e4..a8da26d 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -24,7 +24,8 @@
#define VFE32_BURST_LEN 2
#define VFE32_UB_SIZE 1024
-#define VFE32_EQUAL_SLICE_UB 198
+#define VFE32_EQUAL_SLICE_UB 194
+#define VFE32_AXI_SLICE_UB 792
#define VFE32_WM_BASE(idx) (0x4C + 0x18 * idx)
#define VFE32_RDI_BASE(idx) (idx ? 0x734 + 0x4 * (idx - 1) : 0x06FC)
#define VFE32_XBAR_BASE(idx) (0x40 + 0x4 * (idx / 4))
@@ -319,6 +320,7 @@
uint32_t irq_status0, uint32_t irq_status1,
struct msm_isp_timestamp *ts)
{
+ uint32_t rdi_status;
if (!(irq_status0 & 0x20) && !(irq_status1 & 0x1C000000))
return;
@@ -331,6 +333,18 @@
if (irq_status1 & BIT(28))
msm_isp_sof_notify(vfe_dev, VFE_RAW_2, ts);
+ if (vfe_dev->axi_data.stream_update) {
+ rdi_status = msm_camera_io_r(vfe_dev->vfe_base +
+ VFE32_XBAR_BASE(0));
+ rdi_status |= msm_camera_io_r(vfe_dev->vfe_base +
+ VFE32_XBAR_BASE(4));
+
+ if (((rdi_status & BIT(7)) || (rdi_status & BIT(7)) ||
+ (rdi_status & BIT(7)) || (rdi_status & BIT(7))) &&
+ (!(irq_status0 & 0x20)))
+ return;
+ }
+
if (vfe_dev->axi_data.stream_update)
msm_isp_axi_stream_update(vfe_dev);
if (atomic_read(&vfe_dev->stats_data.stats_update))
@@ -759,11 +773,21 @@
{
int i;
uint32_t ub_offset = 0;
+ uint32_t final_ub_slice_size;
struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
for (i = 0; i < axi_data->hw_info->num_wm; i++) {
- msm_camera_io_w(ub_offset << 16 | (VFE32_EQUAL_SLICE_UB - 1),
- vfe_dev->vfe_base + VFE32_WM_BASE(i) + 0xC);
- ub_offset += VFE32_EQUAL_SLICE_UB;
+ if (ub_offset + VFE32_EQUAL_SLICE_UB > VFE32_AXI_SLICE_UB) {
+ final_ub_slice_size = VFE32_AXI_SLICE_UB - ub_offset;
+ msm_camera_io_w(ub_offset << 16 |
+ (final_ub_slice_size - 1), vfe_dev->vfe_base +
+ VFE32_WM_BASE(i) + 0xC);
+ ub_offset += final_ub_slice_size;
+ } else {
+ msm_camera_io_w(ub_offset << 16 |
+ (VFE32_EQUAL_SLICE_UB - 1), vfe_dev->vfe_base +
+ VFE32_WM_BASE(i) + 0xC);
+ ub_offset += VFE32_EQUAL_SLICE_UB;
+ }
}
}
@@ -1023,7 +1047,7 @@
}
struct msm_vfe_axi_hardware_info msm_vfe32_axi_hw_info = {
- .num_wm = 4,
+ .num_wm = 5,
.num_comp_mask = 3,
.num_rdi = 3,
.num_rdi_master = 3,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index f547b0e..4f3094a 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -524,7 +524,16 @@
}
msm_isp_calculate_framedrop(&vfe_dev->axi_data, stream_cfg_cmd);
-
+ stream_info->vt_enable = stream_cfg_cmd->vt_enable;
+ if (stream_info->vt_enable) {
+ vfe_dev->vt_enable = stream_info->vt_enable;
+ #ifdef CONFIG_MSM_AVTIMER
+ avcs_core_open();
+ avcs_core_disable_power_collapse(1);
+ #endif
+ vfe_dev->p_avtimer_lsw = ioremap(AVTIMER_LSW_PHY_ADDR, 4);
+ vfe_dev->p_avtimer_msw = ioremap(AVTIMER_MSW_PHY_ADDR, 4);
+ }
if (stream_info->num_planes > 1) {
msm_isp_axi_reserve_comp_mask(
&vfe_dev->axi_data, stream_info);
@@ -783,15 +792,21 @@
{
int rc;
struct msm_isp_event_data buf_event;
+ struct timeval *time_stamp;
uint32_t stream_idx = HANDLE_TO_IDX(stream_info->stream_handle);
uint32_t frame_id = vfe_dev->axi_data.
src_info[SRC_TO_INTF(stream_info->stream_src)].frame_id;
if (buf && ts) {
+ if (vfe_dev->vt_enable) {
+ time_stamp = &ts->vt_time;
+ } else {
+ time_stamp = &ts->buf_time;
+ }
if (stream_info->buf_divert) {
rc = vfe_dev->buf_mgr->ops->buf_divert(vfe_dev->buf_mgr,
buf->bufq_handle, buf->buf_idx,
- &ts->buf_time, frame_id);
+ time_stamp, frame_id);
/* Buf divert return value represent whether the buf
* can be diverted. A positive return value means
* other ISP hardware is still processing the frame.
@@ -800,7 +815,7 @@
buf_event.input_intf =
SRC_TO_INTF(stream_info->stream_src);
buf_event.frame_id = frame_id;
- buf_event.timestamp = ts->buf_time;
+ buf_event.timestamp = *time_stamp;
buf_event.u.buf_done.session_id =
stream_info->session_id;
buf_event.u.buf_done.stream_id =
@@ -817,7 +832,7 @@
} else {
vfe_dev->buf_mgr->ops->buf_done(vfe_dev->buf_mgr,
buf->bufq_handle, buf->buf_idx,
- &ts->buf_time, frame_id,
+ time_stamp, frame_id,
stream_info->runtime_output_format);
}
}
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 b024569..5f36a4a 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
@@ -193,6 +193,32 @@
do_gettimeofday(&(time_stamp->event_time));
}
+static inline void msm_isp_get_vt_tstamp(struct vfe_device *vfe_dev,
+ struct msm_isp_timestamp *time_stamp)
+{
+ uint32_t avtimer_msw_1st = 0, avtimer_lsw = 0;
+ uint32_t avtimer_msw_2nd = 0;
+ uint8_t iter = 0;
+ if (!vfe_dev->p_avtimer_msw || !vfe_dev->p_avtimer_lsw) {
+ pr_err("%s: ioremap failed\n", __func__);
+ return;
+ }
+ do {
+ avtimer_msw_1st = msm_camera_io_r(vfe_dev->p_avtimer_msw);
+ avtimer_lsw = msm_camera_io_r(vfe_dev->p_avtimer_lsw);
+ avtimer_msw_2nd = msm_camera_io_r(vfe_dev->p_avtimer_msw);
+ } while ((avtimer_msw_1st != avtimer_msw_2nd)
+ && (iter++ < AVTIMER_ITERATION_CTR));
+ /*Just return if the MSW TimeStamps don't converge after
+ a few iterations Application needs to handle the zero TS values*/
+ if (iter >= AVTIMER_ITERATION_CTR) {
+ pr_err("%s: AVTimer MSW TS did not converge !!!\n", __func__);
+ return;
+ }
+ time_stamp->vt_time.tv_sec = avtimer_msw_1st;
+ time_stamp->vt_time.tv_usec = avtimer_lsw;
+}
+
int msm_isp_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
struct v4l2_event_subscription *sub)
{
@@ -885,6 +911,8 @@
queue_cmd->vfeInterruptStatus0 = irq_status0;
queue_cmd->vfeInterruptStatus1 = irq_status1;
msm_isp_get_timestamp(&queue_cmd->ts);
+ if (vfe_dev->vt_enable)
+ msm_isp_get_vt_tstamp(vfe_dev, &queue_cmd->ts);
queue_cmd->cmd_used = 1;
vfe_dev->taskletq_idx =
(vfe_dev->taskletq_idx + 1) % MSM_VFE_TASKLETQ_SIZE;
@@ -998,6 +1026,9 @@
vfe_dev->axi_data.hw_info = vfe_dev->hw_info->axi_hw_info;
vfe_dev->vfe_open_cnt++;
vfe_dev->taskletq_idx = 0;
+ vfe_dev->vt_enable = 0;
+ vfe_dev->p_avtimer_lsw = NULL;
+ vfe_dev->p_avtimer_msw = NULL;
mutex_unlock(&vfe_dev->core_mutex);
mutex_unlock(&vfe_dev->realtime_mutex);
return 0;
@@ -1024,6 +1055,14 @@
vfe_dev->buf_mgr->ops->buf_mgr_deinit(vfe_dev->buf_mgr);
vfe_dev->hw_info->vfe_ops.core_ops.release_hw(vfe_dev);
vfe_dev->vfe_open_cnt--;
+ if (vfe_dev->vt_enable) {
+ iounmap(vfe_dev->p_avtimer_lsw);
+ iounmap(vfe_dev->p_avtimer_msw);
+ #ifdef CONFIG_MSM_AVTIMER
+ avcs_core_disable_power_collapse(0);
+ #endif
+ vfe_dev->vt_enable = 0;
+ }
mutex_unlock(&vfe_dev->core_mutex);
mutex_unlock(&vfe_dev->realtime_mutex);
return 0;
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index 2b963a4..89016ec 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -72,6 +72,18 @@
{"csi0_clk", NO_SET_RATE},
{"csi0_pix_clk", NO_SET_RATE},
{"csi0_rdi_clk", NO_SET_RATE},
+ {"csi1_src_clk", INIT_RATE},
+ {"csi1_clk", NO_SET_RATE},
+ {"csi1_pix_clk", NO_SET_RATE},
+ {"csi1_rdi_clk", NO_SET_RATE},
+ {"csi2_src_clk", INIT_RATE},
+ {"csi2_clk", NO_SET_RATE},
+ {"csi2_pix_clk", NO_SET_RATE},
+ {"csi2_rdi_clk", NO_SET_RATE},
+ {"csi3_src_clk", INIT_RATE},
+ {"csi3_clk", NO_SET_RATE},
+ {"csi3_pix_clk", NO_SET_RATE},
+ {"csi3_rdi_clk", NO_SET_RATE},
{"vfe0_clk_src", INIT_RATE},
{"camss_vfe_vfe0_clk", NO_SET_RATE},
{"camss_csi_vfe0_clk", NO_SET_RATE},
@@ -110,6 +122,9 @@
CDBG("%s: VFE0 done\n", __func__);
if (timeout <= 0) {
pr_err("%s: VFE0 reset wait timeout\n", __func__);
+ msm_cam_clk_enable(&ispif->pdev->dev,
+ ispif_8974_reset_clk_info, reset_clk,
+ ARRAY_SIZE(ispif_8974_reset_clk_info), 0);
return -ETIMEDOUT;
}
@@ -120,6 +135,9 @@
CDBG("%s: VFE1 done\n", __func__);
if (timeout <= 0) {
pr_err("%s: VFE1 reset wait timeout\n", __func__);
+ msm_cam_clk_enable(&ispif->pdev->dev,
+ ispif_8974_reset_clk_info, reset_clk,
+ ARRAY_SIZE(ispif_8974_reset_clk_info), 0);
return -ETIMEDOUT;
}
}
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index 1fd1065..efa3ad0 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -680,9 +680,14 @@
}
/* should wait on session based condition */
- rc = wait_event_interruptible_timeout(cmd_ack->wait,
- !list_empty_careful(&cmd_ack->command_q.list),
- msecs_to_jiffies(timeout));
+ do {
+ rc = wait_event_interruptible_timeout(cmd_ack->wait,
+ !list_empty_careful(&cmd_ack->command_q.list),
+ msecs_to_jiffies(timeout));
+ if (rc != -ERESTARTSYS)
+ break;
+ } while (1);
+
if (list_empty_careful(&cmd_ack->command_q.list)) {
if (!rc) {
pr_err("%s: Timed out\n", __func__);
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 c1f48f5..8b8d23b 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
@@ -27,6 +27,7 @@
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/workqueue.h>
+#include <mach/clk.h>
#include <mach/iommu_domains.h>
#include <mach/iommu.h>
#include <mach/vreg.h>
@@ -48,6 +49,7 @@
#define CONFIG_MSM_CPP_DBG 0
#define CPP_CMD_TIMEOUT_MS 300
+#define MSM_MICRO_IFACE_CLK_IDX 7
struct msm_cpp_timer_data_t {
struct cpp_device *cpp_dev;
@@ -646,6 +648,38 @@
}
}
+ cpp_dev->cpp_clk[MSM_MICRO_IFACE_CLK_IDX] =
+ clk_get(&cpp_dev->pdev->dev,
+ cpp_clk_info[MSM_MICRO_IFACE_CLK_IDX].clk_name);
+ if (IS_ERR(cpp_dev->cpp_clk[MSM_MICRO_IFACE_CLK_IDX])) {
+ pr_err("%s get failed\n",
+ cpp_clk_info[MSM_MICRO_IFACE_CLK_IDX].clk_name);
+ rc = PTR_ERR(cpp_dev->cpp_clk[MSM_MICRO_IFACE_CLK_IDX]);
+ goto remap_failed;
+ }
+
+ rc = clk_reset(cpp_dev->cpp_clk[MSM_MICRO_IFACE_CLK_IDX],
+ CLK_RESET_ASSERT);
+ if (rc) {
+ pr_err("%s:micro_iface_clk assert failed\n", __func__);
+ clk_put(cpp_dev->cpp_clk[MSM_MICRO_IFACE_CLK_IDX]);
+ goto remap_failed;
+ }
+
+ usleep_range(10000, 12000);
+
+ rc = clk_reset(cpp_dev->cpp_clk[MSM_MICRO_IFACE_CLK_IDX],
+ CLK_RESET_DEASSERT);
+ if (rc) {
+ pr_err("%s:micro_iface_clk assert failed\n", __func__);
+ clk_put(cpp_dev->cpp_clk[MSM_MICRO_IFACE_CLK_IDX]);
+ goto remap_failed;
+ }
+
+ usleep_range(1000, 1200);
+
+ clk_put(cpp_dev->cpp_clk[MSM_MICRO_IFACE_CLK_IDX]);
+
rc = msm_cam_clk_enable(&cpp_dev->pdev->dev, cpp_clk_info,
cpp_dev->cpp_clk, ARRAY_SIZE(cpp_clk_info), 1);
if (rc < 0) {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/Makefile b/drivers/media/platform/msm/camera_v2/sensor/Makefile
index bbfbbdf..280a9a0 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/Makefile
+++ b/drivers/media/platform/msm/camera_v2/sensor/Makefile
@@ -7,7 +7,9 @@
obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
obj-$(CONFIG_S5K3L1YX) += s5k3l1yx.o
obj-$(CONFIG_IMX135) += imx135.o
+obj-$(CONFIG_IMX134) += imx134.o
obj-$(CONFIG_OV8825) += ov8825.o
+obj-$(CONFIG_OV8865) += ov8865.o
obj-$(CONFIG_s5k4e1) += s5k4e1.o
obj-$(CONFIG_OV12830) += ov12830.o
obj-$(CONFIG_OV2720) += ov2720.o
@@ -17,4 +19,3 @@
obj-$(CONFIG_MT9M114) += mt9m114.o
obj-$(CONFIG_SP1628) += sp1628.o
obj-$(CONFIG_GC0339) += gc0339.o
-obj-$(CONFIG_OV8865) += ov8865.o
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index 16a1616..bb2b074 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -79,6 +79,11 @@
struct msm_camera_i2c_reg_array *i2c_tbl = a_ctrl->i2c_reg_tbl;
CDBG("Enter\n");
for (i = 0; i < size; i++) {
+ /* check that the index into i2c_tbl cannot grow larger that
+ the allocated size of i2c_tbl */
+ if ((a_ctrl->total_steps + 1) < (a_ctrl->i2c_tbl_index)) {
+ break;
+ }
if (write_arr[i].reg_write_type == MSM_ACTUATOR_WRITE_DAC) {
value = (next_lens_position <<
write_arr[i].data_shift) |
@@ -196,11 +201,19 @@
struct msm_actuator_move_params_t *move_params)
{
int32_t dest_step_position = move_params->dest_step_pos;
+ struct damping_params_t ringing_params_kernel;
int32_t rc = 0;
int32_t num_steps = move_params->num_steps;
struct msm_camera_i2c_reg_setting reg_setting;
CDBG("Enter\n");
+ if (copy_from_user(&ringing_params_kernel,
+ &(move_params->ringing_params[0]),
+ sizeof(struct damping_params_t))) {
+ pr_err("copy_from_user failed\n");
+ return -EFAULT;
+ }
+
if (num_steps == 0)
return rc;
@@ -208,7 +221,7 @@
a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl,
(num_steps *
a_ctrl->region_params[0].code_per_step),
- move_params->ringing_params[0].hw_params, 0);
+ ringing_params_kernel.hw_params, 0);
reg_setting.reg_setting = a_ctrl->i2c_reg_tbl;
reg_setting.data_type = a_ctrl->i2c_data_type;
@@ -230,6 +243,7 @@
struct msm_actuator_move_params_t *move_params)
{
int32_t rc = 0;
+ struct damping_params_t ringing_params_kernel;
int8_t sign_dir = move_params->sign_dir;
uint16_t step_boundary = 0;
uint16_t target_step_pos = 0;
@@ -240,6 +254,14 @@
int32_t num_steps = move_params->num_steps;
struct msm_camera_i2c_reg_setting reg_setting;
+ if (copy_from_user(&ringing_params_kernel,
+ &(move_params->ringing_params[a_ctrl->curr_region_index]),
+ sizeof(struct damping_params_t))) {
+ pr_err("copy_from_user failed\n");
+ return -EFAULT;
+ }
+
+
CDBG("called, dir %d, num_steps %d\n", dir, num_steps);
if (dest_step_pos == a_ctrl->curr_step_pos)
@@ -262,9 +284,7 @@
a_ctrl->step_position_table[target_step_pos];
a_ctrl->func_tbl->actuator_write_focus(a_ctrl,
curr_lens_pos,
- &(move_params->
- ringing_params[a_ctrl->
- curr_region_index]),
+ &ringing_params_kernel,
sign_dir,
target_lens_pos);
curr_lens_pos = target_lens_pos;
@@ -275,8 +295,7 @@
a_ctrl->step_position_table[target_step_pos];
a_ctrl->func_tbl->actuator_write_focus(a_ctrl,
curr_lens_pos,
- &(move_params->ringing_params[a_ctrl->
- curr_region_index]),
+ &ringing_params_kernel,
sign_dir,
target_lens_pos);
curr_lens_pos = target_lens_pos;
@@ -437,8 +456,11 @@
a_ctrl->i2c_data_type = set_info->actuator_params.i2c_data_type;
a_ctrl->i2c_client.addr_type = set_info->actuator_params.i2c_addr_type;
- a_ctrl->reg_tbl_size = set_info->actuator_params.reg_tbl_size;
- if (a_ctrl->reg_tbl_size > MAX_ACTUATOR_REG_TBL_SIZE) {
+ if (set_info->actuator_params.reg_tbl_size <=
+ MAX_ACTUATOR_REG_TBL_SIZE) {
+ a_ctrl->reg_tbl_size = set_info->actuator_params.reg_tbl_size;
+ } else {
+ a_ctrl->reg_tbl_size = 0;
pr_err("MAX_ACTUATOR_REG_TBL_SIZE is exceeded.\n");
return -EFAULT;
}
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 968dcd7..aacc07b 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
@@ -95,7 +95,7 @@
static void msm_cci_flush_queue(struct cci_device *cci_dev,
enum cci_i2c_master_t master)
{
- uint32_t rc = 0;
+ int32_t rc = 0;
msm_camera_io_w(1 << master, cci_dev->base + CCI_HALT_REQ_ADDR);
rc = wait_for_completion_interruptible_timeout(
@@ -645,7 +645,7 @@
static int32_t msm_cci_init(struct v4l2_subdev *sd,
struct msm_camera_cci_ctrl *c_ctrl)
{
- int rc = 0;
+ int32_t rc = 0;
struct cci_device *cci_dev;
enum cci_i2c_master_t master;
cci_dev = v4l2_get_subdevdata(sd);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
index 7f13568..45db19c 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
@@ -48,10 +48,12 @@
e_ctrl->num_bytes;
break;
case CFG_EEPROM_READ_CAL_DATA:
- CDBG("%s E CFG_EEPROM_READ_CAL_DATA\n", __func__);
- rc = copy_to_user(cdata->cfg.read_data.dbuffer,
+ if (cdata->cfg.read_data.num_bytes <= e_ctrl->num_bytes) {
+ CDBG("%s E CFG_EEPROM_READ_CAL_DATA\n", __func__);
+ rc = copy_to_user(cdata->cfg.read_data.dbuffer,
e_ctrl->memory_data,
cdata->cfg.read_data.num_bytes);
+ }
break;
default:
break;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
index 20905c9..01d2c13 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_led_trigger.c
@@ -29,6 +29,7 @@
extern int32_t msm_led_torch_create_classdev(
struct platform_device *pdev, void *data);
+static enum flash_type flashtype;
static struct msm_led_flash_ctrl_t fctrl;
static int32_t msm_led_trigger_get_subdev_id(struct msm_led_flash_ctrl_t *fctrl,
@@ -119,6 +120,7 @@
struct device_node *of_node = pdev->dev.of_node;
struct device_node *flash_src_node = NULL;
uint32_t count = 0;
+ struct led_trigger *temp = NULL;
CDBG("called\n");
@@ -137,11 +139,18 @@
}
CDBG("pdev id %d\n", pdev->id);
+ rc = of_property_read_u32(of_node,
+ "qcom,flash-type", &flashtype);
+ if (rc < 0) {
+ pr_err("flash-type: read failed\n");
+ return -EINVAL;
+ }
+
if (of_get_property(of_node, "qcom,flash-source", &count)) {
count /= sizeof(uint32_t);
CDBG("count %d\n", count);
if (count > MAX_LED_TRIGGERS) {
- pr_err("failed\n");
+ pr_err("invalid count\n");
return -EINVAL;
}
fctrl.num_sources = count;
@@ -157,7 +166,7 @@
"linux,default-trigger",
&fctrl.flash_trigger_name[i]);
if (rc < 0) {
- pr_err("failed\n");
+ pr_err("default-trigger: read failed\n");
of_node_put(flash_src_node);
continue;
}
@@ -165,12 +174,18 @@
CDBG("default trigger %s\n",
fctrl.flash_trigger_name[i]);
- rc = of_property_read_u32(flash_src_node,
- "qcom,current", &fctrl.flash_op_current[i]);
- if (rc < 0) {
- pr_err("failed rc %d\n", rc);
- of_node_put(flash_src_node);
- continue;
+ if (flashtype == GPIO_FLASH) {
+ /* use fake current */
+ fctrl.flash_op_current[i] = LED_FULL;
+ } else {
+ rc = of_property_read_u32(flash_src_node,
+ "qcom,current",
+ &fctrl.flash_op_current[i]);
+ if (rc < 0) {
+ pr_err("current: read failed\n");
+ of_node_put(flash_src_node);
+ continue;
+ }
}
of_node_put(flash_src_node);
@@ -180,6 +195,10 @@
led_trigger_register_simple(fctrl.flash_trigger_name[i],
&fctrl.flash_trigger[i]);
+
+ if (flashtype == GPIO_FLASH)
+ if (fctrl.flash_trigger[i])
+ temp = fctrl.flash_trigger[i];
}
/* Torch source */
@@ -190,25 +209,39 @@
"linux,default-trigger",
&fctrl.torch_trigger_name);
if (rc < 0) {
- pr_err("failed\n");
- } else {
- CDBG("default trigger %s\n",
- fctrl.torch_trigger_name);
+ pr_err("default-trigger: read failed\n");
+ goto torch_failed;
+ }
+ CDBG("default trigger %s\n",
+ fctrl.torch_trigger_name);
+
+ if (flashtype == GPIO_FLASH) {
+ /* use fake current */
+ fctrl.torch_op_current = LED_FULL;
+ if (temp)
+ fctrl.torch_trigger = temp;
+ else
+ led_trigger_register_simple(
+ fctrl.torch_trigger_name,
+ &fctrl.torch_trigger);
+ } else {
rc = of_property_read_u32(flash_src_node,
"qcom,current",
&fctrl.torch_op_current);
if (rc < 0) {
- pr_err("failed rc %d\n", rc);
- } else {
- CDBG("torch max_current %d\n",
- fctrl.torch_op_current);
-
- led_trigger_register_simple(
- fctrl.torch_trigger_name,
- &fctrl.torch_trigger);
+ pr_err("current: read failed\n");
+ goto torch_failed;
}
+
+ CDBG("torch max_current %d\n",
+ fctrl.torch_op_current);
+
+ led_trigger_register_simple(
+ fctrl.torch_trigger_name,
+ &fctrl.torch_trigger);
}
+torch_failed:
of_node_put(flash_src_node);
}
}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/hi256.c b/drivers/media/platform/msm/camera_v2/sensor/hi256.c
index 835230e..a10d60e 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/hi256.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/hi256.c
@@ -33,7 +33,7 @@
.seq_type = SENSOR_GPIO,
.seq_val = SENSOR_GPIO_STANDBY,
.config_val = GPIO_OUT_LOW,
- .delay = 20,
+ .delay = 0,
},
{
.seq_type = SENSOR_GPIO,
@@ -63,13 +63,13 @@
.seq_type = SENSOR_CLK,
.seq_val = SENSOR_CAM_MCLK,
.config_val = 24000000,
- .delay = 10,
+ .delay = 5,
},
{
.seq_type = SENSOR_GPIO,
.seq_val = SENSOR_GPIO_STANDBY,
.config_val = GPIO_OUT_LOW,
- .delay = 20,
+ .delay = 0,
},
{
.seq_type = SENSOR_GPIO,
@@ -81,7 +81,7 @@
.seq_type = SENSOR_GPIO,
.seq_val = SENSOR_GPIO_RESET,
.config_val = GPIO_OUT_HIGH,
- .delay = 30,
+ .delay = 1,
},
{
.seq_type = SENSOR_I2C_MUX,
diff --git a/drivers/media/platform/msm/camera_v2/sensor/imx134.c b/drivers/media/platform/msm/camera_v2/sensor/imx134.c
new file mode 100644
index 0000000..17a5088
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/imx134.c
@@ -0,0 +1,174 @@
+/* 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 IMX134_SENSOR_NAME "imx134"
+DEFINE_MSM_MUTEX(imx134_mut);
+
+static struct msm_sensor_ctrl_t imx134_s_ctrl;
+
+static struct msm_sensor_power_setting imx134_power_setting[] = {
+ {
+ .seq_type = SENSOR_VREG,
+ .seq_val = CAM_VDIG,
+ .config_val = 0,
+ .delay = 0,
+ },
+ {
+ .seq_type = SENSOR_VREG,
+ .seq_val = CAM_VANA,
+ .config_val = 0,
+ .delay = 0,
+ },
+ {
+ .seq_type = SENSOR_VREG,
+ .seq_val = CAM_VIO,
+ .config_val = 0,
+ .delay = 0,
+ },
+ {
+ .seq_type = SENSOR_VREG,
+ .seq_val = CAM_VAF,
+ .config_val = 0,
+ .delay = 0,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_RESET,
+ .config_val = GPIO_OUT_LOW,
+ .delay = 1,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_RESET,
+ .config_val = GPIO_OUT_HIGH,
+ .delay = 30,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_STANDBY,
+ .config_val = GPIO_OUT_LOW,
+ .delay = 1,
+ },
+ {
+ .seq_type = SENSOR_GPIO,
+ .seq_val = SENSOR_GPIO_STANDBY,
+ .config_val = GPIO_OUT_HIGH,
+ .delay = 30,
+ },
+ {
+ .seq_type = SENSOR_CLK,
+ .seq_val = SENSOR_CAM_MCLK,
+ .config_val = 0,
+ .delay = 1,
+ },
+ {
+ .seq_type = SENSOR_I2C_MUX,
+ .seq_val = 0,
+ .config_val = 0,
+ .delay = 0,
+ },
+};
+
+static struct v4l2_subdev_info imx134_subdev_info[] = {
+ {
+ .code = V4L2_MBUS_FMT_SBGGR10_1X10,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .fmt = 1,
+ .order = 0,
+ },
+};
+
+static const struct i2c_device_id imx134_i2c_id[] = {
+ {IMX134_SENSOR_NAME, (kernel_ulong_t)&imx134_s_ctrl},
+ { }
+};
+
+static int32_t msm_imx134_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ return msm_sensor_i2c_probe(client, id, &imx134_s_ctrl);
+}
+
+static struct i2c_driver imx134_i2c_driver = {
+ .id_table = imx134_i2c_id,
+ .probe = msm_imx134_i2c_probe,
+ .driver = {
+ .name = IMX134_SENSOR_NAME,
+ },
+};
+
+static struct msm_camera_i2c_client imx134_sensor_i2c_client = {
+ .addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static const struct of_device_id imx134_dt_match[] = {
+ {.compatible = "sne,imx134", .data = &imx134_s_ctrl},
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, imx134_dt_match);
+
+static struct platform_driver imx134_platform_driver = {
+ .driver = {
+ .name = "sne,imx134",
+ .owner = THIS_MODULE,
+ .of_match_table = imx134_dt_match,
+ },
+};
+
+static int32_t imx134_platform_probe(struct platform_device *pdev)
+{
+ int32_t rc = 0;
+ const struct of_device_id *match;
+ match = of_match_device(imx134_dt_match, &pdev->dev);
+ rc = msm_sensor_platform_probe(pdev, match->data);
+ return rc;
+}
+
+static int __init imx134_init_module(void)
+{
+ int32_t rc = 0;
+ pr_debug("%s:%d\n", __func__, __LINE__);
+ rc = platform_driver_probe(&imx134_platform_driver,
+ imx134_platform_probe);
+ if (!rc)
+ return rc;
+ pr_debug("%s:%d rc %d\n", __func__, __LINE__, rc);
+ return i2c_add_driver(&imx134_i2c_driver);
+}
+
+static void __exit imx134_exit_module(void)
+{
+ pr_debug("%s:%d\n", __func__, __LINE__);
+ if (imx134_s_ctrl.pdev) {
+ msm_sensor_free_sensor_data(&imx134_s_ctrl);
+ platform_driver_unregister(&imx134_platform_driver);
+ } else {
+ i2c_del_driver(&imx134_i2c_driver);
+ }
+ return;
+}
+
+static struct msm_sensor_ctrl_t imx134_s_ctrl = {
+ .sensor_i2c_client = &imx134_sensor_i2c_client,
+ .power_setting_array.power_setting = imx134_power_setting,
+ .power_setting_array.size = ARRAY_SIZE(imx134_power_setting),
+ .msm_sensor_mutex = &imx134_mut,
+ .sensor_v4l2_subdev_info = imx134_subdev_info,
+ .sensor_v4l2_subdev_info_size = ARRAY_SIZE(imx134_subdev_info),
+};
+
+module_init(imx134_init_module);
+module_exit(imx134_exit_module);
+MODULE_DESCRIPTION("imx134");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 1dba2b6..30ada3e 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -275,12 +275,18 @@
case HAL_BUFFER_OUTPUT:
buffer = HFI_BUFFER_OUTPUT;
break;
+ case HAL_BUFFER_OUTPUT2:
+ buffer = HFI_BUFFER_OUTPUT2;
+ break;
case HAL_BUFFER_EXTRADATA_INPUT:
buffer = HFI_BUFFER_EXTRADATA_INPUT;
break;
case HAL_BUFFER_EXTRADATA_OUTPUT:
buffer = HFI_BUFFER_EXTRADATA_OUTPUT;
break;
+ case HAL_BUFFER_EXTRADATA_OUTPUT2:
+ buffer = HFI_BUFFER_EXTRADATA_OUTPUT2;
+ break;
case HAL_BUFFER_INTERNAL_SCRATCH:
buffer = HFI_BUFFER_INTERNAL_SCRATCH;
break;
@@ -371,6 +377,9 @@
case HAL_BUFFER_MODE_RING:
buf_mode = HFI_BUFFER_MODE_RING;
break;
+ case HAL_BUFFER_MODE_DYNAMIC:
+ buf_mode = HFI_BUFFER_MODE_DYNAMIC;
+ break;
default:
dprintk(VIDC_ERR, "Invalid buffer mode :0x%x\n",
hal_buf_mode);
@@ -1175,7 +1184,50 @@
break;
}
case HAL_CONFIG_VPE_OPERATIONS:
+ {
+ struct hfi_operations_type *hfi;
+ struct hal_operations *prop =
+ (struct hal_operations *) pdata;
+ pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_VPE_OPERATIONS;
+ hfi = (struct hfi_operations_type *) &pkt->rg_property_data[1];
+ switch (prop->rotate) {
+ case HAL_ROTATE_NONE:
+ hfi->rotation = HFI_ROTATE_NONE;
+ break;
+ case HAL_ROTATE_90:
+ hfi->rotation = HFI_ROTATE_90;
+ break;
+ case HAL_ROTATE_180:
+ hfi->rotation = HFI_ROTATE_180;
+ break;
+ case HAL_ROTATE_270:
+ hfi->rotation = HFI_ROTATE_270;
+ break;
+ default:
+ dprintk(VIDC_ERR, "Invalid rotation setting: 0x%x",
+ prop->rotate);
+ rc = -EINVAL;
+ break;
+ }
+ switch (prop->flip) {
+ case HAL_FLIP_NONE:
+ hfi->flip = HFI_FLIP_NONE;
+ break;
+ case HAL_FLIP_HORIZONTAL:
+ hfi->flip = HFI_FLIP_HORIZONTAL;
+ break;
+ case HAL_FLIP_VERTICAL:
+ hfi->flip = HFI_FLIP_VERTICAL;
+ break;
+ default:
+ dprintk(VIDC_ERR, "Invalid flip setting: 0x%x",
+ prop->flip);
+ rc = -EINVAL;
+ break;
+ }
+ pkt->size += sizeof(u32) + sizeof(struct hfi_operations_type);
break;
+ }
case HAL_PARAM_VENC_INTRA_REFRESH:
{
struct hfi_intra_refresh *hfi;
@@ -1299,7 +1351,15 @@
break;
}
case HAL_CONFIG_VPE_DEINTERLACE:
+ {
+ struct hfi_enable *hfi;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_CONFIG_VPE_DEINTERLACE;
+ hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+ hfi->enable = ((struct hal_enable *) pdata)->enable;
+ pkt->size += sizeof(u32) + sizeof(struct hfi_enable);
break;
+ }
case HAL_PARAM_VENC_H264_GENERATE_AUDNAL:
{
struct hfi_enable *hfi;
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 2b6118a..abdb039 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -163,6 +163,38 @@
callback(VIDC_EVENT_CHANGE, &cmd_done);
}
+static void hfi_process_evt_release_buffer_ref(
+ msm_vidc_callback callback, u32 device_id,
+ struct hfi_msg_event_notify_packet *pkt)
+{
+ struct msm_vidc_cb_cmd_done cmd_done = {0};
+ struct msm_vidc_cb_event event_notify = {0};
+
+ struct hfi_msg_release_buffer_ref_event_packet *data;
+
+ dprintk(VIDC_DBG, "RECEIVED:EVENT_NOTIFY - release_buffer_reference");
+ if (sizeof(struct hfi_msg_event_notify_packet)
+ > pkt->size) {
+ dprintk(VIDC_ERR, "hal_process_session_init_done:bad_pkt_size");
+ return;
+ }
+
+ data = (struct hfi_msg_release_buffer_ref_event_packet *)
+ pkt->rg_ext_event_data;
+
+ cmd_done.device_id = device_id;
+ cmd_done.session_id = ((struct hal_session *) pkt->session_id)->
+ session_id;
+ cmd_done.status = VIDC_ERR_NONE;
+ cmd_done.size = sizeof(struct msm_vidc_cb_event);
+
+ event_notify.hal_event_type = HAL_EVENT_RELEASE_BUFFER_REFERENCE;
+ event_notify.packet_buffer = data->packet_buffer;
+ event_notify.exra_data_buffer = data->exra_data_buffer;
+ cmd_done.data = &event_notify;
+ callback(VIDC_EVENT_CHANGE, &cmd_done);
+}
+
static void hfi_process_sys_error(
msm_vidc_callback callback, u32 device_id)
{
@@ -180,7 +212,19 @@
cmd_done.device_id = device_id;
cmd_done.session_id = ((struct hal_session *) pkt->session_id)->
session_id;
- callback(SESSION_ERROR, &cmd_done);
+ dprintk(VIDC_INFO, "Received : SESSION_ERROR with event id : %d\n",
+ pkt->event_data1);
+ switch (pkt->event_data1) {
+ case HFI_ERR_SESSION_INVALID_SCALE_FACTOR:
+ case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE:
+ case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
+ dprintk(VIDC_INFO, "Non Fatal : HFI_EVENT_SESSION_ERROR\n");
+ break;
+ default:
+ dprintk(VIDC_ERR, "HFI_EVENT_SESSION_ERROR\n");
+ callback(SESSION_ERROR, &cmd_done);
+ break;
+ }
}
static void hfi_process_event_notify(
msm_vidc_callback callback, u32 device_id,
@@ -204,7 +248,7 @@
hfi_process_sys_error(callback, device_id);
break;
case HFI_EVENT_SESSION_ERROR:
- dprintk(VIDC_ERR, "HFI_EVENT_SESSION_ERROR");
+ dprintk(VIDC_INFO, "HFI_EVENT_SESSION_ERROR");
if (!validate_session_pkt(sessions, sess, session_lock))
hfi_process_session_error(callback, device_id, pkt);
break;
@@ -217,6 +261,10 @@
case HFI_EVENT_SESSION_PROPERTY_CHANGED:
dprintk(VIDC_INFO, "HFI_EVENT_SESSION_PROPERTY_CHANGED");
break;
+ case HFI_EVENT_RELEASE_BUFFER_REFERENCE:
+ dprintk(VIDC_INFO, "HFI_EVENT_RELEASE_BUFFER_REFERENCE\n");
+ hfi_process_evt_release_buffer_ref(callback, device_id, pkt);
+ break;
default:
dprintk(VIDC_WARN, "hal_process_event_notify:unkown_event_id");
break;
@@ -532,6 +580,39 @@
num_properties--;
break;
}
+ case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED:
+ {
+ struct hfi_buffer_alloc_mode_supported *prop =
+ (struct hfi_buffer_alloc_mode_supported *)
+ (data_ptr + next_offset);
+ int i;
+ if (prop->buffer_type == HFI_BUFFER_OUTPUT ||
+ prop->buffer_type == HFI_BUFFER_OUTPUT2) {
+ sess_init_done->alloc_mode_out = 0;
+ for (i = 0; i < prop->num_entries; i++) {
+ switch (prop->rg_data[i]) {
+ case HFI_BUFFER_MODE_STATIC:
+ sess_init_done->alloc_mode_out
+ |= HAL_BUFFER_MODE_STATIC;
+ break;
+ case HFI_BUFFER_MODE_DYNAMIC:
+ sess_init_done->alloc_mode_out
+ |= HAL_BUFFER_MODE_DYNAMIC;
+ break;
+ }
+ if (i >= 32) {
+ dprintk(VIDC_ERR,
+ "%s - num_entries: %d from f/w seems suspect\n",
+ __func__, prop->num_entries);
+ break;
+ }
+ }
+ }
+ next_offset += sizeof(*prop) -
+ sizeof(u32) + prop->num_entries * sizeof(u32);
+ num_properties--;
+ break;
+ }
default:
dprintk(VIDC_DBG,
"%s default case - 0x%x", __func__, prop_id);
@@ -876,6 +957,7 @@
data_done.output_done.packet_buffer1 = pkt->packet_buffer;
data_done.output_done.extra_data_buffer =
pkt->extra_data_buffer;
+ data_done.output_done.buffer_type = HAL_BUFFER_OUTPUT;
dprintk(VIDC_DBG, "FBD: Received buf: %p, of len: %d\n",
pkt->packet_buffer, pkt->filled_len);
} else if (is_decoder == 1) {
@@ -1128,7 +1210,7 @@
version[i] = ' ';
}
version[i] = '\0';
- dprintk(VIDC_INFO, "F/W version: %s\n", version);
+ dprintk(VIDC_DBG, "F/W version: %s\n", version);
}
smem_table_ptr = smem_get_entry(SMEM_IMAGE_VERSION_TABLE,
diff --git a/drivers/media/platform/msm/vidc/msm_smem.h b/drivers/media/platform/msm/vidc/msm_smem.h
index 4425909..dc384bc 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.h
+++ b/drivers/media/platform/msm/vidc/msm_smem.h
@@ -31,16 +31,16 @@
enum hal_buffer {
HAL_BUFFER_INPUT = 0x1,
HAL_BUFFER_OUTPUT = 0x2,
- HAL_BUFFER_OUTPUT2 = 0x2,
- HAL_BUFFER_EXTRADATA_INPUT = 0x4,
- HAL_BUFFER_EXTRADATA_OUTPUT = 0x8,
- HAL_BUFFER_EXTRADATA_OUTPUT2 = 0x8,
- HAL_BUFFER_INTERNAL_SCRATCH = 0x10,
- HAL_BUFFER_INTERNAL_SCRATCH_1 = 0x20,
- HAL_BUFFER_INTERNAL_SCRATCH_2 = 0x40,
- HAL_BUFFER_INTERNAL_PERSIST = 0x80,
- HAL_BUFFER_INTERNAL_PERSIST_1 = 0x100,
- HAL_BUFFER_INTERNAL_CMD_QUEUE = 0x200,
+ HAL_BUFFER_OUTPUT2 = 0x4,
+ HAL_BUFFER_EXTRADATA_INPUT = 0x8,
+ HAL_BUFFER_EXTRADATA_OUTPUT = 0x10,
+ HAL_BUFFER_EXTRADATA_OUTPUT2 = 0x20,
+ HAL_BUFFER_INTERNAL_SCRATCH = 0x40,
+ HAL_BUFFER_INTERNAL_SCRATCH_1 = 0x80,
+ HAL_BUFFER_INTERNAL_SCRATCH_2 = 0x100,
+ HAL_BUFFER_INTERNAL_PERSIST = 0x200,
+ HAL_BUFFER_INTERNAL_PERSIST_1 = 0x400,
+ HAL_BUFFER_INTERNAL_CMD_QUEUE = 0x800,
};
struct msm_smem {
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index afd7200..468ba74 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -27,7 +27,6 @@
#include "msm_vidc_internal.h"
#include "msm_vidc_debug.h"
#include "vidc_hfi_api.h"
-#include "msm_smem.h"
#include "vidc_hfi_api.h"
#include "msm_vidc_resources.h"
#include "msm_vidc_res_parse.h"
@@ -36,25 +35,7 @@
struct msm_vidc_drv *vidc_driver;
-uint32_t msm_vidc_pwr_collapse_delay = 2000;
-
-struct buffer_info {
- struct list_head list;
- int type;
- int num_planes;
- int fd[VIDEO_MAX_PLANES];
- int buff_off[VIDEO_MAX_PLANES];
- int size[VIDEO_MAX_PLANES];
- u32 uvaddr[VIDEO_MAX_PLANES];
- u32 device_addr[VIDEO_MAX_PLANES];
- struct msm_smem *handle[VIDEO_MAX_PLANES];
-};
-
-struct msm_v4l2_vid_inst {
- struct msm_vidc_inst *vidc_inst;
- void *mem_client;
- struct list_head registered_bufs;
-};
+uint32_t msm_vidc_pwr_collapse_delay = 10000;
static inline struct msm_vidc_inst *get_vidc_inst(struct file *filp, void *fh)
{
@@ -62,234 +43,38 @@
struct msm_vidc_inst, event_handler);
}
-static inline struct msm_v4l2_vid_inst *get_v4l2_inst(struct file *filp,
- void *fh)
-{
- struct msm_vidc_inst *vidc_inst;
- vidc_inst = container_of(filp->private_data,
- struct msm_vidc_inst, event_handler);
- return (struct msm_v4l2_vid_inst *)vidc_inst->priv;
-}
-
-struct buffer_info *get_registered_buf(struct list_head *list,
- int fd, u32 buff_off, u32 size, int *plane)
-{
- struct buffer_info *temp;
- struct buffer_info *ret = NULL;
- int i;
- if (!list || fd < 0 || !plane) {
- dprintk(VIDC_ERR, "Invalid input\n");
- goto err_invalid_input;
- }
- *plane = 0;
- if (!list_empty(list)) {
- list_for_each_entry(temp, list, list) {
- for (i = 0; (i < temp->num_planes)
- && (i < VIDEO_MAX_PLANES); i++) {
- if (temp && temp->fd[i] == fd &&
- (CONTAINS(temp->buff_off[i],
- temp->size[i], buff_off)
- || CONTAINS(buff_off,
- size, temp->buff_off[i])
- || OVERLAPS(buff_off, size,
- temp->buff_off[i],
- temp->size[i]))) {
- dprintk(VIDC_DBG,
- "This memory region is already mapped\n");
- ret = temp;
- *plane = i;
- break;
- }
- }
- if (ret)
- break;
- }
- }
-err_invalid_input:
- return ret;
-}
-
-struct buffer_info *get_same_fd_buffer(struct list_head *list,
- int fd, int *plane)
-{
- struct buffer_info *temp;
- struct buffer_info *ret = NULL;
- int i;
- if (!list || fd < 0 || !plane) {
- dprintk(VIDC_ERR, "Invalid input\n");
- goto err_invalid_input;
- }
- *plane = 0;
- if (!list_empty(list)) {
- list_for_each_entry(temp, list, list) {
- for (i = 0; (i < temp->num_planes)
- && (i < VIDEO_MAX_PLANES); i++) {
- if (temp && temp->fd[i] == fd) {
- dprintk(VIDC_INFO,
- "Found same fd buffer\n");
- ret = temp;
- *plane = i;
- break;
- }
- }
- if (ret)
- break;
- }
- }
-err_invalid_input:
- return ret;
-}
-
-static struct buffer_info *device_to_uvaddr(
- struct list_head *list, u32 device_addr)
-{
- struct buffer_info *temp = NULL;
- int found = 0;
- int i;
- if (!list || !device_addr) {
- dprintk(VIDC_ERR, "Invalid input\n");
- goto err_invalid_input;
- }
- if (!list_empty(list)) {
- list_for_each_entry(temp, list, list) {
- for (i = 0; (i < temp->num_planes)
- && (i < VIDEO_MAX_PLANES); i++) {
- if (temp && temp->device_addr[i]
- == device_addr) {
- dprintk(VIDC_INFO,
- "Found same fd buffer\n");
- found = 1;
- break;
- }
- }
- if (found)
- break;
- }
- }
-err_invalid_input:
- return temp;
-}
-
static int msm_v4l2_open(struct file *filp)
{
- int rc = 0;
struct video_device *vdev = video_devdata(filp);
struct msm_video_device *vid_dev =
container_of(vdev, struct msm_video_device, vdev);
struct msm_vidc_core *core = video_drvdata(filp);
- struct msm_v4l2_vid_inst *v4l2_inst = kzalloc(sizeof(*v4l2_inst),
- GFP_KERNEL);
- if (!v4l2_inst) {
- dprintk(VIDC_ERR,
- "Failed to allocate memory for this instance\n");
- rc = -ENOMEM;
- goto fail_nomem;
- }
- v4l2_inst->mem_client = msm_smem_new_client(SMEM_ION, &core->resources);
- if (!v4l2_inst->mem_client) {
- dprintk(VIDC_ERR, "Failed to create memory client\n");
- rc = -ENOMEM;
- goto fail_mem_client;
- }
+ struct msm_vidc_inst *vidc_inst;
- v4l2_inst->vidc_inst = msm_vidc_open(core->id, vid_dev->type);
- if (!v4l2_inst->vidc_inst) {
+ vidc_inst = msm_vidc_open(core->id, vid_dev->type);
+ if (!vidc_inst) {
dprintk(VIDC_ERR,
"Failed to create video instance, core: %d, type = %d\n",
core->id, vid_dev->type);
- rc = -ENOMEM;
- goto fail_open;
+ return -ENOMEM;
}
- INIT_LIST_HEAD(&v4l2_inst->registered_bufs);
- v4l2_inst->vidc_inst->priv = v4l2_inst;
clear_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags);
- filp->private_data = &(v4l2_inst->vidc_inst->event_handler);
- return rc;
-fail_open:
- msm_smem_delete_client(v4l2_inst->mem_client);
-fail_mem_client:
- kfree(v4l2_inst);
-fail_nomem:
- return rc;
-}
-static int msm_v4l2_release_buffers(struct msm_v4l2_vid_inst *v4l2_inst,
- int buffer_type)
-{
- struct list_head *ptr, *next;
- struct buffer_info *bi;
- struct v4l2_buffer buffer_info;
- struct v4l2_plane plane[VIDEO_MAX_PLANES];
- int rc = 0;
- int i;
- list_for_each_safe(ptr, next, &v4l2_inst->registered_bufs) {
- bi = list_entry(ptr, struct buffer_info, list);
- if (bi->type == buffer_type) {
- buffer_info.type = bi->type;
- for (i = 0; (i < bi->num_planes)
- && (i < VIDEO_MAX_PLANES); i++) {
- plane[i].reserved[0] = bi->fd[i];
- plane[i].reserved[1] = bi->buff_off[i];
- plane[i].length = bi->size[i];
- plane[i].m.userptr = bi->device_addr[i];
- buffer_info.m.planes = plane;
- dprintk(VIDC_DBG,
- "Releasing buffer: %d, %d, %d\n",
- buffer_info.m.planes[i].reserved[0],
- buffer_info.m.planes[i].reserved[1],
- buffer_info.m.planes[i].length);
- }
- buffer_info.length = bi->num_planes;
- rc = msm_vidc_release_buf(v4l2_inst->vidc_inst,
- &buffer_info);
- if (rc)
- dprintk(VIDC_ERR,
- "Failed Release buffer: %d, %d, %d\n",
- buffer_info.m.planes[0].reserved[0],
- buffer_info.m.planes[0].reserved[1],
- buffer_info.m.planes[0].length);
- list_del(&bi->list);
- for (i = 0; i < bi->num_planes; i++) {
- if (bi->handle[i])
- msm_smem_free(v4l2_inst->mem_client,
- bi->handle[i]);
- }
- kfree(bi);
- }
- }
- return rc;
+ filp->private_data = &(vidc_inst->event_handler);
+ return 0;
}
static int msm_v4l2_close(struct file *filp)
{
int rc = 0;
- struct list_head *ptr, *next;
- struct buffer_info *bi;
struct msm_vidc_inst *vidc_inst;
- struct msm_v4l2_vid_inst *v4l2_inst;
- int i;
vidc_inst = get_vidc_inst(filp, NULL);
- v4l2_inst = get_v4l2_inst(filp, NULL);
- rc = msm_v4l2_release_buffers(v4l2_inst,
+ rc = msm_vidc_release_buffers(vidc_inst,
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
if (rc)
dprintk(VIDC_WARN,
"Failed in %s for release output buffers\n", __func__);
- list_for_each_safe(ptr, next, &v4l2_inst->registered_bufs) {
- bi = list_entry(ptr, struct buffer_info, list);
- if (bi->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- list_del(&bi->list);
- for (i = 0; (i < bi->num_planes)
- && (i < VIDEO_MAX_PLANES); i++) {
- if (bi->handle[i])
- msm_smem_free(v4l2_inst->mem_client,
- bi->handle[i]);
- }
- kfree(bi);
- }
- }
- msm_smem_delete_client(v4l2_inst->mem_client);
+
rc = msm_vidc_close(vidc_inst);
- kfree(v4l2_inst);
return rc;
}
@@ -339,11 +124,9 @@
struct v4l2_requestbuffers *b)
{
struct msm_vidc_inst *vidc_inst = get_vidc_inst(file, fh);
- struct msm_v4l2_vid_inst *v4l2_inst;
int rc = 0;
- v4l2_inst = get_v4l2_inst(file, NULL);
if (b->count == 0)
- rc = msm_v4l2_release_buffers(v4l2_inst, b->type);
+ rc = msm_vidc_release_buffers(vidc_inst, b->type);
if (rc)
dprintk(VIDC_WARN,
"Failed in %s for release output buffers\n", __func__);
@@ -353,247 +136,19 @@
int msm_v4l2_prepare_buf(struct file *file, void *fh,
struct v4l2_buffer *b)
{
- struct msm_smem *handle = NULL;
- struct buffer_info *binfo;
- struct buffer_info *temp;
- struct msm_vidc_inst *vidc_inst;
- struct msm_v4l2_vid_inst *v4l2_inst;
- int plane = 0;
- int i, rc = 0;
- struct hfi_device *hdev;
- enum hal_buffer buffer_type;
-
- vidc_inst = get_vidc_inst(file, fh);
- v4l2_inst = get_v4l2_inst(file, fh);
- if (!v4l2_inst || !vidc_inst || !vidc_inst->core
- || !vidc_inst->core->device) {
- rc = -EINVAL;
- goto exit;
- }
-
- hdev = vidc_inst->core->device;
-
- if (!v4l2_inst->mem_client) {
- dprintk(VIDC_ERR, "Failed to get memory client\n");
- rc = -ENOMEM;
- goto exit;
- }
- binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
- if (!binfo) {
- dprintk(VIDC_ERR, "Out of memory\n");
- rc = -ENOMEM;
- goto exit;
- }
- if (b->length > VIDEO_MAX_PLANES) {
- dprintk(VIDC_ERR, "Num planes exceeds max: %d, %d\n",
- b->length, VIDEO_MAX_PLANES);
- rc = -EINVAL;
- goto exit;
- }
- for (i = 0; i < b->length; ++i) {
- if (EXTRADATA_IDX(b->length) &&
- (i == EXTRADATA_IDX(b->length)) &&
- !b->m.planes[i].length) {
- continue;
- }
- temp = get_registered_buf(&v4l2_inst->registered_bufs,
- b->m.planes[i].reserved[0],
- b->m.planes[i].reserved[1],
- b->m.planes[i].length, &plane);
- if (temp) {
- dprintk(VIDC_DBG,
- "This memory region has already been prepared\n");
- rc = -EINVAL;
- kfree(binfo);
- goto exit;
- }
-
- 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);
-
- if (temp) {
- binfo->type = b->type;
- binfo->fd[i] = b->m.planes[i].reserved[0];
- binfo->buff_off[i] = b->m.planes[i].reserved[1];
- binfo->size[i] = b->m.planes[i].length;
- binfo->uvaddr[i] = b->m.planes[i].m.userptr;
- binfo->device_addr[i] =
- temp->handle[plane]->device_addr + binfo->buff_off[i];
- binfo->handle[i] = NULL;
- } else {
- handle = msm_smem_user_to_kernel(v4l2_inst->mem_client,
- b->m.planes[i].reserved[0],
- b->m.planes[i].reserved[1],
- buffer_type);
- if (!handle) {
- dprintk(VIDC_ERR,
- "Failed to get device buffer address\n");
- kfree(binfo);
- goto exit;
- }
- binfo->type = b->type;
- binfo->fd[i] = b->m.planes[i].reserved[0];
- binfo->buff_off[i] = b->m.planes[i].reserved[1];
- binfo->size[i] = b->m.planes[i].length;
- binfo->uvaddr[i] = b->m.planes[i].m.userptr;
- binfo->device_addr[i] =
- handle->device_addr + binfo->buff_off[i];
- binfo->handle[i] = handle;
- dprintk(VIDC_DBG, "Registering buffer: %d, %d, %d\n",
- b->m.planes[i].reserved[0],
- b->m.planes[i].reserved[1],
- b->m.planes[i].length);
- rc = msm_smem_cache_operations(v4l2_inst->mem_client,
- binfo->handle[i], SMEM_CACHE_CLEAN);
- if (rc)
- dprintk(VIDC_WARN,
- "CACHE Clean failed: %d, %d, %d\n",
- b->m.planes[i].reserved[0],
- b->m.planes[i].reserved[1],
- b->m.planes[i].length);
- }
- b->m.planes[i].m.userptr = binfo->device_addr[i];
- }
- binfo->num_planes = b->length;
- list_add_tail(&binfo->list, &v4l2_inst->registered_bufs);
- rc = msm_vidc_prepare_buf(v4l2_inst->vidc_inst, b);
-exit:
- return rc;
+ return msm_vidc_prepare_buf(get_vidc_inst(file, fh), b);
}
int msm_v4l2_qbuf(struct file *file, void *fh,
struct v4l2_buffer *b)
{
- struct msm_vidc_inst *vidc_inst;
- struct msm_v4l2_vid_inst *v4l2_inst;
- struct buffer_info *binfo;
- int plane = 0;
- int rc = 0;
- int i;
- if (b->length > VIDEO_MAX_PLANES) {
- dprintk(VIDC_ERR, "num planes exceeds max: %d\n",
- b->length);
- return -EINVAL;
- }
- vidc_inst = get_vidc_inst(file, fh);
- v4l2_inst = get_v4l2_inst(file, fh);
- for (i = 0; i < b->length; ++i) {
- if (EXTRADATA_IDX(b->length) &&
- (i == EXTRADATA_IDX(b->length)) &&
- !b->m.planes[i].length) {
- b->m.planes[i].m.userptr = 0;
- continue;
- }
- binfo = get_registered_buf(&v4l2_inst->registered_bufs,
- b->m.planes[i].reserved[0],
- b->m.planes[i].reserved[1],
- b->m.planes[i].length, &plane);
- if (!binfo) {
- dprintk(VIDC_ERR,
- "This buffer is not registered: %d, %d, %d\n",
- b->m.planes[i].reserved[0],
- b->m.planes[i].reserved[1],
- b->m.planes[i].length);
- rc = -EINVAL;
- goto err_invalid_buff;
- }
- b->m.planes[i].m.userptr = binfo->device_addr[i];
- dprintk(VIDC_DBG, "Queueing device address = 0x%x\n",
- binfo->device_addr[i]);
-
- if ((vidc_inst->fmts[OUTPUT_PORT]->fourcc ==
- V4L2_PIX_FMT_HEVC_HYBRID) && binfo->handle[i] &&
- (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) {
- rc = msm_smem_cache_operations(v4l2_inst->mem_client,
- binfo->handle[i], SMEM_CACHE_INVALIDATE);
- if (rc) {
- dprintk(VIDC_ERR,
- "Failed to INV caches: %d\n", rc);
- goto err_invalid_buff;
- }
- }
-
- if (binfo->handle[i] &&
- (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) {
- rc = msm_smem_cache_operations(v4l2_inst->mem_client,
- binfo->handle[i], SMEM_CACHE_CLEAN);
- if (rc) {
- dprintk(VIDC_ERR,
- "Failed to clean caches: %d\n", rc);
- goto err_invalid_buff;
- }
- }
- }
- rc = msm_vidc_qbuf(v4l2_inst->vidc_inst, b);
-err_invalid_buff:
- return rc;
+ return msm_vidc_qbuf(get_vidc_inst(file, fh), b);
}
int msm_v4l2_dqbuf(struct file *file, void *fh,
struct v4l2_buffer *b)
{
- int rc = 0;
- int i;
- struct msm_v4l2_vid_inst *v4l2_inst;
- struct msm_vidc_inst *vidc_inst = get_vidc_inst(file, fh);
- struct buffer_info *buffer_info;
- if (b->length > VIDEO_MAX_PLANES) {
- dprintk(VIDC_ERR, "num planes exceed maximum: %d\n",
- b->length);
- return -EINVAL;
- }
- v4l2_inst = get_v4l2_inst(file, fh);
- rc = msm_vidc_dqbuf((void *)vidc_inst, b);
- if (rc) {
- dprintk(VIDC_DBG,
- "Failed to dqbuf, capability: %d, rc: %d\n",
- b->type, rc);
- goto fail_dq_buf;
- }
- for (i = 0; i < b->length; i++) {
- if (EXTRADATA_IDX(b->length) &&
- (i == EXTRADATA_IDX(b->length)) &&
- !b->m.planes[i].m.userptr) {
- continue;
- }
- buffer_info = device_to_uvaddr(
- &v4l2_inst->registered_bufs,
- b->m.planes[i].m.userptr);
- b->m.planes[i].m.userptr = buffer_info->uvaddr[i];
- if (!b->m.planes[i].m.userptr) {
- dprintk(VIDC_ERR,
- "Failed to find user virtual address, 0x%lx, %d, %d\n",
- b->m.planes[i].m.userptr, b->type, i);
- rc = -EINVAL;
- goto fail_dq_buf;
- }
- if (buffer_info->handle[i] &&
- (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) {
- rc = msm_smem_cache_operations(v4l2_inst->mem_client,
- buffer_info->handle[i], SMEM_CACHE_INVALIDATE);
- if (rc) {
- dprintk(VIDC_ERR,
- "Failed to clean caches: %d\n", rc);
- goto fail_dq_buf;
- }
- }
- }
-fail_dq_buf:
- return rc;
+ return msm_vidc_dqbuf(get_vidc_inst(file, fh), b);
}
int msm_v4l2_streamon(struct file *file, void *fh,
@@ -629,12 +184,10 @@
static int msm_v4l2_decoder_cmd(struct file *file, void *fh,
struct v4l2_decoder_cmd *dec)
{
- struct msm_v4l2_vid_inst *v4l2_inst;
struct msm_vidc_inst *vidc_inst = get_vidc_inst(file, fh);
int rc = 0;
- v4l2_inst = get_v4l2_inst(file, NULL);
if (dec->cmd == V4L2_DEC_CMD_STOP)
- rc = msm_v4l2_release_buffers(v4l2_inst,
+ rc = msm_vidc_release_buffers(vidc_inst,
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
if (rc)
dprintk(VIDC_WARN,
@@ -645,12 +198,10 @@
static int msm_v4l2_encoder_cmd(struct file *file, void *fh,
struct v4l2_encoder_cmd *enc)
{
- struct msm_v4l2_vid_inst *v4l2_inst;
struct msm_vidc_inst *vidc_inst = get_vidc_inst(file, fh);
int rc = 0;
- v4l2_inst = get_v4l2_inst(file, NULL);
if (enc->cmd == V4L2_ENC_CMD_STOP)
- rc = msm_v4l2_release_buffers(v4l2_inst,
+ rc = msm_vidc_release_buffers(vidc_inst,
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
if (rc)
dprintk(VIDC_WARN,
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index a3d88c5..f4fdfe7 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -12,7 +12,7 @@
*/
#include <linux/slab.h>
-
+#include <mach/scm.h>
#include "msm_vidc_internal.h"
#include "msm_vidc_common.h"
#include "vidc_hfi_api.h"
@@ -24,6 +24,14 @@
#define MAX_NUM_OUTPUT_BUFFERS 6
#define DEFAULT_CONCEAL_COLOR 0x0
+#define TZ_INFO_GET_FEATURE_VERSION_ID 0x3
+#define TZ_DYNAMIC_BUFFER_FEATURE_ID 12
+#define TZ_FEATURE_VERSION(major, minor, patch) \
+ (((major & 0x3FF) << 22) | ((minor & 0x3FF) << 12) | (patch & 0xFFF))
+struct tz_get_feature_version {
+ u32 feature_id;
+};
+
enum msm_vdec_ctrl_cluster {
MSM_VDEC_CTRL_CLUSTER_MAX = 1 << 0,
};
@@ -72,6 +80,7 @@
static const char *const mpeg_vidc_video_alloc_mode_type[] = {
"Buffer Allocation Static",
"Buffer Allocation Ring Buffer",
+ "Buffer Allocation Dynamic Buffer"
};
static const char *const perf_level[] = {
@@ -255,15 +264,32 @@
.step = 0,
},
{
- .id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE,
- .name = "Buffer allocation mode",
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_INPUT,
+ .name = "Buffer allocation mode for input",
.type = V4L2_CTRL_TYPE_MENU,
.minimum = V4L2_MPEG_VIDC_VIDEO_STATIC,
- .maximum = V4L2_MPEG_VIDC_VIDEO_RING,
+ .maximum = V4L2_MPEG_VIDC_VIDEO_DYNAMIC,
.default_value = V4L2_MPEG_VIDC_VIDEO_STATIC,
.menu_skip_mask = ~(
(1 << V4L2_MPEG_VIDC_VIDEO_STATIC) |
- (1 << V4L2_MPEG_VIDC_VIDEO_RING)
+ (1 << V4L2_MPEG_VIDC_VIDEO_RING) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_DYNAMIC)
+ ),
+ .qmenu = mpeg_vidc_video_alloc_mode_type,
+ .step = 0,
+ .cluster = 0,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT,
+ .name = "Buffer allocation mode for output",
+ .type = V4L2_CTRL_TYPE_MENU,
+ .minimum = V4L2_MPEG_VIDC_VIDEO_STATIC,
+ .maximum = V4L2_MPEG_VIDC_VIDEO_DYNAMIC,
+ .default_value = V4L2_MPEG_VIDC_VIDEO_STATIC,
+ .menu_skip_mask = ~(
+ (1 << V4L2_MPEG_VIDC_VIDEO_STATIC) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_RING) |
+ (1 << V4L2_MPEG_VIDC_VIDEO_DYNAMIC)
),
.qmenu = mpeg_vidc_video_alloc_mode_type,
.step = 0,
@@ -281,6 +307,22 @@
.qmenu = NULL,
.cluster = 0,
},
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE,
+ .name = "Video decoder multi stream",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .minimum =
+ V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY,
+ .maximum =
+ V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY,
+ .default_value =
+ V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY,
+ .step = 1,
+ .menu_skip_mask = 0,
+ .step = 1,
+ .qmenu = NULL,
+ .cluster = 0,
+ },
};
#define NUM_CTRLS ARRAY_SIZE(msm_vdec_ctrls)
@@ -470,7 +512,8 @@
b->m.planes[i].length);
}
buffer_info.buffer_size = b->m.planes[0].length;
- buffer_info.buffer_type = HAL_BUFFER_OUTPUT;
+ buffer_info.buffer_type =
+ msm_comm_get_hal_output_buffer(inst);
buffer_info.num_buffers = 1;
buffer_info.align_device_addr =
b->m.planes[0].m.userptr;
@@ -554,7 +597,8 @@
b->m.planes[i].length);
}
buffer_info.buffer_size = b->m.planes[0].length;
- buffer_info.buffer_type = HAL_BUFFER_OUTPUT;
+ buffer_info.buffer_type =
+ msm_comm_get_hal_output_buffer(inst);
buffer_info.num_buffers = 1;
buffer_info.align_device_addr =
b->m.planes[0].m.userptr;
@@ -642,7 +686,6 @@
int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
{
const struct msm_vidc_format *fmt = NULL;
- struct hal_frame_size frame_sz;
struct hfi_device *hdev;
int stride, scanlines;
int extra_idx = 0;
@@ -664,8 +707,22 @@
f->fmt.pix_mp.pixelformat = fmt->fourcc;
f->fmt.pix_mp.num_planes = fmt->num_planes;
if (inst->in_reconfig == true) {
- inst->prop.height = inst->reconfig_height;
- inst->prop.width = inst->reconfig_width;
+ if (msm_comm_get_stream_output_mode(inst) ==
+ HAL_VIDEO_DECODER_PRIMARY) {
+ inst->prop.height[CAPTURE_PORT] =
+ inst->reconfig_height;
+ inst->prop.width[CAPTURE_PORT] =
+ inst->reconfig_width;
+ inst->prop.height[OUTPUT_PORT] =
+ inst->reconfig_height;
+ inst->prop.width[OUTPUT_PORT] =
+ inst->reconfig_width;
+ } else {
+ inst->prop.height[OUTPUT_PORT] =
+ inst->reconfig_height;
+ inst->prop.width[OUTPUT_PORT] =
+ inst->reconfig_width;
+ }
rc = msm_vidc_check_session_supported(inst);
if (rc) {
dprintk(VIDC_ERR,
@@ -673,15 +730,10 @@
goto exit;
}
}
- f->fmt.pix_mp.height = inst->prop.height;
- f->fmt.pix_mp.width = inst->prop.width;
- stride = inst->prop.width;
- scanlines = inst->prop.height;
- frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
- frame_sz.width = inst->prop.width;
- frame_sz.height = inst->prop.height;
- dprintk(VIDC_DBG, "width = %d, height = %d\n",
- frame_sz.width, frame_sz.height);
+ f->fmt.pix_mp.height = inst->prop.height[CAPTURE_PORT];
+ f->fmt.pix_mp.width = inst->prop.width[CAPTURE_PORT];
+ stride = inst->prop.width[CAPTURE_PORT];
+ scanlines = inst->prop.height[CAPTURE_PORT];
rc = msm_comm_try_get_bufreqs(inst);
if (rc) {
dprintk(VIDC_ERR,
@@ -691,19 +743,15 @@
if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
for (i = 0; i < fmt->num_planes; ++i) {
f->fmt.pix_mp.plane_fmt[i].sizeimage =
- fmt->get_frame_size(i,
- inst->capability.height.max,
- inst->capability.width.max);
- inst->bufq[OUTPUT_PORT].
- vb2_bufq.plane_sizes[i] =
- f->fmt.pix_mp.plane_fmt[i].sizeimage;
+ inst->bufq[OUTPUT_PORT].vb2_bufq.plane_sizes[i];
}
} else {
switch (fmt->fourcc) {
case V4L2_PIX_FMT_NV12:
call_hfi_op(hdev, get_stride_scanline,
COLOR_FMT_NV12,
- inst->prop.width, inst->prop.height,
+ inst->prop.width[CAPTURE_PORT],
+ inst->prop.height[CAPTURE_PORT],
&stride, &scanlines);
break;
default:
@@ -711,7 +759,8 @@
"Color format not recognized\n");
}
buff_req_buffer =
- get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT);
+ get_buff_req_buffer(inst,
+ msm_comm_get_hal_output_buffer(inst));
if (buff_req_buffer)
f->fmt.pix_mp.plane_fmt[0].sizeimage =
buff_req_buffer->buffer_size;
@@ -743,9 +792,9 @@
(__u16)scanlines;
} else {
f->fmt.pix_mp.plane_fmt[0].bytesperline =
- (__u16)inst->prop.width;
+ (__u16)inst->prop.width[CAPTURE_PORT];
f->fmt.pix_mp.plane_fmt[0].reserved[0] =
- (__u16)inst->prop.height;
+ (__u16)inst->prop.height[CAPTURE_PORT];
}
} else {
dprintk(VIDC_ERR,
@@ -812,13 +861,14 @@
int ret = 0;
int i;
struct hal_buffer_requirements *buff_req_buffer;
+ int max_input_size = 0;
+
if (!inst || !f) {
dprintk(VIDC_ERR,
"Invalid input, inst = %p, format = %p\n", inst, f);
return -EINVAL;
}
if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- struct hal_frame_size frame_sz;
fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats,
ARRAY_SIZE(vdec_formats), f->fmt.pix_mp.pixelformat,
@@ -830,14 +880,26 @@
rc = -EINVAL;
goto err_invalid_fmt;
}
+ inst->prop.width[CAPTURE_PORT] = f->fmt.pix_mp.width;
+ inst->prop.height[CAPTURE_PORT] = f->fmt.pix_mp.height;
+ if (msm_comm_get_stream_output_mode(inst) ==
+ HAL_VIDEO_DECODER_PRIMARY) {
+ inst->prop.width[OUTPUT_PORT] = f->fmt.pix_mp.width;
+ inst->prop.height[OUTPUT_PORT] = f->fmt.pix_mp.height;
+ }
inst->fmts[fmt->type] = fmt;
- frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
- frame_sz.width = inst->prop.width;
- frame_sz.height = inst->prop.height;
- dprintk(VIDC_DBG, "width = %d, height = %d\n",
- frame_sz.width, frame_sz.height);
- ret = msm_comm_try_set_prop(inst,
- HAL_PARAM_FRAME_SIZE, &frame_sz);
+ if (msm_comm_get_stream_output_mode(inst) ==
+ HAL_VIDEO_DECODER_SECONDARY) {
+ frame_sz.buffer_type = HAL_BUFFER_OUTPUT2;
+ frame_sz.width = inst->prop.width[CAPTURE_PORT];
+ frame_sz.height = inst->prop.height[CAPTURE_PORT];
+ dprintk(VIDC_DBG,
+ "buffer type = %d width = %d, height = %d\n",
+ frame_sz.buffer_type, frame_sz.width,
+ frame_sz.height);
+ ret = msm_comm_try_set_prop(inst,
+ HAL_PARAM_FRAME_SIZE, &frame_sz);
+ }
ret = ret || msm_comm_try_get_bufreqs(inst);
if (ret) {
for (i = 0; i < fmt->num_planes; ++i) {
@@ -848,7 +910,8 @@
}
} else {
buff_req_buffer =
- get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT);
+ get_buff_req_buffer(inst,
+ msm_comm_get_hal_output_buffer(inst));
if (buff_req_buffer)
f->fmt.pix_mp.plane_fmt[0].sizeimage =
buff_req_buffer->buffer_size;
@@ -873,8 +936,13 @@
f->fmt.pix_mp.plane_fmt[i].sizeimage;
}
} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- inst->prop.width = f->fmt.pix_mp.width;
- inst->prop.height = f->fmt.pix_mp.height;
+ inst->prop.width[OUTPUT_PORT] = f->fmt.pix_mp.width;
+ inst->prop.height[OUTPUT_PORT] = f->fmt.pix_mp.height;
+ if (msm_comm_get_stream_output_mode(inst) ==
+ HAL_VIDEO_DECODER_PRIMARY) {
+ inst->prop.width[CAPTURE_PORT] = f->fmt.pix_mp.width;
+ inst->prop.height[CAPTURE_PORT] = f->fmt.pix_mp.height;
+ }
rc = msm_vidc_check_session_supported(inst);
if (rc) {
dprintk(VIDC_ERR,
@@ -899,12 +967,21 @@
goto err_invalid_fmt;
}
frame_sz.buffer_type = HAL_BUFFER_INPUT;
- frame_sz.width = inst->prop.width;
- frame_sz.height = inst->prop.height;
+ frame_sz.width = inst->prop.width[OUTPUT_PORT];
+ frame_sz.height = inst->prop.height[OUTPUT_PORT];
+ dprintk(VIDC_DBG,
+ "buffer type = %d width = %d, height = %d\n",
+ frame_sz.buffer_type, frame_sz.width,
+ frame_sz.height);
msm_comm_try_set_prop(inst, HAL_PARAM_FRAME_SIZE, &frame_sz);
- f->fmt.pix_mp.plane_fmt[0].sizeimage =
- fmt->get_frame_size(0, inst->capability.height.max,
+
+ max_input_size = fmt->get_frame_size(0,
+ inst->capability.height.max,
inst->capability.width.max);
+
+ if (f->fmt.pix_mp.plane_fmt[0].sizeimage > max_input_size)
+ f->fmt.pix_mp.plane_fmt[0].sizeimage = max_input_size;
+
f->fmt.pix_mp.num_planes = fmt->num_planes;
for (i = 0; i < fmt->num_planes; ++i) {
inst->bufq[OUTPUT_PORT].vb2_bufq.plane_sizes[i] =
@@ -1028,7 +1105,8 @@
break;
}
mutex_lock(&inst->lock);
- bufreq = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT);
+ bufreq = get_buff_req_buffer(inst,
+ msm_comm_get_hal_output_buffer(inst));
if (!bufreq) {
dprintk(VIDC_ERR,
"No buffer requirement for buffer type %x\n",
@@ -1037,15 +1115,14 @@
mutex_unlock(&inst->lock);
break;
}
- if (*num_buffers && *num_buffers >=
- bufreq->buffer_count_actual) {
+ *num_buffers = max(*num_buffers, bufreq->buffer_count_min);
+ if (*num_buffers != bufreq->buffer_count_actual) {
property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
- new_buf_count.buffer_type = HAL_BUFFER_OUTPUT;
+ new_buf_count.buffer_type =
+ msm_comm_get_hal_output_buffer(inst);
new_buf_count.buffer_count_actual = *num_buffers;
rc = call_hfi_op(hdev, session_set_property,
inst->session, property_id, &new_buf_count);
- } else {
- *num_buffers = bufreq->buffer_count_min;
}
mutex_unlock(&inst->lock);
dprintk(VIDC_DBG, "count = %d, size = %d, alignment = %d\n",
@@ -1072,12 +1149,80 @@
return rc;
}
+static int msm_vdec_queue_output_buffers(struct msm_vidc_inst *inst)
+{
+ struct internal_buf *binfo;
+ struct hfi_device *hdev;
+ struct msm_smem *handle;
+ struct vidc_frame_data frame_data = {0};
+ struct hal_buffer_requirements *output_buf, *extradata_buf;
+ int rc = 0;
+ hdev = inst->core->device;
+
+ output_buf = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT);
+ if (!output_buf) {
+ dprintk(VIDC_DBG,
+ "This output buffer not required, buffer_type: %x\n",
+ HAL_BUFFER_OUTPUT);
+ return 0;
+ }
+ dprintk(VIDC_DBG,
+ "output: num = %d, size = %d\n",
+ output_buf->buffer_count_actual,
+ output_buf->buffer_size);
+
+ extradata_buf = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_OUTPUT);
+ if (!extradata_buf) {
+ dprintk(VIDC_DBG,
+ "This extradata buffer not required, buffer_type: %x\n",
+ HAL_BUFFER_EXTRADATA_OUTPUT);
+ return 0;
+ }
+
+ hdev = inst->core->device;
+
+ mutex_lock(&inst->lock);
+ if (!list_empty(&inst->outputbufs)) {
+ list_for_each_entry(binfo, &inst->outputbufs, list) {
+ if (!binfo) {
+ dprintk(VIDC_ERR, "Invalid parameter\n");
+ mutex_unlock(&inst->lock);
+ return -EINVAL;
+ }
+ handle = binfo->handle;
+ frame_data.alloc_len = output_buf->buffer_size;
+ frame_data.filled_len = 0;
+ frame_data.offset = 0;
+ frame_data.device_addr = handle->device_addr;
+ frame_data.flags = 0;
+ frame_data.extradata_addr = handle->device_addr +
+ output_buf->buffer_size;
+ frame_data.buffer_type = HAL_BUFFER_OUTPUT;
+ rc = call_hfi_op(hdev, session_ftb,
+ (void *) inst->session, &frame_data);
+ binfo->buffer_ownership = FIRMWARE;
+ }
+ }
+ mutex_unlock(&inst->lock);
+ return 0;
+}
+
static inline int start_streaming(struct msm_vidc_inst *inst)
{
int rc = 0;
struct vb2_buf_entry *temp;
+ struct hfi_device *hdev;
struct list_head *ptr, *next;
+
+ hdev = inst->core->device;
inst->in_reconfig = false;
+ if (msm_comm_get_stream_output_mode(inst) ==
+ HAL_VIDEO_DECODER_SECONDARY)
+ rc = msm_comm_check_scaling_supported(inst);
+ if (rc) {
+ dprintk(VIDC_ERR, "H/w scaling is not in valid range");
+ return -EINVAL;
+ }
rc = msm_comm_set_scratch_buffers(inst);
if (rc) {
dprintk(VIDC_ERR,
@@ -1091,6 +1236,15 @@
goto fail_start;
}
+ if (msm_comm_get_stream_output_mode(inst) ==
+ HAL_VIDEO_DECODER_SECONDARY) {
+ rc = msm_comm_set_output_buffers(inst);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to set output buffers: %d\n", rc);
+ goto fail_start;
+ }
+ }
mutex_lock(&inst->core->sync_lock);
msm_comm_scale_clocks_and_bus(inst);
mutex_unlock(&inst->core->sync_lock);
@@ -1101,7 +1255,15 @@
"Failed to move inst: %p to start done state\n", inst);
goto fail_start;
}
-
+ if (msm_comm_get_stream_output_mode(inst) ==
+ HAL_VIDEO_DECODER_SECONDARY) {
+ rc = msm_vdec_queue_output_buffers(inst);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to queue output buffers: %d\n", rc);
+ goto fail_start;
+ }
+ }
mutex_lock(&inst->sync_lock);
if (!list_empty(&inst->pendingq)) {
list_for_each_safe(ptr, next, &inst->pendingq) {
@@ -1295,27 +1457,69 @@
}
inst->fmts[OUTPUT_PORT] = &vdec_formats[1];
inst->fmts[CAPTURE_PORT] = &vdec_formats[0];
- inst->prop.height = DEFAULT_HEIGHT;
- inst->prop.width = DEFAULT_WIDTH;
+ inst->prop.height[CAPTURE_PORT] = DEFAULT_HEIGHT;
+ inst->prop.width[CAPTURE_PORT] = DEFAULT_WIDTH;
+ inst->prop.height[OUTPUT_PORT] = DEFAULT_HEIGHT;
+ inst->prop.width[OUTPUT_PORT] = DEFAULT_WIDTH;
inst->capability.height.min = MIN_SUPPORTED_HEIGHT;
inst->capability.height.max = DEFAULT_HEIGHT;
inst->capability.width.min = MIN_SUPPORTED_WIDTH;
inst->capability.width.max = DEFAULT_WIDTH;
+ inst->capability.buffer_mode[OUTPUT_PORT] = HAL_BUFFER_MODE_STATIC;
+ inst->capability.buffer_mode[CAPTURE_PORT] = HAL_BUFFER_MODE_STATIC;
+ inst->buffer_mode_set[OUTPUT_PORT] = HAL_BUFFER_MODE_STATIC;
+ inst->buffer_mode_set[CAPTURE_PORT] = HAL_BUFFER_MODE_STATIC;
inst->prop.fps = 30;
return rc;
}
+static inline enum buffer_mode_type get_buf_type(int val)
+{
+ switch (val) {
+ case V4L2_MPEG_VIDC_VIDEO_STATIC:
+ return HAL_BUFFER_MODE_STATIC;
+ case V4L2_MPEG_VIDC_VIDEO_RING:
+ return HAL_BUFFER_MODE_RING;
+ case V4L2_MPEG_VIDC_VIDEO_DYNAMIC:
+ return HAL_BUFFER_MODE_DYNAMIC;
+ default:
+ dprintk(VIDC_ERR, "%s: invalid buf type: %d", __func__, val);
+ }
+ return 0;
+}
+
+static int check_tz_dynamic_buffer_support(void)
+{
+ int rc = 0;
+ struct tz_get_feature_version tz_feature_id;
+ unsigned int resp = 0;
+
+ tz_feature_id.feature_id = TZ_DYNAMIC_BUFFER_FEATURE_ID;
+ rc = scm_call(SCM_SVC_INFO,
+ TZ_INFO_GET_FEATURE_VERSION_ID, &tz_feature_id,
+ sizeof(tz_feature_id), &resp, sizeof(resp));
+ if ((rc) || (resp != TZ_FEATURE_VERSION(1, 1, 0))) {
+ dprintk(VIDC_DBG,
+ "Dyamic buffer mode not supported, failed to get tz feature version id : %u, rc : %d, response : %u\n",
+ tz_feature_id.feature_id, rc, resp);
+ rc = -ENOTSUPP;
+ }
+ return rc;
+}
+
static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
{
int rc = 0;
struct hal_nal_stream_format_supported stream_format;
struct hal_enable_picture enable_picture;
- struct hal_enable hal_property;/*, prop;*/
+ struct hal_enable hal_property;
enum hal_property property_id = 0;
u32 property_val = 0;
void *pdata = NULL;
struct hfi_device *hdev;
struct hal_extradata_enable extra;
+ struct hal_buffer_alloc_mode alloc_mode;
+ struct hal_multi_stream multi_stream;
if (!inst || !inst->core || !inst->core->device) {
dprintk(VIDC_ERR, "%s invalid parameters", __func__);
@@ -1404,15 +1608,17 @@
}
break;
- case V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE:
- {
- struct hal_buffer_alloc_mode mode;
+ case V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_INPUT:
+ if (ctrl->val == V4L2_MPEG_VIDC_VIDEO_DYNAMIC) {
+ rc = -ENOTSUPP;
+ break;
+ }
property_id = HAL_PARAM_BUFFER_ALLOC_MODE;
- mode.buffer_mode = ctrl->val;
- mode.buffer_type = HAL_BUFFER_INPUT;
- pdata = &mode;
+ alloc_mode.buffer_mode = get_buf_type(ctrl->val);
+ alloc_mode.buffer_type = HAL_BUFFER_INPUT;
+ inst->buffer_mode_set[OUTPUT_PORT] = alloc_mode.buffer_mode;
+ pdata = &alloc_mode;
break;
- }
case V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY:
{
property_id = HAL_PARAM_VDEC_FRAME_ASSEMBLY;
@@ -1420,6 +1626,91 @@
pdata = &hal_property;
break;
}
+ case V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT:
+ property_id = HAL_PARAM_BUFFER_ALLOC_MODE;
+ alloc_mode.buffer_mode = get_buf_type(ctrl->val);
+ if (!(alloc_mode.buffer_mode &
+ inst->capability.buffer_mode[CAPTURE_PORT])) {
+ dprintk(VIDC_DBG,
+ "buffer mode[%d] not supported for Capture Port\n",
+ ctrl->val);
+ rc = -ENOTSUPP;
+ break;
+ }
+ if ((alloc_mode.buffer_mode == HAL_BUFFER_MODE_DYNAMIC) &&
+ (inst->flags & VIDC_SECURE) &&
+ check_tz_dynamic_buffer_support()) {
+ rc = -ENOTSUPP;
+ break;
+ }
+ alloc_mode.buffer_type = HAL_BUFFER_OUTPUT;
+ pdata = &alloc_mode;
+ inst->buffer_mode_set[CAPTURE_PORT] = alloc_mode.buffer_mode;
+ break;
+ case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE:
+ if (ctrl->val && !(inst->capability.pixelprocess_capabilities &
+ HAL_VIDEO_DECODER_MULTI_STREAM_CAPABILITY)) {
+ dprintk(VIDC_ERR, "Downscaling not supported: 0x%x",
+ ctrl->id);
+ rc = -ENOTSUPP;
+ break;
+ }
+ switch (ctrl->val) {
+ case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY:
+ multi_stream.buffer_type = HAL_BUFFER_OUTPUT;
+ multi_stream.enable = true;
+ pdata = &multi_stream;
+ rc = call_hfi_op(hdev, session_set_property, (void *)
+ inst->session, HAL_PARAM_VDEC_MULTI_STREAM,
+ pdata);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed : Enabling OUTPUT port : %d\n",
+ rc);
+ break;
+ }
+ multi_stream.buffer_type = HAL_BUFFER_OUTPUT2;
+ multi_stream.enable = false;
+ pdata = &multi_stream;
+ rc = call_hfi_op(hdev, session_set_property, (void *)
+ inst->session, HAL_PARAM_VDEC_MULTI_STREAM,
+ pdata);
+ if (rc)
+ dprintk(VIDC_ERR,
+ "Failed:Disabling OUTPUT2 port : %d\n",
+ rc);
+ break;
+ case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY:
+ multi_stream.buffer_type = HAL_BUFFER_OUTPUT2;
+ multi_stream.enable = true;
+ pdata = &multi_stream;
+ rc = call_hfi_op(hdev, session_set_property, (void *)
+ inst->session, HAL_PARAM_VDEC_MULTI_STREAM,
+ pdata);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed :Enabling OUTPUT2 port : %d\n",
+ rc);
+ break;
+ }
+ multi_stream.buffer_type = HAL_BUFFER_OUTPUT;
+ multi_stream.enable = false;
+ pdata = &multi_stream;
+ rc = call_hfi_op(hdev, session_set_property, (void *)
+ inst->session, HAL_PARAM_VDEC_MULTI_STREAM,
+ pdata);
+ if (rc)
+ dprintk(VIDC_ERR,
+ "Failed :Disabling OUTPUT port : %d\n",
+ rc);
+ break;
+ default:
+ dprintk(VIDC_ERR,
+ "Failed : Unsupported multi stream setting\n");
+ rc = -ENOTSUPP;
+ break;
+ }
+ break;
default:
break;
}
@@ -1440,6 +1731,10 @@
int rc = 0, c = 0;
struct msm_vidc_inst *inst = container_of(ctrl->handler,
struct msm_vidc_inst, ctrl_handler);
+ if (!inst) {
+ dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+ return -EINVAL;
+ }
rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
if (rc) {
dprintk(VIDC_ERR,
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index c1a9ad0..f9b5519 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -25,9 +25,9 @@
#define MAX_BIT_RATE 160000000
#define DEFAULT_BIT_RATE 64000
#define BIT_RATE_STEP 100
-#define MIN_FRAME_RATE 65536
-#define MAX_FRAME_RATE 15728640
-#define DEFAULT_FRAME_RATE 1966080
+#define MIN_FRAME_RATE 1
+#define MAX_FRAME_RATE 240
+#define DEFAULT_FRAME_RATE 15
#define DEFAULT_IR_MBS 30
#define MAX_SLICE_BYTE_SIZE 1024
#define MIN_SLICE_BYTE_SIZE 1024
@@ -134,7 +134,8 @@
MSM_VENC_CTRL_CLUSTER_BITRATE = 1 << 8,
MSM_VENC_CTRL_CLUSTER_TIMING = 1 << 9,
MSM_VENC_CTRL_CLUSTER_VP8_PROFILE_LEVEL = 1 << 10,
- MSM_VENC_CTRL_CLUSTER_MAX = 1 << 11,
+ MSM_VENC_CTRL_CLUSTER_DEINTERLACE = 1 << 11,
+ MSM_VENC_CTRL_CLUSTER_MAX = 1 << 12,
};
static struct msm_vidc_ctrl msm_venc_ctrls[] = {
@@ -400,7 +401,7 @@
(1 << V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_270)
),
.qmenu = mpeg_video_rotation,
- .cluster = 0,
+ .cluster = MSM_VENC_CTRL_CLUSTER_DEINTERLACE,
},
{
.id = V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP,
@@ -718,6 +719,16 @@
.menu_skip_mask = 0,
.qmenu = NULL,
.cluster = MSM_VENC_CTRL_CLUSTER_INTRA_REFRESH,
+ },
+ {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE,
+ .name = "Deinterlace for encoder",
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .minimum = V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_DISABLED,
+ .maximum = V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_ENABLED,
+ .default_value = V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_DISABLED,
+ .step = 1,
+ .cluster = MSM_VENC_CTRL_CLUSTER_DEINTERLACE,
}
};
@@ -844,7 +855,8 @@
inst->fmts[CAPTURE_PORT]->num_planes = *num_planes;
for (i = 0; i < *num_planes; i++) {
sizes[i] = inst->fmts[CAPTURE_PORT]->get_frame_size(
- i, inst->prop.height, inst->prop.width);
+ i, inst->prop.height[CAPTURE_PORT],
+ inst->prop.width[CAPTURE_PORT]);
}
property_id = HAL_PARAM_BUFFER_COUNT_ACTUAL;
new_buf_count.buffer_type = HAL_BUFFER_OUTPUT;
@@ -881,7 +893,8 @@
inst->buff_req.buffer[0].buffer_count_actual);
for (i = 0; i < *num_planes; i++) {
sizes[i] = inst->fmts[OUTPUT_PORT]->get_frame_size(
- i, inst->prop.height, inst->prop.width);
+ i, inst->prop.height[OUTPUT_PORT],
+ inst->prop.width[OUTPUT_PORT]);
}
break;
default:
@@ -897,7 +910,13 @@
int rc = 0;
struct vb2_buf_entry *temp;
struct list_head *ptr, *next;
-
+ if (inst->capability.pixelprocess_capabilities &
+ HAL_VIDEO_ENCODER_SCALING_CAPABILITY)
+ rc = msm_comm_check_scaling_supported(inst);
+ if (rc) {
+ dprintk(VIDC_ERR, "H/w scaling is not in valid range");
+ return -EINVAL;
+ }
rc = msm_comm_try_get_bufreqs(inst);
if (rc) {
dprintk(VIDC_ERR,
@@ -1212,6 +1231,19 @@
default:
goto unknown_value;
}
+ case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION:
+ switch (value) {
+ case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_NONE:
+ return HAL_ROTATE_NONE;
+ case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_90:
+ return HAL_ROTATE_90;
+ case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_180:
+ return HAL_ROTATE_180;
+ case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_270:
+ return HAL_ROTATE_270;
+ default:
+ goto unknown_value;
+ }
}
unknown_value:
@@ -1257,8 +1289,9 @@
if (!__temp) { \
dprintk(VIDC_ERR, "Can't find %s (%x) in cluster", \
#__ctrl_id, __ctrl_id); \
- rc = -ENOENT; \
- break; \
+ /* Clusters are hardcoded, if we can't find */ \
+ /* something then things are massively screwed up */ \
+ BUG_ON(1); \
} \
__temp; \
})
@@ -1270,11 +1303,15 @@
idr_period.idr_period = ctrl->val;
pdata = &idr_period;
break;
- case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD: {
- struct v4l2_ctrl *b;
- b = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES);
+ case V4L2_CID_MPEG_VIDEO_H264_I_PERIOD:
+ case V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES:
+ case V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES:
+ {
+ int num_p, num_b;
+ struct v4l2_ctrl update_ctrl = {.id = 0, .val = 0};
- if (inst->fmts[CAPTURE_PORT]->fourcc != V4L2_PIX_FMT_H264 &&
+ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_I_PERIOD &&
+ inst->fmts[CAPTURE_PORT]->fourcc != V4L2_PIX_FMT_H264 &&
inst->fmts[CAPTURE_PORT]->fourcc !=
V4L2_PIX_FMT_H264_NO_SC) {
dprintk(VIDC_ERR, "Control 0x%x only valid for H264",
@@ -1283,110 +1320,115 @@
break;
}
- /*
- * We can't set the I-period explicitly. So set it implicitly
- * by setting the number of P and B frames per I-period
- */
- property_id = HAL_CONFIG_VENC_INTRA_PERIOD;
- intra_period.pframes = (ctrl->val - 1) - b->val;
- intra_period.bframes = b->val;
- pdata = &intra_period;
- break;
- }
- case V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES:
- temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES);
- property_id =
- HAL_CONFIG_VENC_INTRA_PERIOD;
- intra_period.pframes = ctrl->val;
- intra_period.bframes = temp_ctrl->val;
- pdata = &intra_period;
- break;
- case V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES:
+ temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES);
+ num_b = temp_ctrl->val;
+
temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES);
- intra_period.bframes = ctrl->val;
- intra_period.pframes = temp_ctrl->val;
- if (intra_period.bframes) {
+ num_p = temp_ctrl->val;
+
+ /* V4L2_CID_MPEG_VIDEO_H264_I_PERIOD and _NUM_P_FRAMES are
+ * implicitly tied to each other. If either is adjusted,
+ * the other needs to be adjusted in a complementary manner.
+ * Ideally we adjust _NUM_B_FRAMES as well but we'll leave it
+ * alone for now */
+ if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_I_PERIOD) {
+ num_p = ctrl->val - 1 - num_b;
+ update_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES;
+ update_ctrl.val = num_p;
+ } else if (ctrl->id == V4L2_CID_MPEG_VIDC_VIDEO_NUM_P_FRAMES) {
+ num_p = ctrl->val;
+ update_ctrl.id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD;
+ update_ctrl.val = num_p + num_b;
+ } else if (ctrl->id == V4L2_CID_MPEG_VIDC_VIDEO_NUM_B_FRAMES) {
+ num_b = ctrl->val;
+ update_ctrl.id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD;
+ update_ctrl.val = num_p + num_b;
+ }
+
+ if (update_ctrl.id) {
+ temp_ctrl = TRY_GET_CTRL(update_ctrl.id);
+ temp_ctrl->val = update_ctrl.val;
+ }
+
+ if (num_b) {
u32 max_num_b_frames = MAX_NUM_B_FRAMES;
- property_id =
- HAL_PARAM_VENC_MAX_NUM_B_FRAMES;
+ property_id = HAL_PARAM_VENC_MAX_NUM_B_FRAMES;
pdata = &max_num_b_frames;
rc = call_hfi_op(hdev, session_set_property,
(void *)inst->session, property_id, pdata);
if (rc) {
dprintk(VIDC_ERR,
- "Failed : Setprop MAX_NUM_B_FRAMES"
- "%d", rc);
+ "Failed : Setprop MAX_NUM_B_FRAMES %d",
+ rc);
break;
}
}
- property_id =
- HAL_CONFIG_VENC_INTRA_PERIOD;
+
+ property_id = HAL_CONFIG_VENC_INTRA_PERIOD;
+ intra_period.pframes = num_p;
+ intra_period.bframes = num_b;
pdata = &intra_period;
+
break;
+ }
case V4L2_CID_MPEG_VIDC_VIDEO_REQUEST_IFRAME:
property_id =
HAL_CONFIG_VENC_REQUEST_IFRAME;
request_iframe.enable = true;
pdata = &request_iframe;
break;
+ case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL:
case V4L2_CID_MPEG_VIDEO_BITRATE_MODE:
{
- bool cfr = true, cbr = true;
int final_mode = 0;
+ struct v4l2_ctrl update_ctrl = {.id = 0, .val = 0};
- temp_ctrl = TRY_GET_CTRL(
- V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL);
-
- switch (temp_ctrl->val) {
- case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_OFF:
- /* Let's assume CFR */
- case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR:
- case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR:
- cfr = true;
- break;
- case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_VFR:
- case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_VFR:
- cfr = false;
- break;
- default:
- dprintk(VIDC_WARN, "Unknown framerate mode");
- }
-
- switch (ctrl->val) {
- case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR:
- cbr = false;
- break;
- case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR:
- cbr = true;
- break;
- default:
- dprintk(VIDC_WARN, "Unknown bitrate mode");
- }
-
- if (!cfr && !cbr)
- final_mode =
- V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_VFR;
- else if (!cfr && cbr)
- final_mode =
- V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_VFR;
- else if (cfr && !cbr)
- final_mode =
+ /* V4L2_CID_MPEG_VIDEO_BITRATE_MODE and _RATE_CONTROL
+ * manipulate the same thing. If one control's state
+ * changes, try to mirror the state in the other control's
+ * value */
+ if (ctrl->id == V4L2_CID_MPEG_VIDEO_BITRATE_MODE) {
+ if (ctrl->val == V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) {
+ final_mode = HAL_RATE_CONTROL_VBR_CFR;
+ update_ctrl.val =
V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR;
- else /* ... if (cfr && cbr) */
- final_mode =
+ } else {/* ...if (ctrl->val == _BITRATE_MODE_CBR) */
+ final_mode = HAL_RATE_CONTROL_CBR_CFR;
+ update_ctrl.val =
V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR;
+ }
+
+ update_ctrl.id = V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL;
+
+ } else if (ctrl->id == V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL) {
+ switch (ctrl->val) {
+ case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_OFF:
+ case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_VFR:
+ case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR:
+ update_ctrl.val =
+ V4L2_MPEG_VIDEO_BITRATE_MODE_VBR;
+ case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_VFR:
+ case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_CBR_CFR:
+ update_ctrl.val =
+ V4L2_MPEG_VIDEO_BITRATE_MODE_CBR;
+ }
+
+ final_mode = ctrl->val;
+ update_ctrl.id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE;
+ }
+
+ if (update_ctrl.id) {
+ temp_ctrl = TRY_GET_CTRL(update_ctrl.id);
+ temp_ctrl->val = update_ctrl.val;
+ }
property_id = HAL_PARAM_VENC_RATE_CONTROL;
property_val = final_mode;
pdata = &property_val;
+
break;
}
- case V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL:
- property_id = HAL_PARAM_VENC_RATE_CONTROL;
- property_val = ctrl->val;
- pdata = &property_val;
- break;
case V4L2_CID_MPEG_VIDEO_BITRATE:
property_id =
HAL_CONFIG_VENC_TARGET_BITRATE;
@@ -1528,11 +1570,33 @@
pdata = &profile_level;
break;
case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION:
+ {
+ struct v4l2_ctrl *deinterlace = NULL;
+ if (ctrl->val && !(inst->capability.pixelprocess_capabilities &
+ HAL_VIDEO_ENCODER_ROTATION_CAPABILITY)) {
+ dprintk(VIDC_ERR, "Rotation not supported: 0x%x",
+ ctrl->id);
+ rc = -ENOTSUPP;
+ break;
+ }
+ deinterlace =
+ TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE);
+ if (ctrl->val && deinterlace && deinterlace->val !=
+ V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_DISABLED) {
+ dprintk(VIDC_ERR,
+ "Rotation not supported with deinterlacing");
+ rc = -EINVAL;
+ break;
+ }
property_id =
HAL_CONFIG_VPE_OPERATIONS;
- operations.rotate = ctrl->val;
+ operations.rotate = venc_v4l2_to_hal(
+ V4L2_CID_MPEG_VIDC_VIDEO_ROTATION,
+ ctrl->val);
+ operations.flip = HAL_FLIP_NONE;
pdata = &operations;
break;
+ }
case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP: {
struct v4l2_ctrl *qpp, *qpb;
@@ -1875,6 +1939,37 @@
}
break;
+ case V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE:
+ {
+ struct v4l2_ctrl *rotation = NULL;
+ if (ctrl->val && !(inst->capability.pixelprocess_capabilities &
+ HAL_VIDEO_ENCODER_DEINTERLACE_CAPABILITY)) {
+ dprintk(VIDC_ERR, "Deinterlace not supported: 0x%x",
+ ctrl->id);
+ rc = -ENOTSUPP;
+ break;
+ }
+ rotation = TRY_GET_CTRL(V4L2_CID_MPEG_VIDC_VIDEO_ROTATION);
+ if (ctrl->val && rotation && rotation->val !=
+ V4L2_CID_MPEG_VIDC_VIDEO_ROTATION_NONE) {
+ dprintk(VIDC_ERR,
+ "Deinterlacing not supported with rotation");
+ rc = -EINVAL;
+ break;
+ }
+ property_id = HAL_CONFIG_VPE_DEINTERLACE;
+ switch (ctrl->val) {
+ case V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_ENABLED:
+ enable.enable = 1;
+ break;
+ case V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_DISABLED:
+ default:
+ enable.enable = 0;
+ break;
+ }
+ pdata = &enable;
+ break;
+ }
default:
rc = -ENOTSUPP;
break;
@@ -1896,8 +1991,15 @@
{
int rc = 0, c = 0;
+
struct msm_vidc_inst *inst = container_of(ctrl->handler,
struct msm_vidc_inst, ctrl_handler);
+
+ if (!inst) {
+ dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+ return -EINVAL;
+ }
+
rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
if (rc) {
@@ -1950,9 +2052,14 @@
}
inst->fmts[CAPTURE_PORT] = &venc_formats[1];
inst->fmts[OUTPUT_PORT] = &venc_formats[0];
- inst->prop.height = DEFAULT_HEIGHT;
- inst->prop.width = DEFAULT_WIDTH;
+ inst->prop.height[CAPTURE_PORT] = DEFAULT_HEIGHT;
+ inst->prop.width[CAPTURE_PORT] = DEFAULT_WIDTH;
+ inst->prop.height[OUTPUT_PORT] = DEFAULT_HEIGHT;
+ inst->prop.width[OUTPUT_PORT] = DEFAULT_WIDTH;
inst->prop.fps = 15;
+ inst->buffer_mode_set[OUTPUT_PORT] = HAL_BUFFER_MODE_STATIC;
+ inst->buffer_mode_set[CAPTURE_PORT] = HAL_BUFFER_MODE_STATIC;
+ inst->capability.pixelprocess_capabilities = 0;
return rc;
}
@@ -2148,12 +2255,20 @@
rc = -EINVAL;
goto exit;
}
+ inst->prop.width[CAPTURE_PORT] = f->fmt.pix_mp.width;
+ inst->prop.height[CAPTURE_PORT] = f->fmt.pix_mp.height;
+ rc = msm_vidc_check_session_supported(inst);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s: session not supported\n", __func__);
+ goto exit;
+ }
} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
struct hal_uncompressed_format_select hal_fmt = {0};
struct hal_frame_size frame_sz;
- inst->prop.width = f->fmt.pix_mp.width;
- inst->prop.height = f->fmt.pix_mp.height;
+ inst->prop.width[OUTPUT_PORT] = f->fmt.pix_mp.width;
+ inst->prop.height[OUTPUT_PORT] = f->fmt.pix_mp.height;
rc = msm_vidc_check_session_supported(inst);
if (rc) {
dprintk(VIDC_ERR,
@@ -2161,8 +2276,8 @@
goto exit;
}
frame_sz.buffer_type = HAL_BUFFER_INPUT;
- frame_sz.width = inst->prop.width;
- frame_sz.height = inst->prop.height;
+ frame_sz.width = inst->prop.width[OUTPUT_PORT];
+ frame_sz.height = inst->prop.height[OUTPUT_PORT];
dprintk(VIDC_DBG, "width = %d, height = %d\n",
frame_sz.width, frame_sz.height);
rc = call_hfi_op(hdev, session_set_property, (void *)
@@ -2172,14 +2287,6 @@
"Failed to set framesize for Output port\n");
goto exit;
}
- frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
- rc = call_hfi_op(hdev, session_set_property, (void *)
- inst->session, HAL_PARAM_FRAME_SIZE, &frame_sz);
- if (rc) {
- dprintk(VIDC_ERR,
- "Failed to set hal property for framesize\n");
- goto exit;
- }
fmt = msm_comm_get_pixel_fmt_fourcc(venc_formats,
ARRAY_SIZE(venc_formats), f->fmt.pix_mp.pixelformat,
OUTPUT_PORT);
@@ -2224,11 +2331,23 @@
}
inst->fmts[fmt->type] = fmt;
if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+ struct hal_frame_size frame_sz;
rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
if (rc) {
dprintk(VIDC_ERR, "Failed to open instance\n");
goto exit;
}
+ frame_sz.width = inst->prop.width[CAPTURE_PORT];
+ frame_sz.height = inst->prop.height[CAPTURE_PORT];
+ frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
+ rc = call_hfi_op(hdev, session_set_property,
+ (void *)inst->session, HAL_PARAM_FRAME_SIZE,
+ &frame_sz);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to set OUTPUT framesize\n");
+ goto exit;
+ }
}
} else {
dprintk(VIDC_ERR, "Buf type not recognized, type = %d\n",
@@ -2244,32 +2363,41 @@
const struct msm_vidc_format *fmt = NULL;
int rc = 0;
int i;
+ u32 height, width;
int extra_idx = 0;
+ struct hal_buffer_requirements *buff_req_buffer;
if (!inst || !f) {
dprintk(VIDC_ERR,
"Invalid input, inst = %p, format = %p\n", inst, f);
return -EINVAL;
}
- if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+ if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
fmt = inst->fmts[CAPTURE_PORT];
- else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ height = inst->prop.height[CAPTURE_PORT];
+ width = inst->prop.width[CAPTURE_PORT];
+ } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
fmt = inst->fmts[OUTPUT_PORT];
+ height = inst->prop.height[OUTPUT_PORT];
+ width = inst->prop.width[OUTPUT_PORT];
+ }
if (fmt) {
f->fmt.pix_mp.pixelformat = fmt->fourcc;
- f->fmt.pix_mp.height = inst->prop.height;
- f->fmt.pix_mp.width = inst->prop.width;
+ f->fmt.pix_mp.height = height;
+ f->fmt.pix_mp.width = width;
f->fmt.pix_mp.num_planes = fmt->num_planes;
for (i = 0; i < fmt->num_planes; ++i) {
f->fmt.pix_mp.plane_fmt[i].sizeimage =
- fmt->get_frame_size(i, inst->prop.height,
- inst->prop.width);
+ fmt->get_frame_size(i, height, width);
}
extra_idx = EXTRADATA_IDX(fmt->num_planes);
if (extra_idx && (extra_idx < VIDEO_MAX_PLANES)) {
+ buff_req_buffer =
+ get_buff_req_buffer(inst,
+ HAL_BUFFER_EXTRADATA_OUTPUT);
f->fmt.pix_mp.plane_fmt[extra_idx].sizeimage =
- inst->buff_req.buffer
- [HAL_BUFFER_EXTRADATA_OUTPUT].buffer_size;
+ buff_req_buffer ?
+ buff_req_buffer->buffer_size : 0;
}
for (i = 0; i < fmt->num_planes; ++i) {
inst->bufq[CAPTURE_PORT].vb2_bufq.plane_sizes[i] =
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 10a0eac..6ed94e4 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -199,6 +199,480 @@
return -EINVAL;
}
+struct buffer_info *get_registered_buf(struct msm_vidc_inst *inst,
+ struct v4l2_buffer *b, int idx, int *plane)
+{
+ struct buffer_info *temp;
+ struct buffer_info *ret = NULL;
+ int i;
+ struct list_head *list = &inst->registered_bufs;
+ int fd = b->m.planes[idx].reserved[0];
+ u32 buff_off = b->m.planes[idx].reserved[1];
+ u32 size = b->m.planes[idx].length;
+ u32 device_addr = b->m.planes[idx].m.userptr;
+
+ if (!list || fd < 0 || !plane) {
+ dprintk(VIDC_ERR, "Invalid input\n");
+ goto err_invalid_input;
+ }
+
+ *plane = 0;
+ mutex_lock(&inst->lock);
+ list_for_each_entry(temp, list, list) {
+ for (i = 0; (i < temp->num_planes)
+ && (i < VIDEO_MAX_PLANES); i++) {
+ if (temp &&
+ ((fd == temp->fd[i]) ||
+ (device_addr == temp->device_addr[i])) &&
+ (CONTAINS(temp->buff_off[i],
+ temp->size[i], buff_off)
+ || CONTAINS(buff_off,
+ size, temp->buff_off[i])
+ || OVERLAPS(buff_off, size,
+ temp->buff_off[i],
+ temp->size[i]))) {
+ dprintk(VIDC_DBG,
+ "This memory region is already mapped\n");
+ ret = temp;
+ *plane = i;
+ break;
+ }
+ }
+ if (ret)
+ break;
+ }
+ mutex_unlock(&inst->lock);
+err_invalid_input:
+ return ret;
+}
+
+struct buffer_info *get_same_fd_buffer(struct msm_vidc_inst *inst,
+ struct list_head *list, int fd, int *plane)
+{
+ struct buffer_info *temp;
+ struct buffer_info *ret = NULL;
+ int i;
+ if (fd == 0)
+ return NULL;
+ if (!list || fd < 0 || !plane) {
+ dprintk(VIDC_ERR, "Invalid input\n");
+ goto err_invalid_input;
+ }
+ *plane = 0;
+ mutex_lock(&inst->lock);
+ list_for_each_entry(temp, list, list) {
+ for (i = 0; (i < temp->num_planes)
+ && (i < VIDEO_MAX_PLANES); i++) {
+ if (temp && temp->fd[i] == fd) {
+ temp->same_fd_ref[i]++;
+ dprintk(VIDC_INFO,
+ "Found same fd buffer\n");
+ ret = temp;
+ *plane = i;
+ break;
+ }
+ }
+ if (ret)
+ break;
+ }
+ mutex_unlock(&inst->lock);
+err_invalid_input:
+ return ret;
+}
+
+struct buffer_info *device_to_uvaddr(struct msm_vidc_inst *inst,
+ struct list_head *list, u32 device_addr)
+{
+ struct buffer_info *temp = NULL;
+ struct buffer_info *dummy = NULL;
+ int found = 0;
+ int i;
+ if (!list || !device_addr || !inst) {
+ dprintk(VIDC_ERR,
+ "Invalid input- list: %p device_addr: %u inst: %p\n",
+ list, device_addr, inst);
+ goto err_invalid_input;
+ }
+ mutex_lock(&inst->lock);
+ list_for_each_entry_safe(temp, dummy, list, list) {
+ for (i = 0; (i < temp->num_planes)
+ && (i < VIDEO_MAX_PLANES); i++) {
+ if (temp && !temp->inactive &&
+ temp->device_addr[i] == device_addr) {
+ dprintk(VIDC_INFO,
+ "Found same fd buffer\n");
+ found = 1;
+ break;
+ }
+ }
+ if (found)
+ break;
+ }
+ mutex_unlock(&inst->lock);
+err_invalid_input:
+ return temp;
+}
+
+static inline void populate_buf_info(struct buffer_info *binfo,
+ struct v4l2_buffer *b, u32 i)
+{
+ binfo->type = b->type;
+ binfo->fd[i] = b->m.planes[i].reserved[0];
+ binfo->buff_off[i] = b->m.planes[i].reserved[1];
+ binfo->size[i] = b->m.planes[i].length;
+ binfo->uvaddr[i] = b->m.planes[i].m.userptr;
+ binfo->num_planes = b->length;
+ binfo->memory = b->memory;
+ binfo->v4l2_index = b->index;
+ binfo->dequeued = false;
+ binfo->timestamp.tv_sec = b->timestamp.tv_sec;
+ binfo->timestamp.tv_usec = b->timestamp.tv_usec;
+ dprintk(VIDC_DBG, "%s: fd[%d] = %d b->index = %d",
+ __func__, i, binfo->fd[0], b->index);
+}
+
+static inline void repopulate_v4l2_buffer(struct v4l2_buffer *b,
+ struct buffer_info *binfo)
+{
+ int i = 0;
+ b->type = binfo->type;
+ b->length = binfo->num_planes;
+ b->memory = binfo->memory;
+ b->index = binfo->v4l2_index;
+ b->timestamp.tv_sec = binfo->timestamp.tv_sec;
+ b->timestamp.tv_usec = binfo->timestamp.tv_usec;
+ for (i = 0; i < binfo->num_planes; ++i) {
+ b->m.planes[i].reserved[0] = binfo->fd[i];
+ b->m.planes[i].reserved[1] = binfo->buff_off[i];
+ b->m.planes[i].length = binfo->size[i];
+ b->m.planes[i].m.userptr = binfo->device_addr[i];
+ dprintk(VIDC_DBG, "%s %d %d %d %u\n", __func__, binfo->fd[i],
+ binfo->buff_off[i], binfo->size[i],
+ binfo->device_addr[i]);
+ }
+}
+
+static struct msm_smem *map_buffer(struct msm_vidc_inst *inst,
+ struct v4l2_plane *p, enum hal_buffer buffer_type)
+{
+ struct msm_smem *handle = NULL;
+ handle = msm_smem_user_to_kernel(inst->mem_client,
+ p->reserved[0],
+ p->reserved[1],
+ buffer_type);
+ if (!handle) {
+ dprintk(VIDC_ERR,
+ "%s: Failed to get device buffer address\n", __func__);
+ return NULL;
+ }
+ if (msm_smem_cache_operations(inst->mem_client, handle,
+ SMEM_CACHE_CLEAN))
+ dprintk(VIDC_WARN,
+ "CACHE Clean failed: %d, %d, %d\n",
+ p->reserved[0],
+ p->reserved[1],
+ p->length);
+ return handle;
+}
+
+static inline enum hal_buffer get_hal_buffer_type(
+ struct msm_vidc_inst *inst, struct v4l2_buffer *b)
+{
+ if (inst->session_type == MSM_VIDC_DECODER) {
+ if (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+ return HAL_BUFFER_INPUT;
+ else /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
+ return 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)
+ return HAL_BUFFER_OUTPUT;
+ else /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
+ return HAL_BUFFER_INPUT;
+ }
+ return -EINVAL;
+}
+
+static inline bool is_dynamic_output_buffer_mode(struct v4l2_buffer *b,
+ struct msm_vidc_inst *inst)
+{
+ return ((b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
+ (inst->buffer_mode_set[CAPTURE_PORT] ==
+ HAL_BUFFER_MODE_DYNAMIC));
+}
+
+
+static inline void save_v4l2_buffer(struct v4l2_buffer *b,
+ struct buffer_info *binfo)
+{
+ int i = 0;
+ for (i = 0; i < b->length; ++i) {
+ if (EXTRADATA_IDX(b->length) &&
+ (i == EXTRADATA_IDX(b->length)) &&
+ !b->m.planes[i].length) {
+ continue;
+ }
+ populate_buf_info(binfo, b, i);
+ }
+}
+
+int map_and_register_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
+{
+ struct buffer_info *binfo = NULL;
+ struct buffer_info *temp = NULL;
+ int plane = 0;
+ int i = 0, rc = 0;
+
+ if (!b || !inst) {
+ dprintk(VIDC_ERR, "%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
+ if (!binfo) {
+ dprintk(VIDC_ERR, "Out of memory\n");
+ rc = -ENOMEM;
+ goto exit;
+ }
+ if (b->length > VIDEO_MAX_PLANES) {
+ dprintk(VIDC_ERR, "Num planes exceeds max: %d, %d\n",
+ b->length, VIDEO_MAX_PLANES);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ dprintk(VIDC_DBG, "[MAP] Create binfo = %p fd = %d type = %d\n",
+ binfo, b->m.planes[0].reserved[0], b->type);
+
+ for (i = 0; i < b->length; ++i) {
+ if (EXTRADATA_IDX(b->length) &&
+ (i == EXTRADATA_IDX(b->length)) &&
+ !b->m.planes[i].length) {
+ continue;
+ }
+ mutex_lock(&inst->sync_lock);
+ temp = get_registered_buf(inst, b, i, &plane);
+ if (temp && !is_dynamic_output_buffer_mode(b, inst)) {
+ dprintk(VIDC_DBG,
+ "This memory region has already been prepared\n");
+ rc = -EINVAL;
+ }
+
+ if (temp && is_dynamic_output_buffer_mode(b, inst) &&
+ (i == 0)) {
+ /*
+ * Buffer is already present in registered list
+ * increment ref_count, populate new values of v4l2
+ * buffer in existing buffer_info struct.
+ *
+ * We will use the saved buffer info and queue it when
+ * we receive RELEASE_BUFFER_REFERENCE EVENT from f/w.
+ */
+ dprintk(VIDC_DBG, "[MAP] Buffer already prepared\n");
+ rc = buf_ref_get(inst, temp);
+ if (rc > 0) {
+ save_v4l2_buffer(b, temp);
+ rc = -EEXIST;
+ }
+ }
+ mutex_unlock(&inst->sync_lock);
+ if (rc < 0)
+ goto exit;
+
+ temp = get_same_fd_buffer(inst, &inst->registered_bufs,
+ b->m.planes[i].reserved[0], &plane);
+
+ populate_buf_info(binfo, b, i);
+ if (temp) {
+ binfo->device_addr[i] =
+ temp->handle[plane]->device_addr + binfo->buff_off[i];
+ b->m.planes[i].m.userptr = binfo->device_addr[i];
+ binfo->mapped[i] = false;
+ } else {
+ if (inst->map_output_buffer) {
+ binfo->handle[i] =
+ map_buffer(inst, &b->m.planes[i],
+ get_hal_buffer_type(inst, b));
+ if (!binfo->handle[i]) {
+ rc = -EINVAL;
+ goto exit;
+ }
+ dprintk(VIDC_DBG,
+ "[MAP] - mapped handle[%d] = %p fd[%d] = %d",
+ i, binfo->handle[i], i, binfo->fd[i]);
+ binfo->mapped[i] = true;
+ binfo->device_addr[i] =
+ binfo->handle[i]->device_addr +
+ binfo->buff_off[i];
+ b->m.planes[i].m.userptr =
+ binfo->device_addr[i];
+ } else {
+ binfo->device_addr[i] =
+ b->m.planes[i].m.userptr;
+ }
+ dprintk(VIDC_DBG, "Registering buffer: %d, %d, %d\n",
+ b->m.planes[i].reserved[0],
+ b->m.planes[i].reserved[1],
+ b->m.planes[i].length);
+ }
+ /* We maintain one ref count for all planes*/
+ if ((i == 0) && is_dynamic_output_buffer_mode(b, inst)) {
+ rc = buf_ref_get(inst, binfo);
+ if (rc < 0)
+ return rc;
+ }
+ }
+ dprintk(VIDC_DBG, "[MAP] Adding binfo = %p to list\n", binfo);
+ mutex_lock(&inst->lock);
+ list_add_tail(&binfo->list, &inst->registered_bufs);
+ mutex_unlock(&inst->lock);
+ return 0;
+exit:
+ kfree(binfo);
+ return rc;
+}
+int unmap_and_deregister_buf(struct msm_vidc_inst *inst,
+ struct buffer_info *binfo)
+{
+ int i = 0;
+ struct buffer_info *temp = NULL;
+ struct buffer_info *dummy = NULL;
+ struct list_head *list;
+ bool found = false, keep_node = false;
+
+ if (!inst || !binfo) {
+ dprintk(VIDC_ERR, "%s invalid param: %p %p\n",
+ __func__, inst, binfo);
+ return -EINVAL;
+ }
+
+ mutex_lock(&inst->lock);
+ list = &inst->registered_bufs;
+ /*
+ * Make sure the buffer to be unmapped and deleted
+ * from the registered list is present in the list.
+ */
+ list_for_each_entry_safe(temp, dummy, list, list) {
+ if (temp == binfo) {
+ found = true;
+ break;
+ }
+ }
+
+ /*
+ * Free the buffer info only if
+ * - buffer info has not been deleted from registered list
+ * - vidc client has called dqbuf on the buffer
+ * - no references are held on the buffer
+ */
+ if (!found || !temp || !temp->pending_deletion || !temp->dequeued)
+ goto exit;
+
+ for (i = 0; i < temp->num_planes; i++) {
+ /*
+ * Unmap the handle only if the buffer has been mapped and no
+ * other buffer has a reference to this buffer.
+ * In case of buffers with same fd, we will map the buffer only
+ * once and subsequent buffers will refer to the mapped buffer's
+ * device address.
+ * For buffers which share the same fd, do not unmap and keep
+ * the buffer info in registered list.
+ */
+ if (temp->handle[i] && temp->mapped[i] &&
+ !temp->same_fd_ref[i]) {
+ dprintk(VIDC_DBG,
+ "[UNMAP] - handle[%d] = %p fd[%d] = %d",
+ i, temp->handle[i], i, temp->fd[i]);
+ msm_smem_free(inst->mem_client,
+ temp->handle[i]);
+ }
+
+ if (temp->same_fd_ref[i])
+ keep_node = true;
+ else {
+ temp->fd[i] = 0;
+ temp->handle[i] = 0;
+ temp->device_addr[i] = 0;
+ temp->uvaddr[i] = 0;
+ }
+ }
+ if (!keep_node) {
+ dprintk(VIDC_DBG, "[UNMAP] AND-FREED binfo: %p\n", temp);
+ list_del(&temp->list);
+ kfree(temp);
+ } else {
+ temp->inactive = true;
+ dprintk(VIDC_DBG, "[UNMAP] NOT-FREED binfo: %p\n", temp);
+ }
+exit:
+ mutex_unlock(&inst->lock);
+ return 0;
+}
+
+
+int qbuf_dynamic_buf(struct msm_vidc_inst *inst,
+ struct buffer_info *binfo)
+{
+ struct v4l2_buffer b = {0};
+ struct v4l2_plane plane[VIDEO_MAX_PLANES] = { {0} };
+
+ if (!binfo) {
+ dprintk(VIDC_ERR, "%s invalid param: %p\n", __func__, binfo);
+ return -EINVAL;
+ }
+ dprintk(VIDC_DBG, "%s fd[0] = %d\n", __func__, binfo->fd[0]);
+
+ b.m.planes = plane;
+ repopulate_v4l2_buffer(&b, binfo);
+
+ if (inst->session_type == MSM_VIDC_DECODER)
+ return msm_vdec_qbuf(inst, &b);
+ if (inst->session_type == MSM_VIDC_ENCODER)
+ return msm_venc_qbuf(inst, &b);
+
+ return -EINVAL;
+}
+
+int output_buffer_cache_invalidate(struct msm_vidc_inst *inst,
+ struct buffer_info *binfo)
+{
+ int i = 0;
+ int rc = 0;
+
+ if (!inst) {
+ dprintk(VIDC_ERR, "%s: invalid inst: %p\n", __func__, inst);
+ return -EINVAL;
+ }
+
+ if (!inst->map_output_buffer)
+ return 0;
+
+ if (!binfo) {
+ dprintk(VIDC_ERR, "%s: invalid buffer info: %p\n",
+ __func__, inst);
+ return -EINVAL;
+ }
+
+ if (binfo->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+ return 0;
+
+
+ for (i = 0; i < binfo->num_planes; i++) {
+ if (binfo->handle[i]) {
+ rc = msm_smem_cache_operations(inst->mem_client,
+ binfo->handle[i], SMEM_CACHE_INVALIDATE);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s: Failed to clean caches: %d\n",
+ __func__, rc);
+ return -EINVAL;
+ }
+ }
+ }
+ return 0;
+}
+
int msm_vidc_prepare_buf(void *instance, struct v4l2_buffer *b)
{
struct msm_vidc_inst *inst = instance;
@@ -206,6 +680,19 @@
if (!inst || !b)
return -EINVAL;
+ if (is_dynamic_output_buffer_mode(b, inst)) {
+ dprintk(VIDC_ERR, "%s: not supported in dynamic buffer mode\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ /* Map the buffer only for non-kernel clients*/
+ if (b->m.planes[0].reserved[0]) {
+ inst->map_output_buffer = true;
+ if (map_and_register_buf(inst, b))
+ return -EINVAL;
+ }
+
if (inst->session_type == MSM_VIDC_DECODER)
return msm_vdec_prepare_buf(instance, b);
if (inst->session_type == MSM_VIDC_ENCODER)
@@ -213,18 +700,58 @@
return -EINVAL;
}
-int msm_vidc_release_buf(void *instance, struct v4l2_buffer *b)
+int msm_vidc_release_buffers(void *instance, int buffer_type)
{
+ struct list_head *ptr, *next;
struct msm_vidc_inst *inst = instance;
+ struct buffer_info *bi;
+ struct v4l2_buffer buffer_info;
+ struct v4l2_plane plane[VIDEO_MAX_PLANES];
+ int i, rc = 0;
- if (!inst || !b)
+ if (!inst)
return -EINVAL;
- if (inst->session_type == MSM_VIDC_DECODER)
- return msm_vdec_release_buf(instance, b);
- if (inst->session_type == MSM_VIDC_ENCODER)
- return msm_venc_release_buf(instance, b);
- return -EINVAL;
+ list_for_each_safe(ptr, next, &inst->registered_bufs) {
+ bi = list_entry(ptr, struct buffer_info, list);
+ if (bi->type == buffer_type) {
+ buffer_info.type = bi->type;
+ for (i = 0; (i < bi->num_planes)
+ && (i < VIDEO_MAX_PLANES); i++) {
+ plane[i].reserved[0] = bi->fd[i];
+ plane[i].reserved[1] = bi->buff_off[i];
+ plane[i].length = bi->size[i];
+ plane[i].m.userptr = bi->device_addr[i];
+ buffer_info.m.planes = plane;
+ dprintk(VIDC_DBG,
+ "Releasing buffer: %d, %d, %d\n",
+ buffer_info.m.planes[i].reserved[0],
+ buffer_info.m.planes[i].reserved[1],
+ buffer_info.m.planes[i].length);
+ }
+ buffer_info.length = bi->num_planes;
+ if (inst->session_type == MSM_VIDC_DECODER)
+ rc = msm_vdec_release_buf(instance,
+ &buffer_info);
+ if (inst->session_type == MSM_VIDC_ENCODER)
+ rc = msm_venc_release_buf(instance,
+ &buffer_info);
+ if (rc)
+ dprintk(VIDC_ERR,
+ "Failed Release buffer: %d, %d, %d\n",
+ buffer_info.m.planes[0].reserved[0],
+ buffer_info.m.planes[0].reserved[1],
+ buffer_info.m.planes[0].length);
+ list_del(&bi->list);
+ for (i = 0; i < bi->num_planes; i++) {
+ if (bi->handle[i])
+ msm_smem_free(inst->mem_client,
+ bi->handle[i]);
+ }
+ kfree(bi);
+ }
+ }
+ return rc;
}
int msm_vidc_encoder_cmd(void *instance, struct v4l2_encoder_cmd *enc)
@@ -246,29 +773,149 @@
int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b)
{
struct msm_vidc_inst *inst = instance;
+ struct buffer_info *binfo;
+ int plane = 0;
+ int rc = 0;
+ int i;
if (!inst || !b)
return -EINVAL;
+ if (b->length > VIDEO_MAX_PLANES) {
+ dprintk(VIDC_ERR, "num planes exceeds max: %d\n",
+ b->length);
+ return -EINVAL;
+ }
+
+ if (is_dynamic_output_buffer_mode(b, inst)) {
+ if (b->m.planes[0].reserved[0])
+ inst->map_output_buffer = true;
+
+ rc = map_and_register_buf(inst, b);
+ if (rc == -EEXIST)
+ return 0;
+ if (rc)
+ return rc;
+ }
+
+ for (i = 0; i < b->length; ++i) {
+ if (!inst->map_output_buffer)
+ continue;
+ if (EXTRADATA_IDX(b->length) &&
+ (i == EXTRADATA_IDX(b->length)) &&
+ !b->m.planes[i].length) {
+ b->m.planes[i].m.userptr = 0;
+ continue;
+ }
+
+ binfo = get_registered_buf(inst, b, i, &plane);
+ if (!binfo) {
+ dprintk(VIDC_ERR,
+ "This buffer is not registered: %d, %d, %d\n",
+ b->m.planes[i].reserved[0],
+ b->m.planes[i].reserved[1],
+ b->m.planes[i].length);
+ goto err_invalid_buff;
+ }
+ b->m.planes[i].m.userptr = binfo->device_addr[i];
+ dprintk(VIDC_DBG, "Queueing device address = 0x%x\n",
+ binfo->device_addr[i]);
+
+ if ((inst->fmts[OUTPUT_PORT]->fourcc ==
+ V4L2_PIX_FMT_HEVC_HYBRID) && binfo->handle[i] &&
+ (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) {
+ rc = msm_smem_cache_operations(inst->mem_client,
+ binfo->handle[i], SMEM_CACHE_INVALIDATE);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to inv caches: %d\n", rc);
+ goto err_invalid_buff;
+ }
+ }
+
+ if (binfo->handle[i] &&
+ (b->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)) {
+ rc = msm_smem_cache_operations(inst->mem_client,
+ binfo->handle[i], SMEM_CACHE_CLEAN);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to clean caches: %d\n", rc);
+ goto err_invalid_buff;
+ }
+ }
+ }
+
if (inst->session_type == MSM_VIDC_DECODER)
return msm_vdec_qbuf(instance, b);
if (inst->session_type == MSM_VIDC_ENCODER)
return msm_venc_qbuf(instance, b);
+
+err_invalid_buff:
return -EINVAL;
}
int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
{
struct msm_vidc_inst *inst = instance;
+ struct buffer_info *buffer_info = NULL;
+ int i = 0, rc = 0;
if (!inst || !b)
return -EINVAL;
+ if (b->length > VIDEO_MAX_PLANES) {
+ dprintk(VIDC_ERR, "num planes exceed maximum: %d\n",
+ b->length);
+ return -EINVAL;
+ }
+
if (inst->session_type == MSM_VIDC_DECODER)
- return msm_vdec_dqbuf(instance, b);
+ rc = msm_vdec_dqbuf(instance, b);
if (inst->session_type == MSM_VIDC_ENCODER)
- return msm_venc_dqbuf(instance, b);
- return -EINVAL;
+ rc = msm_venc_dqbuf(instance, b);
+
+ if (rc)
+ return rc;
+
+ for (i = 0; i < b->length; i++) {
+ if (!inst->map_output_buffer)
+ continue;
+ if (EXTRADATA_IDX(b->length) &&
+ (i == EXTRADATA_IDX(b->length)) &&
+ !b->m.planes[i].m.userptr) {
+ continue;
+ }
+ buffer_info = device_to_uvaddr(inst,
+ &inst->registered_bufs,
+ b->m.planes[i].m.userptr);
+
+ if (!buffer_info) {
+ dprintk(VIDC_ERR,
+ "%s no buffer info registered for buffer addr: 0x%lx\n",
+ __func__, b->m.planes[i].m.userptr);
+ return -EINVAL;
+ }
+
+ b->m.planes[i].m.userptr = buffer_info->uvaddr[i];
+ if (!b->m.planes[i].m.userptr) {
+ dprintk(VIDC_ERR,
+ "%s: Failed to find user virtual address, 0x%lx, %d, %d\n",
+ __func__, b->m.planes[i].m.userptr, b->type, i);
+ return -EINVAL;
+ }
+ }
+
+ if (is_dynamic_output_buffer_mode(b, inst)) {
+ mutex_lock(&inst->lock);
+ buffer_info->dequeued = true;
+ mutex_unlock(&inst->lock);
+ dprintk(VIDC_DBG, "[DEQUEUED]: fd[0] = %d\n",
+ buffer_info->fd[0]);
+ rc = unmap_and_deregister_buf(inst, buffer_info);
+ } else
+ rc = output_buffer_cache_invalidate(inst, buffer_info);
+
+ return rc;
}
int msm_vidc_streamon(void *instance, enum v4l2_buf_type i)
@@ -450,9 +1097,12 @@
INIT_LIST_HEAD(&inst->internalbufs);
INIT_LIST_HEAD(&inst->persistbufs);
INIT_LIST_HEAD(&inst->ctrl_clusters);
+ INIT_LIST_HEAD(&inst->registered_bufs);
+ INIT_LIST_HEAD(&inst->outputbufs);
init_waitqueue_head(&inst->kernel_event_queue);
inst->state = MSM_VIDC_CORE_UNINIT_DONE;
inst->core = core;
+ inst->map_output_buffer = false;
for (i = SESSION_MSG_INDEX(SESSION_MSG_START);
i <= SESSION_MSG_INDEX(SESSION_MSG_END); i++) {
@@ -495,7 +1145,7 @@
inst->debugfs_root =
msm_vidc_debugfs_init_inst(inst, core->debugfs_root);
- setup_event_queue(inst, &core->vdev[core_id].vdev);
+ setup_event_queue(inst, &core->vdev[session_type].vdev);
mutex_lock(&core->sync_lock);
list_add_tail(&inst->list, &core->instances);
@@ -555,6 +1205,17 @@
mutex_lock(&inst->lock);
}
}
+ if (!list_empty(&inst->outputbufs)) {
+ list_for_each_safe(ptr, next, &inst->outputbufs) {
+ buf = list_entry(ptr, struct internal_buf,
+ list);
+ list_del(&buf->list);
+ mutex_unlock(&inst->lock);
+ msm_smem_free(inst->mem_client, buf->handle);
+ kfree(buf);
+ mutex_lock(&inst->lock);
+ }
+ }
if (inst->extradata_handle) {
mutex_unlock(&inst->lock);
msm_smem_free(inst->mem_client, inst->extradata_handle);
@@ -572,12 +1233,27 @@
struct msm_vidc_inst *temp;
struct msm_vidc_core *core;
struct list_head *ptr, *next;
+ struct buffer_info *bi;
int rc = 0;
int i;
if (!inst)
return -EINVAL;
+ list_for_each_safe(ptr, next, &inst->registered_bufs) {
+ bi = list_entry(ptr, struct buffer_info, list);
+ if (bi->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+ list_del(&bi->list);
+ for (i = 0; (i < bi->num_planes)
+ && (i < VIDEO_MAX_PLANES); i++) {
+ if (bi->handle[i])
+ msm_smem_free(inst->mem_client,
+ bi->handle[i]);
+ }
+ kfree(bi);
+ }
+ }
+
core = inst->core;
mutex_lock(&core->sync_lock);
list_for_each_safe(ptr, next, &core->instances) {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index fdc851c..42460fa 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -31,6 +31,8 @@
V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_SUFFICIENT
#define V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT \
V4L2_EVENT_MSM_VIDC_PORT_SETTINGS_CHANGED_INSUFFICIENT
+#define V4L2_EVENT_RELEASE_BUFFER_REFERENCE \
+ V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE
#define NUM_MBS_PER_SEC(__height, __width, __fps) ({\
(__height >> 4) * (__width >> 4) * __fps; \
@@ -80,6 +82,30 @@
}
return false;
}
+enum multi_stream msm_comm_get_stream_output_mode(struct msm_vidc_inst *inst)
+{
+ if (inst->session_type == MSM_VIDC_DECODER) {
+ int rc = 0;
+ struct v4l2_control ctrl = {
+ .id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE
+ };
+ rc = v4l2_g_ctrl(&inst->ctrl_handler, &ctrl);
+ if (!rc && ctrl.value)
+ return HAL_VIDEO_DECODER_SECONDARY;
+ }
+ return HAL_VIDEO_DECODER_PRIMARY;
+
+
+}
+static int msm_comm_get_mbs_per_sec(struct msm_vidc_inst *inst)
+{
+ int height, width;
+ height = max(inst->prop.height[CAPTURE_PORT],
+ inst->prop.height[OUTPUT_PORT]);
+ width = max(inst->prop.width[CAPTURE_PORT],
+ inst->prop.width[OUTPUT_PORT]);
+ return NUM_MBS_PER_SEC(height, width, inst->prop.fps);
+}
static int msm_comm_get_load(struct msm_vidc_core *core,
enum session_type type)
@@ -96,9 +122,8 @@
inst->state >= MSM_VIDC_OPEN_DONE &&
inst->state < MSM_VIDC_STOP_DONE) {
if (!is_thumbnail_session(inst))
- num_mbs_per_sec += NUM_MBS_PER_SEC(
- inst->prop.height,
- inst->prop.width, inst->prop.fps);
+ num_mbs_per_sec +=
+ msm_comm_get_mbs_per_sec(inst);
}
mutex_unlock(&inst->lock);
}
@@ -414,22 +439,32 @@
{
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst = NULL;
+ struct hfi_device *hdev;
+
if (response) {
struct vidc_hal_session_init_done *session_init_done =
(struct vidc_hal_session_init_done *)
response->data;
inst = (struct msm_vidc_inst *)response->session_id;
- if (!inst) {
- dprintk(VIDC_ERR, "%s: invalid input parameters",
- __func__);
+ if (!inst || !inst->core || !inst->core->device) {
+ dprintk(VIDC_ERR, "%s invalid parameters", __func__);
return;
}
+
+ hdev = inst->core->device;
+
if (!response->status && session_init_done) {
inst->capability.width = session_init_done->width;
inst->capability.height = session_init_done->height;
inst->capability.frame_rate =
session_init_done->frame_rate;
+ inst->capability.scale_x = session_init_done->scale_x;
+ inst->capability.scale_y = session_init_done->scale_y;
+ inst->capability.pixelprocess_capabilities =
+ call_hfi_op(hdev, get_core_capabilities);
inst->capability.capability_set = true;
+ inst->capability.buffer_mode[CAPTURE_PORT] =
+ session_init_done->alloc_mode_out;
} else {
dprintk(VIDC_ERR,
"Session init response from FW : 0x%x",
@@ -469,16 +504,83 @@
case HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES:
event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
break;
+ case HAL_EVENT_RELEASE_BUFFER_REFERENCE:
+ {
+ struct v4l2_event buf_event = {0};
+ struct buffer_info *binfo = NULL;
+ u32 *ptr = NULL;
+
+ dprintk(VIDC_DBG,
+ "%s - inst: %p buffer: %p extra: %p\n",
+ __func__, inst,
+ event_notify->packet_buffer,
+ event_notify->exra_data_buffer);
+
+ /*
+ * Get the buffer_info entry for the
+ * device address.
+ */
+ binfo = device_to_uvaddr(inst,
+ &inst->registered_bufs,
+ (u32)event_notify->packet_buffer);
+ if (!binfo) {
+ dprintk(VIDC_ERR,
+ "%s buffer not found in registered list\n",
+ __func__);
+ return;
+ }
+
+ /* Fill event data to be sent to client*/
+ buf_event.type =
+ V4L2_EVENT_RELEASE_BUFFER_REFERENCE;
+ ptr = (u32 *)buf_event.u.data;
+ ptr[0] = binfo->fd[0];
+ ptr[1] = binfo->buff_off[0];
+
+ dprintk(VIDC_DBG,
+ "RELEASE REFERENCE EVENT FROM F/W - fd = %d offset = %d\n",
+ ptr[0], ptr[1]);
+
+ mutex_lock(&inst->sync_lock);
+ /* Decrement buffer reference count*/
+ buf_ref_put(inst, binfo);
+
+ /*
+ * Release buffer and remove from list
+ * if reference goes to zero.
+ */
+ if (unmap_and_deregister_buf(inst, binfo))
+ dprintk(VIDC_ERR,
+ "%s: buffer unmap failed\n", __func__);
+ mutex_unlock(&inst->sync_lock);
+
+ /*send event to client*/
+ v4l2_event_queue_fh(&inst->event_handler,
+ &buf_event);
+ wake_up(&inst->kernel_event_queue);
+ return;
+ }
default:
break;
}
if (event == V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT) {
+ dprintk(VIDC_DBG,
+ "V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT\n");
inst->reconfig_height = event_notify->height;
inst->reconfig_width = event_notify->width;
inst->in_reconfig = true;
} else {
- inst->prop.height = event_notify->height;
- inst->prop.width = event_notify->width;
+ dprintk(VIDC_DBG,
+ "V4L2_EVENT_SEQ_CHANGED_SUFFICIENT\n");
+ inst->prop.height[CAPTURE_PORT] = event_notify->height;
+ inst->prop.width[CAPTURE_PORT] = event_notify->width;
+ if (!msm_comm_get_stream_output_mode(inst) ==
+ HAL_VIDEO_DECODER_SECONDARY) {
+ inst->prop.height[OUTPUT_PORT] =
+ event_notify->height;
+ inst->prop.width[OUTPUT_PORT] =
+ event_notify->width;
+ }
}
rc = msm_vidc_check_session_supported(inst);
if (!rc) {
@@ -576,13 +678,51 @@
"Failed to get valid response for release resource\n");
}
}
+void validate_output_buffers(struct msm_vidc_inst *inst)
+{
+ struct internal_buf *binfo;
+ u32 buffers_owned_by_driver = 0;
+ struct hal_buffer_requirements *output_buf;
+ output_buf = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT);
+ if (!output_buf) {
+ dprintk(VIDC_DBG,
+ "This output buffer not required, buffer_type: %x\n",
+ HAL_BUFFER_OUTPUT);
+ return;
+ }
+ list_for_each_entry(binfo, &inst->outputbufs, list) {
+ if (!binfo) {
+ dprintk(VIDC_ERR, "Invalid parameter\n");
+ return;
+ }
+ if (binfo->buffer_ownership != DRIVER) {
+ dprintk(VIDC_ERR,
+ "Failed : This buffer is with FW 0x%lx\n",
+ binfo->handle->device_addr);
+ return;
+ }
+ buffers_owned_by_driver++;
+ }
+ if (buffers_owned_by_driver != output_buf->buffer_count_actual)
+ dprintk(VIDC_ERR,
+ "OUTPUT Buffer count mismatch %d of %d",
+ buffers_owned_by_driver,
+ output_buf->buffer_count_actual);
+ return;
+}
static void handle_session_flush(enum command_response cmd, void *data)
{
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
if (response) {
inst = (struct msm_vidc_inst *)response->session_id;
+ if (msm_comm_get_stream_output_mode(inst) ==
+ HAL_VIDEO_DECODER_SECONDARY) {
+ mutex_lock(&inst->lock);
+ validate_output_buffers(inst);
+ mutex_unlock(&inst->lock);
+ }
msm_vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_FLUSH_DONE);
} else {
dprintk(VIDC_ERR, "Failed to get valid response for flush\n");
@@ -805,12 +945,156 @@
}
}
+int buf_ref_get(struct msm_vidc_inst *inst, struct buffer_info *binfo)
+{
+ int cnt = 0;
+
+ if (!inst || !binfo)
+ return -EINVAL;
+
+ mutex_lock(&inst->lock);
+ atomic_inc(&binfo->ref_count);
+ cnt = atomic_read(&binfo->ref_count);
+ if (cnt > 2) {
+ dprintk(VIDC_DBG, "%s: invalid ref_cnt: %d\n", __func__, cnt);
+ cnt = -EINVAL;
+ }
+ dprintk(VIDC_DBG, "REF_GET[%d] fd[0] = %d\n", cnt, binfo->fd[0]);
+ mutex_unlock(&inst->lock);
+ return cnt;
+}
+
+int buf_ref_put(struct msm_vidc_inst *inst, struct buffer_info *binfo)
+{
+ int rc = 0;
+ int cnt;
+ bool release_buf = false;
+ bool qbuf_again = false;
+
+ if (!inst || !binfo)
+ return -EINVAL;
+
+ mutex_lock(&inst->lock);
+ atomic_dec(&binfo->ref_count);
+ cnt = atomic_read(&binfo->ref_count);
+ dprintk(VIDC_DBG, "REF_PUT[%d] fd[0] = %d\n", cnt, binfo->fd[0]);
+ if (cnt == 0)
+ release_buf = true;
+ else if (cnt == 1)
+ qbuf_again = true;
+ else {
+ dprintk(VIDC_DBG, "%s: invalid ref_cnt: %d\n", __func__, cnt);
+ cnt = -EINVAL;
+ }
+ mutex_unlock(&inst->lock);
+
+ if (cnt < 0)
+ return cnt;
+
+ rc = output_buffer_cache_invalidate(inst, binfo);
+ if (rc)
+ return rc;
+
+ if (release_buf) {
+ /*
+ * We can not delete binfo here as we need to set the user
+ * virtual address saved in binfo->uvaddr to the dequeued v4l2
+ * buffer.
+ *
+ * We will set the pending_deletion flag to true here and delete
+ * binfo from registered list in dqbuf after setting the uvaddr.
+ */
+ dprintk(VIDC_DBG, "fd[0] = %d -> pending_deletion = true\n",
+ binfo->fd[0]);
+ binfo->pending_deletion = true;
+ } else if (qbuf_again) {
+ rc = qbuf_dynamic_buf(inst, binfo);
+ if (!rc)
+ return rc;
+ }
+ return cnt;
+}
+
+static void handle_dynamic_buffer(struct msm_vidc_inst *inst,
+ u32 device_addr, u32 flags)
+{
+ struct buffer_info *binfo = NULL;
+
+ /*
+ * Update reference count and release OR queue back the buffer,
+ * only when firmware is not holding a reference.
+ */
+ if (inst->buffer_mode_set[CAPTURE_PORT] == HAL_BUFFER_MODE_DYNAMIC) {
+ binfo = device_to_uvaddr(inst, &inst->registered_bufs,
+ device_addr);
+ if (!binfo) {
+ dprintk(VIDC_ERR,
+ "%s buffer not found in registered list\n",
+ __func__);
+ return;
+ }
+ if (flags & HAL_BUFFERFLAG_READONLY) {
+ dprintk(VIDC_DBG,
+ "_F_B_D_ fd[0] = %d -> Reference with f/w, addr: 0x%x",
+ binfo->fd[0], device_addr);
+ } else {
+ dprintk(VIDC_DBG,
+ "_F_B_D_ fd[0] = %d -> FBD_ref_released, addr: 0x%x\n",
+ binfo->fd[0], device_addr);
+ buf_ref_put(inst, binfo);
+ }
+ }
+}
+
+static int handle_multi_stream_buffers(struct msm_vidc_inst *inst,
+ u32 dev_addr)
+{
+ struct internal_buf *binfo;
+ struct msm_smem *handle;
+ bool found = false;
+ mutex_lock(&inst->lock);
+ list_for_each_entry(binfo, &inst->outputbufs, list) {
+ if (!binfo) {
+ dprintk(VIDC_ERR, "Invalid parameter\n");
+ break;
+ }
+ handle = binfo->handle;
+ if (handle && dev_addr == handle->device_addr) {
+ if (binfo->buffer_ownership == DRIVER) {
+ dprintk(VIDC_ERR,
+ "FW returned same buffer : 0x%x\n",
+ dev_addr);
+ break;
+ }
+ binfo->buffer_ownership = DRIVER;
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ dprintk(VIDC_ERR,
+ "Failed to find output buffer in queued list: 0x%x\n",
+ dev_addr);
+ mutex_unlock(&inst->lock);
+ return 0;
+}
+
+enum hal_buffer msm_comm_get_hal_output_buffer(struct msm_vidc_inst *inst)
+{
+ if (msm_comm_get_stream_output_mode(inst) ==
+ HAL_VIDEO_DECODER_SECONDARY)
+ return HAL_BUFFER_OUTPUT2;
+ else
+ return HAL_BUFFER_OUTPUT;
+}
+
static void handle_fbd(enum command_response cmd, void *data)
{
struct msm_vidc_cb_data_done *response = data;
struct msm_vidc_inst *inst;
- struct vb2_buffer *vb;
+ struct vb2_buffer *vb = NULL;
struct vidc_hal_fbd *fill_buf_done;
+ enum hal_buffer buffer_type;
if (!response) {
dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
@@ -818,8 +1102,18 @@
}
inst = (struct msm_vidc_inst *)response->session_id;
fill_buf_done = (struct vidc_hal_fbd *)&response->output_done;
- vb = get_vb_from_device_addr(&inst->bufq[CAPTURE_PORT],
- (u32)fill_buf_done->packet_buffer1);
+ buffer_type = msm_comm_get_hal_output_buffer(inst);
+ if (fill_buf_done->buffer_type == buffer_type)
+ vb = get_vb_from_device_addr(&inst->bufq[CAPTURE_PORT],
+ (u32)fill_buf_done->packet_buffer1);
+ else {
+ if (handle_multi_stream_buffers(inst,
+ (u32)fill_buf_done->packet_buffer1))
+ dprintk(VIDC_ERR,
+ "Failed : Output buffer not found 0x%x\n",
+ (u32)fill_buf_done->packet_buffer1);
+ return;
+ }
if (vb) {
vb->v4l2_planes[0].bytesused = fill_buf_done->filled_len1;
vb->v4l2_planes[0].data_offset = fill_buf_done->offset1;
@@ -848,6 +1142,10 @@
}
vb->v4l2_buf.flags = 0;
+ handle_dynamic_buffer(inst, (u32)fill_buf_done->packet_buffer1,
+ fill_buf_done->flags1);
+ if (fill_buf_done->flags1 & HAL_BUFFERFLAG_READONLY)
+ vb->v4l2_buf.flags |= V4L2_QCOM_BUF_FLAG_READONLY;
if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOS)
vb->v4l2_buf.flags |= V4L2_BUF_FLAG_EOS;
if (fill_buf_done->flags1 & HAL_BUFFERFLAG_CODECCONFIG)
@@ -1404,8 +1702,8 @@
temp->state < MSM_VIDC_STOP_DONE) {
dprintk(VIDC_ERR, "%4d|%4d|%4d|%4d\n",
temp->session_type,
- temp->prop.width,
- temp->prop.height,
+ temp->prop.width[CAPTURE_PORT],
+ temp->prop.height[CAPTURE_PORT],
temp->prop.fps);
}
mutex_unlock(&temp->lock);
@@ -1419,6 +1717,7 @@
u32 ocmem_sz = 0;
struct hfi_device *hdev;
int num_mbs_per_sec = 0;
+ int height, width;
if (!inst || !inst->core || !inst->core->device) {
dprintk(VIDC_ERR, "%s invalid parameters", __func__);
@@ -1452,8 +1751,12 @@
goto exit;
}
if (inst->core->resources.has_ocmem) {
- ocmem_sz = get_ocmem_requirement(inst->prop.height,
- inst->prop.width);
+ height = max(inst->prop.height[CAPTURE_PORT],
+ inst->prop.height[OUTPUT_PORT]);
+ width = max(inst->prop.width[CAPTURE_PORT],
+ inst->prop.width[OUTPUT_PORT]);
+ ocmem_sz = get_ocmem_requirement(
+ height, width);
mutex_lock(&inst->core->sync_lock);
rc = msm_comm_scale_bus(inst->core, inst->session_type,
OCMEM_MEM);
@@ -1646,6 +1949,110 @@
return NULL;
}
+static int set_output_buffers(struct msm_vidc_inst *inst,
+ enum hal_buffer buffer_type)
+{
+ int rc = 0;
+ struct msm_smem *handle;
+ struct internal_buf *binfo;
+ struct vidc_buffer_addr_info buffer_info;
+ u32 smem_flags = 0, buffer_size;
+ struct hal_buffer_requirements *output_buf, *extradata_buf;
+ int i;
+ struct hfi_device *hdev;
+
+ hdev = inst->core->device;
+
+ output_buf = get_buff_req_buffer(inst, buffer_type);
+ if (!output_buf) {
+ dprintk(VIDC_DBG,
+ "This output buffer not required, buffer_type: %x\n",
+ buffer_type);
+ return 0;
+ }
+ dprintk(VIDC_DBG,
+ "output: num = %d, size = %d\n",
+ output_buf->buffer_count_actual,
+ output_buf->buffer_size);
+
+ extradata_buf = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_OUTPUT);
+ if (!extradata_buf) {
+ dprintk(VIDC_DBG,
+ "This extradata buffer not required, buffer_type: %x\n",
+ buffer_type);
+ return 0;
+ }
+ dprintk(VIDC_DBG,
+ "extradata: num = %d, size = %d\n",
+ extradata_buf->buffer_count_actual,
+ extradata_buf->buffer_size);
+
+ buffer_size = output_buf->buffer_size + extradata_buf->buffer_size;
+ if (inst->flags & VIDC_SECURE)
+ smem_flags |= SMEM_SECURE;
+
+ if (output_buf->buffer_size) {
+ for (i = 0; i < output_buf->buffer_count_actual;
+ i++) {
+ handle = msm_smem_alloc(inst->mem_client,
+ buffer_size, 1, smem_flags,
+ buffer_type, 0);
+ if (!handle) {
+ dprintk(VIDC_ERR,
+ "Failed to allocate output memory\n");
+ rc = -ENOMEM;
+ goto err_no_mem;
+ }
+ rc = msm_smem_cache_operations(inst->mem_client,
+ handle, SMEM_CACHE_CLEAN);
+ if (rc) {
+ dprintk(VIDC_WARN,
+ "Failed to clean cache may cause undefined behavior\n");
+ }
+ binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
+ if (!binfo) {
+ dprintk(VIDC_ERR, "Out of memory\n");
+ rc = -ENOMEM;
+ goto fail_kzalloc;
+ }
+ mutex_lock(&inst->lock);
+ binfo->handle = handle;
+ buffer_info.buffer_size = output_buf->buffer_size;
+ buffer_info.buffer_type = buffer_type;
+ binfo->buffer_type = buffer_type;
+ buffer_info.num_buffers = 1;
+ binfo->buffer_ownership = DRIVER;
+ buffer_info.align_device_addr = handle->device_addr;
+ buffer_info.extradata_addr = handle->device_addr +
+ output_buf->buffer_size;
+ buffer_info.extradata_size = extradata_buf->buffer_size;
+ dprintk(VIDC_DBG, "Output buffer address: %x",
+ buffer_info.align_device_addr);
+ dprintk(VIDC_DBG, "Output extradata address: %x",
+ buffer_info.extradata_addr);
+ rc = call_hfi_op(hdev, session_set_buffers,
+ (void *) inst->session, &buffer_info);
+ mutex_unlock(&inst->lock);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s : session_set_buffers failed",
+ __func__);
+ goto fail_set_buffers;
+ }
+ mutex_lock(&inst->lock);
+ list_add_tail(&binfo->list, &inst->outputbufs);
+ mutex_unlock(&inst->lock);
+ }
+ }
+ return rc;
+fail_set_buffers:
+ kfree(binfo);
+fail_kzalloc:
+ msm_smem_free(inst->mem_client, handle);
+err_no_mem:
+ return rc;
+}
+
static int set_scratch_buffers(struct msm_vidc_inst *inst,
enum hal_buffer buffer_type)
{
@@ -2036,7 +2443,8 @@
frame_data.filled_len = 0;
frame_data.offset = 0;
frame_data.alloc_len = vb->v4l2_planes[0].length;
- frame_data.buffer_type = HAL_BUFFER_OUTPUT;
+ frame_data.buffer_type =
+ msm_comm_get_hal_output_buffer(inst);
extra_idx =
EXTRADATA_IDX(inst->fmts[CAPTURE_PORT]->num_planes);
if (extra_idx && (extra_idx < VIDEO_MAX_PLANES) &&
@@ -2130,6 +2538,62 @@
mutex_unlock(&inst->sync_lock);
return rc;
}
+int msm_comm_release_output_buffers(struct msm_vidc_inst *inst)
+{
+ struct msm_smem *handle;
+ struct list_head *ptr, *next;
+ struct internal_buf *buf;
+ struct vidc_buffer_addr_info buffer_info;
+ int rc = 0;
+ struct msm_vidc_core *core;
+ struct hfi_device *hdev;
+ if (!inst) {
+ dprintk(VIDC_ERR,
+ "Invalid instance pointer = %p\n", inst);
+ return -EINVAL;
+ }
+ core = inst->core;
+ if (!core) {
+ dprintk(VIDC_ERR,
+ "Invalid core pointer = %p\n", core);
+ return -EINVAL;
+ }
+ hdev = core->device;
+ if (!hdev) {
+ dprintk(VIDC_ERR, "Invalid device pointer = %p\n", hdev);
+ return -EINVAL;
+ }
+ mutex_lock(&inst->lock);
+ if (!list_empty(&inst->outputbufs)) {
+ list_for_each_safe(ptr, next, &inst->outputbufs) {
+ buf = list_entry(ptr, struct internal_buf,
+ list);
+ handle = buf->handle;
+ buffer_info.buffer_size = handle->size;
+ buffer_info.buffer_type = buf->buffer_type;
+ buffer_info.num_buffers = 1;
+ buffer_info.align_device_addr = handle->device_addr;
+ if (inst->state != MSM_VIDC_CORE_INVALID &&
+ core->state != VIDC_CORE_INVALID) {
+ buffer_info.response_required = false;
+ rc = call_hfi_op(hdev, session_release_buffers,
+ (void *)inst->session, &buffer_info);
+ if (rc)
+ dprintk(VIDC_WARN,
+ "Rel output buf fail:0x%x, %d",
+ buffer_info.align_device_addr,
+ buffer_info.buffer_size);
+ }
+ list_del(&buf->list);
+ mutex_unlock(&inst->lock);
+ msm_smem_free(inst->mem_client, buf->handle);
+ kfree(buf);
+ mutex_lock(&inst->lock);
+ }
+ }
+ mutex_unlock(&inst->lock);
+ return rc;
+}
int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst)
{
@@ -2304,6 +2768,26 @@
return rc;
}
+int msm_comm_set_output_buffers(struct msm_vidc_inst *inst)
+{
+ int rc = 0;
+ if (!inst || !inst->core || !inst->core->device) {
+ dprintk(VIDC_ERR, "%s invalid parameters", __func__);
+ return -EINVAL;
+ }
+
+ if (msm_comm_release_output_buffers(inst))
+ dprintk(VIDC_WARN, "Failed to release output buffers\n");
+
+ rc = set_output_buffers(inst, HAL_BUFFER_OUTPUT);
+ if (rc)
+ goto error;
+ return rc;
+error:
+ msm_comm_release_output_buffers(inst);
+ return rc;
+}
+
int msm_comm_set_scratch_buffers(struct msm_vidc_inst *inst)
{
int rc = 0;
@@ -2398,6 +2882,70 @@
msm_vidc_queue_v4l2_event(inst, V4L2_EVENT_MSM_VIDC_FLUSH_DONE);
return;
}
+
+void msm_comm_flush_dynamic_buffers(struct msm_vidc_inst *inst)
+{
+ struct buffer_info *binfo = NULL, *dummy = NULL;
+ struct list_head *list = NULL;
+
+ if (inst->buffer_mode_set[CAPTURE_PORT] != HAL_BUFFER_MODE_DYNAMIC)
+ return;
+
+ /*
+ * dynamic buffer mode:- if flush is called during seek
+ * driver should not queue any new buffer it has been holding.
+ *
+ * Each dynamic o/p buffer can have one of following ref_count:
+ * ref_count : 0 - f/w has released reference and sent fbd back.
+ * The buffer has been returned back to client.
+ *
+ * ref_count : 1 - f/w is holding reference. f/w may have released
+ * fbd as read_only OR fbd is pending. f/w will
+ * release reference before sending flush_done.
+ *
+ * ref_count : 2 - f/w is holding reference, f/w has released fbd as
+ * read_only, which client has queued back to driver.
+ * driver holds this buffer and will queue back
+ * only when f/w releases the reference. During
+ * flush_done, f/w will release the reference but driver
+ * should not queue back the buffer to f/w.
+ * Flush all buffers with ref_count 2.
+ */
+ mutex_lock(&inst->lock);
+ if (!list_empty(&inst->registered_bufs)) {
+ struct v4l2_event buf_event = {0};
+ u32 *ptr = NULL;
+ list = &inst->registered_bufs;
+ list_for_each_entry_safe(binfo, dummy, list, list) {
+ if (binfo &&
+ (binfo->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
+ (atomic_read(&binfo->ref_count) == 2)) {
+ atomic_dec(&binfo->ref_count);
+ buf_event.type =
+ V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER;
+ ptr = (u32 *)buf_event.u.data;
+ ptr[0] = binfo->fd[0];
+ ptr[1] = binfo->buff_off[0];
+ ptr[2] = binfo->uvaddr[0];
+ ptr[3] = (u32) binfo->timestamp.tv_sec;
+ ptr[4] = (u32) binfo->timestamp.tv_usec;
+ ptr[5] = binfo->v4l2_index;
+ dprintk(VIDC_DBG,
+ "released buffer held in driver before issuing flush: 0x%x fd[0]: %d\n",
+ binfo->device_addr[0], binfo->fd[0]);
+ /*delete this buffer info from registered list*/
+ list_del(&binfo->list);
+ kfree(binfo);
+ /*send event to client*/
+ v4l2_event_queue_fh(&inst->event_handler,
+ &buf_event);
+ wake_up(&inst->kernel_event_queue);
+ }
+ }
+ }
+ mutex_unlock(&inst->lock);
+}
+
int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags)
{
int rc = 0;
@@ -2442,6 +2990,7 @@
}
mutex_lock(&inst->sync_lock);
+ msm_comm_flush_dynamic_buffers(inst);
if (inst->in_reconfig && !ip_flush && op_flush) {
if (!list_empty(&inst->pendingq)) {
/*Execution can never reach here since port reconfig
@@ -2453,6 +3002,11 @@
}
rc = call_hfi_op(hdev, session_flush, inst->session,
HAL_FLUSH_OUTPUT);
+ if (!rc && (msm_comm_get_stream_output_mode(inst) ==
+ HAL_VIDEO_DECODER_SECONDARY))
+ rc = call_hfi_op(hdev, session_flush, inst->session,
+ HAL_FLUSH_OUTPUT2);
+
} else {
if (!list_empty(&inst->pendingq)) {
/*If flush is called after queueing buffers but before
@@ -2473,6 +3027,7 @@
kfree(temp);
}
}
+
/*Do not send flush in case of session_error */
if (!(inst->state == MSM_VIDC_CORE_INVALID &&
core->state != VIDC_CORE_INVALID))
@@ -2604,9 +3159,9 @@
if (inst->state == MSM_VIDC_OPEN_DONE) {
num_mbs_per_sec = msm_comm_get_load(inst->core,
- MSM_VIDC_DECODER);
+ MSM_VIDC_DECODER);
num_mbs_per_sec += msm_comm_get_load(inst->core,
- MSM_VIDC_ENCODER);
+ MSM_VIDC_ENCODER);
if (num_mbs_per_sec > inst->core->resources.max_load) {
dprintk(VIDC_ERR,
"H/w is overloaded. needed: %d max: %d\n",
@@ -2621,6 +3176,71 @@
return 0;
}
+
+int msm_comm_check_scaling_supported(struct msm_vidc_inst *inst)
+{
+ u32 x_min, x_max, y_min, y_max;
+ u32 input_height, input_width, output_height, output_width;
+
+ if (!inst->capability.scale_x.min || !inst->capability.scale_x.max ||
+ !inst->capability.scale_y.min ||
+ !inst->capability.scale_y.max) {
+ dprintk(VIDC_ERR, "%s : Invalid scaling ratios",
+ __func__);
+ return -ENOTSUPP;
+ }
+ x_min = (1 << 16) / inst->capability.scale_x.min;
+ y_min = (1 << 16) / inst->capability.scale_y.min;
+ x_max = inst->capability.scale_x.max >> 16;
+ y_max = inst->capability.scale_y.max >> 16;
+
+ input_height = inst->prop.height[OUTPUT_PORT];
+ input_width = inst->prop.width[OUTPUT_PORT];
+ output_height = inst->prop.height[CAPTURE_PORT];
+ output_width = inst->prop.width[CAPTURE_PORT];
+
+ if (!input_height || !input_width || !output_height || !output_width) {
+ dprintk(VIDC_ERR,
+ "Invalid : Input Height = %d Width = %d"
+ " Output Height = %d Width = %d",
+ input_height, input_width, output_height,
+ output_width);
+ return -ENOTSUPP;
+ }
+
+ if (input_height > output_height) {
+ if (input_height / output_height > x_min) {
+ dprintk(VIDC_ERR,
+ "Unsupported Height Downscale ratio %d Vs %d",
+ input_height/output_height, x_min);
+ return -ENOTSUPP;
+ }
+ } else {
+ if (input_height / output_height > x_max) {
+ dprintk(VIDC_ERR,
+ "Unsupported Height Upscale ratio %d Vs %d",
+ input_height/output_height, x_max);
+ return -ENOTSUPP;
+ }
+ }
+ if (input_width > output_width) {
+ if (input_width / output_width > y_min) {
+ dprintk(VIDC_ERR,
+ "Unsupported Width Downscale ratio %d Vs %d",
+ input_width/output_width, y_min);
+ return -ENOTSUPP;
+ }
+ } else {
+ if (input_width / output_width > y_max) {
+ dprintk(VIDC_ERR,
+ "Unsupported Width Upscale ratio %d Vs %d",
+ input_width/output_width, y_max);
+ return -ENOTSUPP;
+ }
+ }
+ return 0;
+}
+
int msm_vidc_check_session_supported(struct msm_vidc_inst *inst)
{
struct msm_vidc_core_capability *capability;
@@ -2638,14 +3258,16 @@
if (!rc && inst->capability.capability_set) {
rc = call_hfi_op(hdev, capability_check,
inst->fmts[OUTPUT_PORT]->fourcc,
- inst->prop.width, &capability->width.max,
+ inst->prop.width[CAPTURE_PORT], &capability->width.max,
&capability->height.max);
- if (!rc && (inst->prop.height * inst->prop.width >
+ if (!rc && (inst->prop.height[CAPTURE_PORT]
+ * inst->prop.width[CAPTURE_PORT] >
capability->width.max * capability->height.max)) {
dprintk(VIDC_ERR,
"Unsupported WxH = (%u)x(%u), Max supported is - (%u)x(%u)",
- inst->prop.width, inst->prop.height,
+ inst->prop.width[CAPTURE_PORT],
+ inst->prop.height[CAPTURE_PORT],
capability->width.max, capability->height.max);
rc = -ENOTSUPP;
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index c018345..195fa7e 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -31,6 +31,7 @@
enum hal_property ptype, void *pdata);
int msm_comm_set_scratch_buffers(struct msm_vidc_inst *inst);
int msm_comm_set_persist_buffers(struct msm_vidc_inst *inst);
+int msm_comm_set_output_buffers(struct msm_vidc_inst *inst);
int msm_comm_qbuf(struct vb2_buffer *vb);
void msm_comm_scale_clocks_and_bus(struct msm_vidc_inst *inst);
int msm_comm_flush(struct msm_vidc_inst *inst, u32 flags);
@@ -47,5 +48,9 @@
(V4L2_CTRL_ID2CLASS(idx) == V4L2_CTRL_CLASS_MPEG) && \
V4L2_CTRL_DRIVER_PRIV(idx))
-#endif
+int msm_comm_check_scaling_supported(struct msm_vidc_inst *inst);
int msm_comm_recover_from_session_error(struct msm_vidc_inst *inst);
+enum multi_stream msm_comm_get_stream_output_mode(struct msm_vidc_inst *inst);
+enum hal_buffer msm_comm_get_hal_output_buffer(struct msm_vidc_inst *inst);
+
+#endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_debug.c b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
index 03136ae..5a18265 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_debug.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_debug.c
@@ -36,6 +36,10 @@
__buf.filled_size = 0; \
})
+#define DYNAMIC_BUF_OWNER(__binfo) ({ \
+ atomic_read(&__binfo->ref_count) == 2 ? "video driver" : "firmware";\
+})
+
static int core_info_open(struct inode *inode, struct file *file)
{
file->private_data = inode->i_private;
@@ -82,6 +86,18 @@
write_str(&dbg_buf, "irq: %u\n",
call_hfi_op(hdev, get_fw_info, hdev->hfi_device_data,
FW_IRQ));
+ write_str(&dbg_buf, "clock count: %d\n",
+ call_hfi_op(hdev, get_info, hdev->hfi_device_data,
+ DEV_CLOCK_COUNT));
+ write_str(&dbg_buf, "clock enabled: %u\n",
+ call_hfi_op(hdev, get_info, hdev->hfi_device_data,
+ DEV_CLOCK_ENABLED));
+ write_str(&dbg_buf, "power count: %d\n",
+ call_hfi_op(hdev, get_info, hdev->hfi_device_data,
+ DEV_PWR_COUNT));
+ write_str(&dbg_buf, "power enabled: %u\n",
+ call_hfi_op(hdev, get_info, hdev->hfi_device_data,
+ DEV_PWR_ENABLED));
for (i = SYS_MSG_START; i < SYS_MSG_END; i++) {
write_str(&dbg_buf, "completions[%d]: %s\n", i,
completion_done(&core->completions[SYS_MSG_INDEX(i)]) ?
@@ -193,6 +209,37 @@
return 0;
}
+static int publish_unreleased_reference(struct msm_vidc_inst *inst)
+{
+ struct buffer_info *temp = NULL;
+ struct buffer_info *dummy = NULL;
+ struct list_head *list = NULL;
+
+ if (!inst) {
+ dprintk(VIDC_ERR, "%s: invalid param\n", __func__);
+ return -EINVAL;
+ }
+
+ list = &inst->registered_bufs;
+ mutex_lock(&inst->lock);
+ if (inst->buffer_mode_set[CAPTURE_PORT] == HAL_BUFFER_MODE_DYNAMIC) {
+ list_for_each_entry_safe(temp, dummy, list, list) {
+ if (temp && temp->type ==
+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&
+ !temp->inactive && atomic_read(&temp->ref_count)) {
+ write_str(&dbg_buf,
+ "\tpending buffer: 0x%x fd[0] = %d ref_count = %d held by: %s\n",
+ temp->device_addr[0],
+ temp->fd[0],
+ atomic_read(&temp->ref_count),
+ DYNAMIC_BUF_OWNER(temp));
+ }
+ }
+ }
+ mutex_unlock(&inst->lock);
+ return 0;
+}
+
static ssize_t inst_info_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
@@ -221,6 +268,19 @@
write_str(
&dbg_buf, "type: %s\n", inst->fmts[i]->type == OUTPUT_PORT ?
"Output" : "Capture");
+ switch (inst->buffer_mode_set[i]) {
+ case HAL_BUFFER_MODE_STATIC:
+ write_str(&dbg_buf, "buffer mode : %s\n", "static");
+ break;
+ case HAL_BUFFER_MODE_RING:
+ write_str(&dbg_buf, "buffer mode : %s\n", "ring");
+ break;
+ case HAL_BUFFER_MODE_DYNAMIC:
+ write_str(&dbg_buf, "buffer mode : %s\n", "dynamic");
+ break;
+ default:
+ write_str(&dbg_buf, "buffer mode : unsupported\n");
+ }
for (j = 0; j < inst->fmts[i]->num_planes; j++)
write_str(&dbg_buf, "size for plane %d: %u\n", j,
inst->bufq[i].vb2_bufq.plane_sizes[j]);
@@ -235,6 +295,8 @@
write_str(&dbg_buf, "EBD Count: %d\n", inst->count.ebd);
write_str(&dbg_buf, "FTB Count: %d\n", inst->count.ftb);
write_str(&dbg_buf, "FBD Count: %d\n", inst->count.fbd);
+ publish_unreleased_reference(inst);
+
return simple_read_from_buffer(buf, count, ppos,
dbg_buf.ptr, dbg_buf.filled_size);
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 15f4e3f..2b1471c 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -14,7 +14,9 @@
#ifndef _MSM_VIDC_INTERNAL_H_
#define _MSM_VIDC_INTERNAL_H_
+#include <linux/atomic.h>
#include <linux/list.h>
+#include <linux/time.h>
#include <linux/types.h>
#include <linux/completion.h>
#include <linux/wait.h>
@@ -98,10 +100,18 @@
struct vb2_buffer *buf;
};
+enum buffer_owner {
+ DRIVER,
+ FIRMWARE,
+ CLIENT,
+ MAX_OWNER
+};
+
struct internal_buf {
struct list_head list;
enum hal_buffer buffer_type;
struct msm_smem *handle;
+ enum buffer_owner buffer_ownership;
};
struct msm_vidc_format {
@@ -126,8 +136,8 @@
};
struct session_prop {
- u32 width;
- u32 height;
+ u32 width[MAX_PORT_NUM];
+ u32 height[MAX_PORT_NUM];
u32 fps;
u32 bitrate;
};
@@ -177,7 +187,11 @@
struct hal_capability_supported width;
struct hal_capability_supported height;
struct hal_capability_supported frame_rate;
+ u32 pixelprocess_capabilities;
+ struct hal_capability_supported scale_x;
+ struct hal_capability_supported scale_y;
u32 capability_set;
+ enum buffer_mode_type buffer_mode[MAX_PORT_NUM];
};
struct msm_vidc_core {
@@ -208,6 +222,7 @@
struct list_head pendingq;
struct list_head internalbufs;
struct list_head persistbufs;
+ struct list_head outputbufs;
struct buffer_requirements buff_req;
void *mem_client;
struct v4l2_ctrl_handler ctrl_handler;
@@ -226,7 +241,11 @@
struct msm_vidc_debug debug;
struct buf_count count;
enum msm_vidc_modes flags;
+ u32 multi_stream_mode;
struct msm_vidc_core_capability capability;
+ enum buffer_mode_type buffer_mode_set[MAX_PORT_NUM];
+ struct list_head registered_bufs;
+ bool map_output_buffer;
};
extern struct msm_vidc_drv *vidc_driver;
@@ -256,4 +275,35 @@
int msm_vidc_check_session_supported(struct msm_vidc_inst *inst);
void msm_vidc_queue_v4l2_event(struct msm_vidc_inst *inst, int event_type);
+struct buffer_info {
+ struct list_head list;
+ int type;
+ int num_planes;
+ int fd[VIDEO_MAX_PLANES];
+ int buff_off[VIDEO_MAX_PLANES];
+ int size[VIDEO_MAX_PLANES];
+ u32 uvaddr[VIDEO_MAX_PLANES];
+ u32 device_addr[VIDEO_MAX_PLANES];
+ struct msm_smem *handle[VIDEO_MAX_PLANES];
+ enum v4l2_memory memory;
+ u32 v4l2_index;
+ bool pending_deletion;
+ atomic_t ref_count;
+ bool dequeued;
+ bool inactive;
+ bool mapped[VIDEO_MAX_PLANES];
+ int same_fd_ref[VIDEO_MAX_PLANES];
+ struct timeval timestamp;
+};
+
+struct buffer_info *device_to_uvaddr(struct msm_vidc_inst *inst,
+ struct list_head *list, u32 device_addr);
+int buf_ref_get(struct msm_vidc_inst *inst, struct buffer_info *binfo);
+int buf_ref_put(struct msm_vidc_inst *inst, struct buffer_info *binfo);
+int output_buffer_cache_invalidate(struct msm_vidc_inst *inst,
+ struct buffer_info *binfo);
+int qbuf_dynamic_buf(struct msm_vidc_inst *inst,
+ struct buffer_info *binfo);
+int unmap_and_deregister_buf(struct msm_vidc_inst *inst,
+ struct buffer_info *binfo);
#endif
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index a5aebd5..916df1d 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -23,6 +23,7 @@
#include <mach/ocmem.h>
#include <mach/scm.h>
#include <mach/subsystem_restart.h>
+#include <mach/msm_smem.h>
#include <asm/memory.h>
#include "hfi_packetization.h"
#include "venus_hfi.h"
@@ -829,6 +830,7 @@
}
}
device->clocks_enabled = 1;
+ ++device->clk_cnt;
return 0;
fail_clk_enable:
for (i--; i >= 0; i--) {
@@ -858,6 +860,7 @@
clk_disable(cl->clk);
}
device->clocks_enabled = 0;
+ --device->clk_cnt;
}
static DECLARE_COMPLETION(pc_prep_done);
@@ -899,6 +902,7 @@
venus_hfi_unvote_buses(device, DDR_MEM);
device->power_enabled = 0;
+ --device->pwr_cnt;
already_disabled:
return rc;
}
@@ -949,6 +953,7 @@
goto err_reset_core;
}
device->power_enabled = 1;
+ ++device->pwr_cnt;
return rc;
err_reset_core:
venus_hfi_tzbsp_set_video_state(TZBSP_VIDEO_STATE_SUSPEND);
@@ -2711,6 +2716,7 @@
clk_unprepare(cl->clk);
}
device->clocks_enabled = 0;
+ --device->clk_cnt;
mutex_unlock(&device->clk_pwr_lock);
}
static inline int venus_hfi_enable_clks(struct venus_hfi_device *device)
@@ -2736,6 +2742,7 @@
}
}
device->clocks_enabled = 1;
+ ++device->clk_cnt;
mutex_unlock(&device->clk_pwr_lock);
return rc;
fail_clk_enable:
@@ -3206,6 +3213,7 @@
goto fail_load_fw;
}
device->power_enabled = 1;
+ ++device->pwr_cnt;
mutex_unlock(&device->clk_pwr_lock);
/*Clocks can be enabled only after pil_get since
* gdsc is turned-on in pil_get*/
@@ -3231,6 +3239,7 @@
device->resources.fw.cookie = NULL;
regulator_disable(device->gdsc);
device->power_enabled = 0;
+ --device->pwr_cnt;
mutex_unlock(&device->clk_pwr_lock);
fail_enable_gdsc:
venus_hfi_iommu_detach(device);
@@ -3254,6 +3263,7 @@
subsystem_put(device->resources.fw.cookie);
regulator_disable(device->gdsc);
device->power_enabled = 0;
+ --device->pwr_cnt;
mutex_unlock(&device->clk_pwr_lock);
venus_hfi_interface_queues_release(dev);
venus_hfi_iommu_detach(device);
@@ -3295,6 +3305,37 @@
return rc;
}
+static int venus_hfi_get_info(void *dev, enum dev_info info)
+{
+ int rc = 0;
+ struct venus_hfi_device *device = dev;
+ if (!device) {
+ dprintk(VIDC_ERR, "%s Invalid parameter: %p\n",
+ __func__, device);
+ return -EINVAL;
+ }
+
+ mutex_lock(&device->clk_pwr_lock);
+ switch (info) {
+ case DEV_CLOCK_COUNT:
+ rc = device->clk_cnt;
+ break;
+ case DEV_CLOCK_ENABLED:
+ rc = device->clocks_enabled;
+ break;
+ case DEV_PWR_COUNT:
+ rc = device->pwr_cnt;
+ break;
+ case DEV_PWR_ENABLED:
+ rc = device->power_enabled;
+ break;
+ default:
+ dprintk(VIDC_ERR, "Invalid device info requested");
+ }
+ mutex_unlock(&device->clk_pwr_lock);
+ return rc;
+}
+
int venus_hfi_get_stride_scanline(int color_fmt,
int width, int height, int *stride, int *scanlines) {
*stride = VENUS_Y_STRIDE(color_fmt, width);
@@ -3302,6 +3343,44 @@
return 0;
}
+int venus_hfi_get_core_capabilities(void)
+{
+ int i = 0, rc = 0, j = 0, venus_version_length = 0;
+ u32 smem_block_size = 0;
+ u8 *smem_table_ptr;
+ char version[256];
+ const u32 version_string_size = 128;
+ char venus_version[] = "VIDEO.VE.1.4";
+ u8 version_info[256];
+ const u32 smem_image_index_venus = 14 * 128;
+ /* Venus version is stored at 14th entry in smem table */
+
+ smem_table_ptr = smem_get_entry(SMEM_IMAGE_VERSION_TABLE,
+ &smem_block_size);
+ if (smem_table_ptr &&
+ ((smem_image_index_venus + version_string_size) <=
+ smem_block_size))
+ memcpy(version_info, smem_table_ptr + smem_image_index_venus,
+ version_string_size);
+
+ while (version_info[i++] != 'V' && i < version_string_size)
+ ;
+
+ venus_version_length = strlen(venus_version);
+ for (i--, j = 0; i < version_string_size && j < venus_version_length;
+ i++)
+ version[j++] = version_info[i];
+ version[venus_version_length] = '\0';
+ dprintk(VIDC_DBG, "F/W version retrieved : %s\n", version);
+
+ if (strcmp((const char *)version, (const char *)venus_version) == 0)
+ rc = HAL_VIDEO_ENCODER_ROTATION_CAPABILITY |
+ HAL_VIDEO_ENCODER_SCALING_CAPABILITY |
+ HAL_VIDEO_ENCODER_DEINTERLACE_CAPABILITY |
+ HAL_VIDEO_DECODER_MULTI_STREAM_CAPABILITY;
+ return rc;
+}
+
int venus_hfi_capability_check(u32 fourcc, u32 width,
u32 *max_width, u32 *max_height)
{
@@ -3351,6 +3430,10 @@
hdevice->device_id = device_id;
hdevice->callback = callback;
+ hdevice->clocks_enabled = 0;
+ hdevice->clk_cnt = 0;
+ hdevice->power_enabled = 0;
+ hdevice->pwr_cnt = 0;
hdevice->vidc_workq = create_singlethread_workqueue(
"msm_vidc_workerq_venus");
@@ -3472,8 +3555,10 @@
hdev->load_fw = venus_hfi_load_fw;
hdev->unload_fw = venus_hfi_unload_fw;
hdev->get_fw_info = venus_hfi_get_fw_info;
+ hdev->get_info = venus_hfi_get_info;
hdev->get_stride_scanline = venus_hfi_get_stride_scanline;
hdev->capability_check = venus_hfi_capability_check;
+ hdev->get_core_capabilities = venus_hfi_get_core_capabilities;
}
int venus_hfi_initialize(struct hfi_device *hdev, u32 device_id,
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h
index f1d8694..4feda45 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.h
+++ b/drivers/media/platform/msm/vidc/venus_hfi.h
@@ -207,6 +207,8 @@
u32 register_base;
u32 register_size;
u32 irq;
+ int clk_cnt;
+ int pwr_cnt;
struct venus_resources resources;
struct msm_vidc_platform_resources *res;
struct regulator *gdsc;
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index 5059273..70b93ff0 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -19,6 +19,7 @@
#define HFI_EVENT_SESSION_SEQUENCE_CHANGED (HFI_OX_BASE + 0x3)
#define HFI_EVENT_SESSION_PROPERTY_CHANGED (HFI_OX_BASE + 0x4)
+#define HFI_EVENT_RELEASE_BUFFER_REFERENCE (HFI_OX_BASE + 0x6)
#define HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUFFER_RESOURCES \
(HFI_OX_BASE + 0x1)
@@ -60,6 +61,7 @@
#define HFI_BUFFER_MODE_STATIC (HFI_OX_BASE + 0x1)
#define HFI_BUFFER_MODE_RING (HFI_OX_BASE + 0x2)
+#define HFI_BUFFER_MODE_DYNAMIC (HFI_OX_BASE + 0x3)
#define HFI_FLUSH_INPUT (HFI_OX_BASE + 0x1)
#define HFI_FLUSH_OUTPUT (HFI_OX_BASE + 0x2)
@@ -137,6 +139,10 @@
(HFI_PROPERTY_PARAM_OX_START + 0x008)
#define HFI_PROPERTY_PARAM_S3D_FRAME_PACKING_EXTRADATA \
(HFI_PROPERTY_PARAM_OX_START + 0x009)
+#define HFI_PROPERTY_PARAM_ERR_DETECTION_CODE_EXTRADATA \
+ (HFI_PROPERTY_PARAM_OX_START + 0x00A)
+#define HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED \
+ (HFI_PROPERTY_PARAM_OX_START + 0x00B)
#define HFI_PROPERTY_CONFIG_OX_START \
(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_OX_OFFSET + 0x02000)
@@ -278,6 +284,12 @@
u32 format;
};
+struct hfi_buffer_alloc_mode_supported {
+ u32 buffer_type;
+ u32 num_entries;
+ u32 rg_data[1];
+};
+
struct hfi_mb_error_map {
u32 error_map_size;
u8 rg_error_map[1];
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index b600d64..cc07806 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -186,6 +186,22 @@
HAL_UNUSED_DOMAIN = 0x10000000,
};
+enum multi_stream {
+ HAL_VIDEO_DECODER_NONE = 0x00000000,
+ HAL_VIDEO_DECODER_PRIMARY = 0x00000001,
+ HAL_VIDEO_DECODER_SECONDARY = 0x00000002,
+ HAL_VIDEO_DECODER_BOTH_OUTPUTS = 0x00000004,
+ HAL_VIDEO_UNUSED_OUTPUTS = 0x10000000,
+};
+
+enum hal_core_capabilities {
+ HAL_VIDEO_ENCODER_ROTATION_CAPABILITY = 0x00000001,
+ HAL_VIDEO_ENCODER_SCALING_CAPABILITY = 0x00000002,
+ HAL_VIDEO_ENCODER_DEINTERLACE_CAPABILITY = 0x00000004,
+ HAL_VIDEO_DECODER_MULTI_STREAM_CAPABILITY = 0x00000008,
+ HAL_VIDEO_UNUSED_CAPABILITY = 0x10000000,
+};
+
enum hal_video_codec {
HAL_VIDEO_CODEC_UNKNOWN = 0x00000000,
HAL_VIDEO_CODEC_MVC = 0x00000001,
@@ -864,12 +880,14 @@
enum hal_event_type {
HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES,
HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES,
+ HAL_EVENT_RELEASE_BUFFER_REFERENCE,
HAL_UNUSED_SEQCHG = 0x10000000,
};
enum buffer_mode_type {
- HAL_BUFFER_MODE_STATIC = 0x00000000,
- HAL_BUFFER_MODE_RING,
+ HAL_BUFFER_MODE_STATIC = 0x001,
+ HAL_BUFFER_MODE_RING = 0x010,
+ HAL_BUFFER_MODE_DYNAMIC = 0x100,
};
struct hal_buffer_alloc_mode {
@@ -931,6 +949,8 @@
u32 height;
u32 width;
u32 hal_event_type;
+ u8 *packet_buffer;
+ u8 *exra_data_buffer;
};
/* Data callback structure */
@@ -1014,10 +1034,9 @@
struct hal_uncompressed_format_supported uncomp_format;
struct hal_interlace_format_supported HAL_format;
struct hal_nal_stream_format_supported nal_stream_format;
-/* struct hal_profile_level_supported profile_level;
- // allocate and released memory for above. */
struct hal_intra_refresh intra_refresh;
struct hal_seq_header_info seq_hdr_info;
+ enum buffer_mode_type alloc_mode_out;
};
struct buffer_requirements {
@@ -1042,6 +1061,14 @@
FW_INFO_MAX,
};
+enum dev_info {
+ DEV_CLOCK_COUNT,
+ DEV_CLOCK_ENABLED,
+ DEV_PWR_COUNT,
+ DEV_PWR_ENABLED,
+ DEV_INFO_MAX
+};
+
#define call_hfi_op(q, op, args...) \
(((q) && (q)->op) ? ((q)->op(args)) : 0)
@@ -1095,11 +1122,13 @@
int (*load_fw)(void *dev);
void (*unload_fw)(void *dev);
int (*get_fw_info)(void *dev, enum fw_info info);
+ int (*get_info) (void *dev, enum dev_info info);
int (*get_stride_scanline)(int color_fmt, int width,
int height, int *stride, int *scanlines);
int (*capability_check)(u32 fourcc, u32 width,
u32 *max_width, u32 *max_height);
int (*session_clean)(void *sess);
+ int (*get_core_capabilities)(void);
};
typedef void (*hfi_cmd_response_callback) (enum command_response cmd,
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index b5c431e..1916e9f 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -64,7 +64,12 @@
#define HFI_ERR_SESSION_STREAM_CORRUPT (HFI_COMMON_BASE + 0x100B)
#define HFI_ERR_SESSION_ENC_OVERFLOW (HFI_COMMON_BASE + 0x100C)
-#define HFI_ERR_SESSION_UNSUPPORTED_STREAM (HFI_COMMON_BASE + 0x100D)
+#define HFI_ERR_SESSION_UNSUPPORTED_STREAM (HFI_COMMON_BASE + 0x100D)
+#define HFI_ERR_SESSION_CMDSIZE (HFI_COMMON_BASE + 0x100E)
+#define HFI_ERR_SESSION_UNSUPPORT_CMD (HFI_COMMON_BASE + 0x100F)
+#define HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE (HFI_COMMON_BASE + 0x1010)
+#define HFI_ERR_SESSION_BUFFERCOUNT_TOOSMALL (HFI_COMMON_BASE + 0x1011)
+#define HFI_ERR_SESSION_INVALID_SCALE_FACTOR (HFI_COMMON_BASE + 0x1012)
#define HFI_EVENT_SYS_ERROR (HFI_COMMON_BASE + 0x1)
#define HFI_EVENT_SESSION_ERROR (HFI_COMMON_BASE + 0x2)
@@ -433,6 +438,11 @@
u32 idr_period;
};
+struct hfi_operations_type {
+ u32 rotation;
+ u32 flip;
+};
+
struct hfi_max_num_b_frames {
u32 max_num_b_frames;
};
@@ -844,6 +854,12 @@
u32 rg_ext_event_data[1];
};
+struct hfi_msg_release_buffer_ref_event_packet {
+ u8 *packet_buffer;
+ u8 *exra_data_buffer;
+ u32 output_tag;
+};
+
struct hfi_msg_sys_init_done_packet {
u32 size;
u32 packet_type;
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 5e056be..31d03b6 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -49,11 +49,15 @@
static char utf_8_flag;
static char rt_ert_flag;
static char formatting_dir;
+static unsigned char sig_blend = CTRL_ON;
static DEFINE_MUTEX(iris_fm);
module_param(rds_buf, uint, 0);
MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
+module_param(sig_blend, byte, S_IWUSR | S_IRUGO);
+MODULE_PARM_DESC(sig_blend, "signal blending switch: 0:OFF 1:ON");
+
static void radio_hci_cmd_task(unsigned long arg);
static void radio_hci_rx_task(unsigned long arg);
static struct video_device *video_get_dev(void);
@@ -4141,7 +4145,7 @@
}
radio->stereo_mode.stereo_mode = CTRL_OFF;
- radio->stereo_mode.sig_blend = CTRL_ON;
+ radio->stereo_mode.sig_blend = sig_blend;
radio->stereo_mode.intf_blend = CTRL_ON;
radio->stereo_mode.most_switch = CTRL_ON;
retval = hci_set_fm_stereo_mode(&radio->stereo_mode,
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 4a8d974..7e4ceb3 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -597,6 +597,8 @@
case V4L2_CID_MPEG_VIDC_VIDEO_CIR_MBS: return "Intra Refresh CIR MBS";
case V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL:
return "VP8 Profile Level";
+ case V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE:
+ return "Deinterlace for encoder";
/* CAMERA controls */
/* Keep the order of the 'case's the same as in videodev2.h! */
@@ -806,6 +808,16 @@
*min = 0;
*max = *step = 1;
break;
+ case V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE:
+ *type = V4L2_CTRL_TYPE_BOOLEAN;
+ *min = 0;
+ *max = *step = 1;
+ break;
+ case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE:
+ *type = V4L2_CTRL_TYPE_BOOLEAN;
+ *min = 0;
+ *max = *step = 1;
+ break;
default:
*type = V4L2_CTRL_TYPE_INTEGER;
break;
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 317c6a9..907ce7c 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -544,8 +544,10 @@
{WCD9XXX_IRQ_PA2_STARTUP, false},
{WCD9XXX_IRQ_PA3_STARTUP, false},
{WCD9XXX_IRQ_PA4_STARTUP, false},
+ {WCD9306_IRQ_HPH_PA_OCPR_FAULT, false},
{WCD9XXX_IRQ_PA5_STARTUP, false},
{WCD9XXX_IRQ_MICBIAS1_PRECHARGE, false},
+ {WCD9306_IRQ_HPH_PA_OCPL_FAULT, false},
{WCD9XXX_IRQ_MICBIAS2_PRECHARGE, false},
{WCD9XXX_IRQ_MICBIAS3_PRECHARGE, false},
{WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, false},
@@ -1451,23 +1453,23 @@
dev_err(dev, "Looking up %s property in node %s failed",
"qcom,cdc-dmic-sample-rate",
dev->of_node->full_name);
- dmic_sample_rate = TAIKO_DMIC_SAMPLE_RATE_UNDEFINED;
+ dmic_sample_rate = WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED;
}
- if (pdata->mclk_rate == TAIKO_MCLK_CLK_9P6HZ) {
- if ((dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_2P4MHZ) &&
- (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_3P2MHZ) &&
- (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_4P8MHZ) &&
- (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_UNDEFINED)) {
+ if (pdata->mclk_rate == WCD9XXX_MCLK_CLK_9P6HZ) {
+ if ((dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ) &&
+ (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_3P2MHZ) &&
+ (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ) &&
+ (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED)) {
dev_err(dev, "Invalid dmic rate %d for mclk %d\n",
dmic_sample_rate, pdata->mclk_rate);
ret = -EINVAL;
goto err;
}
- } else if (pdata->mclk_rate == TAIKO_MCLK_CLK_12P288MHZ) {
- if ((dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_3P072MHZ) &&
- (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_4P096MHZ) &&
- (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_6P144MHZ) &&
- (dmic_sample_rate != TAIKO_DMIC_SAMPLE_RATE_UNDEFINED)) {
+ } else if (pdata->mclk_rate == WCD9XXX_MCLK_CLK_12P288MHZ) {
+ if ((dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_3P072MHZ) &&
+ (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ) &&
+ (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_6P144MHZ) &&
+ (dmic_sample_rate != WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED)) {
dev_err(dev, "Invalid dmic rate %d for mclk %d\n",
dmic_sample_rate, pdata->mclk_rate);
ret = -EINVAL;
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
index dc32efd..9209f0b 100644
--- a/drivers/mfd/wcd9xxx-irq.c
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -150,13 +150,15 @@
msm_cpuidle_get_deep_idle_latency());
}
mutex_unlock(&wcd9xxx_res->pm_lock);
- os = wcd9xxx_pm_cmpxchg(wcd9xxx_res,
- WCD9XXX_PM_SLEEPABLE,
- WCD9XXX_PM_AWAKE);
+
if (!wait_event_timeout(wcd9xxx_res->pm_wq,
- (os == WCD9XXX_PM_SLEEPABLE ||
- os == WCD9XXX_PM_AWAKE),
- msecs_to_jiffies(WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS))) {
+ ((os = wcd9xxx_pm_cmpxchg(wcd9xxx_res,
+ WCD9XXX_PM_SLEEPABLE,
+ WCD9XXX_PM_AWAKE)) ==
+ WCD9XXX_PM_SLEEPABLE ||
+ (os == WCD9XXX_PM_AWAKE)),
+ msecs_to_jiffies(
+ WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS))) {
pr_warn("%s: system didn't resume within %dms, s %d, w %d\n",
__func__,
WCD9XXX_SYSTEM_RESUME_TIMEOUT_MS, wcd9xxx_res->pm_state,
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 58703cf..a30607c 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -314,7 +314,6 @@
return ret;
}
data->listener.id = 0;
- data->type = QSEECOM_LISTENER_SERVICE;
if (!__qseecom_is_svc_unique(data, &rcvd_lstnr)) {
pr_err("Service is not unique and is already registered\n");
data->released = true;
@@ -432,9 +431,15 @@
uint32_t len;
/* Copy the relevant information needed for loading the image */
- if (__copy_from_user(&req, (void __user *)argp, sizeof(req)))
+ if (copy_from_user(&req, (void __user *)argp, sizeof(req)))
return -EFAULT;
+ if ((req.ifd_data_fd <= 0) || (req.virt_sb_base == 0) ||
+ (req.sb_len == 0)) {
+ pr_err("Inavlid input(s)ion_fd(%d), sb_len(%d), vaddr(0x%x)\n",
+ req.ifd_data_fd, req.sb_len, req.virt_sb_base);
+ return -EFAULT;
+ }
/* Get the handle of the shared fd */
data->client.ihandle = ion_import_dma_buf(qseecom.ion_clnt,
req.ifd_data_fd);
@@ -605,7 +610,7 @@
struct qseecom_load_app_ireq load_req;
/* Copy the relevant information needed for loading the image */
- if (__copy_from_user(&load_img_req,
+ if (copy_from_user(&load_img_req,
(void __user *)argp,
sizeof(struct qseecom_load_img_req))) {
pr_err("copy_from_user failed\n");
@@ -616,6 +621,7 @@
if (ret)
pr_warning("Unable to vote for SFPB clock");
req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
+ load_img_req.img_name[MAX_APP_NAME_SIZE-1] = '\0';
memcpy(req.app_name, load_img_req.img_name, MAX_APP_NAME_SIZE);
ret = __qseecom_check_app_exists(req);
@@ -876,7 +882,7 @@
struct qseecom_send_svc_cmd_req req;
/*struct qseecom_command_scm_resp resp;*/
- if (__copy_from_user(&req,
+ if (copy_from_user(&req,
(void __user *)argp,
sizeof(req))) {
pr_err("copy_from_user failed\n");
@@ -888,8 +894,6 @@
return -EINVAL;
}
- data->type = QSEECOM_SECURE_SERVICE;
-
switch (req.cmd_id) {
case QSEOS_RPMB_PROVISION_KEY_COMMAND:
case QSEOS_RPMB_ERASE_COMMAND:
@@ -901,6 +905,18 @@
pr_err("Unsupported cmd_id %d\n", req.cmd_id);
return -EINVAL;
}
+
+ ret = qsee_vote_for_clock(data, CLK_DFAB);
+ if (ret) {
+ pr_err("Failed to vote for DFAB clock%d\n", ret);
+ return ret;
+ }
+ ret = qsee_vote_for_clock(data, CLK_SFPB);
+ if (ret) {
+ pr_err("Failed to vote for SFPB clock%d\n", ret);
+ goto exit_reset_dfab_freq;
+ }
+
msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle,
data->client.sb_virt, data->client.sb_length,
ION_IOC_CLEAN_INV_CACHES);
@@ -912,7 +928,7 @@
ION_IOC_INV_CACHES);
if (ret) {
pr_err("qseecom_scm_call failed with err: %d\n", ret);
- return ret;
+ goto exit_reset_sdfab_freq;
}
switch (resp.result) {
@@ -935,8 +951,11 @@
ret = -EINVAL;
break;
}
+exit_reset_sdfab_freq:
+ qsee_disable_clock_vote(data, CLK_SFPB);
+exit_reset_dfab_freq:
+ qsee_disable_clock_vote(data, CLK_DFAB);
return ret;
-
}
static int __qseecom_send_cmd(struct qseecom_dev_handle *data,
@@ -951,9 +970,22 @@
pr_err("cmd buffer or response buffer is null\n");
return -EINVAL;
}
+ if (((uint32_t)req->cmd_req_buf < data->client.user_virt_sb_base) ||
+ ((uint32_t)req->cmd_req_buf >= (data->client.user_virt_sb_base +
+ data->client.sb_length))) {
+ pr_err("cmd buffer address not within shared bufffer\n");
+ return -EINVAL;
+ }
- if (req->cmd_req_len <= 0 ||
- req->resp_len <= 0 ||
+
+ if (((uint32_t)req->resp_buf < data->client.user_virt_sb_base) ||
+ ((uint32_t)req->resp_buf >= (data->client.user_virt_sb_base +
+ data->client.sb_length))){
+ pr_err("response buffer address not within shared bufffer\n");
+ return -EINVAL;
+ }
+
+ if ((req->cmd_req_len == 0) || (req->resp_len == 0) ||
req->cmd_req_len > data->client.sb_length ||
req->resp_len > data->client.sb_length) {
pr_err("cmd buffer length or "
@@ -961,6 +993,11 @@
return -EINVAL;
}
+ if (req->cmd_req_len > UINT_MAX - req->resp_len) {
+ pr_err("Integer overflow detected in req_len & rsp_len, exiting now\n");
+ return -EINVAL;
+ }
+
reqd_len_sb_in = req->cmd_req_len + req->resp_len;
if (reqd_len_sb_in > data->client.sb_length) {
pr_debug("Not enough memory to fit cmd_buf and "
@@ -980,7 +1017,7 @@
msm_ion_do_cache_op(qseecom.ion_clnt, data->client.ihandle,
data->client.sb_virt,
- (req->cmd_req_len + req->resp_len),
+ reqd_len_sb_in,
ION_IOC_CLEAN_INV_CACHES);
ret = scm_call(SCM_SVC_TZSCHEDULER, 1, (const void *) &send_data_req,
@@ -1186,6 +1223,7 @@
void __user *argp)
{
int ret = 0;
+ int i;
struct qseecom_send_modfd_cmd_req req;
struct qseecom_send_cmd_req send_cmd_req;
@@ -1199,6 +1237,14 @@
send_cmd_req.resp_buf = req.resp_buf;
send_cmd_req.resp_len = req.resp_len;
+ /* validate offsets */
+ for (i = 0; i < MAX_ION_FD; i++) {
+ if (req.ifd_data[i].cmd_buf_offset >= req.cmd_req_len) {
+ pr_err("Invalid offset %d = 0x%x\n",
+ i, req.ifd_data[i].cmd_buf_offset);
+ return -EINVAL;
+ }
+ }
ret = __qseecom_update_cmd_buf(&req, false, data, false);
if (ret)
return ret;
@@ -1789,11 +1835,20 @@
void __user *argp)
{
struct qseecom_send_modfd_listener_resp resp;
+ int i;
if (copy_from_user(&resp, argp, sizeof(resp))) {
pr_err("copy_from_user failed");
return -EINVAL;
}
+ /* validate offsets */
+ for (i = 0; i < MAX_ION_FD; i++) {
+ if (resp.ifd_data[i].cmd_buf_offset >= resp.resp_len) {
+ pr_err("Invalid offset %d = 0x%x\n",
+ i, resp.ifd_data[i].cmd_buf_offset);
+ return -EINVAL;
+ }
+ }
__qseecom_update_cmd_buf(&resp, false, data, true);
qseecom.send_resp_flag = 1;
wake_up_interruptible(&qseecom.send_resp_wq);
@@ -2072,7 +2127,7 @@
struct qseecom_command_scm_resp resp;
/* Copy the relevant information needed for loading the image */
- if (__copy_from_user(&load_img_req,
+ if (copy_from_user(&load_img_req,
(void __user *)argp,
sizeof(struct qseecom_load_img_req))) {
pr_err("copy_from_user failed\n");
@@ -2234,7 +2289,7 @@
unsigned long flags = 0;
/* Copy the relevant information needed for loading the image */
- if (__copy_from_user(&query_req,
+ if (copy_from_user(&query_req,
(void __user *)argp,
sizeof(struct qseecom_qseos_app_load_query))) {
pr_err("copy_from_user failed\n");
@@ -2242,6 +2297,7 @@
}
req.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
+ query_req.app_name[MAX_APP_NAME_SIZE-1] = '\0';
memcpy(req.app_name, query_req.app_name, MAX_APP_NAME_SIZE);
ret = __qseecom_check_app_exists(req);
@@ -2663,8 +2719,15 @@
switch (cmd) {
case QSEECOM_IOCTL_REGISTER_LISTENER_REQ: {
+ if (data->type != QSEECOM_GENERIC) {
+ pr_err("reg lstnr req: invalid handle (%d)\n",
+ data->type);
+ ret = -EINVAL;
+ break;
+ }
pr_debug("ioctl register_listener_req()\n");
atomic_inc(&data->ioctl_count);
+ data->type = QSEECOM_LISTENER_SERVICE;
ret = qseecom_register_listener(data, argp);
atomic_dec(&data->ioctl_count);
wake_up_all(&data->abort_wq);
@@ -2673,6 +2736,13 @@
break;
}
case QSEECOM_IOCTL_UNREGISTER_LISTENER_REQ: {
+ if ((data->listener.id == 0) ||
+ (data->type != QSEECOM_LISTENER_SERVICE)) {
+ pr_err("unreg lstnr req: invalid handle (%d) lid(%d)\n",
+ data->type, data->listener.id);
+ ret = -EINVAL;
+ break;
+ }
pr_debug("ioctl unregister_listener_req()\n");
atomic_inc(&data->ioctl_count);
ret = qseecom_unregister_listener(data);
@@ -2683,6 +2753,13 @@
break;
}
case QSEECOM_IOCTL_SEND_CMD_REQ: {
+ if ((data->client.app_id == 0) ||
+ (data->type != QSEECOM_CLIENT_APP)) {
+ pr_err("send cmd req: invalid handle (%d) app_id(%d)\n",
+ data->type, data->client.app_id);
+ ret = -EINVAL;
+ break;
+ }
/* Only one client allowed here at a time */
mutex_lock(&app_access_lock);
atomic_inc(&data->ioctl_count);
@@ -2695,6 +2772,13 @@
break;
}
case QSEECOM_IOCTL_SEND_MODFD_CMD_REQ: {
+ if ((data->client.app_id == 0) ||
+ (data->type != QSEECOM_CLIENT_APP)) {
+ pr_err("send mdfd cmd: invalid handle (%d) appid(%d)\n",
+ data->type, data->client.app_id);
+ ret = -EINVAL;
+ break;
+ }
/* Only one client allowed here at a time */
mutex_lock(&app_access_lock);
atomic_inc(&data->ioctl_count);
@@ -2707,6 +2791,13 @@
break;
}
case QSEECOM_IOCTL_RECEIVE_REQ: {
+ if ((data->listener.id == 0) ||
+ (data->type != QSEECOM_LISTENER_SERVICE)) {
+ pr_err("receive req: invalid handle (%d), lid(%d)\n",
+ data->type, data->listener.id);
+ ret = -EINVAL;
+ break;
+ }
atomic_inc(&data->ioctl_count);
ret = qseecom_receive_req(data);
atomic_dec(&data->ioctl_count);
@@ -2716,6 +2807,13 @@
break;
}
case QSEECOM_IOCTL_SEND_RESP_REQ: {
+ if ((data->listener.id == 0) ||
+ (data->type != QSEECOM_LISTENER_SERVICE)) {
+ pr_err("send resp req: invalid handle (%d), lid(%d)\n",
+ data->type, data->listener.id);
+ ret = -EINVAL;
+ break;
+ }
atomic_inc(&data->ioctl_count);
ret = qseecom_send_resp();
atomic_dec(&data->ioctl_count);
@@ -2725,6 +2823,15 @@
break;
}
case QSEECOM_IOCTL_SET_MEM_PARAM_REQ: {
+ if ((data->type != QSEECOM_CLIENT_APP) &&
+ (data->type != QSEECOM_GENERIC) &&
+ (data->type != QSEECOM_SECURE_SERVICE)) {
+ pr_err("set mem param req: invalid handle (%d)\n",
+ data->type);
+ ret = -EINVAL;
+ break;
+ }
+ pr_debug("SET_MEM_PARAM: qseecom addr = 0x%x\n", (u32)data);
ret = qseecom_set_client_mem_param(data, argp);
if (ret)
pr_err("failed Qqseecom_set_mem_param request: %d\n",
@@ -2732,6 +2839,15 @@
break;
}
case QSEECOM_IOCTL_LOAD_APP_REQ: {
+ if ((data->type != QSEECOM_GENERIC) &&
+ (data->type != QSEECOM_CLIENT_APP)) {
+ pr_err("load app req: invalid handle (%d)\n",
+ data->type);
+ ret = -EINVAL;
+ break;
+ }
+ data->type = QSEECOM_CLIENT_APP;
+ pr_debug("LOAD_APP_REQ: qseecom_addr = 0x%x\n", (u32)data);
mutex_lock(&app_access_lock);
atomic_inc(&data->ioctl_count);
if (qseecom.qsee_version > QSEEE_VERSION_00) {
@@ -2750,6 +2866,14 @@
break;
}
case QSEECOM_IOCTL_UNLOAD_APP_REQ: {
+ if ((data->client.app_id == 0) ||
+ (data->type != QSEECOM_CLIENT_APP)) {
+ pr_err("unload app req:invalid handle(%d) app_id(%d)\n",
+ data->type, data->client.app_id);
+ ret = -EINVAL;
+ break;
+ }
+ pr_debug("UNLOAD_APP: qseecom_addr = 0x%x\n", (u32)data);
mutex_lock(&app_access_lock);
atomic_inc(&data->ioctl_count);
ret = qseecom_unload_app(data);
@@ -2768,6 +2892,20 @@
break;
}
case QSEECOM_IOCTL_PERF_ENABLE_REQ:{
+ if ((data->type != QSEECOM_GENERIC) &&
+ (data->type != QSEECOM_CLIENT_APP)) {
+ pr_err("perf enable req: invalid handle (%d)\n",
+ data->type);
+ ret = -EINVAL;
+ break;
+ }
+ if ((data->type == QSEECOM_CLIENT_APP) &&
+ (data->client.app_id == 0)) {
+ pr_err("perf enable req:invalid handle(%d) appid(%d)\n",
+ data->type, data->client.app_id);
+ ret = -EINVAL;
+ break;
+ }
atomic_inc(&data->ioctl_count);
ret = qsee_vote_for_clock(data, CLK_DFAB);
if (ret)
@@ -2779,13 +2917,34 @@
break;
}
case QSEECOM_IOCTL_PERF_DISABLE_REQ:{
+ if ((data->type != QSEECOM_SECURE_SERVICE) &&
+ (data->type != QSEECOM_CLIENT_APP)) {
+ pr_err("perf disable req: invalid handle (%d)\n",
+ data->type);
+ ret = -EINVAL;
+ break;
+ }
+ if ((data->type == QSEECOM_CLIENT_APP) &&
+ (data->client.app_id == 0)) {
+ pr_err("perf disable: invalid handle (%d)app_id(%d)\n",
+ data->type, data->client.app_id);
+ ret = -EINVAL;
+ break;
+ }
atomic_inc(&data->ioctl_count);
- qsee_disable_clock_vote(data, CLK_DFAB);
- qsee_disable_clock_vote(data, CLK_SFPB);
+ qsee_disable_clock_vote(data, CLK_DFAB);
+ qsee_disable_clock_vote(data, CLK_SFPB);
atomic_dec(&data->ioctl_count);
break;
}
case QSEECOM_IOCTL_LOAD_EXTERNAL_ELF_REQ: {
+ if (data->type != QSEECOM_GENERIC) {
+ pr_err("load ext elf req: invalid client handle (%d)\n",
+ data->type);
+ ret = -EINVAL;
+ break;
+ }
+ data->type = QSEECOM_UNAVAILABLE_CLIENT_APP;
data->released = true;
mutex_lock(&app_access_lock);
atomic_inc(&data->ioctl_count);
@@ -2797,6 +2956,12 @@
break;
}
case QSEECOM_IOCTL_UNLOAD_EXTERNAL_ELF_REQ: {
+ if (data->type != QSEECOM_UNAVAILABLE_CLIENT_APP) {
+ pr_err("unload ext elf req: invalid handle (%d)\n",
+ data->type);
+ ret = -EINVAL;
+ break;
+ }
data->released = true;
mutex_lock(&app_access_lock);
atomic_inc(&data->ioctl_count);
@@ -2808,16 +2973,25 @@
break;
}
case QSEECOM_IOCTL_APP_LOADED_QUERY_REQ: {
+ data->type = QSEECOM_CLIENT_APP;
mutex_lock(&app_access_lock);
atomic_inc(&data->ioctl_count);
+ pr_debug("APP_LOAD_QUERY: qseecom_addr = 0x%x\n", (u32)data);
ret = qseecom_query_app_loaded(data, argp);
atomic_dec(&data->ioctl_count);
mutex_unlock(&app_access_lock);
break;
}
case QSEECOM_IOCTL_SEND_CMD_SERVICE_REQ: {
+ if (data->type != QSEECOM_GENERIC) {
+ pr_err("send cmd svc req: invalid handle (%d)\n",
+ data->type);
+ ret = -EINVAL;
+ break;
+ }
+ data->type = QSEECOM_SECURE_SERVICE;
if (qseecom.qsee_version < QSEE_VERSION_03) {
- pr_err("SEND_CMD_SERVICE_REQ: Invalid qsee version %u\n",
+ pr_err("SEND_CMD_SERVICE_REQ: Invalid qsee ver %u\n",
qseecom.qsee_version);
return -EINVAL;
}
@@ -2829,8 +3003,14 @@
break;
}
case QSEECOM_IOCTL_CREATE_KEY_REQ: {
+ if (data->type != QSEECOM_GENERIC) {
+ pr_err("create key req: invalid handle (%d)\n",
+ data->type);
+ ret = -EINVAL;
+ break;
+ }
if (qseecom.qsee_version < QSEE_VERSION_05) {
- pr_err("Create Key feature not supported in qsee version %u\n",
+ pr_err("Create Key feature unsupported: qsee ver %u\n",
qseecom.qsee_version);
return -EINVAL;
}
@@ -2846,8 +3026,14 @@
break;
}
case QSEECOM_IOCTL_WIPE_KEY_REQ: {
+ if (data->type != QSEECOM_GENERIC) {
+ pr_err("wipe key req: invalid handle (%d)\n",
+ data->type);
+ ret = -EINVAL;
+ break;
+ }
if (qseecom.qsee_version < QSEE_VERSION_05) {
- pr_err("Wipe Key feature not supported in qsee version %u\n",
+ pr_err("Wipe Key feature unsupported in qsee ver %u\n",
qseecom.qsee_version);
return -EINVAL;
}
@@ -2862,6 +3048,12 @@
break;
}
case QSEECOM_IOCTL_SAVE_PARTITION_HASH_REQ: {
+ if (data->type != QSEECOM_GENERIC) {
+ pr_err("save part hash req: invalid handle (%d)\n",
+ data->type);
+ ret = -EINVAL;
+ break;
+ }
data->released = true;
mutex_lock(&app_access_lock);
atomic_inc(&data->ioctl_count);
@@ -2871,6 +3063,12 @@
break;
}
case QSEECOM_IOCTL_IS_ES_ACTIVATED_REQ: {
+ if (data->type != QSEECOM_GENERIC) {
+ pr_err("ES activated req: invalid handle (%d)\n",
+ data->type);
+ ret = -EINVAL;
+ break;
+ }
data->released = true;
mutex_lock(&app_access_lock);
atomic_inc(&data->ioctl_count);
@@ -2880,6 +3078,13 @@
break;
}
case QSEECOM_IOCTL_SEND_MODFD_RESP: {
+ if ((data->listener.id == 0) ||
+ (data->type != QSEECOM_LISTENER_SERVICE)) {
+ pr_err("receive req: invalid handle (%d), lid(%d)\n",
+ data->type, data->listener.id);
+ ret = -EINVAL;
+ break;
+ }
/* Only one client allowed here at a time */
atomic_inc(&data->ioctl_count);
ret = qseecom_send_modfd_resp(data, argp);
@@ -2890,6 +3095,13 @@
break;
}
case QSEECOM_IOCTL_UNPROTECT_BUF: {
+ if ((data->listener.id == 0) ||
+ (data->type != QSEECOM_LISTENER_SERVICE)) {
+ pr_err("receive req: invalid handle (%d), lid(%d)\n",
+ data->type, data->listener.id);
+ ret = -EINVAL;
+ break;
+ }
/* Only one client allowed here at a time */
atomic_inc(&data->ioctl_count);
ret = qseecom_unprotect_buffer(argp);
@@ -2900,6 +3112,7 @@
break;
}
default:
+ pr_err("Invalid IOCTL: %d\n", cmd);
return -EINVAL;
}
return ret;
@@ -2931,7 +3144,8 @@
int ret = 0;
if (data->released == false) {
- pr_warn("data->released == false\n");
+ pr_warn("data: released = false, type = %d, data = 0x%x\n",
+ data->type, (u32)data);
switch (data->type) {
case QSEECOM_LISTENER_SERVICE:
ret = qseecom_unregister_listener(data);
@@ -2942,10 +3156,8 @@
case QSEECOM_SECURE_SERVICE:
case QSEECOM_GENERIC:
ret = qseecom_unmap_ion_allocated_memory(data);
- if (ret) {
+ if (ret)
pr_err("Close failed\n");
- return ret;
- }
break;
case QSEECOM_UNAVAILABLE_CLIENT_APP:
break;
@@ -3264,9 +3476,10 @@
}
rc = scm_call(SCM_SVC_TZSCHEDULER, 1, &req, sizeof(req),
&resp, sizeof(resp));
- if (rc) {
- pr_err("Failed to send secapp region info %d\n",
- rc);
+ if (rc || (resp.result != QSEOS_RESULT_SUCCESS)) {
+ pr_err("send secapp reg fail %d resp.res %d\n",
+ rc, resp.result);
+ rc = -EINVAL;
goto err;
}
}
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 1e2d367..293033b 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2688,13 +2688,19 @@
unsigned long mmc_get_max_frequency(struct mmc_host *host)
{
unsigned long freq;
+ unsigned char timing;
if (host->ops && host->ops->get_max_frequency) {
freq = host->ops->get_max_frequency(host);
goto out;
}
- switch (host->ios.timing) {
+ if (mmc_card_hs400(host->card))
+ timing = MMC_TIMING_MMC_HS400;
+ else
+ timing = host->ios.timing;
+
+ switch (timing) {
case MMC_TIMING_UHS_SDR50:
freq = UHS_SDR50_MAX_DTR;
break;
@@ -2707,6 +2713,9 @@
case MMC_TIMING_UHS_DDR50:
freq = UHS_DDR50_MAX_DTR;
break;
+ case MMC_TIMING_MMC_HS400:
+ freq = MMC_HS400_MAX_DTR;
+ break;
default:
mmc_host_clk_hold(host);
freq = host->ios.clock;
@@ -2747,6 +2756,9 @@
case MMC_TIMING_MMC_HS200:
freq = MMC_HIGH_52_MAX_DTR;
break;
+ case MMC_TIMING_MMC_HS400:
+ freq = MMC_HIGH_52_MAX_DTR;
+ break;
case MMC_TIMING_UHS_DDR50:
freq = UHS_DDR50_MAX_DTR / 2;
break;
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index e1609cf..997e14b 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1177,6 +1177,26 @@
return err;
}
+int mmc_set_clock_bus_speed(struct mmc_card *card, unsigned long freq)
+{
+ int err;
+
+ if (freq < MMC_HS400_MAX_DTR) {
+ /*
+ * Lower the clock and adjust the timing to be able
+ * to switch to HighSpeed mode
+ */
+ mmc_set_timing(card->host, MMC_TIMING_LEGACY);
+ mmc_set_clock(card->host, MMC_HIGH_26_MAX_DTR);
+
+ err = mmc_select_hs(card, &card->cached_ext_csd);
+ } else {
+ err = mmc_select_hs400(card, &card->cached_ext_csd);
+ }
+
+ return err;
+}
+
/**
* mmc_change_bus_speed() - Change MMC card bus frequency at runtime
* @host: pointer to mmc host structure
@@ -1219,7 +1239,13 @@
if (*freq < host->f_min)
*freq = host->f_min;
- mmc_set_clock(host, (unsigned int) (*freq));
+ if (mmc_card_hs400(card)) {
+ err = mmc_set_clock_bus_speed(card, *freq);
+ if (err)
+ goto out;
+ } else {
+ mmc_set_clock(host, (unsigned int) (*freq));
+ }
if ((mmc_card_hs400(card) || mmc_card_hs200(card))
&& card->host->ops->execute_tuning) {
@@ -1413,6 +1439,7 @@
err = mmc_get_ext_csd(card, &ext_csd);
if (err)
goto free_card;
+ memcpy(&card->cached_ext_csd, ext_csd, sizeof(card->ext_csd));
err = mmc_read_ext_csd(card, ext_csd);
if (err)
goto free_card;
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 89e3472..5786190 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -516,8 +516,6 @@
if (mrq->data)
mrq->data->bytes_xfered = host->curr.data_xfered;
- if (mrq->cmd->error == -ETIMEDOUT)
- mdelay(5);
msmsdcc_reset_dpsm(host);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index a7ce6ae..2c8598b 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -2687,6 +2687,9 @@
goto vreg_deinit;
}
+ /* Unset HC_MODE_EN bit in HC_MODE register */
+ writel_relaxed(0, (msm_host->core_mem + CORE_HC_MODE));
+
/* Set SW_RST bit in POWER register (Offset 0x0) */
writel_relaxed(readl_relaxed(msm_host->core_mem + CORE_POWER) |
CORE_SW_RST, msm_host->core_mem + CORE_POWER);
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index f9f3802..0cb0491 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -110,7 +110,7 @@
sdhci_readl(host, SDHCI_INT_ENABLE),
sdhci_readl(host, SDHCI_SIGNAL_ENABLE));
pr_info(DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
- sdhci_readw(host, SDHCI_ACMD12_ERR),
+ sdhci_readw(host, SDHCI_AUTO_CMD_ERR),
sdhci_readw(host, SDHCI_SLOT_INT_STATUS));
pr_info(DRIVER_NAME ": Caps: 0x%08x | Caps_1: 0x%08x\n",
sdhci_readl(host, SDHCI_CAPABILITIES),
@@ -118,6 +118,12 @@
pr_info(DRIVER_NAME ": Cmd: 0x%08x | Max curr: 0x%08x\n",
sdhci_readw(host, SDHCI_COMMAND),
sdhci_readl(host, SDHCI_MAX_CURRENT));
+ pr_info(DRIVER_NAME ": Resp 1: 0x%08x | Resp 0: 0x%08x\n",
+ sdhci_readl(host, SDHCI_RESPONSE + 0x4),
+ sdhci_readl(host, SDHCI_RESPONSE));
+ pr_info(DRIVER_NAME ": Resp 3: 0x%08x | Resp 2: 0x%08x\n",
+ sdhci_readl(host, SDHCI_RESPONSE + 0xC),
+ sdhci_readl(host, SDHCI_RESPONSE + 0x8));
pr_info(DRIVER_NAME ": Host ctl2: 0x%08x\n",
sdhci_readw(host, SDHCI_HOST_CONTROL2));
@@ -278,7 +284,8 @@
SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT |
SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
- SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE);
+ SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE |
+ SDHCI_INT_AUTO_CMD_ERR);
if (soft) {
/* force clock reconfiguration */
@@ -2440,6 +2447,7 @@
static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
{
+ u16 auto_cmd_status;
BUG_ON(intmask == 0);
if (!host->cmd) {
@@ -2456,6 +2464,18 @@
SDHCI_INT_INDEX))
host->cmd->error = -EILSEQ;
+ if (intmask & SDHCI_INT_AUTO_CMD_ERR) {
+ auto_cmd_status = sdhci_readw(host, SDHCI_AUTO_CMD_ERR);
+ if (auto_cmd_status & (SDHCI_AUTO_CMD12_NOT_EXEC |
+ SDHCI_AUTO_CMD_INDEX_ERR |
+ SDHCI_AUTO_CMD_ENDBIT_ERR))
+ host->cmd->error = -EIO;
+ else if (auto_cmd_status & SDHCI_AUTO_CMD_TIMEOUT_ERR)
+ host->cmd->error = -ETIMEDOUT;
+ else if (auto_cmd_status & SDHCI_AUTO_CMD_CRC_ERR)
+ host->cmd->error = -EILSEQ;
+ }
+
if (host->quirks2 & SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING) {
if ((host->cmd->opcode == MMC_SEND_TUNING_BLOCK_HS400) ||
(host->cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) ||
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index a3d8442..3db99c4 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -135,21 +135,29 @@
#define SDHCI_INT_DATA_CRC 0x00200000
#define SDHCI_INT_DATA_END_BIT 0x00400000
#define SDHCI_INT_BUS_POWER 0x00800000
-#define SDHCI_INT_ACMD12ERR 0x01000000
+#define SDHCI_INT_AUTO_CMD_ERR 0x01000000
#define SDHCI_INT_ADMA_ERROR 0x02000000
#define SDHCI_INT_NORMAL_MASK 0x00007FFF
#define SDHCI_INT_ERROR_MASK 0xFFFF8000
#define SDHCI_INT_CMD_MASK (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \
- SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)
+ SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX | \
+ SDHCI_INT_AUTO_CMD_ERR)
+
#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR)
#define SDHCI_INT_ALL_MASK ((unsigned int)-1)
-#define SDHCI_ACMD12_ERR 0x3C
+#define SDHCI_AUTO_CMD_ERR 0x3C
+#define SDHCI_AUTO_CMD12_NOT_EXEC 0x0001
+#define SDHCI_AUTO_CMD_TIMEOUT_ERR 0x0002
+#define SDHCI_AUTO_CMD_CRC_ERR 0x0004
+#define SDHCI_AUTO_CMD_ENDBIT_ERR 0x0008
+#define SDHCI_AUTO_CMD_INDEX_ERR 0x0010
+#define SDHCI_AUTO_CMD12_NOT_ISSUED 0x0080
#define SDHCI_HOST_CONTROL2 0x3E
#define SDHCI_CTRL_UHS_MASK 0x0007
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 5ccdd2a..0a408b1 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -314,6 +314,16 @@
---help---
Pre-allocate memory for the WLAN driver module
+config WCNSS_REGISTER_DUMP_ON_BITE
+ bool "Enable/disable WCNSS register dump when there is a WCNSS bite"
+ depends on WCNSS_CORE_PRONTO
+ help
+ When Apps recieves a WDOG bite from WCNSS, collecting a register dump
+ of WCNSS is helpful to root cause the failure. WCNSS may not be
+ properly clocked in some WCNSS bite cases, and that may cause unclocked
+ register access failures. So this feature is to enable/disable the
+ register dump on WCNSS WDOG bite.
+
source "drivers/net/wireless/ath/Kconfig"
source "drivers/net/wireless/b43/Kconfig"
source "drivers/net/wireless/b43legacy/Kconfig"
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 64d1478..7b743a4 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -648,6 +648,14 @@
}
EXPORT_SYMBOL(wcnss_pronto_log_debug_regs);
+#ifdef CONFIG_WCNSS_REGISTER_DUMP_ON_BITE
+void wcnss_log_debug_regs_on_bite(void)
+{
+ if (wcnss_hardware_type() == WCNSS_PRONTO_HW)
+ wcnss_pronto_log_debug_regs();
+}
+#endif
+
/* interface to reset wcnss by sending the reset interrupt */
void wcnss_reset_intr(void)
{
diff --git a/drivers/nfc/nfc-nci.c b/drivers/nfc/nfc-nci.c
index 87c7c30..67b057c 100644
--- a/drivers/nfc/nfc-nci.c
+++ b/drivers/nfc/nfc-nci.c
@@ -26,12 +26,15 @@
#include <linux/of_device.h>
#include <linux/regulator/consumer.h>
#include "nfc-nci.h"
+#include <mach/gpiomux.h>
struct qca199x_platform_data {
unsigned int irq_gpio;
unsigned int dis_gpio;
unsigned int ven_gpio;
unsigned int reg;
+ const char *clk_src;
+ unsigned int clk_src_gpio;
};
static struct of_device_id msm_match_table[] = {
@@ -397,7 +400,9 @@
gpio_set_value(qca199x_dev->dis_gpio, 1);
usleep(1000);
} else if (arg == 2) {
+ mutex_lock(&qca199x_dev->read_mutex);
r = nfcc_initialise(qca199x_dev->client, 0xE);
+ mutex_unlock(&qca199x_dev->read_mutex);
if (r) {
dev_err(&qca199x_dev->client->dev,
"nfc-nci probe: request nfcc initialise failed\n");
@@ -419,7 +424,6 @@
return r;
}
-
/*
* Inside nfc_ioctl_nfcc_mode
*
@@ -477,6 +481,64 @@
}
/*
+ * Inside nfc_ioctl_nfcc_version
+ *
+ * @brief nfc_ioctl_nfcc_version
+ *
+ *
+ */
+int nfc_ioctl_nfcc_version(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ int r = 0;
+ unsigned short slave_addr = 0xE;
+ unsigned short curr_addr;
+
+ unsigned char raw_chip_version_addr = 0x00;
+ unsigned char raw_chip_rev_id_addr = 0x9C;
+ unsigned char raw_chip_version = 0xFF;
+
+ 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) {
+ curr_addr = qca199x_dev->client->addr;
+ qca199x_dev->client->addr = slave_addr;
+ r = nfc_i2c_write(qca199x_dev->client,
+ &raw_chip_version_addr, 1);
+ if (r < 0)
+ goto invalid_wr;
+ usleep(10);
+ r = i2c_master_recv(qca199x_dev->client, &raw_chip_version, 1);
+ /* Restore original NFCC slave I2C address */
+ qca199x_dev->client->addr = curr_addr;
+ }
+ if (arg == 1) {
+ curr_addr = qca199x_dev->client->addr;
+ qca199x_dev->client->addr = slave_addr;
+ r = nfc_i2c_write(qca199x_dev->client,
+ &raw_chip_rev_id_addr, 1);
+ if (r < 0)
+ goto invalid_wr;
+ usleep(10);
+ r = i2c_master_recv(qca199x_dev->client, &raw_chip_version, 1);
+ /* Restore original NFCC slave I2C address */
+ qca199x_dev->client->addr = curr_addr;
+ }
+
+ return raw_chip_version;
+invalid_wr:
+ raw_chip_version = 0xFF;
+ dev_err(&qca199x_dev->client->dev,
+ "\nNFCC_INVALID_CHIP_VERSION = %d\n", raw_chip_version);
+ return raw_chip_version;
+}
+
+
+
+/*
* Inside nfc_ioctl_kernel_logging
*
* @brief nfc_ioctl_kernel_logging
@@ -522,6 +584,9 @@
case NFCC_MODE:
nfc_ioctl_nfcc_mode(pfile, cmd, arg);
break;
+ case NFCC_VERSION:
+ r = nfc_ioctl_nfcc_version(pfile, cmd, arg);
+ break;
case NFC_KERNEL_LOGGING_MODE:
nfc_ioctl_kernel_logging(arg, pfile);
break;
@@ -690,6 +755,14 @@
if ((!gpio_is_valid(pdata->irq_gpio)))
return -EINVAL;
+ r = of_property_read_string(np, "qcom,clk-src", &pdata->clk_src);
+
+ if (!strcmp(pdata->clk_src, "GPCLK"))
+ pdata->clk_src_gpio = of_get_named_gpio(np,
+ "qcom,clk-en-gpio", 0);
+
+ if (r)
+ return -EINVAL;
return r;
}
@@ -698,7 +771,7 @@
{
int r = 0;
int irqn = 0;
- struct clk *nfc_clk;
+ struct clk *nfc_clk = NULL;
struct device_node *node = client->dev.of_node;
struct qca199x_platform_data *platform_data;
struct qca199x_dev *qca199x_dev;
@@ -769,7 +842,7 @@
dev_err(&client->dev,
"NFC: unable to request gpio [%d]\n",
platform_data->dis_gpio);
- goto err_dis_gpio;
+ goto err_free_dev;
}
r = gpio_direction_output(platform_data->dis_gpio, 1);
if (r) {
@@ -785,15 +858,28 @@
gpio_set_value(platform_data->dis_gpio, 1);/* HPD */
msleep(20);
gpio_set_value(platform_data->dis_gpio, 0);/* ULPM */
-
- nfc_clk = clk_get(&client->dev, "ref_clk");
-
- if (nfc_clk == NULL)
- goto err_dis_gpio;
-
+ if (!strcmp(platform_data->clk_src, "BBCLK2")) {
+ nfc_clk = clk_get(&client->dev, "ref_clk");
+ if (nfc_clk == NULL)
+ goto err_dis_gpio;
+ } else if (!strcmp(platform_data->clk_src, "RFCLK3")) {
+ nfc_clk = clk_get(&client->dev, "ref_clk_rf");
+ if (nfc_clk == NULL)
+ goto err_dis_gpio;
+ } else if (!strcmp(platform_data->clk_src, "GPCLK")) {
+ if (gpio_is_valid(platform_data->clk_src_gpio)) {
+ nfc_clk = clk_get(&client->dev, "core_clk");
+ if (nfc_clk == NULL)
+ goto err_dis_gpio;
+ } else {
+ goto err_dis_gpio;
+ }
+ } else {
+ nfc_clk = NULL;
+ }
r = clk_prepare_enable(nfc_clk);
if (r)
- goto err_dis_gpio;
+ goto err_clk;
platform_data->ven_gpio = of_get_named_gpio(node,
"qcom,clk-gpio", 0);
@@ -813,11 +899,9 @@
platform_data->ven_gpio);
goto err_ven_gpio;
}
-
} else {
-
dev_err(&client->dev, "ven gpio not provided\n");
- goto err_dis_gpio;
+ goto err_clk;
}
qca199x_dev->dis_gpio = platform_data->dis_gpio;
qca199x_dev->irq_gpio = platform_data->irq_gpio;
@@ -871,7 +955,18 @@
mutex_destroy(&qca199x_dev->read_mutex);
err_ven_gpio:
gpio_free(platform_data->ven_gpio);
+err_clk:
+ clk_disable_unprepare(nfc_clk);
err_dis_gpio:
+ r = gpio_direction_input(platform_data->dis_gpio);
+ if (r)
+ dev_err(&client->dev, "nfc-nci probe: Unable to set direction\n");
+ if (!strcmp(platform_data->clk_src, "GPCLK")) {
+ r = gpio_direction_input(platform_data->clk_src_gpio);
+ if (r)
+ dev_err(&client->dev, "nfc-nci probe: Unable to set direction\n");
+ gpio_free(platform_data->clk_src_gpio);
+ }
gpio_free(platform_data->dis_gpio);
err_irq:
gpio_free(platform_data->irq_gpio);
diff --git a/drivers/nfc/nfc-nci.h b/drivers/nfc/nfc-nci.h
index c3cabc2..81f2521 100644
--- a/drivers/nfc/nfc-nci.h
+++ b/drivers/nfc/nfc-nci.h
@@ -49,26 +49,27 @@
enum ehandler_mode handle_flavour;
} tdevicemode;
-#define NFC_DRIVER_NAME "nfc-nci"
+#define NFC_DRIVER_NAME "nfc-nci"
#define NFC_I2C_DRIVER_NAME "NCI NFC I2C Interface",
-#define NCI_I2C_SLAVE (0x2C)
-#define NFC_I2C_BUS 3 /* 6, 10, 4, 5 */
-#define NFC_SET_PWR _IOW(0xE9, 0x01, unsigned int)
-#define NFCC_MODE _IOW(0xE9, 0x02, unsigned int)
+#define NCI_I2C_SLAVE (0x2C)
+#define NFC_I2C_BUS 3 /* 6, 10, 4, 5 */
+#define NFC_SET_PWR _IOW(0xE9, 0x01, unsigned int)
+#define NFCC_MODE _IOW(0xE9, 0x02, unsigned int)
#define NFC_KERNEL_LOGGING_MODE _IOW(0xE9, 0x03, unsigned int)
-#define SET_RX_BLOCK _IOW(0xE9, 0x04, unsigned int)
+#define SET_RX_BLOCK _IOW(0xE9, 0x04, unsigned int)
#define SET_EMULATOR_TEST_POINT _IOW(0xE9, 0x05, unsigned int)
+#define NFCC_VERSION _IOW(0xE9, 0x08, unsigned int)
-#define NFC_MAX_I2C_TRANSFER (0x0400)
-#define NFC_MSG_MAX_SIZE (0x21)
+#define NFC_MAX_I2C_TRANSFER (0x0400)
+#define NFC_MSG_MAX_SIZE (0x21)
#define NFC_RX_BUFFER_CNT_START (0x0)
-#define NFC_RX_BUFFER_BLOCK_SIZE (0x120) /* Bytes per Block */
+#define NFC_RX_BUFFER_BLOCK_SIZE (0x120) /* Bytes per Block */
#define NFC_RX_BUFFER_PAGE_SIZE (0x1000) /* Page size Bytes */
#define NFC_RX_BUFFER_PAGES (0x8)
-#define NFC_RX_ORDER_FREE_PAGES (0x3) /* Free 8 Pages */
+#define NFC_RX_ORDER_FREE_PAGES (0x3) /* Free 8 Pages */
/* The total no. of Blocks */
#define NFC_RX_BUFFER_CNT_LIMIT (unsigned short)( \
@@ -86,10 +87,10 @@
/** Power Management Related **/
-#define NFCC_WAKE (0x01)
-#define NFCC_SLEEP (0x00)
+#define NFCC_WAKE (0x01)
+#define NFCC_SLEEP (0x00)
-#define XTAL_CLOCK (0X00)
+#define XTAL_CLOCK (0X00)
#define REFERENCE_CLOCK (0X01)
/* LDO Trim Settings */
@@ -122,8 +123,8 @@
#define LOCALBIASXTAL (0x20)
#define BIAS2X_FORCE (0x10)
#define BIAS2X (0x08)
-#define LBIAS2X (0x04)
-#define SMALLRF (0x02)
+#define LBIAS2X (0x04)
+#define SMALLRF (0x02)
#define SMALLRBIAS (0x01)
/* Select as appropriate */
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index b4edce8..50d5f7b 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -107,6 +107,7 @@
u32 bark_irq;
u16 s2_cntl_addr;
u16 s2_cntl2_addr;
+ bool use_bark;
};
struct qpnp_pon {
@@ -614,7 +615,7 @@
cfg->state_irq);
return rc;
}
- if (cfg->support_reset) {
+ if (cfg->use_bark) {
rc = devm_request_irq(&pon->spmi->dev, cfg->bark_irq,
qpnp_kpdpwr_bark_irq,
IRQF_TRIGGER_RISING,
@@ -637,7 +638,7 @@
cfg->state_irq);
return rc;
}
- if (cfg->support_reset) {
+ if (cfg->use_bark) {
rc = devm_request_irq(&pon->spmi->dev, cfg->bark_irq,
qpnp_resin_bark_irq,
IRQF_TRIGGER_RISING,
@@ -662,7 +663,7 @@
}
break;
case PON_KPDPWR_RESIN:
- if (cfg->support_reset) {
+ if (cfg->use_bark) {
rc = devm_request_irq(&pon->spmi->dev, cfg->bark_irq,
qpnp_kpdpwr_resin_bark_irq,
IRQF_TRIGGER_RISING,
@@ -755,7 +756,9 @@
return rc;
}
- if (cfg->support_reset) {
+ cfg->use_bark = of_property_read_bool(pp,
+ "qcom,use-bark");
+ if (cfg->use_bark) {
cfg->bark_irq = spmi_get_irq_byname(pon->spmi,
NULL, "kpdpwr-bark");
if (cfg->bark_irq < 0) {
@@ -793,7 +796,9 @@
return rc;
}
- if (cfg->support_reset) {
+ cfg->use_bark = of_property_read_bool(pp,
+ "qcom,use-bark");
+ if (cfg->use_bark) {
cfg->bark_irq = spmi_get_irq_byname(pon->spmi,
NULL, "resin-bark");
if (cfg->bark_irq < 0) {
@@ -832,7 +837,9 @@
return rc;
}
- if (cfg->support_reset) {
+ cfg->use_bark = of_property_read_bool(pp,
+ "qcom,use-bark");
+ if (cfg->use_bark) {
cfg->bark_irq = spmi_get_irq_byname(pon->spmi,
NULL, "kpdpwr-resin-bark");
if (cfg->bark_irq < 0) {
@@ -1031,8 +1038,11 @@
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");
+
+ cold_boot = !qpnp_pon_is_warm_reset();
+ pr_info("PMIC@SID%d Power-on reason: %s and '%s' boot\n",
+ pon->spmi->sid, index ? qpnp_pon_reason[index - 1] :
+ "Unknown", cold_boot ? "cold" : "warm");
rc = of_property_read_u32(pon->spmi->dev.of_node,
"qcom,pon-dbc-delay", &delay);
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 4be727f..8bb4f90 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -356,7 +356,7 @@
/*
* Enable USB PRIVATE RAM to be used for BAM FIFOs
* HSUSB: Only RAM13 is used for BAM FIFOs
- * SSUSB: RAM12, 13 are used for BAM FIFOs
+ * SSUSB: RAM11, 12, 13 are used for BAM FIFOs
*/
bam = pipe_connect->bam_type;
if (bam < 0)
@@ -365,7 +365,7 @@
if (bam == HSUSB_BAM)
ram1_value = 0x4;
else
- ram1_value = 0x6;
+ ram1_value = 0x7;
pr_debug("Writing 0x%x to QSCRATCH_RAM1\n", ram1_value);
writel_relaxed(ram1_value, ctx.qscratch_ram1_reg);
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 61f4946..97e952e 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -98,6 +98,23 @@
}
EXPORT_SYMBOL_GPL(power_supply_set_online);
+
+/** power_supply_set_health_state - set health state of the power supply
+ * @psy: the power supply to control
+ * @health: sets health property of power supply
+ */
+int power_supply_set_health_state(struct power_supply *psy, int health)
+{
+ const union power_supply_propval ret = {health,};
+
+ if (psy->set_property)
+ return psy->set_property(psy, POWER_SUPPLY_PROP_HEALTH,
+ &ret);
+ return -ENXIO;
+}
+EXPORT_SYMBOL(power_supply_set_health_state);
+
+
/**
* power_supply_set_scope - set scope of the power supply
* @psy: the power supply to control
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 02fd276..319a24d 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -150,6 +150,7 @@
POWER_SUPPLY_ATTR(input_voltage_regulation),
POWER_SUPPLY_ATTR(current_max),
POWER_SUPPLY_ATTR(input_current_max),
+ POWER_SUPPLY_ATTR(input_current_trim),
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 49e57b9..ad39e88 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -80,8 +80,7 @@
/* Configuration for saving of shutdown soc/iavg */
#define IGNORE_SOC_TEMP_DECIDEG 50
-#define IAVG_STEP_SIZE_MA 50
-#define IAVG_START 600
+#define IAVG_STEP_SIZE_MA 10
#define IAVG_INVALID 0xFF
#define SOC_INVALID 0x7E
@@ -1234,7 +1233,6 @@
}
#define MIN_IAVG_MA 250
-#define MIN_SECONDS_FOR_VALID_SAMPLE 20
static int calculate_unusable_charge_uah(struct qpnp_bms_chip *chip,
struct soc_params *params,
int batt_temp)
@@ -1258,17 +1256,19 @@
chip->iavg_num_samples = IAVG_SAMPLES;
}
- /*
- * if charging use a nominal avg current to keep
- * a reasonable UUC while charging
- */
- if (uuc_iavg_ma < MIN_IAVG_MA)
- uuc_iavg_ma = MIN_IAVG_MA;
- chip->iavg_samples_ma[chip->iavg_index] = uuc_iavg_ma;
- chip->iavg_index = (chip->iavg_index + 1) % IAVG_SAMPLES;
- chip->iavg_num_samples++;
- if (chip->iavg_num_samples >= IAVG_SAMPLES)
- chip->iavg_num_samples = IAVG_SAMPLES;
+ if (params->delta_time_s >= IAVG_MINIMAL_TIME) {
+ /*
+ * if charging use a nominal avg current to keep
+ * a reasonable UUC while charging
+ */
+ if (uuc_iavg_ma < MIN_IAVG_MA)
+ uuc_iavg_ma = MIN_IAVG_MA;
+ chip->iavg_samples_ma[chip->iavg_index] = uuc_iavg_ma;
+ chip->iavg_index = (chip->iavg_index + 1) % IAVG_SAMPLES;
+ chip->iavg_num_samples++;
+ if (chip->iavg_num_samples >= IAVG_SAMPLES)
+ chip->iavg_num_samples = IAVG_SAMPLES;
+ }
/* now that this sample is added calcualte the average */
uuc_iavg_ma = 0;
@@ -1299,7 +1299,6 @@
uuc_uah_iavg = adjust_uuc(chip, params, pc_unusable,
uuc_uah_iavg, batt_temp);
- chip->first_time_calc_uuc = 0;
return uuc_uah_iavg;
}
@@ -1608,8 +1607,8 @@
int rc;
int iavg_ma = chip->prev_uuc_iavg_ma;
- if (iavg_ma > IAVG_START)
- temp = (iavg_ma - IAVG_START) / IAVG_STEP_SIZE_MA;
+ if (iavg_ma > MIN_IAVG_MA)
+ temp = (iavg_ma - MIN_IAVG_MA) / IAVG_STEP_SIZE_MA;
else
temp = 0;
@@ -2333,6 +2332,7 @@
get_current_time(&chip->last_recalc_time);
chip->first_time_calc_soc = 0;
+ chip->first_time_calc_uuc = 0;
return chip->calculated_soc;
}
@@ -2687,7 +2687,8 @@
return;
}
- temp = kzalloc(sizeof(struct single_row_lut), GFP_KERNEL);
+ temp = devm_kzalloc(chip->dev, sizeof(struct single_row_lut),
+ GFP_KERNEL);
if (!temp) {
pr_err("Cannot allocate memory for adjusted fcc table\n");
return;
@@ -2705,7 +2706,7 @@
old = chip->adjusted_fcc_temp_lut;
chip->adjusted_fcc_temp_lut = temp;
- kfree(old);
+ devm_kfree(chip->dev, old);
}
static int read_fcc_data_from_backup(struct qpnp_bms_chip *chip)
@@ -3293,17 +3294,17 @@
if (rc) {
pr_err("failed to read addr = %d %d assuming %d\n",
chip->base + IAVG_STORAGE_REG, rc,
- IAVG_START);
- return IAVG_START;
+ MIN_IAVG_MA);
+ return MIN_IAVG_MA;
} else if (iavg == IAVG_INVALID) {
pr_err("invalid iavg read from BMS1_DATA_REG_1, using %d\n",
- IAVG_START);
- return IAVG_START;
+ MIN_IAVG_MA);
+ return MIN_IAVG_MA;
} else {
if (iavg == 0)
- return IAVG_START;
+ return MIN_IAVG_MA;
else
- return IAVG_START + IAVG_STEP_SIZE_MA * (iavg + 1);
+ return MIN_IAVG_MA + IAVG_STEP_SIZE_MA * iavg;
}
}
@@ -3442,7 +3443,7 @@
static int set_battery_data(struct qpnp_bms_chip *chip)
{
int64_t battery_id;
- int rc, dt_data = false;
+ int rc = 0, dt_data = false;
struct bms_battery_data *batt_data;
struct device_node *node;
@@ -3466,41 +3467,52 @@
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);
+ if (!node) {
+ pr_warn("No available batterydata, using palladium 1500\n");
+ batt_data = &palladium_1500_data;
+ goto assign_data;
+ }
+ batt_data = devm_kzalloc(chip->dev,
+ sizeof(struct bms_battery_data), GFP_KERNEL);
+ if (!batt_data) {
+ pr_err("Could not alloc battery data\n");
+ batt_data = &palladium_1500_data;
+ goto assign_data;
+ }
+ batt_data->fcc_temp_lut = devm_kzalloc(chip->dev,
+ sizeof(struct single_row_lut),
+ GFP_KERNEL);
+ batt_data->pc_temp_ocv_lut = devm_kzalloc(chip->dev,
+ sizeof(struct pc_temp_ocv_lut),
+ GFP_KERNEL);
+ batt_data->rbatt_sf_lut = devm_kzalloc(chip->dev,
+ sizeof(struct sf_lut),
+ GFP_KERNEL);
- batt_data->max_voltage_uv = -1;
- batt_data->cutoff_uv = -1;
- batt_data->iterm_ua = -1;
+ batt_data->max_voltage_uv = -1;
+ batt_data->cutoff_uv = -1;
+ batt_data->iterm_ua = -1;
- 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 {
- dt_data = true;
- }
+ /*
+ * if the alloced luts are 0s, of_batterydata_read_data ignores
+ * them.
+ */
+ rc = of_batterydata_read_data(node, batt_data, battery_id);
+ if (rc == 0 && batt_data->fcc_temp_lut
+ && batt_data->pc_temp_ocv_lut
+ && batt_data->rbatt_sf_lut) {
+ dt_data = true;
} else {
- pr_warn("invalid battid, palladium 1500 assumed batt_id %llx\n",
- battery_id);
+ pr_err("battery data load failed, using palladium 1500\n");
+ devm_kfree(chip->dev, batt_data->fcc_temp_lut);
+ devm_kfree(chip->dev, batt_data->pc_temp_ocv_lut);
+ devm_kfree(chip->dev, batt_data->rbatt_sf_lut);
+ devm_kfree(chip->dev, batt_data);
batt_data = &palladium_1500_data;
}
}
+assign_data:
chip->fcc_mah = batt_data->fcc;
chip->fcc_temp_lut = batt_data->fcc_temp_lut;
chip->fcc_sf_lut = batt_data->fcc_sf_lut;
@@ -3519,13 +3531,20 @@
if (batt_data->iterm_ua >= 0 && dt_data)
chip->chg_term_ua = batt_data->iterm_ua;
- if (dt_data)
- kfree(batt_data);
-
if (chip->pc_temp_ocv_lut == NULL) {
- pr_err("temp ocv lut table is NULL\n");
+ pr_err("temp ocv lut table has not been loaded\n");
+ if (dt_data) {
+ devm_kfree(chip->dev, batt_data->fcc_temp_lut);
+ devm_kfree(chip->dev, batt_data->pc_temp_ocv_lut);
+ devm_kfree(chip->dev, batt_data->rbatt_sf_lut);
+ devm_kfree(chip->dev, batt_data);
+ }
return -EINVAL;
}
+
+ if (dt_data)
+ devm_kfree(chip->dev, batt_data);
+
return 0;
}
@@ -3642,6 +3661,8 @@
chip->fcc_learning_samples = devm_kzalloc(&chip->spmi->dev,
(sizeof(struct fcc_sample) *
chip->min_fcc_learning_samples), GFP_KERNEL);
+ if (chip->fcc_learning_samples == NULL)
+ return -ENOMEM;
pr_debug("min-fcc-soc=%d, min-fcc-pc=%d, min-fcc-cycles=%d\n",
chip->min_fcc_learning_soc, chip->min_fcc_ocv_pc,
chip->min_fcc_learning_samples);
@@ -3981,7 +4002,8 @@
bool warm_reset;
int rc, vbatt;
- chip = kzalloc(sizeof *chip, GFP_KERNEL);
+ chip = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_bms_chip),
+ GFP_KERNEL);
if (chip == NULL) {
pr_err("kzalloc() failed.\n");
@@ -4172,17 +4194,12 @@
wake_lock_destroy(&chip->cv_wake_lock);
error_resource:
error_read:
- kfree(chip);
return rc;
}
-static int __devexit
-qpnp_bms_remove(struct spmi_device *spmi)
+static int qpnp_bms_remove(struct spmi_device *spmi)
{
- struct qpnp_bms_chip *chip = dev_get_drvdata(&spmi->dev);
-
dev_set_drvdata(&spmi->dev, NULL);
- kfree(chip);
return 0;
}
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 6e9dc57..64ad940 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -31,6 +31,7 @@
#include <linux/of_batterydata.h>
#include <linux/qpnp-revid.h>
#include <linux/android_alarm.h>
+#include <linux/spinlock.h>
/* Interrupt offsets */
#define INT_RT_STS(base) (base + 0x10)
@@ -81,11 +82,13 @@
#define CHGR_USB_USB_SUSP 0x47
#define CHGR_USB_USB_OTG_CTL 0x48
#define CHGR_USB_ENUM_T_STOP 0x4E
+#define CHGR_USB_TRIM 0xF1
#define CHGR_CHG_TEMP_THRESH 0x66
#define CHGR_BAT_IF_PRES_STATUS 0x08
#define CHGR_STATUS 0x09
#define CHGR_BAT_IF_VCP 0x42
#define CHGR_BAT_IF_BATFET_CTRL1 0x90
+#define CHGR_BAT_IF_BATFET_CTRL4 0x93
#define CHGR_BAT_IF_SPARE 0xDF
#define CHGR_MISC_BOOT_DONE 0x42
#define CHGR_BUCK_PSTG_CTRL 0x73
@@ -241,6 +244,7 @@
* @btc_disabled Flag to disable btc (disables hot and cold irqs)
* @max_voltage_mv: the max volts the batt should be charged up to
* @min_voltage_mv: min battery voltage before turning the FET on
+ * @batt_weak_voltage_mv: Weak battery voltage threshold
* @max_bat_chg_current: maximum battery charge current in mA
* @warm_bat_chg_ma: warm battery maximum charge current in mA
* @cool_bat_chg_ma: cool battery maximum charge current in mA
@@ -290,14 +294,19 @@
struct qpnp_chg_irq chg_vbatdet_lo;
struct qpnp_chg_irq batt_pres;
struct qpnp_chg_irq batt_temp_ok;
+ struct qpnp_chg_irq coarse_det_usb;
bool bat_is_cool;
bool bat_is_warm;
bool chg_done;
bool charger_monitor_checked;
bool usb_present;
+ u8 usbin_health;
+ bool usb_coarse_det;
bool dc_present;
bool batt_present;
bool charging_disabled;
+ bool ovp_monitor_enable;
+ bool usb_valid_check_ovp;
bool btc_disabled;
bool use_default_batt_values;
bool duty_cycle_100p;
@@ -308,6 +317,7 @@
unsigned int safe_voltage_mv;
unsigned int max_voltage_mv;
unsigned int min_voltage_mv;
+ unsigned int batt_weak_voltage_mv;
int prev_usb_max_ma;
int set_vddmax_mv;
int delta_vddmax_mv;
@@ -341,14 +351,19 @@
struct work_struct adc_disable_work;
struct delayed_work arb_stop_work;
struct delayed_work eoc_work;
+ struct delayed_work usbin_health_check;
struct work_struct soc_check_work;
struct delayed_work aicl_check_work;
struct qpnp_chg_regulator otg_vreg;
struct qpnp_chg_regulator boost_vreg;
struct qpnp_chg_regulator batfet_vreg;
+ bool batfet_ext_en;
+ struct work_struct batfet_lcl_work;
struct qpnp_vadc_chip *vadc_dev;
struct qpnp_adc_tm_chip *adc_tm_dev;
struct mutex jeita_configure_lock;
+ spinlock_t usbin_health_monitor_lock;
+ struct mutex batfet_vreg_lock;
struct alarm reduce_power_stage_alarm;
struct work_struct reduce_power_stage_work;
bool power_stage_workaround_running;
@@ -386,7 +401,13 @@
[COLD_THD_80_PCT] = BIT(1),
};
- static inline int
+enum usbin_health {
+ USBIN_UNKNOW,
+ USBIN_OK,
+ USBIN_OVP,
+};
+
+static inline int
get_bpd(const char *name)
{
int i = 0;
@@ -599,6 +620,58 @@
return (usbin_valid_rt_sts & USB_VALID_BIT) ? 1 : 0;
}
+#define USB_VALID_MASK 0xC0
+#define USB_COARSE_DET 0x10
+#define USB_VALID_UVP_VALUE 0x00
+#define USB_VALID_OVP_VALUE 0x40
+static int
+qpnp_chg_check_usb_coarse_det(struct qpnp_chg_chip *chip)
+{
+ u8 usbin_chg_rt_sts;
+ int rc;
+ rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
+ chip->usb_chgpth_base + CHGR_STATUS , 1);
+ if (rc) {
+ pr_err("spmi read failed: addr=%03X, rc=%d\n",
+ chip->usb_chgpth_base + CHGR_STATUS, rc);
+ return rc;
+ }
+ return (usbin_chg_rt_sts & USB_COARSE_DET) ? 1 : 0;
+}
+
+static int
+qpnp_chg_check_usbin_health(struct qpnp_chg_chip *chip)
+{
+ u8 usbin_chg_rt_sts, usbin_health = 0;
+ int rc;
+
+ rc = qpnp_chg_read(chip, &usbin_chg_rt_sts,
+ chip->usb_chgpth_base + CHGR_STATUS , 1);
+
+ if (rc) {
+ pr_err("spmi read failed: addr=%03X, rc=%d\n",
+ chip->usb_chgpth_base + CHGR_STATUS, rc);
+ return rc;
+ }
+
+ pr_debug("chgr usb sts 0x%x\n", usbin_chg_rt_sts);
+ if ((usbin_chg_rt_sts & USB_COARSE_DET) == USB_COARSE_DET) {
+ if ((usbin_chg_rt_sts & USB_VALID_MASK)
+ == USB_VALID_OVP_VALUE) {
+ usbin_health = USBIN_OVP;
+ pr_err("Over voltage charger inserted\n");
+ } else if ((usbin_chg_rt_sts & USB_VALID_BIT) != 0) {
+ usbin_health = USBIN_OK;
+ pr_debug("Valid charger inserted\n");
+ }
+ } else {
+ usbin_health = USBIN_UNKNOW;
+ pr_debug("Charger plug out\n");
+ }
+
+ return usbin_health;
+}
+
static int
qpnp_chg_is_dc_chg_plugged_in(struct qpnp_chg_chip *chip)
{
@@ -676,6 +749,48 @@
}
static int
+qpnp_chg_iusb_trim_get(struct qpnp_chg_chip *chip)
+{
+ int rc = 0;
+ u8 trim_reg;
+
+ rc = qpnp_chg_read(chip, &trim_reg,
+ chip->usb_chgpth_base + CHGR_USB_TRIM, 1);
+ if (rc) {
+ pr_err("failed to read USB_TRIM rc=%d\n", rc);
+ return 0;
+ }
+
+ return trim_reg;
+}
+
+static int
+qpnp_chg_iusb_trim_set(struct qpnp_chg_chip *chip, int trim)
+{
+ int rc = 0;
+
+ rc = qpnp_chg_masked_write(chip,
+ chip->usb_chgpth_base + SEC_ACCESS,
+ 0xFF,
+ 0xA5, 1);
+ if (rc) {
+ pr_err("failed to write SEC_ACCESS rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_chg_masked_write(chip,
+ chip->usb_chgpth_base + CHGR_USB_TRIM,
+ 0xFF,
+ trim, 1);
+ if (rc) {
+ pr_err("failed to write USB TRIM rc=%d\n", rc);
+ return rc;
+ }
+
+ return rc;
+}
+
+static int
qpnp_chg_iusbmax_set(struct qpnp_chg_chip *chip, int mA)
{
int rc = 0;
@@ -737,7 +852,7 @@
#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_MASK 0x3F
#define QPNP_CHG_VINMIN_MIN_VAL 0x10
static int
qpnp_chg_vinmin_set(struct qpnp_chg_chip *chip, int voltage)
@@ -792,6 +907,26 @@
return vin_min_mv;
}
+#define QPNP_CHG_VBATWEAK_MIN_MV 2100
+#define QPNP_CHG_VBATWEAK_MAX_MV 3600
+#define QPNP_CHG_VBATWEAK_STEP_MV 100
+static int
+qpnp_chg_vbatweak_set(struct qpnp_chg_chip *chip, int vbatweak_mv)
+{
+ u8 temp;
+
+ if (vbatweak_mv < QPNP_CHG_VBATWEAK_MIN_MV
+ || vbatweak_mv > QPNP_CHG_VBATWEAK_MAX_MV)
+ return -EINVAL;
+
+ temp = (vbatweak_mv - QPNP_CHG_VBATWEAK_MIN_MV)
+ / QPNP_CHG_VBATWEAK_STEP_MV;
+
+ pr_debug("voltage=%d setting %02x\n", vbatweak_mv, temp);
+ return qpnp_chg_write(chip, &temp,
+ chip->chgr_base + CHGR_VBAT_WEAK, 1);
+}
+
static int
qpnp_chg_usb_iusbmax_get(struct qpnp_chg_chip *chip)
{
@@ -1117,12 +1252,128 @@
chip->delta_vddmax_mv);
}
+static void
+qpnp_usbin_health_check_work(struct work_struct *work)
+{
+ int usbin_health = 0;
+ u8 psy_health_sts = 0;
+ struct delayed_work *dwork = to_delayed_work(work);
+ struct qpnp_chg_chip *chip = container_of(dwork,
+ struct qpnp_chg_chip, usbin_health_check);
+
+ usbin_health = qpnp_chg_check_usbin_health(chip);
+ spin_lock(&chip->usbin_health_monitor_lock);
+ if (chip->usbin_health != usbin_health) {
+ pr_debug("health_check_work: pr_usbin_health = %d, usbin_health = %d",
+ chip->usbin_health, usbin_health);
+ chip->usbin_health = usbin_health;
+ if (usbin_health == USBIN_OVP)
+ psy_health_sts = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+ else if (usbin_health == USBIN_OK)
+ psy_health_sts = POWER_SUPPLY_HEALTH_GOOD;
+ power_supply_set_health_state(chip->usb_psy, psy_health_sts);
+ power_supply_changed(chip->usb_psy);
+ }
+ /* enable OVP monitor in usb valid after coarse-det complete */
+ chip->usb_valid_check_ovp = true;
+ spin_unlock(&chip->usbin_health_monitor_lock);
+ return;
+}
+
+#define USB_VALID_DEBOUNCE_TIME_MASK 0x3
+#define USB_DEB_BYPASS 0x0
+#define USB_DEB_5MS 0x1
+#define USB_DEB_10MS 0x2
+#define USB_DEB_20MS 0x3
+static irqreturn_t
+qpnp_chg_coarse_det_usb_irq_handler(int irq, void *_chip)
+{
+ struct qpnp_chg_chip *chip = _chip;
+ int host_mode, rc = 0;
+ int debounce[] = {
+ [USB_DEB_BYPASS] = 0,
+ [USB_DEB_5MS] = 5,
+ [USB_DEB_10MS] = 10,
+ [USB_DEB_20MS] = 20 };
+ u8 ovp_ctl;
+ bool usb_coarse_det;
+
+ host_mode = qpnp_chg_is_otg_en_set(chip);
+ usb_coarse_det = qpnp_chg_check_usb_coarse_det(chip);
+ pr_debug("usb coarse-det triggered: %d host_mode: %d\n",
+ usb_coarse_det, host_mode);
+
+ if (host_mode)
+ return IRQ_HANDLED;
+ /* ignore to monitor OVP in usbin valid irq handler
+ if the coarse-det fired first, do the OVP state monitor
+ in the usbin_health_check work, and after the work,
+ enable monitor OVP in usbin valid irq handler */
+ chip->usb_valid_check_ovp = false;
+ if (chip->usb_coarse_det ^ usb_coarse_det) {
+ chip->usb_coarse_det = usb_coarse_det;
+ if (usb_coarse_det) {
+ /* usb coarse-det rising edge, check the usbin_valid
+ debounce time setting, and start a delay work to
+ check the OVP status*/
+ rc = qpnp_chg_read(chip, &ovp_ctl,
+ chip->usb_chgpth_base + USB_OVP_CTL, 1);
+
+ if (rc) {
+ pr_err("spmi read failed: addr=%03X, rc=%d\n",
+ chip->usb_chgpth_base + USB_OVP_CTL,
+ rc);
+ return rc;
+ }
+ ovp_ctl = ovp_ctl & USB_VALID_DEBOUNCE_TIME_MASK;
+ schedule_delayed_work(&chip->usbin_health_check,
+ msecs_to_jiffies(debounce[ovp_ctl]));
+ } else {
+ /* usb coarse-det rising edge, set the usb psy health
+ status to unknown */
+ pr_debug("usb coarse det clear, set usb health to unknown\n");
+ chip->usbin_health = USBIN_UNKNOW;
+ power_supply_set_health_state(chip->usb_psy,
+ POWER_SUPPLY_HEALTH_UNKNOWN);
+ power_supply_changed(chip->usb_psy);
+ }
+
+ }
+ return IRQ_HANDLED;
+}
+
+#define BATFET_LPM_MASK 0xC0
+#define BATFET_LPM 0x40
+#define BATFET_NO_LPM 0x00
+static int
+qpnp_chg_regulator_batfet_set(struct qpnp_chg_chip *chip, bool enable)
+{
+ int rc = 0;
+
+ if (chip->charging_disabled || !chip->bat_if_base)
+ return rc;
+
+ if (chip->type == SMBB)
+ rc = qpnp_chg_masked_write(chip,
+ chip->bat_if_base + CHGR_BAT_IF_SPARE,
+ BATFET_LPM_MASK,
+ enable ? BATFET_NO_LPM : BATFET_LPM, 1);
+ else
+ rc = qpnp_chg_masked_write(chip,
+ chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4,
+ BATFET_LPM_MASK,
+ enable ? BATFET_NO_LPM : BATFET_LPM, 1);
+
+ return rc;
+}
+
#define ENUM_T_STOP_BIT BIT(0)
static irqreturn_t
qpnp_chg_usb_usbin_valid_irq_handler(int irq, void *_chip)
{
struct qpnp_chg_chip *chip = _chip;
- int usb_present, host_mode;
+ int usb_present, host_mode, usbin_health;
+ u8 psy_health_sts;
usb_present = qpnp_chg_is_usb_chg_plugged_in(chip);
host_mode = qpnp_chg_is_otg_en_set(chip);
@@ -1136,15 +1387,55 @@
if (chip->usb_present ^ usb_present) {
chip->usb_present = usb_present;
if (!usb_present) {
+ /* when a valid charger inserted, and increase the
+ * charger voltage to OVP threshold, then
+ * usb_in_valid falling edge interrupt triggers.
+ * So we handle the OVP monitor here, and ignore
+ * other health state changes */
+ if (chip->ovp_monitor_enable &&
+ (chip->usb_valid_check_ovp)) {
+ usbin_health =
+ qpnp_chg_check_usbin_health(chip);
+ if (chip->usbin_health != usbin_health) {
+ chip->usbin_health = usbin_health;
+ if (usbin_health == USBIN_OVP)
+ psy_health_sts =
+ POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+ power_supply_set_health_state(
+ chip->usb_psy,
+ psy_health_sts);
+ power_supply_changed(chip->usb_psy);
+ }
+ }
if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
chip->delta_vddmax_mv = 0;
qpnp_chg_set_appropriate_vddmax(chip);
+ chip->chg_done = false;
}
qpnp_chg_usb_suspend_enable(chip, 1);
- if (!qpnp_chg_is_dc_chg_plugged_in(chip))
- chip->chg_done = false;
chip->prev_usb_max_ma = -EINVAL;
} else {
+ /* when OVP clamped usbin, and then decrease
+ * the charger voltage to lower than the OVP
+ * threshold, a usbin_valid rising edge
+ * interrupt triggered. So we change the usb
+ * psy health state back to good */
+ if (chip->ovp_monitor_enable &&
+ (chip->usb_valid_check_ovp)) {
+ usbin_health =
+ qpnp_chg_check_usbin_health(chip);
+ if (chip->usbin_health != usbin_health) {
+ chip->usbin_health = usbin_health;
+ if (usbin_health == USBIN_OK)
+ psy_health_sts =
+ POWER_SUPPLY_HEALTH_GOOD;
+ power_supply_set_health_state(
+ chip->usb_psy,
+ psy_health_sts);
+ power_supply_changed(chip->usb_psy);
+ }
+ }
+
if (!qpnp_chg_is_dc_chg_plugged_in(chip)) {
chip->delta_vddmax_mv = 0;
qpnp_chg_set_appropriate_vddmax(chip);
@@ -1155,6 +1446,7 @@
}
power_supply_set_present(chip->usb_psy, chip->usb_present);
+ schedule_work(&chip->batfet_lcl_work);
}
return IRQ_HANDLED;
@@ -1232,6 +1524,7 @@
power_supply_changed(&chip->dc_psy);
pr_debug("psy changed batt_psy\n");
power_supply_changed(&chip->batt_psy);
+ schedule_work(&chip->batfet_lcl_work);
}
return IRQ_HANDLED;
@@ -1346,6 +1639,7 @@
case POWER_SUPPLY_PROP_CHARGING_ENABLED:
case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
case POWER_SUPPLY_PROP_COOL_TEMP:
case POWER_SUPPLY_PROP_WARM_TEMP:
@@ -1456,6 +1750,7 @@
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM,
POWER_SUPPLY_PROP_VOLTAGE_MIN,
POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
@@ -1478,7 +1773,11 @@
static int charger_monitor;
module_param(charger_monitor, int, 0644);
+static int ext_ovp_present;
+module_param(ext_ovp_present, int, 0444);
+
#define USB_WALL_THRESHOLD_MA 500
+#define OVP_USB_WALL_THRESHOLD_MA 200
static int
qpnp_power_get_property_mains(struct power_supply *psy,
enum power_supply_property psp,
@@ -1820,8 +2119,12 @@
if (((ret.intval / 1000) > USB_WALL_THRESHOLD_MA)
&& (charger_monitor ||
!chip->charger_monitor_checked)) {
- qpnp_chg_iusbmax_set(chip,
+ if (!ext_ovp_present)
+ qpnp_chg_iusbmax_set(chip,
USB_WALL_THRESHOLD_MA);
+ else
+ qpnp_chg_iusbmax_set(chip,
+ OVP_USB_WALL_THRESHOLD_MA);
} else {
qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
}
@@ -1913,6 +2216,9 @@
case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
val->intval = qpnp_chg_usb_iusbmax_get(chip) * 1000;
break;
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
+ val->intval = qpnp_chg_iusb_trim_get(chip);
+ break;
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
val->intval = qpnp_chg_vinmin_get(chip) * 1000;
break;
@@ -2353,20 +2659,50 @@
.list_voltage = qpnp_chg_regulator_boost_list_voltage,
};
-#define BATFET_LPM_MASK 0xC0
-#define BATFET_LPM 0x40
-#define BATFET_NO_LPM 0x00
+static int
+qpnp_chg_bat_if_batfet_reg_enabled(struct qpnp_chg_chip *chip)
+{
+ int rc = 0;
+ u8 reg = 0;
+
+ if (!chip->bat_if_base)
+ return rc;
+
+ if (chip->type == SMBB)
+ rc = qpnp_chg_read(chip, ®,
+ chip->bat_if_base + CHGR_BAT_IF_SPARE, 1);
+ else
+ rc = qpnp_chg_read(chip, ®,
+ chip->bat_if_base + CHGR_BAT_IF_BATFET_CTRL4, 1);
+
+ if (rc) {
+ pr_err("failed to read batt_if rc=%d\n", rc);
+ return rc;
+ }
+
+ if ((reg & BATFET_LPM_MASK) == BATFET_NO_LPM)
+ return 1;
+
+ return 0;
+}
+
static int
qpnp_chg_regulator_batfet_enable(struct regulator_dev *rdev)
{
struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
- int rc;
+ int rc = 0;
- rc = qpnp_chg_masked_write(chip,
- chip->bat_if_base + CHGR_BAT_IF_SPARE,
- BATFET_LPM_MASK, BATFET_NO_LPM, 1);
- if (rc)
- pr_err("failed to write to batt_if rc=%d\n", rc);
+ mutex_lock(&chip->batfet_vreg_lock);
+ /* Only enable if not already enabled */
+ if (!qpnp_chg_bat_if_batfet_reg_enabled(chip)) {
+ rc = qpnp_chg_regulator_batfet_set(chip, 1);
+ if (rc)
+ pr_err("failed to write to batt_if rc=%d\n", rc);
+ }
+
+ chip->batfet_ext_en = true;
+ mutex_unlock(&chip->batfet_vreg_lock);
+
return rc;
}
@@ -2374,13 +2710,20 @@
qpnp_chg_regulator_batfet_disable(struct regulator_dev *rdev)
{
struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
- int rc;
+ int rc = 0;
- rc = qpnp_chg_masked_write(chip,
- chip->bat_if_base + CHGR_BAT_IF_SPARE,
- BATFET_LPM_MASK, BATFET_LPM, 1);
- if (rc)
- pr_err("failed to write to batt_if rc=%d\n", rc);
+ mutex_lock(&chip->batfet_vreg_lock);
+ /* Don't allow disable if charger connected */
+ if (!qpnp_chg_is_usb_chg_plugged_in(chip) &&
+ !qpnp_chg_is_dc_chg_plugged_in(chip)) {
+ rc = qpnp_chg_regulator_batfet_set(chip, 0);
+ if (rc)
+ pr_err("failed to write to batt_if rc=%d\n", rc);
+ }
+
+ chip->batfet_ext_en = false;
+ mutex_unlock(&chip->batfet_vreg_lock);
+
return rc;
}
@@ -2388,20 +2731,8 @@
qpnp_chg_regulator_batfet_is_enabled(struct regulator_dev *rdev)
{
struct qpnp_chg_chip *chip = rdev_get_drvdata(rdev);
- int rc;
- u8 reg;
- rc = qpnp_chg_read(chip, ®,
- chip->bat_if_base + CHGR_BAT_IF_SPARE, 1);
- if (rc) {
- pr_err("failed to read batt_if rc=%d\n", rc);
- return rc;
- }
-
- if (reg && BATFET_LPM_MASK == BATFET_NO_LPM)
- return 1;
-
- return 0;
+ return chip->batfet_ext_en;
}
static struct regulator_ops qpnp_chg_batfet_vreg_ops = {
@@ -2890,6 +3221,25 @@
}
static void
+qpnp_chg_batfet_lcl_work(struct work_struct *work)
+{
+ struct qpnp_chg_chip *chip = container_of(work,
+ struct qpnp_chg_chip, batfet_lcl_work);
+
+ mutex_lock(&chip->batfet_vreg_lock);
+ if (qpnp_chg_is_usb_chg_plugged_in(chip) ||
+ qpnp_chg_is_dc_chg_plugged_in(chip)) {
+ qpnp_chg_regulator_batfet_set(chip, 1);
+ pr_debug("disabled ULPM\n");
+ } else if (!chip->batfet_ext_en && !qpnp_chg_is_usb_chg_plugged_in(chip)
+ && !qpnp_chg_is_dc_chg_plugged_in(chip)) {
+ qpnp_chg_regulator_batfet_set(chip, 0);
+ pr_debug("enabled ULPM\n");
+ }
+ mutex_unlock(&chip->batfet_vreg_lock);
+}
+
+static void
qpnp_chg_reduce_power_stage_work(struct work_struct *work)
{
struct qpnp_chg_chip *chip = container_of(work,
@@ -2974,6 +3324,9 @@
case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
qpnp_chg_iusbmax_set(chip, val->intval / 1000);
break;
+ case POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM:
+ qpnp_chg_iusb_trim_set(chip, val->intval);
+ break;
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
qpnp_chg_vinmin_set(chip, val->intval / 1000);
break;
@@ -3178,6 +3531,27 @@
case SMBB_USB_CHGPTH_SUBTYPE:
case SMBBP_USB_CHGPTH_SUBTYPE:
case SMBCL_USB_CHGPTH_SUBTYPE:
+ if (chip->ovp_monitor_enable) {
+ chip->coarse_det_usb.irq =
+ spmi_get_irq_byname(spmi,
+ spmi_resource, "coarse-det-usb");
+ if (chip->coarse_det_usb.irq < 0) {
+ pr_err("Can't get coarse-det irq\n");
+ return rc;
+ }
+ rc = devm_request_irq(chip->dev,
+ chip->coarse_det_usb.irq,
+ qpnp_chg_coarse_det_usb_irq_handler,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING,
+ "coarse-det-usb", chip);
+ if (rc < 0) {
+ pr_err("Can't req %d coarse-det: %d\n",
+ chip->coarse_det_usb.irq, rc);
+ return rc;
+ }
+ }
+
chip->usbin_valid.irq = spmi_get_irq_byname(spmi,
spmi_resource, "usbin-valid");
if (chip->usbin_valid.irq < 0) {
@@ -3313,6 +3687,8 @@
case SMBB_CHGR_SUBTYPE:
case SMBBP_CHGR_SUBTYPE:
case SMBCL_CHGR_SUBTYPE:
+ qpnp_chg_vbatweak_set(chip, chip->batt_weak_voltage_mv);
+
rc = qpnp_chg_vinmin_set(chip, chip->min_voltage_mv);
if (rc) {
pr_debug("failed setting min_voltage rc=%d\n", rc);
@@ -3635,6 +4011,7 @@
OF_PROP_READ(chip, hot_batt_p, "batt-hot-percentage", rc, 1);
OF_PROP_READ(chip, cold_batt_p, "batt-cold-percentage", rc, 1);
OF_PROP_READ(chip, soc_resume_limit, "resume-soc", rc, 1);
+ OF_PROP_READ(chip, batt_weak_voltage_mv, "vbatweak-mv", rc, 1);
if (rc)
return rc;
@@ -3675,10 +4052,16 @@
chip->btc_disabled = of_property_read_bool(chip->spmi->dev.of_node,
"qcom,btc-disabled");
+ ext_ovp_present = of_property_read_bool(chip->spmi->dev.of_node,
+ "qcom,ext-ovp-present");
+
/* Get the charging-disabled property */
chip->charging_disabled = of_property_read_bool(chip->spmi->dev.of_node,
"qcom,charging-disabled");
+ chip->ovp_monitor_enable = of_property_read_bool(chip->spmi->dev.of_node,
+ "qcom,ovp-monitor-en");
+
/* Get the duty-cycle-100p property */
chip->duty_cycle_100p = of_property_read_bool(
chip->spmi->dev.of_node,
@@ -3746,10 +4129,14 @@
}
mutex_init(&chip->jeita_configure_lock);
+ spin_lock_init(&chip->usbin_health_monitor_lock);
alarm_init(&chip->reduce_power_stage_alarm, ANDROID_ALARM_RTC_WAKEUP,
qpnp_chg_reduce_power_stage_callback);
INIT_WORK(&chip->reduce_power_stage_work,
qpnp_chg_reduce_power_stage_work);
+ mutex_init(&chip->batfet_vreg_lock);
+ INIT_WORK(&chip->batfet_lcl_work,
+ qpnp_chg_batfet_lcl_work);
/* Get all device tree properties */
rc = qpnp_charger_read_dt_props(chip);
@@ -3959,6 +4346,8 @@
INIT_DELAYED_WORK(&chip->eoc_work, qpnp_eoc_work);
INIT_DELAYED_WORK(&chip->arb_stop_work, qpnp_arb_stop_work);
+ INIT_DELAYED_WORK(&chip->usbin_health_check,
+ qpnp_usbin_health_check_work);
INIT_WORK(&chip->soc_check_work, qpnp_chg_soc_check_work);
INIT_DELAYED_WORK(&chip->aicl_check_work, qpnp_aicl_check_work);
diff --git a/drivers/rtc/alarm-dev.c b/drivers/rtc/alarm-dev.c
index 1d60e97..4682e9c 100644
--- a/drivers/rtc/alarm-dev.c
+++ b/drivers/rtc/alarm-dev.c
@@ -98,7 +98,7 @@
wake_unlock(&alarm_wake_lock);
}
alarm_enabled &= ~alarm_type_mask;
- if (alarm_type == ANDROID_ALARM_RTC_WAKEUP)
+ if (alarm_type == ANDROID_ALARM_RTC_POWEROFF_WAKEUP)
set_power_on_alarm(0);
spin_unlock_irqrestore(&alarm_slock, flags);
break;
@@ -127,7 +127,7 @@
alarm_start_range(&alarms[alarm_type],
timespec_to_ktime(new_alarm_time),
timespec_to_ktime(new_alarm_time));
- if ((alarm_type == ANDROID_ALARM_RTC_WAKEUP) &&
+ if ((alarm_type == ANDROID_ALARM_RTC_POWEROFF_WAKEUP) &&
(ANDROID_ALARM_BASE_CMD(cmd) ==
ANDROID_ALARM_SET(0)))
set_power_on_alarm(new_alarm_time.tv_sec);
@@ -171,6 +171,7 @@
switch (alarm_type) {
case ANDROID_ALARM_RTC_WAKEUP:
case ANDROID_ALARM_RTC:
+ case ANDROID_ALARM_RTC_POWEROFF_WAKEUP:
getnstimeofday(&tmp_time);
break;
case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
diff --git a/drivers/rtc/alarm.c b/drivers/rtc/alarm.c
index 1648cba..7d59e28 100644
--- a/drivers/rtc/alarm.c
+++ b/drivers/rtc/alarm.c
@@ -81,7 +81,8 @@
{
struct alarm *alarm;
bool is_wakeup = base == &alarms[ANDROID_ALARM_RTC_WAKEUP] ||
- base == &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP];
+ base == &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP] ||
+ base == &alarms[ANDROID_ALARM_RTC_POWEROFF_WAKEUP];
if (base->stopped) {
pr_alarm(FLOW, "changed alarm while setting the wall time\n");
@@ -423,15 +424,25 @@
hrtimer_cancel(&alarms[ANDROID_ALARM_RTC_WAKEUP].timer);
hrtimer_cancel(&alarms[
ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].timer);
+ hrtimer_cancel(&alarms[
+ ANDROID_ALARM_RTC_POWEROFF_WAKEUP].timer);
tmp_queue = &alarms[ANDROID_ALARM_RTC_WAKEUP];
if (tmp_queue->first)
wakeup_queue = tmp_queue;
+
tmp_queue = &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP];
if (tmp_queue->first && (!wakeup_queue ||
hrtimer_get_expires(&tmp_queue->timer).tv64 <
hrtimer_get_expires(&wakeup_queue->timer).tv64))
wakeup_queue = tmp_queue;
+
+ tmp_queue = &alarms[ANDROID_ALARM_RTC_POWEROFF_WAKEUP];
+ if (tmp_queue->first && (!wakeup_queue ||
+ hrtimer_get_expires(&tmp_queue->timer).tv64 <
+ hrtimer_get_expires(&wakeup_queue->timer).tv64))
+ wakeup_queue = tmp_queue;
+
if (wakeup_queue) {
rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time);
getnstimeofday(&wall_time);
@@ -466,6 +477,8 @@
false);
update_timer_locked(&alarms[
ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP], false);
+ update_timer_locked(&alarms[
+ ANDROID_ALARM_RTC_POWEROFF_WAKEUP], false);
err = -EBUSY;
spin_unlock_irqrestore(&alarm_slock, flags);
}
@@ -489,6 +502,8 @@
update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP], false);
update_timer_locked(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP],
false);
+ update_timer_locked(&alarms[ANDROID_ALARM_RTC_POWEROFF_WAKEUP],
+ false);
spin_unlock_irqrestore(&alarm_slock, flags);
return 0;
diff --git a/drivers/spi/spi_qsd.c b/drivers/spi/spi_qsd.c
index 4512d02..45400cb 100644
--- a/drivers/spi/spi_qsd.c
+++ b/drivers/spi/spi_qsd.c
@@ -652,8 +652,6 @@
if (dd->qup_ver == SPI_QUP_VERSION_NONE)
/* flags removed from SPI_CONFIG in QUP version-2 */
msm_spi_set_bpw_and_no_io_flags(dd, &spi_config, bpw-1);
- else if (dd->mode == SPI_BAM_MODE)
- spi_config |= SPI_CFG_INPUT_FIRST;
/*
* HS_MODE improves signal stability for spi-clk high rates
diff --git a/drivers/spmi/spmi-dbgfs.h b/drivers/spmi/spmi-dbgfs.h
index 10e98b9..a419002 100644
--- a/drivers/spmi/spmi-dbgfs.h
+++ b/drivers/spmi/spmi-dbgfs.h
@@ -18,8 +18,14 @@
int spmi_dfs_add_controller(struct spmi_controller *ctrl);
int spmi_dfs_del_controller(struct spmi_controller *ctrl);
#else
-static int spmi_dfs_add_controller(struct spmi_controller *ctrl) { return 0; }
-static int spmi_dfs_del_controller(struct spmi_controller *ctrl) { return 0; }
+static inline int spmi_dfs_add_controller(struct spmi_controller *ctrl)
+{
+ return 0;
+}
+static inline int spmi_dfs_del_controller(struct spmi_controller *ctrl)
+{
+ return 0;
+}
#endif
struct dentry *spmi_dfs_create_file(struct spmi_controller *ctrl,
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 674efb3..068dd5f 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -780,6 +780,7 @@
bool softconnect;
void (*notify_event) (struct dwc3 *, unsigned);
int tx_fifo_size;
+ bool tx_fifo_reduced;
};
/* -------------------------------------------------------------------------- */
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 60d7119..784ff3f 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -69,6 +69,10 @@
module_param(override_phy_init, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(override_phy_init, "Override HSPHY Init Seq");
+static int ss_phy_override_deemphasis;
+module_param(ss_phy_override_deemphasis, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(ss_phy_override_deemphasis, "Override SSPHY demphasis value");
+
/* Enable Proprietary charger detection */
static bool prop_chg_detect;
module_param(prop_chg_detect, bool, S_IRUGO | S_IWUSR);
@@ -198,6 +202,7 @@
atomic_t in_lpm;
int hs_phy_irq;
int hsphy_init_seq;
+ int deemphasis_val;
bool lpm_irq_seen;
struct delayed_work resume_work;
struct work_struct restart_usb_work;
@@ -1037,10 +1042,13 @@
struct dwc3 *dwc = dep->dwc;
struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
- if (qdss_enabled)
+ if (qdss_enabled) {
+ dwc->tx_fifo_reduced = true;
dwc->tx_fifo_size = mdwc->qdss_tx_fifo_size;
- else
+ } else {
+ dwc->tx_fifo_reduced = false;
dwc->tx_fifo_size = mdwc->tx_fifo_size;
+ }
}
EXPORT_SYMBOL(dwc3_tx_fifo_resize_request);
@@ -1416,7 +1424,12 @@
*/
data = dwc3_msm_ssusb_read_phycreg(mdwc->base, 0x1002);
data &= ~0x3F80;
- data |= (0x16 << 7);
+ if (ss_phy_override_deemphasis)
+ mdwc->deemphasis_val = ss_phy_override_deemphasis;
+ if (mdwc->deemphasis_val)
+ data |= (mdwc->deemphasis_val << 7);
+ else
+ data |= (0x16 << 7);
data &= ~0x7F;
data |= (0x7F | (1 << 14));
dwc3_msm_ssusb_write_phycreg(mdwc->base, 0x1002, data);
@@ -2978,6 +2991,10 @@
else if (!mdwc->hsphy_init_seq)
dev_warn(&pdev->dev, "incorrect hsphyinitseq.Using PORvalue\n");
+ if (of_property_read_u32(node, "qcom,dwc-ssphy-deemphasis-value",
+ &mdwc->deemphasis_val))
+ dev_dbg(&pdev->dev, "unable to read ssphy deemphasis value\n");
+
pm_runtime_set_active(mdwc->dev);
pm_runtime_enable(mdwc->dev);
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index 5348eb5..9599936 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -24,7 +24,7 @@
#include "io.h"
#include "xhci.h"
-#define VBUS_REG_CHECK_DELAY (jiffies + msecs_to_jiffies(1000))
+#define VBUS_REG_CHECK_DELAY (msecs_to_jiffies(1000))
#define MAX_INVALID_CHRGR_RETRY 3
static int max_chgr_retry_count = MAX_INVALID_CHRGR_RETRY;
module_param(max_chgr_retry_count, int, S_IRUGO | S_IWUSR);
@@ -678,7 +678,7 @@
struct dwc3_charger *charger = dotg->charger;
bool work = 0;
int ret = 0;
- int delay = 0;
+ unsigned long delay = 0;
pm_runtime_resume(phy->dev);
dev_dbg(phy->dev, "%s state\n", otg_state_string(phy->state));
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 8fa4774..38c4b86 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -229,14 +229,20 @@
tmp = mult * (dep->endpoint.maxpacket + mdwidth);
if (dwc->tx_fifo_size &&
- (usb_endpoint_xfer_bulk(dep->endpoint.desc)
- || usb_endpoint_xfer_isoc(dep->endpoint.desc)))
+ (usb_endpoint_xfer_bulk(dep->endpoint.desc)
+ || usb_endpoint_xfer_isoc(dep->endpoint.desc))) {
/*
* Allocate 3KB fifo size for bulk and isochronous TX
- * endpoints irrespective of speed. For interrupt
- * endpoint, allocate fifo size of endpoint maxpacket.
+ * endpoints irrespective of speed if tx_fifo is not
+ * reduced. Otherwise allocate 1KB for endpoints in HS
+ * mode and for non burst endpoints in SS mode. For
+ * interrupt ep, allocate fifo size of ep maxpacket.
*/
- tmp = 3 * (1024 + mdwidth);
+ if (!dwc->tx_fifo_reduced)
+ tmp = 3 * (1024 + mdwidth);
+ else
+ tmp = mult * (1024 + mdwidth);
+ }
tmp += mdwidth;
@@ -2617,10 +2623,13 @@
}
}
+ /*
+ * Notify suspend only to gadget driver, but not resume. Resume is
+ * notified as part of wakeup event in dwc3_gadget_wakeup_interrupt().
+ */
if (next == DWC3_LINK_STATE_U0) {
if (dwc->link_state == DWC3_LINK_STATE_U3) {
dbg_event(0xFF, "RESUME", 0);
- dwc->gadget_driver->resume(&dwc->gadget);
}
} else if (next == DWC3_LINK_STATE_U3) {
dbg_event(0xFF, "SUSPEND", 0);
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index bbb206d..6765078 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -1478,7 +1478,11 @@
rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2],
rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]);
- ret = gether_setup_name(c->cdev->gadget, rndis->ethaddr, "rndis");
+ if (rndis->ethaddr[0])
+ ret = gether_setup_name(c->cdev->gadget, NULL, "rndis");
+ else
+ ret = gether_setup_name(c->cdev->gadget, rndis->ethaddr,
+ "rndis");
if (ret) {
pr_err("%s: gether_setup failed\n", __func__);
return ret;
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index e4fb26a..7d63bf9 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1356,6 +1356,14 @@
if (c && c->setup)
value = c->setup(c, ctrl);
}
+ if (value == USB_GADGET_DELAYED_STATUS) {
+ DBG(cdev,
+ "%s: interface %d (%s) requested delayed status\n",
+ __func__, intf, f->name);
+ cdev->delayed_status++;
+ DBG(cdev, "delayed_status count %d\n",
+ cdev->delayed_status);
+ }
goto done;
}
diff --git a/drivers/usb/gadget/f_diag.c b/drivers/usb/gadget/f_diag.c
index bccc504..effe0fd 100644
--- a/drivers/usb/gadget/f_diag.c
+++ b/drivers/usb/gadget/f_diag.c
@@ -837,17 +837,28 @@
struct dentry *dent_diag;
static void fdiag_debugfs_init(void)
{
+ struct dentry *dent_diag_status;
dent_diag = debugfs_create_dir("usb_diag", 0);
- if (IS_ERR(dent_diag))
+ if (!dent_diag || IS_ERR(dent_diag))
return;
- debugfs_create_file("status", 0444, dent_diag, 0, &debug_fdiag_ops);
+ dent_diag_status = debugfs_create_file("status", 0444, dent_diag, 0,
+ &debug_fdiag_ops);
+
+ if (!dent_diag_status || IS_ERR(dent_diag_status)) {
+ debugfs_remove(dent_diag);
+ dent_diag = NULL;
+ return;
+ }
+}
+
+static void fdiag_debugfs_remove(void)
+{
+ debugfs_remove_recursive(dent_diag);
}
#else
-static void fdiag_debugfs_init(void)
-{
- return;
-}
+static inline void fdiag_debugfs_init(void) {}
+static inline void fdiag_debugfs_remove(void) {}
#endif
static void diag_cleanup(void)
@@ -856,7 +867,7 @@
struct usb_diag_ch *_ch;
unsigned long flags;
- debugfs_remove_recursive(dent_diag);
+ fdiag_debugfs_remove();
list_for_each_safe(act, tmp, &usb_diag_ch_list) {
_ch = list_entry(act, struct usb_diag_ch, list);
diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c
index 2f35315..4410e99 100644
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -637,7 +637,10 @@
*/
DBG(fsg, "bulk reset request\n");
raise_exception(fsg->common, FSG_STATE_RESET);
- return DELAYED_STATUS;
+ if (fsg->common->cdev)
+ return USB_GADGET_DELAYED_STATUS;
+ else
+ return DELAYED_STATUS;
case US_BULK_GET_MAX_LUN:
if (ctrl->bRequestType !=
@@ -2698,8 +2701,13 @@
&common->fsg->atomic_bitflags))
usb_ep_clear_halt(common->fsg->bulk_in);
- if (common->ep0_req_tag == exception_req_tag)
- ep0_queue(common); /* Complete the status stage */
+ if (common->ep0_req_tag == exception_req_tag) {
+ /* Complete the status stage */
+ if (common->cdev)
+ usb_composite_setup_continue(common->cdev);
+ else
+ ep0_queue(common);
+ }
/*
* Technically this should go here, but it would only be
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 6bfa203..2fa8c63 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -1219,6 +1219,7 @@
for (i = 0; i < nr_rmnet_ports; i++)
kfree(rmnet_ports[i].port);
+ gbam_cleanup();
nr_rmnet_ports = 0;
no_ctrl_smd_ports = 0;
no_ctrl_qti_ports = 0;
diff --git a/drivers/usb/gadget/f_rmnet_smd.c b/drivers/usb/gadget/f_rmnet_smd.c
index 8aec34f..74a8062 100644
--- a/drivers/usb/gadget/f_rmnet_smd.c
+++ b/drivers/usb/gadget/f_rmnet_smd.c
@@ -5,7 +5,7 @@
* Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
* Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
* Copyright (C) 2008 Nokia Corporation
- * 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 as published by
@@ -1267,19 +1267,17 @@
};
struct dentry *dent_smd;
-struct dentry *dent_smd_status;
-
static void rmnet_smd_debugfs_init(struct rmnet_smd_dev *dev)
{
-
+ struct dentry *dent_smd_status;
dent_smd = debugfs_create_dir("usb_rmnet_smd", 0);
- if (IS_ERR(dent_smd))
+ if (!dent_smd || IS_ERR(dent_smd))
return;
dent_smd_status = debugfs_create_file("status", 0444, dent_smd, dev,
&rmnet_smd_debug_stats_ops);
- if (!dent_smd_status) {
+ if (!dent_smd_status || IS_ERR(dent_smd_status)) {
debugfs_remove(dent_smd);
dent_smd = NULL;
return;
@@ -1287,8 +1285,14 @@
return;
}
+
+static void rmnet_smd_debugfs_remove(void)
+{
+ debugfs_remove_recursive(dent_smd);
+}
#else
-static void rmnet_smd_debugfs_init(struct rmnet_smd_dev *dev) {}
+static inline void rmnet_smd_debugfs_init(struct rmnet_smd_dev *dev) {}
+static inline void rmnet_smd_debugfs_remove(void){}
#endif
static void
@@ -1307,7 +1311,9 @@
dev->epout = dev->epin = dev->epnotify = NULL; /* release endpoints */
destroy_workqueue(dev->wq);
- debugfs_remove_recursive(dent_smd);
+
+ rmnet_smd_debugfs_remove();
+
kfree(dev);
}
diff --git a/drivers/usb/gadget/f_rmnet_smd_sdio.c b/drivers/usb/gadget/f_rmnet_smd_sdio.c
index aa6c99a..2fc758d 100644
--- a/drivers/usb/gadget/f_rmnet_smd_sdio.c
+++ b/drivers/usb/gadget/f_rmnet_smd_sdio.c
@@ -5,7 +5,7 @@
* Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
* Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
* Copyright (C) 2008 Nokia Corporation
- * 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
@@ -1758,16 +1758,28 @@
static void rmnet_mux_debugfs_init(struct rmnet_mux_dev *dev)
{
-
+ struct dentry *dent_rmnet_mux_status;
dent_rmnet_mux = debugfs_create_dir("usb_rmnet_mux", 0);
- if (IS_ERR(dent_rmnet_mux))
+ if (!dent_rmnet_mux || IS_ERR(dent_rmnet_mux))
return;
- debugfs_create_file("status", 0444, dent_rmnet_mux, dev,
+ dent_rmnet_mux_status = debugfs_create_file("status",
+ 0444, dent_rmnet_mux, dev,
&rmnet_mux_svlte_debug_stats_ops);
+ if (!dent_rmnet_mux_status) {
+ debugfs_remove(dent_rmnet_mux);
+ dent_rmnet_mux = NULL;
+ return;
+ }
+}
+
+static void rmnet_mux_debugfs_remove(void)
+{
+ debugfs_remove_recursive(dent_rmnet_mux);
}
#else
-static void rmnet_mux_debugfs_init(struct rmnet_mux_dev *dev) {}
+static inline void rmnet_mux_debugfs_init(struct rmnet_mux_dev *dev) {}
+static inline void rmnet_mux_debugfs_remove(void) {}
#endif
int usb_rmnet_mux_ctrl_open(struct inode *inode, struct file *fp)
@@ -2037,7 +2049,7 @@
struct rmnet_mux_dev *dev = rmux_dev;
struct rmnet_mux_smd_dev *smd_dev = &dev->smd_dev;
- debugfs_remove_recursive(dent_rmnet_mux);
+ rmnet_mux_debugfs_remove();
misc_deregister(&rmnet_mux_ctrl_dev);
smd_close(smd_dev->smd_data.ch);
destroy_workqueue(dev->wq);
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index b0b2f56..843c207 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -1281,22 +1281,30 @@
.write = gbam_reset_stats,
};
+struct dentry *gbam_dent;
static void gbam_debugfs_init(void)
{
- struct dentry *dent;
struct dentry *dfile;
- dent = debugfs_create_dir("usb_rmnet", 0);
- if (IS_ERR(dent))
+ gbam_dent = debugfs_create_dir("usb_rmnet", 0);
+ if (!gbam_dent || IS_ERR(gbam_dent))
return;
- /* TODO: Implement cleanup function to remove created file */
- dfile = debugfs_create_file("status", 0444, dent, 0, &gbam_stats_ops);
- if (!dfile || IS_ERR(dfile))
- debugfs_remove(dent);
+ dfile = debugfs_create_file("status", 0444, gbam_dent, 0,
+ &gbam_stats_ops);
+ if (!dfile || IS_ERR(dfile)) {
+ debugfs_remove(gbam_dent);
+ gbam_dent = NULL;
+ return;
+ }
+}
+static void gbam_debugfs_remove(void)
+{
+ debugfs_remove_recursive(gbam_dent);
}
#else
-static void gam_debugfs_init(void) { }
+static inline void gbam_debugfs_init(void) {}
+static inline void gbam_debugfs_remove(void) {}
#endif
void gbam_disconnect(struct grmnet *gr, u8 port_num, enum transport_type trans)
@@ -1445,7 +1453,6 @@
d->trans = trans;
queue_work(gbam_wq, &port->connect_w);
-
return 0;
}
@@ -1490,6 +1497,7 @@
goto free_bam_ports;
}
}
+
gbam_debugfs_init();
return 0;
@@ -1503,6 +1511,11 @@
return ret;
}
+void gbam_cleanup(void)
+{
+ gbam_debugfs_remove();
+}
+
void gbam_suspend(struct grmnet *gr, u8 port_num, enum transport_type trans)
{
struct gbam_port *port;
diff --git a/drivers/usb/gadget/u_ctrl_hsuart.c b/drivers/usb/gadget/u_ctrl_hsuart.c
index 3443d12..b57e4e3 100644
--- a/drivers/usb/gadget/u_ctrl_hsuart.c
+++ b/drivers/usb/gadget/u_ctrl_hsuart.c
@@ -479,6 +479,7 @@
return ret;
}
+#if defined(CONFIG_DEBUG_FS)
#define DEBUG_BUF_SIZE 1024
static ssize_t ghsuart_ctrl_read_stats(struct file *file, char __user *ubuf,
size_t count, loff_t *ppos)
@@ -558,7 +559,7 @@
ghsuart_ctrl_dfile =
debugfs_create_file("status", S_IRUGO | S_IWUSR,
- ghsuart_ctrl_dent, 0, &gctrl_stats_ops);
+ ghsuart_ctrl_dent, 0, &ghsuart_ctrl_stats_ops);
if (!ghsuart_ctrl_dfile || IS_ERR(ghsuart_ctrl_dfile)) {
debugfs_remove(ghsuart_ctrl_dent);
ghsuart_ctrl_dent = NULL;
@@ -571,6 +572,10 @@
{
debugfs_remove_recursive(ghsuart_ctrl_dent);
}
+#else
+static int ghsuart_ctrl_debugfs_init(void) { return 0; }
+static void ghsuart_ctrl_debugfs_exit(void) {}
+#endif
static int __init ghsuart_ctrl_init(void)
{
diff --git a/drivers/usb/gadget/u_rmnet.h b/drivers/usb/gadget/u_rmnet.h
index 06471a4..6a80529 100644
--- a/drivers/usb/gadget/u_rmnet.h
+++ b/drivers/usb/gadget/u_rmnet.h
@@ -54,6 +54,7 @@
};
int gbam_setup(unsigned int no_bam_port, unsigned int no_bam2bam_port);
+void gbam_cleanup(void);
int gbam_connect(struct grmnet *gr, u8 port_num,
enum transport_type trans, u8 src_connection_idx,
u8 dst_connection_idx);
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 350e723..299f620c 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -4,6 +4,7 @@
* Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
* Copyright (C) 2008 David Brownell
* Copyright (C) 2008 by Nokia Corporation
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
*
* This code also borrows from usbserial.c, which is
* Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com)
@@ -1294,22 +1295,29 @@
.read = debug_read_status,
};
+struct dentry *gs_dent;
static void usb_debugfs_init(struct gs_port *ui_dev, int port_num)
{
- struct dentry *dent;
char buf[48];
snprintf(buf, 48, "usb_serial%d", port_num);
- dent = debugfs_create_dir(buf, 0);
- if (IS_ERR(dent))
+ gs_dent = debugfs_create_dir(buf, 0);
+ if (!gs_dent || IS_ERR(gs_dent))
return;
- debugfs_create_file("readstatus", 0444, dent, ui_dev, &debug_adb_ops);
+ debugfs_create_file("readstatus", 0444, gs_dent, ui_dev,
+ &debug_adb_ops);
debugfs_create_file("reset", S_IRUGO | S_IWUSR,
- dent, ui_dev, &debug_rst_ops);
+ gs_dent, ui_dev, &debug_rst_ops);
+}
+
+static void usb_debugfs_remove(void)
+{
+ debugfs_remove_recursive(gs_dent);
}
#else
-static void usb_debugfs_init(struct gs_port *ui_dev) {}
+static inline void usb_debugfs_init(struct gs_port *ui_dev, int port_num) {}
+static inline void usb_debugfs_remove(void) {}
#endif
/**
@@ -1474,6 +1482,7 @@
}
n_ports = 0;
+ usb_debugfs_remove();
destroy_workqueue(gserial_wq);
tty_unregister_driver(gs_tty_driver);
put_tty_driver(gs_tty_driver);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index f71f54c..4cf4703 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -3607,6 +3607,9 @@
case POWER_SUPPLY_PROP_TYPE:
val->intval = psy->type;
break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ val->intval = motg->usbin_health;
+ break;
default:
return -EINVAL;
}
@@ -3637,6 +3640,9 @@
case POWER_SUPPLY_PROP_TYPE:
psy->type = val->intval;
break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ motg->usbin_health = val->intval;
+ break;
default:
return -EINVAL;
}
@@ -3649,6 +3655,7 @@
enum power_supply_property psp)
{
switch (psp) {
+ case POWER_SUPPLY_PROP_HEALTH:
case POWER_SUPPLY_PROP_PRESENT:
case POWER_SUPPLY_PROP_ONLINE:
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
@@ -3666,6 +3673,7 @@
};
static enum power_supply_property otg_pm_power_props_usb[] = {
+ POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index 5264005..05cc9cc 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -591,6 +591,17 @@
{
int cnt, len, diff, pkt_size, rc = 0;
char cmd;
+ unsigned char *ctrl_base = dsi_host_private->dsi_base;
+ u32 dsi_ctrl, data;
+ int video_mode;
+
+ /* turn on cmd mode for video mode */
+ dsi_ctrl = MIPI_INP(ctrl_base + DSI_CTRL);
+ video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
+ if (video_mode) {
+ data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
+ MIPI_OUTP(ctrl_base + DSI_CTRL, data);
+ }
if (pdata->panel_info.mipi.no_max_pkt_size)
rlen = ALIGN(rlen, 4); /* Only support rlen = 4*n */
@@ -699,6 +710,9 @@
break;
}
+ if (video_mode)
+ MIPI_OUTP(ctrl_base + DSI_CTRL,
+ dsi_ctrl); /* restore */
end:
return rp->len;
}
diff --git a/drivers/video/msm/mdss/dsi_v2.c b/drivers/video/msm/mdss/dsi_v2.c
index 9ca3461..65cca0e 100644
--- a/drivers/video/msm/mdss/dsi_v2.c
+++ b/drivers/video/msm/mdss/dsi_v2.c
@@ -65,6 +65,7 @@
panel_data);
if (enable) {
+ dsi_ctrl_gpio_request(ctrl_pdata);
mdss_dsi_panel_reset(pdata, 1);
rc = dsi_cmds_tx_v2(pdata, &dsi_panel_tx_buf,
@@ -82,6 +83,7 @@
ctrl_pdata->off_cmds.cmd_cnt);
mdss_dsi_panel_reset(pdata, 0);
+ dsi_ctrl_gpio_free(ctrl_pdata);
}
return rc;
}
@@ -139,117 +141,37 @@
struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
struct device_node *np = pdev->dev.of_node;
- int rc = 0, i = 0;
- u32 tmp[9];
ctrl_pdata->disp_en_gpio = of_get_named_gpio(np,
"qcom,platform-enable-gpio", 0);
- if (!gpio_is_valid(ctrl_pdata->disp_en_gpio)) {
+ if (!gpio_is_valid(ctrl_pdata->disp_en_gpio))
pr_err("%s:%d, Disp_en gpio not specified\n",
__func__, __LINE__);
- } else {
- rc = gpio_request(ctrl_pdata->disp_en_gpio, "disp_enable");
- if (rc) {
- pr_err("request reset gpio failed, rc=%d\n",
- rc);
- gpio_free(ctrl_pdata->disp_en_gpio);
- return -ENODEV;
- }
- }
+ ctrl_pdata->disp_te_gpio = -1;
if (ctrl_pdata->panel_data.panel_info.mipi.mode == DSI_CMD_MODE) {
ctrl_pdata->disp_te_gpio = of_get_named_gpio(np,
"qcom,platform-te-gpio", 0);
- if (!gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
+ if (!gpio_is_valid(ctrl_pdata->disp_te_gpio))
pr_err("%s:%d, Disp_te gpio not specified\n",
__func__, __LINE__);
- } else {
- rc = gpio_request(ctrl_pdata->disp_te_gpio, "disp_te");
- if (rc) {
- pr_err("request TE gpio failed, rc=%d\n",
- rc);
- gpio_free(ctrl_pdata->disp_te_gpio);
- return -ENODEV;
- }
- rc = gpio_tlmm_config(GPIO_CFG(
- ctrl_pdata->disp_te_gpio, 1,
- GPIO_CFG_INPUT,
- GPIO_CFG_PULL_DOWN,
- GPIO_CFG_2MA),
- GPIO_CFG_ENABLE);
-
- if (rc) {
- pr_err("%s: unable to config tlmm = %d\n",
- __func__, ctrl_pdata->disp_te_gpio);
- gpio_free(ctrl_pdata->disp_te_gpio);
- return -ENODEV;
- }
-
- rc = gpio_direction_input(ctrl_pdata->disp_te_gpio);
- if (rc) {
- pr_err("set_direction for disp_en gpio failed, rc=%d\n",
- rc);
- gpio_free(ctrl_pdata->disp_te_gpio);
- if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
- gpio_free(ctrl_pdata->disp_en_gpio);
- return -ENODEV;
- }
- pr_debug("%s: te_gpio=%d\n", __func__,
- ctrl_pdata->disp_te_gpio);
- }
}
- rc = of_property_read_u32_array(np,
- "qcom,platform-reset-sequence", tmp, MDSS_DSI_RST_SEQ_LEN);
- if (rc)
- pr_err("%s:%d, unable to read gpio reset sequence\n",
- __func__, __LINE__);
- else
- for (i = 0; i < MDSS_DSI_RST_SEQ_LEN; ++i)
- ctrl_pdata->rst_seq[i] = tmp[i];
-
ctrl_pdata->rst_gpio = of_get_named_gpio(np,
"qcom,platform-reset-gpio", 0);
- if (!gpio_is_valid(ctrl_pdata->rst_gpio)) {
+ if (!gpio_is_valid(ctrl_pdata->rst_gpio))
pr_err("%s:%d, reset gpio not specified\n",
__func__, __LINE__);
- } else {
- rc = gpio_request(ctrl_pdata->rst_gpio, "disp_rst_n");
- if (rc) {
- pr_err("request reset gpio failed, rc=%d\n",
- rc);
- gpio_free(ctrl_pdata->rst_gpio);
- if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
- gpio_free(ctrl_pdata->disp_en_gpio);
- if (gpio_is_valid(ctrl_pdata->disp_te_gpio))
- gpio_free(ctrl_pdata->disp_te_gpio);
- return -ENODEV;
- }
- }
+ ctrl_pdata->mode_gpio = -1;
if (ctrl_pdata->panel_data.panel_info.mode_gpio_state !=
MODE_GPIO_NOT_VALID) {
ctrl_pdata->mode_gpio = of_get_named_gpio(np,
"qcom,platform-mode-gpio", 0);
- if (!gpio_is_valid(ctrl_pdata->mode_gpio)) {
+ if (!gpio_is_valid(ctrl_pdata->mode_gpio))
pr_info("%s:%d, reset gpio not specified\n",
__func__, __LINE__);
- } else {
- rc = gpio_request(ctrl_pdata->mode_gpio, "panel_mode");
- if (rc) {
- pr_err("request panel mode gpio failed,rc=%d\n",
- rc);
- gpio_free(ctrl_pdata->mode_gpio);
- if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
- gpio_free(ctrl_pdata->disp_en_gpio);
- if (gpio_is_valid(ctrl_pdata->rst_gpio))
- gpio_free(ctrl_pdata->rst_gpio);
- if (gpio_is_valid(ctrl_pdata->disp_te_gpio))
- gpio_free(ctrl_pdata->disp_te_gpio);
- return -ENODEV;
- }
- }
}
return 0;
}
@@ -268,15 +190,81 @@
module_power->vreg_config = NULL;
}
module_power->num_vreg = 0;
+}
- if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
- gpio_free(ctrl_pdata->disp_en_gpio);
- if (gpio_is_valid(ctrl_pdata->rst_gpio))
- gpio_free(ctrl_pdata->rst_gpio);
+int dsi_ctrl_gpio_request(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+{
+ int rc = 0;
+
+ if (gpio_is_valid(ctrl_pdata->disp_en_gpio)) {
+ rc = gpio_request(ctrl_pdata->disp_en_gpio, "disp_enable");
+ if (rc)
+ goto gpio_request_err4;
+
+ ctrl_pdata->disp_en_gpio_requested = 1;
+ }
+
+ if (gpio_is_valid(ctrl_pdata->rst_gpio)) {
+ rc = gpio_request(ctrl_pdata->rst_gpio, "disp_rst_n");
+ if (rc)
+ goto gpio_request_err3;
+
+ ctrl_pdata->rst_gpio_requested = 1;
+ }
+
+ if (gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
+ rc = gpio_request(ctrl_pdata->disp_te_gpio, "disp_te");
+ if (rc)
+ goto gpio_request_err2;
+
+ ctrl_pdata->disp_te_gpio_requested = 1;
+ }
+
+ if (gpio_is_valid(ctrl_pdata->mode_gpio)) {
+ rc = gpio_request(ctrl_pdata->mode_gpio, "panel_mode");
+ if (rc)
+ goto gpio_request_err1;
+
+ ctrl_pdata->mode_gpio_requested = 1;
+ }
+
+ return rc;
+
+gpio_request_err1:
if (gpio_is_valid(ctrl_pdata->disp_te_gpio))
gpio_free(ctrl_pdata->disp_te_gpio);
- if (gpio_is_valid(ctrl_pdata->mode_gpio))
+gpio_request_err2:
+ if (gpio_is_valid(ctrl_pdata->rst_gpio))
+ gpio_free(ctrl_pdata->rst_gpio);
+gpio_request_err3:
+ if (gpio_is_valid(ctrl_pdata->disp_en_gpio))
+ gpio_free(ctrl_pdata->disp_en_gpio);
+gpio_request_err4:
+ ctrl_pdata->disp_en_gpio_requested = 0;
+ ctrl_pdata->rst_gpio_requested = 0;
+ ctrl_pdata->disp_te_gpio_requested = 0;
+ ctrl_pdata->mode_gpio_requested = 0;
+ return rc;
+}
+
+void dsi_ctrl_gpio_free(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+{
+ if (ctrl_pdata->disp_en_gpio_requested) {
+ gpio_free(ctrl_pdata->disp_en_gpio);
+ ctrl_pdata->disp_en_gpio_requested = 0;
+ }
+ if (ctrl_pdata->rst_gpio_requested) {
+ gpio_free(ctrl_pdata->rst_gpio);
+ ctrl_pdata->rst_gpio_requested = 0;
+ }
+ if (ctrl_pdata->disp_te_gpio_requested) {
+ gpio_free(ctrl_pdata->disp_te_gpio);
+ ctrl_pdata->disp_te_gpio_requested = 0;
+ }
+ if (ctrl_pdata->mode_gpio_requested) {
gpio_free(ctrl_pdata->mode_gpio);
+ ctrl_pdata->mode_gpio_requested = 0;
+ }
}
static int dsi_parse_vreg(struct device *dev, struct dss_module_power *mp)
diff --git a/drivers/video/msm/mdss/dsi_v2.h b/drivers/video/msm/mdss/dsi_v2.h
index a554856..e15f640 100644
--- a/drivers/video/msm/mdss/dsi_v2.h
+++ b/drivers/video/msm/mdss/dsi_v2.h
@@ -70,6 +70,10 @@
int dsi_ctrl_config_init(struct platform_device *pdev,
struct mdss_dsi_ctrl_pdata *ctrl_pdata);
+int dsi_ctrl_gpio_request(struct mdss_dsi_ctrl_pdata *ctrl_pdata);
+
+void dsi_ctrl_gpio_free(struct mdss_dsi_ctrl_pdata *ctrl_pdata);
+
struct mdss_panel_cfg *mdp3_panel_intf_type(int intf_val);
int mdp3_panel_get_boot_cfg(void);
diff --git a/drivers/video/msm/mdss/mdp3.c b/drivers/video/msm/mdss/mdp3.c
index eff60a3..55037e3 100644
--- a/drivers/video/msm/mdss/mdp3.c
+++ b/drivers/video/msm/mdss/mdp3.c
@@ -1841,6 +1841,14 @@
return rc;
}
+static int mdp3_debug_dump_stats(void *data, char *buf, int len)
+{
+ int total = 0;
+ total = scnprintf(buf, len,"underrun: %08u\n",
+ mdp3_res->underrun_cnt);
+ return total;
+}
+
static void mdp3_debug_enable_clock(int on)
{
if (on)
@@ -1860,7 +1868,7 @@
mdss_res = mdata;
- mdata->debug_inf.debug_dump_stats = NULL;
+ mdata->debug_inf.debug_dump_stats = mdp3_debug_dump_stats;
mdata->debug_inf.debug_enable_clock = mdp3_debug_enable_clock;
rc = mdss_debugfs_init(mdata);
@@ -1882,6 +1890,14 @@
}
}
+static void mdp3_dma_underrun_intr_handler(int type, void *arg)
+{
+ mdp3_res->underrun_cnt++;
+ pr_debug("display underrun detected count=%d\n",
+ mdp3_res->underrun_cnt);
+}
+
+
static int mdp3_probe(struct platform_device *pdev)
{
int rc;
@@ -1892,6 +1908,11 @@
.fb_stride = mdp3_fb_stride,
};
+ struct mdp3_intr_cb underrun_cb = {
+ .cb = mdp3_dma_underrun_intr_handler,
+ .data = NULL,
+ };
+
if (!pdev->dev.of_node) {
pr_err("MDP driver only supports device tree probe\n");
return -ENOTSUPP;
@@ -1939,6 +1960,11 @@
if (rc)
pr_err("unable to register mdp instance\n");
+ rc = mdp3_set_intr_callback(MDP3_INTR_LCDC_UNDERFLOW,
+ &underrun_cb);
+ if (rc)
+ pr_err("unable to configure interrupt callback\n");
+
probe_done:
if (IS_ERR_VALUE(rc)) {
mdp3_res_deinit();
diff --git a/drivers/video/msm/mdss/mdp3.h b/drivers/video/msm/mdss/mdp3.h
index caee34f..4480c20 100644
--- a/drivers/video/msm/mdss/mdp3.h
+++ b/drivers/video/msm/mdss/mdp3.h
@@ -144,6 +144,7 @@
u32 irq_ref_count[MDP3_MAX_INTR];
u32 irq_mask;
struct mdp3_intr_cb callbacks[MDP3_MAX_INTR];
+ u32 underrun_cnt;
int irq_registered;
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.c b/drivers/video/msm/mdss/mdp3_ctrl.c
index a888541..9c909bf 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.c
+++ b/drivers/video/msm/mdss/mdp3_ctrl.c
@@ -481,12 +481,13 @@
pr_err("fail to start the MDP display interface\n");
goto on_error;
}
+ } else {
+ mdp3_session->first_commit = true;
}
on_error:
if (!rc)
mdp3_session->status = 1;
-
mutex_unlock(&mdp3_session->lock);
return rc;
}
@@ -557,6 +558,56 @@
return 0;
}
+static int mdp3_ctrl_reset_cmd(struct msm_fb_data_type *mfd)
+{
+ int rc = 0;
+ struct mdp3_session_data *mdp3_session;
+ struct mdp3_dma *mdp3_dma;
+ struct mdss_panel_data *panel;
+ struct mdp3_vsync_notification vsync_client;
+
+ pr_debug("mdp3_ctrl_reset_cmd\n");
+ mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+ if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
+ !mdp3_session->intf) {
+ pr_err("mdp3_ctrl_reset no device");
+ return -ENODEV;
+ }
+
+ panel = mdp3_session->panel;
+ mdp3_dma = mdp3_session->dma;
+ mutex_lock(&mdp3_session->lock);
+
+ vsync_client = mdp3_dma->vsync_client;
+
+ rc = mdp3_dma->stop(mdp3_dma, mdp3_session->intf);
+ if (rc) {
+ pr_err("fail to stop the MDP3 dma\n");
+ goto reset_error;
+ }
+
+ rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
+ if (rc) {
+ pr_err("fail to attach dma iommu\n");
+ goto reset_error;
+ }
+
+ mdp3_ctrl_intf_init(mfd, mdp3_session->intf);
+ mdp3_ctrl_dma_init(mfd, mdp3_dma);
+
+ if (vsync_client.handler)
+ mdp3_dma->vsync_enable(mdp3_dma, &vsync_client);
+
+ if (mfd->fbi->screen_base)
+ rc = mdp3_dma->start(mdp3_dma, mdp3_session->intf);
+ else
+ mdp3_session->first_commit = true;
+
+reset_error:
+ mutex_unlock(&mdp3_session->lock);
+ return rc;
+}
+
static int mdp3_ctrl_reset(struct msm_fb_data_type *mfd)
{
int rc = 0;
@@ -573,11 +624,18 @@
return -ENODEV;
}
+ if (mfd->panel.type == MIPI_CMD_PANEL) {
+ rc = mdp3_ctrl_reset_cmd(mfd);
+ return rc;
+ }
+
panel = mdp3_session->panel;
mdp3_dma = mdp3_session->dma;
mutex_lock(&mdp3_session->lock);
vsync_client = mdp3_dma->vsync_client;
+ if (panel && panel->set_backlight)
+ panel->set_backlight(panel, 0);
rc = mdp3_dma->stop(mdp3_dma, mdp3_session->intf);
if (rc) {
@@ -633,6 +691,8 @@
if (mfd->fbi->screen_base)
rc = mdp3_dma->start(mdp3_dma, mdp3_session->intf);
+ else
+ mdp3_session->first_commit = true;
reset_error:
mutex_unlock(&mdp3_session->lock);
@@ -742,11 +802,15 @@
return rc;
}
-static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd)
+static int mdp3_ctrl_display_commit_kickoff(struct msm_fb_data_type *mfd,
+ struct mdp_display_commit *cmt_data)
{
struct mdp3_session_data *mdp3_session;
struct mdp3_img_data *data;
+ struct mdss_panel_info *panel_info = mfd->panel_info;
int rc = 0;
+ bool reset_done = false;
+ struct mdss_panel_data *panel;
if (!mfd || !mfd->mdp.private1)
return -EINVAL;
@@ -755,9 +819,16 @@
if (!mdp3_session || !mdp3_session->dma)
return -EINVAL;
+ if (mdp3_bufq_count(&mdp3_session->bufq_in) == 0) {
+ pr_debug("no buffer in queue yet\n");
+ return -EPERM;
+ }
+
+ panel = mdp3_session->panel;
if (!mdp3_iommu_is_attached(MDP3_CLIENT_DMA_P)) {
pr_debug("continuous splash screen, IOMMU not attached\n");
mdp3_ctrl_reset(mfd);
+ reset_done = true;
}
mdp3_release_splash_memory();
@@ -781,6 +852,15 @@
data = mdp3_bufq_pop(&mdp3_session->bufq_out);
mdp3_put_img(data, MDP3_CLIENT_DMA_P);
}
+
+ if (mdp3_session->first_commit) {
+ /*wait for one frame time to ensure frame is sent to panel*/
+ msleep(1000 / panel_info->mipi.frame_rate);
+ mdp3_session->first_commit = false;
+ }
+ if (reset_done && (panel && panel->set_backlight))
+ panel->set_backlight(panel, panel->panel_info.bl_max);
+
mutex_unlock(&mdp3_session->lock);
mdss_fb_update_notify_update(mfd);
@@ -794,6 +874,7 @@
struct mdp3_session_data *mdp3_session;
u32 offset;
int bpp;
+ struct mdss_panel_info *panel_info = mfd->panel_info;
pr_debug("mdp3_ctrl_pan_display\n");
if (!mfd || !mfd->mdp.private1)
@@ -836,6 +917,13 @@
pr_debug("mdp3_ctrl_pan_display no memory, stop interface");
mdp3_session->dma->stop(mdp3_session->dma, mdp3_session->intf);
}
+
+ if (mdp3_session->first_commit) {
+ /*wait for one frame time to ensure frame is sent to panel*/
+ msleep(1000 / panel_info->mipi.frame_rate);
+ mdp3_session->first_commit = false;
+ }
+
pan_error:
mutex_unlock(&mdp3_session->lock);
}
diff --git a/drivers/video/msm/mdss/mdp3_ctrl.h b/drivers/video/msm/mdss/mdp3_ctrl.h
index eb32797..7c4f6ac 100644
--- a/drivers/video/msm/mdss/mdp3_ctrl.h
+++ b/drivers/video/msm/mdss/mdp3_ctrl.h
@@ -51,6 +51,7 @@
struct mutex histo_lock;
int lut_sel;
int cc_vect_sel;
+ bool first_commit;
};
int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
diff --git a/drivers/video/msm/mdss/mdp3_dma.c b/drivers/video/msm/mdss/mdp3_dma.c
index 5874286..89f3e27 100644
--- a/drivers/video/msm/mdss/mdp3_dma.c
+++ b/drivers/video/msm/mdss/mdp3_dma.c
@@ -159,6 +159,7 @@
.data = dma,
};
+
struct mdp3_intr_cb hist_cb = {
.cb = mdp3_hist_done_intr_handler,
.data = dma,
@@ -298,6 +299,7 @@
dma->output_config = *output_config;
mdp3_dma_sync_config(dma, source_config);
+ mdp3_irq_enable(MDP3_INTR_LCDC_UNDERFLOW);
mdp3_dma_callback_setup(dma);
return 0;
}
@@ -824,6 +826,7 @@
mdp3_dma_callback_disable(dma, MDP3_DMA_CALLBACK_TYPE_VSYNC |
MDP3_DMA_CALLBACK_TYPE_DMA_DONE);
+ mdp3_irq_disable(MDP3_INTR_LCDC_UNDERFLOW);
init_completion(&dma->dma_comp);
dma->vsync_client.handler = NULL;
diff --git a/drivers/video/msm/mdss/mdp3_ppp.c b/drivers/video/msm/mdss/mdp3_ppp.c
index 6e62cc7..8f6168a 100644
--- a/drivers/video/msm/mdss/mdp3_ppp.c
+++ b/drivers/video/msm/mdss/mdp3_ppp.c
@@ -54,6 +54,7 @@
[MDP_YCRYCB_H2V1] = true,
[MDP_Y_CBCR_H2V1] = true,
[MDP_Y_CRCB_H2V1] = true,
+ [MDP_BGRX_8888] = true,
};
#define MAX_LIST_WINDOW 16
@@ -495,6 +496,9 @@
{
int dst_h, src_w, i;
uint32_t mdp_op = blit_op->mdp_op;
+ void *src_p0 = blit_op->src.p0;
+ void *src_p1 = blit_op->src.p1;
+ void *dst_p0 = blit_op->dst.p0;
src_w = req->src_rect.w;
dst_h = blit_op->dst.roi.height;
@@ -527,8 +531,11 @@
/* this is for a remainder update */
dst_h -= 16;
src_w -= blit_op->src.roi.width;
- /* restore mdp_op since MDPOP_ASCALE have been cleared */
+ /* restore parameters that may have been overwritten */
blit_op->mdp_op = mdp_op;
+ blit_op->src.p0 = src_p0;
+ blit_op->src.p1 = src_p1;
+ blit_op->dst.p0 = dst_p0;
}
if ((dst_h < 0) || (src_w < 0))
@@ -548,8 +555,9 @@
tmp_v =
(MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
MDP_MAX_X_SCALE_FACTOR +
- (MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) %
- MDP_MAX_X_SCALE_FACTOR ? 1 : 0;
+ ((MDP_SCALE_Q_FACTOR *
+ blit_op->dst.roi.height) %
+ MDP_MAX_X_SCALE_FACTOR ? 1 : 0);
/* move x location as roi width gets bigger */
blit_op->src.roi.x -= tmp_v - blit_op->src.roi.width;
@@ -559,8 +567,9 @@
tmp_v =
(MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) /
MDP_MIN_X_SCALE_FACTOR +
- (MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) %
- MDP_MIN_X_SCALE_FACTOR ? 1 : 0;
+ ((MDP_SCALE_Q_FACTOR *
+ blit_op->dst.roi.height) %
+ MDP_MIN_X_SCALE_FACTOR ? 1 : 0);
/*
* we don't move x location for continuity of
diff --git a/drivers/video/msm/mdss/mdp3_ppp_data.c b/drivers/video/msm/mdss/mdp3_ppp_data.c
index e1c0f27..e562ad3 100644
--- a/drivers/video/msm/mdss/mdp3_ppp_data.c
+++ b/drivers/video/msm/mdss/mdp3_ppp_data.c
@@ -16,6 +16,8 @@
#include "mdss_fb.h"
#include "mdp3_ppp.h"
+#define MDP_IS_IMGTYPE_BAD(x) ((x) >= MDP_IMGTYPE_LIMIT)
+
/* bg_config_lut not needed since it is same as src */
const uint32_t src_cfg_lut[MDP_IMGTYPE_LIMIT] = {
[MDP_RGB_565] = MDP_RGB_565_SRC_REG,
@@ -34,6 +36,7 @@
[MDP_YCRYCB_H2V1] = MDP_YCRYCB_H2V1_SRC_REG,
[MDP_Y_CBCR_H2V1] = MDP_Y_CRCB_H2V1_SRC_REG,
[MDP_Y_CRCB_H2V1] = MDP_Y_CRCB_H2V1_SRC_REG,
+ [MDP_BGRX_8888] = MDP_RGBX_8888_SRC_REG,
};
const uint32_t out_cfg_lut[MDP_IMGTYPE_LIMIT] = {
@@ -53,6 +56,7 @@
[MDP_YCRYCB_H2V1] = MDP_YCRYCB_H2V1_DST_REG,
[MDP_Y_CBCR_H2V1] = MDP_Y_CRCB_H2V1_DST_REG,
[MDP_Y_CRCB_H2V1] = MDP_Y_CRCB_H2V1_DST_REG,
+ [MDP_BGRX_8888] = MDP_RGBX_8888_DST_REG,
};
const uint32_t pack_patt_lut[MDP_IMGTYPE_LIMIT] = {
@@ -60,8 +64,8 @@
[MDP_BGR_565] = PPP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8),
[MDP_RGB_888] = PPP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8),
[MDP_BGR_888] = PPP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8),
- [MDP_BGRA_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R,
- CLR_G, CLR_B, 8),
+ [MDP_BGRA_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B,
+ CLR_G, CLR_R, 8),
[MDP_RGBA_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R,
CLR_G, CLR_B, 8),
[MDP_ARGB_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R,
@@ -80,6 +84,8 @@
CLR_CR, CLR_Y, CLR_CB, 8),
[MDP_Y_CBCR_H2V1] = PPP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8),
[MDP_Y_CRCB_H2V1] = PPP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8),
+ [MDP_BGRX_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B,
+ CLR_G, CLR_R, 8),
};
const uint32_t dst_op_reg[MDP_IMGTYPE_LIMIT] = {
@@ -119,6 +125,7 @@
[MDP_Y_CRCB_H2V1] = 1,
[MDP_Y_CRCB_H2V2] = 1,
[MDP_YCRYCB_H2V1] = 2,
+ [MDP_BGRX_8888] = 4,
};
const bool per_pixel_alpha[MDP_IMGTYPE_LIMIT] = {
@@ -1504,56 +1511,56 @@
uint32_t ppp_bpp(uint32_t type)
{
- if (type > MDP_IMGTYPE_LIMIT)
+ if (MDP_IS_IMGTYPE_BAD(type))
return 0;
return bytes_per_pixel[type];
}
uint32_t ppp_src_config(uint32_t type)
{
- if (type > MDP_IMGTYPE_LIMIT)
+ if (MDP_IS_IMGTYPE_BAD(type))
return 0;
return src_cfg_lut[type];
}
uint32_t ppp_out_config(uint32_t type)
{
- if (type > MDP_IMGTYPE_LIMIT)
+ if (MDP_IS_IMGTYPE_BAD(type))
return 0;
return out_cfg_lut[type];
}
uint32_t ppp_pack_pattern(uint32_t type)
{
- if (type > MDP_IMGTYPE_LIMIT)
+ if (MDP_IS_IMGTYPE_BAD(type))
return 0;
return pack_patt_lut[type];
}
uint32_t ppp_dst_op_reg(uint32_t type)
{
- if (type > MDP_IMGTYPE_LIMIT)
+ if (MDP_IS_IMGTYPE_BAD(type))
return 0;
return dst_op_reg[type];
}
uint32_t ppp_src_op_reg(uint32_t type)
{
- if (type > MDP_IMGTYPE_LIMIT)
+ if (MDP_IS_IMGTYPE_BAD(type))
return 0;
return src_op_reg[type];
}
bool ppp_per_p_alpha(uint32_t type)
{
- if (type > MDP_IMGTYPE_LIMIT)
+ if (MDP_IS_IMGTYPE_BAD(type))
return 0;
return per_pixel_alpha[type];
}
bool ppp_multi_plane(uint32_t type)
{
- if (type > MDP_IMGTYPE_LIMIT)
+ if (MDP_IS_IMGTYPE_BAD(type))
return 0;
return multi_plane[type];
}
diff --git a/drivers/video/msm/mdss/mdp3_ppp_hwio.c b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
index a051037..eb01d00 100644
--- a/drivers/video/msm/mdss/mdp3_ppp_hwio.c
+++ b/drivers/video/msm/mdss/mdp3_ppp_hwio.c
@@ -354,6 +354,7 @@
case MDP_ARGB_8888:
case MDP_XRGB_8888:
case MDP_RGBX_8888:
+ case MDP_BGRX_8888:
rgb = true;
default:
break;
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index dd1a95b..b70fe28 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -28,6 +28,8 @@
#define MDSS_REG_WRITE(addr, val) writel_relaxed(val, mdss_res->mdp_base + addr)
#define MDSS_REG_READ(addr) readl_relaxed(mdss_res->mdp_base + addr)
+#define MAX_DRV_SUP_MMB_BLKS 44
+
enum mdss_mdp_clk_type {
MDSS_CLK_AHB,
MDSS_CLK_AXI,
@@ -68,6 +70,9 @@
u32 mdp_rev;
struct clk *mdp_clk[MDSS_MAX_CLK];
struct regulator *fs;
+ struct regulator *vdd_cx;
+ bool batfet_required;
+ struct regulator *batfet;
u32 max_mdp_clk_rate;
struct platform_device *pdev;
@@ -110,6 +115,9 @@
u32 nvig_pipes;
u32 nrgb_pipes;
u32 ndma_pipes;
+
+ DECLARE_BITMAP(mmb_alloc_map, MAX_DRV_SUP_MMB_BLKS);
+
struct mdss_mdp_mixer *mixer_intf;
struct mdss_mdp_mixer *mixer_wb;
u32 nmixers_intf;
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 2d0497c..865775a 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -662,6 +662,43 @@
return rc;
}
+static int mdss_dsi_ctl_partial_update(struct mdss_panel_data *pdata)
+{
+ int rc = -EINVAL;
+ u32 data;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+
+ /* DSI_COMMAND_MODE_MDP_STREAM_CTRL */
+ data = (((pdata->panel_info.roi_w * 3) + 1) << 16) |
+ (pdata->panel_info.mipi.vc << 8) | DTYPE_DCS_LWRITE;
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x60, data);
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x58, data);
+
+ /* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */
+ data = pdata->panel_info.roi_h << 16 | pdata->panel_info.roi_w;
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x64, data);
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x5C, data);
+
+ if (ctrl_pdata->partial_update_fnc)
+ rc = ctrl_pdata->partial_update_fnc(pdata);
+
+ if (rc) {
+ pr_err("%s: unable to initialize the panel\n",
+ __func__);
+ return rc;
+ }
+
+ return rc;
+}
+
static int mdss_dsi_event_handler(struct mdss_panel_data *pdata,
int event, void *arg)
{
@@ -714,7 +751,9 @@
mdss_dsi_clk_req(ctrl_pdata, (int)arg);
break;
case MDSS_EVENT_DSI_CMDLIST_KOFF:
+ ctrl_pdata->recovery = (struct mdss_panel_recovery *)arg;
mdss_dsi_cmdlist_commit(ctrl_pdata, 1);
+ break;
case MDSS_EVENT_PANEL_UPDATE_FPS:
if (arg != NULL) {
rc = mdss_dsi_dfps_config(pdata, (int)arg);
@@ -728,6 +767,9 @@
rc = mdss_dsi_blank(pdata);
}
break;
+ case MDSS_EVENT_ENABLE_PARTIAL_UPDATE:
+ rc = mdss_dsi_ctl_partial_update(pdata);
+ break;
default:
pr_debug("%s: unhandled event=%d\n", __func__, event);
break;
@@ -1029,7 +1071,6 @@
{
struct mipi_panel_info *mipi;
int rc, i, len;
- u32 tmp[9];
struct device_node *dsi_ctrl_np = NULL;
struct platform_device *ctrl_pdev = NULL;
bool dynamic_fps;
@@ -1208,15 +1249,6 @@
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(ctrl_pdev->dev.of_node,
"qcom,platform-reset-gpio", 0);
if (!gpio_is_valid(ctrl_pdata->rst_gpio)) {
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index d538743..6953d8b 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -194,8 +194,6 @@
#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 */
@@ -309,10 +307,15 @@
DSI_CTRL_MAX,
};
+#define DSI_EV_PLL_UNLOCKED 0x0001
+#define DSI_EV_MDP_FIFO_UNDERFLOW 0x0002
+#define DSI_EV_MDP_BUSY_RELEASE 0x80000000
+
struct mdss_dsi_ctrl_pdata {
int ndx; /* panel_num */
int (*on) (struct mdss_panel_data *pdata);
int (*off) (struct mdss_panel_data *pdata);
+ int (*partial_update_fnc) (struct mdss_panel_data *pdata);
struct mdss_panel_data panel_data;
unsigned char *ctrl_base;
int reg_size;
@@ -330,20 +333,25 @@
int disp_en_gpio;
int disp_te_gpio;
int mode_gpio;
+ int rst_gpio_requested;
+ int disp_en_gpio_requested;
+ int disp_te_gpio_requested;
+ int mode_gpio_requested;
int bklt_ctrl; /* backlight ctrl */
int pwm_period;
int pwm_pmic_gpio;
int pwm_lpg_chan;
int bklt_max;
int new_fps;
+ int pwm_enabled;
struct pwm_device *pwm_bl;
struct dsi_drv_cm_data shared_pdata;
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;
+ struct mdss_panel_recovery *recovery;
struct dsi_panel_cmds on_cmds;
struct dsi_panel_cmds off_cmds;
@@ -386,7 +394,7 @@
void mdp4_dsi_cmd_trigger(void);
void mdss_dsi_cmd_mdp_start(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_cmd_bta_sw_trigger(struct mdss_panel_data *pdata);
-void mdss_dsi_ack_err_status(unsigned char *dsi_base);
+void mdss_dsi_ack_err_status(struct mdss_dsi_ctrl_pdata *ctrl);
int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable);
void mdss_dsi_clk_req(struct mdss_dsi_ctrl_pdata *ctrl,
int enable);
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 62bc7e6..845ef10 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -19,11 +19,13 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/iopoll.h>
+#include <linux/kthread.h>
#include <mach/iommu_domains.h>
#include "mdss.h"
#include "mdss_dsi.h"
+#include "mdss_panel.h"
#define VSYNC_PERIOD 17
@@ -44,6 +46,28 @@
.irq_handler = mdss_dsi_isr,
};
+
+#define DSI_EVENT_Q_MAX 4
+
+/* event */
+struct dsi_event_q {
+ struct mdss_dsi_ctrl_pdata *ctrl;
+ u32 todo;
+};
+
+struct mdss_dsi_event {
+ int inited;
+ wait_queue_head_t event_q;
+ u32 event_pndx;
+ u32 event_gndx;
+ struct dsi_event_q todo_list[DSI_EVENT_Q_MAX];
+ spinlock_t event_lock;
+};
+
+static struct mdss_dsi_event dsi_event;
+
+static int dsi_event_thread(void *data);
+
void mdss_dsi_ctrl_init(struct mdss_dsi_ctrl_pdata *ctrl)
{
if (ctrl->shared_pdata.broadcast_enable)
@@ -80,6 +104,13 @@
mutex_init(&ctrl->cmd_mutex);
mdss_dsi_buf_alloc(&ctrl->tx_buf, SZ_4K);
mdss_dsi_buf_alloc(&ctrl->rx_buf, SZ_4K);
+
+
+ if (dsi_event.inited == 0) {
+ kthread_run(dsi_event_thread, (void *)&dsi_event,
+ "mdss_dsi_event");
+ dsi_event.inited = 1;
+ }
}
void mdss_dsi_clk_req(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
@@ -94,6 +125,21 @@
mdss_dsi_clk_ctrl(ctrl, enable);
}
+void mdss_dsi_pll_relock(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ int i, cnt;
+
+ cnt = ctrl->clk_cnt;
+
+ /* disable dsi clk */
+ for (i = 0; i < cnt; i++)
+ mdss_dsi_clk_ctrl(ctrl, 0);
+
+ /* enable dsi clk */
+ for (i = 0; i < cnt; i++)
+ mdss_dsi_clk_ctrl(ctrl, 1);
+}
+
void mdss_dsi_enable_irq(struct mdss_dsi_ctrl_pdata *ctrl, u32 term)
{
unsigned long flags;
@@ -942,6 +988,50 @@
wmb();
}
+void mdss_dsi_sw_reset_restore(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ u32 data0, data1;
+
+ data0 = MIPI_INP(ctrl->ctrl_base + 0x0004);
+ data1 = data0;
+ data1 &= ~0x01;
+ MIPI_OUTP(ctrl->ctrl_base + 0x0004, data1);
+ /*
+ * dsi controller need to be disabled before
+ * clocks turned on
+ */
+ wmb(); /* make sure dsi contoller is disabled */
+
+ /* turn esc, byte, dsi, pclk, sclk, hclk on */
+ MIPI_OUTP(ctrl->ctrl_base + 0x11c, 0x23f); /* DSI_CLK_CTRL */
+ wmb(); /* make sure clocks enabled */
+
+ /* dsi controller can only be reset while clocks are running */
+ MIPI_OUTP(ctrl->ctrl_base + 0x118, 0x01);
+ wmb(); /* make sure reset happen */
+ MIPI_OUTP(ctrl->ctrl_base + 0x118, 0x00);
+ wmb(); /* controller out of reset */
+ MIPI_OUTP(ctrl->ctrl_base + 0x0004, data0);
+ wmb(); /* make sure dsi controller enabled again */
+}
+
+void mdss_dsi_err_intr_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, u32 mask,
+ int enable)
+{
+ u32 intr;
+
+ intr = MIPI_INP(ctrl->ctrl_base + 0x0110);
+
+ if (enable)
+ intr |= mask;
+ else
+ intr &= ~mask;
+
+ pr_debug("%s: intr=%x enable=%d\n", __func__, intr, enable);
+
+ MIPI_OUTP(ctrl->ctrl_base + 0x0110, intr); /* DSI_INTL_CTRL */
+}
+
void mdss_dsi_controller_cfg(int enable,
struct mdss_panel_data *pdata)
{
@@ -1072,7 +1162,7 @@
0, timeout_us))
pr_info("%s: DSI status=%x failed\n", __func__, status);
- mdss_dsi_ack_err_status((ctrl_pdata->ctrl_base));
+ mdss_dsi_ack_err_status(ctrl_pdata);
pr_debug("%s: BTA done, status = %d\n", __func__, status);
}
@@ -1746,9 +1836,89 @@
return ret;
}
-void mdss_dsi_ack_err_status(unsigned char *base)
+
+static void dsi_send_events(struct mdss_dsi_ctrl_pdata *ctrl, u32 events)
+{
+ struct dsi_event_q *evq;
+
+ if (!dsi_event.inited)
+ return;
+
+ pr_debug("%s: ev=%x\n", __func__, events);
+
+ spin_lock(&dsi_event.event_lock);
+ evq = &dsi_event.todo_list[dsi_event.event_pndx++];
+ evq->todo = events;
+ evq->ctrl = ctrl;
+ dsi_event.event_pndx %= DSI_EVENT_Q_MAX;
+ wake_up(&dsi_event.event_q);
+ spin_unlock(&dsi_event.event_lock);
+}
+
+static int dsi_event_thread(void *data)
+{
+ struct mdss_dsi_event *ev;
+ struct dsi_event_q *evq;
+ struct mdss_dsi_ctrl_pdata *ctrl;
+ unsigned long flag;
+ struct sched_param param;
+ u32 todo = 0;
+ int ret;
+
+ param.sched_priority = 16;
+ ret = sched_setscheduler_nocheck(current, SCHED_FIFO, ¶m);
+ if (ret)
+ pr_err("%s: set priority failed\n", __func__);
+
+ ev = (struct mdss_dsi_event *)data;
+ /* event */
+ init_waitqueue_head(&ev->event_q);
+ spin_lock_init(&ev->event_lock);
+
+ while (1) {
+ wait_event(ev->event_q, (ev->event_pndx != ev->event_gndx));
+ spin_lock_irqsave(&ev->event_lock, flag);
+ evq = &ev->todo_list[ev->event_gndx++];
+ todo = evq->todo;
+ ctrl = evq->ctrl;
+ evq->todo = 0;
+ ev->event_gndx %= DSI_EVENT_Q_MAX;
+ spin_unlock_irqrestore(&ev->event_lock, flag);
+
+ pr_debug("%s: ev=%x\n", __func__, todo);
+
+ if (todo & DSI_EV_PLL_UNLOCKED)
+ mdss_dsi_pll_relock(ctrl);
+
+ if (todo & DSI_EV_MDP_FIFO_UNDERFLOW) {
+ if (ctrl->recovery) {
+ mdss_dsi_sw_reset_restore(ctrl);
+ ctrl->recovery->fxn(ctrl->recovery->data);
+ }
+ }
+
+ if (todo & DSI_EV_MDP_BUSY_RELEASE) {
+ spin_lock(&ctrl->mdp_lock);
+ ctrl->mdp_busy = false;
+ mdss_dsi_disable_irq_nosync(ctrl, DSI_MDP_TERM);
+ complete(&ctrl->mdp_comp);
+ spin_unlock(&ctrl->mdp_lock);
+
+ /* enable dsi error interrupt */
+ mdss_dsi_err_intr_ctrl(ctrl, DSI_INTR_ERROR_MASK, 1);
+ }
+
+ }
+
+ return 0;
+}
+
+void mdss_dsi_ack_err_status(struct mdss_dsi_ctrl_pdata *ctrl)
{
u32 status;
+ unsigned char *base;
+
+ base = ctrl->ctrl_base;
status = MIPI_INP(base + 0x0068);/* DSI_ACK_ERR_STATUS */
@@ -1758,20 +1928,27 @@
}
}
-void mdss_dsi_timeout_status(unsigned char *base)
+void mdss_dsi_timeout_status(struct mdss_dsi_ctrl_pdata *ctrl)
{
u32 status;
+ unsigned char *base;
+
+ base = ctrl->ctrl_base;
status = MIPI_INP(base + 0x00c0);/* DSI_TIMEOUT_STATUS */
+
if (status & 0x0111) {
MIPI_OUTP(base + 0x00c0, status);
pr_err("%s: status=%x\n", __func__, status);
}
}
-void mdss_dsi_dln0_phy_err(unsigned char *base)
+void mdss_dsi_dln0_phy_err(struct mdss_dsi_ctrl_pdata *ctrl)
{
u32 status;
+ unsigned char *base;
+
+ base = ctrl->ctrl_base;
status = MIPI_INP(base + 0x00b4);/* DSI_DLN0_PHY_ERR */
@@ -1781,44 +1958,70 @@
}
}
-void mdss_dsi_fifo_status(unsigned char *base)
+void mdss_dsi_fifo_status(struct mdss_dsi_ctrl_pdata *ctrl)
{
u32 status;
+ unsigned char *base;
+
+ base = ctrl->ctrl_base;
status = MIPI_INP(base + 0x000c);/* DSI_FIFO_STATUS */
- if (status & 0x44444489) {
+ /* fifo underflow, overflow */
+ if (status & 0xcccc4489) {
MIPI_OUTP(base + 0x000c, status);
pr_err("%s: status=%x\n", __func__, status);
+ if (status & 0x0080) /* CMD_DMA_FIFO_UNDERFLOW */
+ dsi_send_events(ctrl, DSI_EV_MDP_FIFO_UNDERFLOW);
+ }
+}
+
+void mdss_dsi_status(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ u32 status;
+ unsigned char *base;
+
+ base = ctrl->ctrl_base;
+
+ status = MIPI_INP(base + 0x0008);/* DSI_STATUS */
+
+ if (status & 0x80000000) { /* INTERLEAVE_OP_CONTENTION */
+ MIPI_OUTP(base + 0x0008, status);
+ pr_err("%s: status=%x\n", __func__, status);
}
}
-void mdss_dsi_status(unsigned char *base)
+void mdss_dsi_clk_status(struct mdss_dsi_ctrl_pdata *ctrl)
{
u32 status;
+ unsigned char *base;
- status = MIPI_INP(base + 0x0008);/* DSI_STATUS */
+ base = ctrl->ctrl_base;
+ status = MIPI_INP(base + 0x0120);/* DSI_CLK_STATUS */
- if (status & 0x80000000) {
- MIPI_OUTP(base + 0x0008, status);
+ if (status & 0x10000) { /* DSI_CLK_PLL_UNLOCKED */
+ MIPI_OUTP(base + 0x0120, status);
+ dsi_send_events(ctrl, DSI_EV_PLL_UNLOCKED);
pr_err("%s: status=%x\n", __func__, status);
}
}
void mdss_dsi_error(struct mdss_dsi_ctrl_pdata *ctrl)
{
- unsigned char *base;
- base = ctrl->ctrl_base;
+ /* disable dsi error interrupt */
+ mdss_dsi_err_intr_ctrl(ctrl, DSI_INTR_ERROR_MASK, 0);
/* DSI_ERR_INT_MASK0 */
- mdss_dsi_ack_err_status(base); /* mask0, 0x01f */
- mdss_dsi_timeout_status(base); /* mask0, 0x0e0 */
- mdss_dsi_fifo_status(base); /* mask0, 0x133d00 */
- mdss_dsi_status(base); /* mask0, 0xc0100 */
- mdss_dsi_dln0_phy_err(base); /* mask0, 0x3e00000 */
-}
+ mdss_dsi_clk_status(ctrl); /* Mask0, 0x10000000 */
+ mdss_dsi_fifo_status(ctrl); /* mask0, 0x133d00 */
+ mdss_dsi_ack_err_status(ctrl); /* mask0, 0x01f */
+ mdss_dsi_timeout_status(ctrl); /* mask0, 0x0e0 */
+ mdss_dsi_status(ctrl); /* mask0, 0xc0100 */
+ mdss_dsi_dln0_phy_err(ctrl); /* mask0, 0x3e00000 */
+ dsi_send_events(ctrl, DSI_EV_MDP_BUSY_RELEASE);
+}
irqreturn_t mdss_dsi_isr(int irq, void *ptr)
{
@@ -1846,12 +2049,7 @@
if (isr & DSI_INTR_ERROR) {
pr_err("%s: isr=%x %x", __func__, isr, (int)DSI_INTR_ERROR);
- spin_lock(&ctrl->mdp_lock);
- ctrl->mdp_busy = false;
- mdss_dsi_disable_irq_nosync(ctrl, DSI_MDP_TERM);
- complete(&ctrl->mdp_comp);
mdss_dsi_error(ctrl);
- spin_unlock(&ctrl->mdp_lock);
}
if (isr & DSI_INTR_VIDEO_DONE) {
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 203900c..33109e1 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -66,6 +66,13 @@
return;
}
+ if (level == 0) {
+ if (ctrl->pwm_enabled)
+ pwm_disable(ctrl->pwm_bl);
+ ctrl->pwm_enabled = 0;
+ return;
+ }
+
duty = level * ctrl->pwm_period;
duty /= ctrl->bklt_max;
@@ -76,6 +83,11 @@
pr_debug("%s: ndx=%d level=%d duty=%d\n", __func__,
ctrl->ndx, level, duty);
+ if (ctrl->pwm_enabled) {
+ pwm_disable(ctrl->pwm_bl);
+ ctrl->pwm_enabled = 0;
+ }
+
ret = pwm_config(ctrl->pwm_bl, duty, ctrl->pwm_period);
if (ret) {
pr_err("%s: pwm_config() failed err=%d.\n", __func__, ret);
@@ -85,6 +97,7 @@
ret = pwm_enable(ctrl->pwm_bl);
if (ret)
pr_err("%s: pwm_enable() failed err=%d\n", __func__, ret);
+ ctrl->pwm_enabled = 1;
}
static char dcs_cmd[2] = {0x54, 0x00}; /* DTYPE_DCS_READ */
@@ -182,14 +195,16 @@
pinfo = &(ctrl_pdata->panel_data.panel_info);
if (enable) {
- 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);
+ for (i = 0; i < pdata->panel_info.rst_seq_len; ++i) {
+ gpio_set_value((ctrl_pdata->rst_gpio),
+ pdata->panel_info.rst_seq[i]);
+ if (pdata->panel_info.rst_seq[++i])
+ usleep(pdata->panel_info.rst_seq[i] * 1000);
+ }
+
if (gpio_is_valid(ctrl_pdata->mode_gpio)) {
if (pinfo->mode_gpio_state == MODE_GPIO_HIGH)
gpio_set_value((ctrl_pdata->mode_gpio), 1);
@@ -209,6 +224,61 @@
}
}
+static char caset[] = {0x2a, 0x00, 0x00, 0x03, 0x00}; /* DTYPE_DCS_LWRITE */
+static char paset[] = {0x2b, 0x00, 0x00, 0x05, 0x00}; /* DTYPE_DCS_LWRITE */
+
+static struct dsi_cmd_desc partial_update_enable_cmd[] = {
+ {{DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(caset)}, caset},
+ {{DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(paset)}, paset},
+};
+
+static int mdss_dsi_panel_partial_update(struct mdss_panel_data *pdata)
+{
+ struct mipi_panel_info *mipi;
+ struct mdss_dsi_ctrl_pdata *ctrl = NULL;
+ struct dcs_cmd_req cmdreq;
+ int rc = 0;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+
+ ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+ mipi = &pdata->panel_info.mipi;
+
+ pr_debug("%s: ctrl=%p ndx=%d\n", __func__, ctrl, ctrl->ndx);
+
+ caset[1] = (((pdata->panel_info.roi_x) & 0xFF00) >> 8);
+ caset[2] = (((pdata->panel_info.roi_x) & 0xFF));
+ caset[3] = (((pdata->panel_info.roi_x - 1 + pdata->panel_info.roi_w)
+ & 0xFF00) >> 8);
+ caset[4] = (((pdata->panel_info.roi_x - 1 + pdata->panel_info.roi_w)
+ & 0xFF));
+ partial_update_enable_cmd[0].payload = caset;
+
+ paset[1] = (((pdata->panel_info.roi_y) & 0xFF00) >> 8);
+ paset[2] = (((pdata->panel_info.roi_y) & 0xFF));
+ paset[3] = (((pdata->panel_info.roi_y - 1 + pdata->panel_info.roi_h)
+ & 0xFF00) >> 8);
+ paset[4] = (((pdata->panel_info.roi_y - 1 + pdata->panel_info.roi_h)
+ & 0xFF));
+ partial_update_enable_cmd[1].payload = paset;
+
+ pr_debug("%s: enabling partial update\n", __func__);
+ memset(&cmdreq, 0, sizeof(cmdreq));
+ cmdreq.cmds = partial_update_enable_cmd;
+ cmdreq.cmds_cnt = 2;
+ cmdreq.flags = CMD_REQ_COMMIT | CMD_CLK_CTRL;
+ cmdreq.rlen = 0;
+ cmdreq.cb = NULL;
+
+ mdss_dsi_cmdlist_put(ctrl, &cmdreq);
+
+ return rc;
+}
+
static void mdss_dsi_panel_bl_ctrl(struct mdss_panel_data *pdata,
u32 bl_level)
{
@@ -492,6 +562,35 @@
}
+static int mdss_dsi_parse_reset_seq(struct device_node *np,
+ u32 rst_seq[MDSS_DSI_RST_SEQ_LEN], u32 *rst_len,
+ const char *name)
+{
+ int num = 0, i;
+ int rc;
+ struct property *data;
+ u32 tmp[MDSS_DSI_RST_SEQ_LEN];
+ *rst_len = 0;
+ data = of_find_property(np, name, &num);
+ num /= sizeof(u32);
+ if (!data || !num || num > MDSS_DSI_RST_SEQ_LEN || num % 2) {
+ pr_debug("%s:%d, error reading %s, length found = %d\n",
+ __func__, __LINE__, name, num);
+ } else {
+ rc = of_property_read_u32_array(np, name, tmp, num);
+ if (rc)
+ pr_debug("%s:%d, error reading %s, rc = %d\n",
+ __func__, __LINE__, name, rc);
+ else {
+ for (i = 0; i < num; ++i)
+ rst_seq[i] = tmp[i];
+ *rst_len = num;
+ }
+ }
+ return 0;
+}
+
+
static int mdss_panel_parse_dt(struct device_node *np,
struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
@@ -740,6 +839,9 @@
mdss_dsi_parse_fbc_params(np, pinfo);
+ mdss_dsi_parse_reset_seq(np, pinfo->rst_seq, &(pinfo->rst_seq_len),
+ "qcom,mdss-dsi-reset-sequence");
+
mdss_dsi_parse_dcs_cmds(np, &ctrl_pdata->on_cmds,
"qcom,mdss-dsi-on-command", "qcom,mdss-dsi-on-command-state");
@@ -759,6 +861,7 @@
int rc = 0;
static const char *panel_name;
bool cont_splash_enabled;
+ bool partial_update_enabled;
if (!node) {
pr_err("%s: no panel node\n", __func__);
@@ -795,6 +898,18 @@
ctrl_pdata->panel_data.panel_info.cont_splash_enabled = 1;
}
+ partial_update_enabled = of_property_read_bool(node,
+ "qcom,partial-update-enabled");
+ if (partial_update_enabled) {
+ pr_info("%s:%d Partial update enabled.\n", __func__, __LINE__);
+ ctrl_pdata->panel_data.panel_info.partial_update_enabled = 1;
+ ctrl_pdata->partial_update_fnc = mdss_dsi_panel_partial_update;
+ } else {
+ pr_info("%s:%d Partial update disabled.\n", __func__, __LINE__);
+ ctrl_pdata->panel_data.panel_info.partial_update_enabled = 0;
+ ctrl_pdata->partial_update_fnc = NULL;
+ }
+
ctrl_pdata->on = mdss_dsi_panel_on;
ctrl_pdata->off = mdss_dsi_panel_off;
ctrl_pdata->panel_data.set_backlight = mdss_dsi_panel_bl_ctrl;
diff --git a/drivers/video/msm/mdss/mdss_edp.c b/drivers/video/msm/mdss/mdss_edp.c
index 64caaf5..042491d 100644
--- a/drivers/video/msm/mdss/mdss_edp.c
+++ b/drivers/video/msm/mdss/mdss_edp.c
@@ -164,46 +164,33 @@
ret = of_property_read_u32(edp_drv->pdev->dev.of_node,
"qcom,panel-pwm-period", &edp_drv->pwm_period);
if (ret) {
- pr_err("%s: panel pwm period is not specified, %d", __func__,
+ pr_warn("%s: panel pwm period is not specified, %d", __func__,
edp_drv->pwm_period);
- return -EINVAL;
+ edp_drv->pwm_period = -EINVAL;
}
ret = of_property_read_u32(edp_drv->pdev->dev.of_node,
"qcom,panel-lpg-channel", &edp_drv->lpg_channel);
if (ret) {
- pr_err("%s: panel lpg channel is not specified, %d", __func__,
+ pr_warn("%s: panel lpg channel is not specified, %d", __func__,
edp_drv->lpg_channel);
- return -EINVAL;
+ edp_drv->lpg_channel = -EINVAL;
}
- edp_drv->bl_pwm = pwm_request(edp_drv->lpg_channel, "lcd-backlight");
- if (edp_drv->bl_pwm == NULL || IS_ERR(edp_drv->bl_pwm)) {
- pr_err("%s: pwm request failed", __func__);
+ if (edp_drv->pwm_period != -EINVAL &&
+ edp_drv->lpg_channel != -EINVAL) {
+ edp_drv->bl_pwm = pwm_request(edp_drv->lpg_channel,
+ "lcd-backlight");
+ if (edp_drv->bl_pwm == NULL || IS_ERR(edp_drv->bl_pwm)) {
+ pr_err("%s: pwm request failed", __func__);
+ edp_drv->bl_pwm = NULL;
+ return -EIO;
+ }
+ } else {
edp_drv->bl_pwm = NULL;
- return -EIO;
- }
-
- edp_drv->gpio_panel_pwm = of_get_named_gpio(edp_drv->pdev->dev.of_node,
- "gpio-panel-pwm", 0);
- if (!gpio_is_valid(edp_drv->gpio_panel_pwm)) {
- pr_err("%s: gpio_panel_pwm=%d not specified\n", __func__,
- edp_drv->gpio_panel_pwm);
- goto edp_free_pwm;
- }
-
- ret = gpio_request(edp_drv->gpio_panel_pwm, "disp_pwm");
- if (ret) {
- pr_err("%s: Request reset gpio_panel_pwm failed, ret=%d\n",
- __func__, ret);
- goto edp_free_pwm;
}
return 0;
-
-edp_free_pwm:
- pwm_free(edp_drv->bl_pwm);
- return -ENODEV;
}
void mdss_edp_set_backlight(struct mdss_panel_data *pdata, u32 bl_level)
@@ -218,27 +205,26 @@
return;
}
- bl_max = edp_drv->panel_data.panel_info.bl_max;
- if (bl_level > bl_max)
- bl_level = bl_max;
+ if (edp_drv->bl_pwm != NULL) {
+ bl_max = edp_drv->panel_data.panel_info.bl_max;
+ if (bl_level > bl_max)
+ bl_level = bl_max;
- if (edp_drv->bl_pwm == NULL) {
- pr_err("%s: edp_drv->bl_pwm=NULL.\n", __func__);
- return;
- }
+ ret = pwm_config(edp_drv->bl_pwm,
+ bl_level * edp_drv->pwm_period / bl_max,
+ edp_drv->pwm_period);
+ if (ret) {
+ pr_err("%s: pwm_config() failed err=%d.\n", __func__,
+ ret);
+ return;
+ }
- ret = pwm_config(edp_drv->bl_pwm,
- bl_level * edp_drv->pwm_period / bl_max,
- edp_drv->pwm_period);
- if (ret) {
- pr_err("%s: pwm_config() failed err=%d.\n", __func__, ret);
- return;
- }
-
- ret = pwm_enable(edp_drv->bl_pwm);
- if (ret) {
- pr_err("%s: pwm_enable() failed err=%d\n", __func__, ret);
- return;
+ ret = pwm_enable(edp_drv->bl_pwm);
+ if (ret) {
+ pr_err("%s: pwm_enable() failed err=%d\n", __func__,
+ ret);
+ return;
+ }
}
}
@@ -378,7 +364,8 @@
mdss_edp_irq_disable(edp_drv);
gpio_set_value(edp_drv->gpio_panel_en, 0);
- pwm_disable(edp_drv->bl_pwm);
+ if (edp_drv->bl_pwm != NULL)
+ pwm_disable(edp_drv->bl_pwm);
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);
diff --git a/drivers/video/msm/mdss/mdss_edp.h b/drivers/video/msm/mdss/mdss_edp.h
index c3f7d0d..33b899f 100644
--- a/drivers/video/msm/mdss/mdss_edp.h
+++ b/drivers/video/msm/mdss/mdss_edp.h
@@ -261,7 +261,6 @@
/* gpios */
int gpio_panel_en;
- int gpio_panel_pwm;
/* backlight */
struct pwm_device *bl_pwm;
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 793cbd7..631853a 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -43,6 +43,7 @@
#include <linux/sw_sync.h>
#include <linux/file.h>
#include <linux/memory_alloc.h>
+#include <linux/kthread.h>
#include <mach/board.h>
#include <mach/memory.h>
@@ -86,8 +87,10 @@
unsigned long arg);
static int mdss_fb_mmap(struct fb_info *info, struct vm_area_struct *vma);
static void mdss_fb_release_fences(struct msm_fb_data_type *mfd);
+static int __mdss_fb_sync_buf_done_callback(struct notifier_block *p,
+ unsigned long val, void *data);
-static void mdss_fb_commit_wq_handler(struct work_struct *work);
+static int __mdss_fb_display_thread(void *data);
static void mdss_fb_pan_idle(struct msm_fb_data_type *mfd);
static int mdss_fb_send_panel_event(struct msm_fb_data_type *mfd,
int event, void *arg);
@@ -376,18 +379,25 @@
mdss_fb_create_sysfs(mfd);
mdss_fb_send_panel_event(mfd, MDSS_EVENT_FB_REGISTERED, fbi);
- if (mfd->timeline == NULL) {
+ mfd->mdp_sync_pt_data.fence_name = "mdp-fence";
+ if (mfd->mdp_sync_pt_data.timeline == NULL) {
char timeline_name[16];
snprintf(timeline_name, sizeof(timeline_name),
"mdss_fb_%d", mfd->index);
- mfd->timeline = sw_sync_timeline_create(timeline_name);
- if (mfd->timeline == NULL) {
+ mfd->mdp_sync_pt_data.timeline =
+ sw_sync_timeline_create(timeline_name);
+ if (mfd->mdp_sync_pt_data.timeline == NULL) {
pr_err("%s: cannot create time line", __func__);
return -ENOMEM;
- } else {
- mfd->timeline_value = 0;
}
+ mfd->mdp_sync_pt_data.notifier.notifier_call =
+ __mdss_fb_sync_buf_done_callback;
}
+ if ((mfd->panel.type == WRITEBACK_PANEL) ||
+ (mfd->panel.type == MIPI_CMD_PANEL))
+ mfd->mdp_sync_pt_data.threshold = 1;
+ else
+ mfd->mdp_sync_pt_data.threshold = 2;
return rc;
}
@@ -585,9 +595,6 @@
},
};
-static int unset_bl_level, bl_updated;
-static int bl_level_old;
-
static void mdss_fb_scale_bl(struct msm_fb_data_type *mfd, u32 *bl_lvl)
{
u32 temp = *bl_lvl;
@@ -609,11 +616,11 @@
* scaling fraction (x/1024)
*/
temp = (temp * mfd->bl_scale) / 1024;
-
- /*if less than minimum level, use min level*/
- if (temp < mfd->bl_min_lvl)
- temp = mfd->bl_min_lvl;
}
+ /*if less than minimum level, use min level*/
+ else if ((temp < mfd->bl_min_lvl) && (0 != temp))
+ temp = mfd->bl_min_lvl;
+
pr_debug("output = %d", temp);
(*bl_lvl) = temp;
@@ -626,11 +633,15 @@
int (*update_ad_input)(struct msm_fb_data_type *mfd);
u32 temp = bkl_lvl;
- if ((!mfd->panel_power_on || !bl_updated) && !IS_CALIB_MODE_BL(mfd)) {
- unset_bl_level = bkl_lvl;
- return;
+ if (((!mfd->panel_power_on && mfd->dcm_state != DCM_ENTER)
+ || !mfd->bl_updated) && !IS_CALIB_MODE_BL(mfd)) {
+ if (bkl_lvl < mfd->bl_min_lvl)
+ mfd->unset_bl_level = mfd->bl_min_lvl;
+ else
+ mfd->unset_bl_level = bkl_lvl;
+ return;
} else {
- unset_bl_level = 0;
+ mfd->unset_bl_level = 0;
}
pdata = dev_get_platdata(&mfd->pdev->dev);
@@ -646,13 +657,13 @@
* as well as setting bl_level to bkl_lvl even though the
* backlight has been set to the scaled value.
*/
- if (bl_level_old == temp) {
+ if (mfd->bl_level_old == temp) {
mfd->bl_level = bkl_lvl;
return;
}
pdata->set_backlight(pdata, temp);
mfd->bl_level = bkl_lvl;
- bl_level_old = temp;
+ mfd->bl_level_old = temp;
if (mfd->mdp.update_ad_input) {
update_ad_input = mfd->mdp.update_ad_input;
@@ -668,15 +679,15 @@
{
struct mdss_panel_data *pdata;
- if (unset_bl_level && !bl_updated) {
+ if (mfd->unset_bl_level && !mfd->bl_updated) {
pdata = dev_get_platdata(&mfd->pdev->dev);
if ((pdata) && (pdata->set_backlight)) {
mutex_lock(&mfd->bl_lock);
- mfd->bl_level = unset_bl_level;
+ mfd->bl_level = mfd->unset_bl_level;
pdata->set_backlight(pdata, mfd->bl_level);
- bl_level_old = unset_bl_level;
+ mfd->bl_level_old = mfd->unset_bl_level;
mutex_unlock(&mfd->bl_lock);
- bl_updated = 1;
+ mfd->bl_updated = 1;
}
}
}
@@ -723,7 +734,7 @@
mfd->op_enable = false;
curr_pwr_state = mfd->panel_power_on;
mfd->panel_power_on = false;
- bl_updated = 0;
+ mfd->bl_updated = 0;
ret = mfd->mdp.off_fnc(mfd);
if (ret)
@@ -1078,22 +1089,19 @@
mutex_init(&mfd->update.lock);
mutex_init(&mfd->no_update.lock);
- mutex_init(&mfd->sync_mutex);
+ mutex_init(&mfd->mdp_sync_pt_data.sync_mutex);
+ atomic_set(&mfd->mdp_sync_pt_data.commit_cnt, 0);
+ atomic_set(&mfd->commits_pending, 0);
+
init_timer(&mfd->no_update.timer);
mfd->no_update.timer.function = mdss_fb_no_update_notify_timer_cb;
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);
- mfd->msm_fb_backup = kzalloc(sizeof(struct msm_fb_backup_type),
- GFP_KERNEL);
- if (mfd->msm_fb_backup == 0) {
- pr_err("error: not enough memory!\n");
- return -ENOMEM;
- }
+ init_waitqueue_head(&mfd->commit_wait_q);
+ init_waitqueue_head(&mfd->idle_wait_q);
ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
if (ret)
@@ -1110,9 +1118,9 @@
mfd->index, fbi->var.xres, fbi->var.yres,
fbi->fix.smem_len);
- ret = 0;
+ kthread_run(__mdss_fb_display_thread, mfd, "mdss_fb%d", mfd->index);
- return ret;
+ return 0;
}
static int mdss_fb_open(struct fb_info *info, int user)
@@ -1183,6 +1191,12 @@
if (!pinfo || (pinfo->pid != pid)) {
pr_warn("unable to find process info for fb%d pid=%d\n",
mfd->index, pid);
+ if (mfd->mdp.release_fnc) {
+ ret = mfd->mdp.release_fnc(mfd);
+ if (ret)
+ pr_err("error releasing fb%d resources\n",
+ mfd->index);
+ }
} else {
pr_debug("found process entry pid=%d ref=%d\n",
pinfo->pid, pinfo->ref_cnt);
@@ -1233,87 +1247,157 @@
}
}
-void mdss_fb_wait_for_fence(struct msm_fb_data_type *mfd)
+void mdss_fb_wait_for_fence(struct msm_sync_pt_data *sync_pt_data)
{
+ struct sync_fence *fences[MDP_MAX_FENCE_FD];
+ int fence_cnt;
int i, ret = 0;
+
+ pr_debug("%s: wait for fences\n", sync_pt_data->fence_name);
+
+ mutex_lock(&sync_pt_data->sync_mutex);
+ /*
+ * Assuming that acq_fen_cnt is sanitized in bufsync ioctl
+ * to check for sync_pt_data->acq_fen_cnt) <= MDP_MAX_FENCE_FD
+ */
+ fence_cnt = sync_pt_data->acq_fen_cnt;
+ sync_pt_data->acq_fen_cnt = 0;
+ if (fence_cnt)
+ memcpy(fences, sync_pt_data->acq_fen,
+ fence_cnt * sizeof(struct sync_fence *));
+ mutex_unlock(&sync_pt_data->sync_mutex);
+
/* buf sync */
- for (i = 0; i < mfd->acq_fen_cnt; i++) {
- ret = sync_fence_wait(mfd->acq_fen[i],
+ for (i = 0; i < fence_cnt && !ret; i++) {
+ ret = sync_fence_wait(fences[i],
WAIT_FENCE_FIRST_TIMEOUT);
if (ret == -ETIME) {
- pr_warn("sync_fence_wait timed out! ");
+ pr_warn("%s: sync_fence_wait timed out! ",
+ sync_pt_data->fence_name);
pr_cont("Waiting %ld more seconds\n",
WAIT_FENCE_FINAL_TIMEOUT/MSEC_PER_SEC);
- ret = sync_fence_wait(mfd->acq_fen[i],
+ ret = sync_fence_wait(fences[i],
WAIT_FENCE_FINAL_TIMEOUT);
}
- if (ret < 0) {
- pr_err("%s: sync_fence_wait failed! ret = %x\n",
- __func__, ret);
- break;
- }
- sync_fence_put(mfd->acq_fen[i]);
+ sync_fence_put(fences[i]);
}
if (ret < 0) {
- while (i < mfd->acq_fen_cnt) {
- sync_fence_put(mfd->acq_fen[i]);
- i++;
- }
+ pr_err("%s: sync_fence_wait failed! ret = %x\n",
+ sync_pt_data->fence_name, ret);
+ for (; i < fence_cnt; i++)
+ sync_fence_put(fences[i]);
}
- mfd->acq_fen_cnt = 0;
}
-static void mdss_fb_signal_timeline_locked(struct msm_fb_data_type *mfd)
+/**
+ * mdss_fb_signal_timeline() - signal a single release fence
+ * @sync_pt_data: Sync point data structure for the timeline which
+ * should be signaled.
+ *
+ * This is called after a frame has been pushed to display. This signals the
+ * timeline to release the fences associated with this frame.
+ */
+void mdss_fb_signal_timeline(struct msm_sync_pt_data *sync_pt_data)
{
- if (mfd->timeline && !list_empty((const struct list_head *)
- (&(mfd->timeline->obj.active_list_head)))) {
- sw_sync_timeline_inc(mfd->timeline, 1);
- mfd->timeline_value++;
+ mutex_lock(&sync_pt_data->sync_mutex);
+ if (atomic_add_unless(&sync_pt_data->commit_cnt, -1, 0) &&
+ sync_pt_data->timeline) {
+ sw_sync_timeline_inc(sync_pt_data->timeline, 1);
+ sync_pt_data->timeline_value++;
+
+ pr_debug("%s: buffer signaled! timeline val=%d remaining=%d\n",
+ sync_pt_data->fence_name, sync_pt_data->timeline_value,
+ atomic_read(&sync_pt_data->commit_cnt));
+ } else {
+ pr_debug("%s timeline signaled without commits val=%d\n",
+ sync_pt_data->fence_name, sync_pt_data->timeline_value);
}
- mfd->last_rel_fence = mfd->cur_rel_fence;
- mfd->cur_rel_fence = 0;
+ mutex_unlock(&sync_pt_data->sync_mutex);
}
-void mdss_fb_signal_timeline(struct msm_fb_data_type *mfd)
-{
- mutex_lock(&mfd->sync_mutex);
- mdss_fb_signal_timeline_locked(mfd);
- mutex_unlock(&mfd->sync_mutex);
-}
-
+/**
+ * mdss_fb_release_fences() - signal all pending release fences
+ * @mfd: Framebuffer data structure for display
+ *
+ * Release all currently pending release fences, including those that are in
+ * the process to be commited.
+ *
+ * Note: this should only be called during close or suspend sequence.
+ */
static void mdss_fb_release_fences(struct msm_fb_data_type *mfd)
{
- mutex_lock(&mfd->sync_mutex);
- if (mfd->timeline) {
- sw_sync_timeline_inc(mfd->timeline, 2);
- mfd->timeline_value += 2;
+ struct msm_sync_pt_data *sync_pt_data = &mfd->mdp_sync_pt_data;
+ int val;
+
+ mutex_lock(&sync_pt_data->sync_mutex);
+ if (sync_pt_data->timeline) {
+ val = sync_pt_data->threshold +
+ atomic_read(&sync_pt_data->commit_cnt);
+ sw_sync_timeline_inc(sync_pt_data->timeline, val);
+ sync_pt_data->timeline_value += val;
+ atomic_set(&sync_pt_data->commit_cnt, 0);
}
- mfd->last_rel_fence = 0;
- mfd->cur_rel_fence = 0;
- mutex_unlock(&mfd->sync_mutex);
+ mutex_unlock(&sync_pt_data->sync_mutex);
}
+/**
+ * __mdss_fb_sync_buf_done_callback() - process async display events
+ * @p: Notifier block registered for async events.
+ * @event: Event enum to identify the event.
+ * @data: Optional argument provided with the event.
+ *
+ * See enum mdp_notify_event for events handled.
+ */
+static int __mdss_fb_sync_buf_done_callback(struct notifier_block *p,
+ unsigned long event, void *data)
+{
+ struct msm_sync_pt_data *sync_pt_data;
+
+ sync_pt_data = container_of(p, struct msm_sync_pt_data, notifier);
+
+ switch (event) {
+ case MDP_NOTIFY_FRAME_READY:
+ if (sync_pt_data->async_wait_fences)
+ mdss_fb_wait_for_fence(sync_pt_data);
+ break;
+ case MDP_NOTIFY_FRAME_FLUSHED:
+ pr_debug("%s: frame flushed\n", sync_pt_data->fence_name);
+ sync_pt_data->flushed = true;
+ break;
+ case MDP_NOTIFY_FRAME_TIMEOUT:
+ pr_err("%s: frame timeout\n", sync_pt_data->fence_name);
+ mdss_fb_signal_timeline(sync_pt_data);
+ break;
+ case MDP_NOTIFY_FRAME_DONE:
+ pr_debug("%s: frame done\n", sync_pt_data->fence_name);
+ mdss_fb_signal_timeline(sync_pt_data);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+/**
+ * mdss_fb_pan_idle() - wait for panel programming to be idle
+ * @mfd: Framebuffer data structure for display
+ *
+ * Wait for any pending programming to be done if in the process of programming
+ * hardware configuration. After this function returns it is safe to perform
+ * software updates for next frame.
+ */
static void mdss_fb_pan_idle(struct msm_fb_data_type *mfd)
{
int ret;
- if (mfd->is_committing) {
- ret = wait_for_completion_timeout(
- &mfd->commit_comp,
+ ret = wait_event_timeout(mfd->idle_wait_q,
+ !atomic_read(&mfd->commits_pending),
msecs_to_jiffies(WAIT_DISP_OP_TIMEOUT));
- if (ret < 0)
- ret = -ERESTARTSYS;
- else if (!ret)
- pr_err("%s wait for commit_comp timeout %d %d",
- __func__, ret, mfd->is_committing);
- if (ret <= 0) {
- mutex_lock(&mfd->sync_mutex);
- mdss_fb_signal_timeline_locked(mfd);
- mfd->is_committing = 0;
- complete_all(&mfd->commit_comp);
- mutex_unlock(&mfd->sync_mutex);
- }
+ if (!ret) {
+ pr_err("wait for idle timeout %d pending=%d\n",
+ ret, atomic_read(&mfd->commits_pending));
+
+ mdss_fb_signal_timeline(&mfd->mdp_sync_pt_data);
}
}
@@ -1321,7 +1405,6 @@
struct mdp_display_commit *disp_commit)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
- struct msm_fb_backup_type *fb_backup;
struct fb_var_screeninfo *var = &disp_commit->var;
u32 wait_for_finish = disp_commit->wait_for_finish;
int ret = 0;
@@ -1337,7 +1420,7 @@
mdss_fb_pan_idle(mfd);
- mutex_lock(&mfd->sync_mutex);
+ mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
if (info->fix.xpanstep)
info->var.xoffset =
(var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
@@ -1346,14 +1429,13 @@
info->var.yoffset =
(var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
- fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup;
- memcpy(&fb_backup->info, info, sizeof(struct fb_info));
- memcpy(&fb_backup->disp_commit, disp_commit,
- sizeof(struct mdp_display_commit));
- INIT_COMPLETION(mfd->commit_comp);
- mfd->is_committing = 1;
- schedule_work(&mfd->commit_work);
- mutex_unlock(&mfd->sync_mutex);
+ mfd->msm_fb_backup.info = *info;
+ mfd->msm_fb_backup.disp_commit = *disp_commit;
+
+ atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt);
+ atomic_inc(&mfd->commits_pending);
+ wake_up_all(&mfd->commit_wait_q);
+ mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex);
if (wait_for_finish)
mdss_fb_pan_idle(mfd);
return ret;
@@ -1391,14 +1473,12 @@
info->var.yoffset =
(var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
- mdss_fb_wait_for_fence(mfd);
if (mfd->mdp.dma_fnc)
mfd->mdp.dma_fnc(mfd);
else
pr_warn("dma function not set for panel type=%d\n",
mfd->panel.type);
- mdss_fb_signal_timeline(mfd);
- mdss_fb_update_backlight(mfd);
+
return 0;
}
@@ -1416,34 +1496,69 @@
pinfo->clk_rate = var->pixclock;
}
-static void mdss_fb_commit_wq_handler(struct work_struct *work)
+/**
+ * __mdss_fb_perform_commit() - process a frame to display
+ * @mfd: Framebuffer data structure for display
+ *
+ * Processes all layers and buffers programmed and ensures all pending release
+ * fences are signaled once the buffer is transfered to display.
+ */
+static int __mdss_fb_perform_commit(struct msm_fb_data_type *mfd)
{
- struct msm_fb_data_type *mfd;
- struct fb_var_screeninfo *var;
- struct fb_info *info;
- struct msm_fb_backup_type *fb_backup;
- int ret;
+ struct msm_sync_pt_data *sync_pt_data = &mfd->mdp_sync_pt_data;
+ struct msm_fb_backup_type *fb_backup = &mfd->msm_fb_backup;
+ int ret = -ENOSYS;
- mfd = container_of(work, struct msm_fb_data_type, commit_work);
- fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup;
- info = &fb_backup->info;
- if (fb_backup->disp_commit.flags &
- MDP_DISPLAY_COMMIT_OVERLAY) {
- mdss_fb_wait_for_fence(mfd);
+ if (!sync_pt_data->async_wait_fences)
+ mdss_fb_wait_for_fence(sync_pt_data);
+ sync_pt_data->flushed = false;
+
+ if (fb_backup->disp_commit.flags & MDP_DISPLAY_COMMIT_OVERLAY) {
if (mfd->mdp.kickoff_fnc)
- mfd->mdp.kickoff_fnc(mfd);
- mdss_fb_update_backlight(mfd);
- mdss_fb_signal_timeline(mfd);
+ ret = mfd->mdp.kickoff_fnc(mfd,
+ &fb_backup->disp_commit);
+ else
+ pr_warn("no kickoff function setup for fb%d\n",
+ mfd->index);
} else {
- var = &fb_backup->disp_commit.var;
- ret = mdss_fb_pan_display_sub(var, info);
+ ret = mdss_fb_pan_display_sub(&fb_backup->disp_commit.var,
+ &fb_backup->info);
if (ret)
- pr_err("%s fails: ret = %x", __func__, ret);
+ pr_err("pan display failed %x on fb%d\n", ret,
+ mfd->index);
}
- mutex_lock(&mfd->sync_mutex);
- mfd->is_committing = 0;
- complete_all(&mfd->commit_comp);
- mutex_unlock(&mfd->sync_mutex);
+ if (!ret)
+ mdss_fb_update_backlight(mfd);
+
+ if (IS_ERR_VALUE(ret) || !sync_pt_data->flushed)
+ mdss_fb_signal_timeline(sync_pt_data);
+
+ return ret;
+}
+
+static int __mdss_fb_display_thread(void *data)
+{
+ struct msm_fb_data_type *mfd = data;
+ int ret;
+ struct sched_param param;
+
+ param.sched_priority = 16;
+ ret = sched_setscheduler(current, SCHED_FIFO, ¶m);
+ if (ret)
+ pr_warn("set priority failed for fb%d display thread\n",
+ mfd->index);
+
+ while (1) {
+ wait_event(mfd->commit_wait_q,
+ atomic_read(&mfd->commits_pending));
+
+ ret = __mdss_fb_perform_commit(mfd);
+
+ atomic_dec(&mfd->commits_pending);
+ wake_up_all(&mfd->idle_wait_q);
+ }
+
+ return ret;
}
static int mdss_fb_check_var(struct fb_var_screeninfo *var,
@@ -1701,95 +1816,127 @@
return 0;
}
-static int mdss_fb_handle_buf_sync_ioctl(struct msm_fb_data_type *mfd,
- struct mdp_buf_sync *buf_sync)
+/**
+ * mdss_fb_sync_get_rel_fence() - get release fence from sync pt timeline
+ * @sync_pt_data: Sync pt structure holding timeline and fence info.
+ *
+ * Function returns a release fence on the timeline associated with the
+ * sync pt struct given and it's associated information. The release fence
+ * created can be used to signal when buffers provided will be released.
+ */
+static struct sync_fence *__mdss_fb_sync_get_rel_fence(
+ struct msm_sync_pt_data *sync_pt_data)
{
- int i, fence_cnt = 0, ret = 0;
+ struct sync_pt *rel_sync_pt;
+ struct sync_fence *rel_fence;
+ int val;
+
+ val = sync_pt_data->timeline_value + sync_pt_data->threshold +
+ atomic_read(&sync_pt_data->commit_cnt);
+
+ pr_debug("%s: buf sync rel fence timeline=%d\n",
+ sync_pt_data->fence_name, val);
+
+ rel_sync_pt = sw_sync_pt_create(sync_pt_data->timeline, val);
+ if (rel_sync_pt == NULL) {
+ pr_err("%s: cannot create sync point\n",
+ sync_pt_data->fence_name);
+ return NULL;
+ }
+
+ /* create fence */
+ rel_fence = sync_fence_create(sync_pt_data->fence_name, rel_sync_pt);
+ if (rel_fence == NULL) {
+ sync_pt_free(rel_sync_pt);
+ pr_err("%s: cannot create fence\n", sync_pt_data->fence_name);
+ return NULL;
+ }
+
+ return rel_fence;
+}
+
+static int mdss_fb_handle_buf_sync_ioctl(struct msm_sync_pt_data *sync_pt_data,
+ struct mdp_buf_sync *buf_sync)
+{
+ int i, ret = 0;
int acq_fen_fd[MDP_MAX_FENCE_FD];
- struct sync_fence *fence;
- u32 threshold;
+ struct sync_fence *fence, *rel_fence;
+ int rel_fen_fd;
if ((buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
- (mfd->timeline == NULL))
+ (sync_pt_data->timeline == NULL))
return -EINVAL;
- if ((!mfd->op_enable) || (!mfd->panel_power_on))
- return -EPERM;
-
if (buf_sync->acq_fen_fd_cnt)
ret = copy_from_user(acq_fen_fd, buf_sync->acq_fen_fd,
buf_sync->acq_fen_fd_cnt * sizeof(int));
if (ret) {
- pr_err("%s:copy_from_user failed", __func__);
+ pr_err("%s: copy_from_user failed", sync_pt_data->fence_name);
return ret;
}
- mutex_lock(&mfd->sync_mutex);
+
+ if (sync_pt_data->acq_fen_cnt) {
+ pr_warn("%s: currently %d fences active. waiting...\n",
+ sync_pt_data->fence_name,
+ sync_pt_data->acq_fen_cnt);
+ mdss_fb_wait_for_fence(sync_pt_data);
+ }
+
+ mutex_lock(&sync_pt_data->sync_mutex);
for (i = 0; i < buf_sync->acq_fen_fd_cnt; i++) {
fence = sync_fence_fdget(acq_fen_fd[i]);
if (fence == NULL) {
- pr_info("%s: null fence! i=%d fd=%d\n", __func__, i,
- acq_fen_fd[i]);
+ pr_err("%s: null fence! i=%d fd=%d\n",
+ sync_pt_data->fence_name, i,
+ acq_fen_fd[i]);
ret = -EINVAL;
break;
}
- mfd->acq_fen[i] = fence;
+ sync_pt_data->acq_fen[i] = fence;
}
- fence_cnt = i;
+ sync_pt_data->acq_fen_cnt = i;
if (ret)
goto buf_sync_err_1;
- mfd->acq_fen_cnt = fence_cnt;
- if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT)
- mdss_fb_wait_for_fence(mfd);
- if (mfd->panel.type == WRITEBACK_PANEL)
- threshold = 1;
- else
- threshold = 2;
-
- mfd->cur_rel_sync_pt = sw_sync_pt_create(mfd->timeline,
- mfd->timeline_value + threshold);
- if (mfd->cur_rel_sync_pt == NULL) {
- pr_err("%s: cannot create sync point", __func__);
- ret = -ENOMEM;
+ rel_fence = __mdss_fb_sync_get_rel_fence(sync_pt_data);
+ if (IS_ERR_OR_NULL(rel_fence)) {
+ pr_err("%s: unable to retrieve release fence\n",
+ sync_pt_data->fence_name);
+ ret = rel_fence ? PTR_ERR(rel_fence) : -ENOMEM;
goto buf_sync_err_1;
}
- /* create fence */
- mfd->cur_rel_fence = sync_fence_create("mdp-fence",
- mfd->cur_rel_sync_pt);
- if (mfd->cur_rel_fence == NULL) {
- sync_pt_free(mfd->cur_rel_sync_pt);
- mfd->cur_rel_sync_pt = NULL;
- pr_err("%s: cannot create fence", __func__);
- ret = -ENOMEM;
- goto buf_sync_err_1;
- }
+
/* create fd */
- mfd->cur_rel_fen_fd = get_unused_fd_flags(0);
- if (mfd->cur_rel_fen_fd < 0) {
- pr_err("%s: get_unused_fd_flags failed", __func__);
- ret = -EIO;
+ rel_fen_fd = get_unused_fd_flags(0);
+ if (rel_fen_fd < 0) {
+ pr_err("%s: get_unused_fd_flags failed\n",
+ sync_pt_data->fence_name);
+ ret = -EIO;
goto buf_sync_err_2;
}
- sync_fence_install(mfd->cur_rel_fence, mfd->cur_rel_fen_fd);
- ret = copy_to_user(buf_sync->rel_fen_fd,
- &mfd->cur_rel_fen_fd, sizeof(int));
+
+ sync_fence_install(rel_fence, rel_fen_fd);
+
+ ret = copy_to_user(buf_sync->rel_fen_fd, &rel_fen_fd, sizeof(int));
if (ret) {
- pr_err("%s:copy_to_user failed", __func__);
+ pr_err("%s: copy_to_user failed\n", sync_pt_data->fence_name);
goto buf_sync_err_3;
}
- mutex_unlock(&mfd->sync_mutex);
+ mutex_unlock(&sync_pt_data->sync_mutex);
+
+ if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT)
+ mdss_fb_wait_for_fence(sync_pt_data);
+
return ret;
buf_sync_err_3:
- put_unused_fd(mfd->cur_rel_fen_fd);
+ put_unused_fd(rel_fen_fd);
buf_sync_err_2:
- sync_fence_put(mfd->cur_rel_fence);
- mfd->cur_rel_fence = NULL;
- mfd->cur_rel_fen_fd = 0;
+ sync_fence_put(rel_fence);
buf_sync_err_1:
- for (i = 0; i < fence_cnt; i++)
- sync_fence_put(mfd->acq_fen[i]);
- mfd->acq_fen_cnt = 0;
- mutex_unlock(&mfd->sync_mutex);
+ for (i = 0; i < sync_pt_data->acq_fen_cnt; i++)
+ sync_fence_put(sync_pt_data->acq_fen[i]);
+ sync_pt_data->acq_fen_cnt = 0;
+ mutex_unlock(&sync_pt_data->sync_mutex);
return ret;
}
static int mdss_fb_display_commit(struct fb_info *info,
@@ -1816,13 +1963,13 @@
struct mdp_page_protection fb_page_protection;
int ret = -ENOSYS;
struct mdp_buf_sync buf_sync;
-
+ struct msm_sync_pt_data *sync_pt_data = NULL;
if (!info || !info->par)
return -EINVAL;
mfd = (struct msm_fb_data_type *)info->par;
mdss_fb_power_setting_idle(mfd);
-
- mdss_fb_pan_idle(mfd);
+ if ((cmd != MSMFB_VSYNC_CTRL) && (cmd != MSMFB_OVERLAY_VSYNC_CTRL))
+ mdss_fb_pan_idle(mfd);
switch (cmd) {
case MSMFB_CURSOR:
@@ -1846,8 +1993,14 @@
ret = copy_from_user(&buf_sync, argp, sizeof(buf_sync));
if (ret)
return ret;
+ if ((!mfd->op_enable) || (!mfd->panel_power_on))
+ return -EPERM;
+ if (mfd->mdp.get_sync_fnc)
+ sync_pt_data = mfd->mdp.get_sync_fnc(mfd, &buf_sync);
+ if (!sync_pt_data)
+ sync_pt_data = &mfd->mdp_sync_pt_data;
- ret = mdss_fb_handle_buf_sync_ioctl(mfd, &buf_sync);
+ ret = mdss_fb_handle_buf_sync_ioctl(sync_pt_data, &buf_sync);
if (!ret)
ret = copy_to_user(argp, &buf_sync, sizeof(buf_sync));
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index fd96e63..8213dbe 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -18,6 +18,7 @@
#include <linux/list.h>
#include <linux/msm_mdp.h>
#include <linux/types.h>
+#include <linux/notifier.h>
#include "mdss_panel.h"
@@ -40,6 +41,32 @@
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#endif
+/**
+ * enum mdp_notify_event - Different frame events to indicate frame update state
+ *
+ * @MDP_NOTIFY_FRAME_BEGIN: Frame update has started, the frame is about to
+ * be programmed into hardware.
+ * @MDP_NOTIFY_FRAME_READY: Frame ready to be kicked off, this can be used
+ * as the last point in time to synchronized with
+ * source buffers before kickoff.
+ * @MDP_NOTIFY_FRAME_FLUSHED: Configuration of frame has been flushed and
+ * DMA transfer has started.
+ * @MDP_NOTIFY_FRAME_DONE: Frame DMA transfer has completed.
+ * - For video mode panels this will indicate that
+ * previous frame has been replaced by new one.
+ * - For command mode/writeback frame done happens
+ * as soon as the DMA of the frame is done.
+ * @MDP_NOTIFY_FRAME_TIMEOUT: Frame DMA transfer has failed to complete within
+ * a fair amount of time.
+ */
+enum mdp_notify_event {
+ MDP_NOTIFY_FRAME_BEGIN = 1,
+ MDP_NOTIFY_FRAME_READY,
+ MDP_NOTIFY_FRAME_FLUSHED,
+ MDP_NOTIFY_FRAME_DONE,
+ MDP_NOTIFY_FRAME_TIMEOUT,
+};
+
struct disp_info_type_suspend {
int op_enable;
int panel_power_on;
@@ -53,6 +80,23 @@
int value;
};
+struct msm_sync_pt_data {
+ char *fence_name;
+ u32 acq_fen_cnt;
+ struct sync_fence *acq_fen[MDP_MAX_FENCE_FD];
+
+ struct sw_sync_timeline *timeline;
+ int timeline_value;
+ u32 threshold;
+
+ atomic_t commit_cnt;
+ bool flushed;
+ bool async_wait_fences;
+
+ struct mutex sync_mutex;
+ struct notifier_block notifier;
+};
+
struct msm_fb_data_type;
struct msm_mdp_interface {
@@ -63,7 +107,8 @@
int (*off_fnc)(struct msm_fb_data_type *mfd);
/* called to release resources associated to the process */
int (*release_fnc)(struct msm_fb_data_type *mfd);
- int (*kickoff_fnc)(struct msm_fb_data_type *mfd);
+ int (*kickoff_fnc)(struct msm_fb_data_type *mfd,
+ struct mdp_display_commit *data);
int (*ioctl_handler)(struct msm_fb_data_type *mfd, u32 cmd, void *arg);
void (*dma_fnc)(struct msm_fb_data_type *mfd);
int (*cursor_update)(struct msm_fb_data_type *mfd,
@@ -74,6 +119,8 @@
int (*update_ad_input)(struct msm_fb_data_type *mfd);
int (*panel_register_done)(struct mdss_panel_data *pdata);
u32 (*fb_stride)(u32 fb_index, u32 xres, int bpp);
+ struct msm_sync_pt_data *(*get_sync_fnc)(struct msm_fb_data_type *mfd,
+ const struct mdp_buf_sync *buf_sync);
void *private1;
};
@@ -89,6 +136,11 @@
struct list_head list;
};
+struct msm_fb_backup_type {
+ struct fb_info info;
+ struct mdp_display_commit disp_commit;
+};
+
struct msm_fb_data_type {
u32 key;
u32 index;
@@ -124,6 +176,9 @@
u32 bl_level;
u32 bl_scale;
u32 bl_min_lvl;
+ u32 unset_bl_level;
+ u32 bl_updated;
+ u32 bl_level_old;
struct mutex bl_lock;
struct mutex lock;
@@ -137,22 +192,14 @@
struct msm_mdp_interface mdp;
- u32 acq_fen_cnt;
- struct sync_fence *acq_fen[MDP_MAX_FENCE_FD];
- int cur_rel_fen_fd;
- struct sync_pt *cur_rel_sync_pt;
- struct sync_fence *cur_rel_fence;
- struct sync_fence *last_rel_fence;
- struct sw_sync_timeline *timeline;
- int timeline_value;
- u32 last_acq_fen_cnt;
- struct sync_fence *last_acq_fen[MDP_MAX_FENCE_FD];
- struct mutex sync_mutex;
+ struct msm_sync_pt_data mdp_sync_pt_data;
+
/* for non-blocking */
- struct completion commit_comp;
- u32 is_committing;
- struct work_struct commit_work;
- void *msm_fb_backup;
+ atomic_t commits_pending;
+ wait_queue_head_t commit_wait_q;
+ wait_queue_head_t idle_wait_q;
+
+ struct msm_fb_backup_type msm_fb_backup;
struct completion power_set_comp;
u32 is_power_setting;
@@ -160,11 +207,6 @@
struct list_head proc_list;
};
-struct msm_fb_backup_type {
- struct fb_info info;
- struct mdp_display_commit disp_commit;
-};
-
static inline void mdss_fb_update_notify_update(struct msm_fb_data_type *mfd)
{
int needs_complete = 0;
@@ -187,8 +229,8 @@
int mdss_fb_get_phys_info(unsigned long *start, unsigned long *len, int fb_num);
void mdss_fb_set_backlight(struct msm_fb_data_type *mfd, u32 bkl_lvl);
void mdss_fb_update_backlight(struct msm_fb_data_type *mfd);
-void mdss_fb_wait_for_fence(struct msm_fb_data_type *mfd);
-void mdss_fb_signal_timeline(struct msm_fb_data_type *mfd);
+void mdss_fb_wait_for_fence(struct msm_sync_pt_data *sync_pt_data);
+void mdss_fb_signal_timeline(struct msm_sync_pt_data *sync_pt_data);
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_cec.c b/drivers/video/msm/mdss/mdss_hdmi_cec.c
index b74f074..410f2b3 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_cec.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_cec.c
@@ -350,7 +350,8 @@
(msg->operand[i] << 8) | frame_type);
while ((DSS_REG_R(io, HDMI_CEC_STATUS) & BIT(0)) &&
- line_check_retry--) {
+ line_check_retry) {
+ line_check_retry--;
DEV_DBG("%s: CEC line is busy(%d)\n", __func__,
line_check_retry);
schedule();
@@ -756,7 +757,7 @@
hdmi_wta_cec_enable);
static DEVICE_ATTR(enable_compliance, S_IRUGO | S_IWUSR,
hdmi_rda_cec_enable_compliance, hdmi_wta_cec_enable_compliance);
-static DEVICE_ATTR(logical_addr, S_IRUGO | S_IWUSR,
+static DEVICE_ATTR(logical_addr, S_IRUSR | S_IWUSR,
hdmi_rda_cec_logical_addr, hdmi_wta_cec_logical_addr);
static DEVICE_ATTR(rd_msg, S_IRUGO, hdmi_rda_cec_msg, NULL);
static DEVICE_ATTR(wr_msg, S_IWUSR, NULL, hdmi_wta_cec_msg);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c
index 65dc19c..cf0c287 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_edid.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c
@@ -27,6 +27,11 @@
#define MAX_AUDIO_DATA_BLOCK_SIZE 30
#define MAX_SPKR_ALLOC_DATA_BLOCK_SIZE 3
+#define BUFF_SIZE_3D 128
+
+/* Support for first 5 EDID blocks */
+#define MAX_EDID_BLOCK_SIZE (0x80 * 5)
+
struct hdmi_edid_sink_data {
u32 disp_mode_list[HDMI_VFRMT_MAX];
u32 disp_3d_mode_list[HDMI_VFRMT_MAX];
@@ -50,6 +55,7 @@
int adb_size;
u8 spkr_alloc_data_block[MAX_SPKR_ALLOC_DATA_BLOCK_SIZE];
int sadb_size;
+ u8 edid_buf[MAX_EDID_BLOCK_SIZE];
struct hdmi_edid_sink_data sink_data;
struct hdmi_edid_init_data init_data;
@@ -249,19 +255,19 @@
if (!hdmi_get_supported_mode(*video_mode))
continue;
if (ret > 0)
- ret += snprintf(buf+ret, PAGE_SIZE-ret, ",%d",
- *video_mode++);
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ ",%d", *video_mode++);
else
- ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d",
- *video_mode++);
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
+ "%d", *video_mode++);
}
} else {
- ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d",
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%d",
edid_ctrl->video_resolution);
}
DEV_DBG("%s: '%s'\n", __func__, buf);
- ret += snprintf(buf+ret, PAGE_SIZE-ret, "\n");
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
return ret;
} /* hdmi_edid_sysfs_rda_modes */
@@ -279,12 +285,12 @@
return -EINVAL;
}
- ret = snprintf(buf, PAGE_SIZE, "%d\n", edid_ctrl->physical_address);
+ ret = scnprintf(buf, PAGE_SIZE, "%d\n", edid_ctrl->physical_address);
DEV_DBG("%s: '%d'\n", __func__, edid_ctrl->physical_address);
return ret;
} /* hdmi_edid_sysfs_rda_physical_address */
-static DEVICE_ATTR(pa, S_IRUGO, hdmi_edid_sysfs_rda_physical_address, NULL);
+static DEVICE_ATTR(pa, S_IRUSR, hdmi_edid_sysfs_rda_physical_address, NULL);
static ssize_t hdmi_edid_sysfs_rda_scan_info(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -298,7 +304,7 @@
return -EINVAL;
}
- ret = snprintf(buf, PAGE_SIZE, "%d, %d, %d\n", edid_ctrl->pt_scan_info,
+ ret = scnprintf(buf, PAGE_SIZE, "%d, %d, %d\n", edid_ctrl->pt_scan_info,
edid_ctrl->it_scan_info, edid_ctrl->ce_scan_info);
DEV_DBG("%s: '%s'\n", __func__, buf);
@@ -311,7 +317,8 @@
{
ssize_t ret = 0;
int i;
- char buff_3d[128];
+ char buff_3d[BUFF_SIZE_3D];
+
struct hdmi_edid_ctrl *edid_ctrl =
hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_EDID);
@@ -327,33 +334,52 @@
for (i = 0; i < edid_ctrl->sink_data.num_of_elements; ++i) {
ret = hdmi_get_video_3d_fmt_2string(*video_3d_mode++,
- buff_3d);
+ buff_3d, sizeof(buff_3d));
if (ret > 0)
- ret += snprintf(buf+ret, PAGE_SIZE-ret,
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
",%d=%s", *video_mode++,
buff_3d);
else
- ret += snprintf(buf+ret, PAGE_SIZE-ret,
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret,
"%d=%s", *video_mode++,
buff_3d);
}
} else {
- ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d",
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%d",
edid_ctrl->video_resolution);
}
DEV_DBG("%s: '%s'\n", __func__, buf);
- ret += snprintf(buf+ret, PAGE_SIZE-ret, "\n");
+ ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
return ret;
} /* hdmi_edid_sysfs_rda_3d_modes */
static DEVICE_ATTR(edid_3d_modes, S_IRUGO, hdmi_edid_sysfs_rda_3d_modes, NULL);
+static ssize_t hdmi_common_rda_edid_raw_data(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct hdmi_edid_ctrl *edid_ctrl =
+ hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_EDID);
+
+ if (!edid_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ memcpy(buf, edid_ctrl->edid_buf,
+ sizeof(edid_ctrl->edid_buf));
+
+ return sizeof(edid_ctrl->edid_buf);
+} /* hdmi_common_rda_edid_raw_data */
+static DEVICE_ATTR(edid_raw_data, S_IRUGO, hdmi_common_rda_edid_raw_data, NULL);
+
static struct attribute *hdmi_edid_fs_attrs[] = {
&dev_attr_edid_modes.attr,
&dev_attr_pa.attr,
&dev_attr_scan_info.attr,
&dev_attr_edid_3d_modes.attr,
+ &dev_attr_edid_raw_data.attr,
NULL,
};
@@ -443,13 +469,17 @@
return status;
} /* hdmi_edid_read_block */
+#define EDID_BLK_LEN 128
+#define EDID_DTD_LEN 18
static const u8 *hdmi_edid_find_block(const u8 *in_buf, u32 start_offset,
u8 type, u8 *len)
{
/* the start of data block collection, start of Video Data Block */
u32 offset = start_offset;
- u32 end_dbc_offset = in_buf[2];
+ u32 dbc_offset = in_buf[2];
+ if (dbc_offset >= EDID_BLK_LEN - EDID_DTD_LEN)
+ return NULL;
*len = 0;
/*
@@ -458,14 +488,15 @@
* * edid buffer 1, byte 2 being 0 menas no non-DTD/DATA block
* collection present and no DTD data present.
*/
- if ((end_dbc_offset == 0) || (end_dbc_offset == 4)) {
+ if ((dbc_offset == 0) || (dbc_offset == 4)) {
DEV_WARN("EDID: no DTD or non-DTD data present\n");
return NULL;
}
- while (offset < end_dbc_offset) {
+ while (offset < dbc_offset) {
u8 block_len = in_buf[offset] & 0x1F;
- if ((in_buf[offset] >> 5) == type) {
+ if ((offset + block_len <= dbc_offset) &&
+ (in_buf[offset] >> 5) == type) {
*len = block_len;
DEV_DBG("%s: EDID: block=%d found @ 0x%x w/ len=%d\n",
__func__, type, offset, block_len);
@@ -669,7 +700,7 @@
}
vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3, &len);
- if (vsd == NULL)
+ if (vsd == NULL || len < 8)
return 0;
DEV_DBG("%s: EDID: VSD PhyAddr=%04x, MaxTMDS=%dMHz\n", __func__,
@@ -816,7 +847,7 @@
static void hdmi_edid_add_sink_3d_format(struct hdmi_edid_sink_data *sink_data,
u32 video_format, u32 video_3d_format)
{
- char string[128];
+ char string[BUFF_SIZE_3D];
u32 added = false;
int i;
@@ -828,7 +859,7 @@
}
}
- hdmi_get_video_3d_fmt_2string(video_3d_format, string);
+ hdmi_get_video_3d_fmt_2string(video_3d_format, string, sizeof(string));
DEV_DBG("%s: EDID[3D]: format: %d [%s], %s %s\n", __func__,
video_format, msm_hdmi_mode_2string(video_format),
@@ -859,7 +890,7 @@
}
} /* hdmi_edid_add_sink_video_format */
-static void hdmi_edid_get_display_vsd_3d_mode(const u8 *data_buf,
+static int hdmi_edid_get_display_vsd_3d_mode(const u8 *data_buf,
struct hdmi_edid_sink_data *sink_data, u32 num_of_cea_blocks)
{
u8 len, offset, present_multi_3d, hdmi_vic_len;
@@ -870,22 +901,34 @@
3, &len) : NULL;
int i;
+ if (!vsd)
+ return -ENXIO;
+
offset = HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd);
+ if (offset >= len - 1)
+ return -ETOOSMALL;
+
present_multi_3d = (vsd[offset] & 0x60) >> 5;
offset += 1;
+
hdmi_vic_len = (vsd[offset] >> 5) & 0x7;
hdmi_3d_len = vsd[offset] & 0x1F;
DEV_DBG("%s: EDID[3D]: HDMI_VIC_LEN = %d, HDMI_3D_LEN = %d\n", __func__,
hdmi_vic_len, hdmi_3d_len);
offset += (hdmi_vic_len + 1);
+ if (offset >= len - 1)
+ return -ETOOSMALL;
+
if (present_multi_3d == 1 || present_multi_3d == 2) {
DEV_DBG("%s: EDID[3D]: multi 3D present (%d)\n", __func__,
present_multi_3d);
/* 3d_structure_all */
structure_all = (vsd[offset] << 8) | vsd[offset + 1];
offset += 2;
+ if (offset >= len - 1)
+ return -ETOOSMALL;
hdmi_3d_len -= 2;
if (present_multi_3d == 2) {
/* 3d_structure_mask */
@@ -932,16 +975,18 @@
i = 0;
while (hdmi_3d_len > 0) {
+ if (offset >= len - 1)
+ return -ETOOSMALL;
DEV_DBG("%s: EDID: 3D_Structure_%d @ 0x%x: %02x\n",
__func__, i + 1, offset, vsd[offset]);
-
if ((vsd[offset] >> 4) >=
sink_data->disp_multi_3d_mode_list_cnt) {
if ((vsd[offset] & 0x0F) >= 8) {
offset += 1;
hdmi_3d_len -= 1;
DEV_DBG("%s:EDID:3D_Detail_%d @ 0x%x: %02x\n",
- __func__, i + 1, offset, vsd[offset]);
+ __func__, i + 1, offset,
+ vsd[min_t(u32, offset, (len - 1))]);
}
i += 1;
offset += 1;
@@ -977,12 +1022,13 @@
hdmi_3d_len -= 1;
DEV_DBG("%s: EDID[3D]: 3D_Detail_%d @ 0x%x: %02x\n",
__func__, i + 1, offset,
- vsd[offset]);
+ vsd[min_t(u32, offset, (len - 1))]);
}
i += 1;
offset += 1;
hdmi_3d_len -= 1;
}
+ return 0;
} /* hdmi_edid_get_display_vsd_3d_mode */
static void hdmi_edid_get_extended_video_formats(
@@ -1035,6 +1081,7 @@
u32 video_format = HDMI_VFRMT_640x480p60_4_3;
u32 has480p = false;
u8 len;
+ int rc;
const u8 *edid_blk0 = NULL;
const u8 *edid_blk1 = NULL;
const u8 *svd = NULL;
@@ -1285,8 +1332,10 @@
}
/* 3d format described in Vendor Specific Data */
- hdmi_edid_get_display_vsd_3d_mode(data_buf, sink_data,
+ rc = hdmi_edid_get_display_vsd_3d_mode(data_buf, sink_data,
num_of_cea_blocks);
+ if (!rc)
+ pr_debug("%s: 3D formats in VSD\n", __func__);
}
/*
@@ -1302,7 +1351,7 @@
int hdmi_edid_read(void *input)
{
/* EDID_BLOCK_SIZE[0x80] Each page size in the EDID ROM */
- u8 edid_buf[0x80 * 4];
+ u8 *edid_buf = NULL;
u32 cea_extension_ver = 0;
u32 num_of_cea_blocks = 0;
u32 ieee_reg_id = 0;
@@ -1316,12 +1365,14 @@
return -EINVAL;
}
+ edid_buf = edid_ctrl->edid_buf;
+
edid_ctrl->pt_scan_info = 0;
edid_ctrl->it_scan_info = 0;
edid_ctrl->ce_scan_info = 0;
edid_ctrl->present_3d = 0;
memset(&edid_ctrl->sink_data, 0, sizeof(edid_ctrl->sink_data));
- memset(edid_buf, 0, sizeof(edid_buf));
+ memset(edid_buf, 0, sizeof(edid_ctrl->edid_buf));
memset(edid_ctrl->audio_data_block, 0,
sizeof(edid_ctrl->audio_data_block));
memset(edid_ctrl->spkr_alloc_data_block, 0,
@@ -1388,7 +1439,7 @@
for (i = 1; i <= num_of_cea_blocks; i++) {
if (!(i % 2)) {
status = hdmi_edid_read_block(
- edid_ctrl, i, edid_buf+0x00);
+ edid_ctrl, i, edid_buf + (0x80 * i));
if (status) {
DEV_ERR("%s: read blk(%d) failed:%d\n",
__func__, i, status);
@@ -1396,7 +1447,7 @@
}
} else {
status = hdmi_edid_read_block(
- edid_ctrl, i, edid_buf+0x80);
+ edid_ctrl, i, edid_buf + (0x80 * i));
if (status) {
DEV_ERR("%s: read blk(%d) failed:%d\n",
__func__, i, status);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
index 367c918..80b27ed 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_hdcp.c
@@ -17,6 +17,7 @@
#include <linux/stat.h>
#include "mdss_hdmi_hdcp.h"
+#include "video/msm_hdmi_hdcp_mgr.h"
#define HDCP_STATE_NAME (hdcp_state_name(hdcp_ctrl->hdcp_state))
@@ -31,7 +32,11 @@
#define HDCP_KEYS_STATE_RESERVED 7
struct hdmi_hdcp_ctrl {
+ u32 auth_retries;
+ u32 tp_msgid;
enum hdmi_hdcp_state hdcp_state;
+ struct HDCP_V2V1_MSG_TOPOLOGY cached_tp;
+ struct HDCP_V2V1_MSG_TOPOLOGY current_tp;
struct delayed_work hdcp_auth_work;
struct work_struct hdcp_int_work;
struct completion r0_checked;
@@ -194,7 +199,7 @@
bool is_match;
bool stale_an = false;
struct dss_io_data *io;
- u8 aksv[5], bksv[5];
+ u8 aksv[5], *bksv = NULL;
u8 an[8];
u8 bcaps;
struct hdmi_tx_ddc_data ddc_data;
@@ -215,6 +220,8 @@
goto error;
}
+ bksv = hdcp_ctrl->current_tp.bksv;
+
io = hdcp_ctrl->init_data.core_io;
/* Fetch aksv from QFPROM, this info should be public. */
@@ -606,11 +613,12 @@
{
int rc, cnt, i;
struct hdmi_tx_ddc_data ddc_data;
- u32 timeout_count, down_stream_devices;
+ u32 timeout_count, down_stream_devices = 0;
+ u32 repeater_cascade_depth = 0;
u8 buf[0xFF];
- u8 ksv_fifo[5 * 127];
+ u8 *ksv_fifo = NULL;
u8 bcaps;
- u16 bstatus, max_devs_exceeded, max_cascade_exceeded;
+ u16 bstatus, max_devs_exceeded = 0, max_cascade_exceeded = 0;
u32 link0_status;
u32 ksv_bytes;
struct dss_io_data *io;
@@ -628,10 +636,13 @@
goto error;
}
+ ksv_fifo = hdcp_ctrl->current_tp.ksv_list;
+
io = hdcp_ctrl->init_data.core_io;
memset(buf, 0, sizeof(buf));
- memset(ksv_fifo, 0, sizeof(ksv_fifo));
+ memset(ksv_fifo, 0,
+ sizeof(hdcp_ctrl->current_tp.ksv_list));
/* Read BCAPS at offset 0x40 */
memset(&ddc_data, 0, sizeof(ddc_data));
@@ -652,6 +663,10 @@
DEV_DBG("%s: %s: BCAPS=%02x (%s)\n", __func__, HDCP_STATE_NAME, bcaps,
(bcaps & BIT(6)) ? "repeater" : "no repeater");
+ /* receiver (0), repeater (1) */
+ hdcp_ctrl->current_tp.ds_type =
+ (bcaps & BIT(6)) >> 6 ? DS_REPEATER : DS_RECEIVER;
+
/* if REPEATER (Bit 6), perform Part2 Authentication */
if (!(bcaps & BIT(6))) {
DEV_INFO("%s: %s: auth part II skipped, no repeater\n",
@@ -717,6 +732,9 @@
goto error;
}
+ /* Cascaded repeater depth */
+ repeater_cascade_depth = (bstatus >> 8) & 0x7;
+
/*
* HDCP Compliance 1B-05:
* Check if no. of devices connected to repeater
@@ -866,9 +884,46 @@
else
DEV_INFO("%s: %s: Authentication Part II successful\n",
__func__, HDCP_STATE_NAME);
+
+ /* Update topology information */
+ hdcp_ctrl->current_tp.dev_count = down_stream_devices;
+ hdcp_ctrl->current_tp.max_cascade_exceeded = max_cascade_exceeded;
+ hdcp_ctrl->current_tp.max_dev_exceeded = max_devs_exceeded;
+ hdcp_ctrl->current_tp.depth = repeater_cascade_depth;
+
return rc;
} /* hdmi_hdcp_authentication_part2 */
+static void hdmi_hdcp_cache_topology(struct hdmi_hdcp_ctrl *hdcp_ctrl)
+{
+ if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ memcpy((void *)&hdcp_ctrl->cached_tp,
+ (void *) &hdcp_ctrl->current_tp,
+ sizeof(hdcp_ctrl->cached_tp));
+}
+
+static void hdmi_hdcp_notify_topology(struct hdmi_hdcp_ctrl *hdcp_ctrl)
+{
+ char a[16], b[16];
+ char *envp[] = {
+ [0] = "HDCP_MGR_EVENT=MSG_READY",
+ [1] = a,
+ [2] = b,
+ NULL,
+ };
+
+ snprintf(envp[1], 16, "%d", (int)DOWN_CHECK_TOPOLOGY);
+ snprintf(envp[2], 16, "%d", (int)HDCP_V1_TX);
+ kobject_uevent_env(hdcp_ctrl->init_data.sysfs_kobj, KOBJ_CHANGE, envp);
+
+ DEV_DBG("%s Event Sent: %s msgID = %s srcID = %s\n", __func__,
+ envp[0], envp[1], envp[2]);
+}
+
static void hdmi_hdcp_int_work(struct work_struct *work)
{
struct hdmi_hdcp_ctrl *hdcp_ctrl = container_of(work,
@@ -928,7 +983,7 @@
goto error;
}
/* Disabling software DDC before going into part3 to make sure
- * there is no Arbitratioon between software and hardware for DDC */
+ * there is no Arbitration between software and hardware for DDC */
DSS_REG_W_ND(io, HDMI_DDC_ARBITRATION , DSS_REG_R(io,
HDMI_DDC_ARBITRATION) | (BIT(4)));
@@ -941,10 +996,14 @@
*/
mutex_lock(hdcp_ctrl->init_data.mutex);
if (HDCP_STATE_AUTHENTICATING == hdcp_ctrl->hdcp_state) {
- if (rc)
+ if (rc) {
hdcp_ctrl->hdcp_state = HDCP_STATE_AUTH_FAIL;
- else
+ } else {
hdcp_ctrl->hdcp_state = HDCP_STATE_AUTHENTICATED;
+ hdcp_ctrl->auth_retries = 0;
+ hdmi_hdcp_cache_topology(hdcp_ctrl);
+ hdmi_hdcp_notify_topology(hdcp_ctrl);
+ }
mutex_unlock(hdcp_ctrl->init_data.mutex);
/* Notify HDMI Tx controller of the result */
@@ -989,10 +1048,38 @@
return 0;
} /* hdmi_hdcp_authenticate */
+/*
+ * Only retries defined times then abort current authenticating process
+ * Send check_topology message to notify any hdcpmanager's client of non-
+ * hdcp authenticated data link so the client can tear down any active secure
+ * playback.
+ * Reduce hdcp link to regular hdmi data link with hdcp disabled so any
+ * un-secure like UI & menu still can be sent over HDMI and display.
+ */
+#define AUTH_RETRIES_TIME (30)
+static int hdmi_msm_if_abort_reauth(struct hdmi_hdcp_ctrl *hdcp_ctrl)
+{
+ int ret = 0;
+
+ if (!hdcp_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ if (++hdcp_ctrl->auth_retries == AUTH_RETRIES_TIME) {
+ hdmi_hdcp_off(hdcp_ctrl);
+ hdcp_ctrl->auth_retries = 0;
+ ret = -ERANGE;
+ }
+
+ return ret;
+}
+
int hdmi_hdcp_reauthenticate(void *input)
{
struct hdmi_hdcp_ctrl *hdcp_ctrl = (struct hdmi_hdcp_ctrl *)input;
struct dss_io_data *io;
+ u32 ret = 0;
if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
DEV_ERR("%s: invalid input\n", __func__);
@@ -1001,13 +1088,19 @@
io = hdcp_ctrl->init_data.core_io;
-
if (HDCP_STATE_AUTH_FAIL != hdcp_ctrl->hdcp_state) {
DEV_DBG("%s: %s: invalid state. returning\n", __func__,
HDCP_STATE_NAME);
return 0;
}
+ ret = hdmi_msm_if_abort_reauth(hdcp_ctrl);
+
+ if (ret) {
+ DEV_ERR("%s: abort reauthentication!\n", __func__);
+ return ret;
+ }
+
/*
* Disable HPD circuitry.
* This is needed to reset the HDCP cipher engine so that when we
@@ -1042,7 +1135,7 @@
queue_delayed_work(hdcp_ctrl->init_data.workq,
&hdcp_ctrl->hdcp_auth_work, HZ/2);
- return 0;
+ return ret;
} /* hdmi_hdcp_reauthenticate */
void hdmi_hdcp_off(void *input)
@@ -1092,9 +1185,6 @@
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);
@@ -1192,10 +1282,76 @@
return ret;
} /* hdmi_hdcp_sysfs_rda_hdcp*/
+static ssize_t hdmi_hdcp_sysfs_rda_tp(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ struct hdmi_hdcp_ctrl *hdcp_ctrl =
+ hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_HDCP);
+
+ if (!hdcp_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (hdcp_ctrl->tp_msgid) {
+ case DOWN_CHECK_TOPOLOGY:
+ case DOWN_REQUEST_TOPOLOGY:
+ buf[MSG_ID_IDX] = hdcp_ctrl->tp_msgid;
+ buf[RET_CODE_IDX] = HDCP_AUTHED;
+ ret = HEADER_LEN;
+
+ memcpy(buf + HEADER_LEN, &hdcp_ctrl->cached_tp,
+ sizeof(struct HDCP_V2V1_MSG_TOPOLOGY));
+
+ ret += sizeof(struct HDCP_V2V1_MSG_TOPOLOGY);
+
+ /* clear the flag once data is read back to user space*/
+ hdcp_ctrl->tp_msgid = -1;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+} /* hdmi_hdcp_sysfs_rda_tp*/
+
+static ssize_t hdmi_hdcp_sysfs_wta_tp(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ int msgid = 0;
+ ssize_t ret = count;
+ struct hdmi_hdcp_ctrl *hdcp_ctrl =
+ hdmi_get_featuredata_from_sysfs_dev(dev, HDMI_TX_FEAT_HDCP);
+
+ if (!hdcp_ctrl || !buf) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ msgid = buf[0];
+
+ switch (msgid) {
+ case DOWN_CHECK_TOPOLOGY:
+ case DOWN_REQUEST_TOPOLOGY:
+ hdcp_ctrl->tp_msgid = msgid;
+ break;
+ /* more cases added here */
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+} /* hdmi_tx_sysfs_wta_hpd */
+
static DEVICE_ATTR(status, S_IRUGO, hdmi_hdcp_sysfs_rda_status, NULL);
+static DEVICE_ATTR(tp, S_IRUGO | S_IWUSR, hdmi_hdcp_sysfs_rda_tp,
+ hdmi_hdcp_sysfs_wta_tp);
+
static struct attribute *hdmi_hdcp_fs_attrs[] = {
&dev_attr_status.attr,
+ &dev_attr_tp.attr,
NULL,
};
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 0fd3655..e46e361 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -46,6 +46,14 @@
#define HPD_DISCONNECT_POLARITY 0
#define HPD_CONNECT_POLARITY 1
+/*
+ * Audio engine may take 1 to 3 sec to shutdown
+ * in normal cases. To handle worst cases, making
+ * timeout for audio engine shutdown as 5 sec.
+ */
+#define AUDIO_POLL_SLEEP_US (5 * 1000)
+#define AUDIO_POLL_TIMEOUT_US (AUDIO_POLL_SLEEP_US * 1000)
+
#define IFRAME_CHECKSUM_32(d) \
((d & 0xff) + ((d >> 8) & 0xff) + \
((d >> 16) & 0xff) + ((d >> 24) & 0xff))
@@ -87,8 +95,8 @@
static void hdmi_tx_hpd_off(struct hdmi_tx_ctrl *hdmi_ctrl);
static int hdmi_tx_enable_power(struct hdmi_tx_ctrl *hdmi_ctrl,
enum hdmi_tx_power_module_type module, int enable);
-static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl,
- bool wait_audio_tx);
+static inline void hdmi_tx_set_audio_switch_node(struct hdmi_tx_ctrl *hdmi_ctrl,
+ int val, bool force);
static int hdmi_tx_audio_setup(struct hdmi_tx_ctrl *hdmi_ctrl);
struct mdss_hw hdmi_tx_hw = {
@@ -126,7 +134,13 @@
}
} /* hdmi_pm_name */
-static u8 hdmi_tx_avi_iframe_lut[][20] = {
+static DEFINE_MUTEX(avi_iframe_lut_lock);
+#define NUM_MODES_AVI 20
+#define SET_ITC_BIT(byte) (byte | 0x80)
+#define CLR_ITC_BIT(byte) (byte & 0x7F)
+#define CONFIG_CN_BITS(bits, byte) ((byte & ~(0x03 << 4)) | (bits << 4))
+
+static u8 hdmi_tx_avi_iframe_lut[][NUM_MODES_AVI] = {
{0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10}, /*00*/
@@ -193,6 +207,55 @@
{20480, 247500} } },
};
+/* To statically config ITC bit from sysfs attribute */
+static int hdmi_tx_config_itc_bit(int itc)
+{
+ int ret = 0, loop = NUM_MODES_AVI;
+
+ if (mutex_lock_interruptible(&avi_iframe_lut_lock)) {
+ ret = -ERESTARTSYS;
+ goto signal_intr;
+ }
+
+ do {
+ --loop;
+ if (itc == 0)
+ hdmi_tx_avi_iframe_lut[2][loop] =
+ CLR_ITC_BIT(hdmi_tx_avi_iframe_lut[2][loop]);
+ if (itc == 1)
+ hdmi_tx_avi_iframe_lut[2][loop] =
+ SET_ITC_BIT(hdmi_tx_avi_iframe_lut[2][loop]);
+ } while (loop);
+
+ mutex_unlock(&avi_iframe_lut_lock);
+
+signal_intr:
+ return ret;
+}
+
+/* To configure CN0_1 bits from sysfs attribute */
+static int hdmi_tx_config_cn_bits(int cns)
+{
+ int ret = 0, loop = NUM_MODES_AVI;
+
+ if (mutex_lock_interruptible(&avi_iframe_lut_lock)) {
+ ret = -ERESTARTSYS;
+ goto signal_intr;
+ }
+
+ do {
+ --loop;
+ hdmi_tx_avi_iframe_lut[4][loop] =
+ CONFIG_CN_BITS(cns, hdmi_tx_avi_iframe_lut[4][loop]);
+ } while (loop);
+
+ mutex_unlock(&avi_iframe_lut_lock);
+
+signal_intr:
+ return ret;
+}
+
+
static bool hdmi_tx_is_cea_format(int mode)
{
bool cea_fmt;
@@ -288,6 +351,52 @@
return new_vic;
} /* hdmi_tx_get_vic_from_panel_info */
+static inline void hdmi_tx_send_cable_notification(
+ struct hdmi_tx_ctrl *hdmi_ctrl, int val)
+{
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ if (!hdmi_ctrl->pdata.primary && (hdmi_ctrl->sdev.state != val))
+ switch_set_state(&hdmi_ctrl->sdev, val);
+} /* hdmi_tx_send_cable_notification */
+
+static inline u32 hdmi_tx_is_dvi_mode(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ return hdmi_edid_get_sink_mode(
+ hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) ? 0 : 1;
+} /* hdmi_tx_is_dvi_mode */
+
+static void hdmi_tx_wait_for_audio_engine(struct hdmi_tx_ctrl *hdmi_ctrl)
+{
+ u32 status = 0;
+ struct dss_io_data *io = NULL;
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+ if (!io->base) {
+ DEV_ERR("%s: core io not inititalized\n", __func__);
+ return;
+ }
+
+ if (readl_poll_timeout(io->base + HDMI_AUDIO_PKT_CTRL, status,
+ (status & BIT(0)) == 0, AUDIO_POLL_SLEEP_US,
+ AUDIO_POLL_TIMEOUT_US))
+ DEV_ERR("%s: Error turning off audio packet transmission.\n",
+ __func__);
+
+ if (readl_poll_timeout(io->base + HDMI_AUDIO_CFG, status,
+ (status & BIT(0)) == 0, AUDIO_POLL_SLEEP_US,
+ AUDIO_POLL_TIMEOUT_US))
+ DEV_ERR("%s: Error turning off audio engine.\n", __func__);
+}
+
static struct hdmi_tx_ctrl *hdmi_tx_get_drvdata_from_panel_data(
struct mdss_panel_data *mpd)
{
@@ -327,7 +436,7 @@
{
struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
- if (!device || feature_type > HDMI_TX_FEAT_MAX) {
+ if (!device || feature_type >= HDMI_TX_FEAT_MAX) {
DEV_ERR("%s: invalid input\n", __func__);
return NULL;
}
@@ -406,6 +515,15 @@
if (0 == hpd && hdmi_ctrl->hpd_feature_on) {
rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, false);
+
+ if (hdmi_ctrl->panel_power_on && hdmi_ctrl->hpd_state) {
+ hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, false);
+ hdmi_tx_wait_for_audio_engine(hdmi_ctrl);
+ }
+
+ hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
+ DEV_DBG("%s: Hdmi state switch to %d\n", __func__,
+ hdmi_ctrl->sdev.state);
} else if (1 == hpd && !hdmi_ctrl->hpd_feature_on) {
rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, true);
} else {
@@ -544,6 +662,58 @@
return ret;
} /* hdmi_tx_sysfs_rda_product_description */
+static ssize_t hdmi_tx_sysfs_wta_avi_itc(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ ssize_t ret = strnlen(buf, PAGE_SIZE);
+ int err = 0;
+ int itc = 0, rc = 0;
+
+ rc = kstrtoint(buf, 10, &itc);
+ if (rc) {
+ DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc);
+ return rc;
+ }
+
+ if (itc == 0 || itc == 1) {
+ if (hdmi_tx_config_itc_bit(itc))
+ ret = err;
+ else
+ DEV_DBG("%s: '%d is configured'!\n", __func__, itc);
+ } else {
+ DEV_ERR("%s: unknown ITC '%d', should be either 0 or 1\n",
+ __func__, itc);
+ }
+
+ return ret;
+} /* hdmi_tx_sysfs_wta_avi_itc */
+
+static ssize_t hdmi_tx_sysfs_wta_avi_cn0_1(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ ssize_t ret = strnlen(buf, PAGE_SIZE);
+ int err = 0;
+ int cns = 0, rc = 0;
+
+ rc = kstrtoint(buf, 10, &cns);
+ if (rc) {
+ DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc);
+ return rc;
+ }
+
+ if (cns == 0 || cns == 1 || cns == 2 || cns == 3) {
+ if (hdmi_tx_config_cn_bits(cns))
+ ret = err;
+ else
+ DEV_DBG("%s: '%d is configured'!\n", __func__, cns);
+ } else {
+ DEV_ERR("%s: unknown CN '%d' should be either 0 or 1, 2 ,3\n",
+ __func__, cns);
+ }
+
+ return ret;
+} /* hdmi_tx_sysfs_wta_avi_cn0_1 */
+
static DEVICE_ATTR(connected, S_IRUGO, hdmi_tx_sysfs_rda_connected, NULL);
static DEVICE_ATTR(hpd, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_hpd,
hdmi_tx_sysfs_wta_hpd);
@@ -552,12 +722,16 @@
static DEVICE_ATTR(product_description, S_IRUGO | S_IWUSR,
hdmi_tx_sysfs_rda_product_description,
hdmi_tx_sysfs_wta_product_description);
+static DEVICE_ATTR(avi_itc, S_IWUSR, NULL, hdmi_tx_sysfs_wta_avi_itc);
+static DEVICE_ATTR(avi_cn0_1, S_IWUSR, NULL, hdmi_tx_sysfs_wta_avi_cn0_1);
static struct attribute *hdmi_tx_fs_attrs[] = {
&dev_attr_connected.attr,
&dev_attr_hpd.attr,
&dev_attr_vendor_name.attr,
&dev_attr_product_description.attr,
+ &dev_attr_avi_itc.attr,
+ &dev_attr_avi_cn0_1.attr,
NULL,
};
static struct attribute_group hdmi_tx_fs_attrs_group = {
@@ -597,24 +771,6 @@
hdmi_ctrl->kobj = NULL;
} /* hdmi_tx_sysfs_remove */
-static inline u32 hdmi_tx_is_dvi_mode(struct hdmi_tx_ctrl *hdmi_ctrl)
-{
- return hdmi_edid_get_sink_mode(
- hdmi_ctrl->feature_data[HDMI_TX_FEAT_EDID]) ? 0 : 1;
-} /* hdmi_tx_is_dvi_mode */
-
-static inline void hdmi_tx_send_cable_notification(
- struct hdmi_tx_ctrl *hdmi_ctrl, int val)
-{
- if (!hdmi_ctrl) {
- DEV_ERR("%s: invalid input\n", __func__);
- return;
- }
-
- if (!hdmi_ctrl->pdata.primary && (hdmi_ctrl->sdev.state != val))
- switch_set_state(&hdmi_ctrl->sdev, val);
-} /* hdmi_tx_send_cable_notification */
-
static inline void hdmi_tx_set_audio_switch_node(struct hdmi_tx_ctrl *hdmi_ctrl,
int val, bool force)
{
@@ -901,8 +1057,8 @@
DEV_INFO("%s: sense cable CONNECTED: state switch to %d\n",
__func__, hdmi_ctrl->sdev.state);
} else {
- if (hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, false))
- DEV_WARN("%s: Failed to disable ddc power\n", __func__);
+ hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, false);
+ hdmi_tx_wait_for_audio_engine(hdmi_ctrl);
hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
DEV_INFO("%s: sense cable DISCONNECTED: state switch to %d\n",
@@ -2134,10 +2290,8 @@
return 0;
} /* hdmi_tx_audio_setup */
-static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl,
- bool wait_audio_tx)
+static void hdmi_tx_audio_off(struct hdmi_tx_ctrl *hdmi_ctrl)
{
- u32 i = 0, status, sleep_us, timeout_us, timeout_sec = 15;
struct dss_io_data *io = NULL;
if (!hdmi_ctrl) {
@@ -2151,34 +2305,6 @@
return;
}
- if (wait_audio_tx) {
- /* Check if audio engine is turned off by QDSP or not */
- /* send off notification after every 1 sec for 15 seconds */
- for (i = 0; i < timeout_sec; i++) {
- /* Maximum time to sleep between two reads */
- sleep_us = 5000;
- /* Total time for condition to meet */
- timeout_us = 1000 * 1000;
-
- if (readl_poll_timeout((io->base + HDMI_AUDIO_CFG),
- status, ((status & BIT(0)) == 0),
- sleep_us, timeout_us)) {
-
- DEV_ERR(
- "%s: audio still on after %d sec. try again\n",
- __func__, i+1);
-
- hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0,
- true);
- continue;
- }
- break;
- }
- }
-
- if (i == timeout_sec)
- DEV_ERR("%s: Error: cannot turn off audio engine\n", __func__);
-
if (hdmi_tx_audio_iframe_setup(hdmi_ctrl, false))
DEV_ERR("%s: hdmi_tx_audio_iframe_setup failed.\n", __func__);
@@ -2302,10 +2428,11 @@
hdmi_hdcp_off(hdmi_ctrl->feature_data[HDMI_TX_FEAT_HDCP]);
}
- if (!hdmi_tx_is_dvi_mode(hdmi_ctrl)) {
- hdmi_tx_set_audio_switch_node(hdmi_ctrl, 0, false);
- hdmi_tx_audio_off(hdmi_ctrl, true);
- }
+ if (hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, false))
+ DEV_WARN("%s: Failed to disable ddc power\n", __func__);
+
+ if (!hdmi_tx_is_dvi_mode(hdmi_ctrl))
+ hdmi_tx_audio_off(hdmi_ctrl);
hdmi_tx_powerdown_phy(hdmi_ctrl);
@@ -2556,10 +2683,6 @@
hdmi_tx_hpd_off(hdmi_ctrl);
else
hdmi_ctrl->hpd_off_pending = true;
-
- hdmi_tx_send_cable_notification(hdmi_ctrl, 0);
- DEV_DBG("%s: Hdmi state switch to %d\n", __func__,
- hdmi_ctrl->sdev.state);
}
return rc;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.c b/drivers/video/msm/mdss/mdss_hdmi_util.c
index 53dfc71..711ec68 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.c
@@ -123,30 +123,30 @@
return "";
} /* hdmi_get_single_video_3d_fmt_2string */
-ssize_t hdmi_get_video_3d_fmt_2string(u32 format, char *buf)
+ssize_t hdmi_get_video_3d_fmt_2string(u32 format, char *buf, u32 size)
{
ssize_t ret, len = 0;
- ret = snprintf(buf, PAGE_SIZE, "%s",
+ ret = scnprintf(buf, size, "%s",
hdmi_get_single_video_3d_fmt_2string(
format & FRAME_PACKING));
len += ret;
if (len && (format & TOP_AND_BOTTOM))
- ret = snprintf(buf + len, PAGE_SIZE, ":%s",
+ ret = scnprintf(buf + len, size - len, ":%s",
hdmi_get_single_video_3d_fmt_2string(
format & TOP_AND_BOTTOM));
else
- ret = snprintf(buf + len, PAGE_SIZE, "%s",
+ ret = scnprintf(buf + len, size - len, "%s",
hdmi_get_single_video_3d_fmt_2string(
format & TOP_AND_BOTTOM));
len += ret;
if (len && (format & SIDE_BY_SIDE_HALF))
- ret = snprintf(buf + len, PAGE_SIZE, ":%s",
+ ret = scnprintf(buf + len, size - len, ":%s",
hdmi_get_single_video_3d_fmt_2string(
format & SIDE_BY_SIDE_HALF));
else
- ret = snprintf(buf + len, PAGE_SIZE, "%s",
+ ret = scnprintf(buf + len, size - len, "%s",
hdmi_get_single_video_3d_fmt_2string(
format & SIDE_BY_SIDE_HALF));
len += ret;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.h b/drivers/video/msm/mdss/mdss_hdmi_util.h
index e99e549..5f7878b 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.h
@@ -256,7 +256,7 @@
int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in);
const struct msm_hdmi_mode_timing_info *hdmi_get_supported_mode(u32 mode);
void hdmi_del_supported_mode(u32 mode);
-ssize_t hdmi_get_video_3d_fmt_2string(u32 format, char *buf);
+ssize_t hdmi_get_video_3d_fmt_2string(u32 format, char *buf, u32 size);
/* todo: Fix this. Right now this is defined in mdss_hdmi_tx.c */
void *hdmi_get_featuredata_from_sysfs_dev(struct device *device, u32 type);
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 3107e38..9cb76c2 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -48,6 +48,7 @@
#include <mach/iommu_domains.h>
#include <mach/memory.h>
#include <mach/msm_memtypes.h>
+#include <mach/rpm-regulator-smd.h>
#include "mdss.h"
#include "mdss_fb.h"
@@ -700,6 +701,14 @@
}
mdata->fs_ena = false;
+ mdata->vdd_cx = devm_regulator_get(&mdata->pdev->dev,
+ "vdd-cx");
+ if (IS_ERR_OR_NULL(mdata->vdd_cx)) {
+ pr_debug("unable to get CX reg. rc=%d\n",
+ PTR_RET(mdata->vdd_cx));
+ mdata->vdd_cx = NULL;
+ }
+
if (mdss_mdp_irq_clk_register(mdata, "bus_clk", MDSS_CLK_AXI) ||
mdss_mdp_irq_clk_register(mdata, "iface_clk", MDSS_CLK_AHB) ||
mdss_mdp_irq_clk_register(mdata, "core_clk_src",
@@ -1762,7 +1771,8 @@
struct mdss_data_type *mdata = platform_get_drvdata(pdev);
u32 num;
u32 data[2];
- int rc;
+ int rc, len;
+ const u32 *arr;
num = mdss_mdp_parse_dt_prop_len(pdev, "qcom,mdss-smp-data");
@@ -1784,7 +1794,49 @@
"qcom,mdss-smp-mb-per-pipe", data);
mdata->smp_mb_per_pipe = (!rc ? data[0] : 0);
- return 0;
+ rc = 0;
+ arr = of_get_property(pdev->dev.of_node,
+ "qcom,mdss-pipe-rgb-fixed-mmb", &len);
+ if (arr) {
+ int i, j, k;
+ u32 cnt, mmb;
+
+ len /= sizeof(u32);
+ for (i = 0, k = 0; i < len; k++) {
+ struct mdss_mdp_pipe *pipe = NULL;
+
+ if (k >= mdata->nrgb_pipes) {
+ pr_err("invalid fixed mmbs for rgb pipes\n");
+ return -EINVAL;
+ }
+
+ pipe = &mdata->rgb_pipes[k];
+
+ cnt = be32_to_cpu(arr[i++]);
+ if (cnt == 0)
+ continue;
+
+ for (j = 0; j < cnt; j++) {
+ mmb = be32_to_cpu(arr[i++]);
+ if (mmb > mdata->smp_mb_cnt) {
+ pr_err("overflow mmb%d: rgb%d: max%d\n",
+ mmb, k, mdata->smp_mb_cnt);
+ return -EINVAL;
+ }
+ /* rgb pipes fetches only single plane */
+ set_bit(mmb, pipe->smp_map[0].fixed);
+ }
+ if (bitmap_intersects(pipe->smp_map[0].fixed,
+ mdata->mmb_alloc_map, mdata->smp_mb_cnt)) {
+ pr_err("overlapping fixed mmb map\n");
+ return -EINVAL;
+ }
+ bitmap_or(mdata->mmb_alloc_map, pipe->smp_map[0].fixed,
+ mdata->mmb_alloc_map, mdata->smp_mb_cnt);
+ }
+ }
+
+ return rc;
}
static int mdss_mdp_parse_dt_misc(struct platform_device *pdev)
@@ -1792,6 +1844,7 @@
struct mdss_data_type *mdata = platform_get_drvdata(pdev);
u32 data;
int rc;
+ struct property *prop = NULL;
rc = of_property_read_u32(pdev->dev.of_node, "qcom,mdss-rot-block-size",
&data);
@@ -1803,6 +1856,9 @@
"qcom,mdss-has-decimation");
mdata->has_wfd_blk = of_property_read_bool(pdev->dev.of_node,
"qcom,mdss-has-wfd-blk");
+ prop = of_find_property(pdev->dev.of_node, "batfet-supply", NULL);
+ mdata->batfet_required = prop ? true : false;
+
return 0;
}
@@ -1931,6 +1987,76 @@
return rc;
}
+static int mdss_mdp_cx_ctrl(struct mdss_data_type *mdata, int enable)
+{
+ int rc = 0;
+
+ if (!mdata->vdd_cx)
+ return rc;
+
+ if (enable) {
+ rc = regulator_set_voltage(
+ mdata->vdd_cx,
+ RPM_REGULATOR_CORNER_SVS_SOC,
+ RPM_REGULATOR_CORNER_SUPER_TURBO);
+ if (rc < 0)
+ goto vreg_set_voltage_fail;
+
+ pr_debug("Enabling CX power rail\n");
+ rc = regulator_enable(mdata->vdd_cx);
+ if (rc) {
+ pr_err("Failed to enable regulator.\n");
+ return rc;
+ }
+ } else {
+ pr_debug("Disabling CX power rail\n");
+ rc = regulator_disable(mdata->vdd_cx);
+ if (rc) {
+ pr_err("Failed to disable regulator.\n");
+ return rc;
+ }
+ rc = regulator_set_voltage(
+ mdata->vdd_cx,
+ RPM_REGULATOR_CORNER_NONE,
+ RPM_REGULATOR_CORNER_SUPER_TURBO);
+ if (rc < 0)
+ goto vreg_set_voltage_fail;
+ }
+
+ return rc;
+
+vreg_set_voltage_fail:
+ pr_err("Set vltg fail\n");
+ return rc;
+}
+
+void mdss_mdp_batfet_ctrl(struct mdss_data_type *mdata, int enable)
+{
+ if (!mdata->batfet_required)
+ return;
+
+ if (!mdata->batfet) {
+ if (enable) {
+ mdata->batfet = devm_regulator_get(&mdata->pdev->dev,
+ "batfet");
+ if (IS_ERR_OR_NULL(mdata->batfet)) {
+ pr_debug("unable to get batfet reg. rc=%d\n",
+ PTR_RET(mdata->batfet));
+ mdata->batfet = NULL;
+ return;
+ }
+ } else {
+ pr_debug("Batfet regulator disable w/o enable\n");
+ return;
+ }
+ }
+
+ if (enable)
+ regulator_enable(mdata->batfet);
+ else
+ regulator_disable(mdata->batfet);
+}
+
static void mdss_mdp_footswitch_ctrl(struct mdss_data_type *mdata, int on)
{
if (!mdata->fs)
@@ -1938,14 +2064,20 @@
if (on) {
pr_debug("Enable MDP FS\n");
- if (!mdata->fs_ena)
+ if (!mdata->fs_ena) {
regulator_enable(mdata->fs);
+ mdss_mdp_cx_ctrl(mdata, true);
+ mdss_mdp_batfet_ctrl(mdata, true);
+ }
mdata->fs_ena = true;
} else {
pr_debug("Disable MDP FS\n");
mdss_iommu_dettach(mdata);
- if (mdata->fs_ena)
+ if (mdata->fs_ena) {
regulator_disable(mdata->fs);
+ mdss_mdp_cx_ctrl(mdata, false);
+ mdss_mdp_batfet_ctrl(mdata, false);
+ }
mdata->fs_ena = false;
}
}
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 134ffea..d8dc6ca 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -18,9 +18,11 @@
#include <linux/io.h>
#include <linux/msm_mdp.h>
#include <linux/platform_device.h>
+#include <linux/notifier.h>
#include "mdss.h"
#include "mdss_mdp_hwio.h"
+#include "mdss_fb.h"
#define MDSS_MDP_DEFAULT_INTR_MASK 0
#define MDSS_MDP_CURSOR_WIDTH 64
@@ -114,6 +116,13 @@
struct mdss_mdp_ctl;
typedef void (*mdp_vsync_handler_t)(struct mdss_mdp_ctl *, ktime_t);
+struct mdss_mdp_img_rect {
+ u16 x;
+ u16 y;
+ u16 w;
+ u16 h;
+};
+
struct mdss_mdp_vsync_handler {
bool enabled;
bool cmd_post_flush;
@@ -165,6 +174,9 @@
struct mdss_panel_data *panel_data;
struct mdss_mdp_vsync_handler vsync_handler;
+ struct mdss_mdp_img_rect roi;
+ u8 roi_changed;
+
int (*start_fnc) (struct mdss_mdp_ctl *ctl);
int (*stop_fnc) (struct mdss_mdp_ctl *ctl);
int (*prepare_fnc) (struct mdss_mdp_ctl *ctl, void *arg);
@@ -177,6 +189,9 @@
int (*remove_vsync_handler) (struct mdss_mdp_ctl *,
struct mdss_mdp_vsync_handler *);
int (*config_fps_fnc) (struct mdss_mdp_ctl *ctl, int new_fps);
+
+ struct blocking_notifier_head notifier_head;
+
void *priv_data;
u32 wb_type;
};
@@ -191,6 +206,7 @@
u8 params_changed;
u16 width;
u16 height;
+ struct mdss_mdp_img_rect roi;
u8 cursor_enabled;
u8 rotator_mode;
@@ -198,13 +214,6 @@
struct mdss_mdp_pipe *stage_pipe[MDSS_MDP_MAX_STAGE];
};
-struct mdss_mdp_img_rect {
- u16 x;
- u16 y;
- u16 w;
- u16 h;
-};
-
struct mdss_mdp_format_params {
u32 format;
u8 is_yuv;
@@ -307,8 +316,9 @@
};
struct mdss_mdp_pipe_smp_map {
- DECLARE_BITMAP(reserved, MDSS_MDP_SMP_MMB_BLOCKS);
- DECLARE_BITMAP(allocated, MDSS_MDP_SMP_MMB_BLOCKS);
+ DECLARE_BITMAP(reserved, MAX_DRV_SUP_MMB_BLKS);
+ DECLARE_BITMAP(allocated, MAX_DRV_SUP_MMB_BLKS);
+ DECLARE_BITMAP(fixed, MAX_DRV_SUP_MMB_BLKS);
};
struct mdss_mdp_pipe {
@@ -320,6 +330,7 @@
atomic_t ref_cnt;
u32 play_cnt;
int pid;
+ bool is_handed_off;
u32 flags;
u32 bwc_mode;
@@ -389,8 +400,10 @@
int free_list_size;
int ad_state;
+ bool handoff;
u32 splash_mem_addr;
u32 splash_mem_size;
+ u32 sd_enabled;
};
struct mdss_mdp_perf_params {
@@ -446,6 +459,7 @@
void (*fnc_ptr)(void *), void *arg);
void mdss_mdp_footswitch_ctrl_splash(int on);
+void mdss_mdp_batfet_ctrl(struct mdss_data_type *mdata, int enable);
int mdss_mdp_bus_scale_set_quota(u64 ab_quota, u64 ib_quota);
void mdss_mdp_set_clk_rate(unsigned long min_clk_rate);
unsigned long mdss_mdp_get_clk_rate(u32 clk_idx);
@@ -454,19 +468,30 @@
struct mdss_data_type *mdss_mdp_get_mdata(void);
int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd);
+int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd,
+ struct mdp_overlay *req,
+ struct mdss_mdp_format_params *fmt);
int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en);
+int mdss_mdp_overlay_get_buf(struct msm_fb_data_type *mfd,
+ struct mdss_mdp_data *data,
+ struct msmfb_data *planes,
+ int num_planes,
+ u32 flags);
int mdss_mdp_video_addr_setup(struct mdss_data_type *mdata,
u32 *offsets, u32 count);
int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl);
int mdss_mdp_cmd_start(struct mdss_mdp_ctl *ctl);
int mdss_mdp_writeback_start(struct mdss_mdp_ctl *ctl);
-int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd);
+int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
+ struct mdp_display_commit *data);
struct mdss_mdp_ctl *mdss_mdp_ctl_init(struct mdss_panel_data *pdata,
struct msm_fb_data_type *mfd);
-int mdss_mdp_video_reconfigure_splash_done(struct mdss_mdp_ctl *ctl);
-int mdss_mdp_cmd_reconfigure_splash_done(struct mdss_mdp_ctl *ctl);
-int mdss_mdp_ctl_splash_finish(struct mdss_mdp_ctl *ctl);
+int mdss_mdp_video_reconfigure_splash_done(struct mdss_mdp_ctl *ctl,
+ bool handoff);
+int mdss_mdp_cmd_reconfigure_splash_done(struct mdss_mdp_ctl *ctl,
+ bool handoff);
+int mdss_mdp_ctl_splash_finish(struct mdss_mdp_ctl *ctl, bool handoff);
int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl);
int mdss_mdp_ctl_split_display_setup(struct mdss_mdp_ctl *ctl,
struct mdss_panel_data *pdata);
@@ -476,7 +501,14 @@
int mdss_mdp_ctl_intf_event(struct mdss_mdp_ctl *ctl, int event, void *arg);
int mdss_mdp_perf_calc_pipe(struct mdss_mdp_pipe *pipe,
struct mdss_mdp_perf_params *perf);
+int mdss_mdp_ctl_notify(struct mdss_mdp_ctl *ctl, int event);
+void mdss_mdp_ctl_notifier_register(struct mdss_mdp_ctl *ctl,
+ struct notifier_block *notifier);
+void mdss_mdp_ctl_notifier_unregister(struct mdss_mdp_ctl *ctl,
+ struct notifier_block *notifier);
+int mdss_mdp_mixer_handoff(struct mdss_mdp_ctl *ctl, u32 num,
+ struct mdss_mdp_pipe *pipe);
struct mdss_mdp_mixer *mdss_mdp_wb_mixer_alloc(int rotator);
int mdss_mdp_wb_mixer_destroy(struct mdss_mdp_mixer *mixer);
struct mdss_mdp_mixer *mdss_mdp_mixer_get(struct mdss_mdp_ctl *ctl, int mux);
@@ -508,33 +540,18 @@
int mdss_hw_init(struct mdss_data_type *mdata);
-int mdss_mdp_pa_config(struct mdss_mdp_ctl *ctl,
- struct mdp_pa_cfg_data *config,
- u32 *copyback);
-int mdss_mdp_pcc_config(struct mdss_mdp_ctl *ctl,
- struct mdp_pcc_cfg_data *cfg_ptr,
- u32 *copyback);
-int mdss_mdp_igc_lut_config(struct mdss_mdp_ctl *ctl,
- struct mdp_igc_lut_data *config,
- u32 *copyback, u32 copy_from_kernel);
-int mdss_mdp_argc_config(struct mdss_mdp_ctl *ctl,
- struct mdp_pgc_lut_data *config,
- u32 *copyback);
-int mdss_mdp_hist_lut_config(struct mdss_mdp_ctl *ctl,
- struct mdp_hist_lut_data *config,
- u32 *copyback);
-int mdss_mdp_dither_config(struct mdss_mdp_ctl *ctl,
- struct mdp_dither_cfg_data *config,
- u32 *copyback);
-int mdss_mdp_gamut_config(struct mdss_mdp_ctl *ctl,
- struct mdp_gamut_cfg_data *config,
- u32 *copyback);
+int mdss_mdp_pa_config(struct mdp_pa_cfg_data *config, u32 *copyback);
+int mdss_mdp_pcc_config(struct mdp_pcc_cfg_data *cfg_ptr, u32 *copyback);
+int mdss_mdp_igc_lut_config(struct mdp_igc_lut_data *config, u32 *copyback,
+ u32 copy_from_kernel);
+int mdss_mdp_argc_config(struct mdp_pgc_lut_data *config, u32 *copyback);
+int mdss_mdp_hist_lut_config(struct mdp_hist_lut_data *config, u32 *copyback);
+int mdss_mdp_dither_config(struct mdp_dither_cfg_data *config, u32 *copyback);
+int mdss_mdp_gamut_config(struct mdp_gamut_cfg_data *config, u32 *copyback);
-int mdss_mdp_histogram_start(struct mdss_mdp_ctl *ctl,
- struct mdp_histogram_start_req *req);
-int mdss_mdp_histogram_stop(struct mdss_mdp_ctl *ctl, u32 block);
-int mdss_mdp_hist_collect(struct mdss_mdp_ctl *ctl,
- struct mdp_histogram_data *hist);
+int mdss_mdp_histogram_start(struct mdp_histogram_start_req *req);
+int mdss_mdp_histogram_stop(u32 block);
+int mdss_mdp_hist_collect(struct mdp_histogram_data *hist);
void mdss_mdp_hist_intr_done(u32 isr);
int mdss_mdp_ad_config(struct msm_fb_data_type *mfd,
@@ -545,6 +562,8 @@
int mdss_mdp_calib_mode(struct msm_fb_data_type *mfd,
struct mdss_calib_cfg *cfg);
+int mdss_mdp_pipe_handoff(struct mdss_mdp_pipe *pipe);
+int mdss_mdp_smp_handoff(struct mdss_data_type *mdata);
struct mdss_mdp_pipe *mdss_mdp_pipe_alloc(struct mdss_mdp_mixer *mixer,
u32 type);
struct mdss_mdp_pipe *mdss_mdp_pipe_get(struct mdss_data_type *mdata, u32 ndx);
@@ -581,8 +600,12 @@
struct mdss_mdp_format_params *mdss_mdp_get_format_params(u32 format);
int mdss_mdp_put_img(struct mdss_mdp_img_data *data);
int mdss_mdp_get_img(struct msmfb_data *img, struct mdss_mdp_img_data *data);
+int mdss_mdp_overlay_free_buf(struct mdss_mdp_data *data);
u32 mdss_get_panel_framerate(struct msm_fb_data_type *mfd);
int mdss_mdp_calc_phase_step(u32 src, u32 dst, u32 *out_phase);
+void mdss_mdp_intersect_rect(struct mdss_mdp_img_rect *res_rect,
+ const struct mdss_mdp_img_rect *dst_rect,
+ const struct mdss_mdp_img_rect *sci_rect);
int mdss_mdp_wb_kickoff(struct msm_fb_data_type *mfd);
int mdss_mdp_wb_ioctl_handler(struct msm_fb_data_type *mfd, u32 cmd, void *arg);
@@ -600,6 +623,8 @@
int mdss_mdp_writeback_display_commit(struct mdss_mdp_ctl *ctl, void *arg);
struct mdss_mdp_ctl *mdss_mdp_ctl_mixer_switch(struct mdss_mdp_ctl *ctl,
u32 return_type);
+void mdss_mdp_set_roi(struct mdss_mdp_ctl *ctl,
+ struct mdp_display_commit *data);
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,
@@ -613,4 +638,5 @@
#define mfd_to_wb(mfd) (((struct mdss_overlay_private *)\
(mfd->mdp.private1))->wb)
+int mdss_mdp_ctl_reset(struct mdss_mdp_ctl *ctl);
#endif /* MDSS_MDP_H */
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index bce4248..82937e3 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -16,6 +16,8 @@
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
#include "mdss_fb.h"
#include "mdss_mdp.h"
@@ -383,6 +385,7 @@
ctl->ref_cnt++;
ctl->mdata = mdata;
mutex_init(&ctl->lock);
+ BLOCKING_INIT_NOTIFIER_HEAD(&ctl->notifier_head);
pr_debug("alloc ctl_num=%d\n", ctl->num);
break;
}
@@ -588,6 +591,11 @@
{
struct mdss_mdp_ctl *ctl;
+ if (!mixer || !mixer->ctl) {
+ pr_err("invalid ctl handle\n");
+ return -ENODEV;
+ }
+
ctl = mixer->ctl;
mixer->rotator_mode = 0;
@@ -603,13 +611,13 @@
return 0;
}
-int mdss_mdp_ctl_splash_finish(struct mdss_mdp_ctl *ctl)
+int mdss_mdp_ctl_splash_finish(struct mdss_mdp_ctl *ctl, bool handoff)
{
switch (ctl->panel_data->panel_info.type) {
case MIPI_VIDEO_PANEL:
- return mdss_mdp_video_reconfigure_splash_done(ctl);
+ return mdss_mdp_video_reconfigure_splash_done(ctl, handoff);
case MIPI_CMD_PANEL:
- return mdss_mdp_cmd_reconfigure_splash_done(ctl);
+ return mdss_mdp_cmd_reconfigure_splash_done(ctl, handoff);
default:
return 0;
}
@@ -716,6 +724,7 @@
ctl->width = width;
ctl->height = height;
+ ctl->roi = (struct mdss_mdp_img_rect) {0, 0, width, height};
if (!ctl->mixer_left) {
ctl->mixer_left =
@@ -734,6 +743,7 @@
ctl->mixer_left->width = width;
ctl->mixer_left->height = height;
+ ctl->mixer_left->roi = (struct mdss_mdp_img_rect) {0, 0, width, height};
if (split_ctl) {
pr_debug("split display detected\n");
@@ -756,6 +766,8 @@
}
ctl->mixer_right->width = width;
ctl->mixer_right->height = height;
+ ctl->mixer_right->roi = (struct mdss_mdp_img_rect)
+ {0, 0, width, height};
} else if (ctl->mixer_right) {
mdss_mdp_mixer_free(ctl->mixer_right);
ctl->mixer_right = NULL;
@@ -906,7 +918,7 @@
ctl->dst_format = MDSS_MDP_PANEL_FORMAT_RGB888;
break;
}
- mdss_mdp_dither_config(ctl, &dither, NULL);
+ mdss_mdp_dither_config(&dither, NULL);
}
return ctl;
@@ -1067,9 +1079,12 @@
pr_debug("ctl_num=%d\n", ctl->num);
- nmixers = MDSS_MDP_INTF_MAX_LAYERMIXER + MDSS_MDP_WB_MAX_LAYERMIXER;
- for (i = 0; i < nmixers; i++)
- mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_LAYER(i), 0);
+ if (!ctl->panel_data->panel_info.cont_splash_enabled) {
+ nmixers = MDSS_MDP_INTF_MAX_LAYERMIXER +
+ MDSS_MDP_WB_MAX_LAYERMIXER;
+ for (i = 0; i < nmixers; i++)
+ mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_LAYER(i), 0);
+ }
mixer = ctl->mixer_left;
mdss_mdp_pp_resume(ctl, mixer->num);
@@ -1208,6 +1223,83 @@
return ret;
}
+void mdss_mdp_set_roi(struct mdss_mdp_ctl *ctl,
+ struct mdp_display_commit *data)
+{
+ struct mdss_mdp_img_rect temp_roi, mixer_roi;
+
+ temp_roi.x = data->roi.x;
+ temp_roi.y = data->roi.y;
+ temp_roi.w = data->roi.w;
+ temp_roi.h = data->roi.h;
+
+ /*
+ * No Partial Update for:
+ * 1) dual DSI panels
+ * 2) non-cmd mode panels
+ */
+ if (!temp_roi.w || !temp_roi.h || ctl->mixer_right ||
+ (ctl->panel_data->panel_info.type != MIPI_CMD_PANEL) ||
+ !ctl->panel_data->panel_info.partial_update_enabled) {
+ temp_roi = (struct mdss_mdp_img_rect)
+ {0, 0, ctl->mixer_left->width,
+ ctl->mixer_left->height};
+ }
+
+ ctl->roi_changed = 0;
+ if (((temp_roi.x != ctl->roi.x) ||
+ (temp_roi.y != ctl->roi.y)) ||
+ ((temp_roi.w != ctl->roi.w) ||
+ (temp_roi.h != ctl->roi.h))) {
+ ctl->roi = temp_roi;
+ ctl->roi_changed++;
+
+ mixer_roi = ctl->mixer_left->roi;
+ if ((mixer_roi.w != temp_roi.w) ||
+ (mixer_roi.h != temp_roi.h)) {
+ ctl->mixer_left->roi = temp_roi;
+ ctl->mixer_left->params_changed++;
+ }
+ }
+ pr_debug("ROI requested: [%d, %d, %d, %d]\n",
+ ctl->roi.x, ctl->roi.y, ctl->roi.w, ctl->roi.h);
+}
+
+/*
+ * mdss_mdp_ctl_reset() - reset mdp ctl path.
+ * @ctl: mdp controller.
+ * this function called when underflow happen,
+ * it will reset mdp ctl path and poll for its completion
+ *
+ * Note: called within atomic context.
+ */
+int mdss_mdp_ctl_reset(struct mdss_mdp_ctl *ctl)
+{
+ u32 status = 1;
+ int cnt = 20;
+
+ mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_SW_RESET, 1);
+
+ /*
+ * it takes around 30us to have mdp finish resetting its ctl path
+ * poll every 50us so that reset should be completed at 1st poll
+ */
+
+ do {
+ udelay(50);
+ status = mdss_mdp_ctl_read(ctl, MDSS_MDP_REG_CTL_SW_RESET);
+ status &= 0x01;
+ pr_debug("status=%x\n", status);
+ cnt--;
+ if (cnt == 0) {
+ pr_err("timeout\n");
+ return -EAGAIN;
+ }
+ } while (status);
+
+ return 0;
+}
+
static int mdss_mdp_mixer_setup(struct mdss_mdp_ctl *ctl,
struct mdss_mdp_mixer *mixer)
{
@@ -1217,6 +1309,7 @@
u32 fg_alpha = 0, bg_alpha = 0;
int stage, secure = 0;
int screen_state;
+ int outsize = 0;
screen_state = ctl->force_screen_state;
@@ -1225,6 +1318,9 @@
pr_debug("setup mixer=%d\n", mixer->num);
+ outsize = (mixer->roi.h << 16) | mixer->roi.w;
+ mdp_mixer_write(mixer, MDSS_MDP_REG_LM_OUT_SIZE, outsize);
+
if (screen_state == MDSS_SCREEN_FORCE_BLANK) {
mixercfg = MDSS_MDP_LM_BORDER_COLOR;
goto update_mixer;
@@ -1778,6 +1874,11 @@
}
}
+ mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_READY);
+
+ if (ctl->wait_pingpong)
+ ctl->wait_pingpong(ctl, NULL);
+
/* postprocessing setup, including dspp */
mdss_mdp_pp_setup_locked(ctl);
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl->flush_bits);
@@ -1803,6 +1904,23 @@
return ret;
}
+void mdss_mdp_ctl_notifier_register(struct mdss_mdp_ctl *ctl,
+ struct notifier_block *notifier)
+{
+ blocking_notifier_chain_register(&ctl->notifier_head, notifier);
+}
+
+void mdss_mdp_ctl_notifier_unregister(struct mdss_mdp_ctl *ctl,
+ struct notifier_block *notifier)
+{
+ blocking_notifier_chain_unregister(&ctl->notifier_head, notifier);
+}
+
+int mdss_mdp_ctl_notify(struct mdss_mdp_ctl *ctl, int event)
+{
+ return blocking_notifier_call_chain(&ctl->notifier_head, event, ctl);
+}
+
int mdss_mdp_get_ctl_mixers(u32 fb_num, u32 *mixer_id)
{
int i;
@@ -1873,3 +1991,66 @@
MDSS_MDP_INTF_LAYERMIXER3);
}
}
+
+static int __mdss_mdp_mixer_handoff_helper(struct mdss_mdp_mixer *mixer,
+ struct mdss_mdp_pipe *pipe)
+{
+ int rc = 0;
+
+ if (!mixer) {
+ rc = -EINVAL;
+ goto error;
+ }
+
+ if (mixer->stage_pipe[MDSS_MDP_STAGE_UNUSED] != NULL) {
+ pr_err("More than one pipe staged on mixer num %d\n",
+ mixer->num);
+ rc = -EINVAL;
+ goto error;
+ }
+
+ pr_debug("Staging pipe num %d on mixer num %d\n",
+ pipe->num, mixer->num);
+ mixer->stage_pipe[MDSS_MDP_STAGE_UNUSED] = pipe;
+ pipe->mixer = mixer;
+ pipe->mixer_stage = MDSS_MDP_STAGE_UNUSED;
+
+error:
+ return rc;
+}
+
+/**
+ * mdss_mdp_mixer_handoff() - Stages a given pipe on the appropriate mixer
+ * @ctl: pointer to the control structure associated with the overlay device.
+ * @num: the mixer number on which the pipe needs to be staged.
+ * @pipe: pointer to the pipe to be staged.
+ *
+ * Function stages a given pipe on either the left mixer or the right mixer
+ * for the control structre based on the mixer number. If the input mixer
+ * number does not match either of the mixers then an error is returned.
+ * This function is called during overlay handoff when certain pipes are
+ * already staged by the bootloader.
+ */
+int mdss_mdp_mixer_handoff(struct mdss_mdp_ctl *ctl, u32 num,
+ struct mdss_mdp_pipe *pipe)
+{
+ int rc = 0;
+ struct mdss_mdp_mixer *mx_left = ctl->mixer_left;
+ struct mdss_mdp_mixer *mx_right = ctl->mixer_right;
+
+ /*
+ * For performance calculations, stage the handed off pipe
+ * as MDSS_MDP_STAGE_UNUSED
+ */
+ if (mx_left && (mx_left->num == num)) {
+ rc = __mdss_mdp_mixer_handoff_helper(mx_left, pipe);
+ } else if (mx_right && (mx_right->num == num)) {
+ rc = __mdss_mdp_mixer_handoff_helper(mx_right, pipe);
+ } else {
+ pr_err("pipe num %d staged on unallocated mixer num %d\n",
+ pipe->num, num);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index 213368a..c8af903 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -114,6 +114,7 @@
#define MDSS_MDP_REG_CTL_FLUSH 0x018
#define MDSS_MDP_REG_CTL_START 0x01C
#define MDSS_MDP_REG_CTL_PACK_3D 0x020
+#define MDSS_MDP_REG_CTL_SW_RESET 0x030
#define MDSS_MDP_CTL_OP_VIDEO_MODE (0 << 17)
#define MDSS_MDP_CTL_OP_CMD_MODE (1 << 17)
@@ -418,8 +419,6 @@
MDSS_MDP_MAX_INTF
};
-#define MDSS_MDP_REG_INTF_OFFSET(intf) (0x20F00 + ((intf) * 0x200))
-
#define MDSS_MDP_REG_INTF_TIMING_ENGINE_EN 0x000
#define MDSS_MDP_REG_INTF_CONFIG 0x004
#define MDSS_MDP_REG_INTF_HSYNC_CTL 0x008
@@ -498,8 +497,6 @@
#define MDSS_MDP_REG_SMP_ALLOC_W0 0x00180
#define MDSS_MDP_REG_SMP_ALLOC_R0 0x00230
-#define MDSS_MDP_SMP_MMB_BLOCKS 44
-
#define MDSS_MDP_LP_MISR_SEL 0x450
#define MDSS_MDP_LP_MISR_CTRL_MDP 0x454
#define MDSS_MDP_LP_MISR_CTRL_HDMI 0x458
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index 920c231..6056f21 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -12,9 +12,9 @@
*/
#include <linux/kernel.h>
-#include "mdss_panel.h"
+
#include "mdss_mdp.h"
-#include "mdss_dsi.h"
+#include "mdss_panel.h"
#define VSYNC_EXPIRE_TICK 4
@@ -43,6 +43,8 @@
struct mutex clk_mtx;
spinlock_t clk_lock;
struct work_struct clk_work;
+ struct work_struct pp_done_work;
+ atomic_t pp_done_cnt;
/* te config */
u8 tear_check;
@@ -50,6 +52,7 @@
u16 vporch; /* vertical porches */
u16 start_threshold;
u32 vclk_line; /* vsync clock per line */
+ struct mdss_panel_recovery recovery;
};
struct mdss_mdp_cmd_ctx mdss_mdp_cmd_ctx_list[MAX_SESSIONS];
@@ -264,6 +267,31 @@
spin_unlock(&ctx->clk_lock);
}
+static void mdss_mdp_cmd_underflow_recovery(void *data)
+{
+ struct mdss_mdp_cmd_ctx *ctx = data;
+ unsigned long flags;
+
+ if (!data) {
+ pr_err("%s: invalid ctx\n", __func__);
+ return;
+ }
+
+ if (!ctx->ctl)
+ return;
+ spin_lock_irqsave(&ctx->clk_lock, flags);
+ if (ctx->koff_cnt) {
+ mdss_mdp_ctl_reset(ctx->ctl);
+ pr_debug("%s: intf_num=%d\n", __func__,
+ ctx->ctl->intf_num);
+ ctx->koff_cnt--;
+ mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP,
+ ctx->pp_num);
+ complete_all(&ctx->pp_comp);
+ }
+ spin_unlock_irqrestore(&ctx->clk_lock, flags);
+}
+
static void mdss_mdp_cmd_pingpong_done(void *arg)
{
struct mdss_mdp_ctl *ctl = arg;
@@ -286,6 +314,8 @@
complete_all(&ctx->pp_comp);
if (ctx->koff_cnt) {
+ atomic_inc(&ctx->pp_done_cnt);
+ schedule_work(&ctx->pp_done_work);
ctx->koff_cnt--;
if (ctx->koff_cnt) {
pr_err("%s: too many kickoffs=%d!\n", __func__,
@@ -301,6 +331,16 @@
spin_unlock(&ctx->clk_lock);
}
+static void pingpong_done_work(struct work_struct *work)
+{
+ struct mdss_mdp_cmd_ctx *ctx =
+ container_of(work, typeof(*ctx), pp_done_work);
+
+ if (ctx->ctl)
+ while (atomic_add_unless(&ctx->pp_done_cnt, -1, 0))
+ mdss_mdp_ctl_notify(ctx->ctl, MDP_NOTIFY_FRAME_DONE);
+}
+
static void clk_ctrl_work(struct work_struct *work)
{
struct mdss_mdp_cmd_ctx *ctx =
@@ -374,7 +414,7 @@
return 0;
}
-int mdss_mdp_cmd_reconfigure_splash_done(struct mdss_mdp_ctl *ctl)
+int mdss_mdp_cmd_reconfigure_splash_done(struct mdss_mdp_ctl *ctl, bool handoff)
{
struct mdss_panel_data *pdata;
int ret = 0;
@@ -421,13 +461,31 @@
WARN(1, "cmd kickoff timed out (%d) ctl=%d\n",
rc, ctl->num);
rc = -EPERM;
- } else
+ mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_TIMEOUT);
+ } else {
rc = 0;
+ }
}
return rc;
}
+static int mdss_mdp_cmd_set_partial_roi(struct mdss_mdp_ctl *ctl)
+{
+ int rc = 0;
+ if (ctl->roi.w && ctl->roi.h && ctl->roi_changed &&
+ ctl->panel_data->panel_info.partial_update_enabled) {
+ ctl->panel_data->panel_info.roi_x = ctl->roi.x;
+ ctl->panel_data->panel_info.roi_y = ctl->roi.y;
+ ctl->panel_data->panel_info.roi_w = ctl->roi.w;
+ ctl->panel_data->panel_info.roi_h = ctl->roi.h;
+
+ rc = mdss_mdp_ctl_intf_event(ctl,
+ MDSS_EVENT_ENABLE_PARTIAL_UPDATE, NULL);
+ }
+ return rc;
+}
+
int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
{
struct mdss_mdp_cmd_ctx *ctx;
@@ -450,12 +508,15 @@
WARN(rc, "intf %d panel on error (%d)\n", ctl->intf_num, rc);
}
- mdss_mdp_cmd_clk_on(ctx);
+ mdss_mdp_cmd_set_partial_roi(ctl);
/*
* tx dcs command if had any
*/
- mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_DSI_CMDLIST_KOFF, NULL);
+ mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_DSI_CMDLIST_KOFF,
+ (void *)&ctx->recovery);
+
+ mdss_mdp_cmd_clk_on(ctx);
INIT_COMPLETION(ctx->pp_comp);
mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num);
@@ -481,6 +542,10 @@
pr_err("invalid ctx\n");
return -ENODEV;
}
+
+ list_for_each_entry_safe(handle, tmp, &ctx->vsync_handlers, list)
+ mdss_mdp_cmd_remove_vsync_handler(ctl, handle);
+
spin_lock_irqsave(&ctx->clk_lock, flags);
if (ctx->rdptr_enabled) {
INIT_COMPLETION(ctx->stop_comp);
@@ -498,10 +563,9 @@
mdss_mdp_cmd_clk_off(ctx);
- ctx->panel_on = 0;
+ flush_work(&ctx->pp_done_work);
- list_for_each_entry_safe(handle, tmp, &ctx->vsync_handlers, list)
- mdss_mdp_cmd_remove_vsync_handler(ctl, handle);
+ ctx->panel_on = 0;
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctx->pp_num,
NULL, NULL);
@@ -567,8 +631,13 @@
spin_lock_init(&ctx->clk_lock);
mutex_init(&ctx->clk_mtx);
INIT_WORK(&ctx->clk_work, clk_ctrl_work);
+ INIT_WORK(&ctx->pp_done_work, pingpong_done_work);
+ atomic_set(&ctx->pp_done_cnt, 0);
INIT_LIST_HEAD(&ctx->vsync_handlers);
+ ctx->recovery.fxn = mdss_mdp_cmd_underflow_recovery;
+ ctx->recovery.data = ctx;
+
pr_debug("%s: ctx=%p num=%d mixer=%d\n", __func__,
ctx, ctx->pp_num, mixer->num);
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index 8d4ca2b..7c79ceb 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -21,6 +21,7 @@
#include "mdss_fb.h"
#include "mdss_mdp.h"
+#include "mdss_panel.h"
/* wait for at least 2 vsyncs for lowest refresh rate (24hz) */
#define VSYNC_TIMEOUT_US 100000
@@ -78,11 +79,15 @@
static inline u32 mdss_mdp_video_line_count(struct mdss_mdp_ctl *ctl)
{
- struct mdss_mdp_video_ctx *ctx = ctl->priv_data;
+ struct mdss_mdp_video_ctx *ctx;
u32 line_cnt = 0;
+ if (!ctl || !ctl->priv_data)
+ goto line_count_exit;
+ ctx = ctl->priv_data;
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
line_cnt = mdp_video_read(ctx, MDSS_MDP_REG_INTF_LINE_COUNT);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+line_count_exit:
return line_cnt;
}
@@ -326,6 +331,7 @@
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num,
NULL, NULL);
+ mdss_mdp_ctl_reset(ctl);
ctx->ref_cnt--;
ctl->priv_data = NULL;
@@ -423,6 +429,9 @@
} else {
rc = 0;
}
+
+ mdss_mdp_ctl_notify(ctl,
+ rc ? MDP_NOTIFY_FRAME_TIMEOUT : MDP_NOTIFY_FRAME_DONE);
}
if (ctx->wait_pending) {
@@ -578,46 +587,52 @@
return 0;
}
-int mdss_mdp_video_reconfigure_splash_done(struct mdss_mdp_ctl *ctl)
+int mdss_mdp_video_reconfigure_splash_done(struct mdss_mdp_ctl *ctl,
+ bool handoff)
{
- struct mdss_panel_data *pdata;
- int ret = 0, off;
- int mdss_mdp_rev = MDSS_MDP_REG_READ(MDSS_MDP_REG_HW_VERSION);
- int mdss_v2_intf_off = 0;
+ struct mdss_panel_data *pdata = ctl->panel_data;
+ int i, ret = 0;
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(ctl->mfd);
+ struct mdss_mdp_video_ctx *ctx;
+ struct mdss_data_type *mdata = ctl->mdata;
- off = 0;
-
- pdata = ctl->panel_data;
-
- pdata->panel_info.cont_splash_enabled = 0;
-
- ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CONT_SPLASH_BEGIN,
- NULL);
- if (ret) {
- pr_err("%s: Failed to handle 'CONT_SPLASH_BEGIN' event\n",
- __func__);
- return ret;
+ i = ctl->intf_num - MDSS_MDP_INTF0;
+ if (i < mdata->nintf) {
+ ctx = ((struct mdss_mdp_video_ctx *) mdata->video_intf) + i;
+ pr_debug("video Intf #%d base=%p", ctx->intf_num, ctx->base);
+ } else {
+ pr_err("Invalid intf number: %d\n", ctl->intf_num);
+ ret = -EINVAL;
+ goto error;
}
- mdss_mdp_ctl_write(ctl, 0, MDSS_MDP_LM_BORDER_COLOR);
- off = MDSS_MDP_REG_INTF_OFFSET(ctl->intf_num);
+ if (!handoff) {
+ ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CONT_SPLASH_BEGIN,
+ NULL);
+ if (ret) {
+ pr_err("%s: Failed to handle 'CONT_SPLASH_BEGIN' event\n"
+ , __func__);
+ return ret;
+ }
- if (mdss_mdp_rev >= MDSS_MDP_HW_REV_102)
- mdss_v2_intf_off = 0xEC00;
+ mdss_mdp_ctl_write(ctl, 0, MDSS_MDP_LM_BORDER_COLOR);
+ mdp_video_write(ctx, MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 0);
- MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_INTF_TIMING_ENGINE_EN -
- mdss_v2_intf_off, 0);
- /* wait for 1 VSYNC for the pipe to be unstaged */
- msleep(20);
+ /* wait for 1 VSYNC for the pipe to be unstaged */
+ msleep(20);
+
+ ret = mdss_mdp_ctl_intf_event(ctl,
+ MDSS_EVENT_CONT_SPLASH_FINISH, NULL);
+ }
+
+error:
+ pdata->panel_info.cont_splash_enabled = 0;
/* Give back the reserved memory to the system */
memblock_free(mdp5_data->splash_mem_addr, mdp5_data->splash_mem_size);
free_bootmem_late(mdp5_data->splash_mem_addr,
mdp5_data->splash_mem_size);
- ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CONT_SPLASH_FINISH,
- NULL);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
return ret;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index 2b07428..3929501 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -13,9 +13,9 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
-#include "mdss_fb.h"
#include "mdss_mdp.h"
#include "mdss_mdp_rotator.h"
+#include "mdss_panel.h"
enum mdss_mdp_writeback_type {
MDSS_MDP_WRITEBACK_TYPE_ROTATOR,
@@ -283,9 +283,9 @@
ctx->rot90 = !!(rot->flags & MDP_ROT_90);
if (ctx->bwc_mode || ctx->rot90)
- format = mdss_mdp_get_rotator_dst_format(rot->format);
+ format = mdss_mdp_get_rotator_dst_format(rot->format, 1);
else
- format = rot->format;
+ format = mdss_mdp_get_rotator_dst_format(rot->format, 0);
if (ctx->rot90) {
ctx->opmode |= BIT(5); /* ROT 90 */
@@ -421,10 +421,12 @@
NULL, NULL);
if (rc == 0) {
+ mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_TIMEOUT);
rc = -ENODEV;
WARN(1, "writeback kickoff timed out (%d) ctl=%d\n",
rc, ctl->num);
} else {
+ mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_DONE);
rc = 0;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 5f0d646..c565d98 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -27,7 +27,7 @@
#include <mach/iommu_domains.h>
#include <mach/event_timer.h>
#include <mach/msm_bus.h>
-
+#include <mach/scm.h>
#include "mdss.h"
#include "mdss_debug.h"
#include "mdss_fb.h"
@@ -42,12 +42,38 @@
#define PP_CLK_CFG_OFF 0
#define PP_CLK_CFG_ON 1
+#define MEM_PROTECT_SD_CTRL 0xF
+
+struct sd_ctrl_req {
+ unsigned int enable;
+} __attribute__ ((__packed__));
+
static atomic_t ov_active_panels = ATOMIC_INIT(0);
static int mdss_mdp_overlay_free_fb_pipe(struct msm_fb_data_type *mfd);
static int mdss_mdp_overlay_fb_parse_dt(struct msm_fb_data_type *mfd);
static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd);
static int mdss_mdp_overlay_splash_parse_dt(struct msm_fb_data_type *mfd);
+static int mdss_mdp_overlay_sd_ctrl(struct msm_fb_data_type *mfd,
+ unsigned int enable)
+{
+ struct sd_ctrl_req request;
+ unsigned int resp = -1;
+ int ret = 0;
+ pr_debug("sd_ctrl %u\n", enable);
+
+ request.enable = enable;
+
+ ret = scm_call(SCM_SVC_MP, MEM_PROTECT_SD_CTRL,
+ &request, sizeof(request), &resp, sizeof(resp));
+ pr_debug("scm_call MEM_PROTECT_SD_CTRL(%u): ret=%d, resp=%x",
+ enable, ret, resp);
+ if (ret)
+ return ret;
+
+ return resp;
+}
+
static int mdss_mdp_overlay_get(struct msm_fb_data_type *mfd,
struct mdp_overlay *req)
{
@@ -66,9 +92,9 @@
return 0;
}
-static int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd,
- struct mdp_overlay *req,
- struct mdss_mdp_format_params *fmt)
+int mdss_mdp_overlay_req_check(struct msm_fb_data_type *mfd,
+ struct mdp_overlay *req,
+ struct mdss_mdp_format_params *fmt)
{
u32 xres, yres;
u32 min_src_size, min_dst_size;
@@ -224,84 +250,6 @@
return 0;
}
-static int mdss_mdp_overlay_rotator_setup(struct msm_fb_data_type *mfd,
- struct mdp_overlay *req)
-{
- struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
- struct mdss_mdp_rotator_session *rot;
- struct mdss_mdp_format_params *fmt;
- int ret = 0;
- u32 bwc_enabled;
-
- pr_debug("rot ctl=%u req id=%x\n", mdp5_data->ctl->num, req->id);
-
- fmt = mdss_mdp_get_format_params(req->src.format);
- if (!fmt) {
- pr_err("invalid rot format %d\n", req->src.format);
- return -EINVAL;
- }
-
- ret = mdss_mdp_overlay_req_check(mfd, req, fmt);
- if (ret)
- return ret;
-
- if (req->id == MSMFB_NEW_REQUEST) {
- rot = mdss_mdp_rotator_session_alloc();
- rot->pid = current->tgid;
- list_add(&rot->list, &mdp5_data->rot_proc_list);
-
- if (!rot) {
- pr_err("unable to allocate rotator session\n");
- return -ENOMEM;
- }
- } else if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
- rot = mdss_mdp_rotator_session_get(req->id);
-
- if (!rot) {
- pr_err("rotator session=%x not found\n", req->id);
- return -ENODEV;
- }
- } else {
- pr_err("invalid rotator session id=%x\n", req->id);
- return -EINVAL;
- }
-
- /* keep only flags of interest to rotator */
- rot->flags = req->flags & (MDP_ROT_90 | MDP_FLIP_LR | MDP_FLIP_UD |
- MDP_SECURE_OVERLAY_SESSION);
-
- bwc_enabled = req->flags & MDP_BWC_EN;
- if (bwc_enabled && !mdp5_data->mdata->has_bwc) {
- pr_err("BWC is not supported in MDP version %x\n",
- mdp5_data->mdata->mdp_rev);
- rot->bwc_mode = 0;
- } else {
- rot->bwc_mode = bwc_enabled ? 1 : 0;
- }
- rot->format = fmt->format;
- rot->img_width = req->src.width;
- rot->img_height = req->src.height;
- rot->src_rect.x = req->src_rect.x;
- rot->src_rect.y = req->src_rect.y;
- rot->src_rect.w = req->src_rect.w;
- rot->src_rect.h = req->src_rect.h;
-
- if (req->flags & MDP_DEINTERLACE) {
- rot->flags |= MDP_DEINTERLACE;
- rot->src_rect.h /= 2;
- }
-
- ret = mdss_mdp_rotator_setup(rot);
- if (ret == 0) {
- req->id = rot->session_id;
- } else {
- pr_err("Unable to setup rotator session\n");
- mdss_mdp_rotator_release(rot);
- }
-
- return ret;
-}
-
static int __mdp_pipe_tune_perf(struct mdss_mdp_pipe *pipe)
{
struct mdss_data_type *mdata = pipe->mixer->ctl->mdata;
@@ -389,7 +337,7 @@
if (req->flags & (MDP_SOURCE_ROTATED_90 | MDP_BWC_EN))
req->src.format =
- mdss_mdp_get_rotator_dst_format(req->src.format);
+ mdss_mdp_get_rotator_dst_format(req->src.format, 1);
fmt = mdss_mdp_get_format_params(req->src.format);
if (!fmt) {
@@ -547,12 +495,11 @@
pipe->pp_cfg.hist_cfg.frame_cnt;
hist.bit_mask = pipe->pp_cfg.hist_cfg.bit_mask;
hist.num_bins = pipe->pp_cfg.hist_cfg.num_bins;
- mdss_mdp_histogram_start(pipe->mixer->ctl,
- &hist);
+ mdss_mdp_histogram_start(&hist);
} else if (pipe->pp_cfg.hist_cfg.ops &
MDP_PP_OPS_DISABLE) {
- mdss_mdp_histogram_stop(pipe->mixer->ctl,
- pipe->pp_cfg.hist_cfg.block);
+ mdss_mdp_histogram_stop(
+ pipe->pp_cfg.hist_cfg.block);
}
}
len = pipe->pp_cfg.hist_lut_cfg.len;
@@ -645,7 +592,7 @@
}
if (req->flags & MDSS_MDP_ROT_ONLY) {
- ret = mdss_mdp_overlay_rotator_setup(mfd, req);
+ ret = mdss_mdp_rotator_setup(mfd, req);
} else if (req->src.format == MDP_RGB_BORDERFILL) {
req->id = BORDERFILL_NDX;
} else {
@@ -664,7 +611,7 @@
return ret;
}
-static inline int mdss_mdp_overlay_get_buf(struct msm_fb_data_type *mfd,
+int mdss_mdp_overlay_get_buf(struct msm_fb_data_type *mfd,
struct mdss_mdp_data *data,
struct msmfb_data *planes,
int num_planes,
@@ -694,7 +641,7 @@
return rc;
}
-static inline int mdss_mdp_overlay_free_buf(struct mdss_mdp_data *data)
+int mdss_mdp_overlay_free_buf(struct mdss_mdp_data *data)
{
int i;
for (i = 0; i < data->num_planes && data->p[i].len; i++)
@@ -773,13 +720,64 @@
mdss_mdp_pipe_destroy(pipe);
}
+static void __mdss_mdp_handoff_cleanup_pipes(struct msm_fb_data_type *mfd,
+ u32 type)
+{
+ u32 i, npipes;
+ struct mdss_mdp_pipe *pipes;
+ struct mdss_mdp_pipe *pipe;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ struct mdss_data_type *mdata = mfd_to_mdata(mfd);
+
+ switch (type) {
+ case MDSS_MDP_PIPE_TYPE_VIG:
+ pipes = mdata->vig_pipes;
+ npipes = mdata->nvig_pipes;
+ break;
+ case MDSS_MDP_PIPE_TYPE_RGB:
+ pipes = mdata->rgb_pipes;
+ npipes = mdata->nrgb_pipes;
+ break;
+ case MDSS_MDP_PIPE_TYPE_DMA:
+ pipes = mdata->dma_pipes;
+ npipes = mdata->ndma_pipes;
+ break;
+ default:
+ return;
+ }
+
+ for (i = 0; i < npipes; i++) {
+ pipe = &pipes[i];
+ if (pipe->is_handed_off) {
+ pr_debug("Unmapping handed off pipe %d\n", pipe->num);
+ list_add(&pipe->cleanup_list,
+ &mdp5_data->pipes_cleanup);
+ mdss_mdp_mixer_pipe_unstage(pipe);
+ pipe->is_handed_off = false;
+ }
+ }
+}
+
+/**
+ * mdss_mdp_overlay_start() - Programs the MDP control data path to hardware
+ * @mfd: Msm frame buffer structure associated with fb device.
+ *
+ * Program the MDP hardware with the control settings for the framebuffer
+ * device. In addition to this, this function also handles the transition
+ * from the the splash screen to the android boot animation when the
+ * continuous splash screen feature is enabled.
+ */
static int mdss_mdp_overlay_start(struct msm_fb_data_type *mfd)
{
int rc;
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ struct mdss_mdp_ctl *ctl = mdp5_data->ctl;
- if (mdp5_data->ctl->power_on)
+ if (ctl->power_on) {
+ if (!mdp5_data->mdata->batfet)
+ mdss_mdp_batfet_ctrl(mdp5_data->mdata, true);
return 0;
+ }
pr_debug("starting fb%d overlay\n", mfd->index);
@@ -789,24 +787,84 @@
return rc;
}
- if (mfd->panel_info->cont_splash_enabled) {
- mdss_mdp_ctl_splash_finish(mdp5_data->ctl);
- mdss_mdp_footswitch_ctrl_splash(0);
- }
-
+ /*
+ * We need to do hw init before any hw programming.
+ * Also, hw init involves programming the VBIF registers which
+ * should be done only after attaching IOMMU which in turn would call
+ * in to TZ to restore security configs on the VBIF registers.
+ * This is not needed when continuous splash screen is enabled since
+ * we would have called in to TZ to restore security configs from LK.
+ */
if (!is_mdss_iommu_attached()) {
- mdss_iommu_attach(mdss_res);
+ if (!mfd->panel_info->cont_splash_enabled)
+ mdss_iommu_attach(mdss_res);
mdss_hw_init(mdss_res);
}
- rc = mdss_mdp_ctl_start(mdp5_data->ctl);
+ rc = mdss_mdp_ctl_start(ctl);
if (rc == 0) {
atomic_inc(&ov_active_panels);
- } else {
- pr_err("overlay start failed.\n");
- mdss_mdp_ctl_destroy(mdp5_data->ctl);
- mdp5_data->ctl = NULL;
+ mdss_mdp_ctl_notifier_register(mdp5_data->ctl,
+ &mfd->mdp_sync_pt_data.notifier);
+ } else {
+ pr_err("mdp ctl start failed.\n");
+ goto error;
+ }
+
+ if (mfd->panel_info->cont_splash_enabled) {
+ if (mdp5_data->handoff) {
+ /*
+ * Set up border-fill on the handed off pipes.
+ * This is needed to ensure that there are no memory
+ * accesses prior to attaching iommu during continuous
+ * splash screen case. However, for command mode
+ * displays, this is not necessary since the panels can
+ * refresh from their internal memory if no data is sent
+ * out on the dsi lanes.
+ */
+ if (ctl && ctl->is_video_mode) {
+ rc = mdss_mdp_display_commit(ctl, NULL);
+ if (!IS_ERR_VALUE(rc)) {
+ mdss_mdp_display_wait4comp(ctl);
+ } else {
+ /*
+ * Since border-fill setup failed, we
+ * need to ensure that we turn off the
+ * MDP timing generator before attaching
+ * iommu
+ */
+ pr_err("failed to set BF at handoff\n");
+ mdp5_data->handoff = false;
+ rc = 0;
+ }
+ }
+
+ /* Add all the handed off pipes to the cleanup list */
+ __mdss_mdp_handoff_cleanup_pipes(mfd,
+ MDSS_MDP_PIPE_TYPE_RGB);
+ __mdss_mdp_handoff_cleanup_pipes(mfd,
+ MDSS_MDP_PIPE_TYPE_VIG);
+ __mdss_mdp_handoff_cleanup_pipes(mfd,
+ MDSS_MDP_PIPE_TYPE_DMA);
+ }
+ rc = mdss_mdp_ctl_splash_finish(ctl, mdp5_data->handoff);
+ /*
+ * Remove the vote for footswitch even if above function
+ * returned error
+ */
+ mdss_mdp_footswitch_ctrl_splash(0);
+ if (rc)
+ goto error;
+
+ if (!is_mdss_iommu_attached())
+ mdss_iommu_attach(mdss_res);
+ }
+
+error:
+ if (rc) {
+ mdss_mdp_ctl_destroy(ctl);
+ mdp5_data->ctl = NULL;
pm_runtime_put(&mfd->pdev->dev);
}
@@ -826,13 +884,15 @@
activate_event_timer(mdp5_data->cpu_pm_hdl, wakeup_time);
}
-int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd)
+int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd,
+ struct mdp_display_commit *data)
{
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
struct mdss_mdp_pipe *pipe;
struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
struct mdss_mdp_ctl *tmp;
- int ret;
+ int ret = 0;
+ int sd_in_pipe = 0;
if (ctl->shared_lock)
mutex_lock(ctl->shared_lock);
@@ -840,18 +900,44 @@
mutex_lock(&mdp5_data->ov_lock);
mutex_lock(&mfd->lock);
- ret = mdss_mdp_display_wait4pingpong(mdp5_data->ctl);
- if (ret) {
- mutex_unlock(&mfd->lock);
- mutex_unlock(&mdp5_data->ov_lock);
- if (ctl->shared_lock)
- mutex_unlock(ctl->shared_lock);
- return ret;
+ /*
+ * check if there is a secure display session
+ */
+ list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) {
+ if (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION) {
+ sd_in_pipe |= 1;
+ pr_debug("Secure pipe: %u : %08X\n",
+ pipe->num, pipe->flags);
+ }
}
+ /*
+ * If there is no secure display session and sd_enabled, disable the
+ * secure display session
+ */
+ if (!sd_in_pipe && mdp5_data->sd_enabled) {
+ if (0 == mdss_mdp_overlay_sd_ctrl(mfd, 0))
+ mdp5_data->sd_enabled = 0;
+ }
+
+ mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_BEGIN);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+ if (data)
+ mdss_mdp_set_roi(ctl, data);
list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) {
struct mdss_mdp_data *buf;
/*
+ * When secure display is enabled, if there is a non secure
+ * display pipe, skip that
+ */
+ if ((mdp5_data->sd_enabled) &&
+ !(pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION)) {
+ pr_warn("Non secure pipe during secure display: %u: %08X, skip\n",
+ pipe->num, pipe->flags);
+ continue;
+ }
+ /*
* When external is connected and no dedicated wfd is present,
* reprogram DMA pipe before kickoff to clear out any previous
* block mode configuration.
@@ -917,9 +1003,21 @@
ret = mdss_mdp_display_wait4comp(mdp5_data->ctl);
+ if (ret == 0) {
+ mutex_lock(&mfd->lock);
+ if (!mdp5_data->sd_enabled && (sd_in_pipe == 1)) {
+ ret = mdss_mdp_overlay_sd_ctrl(mfd, 1);
+ if (ret == 0)
+ mdp5_data->sd_enabled = 1;
+ }
+ mutex_unlock(&mfd->lock);
+ }
+
mdss_fb_update_notify_update(mfd);
commit_fail:
mdss_mdp_overlay_cleanup(mfd);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+ mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_FLUSHED);
mutex_unlock(&mdp5_data->ov_lock);
if (ctl->shared_lock)
@@ -991,17 +1089,7 @@
pr_debug("unset ndx=%x\n", ndx);
if (ndx & MDSS_MDP_ROT_SESSION_MASK) {
- struct mdss_mdp_rotator_session *rot;
- rot = mdss_mdp_rotator_session_get(ndx);
- if (rot) {
- mdss_mdp_overlay_free_buf(&rot->src_buf);
- mdss_mdp_overlay_free_buf(&rot->dst_buf);
-
- rot->pid = 0;
- if (!list_empty(&rot->list))
- list_del_init(&rot->list);
- ret = mdss_mdp_rotator_release(rot);
- }
+ ret = mdss_mdp_rotator_unset(ndx);
} else {
ret = mdss_mdp_overlay_release(mfd, ndx);
}
@@ -1033,7 +1121,7 @@
mutex_lock(&mdp5_data->ov_lock);
mutex_lock(&mfd->lock);
list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) {
- if (pipe->pid == pid) {
+ if (!mfd->ref_cnt || (pipe->pid == pid)) {
unset_ndx |= pipe->ndx;
cnt++;
}
@@ -1054,7 +1142,7 @@
mutex_unlock(&mdp5_data->ov_lock);
if (cnt)
- mfd->mdp.kickoff_fnc(mfd);
+ mfd->mdp.kickoff_fnc(mfd, NULL);
list_for_each_entry_safe(rot, tmp, &mdp5_data->rot_proc_list, list) {
if (rot->pid == pid) {
@@ -1075,51 +1163,13 @@
if (!mfd)
return -ENODEV;
- ret = mfd->mdp.kickoff_fnc(mfd);
+ ret = mfd->mdp.kickoff_fnc(mfd, NULL);
if (!ret)
pr_err("error displaying\n");
return ret;
}
-static int mdss_mdp_overlay_rotate(struct msm_fb_data_type *mfd,
- struct msmfb_overlay_data *req)
-{
- struct mdss_mdp_rotator_session *rot;
- int ret;
- u32 flgs;
-
- rot = mdss_mdp_rotator_session_get(req->id);
- if (!rot) {
- pr_err("invalid session id=%x\n", req->id);
- return -ENOENT;
- }
-
- flgs = rot->flags & MDP_SECURE_OVERLAY_SESSION;
-
- mdss_mdp_overlay_free_buf(&rot->src_buf);
- ret = mdss_mdp_overlay_get_buf(mfd, &rot->src_buf, &req->data, 1, flgs);
- if (ret) {
- pr_err("src_data pmem error\n");
- return ret;
- }
-
- mdss_mdp_overlay_free_buf(&rot->dst_buf);
- ret = mdss_mdp_overlay_get_buf(mfd, &rot->dst_buf,
- &req->dst_data, 1, flgs);
- if (ret) {
- pr_err("dst_data pmem error\n");
- goto dst_buf_fail;
- }
-
- ret = mdss_mdp_rotator_queue(rot, &rot->src_buf, &rot->dst_buf);
- if (ret)
- pr_err("rotator queue error session id=%x\n", req->id);
-
-dst_buf_fail:
- return ret;
-}
-
static int mdss_mdp_overlay_queue(struct msm_fb_data_type *mfd,
struct msmfb_overlay_data *req)
{
@@ -1138,6 +1188,7 @@
pr_debug("ov queue pnum=%d\n", pipe->num);
flags = (pipe->flags & MDP_SECURE_OVERLAY_SESSION);
+ flags |= (pipe->flags & MDP_SECURE_DISPLAY_OVERLAY_SESSION);
src_data = &pipe->back_buf;
if (src_data->num_planes) {
@@ -1214,7 +1265,7 @@
if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
mdss_mdp_overlay_force_dma_cleanup(mfd_to_mdata(mfd));
- ret = mdss_mdp_overlay_rotate(mfd, req);
+ ret = mdss_mdp_rotator_play(mfd, req);
} else if (req->id == BORDERFILL_NDX) {
pr_debug("borderfill enable\n");
mdp5_data->borderfill_enable = true;
@@ -1338,7 +1389,7 @@
if (!fbi->fix.smem_start || fbi->fix.smem_len == 0 ||
mdp5_data->borderfill_enable) {
- mfd->mdp.kickoff_fnc(mfd);
+ mfd->mdp.kickoff_fnc(mfd, NULL);
return;
}
@@ -1412,7 +1463,7 @@
if ((fbi->var.activate & FB_ACTIVATE_VBL) ||
(fbi->var.activate & FB_ACTIVATE_FORCE))
- mfd->mdp.kickoff_fnc(mfd);
+ mfd->mdp.kickoff_fnc(mfd, NULL);
return;
@@ -1812,7 +1863,6 @@
struct msmfb_mdp_pp mdp_pp;
u32 copyback = 0;
u32 copy_from_kernel = 0;
- struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
ret = copy_from_user(&mdp_pp, argp, sizeof(mdp_pp));
if (ret)
@@ -1827,14 +1877,12 @@
switch (mdp_pp.op) {
case mdp_op_pa_cfg:
- ret = mdss_mdp_pa_config(mdp5_data->ctl,
- &mdp_pp.data.pa_cfg_data,
+ ret = mdss_mdp_pa_config(&mdp_pp.data.pa_cfg_data,
©back);
break;
case mdp_op_pcc_cfg:
- ret = mdss_mdp_pcc_config(mdp5_data->ctl,
- &mdp_pp.data.pcc_cfg_data,
+ ret = mdss_mdp_pcc_config(&mdp_pp.data.pcc_cfg_data,
©back);
break;
@@ -1842,7 +1890,6 @@
switch (mdp_pp.data.lut_cfg_data.lut_type) {
case mdp_lut_igc:
ret = mdss_mdp_igc_lut_config(
- mdp5_data->ctl,
(struct mdp_igc_lut_data *)
&mdp_pp.data.lut_cfg_data.data,
©back, copy_from_kernel);
@@ -1850,14 +1897,12 @@
case mdp_lut_pgc:
ret = mdss_mdp_argc_config(
- mdp5_data->ctl,
&mdp_pp.data.lut_cfg_data.data.pgc_lut_data,
©back);
break;
case mdp_lut_hist:
ret = mdss_mdp_hist_lut_config(
- mdp5_data->ctl,
(struct mdp_hist_lut_data *)
&mdp_pp.data.lut_cfg_data.data, ©back);
break;
@@ -1869,13 +1914,11 @@
break;
case mdp_op_dither_cfg:
ret = mdss_mdp_dither_config(
- mdp5_data->ctl,
&mdp_pp.data.dither_cfg_data,
©back);
break;
case mdp_op_gamut_cfg:
ret = mdss_mdp_gamut_config(
- mdp5_data->ctl,
&mdp_pp.data.gamut_cfg_data,
©back);
break;
@@ -1926,7 +1969,6 @@
struct mdp_histogram_data hist;
struct mdp_histogram_start_req hist_req;
u32 block;
- struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
u32 pp_bus_handle;
static int req = -1;
@@ -1945,7 +1987,7 @@
if (ret)
return ret;
- ret = mdss_mdp_histogram_start(mdp5_data->ctl, &hist_req);
+ ret = mdss_mdp_histogram_start(&hist_req);
break;
case MSMFB_HISTOGRAM_STOP:
@@ -1953,7 +1995,7 @@
if (ret)
return ret;
- ret = mdss_mdp_histogram_stop(mdp5_data->ctl, block);
+ ret = mdss_mdp_histogram_stop(block);
if (ret)
return ret;
@@ -1975,7 +2017,7 @@
if (ret)
return ret;
- ret = mdss_mdp_hist_collect(mdp5_data->ctl, &hist);
+ ret = mdss_mdp_hist_collect(&hist);
if (!ret)
ret = copy_to_user(argp, &hist, sizeof(hist));
break;
@@ -2159,9 +2201,8 @@
}
break;
case MSMFB_OVERLAY_COMMIT:
- mdss_fb_wait_for_fence(mfd);
- ret = mfd->mdp.kickoff_fnc(mfd);
- mdss_fb_signal_timeline(mfd);
+ mdss_fb_wait_for_fence(&(mfd->mdp_sync_pt_data));
+ ret = mfd->mdp.kickoff_fnc(mfd, NULL);
break;
case MSMFB_METADATA_SET:
ret = copy_from_user(&metadata, argp, sizeof(metadata));
@@ -2186,10 +2227,66 @@
return ret;
}
+/**
+ * __mdss_mdp_overlay_ctl_init - Helper function to intialize control structure
+ * @mfd: msm frame buffer data structure associated with the fb device.
+ *
+ * Helper function that allocates and initializes the mdp control structure
+ * for a frame buffer device. Whenver applicable, this function will also setup
+ * the control for the split display path as well.
+ *
+ * Return: pointer to the newly allocated control structure.
+ */
+static struct mdss_mdp_ctl *__mdss_mdp_overlay_ctl_init(
+ struct msm_fb_data_type *mfd)
+{
+ int rc = 0;
+ struct mdss_mdp_ctl *ctl;
+ struct mdss_panel_data *pdata;
+
+ if (!mfd)
+ return ERR_PTR(-EINVAL);
+
+ pdata = dev_get_platdata(&mfd->pdev->dev);
+ if (!pdata) {
+ pr_err("no panel connected for fb%d\n", mfd->index);
+ rc = -ENODEV;
+ goto error;
+ }
+
+ ctl = mdss_mdp_ctl_init(pdata, mfd);
+ if (IS_ERR_OR_NULL(ctl)) {
+ pr_err("Unable to initialize ctl for fb%d\n",
+ mfd->index);
+ rc = PTR_ERR(ctl);
+ goto error;
+ }
+ ctl->vsync_handler.vsync_handler =
+ mdss_mdp_overlay_handle_vsync;
+ ctl->vsync_handler.cmd_post_flush = false;
+
+ if (mfd->split_display && pdata->next) {
+ /* enable split display */
+ rc = mdss_mdp_ctl_split_display_setup(ctl, pdata->next);
+ if (rc) {
+ mdss_mdp_ctl_destroy(ctl);
+ goto error;
+ }
+ }
+
+error:
+ if (rc)
+ return ERR_PTR(rc);
+ else
+ return ctl;
+}
+
static int mdss_mdp_overlay_on(struct msm_fb_data_type *mfd)
{
int rc;
struct mdss_overlay_private *mdp5_data;
+ struct mdss_mdp_ctl *ctl = NULL;
+
if (!mfd)
return -ENODEV;
@@ -2201,33 +2298,9 @@
return -EINVAL;
if (!mdp5_data->ctl) {
- struct mdss_mdp_ctl *ctl;
- struct mdss_panel_data *pdata;
-
- pdata = dev_get_platdata(&mfd->pdev->dev);
- if (!pdata) {
- pr_err("no panel connected for fb%d\n", mfd->index);
- return -ENODEV;
- }
-
- ctl = mdss_mdp_ctl_init(pdata, mfd);
- if (IS_ERR_OR_NULL(ctl)) {
- pr_err("Unable to initialize ctl for fb%d\n",
- mfd->index);
+ ctl = __mdss_mdp_overlay_ctl_init(mfd);
+ if (IS_ERR_OR_NULL(ctl))
return PTR_ERR(ctl);
- }
- ctl->vsync_handler.vsync_handler =
- mdss_mdp_overlay_handle_vsync;
- ctl->vsync_handler.cmd_post_flush = false;
-
- if (mfd->split_display && pdata->next) {
- /* enable split display */
- rc = mdss_mdp_ctl_split_display_setup(ctl, pdata->next);
- if (rc) {
- mdss_mdp_ctl_destroy(ctl);
- return rc;
- }
- }
mdp5_data->ctl = ctl;
}
@@ -2236,7 +2309,7 @@
(mfd->panel_info->type != WRITEBACK_PANEL)) {
rc = mdss_mdp_overlay_start(mfd);
if (!IS_ERR_VALUE(rc))
- rc = mdss_mdp_overlay_kickoff(mfd);
+ rc = mdss_mdp_overlay_kickoff(mfd, NULL);
} else {
rc = mdss_mdp_ctl_setup(mdp5_data->ctl);
if (rc)
@@ -2289,12 +2362,14 @@
if (need_cleanup) {
pr_debug("cleaning up pipes on fb%d\n", mfd->index);
- mdss_mdp_overlay_kickoff(mfd);
+ mdss_mdp_overlay_kickoff(mfd, NULL);
}
rc = mdss_mdp_ctl_stop(mdp5_data->ctl);
if (rc == 0) {
__mdss_mdp_overlay_free_list_purge(mfd);
+ mdss_mdp_ctl_notifier_unregister(mdp5_data->ctl,
+ &mfd->mdp_sync_pt_data.notifier);
if (!mfd->ref_cnt) {
mdp5_data->borderfill_enable = false;
@@ -2326,6 +2401,96 @@
return 0;
}
+/**
+ * mdss_mdp_overlay_handoff() - Read MDP registers to handoff an active ctl path
+ * @mfd: Msm frame buffer structure associated with the fb device.
+ *
+ * This function populates the MDP software structures with the current state of
+ * the MDP hardware to handoff any active control path for the framebuffer
+ * device. This is needed to identify any ctl, mixers and pipes being set up by
+ * the bootloader to display the splash screen when the continuous splash screen
+ * feature is enabled in kernel.
+ */
+static int mdss_mdp_overlay_handoff(struct msm_fb_data_type *mfd)
+{
+ int rc = 0;
+ struct mdss_data_type *mdata = mfd_to_mdata(mfd);
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ int i, j;
+ u32 reg;
+ struct mdss_mdp_pipe *pipe = NULL;
+ struct mdss_mdp_ctl *ctl = NULL;
+
+ if (!mdp5_data->ctl) {
+ ctl = __mdss_mdp_overlay_ctl_init(mfd);
+ if (IS_ERR_OR_NULL(ctl)) {
+ rc = PTR_ERR(ctl);
+ goto error;
+ }
+ mdp5_data->ctl = ctl;
+ }
+
+ rc = mdss_mdp_ctl_setup(ctl);
+ if (rc)
+ goto error;
+
+ ctl->clk_rate = mdss_mdp_get_clk_rate(MDSS_CLK_MDP_SRC);
+ pr_debug("Set the ctl clock rate to %d Hz\n", ctl->clk_rate);
+
+ for (i = 0; i < mdata->nmixers_intf; i++) {
+ reg = mdss_mdp_ctl_read(ctl, MDSS_MDP_REG_CTL_LAYER(i));
+ pr_debug("for lm%d reg = 0x%09x\n", i, reg);
+ for (j = MDSS_MDP_SSPP_VIG0; j < MDSS_MDP_MAX_SSPP; j++) {
+ u32 cfg = j * 3;
+ if ((j == MDSS_MDP_SSPP_VIG3) ||
+ (j == MDSS_MDP_SSPP_RGB3)) {
+ /* Add 2 to account for Cursor & Border bits */
+ cfg += 2;
+ }
+ if (reg & (0x7 << cfg)) {
+ pr_debug("Pipe %d staged\n", j);
+ pipe = mdss_mdp_pipe_search(mdata, BIT(j));
+ if (!pipe) {
+ pr_warn("Invalid pipe %d staged\n", j);
+ continue;
+ }
+
+ rc = mdss_mdp_pipe_handoff(pipe);
+ if (rc) {
+ pr_err("Failed to handoff pipe num %d\n"
+ , pipe->num);
+ goto error;
+ }
+
+ rc = mdss_mdp_mixer_handoff(ctl, i, pipe);
+ if (rc) {
+ pr_err("failed to handoff mixer num %d\n"
+ , i);
+ goto error;
+ }
+ }
+ }
+ }
+
+ rc = mdss_mdp_smp_handoff(mdata);
+ if (rc)
+ pr_err("Failed to handoff smps\n");
+
+ mdp5_data->handoff = true;
+
+error:
+ if (rc && ctl) {
+ __mdss_mdp_handoff_cleanup_pipes(mfd, MDSS_MDP_PIPE_TYPE_RGB);
+ __mdss_mdp_handoff_cleanup_pipes(mfd, MDSS_MDP_PIPE_TYPE_VIG);
+ __mdss_mdp_handoff_cleanup_pipes(mfd, MDSS_MDP_PIPE_TYPE_DMA);
+ mdss_mdp_ctl_destroy(ctl);
+ mdp5_data->ctl = NULL;
+ mdp5_data->handoff = false;
+ }
+
+ return rc;
+}
+
int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd)
{
struct device *dev = mfd->fbi->dev;
@@ -2342,6 +2507,7 @@
mdp5_interface->ioctl_handler = mdss_mdp_overlay_ioctl_handler;
mdp5_interface->panel_register_done = mdss_panel_register_done;
mdp5_interface->kickoff_fnc = mdss_mdp_overlay_kickoff;
+ mdp5_interface->get_sync_fnc = mdss_mdp_rotator_sync_pt_get;
mdp5_data = kmalloc(sizeof(struct mdss_overlay_private), GFP_KERNEL);
if (!mdp5_data) {
@@ -2391,6 +2557,7 @@
goto init_fail;
}
}
+ mfd->mdp_sync_pt_data.async_wait_fences = true;
pm_runtime_set_suspended(&mfd->pdev->dev);
pm_runtime_enable(&mfd->pdev->dev);
@@ -2402,6 +2569,21 @@
if (!mdp5_data->cpu_pm_hdl)
pr_warn("%s: unable to add event timer\n", __func__);
+ if (mfd->panel_info->cont_splash_enabled) {
+ rc = mdss_mdp_overlay_handoff(mfd);
+ if (rc) {
+ /*
+ * Even though handoff failed, it is not fatal.
+ * MDP can continue, just that we would have a longer
+ * delay in transitioning from splash screen to boot
+ * animation
+ */
+ pr_warn("Overlay handoff failed for fb%d. rc=%d\n",
+ mfd->index, rc);
+ rc = 0;
+ }
+ }
+
return rc;
init_fail:
kfree(mdp5_data);
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 16ea7dc..779f74c 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -27,10 +27,10 @@
static DEFINE_MUTEX(mdss_mdp_sspp_lock);
static DEFINE_MUTEX(mdss_mdp_smp_lock);
-static DECLARE_BITMAP(mdss_mdp_smp_mmb_pool, MDSS_MDP_SMP_MMB_BLOCKS);
static int mdss_mdp_pipe_free(struct mdss_mdp_pipe *pipe);
-static int __mdss_mdp_pipe_smp_mmb_is_empty(unsigned long *smp);
+static struct mdss_mdp_pipe *mdss_mdp_pipe_search_by_client_id(
+ struct mdss_data_type *mdata, int client_id);
static inline void mdss_mdp_pipe_write(struct mdss_mdp_pipe *pipe,
u32 reg, u32 val)
@@ -43,21 +43,29 @@
return readl_relaxed(pipe->base + reg);
}
-static u32 mdss_mdp_smp_mmb_reserve(unsigned long *existing,
- unsigned long *reserve, size_t n)
+static u32 mdss_mdp_smp_mmb_reserve(struct mdss_mdp_pipe_smp_map *smp_map,
+ size_t n)
{
u32 i, mmb;
+ u32 fixed_cnt = bitmap_weight(smp_map->fixed, SMP_MB_CNT);
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+
+ if (n <= fixed_cnt)
+ return fixed_cnt;
+ else
+ n -= fixed_cnt;
/* reserve more blocks if needed, but can't free mmb at this point */
- for (i = bitmap_weight(existing, SMP_MB_CNT); i < n; i++) {
- if (bitmap_full(mdss_mdp_smp_mmb_pool, SMP_MB_CNT))
+ for (i = bitmap_weight(smp_map->allocated, SMP_MB_CNT); i < n; i++) {
+ if (bitmap_full(mdata->mmb_alloc_map, SMP_MB_CNT))
break;
- mmb = find_first_zero_bit(mdss_mdp_smp_mmb_pool, SMP_MB_CNT);
- set_bit(mmb, reserve);
- set_bit(mmb, mdss_mdp_smp_mmb_pool);
+ mmb = find_first_zero_bit(mdata->mmb_alloc_map, SMP_MB_CNT);
+ set_bit(mmb, smp_map->reserved);
+ set_bit(mmb, mdata->mmb_alloc_map);
}
- return i;
+
+ return i + fixed_cnt;
}
static int mdss_mdp_smp_mmb_set(int client_id, unsigned long *smp)
@@ -86,20 +94,17 @@
static void mdss_mdp_smp_mmb_free(unsigned long *smp, bool write)
{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+
if (!bitmap_empty(smp, SMP_MB_CNT)) {
if (write)
mdss_mdp_smp_mmb_set(0, smp);
- bitmap_andnot(mdss_mdp_smp_mmb_pool, mdss_mdp_smp_mmb_pool,
+ bitmap_andnot(mdata->mmb_alloc_map, mdata->mmb_alloc_map,
smp, SMP_MB_CNT);
bitmap_zero(smp, SMP_MB_CNT);
}
}
-static int __mdss_mdp_pipe_smp_mmb_is_empty(unsigned long *smp)
-{
- return bitmap_weight(smp, SMP_MB_CNT) == 0;
-}
-
static void mdss_mdp_smp_set_wm_levels(struct mdss_mdp_pipe *pipe, int mb_cnt)
{
u32 fetch_size, val, wm[3];
@@ -229,8 +234,8 @@
pr_debug("reserving %d mmb for pnum=%d plane=%d\n",
num_blks, pipe->num, i);
- reserved = mdss_mdp_smp_mmb_reserve(pipe->smp_map[i].allocated,
- pipe->smp_map[i].reserved, num_blks);
+ reserved = mdss_mdp_smp_mmb_reserve(&pipe->smp_map[i],
+ num_blks);
if (reserved < num_blks)
break;
}
@@ -246,7 +251,21 @@
return rc;
}
-
+/*
+ * mdss_mdp_smp_alloc() -- set smp mmb and and wm levels for a staged pipe
+ * @pipe: pointer to a pipe
+ *
+ * Function amends reserved smp mmbs to allocated bitmap and ties respective
+ * mmbs to their pipe fetch_ids. Based on the number of total allocated mmbs
+ * for a staged pipe, it also sets the watermark levels (wm).
+ *
+ * This function will be called on every commit where pipe params might not
+ * have changed. In such cases, we need to ensure that wm levels are not
+ * wiped out. Also in some rare situations hw might have reset and wiped out
+ * smp mmb programming but new smp reservation is not done. In such cases we
+ * need to ensure that for a staged pipes, mmbs are set properly based on
+ * allocated bitmap.
+ */
static int mdss_mdp_smp_alloc(struct mdss_mdp_pipe *pipe)
{
int i;
@@ -254,8 +273,14 @@
mutex_lock(&mdss_mdp_smp_lock);
for (i = 0; i < MAX_PLANES; i++) {
- if (__mdss_mdp_pipe_smp_mmb_is_empty(pipe->smp_map[i].reserved))
+ cnt += bitmap_weight(pipe->smp_map[i].fixed, SMP_MB_CNT);
+
+ if (bitmap_empty(pipe->smp_map[i].reserved, SMP_MB_CNT)) {
+ cnt += mdss_mdp_smp_mmb_set(pipe->ftch_id + i,
+ pipe->smp_map[i].allocated);
continue;
+ }
+
mdss_mdp_smp_mmb_amend(pipe->smp_map[i].allocated,
pipe->smp_map[i].reserved);
cnt += mdss_mdp_smp_mmb_set(pipe->ftch_id + i,
@@ -284,6 +309,80 @@
return 0;
}
+/**
+ * mdss_mdp_smp_handoff() - Handoff SMP MMBs in use by staged pipes
+ * @mdata: pointer to the global mdss data structure.
+ *
+ * Iterate through the list of all SMP MMBs and check to see if any
+ * of them are assigned to a pipe being marked as being handed-off.
+ * If so, update the corresponding software allocation map to reflect
+ * this.
+ *
+ * This function would typically be called during MDP probe for the case
+ * when certain pipes might be programmed in the bootloader to display
+ * the splash screen.
+ */
+int mdss_mdp_smp_handoff(struct mdss_data_type *mdata)
+{
+ int rc = 0;
+ int i, client_id, prev_id = 0;
+ u32 off, s, data;
+ struct mdss_mdp_pipe *pipe = NULL;
+
+ /*
+ * figure out what SMP MMBs are allocated for each of the pipes
+ * that need to be handed off.
+ */
+ for (i = 0; i < SMP_MB_CNT; i++) {
+ off = (i / 3) * 4;
+ s = (i % 3) * 8;
+ data = MDSS_MDP_REG_READ(MDSS_MDP_REG_SMP_ALLOC_W0 + off);
+ client_id = (data >> s) & 0xFF;
+ if (test_bit(i, mdata->mmb_alloc_map)) {
+ /*
+ * Certain pipes may have a dedicated set of
+ * SMP MMBs statically allocated to them. In
+ * such cases, we do not need to do anything
+ * here.
+ */
+ pr_debug("smp mmb %d already assigned to pipe %d (client_id %d)"
+ , i, pipe->num, client_id);
+ continue;
+ }
+
+ if (client_id) {
+ if (client_id != prev_id) {
+ pipe = mdss_mdp_pipe_search_by_client_id(mdata,
+ client_id);
+ prev_id = client_id;
+ }
+
+ if (!pipe) {
+ pr_warn("Invalid client id %d for SMP MMB %d\n",
+ client_id, i);
+ continue;
+ }
+
+ if (!pipe->is_handed_off) {
+ pr_warn("SMP MMB %d assigned to a pipe not marked for handoff (client id %d)"
+ , i, client_id);
+ continue;
+ }
+
+ /*
+ * Assume that the source format only has
+ * one plane
+ */
+ pr_debug("Assigning smp mmb %d to pipe %d (client_id %d)\n"
+ , i, pipe->num, client_id);
+ set_bit(i, pipe->smp_map[0].allocated);
+ set_bit(i, mdata->mmb_alloc_map);
+ }
+ }
+
+ return rc;
+}
+
void mdss_mdp_pipe_unmap(struct mdss_mdp_pipe *pipe)
{
int tmp;
@@ -307,7 +406,7 @@
static struct mdss_mdp_pipe *mdss_mdp_pipe_init(struct mdss_mdp_mixer *mixer,
u32 type, u32 off)
{
- struct mdss_mdp_pipe *pipe;
+ struct mdss_mdp_pipe *pipe = NULL;
struct mdss_data_type *mdata;
struct mdss_mdp_pipe *pipe_pool = NULL;
u32 npipes;
@@ -427,6 +526,29 @@
return pipe;
}
+static struct mdss_mdp_pipe *mdss_mdp_pipe_search_by_client_id(
+ struct mdss_data_type *mdata, int client_id)
+{
+ u32 i;
+
+ for (i = 0; i < mdata->nrgb_pipes; i++) {
+ if (mdata->rgb_pipes[i].ftch_id == client_id)
+ return &mdata->rgb_pipes[i];
+ }
+
+ for (i = 0; i < mdata->nvig_pipes; i++) {
+ if (mdata->vig_pipes[i].ftch_id == client_id)
+ return &mdata->vig_pipes[i];
+ }
+
+ for (i = 0; i < mdata->ndma_pipes; i++) {
+ if (mdata->dma_pipes[i].ftch_id == client_id)
+ return &mdata->dma_pipes[i];
+ }
+
+ return NULL;
+}
+
struct mdss_mdp_pipe *mdss_mdp_pipe_search(struct mdss_data_type *mdata,
u32 ndx)
{
@@ -481,22 +603,112 @@
}
-static int mdss_mdp_image_setup(struct mdss_mdp_pipe *pipe)
+/**
+ * mdss_mdp_pipe_handoff() - Handoff staged pipes during bootup
+ * @pipe: pointer to the pipe to be handed-off
+ *
+ * Populate the software structures for the pipe based on the current
+ * configuration of the hardware pipe by the reading the appropriate MDP
+ * registers.
+ *
+ * This function would typically be called during MDP probe for the case
+ * when certain pipes might be programmed in the bootloader to display
+ * the splash screen.
+ */
+int mdss_mdp_pipe_handoff(struct mdss_mdp_pipe *pipe)
+{
+ int rc = 0;
+ u32 src_fmt, reg = 0, bpp = 0;
+
+ /*
+ * todo: for now, only reading pipe src and dest size details
+ * from the registers. This is needed for appropriately
+ * calculating perf metrics for the handed off pipes.
+ * We may need to parse some more details at a later date.
+ */
+ reg = mdss_mdp_pipe_read(pipe, MDSS_MDP_REG_SSPP_SRC_SIZE);
+ pipe->src.h = reg >> 16;
+ pipe->src.w = reg & 0xFFFF;
+ reg = mdss_mdp_pipe_read(pipe, MDSS_MDP_REG_SSPP_OUT_SIZE);
+ pipe->dst.h = reg >> 16;
+ pipe->dst.w = reg & 0xFFFF;
+
+ /* Assume that the source format is RGB */
+ reg = mdss_mdp_pipe_read(pipe, MDSS_MDP_REG_SSPP_SRC_FORMAT);
+ bpp = ((reg >> 9) & 0x3) + 1;
+ switch (bpp) {
+ case 4:
+ src_fmt = MDP_RGBA_8888;
+ break;
+ case 3:
+ src_fmt = MDP_RGB_888;
+ break;
+ case 2:
+ src_fmt = MDP_RGB_565;
+ break;
+ default:
+ pr_err("Invalid bpp=%d found\n", bpp);
+ rc = -EINVAL;
+ goto error;
+ }
+ pipe->src_fmt = mdss_mdp_get_format_params(src_fmt);
+
+ pr_debug("Pipe settings: src.h=%d src.w=%d dst.h=%d dst.w=%d bpp=%d\n"
+ , pipe->src.h, pipe->src.w, pipe->dst.h, pipe->dst.w,
+ pipe->src_fmt->bpp);
+
+ pipe->is_handed_off = true;
+ atomic_inc(&pipe->ref_cnt);
+
+error:
+ return rc;
+}
+
+void mdss_mdp_crop_rect(struct mdss_mdp_img_rect *src_rect,
+ struct mdss_mdp_img_rect *dst_rect,
+ const struct mdss_mdp_img_rect *sci_rect)
+{
+ struct mdss_mdp_img_rect res;
+ mdss_mdp_intersect_rect(&res, dst_rect, sci_rect);
+
+ if (res.w && res.h) {
+ if ((res.w != dst_rect->w) || (res.h != dst_rect->h)) {
+ src_rect->x = src_rect->x + (res.x - dst_rect->x);
+ src_rect->y = src_rect->y + (res.y - dst_rect->y);
+ src_rect->w = res.w;
+ src_rect->h = res.h;
+ }
+ *dst_rect = (struct mdss_mdp_img_rect)
+ {(res.x - sci_rect->x), (res.y - sci_rect->y),
+ res.w, res.h};
+ }
+}
+
+static int mdss_mdp_image_setup(struct mdss_mdp_pipe *pipe,
+ struct mdss_mdp_data *data)
{
u32 img_size, src_size, src_xy, dst_size, dst_xy, ystride0, ystride1;
u32 width, height;
u32 decimation;
+ struct mdss_mdp_img_rect sci, dst, src;
+ int ret = 0;
pr_debug("pnum=%d wh=%dx%d src={%d,%d,%d,%d} dst={%d,%d,%d,%d}\n",
- pipe->num, pipe->img_width, pipe->img_height,
- pipe->src.x, pipe->src.y, pipe->src.w, pipe->src.h,
- pipe->dst.x, pipe->dst.y, pipe->dst.w, pipe->dst.h);
+ pipe->num, pipe->img_width, pipe->img_height,
+ pipe->src.x, pipe->src.y, pipe->src.w, pipe->src.h,
+ pipe->dst.x, pipe->dst.y, pipe->dst.w, pipe->dst.h);
width = pipe->img_width;
height = pipe->img_height;
mdss_mdp_get_plane_sizes(pipe->src_fmt->format, width, height,
&pipe->src_planes, pipe->bwc_mode);
+ if (data != NULL) {
+ ret = mdss_mdp_data_check(data, &pipe->src_planes);
+ if (ret)
+ return ret;
+ }
+
if ((pipe->flags & MDP_DEINTERLACE) &&
!(pipe->flags & MDP_SOURCE_ROTATED_90)) {
int i;
@@ -512,15 +724,23 @@
pr_debug("Image decimation h=%d v=%d\n",
pipe->horz_deci, pipe->vert_deci);
+ sci = pipe->mixer->ctl->roi;
+ dst = pipe->dst;
+ src = pipe->src;
+
+ mdss_mdp_crop_rect(&src, &dst, &sci);
+
+ src_size = (src.h << 16) | src.w;
+ src_xy = (src.y << 16) | src.x;
+ dst_size = (dst.h << 16) | dst.w;
+ dst_xy = (dst.y << 16) | dst.x;
+
img_size = (height << 16) | width;
- src_size = (pipe->src.h << 16) | pipe->src.w;
- src_xy = (pipe->src.y << 16) | pipe->src.x;
- dst_size = (pipe->dst.h << 16) | pipe->dst.w;
- dst_xy = (pipe->dst.y << 16) | pipe->dst.x;
+
ystride0 = (pipe->src_planes.ystride[0]) |
- (pipe->src_planes.ystride[1] << 16);
+ (pipe->src_planes.ystride[1] << 16);
ystride1 = (pipe->src_planes.ystride[2]) |
- (pipe->src_planes.ystride[3] << 16);
+ (pipe->src_planes.ystride[3] << 16);
if (pipe->overfetch_disable) {
img_size = src_size;
@@ -661,7 +881,7 @@
pr_debug("solid fill setup on pnum=%d\n", pipe->num);
- ret = mdss_mdp_image_setup(pipe);
+ ret = mdss_mdp_image_setup(pipe, NULL);
if (ret) {
pr_err("image setup error for pnum=%d\n", pipe->num);
return ret;
@@ -706,7 +926,8 @@
params_changed = (pipe->params_changed) ||
((pipe->type == MDSS_MDP_PIPE_TYPE_DMA) &&
(pipe->mixer->type == MDSS_MDP_MIXER_TYPE_WRITEBACK)
- && (ctl->mdata->mixer_switched));
+ && (ctl->mdata->mixer_switched)) ||
+ ctl->roi_changed;
if (src_data == NULL) {
mdss_mdp_pipe_solidfill_setup(pipe);
goto update_nobuf;
@@ -721,7 +942,7 @@
goto done;
}
- ret = mdss_mdp_image_setup(pipe);
+ ret = mdss_mdp_image_setup(pipe, src_data);
if (ret) {
pr_err("image setup error for pnum=%d\n", pipe->num);
goto done;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pp.c b/drivers/video/msm/mdss/mdss_mdp_pp.c
index 09b789b..b31f6c1 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pp.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pp.c
@@ -295,6 +295,9 @@
struct mdp_pgc_lut_data *config);
static void pp_update_hist_lut(char __iomem *base,
struct mdp_hist_lut_data *cfg);
+static int pp_gm_has_invalid_lut_size(struct mdp_gamut_cfg_data *config);
+static void pp_gamut_config(struct mdp_gamut_cfg_data *gamut_cfg,
+ u32 base, struct pp_sts_type *pp_sts);
static void pp_pa_config(unsigned long flags, u32 base,
struct pp_sts_type *pp_sts,
struct mdp_pa_cfg *pa_config);
@@ -708,7 +711,7 @@
if (src_h <= pipe->dst.h) {
scale_config |= /* G/Y, A */
(filter_mode << 10) |
- (MDSS_MDP_SCALE_FILTER_NEAREST << 18);
+ (MDSS_MDP_SCALE_FILTER_BIL << 18);
} else
scale_config |= /* G/Y, A */
(MDSS_MDP_SCALE_FILTER_PCMN << 10) |
@@ -727,7 +730,7 @@
if (src_h <= pipe->dst.h)
scale_config |= /* RGB, A */
(MDSS_MDP_SCALE_FILTER_BIL << 10) |
- (MDSS_MDP_SCALE_FILTER_NEAREST << 18);
+ (MDSS_MDP_SCALE_FILTER_BIL << 18);
else
scale_config |= /* RGB, A */
(MDSS_MDP_SCALE_FILTER_PCMN << 10) |
@@ -761,7 +764,7 @@
if (src_w <= pipe->dst.w) {
scale_config |= /* G/Y, A */
(filter_mode << 8) |
- (MDSS_MDP_SCALE_FILTER_NEAREST << 16);
+ (MDSS_MDP_SCALE_FILTER_BIL << 16);
} else
scale_config |= /* G/Y, A */
(MDSS_MDP_SCALE_FILTER_PCMN << 8) |
@@ -780,7 +783,7 @@
if (src_w <= pipe->dst.w)
scale_config |= /* RGB, A */
(MDSS_MDP_SCALE_FILTER_BIL << 8) |
- (MDSS_MDP_SCALE_FILTER_NEAREST << 16);
+ (MDSS_MDP_SCALE_FILTER_BIL << 16);
else
scale_config |= /* RGB, A */
(MDSS_MDP_SCALE_FILTER_PCMN << 8) |
@@ -1133,7 +1136,7 @@
flush_exit:
writel_relaxed(opmode, basel + MDSS_MDP_REG_DSPP_OP_MODE);
- mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, BIT(13 + dspp_num));
+ ctl->flush_bits |= BIT(13 + dspp_num);
wmb();
dspp_exit:
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
@@ -1210,7 +1213,7 @@
pp_ad_cfg_write(ad);
if (PP_AD_STATE_INIT & ad->state)
pp_ad_init_write(ad);
- if (PP_AD_STATE_DATA & ad->state) {
+ if ((PP_AD_STATE_DATA & ad->state) && (ad->sts & PP_STS_ENABLE)) {
bl = ad->bl_mfd->bl_level;
ad->last_bl = bl;
if (ad->state & PP_AD_STATE_BL_LIN) {
@@ -1369,15 +1372,12 @@
return 0;
}
-int mdss_mdp_pa_config(struct mdss_mdp_ctl *ctl, struct mdp_pa_cfg_data *config,
+int mdss_mdp_pa_config(struct mdp_pa_cfg_data *config,
u32 *copyback)
{
int ret = 0;
u32 pa_offset, disp_num, dspp_num = 0;
- if (!ctl)
- return -EINVAL;
-
if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
(config->block >= MDP_BLOCK_MAX))
return -EINVAL;
@@ -1411,8 +1411,6 @@
pa_config_exit:
mutex_unlock(&mdss_pp_mutex);
- if (!ret)
- mdss_mdp_pp_setup(ctl);
return ret;
}
@@ -1542,16 +1540,12 @@
MDSS_MDP_REG_WRITE(offset + 8, cfg_ptr->b.rgb_1);
}
-int mdss_mdp_pcc_config(struct mdss_mdp_ctl *ctl,
- struct mdp_pcc_cfg_data *config,
+int mdss_mdp_pcc_config(struct mdp_pcc_cfg_data *config,
u32 *copyback)
{
int ret = 0;
u32 base, disp_num, dspp_num = 0;
- if (!ctl)
- return -EINVAL;
-
if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
(config->block >= MDP_BLOCK_MAX))
return -EINVAL;
@@ -1581,8 +1575,6 @@
pcc_config_exit:
mutex_unlock(&mdss_pp_mutex);
- if (!ret)
- mdss_mdp_pp_setup(ctl);
return ret;
}
@@ -1656,22 +1648,18 @@
config.c0_c1_data = igc_limited;
config.c2_data = igc_limited;
- ret = mdss_mdp_igc_lut_config(ctl, &config, ©back,
+ ret = mdss_mdp_igc_lut_config(&config, ©back,
copy_from_kernel);
return ret;
}
-int mdss_mdp_igc_lut_config(struct mdss_mdp_ctl *ctl,
- struct mdp_igc_lut_data *config,
+int mdss_mdp_igc_lut_config(struct mdp_igc_lut_data *config,
u32 *copyback, u32 copy_from_kernel)
{
int ret = 0;
u32 tbl_idx, igc_offset, disp_num, dspp_num = 0;
struct mdp_igc_lut_data local_cfg;
- if (!ctl)
- return -EINVAL;
-
if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
(config->block >= MDP_BLOCK_MAX))
return -EINVAL;
@@ -1748,8 +1736,6 @@
igc_config_exit:
mutex_unlock(&mdss_pp_mutex);
- if (!ret)
- mdss_mdp_pp_setup(ctl);
return ret;
}
static void pp_update_gc_one_lut(u32 offset,
@@ -1864,8 +1850,7 @@
writel_relaxed(1, offset + 16);
}
-int mdss_mdp_argc_config(struct mdss_mdp_ctl *ctl,
- struct mdp_pgc_lut_data *config,
+int mdss_mdp_argc_config(struct mdp_pgc_lut_data *config,
u32 *copyback)
{
int ret = 0;
@@ -1874,9 +1859,6 @@
struct mdp_pgc_lut_data *pgc_ptr;
u32 tbl_size, r_size, g_size, b_size;
- if (!ctl)
- return -EINVAL;
-
if ((PP_BLOCK(config->block) < MDP_LOGICAL_BLOCK_DISP_0) ||
(PP_BLOCK(config->block) >= MDP_BLOCK_MAX))
return -EINVAL;
@@ -1986,20 +1968,14 @@
}
argc_config_exit:
mutex_unlock(&mdss_pp_mutex);
- if (!ret)
- mdss_mdp_pp_setup(ctl);
return ret;
}
-int mdss_mdp_hist_lut_config(struct mdss_mdp_ctl *ctl,
- struct mdp_hist_lut_data *config,
+int mdss_mdp_hist_lut_config(struct mdp_hist_lut_data *config,
u32 *copyback)
{
int i, ret = 0;
u32 hist_offset, disp_num, dspp_num = 0;
- if (!ctl)
- return -EINVAL;
-
if ((PP_BLOCK(config->block) < MDP_LOGICAL_BLOCK_DISP_0) ||
(PP_BLOCK(config->block) >= MDP_BLOCK_MAX))
return -EINVAL;
@@ -2043,18 +2019,13 @@
}
enhist_config_exit:
mutex_unlock(&mdss_pp_mutex);
- if (!ret)
- mdss_mdp_pp_setup(ctl);
return ret;
}
-int mdss_mdp_dither_config(struct mdss_mdp_ctl *ctl,
- struct mdp_dither_cfg_data *config,
+int mdss_mdp_dither_config(struct mdp_dither_cfg_data *config,
u32 *copyback)
{
u32 disp_num;
- if (!ctl)
- return -EINVAL;
if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
(config->block >= MDP_BLOCK_MAX))
@@ -2067,15 +2038,35 @@
mdss_pp_res->dither_disp_cfg[disp_num] = *config;
mdss_pp_res->pp_disp_flags[disp_num] |= PP_FLAGS_DIRTY_DITHER;
mutex_unlock(&mdss_pp_mutex);
- mdss_mdp_pp_setup(ctl);
return 0;
}
-int mdss_mdp_gamut_config(struct mdss_mdp_ctl *ctl,
- struct mdp_gamut_cfg_data *config,
+static int pp_gm_has_invalid_lut_size(struct mdp_gamut_cfg_data *config)
+{
+ if (config->tbl_size[0] != GAMUT_T0_SIZE)
+ return -EINVAL;
+ if (config->tbl_size[1] != GAMUT_T1_SIZE)
+ return -EINVAL;
+ if (config->tbl_size[2] != GAMUT_T2_SIZE)
+ return -EINVAL;
+ if (config->tbl_size[3] != GAMUT_T3_SIZE)
+ return -EINVAL;
+ if (config->tbl_size[4] != GAMUT_T4_SIZE)
+ return -EINVAL;
+ if (config->tbl_size[5] != GAMUT_T5_SIZE)
+ return -EINVAL;
+ if (config->tbl_size[6] != GAMUT_T6_SIZE)
+ return -EINVAL;
+ if (config->tbl_size[7] != GAMUT_T7_SIZE)
+ return -EINVAL;
+
+ return 0;
+}
+
+int mdss_mdp_gamut_config(struct mdp_gamut_cfg_data *config,
u32 *copyback)
{
- int i, j, size_total = 0, ret = 0;
+ int i, j, ret = 0;
u32 offset, disp_num, dspp_num = 0;
uint16_t *tbl_off;
struct mdp_gamut_cfg_data local_cfg;
@@ -2084,15 +2075,11 @@
uint16_t *b_tbl[MDP_GAMUT_TABLE_NUM];
- if (!ctl)
- return -EINVAL;
-
if ((config->block < MDP_LOGICAL_BLOCK_DISP_0) ||
(config->block >= MDP_BLOCK_MAX))
return -EINVAL;
- for (i = 0; i < MDP_GAMUT_TABLE_NUM; i++)
- size_total += config->tbl_size[i];
- if (size_total != GAMUT_TOTAL_TABLE_SIZE)
+
+ if (pp_gm_has_invalid_lut_size(config))
return -EINVAL;
mutex_lock(&mdss_pp_mutex);
@@ -2209,8 +2196,6 @@
}
gamut_config_exit:
mutex_unlock(&mdss_pp_mutex);
- if (!ret)
- mdss_mdp_pp_setup(ctl);
return ret;
}
static void pp_hist_read(char __iomem *v_base,
@@ -2253,7 +2238,7 @@
hist_info->col_state = HIST_RESET;
hist_info->col_en = true;
spin_unlock_irqrestore(&hist_info->hist_lock, flag);
- hist_info->is_kick_ready = false;
+ hist_info->is_kick_ready = true;
mdss_mdp_hist_irq_enable(3 << shift_bit);
writel_relaxed(req->frame_cnt, ctl_base + 8);
/* Kick out reset start */
@@ -2263,8 +2248,7 @@
return ret;
}
-int mdss_mdp_histogram_start(struct mdss_mdp_ctl *ctl,
- struct mdp_histogram_start_req *req)
+int mdss_mdp_histogram_start(struct mdp_histogram_start_req *req)
{
u32 done_shift_bit;
char __iomem *ctl_base;
@@ -2274,8 +2258,6 @@
u32 mixer_cnt, mixer_id[MDSS_MDP_INTF_MAX_LAYERMIXER];
struct mdss_mdp_pipe *pipe;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
- if (!ctl)
- return -EINVAL;
if ((PP_BLOCK(req->block) < MDP_LOGICAL_BLOCK_DISP_0) ||
(PP_BLOCK(req->block) >= MDP_BLOCK_MAX))
@@ -2342,31 +2324,6 @@
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
hist_exit:
- if (!ret && (PP_LOCAT(req->block) == MDSS_PP_DSPP_CFG)) {
- mdss_mdp_pp_setup(ctl);
- /* wait for a frame to let histrogram enable itself */
- /* TODO add hysteresis value to be able to remove this sleep */
- usleep(41666);
- for (i = 0; i < mixer_cnt; i++) {
- dspp_num = mixer_id[i];
- hist_info = &mdss_pp_res->dspp_hist[dspp_num];
- mutex_lock(&hist_info->hist_mutex);
- hist_info->is_kick_ready = true;
- mutex_unlock(&hist_info->hist_mutex);
- }
- } else if (!ret) {
- for (i = 0; i < MDSS_PP_ARG_NUM; i++) {
- if (!PP_ARG(i, req->block))
- continue;
- pr_info("PP_ARG(%d) = %d", i, PP_ARG(i, req->block));
- pipe = mdss_mdp_pipe_get(mdata, BIT(i));
- if (IS_ERR_OR_NULL(pipe))
- continue;
- hist_info = &pipe->pp_res.hist;
- hist_info->is_kick_ready = true;
- mdss_mdp_pipe_unmap(pipe);
- }
- }
return ret;
}
@@ -2395,7 +2352,7 @@
return ret;
}
-int mdss_mdp_histogram_stop(struct mdss_mdp_ctl *ctl, u32 block)
+int mdss_mdp_histogram_stop(u32 block)
{
int i, ret = 0;
char __iomem *ctl_base;
@@ -2405,9 +2362,6 @@
struct mdss_mdp_pipe *pipe;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
- if (!ctl)
- return -EINVAL;
-
if ((PP_BLOCK(block) < MDP_LOGICAL_BLOCK_DISP_0) ||
(PP_BLOCK(block) >= MDP_BLOCK_MAX))
return -EINVAL;
@@ -2472,13 +2426,10 @@
hist_stop_clk:
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
hist_stop_exit:
- if (!ret && (PP_LOCAT(block) == MDSS_PP_DSPP_CFG))
- mdss_mdp_pp_setup(ctl);
return ret;
}
-static int pp_hist_collect(struct mdss_mdp_ctl *ctl,
- struct mdp_histogram_data *hist,
+static int pp_hist_collect(struct mdp_histogram_data *hist,
struct pp_hist_col_info *hist_info,
char __iomem *ctl_base)
{
@@ -2502,9 +2453,6 @@
spin_unlock_irqrestore(&hist_info->hist_lock, flag);
timeout = HIST_WAIT_TIMEOUT(hist_info->frame_cnt);
mutex_unlock(&hist_info->hist_mutex);
- /* flush updates before wait*/
- if (PP_LOCAT(hist->block) == MDSS_PP_DSPP_CFG)
- mdss_mdp_pp_setup(ctl);
if (PP_LOCAT(hist->block) == MDSS_PP_SSPP_CFG) {
res = container_of(hist_info, struct mdss_pipe_pp_res,
hist);
@@ -2565,8 +2513,7 @@
return ret;
}
-int mdss_mdp_hist_collect(struct mdss_mdp_ctl *ctl,
- struct mdp_histogram_data *hist)
+int mdss_mdp_hist_collect(struct mdp_histogram_data *hist)
{
int i, j, off, ret = 0;
struct pp_hist_col_info *hist_info;
@@ -2580,9 +2527,6 @@
struct mdss_mdp_pipe *pipe;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
- if (!ctl)
- return -EINVAL;
-
if ((PP_BLOCK(hist->block) < MDP_LOGICAL_BLOCK_DISP_0) ||
(PP_BLOCK(hist->block) >= MDP_BLOCK_MAX))
return -EINVAL;
@@ -2609,7 +2553,7 @@
hist_info = &mdss_pp_res->dspp_hist[dspp_num];
ctl_base = mdss_mdp_get_dspp_addr_off(dspp_num) +
MDSS_MDP_REG_DSPP_HIST_CTL_BASE;
- ret = pp_hist_collect(ctl, hist, hist_info, ctl_base);
+ ret = pp_hist_collect(hist, hist_info, ctl_base);
if (ret)
goto hist_collect_exit;
}
@@ -2678,7 +2622,7 @@
hist_info = &pipe->pp_res.hist;
ctl_base = pipe->base +
MDSS_MDP_REG_VIG_HIST_CTL_BASE;
- ret = pp_hist_collect(ctl, hist, hist_info, ctl_base);
+ ret = pp_hist_collect(hist, hist_info, ctl_base);
mdss_mdp_pipe_unmap(pipe);
if (ret)
goto hist_collect_exit;
@@ -2971,8 +2915,6 @@
}
mutex_unlock(&ad->lock);
ctl = mfd_to_ctl(mfd);
- if (!ret)
- mdss_mdp_pp_setup(ctl);
return ret;
}
@@ -2980,7 +2922,6 @@
struct mdss_ad_input *input, int wait) {
int ret = 0;
struct mdss_ad_info *ad;
- struct mdss_mdp_ctl *ctl;
u32 bl;
ret = mdss_mdp_get_ad(mfd, &ad);
@@ -3056,8 +2997,6 @@
init_completion(&ad->comp);
mutex_unlock(&ad->lock);
}
- ctl = mfd_to_ctl(mfd);
- mdss_mdp_pp_setup(ctl);
if (wait) {
ret = wait_for_completion_interruptible_timeout(
&ad->comp, HIST_WAIT_TIMEOUT(1));
@@ -3415,7 +3354,7 @@
}
mutex_unlock(&ad->lock);
mutex_lock(&mfd->lock);
- mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, BIT(13 + ad->num));
+ ctl->flush_bits |= BIT(13 + ad->num);
mutex_unlock(&mfd->lock);
/* Trigger update notify to wake up those waiting for display updates */
@@ -3571,12 +3510,22 @@
int mdss_mdp_calib_config_buffer(struct mdp_calib_config_buffer *cfg,
u32 *copyback)
{
- int ret = -1;
- int counter = cfg->size / (sizeof(uint32_t) * 2);
+ int ret = -1, counter;
uint32_t *buff = NULL, *buff_org = NULL;
void *ptr;
int i = 0;
+ if (!cfg) {
+ pr_err("Invalid buffer pointer");
+ return ret;
+ }
+
+ if (cfg->size == 0) {
+ pr_err("Invalid buffer size");
+ return ret;
+ }
+
+ counter = cfg->size / (sizeof(uint32_t) * 2);
buff_org = buff = kzalloc(cfg->size, GFP_KERNEL);
if (buff == NULL) {
pr_err("Allocation failed");
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index 8381c5b..1d172f3 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -17,9 +17,12 @@
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/types.h>
+#include <linux/sync.h>
+#include <linux/sw_sync.h>
#include "mdss_mdp.h"
#include "mdss_mdp_rotator.h"
+#include "mdss_fb.h"
#define MAX_ROTATOR_SESSIONS 8
@@ -28,13 +31,17 @@
static LIST_HEAD(rotator_queue);
static int mdss_mdp_rotator_finish(struct mdss_mdp_rotator_session *rot);
+static void mdss_mdp_rotator_commit_wq_handler(struct work_struct *work);
+static int mdss_mdp_rotator_busy_wait(struct mdss_mdp_rotator_session *rot);
+static int mdss_mdp_rotator_queue_helper(struct mdss_mdp_rotator_session *rot);
+static struct msm_sync_pt_data *mdss_mdp_rotator_sync_pt_create(
+ struct mdss_mdp_rotator_session *rot);
-struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void)
+static struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void)
{
struct mdss_mdp_rotator_session *rot;
int i;
- mutex_lock(&rotator_lock);
for (i = 0; i < MAX_ROTATOR_SESSIONS; i++) {
rot = &rotator_session[i];
if (rot->ref_cnt == 0) {
@@ -44,16 +51,15 @@
break;
}
}
- mutex_unlock(&rotator_lock);
if (i == MAX_ROTATOR_SESSIONS) {
pr_err("max rotator sessions reached\n");
return NULL;
}
-
return rot;
}
-struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_get(u32 session_id)
+static inline struct mdss_mdp_rotator_session
+*mdss_mdp_rotator_session_get(u32 session_id)
{
struct mdss_mdp_rotator_session *rot;
u32 ndx;
@@ -67,6 +73,22 @@
return NULL;
}
+struct msm_sync_pt_data *mdss_mdp_rotator_sync_pt_get(
+ struct msm_fb_data_type *mfd, const struct mdp_buf_sync *buf_sync)
+{
+ struct mdss_mdp_rotator_session *rot;
+
+ rot = mdss_mdp_rotator_session_get(buf_sync->session_id);
+ if (!rot)
+ return NULL;
+ if (!rot->rot_sync_pt_data)
+ rot->rot_sync_pt_data = mdss_mdp_rotator_sync_pt_create(rot);
+ if (rot->rot_sync_pt_data)
+ rot->use_sync_pt = true;
+
+ return rot->rot_sync_pt_data;
+}
+
static struct mdss_mdp_pipe *mdss_mdp_rotator_pipe_alloc(void)
{
struct mdss_mdp_mixer *mixer;
@@ -89,16 +111,15 @@
static int mdss_mdp_rotator_busy_wait(struct mdss_mdp_rotator_session *rot)
{
- struct mdss_mdp_pipe *rot_pipe = NULL;
- struct mdss_mdp_ctl *ctl = NULL;
- rot_pipe = rot->pipe;
- if (!rot_pipe)
- return -ENODEV;
-
- ctl = rot_pipe->mixer->ctl;
mutex_lock(&rot->lock);
+ if (!rot->pipe || !rot->pipe->mixer || !rot->pipe->mixer->ctl) {
+ mutex_unlock(&rot->lock);
+ return -ENODEV;
+ }
+
if (rot->busy) {
+ struct mdss_mdp_ctl *ctl = rot->pipe->mixer->ctl;
mdss_mdp_display_wait4comp(ctl);
rot->busy = false;
if (ctl->shared_lock)
@@ -246,23 +267,81 @@
return ret;
}
-int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot,
- struct mdss_mdp_data *src_data,
- struct mdss_mdp_data *dst_data)
+static void mdss_mdp_rotator_commit_wq_handler(struct work_struct *work)
+{
+ struct mdss_mdp_rotator_session *rot;
+ int ret;
+
+ rot = container_of(work, struct mdss_mdp_rotator_session, commit_work);
+
+ mutex_lock(&rotator_lock);
+ ret = mdss_mdp_rotator_queue_helper(rot);
+ if (ret)
+ pr_err("rotator queue failed\n");
+
+ if (rot->rot_sync_pt_data) {
+ atomic_inc(&rot->rot_sync_pt_data->commit_cnt);
+ mdss_fb_signal_timeline(rot->rot_sync_pt_data);
+ } else {
+ pr_err("rot_sync_pt_data is NULL\n");
+ }
+
+ mutex_unlock(&rotator_lock);
+}
+
+static struct msm_sync_pt_data *mdss_mdp_rotator_sync_pt_create(
+ struct mdss_mdp_rotator_session *rot)
+{
+ struct msm_sync_pt_data *sync_pt_data;
+ char timeline_name[16];
+
+ rot->rot_sync_pt_data = kzalloc(
+ sizeof(struct msm_sync_pt_data), GFP_KERNEL);
+ sync_pt_data = rot->rot_sync_pt_data;
+ if (!sync_pt_data)
+ return NULL;
+ sync_pt_data->fence_name = "rot-fence";
+ sync_pt_data->threshold = 1;
+ snprintf(timeline_name, sizeof(timeline_name),
+ "mdss_rot_%d", rot->session_id);
+ sync_pt_data->timeline = sw_sync_timeline_create(timeline_name);
+ if (sync_pt_data->timeline == NULL) {
+ kfree(rot->rot_sync_pt_data);
+ pr_err("%s: cannot create time line", __func__);
+ return NULL;
+ } else {
+ sync_pt_data->timeline_value = 0;
+ }
+ INIT_WORK(&rot->commit_work,
+ mdss_mdp_rotator_commit_wq_handler);
+ mutex_init(&sync_pt_data->sync_mutex);
+ return sync_pt_data;
+}
+
+static int mdss_mdp_rotator_busy_wait_ex(struct mdss_mdp_rotator_session *rot)
+{
+
+ struct mdss_mdp_rotator_session *tmp;
+
+ for (tmp = rot; tmp; tmp = tmp->next)
+ mdss_mdp_rotator_busy_wait(tmp);
+
+ if (rot->use_sync_pt)
+ mdss_fb_wait_for_fence(rot->rot_sync_pt_data);
+
+ return 0;
+}
+
+static int mdss_mdp_rotator_queue_helper(struct mdss_mdp_rotator_session *rot)
{
int ret;
- struct mdss_mdp_rotator_session *tmp = rot;
-
- ret = mutex_lock_interruptible(&rotator_lock);
- if (ret)
- return ret;
+ struct mdss_mdp_rotator_session *tmp;
pr_debug("rotator session=%x start\n", rot->session_id);
for (ret = 0, tmp = rot; ret == 0 && tmp; tmp = tmp->next)
- ret = mdss_mdp_rotator_queue_sub(tmp, src_data, dst_data);
-
- mutex_unlock(&rotator_lock);
+ ret = mdss_mdp_rotator_queue_sub(tmp,
+ &rot->src_buf, &rot->dst_buf);
if (ret) {
pr_err("rotation failed %d for rot=%d\n", ret, rot->session_id);
@@ -272,15 +351,97 @@
for (tmp = rot; tmp; tmp = tmp->next)
mdss_mdp_rotator_busy_wait(tmp);
+ return ret;
+}
+
+static int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot)
+{
+ int ret = 0;
+
+ if (rot->use_sync_pt)
+ schedule_work(&rot->commit_work);
+ else
+ ret = mdss_mdp_rotator_queue_helper(rot);
+
pr_debug("rotator session=%x queue done\n", rot->session_id);
return ret;
}
-int mdss_mdp_rotator_setup(struct mdss_mdp_rotator_session *rot)
+int mdss_mdp_rotator_setup(struct msm_fb_data_type *mfd,
+ struct mdp_overlay *req)
{
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ struct mdss_mdp_rotator_session *rot = NULL;
+ struct mdss_mdp_format_params *fmt;
+ u32 bwc_enabled;
+ int ret = 0;
+
+ mutex_lock(&rotator_lock);
+
+ fmt = mdss_mdp_get_format_params(req->src.format);
+ if (!fmt) {
+ pr_err("invalid rot format %d\n", req->src.format);
+ ret = -EINVAL;
+ goto rot_err;
+ }
+
+ ret = mdss_mdp_overlay_req_check(mfd, req, fmt);
+ if (ret)
+ goto rot_err;
+
+ if (req->id == MSMFB_NEW_REQUEST) {
+ rot = mdss_mdp_rotator_session_alloc();
+ rot->pid = current->tgid;
+ list_add(&rot->list, &mdp5_data->rot_proc_list);
+
+ if (!rot) {
+ pr_err("unable to allocate rotator session\n");
+ ret = -ENOMEM;
+ goto rot_err;
+ }
+ } else if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
+ rot = mdss_mdp_rotator_session_get(req->id);
+
+ if (!rot) {
+ pr_err("rotator session=%x not found\n", req->id);
+ ret = -ENODEV;
+ goto rot_err;
+ }
+ } else {
+ pr_err("invalid rotator session id=%x\n", req->id);
+ ret = -EINVAL;
+ goto rot_err;
+ }
+
+ /* keep only flags of interest to rotator */
+ rot->flags = req->flags & (MDP_ROT_90 | MDP_FLIP_LR | MDP_FLIP_UD |
+ MDP_SECURE_OVERLAY_SESSION);
+
+ bwc_enabled = req->flags & MDP_BWC_EN;
+ if (bwc_enabled && !mdp5_data->mdata->has_bwc) {
+ pr_err("BWC is not supported in MDP version %x\n",
+ mdp5_data->mdata->mdp_rev);
+ rot->bwc_mode = 0;
+ } else {
+ rot->bwc_mode = bwc_enabled ? 1 : 0;
+ }
+ rot->format = fmt->format;
+ rot->img_width = req->src.width;
+ rot->img_height = req->src.height;
+ rot->src_rect.x = req->src_rect.x;
+ rot->src_rect.y = req->src_rect.y;
+ rot->src_rect.w = req->src_rect.w;
+ rot->src_rect.h = req->src_rect.h;
+
+ if (req->flags & MDP_DEINTERLACE) {
+ rot->flags |= MDP_DEINTERLACE;
+ rot->src_rect.h /= 2;
+ rot->src_rect.y = DIV_ROUND_UP(rot->src_rect.y, 2);
+ }
rot->dst = rot->src_rect;
+
/*
* by default, rotator output should be placed directly on
* output buffer address without any offset.
@@ -297,7 +458,8 @@
if (rot->bwc_mode) {
pr_err("Unable to do split rotation with bwc set\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto rot_err;
}
width = rot->src_rect.w;
@@ -307,14 +469,16 @@
if (width > (MAX_MIXER_WIDTH * 2)) {
pr_err("unsupported source width %d\n", width);
- return -EOVERFLOW;
+ ret = -EOVERFLOW;
+ goto rot_err;
}
if (!rot->next) {
tmp = mdss_mdp_rotator_session_alloc();
if (!tmp) {
pr_err("unable to allocate rot dual session\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto rot_err;
}
rot->next = tmp;
}
@@ -362,7 +526,16 @@
rot->params_changed++;
- return 0;
+ req->id = rot->session_id;
+
+ rot_err:
+ mutex_unlock(&rotator_lock);
+ if (ret) {
+ pr_err("Unable to setup rotator session\n");
+ if (rot)
+ mdss_mdp_rotator_release(rot);
+ }
+ return ret;
}
static int mdss_mdp_rotator_finish(struct mdss_mdp_rotator_session *rot)
@@ -370,6 +543,8 @@
struct mdss_mdp_pipe *rot_pipe;
struct mdss_mdp_ctl *tmp;
int ret = 0;
+ struct msm_sync_pt_data *rot_sync_pt_data;
+ struct work_struct commit_work;
if (!rot)
return -ENODEV;
@@ -384,7 +559,13 @@
mdss_mdp_rotator_busy_wait(rot);
list_del(&rot->head);
}
+
+ rot_sync_pt_data = rot->rot_sync_pt_data;
+ commit_work = rot->commit_work;
memset(rot, 0, sizeof(*rot));
+ rot->rot_sync_pt_data = rot_sync_pt_data;
+ rot->commit_work = commit_work;
+
if (rot_pipe) {
struct mdss_mdp_mixer *mixer = rot_pipe->mixer;
mdss_mdp_pipe_unmap(rot_pipe);
@@ -430,3 +611,70 @@
return 0;
}
+
+int mdss_mdp_rotator_play(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_data *req)
+{
+ struct mdss_mdp_rotator_session *rot;
+ int ret;
+ u32 flgs;
+
+ mutex_lock(&rotator_lock);
+ rot = mdss_mdp_rotator_session_get(req->id);
+ if (!rot) {
+ pr_err("invalid session id=%x\n", req->id);
+ ret = -ENOENT;
+ goto dst_buf_fail;
+ }
+
+ flgs = rot->flags & MDP_SECURE_OVERLAY_SESSION;
+
+ ret = mdss_mdp_rotator_busy_wait_ex(rot);
+ if (ret) {
+ pr_err("rotator busy wait error\n");
+ goto dst_buf_fail;
+ }
+
+ mdss_mdp_overlay_free_buf(&rot->src_buf);
+ ret = mdss_mdp_overlay_get_buf(mfd, &rot->src_buf, &req->data, 1, flgs);
+ if (ret) {
+ pr_err("src_data pmem error\n");
+ goto dst_buf_fail;
+ }
+
+ mdss_mdp_overlay_free_buf(&rot->dst_buf);
+ ret = mdss_mdp_overlay_get_buf(mfd, &rot->dst_buf,
+ &req->dst_data, 1, flgs);
+ if (ret) {
+ pr_err("dst_data pmem error\n");
+ goto dst_buf_fail;
+ }
+
+ ret = mdss_mdp_rotator_queue(rot);
+
+ if (ret)
+ pr_err("rotator queue error session id=%x\n", req->id);
+
+dst_buf_fail:
+ mutex_unlock(&rotator_lock);
+ return ret;
+}
+
+int mdss_mdp_rotator_unset(int ndx)
+{
+ struct mdss_mdp_rotator_session *rot;
+ int ret = 0;
+ mutex_lock(&rotator_lock);
+ rot = mdss_mdp_rotator_session_get(ndx);
+ if (rot) {
+ mdss_mdp_overlay_free_buf(&rot->src_buf);
+ mdss_mdp_overlay_free_buf(&rot->dst_buf);
+
+ rot->pid = 0;
+ if (!list_empty(&rot->list))
+ list_del_init(&rot->list);
+ ret = mdss_mdp_rotator_finish(rot);
+ }
+ mutex_unlock(&rotator_lock);
+ return ret;
+}
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.h b/drivers/video/msm/mdss/mdss_mdp_rotator.h
index 74eeeeb..7229995 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.h
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.h
@@ -43,18 +43,29 @@
struct mdss_mdp_data src_buf;
struct mdss_mdp_data dst_buf;
+ bool use_sync_pt;
struct list_head head;
struct list_head list;
struct mdss_mdp_rotator_session *next;
+ struct msm_sync_pt_data *rot_sync_pt_data;
+ struct work_struct commit_work;
};
-static inline u32 mdss_mdp_get_rotator_dst_format(u32 in_format)
+static inline u32 mdss_mdp_get_rotator_dst_format(u32 in_format, u8 in_rot90)
{
switch (in_format) {
case MDP_RGB_565:
case MDP_BGR_565:
- return MDP_RGB_888;
+ if (in_rot90)
+ return MDP_RGB_888;
+ else
+ return in_format;
case MDP_Y_CBCR_H2V2_VENUS:
+ case MDP_Y_CBCR_H2V2:
+ if (in_rot90)
+ return MDP_Y_CRCB_H2V2;
+ else
+ return in_format;
case MDP_Y_CB_CR_H2V2:
case MDP_Y_CR_CB_GH2V2:
case MDP_Y_CR_CB_H2V2:
@@ -64,15 +75,13 @@
}
}
-struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_alloc(void);
-struct mdss_mdp_rotator_session *mdss_mdp_rotator_session_get(u32 session_id);
-
-int mdss_mdp_rotator_setup(struct mdss_mdp_rotator_session *rot);
-int mdss_mdp_rotator_queue(struct mdss_mdp_rotator_session *rot,
- struct mdss_mdp_data *src_data,
- struct mdss_mdp_data *dst_data);
-
+int mdss_mdp_rotator_setup(struct msm_fb_data_type *mfd,
+ struct mdp_overlay *req);
int mdss_mdp_rotator_release(struct mdss_mdp_rotator_session *rot);
int mdss_mdp_rotator_release_all(void);
-
+struct msm_sync_pt_data *mdss_mdp_rotator_sync_pt_get(
+ struct msm_fb_data_type *mfd, const struct mdp_buf_sync *buf_sync);
+int mdss_mdp_rotator_play(struct msm_fb_data_type *mfd,
+ struct msmfb_overlay_data *req);
+int mdss_mdp_rotator_unset(int ndx);
#endif /* MDSS_MDP_ROTATOR_H */
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index b65d894..1170d1e 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -237,6 +237,20 @@
return NULL;
}
+void mdss_mdp_intersect_rect(struct mdss_mdp_img_rect *res_rect,
+ const struct mdss_mdp_img_rect *dst_rect,
+ const struct mdss_mdp_img_rect *sci_rect)
+{
+ int l = max(dst_rect->x, sci_rect->x);
+ int t = max(dst_rect->y, sci_rect->y);
+ int r = min((dst_rect->x + dst_rect->w), (sci_rect->x + sci_rect->w));
+ int b = min((dst_rect->y + dst_rect->h), (sci_rect->y + sci_rect->h));
+
+ if (r < l || b < t)
+ *res_rect = (struct mdss_mdp_img_rect){0, 0, 0, 0};
+ else
+ *res_rect = (struct mdss_mdp_img_rect){l, t, (r-l), (b-t)};
+}
int mdss_mdp_get_rau_strides(u32 w, u32 h,
struct mdss_mdp_format_params *fmt,
struct mdss_mdp_plane_sizes *ps)
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index a9f3e35..58acb8e 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -524,6 +524,7 @@
pr_err("unable to get writeback buf ctl=%d\n", ctl->num);
/* drop buffer but don't return error */
ret = 0;
+ mdss_mdp_ctl_notify(ctl, MDP_NOTIFY_FRAME_DONE);
goto kickoff_fail;
}
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index c7a219b..75fc095 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -24,6 +24,7 @@
};
#define DEFAULT_FRAME_RATE 60
+#define MDSS_DSI_RST_SEQ_LEN 10
/* panel type list */
#define NO_PANEL 0xffff /* No Panel */
@@ -84,6 +85,11 @@
bool init_done;
};
+struct mdss_panel_recovery {
+ void (*fxn)(void *ctx);
+ void *data;
+};
+
/**
* enum mdss_intf_events - Different events generated by MDP core
*
@@ -119,7 +125,8 @@
* @MDSS_EVENT_PANEL_CLK_CTRL: panel clock control
- 0 clock disable
- 1 clock enable
- * @MDSS_EVENT_DSI_CMDLIST_KOFF: kickoff sending dcs command from command list
+ * @MDSS_EVENT_ENABLE_PARTIAL_UPDATE: Event to update ROI of the panel.
+ * @MDSS_EVENT_DSI_CMDLIST_KOFF: acquire dsi_mdp_busy lock before kickoff.
*/
enum mdss_intf_events {
MDSS_EVENT_RESET = 1,
@@ -137,6 +144,7 @@
MDSS_EVENT_FB_REGISTERED,
MDSS_EVENT_PANEL_CLK_CTRL,
MDSS_EVENT_DSI_CMDLIST_KOFF,
+ MDSS_EVENT_ENABLE_PARTIAL_UPDATE,
};
struct lcd_panel_info {
@@ -270,7 +278,13 @@
u32 frame_count;
u32 is_3d_panel;
u32 out_format;
+ u32 rst_seq[MDSS_DSI_RST_SEQ_LEN];
+ u32 rst_seq_len;
u32 vic; /* video identification code */
+ u32 roi_x;
+ u32 roi_y;
+ u32 roi_w;
+ u32 roi_h;
int bklt_ctrl; /* backlight ctrl */
int pwm_pmic_gpio;
int pwm_lpg_chan;
@@ -281,6 +295,7 @@
int new_fps;
u32 cont_splash_enabled;
+ u32 partial_update_enabled;
struct ion_handle *splash_ihdl;
u32 panel_power_on;
diff --git a/include/linux/android_alarm.h b/include/linux/android_alarm.h
index 096f777..b017caa 100644
--- a/include/linux/android_alarm.h
+++ b/include/linux/android_alarm.h
@@ -25,6 +25,7 @@
ANDROID_ALARM_RTC,
ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
ANDROID_ALARM_ELAPSED_REALTIME,
+ ANDROID_ALARM_RTC_POWEROFF_WAKEUP,
ANDROID_ALARM_SYSTEMTIME,
ANDROID_ALARM_TYPE_COUNT,
@@ -86,6 +87,7 @@
1U << ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
ANDROID_ALARM_ELAPSED_REALTIME_MASK =
1U << ANDROID_ALARM_ELAPSED_REALTIME,
+ ANDROID_ALARM_RTC_POWEROFF_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_POWEROFF_WAKEUP,
ANDROID_ALARM_SYSTEMTIME_MASK = 1U << ANDROID_ALARM_SYSTEMTIME,
ANDROID_ALARM_TIME_CHANGE_MASK = 1U << 16
};
diff --git a/include/linux/bif/consumer.h b/include/linux/bif/consumer.h
index e4c190e..a4579db 100644
--- a/include/linux/bif/consumer.h
+++ b/include/linux/bif/consumer.h
@@ -311,10 +311,11 @@
* @type: Object type
* @version: Object version
* @manufacturer_id: Manufacturer ID number allocated by MIPI
- * @length: Length of the entire object including header and CRC
+ * @length: Length of the entire object including header and CRC;
+ * data length == total length - 8.
* @data: Raw byte data found in the object
* @crc: CRC of the object calculated using CRC-CCITT
- * @list: Linked-list connection parameter
+ * @list: Linked-list connection parameter; internal use only
* @addr: BIF slave address correspond to the start of the object
*
* manufacturer_id == 0x0000 if MIPI type and version.
@@ -342,6 +343,8 @@
* is used to denote a 256 byte buffer.
* @nvm_base_address: BIF slave address where NVM begins
* @nvm_size: NVM size in bytes
+ * @nvm_lock_offset: Offset from the beginning of NVM of the first
+ * writable address
* @object_count: Number of BIF objects read from NVM
* @object_list: List of BIF objects read from NVM
*/
@@ -351,6 +354,7 @@
u8 write_buffer_size;
u16 nvm_base_address;
u16 nvm_size;
+ u16 nvm_lock_offset;
int object_count;
struct list_head object_list;
};
@@ -412,6 +416,9 @@
#define BIF_MATCH_FUNCTION_TYPE BIT(2)
#define BIF_MATCH_FUNCTION_VERSION BIT(3)
#define BIF_MATCH_IGNORE_PRESENCE BIT(4)
+#define BIF_MATCH_OBJ_TYPE BIT(5)
+#define BIF_MATCH_OBJ_VERSION BIT(6)
+#define BIF_MATCH_OBJ_MANUFACTURER_ID BIT(7)
/**
* struct bif_match_criteria - specifies the matching criteria that a BIF
@@ -428,6 +435,17 @@
* @ignore_presence: If true, then slaves that are currently not present
* will be successfully matched against. By default, only
* present slaves can be matched.
+ * @obj_type: Defines the type of a BIF object found in the
+ * non-volatile memory of a slave.
+ * @obj_version: Defines the version of a BIF object found in the
+ * non-volatile memory of a slave.
+ * @obj_manufacturer_id: Manufacturer ID of a BIF object found in the
+ * non-volatile memory of a slave.
+ *
+ * If function_type and function_verion are both specified, then they must both
+ * match for a single BIF function. If obj_type and obj_version or
+ * obj_manufacturer_id are specified, then all must match for a single BIF
+ * object.
*/
struct bif_match_criteria {
u32 match_mask;
@@ -436,6 +454,34 @@
u8 function_type;
u8 function_version;
bool ignore_presence;
+ u8 obj_type;
+ u8 obj_version;
+ u16 obj_manufacturer_id;
+};
+
+/* Mask values to be ORed for use in bif_obj_match_criteria.match_mask. */
+#define BIF_OBJ_MATCH_TYPE BIT(0)
+#define BIF_OBJ_MATCH_VERSION BIT(1)
+#define BIF_OBJ_MATCH_MANUFACTURER_ID BIT(2)
+
+/**
+ * struct bif_obj_match_criteria - specifies the matching criteria that a BIF
+ * consumer uses to find an appropriate BIF data object
+ * within a slave
+ * @match_mask: Mask value specifying which parameters to match upon.
+ * This value should be some ORed combination of
+ * BIF_OBJ_MATCH_* specified above.
+ * @type: Defines the type of the object. The type may be either
+ * MIPI or manufacturer defined.
+ * @version: Defines the version of the object. The version may be
+ * either MIPI or manufacturer defined.
+ * @manufacturer_id: Manufacturer ID number allocated by MIPI.
+ */
+struct bif_obj_match_criteria {
+ u32 match_mask;
+ u8 type;
+ u8 version;
+ u16 manufacturer_id;
};
/**
@@ -472,6 +518,8 @@
struct notifier_block *nb);
int bif_trigger_task(struct bif_slave *slave, unsigned int task);
+int bif_enable_auto_task(struct bif_slave *slave, unsigned int task);
+int bif_disable_auto_task(struct bif_slave *slave, unsigned int task);
int bif_task_is_busy(struct bif_slave *slave, unsigned int task);
int bif_ctrl_count(void);
@@ -481,10 +529,10 @@
int bif_ctrl_signal_battery_changed(struct bif_ctrl *ctrl);
-int bif_slave_match_count(const struct bif_ctrl *ctrl,
+int bif_slave_match_count(struct bif_ctrl *ctrl,
const struct bif_match_criteria *match_criteria);
-struct bif_slave *bif_slave_match_get(const struct bif_ctrl *ctrl,
+struct bif_slave *bif_slave_match_get(struct bif_ctrl *ctrl,
unsigned int id, const struct bif_match_criteria *match_criteria);
void bif_slave_put(struct bif_slave *slave);
@@ -500,9 +548,31 @@
int bif_slave_find_function(struct bif_slave *slave, u8 function, u8 *version,
u16 *function_pointer);
+int bif_object_match_count(struct bif_slave *slave,
+ const struct bif_obj_match_criteria *match_criteria);
+
+struct bif_object *bif_object_match_get(struct bif_slave *slave,
+ unsigned int id, const struct bif_obj_match_criteria *match_criteria);
+
+void bif_object_put(struct bif_object *object);
+
int bif_slave_read(struct bif_slave *slave, u16 addr, u8 *buf, int len);
int bif_slave_write(struct bif_slave *slave, u16 addr, u8 *buf, int len);
+int bif_slave_nvm_raw_read(struct bif_slave *slave, u16 offset, u8 *buf,
+ int len);
+int bif_slave_nvm_raw_write(struct bif_slave *slave, u16 offset, u8 *buf,
+ int len);
+
+int bif_object_write(struct bif_slave *slave, u8 type, u8 version, u16
+ manufacturer_id, const u8 *data, int data_len);
+
+int bif_object_overwrite(struct bif_slave *slave,
+ struct bif_object *object, u8 type, u8 version,
+ u16 manufacturer_id, const u8 *data, int data_len);
+
+int bif_object_delete(struct bif_slave *slave, const struct bif_object *object);
+
int bif_slave_is_present(struct bif_slave *slave);
int bif_slave_is_selected(struct bif_slave *slave);
@@ -534,6 +604,12 @@
static inline int bif_trigger_task(struct bif_slave *slave, unsigned int task)
{ return -EPERM; }
+static inline int bif_enable_auto_task(struct bif_slave *slave,
+ unsigned int task)
+{ return -EPERM; }
+static inline int bif_disable_auto_task(struct bif_slave *slave,
+ unsigned int task)
+{ return -EPERM; }
static inline int bif_task_is_busy(struct bif_slave *slave, unsigned int task)
{ return -EPERM; }
@@ -544,13 +620,14 @@
{ return ERR_PTR(-EPERM); }
static inline void bif_ctrl_put(struct bif_ctrl *ctrl) { return; }
-int bif_ctrl_signal_battery_changed(struct bif_ctrl *ctrl) { return -EPERM; }
+static inline int bif_ctrl_signal_battery_changed(struct bif_ctrl *ctrl)
+{ return -EPERM; }
-static inline int bif_slave_match_count(const struct bif_ctrl *ctrl,
+static inline int bif_slave_match_count(struct bif_ctrl *ctrl,
const struct bif_match_criteria *match_criteria)
{ return -EPERM; }
-static inline struct bif_slave *bif_slave_match_get(const struct bif_ctrl *ctrl,
+static inline struct bif_slave *bif_slave_match_get(struct bif_ctrl *ctrl,
unsigned int id, const struct bif_match_criteria *match_criteria)
{ return ERR_PTR(-EPERM); }
@@ -571,6 +648,17 @@
u8 *version, u16 *function_pointer)
{ return -EPERM; }
+static inline int bif_object_match_count(struct bif_slave *slave,
+ const struct bif_obj_match_criteria *match_criteria)
+{ return -EPERM; }
+
+static inline struct bif_object *bif_object_match_get(struct bif_slave *slave,
+ unsigned int id, const struct bif_obj_match_criteria *match_criteria)
+{ return ERR_PTR(-EPERM); }
+
+static inline void bif_object_put(struct bif_object *object)
+{}
+
static inline int bif_slave_read(struct bif_slave *slave, u16 addr, u8 *buf,
int len)
{ return -EPERM; }
@@ -578,18 +666,42 @@
int len)
{ return -EPERM; }
-int bif_slave_is_present(struct bif_slave *slave) { return -EPERM; }
-
-int bif_slave_is_selected(struct bif_slave *slave) { return -EPERM; }
-int bif_slave_select(struct bif_slave *slave) { return -EPERM; }
-
-int bif_ctrl_raw_transaction(struct bif_ctrl *ctrl, int transaction, u8 data)
+static inline int bif_slave_nvm_raw_read(struct bif_slave *slave, u16 offset,
+ u8 *buf, int len)
{ return -EPERM; }
-int bif_ctrl_raw_transaction_read(struct bif_ctrl *ctrl, int transaction,
- u8 data, int *response)
+static inline int bif_slave_nvm_raw_write(struct bif_slave *slave, u16 offset,
+ u8 *buf, int len)
{ return -EPERM; }
-int bif_ctrl_raw_transaction_query(struct bif_ctrl *ctrl, int transaction,
- u8 data, bool *query_response)
+
+static inline int bif_object_write(struct bif_slave *slave, u8 type, u8 version,
+ u16 manufacturer_id, const u8 *data, int data_len)
+{ return -EPERM; }
+
+static inline int bif_object_overwrite(struct bif_slave *slave,
+ struct bif_object *object, u8 type, u8 version,
+ u16 manufacturer_id, const u8 *data, int data_len)
+{ return -EPERM; }
+
+static inline int bif_object_delete(struct bif_slave *slave,
+ const struct bif_object *object)
+{ return -EPERM; }
+
+static inline int bif_slave_is_present(struct bif_slave *slave)
+{ return -EPERM; }
+
+static inline int bif_slave_is_selected(struct bif_slave *slave)
+{ return -EPERM; }
+static inline int bif_slave_select(struct bif_slave *slave)
+{ return -EPERM; }
+
+static inline int bif_ctrl_raw_transaction(struct bif_ctrl *ctrl,
+ int transaction, u8 data)
+{ return -EPERM; }
+static inline int bif_ctrl_raw_transaction_read(struct bif_ctrl *ctrl,
+ int transaction, u8 data, int *response)
+{ return -EPERM; }
+static inline int bif_ctrl_raw_transaction_query(struct bif_ctrl *ctrl,
+ int transaction, u8 data, bool *query_response)
{ return -EPERM; }
static inline void bif_ctrl_bus_lock(struct bif_ctrl *ctrl)
@@ -601,11 +713,14 @@
{ return 0; }
static inline int bif_ctrl_measure_rid(struct bif_ctrl *ctrl) { return -EPERM; }
-int bif_ctrl_get_bus_period(struct bif_ctrl *ctrl) { return -EPERM; }
-int bif_ctrl_set_bus_period(struct bif_ctrl *ctrl, int period_ns)
+static inline int bif_ctrl_get_bus_period(struct bif_ctrl *ctrl)
{ return -EPERM; }
-int bif_ctrl_get_bus_state(struct bif_ctrl *ctrl) { return -EPERM; }
-int bif_ctrl_set_bus_state(struct bif_ctrl *ctrl, enum bif_bus_state state)
+static inline int bif_ctrl_set_bus_period(struct bif_ctrl *ctrl, int period_ns)
+{ return -EPERM; }
+static inline int bif_ctrl_get_bus_state(struct bif_ctrl *ctrl)
+{ return -EPERM; }
+static inline int bif_ctrl_set_bus_state(struct bif_ctrl *ctrl,
+ enum bif_bus_state state)
{ return -EPERM; }
#endif
diff --git a/include/linux/input/ft5x06_ts.h b/include/linux/input/ft5x06_ts.h
index 149133e..7b84534 100644
--- a/include/linux/input/ft5x06_ts.h
+++ b/include/linux/input/ft5x06_ts.h
@@ -58,6 +58,7 @@
bool fw_vkey_support;
bool no_force_update;
bool i2c_pull_up;
+ bool ignore_id_check;
int (*power_init) (bool);
int (*power_on) (bool);
};
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index c2ad2b4..85be7c3 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -64,8 +64,10 @@
WCD9XXX_IRQ_PA2_STARTUP,
WCD9XXX_IRQ_PA3_STARTUP,
WCD9XXX_IRQ_PA4_STARTUP,
+ WCD9306_IRQ_HPH_PA_OCPR_FAULT = WCD9XXX_IRQ_PA4_STARTUP,
WCD9XXX_IRQ_PA5_STARTUP,
WCD9XXX_IRQ_MICBIAS1_PRECHARGE,
+ WCD9306_IRQ_HPH_PA_OCPL_FAULT = WCD9XXX_IRQ_MICBIAS1_PRECHARGE,
WCD9XXX_IRQ_MICBIAS2_PRECHARGE,
WCD9XXX_IRQ_MICBIAS3_PRECHARGE,
/* INTR_REG 2 */
diff --git a/include/linux/mfd/wcd9xxx/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h
index b7ba6fb..ffbd732 100644
--- a/include/linux/mfd/wcd9xxx/pdata.h
+++ b/include/linux/mfd/wcd9xxx/pdata.h
@@ -69,20 +69,20 @@
#define TABLA_DCYCLE_3839 0xE
#define TABLA_DCYCLE_4095 0xF
-#define TAIKO_MCLK_CLK_12P288MHZ 12288000
-#define TAIKO_MCLK_CLK_9P6HZ 9600000
+#define WCD9XXX_MCLK_CLK_12P288MHZ 12288000
+#define WCD9XXX_MCLK_CLK_9P6HZ 9600000
/* Only valid for 9.6 MHz mclk */
-#define TAIKO_DMIC_SAMPLE_RATE_2P4MHZ 2400000
-#define TAIKO_DMIC_SAMPLE_RATE_3P2MHZ 3200000
-#define TAIKO_DMIC_SAMPLE_RATE_4P8MHZ 4800000
+#define WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ 2400000
+#define WCD9XXX_DMIC_SAMPLE_RATE_3P2MHZ 3200000
+#define WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ 4800000
/* Only valid for 12.288 MHz mclk */
-#define TAIKO_DMIC_SAMPLE_RATE_3P072MHZ 3072000
-#define TAIKO_DMIC_SAMPLE_RATE_4P096MHZ 4096000
-#define TAIKO_DMIC_SAMPLE_RATE_6P144MHZ 6144000
+#define WCD9XXX_DMIC_SAMPLE_RATE_3P072MHZ 3072000
+#define WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ 4096000
+#define WCD9XXX_DMIC_SAMPLE_RATE_6P144MHZ 6144000
-#define TAIKO_DMIC_SAMPLE_RATE_UNDEFINED 0
+#define WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED 0
struct wcd9xxx_amic {
/*legacy mode, txfe_enable and txfe_buff take 7 input
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 48268f0..a5fa304 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -302,16 +302,16 @@
* On nommu, vmalloc/vfree wrap through kmalloc/kfree directly, so there
* is no special casing required.
*/
+
+#ifdef CONFIG_MMU
+extern int is_vmalloc_addr(const void *x);
+#else
static inline int is_vmalloc_addr(const void *x)
{
-#ifdef CONFIG_MMU
- unsigned long addr = (unsigned long)x;
-
- return addr >= VMALLOC_START && addr < VMALLOC_END;
-#else
return 0;
-#endif
}
+#endif
+
#ifdef CONFIG_MMU
extern int is_vmalloc_or_module_addr(const void *x);
#else
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index 9d15908..d0ad3e4 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -391,6 +391,7 @@
unsigned int idle_timeout;
struct notifier_block reboot_notify;
bool issue_long_pon;
+ u8 cached_ext_csd;
};
/*
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index baa9d6c..0c08421 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -187,6 +187,7 @@
#define MDP_BACKEND_COMPOSITION 0x00040000
#define MDP_BORDERFILL_SUPPORTED 0x00010000
#define MDP_SECURE_OVERLAY_SESSION 0x00008000
+#define MDP_SECURE_DISPLAY_OVERLAY_SESSION 0x00002000
#define MDP_OV_PIPE_FORCE_DMA 0x00004000
#define MDP_MEMORY_ID_TYPE_FB 0x00001000
#define MDP_BWC_EN 0x00000400
@@ -838,6 +839,7 @@
struct mdp_buf_sync {
uint32_t flags;
uint32_t acq_fen_fd_cnt;
+ uint32_t session_id;
int *acq_fen_fd;
int *rel_fen_fd;
};
@@ -862,6 +864,7 @@
uint32_t wait_for_finish;
struct fb_var_screeninfo var;
struct mdp_buf_fence buf_fence;
+ struct mdp_rect roi;
};
struct mdp_page_protection {
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 5106c71..93af04d 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -103,6 +103,7 @@
POWER_SUPPLY_PROP_INPUT_VOLTAGE_REGULATION,
POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_INPUT_CURRENT_MAX,
+ POWER_SUPPLY_PROP_INPUT_CURRENT_TRIM,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CURRENT_AVG,
POWER_SUPPLY_PROP_POWER_NOW,
@@ -228,6 +229,7 @@
extern int power_supply_set_battery_charged(struct power_supply *psy);
extern int power_supply_set_current_limit(struct power_supply *psy, int limit);
extern int power_supply_set_online(struct power_supply *psy, bool enable);
+extern int power_supply_set_health_state(struct power_supply *psy, int health);
extern int power_supply_set_present(struct power_supply *psy, bool enable);
extern int power_supply_set_scope(struct power_supply *psy, int scope);
extern int power_supply_set_charge_type(struct power_supply *psy, int type);
@@ -252,6 +254,9 @@
static inline int power_supply_set_online(struct power_supply *psy,
bool enable)
{ return -ENOSYS; }
+static inline int power_supply_set_health_state(struct power_supply *psy,
+ int health)
+ { return -ENOSYS; }
static inline int power_supply_set_present(struct power_supply *psy,
bool enable)
{ return -ENOSYS; }
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 84c59dc..d950b5c 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -154,6 +154,7 @@
KERN_NMI_WATCHDOG=75, /* int: enable/disable nmi watchdog */
KERN_PANIC_ON_NMI=76, /* int: whether we will panic on an unrecovered */
KERN_BOOT_REASON = 77, /* int: identify reason system was booted */
+ KERN_COLD_BOOT = 78, /* int: identify if system cold booted */
};
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index f462b64..be92ca7 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -440,6 +440,7 @@
unsigned int host_mode;
unsigned int voltage_max;
unsigned int current_max;
+ unsigned int usbin_health;
dev_t ext_chg_dev;
struct cdev ext_chg_cdev;
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index e1c096b..560accb 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -707,6 +707,7 @@
#define V4L2_QCOM_BUF_DROP_FRAME 0x100000
#define V4L2_QCOM_BUF_INPUT_UNSUPPORTED 0x200000
#define V4L2_QCOM_BUF_FLAG_EOS 0x2000
+#define V4L2_QCOM_BUF_FLAG_READONLY 0x400000
/*
* O V E R L A Y P R E V I E W
@@ -1863,22 +1864,25 @@
V4L2_MPEG_VIDC_VIDEO_H264_VUI_TIMING_INFO_ENABLED = 1
};
-#define V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE \
+#define V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_INPUT \
(V4L2_CID_MPEG_MSM_VIDC_BASE+30)
+#define V4L2_CID_MPEG_VIDC_VIDEO_ALLOC_MODE_OUTPUT \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE+31)
enum v4l2_mpeg_vidc_video_alloc_mode_type {
V4L2_MPEG_VIDC_VIDEO_STATIC = 0,
V4L2_MPEG_VIDC_VIDEO_RING = 1,
+ V4L2_MPEG_VIDC_VIDEO_DYNAMIC = 2,
};
#define V4L2_CID_MPEG_VIDC_VIDEO_FRAME_ASSEMBLY \
- (V4L2_CID_MPEG_MSM_VIDC_BASE+31)
+ (V4L2_CID_MPEG_MSM_VIDC_BASE+32)
enum v4l2_mpeg_vidc_video_assembly {
V4L2_MPEG_VIDC_FRAME_ASSEMBLY_DISABLE = 0,
V4L2_MPEG_VIDC_FRAME_ASSEMBLY_ENABLE = 1,
};
#define V4L2_CID_MPEG_VIDC_VIDEO_VP8_PROFILE_LEVEL \
- (V4L2_CID_MPEG_MSM_VIDC_BASE+32)
+ (V4L2_CID_MPEG_MSM_VIDC_BASE+33)
enum v4l2_mpeg_vidc_video_vp8_profile_level {
V4L2_MPEG_VIDC_VIDEO_VP8_UNUSED,
V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_0,
@@ -1887,6 +1891,19 @@
V4L2_MPEG_VIDC_VIDEO_VP8_VERSION_3,
};
+#define V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE + 34)
+enum v4l2_mpeg_vidc_video_deinterlace {
+ V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_DISABLED = 0,
+ V4L2_CID_MPEG_VIDC_VIDEO_DEINTERLACE_ENABLED = 1
+};
+#define V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_MODE \
+ (V4L2_CID_MPEG_MSM_VIDC_BASE + 35)
+enum v4l2_mpeg_vidc_video_decoder_multi_stream {
+ V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_PRIMARY = 0,
+ V4L2_CID_MPEG_VIDC_VIDEO_STREAM_OUTPUT_SECONDARY = 1,
+};
+
/* Camera class control IDs */
#define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900)
#define V4L2_CID_CAMERA_CLASS (V4L2_CTRL_CLASS_CAMERA | 1)
@@ -2448,7 +2465,10 @@
(V4L2_EVENT_MSM_VIDC_START + 3)
#define V4L2_EVENT_MSM_VIDC_CLOSE_DONE (V4L2_EVENT_MSM_VIDC_START + 4)
#define V4L2_EVENT_MSM_VIDC_SYS_ERROR (V4L2_EVENT_MSM_VIDC_START + 5)
-
+#define V4L2_EVENT_MSM_VIDC_RELEASE_BUFFER_REFERENCE \
+ (V4L2_EVENT_MSM_VIDC_START + 6)
+#define V4L2_EVENT_MSM_VIDC_RELEASE_UNQUEUED_BUFFER \
+ (V4L2_EVENT_MSM_VIDC_START + 7)
/* Payload for V4L2_EVENT_VSYNC */
struct v4l2_event_vsync {
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 663bc05..7675a5c 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -14,6 +14,7 @@
#define VM_USERMAP 0x00000008 /* suitable for remap_vmalloc_range */
#define VM_VPAGES 0x00000010 /* buffer for pages was vmalloc'ed */
#define VM_UNLIST 0x00000020 /* vm_struct is not listed in vmlist */
+#define VM_LOWMEM 0x00000040 /* Tracking of direct mapped lowmem */
/* bits [20..32] reserved for arch specific ioremap internals */
/*
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index 717bd73..39357e0 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -79,6 +79,13 @@
int wcnss_xo_auto_detect_enabled(void);
u32 wcnss_get_wlan_rx_buff_count(void);
int wcnss_wlan_iris_xo_mode(void);
+#ifdef CONFIG_WCNSS_REGISTER_DUMP_ON_BITE
+void wcnss_log_debug_regs_on_bite(void);
+#else
+static inline void wcnss_log_debug_regs_on_bite(void)
+{
+}
+#endif
#define wcnss_wlan_get_drvdata(dev) dev_get_drvdata(dev)
#define wcnss_wlan_set_drvdata(dev, data) dev_set_drvdata((dev), (data))
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index 326e8bf..cccf851 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -48,6 +48,12 @@
#define MAX_AF_ITERATIONS 3
+enum flash_type {
+ LED_FLASH = 1,
+ STROBE_FLASH,
+ GPIO_FLASH
+};
+
enum msm_camera_i2c_reg_addr_type {
MSM_CAMERA_I2C_BYTE_ADDR = 1,
MSM_CAMERA_I2C_WORD_ADDR,
diff --git a/include/media/msm_media_info.h b/include/media/msm_media_info.h
index 65831db..ddf9c8e 100644
--- a/include/media/msm_media_info.h
+++ b/include/media/msm_media_info.h
@@ -6,7 +6,76 @@
#endif
enum color_fmts {
+ /* Venus NV12:
+ * YUV 4:2:0 image with a plane of 8 bit Y samples followed
+ * by an interleaved U/V plane containing 8 bit 2x2 subsampled
+ * colour difference samples.
+ *
+ * <-------- Y/UV_Stride -------->
+ * <------- Width ------->
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X ^ ^
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X Height |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | Y_Scanlines
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X V |
+ * X X X X X X X X X X X X X X X X |
+ * X X X X X X X X X X X X X X X X |
+ * X X X X X X X X X X X X X X X X |
+ * X X X X X X X X X X X X X X X X V
+ * U V U V U V U V U V U V X X X X ^
+ * U V U V U V U V U V U V X X X X |
+ * U V U V U V U V U V U V X X X X |
+ * U V U V U V U V U V U V X X X X UV_Scanlines
+ * X X X X X X X X X X X X X X X X |
+ * X X X X X X X X X X X X X X X X V
+ * X X X X X X X X X X X X X X X X --> Buffer size alignment
+ *
+ * Y_Stride : Width aligned to 128
+ * UV_Stride : Width aligned to 128
+ * Y_Scanlines: Height aligned to 32
+ * UV_Scanlines: Height/2 aligned to 16
+ * Total size = align((Y_Stride * Y_Scanlines
+ * + UV_Stride * UV_Scanlines + 4096), 4096)
+ */
COLOR_FMT_NV12,
+
+ /* Venus NV21:
+ * YUV 4:2:0 image with a plane of 8 bit Y samples followed
+ * by an interleaved V/U plane containing 8 bit 2x2 subsampled
+ * colour difference samples.
+ *
+ * <-------- Y/UV_Stride -------->
+ * <------- Width ------->
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X ^ ^
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X Height |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | Y_Scanlines
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X | |
+ * Y Y Y Y Y Y Y Y Y Y Y Y X X X X V |
+ * X X X X X X X X X X X X X X X X |
+ * X X X X X X X X X X X X X X X X |
+ * X X X X X X X X X X X X X X X X |
+ * X X X X X X X X X X X X X X X X V
+ * V U V U V U V U V U V U X X X X ^
+ * V U V U V U V U V U V U X X X X |
+ * V U V U V U V U V U V U X X X X |
+ * V U V U V U V U V U V U X X X X UV_Scanlines
+ * X X X X X X X X X X X X X X X X |
+ * X X X X X X X X X X X X X X X X V
+ * X X X X X X X X X X X X X X X X --> Padding & Buffer size alignment
+ *
+ * Y_Stride : Width aligned to 128
+ * UV_Stride : Width aligned to 128
+ * Y_Scanlines: Height aligned to 32
+ * UV_Scanlines: Height/2 aligned to 16
+ * Total size = align((Y_Stride * Y_Scanlines
+ * + UV_Stride * UV_Scanlines + 4096), 4096)
+ */
COLOR_FMT_NV21,
};
diff --git a/include/media/msm_vidc.h b/include/media/msm_vidc.h
index 2164275..868be9f 100644
--- a/include/media/msm_vidc.h
+++ b/include/media/msm_vidc.h
@@ -28,7 +28,7 @@
int msm_vidc_g_ctrl(void *instance, struct v4l2_control *a);
int msm_vidc_reqbufs(void *instance, struct v4l2_requestbuffers *b);
int msm_vidc_prepare_buf(void *instance, struct v4l2_buffer *b);
-int msm_vidc_release_buf(void *instance, struct v4l2_buffer *b);
+int msm_vidc_release_buffers(void *instance, int buffer_type);
int msm_vidc_qbuf(void *instance, struct v4l2_buffer *b);
int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b);
int msm_vidc_streamon(void *instance, enum v4l2_buf_type i);
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
index 23b19b5..7b0ad14 100644
--- a/include/media/msmb_isp.h
+++ b/include/media/msmb_isp.h
@@ -129,6 +129,7 @@
struct msm_vfe_axi_stream_request_cmd {
uint32_t session_id;
uint32_t stream_id;
+ uint32_t vt_enable;
uint32_t output_format;/*Planar/RAW/Misc*/
enum msm_vfe_axi_stream_src stream_src; /*CAMIF/IDEAL/RDIs*/
struct msm_vfe_axi_plane_cfg plane_cfg[MAX_PLANES_PER_STREAM];
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index cc37cd8..8e3aced 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -10,6 +10,7 @@
#include <linux/types.h>
#include <linux/scatterlist.h>
+#include <linux/device.h>
struct scsi_cmnd;
diff --git a/include/video/Kbuild b/include/video/Kbuild
index 53e13cb..fce6fd1 100644
--- a/include/video/Kbuild
+++ b/include/video/Kbuild
@@ -2,3 +2,4 @@
header-y += sisfb.h
header-y += uvesafb.h
header-y += msm_hdmi_modes.h
+header-y += msm_hdmi_hdcp_mgr.h
diff --git a/include/video/msm_hdmi_hdcp_mgr.h b/include/video/msm_hdmi_hdcp_mgr.h
new file mode 100644
index 0000000..7b8e7f5
--- /dev/null
+++ b/include/video/msm_hdmi_hdcp_mgr.h
@@ -0,0 +1,66 @@
+/* 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.
+ */
+
+#ifndef MSM_HDMI_HDCP_MGR_H
+#define MSM_HDMI_HDCP_MGR_H
+
+enum DS_TYPE { /* type of downstream device */
+ DS_UNKNOWN,
+ DS_RECEIVER,
+ DS_REPEATER,
+};
+
+enum {
+ MSG_ID_IDX,
+ RET_CODE_IDX,
+ HEADER_LEN,
+};
+
+enum RET_CODE {
+ HDCP_NOT_AUTHED,
+ HDCP_AUTHED,
+ HDCP_DISABLE,
+};
+
+enum MSG_ID { /* List of functions expected to be called after it */
+ DOWN_CHECK_TOPOLOGY,
+ UP_REQUEST_TOPOLOGY,
+ UP_SEND_TOPOLOGY,
+ DOWN_REQUEST_TOPOLOGY,
+ MSG_NUM,
+};
+
+enum SOURCE_ID {
+ HDCP_V1_TX,
+ HDCP_V1_RX,
+ HDCP_V2_RX,
+ HDCP_V2_TX,
+ SRC_NUM,
+};
+
+/*
+ * how to parse sysfs params buffer
+ * from hdcp_tx driver.
+ */
+
+struct HDCP_V2V1_MSG_TOPOLOGY {
+ /* indicates downstream's type */
+ uint32_t ds_type;
+ uint8_t bksv[5];
+ uint8_t dev_count;
+ uint8_t depth;
+ uint8_t ksv_list[5 * 127];
+ uint32_t max_cascade_exceeded;
+ uint32_t max_dev_exceeded;
+};
+
+#endif /* MSM_HDMI_HDCP_MGR_H */
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index b390dad..d16a59ec 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1009,7 +1009,15 @@
.maxlen = sizeof(int),
.mode = 0444,
.proc_handler = proc_dointvec,
-},
+ },
+
+ {
+ .procname = "cold_boot",
+ .data = &cold_boot,
+ .maxlen = sizeof(int),
+ .mode = 0444,
+ .proc_handler = proc_dointvec,
+ },
#endif
/*
* NOTE: do not add new entries to this table unless you have read
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index acb60be..6170f45 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -138,6 +138,7 @@
{ CTL_INT, KERN_MAX_LOCK_DEPTH, "max_lock_depth" },
{ CTL_INT, KERN_PANIC_ON_NMI, "panic_on_unrecovered_nmi" },
{ CTL_INT, KERN_BOOT_REASON, "boot_reason" },
+ { CTL_INT, KERN_COLD_BOOT, "cold_boot" },
{}
};
diff --git a/lib/klist.c b/lib/klist.c
index 0874e41..358a368 100644
--- a/lib/klist.c
+++ b/lib/klist.c
@@ -193,10 +193,10 @@
if (waiter->node != n)
continue;
+ list_del(&waiter->list);
waiter->woken = 1;
mb();
wake_up_process(waiter->process);
- list_del(&waiter->list);
}
spin_unlock(&klist_remove_lock);
knode_set_klist(n, NULL);
diff --git a/mm/debug-pagealloc.c b/mm/debug-pagealloc.c
index 789ff70..bc91cba 100644
--- a/mm/debug-pagealloc.c
+++ b/mm/debug-pagealloc.c
@@ -69,6 +69,7 @@
print_hex_dump(KERN_ERR, "", DUMP_PREFIX_ADDRESS, 16, 1, start,
end - start + 1, 1);
+ BUG_ON(PANIC_CORRUPTION);
dump_stack();
}
diff --git a/mm/slub.c b/mm/slub.c
index 80848cd..931c8eb 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2310,13 +2310,18 @@
return NULL;
redo:
-
/*
* Must read kmem_cache cpu data via this cpu ptr. Preemption is
* enabled. We may switch back and forth between cpus while
* reading from one cpu area. That does not matter as long
* as we end up on the original cpu again when doing the cmpxchg.
+ *
+ * Preemption is disabled for the retrieval of the tid because that
+ * must occur from the current processor. We cannot allow rescheduling
+ * on a different processor between the determination of the pointer
+ * and the retrieval of the tid.
*/
+ preempt_disable();
c = __this_cpu_ptr(s->cpu_slab);
/*
@@ -2326,7 +2331,7 @@
* linked list in between.
*/
tid = c->tid;
- barrier();
+ preempt_enable();
object = c->freelist;
if (unlikely(!object || !node_match(c, node)))
@@ -2572,10 +2577,11 @@
* data is retrieved via this pointer. If we are on the same cpu
* during the cmpxchg then the free will succedd.
*/
+ preempt_disable();
c = __this_cpu_ptr(s->cpu_slab);
tid = c->tid;
- barrier();
+ preempt_enable();
if (likely(page == c->page)) {
set_freepointer(s, object, c->freelist);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index a2ab2ab..e174693 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -184,6 +184,36 @@
return ret;
}
+#ifdef ENABLE_VMALLOC_SAVING
+int is_vmalloc_addr(const void *x)
+{
+ struct rb_node *n;
+ struct vmap_area *va;
+ int ret = 0;
+
+ spin_lock(&vmap_area_lock);
+
+ for (n = rb_first(vmap_area_root); n; rb_next(n)) {
+ va = rb_entry(n, struct vmap_area, rb_node);
+ if (x >= va->va_start && x < va->va_end) {
+ ret = 1;
+ break;
+ }
+ }
+
+ spin_unlock(&vmap_area_lock);
+ return ret;
+}
+#else
+int is_vmalloc_addr(const void *x)
+{
+ unsigned long addr = (unsigned long)x;
+
+ return addr >= VMALLOC_START && addr < VMALLOC_END;
+}
+#endif
+EXPORT_SYMBOL(is_vmalloc_addr);
+
int is_vmalloc_or_module_addr(const void *x)
{
/*
@@ -2643,6 +2673,9 @@
if (v->flags & VM_VPAGES)
seq_printf(m, " vpages");
+ if (v->flags & VM_LOWMEM)
+ seq_printf(m, " lowmem");
+
show_numa_info(m, v);
seq_putc(m, '\n');
return 0;
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index 5016fa5..c2b18e6 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -1014,7 +1014,7 @@
caif_assert(sk_unhashed(sk));
caif_assert(!sk->sk_socket);
if (!sock_flag(sk, SOCK_DEAD)) {
- pr_debug("Attempt to release alive CAIF socket: %p\n", sk);
+ WARN(1, "Attempt to release alive CAIF socket: %p\n", sk);
return;
}
sk_stream_kill_queues(&cf_sk->sk);
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 0b71165..f20b5cc 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -154,12 +154,12 @@
sk_mem_reclaim(sk);
if (sk->sk_type == SOCK_STREAM && sk->sk_state != TCP_CLOSE) {
- pr_err("Attempt to release TCP socket in state %d %p\n",
+ WARN(1, "Attempt to release TCP socket in state %d %p\n",
sk->sk_state, sk);
return;
}
if (!sock_flag(sk, SOCK_DEAD)) {
- pr_err("Attempt to release alive inet socket %p\n", sk);
+ WARN(1, "Attempt to release alive inet socket %p\n", sk);
return;
}
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index 07d7d55..433f7f7 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -408,7 +408,7 @@
sk_mem_reclaim(sk);
if (!sock_flag(sk, SOCK_DEAD)) {
- pr_err("Attempt to release alive iucv socket %p\n", sk);
+ WARN(1, "Attempt to release alive iucv socket %p\n", sk);
return;
}
diff --git a/net/key/af_key.c b/net/key/af_key.c
index 7e5d927..153fbf1 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -99,7 +99,7 @@
skb_queue_purge(&sk->sk_receive_queue);
if (!sock_flag(sk, SOCK_DEAD)) {
- pr_err("Attempt to release alive pfkey socket: %p\n", sk);
+ WARN(1, "Attempt to release alive pfkey socket: %p\n", sk);
return;
}
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 4f2c0df..a72cd66 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -1168,7 +1168,7 @@
WARN_ON(atomic_read(&sk->sk_wmem_alloc));
if (!sock_flag(sk, SOCK_DEAD)) {
- pr_err("Attempt to release alive packet socket: %p\n", sk);
+ WARN(1, "Attempt to release alive packet socket: %p\n", sk);
return;
}
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 74c064c..798ea39 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -670,7 +670,7 @@
WARN_ON(sk->sk_socket);
if (!sock_flag(sk, SOCK_DEAD)) {
- printk("Attempt to release alive rxrpc socket: %p\n", sk);
+ WARN(1, "Attempt to release alive rxrpc socket: %p\n", sk);
return;
}
}
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 109e30b..2a89d01 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -357,7 +357,7 @@
WARN_ON(!sk_unhashed(sk));
WARN_ON(sk->sk_socket);
if (!sock_flag(sk, SOCK_DEAD)) {
- printk(KERN_INFO "Attempt to release alive unix socket: %p\n", sk);
+ WARN(1, "Attempt to release alive unix socket: %p\n", sk);
return;
}
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
old mode 100644
new mode 100755
index e9a0ac8..b96094c
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -2187,10 +2187,15 @@
* However if a driver requested this specific regulatory
* domain we keep it for its private use
*/
- if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER)
+ if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER) {
+ const struct ieee80211_regdomain *tmp;
+
+ tmp = request_wiphy->regd;
request_wiphy->regd = rd;
- else
+ kfree(tmp);
+ } else {
kfree(rd);
+ }
rd = NULL;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 06d617b..db94741 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1672,6 +1672,11 @@
switch (runtime->access) {
case SNDRV_PCM_ACCESS_MMAP_INTERLEAVED:
case SNDRV_PCM_ACCESS_RW_INTERLEAVED:
+ if ((UINT_MAX/width) < info->channel) {
+ snd_printd("%s: integer overflow while multiply\n",
+ __func__);
+ return -EINVAL;
+ }
info->first = info->channel * width;
info->step = runtime->channels * width;
break;
@@ -1679,6 +1684,12 @@
case SNDRV_PCM_ACCESS_RW_NONINTERLEAVED:
{
size_t size = runtime->dma_bytes / runtime->channels;
+
+ if ((size > 0) && ((UINT_MAX/(size * 8)) < info->channel)) {
+ snd_printd("%s: integer overflow while multiply\n",
+ __func__);
+ return -EINVAL;
+ }
info->first = info->channel * size * 8;
info->step = width;
break;
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 8bba8d7..7504576 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -448,7 +448,8 @@
runtime->silence_threshold = 0;
runtime->silence_size = 0;
runtime->boundary = runtime->buffer_size;
- while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size)
+ while (runtime->boundary * 2 * runtime->channels <=
+ LONG_MAX - runtime->buffer_size)
runtime->boundary *= 2;
snd_pcm_timer_resolution_change(substream);
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 56cd5e6..a3ed23d 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -53,7 +53,7 @@
snd-soc-cs8427-objs := cs8427.o
snd-soc-wcd9320-objs := wcd9xxx-resmgr.o wcd9320.o wcd9320-tables.o wcd9xxx-mbhc.o wcd9xxx-common.o
snd-soc-wcd9306-objs := wcd9306.o wcd9306-tables.o wcd9xxx-common.o
-snd-soc-msm8x10-wcd-objs := msm8x10-wcd.o msm8x10-wcd-tables.o
+snd-soc-msm8x10-wcd-objs := msm8x10-wcd.o msm8x10-wcd-tables.o wcd9xxx-common.o
snd-soc-wl1273-objs := wl1273.o
snd-soc-wm1250-ev1-objs := wm1250-ev1.o
snd-soc-wm2000-objs := wm2000.o
diff --git a/sound/soc/codecs/msm8x10-wcd.c b/sound/soc/codecs/msm8x10-wcd.c
index 4e3df21..1b1528b 100644
--- a/sound/soc/codecs/msm8x10-wcd.c
+++ b/sound/soc/codecs/msm8x10-wcd.c
@@ -39,6 +39,7 @@
#include "wcd9xxx-resmgr.h"
#include "msm8x10_wcd_registers.h"
#include "../msm/qdsp6v2/q6core.h"
+#include "wcd9xxx-common.h"
#define MSM8X10_WCD_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
@@ -63,6 +64,15 @@
#define MAX_ON_DEMAND_SUPPLY_NAME_LENGTH 64
#define HELICON_MCLK_CLK_9P6MHZ 9600000
+/*
+ * Multiplication factor to compute impedance on codec
+ * This is computed from (Vx / (m*Ical)) = (10mV/(180*30uA))
+ */
+#define MSM8X10_WCD_ZDET_MUL_FACTOR 1852
+
+/* RX_HPH_CNP_WG_TIME increases by 0.24ms */
+#define MSM8X10_WCD_WG_TIME_FACTOR_US 240
+
enum {
MSM8X10_WCD_I2C_TOP_LEVEL = 0,
MSM8X10_WCD_I2C_ANALOG,
@@ -168,6 +178,12 @@
struct delayed_work hs_detect_work;
struct wcd9xxx_mbhc_config *mbhc_cfg;
+
+ /*
+ * list used to save/restore registers at start and
+ * end of impedance measurement
+ */
+ struct list_head reg_save_restore;
};
static unsigned short rx_digital_gain_reg[] = {
@@ -435,8 +451,8 @@
__func__, reg);
else
dev_dbg(msm8x10_wcd->dev,
- "%s: Codec reg 0x%x written with value 0x%x\n",
- __func__, reg, val);
+ "%s: Write %x to R%d(0x%x)\n",
+ __func__, val, reg, reg);
return ret;
}
@@ -2424,6 +2440,11 @@
MSM8X10_WCD_A_MICB_1_CTL, 7, 0,
msm8x10_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS External",
+ MSM8X10_WCD_A_MICB_1_CTL, 7, 0,
+ msm8x10_wcd_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
SND_SOC_DAPM_ADC_E("ADC1", NULL, MSM8X10_WCD_A_TX_1_EN, 7, 0,
msm8x10_wcd_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
@@ -2439,9 +2460,6 @@
SND_SOC_DAPM_MUX("ADC2 MUX", SND_SOC_NOPM, 0, 0,
&tx_adc2_mux),
- SND_SOC_DAPM_MICBIAS("MIC BIAS External", MSM8X10_WCD_A_MICB_1_CTL,
- 7, 0),
-
SND_SOC_DAPM_INPUT("AMIC3"),
SND_SOC_DAPM_MUX_E("DEC1 MUX",
@@ -2517,8 +2535,10 @@
/* Enable pulldown to reduce leakage */
MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_MICB_1_CTL, 0x82),
MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_TX_COM_BIAS, 0xE0),
+ /* Keep the same default gain settings for TX paths */
MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_TX_1_EN, 0x32),
MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_TX_2_EN, 0x32),
+ MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_TX_3_EN, 0x30),
/* ClassG fine tuning setting for 16 ohm HPH */
MSM8X10_WCD_REG_VAL(MSM8X10_WCD_A_CDC_CLSG_FREQ_THRESH_B1_CTL, 0x05),
@@ -2608,12 +2628,6 @@
0xE0, 0xE0);
}
-static int msm8x10_wcd_get_jack_detect_irq(
- struct snd_soc_codec *codec)
-{
- return MSM8X10_WCD_IRQ_MBHC_HS_DET;
-}
-
static struct wcd9xxx_cfilt_mode msm8x10_wcd_switch_cfilt_mode(
struct wcd9xxx_mbhc *mbhc, bool fast)
{
@@ -2638,14 +2652,6 @@
mbhc->mbhc_bias_regs.ctl_reg, 0x60, 0x00);
}
-static void msm8x10_wcd_free_irq(struct wcd9xxx_mbhc *mbhc)
-{
- struct msm8x10_wcd *msm8x10_wcd = mbhc->codec->control_data;
- struct wcd9xxx_core_resource *core_res =
- &msm8x10_wcd->wcd9xxx_res;
- wcd9xxx_free_irq(core_res, MSM8X10_WCD_IRQ_MBHC_HS_DET, mbhc);
-}
-
enum wcd9xxx_cdc_type msm8x10_wcd_get_cdc_type(void)
{
return WCD9XXX_CDC_TYPE_HELICON;
@@ -2699,20 +2705,242 @@
0x40, on ? 0x40 : 0x00);
}
+static void msm8x10_wcd_prepare_hph_pa(struct snd_soc_codec *codec,
+ struct list_head *lh)
+{
+ int i;
+ u32 delay;
+
+ const struct wcd9xxx_reg_mask_val reg_set_paon[] = {
+ {MSM8X10_WCD_A_CDC_RX1_B6_CTL, 0xFF, 0x01},
+ {MSM8X10_WCD_A_CDC_RX2_B6_CTL, 0xFF, 0x01},
+ {MSM8X10_WCD_A_RX_HPH_L_GAIN, 0xFF, 0x2C},
+ {MSM8X10_WCD_A_RX_HPH_R_GAIN, 0xFF, 0x2C},
+ {MSM8X10_WCD_A_CDC_CLK_RX_B1_CTL, 0xFF, 0x01},
+ {MSM8X10_WCD_A_RX_COM_BIAS, 0xFF, 0x80},
+ {MSM8X10_WCD_A_CP_EN, 0xFF, 0xE7},
+ {MSM8X10_WCD_A_CP_STATIC, 0xFF, 0x13},
+ {MSM8X10_WCD_A_CP_STATIC, 0xFF, 0x1B},
+ {MSM8X10_WCD_A_CDC_RX2_B6_CTL, 0xFF, 0x01},
+ {MSM8X10_WCD_A_CDC_CLK_RX_B1_CTL, 0xFF, 0x03},
+ {MSM8X10_WCD_A_CDC_ANA_CLK_CTL, 0xFF, 0x22},
+ {MSM8X10_WCD_A_CDC_ANA_CLK_CTL, 0xFF, 0x23},
+ {MSM8X10_WCD_A_RX_HPH_CNP_WG_CTL, 0xFF, 0xDA},
+ {MSM8X10_WCD_A_CDC_DIG_CLK_CTL, 0xFF, 0x01},
+ {MSM8X10_WCD_A_CDC_DIG_CLK_CTL, 0xFF, 0x03},
+ {MSM8X10_WCD_A_RX_HPH_CHOP_CTL, 0xFF, 0xA4},
+ {MSM8X10_WCD_A_RX_HPH_OCP_CTL, 0xFF, 0x67},
+ {MSM8X10_WCD_A_RX_HPH_L_TEST, 0x01, 0x00},
+ {MSM8X10_WCD_A_RX_HPH_R_TEST, 0x01, 0x00},
+ {MSM8X10_WCD_A_RX_HPH_BIAS_WG_OCP, 0xFF, 0x1A},
+ {MSM8X10_WCD_A_RX_HPH_CNP_WG_CTL, 0xFF, 0xDB},
+ {MSM8X10_WCD_A_RX_HPH_CNP_WG_TIME, 0xFF, 0xDB},
+ {MSM8X10_WCD_A_RX_HPH_L_DAC_CTL, 0xFF, 0x40},
+ {MSM8X10_WCD_A_RX_HPH_L_DAC_CTL, 0xFF, 0xC0},
+ {MSM8X10_WCD_A_RX_HPH_R_DAC_CTL, 0xFF, 0x40},
+ {MSM8X10_WCD_A_RX_HPH_R_DAC_CTL, 0xFF, 0xC0},
+ {MSM8X10_WCD_A_RX_HPH_L_DAC_CTL, 0x03, 0x01},
+ {MSM8X10_WCD_A_RX_HPH_R_DAC_CTL, 0x03, 0x01},
+ };
+
+ for (i = 0; i < ARRAY_SIZE(reg_set_paon); i++) {
+ delay = 0;
+ wcd9xxx_soc_update_bits_push(codec, lh,
+ reg_set_paon[i].reg,
+ reg_set_paon[i].mask,
+ reg_set_paon[i].val, delay);
+ }
+ dev_dbg(codec->dev, "%s: PAs are prepared\n", __func__);
+ return;
+}
+
+static int msm8x10_wcd_enable_static_pa(struct snd_soc_codec *codec,
+ bool enable)
+{
+ int wg_time = snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME) *
+ MSM8X10_WCD_WG_TIME_FACTOR_US;
+
+ wg_time += (int) (wg_time * 35) / 100;
+
+ snd_soc_update_bits(codec, MSM8X10_WCD_A_RX_HPH_CNP_EN, 0x30,
+ enable ? 0x30 : 0x0);
+ /* Wait for wave gen time to avoid pop noise */
+ usleep_range(wg_time, wg_time + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+ snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_RX1_B6_CTL, 0xFF, 0x00);
+ snd_soc_update_bits(codec, MSM8X10_WCD_A_CDC_RX2_B6_CTL, 0xFF, 0x00);
+
+ dev_dbg(codec->dev, "%s: PAs are %s as static mode (wg_time %d)\n",
+ __func__, enable ? "enabled" : "disabled", wg_time);
+ return 0;
+}
+
+static int msm8x10_wcd_setup_zdet(struct wcd9xxx_mbhc *mbhc,
+ enum mbhc_impedance_detect_stages stage)
+{
+ int ret = 0;
+ struct snd_soc_codec *codec = mbhc->codec;
+ struct msm8x10_wcd_priv *wcd_priv = snd_soc_codec_get_drvdata(codec);
+ const int mux_wait_us = 25;
+
+#define __wr(reg, mask, value) \
+ do { \
+ ret = wcd9xxx_soc_update_bits_push(codec, \
+ &wcd_priv->reg_save_restore, \
+ reg, mask, value, 0); \
+ if (ret < 0) \
+ return ret; \
+ } while (0)
+
+ switch (stage) {
+ case PRE_MEAS:
+ dev_dbg(codec->dev, "%s: PRE_MEAS\n", __func__);
+ INIT_LIST_HEAD(&wcd_priv->reg_save_restore);
+ /* Configure PA */
+ msm8x10_wcd_prepare_hph_pa(mbhc->codec,
+ &wcd_priv->reg_save_restore);
+
+ /* Setup MBHC */
+ __wr(WCD9XXX_A_MBHC_SCALING_MUX_1, 0x7F, 0x40);
+ __wr(WCD9XXX_A_MBHC_SCALING_MUX_2, 0xFF, 0xF0);
+ __wr(0x171, 0xFF, 0x90);
+ __wr(WCD9XXX_A_TX_7_MBHC_EN, 0xFF, 0xF0);
+ __wr(WCD9XXX_A_CDC_MBHC_TIMER_B4_CTL, 0xFF, 0x45);
+ __wr(WCD9XXX_A_CDC_MBHC_TIMER_B5_CTL, 0xFF, 0x80);
+
+ __wr(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x0A);
+ snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x2);
+ __wr(WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xFF, 0x02);
+
+ /* Enable Impedance Detection */
+ __wr(WCD9XXX_A_MBHC_HPH, 0xFF, 0xC8);
+
+ /*
+ * CnP setup for 0mV
+ * Route static data as input to noise shaper
+ */
+ __wr(MSM8X10_WCD_A_CDC_RX1_B3_CTL, 0xFF, 0x02);
+ __wr(MSM8X10_WCD_A_CDC_RX2_B3_CTL, 0xFF, 0x02);
+
+ snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_L_TEST,
+ 0x02, 0x00);
+ snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_R_TEST,
+ 0x02, 0x00);
+
+ /* Reset the HPHL static data pointer */
+ __wr(MSM8X10_WCD_A_CDC_RX1_B2_CTL, 0xFF, 0x00);
+ /* Four consecutive writes to set 0V as static data input */
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX1_B1_CTL, 0x00);
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX1_B1_CTL, 0x00);
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX1_B1_CTL, 0x00);
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX1_B1_CTL, 0x00);
+
+ /* Reset the HPHR static data pointer */
+ __wr(MSM8X10_WCD_A_CDC_RX2_B2_CTL, 0xFF, 0x00);
+ /* Four consecutive writes to set 0V as static data input */
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX2_B1_CTL, 0x00);
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX2_B1_CTL, 0x00);
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX2_B1_CTL, 0x00);
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX2_B1_CTL, 0x00);
+
+ /* Enable the HPHL and HPHR PA */
+ msm8x10_wcd_enable_static_pa(mbhc->codec, true);
+ break;
+
+ case POST_MEAS:
+ dev_dbg(codec->dev, "%s: POST_MEAS\n", __func__);
+ /* Turn off ICAL */
+ snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_2, 0xF0);
+
+ msm8x10_wcd_enable_static_pa(mbhc->codec, false);
+
+ /*
+ * Setup CnP wavegen to ramp to the desired
+ * output using a 40ms ramp
+ */
+
+ /* CnP wavegen current to 0.5uA */
+ snd_soc_write(codec, WCD9XXX_A_RX_HPH_BIAS_WG_OCP, 0x1A);
+ /* Set the current division ratio to 2000 */
+ snd_soc_write(codec, WCD9XXX_A_RX_HPH_CNP_WG_CTL, 0xDF);
+ /* Set the wavegen timer to max (60msec) */
+ snd_soc_write(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME, 0xA0);
+ /* Set the CnP reference current to sc_bias */
+ snd_soc_write(codec, WCD9XXX_A_RX_HPH_OCP_CTL, 0x6D);
+
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX1_B2_CTL, 0x00);
+ /* Four consecutive writes to set -10mV as static data input */
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX1_B1_CTL, 0x00);
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX1_B1_CTL, 0x1F);
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX1_B1_CTL, 0xE3);
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX1_B1_CTL, 0x08);
+
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX2_B2_CTL, 0x00);
+ /* Four consecutive writes to set -10mV as static data input */
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX2_B1_CTL, 0x00);
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX2_B1_CTL, 0x1F);
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX2_B1_CTL, 0xE3);
+ snd_soc_write(codec, MSM8X10_WCD_A_CDC_RX2_B1_CTL, 0x08);
+
+ snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_L_TEST,
+ 0x02, 0x02);
+ snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_R_TEST,
+ 0x02, 0x02);
+ /* Enable the HPHL and HPHR PA and wait for 60mS */
+ msm8x10_wcd_enable_static_pa(mbhc->codec, true);
+
+ snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_1,
+ 0x7F, 0x40);
+ usleep_range(mux_wait_us,
+ mux_wait_us + WCD9XXX_USLEEP_RANGE_MARGIN_US);
+ break;
+ case PA_DISABLE:
+ dev_dbg(codec->dev, "%s: PA_DISABLE\n", __func__);
+ msm8x10_wcd_enable_static_pa(mbhc->codec, false);
+ wcd9xxx_restore_registers(codec, &wcd_priv->reg_save_restore);
+ break;
+ }
+#undef __wr
+
+ return ret;
+}
+
+static void msm8x10_wcd_compute_impedance(s16 *l, s16 *r, uint32_t *zl,
+ uint32_t *zr)
+{
+ int zln, zld;
+ int zrn, zrd;
+ int rl = 0, rr = 0;
+
+ zln = (l[1] - l[0]) * MSM8X10_WCD_ZDET_MUL_FACTOR;
+ zld = (l[2] - l[0]);
+ if (zld)
+ rl = zln / zld;
+
+ zrn = (r[1] - r[0]) * MSM8X10_WCD_ZDET_MUL_FACTOR;
+ zrd = (r[2] - r[0]);
+ if (zrd)
+ rr = zrn / zrd;
+
+ *zl = rl;
+ *zr = rr;
+}
+
+
+
static const struct wcd9xxx_mbhc_cb mbhc_cb = {
.enable_mux_bias_block = msm8x10_wcd_enable_mux_bias_block,
.cfilt_fast_mode = msm8x10_wcd_put_cfilt_fast_mode,
.codec_specific_cal = msm8x10_wcd_codec_specific_cal_setup,
- .jack_detect_irq = msm8x10_wcd_get_jack_detect_irq,
.switch_cfilt_mode = msm8x10_wcd_switch_cfilt_mode,
.select_cfilt = msm8x10_wcd_select_cfilt,
- .free_irq = msm8x10_wcd_free_irq,
.get_cdc_type = msm8x10_wcd_get_cdc_type,
.enable_clock_gate = msm8x10_wcd_mbhc_clk_gate,
.enable_mbhc_txfe = msm8x10_wcd_mbhc_txfe,
.enable_mb_source = msm8x10_wcd_enable_ext_mb_source,
.setup_int_rbias = msm8x10_wcd_micb_internal,
.pull_mb_to_vddio = msm8x10_wcd_enable_mb_vddio,
+ .setup_zdet = msm8x10_wcd_setup_zdet,
+ .compute_impedance = msm8x10_wcd_compute_impedance,
};
static void delayed_hs_detect_fn(struct work_struct *work)
@@ -2815,6 +3043,17 @@
.priority = -INT_MAX,
};
+static const struct wcd9xxx_mbhc_intr cdc_intr_ids = {
+ .poll_plug_rem = MSM8X10_WCD_IRQ_MBHC_REMOVAL,
+ .shortavg_complete = MSM8X10_WCD_IRQ_MBHC_SHORT_TERM,
+ .potential_button_press = MSM8X10_WCD_IRQ_MBHC_PRESS,
+ .button_release = MSM8X10_WCD_IRQ_MBHC_RELEASE,
+ .dce_est_complete = MSM8X10_WCD_IRQ_MBHC_POTENTIAL,
+ .insertion = MSM8X10_WCD_IRQ_MBHC_INSERTION,
+ .hph_left_ocp = MSM8X10_WCD_IRQ_HPH_PA_OCPL_FAULT,
+ .hph_right_ocp = MSM8X10_WCD_IRQ_HPH_PA_OCPR_FAULT,
+ .hs_jack_switch = MSM8X10_WCD_IRQ_MBHC_HS_DET,
+};
static int msm8x10_wcd_codec_probe(struct snd_soc_codec *codec)
{
@@ -2892,8 +3131,8 @@
ret = wcd9xxx_mbhc_init(&msm8x10_wcd_priv->mbhc,
&msm8x10_wcd_priv->resmgr,
- codec, NULL, &mbhc_cb,
- HELICON_MCLK_CLK_9P6MHZ, false);
+ codec, NULL, &mbhc_cb, &cdc_intr_ids,
+ HELICON_MCLK_CLK_9P6MHZ, true);
if (ret) {
pr_err("%s: Failed to initialize mbhc\n", __func__);
goto exit_probe;
@@ -3312,12 +3551,61 @@
{ },
};
+#ifdef CONFIG_PM
+static int msm8x10_wcd_i2c_resume(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct msm8x10_wcd_priv *priv = i2c_get_clientdata(client);
+ struct msm8x10_wcd *msm8x10;
+ int ret = 0;
+
+ if (client->addr == HELICON_CORE_0_I2C_ADDR) {
+ if (!priv || !priv->codec || !priv->codec->control_data) {
+ ret = -EINVAL;
+ dev_err(dev, "%s: Invalid client data\n", __func__);
+ goto rtn;
+ }
+ msm8x10 = priv->codec->control_data;
+ return wcd9xxx_core_res_resume(&msm8x10->wcd9xxx_res);
+ }
+rtn:
+ return 0;
+}
+
+static int msm8x10_wcd_i2c_suspend(struct device *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ struct msm8x10_wcd_priv *priv = i2c_get_clientdata(client);
+ struct msm8x10_wcd *msm8x10;
+ int ret = 0;
+
+ if (client->addr == HELICON_CORE_0_I2C_ADDR) {
+ if (!priv || !priv->codec || !priv->codec->control_data) {
+ ret = -EINVAL;
+ dev_err(dev, "%s: Invalid client data\n", __func__);
+ goto rtn;
+ }
+ msm8x10 = priv->codec->control_data;
+ return wcd9xxx_core_res_suspend(&msm8x10->wcd9xxx_res,
+ PMSG_SUSPEND);
+ }
+
+rtn:
+ return ret;
+}
+
+static SIMPLE_DEV_PM_OPS(msm8x1_wcd_pm_ops, msm8x10_wcd_i2c_suspend,
+ msm8x10_wcd_i2c_resume);
+#endif
static struct i2c_driver msm8x10_wcd_i2c_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "msm8x10-wcd-i2c-core",
- .of_match_table = msm8x10_wcd_of_match
+ .of_match_table = msm8x10_wcd_of_match,
+#ifdef CONFIG_PM
+ .pm = &msm8x1_wcd_pm_ops,
+#endif
},
.id_table = msm8x10_wcd_id_table,
.probe = msm8x10_wcd_i2c_probe,
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index 4e07d7f..4857593 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -97,8 +97,6 @@
#define TAPAN_SLIM_IRQ_UNDERFLOW (1 << 1)
#define TAPAN_SLIM_IRQ_PORT_CLOSED (1 << 2)
-#define TAPAN_IRQ_MBHC_JACK_SWITCH 21
-
enum tapan_codec_type {
WCD9306,
WCD9302,
@@ -1063,6 +1061,25 @@
static const struct snd_kcontrol_new class_h_dsm_mux =
SOC_DAPM_ENUM("CLASS_H_DSM MUX Mux", class_h_dsm_enum);
+static int tapan_hph_impedance_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ uint32_t zl, zr;
+ bool hphr;
+ struct soc_multi_mixer_control *mc;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct tapan_priv *priv = snd_soc_codec_get_drvdata(codec);
+
+ mc = (struct soc_multi_mixer_control *)(kcontrol->private_value);
+
+ hphr = mc->shift;
+ wcd9xxx_mbhc_get_impedance(&priv->mbhc, &zl, &zr);
+ pr_debug("%s: zl %u, zr %u\n", __func__, zl, zr);
+ ucontrol->value.integer.value[0] = hphr ? zr : zl;
+
+ return 0;
+}
+
static const struct snd_kcontrol_new tapan_common_snd_controls[] = {
SOC_ENUM_EXT("EAR PA Gain", tapan_ear_pa_gain_enum[0],
@@ -1165,6 +1182,11 @@
tapan_get_iir_band_audio_mixer, tapan_put_iir_band_audio_mixer),
SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
tapan_get_iir_band_audio_mixer, tapan_put_iir_band_audio_mixer),
+
+ SOC_SINGLE_EXT("HPHL Impedance", 0, 0, UINT_MAX, 0,
+ tapan_hph_impedance_get, NULL),
+ SOC_SINGLE_EXT("HPHR Impedance", 0, 1, UINT_MAX, 0,
+ tapan_hph_impedance_get, NULL),
};
static const struct snd_kcontrol_new tapan_9306_snd_controls[] = {
@@ -4576,6 +4598,9 @@
u8 flag = pdata->amic_settings.use_pdata;
u8 i = 0, j = 0;
u8 val_txfe = 0, value = 0;
+ u8 dmic_sample_rate_value = 0;
+ u8 dmic_b1_ctl_value = 0;
+ u8 anc_ctl_value = 0;
if (!pdata) {
dev_err(codec->dev, "%s: NULL pdata\n", __func__);
@@ -4669,6 +4694,78 @@
0x00 : 0x10);
snd_soc_update_bits(codec, TAPAN_A_MICB_3_CTL, 0x10, value);
+ /* Set the DMIC sample rate */
+ if (pdata->mclk_rate == TAPAN_MCLK_CLK_9P6MHZ) {
+ switch (pdata->dmic_sample_rate) {
+ case WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ:
+ dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_4;
+ dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_4;
+ anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
+ break;
+ case WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ:
+ dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_2;
+ dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_2;
+ anc_ctl_value = WCD9XXX_ANC_DMIC_X2_ON;
+ break;
+ case WCD9XXX_DMIC_SAMPLE_RATE_3P2MHZ:
+ case WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED:
+ dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_3;
+ dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_3;
+ anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
+ break;
+ default:
+ dev_err(codec->dev,
+ "%s Invalid sample rate %d for mclk %d\n",
+ __func__, pdata->dmic_sample_rate,
+ pdata->mclk_rate);
+ rc = -EINVAL;
+ goto done;
+ }
+ } else if (pdata->mclk_rate == TAPAN_MCLK_CLK_12P288MHZ) {
+ switch (pdata->dmic_sample_rate) {
+ case WCD9XXX_DMIC_SAMPLE_RATE_3P072MHZ:
+ dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_4;
+ dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_4;
+ anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
+ break;
+ case WCD9XXX_DMIC_SAMPLE_RATE_6P144MHZ:
+ dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_2;
+ dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_2;
+ anc_ctl_value = WCD9XXX_ANC_DMIC_X2_ON;
+ break;
+ case WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ:
+ case WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED:
+ dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_3;
+ dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_3;
+ anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
+ break;
+ default:
+ dev_err(codec->dev,
+ "%s Invalid sample rate %d for mclk %d\n",
+ __func__, pdata->dmic_sample_rate,
+ pdata->mclk_rate);
+ rc = -EINVAL;
+ goto done;
+ }
+ } else {
+ dev_err(codec->dev, "%s MCLK is not set!\n", __func__);
+ rc = -EINVAL;
+ goto done;
+ }
+
+ snd_soc_update_bits(codec, TAPAN_A_CDC_TX1_DMIC_CTL,
+ 0x7, dmic_sample_rate_value);
+ snd_soc_update_bits(codec, TAPAN_A_CDC_TX2_DMIC_CTL,
+ 0x7, dmic_sample_rate_value);
+ snd_soc_update_bits(codec, TAPAN_A_CDC_TX3_DMIC_CTL,
+ 0x7, dmic_sample_rate_value);
+ snd_soc_update_bits(codec, TAPAN_A_CDC_TX4_DMIC_CTL,
+ 0x7, dmic_sample_rate_value);
+ snd_soc_update_bits(codec, TAPAN_A_CDC_CLK_DMIC_B1_CTL,
+ 0xEE, dmic_b1_ctl_value);
+ snd_soc_update_bits(codec, TAPAN_A_CDC_ANC1_B2_CTL,
+ 0x1, anc_ctl_value);
+
done:
return rc;
}
@@ -4862,15 +4959,6 @@
{TAPAN_A_CDC_TX3_MUX_CTL, 0x8, 0x0},
{TAPAN_A_CDC_TX4_MUX_CTL, 0x8, 0x0},
- /* config Decimator for DMIC CLK_MODE_1(3.2Mhz@9.6Mhz mclk) */
- {TAPAN_A_CDC_TX1_DMIC_CTL, 0x7, 0x1},
- {TAPAN_A_CDC_TX2_DMIC_CTL, 0x7, 0x1},
- {TAPAN_A_CDC_TX3_DMIC_CTL, 0x7, 0x1},
- {TAPAN_A_CDC_TX4_DMIC_CTL, 0x7, 0x1},
-
- /* config DMIC clk to CLK_MODE_1 (3.2Mhz@9.6Mhz mclk) */
- {TAPAN_A_CDC_CLK_DMIC_B1_CTL, 0xEE, 0x22},
-
/* Compander zone selection */
{TAPAN_A_CDC_COMP0_B4_CTL, 0x3F, 0x37},
{TAPAN_A_CDC_COMP1_B4_CTL, 0x3F, 0x37},
@@ -4996,11 +5084,6 @@
snd_soc_update_bits(codec, WCD9XXX_A_TX_7_MBHC_EN, 0xE0, 0xE0);
}
-static int tapan_get_jack_detect_irq(struct snd_soc_codec *codec)
-{
- return TAPAN_IRQ_MBHC_JACK_SWITCH;
-}
-
static struct wcd9xxx_cfilt_mode tapan_codec_switch_cfilt_mode(
struct wcd9xxx_mbhc *mbhc,
bool fast)
@@ -5026,14 +5109,6 @@
snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x60, 0x00);
}
-static void tapan_free_irq(struct wcd9xxx_mbhc *mbhc)
-{
- struct wcd9xxx *wcd9xxx = mbhc->codec->control_data;
- struct wcd9xxx_core_resource *core_res =
- &wcd9xxx->core_res;
- wcd9xxx_free_irq(core_res, WCD9306_IRQ_MBHC_JACK_SWITCH, mbhc);
-}
-
enum wcd9xxx_cdc_type tapan_get_cdc_type(void)
{
return WCD9XXX_CDC_TYPE_TAPAN;
@@ -5292,10 +5367,8 @@
.enable_mux_bias_block = tapan_enable_mux_bias_block,
.cfilt_fast_mode = tapan_put_cfilt_fast_mode,
.codec_specific_cal = tapan_codec_specific_cal_setup,
- .jack_detect_irq = tapan_get_jack_detect_irq,
.switch_cfilt_mode = tapan_codec_switch_cfilt_mode,
.select_cfilt = tapan_select_cfilt,
- .free_irq = tapan_free_irq,
.get_cdc_type = tapan_get_cdc_type,
.setup_zdet = tapan_setup_zdet,
.compute_impedance = tapan_compute_impedance,
@@ -5336,6 +5409,18 @@
return 0;
}
+static const struct wcd9xxx_mbhc_intr cdc_intr_ids = {
+ .poll_plug_rem = WCD9XXX_IRQ_MBHC_REMOVAL,
+ .shortavg_complete = WCD9XXX_IRQ_MBHC_SHORT_TERM,
+ .potential_button_press = WCD9XXX_IRQ_MBHC_PRESS,
+ .button_release = WCD9XXX_IRQ_MBHC_RELEASE,
+ .dce_est_complete = WCD9XXX_IRQ_MBHC_POTENTIAL,
+ .insertion = WCD9XXX_IRQ_MBHC_INSERTION,
+ .hph_left_ocp = WCD9306_IRQ_HPH_PA_OCPL_FAULT,
+ .hph_right_ocp = WCD9306_IRQ_HPH_PA_OCPR_FAULT,
+ .hs_jack_switch = WCD9306_IRQ_MBHC_JACK_SWITCH,
+};
+
static int tapan_post_reset_cb(struct wcd9xxx *wcd9xxx)
{
int ret = 0;
@@ -5383,7 +5468,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, &cdc_intr_ids, rco_clk_rate,
TAPAN_CDC_ZDET_SUPPORTED);
if (ret)
pr_err("%s: mbhc init failed %d\n", __func__, ret);
@@ -5589,7 +5674,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, &cdc_intr_ids, rco_clk_rate,
TAPAN_CDC_ZDET_SUPPORTED);
if (ret) {
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 4ce9b4a..5656887 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -248,21 +248,6 @@
#define TAIKO_I2S_MASTER_MODE_MASK 0x08
-#define TAIKO_DMIC_SAMPLE_RATE_DIV_2 0x0
-#define TAIKO_DMIC_SAMPLE_RATE_DIV_3 0x1
-#define TAIKO_DMIC_SAMPLE_RATE_DIV_4 0x2
-
-#define TAIKO_DMIC_B1_CTL_DIV_2 0x00
-#define TAIKO_DMIC_B1_CTL_DIV_3 0x22
-#define TAIKO_DMIC_B1_CTL_DIV_4 0x44
-
-#define TAIKO_DMIC_B2_CTL_DIV_2 0x00
-#define TAIKO_DMIC_B2_CTL_DIV_3 0x02
-#define TAIKO_DMIC_B2_CTL_DIV_4 0x04
-
-#define TAIKO_ANC_DMIC_X2_ON 0x1
-#define TAIKO_ANC_DMIC_X2_OFF 0x0
-
#define TAIKO_SLIM_CLOSE_TIMEOUT 1000
#define TAIKO_SLIM_IRQ_OVERFLOW (1 << 0)
#define TAIKO_SLIM_IRQ_UNDERFLOW (1 << 1)
@@ -1142,6 +1127,125 @@
static const struct snd_kcontrol_new class_h_dsm_mux =
SOC_DAPM_ENUM("CLASS_H_DSM MUX Mux", class_h_dsm_enum);
+static const char *const taiko_conn_mad_text[] = {
+ "ADC_MB", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "NOTUSED1",
+ "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6", "NOTUSED2",
+ "NOTUSED3"};
+
+static const struct soc_enum taiko_conn_mad_enum =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(taiko_conn_mad_text),
+ taiko_conn_mad_text);
+
+
+static int taiko_mad_input_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 taiko_mad_input;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ taiko_mad_input = snd_soc_read(codec, TAIKO_A_CDC_CONN_MAD);
+
+ taiko_mad_input = taiko_mad_input & 0x0F;
+
+ ucontrol->value.integer.value[0] = taiko_mad_input;
+
+ pr_debug("%s: taiko_mad_input = %s\n", __func__,
+ taiko_conn_mad_text[taiko_mad_input]);
+
+ return 0;
+}
+
+static int taiko_mad_input_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 taiko_mad_input;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = codec->card;
+ char mad_amic_input_widget[6];
+ u32 adc;
+ const char *mad_input_widget;
+ u32 mic_bias_found = 0;
+ u32 i;
+ int ret = 0;
+
+ taiko_mad_input = ucontrol->value.integer.value[0];
+
+ pr_debug("%s: taiko_mad_input = %s\n", __func__,
+ taiko_conn_mad_text[taiko_mad_input]);
+
+ if (!strcmp(taiko_conn_mad_text[taiko_mad_input], "NOTUSED1") ||
+ !strcmp(taiko_conn_mad_text[taiko_mad_input], "NOTUSED2") ||
+ !strcmp(taiko_conn_mad_text[taiko_mad_input], "NOTUSED3") ||
+ !strcmp(taiko_conn_mad_text[taiko_mad_input], "ADC_MB")) {
+ pr_info("%s: taiko mad input is set to unsupported input = %s\n",
+ __func__, taiko_conn_mad_text[taiko_mad_input]);
+ return -EINVAL;
+ }
+
+ if (strnstr(taiko_conn_mad_text[taiko_mad_input],
+ "ADC", sizeof("ADC"))) {
+ ret = kstrtouint(strpbrk(taiko_conn_mad_text[taiko_mad_input]
+ , "123456"), 10, &adc);
+ if ((ret < 0) || (adc > 6)) {
+ pr_err("%s: Invalid ADC = %s\n", __func__,
+ taiko_conn_mad_text[taiko_mad_input]);
+ ret = -EINVAL;
+ }
+
+ snprintf(mad_amic_input_widget, 6, "%s%u", "AMIC", adc);
+
+ mad_input_widget = mad_amic_input_widget;
+ pr_debug("%s: taiko amic input widget = %s\n", __func__,
+ mad_amic_input_widget);
+ } else {
+ /* DMIC type input widget*/
+ mad_input_widget = taiko_conn_mad_text[taiko_mad_input];
+ }
+
+ pr_debug("%s: taiko input widget = %s\n", __func__, mad_input_widget);
+
+ for (i = 0; i < card->num_dapm_routes; i++) {
+
+ if (!strncmp(card->dapm_routes[i].sink,
+ mad_input_widget, strlen(mad_input_widget))) {
+
+ if (strnstr(card->dapm_routes[i].source,
+ "MIC BIAS1", sizeof("MIC BIAS1"))) {
+ mic_bias_found = 1;
+ break;
+ } else if (strnstr(card->dapm_routes[i].source,
+ "MIC BIAS2", sizeof("MIC BIAS2"))) {
+ mic_bias_found = 2;
+ break;
+ } else if (strnstr(card->dapm_routes[i].source,
+ "MIC BIAS3", sizeof("MIC BIAS3"))) {
+ mic_bias_found = 3;
+ break;
+ } else if (strnstr(card->dapm_routes[i].source,
+ "MIC BIAS4", sizeof("MIC BIAS4"))) {
+ mic_bias_found = 4;
+ break;
+ }
+ }
+ }
+
+ if (mic_bias_found) {
+ pr_debug("%s: source mic bias = %s. sink = %s\n", __func__,
+ card->dapm_routes[i].source,
+ card->dapm_routes[i].sink);
+
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CONN_MAD,
+ 0x0F, taiko_mad_input);
+ snd_soc_update_bits(codec, TAIKO_A_MAD_ANA_CTRL,
+ 0x07, mic_bias_found);
+ return 0;
+ } else {
+ pr_err("%s: mic bias source not found for input = %s\n",
+ __func__, mad_input_widget);
+ return -EINVAL;
+ }
+}
+
static const struct snd_kcontrol_new taiko_snd_controls[] = {
@@ -1290,6 +1394,9 @@
SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, COMPANDER_2, 1, 0,
taiko_get_compander, taiko_set_compander),
+ SOC_ENUM_EXT("MAD Input", taiko_conn_mad_enum,
+ taiko_mad_input_get, taiko_mad_input_put),
+
};
static int taiko_pa_gain_get(struct snd_kcontrol *kcontrol,
@@ -2513,8 +2620,6 @@
return -EINVAL;
}
- snd_soc_update_bits(codec, TAIKO_A_CDC_CONN_MAD,
- 0x0F, mad_cal->microphone_info.input_microphone);
snd_soc_write(codec, TAIKO_A_CDC_MAD_MAIN_CTL_2,
mad_cal->microphone_info.cycle_time);
snd_soc_update_bits(codec, TAIKO_A_CDC_MAD_MAIN_CTL_1, 0xFF << 3,
@@ -5741,24 +5846,24 @@
/* Set the DMIC sample rate */
if (pdata->mclk_rate == TAIKO_MCLK_CLK_9P6MHZ) {
switch (pdata->dmic_sample_rate) {
- case TAIKO_DMIC_SAMPLE_RATE_2P4MHZ:
- dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_4;
- dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_4;
- dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_4;
- anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
+ case WCD9XXX_DMIC_SAMPLE_RATE_2P4MHZ:
+ dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_4;
+ dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_4;
+ dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_4;
+ anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
break;
- case TAIKO_DMIC_SAMPLE_RATE_4P8MHZ:
- dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_2;
- dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_2;
- dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_2;
- anc_ctl_value = TAIKO_ANC_DMIC_X2_ON;
+ case WCD9XXX_DMIC_SAMPLE_RATE_4P8MHZ:
+ dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_2;
+ dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_2;
+ dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_2;
+ anc_ctl_value = WCD9XXX_ANC_DMIC_X2_ON;
break;
- case TAIKO_DMIC_SAMPLE_RATE_3P2MHZ:
- case TAIKO_DMIC_SAMPLE_RATE_UNDEFINED:
- dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_3;
- dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_3;
- dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_3;
- anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
+ case WCD9XXX_DMIC_SAMPLE_RATE_3P2MHZ:
+ case WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED:
+ dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_3;
+ dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_3;
+ dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_3;
+ anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
break;
default:
pr_err("%s Invalid sample rate %d for mclk %d\n",
@@ -5769,24 +5874,24 @@
}
} else if (pdata->mclk_rate == TAIKO_MCLK_CLK_12P288MHZ) {
switch (pdata->dmic_sample_rate) {
- case TAIKO_DMIC_SAMPLE_RATE_3P072MHZ:
- dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_4;
- dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_4;
- dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_4;
- anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
+ case WCD9XXX_DMIC_SAMPLE_RATE_3P072MHZ:
+ dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_4;
+ dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_4;
+ dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_4;
+ anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
break;
- case TAIKO_DMIC_SAMPLE_RATE_6P144MHZ:
- dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_2;
- dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_2;
- dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_2;
- anc_ctl_value = TAIKO_ANC_DMIC_X2_ON;
+ case WCD9XXX_DMIC_SAMPLE_RATE_6P144MHZ:
+ dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_2;
+ dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_2;
+ dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_2;
+ anc_ctl_value = WCD9XXX_ANC_DMIC_X2_ON;
break;
- case TAIKO_DMIC_SAMPLE_RATE_4P096MHZ:
- case TAIKO_DMIC_SAMPLE_RATE_UNDEFINED:
- dmic_sample_rate_value = TAIKO_DMIC_SAMPLE_RATE_DIV_3;
- dmic_b1_ctl_value = TAIKO_DMIC_B1_CTL_DIV_3;
- dmic_b2_ctl_value = TAIKO_DMIC_B2_CTL_DIV_3;
- anc_ctl_value = TAIKO_ANC_DMIC_X2_OFF;
+ case WCD9XXX_DMIC_SAMPLE_RATE_4P096MHZ:
+ case WCD9XXX_DMIC_SAMPLE_RATE_UNDEFINED:
+ dmic_sample_rate_value = WCD9XXX_DMIC_SAMPLE_RATE_DIV_3;
+ dmic_b1_ctl_value = WCD9XXX_DMIC_B1_CTL_DIV_3;
+ dmic_b2_ctl_value = WCD9XXX_DMIC_B2_CTL_DIV_3;
+ anc_ctl_value = WCD9XXX_ANC_DMIC_X2_OFF;
break;
default:
pr_err("%s Invalid sample rate %d for mclk %d\n",
@@ -6080,6 +6185,9 @@
/* Program the 0.85 volt VBG_REFERENCE */
{TAIKO_A_BIAS_CURR_CTL_2, 0xFF, 0x04},
+
+ /* set MAD input MIC to DMIC1 */
+ {TAIKO_A_CDC_CONN_MAD, 0x0F, 0x08},
};
static void taiko_codec_init_reg(struct snd_soc_codec *codec)
@@ -6383,6 +6491,18 @@
.compute_impedance = taiko_compute_impedance,
};
+static const struct wcd9xxx_mbhc_intr cdc_intr_ids = {
+ .poll_plug_rem = WCD9XXX_IRQ_MBHC_REMOVAL,
+ .shortavg_complete = WCD9XXX_IRQ_MBHC_SHORT_TERM,
+ .potential_button_press = WCD9XXX_IRQ_MBHC_PRESS,
+ .button_release = WCD9XXX_IRQ_MBHC_RELEASE,
+ .dce_est_complete = WCD9XXX_IRQ_MBHC_POTENTIAL,
+ .insertion = WCD9XXX_IRQ_MBHC_INSERTION,
+ .hph_left_ocp = WCD9XXX_IRQ_HPH_PA_OCPL_FAULT,
+ .hph_right_ocp = WCD9XXX_IRQ_HPH_PA_OCPR_FAULT,
+ .hs_jack_switch = WCD9320_IRQ_MBHC_JACK_SWITCH,
+};
+
static int taiko_post_reset_cb(struct wcd9xxx *wcd9xxx)
{
int ret = 0;
@@ -6428,7 +6548,8 @@
ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
taiko_enable_mbhc_micbias,
- &mbhc_cb, rco_clk_rate, true);
+ &mbhc_cb, &cdc_intr_ids,
+ rco_clk_rate, true);
if (ret)
pr_err("%s: mbhc init failed %d\n", __func__, ret);
else
@@ -6617,7 +6738,8 @@
/* init and start mbhc */
ret = wcd9xxx_mbhc_init(&taiko->mbhc, &taiko->resmgr, codec,
taiko_enable_mbhc_micbias,
- &mbhc_cb, rco_clk_rate, true);
+ &mbhc_cb, &cdc_intr_ids,
+ rco_clk_rate, true);
if (ret) {
pr_err("%s: mbhc init failed %d\n", __func__, ret);
goto err_init;
diff --git a/sound/soc/codecs/wcd9xxx-common.h b/sound/soc/codecs/wcd9xxx-common.h
index e63d36a..0239c86 100644
--- a/sound/soc/codecs/wcd9xxx-common.h
+++ b/sound/soc/codecs/wcd9xxx-common.h
@@ -37,6 +37,21 @@
#define WCD9XXX_CLSH_STATE_LO (0x01 << 3)
#define NUM_CLSH_STATES ((0x01 << 4) - 1)
+#define WCD9XXX_DMIC_SAMPLE_RATE_DIV_2 0x0
+#define WCD9XXX_DMIC_SAMPLE_RATE_DIV_3 0x1
+#define WCD9XXX_DMIC_SAMPLE_RATE_DIV_4 0x2
+
+#define WCD9XXX_DMIC_B1_CTL_DIV_2 0x00
+#define WCD9XXX_DMIC_B1_CTL_DIV_3 0x22
+#define WCD9XXX_DMIC_B1_CTL_DIV_4 0x44
+
+#define WCD9XXX_DMIC_B2_CTL_DIV_2 0x00
+#define WCD9XXX_DMIC_B2_CTL_DIV_3 0x02
+#define WCD9XXX_DMIC_B2_CTL_DIV_4 0x04
+
+#define WCD9XXX_ANC_DMIC_X2_ON 0x1
+#define WCD9XXX_ANC_DMIC_X2_OFF 0x0
+
/* Derived State: Bits 1 and 2 should be set for Headphone stereo */
#define WCD9XXX_CLSH_STATE_HPH_ST (WCD9XXX_CLSH_STATE_HPHL | \
WCD9XXX_CLSH_STATE_HPHR)
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index c2d626b..362a9ca 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -118,13 +118,16 @@
/* RX_HPH_CNP_WG_TIME increases by 0.24ms */
#define WCD9XXX_WG_TIME_FACTOR_US 240
-#define WCD9XXX_IRQ_MBHC_JACK_SWITCH_DEFAULT 28
-
#define WCD9XXX_V_CS_HS_MAX 500
#define WCD9XXX_V_CS_NO_MIC 5
#define WCD9XXX_MB_MEAS_DELTA_MAX_MV 80
#define WCD9XXX_CS_MEAS_DELTA_MAX_MV 10
+static int impedance_detect_en;
+module_param(impedance_detect_en, int,
+ S_IRUGO | S_IWUSR | S_IWGRP);
+MODULE_PARM_DESC(impedance_detect_en, "enable/disable impedance detect");
+
static bool detect_use_vddio_switch = true;
struct wcd9xxx_mbhc_detect {
@@ -565,7 +568,7 @@
* reset retry counter as PA is turned off signifying
* start of new OCP detection session
*/
- if (WCD9XXX_IRQ_HPH_PA_OCPL_FAULT)
+ if (mbhc->intr_ids->hph_left_ocp)
mbhc->hphlocp_cnt = 0;
else
mbhc->hphrocp_cnt = 0;
@@ -576,13 +579,13 @@
static void hphrocp_off_report(struct wcd9xxx_mbhc *mbhc, u32 jack_status)
{
__hphocp_off_report(mbhc, SND_JACK_OC_HPHR,
- WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
+ mbhc->intr_ids->hph_right_ocp);
}
static void hphlocp_off_report(struct wcd9xxx_mbhc *mbhc, u32 jack_status)
{
__hphocp_off_report(mbhc, SND_JACK_OC_HPHL,
- WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
+ mbhc->intr_ids->hph_left_ocp);
}
static void wcd9xxx_get_mbhc_micbias_regs(struct wcd9xxx_mbhc *mbhc,
@@ -863,7 +866,7 @@
mbhc->micbias_enable_cb(mbhc->codec, true);
}
- if (mbhc->impedance_detect)
+ if (mbhc->impedance_detect && impedance_detect_en)
wcd9xxx_detect_impedance(mbhc, &mbhc->zl, &mbhc->zr);
pr_debug("%s: Reporting insertion %d(%x)\n", __func__,
@@ -967,7 +970,8 @@
short bias_value;
struct snd_soc_codec *codec = mbhc->codec;
- wcd9xxx_disable_irq(mbhc->resmgr->core_res, WCD9XXX_IRQ_MBHC_POTENTIAL);
+ wcd9xxx_disable_irq(mbhc->resmgr->core_res,
+ mbhc->intr_ids->dce_est_complete);
if (noreldetection)
wcd9xxx_turn_onoff_rel_detection(codec, false);
@@ -1013,7 +1017,8 @@
if (noreldetection)
wcd9xxx_turn_onoff_rel_detection(codec, true);
- wcd9xxx_enable_irq(mbhc->resmgr->core_res, WCD9XXX_IRQ_MBHC_POTENTIAL);
+ wcd9xxx_enable_irq(mbhc->resmgr->core_res,
+ mbhc->intr_ids->dce_est_complete);
return bias_value;
}
@@ -1051,6 +1056,27 @@
mbhc->mbhc_data.micb_mv);
}
+/* To enable/disable bandgap and RC oscillator */
+static void wcd9xxx_mbhc_ctrl_clk_bandgap(struct wcd9xxx_mbhc *mbhc,
+ bool enable)
+{
+ if (enable) {
+ WCD9XXX_BG_CLK_LOCK(mbhc->resmgr);
+ wcd9xxx_resmgr_get_bandgap(mbhc->resmgr,
+ WCD9XXX_BANDGAP_AUDIO_MODE);
+ wcd9xxx_resmgr_get_clk_block(mbhc->resmgr,
+ WCD9XXX_CLK_RCO);
+ WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr);
+ } else {
+ WCD9XXX_BG_CLK_LOCK(mbhc->resmgr);
+ wcd9xxx_resmgr_put_clk_block(mbhc->resmgr,
+ WCD9XXX_CLK_RCO);
+ wcd9xxx_resmgr_put_bandgap(mbhc->resmgr,
+ WCD9XXX_BANDGAP_AUDIO_MODE);
+ WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr);
+ }
+}
+
/* called only from interrupt which is under codec_resource_lock acquisition */
static short wcd9xxx_mbhc_setup_hs_polling(struct wcd9xxx_mbhc *mbhc,
bool is_cs_enable)
@@ -1077,13 +1103,16 @@
mbhc->mbhc_cb->enable_mb_source(codec, true);
/*
- * Request BG and clock.
- * These will be released by wcd9xxx_cleanup_hs_polling
+ * setup internal micbias if codec uses internal micbias for
+ * headset detection
*/
- WCD9XXX_BG_CLK_LOCK(mbhc->resmgr);
- wcd9xxx_resmgr_get_bandgap(mbhc->resmgr, WCD9XXX_BANDGAP_AUDIO_MODE);
- wcd9xxx_resmgr_get_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO);
- WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr);
+ if (mbhc->mbhc_cfg->use_int_rbias) {
+ if (mbhc->mbhc_cb && mbhc->mbhc_cb->setup_int_rbias)
+ mbhc->mbhc_cb->setup_int_rbias(codec, true);
+ else
+ pr_err("%s: internal bias is requested but codec did not provide callback\n",
+ __func__);
+ }
snd_soc_update_bits(codec, WCD9XXX_A_CLK_BUFF_EN1, 0x05, 0x01);
@@ -1195,11 +1224,6 @@
wcd9xxx_shutdown_hs_removal_detect(mbhc);
- /* Release clock and BG requested by wcd9xxx_mbhc_setup_hs_polling */
- WCD9XXX_BG_CLK_LOCK(mbhc->resmgr);
- wcd9xxx_resmgr_put_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO);
- wcd9xxx_resmgr_put_bandgap(mbhc->resmgr, WCD9XXX_BANDGAP_MBHC_MODE);
- WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr);
/* Disable external voltage source to micbias if present */
if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mb_source)
@@ -1406,7 +1430,7 @@
(dgnd->_vdces + WCD9XXX_CS_GM_SWAP_THRES_MAX_MV >
maxv))
type = PLUG_TYPE_GND_MIC_SWAP;
- else if (dgnd->_type != PLUG_TYPE_HEADSET) {
+ else if (dgnd->_type != PLUG_TYPE_HEADSET && !dmicbias) {
pr_debug("%s: Invalid, inconsistent types\n", __func__);
type = PLUG_TYPE_INVALID;
}
@@ -1674,6 +1698,7 @@
BUG_ON(NUM_DCE_PLUG_INS_DETECT < 4);
+ wcd9xxx_mbhc_ctrl_clk_bandgap(mbhc, true);
rt[0].swap_gnd = false;
rt[0].vddio = false;
rt[0].hwvalue = true;
@@ -1702,6 +1727,7 @@
type = wcd9xxx_cs_find_plug_type(mbhc, rt, ARRAY_SIZE(rt), highhph,
mbhc->event_state);
+ wcd9xxx_mbhc_ctrl_clk_bandgap(mbhc, false);
pr_debug("%s: plug_type:%d\n", __func__, type);
return type;
@@ -1742,6 +1768,8 @@
*/
(void) wcd9xxx_pull_down_micbias(mbhc,
WCD9XXX_MICBIAS_PULLDOWN_SETTLE_US);
+
+ wcd9xxx_mbhc_ctrl_clk_bandgap(mbhc, true);
rt[0].hphl_status = wcd9xxx_hphl_status(mbhc);
rt[0].dce = wcd9xxx_mbhc_setup_hs_polling(mbhc, false);
rt[0].swap_gnd = false;
@@ -1781,6 +1809,7 @@
type = wcd9xxx_find_plug_type(mbhc, rt, ARRAY_SIZE(rt),
mbhc->event_state);
+ wcd9xxx_mbhc_ctrl_clk_bandgap(mbhc, false);
pr_debug("%s: leave\n", __func__);
return type;
}
@@ -1928,7 +1957,7 @@
snd_soc_update_bits(codec, mbhc->resmgr->reg_addr->micb_4_mbhc,
0x3, mbhc->mbhc_cfg->micbias);
- wcd9xxx_enable_irq(mbhc->resmgr->core_res, WCD9XXX_IRQ_MBHC_INSERTION);
+ wcd9xxx_enable_irq(mbhc->resmgr->core_res, mbhc->intr_ids->insertion);
snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
pr_debug("%s: leave\n", __func__);
@@ -1969,6 +1998,8 @@
* only report the mic line
*/
wcd9xxx_report_plug(mbhc, 1, SND_JACK_HEADSET);
+ /* Button detection required RC oscillator */
+ wcd9xxx_mbhc_ctrl_clk_bandgap(mbhc, true);
msleep(100);
/* if PA is already on, switch micbias source to VDDIO */
@@ -2257,8 +2288,11 @@
usleep_range(generic->t_shutdown_plug_rem,
generic->t_shutdown_plug_rem);
- cs_enable = ((mbhc->mbhc_cfg->cs_enable_flags &
- (1 << MBHC_CS_ENABLE_REMOVAL)) != 0);
+ /* If micbias is enabled, don't enable current source */
+ cs_enable = (((mbhc->mbhc_cfg->cs_enable_flags &
+ (1 << MBHC_CS_ENABLE_REMOVAL)) != 0) &&
+ (!(snd_soc_read(codec,
+ mbhc->mbhc_bias_regs.ctl_reg) & 0x80)));
if (cs_enable)
wcd9xxx_turn_onoff_current_source(mbhc, true, false);
@@ -2300,6 +2334,9 @@
* extension cable is still plugged in
* report it as LINEOUT device
*/
+ if (mbhc->hph_status == SND_JACK_HEADSET)
+ wcd9xxx_mbhc_ctrl_clk_bandgap(mbhc,
+ false);
wcd9xxx_report_plug(mbhc, 1, SND_JACK_LINEOUT);
wcd9xxx_cleanup_hs_polling(mbhc);
wcd9xxx_enable_hs_detect(mbhc, 1,
@@ -2318,6 +2355,7 @@
wcd9xxx_switch_micbias(mbhc, 0);
wcd9xxx_report_plug(mbhc, 0, SND_JACK_HEADSET);
+ wcd9xxx_mbhc_ctrl_clk_bandgap(mbhc, false);
wcd9xxx_cleanup_hs_polling(mbhc);
wcd9xxx_enable_hs_detect(mbhc, 1, MBHC_USE_MB_TRIGGER |
MBHC_USE_HPHL_TRIGGER,
@@ -2394,7 +2432,7 @@
pr_debug("%s: enter\n", __func__);
WCD9XXX_BCL_LOCK(mbhc->resmgr);
- wcd9xxx_disable_irq(mbhc->resmgr->core_res, WCD9XXX_IRQ_MBHC_INSERTION);
+ wcd9xxx_disable_irq(mbhc->resmgr->core_res, mbhc->intr_ids->insertion);
is_mb_trigger = !!(snd_soc_read(codec, mbhc->mbhc_bias_regs.mbhc_reg) &
0x10);
@@ -2461,7 +2499,7 @@
snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 0x90, 0x00);
snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x13, 0x00);
snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
- wcd9xxx_disable_irq_sync(core_res, WCD9XXX_IRQ_MBHC_INSERTION);
+ wcd9xxx_disable_irq_sync(core_res, mbhc->intr_ids->insertion);
wcd9xxx_mbhc_detect_plug_type(mbhc);
wcd9xxx_unlock_sleep(core_res);
}
@@ -2830,6 +2868,10 @@
/* cancel detect plug */
wcd9xxx_cancel_hs_detect_plug(mbhc,
&mbhc->correct_plug_swch);
+ if ((mbhc->current_plug != PLUG_TYPE_NONE) &&
+ !(snd_soc_read(codec, WCD9XXX_A_MBHC_INSERT_DETECT) &
+ (1 << 1)))
+ goto exit;
/* Disable Mic Bias pull down and HPH Switch to GND */
snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x01,
@@ -2852,6 +2894,7 @@
is_removed = true;
} else if (mbhc->current_plug == PLUG_TYPE_HEADSET) {
wcd9xxx_pause_hs_polling(mbhc);
+ wcd9xxx_mbhc_ctrl_clk_bandgap(mbhc, false);
wcd9xxx_cleanup_hs_polling(mbhc);
wcd9xxx_report_plug(mbhc, 0, SND_JACK_HEADSET);
is_removed = true;
@@ -2882,7 +2925,7 @@
wcd9xxx_turn_onoff_override(mbhc, false);
}
}
-
+exit:
mbhc->in_swch_irq_handler = false;
WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
pr_debug("%s: leave\n", __func__);
@@ -3030,13 +3073,14 @@
change = snd_soc_update_bits(codec, WCD9XXX_A_MAD_ANA_CTRL, 1 << 4,
1 << 0);
usleep_range(1000, 1000 + 1000);
- if (sta_z)
+ if (sta_z) {
*sta_z = wcd9xxx_codec_sta_dce(mbhc, 0, false);
- if (dce_z)
+ pr_debug("%s: sta_z 0x%x\n", __func__, *sta_z & 0xFFFF);
+ }
+ if (dce_z) {
*dce_z = wcd9xxx_codec_sta_dce(mbhc, 1, false);
-
- pr_debug("%s: sta_z 0x%x, dce_z 0x%x\n", __func__, *sta_z & 0xFFFF,
- *dce_z & 0xFFFF);
+ pr_debug("%s: dce_z 0x%x\n", __func__, *dce_z & 0xFFFF);
+ }
/* Connect override from micbias */
if (change)
@@ -3348,7 +3392,7 @@
0x10, 0x10);
} else {
wcd9xxx_disable_irq(mbhc->resmgr->core_res,
- WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
+ mbhc->intr_ids->hph_left_ocp);
mbhc->hph_status |= SND_JACK_OC_HPHL;
wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
mbhc->hph_status,
@@ -3378,7 +3422,7 @@
0x10);
} else {
wcd9xxx_disable_irq(mbhc->resmgr->core_res,
- WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
+ mbhc->intr_ids->hph_right_ocp);
mbhc->hph_status |= SND_JACK_OC_HPHR;
wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
mbhc->hph_status, WCD9XXX_JACK_MASK);
@@ -3458,7 +3502,8 @@
struct snd_soc_codec *codec = mbhc->codec;
pr_debug("%s: enter\n", __func__);
- wcd9xxx_disable_irq(mbhc->resmgr->core_res, WCD9XXX_IRQ_MBHC_POTENTIAL);
+ wcd9xxx_disable_irq(mbhc->resmgr->core_res,
+ mbhc->intr_ids->dce_est_complete);
wcd9xxx_turn_onoff_rel_detection(codec, false);
/* t_dce and t_sta are updated by wcd9xxx_update_mbhc_clk_rate() */
@@ -3598,7 +3643,8 @@
if (mbhc->mbhc_cb && mbhc->mbhc_cb->enable_mb_source)
mbhc->mbhc_cb->enable_mb_source(codec, false);
- wcd9xxx_enable_irq(mbhc->resmgr->core_res, WCD9XXX_IRQ_MBHC_POTENTIAL);
+ wcd9xxx_enable_irq(mbhc->resmgr->core_res,
+ mbhc->intr_ids->dce_est_complete);
wcd9xxx_turn_onoff_rel_detection(codec, true);
pr_debug("%s: leave\n", __func__);
@@ -3664,14 +3710,7 @@
static int wcd9xxx_setup_jack_detect_irq(struct wcd9xxx_mbhc *mbhc)
{
int ret = 0;
- struct snd_soc_codec *codec = mbhc->codec;
void *core_res = mbhc->resmgr->core_res;
- int jack_irq;
-
- if (mbhc->mbhc_cb && mbhc->mbhc_cb->jack_detect_irq)
- jack_irq = mbhc->mbhc_cb->jack_detect_irq(codec);
- else
- jack_irq = WCD9XXX_IRQ_MBHC_JACK_SWITCH_DEFAULT;
if (mbhc->mbhc_cfg->gpio) {
ret = request_threaded_irq(mbhc->mbhc_cfg->gpio_irq, NULL,
@@ -3694,13 +3733,14 @@
snd_soc_update_bits(mbhc->codec, WCD9XXX_A_RX_HPH_OCP_CTL,
1 << 1, 1 << 1);
- ret = wcd9xxx_request_irq(core_res, jack_irq,
+ ret = wcd9xxx_request_irq(core_res,
+ mbhc->intr_ids->hs_jack_switch,
wcd9xxx_mech_plug_detect_irq,
"Jack Detect",
mbhc);
if (ret)
pr_err("%s: Failed to request insert detect irq %d\n",
- __func__, jack_irq);
+ __func__, mbhc->intr_ids->hs_jack_switch);
}
return ret;
@@ -3730,9 +3770,9 @@
snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL, 0x10,
0x10);
wcd9xxx_enable_irq(mbhc->resmgr->core_res,
- WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
+ mbhc->intr_ids->hph_left_ocp);
wcd9xxx_enable_irq(mbhc->resmgr->core_res,
- WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
+ mbhc->intr_ids->hph_right_ocp);
/* Initialize mechanical mbhc */
ret = wcd9xxx_setup_jack_detect_irq(mbhc);
@@ -4323,16 +4363,7 @@
*/
mutex_lock(&codec->mutex);
- WCD9XXX_BG_CLK_LOCK(mbhc->resmgr);
- /*
- * Fast(mbhc) mode bandagap doesn't need to be enabled explicitly
- * since fast mode is set by MBHC hardware when override is on.
- * Enable bandgap mode to avoid unnecessary RCO disable and enable
- * during clock source change.
- */
- wcd9xxx_resmgr_get_bandgap(mbhc->resmgr, WCD9XXX_BANDGAP_AUDIO_MODE);
- wcd9xxx_resmgr_get_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO);
- WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr);
+ wcd9xxx_onoff_ext_mclk(mbhc, true);
wcd9xxx_turn_onoff_override(mbhc, true);
pr_debug("%s: Setting impedance detection\n", __func__);
@@ -4380,10 +4411,7 @@
mutex_unlock(&codec->mutex);
- WCD9XXX_BG_CLK_LOCK(mbhc->resmgr);
- wcd9xxx_resmgr_put_bandgap(mbhc->resmgr, WCD9XXX_BANDGAP_AUDIO_MODE);
- wcd9xxx_resmgr_put_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO);
- WCD9XXX_BG_CLK_UNLOCK(mbhc->resmgr);
+ wcd9xxx_onoff_ext_mclk(mbhc, false);
wcd9xxx_turn_onoff_override(mbhc, false);
mbhc->mbhc_cb->compute_impedance(l, r, zl, zr);
@@ -4422,7 +4450,9 @@
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,
+ const struct wcd9xxx_mbhc_intr *mbhc_cdc_intr_ids,
+ int rco_clk_rate,
bool impedance_det_en)
{
int ret;
@@ -4449,8 +4479,14 @@
mbhc->micbias_enable_cb = micbias_enable_cb;
mbhc->rco_clk_rate = rco_clk_rate;
mbhc->mbhc_cb = mbhc_cb;
+ mbhc->intr_ids = mbhc_cdc_intr_ids;
mbhc->impedance_detect = impedance_det_en;
+ if (mbhc->intr_ids == NULL) {
+ pr_err("%s: Interrupt mapping not provided\n", __func__);
+ return -EINVAL;
+ }
+
if (mbhc->headset_jack.jack == NULL) {
ret = snd_soc_jack_new(codec, "Headset Jack", WCD9XXX_JACK_MASK,
&mbhc->headset_jack);
@@ -4493,63 +4529,71 @@
wcd9xxx_init_debugfs(mbhc);
+
+ /* Disable Impedance detection by default for certain codec types */
+ if (mbhc->mbhc_cb &&
+ mbhc->mbhc_cb->get_cdc_type() == WCD9XXX_CDC_TYPE_HELICON)
+ impedance_detect_en = 0;
+ else
+ impedance_detect_en = impedance_det_en ? 1 : 0;
+
core_res = mbhc->resmgr->core_res;
- ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_MBHC_INSERTION,
+ ret = wcd9xxx_request_irq(core_res, mbhc->intr_ids->insertion,
wcd9xxx_hs_insert_irq,
"Headset insert detect", mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d, ret = %d\n", __func__,
- WCD9XXX_IRQ_MBHC_INSERTION, ret);
+ mbhc->intr_ids->insertion, ret);
goto err_insert_irq;
}
- wcd9xxx_disable_irq(core_res, WCD9XXX_IRQ_MBHC_INSERTION);
+ wcd9xxx_disable_irq(core_res, mbhc->intr_ids->insertion);
- ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_MBHC_REMOVAL,
+ ret = wcd9xxx_request_irq(core_res, mbhc->intr_ids->poll_plug_rem,
wcd9xxx_hs_remove_irq,
"Headset remove detect", mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
- WCD9XXX_IRQ_MBHC_REMOVAL);
+ mbhc->intr_ids->poll_plug_rem);
goto err_remove_irq;
}
- ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_MBHC_POTENTIAL,
+ ret = wcd9xxx_request_irq(core_res, mbhc->intr_ids->dce_est_complete,
wcd9xxx_dce_handler, "DC Estimation detect",
mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
- WCD9XXX_IRQ_MBHC_POTENTIAL);
+ mbhc->intr_ids->dce_est_complete);
goto err_potential_irq;
}
- ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_MBHC_RELEASE,
+ ret = wcd9xxx_request_irq(core_res, mbhc->intr_ids->button_release,
wcd9xxx_release_handler,
"Button Release detect", mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
- WCD9XXX_IRQ_MBHC_RELEASE);
+ mbhc->intr_ids->button_release);
goto err_release_irq;
}
- ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT,
+ ret = wcd9xxx_request_irq(core_res, mbhc->intr_ids->hph_left_ocp,
wcd9xxx_hphl_ocp_irq, "HPH_L OCP detect",
mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
- WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
+ mbhc->intr_ids->hph_left_ocp);
goto err_hphl_ocp_irq;
}
- wcd9xxx_disable_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
+ wcd9xxx_disable_irq(core_res, mbhc->intr_ids->hph_left_ocp);
- ret = wcd9xxx_request_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT,
+ ret = wcd9xxx_request_irq(core_res, mbhc->intr_ids->hph_right_ocp,
wcd9xxx_hphr_ocp_irq, "HPH_R OCP detect",
mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
- WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
+ mbhc->intr_ids->hph_right_ocp);
goto err_hphr_ocp_irq;
}
- wcd9xxx_disable_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
+ wcd9xxx_disable_irq(core_res, mbhc->intr_ids->hph_right_ocp);
wcd9xxx_regmgr_cond_register(resmgr, 1 << WCD9XXX_COND_HPH_MIC |
1 << WCD9XXX_COND_HPH);
@@ -4558,15 +4602,15 @@
return ret;
err_hphr_ocp_irq:
- wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, mbhc);
+ wcd9xxx_free_irq(core_res, mbhc->intr_ids->hph_left_ocp, mbhc);
err_hphl_ocp_irq:
- wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_RELEASE, mbhc);
+ wcd9xxx_free_irq(core_res, mbhc->intr_ids->button_release, mbhc);
err_release_irq:
- wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_POTENTIAL, mbhc);
+ wcd9xxx_free_irq(core_res, mbhc->intr_ids->dce_est_complete, mbhc);
err_potential_irq:
- wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_REMOVAL, mbhc);
+ wcd9xxx_free_irq(core_res, mbhc->intr_ids->poll_plug_rem, mbhc);
err_remove_irq:
- wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_INSERTION, mbhc);
+ wcd9xxx_free_irq(core_res, mbhc->intr_ids->insertion, mbhc);
err_insert_irq:
wcd9xxx_resmgr_unregister_notifier(mbhc->resmgr, &mbhc->nblock);
@@ -4583,22 +4627,15 @@
wcd9xxx_regmgr_cond_deregister(mbhc->resmgr, 1 << WCD9XXX_COND_HPH_MIC |
1 << WCD9XXX_COND_HPH);
- wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_RELEASE, mbhc);
- wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_POTENTIAL, mbhc);
- wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_REMOVAL, mbhc);
- wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_MBHC_INSERTION, mbhc);
-
- if (mbhc->mbhc_cb && mbhc->mbhc_cb->free_irq)
- mbhc->mbhc_cb->free_irq(mbhc);
- else
- wcd9xxx_free_irq(core_res, WCD9320_IRQ_MBHC_JACK_SWITCH,
- mbhc);
-
- wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, mbhc);
- wcd9xxx_free_irq(core_res, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT, mbhc);
+ wcd9xxx_free_irq(core_res, mbhc->intr_ids->button_release, mbhc);
+ wcd9xxx_free_irq(core_res, mbhc->intr_ids->dce_est_complete, mbhc);
+ wcd9xxx_free_irq(core_res, mbhc->intr_ids->poll_plug_rem, mbhc);
+ wcd9xxx_free_irq(core_res, mbhc->intr_ids->insertion, mbhc);
+ wcd9xxx_free_irq(core_res, mbhc->intr_ids->hs_jack_switch, mbhc);
+ wcd9xxx_free_irq(core_res, mbhc->intr_ids->hph_left_ocp, mbhc);
+ wcd9xxx_free_irq(core_res, mbhc->intr_ids->hph_right_ocp, mbhc);
wcd9xxx_resmgr_unregister_notifier(mbhc->resmgr, &mbhc->nblock);
-
wcd9xxx_cleanup_debugfs(mbhc);
}
EXPORT_SYMBOL(wcd9xxx_mbhc_deinit);
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.h b/sound/soc/codecs/wcd9xxx-mbhc.h
index 91280e4..9d0afe9 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.h
+++ b/sound/soc/codecs/wcd9xxx-mbhc.h
@@ -236,16 +236,26 @@
u8 reg_mask;
};
+struct wcd9xxx_mbhc_intr {
+ int poll_plug_rem;
+ int shortavg_complete;
+ int potential_button_press;
+ int button_release;
+ int dce_est_complete;
+ int insertion;
+ int hph_left_ocp;
+ int hph_right_ocp;
+ int hs_jack_switch;
+};
+
struct wcd9xxx_mbhc_cb {
void (*enable_mux_bias_block) (struct snd_soc_codec *);
void (*cfilt_fast_mode) (struct snd_soc_codec *, struct wcd9xxx_mbhc *);
void (*codec_specific_cal) (struct snd_soc_codec *,
struct wcd9xxx_mbhc *);
- int (*jack_detect_irq) (struct snd_soc_codec *);
struct wcd9xxx_cfilt_mode (*switch_cfilt_mode) (struct wcd9xxx_mbhc *,
bool);
void (*select_cfilt) (struct snd_soc_codec *, struct wcd9xxx_mbhc *);
- void (*free_irq) (struct wcd9xxx_mbhc *);
enum wcd9xxx_cdc_type (*get_cdc_type) (void);
void (*enable_clock_gate) (struct snd_soc_codec *, bool);
int (*setup_zdet) (struct wcd9xxx_mbhc *,
@@ -327,6 +337,9 @@
bool update_z;
+ /* Holds codec specific interrupt mapping */
+ const struct wcd9xxx_mbhc_intr *intr_ids;
+
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_poke;
struct dentry *debugfs_mbhc;
@@ -395,6 +408,7 @@
struct snd_soc_codec *codec,
int (*micbias_enable_cb) (struct snd_soc_codec*, bool),
const struct wcd9xxx_mbhc_cb *mbhc_cb,
+ const struct wcd9xxx_mbhc_intr *mbhc_cdc_intr_ids,
int rco_clk_rate,
bool impedance_det_en);
void wcd9xxx_mbhc_deinit(struct wcd9xxx_mbhc *mbhc);
diff --git a/sound/soc/codecs/wcd9xxx-resmgr.c b/sound/soc/codecs/wcd9xxx-resmgr.c
index 95244c0..cb76342 100644
--- a/sound/soc/codecs/wcd9xxx-resmgr.c
+++ b/sound/soc/codecs/wcd9xxx-resmgr.c
@@ -199,12 +199,17 @@
usleep_range(50, 50);
}
/* Notify */
- if (resmgr->clk_type == WCD9XXX_CLK_RCO)
+ if (resmgr->clk_type == WCD9XXX_CLK_RCO) {
wcd9xxx_resmgr_notifier_call(resmgr,
WCD9XXX_EVENT_POST_RCO_OFF);
- else
+ } else {
+ if (resmgr->codec_type == WCD9XXX_CDC_TYPE_HELICON)
+ snd_soc_update_bits(codec,
+ MSM8X10_WCD_A_CDC_CLK_PDM_CTL, 0x03, 0x00);
+
wcd9xxx_resmgr_notifier_call(resmgr,
WCD9XXX_EVENT_POST_MCLK_OFF);
+ }
pr_debug("%s: leave\n", __func__);
}
diff --git a/sound/soc/msm/msm-pcm-hostless.c b/sound/soc/msm/msm-pcm-hostless.c
index 789749f..0f3573b 100644
--- a/sound/soc/msm/msm-pcm-hostless.c
+++ b/sound/soc/msm/msm-pcm-hostless.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
@@ -18,7 +18,21 @@
#include <sound/soc.h>
#include <sound/pcm.h>
-static struct snd_pcm_ops msm_pcm_hostless_ops = {};
+
+static int msm_pcm_hostless_prepare(struct snd_pcm_substream *substream)
+{
+ if (!substream) {
+ pr_err("%s: invalid params\n", __func__);
+ return -EINVAL;
+ }
+ if (pm_qos_request_active(&substream->latency_pm_qos_req))
+ pm_qos_remove_request(&substream->latency_pm_qos_req);
+ return 0;
+}
+
+static struct snd_pcm_ops msm_pcm_hostless_ops = {
+ .prepare = msm_pcm_hostless_prepare
+};
static struct snd_soc_platform_driver msm_soc_hostless_platform = {
.ops = &msm_pcm_hostless_ops,
diff --git a/sound/soc/msm/msm-pcm-voip.c b/sound/soc/msm/msm-pcm-voip.c
index 22bc9e1..470f44e 100644
--- a/sound/soc/msm/msm-pcm-voip.c
+++ b/sound/soc/msm/msm-pcm-voip.c
@@ -721,6 +721,7 @@
struct snd_pcm_runtime *runtime = substream->runtime;
struct voip_drv_info *prtd = runtime->private_data;
unsigned long dsp_flags;
+ int size;
count = frames_to_bytes(runtime, frames);
@@ -739,14 +740,19 @@
struct voip_buf_node, list);
list_del(&buf_node->list);
spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
- if (prtd->mode == MODE_PCM)
+ if (prtd->mode == MODE_PCM) {
ret = copy_to_user(buf,
&buf_node->frame.voc_pkt,
- count);
- else
+ buf_node->frame.len);
+ } else {
+ size = sizeof(buf_node->frame.header) +
+ sizeof(buf_node->frame.len) +
+ buf_node->frame.len;
+
ret = copy_to_user(buf,
&buf_node->frame,
- count);
+ size;
+ }
if (ret) {
pr_err("%s: Copy to user retuned %d\n",
__func__, ret);
diff --git a/sound/soc/msm/msm8226.c b/sound/soc/msm/msm8226.c
index d1ddfae..40de65b 100644
--- a/sound/soc/msm/msm8226.c
+++ b/sound/soc/msm/msm8226.c
@@ -939,21 +939,21 @@
btn_high = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg,
MBHC_BTN_DET_V_BTN_HIGH);
btn_low[0] = -50;
- btn_high[0] = 10;
- btn_low[1] = 11;
- btn_high[1] = 52;
- btn_low[2] = 53;
- btn_high[2] = 94;
- btn_low[3] = 95;
- btn_high[3] = 133;
- btn_low[4] = 134;
- btn_high[4] = 171;
- btn_low[5] = 172;
- btn_high[5] = 208;
- btn_low[6] = 209;
- btn_high[6] = 244;
- btn_low[7] = 245;
- btn_high[7] = 330;
+ btn_high[0] = 20;
+ btn_low[1] = 21;
+ btn_high[1] = 61;
+ btn_low[2] = 62;
+ btn_high[2] = 104;
+ btn_low[3] = 105;
+ btn_high[3] = 148;
+ btn_low[4] = 149;
+ btn_high[4] = 189;
+ btn_low[5] = 190;
+ btn_high[5] = 228;
+ btn_low[6] = 229;
+ btn_high[6] = 269;
+ btn_low[7] = 270;
+ btn_high[7] = 500;
n_ready = wcd9xxx_mbhc_cal_btn_det_mp(btn_cfg, MBHC_BTN_DET_N_READY);
n_ready[0] = 80;
n_ready[1] = 12;
diff --git a/sound/soc/msm/msm8x10.c b/sound/soc/msm/msm8x10.c
index 4b61db6..c318849 100644
--- a/sound/soc/msm/msm8x10.c
+++ b/sound/soc/msm/msm8x10.c
@@ -29,6 +29,7 @@
#include <qdsp6v2/msm-pcm-routing-v2.h>
#include <sound/q6afe-v2.h>
#include <linux/module.h>
+#include <mach/gpiomux.h>
#include "../codecs/msm8x10-wcd.h"
#define DRV_NAME "msm8x10-asoc-wcd"
#define BTSCO_RATE_8KHZ 8000
@@ -186,6 +187,10 @@
static int msm_config_mclk(u16 port_id, struct afe_digital_clk_cfg *cfg)
{
+ /* set the drive strength on the clock */
+ msm_tlmm_misc_reg_write(TLMM_CDC_HDRV_CTL, 0x00);
+ msm_tlmm_misc_reg_write(TLMM_CDC_HDRV_PULL_CTL, 0x0006db6d);
+
iowrite32(0x1, pcbcr);
/* Set the update bit to make the settings go through */
iowrite32(0x1, prcgr);
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 094c58b..d23eee1 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -1519,7 +1519,8 @@
/* get the cvs cal data */
get_all_vocstrm_cal(&cal_block);
- if (cal_block.cal_size == 0)
+ if (cal_block.cal_size == 0 ||
+ cal_block.cal_size > CVS_CAL_SIZE)
goto fail;
if (v == NULL) {
@@ -1594,7 +1595,8 @@
u16 cvs_handle;
get_all_vocstrm_cal(&cal_block);
- if (cal_block.cal_size == 0)
+ if (cal_block.cal_size == 0 ||
+ cal_block.cal_size > CVS_CAL_SIZE)
return 0;
if (v == NULL) {
@@ -1646,7 +1648,8 @@
struct acdb_cal_block cal_block;
/* get all cvp cal data */
get_all_cvp_cal(&cal_block);
- if (cal_block.cal_size == 0)
+ if (cal_block.cal_size == 0 ||
+ cal_block.cal_size > CVP_CAL_SIZE)
goto fail;
if (is_volte_session(v->session_id) ||
@@ -1787,7 +1790,8 @@
/* get all cvs cal data */
get_all_vocstrm_cal(&cal_block);
- if (cal_block.cal_size == 0)
+ if (cal_block.cal_size == 0 ||
+ cal_block.cal_size > CVS_CAL_SIZE)
goto fail;
if (v == NULL) {
@@ -1859,7 +1863,8 @@
uint32_t cal_paddr = 0;
get_all_vocstrm_cal(&cal_block);
- if (cal_block.cal_size == 0)
+ if (cal_block.cal_size == 0 ||
+ cal_block.cal_size > CVS_CAL_SIZE)
return 0;
if (v == NULL) {
@@ -1928,7 +1933,8 @@
/* get the cvp cal data */
get_all_vocproc_cal(&cal_block);
- if (cal_block.cal_size == 0)
+ if (cal_block.cal_size == 0 ||
+ cal_block.cal_size > CVP_CAL_SIZE)
goto fail;
if (v == NULL) {
@@ -2003,7 +2009,8 @@
u16 cvp_handle;
get_all_vocproc_cal(&cal_block);
- if (cal_block.cal_size == 0)
+ if (cal_block.cal_size == 0 ||
+ cal_block.cal_size > CVP_CAL_SIZE)
return 0;
if (v == NULL) {
@@ -2053,6 +2060,7 @@
struct cvp_register_vol_cal_table_cmd cvp_reg_cal_tbl_cmd;
struct acdb_cal_block vol_block;
struct acdb_cal_block voc_block;
+ struct acdb_cal_block cvp_block;
int ret = 0;
void *apr_cvp;
u16 cvp_handle;
@@ -2062,8 +2070,10 @@
/* get the cvp vol cal data */
get_all_vocvol_cal(&vol_block);
get_all_vocproc_cal(&voc_block);
+ get_all_cvp_cal(&cvp_block);
- if (vol_block.cal_size == 0)
+ if (vol_block.cal_size == 0 ||
+ cvp_block.cal_size > CVP_CAL_SIZE)
goto fail;
if (v == NULL) {
@@ -2135,12 +2145,16 @@
{
struct cvp_deregister_vol_cal_table_cmd cvp_dereg_cal_tbl_cmd;
struct acdb_cal_block cal_block;
+ struct acdb_cal_block voc_block;
int ret = 0;
void *apr_cvp;
u16 cvp_handle;
get_all_vocvol_cal(&cal_block);
- if (cal_block.cal_size == 0)
+ get_all_cvp_cal(&voc_block);
+
+ if (cal_block.cal_size == 0 ||
+ voc_block.cal_size > CVP_CAL_SIZE)
return 0;
if (v == NULL) {
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index 9a2d4d3..01422cf 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -401,7 +401,7 @@
delay = &acdb_data.hw_delay_tx;
if ((delay == NULL) || ((delay != NULL) && delay->num_entries == 0)) {
- pr_err("ACDB=> %s Invalid delay/ delay entries\n", __func__);
+ pr_debug("ACDB=> %s Invalid delay/ delay entries\n", __func__);
result = -EINVAL;
goto done;
}
@@ -455,7 +455,7 @@
}
if ((delay.num_entries <= 0) ||
(delay.num_entries > MAX_HW_DELAY_ENTRIES)) {
- pr_err("ACDB=> %s incorrect no of hw delay entries: %d\n",
+ pr_debug("ACDB=> %s incorrect no of hw delay entries: %d\n",
__func__, delay.num_entries);
result = -EINVAL;
goto done;
@@ -1120,8 +1120,12 @@
atomic_set(&acdb_data.valid_asm_custom_top, 1);
atomic_inc(&usage_count);
+ return result;
+}
+
+static void allocate_hw_delay_entries(void)
+{
/* Allocate memory for hw delay entries */
- mutex_lock(&acdb_data.acdb_mutex);
acdb_data.hw_delay_rx.num_entries = 0;
acdb_data.hw_delay_tx.num_entries = 0;
acdb_data.hw_delay_rx.delay_info =
@@ -1140,9 +1144,6 @@
pr_err("%s : Failed to allocate av sync delay entries tx\n",
__func__);
}
- mutex_unlock(&acdb_data.acdb_mutex);
-
- return result;
}
static int unmap_cal_tables(void)
@@ -1194,15 +1195,17 @@
int i;
pr_debug("%s\n", __func__);
+ mutex_lock(&acdb_data.acdb_mutex);
+ kfree(acdb_data.hw_delay_tx.delay_info);
+ kfree(acdb_data.hw_delay_rx.delay_info);
+
if (atomic64_read(&acdb_data.mem_len)) {
- mutex_lock(&acdb_data.acdb_mutex);
/* unmap all cal data */
result = unmap_cal_tables();
if (result < 0)
pr_err("%s: unmap_cal_tables failed, err = %d\n",
__func__, result);
-
atomic64_set(&acdb_data.mem_len, 0);
for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
@@ -1214,7 +1217,8 @@
acdb_data.ion_handle = NULL;
mutex_unlock(&acdb_data.acdb_mutex);
}
- return result;
+ mutex_unlock(&acdb_data.acdb_mutex);
+ return 0;
}
static int register_memory(void)
@@ -1228,6 +1232,7 @@
pr_debug("%s\n", __func__);
mutex_lock(&acdb_data.acdb_mutex);
+ allocate_hw_delay_entries();
for (i = 0; i < MAX_VOCPROC_TYPES; i++) {
acdb_data.col_data[i] = kmalloc(MAX_COL_SIZE, GFP_KERNEL);
atomic_set(&acdb_data.vocproc_col_cal[i].cal_kvaddr,
@@ -1503,7 +1508,7 @@
static int acdb_mmap(struct file *file, struct vm_area_struct *vma)
{
int result = 0;
- int size = vma->vm_end - vma->vm_start;
+ uint32_t size = vma->vm_end - vma->vm_start;
pr_debug("%s\n", __func__);
@@ -1543,9 +1548,6 @@
else
result = deregister_memory();
- kfree(acdb_data.hw_delay_rx.delay_info);
- kfree(acdb_data.hw_delay_tx.delay_info);
-
return result;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
index caf77ee..c80d2a3 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
@@ -290,6 +290,7 @@
struct output_meta_data_st output_meta_data;
pr_debug("%s: restart\n", __func__);
+ memset(&output_meta_data, 0x0, sizeof(struct output_meta_data_st));
if (runtime->render_flag & SNDRV_RENDER_STOPPED) {
buf = prtd->audio_client->port[IN].buf;
pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n",
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index f6ea266..1b4fae9 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -1640,6 +1640,9 @@
SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
@@ -1652,6 +1655,9 @@
SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
@@ -1883,6 +1889,21 @@
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),
+ SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("VOC_REC_DL", MSM_BACKEND_DAI_INCALL_RECORD_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("VOC_REC_UL", MSM_BACKEND_DAI_INCALL_RECORD_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[] = {
@@ -3265,10 +3286,12 @@
/* incall */
{"Incall_Music Audio Mixer", "MultiMedia1", "MM_DL1"},
{"Incall_Music Audio Mixer", "MultiMedia2", "MM_DL2"},
+ {"Incall_Music Audio Mixer", "MultiMedia5", "MM_DL5"},
{"Incall_Music Audio Mixer", "MultiMedia9", "MM_DL9"},
{"VOICE_PLAYBACK_TX", NULL, "Incall_Music Audio Mixer"},
{"Incall_Music_2 Audio Mixer", "MultiMedia1", "MM_DL1"},
{"Incall_Music_2 Audio Mixer", "MultiMedia2", "MM_DL2"},
+ {"Incall_Music_2 Audio Mixer", "MultiMedia5", "MM_DL5"},
{"Incall_Music_2 Audio Mixer", "MultiMedia9", "MM_DL9"},
{"VOICE2_PLAYBACK_TX", NULL, "Incall_Music_2 Audio Mixer"},
{"SLIMBUS_4_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
@@ -3276,7 +3299,9 @@
{"SLIMBUS_4_RX", NULL, "SLIMBUS_4_RX Audio Mixer"},
{"MultiMedia1 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
+ {"MultiMedia4 Mixer", "VOC_REC_UL", "INCALL_RECORD_TX"},
{"MultiMedia1 Mixer", "VOC_REC_DL", "INCALL_RECORD_RX"},
+ {"MultiMedia4 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"},
@@ -3371,11 +3396,14 @@
{"PCM_RX", NULL, "AFE_PCM_RX Audio Mixer"},
{"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
+ {"MultiMedia4 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
{"MultiMedia5 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
{"MultiMedia1 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
+ {"MultiMedia4 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"MultiMedia5 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"MultiMedia1 Mixer", "AFE_PCM_TX", "PCM_TX"},
+ {"MultiMedia4 Mixer", "AFE_PCM_TX", "PCM_TX"},
{"MultiMedia5 Mixer", "AFE_PCM_TX", "PCM_TX"},
{"MM_UL1", NULL, "MultiMedia1 Mixer"},
{"MultiMedia2 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
index 6cfc2ef..af25454 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voip-v2.c
@@ -615,6 +615,7 @@
struct snd_pcm_runtime *runtime = substream->runtime;
struct voip_drv_info *prtd = runtime->private_data;
unsigned long dsp_flags;
+ int size;
count = frames_to_bytes(runtime, frames);
@@ -633,14 +634,19 @@
struct voip_buf_node, list);
list_del(&buf_node->list);
spin_unlock_irqrestore(&prtd->dsp_ul_lock, dsp_flags);
- if (prtd->mode == MODE_PCM)
+ if (prtd->mode == MODE_PCM) {
ret = copy_to_user(buf,
&buf_node->frame.voc_pkt,
- count);
- else
+ buf_node->frame.pktlen);
+ } else {
+ size = sizeof(buf_node->frame.frm_hdr) +
+ sizeof(buf_node->frame.pktlen) +
+ buf_node->frame.pktlen;
+
ret = copy_to_user(buf,
&buf_node->frame,
- count);
+ size);
+ }
if (ret) {
pr_err("%s: Copy to user retuned %d\n",
__func__, ret);
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 59113fe..09ecd75 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -648,7 +648,7 @@
ret = get_hw_delay(RX_CAL, &delay_entry);
if (ret != 0) {
- pr_warn("%s: Failed to get hw delay info\n", __func__);
+ pr_debug("%s: Failed to get hw delay info\n", __func__);
goto fail_cmd;
}
index = q6audio_get_port_index(port_id);
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 9c0c362..7c4547e 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -78,6 +78,12 @@
void *q6asm_mmap_apr_reg(void);
+/* for ASM custom topology */
+static struct audio_buffer common_buf[2];
+static struct audio_client common_client;
+static int set_custom_topology;
+static int topology_map_handle;
+
#ifdef CONFIG_DEBUG_FS
#define OUT_BUFFER_SIZE 56
#define IN_BUFFER_SIZE 24
@@ -95,10 +101,6 @@
static int out_cold_index;
static char *out_buffer;
static char *in_buffer;
-static struct audio_buffer common_buf[2];
-static struct audio_client common_client;
-static int set_custom_topology;
-static int topology_map_handle;
int q6asm_mmap_apr_dereg(void)
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index c16b14c..673ecff 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -1958,20 +1958,22 @@
if (!common.apr_q6_cvs) {
pr_err("%s: apr_cvs is NULL\n", __func__);
- ret = -EPERM;
+ ret = -EINVAL;
goto done;
}
if (!common.cal_mem_handle) {
pr_err("%s: Cal mem handle is NULL\n", __func__);
- ret = -EPERM;
+
+ ret = -EINVAL;
goto done;
}
get_vocstrm_cal(&cal_block);
if (cal_block.cal_size == 0) {
pr_err("%s: CVS cal size is 0\n", __func__);
- ret = -EPERM;
+
+ ret = -EINVAL;
goto done;
}
@@ -1992,6 +1994,15 @@
/* Get the column info corresponding to CVS cal from ACDB. */
get_voice_col_data(VOCSTRM_CAL, &cal_block);
+ if (cal_block.cal_size == 0 ||
+ cal_block.cal_size >
+ sizeof(cvs_reg_cal_cmd.cvs_cal_data.column_info)) {
+ pr_err("%s: Invalid VOCSTRM_CAL size %d\n",
+ __func__, cal_block.cal_size);
+
+ ret = -EINVAL;
+ goto done;
+ }
memcpy(&cvs_reg_cal_cmd.cvs_cal_data.column_info[0],
(void *) cal_block.cal_kvaddr,
cal_block.cal_size);
@@ -2238,20 +2249,22 @@
if (!common.apr_q6_cvp) {
pr_err("%s: apr_cvp is NULL\n", __func__);
- ret = -EPERM;
+ ret = -EINVAL;
goto done;
}
if (!common.cal_mem_handle) {
pr_err("%s: Cal mem handle is NULL\n", __func__);
- ret = -EPERM;
+
+ ret = -EINVAL;
goto done;
}
get_vocproc_cal(&cal_block);
if (cal_block.cal_size == 0) {
pr_err("%s: CVP cal size is 0\n", __func__);
- ret = -EPERM;
+
+ ret = -EINVAL;
goto done;
}
@@ -2272,6 +2285,16 @@
/* Get the column info corresponding to CVP cal from ACDB. */
get_voice_col_data(VOCPROC_CAL, &cal_block);
+ if (cal_block.cal_size == 0 ||
+ cal_block.cal_size >
+ sizeof(cvp_reg_cal_cmd.cvp_cal_data.column_info)) {
+ pr_err("%s: Invalid VOCPROC_CAL size %d\n",
+ __func__, cal_block.cal_size);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
memcpy(&cvp_reg_cal_cmd.cvp_cal_data.column_info[0],
(void *) cal_block.cal_kvaddr,
cal_block.cal_size);
@@ -2378,20 +2401,22 @@
if (!common.apr_q6_cvp) {
pr_err("%s: apr_cvp is NULL\n", __func__);
- ret = -EPERM;
+ ret = -EINVAL;
goto done;
}
if (!common.cal_mem_handle) {
pr_err("%s: Cal mem handle is NULL\n", __func__);
- ret = -EPERM;
+
+ ret = -EINVAL;
goto done;
}
get_vocvol_cal(&cal_block);
if (cal_block.cal_size == 0) {
pr_err("%s: CVP vol cal size is 0\n", __func__);
- ret = -EPERM;
+
+ ret = -EINVAL;
goto done;
}
@@ -2414,6 +2439,16 @@
/* Get the column info corresponding to CVP volume cal from ACDB. */
get_voice_col_data(VOCVOL_CAL, &cal_block);
+ if (cal_block.cal_size == 0 ||
+ cal_block.cal_size >
+ sizeof(cvp_reg_vol_cal_cmd.cvp_vol_cal_data.column_info)) {
+ pr_err("%s: Invalid VOCVOL_CAL size %d\n",
+ __func__, cal_block.cal_size);
+
+ ret = -EINVAL;
+ goto done;
+ }
+
memcpy(&cvp_reg_vol_cal_cmd.cvp_vol_cal_data.column_info[0],
(void *) cal_block.cal_kvaddr,
cal_block.cal_size);