Merge "msm: kgsl: a2xx: Check the right interrupt status bits"
diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX
index 2214f12..755d817 100644
--- a/Documentation/00-INDEX
+++ b/Documentation/00-INDEX
@@ -72,6 +72,8 @@
- misc. LCD driver documentation (cfag12864b, ks0108).
basic_profiling.txt
- basic instructions for those who wants to profile Linux kernel.
+bif-framework.txt
+ - information about MIPI-BIF support in the Linux kernel.
binfmt_misc.txt
- info on the kernel support for extra binary formats.
blackfin/
diff --git a/Documentation/bif-framework.txt b/Documentation/bif-framework.txt
new file mode 100644
index 0000000..3ba500d
--- /dev/null
+++ b/Documentation/bif-framework.txt
@@ -0,0 +1,508 @@
+Introduction
+============
+
+BIF (Battery Interface) is a MIPI (Mobile Industry Processor Interface)
+Alliance specification for a serial interface between a host device and a
+battery pack. It provides a means to handle smart battery packs which can
+communicate over BIF as well as low cost battery packs which provide no
+serial communication interface.
+
+The BIF bus supports 1 master and up to 256 slaves. It supports data rates
+up to 250 kbps. The master is in charge of initiating all bus
+communications. Slaves may only respond asynchronously when they need to
+signal the master that they have an interrupt pending and when the bus is
+configured for interrupt mode.
+
+The BIF framework consists of a core into which BIF controller drivers
+register. At runtime, consumers are notified of various events (e.g. battery
+insertion and battery removal) via a notifier. Various framework functions are
+available for consumers to read and write slave registers as well as to send
+arbitrary BIF commands on the bus.
+
+Hardware description
+====================
+
+The BIF bus is a 1-wire wired-or interface. The bus signal is referred to as
+the battery communication line (BCL). The BCL is pulled high by a resistor on
+the host side and is driven low when the master or one of the slaves is
+communicating. Additionally, there is a pull down resistor in the battery
+pack which is used to identify whether or not the battery pack has BIF slaves.
+Battery removal detection is achieved by comparing the analog voltage of the BCL
+when idle to the host side reference voltage. If these voltages are within a
+certain threshold, then a battery pack is not present.
+
+Slaves are addressed on the BIF bus using an 8-bit device address (DEV_ADR).
+Notably, it is possible for no slaves to have defined DEV_ADR. In this case,
+slave addressing is achieved via the always present unique ID (UID). The UID
+of a slave is 80 bits long and guaranteed to be globally unique. A UID search
+algorithm can be followed in order determine the UID of all slaves on the bus.
+
+BIF slaves come in two varieties: primary and secondary. A single primary
+slave may be present on the battery pack and a single primary slave may be
+present on the host. A battery pack primary slave has DEV_ADR=0x01. The
+DEV_ADR of a host primary slave is set by the manufacturer. A given primary
+slave contains a list of the UIDs of all secondary slaves in the same
+subsystem. This provides a fast mechanism to determine the address of all
+slaves without having to resort to the lengthy UID search algorithm.
+
+Each slave has a 64 kB address space. Part of this address space consists of
+generic DDB L1 and L2 data structures at known addresses. This allows for
+runtime discovery of supported battery properties and functions of a given
+smart battery pack.
+
+System Diagram:
+ +-------------------------------+ +---------------------------------+
+ | Host | | Smart Battery Pack |
+ | | | |
+ | Vbat-<+>-------<+>----------------------------+ |
+ | | | | |
+ | +--------------+ | | +--------------+ | |
+ | | Master BIF<+>-+---------<+>--BCL--<+>------+-<+>BIF Primary | | |
+ | | | | | | | | Slave | | |
+ | +--------------+ | | | | +--------------+ | |
+ | | | | | | |
+ | + - - - - - - -+ | | | | + - - - - - - -+ | |
+ | | Primary BIF<+>-+ | | +-<+>BIF Secondary| | |
+ | | Slave | | | | | | Slave | | |
+ | +- - - - - - - + | | | | +-- - - - - - -+ | |
+ | | | | | | |
+ | + - - - - - - -+ | | | | + - - - - - - -+ | |
+ | |Secondary BIF<+>-+ | | +-<+>BIF Secondary| | |
+ | |Slave | | | | | | Slave | | |
+ | +- - - - - - - + | | | | +-- - - - - - -+ | |
+ | / | | / | |
+ | Vref \ Rpu | | Rid \ ---- |
+ | ___ / | | / Battery -- |
+ | | \ | | \ Cell ---- |
+ | +-------+ | | | -- |
+ | | | | | |
+ | GND-<+>-------<+>------+---------------------+ |
+ | | | |
+ +-------------------------------+ +---------------------------------+
+
+An overview of BIF is available at:
+http://mipi.org/specifications/battery-interface
+
+Software description
+====================
+
+A given BIF hardware interface driver registers as a BIF controller in the
+BIF framework during its probe function. The controller specifies a set of
+callback functions which are used by the BIF framework to initiate bus
+transactions (e.g. register read, register write, wait for slave interrupt)
+and to configure the bus. The framework exposes a small API to controllers
+which is used to notify the framework about asynchronous events such as
+battery pack insertion/removal and slave interrupts.
+
+A given BIF consumer is linked to a BIF controller by specifying a property
+in the consumer's device tree node which takes as its value the phandle of
+the BIF controller's device tree node.
+
+A consumer driver calls a get function during its probe function with its
+device pointer in order to get a handle to the BIF controller if it has probed.
+If it hasn't, then ERR_PTR(-EPROBE_DEFER) is returned. The controller handle
+can be used directly by the consumer to issue raw bus transactions if needed.
+The controller handle can then be used to query which slaves are currently
+present on the bus, if any. Handles to these slaves may be used by a consumer
+driver in high level framework APIs such as register read and register write
+which are slave oriented. All BIF framework API functions are synchronous,
+blocking, and can sleep.
+
+Consumer drivers may also register a notifier function which is called when
+certain bus activities occur such as battery pack insertion and removal.
+Additionally, consumer drivers may register a notifier function which is called
+when a specified slave interrupt fires.
+
+The framework maintains several linked-lists. One list contains all controllers
+that have been registered. A second list contains all slaves that have been
+seen since the system booted as well as a flag to indicate if they are currently
+present or not. This scheme is used to avoid issues with slave handles existing
+after a slave is removed and also so that function and object values do not have
+to be searched when a slave is reinserted in the system since slaves are
+globally unique and these features are read-only. Two further lists are
+maintained inside slave device structures which contain BIF functions and
+objects found in the slave. API functions are provided so that consumers can
+find functions supported by slaves.
+
+Design
+======
+
+Design Goals:
+One major goal of the BIF framework is to provide a uniform API for BIF
+consumers to communicate with battery packs. This ensures that consumers are
+unaffected by changes in the controller driver which actually interfaces with
+the BCL at a hardware level.
+
+Another goal of the framework is to ensure the BIF bus can be shared between
+multiple consumers in a simple and functionally correct way. Locking is used
+inside of the framework to provide mutual exclusion on the bus.
+
+The framework also exposes features that almost all consumers will need, such
+as BIF slave identification and BIF function enumeration within a given slave.
+
+The framework allows consumers to issue very specific bus commands which may
+not be used within high level APIs. This provides maximum flexibility so
+that consumers can make use of manufacturer defined bus commands which cannot be
+handled in a generic fashion.
+
+Design Trade-offs:
+The choice to not treat BIF like a traditional Linux bus was made because
+there is nothing within BIF that naturally maps to a device on the bus for a
+driver to manage. Slave devices would be a good candidate except that
+consumers will not be managing slaves so much as functions exposed within
+slaves. Bus matching could then instead be made at a BIF slave function
+level. Unfortunately, the BIF specification allows for manufacturer specific
+features to reside at any non-defined addresses. Additionally, consumers may
+wish only to read and make policy decisions based on BIF non-volatile memory
+(NVM) objects read out of memory. Thus, there are use-cases that require
+consumers to utilize the bus without having a particular function to match to.
+
+Another trade-off was the choice to use custom interrupt handling functions
+instead of the Linux interrupt framework. This choice was made because there is
+no obvious way to handle IRQ chip registration given the dynamic nature of BIF
+slaves (i.e. slaves may come and go at runtime if battery packs are swapped).
+
+Software layering:
+BIF controller drivers register a set of callback functions with the BIF
+framework which implement various BIF transaction primitives. These
+callbacks ensure that tight timing constraints are met such as when receiving
+a bus query response immediately after issuing a command. Such actions
+cannot be carried out at the framework level as timing requirements are on
+the order of 32 us when using the maximum data rate.
+
+The BIF framework provides easy access to standard BIF features such as
+slave, functions, and interrupts. The framework also ensures mutual exclusion
+between different BIF consumers.
+
+BIF consumer drivers make use of the API exposed by the framework in order
+utilize functionality found on smart battery packs. One example of a
+consumer driver is a temperature monitoring driver which reads the
+temperature reported by the BIF temperature function on a BIF slave and
+reports it to the Linux thermal framework.
+
+Power Management
+================
+
+The framework does not perform any special actions during system suspend and
+resume. Controller drivers may choose to enter low power states during
+suspend if they wish as long as it does not affect the logical state of the
+bus.
+
+SMP/multi-core
+==============
+
+Various linked lists are maintained inside of the framework which are
+protected by mutexes. Mutex locks are also used during transactions at a bus
+level in order to ensure mutual exclusion between consumers of the bus.
+
+Performance
+===========
+
+The BIF bus is inherently slow. Consumers should expect transactions to take
+a long time to execute. Consumers are responsible for blocking suspend if
+their transactions must be completed before the system enters suspend.
+
+Interface - BIF Consumer API
+============================
+
+BIF framework structs, enums, and functions used by BIF consumers are defined in
+include/linux/bif/consumer.h
+
+Detailed descriptions of the BIF framework functions can be found in:
+drivers/bif/bif-core.c
+
+Get/put handle for a BIF controller:
+------------------------------------
+
+struct bif_ctrl *bif_ctrl_get(struct device *consumer_dev);
+
+void bif_ctrl_put(struct bif_ctrl *ctrl);
+
+int bif_ctrl_count(void);
+
+struct bif_ctrl *bif_ctrl_get_by_id(unsigned int id);
+
+The function bif_ctrl_get() is intended to be the primary way to get a consumer
+BIF controller handle. It relies upon the consumer device specifying a
+"qcom,bif-ctrl" property in its device tree node which points to the phandle of
+the BIF controller it wishes to use.
+
+A secondary mechanism is also provided for drivers without device tree support.
+bif_ctrl_count() returns the number of BIF controllers currently registered.
+bif_ctrl_get_by_id() returns a handle to the id'th controller enumerated in
+registration order.
+
+Get/put handle for a BIF slave:
+-------------------------------
+
+int bif_slave_match_count(const struct bif_ctrl *ctrl,
+ const struct bif_match_criteria *match_criteria);
+
+struct bif_slave *bif_slave_match_get(const struct bif_ctrl *ctrl,
+ unsigned int id, const struct bif_match_criteria *match_criteria);
+
+void bif_slave_put(struct bif_slave *slave);
+
+A consumer finds a slave attached to a given BIF controller by specifying a set
+of matching criteria. The criteria can include such quantities as manufacturer
+ID, product ID, function type or function version. It is possible that multiple
+slaves will match the criteria. bif_slave_match_count() returns how many slaves
+match the specified criteria. bif_slave_match_get() returns the id'th slave
+which matches the criteria in an arbitrary, but fixed order (for a constant set
+of slaves). Consumer drivers need to be able to handle the case of multiple
+slaves matching the criteria.
+
+Additionally, if a battery pack is inserted or removed, then the output of
+bif_slave_match_count() and bif_slave_match_get() could change. A consumer
+driver can register to receive notification of battery pack insertion and
+removal using the bif_ctrl_notifier_register() function listed below.
+
+Check if slave handle is still meaningful:
+------------------------------------------
+
+int bif_slave_is_present(struct bif_slave *slave);
+
+If a battery pack is removed, then the handles for its slaves will no longer be
+meaningful. All transactions using a handle for a slave that isn't present will
+fail. The function bif_slave_is_present() allows a consumer to determine if
+a given slave is still physically present in the system.
+
+Get access to the controller handle present in a slave handle:
+--------------------------------------------------------------
+
+struct bif_ctrl *bif_get_ctrl_handle(struct bif_slave *slave);
+
+This function is useful if a consumer wishes to only store a slave handle but
+also has need to call bus oriented BIF framework functions.
+
+Get version and register offset of a BIF function if it is present in a slave:
+------------------------------------------------------------------------------
+
+int bif_slave_find_function(struct bif_slave *slave, u8 function, u8 *version,
+ u16 *function_pointer);
+
+This function is used by consumers who wish to support given BIF functions
+(e.g. temperature measurement, authentication, etc.) found inside of slaves.
+
+Receive notification upon battery insertion and removal:
+--------------------------------------------------------
+
+int bif_ctrl_notifier_register(struct bif_ctrl *ctrl,
+ struct notifier_block *nb);
+
+int bif_ctrl_notifier_unregister(struct bif_ctrl *ctrl,
+ struct notifier_block *nb);
+
+
+Read or write BIF slave registers:
+----------------------------------
+
+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);
+
+
+Get or set the BIF bus state or period:
+---------------------------------------
+
+int bif_ctrl_get_bus_state(struct bif_ctrl *ctrl);
+
+int bif_ctrl_set_bus_state(struct bif_ctrl *ctrl, enum bif_bus_state state);
+
+int bif_ctrl_get_bus_period(struct bif_ctrl *ctrl);
+
+int bif_ctrl_set_bus_period(struct bif_ctrl *ctrl, int period_ns);
+
+Bus states include: active for communication, active waiting for interrupt,
+standby, and power down. The MIPI-BIF specification defines the allowed range
+of bus periods as 2000 ns to 153000 ns. Individual controllers may further
+restrict the range of allowed periods. When bif_ctrl_set_bus_period() is called
+the first supported period that greater than or equal to the specified period
+will be set.
+
+Measure battery pack resistance:
+--------------------------------
+
+int bif_ctrl_measure_rid(struct bif_ctrl *ctrl);
+
+This function returns an estimate of the battery pack resistance in ohms. If
+no battery pack is connected, then the output of this function is undefined.
+
+Utilize BIF slave tasks and interrupts:
+---------------------------------------
+
+int bif_request_irq(struct bif_slave *slave, unsigned int task,
+ struct notifier_block *nb);
+
+int bif_free_irq(struct bif_slave *slave, unsigned int task,
+ struct notifier_block *nb);
+
+int bif_trigger_task(struct bif_slave *slave, unsigned int task);
+
+int bif_task_is_busy(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.
+
+Raw BIF bus transactions:
+-------------------------
+
+void bif_ctrl_bus_lock(struct bif_ctrl *ctrl);
+
+void bif_ctrl_bus_unlock(struct bif_ctrl *ctrl);
+
+int bif_ctrl_raw_transaction(struct bif_ctrl *ctrl, int transaction, u8 data);
+
+int bif_ctrl_raw_transaction_read(struct bif_ctrl *ctrl, int transaction,
+ u8 data, int *response);
+
+int bif_ctrl_raw_transaction_query(struct bif_ctrl *ctrl, int transaction,
+ u8 data, bool *query_response);
+
+int bif_slave_is_selected(struct bif_slave *slave);
+
+int bif_slave_select(struct bif_slave *slave);
+
+The function bif_ctrl_bus_lock() locks the BIF bus for exclusive use by the
+consumer. No other transactions will be allowed on the bus including those
+that would arise from battery insertion/removal or slave interrupt reception.
+This lock is primarily intended to be used along with the raw transaction
+functions. These functions allow a consumer to issue any BIF transaction
+including manufacturer specific bus commands not handled by the BIF framework.
+
+While performing raw transactions, features normally performed transparently by
+the core, such as device selection, are not available. The functions
+bif_slave_select() and bif_slave_is_selected() can be used to fill in this gap
+so that raw transactions are performed on the desired slave.
+
+Notify the BIF core that a battery has been inserted or removed:
+----------------------------------------------------------------
+
+int bif_ctrl_signal_battery_changed(struct bif_ctrl *ctrl);
+
+This function should only be called on systems where the BIF controller driver
+is architecturally unable to detect battery insertion and removal on its own.
+
+Perform BIF object CRC using CRC-CCITT algorithm:
+-------------------------------------------------
+
+u16 bif_crc_ccitt(const u8 *buffer, int len);
+
+Interface - BIF Controller API
+==============================
+
+BIF framework structs and functions used by BIF controllers are defined in:
+include/linux/bif/driver.h
+
+Ops found in struct bif_ctrl_ops:
+---------------------------------
+
+int (*bus_transaction) (struct bif_ctrl_dev *bdev, int transaction, u8 data);
+
+int (*bus_transaction_query) (struct bif_ctrl_dev *bdev, int transaction,
+ u8 data, bool *query_response);
+
+int (*bus_transaction_read) (struct bif_ctrl_dev *bdev, int transaction,
+ u8 data, int *response);
+
+int (*read_slave_registers) (struct bif_ctrl_dev *bdev, u16 addr,
+ u8 *data, int len);
+
+int (*write_slave_registers) (struct bif_ctrl_dev *bdev, u16 addr,
+ const u8 *data, int len);
+
+int (*get_bus_period) (struct bif_ctrl_dev *bdev);
+
+int (*set_bus_period) (struct bif_ctrl_dev *bdev, int period_ns);
+
+int (*get_battery_presence) (struct bif_ctrl_dev *bdev);
+
+int (*get_battery_rid) (struct bif_ctrl_dev *bdev);
+
+int (*get_bus_state) (struct bif_ctrl_dev *bdev);
+
+int (*set_bus_state) (struct bif_ctrl_dev *bdev, int state);
+
+A BIF controller driver registers a set of call back functions which instantiate
+these ops. The BIF framework then calls these functions based on internal and
+consumer needs.
+
+The ops bus_transaction(), bus_transaction_query(), and bus_transaction_read()
+carry out the controller hardware specific actions to perform BIF transactions
+on the BIF bus. These transactions result in no slave response, a pulse in
+response, or a word in response respectively. The ops read_slave_registers()
+and write_slave_registers() internally must perform all transactions necessary
+to read and write to BIF slave registers. These ops exist so that burst reads
+and writes can take place since these activities have very tight timing
+constraints that the BIF core cannot handle.
+
+The ops get_bus_period() and set_bus_period() return the current bus clock base
+period in nanoseconds and change the period to a new value respectively. The
+ops get_bus_state() and set_bus_state() allow for monitoring and controlling the
+bus state (i.e. active for communication, active waiting for interrupt, standby,
+or power down). The op get_battery_presence() returns if any battery pack
+(smart or low cost) is currently connected to the BCL. The op get_battery_rid()
+returns a best estimate of the Rid battery pack pull down ID resistance in ohms
+which can be used to determine if the battery pack is smart or low cost.
+
+Register/unregister a BIF controller:
+-------------------------------------
+
+struct bif_ctrl_dev *bif_ctrl_register(struct bif_ctrl_desc *bif_desc,
+ struct device *dev, void *driver_data, struct device_node *of_node);
+
+void bif_ctrl_unregister(struct bif_ctrl_dev *bdev);
+
+Notify the BIF framework that a battery has been inserted or removed:
+---------------------------------------------------------------------
+
+int bif_ctrl_notify_battery_changed(struct bif_ctrl_dev *bdev);
+
+The BIF core will then call the get_battery_presence() op internally to
+determine if the event is an insertion or removal.
+
+Notify the BIF framework that a slave interrupt has been received:
+------------------------------------------------------------------
+
+int bif_ctrl_notify_slave_irq(struct bif_ctrl_dev *bdev);
+
+Upon receiving this call, the BIF core interrogates each slave to determine
+which slaves have pending interrupts. It then iterates through all interrupts
+on those slaves clearing all pending interrupts and notifying any consumers
+waiting for the interrupts.
+
+Get BIF controller private data:
+--------------------------------
+
+void *bdev_get_drvdata(struct bif_ctrl_dev *bdev);
+
+Config options
+==============
+
+CONFIG_BIF - Enables BIF framework support.
+
+User space utilities
+====================
+
+No user space interface is provided in the BIF framework. Therefore, user
+space will not be able to directly use it.
+
+To do
+=====
+
+It is conceivable that the BIF framework should take some action during
+system suspend and resume. However, it is not clear exactly what should be
+done given that the BCL would still need to be active in order to detect
+battery removal while suspended.
+
+sysfs nodes could be added which describe slaves as well as functions and
+objects within the slaves. However these nodes would be read-only and would
+really only be useful for descriptive as opposed to control purposes.
+
+The exact time at which slave searching, function enumeration, and object
+loading takes place could be optimized in order to improve performance to
+some degree. It could also be made configurable at a controller level if
+needed.
diff --git a/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt b/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
index 53a67a4..9616a94 100644
--- a/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
+++ b/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
@@ -7,6 +7,7 @@
Optional properties:
-qcom,satellite-mode: the hardware needs to be configured in satellite mode
+-qcom,rx-ring-size: the size of the receive ring buffer pool, default is 32
Example:
@@ -15,4 +16,5 @@
reg = <0xfc834000 0x7000>;
interrupts = <0 29 1>;
qcom,satellite-mode;
+ qcom,rx-ring-size = <64>;
};
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 0588c5e..a9528c5 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -55,8 +55,36 @@
- label: A string used as a descriptive name of the panel
- qcom,enable-gpio: Specifies the panel lcd/display enable gpio.
- qcom,rst-gpio: Specifies the panel reset gpio.
+- qcom,te-gpio: Specifies the gpio used for TE.
+- qcom,dsi-lpg-channel : LPG channel for backlight.
+- qcom,dsi-pwm-period : PWM period in microseconds.
+- qcom,dsi-pwm-gpio : PWM gpio.
- qcom,mdss-pan-broadcast-mode: Boolean used to enable broadcast mode.
- qcom,cont-splash-enabled: Boolean used to enable continuous splash mode.
+- qcom,fbc-enabled: Boolean used to enable frame buffer compression mode.
+- qcom,fbc-mode-select: An array of length 7 that specifies the fbc mode supported
+ by the panel. FBC enabled panels may or may not support
+ the modes specified here. Each entry will
+ have the format specified below:
+ --> compressed bpp supported by the panel
+ --> component packing
+ --> enable/disable quantization error calculation
+ --> Bias for CD
+ --> enable/disable PAT mode
+ --> enable/disable VLC mode
+ --> enable/disable BFLC mode
+- qcom,fbc-budget-ctl: An array of length 3 that specifies the budget control settings
+ supported by the fbc enabled panel. Each entry will have the format
+ specified below:
+ --> per line extra budget
+ --> extra budget level
+ --> per block budget
+- qcom,fbc-lossy-mode: An array of 3 that specifies the lossy mode settings
+ supported by the fbc enabled panel. Each entry will
+ have the format specified below:
+ --> lossless mode threshold
+ --> lossy mode threshold
+ --> lossy RGB threshold
- qcom,mdss-pan-porch-values: An array of size 6 that specifies the panel blanking values.
- qcom,mdss-pan-underflow-clr: Specifies the controller settings for the panel underflow clear
settings. Default value is 0xff.
@@ -71,6 +99,15 @@
- qcom,mdss-pan-dsi-mode: Specifies the panel operating mode.
0 = enable video mode(default mode).
1 = enable command mode.
+- qcom,mdss-vsync-enable: Specifies Tear Check configuration.
+ 0 = TE disable.
+ 1 = TE enable.
+- qcom,mdss-hw-vsync-mode: Specifies TE type.
+ 0 = software vsync.
+ 1 = hardware vsync (TE gpio pin).
+- qcom,mdss-pan-te-sel: Specifies TE operating mode.
+ 0 = TE through embedded dcs command
+ 1 = TE through TE gpio pin.
- qcom,mdss-pan-dsi-h-pulse-mode: Specifies the pulse mode option for the panel.
0 = Don't send hsa/he following vs/ve packet(default)
1 = Send hsa/he following vs/ve packet
@@ -171,5 +208,9 @@
qcom,on-cmds-dsi-state = "DSI_LP_MODE";
qcom,panel-off-cmds = [22 01 00 00 00 00 00];
qcom,off-cmds-dsi-state = "DSI LP MODE";
+ qcom,fbc-enabled;
+ qcom,fbc-mode = <12 0 1 2 1 1 1>;
+ qcom,fbc-budget-ctl = <675 5 91>;
+ qcom,fbc-lossy-mode = <0 0xc0 0 3>;
};
};
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 497471a..0422b57 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -75,6 +75,12 @@
The number of dspp blocks should match the
number of mixers driving data to interface
defined in property: qcom,mdss-mixer-intf-off
+- qcom,mdss-pingpong-off: Array of offset addresses for the available
+ pingpong blocks. These offsets are calculated
+ from regsiter "mdp_phys" defined in reg property.
+ The number of pingpong blocks should match the
+ number of mixers driving data to interface
+ defined in property: qcom,mdss-mixer-intf-off
- qcom,mdss-mixer-wb-off: Array of offset addresses for the available
mixer blocks that can be drive data to writeback
block. These offsets will be calculated from
@@ -142,6 +148,7 @@
0x00003A00>;
qcom,mdss-mixer-wb-off = <0x00003E00 0x00004200>;
qcom,mdss-dspp-off = <0x00004600 0x00004A00 0x00004E00>;
+ qcom,mdss-pingpong-off = <0x00012D00 0x00012E00 0x00012F00>;
qcom,mdss-wb-off = <0x00011100 0x00013100 0x00015100
0x00017100 0x00019100>;
qcom,mdss-intf-off = <0x00021100 0x00021300
diff --git a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
index b31ec30..d24139b 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/synaptics_i2c_rmi4.txt
@@ -20,6 +20,7 @@
- synaptics,y-flip : modify orientation of the y axis
- synaptics,panel-x : panel x dimension
- synaptics,panel-y : panel y dimension
+ - synaptics,fw-image-name : name of firmware .img file in /etc/firmware
Example:
i2c@f9927000 { /* BLSP1 QUP5 */
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
index 812a895..4f31f07 100644
--- a/Documentation/devicetree/bindings/leds/leds-qpnp.txt
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -30,7 +30,7 @@
- qcom,ctrl-delay-us: delay in activation of led
- qcom,dig-mod-gen-en: digital module generator
- qcom,cs-out-en: current sink output enable
-- qcom,op-fdbck: selection of output as feedback for the boost
+- qcom,op-fdbck: selection of output as feedback for the boost, 00 = automatic selection, 01 = select LED1 output, 02 = select LED2 output, 03 = select LED3 output
- qcom,cp-select: high pole capacitance
- linux,default-trigger: trigger the led from external modules such as display
- qcom,default-state: default state of the led, should be "on" or "off"
@@ -138,7 +138,7 @@
linux,default-trigger = "bkl-trigger"
label = "wled";
qcom,cs-out-en;
- qcom,op-fdbck;
+ qcom,op-fdbck = <1>;
qcom,default-state "off";
qcom,max-current = <25>;
qcom,ctrl-delay-us = <0>;
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index bebdb5a..2caa959 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -40,6 +40,8 @@
(enum hal_buffer) to its corresponding TZ usage. The TZ usages are defined
as "enum cp_mem_usage" in include/linux/msm_ion.h
- qcom,has-ocmem: indicate the target has ocmem if this property exists
+- qcom,max-hw-load: The maximum load the hardware can support expressed in units
+ of macroblocks per second.
Example:
@@ -73,4 +75,5 @@
qcom,iommu-group-buffer-types = <0xfff 0x1ff>;
qcom,buffer-type-tz-usage-table = <0x1 0x1>,
<0x1fe 0x2>;
+ qcom,max-hw-load = <1224450>; /* 4k @ 30 + 1080p @ 30*/
};
diff --git a/Documentation/devicetree/bindings/pil/pil-pronto.txt b/Documentation/devicetree/bindings/pil/pil-pronto.txt
index e3108ac..ad35985 100644
--- a/Documentation/devicetree/bindings/pil/pil-pronto.txt
+++ b/Documentation/devicetree/bindings/pil/pil-pronto.txt
@@ -13,6 +13,8 @@
- interrupts: WCNSS to Apps watchdog bite interrupt
- vdd_pronto_pll-supply: regulator to supply pronto pll.
- qcom,firmware-name: Base name of the firmware image. Ex. "wcnss"
+- qcom,gpio-err-fatal: GPIO used by the wcnss to indicate error fatal to the Apps.
+- qcom,gpio-force-stop: GPIO used by the Apps to force the wcnss to shutdown.
Example:
qcom,pronto@fb21b000 {
@@ -25,4 +27,10 @@
interrupts = <0 231 1>;
qcom,firmware-name = "wcnss";
+
+ /* GPIO input from wcnss */
+ qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+
+ /* GPIO output to wcnss */
+ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
};
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index acd0ae3..383da0c 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -46,8 +46,8 @@
qcom,pil-self-auth;
/* GPIO inputs from mss */
- gpio_err_fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+ qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
/* GPIO output to mss */
- gpio_force_stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
+ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
};
diff --git a/Documentation/devicetree/bindings/qseecom/qseecom.txt b/Documentation/devicetree/bindings/qseecom/qseecom.txt
index 43033a8..ac82387 100644
--- a/Documentation/devicetree/bindings/qseecom/qseecom.txt
+++ b/Documentation/devicetree/bindings/qseecom/qseecom.txt
@@ -3,6 +3,9 @@
Required properties:
- compatible : Should be "qcom,qseecom"
- reg : should contain memory region address reserved for loading secure apps.
+- qcom,disk-encrypt-pipe-pair : indicates what CE HW pipe pair is used for disk encryption
+- qcom,hlos-ce-hw-instance : indicates what CE HW is used by HLOS crypto driver
+- qcom,qsee-ce-hw-instance : indicates what CE HW is used by secure domain (TZ) crypto driver
- qcom, msm_bus,name: Should be "qseecom-noc"
- qcom, msm_bus,num_cases: Depends on the use cases for bus scaling
- qcom, msm_bus,num_paths: The paths for source and destination ports
@@ -13,6 +16,9 @@
compatible = "qcom,qseecom";
reg = <0x7f00000 0x500000>;
reg-names = "secapp-region";
+ qcom,disk-encrypt-pipe-pair = <2>;
+ qcom,hlos-ce-hw-instance = <1>;
+ qcom,qsee-ce-hw-instance = <0>;
qcom,msm_bus,name = "qseecom-noc";
qcom,msm_bus,num_cases = <4>;
qcom,msm_bus,active_only = <0>;
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index a4c05d4..fe3d62f 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -389,15 +389,25 @@
qcom,msm-cpudai-auxpcm-data = <0>, <0>;
qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
- qcom,msm-auxpcm-rx {
+ qcom,msm-prim-auxpcm-rx {
qcom,msm-auxpcm-dev-id = <4106>;
compatible = "qcom,msm-auxpcm-dev";
};
- qcom,msm-auxpcm-tx {
+ qcom,msm-prim-auxpcm-tx {
qcom,msm-auxpcm-dev-id = <4107>;
compatible = "qcom,msm-auxpcm-dev";
};
+
+ qcom,msm-sec-auxpcm-rx {
+ qcom,msm-auxpcm-dev-id = <4108>;
+ compatible = "qcom,msm-auxpcm-dev";
+ };
+
+ qcom,msm-sec-auxpcm-tx {
+ qcom,msm-auxpcm-dev-id = <4109>;
+ compatible = "qcom,msm-auxpcm-dev";
+ };
};
qcom,msm-pcm-hostless {
@@ -436,10 +446,14 @@
- taiko-mclk-clk : phandle to PMIC8941 clkdiv1 node.
- qcom,taiko-mclk-clk-freq : Taiko mclk Freq in Hz. currently only 9600000Hz
is supported.
-- prim-auxpcm-gpio-clk : GPIO on which AUXPCM clk signal is coming.
-- prim-auxpcm-gpio-sync : GPIO on which AUXPCM SYNC signal is coming.
-- prim-auxpcm-gpio-din : GPIO on which AUXPCM DIN signal is coming.
-- prim-auxpcm-gpio-dout : GPIO on which AUXPCM DOUT signal is coming.
+- qcom,prim-auxpcm-gpio-clk : GPIO on which Primary AUXPCM clk signal is coming.
+- qcom,prim-auxpcm-gpio-sync : GPIO on which Primary AUXPCM SYNC signal is coming.
+- qcom,prim-auxpcm-gpio-din : GPIO on which Primary AUXPCM DIN signal is coming.
+- qcom,prim-auxpcm-gpio-dout : GPIO on which Primary AUXPCM DOUT signal is coming.
+- qcom,sec-auxpcm-gpio-clk : GPIO on which Secondary AUXPCM clk signal is coming.
+- qcom,sec-auxpcm-gpio-sync : GPIO on which Secondary AUXPCM SYNC signal is coming.
+- qcom,sec-auxpcm-gpio-din : GPIO on which Secondary AUXPCM DIN signal is coming.
+- qcom,sec-auxpcm-gpio-dout : GPIO on which Secondary AUXPCM DOUT signal is coming.
- qcom,us-euro-gpios : GPIO on which gnd/mic swap signal is coming.
Optional properties:
@@ -487,10 +501,14 @@
qcom,hdmi-audio-rx;
- prim-auxpcm-gpio-clk = <&msmgpio 65 0>;
- prim-auxpcm-gpio-sync = <&msmgpio 66 0>;
- prim-auxpcm-gpio-din = <&msmgpio 67 0>;
- prim-auxpcm-gpio-dout = <&msmgpio 68 0>;
+ qcom,prim-auxpcm-gpio-clk = <&msmgpio 65 0>;
+ qcom,prim-auxpcm-gpio-sync = <&msmgpio 66 0>;
+ qcom,prim-auxpcm-gpio-din = <&msmgpio 67 0>;
+ qcom,prim-auxpcm-gpio-dout = <&msmgpio 68 0>;
+ qcom,sec-auxpcm-gpio-clk = <&msmgpio 79 0>;
+ qcom,sec-auxpcm-gpio-sync = <&msmgpio 80 0>;
+ qcom,sec-auxpcm-gpio-din = <&msmgpio 81 0>;
+ qcom,sec-auxpcm-gpio-dout = <&msmgpio 82 0>;
};
* msm-dai-mi2s
@@ -608,7 +626,7 @@
* msm-adsp-loader
Required properties:
- - compatible : "msm-adsp-loader"
+ - compatible : "qcom,adsp-loader"
- qcom,adsp-state:
It is possible that some MSM use PIL to load the ADSP image. While
other MSM may use SBL to load the ADSP image at boot. Audio APR needs
@@ -623,3 +641,22 @@
compatible = "qcom,adsp-loader";
qcom,adsp-state = <2>;
};
+
+* msm-audio-ion
+
+Required properties:
+ - compatible : "qcom,msm-audio-ion"
+
+Optional properties:
+ - qcom,smmu-enabled:
+ It is possible that some MSM have SMMU in ADSP. While other MSM use
+ no SMMU. Audio lib introduce wrapper for ION APIs. The wrapper needs
+ presence of SMMU in ADSP to handle ION APIs differently.
+ Presence of this property means ADSP has SMMU in it.
+
+Example:
+
+qcom,msm-audio-ion {
+ compatible = "qcom,msm-audio-ion;
+ qcom,smmu-enabled;
+};
diff --git a/Documentation/devicetree/bindings/sound/taiko_codec.txt b/Documentation/devicetree/bindings/sound/taiko_codec.txt
index 989bea8..ffea58f 100644
--- a/Documentation/devicetree/bindings/sound/taiko_codec.txt
+++ b/Documentation/devicetree/bindings/sound/taiko_codec.txt
@@ -2,21 +2,38 @@
Required properties:
- - compatible : "qcom,taiko-slim-pgd"
- - elemental-addr: codec slimbus slave PGD enumeration address.(48 bits)
+ - compatible : "qcom,taiko-slim-pgd"
+ - elemental-addr: codec slimbus slave PGD enumeration address.(48 bits)
- - qcom,cdc-reset-gpio: gpio used for codec SOC reset.
+ - qcom,cdc-reset-gpio: gpio used for codec SOC reset.
- - <supply-name>-supply: phandle to the regulator device tree node
- - qcom,<supply-name>-voltage - specifies voltage levels for supply.
- Should be specified in pairs (min, max), units mV.
- - qcom,<supply-name>-current - specifies max current in mA that can drawn
- from the <supply-name>.
+ - cdc-vdd-buck-supply: phandle of buck supply's regulator device tree node.
+ - qcom,cdc-vdd-buck-voltage: buck supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-buck-current: buck supply's max current in mA.
- above three properties with "supply-name" set to "qcom,cdc-vdd-buck",
- "qcom,cdc-vdd-tx-h", "qcom,cdc-vdd-rx-h", "qcom,cdc-vddpx-1",
- "qcom,cdc-vdd-a-1p2v", "qcom,cdc-vddcx-1", "qcom,cdc-vddcx-2"
- should be present.
+ - cdc-vdd-tx-h-supply: phandle of tx-h supply's regulator device tree node.
+ - qcom,cdc-vdd-tx-h-voltage: tx-h supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-tx-h-current: tx-h supply's max current in mA.
+
+ - cdc-vdd-rx-h-supply: phandle of rx-h supply's regulator device tree node.
+ - qcom,cdc-vdd-rx-h-voltage: rx-h supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-rx-h-current: rx-h supply's max current in mA.
+
+ - cdc-vddpx-1-supply: phandle of px-1 supply's regulator device tree node.
+ - qcom,cdc-vddpx-1-voltage: px-1 supply's voltage level min and max in mV.
+ - qcom,cdc-vddpx-1-current: px-1 supply's max current in mA.
+
+ - cdc-vdd-a-1p2v-supply: phandle of 1.2v supply's regulator device tree node.
+ - qcom,cdc-vdd-a-1p2v-voltage: 1.2v supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-a-1p2v-current: 1.2v supply's max current in mA.
+
+ - cdc-vddcx-1-supply: phandle of cx-1 supply's regulator device tree node.
+ - qcom,cdc-vddcx-1-voltage: cx-1 supply's voltage level min and max in mV.
+ - qcom,cdc-vddcx-1-current: cx-1 supply's max current in mA.
+
+ - cdc-vddcx-2-supply: phandle of cx-2 supply's regulator device tree node.
+ - qcom,cdc-vddcx-2-voltage: cx-2 supply's voltage level min and max in mV.
+ - qcom,cdc-vddcx-2-current: cx-2 supply's max current in mA.
- qcom,cdc-micbias-ldoh-v - LDOH output in volts (should be 1.95 V and 3.00 V).
@@ -44,6 +61,12 @@
- qcom,cdc-slim-ifd-dev - namme of the codec slim interface device.
- qcom,cdc-slim-ifd-elemental-addr - codec slimbus slave interface device
enumeration address.
+
+Optional properties:
+ - cdc-dmic-sample-rate: Specifies the sample rate of digital mic in HZ. The
+ values for 9.6MHZ mclk can be 2400000 Hz, 3200000 Hz
+ and 4800000 Hz. The values for 12.288MHz mclk can be
+ 3072200 Hz, 4096000 Hz and 6144000 Hz.
Example:
taiko_codec {
@@ -95,23 +118,42 @@
qcom,cdc-mclk-clk-rate = <9600000>;
qcom,cdc-slim-ifd = "taiko-slim-ifd";
qcom,cdc-slim-ifd-elemental-addr = [00 00 A0 00 17 02];
+ qcom,cdc-dmic-sample-rate = <4800000>;
};
Wcd9xxx audio CODEC in I2C mode
- - compatible = "qcom,wcd9xxx-i2c-device";
- - reg: represents the slave address provided to the I2C driver.
- - qcom,cdc-reset-gpio: gpio used for codec SOC reset.
- - <supply-name>-supply: phandle to the regulator device tree node.
- - qcom,<supply-name>-voltage - specifies voltage levels for supply.
- Should be specified in pairs (min, max), units mV.
- - qcom,<supply-name>-current - specifies max current in mA that can drawn
- from the <supply-name>.
+ - compatible = "qcom,wcd9xxx-i2c-device";
+ - reg: represents the slave address provided to the I2C driver.
+ - qcom,cdc-reset-gpio: gpio used for codec SOC reset.
- above three properties with "supply-name" set to "qcom,cdc-vdd-buck",
- "qcom,cdc-vdd-tx-h", "qcom,cdc-vdd-rx-h", "qcom,cdc-vddpx-1",
- "qcom,cdc-vdd-a-1p2v", "qcom,cdc-vddcx-1", "qcom,cdc-vddcx-2"
- should be present.
+ - cdc-vdd-buck-supply: phandle of buck supply's regulator device tree node.
+ - qcom,cdc-vdd-buck-voltage: buck supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-buck-current: buck supply's max current in mA.
+
+ - cdc-vdd-tx-h-supply: phandle of tx-h supply's regulator device tree node.
+ - qcom,cdc-vdd-tx-h-voltage: tx-h supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-tx-h-current: tx-h supply's max current in mA.
+
+ - cdc-vdd-rx-h-supply: phandle of rx-h supply's regulator device tree node.
+ - qcom,cdc-vdd-rx-h-voltage: rx-h supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-rx-h-current: rx-h supply's max current in mA.
+
+ - cdc-vddpx-1-supply: phandle of px-1 supply's regulator device tree node.
+ - qcom,cdc-vddpx-1-voltage: px-1 supply's voltage level min and max in mV.
+ - qcom,cdc-vddpx-1-current: px-1 supply's max current in mA.
+
+ - cdc-vdd-a-1p2v-supply: phandle of 1.2v supply's regulator device tree node.
+ - qcom,cdc-vdd-a-1p2v-voltage: 1.2v supply's voltage level min and max in mV.
+ - qcom,cdc-vdd-a-1p2v-current: 1.2v supply's max current in mA.
+
+ - cdc-vddcx-1-supply: phandle of cx-1 supply's regulator device tree node.
+ - qcom,cdc-vddcx-1-voltage: cx-1 supply's voltage level min and max in mV.
+ - qcom,cdc-vddcx-1-current: cx-1 supply's max current in mA.
+
+ - cdc-vddcx-2-supply: phandle of cx-2 supply's regulator device tree node.
+ - qcom,cdc-vddcx-2-voltage: cx-2 supply's voltage level min and max in mV.
+ - qcom,cdc-vddcx-2-current: cx-2 supply's max current in mA.
- qcom,cdc-micbias-ldoh-v - LDOH output in volts (should be 1.95 V and 3.00 V).
@@ -121,13 +163,13 @@
cfilt voltage can be set to max of qcom,cdc-micbias-ldoh-v - 0.15V.
- qcom,cdc-micbias1-cfilt-sel = cfilt to use for micbias1
- (should be from 1 to 3).
+ (should be from 1 to 3).
- qcom,cdc-micbias2-cfilt-sel = cfilt to use for micbias2
- (should be from 1 to 3).
+ (should be from 1 to 3).
- qcom,cdc-micbias3-cfilt-sel = cfilt to use for micbias3
- (should be from 1 to 3).
+ (should be from 1 to 3).
- qcom,cdc-micbias4-cfilt-sel = cfilt to use for micbias4
- (should be from 1 to 3).
+ (should be from 1 to 3).
This value represents the connected CFLIT to MIC Bias.
- qcom,cdc-micbias1-ext-cap: Boolean. Enable micbias 1 external capacitor mode.
diff --git a/Documentation/devicetree/bindings/usb/dwc3.txt b/Documentation/devicetree/bindings/usb/dwc3.txt
index 9ce5421..fd5b93e 100644
--- a/Documentation/devicetree/bindings/usb/dwc3.txt
+++ b/Documentation/devicetree/bindings/usb/dwc3.txt
@@ -6,6 +6,9 @@
- compatible: must be "synopsys,dwc3"
- reg : Address and length of the register set for the device
- interrupts: Interrupts used by the dwc3 controller.
+ - interrupt-names : Required interrupt resource entries are:
+ "irq" : Interrupt for DWC3 core
+ "otg_irq" : Interrupt for DWC3 core's OTG Events
Optional properties:
- tx-fifo-resize: determines if the FIFO *has* to be reallocated.
@@ -15,6 +18,7 @@
dwc3@4a030000 {
compatible = "synopsys,dwc3";
reg = <0x4a030000 0xcfff>;
- interrupts = <0 92 4>
+ interrupts = <0 92 4>, <0 179 0>;
+ interrupt-names = "irq", "otg_irq";
tx-fifo-resize;
};
diff --git a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
index 1fb2ba9..6ea9e62 100644
--- a/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ehci-hsic.txt
@@ -38,6 +38,9 @@
STROBE GPIO PAD.
- hsic,data-pad-offset : Offset of TLMM register for configuring HSIC
DATA GPIO PAD.
+- qcom,phy-sof-workaround : If present then HSIC PHY has h/w BUGs related to
+ SOFs. Software workarounds are required for the same.
+
- Refer to "Documentation/devicetree/bindings/arm/msm/msm_bus.txt" for
below optional properties:
- qcom,msm_bus,name
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 02c2871..c1d4a05 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -22,6 +22,10 @@
1 - PHY control
2 - PMIC control
3 - User control (via debugfs)
+- <supply-name>-supply: handle to the regulator device tree node
+ Required "supply-name" is "HSUSB_VDDCX" (when voting for VDDCX) or
+ "hsusb_vdd_dig" (when voting for VDDCX Corner voltage),
+ "HSUSB_1p8-supply" and "HSUSB_3p3-supply".
Optional properties :
- qcom,hsusb-otg-disable-reset: If present then core is RESET only during
@@ -54,10 +58,8 @@
Used for allowing USB to respond for remote wakup.
- qcom,hsusb-otg-delay-lpm: If present then USB core will wait one second
after disconnect before entering low power mode.
-- <supply-name>-supply: handle to the regulator device tree node
- Required "supply-name" is "HSUSB_VDDCX" (when voting for VDDCX) or
- "hsusb_vdd_dig" (when voting for VDDCX Corner voltage),
- "HSUSB_1p8-supply" and "HSUSB_3p3-supply".
+- <supply-name>-supply: handle to the regulator device tree node.
+ Optional "supply-name" is "vbus_otg" to supply vbus in host mode.
- qcom,vdd-voltage-level: This property must be a list of three integer
values (no, min, max) where each value represents either a voltage
in microvolts or a value corresponding to voltage corner.
@@ -173,7 +175,11 @@
If HSUSB_BAM is used, "hsusb" should be present.
If HSIC_BAM is used, "hsic" should be present.
- qcom,usb-bam-num-pipes: max number of pipes that can be used
-- qcom,usb-base-address: physical base address of the BAM
+
+Optional properties:
+- qcom,usb-bam-fifo-baseaddr: base address for bam pipe's data and descriptor
+ fifos. This can be on chip memory (ocimem) or usb private memory. This
+ property is required if sub-node's mem-type is ocimem or usb private mem.
A number of USB BAM pipe parameters are represented as sub-nodes:
@@ -186,8 +192,9 @@
pipe num options: 0..127
- qcom,usb-bam-mem-type: Type of memory used by this PIPE. Can be one of
0 - Uses SPS's dedicated pipe memory
- 1 - USB's private memory residing @ 'qcom,usb-base-address'
+ 1 - USB's private memory residing @ 'qcom,usb-bam-fifo-baseaddr'
2 - System RAM allocated by driver
+ 3 - OCI memory residing @ 'qcom,usb-bam-fifo-baseaddr'
- qcom,bam-type: BAM type can be one of
0 - SSUSB_BAM
1 - HSUSB_BAM
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index 51c0750..5391734 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -6,9 +6,6 @@
offset and length of the TCSR register for routing USB
signals to either picoPHY0 or picoPHY1.
- interrupts: IRQ lines used by this controller
-- interrupt-names : Required interrupt resource entries are:
- "irq" : Interrupt for DWC3 core
- "otg_irq" : Interrupt for DWC3 core's OTG Events
- <supply-name>-supply: phandle to the regulator device tree node
Required "supply-name" examples are:
"SSUSB_lp8" : 1.8v supply for SSPHY
@@ -49,13 +46,18 @@
bits 13-19 PARAMETER_OVERRIDE_C
bits 20-25 PARAMETER_OVERRIDE_D
+Sub nodes:
+- Sub node for "DWC3- USB3 controller".
+ This sub node is required property for device node. The properties of this subnode
+ are specified in dwc3.txt.
+
Example MSM USB3.0 controller device node :
usb@f9200000 {
compatible = "qcom,dwc-usb3-msm";
- reg = <0xF9200000 0xFA000>,
- <0xFD4AB000 0x4>;
- interrupts = <0 131 0>, <0 179 0>, <0 133 0>;
- interrupt-names = "irq", "otg_irq", "hs_phy_irq";
+ reg = <0xf9200000 0xfc000>,
+ <0xfd4ab000 0x4>;
+ interrupts = <0 133 0>;
+ interrupt-names = "hs_phy_irq";
ssusb_vdd_dig-supply = <&pm8841_s2_corner>;
SSUSB_1p8-supply = <&pm8941_l6>;
hsusb_vdd_dig-supply = <&pm8841_s2_corner>;
@@ -73,4 +75,11 @@
qcom,msm_bus,vectors =
<61 512 0 0>,
<61 512 240000000 960000000>;
+ dwc3@f9200000 {
+ compatible = "synopsys,dwc3";
+ reg = <0xf9200000 0xfc000>;
+ interrupts = <0 131 0>, <0 179 0>;
+ interrupt-names = "irq", "otg_irq";
+ tx-fifo-resize;
+};
};
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 2825288..c52b7dd 100644
--- a/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-nt35590-720p-video.dtsi
@@ -23,7 +23,7 @@
qcom,mdss-pan-porch-values = <164 8 140 1 1 6>;
qcom,mdss-pan-underflow-clr = <0xff>;
qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
- qcom,mdss-pan-bl-levels = <1 255>;
+ qcom,mdss-pan-bl-levels = <1 4095>;
qcom,mdss-pan-dsi-mode = <0>;
qcom,mdss-pan-dsi-h-pulse-mode = <1>;
qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
diff --git a/arch/arm/boot/dts/msm-pm8226.dtsi b/arch/arm/boot/dts/msm-pm8226.dtsi
index e2b6a66..72de900 100644
--- a/arch/arm/boot/dts/msm-pm8226.dtsi
+++ b/arch/arm/boot/dts/msm-pm8226.dtsi
@@ -690,6 +690,13 @@
status = "disabled";
};
+ qcom,vibrator@c000 {
+ compatible = "qcom,qpnp-vibrator";
+ reg = <0xc000 0x100>;
+ label = "vibrator";
+ status = "disabled";
+ };
+
qcom,leds@d300 {
compatible = "qcom,leds-qpnp";
status = "disable";
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 9761e01..6042f23 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -105,7 +105,7 @@
qcom,r-sense-uohm = <10000>;
qcom,v-cutoff-uv = <3400000>;
qcom,max-voltage-uv = <4200000>;
- qcom,r-conn-mohm = <18>;
+ qcom,r-conn-mohm = <0>;
qcom,shutdown-soc-valid-limit = <20>;
qcom,adjust-soc-low-threshold = <25>;
qcom,adjust-soc-high-threshold = <45>;
@@ -724,7 +724,7 @@
};
chan@b5 {
- label = "pa_therm1";
+ label = "pa_therm0";
reg = <0xb5>;
qcom,decimation = <0>;
qcom,pre-div-channel-scaling = <0>;
@@ -735,7 +735,7 @@
};
chan@b7 {
- label = "pa_therm2";
+ label = "pa_therm1";
reg = <0xb7>;
qcom,decimation = <0>;
qcom,pre-div-channel-scaling = <0>;
@@ -814,7 +814,7 @@
qcom,calibration-type = "ratiometric";
qcom,scale-function = <2>;
qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
+ qcom,fast-avg-setup = <3>;
qcom,btm-channel-number = <0x48>;
};
@@ -826,7 +826,7 @@
qcom,calibration-type = "ratiometric";
qcom,scale-function = <1>;
qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
+ qcom,fast-avg-setup = <3>;
qcom,btm-channel-number = <0x68>;
};
@@ -838,8 +838,8 @@
qcom,calibration-type = "absolute";
qcom,scale-function = <1>;
qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <0>;
- qcom,btm-channel-number = <0x88>;
+ qcom,fast-avg-setup = <3>;
+ qcom,btm-channel-number = <0x70>;
};
chan@6 {
@@ -848,35 +848,35 @@
qcom,decimation = <0>;
qcom,pre-div-channel-scaling = <1>;
qcom,calibration-type = "absolute";
- qcom,scale-function = <3>;
+ qcom,scale-function = <0>;
qcom,hw-settle-time = <0>;
- qcom,fast-avg-setup = <0>;
- qcom,btm-channel-number = <0x90>;
+ qcom,fast-avg-setup = <3>;
+ qcom,btm-channel-number = <0x78>;
};
chan@b5 {
- label = "pa_therm1";
+ label = "pa_therm0";
reg = <0xb5>;
qcom,decimation = <0>;
qcom,pre-div-channel-scaling = <0>;
qcom,calibration-type = "absolute";
qcom,scale-function = <2>;
qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- qcom,btm-channel-number = <0x70>;
+ qcom,fast-avg-setup = <3>;
+ qcom,btm-channel-number = <0x80>;
qcom,thermal-node;
};
chan@b7 {
- label = "pa_therm2";
+ label = "pa_therm1";
reg = <0xb7>;
qcom,decimation = <0>;
qcom,pre-div-channel-scaling = <0>;
qcom,calibration-type = "ratiometric";
qcom,scale-function = <2>;
qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- qcom,btm-channel-number = <0x78>;
+ qcom,fast-avg-setup = <3>;
+ qcom,btm-channel-number = <0x88>;
qcom,thermal-node;
};
@@ -888,8 +888,8 @@
qcom,calibration-type = "ratiometric";
qcom,scale-function = <2>;
qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
- qcom,btm-channel-number = <0x80>;
+ qcom,fast-avg-setup = <3>;
+ qcom,btm-channel-number = <0x90>;
qcom,thermal-node;
};
@@ -901,7 +901,7 @@
qcom,calibration-type = "ratiometric";
qcom,scale-function = <2>;
qcom,hw-settle-time = <2>;
- qcom,fast-avg-setup = <0>;
+ qcom,fast-avg-setup = <3>;
qcom,btm-channel-number = <0x98>;
qcom,thermal-node;
};
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-cdp-mtp-qrd.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-cdp-qrd.dtsi
similarity index 100%
rename from arch/arm/boot/dts/msm8226-camera-sensor-cdp-mtp-qrd.dtsi
rename to arch/arm/boot/dts/msm8226-camera-sensor-cdp-qrd.dtsi
diff --git a/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.dtsi
new file mode 100644
index 0000000..02089be
--- /dev/null
+++ b/arch/arm/boot/dts/msm8226-camera-sensor-mtp.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.
+ */
+
+/ {
+
+ led_flash0: qcom,camera-led-flash {
+ cell-index = <0>;
+ compatible = "qcom,camera-led-flash";
+ qcom,flash-type = <1>;
+ qcom,flash-source = <&pm8226_flash0 &pm8226_flash1>;
+ };
+};
+
+&cci {
+
+ actuator0: qcom,actuator@6e {
+ cell-index = <3>;
+ reg = <0x6c 0x0>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ };
+
+ qcom,camera@6f {
+ compatible = "qcom,ov8825";
+ reg = <0x6f>;
+ qcom,slave-id = <0x6c 0x300a 0x8825>;
+ 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 = "ov8825";
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ cam_vaf-supply = <&pm8226_l15>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 1 0 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000 2800000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000 2800000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 37 0>,
+ <&msmgpio 35 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 = <0x4320>;
+ qcom,csi-lane-mask = <0x1f>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ };
+
+ qcom,camera@6d {
+ compatible = "qcom,ov9724";
+ reg = <0x6d>;
+ qcom,slave-id = <0x20 0x0 0x9724>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "ov9724";
+ cam_vdig-supply = <&pm8226_l5>;
+ cam_vana-supply = <&pm8226_l19>;
+ cam_vio-supply = <&pm8226_lvs1>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-type = <0 1 0>;
+ qcom,cam-vreg-min-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 26 0>,
+ <&msmgpio 28 0>,
+ <&msmgpio 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_RESET",
+ "CAM_STANDBY";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 4000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x3>;
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <1>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ };
+};
diff --git a/arch/arm/boot/dts/msm8226-cdp.dts b/arch/arm/boot/dts/msm8226-cdp.dts
index 8d8aa79..7b8dd59 100644
--- a/arch/arm/boot/dts/msm8226-cdp.dts
+++ b/arch/arm/boot/dts/msm8226-cdp.dts
@@ -13,11 +13,11 @@
/dts-v1/;
/include/ "msm8226.dtsi"
/include/ "dsi-panel-nt35590-720p-video.dtsi"
-/include/ "msm8226-camera-sensor-cdp-mtp-qrd.dtsi"
+/include/ "msm8226-camera-sensor-cdp-qrd.dtsi"
/ {
model = "Qualcomm MSM 8226 CDP";
- compatible = "qcom,msm8226-cdp", "qcom,msm8226";
+ compatible = "qcom,msm8226-cdp", "qcom,msm8226", "qcom,cdp";
qcom,msm-id = <145 1 0>;
serial@f991f000 {
@@ -189,7 +189,7 @@
linux,name = "wled:backlight";
linux,default-trigger = "bkl-trigger";
qcom,cs-out-en;
- qcom,op-fdbck;
+ qcom,op-fdbck = <1>;
qcom,default-state = "on";
qcom,max-current = <25>;
qcom,ctrl-delay-us = <0>;
diff --git a/arch/arm/boot/dts/msm8226-coresight.dtsi b/arch/arm/boot/dts/msm8226-coresight.dtsi
index 35d329c..993b4e6 100644
--- a/arch/arm/boot/dts/msm8226-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8226-coresight.dtsi
@@ -213,7 +213,7 @@
coresight-name = "coresight-csr";
coresight-nr-inports = <0>;
- qcom,blk-size = <3>;
+ qcom,blk-size = <1>;
};
cti0: cti@fc308000 {
diff --git a/arch/arm/boot/dts/msm8226-fluid.dts b/arch/arm/boot/dts/msm8226-fluid.dts
index af86922..02a0b0b 100644
--- a/arch/arm/boot/dts/msm8226-fluid.dts
+++ b/arch/arm/boot/dts/msm8226-fluid.dts
@@ -15,7 +15,7 @@
/ {
model = "Qualcomm MSM 8226 FLUID";
- compatible = "qcom,msm8226-fluid", "qcom,msm8226";
+ compatible = "qcom,msm8226-fluid", "qcom,msm8226", "qcom,fluid";
qcom,msm-id = <145 3 0>;
serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8226-gpu.dtsi b/arch/arm/boot/dts/msm8226-gpu.dtsi
index ebd7749..6a8ba3a 100644
--- a/arch/arm/boot/dts/msm8226-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8226-gpu.dtsi
@@ -9,61 +9,156 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+/ {
+ msm_gpu: qcom,kgsl-3d0@fdb00000 {
+ label = "kgsl-3d0";
+ compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
+ reg = <0xfdb00000 0x10000
+ 0xfdb20000 0x10000>;
+ reg-names = "kgsl_3d0_reg_memory" , "kgsl_3d0_shader_memory";
+ interrupts = <0 33 0>;
+ interrupt-names = "kgsl_3d0_irq";
+ qcom,id = <0>;
-/include/ "msm8974-gpu.dtsi"
+ qcom,chipid = <0x03000510>;
-&msm_gpu {
- qcom,chipid = <0x03000510>;
+ qcom,initial-pwrlevel = <2>;
+ qcom,step-pwrlevel = <2>;
- qcom,clk-map = <0x00000016>; /* KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE */
+ qcom,idle-timeout = <8>; //<HZ/12>
+ qcom,nap-allowed = <1>;
+ qcom,strtstp-sleepwake;
+ qcom,clk-map = <0x00000016>; /* KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE */
- /* Bus Scale Settings */
- qcom,msm-bus,name = "grp3d";
- qcom,msm-bus,num-cases = <4>;
- qcom,msm-bus,active-only = <0>;
- qcom,msm-bus,num-paths = <2>;
- qcom,msm-bus,vectors-KBps =
+ /* Bus Scale Settings */
+ qcom,msm-bus,name = "grp3d";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,active-only = <0>;
+ qcom,msm-bus,num-paths = <2>;
+ qcom,msm-bus,vectors-KBps =
<26 512 0 0>, <89 604 0 0>,
<26 512 0 1600000>, <89 604 0 3200000>,
<26 512 0 3200000>, <89 604 0 5120000>,
<26 512 0 4256000>, <89 604 0 6400000>;
- /* GDSC oxili regulators */
- vddcx-supply = "\0";
- vdd-supply = <&gdsc_oxili_cx>;
- qcom,gpu-pwrlevels {
- #address-cells = <1>;
- #size-cells = <0>;
+ /* GDSC oxili regulators */
+ vddcx-supply = "\0";
+ vdd-supply = <&gdsc_oxili_cx>;
- compatible = "qcom,gpu-pwrlevels";
- qcom,gpu-pwrlevel@0 {
- reg = <0>;
- qcom,gpu-freq = <450000000>;
- qcom,bus-freq = <3>;
- qcom,io-fraction = <0>;
+ /* IOMMU Data */
+ iommu = <&kgsl_iommu>;
+
+ /* Power levels */
+ qcom,gpu-pwrlevels {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "qcom,gpu-pwrlevels";
+
+ qcom,gpu-pwrlevel@0 {
+ reg = <0>;
+ qcom,gpu-freq = <450000000>;
+ qcom,bus-freq = <3>;
+ qcom,io-fraction = <0>;
+ };
+
+ qcom,gpu-pwrlevel@1 {
+ reg = <1>;
+ qcom,gpu-freq = <320000000>;
+ qcom,bus-freq = <2>;
+ qcom,io-fraction = <33>;
+ };
+
+ qcom,gpu-pwrlevel@2 {
+ reg = <2>;
+ qcom,gpu-freq = <200000000>;
+ qcom,bus-freq = <1>;
+ qcom,io-fraction = <100>;
+ };
+
+ qcom,gpu-pwrlevel@3 {
+ reg = <3>;
+ qcom,gpu-freq = <19000000>;
+ qcom,bus-freq = <0>;
+ qcom,io-fraction = <0>;
+ };
};
- qcom,gpu-pwrlevel@1 {
- reg = <1>;
- qcom,gpu-freq = <320000000>;
- qcom,bus-freq = <2>;
- qcom,io-fraction = <33>;
+ qcom,dcvs-core-info {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "qcom,dcvs-core-info";
+
+ qcom,num-cores = <1>;
+ qcom,sensors = <0>;
+
+ qcom,core-core-type = <1>;
+
+ qcom,algo-disable-pc-threshold = <0>;
+ qcom,algo-em-win-size-min-us = <100000>;
+ qcom,algo-em-win-size-max-us = <300000>;
+ qcom,algo-em-max-util-pct = <97>;
+ qcom,algo-group-id = <95>;
+ qcom,algo-max-freq-chg-time-us = <100000>;
+ qcom,algo-slack-mode-dynamic = <100000>;
+ qcom,algo-slack-weight-thresh-pct = <0>;
+ qcom,algo-slack-time-min-us = <39000>;
+ qcom,algo-slack-time-max-us = <39000>;
+ qcom,algo-ss-win-size-min-us = <1000000>;
+ qcom,algo-ss-win-size-max-us = <1000000>;
+ qcom,algo-ss-util-pct = <95>;
+ qcom,algo-ss-no-corr-below-freq = <0>;
+
+ qcom,energy-active-coeff-a = <2492>;
+ qcom,energy-active-coeff-b = <0>;
+ qcom,energy-active-coeff-c = <0>;
+ qcom,energy-leakage-coeff-a = <11>;
+ qcom,energy-leakage-coeff-b = <157150>;
+ qcom,energy-leakage-coeff-c = <0>;
+ qcom,energy-leakage-coeff-d = <0>;
+
+ qcom,power-current-temp = <25>;
+ qcom,power-num-freq = <4>;
+
+ qcom,dcvs-freq@0 {
+ reg = <0>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
+ };
+
+ qcom,dcvs-freq@1 {
+ reg = <1>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
+ };
+
+ qcom,dcvs-freq@2 {
+ reg = <2>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
+ };
+
+ qcom,dcvs-freq@3 {
+ reg = <3>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <844545>;
+ qcom,leakage-energy-offset = <0>;
+ };
};
- qcom,gpu-pwrlevel@2 {
- reg = <2>;
- qcom,gpu-freq = <200000000>;
- qcom,bus-freq = <1>;
- qcom,io-fraction = <100>;
- };
-
- qcom,gpu-pwrlevel@3 {
- reg = <3>;
- qcom,gpu-freq = <19000000>;
- qcom,bus-freq = <0>;
- qcom,io-fraction = <0>;
- };
};
};
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index 9c76512..7ab76f1 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -32,6 +32,7 @@
qcom,mdss-mixer-intf-off = <0x00003200>;
qcom,mdss-mixer-wb-off = <0x00003E00>;
qcom,mdss-dspp-off = <0x00004600>;
+ qcom,mdss-pingpong-off = <0x00021B00>;
qcom,mdss-wb-off = <0x00011100 0x00013100>;
qcom,mdss-intf-off = <0x00000000 0x00021300>;
qcom,mdss-rot-block-size = <64>;
diff --git a/arch/arm/boot/dts/msm8226-mtp.dts b/arch/arm/boot/dts/msm8226-mtp.dts
index 32d9a95..dab15ae 100644
--- a/arch/arm/boot/dts/msm8226-mtp.dts
+++ b/arch/arm/boot/dts/msm8226-mtp.dts
@@ -13,11 +13,11 @@
/dts-v1/;
/include/ "msm8226.dtsi"
/include/ "dsi-panel-nt35590-720p-video.dtsi"
-/include/ "msm8226-camera-sensor-cdp-mtp-qrd.dtsi"
+/include/ "msm8226-camera-sensor-mtp.dtsi"
/ {
model = "Qualcomm MSM 8226 MTP";
- compatible = "qcom,msm8226-mtp", "qcom,msm8226";
+ compatible = "qcom,msm8226-mtp", "qcom,msm8226", "qcom,mtp";
qcom,msm-id = <145 8 0>;
serial@f991f000 {
@@ -182,7 +182,7 @@
linux,name = "wled:backlight";
linux,default-trigger = "bkl-trigger";
qcom,cs-out-en;
- qcom,op-fdbck;
+ qcom,op-fdbck = <1>;
qcom,default-state = "on";
qcom,max-current = <25>;
qcom,ctrl-delay-us = <0>;
diff --git a/arch/arm/boot/dts/msm8226-pm.dtsi b/arch/arm/boot/dts/msm8226-pm.dtsi
index 34283e8..2613e11 100644
--- a/arch/arm/boot/dts/msm8226-pm.dtsi
+++ b/arch/arm/boot/dts/msm8226-pm.dtsi
@@ -25,9 +25,9 @@
qcom,saw2-spm-ctl = <0x0>;
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
- 0b 94 5b 80 10 2b 06 26 30 0f];
+ 0b 94 5b 80 10 06 26 30 0f];
qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
- 0b 94 5b 80 10 2b 06 26 30 0f];
+ 0b 94 5b 80 10 06 26 30 0f];
};
qcom,spm@f9099000 {
@@ -42,9 +42,9 @@
qcom,saw2-spm-ctl = <0x0>;
qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
- 0b 94 5b 80 10 2b 06 26 30 0f];
+ 0b 94 5b 80 10 06 26 30 0f];
qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
- 0b 94 5b 80 10 2b 06 26 30 0f];
+ 0b 94 5b 80 10 06 26 30 0f];
};
qcom,spm@f90a9000 {
@@ -57,11 +57,11 @@
qcom,saw2-cfg = <0x01>;
qcom,saw2-spm-dly= <0x3c102800>;
qcom,saw2-spm-ctl = <0x0>;
- qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
+ qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
- 0b 94 5b 80 10 2b 06 26 30 0f];
+ 0b 94 5b 80 10 06 26 30 0f];
qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
- 0b 94 5b 80 10 2b 06 26 30 0f];
+ 0b 94 5b 80 10 06 26 30 0f];
};
qcom,spm@f90b9000 {
@@ -74,11 +74,11 @@
qcom,saw2-cfg = <0x01>;
qcom,saw2-spm-dly= <0x3c102800>;
qcom,saw2-spm-ctl = <0x0>;
- qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
+ qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
- 0b 94 5b 80 10 2b 06 26 30 0f];
+ 0b 94 5b 80 10 06 26 30 0f];
qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
- 0b 94 5b 80 10 2b 06 26 30 0f];
+ 0b 94 5b 80 10 06 26 30 0f];
};
qcom,spm@f9012000 {
@@ -91,19 +91,16 @@
qcom,saw2-cfg = <0x14>;
qcom,saw2-spm-dly= <0x3c102800>;
qcom,saw2-spm-ctl = <0x0>;
- qcom,saw2-pmic-data0 = <0x0400009c>;
- qcom,saw2-pmic-data1 = <0x0000001c>;
+ qcom,saw2-pmic-data0 = <0x02030080>;
+ qcom,saw2-pmic-data1 = <0x00030000>;
qcom,vctl-timeout-us = <50>;
qcom,vctl-port = <0x0>;
qcom,phase-port = <0x1>;
qcom,pfm-port = <0x2>;
qcom,saw2-spm-cmd-ret = [00 03 00 7b 0f];
- qcom,saw2-spm-cmd-gdhs = [00 20 32 60 70 80 6b c0 e0 d0 42 07
- 78 1f 80 4e d0 e0 c0 22 6b 50 4b 60 02 32 50 7b
- 0f];
- qcom,saw2-spm-cmd-pc = [00 32 60 70 80 b0 10 e0 d0 6b c0
- 42 f0 11 07 01 b0 78 1f 80 4e c0 d0 12 e0 6b 50 4b
- 60 02 32 50 f0 7b 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 4e c0 d0 12 e0 6b 50 02 32
+ 50 f0 7b 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
};
qcom,lpm-resources {
@@ -125,8 +122,8 @@
qcom,name = "vdd-mem";
qcom,type = <0x616F646C>; /* "ldoa" */
qcom,id = <0x03>;
- qcom,key = <0x7675>; /* "uv" */
- qcom,init-value = <1050000>; /* Super Turbo */
+ qcom,key = <0x6e726f63>; /* "corn" */
+ qcom,init-value = <3>; /* Active */
};
qcom,lpm-resources@2 {
@@ -156,10 +153,12 @@
qcom,mode = "wfi";
qcom,xo = "xo_on";
qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
- qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <5>; /* MAX */
- qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
+ qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <3>; /* NORMAL */
+ qcom,irqs-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <1>;
qcom,ss-power = <784>;
qcom,energy-overhead = <190000>;
@@ -168,78 +167,83 @@
qcom,lpm-level@1 {
reg = <0x1>;
- qcom,mode = "retention";
- qcom,xo = "xo_on";
- qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
- qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <5>; /* MAX */
- qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
- qcom,latency-us = <75>;
- qcom,ss-power = <735>;
- qcom,energy-overhead = <77341>;
- qcom,time-overhead = <105>;
- };
-
-
- qcom,lpm-level@2 {
- reg = <0x2>;
qcom,mode = "standalone_pc";
qcom,xo = "xo_on";
qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
- qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <5>; /* MAX */
- qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
- qcom,latency-us = <95>;
+ qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <3>; /* NORMAL */
+ qcom,irqs-detectable;
+ qcom,gpio-detectable;
+ qcom,latency-us = <3000>;
qcom,ss-power = <725>;
qcom,energy-overhead = <99500>;
- qcom,time-overhead = <130>;
+ qcom,time-overhead = <3130>;
+ };
+
+ qcom,lpm-level@2 {
+ reg = <0x2>;
+ qcom,mode = "pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_retention";
+ qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <3>; /* NORMAL */
+ qcom,irqs-detectable;
+ qcom,gpio-detectable;
+ qcom,latency-us = <8000>;
+ qcom,ss-power = <138>;
+ qcom,energy-overhead = <1208400>;
+ qcom,time-overhead = <9200>;
};
qcom,lpm-level@3 {
reg = <0x3>;
qcom,mode = "pc";
qcom,xo = "xo_on";
- qcom,l2 = "l2_cache_gdhs";
- qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
- qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <5>; /* MAX */
- qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
- qcom,latency-us = <2000>;
- qcom,ss-power = <138>;
- qcom,energy-overhead = <1208400>;
- qcom,time-overhead = <3200>;
+ qcom,l2 = "l2_cache_pc";
+ qcom,vdd-mem-upper-bound = <3>; /* NORMAL */
+ qcom,vdd-mem-lower-bound = <2>; /* SVS SOC */
+ qcom,vdd-dig-upper-bound = <3>; /* NORMAL */
+ qcom,vdd-dig-lower-bound = <2>; /* SVS SOC */
+ qcom,irqs-detectable;
+ qcom,gpio-detectable;
+ qcom,latency-us = <9000>;
+ qcom,ss-power = <110>;
+ qcom,energy-overhead = <1250300>;
+ qcom,time-overhead = <9500>;
};
qcom,lpm-level@4 {
reg = <0x4>;
qcom,mode = "pc";
- qcom,xo = "xo_on";
+ qcom,xo = "xo_off";
qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
- qcom,vdd-mem-lower-bound = <750000>; /* RETENTION HIGH */
- qcom,vdd-dig-upper-bound = <3>; /* ACTIVE */
- qcom,vdd-dig-lower-bound = <2>; /* RETENTION HIGH */
- qcom,latency-us = <3000>;
- qcom,ss-power = <110>;
- qcom,energy-overhead = <1250300>;
- qcom,time-overhead = <3500>;
+ qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <3>; /* NORMAL */
+ qcom,latency-us = <16300>;
+ qcom,ss-power = <63>;
+ qcom,energy-overhead = <2128000>;
+ qcom,time-overhead = <24200>;
};
qcom,lpm-level@5 {
reg = <0x5>;
qcom,mode = "pc";
qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_gdhs";
- qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
- qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <5>; /* MAX */
- qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
- qcom,latency-us = <3000>;
- qcom,ss-power = <68>;
- qcom,energy-overhead = <1350200>;
- qcom,time-overhead = <4000>;
+ qcom,l2 = "l2_cache_pc";
+ qcom,vdd-mem-upper-bound = <3>; /* NORMAL */
+ qcom,vdd-mem-lower-bound = <2>; /* SVS SOC */
+ qcom,vdd-dig-upper-bound = <3>; /* NORMAL */
+ qcom,vdd-dig-lower-bound = <2>; /* SVS SOC */
+ qcom,latency-us = <24000>;
+ qcom,ss-power = <10>;
+ qcom,energy-overhead = <3202600>;
+ qcom,time-overhead = <33000>;
};
qcom,lpm-level@6 {
@@ -247,44 +251,14 @@
qcom,mode = "pc";
qcom,xo = "xo_off";
qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
- qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <5>; /* MAX */
- qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
- qcom,latency-us = <10300>;
- qcom,ss-power = <63>;
- qcom,energy-overhead = <2128000>;
- qcom,time-overhead = <18200>;
- };
-
- qcom,lpm-level@7 {
- reg = <0x7>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
- qcom,vdd-mem-lower-bound = <750000>; /* RETENTION HIGH */
- qcom,vdd-dig-upper-bound = <3>; /* ACTIVE */
- qcom,vdd-dig-lower-bound = <2>; /* RETIONTION HIGH */
- qcom,latency-us = <18000>;
- qcom,ss-power = <10>;
- qcom,energy-overhead = <3202600>;
- qcom,time-overhead = <27000>;
- };
-
- qcom,lpm-level@8 {
- reg = <0x8>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <750000>; /* RETENTION HIGH */
- qcom,vdd-mem-lower-bound = <750000>; /* RETENTION LOW */
- qcom,vdd-dig-upper-bound = <2>; /* RETENTION HIGH */
- qcom,vdd-dig-lower-bound = <0>; /* RETENTION LOW */
- qcom,latency-us = <20000>;
+ qcom,vdd-mem-upper-bound = <2>; /* SVS SOC */
+ qcom,vdd-mem-lower-bound = <0>; /* RETENTION */
+ qcom,vdd-dig-upper-bound = <2>; /* SVS SOC */
+ qcom,vdd-dig-lower-bound = <0>; /* RETENTION */
+ qcom,latency-us = <26000>;
qcom,ss-power = <2>;
qcom,energy-overhead = <4252000>;
- qcom,time-overhead = <32000>;
+ qcom,time-overhead = <38000>;
};
};
@@ -306,6 +280,7 @@
qcom,gic-map = <47 172>, /* usb2_hsic_async_wakeup_irq */
<53 104>, /* mdss_irq */
<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+ <2 216>, /* tsens_upper_lower_int */
<0xff 56>, /* q6_wdog_expired_irq */
<0xff 57>, /* mss_to_apps_irq(0) */
<0xff 58>, /* mss_to_apps_irq(1) */
@@ -393,6 +368,17 @@
qcom,use-sync-timer;
};
+ qcom,rpm-log@fc19dc00 {
+ compatible = "qcom,rpm-log";
+ reg = <0xfc19dc00 0x4000>;
+ qcom,rpm-addr-phys = <0xfc000000>;
+ qcom,offset-version = <4>;
+ qcom,offset-page-buffer-addr = <36>;
+ qcom,offset-log-len = <40>;
+ qcom,offset-log-len-mask = <44>;
+ qcom,offset-page-indices = <56>;
+ };
+
qcom,rpm-stats@0xfc19dbd0{
compatible = "qcom,rpm-stats";
reg = <0xfc19dbd0 0x1000>;
diff --git a/arch/arm/boot/dts/msm8226-qrd.dts b/arch/arm/boot/dts/msm8226-qrd.dts
index ae97be9..4879691 100644
--- a/arch/arm/boot/dts/msm8226-qrd.dts
+++ b/arch/arm/boot/dts/msm8226-qrd.dts
@@ -13,11 +13,11 @@
/dts-v1/;
/include/ "msm8226.dtsi"
/include/ "dsi-panel-nt35590-720p-video.dtsi"
-/include/ "msm8226-camera-sensor-cdp-mtp-qrd.dtsi"
+/include/ "msm8226-camera-sensor-cdp-qrd.dtsi"
/ {
model = "Qualcomm MSM 8226 QRD";
- compatible = "qcom,msm8226-qrd", "qcom,msm8226";
+ compatible = "qcom,msm8226-qrd", "qcom,msm8226", "qcom,qrd";
qcom,msm-id = <145 11 0>;
serial@f991f000 {
@@ -185,7 +185,7 @@
linux,name = "wled:backlight";
linux,default-trigger = "bkl-trigger";
qcom,cs-out-en;
- qcom,op-fdbck;
+ qcom,op-fdbck = <1>;
qcom,default-state = "on";
qcom,max-current = <25>;
qcom,ctrl-delay-us = <0>;
@@ -197,6 +197,13 @@
qcom,id = <0>;
};
};
+
+ qcom,vibrator@c000 {
+ status = "okay";
+ qcom,vib-timeout-ms = <15000>;
+ qcom,vib-vtg-level-mV = <3100>;
+ };
+
};
};
diff --git a/arch/arm/boot/dts/msm8226-regulator.dtsi b/arch/arm/boot/dts/msm8226-regulator.dtsi
index 448a5be..f24cea1 100644
--- a/arch/arm/boot/dts/msm8226-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8226-regulator.dtsi
@@ -24,6 +24,29 @@
};
};
+/* CPR controlled regulator */
+
+/ {
+ apc_vreg_corner: regulator@f9018000 {
+ status = "okay";
+ compatible = "qcom,cpr-regulator";
+ reg = <0xf9018000 0x1000>,
+ <0xfc4b80b0 8>;
+ reg-names = "rbcpr", "efuse_phys";
+ regulator-name = "apc_corner";
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <4>;
+ qcom,num-efuse-bits = <5>;
+ qcom,efuse-bit-pos = <6 7 8 9 10>;
+ qcom,pvs-bin-process = <0 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2
+ 2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
+ qcom,pvs-corner-ceiling-slow = <1050000 1150000 1275000 1350000>;
+ qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000 1200000>;
+ qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000 1140000>;
+ vdd-apc-supply = <&pm8226_s2>;
+ };
+};
+
/* RPM controlled regulators: */
&rpm_bus {
@@ -41,7 +64,7 @@
regulator-min-microvolt = <1>;
regulator-max-microvolt = <7>;
qcom,use-voltage-corner;
- qcom,consumer-supplies = "vdd_dig", "";
+ qcom,consumer-supplies = "vdd_dig", "", "vdd_sr2_dig", "";
};
pm8226_s1_corner_ao: regulator-s1-corner-ao {
compatible = "qcom,rpm-regulator-smd";
diff --git a/arch/arm/boot/dts/msm8226-sim.dts b/arch/arm/boot/dts/msm8226-sim.dts
index b6590b3..a86dc48 100644
--- a/arch/arm/boot/dts/msm8226-sim.dts
+++ b/arch/arm/boot/dts/msm8226-sim.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 8226 Simulator";
- compatible = "qcom,msm8226-sim", "qcom,msm8226";
+ compatible = "qcom,msm8226-sim", "qcom,msm8226", "qcom,sim";
qcom,msm-id = <145 16 0>;
serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8226-smp2p.dtsi b/arch/arm/boot/dts/msm8226-smp2p.dtsi
index 1b08246..91029e2 100644
--- a/arch/arm/boot/dts/msm8226-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm8226-smp2p.dtsi
@@ -34,7 +34,6 @@
interrupts = <0 143 1>;
};
- /* SMP2P Test Driver for inbound entries */
smp2pgpio_smp2p_7_in: qcom,smp2pgpio-smp2p-7-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -51,7 +50,6 @@
gpios = <&smp2pgpio_smp2p_7_in 0 0>;
};
- /* SMP2P Test Driver for outbound entries */
smp2pgpio_smp2p_7_out: qcom,smp2pgpio-smp2p-7-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -67,7 +65,6 @@
gpios = <&smp2pgpio_smp2p_7_out 0 0>;
};
- /* SMP2P Test Driver for modem inbound */
smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -84,7 +81,6 @@
gpios = <&smp2pgpio_smp2p_1_in 0 0>;
};
- /* SMP2P Test Driver for modem output */
smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -100,7 +96,6 @@
gpios = <&smp2pgpio_smp2p_1_out 0 0>;
};
- /* SMP2P SSR Driver for inbound entry from modem. */
smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "slave-kernel";
@@ -112,7 +107,6 @@
#interrupt-cells = <2>;
};
- /* SMP2P SSR Driver for outbound entry to modem */
smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "master-kernel";
@@ -123,7 +117,6 @@
#interrupt-cells = <2>;
};
- /* SMP2P Test Driver for adsp inbound */
smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -140,7 +133,6 @@
gpios = <&smp2pgpio_smp2p_2_in 0 0>;
};
- /* SMP2P Test Driver for adsp output */
smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -156,7 +148,6 @@
gpios = <&smp2pgpio_smp2p_2_out 0 0>;
};
- /* SMP2P Test Driver for wcnss inbound */
smp2pgpio_smp2p_4_in: qcom,smp2pgpio-smp2p-4-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -173,7 +164,6 @@
gpios = <&smp2pgpio_smp2p_4_in 0 0>;
};
- /* SMP2P Test Driver for wcnss output */
smp2pgpio_smp2p_4_out: qcom,smp2pgpio-smp2p-4-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -184,6 +174,27 @@
#interrupt-cells = <2>;
};
+ smp2pgpio_ssr_smp2p_4_in: qcom,smp2pgpio-ssr-smp2p-4-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "slave-kernel";
+ qcom,remote-pid = <4>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ smp2pgpio_ssr_smp2p_4_out: qcom,smp2pgpio-ssr-smp2p-4-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "master-kernel";
+ qcom,remote-pid = <4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
qcom,smp2pgpio_test_smp2p_4_out {
compatible = "qcom,smp2pgpio_test_smp2p_4_out";
gpios = <&smp2pgpio_smp2p_4_out 0 0>;
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 25c534b..75cf6e5 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -96,6 +96,7 @@
qcom,iommu-group-buffer-types = <0xfff 0x1ff>;
qcom,buffer-type-tz-usage-table = <0x1 0x1>,
<0x1fe 0x2>;
+ qcom,max-hw-load = <352800>; /* 720p @ 30 + 1080p @ 30 */
};
qcom,wfd {
@@ -128,6 +129,35 @@
interrupts = <0 94 0>;
};
+ qcom,usbbam@f9a44000 {
+ compatible = "qcom,usb-bam-msm";
+ reg = <0xf9a44000 0x11000>;
+ reg-names = "hsusb";
+ interrupts = <0 135 0>;
+ interrupt-names = "hsusb";
+ qcom,usb-bam-num-pipes = <16>;
+ qcom,usb-bam-fifo-baseaddr = <0xfe803000>;
+ qcom,ignore-core-reset-ack;
+ qcom,disable-clk-gating;
+
+ qcom,pipe0 {
+ label = "hsusb-qdss-in-0";
+ qcom,usb-bam-mem-type = <3>;
+ qcom,bam-type = <1>;
+ qcom,dir = <1>;
+ qcom,pipe-num = <0>;
+ qcom,peer-bam = <1>;
+ qcom,src-bam-physical-address = <0xfc37c000>;
+ qcom,src-bam-pipe-index = <0>;
+ qcom,dst-bam-physical-address = <0xf9a44000>;
+ qcom,dst-bam-pipe-index = <2>;
+ qcom,data-fifo-offset = <0x0>;
+ qcom,data-fifo-size = <0x600>;
+ qcom,descriptor-fifo-offset = <0x600>;
+ qcom,descriptor-fifo-size = <0x200>;
+ };
+ };
+
usb@f9a55000 {
compatible = "qcom,hsusb-otg";
reg = <0xf9a55000 0x400>;
@@ -380,17 +410,7 @@
qcom,msm-pcm-hostless {
compatible = "qcom,msm-pcm-hostless";
};
- qcom,pronto@fb21b000 {
- compatible = "qcom,pil-pronto";
- reg = <0xfb21b000 0x3000>,
- <0xfc401700 0x4>,
- <0xfd485300 0xc>;
- reg-names = "pmu_base", "clk_base", "halt_base";
- interrupts = <0 149 1>;
- vdd_pronto_pll-supply = <&pm8226_l12>;
- qcom,firmware-name = "wcnss";
- };
qcom,wcnss-wlan@fb000000 {
compatible = "qcom,wcnss_wlan";
reg = <0xfb000000 0x280000>;
@@ -574,7 +594,7 @@
compatible = "qcom,acpuclk-a7";
reg = <0xf9011050 0x8>;
reg-names = "rcg_base";
- a7_cpu-supply = <&pm8226_s2>;
+ a7_cpu-supply = <&apc_vreg_corner>;
a7_mem-supply = <&pm8226_l3>;
};
@@ -621,6 +641,12 @@
vdd_pronto_pll-supply = <&pm8226_l8>;
qcom,firmware-name = "wcnss";
+
+ /* GPIO input from wcnss */
+ qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+
+ /* GPIO output to wcnss */
+ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
};
qcom,iris-fm {
diff --git a/arch/arm/boot/dts/msm8610-bus.dtsi b/arch/arm/boot/dts/msm8610-bus.dtsi
new file mode 100644
index 0000000..50066f3
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-bus.dtsi
@@ -0,0 +1,978 @@
+/* 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.
+ */
+
+/ {
+ msm-mmss-noc@fc478000 {
+ compatible = "msm-bus-fabric";
+ reg = <0xfc478000 0x00004000>;
+ cell-id = <2048>;
+ label = "msm_mmss_noc";
+ qcom,fabclk-dual = "bus_clk";
+ qcom,fabclk-active = "bus_a_clk";
+ qcom,ntieredslaves = <0>;
+ qcom,qos-freq = <4800>;
+ qcom,hw-sel = "NoC";
+ qcom,rpm-en;
+
+ mas-mdp-port0 {
+ cell-id = <22>;
+ label = "mas-mdp-port0";
+ qcom,masterp = <2>;
+ qcom,tier = <2>;
+ qcom,hw-sel = "NoC";
+ qcom,perm-mode = "Bypass";
+ qcom,mode = "Bypass";
+ qcom,qport = <0>;
+ qcom,ws = <10000>;
+ qcom,mas-hw-id = <8>;
+ };
+
+ mas-vfe {
+ cell-id = <29>;
+ label = "mas-vfe";
+ qcom,masterp = <3>;
+ qcom,tier = <2>;
+ qcom,hw-sel = "NoC";
+ qcom,perm-mode = "Bypass";
+ qcom,mode = "Bypass";
+ qcom,ws = <10000>;
+ qcom,qport = <2>;
+ qcom,mas-hw-id = <11>;
+ };
+
+ mas-mdpe {
+ cell-id = <92>;
+ label = "mas-mdpe";
+ qcom,masterp = <4>;
+ qcom,tier = <2>;
+ qcom,hw-sel = "NoC";
+ qcom,perm-mode = "Bypass";
+ qcom,mode = "Bypass";
+ qcom,ws = <10000>;
+ qcom,qport = <7>;
+ qcom,mas-hw-id = <11>;
+ };
+
+ fab-bimc {
+ cell-id = <0>;
+ label = "fab-bimc";
+ qcom,gateway;
+ qcom,slavep = <16>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <16>;
+ };
+
+ slv-camera-cfg {
+ cell-id = <589>;
+ label = "slv-camera-cfg";
+ qcom,slavep = <0>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <3>;
+ };
+
+ slv-display-cfg {
+ cell-id = <590>;
+ label = "slv-display-cfg";
+ qcom,slavep = <1>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <4>;
+ };
+
+ slv-cpr-cfg {
+ cell-id = <592>;
+ label = "slv-cpr-cfg";
+ qcom,slavep = <3>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <6>;
+ };
+
+ slv-cpr-xpu-cfg {
+ cell-id = <593>;
+ label = "slv-cpr-xpu-cfg";
+ qcom,slavep = <4>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <7>;
+ };
+
+ slv-misc-cfg {
+ cell-id = <594>;
+ label = "slv-misc-cfg";
+ qcom,slavep = <6>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <8>;
+ };
+
+ slv-misc-xpu-cfg {
+ cell-id = <595>;
+ label = "slv-misc-xpu-cfg";
+ qcom,slavep = <7>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <9>;
+ };
+
+ slv-gfx3d-cfg {
+ cell-id = <598>;
+ label = "slv-gfx3d-cfg";
+ qcom,slavep = <9>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <11>;
+ };
+
+ slv-mmss-clk-cfg {
+ cell-id = <599>;
+ label = "slv-mmss-clk-cfg";
+ qcom,slavep = <11>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <12>;
+ };
+
+ slv-mmss-clk-xpu-cfg {
+ cell-id = <600>;
+ label = "slv-mmss-clk-xpu-cfg";
+ qcom,slavep = <12>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <13>;
+ };
+
+ slv-mnoc-mpu-cfg {
+ cell-id = <601>;
+ label = "slv-mnoc-mpu-cfg";
+ qcom,slavep = <13>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <14>;
+ };
+
+ slv-onoc-mpu-cfg {
+ cell-id = <602>;
+ label = "slv-onoc-mpu-cfg";
+ qcom,slavep = <14>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <15>;
+ };
+
+ slv-service-mnoc {
+ cell-id = <603>;
+ label = "slv-service-mnoc";
+ qcom,slavep = <18>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <17>;
+ };
+
+ slv-dsi-cfg {
+ cell-id = <649>;
+ label = "slv-dsi-cfg";
+ qcom,slavep = <19>;
+ qcom,tier = <2>;
+ qcom,buswidth = <16>;
+ qcom,hw-sel = "NoC";
+ qcom,slv-hw-id = <19>;
+ };
+ };
+
+ msm-sys-noc@fc460000 {
+ compatible = "msm-bus-fabric";
+ reg = <0xfc460000 0x00004000>;
+ cell-id = <1024>;
+ label = "msm_sys_noc";
+ qcom,fabclk-dual = "bus_clk";
+ qcom,fabclk-active = "bus_a_clk";
+ qcom,ntieredslaves = <0>;
+ qcom,qos-freq = <4800>;
+ qcom,hw-sel = "NoC";
+ qcom,rpm-en;
+
+ mas-lpass-ahb {
+ cell-id = <52>;
+ label = "mas-lpass-ahb";
+ qcom,masterp = <0>;
+ qcom,tier = <2>;
+ qcom,mas-hw-id = <18>;
+ };
+
+ mas-qdss-bam {
+ cell-id = <53>;
+ label = "mas-qdss-bam";
+ qcom,masterp = <1>;
+ qcom,tier = <2>;
+ qcom,mas-hw-id = <19>;
+ };
+
+ mas-snoc-cfg {
+ cell-id = <54>;
+ label = "mas-snoc-cfg";
+ qcom,masterp = <2>;
+ qcom,tier = <2>;
+ qcom,mas-hw-id = <20>;
+ };
+
+ fab-bimc {
+ cell-id = <0>;
+ label= "fab-bimc";
+ qcom,gateway;
+ qcom,slavep = <7>;
+ qcom,masterp = <3>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <21>;
+ qcom,slv-hw-id = <24>;
+ };
+
+ fab-cnoc {
+ cell-id = <5120>;
+ label = "fab-cnoc";
+ qcom,gateway;
+ qcom,slavep = <8>;
+ qcom,masterp = <4>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <22>;
+ qcom,slv-hw-id = <25>;
+ };
+
+ fab-pnoc {
+ cell-id = <4096>;
+ label = "fab-pnoc";
+ qcom,gateway;
+ qcom,slavep = <10>;
+ qcom,masterp = <10>;
+ qcom,buswidth = <8>;
+ qcom,qport = <8>;
+ qcom,mas-hw-id = <29>;
+ qcom,slv-hw-id = <28>;
+ qcom,mode = "Fixed";
+ qcom,prio-rd = <2>;
+ qcom,prio-wr = <2>;
+ };
+
+ fab-ovnoc {
+ cell-id = <6144>;
+ label = "fab-ovnoc";
+ qcom,gateway;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <53>;
+ qcom,slv-hw-id = <77>;
+ };
+
+ mas-crypto-core0 {
+ cell-id = <55>;
+ label = "mas-crypto-core0";
+ qcom,masterp = <5>;
+ qcom,tier = <2>;
+ qcom,mas-hw-id = <23>;
+ };
+
+ mas-mss {
+ cell-id = <38>;
+ label = "mas-mss";
+ qcom,masterp = <7>;
+ qcom,tier = <2>;
+ qcom,mas-hw-id = <26>;
+ };
+
+ mas-mss-nav {
+ cell-id = <57>;
+ label = "mas-mss-nav";
+ qcom,masterp = <8>;
+ qcom,tier = <2>;
+ qcom,mas-hw-id = <27>;
+ };
+
+ mas-ocmem-dma {
+ cell-id = <58>;
+ label = "mas-ocmem-dma";
+ qcom,masterp = <9>;
+ qcom,tier = <2>;
+ qcom,mode = "Fixed";
+ qcom,qport = <7>;
+ qcom,mas-hw-id = <28>;
+ };
+
+ mas-wcss {
+ cell-id = <59>;
+ label = "mas-wcss";
+ qcom,masterp = <11>;
+ qcom,tier = <2>;
+ qcom,mas-hw-id = <30>;
+ };
+
+ mas-qdss-etr {
+ cell-id = <60>;
+ label = "mas-qdss-etr";
+ qcom,masterp = <12>;
+ qcom,tier = <2>;
+ qcom,qport = <10>;
+ qcom,mode = "Fixed";
+ qcom,mas-hw-id = <31>;
+ };
+
+ slv-ocmem {
+ cell-id = <604>;
+ label = "slv-gmem";
+ qcom,slavep = <15>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <18>;
+ };
+
+ slv-ampss {
+ cell-id = <520>;
+ label = "slv-ampss";
+ qcom,slavep = <1>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <20>;
+ };
+
+ slv-lpass {
+ cell-id = <522>;
+ label = "slv-lpass";
+ qcom,slavep = <2>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <21>;
+ };
+
+ slv-wcss {
+ cell-id = <584>;
+ label = "slv-wcss";
+ qcom,slavep = <6>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <23>;
+ };
+
+ slv-ocimem {
+ cell-id = <585>;
+ label = "slv-ocimem";
+ qcom,slavep = <10>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <26>;
+ };
+
+ slv-service-snoc {
+ cell-id = <587>;
+ label = "slv-service-snoc";
+ qcom,slavep = <11>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <29>;
+ };
+
+ slv-qdss-stm {
+ cell-id = <588>;
+ label = "slv-qdss-stm";
+ qcom,slavep = <12>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <30>;
+ };
+
+ };
+
+ msm-periph-noc@fc468000 {
+ compatible = "msm-bus-fabric";
+ reg = <0xfc468000 0x00004000>;
+ cell-id = <4096>;
+ label = "msm_periph_noc";
+ qcom,fabclk-dual = "bus_clk";
+ qcom,fabclk-active = "bus_a_clk";
+ qcom,ntieredslaves = <0>;
+ qcom,hw-sel = "NoC";
+ qcom,rpm-en;
+
+ mas-pnoc-cfg {
+ cell-id = <88>;
+ label = "mas-pnoc-cfg";
+ qcom,masterp = <7>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <43>;
+ };
+
+ mas-sdcc-1 {
+ cell-id = <78>;
+ label = "mas-sdcc-1";
+ qcom,masterp = <0>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <33>;
+ };
+
+ mas-sdcc-2 {
+ cell-id = <81>;
+ label = "mas-sdcc-2";
+ qcom,masterp = <2>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <35>;
+ };
+
+ mas-blsp-1 {
+ cell-id = <86>;
+ label = "mas-blsp-1";
+ qcom,masterp = <5>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <41>;
+ };
+
+ mas-usb-hs {
+ cell-id = <87>;
+ label = "mas-usb-hs";
+ qcom,masterp = <6>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <42>;
+ };
+
+ fab-snoc {
+ cell-id = <1024>;
+ label = "fab-snoc";
+ qcom,gateway;
+ qcom,slavep = <12>;
+ qcom,masterp = <8>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <45>;
+ qcom,mas-hw-id = <44>;
+ };
+
+ slv-sdcc-1 {
+ cell-id = <606>;
+ label = "slv-sdcc-1";
+ qcom,slavep = <0>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <31>;
+ };
+
+ slv-sdcc-2 {
+ cell-id = <608>;
+ label = "slv-sdcc-2";
+ qcom,slavep = <2>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <33>;
+ };
+
+ slv-blsp-1 {
+ cell-id = <613>;
+ label = "slv-blsp-1";
+ qcom,slavep = <5>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <39>;
+ };
+
+ slv-usb-hs {
+ cell-id = <614>;
+ label = "slv-usb-hs";
+ qcom,slavep = <6>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <40>;
+ };
+
+ slv-pdm {
+ cell-id = <615>;
+ label = "slv-pdm";
+ qcom,slavep = <7>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <41>;
+ };
+
+ slv-periph-apu-cfg {
+ cell-id = <616>;
+ label = "slv-periph-apu-cfg";
+ qcom,slavep = <8>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <42>;
+ };
+
+ slv-pnoc-mpu-cfg {
+ cell-id = <617>;
+ label = "slv-pnoc-mpu-cfg";
+ qcom,slavep = <9>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <43>;
+ };
+
+ slv-prng {
+ cell-id = <618>;
+ label = "slv-prng";
+ qcom,slavep = <10>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <44>;
+ };
+
+ slv-service-pnoc {
+ cell-id = <619>;
+ label = "slv-service-pnoc";
+ qcom,slavep = <12>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <46>;
+ };
+
+ };
+
+ msm-config-noc@fc480000 {
+ compatible = "msm-bus-fabric";
+ reg = <0xfc480000 0x00004000>;
+ cell-id = <5120>;
+ label = "msm_config_noc";
+ qcom,fabclk-dual = "bus_clk";
+ qcom,fabclk-active = "bus_a_clk";
+ qcom,ntieredslaves = <0>;
+ qcom,hw-sel = "NoC";
+ qcom,rpm-en;
+
+ mas-rpm-inst {
+ cell-id = <72>;
+ label = "mas-rpm-inst";
+ qcom,masterp = <0>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <45>;
+ };
+
+ mas-rpm-data {
+ cell-id = <73>;
+ label = "mas-rpm-data";
+ qcom,masterp = <1>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <46>;
+ };
+
+ mas-rpm-sys {
+ cell-id = <74>;
+ label = "mas-rpm-sys";
+ qcom,masterp = <2>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <47>;
+ };
+
+ mas-dehr {
+ cell-id = <75>;
+ label = "mas-dehr";
+ qcom,masterp = <3>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <48>;
+ };
+
+ mas-qdss-dsp {
+ cell-id = <76>;
+ label = "mas-qdss-dap";
+ qcom,masterp = <4>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <49>;
+ };
+
+ mas-spdm {
+ cell-id = <36>;
+ label = "mas-spdm";
+ qcom,masterp = <5>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <50>;
+ };
+
+ mas-tic {
+ cell-id = <77>;
+ label = "mas-tic";
+ qcom,masterp = <6>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <51>;
+ };
+
+ slv-clk-ctl {
+ cell-id = <620>;
+ label = "slv-clk-ctl";
+ qcom,slavep = <1>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <47>;
+ };
+
+ slv-cnoc-mss {
+ cell-id = <621>;
+ label = "slv-cnoc-mss";
+ qcom,slavep = <2>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <48>;
+ };
+
+ slv-security {
+ cell-id = <622>;
+ label = "slv-security";
+ qcom,slavep = <3>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <49>;
+ };
+
+ slv-tcsr {
+ cell-id = <623>;
+ label = "slv-tcsr";
+ qcom,slavep = <4>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <50>;
+ };
+
+ slv-tlmm {
+ cell-id = <624>;
+ label = "slv-tlmm";
+ qcom,slavep = <5>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <51>;
+ };
+
+ slv-crypto-0-cfg {
+ cell-id = <625>;
+ label = "slv-crypto-0-cfg";
+ qcom,slavep = <6>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <52>;
+ };
+
+ slv-imem-cfg {
+ cell-id = <627>;
+ label = "slv-imem-cfg";
+ qcom,slavep = <7>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <54>;
+ };
+
+ slv-message-ram {
+ cell-id = <628>;
+ label = "slv-message-ram";
+ qcom,slavep = <8>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <55>;
+ };
+
+ slv-bimc-cfg {
+ cell-id = <629>;
+ label = "slv-bimc-cfg";
+ qcom,slavep = <9>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <56>;
+ };
+
+ slv-boot-rom {
+ cell-id = <630>;
+ label = "slv-boot-rom";
+ qcom,slavep = <10>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <57>;
+ };
+
+ slv-pmic-arb {
+ cell-id = <632>;
+ label = "slv-pmic-arb";
+ qcom,slavep = <12>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <59>;
+ };
+
+ slv-spdm-wrapper {
+ cell-id = <633>;
+ label = "slv-spdm-wrapper";
+ qcom,slavep = <13>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <60>;
+ };
+
+ slv-dehr-cfg {
+ cell-id = <634>;
+ label = "slv-dehr-cfg";
+ qcom,slavep = <14>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <61>;
+ };
+
+ slv-mpm {
+ cell-id = <536>;
+ label = "slv-mpm";
+ qcom,slavep = <15>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <62>;
+ };
+
+ slv-qdss-cfg {
+ cell-id = <635>;
+ label = "slv-qdss-cfg";
+ qcom,slavep = <16>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <63>;
+ };
+
+ slv-rbcpr-cfg {
+ cell-id = <636>;
+ label = "slv-rbcpr-cfg";
+ qcom,slavep = <17>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <64>;
+ };
+
+ slv-rbcpr-qdss-apu-cfg {
+ cell-id = <637>;
+ label = "slv-rbcpr-qdss-apu-cfg";
+ qcom,slavep = <18>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <65>;
+ };
+
+ fab-snoc {
+ cell-id = <1024>;
+ label = "fab-snoc";
+ qcom,gateway;
+ qcom,slavep = <26>;
+ qcom,masterp = <7>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,mas-hw-id = <52>;
+ qcom,slv-hw-id = <75>;
+ };
+
+ slv-cnoc-mnoc-mmss-cfg {
+ cell-id = <631>;
+ label = "slv-cnoc-mnoc-mmss-cfg";
+ qcom,slavep = <11>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <58>;
+ };
+
+ slv-cnoc-mnoc-cfg {
+ cell-id = <640>;
+ label = "slv-cnoc-mnoc-cfg";
+ qcom,slavep = <19>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <66>;
+ };
+
+ slv-pnoc-cfg {
+ cell-id = <641>;
+ label = "slv-pnoc-cfg";
+ qcom,slavep = <21>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <69>;
+ };
+
+ slv-snoc-mpu-cfg {
+ cell-id = <638>;
+ label = "slv-snoc-mpu-cfg";
+ qcom,slavep = <20>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <67>;
+ };
+
+ slv-snoc-cfg {
+ cell-id = <642>;
+ label = "slv-snoc-cfg";
+ qcom,slavep = <22>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <70>;
+ };
+
+ slv-phy-apu-cfg {
+ cell-id = <644>;
+ label = "slv-phy-apu-cfg";
+ qcom,slavep = <23>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <72>;
+ };
+
+ slv-ebi1-phy-cfg {
+ cell-id = <645>;
+ label = "slv-ebi1-phy-cfg";
+ qcom,slavep = <24>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <73>;
+ };
+
+ slv-rpm {
+ cell-id = <534>;
+ label = "slv-rpm";
+ qcom,slavep = <25>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <74>;
+ };
+
+ slv-service-cnoc {
+ cell-id = <646>;
+ label = "slv-service-cnoc";
+ qcom,slavep = <27>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <76>;
+ };
+
+ };
+
+ msm-bimc@0xfc380000 {
+ compatible = "msm-bus-fabric";
+ reg = <0xfc380000 0x0006A000>;
+ cell-id = <0>;
+ label = "msm_bimc";
+ qcom,fabclk-dual = "mem_clk";
+ qcom,fabclk-active = "mem_a_clk";
+ qcom,ntieredslaves = <0>;
+ qcom,qos-freq = <4800>;
+ qcom,hw-sel = "BIMC";
+ qcom,rpm-en;
+
+ mas-ampss-m0 {
+ cell-id = <1>;
+ label = "mas-ampss-m0";
+ qcom,masterp = <0>;
+ qcom,tier = <2>;
+ qcom,hw-sel = "BIMC";
+ qcom,mode = "Fixed";
+ qcom,qport = <0>;
+ qcom,ws = <10000>;
+ qcom,mas-hw-id = <0>;
+ qcom,prio-rd = <1>;
+ qcom,prio-wr = <1>;
+ };
+
+ mas-mss-proc {
+ cell-id = <65>;
+ label = "mas-mss-proc";
+ qcom,masterp = <3>;
+ qcom,tier = <2>;
+ qcom,hw-sel = "RPM";
+ qcom,mas-hw-id = <1>;
+ };
+
+ fab-mmss-noc {
+ cell-id = <2048>;
+ label = "fab_mmss_noc";
+ qcom,masterp = <1>;
+ qcom,qport = <1>;
+ qcom,buswidth = <8>;
+ qcom,ws = <10000>;
+ qcom,mas-hw-id = <2>;
+ qcom,hw-sel = "BIMC";
+ qcom,mode = "Bypass";
+ };
+
+ fab-snoc {
+ cell-id = <1024>;
+ label = "fab-snoc";
+ qcom,gateway;
+ qcom,slavep = <2>;
+ qcom,masterp = <2>;
+ qcom,qport = <2>;
+ qcom,buswidth = <8>;
+ qcom,ws = <10000>;
+ qcom,mas-hw-id = <3>;
+ qcom,slv-hw-id = <2>;
+ };
+
+ mas-lpass-proc {
+ cell-id = <11>;
+ label = "mas-lpass-proc";
+ qcom,masterp = <4>;
+ qcom,tier = <2>;
+ qcom,qport = <4>;
+ qcom,mas-hw-id = <25>;
+ qcom,mode = "Fixed";
+ qcom,prio-rd = <1>;
+ qcom,prio-wr = <1>;
+ };
+
+ mas-gfx3d {
+ cell-id = <26>;
+ label = "mas-gfx3d";
+ qcom,masterp = <5>;
+ qcom,tier = <2>;
+ qcom,hw-sel = "NoC";
+ qcom,perm-mode = "Bypass";
+ qcom,mode = "Bypass";
+ qcom,ws = <10000>;
+ qcom,qport = <5>;
+ qcom,prio-rd = <1>;
+ qcom,prio-wr = <1>;
+ qcom,mas-hw-id = <6>;
+ };
+
+
+ slv-ebi-ch0 {
+ cell-id = <512>;
+ label = "slv-ebi-ch0";
+ qcom,slavep = <0>;
+ qcom,tier = <2>;
+ qcom,buswidth = <8>;
+ qcom,slv-hw-id = <0>;
+ };
+ };
+
+};
+
+
diff --git a/arch/arm/boot/dts/msm8610-cdp.dts b/arch/arm/boot/dts/msm8610-cdp.dts
index 390c02a..d523c67 100644
--- a/arch/arm/boot/dts/msm8610-cdp.dts
+++ b/arch/arm/boot/dts/msm8610-cdp.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 8610 CDP";
- compatible = "qcom,msm8610-cdp", "qcom,msm8610";
+ compatible = "qcom,msm8610-cdp", "qcom,msm8610", "qcom,cdp";
qcom,msm-id = <147 1 0>;
serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8610-coresight.dtsi b/arch/arm/boot/dts/msm8610-coresight.dtsi
index 3612078..89a00f1 100644
--- a/arch/arm/boot/dts/msm8610-coresight.dtsi
+++ b/arch/arm/boot/dts/msm8610-coresight.dtsi
@@ -203,7 +203,7 @@
coresight-name = "coresight-csr";
coresight-nr-inports = <0>;
- qcom,blk-size = <3>;
+ qcom,blk-size = <1>;
};
cti0: cti@fc310000 {
diff --git a/arch/arm/boot/dts/msm8610-gpu.dtsi b/arch/arm/boot/dts/msm8610-gpu.dtsi
new file mode 100644
index 0000000..f3a8259
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-gpu.dtsi
@@ -0,0 +1,168 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+/ {
+ msm_gpu: qcom,kgsl-3d0@fdc00000 {
+ label = "kgsl-3d0";
+ compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
+ reg = <0xfdc00000 0x10000
+ 0xfdc10000 0x10000>;
+ reg-names = "kgsl_3d0_reg_memory", "kgsl_3d0_shader_memory";
+ interrupts = <0 33 0>;
+ interrupt-names = "kgsl_3d0_irq";
+ qcom,id = <0>;
+
+ qcom,chipid = <0x03000520>;
+
+ qcom,initial-pwrlevel = <1>;
+
+ qcom,idle-timeout = <8>; /* <HZ/12> */
+ qcom,nap-allowed = <1>;
+ qcom,strtstp-sleepwake;
+ qcom,clk-map = <0x000001E>; /* KGSL_CLK_CORE |
+ KGSL_CLK_IFACE | KGSL_CLK_MEM | KGSL_CLK_MEM_IFACE */
+
+ /* Bus Scale Settings */
+ qcom,msm-bus,name = "grp3d";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,active-only = <0>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <26 512 0 0>,
+ <26 512 0 800000>,
+ <26 512 0 1600000>,
+ <26 512 0 2128000>;
+
+ /* GDSC oxili regulators */
+ vdd-supply = <&gdsc_oxili_cx>;
+
+ /* IOMMU Data */
+ iommu = <&gfx_iommu>;
+
+ /* Power levels */
+ qcom,gpu-pwrlevels {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "qcom,gpu-pwrlevels";
+
+ qcom,gpu-pwrlevel@0 {
+ reg = <0>;
+ qcom,gpu-freq = <400000000>;
+ qcom,bus-freq = <3>;
+ qcom,io-fraction = <0>;
+ };
+
+ qcom,gpu-pwrlevel@1 {
+ reg = <1>;
+ qcom,gpu-freq = <300000000>;
+ qcom,bus-freq = <2>;
+ qcom,io-fraction = <33>;
+ };
+
+ qcom,gpu-pwrlevel@2 {
+ reg = <2>;
+ qcom,gpu-freq = <200000000>;
+ qcom,bus-freq = <2>;
+ qcom,io-fraction = <33>;
+ };
+
+ qcom,gpu-pwrlevel@3 {
+ reg = <3>;
+ qcom,gpu-freq = <150000000>;
+ qcom,bus-freq = <1>;
+ qcom,io-fraction = <100>;
+ };
+
+ qcom,gpu-pwrlevel@4 {
+ reg = <4>;
+ qcom,gpu-freq = <27000000>;
+ qcom,bus-freq = <0>;
+ qcom,io-fraction = <0>;
+ };
+ };
+
+ /* DVCS Info */
+ qcom,dcvs-core-info {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "qcom,dcvs-core-info";
+
+ qcom,num-cores = <1>;
+ qcom,sensors = <0>;
+
+ qcom,core-core-type = <1>;
+
+ qcom,algo-disable-pc-threshold = <0>;
+ qcom,algo-em-win-size-min-us = <100000>;
+ qcom,algo-em-win-size-max-us = <300000>;
+ qcom,algo-em-max-util-pct = <97>;
+ qcom,algo-group-id = <95>;
+ qcom,algo-max-freq-chg-time-us = <100000>;
+ qcom,algo-slack-mode-dynamic = <100000>;
+ qcom,algo-slack-weight-thresh-pct = <0>;
+ qcom,algo-slack-time-min-us = <39000>;
+ qcom,algo-slack-time-max-us = <39000>;
+ qcom,algo-ss-win-size-min-us = <1000000>;
+ qcom,algo-ss-win-size-max-us = <1000000>;
+ qcom,algo-ss-util-pct = <95>;
+ qcom,algo-ss-no-corr-below-freq = <0>;
+
+ qcom,energy-active-coeff-a = <2492>;
+ qcom,energy-active-coeff-b = <0>;
+ qcom,energy-active-coeff-c = <0>;
+ qcom,energy-leakage-coeff-a = <11>;
+ qcom,energy-leakage-coeff-b = <157150>;
+ qcom,energy-leakage-coeff-c = <0>;
+ qcom,energy-leakage-coeff-d = <0>;
+
+ qcom,power-current-temp = <25>;
+ qcom,power-num-freq = <4>;
+
+ qcom,dcvs-freq@0 {
+ reg = <0>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
+ };
+
+ qcom,dcvs-freq@1 {
+ reg = <1>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
+ };
+
+ qcom,dcvs-freq@2 {
+ reg = <2>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <100>;
+ qcom,leakage-energy-offset = <0>;
+ };
+
+ qcom,dcvs-freq@3 {
+ reg = <3>;
+ qcom,freq = <0>;
+ qcom,voltage = <0>;
+ qcom,is_trans_level = <0>;
+ qcom,active-energy-offset = <844545>;
+ qcom,leakage-energy-offset = <0>;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msm8610-mtp.dts b/arch/arm/boot/dts/msm8610-mtp.dts
index 70ac0e8..f718d5e 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dts
+++ b/arch/arm/boot/dts/msm8610-mtp.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 8610 MTP";
- compatible = "qcom,msm8610-mtp", "qcom,msm8610";
+ compatible = "qcom,msm8610-mtp", "qcom,msm8610", "qcom,mtp";
qcom,msm-id = <147 8 0>;
serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8610-pm.dtsi b/arch/arm/boot/dts/msm8610-pm.dtsi
index ff16b8d..08a3758 100644
--- a/arch/arm/boot/dts/msm8610-pm.dtsi
+++ b/arch/arm/boot/dts/msm8610-pm.dtsi
@@ -21,13 +21,13 @@
qcom,core-id = <0>;
qcom,saw2-ver-reg = <0xfd0>;
qcom,saw2-cfg = <0x01>;
- qcom,saw2-spm-dly= <0x20000400>;
- qcom,saw2-spm-ctl = <0x1>;
- qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
- qcom,saw2-spm-cmd-spc = [00 20 10 80 90 5b 60 03 60 3b 76 76 94
- 5b 80 10 2b 30 06 26 30 0f];
- qcom,saw2-spm-cmd-pc = [00 20 10 80 90 5b 60 07 3b 76 76 0b 94
- 5b 80 10 2b 30 06 26 30 0f];
+ qcom,saw2-spm-dly= <0x3c102800>;
+ qcom,saw2-spm-ctl = <0x0>;
+ qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
+ 0b 94 5b 80 10 06 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
+ 0b 94 5b 80 10 06 26 30 0f];
};
qcom,spm@f9099000 {
@@ -38,13 +38,13 @@
qcom,core-id = <1>;
qcom,saw2-ver-reg = <0xfd0>;
qcom,saw2-cfg = <0x01>;
- qcom,saw2-spm-dly= <0x20000400>;
- qcom,saw2-spm-ctl = <0x1>;
- qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
- qcom,saw2-spm-cmd-spc = [00 20 10 80 90 5b 60 03 60 3b 76 76 94
- 5b 80 10 2b 30 06 26 30 0f];
- qcom,saw2-spm-cmd-pc = [00 20 10 80 90 5b 60 07 3b 76 76 0b 94
- 5b 80 10 2b 30 06 26 30 0f];
+ qcom,saw2-spm-dly= <0x3c102800>;
+ qcom,saw2-spm-ctl = <0x0>;
+ qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
+ 0b 94 5b 80 10 06 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
+ 0b 94 5b 80 10 06 26 30 0f];
};
qcom,spm@f90a9000 {
@@ -55,13 +55,13 @@
qcom,core-id = <2>;
qcom,saw2-ver-reg = <0xfd0>;
qcom,saw2-cfg = <0x01>;
- qcom,saw2-spm-dly= <0x20000400>;
- qcom,saw2-spm-ctl = <0x1>;
- qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
- qcom,saw2-spm-cmd-spc = [00 20 10 80 90 5b 60 03 60 3b 76 76 94
- 5b 80 10 2b 30 06 26 30 0f];
- qcom,saw2-spm-cmd-pc = [00 20 10 80 90 5b 60 07 3b 76 76 0b 94
- 5b 80 10 2b 30 06 26 30 0f];
+ qcom,saw2-spm-dly= <0x3c102800>;
+ qcom,saw2-spm-ctl = <0x0>;
+ qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
+ 0b 94 5b 80 10 06 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
+ 0b 94 5b 80 10 06 26 30 0f];
};
qcom,spm@f90b9000 {
@@ -72,13 +72,13 @@
qcom,core-id = <3>;
qcom,saw2-ver-reg = <0xfd0>;
qcom,saw2-cfg = <0x01>;
- qcom,saw2-spm-dly= <0x20000400>;
- qcom,saw2-spm-ctl = <0x1>;
- qcom,saw2-spm-cmd-wfi = [60 03 60 76 76 0b 0f];
- qcom,saw2-spm-cmd-spc = [00 20 10 80 90 5b 60 03 60 3b 76 76 94
- 5b 80 10 2b 30 06 26 30 0f];
- qcom,saw2-spm-cmd-pc = [00 20 10 80 90 5b 60 07 3b 76 76 0b 94
- 5b 80 10 2b 30 06 26 30 0f];
+ qcom,saw2-spm-dly= <0x3c102800>;
+ qcom,saw2-spm-ctl = <0x0>;
+ qcom,saw2-spm-cmd-wfi = [60 03 60 0b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 10 80 30 90 5b 60 03 60 3b 76 76
+ 0b 94 5b 80 10 06 26 30 0f];
+ qcom,saw2-spm-cmd-pc = [00 20 10 80 30 90 5b 60 07 60 3b 76 76
+ 0b 94 5b 80 10 06 26 30 0f];
};
qcom,spm@f9012000 {
@@ -89,21 +89,18 @@
qcom,core-id = <0xffff>; /* L2/APCS SAW */
qcom,saw2-ver-reg = <0xfd0>;
qcom,saw2-cfg = <0x14>;
- qcom,saw2-spm-dly= <0x20000400>;
- qcom,saw2-spm-ctl = <0x1>;
+ qcom,saw2-spm-dly= <0x3c102800>;
+ qcom,saw2-spm-ctl = <0x0>;
qcom,saw2-pmic-data0 = <0x02030080>;
qcom,saw2-pmic-data1 = <0x00030000>;
qcom,vctl-timeout-us = <50>;
qcom,vctl-port = <0x0>;
qcom,phase-port = <0x1>;
qcom,pfm-port = <0x2>;
- qcom,saw2-spm-cmd-ret = [0b 00 03 00 7b 0f];
- qcom,saw2-spm-cmd-gdhs = [00 20 32 60 70 80 0b 6b c0 e0 d0 42 07
- 78 1f 80 4e d0 e0 c0 22 6b 50 4b 60 02 32 50 7b
- 0f];
- qcom,saw2-spm-cmd-pc = [00 32 60 70 80 b0 0b 10 e0 d0 6b c0
- 42 f0 11 07 01 b0 78 1f 80 4e c0 d0 12 e0 6b 50 4b
- 60 02 32 50 f0 7b 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
+ qcom,saw2-spm-cmd-ret = [00 03 00 7b 0f];
+ qcom,saw2-spm-cmd-pc = [00 32 b0 10 e0 d0 6b c0 42 f0
+ 11 07 01 b0 4e c0 d0 12 e0 6b 50 02 32
+ 50 f0 7b 0f]; /*APCS_PMIC_OFF_L2RAM_OFF*/
};
qcom,lpm-resources {
@@ -114,8 +111,8 @@
qcom,lpm-resources@0 {
reg = <0x0>;
qcom,name = "vdd-dig";
- qcom,type = <0x62706d73>; /* "smpb" */
- qcom,id = <0x02>;
+ qcom,type = <0x61706d73>; /* "smpa" */
+ qcom,id = <0x01>;
qcom,key = <0x6e726f63>; /* "corn" */
qcom,init-value = <5>; /* Super Turbo */
};
@@ -123,10 +120,10 @@
qcom,lpm-resources@1 {
reg = <0x1>;
qcom,name = "vdd-mem";
- qcom,type = <0x62706d73>; /* "smpb" */
- qcom,id = <0x01>;
- qcom,key = <0x7675>; /* "uv" */
- qcom,init-value = <1050000>; /* Super Turbo */
+ qcom,type = <0x616F646C>; /* "ldoa" */
+ qcom,id = <0x03>;
+ qcom,key = <0x6e726f63>; /* "corn" */
+ qcom,init-value = <3>; /* Active */
};
qcom,lpm-resources@2 {
@@ -156,10 +153,12 @@
qcom,mode = "wfi";
qcom,xo = "xo_on";
qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
- qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <5>; /* MAX */
- qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
+ qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <3>; /* NORMAL */
+ qcom,irqs-detectable;
+ qcom,gpio-detectable;
qcom,latency-us = <1>;
qcom,ss-power = <784>;
qcom,energy-overhead = <190000>;
@@ -168,78 +167,83 @@
qcom,lpm-level@1 {
reg = <0x1>;
- qcom,mode = "retention";
- qcom,xo = "xo_on";
- qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
- qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <5>; /* MAX */
- qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
- qcom,latency-us = <75>;
- qcom,ss-power = <735>;
- qcom,energy-overhead = <77341>;
- qcom,time-overhead = <105>;
- };
-
-
- qcom,lpm-level@2 {
- reg = <0x2>;
qcom,mode = "standalone_pc";
qcom,xo = "xo_on";
qcom,l2 = "l2_cache_active";
- qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
- qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <5>; /* MAX */
- qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
- qcom,latency-us = <95>;
+ qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <3>; /* NORMAL */
+ qcom,irqs-detectable;
+ qcom,gpio-detectable;
+ qcom,latency-us = <3000>;
qcom,ss-power = <725>;
qcom,energy-overhead = <99500>;
- qcom,time-overhead = <130>;
+ qcom,time-overhead = <3130>;
+ };
+
+ qcom,lpm-level@2 {
+ reg = <0x2>;
+ qcom,mode = "pc";
+ qcom,xo = "xo_on";
+ qcom,l2 = "l2_cache_retention";
+ qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <3>; /* NORMAL */
+ qcom,irqs-detectable;
+ qcom,gpio-detectable;
+ qcom,latency-us = <8000>;
+ qcom,ss-power = <138>;
+ qcom,energy-overhead = <1208400>;
+ qcom,time-overhead = <9200>;
};
qcom,lpm-level@3 {
reg = <0x3>;
qcom,mode = "pc";
qcom,xo = "xo_on";
- qcom,l2 = "l2_cache_gdhs";
- qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
- qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <5>; /* MAX */
- qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
- qcom,latency-us = <2000>;
- qcom,ss-power = <138>;
- qcom,energy-overhead = <1208400>;
- qcom,time-overhead = <3200>;
+ qcom,l2 = "l2_cache_pc";
+ qcom,vdd-mem-upper-bound = <3>; /* NORMAL */
+ qcom,vdd-mem-lower-bound = <2>; /* SVS SOC */
+ qcom,vdd-dig-upper-bound = <3>; /* NORMAL */
+ qcom,vdd-dig-lower-bound = <2>; /* SVS SOC */
+ qcom,irqs-detectable;
+ qcom,gpio-detectable;
+ qcom,latency-us = <9000>;
+ qcom,ss-power = <110>;
+ qcom,energy-overhead = <1250300>;
+ qcom,time-overhead = <9500>;
};
qcom,lpm-level@4 {
reg = <0x4>;
qcom,mode = "pc";
- qcom,xo = "xo_on";
+ qcom,xo = "xo_off";
qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
- qcom,vdd-mem-lower-bound = <750000>; /* RETENTION HIGH */
- qcom,vdd-dig-upper-bound = <3>; /* ACTIVE */
- qcom,vdd-dig-lower-bound = <2>; /* RETENTION HIGH */
- qcom,latency-us = <3000>;
- qcom,ss-power = <110>;
- qcom,energy-overhead = <1250300>;
- qcom,time-overhead = <3500>;
+ qcom,vdd-mem-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-mem-lower-bound = <3>; /* NORMAL */
+ qcom,vdd-dig-upper-bound = <5>; /* SUPER TURBO */
+ qcom,vdd-dig-lower-bound = <3>; /* NORMAL */
+ qcom,latency-us = <16300>;
+ qcom,ss-power = <63>;
+ qcom,energy-overhead = <2128000>;
+ qcom,time-overhead = <24200>;
};
qcom,lpm-level@5 {
reg = <0x5>;
qcom,mode = "pc";
qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_gdhs";
- qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
- qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <5>; /* MAX */
- qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
- qcom,latency-us = <3000>;
- qcom,ss-power = <68>;
- qcom,energy-overhead = <1350200>;
- qcom,time-overhead = <4000>;
+ qcom,l2 = "l2_cache_pc";
+ qcom,vdd-mem-upper-bound = <3>; /* NORMAL */
+ qcom,vdd-mem-lower-bound = <2>; /* SVS SOC */
+ qcom,vdd-dig-upper-bound = <3>; /* NORMAL */
+ qcom,vdd-dig-lower-bound = <2>; /* SVS SOC */
+ qcom,latency-us = <24000>;
+ qcom,ss-power = <10>;
+ qcom,energy-overhead = <3202600>;
+ qcom,time-overhead = <33000>;
};
qcom,lpm-level@6 {
@@ -247,44 +251,14 @@
qcom,mode = "pc";
qcom,xo = "xo_off";
qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
- qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
- qcom,vdd-dig-upper-bound = <5>; /* MAX */
- qcom,vdd-dig-lower-bound = <3>; /* ACTIVE */
- qcom,latency-us = <10300>;
- qcom,ss-power = <63>;
- qcom,energy-overhead = <2128000>;
- qcom,time-overhead = <18200>;
- };
-
- qcom,lpm-level@7 {
- reg = <0x7>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
- qcom,vdd-mem-lower-bound = <750000>; /* RETENTION HIGH */
- qcom,vdd-dig-upper-bound = <3>; /* ACTIVE */
- qcom,vdd-dig-lower-bound = <2>; /* RETIONTION HIGH */
- qcom,latency-us = <18000>;
- qcom,ss-power = <10>;
- qcom,energy-overhead = <3202600>;
- qcom,time-overhead = <27000>;
- };
-
- qcom,lpm-level@8 {
- reg = <0x8>;
- qcom,mode = "pc";
- qcom,xo = "xo_off";
- qcom,l2 = "l2_cache_pc";
- qcom,vdd-mem-upper-bound = <750000>; /* RETENTION HIGH */
- qcom,vdd-mem-lower-bound = <750000>; /* RETENTION LOW */
- qcom,vdd-dig-upper-bound = <2>; /* RETENTION HIGH */
- qcom,vdd-dig-lower-bound = <0>; /* RETENTION LOW */
- qcom,latency-us = <20000>;
+ qcom,vdd-mem-upper-bound = <2>; /* SVS SOC */
+ qcom,vdd-mem-lower-bound = <0>; /* RETENTION */
+ qcom,vdd-dig-upper-bound = <2>; /* SVS SOC */
+ qcom,vdd-dig-lower-bound = <0>; /* RETENTION */
+ qcom,latency-us = <26000>;
qcom,ss-power = <2>;
qcom,energy-overhead = <4252000>;
- qcom,time-overhead = <32000>;
+ qcom,time-overhead = <38000>;
};
};
@@ -306,6 +280,7 @@
qcom,gic-map = <47 172>, /* usb2_hsic_async_wakeup_irq */
<53 104>, /* mdss_irq */
<62 222>, /* ee0_krait_hlos_spmi_periph_irq */
+ <2 216>, /* tsens_upper_lower_int */
<0xff 56>, /* q6_wdog_expired_irq */
<0xff 57>, /* mss_to_apps_irq(0) */
<0xff 58>, /* mss_to_apps_irq(1) */
@@ -395,6 +370,17 @@
qcom,use-sync-timer;
};
+ qcom,rpm-log@fc19dc00 {
+ compatible = "qcom,rpm-log";
+ reg = <0xfc19dc00 0x4000>;
+ qcom,rpm-addr-phys = <0xfc000000>;
+ qcom,offset-version = <4>;
+ qcom,offset-page-buffer-addr = <36>;
+ qcom,offset-log-len = <40>;
+ qcom,offset-log-len-mask = <44>;
+ qcom,offset-page-indices = <56>;
+ };
+
qcom,rpm-stats@0xfc19dbd0{
compatible = "qcom,rpm-stats";
reg = <0xfc19dbd0 0x1000>;
diff --git a/arch/arm/boot/dts/msm8610-regulator.dtsi b/arch/arm/boot/dts/msm8610-regulator.dtsi
index f11f04b..d50902c 100644
--- a/arch/arm/boot/dts/msm8610-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8610-regulator.dtsi
@@ -19,7 +19,44 @@
qcom,hpm-min-load = <100000>;
regulator-min-microvolt = <1>;
regulator-max-microvolt = <7>;
- qcom,consumer-supplies = "vdd_dig", "";
+ qcom,consumer-supplies = "vdd_dig", "", "vdd_sr2_dig", "";
+ };
+};
+
+/* SPM controlled regulators */
+
+&spmi_bus {
+ qcom,pm8110@1 {
+ pm8110_s2: spm-regulator@1700 {
+ compatible = "qcom,spm-regulator";
+ regulator-name = "8110_s2";
+ reg = <0x1700 0x100>;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1350000>;
+ };
+ };
+};
+
+/* CPR controlled regulator */
+
+/ {
+ apc_vreg_corner: regulator@f9018000 {
+ status = "okay";
+ compatible = "qcom,cpr-regulator";
+ reg = <0xf9018000 0x1000>,
+ <0xfc4b80b0 8>;
+ reg-names = "rbcpr", "efuse_phys";
+ regulator-name = "apc_corner";
+ regulator-min-microvolt = <1>;
+ regulator-max-microvolt = <4>;
+ qcom,num-efuse-bits = <5>;
+ qcom,efuse-bit-pos = <6 7 8 9 10>;
+ qcom,pvs-bin-process = <0 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2
+ 2 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0>;
+ qcom,pvs-corner-ceiling-slow = <1050000 1150000 1275000 1350000>;
+ qcom,pvs-corner-ceiling-nom = <975000 1075000 1200000 1200000>;
+ qcom,pvs-corner-ceiling-fast = <900000 1000000 1140000 1140000>;
+ vdd-apc-supply = <&pm8110_s2>;
};
};
@@ -38,15 +75,6 @@
regulator-always-on;
};
- pm8110_s2: regulator@1700 {
- status = "okay";
- regulator-min-microvolt = <1050000>;
- regulator-max-microvolt = <1150000>;
- qcom,enable-time = <500>;
- qcom,system-load = <100000>;
- regulator-always-on;
- };
-
pm8110_s3: regulator@1a00 {
status = "okay";
regulator-min-microvolt = <1350000>;
diff --git a/arch/arm/boot/dts/msm8610-rumi.dts b/arch/arm/boot/dts/msm8610-rumi.dts
index a4507e3..cab7560 100644
--- a/arch/arm/boot/dts/msm8610-rumi.dts
+++ b/arch/arm/boot/dts/msm8610-rumi.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 8610 Rumi";
- compatible = "qcom,msm8610-rumi", "qcom,msm8610";
+ compatible = "qcom,msm8610-rumi", "qcom,msm8610", "qcom,rumi";
qcom,msm-id = <147 15 0>;
serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8610-sim.dts b/arch/arm/boot/dts/msm8610-sim.dts
index 2268daf..1838b94 100644
--- a/arch/arm/boot/dts/msm8610-sim.dts
+++ b/arch/arm/boot/dts/msm8610-sim.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 8610 Simulator";
- compatible = "qcom,msm8610-sim", "qcom,msm8610";
+ compatible = "qcom,msm8610-sim", "qcom,msm8610", "qcom,sim";
qcom,msm-id = <147 16 0>;
serial@f991f000 {
diff --git a/arch/arm/boot/dts/msm8610-smp2p.dtsi b/arch/arm/boot/dts/msm8610-smp2p.dtsi
new file mode 100644
index 0000000..4a5273b
--- /dev/null
+++ b/arch/arm/boot/dts/msm8610-smp2p.dtsi
@@ -0,0 +1,184 @@
+/* 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,smp2p-modem {
+ compatible = "qcom,smp2p";
+ reg = <0xfa006000 0x1000>, <0x8 0x0>;
+ reg-names = "irq-reg-base", "irq-reg-offset";
+ qcom,remote-pid = <1>;
+ qcom,irq-bitmask = <0x4000>;
+ interrupts = <0 27 1>;
+ };
+
+ qcom,smp2p-adsp {
+ compatible = "qcom,smp2p";
+ reg = <0xfa006000 0x1000>, <0x8 0x0>;
+ reg-names = "irq-reg-base", "irq-reg-offset";
+ qcom,remote-pid = <2>;
+ qcom,irq-bitmask = <0x400>;
+ interrupts = <0 158 1>;
+ };
+
+ qcom,smp2p-wcnss {
+ compatible = "qcom,smp2p";
+ reg = <0xfa006000 0x1000>, <0x8 0x0>;
+ reg-names = "irq-reg-base", "irq-reg-offset";
+ qcom,remote-pid = <4>;
+ qcom,irq-bitmask = <0x40000>;
+ interrupts = <0 143 1>;
+ };
+
+ smp2pgpio_smp2p_7_in: qcom,smp2pgpio-smp2p-7-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <7>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_7_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_7_in";
+ gpios = <&smp2pgpio_smp2p_7_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_7_out: qcom,smp2pgpio-smp2p-7-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <7>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_7_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_7_out";
+ gpios = <&smp2pgpio_smp2p_7_out 0 0>;
+ };
+
+ smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_1_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_1_in";
+ gpios = <&smp2pgpio_smp2p_1_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_1_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_1_out";
+ gpios = <&smp2pgpio_smp2p_1_out 0 0>;
+ };
+
+ smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "slave-kernel";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "master-kernel";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <2>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_2_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_2_in";
+ gpios = <&smp2pgpio_smp2p_2_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_2_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_2_out";
+ gpios = <&smp2pgpio_smp2p_2_out 0 0>;
+ };
+
+ smp2pgpio_smp2p_4_in: qcom,smp2pgpio-smp2p-4-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <4>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_4_in {
+ compatible = "qcom,smp2pgpio_test_smp2p_4_in";
+ gpios = <&smp2pgpio_smp2p_4_in 0 0>;
+ };
+
+ smp2pgpio_smp2p_4_out: qcom,smp2pgpio-smp2p-4-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "smp2p";
+ qcom,remote-pid = <4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ qcom,smp2pgpio_test_smp2p_4_out {
+ compatible = "qcom,smp2pgpio_test_smp2p_4_out";
+ gpios = <&smp2pgpio_smp2p_4_out 0 0>;
+ };
+};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index d945619..5967dfb 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -13,9 +13,12 @@
/include/ "skeleton.dtsi"
/include/ "msm-iommu-v0.dtsi"
/include/ "msm8610-ion.dtsi"
+/include/ "msm8610-gpu.dtsi"
/include/ "msm-gdsc.dtsi"
/include/ "msm8610-coresight.dtsi"
/include/ "msm8610-pm.dtsi"
+/include/ "msm8610-smp2p.dtsi"
+/include/ "msm8610-bus.dtsi"
/ {
model = "Qualcomm MSM 8610";
@@ -77,6 +80,7 @@
qcom,buffer-type-tz-usage-map = <0x1 0x1>,
<0x1fe 0x2>;
qcom,hfi = "q6";
+ qcom,max-hw-load = <97200>; /* FWVGA @ 30 * 2 */
};
usb@f9a55000 {
@@ -262,7 +266,7 @@
compatible = "qcom,acpuclk-a7";
reg = <0xf9011050 0x8>;
reg-names = "rcg_base";
- a7_cpu-supply = <&pm8110_s2>;
+ a7_cpu-supply = <&apc_vreg_corner>;
a7_mem-supply = <&pm8110_l3>;
};
@@ -453,6 +457,12 @@
qcom,is-loadable;
qcom,firmware-name = "mba";
qcom,pil-self-auth;
+
+ /* GPIO input from mss */
+ qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+
+ /* GPIO output to mss */
+ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
};
qcom,lpass@fe200000 {
@@ -474,11 +484,19 @@
interrupts = <0 184 0>;
qcom,sensors = <2>;
qcom,slope = <2901 2846>;
- qcom,calib-mode = "fuse_map2";
+ qcom,calib-mode = "fuse_map3";
qcom,calibration-less-mode;
qcom,tsens-local-init;
};
+ qcom,msm-thermal {
+ compatible = "qcom,msm-thermal";
+ qcom,sensor-id = <0>;
+ qcom,poll-ms = <250>;
+ qcom,limit-temp = <60>;
+ qcom,temp-hysteresis = <10>;
+ qcom,freq-step = <2>;
+ };
};
&gdsc_vfe {
diff --git a/arch/arm/boot/dts/msm8660-surf.dts b/arch/arm/boot/dts/msm8660-surf.dts
index 45bc4bb..4518fc4 100644
--- a/arch/arm/boot/dts/msm8660-surf.dts
+++ b/arch/arm/boot/dts/msm8660-surf.dts
@@ -4,7 +4,7 @@
/ {
model = "Qualcomm MSM8660 SURF";
- compatible = "qcom,msm8660-surf", "qcom,msm8660";
+ compatible = "qcom,msm8660-surf", "qcom,msm8660", "qcom,surf";
interrupt-parent = <&intc>;
intc: interrupt-controller@02080000 {
diff --git a/arch/arm/boot/dts/msm8974-bus.dtsi b/arch/arm/boot/dts/msm8974-bus.dtsi
index 828e7ae..cebb907 100644
--- a/arch/arm/boot/dts/msm8974-bus.dtsi
+++ b/arch/arm/boot/dts/msm8974-bus.dtsi
@@ -296,6 +296,9 @@
qcom,mode = "Fixed";
qcom,qport = <1>;
qcom,mas-hw-id = <19>;
+ qcom,prio-rd = <1>;
+ qcom,prio-wr = <1>;
+ qcom,hw-sel = "NoC";
};
mas-snoc-cfg {
@@ -432,6 +435,9 @@
qcom,qport = <10>;
qcom,mode = "Fixed";
qcom,mas-hw-id = <31>;
+ qcom,prio-rd = <1>;
+ qcom,prio-wr = <1>;
+ qcom,hw-sel = "NoC";
};
mas-usb3 {
@@ -442,8 +448,8 @@
qcom,mode = "Fixed";
qcom,qport = <11>;
qcom,mas-hw-id = <32>;
- qcom,prio-rd = <2>;
- qcom,prio-wr = <2>;
+ qcom,prio-rd = <1>;
+ qcom,prio-wr = <1>;
qcom,hw-sel = "NoC";
qcom,iface-clk-node = "msm_usb3";
};
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
similarity index 93%
copy from arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
copy to arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
index 3fb5b20..df0db7e 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-cdp.dtsi
@@ -15,19 +15,25 @@
actuator0: qcom,actuator@18 {
cell-index = <0>;
- reg = <0x18>;
+ reg = <0x18 0x0>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ };
+
+ actuator1: qcom,actuator@36 {
+ cell-index = <1>;
+ reg = <0x36>;
compatible = "qcom,actuator";
qcom,cci-master = <0>;
};
qcom,camera@6e {
compatible = "qcom,s5k3l1yx";
- reg = <0x6e>;
+ reg = <0x6e 0x0>;
qcom,slave-id = <0x6e 0x0 0x3121>;
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 = "s5k3l1yx";
cam_vdig-supply = <&pm8941_l3>;
@@ -65,11 +71,12 @@
qcom,camera@20 {
compatible = "qcom,imx135";
reg = <0x20>;
- qcom,slave-id = <0x20 0x0 0x1210>;
+ qcom,slave-id = <0x20 0x0016 0x0135>;
qcom,csiphy-sd-index = <0>;
qcom,csid-sd-index = <0>;
qcom,mount-angle = <90>;
qcom,sensor-name = "imx135";
+ qcom,actuator-src = <&actuator1>;
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
@@ -99,10 +106,9 @@
status = "ok";
};
-
qcom,camera@6c {
compatible = "qcom,ov2720";
- reg = <0x6c>;
+ reg = <0x6c 0x0>;
qcom,slave-id = <0x6c 0x300A 0x2720>;
qcom,csiphy-sd-index = <2>;
qcom,csid-sd-index = <0>;
@@ -131,13 +137,13 @@
qcom,csi-lane-mask = <0x7>;
qcom,sensor-position = <1>;
qcom,sensor-mode = <1>;
- qcom,cci-master = <1>;
+ qcom,cci-master = <0>;
status = "ok";
};
qcom,camera@90 {
compatible = "qcom,mt9m114";
- reg = <0x90>;
+ reg = <0x90 0x0>;
qcom,slave-id = <0x90 0x0 0x2481>;
qcom,csiphy-sd-index = <1>;
qcom,csid-sd-index = <0>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
index c9d1abc..f58c1e2 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-fluid.dtsi
@@ -20,6 +20,13 @@
qcom,cci-master = <0>;
};
+ actuator1: qcom,actuator@36 {
+ cell-index = <1>;
+ reg = <0x36>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ };
+
qcom,camera@6e {
compatible = "qcom,s5k3l1yx";
reg = <0x6e>;
@@ -62,6 +69,44 @@
status = "ok";
};
+ qcom,camera@20 {
+ compatible = "qcom,imx135";
+ reg = <0x20>;
+ qcom,slave-id = <0x20 0x0016 0x0135>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <270>;
+ qcom,sensor-name = "imx135";
+ qcom,actuator-src = <&actuator1>;
+ cam_vdig-supply = <&pm8941_l3>;
+ cam_vana-supply = <&pm8941_l17>;
+ cam_vio-supply = <&pm8941_lvs3>;
+ cam_vaf-supply = <&pm8941_l23>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 1 0 0>;
+ qcom,cam-vreg-min-voltage = <1225000 0 2850000 3000000>;
+ qcom,cam-vreg-max-voltage = <1225000 0 2850000 3000000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 15 0>,
+ <&msmgpio 90 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET1";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 30000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x1F>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,sensor-type = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ };
+
qcom,camera@6c {
compatible = "qcom,ov2720";
reg = <0x6c>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
index f9b89e1..5a97a11 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-liquid.dtsi
@@ -21,6 +21,13 @@
qcom,cci-master = <0>;
};
+ actuator1: qcom,actuator@36 {
+ cell-index = <1>;
+ reg = <0x36>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ };
+
qcom,camera@6e {
compatible = "qcom,s5k3l1yx";
reg = <0x6e>;
@@ -31,7 +38,7 @@
qcom,sensor-name = "s5k3l1yx";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
- cam_vio-supply = <&pm8941_lvs3>;
+ cam_vio-supply = <&pm8941_lvs2>;
cam_vaf-supply = <&pm8941_l23>;
qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
"cam_vaf";
@@ -58,6 +65,44 @@
status = "ok";
};
+ qcom,camera@20 {
+ compatible = "qcom,imx135";
+ reg = <0x20>;
+ qcom,slave-id = <0x20 0x0016 0x0135>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <0>;
+ qcom,sensor-name = "imx135";
+ qcom,actuator-src = <&actuator1>;
+ cam_vdig-supply = <&pm8941_l3>;
+ cam_vana-supply = <&pm8941_l17>;
+ cam_vio-supply = <&pm8941_lvs2>;
+ cam_vaf-supply = <&pm8941_l23>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 1 0 0>;
+ qcom,cam-vreg-min-voltage = <1225000 0 2850000 3000000>;
+ qcom,cam-vreg-max-voltage = <1225000 0 2850000 3000000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 15 0>,
+ <&msmgpio 90 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK", "CAM_RESET1";
+ qcom,gpio-set-tbl-num = <1 1>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 30000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x1F>;
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,sensor-type = <0>;
+ qcom,cci-master = <0>;
+ status = "ok";
+ };
+
qcom,camera@6c {
compatible = "qcom,ov2720";
reg = <0x6c>;
@@ -68,7 +113,7 @@
qcom,sensor-name = "ov2720";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
- cam_vio-supply = <&pm8941_lvs3>;
+ cam_vio-supply = <&pm8941_lvs2>;
qcom,cam-vreg-name = "cam_vdig", "cam_vana", "cam_vio";
qcom,cam-vreg-type = <0 0 1>;
qcom,cam-vreg-min-voltage = <1225000 2850000 0>;
@@ -103,7 +148,7 @@
qcom,sensor-name = "mt9m114";
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
- cam_vio-supply = <&pm8941_lvs3>;
+ cam_vio-supply = <&pm8941_lvs2>;
qcom,cam-vreg-name = "cam_vdig", "cam_vana", "cam_vio";
qcom,cam-vreg-type = <0 0 1>;
qcom,cam-vreg-min-voltage = <1225000 2850000 0>;
diff --git a/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
similarity index 95%
rename from arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
rename to arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
index 3fb5b20..767a705 100644
--- a/arch/arm/boot/dts/msm8974-camera-sensor-cdp-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera-sensor-mtp.dtsi
@@ -20,6 +20,13 @@
qcom,cci-master = <0>;
};
+ actuator1: qcom,actuator@36 {
+ cell-index = <1>;
+ reg = <0x36>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ };
+
qcom,camera@6e {
compatible = "qcom,s5k3l1yx";
reg = <0x6e>;
@@ -65,11 +72,12 @@
qcom,camera@20 {
compatible = "qcom,imx135";
reg = <0x20>;
- qcom,slave-id = <0x20 0x0 0x1210>;
+ qcom,slave-id = <0x20 0x0016 0x0135>;
qcom,csiphy-sd-index = <0>;
qcom,csid-sd-index = <0>;
qcom,mount-angle = <90>;
qcom,sensor-name = "imx135";
+ qcom,actuator-src = <&actuator1>;
cam_vdig-supply = <&pm8941_l3>;
cam_vana-supply = <&pm8941_l17>;
cam_vio-supply = <&pm8941_lvs3>;
diff --git a/arch/arm/boot/dts/msm8974-cdp.dtsi b/arch/arm/boot/dts/msm8974-cdp.dtsi
index adab873..41e3783 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dtsi
+++ b/arch/arm/boot/dts/msm8974-cdp.dtsi
@@ -13,7 +13,7 @@
/include/ "dsi-panel-toshiba-720p-video.dtsi"
/include/ "dsi-panel-orise-720p-video.dtsi"
/include/ "msm8974-leds.dtsi"
-/include/ "msm8974-camera-sensor-cdp-mtp.dtsi"
+/include/ "msm8974-camera-sensor-cdp.dtsi"
/ {
serial@f991e000 {
@@ -247,7 +247,7 @@
linux,name = "wled:backlight";
linux,default-trigger = "bkl-trigger";
qcom,cs-out-en;
- qcom,op-fdbck;
+ qcom,op-fdbck = <1>;
qcom,default-state = "on";
qcom,max-current = <25>;
qcom,ctrl-delay-us = <0>;
@@ -298,6 +298,10 @@
};
};
+&sdcc1 {
+ status = "disabled";
+};
+
&sdcc2 {
#address-cells = <0>;
interrupt-parent = <&sdcc2>;
@@ -310,6 +314,7 @@
interrupt-names = "core_irq", "bam_irq", "status_irq";
cd-gpios = <&msmgpio 62 0x1>;
wp-gpios = <&pm8941_gpios 29 0x1>;
+ status = "disabled";
};
&sdhc_1 {
@@ -331,6 +336,7 @@
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
qcom,nonremovable;
+ status = "ok";
};
&sdhc_2 {
@@ -358,6 +364,7 @@
qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+ status = "ok";
};
&uart7 {
diff --git a/arch/arm/boot/dts/msm8974-fluid.dtsi b/arch/arm/boot/dts/msm8974-fluid.dtsi
index e70d5d8..ec8a459 100644
--- a/arch/arm/boot/dts/msm8974-fluid.dtsi
+++ b/arch/arm/boot/dts/msm8974-fluid.dtsi
@@ -224,7 +224,7 @@
linux,name = "wled:backlight";
linux,default-trigger = "bkl-trigger";
qcom,cs-out-en;
- qcom,op-fdbck;
+ qcom,op-fdbck = <1>;
qcom,default-state = "on";
qcom,max-current = <25>;
qcom,ctrl-delay-us = <0>;
@@ -277,6 +277,7 @@
&sdcc1 {
qcom,bus-width = <4>;
+ status = "disabled";
};
&sdcc2 {
@@ -290,6 +291,7 @@
2 &msmgpio 62 0x3>;
interrupt-names = "core_irq", "bam_irq", "status_irq";
cd-gpios = <&msmgpio 62 0x1>;
+ status = "disabled";
};
&sdhc_1 {
@@ -311,6 +313,7 @@
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
qcom,nonremovable;
+ status = "ok";
};
&sdhc_2 {
@@ -338,6 +341,7 @@
qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+ status = "ok";
};
&usb3 {
@@ -350,6 +354,7 @@
&pm8941_chg {
status = "ok";
+ qcom,chg-charging-disabled;
qcom,chg-chgr@1000 {
status = "ok";
diff --git a/arch/arm/boot/dts/msm8974-gpu.dtsi b/arch/arm/boot/dts/msm8974-gpu.dtsi
index ceba72f..a7544ab 100644
--- a/arch/arm/boot/dts/msm8974-gpu.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpu.dtsi
@@ -62,21 +62,21 @@
reg = <0>;
qcom,gpu-freq = <450000000>;
qcom,bus-freq = <5>;
- qcom,io-fraction = <0>;
+ qcom,io-fraction = <33>;
};
qcom,gpu-pwrlevel@1 {
reg = <1>;
qcom,gpu-freq = <300000000>;
qcom,bus-freq = <4>;
- qcom,io-fraction = <33>;
+ qcom,io-fraction = <66>;
};
qcom,gpu-pwrlevel@2 {
reg = <2>;
qcom,gpu-freq = <300000000>;
qcom,bus-freq = <3>;
- qcom,io-fraction = <33>;
+ qcom,io-fraction = <66>;
};
qcom,gpu-pwrlevel@3 {
diff --git a/arch/arm/boot/dts/msm8974-liquid.dtsi b/arch/arm/boot/dts/msm8974-liquid.dtsi
index 8a8a8b7..0f38e44 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dtsi
+++ b/arch/arm/boot/dts/msm8974-liquid.dtsi
@@ -764,6 +764,14 @@
};
};
+&sdcc1 {
+ status = "disabled";
+};
+
+&sdcc2 {
+ status = "disabled";
+};
+
&sdhc_1 {
vdd-supply = <&pm8941_l20>;
vdd-io-supply = <&pm8941_s3>;
@@ -783,6 +791,7 @@
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
qcom,nonremovable;
+ status = "ok";
};
&sdhc_2 {
@@ -799,4 +808,5 @@
qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+ status = "ok";
};
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index 0912a33..5c42b2c 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -50,7 +50,13 @@
<0x0160 0x22222222>,
<0x0164 0x00002222>;
qcom,mdp-settings = <0x02E0 0x000000AA>,
- <0x02E4 0x00000055>;
+ <0x02E4 0x00000055>,
+ <0x03AC 0xC0000CCC>,
+ <0x03B4 0xC0000CCC>,
+ <0x03BC 0x00CCCCCC>,
+ <0x04A8 0x0CCCC0C0>,
+ <0x04B0 0xCCCCC0C0>,
+ <0x04B8 0xCCCCC000>;
mdss_fb0: qcom,mdss_fb_primary {
cell-index = <0>;
diff --git a/arch/arm/boot/dts/msm8974-mtp.dtsi b/arch/arm/boot/dts/msm8974-mtp.dtsi
index d61de02..5970e6b 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8974-mtp.dtsi
@@ -11,7 +11,7 @@
*/
/include/ "dsi-panel-toshiba-720p-video.dtsi"
-/include/ "msm8974-camera-sensor-cdp-mtp.dtsi"
+/include/ "msm8974-camera-sensor-mtp.dtsi"
/include/ "msm8974-leds.dtsi"
/ {
@@ -199,7 +199,7 @@
linux,name = "wled:backlight";
linux,default-trigger = "bkl-trigger";
qcom,cs-out-en;
- qcom,op-fdbck;
+ qcom,op-fdbck = <1>;
qcom,default-state = "on";
qcom,max-current = <25>;
qcom,ctrl-delay-us = <0>;
@@ -250,6 +250,10 @@
};
};
+&sdcc1 {
+ status = "disabled";
+};
+
&sdcc2 {
#address-cells = <0>;
interrupt-parent = <&sdcc2>;
@@ -261,6 +265,7 @@
2 &msmgpio 62 0x3>;
interrupt-names = "core_irq", "bam_irq", "status_irq";
cd-gpios = <&msmgpio 62 0x1>;
+ status = "disabled";
};
&sdhc_1 {
@@ -282,6 +287,7 @@
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
qcom,nonremovable;
+ status = "ok";
};
&sdhc_2 {
@@ -309,6 +315,7 @@
qcom,pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
qcom,pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
qcom,pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+ status = "ok";
};
&usb_otg {
@@ -329,6 +336,7 @@
&pm8941_chg {
status = "ok";
+ qcom,chg-charging-disabled;
qcom,chg-chgr@1000 {
status = "ok";
diff --git a/arch/arm/boot/dts/msm8974-rumi.dtsi b/arch/arm/boot/dts/msm8974-rumi.dtsi
index ce9d6c9..c569e58 100644
--- a/arch/arm/boot/dts/msm8974-rumi.dtsi
+++ b/arch/arm/boot/dts/msm8974-rumi.dtsi
@@ -11,7 +11,7 @@
*/
/include/ "msm8974-leds.dtsi"
-/include/ "msm8974-camera-sensor-cdp-mtp.dtsi"
+/include/ "msm8974-camera-sensor-cdp.dtsi"
/ {
timer {
diff --git a/arch/arm/boot/dts/msm8974-sim.dtsi b/arch/arm/boot/dts/msm8974-sim.dtsi
index a5606b8..786c50c 100644
--- a/arch/arm/boot/dts/msm8974-sim.dtsi
+++ b/arch/arm/boot/dts/msm8974-sim.dtsi
@@ -12,7 +12,7 @@
/include/ "dsi-panel-sim-video.dtsi"
/include/ "msm8974-leds.dtsi"
-/include/ "msm8974-camera-sensor-cdp-mtp.dtsi"
+/include/ "msm8974-camera-sensor-cdp.dtsi"
/ {
qcom,mdss_dsi@fd922800 {
diff --git a/arch/arm/boot/dts/msm8974-smp2p.dtsi b/arch/arm/boot/dts/msm8974-smp2p.dtsi
index 1b08246..91029e2 100644
--- a/arch/arm/boot/dts/msm8974-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm8974-smp2p.dtsi
@@ -34,7 +34,6 @@
interrupts = <0 143 1>;
};
- /* SMP2P Test Driver for inbound entries */
smp2pgpio_smp2p_7_in: qcom,smp2pgpio-smp2p-7-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -51,7 +50,6 @@
gpios = <&smp2pgpio_smp2p_7_in 0 0>;
};
- /* SMP2P Test Driver for outbound entries */
smp2pgpio_smp2p_7_out: qcom,smp2pgpio-smp2p-7-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -67,7 +65,6 @@
gpios = <&smp2pgpio_smp2p_7_out 0 0>;
};
- /* SMP2P Test Driver for modem inbound */
smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -84,7 +81,6 @@
gpios = <&smp2pgpio_smp2p_1_in 0 0>;
};
- /* SMP2P Test Driver for modem output */
smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -100,7 +96,6 @@
gpios = <&smp2pgpio_smp2p_1_out 0 0>;
};
- /* SMP2P SSR Driver for inbound entry from modem. */
smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "slave-kernel";
@@ -112,7 +107,6 @@
#interrupt-cells = <2>;
};
- /* SMP2P SSR Driver for outbound entry to modem */
smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "master-kernel";
@@ -123,7 +117,6 @@
#interrupt-cells = <2>;
};
- /* SMP2P Test Driver for adsp inbound */
smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -140,7 +133,6 @@
gpios = <&smp2pgpio_smp2p_2_in 0 0>;
};
- /* SMP2P Test Driver for adsp output */
smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -156,7 +148,6 @@
gpios = <&smp2pgpio_smp2p_2_out 0 0>;
};
- /* SMP2P Test Driver for wcnss inbound */
smp2pgpio_smp2p_4_in: qcom,smp2pgpio-smp2p-4-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -173,7 +164,6 @@
gpios = <&smp2pgpio_smp2p_4_in 0 0>;
};
- /* SMP2P Test Driver for wcnss output */
smp2pgpio_smp2p_4_out: qcom,smp2pgpio-smp2p-4-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -184,6 +174,27 @@
#interrupt-cells = <2>;
};
+ smp2pgpio_ssr_smp2p_4_in: qcom,smp2pgpio-ssr-smp2p-4-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "slave-kernel";
+ qcom,remote-pid = <4>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ smp2pgpio_ssr_smp2p_4_out: qcom,smp2pgpio-ssr-smp2p-4-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "master-kernel";
+ qcom,remote-pid = <4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
qcom,smp2pgpio_test_smp2p_4_out {
compatible = "qcom,smp2pgpio_test_smp2p_4_out";
gpios = <&smp2pgpio_smp2p_4_out 0 0>;
diff --git a/arch/arm/boot/dts/msm8974-v1-cdp.dts b/arch/arm/boot/dts/msm8974-v1-cdp.dts
index 33bd1fb..cb58026 100644
--- a/arch/arm/boot/dts/msm8974-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-v1-cdp.dts
@@ -17,7 +17,7 @@
/ {
model = "Qualcomm MSM 8974 CDP";
- compatible = "qcom,msm8974-cdp", "qcom,msm8974";
+ compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
qcom,msm-id = <126 1 0>;
};
@@ -25,3 +25,7 @@
status = "ok";
vbus-supply = <&usb2_otg_sw>;
};
+
+&hsic_host {
+ qcom,phy-sof-workaround;
+};
diff --git a/arch/arm/boot/dts/msm8974-v1-fluid.dts b/arch/arm/boot/dts/msm8974-v1-fluid.dts
index 9fb287c..0f762a8 100644
--- a/arch/arm/boot/dts/msm8974-v1-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-v1-fluid.dts
@@ -17,7 +17,7 @@
/ {
model = "Qualcomm MSM 8974 FLUID";
- compatible = "qcom,msm8974-fluid", "qcom,msm8974";
+ compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
qcom,msm-id = <126 3 0>;
};
diff --git a/arch/arm/boot/dts/msm8974-v1-liquid.dts b/arch/arm/boot/dts/msm8974-v1-liquid.dts
index 5c12569..ccbd82f 100644
--- a/arch/arm/boot/dts/msm8974-v1-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-v1-liquid.dts
@@ -17,6 +17,6 @@
/ {
model = "Qualcomm MSM 8974 LIQUID";
- compatible = "qcom,msm8974-liquid", "qcom,msm8974";
+ compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
qcom,msm-id = <126 9 0>;
};
diff --git a/arch/arm/boot/dts/msm8974-v1-mtp.dts b/arch/arm/boot/dts/msm8974-v1-mtp.dts
index 205ee24..6cb9f09 100644
--- a/arch/arm/boot/dts/msm8974-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v1-mtp.dts
@@ -17,7 +17,7 @@
/ {
model = "Qualcomm MSM 8974 MTP";
- compatible = "qcom,msm8974-mtp", "qcom,msm8974";
+ compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
qcom,msm-id = <126 8 0>;
};
diff --git a/arch/arm/boot/dts/msm8974-v1-rumi.dts b/arch/arm/boot/dts/msm8974-v1-rumi.dts
index ebb37b7..caf89ee 100644
--- a/arch/arm/boot/dts/msm8974-v1-rumi.dts
+++ b/arch/arm/boot/dts/msm8974-v1-rumi.dts
@@ -17,6 +17,6 @@
/ {
model = "Qualcomm MSM 8974 RUMI";
- compatible = "qcom,msm8974-rumi", "qcom,msm8974";
+ compatible = "qcom,msm8974-rumi", "qcom,msm8974", "qcom,rumi";
qcom,msm-id = <126 15 0>;
};
diff --git a/arch/arm/boot/dts/msm8974-v1-sim.dts b/arch/arm/boot/dts/msm8974-v1-sim.dts
index 29add5d..c4b29c2 100644
--- a/arch/arm/boot/dts/msm8974-v1-sim.dts
+++ b/arch/arm/boot/dts/msm8974-v1-sim.dts
@@ -17,6 +17,6 @@
/ {
model = "Qualcomm MSM 8974 Simulator";
- compatible = "qcom,msm8974-sim", "qcom,msm8974";
+ compatible = "qcom,msm8974-sim", "qcom,msm8974", "qcom,sim";
qcom,msm-id = <126 16 0>;
};
diff --git a/arch/arm/boot/dts/msm8974-v1.dtsi b/arch/arm/boot/dts/msm8974-v1.dtsi
index bccf0fe..62837a1 100644
--- a/arch/arm/boot/dts/msm8974-v1.dtsi
+++ b/arch/arm/boot/dts/msm8974-v1.dtsi
@@ -56,6 +56,10 @@
qcom,write-64bit;
};
+&mdss_mdp {
+ qcom,mdss-pingpong-off = <0x00021B00 0x00021C00 0x00021D00>;
+};
+
&msm_vidc {
qcom,vidc-cp-map = <0x1000000 0x3f000000>;
qcom,vidc-ns-map = <0x40000000 0x40000000>;
@@ -124,3 +128,7 @@
&ldrex_spinlock {
status = "ok";
};
+
+&usb_otg {
+ qcom,hsusb-otg-pnoc-errata-fix;
+};
diff --git a/arch/arm/boot/dts/msm8974-v2-cdp.dts b/arch/arm/boot/dts/msm8974-v2-cdp.dts
index e591dee..4fa1f2a 100644
--- a/arch/arm/boot/dts/msm8974-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-cdp.dts
@@ -17,21 +17,18 @@
/ {
model = "Qualcomm MSM 8974v2 CDP";
- compatible = "qcom,msm8974-cdp", "qcom,msm8974";
+ compatible = "qcom,msm8974-cdp", "qcom,msm8974", "qcom,cdp";
qcom,msm-id = <126 1 0x20000>;
};
&usb3 {
- #address-cells = <0>;
interrupt-parent = <&usb3>;
- interrupts = <0 1 2 3>;
+ interrupts = <0 1>;
#interrupt-cells = <1>;
- interrupt-map-mask = <0xffffffff>;
- interrupt-map = <0 &intc 0 131 0
- 1 &intc 0 179 0
- 2 &intc 0 133 0
- 3 &spmi_bus 0x0 0x0 0x9 0x0>;
- interrupt-names = "irq", "otg_irq", "hs_phy_irq", "pmic_id_irq";
+ interrupt-map-mask = <0x0 0xffffffff>;
+ interrupt-map = <0x0 0 &intc 0 133 0
+ 0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
+ interrupt-names = "hs_phy_irq", "pmic_id_irq";
qcom,misc-ref = <&pm8941_misc>;
};
diff --git a/arch/arm/boot/dts/msm8974-v2-fluid.dts b/arch/arm/boot/dts/msm8974-v2-fluid.dts
index 4efad9e..c5779b1 100644
--- a/arch/arm/boot/dts/msm8974-v2-fluid.dts
+++ b/arch/arm/boot/dts/msm8974-v2-fluid.dts
@@ -17,21 +17,18 @@
/ {
model = "Qualcomm MSM 8974v2 FLUID";
- compatible = "qcom,msm8974-fluid", "qcom,msm8974";
+ compatible = "qcom,msm8974-fluid", "qcom,msm8974", "qcom,fluid";
qcom,msm-id = <126 3 0x20000>;
};
&usb3 {
- #address-cells = <0>;
interrupt-parent = <&usb3>;
- interrupts = <0 1 2 3>;
+ interrupts = <0 1>;
#interrupt-cells = <1>;
- interrupt-map-mask = <0xffffffff>;
- interrupt-map = <0 &intc 0 131 0
- 1 &intc 0 179 0
- 2 &intc 0 133 0
- 3 &spmi_bus 0x0 0x0 0x9 0x0>;
- interrupt-names = "irq", "otg_irq", "hs_phy_irq", "pmic_id_irq";
+ interrupt-map-mask = <0x0 0xffffffff>;
+ interrupt-map = <0x0 0 &intc 0 133 0
+ 0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
+ interrupt-names = "hs_phy_irq", "pmic_id_irq";
qcom,misc-ref = <&pm8941_misc>;
};
diff --git a/arch/arm/boot/dts/msm8974-v2-liquid.dts b/arch/arm/boot/dts/msm8974-v2-liquid.dts
index 86584f8..7132f43 100644
--- a/arch/arm/boot/dts/msm8974-v2-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-v2-liquid.dts
@@ -17,21 +17,18 @@
/ {
model = "Qualcomm MSM 8974v2 LIQUID";
- compatible = "qcom,msm8974-liquid", "qcom,msm8974";
+ compatible = "qcom,msm8974-liquid", "qcom,msm8974", "qcom,liquid";
qcom,msm-id = <126 9 0x20000>;
};
&usb3 {
- #address-cells = <0>;
interrupt-parent = <&usb3>;
- interrupts = <0 1 2 3>;
+ interrupts = <0 1>;
#interrupt-cells = <1>;
- interrupt-map-mask = <0xffffffff>;
- interrupt-map = <0 &intc 0 131 0
- 1 &intc 0 179 0
- 2 &intc 0 133 0
- 3 &spmi_bus 0x0 0x0 0x9 0x0>;
- interrupt-names = "irq", "otg_irq", "hs_phy_irq", "pmic_id_irq";
+ interrupt-map-mask = <0x0 0xffffffff>;
+ interrupt-map = <0x0 0 &intc 0 133 0
+ 0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
+ interrupt-names = "hs_phy_irq", "pmic_id_irq";
qcom,misc-ref = <&pm8941_misc>;
};
diff --git a/arch/arm/boot/dts/msm8974-v2-mtp.dts b/arch/arm/boot/dts/msm8974-v2-mtp.dts
index a2e2ffa..d38e663 100644
--- a/arch/arm/boot/dts/msm8974-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-v2-mtp.dts
@@ -17,21 +17,18 @@
/ {
model = "Qualcomm MSM 8974v2 MTP";
- compatible = "qcom,msm8974-mtp", "qcom,msm8974";
+ compatible = "qcom,msm8974-mtp", "qcom,msm8974", "qcom,mtp";
qcom,msm-id = <126 8 0x20000>;
};
&usb3 {
- #address-cells = <0>;
interrupt-parent = <&usb3>;
- interrupts = <0 1 2 3>;
+ interrupts = <0 1>;
#interrupt-cells = <1>;
- interrupt-map-mask = <0xffffffff>;
- interrupt-map = <0 &intc 0 131 0
- 1 &intc 0 179 0
- 2 &intc 0 133 0
- 3 &spmi_bus 0x0 0x0 0x9 0x0>;
- interrupt-names = "irq", "otg_irq", "hs_phy_irq", "pmic_id_irq";
+ interrupt-map-mask = <0x0 0xffffffff>;
+ interrupt-map = <0x0 0 &intc 0 133 0
+ 0x0 1 &spmi_bus 0x0 0x0 0x9 0x0>;
+ interrupt-names = "hs_phy_irq", "pmic_id_irq";
qcom,misc-ref = <&pm8941_misc>;
};
diff --git a/arch/arm/boot/dts/msm8974-v2.dtsi b/arch/arm/boot/dts/msm8974-v2.dtsi
index 16cdeb1..61f2c4f 100644
--- a/arch/arm/boot/dts/msm8974-v2.dtsi
+++ b/arch/arm/boot/dts/msm8974-v2.dtsi
@@ -64,6 +64,7 @@
0x00011900 0x00011D00 0x00012100>;
qcom,mdss-intf-off = <0x00012500 0x00012700
0x00012900 0x00012b00>;
+ qcom,mdss-pingpong-off = <0x00012D00 0x00012E00 0x00012F00>;
};
&msm_vidc {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 7557657..9a5a5d2 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -96,6 +96,7 @@
interrupts = <0 44 0>;
qcom,hfi = "venus";
qcom,has-ocmem;
+ qcom,max-hw-load = <1224450>; /* 4k @ 30 + 1080p @ 30*/
};
qcom,vidc {
@@ -143,16 +144,16 @@
reg = <0xf9a55000 0x400>;
interrupts = <0 134 0 0 140 0>;
interrupt-names = "core_irq", "async_irq";
- HSUSB_VDDCX-supply = <&pm8841_s2>;
+ HSUSB_VDDCX-supply = <&pm8841_s2_corner>;
HSUSB_1p8-supply = <&pm8941_l6>;
HSUSB_3p3-supply = <&pm8941_l24>;
+ qcom,vdd-voltage-level = <1 5 7>;
qcom,hsusb-otg-phy-type = <2>;
qcom,hsusb-otg-phy-init-seq = <0x63 0x81 0xffffffff>;
qcom,hsusb-otg-mode = <1>;
qcom,hsusb-otg-otg-control = <1>;
qcom,hsusb-otg-disable-reset;
- qcom,hsusb-otg-pnoc-errata-fix;
qcom,msm-bus,name = "usb2";
qcom,msm-bus,num-cases = <2>;
@@ -209,6 +210,7 @@
<78 512 2048000 4096000>; /* Max. bandwidth */
qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000 100000000 200000000 4294967295>;
qcom,dat1-mpm-int = <42>;
+ status = "disable";
};
sdcc2: qcom,sdcc@f98a4000 {
@@ -255,6 +257,7 @@
<81 512 2048000 4096000>; /* Max. bandwidth */
qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000 100000000 200000000 4294967295>;
qcom,dat1-mpm-int = <44>;
+ status = "disable";
};
sdcc3: qcom,sdcc@f9864000 {
@@ -590,6 +593,7 @@
qcom,cdc-mclk-clk-rate = <9600000>;
qcom,cdc-slim-ifd = "taiko-slim-ifd";
qcom,cdc-slim-ifd-elemental-addr = [00 00 A0 00 17 02];
+ qcom,cdc-dmic-sample-rate = <4800000>;
};
};
@@ -625,10 +629,14 @@
qcom,cdc-mclk-gpios = <&pm8941_gpios 15 0>;
taiko-mclk-clk = <&pm8941_clkdiv1>;
qcom,taiko-mclk-clk-freq = <9600000>;
- prim-auxpcm-gpio-clk = <&msmgpio 65 0>;
- prim-auxpcm-gpio-sync = <&msmgpio 66 0>;
- prim-auxpcm-gpio-din = <&msmgpio 67 0>;
- prim-auxpcm-gpio-dout = <&msmgpio 68 0>;
+ qcom,prim-auxpcm-gpio-clk = <&msmgpio 65 0>;
+ qcom,prim-auxpcm-gpio-sync = <&msmgpio 66 0>;
+ qcom,prim-auxpcm-gpio-din = <&msmgpio 67 0>;
+ qcom,prim-auxpcm-gpio-dout = <&msmgpio 68 0>;
+ qcom,sec-auxpcm-gpio-clk = <&msmgpio 79 0>;
+ qcom,sec-auxpcm-gpio-sync = <&msmgpio 80 0>;
+ qcom,sec-auxpcm-gpio-din = <&msmgpio 81 0>;
+ qcom,sec-auxpcm-gpio-dout = <&msmgpio 82 0>;
};
spmi_bus: qcom,spmi@fc4c0000 {
@@ -709,8 +717,11 @@
compatible = "qcom,dwc-usb3-msm";
reg = <0xf9200000 0xfc000>,
<0xfd4ab000 0x4>;
- interrupts = <0 131 0>, <0 179 0>, <0 133 0>;
- interrupt-names = "irq", "otg_irq", "hs_phy_irq";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ interrupts = <0 133 0>;
+ interrupt-names = "hs_phy_irq";
ssusb_vdd_dig-supply = <&pm8841_s2_corner>;
SSUSB_1p8-supply = <&pm8941_l6>;
hsusb_vdd_dig-supply = <&pm8841_s2_corner>;
@@ -728,6 +739,14 @@
qcom,msm-bus,vectors-KBps =
<61 512 0 0>,
<61 512 240000 960000>;
+ dwc3@f9200000 {
+ compatible = "synopsys,dwc3";
+ reg = <0xf9200000 0xfc000>;
+ interrupt-parent = <&intc>;
+ interrupts = <0 131 0>, <0 179 0>;
+ interrupt-names = "irq", "otg_irq";
+ tx-fifo-resize;
+ };
};
ehci: qcom,ehci-host@f9a55000 {
@@ -764,6 +783,10 @@
qcom,adsp-state = <0>;
};
+ qcom,msm-audio-ion {
+ compatible = "qcom,msm-audio-ion";
+ };
+
qcom,msm-pcm {
compatible = "qcom,msm-pcm-dsp";
qcom,msm-pcm-dsp-id = <0>;
@@ -940,15 +963,25 @@
qcom,msm-cpudai-auxpcm-data = <0>, <0>;
qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
- qcom,msm-auxpcm-rx {
+ qcom,msm-prim-auxpcm-rx {
qcom,msm-auxpcm-dev-id = <4106>;
compatible = "qcom,msm-auxpcm-dev";
};
- qcom,msm-auxpcm-tx {
+ qcom,msm-prim-auxpcm-tx {
qcom,msm-auxpcm-dev-id = <4107>;
compatible = "qcom,msm-auxpcm-dev";
};
+
+ qcom,msm-sec-auxpcm-rx {
+ qcom,msm-auxpcm-dev-id = <4108>;
+ compatible = "qcom,msm-auxpcm-dev";
+ };
+
+ qcom,msm-sec-auxpcm-tx {
+ qcom,msm-auxpcm-dev-id = <4109>;
+ compatible = "qcom,msm-auxpcm-dev";
+ };
};
qcom,msm-dai-mi2s {
@@ -1020,6 +1053,12 @@
vdd_pronto_pll-supply = <&pm8941_l12>;
qcom,firmware-name = "wcnss";
+
+ /* GPIO input from wcnss */
+ qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+
+ /* GPIO output to wcnss */
+ qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
};
qcom,iris-fm {
@@ -1097,6 +1136,9 @@
compatible = "qcom,qseecom";
reg = <0x7f00000 0x500000>;
reg-names = "secapp-region";
+ qcom,disk-encrypt-pipe-pair = <2>;
+ qcom,hlos-ce-hw-instance = <1>;
+ qcom,qsee-ce-hw-instance = <0>;
qcom,msm-bus,name = "qseecom-noc";
qcom,msm-bus,num-cases = <4>;
qcom,msm-bus,active-only = <0>;
@@ -1213,7 +1255,7 @@
interrupts = <0 132 0 0 135 0>;
interrupt-names = "ssusb", "hsusb";
qcom,usb-bam-num-pipes = <16>;
- qcom,usb-base-address = <0xf9200000>;
+ qcom,usb-bam-fifo-baseaddr = <0xf9200000>;
qcom,ignore-core-reset-ack;
qcom,disable-clk-gating;
@@ -1266,6 +1308,7 @@
compatible = "qcom,bam_dmux";
reg = <0xfc834000 0x7000>;
interrupts = <0 29 1>;
+ qcom,rx-ring-size = <64>;
};
qcom,msm-mem-hole {
diff --git a/arch/arm/boot/dts/msm9625-smp2p.dtsi b/arch/arm/boot/dts/msm9625-smp2p.dtsi
index 02c95e4..46af1b2 100644
--- a/arch/arm/boot/dts/msm9625-smp2p.dtsi
+++ b/arch/arm/boot/dts/msm9625-smp2p.dtsi
@@ -26,7 +26,6 @@
interrupts = <0 158 1>;
};
- /* SMP2P Test Driver for inbound entries */
smp2pgpio_smp2p_7_in: qcom,smp2pgpio-smp2p-7-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -43,7 +42,6 @@
gpios = <&smp2pgpio_smp2p_7_in 0 0>;
};
- /* SMP2P Test Driver for outbound entries */
smp2pgpio_smp2p_7_out: qcom,smp2pgpio-smp2p-7-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -59,7 +57,6 @@
gpios = <&smp2pgpio_smp2p_7_out 0 0>;
};
- /* SMP2P Test Driver for modem inbound */
smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -76,7 +73,6 @@
gpios = <&smp2pgpio_smp2p_1_in 0 0>;
};
- /* SMP2P Test Driver for modem output */
smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -92,7 +88,6 @@
gpios = <&smp2pgpio_smp2p_1_out 0 0>;
};
- /* SMP2P SSR Driver for inbound entry from modem. */
smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "slave-kernel";
@@ -104,7 +99,6 @@
#interrupt-cells = <2>;
};
- /* SMP2P SSR Driver for outbound entry to modem */
smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "master-kernel";
@@ -115,7 +109,6 @@
#interrupt-cells = <2>;
};
- /* SMP2P Test Driver for adsp inbound */
smp2pgpio_smp2p_2_in: qcom,smp2pgpio-smp2p-2-in {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
@@ -132,7 +125,6 @@
gpios = <&smp2pgpio_smp2p_2_in 0 0>;
};
- /* SMP2P Test Driver for adsp output */
smp2pgpio_smp2p_2_out: qcom,smp2pgpio-smp2p-2-out {
compatible = "qcom,smp2pgpio";
qcom,entry-name = "smp2p";
diff --git a/arch/arm/boot/dts/msm9625-v1-cdp.dts b/arch/arm/boot/dts/msm9625-v1-cdp.dts
index cc7a758..cf17c69 100644
--- a/arch/arm/boot/dts/msm9625-v1-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-v1-cdp.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 9625V1 CDP";
- compatible = "qcom,msm9625-cdp", "qcom,msm9625";
+ compatible = "qcom,msm9625-cdp", "qcom,msm9625", "qcom,cdp";
qcom,msm-id = <134 1 0>, <152 1 0>, <149 1 0>, <150 1 0>,
<151 1 0>, <148 1 0>, <173 1 0>, <174 1 0>,
<175 1 0>;
diff --git a/arch/arm/boot/dts/msm9625-v1-mtp.dts b/arch/arm/boot/dts/msm9625-v1-mtp.dts
index d78bb77..24aa3af 100644
--- a/arch/arm/boot/dts/msm9625-v1-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v1-mtp.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 9625V1 MTP";
- compatible = "qcom,msm9625-mtp", "qcom,msm9625";
+ compatible = "qcom,msm9625-mtp", "qcom,msm9625", "qcom,mtp";
qcom,msm-id = <134 7 0>, <152 7 0>, <149 7 0>, <150 7 0>,
<151 7 0>, <148 7 0>, <173 7 0>, <174 7 0>,
<175 7 0>;
@@ -97,11 +97,23 @@
};
mpp@a300 { /* MPP 4 */
+ /* VADC channel 19 */
+ qcom,mode = <4>;
+ qcom,ain-route = <3>; /* AMUX 8 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ qcom,invert = <1>;
};
mpp@a400 { /* MPP 5 */
};
mpp@a500 { /* MPP 6 */
+ /* VADC channel 21 */
+ qcom,mode = <4>;
+ qcom,ain-route = <1>; /* AMUX 6 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ qcom,invert = <1>;
};
};
diff --git a/arch/arm/boot/dts/msm9625-v1-rumi.dts b/arch/arm/boot/dts/msm9625-v1-rumi.dts
index a854947..ef00681 100644
--- a/arch/arm/boot/dts/msm9625-v1-rumi.dts
+++ b/arch/arm/boot/dts/msm9625-v1-rumi.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 9625V1 RUMI";
- compatible = "qcom,msm9625-rumi", "qcom,msm9625";
+ compatible = "qcom,msm9625-rumi", "qcom,msm9625", "qcom,rumi";
qcom,msm-id = <134 15 0>;
chosen{
diff --git a/arch/arm/boot/dts/msm9625-v1.dtsi b/arch/arm/boot/dts/msm9625-v1.dtsi
index 54aa02a..ad95601 100644
--- a/arch/arm/boot/dts/msm9625-v1.dtsi
+++ b/arch/arm/boot/dts/msm9625-v1.dtsi
@@ -57,3 +57,7 @@
&ldrex_spinlock {
status = "ok";
};
+
+&hsic_host {
+ qcom,phy-sof-workaround;
+};
diff --git a/arch/arm/boot/dts/msm9625-v2-1-cdp.dts b/arch/arm/boot/dts/msm9625-v2-1-cdp.dts
index 8702184..da07100 100644
--- a/arch/arm/boot/dts/msm9625-v2-1-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-1-cdp.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 9625V2.1 CDP";
- compatible = "qcom,msm9625-cdp", "qcom,msm9625";
+ compatible = "qcom,msm9625-cdp", "qcom,msm9625", "qcom,cdp";
qcom,msm-id = <134 1 0x20001>, <152 1 0x20001>, <149 1 0x20001>,
<150 1 0x20001>, <151 1 0x20001>, <148 1 0x20001>,
<173 1 0x20001>, <174 1 0x20001>, <175 1 0x20001>;
diff --git a/arch/arm/boot/dts/msm9625-v2-1-mtp.dts b/arch/arm/boot/dts/msm9625-v2-1-mtp.dts
index 2dc040c..1e0f3c0 100644
--- a/arch/arm/boot/dts/msm9625-v2-1-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-1-mtp.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 9625V2.1 MTP";
- compatible = "qcom,msm9625-mtp", "qcom,msm9625";
+ compatible = "qcom,msm9625-mtp", "qcom,msm9625", "qcom,mtp";
qcom,msm-id = <134 7 0x20001>, <152 7 0x20001>, <149 7 0x20001>,
<150 7 0x20001>, <151 7 0x20001>, <148 7 0x20001>,
<173 7 0x20001>, <174 7 0x20001>, <175 7 0x20001>;
diff --git a/arch/arm/boot/dts/msm9625-v2-cdp.dts b/arch/arm/boot/dts/msm9625-v2-cdp.dts
index 94fe019..660bdbd 100644
--- a/arch/arm/boot/dts/msm9625-v2-cdp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-cdp.dts
@@ -18,7 +18,7 @@
/ {
model = "Qualcomm MSM 9625V2 CDP";
- compatible = "qcom,msm9625-cdp", "qcom,msm9625";
+ compatible = "qcom,msm9625-cdp", "qcom,msm9625", "qcom,cdp";
qcom,msm-id = <134 1 0x20000>, <152 1 0x20000>, <149 1 0x20000>,
<150 1 0x20000>, <151 1 0x20000>, <148 1 0x20000>,
<173 1 0x20000>, <174 1 0x20000>, <175 1 0x20000>;
diff --git a/arch/arm/boot/dts/msm9625-v2-mtp.dts b/arch/arm/boot/dts/msm9625-v2-mtp.dts
index 2840024..c9e54be 100644
--- a/arch/arm/boot/dts/msm9625-v2-mtp.dts
+++ b/arch/arm/boot/dts/msm9625-v2-mtp.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM 9625V2 MTP";
- compatible = "qcom,msm9625-mtp", "qcom,msm9625";
+ compatible = "qcom,msm9625-mtp", "qcom,msm9625", "qcom,mtp";
qcom,msm-id = <134 7 0x20000>, <152 7 0x20000>, <149 7 0x20000>,
<150 7 0x20000>, <151 7 0x20000>, <148 7 0x20000>,
<173 7 0x20000>, <174 7 0x20000>, <175 7 0x20000>;
@@ -97,11 +97,23 @@
};
mpp@a300 { /* MPP 4 */
+ /* VADC channel 19 */
+ qcom,mode = <4>;
+ qcom,ain-route = <3>; /* AMUX 8 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ qcom,invert = <1>;
};
mpp@a400 { /* MPP 5 */
};
mpp@a500 { /* MPP 6 */
+ /* channel 21 */
+ qcom,mode = <4>;
+ qcom,ain-route = <1>; /* AMUX 6 */
+ qcom,master-en = <1>;
+ qcom,src-sel = <0>; /* Function constant */
+ qcom,invert = <1>;
};
};
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 3dbc95d..fe81fa9 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -108,7 +108,7 @@
<87 512 40000 640000>;
};
- hsic@f9a15000 {
+ hsic_host: hsic@f9a15000 {
compatible = "qcom,hsic-host";
reg = <0xf9a15000 0x400>;
interrupts = <0 136 0>, <0 148 0>;
@@ -825,7 +825,7 @@
};
chan@33 {
- label = "pa_therm1";
+ label = "pa_therm0";
reg = <0x33>;
qcom,decimation = <0>;
qcom,pre-div-channel-scaling = <0>;
@@ -836,7 +836,7 @@
};
chan@34 {
- label = "pa_therm2";
+ label = "pa_therm1";
reg = <0x34>;
qcom,decimation = <0>;
qcom,pre-div-channel-scaling = <0>;
@@ -867,4 +867,26 @@
qcom,hw-settle-time = <2>;
qcom,fast-avg-setup = <0>;
};
+
+ chan@13 {
+ label = "case_therm";
+ reg = <0x13>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
+
+ chan@15 {
+ label = "ambient_therm";
+ reg = <0x15>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <0>;
+ qcom,calibration-type = "ratiometric";
+ qcom,scale-function = <2>;
+ qcom,hw-settle-time = <2>;
+ qcom,fast-avg-setup = <0>;
+ };
};
diff --git a/arch/arm/boot/dts/msmzinc-ion.dtsi b/arch/arm/boot/dts/msmzinc-ion.dtsi
index 4bf078a..aac4230 100644
--- a/arch/arm/boot/dts/msmzinc-ion.dtsi
+++ b/arch/arm/boot/dts/msmzinc-ion.dtsi
@@ -20,6 +20,10 @@
reg = <30>;
};
+ qcom,ion-heap@21 { /* SYSTEM CONTIG HEAP */
+ reg = <21>;
+ };
+
qcom,ion-heap@25 { /* IOMMU HEAP */
reg = <25>;
};
diff --git a/arch/arm/boot/dts/msmzinc-sim.dts b/arch/arm/boot/dts/msmzinc-sim.dts
index 48d7ef1..e410344 100644
--- a/arch/arm/boot/dts/msmzinc-sim.dts
+++ b/arch/arm/boot/dts/msmzinc-sim.dts
@@ -16,7 +16,7 @@
/ {
model = "Qualcomm MSM ZINC Simulator";
- compatible = "qcom,msmzinc-sim", "qcom,msmzinc";
+ compatible = "qcom,msmzinc-sim", "qcom,msmzinc", "qcom,sim";
qcom,msm-id = <178 0 0>;
aliases {
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index c0a945e..8a974c4 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -57,7 +57,9 @@
CONFIG_MSM_TZ_LOG=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_MSM_WATCHDOG_V2=y
+CONFIG_MSM_MEMORY_DUMP=y
CONFIG_MSM_DLOAD_MODE=y
+CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
CONFIG_MSM_ADSP_LOADER=m
CONFIG_MSM_OCMEM=y
CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
@@ -203,7 +205,6 @@
CONFIG_DM_CRYPT=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
-CONFIG_KS8851=y
# CONFIG_MSM_RMNET is not set
CONFIG_MSM_RMNET_BAM=y
CONFIG_WCNSS_CORE=y
@@ -215,6 +216,7 @@
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI4_DEV=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=m
@@ -315,6 +317,7 @@
CONFIG_ANDROID_TIMED_GPIO=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
CONFIG_SPS=y
+CONFIG_USB_BAM=y
CONFIG_SPS_SUPPORT_NDP_BAM=y
CONFIG_QPNP_PWM=y
CONFIG_QPNP_POWER_ON=y
@@ -343,8 +346,20 @@
CONFIG_MAGIC_SYSRQ=y
CONFIG_SCHEDSTATS=y
CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_KMEMLEAK=y
+CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
+CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_DEBUG_LIST=y
+CONFIG_FAULT_INJECTION=y
+CONFIG_FAIL_PAGE_ALLOC=y
+CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
+CONFIG_DEBUG_PAGEALLOC=y
CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
@@ -354,3 +369,4 @@
CONFIG_CRYPTO_TWOFISH=y
# CONFIG_CRYPTO_HW is not set
CONFIG_CRC_CCITT=y
+CONFIG_QPNP_VIBRATOR=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index c33a236..f76f810 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -330,6 +330,7 @@
CONFIG_MSM_CSI30_HEADER=y
CONFIG_MSM_CSIPHY=y
CONFIG_MSM_CSID=y
+CONFIG_MSM_EEPROM=y
CONFIG_MSM_ISPIF=y
CONFIG_S5K3L1YX=y
CONFIG_MSMB_CAMERA=y
@@ -387,6 +388,7 @@
CONFIG_USB_EHSET_TEST_FIXTURE=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_CI13XXX_MSM=y
CONFIG_USB_DWC3_MSM=y
CONFIG_USB_G_ANDROID=y
CONFIG_MMC=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 1cda524..6112134 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -242,6 +242,7 @@
CONFIG_CMA=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
+CONFIG_UID_STAT=y
CONFIG_TSPP=m
CONFIG_HAPTIC_ISA1200=y
CONFIG_QSEECOM=y
@@ -336,6 +337,7 @@
CONFIG_MSM_CSI30_HEADER=y
CONFIG_MSM_CSIPHY=y
CONFIG_MSM_CSID=y
+CONFIG_MSM_EEPROM=y
CONFIG_MSM_ISPIF=y
CONFIG_S5K3L1YX=y
CONFIG_MSMB_CAMERA=y
@@ -395,6 +397,7 @@
CONFIG_USB_EHSET_TEST_FIXTURE=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_CI13XXX_MSM=y
CONFIG_USB_DWC3_MSM=y
CONFIG_USB_G_ANDROID=y
CONFIG_MMC=y
diff --git a/arch/arm/configs/msm9625-perf_defconfig b/arch/arm/configs/msm9625-perf_defconfig
index 8d6bc81..42acd99 100644
--- a/arch/arm/configs/msm9625-perf_defconfig
+++ b/arch/arm/configs/msm9625-perf_defconfig
@@ -53,6 +53,7 @@
CONFIG_MSM_WATCHDOG_V2=y
CONFIG_MSM_MEMORY_DUMP=y
CONFIG_MSM_DLOAD_MODE=y
+CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
CONFIG_MSM_ADSP_LOADER=m
CONFIG_MSM_RTB=y
CONFIG_MSM_UARTDM_Core_v14=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 9e9bba9..041e89a 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -53,6 +53,7 @@
CONFIG_MSM_WATCHDOG_V2=y
CONFIG_MSM_MEMORY_DUMP=y
CONFIG_MSM_DLOAD_MODE=y
+CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
CONFIG_MSM_ADSP_LOADER=m
CONFIG_MSM_RTB=y
CONFIG_MSM_UARTDM_Core_v14=y
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index 2b3667f..366debb 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -381,6 +381,8 @@
.stop = arch_timer_stop,
};
+static struct clock_event_device arch_timer_global_evt;
+
static int __init arch_timer_common_register(void)
{
int err;
@@ -431,9 +433,19 @@
}
err = local_timer_register(&arch_timer_ops);
+ if (err) {
+ /*
+ * We couldn't register as a local timer (could be
+ * because we're on a UP platform, or because some
+ * other local timer is already present...). Try as a
+ * global timer instead.
+ */
+ arch_timer_global_evt.cpumask = cpumask_of(0);
+ err = arch_timer_setup(&arch_timer_global_evt);
+ }
+
if (err)
goto out_free_irq;
- percpu_timer_setup();
/* Use the architected timer for the delay loop. */
arch_delay_timer.read_current_timer = &arch_timer_read_current_timer;
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index cef66ec..c440f47 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -742,6 +742,7 @@
static struct of_device_id armpmu_of_device_ids[] = {
{.compatible = "arm,cortex-a9-pmu"},
{.compatible = "arm,cortex-a8-pmu"},
+ {.compatible = "arm,cortex-a5-pmu"},
{.compatible = "arm,arm1136-pmu"},
{.compatible = "arm,arm1176-pmu"},
{.compatible = "qcom,krait-pmu"},
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index ac51e25..601fcfa 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -368,10 +368,8 @@
select ARM_GIC
select MIGHT_HAVE_CACHE_L2X0
select ARCH_MSM_CORTEX_A5
- select SMP
- select MSM_SMP
select CPU_V7
- select MSM_SCM if SMP
+ select MSM_SCM
select MSM_GPIOMUX
select MSM_RPM_SMD
select MSM_NATIVE_RESTART
@@ -428,6 +426,10 @@
select REGULATOR
select MSM_RPM_REGULATOR_SMD
select MSM_SPM_REGULATOR
+ select MSM_JTAG_MM if CORESIGHT_ETM
+ select MSM_CPR_REGULATOR
+ select MSM_RPM_LOG
+ select MSM_RPM_STATS_LOG
config ARCH_MSM8226
bool "MSM8226"
@@ -466,6 +468,8 @@
select MSM_SPM_REGULATOR
select MSM_JTAG_MM if CORESIGHT_ETM
select MSM_CPR_REGULATOR
+ select MSM_RPM_LOG
+ select MSM_RPM_STATS_LOG
endmenu
choice
@@ -1079,7 +1083,7 @@
config KERNEL_MSM_CONTIG_MEM_REGION
bool "Enable in-kernel contiguous memory region"
default y if ARCH_MSM8X60
- depends on ANDROID_PMEM && (ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_MSM8974)
+ depends on ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_MSM8974
help
Enable the in-kernel contiguous memory allocator. Sets up a
region of physically contiguous memory. This memory is
@@ -2642,8 +2646,6 @@
config SENSORS_ADSP
bool "Enable Sensors Driver Support for ADSP"
- depends on (ARCH_MSM8226 || ARCH_MSM8974)
- default y
help
Add support for sensors ADSP driver.
This driver is used for exercising different sensors use cases,
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index d07b094..1c14ac6 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -5,7 +5,7 @@
obj-y += timer.o
endif
obj-y += clock.o clock-voter.o clock-dummy.o
-obj-y += modem_notifier.o subsystem_map.o
+obj-y += modem_notifier.o
obj-$(CONFIG_USE_OF) += board-dt.o
obj-$(CONFIG_CPU_FREQ_MSM) += cpufreq.o
obj-$(CONFIG_DEBUG_FS) += nohlt.o clock-debug.o
@@ -24,6 +24,7 @@
endif
obj-y += acpuclock.o
+obj-$(CONFIG_HW_PERF_EVENTS) += perf_trace_counters.o
obj-$(CONFIG_ARCH_MSM_KRAIT) += acpuclock-krait.o
ifdef CONFIG_ARCH_MSM_KRAIT
obj-$(CONFIG_DEBUG_FS) += acpuclock-krait-debug.o
diff --git a/arch/arm/mach-msm/acpuclock-8226.c b/arch/arm/mach-msm/acpuclock-8226.c
index 73ea435..799d629 100644
--- a/arch/arm/mach-msm/acpuclock-8226.c
+++ b/arch/arm/mach-msm/acpuclock-8226.c
@@ -17,8 +17,10 @@
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/io.h>
+#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
+#include <linux/regulator/cpr-regulator.h>
#include <mach/clk-provider.h>
#include <mach/msm_bus.h>
@@ -53,13 +55,13 @@
* 3) Depending on Frodo version, may need minimum of LVL_NOM
*/
static struct clkctl_acpu_speed acpu_freq_tbl[] = {
- { 0, 19200, CXO, 0, 0, 1150000, 1150000, 0 },
- { 1, 300000, PLL0, 4, 2, 1150000, 1150000, 4 },
- { 1, 384000, ACPUPLL, 5, 0, 1150000, 1150000, 4 },
- { 1, 600000, PLL0, 4, 0, 1150000, 1150000, 6 },
- { 1, 787200, ACPUPLL, 5, 0, 1150000, 1150000, 7 },
- { 0, 998400, ACPUPLL, 5, 0, 1150000, 1150000, 7 },
- { 0, 1190400, ACPUPLL, 5, 0, 1150000, 1150000, 7 },
+ { 0, 19200, CXO, 0, 0, CPR_CORNER_SVS, 1150000, 0 },
+ { 1, 300000, PLL0, 4, 2, CPR_CORNER_SVS, 1150000, 4 },
+ { 1, 384000, ACPUPLL, 5, 0, CPR_CORNER_SVS, 1150000, 4 },
+ { 1, 600000, PLL0, 4, 0, CPR_CORNER_NORMAL, 1150000, 6 },
+ { 1, 787200, ACPUPLL, 5, 0, CPR_CORNER_NORMAL, 1150000, 7 },
+ { 0, 998400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 1150000, 7 },
+ { 0, 1190400, ACPUPLL, 5, 0, CPR_CORNER_TURBO, 1150000, 7 },
{ 0 }
};
@@ -67,8 +69,7 @@
.freq_tbl = acpu_freq_tbl,
.current_speed = &(struct clkctl_acpu_speed){ 0 },
.bus_scale = &bus_client_pdata,
- /* FIXME regulator doesn't support corners yet */
- .vdd_max_cpu = 1150000,
+ .vdd_max_cpu = CPR_CORNER_TURBO,
.vdd_max_mem = 1150000,
.src_clocks = {
[PLL0].name = "gpll0",
@@ -82,17 +83,21 @@
.update_mask = RCG_CONFIG_UPDATE_BIT,
.poll_mask = RCG_CONFIG_UPDATE_BIT,
},
+ .power_collapse_khz = 300000,
+ .wait_for_irq_khz = 300000,
};
static int __init acpuclk_a7_probe(struct platform_device *pdev)
{
struct resource *res;
+ u32 i;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rcg_base");
if (!res)
return -EINVAL;
- drv_data.apcs_rcg_cmd = ioremap(res->start, resource_size(res));
+ drv_data.apcs_rcg_cmd = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
if (!drv_data.apcs_rcg_cmd)
return -ENOMEM;
@@ -110,6 +115,21 @@
return PTR_ERR(drv_data.vdd_mem);
}
+ for (i = 0; i < NUM_SRC; i++) {
+ if (!drv_data.src_clocks[i].name)
+ continue;
+ drv_data.src_clocks[i].clk =
+ devm_clk_get(&pdev->dev, drv_data.src_clocks[i].name);
+ if (IS_ERR(drv_data.src_clocks[i].clk)) {
+ dev_err(&pdev->dev, "Unable to get clock %s\n",
+ drv_data.src_clocks[i].name);
+ return -EPROBE_DEFER;
+ }
+ }
+
+ /* Enable the always on source */
+ clk_prepare_enable(drv_data.src_clocks[PLL0].clk);
+
return acpuclk_cortex_init(pdev, &drv_data);
}
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 83c14a8..b673f93 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -259,242 +259,452 @@
static struct l2_level l2_freq_tbl_v2[] __initdata = {
[0] = { { 300000, PLL_0, 0, 0 }, LVL_LOW, 950000, 0 },
- [1] = { { 345600, HFPLL, 2, 36 }, LVL_NOM, 950000, 1 },
- [2] = { { 422400, HFPLL, 2, 44 }, LVL_NOM, 950000, 1 },
- [3] = { { 499200, HFPLL, 2, 52 }, LVL_NOM, 950000, 2 },
- [4] = { { 576000, HFPLL, 1, 30 }, LVL_NOM, 950000, 3 },
- [5] = { { 652800, HFPLL, 1, 34 }, LVL_NOM, 950000, 3 },
- [6] = { { 729600, HFPLL, 1, 38 }, LVL_NOM, 950000, 3 },
- [7] = { { 806400, HFPLL, 1, 42 }, LVL_HIGH, 1050000, 4 },
- [8] = { { 883200, HFPLL, 1, 46 }, LVL_HIGH, 1050000, 4 },
- [9] = { { 960000, HFPLL, 1, 50 }, LVL_HIGH, 1050000, 4 },
- [10] = { { 1036800, HFPLL, 1, 54 }, LVL_HIGH, 1050000, 5 },
- [11] = { { 1113600, HFPLL, 1, 58 }, LVL_HIGH, 1050000, 5 },
+ [1] = { { 345600, HFPLL, 2, 36 }, LVL_LOW, 950000, 1 },
+ [2] = { { 422400, HFPLL, 2, 44 }, LVL_LOW, 950000, 2 },
+ [3] = { { 499200, HFPLL, 2, 52 }, LVL_LOW, 950000, 3 },
+ [4] = { { 576000, HFPLL, 1, 30 }, LVL_LOW, 950000, 4 },
+ [5] = { { 652800, HFPLL, 1, 34 }, LVL_NOM, 950000, 4 },
+ [6] = { { 729600, HFPLL, 1, 38 }, LVL_NOM, 950000, 4 },
+ [7] = { { 806400, HFPLL, 1, 42 }, LVL_NOM, 950000, 4 },
+ [8] = { { 883200, HFPLL, 1, 46 }, LVL_NOM, 950000, 5 },
+ [9] = { { 960000, HFPLL, 1, 50 }, LVL_NOM, 950000, 5 },
+ [10] = { { 1036800, HFPLL, 1, 54 }, LVL_NOM, 950000, 6 },
+ [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, 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 },
- [17] = { { 1574400, HFPLL, 1, 82 }, LVL_HIGH, 1050000, 8 },
- [18] = { { 1651200, HFPLL, 1, 86 }, LVL_HIGH, 1050000, 8 },
+ [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 },
{ }
};
static struct acpu_level acpu_freq_tbl_2g_pvs0[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 815000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 825000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 835000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 845000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 855000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 865000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 875000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 890000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 900000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 915000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 815000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 825000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 835000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 845000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 855000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 865000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 875000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 890000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 900000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 915000, 3200000 },
{ 1, { 1036800, HFPLL, 1, 54 }, L2(10), 925000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 940000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 950000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 965000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 980000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 995000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 1010000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 1025000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 1040000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1055000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 1070000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 1085000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 940000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 950000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 965000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 980000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 995000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 1010000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 1025000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 1040000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 1055000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1070000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1085000, 3200000 },
{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1100000, 3200000 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2g_pvs1[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 810000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 820000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 830000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 840000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 850000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 860000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 875000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 885000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 895000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 810000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 820000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 830000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 840000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 850000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 860000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 875000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 885000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 895000, 3200000 },
{ 1, { 1036800, HFPLL, 1, 54 }, L2(10), 910000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 920000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 930000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 945000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 960000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 975000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 990000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 1005000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 1020000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1030000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 1045000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 1060000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 920000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 930000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 945000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 960000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 975000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 990000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 1005000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 1020000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 1030000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1045000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1060000, 3200000 },
{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1075000, 3200000 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2g_pvs2[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 785000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 795000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 805000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 815000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 825000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 835000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 845000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 855000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 865000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 875000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 785000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 795000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 805000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 815000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 825000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 835000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 845000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 855000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 865000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 875000, 3200000 },
{ 1, { 1036800, HFPLL, 1, 54 }, L2(10), 890000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 900000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 910000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 925000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 940000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 955000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 970000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 980000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 995000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 1005000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 1020000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 1035000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 900000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 910000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 925000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 940000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 955000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 970000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 980000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 995000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 1005000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1020000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1035000, 3200000 },
{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1050000, 3200000 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2g_pvs3[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 780000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 790000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 800000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 810000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 820000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 830000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 840000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 850000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 860000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 780000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 790000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 810000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 820000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 830000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 840000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 850000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 860000, 3200000 },
{ 1, { 1036800, HFPLL, 1, 54 }, L2(10), 875000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 885000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 895000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 910000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 925000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 935000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 950000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 960000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 970000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 985000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 995000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 1010000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 885000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 895000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 910000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 925000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 935000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 950000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 960000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 970000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 985000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 995000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1010000, 3200000 },
{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1025000, 3200000 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2g_pvs4[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 775000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 780000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 790000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 800000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 810000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 820000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 830000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 840000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 850000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 780000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 790000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 810000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 820000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 830000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 840000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 850000, 3200000 },
{ 1, { 1036800, HFPLL, 1, 54 }, L2(10), 860000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 870000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 880000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 895000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 910000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 920000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 930000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 940000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 950000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 960000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 975000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 985000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 870000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 880000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 895000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 910000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 920000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 930000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 940000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 950000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 960000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 975000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 985000, 3200000 },
{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1000000, 3200000 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2g_pvs5[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 760000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 770000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 780000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 790000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 800000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 810000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 820000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 830000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 840000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 760000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 770000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 780000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 790000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 800000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 810000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 820000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 830000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 840000, 3200000 },
{ 1, { 1036800, HFPLL, 1, 54 }, L2(10), 850000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 860000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 870000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 880000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 890000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 900000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 920000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 930000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 940000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 955000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 965000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 860000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 870000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 880000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 890000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 900000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 920000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 930000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 940000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 955000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 965000, 3200000 },
{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 975000, 3200000 },
{ 0, { 0 } }
};
static struct acpu_level acpu_freq_tbl_2g_pvs6[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 750000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 760000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 770000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 780000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 790000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 800000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 810000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 820000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 830000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 760000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 770000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 780000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 790000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 800000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 810000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 820000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 830000, 3200000 },
{ 1, { 1036800, HFPLL, 1, 54 }, L2(10), 840000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 850000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 860000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 870000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 875000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 885000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 895000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 905000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 915000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 920000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 930000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 940000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 850000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 860000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 870000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 875000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 885000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 895000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 905000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 915000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 920000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 930000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 940000, 3200000 },
{ 1, { 1958400, HFPLL, 1, 102 }, L2(19), 950000, 3200000 },
{ 0, { 0 } }
};
-static struct acpu_level acpu_freq_tbl_2p3g_pvs0[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 800000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 800000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 805000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 815000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 825000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 835000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 845000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 855000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 865000, 3200000 },
+static struct acpu_level acpu_freq_tbl_2p2g_pvs0[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 805000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 815000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 825000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 835000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 845000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 855000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 865000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 875000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 890000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 900000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 915000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 925000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 940000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 950000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 965000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 980000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 995000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 1010000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1025000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1040000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1055000, 3200000 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1070000, 3200000 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1085000, 3200000 },
+ { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1100000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p2g_pvs1[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 810000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 820000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 830000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 840000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 850000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 860000, 3200000 },
{ 1, { 1036800, HFPLL, 1, 54 }, L2(10), 875000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 890000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 900000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 915000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 925000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 940000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 950000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 965000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 980000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 995000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 1010000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 1025000, 3200000 },
- { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 1040000, 3200000 },
- { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 1055000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 885000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 895000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 910000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 920000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 930000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 945000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 960000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 975000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 990000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1005000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1020000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1030000, 3200000 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1045000, 3200000 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1060000, 3200000 },
+ { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1075000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p2g_pvs2[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 785000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 795000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 805000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 815000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 825000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 835000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 845000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 855000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 865000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 875000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 890000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 900000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 910000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 925000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 940000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 955000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 970000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 980000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 995000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1005000, 3200000 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1020000, 3200000 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1035000, 3200000 },
+ { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1050000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p2g_pvs3[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 780000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 790000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 800000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 810000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 820000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 830000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 840000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 850000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 860000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 875000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 885000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 895000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 925000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 935000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 950000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 960000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 970000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 985000, 3200000 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 995000, 3200000 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1010000, 3200000 },
+ { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1025000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p2g_pvs4[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 780000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 790000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 800000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 810000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 820000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 830000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 840000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 850000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 860000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 870000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 880000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 895000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 910000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 920000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 930000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 940000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 950000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 960000, 3200000 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 975000, 3200000 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 985000, 3200000 },
+ { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 1000000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p2g_pvs5[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 760000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 770000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 780000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 790000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 810000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 820000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 830000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 840000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 850000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 860000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 870000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 880000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 890000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 900000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 910000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 920000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 930000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 940000, 3200000 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 955000, 3200000 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 965000, 3200000 },
+ { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 975000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p2g_pvs6[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 75000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 75000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 75000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 75000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 75000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 76000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 77000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 78000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 79000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 80000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 81000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 82000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 83000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 84000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 85000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 86000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 87000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 87500, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 88500, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 89500, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 90500, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 91500, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 92000, 3200000 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 93000, 3200000 },
+ { 0, { 2112000, HFPLL, 1, 110 }, L2(19), 94000, 3200000 },
+ { 1, { 2150400, HFPLL, 1, 112 }, L2(19), 95000, 3200000 },
+ { 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_2p3g_pvs0[] __initdata = {
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 805000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 815000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 825000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 835000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 845000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 855000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 865000, 3200000 },
+ { 1, { 1036800, HFPLL, 1, 54 }, L2(10), 875000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 890000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 900000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 915000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 925000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 940000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 950000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 965000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 980000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 995000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 1010000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1025000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1040000, 3200000 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1055000, 3200000 },
{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1070000, 3200000 },
{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1085000, 3200000 },
{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1100000, 3200000 },
@@ -502,30 +712,30 @@
};
static struct acpu_level acpu_freq_tbl_2p3g_pvs1[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 800000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 800000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 800000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 800000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 810000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 820000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 830000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 840000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 850000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 800000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 800000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 800000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 800000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 800000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 810000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 820000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 830000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 840000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 850000, 3200000 },
{ 1, { 1036800, HFPLL, 1, 54 }, L2(10), 860000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 875000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 885000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 895000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 910000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 920000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 930000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 945000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 960000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 975000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 990000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 1005000, 3200000 },
- { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 3200000 },
- { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 875000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 885000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 895000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 910000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 920000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 930000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 945000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 960000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 975000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 990000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 1005000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 1020000, 3200000 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1030000, 3200000 },
{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1045000, 3200000 },
{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1060000, 3200000 },
{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1075000, 3200000 },
@@ -533,30 +743,30 @@
};
static struct acpu_level acpu_freq_tbl_2p3g_pvs2[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 775000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 775000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 775000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 785000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 795000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 805000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 815000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 825000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 835000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 785000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 795000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 805000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 815000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 825000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 835000, 3200000 },
{ 1, { 1036800, HFPLL, 1, 54 }, L2(10), 845000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 855000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 865000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 875000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 890000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 900000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 925000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 940000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 955000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 970000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 980000, 3200000 },
- { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 995000, 3200000 },
- { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 855000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 865000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 875000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 890000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 900000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 910000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 925000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 940000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 955000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 970000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 980000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 995000, 3200000 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 1005000, 3200000 },
{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 1020000, 3200000 },
{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1035000, 3200000 },
{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1050000, 3200000 },
@@ -564,30 +774,30 @@
};
static struct acpu_level acpu_freq_tbl_2p3g_pvs3[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 775000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 775000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 775000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 775000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 780000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 790000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 800000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 810000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 820000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 780000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 790000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 800000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 810000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 820000, 3200000 },
{ 1, { 1036800, HFPLL, 1, 54 }, L2(10), 830000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 840000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 850000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 860000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 875000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 885000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 895000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 910000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 925000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 935000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 950000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 960000, 3200000 },
- { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 970000, 3200000 },
- { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 985000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 840000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 850000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 860000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 875000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 885000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 895000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 910000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 925000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 935000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 950000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 960000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 970000, 3200000 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 985000, 3200000 },
{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 995000, 3200000 },
{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 1010000, 3200000 },
{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1025000, 3200000 },
@@ -595,30 +805,30 @@
};
static struct acpu_level acpu_freq_tbl_2p3g_pvs4[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 775000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 775000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 775000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 775000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 775000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 780000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 790000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 800000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 810000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 775000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 775000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 775000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 775000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 775000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 775000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 780000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 790000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 800000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 810000, 3200000 },
{ 1, { 1036800, HFPLL, 1, 54 }, L2(10), 820000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 830000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 840000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 850000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 860000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 870000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 880000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 895000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 910000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 920000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 930000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 940000, 3200000 },
- { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 950000, 3200000 },
- { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 960000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 830000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 840000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 850000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 860000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 870000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 880000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 895000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 910000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 920000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 930000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 940000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 950000, 3200000 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 960000, 3200000 },
{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 975000, 3200000 },
{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 985000, 3200000 },
{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 1000000, 3200000 },
@@ -626,30 +836,30 @@
};
static struct acpu_level acpu_freq_tbl_2p3g_pvs5[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 750000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 750000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 750000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 750000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 760000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 770000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 780000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 790000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 800000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 760000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 770000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 780000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 790000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 800000, 3200000 },
{ 1, { 1036800, HFPLL, 1, 54 }, L2(10), 810000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 820000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 830000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 840000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 850000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 860000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 880000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 890000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 900000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 910000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 920000, 3200000 },
- { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 930000, 3200000 },
- { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 940000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 820000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 830000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 840000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 850000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 860000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 870000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 880000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 890000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 900000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 910000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 920000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 930000, 3200000 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 940000, 3200000 },
{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 955000, 3200000 },
{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 965000, 3200000 },
{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 975000, 3200000 },
@@ -657,30 +867,30 @@
};
static struct acpu_level acpu_freq_tbl_2p3g_pvs6[] __initdata = {
- { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
- { 0, { 345600, HFPLL, 2, 36 }, L2(3), 750000, 3200000 },
- { 1, { 422400, HFPLL, 2, 44 }, L2(3), 750000, 3200000 },
- { 0, { 499200, HFPLL, 2, 52 }, L2(6), 750000, 3200000 },
- { 1, { 576000, HFPLL, 1, 30 }, L2(6), 750000, 3200000 },
- { 1, { 652800, HFPLL, 1, 34 }, L2(7), 750000, 3200000 },
- { 1, { 729600, HFPLL, 1, 38 }, L2(7), 760000, 3200000 },
- { 0, { 806400, HFPLL, 1, 42 }, L2(10), 770000, 3200000 },
- { 1, { 883200, HFPLL, 1, 46 }, L2(10), 780000, 3200000 },
- { 0, { 960000, HFPLL, 1, 50 }, L2(10), 790000, 3200000 },
+ { 1, { 300000, PLL_0, 0, 0 }, L2(0), 750000, 400000 },
+ { 0, { 345600, HFPLL, 2, 36 }, L2(1), 750000, 3200000 },
+ { 1, { 422400, HFPLL, 2, 44 }, L2(2), 750000, 3200000 },
+ { 0, { 499200, HFPLL, 2, 52 }, L2(2), 750000, 3200000 },
+ { 0, { 576000, HFPLL, 1, 30 }, L2(3), 750000, 3200000 },
+ { 1, { 652800, HFPLL, 1, 34 }, L2(3), 750000, 3200000 },
+ { 1, { 729600, HFPLL, 1, 38 }, L2(4), 760000, 3200000 },
+ { 0, { 806400, HFPLL, 1, 42 }, L2(4), 770000, 3200000 },
+ { 1, { 883200, HFPLL, 1, 46 }, L2(4), 780000, 3200000 },
+ { 1, { 960000, HFPLL, 1, 50 }, L2(9), 790000, 3200000 },
{ 1, { 1036800, HFPLL, 1, 54 }, L2(10), 800000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 58 }, L2(12), 810000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 62 }, L2(12), 820000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 66 }, L2(12), 830000, 3200000 },
- { 1, { 1344000, HFPLL, 1, 70 }, L2(12), 840000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 74 }, L2(16), 850000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 78 }, L2(16), 860000, 3200000 },
- { 0, { 1574400, HFPLL, 1, 82 }, L2(16), 870000, 3200000 },
- { 0, { 1651200, HFPLL, 1, 86 }, L2(16), 875000, 3200000 },
- { 1, { 1728000, HFPLL, 1, 90 }, L2(16), 885000, 3200000 },
- { 0, { 1804800, HFPLL, 1, 94 }, L2(19), 895000, 3200000 },
- { 0, { 1881600, HFPLL, 1, 98 }, L2(19), 905000, 3200000 },
- { 0, { 1958400, HFPLL, 1, 102 }, L2(19), 915000, 3200000 },
- { 1, { 2035200, HFPLL, 1, 106 }, L2(19), 920000, 3200000 },
+ { 0, { 1113600, HFPLL, 1, 58 }, L2(10), 810000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 62 }, L2(10), 820000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 66 }, L2(13), 830000, 3200000 },
+ { 0, { 1344000, HFPLL, 1, 70 }, L2(14), 840000, 3200000 },
+ { 0, { 1420800, HFPLL, 1, 74 }, L2(15), 850000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 78 }, L2(16), 860000, 3200000 },
+ { 1, { 1574400, HFPLL, 1, 82 }, L2(17), 870000, 3200000 },
+ { 0, { 1651200, HFPLL, 1, 86 }, L2(17), 875000, 3200000 },
+ { 1, { 1728000, HFPLL, 1, 90 }, L2(18), 885000, 3200000 },
+ { 0, { 1804800, HFPLL, 1, 94 }, L2(18), 895000, 3200000 },
+ { 0, { 1881600, HFPLL, 1, 98 }, L2(18), 905000, 3200000 },
+ { 1, { 1958400, HFPLL, 1, 102 }, L2(19), 915000, 3200000 },
+ { 0, { 2035200, HFPLL, 1, 106 }, L2(19), 920000, 3200000 },
{ 0, { 2112000, HFPLL, 1, 110 }, L2(19), 930000, 3200000 },
{ 0, { 2188800, HFPLL, 1, 114 }, L2(19), 940000, 3200000 },
{ 1, { 2265600, HFPLL, 1, 118 }, L2(19), 950000, 3200000 },
@@ -716,6 +926,17 @@
[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) },
+
+ /* 8974v2 2.0GHz 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) },
+
};
static struct msm_bus_scale_pdata bus_scale_data __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-9625.c b/arch/arm/mach-msm/acpuclock-9625.c
index 34952fb..42659f9 100644
--- a/arch/arm/mach-msm/acpuclock-9625.c
+++ b/arch/arm/mach-msm/acpuclock-9625.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/io.h>
+#include <linux/clk.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
@@ -80,18 +81,21 @@
.update_mask = RCG_CONFIG_PGM_DATA_BIT | RCG_CONFIG_PGM_ENA_BIT,
.poll_mask = RCG_CONFIG_PGM_DATA_BIT,
},
+ .power_collapse_khz = 19200,
+ .wait_for_irq_khz = 19200,
};
static int __init acpuclk_9625_probe(struct platform_device *pdev)
{
struct resource *res;
- u32 regval;
+ u32 regval, i;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rcg_base");
if (!res)
return -EINVAL;
- drv_data.apcs_rcg_config = ioremap(res->start, resource_size(res));
+ drv_data.apcs_rcg_config = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
if (!drv_data.apcs_rcg_config)
return -ENOMEM;
@@ -117,6 +121,18 @@
return PTR_ERR(drv_data.vdd_mem);
}
+ for (i = 0; i < NUM_SRC; i++) {
+ if (!drv_data.src_clocks[i].name)
+ continue;
+ drv_data.src_clocks[i].clk =
+ devm_clk_get(&pdev->dev, drv_data.src_clocks[i].name);
+ if (IS_ERR(drv_data.src_clocks[i].clk)) {
+ dev_err(&pdev->dev, "Unable to get clock %s\n",
+ drv_data.src_clocks[i].name);
+ return -EPROBE_DEFER;
+ }
+ }
+
/* Disable hardware gating of gpll0 to A5SS */
regval = readl_relaxed(drv_data.apcs_cpu_pwr_ctl);
regval |= GPLL0_TO_A5_ALWAYS_ENABLE;
diff --git a/arch/arm/mach-msm/acpuclock-cortex.c b/arch/arm/mach-msm/acpuclock-cortex.c
index 88bf919..ca7fc2b 100644
--- a/arch/arm/mach-msm/acpuclock-cortex.c
+++ b/arch/arm/mach-msm/acpuclock-cortex.c
@@ -317,8 +317,6 @@
static struct acpuclk_data acpuclk_cortex_data = {
.set_rate = acpuclk_cortex_set_rate,
.get_rate = acpuclk_cortex_get_rate,
- .power_collapse_khz = 19200,
- .wait_for_irq_khz = 19200,
};
int __init acpuclk_cortex_init(struct platform_device *pdev,
@@ -330,20 +328,15 @@
priv = data;
mutex_init(&priv->lock);
+ acpuclk_cortex_data.power_collapse_khz = priv->wait_for_irq_khz;
+ acpuclk_cortex_data.wait_for_irq_khz = priv->wait_for_irq_khz;
+
bus_perf_client = msm_bus_scale_register_client(priv->bus_scale);
if (!bus_perf_client) {
pr_err("Unable to register bus client\n");
BUG();
}
- for (i = 0; i < NUM_SRC; i++) {
- if (!priv->src_clocks[i].name)
- continue;
- priv->src_clocks[i].clk =
- devm_clk_get(&pdev->dev, priv->src_clocks[i].name);
- BUG_ON(IS_ERR(priv->src_clocks[i].clk));
- }
-
/* Improve boot time by ramping up CPU immediately */
for (i = 0; priv->freq_tbl[i].khz != 0; i++)
if (priv->freq_tbl[i].use_for_scaling)
diff --git a/arch/arm/mach-msm/acpuclock-cortex.h b/arch/arm/mach-msm/acpuclock-cortex.h
index 2db3987..89a0a84 100644
--- a/arch/arm/mach-msm/acpuclock-cortex.h
+++ b/arch/arm/mach-msm/acpuclock-cortex.h
@@ -63,6 +63,8 @@
unsigned long vdd_max_mem;
struct src_clock src_clocks[NUM_SRC];
struct acpuclk_reg_data reg_data;
+ unsigned long power_collapse_khz;
+ unsigned long wait_for_irq_khz;
};
/* Instantaneous bandwidth requests in MB/s. */
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 20c461d..92be927 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -174,7 +174,7 @@
#define A2_PHYS_BASE 0x124C2000
#define A2_PHYS_SIZE 0x2000
#define BUFFER_SIZE 2048
-#define NUM_BUFFERS 32
+#define DEFAULT_NUM_BUFFERS 32
#ifndef A2_BAM_IRQ
#define A2_BAM_IRQ -1
@@ -194,6 +194,7 @@
static struct sps_register_event tx_register_event;
static struct sps_register_event rx_register_event;
static bool satellite_mode;
+static uint32_t num_buffers;
static struct bam_ch_info bam_ch[BAM_DMUX_NUM_CHANNELS];
static int bam_mux_initialized;
@@ -396,7 +397,7 @@
rx_len_cached = bam_rx_pool_len;
mutex_unlock(&bam_rx_pool_mutexlock);
- while (bam_connection_is_active && rx_len_cached < NUM_BUFFERS) {
+ while (bam_connection_is_active && rx_len_cached < num_buffers) {
if (in_global_reset)
goto fail;
@@ -433,8 +434,7 @@
list_add_tail(&info->list_node, &bam_rx_pool);
rx_len_cached = ++bam_rx_pool_len;
ret = sps_transfer_one(bam_rx_pipe, info->dma_address,
- BUFFER_SIZE, info,
- SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
+ BUFFER_SIZE, info, 0);
if (ret) {
list_del(&info->list_node);
rx_len_cached = --bam_rx_pool_len;
@@ -656,7 +656,7 @@
spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
list_add_tail(&pkt->list_node, &bam_tx_pool);
rc = sps_transfer_one(bam_tx_pipe, dma_address, len,
- pkt, SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
+ pkt, SPS_IOVEC_FLAG_EOT);
if (rc) {
DMUX_LOG_KERR("%s sps_transfer_one failed rc=%d\n",
__func__, rc);
@@ -829,7 +829,7 @@
spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
list_add_tail(&pkt->list_node, &bam_tx_pool);
rc = sps_transfer_one(bam_tx_pipe, dma_address, skb->len,
- pkt, SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
+ pkt, SPS_IOVEC_FLAG_EOT);
if (rc) {
DMUX_LOG_KERR("%s sps_transfer_one failed rc=%d\n",
__func__, rc);
@@ -1182,14 +1182,14 @@
break;
}
- buffs_used = NUM_BUFFERS - buffs_unused;
+ buffs_used = num_buffers - buffs_unused;
if (buffs_unused == 0) {
rx_timer_interval = MIN_POLLING_SLEEP;
} else {
if (buffs_used > 0) {
rx_timer_interval =
- (2 * NUM_BUFFERS *
+ (2 * num_buffers *
rx_timer_interval)/
(3 * buffs_used);
} else {
@@ -2282,15 +2282,27 @@
satellite_mode = of_property_read_bool(pdev->dev.of_node,
"qcom,satellite-mode");
- DBG("%s: base:%p size:%x irq:%d satellite:%d\n", __func__,
+ rc = of_property_read_u32(pdev->dev.of_node,
+ "qcom,rx-ring-size",
+ &num_buffers);
+ if (rc) {
+ DBG("%s: falling back to num_buffs default, rc:%d\n",
+ __func__, rc);
+ num_buffers = DEFAULT_NUM_BUFFERS;
+ }
+
+ DBG("%s: base:%p size:%x irq:%d satellite:%d num_buffs:%d\n",
+ __func__,
a2_phys_base,
a2_phys_size,
a2_bam_irq,
- satellite_mode);
+ satellite_mode,
+ num_buffers);
} else { /* fallback to default init data */
a2_phys_base = (void *)(A2_PHYS_BASE);
a2_phys_size = A2_PHYS_SIZE;
a2_bam_irq = A2_BAM_IRQ;
+ num_buffers = DEFAULT_NUM_BUFFERS;
}
xo_clk = clk_get(&pdev->dev, "xo");
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index a1ed251..5ab4a53 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -475,6 +475,9 @@
.low_voltage_calc_ms = 1000,
.alarm_low_mv = 3400,
.alarm_high_mv = 4000,
+ .high_ocv_correction_limit_uv = 50,
+ .low_ocv_correction_limit_uv = 100,
+ .hold_soc_est = 3,
};
static struct pm8921_platform_data
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 42bde8f..e36884e 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -675,6 +675,7 @@
static struct msm_hsic_host_platform_data msm_hsic_pdata = {
.strobe = 88,
.data = 89,
+ .phy_sof_workaround = true,
.bus_scale_table = &hsic_bus_scale_pdata,
};
#else
@@ -3804,6 +3805,8 @@
if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
pr_err("meminfo_init() failed!\n");
+ msm_thermal_pdata.limit_temp_degC = 80;
+
apq8064_common_init();
ethernet_init();
fsm8064_ep_pcie_init();
diff --git a/arch/arm/mach-msm/board-8226.c b/arch/arm/mach-msm/board-8226.c
index 872fabe..6371b9d 100644
--- a/arch/arm/mach-msm/board-8226.c
+++ b/arch/arm/mach-msm/board-8226.c
@@ -108,7 +108,7 @@
msm_spm_device_init();
rpm_regulator_smd_driver_init();
qpnp_regulator_init();
- if (machine_is_msm8226_rumi())
+ if (of_board_is_rumi())
msm_clock_init(&msm8226_rumi_clock_init_data);
else
msm_clock_init(&msm8226_clock_init_data);
diff --git a/arch/arm/mach-msm/board-8610.c b/arch/arm/mach-msm/board-8610.c
index 5f5366f..9495b72 100644
--- a/arch/arm/mach-msm/board-8610.c
+++ b/arch/arm/mach-msm/board-8610.c
@@ -103,7 +103,7 @@
qpnp_regulator_init();
msm_thermal_device_init();
- if (machine_is_msm8610_rumi())
+ if (of_board_is_rumi())
msm_clock_init(&msm8610_rumi_clock_init_data);
else
msm_clock_init(&msm8610_clock_init_data);
diff --git a/arch/arm/mach-msm/board-8930-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
index 4f398f4..ef65613 100644
--- a/arch/arm/mach-msm/board-8930-pmic.c
+++ b/arch/arm/mach-msm/board-8930-pmic.c
@@ -478,6 +478,9 @@
.low_voltage_calc_ms = 1000,
.alarm_low_mv = 3400,
.alarm_high_mv = 4000,
+ .high_ocv_correction_limit_uv = 50,
+ .low_ocv_correction_limit_uv = 100,
+ .hold_soc_est = 3,
};
static struct pm8038_platform_data pm8038_platform_data __devinitdata = {
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index 8c16984..c87d966 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -435,6 +435,9 @@
.low_voltage_calc_ms = 1000,
.alarm_low_mv = 3400,
.alarm_high_mv = 4000,
+ .high_ocv_correction_limit_uv = 50,
+ .low_ocv_correction_limit_uv = 100,
+ .hold_soc_est = 3,
};
#define PM8921_LC_LED_MAX_CURRENT 4 /* I = 4mA */
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 7ef6fed..f3d8a2f 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1459,8 +1459,9 @@
#ifdef CONFIG_USB_EHCI_MSM_HSIC
#define HSIC_HUB_RESET_GPIO 91
static struct msm_hsic_host_platform_data msm_hsic_pdata = {
- .strobe = 150,
- .data = 151,
+ .strobe = 150,
+ .data = 151,
+ .phy_sof_workaround = true,
};
static struct smsc_hub_platform_data hsic_hub_pdata = {
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 688c6f7..35f3f99 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -718,14 +718,14 @@
},
};
-static struct gpiomux_setting pri_auxpcm_act_cfg = {
+static struct gpiomux_setting auxpcm_act_cfg = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_8MA,
.pull = GPIOMUX_PULL_NONE,
};
-static struct gpiomux_setting pri_auxpcm_sus_cfg = {
+static struct gpiomux_setting auxpcm_sus_cfg = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_2MA,
.pull = GPIOMUX_PULL_DOWN,
@@ -735,29 +735,60 @@
{
.gpio = 65,
.settings = {
- [GPIOMUX_SUSPENDED] = &pri_auxpcm_sus_cfg,
- [GPIOMUX_ACTIVE] = &pri_auxpcm_act_cfg,
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
},
},
{
.gpio = 66,
.settings = {
- [GPIOMUX_SUSPENDED] = &pri_auxpcm_sus_cfg,
- [GPIOMUX_ACTIVE] = &pri_auxpcm_act_cfg,
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
},
},
{
.gpio = 67,
.settings = {
- [GPIOMUX_SUSPENDED] = &pri_auxpcm_sus_cfg,
- [GPIOMUX_ACTIVE] = &pri_auxpcm_act_cfg,
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
},
},
{
.gpio = 68,
.settings = {
- [GPIOMUX_SUSPENDED] = &pri_auxpcm_sus_cfg,
- [GPIOMUX_ACTIVE] = &pri_auxpcm_act_cfg,
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+ },
+ },
+};
+
+static struct msm_gpiomux_config msm8974_sec_auxpcm_configs[] __initdata = {
+ {
+ .gpio = 79,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+ },
+ },
+ {
+ .gpio = 80,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+ },
+ },
+ {
+ .gpio = 81,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
+ },
+ },
+ {
+ .gpio = 82,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &auxpcm_sus_cfg,
+ [GPIOMUX_ACTIVE] = &auxpcm_act_cfg,
},
},
};
@@ -1024,17 +1055,19 @@
ARRAY_SIZE(msm_hsic_hub_configs));
msm_gpiomux_install(msm_hdmi_configs, ARRAY_SIZE(msm_hdmi_configs));
- if (machine_is_msm8974_fluid())
+ if (of_board_is_fluid())
msm_gpiomux_install(msm_mhl_configs,
ARRAY_SIZE(msm_mhl_configs));
msm_gpiomux_install(msm8974_pri_auxpcm_configs,
ARRAY_SIZE(msm8974_pri_auxpcm_configs));
+ msm_gpiomux_install(msm8974_sec_auxpcm_configs,
+ ARRAY_SIZE(msm8974_sec_auxpcm_configs));
msm_gpiomux_install_nowrite(msm_lcd_configs,
ARRAY_SIZE(msm_lcd_configs));
- if (machine_is_msm8974_rumi())
+ if (of_board_is_rumi())
msm_gpiomux_install(msm_rumi_blsp_configs,
ARRAY_SIZE(msm_rumi_blsp_configs));
}
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index e624e3f..9b69c8f 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -97,7 +97,7 @@
rpm_regulator_smd_driver_init();
msm_spm_device_init();
krait_power_init();
- if (machine_is_msm8974_rumi())
+ if (of_board_is_rumi())
msm_clock_init(&msm8974_rumi_clock_init_data);
else
msm_clock_init(&msm8974_clock_init_data);
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 50f4fd7..b77a3b9 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -841,6 +841,10 @@
.prv_data = &msm_hsic_peripheral_pdata_private,
};
+static struct msm_hsic_host_platform_data msm_hsic_pdata = {
+ .phy_sof_workaround = true,
+};
+
#define PID_MAGIC_ID 0x71432909
#define SERIAL_NUM_MAGIC_ID 0x61945374
#define SERIAL_NUMBER_LENGTH 127
@@ -1073,6 +1077,7 @@
&msm_peripheral_pdata;
msm_device_hsic_peripheral.dev.platform_data =
&msm_hsic_peripheral_pdata;
+ msm_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
msm_device_usb_bam.dev.platform_data = &msm_usb_bam_pdata;
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
msm9615_pm8xxx_gpio_mpp_init();
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 413927c..4079b5a 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -2736,16 +2736,20 @@
enum vdd_sr2_pll_levels {
VDD_SR2_PLL_OFF,
- VDD_SR2_PLL_ON,
+ VDD_SR2_PLL_SVS,
+ VDD_SR2_PLL_NOM,
+ VDD_SR2_PLL_TUR,
VDD_SR2_PLL_NUM
};
static const int *vdd_sr2_levels[] = {
- [VDD_SR2_PLL_OFF] = VDD_UV(0),
- [VDD_SR2_PLL_ON] = VDD_UV(1800000),
+ [VDD_SR2_PLL_OFF] = VDD_UV(0, RPM_REGULATOR_CORNER_NONE),
+ [VDD_SR2_PLL_SVS] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SVS_SOC),
+ [VDD_SR2_PLL_NOM] = VDD_UV(1800000, RPM_REGULATOR_CORNER_NORMAL),
+ [VDD_SR2_PLL_TUR] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SUPER_TURBO),
};
-static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 1, vdd_sr2_levels);
+static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 2, vdd_sr2_levels);
static struct pll_freq_tbl apcs_pll_freq[] = {
F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
@@ -2776,7 +2780,8 @@
.ops = &clk_ops_sr2_pll,
.vdd_class = &vdd_sr2_pll,
.fmax = (unsigned long [VDD_SR2_PLL_NUM]) {
- [VDD_SR2_PLL_ON] = ULONG_MAX,
+ [VDD_SR2_PLL_SVS] = 1000000000,
+ [VDD_SR2_PLL_NOM] = 1900000000,
},
.num_fmax = VDD_SR2_PLL_NUM,
CLK_INIT(a7sspll.c),
@@ -3514,12 +3519,17 @@
if (IS_ERR(vdd_sr2_pll.regulator[0]))
panic("clock-8226: Unable to get the sr2_pll regulator!");
+ vdd_sr2_pll.regulator[1] = regulator_get(NULL, "vdd_sr2_dig");
+ if (IS_ERR(vdd_sr2_pll.regulator[1]))
+ panic("clock-8226: Unable to get the vdd_sr2_dig regulator!");
+
/*
* These regulators are used at boot. Ensure they stay on
* while the clock framework comes online.
*/
- regulator_set_voltage(vdd_sr2_pll.regulator[0], 1800000, 1800000);
+ vote_vdd_level(&vdd_sr2_pll, VDD_SR2_PLL_TUR);
regulator_enable(vdd_sr2_pll.regulator[0]);
+ regulator_enable(vdd_sr2_pll.regulator[1]);
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
regulator_enable(vdd_dig.regulator[0]);
@@ -3548,7 +3558,9 @@
static int __init msm8226_clock_late_init(void)
{
- return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+ unvote_vdd_level(&vdd_sr2_pll, VDD_SR2_PLL_TUR);
+ unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+ return 0;
}
struct clock_init_data msm8226_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-8610.c b/arch/arm/mach-msm/clock-8610.c
index a645e9c..d63d722 100644
--- a/arch/arm/mach-msm/clock-8610.c
+++ b/arch/arm/mach-msm/clock-8610.c
@@ -345,9 +345,6 @@
#define gpll0_mm_source_val 5
#define gcc_xo_mm_source_val 0
#define mm_gnd_source_val 6
-#define cxo_lpass_source_val 0
-#define lpapll0_lpass_source_val 1
-#define gpll0_lpass_source_val 5
#define dsipll_mm_source_val 1
#define F(f, s, div, m, n) \
@@ -404,17 +401,6 @@
| BVAL(10, 8, s##_mm_source_val), \
}
-#define F_LPASS(f, s, div, m, n) \
- { \
- .freq_hz = (f), \
- .src_clk = &s##_clk_src.c, \
- .m_val = (m), \
- .n_val = ~((n)-(m)) * !!(n), \
- .d_val = ~(n),\
- .div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
- | BVAL(10, 8, s##_lpass_source_val), \
- }
-
#define VDD_DIG_FMAX_MAP1(l1, f1) \
.vdd_class = &vdd_dig, \
.fmax = (unsigned long[VDD_DIG_NUM]) { \
@@ -538,17 +524,20 @@
enum vdd_sr2_pll_levels {
VDD_SR2_PLL_OFF,
- VDD_SR2_PLL_ON,
+ VDD_SR2_PLL_SVS,
+ VDD_SR2_PLL_NOM,
+ VDD_SR2_PLL_TUR,
VDD_SR2_PLL_NUM
};
-static const int *vdd_sr2_pll_levels[] = {
- [VDD_SR2_PLL_OFF] = VDD_UV(0),
- [VDD_SR2_PLL_ON] = VDD_UV(1800000),
+static const int *vdd_sr2_levels[] = {
+ [VDD_SR2_PLL_OFF] = VDD_UV(0, RPM_REGULATOR_CORNER_NONE),
+ [VDD_SR2_PLL_SVS] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SVS_SOC),
+ [VDD_SR2_PLL_NOM] = VDD_UV(1800000, RPM_REGULATOR_CORNER_NORMAL),
+ [VDD_SR2_PLL_TUR] = VDD_UV(1800000, RPM_REGULATOR_CORNER_SUPER_TURBO),
};
-static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 1,
- vdd_sr2_pll_levels);
+static DEFINE_VDD_REGULATORS(vdd_sr2_pll, VDD_SR2_PLL_NUM, 2, vdd_sr2_levels);
static struct pll_freq_tbl apcs_pll_freq[] = {
F_APCS_PLL( 384000000, 20, 0x0, 0x1, 0x0, 0x0, 0x0),
@@ -579,7 +568,8 @@
.ops = &clk_ops_sr2_pll,
.vdd_class = &vdd_sr2_pll,
.fmax = (unsigned long [VDD_SR2_PLL_NUM]) {
- [VDD_SR2_PLL_ON] = ULONG_MAX,
+ [VDD_SR2_PLL_SVS] = 1000000000,
+ [VDD_SR2_PLL_NOM] = 1900000000,
},
.num_fmax = VDD_SR2_PLL_NUM,
CLK_INIT(a7sspll.c),
@@ -672,21 +662,6 @@
.base = &virt_bases[MMSS_BASE],
};
-static struct pll_vote_clk lpapll0_clk_src = {
- .en_reg = (void __iomem *)LPA_PLL_VOTE_APPS,
- .en_mask = BIT(0),
- .status_reg = (void __iomem *)LPAAUDIO_PLL_STATUS,
- .status_mask = BIT(17),
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &gcc_xo_clk_src.c,
- .rate = 491520000,
- .dbg_name = "lpapll0_clk_src",
- .ops = &clk_ops_pll_vote,
- CLK_INIT(lpapll0_clk_src.c),
- },
-};
-
static struct clk_freq_tbl ftbl_gcc_blsp1_qup1_6_spi_apps_clk[] = {
F( 960000, gcc_xo, 10, 1, 2),
F( 4800000, gcc_xo, 4, 0, 0),
@@ -2227,197 +2202,6 @@
},
};
-static struct clk_freq_tbl ftbl_audio_core_lpaif_clk[] = {
- F_LPASS( 512000, lpapll0, 16, 1, 60),
- F_LPASS( 768000, lpapll0, 16, 1, 40),
- F_LPASS( 1024000, lpapll0, 16, 1, 30),
- F_LPASS( 1536000, lpapll0, 16, 1, 20),
- F_LPASS( 2048000, lpapll0, 16, 1, 15),
- F_LPASS( 3072000, lpapll0, 16, 1, 10),
- F_LPASS( 4096000, lpapll0, 15, 1, 8),
- F_LPASS( 6144000, lpapll0, 10, 1, 8),
- F_LPASS( 8192000, lpapll0, 15, 1, 4),
- F_LPASS(12288000, lpapll0, 10, 1, 4),
- F_END,
-};
-
-static struct rcg_clk lpaif_pri_clk_src = {
- .cmd_rcgr_reg = LPAIF_PRI_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "lpaif_pri_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 12290000, NOMINAL, 24580000),
- CLK_INIT(lpaif_pri_clk_src.c),
- },
-};
-
-static struct rcg_clk lpaif_quad_clk_src = {
- .cmd_rcgr_reg = LPAIF_QUAD_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "lpaif_quad_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 12290000, NOMINAL, 24580000),
- CLK_INIT(lpaif_quad_clk_src.c),
- },
-};
-
-static struct rcg_clk lpaif_sec_clk_src = {
- .cmd_rcgr_reg = LPAIF_SEC_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "lpaif_sec_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 12290000, NOMINAL, 24580000),
- CLK_INIT(lpaif_sec_clk_src.c),
- },
-};
-
-static struct rcg_clk lpaif_spkr_clk_src = {
- .cmd_rcgr_reg = LPAIF_SPKR_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "lpaif_spkr_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 12290000, NOMINAL, 24580000),
- CLK_INIT(lpaif_spkr_clk_src.c),
- },
-};
-
-static struct rcg_clk lpaif_ter_clk_src = {
- .cmd_rcgr_reg = LPAIF_TER_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "lpaif_ter_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 12290000, NOMINAL, 24580000),
- CLK_INIT(lpaif_ter_clk_src.c),
- },
-};
-
-static struct clk_freq_tbl ftbl_audio_core_lpaif_pcm0_1_clk[] = {
- F_LPASS( 512000, lpapll0, 16, 1, 60),
- F_LPASS( 768000, lpapll0, 16, 1, 40),
- F_LPASS(1024000, lpapll0, 16, 1, 30),
- F_LPASS(1536000, lpapll0, 16, 1, 20),
- F_LPASS(2048000, lpapll0, 16, 1, 15),
- F_LPASS(3072000, lpapll0, 16, 1, 10),
- F_LPASS(4096000, lpapll0, 15, 1, 8),
- F_LPASS(6144000, lpapll0, 10, 1, 8),
- F_LPASS(8192000, lpapll0, 15, 1, 4),
- F_END,
-};
-
-static struct rcg_clk lpaif_pcm0_clk_src = {
- .cmd_rcgr_reg = LPAIF_PCM0_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_pcm0_1_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "lpaif_pcm0_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 4100000, NOMINAL, 8192000),
- CLK_INIT(lpaif_pcm0_clk_src.c),
- },
-};
-
-static struct rcg_clk lpaif_pcm1_clk_src = {
- .cmd_rcgr_reg = LPAIF_PCM1_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_pcm0_1_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "lpaif_pcm1_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 4100000, NOMINAL, 8192000),
- CLK_INIT(lpaif_pcm1_clk_src.c),
- },
-};
-
-static struct rcg_clk lpaif_pcmoe_clk_src = {
- .cmd_rcgr_reg = LPAIF_PCMOE_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_lpaif_pcm0_1_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "lpaif_pcmoe_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 6140000, NOMINAL, 12290000),
- CLK_INIT(lpaif_pcmoe_clk_src.c),
- },
-};
-
-static struct clk_freq_tbl ftbl_audio_core_slimbus_core_clock[] = {
- F_LPASS(24576000, lpapll0, 4, 1, 5),
- F_END
-};
-
-static struct rcg_clk audio_core_slimbus_core_clk_src = {
- .cmd_rcgr_reg = SLIMBUS_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_audio_core_slimbus_core_clock,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_slimbus_core_clk_src",
- .ops = &clk_ops_rcg_mnd,
- VDD_DIG_FMAX_MAP2(LOW, 12935000, NOMINAL, 25869000),
- CLK_INIT(audio_core_slimbus_core_clk_src.c),
- },
-};
-
-static struct branch_clk audio_core_slimbus_core_clk = {
- .cbcr_reg = AUDIO_CORE_SLIMBUS_CORE_CBCR,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &audio_core_slimbus_core_clk_src.c,
- .dbg_name = "audio_core_slimbus_core_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_slimbus_core_clk.c),
- },
-};
-
-static struct branch_clk audio_core_ixfabric_clk = {
- .cbcr_reg = AUDIO_CORE_IXFABRIC_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_ixfabric_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_ixfabric_clk.c),
- },
-};
-
-static struct branch_clk audio_wrapper_br_clk = {
- .cbcr_reg = AUDIO_WRAPPER_BR_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_wrapper_br_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_wrapper_br_clk.c),
- },
-};
-
static struct branch_clk q6ss_ahb_lfabif_clk = {
.cbcr_reg = Q6SS_AHB_LFABIF_CBCR,
.has_sibling = 1,
@@ -2453,244 +2237,6 @@
},
};
-static struct branch_clk audio_core_lpaif_pcm_data_oe_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PCM_DATA_OE_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &lpaif_pcmoe_clk_src.c,
- .dbg_name = "audio_core_lpaif_pcm_data_oe_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pcm_data_oe_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pri_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PRI_EBIT_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pri_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pri_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pri_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PRI_IBIT_CBCR,
- .has_sibling = 0,
- .max_div = 511,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &lpaif_pri_clk_src.c,
- .dbg_name = "audio_core_lpaif_pri_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pri_ibit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pri_osr_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PRI_OSR_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &lpaif_pri_clk_src.c,
- .dbg_name = "audio_core_lpaif_pri_osr_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pri_osr_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pcm0_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PCM0_EBIT_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pcm0_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pcm0_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pcm0_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PCM0_IBIT_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &lpaif_pcm0_clk_src.c,
- .dbg_name = "audio_core_lpaif_pcm0_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pcm0_ibit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_quad_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_QUAD_EBIT_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_quad_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_quad_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_quad_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_QUAD_IBIT_CBCR,
- .has_sibling = 0,
- .max_div = 511,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &lpaif_quad_clk_src.c,
- .dbg_name = "audio_core_lpaif_quad_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_quad_ibit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_quad_osr_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_QUAD_OSR_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &lpaif_quad_clk_src.c,
- .dbg_name = "audio_core_lpaif_quad_osr_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_quad_osr_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_sec_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_SEC_EBIT_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_sec_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_sec_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_sec_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_SEC_IBIT_CBCR,
- .has_sibling = 0,
- .max_div = 511,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &lpaif_sec_clk_src.c,
- .dbg_name = "audio_core_lpaif_sec_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_sec_ibit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_sec_osr_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_SEC_OSR_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &lpaif_sec_clk_src.c,
- .dbg_name = "audio_core_lpaif_sec_osr_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_sec_osr_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pcm1_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PCM1_EBIT_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_pcm1_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pcm1_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_pcm1_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_PCM1_IBIT_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &lpaif_pcm1_clk_src.c,
- .dbg_name = "audio_core_lpaif_pcm1_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_pcm1_ibit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_codec_spkr_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_EBIT_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_codec_spkr_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_codec_spkr_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_codec_spkr_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_IBIT_CBCR,
- .has_sibling = 1,
- .max_div = 511,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &lpaif_spkr_clk_src.c,
- .dbg_name = "audio_core_lpaif_codec_spkr_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_codec_spkr_ibit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_codec_spkr_osr_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_CODEC_SPKR_OSR_CBCR,
- .has_sibling = 1,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &lpaif_spkr_clk_src.c,
- .dbg_name = "audio_core_lpaif_codec_spkr_osr_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_codec_spkr_osr_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_ter_ebit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_TER_EBIT_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .dbg_name = "audio_core_lpaif_ter_ebit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_ter_ebit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_ter_ibit_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_TER_IBIT_CBCR,
- .has_sibling = 0,
- .max_div = 511,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &lpaif_ter_clk_src.c,
- .dbg_name = "audio_core_lpaif_ter_ibit_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_ter_ibit_clk.c),
- },
-};
-
-static struct branch_clk audio_core_lpaif_ter_osr_clk = {
- .cbcr_reg = AUDIO_CORE_LPAIF_TER_OSR_CBCR,
- .has_sibling = 0,
- .base = &virt_bases[LPASS_BASE],
- .c = {
- .parent = &lpaif_ter_clk_src.c,
- .dbg_name = "audio_core_lpaif_ter_osr_clk",
- .ops = &clk_ops_branch,
- CLK_INIT(audio_core_lpaif_ter_osr_clk.c),
- },
-};
-
#ifdef CONFIG_DEBUG_FS
struct measure_mux_entry {
@@ -2781,20 +2327,9 @@
{ &csi1pix_clk.c, MMSS_BASE, 0x0025},
{ &bimc_gfx_clk.c, MMSS_BASE, 0x0032},
- { &lpaif_pcmoe_clk_src.c, LPASS_BASE, 0x000f},
- { &lpaif_pcm1_clk_src.c, LPASS_BASE, 0x0012},
- { &lpaif_pcm0_clk_src.c, LPASS_BASE, 0x0013},
- { &lpaif_quad_clk_src.c, LPASS_BASE, 0x0014},
- { &lpaif_ter_clk_src.c, LPASS_BASE, 0x0015},
- { &lpaif_sec_clk_src.c, LPASS_BASE, 0x0016},
- { &lpaif_pri_clk_src.c, LPASS_BASE, 0x0017},
- { &lpaif_spkr_clk_src.c, LPASS_BASE, 0x0018},
{ &q6ss_ahbm_clk.c, LPASS_BASE, 0x001d},
{ &q6ss_ahb_lfabif_clk.c, LPASS_BASE, 0x001e},
- { &audio_wrapper_br_clk.c, LPASS_BASE, 0x0022},
{ &q6ss_xo_clk.c, LPASS_BASE, 0x002b},
- {&audio_core_lpaif_pcm_data_oe_clk.c, LPASS_BASE, 0x0030},
- { &audio_core_ixfabric_clk.c, LPASS_BASE, 0x0059},
{&apc0_m_clk, APCS_BASE, 0x10},
{&apc1_m_clk, APCS_BASE, 0x11},
@@ -3232,40 +2767,6 @@
"fd010000.qcom,iommu"),
CLK_LOOKUP("core_clk", pnoc_iommu_clk.c, "fd010000.qcom,iommu"),
- CLK_LOOKUP("core_clk_src", lpaif_pri_clk_src.c, ""),
- CLK_LOOKUP("core_clk_src", lpaif_quad_clk_src.c, ""),
- CLK_LOOKUP("core_clk_src", lpaif_sec_clk_src.c, ""),
- CLK_LOOKUP("core_clk_src", lpaif_spkr_clk_src.c, ""),
- CLK_LOOKUP("core_clk_src", lpaif_ter_clk_src.c, ""),
- CLK_LOOKUP("core_clk_src", lpaif_pcm0_clk_src.c, ""),
- CLK_LOOKUP("core_clk_src", lpaif_pcm1_clk_src.c, ""),
- CLK_LOOKUP("core_clk_src", lpaif_pcmoe_clk_src.c, ""),
- CLK_LOOKUP("core_clk", audio_core_ixfabric_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_wrapper_br_clk.c, ""),
- CLK_LOOKUP("core_clk", q6ss_ahb_lfabif_clk.c, ""),
- CLK_LOOKUP("core_clk", q6ss_ahbm_clk.c, ""),
- CLK_LOOKUP("core_clk", q6ss_xo_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_pcm_data_oe_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_pri_ebit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_pri_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_pri_osr_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_pcm0_ebit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_pcm0_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_quad_ebit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_quad_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_quad_osr_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_sec_ebit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_sec_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_sec_osr_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_pcm1_ebit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_pcm1_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_codec_spkr_ebit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_codec_spkr_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_codec_spkr_osr_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_ter_ebit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_ter_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", audio_core_lpaif_ter_osr_clk.c, ""),
-
CLK_LOOKUP("core_clk", q6ss_xo_clk.c, "fe200000.qcom,lpass"),
CLK_LOOKUP("bus_clk", gcc_lpass_q6_axi_clk.c, "fe200000.qcom,lpass"),
CLK_LOOKUP("iface_clk", q6ss_ahb_lfabif_clk.c, "fe200000.qcom,lpass"),
@@ -3316,32 +2817,6 @@
.size = ARRAY_SIZE(msm_clocks_8610_rumi),
};
-static struct pll_config_regs gpll0_regs __initdata = {
- .l_reg = (void __iomem *)GPLL0_L_VAL,
- .m_reg = (void __iomem *)GPLL0_M_VAL,
- .n_reg = (void __iomem *)GPLL0_N_VAL,
- .config_reg = (void __iomem *)GPLL0_USER_CTL,
- .mode_reg = (void __iomem *)GPLL0_MODE,
- .base = &virt_bases[GCC_BASE],
-};
-
-/* GPLL0 at 600 MHz, main output enabled. */
-static struct pll_config gpll0_config __initdata = {
- .l = 0x1f,
- .m = 0x1,
- .n = 0x4,
- .vco_val = 0x0,
- .vco_mask = BM(21, 20),
- .pre_div_val = 0x0,
- .pre_div_mask = BM(14, 12),
- .post_div_val = 0x0,
- .post_div_mask = BM(9, 8),
- .mn_ena_val = BIT(24),
- .mn_ena_mask = BIT(24),
- .main_output_val = BIT(0),
- .main_output_mask = BIT(0),
-};
-
/* MMPLL0 at 800 MHz, main output enabled. */
static struct pll_config mmpll0_config __initdata = {
.l = 0x29,
@@ -3376,32 +2851,6 @@
.main_output_mask = BIT(0),
};
-static struct pll_config_regs lpapll0_regs __initdata = {
- .l_reg = (void __iomem *)LPAAUDIO_PLL_L_VAL,
- .m_reg = (void __iomem *)LPAAUDIO_PLL_M_VAL,
- .n_reg = (void __iomem *)LPAAUDIO_PLL_N_VAL,
- .config_reg = (void __iomem *)LPAAUDIO_PLL_USER_CTL,
- .mode_reg = (void __iomem *)LPAAUDIO_PLL_MODE,
- .base = &virt_bases[LPASS_BASE],
-};
-
-/* LPAPLL0 at 491.52 MHz, main output enabled. */
-static struct pll_config lpapll0_config __initdata = {
- .l = 0x33,
- .m = 0x1,
- .n = 0x5,
- .vco_val = 0x0,
- .vco_mask = BM(21, 20),
- .pre_div_val = BVAL(14, 12, 0x1),
- .pre_div_mask = BM(14, 12),
- .post_div_val = 0x0,
- .post_div_mask = BM(9, 8),
- .mn_ena_val = BIT(24),
- .mn_ena_mask = BIT(24),
- .main_output_val = BIT(0),
- .main_output_mask = BIT(0),
-};
-
#define PLL_AUX_OUTPUT_BIT 1
#define PLL_AUX2_OUTPUT_BIT 2
@@ -3421,21 +2870,10 @@
static void __init reg_init(void)
{
- u32 regval, status;
- int ret;
-
- if (!(readl_relaxed(GCC_REG_BASE(GPLL0_STATUS))
- & gpll0_clk_src.status_mask))
- configure_sr_hpm_lp_pll(&gpll0_config, &gpll0_regs, 1);
+ u32 regval;
configure_sr_hpm_lp_pll(&mmpll0_config, &mmpll0_regs, 1);
configure_sr_hpm_lp_pll(&mmpll1_config, &mmpll1_regs, 1);
- configure_sr_hpm_lp_pll(&lpapll0_config, &lpapll0_regs, 1);
-
- /* Enable GPLL0's aux outputs. */
- regval = readl_relaxed(GCC_REG_BASE(GPLL0_USER_CTL));
- regval |= BIT(PLL_AUX_OUTPUT_BIT) | BIT(PLL_AUX2_OUTPUT_BIT);
- writel_relaxed(regval, GCC_REG_BASE(GPLL0_USER_CTL));
/* Vote for GPLL0 to turn on. Needed by acpuclock. */
regval = readl_relaxed(GCC_REG_BASE(APCS_GPLL_ENA_VOTE));
@@ -3447,31 +2885,6 @@
* register.
*/
writel_relaxed(0x0, GCC_REG_BASE(APCS_CLOCK_SLEEP_ENA_VOTE));
-
- /*
- * TODO: The following sequence enables the LPASS audio core GDSC.
- * Remove when this becomes unnecessary.
- */
-
- /*
- * Disable HW trigger: collapse/restore occur based on registers writes.
- * Disable SW override: Use hardware state-machine for sequencing.
- */
- regval = readl_relaxed(LPASS_REG_BASE(AUDIO_CORE_GDSCR));
- regval &= ~(HW_CONTROL_MASK | SW_OVERRIDE_MASK);
-
- /* Configure wait time between states. */
- regval &= ~(EN_REST_WAIT_MASK | EN_FEW_WAIT_MASK | CLK_DIS_WAIT_MASK);
- regval |= EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL;
- writel_relaxed(regval, LPASS_REG_BASE(AUDIO_CORE_GDSCR));
-
- regval = readl_relaxed(LPASS_REG_BASE(AUDIO_CORE_GDSCR));
- regval &= ~BIT(0);
- writel_relaxed(regval, LPASS_REG_BASE(AUDIO_CORE_GDSCR));
-
- ret = readl_poll_timeout(LPASS_REG_BASE(AUDIO_CORE_GDSCR), status,
- status & PWR_ON_MASK, 50, GDSC_TIMEOUT_US);
- WARN(ret, "LPASS Audio Core GDSC did not power on.\n");
}
static void __init msm8610_clock_post_init(void)
@@ -3489,8 +2902,6 @@
clk_set_rate(&pdm2_clk_src.c, pdm2_clk_src.freq_tbl[0].freq_hz);
clk_set_rate(&mclk0_clk_src.c, mclk0_clk_src.freq_tbl[0].freq_hz);
clk_set_rate(&mclk1_clk_src.c, mclk1_clk_src.freq_tbl[0].freq_hz);
- clk_set_rate(&audio_core_slimbus_core_clk_src.c,
- audio_core_slimbus_core_clk_src.freq_tbl[0].freq_hz);
}
#define GCC_CC_PHYS 0xFC400000
@@ -3541,8 +2952,13 @@
if (IS_ERR(vdd_sr2_pll.regulator[0]))
panic("clock-8610: Unable to get the vdd_sr2_pll regulator!");
- regulator_set_voltage(vdd_sr2_pll.regulator[0], 1800000, 1800000);
+ vdd_sr2_pll.regulator[1] = regulator_get(NULL, "vdd_sr2_dig");
+ if (IS_ERR(vdd_sr2_pll.regulator[1]))
+ panic("clock-8610: Unable to get the vdd_sr2_dig regulator!");
+
+ vote_vdd_level(&vdd_sr2_pll, VDD_SR2_PLL_TUR);
regulator_enable(vdd_sr2_pll.regulator[0]);
+ regulator_enable(vdd_sr2_pll.regulator[1]);
/*
* TODO: Set a voltage and enable vdd_dig, leaving the voltage high
@@ -3567,16 +2983,13 @@
/* TODO: Remove this once the bus driver is in place */
clk_set_rate(&axi_clk_src.c, 200000000);
clk_prepare_enable(&mmss_s0_axi_clk.c);
-
- /* TODO: Temporarily enable a clock to allow access to LPASS core
- * registers.
- */
- clk_prepare_enable(&audio_core_ixfabric_clk.c);
}
static int __init msm8610_clock_late_init(void)
{
- return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+ unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+ unvote_vdd_level(&vdd_sr2_pll, VDD_SR2_PLL_TUR);
+ return 0;
}
struct clock_init_data msm8610_clock_init_data __initdata = {
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index d8e4ed5..6817c6c 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -147,6 +147,7 @@
#define USB_HSIC_SYSTEM_CBCR 0x040C
#define USB_HSIC_CBCR 0x0410
#define USB_HSIC_IO_CAL_CBCR 0x0414
+#define USB_HSIC_IO_CAL_SLEEP_CBCR 0x0418
#define USB_HSIC_XCVR_FS_CBCR 0x042C
#define USB_HS_SYSTEM_CBCR 0x0484
#define USB_HS_AHB_CBCR 0x0488
@@ -187,6 +188,7 @@
#define PDM2_CBCR 0x0CCC
#define PRNG_AHB_CBCR 0x0D04
#define BAM_DMA_AHB_CBCR 0x0D44
+#define BAM_DMA_INACTIVITY_TIMERS_CBCR 0x0D48
#define MSG_RAM_AHB_CBCR 0x0E44
#define CE1_CBCR 0x1044
#define CE1_AXI_CBCR 0x1048
@@ -1002,6 +1004,18 @@
},
};
+static struct local_vote_clk gcc_bam_dma_inactivity_timers_clk = {
+ .cbcr_reg = BAM_DMA_INACTIVITY_TIMERS_CBCR,
+ .vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+ .en_mask = BIT(11),
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_bam_dma_inactivity_timers_clk",
+ .ops = &clk_ops_vote,
+ CLK_INIT(gcc_bam_dma_inactivity_timers_clk.c),
+ },
+};
+
static struct local_vote_clk gcc_blsp1_ahb_clk = {
.cbcr_reg = BLSP1_AHB_CBCR,
.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
@@ -1517,6 +1531,17 @@
},
};
+static struct branch_clk gcc_usb_hsic_io_cal_sleep_clk = {
+ .cbcr_reg = USB_HSIC_IO_CAL_SLEEP_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_usb_hsic_io_cal_sleep_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_usb_hsic_io_cal_sleep_clk.c),
+ },
+};
+
static struct branch_clk gcc_usb_hsic_system_clk = {
.cbcr_reg = USB_HSIC_SYSTEM_CBCR,
.bcr_reg = USB_HS_HSIC_BCR,
@@ -1554,6 +1579,7 @@
struct measure_mux_entry measure_mux_common[] __initdata = {
{&gcc_pdm_ahb_clk.c, GCC_BASE, 0x00d0},
+ {&gcc_usb_hsic_io_cal_sleep_clk.c, GCC_BASE, 0x005c},
{&gcc_usb_hsic_xcvr_fs_clk.c, GCC_BASE, 0x005d},
{&gcc_usb_hsic_system_clk.c, GCC_BASE, 0x0059},
{&gcc_usb_hsic_io_cal_clk.c, GCC_BASE, 0x005b},
@@ -1583,6 +1609,7 @@
{&gcc_sdcc2_apps_clk.c, GCC_BASE, 0x0070},
{&gcc_blsp1_uart1_apps_clk.c, GCC_BASE, 0x008c},
{&gcc_blsp1_qup4_i2c_apps_clk.c, GCC_BASE, 0x0099},
+ {&gcc_bam_dma_inactivity_timers_clk.c, GCC_BASE, 0x00E1},
{&gcc_boot_rom_ahb_clk.c, GCC_BASE, 0x00f8},
{&gcc_ce1_ahb_clk.c, GCC_BASE, 0x013a},
{&gcc_pdm2_clk.c, GCC_BASE, 0x00d2},
@@ -1786,6 +1813,8 @@
CLK_LOOKUP("pll14", apcspll_clk_src.c, "f9010008.qcom,acpuclk"),
CLK_LOOKUP("dma_bam_pclk", gcc_bam_dma_ahb_clk.c, "msm_sps"),
+ CLK_LOOKUP("inactivity_clk", gcc_bam_dma_inactivity_timers_clk.c,
+ "msm_sps"),
CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f9924000.spi"),
CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f9925000.i2c"),
@@ -1842,6 +1871,8 @@
CLK_LOOKUP("cal_clk", gcc_usb_hsic_io_cal_clk.c, "msm_hsic_host"),
CLK_LOOKUP("core_clk", gcc_usb_hsic_system_clk.c, "msm_hsic_host"),
CLK_LOOKUP("alt_core_clk", gcc_usb_hsic_xcvr_fs_clk.c, ""),
+ CLK_LOOKUP("inactivity_clk", gcc_usb_hsic_io_cal_sleep_clk.c,
+ "msm_hsic_host"),
CLK_LOOKUP("core_clk", gcc_ce1_clk.c, "fd400000.qcom,qcedev"),
CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, "fd400000.qcom,qcedev"),
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index ecd25fc..9b34465 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -419,10 +419,21 @@
int clk_set_parent(struct clk *clk, struct clk *parent)
{
- if (!clk->ops->set_parent)
- return 0;
+ int rc = 0;
- return clk->ops->set_parent(clk, parent);
+ if (!clk->ops->set_parent)
+ return -ENOSYS;
+
+ mutex_lock(&clk->prepare_lock);
+ if (clk->parent == parent)
+ goto out;
+ rc = clk->ops->set_parent(clk, parent);
+ if (!rc)
+ clk->parent = parent;
+out:
+ mutex_unlock(&clk->prepare_lock);
+
+ return rc;
}
EXPORT_SYMBOL(clk_set_parent);
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 656c3f4..2f44566 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -2652,8 +2652,8 @@
[MSM_RPM_LOG_PAGE_BUFFER] = 0x000000A0,
},
.phys_size = SZ_8K,
- .log_len = 4096, /* log's buffer length in bytes */
- .log_len_mask = (4096 >> 2) - 1, /* length mask in units of u32 */
+ .log_len = 6144, /* log's buffer length in bytes */
+ .log_len_mask = (6144 >> 2) - 1, /* length mask in units of u32 */
};
struct platform_device apq8064_rpm_log_device = {
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index 2f8f547..e2a57f9 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -550,14 +550,14 @@
};
static struct msm_rpm_log_platform_data msm_rpm_log_pdata = {
- .phys_addr_base = 0x0010C000,
+ .phys_addr_base = 0x10B6A0,
.reg_offsets = {
[MSM_RPM_LOG_PAGE_INDICES] = 0x00000080,
[MSM_RPM_LOG_PAGE_BUFFER] = 0x000000A0,
},
.phys_size = SZ_8K,
- .log_len = 4096, /* log's buffer length in bytes */
- .log_len_mask = (4096 >> 2) - 1, /* length mask in units of u32 */
+ .log_len = 8192, /* log's buffer length in bytes */
+ .log_len_mask = (8192 >> 2) - 1, /* length mask in units of u32 */
};
struct platform_device msm8930_rpm_log_device = {
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index d4c33e3..837aef3 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1093,6 +1093,7 @@
.num_iommu_table = 2,
.load_table = vidc_v4l2_load_table,
.num_load_table = 2,
+ .max_load = 800*480*30/256,
};
struct platform_device msm_device_vidc_v4l2 = {
@@ -3960,8 +3961,8 @@
[MSM_RPM_LOG_PAGE_BUFFER] = 0x000000A0,
},
.phys_size = SZ_8K,
- .log_len = 4096, /* log's buffer length in bytes */
- .log_len_mask = (4096 >> 2) - 1, /* length mask in units of u32 */
+ .log_len = 6144, /* log's buffer length in bytes */
+ .log_len_mask = (6144 >> 2) - 1, /* length mask in units of u32 */
};
struct platform_device msm8960_rpm_log_device = {
diff --git a/arch/arm/mach-msm/gdsc.c b/arch/arm/mach-msm/gdsc.c
index 6240195..e5b9d93 100644
--- a/arch/arm/mach-msm/gdsc.c
+++ b/arch/arm/mach-msm/gdsc.c
@@ -36,7 +36,7 @@
#define EN_FEW_WAIT_VAL (0x8 << 16)
#define CLK_DIS_WAIT_VAL (0x2 << 12)
-#define TIMEOUT_US 10
+#define TIMEOUT_US 100
struct gdsc {
struct regulator_dev *rdev;
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 3fa2d5e..35257b2 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -567,6 +567,8 @@
*/
int64_t **load_table;
int num_load_table;
+
+ uint32_t max_load;
};
struct vcap_platform_data {
diff --git a/arch/arm/mach-msm/include/mach/camera2.h b/arch/arm/mach-msm/include/mach/camera2.h
index b518e56..248c9b0 100644
--- a/arch/arm/mach-msm/include/mach/camera2.h
+++ b/arch/arm/mach-msm/include/mach/camera2.h
@@ -20,6 +20,7 @@
enum msm_camera_device_type_t {
MSM_CAMERA_I2C_DEVICE,
MSM_CAMERA_PLATFORM_DEVICE,
+ MSM_CAMERA_SPI_DEVICE,
};
enum msm_bus_perf_setting {
@@ -100,4 +101,39 @@
enum msm_camera_i2c_data_type data_type;
};
+struct eeprom_map_t {
+ uint32_t valid_size;
+ uint32_t addr;
+ uint32_t addr_t;
+ uint32_t data;
+ uint32_t data_t;
+ uint32_t delay;
+};
+
+struct eeprom_memory_map_t {
+ struct eeprom_map_t page;
+ struct eeprom_map_t poll;
+ struct eeprom_map_t mem;
+};
+
+struct msm_camera_power_ctrl_t {
+ struct device *dev;
+ struct msm_sensor_power_setting *power_setting;
+ uint16_t power_setting_size;
+ struct msm_camera_gpio_conf *gpio_conf;
+ struct camera_vreg_t *cam_vreg;
+ int num_vreg;
+ struct msm_camera_i2c_conf *i2c_conf;
+ struct msm_cam_clk_info *clk_info;
+ uint16_t clk_info_size;
+};
+
+struct msm_eeprom_board_info {
+ const char *eeprom_name;
+ uint16_t i2c_slaveaddr;
+ uint32_t num_blocks;
+ struct eeprom_memory_map_t *eeprom_map;
+ struct msm_camera_power_ctrl_t power_info;
+};
+
#endif
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index c5c4988..f750dc8 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -123,6 +123,24 @@
unsigned int ctx_attach_count;
};
+/**
+ * struct iommu_access_ops - Callbacks for accessing IOMMU
+ * @iommu_power_on: Turn on power to unit
+ * @iommu_power_off: Turn off power to unit
+ * @iommu_clk_on: Turn on clks to unit
+ * @iommu_clk_off: Turn off clks to unit
+ * @iommu_lock_acquire: Acquire any locks needed
+ * @iommu_lock_release: Release locks needed
+ */
+struct iommu_access_ops {
+ int (*iommu_power_on)(struct msm_iommu_drvdata *);
+ void (*iommu_power_off)(struct msm_iommu_drvdata *);
+ int (*iommu_clk_on)(struct msm_iommu_drvdata *);
+ void (*iommu_clk_off)(struct msm_iommu_drvdata *);
+ void (*iommu_lock_acquire)(void);
+ void (*iommu_lock_release)(void);
+};
+
void msm_iommu_add_drv(struct msm_iommu_drvdata *drv);
void msm_iommu_remove_drv(struct msm_iommu_drvdata *drv);
void program_iommu_bfb_settings(void __iomem *base,
@@ -241,6 +259,7 @@
* This should only be called on IOMMUs for which kernel programming
* of global registers is not possible
*/
+void msm_iommu_sec_set_access_ops(struct iommu_access_ops *access_ops);
int msm_iommu_sec_program_iommu(int sec_id);
static inline int msm_soc_version_supports_iommu_v0(void)
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index fec734a..9a89508 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -13,6 +13,7 @@
#ifndef _ARCH_IOMMU_DOMAINS_H
#define _ARCH_IOMMU_DOMAINS_H
+#include <linux/errno.h>
#include <linux/memory_alloc.h>
#define MSM_IOMMU_DOMAIN_SECURE 0x1
diff --git a/arch/arm/mach-msm/include/mach/iommu_perfmon.h b/arch/arm/mach-msm/include/mach/iommu_perfmon.h
index c03c752..dcae83b 100644
--- a/arch/arm/mach-msm/include/mach/iommu_perfmon.h
+++ b/arch/arm/mach-msm/include/mach/iommu_perfmon.h
@@ -18,20 +18,6 @@
#define MSM_IOMMU_PERFMON_H
/**
- * struct iommu_access_ops - Callbacks for accessing IOMMU
- * @iommu_power_on: Turn on clocks/power to unit
- * @iommu_power_off: Turn off clocks/power to unit
- * @iommu_lock_acquire: Acquire any locks needed
- * @iommu_lock_release: Release locks needed
- */
-struct iommu_access_ops {
- int (*iommu_power_on)(void *);
- int (*iommu_power_off)(void *);
- void (*iommu_lock_acquire)(void);
- void (*iommu_lock_release)(void);
-};
-
-/**
* struct iommu_pmon_counter - container for a performance counter.
* @counter_no: counter number within the group
* @absolute_counter_no: counter number within IOMMU PMU
diff --git a/arch/arm/mach-msm/include/mach/msm_bus.h b/arch/arm/mach-msm/include/mach/msm_bus.h
index 049cf02..ebc43da 100644
--- a/arch/arm/mach-msm/include/mach/msm_bus.h
+++ b/arch/arm/mach-msm/include/mach/msm_bus.h
@@ -112,6 +112,8 @@
#endif
#if defined(CONFIG_OF) && defined(CONFIG_MSM_BUS_SCALING)
+struct msm_bus_scale_pdata *msm_bus_pdata_from_node(
+ struct platform_device *pdev, struct device_node *of_node);
struct msm_bus_scale_pdata *msm_bus_cl_get_pdata(struct platform_device *pdev);
void msm_bus_cl_clear_pdata(struct msm_bus_scale_pdata *pdata);
#else
@@ -121,6 +123,12 @@
return NULL;
}
+static inline struct msm_bus_scale_pdata *msm_bus_pdata_from_node(
+ struct platform_device *pdev, struct device_node *of_node)
+{
+ return NULL;
+}
+
static inline void msm_bus_cl_clear_pdata(struct msm_bus_scale_pdata *pdata)
{
}
diff --git a/arch/arm/mach-msm/include/mach/msm_subsystem_map.h b/arch/arm/mach-msm/include/mach/msm_subsystem_map.h
deleted file mode 100644
index 3119023..0000000
--- a/arch/arm/mach-msm/include/mach/msm_subsystem_map.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2011, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-#ifndef __ARCH_MACH_MSM_SUBSYSTEM_MAP_H
-#define __ARCH_MACH_MSM_SUBSYSTEM_MAP_H
-
-#include <linux/iommu.h>
-#include <mach/iommu_domains.h>
-
-/* map the physical address in the kernel vaddr space */
-#define MSM_SUBSYSTEM_MAP_KADDR 0x1
-/* map the physical address in the iova address space */
-#define MSM_SUBSYSTEM_MAP_IOVA 0x2
-/* ioremaps in the kernel address space are cached */
-#define MSM_SUBSYSTEM_MAP_CACHED 0x4
-/* ioremaps in the kernel address space are uncached */
-#define MSM_SUBSYSTEM_MAP_UNCACHED 0x8
-/*
- * Will map 2x the length requested.
- */
-#define MSM_SUBSYSTEM_MAP_IOMMU_2X 0x10
-
-/*
- * Shortcut flags for alignment.
- * The flag must be equal to the alignment requested.
- * e.g. for 8k alignment the flags must be (0x2000 | other flags)
- */
-#define MSM_SUBSYSTEM_ALIGN_IOVA_8K SZ_8K
-#define MSM_SUBSYSTEM_ALIGN_IOVA_1M SZ_1M
-
-
-enum msm_subsystem_id {
- INVALID_SUBSYS_ID = -1,
- MSM_SUBSYSTEM_VIDEO,
- MSM_SUBSYSTEM_VIDEO_FWARE,
- MSM_SUBSYSTEM_CAMERA,
- MSM_SUBSYSTEM_DISPLAY,
- MSM_SUBSYSTEM_ROTATOR,
- MAX_SUBSYSTEM_ID
-};
-
-static inline int msm_subsystem_check_id(int subsys_id)
-{
- return subsys_id > INVALID_SUBSYS_ID && subsys_id < MAX_SUBSYSTEM_ID;
-}
-
-struct msm_mapped_buffer {
- /*
- * VA mapped in the kernel address space. This field shall be NULL if
- * MSM_SUBSYSTEM_MAP_KADDR was not passed to the map buffer function.
- */
- void *vaddr;
- /*
- * iovas mapped in the iommu address space. The ith entry of this array
- * corresponds to the iova mapped in the ith subsystem in the array
- * pased in to msm_subsystem_map_buffer. This field shall be NULL if
- * MSM_SUBSYSTEM_MAP_IOVA was not passed to the map buffer function,
- */
- unsigned long *iova;
-};
-
-extern struct msm_mapped_buffer *msm_subsystem_map_buffer(
- unsigned long phys,
- unsigned int length,
- unsigned int flags,
- int *subsys_ids,
- unsigned int nsubsys);
-
-extern int msm_subsystem_unmap_buffer(struct msm_mapped_buffer *buf);
-
-extern phys_addr_t msm_subsystem_check_iova_mapping(int subsys_id,
- unsigned long iova);
-
-#endif /* __ARCH_MACH_MSM_SUBSYSTEM_MAP_H */
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h b/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h
index ea345fb..91e4ef1 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/q6core.h
@@ -53,10 +53,19 @@
uint8_t model_ID[128];
};
+#define ADSP_CMD_SET_DOLBY_MANUFACTURER_ID 0x00012918
+
+struct adsp_dolby_manufacturer_id {
+ struct apr_hdr hdr;
+ int manufacturer_id;
+};
+
int core_req_bus_bandwith(u16 bus_id, u32 ab_bps, u32 ib_bps);
uint32_t core_get_adsp_version(void);
uint32_t core_set_dts_model_id(uint32_t id_size, uint8_t *id);
+uint32_t core_set_dolby_manufacturer_id(int manufacturer_id);
+
#endif /* __Q6CORE_H__ */
diff --git a/arch/arm/mach-msm/include/mach/qseecomi.h b/arch/arm/mach-msm/include/mach/qseecomi.h
index 3a13af8..20dc851 100644
--- a/arch/arm/mach-msm/include/mach/qseecomi.h
+++ b/arch/arm/mach-msm/include/mach/qseecomi.h
@@ -16,6 +16,8 @@
#include <linux/qseecom.h>
+#define QSEECOM_KEY_ID_SIZE 32
+
enum qseecom_command_scm_resp_type {
QSEOS_APP_ID = 0xEE01,
QSEOS_LISTENER_ID
@@ -36,6 +38,8 @@
QSEOS_UNLOAD_SERV_IMAGE_COMMAND,
QSEOS_APP_REGION_NOTIFICATION,
QSEOS_REGISTER_LOG_BUF_COMMAND,
+ QSEE_RPMB_PROVISION_KEY_COMMAND,
+ QSEE_RPMB_ERASE_COMMAND,
QSEOS_CMD_MAX = 0xEFFFFFFF
};
@@ -127,4 +131,57 @@
unsigned int data;
};
+struct qseecom_rpmb_provision_key {
+ uint32_t key_type;
+};
+
+__packed struct qseecom_client_send_service_ireq {
+ uint32_t qsee_cmd_id;
+ uint32_t key_type; /* in */
+ unsigned int req_len; /* in */
+ void *rsp_ptr; /* in/out */
+ unsigned int rsp_len; /* in/out */
+};
+
+/* Key Management requests */
+enum qseecom_qceos_key_gen_cmd_id {
+ QSEOS_GENERATE_KEY = 0x02,
+ QSEOS_SET_KEY,
+ QSEOS_DELETE_KEY,
+ QSEOS_MAX_KEY_COUNT,
+ QSEOS_KEY_CMD_MAX = 0xEFFFFFFF
+};
+
+__packed struct qseecom_key_generate_ireq {
+ uint32_t flags;
+ uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+};
+
+__packed struct qseecom_key_select_ireq {
+ uint32_t ce;
+ uint32_t pipe;
+ uint32_t flags;
+ uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+ unsigned char hash[QSEECOM_HASH_SIZE];
+};
+
+__packed struct qseecom_key_delete_ireq {
+ uint32_t flags;
+ uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+};
+
+__packed struct qseecom_key_max_count_query_ireq {
+ uint32_t flags;
+};
+
+__packed struct qseecom_key_max_count_query_irsp {
+ uint32_t max_key_count;
+};
+
+struct key_id_info {
+ uint32_t ce_hw;
+ uint32_t pipe;
+ bool flags;
+};
+
#endif /* __QSEECOMI_H_ */
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator-smd.h b/arch/arm/mach-msm/include/mach/rpm-regulator-smd.h
index 9e70510..cfe8ae7 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator-smd.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator-smd.h
@@ -38,6 +38,32 @@
RPM_REGULATOR_CORNER_SUPER_TURBO,
};
+/**
+ * enum rpm_regulator_mode - control mode for LDO or SMPS type regulators
+ * %RPM_REGULATOR_MODE_AUTO: For SMPS type regulators, use SMPS auto mode so
+ * that the hardware can automatically switch
+ * between PFM and PWM modes based on realtime
+ * load.
+ * LDO type regulators do not support this mode.
+ * %RPM_REGULATOR_MODE_IPEAK: For SMPS type regulators, use aggregated
+ * software current requests to determine
+ * usage of PFM or PWM mode.
+ * For LDO type regulators, use aggregated
+ * software current requests to determine
+ * usage of LPM or HPM mode.
+ * %RPM_REGULATOR_MODE_HPM: For SMPS type regulators, force the
+ * usage of PWM mode.
+ * For LDO type regulators, force the
+ * usage of HPM mode.
+ *
+ * These values should be used in calls to rpm_regulator_set_mode().
+ */
+enum rpm_regulator_mode {
+ RPM_REGULATOR_MODE_AUTO,
+ RPM_REGULATOR_MODE_IPEAK,
+ RPM_REGULATOR_MODE_HPM,
+};
+
#if defined(CONFIG_MSM_RPM_REGULATOR_SMD) || defined(CONFIG_MSM_RPM_REGULATOR)
struct rpm_regulator *rpm_regulator_get(struct device *dev, const char *supply);
@@ -71,6 +97,14 @@
static inline int __init rpm_regulator_smd_driver_init(void) { return 0; }
-#endif /* CONFIG_MSM_RPM_REGULATOR_SMD */
+#endif /* CONFIG_MSM_RPM_REGULATOR_SMD || CONFIG_MSM_RPM_REGULATOR */
+
+#ifdef CONFIG_MSM_RPM_REGULATOR_SMD
+int rpm_regulator_set_mode(struct rpm_regulator *regulator,
+ enum rpm_regulator_mode mode);
+#else
+static inline int rpm_regulator_set_mode(struct rpm_regulator *regulator,
+ enum rpm_regulator_mode mode) { return 0; }
+#endif
#endif
diff --git a/arch/arm/mach-msm/include/mach/scm.h b/arch/arm/mach-msm/include/mach/scm.h
index 0cc7bbf..4258dbd 100644
--- a/arch/arm/mach-msm/include/mach/scm.h
+++ b/arch/arm/mach-msm/include/mach/scm.h
@@ -22,6 +22,7 @@
#define SCM_SVC_FUSE 0x8
#define SCM_SVC_PWR 0x9
#define SCM_SVC_MP 0xC
+#define SCM_SVC_CRYPTO 0xA
#define SCM_SVC_DCVS 0xD
#define SCM_SVC_TZSCHEDULER 0xFC
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 45f2646..b898fe8 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -32,77 +32,36 @@
#define SOCINFO_VERSION_MINOR(ver) (ver & 0x0000ffff)
#ifdef CONFIG_OF
-#define early_machine_is_msm8974() \
- of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8974")
-#define machine_is_msm8974() \
- of_machine_is_compatible("qcom,msm8974")
-#define machine_is_msm8974_sim() \
- of_machine_is_compatible("qcom,msm8974-sim")
-#define machine_is_msm8974_rumi() \
- of_machine_is_compatible("qcom,msm8974-rumi")
-#define machine_is_msm8974_fluid() \
- of_machine_is_compatible("qcom,msm8974-fluid")
-#define early_machine_is_msm9625() \
- of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm9625")
-#define machine_is_msm9625() \
- of_machine_is_compatible("qcom,msm9625")
-#define early_machine_is_mpq8092() \
- of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,mpq8092")
-#define machine_is_mpq8092_sim() \
- of_machine_is_compatible("qcom,mpq8092-sim")
-#define early_machine_is_msm8226() \
- of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8226")
-#define machine_is_msm8226() \
- of_machine_is_compatible("qcom,msm8226")
-#define machine_is_msm8226_sim() \
- of_machine_is_compatible("qcom,msm8226-sim")
-#define machine_is_msm8226_rumi() \
- of_machine_is_compatible("qcom,msm8226-rumi")
-#define machine_is_msm8226_cdp() \
- of_machine_is_compatible("qcom,msm8226-cdp")
-#define machine_is_msm8226_fluid() \
- of_machine_is_compatible("qcom,msm8226-fluid")
-#define machine_is_msm8226_mtp() \
- of_machine_is_compatible("qcom,msm8226-mtp")
-#define machine_is_msm8226_qrd() \
- of_machine_is_compatible("qcom,msm8226-qrd")
+#define of_board_is_sim() of_machine_is_compatible("qcom,sim")
+#define of_board_is_rumi() of_machine_is_compatible("qcom,rumi")
+#define of_board_is_fluid() of_machine_is_compatible("qcom,fluid")
+#define of_board_is_liquid() of_machine_is_compatible("qcom,liquid")
+
+#define machine_is_msm8974() of_machine_is_compatible("qcom,msm8974")
+#define machine_is_msm9625() of_machine_is_compatible("qcom,msm9625")
+#define machine_is_msm8610() of_machine_is_compatible("qcom,msm8610")
+#define machine_is_msm8226() of_machine_is_compatible("qcom,msm8226")
+
#define early_machine_is_msm8610() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8610")
-#define machine_is_msm8610() \
- of_machine_is_compatible("qcom,msm8610")
-#define machine_is_msm8610_sim() \
- of_machine_is_compatible("qcom,msm8610-sim")
-#define machine_is_msm8610_rumi() \
- of_machine_is_compatible("qcom,msm8610-rumi")
-#define machine_is_msm8610_mtp() \
- of_machine_is_compatible("qcom,msm8610-mtp")
-#define machine_is_msm8610_cdp() \
- of_machine_is_compatible("qcom,msm8610-cdp")
+#define early_machine_is_mpq8092() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,mpq8092")
#define early_machine_is_msmzinc() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msmzinc")
-#define machine_is_msmzinc_sim() \
- of_machine_is_compatible("qcom,msmzinc-sim")
#else
-#define early_machine_is_msm8974() 0
-#define machine_is_msm8974() 0
-#define machine_is_msm8974_sim() 0
-#define machine_is_msm8974_rumi() 0
-#define machine_is_msm8974_fluid() 0
-#define early_machine_is_msm9625() 0
-#define machine_is_msm9625() 0
-#define early_machine_is_mpq8092() 0
-#define machine_is_mpq8092_sim() 0
-#define early_machine_is_msm8226() 0
-#define machine_is_msm8226() 0
-#define machine_is_msm8226_sim() 0
-#define machine_is_msm8226_rumi() 0
-#define early_machine_is_msm8610() 0
-#define machine_is_msm8610() 0
-#define machine_is_msm8610_sim() 0
-#define machine_is_msm8610_rumi() 0
-#define early_machine_is_msmzinc() 0
-#define machine_is_msmzinc_sim() 0
+#define of_board_is_sim() 0
+#define of_board_is_rumi() 0
+#define of_board_is_fluid() 0
+#define of_board_is_liquid() 0
+#define machine_is_msm8974() 0
+#define machine_is_msm9625() 0
+#define machine_is_msm8610() 0
+#define machine_is_msm8226() 0
+
+#define early_machine_is_msm8610() 0
+#define early_machine_is_mpq8092() 0
+#define early_machine_is_msmzinc() 0
#endif
#define PLATFORM_SUBTYPE_SGLTE 6
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index cf59dd8..662655b 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -146,6 +146,8 @@
SPS_O_WRITE_NWD = 0x00040000,
/* Options to enable software features */
+ /* Do not disable a pipe during disconnection */
+ SPS_O_NO_DISABLE = 0x00800000,
/* Transfer operation should be polled */
SPS_O_POLL = 0x01000000,
/* Disable queuing of transfer events for the connection end point */
@@ -1261,7 +1263,7 @@
*
*/
int sps_get_bam_debug_info(u32 dev, u32 option, u32 para,
- u32 tb_sel, u8 desc_sel);
+ u32 tb_sel, u32 desc_sel);
#else
static inline int sps_register_bam_device(const struct sps_bam_props
@@ -1421,7 +1423,7 @@
}
static inline int sps_get_bam_debug_info(u32 dev, u32 option, u32 para,
- u32 tb_sel, u8 pre_level)
+ u32 tb_sel, u32 desc_sel)
{
return -EPERM;
}
diff --git a/arch/arm/mach-msm/include/mach/usb_bam.h b/arch/arm/mach-msm/include/mach/usb_bam.h
index 5a77d99..68313c5 100644
--- a/arch/arm/mach-msm/include/mach/usb_bam.h
+++ b/arch/arm/mach-msm/include/mach/usb_bam.h
@@ -39,6 +39,7 @@
SPS_PIPE_MEM = 0, /* Default, SPS dedicated pipe memory */
USB_PRIVATE_MEM, /* USB's private memory */
SYSTEM_MEM, /* System RAM, requires allocation */
+ OCI_MEM, /* Shared memory among peripherals */
};
struct usb_bam_connect_ipa_params {
@@ -119,7 +120,9 @@
* @connections: holds all pipe connections data.
* @usb_bam_num_pipes: max number of pipes to use.
* @active_conn_num: number of active pipe connections.
- * @usb_base_address: BAM physical address.
+ * @usb_bam_fifo_baseaddr: base address for bam pipe's data and descriptor
+ * fifos. This can be on chip memory (ocimem) or usb
+ * private memory.
* @ignore_core_reset_ack: BAM can ignore ACK from USB core during PIPE RESET
* @disable_clk_gating: Disable clock gating
*/
@@ -127,7 +130,7 @@
struct usb_bam_pipe_connect *connections;
u8 max_connections;
int usb_bam_num_pipes;
- u32 usb_base_address;
+ phys_addr_t usb_bam_fifo_baseaddr;
bool ignore_core_reset_ack;
bool reset_on_connect[MAX_BAMS];
bool disable_clk_gating;
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index a837ca1..18562a3 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -27,7 +27,6 @@
#include <mach/iommu_domains.h>
#include <mach/msm_iommu_priv.h>
#include <mach/socinfo.h>
-#include <mach/msm_subsystem_map.h>
struct msm_iova_data {
struct rb_node node;
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index f40bd5d..c0422a1 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -194,7 +194,7 @@
static int msm_ipc_router_extract_msg(struct msghdr *m,
struct sk_buff_head *msg_head)
{
- struct sockaddr_msm_ipc *addr = (struct sockaddr_msm_ipc *)m->msg_name;
+ struct sockaddr_msm_ipc *addr;
struct rr_header *hdr;
struct sk_buff *temp;
int offset = 0, data_len = 0, copy_len;
@@ -203,10 +203,11 @@
pr_err("%s: Invalid pointers passed\n", __func__);
return -EINVAL;
}
+ addr = (struct sockaddr_msm_ipc *)m->msg_name;
temp = skb_peek(msg_head);
hdr = (struct rr_header *)(temp->data);
- if (addr || (hdr->src_port_id != IPC_ROUTER_ADDRESS)) {
+ if (addr && (hdr->src_port_id != IPC_ROUTER_ADDRESS)) {
addr->family = AF_MSM_IPC;
addr->address.addrtype = MSM_IPC_ADDR_ID;
addr->address.addr.port_addr.node_id = hdr->src_node_id;
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_of.c b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
index 489eb5c..b9a553a 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_of.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_of.c
@@ -42,20 +42,9 @@
return -EINVAL;
}
-/**
- * msm_bus_cl_get_pdata() - Generate bus client data from device tree
- * provided by clients.
- *
- * of_node: Device tree node to extract information from
- *
- * The function returns a valid pointer to the allocated bus-scale-pdata
- * if the vectors were correctly read from the client's device node.
- * Any error in reading or parsing the device node will return NULL
- * to the caller.
- */
-struct msm_bus_scale_pdata *msm_bus_cl_get_pdata(struct platform_device *pdev)
+static struct msm_bus_scale_pdata *get_pdata(struct platform_device *pdev,
+ struct device_node *of_node)
{
- struct device_node *of_node;
struct msm_bus_scale_pdata *pdata = NULL;
struct msm_bus_paths *usecase = NULL;
int i = 0, j, ret, num_usecases = 0, num_paths, len;
@@ -67,7 +56,6 @@
return NULL;
}
- of_node = pdev->dev.of_node;
pdata = devm_kzalloc(&pdev->dev, sizeof(struct msm_bus_scale_pdata),
GFP_KERNEL);
if (!pdata) {
@@ -154,9 +142,81 @@
return NULL;
}
+
+/**
+ * msm_bus_cl_get_pdata() - Generate bus client data from device tree
+ * provided by clients.
+ *
+ * of_node: Device tree node to extract information from
+ *
+ * The function returns a valid pointer to the allocated bus-scale-pdata
+ * if the vectors were correctly read from the client's device node.
+ * Any error in reading or parsing the device node will return NULL
+ * to the caller.
+ */
+struct msm_bus_scale_pdata *msm_bus_cl_get_pdata(struct platform_device *pdev)
+{
+ struct device_node *of_node;
+ struct msm_bus_scale_pdata *pdata = NULL;
+
+ if (!pdev) {
+ pr_err("Error: Null Platform device\n");
+ return NULL;
+ }
+
+ of_node = pdev->dev.of_node;
+ pdata = get_pdata(pdev, of_node);
+ if (!pdata) {
+ pr_err("Error getting bus pdata!\n");
+ return NULL;
+ }
+
+ return pdata;
+}
EXPORT_SYMBOL(msm_bus_cl_get_pdata);
/**
+ * msm_bus_cl_pdata_from_node() - Generate bus client data from device tree
+ * node provided by clients. This function should be used when a client
+ * driver needs to register multiple bus-clients from a single device-tree
+ * node associated with the platform-device.
+ *
+ * of_node: The subnode containing information about the bus scaling
+ * data
+ *
+ * pdev: Platform device associated with the device-tree node
+ *
+ * The function returns a valid pointer to the allocated bus-scale-pdata
+ * if the vectors were correctly read from the client's device node.
+ * Any error in reading or parsing the device node will return NULL
+ * to the caller.
+ */
+struct msm_bus_scale_pdata *msm_bus_pdata_from_node(
+ struct platform_device *pdev, struct device_node *of_node)
+{
+ struct msm_bus_scale_pdata *pdata = NULL;
+
+ if (!pdev) {
+ pr_err("Error: Null Platform device\n");
+ return NULL;
+ }
+
+ if (!of_node) {
+ pr_err("Error: Null of_node passed to bus driver\n");
+ return NULL;
+ }
+
+ pdata = get_pdata(pdev, of_node);
+ if (!pdata) {
+ pr_err("Error getting bus pdata!\n");
+ return NULL;
+ }
+
+ return pdata;
+}
+EXPORT_SYMBOL(msm_bus_pdata_from_node);
+
+/**
* msm_bus_cl_clear_pdata() - Clear pdata allocated from device-tree
* of_node: Device tree node to extract information from
*/
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index 868fd1a..8afe695 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -377,6 +377,7 @@
static int destroy_region(struct ocmem_region *region)
{
+ idr_destroy(®ion->region_idr);
kfree(region);
return 0;
}
diff --git a/arch/arm/mach-msm/perf_debug.c b/arch/arm/mach-msm/perf_debug.c
index 7f2f528..5bf88a2 100644
--- a/arch/arm/mach-msm/perf_debug.c
+++ b/arch/arm/mach-msm/perf_debug.c
@@ -28,6 +28,8 @@
"3 Perf: Correct irq for CPU hotplug detection\n"
"4 Perf: Check perf activity on correct CPU\n"
"5 Perf: Add DT support for L1 and L2 PMU\n"
+ "6 Perf: Add cortex A5 device tree support\n"
+ "7 Perf: Add L1 counters to tracepoints\n"
;
static ssize_t desc_read(struct file *fp, char __user *buf,
diff --git a/arch/arm/mach-msm/perf_trace_counters.c b/arch/arm/mach-msm/perf_trace_counters.c
new file mode 100644
index 0000000..d961994
--- /dev/null
+++ b/arch/arm/mach-msm/perf_trace_counters.c
@@ -0,0 +1,42 @@
+/* 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 <asm/thread_notify.h>
+#define CREATE_TRACE_POINTS
+#include "perf_trace_counters.h"
+
+static int tracectr_notifier(struct notifier_block *self, unsigned long cmd,
+ void *v)
+{
+ static int old_pid = -1;
+ struct thread_info *thread = v;
+ int current_pid;
+
+ if (cmd != THREAD_NOTIFY_SWITCH)
+ return old_pid;
+
+ current_pid = thread->task->pid;
+ if (old_pid != -1)
+ trace_sched_switch_with_ctrs(old_pid, current_pid);
+ old_pid = current_pid;
+ return old_pid;
+}
+
+static struct notifier_block tracectr_notifier_block = {
+ .notifier_call = tracectr_notifier,
+};
+
+int __init init_tracecounters(void)
+{
+ thread_register_notifier(&tracectr_notifier_block);
+ return 0;
+}
+late_initcall(init_tracecounters);
diff --git a/arch/arm/mach-msm/perf_trace_counters.h b/arch/arm/mach-msm/perf_trace_counters.h
new file mode 100644
index 0000000..ce7e336
--- /dev/null
+++ b/arch/arm/mach-msm/perf_trace_counters.h
@@ -0,0 +1,127 @@
+/* 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.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM perf_trace_counters
+
+#if !defined(_PERF_TRACE_COUNTERS_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _PERF_TRACE_COUNTERS_H_
+
+/* Ctr index for PMCNTENSET/CLR */
+#define CC 0x80000000
+#define C0 0x1
+#define C1 0x10
+#define C2 0x100
+#define C3 0x1000
+
+
+#include <linux/sched.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(sched_switch_with_ctrs,
+
+ TP_PROTO(pid_t prev, pid_t next),
+
+ TP_ARGS(prev, next),
+
+ TP_STRUCT__entry(
+ __field(pid_t, old_pid)
+ __field(pid_t, new_pid)
+ __field(u32, cctr)
+ __field(u32, ctr0)
+ __field(u32, ctr1)
+ __field(u32, ctr2)
+ __field(u32, ctr3)
+ ),
+
+ TP_fast_assign(
+ __entry->old_pid = prev;
+ __entry->new_pid = next;
+
+ /* cycle counter */
+ /* Disable */
+ asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(CC));
+ /* Read value */
+ asm volatile("mrc p15, 0, %0, c9, c13, 0"
+ : "=r"(__entry->cctr));
+ /* Reset */
+ asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r"(0));
+ /* Enable */
+ asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(CC));
+
+ /* ctr 0 */
+ /* Disable */
+ asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(C0));
+ /* Select */
+ asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(0));
+ /* Read value */
+ asm volatile("mrc p15, 0, %0, c9, c13, 2"
+ : "=r"(__entry->ctr0));
+ /* Reset */
+ asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r"(0));
+ /* Enable */
+ asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(C0));
+
+ /* ctr 1 */
+ /* Disable */
+ asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(C1));
+ /* Select */
+ asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(1));
+ /* Read value */
+ asm volatile("mrc p15, 0, %0, c9, c13, 2"
+ : "=r"(__entry->ctr1));
+ /* Reset */
+ asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r"(0));
+ /* Enable */
+ asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(C1));
+
+ /* ctr 2 */
+ /* Disable */
+ asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(C2));
+ /* Select */
+ asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(2));
+ /* Read value */
+ asm volatile("mrc p15, 0, %0, c9, c13, 2"
+ : "=r"(__entry->ctr2));
+ /* Reset */
+ asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r"(0));
+ /* Enable */
+ asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(C2));
+
+ /* ctr 3 */
+ /* Disable */
+ asm volatile("mcr p15, 0, %0, c9, c12, 2" : : "r"(C3));
+ /* Select */
+ asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r"(3));
+ /* Read value */
+ asm volatile("mrc p15, 0, %0, c9, c13, 2"
+ : "=r"(__entry->ctr3));
+ /* Reset */
+ asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r"(0));
+ /* Enable */
+ asm volatile("mcr p15, 0, %0, c9, c12, 1" : : "r"(C3));
+
+ ),
+
+ TP_printk("prev_pid=%d, next_pid=%d, CCNTR: %u, CTR0: %u," \
+ " CTR1: %u, CTR2: %u, CTR3: %u",
+ __entry->old_pid, __entry->new_pid,
+ __entry->cctr, __entry->ctr0, __entry->ctr1,
+ __entry->ctr2, __entry->ctr3)
+);
+
+#endif
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE perf_trace_counters
+#include <trace/define_trace.h>
+
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 958edaf..4e8674c 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -29,6 +29,7 @@
#include <linux/list.h>
#include <linux/list_sort.h>
#include <linux/idr.h>
+#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include <asm/setup.h>
@@ -226,10 +227,21 @@
if (immediate)
timeout = 0;
- schedule_delayed_work(&priv->proxy, msecs_to_jiffies(timeout));
+
+ if (!desc->proxy_unvote_irq || immediate)
+ schedule_delayed_work(&priv->proxy,
+ msecs_to_jiffies(timeout));
}
}
+static irqreturn_t proxy_unvote_intr_handler(int irq, void *dev_id)
+{
+ struct pil_desc *desc = dev_id;
+
+ schedule_delayed_work(&desc->priv->proxy, 0);
+ return IRQ_HANDLED;
+}
+
static bool segment_is_relocatable(const struct elf32_phdr *p)
{
return !!(p->p_flags & BIT(27));
@@ -685,13 +697,16 @@
int pil_desc_init(struct pil_desc *desc)
{
struct pil_priv *priv;
- int id;
+ int ret;
void __iomem *addr;
char buf[sizeof(priv->info->name)];
/* Ignore users who don't make any sense */
- WARN(desc->ops->proxy_unvote && !desc->proxy_timeout,
- "A proxy timeout of 0 was specified.\n");
+ WARN(desc->ops->proxy_unvote && desc->proxy_unvote_irq == 0
+ && !desc->proxy_timeout,
+ "Invalid proxy unvote callback or a proxy timeout of 0"
+ " was specified or no proxy unvote IRQ was specified.\n");
+
if (WARN(desc->ops->proxy_unvote && !desc->ops->proxy_vote,
"Invalid proxy voting. Ignoring\n"))
((struct pil_reset_ops *)desc->ops)->proxy_unvote = NULL;
@@ -702,23 +717,38 @@
desc->priv = priv;
priv->desc = desc;
- priv->id = id = ida_simple_get(&pil_ida, 0, 10, GFP_KERNEL);
- if (id < 0) {
- kfree(priv);
- return id;
- }
- addr = PIL_IMAGE_INFO_BASE + sizeof(struct pil_image_info) * id;
+ priv->id = ret = ida_simple_get(&pil_ida, 0, 10, GFP_KERNEL);
+ if (priv->id < 0)
+ goto err;
+
+ addr = PIL_IMAGE_INFO_BASE + sizeof(struct pil_image_info) * priv->id;
priv->info = (struct pil_image_info __iomem *)addr;
strncpy(buf, desc->name, sizeof(buf));
__iowrite32_copy(priv->info->name, buf, sizeof(buf) / 4);
+ if (desc->proxy_unvote_irq > 0) {
+ ret = request_irq(desc->proxy_unvote_irq,
+ proxy_unvote_intr_handler,
+ IRQF_TRIGGER_RISING|IRQF_SHARED,
+ desc->name, desc);
+ if (ret < 0) {
+ dev_err(desc->dev,
+ "Unable to request proxy unvote IRQ: %d\n",
+ ret);
+ goto err;
+ }
+ }
+
snprintf(priv->wname, sizeof(priv->wname), "pil-%s", desc->name);
wake_lock_init(&priv->wlock, WAKE_LOCK_SUSPEND, priv->wname);
INIT_DELAYED_WORK(&priv->proxy, pil_proxy_work);
INIT_LIST_HEAD(&priv->segs);
return 0;
+err:
+ kfree(priv);
+ return ret;
}
EXPORT_SYMBOL(pil_desc_init);
diff --git a/arch/arm/mach-msm/peripheral-loader.h b/arch/arm/mach-msm/peripheral-loader.h
index c1a4167..ff10fe5 100644
--- a/arch/arm/mach-msm/peripheral-loader.h
+++ b/arch/arm/mach-msm/peripheral-loader.h
@@ -25,6 +25,8 @@
* @proxy_timeout: delay in ms until proxy vote is removed
* @flags: bitfield for image flags
* @priv: DON'T USE - internal only
+ * @proxy_unvote_irq: IRQ to trigger a proxy unvote. proxy_timeout
+ * is ignored if this is set.
*/
struct pil_desc {
const char *name;
@@ -35,6 +37,7 @@
unsigned long flags;
#define PIL_SKIP_ENTRY_CHECK BIT(0)
struct pil_priv *priv;
+ unsigned int proxy_unvote_irq;
};
/**
diff --git a/arch/arm/mach-msm/pil-pronto.c b/arch/arm/mach-msm/pil-pronto.c
index 6bd087c..edaa60c 100644
--- a/arch/arm/mach-msm/pil-pronto.c
+++ b/arch/arm/mach-msm/pil-pronto.c
@@ -25,6 +25,7 @@
#include <linux/jiffies.h>
#include <linux/workqueue.h>
#include <linux/wcnss_wlan.h>
+#include <linux/of_gpio.h>
#include <mach/subsystem_restart.h>
#include <mach/msm_smsm.h>
@@ -82,6 +83,8 @@
bool crash;
struct delayed_work cancel_vote_work;
int irq;
+ unsigned int err_fatal_irq;
+ int force_stop_gpio;
struct ramdump_device *ramdump_dev;
};
@@ -302,25 +305,22 @@
subsystem_restart_dev(drv->subsys);
}
-static void smsm_state_cb_hdlr(void *data, uint32_t old_state,
- uint32_t new_state)
+static irqreturn_t wcnss_err_fatal_intr_handler(int irq, void *dev_id)
{
- struct pronto_data *drv = data;
+ struct pronto_data *drv = dev_id;
+
+ pr_err("Fatal error on the wcnss.\n");
drv->crash = true;
-
- pr_err("wcnss smsm state changed\n");
-
- if (!(new_state & SMSM_RESET))
- return;
-
if (drv->restart_inprogress) {
- pr_err("wcnss: Ignoring smsm reset req, restart in progress\n");
- return;
+ pr_err("wcnss: Ignoring error fatal, restart in progress\n");
+ return IRQ_HANDLED;
}
drv->restart_inprogress = true;
restart_wcnss(drv);
+
+ return IRQ_HANDLED;
}
static irqreturn_t wcnss_wdog_bite_irq_hdlr(int irq, void *dev_id)
@@ -389,7 +389,7 @@
pr_err("wcnss crash shutdown %d\n", drv->crash);
if (!drv->crash)
- smsm_change_state(SMSM_APPS_STATE, SMSM_RESET, SMSM_RESET);
+ gpio_set_value(drv->force_stop_gpio, 1);
}
static int wcnss_ramdump(int enable, const struct subsys_desc *subsys)
@@ -407,7 +407,7 @@
struct pronto_data *drv;
struct resource *res;
struct pil_desc *desc;
- int ret;
+ int ret, err_fatal_gpio, irq;
uint32_t regval;
drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
@@ -440,6 +440,23 @@
if (ret)
return ret;
+ err_fatal_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,gpio-err-fatal", 0);
+ if (err_fatal_gpio < 0)
+ return err_fatal_gpio;
+
+ irq = gpio_to_irq(err_fatal_gpio);
+ if (irq < 0)
+ return irq;
+
+ drv->err_fatal_irq = irq;
+
+ drv->force_stop_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,gpio-force-stop", 0);
+ if (drv->force_stop_gpio < 0)
+ return drv->force_stop_gpio;
+
+
desc->dev = &pdev->dev;
desc->owner = THIS_MODULE;
desc->proxy_timeout = 10000;
@@ -478,11 +495,6 @@
if (ret)
return ret;
- ret = smsm_state_cb_register(SMSM_WCNSS_STATE, SMSM_RESET,
- smsm_state_cb_hdlr, drv);
- if (ret < 0)
- goto err_smsm;
-
drv->subsys_desc.name = desc->name;
drv->subsys_desc.dev = &pdev->dev;
drv->subsys_desc.owner = THIS_MODULE;
@@ -506,6 +518,14 @@
if (ret < 0)
goto err_irq;
+ ret = devm_request_irq(&pdev->dev, drv->err_fatal_irq,
+ wcnss_err_fatal_intr_handler,
+ IRQF_TRIGGER_RISING, "pil-pronto", drv);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Unable to register SMP2P err fatal handler!\n");
+ goto err_irq;
+ }
+
drv->ramdump_dev = create_ramdump_device("pronto", &pdev->dev);
if (!drv->ramdump_dev) {
ret = -ENOMEM;
@@ -520,12 +540,10 @@
writel_relaxed(regval, drv->base + PRONTO_PMU_COMMON_GDSCR);
return 0;
+
err_irq:
subsys_unregister(drv->subsys);
err_subsys:
- smsm_state_cb_deregister(SMSM_WCNSS_STATE, SMSM_RESET,
- smsm_state_cb_hdlr, drv);
-err_smsm:
pil_desc_release(desc);
return ret;
}
@@ -534,8 +552,6 @@
{
struct pronto_data *drv = platform_get_drvdata(pdev);
subsys_unregister(drv->subsys);
- smsm_state_cb_deregister(SMSM_WCNSS_STATE, SMSM_RESET,
- smsm_state_cb_hdlr, drv);
pil_desc_release(&drv->desc);
destroy_ramdump_device(drv->ramdump_dev);
return 0;
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index bc40130..f4ca4e3 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -282,10 +282,9 @@
pr_debug("Starting secondary CPU %d\n", cpu);
if (per_cpu(cold_boot_done, cpu) == false) {
- if (machine_is_msm8974_sim() || machine_is_mpq8092_sim())
+ if (of_board_is_sim())
release_secondary_sim(0xf9088000, cpu);
- else if (!machine_is_msm8974_rumi() &&
- !machine_is_msmzinc_sim())
+ else if (!of_board_is_rumi())
msm8974_release_secondary(0xf9088000, cpu);
per_cpu(cold_boot_done, cpu) = true;
@@ -298,9 +297,9 @@
pr_debug("Starting secondary CPU %d\n", cpu);
if (per_cpu(cold_boot_done, cpu) == false) {
- if (machine_is_msm8226_sim() || machine_is_msm8610_sim())
+ if (of_board_is_sim())
release_secondary_sim(0xf9088000, cpu);
- else if (!machine_is_msm8610_rumi())
+ else if (!of_board_is_rumi())
arm_release_secondary(0xf9088000, cpu);
per_cpu(cold_boot_done, cpu) = true;
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 88de98b..88e2894 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -23,7 +23,7 @@
obj-$(CONFIG_MSM_QDSP6_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_amrwbplus.o audio_evrc.o audio_qcelp.o amrwb_in.o
obj-$(CONFIG_MSM_QDSP6V2_CODECS) += aac_in.o qcelp_in.o evrc_in.o amrnb_in.o audio_utils.o
obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_wma.o audio_wmapro.o audio_aac.o audio_multi_aac.o audio_utils_aio.o
-obj-$(CONFIG_MSM_QDSP6V2_CODECS) += q6audio_v2.o q6audio_v2_aio.o
+obj-$(CONFIG_MSM_QDSP6V2_CODECS) += q6audio_v2.o q6audio_v2_aio.o msm_audio_ion.o
obj-$(CONFIG_MSM_QDSP6V2_CODECS) += audio_mp3.o audio_amrnb.o audio_amrwb.o audio_amrwbplus.o audio_evrc.o audio_qcelp.o amrwb_in.o
obj-$(CONFIG_MSM_ADSP_LOADER) += adsp-loader.o
obj-$(CONFIG_MSM_ULTRASOUND_A) += ultrasound/version_a/
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index e6b9549..5d744a1 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -24,6 +24,7 @@
#include <linux/atomic.h>
#include <asm/ioctls.h>
#include <linux/debugfs.h>
+#include <linux/msm_audio_ion.h>
#include "audio_utils_aio.h"
#ifdef CONFIG_USE_DEV_CTRL_VOLUME
#include <mach/qdsp6v2/audio_dev_ctl.h>
@@ -374,8 +375,7 @@
list_for_each_safe(ptr, next, &audio->ion_region_queue) {
region = list_entry(ptr, struct audio_aio_ion_region, list);
list_del(®ion->list);
- ion_unmap_kernel(audio->client, region->handle);
- ion_free(audio->client, region->handle);
+ msm_audio_ion_free_legacy(audio->client, region->handle);
kfree(region);
}
@@ -557,7 +557,7 @@
audio_aio_disable(audio);
audio_aio_unmap_ion_region(audio);
audio_aio_reset_ion_region(audio);
- ion_client_destroy(audio->client);
+ msm_audio_ion_client_destroy(audio->client);
audio->event_abort = 1;
wake_up(&audio->event_wait);
audio_aio_reset_event_queue(audio);
@@ -771,12 +771,11 @@
{
ion_phys_addr_t paddr;
size_t len;
- unsigned long kvaddr;
struct audio_aio_ion_region *region;
int rc = -EINVAL;
struct ion_handle *handle;
unsigned long ionflag;
- void *temp_ptr;
+ void *kvaddr;
pr_debug("%s[%p]:\n", __func__, audio);
region = kmalloc(sizeof(*region), GFP_KERNEL);
@@ -786,31 +785,14 @@
goto end;
}
- handle = ion_import_dma_buf(audio->client, info->fd);
- if (IS_ERR_OR_NULL(handle)) {
- pr_err("%s: could not get handle of the given fd\n", __func__);
+ rc = msm_audio_ion_import_legacy("Audio_Dec_Client", audio->client,
+ &handle, info->fd, &ionflag,
+ 0, &paddr, &len, &kvaddr);
+ if (rc) {
+ pr_err("%s: msm audio ion alloc failed\n", __func__);
goto import_error;
}
- rc = ion_handle_get_flags(audio->client, handle, &ionflag);
- if (rc) {
- pr_err("%s: could not get flags for the handle\n", __func__);
- goto flag_error;
- }
-
- temp_ptr = ion_map_kernel(audio->client, handle);
- if (IS_ERR_OR_NULL(temp_ptr)) {
- pr_err("%s: could not get virtual address\n", __func__);
- goto map_error;
- }
- kvaddr = (unsigned long)temp_ptr;
-
- rc = ion_phys(audio->client, handle, &paddr, &len);
- if (rc) {
- pr_err("%s: could not get physical address\n", __func__);
- goto ion_error;
- }
-
rc = audio_aio_ion_check(audio, info->vaddr, len);
if (rc < 0) {
pr_err("%s: audio_aio_ion_check failed\n", __func__);
@@ -821,7 +803,7 @@
region->vaddr = info->vaddr;
region->fd = info->fd;
region->paddr = paddr;
- region->kvaddr = kvaddr;
+ region->kvaddr = (unsigned long)kvaddr;
region->len = len;
region->ref_cnt = 0;
pr_debug("%s[%p]:add region paddr %lx vaddr %p, len %lu kvaddr %lx\n",
@@ -839,10 +821,7 @@
mmap_error:
list_del(®ion->list);
ion_error:
- ion_unmap_kernel(audio->client, handle);
-map_error:
-flag_error:
- ion_free(audio->client, handle);
+ msm_audio_ion_free_legacy(audio->client, handle);
import_error:
kfree(region);
end:
@@ -879,8 +858,8 @@
__func__, audio);
list_del(®ion->list);
- ion_unmap_kernel(audio->client, region->handle);
- ion_free(audio->client, region->handle);
+ msm_audio_ion_free_legacy(audio->client,
+ region->handle);
kfree(region);
rc = 0;
break;
@@ -1167,7 +1146,8 @@
break;
}
}
- audio->client = msm_ion_client_create(UINT_MAX, "Audio_Dec_Client");
+ audio->client = msm_audio_ion_client_create(UINT_MAX,
+ "Audio_Dec_Client");
if (IS_ERR_OR_NULL(audio->client)) {
pr_err("Unable to create ION client\n");
rc = -EACCES;
diff --git a/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
new file mode 100644
index 0000000..c9bc3d7
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/msm_audio_ion.c
@@ -0,0 +1,326 @@
+/*
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <mach/subsystem_restart.h>
+#include <mach/qdsp6v2/apr.h>
+#include <linux/of_device.h>
+#include <linux/msm_audio_ion.h>
+
+struct msm_audio_ion_private {
+ bool smmu_enabled;
+ /*u32 group_id;*/
+ /*u32 domain_id;*/
+};
+
+static struct msm_audio_ion_private msm_audio_ion_data = {0,};
+
+
+static int msm_audio_ion_get_phys(struct ion_client *client,
+ struct ion_handle *handle,
+ ion_phys_addr_t *addr, size_t *len);
+
+
+
+int msm_audio_ion_alloc(const char *name, struct ion_client **client,
+ struct ion_handle **handle, size_t bufsz,
+ ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
+{
+ int rc = 0;
+
+ *client = msm_audio_ion_client_create(UINT_MAX, name);
+ if (IS_ERR_OR_NULL((void *)(*client))) {
+ pr_err("%s: ION create client for AUDIO failed\n", __func__);
+ goto err;
+ }
+
+ *handle = ion_alloc(*client, bufsz, SZ_4K, (0x1<<ION_AUDIO_HEAP_ID), 0);
+ if (IS_ERR_OR_NULL((void *) (*handle))) {
+ pr_err("%s: ION memory allocation for AUDIO failed\n",
+ __func__);
+ goto err_ion_client;
+ }
+
+ rc = msm_audio_ion_get_phys(*client, *handle, paddr, pa_len);
+ if (rc) {
+ pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+ __func__, rc);
+ goto err_ion_handle;
+ }
+
+ /*Need to add condition SMMU enable or not */
+ *vaddr = ion_map_kernel(*client, *handle);
+ if (IS_ERR_OR_NULL((void *)*vaddr)) {
+ pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+ goto err_ion_handle;
+ }
+
+ if (bufsz != 0)
+ memset((void *)*vaddr, 0, bufsz);
+
+ return 0;
+
+err_ion_handle:
+ ion_free(*client, *handle);
+err_ion_client:
+ msm_audio_ion_client_destroy(*client);
+err:
+ return -EINVAL;
+
+}
+
+int msm_audio_ion_import(const char *name, struct ion_client **client,
+ struct ion_handle **handle, int fd,
+ unsigned long *ionflag, size_t bufsz,
+ ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
+{
+ int rc = 0;
+
+ *client = msm_audio_ion_client_create(UINT_MAX, name);
+ if (IS_ERR_OR_NULL((void *)(*client))) {
+ pr_err("%s: ION create client for AUDIO failed\n", __func__);
+ goto err;
+ }
+
+ /* name should be audio_acdb_client or Audio_Dec_Client,
+ bufsz should be 0 and fd shouldn't be 0 as of now
+ */
+ *handle = ion_import_dma_buf(*client, fd);
+ pr_err("%s: DMA Buf name=%s, fd=%d handle=%p\n", __func__,
+ name, fd, *handle);
+ if (IS_ERR_OR_NULL((void *) (*handle))) {
+ pr_err("%s: ion import dma buffer failed\n",
+ __func__);
+ goto err_ion_handle;
+ }
+
+ if (ionflag != NULL) {
+ rc = ion_handle_get_flags(*client, *handle, ionflag);
+ if (rc) {
+ pr_err("%s: could not get flags for the handle\n",
+ __func__);
+ goto err_ion_handle;
+ }
+ }
+
+ rc = msm_audio_ion_get_phys(*client, *handle, paddr, pa_len);
+ if (rc) {
+ pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+ __func__, rc);
+ goto err_ion_handle;
+ }
+
+ /*Need to add condition SMMU enable or not */
+ *vaddr = ion_map_kernel(*client, *handle);
+ if (IS_ERR_OR_NULL((void *)*vaddr)) {
+ pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+ goto err_ion_handle;
+ }
+
+ if (bufsz != 0)
+ memset((void *)*vaddr, 0, bufsz);
+
+ return 0;
+
+err_ion_handle:
+ ion_free(*client, *handle);
+ msm_audio_ion_client_destroy(*client);
+err:
+ return -EINVAL;
+
+}
+
+int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle)
+{
+ /* add condition for SMMU enabled */
+ ion_unmap_kernel(client, handle);
+
+ ion_free(client, handle);
+ msm_audio_ion_client_destroy(client);
+ return 0;
+}
+
+
+bool msm_audio_ion_is_smmu_available(void)
+{
+ return msm_audio_ion_data.smmu_enabled;
+}
+
+/* move to static section again */
+struct ion_client *msm_audio_ion_client_create(unsigned int heap_mask,
+ const char *name)
+{
+ pr_debug("%s: smmu_enabled = %d\n", __func__,
+ msm_audio_ion_data.smmu_enabled);
+
+
+ return msm_ion_client_create(heap_mask, name);
+}
+
+
+void msm_audio_ion_client_destroy(struct ion_client *client)
+{
+ pr_debug("%s: smmu_enabled = %d\n", __func__,
+ msm_audio_ion_data.smmu_enabled);
+
+ ion_client_destroy(client);
+}
+
+int msm_audio_ion_import_legacy(const char *name, struct ion_client *client,
+ struct ion_handle **handle, int fd,
+ unsigned long *ionflag, size_t bufsz,
+ ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
+{
+ int rc = 0;
+ /* client is already created for legacy and given*/
+ /* name should be audio_acdb_client or Audio_Dec_Client,
+ bufsz should be 0 and fd shouldn't be 0 as of now
+ */
+ *handle = ion_import_dma_buf(client, fd);
+ pr_err("%s: DMA Buf name=%s, fd=%d handle=%p\n", __func__,
+ name, fd, *handle);
+ if (IS_ERR_OR_NULL((void *) (*handle))) {
+ pr_err("%s: ion import dma buffer failed\n",
+ __func__);
+ goto err_ion_handle;
+ }
+
+ if (ionflag != NULL) {
+ rc = ion_handle_get_flags(client, *handle, ionflag);
+ if (rc) {
+ pr_err("%s: could not get flags for the handle\n",
+ __func__);
+ goto err_ion_handle;
+ }
+ }
+
+ rc = msm_audio_ion_get_phys(client, *handle, paddr, pa_len);
+ if (rc) {
+ pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+ __func__, rc);
+ goto err_ion_handle;
+ }
+
+ /*Need to add condition SMMU enable or not */
+ *vaddr = ion_map_kernel(client, *handle);
+ if (IS_ERR_OR_NULL((void *)*vaddr)) {
+ pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+ goto err_ion_handle;
+ }
+
+ if (bufsz != 0)
+ memset((void *)*vaddr, 0, bufsz);
+
+ return 0;
+
+err_ion_handle:
+ ion_free(client, *handle);
+ return -EINVAL;
+
+}
+
+int msm_audio_ion_free_legacy(struct ion_client *client,
+ struct ion_handle *handle)
+{
+ /* To add condition for SMMU enabled */
+ ion_unmap_kernel(client, handle);
+
+ ion_free(client, handle);
+ /* no client_destrody in legacy*/
+ return 0;
+}
+
+
+static int msm_audio_ion_get_phys(struct ion_client *client,
+ struct ion_handle *handle,
+ ion_phys_addr_t *addr, size_t *len)
+{
+ int rc = 0;
+ pr_debug("%s: smmu_enabled = %d\n", __func__,
+ msm_audio_ion_data.smmu_enabled);
+
+ if (msm_audio_ion_data.smmu_enabled) {
+ /* SMMU enabled case ion_map_iommu()*/
+ } else {
+ /* SMMU is disabled*/
+ rc = ion_phys(client, handle, addr, len);
+ }
+ pr_debug("%s: addr= 0x%p, len= %d\n", __func__, addr, *len);
+ return rc;
+}
+
+
+
+
+static int msm_audio_ion_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ const char *msm_audio_ion_dt = "qcom,smmu-enabled";
+ bool smmu_enabled;
+
+ if (pdev->dev.of_node == NULL) {
+ pr_err("%s: device tree is not found\n", __func__);
+ msm_audio_ion_data.smmu_enabled = 0;
+ return 0;
+ }
+
+ smmu_enabled = of_property_read_bool(pdev->dev.of_node,
+ msm_audio_ion_dt);
+ msm_audio_ion_data.smmu_enabled = smmu_enabled;
+
+ pr_debug("%s: SMMU-Enabled = %d\n", __func__, smmu_enabled);
+ return rc;
+}
+
+static int msm_audio_ion_remove(struct platform_device *pdev)
+{
+ pr_debug("%s: msm audio ion is unloaded\n", __func__);
+
+ return 0;
+}
+
+static const struct of_device_id msm_audio_ion_dt_match[] = {
+ { .compatible = "qcom,msm-audio-ion" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, msm_audio_ion_dt_match);
+
+static struct platform_driver msm_audio_ion_driver = {
+ .driver = {
+ .name = "msm-audio-ion",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_audio_ion_dt_match,
+ },
+ .probe = msm_audio_ion_probe,
+ .remove = __devexit_p(msm_audio_ion_remove),
+};
+
+static int __init msm_audio_ion_init(void)
+{
+ return platform_driver_register(&msm_audio_ion_driver);
+}
+module_init(msm_audio_ion_init);
+
+static void __exit msm_audio_ion_exit(void)
+{
+ platform_driver_unregister(&msm_audio_ion_driver);
+}
+module_exit(msm_audio_ion_exit);
+
+MODULE_DESCRIPTION("MSM Audio ION module");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/qdsp6v2/q6core.c b/arch/arm/mach-msm/qdsp6v2/q6core.c
index f23ba67..6594b08 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6core.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6core.c
@@ -413,6 +413,32 @@
return rc;
}
+uint32_t core_set_dolby_manufacturer_id(int manufacturer_id)
+{
+ struct adsp_dolby_manufacturer_id payload;
+ int rc = 0;
+ pr_debug("%s manufacturer_id :%d\n", __func__, manufacturer_id);
+ core_open();
+ if (core_handle_q) {
+ payload.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_EVENT,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ payload.hdr.pkt_size =
+ sizeof(struct adsp_dolby_manufacturer_id);
+ payload.hdr.src_port = 0;
+ payload.hdr.dest_port = 0;
+ payload.hdr.token = 0;
+ payload.hdr.opcode = ADSP_CMD_SET_DOLBY_MANUFACTURER_ID;
+ payload.manufacturer_id = manufacturer_id;
+ pr_debug("Send Dolby security opcode=%x manufacturer ID = %d\n",
+ payload.hdr.opcode, payload.manufacturer_id);
+ rc = apr_send_pkt(core_handle_q, (uint32_t *)&payload);
+ if (rc < 0)
+ pr_err("%s: SET_DOLBY_MANUFACTURER_ID failed op[0x%x]rc[%d]\n",
+ __func__, payload.hdr.opcode, rc);
+ }
+ return rc;
+}
+
static const struct file_operations apr_debug_fops = {
.write = apr_debug_write,
.open = apr_debug_open,
diff --git a/arch/arm/mach-msm/rpm-regulator-smd.c b/arch/arm/mach-msm/rpm-regulator-smd.c
index 55ce4b1..923e647 100644
--- a/arch/arm/mach-msm/rpm-regulator-smd.c
+++ b/arch/arm/mach-msm/rpm-regulator-smd.c
@@ -73,6 +73,17 @@
RPM_REGULATOR_PARAM_MAX,
};
+enum rpm_regulator_smps_mode {
+ RPM_REGULATOR_SMPS_MODE_AUTO = 0,
+ RPM_REGULATOR_SMPS_MODE_IPEAK = 1,
+ RPM_REGULATOR_SMPS_MODE_PWM = 2,
+};
+
+enum rpm_regulator_ldo_mode {
+ RPM_REGULATOR_LDO_MODE_IPEAK = 0,
+ RPM_REGULATOR_LDO_MODE_HPM = 1,
+};
+
#define RPM_SET_CONFIG_ACTIVE BIT(0)
#define RPM_SET_CONFIG_SLEEP BIT(1)
#define RPM_SET_CONFIG_BOTH (RPM_SET_CONFIG_ACTIVE \
@@ -118,6 +129,20 @@
PARAM(FLOOR_CORNER, 1, 1, 0, 0, "vfc", 0, 6, "qcom,init-voltage-floor-corner"),
};
+struct rpm_regulator_mode_map {
+ int ldo_mode;
+ int smps_mode;
+};
+
+static struct rpm_regulator_mode_map mode_mapping[] = {
+ [RPM_REGULATOR_MODE_AUTO]
+ = {-1, RPM_REGULATOR_SMPS_MODE_AUTO},
+ [RPM_REGULATOR_MODE_IPEAK]
+ = {RPM_REGULATOR_LDO_MODE_IPEAK, RPM_REGULATOR_SMPS_MODE_IPEAK},
+ [RPM_REGULATOR_MODE_HPM]
+ = {RPM_REGULATOR_LDO_MODE_HPM, RPM_REGULATOR_SMPS_MODE_PWM},
+};
+
struct rpm_vreg_request {
u32 param[RPM_REGULATOR_PARAM_MAX];
u32 valid;
@@ -1077,6 +1102,71 @@
}
EXPORT_SYMBOL_GPL(rpm_regulator_set_voltage);
+/**
+ * rpm_regulator_set_mode() - set regulator operating mode
+ * @regulator: RPM regulator handle
+ * @mode: operating mode requested for the regulator
+ *
+ * Requests that the mode of the regulator be set to the mode specified. This
+ * parameter is aggregated using a max function such that AUTO < IPEAK < HPM.
+ *
+ * Returns 0 on success or errno on failure.
+ */
+int rpm_regulator_set_mode(struct rpm_regulator *regulator,
+ enum rpm_regulator_mode mode)
+{
+ int index = 0;
+ u32 new_mode, prev_mode;
+ int rc;
+
+ rc = rpm_regulator_check_input(regulator);
+ if (rc)
+ return rc;
+
+ if (mode < 0 || mode >= ARRAY_SIZE(mode_mapping)) {
+ vreg_err(regulator, "invalid mode requested: %d\n", mode);
+ return -EINVAL;
+ }
+
+ switch (regulator->rpm_vreg->regulator_type) {
+ case RPM_REGULATOR_SMD_TYPE_SMPS:
+ index = RPM_REGULATOR_PARAM_MODE_SMPS;
+ new_mode = mode_mapping[mode].smps_mode;
+ break;
+ case RPM_REGULATOR_SMD_TYPE_LDO:
+ index = RPM_REGULATOR_PARAM_MODE_LDO;
+ new_mode = mode_mapping[mode].ldo_mode;
+ break;
+ default:
+ vreg_err(regulator, "unsupported regulator type: %d\n",
+ regulator->rpm_vreg->regulator_type);
+ return -EINVAL;
+ };
+
+ if (new_mode < params[index].min || new_mode > params[index].max) {
+ vreg_err(regulator, "invalid mode requested: %d for type: %d\n",
+ mode, regulator->rpm_vreg->regulator_type);
+ return -EINVAL;
+ }
+
+ rpm_vreg_lock(regulator->rpm_vreg);
+
+ prev_mode = regulator->req.param[index];
+ regulator->req.param[index] = new_mode;
+ regulator->req.modified |= BIT(index);
+
+ rc = rpm_vreg_aggregate_requests(regulator);
+ if (rc) {
+ vreg_err(regulator, "set mode failed, rc=%d", rc);
+ regulator->req.param[index] = prev_mode;
+ }
+
+ rpm_vreg_unlock(regulator->rpm_vreg);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(rpm_regulator_set_mode);
+
static struct regulator_ops ldo_ops = {
.enable = rpm_vreg_enable,
.disable = rpm_vreg_disable,
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index 21e1bf4..0b270b7 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -58,15 +58,11 @@
static void *smd_tty_log_ctx;
static DEFINE_MUTEX(smd_tty_lock);
-static uint smd_tty_modem_wait;
-module_param_named(modem_wait, smd_tty_modem_wait,
- uint, S_IRUGO | S_IWUSR | S_IWGRP);
-
struct smd_tty_info {
smd_channel_t *ch;
struct tty_port port;
+ struct device *device_ptr;
struct wake_lock wake_lock;
- int open_count;
struct tasklet_struct tty_tsklt;
struct timer_list buf_req_timer;
struct completion ch_allocated;
@@ -75,6 +71,7 @@
int in_reset;
int in_reset_updated;
int is_open;
+ unsigned int open_wait;
wait_queue_head_t ch_opened_wait_queue;
spinlock_t reset_lock;
spinlock_t ra_lock; /* Read Available Lock*/
@@ -137,6 +134,57 @@
spin_unlock_irqrestore(&info->reset_lock, flags);
}
+static ssize_t open_timeout_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t n)
+{
+ unsigned int num_dev;
+ unsigned long wait;
+ if (dev == NULL) {
+ SMD_TTY_INFO("%s: Invalid Device passed", __func__);
+ return -EINVAL;
+ }
+ for (num_dev = 0; num_dev < MAX_SMD_TTYS; num_dev++) {
+ if (dev == smd_tty[num_dev].device_ptr)
+ break;
+ }
+ if (num_dev >= MAX_SMD_TTYS) {
+ SMD_TTY_ERR("[%s]: Device Not found", __func__);
+ return -EINVAL;
+ }
+ if (!kstrtoul(buf, 10, &wait)) {
+ smd_tty[num_dev].open_wait = wait;
+ return n;
+ } else {
+ SMD_TTY_INFO("[%s]: Unable to convert %s to an int",
+ __func__, buf);
+ return -EINVAL;
+ }
+}
+
+static ssize_t open_timeout_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ unsigned int num_dev;
+
+ if (dev == NULL) {
+ SMD_TTY_INFO("%s: Invalid Device passed", __func__);
+ return -EINVAL;
+ }
+ for (num_dev = 0; num_dev < MAX_SMD_TTYS; num_dev++) {
+ if (dev == smd_tty[num_dev].device_ptr)
+ break;
+ }
+ if (num_dev >= MAX_SMD_TTYS)
+ SMD_TTY_ERR("[%s]: Device Not Found", __func__);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ smd_tty[num_dev].open_wait);
+}
+
+static DEVICE_ATTR
+ (open_timeout, 0664, open_timeout_show, open_timeout_store);
+
static void smd_tty_read(unsigned long param)
{
unsigned char *ptr;
@@ -284,102 +332,106 @@
mutex_lock(&smd_tty_lock);
tty->driver_data = info;
- if (info->open_count++ == 0) {
- peripheral = smd_edge_to_subsystem(smd_tty[n].smd->edge);
- if (peripheral) {
- info->pil = subsystem_get(peripheral);
- if (IS_ERR(info->pil)) {
- res = PTR_ERR(info->pil);
- goto out;
- }
-
- /* Wait for the modem SMSM to be inited for the SMD
- * Loopback channel to be allocated at the modem. Since
- * the wait need to be done atmost once, using msleep
- * doesn't degrade the performance.
- */
- if (n == LOOPBACK_IDX) {
- if (!is_modem_smsm_inited())
- msleep(5000);
- smsm_change_state(SMSM_APPS_STATE,
- 0, SMSM_SMD_LOOPBACK);
- msleep(100);
- }
-
+ peripheral = smd_edge_to_subsystem(smd_tty[n].smd->edge);
+ if (peripheral) {
+ info->pil = subsystem_get(peripheral);
+ if (IS_ERR(info->pil)) {
+ SMD_TTY_INFO(
+ "%s failed on smd_tty device :%s subsystem_get failed for %s",
+ __func__, smd_tty[n].smd->port_name,
+ peripheral);
/*
- * Wait for a channel to be allocated so we know
- * the modem is ready enough.
+ * Sleep, inorder to reduce the frequency of
+ * retry by user-space modules and to avoid
+ * possible watchdog bite.
*/
- if (smd_tty_modem_wait) {
- res = wait_for_completion_interruptible_timeout(
- &info->ch_allocated,
- msecs_to_jiffies(smd_tty_modem_wait *
- 1000));
-
- if (res == 0) {
- SMD_TTY_INFO(
- "Timed out waiting for SMD channel %s",
- smd_tty[n].smd->port_name);
- res = -ETIMEDOUT;
- goto release_pil;
- } else if (res < 0) {
- SMD_TTY_INFO(
- "Error waiting for SMD channel %s : %d\n",
- smd_tty[n].smd->port_name, res);
- goto release_pil;
- }
-
- res = 0;
- }
+ msleep((smd_tty[n].open_wait * 1000));
+ res = PTR_ERR(info->pil);
+ goto out;
}
- tasklet_init(&info->tty_tsklt, smd_tty_read,
- (unsigned long)info);
- wake_lock_init(&info->wake_lock, WAKE_LOCK_SUSPEND,
- smd_tty[n].smd->port_name);
- scnprintf(info->ra_wake_lock_name,
- MAX_RA_WAKE_LOCK_NAME_LEN,
- "SMD_TTY_%s_RA", smd_tty[n].smd->port_name);
- wake_lock_init(&info->ra_wake_lock, WAKE_LOCK_SUSPEND,
- info->ra_wake_lock_name);
- if (!info->ch) {
- res = smd_named_open_on_edge(smd_tty[n].smd->port_name,
- smd_tty[n].smd->edge,
- &info->ch, info,
- smd_tty_notify);
- if (res < 0) {
- SMD_TTY_INFO(
- "%s: %s open failed %d\n",
- __func__, smd_tty[n].smd->port_name,
- res);
- goto release_pil;
- }
+ /* Wait for the modem SMSM to be inited for the SMD
+ * Loopback channel to be allocated at the modem. Since
+ * the wait need to be done atmost once, using msleep
+ * doesn't degrade the performance.
+ */
+ if (n == LOOPBACK_IDX) {
+ if (!is_modem_smsm_inited())
+ msleep(5000);
+ smsm_change_state(SMSM_APPS_STATE,
+ 0, SMSM_SMD_LOOPBACK);
+ msleep(100);
+ }
- res = wait_event_interruptible_timeout(
- info->ch_opened_wait_queue,
- info->is_open, (2 * HZ));
- if (res == 0)
- res = -ETIMEDOUT;
- if (res < 0) {
+ /*
+ * Wait for a channel to be allocated so we know
+ * the modem is ready enough.
+ */
+ if (smd_tty[n].open_wait) {
+ res = wait_for_completion_interruptible_timeout(
+ &info->ch_allocated,
+ msecs_to_jiffies(smd_tty[n].open_wait *
+ 1000));
+
+ if (res == 0) {
SMD_TTY_INFO(
- "%s: wait for %s smd_open failed %d\n",
- __func__, smd_tty[n].smd->port_name,
- res);
+ "Timed out waiting for SMD channel %s",
+ smd_tty[n].smd->port_name);
+ res = -ETIMEDOUT;
+ goto release_pil;
+ } else if (res < 0) {
+ SMD_TTY_INFO(
+ "Error waiting for SMD channel %s : %d\n",
+ smd_tty[n].smd->port_name, res);
goto release_pil;
}
- res = 0;
- SMD_TTY_INFO("%s with PID %u opened port %s",
- current->comm, current->pid,
- smd_tty[n].smd->port_name);
}
}
+ tasklet_init(&info->tty_tsklt, smd_tty_read, (unsigned long)info);
+ wake_lock_init(&info->wake_lock, WAKE_LOCK_SUSPEND,
+ smd_tty[n].smd->port_name);
+ scnprintf(info->ra_wake_lock_name, MAX_RA_WAKE_LOCK_NAME_LEN,
+ "SMD_TTY_%s_RA", smd_tty[n].smd->port_name);
+ wake_lock_init(&info->ra_wake_lock, WAKE_LOCK_SUSPEND,
+ info->ra_wake_lock_name);
+
+ res = smd_named_open_on_edge(smd_tty[n].smd->port_name,
+ smd_tty[n].smd->edge, &info->ch, info,
+ smd_tty_notify);
+ if (res < 0) {
+ SMD_TTY_INFO("%s: %s open failed %d\n",
+ __func__, smd_tty[n].smd->port_name, res);
+ goto release_wl_tl;
+ }
+
+ res = wait_event_interruptible_timeout(info->ch_opened_wait_queue,
+ info->is_open, (2 * HZ));
+ if (res == 0)
+ res = -ETIMEDOUT;
+ if (res < 0) {
+ SMD_TTY_INFO("%s: wait for %s smd_open failed %d\n",
+ __func__, smd_tty[n].smd->port_name, res);
+ goto close_ch;
+ }
+ SMD_TTY_INFO("%s with PID %u opened port %s",
+ current->comm, current->pid, smd_tty[n].smd->port_name);
+ smd_disable_read_intr(info->ch);
+ mutex_unlock(&smd_tty_lock);
+ return 0;
+
+close_ch:
+ smd_close(info->ch);
+ info->ch = NULL;
+
+release_wl_tl:
+ tasklet_kill(&info->tty_tsklt);
+ wake_lock_destroy(&info->wake_lock);
+ wake_lock_destroy(&info->ra_wake_lock);
+
release_pil:
- if (res < 0)
- subsystem_put(info->pil);
- else
- smd_disable_read_intr(info->ch);
+ subsystem_put(info->pil);
out:
mutex_unlock(&smd_tty_lock);
@@ -399,26 +451,25 @@
}
mutex_lock(&smd_tty_lock);
- if (--info->open_count == 0) {
- spin_lock_irqsave(&info->reset_lock, flags);
- info->is_open = 0;
- spin_unlock_irqrestore(&info->reset_lock, flags);
- if (tty) {
- tasklet_kill(&info->tty_tsklt);
- wake_lock_destroy(&info->wake_lock);
- wake_lock_destroy(&info->ra_wake_lock);
- }
- SMD_TTY_INFO("%s with PID %u closed port %s",
- current->comm, current->pid,
- info->smd->port_name);
- tty->driver_data = 0;
- del_timer(&info->buf_req_timer);
- if (info->ch) {
- smd_close(info->ch);
- info->ch = 0;
- subsystem_put(info->pil);
- }
- }
+
+ spin_lock_irqsave(&info->reset_lock, flags);
+ info->is_open = 0;
+ spin_unlock_irqrestore(&info->reset_lock, flags);
+
+ tasklet_kill(&info->tty_tsklt);
+ wake_lock_destroy(&info->wake_lock);
+ wake_lock_destroy(&info->ra_wake_lock);
+
+ SMD_TTY_INFO("%s with PID %u closed port %s",
+ current->comm, current->pid,
+ info->smd->port_name);
+ tty->driver_data = NULL;
+ del_timer(&info->buf_req_timer);
+
+ smd_close(info->ch);
+ info->ch = NULL;
+ subsystem_put(info->pil);
+
mutex_unlock(&smd_tty_lock);
tty_kref_put(tty);
}
@@ -664,7 +715,14 @@
tty_port_init(port);
port->ops = &smd_tty_port_ops;
/* TODO: For kernel >= 3.7 use tty_port_register_device */
- tty_register_device(smd_tty_driver, idx, 0);
+ smd_tty[idx].device_ptr =
+ tty_register_device(smd_tty_driver, idx, 0);
+ if (device_create_file(smd_tty[idx].device_ptr,
+ &dev_attr_open_timeout))
+ SMD_TTY_ERR(
+ "%s: Unable to create device attributes for %s",
+ __func__, smd_configs[n].port_name);
+
init_completion(&smd_tty[idx].ch_allocated);
/* register platform device */
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 1f0fa85..ee6dfbf 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -845,25 +845,7 @@
static void * __init setup_dummy_socinfo(void)
{
- if (machine_is_msm8960_cdp())
- dummy_socinfo.id = 87;
- else if (machine_is_msm9615_mtp() || machine_is_msm9615_cdp())
- dummy_socinfo.id = 104;
- else if (early_machine_is_msm8974()) {
- dummy_socinfo.id = 126;
- strlcpy(dummy_socinfo.build_id, "msm8974 - ",
- sizeof(dummy_socinfo.build_id));
- } else if (early_machine_is_msm9625()) {
- dummy_socinfo.id = 134;
- strlcpy(dummy_socinfo.build_id, "msm9625 - ",
- sizeof(dummy_socinfo.build_id));
- } else if (early_machine_is_msm8226()) {
- dummy_socinfo.id = 145;
- strlcpy(dummy_socinfo.build_id, "msm8226 - ",
- sizeof(dummy_socinfo.build_id));
- } else if (machine_is_msm8625_rumi3())
- dummy_socinfo.id = 127;
- else if (early_machine_is_mpq8092()) {
+ if (early_machine_is_mpq8092()) {
dummy_socinfo.id = 146;
strlcpy(dummy_socinfo.build_id, "mpq8092 - ",
sizeof(dummy_socinfo.build_id));
diff --git a/arch/arm/mach-msm/subsystem_map.c b/arch/arm/mach-msm/subsystem_map.c
deleted file mode 100644
index 116fc2e..0000000
--- a/arch/arm/mach-msm/subsystem_map.c
+++ /dev/null
@@ -1,555 +0,0 @@
-/* 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
- * 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/io.h>
-#include <linux/types.h>
-#include <linux/err.h>
-#include <linux/slab.h>
-#include <linux/memory_alloc.h>
-#include <linux/module.h>
-#include <mach/iommu.h>
-#include <mach/iommu_domains.h>
-#include <mach/msm_subsystem_map.h>
-
-struct msm_buffer_node {
- struct rb_node rb_node_all_buffer;
- struct rb_node rb_node_paddr;
- struct msm_mapped_buffer *buf;
- unsigned long length;
- unsigned int *subsystems;
- unsigned int nsubsys;
- unsigned int phys;
-};
-
-static struct rb_root buffer_root;
-static struct rb_root phys_root;
-DEFINE_MUTEX(msm_buffer_mutex);
-
-static unsigned long subsystem_to_domain_tbl[] = {
- VIDEO_DOMAIN,
- VIDEO_DOMAIN,
- CAMERA_DOMAIN,
- DISPLAY_READ_DOMAIN,
- DISPLAY_WRITE_DOMAIN,
- ROTATOR_SRC_DOMAIN,
- ROTATOR_DST_DOMAIN,
- 0xFFFFFFFF
-};
-
-static struct msm_buffer_node *find_buffer(void *key)
-{
- struct rb_root *root = &buffer_root;
- struct rb_node *p = root->rb_node;
-
- mutex_lock(&msm_buffer_mutex);
-
- while (p) {
- struct msm_buffer_node *node;
-
- node = rb_entry(p, struct msm_buffer_node, rb_node_all_buffer);
- if (node->buf->vaddr) {
- if (key < node->buf->vaddr)
- p = p->rb_left;
- else if (key > node->buf->vaddr)
- p = p->rb_right;
- else {
- mutex_unlock(&msm_buffer_mutex);
- return node;
- }
- } else {
- if (key < (void *)node->buf)
- p = p->rb_left;
- else if (key > (void *)node->buf)
- p = p->rb_right;
- else {
- mutex_unlock(&msm_buffer_mutex);
- return node;
- }
- }
- }
- mutex_unlock(&msm_buffer_mutex);
- return NULL;
-}
-
-static struct msm_buffer_node *find_buffer_phys(unsigned int phys)
-{
- struct rb_root *root = &phys_root;
- struct rb_node *p = root->rb_node;
-
- mutex_lock(&msm_buffer_mutex);
-
- while (p) {
- struct msm_buffer_node *node;
-
- node = rb_entry(p, struct msm_buffer_node, rb_node_paddr);
- if (phys < node->phys)
- p = p->rb_left;
- else if (phys > node->phys)
- p = p->rb_right;
- else {
- mutex_unlock(&msm_buffer_mutex);
- return node;
- }
- }
- mutex_unlock(&msm_buffer_mutex);
- return NULL;
-
-}
-
-static int add_buffer(struct msm_buffer_node *node)
-{
- struct rb_root *root = &buffer_root;
- struct rb_node **p = &root->rb_node;
- struct rb_node *parent = NULL;
- void *key;
-
- if (node->buf->vaddr)
- key = node->buf->vaddr;
- else
- key = node->buf;
-
- mutex_lock(&msm_buffer_mutex);
- while (*p) {
- struct msm_buffer_node *tmp;
- parent = *p;
-
- tmp = rb_entry(parent, struct msm_buffer_node,
- rb_node_all_buffer);
-
- if (tmp->buf->vaddr) {
- if (key < tmp->buf->vaddr)
- p = &(*p)->rb_left;
- else if (key > tmp->buf->vaddr)
- p = &(*p)->rb_right;
- else {
- WARN(1, "tried to add buffer twice! buf = %p"
- " vaddr = %p iova = %p", tmp->buf,
- tmp->buf->vaddr,
- tmp->buf->iova);
- mutex_unlock(&msm_buffer_mutex);
- return -EINVAL;
-
- }
- } else {
- if (key < (void *)tmp->buf)
- p = &(*p)->rb_left;
- else if (key > (void *)tmp->buf)
- p = &(*p)->rb_right;
- else {
- WARN(1, "tried to add buffer twice! buf = %p"
- " vaddr = %p iova = %p", tmp->buf,
- tmp->buf->vaddr,
- tmp->buf->iova);
- mutex_unlock(&msm_buffer_mutex);
- return -EINVAL;
- }
- }
- }
- rb_link_node(&node->rb_node_all_buffer, parent, p);
- rb_insert_color(&node->rb_node_all_buffer, root);
- mutex_unlock(&msm_buffer_mutex);
- return 0;
-}
-
-static int add_buffer_phys(struct msm_buffer_node *node)
-{
- struct rb_root *root = &phys_root;
- struct rb_node **p = &root->rb_node;
- struct rb_node *parent = NULL;
-
- mutex_lock(&msm_buffer_mutex);
- while (*p) {
- struct msm_buffer_node *tmp;
- parent = *p;
-
- tmp = rb_entry(parent, struct msm_buffer_node, rb_node_paddr);
-
- if (node->phys < tmp->phys)
- p = &(*p)->rb_left;
- else if (node->phys > tmp->phys)
- p = &(*p)->rb_right;
- else {
- WARN(1, "tried to add buffer twice! buf = %p"
- " vaddr = %p iova = %p", tmp->buf,
- tmp->buf->vaddr,
- tmp->buf->iova);
- mutex_unlock(&msm_buffer_mutex);
- return -EINVAL;
-
- }
- }
- rb_link_node(&node->rb_node_paddr, parent, p);
- rb_insert_color(&node->rb_node_paddr, root);
- mutex_unlock(&msm_buffer_mutex);
- return 0;
-}
-
-static int remove_buffer(struct msm_buffer_node *victim_node)
-{
- struct rb_root *root = &buffer_root;
-
- if (!victim_node)
- return -EINVAL;
-
- mutex_lock(&msm_buffer_mutex);
- rb_erase(&victim_node->rb_node_all_buffer, root);
- mutex_unlock(&msm_buffer_mutex);
- return 0;
-}
-
-static int remove_buffer_phys(struct msm_buffer_node *victim_node)
-{
- struct rb_root *root = &phys_root;
-
- if (!victim_node)
- return -EINVAL;
-
- mutex_lock(&msm_buffer_mutex);
- rb_erase(&victim_node->rb_node_paddr, root);
- mutex_unlock(&msm_buffer_mutex);
- return 0;
-}
-
-static unsigned long msm_subsystem_get_domain_no(int subsys_id)
-{
- if (subsys_id > INVALID_SUBSYS_ID && subsys_id <= MAX_SUBSYSTEM_ID &&
- subsys_id < ARRAY_SIZE(subsystem_to_domain_tbl))
- return subsystem_to_domain_tbl[subsys_id];
- else
- return subsystem_to_domain_tbl[MAX_SUBSYSTEM_ID];
-}
-
-static unsigned long msm_subsystem_get_partition_no(int subsys_id)
-{
- switch (subsys_id) {
- case MSM_SUBSYSTEM_VIDEO_FWARE:
- return VIDEO_FIRMWARE_POOL;
- case MSM_SUBSYSTEM_VIDEO:
- return VIDEO_MAIN_POOL;
- case MSM_SUBSYSTEM_CAMERA:
- case MSM_SUBSYSTEM_DISPLAY:
- case MSM_SUBSYSTEM_ROTATOR:
- return GEN_POOL;
- default:
- return 0xFFFFFFFF;
- }
-}
-
-phys_addr_t msm_subsystem_check_iova_mapping(int subsys_id, unsigned long iova)
-{
- struct iommu_domain *subsys_domain;
-
- if (!msm_use_iommu())
- /*
- * If there is no iommu, Just return the iova in this case.
- */
- return iova;
-
- subsys_domain = msm_get_iommu_domain(msm_subsystem_get_domain_no
- (subsys_id));
- if (!subsys_domain)
- return -EINVAL;
-
- return iommu_iova_to_phys(subsys_domain, iova);
-}
-EXPORT_SYMBOL(msm_subsystem_check_iova_mapping);
-
-struct msm_mapped_buffer *msm_subsystem_map_buffer(unsigned long phys,
- unsigned int length,
- unsigned int flags,
- int *subsys_ids,
- unsigned int nsubsys)
-{
- struct msm_mapped_buffer *buf, *err;
- struct msm_buffer_node *node;
- int i = 0, j = 0, ret;
- unsigned long iova_start = 0, temp_phys, temp_va = 0;
- struct iommu_domain *d = NULL;
- int map_size = length;
-
- if (!((flags & MSM_SUBSYSTEM_MAP_KADDR) ||
- (flags & MSM_SUBSYSTEM_MAP_IOVA))) {
- pr_warn("%s: no mapping flag was specified. The caller"
- " should explicitly specify what to map in the"
- " flags.\n", __func__);
- err = ERR_PTR(-EINVAL);
- goto outret;
- }
-
- buf = kzalloc(sizeof(*buf), GFP_ATOMIC);
- if (!buf) {
- err = ERR_PTR(-ENOMEM);
- goto outret;
- }
-
- node = kzalloc(sizeof(*node), GFP_ATOMIC);
- if (!node) {
- err = ERR_PTR(-ENOMEM);
- goto outkfreebuf;
- }
-
- node->phys = phys;
-
- if (flags & MSM_SUBSYSTEM_MAP_KADDR) {
- struct msm_buffer_node *old_buffer;
-
- old_buffer = find_buffer_phys(phys);
-
- if (old_buffer) {
- WARN(1, "%s: Attempting to map %lx twice in the kernel"
- " virtual space. Don't do that!\n", __func__,
- phys);
- err = ERR_PTR(-EINVAL);
- goto outkfreenode;
- }
-
- if (flags & MSM_SUBSYSTEM_MAP_CACHED)
- buf->vaddr = ioremap(phys, length);
- else if (flags & MSM_SUBSYSTEM_MAP_KADDR)
- buf->vaddr = ioremap_nocache(phys, length);
- else {
- pr_warn("%s: no cachability flag was indicated. Caller"
- " must specify a cachability flag.\n",
- __func__);
- err = ERR_PTR(-EINVAL);
- goto outkfreenode;
- }
-
- if (!buf->vaddr) {
- pr_err("%s: could not ioremap\n", __func__);
- err = ERR_PTR(-EINVAL);
- goto outkfreenode;
- }
-
- if (add_buffer_phys(node)) {
- err = ERR_PTR(-EINVAL);
- goto outiounmap;
- }
- }
-
- if ((flags & MSM_SUBSYSTEM_MAP_IOVA) && subsys_ids) {
- int min_align;
-
- length = round_up(length, SZ_4K);
-
- if (flags & MSM_SUBSYSTEM_MAP_IOMMU_2X)
- map_size = 2 * length;
- else
- map_size = length;
-
- buf->iova = kzalloc(sizeof(unsigned long)*nsubsys, GFP_ATOMIC);
- if (!buf->iova) {
- err = ERR_PTR(-ENOMEM);
- goto outremovephys;
- }
-
- /*
- * The alignment must be specified as the exact value wanted
- * e.g. 8k alignment must pass (0x2000 | other flags)
- */
- min_align = flags & ~(SZ_4K - 1);
-
- for (i = 0; i < nsubsys; i++) {
- unsigned int domain_no, partition_no;
-
- if (!msm_use_iommu()) {
- buf->iova[i] = phys;
- continue;
- }
-
- d = msm_get_iommu_domain(
- msm_subsystem_get_domain_no(subsys_ids[i]));
-
- if (!d) {
- pr_err("%s: could not get domain for subsystem"
- " %d\n", __func__, subsys_ids[i]);
- continue;
- }
-
- domain_no = msm_subsystem_get_domain_no(subsys_ids[i]);
- partition_no = msm_subsystem_get_partition_no(
- subsys_ids[i]);
-
- ret = msm_allocate_iova_address(domain_no,
- partition_no,
- map_size,
- max(min_align, SZ_4K),
- &iova_start);
-
- if (ret) {
- pr_err("%s: could not allocate iova address\n",
- __func__);
- continue;
- }
-
- temp_phys = phys;
- temp_va = iova_start;
- for (j = length; j > 0; j -= SZ_4K,
- temp_phys += SZ_4K,
- temp_va += SZ_4K) {
- ret = iommu_map(d, temp_va, temp_phys,
- SZ_4K,
- (IOMMU_READ | IOMMU_WRITE));
- if (ret) {
- pr_err("%s: could not map iommu for"
- " domain %p, iova %lx,"
- " phys %lx\n", __func__, d,
- temp_va, temp_phys);
- err = ERR_PTR(-EINVAL);
- goto outdomain;
- }
- }
- buf->iova[i] = iova_start;
-
- if (flags & MSM_SUBSYSTEM_MAP_IOMMU_2X)
- msm_iommu_map_extra
- (d, temp_va, phys, length, SZ_4K,
- IOMMU_READ);
- }
-
- }
-
- node->buf = buf;
- node->subsystems = subsys_ids;
- node->length = map_size;
- node->nsubsys = nsubsys;
-
- if (add_buffer(node)) {
- err = ERR_PTR(-EINVAL);
- goto outiova;
- }
-
- return buf;
-
-outiova:
- if (flags & MSM_SUBSYSTEM_MAP_IOVA) {
- if (d)
- iommu_unmap(d, temp_va, SZ_4K);
- }
-outdomain:
- if (flags & MSM_SUBSYSTEM_MAP_IOVA) {
- /* Unmap the rest of the current domain, i */
- if (d) {
- for (j -= SZ_4K, temp_va -= SZ_4K;
- j > 0; temp_va -= SZ_4K, j -= SZ_4K)
- iommu_unmap(d, temp_va, SZ_4K);
- }
- /* Unmap all the other domains */
- for (i--; i >= 0; i--) {
- unsigned int domain_no, partition_no;
- if (!msm_use_iommu())
- continue;
- domain_no = msm_subsystem_get_domain_no(subsys_ids[i]);
- partition_no = msm_subsystem_get_partition_no(
- subsys_ids[i]);
-
- d = msm_get_iommu_domain(domain_no);
-
- if (d) {
- temp_va = buf->iova[i];
- for (j = length; j > 0; j -= SZ_4K,
- temp_va += SZ_4K)
- iommu_unmap(d, temp_va, SZ_4K);
- }
- msm_free_iova_address(buf->iova[i], domain_no,
- partition_no, length);
- }
-
- kfree(buf->iova);
- }
-
-outremovephys:
- if (flags & MSM_SUBSYSTEM_MAP_KADDR)
- remove_buffer_phys(node);
-outiounmap:
- if (flags & MSM_SUBSYSTEM_MAP_KADDR)
- iounmap(buf->vaddr);
-outkfreenode:
- kfree(node);
-outkfreebuf:
- kfree(buf);
-outret:
- return err;
-}
-EXPORT_SYMBOL(msm_subsystem_map_buffer);
-
-int msm_subsystem_unmap_buffer(struct msm_mapped_buffer *buf)
-{
- struct msm_buffer_node *node;
- int i, j, ret;
- unsigned long temp_va;
-
- if (IS_ERR_OR_NULL(buf))
- goto out;
-
- if (buf->vaddr)
- node = find_buffer(buf->vaddr);
- else
- node = find_buffer(buf);
-
- if (!node)
- goto out;
-
- if (node->buf != buf) {
- pr_err("%s: caller must pass in the same buffer structure"
- " returned from map_buffer when freeding\n", __func__);
- goto out;
- }
-
- if (buf->iova) {
- if (msm_use_iommu())
- for (i = 0; i < node->nsubsys; i++) {
- struct iommu_domain *subsys_domain;
- unsigned int domain_no, partition_no;
-
- subsys_domain = msm_get_iommu_domain(
- msm_subsystem_get_domain_no(
- node->subsystems[i]));
-
- if (!subsys_domain)
- continue;
-
- domain_no = msm_subsystem_get_domain_no(
- node->subsystems[i]);
- partition_no = msm_subsystem_get_partition_no(
- node->subsystems[i]);
-
- temp_va = buf->iova[i];
- for (j = node->length; j > 0; j -= SZ_4K,
- temp_va += SZ_4K) {
- ret = iommu_unmap(subsys_domain,
- temp_va,
- SZ_4K);
- WARN(ret, "iommu_unmap returned a "
- " non-zero value.\n");
- }
- msm_free_iova_address(buf->iova[i], domain_no,
- partition_no, node->length);
- }
- kfree(buf->iova);
-
- }
-
- if (buf->vaddr) {
- remove_buffer_phys(node);
- iounmap(buf->vaddr);
- }
-
- remove_buffer(node);
- kfree(node);
- kfree(buf);
-
- return 0;
-out:
- return -EINVAL;
-}
-EXPORT_SYMBOL(msm_subsystem_unmap_buffer);
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 3144113..06a4c29 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -292,8 +292,6 @@
clock = clockevent_to_clock(evt);
clock_state = &__get_cpu_var(msm_clocks_percpu)[clock->index];
- if (clock_state->stopped)
- return 0;
now = msm_read_timer_count(clock, LOCAL_TIMER);
alarm = now + (cycles << clock->shift);
if (clock->flags & MSM_CLOCK_FLAGS_ODD_MATCH_WRITE)
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 66567bb..26b92d4 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -361,7 +361,7 @@
BUG_ON(!arm_memblock_steal_permitted);
- phys = memblock_alloc(size, align);
+ phys = memblock_alloc_base(size, align, MEMBLOCK_ALLOC_ANYWHERE);
memblock_free(phys, size);
memblock_remove(phys, size);
diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c
index 45c9023..ed91480 100644
--- a/drivers/base/dma-contiguous.c
+++ b/drivers/base/dma-contiguous.c
@@ -227,7 +227,7 @@
pr_info("Found %s, memory base %lx, size %ld MiB\n", uname,
(unsigned long)base, (unsigned long)size / SZ_1M);
- dma_contiguous_reserve_area(size, &base, MEMBLOCK_ALLOC_ANYWHERE, name);
+ dma_contiguous_reserve_area(size, &base, 0, name);
return 0;
}
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 555ffa0..6f37608 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -270,6 +270,7 @@
unsigned char *hdlc_buf;
unsigned hdlc_count;
unsigned hdlc_escape;
+ int in_busy_pktdata;
#ifdef CONFIG_DIAG_OVER_USB
int usb_connected;
struct usb_diag_ch *legacy_ch;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index fb8efe4..a0c32f5 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1310,6 +1310,7 @@
COPY_USER_SPACE_OR_EXIT(buf+4, *(driver->pkt_buf),
driver->pkt_length);
driver->data_ready[index] ^= PKT_TYPE;
+ driver->in_busy_pktdata = 0;
goto exit;
}
@@ -1397,6 +1398,117 @@
payload_size);
return err;
}
+ if (pkt_type == CALLBACK_DATA_TYPE) {
+ err = copy_from_user(driver->user_space_data, buf + 4,
+ payload_size);
+ if (err) {
+ pr_err("diag: copy failed for user space data\n");
+ return -EIO;
+ }
+ /* Check for proc_type */
+ remote_proc = diag_get_remote(*(int *)driver->user_space_data);
+
+ if (!remote_proc) {
+ wait_event_interruptible(driver->wait_q,
+ (driver->in_busy_pktdata == 0));
+ return diag_process_apps_pkt(driver->user_space_data,
+ payload_size);
+ }
+ /* The packet is for the remote processor */
+ token_offset = 4;
+ payload_size -= 4;
+ buf += 4;
+ /* Perform HDLC encoding on incoming data */
+ send.state = DIAG_STATE_START;
+ send.pkt = (void *)(driver->user_space_data + token_offset);
+ send.last = (void *)(driver->user_space_data + token_offset -
+ 1 + payload_size);
+ send.terminate = 1;
+
+ mutex_lock(&driver->diagchar_mutex);
+ if (!buf_hdlc)
+ buf_hdlc = diagmem_alloc(driver, HDLC_OUT_BUF_SIZE,
+ POOL_TYPE_HDLC);
+ if (!buf_hdlc) {
+ ret = -ENOMEM;
+ goto fail_free_hdlc;
+ }
+ if (HDLC_OUT_BUF_SIZE < (2 * payload_size) + 3) {
+ pr_err("diag: Dropping packet, HDLC encoded packet payload size crosses buffer limit. Current payload size %d\n",
+ ((2*payload_size) + 3));
+ driver->dropped_count++;
+ ret = -EBADMSG;
+ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
+ goto fail_free_hdlc;
+ }
+ enc.dest = buf_hdlc + driver->used;
+ enc.dest_last = (void *)(buf_hdlc + driver->used +
+ (2 * payload_size) + token_offset - 1);
+ diag_hdlc_encode(&send, &enc);
+
+#ifdef CONFIG_DIAG_SDIO_PIPE
+ /* send masks to 9k too */
+ if (driver->sdio_ch && (remote_proc == MDM)) {
+ wait_event_interruptible(driver->wait_q,
+ (sdio_write_avail(driver->sdio_ch) >=
+ payload_size));
+ if (driver->sdio_ch && (payload_size > 0)) {
+ sdio_write(driver->sdio_ch, (void *)
+ (char *)buf_hdlc, payload_size + 3);
+ }
+ }
+#endif
+#ifdef CONFIG_DIAGFWD_BRIDGE_CODE
+ /* send masks to All 9k */
+ if ((remote_proc >= MDM) && (remote_proc <= MDM4)) {
+ index = remote_proc - MDM;
+ if (diag_hsic[index].hsic_ch && (payload_size > 0)) {
+ /* wait sending mask updates
+ * if HSIC ch not ready */
+ if (diag_hsic[index].in_busy_hsic_write)
+ wait_event_interruptible(driver->wait_q,
+ (diag_hsic[index].
+ in_busy_hsic_write != 1));
+ diag_hsic[index].in_busy_hsic_write = 1;
+ diag_hsic[index].in_busy_hsic_read_on_device =
+ 0;
+ err = diag_bridge_write(index,
+ (char *)buf_hdlc, payload_size + 3);
+ if (err) {
+ pr_err("diag: err sending mask to MDM: %d\n",
+ err);
+ /*
+ * If the error is recoverable, then
+ * clear the write flag, so we will
+ * resubmit a write on the next frame.
+ * Otherwise, don't resubmit a write
+ * on the next frame.
+ */
+ if ((-ESHUTDOWN) != err)
+ diag_hsic[index].
+ in_busy_hsic_write = 0;
+ }
+ }
+ }
+ if (driver->diag_smux_enabled && (remote_proc == QSC)
+ && driver->lcid) {
+ if (payload_size > 0) {
+ err = msm_smux_write(driver->lcid, NULL,
+ (char *)buf_hdlc, payload_size + 3);
+ if (err) {
+ pr_err("diag:send mask to MDM err %d",
+ err);
+ ret = err;
+ }
+ }
+ }
+#endif
+ diagmem_free(driver, buf_hdlc, POOL_TYPE_HDLC);
+ buf_hdlc = NULL;
+ driver->used = 0;
+ mutex_unlock(&driver->diagchar_mutex);
+ return ret;
+ }
if (pkt_type == USER_SPACE_DATA_TYPE) {
err = copy_from_user(driver->user_space_data, buf + 4,
payload_size);
@@ -1839,6 +1951,7 @@
driver->socket_process = NULL;
driver->callback_process = NULL;
driver->mask_check = 0;
+ driver->in_busy_pktdata = 0;
mutex_init(&driver->diagchar_mutex);
init_waitqueue_head(&driver->wait_q);
init_waitqueue_head(&driver->smd_wait_q);
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index bb74370..5b929d7 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -641,9 +641,10 @@
unsigned char *temp = buf;
mutex_lock(&driver->diagchar_mutex);
- if (CHK_OVERFLOW(ptr, ptr, ptr + PKT_SIZE, driver->pkt_length))
+ if (CHK_OVERFLOW(ptr, ptr, ptr + PKT_SIZE, driver->pkt_length)) {
memcpy(ptr, temp , driver->pkt_length);
- else
+ driver->in_busy_pktdata = 1;
+ } else
printk(KERN_CRIT " Not enough buffer space for PKT_RESP\n");
mutex_unlock(&driver->diagchar_mutex);
}
@@ -718,7 +719,7 @@
}
}
-static int diag_process_apps_pkt(unsigned char *buf, int len)
+int diag_process_apps_pkt(unsigned char *buf, int len)
{
uint16_t subsys_cmd_code;
int subsys_id, ssid_first, ssid_last, ssid_range;
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index 8cf15de..09f2f5e 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -48,6 +48,7 @@
int diag_command_reg(unsigned long);
void diag_cmp_logging_modes_sdio_pipe(int old_mode, int new_mode);
void diag_cmp_logging_modes_diagfwd_bridge(int old_mode, int new_mode);
+int diag_process_apps_pkt(unsigned char *buf, int len);
/* 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 4ddd78a..c3ff7dc 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -86,14 +86,15 @@
range = buf+HDR_SIZ+
sizeof(struct diag_ctrl_msg);
pkt_params->count = msg->count_entries;
- temp = kzalloc(pkt_params->count * sizeof(struct
- bindpkt_params), GFP_KERNEL);
- if (temp == NULL) {
+ pkt_params->params = kzalloc(pkt_params->count *
+ sizeof(struct bindpkt_params), GFP_KERNEL);
+ if (pkt_params->params == NULL) {
pr_alert("diag: In %s, Memory alloc fail\n",
__func__);
kfree(pkt_params);
return flag;
}
+ temp = pkt_params->params;
for (j = 0; j < pkt_params->count; j++) {
temp->cmd_code = msg->cmd_code;
temp->subsys_id = msg->subsysid;
@@ -104,8 +105,6 @@
range++;
temp++;
}
- temp -= pkt_params->count;
- pkt_params->params = temp;
flag = 1;
/* peripheral undergoing SSR should not
* record new registration
@@ -116,7 +115,7 @@
else
pr_err("diag: drop reg proc %d\n",
smd_info->peripheral);
- kfree(temp);
+ kfree(pkt_params->params);
} else if ((type == DIAG_CTRL_MSG_FEATURE) &&
(smd_info->peripheral == MODEM_DATA)) {
feature_mask_len = *(int *)(buf + 8);
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index b0fb9d8..e946b42 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -32,7 +32,6 @@
#include <mach/msm_bus.h>
#include <mach/msm_bus_board.h>
#endif
-#include <mach/msm_subsystem_map.h>
#include <mach/iommu_domains.h>
#define DRIVER_NAME "msm_rotator"
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index 8545a5c..ba0fd7c 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -40,7 +40,6 @@
#define CRYPTO_CONFIG_RESET 0xE001F
#define QCE_MAX_NUM_DSCR 0x400
-#define QCE_SIZE_BAM_DSCR 0x08
#define QCE_SECTOR_SIZE 0x200
static DEFINE_MUTEX(bam_register_cnt);
@@ -1095,7 +1094,8 @@
* descriptor memory (256 bytes + 8 bytes). But in order to be
* in power of 2, we are allocating 512 bytes of memory.
*/
- sps_connect_info->desc.size = QCE_MAX_NUM_DSCR * QCE_SIZE_BAM_DSCR;
+ sps_connect_info->desc.size = QCE_MAX_NUM_DSCR *
+ sizeof(struct sps_iovec);
sps_connect_info->desc.base = dma_alloc_coherent(pce_dev->pdev,
sps_connect_info->desc.size,
&sps_connect_info->desc.phys_base,
@@ -2216,12 +2216,12 @@
pce_dev->ce_sps.in_transfer.iovec = (struct sps_iovec *)vaddr;
pce_dev->ce_sps.in_transfer.iovec_phys =
(uint32_t)GET_PHYS_ADDR(vaddr);
- vaddr += MAX_BAM_DESCRIPTORS * 8;
+ vaddr += QCE_MAX_NUM_DSCR * sizeof(struct sps_iovec);
pce_dev->ce_sps.out_transfer.iovec = (struct sps_iovec *)vaddr;
pce_dev->ce_sps.out_transfer.iovec_phys =
(uint32_t)GET_PHYS_ADDR(vaddr);
- vaddr += MAX_BAM_DESCRIPTORS * 8;
+ vaddr += QCE_MAX_NUM_DSCR * sizeof(struct sps_iovec);
qce_setup_cmdlistptrs(pce_dev, &vaddr);
vaddr = (unsigned char *) ALIGN(((unsigned int)vaddr),
diff --git a/drivers/crypto/msm/qce50.h b/drivers/crypto/msm/qce50.h
index dc4ccf7..f5123df 100644
--- a/drivers/crypto/msm/qce50.h
+++ b/drivers/crypto/msm/qce50.h
@@ -17,7 +17,6 @@
/* MAX Data xfer block size between BAM and CE */
#define MAX_CE_BAM_BURST_SIZE 0x40
#define QCEBAM_BURST_SIZE MAX_CE_BAM_BURST_SIZE
-#define MAX_BAM_DESCRIPTORS (0x40 - 1)
#define GET_VIRT_ADDR(x) \
((uint32_t)pce_dev->coh_vmem + \
diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 9128177..ce25bfd 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -39,7 +39,6 @@
#include <mach/iommu_domains.h>
#include "ion_priv.h"
-#define DEBUG
/**
* struct ion_device - the metadata of the ion device node
@@ -107,6 +106,12 @@
unsigned int iommu_map_cnt;
};
+bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer)
+{
+ return ((buffer->flags & ION_FLAG_CACHED) &&
+ !(buffer->flags & ION_FLAG_CACHED_NEEDS_SYNC));
+}
+
static void ion_iommu_release(struct kref *kref);
/* this function should only be called while dev->lock is held */
@@ -190,6 +195,8 @@
return NULL;
}
+static int ion_buffer_alloc_dirty(struct ion_buffer *buffer);
+
/* this function should only be called while dev->lock is held */
static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
struct ion_device *dev,
@@ -199,13 +206,15 @@
{
struct ion_buffer *buffer;
struct sg_table *table;
- int ret;
+ struct scatterlist *sg;
+ int i, ret;
buffer = kzalloc(sizeof(struct ion_buffer), GFP_KERNEL);
if (!buffer)
return ERR_PTR(-ENOMEM);
buffer->heap = heap;
+ buffer->flags = flags;
kref_init(&buffer->ref);
ret = heap->ops->allocate(heap, buffer, len, align, flags);
@@ -216,19 +225,54 @@
buffer->dev = dev;
buffer->size = len;
- buffer->flags = flags;
- table = buffer->heap->ops->map_dma(buffer->heap, buffer);
+ table = heap->ops->map_dma(heap, buffer);
if (IS_ERR_OR_NULL(table)) {
heap->ops->free(buffer);
kfree(buffer);
return ERR_PTR(PTR_ERR(table));
}
buffer->sg_table = table;
+ if (ion_buffer_fault_user_mappings(buffer)) {
+ for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents,
+ i) {
+ if (sg_dma_len(sg) == PAGE_SIZE)
+ continue;
+ pr_err("%s: cached mappings that will be faulted in "
+ "must have pagewise sg_lists\n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+ ret = ion_buffer_alloc_dirty(buffer);
+ if (ret)
+ goto err;
+ }
+
+ buffer->dev = dev;
+ buffer->size = len;
+ INIT_LIST_HEAD(&buffer->vmas);
mutex_init(&buffer->lock);
+ /* this will set up dma addresses for the sglist -- it is not
+ technically correct as per the dma api -- a specific
+ device isn't really taking ownership here. However, in practice on
+ our systems the only dma_address space is physical addresses.
+ Additionally, we can't afford the overhead of invalidating every
+ allocation via dma_map_sg. The implicit contract here is that
+ memory comming from the heaps is ready for dma, ie if it has a
+ cached mapping that mapping has been invalidated */
+ for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) {
+ if (sg_dma_address(sg) == 0)
+ sg_dma_address(sg) = sg_phys(sg);
+ }
ion_buffer_add(dev, buffer);
return buffer;
+
+err:
+ heap->ops->unmap_dma(heap, buffer);
+ heap->ops->free(buffer);
+ kfree(buffer);
+ return ERR_PTR(ret);
}
/**
@@ -276,7 +320,6 @@
if (WARN_ON(buffer->kmap_cnt > 0))
buffer->heap->ops->unmap_kernel(buffer->heap, buffer);
-
buffer->heap->ops->unmap_dma(buffer->heap, buffer);
ion_delayed_unsecure(buffer);
@@ -285,6 +328,8 @@
mutex_lock(&dev->lock);
rb_erase(&buffer->node, &dev->buffers);
mutex_unlock(&dev->lock);
+ if (buffer->flags & ION_FLAG_CACHED)
+ kfree(buffer->dirty);
kfree(buffer);
}
@@ -419,6 +464,16 @@
dbg_str[0] = '\0';
/*
+ * For now, we don't want to fault in pages individually since
+ * clients are already doing manual cache maintenance. In
+ * other words, the implicit caching infrastructure is in
+ * place (in code) but should not be used.
+ */
+ flags |= ION_FLAG_CACHED_NEEDS_SYNC;
+
+ pr_debug("%s: len %d align %d heap_mask %u flags %x\n", __func__, len,
+ align, heap_mask, flags);
+ /*
* traverse the list of heaps available in this system in priority
* order. If the heap type is supported by the client, and matches the
* request of the caller allocate from it. Repeat until allocate has
@@ -1205,12 +1260,47 @@
}
EXPORT_SYMBOL(ion_sg_table);
+struct sg_table *ion_create_chunked_sg_table(phys_addr_t buffer_base,
+ size_t chunk_size, size_t total_size)
+{
+ struct sg_table *table;
+ int i, n_chunks, ret;
+ struct scatterlist *sg;
+
+ table = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
+ if (!table)
+ return ERR_PTR(-ENOMEM);
+
+ n_chunks = DIV_ROUND_UP(total_size, chunk_size);
+ pr_debug("creating sg_table with %d chunks\n", n_chunks);
+
+ ret = sg_alloc_table(table, n_chunks, GFP_KERNEL);
+ if (ret)
+ goto err0;
+
+ for_each_sg(table->sgl, sg, table->nents, i) {
+ dma_addr_t addr = buffer_base + i * chunk_size;
+ sg_dma_address(sg) = addr;
+ sg_dma_len(sg) = chunk_size;
+ }
+
+ return table;
+err0:
+ kfree(table);
+ return ERR_PTR(ret);
+}
+
+static void ion_buffer_sync_for_device(struct ion_buffer *buffer,
+ struct device *dev,
+ enum dma_data_direction direction);
+
static struct sg_table *ion_map_dma_buf(struct dma_buf_attachment *attachment,
enum dma_data_direction direction)
{
struct dma_buf *dmabuf = attachment->dmabuf;
struct ion_buffer *buffer = dmabuf->priv;
+ ion_buffer_sync_for_device(buffer, attachment->dev, direction);
return buffer->sg_table;
}
@@ -1220,24 +1310,119 @@
{
}
-static void ion_vma_close(struct vm_area_struct *vma)
+static int ion_buffer_alloc_dirty(struct ion_buffer *buffer)
+{
+ unsigned long pages = buffer->sg_table->nents;
+ unsigned long length = (pages + BITS_PER_LONG - 1)/BITS_PER_LONG;
+
+ buffer->dirty = kzalloc(length * sizeof(unsigned long), GFP_KERNEL);
+ if (!buffer->dirty)
+ return -ENOMEM;
+ return 0;
+}
+
+struct ion_vma_list {
+ struct list_head list;
+ struct vm_area_struct *vma;
+};
+
+static void ion_buffer_sync_for_device(struct ion_buffer *buffer,
+ struct device *dev,
+ enum dma_data_direction dir)
+{
+ struct scatterlist *sg;
+ int i;
+ struct ion_vma_list *vma_list;
+
+ pr_debug("%s: syncing for device %s\n", __func__,
+ dev ? dev_name(dev) : "null");
+
+ if (!ion_buffer_fault_user_mappings(buffer))
+ return;
+
+ mutex_lock(&buffer->lock);
+ for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) {
+ if (!test_bit(i, buffer->dirty))
+ continue;
+ dma_sync_sg_for_device(dev, sg, 1, dir);
+ clear_bit(i, buffer->dirty);
+ }
+ list_for_each_entry(vma_list, &buffer->vmas, list) {
+ struct vm_area_struct *vma = vma_list->vma;
+
+ zap_page_range(vma, vma->vm_start, vma->vm_end - vma->vm_start,
+ NULL);
+ }
+ mutex_unlock(&buffer->lock);
+}
+
+int ion_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct ion_buffer *buffer = vma->vm_private_data;
+ struct scatterlist *sg;
+ int i;
- pr_debug("%s: %d\n", __func__, __LINE__);
+ mutex_lock(&buffer->lock);
+ set_bit(vmf->pgoff, buffer->dirty);
+
+ for_each_sg(buffer->sg_table->sgl, sg, buffer->sg_table->nents, i) {
+ if (i != vmf->pgoff)
+ continue;
+ dma_sync_sg_for_cpu(NULL, sg, 1, DMA_BIDIRECTIONAL);
+ vm_insert_page(vma, (unsigned long)vmf->virtual_address,
+ sg_page(sg));
+ break;
+ }
+ mutex_unlock(&buffer->lock);
+ return VM_FAULT_NOPAGE;
+}
+
+static void ion_vm_open(struct vm_area_struct *vma)
+{
+ struct ion_buffer *buffer = vma->vm_private_data;
+ struct ion_vma_list *vma_list;
+
+ vma_list = kmalloc(sizeof(struct ion_vma_list), GFP_KERNEL);
+ if (!vma_list)
+ return;
+ vma_list->vma = vma;
+ mutex_lock(&buffer->lock);
+ list_add(&vma_list->list, &buffer->vmas);
+ mutex_unlock(&buffer->lock);
+ pr_debug("%s: adding %p\n", __func__, vma);
+}
+
+static void ion_vm_close(struct vm_area_struct *vma)
+{
+ struct ion_buffer *buffer = vma->vm_private_data;
+ struct ion_vma_list *vma_list, *tmp;
+
+ pr_debug("%s\n", __func__);
+ mutex_lock(&buffer->lock);
+ list_for_each_entry_safe(vma_list, tmp, &buffer->vmas, list) {
+ if (vma_list->vma != vma)
+ continue;
+ list_del(&vma_list->list);
+ kfree(vma_list);
+ pr_debug("%s: deleting %p\n", __func__, vma);
+ break;
+ }
+ mutex_unlock(&buffer->lock);
if (buffer->heap->ops->unmap_user)
buffer->heap->ops->unmap_user(buffer->heap, buffer);
}
-static struct vm_operations_struct ion_vm_ops = {
- .close = ion_vma_close,
+struct vm_operations_struct ion_vma_ops = {
+ .open = ion_vm_open,
+ .close = ion_vm_close,
+ .fault = ion_vm_fault,
};
static int ion_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
{
struct ion_buffer *buffer = dmabuf->priv;
- int ret;
+ int ret = 0;
if (!buffer->heap->ops->map_user) {
pr_err("%s: this heap does not define a method for mapping "
@@ -1245,22 +1430,26 @@
return -EINVAL;
}
+ if (ion_buffer_fault_user_mappings(buffer)) {
+ vma->vm_private_data = buffer;
+ vma->vm_ops = &ion_vma_ops;
+ vma->vm_flags |= VM_MIXEDMAP;
+ ion_vm_open(vma);
+ return 0;
+ }
+
+ if (!(buffer->flags & ION_FLAG_CACHED))
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
mutex_lock(&buffer->lock);
/* now map it to userspace */
ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma);
mutex_unlock(&buffer->lock);
- if (ret) {
+ if (ret)
pr_err("%s: failure mapping buffer to userspace\n",
__func__);
- } else {
- vma->vm_ops = &ion_vm_ops;
- /*
- * move the buffer into the vm_private_data so we can access it
- * from vma_open/close
- */
- vma->vm_private_data = buffer;
- }
+
return ret;
}
@@ -1396,6 +1585,30 @@
}
EXPORT_SYMBOL(ion_import_dma_buf);
+static int ion_sync_for_device(struct ion_client *client, int fd)
+{
+ struct dma_buf *dmabuf;
+ struct ion_buffer *buffer;
+
+ dmabuf = dma_buf_get(fd);
+ if (IS_ERR_OR_NULL(dmabuf))
+ return PTR_ERR(dmabuf);
+
+ /* if this memory came from ion */
+ if (dmabuf->ops != &dma_buf_ops) {
+ pr_err("%s: can not sync dmabuf from another exporter\n",
+ __func__);
+ dma_buf_put(dmabuf);
+ return -EINVAL;
+ }
+ buffer = dmabuf->priv;
+
+ dma_sync_sg_for_device(NULL, buffer->sg_table->sgl,
+ buffer->sg_table->nents, DMA_BIDIRECTIONAL);
+ dma_buf_put(dmabuf);
+ return 0;
+}
+
static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct ion_client *client = filp->private_data;
@@ -1468,6 +1681,15 @@
return ret;
break;
}
+ case ION_IOC_SYNC:
+ {
+ struct ion_fd_data data;
+ if (copy_from_user(&data, (void __user *)arg,
+ sizeof(struct ion_fd_data)))
+ return -EFAULT;
+ ion_sync_for_device(client, data.fd);
+ break;
+ }
case ION_IOC_CUSTOM:
{
struct ion_device *dev = client->dev;
diff --git a/drivers/gpu/ion/ion_carveout_heap.c b/drivers/gpu/ion/ion_carveout_heap.c
index 798c027..9610dfe 100644
--- a/drivers/gpu/ion/ion_carveout_heap.c
+++ b/drivers/gpu/ion/ion_carveout_heap.c
@@ -112,26 +112,13 @@
struct sg_table *ion_carveout_heap_map_dma(struct ion_heap *heap,
struct ion_buffer *buffer)
{
- struct sg_table *table;
- int ret;
+ size_t chunk_size = buffer->size;
- table = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
- if (!table)
- return ERR_PTR(-ENOMEM);
+ if (ION_IS_CACHED(buffer->flags))
+ chunk_size = PAGE_SIZE;
- ret = sg_alloc_table(table, 1, GFP_KERNEL);
- if (ret)
- goto err0;
-
- table->sgl->length = buffer->size;
- table->sgl->offset = 0;
- table->sgl->dma_address = buffer->priv_phys;
-
- return table;
-
-err0:
- kfree(table);
- return ERR_PTR(ret);
+ return ion_create_chunked_sg_table(buffer->priv_phys, chunk_size,
+ buffer->size);
}
void ion_carveout_heap_unmap_dma(struct ion_heap *heap,
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index 8a5e5c9..7bcae01 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -26,7 +26,6 @@
#include <linux/vmalloc.h>
#include <linux/memory_alloc.h>
#include <linux/seq_file.h>
-#include <linux/fmem.h>
#include <linux/iommu.h>
#include <linux/dma-mapping.h>
#include <trace/events/kmem.h>
@@ -70,8 +69,6 @@
* user space.
* @iommu_iova: saved iova when mapping full heap at once.
* @iommu_partition: partition used to map full heap.
- * @reusable: indicates if the memory should be reused via fmem.
- * @reserved_vrange: reserved virtual address range for use with fmem
* @iommu_map_all: Indicates whether we should map whole heap into IOMMU.
* @iommu_2x_map_domain: Indicates the domain to use for overmapping.
* @has_outer_cache: set to 1 if outer cache is used, 0 otherwise.
@@ -95,7 +92,6 @@
unsigned long umap_count;
unsigned long iommu_iova[MAX_DOMAINS];
unsigned long iommu_partition[MAX_DOMAINS];
- int reusable;
void *reserved_vrange;
int iommu_map_all;
int iommu_2x_map_domain;
@@ -198,12 +194,6 @@
container_of(heap, struct ion_cp_heap, heap);
int ret_value;
- if (cp_heap->reusable) {
- ret_value = fmem_set_state(FMEM_C_STATE);
- if (ret_value)
- return 1;
- }
-
if (cp_heap->cma) {
ret_value = allocate_heap_memory(heap);
if (ret_value)
@@ -217,11 +207,6 @@
struct ion_cp_heap *cp_heap =
container_of(heap, struct ion_cp_heap, heap);
- if (cp_heap->reusable)
- if (fmem_set_state(FMEM_T_STATE) != 0)
- pr_err("%s: unable to transition heap to T-state\n",
- __func__);
-
if (cp_heap->cma)
free_heap_memory(heap);
}
@@ -457,6 +442,12 @@
struct ion_cp_buffer *buf;
phys_addr_t addr;
+ /*
+ * we never want Ion to fault pages in for us with this
+ * heap. We want to set up the mappings ourselves in .map_user
+ */
+ flags |= ION_FLAG_CACHED_NEEDS_SYNC;
+
buf = kzalloc(sizeof(*buf), GFP_KERNEL);
if (!buf)
return ION_CP_ALLOCATE_FAIL;
@@ -491,9 +482,6 @@
struct sg_table *ion_cp_heap_create_sg_table(struct ion_buffer *buffer)
{
size_t chunk_size = buffer->size;
- struct sg_table *table;
- int ret, i, n_chunks;
- struct scatterlist *sg;
struct ion_cp_buffer *buf = buffer->priv_virt;
if (ION_IS_CACHED(buffer->flags))
@@ -501,26 +489,8 @@
else if (buf->is_secure && IS_ALIGNED(buffer->size, SZ_1M))
chunk_size = SZ_1M;
- table = kzalloc(sizeof(struct sg_table), GFP_KERNEL);
- if (!table)
- return ERR_PTR(-ENOMEM);
-
- n_chunks = DIV_ROUND_UP(buffer->size, chunk_size);
-
- ret = sg_alloc_table(table, n_chunks, GFP_KERNEL);
- if (ret)
- goto err0;
-
- for_each_sg(table->sgl, sg, table->nents, i) {
- sg_dma_address(sg) = buf->buffer + i * chunk_size;
- sg->length = chunk_size;
- sg->offset = 0;
- }
-
- return table;
-err0:
- kfree(table);
- return ERR_PTR(ret);
+ return ion_create_chunked_sg_table(buf->buffer, chunk_size,
+ buffer->size);
}
struct sg_table *ion_cp_heap_map_dma(struct ion_heap *heap,
@@ -564,29 +534,6 @@
return ret_value;
}
-void *ion_map_fmem_buffer(struct ion_buffer *buffer, unsigned long phys_base,
- void *virt_base, unsigned long flags)
-{
- int ret;
- struct ion_cp_buffer *buf = buffer->priv_virt;
- unsigned int offset = buf->buffer - phys_base;
- unsigned long start = ((unsigned long)virt_base) + offset;
- const struct mem_type *type = ION_IS_CACHED(flags) ?
- get_mem_type(MT_DEVICE_CACHED) :
- get_mem_type(MT_DEVICE);
-
- if (phys_base > buf->buffer)
- return NULL;
-
-
- ret = ioremap_pages(start, buf->buffer, buffer->size, type);
-
- if (!ret)
- return (void *)start;
- else
- return NULL;
-}
-
void *ion_cp_heap_map_kernel(struct ion_heap *heap, struct ion_buffer *buffer)
{
struct ion_cp_heap *cp_heap =
@@ -604,10 +551,7 @@
return NULL;
}
- if (cp_heap->reusable) {
- ret_value = ion_map_fmem_buffer(buffer, cp_heap->base,
- cp_heap->reserved_vrange, buffer->flags);
- } else if (cp_heap->cma) {
+ if (cp_heap->cma) {
int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE;
struct page **pages = vmalloc(
sizeof(struct page *) * npages);
@@ -660,9 +604,7 @@
container_of(heap, struct ion_cp_heap, heap);
struct ion_cp_buffer *buf = buffer->priv_virt;
- if (cp_heap->reusable)
- unmap_kernel_range((unsigned long)buffer->vaddr, buffer->size);
- else if (cp_heap->cma)
+ if (cp_heap->cma)
vunmap(buffer->vaddr);
else
__arm_iounmap(buffer->vaddr);
@@ -841,7 +783,6 @@
seq_printf(s, "umapping count: %lx\n", umap_count);
seq_printf(s, "kmapping count: %lx\n", kmap_count);
seq_printf(s, "heap protected: %s\n", heap_protected ? "Yes" : "No");
- seq_printf(s, "reusable: %s\n", cp_heap->reusable ? "Yes" : "No");
if (mem_map) {
unsigned long base = cp_heap->base;
@@ -1166,8 +1107,6 @@
if (heap_data->extra_data) {
struct ion_cp_heap_pdata *extra_data =
heap_data->extra_data;
- cp_heap->reusable = extra_data->reusable;
- cp_heap->reserved_vrange = extra_data->virt_addr;
cp_heap->permission_type = extra_data->permission_type;
if (extra_data->secure_size) {
cp_heap->secure_base = extra_data->secure_base;
diff --git a/drivers/gpu/ion/ion_heap.c b/drivers/gpu/ion/ion_heap.c
index 46fefb5..510b9ce 100644
--- a/drivers/gpu/ion/ion_heap.c
+++ b/drivers/gpu/ion/ion_heap.c
@@ -18,13 +18,12 @@
#include <linux/err.h>
#include <linux/ion.h>
#include "ion_priv.h"
-#include <linux/msm_ion.h>
struct ion_heap *ion_heap_create(struct ion_platform_heap *heap_data)
{
struct ion_heap *heap = NULL;
- switch ((int) heap_data->type) {
+ switch (heap_data->type) {
case ION_HEAP_TYPE_SYSTEM_CONTIG:
heap = ion_system_contig_heap_create(heap_data);
break;
@@ -34,21 +33,6 @@
case ION_HEAP_TYPE_CARVEOUT:
heap = ion_carveout_heap_create(heap_data);
break;
- case ION_HEAP_TYPE_IOMMU:
- heap = ion_iommu_heap_create(heap_data);
- break;
- case ION_HEAP_TYPE_CP:
- heap = ion_cp_heap_create(heap_data);
- break;
-#ifdef CONFIG_CMA
- case ION_HEAP_TYPE_DMA:
- heap = ion_cma_heap_create(heap_data);
- break;
-
- case ION_HEAP_TYPE_SECURE_DMA:
- heap = ion_secure_cma_heap_create(heap_data);
- break;
-#endif
default:
pr_err("%s: Invalid heap type %d\n", __func__,
heap_data->type);
@@ -73,7 +57,7 @@
if (!heap)
return;
- switch ((int) heap->type) {
+ switch (heap->type) {
case ION_HEAP_TYPE_SYSTEM_CONTIG:
ion_system_contig_heap_destroy(heap);
break;
@@ -83,20 +67,6 @@
case ION_HEAP_TYPE_CARVEOUT:
ion_carveout_heap_destroy(heap);
break;
- case ION_HEAP_TYPE_IOMMU:
- ion_iommu_heap_destroy(heap);
- break;
- case ION_HEAP_TYPE_CP:
- ion_cp_heap_destroy(heap);
- break;
-#ifdef CONFIG_CMA
- case ION_HEAP_TYPE_DMA:
- ion_cma_heap_destroy(heap);
- break;
- case ION_HEAP_TYPE_SECURE_DMA:
- ion_secure_cma_heap_destroy(heap);
- break;
-#endif
default:
pr_err("%s: Invalid heap type %d\n", __func__,
heap->type);
diff --git a/drivers/gpu/ion/ion_iommu_heap.c b/drivers/gpu/ion/ion_iommu_heap.c
index 9ab6b85..512ebf3 100644
--- a/drivers/gpu/ion/ion_iommu_heap.c
+++ b/drivers/gpu/ion/ion_iommu_heap.c
@@ -76,10 +76,14 @@
if (max_order < orders[i])
continue;
- gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_COMP;
- if (orders[i])
- gfp |= __GFP_NOWARN;
+ gfp = __GFP_HIGHMEM;
+ if (orders[i]) {
+ gfp |= __GFP_COMP | __GFP_NORETRY |
+ __GFP_NO_KSWAPD | __GFP_NOWARN;
+ } else {
+ gfp |= GFP_KERNEL;
+ }
page = alloc_pages(gfp, orders[i]);
if (!page)
continue;
diff --git a/drivers/gpu/ion/ion_priv.h b/drivers/gpu/ion/ion_priv.h
index 2ab2ed6..28ef1a5 100644
--- a/drivers/gpu/ion/ion_priv.h
+++ b/drivers/gpu/ion/ion_priv.h
@@ -98,6 +98,8 @@
void *vaddr;
int dmap_cnt;
struct sg_table *sg_table;
+ unsigned long *dirty;
+ struct list_head vmas;
unsigned int iommu_map_cnt;
struct rb_root iommu_maps;
int marked;
@@ -179,6 +181,15 @@
};
/**
+ * ion_buffer_fault_user_mappings - fault in user mappings of this buffer
+ * @buffer: buffer
+ *
+ * indicates whether userspace mappings of this buffer will be faulted
+ * in, this can affect how buffers are allocated from the heap.
+ */
+bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer);
+
+/**
* struct mem_map_data - represents information about the memory map for a heap
* @node: rb node used to store in the tree of mem_map_data
* @addr: start address of memory region.
@@ -330,4 +341,16 @@
int ion_heap_allow_heap_secure(enum ion_heap_type type);
int ion_heap_allow_handle_secure(enum ion_heap_type type);
+
+/**
+ * ion_create_chunked_sg_table - helper function to create sg table
+ * with specified chunk size
+ * @buffer_base: The starting address used for the sg dma address
+ * @chunk_size: The size of each entry in the sg table
+ * @total_size: The total size of the sg table (i.e. the sum of the
+ * entries). This will be rounded up to the nearest
+ * multiple of `chunk_size'
+ */
+struct sg_table *ion_create_chunked_sg_table(phys_addr_t buffer_base,
+ size_t chunk_size, size_t total_size);
#endif /* _ION_PRIV_H */
diff --git a/drivers/gpu/ion/ion_system_heap.c b/drivers/gpu/ion/ion_system_heap.c
index 7046709..ceb30a4 100644
--- a/drivers/gpu/ion/ion_system_heap.c
+++ b/drivers/gpu/ion/ion_system_heap.c
@@ -15,7 +15,10 @@
*
*/
+#include <asm/page.h>
+#include <linux/dma-mapping.h>
#include <linux/err.h>
+#include <linux/highmem.h>
#include <linux/ion.h>
#include <linux/mm.h>
#include <linux/scatterlist.h>
@@ -35,6 +38,37 @@
static unsigned int system_heap_has_outer_cache;
static unsigned int system_heap_contig_has_outer_cache;
+struct page_info {
+ struct page *page;
+ unsigned long order;
+ struct list_head list;
+};
+
+static struct page_info *alloc_largest_available(unsigned long size,
+ bool split_pages)
+{
+ static unsigned int orders[] = {8, 4, 0};
+ struct page *page;
+ struct page_info *info;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(orders); i++) {
+ if (size < (1 << orders[i]) * PAGE_SIZE)
+ continue;
+ page = alloc_pages(GFP_HIGHUSER | __GFP_ZERO |
+ __GFP_NOWARN | __GFP_NORETRY, orders[i]);
+ if (!page)
+ continue;
+ if (split_pages)
+ split_page(page, orders[i]);
+ info = kmap(page);
+ info->page = page;
+ info->order = orders[i];
+ return info;
+ }
+ return NULL;
+}
+
static int ion_system_heap_allocate(struct ion_heap *heap,
struct ion_buffer *buffer,
unsigned long size, unsigned long align,
@@ -42,31 +76,73 @@
{
struct sg_table *table;
struct scatterlist *sg;
- int i, j;
- int npages = PAGE_ALIGN(size) / PAGE_SIZE;
+ int ret;
+ struct list_head pages;
+ struct page_info *info, *tmp_info;
+ int i = 0;
+ long size_remaining = PAGE_ALIGN(size);
+ bool split_pages = ion_buffer_fault_user_mappings(buffer);
+
+
+ INIT_LIST_HEAD(&pages);
+ while (size_remaining > 0) {
+ info = alloc_largest_available(size_remaining, split_pages);
+ if (!info)
+ goto err;
+ list_add_tail(&info->list, &pages);
+ size_remaining -= (1 << info->order) * PAGE_SIZE;
+ i++;
+ }
table = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
if (!table)
- return -ENOMEM;
- i = sg_alloc_table(table, npages, GFP_KERNEL);
- if (i)
- goto err0;
- for_each_sg(table->sgl, sg, table->nents, i) {
- struct page *page;
- page = alloc_page(GFP_KERNEL|__GFP_ZERO);
- if (!page)
- goto err1;
- sg_set_page(sg, page, PAGE_SIZE, 0);
+ goto err;
+
+ if (split_pages)
+ ret = sg_alloc_table(table, PAGE_ALIGN(size) / PAGE_SIZE,
+ GFP_KERNEL);
+ else
+ ret = sg_alloc_table(table, i, GFP_KERNEL);
+
+ if (ret)
+ goto err1;
+
+ sg = table->sgl;
+ list_for_each_entry_safe(info, tmp_info, &pages, list) {
+ struct page *page = info->page;
+
+ if (split_pages) {
+ for (i = 0; i < (1 << info->order); i++) {
+ sg_set_page(sg, page + i, PAGE_SIZE, 0);
+ sg = sg_next(sg);
+ }
+ } else {
+ sg_set_page(sg, page, (1 << info->order) * PAGE_SIZE,
+ 0);
+ sg = sg_next(sg);
+ }
+ list_del(&info->list);
+ kunmap(page);
}
+
+ dma_sync_sg_for_device(NULL, table->sgl, table->nents,
+ DMA_BIDIRECTIONAL);
+
buffer->priv_virt = table;
atomic_add(size, &system_heap_allocated);
return 0;
err1:
- for_each_sg(table->sgl, sg, i, j)
- __free_page(sg_page(sg));
- sg_free_table(table);
-err0:
kfree(table);
+err:
+ list_for_each_entry(info, &pages, list) {
+ if (split_pages)
+ for (i = 0; i < (1 << info->order); i++)
+ __free_page(info->page + i);
+ else
+ __free_pages(info->page, info->order);
+
+ kunmap(info->page);
+ }
return -ENOMEM;
}
@@ -77,7 +153,7 @@
struct sg_table *table = buffer->priv_virt;
for_each_sg(table->sgl, sg, table->nents, i)
- __free_page(sg_page(sg));
+ __free_pages(sg_page(sg), get_order(sg_dma_len(sg)));
if (buffer->sg_table)
sg_free_table(buffer->sg_table);
kfree(buffer->sg_table);
@@ -99,25 +175,33 @@
void *ion_system_heap_map_kernel(struct ion_heap *heap,
struct ion_buffer *buffer)
{
- if (!ION_IS_CACHED(buffer->flags)) {
- pr_err("%s: cannot map system heap uncached\n", __func__);
- return ERR_PTR(-EINVAL);
- } else {
- struct scatterlist *sg;
- int i;
- void *vaddr;
- struct sg_table *table = buffer->priv_virt;
- struct page **pages = kmalloc(
- sizeof(struct page *) * table->nents,
- GFP_KERNEL);
+ struct scatterlist *sg;
+ int i, j;
+ void *vaddr;
+ pgprot_t pgprot;
+ struct sg_table *table = buffer->priv_virt;
+ int npages = PAGE_ALIGN(buffer->size) / PAGE_SIZE;
+ struct page **pages = kzalloc(sizeof(struct page *) * npages,
+ GFP_KERNEL);
+ struct page **tmp = pages;
- for_each_sg(table->sgl, sg, table->nents, i)
- pages[i] = sg_page(sg);
- vaddr = vmap(pages, table->nents, VM_MAP, PAGE_KERNEL);
- kfree(pages);
+ if (buffer->flags & ION_FLAG_CACHED)
+ pgprot = PAGE_KERNEL;
+ else
+ pgprot = pgprot_writecombine(PAGE_KERNEL);
- return vaddr;
+ for_each_sg(table->sgl, sg, table->nents, i) {
+ int npages_this_entry = PAGE_ALIGN(sg_dma_len(sg)) / PAGE_SIZE;
+ struct page *page = sg_page(sg);
+ BUG_ON(i >= npages);
+ for (j = 0; j < npages_this_entry; j++) {
+ *(tmp++) = page++;
+ }
}
+ vaddr = vmap(pages, npages, VM_MAP, pgprot);
+ kfree(pages);
+
+ return vaddr;
}
void ion_system_heap_unmap_kernel(struct ion_heap *heap,
@@ -155,26 +239,27 @@
int ion_system_heap_map_user(struct ion_heap *heap, struct ion_buffer *buffer,
struct vm_area_struct *vma)
{
+ struct sg_table *table = buffer->priv_virt;
+ unsigned long addr = vma->vm_start;
+ unsigned long offset = vma->vm_pgoff;
+ struct scatterlist *sg;
+ int i;
+
if (!ION_IS_CACHED(buffer->flags)) {
pr_err("%s: cannot map system heap uncached\n", __func__);
return -EINVAL;
- } else {
- struct sg_table *table = buffer->priv_virt;
- unsigned long addr = vma->vm_start;
- unsigned long offset = vma->vm_pgoff;
- struct scatterlist *sg;
- int i;
-
- for_each_sg(table->sgl, sg, table->nents, i) {
- if (offset) {
- offset--;
- continue;
- }
- vm_insert_page(vma, addr, sg_page(sg));
- addr += PAGE_SIZE;
- }
- return 0;
}
+
+ for_each_sg(table->sgl, sg, table->nents, i) {
+ if (offset) {
+ offset--;
+ continue;
+ }
+ remap_pfn_range(vma, addr, page_to_pfn(sg_page(sg)),
+ sg_dma_len(sg), vma->vm_page_prot);
+ addr += sg_dma_len(sg);
+ }
+ return 0;
}
int ion_system_heap_cache_ops(struct ion_heap *heap, struct ion_buffer *buffer,
@@ -382,7 +467,7 @@
}
struct sg_table *ion_system_contig_heap_map_dma(struct ion_heap *heap,
- struct ion_buffer *buffer)
+ struct ion_buffer *buffer)
{
struct sg_table *table;
int ret;
@@ -400,6 +485,13 @@
return table;
}
+void ion_system_contig_heap_unmap_dma(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ sg_free_table(buffer->sg_table);
+ kfree(buffer->sg_table);
+}
+
int ion_system_contig_heap_map_user(struct ion_heap *heap,
struct ion_buffer *buffer,
struct vm_area_struct *vma)
@@ -561,7 +653,7 @@
.free = ion_system_contig_heap_free,
.phys = ion_system_contig_heap_phys,
.map_dma = ion_system_contig_heap_map_dma,
- .unmap_dma = ion_system_heap_unmap_dma,
+ .unmap_dma = ion_system_contig_heap_unmap_dma,
.map_kernel = ion_system_contig_heap_map_kernel,
.unmap_kernel = ion_system_contig_heap_unmap_kernel,
.map_user = ion_system_contig_heap_map_user,
diff --git a/drivers/gpu/ion/msm/ion_cp_common.c b/drivers/gpu/ion/msm/ion_cp_common.c
index 48c2efb..7d54cfa 100644
--- a/drivers/gpu/ion/msm/ion_cp_common.c
+++ b/drivers/gpu/ion/msm/ion_cp_common.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2011 Google, Inc
- * 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
@@ -20,6 +20,7 @@
#include "ion_cp_common.h"
#define MEM_PROTECT_LOCK_ID 0x05
+#define MEM_PROTECT_LOCK_ID2 0x0A
struct cp2_mem_chunks {
unsigned int *chunk_list;
@@ -27,10 +28,11 @@
unsigned int chunk_size;
} __attribute__ ((__packed__));
-struct cp2_lock_req {
+struct cp2_lock2_req {
struct cp2_mem_chunks chunks;
unsigned int mem_usage;
unsigned int lock;
+ unsigned int flags;
} __attribute__ ((__packed__));
/* SCM related code for locking down memory for content protection */
@@ -144,17 +146,18 @@
enum cp_mem_usage usage,
int lock)
{
- struct cp2_lock_req request;
+ struct cp2_lock2_req request;
u32 resp;
request.mem_usage = usage;
request.lock = lock;
+ request.flags = 0;
request.chunks.chunk_list = (unsigned int *)chunks;
request.chunks.chunk_list_size = nchunks;
request.chunks.chunk_size = chunk_size;
- return scm_call(SCM_SVC_MP, MEM_PROTECT_LOCK_ID,
+ return scm_call(SCM_SVC_MP, MEM_PROTECT_LOCK_ID2,
&request, sizeof(request), &resp, sizeof(resp));
}
diff --git a/drivers/gpu/ion/msm/msm_ion.c b/drivers/gpu/ion/msm/msm_ion.c
index 33e6fed..4b55875 100644
--- a/drivers/gpu/ion/msm/msm_ion.c
+++ b/drivers/gpu/ion/msm/msm_ion.c
@@ -750,6 +750,68 @@
return 0;
}
+static struct ion_heap *msm_ion_heap_create(struct ion_platform_heap *heap_data)
+{
+ struct ion_heap *heap = NULL;
+
+ switch ((int)heap_data->type) {
+ case ION_HEAP_TYPE_IOMMU:
+ heap = ion_iommu_heap_create(heap_data);
+ break;
+ case ION_HEAP_TYPE_CP:
+ heap = ion_cp_heap_create(heap_data);
+ break;
+#ifdef CONFIG_CMA
+ case ION_HEAP_TYPE_DMA:
+ heap = ion_cma_heap_create(heap_data);
+ break;
+
+ case ION_HEAP_TYPE_SECURE_DMA:
+ heap = ion_secure_cma_heap_create(heap_data);
+ break;
+#endif
+ default:
+ heap = ion_heap_create(heap_data);
+ }
+
+ if (IS_ERR_OR_NULL(heap)) {
+ pr_err("%s: error creating heap %s type %d base %pa size %u\n",
+ __func__, heap_data->name, heap_data->type,
+ &heap_data->base, heap_data->size);
+ return ERR_PTR(-EINVAL);
+ }
+
+ heap->name = heap_data->name;
+ heap->id = heap_data->id;
+ heap->priv = heap_data->priv;
+ return heap;
+}
+
+static void msm_ion_heap_destroy(struct ion_heap *heap)
+{
+ if (!heap)
+ return;
+
+ switch ((int)heap->type) {
+ case ION_HEAP_TYPE_IOMMU:
+ ion_iommu_heap_destroy(heap);
+ break;
+ case ION_HEAP_TYPE_CP:
+ ion_cp_heap_destroy(heap);
+ break;
+#ifdef CONFIG_CMA
+ case ION_HEAP_TYPE_DMA:
+ ion_cma_heap_destroy(heap);
+ break;
+ case ION_HEAP_TYPE_SECURE_DMA:
+ ion_secure_cma_heap_destroy(heap);
+ break;
+#endif
+ default:
+ ion_heap_destroy(heap);
+ }
+}
+
static int msm_ion_probe(struct platform_device *pdev)
{
struct ion_platform_data *pdata;
@@ -791,7 +853,7 @@
msm_ion_allocate(heap_data);
heap_data->has_outer_cache = pdata->has_outer_cache;
- heaps[i] = ion_heap_create(heap_data);
+ heaps[i] = msm_ion_heap_create(heap_data);
if (IS_ERR_OR_NULL(heaps[i])) {
heaps[i] = 0;
continue;
@@ -829,7 +891,7 @@
int i;
for (i = 0; i < num_heaps; i++)
- ion_heap_destroy(heaps[i]);
+ msm_ion_heap_destroy(heaps[i]);
ion_device_destroy(idev);
kfree(heaps);
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index ed351bd..a2f0e60 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -66,15 +66,103 @@
#define A3XX_RBBM_INT_0_MASK 0x063
#define A3XX_RBBM_INT_0_STATUS 0x064
#define A3XX_RBBM_PERFCTR_CTL 0x80
+#define A3XX_RBBM_PERFCTR_LOAD_CMD0 0x81
+#define A3XX_RBBM_PERFCTR_LOAD_CMD1 0x82
+#define A3XX_RBBM_PERFCTR_LOAD_VALUE_LO 0x84
+#define A3XX_RBBM_PERFCTR_LOAD_VALUE_HI 0x85
+#define A3XX_RBBM_PERFCOUNTER0_SELECT 0x86
+#define A3XX_RBBM_PERFCOUNTER1_SELECT 0x87
#define A3XX_RBBM_GPU_BUSY_MASKED 0x88
+#define A3XX_RBBM_PERFCTR_CP_0_LO 0x90
+#define A3XX_RBBM_PERFCTR_CP_0_HI 0x91
+#define A3XX_RBBM_PERFCTR_RBBM_0_LO 0x92
+#define A3XX_RBBM_PERFCTR_RBBM_0_HI 0x93
+#define A3XX_RBBM_PERFCTR_RBBM_1_LO 0x94
+#define A3XX_RBBM_PERFCTR_RBBM_1_HI 0x95
+#define A3XX_RBBM_PERFCTR_PC_0_LO 0x96
+#define A3XX_RBBM_PERFCTR_PC_0_HI 0x97
+#define A3XX_RBBM_PERFCTR_PC_1_LO 0x98
+#define A3XX_RBBM_PERFCTR_PC_1_HI 0x99
+#define A3XX_RBBM_PERFCTR_PC_2_LO 0x9A
+#define A3XX_RBBM_PERFCTR_PC_2_HI 0x9B
+#define A3XX_RBBM_PERFCTR_PC_3_LO 0x9C
+#define A3XX_RBBM_PERFCTR_PC_3_HI 0x9D
+#define A3XX_RBBM_PERFCTR_VFD_0_LO 0x9E
+#define A3XX_RBBM_PERFCTR_VFD_0_HI 0x9F
+#define A3XX_RBBM_PERFCTR_VFD_1_LO 0xA0
+#define A3XX_RBBM_PERFCTR_VFD_1_HI 0xA1
+#define A3XX_RBBM_PERFCTR_HLSQ_0_LO 0xA2
+#define A3XX_RBBM_PERFCTR_HLSQ_0_HI 0xA3
+#define A3XX_RBBM_PERFCTR_HLSQ_1_LO 0xA4
+#define A3XX_RBBM_PERFCTR_HLSQ_1_HI 0xA5
+#define A3XX_RBBM_PERFCTR_HLSQ_2_LO 0xA6
+#define A3XX_RBBM_PERFCTR_HLSQ_2_HI 0xA7
+#define A3XX_RBBM_PERFCTR_HLSQ_3_LO 0xA8
+#define A3XX_RBBM_PERFCTR_HLSQ_3_HI 0xA9
+#define A3XX_RBBM_PERFCTR_HLSQ_4_LO 0xAA
+#define A3XX_RBBM_PERFCTR_HLSQ_4_HI 0xAB
+#define A3XX_RBBM_PERFCTR_HLSQ_5_LO 0xAC
+#define A3XX_RBBM_PERFCTR_HLSQ_5_HI 0xAD
+#define A3XX_RBBM_PERFCTR_VPC_0_LO 0xAE
+#define A3XX_RBBM_PERFCTR_VPC_0_HI 0xAF
+#define A3XX_RBBM_PERFCTR_VPC_1_LO 0xB0
+#define A3XX_RBBM_PERFCTR_VPC_1_HI 0xB1
+#define A3XX_RBBM_PERFCTR_TSE_0_LO 0xB2
+#define A3XX_RBBM_PERFCTR_TSE_0_HI 0xB3
+#define A3XX_RBBM_PERFCTR_TSE_1_LO 0xB4
+#define A3XX_RBBM_PERFCTR_TSE_1_HI 0xB5
+#define A3XX_RBBM_PERFCTR_RAS_0_LO 0xB6
+#define A3XX_RBBM_PERFCTR_RAS_0_HI 0xB7
+#define A3XX_RBBM_PERFCTR_RAS_1_LO 0xB8
+#define A3XX_RBBM_PERFCTR_RAS_1_HI 0xB9
+#define A3XX_RBBM_PERFCTR_UCHE_0_LO 0xBA
+#define A3XX_RBBM_PERFCTR_UCHE_0_HI 0xBB
+#define A3XX_RBBM_PERFCTR_UCHE_1_LO 0xBC
+#define A3XX_RBBM_PERFCTR_UCHE_1_HI 0xBD
+#define A3XX_RBBM_PERFCTR_UCHE_2_LO 0xBE
+#define A3XX_RBBM_PERFCTR_UCHE_2_HI 0xBF
+#define A3XX_RBBM_PERFCTR_UCHE_3_LO 0xC0
+#define A3XX_RBBM_PERFCTR_UCHE_3_HI 0xC1
+#define A3XX_RBBM_PERFCTR_UCHE_4_LO 0xC2
+#define A3XX_RBBM_PERFCTR_UCHE_4_HI 0xC3
+#define A3XX_RBBM_PERFCTR_UCHE_5_LO 0xC4
+#define A3XX_RBBM_PERFCTR_UCHE_5_HI 0xC5
+#define A3XX_RBBM_PERFCTR_TP_0_LO 0xC6
+#define A3XX_RBBM_PERFCTR_TP_0_HI 0xC7
+#define A3XX_RBBM_PERFCTR_TP_1_LO 0xC8
+#define A3XX_RBBM_PERFCTR_TP_1_HI 0xC9
+#define A3XX_RBBM_PERFCTR_TP_2_LO 0xCA
+#define A3XX_RBBM_PERFCTR_TP_2_HI 0xCB
+#define A3XX_RBBM_PERFCTR_TP_3_LO 0xCC
+#define A3XX_RBBM_PERFCTR_TP_3_HI 0xCD
+#define A3XX_RBBM_PERFCTR_TP_4_LO 0xCE
+#define A3XX_RBBM_PERFCTR_TP_4_HI 0xCF
+#define A3XX_RBBM_PERFCTR_TP_5_LO 0xD0
+#define A3XX_RBBM_PERFCTR_TP_5_HI 0xD1
+#define A3XX_RBBM_PERFCTR_SP_0_LO 0xD2
+#define A3XX_RBBM_PERFCTR_SP_0_HI 0xD3
+#define A3XX_RBBM_PERFCTR_SP_1_LO 0xD4
+#define A3XX_RBBM_PERFCTR_SP_1_HI 0xD5
+#define A3XX_RBBM_PERFCTR_SP_2_LO 0xD6
+#define A3XX_RBBM_PERFCTR_SP_2_HI 0xD7
+#define A3XX_RBBM_PERFCTR_SP_3_LO 0xD8
+#define A3XX_RBBM_PERFCTR_SP_3_HI 0xD9
+#define A3XX_RBBM_PERFCTR_SP_4_LO 0xDA
+#define A3XX_RBBM_PERFCTR_SP_4_HI 0xDB
#define A3XX_RBBM_PERFCTR_SP_5_LO 0xDC
#define A3XX_RBBM_PERFCTR_SP_5_HI 0xDD
#define A3XX_RBBM_PERFCTR_SP_6_LO 0xDE
#define A3XX_RBBM_PERFCTR_SP_6_HI 0xDF
#define A3XX_RBBM_PERFCTR_SP_7_LO 0xE0
#define A3XX_RBBM_PERFCTR_SP_7_HI 0xE1
+#define A3XX_RBBM_PERFCTR_RB_0_LO 0xE2
+#define A3XX_RBBM_PERFCTR_RB_0_HI 0xE3
+#define A3XX_RBBM_PERFCTR_RB_1_LO 0xE4
+#define A3XX_RBBM_PERFCTR_RB_1_HI 0xE5
+
#define A3XX_RBBM_RBBM_CTL 0x100
-#define A3XX_RBBM_RBBM_CTL 0x100
+#define A3XX_RBBM_PERFCTR_PWR_0_LO 0x0EA
+#define A3XX_RBBM_PERFCTR_PWR_0_HI 0x0EB
#define A3XX_RBBM_PERFCTR_PWR_1_LO 0x0EC
#define A3XX_RBBM_PERFCTR_PWR_1_HI 0x0ED
#define A3XX_RBBM_DEBUG_BUS_CTL 0x111
@@ -90,6 +178,7 @@
#define A3XX_CP_MERCIU_DATA2 0x1D3
#define A3XX_CP_MEQ_ADDR 0x1DA
#define A3XX_CP_MEQ_DATA 0x1DB
+#define A3XX_CP_PERFCOUNTER_SELECT 0x445
#define A3XX_CP_HW_FAULT 0x45C
#define A3XX_CP_AHB_FAULT 0x54D
#define A3XX_CP_PROTECT_CTRL 0x45E
@@ -138,6 +227,14 @@
#define A3XX_VSC_PIPE_CONFIG_7 0xC1B
#define A3XX_VSC_PIPE_DATA_ADDRESS_7 0xC1C
#define A3XX_VSC_PIPE_DATA_LENGTH_7 0xC1D
+#define A3XX_PC_PERFCOUNTER0_SELECT 0xC48
+#define A3XX_PC_PERFCOUNTER1_SELECT 0xC49
+#define A3XX_PC_PERFCOUNTER2_SELECT 0xC4A
+#define A3XX_PC_PERFCOUNTER3_SELECT 0xC4B
+#define A3XX_GRAS_PERFCOUNTER0_SELECT 0xC88
+#define A3XX_GRAS_PERFCOUNTER1_SELECT 0xC89
+#define A3XX_GRAS_PERFCOUNTER2_SELECT 0xC8A
+#define A3XX_GRAS_PERFCOUNTER3_SELECT 0xC8B
#define A3XX_GRAS_CL_USER_PLANE_X0 0xCA0
#define A3XX_GRAS_CL_USER_PLANE_Y0 0xCA1
#define A3XX_GRAS_CL_USER_PLANE_Z0 0xCA2
@@ -163,14 +260,42 @@
#define A3XX_GRAS_CL_USER_PLANE_Z5 0xCB6
#define A3XX_GRAS_CL_USER_PLANE_W5 0xCB7
#define A3XX_RB_GMEM_BASE_ADDR 0xCC0
+#define A3XX_RB_PERFCOUNTER0_SELECT 0xCC6
+#define A3XX_RB_PERFCOUNTER1_SELECT 0xCC7
+#define A3XX_HLSQ_PERFCOUNTER0_SELECT 0xE00
+#define A3XX_HLSQ_PERFCOUNTER1_SELECT 0xE01
+#define A3XX_HLSQ_PERFCOUNTER2_SELECT 0xE02
+#define A3XX_HLSQ_PERFCOUNTER3_SELECT 0xE03
+#define A3XX_HLSQ_PERFCOUNTER4_SELECT 0xE04
+#define A3XX_HLSQ_PERFCOUNTER5_SELECT 0xE05
#define A3XX_VFD_PERFCOUNTER0_SELECT 0xE44
+#define A3XX_VFD_PERFCOUNTER1_SELECT 0xE45
#define A3XX_VPC_VPC_DEBUG_RAM_SEL 0xE61
#define A3XX_VPC_VPC_DEBUG_RAM_READ 0xE62
+#define A3XX_VPC_PERFCOUNTER0_SELECT 0xE64
+#define A3XX_VPC_PERFCOUNTER1_SELECT 0xE65
#define A3XX_UCHE_CACHE_MODE_CONTROL_REG 0xE82
+#define A3XX_UCHE_PERFCOUNTER0_SELECT 0xE84
+#define A3XX_UCHE_PERFCOUNTER1_SELECT 0xE85
+#define A3XX_UCHE_PERFCOUNTER2_SELECT 0xE86
+#define A3XX_UCHE_PERFCOUNTER3_SELECT 0xE87
+#define A3XX_UCHE_PERFCOUNTER4_SELECT 0xE88
+#define A3XX_UCHE_PERFCOUNTER5_SELECT 0xE89
#define A3XX_UCHE_CACHE_INVALIDATE0_REG 0xEA0
+#define A3XX_SP_PERFCOUNTER0_SELECT 0xEC4
+#define A3XX_SP_PERFCOUNTER1_SELECT 0xEC5
+#define A3XX_SP_PERFCOUNTER2_SELECT 0xEC6
+#define A3XX_SP_PERFCOUNTER3_SELECT 0xEC7
+#define A3XX_SP_PERFCOUNTER4_SELECT 0xEC8
#define A3XX_SP_PERFCOUNTER5_SELECT 0xEC9
#define A3XX_SP_PERFCOUNTER6_SELECT 0xECA
#define A3XX_SP_PERFCOUNTER7_SELECT 0xECB
+#define A3XX_TP_PERFCOUNTER0_SELECT 0xF04
+#define A3XX_TP_PERFCOUNTER1_SELECT 0xF05
+#define A3XX_TP_PERFCOUNTER2_SELECT 0xF06
+#define A3XX_TP_PERFCOUNTER3_SELECT 0xF07
+#define A3XX_TP_PERFCOUNTER4_SELECT 0xF08
+#define A3XX_TP_PERFCOUNTER5_SELECT 0xF09
#define A3XX_GRAS_CL_CLIP_CNTL 0x2040
#define A3XX_GRAS_CL_GB_CLIP_ADJ 0x2044
#define A3XX_GRAS_CL_VPORT_XOFFSET 0x2048
@@ -273,8 +398,10 @@
#define A3XX_VBIF_OUT_AXI_AOOO 0x305F
/* Bit flags for RBBM_CTL */
-#define RBBM_RBBM_CTL_RESET_PWR_CTR1 (1 << 1)
-#define RBBM_RBBM_CTL_ENABLE_PWR_CTR1 (1 << 17)
+#define RBBM_RBBM_CTL_RESET_PWR_CTR0 BIT(0)
+#define RBBM_RBBM_CTL_RESET_PWR_CTR1 BIT(1)
+#define RBBM_RBBM_CTL_ENABLE_PWR_CTR0 BIT(16)
+#define RBBM_RBBM_CTL_ENABLE_PWR_CTR1 BIT(17)
/* Various flags used by the context switch code */
@@ -540,6 +667,7 @@
/* RBBM_CLOCK_CTL default value */
#define A305_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA
+#define A305C_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA
#define A320_RBBM_CLOCK_CTL_DEFAULT 0xBFFFFFFF
#define A330_RBBM_CLOCK_CTL_DEFAULT 0xBFFCFFFF
#define A330v2_RBBM_CLOCK_CTL_DEFAULT 0xBFFCFFFF
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index b9f00b5..62b6a71 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -213,8 +213,318 @@
{ ADRENO_REV_A305B, 3, 0, 5, 0x10,
"a330_pm4.fw", "a330_pfp.fw", &adreno_a3xx_gpudev,
512, 0, 2, SZ_128K, NO_VER, NO_VER },
+ { ADRENO_REV_A305C, 3, 0, 5, 0x20,
+ "a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev,
+ 512, 0, 2, SZ_128K, 0x3FF037, 0x3FF016 },
};
+/**
+ * adreno_perfcounter_init: Reserve kernel performance counters
+ * @device: device to configure
+ *
+ * The kernel needs/wants a certain group of performance counters for
+ * its own activities. Reserve these performance counters at init time
+ * to ensure that they are always reserved for the kernel. The performance
+ * counters used by the kernel can be obtained by the user, but these
+ * performance counters will remain active as long as the device is alive.
+ */
+
+static void adreno_perfcounter_init(struct kgsl_device *device)
+{
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+
+ if (adreno_dev->gpudev->perfcounter_init)
+ adreno_dev->gpudev->perfcounter_init(adreno_dev);
+};
+
+/**
+ * adreno_perfcounter_start: Enable performance counters
+ * @adreno_dev: Adreno device to configure
+ *
+ * Ensure all performance counters are enabled that are allocated. Since
+ * the device was most likely stopped, we can't trust that the counters
+ * are still valid so make it so.
+ */
+
+static void adreno_perfcounter_start(struct adreno_device *adreno_dev)
+{
+ struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters;
+ struct adreno_perfcount_group *group;
+ unsigned int i, j;
+
+ /* group id iter */
+ for (i = 0; i < counters->group_count; i++) {
+ group = &(counters->groups[i]);
+
+ /* countable iter */
+ for (j = 0; j < group->reg_count; j++) {
+ if (group->regs[j].countable ==
+ KGSL_PERFCOUNTER_NOT_USED)
+ continue;
+
+ if (adreno_dev->gpudev->perfcounter_enable)
+ adreno_dev->gpudev->perfcounter_enable(
+ adreno_dev, i, j,
+ group->regs[j].countable);
+ }
+ }
+}
+
+/**
+ * adreno_perfcounter_read_group: Determine which countables are in counters
+ * @adreno_dev: Adreno device to configure
+ * @reads: List of kgsl_perfcounter_read_groups
+ * @count: Length of list
+ *
+ * Read the performance counters for the groupid/countable pairs and return
+ * the 64 bit result for each pair
+ */
+
+int adreno_perfcounter_read_group(struct adreno_device *adreno_dev,
+ struct kgsl_perfcounter_read_group *reads, unsigned int count)
+{
+ struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters;
+ struct adreno_perfcount_group *group;
+ struct kgsl_perfcounter_read_group *list = NULL;
+ unsigned int i, j;
+ int ret = 0;
+
+ /* perfcounter get/put/query/read not allowed on a2xx */
+ if (adreno_is_a2xx(adreno_dev))
+ return -EINVAL;
+
+ /* sanity check for later */
+ if (!adreno_dev->gpudev->perfcounter_read)
+ return -EINVAL;
+
+ /* sanity check params passed in */
+ if (reads == NULL || count == 0 || count > 100)
+ return -EINVAL;
+
+ /* verify valid inputs group ids and countables */
+ for (i = 0; i < count; i++) {
+ if (reads[i].groupid >= counters->group_count)
+ return -EINVAL;
+ }
+
+ list = kmalloc(sizeof(struct kgsl_perfcounter_read_group) * count,
+ GFP_KERNEL);
+ if (!list)
+ return -ENOMEM;
+
+ if (copy_from_user(list, reads,
+ sizeof(struct kgsl_perfcounter_read_group) * count)) {
+ ret = -EFAULT;
+ goto done;
+ }
+
+ /* list iterator */
+ for (j = 0; j < count; j++) {
+ list[j].value = 0;
+
+ group = &(counters->groups[list[j].groupid]);
+
+ /* group/counter iterator */
+ for (i = 0; i < group->reg_count; i++) {
+ if (group->regs[i].countable == list[j].countable) {
+ list[j].value =
+ adreno_dev->gpudev->perfcounter_read(
+ adreno_dev, list[j].groupid,
+ i, group->regs[i].offset);
+ break;
+ }
+ }
+ }
+
+ /* write the data */
+ if (copy_to_user(reads, list,
+ sizeof(struct kgsl_perfcounter_read_group) *
+ count) != 0)
+ ret = -EFAULT;
+
+done:
+ kfree(list);
+ return ret;
+}
+
+/**
+ * adreno_perfcounter_query_group: Determine which countables are in counters
+ * @adreno_dev: Adreno device to configure
+ * @groupid: Desired performance counter group
+ * @countables: Return list of all countables in the groups counters
+ * @count: Max length of the array
+ * @max_counters: max counters for the groupid
+ *
+ * Query the current state of counters for the group.
+ */
+
+int adreno_perfcounter_query_group(struct adreno_device *adreno_dev,
+ unsigned int groupid, unsigned int *countables, unsigned int count,
+ unsigned int *max_counters)
+{
+ struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters;
+ struct adreno_perfcount_group *group;
+ unsigned int i;
+
+ *max_counters = 0;
+
+ /* perfcounter get/put/query not allowed on a2xx */
+ if (adreno_is_a2xx(adreno_dev))
+ return -EINVAL;
+
+ if (groupid >= counters->group_count)
+ return -EINVAL;
+
+ group = &(counters->groups[groupid]);
+ *max_counters = group->reg_count;
+
+ /*
+ * if NULL countable or *count of zero, return max reg_count in
+ * *max_counters and return success
+ */
+ if (countables == NULL || count == 0)
+ return 0;
+
+ /*
+ * Go through all available counters. Write upto *count * countable
+ * values.
+ */
+ for (i = 0; i < group->reg_count && i < count; i++) {
+ if (copy_to_user(&countables[i], &(group->regs[i].countable),
+ sizeof(unsigned int)) != 0)
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+/**
+ * adreno_perfcounter_get: Try to put a countable in an available counter
+ * @adreno_dev: Adreno device to configure
+ * @groupid: Desired performance counter group
+ * @countable: Countable desired to be in a counter
+ * @offset: Return offset of the countable
+ * @flags: Used to setup kernel perf counters
+ *
+ * Try to place a countable in an available counter. If the countable is
+ * already in a counter, reference count the counter/countable pair resource
+ * and return success
+ */
+
+int adreno_perfcounter_get(struct adreno_device *adreno_dev,
+ unsigned int groupid, unsigned int countable, unsigned int *offset,
+ unsigned int flags)
+{
+ struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters;
+ struct adreno_perfcount_group *group;
+ unsigned int i, empty = -1;
+
+ /* always clear return variables */
+ if (offset)
+ *offset = 0;
+
+ /* perfcounter get/put/query not allowed on a2xx */
+ if (adreno_is_a2xx(adreno_dev))
+ return -EINVAL;
+
+ if (groupid >= counters->group_count)
+ return -EINVAL;
+
+ group = &(counters->groups[groupid]);
+
+ /*
+ * Check if the countable is already associated with a counter.
+ * Refcount and return the offset, otherwise, try and find an empty
+ * counter and assign the countable to it.
+ */
+ for (i = 0; i < group->reg_count; i++) {
+ if (group->regs[i].countable == countable) {
+ /* Countable already associated with counter */
+ group->regs[i].refcount++;
+ group->regs[i].flags |= flags;
+ if (offset)
+ *offset = group->regs[i].offset;
+ return 0;
+ } else if (group->regs[i].countable ==
+ KGSL_PERFCOUNTER_NOT_USED) {
+ /* keep track of unused counter */
+ empty = i;
+ }
+ }
+
+ /* no available counters, so do nothing else */
+ if (empty == -1)
+ return -EBUSY;
+
+ /* initialize the new counter */
+ group->regs[empty].countable = countable;
+ group->regs[empty].refcount = 1;
+
+ /* enable the new counter */
+ adreno_dev->gpudev->perfcounter_enable(adreno_dev, groupid, empty,
+ countable);
+
+ group->regs[empty].flags = flags;
+
+ if (offset)
+ *offset = group->regs[empty].offset;
+
+ return 0;
+}
+
+
+/**
+ * adreno_perfcounter_put: Release a countable from counter resource
+ * @adreno_dev: Adreno device to configure
+ * @groupid: Desired performance counter group
+ * @countable: Countable desired to be freed from a counter
+ *
+ * Put a performance counter/countable pair that was previously received. If
+ * noone else is using the countable, free up the counter for others.
+ */
+int adreno_perfcounter_put(struct adreno_device *adreno_dev,
+ unsigned int groupid, unsigned int countable)
+{
+ struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters;
+ struct adreno_perfcount_group *group;
+
+ unsigned int i;
+
+ /* perfcounter get/put/query not allowed on a2xx */
+ if (adreno_is_a2xx(adreno_dev))
+ return -EINVAL;
+
+ if (groupid >= counters->group_count)
+ return -EINVAL;
+
+ group = &(counters->groups[groupid]);
+
+ for (i = 0; i < group->reg_count; i++) {
+ if (group->regs[i].countable == countable) {
+ if (group->regs[i].refcount > 0) {
+ group->regs[i].refcount--;
+
+ /*
+ * book keeping to ensure we never free a
+ * perf counter used by kernel
+ */
+ if (group->regs[i].flags &&
+ group->regs[i].refcount == 0)
+ group->regs[i].refcount++;
+
+ /* make available if not used */
+ if (group->regs[i].refcount == 0)
+ group->regs[i].countable =
+ KGSL_PERFCOUNTER_NOT_USED;
+ }
+
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
static irqreturn_t adreno_irq_handler(struct kgsl_device *device)
{
irqreturn_t result;
@@ -1280,15 +1590,7 @@
*/
ft_detect_regs[0] = adreno_dev->gpudev->reg_rbbm_status;
- /* Add A3XX specific registers for hang detection */
- if (adreno_is_a3xx(adreno_dev)) {
- ft_detect_regs[6] = A3XX_RBBM_PERFCTR_SP_7_LO;
- ft_detect_regs[7] = A3XX_RBBM_PERFCTR_SP_7_HI;
- ft_detect_regs[8] = A3XX_RBBM_PERFCTR_SP_6_LO;
- ft_detect_regs[9] = A3XX_RBBM_PERFCTR_SP_6_HI;
- ft_detect_regs[10] = A3XX_RBBM_PERFCTR_SP_5_LO;
- ft_detect_regs[11] = A3XX_RBBM_PERFCTR_SP_5_HI;
- }
+ adreno_perfcounter_init(device);
/* Power down the device */
kgsl_pwrctrl_disable(device);
@@ -1301,6 +1603,8 @@
int status = -EINVAL;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ kgsl_cffdump_open(device);
+
if (KGSL_STATE_DUMP_AND_FT != device->state)
kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT);
@@ -1346,6 +1650,8 @@
if (KGSL_STATE_DUMP_AND_FT != device->state)
mod_timer(&device->idle_timer, jiffies + FIRST_TIMEOUT);
+ adreno_perfcounter_start(adreno_dev);
+
device->reset_counter++;
return 0;
@@ -1382,6 +1688,8 @@
/* Power down the device */
kgsl_pwrctrl_disable(device);
+ kgsl_cffdump_close(device->id);
+
return 0;
}
@@ -1464,6 +1772,8 @@
start_ptr = adreno_ringbuffer_dec_wrapped(start_ptr,
size);
kgsl_sharedmem_readl(&rb->buffer_desc, &val1, start_ptr);
+ /* Ensure above read is finished before next read */
+ rmb();
if (KGSL_CMD_IDENTIFIER == val1) {
if ((start_ptr / sizeof(unsigned int)) != rb->wptr)
start_ptr = adreno_ringbuffer_dec_wrapped(
@@ -1501,6 +1811,8 @@
temp_rb_rptr, size);
kgsl_sharedmem_readl(&rb->buffer_desc, &val[i],
temp_rb_rptr);
+ /* Ensure above read is finished before next read */
+ rmb();
if (check && ((inc && val[i] == global_eop) ||
(!inc && (val[i] ==
@@ -1565,6 +1877,8 @@
while (temp_rb_rptr / sizeof(unsigned int) != rb->wptr) {
kgsl_sharedmem_readl(&rb->buffer_desc, &val[i], temp_rb_rptr);
+ /* Ensure above read is finished before next read */
+ rmb();
if (check && val[i] == ib1) {
/* decrement i, i.e i = (i - 1 + 2) % 2 */
@@ -1631,6 +1945,9 @@
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
eoptimestamp));
+ /* Ensure context id and global eop ts read complete */
+ rmb();
+
ft_data->rb_buffer = vmalloc(rb->buffer_desc.size);
if (!ft_data->rb_buffer) {
KGSL_MEM_ERR(device, "vmalloc(%d) failed\n",
@@ -1708,6 +2025,8 @@
&curr_global_ts,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
eoptimestamp));
+ /* Ensure above read is finished before long ib check */
+ rmb();
/* Mark long ib as handled */
adreno_dev->long_ib = 0;
@@ -3202,27 +3521,55 @@
static long adreno_ioctl(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
+ struct kgsl_device *device = dev_priv->device;
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
int result = 0;
- struct kgsl_drawctxt_set_bin_base_offset *binbase;
- struct kgsl_context *context;
switch (cmd) {
- case IOCTL_KGSL_DRAWCTXT_SET_BIN_BASE_OFFSET:
+ case IOCTL_KGSL_DRAWCTXT_SET_BIN_BASE_OFFSET: {
+ struct kgsl_drawctxt_set_bin_base_offset *binbase = data;
+ struct kgsl_context *context;
+
binbase = data;
context = kgsl_find_context(dev_priv, binbase->drawctxt_id);
if (context) {
adreno_drawctxt_set_bin_base_offset(
- dev_priv->device, context, binbase->offset);
+ device, context, binbase->offset);
} else {
result = -EINVAL;
- KGSL_DRV_ERR(dev_priv->device,
+ KGSL_DRV_ERR(device,
"invalid drawctxt drawctxt_id %d "
"device_id=%d\n",
- binbase->drawctxt_id, dev_priv->device->id);
+ binbase->drawctxt_id, device->id);
}
break;
-
+ }
+ case IOCTL_KGSL_PERFCOUNTER_GET: {
+ struct kgsl_perfcounter_get *get = data;
+ result = adreno_perfcounter_get(adreno_dev, get->groupid,
+ get->countable, &get->offset, PERFCOUNTER_FLAG_NONE);
+ break;
+ }
+ case IOCTL_KGSL_PERFCOUNTER_PUT: {
+ struct kgsl_perfcounter_put *put = data;
+ result = adreno_perfcounter_put(adreno_dev, put->groupid,
+ put->countable);
+ break;
+ }
+ case IOCTL_KGSL_PERFCOUNTER_QUERY: {
+ struct kgsl_perfcounter_query *query = data;
+ result = adreno_perfcounter_query_group(adreno_dev,
+ query->groupid, query->countables,
+ query->count, &query->max_counters);
+ break;
+ }
+ case IOCTL_KGSL_PERFCOUNTER_READ: {
+ struct kgsl_perfcounter_read *read = data;
+ result = adreno_perfcounter_read_group(adreno_dev,
+ read->reads, read->count);
+ break;
+ }
default:
KGSL_DRV_INFO(dev_priv->device,
"invalid ioctl code %08x\n", cmd);
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 6c57078..90d6027 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -73,6 +73,7 @@
ADRENO_REV_A220 = 220,
ADRENO_REV_A225 = 225,
ADRENO_REV_A305 = 305,
+ ADRENO_REV_A305C = 306,
ADRENO_REV_A320 = 320,
ADRENO_REV_A330 = 330,
ADRENO_REV_A305B = 335,
@@ -115,6 +116,44 @@
unsigned int gpu_cycles;
};
+#define PERFCOUNTER_FLAG_NONE 0x0
+#define PERFCOUNTER_FLAG_KERNEL 0x1
+
+/* Structs to maintain the list of active performance counters */
+
+/**
+ * struct adreno_perfcount_register: register state
+ * @countable: countable the register holds
+ * @refcount: number of users of the register
+ * @offset: register hardware offset
+ */
+struct adreno_perfcount_register {
+ unsigned int countable;
+ unsigned int refcount;
+ unsigned int offset;
+ unsigned int flags;
+};
+
+/**
+ * struct adreno_perfcount_group: registers for a hardware group
+ * @regs: available registers for this group
+ * @reg_count: total registers for this group
+ */
+struct adreno_perfcount_group {
+ struct adreno_perfcount_register *regs;
+ unsigned int reg_count;
+};
+
+/**
+ * adreno_perfcounts: all available perfcounter groups
+ * @groups: available groups for this device
+ * @group_count: total groups for this device
+ */
+struct adreno_perfcounters {
+ struct adreno_perfcount_group *groups;
+ unsigned int group_count;
+};
+
struct adreno_gpudev {
/*
* These registers are in a different location on A3XX, so define
@@ -126,6 +165,8 @@
/* keeps track of when we need to execute the draw workaround code */
int ctx_switches_since_last_draw;
+ struct adreno_perfcounters *perfcounters;
+
/* GPU specific function hooks */
int (*ctxt_create)(struct adreno_device *, struct adreno_context *);
void (*ctxt_save)(struct adreno_device *, struct adreno_context *);
@@ -137,8 +178,14 @@
unsigned int (*irq_pending)(struct adreno_device *);
void * (*snapshot)(struct adreno_device *, void *, int *, int);
int (*rb_init)(struct adreno_device *, struct adreno_ringbuffer *);
+ void (*perfcounter_init)(struct adreno_device *);
void (*start)(struct adreno_device *);
unsigned int (*busy_cycles)(struct adreno_device *);
+ void (*perfcounter_enable)(struct adreno_device *, unsigned int group,
+ unsigned int counter, unsigned int countable);
+ uint64_t (*perfcounter_read)(struct adreno_device *adreno_dev,
+ unsigned int group, unsigned int counter,
+ unsigned int offset);
};
/*
@@ -258,6 +305,13 @@
unsigned int adreno_ft_detect(struct kgsl_device *device,
unsigned int *prev_reg_val);
+int adreno_perfcounter_get(struct adreno_device *adreno_dev,
+ unsigned int groupid, unsigned int countable, unsigned int *offset,
+ unsigned int flags);
+
+int adreno_perfcounter_put(struct adreno_device *adreno_dev,
+ unsigned int groupid, unsigned int countable);
+
static inline int adreno_is_a200(struct adreno_device *adreno_dev)
{
return (adreno_dev->gpurev == ADRENO_REV_A200);
@@ -314,6 +368,11 @@
return (adreno_dev->gpurev == ADRENO_REV_A305B);
}
+static inline int adreno_is_a305c(struct adreno_device *adreno_dev)
+{
+ return (adreno_dev->gpurev == ADRENO_REV_A305C);
+}
+
static inline int adreno_is_a320(struct adreno_device *adreno_dev)
{
return (adreno_dev->gpurev == ADRENO_REV_A320);
@@ -438,6 +497,7 @@
*cmds++ = 0;
if ((adreno_dev->gpurev == ADRENO_REV_A305) ||
+ (adreno_dev->gpurev == ADRENO_REV_A305C) ||
(adreno_dev->gpurev == ADRENO_REV_A320)) {
*cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1);
*cmds++ = 0;
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index b4ee100..dd9bdc3 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1515,18 +1515,26 @@
"Current active context has caused gpu hang\n");
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
-
+ kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ context->reg_save[1],
+ context->reg_save[2] << 2, true);
/* save registers and constants. */
adreno_ringbuffer_issuecmds(device, context,
KGSL_CMD_FLAGS_NONE,
context->reg_save, 3);
if (context->flags & CTXT_FLAGS_SHADER_SAVE) {
+ kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ context->shader_save[1],
+ context->shader_save[2] << 2, true);
/* save shader partitioning and instructions. */
adreno_ringbuffer_issuecmds(device, context,
KGSL_CMD_FLAGS_PMODE,
context->shader_save, 3);
+ kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ context->shader_fixup[1],
+ context->shader_fixup[2] << 2, true);
/*
* fixup shader partitioning parameter for
* SET_SHADER_BASES.
@@ -1541,6 +1549,9 @@
if ((context->flags & CTXT_FLAGS_GMEM_SAVE) &&
(context->flags & CTXT_FLAGS_GMEM_SHADOW)) {
+ kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ context->context_gmem_shadow.gmem_save[1],
+ context->context_gmem_shadow.gmem_save[2] << 2, true);
/* save gmem.
* (note: changes shader. shader must already be saved.)
*/
@@ -1548,6 +1559,10 @@
KGSL_CMD_FLAGS_PMODE,
context->context_gmem_shadow.gmem_save, 3);
+ kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ context->chicken_restore[1],
+ context->chicken_restore[2] << 2, true);
+
/* Restore TP0_CHICKEN */
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
adreno_ringbuffer_issuecmds(device, context,
@@ -1584,21 +1599,24 @@
cmds, 5);
kgsl_mmu_setstate(&device->mmu, context->pagetable, context->id);
-#ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
- kgsl_cffdump_syncmem(NULL, &context->gpustate,
- context->gpustate.gpuaddr, LCC_SHADOW_SIZE +
- REG_SHADOW_SIZE + CMD_BUFFER_SIZE + TEX_SHADOW_SIZE, false);
-#endif
-
/* restore gmem.
* (note: changes shader. shader must not already be restored.)
*/
if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
+ kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ context->context_gmem_shadow.gmem_restore[1],
+ context->context_gmem_shadow.gmem_restore[2] << 2,
+ true);
+
adreno_ringbuffer_issuecmds(device, context,
KGSL_CMD_FLAGS_PMODE,
context->context_gmem_shadow.gmem_restore, 3);
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
+ kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ context->chicken_restore[1],
+ context->chicken_restore[2] << 2, true);
+
/* Restore TP0_CHICKEN */
adreno_ringbuffer_issuecmds(device, context,
KGSL_CMD_FLAGS_NONE,
@@ -1609,6 +1627,9 @@
}
if (!(context->flags & CTXT_FLAGS_PREAMBLE)) {
+ kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ context->reg_restore[1],
+ context->reg_restore[2] << 2, true);
/* restore registers and constants. */
adreno_ringbuffer_issuecmds(device, context,
@@ -1616,6 +1637,10 @@
/* restore shader instructions & partitioning. */
if (context->flags & CTXT_FLAGS_SHADER_RESTORE) {
+ kgsl_cffdump_syncmem(NULL, &context->gpustate,
+ context->shader_restore[1],
+ context->shader_restore[2] << 2, true);
+
adreno_ringbuffer_issuecmds(device, context,
KGSL_CMD_FLAGS_NONE,
context->shader_restore, 3);
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index f1024d6..13c723a 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -450,6 +450,8 @@
{
if (adreno_is_a305(adreno_dev))
return A305_RBBM_CLOCK_CTL_DEFAULT;
+ else if (adreno_is_a305c(adreno_dev))
+ return A305C_RBBM_CLOCK_CTL_DEFAULT;
else if (adreno_is_a320(adreno_dev))
return A320_RBBM_CLOCK_CTL_DEFAULT;
else if (adreno_is_a330v2(adreno_dev))
@@ -2417,6 +2419,11 @@
* already be saved.)
*/
+ kgsl_cffdump_syncmem(NULL,
+ &context->gpustate,
+ context->context_gmem_shadow.gmem_save[1],
+ context->context_gmem_shadow.gmem_save[2] << 2, true);
+
adreno_ringbuffer_issuecmds(device, context,
KGSL_CMD_FLAGS_PMODE,
context->context_gmem_shadow.
@@ -2454,6 +2461,12 @@
*/
if (context->flags & CTXT_FLAGS_GMEM_RESTORE) {
+ kgsl_cffdump_syncmem(NULL,
+ &context->gpustate,
+ context->context_gmem_shadow.gmem_restore[1],
+ context->context_gmem_shadow.gmem_restore[2] << 2,
+ true);
+
adreno_ringbuffer_issuecmds(device, context,
KGSL_CMD_FLAGS_PMODE,
context->context_gmem_shadow.
@@ -2603,6 +2616,213 @@
queue_work(device->work_queue, &device->ts_expired_ws);
}
+/**
+ * struct a3xx_perfcounter_register - Define a performance counter register
+ * @load_bit: the bit to set in RBBM_LOAD_CMD0/RBBM_LOAD_CMD1 to force the RBBM
+ * to load the reset value into the appropriate counter
+ * @select: The dword offset of the register to write the selected
+ * countable into
+ */
+
+struct a3xx_perfcounter_register {
+ unsigned int load_bit;
+ unsigned int select;
+};
+
+static struct a3xx_perfcounter_register a3xx_perfcounter_reg_cp[] = {
+ { 0, A3XX_CP_PERFCOUNTER_SELECT },
+};
+
+static struct a3xx_perfcounter_register a3xx_perfcounter_reg_rbbm[] = {
+ { 1, A3XX_RBBM_PERFCOUNTER0_SELECT },
+ { 2, A3XX_RBBM_PERFCOUNTER1_SELECT },
+};
+
+static struct a3xx_perfcounter_register a3xx_perfcounter_reg_pc[] = {
+ { 3, A3XX_PC_PERFCOUNTER0_SELECT },
+ { 4, A3XX_PC_PERFCOUNTER1_SELECT },
+ { 5, A3XX_PC_PERFCOUNTER2_SELECT },
+ { 6, A3XX_PC_PERFCOUNTER3_SELECT },
+};
+
+static struct a3xx_perfcounter_register a3xx_perfcounter_reg_vfd[] = {
+ { 7, A3XX_VFD_PERFCOUNTER0_SELECT },
+ { 8, A3XX_VFD_PERFCOUNTER1_SELECT },
+};
+
+static struct a3xx_perfcounter_register a3xx_perfcounter_reg_hlsq[] = {
+ { 9, A3XX_HLSQ_PERFCOUNTER0_SELECT },
+ { 10, A3XX_HLSQ_PERFCOUNTER1_SELECT },
+ { 11, A3XX_HLSQ_PERFCOUNTER2_SELECT },
+ { 12, A3XX_HLSQ_PERFCOUNTER3_SELECT },
+ { 13, A3XX_HLSQ_PERFCOUNTER4_SELECT },
+ { 14, A3XX_HLSQ_PERFCOUNTER5_SELECT },
+};
+
+static struct a3xx_perfcounter_register a3xx_perfcounter_reg_vpc[] = {
+ { 15, A3XX_VPC_PERFCOUNTER0_SELECT },
+ { 16, A3XX_VPC_PERFCOUNTER1_SELECT },
+};
+
+static struct a3xx_perfcounter_register a3xx_perfcounter_reg_tse[] = {
+ { 17, A3XX_GRAS_PERFCOUNTER0_SELECT },
+ { 18, A3XX_GRAS_PERFCOUNTER1_SELECT },
+};
+
+static struct a3xx_perfcounter_register a3xx_perfcounter_reg_ras[] = {
+ { 19, A3XX_GRAS_PERFCOUNTER2_SELECT },
+ { 20, A3XX_GRAS_PERFCOUNTER3_SELECT },
+};
+
+static struct a3xx_perfcounter_register a3xx_perfcounter_reg_uche[] = {
+ { 21, A3XX_UCHE_PERFCOUNTER0_SELECT },
+ { 22, A3XX_UCHE_PERFCOUNTER1_SELECT },
+ { 23, A3XX_UCHE_PERFCOUNTER2_SELECT },
+ { 24, A3XX_UCHE_PERFCOUNTER3_SELECT },
+ { 25, A3XX_UCHE_PERFCOUNTER4_SELECT },
+ { 26, A3XX_UCHE_PERFCOUNTER5_SELECT },
+};
+
+static struct a3xx_perfcounter_register a3xx_perfcounter_reg_tp[] = {
+ { 27, A3XX_TP_PERFCOUNTER0_SELECT },
+ { 28, A3XX_TP_PERFCOUNTER1_SELECT },
+ { 29, A3XX_TP_PERFCOUNTER2_SELECT },
+ { 30, A3XX_TP_PERFCOUNTER3_SELECT },
+ { 31, A3XX_TP_PERFCOUNTER4_SELECT },
+ { 32, A3XX_TP_PERFCOUNTER5_SELECT },
+};
+
+static struct a3xx_perfcounter_register a3xx_perfcounter_reg_sp[] = {
+ { 33, A3XX_SP_PERFCOUNTER0_SELECT },
+ { 34, A3XX_SP_PERFCOUNTER1_SELECT },
+ { 35, A3XX_SP_PERFCOUNTER2_SELECT },
+ { 36, A3XX_SP_PERFCOUNTER3_SELECT },
+ { 37, A3XX_SP_PERFCOUNTER4_SELECT },
+ { 38, A3XX_SP_PERFCOUNTER5_SELECT },
+ { 39, A3XX_SP_PERFCOUNTER6_SELECT },
+ { 40, A3XX_SP_PERFCOUNTER7_SELECT },
+};
+
+static struct a3xx_perfcounter_register a3xx_perfcounter_reg_rb[] = {
+ { 41, A3XX_RB_PERFCOUNTER0_SELECT },
+ { 42, A3XX_RB_PERFCOUNTER1_SELECT },
+};
+
+#define REGCOUNTER_GROUP(_x) { (_x), ARRAY_SIZE((_x)) }
+
+static struct {
+ struct a3xx_perfcounter_register *regs;
+ int count;
+} a3xx_perfcounter_reglist[] = {
+ REGCOUNTER_GROUP(a3xx_perfcounter_reg_cp),
+ REGCOUNTER_GROUP(a3xx_perfcounter_reg_rbbm),
+ REGCOUNTER_GROUP(a3xx_perfcounter_reg_pc),
+ REGCOUNTER_GROUP(a3xx_perfcounter_reg_vfd),
+ REGCOUNTER_GROUP(a3xx_perfcounter_reg_hlsq),
+ REGCOUNTER_GROUP(a3xx_perfcounter_reg_vpc),
+ REGCOUNTER_GROUP(a3xx_perfcounter_reg_tse),
+ REGCOUNTER_GROUP(a3xx_perfcounter_reg_ras),
+ REGCOUNTER_GROUP(a3xx_perfcounter_reg_uche),
+ REGCOUNTER_GROUP(a3xx_perfcounter_reg_tp),
+ REGCOUNTER_GROUP(a3xx_perfcounter_reg_sp),
+ REGCOUNTER_GROUP(a3xx_perfcounter_reg_rb),
+};
+
+static void a3xx_perfcounter_enable_pwr(struct kgsl_device *device,
+ unsigned int countable)
+{
+ unsigned int in, out;
+
+ adreno_regread(device, A3XX_RBBM_RBBM_CTL, &in);
+
+ if (countable == 0)
+ out = in | RBBM_RBBM_CTL_RESET_PWR_CTR0;
+ else
+ out = in | RBBM_RBBM_CTL_RESET_PWR_CTR1;
+
+ adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, out);
+
+ if (countable == 0)
+ out = in | RBBM_RBBM_CTL_ENABLE_PWR_CTR0;
+ else
+ out = in | RBBM_RBBM_CTL_ENABLE_PWR_CTR1;
+
+ adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, out);
+
+ return;
+}
+
+/*
+ * a3xx_perfcounter_enable - Configure a performance counter for a countable
+ * @adreno_dev - Adreno device to configure
+ * @group - Desired performance counter group
+ * @counter - Desired performance counter in the group
+ * @countable - Desired countable
+ *
+ * Physically set up a counter within a group with the desired countable
+ */
+
+static void a3xx_perfcounter_enable(struct adreno_device *adreno_dev,
+ unsigned int group, unsigned int counter, unsigned int countable)
+{
+ struct kgsl_device *device = &adreno_dev->dev;
+ unsigned int val = 0;
+ struct a3xx_perfcounter_register *reg;
+
+ if (group > ARRAY_SIZE(a3xx_perfcounter_reglist))
+ return;
+
+ if (counter > a3xx_perfcounter_reglist[group].count)
+ return;
+
+ /* Special case - power */
+ if (group == KGSL_PERFCOUNTER_GROUP_PWR)
+ return a3xx_perfcounter_enable_pwr(device, countable);
+
+ reg = &(a3xx_perfcounter_reglist[group].regs[counter]);
+
+ /* Select the desired perfcounter */
+ adreno_regwrite(device, reg->select, countable);
+
+ if (reg->load_bit < 32) {
+ val = 1 << reg->load_bit;
+ adreno_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD0, val);
+ } else {
+ val = 1 << (reg->load_bit - 32);
+ adreno_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD1, val);
+ }
+}
+
+static uint64_t a3xx_perfcounter_read(struct adreno_device *adreno_dev,
+ unsigned int group, unsigned int counter,
+ unsigned int offset)
+{
+ struct kgsl_device *device = &adreno_dev->dev;
+ struct a3xx_perfcounter_register *reg = NULL;
+ unsigned int lo = 0, hi = 0;
+ unsigned int val;
+
+ if (group > ARRAY_SIZE(a3xx_perfcounter_reglist))
+ return 0;
+
+ reg = &(a3xx_perfcounter_reglist[group].regs[counter]);
+
+ /* Freeze the counter */
+ adreno_regread(device, A3XX_RBBM_PERFCTR_CTL, &val);
+ val &= ~reg->load_bit;
+ adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, val);
+
+ /* Read the values */
+ adreno_regread(device, offset, &lo);
+ adreno_regread(device, offset + 1, &hi);
+
+ /* Re-Enable the counter */
+ val |= reg->load_bit;
+ adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, val);
+
+ return (((uint64_t) hi) << 32) | lo;
+}
+
#define A3XX_IRQ_CALLBACK(_c) { .func = _c }
#define A3XX_INT_MASK \
@@ -2757,6 +2977,19 @@
{0, 0},
};
+static struct a3xx_vbif_data a305c_vbif[] = {
+ { A3XX_VBIF_IN_RD_LIM_CONF0, 0x00101010 },
+ { A3XX_VBIF_IN_WR_LIM_CONF0, 0x00101010 },
+ { A3XX_VBIF_OUT_RD_LIM_CONF0, 0x00000010 },
+ { A3XX_VBIF_OUT_WR_LIM_CONF0, 0x00000010 },
+ { A3XX_VBIF_DDR_OUT_MAX_BURST, 0x00000101 },
+ { A3XX_VBIF_ARB_CTL, 0x00000010 },
+ /* Set up AOOO */
+ { A3XX_VBIF_OUT_AXI_AOOO_EN, 0x00000007 },
+ { A3XX_VBIF_OUT_AXI_AOOO, 0x00070007 },
+ {0, 0},
+};
+
static struct a3xx_vbif_data a320_vbif[] = {
/* Set up 16 deep read/write request queues */
{ A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010 },
@@ -2828,6 +3061,7 @@
struct a3xx_vbif_data *vbif;
} a3xx_vbif_platforms[] = {
{ adreno_is_a305, a305_vbif },
+ { adreno_is_a305c, a305c_vbif },
{ adreno_is_a320, a320_vbif },
/* A330v2 needs to be ahead of A330 so the right device matches */
{ adreno_is_a330v2, a330v2_vbif },
@@ -2835,12 +3069,45 @@
{ adreno_is_a305b, a305b_vbif },
};
+static void a3xx_perfcounter_init(struct adreno_device *adreno_dev)
+{
+ /*
+ * Set SP to count SP_ALU_ACTIVE_CYCLES, it includes
+ * all ALU instruction execution regardless precision or shader ID.
+ * Set SP to count SP0_ICL1_MISSES, It counts
+ * USP L1 instruction miss request.
+ * Set SP to count SP_FS_FULL_ALU_INSTRUCTIONS, it
+ * counts USP flow control instruction execution.
+ * we will use this to augment our hang detection
+ */
+ if (adreno_dev->fast_hang_detect) {
+ adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
+ SP_ALU_ACTIVE_CYCLES, &ft_detect_regs[6],
+ PERFCOUNTER_FLAG_KERNEL);
+ ft_detect_regs[7] = ft_detect_regs[6] + 1;
+ adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
+ SP0_ICL1_MISSES, &ft_detect_regs[8],
+ PERFCOUNTER_FLAG_KERNEL);
+ ft_detect_regs[9] = ft_detect_regs[8] + 1;
+ adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
+ SP_FS_CFLOW_INSTRUCTIONS, &ft_detect_regs[10],
+ PERFCOUNTER_FLAG_KERNEL);
+ ft_detect_regs[11] = ft_detect_regs[10] + 1;
+ }
+
+ adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP,
+ SP_FS_FULL_ALU_INSTRUCTIONS, NULL, PERFCOUNTER_FLAG_KERNEL);
+
+ /* Reserve and start countable 1 in the PWR perfcounter group */
+ adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_PWR, 1,
+ NULL, PERFCOUNTER_FLAG_KERNEL);
+}
+
static void a3xx_start(struct adreno_device *adreno_dev)
{
struct kgsl_device *device = &adreno_dev->dev;
struct a3xx_vbif_data *vbif = NULL;
int i;
- unsigned int reg;
for (i = 0; i < ARRAY_SIZE(a3xx_vbif_platforms); i++) {
if (a3xx_vbif_platforms[i].devfunc(adreno_dev)) {
@@ -2904,39 +3171,121 @@
/* Turn on performance counters */
adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, 0x01);
- /*
- * Set SP perfcounter 5 to count SP_ALU_ACTIVE_CYCLES, it includes
- * all ALU instruction execution regardless precision or shader ID.
- * Set SP perfcounter 6 to count SP0_ICL1_MISSES, It counts
- * USP L1 instruction miss request.
- * Set SP perfcounter 7 to count SP_FS_FULL_ALU_INSTRUCTIONS, it
- * counts USP flow control instruction execution.
- * we will use this to augment our hang detection
- */
- if (adreno_dev->fast_hang_detect) {
- adreno_regwrite(device, A3XX_SP_PERFCOUNTER5_SELECT,
- SP_ALU_ACTIVE_CYCLES);
- adreno_regwrite(device, A3XX_SP_PERFCOUNTER6_SELECT,
- SP0_ICL1_MISSES);
- adreno_regwrite(device, A3XX_SP_PERFCOUNTER7_SELECT,
- SP_FS_CFLOW_INSTRUCTIONS);
- }
-
- adreno_regwrite(device, A3XX_SP_PERFCOUNTER7_SELECT,
- SP_FS_FULL_ALU_INSTRUCTIONS);
-
/* Turn on the GPU busy counter and let it run free */
adreno_dev->gpu_cycles = 0;
-
- adreno_regread(device, A3XX_RBBM_RBBM_CTL, ®);
- reg |= RBBM_RBBM_CTL_RESET_PWR_CTR1;
- adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, reg);
- reg &= ~RBBM_RBBM_CTL_RESET_PWR_CTR1;
- reg |= RBBM_RBBM_CTL_ENABLE_PWR_CTR1;
- adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, reg);
}
+/*
+ * Define the available perfcounter groups - these get used by
+ * adreno_perfcounter_get and adreno_perfcounter_put
+ */
+
+static struct adreno_perfcount_register a3xx_perfcounters_cp[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_CP_0_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_rbbm[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RBBM_0_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RBBM_1_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_pc[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_0_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_1_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_2_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_3_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_vfd[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VFD_0_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VFD_1_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_hlsq[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_0_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_1_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_2_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_3_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_4_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_5_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_vpc[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VPC_0_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VPC_1_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_tse[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TSE_0_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TSE_1_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_ras[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RAS_0_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RAS_1_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_uche[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_0_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_1_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_2_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_3_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_4_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_5_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_tp[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_0_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_1_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_2_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_3_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_4_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_5_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_sp[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_0_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_1_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_2_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_3_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_4_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_5_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_6_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_7_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_rb[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RB_0_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RB_1_LO, 0 },
+};
+
+static struct adreno_perfcount_register a3xx_perfcounters_pwr[] = {
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PWR_0_LO, 0 },
+ { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PWR_1_LO, 0 },
+};
+
+static struct adreno_perfcount_group a3xx_perfcounter_groups[] = {
+ { a3xx_perfcounters_cp, ARRAY_SIZE(a3xx_perfcounters_cp) },
+ { a3xx_perfcounters_rbbm, ARRAY_SIZE(a3xx_perfcounters_rbbm) },
+ { a3xx_perfcounters_pc, ARRAY_SIZE(a3xx_perfcounters_pc) },
+ { a3xx_perfcounters_vfd, ARRAY_SIZE(a3xx_perfcounters_vfd) },
+ { a3xx_perfcounters_hlsq, ARRAY_SIZE(a3xx_perfcounters_hlsq) },
+ { a3xx_perfcounters_vpc, ARRAY_SIZE(a3xx_perfcounters_vpc) },
+ { a3xx_perfcounters_tse, ARRAY_SIZE(a3xx_perfcounters_tse) },
+ { a3xx_perfcounters_ras, ARRAY_SIZE(a3xx_perfcounters_ras) },
+ { a3xx_perfcounters_uche, ARRAY_SIZE(a3xx_perfcounters_uche) },
+ { a3xx_perfcounters_tp, ARRAY_SIZE(a3xx_perfcounters_tp) },
+ { a3xx_perfcounters_sp, ARRAY_SIZE(a3xx_perfcounters_sp) },
+ { a3xx_perfcounters_rb, ARRAY_SIZE(a3xx_perfcounters_rb) },
+ { a3xx_perfcounters_pwr, ARRAY_SIZE(a3xx_perfcounters_pwr) },
+};
+
+static struct adreno_perfcounters a3xx_perfcounters = {
+ a3xx_perfcounter_groups,
+ ARRAY_SIZE(a3xx_perfcounter_groups),
+};
+
/* Defined in adreno_a3xx_snapshot.c */
void *a3xx_snapshot(struct adreno_device *adreno_dev, void *snapshot,
int *remain, int hang);
@@ -2945,16 +3294,20 @@
.reg_rbbm_status = A3XX_RBBM_STATUS,
.reg_cp_pfp_ucode_addr = A3XX_CP_PFP_UCODE_ADDR,
.reg_cp_pfp_ucode_data = A3XX_CP_PFP_UCODE_DATA,
+ .perfcounters = &a3xx_perfcounters,
.ctxt_create = a3xx_drawctxt_create,
.ctxt_save = a3xx_drawctxt_save,
.ctxt_restore = a3xx_drawctxt_restore,
.ctxt_draw_workaround = NULL,
.rb_init = a3xx_rb_init,
+ .perfcounter_init = a3xx_perfcounter_init,
.irq_control = a3xx_irq_control,
.irq_handler = a3xx_irq_handler,
.irq_pending = a3xx_irq_pending,
.busy_cycles = a3xx_busy_cycles,
.start = a3xx_start,
.snapshot = a3xx_snapshot,
+ .perfcounter_enable = a3xx_perfcounter_enable,
+ .perfcounter_read = a3xx_perfcounter_read,
};
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index ceb210d..a4bb4fa 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -431,7 +431,8 @@
return status;
/* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */
- if (adreno_is_a305(adreno_dev) || adreno_is_a320(adreno_dev))
+ if (adreno_is_a305(adreno_dev) || adreno_is_a305c(adreno_dev) ||
+ adreno_is_a320(adreno_dev))
adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000E0602);
else if (adreno_is_a330(adreno_dev) || adreno_is_a305b(adreno_dev))
adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x003E2008);
@@ -592,6 +593,9 @@
if (adreno_is_a20x(adreno_dev))
total_sizedwords += 2; /* CACHE_FLUSH */
+ if (flags & KGSL_CMD_FLAGS_EOF)
+ total_sizedwords += 2;
+
ringcmds = adreno_ringbuffer_allocspace(rb, context, total_sizedwords);
if (!ringcmds) {
/*
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index b3e7f90..53ef392 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2974,7 +2974,6 @@
if (result)
goto error_pwrctrl_close;
- kgsl_cffdump_open(device->id);
setup_timer(&device->idle_timer, kgsl_timer, (unsigned long) device);
status = kgsl_create_device_workqueue(device);
@@ -3103,7 +3102,6 @@
{
kgsl_device_snapshot_close(device);
- kgsl_cffdump_close(device->id);
kgsl_pwrctrl_uninit_sysfs(device);
pm_qos_remove_request(&device->pwrctrl.pm_qos_req_dma);
diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c
index e06c94d..6dc2ccc 100644
--- a/drivers/gpu/msm/kgsl_cffdump.c
+++ b/drivers/gpu/msm/kgsl_cffdump.c
@@ -28,6 +28,7 @@
#include "kgsl_log.h"
#include "kgsl_sharedmem.h"
#include "adreno_pm4types.h"
+#include "adreno.h"
static struct rchan *chan;
static struct dentry *dir;
@@ -334,7 +335,7 @@
return;
}
- kgsl_cff_dump_enable = 1;
+ kgsl_cff_dump_enable = 0;
spin_lock_init(&cffdump_lock);
@@ -356,10 +357,21 @@
debugfs_remove(dir);
}
-void kgsl_cffdump_open(enum kgsl_deviceid device_id)
+void kgsl_cffdump_open(struct kgsl_device *device)
{
- kgsl_cffdump_memory_base(device_id, KGSL_PAGETABLE_BASE,
- kgsl_mmu_get_ptsize(), SZ_256K);
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+
+ if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) {
+ kgsl_cffdump_memory_base(device->id,
+ kgsl_mmu_get_base_addr(&device->mmu),
+ kgsl_mmu_get_ptsize(&device->mmu) +
+ KGSL_IOMMU_GLOBAL_MEM_SIZE, adreno_dev->gmem_size);
+ } else {
+ kgsl_cffdump_memory_base(device->id,
+ kgsl_mmu_get_base_addr(&device->mmu),
+ kgsl_mmu_get_ptsize(&device->mmu),
+ adreno_dev->gmem_size);
+ }
}
void kgsl_cffdump_memory_base(enum kgsl_deviceid device_id, unsigned int base,
@@ -387,7 +399,7 @@
}
void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
- const struct kgsl_memdesc *memdesc, uint gpuaddr, uint sizebytes,
+ struct kgsl_memdesc *memdesc, uint gpuaddr, uint sizebytes,
bool clean_cache)
{
const void *src;
@@ -522,7 +534,7 @@
}
static struct dentry *create_buf_file_handler(const char *filename,
- struct dentry *parent, int mode, struct rchan_buf *buf,
+ struct dentry *parent, unsigned short mode, struct rchan_buf *buf,
int *is_global)
{
return debugfs_create_file(filename, mode, parent, buf,
diff --git a/drivers/gpu/msm/kgsl_cffdump.h b/drivers/gpu/msm/kgsl_cffdump.h
index 2733cc3..d5656f8 100644
--- a/drivers/gpu/msm/kgsl_cffdump.h
+++ b/drivers/gpu/msm/kgsl_cffdump.h
@@ -22,10 +22,10 @@
void kgsl_cffdump_init(void);
void kgsl_cffdump_destroy(void);
-void kgsl_cffdump_open(enum kgsl_deviceid device_id);
+void kgsl_cffdump_open(struct kgsl_device *device);
void kgsl_cffdump_close(enum kgsl_deviceid device_id);
void kgsl_cffdump_syncmem(struct kgsl_device_private *dev_priv,
- const struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes,
+ struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes,
bool clean_cache);
void kgsl_cffdump_setmem(uint addr, uint value, uint sizebytes);
void kgsl_cffdump_regwrite(enum kgsl_deviceid device_id, uint addr,
@@ -49,7 +49,7 @@
#define kgsl_cffdump_init() (void)0
#define kgsl_cffdump_destroy() (void)0
-#define kgsl_cffdump_open(device_id) (void)0
+#define kgsl_cffdump_open(device) (void)0
#define kgsl_cffdump_close(device_id) (void)0
#define kgsl_cffdump_syncmem(dev_priv, memdesc, addr, sizebytes, clean_cache) \
(void) 0
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index f327c04..739fcff 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -33,6 +33,7 @@
#include "adreno.h"
#include "kgsl_trace.h"
#include "z180.h"
+#include "kgsl_cffdump.h"
static struct kgsl_iommu_register_list kgsl_iommuv0_reg[KGSL_IOMMU_REG_MAX] = {
@@ -1548,6 +1549,10 @@
kgsl_iommu_lock_rb_in_tlb(mmu);
msm_iommu_unlock();
+ /* For complete CFF */
+ kgsl_cffdump_setmem(mmu->setstate_memory.gpuaddr +
+ KGSL_IOMMU_SETSTATE_NOP_OFFSET,
+ cp_nop_packet(1), sizeof(unsigned int));
kgsl_iommu_disable_clk_on_ts(mmu, 0, false);
mmu->flags |= KGSL_FLAGS_STARTED;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 296de11..4c9c744 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -106,7 +106,12 @@
{
struct kgsl_snapshot_linux_context *header = _ctxtptr;
struct kgsl_context *context = ptr;
- struct kgsl_device *device = context->dev_priv->device;
+ struct kgsl_device *device;
+
+ if (context)
+ device = context->dev_priv->device;
+ else
+ device = (struct kgsl_device *)data;
header->id = id;
@@ -141,6 +146,9 @@
idr_for_each(&device->context_idr, snapshot_context_count, &ctxtcount);
+ /* Increment ctxcount for the global memstore */
+ ctxtcount++;
+
size += ctxtcount * sizeof(struct kgsl_snapshot_linux_context);
/* Make sure there is enough room for the data */
@@ -186,8 +194,10 @@
header->ctxtcount = ctxtcount;
- /* append information for each context */
_ctxtptr = snapshot + sizeof(*header);
+ /* append information for the global context */
+ snapshot_context_info(KGSL_MEMSTORE_GLOBAL, NULL, device);
+ /* append information for each context */
idr_for_each(&device->context_idr, snapshot_context_info, NULL);
/* Return the size of the data segment */
diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c
index 98edb83..0e3e046 100644
--- a/drivers/gpu/msm/kgsl_sync.c
+++ b/drivers/gpu/msm/kgsl_sync.c
@@ -206,7 +206,7 @@
struct kgsl_sync_timeline *ktimeline =
(struct kgsl_sync_timeline *) timeline;
- if (timestamp_cmp(timestamp, ktimeline->last_timestamp > 0))
+ if (timestamp_cmp(timestamp, ktimeline->last_timestamp) > 0)
ktimeline->last_timestamp = timestamp;
sync_timeline_signal(timeline);
}
diff --git a/drivers/gpu/msm/z180.h b/drivers/gpu/msm/z180.h
index 268aac3..1be0870 100644
--- a/drivers/gpu/msm/z180.h
+++ b/drivers/gpu/msm/z180.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
@@ -29,7 +29,7 @@
#define Z180_DEFAULT_PWRSCALE_POLICY NULL
/* Wait a maximum of 10 seconds when trying to idle the core */
-#define Z180_IDLE_TIMEOUT (10 * 1000)
+#define Z180_IDLE_TIMEOUT (20 * 1000)
struct z180_ringbuffer {
unsigned int prevctx;
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index 60c2da3..1458bc5 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -365,7 +365,7 @@
return 0;
}
-EXPORT_SYMBOL_GPL(qpnp_adc_scale_pmic_therm);
+EXPORT_SYMBOL(qpnp_adc_scale_pmic_therm);
int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(
struct qpnp_adc_tm_btm_param *param,
@@ -400,7 +400,7 @@
return 0;
}
-EXPORT_SYMBOL_GPL(qpnp_adc_scale_millidegc_pmic_voltage_thr);
+EXPORT_SYMBOL(qpnp_adc_scale_millidegc_pmic_voltage_thr);
/* Scales the ADC code to degC using the mapping
* table for the XO thermistor.
@@ -426,7 +426,7 @@
return 0;
}
-EXPORT_SYMBOL_GPL(qpnp_adc_tdkntcg_therm);
+EXPORT_SYMBOL(qpnp_adc_tdkntcg_therm);
int32_t qpnp_adc_scale_batt_therm(int32_t adc_code,
const struct qpnp_adc_properties *adc_properties,
@@ -444,7 +444,7 @@
bat_voltage,
&adc_chan_result->physical);
}
-EXPORT_SYMBOL_GPL(qpnp_adc_scale_batt_therm);
+EXPORT_SYMBOL(qpnp_adc_scale_batt_therm);
int32_t qpnp_adc_scale_therm_pu1(int32_t adc_code,
const struct qpnp_adc_properties *adc_properties,
@@ -462,7 +462,7 @@
return 0;
}
-EXPORT_SYMBOL_GPL(qpnp_adc_scale_therm_pu1);
+EXPORT_SYMBOL(qpnp_adc_scale_therm_pu1);
int32_t qpnp_adc_scale_therm_pu2(int32_t adc_code,
const struct qpnp_adc_properties *adc_properties,
@@ -480,7 +480,7 @@
return 0;
}
-EXPORT_SYMBOL_GPL(qpnp_adc_scale_therm_pu2);
+EXPORT_SYMBOL(qpnp_adc_scale_therm_pu2);
int32_t qpnp_adc_tm_scale_voltage_therm_pu2(uint32_t reg, int64_t *result)
{
@@ -506,7 +506,7 @@
return 0;
}
-EXPORT_SYMBOL_GPL(qpnp_adc_tm_scale_voltage_therm_pu2);
+EXPORT_SYMBOL(qpnp_adc_tm_scale_voltage_therm_pu2);
int32_t qpnp_adc_tm_scale_therm_voltage_pu2(struct qpnp_adc_tm_config *param)
{
@@ -537,7 +537,7 @@
return 0;
}
-EXPORT_SYMBOL_GPL(qpnp_adc_tm_scale_therm_voltage_pu2);
+EXPORT_SYMBOL(qpnp_adc_tm_scale_therm_voltage_pu2);
int32_t qpnp_adc_scale_batt_id(int32_t adc_code,
const struct qpnp_adc_properties *adc_properties,
@@ -553,7 +553,7 @@
return 0;
}
-EXPORT_SYMBOL_GPL(qpnp_adc_scale_batt_id);
+EXPORT_SYMBOL(qpnp_adc_scale_batt_id);
int32_t qpnp_adc_scale_default(int32_t adc_code,
const struct qpnp_adc_properties *adc_properties,
@@ -610,7 +610,7 @@
return 0;
}
-EXPORT_SYMBOL_GPL(qpnp_adc_scale_default);
+EXPORT_SYMBOL(qpnp_adc_scale_default);
int32_t qpnp_adc_usb_scaler(struct qpnp_adc_tm_btm_param *param,
uint32_t *low_threshold, uint32_t *high_threshold)
@@ -631,28 +631,35 @@
param->low_thr);
return 0;
}
-EXPORT_SYMBOL_GPL(qpnp_adc_usb_scaler);
+EXPORT_SYMBOL(qpnp_adc_usb_scaler);
int32_t qpnp_adc_vbatt_rscaler(struct qpnp_adc_tm_btm_param *param,
uint32_t *low_threshold, uint32_t *high_threshold)
{
struct qpnp_vadc_linear_graph vbatt_param;
+ int rc = 0;
- qpnp_get_vadc_gain_and_offset(&vbatt_param, CALIB_ABSOLUTE);
+ rc = qpnp_get_vadc_gain_and_offset(&vbatt_param, CALIB_ABSOLUTE);
+ if (rc < 0)
+ return rc;
- *low_threshold = param->low_thr * vbatt_param.dy;
- do_div(*low_threshold, vbatt_param.adc_vref);
+ *low_threshold = (((param->low_thr/3) - QPNP_ADC_625_UV) *
+ vbatt_param.dy);
+ do_div(*low_threshold, QPNP_ADC_625_UV);
*low_threshold += vbatt_param.adc_gnd;
- *high_threshold = param->high_thr * vbatt_param.dy;
- do_div(*high_threshold, vbatt_param.adc_vref);
+ *high_threshold = (((param->high_thr/3) - QPNP_ADC_625_UV) *
+ vbatt_param.dy);
+ do_div(*high_threshold, QPNP_ADC_625_UV);
*high_threshold += vbatt_param.adc_gnd;
pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
param->low_thr);
+ pr_debug("adc_code_high:%x, adc_code_low:%x\n", *high_threshold,
+ *low_threshold);
return 0;
}
-EXPORT_SYMBOL_GPL(qpnp_adc_vbatt_rscaler);
+EXPORT_SYMBOL(qpnp_adc_vbatt_rscaler);
int32_t qpnp_adc_btm_scaler(struct qpnp_adc_tm_btm_param *param,
uint32_t *low_threshold, uint32_t *high_threshold)
@@ -704,7 +711,7 @@
*low_threshold);
return 0;
}
-EXPORT_SYMBOL_GPL(qpnp_adc_btm_scaler);
+EXPORT_SYMBOL(qpnp_adc_btm_scaler);
int32_t qpnp_vadc_check_result(int32_t *data)
{
@@ -715,7 +722,7 @@
return 0;
}
-EXPORT_SYMBOL_GPL(qpnp_vadc_check_result);
+EXPORT_SYMBOL(qpnp_vadc_check_result);
int32_t qpnp_adc_get_devicetree_data(struct spmi_device *spmi,
struct qpnp_adc_drv *adc_qpnp)
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 60dcada..27b9607 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -125,7 +125,6 @@
#define QPNP_BIT_SHIFT_8 8
#define QPNP_RSENSE_MSB_SIGN_CHECK 0x80
#define QPNP_ADC_COMPLETION_TIMEOUT HZ
-#define QPNP_IADC_ERR_CHK_RATELIMIT 3
struct qpnp_iadc_drv {
struct qpnp_adc_drv *adc;
@@ -136,7 +135,6 @@
struct delayed_work iadc_work;
struct mutex iadc_vadc_lock;
bool iadc_mode_sel;
- uint32_t iadc_err_cnt;
struct sensor_device_attribute sens_attr[0];
};
@@ -254,7 +252,7 @@
return rc;
}
- pr_err("EOC not set with status:%x, dig:%x, ch:%x, mode:%x, en:%x\n",
+ pr_debug("EOC not set with status:%x, dig:%x, ch:%x, mode:%x, en:%x\n",
status1, dig, chan, mode, en);
rc = qpnp_iadc_enable(false);
@@ -347,6 +345,8 @@
return rc;
}
+ INIT_COMPLETION(iadc->adc->adc_rslt_completion);
+
rc = qpnp_iadc_enable(true);
if (rc)
return rc;
@@ -409,7 +409,7 @@
return 0;
}
-static int32_t qpnp_iadc_calibrate_for_trim(void)
+int32_t qpnp_iadc_calibrate_for_trim(void)
{
struct qpnp_iadc_drv *iadc = qpnp_iadc;
uint8_t rslt_lsb, rslt_msb;
@@ -487,6 +487,7 @@
mutex_unlock(&iadc->adc->adc_lock);
return rc;
}
+EXPORT_SYMBOL(qpnp_iadc_calibrate_for_trim);
static void qpnp_iadc_work(struct work_struct *work)
{
@@ -494,16 +495,12 @@
int rc = 0;
rc = qpnp_iadc_calibrate_for_trim();
- if (rc) {
- pr_err("periodic IADC calibration failed\n");
- iadc->iadc_err_cnt++;
- }
-
- if (iadc->iadc_err_cnt < QPNP_IADC_ERR_CHK_RATELIMIT)
+ if (rc)
+ pr_debug("periodic IADC calibration failed\n");
+ else
schedule_delayed_work(&iadc->iadc_work,
round_jiffies_relative(msecs_to_jiffies
(QPNP_IADC_CALIB_SECONDS)));
-
return;
}
@@ -856,7 +853,6 @@
mutex_init(&iadc->iadc_vadc_lock);
INIT_DELAYED_WORK(&iadc->iadc_work, qpnp_iadc_work);
- iadc->iadc_err_cnt = 0;
iadc->iadc_initialized = true;
rc = qpnp_iadc_calibrate_for_trim();
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 0470a62..d296a47 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -90,6 +90,7 @@
#define QPNP_VADC_CONV_TIME_MIN 2000
#define QPNP_VADC_CONV_TIME_MAX 2100
#define QPNP_ADC_COMPLETION_TIMEOUT HZ
+#define QPNP_VADC_ERR_COUNT 5
struct qpnp_vadc_drv {
struct qpnp_adc_drv *adc;
@@ -434,7 +435,7 @@
{
struct qpnp_vadc_drv *vadc = qpnp_vadc;
struct qpnp_adc_amux_properties conv;
- int rc, calib_read_1, calib_read_2;
+ int rc, calib_read_1, calib_read_2, count = 0;
u8 status1 = 0;
conv.amux_channel = REF_125V;
@@ -456,6 +457,11 @@
status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
usleep_range(QPNP_VADC_CONV_TIME_MIN,
QPNP_VADC_CONV_TIME_MAX);
+ count++;
+ if (count > QPNP_VADC_ERR_COUNT) {
+ rc = -ENODEV;
+ goto calib_fail;
+ }
}
rc = qpnp_vadc_read_conversion_result(&calib_read_1);
@@ -476,6 +482,7 @@
}
status1 = 0;
+ count = 0;
while (status1 != QPNP_VADC_STATUS1_EOC) {
rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
if (rc < 0)
@@ -483,6 +490,11 @@
status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
usleep_range(QPNP_VADC_CONV_TIME_MIN,
QPNP_VADC_CONV_TIME_MAX);
+ count++;
+ if (count > QPNP_VADC_ERR_COUNT) {
+ rc = -ENODEV;
+ goto calib_fail;
+ }
}
rc = qpnp_vadc_read_conversion_result(&calib_read_2);
@@ -516,6 +528,7 @@
}
status1 = 0;
+ count = 0;
while (status1 != QPNP_VADC_STATUS1_EOC) {
rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
if (rc < 0)
@@ -523,6 +536,11 @@
status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
usleep_range(QPNP_VADC_CONV_TIME_MIN,
QPNP_VADC_CONV_TIME_MAX);
+ count++;
+ if (count > QPNP_VADC_ERR_COUNT) {
+ rc = -ENODEV;
+ goto calib_fail;
+ }
}
rc = qpnp_vadc_read_conversion_result(&calib_read_1);
@@ -543,6 +561,7 @@
}
status1 = 0;
+ count = 0;
while (status1 != QPNP_VADC_STATUS1_EOC) {
rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
if (rc < 0)
@@ -550,6 +569,11 @@
status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
usleep_range(QPNP_VADC_CONV_TIME_MIN,
QPNP_VADC_CONV_TIME_MAX);
+ count++;
+ if (count > QPNP_VADC_ERR_COUNT) {
+ rc = -ENODEV;
+ goto calib_fail;
+ }
}
rc = qpnp_vadc_read_conversion_result(&calib_read_2);
@@ -741,7 +765,7 @@
return qpnp_vadc_conv_seq_request(ADC_SEQ_NONE,
channel, result);
}
-EXPORT_SYMBOL_GPL(qpnp_vadc_read);
+EXPORT_SYMBOL(qpnp_vadc_read);
static void qpnp_vadc_lock(void)
{
diff --git a/drivers/input/touchscreen/synaptics_fw_update.c b/drivers/input/touchscreen/synaptics_fw_update.c
index 7452587..986c062 100644
--- a/drivers/input/touchscreen/synaptics_fw_update.c
+++ b/drivers/input/touchscreen/synaptics_fw_update.c
@@ -30,7 +30,6 @@
#define DEBUG_FW_UPDATE
#define SHOW_PROGRESS
-#define FW_IMAGE_NAME "PR1063486-s7301_00000000.img"
#define MAX_FIRMWARE_ID_LEN 10
#define FORCE_UPDATE false
#define INSIDE_FIRMWARE_UPDATE
@@ -561,8 +560,6 @@
goto exit;
}
- imagePR = kzalloc(sizeof(MAX_FIRMWARE_ID_LEN), GFP_KERNEL);
-
/* Force update firmware when device is in bootloader mode */
if (f01_device_status.flash_prog) {
dev_info(&i2c_client->dev,
@@ -587,7 +584,8 @@
deviceFirmwareID = extract_uint(firmware_id);
/* .img firmware id */
- strptr = strstr(FW_IMAGE_NAME, "PR");
+ strptr = strnstr(fwu->rmi4_data->fw_image_name, "PR",
+ sizeof(fwu->rmi4_data->fw_image_name));
if (!strptr) {
dev_err(&i2c_client->dev,
"No valid PR number (PRxxxxxxx)" \
@@ -616,6 +614,11 @@
if (imageFirmwareID > deviceFirmwareID) {
flash_area = UI_FIRMWARE;
goto exit;
+ } else if (imageFirmwareID < deviceFirmwareID) {
+ flash_area = NONE;
+ dev_info(&i2c_client->dev,
+ "Img fw is older than device fw. Skip fw update.\n");
+ goto exit;
}
/* device config id */
@@ -1216,19 +1219,28 @@
pr_notice("%s: Start of reflash process\n", __func__);
+ if (!fwu->rmi4_data->fw_image_name) {
+ retval = 0;
+ dev_err(&fwu->rmi4_data->i2c_client->dev,
+ "Firmware image name not given, skipping update\n");
+ goto exit;
+ }
+
if (fwu->ext_data_source)
fw_image = fwu->ext_data_source;
else {
dev_dbg(&fwu->rmi4_data->i2c_client->dev,
"%s: Requesting firmware image %s\n",
- __func__, FW_IMAGE_NAME);
+ __func__, fwu->rmi4_data->fw_image_name);
- retval = request_firmware(&fw_entry, FW_IMAGE_NAME,
+ retval = request_firmware(&fw_entry,
+ fwu->rmi4_data->fw_image_name,
&fwu->rmi4_data->i2c_client->dev);
if (retval != 0) {
dev_err(&fwu->rmi4_data->i2c_client->dev,
"%s: Firmware image %s not available\n",
- __func__, FW_IMAGE_NAME);
+ __func__,
+ fwu->rmi4_data->fw_image_name);
retval = -EINVAL;
goto exit;
}
@@ -1650,6 +1662,9 @@
&fwu->fwu_work,
msecs_to_jiffies(1000));
#endif
+
+ init_completion(&remove_complete);
+
return 0;
exit_remove_attrs:
@@ -1700,7 +1715,6 @@
static void __exit rmi4_fw_update_module_exit(void)
{
- init_completion(&remove_complete);
synaptics_rmi4_new_function(RMI_FW_UPDATER, false,
synaptics_rmi4_fwu_init,
synaptics_rmi4_fwu_remove,
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.c b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
index 775d62a..417ef83 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.c
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.c
@@ -65,8 +65,8 @@
#define NORMAL_OPERATION (0 << 0)
#define SENSOR_SLEEP (1 << 0)
-#define NO_SLEEP_OFF (0 << 3)
-#define NO_SLEEP_ON (1 << 3)
+#define NO_SLEEP_OFF (0 << 2)
+#define NO_SLEEP_ON (1 << 2)
#define RMI4_VTG_MIN_UV 2700000
#define RMI4_VTG_MAX_UV 3300000
@@ -125,6 +125,19 @@
static ssize_t synaptics_rmi4_0dbutton_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t synaptics_rmi4_flipx_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_flipx_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+static ssize_t synaptics_rmi4_flipy_show(struct device *dev,
+ struct device_attribute *attr, char *buf);
+
+static ssize_t synaptics_rmi4_flipy_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count);
+
+
struct synaptics_rmi4_f01_device_status {
union {
struct {
@@ -223,6 +236,12 @@
__ATTR(0dbutton, (S_IRUGO | S_IWUGO),
synaptics_rmi4_0dbutton_show,
synaptics_rmi4_0dbutton_store),
+ __ATTR(flipx, (S_IRUGO | S_IWUGO),
+ synaptics_rmi4_flipx_show,
+ synaptics_rmi4_flipx_store),
+ __ATTR(flipy, (S_IRUGO | S_IWUGO),
+ synaptics_rmi4_flipy_show,
+ synaptics_rmi4_flipy_store),
};
static bool exp_fn_inited;
@@ -391,6 +410,52 @@
return count;
}
+static ssize_t synaptics_rmi4_flipx_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ rmi4_data->flip_x);
+}
+
+static ssize_t synaptics_rmi4_flipx_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int input;
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ if (sscanf(buf, "%u", &input) != 1)
+ return -EINVAL;
+
+ rmi4_data->flip_x = input > 0 ? 1 : 0;
+
+ return count;
+}
+
+static ssize_t synaptics_rmi4_flipy_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ rmi4_data->flip_y);
+}
+
+static ssize_t synaptics_rmi4_flipy_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ unsigned int input;
+ struct synaptics_rmi4_data *rmi4_data = dev_get_drvdata(dev);
+
+ if (sscanf(buf, "%u", &input) != 1)
+ return -EINVAL;
+
+ rmi4_data->flip_y = input > 0 ? 1 : 0;
+
+ return count;
+}
+
/**
* synaptics_rmi4_set_page()
*
@@ -581,6 +646,7 @@
int y;
int wx;
int wy;
+ int z;
/*
* The number of finger status registers is determined by the
@@ -634,10 +700,11 @@
y = (data[1] << 4) | ((data[2] >> 4) & MASK_4BIT);
wx = (data[3] & MASK_4BIT);
wy = (data[3] >> 4) & MASK_4BIT;
+ z = data[4];
- if (rmi4_data->board->x_flip)
+ if (rmi4_data->flip_x)
x = rmi4_data->sensor_max_x - x;
- if (rmi4_data->board->y_flip)
+ if (rmi4_data->flip_y)
y = rmi4_data->sensor_max_y - y;
dev_dbg(&rmi4_data->i2c_client->dev,
@@ -655,6 +722,8 @@
ABS_MT_POSITION_X, x);
input_report_abs(rmi4_data->input_dev,
ABS_MT_POSITION_Y, y);
+ input_report_abs(rmi4_data->input_dev,
+ ABS_MT_PRESSURE, z);
#ifdef REPORT_2D_W
input_report_abs(rmi4_data->input_dev,
@@ -937,6 +1006,13 @@
rmi4_pdata->panel_y = temp_val;
}
+ rc = of_property_read_string(np, "synaptics,fw-image-name",
+ &rmi4_pdata->fw_image_name);
+ if (rc && (rc != -EINVAL)) {
+ dev_err(dev, "Unable to read fw image name\n");
+ return rc;
+ }
+
/* reset, irq gpio info */
rmi4_pdata->reset_gpio = of_get_named_gpio_flags(np,
"synaptics,reset-gpio", 0, &rmi4_pdata->reset_flags);
@@ -1007,22 +1083,12 @@
if (retval < 0)
return retval;
- retval = request_threaded_irq(rmi4_data->irq, NULL,
- synaptics_rmi4_irq,
- rmi4_data->board->irq_flags,
- DRIVER_NAME, rmi4_data);
- if (retval < 0) {
- dev_err(&rmi4_data->i2c_client->dev,
- "%s: Failed to create irq thread\n",
- __func__);
- return retval;
- }
+ enable_irq(rmi4_data->irq);
rmi4_data->irq_enabled = true;
} else {
if (rmi4_data->irq_enabled) {
disable_irq(rmi4_data->irq);
- free_irq(rmi4_data->irq, rmi4_data);
rmi4_data->irq_enabled = false;
}
}
@@ -1257,7 +1323,7 @@
static int synaptics_rmi4_alloc_fh(struct synaptics_rmi4_fn **fhandler,
struct synaptics_rmi4_fn_desc *rmi_fd, int page_number)
{
- *fhandler = kmalloc(sizeof(**fhandler), GFP_KERNEL);
+ *fhandler = kzalloc(sizeof(**fhandler), GFP_KERNEL);
if (!(*fhandler))
return -ENOMEM;
@@ -1273,6 +1339,7 @@
(*fhandler)->full_addr.query_base =
(rmi_fd->query_base_addr |
(page_number << 8));
+ (*fhandler)->fn_number = rmi_fd->fn_number;
return 0;
}
@@ -1331,7 +1398,7 @@
__func__, retval);
return retval;
}
- return retval;
+ return 0;
}
/**
@@ -1423,15 +1490,6 @@
}
break;
- case SYNAPTICS_RMI4_F34:
- retval = synaptics_rmi4_i2c_read(rmi4_data,
- rmi_fd.ctrl_base_addr,
- rmi->config_id,
- sizeof(rmi->config_id));
- if (retval < 0)
- return retval;
- break;
-
case SYNAPTICS_RMI4_F11:
if (rmi_fd.intr_src_count == 0)
break;
@@ -1530,14 +1588,51 @@
return 0;
}
-static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data)
+static int synaptics_rmi4_reset_command(struct synaptics_rmi4_data *rmi4_data)
{
int retval;
+ int page_number;
unsigned char command = 0x01;
- struct synaptics_rmi4_fn *fhandler;
- struct synaptics_rmi4_device_info *rmi;
+ unsigned short pdt_entry_addr;
+ struct synaptics_rmi4_fn_desc rmi_fd;
+ bool done = false;
- rmi = &(rmi4_data->rmi4_mod_info);
+ /* Scan the page description tables of the pages to service */
+ for (page_number = 0; page_number < PAGES_TO_SERVICE; page_number++) {
+ for (pdt_entry_addr = PDT_START; pdt_entry_addr > PDT_END;
+ pdt_entry_addr -= PDT_ENTRY_SIZE) {
+ retval = synaptics_rmi4_i2c_read(rmi4_data,
+ pdt_entry_addr,
+ (unsigned char *)&rmi_fd,
+ sizeof(rmi_fd));
+ if (retval < 0)
+ return retval;
+
+ if (rmi_fd.fn_number == 0)
+ break;
+
+ switch (rmi_fd.fn_number) {
+ case SYNAPTICS_RMI4_F01:
+ rmi4_data->f01_cmd_base_addr =
+ rmi_fd.cmd_base_addr;
+ done = true;
+ break;
+ }
+ }
+ if (done) {
+ dev_info(&rmi4_data->i2c_client->dev,
+ "%s: Find F01 in page description table 0x%x\n",
+ __func__, rmi4_data->f01_cmd_base_addr);
+ break;
+ }
+ }
+
+ if (!done) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "%s: Cannot find F01 in page description table\n",
+ __func__);
+ return -EINVAL;
+ }
retval = synaptics_rmi4_i2c_write(rmi4_data,
rmi4_data->f01_cmd_base_addr,
@@ -1551,6 +1646,24 @@
}
msleep(100);
+ return retval;
+};
+
+static int synaptics_rmi4_reset_device(struct synaptics_rmi4_data *rmi4_data)
+{
+ int retval;
+ struct synaptics_rmi4_fn *fhandler;
+ struct synaptics_rmi4_device_info *rmi;
+
+ rmi = &(rmi4_data->rmi4_mod_info);
+
+ retval = synaptics_rmi4_reset_command(rmi4_data);
+ if (retval < 0) {
+ dev_err(&rmi4_data->i2c_client->dev,
+ "%s: Failed to send command reset\n",
+ __func__);
+ return retval;
+ }
if (!list_empty(&rmi->support_fn_list)) {
list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
@@ -1921,6 +2034,11 @@
rmi4_data->irq_enable = synaptics_rmi4_irq_enable;
rmi4_data->reset_device = synaptics_rmi4_reset_device;
+ rmi4_data->flip_x = rmi4_data->board->x_flip;
+ rmi4_data->flip_y = rmi4_data->board->y_flip;
+
+ rmi4_data->fw_image_name = rmi4_data->board->fw_image_name;
+
rmi4_data->input_dev->name = DRIVER_NAME;
rmi4_data->input_dev->phys = INPUT_PHYS_NAME;
rmi4_data->input_dev->id.bustype = BUS_I2C;
@@ -1993,7 +2111,8 @@
usleep(RMI4_GPIO_SLEEP_LOW_US);
gpio_set_value(platform_data->reset_gpio, 1);
msleep(RMI4_GPIO_WAIT_HIGH_MS);
- }
+ } else
+ synaptics_rmi4_reset_command(rmi4_data);
init_waitqueue_head(&rmi4_data->wait);
@@ -2013,6 +2132,8 @@
input_set_abs_params(rmi4_data->input_dev,
ABS_MT_POSITION_Y, 0,
rmi4_data->sensor_max_y, 0, 0);
+ input_set_abs_params(rmi4_data->input_dev,
+ ABS_PRESSURE, 0, 255, 0, 0);
#ifdef REPORT_2D_W
input_set_abs_params(rmi4_data->input_dev,
ABS_MT_TOUCH_MAJOR, 0,
@@ -2074,10 +2195,14 @@
rmi4_data->irq = gpio_to_irq(platform_data->irq_gpio);
- retval = synaptics_rmi4_irq_enable(rmi4_data, true);
+ retval = request_threaded_irq(rmi4_data->irq, NULL,
+ synaptics_rmi4_irq, platform_data->irq_flags,
+ DRIVER_NAME, rmi4_data);
+ rmi4_data->irq_enabled = true;
+
if (retval < 0) {
dev_err(&client->dev,
- "%s: Failed to enable attention interrupt\n",
+ "%s: Failed to create irq thread\n",
__func__);
goto err_enable_irq;
}
@@ -2092,6 +2217,13 @@
goto err_sysfs;
}
}
+ retval = synaptics_rmi4_irq_enable(rmi4_data, true);
+ if (retval < 0) {
+ dev_err(&client->dev,
+ "%s: Failed to enable attention interrupt\n",
+ __func__);
+ goto err_sysfs;
+ }
return retval;
@@ -2162,7 +2294,7 @@
rmi4_data->touch_stopped = true;
wake_up(&rmi4_data->wait);
- synaptics_rmi4_irq_enable(rmi4_data, false);
+ free_irq(rmi4_data->irq, rmi4_data);
for (attr_count = 0; attr_count < ARRAY_SIZE(attrs); attr_count++) {
sysfs_remove_file(&rmi4_data->input_dev->dev.kobj,
diff --git a/drivers/input/touchscreen/synaptics_i2c_rmi4.h b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
index b1d2645..16b1f8f 100644
--- a/drivers/input/touchscreen/synaptics_i2c_rmi4.h
+++ b/drivers/input/touchscreen/synaptics_i2c_rmi4.h
@@ -24,7 +24,7 @@
#define SYNAPTICS_DS4 (1 << 0)
#define SYNAPTICS_DS5 (1 << 1)
#define SYNAPTICS_DSX_DRIVER_PRODUCT SYNAPTICS_DS4
-#define SYNAPTICS_DSX_DRIVER_VERSION 0x1002
+#define SYNAPTICS_DSX_DRIVER_VERSION 0x1004
#include <linux/version.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
@@ -177,6 +177,8 @@
* @irq_enabled: flag for indicating interrupt enable status
* @touch_stopped: flag to stop interrupt thread processing
* @fingers_on_2d: flag to indicate presence of fingers in 2d area
+ * @flip_x: set to TRUE if desired to flip direction on x-axis
+ * @flip_y: set to TRUE if desired to flip direction on y-axis
* @sensor_sleep: flag to indicate sleep state of sensor
* @wait: wait queue for touch data polling in interrupt thread
* @i2c_read: pointer to i2c read function
@@ -196,6 +198,7 @@
#ifdef CONFIG_HAS_EARLYSUSPEND
struct early_suspend early_suspend;
#endif
+ const char *fw_image_name;
unsigned char current_page;
unsigned char button_0d_enabled;
unsigned char full_pm_cycle;
@@ -215,6 +218,8 @@
bool touch_stopped;
bool fingers_on_2d;
bool sensor_sleep;
+ bool flip_x;
+ bool flip_y;
wait_queue_head_t wait;
int (*i2c_read)(struct synaptics_rmi4_data *pdata, unsigned short addr,
unsigned char *data, unsigned short length);
diff --git a/drivers/input/touchscreen/synaptics_rmi_dev.c b/drivers/input/touchscreen/synaptics_rmi_dev.c
index 7f1aac5..c6b8a1c 100644
--- a/drivers/input/touchscreen/synaptics_rmi_dev.c
+++ b/drivers/input/touchscreen/synaptics_rmi_dev.c
@@ -619,6 +619,8 @@
}
}
+ init_completion(&remove_complete);
+
return 0;
err_sysfs_attrs:
diff --git a/drivers/iommu/msm_iommu-v0.c b/drivers/iommu/msm_iommu-v0.c
index de35f9a..c0a4720 100644
--- a/drivers/iommu/msm_iommu-v0.c
+++ b/drivers/iommu/msm_iommu-v0.c
@@ -156,21 +156,15 @@
clk_disable_unprepare(drvdata->pclk);
}
-static int _iommu_power_on(void *data)
+static int __enable_regulators(struct msm_iommu_drvdata *drvdata)
{
- struct msm_iommu_drvdata *drvdata;
-
- drvdata = (struct msm_iommu_drvdata *)data;
- return __enable_clocks(drvdata);
+ /* No need to do anything. IOMMUv0 is always on. */
+ return 0;
}
-static int _iommu_power_off(void *data)
+static void __disable_regulators(struct msm_iommu_drvdata *drvdata)
{
- struct msm_iommu_drvdata *drvdata;
-
- drvdata = (struct msm_iommu_drvdata *)data;
- __disable_clocks(drvdata);
- return 0;
+ /* No need to do anything. IOMMUv0 is always on. */
}
static void _iommu_lock_acquire(void)
@@ -184,8 +178,10 @@
}
struct iommu_access_ops iommu_access_ops_v0 = {
- .iommu_power_on = _iommu_power_on,
- .iommu_power_off = _iommu_power_off,
+ .iommu_power_on = __enable_regulators,
+ .iommu_power_off = __disable_regulators,
+ .iommu_clk_on = __enable_clocks,
+ .iommu_clk_off = __disable_clocks,
.iommu_lock_acquire = _iommu_lock_acquire,
.iommu_lock_release = _iommu_lock_release,
};
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index f552474..8a26003 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -103,36 +103,6 @@
clk_disable_unprepare(drvdata->pclk);
}
-static int _iommu_power_off(void *data)
-{
- struct msm_iommu_drvdata *drvdata;
-
- drvdata = (struct msm_iommu_drvdata *)data;
- __disable_clocks(drvdata);
- __disable_regulators(drvdata);
- return 0;
-}
-
-static int _iommu_power_on(void *data)
-{
- int ret;
- struct msm_iommu_drvdata *drvdata;
-
- drvdata = (struct msm_iommu_drvdata *)data;
- ret = __enable_regulators(drvdata);
- if (ret)
- goto fail;
-
- ret = __enable_clocks(drvdata);
- if (ret) {
- __disable_regulators(drvdata);
- goto fail;
- }
- return 0;
-fail:
- return -EIO;
-}
-
static void _iommu_lock_acquire(void)
{
mutex_lock(&msm_iommu_lock);
@@ -144,8 +114,10 @@
}
struct iommu_access_ops iommu_access_ops_v1 = {
- .iommu_power_on = _iommu_power_on,
- .iommu_power_off = _iommu_power_off,
+ .iommu_power_on = __enable_regulators,
+ .iommu_power_off = __disable_regulators,
+ .iommu_clk_on = __enable_clocks,
+ .iommu_clk_off = __disable_clocks,
.iommu_lock_acquire = _iommu_lock_acquire,
.iommu_lock_release = _iommu_lock_release,
};
@@ -260,8 +232,6 @@
SET_GFAR(base, 0);
SET_GFSRRESTORE(base, 0);
SET_TLBIALLNSNH(base, 0);
- SET_SCR1(base, 0);
- SET_SSDR_N(base, 0, 0);
smt_size = GET_IDR0_NUMSMRG(base);
for (i = 0; i < smt_size; i++)
diff --git a/drivers/iommu/msm_iommu_dev-v1.c b/drivers/iommu/msm_iommu_dev-v1.c
index f994413..418a086 100644
--- a/drivers/iommu/msm_iommu_dev-v1.c
+++ b/drivers/iommu/msm_iommu_dev-v1.c
@@ -265,6 +265,8 @@
platform_set_drvdata(pdev, drvdata);
+ msm_iommu_sec_set_access_ops(&iommu_access_ops_v1);
+
pmon_info = msm_iommu_pm_alloc(&pdev->dev);
if (pmon_info != NULL) {
ret = msm_iommu_pmon_parse_dt(pdev, pmon_info);
diff --git a/drivers/iommu/msm_iommu_perfmon-v0.c b/drivers/iommu/msm_iommu_perfmon-v0.c
index c80d1e5..1073623 100644
--- a/drivers/iommu/msm_iommu_perfmon-v0.c
+++ b/drivers/iommu/msm_iommu_perfmon-v0.c
@@ -21,6 +21,7 @@
#include <linux/device.h>
#include <mach/iommu_hw-v0.h>
#include <mach/iommu_perfmon.h>
+#include <mach/iommu.h>
#define PM_RESET_MASK (0xF)
#define PM_RESET_SHIFT (0x8)
@@ -280,7 +281,9 @@
* for locking here.
*/
iommu->ops->iommu_power_on(iommu_drvdata);
+ iommu->ops->iommu_clk_on(iommu_drvdata);
iommu_pm_set_int_active_high(iommu);
+ iommu->ops->iommu_clk_off(iommu_drvdata);
iommu->ops->iommu_power_off(iommu_drvdata);
}
diff --git a/drivers/iommu/msm_iommu_perfmon-v1.c b/drivers/iommu/msm_iommu_perfmon-v1.c
index d76ee7f..7d6dd34 100644
--- a/drivers/iommu/msm_iommu_perfmon-v1.c
+++ b/drivers/iommu/msm_iommu_perfmon-v1.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <mach/iommu_hw-v1.h>
#include <mach/iommu_perfmon.h>
+#include <mach/iommu.h>
#define PMCR_P_MASK (0x1)
#define PMCR_P_SHIFT (1)
diff --git a/drivers/iommu/msm_iommu_perfmon.c b/drivers/iommu/msm_iommu_perfmon.c
index 41df1ed..fee8a4a 100644
--- a/drivers/iommu/msm_iommu_perfmon.c
+++ b/drivers/iommu/msm_iommu_perfmon.c
@@ -242,6 +242,7 @@
dev_get_drvdata(iommu->iommu_dev);
iommu->ops->iommu_power_on(iommu_drvdata);
+ iommu->ops->iommu_clk_on(iommu_drvdata);
/* Reset counters in HW */
iommu->ops->iommu_lock_acquire();
@@ -294,6 +295,7 @@
iommu_pm_read_all_counters(pmon);
iommu->ops->iommu_lock_release();
+ iommu->ops->iommu_clk_off(iommu_drvdata);
iommu->ops->iommu_power_off(iommu_drvdata);
pr_info("%s: TLB performance monitoring turned OFF\n",
diff --git a/drivers/iommu/msm_iommu_sec.c b/drivers/iommu/msm_iommu_sec.c
index 5ca6fd9..74d8b48 100644
--- a/drivers/iommu/msm_iommu_sec.c
+++ b/drivers/iommu/msm_iommu_sec.c
@@ -43,8 +43,11 @@
#define IOMMU_SECURE_PTBL_INIT 4
#define IOMMU_SECURE_MAP 6
#define IOMMU_SECURE_UNMAP 7
+#define IOMMU_SECURE_MAP2 0x0B
+#define IOMMU_SECURE_UNMAP2 0x0C
+#define IOMMU_TLBINVAL_FLAG 0x00000001
-static DEFINE_MUTEX(msm_iommu_lock);
+static struct iommu_access_ops *iommu_access_ops;
struct msm_scm_paddr_list {
unsigned int list;
@@ -59,11 +62,22 @@
unsigned int size;
};
-struct msm_scm_map_req {
+struct msm_scm_map2_req {
struct msm_scm_paddr_list plist;
struct msm_scm_mapping_info info;
+ unsigned int flags;
};
+struct msm_scm_unmap2_req {
+ struct msm_scm_mapping_info info;
+ unsigned int flags;
+};
+
+void msm_iommu_sec_set_access_ops(struct iommu_access_ops *access_ops)
+{
+ iommu_access_ops = access_ops;
+}
+
static int msm_iommu_sec_ptbl_init(void)
{
struct device_node *np;
@@ -153,7 +167,7 @@
struct msm_iommu_ctx_drvdata *ctx_drvdata,
unsigned long va, phys_addr_t pa, size_t len)
{
- struct msm_scm_map_req map;
+ struct msm_scm_map2_req map;
int ret = 0;
map.plist.list = virt_to_phys(&pa);
@@ -163,8 +177,9 @@
map.info.ctx_id = ctx_drvdata->num;
map.info.va = va;
map.info.size = len;
+ map.flags = IOMMU_TLBINVAL_FLAG;
- if (scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP, &map, sizeof(map), &ret,
+ if (scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP2, &map, sizeof(map), &ret,
sizeof(ret)))
return -EINVAL;
if (ret)
@@ -191,7 +206,7 @@
unsigned long va, struct scatterlist *sg, size_t len)
{
struct scatterlist *sgiter;
- struct msm_scm_map_req map;
+ struct msm_scm_map2_req map;
unsigned int *pa_list = 0;
unsigned int pa, cnt;
unsigned int offset = 0, chunk_offset = 0;
@@ -201,6 +216,7 @@
map.info.ctx_id = ctx_drvdata->num;
map.info.va = va;
map.info.size = len;
+ map.flags = IOMMU_TLBINVAL_FLAG;
if (sg->length == len) {
pa = get_phys_addr(sg);
@@ -239,7 +255,7 @@
map.plist.size = SZ_1M;
}
- ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP, &map, sizeof(map),
+ ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_MAP2, &map, sizeof(map),
&scm_ret, sizeof(scm_ret));
kfree(pa_list);
return ret;
@@ -249,50 +265,20 @@
struct msm_iommu_ctx_drvdata *ctx_drvdata,
unsigned long va, size_t len)
{
- struct msm_scm_mapping_info mi;
+ struct msm_scm_unmap2_req unmap;
int ret, scm_ret;
- mi.id = iommu_drvdata->sec_id;
- mi.ctx_id = ctx_drvdata->num;
- mi.va = va;
- mi.size = len;
+ unmap.info.id = iommu_drvdata->sec_id;
+ unmap.info.ctx_id = ctx_drvdata->num;
+ unmap.info.va = va;
+ unmap.info.size = len;
+ unmap.flags = IOMMU_TLBINVAL_FLAG;
- ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_UNMAP, &mi, sizeof(mi),
+ ret = scm_call(SCM_SVC_MP, IOMMU_SECURE_UNMAP2, &unmap, sizeof(unmap),
&scm_ret, sizeof(scm_ret));
return ret;
}
-static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
-{
- int ret;
-
- ret = clk_prepare_enable(drvdata->pclk);
- if (ret)
- goto fail;
-
- ret = clk_prepare_enable(drvdata->clk);
- if (ret)
- clk_disable_unprepare(drvdata->pclk);
-
- if (drvdata->aclk) {
- ret = clk_prepare_enable(drvdata->aclk);
- if (ret) {
- clk_disable_unprepare(drvdata->clk);
- clk_disable_unprepare(drvdata->pclk);
- }
- }
-fail:
- return ret;
-}
-
-static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
-{
- if (drvdata->aclk)
- clk_disable_unprepare(drvdata->aclk);
- clk_disable_unprepare(drvdata->clk);
- clk_disable_unprepare(drvdata->pclk);
-}
-
static int msm_iommu_domain_init(struct iommu_domain *domain, int flags)
{
struct msm_iommu_priv *priv;
@@ -310,12 +296,12 @@
{
struct msm_iommu_priv *priv;
- mutex_lock(&msm_iommu_lock);
+ iommu_access_ops->iommu_lock_acquire();
priv = domain->priv;
domain->priv = NULL;
kfree(priv);
- mutex_unlock(&msm_iommu_lock);
+ iommu_access_ops->iommu_lock_release();
}
static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
@@ -326,7 +312,7 @@
struct msm_iommu_ctx_drvdata *tmp_drvdata;
int ret = 0;
- mutex_lock(&msm_iommu_lock);
+ iommu_access_ops->iommu_lock_acquire();
priv = domain->priv;
if (!priv || !dev) {
@@ -352,15 +338,15 @@
goto fail;
}
- ret = regulator_enable(iommu_drvdata->gdsc);
+ ret = iommu_access_ops->iommu_power_on(iommu_drvdata);
if (ret)
goto fail;
/* We can only do this once */
if (!iommu_drvdata->ctx_attach_count) {
- ret = __enable_clocks(iommu_drvdata);
+ ret = iommu_access_ops->iommu_clk_on(iommu_drvdata);
if (ret) {
- regulator_disable(iommu_drvdata->gdsc);
+ iommu_access_ops->iommu_power_off(iommu_drvdata);
goto fail;
}
@@ -370,9 +356,9 @@
program_iommu_bfb_settings(iommu_drvdata->base,
iommu_drvdata->bfb_settings);
- __disable_clocks(iommu_drvdata);
+ iommu_access_ops->iommu_clk_off(iommu_drvdata);
if (ret) {
- regulator_disable(iommu_drvdata->gdsc);
+ iommu_access_ops->iommu_power_off(iommu_drvdata);
goto fail;
}
}
@@ -381,12 +367,12 @@
ctx_drvdata->attached_domain = domain;
++iommu_drvdata->ctx_attach_count;
- mutex_unlock(&msm_iommu_lock);
+ iommu_access_ops->iommu_lock_release();
msm_iommu_attached(dev->parent);
return ret;
fail:
- mutex_unlock(&msm_iommu_lock);
+ iommu_access_ops->iommu_lock_release();
return ret;
}
@@ -398,7 +384,7 @@
msm_iommu_detached(dev->parent);
- mutex_lock(&msm_iommu_lock);
+ iommu_access_ops->iommu_lock_acquire();
if (!dev)
goto fail;
@@ -410,11 +396,11 @@
list_del_init(&ctx_drvdata->attached_elm);
ctx_drvdata->attached_domain = NULL;
- regulator_disable(iommu_drvdata->gdsc);
+ iommu_access_ops->iommu_power_off(iommu_drvdata);
BUG_ON(iommu_drvdata->ctx_attach_count == 0);
--iommu_drvdata->ctx_attach_count;
fail:
- mutex_unlock(&msm_iommu_lock);
+ iommu_access_ops->iommu_lock_release();
}
static int get_drvdata(struct iommu_domain *domain,
@@ -444,16 +430,18 @@
struct msm_iommu_ctx_drvdata *ctx_drvdata;
int ret = 0;
- mutex_lock(&msm_iommu_lock);
+ iommu_access_ops->iommu_lock_acquire();
ret = get_drvdata(domain, &iommu_drvdata, &ctx_drvdata);
if (ret)
goto fail;
+ iommu_access_ops->iommu_clk_on(iommu_drvdata);
ret = msm_iommu_sec_ptbl_map(iommu_drvdata, ctx_drvdata,
va, pa, len);
+ iommu_access_ops->iommu_clk_off(iommu_drvdata);
fail:
- mutex_unlock(&msm_iommu_lock);
+ iommu_access_ops->iommu_lock_release();
return ret;
}
@@ -464,16 +452,18 @@
struct msm_iommu_ctx_drvdata *ctx_drvdata;
int ret = -ENODEV;
- mutex_lock(&msm_iommu_lock);
+ iommu_access_ops->iommu_lock_acquire();
ret = get_drvdata(domain, &iommu_drvdata, &ctx_drvdata);
if (ret)
goto fail;
+ iommu_access_ops->iommu_clk_on(iommu_drvdata);
ret = msm_iommu_sec_ptbl_unmap(iommu_drvdata, ctx_drvdata,
va, len);
+ iommu_access_ops->iommu_clk_off(iommu_drvdata);
fail:
- mutex_unlock(&msm_iommu_lock);
+ iommu_access_ops->iommu_lock_release();
/* the IOMMU API requires us to return how many bytes were unmapped */
len = ret ? 0 : len;
@@ -488,15 +478,17 @@
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
- mutex_lock(&msm_iommu_lock);
+ iommu_access_ops->iommu_lock_acquire();
ret = get_drvdata(domain, &iommu_drvdata, &ctx_drvdata);
if (ret)
goto fail;
+ iommu_access_ops->iommu_clk_on(iommu_drvdata);
ret = msm_iommu_sec_ptbl_map_range(iommu_drvdata, ctx_drvdata,
va, sg, len);
+ iommu_access_ops->iommu_clk_off(iommu_drvdata);
fail:
- mutex_unlock(&msm_iommu_lock);
+ iommu_access_ops->iommu_lock_release();
return ret;
}
@@ -508,16 +500,18 @@
struct msm_iommu_ctx_drvdata *ctx_drvdata;
int ret;
- mutex_lock(&msm_iommu_lock);
+ iommu_access_ops->iommu_lock_acquire();
ret = get_drvdata(domain, &iommu_drvdata, &ctx_drvdata);
if (ret)
goto fail;
+ iommu_access_ops->iommu_clk_on(iommu_drvdata);
ret = msm_iommu_sec_ptbl_unmap(iommu_drvdata, ctx_drvdata, va, len);
+ iommu_access_ops->iommu_clk_off(iommu_drvdata);
fail:
- mutex_unlock(&msm_iommu_lock);
+ iommu_access_ops->iommu_lock_release();
return 0;
}
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index 202edc0..e88e574 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -61,6 +61,7 @@
#define WLED_MAX_CURR_MASK 0x19
#define WLED_OP_FDBCK_MASK 0x07
#define WLED_OP_FDBCK_BIT_SHFT 0x00
+#define WLED_OP_FDBCK_DEFAULT 0x00
#define WLED_MAX_LEVEL 4095
#define WLED_8_BIT_MASK 0xFF
@@ -90,6 +91,8 @@
#define FLASH_VREG_OK_FORCE(base) (base + 0x4F)
#define FLASH_ENABLE_CONTROL(base) (base + 0x46)
#define FLASH_LED_STROBE_CTRL(base) (base + 0x47)
+#define FLASH_LED_UNLOCK_SECURE(base) (base + 0xD0)
+#define FLASH_LED_TORCH(base) (base + 0xE4)
#define FLASH_MAX_LEVEL 0x4F
#define FLASH_NO_MASK 0x00
@@ -99,6 +102,7 @@
#define FLASH_HEADROOM_MASK 0x03
#define FLASH_SAFETY_TIMER_MASK 0x7F
#define FLASH_CURRENT_MASK 0xFF
+#define FLASH_MAX_CURRENT_MASK 0x7F
#define FLASH_TMR_MASK 0x03
#define FLASH_TMR_WATCHDOG 0x03
#define FLASH_TMR_SAFETY 0x00
@@ -117,17 +121,26 @@
#define FLASH_ENABLE_LED_1 0x20
#define FLASH_INIT_MASK 0xE0
-#define FLASH_STROBE_ALL 0xC0
-#define FLASH_STROBE_MASK 0xC0
+#define FLASH_STROBE_SW 0xC0
+#define FLASH_STROBE_HW 0xC4
+#define FLASH_STROBE_MASK 0xC7
#define FLASH_LED_0_OUTPUT 0x80
#define FLASH_LED_1_OUTPUT 0x40
#define FLASH_CURRENT_PRGM_MIN 1
#define FLASH_CURRENT_PRGM_SHIFT 1
+#define FLASH_CURRENT_MAX 0x4F
+#define FLASH_CURRENT_TORCH 0x0F
#define FLASH_DURATION_200ms 0x13
#define FLASH_CLAMP_200mA 0x0F
+#define FLASH_TORCH_MASK 0x03
+#define FLASH_LED_TORCH_ENABLE 0x00
+#define FLASH_LED_TORCH_DISABLE 0x03
+#define FLASH_UNLOCK_SECURE 0xA5
+#define FLASH_SECURE_MASK 0xFF
+
#define LED_TRIGGER_DEFAULT "none"
#define RGB_LED_SRC_SEL(base) (base + 0x45)
@@ -245,9 +258,9 @@
u8 cp_select;
u8 ctrl_delay_us;
u8 switch_freq;
+ u8 op_fdbck;
bool dig_mod_gen_en;
bool cs_out_en;
- bool op_fdbck;
};
/**
@@ -259,9 +272,11 @@
* @enable_module - enable address for particular flash
* @trigger_flash - trigger flash
* @startup_dly - startup delay for flash
+ * @strobe_type - select between sw and hw strobe
* @current_addr - address to write for current
* @second_addr - address of secondary flash to be written
* @safety_timer - enable safety timer or watchdog timer
+ * @torch_enable - enable flash LED torch mode
*/
struct flash_config_data {
u8 current_prgm;
@@ -271,9 +286,11 @@
u8 enable_module;
u8 trigger_flash;
u8 startup_dly;
+ u8 strobe_type;
u16 current_addr;
u16 second_addr;
bool safety_timer;
+ bool torch_enable;
};
/**
@@ -456,62 +473,176 @@
/* Set led current */
if (val > 0) {
- 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;
+ if (led->flash_cfg->torch_enable) {
+ rc = qpnp_led_masked_write(led,
+ FLASH_LED_UNLOCK_SECURE(led->base),
+ FLASH_SECURE_MASK, FLASH_UNLOCK_SECURE);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Secure reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ FLASH_LED_TORCH(led->base),
+ FLASH_TORCH_MASK, FLASH_LED_TORCH_ENABLE);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Torch reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ qpnp_led_masked_write(led, FLASH_MAX_CURR(led->base),
+ FLASH_CURRENT_MASK, FLASH_CURRENT_TORCH);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Max current reg write failed(%d)\n",
+ rc);
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ led->flash_cfg->current_addr,
+ FLASH_CURRENT_MASK, FLASH_CURRENT_TORCH);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Current reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ led->flash_cfg->second_addr,
+ FLASH_CURRENT_MASK, FLASH_CURRENT_TORCH);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "2nd Current reg write failed(%d)\n",
+ rc);
+ return rc;
+ }
+
+ 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;
+ }
+ } else {
+ rc = qpnp_led_masked_write(led,
+ FLASH_MAX_CURR(led->base),
+ FLASH_CURRENT_MASK, FLASH_CURRENT_MAX);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Max current reg write failed(%d)\n",
+ rc);
+ return rc;
+ }
+
+ /* Write 0x80 to MODULE_ENABLE before writing 0xE0
+ * in order to avoid reg value goes from 0x00 to
+ * 0xE0. This causes a hardware bug.
+ */
+ 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,
+ led->flash_cfg->current_addr,
+ FLASH_CURRENT_MASK,
+ led->flash_cfg->current_prgm);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Current reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ led->flash_cfg->second_addr,
+ FLASH_CURRENT_MASK,
+ led->flash_cfg->current_prgm);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "2nd Current reg write failed(%d)\n",
+ rc);
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ FLASH_CLAMP_CURR(led->base),
+ FLASH_CURRENT_MASK, FLASH_CURRENT_TORCH);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Clamp Current reg write failed(%d)\n",
+ rc);
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ FLASH_ENABLE_CONTROL(led->base),
+ FLASH_ENABLE_MASK, FLASH_ENABLE_ALL);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Enable reg write failed(%d)\n", rc);
+ return rc;
+ }
}
- rc = qpnp_led_masked_write(led, led->flash_cfg->current_addr,
- FLASH_CURRENT_MASK, led->flash_cfg->current_prgm);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Current reg write failed(%d)\n", rc);
- return rc;
- }
-
- rc = qpnp_led_masked_write(led, led->flash_cfg->second_addr,
- FLASH_CURRENT_MASK, led->flash_cfg->current_prgm);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Current reg write failed(%d)\n", rc);
- return rc;
- }
-
- rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
- FLASH_ENABLE_MASK,
- FLASH_ENABLE_ALL);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Enable reg write failed(%d)\n", rc);
- return rc;
- }
- rc = qpnp_led_masked_write(led,
- FLASH_LED_STROBE_CTRL(led->base),
- FLASH_STROBE_MASK, FLASH_STROBE_ALL);
-
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "LED %d flash write failed(%d)\n", led->id, rc);
- return rc;
- }
- rc = qpnp_led_masked_write(led, FLASH_VREG_OK_FORCE(led->base),
- FLASH_VREG_MASK, FLASH_HW_VREG_OK);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Vreg OK reg write failed(%d)\n", rc);
- return rc;
+ if (!led->flash_cfg->strobe_type) {
+ rc = qpnp_led_masked_write(led,
+ FLASH_LED_STROBE_CTRL(led->base),
+ FLASH_STROBE_MASK, FLASH_STROBE_SW);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "LED %d strobe reg write failed(%d)\n",
+ led->id, rc);
+ return rc;
+ }
+ } else {
+ rc = qpnp_led_masked_write(led,
+ FLASH_LED_STROBE_CTRL(led->base),
+ FLASH_STROBE_MASK, FLASH_STROBE_HW);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "LED %d strobe reg write failed(%d)\n",
+ led->id, rc);
+ return rc;
+ }
}
} else {
- rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
- FLASH_ENABLE_MASK,
- FLASH_DISABLE_ALL);
- if (rc) {
- dev_err(&led->spmi_dev->dev,
- "Enable reg write failed(%d)\n", rc);
- return rc;
+ if (led->flash_cfg->torch_enable) {
+ rc = qpnp_led_masked_write(led,
+ FLASH_LED_UNLOCK_SECURE(led->base),
+ FLASH_SECURE_MASK, FLASH_UNLOCK_SECURE);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Secure reg write failed(%d)\n", rc);
+ }
+
+ rc = qpnp_led_masked_write(led,
+ FLASH_LED_TORCH(led->base),
+ FLASH_TORCH_MASK, FLASH_LED_TORCH_DISABLE);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Torch reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_led_masked_write(led,
+ FLASH_SAFETY_TIMER(led->base),
+ FLASH_SAFETY_TIMER_MASK,
+ led->flash_cfg->duration);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Safety timer reg write failed(%d)\n",
+ rc);
+ return rc;
+ }
}
rc = qpnp_led_masked_write(led,
@@ -523,6 +654,15 @@
"LED %d flash write failed(%d)\n", led->id, rc);
return rc;
}
+
+ rc = qpnp_led_masked_write(led, FLASH_ENABLE_CONTROL(led->base),
+ FLASH_ENABLE_MASK,
+ FLASH_DISABLE_ALL);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Enable reg write failed(%d)\n", rc);
+ return rc;
+ }
}
qpnp_dump_regs(led, flash_debug_regs, ARRAY_SIZE(flash_debug_regs));
@@ -797,6 +937,67 @@
return 0;
}
+static ssize_t led_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct qpnp_led_data *led;
+ unsigned long state;
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ ssize_t ret = -EINVAL;
+
+ ret = kstrtoul(buf, 10, &state);
+ if (ret)
+ return ret;
+
+ led = container_of(led_cdev, struct qpnp_led_data, cdev);
+
+ /* '1' to enable torch mode; '0' to switch to flash mode */
+ if (state == 1)
+ led->flash_cfg->torch_enable = true;
+ else
+ led->flash_cfg->torch_enable = false;
+
+ return count;
+}
+
+static ssize_t led_strobe_type_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct qpnp_led_data *led;
+ unsigned long state;
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ ssize_t ret = -EINVAL;
+
+ ret = kstrtoul(buf, 10, &state);
+ if (ret)
+ return ret;
+
+ led = container_of(led_cdev, struct qpnp_led_data, cdev);
+
+ /* '0' for sw strobe; '1' for hw strobe */
+ if (state == 1)
+ led->flash_cfg->strobe_type = 1;
+ else
+ led->flash_cfg->strobe_type = 0;
+
+ return count;
+}
+
+static DEVICE_ATTR(led_mode, 0664, NULL, led_mode_store);
+static DEVICE_ATTR(strobe, 0664, NULL, led_strobe_type_store);
+
+static struct attribute *led_attrs[] = {
+ &dev_attr_led_mode.attr,
+ &dev_attr_strobe.attr,
+ NULL
+};
+
+static const struct attribute_group led_attr_group = {
+ .attrs = led_attrs,
+};
+
static int __devinit qpnp_flash_init(struct qpnp_led_data *led)
{
int rc;
@@ -890,7 +1091,7 @@
return rc;
}
- /* Set led current and enable module */
+ /* Set led current and disable module */
rc = qpnp_led_masked_write(led, led->flash_cfg->current_addr,
FLASH_CURRENT_MASK, led->flash_cfg->current_prgm);
if (rc) {
@@ -906,6 +1107,10 @@
"Enable reg write failed(%d)\n", rc);
return rc;
}
+
+ led->flash_cfg->torch_enable = false;
+ led->flash_cfg->strobe_type = 0;
+
/* dump flash registers */
qpnp_dump_regs(led, flash_debug_regs, ARRAY_SIZE(flash_debug_regs));
@@ -1099,6 +1304,13 @@
else if (rc != -EINVAL)
return rc;
+ led->wled_cfg->op_fdbck = WLED_OP_FDBCK_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,op-fdbck", &val);
+ if (!rc)
+ led->wled_cfg->op_fdbck = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
led->wled_cfg->switch_freq = WLED_SWITCH_FREQ_DEFAULT;
rc = of_property_read_u32(node, "qcom,switch-freq", &val);
if (!rc)
@@ -1112,9 +1324,6 @@
led->wled_cfg->cs_out_en =
of_property_read_bool(node, "qcom,cs-out-en");
- led->wled_cfg->op_fdbck =
- of_property_read_bool(node, "qcom,op-fdbck");
-
return 0;
}
@@ -1451,6 +1660,16 @@
led->id, rc);
goto fail_id_check;
}
+
+ if (led->id == QPNP_ID_FLASH1_LED0 ||
+ led->id == QPNP_ID_FLASH1_LED1) {
+ rc = sysfs_create_group(&led->cdev.dev->kobj,
+ &led_attr_group);
+ if (rc)
+ goto fail_id_check;
+
+ }
+
/* configure default state */
if (led->default_on) {
led->cdev.brightness = led->cdev.max_brightness;
@@ -1477,8 +1696,26 @@
struct qpnp_led_data *led_array = dev_get_drvdata(&spmi->dev);
int i, parsed_leds = led_array->num_leds;
- for (i = 0; i < parsed_leds; i++)
+ for (i = 0; i < parsed_leds; i++) {
led_classdev_unregister(&led_array[i].cdev);
+ switch (led_array[i].id) {
+ case QPNP_ID_WLED:
+ break;
+ case QPNP_ID_FLASH1_LED0:
+ case QPNP_ID_FLASH1_LED1:
+ sysfs_remove_group(&led_array[i].cdev.dev->kobj,
+ &led_attr_group);
+ break;
+ case QPNP_ID_RGB_RED:
+ case QPNP_ID_RGB_GREEN:
+ case QPNP_ID_RGB_BLUE:
+ default:
+ dev_err(&led_array[i].spmi_dev->dev,
+ "Invalid LED(%d)\n",
+ led_array[i].id);
+ return -EINVAL;
+ }
+ }
return 0;
}
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 2a0cde9..0fef315 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -1876,13 +1876,13 @@
if (dvbdemux->dmx.debugfs_demux_dir != NULL) {
debugfs_create_u32(
"total_processing_time",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
dvbdemux->dmx.debugfs_demux_dir,
&dvbdemux->total_process_time);
debugfs_create_u32(
"total_crc_time",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
dvbdemux->dmx.debugfs_demux_dir,
&dvbdemux->total_crc_time);
}
diff --git a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
index 92f7463..e8480f7 100644
--- a/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
+++ b/drivers/media/dvb/dvb-core/dvb_ringbuffer.c
@@ -5,7 +5,7 @@
* Copyright (C) 2003 Oliver Endriss
* Copyright (C) 2004 Andrew de Quincey
*
- * Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* based on code originally found in av7110.c & dvb_ci.c:
* Copyright (C) 1999-2003 Ralph Metzler
@@ -334,7 +334,10 @@
idx = (idx + curpktlen + DVB_RINGBUFFER_PKTHDRSIZE) % rbuf->size;
}
- consumed = (idx - rbuf->pread) % rbuf->size;
+ if (idx >= rbuf->pread)
+ consumed = idx - rbuf->pread;
+ else
+ consumed = rbuf->size - (rbuf->pread - idx);
while((dvb_ringbuffer_avail(rbuf) - consumed) > DVB_RINGBUFFER_PKTHDRSIZE) {
diff --git a/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c
index 3607f2e..cda36d9 100644
--- a/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c
+++ b/drivers/media/platform/msm/camera_v1/mercury/msm_mercury_platform.c
@@ -16,7 +16,6 @@
#include <mach/clk.h>
#include <mach/camera.h>
-#include <mach/msm_subsystem_map.h>
#include "msm_mercury_platform.h"
#include "msm_mercury_sync.h"
diff --git a/drivers/media/platform/msm/camera_v2/Kconfig b/drivers/media/platform/msm/camera_v2/Kconfig
index 269e538..d9552e2 100644
--- a/drivers/media/platform/msm/camera_v2/Kconfig
+++ b/drivers/media/platform/msm/camera_v2/Kconfig
@@ -64,6 +64,15 @@
based on cid which is mapped to a virtual channel
and datatype.
+config MSM_EEPROM
+ bool "Qualcomm MSM Camera ROM Interface for Calibration support"
+ depends on MSMB_CAMERA
+ ---help---
+ Enable support for ROM Interface for Calibration
+ Provides interface for reading the Claibration data.
+ and also provides support for writing data in case of FLASH ROM.
+ Currently supports I2C, CCI and SPI protocol
+
config MSM_ISPIF
bool "Qualcomm MSM Image Signal Processing interface support"
depends on MSMB_CAMERA
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
index ff86aae..447c752 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c
@@ -113,7 +113,8 @@
vfe_dev->subdev.sd.flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
v4l2_set_subdevdata(&vfe_dev->subdev.sd, vfe_dev);
platform_set_drvdata(pdev, &vfe_dev->subdev.sd);
- mutex_init(&vfe_dev->mutex);
+ mutex_init(&vfe_dev->realtime_mutex);
+ mutex_init(&vfe_dev->core_mutex);
spin_lock_init(&vfe_dev->tasklet_lock);
spin_lock_init(&vfe_dev->shared_data_lock);
media_entity_init(&vfe_dev->subdev.sd.entity, 0, NULL, 0);
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 cfbe29c..1b762ea 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -33,7 +33,7 @@
#define MAX_NUM_COMPOSITE_MASK 4
#define MAX_NUM_STATS_COMP_MASK 2
#define MAX_INIT_FRAME_DROP 31
-#define ISP_SUB(a) ((a > 0) ? a-1 : 0)
+#define ISP_Q2 (1 << 2)
#define VFE_PING_FLAG 0xFFFFFFFF
#define VFE_PONG_FLAG 0x0
@@ -183,6 +183,7 @@
struct msm_vfe_hardware_info {
int num_iommu_ctx;
+ int vfe_clk_idx;
struct msm_vfe_ops vfe_ops;
struct msm_vfe_axi_hardware_info *axi_hw_info;
struct msm_vfe_stats_hardware_info *stats_hw_info;
@@ -206,6 +207,7 @@
PAUSE,
START_PENDING,
STOP_PENDING,
+ STARTING,
STOPPING,
PAUSE_PENDING,
};
@@ -246,9 +248,16 @@
uint32_t burst_frame_count;/*number of sof before burst stop*/
uint8_t framedrop_update;
+ /*Bandwidth calculation info*/
+ uint32_t max_width;
+ /*Based on format plane size in Q2. e.g NV12 = 1.5*/
+ uint32_t format_factor;
+ uint32_t bandwidth;
+
/*Run time update variables*/
uint32_t runtime_init_frame_drop;
uint32_t runtime_burst_frame_count;/*number of sof before burst stop*/
+ uint32_t runtime_num_burst_capture;
uint8_t runtime_framedrop_update;
};
@@ -263,6 +272,8 @@
uint8_t pix_stream_count;
uint8_t raw_stream_count;
enum msm_vfe_inputmux input_mux;
+ uint32_t width;
+ long pixel_clock;
};
enum msm_wm_ub_cfg_type {
@@ -369,7 +380,8 @@
struct completion reset_complete;
struct completion halt_complete;
struct completion stream_config_complete;
- struct mutex mutex;
+ struct mutex realtime_mutex;
+ struct mutex core_mutex;
atomic_t irq_cnt;
uint8_t taskletq_idx;
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 b981653..31fa39e 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -39,42 +39,7 @@
(VFE32_STATS_BASE(idx) + 0x4 * \
(~(ping_pong >> (idx + VFE32_STATS_PING_PONG_OFFSET)) & 0x1))
-/*Temporary use fixed bus vectors in VFE */
-static struct msm_bus_vectors msm_vfe32_init_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VFE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
-};
-
-static struct msm_bus_vectors msm_vfe32_preview_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VFE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 1027648000,
- .ib = 1105920000,
- },
-};
-
-static struct msm_bus_paths msm_vfe32_bus_client_config[] = {
- {
- ARRAY_SIZE(msm_vfe32_init_vectors),
- msm_vfe32_init_vectors,
- },
- {
- ARRAY_SIZE(msm_vfe32_preview_vectors),
- msm_vfe32_preview_vectors,
- },
-};
-
-static struct msm_bus_scale_pdata msm_vfe32_bus_client_pdata = {
- msm_vfe32_bus_client_config,
- ARRAY_SIZE(msm_vfe32_bus_client_config),
- .name = "msm_camera_vfe",
-};
-
+#define VFE32_CLK_IDX 0
static struct msm_cam_clk_info msm_vfe32_clk_info[] = {
{"vfe_clk", 266667000},
{"vfe_pclk", -1},
@@ -84,15 +49,11 @@
static int msm_vfe32_init_hardware(struct vfe_device *vfe_dev)
{
int rc = -1;
-
- vfe_dev->bus_perf_client =
- msm_bus_scale_register_client(&msm_vfe32_bus_client_pdata);
- if (!vfe_dev->bus_perf_client) {
- pr_err("%s: Registration Failed!\n", __func__);
- vfe_dev->bus_perf_client = 0;
+ rc = msm_isp_init_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
+ if (rc < 0) {
+ pr_err("%s: Bandwidth registration Failed!\n", __func__);
goto bus_scale_register_failed;
}
- msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 1);
if (vfe_dev->fs_vfe) {
rc = regulator_enable(vfe_dev->fs_vfe);
@@ -131,8 +92,7 @@
clk_enable_failed:
regulator_disable(vfe_dev->fs_vfe);
fs_failed:
- msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
- msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+ msm_isp_deinit_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
bus_scale_register_failed:
return rc;
}
@@ -145,8 +105,7 @@
msm_cam_clk_enable(&vfe_dev->pdev->dev, msm_vfe32_clk_info,
vfe_dev->vfe_clk, ARRAY_SIZE(msm_vfe32_clk_info), 0);
regulator_disable(vfe_dev->fs_vfe);
- msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
- msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+ msm_isp_deinit_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
}
static void msm_vfe32_init_hardware_reg(struct vfe_device *vfe_dev)
@@ -1021,6 +980,7 @@
struct msm_vfe_hardware_info vfe32_hw_info = {
.num_iommu_ctx = 2,
+ .vfe_clk_idx = VFE32_CLK_IDX,
.vfe_ops = {
.irq_ops = {
.read_irq_status = msm_vfe32_read_irq_status,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index a786750..256d136 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -77,42 +77,7 @@
#define VFE40_BUS_BDG_QOS_CFG_6 0x000002DC
#define VFE40_BUS_BDG_QOS_CFG_7 0x000002E0
-/*Temporary use fixed bus vectors in VFE */
-static struct msm_bus_vectors msm_vfe40_init_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VFE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 0,
- .ib = 0,
- },
-};
-
-static struct msm_bus_vectors msm_vfe40_preview_vectors[] = {
- {
- .src = MSM_BUS_MASTER_VFE,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 2027648000U,
- .ib = 2805920000U,
- },
-};
-
-static struct msm_bus_paths msm_vfe40_bus_client_config[] = {
- {
- ARRAY_SIZE(msm_vfe40_init_vectors),
- msm_vfe40_init_vectors,
- },
- {
- ARRAY_SIZE(msm_vfe40_preview_vectors),
- msm_vfe40_preview_vectors,
- },
-};
-
-static struct msm_bus_scale_pdata msm_vfe40_bus_client_pdata = {
- msm_vfe40_bus_client_config,
- ARRAY_SIZE(msm_vfe40_bus_client_config),
- .name = "msm_camera_vfe",
-};
-
+#define VFE40_CLK_IDX 1
static struct msm_cam_clk_info msm_vfe40_clk_info[] = {
{"camss_top_ahb_clk", -1},
{"vfe_clk_src", 266670000},
@@ -223,16 +188,11 @@
static int msm_vfe40_init_hardware(struct vfe_device *vfe_dev)
{
int rc = -1;
-
- vfe_dev->bus_perf_client =
- msm_bus_scale_register_client(&msm_vfe40_bus_client_pdata);
- if (!vfe_dev->bus_perf_client) {
- pr_err("%s: Registration Failed!\n", __func__);
- vfe_dev->bus_perf_client = 0;
+ rc = msm_isp_init_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
+ if (rc < 0) {
+ pr_err("%s: Bandwidth registration Failed!\n", __func__);
goto bus_scale_register_failed;
}
- msm_bus_scale_client_update_request(
- vfe_dev->bus_perf_client, 1);
if (vfe_dev->fs_vfe) {
rc = regulator_enable(vfe_dev->fs_vfe);
@@ -280,8 +240,7 @@
clk_enable_failed:
regulator_disable(vfe_dev->fs_vfe);
fs_failed:
- msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
- msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+ msm_isp_deinit_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
bus_scale_register_failed:
return rc;
}
@@ -295,8 +254,7 @@
msm_cam_clk_enable(&vfe_dev->pdev->dev, msm_vfe40_clk_info,
vfe_dev->vfe_clk, ARRAY_SIZE(msm_vfe40_clk_info), 0);
regulator_disable(vfe_dev->fs_vfe);
- msm_bus_scale_client_update_request(vfe_dev->bus_perf_client, 0);
- msm_bus_scale_unregister_client(vfe_dev->bus_perf_client);
+ msm_isp_deinit_bandwidth_mgr(ISP_VFE0 + vfe_dev->pdev->id);
}
static void msm_vfe40_init_hardware_reg(struct vfe_device *vfe_dev)
@@ -1288,6 +1246,7 @@
struct msm_vfe_hardware_info vfe40_hw_info = {
.num_iommu_ctx = 1,
+ .vfe_clk_idx = VFE40_CLK_IDX,
.vfe_ops = {
.irq_ops = {
.read_irq_status = msm_vfe40_read_irq_status,
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 f1bfd68..477985d 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
@@ -18,6 +18,8 @@
((src < RDI_INTF_0) ? VFE_PIX_0 : \
(VFE_RAW_0 + src - RDI_INTF_0))
+#define HANDLE_TO_IDX(handle) (handle & 0xFF)
+
int msm_isp_axi_create_stream(
struct msm_vfe_axi_shared_data *axi_data,
struct msm_vfe_axi_stream_request_cmd *stream_cfg_cmd)
@@ -67,7 +69,7 @@
int rc = -1, i;
struct msm_vfe_axi_stream *stream_info =
&axi_data->stream_info[
- (stream_cfg_cmd->axi_stream_handle & 0xFF)];
+ HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
switch (stream_cfg_cmd->output_format) {
case V4L2_PIX_FMT_SBGGR8:
@@ -95,12 +97,14 @@
case V4L2_PIX_FMT_QGRBG12:
case V4L2_PIX_FMT_QRGGB12:
stream_info->num_planes = 1;
+ stream_info->format_factor = ISP_Q2;
break;
case V4L2_PIX_FMT_NV12:
case V4L2_PIX_FMT_NV21:
case V4L2_PIX_FMT_NV16:
case V4L2_PIX_FMT_NV61:
stream_info->num_planes = 2;
+ stream_info->format_factor = 1.5 * ISP_Q2;
break;
/*TD: Add more image format*/
default:
@@ -131,9 +135,12 @@
return rc;
}
- for (i = 0; i < stream_info->num_planes; i++)
+ for (i = 0; i < stream_info->num_planes; i++) {
stream_info->plane_offset[i] =
stream_cfg_cmd->plane_cfg[i].plane_addr_offset;
+ stream_info->max_width = max(stream_info->max_width,
+ stream_cfg_cmd->plane_cfg[i].output_width);
+ }
stream_info->stream_src = stream_cfg_cmd->stream_src;
stream_info->frame_based = stream_cfg_cmd->frame_base;
@@ -209,7 +216,7 @@
int i, j;
struct msm_vfe_axi_stream *stream_info =
&axi_data->stream_info[
- (stream_cfg_cmd->axi_stream_handle & 0xFF)];
+ HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
for (i = 0; i < stream_info->num_planes; i++) {
for (j = 0; j < axi_data->hw_info->num_wm; j++) {
@@ -245,7 +252,7 @@
uint8_t comp_mask = 0;
struct msm_vfe_axi_stream *stream_info =
&axi_data->stream_info[
- (stream_cfg_cmd->axi_stream_handle & 0xFF)];
+ HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
for (i = 0; i < stream_info->num_planes; i++)
comp_mask |= 1 << stream_info->wm[i];
@@ -285,7 +292,7 @@
for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
stream_info = &axi_data->stream_info[
- (stream_cfg_cmd->stream_handle[i] & 0xFF)];
+ HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
if (stream_info->state != valid_state) {
pr_err("%s: Invalid stream state\n", __func__);
rc = -EINVAL;
@@ -344,6 +351,8 @@
stream_info->runtime_init_frame_drop = stream_info->init_frame_drop;
stream_info->runtime_burst_frame_count =
stream_info->burst_frame_count;
+ stream_info->runtime_num_burst_capture =
+ stream_info->num_burst_capture;
stream_info->runtime_framedrop_update = stream_info->framedrop_update;
vfe_dev->hw_info->vfe_ops.axi_ops.cfg_framedrop(vfe_dev, stream_info);
}
@@ -411,7 +420,7 @@
{
struct msm_vfe_axi_stream *stream_info =
&axi_data->stream_info[
- (stream_cfg_cmd->axi_stream_handle & 0xFF)];
+ HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
uint32_t framedrop_period = msm_isp_get_framedrop_period(
stream_cfg_cmd->frame_skip_pattern);
@@ -443,6 +452,23 @@
}
}
+void msm_isp_calculate_bandwidth(
+ struct msm_vfe_axi_shared_data *axi_data,
+ struct msm_vfe_axi_stream *stream_info)
+{
+ if (stream_info->stream_src < RDI_INTF_0) {
+ stream_info->bandwidth =
+ (axi_data->src_info[VFE_PIX_0].pixel_clock /
+ axi_data->src_info[VFE_PIX_0].width) *
+ stream_info->max_width;
+ stream_info->bandwidth = stream_info->bandwidth *
+ stream_info->format_factor / ISP_Q2;
+ } else {
+ int rdi = SRC_TO_INTF(stream_info->stream_src);
+ stream_info->bandwidth = axi_data->src_info[rdi].pixel_clock;
+ }
+}
+
int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg)
{
int rc = 0, i;
@@ -461,13 +487,12 @@
if (rc) {
pr_err("%s: Request validation failed\n", __func__);
msm_isp_axi_destroy_stream(&vfe_dev->axi_data,
- (stream_cfg_cmd->axi_stream_handle & 0xFF));
+ HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle));
return rc;
}
- stream_info =
- &vfe_dev->axi_data.
- stream_info[(stream_cfg_cmd->axi_stream_handle & 0xFF)];
+ stream_info = &vfe_dev->axi_data.
+ stream_info[HANDLE_TO_IDX(stream_cfg_cmd->axi_stream_handle)];
msm_isp_axi_reserve_wm(&vfe_dev->axi_data, stream_cfg_cmd);
if (stream_cfg_cmd->stream_src == CAMIF_RAW ||
@@ -504,7 +529,7 @@
struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
struct msm_vfe_axi_stream *stream_info =
&axi_data->stream_info[
- (stream_release_cmd->stream_handle & 0xFF)];
+ HANDLE_TO_IDX(stream_release_cmd->stream_handle)];
struct msm_vfe_axi_stream_cfg_cmd stream_cfg;
if (stream_info->state == AVALIABLE) {
@@ -538,79 +563,70 @@
msm_isp_axi_free_wm(axi_data, stream_info);
msm_isp_axi_destroy_stream(&vfe_dev->axi_data,
- (stream_release_cmd->stream_handle & 0xFF));
+ HANDLE_TO_IDX(stream_release_cmd->stream_handle));
return rc;
}
-void msm_isp_axi_stream_enable_cfg(
+static void msm_isp_axi_stream_enable_cfg(
struct vfe_device *vfe_dev,
- struct msm_vfe_axi_stream *stream_info,
- uint32_t *wm_reload_mask)
+ struct msm_vfe_axi_stream *stream_info)
{
int i;
struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
if (stream_info->state == INACTIVE)
return;
for (i = 0; i < stream_info->num_planes; i++) {
- /*TD: Frame base command*/
if (stream_info->state == START_PENDING)
vfe_dev->hw_info->vfe_ops.axi_ops.
enable_wm(vfe_dev, stream_info->wm[i], 1);
else
vfe_dev->hw_info->vfe_ops.axi_ops.
enable_wm(vfe_dev, stream_info->wm[i], 0);
-
- *wm_reload_mask |= (1 << stream_info->wm[i]);
}
- if (stream_info->state == START_PENDING) {
+ if (stream_info->state == START_PENDING)
axi_data->num_active_stream++;
- stream_info->state = ACTIVE;
- } else {
+ else
axi_data->num_active_stream--;
- stream_info->state = INACTIVE;
- }
}
void msm_isp_axi_stream_update(struct vfe_device *vfe_dev)
{
int i;
struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
- uint32_t wm_reload_mask = 0x0;
for (i = 0; i < MAX_NUM_STREAM; i++) {
if (axi_data->stream_info[i].state == START_PENDING ||
axi_data->stream_info[i].state ==
STOP_PENDING) {
msm_isp_axi_stream_enable_cfg(
- vfe_dev, &axi_data->stream_info[i],
- &wm_reload_mask);
- if (axi_data->stream_info[i].state == STOP_PENDING)
- axi_data->stream_info[i].state = STOPPING;
+ vfe_dev, &axi_data->stream_info[i]);
+ axi_data->stream_info[i].state =
+ axi_data->stream_info[i].state ==
+ START_PENDING ? STARTING : STOPPING;
+ } else if (axi_data->stream_info[i].state == STARTING ||
+ axi_data->stream_info[i].state == STOPPING) {
+ axi_data->stream_info[i].state =
+ axi_data->stream_info[i].state == STARTING ?
+ ACTIVE : INACTIVE;
}
}
- /*Reload AXI*/
- vfe_dev->hw_info->vfe_ops.axi_ops.
- reload_wm(vfe_dev, wm_reload_mask);
- if (vfe_dev->axi_data.stream_update) {
- vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev);
- ISP_DBG("%s: send update complete\n", __func__);
- vfe_dev->axi_data.stream_update = 0;
+ vfe_dev->axi_data.stream_update--;
+ if (vfe_dev->axi_data.stream_update == 0)
complete(&vfe_dev->stream_config_complete);
- }
}
static void msm_isp_cfg_pong_address(struct vfe_device *vfe_dev,
struct msm_vfe_axi_stream *stream_info)
{
int i;
- struct msm_isp_buffer *buf = stream_info->buf[1];
+ struct msm_isp_buffer *buf = stream_info->buf[0];
for (i = 0; i < stream_info->num_planes; i++)
vfe_dev->hw_info->vfe_ops.axi_ops.update_ping_pong_addr(
vfe_dev, stream_info->wm[i],
- VFE_PING_FLAG, buf->mapped_info[i].paddr +
+ VFE_PONG_FLAG, buf->mapped_info[i].paddr +
stream_info->plane_offset[i]);
- stream_info->buf[0] = buf;
+ stream_info->buf[1] = buf;
}
static void msm_isp_get_done_buf(struct vfe_device *vfe_dev,
@@ -636,7 +652,7 @@
struct msm_isp_buffer *buf = NULL;
uint32_t pingpong_bit = 0;
uint32_t bufq_handle = stream_info->bufq_handle;
- uint32_t stream_idx = stream_info->stream_handle & 0xFF;
+ uint32_t stream_idx = HANDLE_TO_IDX(stream_info->stream_handle);
rc = vfe_dev->buf_mgr->ops->get_buf(vfe_dev->buf_mgr,
vfe_dev->pdev->id, bufq_handle, &buf);
@@ -673,7 +689,7 @@
{
int rc;
struct msm_isp_event_data buf_event;
- uint32_t stream_idx = stream_info->stream_handle & 0xFF;
+ 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;
@@ -724,7 +740,7 @@
for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
stream_info =
&axi_data->stream_info[
- (stream_cfg_cmd->stream_handle[i] & 0xFF)];
+ HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
if (stream_info->stream_src < RDI_INTF_0)
pix_stream_cnt++;
if (stream_info->stream_src == PIX_ENCODER ||
@@ -793,16 +809,193 @@
ISP_DBG("%s\n", line_str);
}
-int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg)
+/*Factor in Q2 format*/
+#define ISP_DEFAULT_FORMAT_FACTOR 6
+#define ISP_BUS_UTILIZATION_FACTOR 6
+static int msm_isp_update_stream_bandwidth(struct vfe_device *vfe_dev)
{
- int rc = 0, i;
- struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd = arg;
+ int i, rc = 0;
+ struct msm_vfe_axi_stream *stream_info;
+ struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+ uint32_t total_pix_bandwidth = 0, total_rdi_bandwidth = 0;
+ uint32_t num_pix_streams = 0;
+ uint64_t total_bandwidth = 0;
+
+ for (i = 0; i < MAX_NUM_STREAM; i++) {
+ stream_info = &axi_data->stream_info[i];
+ if (stream_info->state == ACTIVE ||
+ stream_info->state == START_PENDING) {
+ if (stream_info->stream_src < RDI_INTF_0) {
+ total_pix_bandwidth += stream_info->bandwidth;
+ num_pix_streams++;
+ } else {
+ total_rdi_bandwidth += stream_info->bandwidth;
+ }
+ }
+ }
+ if (num_pix_streams > 0)
+ total_pix_bandwidth = total_pix_bandwidth /
+ num_pix_streams * (num_pix_streams - 1) +
+ axi_data->src_info[VFE_PIX_0].pixel_clock *
+ ISP_DEFAULT_FORMAT_FACTOR / ISP_Q2;
+ total_bandwidth = total_pix_bandwidth + total_rdi_bandwidth;
+
+ rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
+ total_bandwidth, total_bandwidth *
+ ISP_BUS_UTILIZATION_FACTOR / ISP_Q2);
+ if (rc < 0)
+ pr_err("%s: update failed\n", __func__);
+
+ return rc;
+}
+
+static int msm_isp_axi_wait_for_cfg_done(struct vfe_device *vfe_dev)
+{
+ int rc;
+ unsigned long flags;
+ spin_lock_irqsave(&vfe_dev->shared_data_lock, flags);
+ init_completion(&vfe_dev->stream_config_complete);
+ vfe_dev->axi_data.stream_update = 2;
+ spin_unlock_irqrestore(&vfe_dev->shared_data_lock, flags);
+ rc = wait_for_completion_interruptible_timeout(
+ &vfe_dev->stream_config_complete,
+ msecs_to_jiffies(500));
+ if (rc == 0) {
+ pr_err("%s: wait timeout\n", __func__);
+ rc = -1;
+ } else {
+ rc = 0;
+ }
+ return rc;
+}
+
+static int msm_isp_init_stream_ping_pong_reg(
+ struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream *stream_info)
+{
+ int rc = 0;
+ /*Set address for both PING & PONG register */
+ rc = msm_isp_cfg_ping_pong_address(vfe_dev,
+ stream_info, VFE_PING_FLAG);
+ if (rc < 0) {
+ pr_err("%s: No free buffer for ping\n",
+ __func__);
+ return rc;
+ }
+
+ /* For burst stream of one capture, only one buffer
+ * is allocated. Duplicate ping buffer address to pong
+ * buffer to ensure hardware write to a valid address
+ */
+ if (stream_info->stream_type == BURST_STREAM &&
+ stream_info->runtime_num_burst_capture <= 1) {
+ msm_isp_cfg_pong_address(vfe_dev, stream_info);
+ } else {
+ rc = msm_isp_cfg_ping_pong_address(vfe_dev,
+ stream_info, VFE_PONG_FLAG);
+ if (rc < 0) {
+ pr_err("%s: No free buffer for pong\n",
+ __func__);
+ return rc;
+ }
+ }
+ return rc;
+}
+
+static void msm_isp_get_stream_wm_mask(
+ struct msm_vfe_axi_stream *stream_info,
+ uint32_t *wm_reload_mask)
+{
+ int i;
+ for (i = 0; i < stream_info->num_planes; i++)
+ *wm_reload_mask |= (1 << stream_info->wm[i]);
+}
+
+static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd,
+ enum msm_isp_camif_update_state camif_update)
+{
+ int i, rc = 0;
+ uint8_t src_state, wait_for_complete = 0;
uint32_t wm_reload_mask = 0x0;
struct msm_vfe_axi_stream *stream_info;
struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
- uint8_t src_state;
+ for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+ stream_info = &axi_data->stream_info[
+ HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
+ src_state = axi_data->src_info[
+ SRC_TO_INTF(stream_info->stream_src)].active;
+
+ msm_isp_calculate_bandwidth(axi_data, stream_info);
+ msm_isp_reset_framedrop(vfe_dev, stream_info);
+ msm_isp_get_stream_wm_mask(stream_info, &wm_reload_mask);
+ rc = msm_isp_init_stream_ping_pong_reg(vfe_dev, stream_info);
+ if (rc < 0) {
+ pr_err("%s: No buffer for stream%d\n", __func__,
+ HANDLE_TO_IDX(
+ stream_cfg_cmd->stream_handle[i]));
+ return rc;
+ }
+
+ stream_info->state = START_PENDING;
+ if (src_state) {
+ wait_for_complete = 1;
+ } else {
+ if (vfe_dev->dump_reg)
+ msm_camera_io_dump_2(vfe_dev->vfe_base, 0x900);
+
+ /*Configure AXI start bits to start immediately*/
+ msm_isp_axi_stream_enable_cfg(vfe_dev, stream_info);
+ stream_info->state = ACTIVE;
+ }
+ }
+ msm_isp_update_stream_bandwidth(vfe_dev);
+ vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev, wm_reload_mask);
+ vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev);
+
+ if (camif_update == ENABLE_CAMIF)
+ vfe_dev->hw_info->vfe_ops.core_ops.
+ update_camif_state(vfe_dev, camif_update);
+
+ if (wait_for_complete)
+ rc = msm_isp_axi_wait_for_cfg_done(vfe_dev);
+
+ return rc;
+}
+
+static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev,
+ struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd,
+ enum msm_isp_camif_update_state camif_update)
+{
+ int i, rc = 0;
+ struct msm_vfe_axi_stream *stream_info;
+ struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
+ for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+ stream_info = &axi_data->stream_info[
+ HANDLE_TO_IDX(stream_cfg_cmd->stream_handle[i])];
+ stream_info->state = STOP_PENDING;
+ }
+
+ rc = msm_isp_axi_wait_for_cfg_done(vfe_dev);
+ if (rc < 0) {
+ pr_err("%s: wait for config done failed\n", __func__);
+ return rc;
+ }
+ msm_isp_update_stream_bandwidth(vfe_dev);
+ if (camif_update == DISABLE_CAMIF)
+ vfe_dev->hw_info->vfe_ops.core_ops.
+ update_camif_state(vfe_dev, DISABLE_CAMIF);
+ return rc;
+}
+
+
+int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg)
+{
+ int rc = 0;
+ struct msm_vfe_axi_stream_cfg_cmd *stream_cfg_cmd = arg;
+ struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
enum msm_isp_camif_update_state camif_update;
- uint8_t wait_for_complete = 0;
+
rc = msm_isp_axi_check_stream_state(vfe_dev, stream_cfg_cmd);
if (rc < 0) {
pr_err("%s: Invalid stream state\n", __func__);
@@ -813,104 +1006,18 @@
/*Configure UB*/
vfe_dev->hw_info->vfe_ops.axi_ops.cfg_ub(vfe_dev);
}
-
camif_update =
msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
- if (camif_update == DISABLE_CAMIF)
- vfe_dev->hw_info->vfe_ops.core_ops.
- update_camif_state(vfe_dev, DISABLE_CAMIF);
+ if (stream_cfg_cmd->cmd == START_STREAM)
+ rc = msm_isp_start_axi_stream(
+ vfe_dev, stream_cfg_cmd, camif_update);
+ else
+ rc = msm_isp_stop_axi_stream(
+ vfe_dev, stream_cfg_cmd, camif_update);
- /*
- * Stream start either immediately or at reg update
- * Depends on whether the stream src is active
- * If source is on, start and stop have to be done during reg update
- * If source is off, start can happen immediately or during reg update
- * stop has to be done immediately.
- */
- for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
- stream_info =
- &axi_data->stream_info[
- (stream_cfg_cmd->stream_handle[i] & 0xFF)];
-
- if (stream_info->stream_src < RDI_INTF_0)
- src_state = axi_data->src_info[0].active;
- else
- src_state = axi_data->src_info[
- (stream_info->stream_src - RDI_INTF_0)].active;
-
- stream_info->state = (stream_cfg_cmd->cmd == START_STREAM) ?
- START_PENDING : STOP_PENDING;
-
- if (stream_cfg_cmd->cmd == START_STREAM) {
- /*Configure framedrop*/
- msm_isp_reset_framedrop(vfe_dev, stream_info);
-
- /*Set address for both PING & PONG register */
- rc = msm_isp_cfg_ping_pong_address(vfe_dev,
- stream_info, VFE_PONG_FLAG);
- if (rc < 0) {
- pr_err("%s: No buffer for start stream\n",
- __func__);
- return rc;
- }
- /* For burst stream of one capture, only one buffer
- * is allocated. Duplicate ping buffer address to pong
- * buffer to ensure hardware write to a valid address
- */
- if (stream_info->stream_type == BURST_STREAM &&
- stream_info->num_burst_capture <= 1) {
- msm_isp_cfg_pong_address(vfe_dev, stream_info);
- } else {
- rc = msm_isp_cfg_ping_pong_address(vfe_dev,
- stream_info, VFE_PING_FLAG);
- }
- }
- if (src_state && camif_update != DISABLE_CAMIF) {
- /*On the fly stream start/stop */
- wait_for_complete = 1;
- } else {
- if (vfe_dev->dump_reg &&
- stream_cfg_cmd->cmd == START_STREAM)
- msm_camera_io_dump_2(vfe_dev->vfe_base, 0x900);
- /*Configure AXI start bits to start immediately*/
- msm_isp_axi_stream_enable_cfg(
- vfe_dev, stream_info, &wm_reload_mask);
- }
- }
- if (!wait_for_complete) {
- /*Reload AXI*/
- if (stream_cfg_cmd->cmd == START_STREAM)
- vfe_dev->hw_info->vfe_ops.axi_ops.
- reload_wm(vfe_dev, wm_reload_mask);
-
- vfe_dev->hw_info->vfe_ops.core_ops.
- reg_update(vfe_dev);
-
- if (camif_update == ENABLE_CAMIF)
- vfe_dev->hw_info->vfe_ops.core_ops.
- update_camif_state(vfe_dev, camif_update);
- } else {
- unsigned long flags;
- spin_lock_irqsave(&vfe_dev->shared_data_lock, flags);
- init_completion(&vfe_dev->stream_config_complete);
- axi_data->stream_update = 1;
- spin_unlock_irqrestore(&vfe_dev->shared_data_lock, flags);
- /*Reload AXI*/
- if (stream_cfg_cmd->cmd == START_STREAM)
- vfe_dev->hw_info->vfe_ops.axi_ops.
- reload_wm(vfe_dev, wm_reload_mask);
- vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev);
- rc = wait_for_completion_interruptible_timeout(
- &vfe_dev->stream_config_complete,
- msecs_to_jiffies(500));
- if (rc == 0) {
- pr_err("%s: wait timeout\n", __func__);
- rc = -1;
- } else {
- rc = 0;
- }
- }
+ if (rc < 0)
+ pr_err("%s: start/stop stream failed\n", __func__);
return rc;
}
@@ -921,7 +1028,7 @@
struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
struct msm_vfe_axi_stream_update_cmd *update_cmd = arg;
stream_info = &axi_data->stream_info[
- (update_cmd->stream_handle & 0xFF)];
+ HANDLE_TO_IDX(update_cmd->stream_handle)];
if (stream_info->state != ACTIVE && stream_info->state != INACTIVE) {
pr_err("%s: Invalid stream state\n", __func__);
return -EINVAL;
@@ -984,18 +1091,25 @@
pr_err("%s: Invalid handle for composite irq\n",
__func__);
} else {
- stream_idx = comp_info->stream_handle & 0xFF;
+ stream_idx =
+ HANDLE_TO_IDX(comp_info->stream_handle);
stream_info =
&axi_data->stream_info[stream_idx];
ISP_DBG("%s: stream%d frame id: 0x%x\n",
__func__,
stream_idx, stream_info->frame_id);
stream_info->frame_id++;
+
+ if (stream_info->stream_type == BURST_STREAM)
+ stream_info->
+ runtime_num_burst_capture--;
+
msm_isp_get_done_buf(vfe_dev, stream_info,
pingpong_status, &done_buf);
if (stream_info->stream_type ==
CONTINUOUS_STREAM ||
- stream_info->num_burst_capture > 1) {
+ stream_info->
+ runtime_num_burst_capture > 1) {
rc = msm_isp_cfg_ping_pong_address(
vfe_dev, stream_info,
pingpong_status);
@@ -1015,16 +1129,20 @@
__func__);
continue;
}
- stream_idx = axi_data->free_wm[i] & 0xFF;
+ stream_idx = HANDLE_TO_IDX(axi_data->free_wm[i]);
stream_info = &axi_data->stream_info[stream_idx];
ISP_DBG("%s: stream%d frame id: 0x%x\n",
__func__,
stream_idx, stream_info->frame_id);
stream_info->frame_id++;
+
+ if (stream_info->stream_type == BURST_STREAM)
+ stream_info->runtime_num_burst_capture--;
+
msm_isp_get_done_buf(vfe_dev, stream_info,
pingpong_status, &done_buf);
if (stream_info->stream_type == CONTINUOUS_STREAM ||
- stream_info->num_burst_capture > 1) {
+ stream_info->runtime_num_burst_capture > 1) {
rc = msm_isp_cfg_ping_pong_address(vfe_dev,
stream_info, pingpong_status);
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
index ba845bc..f592a60 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
@@ -46,10 +46,6 @@
int msm_isp_release_axi_stream(struct vfe_device *vfe_dev, void *arg);
int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg);
-void msm_isp_axi_stream_enable_cfg(struct vfe_device *vfe_dev,
- struct msm_vfe_axi_stream *stream_info,
- uint32_t *wm_reload_mask);
-
void msm_isp_axi_stream_update(struct vfe_device *vfe_dev);
void msm_isp_update_framedrop_reg(struct vfe_device *vfe_dev);
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 ae89500..9fd87f3 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
@@ -9,6 +9,7 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
+#include <linux/mutex.h>
#include <linux/io.h>
#include <media/v4l2-subdev.h>
@@ -19,6 +20,139 @@
#include "msm_camera_io_util.h"
#define MAX_ISP_V4l2_EVENTS 100
+static DEFINE_MUTEX(bandwidth_mgr_mutex);
+static struct msm_isp_bandwidth_mgr isp_bandwidth_mgr;
+
+#define MSM_ISP_MIN_AB 300000000
+#define MSM_ISP_MIN_IB 450000000
+
+static struct msm_bus_vectors msm_isp_init_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+static struct msm_bus_vectors msm_isp_ping_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = MSM_ISP_MIN_AB,
+ .ib = MSM_ISP_MIN_IB,
+ },
+};
+
+static struct msm_bus_vectors msm_isp_pong_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = MSM_ISP_MIN_AB,
+ .ib = MSM_ISP_MIN_IB,
+ },
+};
+
+static struct msm_bus_paths msm_isp_bus_client_config[] = {
+ {
+ ARRAY_SIZE(msm_isp_init_vectors),
+ msm_isp_init_vectors,
+ },
+ {
+ ARRAY_SIZE(msm_isp_ping_vectors),
+ msm_isp_ping_vectors,
+ },
+ {
+ ARRAY_SIZE(msm_isp_pong_vectors),
+ msm_isp_pong_vectors,
+ },
+};
+
+static struct msm_bus_scale_pdata msm_isp_bus_client_pdata = {
+ msm_isp_bus_client_config,
+ ARRAY_SIZE(msm_isp_bus_client_config),
+ .name = "msm_camera_isp",
+};
+
+int msm_isp_init_bandwidth_mgr(enum msm_isp_hw_client client)
+{
+ int rc = 0;
+ mutex_lock(&bandwidth_mgr_mutex);
+ isp_bandwidth_mgr.client_info[client].active = 1;
+ if (isp_bandwidth_mgr.use_count++) {
+ mutex_unlock(&bandwidth_mgr_mutex);
+ return rc;
+ }
+ isp_bandwidth_mgr.bus_client =
+ msm_bus_scale_register_client(&msm_isp_bus_client_pdata);
+ if (!isp_bandwidth_mgr.bus_client) {
+ pr_err("%s: client register failed\n", __func__);
+ mutex_unlock(&bandwidth_mgr_mutex);
+ return -EINVAL;
+ }
+
+ isp_bandwidth_mgr.bus_vector_active_idx = 1;
+ msm_bus_scale_client_update_request(
+ isp_bandwidth_mgr.bus_client,
+ isp_bandwidth_mgr.bus_vector_active_idx);
+
+ mutex_unlock(&bandwidth_mgr_mutex);
+ return 0;
+}
+
+int msm_isp_update_bandwidth(enum msm_isp_hw_client client,
+ uint64_t ab, uint64_t ib)
+{
+ int i;
+ struct msm_bus_paths *path;
+ mutex_lock(&bandwidth_mgr_mutex);
+ if (!isp_bandwidth_mgr.use_count ||
+ !isp_bandwidth_mgr.bus_client) {
+ pr_err("%s: bandwidth manager inactive\n", __func__);
+ return -EINVAL;
+ }
+
+ isp_bandwidth_mgr.client_info[client].ab = ab;
+ isp_bandwidth_mgr.client_info[client].ib = ib;
+ ALT_VECTOR_IDX(isp_bandwidth_mgr.bus_vector_active_idx);
+ path =
+ &(msm_isp_bus_client_pdata.usecase[
+ isp_bandwidth_mgr.bus_vector_active_idx]);
+ path->vectors[0].ab = MSM_ISP_MIN_AB;
+ path->vectors[0].ib = MSM_ISP_MIN_IB;
+ for (i = 0; i < MAX_ISP_CLIENT; i++) {
+ if (isp_bandwidth_mgr.client_info[client].active) {
+ path->vectors[0].ab +=
+ isp_bandwidth_mgr.client_info[i].ab;
+ path->vectors[0].ib +=
+ isp_bandwidth_mgr.client_info[i].ib;
+ }
+ }
+ msm_bus_scale_client_update_request(isp_bandwidth_mgr.bus_client,
+ isp_bandwidth_mgr.bus_vector_active_idx);
+ mutex_unlock(&bandwidth_mgr_mutex);
+ return 0;
+}
+
+void msm_isp_deinit_bandwidth_mgr(enum msm_isp_hw_client client)
+{
+ mutex_lock(&bandwidth_mgr_mutex);
+ memset(&isp_bandwidth_mgr.client_info[client], 0,
+ sizeof(struct msm_isp_bandwidth_info));
+ if (--isp_bandwidth_mgr.use_count) {
+ mutex_unlock(&bandwidth_mgr_mutex);
+ return;
+ }
+
+ if (!isp_bandwidth_mgr.bus_client)
+ return;
+
+ msm_bus_scale_client_update_request(
+ isp_bandwidth_mgr.bus_client, 0);
+ msm_bus_scale_unregister_client(isp_bandwidth_mgr.bus_client);
+ isp_bandwidth_mgr.bus_client = 0;
+ mutex_unlock(&bandwidth_mgr_mutex);
+}
static inline void msm_isp_get_timestamp(struct msm_isp_timestamp *time_stamp)
{
@@ -68,28 +202,67 @@
return rc;
}
-int msm_isp_cfg_pix(struct vfe_device *vfe_dev,
- struct msm_vfe_pix_cfg *pix_cfg)
+static int msm_isp_set_clk_rate(struct vfe_device *vfe_dev, uint32_t rate)
{
int rc = 0;
- /*TD Validate config info
- * should check if all streams are off */
+ int clk_idx = vfe_dev->hw_info->vfe_clk_idx;
+ long round_rate =
+ clk_round_rate(vfe_dev->vfe_clk[clk_idx], rate);
+ if (round_rate < 0) {
+ pr_err("%s: Invalid vfe clock rate\n", __func__);
+ return round_rate;
+ }
- vfe_dev->axi_data.src_info[VFE_PIX_0].input_mux = pix_cfg->input_mux;
+ rc = clk_set_rate(vfe_dev->vfe_clk[clk_idx], round_rate);
+ if (rc < 0) {
+ pr_err("%s: Vfe set rate error\n", __func__);
+ return rc;
+ }
+ return 0;
+}
- vfe_dev->hw_info->vfe_ops.core_ops.cfg_camif(vfe_dev, pix_cfg);
+int msm_isp_cfg_pix(struct vfe_device *vfe_dev,
+ struct msm_vfe_input_cfg *input_cfg)
+{
+ int rc = 0;
+ if (vfe_dev->axi_data.src_info[VFE_PIX_0].active) {
+ pr_err("%s: pixel path is active\n", __func__);
+ return -EINVAL;
+ }
+
+ vfe_dev->axi_data.src_info[VFE_PIX_0].pixel_clock =
+ input_cfg->input_pix_clk;
+ vfe_dev->axi_data.src_info[VFE_PIX_0].input_mux =
+ input_cfg->d.pix_cfg.input_mux;
+ vfe_dev->axi_data.src_info[VFE_PIX_0].width =
+ input_cfg->d.pix_cfg.camif_cfg.pixels_per_line;
+
+ rc = msm_isp_set_clk_rate(vfe_dev,
+ vfe_dev->axi_data.src_info[VFE_PIX_0].pixel_clock);
+ if (rc < 0) {
+ pr_err("%s: clock set rate failed\n", __func__);
+ return rc;
+ }
+
+ vfe_dev->hw_info->vfe_ops.core_ops.cfg_camif(
+ vfe_dev, &input_cfg->d.pix_cfg);
return rc;
}
int msm_isp_cfg_rdi(struct vfe_device *vfe_dev,
- struct msm_vfe_rdi_cfg *rdi_cfg, enum msm_vfe_input_src input_src)
+ struct msm_vfe_input_cfg *input_cfg)
{
int rc = 0;
- /*TD Validate config info
- * should check if all streams are off */
+ if (vfe_dev->axi_data.src_info[input_cfg->input_src].active) {
+ pr_err("%s: RAW%d path is active\n", __func__,
+ input_cfg->input_src - VFE_RAW_0);
+ return -EINVAL;
+ }
- vfe_dev->hw_info->vfe_ops.core_ops.
- cfg_rdi_reg(vfe_dev, rdi_cfg, input_src);
+ vfe_dev->axi_data.src_info[input_cfg->input_src].pixel_clock =
+ input_cfg->input_pix_clk;
+ vfe_dev->hw_info->vfe_ops.core_ops.cfg_rdi_reg(
+ vfe_dev, &input_cfg->d.rdi_cfg, input_cfg->input_src);
return rc;
}
@@ -100,16 +273,16 @@
switch (input_cfg->input_src) {
case VFE_PIX_0:
- msm_isp_cfg_pix(vfe_dev, &input_cfg->d.pix_cfg);
+ rc = msm_isp_cfg_pix(vfe_dev, input_cfg);
break;
case VFE_RAW_0:
case VFE_RAW_1:
case VFE_RAW_2:
- msm_isp_cfg_rdi(vfe_dev, &input_cfg->d.rdi_cfg,
- input_cfg->input_src);
+ rc = msm_isp_cfg_rdi(vfe_dev, input_cfg);
break;
- case VFE_SRC_MAX:
- break;
+ default:
+ pr_err("%s: Invalid input source\n", __func__);
+ rc = -EINVAL;
}
return rc;
}
@@ -120,55 +293,82 @@
long rc = 0;
struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
- mutex_lock(&vfe_dev->mutex);
- ISP_DBG("%s cmd: %d\n", __func__, cmd);
+ /* Use real time mutex for hard real-time ioctls such as
+ * buffer operations and register updates.
+ * Use core mutex for other ioctls that could take
+ * longer time to complete such as start/stop ISP streams
+ * which blocks until the hardware start/stop streaming
+ */
+ ISP_DBG("%s cmd: %d\n", __func__, _IOC_TYPE(cmd));
switch (cmd) {
case VIDIOC_MSM_VFE_REG_CFG: {
+ mutex_lock(&vfe_dev->realtime_mutex);
rc = msm_isp_proc_cmd(vfe_dev, arg);
+ mutex_unlock(&vfe_dev->realtime_mutex);
break;
}
case VIDIOC_MSM_ISP_REQUEST_BUF:
case VIDIOC_MSM_ISP_ENQUEUE_BUF:
case VIDIOC_MSM_ISP_RELEASE_BUF: {
+ mutex_lock(&vfe_dev->realtime_mutex);
rc = msm_isp_proc_buf_cmd(vfe_dev->buf_mgr, cmd, arg);
+ mutex_unlock(&vfe_dev->realtime_mutex);
break;
}
case VIDIOC_MSM_ISP_REQUEST_STREAM:
+ mutex_lock(&vfe_dev->core_mutex);
rc = msm_isp_request_axi_stream(vfe_dev, arg);
+ mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_RELEASE_STREAM:
+ mutex_lock(&vfe_dev->core_mutex);
rc = msm_isp_release_axi_stream(vfe_dev, arg);
+ mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_CFG_STREAM:
+ mutex_lock(&vfe_dev->core_mutex);
rc = msm_isp_cfg_axi_stream(vfe_dev, arg);
+ mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_INPUT_CFG:
+ mutex_lock(&vfe_dev->core_mutex);
rc = msm_isp_cfg_input(vfe_dev, arg);
+ mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_SET_SRC_STATE:
+ mutex_lock(&vfe_dev->core_mutex);
msm_isp_set_src_state(vfe_dev, arg);
+ mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_REQUEST_STATS_STREAM:
+ mutex_lock(&vfe_dev->core_mutex);
rc = msm_isp_request_stats_stream(vfe_dev, arg);
+ mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_RELEASE_STATS_STREAM:
+ mutex_lock(&vfe_dev->core_mutex);
rc = msm_isp_release_stats_stream(vfe_dev, arg);
+ mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_CFG_STATS_STREAM:
+ mutex_lock(&vfe_dev->core_mutex);
rc = msm_isp_cfg_stats_stream(vfe_dev, arg);
+ mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_CFG_STATS_COMP_POLICY:
+ mutex_lock(&vfe_dev->core_mutex);
rc = msm_isp_cfg_stats_comp_policy(vfe_dev, arg);
+ mutex_unlock(&vfe_dev->core_mutex);
break;
case VIDIOC_MSM_ISP_UPDATE_STREAM:
+ mutex_lock(&vfe_dev->core_mutex);
rc = msm_isp_update_axi_stream(vfe_dev, arg);
+ mutex_unlock(&vfe_dev->core_mutex);
break;
default:
pr_err("%s: Invalid ISP command\n", __func__);
rc = -EINVAL;
}
-
- mutex_unlock(&vfe_dev->mutex);
return rc;
}
@@ -623,23 +823,27 @@
long rc;
ISP_DBG("%s\n", __func__);
- mutex_lock(&vfe_dev->mutex);
+ mutex_lock(&vfe_dev->realtime_mutex);
+ mutex_lock(&vfe_dev->core_mutex);
if (vfe_dev->vfe_open_cnt == 1) {
pr_err("VFE already open\n");
- mutex_unlock(&vfe_dev->mutex);
+ mutex_unlock(&vfe_dev->core_mutex);
+ mutex_unlock(&vfe_dev->realtime_mutex);
return -ENODEV;
}
if (vfe_dev->hw_info->vfe_ops.core_ops.init_hw(vfe_dev) < 0) {
pr_err("%s: init hardware failed\n", __func__);
- mutex_unlock(&vfe_dev->mutex);
+ mutex_unlock(&vfe_dev->core_mutex);
+ mutex_unlock(&vfe_dev->realtime_mutex);
return -EBUSY;
}
rc = vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev);
if (rc <= 0) {
pr_err("%s: reset timeout\n", __func__);
- mutex_unlock(&vfe_dev->mutex);
+ mutex_unlock(&vfe_dev->core_mutex);
+ mutex_unlock(&vfe_dev->realtime_mutex);
return -EINVAL;
}
vfe_dev->vfe_hw_version = msm_camera_io_r(vfe_dev->vfe_base);
@@ -659,7 +863,8 @@
vfe_dev->axi_data.hw_info = vfe_dev->hw_info->axi_hw_info;
vfe_dev->vfe_open_cnt++;
vfe_dev->taskletq_idx = 0;
- mutex_unlock(&vfe_dev->mutex);
+ mutex_unlock(&vfe_dev->core_mutex);
+ mutex_unlock(&vfe_dev->realtime_mutex);
return 0;
}
@@ -669,10 +874,12 @@
long rc;
struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
ISP_DBG("%s\n", __func__);
- mutex_lock(&vfe_dev->mutex);
+ mutex_lock(&vfe_dev->realtime_mutex);
+ mutex_lock(&vfe_dev->core_mutex);
if (vfe_dev->vfe_open_cnt == 0) {
pr_err("%s: Invalid close\n", __func__);
- mutex_unlock(&vfe_dev->mutex);
+ mutex_unlock(&vfe_dev->core_mutex);
+ mutex_unlock(&vfe_dev->realtime_mutex);
return -ENODEV;
}
@@ -689,6 +896,7 @@
vfe_dev->hw_info->vfe_ops.core_ops.release_hw(vfe_dev);
vfe_dev->vfe_open_cnt--;
- mutex_unlock(&vfe_dev->mutex);
+ mutex_unlock(&vfe_dev->core_mutex);
+ mutex_unlock(&vfe_dev->realtime_mutex);
return 0;
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
index 3dac7e0..7934f26 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
@@ -22,6 +22,32 @@
#define ISP_DBG(fmt, args...) pr_debug(fmt, ##args)
#endif
+#define ALT_VECTOR_IDX(x) {x = 3 - x; }
+struct msm_isp_bandwidth_info {
+ uint32_t active;
+ uint64_t ab;
+ uint64_t ib;
+};
+
+enum msm_isp_hw_client {
+ ISP_VFE0,
+ ISP_VFE1,
+ ISP_CPP,
+ MAX_ISP_CLIENT,
+};
+
+struct msm_isp_bandwidth_mgr {
+ uint32_t bus_client;
+ uint32_t bus_vector_active_idx;
+ uint32_t use_count;
+ struct msm_isp_bandwidth_info client_info[MAX_ISP_CLIENT];
+};
+
+int msm_isp_init_bandwidth_mgr(enum msm_isp_hw_client client);
+int msm_isp_update_bandwidth(enum msm_isp_hw_client client,
+ uint64_t ab, uint64_t ib);
+void msm_isp_deinit_bandwidth_mgr(enum msm_isp_hw_client client);
+
int msm_isp_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
struct v4l2_event_subscription *sub);
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 85788e9..f209330 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -78,7 +78,7 @@
{"camss_csi_vfe_clk1", -1},
};
-static int msm_ispif_clk_enable(struct ispif_device *ispif,
+static int msm_ispif_clk_enable_one(struct ispif_device *ispif,
enum msm_ispif_vfe_intf vfe_intf, int enable)
{
int rc = 0;
@@ -119,8 +119,8 @@
ARRAY_SIZE(ispif_8974_clk_info_vfe1), enable);
}
if (rc) {
- pr_err("%s: cannot enable clock, error = %d\n",
- __func__, rc);
+ pr_err("%s: cannot enable clock, error = %d, vfeid = %d\n",
+ __func__, rc, vfe_intf);
goto end;
}
} else {
@@ -133,17 +133,56 @@
return rc;
}
+static int msm_ispif_clk_enable(struct ispif_device *ispif,
+ struct msm_ispif_param_data *params, int enable)
+{
+ int rc = 0;
+ int i, j;
+ uint32_t vfe_intf_mask = 0;
+
+ for (i = 0; i < params->num; i++) {
+ if (vfe_intf_mask & (1 << params->entries[i].vfe_intf))
+ continue;
+ rc = msm_ispif_clk_enable_one(ispif,
+ params->entries[i].vfe_intf, 1);
+ if (rc < 0 && enable) {
+ pr_err("%s: unable to enable clocks for VFE %d",
+ __func__, params->entries[i].vfe_intf);
+ for (j = 0; j < i; j++) {
+ /* if VFE clock is not enabled do
+ * not disable the clock */
+ if (!(vfe_intf_mask & (1 <<
+ params->entries[i].vfe_intf)))
+ continue;
+ msm_ispif_clk_enable_one(ispif,
+ params->entries[j].vfe_intf, 0);
+ /* remove the VFE ID from the mask */
+ vfe_intf_mask &=
+ ~(1 << params->entries[i].vfe_intf);
+ }
+ break;
+ }
+ vfe_intf_mask |= 1 << params->entries[i].vfe_intf;
+ }
+ return rc;
+}
+
static int msm_ispif_intf_reset(struct ispif_device *ispif,
struct msm_ispif_param_data *params)
{
int i, rc = 0;
enum msm_ispif_intftype intf_type;
- uint32_t data = STROBED_RST_EN;
+ int vfe_intf = 0;
+ uint32_t data = 0;
for (i = 0; i < params->num; i++) {
+ data = STROBED_RST_EN;
+ vfe_intf = params->entries[i].vfe_intf;
intf_type = params->entries[i].intftype;
- ispif->sof_count[params->vfe_intf].sof_cnt[intf_type] = 0;
+ ispif->sof_count[params->entries[i].vfe_intf].
+ sof_cnt[intf_type] = 0;
+
switch (intf_type) {
case PIX0:
data |= (PIX_0_VFE_RST_STB | PIX_0_CSID_RST_STB);
@@ -164,35 +203,40 @@
rc = -EINVAL;
break;
}
- }
- if (data > 0x1) {
- unsigned long jiffes = msecs_to_jiffies(500);
- long lrc = 0;
- unsigned long flags;
+ if (data > 0x1) {
+ unsigned long jiffes = msecs_to_jiffies(500);
+ long lrc = 0;
+ unsigned long flags;
- spin_lock_irqsave(&ispif->auto_complete_lock, flags);
- ispif->wait_timeout[params->vfe_intf] = 0;
- init_completion(&ispif->reset_complete[params->vfe_intf]);
- spin_unlock_irqrestore(&ispif->auto_complete_lock, flags);
-
- if (params->vfe_intf == VFE0)
- msm_camera_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
- else
- msm_camera_io_w(data, ispif->base +
- ISPIF_RST_CMD_1_ADDR);
-
- lrc = wait_for_completion_interruptible_timeout(
- &ispif->reset_complete[params->vfe_intf], jiffes);
- if (lrc < 0 || !lrc) {
- pr_err("%s: wait timeout ret = %ld\n", __func__, lrc);
- rc = -EIO;
-
- spin_lock_irqsave(&ispif->auto_complete_lock, flags);
- ispif->wait_timeout[params->vfe_intf] = 1;
+ spin_lock_irqsave(
+ &ispif->auto_complete_lock, flags);
+ ispif->wait_timeout[vfe_intf] = 0;
+ init_completion(&ispif->reset_complete[vfe_intf]);
spin_unlock_irqrestore(
&ispif->auto_complete_lock, flags);
+
+ if (vfe_intf == VFE0)
+ msm_camera_io_w(data, ispif->base +
+ ISPIF_RST_CMD_ADDR);
+ else
+ msm_camera_io_w(data, ispif->base +
+ ISPIF_RST_CMD_1_ADDR);
+ lrc = wait_for_completion_interruptible_timeout(
+ &ispif->reset_complete[vfe_intf], jiffes);
+ if (lrc < 0 || !lrc) {
+ pr_err("%s: wait timeout ret = %ld, vfe_id = %d\n",
+ __func__, lrc, vfe_intf);
+ rc = -EIO;
+
+ spin_lock_irqsave(
+ &ispif->auto_complete_lock, flags);
+ ispif->wait_timeout[vfe_intf] = 1;
+ spin_unlock_irqrestore(
+ &ispif->auto_complete_lock, flags);
+ }
}
}
+
return rc;
}
@@ -223,7 +267,8 @@
&ispif->reset_complete[VFE0], jiffes);
if (lrc < 0 || !lrc) {
- pr_err("%s: wait timeout ret = %ld\n", __func__, lrc);
+ pr_err("%s: wait timeout ret = %ld, vfeid = %d\n",
+ __func__, lrc, VFE0);
rc = -EIO;
spin_lock_irqsave(&ispif->auto_complete_lock, flags);
@@ -242,7 +287,8 @@
&ispif->reset_complete[VFE1], jiffes);
if (lrc < 0 || !lrc) {
- pr_err("%s: wait timeout ret = %ld\n", __func__, lrc);
+ pr_err("%s: wait timeout ret = %ld, vfeid = %d\n",
+ __func__, lrc, VFE1);
rc = -EIO;
spin_lock_irqsave(&ispif->auto_complete_lock, flags);
@@ -320,6 +366,38 @@
ISPIF_VFE_m_INPUT_SEL(vfe_intf));
}
+static void msm_ispif_enable_crop(struct ispif_device *ispif,
+ uint8_t intftype, uint8_t vfe_intf, uint16_t start_pixel,
+ uint16_t end_pixel)
+{
+ uint32_t data;
+ BUG_ON(!ispif);
+
+ if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
+ pr_err("%s: invalid interface type\n", __func__);
+ return;
+ }
+
+ data = msm_camera_io_r(ispif->base + ISPIF_VFE_m_CTRL_0(vfe_intf));
+ data |= (1 << (intftype + 7));
+ if (intftype == PIX0)
+ data |= 1 << PIX0_LINE_BUF_EN_BIT;
+ msm_camera_io_w(data,
+ ispif->base + ISPIF_VFE_m_CTRL_0(vfe_intf));
+
+ if (intftype == PIX0)
+ msm_camera_io_w_mb(start_pixel | (end_pixel << 16),
+ ispif->base + ISPIF_VFE_m_PIX_INTF_n_CROP(vfe_intf, 0));
+ else if (intftype == PIX1)
+ msm_camera_io_w_mb(start_pixel | (end_pixel << 16),
+ ispif->base + ISPIF_VFE_m_PIX_INTF_n_CROP(vfe_intf, 1));
+ else {
+ pr_err("%s: invalid intftype=%d\n", __func__, intftype);
+ BUG_ON(1);
+ return;
+ }
+}
+
static void msm_ispif_enable_intf_cids(struct ispif_device *ispif,
uint8_t intftype, uint16_t cid_mask, uint8_t vfe_intf, uint8_t enable)
{
@@ -427,28 +505,37 @@
BUG_ON(!ispif);
BUG_ON(!params);
- vfe_intf = params->vfe_intf;
-
- rc = msm_ispif_clk_enable(ispif, vfe_intf, 1);
- if (rc < 0) {
- pr_err("%s: unable to enable clocks for VFE%d", __func__,
- vfe_intf);
+ if (ispif->ispif_state != ISPIF_POWER_UP) {
+ pr_err("%s: ispif invalid state %d\n", __func__,
+ ispif->ispif_state);
+ rc = -EPERM;
return rc;
}
- if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
- pr_err("%s: invalid interface type\n", __func__);
- return -EINVAL;
+ rc = msm_ispif_clk_enable(ispif, params, 1);
+ if (rc < 0) {
+ pr_err("%s: unable to enable clocks", __func__);
+ return rc;
}
-
- msm_camera_io_w(0x0, ispif->base + ISPIF_VFE_m_IRQ_MASK_0(vfe_intf));
- msm_camera_io_w(0x0, ispif->base + ISPIF_VFE_m_IRQ_MASK_1(vfe_intf));
- msm_camera_io_w_mb(0x0, ispif->base + ISPIF_VFE_m_IRQ_MASK_2(vfe_intf));
+ for (i = 0; i < params->num; i++) {
+ vfe_intf = params->entries[i].vfe_intf;
+ if (!msm_ispif_is_intf_valid(ispif->csid_version,
+ vfe_intf)) {
+ pr_err("%s: invalid interface type\n", __func__);
+ return -EINVAL;
+ }
+ msm_camera_io_w(0x0, ispif->base +
+ ISPIF_VFE_m_IRQ_MASK_0(vfe_intf));
+ msm_camera_io_w(0x0, ispif->base +
+ ISPIF_VFE_m_IRQ_MASK_1(vfe_intf));
+ msm_camera_io_w_mb(0x0, ispif->base +
+ ISPIF_VFE_m_IRQ_MASK_2(vfe_intf));
+ }
for (i = 0; i < params->num; i++) {
intftype = params->entries[i].intftype;
- vfe_intf = params->vfe_intf;
+ vfe_intf = params->entries[i].vfe_intf;
CDBG("%s intftype %x, vfe_intf %d, csid %d\n", __func__,
intftype, vfe_intf, params->entries[i].csid);
@@ -475,31 +562,36 @@
¶ms->entries[i]);
msm_ispif_enable_intf_cids(ispif, intftype,
cid_mask, vfe_intf, 1);
+ if (params->entries[i].crop_enable)
+ msm_ispif_enable_crop(ispif, intftype, vfe_intf,
+ params->entries[i].crop_start_pixel,
+ params->entries[i].crop_end_pixel);
}
- msm_camera_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base +
- ISPIF_VFE_m_IRQ_MASK_0(vfe_intf));
+ for (vfe_intf = 0; vfe_intf < 2; vfe_intf++) {
+ msm_camera_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base +
+ ISPIF_VFE_m_IRQ_MASK_0(vfe_intf));
- msm_camera_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base +
- ISPIF_VFE_m_IRQ_CLEAR_0(vfe_intf));
+ msm_camera_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base +
+ ISPIF_VFE_m_IRQ_CLEAR_0(vfe_intf));
- msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base +
- ISPIF_VFE_m_IRQ_MASK_1(vfe_intf));
+ msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base +
+ ISPIF_VFE_m_IRQ_MASK_1(vfe_intf));
- msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base +
- ISPIF_VFE_m_IRQ_CLEAR_1(vfe_intf));
+ msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base +
+ ISPIF_VFE_m_IRQ_CLEAR_1(vfe_intf));
- msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base +
- ISPIF_VFE_m_IRQ_MASK_2(vfe_intf));
+ msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base +
+ ISPIF_VFE_m_IRQ_MASK_2(vfe_intf));
- msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base +
- ISPIF_VFE_m_IRQ_CLEAR_2(vfe_intf));
+ msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base +
+ ISPIF_VFE_m_IRQ_CLEAR_2(vfe_intf));
+ }
msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
-
- rc = msm_ispif_clk_enable(ispif, vfe_intf, 0);
+ msm_ispif_clk_enable(ispif, params, 0);
return rc;
}
@@ -511,18 +603,22 @@
int i, k;
enum msm_ispif_intftype intf_type;
enum msm_ispif_cid cid;
- enum msm_ispif_vfe_intf vfe_intf = params->vfe_intf;
+ enum msm_ispif_vfe_intf vfe_intf;
BUG_ON(!ispif);
BUG_ON(!params);
- if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
- pr_err("%s: invalid interface type\n", __func__);
- return;
+ for (i = 0; i < params->num; i++) {
+ vfe_intf = params->entries[i].vfe_intf;
+ if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
+ pr_err("%s: invalid interface type\n", __func__);
+ return;
+ }
}
for (i = 0; i < params->num; i++) {
intf_type = params->entries[i].intftype;
+ vfe_intf = params->entries[i].vfe_intf;
for (k = 0; k < params->entries[i].num_cids; k++) {
cid = params->entries[i].cids[k];
vc = cid % 4;
@@ -542,16 +638,19 @@
(cmd_bits << (vc * 2 + intf_type * 8));
}
}
+
+ /* cmd for PIX0, PIX1, RDI0, RDI1 */
+ if (ispif->applied_intf_cmd[vfe_intf].intf_cmd != 0xFFFFFFFF)
+ msm_camera_io_w_mb(
+ ispif->applied_intf_cmd[vfe_intf].intf_cmd,
+ ispif->base + ISPIF_VFE_m_INTF_CMD_0(vfe_intf));
+
+ /* cmd for RDI2 */
+ if (ispif->applied_intf_cmd[vfe_intf].intf_cmd1 != 0xFFFFFFFF)
+ msm_camera_io_w_mb(
+ ispif->applied_intf_cmd[vfe_intf].intf_cmd1,
+ ispif->base + ISPIF_VFE_m_INTF_CMD_1(vfe_intf));
}
- /* cmd for PIX0, PIX1, RDI0, RDI1 */
- if (ispif->applied_intf_cmd[vfe_intf].intf_cmd != 0xFFFFFFFF) {
- msm_camera_io_w_mb(ispif->applied_intf_cmd[vfe_intf].intf_cmd,
- ispif->base + ISPIF_VFE_m_INTF_CMD_0(vfe_intf));
- }
- /* cmd for RDI2 */
- if (ispif->applied_intf_cmd[vfe_intf].intf_cmd1 != 0xFFFFFFFF)
- msm_camera_io_w_mb(ispif->applied_intf_cmd[vfe_intf].intf_cmd1,
- ispif->base + ISPIF_VFE_m_INTF_CMD_1(vfe_intf));
}
static int msm_ispif_stop_immediately(struct ispif_device *ispif,
@@ -563,6 +662,13 @@
BUG_ON(!ispif);
BUG_ON(!params);
+ if (ispif->ispif_state != ISPIF_POWER_UP) {
+ pr_err("%s: ispif invalid state %d\n", __func__,
+ ispif->ispif_state);
+ rc = -EPERM;
+ return rc;
+ }
+
msm_ispif_intf_cmd(ispif, ISPIF_INTF_CMD_DISABLE_IMMEDIATELY, params);
/* after stop the interface we need to unmask the CID enable bits */
@@ -570,7 +676,7 @@
cid_mask = msm_ispif_get_cids_mask_from_cfg(
¶ms->entries[i]);
msm_ispif_enable_intf_cids(ispif, params->entries[i].intftype,
- cid_mask, params->vfe_intf, 0);
+ cid_mask, params->entries[i].vfe_intf, 0);
}
return rc;
@@ -581,10 +687,16 @@
{
int rc;
- rc = msm_ispif_clk_enable(ispif, params->vfe_intf, 1);
+ if (ispif->ispif_state != ISPIF_POWER_UP) {
+ pr_err("%s: ispif invalid state %d\n", __func__,
+ ispif->ispif_state);
+ rc = -EPERM;
+ return rc;
+ }
+
+ rc = msm_ispif_clk_enable(ispif, params, 1);
if (rc < 0) {
- pr_err("%s: unable to enable clocks for VFE%d", __func__,
- params->vfe_intf);
+ pr_err("%s: unable to enable clocks", __func__);
return rc;
}
@@ -592,13 +704,13 @@
if (rc) {
pr_err("%s: msm_ispif_intf_reset failed. rc=%d\n",
__func__, rc);
- return rc;
+ goto end;
}
msm_ispif_intf_cmd(ispif, ISPIF_INTF_CMD_ENABLE_FRAME_BOUNDARY, params);
- msm_ispif_clk_enable(ispif, params->vfe_intf, 0);
-
+end:
+ msm_ispif_clk_enable(ispif, params, 0);
return rc;
}
@@ -613,18 +725,27 @@
BUG_ON(!ispif);
BUG_ON(!params);
- vfe_intf = params->vfe_intf;
- rc = msm_ispif_clk_enable(ispif, params->vfe_intf, 1);
- if (rc < 0) {
- pr_err("%s: unable to enable clocks for VFE%d", __func__,
- params->vfe_intf);
+ if (ispif->ispif_state != ISPIF_POWER_UP) {
+ pr_err("%s: ispif invalid state %d\n", __func__,
+ ispif->ispif_state);
+ rc = -EPERM;
return rc;
}
- if (!msm_ispif_is_intf_valid(ispif->csid_version, vfe_intf)) {
- pr_err("%s: invalid interface type\n", __func__);
- return -EINVAL;
+ rc = msm_ispif_clk_enable(ispif, params, 1);
+ if (rc < 0) {
+ pr_err("%s: unable to enable clocks", __func__);
+ return rc;
+ }
+
+ for (i = 0; i < params->num; i++) {
+ if (!msm_ispif_is_intf_valid(ispif->csid_version,
+ params->entries[i].vfe_intf)) {
+ pr_err("%s: invalid interface type\n", __func__);
+ rc = -EINVAL;
+ goto end;
+ }
}
msm_ispif_intf_cmd(ispif,
@@ -633,6 +754,7 @@
for (i = 0; i < params->num; i++) {
cid_mask =
msm_ispif_get_cids_mask_from_cfg(¶ms->entries[i]);
+ vfe_intf = params->entries[i].vfe_intf;
switch (params->entries[i].intftype) {
case PIX0:
@@ -653,7 +775,8 @@
default:
pr_err("%s: invalid intftype=%d\n", __func__,
params->entries[i].intftype);
- return -EPERM;
+ rc = -EPERM;
+ goto end;
}
/* todo_bug_fix? very bad. use readl_poll_timeout */
@@ -666,7 +789,8 @@
cid_mask, vfe_intf, 0);
}
- msm_ispif_clk_enable(ispif, vfe_intf, 0);
+end:
+ msm_ispif_clk_enable(ispif, params, 0);
return rc;
}
@@ -718,6 +842,25 @@
msm_camera_io_w_mb(out[VFE0].ispifIrqStatus2,
ispif->base + ISPIF_VFE_m_IRQ_CLEAR_2(VFE0));
+ if (ispif->vfe_info.num_vfe > 1) {
+ out[VFE1].ispifIrqStatus0 = msm_camera_io_r(ispif->base +
+ ISPIF_VFE_m_IRQ_STATUS_0(VFE1));
+ msm_camera_io_w(out[VFE1].ispifIrqStatus0,
+ ispif->base + ISPIF_VFE_m_IRQ_CLEAR_0(VFE1));
+
+ out[VFE1].ispifIrqStatus1 = msm_camera_io_r(ispif->base +
+ ISPIF_VFE_m_IRQ_STATUS_1(VFE1));
+ msm_camera_io_w(out[VFE1].ispifIrqStatus1,
+ ispif->base + ISPIF_VFE_m_IRQ_CLEAR_1(VFE1));
+
+ out[VFE1].ispifIrqStatus2 = msm_camera_io_r(ispif->base +
+ ISPIF_VFE_m_IRQ_STATUS_2(VFE1));
+ msm_camera_io_w_mb(out[VFE1].ispifIrqStatus2,
+ ispif->base + ISPIF_VFE_m_IRQ_CLEAR_2(VFE1));
+ }
+ msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
+ ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
+
if (out[VFE0].ispifIrqStatus0 & ISPIF_IRQ_STATUS_MASK) {
if (out[VFE0].ispifIrqStatus0 & RESET_DONE_IRQ) {
unsigned long flags;
@@ -742,24 +885,7 @@
ispif_process_irq(ispif, out, VFE0);
}
- if (ispif->csid_version >= CSID_VERSION_V3 &&
- ispif->vfe_info.num_vfe > 1) {
- out[VFE1].ispifIrqStatus0 = msm_camera_io_r(ispif->base +
- ISPIF_VFE_m_IRQ_STATUS_0(VFE1));
- msm_camera_io_w(out[VFE1].ispifIrqStatus0,
- ispif->base + ISPIF_VFE_m_IRQ_CLEAR_0(VFE1));
-
- out[VFE1].ispifIrqStatus1 = msm_camera_io_r(ispif->base +
- ISPIF_VFE_m_IRQ_STATUS_1(VFE1));
- msm_camera_io_w(out[VFE1].ispifIrqStatus1,
- ispif->base + ISPIF_VFE_m_IRQ_CLEAR_1(VFE1));
-
- out[VFE1].ispifIrqStatus2 = msm_camera_io_r(ispif->base +
- ISPIF_VFE_m_IRQ_STATUS_2(VFE1));
- msm_camera_io_w_mb(out[VFE1].ispifIrqStatus2,
- ispif->base + ISPIF_VFE_m_IRQ_CLEAR_2(VFE1));
-
-
+ if (ispif->vfe_info.num_vfe > 1) {
if (out[VFE1].ispifIrqStatus0 & RESET_DONE_IRQ) {
unsigned long flags;
spin_lock_irqsave(&ispif->auto_complete_lock, flags);
@@ -783,8 +909,6 @@
ispif_process_irq(ispif, out, VFE1);
}
- msm_camera_io_w_mb(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
- ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
}
static irqreturn_t msm_io_ispif_irq(int irq_num, void *data)
@@ -825,7 +949,7 @@
memset(ispif->sof_count, 0, sizeof(ispif->sof_count));
ispif->csid_version = csid_version;
- rc = msm_ispif_clk_enable(ispif, VFE0, 1);
+ rc = msm_ispif_clk_enable_one(ispif, VFE0, 1);
if (rc < 0) {
pr_err("%s: unable to enable clocks for VFE0", __func__);
goto error_clk0;
@@ -833,7 +957,7 @@
if (ispif->csid_version >= CSID_VERSION_V3 &&
ispif->vfe_info.num_vfe > 1) {
- rc = msm_ispif_clk_enable(ispif, VFE1, 1);
+ rc = msm_ispif_clk_enable_one(ispif, VFE1, 1);
if (rc < 0) {
pr_err("%s: unable to enable clocks for VFE1",
__func__);
@@ -868,10 +992,10 @@
end:
if (ispif->csid_version >= CSID_VERSION_V3 &&
ispif->vfe_info.num_vfe > 1)
- msm_ispif_clk_enable(ispif, VFE1, 0);
+ msm_ispif_clk_enable_one(ispif, VFE1, 0);
error_clk1:
- msm_ispif_clk_enable(ispif, VFE0, 0);
+ msm_ispif_clk_enable_one(ispif, VFE0, 0);
error_clk0:
return rc;
@@ -889,7 +1013,7 @@
}
for (i = 0; i < ispif->vfe_info.num_vfe; i++)
- msm_ispif_clk_enable(ispif, i, 1);
+ msm_ispif_clk_enable_one(ispif, i, 1);
/* make sure no streaming going on */
msm_ispif_reset(ispif);
@@ -899,7 +1023,7 @@
iounmap(ispif->base);
for (i = 0; i < ispif->vfe_info.num_vfe; i++)
- msm_ispif_clk_enable(ispif, i, 0);
+ msm_ispif_clk_enable_one(ispif, i, 0);
ispif->ispif_state = ISPIF_POWER_DOWN;
}
@@ -961,7 +1085,7 @@
case VIDIOC_MSM_ISPIF_CFG:
return msm_ispif_cmd(sd, arg);
default:
- pr_err("%s: invalid cmd received\n", __func__);
+ pr_err("%s: invalid cmd 0x%x received\n", __func__, cmd);
return -ENOIOCTLCMD;
}
}
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
index afd91d1..9f8b2fa 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v1.h
@@ -16,6 +16,7 @@
/* common registers */
#define ISPIF_RST_CMD_ADDR 0x0000
#define ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR 0x0124
+#define PIX0_LINE_BUF_EN_BIT 0
#define ISPIF_VFE(m) (0x0)
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
index 80b32d4..5e61a4d 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif_hwreg_v2.h
@@ -17,6 +17,7 @@
#define ISPIF_RST_CMD_ADDR 0x008
#define ISPIF_RST_CMD_1_ADDR 0x00C
#define ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR 0x01C
+#define PIX0_LINE_BUF_EN_BIT 6
#define ISPIF_VFE(m) ((m) * 0x200)
diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c
index fbc2b93..e50ac3a 100644
--- a/drivers/media/platform/msm/camera_v2/msm.c
+++ b/drivers/media/platform/msm/camera_v2/msm.c
@@ -277,6 +277,7 @@
{
struct msm_session *session = NULL;
struct msm_stream *stream = NULL;
+ unsigned long flags;
session = msm_queue_find(msm_session_q, struct msm_session,
list, __msm_queue_find_session, &session_id);
@@ -287,9 +288,10 @@
list, __msm_queue_find_stream, &stream_id);
if (!stream)
return;
-
+ spin_lock_irqsave(&(session->stream_q.lock), flags);
list_del_init(&stream->list);
session->stream_q.len--;
+ spin_unlock_irqrestore(&(session->stream_q.lock), flags);
kzfree(stream);
}
@@ -426,6 +428,7 @@
{
struct msm_session *session;
struct msm_command_ack *cmd_ack;
+ unsigned long flags;
session = msm_queue_find(msm_session_q, struct msm_session,
list, __msm_queue_find_session, &session_id);
@@ -439,6 +442,11 @@
return;
msm_queue_drain(&cmd_ack->command_q, struct msm_command, list);
+
+ spin_lock_irqsave(&(session->command_ack_q.lock), flags);
+ list_del_init(&cmd_ack->list);
+ session->command_ack_q.len--;
+ spin_unlock_irqrestore(&(session->command_ack_q.lock), flags);
}
static inline int __msm_v4l2_subdev_shutdown(struct v4l2_subdev *sd)
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
index 8a21512..35210a0 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
@@ -13,9 +13,15 @@
static struct msm_buf_mngr_device *msm_buf_mngr_dev;
+struct v4l2_subdev *msm_buf_mngr_get_subdev(void)
+{
+ return &msm_buf_mngr_dev->subdev.sd;
+}
+
static int msm_buf_mngr_get_buf(struct msm_buf_mngr_device *buf_mngr_dev,
void __user *argp)
{
+ unsigned long flags;
struct msm_buf_mngr_info *buf_info =
(struct msm_buf_mngr_info *)argp;
struct msm_get_bufs *new_entry =
@@ -35,9 +41,9 @@
}
new_entry->session_id = buf_info->session_id;
new_entry->stream_id = buf_info->stream_id;
- mutex_lock(&buf_mngr_dev->buf_q_lock);
+ spin_lock_irqsave(&buf_mngr_dev->buf_q_spinlock, flags);
list_add_tail(&new_entry->entry, &buf_mngr_dev->buf_qhead);
- mutex_unlock(&buf_mngr_dev->buf_q_lock);
+ spin_unlock_irqrestore(&buf_mngr_dev->buf_q_spinlock, flags);
buf_info->index = new_entry->vb2_buf->v4l2_buf.index;
return 0;
}
@@ -45,10 +51,11 @@
static int msm_buf_mngr_buf_done(struct msm_buf_mngr_device *buf_mngr_dev,
struct msm_buf_mngr_info *buf_info)
{
+ unsigned long flags;
struct msm_get_bufs *bufs, *save;
int ret = -EINVAL;
- mutex_lock(&buf_mngr_dev->buf_q_lock);
+ spin_lock_irqsave(&buf_mngr_dev->buf_q_spinlock, flags);
list_for_each_entry_safe(bufs, save, &buf_mngr_dev->buf_qhead, entry) {
if ((bufs->session_id == buf_info->session_id) &&
(bufs->stream_id == buf_info->stream_id) &&
@@ -64,7 +71,7 @@
break;
}
}
- mutex_unlock(&buf_mngr_dev->buf_q_lock);
+ spin_unlock_irqrestore(&buf_mngr_dev->buf_q_spinlock, flags);
return ret;
}
@@ -72,10 +79,11 @@
static int msm_buf_mngr_put_buf(struct msm_buf_mngr_device *buf_mngr_dev,
struct msm_buf_mngr_info *buf_info)
{
+ unsigned long flags;
struct msm_get_bufs *bufs, *save;
int ret = -EINVAL;
- mutex_lock(&buf_mngr_dev->buf_q_lock);
+ spin_lock_irqsave(&buf_mngr_dev->buf_q_spinlock, flags);
list_for_each_entry_safe(bufs, save, &buf_mngr_dev->buf_qhead, entry) {
if ((bufs->session_id == buf_info->session_id) &&
(bufs->stream_id == buf_info->stream_id) &&
@@ -87,7 +95,7 @@
break;
}
}
- mutex_unlock(&buf_mngr_dev->buf_q_lock);
+ spin_unlock_irqrestore(&buf_mngr_dev->buf_q_spinlock, flags);
return ret;
}
@@ -163,14 +171,13 @@
&msm_buf_mngr_dev->vb2_ops);
INIT_LIST_HEAD(&msm_buf_mngr_dev->buf_qhead);
- mutex_init(&msm_buf_mngr_dev->buf_q_lock);
+ spin_lock_init(&msm_buf_mngr_dev->buf_q_spinlock);
end:
return rc;
}
static void __exit msm_buf_mngr_exit(void)
{
- mutex_destroy(&msm_buf_mngr_dev->buf_q_lock);
kfree(msm_buf_mngr_dev);
}
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h
index a2b3a7e..56886cd 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.h
@@ -33,7 +33,7 @@
struct msm_buf_mngr_device {
struct list_head buf_qhead;
- struct mutex buf_q_lock;
+ spinlock_t buf_q_spinlock;
struct msm_sd_subdev subdev;
struct msm_sd_req_vb2_q vb2_ops;
};
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/Makefile b/drivers/media/platform/msm/camera_v2/pproc/cpp/Makefile
index 2f969d2..c793ef6 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/Makefile
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/Makefile
@@ -1,3 +1,4 @@
ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/isp/
ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
obj-$(CONFIG_MSM_CPP) += msm_cpp.o
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 8f63d33..1203d17 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
@@ -22,7 +22,6 @@
#include <linux/regulator/consumer.h>
#include <linux/ion.h>
#include <linux/proc_fs.h>
-#include <linux/debugfs.h>
#include <linux/msm_ion.h>
#include <linux/iommu.h>
#include <mach/iommu_domains.h>
@@ -33,11 +32,15 @@
#include <media/v4l2-ioctl.h>
#include <media/msmb_camera.h>
#include <media/msmb_pproc.h>
+#include <media/msmb_generic_buf_mgr.h>
#include "msm_cpp.h"
+#include "msm_isp_util.h"
#include "msm_camera_io_util.h"
#define MSM_CPP_DRV_NAME "msm_cpp"
+#define MSM_CPP_MAX_BUFF_QUEUE 16
+
#define CONFIG_MSM_CPP_DBG 0
#if CONFIG_MSM_CPP_DBG
@@ -126,6 +129,278 @@
return tmp;
}
+static struct msm_cpp_buff_queue_info_t *msm_cpp_get_buff_queue_entry(
+ struct cpp_device *cpp_dev, uint32_t session_id, uint32_t stream_id)
+{
+ uint32_t i = 0;
+ struct msm_cpp_buff_queue_info_t *buff_queue_info = NULL;
+
+ for (i = 0; i < cpp_dev->num_buffq; i++) {
+ if ((cpp_dev->buff_queue[i].used == 1) &&
+ (cpp_dev->buff_queue[i].session_id == session_id) &&
+ (cpp_dev->buff_queue[i].stream_id == stream_id)) {
+ buff_queue_info = &cpp_dev->buff_queue[i];
+ break;
+ }
+ }
+
+ if (buff_queue_info == NULL) {
+ pr_err("error buffer queue entry for sess:%d strm:%d not found\n",
+ session_id, stream_id);
+ }
+ return buff_queue_info;
+}
+
+static unsigned long msm_cpp_get_phy_addr(struct cpp_device *cpp_dev,
+ struct msm_cpp_buff_queue_info_t *buff_queue_info, uint32_t buff_index,
+ uint8_t native_buff)
+{
+ unsigned long phy_add = 0;
+ struct list_head *buff_head;
+ struct msm_cpp_buffer_map_list_t *buff, *save;
+
+ if (native_buff)
+ buff_head = &buff_queue_info->native_buff_head;
+ else
+ buff_head = &buff_queue_info->vb2_buff_head;
+
+ list_for_each_entry_safe(buff, save, buff_head, entry) {
+ if (buff->map_info.buff_info.index == buff_index) {
+ phy_add = buff->map_info.phy_addr;
+ break;
+ }
+ }
+
+ return phy_add;
+}
+
+static unsigned long msm_cpp_queue_buffer_info(struct cpp_device *cpp_dev,
+ struct msm_cpp_buff_queue_info_t *buff_queue,
+ struct msm_cpp_buffer_info_t *buffer_info)
+{
+ struct list_head *buff_head;
+ struct msm_cpp_buffer_map_list_t *buff, *save;
+ int rc = 0;
+
+ if (buffer_info->native_buff)
+ buff_head = &buff_queue->native_buff_head;
+ else
+ buff_head = &buff_queue->vb2_buff_head;
+
+ list_for_each_entry_safe(buff, save, buff_head, entry) {
+ if (buff->map_info.buff_info.index == buffer_info->index) {
+ pr_err("error buffer index already queued\n");
+ return -EINVAL;
+ }
+ }
+
+ buff = kzalloc(
+ sizeof(struct msm_cpp_buffer_map_list_t), GFP_KERNEL);
+ if (!buff) {
+ pr_err("error allocating memory\n");
+ return -EINVAL;
+ }
+
+ buff->map_info.buff_info = *buffer_info;
+ buff->map_info.ion_handle = ion_import_dma_buf(cpp_dev->client,
+ buffer_info->fd);
+ if (IS_ERR_OR_NULL(buff->map_info.ion_handle)) {
+ pr_err("ION import failed\n");
+ goto QUEUE_BUFF_ERROR1;
+ }
+
+ rc = ion_map_iommu(cpp_dev->client, buff->map_info.ion_handle,
+ cpp_dev->domain_num, 0, SZ_4K, 0,
+ (unsigned long *)&buff->map_info.phy_addr,
+ &buff->map_info.len, 0, 0);
+ if (rc < 0) {
+ pr_err("ION mmap failed\n");
+ goto QUEUE_BUFF_ERROR2;
+ }
+
+ INIT_LIST_HEAD(&buff->entry);
+ list_add_tail(&buff->entry, buff_head);
+
+ return buff->map_info.phy_addr;
+
+QUEUE_BUFF_ERROR2:
+ ion_unmap_iommu(cpp_dev->client, buff->map_info.ion_handle,
+ cpp_dev->domain_num, 0);
+QUEUE_BUFF_ERROR1:
+ ion_free(cpp_dev->client, buff->map_info.ion_handle);
+ buff->map_info.ion_handle = NULL;
+ kzfree(buff);
+
+ return 0;
+}
+
+static void msm_cpp_dequeue_buffer_info(struct cpp_device *cpp_dev,
+ struct msm_cpp_buffer_map_list_t *buff)
+{
+ ion_unmap_iommu(cpp_dev->client, buff->map_info.ion_handle,
+ cpp_dev->domain_num, 0);
+ ion_free(cpp_dev->client, buff->map_info.ion_handle);
+ buff->map_info.ion_handle = NULL;
+
+ list_del_init(&buff->entry);
+ kzfree(buff);
+
+ return;
+}
+
+static unsigned long msm_cpp_fetch_buffer_info(struct cpp_device *cpp_dev,
+ struct msm_cpp_buffer_info_t *buffer_info, uint32_t session_id,
+ uint32_t stream_id)
+{
+ unsigned long phy_addr = 0;
+ struct msm_cpp_buff_queue_info_t *buff_queue_info;
+ uint8_t native_buff = buffer_info->native_buff;
+
+ buff_queue_info = msm_cpp_get_buff_queue_entry(cpp_dev, session_id,
+ stream_id);
+ if (buff_queue_info == NULL) {
+ pr_err("error finding buffer queue entry for sessid:%d strmid:%d\n",
+ session_id, stream_id);
+ return phy_addr;
+ }
+
+ phy_addr = msm_cpp_get_phy_addr(cpp_dev, buff_queue_info,
+ buffer_info->index, native_buff);
+ if ((phy_addr == 0) && (native_buff)) {
+ phy_addr = msm_cpp_queue_buffer_info(cpp_dev, buff_queue_info,
+ buffer_info);
+ }
+ return phy_addr;
+}
+
+static int32_t msm_cpp_enqueue_buff_info_list(struct cpp_device *cpp_dev,
+ struct msm_cpp_stream_buff_info_t *stream_buff_info)
+{
+ uint32_t j;
+ struct msm_cpp_buff_queue_info_t *buff_queue_info;
+
+ buff_queue_info = msm_cpp_get_buff_queue_entry(cpp_dev,
+ (stream_buff_info->identity >> 16) & 0xFFFF,
+ stream_buff_info->identity & 0xFFFF);
+ if (buff_queue_info == NULL) {
+ pr_err("error finding buffer queue entry for sessid:%d strmid:%d\n",
+ (stream_buff_info->identity >> 16) & 0xFFFF,
+ stream_buff_info->identity & 0xFFFF);
+ return -EINVAL;
+ }
+
+ for (j = 0; j < stream_buff_info->num_buffs; j++) {
+ msm_cpp_queue_buffer_info(cpp_dev, buff_queue_info,
+ &stream_buff_info->buffer_info[j]);
+ }
+ return 0;
+}
+
+static int32_t msm_cpp_dequeue_buff_info_list(struct cpp_device *cpp_dev,
+ struct msm_cpp_buff_queue_info_t *buff_queue_info)
+{
+ struct msm_cpp_buffer_map_list_t *buff, *save;
+ struct list_head *buff_head;
+
+ buff_head = &buff_queue_info->native_buff_head;
+ list_for_each_entry_safe(buff, save, buff_head, entry) {
+ msm_cpp_dequeue_buffer_info(cpp_dev, buff);
+ }
+
+ buff_head = &buff_queue_info->vb2_buff_head;
+ list_for_each_entry_safe(buff, save, buff_head, entry) {
+ msm_cpp_dequeue_buffer_info(cpp_dev, buff);
+ }
+
+ return 0;
+}
+
+static int32_t msm_cpp_add_buff_queue_entry(struct cpp_device *cpp_dev,
+ uint16_t session_id, uint16_t stream_id)
+{
+ uint32_t i;
+ struct msm_cpp_buff_queue_info_t *buff_queue_info;
+
+ for (i = 0; i < cpp_dev->num_buffq; i++) {
+ if (cpp_dev->buff_queue[i].used == 0) {
+ buff_queue_info = &cpp_dev->buff_queue[i];
+ buff_queue_info->used = 1;
+ buff_queue_info->session_id = session_id;
+ buff_queue_info->stream_id = stream_id;
+ INIT_LIST_HEAD(&buff_queue_info->vb2_buff_head);
+ INIT_LIST_HEAD(&buff_queue_info->native_buff_head);
+ return 0;
+ }
+ }
+ pr_err("buffer queue full. error for sessionid: %d streamid: %d\n",
+ session_id, stream_id);
+ return -EINVAL;
+}
+
+static int32_t msm_cpp_free_buff_queue_entry(struct cpp_device *cpp_dev,
+ uint32_t session_id, uint32_t stream_id)
+{
+ struct msm_cpp_buff_queue_info_t *buff_queue_info;
+
+ buff_queue_info = msm_cpp_get_buff_queue_entry(cpp_dev, session_id,
+ stream_id);
+ if (buff_queue_info == NULL) {
+ pr_err("error finding buffer queue entry for sessid:%d strmid:%d\n",
+ session_id, stream_id);
+ return -EINVAL;
+ }
+
+ buff_queue_info->used = 0;
+ buff_queue_info->session_id = 0;
+ buff_queue_info->stream_id = 0;
+ INIT_LIST_HEAD(&buff_queue_info->vb2_buff_head);
+ INIT_LIST_HEAD(&buff_queue_info->native_buff_head);
+ return 0;
+}
+
+static int32_t msm_cpp_create_buff_queue(struct cpp_device *cpp_dev,
+ uint32_t num_buffq)
+{
+ struct msm_cpp_buff_queue_info_t *buff_queue;
+ buff_queue = kzalloc(
+ sizeof(struct msm_cpp_buff_queue_info_t) * num_buffq,
+ GFP_KERNEL);
+ if (!buff_queue) {
+ pr_err("Buff queue allocation failure\n");
+ return -ENOMEM;
+ }
+
+ if (cpp_dev->buff_queue) {
+ pr_err("Buff queue not empty\n");
+ kzfree(buff_queue);
+ return -EINVAL;
+ } else {
+ cpp_dev->buff_queue = buff_queue;
+ cpp_dev->num_buffq = num_buffq;
+ }
+ return 0;
+}
+
+static void msm_cpp_delete_buff_queue(struct cpp_device *cpp_dev)
+{
+ uint32_t i;
+
+ for (i = 0; i < cpp_dev->num_buffq; i++) {
+ if (cpp_dev->buff_queue[i].used == 1) {
+ pr_err("Queue not free sessionid: %d, streamid: %d\n",
+ cpp_dev->buff_queue[i].session_id,
+ cpp_dev->buff_queue[i].stream_id);
+ msm_cpp_free_buff_queue_entry(cpp_dev,
+ cpp_dev->buff_queue[i].session_id,
+ cpp_dev->buff_queue[i].stream_id);
+ }
+ }
+ kzfree(cpp_dev->buff_queue);
+ cpp_dev->buff_queue = NULL;
+ cpp_dev->num_buffq = 0;
+ return;
+}
+
static void msm_cpp_poll(void __iomem *cpp_base, u32 val)
{
uint32_t tmp, retry = 0;
@@ -176,12 +451,13 @@
static irqreturn_t msm_cpp_irq(int irq_num, void *data)
{
+ unsigned long flags;
uint32_t tx_level;
uint32_t irq_status;
- uint32_t msg_id, cmd_len;
uint32_t i;
- uint32_t tx_fifo[16];
+ uint32_t tx_fifo[MSM_CPP_TX_FIFO_LEVEL];
struct cpp_device *cpp_dev = data;
+ struct msm_cpp_tasklet_queue_cmd *queue_cmd;
irq_status = msm_camera_io_r(cpp_dev->base + MSM_CPP_MICRO_IRQGEN_STAT);
CPP_DBG("status: 0x%x\n", irq_status);
if (irq_status & 0x8) {
@@ -192,6 +468,62 @@
MSM_CPP_MICRO_FIFO_TX_DATA);
}
+ spin_lock_irqsave(&cpp_dev->tasklet_lock, flags);
+ queue_cmd = &cpp_dev->tasklet_queue_cmd[cpp_dev->taskletq_idx];
+ if (queue_cmd->cmd_used) {
+ pr_err("%s: cpp tasklet queue overflow\n", __func__);
+ list_del(&queue_cmd->list);
+ } else {
+ atomic_add(1, &cpp_dev->irq_cnt);
+ }
+ queue_cmd->irq_status = irq_status;
+ queue_cmd->tx_level = tx_level;
+ memset(&queue_cmd->tx_fifo[0], 0, sizeof(queue_cmd->tx_fifo));
+ for (i = 0; i < tx_level; i++)
+ queue_cmd->tx_fifo[i] = tx_fifo[i];
+
+ queue_cmd->cmd_used = 1;
+ cpp_dev->taskletq_idx =
+ (cpp_dev->taskletq_idx + 1) % MSM_CPP_TASKLETQ_SIZE;
+ list_add_tail(&queue_cmd->list, &cpp_dev->tasklet_q);
+ spin_unlock_irqrestore(&cpp_dev->tasklet_lock, flags);
+
+ tasklet_schedule(&cpp_dev->cpp_tasklet);
+ }
+ msm_camera_io_w(irq_status, cpp_dev->base + MSM_CPP_MICRO_IRQGEN_CLR);
+ return IRQ_HANDLED;
+}
+
+void msm_cpp_do_tasklet(unsigned long data)
+{
+ unsigned long flags;
+ uint32_t irq_status;
+ uint32_t tx_level;
+ uint32_t msg_id, cmd_len;
+ uint32_t i;
+ uint32_t tx_fifo[MSM_CPP_TX_FIFO_LEVEL];
+ struct cpp_device *cpp_dev = (struct cpp_device *) data;
+ struct msm_cpp_tasklet_queue_cmd *queue_cmd;
+
+ while (atomic_read(&cpp_dev->irq_cnt)) {
+ spin_lock_irqsave(&cpp_dev->tasklet_lock, flags);
+ queue_cmd = list_first_entry(&cpp_dev->tasklet_q,
+ struct msm_cpp_tasklet_queue_cmd, list);
+ if (!queue_cmd) {
+ atomic_set(&cpp_dev->irq_cnt, 0);
+ spin_unlock_irqrestore(&cpp_dev->tasklet_lock, flags);
+ return;
+ }
+ atomic_sub(1, &cpp_dev->irq_cnt);
+ list_del(&queue_cmd->list);
+ queue_cmd->cmd_used = 0;
+ irq_status = queue_cmd->irq_status;
+ tx_level = queue_cmd->tx_level;
+ for (i = 0; i < tx_level; i++)
+ tx_fifo[i] = queue_cmd->tx_fifo[i];
+
+ spin_unlock_irqrestore(&cpp_dev->tasklet_lock, flags);
+
for (i = 0; i < tx_level; i++) {
if (tx_fifo[i] == MSM_CPP_MSG_ID_CMD) {
cmd_len = tx_fifo[i+1];
@@ -204,8 +536,6 @@
}
}
}
- msm_camera_io_w(irq_status, cpp_dev->base + MSM_CPP_MICRO_IRQGEN_CLR);
- return IRQ_HANDLED;
}
static void msm_cpp_boot_hw(struct cpp_device *cpp_dev)
@@ -253,6 +583,12 @@
static int cpp_init_hardware(struct cpp_device *cpp_dev)
{
int rc = 0;
+ rc = msm_isp_init_bandwidth_mgr(ISP_CPP);
+ if (rc < 0) {
+ pr_err("%s: Bandwidth registration Failed!\n", __func__);
+ goto bus_scale_register_failed;
+ }
+ msm_isp_update_bandwidth(ISP_CPP, 981345600, 1600020000);
if (cpp_dev->fs_cpp == NULL) {
cpp_dev->fs_cpp =
@@ -309,6 +645,7 @@
rc = -EBUSY;
goto req_irq_fail;
}
+ cpp_dev->buf_mgr_subdev = msm_buf_mngr_get_subdev();
}
cpp_dev->hw_info.cpp_hw_version =
@@ -318,6 +655,9 @@
msm_camera_io_r(cpp_dev->cpp_hw_base + 0x4);
pr_debug("CPP HW Caps: 0x%x\n", cpp_dev->hw_info.cpp_hw_caps);
msm_camera_io_w(0x1, cpp_dev->vbif_base + 0x4);
+ cpp_dev->taskletq_idx = 0;
+ atomic_set(&cpp_dev->irq_cnt, 0);
+ msm_cpp_create_buff_queue(cpp_dev, MSM_CPP_MAX_BUFF_QUEUE);
if (cpp_dev->is_firmware_loaded == 1)
msm_cpp_boot_hw(cpp_dev);
return rc;
@@ -334,14 +674,20 @@
regulator_disable(cpp_dev->fs_cpp);
regulator_put(cpp_dev->fs_cpp);
fs_failed:
+ msm_isp_update_bandwidth(ISP_CPP, 0, 0);
+ msm_isp_deinit_bandwidth_mgr(ISP_CPP);
+bus_scale_register_failed:
return rc;
}
static void cpp_release_hardware(struct cpp_device *cpp_dev)
{
- if (cpp_dev->state != CPP_STATE_BOOT)
+ if (cpp_dev->state != CPP_STATE_BOOT) {
free_irq(cpp_dev->irq->start, cpp_dev);
-
+ tasklet_kill(&cpp_dev->cpp_tasklet);
+ atomic_set(&cpp_dev->irq_cnt, 0);
+ }
+ msm_cpp_delete_buff_queue(cpp_dev);
iounmap(cpp_dev->base);
iounmap(cpp_dev->vbif_base);
iounmap(cpp_dev->cpp_hw_base);
@@ -352,6 +698,8 @@
regulator_put(cpp_dev->fs_cpp);
cpp_dev->fs_cpp = NULL;
}
+ msm_isp_update_bandwidth(ISP_CPP, 0, 0);
+ msm_isp_deinit_bandwidth_mgr(ISP_CPP);
}
static void cpp_load_fw(struct cpp_device *cpp_dev, char *fw_name_bin)
@@ -504,6 +852,18 @@
.close = cpp_close_node,
};
+static int msm_cpp_buffer_ops(struct cpp_device *cpp_dev,
+ uint32_t buff_mgr_ops, struct msm_buf_mngr_info *buff_mgr_info)
+{
+ int rc = -EINVAL;
+
+ rc = v4l2_subdev_call(cpp_dev->buf_mgr_subdev, core, ioctl,
+ buff_mgr_ops, buff_mgr_info);
+ if (rc < 0)
+ pr_err("%s: line %d rc = %d\n", __func__, __LINE__, rc);
+ return rc;
+}
+
static int msm_cpp_notify_frame_done(struct cpp_device *cpp_dev)
{
struct v4l2_event v4l2_evt;
@@ -511,10 +871,13 @@
struct msm_queue_cmd *event_qcmd;
struct msm_cpp_frame_info_t *processed_frame;
struct msm_device_queue *queue = &cpp_dev->processing_q;
+ struct msm_buf_mngr_info buff_mgr_info;
+ int rc = 0;
if (queue->len > 0) {
frame_qcmd = msm_dequeue(queue, list_frame);
processed_frame = frame_qcmd->command;
+ do_gettimeofday(&(processed_frame->out_time));
kfree(frame_qcmd);
event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_ATOMIC);
if (!event_qcmd) {
@@ -526,78 +889,57 @@
CPP_DBG("fid %d\n", processed_frame->frame_id);
msm_enqueue(&cpp_dev->eventData_q, &event_qcmd->list_eventdata);
+ if (!processed_frame->output_buffer_info.processed_divert) {
+ memset(&buff_mgr_info, 0 ,
+ sizeof(struct msm_buf_mngr_info));
+ buff_mgr_info.session_id =
+ ((processed_frame->identity >> 16) & 0xFFFF);
+ buff_mgr_info.stream_id =
+ (processed_frame->identity & 0xFFFF);
+ buff_mgr_info.frame_id = processed_frame->frame_id;
+ buff_mgr_info.timestamp = processed_frame->timestamp;
+ buff_mgr_info.index =
+ processed_frame->output_buffer_info.index;
+ rc = msm_cpp_buffer_ops(cpp_dev,
+ VIDIOC_MSM_BUF_MNGR_BUF_DONE,
+ &buff_mgr_info);
+ if (rc < 0) {
+ pr_err("error putting buffer\n");
+ rc = -EINVAL;
+ }
+ }
v4l2_evt.id = processed_frame->inst_id;
v4l2_evt.type = V4L2_EVENT_CPP_FRAME_DONE;
v4l2_event_queue(cpp_dev->msm_sd.sd.devnode, &v4l2_evt);
}
- return 0;
+ return rc;
}
-static int msm_cpp_send_frame_to_hardware(struct cpp_device *cpp_dev)
+static int msm_cpp_send_frame_to_hardware(struct cpp_device *cpp_dev,
+ struct msm_queue_cmd *frame_qcmd)
{
uint32_t i;
- struct msm_queue_cmd *frame_qcmd;
+ int32_t rc = -EAGAIN;
struct msm_cpp_frame_info_t *process_frame;
- struct msm_device_queue *queue;
if (cpp_dev->processing_q.len < MAX_CPP_PROCESSING_FRAME) {
- while (cpp_dev->processing_q.len < MAX_CPP_PROCESSING_FRAME) {
- if (cpp_dev->realtime_q.len != 0) {
- queue = &cpp_dev->realtime_q;
- } else if (cpp_dev->offline_q.len != 0) {
- queue = &cpp_dev->offline_q;
- } else {
- pr_debug("All frames queued\n");
- break;
- }
- frame_qcmd = msm_dequeue(queue, list_frame);
- process_frame = frame_qcmd->command;
- msm_enqueue(&cpp_dev->processing_q,
- &frame_qcmd->list_frame);
- msm_cpp_write(0x6, cpp_dev->base);
- for (i = 0; i < process_frame->msg_len; i++)
- msm_cpp_write(process_frame->cpp_cmd_msg[i],
- cpp_dev->base);
- }
+ process_frame = frame_qcmd->command;
+ msm_enqueue(&cpp_dev->processing_q,
+ &frame_qcmd->list_frame);
+ msm_cpp_write(0x6, cpp_dev->base);
+ for (i = 0; i < process_frame->msg_len; i++)
+ msm_cpp_write(process_frame->cpp_cmd_msg[i],
+ cpp_dev->base);
+ do_gettimeofday(&(process_frame->in_time));
+ rc = 0;
}
- return 0;
+ if (rc < 0)
+ pr_err("process queue full. drop frame\n");
+ return rc;
}
static int msm_cpp_flush_frames(struct cpp_device *cpp_dev)
{
- struct v4l2_event v4l2_evt;
- struct msm_queue_cmd *frame_qcmd;
- struct msm_cpp_frame_info_t *process_frame;
- struct msm_device_queue *queue;
- struct msm_queue_cmd *event_qcmd;
-
- do {
- if (cpp_dev->realtime_q.len != 0) {
- queue = &cpp_dev->realtime_q;
- } else if (cpp_dev->offline_q.len != 0) {
- queue = &cpp_dev->offline_q;
- } else {
- pr_debug("All frames flushed\n");
- break;
- }
- frame_qcmd = msm_dequeue(queue, list_frame);
- process_frame = frame_qcmd->command;
- kfree(frame_qcmd);
- event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_ATOMIC);
- if (!event_qcmd) {
- pr_err("Insufficient memory. return");
- return -ENOMEM;
- }
- atomic_set(&event_qcmd->on_heap, 1);
- event_qcmd->command = process_frame;
- CPP_DBG("fid %d\n", process_frame->frame_id);
- msm_enqueue(&cpp_dev->eventData_q, &event_qcmd->list_eventdata);
-
- v4l2_evt.id = process_frame->inst_id;
- v4l2_evt.type = V4L2_EVENT_CPP_FRAME_DONE;
- v4l2_event_queue(cpp_dev->msm_sd.sd.devnode, &v4l2_evt);
- } while ((cpp_dev->realtime_q.len != 0) ||
- (cpp_dev->offline_q.len != 0));
return 0;
}
@@ -609,9 +951,12 @@
struct msm_cpp_frame_info_t *new_frame =
kzalloc(sizeof(struct msm_cpp_frame_info_t), GFP_KERNEL);
uint32_t *cpp_frame_msg;
- unsigned long len;
unsigned long in_phyaddr, out_phyaddr;
uint16_t num_stripes = 0;
+ struct msm_buf_mngr_info buff_mgr_info;
+ struct msm_cpp_frame_info_t *u_frame_info =
+ (struct msm_cpp_frame_info_t *)ioctl_ptr->ioctl_ptr;
+ int32_t status = 0;
int i = 0;
if (!new_frame) {
@@ -646,44 +991,40 @@
new_frame->cpp_cmd_msg = cpp_frame_msg;
- CPP_DBG("CPP in_fd: %d out_fd: %d\n", new_frame->src_fd,
- new_frame->dst_fd);
-
- new_frame->src_ion_handle = ion_import_dma_buf(cpp_dev->client,
- new_frame->src_fd);
- if (IS_ERR_OR_NULL(new_frame->src_ion_handle)) {
- pr_err("ION import failed\n");
- rc = PTR_ERR(new_frame->src_ion_handle);
+ in_phyaddr = msm_cpp_fetch_buffer_info(cpp_dev,
+ &new_frame->input_buffer_info,
+ ((new_frame->identity >> 16) & 0xFFFF),
+ (new_frame->identity & 0xFFFF));
+ if (!in_phyaddr) {
+ pr_err("error gettting input physical address\n");
+ rc = -EINVAL;
goto ERROR2;
}
- rc = ion_map_iommu(cpp_dev->client, new_frame->src_ion_handle,
- cpp_dev->domain_num, 0, SZ_4K, 0,
- (unsigned long *)&in_phyaddr, &len, 0, 0);
+ memset(&new_frame->output_buffer_info, 0,
+ sizeof(struct msm_cpp_buffer_info_t));
+ memset(&buff_mgr_info, 0, sizeof(struct msm_buf_mngr_info));
+ buff_mgr_info.session_id = ((new_frame->identity >> 16) & 0xFFFF);
+ buff_mgr_info.stream_id = (new_frame->identity & 0xFFFF);
+ rc = msm_cpp_buffer_ops(cpp_dev, VIDIOC_MSM_BUF_MNGR_GET_BUF,
+ &buff_mgr_info);
if (rc < 0) {
- pr_err("ION import failed\n");
- rc = PTR_ERR(new_frame->src_ion_handle);
+ rc = -EAGAIN;
+ pr_err("error getting buffer rc:%d\n", rc);
+ goto ERROR2;
+ }
+
+ new_frame->output_buffer_info.index = buff_mgr_info.index;
+ out_phyaddr = msm_cpp_fetch_buffer_info(cpp_dev,
+ &new_frame->output_buffer_info,
+ ((new_frame->identity >> 16) & 0xFFFF),
+ (new_frame->identity & 0xFFFF));
+ if (!out_phyaddr) {
+ pr_err("error gettting output physical address\n");
+ rc = -EINVAL;
goto ERROR3;
}
- CPP_DBG("in phy addr: 0x%x len: %ld\n", (uint32_t) in_phyaddr, len);
- new_frame->dest_ion_handle = ion_import_dma_buf(cpp_dev->client,
- new_frame->dst_fd);
- if (IS_ERR_OR_NULL(new_frame->dest_ion_handle)) {
- pr_err("ION import failed\n");
- rc = PTR_ERR(new_frame->dest_ion_handle);
- goto ERROR4;
- }
-
- rc = ion_map_iommu(cpp_dev->client, new_frame->dest_ion_handle,
- cpp_dev->domain_num, 0, SZ_4K, 0,
- (unsigned long *)&out_phyaddr, &len, 0, 0);
- if (rc < 0) {
- rc = PTR_ERR(new_frame->dest_ion_handle);
- goto ERROR5;
- }
-
- CPP_DBG("out phy addr: 0x%x len: %ld\n", (uint32_t)out_phyaddr, len);
num_stripes = ((cpp_frame_msg[12] >> 20) & 0x3FF) +
((cpp_frame_msg[12] >> 10) & 0x3FF) +
(cpp_frame_msg[12] & 0x3FF);
@@ -700,44 +1041,43 @@
if (!frame_qcmd) {
pr_err("Insufficient memory. return\n");
rc = -ENOMEM;
- goto ERROR6;
+ goto ERROR3;
}
atomic_set(&frame_qcmd->on_heap, 1);
frame_qcmd->command = new_frame;
- if (new_frame->frame_type == MSM_CPP_REALTIME_FRAME) {
- msm_enqueue(&cpp_dev->realtime_q,
- &frame_qcmd->list_frame);
- } else if (new_frame->frame_type == MSM_CPP_OFFLINE_FRAME) {
- msm_enqueue(&cpp_dev->offline_q,
- &frame_qcmd->list_frame);
- } else {
- pr_err("Invalid frame type\n");
+ rc = msm_cpp_send_frame_to_hardware(cpp_dev, frame_qcmd);
+ if (rc < 0) {
+ pr_err("error cannot send frame to hardware\n");
rc = -EINVAL;
- goto ERROR7;
+ goto ERROR4;
}
- msm_cpp_send_frame_to_hardware(cpp_dev);
+
+ ioctl_ptr->trans_code = rc;
+ status = rc;
+ rc = (copy_to_user((void __user *)u_frame_info->status, &status,
+ sizeof(int32_t)) ? -EFAULT : 0);
+ if (rc) {
+ ERR_COPY_FROM_USER();
+ rc = -EINVAL;
+ goto ERROR4;
+ }
return rc;
-ERROR7:
- kfree(frame_qcmd);
-ERROR6:
- ion_unmap_iommu(cpp_dev->client, new_frame->dest_ion_handle,
- cpp_dev->domain_num, 0);
-ERROR5:
- ion_free(cpp_dev->client, new_frame->dest_ion_handle);
- new_frame->dest_ion_handle = NULL;
ERROR4:
- ion_unmap_iommu(cpp_dev->client, new_frame->src_ion_handle,
- cpp_dev->domain_num, 0);
+ kfree(frame_qcmd);
ERROR3:
- ion_free(cpp_dev->client, new_frame->src_ion_handle);
- new_frame->src_ion_handle = NULL;
+ msm_cpp_buffer_ops(cpp_dev, VIDIOC_MSM_BUF_MNGR_PUT_BUF,
+ &buff_mgr_info);
ERROR2:
kfree(cpp_frame_msg);
ERROR1:
kfree(new_frame);
+ ioctl_ptr->trans_code = rc;
+ status = rc;
+ if (copy_to_user((void __user *)u_frame_info->status, &status,
+ sizeof(int32_t)))
+ pr_err("error cannot copy error\n");
return rc;
-
}
long msm_cpp_subdev_ioctl(struct v4l2_subdev *sd,
@@ -795,6 +1135,97 @@
case VIDIOC_MSM_CPP_FLUSH_QUEUE:
rc = msm_cpp_flush_frames(cpp_dev);
break;
+ case VIDIOC_MSM_CPP_ENQUEUE_STREAM_BUFF_INFO: {
+ struct msm_cpp_stream_buff_info_t *u_stream_buff_info;
+ struct msm_cpp_stream_buff_info_t k_stream_buff_info;
+ if (sizeof(struct msm_cpp_stream_buff_info_t) !=
+ ioctl_ptr->len) {
+ pr_err("%s:%d: invalid length\n", __func__, __LINE__);
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+
+ u_stream_buff_info = kzalloc(ioctl_ptr->len, GFP_KERNEL);
+ if (!u_stream_buff_info) {
+ pr_err("%s:%d: malloc error\n", __func__, __LINE__);
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+
+ rc = (copy_from_user(u_stream_buff_info,
+ (void __user *)ioctl_ptr->ioctl_ptr,
+ ioctl_ptr->len) ? -EFAULT : 0);
+ if (rc) {
+ ERR_COPY_FROM_USER();
+ kfree(u_stream_buff_info);
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+
+ k_stream_buff_info.num_buffs = u_stream_buff_info->num_buffs;
+ k_stream_buff_info.identity = u_stream_buff_info->identity;
+ k_stream_buff_info.buffer_info =
+ kzalloc(k_stream_buff_info.num_buffs *
+ sizeof(struct msm_cpp_buffer_info_t), GFP_KERNEL);
+ if (!k_stream_buff_info.buffer_info) {
+ pr_err("%s:%d: malloc error\n", __func__, __LINE__);
+ kfree(u_stream_buff_info);
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+
+ rc = (copy_from_user(k_stream_buff_info.buffer_info,
+ (void __user *)u_stream_buff_info->buffer_info,
+ k_stream_buff_info.num_buffs *
+ sizeof(struct msm_cpp_buffer_info_t)) ?
+ -EFAULT : 0);
+ if (rc) {
+ ERR_COPY_FROM_USER();
+ kfree(k_stream_buff_info.buffer_info);
+ kfree(u_stream_buff_info);
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+
+ rc = msm_cpp_add_buff_queue_entry(cpp_dev,
+ ((k_stream_buff_info.identity >> 16) & 0xFFFF),
+ (k_stream_buff_info.identity & 0xFFFF));
+ if (!rc)
+ rc = msm_cpp_enqueue_buff_info_list(cpp_dev,
+ &k_stream_buff_info);
+
+ kfree(k_stream_buff_info.buffer_info);
+ kfree(u_stream_buff_info);
+ break;
+ }
+ case VIDIOC_MSM_CPP_DEQUEUE_STREAM_BUFF_INFO: {
+ uint32_t identity;
+ struct msm_cpp_buff_queue_info_t *buff_queue_info;
+
+ rc = (copy_from_user(&identity,
+ (void __user *)ioctl_ptr->ioctl_ptr,
+ ioctl_ptr->len) ? -EFAULT : 0);
+ if (rc) {
+ ERR_COPY_FROM_USER();
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+
+ buff_queue_info = msm_cpp_get_buff_queue_entry(cpp_dev,
+ ((identity >> 16) & 0xFFFF), (identity & 0xFFFF));
+ if (buff_queue_info == NULL) {
+ pr_err("error finding buffer queue entry for identity:%d\n",
+ identity);
+ mutex_unlock(&cpp_dev->mutex);
+ return -EINVAL;
+ }
+
+ msm_cpp_dequeue_buff_info_list(cpp_dev, buff_queue_info);
+ rc = msm_cpp_free_buff_queue_entry(cpp_dev,
+ buff_queue_info->session_id,
+ buff_queue_info->stream_id);
+ break;
+ }
case VIDIOC_MSM_CPP_GET_EVENTPAYLOAD: {
struct msm_device_queue *queue = &cpp_dev->eventData_q;
struct msm_queue_cmd *event_qcmd;
@@ -808,23 +1239,6 @@
mutex_unlock(&cpp_dev->mutex);
return -EINVAL;
}
- if (process_frame->dest_ion_handle) {
- ion_unmap_iommu(cpp_dev->client,
- process_frame->dest_ion_handle,
- cpp_dev->domain_num, 0);
- ion_free(cpp_dev->client,
- process_frame->dest_ion_handle);
- process_frame->dest_ion_handle = NULL;
- }
-
- if (process_frame->src_ion_handle) {
- ion_unmap_iommu(cpp_dev->client,
- process_frame->src_ion_handle,
- cpp_dev->domain_num, 0);
- ion_free(cpp_dev->client,
- process_frame->src_ion_handle);
- process_frame->src_ion_handle = NULL;
- }
kfree(process_frame->cpp_cmd_msg);
kfree(process_frame);
@@ -834,7 +1248,7 @@
}
mutex_unlock(&cpp_dev->mutex);
CPP_DBG("X\n");
- return 0;
+ return rc;
}
int msm_cpp_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
@@ -861,8 +1275,6 @@
.core = &msm_cpp_subdev_core_ops,
};
-static int msm_cpp_enable_debugfs(struct cpp_device *cpp_dev);
-
static struct v4l2_file_operations msm_cpp_v4l2_subdev_fops;
static long msm_cpp_subdev_do_ioctl(
@@ -960,6 +1372,7 @@
v4l2_set_subdevdata(&cpp_dev->msm_sd.sd, cpp_dev);
platform_set_drvdata(pdev, &cpp_dev->msm_sd.sd);
mutex_init(&cpp_dev->mutex);
+ spin_lock_init(&cpp_dev->tasklet_lock);
if (pdev->dev.of_node)
of_property_read_u32((&pdev->dev)->of_node,
@@ -1054,14 +1467,13 @@
cpp_release_hardware(cpp_dev);
cpp_dev->state = CPP_STATE_OFF;
- msm_cpp_enable_debugfs(cpp_dev);
msm_queue_init(&cpp_dev->eventData_q, "eventdata");
- msm_queue_init(&cpp_dev->offline_q, "frame");
- msm_queue_init(&cpp_dev->realtime_q, "frame");
msm_queue_init(&cpp_dev->processing_q, "frame");
+ INIT_LIST_HEAD(&cpp_dev->tasklet_q);
+ tasklet_init(&cpp_dev->cpp_tasklet, msm_cpp_do_tasklet,
+ (unsigned long)cpp_dev);
cpp_dev->cpp_open_cnt = 0;
cpp_dev->is_firmware_loaded = 0;
-
return rc;
ERROR3:
@@ -1126,65 +1538,6 @@
platform_driver_unregister(&cpp_driver);
}
-static int msm_cpp_debugfs_stream_s(void *data, u64 val)
-{
- struct cpp_device *cpp_dev = data;
- CPP_DBG("CPP processing frame E\n");
- while (1) {
- mutex_lock(&cpp_dev->mutex);
- msm_cpp_notify_frame_done(cpp_dev);
- msm_cpp_send_frame_to_hardware(cpp_dev);
- mutex_unlock(&cpp_dev->mutex);
- msleep(20);
- }
- CPP_DBG("CPP processing frame X\n");
- return 0;
-}
-
-static int msm_cpp_debugfs_load_fw(void *data, u64 val)
-{
- const struct firmware *fw = NULL;
- struct cpp_device *cpp_dev = data;
- int rc = 0;
- CPP_DBG("%s\n", __func__);
- rc = request_firmware(&fw, "FIRMWARE.bin", &cpp_dev->pdev->dev);
- if (rc) {
- pr_err("request_fw failed\n");
- } else {
- CPP_DBG("request ok\n");
- release_firmware(fw);
- }
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(cpp_debugfs_stream, NULL,
- msm_cpp_debugfs_stream_s, "%llu\n");
-DEFINE_SIMPLE_ATTRIBUTE(cpp_debugfs_fw, NULL,
- msm_cpp_debugfs_load_fw, "%llu\n");
-
-static int msm_cpp_enable_debugfs(struct cpp_device *cpp_dev)
-{
- struct dentry *debugfs_base, *debugfs_test;
- debugfs_base = debugfs_create_dir("msm_camera", NULL);
- if (!debugfs_base)
- return -ENOMEM;
-
- debugfs_test = debugfs_create_file("test", S_IRUGO | S_IWUSR,
- debugfs_base, (void *)cpp_dev, &cpp_debugfs_stream);
- if (!debugfs_test) {
- debugfs_remove(debugfs_base);
- return -ENOMEM;
- }
-
- if (!debugfs_create_file("fw", S_IRUGO | S_IWUSR, debugfs_base,
- (void *)cpp_dev, &cpp_debugfs_fw)) {
- debugfs_remove(debugfs_test);
- debugfs_remove(debugfs_base);
- return -ENOMEM;
- }
- return 0;
-}
-
module_init(msm_cpp_init_module);
module_exit(msm_cpp_exit_module);
MODULE_DESCRIPTION("MSM CPP driver");
diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
index 0c586ca..36a5fa5 100644
--- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
+++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.h
@@ -17,6 +17,7 @@
#include <linux/io.h>
#include <linux/list.h>
#include <linux/platform_device.h>
+#include <linux/interrupt.h>
#include <media/v4l2-subdev.h>
#include "msm_sd.h"
@@ -70,6 +71,8 @@
#define MSM_CPP_END_ADDRESS 0x3F00
#define MSM_CPP_POLL_RETRIES 20
+#define MSM_CPP_TASKLETQ_SIZE 16
+#define MSM_CPP_TX_FIFO_LEVEL 16
struct cpp_subscribe_info {
struct v4l2_fh *vfh;
@@ -116,6 +119,34 @@
const char *name;
};
+struct msm_cpp_tasklet_queue_cmd {
+ struct list_head list;
+ uint32_t irq_status;
+ uint32_t tx_fifo[MSM_CPP_TX_FIFO_LEVEL];
+ uint32_t tx_level;
+ uint8_t cmd_used;
+};
+
+struct msm_cpp_buffer_map_info_t {
+ unsigned long len;
+ unsigned long phy_addr;
+ struct ion_handle *ion_handle;
+ struct msm_cpp_buffer_info_t buff_info;
+};
+
+struct msm_cpp_buffer_map_list_t {
+ struct msm_cpp_buffer_map_info_t map_info;
+ struct list_head entry;
+};
+
+struct msm_cpp_buff_queue_info_t {
+ uint32_t used;
+ uint16_t session_id;
+ uint16_t stream_id;
+ struct list_head vb2_buff_head;
+ struct list_head native_buff_head;
+};
+
struct cpp_device {
struct platform_device *pdev;
struct msm_sd_subdev msm_sd;
@@ -141,19 +172,28 @@
struct ion_client *client;
struct kref refcount;
+ /* Reusing proven tasklet from msm isp */
+ atomic_t irq_cnt;
+ uint8_t taskletq_idx;
+ spinlock_t tasklet_lock;
+ struct list_head tasklet_q;
+ struct tasklet_struct cpp_tasklet;
+ struct msm_cpp_tasklet_queue_cmd
+ tasklet_queue_cmd[MSM_CPP_TASKLETQ_SIZE];
+
struct cpp_subscribe_info cpp_subscribe_list[MAX_ACTIVE_CPP_INSTANCE];
uint32_t cpp_open_cnt;
struct cpp_hw_info hw_info;
struct msm_device_queue eventData_q; /* V4L2 Event Payload Queue */
- /* Offline Frame Queue process when realtime queue is empty */
- struct msm_device_queue offline_q;
- /* Realtime Frame Queue process with highest priority */
- struct msm_device_queue realtime_q;
/* Processing Queue
* store frame info for frames sent to microcontroller
*/
struct msm_device_queue processing_q;
+
+ struct msm_cpp_buff_queue_info_t *buff_queue;
+ uint32_t num_buffq;
+ struct v4l2_subdev *buf_mgr_subdev;
};
#endif /* __MSM_CPP_H__ */
diff --git a/drivers/media/platform/msm/camera_v2/sensor/Makefile b/drivers/media/platform/msm/camera_v2/sensor/Makefile
index b6708a3..5104bcb 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/Makefile
+++ b/drivers/media/platform/msm/camera_v2/sensor/Makefile
@@ -3,7 +3,7 @@
ccflags-y += -Idrivers/media/platform/msm/camera_v2/camera
ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/cci
-obj-$(CONFIG_MSMB_CAMERA) += cci/ io/ csiphy/ csid/ actuator/ flash/
+obj-$(CONFIG_MSMB_CAMERA) += cci/ io/ csiphy/ csid/ actuator/ flash/ eeprom/
obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
obj-$(CONFIG_S5K3L1YX) += s5k3l1yx.o
obj-$(CONFIG_IMX135) += imx135.o
diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c
index 12ac4cb..9300ce0 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
@@ -39,6 +39,9 @@
#define CDBG(fmt, args...) do { } while (0)
#endif
+/* Max bytes that can be read per CCI read transaction */
+#define CCI_READ_MAX 12
+
static struct v4l2_subdev *g_cci_subdev;
static void msm_cci_set_clk_param(struct cci_device *cci_dev)
@@ -377,6 +380,61 @@
return rc;
}
+static int32_t msm_cci_i2c_read_bytes(struct v4l2_subdev *sd,
+ struct msm_camera_cci_ctrl *c_ctrl)
+{
+ int32_t rc = 0;
+ struct cci_device *cci_dev = NULL;
+ enum cci_i2c_master_t master;
+ struct msm_camera_cci_i2c_read_cfg *read_cfg = NULL;
+ uint16_t read_bytes = 0;
+
+ if (!sd || !c_ctrl) {
+ pr_err("%s:%d sd %p c_ctrl %p\n", __func__,
+ __LINE__, sd, c_ctrl);
+ return -EINVAL;
+ }
+ if (!c_ctrl->cci_info) {
+ pr_err("%s:%d cci_info NULL\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+ cci_dev = v4l2_get_subdevdata(sd);
+ if (!cci_dev) {
+ pr_err("%s:%d cci_dev NULL\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ master = c_ctrl->cci_info->cci_i2c_master;
+ read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg;
+ if (!read_cfg->num_byte) {
+ pr_err("%s:%d read num bytes 0\n", __func__, __LINE__);
+ rc = -EINVAL;
+ goto ERROR;
+ }
+
+ read_bytes = read_cfg->num_byte;
+ do {
+ if (read_bytes > CCI_READ_MAX)
+ read_cfg->num_byte = CCI_READ_MAX;
+ else
+ read_cfg->num_byte = read_bytes;
+ rc = msm_cci_i2c_read(sd, c_ctrl);
+ if (rc < 0) {
+ pr_err("%s:%d failed rc %d\n", __func__, __LINE__, rc);
+ goto ERROR;
+ }
+ if (read_bytes > CCI_READ_MAX) {
+ read_cfg->addr += CCI_READ_MAX;
+ read_cfg->data += CCI_READ_MAX;
+ read_bytes -= CCI_READ_MAX;
+ } else {
+ read_bytes = 0;
+ }
+ } while (read_bytes);
+ERROR:
+ return rc;
+}
+
static int32_t msm_cci_i2c_write(struct v4l2_subdev *sd,
struct msm_camera_cci_ctrl *c_ctrl)
{
@@ -589,7 +647,7 @@
rc = msm_cci_i2c_config_sync_timer(sd, cci_ctrl);
break;
case MSM_CCI_I2C_READ:
- rc = msm_cci_i2c_read(sd, cci_ctrl);
+ rc = msm_cci_i2c_read_bytes(sd, cci_ctrl);
break;
case MSM_CCI_I2C_WRITE:
rc = msm_cci_i2c_write(sd, cci_ctrl);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
index 0df0488..fbd4a2e 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
@@ -24,7 +24,7 @@
#define CSID_VERSION_V3 0x30000000
#define MSM_CSID_DRV_NAME "msm_csid"
-#define DBG_CSID 1
+#define DBG_CSID 0
#define TRUE 1
#define FALSE 0
@@ -36,8 +36,6 @@
#define CDBG(fmt, args...) do { } while (0)
#endif
-static uint32_t irq_count;
-
static int msm_csid_cid_lut(
struct msm_camera_csid_lut_params *csid_lut_params,
void __iomem *csidbase)
@@ -84,8 +82,8 @@
{
uint32_t val = 0;
val = ((1 << csid_params->lane_cnt) - 1) << 20;
- msm_camera_io_w(0x7f010801 | val, csidbase + CSID_IRQ_MASK_ADDR);
- msm_camera_io_w(0x7f010801 | val, csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
+ msm_camera_io_w(0x7f010800 | val, csidbase + CSID_IRQ_MASK_ADDR);
+ msm_camera_io_w(0x7f010800 | val, csidbase + CSID_IRQ_CLEAR_CMD_ADDR);
}
#else
static void msm_csid_set_debug_reg(void __iomem *csidbase,
@@ -94,11 +92,8 @@
static void msm_csid_reset(struct csid_device *csid_dev)
{
- CDBG("%s:%d called\n", __func__, __LINE__);
msm_camera_io_w(CSID_RST_STB_ALL, csid_dev->base + CSID_RST_CMD_ADDR);
- CDBG("%s:%d called\n", __func__, __LINE__);
wait_for_completion_interruptible(&csid_dev->reset_complete);
- CDBG("%s:%d called\n", __func__, __LINE__);
return;
}
@@ -159,11 +154,6 @@
__func__, csid_dev->pdev->id, irq);
if (irq & (0x1 << CSID_RST_DONE_IRQ_BITSHIFT))
complete(&csid_dev->reset_complete);
- if (irq & 0x1) {
- pr_debug("%s CSID%d_IRQ_STATUS_ADDR = 0x%x\n",
- __func__, csid_dev->pdev->id, irq);
- irq_count++;
- }
msm_camera_io_w(irq, csid_dev->base + CSID_IRQ_CLEAR_CMD_ADDR);
return IRQ_HANDLED;
}
@@ -253,13 +243,11 @@
int rc = 0;
uint8_t core_id = 0;
- CDBG("%s:%d called\n", __func__, __LINE__);
if (!csid_version) {
pr_err("%s:%d csid_version NULL\n", __func__, __LINE__);
rc = -EINVAL;
return rc;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
if (csid_dev->csid_state == CSID_POWER_UP) {
pr_err("%s: csid invalid state %d\n", __func__,
@@ -267,7 +255,6 @@
rc = -EINVAL;
return rc;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
csid_dev->base = ioremap(csid_dev->mem->start,
resource_size(csid_dev->mem));
@@ -276,10 +263,8 @@
rc = -ENOMEM;
return rc;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
if (CSID_VERSION <= CSID_VERSION_V2) {
- CDBG("%s:%d called\n", __func__, __LINE__);
rc = msm_camera_config_vreg(&csid_dev->pdev->dev,
csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
NULL, 0, &csid_dev->csi_vdd, 1);
@@ -287,7 +272,6 @@
pr_err("%s: regulator on failed\n", __func__);
goto vreg_config_failed;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
rc = msm_camera_enable_vreg(&csid_dev->pdev->dev,
csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
@@ -296,7 +280,6 @@
pr_err("%s: regulator enable failed\n", __func__);
goto vreg_enable_failed;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
csid_8960_clk_info, csid_dev->csid_clk,
@@ -305,9 +288,7 @@
pr_err("%s: clock enable failed\n", __func__);
goto clk_enable_failed;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
} else if (CSID_VERSION >= CSID_VERSION_V3) {
- CDBG("%s:%d called\n", __func__, __LINE__);
rc = msm_camera_config_vreg(&csid_dev->pdev->dev,
csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
NULL, 0, &csid_dev->csi_vdd, 1);
@@ -315,7 +296,6 @@
pr_err("%s: regulator on failed\n", __func__);
goto vreg_config_failed;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
rc = msm_camera_enable_vreg(&csid_dev->pdev->dev,
csid_vreg_info, ARRAY_SIZE(csid_vreg_info),
@@ -324,7 +304,6 @@
pr_err("%s: regulator enable failed\n", __func__);
goto vreg_enable_failed;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
csid_8974_clk_info[0].clk_info, csid_dev->csid0_clk,
@@ -333,10 +312,8 @@
pr_err("%s: clock enable failed\n", __func__);
goto csid0_clk_enable_failed;
}
- CDBG("%s:%d called\n", __func__, __LINE__);
core_id = csid_dev->pdev->id;
if (core_id) {
- CDBG("%s:%d called\n", __func__, __LINE__);
rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
csid_8974_clk_info[core_id].clk_info,
csid_dev->csid_clk,
@@ -348,7 +325,6 @@
}
}
}
- CDBG("%s:%d called\n", __func__, __LINE__);
csid_dev->hw_version =
msm_camera_io_r(csid_dev->base + CSID_HW_VERSION_ADDR);
@@ -356,17 +332,12 @@
csid_dev->hw_version);
*csid_version = csid_dev->hw_version;
- CDBG("%s:%d called\n", __func__, __LINE__);
init_completion(&csid_dev->reset_complete);
- CDBG("%s:%d called\n", __func__, __LINE__);
enable_irq(csid_dev->irq->start);
- CDBG("%s:%d called\n", __func__, __LINE__);
msm_csid_reset(csid_dev);
- CDBG("%s:%d called\n", __func__, __LINE__);
csid_dev->csid_state = CSID_POWER_UP;
- irq_count = 0;
return rc;
clk_enable_failed:
@@ -578,7 +549,6 @@
struct csid_device *new_csid_dev;
uint32_t csi_vdd_voltage = 0;
int rc = 0;
- CDBG("%s:%d called\n", __func__, __LINE__);
new_csid_dev = kzalloc(sizeof(struct csid_device), GFP_KERNEL);
if (!new_csid_dev) {
pr_err("%s: no enough memory\n", __func__);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/Makefile b/drivers/media/platform/msm/camera_v2/sensor/eeprom/Makefile
new file mode 100644
index 0000000..de843fb
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/Makefile
@@ -0,0 +1,4 @@
+ccflags-y += -Idrivers/media/platform/msm/camera_v2
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/cci
+obj-$(CONFIG_MSM_EEPROM) += msm_eeprom.o
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
new file mode 100644
index 0000000..47e672d
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
@@ -0,0 +1,932 @@
+/* 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/delay.h>
+#include "msm_sd.h"
+#include "msm_cci.h"
+#include "msm_eeprom.h"
+
+#undef CDBG
+#ifdef MSM_EEPROM_DEBUG
+#define CDBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#endif
+
+DEFINE_MSM_MUTEX(msm_eeprom_mutex);
+
+int32_t msm_eeprom_config(struct msm_eeprom_ctrl_t *e_ctrl,
+ void __user *argp)
+{
+ struct msm_eeprom_cfg_data *cdata =
+ (struct msm_eeprom_cfg_data *)argp;
+ int32_t rc = 0;
+
+ CDBG("%s E\n", __func__);
+ switch (cdata->cfgtype) {
+ case CFG_EEPROM_GET_INFO:
+ CDBG("%s E CFG_EEPROM_GET_INFO\n", __func__);
+ cdata->is_supported = e_ctrl->is_supported;
+ memcpy(cdata->cfg.eeprom_name,
+ e_ctrl->eboard_info->eeprom_name,
+ sizeof(cdata->cfg.eeprom_name));
+ break;
+ case CFG_EEPROM_GET_DATA:
+ CDBG("%s E CFG_EEPROM_GET_DATA\n", __func__);
+ cdata->cfg.get_data.num_bytes =
+ e_ctrl->num_bytes;
+ break;
+ case CFG_EEPROM_READ_DATA:
+ CDBG("%s E CFG_EEPROM_READ_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;
+ }
+
+ CDBG("%s X\n", __func__);
+ return rc;
+}
+static int32_t msm_eeprom_get_subdev_id(
+ struct msm_eeprom_ctrl_t *e_ctrl, void *arg)
+{
+ uint32_t *subdev_id = (uint32_t *)arg;
+ CDBG("%s E\n", __func__);
+ if (!subdev_id) {
+ pr_err("%s failed\n", __func__);
+ return -EINVAL;
+ }
+ *subdev_id = e_ctrl->subdev_id;
+ CDBG("subdev_id %d\n", *subdev_id);
+ CDBG("%s X\n", __func__);
+ return 0;
+}
+
+static long msm_eeprom_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ struct msm_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd);
+ void __user *argp = (void __user *)arg;
+ CDBG("%s E\n", __func__);
+ CDBG("%s:%d a_ctrl %p argp %p\n", __func__, __LINE__, e_ctrl, argp);
+ switch (cmd) {
+ case VIDIOC_MSM_SENSOR_GET_SUBDEV_ID:
+ return msm_eeprom_get_subdev_id(e_ctrl, argp);
+ case VIDIOC_MSM_EEPROM_CFG:
+ return msm_eeprom_config(e_ctrl, argp);
+ default:
+ return -ENOIOCTLCMD;
+ }
+
+ CDBG("%s X\n", __func__);
+}
+
+static struct msm_camera_i2c_fn_t msm_eeprom_cci_func_tbl = {
+ .i2c_read = msm_camera_cci_i2c_read,
+ .i2c_read_seq = msm_camera_cci_i2c_read_seq,
+ .i2c_write = msm_camera_cci_i2c_write,
+ .i2c_write_table = msm_camera_cci_i2c_write_table,
+ .i2c_write_seq_table = msm_camera_cci_i2c_write_seq_table,
+ .i2c_write_table_w_microdelay =
+ msm_camera_cci_i2c_write_table_w_microdelay,
+ .i2c_util = msm_sensor_cci_i2c_util,
+ .i2c_poll = msm_camera_cci_i2c_poll,
+};
+
+static struct msm_camera_i2c_fn_t msm_eeprom_qup_func_tbl = {
+ .i2c_read = msm_camera_qup_i2c_read,
+ .i2c_read_seq = msm_camera_qup_i2c_read_seq,
+ .i2c_write = msm_camera_qup_i2c_write,
+ .i2c_write_table = msm_camera_qup_i2c_write_table,
+ .i2c_write_seq_table = msm_camera_qup_i2c_write_seq_table,
+ .i2c_write_table_w_microdelay =
+ msm_camera_qup_i2c_write_table_w_microdelay,
+};
+
+static struct msm_camera_i2c_fn_t msm_eeprom_spi_func_tbl = {
+ .i2c_read = msm_camera_spi_read,
+ .i2c_read_seq = msm_camera_spi_read_seq,
+};
+
+static int msm_eeprom_open(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh) {
+ int rc = 0;
+ struct msm_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd);
+ CDBG("%s E\n", __func__);
+ if (!e_ctrl) {
+ pr_err("%s failed e_ctrl is NULL\n", __func__);
+ return -EINVAL;
+ }
+ if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+ rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_util(
+ &e_ctrl->i2c_client, MSM_CCI_INIT);
+ if (rc < 0)
+ pr_err("%s cci_init failed\n", __func__);
+ }
+ CDBG("%s X\n", __func__);
+ return rc;
+}
+
+static int msm_eeprom_close(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh) {
+ int rc = 0;
+ struct msm_eeprom_ctrl_t *e_ctrl = v4l2_get_subdevdata(sd);
+ CDBG("%s E\n", __func__);
+ if (!e_ctrl) {
+ pr_err("%s failed e_ctrl is NULL\n", __func__);
+ return -EINVAL;
+ }
+ if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+ rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_util(
+ &e_ctrl->i2c_client, MSM_CCI_RELEASE);
+ if (rc < 0)
+ pr_err("%s cci_init failed\n", __func__);
+ }
+ CDBG("%s X\n", __func__);
+ return rc;
+}
+
+static const struct v4l2_subdev_internal_ops msm_eeprom_internal_ops = {
+ .open = msm_eeprom_open,
+ .close = msm_eeprom_close,
+};
+
+int32_t read_eeprom_memory(struct msm_eeprom_ctrl_t *e_ctrl)
+{
+ int rc = 0;
+ int j;
+ uint8_t *memptr = NULL;
+ struct msm_eeprom_board_info *eb_info = NULL;
+ struct eeprom_memory_map_t *emap = NULL;
+ if (!e_ctrl) {
+ pr_err("%s e_ctrl is NULL", __func__);
+ rc = -1;
+ return rc;
+ }
+ memptr = e_ctrl->memory_data;
+ eb_info = e_ctrl->eboard_info;
+ emap = eb_info->eeprom_map;
+
+ for (j = 0; j < eb_info->num_blocks; j++) {
+ if (emap[j].page.valid_size) {
+ e_ctrl->i2c_client.addr_type = emap[j].page.addr_t;
+ rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_write(
+ &(e_ctrl->i2c_client), emap[j].page.addr,
+ emap[j].page.data, emap[j].page.data_t);
+ msleep(emap[j].page.delay);
+ if (rc < 0) {
+ pr_err("%s: page write failed\n", __func__);
+ return rc;
+ }
+ }
+
+ if (emap[j].poll.valid_size) {
+ e_ctrl->i2c_client.addr_type = emap[j].poll.addr_t;
+ rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_poll(
+ &(e_ctrl->i2c_client), emap[j].poll.addr,
+ emap[j].poll.data, emap[j].poll.data_t);
+ msleep(emap[j].poll.delay);
+ if (rc < 0) {
+ pr_err("%s: poll failed\n", __func__);
+ return rc;
+ }
+ }
+
+ if (emap[j].mem.valid_size) {
+ e_ctrl->i2c_client.addr_type = emap[j].mem.addr_t;
+ rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_read_seq(
+ &(e_ctrl->i2c_client), emap[j].mem.addr,
+ memptr, emap[j].mem.valid_size);
+ if (rc < 0) {
+ pr_err("%s: read failed\n", __func__);
+ return rc;
+ }
+ memptr += emap[j].mem.valid_size;
+ }
+ }
+ return rc;
+}
+
+static int msm_eeprom_alloc_memory_map(struct msm_eeprom_ctrl_t *e_ctrl,
+ struct device_node *of)
+{
+ int i, rc = 0;
+ char property[12];
+ uint32_t count = 6;
+ struct msm_eeprom_board_info *eb = e_ctrl->eboard_info;
+
+ rc = of_property_read_u32(of, "qcom,num-blocks", &eb->num_blocks);
+ CDBG("%s: qcom,num_blocks %d\n", __func__, eb->num_blocks);
+ if (rc < 0) {
+ pr_err("%s failed rc %d\n", __func__, rc);
+ return rc;
+ }
+
+ eb->eeprom_map = kzalloc((sizeof(struct eeprom_memory_map_t)
+ * eb->num_blocks), GFP_KERNEL);
+
+ if (!eb->eeprom_map) {
+ pr_err("%s failed line %d\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < eb->num_blocks; i++) {
+ snprintf(property, 12, "qcom,page%d", i);
+ rc = of_property_read_u32_array(of, property,
+ (uint32_t *) &eb->eeprom_map[i].page, count);
+ if (rc < 0) {
+ pr_err("%s: failed %d\n", __func__, __LINE__);
+ goto out;
+ }
+
+ snprintf(property, 12, "qcom,poll%d", i);
+ rc = of_property_read_u32_array(of, property,
+ (uint32_t *) &eb->eeprom_map[i].poll, count);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto out;
+ }
+
+ snprintf(property, 12, "qcom,mem%d", i);
+ rc = of_property_read_u32_array(of, property,
+ (uint32_t *) &eb->eeprom_map[i].mem, count);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto out;
+ }
+ e_ctrl->num_bytes += eb->eeprom_map[i].mem.valid_size;
+ }
+
+ CDBG("%s num_bytes %d\n", __func__, e_ctrl->num_bytes);
+
+ e_ctrl->memory_data = kzalloc(e_ctrl->num_bytes, GFP_KERNEL);
+ if (!e_ctrl->memory_data) {
+ pr_err("%s failed line %d\n", __func__, __LINE__);
+ rc = -ENOMEM;
+ goto out;
+ }
+ return rc;
+
+out:
+ kfree(eb->eeprom_map);
+ return rc;
+}
+
+static struct msm_cam_clk_info cam_8960_clk_info[] = {
+ [SENSOR_CAM_MCLK] = {"cam_clk", 24000000},
+};
+
+static struct msm_cam_clk_info cam_8974_clk_info[] = {
+ [SENSOR_CAM_MCLK] = {"cam_src_clk", 19200000},
+ [SENSOR_CAM_CLK] = {"cam_clk", 0},
+};
+
+static struct v4l2_subdev_core_ops msm_eeprom_subdev_core_ops = {
+ .ioctl = msm_eeprom_subdev_ioctl,
+};
+
+static struct v4l2_subdev_ops msm_eeprom_subdev_ops = {
+ .core = &msm_eeprom_subdev_core_ops,
+};
+
+int32_t msm_eeprom_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id) {
+ int rc = 0;
+ struct msm_eeprom_ctrl_t *e_ctrl = NULL;
+ struct msm_camera_power_ctrl_t *power_info = NULL;
+ CDBG("%s E\n", __func__);
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ pr_err("%s i2c_check_functionality failed\n", __func__);
+ goto probe_failure;
+ }
+
+ e_ctrl = kzalloc(sizeof(struct msm_eeprom_ctrl_t), GFP_KERNEL);
+ if (!e_ctrl) {
+ pr_err("%s:%d kzalloc failed\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+ e_ctrl->eeprom_v4l2_subdev_ops = &msm_eeprom_subdev_ops;
+ e_ctrl->eeprom_mutex = &msm_eeprom_mutex;
+ CDBG("%s client = %x\n", __func__, (unsigned int)client);
+ e_ctrl->eboard_info = (struct msm_eeprom_board_info *)(id->driver_data);
+ if (!e_ctrl->eboard_info) {
+ pr_err("%s:%d board info NULL\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+ power_info = &e_ctrl->eboard_info->power_info;
+ e_ctrl->i2c_client.client = client;
+
+ /* Set device type as I2C */
+ e_ctrl->eeprom_device_type = MSM_CAMERA_I2C_DEVICE;
+ e_ctrl->i2c_client.i2c_func_tbl = &msm_eeprom_qup_func_tbl;
+
+ if (e_ctrl->eboard_info->i2c_slaveaddr != 0)
+ e_ctrl->i2c_client.client->addr =
+ e_ctrl->eboard_info->i2c_slaveaddr;
+ power_info->clk_info = cam_8960_clk_info;
+ power_info->clk_info_size = ARRAY_SIZE(cam_8960_clk_info);
+ power_info->dev = &client->dev;
+
+ /*IMPLEMENT READING PART*/
+ /* Initialize sub device */
+ v4l2_i2c_subdev_init(&e_ctrl->msm_sd.sd,
+ e_ctrl->i2c_client.client,
+ e_ctrl->eeprom_v4l2_subdev_ops);
+ v4l2_set_subdevdata(&e_ctrl->msm_sd.sd, e_ctrl);
+ e_ctrl->msm_sd.sd.internal_ops = &msm_eeprom_internal_ops;
+ e_ctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ media_entity_init(&e_ctrl->msm_sd.sd.entity, 0, NULL, 0);
+ e_ctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+ e_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_EEPROM;
+ msm_sd_register(&e_ctrl->msm_sd);
+ CDBG("%s success result=%d X\n", __func__, rc);
+ return rc;
+
+probe_failure:
+ pr_err("%s failed! rc = %d\n", __func__, rc);
+ return rc;
+}
+
+static int32_t msm_eeprom_i2c_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+ struct msm_eeprom_ctrl_t *e_ctrl;
+ if (!sd) {
+ pr_err("%s: Subdevice is NULL\n", __func__);
+ return 0;
+ }
+
+ e_ctrl = (struct msm_eeprom_ctrl_t *)v4l2_get_subdevdata(sd);
+ if (!e_ctrl) {
+ pr_err("%s: eeprom device is NULL\n", __func__);
+ return 0;
+ }
+
+ kfree(e_ctrl->memory_data);
+ if (e_ctrl->eboard_info) {
+ kfree(e_ctrl->eboard_info->power_info.gpio_conf);
+ kfree(e_ctrl->eboard_info->eeprom_map);
+ }
+ kfree(e_ctrl->eboard_info);
+ kfree(e_ctrl);
+ return 0;
+}
+
+#define msm_eeprom_spi_parse_cmd(spic, str, name, out, size) \
+ { \
+ if (of_property_read_u32_array( \
+ spic->spi_master->dev.of_node, \
+ str, out, size)) { \
+ return -EFAULT; \
+ } else { \
+ spic->cmd_tbl.name.opcode = out[0]; \
+ spic->cmd_tbl.name.addr_len = out[1]; \
+ spic->cmd_tbl.name.dummy_len = out[2]; \
+ } \
+ }
+
+static int msm_eeprom_spi_parse_of(struct msm_camera_spi_client *spic)
+{
+ int rc = -EFAULT;
+ uint32_t tmp[3];
+ msm_eeprom_spi_parse_cmd(spic, "qcom,spiop,read", read, tmp, 3);
+ msm_eeprom_spi_parse_cmd(spic, "qcom,spiop,readseq", read_seq, tmp, 3);
+ msm_eeprom_spi_parse_cmd(spic, "qcom,spiop,queryid", query_id, tmp, 3);
+
+ rc = of_property_read_u32_array(spic->spi_master->dev.of_node,
+ "qcom,eeprom-id", tmp, 2);
+ if (rc) {
+ pr_err("%s: Failed to get eeprom id\n", __func__);
+ return rc;
+ }
+ spic->mfr_id = tmp[0];
+ spic->device_id = tmp[1];
+
+ return 0;
+}
+
+static int msm_eeprom_check_id(struct msm_eeprom_ctrl_t *e_ctrl)
+{
+ int rc;
+ struct msm_camera_i2c_client *client = &e_ctrl->i2c_client;
+ uint8_t id[2];
+
+ rc = msm_camera_spi_query_id(client, 0, &id[0], 2);
+ if (rc)
+ return rc;
+ if (id[0] != client->spi_client->mfr_id
+ || id[1] != client->spi_client->device_id) {
+ CDBG("%s: read 0x%x 0x%x, check 0x%x 0x%x\n", __func__, id[0],
+ id[1], client->spi_client->mfr_id,
+ client->spi_client->device_id);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int msm_eeprom_get_dt_data(struct msm_eeprom_ctrl_t *e_ctrl)
+{
+ int rc = 0, i = 0;
+ struct msm_eeprom_board_info *eb_info;
+ struct msm_camera_power_ctrl_t *power_info =
+ &e_ctrl->eboard_info->power_info;
+ struct spi_device *spi = e_ctrl->i2c_client.spi_client->spi_master;
+ struct device_node *of_node = spi->dev.of_node;
+ struct msm_camera_gpio_conf *gconf = NULL;
+ uint16_t gpio_array_size = 0;
+ uint16_t *gpio_array = NULL;
+
+ eb_info = e_ctrl->eboard_info;
+ rc = msm_camera_get_dt_power_setting_data(spi->dev.of_node,
+ &power_info->power_setting, &power_info->power_setting_size);
+ if (rc)
+ return rc;
+
+ rc = msm_camera_get_dt_vreg_data(of_node, &power_info->cam_vreg,
+ &power_info->num_vreg);
+ if (rc)
+ goto ERROR1;
+
+ power_info->gpio_conf = kzalloc(sizeof(struct msm_camera_gpio_conf),
+ GFP_KERNEL);
+ if (!power_info->gpio_conf) {
+ rc = -ENOMEM;
+ goto ERROR2;
+ }
+ gconf = power_info->gpio_conf;
+ gpio_array_size = of_gpio_count(of_node);
+ CDBG("%s gpio count %d\n", __func__, gpio_array_size);
+
+ if (gpio_array_size) {
+ gpio_array = kzalloc(sizeof(uint16_t) * gpio_array_size,
+ GFP_KERNEL);
+ if (!gpio_array) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR3;
+ }
+ for (i = 0; i < gpio_array_size; i++) {
+ gpio_array[i] = of_get_gpio(of_node, i);
+ CDBG("%s gpio_array[%d] = %d\n", __func__, i,
+ gpio_array[i]);
+ }
+
+ rc = msm_camera_get_dt_gpio_req_tbl(of_node, gconf,
+ gpio_array, gpio_array_size);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR4;
+ }
+
+ rc = msm_camera_init_gpio_pin_tbl(of_node, gconf,
+ gpio_array, gpio_array_size);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR4;
+ }
+ kfree(gpio_array);
+ }
+
+ return rc;
+ERROR4:
+ kfree(gpio_array);
+ERROR3:
+ kfree(power_info->gpio_conf);
+ERROR2:
+ kfree(power_info->cam_vreg);
+ERROR1:
+ kfree(power_info->power_setting);
+ return rc;
+}
+
+static int msm_eeprom_spi_setup(struct spi_device *spi)
+{
+ struct msm_eeprom_ctrl_t *e_ctrl = NULL;
+ struct msm_camera_i2c_client *client = NULL;
+ struct msm_camera_spi_client *spi_client;
+ struct msm_eeprom_board_info *eb_info;
+ struct msm_camera_power_ctrl_t *power_info = NULL;
+ int rc = 0;
+
+ e_ctrl = kzalloc(sizeof(struct msm_eeprom_ctrl_t), GFP_KERNEL);
+ if (!e_ctrl) {
+ pr_err("%s:%d kzalloc failed\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+ e_ctrl->eeprom_v4l2_subdev_ops = &msm_eeprom_subdev_ops;
+ e_ctrl->eeprom_mutex = &msm_eeprom_mutex;
+ client = &e_ctrl->i2c_client;
+ e_ctrl->is_supported = 0;
+
+ spi_client = kzalloc(sizeof(spi_client), GFP_KERNEL);
+ if (!spi_client) {
+ pr_err("%s:%d kzalloc failed\n", __func__, __LINE__);
+ kfree(e_ctrl);
+ return -ENOMEM;
+ }
+
+ rc = of_property_read_u32(spi->dev.of_node, "cell-index",
+ &e_ctrl->subdev_id);
+ CDBG("cell-index %d, rc %d\n", e_ctrl->subdev_id, rc);
+ if (rc) {
+ pr_err("failed rc %d\n", rc);
+ return rc;
+ }
+
+ e_ctrl->eeprom_device_type = MSM_CAMERA_SPI_DEVICE;
+ client->spi_client = spi_client;
+ spi_client->spi_master = spi;
+ client->i2c_func_tbl = &msm_eeprom_spi_func_tbl;
+ client->addr_type = MSM_CAMERA_I2C_3B_ADDR;
+
+ eb_info = kzalloc(sizeof(eb_info), GFP_KERNEL);
+ if (!eb_info)
+ goto spi_free;
+ e_ctrl->eboard_info = eb_info;
+ rc = of_property_read_string(spi->dev.of_node, "qcom,eeprom-name",
+ &eb_info->eeprom_name);
+ CDBG("%s qcom,eeprom-name %s, rc %d\n", __func__,
+ eb_info->eeprom_name, rc);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto board_free;
+ }
+ power_info = &eb_info->power_info;
+
+ power_info->clk_info = cam_8974_clk_info;
+ power_info->clk_info_size = ARRAY_SIZE(cam_8974_clk_info);
+ power_info->dev = &spi->dev;
+
+ rc = msm_eeprom_get_dt_data(e_ctrl);
+ if (rc)
+ goto board_free;
+
+ /* set spi instruction info */
+ spi_client->retry_delay = 1;
+ spi_client->retries = 0;
+
+ if (msm_eeprom_spi_parse_of(spi_client)) {
+ dev_err(&spi->dev,
+ "%s: Error parsing device properties\n", __func__);
+ goto board_free;
+ }
+
+ rc = msm_eeprom_alloc_memory_map(e_ctrl, spi->dev.of_node);
+ if (rc)
+ goto board_free;
+
+ rc = msm_camera_power_up(power_info, e_ctrl->eeprom_device_type,
+ &e_ctrl->i2c_client);
+ if (rc) {
+ pr_err("failed rc %d\n", rc);
+ goto memmap_free;
+ }
+
+ /* check eeprom id */
+ rc = msm_eeprom_check_id(e_ctrl);
+ if (rc) {
+ CDBG("%s: eeprom not matching %d\n", __func__, rc);
+ goto power_down;
+ }
+ /* read eeprom */
+ rc = read_eeprom_memory(e_ctrl);
+ if (rc) {
+ dev_err(&spi->dev, "%s: read eeprom memory failed\n", __func__);
+ goto power_down;
+ }
+
+ rc = msm_camera_power_down(power_info, e_ctrl->eeprom_device_type,
+ &e_ctrl->i2c_client);
+ if (rc) {
+ pr_err("failed rc %d\n", rc);
+ goto memmap_free;
+ }
+
+ /* initiazlie subdev */
+ v4l2_spi_subdev_init(&e_ctrl->msm_sd.sd,
+ e_ctrl->i2c_client.spi_client->spi_master,
+ e_ctrl->eeprom_v4l2_subdev_ops);
+ v4l2_set_subdevdata(&e_ctrl->msm_sd.sd, e_ctrl);
+ e_ctrl->msm_sd.sd.internal_ops = &msm_eeprom_internal_ops;
+ e_ctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ media_entity_init(&e_ctrl->msm_sd.sd.entity, 0, NULL, 0);
+ e_ctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+ e_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_EEPROM;
+ msm_sd_register(&e_ctrl->msm_sd);
+ e_ctrl->is_supported = 1;
+ CDBG("%s success result=%d X\n", __func__, rc);
+
+ return 0;
+
+power_down:
+ msm_camera_power_down(power_info, e_ctrl->eeprom_device_type,
+ &e_ctrl->i2c_client);
+memmap_free:
+ kfree(e_ctrl->eboard_info->eeprom_map);
+ kfree(e_ctrl->memory_data);
+board_free:
+ kfree(e_ctrl->eboard_info);
+spi_free:
+ kfree(spi_client);
+ return rc;
+}
+
+static int msm_eeprom_spi_probe(struct spi_device *spi)
+{
+ int irq, cs, cpha, cpol, cs_high;
+
+ CDBG("%s\n", __func__);
+ spi->bits_per_word = 8;
+ spi->mode = SPI_MODE_0;
+ spi_setup(spi);
+
+ irq = spi->irq;
+ cs = spi->chip_select;
+ cpha = (spi->mode & SPI_CPHA) ? 1 : 0;
+ cpol = (spi->mode & SPI_CPOL) ? 1 : 0;
+ cs_high = (spi->mode & SPI_CS_HIGH) ? 1 : 0;
+ dev_info(&spi->dev, "irq[%d] cs[%x] CPHA[%x] CPOL[%x] CS_HIGH[%x]\n",
+ irq, cs, cpha, cpol, cs_high);
+ dev_info(&spi->dev, "max_speed[%u]\n", spi->max_speed_hz);
+
+ return msm_eeprom_spi_setup(spi);
+}
+
+static int32_t msm_eeprom_spi_remove(struct spi_device *sdev)
+{
+ struct v4l2_subdev *sd = spi_get_drvdata(sdev);
+ struct msm_eeprom_ctrl_t *e_ctrl;
+ if (!sd) {
+ pr_err("%s: Subdevice is NULL\n", __func__);
+ return 0;
+ }
+
+ e_ctrl = (struct msm_eeprom_ctrl_t *)v4l2_get_subdevdata(sd);
+ if (!e_ctrl) {
+ pr_err("%s: eeprom device is NULL\n", __func__);
+ return 0;
+ }
+
+ kfree(e_ctrl->i2c_client.spi_client);
+ kfree(e_ctrl->memory_data);
+ if (e_ctrl->eboard_info) {
+ kfree(e_ctrl->eboard_info->power_info.gpio_conf);
+ kfree(e_ctrl->eboard_info->eeprom_map);
+ }
+ kfree(e_ctrl->eboard_info);
+ kfree(e_ctrl);
+ return 0;
+}
+
+static int32_t msm_eeprom_platform_probe(struct platform_device *pdev)
+{
+ int32_t rc = 0;
+ int32_t j = 0;
+ uint32_t temp;
+
+ struct msm_camera_cci_client *cci_client = NULL;
+ struct msm_eeprom_ctrl_t *e_ctrl = NULL;
+ struct msm_eeprom_board_info *eb_info = NULL;
+ struct device_node *of_node = pdev->dev.of_node;
+ struct msm_camera_power_ctrl_t *power_info = NULL;
+
+ CDBG("%s E\n", __func__);
+
+ e_ctrl = kzalloc(sizeof(struct msm_eeprom_ctrl_t), GFP_KERNEL);
+ if (!e_ctrl) {
+ pr_err("%s:%d kzalloc failed\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+ e_ctrl->eeprom_v4l2_subdev_ops = &msm_eeprom_subdev_ops;
+ e_ctrl->eeprom_mutex = &msm_eeprom_mutex;
+
+ e_ctrl->is_supported = 0;
+ if (!of_node) {
+ pr_err("%s dev.of_node NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32(of_node, "cell-index",
+ &pdev->id);
+ CDBG("cell-index %d, rc %d\n", pdev->id, rc);
+ if (rc < 0) {
+ pr_err("failed rc %d\n", rc);
+ return rc;
+ }
+ e_ctrl->subdev_id = pdev->id;
+
+ rc = of_property_read_u32(of_node, "qcom,cci-master",
+ &e_ctrl->cci_master);
+ CDBG("qcom,cci-master %d, rc %d\n", e_ctrl->cci_master, rc);
+ if (rc < 0) {
+ pr_err("%s failed rc %d\n", __func__, rc);
+ return rc;
+ }
+ rc = of_property_read_u32(of_node, "qcom,slave-addr",
+ &temp);
+ if (rc < 0) {
+ pr_err("%s failed rc %d\n", __func__, rc);
+ return rc;
+ }
+
+ /* Set platform device handle */
+ e_ctrl->pdev = pdev;
+ /* Set device type as platform device */
+ e_ctrl->eeprom_device_type = MSM_CAMERA_PLATFORM_DEVICE;
+ e_ctrl->i2c_client.i2c_func_tbl = &msm_eeprom_cci_func_tbl;
+ e_ctrl->i2c_client.cci_client = kzalloc(sizeof(
+ struct msm_camera_cci_client), GFP_KERNEL);
+ if (!e_ctrl->i2c_client.cci_client) {
+ pr_err("%s failed no memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ e_ctrl->eboard_info = kzalloc(sizeof(
+ struct msm_eeprom_board_info), GFP_KERNEL);
+ if (!e_ctrl->eboard_info) {
+ pr_err("%s failed line %d\n", __func__, __LINE__);
+ rc = -ENOMEM;
+ goto cciclient_free;
+ }
+ eb_info = e_ctrl->eboard_info;
+ power_info = &eb_info->power_info;
+ eb_info->i2c_slaveaddr = temp;
+
+ power_info->clk_info = cam_8974_clk_info;
+ power_info->clk_info_size = ARRAY_SIZE(cam_8974_clk_info);
+ power_info->dev = &pdev->dev;
+
+ CDBG("qcom,slave-addr = 0x%X\n", eb_info->i2c_slaveaddr);
+ cci_client = e_ctrl->i2c_client.cci_client;
+ cci_client->cci_subdev = msm_cci_get_subdev();
+ cci_client->cci_i2c_master = e_ctrl->cci_master;
+ cci_client->sid = eb_info->i2c_slaveaddr >> 1;
+ cci_client->retries = 3;
+ cci_client->id_map = 0;
+
+ rc = of_property_read_string(of_node, "qcom,eeprom-name",
+ &eb_info->eeprom_name);
+ CDBG("%s qcom,eeprom-name %s, rc %d\n", __func__,
+ eb_info->eeprom_name, rc);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto board_free;
+ }
+
+ if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+ rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_util(
+ &e_ctrl->i2c_client, MSM_CCI_INIT);
+ if (rc < 0)
+ pr_err("%s cci_init failed\n", __func__);
+ }
+
+ rc = msm_eeprom_alloc_memory_map(e_ctrl, of_node);
+ if (rc)
+ goto board_free;
+
+ rc = read_eeprom_memory(e_ctrl);
+ if (rc < 0) {
+ pr_err("%s read_eeprom_memory failed\n", __func__);
+ goto memdata_free;
+ }
+ pr_err("%s line %d\n", __func__, __LINE__);
+ for (j = 0; j < e_ctrl->num_bytes; j++)
+ CDBG("memory_data[%d] = 0x%X\n", j, e_ctrl->memory_data[j]);
+
+ v4l2_subdev_init(&e_ctrl->msm_sd.sd,
+ e_ctrl->eeprom_v4l2_subdev_ops);
+ v4l2_set_subdevdata(&e_ctrl->msm_sd.sd, e_ctrl);
+ platform_set_drvdata(pdev, &e_ctrl->msm_sd.sd);
+ e_ctrl->msm_sd.sd.internal_ops = &msm_eeprom_internal_ops;
+ e_ctrl->msm_sd.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ snprintf(e_ctrl->msm_sd.sd.name,
+ ARRAY_SIZE(e_ctrl->msm_sd.sd.name), "msm_eeprom");
+ media_entity_init(&e_ctrl->msm_sd.sd.entity, 0, NULL, 0);
+ e_ctrl->msm_sd.sd.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+ e_ctrl->msm_sd.sd.entity.group_id = MSM_CAMERA_SUBDEV_EEPROM;
+ msm_sd_register(&e_ctrl->msm_sd);
+
+
+ if (e_ctrl->eeprom_device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+ rc = e_ctrl->i2c_client.i2c_func_tbl->i2c_util(
+ &e_ctrl->i2c_client, MSM_CCI_RELEASE);
+ if (rc < 0)
+ pr_err("%s cci_init failed\n", __func__);
+ }
+ e_ctrl->is_supported = 1;
+ CDBG("%s X\n", __func__);
+ return rc;
+
+memdata_free:
+ kfree(e_ctrl->memory_data);
+ kfree(eb_info->eeprom_map);
+board_free:
+ kfree(e_ctrl->eboard_info);
+cciclient_free:
+ kfree(e_ctrl->i2c_client.cci_client);
+ return rc;
+}
+
+static int32_t msm_eeprom_platform_remove(struct platform_device *pdev)
+{
+ struct v4l2_subdev *sd = platform_get_drvdata(pdev);
+ struct msm_eeprom_ctrl_t *e_ctrl;
+ if (!sd) {
+ pr_err("%s: Subdevice is NULL\n", __func__);
+ return 0;
+ }
+
+ e_ctrl = (struct msm_eeprom_ctrl_t *)v4l2_get_subdevdata(sd);
+ if (!e_ctrl) {
+ pr_err("%s: eeprom device is NULL\n", __func__);
+ return 0;
+ }
+
+ kfree(e_ctrl->i2c_client.cci_client);
+ kfree(e_ctrl->memory_data);
+ if (e_ctrl->eboard_info) {
+ kfree(e_ctrl->eboard_info->power_info.gpio_conf);
+ kfree(e_ctrl->eboard_info->eeprom_map);
+ }
+ kfree(e_ctrl->eboard_info);
+ kfree(e_ctrl);
+ return 0;
+}
+
+static const struct of_device_id msm_eeprom_dt_match[] = {
+ { .compatible = "qcom,eeprom" },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, msm_eeprom_dt_match);
+
+static struct platform_driver msm_eeprom_platform_driver = {
+ .driver = {
+ .name = "qcom,eeprom",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_eeprom_dt_match,
+ },
+ .remove = __devexit_p(msm_eeprom_platform_remove),
+};
+
+static const struct i2c_device_id msm_eeprom_i2c_id[] = {
+ { "msm_eeprom", (kernel_ulong_t)NULL},
+ { }
+};
+
+static struct i2c_driver msm_eeprom_i2c_driver = {
+ .id_table = msm_eeprom_i2c_id,
+ .probe = msm_eeprom_i2c_probe,
+ .remove = __devexit_p(msm_eeprom_i2c_remove),
+ .driver = {
+ .name = "msm_eeprom",
+ },
+};
+
+static struct spi_driver msm_eeprom_spi_driver = {
+ .driver = {
+ .name = "qcom_eeprom",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_eeprom_dt_match,
+ },
+ .probe = msm_eeprom_spi_probe,
+ .remove = __devexit_p(msm_eeprom_spi_remove),
+};
+
+static int __init msm_eeprom_init_module(void)
+{
+ int32_t rc = 0;
+ CDBG("%s E\n", __func__);
+ rc = platform_driver_probe(&msm_eeprom_platform_driver,
+ msm_eeprom_platform_probe);
+ CDBG("%s:%d platform rc %d\n", __func__, __LINE__, rc);
+ rc = spi_register_driver(&msm_eeprom_spi_driver);
+ CDBG("%s:%d spi rc %d\n", __func__, __LINE__, rc);
+ return i2c_add_driver(&msm_eeprom_i2c_driver);
+}
+
+static void __exit msm_eeprom_exit_module(void)
+{
+ platform_driver_unregister(&msm_eeprom_platform_driver);
+ spi_unregister_driver(&msm_eeprom_spi_driver);
+ i2c_del_driver(&msm_eeprom_i2c_driver);
+}
+
+module_init(msm_eeprom_init_module);
+module_exit(msm_eeprom_exit_module);
+MODULE_DESCRIPTION("MSM EEPROM driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.h b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.h
new file mode 100644
index 0000000..cebe585
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.h
@@ -0,0 +1,48 @@
+/* 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
+ * 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_EEPROM_H
+#define MSM_EEPROM_H
+
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <mach/camera2.h>
+#include <media/v4l2-subdev.h>
+#include <media/msmb_camera.h>
+#include "msm_camera_i2c.h"
+#include "msm_camera_spi.h"
+#include "msm_camera_io_util.h"
+#include "msm_camera_dt_util.h"
+
+struct msm_eeprom_ctrl_t;
+
+#define DEFINE_MSM_MUTEX(mutexname) \
+ static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
+
+struct msm_eeprom_ctrl_t {
+ struct platform_device *pdev;
+ struct mutex *eeprom_mutex;
+
+ struct v4l2_subdev sdev;
+ struct v4l2_subdev_ops *eeprom_v4l2_subdev_ops;
+ enum msm_camera_device_type_t eeprom_device_type;
+ struct msm_sd_subdev msm_sd;
+ enum cci_i2c_master_t cci_master;
+
+ struct msm_camera_i2c_client i2c_client;
+ uint32_t num_bytes;
+ uint8_t *memory_data;
+ uint8_t is_supported;
+ struct msm_eeprom_board_info *eboard_info;
+ uint32_t subdev_id;
+};
+
+#endif
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/Makefile b/drivers/media/platform/msm/camera_v2/sensor/io/Makefile
index f71b09d..0c7c191 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/Makefile
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/Makefile
@@ -1,3 +1,4 @@
ccflags-y += -Idrivers/media/platform/msm/camera_v2/
+ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor
ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/cci
-obj-$(CONFIG_MSMB_CAMERA) += msm_camera_io_util.o msm_camera_cci_i2c.o msm_camera_qup_i2c.o msm_camera_i2c_mux.o
+obj-$(CONFIG_MSMB_CAMERA) += msm_camera_io_util.o msm_camera_cci_i2c.o msm_camera_qup_i2c.o msm_camera_i2c_mux.o msm_camera_spi.o msm_camera_dt_util.o
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
index b07f04f..80b1ccb 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_cci_i2c.c
@@ -28,7 +28,7 @@
#define I2C_POLL_MAX_ITERATION 20
int32_t msm_camera_cci_i2c_read(struct msm_camera_i2c_client *client,
- uint16_t addr, uint16_t *data,
+ uint32_t addr, uint16_t *data,
enum msm_camera_i2c_data_type data_type)
{
int32_t rc = -EFAULT;
@@ -64,10 +64,10 @@
}
int32_t msm_camera_cci_i2c_read_seq(struct msm_camera_i2c_client *client,
- uint16_t addr, uint8_t *data, uint16_t num_byte)
+ uint32_t addr, uint8_t *data, uint16_t num_byte)
{
int32_t rc = -EFAULT;
- unsigned char buf[client->addr_type+num_byte];
+ unsigned char *buf = NULL;
int i;
struct msm_camera_cci_ctrl cci_ctrl;
@@ -76,6 +76,11 @@
|| num_byte == 0)
return rc;
+ buf = kzalloc(num_byte, GFP_KERNEL);
+ if (!buf) {
+ pr_err("%s:%d no memory\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
cci_ctrl.cmd = MSM_CCI_I2C_READ;
cci_ctrl.cci_info = client->cci_client;
cci_ctrl.cfg.cci_i2c_read_cfg.addr = addr;
@@ -93,11 +98,12 @@
S_I2C_DBG("Byte %d: 0x%x\n", i, buf[i]);
S_I2C_DBG("Data: 0x%x\n", data[i]);
}
+ kfree(buf);
return rc;
}
int32_t msm_camera_cci_i2c_write(struct msm_camera_i2c_client *client,
- uint16_t addr, uint16_t data,
+ uint32_t addr, uint16_t data,
enum msm_camera_i2c_data_type data_type)
{
int32_t rc = -EFAULT;
@@ -131,7 +137,7 @@
}
int32_t msm_camera_cci_i2c_write_seq(struct msm_camera_i2c_client *client,
- uint16_t addr, uint8_t *data, uint16_t num_byte)
+ uint32_t addr, uint8_t *data, uint16_t num_byte)
{
int32_t rc = -EFAULT;
uint8_t i = 0;
@@ -272,7 +278,7 @@
}
static int32_t msm_camera_cci_i2c_compare(struct msm_camera_i2c_client *client,
- uint16_t addr, uint16_t data,
+ uint32_t addr, uint16_t data,
enum msm_camera_i2c_data_type data_type)
{
int32_t rc;
@@ -327,8 +333,8 @@
return rc;
}
-static int32_t msm_camera_cci_i2c_poll(struct msm_camera_i2c_client *client,
- uint16_t addr, uint16_t data,
+int32_t msm_camera_cci_i2c_poll(struct msm_camera_i2c_client *client,
+ uint32_t addr, uint16_t data,
enum msm_camera_i2c_data_type data_type)
{
int32_t rc;
@@ -347,7 +353,7 @@
}
static int32_t msm_camera_cci_i2c_set_mask(struct msm_camera_i2c_client *client,
- uint16_t addr, uint16_t mask,
+ uint32_t addr, uint16_t mask,
enum msm_camera_i2c_data_type data_type, uint16_t set_mask)
{
int32_t rc;
@@ -376,7 +382,7 @@
static int32_t msm_camera_cci_i2c_set_write_mask_data(
struct msm_camera_i2c_client *client,
- uint16_t addr, uint16_t data, int16_t mask,
+ uint32_t addr, uint16_t data, int16_t mask,
enum msm_camera_i2c_data_type data_type)
{
int32_t rc;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
new file mode 100644
index 0000000..2511651
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.c
@@ -0,0 +1,662 @@
+/* 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 <mach/gpiomux.h>
+#include "msm_camera_dt_util.h"
+#include "msm_camera_io_util.h"
+#include "msm_camera_i2c_mux.h"
+#include "msm_cci.h"
+
+#undef CDBG
+#ifdef CONFIG_MSM_CAMERA_DT_DEBUG
+#define CDBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define CDBG(fmt, args...) do { } while (0)
+#endif
+
+int32_t msm_camera_get_dt_power_setting_data(struct device_node *of_node,
+ struct msm_sensor_power_setting **power_setting,
+ uint16_t *power_setting_size)
+{
+ int32_t rc = 0, i = 0;
+ int32_t count = 0;
+ const char *seq_name = NULL;
+ uint32_t *array = NULL;
+ struct msm_sensor_power_setting *ps;
+
+ if (!power_setting || !power_setting_size)
+ return -EINVAL;
+
+ count = of_property_count_strings(of_node, "qcom,cam-power-seq-type");
+ *power_setting_size = count;
+ CDBG("%s qcom,cam-power-seq-type count %d\n", __func__, count);
+
+ if (count <= 0)
+ return 0;
+
+ ps = kzalloc(sizeof(struct msm_sensor_power_setting) * count,
+ GFP_KERNEL);
+ if (!ps) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+ *power_setting = ps;
+
+ for (i = 0; i < count; i++) {
+ rc = of_property_read_string_index(of_node,
+ "qcom,cam-power-seq-type", i,
+ &seq_name);
+ CDBG("%s seq_name[%d] = %s\n", __func__, i,
+ seq_name);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR1;
+ }
+ if (!strcmp(seq_name, "sensor_vreg")) {
+ ps[i].seq_type = SENSOR_VREG;
+ CDBG("%s:%d seq_type[%d] %d\n", __func__, __LINE__,
+ i, ps[i].seq_type);
+ } else if (!strcmp(seq_name, "sensor_gpio")) {
+ ps[i].seq_type = SENSOR_GPIO;
+ CDBG("%s:%d seq_type[%d] %d\n", __func__, __LINE__,
+ i, ps[i].seq_type);
+ } else if (!strcmp(seq_name, "sensor_clk")) {
+ ps[i].seq_type = SENSOR_CLK;
+ CDBG("%s:%d seq_type[%d] %d\n", __func__, __LINE__,
+ i, ps[i].seq_type);
+ } else if (!strcmp(seq_name, "sensor_i2c_mux")) {
+ ps[i].seq_type = SENSOR_I2C_MUX;
+ CDBG("%s:%d seq_type[%d] %d\n", __func__, __LINE__,
+ i, ps[i].seq_type);
+ }
+ }
+
+
+ for (i = 0; i < count; i++) {
+ rc = of_property_read_string_index(of_node,
+ "qcom,cam-power-seq-val", i,
+ &seq_name);
+ CDBG("%s seq_name[%d] = %s\n", __func__, i,
+ seq_name);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR1;
+ }
+ if (!strcmp(seq_name, "cam_vdig"))
+ ps[i].seq_val = CAM_VDIG;
+ else if (!strcmp(seq_name, "cam_vio"))
+ ps[i].seq_val = CAM_VIO;
+ else if (!strcmp(seq_name, "cam_vana"))
+ ps[i].seq_val = CAM_VANA;
+ else if (!strcmp(seq_name, "cam_vaf"))
+ ps[i].seq_val = CAM_VAF;
+ else if (!strcmp(seq_name, "sensor_gpio_reset"))
+ ps[i].seq_val = SENSOR_GPIO_RESET;
+ else if (!strcmp(seq_name, "sensor_gpio_standby"))
+ ps[i].seq_val = SENSOR_GPIO_STANDBY;
+ else if (!strcmp(seq_name, "sensor_cam_mclk"))
+ ps[i].seq_val = SENSOR_CAM_MCLK;
+ else if (!strcmp(seq_name, "sensor_cam_clk"))
+ ps[i].seq_val = SENSOR_CAM_CLK;
+ else if (!strcmp(seq_name, "none"))
+ ps[i].seq_val = 0;
+ }
+
+ array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
+ if (!array) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ rc = -ENOMEM;
+ goto ERROR1;
+ }
+
+
+ rc = of_property_read_u32_array(of_node, "qcom,cam-power-seq-cfg-val",
+ array, count);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR2;
+ }
+ for (i = 0; i < count; i++) {
+ if (ps[i].seq_type == SENSOR_GPIO) {
+ if (array[i] == 0)
+ ps[i].config_val = GPIO_OUT_LOW;
+ else if (array[i] == 1)
+ ps[i].config_val = GPIO_OUT_HIGH;
+ } else {
+ ps[i].config_val = array[i];
+ }
+ CDBG("%s power_setting[%d].config_val = %ld\n", __func__, i,
+ ps[i].config_val);
+ }
+
+ rc = of_property_read_u32_array(of_node, "qcom,cam-power-seq-delay",
+ array, count);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR2;
+ }
+ for (i = 0; i < count; i++) {
+ ps[i].delay = array[i];
+ CDBG("%s power_setting[%d].delay = %d\n", __func__,
+ i, ps[i].delay);
+ }
+ kfree(array);
+ return rc;
+ERROR2:
+ kfree(array);
+ERROR1:
+ kfree(ps);
+ power_setting_size = 0;
+ return rc;
+}
+
+int32_t msm_camera_get_dt_gpio_req_tbl(struct device_node *of_node,
+ struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+ uint16_t gpio_array_size)
+{
+ int32_t rc = 0, i = 0;
+ uint32_t count = 0;
+ uint32_t *val_array = NULL;
+
+ if (!of_get_property(of_node, "qcom,gpio-req-tbl-num", &count))
+ return 0;
+
+ count /= sizeof(uint32_t);
+ if (!count) {
+ pr_err("%s qcom,gpio-req-tbl-num 0\n", __func__);
+ return 0;
+ }
+
+ val_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
+ if (!val_array) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+
+ gconf->cam_gpio_req_tbl = kzalloc(sizeof(struct gpio) * count,
+ GFP_KERNEL);
+ if (!gconf->cam_gpio_req_tbl) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ rc = -ENOMEM;
+ goto ERROR1;
+ }
+ gconf->cam_gpio_req_tbl_size = count;
+
+ rc = of_property_read_u32_array(of_node, "qcom,gpio-req-tbl-num",
+ val_array, count);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR2;
+ }
+ for (i = 0; i < count; i++) {
+ if (val_array[i] >= gpio_array_size) {
+ pr_err("%s gpio req tbl index %d invalid\n",
+ __func__, val_array[i]);
+ return -EINVAL;
+ }
+ gconf->cam_gpio_req_tbl[i].gpio = gpio_array[val_array[i]];
+ CDBG("%s cam_gpio_req_tbl[%d].gpio = %d\n", __func__, i,
+ gconf->cam_gpio_req_tbl[i].gpio);
+ }
+
+ rc = of_property_read_u32_array(of_node, "qcom,gpio-req-tbl-flags",
+ val_array, count);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR2;
+ }
+ for (i = 0; i < count; i++) {
+ gconf->cam_gpio_req_tbl[i].flags = val_array[i];
+ CDBG("%s cam_gpio_req_tbl[%d].flags = %ld\n", __func__, i,
+ gconf->cam_gpio_req_tbl[i].flags);
+ }
+
+ for (i = 0; i < count; i++) {
+ rc = of_property_read_string_index(of_node,
+ "qcom,gpio-req-tbl-label", i,
+ &gconf->cam_gpio_req_tbl[i].label);
+ CDBG("%s cam_gpio_req_tbl[%d].label = %s\n", __func__, i,
+ gconf->cam_gpio_req_tbl[i].label);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR2;
+ }
+ }
+
+ kfree(val_array);
+ return rc;
+
+ERROR2:
+ kfree(gconf->cam_gpio_req_tbl);
+ERROR1:
+ kfree(val_array);
+ gconf->cam_gpio_req_tbl_size = 0;
+ return rc;
+}
+
+int32_t msm_camera_init_gpio_pin_tbl(struct device_node *of_node,
+ struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+ uint16_t gpio_array_size)
+{
+ int32_t rc = 0;
+ int32_t val = 0;
+
+ gconf->gpio_num_info = kzalloc(sizeof(struct msm_camera_gpio_num_info),
+ GFP_KERNEL);
+ if (!gconf->gpio_num_info) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ if (of_property_read_bool(of_node, "qcom,gpio-reset") == true) {
+ rc = of_property_read_u32(of_node, "qcom,gpio-reset", &val);
+ if (rc < 0) {
+ pr_err("%s:%d read qcom,gpio-reset failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ } else if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-reset invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_RESET] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-reset %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_RESET]);
+ }
+
+ if (of_property_read_bool(of_node, "qcom,gpio-standby") == true) {
+ rc = of_property_read_u32(of_node, "qcom,gpio-standby", &val);
+ if (rc < 0) {
+ pr_err("%s:%d read qcom,gpio-standby failed rc %d\n",
+ __func__, __LINE__, rc);
+ goto ERROR;
+ } else if (val >= gpio_array_size) {
+ pr_err("%s:%d qcom,gpio-standby invalid %d\n",
+ __func__, __LINE__, val);
+ goto ERROR;
+ }
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_STANDBY] =
+ gpio_array[val];
+ CDBG("%s qcom,gpio-reset %d\n", __func__,
+ gconf->gpio_num_info->gpio_num[SENSOR_GPIO_STANDBY]);
+ }
+ return rc;
+
+ERROR:
+ kfree(gconf->gpio_num_info);
+ gconf->gpio_num_info = NULL;
+ return rc;
+}
+
+int32_t msm_camera_get_dt_vreg_data(struct device_node *of_node,
+ struct camera_vreg_t **cam_vreg, int *num_vreg)
+{
+ int32_t rc = 0, i = 0;
+ uint32_t count = 0;
+ uint32_t *vreg_array = NULL;
+ struct camera_vreg_t *vreg = NULL;
+
+ count = of_property_count_strings(of_node, "qcom,cam-vreg-name");
+ CDBG("%s qcom,cam-vreg-name count %d\n", __func__, count);
+
+ if (!count)
+ return 0;
+
+ vreg = kzalloc(sizeof(struct camera_vreg_t) * count,
+ GFP_KERNEL);
+ if (!vreg) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ return -ENOMEM;
+ }
+ *cam_vreg = vreg;
+ *num_vreg = count;
+ for (i = 0; i < count; i++) {
+ rc = of_property_read_string_index(of_node,
+ "qcom,cam-vreg-name", i,
+ &vreg[i].reg_name);
+ CDBG("%s reg_name[%d] = %s\n", __func__, i,
+ vreg[i].reg_name);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR1;
+ }
+ }
+
+ vreg_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
+ if (!vreg_array) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ rc = -ENOMEM;
+ goto ERROR1;
+ }
+
+ rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-type",
+ vreg_array, count);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR2;
+ }
+ for (i = 0; i < count; i++) {
+ vreg[i].type = vreg_array[i];
+ CDBG("%s cam_vreg[%d].type = %d\n", __func__, i,
+ vreg[i].type);
+ }
+
+ rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-min-voltage",
+ vreg_array, count);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR2;
+ }
+ for (i = 0; i < count; i++) {
+ vreg[i].min_voltage = vreg_array[i];
+ CDBG("%s cam_vreg[%d].min_voltage = %d\n", __func__,
+ i, vreg[i].min_voltage);
+ }
+
+ rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-max-voltage",
+ vreg_array, count);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR2;
+ }
+ for (i = 0; i < count; i++) {
+ vreg[i].max_voltage = vreg_array[i];
+ CDBG("%s cam_vreg[%d].max_voltage = %d\n", __func__,
+ i, vreg[i].max_voltage);
+ }
+
+ rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-op-mode",
+ vreg_array, count);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR2;
+ }
+ for (i = 0; i < count; i++) {
+ vreg[i].op_mode = vreg_array[i];
+ CDBG("%s cam_vreg[%d].op_mode = %d\n", __func__, i,
+ vreg[i].op_mode);
+ }
+
+ kfree(vreg_array);
+ return rc;
+ERROR2:
+ kfree(vreg_array);
+ERROR1:
+ kfree(vreg);
+ *num_vreg = 0;
+ return rc;
+}
+
+static int32_t msm_camera_enable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
+{
+ struct v4l2_subdev *i2c_mux_sd =
+ dev_get_drvdata(&i2c_conf->mux_dev->dev);
+ v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+ VIDIOC_MSM_I2C_MUX_INIT, NULL);
+ v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+ VIDIOC_MSM_I2C_MUX_CFG, (void *)&i2c_conf->i2c_mux_mode);
+ return 0;
+}
+
+static int32_t msm_camera_disable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
+{
+ struct v4l2_subdev *i2c_mux_sd =
+ dev_get_drvdata(&i2c_conf->mux_dev->dev);
+ v4l2_subdev_call(i2c_mux_sd, core, ioctl,
+ VIDIOC_MSM_I2C_MUX_RELEASE, NULL);
+ return 0;
+}
+
+int32_t msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
+ enum msm_camera_device_type_t device_type,
+ struct msm_camera_i2c_client *sensor_i2c_client)
+{
+ int32_t rc = 0, index = 0, no_gpio = 0;
+ struct msm_sensor_power_setting *power_setting = NULL;
+
+ CDBG("%s:%d\n", __func__, __LINE__);
+ if (!ctrl || !sensor_i2c_client) {
+ pr_err("failed ctrl %p sensor_i2c_client %p\n", ctrl,
+ sensor_i2c_client);
+ return -EINVAL;
+ }
+ if (ctrl->gpio_conf->cam_gpiomux_conf_tbl != NULL) {
+ pr_err("%s:%d mux install\n", __func__, __LINE__);
+ msm_gpiomux_install(
+ (struct msm_gpiomux_config *)
+ ctrl->gpio_conf->cam_gpiomux_conf_tbl,
+ ctrl->gpio_conf->cam_gpiomux_conf_tbl_size);
+ }
+
+ rc = msm_camera_request_gpio_table(
+ ctrl->gpio_conf->cam_gpio_req_tbl,
+ ctrl->gpio_conf->cam_gpio_req_tbl_size, 1);
+ if (rc < 0)
+ no_gpio = rc;
+
+ for (index = 0; index < ctrl->power_setting_size; index++) {
+ CDBG("%s index %d\n", __func__, index);
+ power_setting = &ctrl->power_setting[index];
+ CDBG("%s type %d\n", __func__, power_setting->seq_type);
+ switch (power_setting->seq_type) {
+ case SENSOR_CLK:
+ if (power_setting->seq_val >= ctrl->clk_info_size) {
+ pr_err("%s clk index %d >= max %d\n", __func__,
+ power_setting->seq_val,
+ ctrl->clk_info_size);
+ goto power_up_failed;
+ }
+ if (power_setting->config_val)
+ ctrl->clk_info[power_setting->seq_val].
+ clk_rate = power_setting->config_val;
+
+ rc = msm_cam_clk_enable(ctrl->dev,
+ &ctrl->clk_info[0],
+ (struct clk **)&power_setting->data[0],
+ ctrl->clk_info_size,
+ 1);
+ if (rc < 0) {
+ pr_err("%s: clk enable failed\n",
+ __func__);
+ goto power_up_failed;
+ }
+ break;
+ case SENSOR_GPIO:
+ if (no_gpio) {
+ pr_err("%s: request gpio failed\n", __func__);
+ return no_gpio;
+ }
+ if (power_setting->seq_val >= SENSOR_GPIO_MAX ||
+ !ctrl->gpio_conf->gpio_num_info) {
+ pr_err("%s gpio index %d >= max %d\n", __func__,
+ power_setting->seq_val,
+ SENSOR_GPIO_MAX);
+ goto power_up_failed;
+ }
+ pr_debug("%s:%d gpio set val %d\n", __func__, __LINE__,
+ ctrl->gpio_conf->gpio_num_info->gpio_num
+ [power_setting->seq_val]);
+ gpio_set_value_cansleep(
+ ctrl->gpio_conf->gpio_num_info->gpio_num
+ [power_setting->seq_val],
+ power_setting->config_val);
+ break;
+ case SENSOR_VREG:
+ if (power_setting->seq_val >= CAM_VREG_MAX) {
+ pr_err("%s vreg index %d >= max %d\n", __func__,
+ power_setting->seq_val,
+ SENSOR_GPIO_MAX);
+ goto power_up_failed;
+ }
+ msm_camera_config_single_vreg(ctrl->dev,
+ &ctrl->cam_vreg[power_setting->seq_val],
+ (struct regulator **)&power_setting->data[0],
+ 1);
+ break;
+ case SENSOR_I2C_MUX:
+ if (ctrl->i2c_conf && ctrl->i2c_conf->use_i2c_mux)
+ msm_camera_enable_i2c_mux(ctrl->i2c_conf);
+ break;
+ default:
+ pr_err("%s error power seq type %d\n", __func__,
+ power_setting->seq_type);
+ break;
+ }
+ if (power_setting->delay > 20) {
+ msleep(power_setting->delay);
+ } else if (power_setting->delay) {
+ usleep_range(power_setting->delay * 1000,
+ (power_setting->delay * 1000) + 1000);
+ }
+ }
+
+ if (device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+ rc = sensor_i2c_client->i2c_func_tbl->i2c_util(
+ sensor_i2c_client, MSM_CCI_INIT);
+ if (rc < 0) {
+ pr_err("%s cci_init failed\n", __func__);
+ goto power_up_failed;
+ }
+ }
+
+ CDBG("%s exit\n", __func__);
+ return 0;
+power_up_failed:
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ if (device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+ sensor_i2c_client->i2c_func_tbl->i2c_util(
+ sensor_i2c_client, MSM_CCI_RELEASE);
+ }
+
+ for (index--; index >= 0; index--) {
+ CDBG("%s index %d\n", __func__, index);
+ power_setting = &ctrl->power_setting[index];
+ CDBG("%s type %d\n", __func__, power_setting->seq_type);
+ switch (power_setting->seq_type) {
+ case SENSOR_CLK:
+ msm_cam_clk_enable(ctrl->dev,
+ &ctrl->clk_info[0],
+ (struct clk **)&power_setting->data[0],
+ ctrl->clk_info_size,
+ 0);
+ break;
+ case SENSOR_GPIO:
+ gpio_set_value_cansleep(
+ ctrl->gpio_conf->gpio_num_info->gpio_num
+ [power_setting->seq_val], GPIOF_OUT_INIT_LOW);
+ break;
+ case SENSOR_VREG:
+ msm_camera_config_single_vreg(ctrl->dev,
+ &ctrl->cam_vreg[power_setting->seq_val],
+ (struct regulator **)&power_setting->data[0],
+ 0);
+ break;
+ case SENSOR_I2C_MUX:
+ if (ctrl->i2c_conf && ctrl->i2c_conf->use_i2c_mux)
+ msm_camera_disable_i2c_mux(ctrl->i2c_conf);
+ break;
+ default:
+ pr_err("%s error power seq type %d\n", __func__,
+ power_setting->seq_type);
+ break;
+ }
+ if (power_setting->delay > 20) {
+ msleep(power_setting->delay);
+ } else if (power_setting->delay) {
+ usleep_range(power_setting->delay * 1000,
+ (power_setting->delay * 1000) + 1000);
+ }
+ }
+ msm_camera_request_gpio_table(
+ ctrl->gpio_conf->cam_gpio_req_tbl,
+ ctrl->gpio_conf->cam_gpio_req_tbl_size, 0);
+ return rc;
+}
+
+int32_t msm_camera_power_down(struct msm_camera_power_ctrl_t *ctrl,
+ enum msm_camera_device_type_t device_type,
+ struct msm_camera_i2c_client *sensor_i2c_client)
+{
+ int32_t index = 0;
+ struct msm_sensor_power_setting *power_setting = NULL;
+
+ CDBG("%s:%d\n", __func__, __LINE__);
+ if (!ctrl || !sensor_i2c_client) {
+ pr_err("failed ctrl %p sensor_i2c_client %p\n", ctrl,
+ sensor_i2c_client);
+ return -EINVAL;
+ }
+
+ if (device_type == MSM_CAMERA_PLATFORM_DEVICE)
+ sensor_i2c_client->i2c_func_tbl->i2c_util(
+ sensor_i2c_client, MSM_CCI_RELEASE);
+
+ for (index = (ctrl->power_setting_size - 1); index >= 0; index--) {
+ CDBG("%s index %d\n", __func__, index);
+ power_setting = &ctrl->power_setting[index];
+ CDBG("%s type %d\n", __func__, power_setting->seq_type);
+ switch (power_setting->seq_type) {
+ case SENSOR_CLK:
+ msm_cam_clk_enable(ctrl->dev,
+ &ctrl->clk_info[0],
+ (struct clk **)&power_setting->data[0],
+ ctrl->clk_info_size,
+ 0);
+ break;
+ case SENSOR_GPIO:
+ if (power_setting->seq_val >= SENSOR_GPIO_MAX ||
+ !ctrl->gpio_conf->gpio_num_info) {
+ pr_err("%s gpio index %d >= max %d\n", __func__,
+ power_setting->seq_val,
+ SENSOR_GPIO_MAX);
+ continue;
+ }
+ gpio_set_value_cansleep(
+ ctrl->gpio_conf->gpio_num_info->gpio_num
+ [power_setting->seq_val], GPIOF_OUT_INIT_LOW);
+ break;
+ case SENSOR_VREG:
+ if (power_setting->seq_val >= CAM_VREG_MAX) {
+ pr_err("%s vreg index %d >= max %d\n", __func__,
+ power_setting->seq_val,
+ SENSOR_GPIO_MAX);
+ continue;
+ }
+ msm_camera_config_single_vreg(ctrl->dev,
+ &ctrl->cam_vreg[power_setting->seq_val],
+ (struct regulator **)&power_setting->data[0],
+ 0);
+ break;
+ case SENSOR_I2C_MUX:
+ if (ctrl->i2c_conf && ctrl->i2c_conf->use_i2c_mux)
+ msm_camera_disable_i2c_mux(ctrl->i2c_conf);
+ break;
+ default:
+ pr_err("%s error power seq type %d\n", __func__,
+ power_setting->seq_type);
+ break;
+ }
+ if (power_setting->delay > 20) {
+ msleep(power_setting->delay);
+ } else if (power_setting->delay) {
+ usleep_range(power_setting->delay * 1000,
+ (power_setting->delay * 1000) + 1000);
+ }
+ }
+ msm_camera_request_gpio_table(
+ ctrl->gpio_conf->cam_gpio_req_tbl,
+ ctrl->gpio_conf->cam_gpio_req_tbl_size, 0);
+ CDBG("%s exit\n", __func__);
+ return 0;
+}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.h
new file mode 100644
index 0000000..5a35747
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_dt_util.h
@@ -0,0 +1,44 @@
+/* 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_CAMERA_DT_UTIL_H__
+#define MSM_CAMERA_DT_UTIL_H__
+
+#include <mach/camera2.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include "msm_camera_i2c.h"
+
+int32_t msm_camera_get_dt_power_setting_data(struct device_node *of_node,
+ struct msm_sensor_power_setting **power_setting,
+ uint16_t *power_setting_size);
+
+int32_t msm_camera_get_dt_gpio_req_tbl(struct device_node *of_node,
+ struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+ uint16_t gpio_array_size);
+
+int32_t msm_camera_init_gpio_pin_tbl(struct device_node *of_node,
+ struct msm_camera_gpio_conf *gconf, uint16_t *gpio_array,
+ uint16_t gpio_array_size);
+
+int32_t msm_camera_get_dt_vreg_data(struct device_node *of_node,
+ struct camera_vreg_t **cam_vreg, int *num_vreg);
+
+int32_t msm_camera_power_up(struct msm_camera_power_ctrl_t *ctrl,
+ enum msm_camera_device_type_t device_type,
+ struct msm_camera_i2c_client *sensor_i2c_client);
+
+int32_t msm_camera_power_down(struct msm_camera_power_ctrl_t *ctrl,
+ enum msm_camera_device_type_t device_type,
+ struct msm_camera_i2c_client *sensor_i2c_client);
+
+#endif
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c.h
index 26f1c4f..b1331ab 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c.h
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_i2c.h
@@ -21,6 +21,7 @@
struct msm_camera_i2c_fn_t *i2c_func_tbl;
struct i2c_client *client;
struct msm_camera_cci_client *cci_client;
+ struct msm_camera_spi_client *spi_client;
enum msm_camera_i2c_reg_addr_type addr_type;
};
@@ -31,13 +32,13 @@
};
struct msm_camera_i2c_fn_t {
- int (*i2c_read) (struct msm_camera_i2c_client *, uint16_t, uint16_t *,
+ int (*i2c_read) (struct msm_camera_i2c_client *, uint32_t, uint16_t *,
enum msm_camera_i2c_data_type);
- int32_t (*i2c_read_seq)(struct msm_camera_i2c_client *, uint16_t,
+ int32_t (*i2c_read_seq)(struct msm_camera_i2c_client *, uint32_t,
uint8_t *, uint16_t);
- int (*i2c_write) (struct msm_camera_i2c_client *, uint16_t, uint16_t,
+ int (*i2c_write) (struct msm_camera_i2c_client *, uint32_t, uint16_t,
enum msm_camera_i2c_data_type);
- int (*i2c_write_seq) (struct msm_camera_i2c_client *, uint16_t ,
+ int (*i2c_write_seq) (struct msm_camera_i2c_client *, uint32_t ,
uint8_t *, uint16_t);
int32_t (*i2c_write_table)(struct msm_camera_i2c_client *,
struct msm_camera_i2c_reg_setting *);
@@ -51,21 +52,24 @@
int32_t (*i2c_write_conf_tbl)(struct msm_camera_i2c_client *client,
struct msm_camera_i2c_reg_conf *reg_conf_tbl, uint16_t size,
enum msm_camera_i2c_data_type data_type);
+ int32_t (*i2c_poll)(struct msm_camera_i2c_client *client,
+ uint32_t addr, uint16_t data,
+ enum msm_camera_i2c_data_type data_type);
};
int32_t msm_camera_cci_i2c_read(struct msm_camera_i2c_client *client,
- uint16_t addr, uint16_t *data,
+ uint32_t addr, uint16_t *data,
enum msm_camera_i2c_data_type data_type);
int32_t msm_camera_cci_i2c_read_seq(struct msm_camera_i2c_client *client,
- uint16_t addr, uint8_t *data, uint16_t num_byte);
+ uint32_t addr, uint8_t *data, uint16_t num_byte);
int32_t msm_camera_cci_i2c_write(struct msm_camera_i2c_client *client,
- uint16_t addr, uint16_t data,
+ uint32_t addr, uint16_t data,
enum msm_camera_i2c_data_type data_type);
int32_t msm_camera_cci_i2c_write_seq(struct msm_camera_i2c_client *client,
- uint16_t addr, uint8_t *data, uint16_t num_byte);
+ uint32_t addr, uint8_t *data, uint16_t num_byte);
int32_t msm_camera_cci_i2c_write_table(
struct msm_camera_i2c_client *client,
@@ -88,19 +92,23 @@
int32_t msm_sensor_cci_i2c_util(struct msm_camera_i2c_client *client,
uint16_t cci_cmd);
+int32_t msm_camera_cci_i2c_poll(struct msm_camera_i2c_client *client,
+ uint32_t addr, uint16_t data,
+ enum msm_camera_i2c_data_type data_type);
+
int32_t msm_camera_qup_i2c_read(struct msm_camera_i2c_client *client,
- uint16_t addr, uint16_t *data,
+ uint32_t addr, uint16_t *data,
enum msm_camera_i2c_data_type data_type);
int32_t msm_camera_qup_i2c_read_seq(struct msm_camera_i2c_client *client,
- uint16_t addr, uint8_t *data, uint16_t num_byte);
+ uint32_t addr, uint8_t *data, uint16_t num_byte);
int32_t msm_camera_qup_i2c_write(struct msm_camera_i2c_client *client,
- uint16_t addr, uint16_t data,
+ uint32_t addr, uint16_t data,
enum msm_camera_i2c_data_type data_type);
int32_t msm_camera_qup_i2c_write_seq(struct msm_camera_i2c_client *client,
- uint16_t addr, uint8_t *data, uint16_t num_byte);
+ uint32_t addr, uint8_t *data, uint16_t num_byte);
int32_t msm_camera_qup_i2c_write_table(struct msm_camera_i2c_client *client,
struct msm_camera_i2c_reg_setting *write_setting);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c
index 55f27e0..9222bb5 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_qup_i2c.c
@@ -69,7 +69,7 @@
}
int32_t msm_camera_qup_i2c_read(struct msm_camera_i2c_client *client,
- uint16_t addr, uint16_t *data,
+ uint32_t addr, uint16_t *data,
enum msm_camera_i2c_data_type data_type)
{
int32_t rc = -EFAULT;
@@ -103,7 +103,7 @@
}
int32_t msm_camera_qup_i2c_read_seq(struct msm_camera_i2c_client *client,
- uint16_t addr, uint8_t *data, uint16_t num_byte)
+ uint32_t addr, uint8_t *data, uint16_t num_byte)
{
int32_t rc = -EFAULT;
unsigned char buf[client->addr_type+num_byte];
@@ -136,7 +136,7 @@
}
int32_t msm_camera_qup_i2c_write(struct msm_camera_i2c_client *client,
- uint16_t addr, uint16_t data,
+ uint32_t addr, uint16_t data,
enum msm_camera_i2c_data_type data_type)
{
int32_t rc = -EFAULT;
@@ -184,7 +184,7 @@
}
int32_t msm_camera_qup_i2c_write_seq(struct msm_camera_i2c_client *client,
- uint16_t addr, uint8_t *data, uint16_t num_byte)
+ uint32_t addr, uint8_t *data, uint16_t num_byte)
{
int32_t rc = -EFAULT;
unsigned char buf[client->addr_type+num_byte];
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.c
new file mode 100644
index 0000000..d1d5f23
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.c
@@ -0,0 +1,154 @@
+/* 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 <mach/camera2.h>
+#include "msm_camera_spi.h"
+
+#undef SPIDBG
+#ifdef CONFIG_MSMB_CAMERA_DEBUG
+#define SPIDBG(fmt, args...) pr_debug(fmt, ##args)
+#define S_I2C_DBG(fmt, args...) pr_debug(fmt, ##args)
+#else
+#define SPIDBG(fmt, args...) do { } while (0)
+#define S_I2C_DBG(fmt, args...) do { } while (0)
+#endif
+
+static int msm_camera_spi_txfr(struct spi_device *spi, char *txbuf,
+ char *rxbuf, int num_byte)
+{
+ struct spi_transfer t;
+ struct spi_message m;
+
+ memset(&t, 0, sizeof(t));
+ t.tx_buf = txbuf;
+ t.rx_buf = rxbuf;
+ t.len = num_byte;
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ return spi_sync(spi, &m);
+}
+
+/**
+ * msm_camera_set_addr() - helper function to set transfer address
+ * @addr: device address
+ * @addr_len: the addr field length of an instruction
+ * @type: type (i.e. byte-length) of @addr
+ * @str: shifted address output, must be zeroed when passed in
+ *
+ * This helper function sets @str based on the addr field length of an
+ * instruction and the data length.
+ */
+static void msm_camera_set_addr(uint32_t addr, uint8_t addr_len,
+ enum msm_camera_i2c_reg_addr_type type,
+ char *str)
+{
+ int i, len;
+
+ if (addr_len < type)
+ SPIDBG("%s: omitting higher bits in address\n", __func__);
+
+ /* only support transfer MSB first for now */
+ len = addr_len - type;
+ for (i = len; i < addr_len; i++) {
+ if (i >= 0)
+ str[i] = (addr >> (BITS_PER_BYTE * (addr_len - i - 1)))
+ & 0xFF;
+ }
+
+}
+
+static int32_t msm_camera_spi_read_helper(struct msm_camera_i2c_client *client,
+ struct msm_camera_spi_inst *inst, uint32_t addr, uint8_t *data,
+ uint16_t num_byte)
+{
+ int32_t rc = -EFAULT;
+ struct spi_device *spi = client->spi_client->spi_master;
+ char *tx, *rx;
+ uint16_t len;
+ int8_t retries = client->spi_client->retries;
+
+ if ((client->addr_type != MSM_CAMERA_I2C_BYTE_ADDR)
+ && (client->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+ && (client->addr_type != MSM_CAMERA_I2C_3B_ADDR))
+ return rc;
+
+ len = sizeof(inst->opcode) + inst->addr_len + inst->dummy_len
+ + num_byte;
+
+ tx = kmalloc(len, GFP_KERNEL | GFP_DMA);
+ if (!tx)
+ return -ENOMEM;
+ rx = kmalloc(len, GFP_KERNEL | GFP_DMA);
+ if (!rx) {
+ kfree(tx);
+ return -ENOMEM;
+ }
+ memset(tx, 0, len);
+ memset(rx, 0, len);
+
+ tx[0] = inst->opcode;
+ msm_camera_set_addr(addr, inst->addr_len, client->addr_type, tx + 1);
+ while ((rc = msm_camera_spi_txfr(spi, tx, rx, len)) && retries) {
+ retries--;
+ msleep(client->spi_client->retry_delay);
+ }
+ if (rc) {
+ SPIDBG("%s: failed %d\n", __func__, rc);
+ goto out;
+ }
+ len = sizeof(inst->opcode) + inst->addr_len + inst->dummy_len;
+ memcpy(data, rx + len, num_byte);
+out:
+ kfree(tx);
+ kfree(rx);
+ return rc;
+}
+
+int32_t msm_camera_spi_read(struct msm_camera_i2c_client *client,
+ uint32_t addr, uint16_t *data,
+ enum msm_camera_i2c_data_type data_type)
+{
+ int32_t rc = -EFAULT;
+ uint8_t temp[2];
+
+ if ((data_type != MSM_CAMERA_I2C_BYTE_DATA)
+ && (data_type != MSM_CAMERA_I2C_WORD_DATA))
+ return rc;
+
+ rc = msm_camera_spi_read_helper(client,
+ &client->spi_client->cmd_tbl.read, addr, &temp[0], data_type);
+ if (rc)
+ return rc;
+
+ if (data_type == MSM_CAMERA_I2C_BYTE_DATA)
+ *data = temp[0];
+ else
+ *data = (temp[0] << BITS_PER_BYTE) | temp[1];
+
+ SPIDBG("%s: addr 0x%x, data %u\n", __func__, addr, *data);
+ return rc;
+}
+
+int32_t msm_camera_spi_read_seq(struct msm_camera_i2c_client *client,
+ uint32_t addr, uint8_t *data, uint16_t num_byte)
+{
+ return msm_camera_spi_read_helper(client,
+ &client->spi_client->cmd_tbl.read_seq, addr, data, num_byte);
+}
+
+int32_t msm_camera_spi_query_id(struct msm_camera_i2c_client *client,
+ uint32_t addr, uint8_t *data, uint16_t num_byte)
+{
+ return msm_camera_spi_read_helper(client,
+ &client->spi_client->cmd_tbl.query_id, addr, data, num_byte);
+}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.h b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.h
new file mode 100644
index 0000000..564e470
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_spi.h
@@ -0,0 +1,51 @@
+/* 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_CAMERA_SPI_H
+#define __MSM_CAMERA_SPI_H
+
+#include <linux/spi/spi.h>
+#include <media/msm_cam_sensor.h>
+#include "msm_camera_i2c.h"
+
+struct msm_camera_spi_inst {
+ uint8_t opcode; /* one-byte opcode */
+ uint8_t addr_len; /* addr len in bytes */
+ uint8_t dummy_len; /* setup cycles */
+};
+
+struct msm_camera_spi_inst_tbl {
+ struct msm_camera_spi_inst read;
+ struct msm_camera_spi_inst read_seq;
+ struct msm_camera_spi_inst query_id;
+};
+
+struct msm_camera_spi_client {
+ struct spi_device *spi_master;
+ struct msm_camera_spi_inst_tbl cmd_tbl;
+ uint8_t device_id;
+ uint8_t mfr_id;
+ uint8_t retry_delay; /* ms */
+ uint8_t retries; /* retry times upon failure */
+};
+
+int32_t msm_camera_spi_read(struct msm_camera_i2c_client *client,
+ uint32_t addr, uint16_t *data,
+ enum msm_camera_i2c_data_type data_type);
+
+int32_t msm_camera_spi_read_seq(struct msm_camera_i2c_client *client,
+ uint32_t addr, uint8_t *data, uint16_t num_byte);
+
+int32_t msm_camera_spi_query_id(struct msm_camera_i2c_client *client,
+ uint32_t addr, uint8_t *data, uint16_t num_byte);
+
+#endif
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index 453b14a..fa63e2b 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -78,6 +78,23 @@
src_node = NULL;
}
+ src_node = of_parse_phandle(of_node, "qcom,eeprom-src", 0);
+ if (!src_node) {
+ CDBG("%s:%d eeprom src_node NULL\n", __func__, __LINE__);
+ } else {
+ rc = of_property_read_u32(src_node, "cell-index", &val);
+ CDBG("%s qcom,eeprom cell index %d, rc %d\n", __func__,
+ val, rc);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR;
+ }
+ sensordata->sensor_info->
+ subdev_id[SUB_MODULE_EEPROM] = val;
+ of_node_put(src_node);
+ src_node = NULL;
+ }
+
if (of_property_read_bool(of_node, "qcom,eeprom-sd-index") ==
true) {
rc = of_property_read_u32(of_node, "qcom,eeprom-sd-index",
diff --git a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 83b9bb3..6775a23 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -640,109 +640,109 @@
debugfs_create_u32(
"hw_notification_interval",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->hw_notification_interval);
debugfs_create_u32(
"hw_notification_min_interval",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->hw_notification_min_interval);
debugfs_create_u32(
"hw_notification_count",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->hw_notification_count);
debugfs_create_u32(
"hw_notification_size",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->hw_notification_size);
debugfs_create_u32(
"hw_notification_min_size",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->hw_notification_min_size);
debugfs_create_u32(
"decoder_drop_count",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->decoder_drop_count);
debugfs_create_u32(
"decoder_out_count",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->decoder_out_count);
debugfs_create_u32(
"decoder_out_interval_sum",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->decoder_out_interval_sum);
debugfs_create_u32(
"decoder_out_interval_average",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->decoder_out_interval_average);
debugfs_create_u32(
"decoder_out_interval_max",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->decoder_out_interval_max);
debugfs_create_u32(
"decoder_ts_errors",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->decoder_ts_errors);
debugfs_create_u32(
"sdmx_process_count",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->sdmx_process_count);
debugfs_create_u32(
"sdmx_process_time_sum",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->sdmx_process_time_sum);
debugfs_create_u32(
"sdmx_process_time_average",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->sdmx_process_time_average);
debugfs_create_u32(
"sdmx_process_time_max",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->sdmx_process_time_max);
debugfs_create_u32(
"sdmx_process_packets_sum",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->sdmx_process_packets_sum);
debugfs_create_u32(
"sdmx_process_packets_average",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->sdmx_process_packets_average);
debugfs_create_u32(
"sdmx_process_packets_min",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
mpq_demux->demux.dmx.debugfs_demux_dir,
&mpq_demux->sdmx_process_packets_min);
}
@@ -1220,6 +1220,8 @@
{
struct mpq_demux *mpq_demux = feed->demux->priv;
+ MPQ_DVB_DBG_PRINT("%s: cookie=%d\n", __func__, cookie);
+
if (cookie < 0) {
MPQ_DVB_ERR_PRINT("%s: invalid cookie parameter\n", __func__);
return -EINVAL;
@@ -2441,9 +2443,15 @@
data->data_length = 0;
data->buf.handle = packet->raw_data_handle;
+
/* this has to succeed when called here, after packet was written */
data->buf.cookie = mpq_streambuffer_pkt_next(stream_buffer,
feed_data->last_pkt_index, &len);
+ if (data->buf.cookie < 0)
+ MPQ_DVB_DBG_PRINT(
+ "%s: received invalid packet index %d\n",
+ __func__, data->buf.cookie);
+
data->buf.offset = packet->raw_data_offset;
data->buf.len = packet->raw_data_len;
data->buf.pts_exists = pts_dts->pts_exist;
@@ -2459,6 +2467,8 @@
/* save for next time: */
feed_data->last_pkt_index = data->buf.cookie;
+ MPQ_DVB_DBG_PRINT("%s: cookie=%d\n", __func__, data->buf.cookie);
+
/* reset counters */
feed_data->ts_packets_num = 0;
feed_data->ts_dropped_bytes = 0;
@@ -4235,7 +4245,12 @@
__func__, ret);
}
mpq_dmx_update_decoder_stat(mpq_demux);
- mpq_streambuffer_pkt_write(sbuf, &packet, (u8 *)&meta_data);
+ if (mpq_streambuffer_pkt_write(sbuf,
+ &packet,
+ (u8 *)&meta_data) < 0)
+ MPQ_DVB_ERR_PRINT(
+ "%s: Couldn't write packet. Should never happen\n",
+ __func__);
mpq_dmx_prepare_es_event_data(
&packet, &meta_data, &mpq_feed->video_info,
diff --git a/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c b/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
index b9fdc5e..45a9dd5 100644
--- a/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
+++ b/drivers/media/platform/msm/dvb/video/mpq_dvb_video.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -31,7 +31,7 @@
#include <linux/clk.h>
#include <linux/timer.h>
-#include <mach/msm_subsystem_map.h>
+#include <mach/iommu_domains.h>
#include <media/msm/vidc_type.h>
#include <media/msm/vcd_api.h>
#include <media/msm/vidc_init.h>
@@ -1188,9 +1188,6 @@
if (!client_ctx)
return -EINVAL;
- if (client_ctx->vcd_h264_mv_buffer.client_data)
- msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
- client_ctx->vcd_h264_mv_buffer.client_data);
vcd_property_hdr.prop_id = VCD_I_FREE_H264_MV_BUFFER;
vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
diff --git a/drivers/media/platform/msm/vidc/Kconfig b/drivers/media/platform/msm/vidc/Kconfig
index 3fc2b9e..4a27fd3 100644
--- a/drivers/media/platform/msm/vidc/Kconfig
+++ b/drivers/media/platform/msm/vidc/Kconfig
@@ -4,4 +4,4 @@
menuconfig MSM_VIDC_V4L2
bool "Qualcomm MSM V4L2 based video driver"
- depends on (ARCH_MSM8974 || ARCH_MSM8610) && VIDEO_V4L2
+ depends on (ARCH_MSM8974 || ARCH_MSM8610 || ARCH_MSM8226) && VIDEO_V4L2
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 102e1ec..91fb514 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -1003,12 +1003,6 @@
return;
}
- sess_close = (struct hal_session *)pkt->session_id;
- dprintk(VIDC_INFO, "deleted the session: 0x%x",
- sess_close->session_id);
- list_del(&sess_close->list);
- kfree(sess_close);
-
memset(&cmd_done, 0, sizeof(struct msm_vidc_cb_cmd_done));
cmd_done.device_id = device_id;
cmd_done.session_id =
@@ -1016,6 +1010,11 @@
cmd_done.status = hfi_map_err_status((u32)pkt->error_type);
cmd_done.data = NULL;
cmd_done.size = 0;
+ sess_close = (struct hal_session *)pkt->session_id;
+ dprintk(VIDC_INFO, "deleted the session: 0x%x",
+ sess_close->session_id);
+ list_del(&sess_close->list);
+ kfree(sess_close);
callback(SESSION_END_DONE, &cmd_done);
}
diff --git a/drivers/media/platform/msm/vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c
index b3bce5f..79a492e 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.c
+++ b/drivers/media/platform/msm/vidc/msm_smem.c
@@ -80,12 +80,18 @@
goto mem_domain_get_failed;
}
}
- rc = ion_map_iommu(clnt, hndl, domain, partition, align,
- 0, iova, buffer_size, 0, 0);
+ if (is_iommu_present(smem_client->res)) {
+ dprintk(VIDC_DBG,
+ "Calling ion_map_iommu - domain: %d, partition: %d",
+ domain, partition);
+ rc = ion_map_iommu(clnt, hndl, domain, partition, align,
+ 0, iova, buffer_size, 0, 0);
+ } else {
+ dprintk(VIDC_DBG, "Using physical memory address");
+ rc = ion_phys(clnt, hndl, iova, (size_t *)buffer_size);
+ }
if (rc) {
- dprintk(VIDC_ERR,
- "ion_map_iommu failed(%d).domain: %d,partition: %d\n",
- rc, domain, partition);
+ dprintk(VIDC_ERR, "ion memory map failed - %d", rc);
goto mem_map_failed;
}
@@ -97,10 +103,28 @@
return rc;
}
-static void put_device_address(struct ion_client *clnt,
+static void put_device_address(struct smem_client *smem_client,
struct ion_handle *hndl, int domain_num, int partition_num, u32 flags)
{
- ion_unmap_iommu(clnt, hndl, domain_num, partition_num);
+ struct ion_client *clnt = NULL;
+
+ if (!hndl || !smem_client) {
+ dprintk(VIDC_WARN, "Invalid params: %p, %p\n",
+ smem_client, hndl);
+ return;
+ }
+
+ clnt = smem_client->clnt;
+ if (!clnt) {
+ dprintk(VIDC_WARN, "Invalid client");
+ return;
+ }
+ if (is_iommu_present(smem_client->res)) {
+ dprintk(VIDC_DBG,
+ "Calling ion_unmap_iommu - domain: %d, parition: %d",
+ domain_num, partition_num);
+ ion_unmap_iommu(clnt, hndl, domain_num, partition_num);
+ }
if (flags & SMEM_SECURE) {
if (msm_ion_unsecure_buffer(clnt, hndl))
dprintk(VIDC_ERR, "Failed to unsecure memory\n");
@@ -128,16 +152,7 @@
rc = ion_handle_get_flags(client->clnt, hndl, &ionflags);
if (rc) {
dprintk(VIDC_ERR, "Failed to get ion flags: %d\n", rc);
- goto fail_map;
- }
- if (ION_IS_CACHED(ionflags)) {
- mem->kvaddr = ion_map_kernel(client->clnt, hndl);
- if (!mem->kvaddr) {
- dprintk(VIDC_ERR,
- "Failed to map shared mem in kernel\n");
- rc = -EIO;
- goto fail_map;
- }
+ goto fail_device_address;
}
mem->flags = ionflags;
@@ -160,9 +175,6 @@
mem->device_addr, mem->size);
return rc;
fail_device_address:
- if (mem->kvaddr)
- ion_unmap_kernel(client->clnt, hndl);
-fail_map:
ion_free(client->clnt, hndl);
fail_import_fd:
return rc;
@@ -186,7 +198,15 @@
align = ALIGN(align, SZ_1M);
}
- heap_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
+ if (is_iommu_present(client->res)) {
+ heap_mask = ION_HEAP(ION_IOMMU_HEAP_ID);
+ } else {
+ dprintk(VIDC_DBG,
+ "allocate shared memory from adsp heap size %d align %d\n",
+ size, align);
+ heap_mask = ION_HEAP(ION_ADSP_HEAP_ID);
+ }
+
if (flags & SMEM_SECURE)
heap_mask = ION_HEAP(ION_CP_MM_HEAP_ID);
@@ -246,7 +266,7 @@
}
if (mem->device_addr)
- put_device_address(client->clnt,
+ put_device_address(client,
mem->smem_priv, domain, partition, mem->flags);
if (mem->kvaddr)
ion_unmap_kernel(client->clnt, mem->smem_priv);
@@ -334,20 +354,14 @@
rc = -EINVAL;
goto cache_op_failed;
}
- if (mem->kvaddr) {
- rc = msm_ion_do_cache_op(client->clnt,
- (struct ion_handle *)mem->smem_priv,
- (unsigned long *) mem->kvaddr,
- (unsigned long)mem->size,
- msm_cache_ops);
- if (rc) {
- dprintk(VIDC_ERR,
+ rc = msm_ion_do_cache_op(client->clnt,
+ (struct ion_handle *)mem->smem_priv,
+ 0, (unsigned long)mem->size,
+ msm_cache_ops);
+ if (rc) {
+ dprintk(VIDC_ERR,
"cache operation failed %d\n", rc);
- goto cache_op_failed;
- }
- } else {
- dprintk(VIDC_WARN,
- "cache operation failed as no kernel mapping\n");
+ goto cache_op_failed;
}
}
cache_op_failed:
diff --git a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
index d782227..687bd71 100644
--- a/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_v4l2_vidc.c
@@ -1061,10 +1061,9 @@
if (!of_get_property(pdev->dev.of_node, "qcom,iommu-groups",
&array_size)) {
- dprintk(VIDC_ERR, "Could not find iommu_groups property\n");
+ dprintk(VIDC_DBG, "iommu_groups property not present\n");
iommu_group_set->count = 0;
- rc = -ENOENT;
- goto err_no_of_node;
+ return 0;
}
iommu_group_set->count = array_size / sizeof(u32);
@@ -1245,6 +1244,15 @@
"Failed to load buffer usage table: %d\n", rc);
goto err_load_buffer_usage_table;
}
+
+ rc = of_property_read_u32(pdev->dev.of_node, "qcom,max-hw-load",
+ &res->max_load);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to determine max load supported: %d\n", rc);
+ goto err_load_buffer_usage_table;
+ }
+
return rc;
err_load_buffer_usage_table:
@@ -1295,6 +1303,8 @@
res->load_freq_tbl[c].load = pdata->load_table[c][0];
res->load_freq_tbl[c].freq = pdata->load_table[c][1];
}
+
+ res->max_load = pdata->max_load;
return rc;
}
@@ -1348,10 +1358,37 @@
return rc;
}
+static ssize_t msm_vidc_link_name_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct msm_vidc_core *core = dev_get_drvdata(dev);
+ if (core)
+ if (dev == &core->vdev[MSM_VIDC_DECODER].vdev.dev)
+ if (core->hfi_type == VIDC_HFI_Q6)
+ return snprintf(buf, PAGE_SIZE, "q6_dec");
+ else
+ return snprintf(buf, PAGE_SIZE, "venus_dec");
+ else if (dev == &core->vdev[MSM_VIDC_ENCODER].vdev.dev)
+ if (core->hfi_type == VIDC_HFI_Q6)
+ return snprintf(buf, PAGE_SIZE, "q6_enc");
+ else
+ return snprintf(buf, PAGE_SIZE, "venus_enc");
+ else
+ return 0;
+ else
+ return 0;
+}
+
+static DEVICE_ATTR(link_name, 0644, msm_vidc_link_name_show, NULL);
+
static int __devinit msm_vidc_probe(struct platform_device *pdev)
{
int rc = 0;
struct msm_vidc_core *core;
+ struct device *dev;
+ int nr = BASE_DEVICE_NUMBER;
+
core = kzalloc(sizeof(*core), GFP_KERNEL);
if (!core || !vidc_driver) {
dprintk(VIDC_ERR,
@@ -1364,6 +1401,10 @@
dprintk(VIDC_ERR, "Failed to init core\n");
goto err_v4l2_register;
}
+ if (core->hfi_type == VIDC_HFI_Q6) {
+ dprintk(VIDC_ERR, "Q6 hfi device probe called\n");
+ nr += MSM_VIDC_MAX_DEVICES;
+ }
rc = v4l2_device_register(&pdev->dev, &core->v4l2_dev);
if (rc) {
dprintk(VIDC_ERR, "Failed to register v4l2 device\n");
@@ -1375,12 +1416,19 @@
core->vdev[MSM_VIDC_DECODER].vdev.ioctl_ops = &msm_v4l2_ioctl_ops;
core->vdev[MSM_VIDC_DECODER].type = MSM_VIDC_DECODER;
rc = video_register_device(&core->vdev[MSM_VIDC_DECODER].vdev,
- VFL_TYPE_GRABBER, BASE_DEVICE_NUMBER);
+ VFL_TYPE_GRABBER, nr);
if (rc) {
dprintk(VIDC_ERR, "Failed to register video decoder device");
goto err_dec_register;
}
video_set_drvdata(&core->vdev[MSM_VIDC_DECODER].vdev, core);
+ dev = &core->vdev[MSM_VIDC_DECODER].vdev.dev;
+ rc = device_create_file(dev, &dev_attr_link_name);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to create link name sysfs for decoder");
+ goto err_dec_attr_link_name;
+ }
core->vdev[MSM_VIDC_ENCODER].vdev.release =
msm_vidc_release_video_device;
@@ -1388,19 +1436,20 @@
core->vdev[MSM_VIDC_ENCODER].vdev.ioctl_ops = &msm_v4l2_ioctl_ops;
core->vdev[MSM_VIDC_ENCODER].type = MSM_VIDC_ENCODER;
rc = video_register_device(&core->vdev[MSM_VIDC_ENCODER].vdev,
- VFL_TYPE_GRABBER, BASE_DEVICE_NUMBER + 1);
+ VFL_TYPE_GRABBER, nr + 1);
if (rc) {
dprintk(VIDC_ERR, "Failed to register video encoder device");
goto err_enc_register;
}
video_set_drvdata(&core->vdev[MSM_VIDC_ENCODER].vdev, core);
-
- core->device = vidc_hfi_initialize(core->hfi_type, core->id,
- &core->resources, &handle_cmd_response);
- if (!core->device) {
- dprintk(VIDC_ERR, "Failed to create HFI device\n");
- goto err_cores_exceeded;
+ dev = &core->vdev[MSM_VIDC_ENCODER].vdev.dev;
+ rc = device_create_file(dev, &dev_attr_link_name);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to create link name sysfs for encoder");
+ goto err_enc_attr_link_name;
}
+
mutex_lock(&vidc_driver->lock);
if (vidc_driver->num_cores + 1 > MSM_VIDC_CORES_MAX) {
mutex_unlock(&vidc_driver->lock);
@@ -1408,8 +1457,20 @@
vidc_driver->num_cores);
goto err_cores_exceeded;
}
-
core->id = vidc_driver->num_cores++;
+ mutex_unlock(&vidc_driver->lock);
+
+ core->device = vidc_hfi_initialize(core->hfi_type, core->id,
+ &core->resources, &handle_cmd_response);
+ if (!core->device) {
+ dprintk(VIDC_ERR, "Failed to create HFI device\n");
+ mutex_lock(&vidc_driver->lock);
+ vidc_driver->num_cores--;
+ mutex_unlock(&vidc_driver->lock);
+ goto err_cores_exceeded;
+ }
+
+ mutex_lock(&vidc_driver->lock);
list_add_tail(&core->list, &vidc_driver->cores);
mutex_unlock(&vidc_driver->lock);
core->debugfs_root = msm_vidc_debugfs_init_core(
@@ -1418,8 +1479,14 @@
return rc;
err_cores_exceeded:
+ device_remove_file(&core->vdev[MSM_VIDC_ENCODER].vdev.dev,
+ &dev_attr_link_name);
+err_enc_attr_link_name:
video_unregister_device(&core->vdev[MSM_VIDC_ENCODER].vdev);
err_enc_register:
+ device_remove_file(&core->vdev[MSM_VIDC_DECODER].vdev.dev,
+ &dev_attr_link_name);
+err_dec_attr_link_name:
video_unregister_device(&core->vdev[MSM_VIDC_DECODER].vdev);
err_dec_register:
v4l2_device_unregister(&core->v4l2_dev);
@@ -1446,7 +1513,11 @@
}
vidc_hfi_deinitialize(core->hfi_type, core->device);
+ device_remove_file(&core->vdev[MSM_VIDC_ENCODER].vdev.dev,
+ &dev_attr_link_name);
video_unregister_device(&core->vdev[MSM_VIDC_ENCODER].vdev);
+ device_remove_file(&core->vdev[MSM_VIDC_DECODER].vdev.dev,
+ &dev_attr_link_name);
video_unregister_device(&core->vdev[MSM_VIDC_DECODER].vdev);
v4l2_device_unregister(&core->v4l2_dev);
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 2ca5008..6cf2572 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -621,13 +621,6 @@
frame_sz.height = inst->prop.height;
dprintk(VIDC_DBG, "width = %d, height = %d\n",
frame_sz.width, frame_sz.height);
- rc = msm_comm_try_set_prop(inst,
- HAL_PARAM_FRAME_SIZE, &frame_sz);
- if (rc) {
- dprintk(VIDC_ERR,
- "%s: Failed : Frame size setting\n", __func__);
- goto exit;
- }
rc = msm_comm_try_get_bufreqs(inst);
if (rc) {
dprintk(VIDC_ERR,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 30530d4..adf6dec 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -22,7 +22,7 @@
#include "msm_smem.h"
#include "msm_vidc_debug.h"
-#define HW_RESPONSE_TIMEOUT msecs_to_jiffies(200)
+#define HW_RESPONSE_TIMEOUT 200
#define IS_ALREADY_IN_STATE(__p, __d) ({\
int __rc = (__p >= __d);\
@@ -49,11 +49,6 @@
#define TIME_DIFF_THRESHOLD 200
-/*Load is in Macroblocks (MBs) per sec. This value is calculated
- * based on one 4k video instance @ 24 fps plus one 1080p video
- * instance @ 30fps. 1 MB = 16 X 16 pixels*/
-#define MAX_LOAD 1074240
-
static int msm_comm_get_load(struct msm_vidc_core *core,
enum session_type type)
{
@@ -380,7 +375,7 @@
struct msm_vidc_inst *inst;
struct v4l2_control control = {0};
struct msm_vidc_cb_event *event_notify;
- int event = 0;
+ int event = V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT;
int rc = 0;
if (response) {
inst = (struct msm_vidc_inst *)response->session_id;
@@ -403,11 +398,14 @@
default:
break;
}
-
- inst->reconfig_height = event_notify->height;
- inst->reconfig_width = event_notify->width;
- inst->in_reconfig = true;
-
+ if (event == V4L2_EVENT_SEQ_CHANGED_INSUFFICIENT) {
+ 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;
+ }
rc = msm_vidc_check_session_supported(inst);
if (!rc) {
queue_v4l2_event(inst, event);
@@ -826,6 +824,7 @@
vb->v4l2_planes[0].bytesused = fill_buf_done->filled_len1;
vb->v4l2_buf.flags = V4L2_QCOM_BUF_FLAG_CODECCONFIG;
+ vb->v4l2_buf.timestamp = ns_to_timeval(0);
dprintk(VIDC_DBG, "Filled length = %d; flags %x\n",
vb->v4l2_planes[0].bytesused,
@@ -1265,13 +1264,32 @@
dprintk(VIDC_ERR, "%s invalid parameters", __func__);
return -EINVAL;
}
+
num_mbs_per_sec = msm_comm_get_load(inst->core, MSM_VIDC_DECODER);
num_mbs_per_sec += msm_comm_get_load(inst->core, MSM_VIDC_ENCODER);
- if (num_mbs_per_sec > MAX_LOAD) {
- dprintk(VIDC_ERR, "HW is overloaded, needed:%d max: %d\n",
- num_mbs_per_sec, MAX_LOAD);
+ if (num_mbs_per_sec > inst->core->resources.max_load) {
+ struct msm_vidc_inst *temp;
+
+ dprintk(VIDC_ERR, "HW is overloaded, needed: %d max: %d\n",
+ num_mbs_per_sec, inst->core->resources.max_load);
+ dprintk(VIDC_ERR, "Running instances:\n");
+ dprintk(VIDC_ERR, "%4s|%4s|%4s|%4s\n", "type", "w", "h", "fps");
+ list_for_each_entry(temp, &inst->core->instances, list) {
+ mutex_lock(&temp->lock);
+ if (temp->state >= MSM_VIDC_OPEN_DONE &&
+ 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.fps);
+ }
+ mutex_unlock(&temp->lock);
+ }
+
return -ENOMEM;
}
+
hdev = inst->core->device;
if (IS_ALREADY_IN_STATE(flipped_state, MSM_VIDC_LOAD_RESOURCES)) {
@@ -1431,7 +1449,7 @@
"Failed to send close\n");
goto exit;
}
- change_inst_state(inst, MSM_VIDC_OPEN);
+ change_inst_state(inst, MSM_VIDC_CLOSE);
exit:
return rc;
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 1bfbaa6..e5696be 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -37,7 +37,7 @@
#define MSM_VIDC_VERSION KERNEL_VERSION(0, 0, 1);
#define MAX_DEBUGFS_NAME 50
#define DEFAULT_TIMEOUT 3
-#define DEFAULT_HEIGHT 1080
+#define DEFAULT_HEIGHT 1088
#define DEFAULT_WIDTH 1920
#define MIN_SUPPORTED_WIDTH 32
#define MIN_SUPPORTED_HEIGHT 32
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index 86b824b..43af909 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -74,8 +74,17 @@
struct iommu_set iommu_group_set;
struct buffer_usage_set buffer_usage_set;
bool has_ocmem;
+ uint32_t max_load;
struct platform_device *pdev;
};
+static inline int is_iommu_present(struct msm_vidc_platform_resources *res)
+{
+ if (res)
+ return (res->iommu_group_set.count > 0 &&
+ res->iommu_group_set.iommu_maps != NULL);
+ return 0;
+}
+
#endif
diff --git a/drivers/media/platform/msm/vidc/q6_hfi.c b/drivers/media/platform/msm/vidc/q6_hfi.c
index bf6c7db..123b654 100644
--- a/drivers/media/platform/msm/vidc/q6_hfi.c
+++ b/drivers/media/platform/msm/vidc/q6_hfi.c
@@ -479,7 +479,7 @@
q6_hfi_add_apr_hdr(dev, &apr.hdr, sizeof(apr), HFI_CMD_SYS_INIT);
- rc = create_pkt_cmd_sys_init(&apr.pkt, HFI_ARCH_OX_OFFSET);
+ rc = create_pkt_cmd_sys_init(&apr.pkt, HFI_VIDEO_ARCH_OX);
if (rc) {
dprintk(VIDC_ERR, "Failed to create sys init pkt");
goto err_core_init;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index b5dd15d..8031c74 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -386,11 +386,22 @@
msm_smem_free(clnt, mem);
}
-static void venus_hfi_write_register(u8 *base_addr, u32 reg,
+static void venus_hfi_write_register(struct venus_hfi_device *device, u32 reg,
u32 value, u8 *vaddr)
{
u32 hwiosymaddr = reg;
+ u8 *base_addr;
+ if (!device) {
+ dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+ return;
+ }
+ base_addr = device->hal_data->register_base_addr;
+ if (!device->clocks_enabled) {
+ dprintk(VIDC_WARN,
+ "HFI Write register failed : Clocks are OFF\n");
+ return;
+ }
reg &= REG_ADDR_OFFSET_BITMASK;
if (reg == (u32)VIDC_CPU_CS_SCIACMDARG2) {
/* workaround to offset of FW bias */
@@ -416,14 +427,26 @@
wmb();
}
-static int venus_hfi_read_register(u8 *base_addr, u32 reg)
+static int venus_hfi_read_register(struct venus_hfi_device *device, u32 reg)
{
- int rc = readl_relaxed((u32)base_addr + reg);
+ int rc ;
+ u8 *base_addr;
+ if (!device) {
+ dprintk(VIDC_ERR, "Invalid params: %p\n", device);
+ return -EINVAL;
+ }
+
+ base_addr = device->hal_data->register_base_addr;
+ if (!device->clocks_enabled) {
+ dprintk(VIDC_WARN,
+ "HFI Read register failed : Clocks are OFF\n");
+ return -EINVAL;
+ }
+ rc = readl_relaxed((u32)base_addr + reg);
rmb();
return rc;
}
-static inline void venus_hfi_clk_gating_on(struct venus_hfi_device *device,
- enum vidc_clocks clk_level)
+static inline void venus_hfi_clk_gating_on(struct venus_hfi_device *device)
{
int i;
struct venus_core_clock *cl;
@@ -431,19 +454,18 @@
dprintk(VIDC_ERR, "Invalid params: %p\n", device);
return;
}
- if (device->clocks_enabled == 0) {
- dprintk(VIDC_DBG, "VCODEC clocks are already disabled");
+ if (!device->clocks_enabled) {
+ dprintk(VIDC_DBG, "Clocks are already disabled");
goto already_disabled;
}
- for (i = 0; i < clk_level; i++) {
+ for (i = 0; i <= device->clk_gating_level; i++) {
cl = &device->resources.clock[i];
- clk_disable_unprepare(cl->clk);
+ clk_disable(cl->clk);
}
already_disabled:
device->clocks_enabled = 0;
}
-static inline int venus_hfi_clk_gating_off(struct venus_hfi_device *device,
- enum vidc_clocks clk_level)
+static inline int venus_hfi_clk_gating_off(struct venus_hfi_device *device)
{
int i;
struct venus_core_clock *cl;
@@ -452,13 +474,13 @@
dprintk(VIDC_ERR, "Invalid params: %p\n", device);
return -EINVAL;
}
- if (device->clocks_enabled == 1) {
- dprintk(VIDC_DBG, "VCODEC clocks are already enabled");
+ if (device->clocks_enabled) {
+ dprintk(VIDC_DBG, "Clocks are already enabled");
goto already_enabled;
}
- for (i = 0; i < clk_level; i++) {
+ for (i = 0; i <= device->clk_gating_level; i++) {
cl = &device->resources.clock[i];
- rc = clk_prepare_enable(cl->clk);
+ rc = clk_enable(cl->clk);
if (rc) {
dprintk(VIDC_ERR, "Failed to enable clocks\n");
goto fail_clk_enable;
@@ -472,7 +494,7 @@
fail_clk_enable:
for (; i >= 0; i--) {
cl = &device->resources.clock[i];
- clk_disable_unprepare(cl->clk);
+ clk_disable(cl->clk);
}
return rc;
}
@@ -482,7 +504,7 @@
{
int num_rows = clock->count;
struct load_freq_table *table = clock->load_freq_tbl;
- unsigned long ret = table[num_rows-1].freq;
+ unsigned long ret = table[0].freq;
int i;
for (i = 0; i < num_rows; i++) {
if (num_mbs_per_sec > table[i].load)
@@ -497,11 +519,11 @@
{
int rc = 0;
struct venus_hfi_device *device = dev;
- device->load = load;
if (!device) {
dprintk(VIDC_ERR, "Invalid args: %p\n", device);
return -EINVAL;
}
+ device->load = load;
rc = clk_set_rate(device->resources.clock[VCODEC_CLK].clk,
venus_hfi_get_clock_rate(&device->resources.clock[VCODEC_CLK],
load));
@@ -527,20 +549,22 @@
dprintk(VIDC_ERR, "cannot write to shared Q's");
goto err_q_write;
}
- result = venus_hfi_clk_gating_off(device, VCODEC_CLK);
+ mutex_lock(&device->clock_lock);
+ result = venus_hfi_clk_gating_off(device);
if (result) {
- dprintk(VIDC_ERR, "VCODEC clock enable failed\n");
+ dprintk(VIDC_ERR, "%s : Clock enable failed\n",
+ __func__);
goto err_q_write;
}
result = venus_hfi_scale_clocks(device, device->load);
if (result) {
- dprintk(VIDC_ERR, "VCODEC clock scaling failed\n");
+ dprintk(VIDC_ERR, "Clock scaling failed\n");
goto err_q_write;
}
if (!venus_hfi_write_queue(q_info, (u8 *)pkt, &rx_req_is_set)) {
if (rx_req_is_set)
venus_hfi_write_register(
- device->hal_data->register_base_addr,
+ device,
VIDC_CPU_IC_SOFTINT,
1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
result = 0;
@@ -549,6 +573,7 @@
}
err_q_write:
mutex_unlock(&device->write_lock);
+ mutex_unlock(&device->clock_lock);
return result;
}
@@ -570,11 +595,17 @@
goto read_error;
}
q_info = &device->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
-
+ mutex_lock(&device->clock_lock);
+ rc = venus_hfi_clk_gating_off(device);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s : Clock enable failed\n", __func__);
+ goto read_error;
+ }
if (!venus_hfi_read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) {
if (tx_req_is_set)
venus_hfi_write_register(
- device->hal_data->register_base_addr,
+ device,
VIDC_CPU_IC_SOFTINT,
1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
rc = 0;
@@ -584,6 +615,7 @@
}
read_error:
mutex_unlock(&device->read_lock);
+ mutex_unlock(&device->clock_lock);
return rc;
}
@@ -604,11 +636,18 @@
rc = -ENODATA;
goto dbg_error;
}
+ mutex_lock(&device->clock_lock);
+ rc = venus_hfi_clk_gating_off(device);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s : Clock enable failed\n", __func__);
+ goto dbg_error;
+ }
q_info = &device->iface_queues[VIDC_IFACEQ_DBGQ_IDX];
if (!venus_hfi_read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) {
if (tx_req_is_set)
venus_hfi_write_register(
- device->hal_data->register_base_addr,
+ device,
VIDC_CPU_IC_SOFTINT,
1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
rc = 0;
@@ -618,6 +657,7 @@
}
dbg_error:
mutex_unlock(&device->read_lock);
+ mutex_unlock(&device->clock_lock);
return rc;
}
@@ -822,16 +862,16 @@
iface_q->q_array.align_device_addr;
q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q;
- venus_hfi_write_register(dev->hal_data->register_base_addr,
+ venus_hfi_write_register(dev,
VIDC_UC_REGION_ADDR,
(u32) dev->iface_q_table.align_device_addr, 0);
- venus_hfi_write_register(dev->hal_data->register_base_addr,
+ venus_hfi_write_register(dev,
VIDC_UC_REGION_SIZE, SHARED_QSIZE, 0);
- venus_hfi_write_register(dev->hal_data->register_base_addr,
+ venus_hfi_write_register(dev,
VIDC_CPU_CS_SCIACMDARG2,
(u32) dev->iface_q_table.align_device_addr,
dev->iface_q_table.align_virtual_addr);
- venus_hfi_write_register(dev->hal_data->register_base_addr,
+ venus_hfi_write_register(dev,
VIDC_CPU_CS_SCIACMDARG1, 0x01,
dev->iface_q_table.align_virtual_addr);
@@ -851,14 +891,14 @@
dev->qdss.mem_data = NULL;
}
if (!IS_ERR_OR_NULL(dev->qdss.align_device_addr))
- venus_hfi_write_register(dev->hal_data->register_base_addr,
+ venus_hfi_write_register(dev,
VIDC_MMAP_ADDR,
(u32) dev->qdss.align_device_addr, 0);
vsfr = (struct hfi_sfr_struct *) dev->sfr.align_virtual_addr;
vsfr->bufSize = SFR_SIZE;
if (!IS_ERR_OR_NULL(dev->sfr.align_device_addr))
- venus_hfi_write_register(dev->hal_data->register_base_addr,
+ venus_hfi_write_register(dev,
VIDC_SFR_ADDR, (u32)dev->sfr.align_device_addr , 0);
return 0;
fail_alloc_queue:
@@ -869,14 +909,14 @@
{
u32 ctrl_status = 0, count = 0, rc = 0;
int max_tries = 100;
- venus_hfi_write_register(device->hal_data->register_base_addr,
+ venus_hfi_write_register(device,
VIDC_WRAPPER_INTR_MASK, 0x8, 0);
- venus_hfi_write_register(device->hal_data->register_base_addr,
+ venus_hfi_write_register(device,
VIDC_CPU_CS_SCIACMDARG3, 1, 0);
while (!ctrl_status && count < max_tries) {
ctrl_status = venus_hfi_read_register(
- device->hal_data->register_base_addr,
+ device,
VIDC_CPU_CS_SCIACMDARG0);
if ((ctrl_status & 0xFE) == 0x4) {
dprintk(VIDC_ERR, "invalid setting for UC_REGION\n");
@@ -903,7 +943,7 @@
reg_set = &device->res->reg_set;
for (i = 0; i < reg_set->count; i++) {
- venus_hfi_write_register(device->hal_data->register_base_addr,
+ venus_hfi_write_register(device,
reg_set->reg_tbl[i].reg,
reg_set->reg_tbl[i].value, 0);
}
@@ -981,7 +1021,7 @@
goto err_core_init;
}
enable_irq(dev->hal_data->irq);
- venus_hfi_write_register(dev->hal_data->register_base_addr,
+ venus_hfi_write_register(dev,
VIDC_CTRL_INIT, 0x1, 0);
rc = venus_hfi_core_start_cpu(dev);
if (rc) {
@@ -990,7 +1030,7 @@
goto err_core_init;
}
- rc = create_pkt_cmd_sys_init(&pkt, HFI_ARCH_OX_OFFSET);
+ rc = create_pkt_cmd_sys_init(&pkt, HFI_VIDEO_ARCH_OX);
if (rc) {
dprintk(VIDC_ERR, "Failed to create sys init pkt");
goto err_core_init;
@@ -1008,6 +1048,7 @@
static int venus_hfi_core_release(void *device)
{
struct venus_hfi_device *dev;
+ int rc = 0;
if (device) {
dev = device;
} else {
@@ -1015,13 +1056,22 @@
return -ENODEV;
}
if (dev->hal_client) {
- venus_hfi_write_register(dev->hal_data->register_base_addr,
+ mutex_lock(&dev->clock_lock);
+ rc = venus_hfi_clk_gating_off(device);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s : Clock enable failed\n", __func__);
+ mutex_unlock(&dev->clock_lock);
+ return -EIO;
+ }
+ venus_hfi_write_register(dev,
VIDC_CPU_CS_SCIACMDARG3, 0, 0);
if (!(dev->intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK))
disable_irq_nosync(dev->hal_data->irq);
dev->intr_status = 0;
venus_hfi_interface_queues_release(dev);
}
+ mutex_unlock(&dev->clock_lock);
dprintk(VIDC_INFO, "HAL exited\n");
return 0;
}
@@ -1055,16 +1105,26 @@
static void venus_hfi_core_clear_interrupt(struct venus_hfi_device *device)
{
u32 intr_status = 0;
+ int rc = 0;
if (!device->callback)
return;
-
+ mutex_lock(&device->clock_lock);
+ rc = venus_hfi_clk_gating_off(device);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "%s : Clock enable failed\n", __func__);
+ mutex_unlock(&device->clock_lock);
+ return;
+ }
intr_status = venus_hfi_read_register(
- device->hal_data->register_base_addr,
+ device,
VIDC_WRAPPER_INTR_STATUS);
if ((intr_status & VIDC_WRAPPER_INTR_STATUS_A2H_BMSK) ||
- (intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK)) {
+ (intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK) ||
+ (intr_status &
+ VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK)) {
device->intr_status |= intr_status;
dprintk(VIDC_DBG, "INTERRUPT for device: 0x%x: "
"times: %d interrupt_status: %d",
@@ -1074,10 +1134,11 @@
"times: %d interrupt_status: %d",
(u32) device, ++device->spur_count, intr_status);
}
- venus_hfi_write_register(device->hal_data->register_base_addr,
+ venus_hfi_write_register(device,
VIDC_CPU_CS_A2HSOFTINTCLR, 1, 0);
- venus_hfi_write_register(device->hal_data->register_base_addr,
+ venus_hfi_write_register(device,
VIDC_WRAPPER_INTR_CLEAR, intr_status, 0);
+ mutex_unlock(&device->clock_lock);
dprintk(VIDC_DBG, "Cleared WRAPPER/A2H interrupt");
}
@@ -1798,14 +1859,16 @@
return -ENODEV;
}
mutex_lock(&device->write_lock);
+ mutex_lock(&device->clock_lock);
rc = venus_hfi_is_cmd_pending(device);
ctrl_status = venus_hfi_read_register(
- device->hal_data->register_base_addr,
+ device,
VIDC_CPU_CS_SCIACMDARG0);
if (((ctrl_status & VIDC_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK)
!= 0) && !rc)
- venus_hfi_clk_gating_on(device, VCODEC_CLK);
+ venus_hfi_clk_gating_on(device);
mutex_unlock(&device->write_lock);
+ mutex_unlock(&device->clock_lock);
return rc;
}
@@ -1826,15 +1889,14 @@
rc = hfi_process_msg_packet(device->callback,
device->device_id,
(struct vidc_hal_msg_pkt_hdr *) packet);
- if (rc == HFI_MSG_SYS_IDLE)
- rc = venus_hfi_try_clk_gating(device);
-
}
while (!venus_hfi_iface_dbgq_read(device, packet)) {
struct hfi_msg_sys_debug_packet *pkt =
(struct hfi_msg_sys_debug_packet *) packet;
dprintk(VIDC_FW, "FW-SAYS: %s", pkt->rg_msg_data);
}
+ if (rc == HFI_MSG_SYS_IDLE)
+ rc = venus_hfi_try_clk_gating(device);
} else {
dprintk(VIDC_ERR, "SPURIOUS_INTERRUPT");
}
@@ -2015,12 +2077,23 @@
dprintk(VIDC_ERR, "Invalid params: %p\n", device);
return;
}
-
+ if (device->clocks_enabled) {
+ for (i = VCODEC_CLK; i < VCODEC_MAX_CLKS; i++) {
+ cl = &device->resources.clock[i];
+ clk_disable(cl->clk);
+ }
+ } else {
+ for (i = device->clk_gating_level + 1;
+ i < VCODEC_MAX_CLKS; i++) {
+ cl = &device->resources.clock[i];
+ clk_disable(cl->clk);
+ }
+ }
for (i = VCODEC_CLK; i < VCODEC_MAX_CLKS; i++) {
if (i == VCODEC_OCMEM_CLK && !device->res->has_ocmem)
continue;
cl = &device->resources.clock[i];
- clk_disable_unprepare(cl->clk);
+ clk_unprepare(cl->clk);
}
device->clocks_enabled = 0;
}
@@ -2311,6 +2384,7 @@
struct vidc_resource_hdr rhdr;
struct venus_hfi_device *device = dev;
int rc = 0;
+
if (!device) {
dprintk(VIDC_ERR, "%s Invalid params, device:%p\n",
__func__, device);
@@ -2323,7 +2397,6 @@
rc = -EINVAL;
goto ocmem_unset_failed;
}
-
rhdr.resource_id = VIDC_RESOURCE_OCMEM;
rhdr.resource_handle = (u32) &device->resources.ocmem;
rc = venus_hfi_core_release_resource(device, &rhdr);
@@ -2625,7 +2698,8 @@
__func__, device);
return -EINVAL;
}
-
+ mutex_init(&device->clock_lock);
+ device->clk_gating_level = VCODEC_CLK;
rc = venus_hfi_iommu_attach(device);
if (rc) {
dprintk(VIDC_ERR, "Failed to attach iommu");
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h
index 7a96ff4..197c754 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.h
+++ b/drivers/media/platform/msm/vidc/venus_hfi.h
@@ -176,8 +176,10 @@
u32 device_id;
u32 load;
u32 clocks_enabled;
+ enum vidc_clocks clk_gating_level;
struct mutex read_lock;
struct mutex write_lock;
+ struct mutex clock_lock;
msm_vidc_callback callback;
struct vidc_mem_addr iface_q_table;
struct vidc_mem_addr qdss;
diff --git a/drivers/media/platform/msm/wfd/enc-venus-subdev.c b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
index 9ebf763..b719b3f 100644
--- a/drivers/media/platform/msm/wfd/enc-venus-subdev.c
+++ b/drivers/media/platform/msm/wfd/enc-venus-subdev.c
@@ -767,6 +767,7 @@
if (inst->secure)
msm_ion_unsecure_buffer(venc_ion_client, mregion->ion_handle);
+ ion_free(venc_ion_client, mregion->ion_handle);
return rc;
}
@@ -1286,9 +1287,11 @@
return rc;
}
- if (mregion->paddr)
+ if (mregion->paddr) {
ion_unmap_iommu(mmap->ion_client, mregion->ion_handle,
domain, partition);
+ mregion->paddr = NULL;
+ }
if (inst->secure)
msm_ion_unsecure_buffer(mmap->ion_client, mregion->ion_handle);
diff --git a/drivers/media/platform/msm/wfd/mdp-5-subdev.c b/drivers/media/platform/msm/wfd/mdp-5-subdev.c
index 4089a99..16de0d4 100644
--- a/drivers/media/platform/msm/wfd/mdp-5-subdev.c
+++ b/drivers/media/platform/msm/wfd/mdp-5-subdev.c
@@ -127,9 +127,9 @@
if (inst->secure)
msm_fb_writeback_set_secure(inst->mdp, false);
msm_fb_writeback_terminate(fbi);
- kfree(inst);
/* Unregister wfd node from switch driver */
switch_dev_unregister(&inst->sdev);
+ kfree(inst);
}
return 0;
}
diff --git a/drivers/media/platform/msm/wfd/wfd-ioctl.c b/drivers/media/platform/msm/wfd/wfd-ioctl.c
index 72b02bb..e589878 100644
--- a/drivers/media/platform/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/platform/msm/wfd/wfd-ioctl.c
@@ -166,11 +166,15 @@
unsigned int alloc_regions = 0, ion_flags = 0, align = 0;
int rc = 0;
- alloc_regions = ION_HEAP(ION_CP_MM_HEAP_ID);
- alloc_regions |= secure ? 0 :
- ION_HEAP(ION_IOMMU_HEAP_ID);
- ion_flags |= secure ? ION_SECURE : 0;
- align = secure ? SZ_1M : SZ_4K;
+ if (secure) {
+ alloc_regions = ION_HEAP(ION_CP_MM_HEAP_ID);
+ ion_flags = ION_SECURE;
+ align = SZ_1M;
+ } else {
+ alloc_regions = ION_HEAP(ION_IOMMU_HEAP_ID);
+ align = SZ_4K;
+ }
+
handle = ion_alloc(client, mregion->size, align,
alloc_regions, ion_flags);
@@ -1036,7 +1040,7 @@
{
int rc = 0;
struct wfd_device *wfd_dev = video_drvdata(filp);
- struct wfd_inst *inst = filp->private_data;
+ struct wfd_inst *inst = file_to_inst(filp);
switch (a->id) {
case V4L2_CID_MPEG_VIDC_VIDEO_SECURE:
@@ -1546,10 +1550,10 @@
WFD_MSG_ERR("Failed to CLOSE vsg subdev: %d\n", rc);
wfd_stats_deinit(&inst->stats);
+ v4l2_fh_del(&inst->event_handler);
kfree(inst);
}
- v4l2_fh_del(&inst->event_handler);
mutex_lock(&wfd_dev->dev_lock);
wfd_dev->in_use = false;
diff --git a/drivers/mfd/pm8xxx-misc.c b/drivers/mfd/pm8xxx-misc.c
index fce1547..09d942a 100644
--- a/drivers/mfd/pm8xxx-misc.c
+++ b/drivers/mfd/pm8xxx-misc.c
@@ -1,5 +1,5 @@
/*
- * 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
@@ -182,6 +182,41 @@
return rc;
}
+/**
+ * pm8xxx_read_register - Read a PMIC register
+ * @addr: PMIC register address
+ * @value: Output parameter which gets the value of the register read.
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_read_register(u16 addr, u8 *value)
+{
+ struct pm8xxx_misc_chip *chip;
+ unsigned long flags;
+ int rc = 0;
+
+ spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+ /* Loop over all attached PMICs and call specific functions for them. */
+ list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+ switch (chip->version) {
+ case PM8XXX_VERSION_8921:
+ rc = pm8xxx_readb(chip->dev->parent, addr, value);
+ if (rc) {
+ pr_err("pm8xxx_readb(0x%03X) failed, rc=%d\n",
+ addr, rc);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(pm8xxx_read_register);
+
/*
* Set an SMPS regulator to be disabled in its CTRL register, but enabled
* in the master enable register. Also set it's pull down enable bit.
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index ff8234e..7c73d6c 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -1153,6 +1153,7 @@
char **codec_supplies;
u32 num_of_supplies = 0;
u32 mclk_rate = 0;
+ u32 dmic_sample_rate = 0;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
@@ -1212,6 +1213,38 @@
goto err;
}
pdata->mclk_rate = mclk_rate;
+
+ ret = of_property_read_u32(dev->of_node,
+ "qcom,cdc-dmic-sample-rate",
+ &dmic_sample_rate);
+ if (ret) {
+ 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;
+ }
+ 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)) {
+ 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)) {
+ dev_err(dev, "Invalid dmic rate %d for mclk %d\n",
+ dmic_sample_rate, pdata->mclk_rate);
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+ pdata->dmic_sample_rate = dmic_sample_rate;
return pdata;
err:
devm_kfree(dev, pdata);
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 7d76b43..73e2e0f 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -52,6 +52,7 @@
#define QSEEE_VERSION_00 0x400000
#define QSEE_VERSION_01 0x401000
#define QSEE_VERSION_02 0x402000
+#define QSEE_VERSION_03 0x403000
#define QSEOS_CHECK_VERSION_CMD 0x00001803
@@ -59,12 +60,20 @@
#define QSEE_CE_CLK_100MHZ 100000000
#define QSEECOM_MAX_SG_ENTRY 512
+#define QSEECOM_DISK_ENCRYTPION_KEY_ID 0
enum qseecom_clk_definitions {
CLK_DFAB = 0,
CLK_SFPB,
};
+enum qseecom_client_handle_type {
+ QSEECOM_CLIENT_APP = 0,
+ QSEECOM_LISTENER_SERVICE,
+ QSEECOM_SECURE_SERVICE,
+ QSEECOM_GENERIC,
+};
+
static struct class *driver_class;
static dev_t qseecom_device_no;
static struct cdev qseecom_cdev;
@@ -101,6 +110,12 @@
struct qseecom_handle *handle;
};
+struct ce_hw_usage_info {
+ uint32_t qsee_ce_hw_instance;
+ uint32_t hlos_ce_hw_instance;
+ uint32_t disk_encrypt_pipe;
+};
+
struct qseecom_clk {
struct clk *ce_core_clk;
struct clk *ce_clk;
@@ -126,6 +141,7 @@
uint32_t qsee_version;
struct device *pdev;
bool commonlib_loaded;
+ struct ce_hw_usage_info ce_info;
int qsee_bw_count;
int qsee_sfpb_bw_count;
@@ -152,7 +168,7 @@
static struct qseecom_control qseecom;
struct qseecom_dev_handle {
- bool service;
+ enum qseecom_client_handle_type type;
union {
struct qseecom_client_handle client;
struct qseecom_listener_handle listener;
@@ -163,6 +179,20 @@
atomic_t ioctl_count;
};
+enum qseecom_set_clear_key_flag {
+ QSEECOM_CLEAR_CE_KEY_CMD = 0,
+ QSEECOM_SET_CE_KEY_CMD,
+};
+
+struct qseecom_set_key_parameter {
+ uint32_t ce_hw;
+ uint32_t pipe;
+ uint32_t flags;
+ uint8_t key_id[QSEECOM_KEY_ID_SIZE];
+ unsigned char hash32[QSEECOM_HASH_SIZE];
+ enum qseecom_set_clear_key_flag set_clear_key_flag;
+};
+
struct qseecom_sg_entry {
uint32_t phys_addr;
uint32_t len;
@@ -307,7 +337,7 @@
return ret;
}
data->listener.id = 0;
- data->service = true;
+ 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;
@@ -495,7 +525,6 @@
struct qseecom_client_listener_data_irsp send_data_rsp;
struct qseecom_registered_listener_list *ptr_svc = NULL;
-
while (resp->result == QSEOS_RESULT_INCOMPLETE) {
lstnr = resp->data;
/*
@@ -544,13 +573,14 @@
sizeof(*resp));
if (ret) {
pr_err("scm_call() failed with err: %d (app_id = %d)\n",
- ret, data->client.app_id);
+ ret, data->client.app_id);
return ret;
}
- if (resp->result == QSEOS_RESULT_FAILURE) {
- pr_err("Response result %d FAIL (app_id = %d)\n",
- resp->result, data->client.app_id);
- return -EINVAL;
+ if ((resp->result != QSEOS_RESULT_SUCCESS) &&
+ (resp->result != QSEOS_RESULT_INCOMPLETE)) {
+ pr_err("fail:resp res= %d,app_id = %d,lstr = %d\n",
+ resp->result, data->client.app_id, lstnr);
+ ret = -EINVAL;
}
}
if (rc)
@@ -754,6 +784,17 @@
return 1;
}
+static int qseecom_unmap_ion_allocated_memory(struct qseecom_dev_handle *data)
+{
+ int ret = 0;
+ if (!IS_ERR_OR_NULL(data->client.ihandle)) {
+ ion_unmap_kernel(qseecom.ion_clnt, data->client.ihandle);
+ ion_free(qseecom.ion_clnt, data->client.ihandle);
+ data->client.ihandle = NULL;
+ }
+ return ret;
+}
+
static int qseecom_unload_app(struct qseecom_dev_handle *data)
{
unsigned long flags;
@@ -836,11 +877,7 @@
}
}
}
- if (!IS_ERR_OR_NULL(data->client.ihandle)) {
- ion_unmap_kernel(qseecom.ion_clnt, data->client.ihandle);
- ion_free(qseecom.ion_clnt, data->client.ihandle);
- data->client.ihandle = NULL;
- }
+ qseecom_unmap_ion_allocated_memory(data);
data->released = true;
return ret;
}
@@ -943,6 +980,96 @@
return ret;
}
+int __qseecom_process_rpmb_svc_cmd(struct qseecom_dev_handle *data_ptr,
+ struct qseecom_send_svc_cmd_req *req_ptr,
+ struct qseecom_client_send_service_ireq *send_svc_ireq_ptr)
+{
+ int ret = 0;
+ if ((req_ptr == NULL) || (send_svc_ireq_ptr == NULL)) {
+ pr_err("Error with pointer: req_ptr = %p, send_svc_ptr = %p\n",
+ req_ptr, send_svc_ireq_ptr);
+ return -EINVAL;
+ }
+ send_svc_ireq_ptr->qsee_cmd_id = req_ptr->cmd_id;
+ send_svc_ireq_ptr->key_type =
+ ((struct qseecom_rpmb_provision_key *)req_ptr->cmd_req_buf)->key_type;
+ send_svc_ireq_ptr->req_len = req_ptr->cmd_req_len;
+ send_svc_ireq_ptr->rsp_ptr = (void *)(__qseecom_uvirt_to_kphys(data_ptr,
+ (uint32_t)req_ptr->resp_buf));
+ send_svc_ireq_ptr->rsp_len = req_ptr->resp_len;
+
+ pr_debug("CMD ID (%x), KEY_TYPE (%d)\n", send_svc_ireq_ptr->qsee_cmd_id,
+ ((struct qseecom_rpmb_provision_key *)req_ptr->cmd_req_buf)->key_type);
+ return ret;
+}
+
+static int qseecom_send_service_cmd(struct qseecom_dev_handle *data,
+ void __user *argp)
+{
+ int ret = 0;
+ struct qseecom_client_send_service_ireq send_svc_ireq;
+ struct qseecom_command_scm_resp resp;
+ struct qseecom_send_svc_cmd_req req;
+ /*struct qseecom_command_scm_resp resp;*/
+
+ if (__copy_from_user(&req,
+ (void __user *)argp,
+ sizeof(req))) {
+ pr_err("copy_from_user failed\n");
+ return -EFAULT;
+ }
+
+ if (req.resp_buf == NULL) {
+ pr_err("cmd buffer or response buffer is null\n");
+ return -EINVAL;
+ }
+
+ data->type = QSEECOM_SECURE_SERVICE;
+
+ switch (req.cmd_id) {
+ case QSEE_RPMB_PROVISION_KEY_COMMAND:
+ case QSEE_RPMB_ERASE_COMMAND:
+ if (__qseecom_process_rpmb_svc_cmd(data, &req,
+ &send_svc_ireq))
+ return -EINVAL;
+ break;
+ default:
+ pr_err("Unsupported cmd_id %d\n", req.cmd_id);
+ return -EINVAL;
+ }
+
+ ret = scm_call(SCM_SVC_TZSCHEDULER, 1, (const void *) &send_svc_ireq,
+ sizeof(send_svc_ireq),
+ &resp, sizeof(resp));
+ if (ret) {
+ pr_err("qseecom_scm_call failed with err: %d\n", ret);
+ return ret;
+ }
+
+ switch (resp.result) {
+ case QSEOS_RESULT_SUCCESS:
+ break;
+ case QSEOS_RESULT_INCOMPLETE:
+ pr_err("qseos_result_incomplete\n");
+ ret = __qseecom_process_incomplete_cmd(data, &resp);
+ if (ret) {
+ pr_err("process_incomplete_cmd fail: err: %d\n",
+ ret);
+ }
+ break;
+ case QSEOS_RESULT_FAILURE:
+ pr_err("process_incomplete_cmd failed err: %d\n", ret);
+ break;
+ default:
+ pr_err("Response result %d not supported\n",
+ resp.result);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+
+}
+
static int __qseecom_send_cmd(struct qseecom_dev_handle *data,
struct qseecom_send_cmd_req *req)
{
@@ -1504,7 +1631,7 @@
return -ENOMEM;
}
data->abort = 0;
- data->service = false;
+ data->type = QSEECOM_CLIENT_APP;
data->released = false;
data->client.app_id = ret;
data->client.sb_length = size;
@@ -1769,7 +1896,7 @@
int rc = 0;
struct qseecom_clk *qclk;
- qclk = &qseecom.qsee;
+ qclk = &qseecom.qsee;
/* Enable CE core clk */
rc = clk_prepare_enable(qclk->ce_core_clk);
if (rc) {
@@ -2176,6 +2303,273 @@
}
}
+static int __qseecom_get_ce_pipe_info(
+ enum qseecom_key_management_usage_type usage,
+ uint32_t *pipe, uint32_t *ce_hw)
+{
+ int ret;
+ switch (usage) {
+ case QSEOS_KM_USAGE_DISK_ENCRYPTION:
+ if (qseecom.ce_info.disk_encrypt_pipe == 0xFF ||
+ qseecom.ce_info.hlos_ce_hw_instance == 0xFF) {
+ pr_err("nfo unavailable: disk encr pipe %d ce_hw %d\n",
+ qseecom.ce_info.disk_encrypt_pipe,
+ qseecom.ce_info.hlos_ce_hw_instance);
+ ret = -EINVAL;
+ } else {
+ *pipe = qseecom.ce_info.disk_encrypt_pipe;
+ *ce_hw = qseecom.ce_info.hlos_ce_hw_instance;
+ ret = 0;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int __qseecom_generate_and_save_key(struct qseecom_dev_handle *data,
+ enum qseecom_key_management_usage_type usage,
+ uint8_t *key_id, uint32_t flags)
+{
+ struct qseecom_key_generate_ireq ireq;
+ struct qseecom_command_scm_resp resp;
+ int ret;
+
+ if (usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+ pr_err("Error:: unsupported usage %d\n", usage);
+ return -EFAULT;
+ }
+
+ memcpy(ireq.key_id, key_id, QSEECOM_KEY_ID_SIZE);
+ ireq.flags = flags;
+
+ ret = scm_call(SCM_SVC_CRYPTO, QSEOS_GENERATE_KEY,
+ &ireq, sizeof(struct qseecom_key_generate_ireq),
+ &resp, sizeof(resp));
+ if (ret) {
+ pr_err("scm call to generate key failed : %d\n", ret);
+ return ret;
+ }
+
+ switch (resp.result) {
+ case QSEOS_RESULT_SUCCESS:
+ break;
+ case QSEOS_RESULT_INCOMPLETE:
+ ret = __qseecom_process_incomplete_cmd(data, &resp);
+ if (ret)
+ pr_err("process_incomplete_cmd FAILED\n");
+ break;
+ case QSEOS_RESULT_FAILURE:
+ default:
+ pr_err("gen key scm call failed resp.result %d\n", resp.result);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int __qseecom_delete_saved_key(struct qseecom_dev_handle *data,
+ enum qseecom_key_management_usage_type usage,
+ uint8_t *key_id, uint32_t flags)
+{
+ struct qseecom_key_delete_ireq ireq;
+ struct qseecom_command_scm_resp resp;
+ int ret;
+
+ if (usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+ pr_err("Error:: unsupported usage %d\n", usage);
+ return -EFAULT;
+ }
+
+ memcpy(ireq.key_id, key_id, QSEECOM_KEY_ID_SIZE);
+ ireq.flags = flags;
+
+ ret = scm_call(SCM_SVC_CRYPTO, QSEOS_DELETE_KEY,
+ &ireq, sizeof(struct qseecom_key_delete_ireq),
+ &resp, sizeof(struct qseecom_command_scm_resp));
+ if (ret) {
+ pr_err("scm call to delete key failed : %d\n", ret);
+ return ret;
+ }
+
+ switch (resp.result) {
+ case QSEOS_RESULT_SUCCESS:
+ break;
+ case QSEOS_RESULT_INCOMPLETE:
+ ret = __qseecom_process_incomplete_cmd(data, &resp);
+ if (ret)
+ pr_err("process_incomplete_cmd FAILED\n");
+ break;
+ case QSEOS_RESULT_FAILURE:
+ default:
+ pr_err("Delete key scm call failed resp.result %d\n",
+ resp.result);
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int __qseecom_set_clear_ce_key(struct qseecom_dev_handle *data,
+ enum qseecom_key_management_usage_type usage,
+ struct qseecom_set_key_parameter *set_key_para)
+{
+ struct qseecom_key_select_ireq ireq;
+ struct qseecom_command_scm_resp resp;
+ int ret;
+
+ if (usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+ pr_err("Error:: unsupported usage %d\n", usage);
+ return -EFAULT;
+ }
+ memcpy(ireq.key_id, set_key_para->key_id, QSEECOM_KEY_ID_SIZE);
+ ireq.ce = set_key_para->ce_hw;
+ ireq.pipe = set_key_para->pipe;
+ ireq.flags = set_key_para->flags;
+
+ if (set_key_para->set_clear_key_flag ==
+ QSEECOM_SET_CE_KEY_CMD)
+ memcpy((void *)ireq.hash, (void *)set_key_para->hash32,
+ QSEECOM_HASH_SIZE);
+ else
+ memset((void *)ireq.hash, 0, QSEECOM_HASH_SIZE);
+
+ ret = scm_call(SCM_SVC_CRYPTO, QSEOS_SET_KEY,
+ &ireq, sizeof(struct qseecom_key_select_ireq),
+ &resp, sizeof(struct qseecom_command_scm_resp));
+ if (ret) {
+ pr_err("scm call to set key failed : %d\n", ret);
+ return ret;
+ }
+
+ switch (resp.result) {
+ case QSEOS_RESULT_SUCCESS:
+ break;
+ case QSEOS_RESULT_INCOMPLETE:
+ ret = __qseecom_process_incomplete_cmd(data, &resp);
+ if (ret)
+ pr_err("process_incomplete_cmd FAILED\n");
+ break;
+ case QSEOS_RESULT_FAILURE:
+ default:
+ pr_err("Set key scm call failed resp.result %d\n", resp.result);
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int qseecom_create_key(struct qseecom_dev_handle *data,
+ void __user *argp)
+{
+ uint32_t ce_hw = 0;
+ uint32_t pipe = 0;
+ uint8_t key_id[QSEECOM_KEY_ID_SIZE] = {0};
+ int ret = 0;
+ uint32_t flags = 0;
+ struct qseecom_set_key_parameter set_key_para;
+ struct qseecom_create_key_req create_key_req;
+
+ ret = copy_from_user(&create_key_req, argp, sizeof(create_key_req));
+ if (ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
+
+ if (create_key_req.usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+ pr_err("Error:: unsupported usage %d\n", create_key_req.usage);
+ return -EFAULT;
+ }
+
+ ret = __qseecom_get_ce_pipe_info(create_key_req.usage, &pipe, &ce_hw);
+ if (ret) {
+ pr_err("Failed to retrieve pipe/ce_hw info: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = __qseecom_generate_and_save_key(data, create_key_req.usage,
+ key_id, flags);
+ if (ret) {
+ pr_err("Failed to generate key on storage: %d\n", ret);
+ return -EFAULT;
+ }
+
+ set_key_para.ce_hw = ce_hw;
+ set_key_para.pipe = pipe;
+ memcpy(set_key_para.key_id, key_id, QSEECOM_KEY_ID_SIZE);
+ set_key_para.flags = flags;
+ set_key_para.set_clear_key_flag = QSEECOM_SET_CE_KEY_CMD;
+ memcpy((void *)set_key_para.hash32, (void *)create_key_req.hash32,
+ QSEECOM_HASH_SIZE);
+
+ ret = __qseecom_set_clear_ce_key(data, create_key_req.usage,
+ &set_key_para);
+ if (ret) {
+ pr_err("Failed to create key: pipe %d, ce %d: %d\n",
+ pipe, ce_hw, ret);
+ return -EFAULT;
+ }
+
+ return ret;
+}
+
+static int qseecom_wipe_key(struct qseecom_dev_handle *data,
+ void __user *argp)
+{
+ uint32_t ce_hw = 0;
+ uint32_t pipe = 0;
+ uint8_t key_id[QSEECOM_KEY_ID_SIZE] = {0};
+ int ret = 0;
+ uint32_t flags = 0;
+ int i;
+ struct qseecom_wipe_key_req wipe_key_req;
+ struct qseecom_set_key_parameter clear_key_para;
+
+ ret = copy_from_user(&wipe_key_req, argp, sizeof(wipe_key_req));
+ if (ret) {
+ pr_err("copy_from_user failed\n");
+ return ret;
+ }
+
+ if (wipe_key_req.usage != QSEOS_KM_USAGE_DISK_ENCRYPTION) {
+ pr_err("Error:: unsupported usage %d\n", wipe_key_req.usage);
+ return -EFAULT;
+ }
+
+ ret = __qseecom_get_ce_pipe_info(wipe_key_req.usage, &pipe, &ce_hw);
+ if (ret) {
+ pr_err("Failed to retrieve pipe/ce_hw info: %d\n", ret);
+ return -EINVAL;
+ }
+
+ ret = __qseecom_delete_saved_key(data, wipe_key_req.usage, key_id,
+ flags);
+ if (ret) {
+ pr_err("Failed to delete key from ssd storage: %d\n", ret);
+ return -EFAULT;
+ }
+
+ /* an invalid key_id 0xff is used to indicate clear key*/
+ for (i = 0; i < QSEECOM_KEY_ID_SIZE; i++)
+ clear_key_para.key_id[i] = 0xff;
+ clear_key_para.ce_hw = ce_hw;
+ clear_key_para.pipe = pipe;
+ clear_key_para.flags = flags;
+ clear_key_para.set_clear_key_flag = QSEECOM_CLEAR_CE_KEY_CMD;
+ ret = __qseecom_set_clear_ce_key(data, wipe_key_req.usage,
+ &clear_key_para);
+ if (ret) {
+ pr_err("Failed to wipe key: pipe %d, ce %d: %d\n",
+ pipe, ce_hw, ret);
+ return -EFAULT;
+ }
+
+ return ret;
+}
+
static long qseecom_ioctl(struct file *file, unsigned cmd,
unsigned long arg)
{
@@ -2352,6 +2746,42 @@
mutex_unlock(&app_access_lock);
break;
}
+ case QSEECOM_IOCTL_SEND_CMD_SERVICE_REQ: {
+ if (qseecom.qsee_version < QSEE_VERSION_03) {
+ pr_err("SEND_CMD_SERVICE_REQ: Invalid qsee version %u\n",
+ qseecom.qsee_version);
+ return -EINVAL;
+ }
+ mutex_lock(&app_access_lock);
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_send_service_cmd(data, argp);
+ atomic_dec(&data->ioctl_count);
+ mutex_unlock(&app_access_lock);
+ break;
+ }
+ case QSEECOM_IOCTL_CREATE_KEY_REQ: {
+ data->released = true;
+ mutex_lock(&app_access_lock);
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_create_key(data, argp);
+ if (ret)
+ pr_err("failed to create encryption key: %d\n", ret);
+
+ atomic_dec(&data->ioctl_count);
+ mutex_unlock(&app_access_lock);
+ break;
+ }
+ case QSEECOM_IOCTL_WIPE_KEY_REQ: {
+ data->released = true;
+ mutex_lock(&app_access_lock);
+ atomic_inc(&data->ioctl_count);
+ ret = qseecom_wipe_key(data, argp);
+ if (ret)
+ pr_err("failed to wipe encryption key: %d\n", ret);
+ atomic_dec(&data->ioctl_count);
+ mutex_unlock(&app_access_lock);
+ break;
+ }
default:
return -EINVAL;
}
@@ -2370,7 +2800,7 @@
}
file->private_data = data;
data->abort = 0;
- data->service = false;
+ data->type = QSEECOM_GENERIC;
data->released = false;
init_waitqueue_head(&data->abort_wq);
atomic_set(&data->ioctl_count, 0);
@@ -2401,15 +2831,27 @@
if (data->released == false) {
pr_warn("data->released == false\n");
- if (data->service)
+ switch (data->type) {
+ case QSEECOM_LISTENER_SERVICE:
ret = qseecom_unregister_listener(data);
- else
+ break;
+ case QSEECOM_CLIENT_APP:
ret = qseecom_unload_app(data);
- if (ret) {
- pr_err("Close failed\n");
- return ret;
+ break;
+ case QSEECOM_SECURE_SERVICE:
+ ret = qseecom_unmap_ion_allocated_memory(data);
+ if (ret) {
+ pr_err("Close failed\n");
+ return ret;
+ }
+ break;
+ default:
+ pr_err("Unsupported clnt_handle_type %d",
+ data->type);
+ break;
}
}
+
if (data->client.fast_load_enabled == true)
qsee_disable_clock_vote(data, CLK_SFPB);
if (data->client.perf_enabled == true)
@@ -2610,6 +3052,42 @@
/* register client for bus scaling */
if (pdev->dev.of_node) {
+ if (of_property_read_u32((&pdev->dev)->of_node,
+ "qcom,disk-encrypt-pipe-pair",
+ &qseecom.ce_info.disk_encrypt_pipe)) {
+ pr_err("Fail to get disk-encrypt pipe pair information.\n");
+ qseecom.ce_info.disk_encrypt_pipe = 0xff;
+ rc = -EINVAL;
+ goto err;
+ } else {
+ pr_warn("bam_pipe_pair=0x%x",
+ qseecom.ce_info.disk_encrypt_pipe);
+ }
+
+ if (of_property_read_u32((&pdev->dev)->of_node,
+ "qcom,qsee-ce-hw-instance",
+ &qseecom.ce_info.qsee_ce_hw_instance)) {
+ pr_err("Fail to get qsee ce hw instance information.\n");
+ qseecom.ce_info.qsee_ce_hw_instance = 0xff;
+ rc = -EINVAL;
+ goto err;
+ } else {
+ pr_warn("qsee-ce-hw-instance=0x%x",
+ qseecom.ce_info.qsee_ce_hw_instance);
+ }
+
+ if (of_property_read_u32((&pdev->dev)->of_node,
+ "qcom,hlos-ce-hw-instance",
+ &qseecom.ce_info.hlos_ce_hw_instance)) {
+ pr_err("Fail to get hlos ce hw instance information.\n");
+ qseecom.ce_info.hlos_ce_hw_instance = 0xff;
+ rc = -EINVAL;
+ goto err;
+ } else {
+ pr_warn("hlos-ce-hw-instance=0x%x",
+ qseecom.ce_info.hlos_ce_hw_instance);
+ }
+
ret = __qseecom_init_clk();
if (ret)
goto err;
diff --git a/drivers/misc/tsif.c b/drivers/misc/tsif.c
index 05f6c86..f80fbcc 100644
--- a/drivers/misc/tsif.c
+++ b/drivers/misc/tsif.c
@@ -216,8 +216,6 @@
tsif_device->tsif_clk = clk_get(&tsif_device->pdev->dev,
pdata->tsif_clk);
if (IS_ERR(tsif_device->tsif_clk)) {
- dev_err(&tsif_device->pdev->dev, "failed to get %s\n",
- pdata->tsif_clk);
rc = PTR_ERR(tsif_device->tsif_clk);
tsif_device->tsif_clk = NULL;
goto ret;
@@ -227,8 +225,6 @@
tsif_device->tsif_pclk = clk_get(&tsif_device->pdev->dev,
pdata->tsif_pclk);
if (IS_ERR(tsif_device->tsif_pclk)) {
- dev_err(&tsif_device->pdev->dev, "failed to get %s\n",
- pdata->tsif_pclk);
rc = PTR_ERR(tsif_device->tsif_pclk);
tsif_device->tsif_pclk = NULL;
goto ret;
@@ -238,8 +234,6 @@
tsif_device->tsif_ref_clk = clk_get(&tsif_device->pdev->dev,
pdata->tsif_ref_clk);
if (IS_ERR(tsif_device->tsif_ref_clk)) {
- dev_err(&tsif_device->pdev->dev, "failed to get %s\n",
- pdata->tsif_ref_clk);
rc = PTR_ERR(tsif_device->tsif_ref_clk);
tsif_device->tsif_ref_clk = NULL;
goto ret;
@@ -1431,7 +1425,8 @@
(unsigned long)tsif_device);
tasklet_init(&tsif_device->clocks_off, tsif_clocks_off,
(unsigned long)tsif_device);
- if (tsif_get_clocks(tsif_device))
+ rc = tsif_get_clocks(tsif_device);
+ if (rc)
goto err_clocks;
/* map I/O memory */
tsif_device->memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index 9598d45..dbb4f5e 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -1569,6 +1569,7 @@
{
int i;
int id;
+ int table_idx;
u32 val;
struct sps_connect *config;
@@ -1606,16 +1607,18 @@
wmb();
/* unregister all filters for this channel */
- for (i = 0; i < TSPP_NUM_PRIORITIES; i++) {
- struct tspp_pid_filter *tspp_filter =
- &pdev->filters[channel->src]->filter[i];
- id = FILTER_GET_PIPE_NUMBER0(tspp_filter);
- if (id == channel->id) {
- if (FILTER_HAS_ENCRYPTION(tspp_filter))
- tspp_free_key_entry(
- FILTER_GET_KEY_NUMBER(tspp_filter));
- tspp_filter->config = 0;
- tspp_filter->filter = 0;
+ for (table_idx = 0; table_idx < TSPP_FILTER_TABLES; table_idx++) {
+ for (i = 0; i < TSPP_NUM_PRIORITIES; i++) {
+ struct tspp_pid_filter *filter =
+ &pdev->filters[table_idx]->filter[i];
+ id = FILTER_GET_PIPE_NUMBER0(filter);
+ if (id == channel->id) {
+ if (FILTER_HAS_ENCRYPTION(filter))
+ tspp_free_key_entry(
+ FILTER_GET_KEY_NUMBER(filter));
+ filter->config = 0;
+ filter->filter = 0;
+ }
}
}
channel->filter_count = 0;
@@ -2582,28 +2585,27 @@
debugfs_create_u32(
"stat_rx_chunks",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
tsif_device->dent_tsif,
&tsif_device->stat_rx);
debugfs_create_u32(
"stat_overflow",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
tsif_device->dent_tsif,
&tsif_device->stat_overflow);
debugfs_create_u32(
"stat_lost_sync",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
tsif_device->dent_tsif,
&tsif_device->stat_lost_sync);
debugfs_create_u32(
"stat_timeout",
- S_IRUGO|S_IWUGO,
+ S_IRUGO | S_IWUSR | S_IWGRP,
tsif_device->dent_tsif,
&tsif_device->stat_timeout);
-
}
}
@@ -2837,8 +2839,6 @@
if (data->tsif_pclk) {
device->tsif_pclk = clk_get(&pdev->dev, data->tsif_pclk);
if (IS_ERR(device->tsif_pclk)) {
- pr_err("tspp: failed to get %s",
- data->tsif_pclk);
rc = PTR_ERR(device->tsif_pclk);
device->tsif_pclk = NULL;
goto err_pclock;
@@ -2847,8 +2847,6 @@
if (data->tsif_ref_clk) {
device->tsif_ref_clk = clk_get(&pdev->dev, data->tsif_ref_clk);
if (IS_ERR(device->tsif_ref_clk)) {
- pr_err("tspp: failed to get %s",
- data->tsif_ref_clk);
rc = PTR_ERR(device->tsif_ref_clk);
device->tsif_ref_clk = NULL;
goto err_refclock;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index bea8428..fc7c399 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -820,7 +820,15 @@
context_info->is_done_rcv = false;
break; /* return err */
} else {
+ /*
+ * We have stopped the ongoing request
+ * and are sure that mmc_request_done()
+ * is not going to get called. Update
+ * stuff that we ought to do when the
+ * request actually completes.
+ */
mmc_update_clk_scaling(host);
+ mmc_host_clk_release(host);
}
err = host->areq->update_interrupted_req(
host->card, host->areq);
@@ -2815,7 +2823,13 @@
u32 status;
bool ret = false;
- if (!card)
+ /*
+ * If the current partition type is RPMB, clock switching may not
+ * work properly as sending tuning command (CMD21) is illegal in
+ * this mode.
+ */
+ if (!card || (mmc_card_mmc(card) &&
+ card->part_curr == EXT_CSD_PART_CONFIG_ACC_RPMB))
goto out;
if (mmc_send_status(card, &status)) {
@@ -3586,6 +3600,20 @@
EXPORT_SYMBOL(mmc_set_embedded_sdio_data);
#endif
+#ifdef CONFIG_PM_RUNTIME
+void mmc_dump_dev_pm_state(struct mmc_host *host, struct device *dev)
+{
+ pr_err("%s: %s: err: runtime_error: %d\n", dev_name(dev),
+ mmc_hostname(host), dev->power.runtime_error);
+ pr_err("%s: %s: disable_depth: %d runtime_status: %d idle_notification: %d\n",
+ dev_name(dev), mmc_hostname(host), dev->power.disable_depth,
+ dev->power.runtime_status,
+ dev->power.idle_notification);
+ pr_err("%s: %s: request_pending: %d, request: %d\n",
+ dev_name(dev), mmc_hostname(host),
+ dev->power.request_pending, dev->power.request);
+}
+
void mmc_rpm_hold(struct mmc_host *host, struct device *dev)
{
int ret = 0;
@@ -3594,13 +3622,16 @@
return;
ret = pm_runtime_get_sync(dev);
- if (ret < 0) {
- pr_err("%s: %s: %s: error resuming device: %d\n",
+ if ((ret < 0) &&
+ (dev->power.runtime_error || (dev->power.disable_depth > 0))) {
+ pr_err("%s: %s: %s: pm_runtime_get_sync: err: %d\n",
dev_name(dev), mmc_hostname(host), __func__, ret);
+ mmc_dump_dev_pm_state(host, dev);
if (pm_runtime_suspended(dev))
BUG_ON(1);
}
}
+
EXPORT_SYMBOL(mmc_rpm_hold);
void mmc_rpm_release(struct mmc_host *host, struct device *dev)
@@ -3611,11 +3642,22 @@
return;
ret = pm_runtime_put_sync(dev);
- if (ret < 0 && ret != -EBUSY)
- pr_err("%s: %s: %s: put sync ret: %d\n",
+ if ((ret < 0) &&
+ (dev->power.runtime_error || (dev->power.disable_depth > 0))) {
+ pr_err("%s: %s: %s: pm_runtime_put_sync: err: %d\n",
dev_name(dev), mmc_hostname(host), __func__, ret);
+ mmc_dump_dev_pm_state(host, dev);
+ }
}
+
EXPORT_SYMBOL(mmc_rpm_release);
+#else
+void mmc_rpm_hold(struct mmc_host *host, struct device *dev) {}
+EXPORT_SYMBOL(mmc_rpm_hold);
+
+void mmc_rpm_release(struct mmc_host *host, struct device *dev) {}
+EXPORT_SYMBOL(mmc_rpm_release);
+#endif
/**
* mmc_init_context_info() - init synchronization context
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index dc129f7..60e0640 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1166,6 +1166,7 @@
if (!retries) {
printk(KERN_ERR "%s(%s): Unable to re-detect card (%d)\n",
__func__, mmc_hostname(host), err);
+ err = _mmc_detect_card_removed(host);
}
#else
err = _mmc_detect_card_removed(host);
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 2769709..2038d3d 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -1187,9 +1187,12 @@
static unsigned int sdhci_get_bw_required(struct sdhci_host *host,
struct mmc_ios *ios)
{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_msm_host *msm_host = pltfm_host->priv;
+
unsigned int bw;
- bw = host->clock;
+ bw = msm_host->clk_rate;
/*
* For DDR mode, SDCC controller clock will be at
* the double rate than the actual clock that goes to card.
@@ -2184,6 +2187,7 @@
host->quirks |= SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
host->quirks2 |= SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK;
host->quirks2 |= SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING;
+ host->quirks2 |= SDHCI_QUIRK2_USE_MAX_DISCARD_SIZE;
host_version = readl_relaxed((host->ioaddr + SDHCI_HOST_VERSION));
dev_dbg(&pdev->dev, "Host Version: 0x%x Vendor Version 0x%x\n",
@@ -2253,7 +2257,6 @@
MMC_CAP2_DETECT_ON_ERR);
msm_host->mmc->caps2 |= MMC_CAP2_SANITIZE;
msm_host->mmc->caps2 |= MMC_CAP2_CACHE_CTRL;
- msm_host->mmc->caps2 |= MMC_CAP2_INIT_BKOPS;
msm_host->mmc->caps2 |= MMC_CAP2_POWEROFF_NOTIFY;
msm_host->mmc->caps2 |= MMC_CAP2_CLK_SCALE;
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index c247ae9..d58379f 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -66,53 +66,67 @@
}
#endif
+static void sdhci_dump_state(struct sdhci_host *host)
+{
+ struct mmc_host *mmc = host->mmc;
+
+ pr_info("%s: clk: %d clk-gated: %d claimer: %s pwr: %d\n",
+ mmc_hostname(mmc), host->clock, mmc->clk_gated,
+ mmc->claimer->comm, host->pwr);
+ pr_info("%s: rpmstatus[pltfm](runtime-suspend:usage_count:disable_depth)(%d:%d:%d)\n",
+ mmc_hostname(mmc), mmc->parent->power.runtime_status,
+ atomic_read(&mmc->parent->power.usage_count),
+ mmc->parent->power.disable_depth);
+}
+
static void sdhci_dumpregs(struct sdhci_host *host)
{
- pr_debug(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n",
+ pr_info(DRIVER_NAME ": =========== REGISTER DUMP (%s)===========\n",
mmc_hostname(host->mmc));
- pr_debug(DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n",
+ pr_info(DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n",
sdhci_readl(host, SDHCI_DMA_ADDRESS),
sdhci_readw(host, SDHCI_HOST_VERSION));
- pr_debug(DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n",
+ pr_info(DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n",
sdhci_readw(host, SDHCI_BLOCK_SIZE),
sdhci_readw(host, SDHCI_BLOCK_COUNT));
- pr_debug(DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
+ pr_info(DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n",
sdhci_readl(host, SDHCI_ARGUMENT),
sdhci_readw(host, SDHCI_TRANSFER_MODE));
- pr_debug(DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n",
+ pr_info(DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n",
sdhci_readl(host, SDHCI_PRESENT_STATE),
sdhci_readb(host, SDHCI_HOST_CONTROL));
- pr_debug(DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n",
+ pr_info(DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n",
sdhci_readb(host, SDHCI_POWER_CONTROL),
sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL));
- pr_debug(DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n",
+ pr_info(DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n",
sdhci_readb(host, SDHCI_WAKE_UP_CONTROL),
sdhci_readw(host, SDHCI_CLOCK_CONTROL));
- pr_debug(DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n",
+ pr_info(DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n",
sdhci_readb(host, SDHCI_TIMEOUT_CONTROL),
sdhci_readl(host, SDHCI_INT_STATUS));
- pr_debug(DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
+ pr_info(DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n",
sdhci_readl(host, SDHCI_INT_ENABLE),
sdhci_readl(host, SDHCI_SIGNAL_ENABLE));
- pr_debug(DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
+ pr_info(DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n",
sdhci_readw(host, SDHCI_ACMD12_ERR),
sdhci_readw(host, SDHCI_SLOT_INT_STATUS));
- pr_debug(DRIVER_NAME ": Caps: 0x%08x | Caps_1: 0x%08x\n",
+ pr_info(DRIVER_NAME ": Caps: 0x%08x | Caps_1: 0x%08x\n",
sdhci_readl(host, SDHCI_CAPABILITIES),
sdhci_readl(host, SDHCI_CAPABILITIES_1));
- pr_debug(DRIVER_NAME ": Cmd: 0x%08x | Max curr: 0x%08x\n",
+ pr_info(DRIVER_NAME ": Cmd: 0x%08x | Max curr: 0x%08x\n",
sdhci_readw(host, SDHCI_COMMAND),
sdhci_readl(host, SDHCI_MAX_CURRENT));
- pr_debug(DRIVER_NAME ": Host ctl2: 0x%08x\n",
+ pr_info(DRIVER_NAME ": Host ctl2: 0x%08x\n",
sdhci_readw(host, SDHCI_HOST_CONTROL2));
if (host->flags & SDHCI_USE_ADMA)
- pr_debug(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
+ pr_info(DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
readl(host->ioaddr + SDHCI_ADMA_ERROR),
readl(host->ioaddr + SDHCI_ADMA_ADDRESS));
- pr_debug(DRIVER_NAME ": ===========================================\n");
+ sdhci_dump_state(host);
+ pr_info(DRIVER_NAME ": ===========================================\n");
}
/*****************************************************************************\
@@ -1372,6 +1386,17 @@
}
}
+static bool sdhci_check_state(struct sdhci_host *host)
+{
+ struct mmc_host *mmc = host->mmc;
+
+ if (!host->clock || !host->pwr ||
+ pm_runtime_suspended(mmc->parent))
+ return true;
+ else
+ return false;
+}
+
static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
struct sdhci_host *host;
@@ -1381,6 +1406,15 @@
host = mmc_priv(mmc);
sdhci_runtime_pm_get(host);
+ if (sdhci_check_state(host)) {
+ sdhci_dump_state(host);
+ WARN(1, "sdhci in bad state");
+ mrq->cmd->error = -EIO;
+ if (mrq->data)
+ mrq->data->error = -EIO;
+ tasklet_schedule(&host->finish_tasklet);
+ return;
+ }
spin_lock_irqsave(&host->lock, flags);
@@ -2217,6 +2251,11 @@
sdhci_dumpregs(host);
if (host->data) {
+ pr_info("%s: bytes to transfer: %d transferred: %d\n",
+ mmc_hostname(host->mmc),
+ (host->data->blksz * host->data->blocks),
+ (sdhci_readw(host, SDHCI_BLOCK_SIZE) & 0xFFF) *
+ sdhci_readw(host, SDHCI_BLOCK_COUNT));
host->data->error = -ETIMEDOUT;
sdhci_finish_data(host);
} else {
@@ -2354,6 +2393,7 @@
static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
{
u32 command;
+ bool pr_msg = false;
BUG_ON(intmask == 0);
/* CMD19 generates _only_ Buffer Read Ready interrupt */
@@ -2401,10 +2441,25 @@
sdhci_show_adma_error(host);
host->data->error = -EIO;
}
-
- if (host->data->error)
+ if (host->data->error) {
+ if ((intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT)) &&
+ (host->quirks2 & SDHCI_QUIRK2_IGNORE_CMDCRC_FOR_TUNING)) {
+ command = SDHCI_GET_CMD(sdhci_readw(host,
+ SDHCI_COMMAND));
+ if ((command != MMC_SEND_TUNING_BLOCK_HS200) &&
+ (command != MMC_SEND_TUNING_BLOCK))
+ pr_msg = true;
+ } else {
+ pr_msg = true;
+ }
+ if (pr_msg) {
+ pr_err("%s: data txfr (0x%08x) error: %d\n",
+ mmc_hostname(host->mmc), intmask,
+ host->data->error);
+ sdhci_dumpregs(host);
+ }
sdhci_finish_data(host);
- else {
+ } else {
if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
sdhci_transfer_pio(host);
@@ -2962,7 +3017,8 @@
if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)
host->timeout_clk = mmc->f_max / 1000;
- mmc->max_discard_to = (1 << 27) / host->timeout_clk;
+ if (!(host->quirks2 & SDHCI_QUIRK2_USE_MAX_DISCARD_SIZE))
+ mmc->max_discard_to = (1 << 27) / host->timeout_clk;
mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c
index c37a4a4..570c257 100644
--- a/drivers/mtd/devices/msm_qpic_nand.c
+++ b/drivers/mtd/devices/msm_qpic_nand.c
@@ -28,8 +28,9 @@
#include <linux/bitrev.h>
#include <linux/mutex.h>
#include <linux/of.h>
+#include <linux/ctype.h>
#include <mach/sps.h>
-
+#include <mach/msm_smsm.h>
#define PAGE_SIZE_2K 2048
#define PAGE_SIZE_4K 4096
#define WRITE 1
@@ -285,6 +286,34 @@
uint16_t integrity_crc;
} __attribute__((__packed__));
+#define FLASH_PART_MAGIC1 0x55EE73AA
+#define FLASH_PART_MAGIC2 0xE35EBDDB
+#define FLASH_PTABLE_V3 3
+#define FLASH_PTABLE_V4 4
+#define FLASH_PTABLE_MAX_PARTS_V3 16
+#define FLASH_PTABLE_MAX_PARTS_V4 32
+#define FLASH_PTABLE_HDR_LEN (4*sizeof(uint32_t))
+#define FLASH_PTABLE_ENTRY_NAME_SIZE 16
+
+struct flash_partition_entry {
+ char name[FLASH_PTABLE_ENTRY_NAME_SIZE];
+ u32 offset; /* Offset in blocks from beginning of device */
+ u32 length; /* Length of the partition in blocks */
+ u8 attr; /* Flags for this partition */
+};
+
+struct flash_partition_table {
+ u32 magic1;
+ u32 magic2;
+ u32 version;
+ u32 numparts;
+ struct flash_partition_entry part_entry[FLASH_PTABLE_MAX_PARTS_V4];
+};
+
+static struct flash_partition_table ptable;
+
+static struct mtd_partition mtd_part[FLASH_PTABLE_MAX_PARTS_V4];
+
/*
* Get the DMA memory for requested amount of size. It returns the pointer
* to free memory available from the allocated pool. Returns NULL if there
@@ -660,6 +689,14 @@
if (ret < 0)
goto free_dma;
+ /* Lookup the 'APPS' partition's first page address */
+ for (i = 0; i < FLASH_PTABLE_MAX_PARTS_V4; i++) {
+ if (!strncmp("apps", ptable.part_entry[i].name,
+ strlen(ptable.part_entry[i].name))) {
+ page_address = ptable.part_entry[i].offset << 6;
+ break;
+ }
+ }
data.cfg.cmd = MSM_NAND_CMD_PAGE_READ_ALL;
data.exec = 1;
data.cfg.addr0 = (page_address << 16) |
@@ -2338,6 +2375,75 @@
}
+#ifdef CONFIG_MSM_SMD
+static int msm_nand_parse_smem_ptable(int *nr_parts)
+{
+
+ uint32_t i, j;
+ uint32_t len = FLASH_PTABLE_HDR_LEN;
+ struct flash_partition_entry *pentry;
+ char *delimiter = ":";
+
+ pr_info("Parsing partition table info from SMEM\n");
+ /* Read only the header portion of ptable */
+ ptable = *(struct flash_partition_table *)
+ (smem_get_entry(SMEM_AARM_PARTITION_TABLE, &len));
+ /* Verify ptable magic */
+ if (ptable.magic1 != FLASH_PART_MAGIC1 ||
+ ptable.magic2 != FLASH_PART_MAGIC2) {
+ pr_err("Partition table magic verification failed\n");
+ goto out;
+ }
+ /* Ensure that # of partitions is less than the max we have allocated */
+ if (ptable.numparts > FLASH_PTABLE_MAX_PARTS_V4) {
+ pr_err("Partition numbers exceed the max limit\n");
+ goto out;
+ }
+ /* Find out length of partition data based on table version. */
+ if (ptable.version <= FLASH_PTABLE_V3) {
+ len = FLASH_PTABLE_HDR_LEN + FLASH_PTABLE_MAX_PARTS_V3 *
+ sizeof(struct flash_partition_entry);
+ } else if (ptable.version == FLASH_PTABLE_V4) {
+ len = FLASH_PTABLE_HDR_LEN + FLASH_PTABLE_MAX_PARTS_V4 *
+ sizeof(struct flash_partition_entry);
+ } else {
+ pr_err("Unknown ptable version (%d)", ptable.version);
+ goto out;
+ }
+
+ *nr_parts = ptable.numparts;
+ ptable = *(struct flash_partition_table *)
+ (smem_get_entry(SMEM_AARM_PARTITION_TABLE, &len));
+ for (i = 0; i < ptable.numparts; i++) {
+ pentry = &ptable.part_entry[i];
+ if (pentry->name == '\0')
+ continue;
+ /* Convert name to lower case and discard the initial chars */
+ mtd_part[i].name = pentry->name;
+ for (j = 0; j < strlen(mtd_part[i].name); j++)
+ *(mtd_part[i].name + j) =
+ tolower(*(mtd_part[i].name + j));
+ strsep(&(mtd_part[i].name), delimiter);
+ mtd_part[i].offset = pentry->offset;
+ mtd_part[i].mask_flags = pentry->attr;
+ mtd_part[i].size = pentry->length;
+ pr_debug("%d: %s offs=0x%08x size=0x%08x attr:0x%08x\n",
+ i, pentry->name, pentry->offset, pentry->length,
+ pentry->attr);
+ }
+ pr_info("SMEM partition table found: ver: %d len: %d\n",
+ ptable.version, ptable.numparts);
+ return 0;
+out:
+ return -EINVAL;
+}
+#else
+static int msm_nand_parse_smem_ptable(int *nr_parts)
+{
+ return -ENODEV;
+}
+#endif
+
/*
* This function gets called when its device named msm-nand is added to
* device tree .dts file with all its resources such as physical addresses
@@ -2352,26 +2458,13 @@
{
struct msm_nand_info *info;
struct resource *res;
- int err;
- struct device_node *pnode;
- struct mtd_part_parser_data parser_data;
-
- if (!pdev->dev.of_node) {
- pr_err("No valid device tree info for NANDc\n");
- err = -ENODEV;
- goto out;
- }
+ int i, err, nr_parts;
/*
* The partition information can also be passed from kernel command
* line. Also, the MTD core layer supports adding the whole device as
* one MTD device when no partition information is available at all.
- * Hence, do not bail out when partition information is not availabe
- * in device tree.
*/
- pnode = of_find_node_by_path("/qcom,mtd-partitions");
- if (!pnode)
- pr_info("No partition info available in device tree\n");
info = devm_kzalloc(&pdev->dev, sizeof(struct msm_nand_info),
GFP_KERNEL);
if (!info) {
@@ -2379,7 +2472,6 @@
err = -ENOMEM;
goto out;
}
-
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"nand_phys");
if (!res || !res->start) {
@@ -2438,14 +2530,22 @@
pr_err("Failed to enable DMA in NANDc\n");
goto free_bam;
}
+ err = msm_nand_parse_smem_ptable(&nr_parts);
+ if (err < 0) {
+ pr_err("Failed to parse partition table in SMEM\n");
+ goto free_bam;
+ }
if (msm_nand_scan(&info->mtd)) {
pr_err("No nand device found\n");
err = -ENXIO;
goto free_bam;
}
- parser_data.of_node = pnode;
- err = mtd_device_parse_register(&info->mtd, NULL, &parser_data,
- NULL, 0);
+ for (i = 0; i < nr_parts; i++) {
+ mtd_part[i].offset *= info->mtd.erasesize;
+ mtd_part[i].size *= info->mtd.erasesize;
+ }
+ err = mtd_device_parse_register(&info->mtd, NULL, NULL,
+ &mtd_part[0], nr_parts);
if (err < 0) {
pr_err("Unable to register MTD partitions %d\n", err);
goto free_bam;
diff --git a/drivers/net/ethernet/msm/msm_rmnet_smux.c b/drivers/net/ethernet/msm/msm_rmnet_smux.c
index 7b27b73..5fe724e 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_smux.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_smux.c
@@ -804,7 +804,7 @@
for (i = 0; i < RMNET_SMUX_DEVICE_COUNT; i++) {
p = netdev_priv(netdevs[i]);
- if ((p != NULL) && (p->device_state == DEVICE_INACTIVE)) {
+ if (p != NULL) {
r = msm_smux_open(p->ch_id,
netdevs[i],
rmnet_smux_notify,
@@ -828,7 +828,7 @@
for (i = 0; i < RMNET_SMUX_DEVICE_COUNT; i++) {
p = netdev_priv(netdevs[i]);
- if ((p != NULL) && (p->device_state == DEVICE_ACTIVE)) {
+ if (p != NULL) {
r = msm_smux_close(p->ch_id);
if (r < 0) {
diff --git a/drivers/platform/msm/ipa/ipa_bridge.c b/drivers/platform/msm/ipa/ipa_bridge.c
index eeb98e9..dd00081 100644
--- a/drivers/platform/msm/ipa/ipa_bridge.c
+++ b/drivers/platform/msm/ipa/ipa_bridge.c
@@ -403,7 +403,7 @@
sys->connection.dest_pipe_index = ipa_ctx->a5_pipe_index++;
sys->connection.mode = SPS_MODE_SRC;
sys->connection.options = SPS_O_AUTO_ENABLE | SPS_O_EOT |
- SPS_O_ACK_TRANSFERS;
+ SPS_O_ACK_TRANSFERS | SPS_O_NO_DISABLE;
}
sys->desc_mem_buf.size = props->desc_fifo_sz;
diff --git a/drivers/platform/msm/ipa/ipa_client.c b/drivers/platform/msm/ipa/ipa_client.c
index a4b7e22..f2f80bf 100644
--- a/drivers/platform/msm/ipa/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_client.c
@@ -33,17 +33,56 @@
static int ipa_disable_data_path(u32 clnt_hdl)
{
+ DECLARE_COMPLETION_ONSTACK(tag_rsp);
+ struct ipa_desc desc = {0};
+ struct ipa_ip_packet_tag cmd;
struct ipa_ep_context *ep = &ipa_ctx->ep[clnt_hdl];
+ struct ipa_tree_node *node;
+ int result = 0;
if (ipa_ctx->ipa_hw_mode == IPA_HW_MODE_VIRTUAL) {
/* IPA_HW_MODE_VIRTUAL lacks support for TAG IC & EP suspend */
return 0;
}
+ node = kmem_cache_zalloc(ipa_ctx->tree_node_cache, GFP_KERNEL);
+ if (!node) {
+ IPAERR("failed to alloc tree node object\n");
+ result = -ENOMEM;
+ goto fail_alloc;
+ }
+
if (ipa_ctx->ipa_hw_type == IPA_HW_v1_1 && !ep->suspended) {
ipa_write_reg(ipa_ctx->mmio,
IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 1);
+ cmd.tag = (u32) &tag_rsp;
+
+ desc.pyld = &cmd;
+ desc.len = sizeof(struct ipa_ip_packet_tag);
+ desc.type = IPA_IMM_CMD_DESC;
+ desc.opcode = IPA_IP_PACKET_TAG;
+
+ IPADBG("Wait on TAG %p clnt=%d\n", &tag_rsp, clnt_hdl);
+
+ node->hdl = cmd.tag;
+ mutex_lock(&ipa_ctx->lock);
+ if (ipa_insert(&ipa_ctx->tag_tree, node)) {
+ IPAERR("failed to add to tree\n");
+ result = -EINVAL;
+ mutex_unlock(&ipa_ctx->lock);
+ goto fail_insert;
+ }
+ mutex_unlock(&ipa_ctx->lock);
+
+ if (ipa_send_cmd(1, &desc)) {
+ ipa_write_reg(ipa_ctx->mmio,
+ IPA_ENDP_INIT_CTRL_n_OFST(clnt_hdl), 0);
+ IPAERR("fail to send TAG command\n");
+ result = -EPERM;
+ goto fail_send;
+ }
+ wait_for_completion(&tag_rsp);
if (IPA_CLIENT_IS_CONS(ep->client) &&
ep->cfg.aggr.aggr_en == IPA_ENABLE_AGGR &&
ep->cfg.aggr.aggr_time_limit)
@@ -52,6 +91,13 @@
}
return 0;
+
+fail_send:
+ rb_erase(&node->node, &ipa_ctx->tag_tree);
+fail_insert:
+ kmem_cache_free(ipa_ctx->tree_node_cache, node);
+fail_alloc:
+ return result;
}
static int ipa_connect_configure_sps(const struct ipa_connect_params *in,
@@ -238,6 +284,9 @@
ep->connect.event_thresh = IPA_EVENT_THRESHOLD;
ep->connect.options = SPS_O_AUTO_ENABLE; /* BAM-to-BAM */
+ if (IPA_CLIENT_IS_CONS(in->client))
+ ep->connect.options |= SPS_O_NO_DISABLE;
+
result = sps_connect(ep->ep_hdl, &ep->connect);
if (result) {
IPAERR("sps_connect fails.\n");
diff --git a/drivers/platform/msm/ipa/ipa_dp.c b/drivers/platform/msm/ipa/ipa_dp.c
index bd1da2c..5f7f3d9 100644
--- a/drivers/platform/msm/ipa/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_dp.c
@@ -259,7 +259,7 @@
if (unlikely(!in_atomic))
mem_flag = GFP_KERNEL;
- transfer.iovec = dma_alloc_coherent(NULL, size, &dma_addr, 0);
+ transfer.iovec = dma_alloc_coherent(NULL, size, &dma_addr, mem_flag);
transfer.iovec_phys = dma_addr;
transfer.iovec_count = num_desc;
spin_lock_irqsave(&sys->spinlock, irq_flags);
@@ -528,6 +528,8 @@
struct ipa_sys_context *sys = &ipa_ctx->sys[IPA_A5_LAN_WAN_IN];
struct ipa_ep_context *ep;
int cnt = 0;
+ struct completion *compl;
+ struct ipa_tree_node *node;
unsigned int src_pipe;
while ((in_poll_state ? atomic_read(&ipa_ctx->curr_polling_state) :
@@ -582,6 +584,35 @@
IPA_STATS_INC_CNT(ipa_ctx->stats.rx_pkts);
IPA_STATS_EXCP_CNT(mux_hdr->flags, ipa_ctx->stats.rx_excp_pkts);
+ if (unlikely(mux_hdr->flags & IPA_A5_MUX_HDR_EXCP_FLAG_TAG)) {
+ if (ipa_ctx->ipa_hw_mode != IPA_HW_MODE_VIRTUAL) {
+ /* retrieve the compl object from tag value */
+ mux_hdr++;
+ compl = (struct completion *)
+ ntohl(*((u32 *)mux_hdr));
+ IPADBG("%x %x %p\n", *(u32 *)mux_hdr,
+ *((u32 *)mux_hdr + 1), compl);
+
+ mutex_lock(&ipa_ctx->lock);
+ node = ipa_search(&ipa_ctx->tag_tree,
+ (u32)compl);
+ if (node) {
+ complete_all(compl);
+ rb_erase(&node->node,
+ &ipa_ctx->tag_tree);
+ kmem_cache_free(
+ ipa_ctx->tree_node_cache, node);
+ } else {
+ WARN_ON(1);
+ }
+ mutex_unlock(&ipa_ctx->lock);
+ }
+ dev_kfree_skb(rx_skb);
+ ipa_replenish_rx_cache();
+ ++cnt;
+ continue;
+ }
+
/*
* Any packets arriving over AMPDU_TX should be dispatched
* to the regular WLAN RX data-path.
@@ -791,7 +822,8 @@
ipa_ctx->a5_pipe_index++;
ipa_ctx->ep[ipa_ep_idx].connect.src_pipe_index = ipa_ep_idx;
ipa_ctx->ep[ipa_ep_idx].connect.options =
- SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS;
+ SPS_O_AUTO_ENABLE | SPS_O_EOT | SPS_O_ACK_TRANSFERS |
+ SPS_O_NO_DISABLE;
if (ipa_ctx->polling_mode)
ipa_ctx->ep[ipa_ep_idx].connect.options |= SPS_O_POLL;
} else {
@@ -943,7 +975,6 @@
static void ipa_tx_cmd_comp(void *user1, void *user2)
{
- IPA_STATS_INC_CNT(ipa_ctx->stats.imm_cmds[IPA_IP_PACKET_INIT]);
kfree(user1);
}
@@ -1022,6 +1053,7 @@
IPAERR("fail to send immediate command\n");
goto fail_send;
}
+ IPA_STATS_INC_CNT(ipa_ctx->stats.imm_cmds[IPA_IP_PACKET_INIT]);
} else if (dst == IPA_CLIENT_A5_WLAN_AMPDU_PROD) {
desc[0].pyld = skb->data;
desc[0].len = skb->len;
diff --git a/drivers/platform/msm/sps/bam.c b/drivers/platform/msm/sps/bam.c
index 0f81285..47108c6 100644
--- a/drivers/platform/msm/sps/bam.c
+++ b/drivers/platform/msm/sps/bam.c
@@ -17,6 +17,7 @@
#include <linux/io.h> /* ioread32() */
#include <linux/bitops.h> /* find_first_bit() */
#include <linux/errno.h> /* ENODEV */
+#include <linux/memory.h>
#include "bam.h"
#include "sps_bam.h"
@@ -849,7 +850,7 @@
print_bam_test_bus_reg(base, 0);
- print_bam_reg(base);
+ print_bam_selected_reg(base, BAM_MAX_EES);
num_pipes = bam_read_reg_field(base, NUM_PIPES,
BAM_NUM_PIPES);
@@ -857,8 +858,7 @@
(u32) base, num_pipes);
for (i = 0; i < num_pipes; i++)
- print_bam_pipe_reg(base, i);
-
+ print_bam_pipe_selected_reg(base, i);
}
/**
@@ -1174,7 +1174,7 @@
pipes = bam[0xfbc / 4];
#endif
- SPS_INFO("\nsps:----- Content of BAM-level registers <begin> -----\n");
+ SPS_INFO("\nsps:<bam-begin> --- Content of BAM-level registers---\n");
SPS_INFO("BAM_CTRL: 0x%x.\n", ctrl);
SPS_INFO("BAM_REVISION: 0x%x.\n", ver);
@@ -1198,7 +1198,7 @@
bam[i / 4], bam[(i / 4) + 1],
bam[(i / 4) + 2], bam[(i / 4) + 3]);
- SPS_INFO("\nsps:----- Content of BAM-level registers <end> -----\n");
+ SPS_INFO("\nsps:<bam-begin> --- Content of BAM-level registers ---\n");
}
/* output the content of BAM pipe registers */
@@ -1211,7 +1211,7 @@
if (bam == NULL)
return;
- SPS_INFO("\nsps:----- Content of Pipe %d registers <begin> -----\n",
+ SPS_INFO("\nsps:<pipe-begin> --- Content of Pipe %d registers ---\n",
pipe);
SPS_INFO("-- Pipe Management Registers --\n");
@@ -1240,47 +1240,110 @@
bam[i / 4], bam[(i / 4) + 1],
bam[(i / 4) + 2], bam[(i / 4) + 3]);
- SPS_INFO("\nsps:----- Content of Pipe %d registers <end> -----\n",
+ SPS_INFO("\nsps:<pipe-end> --- Content of Pipe %d registers ---\n",
pipe);
}
/* output the content of selected BAM-level registers */
-void print_bam_selected_reg(void *virt_addr)
+void print_bam_selected_reg(void *virt_addr, u32 ee)
{
void *base = virt_addr;
+ u32 bam_ctrl;
+ u32 bam_revision;
+ u32 bam_rev_num;
+ u32 bam_rev_ee_num;
+
+ u32 bam_num_pipes;
+ u32 bam_pipe_num;
+
+ u32 bam_desc_cnt_trshld;
+ u32 bam_desc_cnt_trd_val;
+
+ u32 bam_irq_en;
+ u32 bam_irq_stts;
+
+ u32 bam_irq_src_ee = 0;
+ u32 bam_irq_msk_ee = 0;
+ u32 bam_irq_unmsk_ee = 0;
+
+ u32 bam_ahb_err_ctrl;
+ u32 bam_ahb_err_addr;
+ u32 bam_ahb_err_data;
+ u32 bam_cnfg_bits;
+
+ u32 bam_sw_rev = 0;
+ u32 bam_timer = 0;
+ u32 bam_timer_ctrl = 0;
+
if (base == NULL)
return;
- SPS_INFO("\nsps:----- Content of BAM-level registers <begin> -----\n");
+ bam_ctrl = bam_read_reg(base, CTRL);
+ bam_revision = bam_read_reg(base, REVISION);
+ bam_rev_num = bam_read_reg_field(base, REVISION, BAM_REVISION);
+ bam_rev_ee_num = bam_read_reg_field(base, REVISION, BAM_NUM_EES);
- SPS_INFO("BAM_CTRL: 0x%x\n"
- "BAM_REVISION: 0x%x\n"
- "BAM_NUM_EES: %d\n"
-#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
- "BAM_CMD_DESC_EN: 0x%x\n"
-#endif
- "BAM_NUM_PIPES: %d\n"
- "BAM_DESC_CNT_TRSHLD: 0x%x (%d)\n"
- "BAM_IRQ_SRCS: 0x%x\n"
- "BAM_IRQ_SRCS_MSK: 0x%x\n"
- "BAM_EE: %d\n"
- "BAM_CNFG_BITS: 0x%x\n",
- bam_read_reg(base, CTRL),
- bam_read_reg_field(base, REVISION, BAM_REVISION),
- bam_read_reg_field(base, REVISION, BAM_NUM_EES),
-#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
- bam_read_reg_field(base, REVISION, BAM_CMD_DESC_EN),
-#endif
- bam_read_reg_field(base, NUM_PIPES, BAM_NUM_PIPES),
- bam_read_reg_field(base, DESC_CNT_TRSHLD, BAM_DESC_CNT_TRSHLD),
- bam_read_reg_field(base, DESC_CNT_TRSHLD, BAM_DESC_CNT_TRSHLD),
- bam_read_reg(base, IRQ_SRCS),
- bam_read_reg(base, IRQ_SRCS_MSK),
- bam_read_reg_field(base, TRUST_REG, BAM_EE),
- bam_read_reg(base, CNFG_BITS));
+ bam_num_pipes = bam_read_reg(base, NUM_PIPES);
+ bam_pipe_num = bam_read_reg_field(base, NUM_PIPES, BAM_NUM_PIPES);
- SPS_INFO("\nsps:----- Content of BAM-level registers <end> -----\n");
+ bam_desc_cnt_trshld = bam_read_reg(base, DESC_CNT_TRSHLD);
+ bam_desc_cnt_trd_val = bam_read_reg_field(base, DESC_CNT_TRSHLD,
+ BAM_DESC_CNT_TRSHLD);
+
+ bam_irq_en = bam_read_reg(base, IRQ_EN);
+ bam_irq_stts = bam_read_reg(base, IRQ_STTS);
+
+ if (ee < BAM_MAX_EES) {
+ bam_irq_src_ee = bam_read_reg(base, IRQ_SRCS_EE(ee));
+ bam_irq_msk_ee = bam_read_reg(base, IRQ_SRCS_MSK_EE(ee));
+ bam_irq_unmsk_ee = bam_read_reg(base, IRQ_SRCS_UNMASKED_EE(ee));
+ }
+
+ bam_ahb_err_ctrl = bam_read_reg(base, AHB_MASTER_ERR_CTRLS);
+ bam_ahb_err_addr = bam_read_reg(base, AHB_MASTER_ERR_ADDR);
+ bam_ahb_err_data = bam_read_reg(base, AHB_MASTER_ERR_DATA);
+ bam_cnfg_bits = bam_read_reg(base, CNFG_BITS);
+
+#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
+ bam_sw_rev = bam_read_reg(base, SW_REVISION);
+ bam_timer = bam_read_reg(base, TIMER);
+ bam_timer_ctrl = bam_read_reg(base, TIMER_CTRL);
+#endif
+
+
+ SPS_INFO("\nsps:<bam-begin> --- BAM-level registers ---\n\n");
+
+ SPS_INFO("BAM_CTRL: 0x%x\n", bam_ctrl);
+ SPS_INFO("BAM_REVISION: 0x%x\n", bam_revision);
+ SPS_INFO(" REVISION: 0x%x\n", bam_rev_num);
+ SPS_INFO(" NUM_EES: %d\n", bam_rev_ee_num);
+ SPS_INFO("BAM_SW_REVISION: 0x%x\n", bam_sw_rev);
+ SPS_INFO("BAM_NUM_PIPES: %d\n", bam_num_pipes);
+ SPS_INFO(" NUM_PIPES: %d\n", bam_pipe_num);
+ SPS_INFO("BAM_DESC_CNT_TRSHLD: 0x%x\n", bam_desc_cnt_trshld);
+ SPS_INFO(" DESC_CNT_TRSHLD: 0x%x (%d)\n", bam_desc_cnt_trd_val,
+ bam_desc_cnt_trd_val);
+
+ SPS_INFO("BAM_IRQ_EN: 0x%x\n", bam_irq_en);
+ SPS_INFO("BAM_IRQ_STTS: 0x%x\n", bam_irq_stts);
+
+ if (ee < BAM_MAX_EES) {
+ SPS_INFO("BAM_IRQ_SRCS_EE(%d): 0x%x\n", ee, bam_irq_src_ee);
+ SPS_INFO("BAM_IRQ_SRCS_MSK_EE(%d): 0x%x\n", ee, bam_irq_msk_ee);
+ SPS_INFO("BAM_IRQ_SRCS_UNMASKED_EE(%d): 0x%x\n", ee,
+ bam_irq_unmsk_ee);
+ }
+
+ SPS_INFO("BAM_AHB_MASTER_ERR_CTRLS: 0x%x\n", bam_ahb_err_ctrl);
+ SPS_INFO("BAM_AHB_MASTER_ERR_ADDR: 0x%x\n", bam_ahb_err_addr);
+ SPS_INFO("BAM_AHB_MASTER_ERR_DATA: 0x%x\n", bam_ahb_err_data);
+
+ SPS_INFO("BAM_CNFG_BITS: 0x%x\n", bam_cnfg_bits);
+ SPS_INFO("BAM_TIMER: 0x%x\n", bam_timer);
+ SPS_INFO("BAM_TIMER_CTRL: 0x%x\n", bam_timer_ctrl);
+
+ SPS_INFO("\nsps:<bam-end> --- BAM-level registers ---\n\n");
}
/* output the content of selected BAM pipe registers */
@@ -1289,68 +1352,205 @@
void *base = virt_addr;
u32 pipe = pipe_index;
+ u32 p_ctrl;
+ u32 p_sys_mode;
+ u32 p_direction;
+ u32 p_lock_group = 0;
+
+ u32 p_irq_en;
+ u32 p_irq_stts;
+ u32 p_irq_stts_eot;
+ u32 p_irq_stts_int;
+
+ u32 p_prd_sdbd;
+ u32 p_bytes_free;
+ u32 p_prd_ctrl;
+ u32 p_prd_toggle;
+ u32 p_prd_sb_updated;
+
+ u32 p_con_sdbd;
+ u32 p_bytes_avail;
+ u32 p_con_ctrl;
+ u32 p_con_toggle;
+ u32 p_con_ack_toggle;
+ u32 p_con_ack_toggle_r;
+ u32 p_con_wait_4_ack;
+ u32 p_con_sb_updated;
+
+ u32 p_sw_offset;
+ u32 p_read_pointer;
+ u32 p_evnt_reg;
+ u32 p_write_pointer;
+
+ u32 p_evnt_dest;
+ u32 p_desc_fifo_addr;
+ u32 p_desc_fifo_size;
+ u32 p_data_fifo_addr;
+ u32 p_data_fifo_size;
+ u32 p_fifo_sizes;
+
+ u32 p_evnt_trd;
+ u32 p_evnt_trd_val;
+
+ u32 p_retr_ct;
+ u32 p_retr_offset;
+ u32 p_si_ct;
+ u32 p_si_offset;
+ u32 p_df_ct = 0;
+ u32 p_df_offset = 0;
+ u32 p_au_ct1;
+ u32 p_psm_ct2;
+ u32 p_psm_ct3;
+ u32 p_psm_ct4;
+ u32 p_psm_ct5;
+
+ u32 p_timer;
+ u32 p_timer_ctrl;
+
if (base == NULL)
return;
- SPS_INFO("\nsps:----- Registers of Pipe %d -----\n", pipe);
+ p_ctrl = bam_read_reg(base, P_CTRL(pipe));
+ p_sys_mode = bam_read_reg_field(base, P_CTRL(pipe), P_SYS_MODE);
+ p_direction = bam_read_reg_field(base, P_CTRL(pipe), P_DIRECTION);
- SPS_INFO("BAM_P_CTRL: 0x%x\n"
- "BAM_P_SYS_MODE: %d\n"
- "BAM_P_DIRECTION: %d\n"
+ p_irq_en = bam_read_reg(base, P_IRQ_EN(pipe));
+ p_irq_stts = bam_read_reg(base, P_IRQ_STTS(pipe));
+ p_irq_stts_eot = bam_read_reg_field(base, P_IRQ_STTS(pipe),
+ P_IRQ_STTS_P_TRNSFR_END_IRQ);
+ p_irq_stts_int = bam_read_reg_field(base, P_IRQ_STTS(pipe),
+ P_IRQ_STTS_P_PRCSD_DESC_IRQ);
+
+ p_prd_sdbd = bam_read_reg(base, P_PRDCR_SDBND(pipe));
+ p_bytes_free = bam_read_reg_field(base, P_PRDCR_SDBND(pipe),
+ P_PRDCR_SDBNDn_BAM_P_BYTES_FREE);
+ p_prd_ctrl = bam_read_reg_field(base, P_PRDCR_SDBND(pipe),
+ P_PRDCR_SDBNDn_BAM_P_CTRL);
+ p_prd_toggle = bam_read_reg_field(base, P_PRDCR_SDBND(pipe),
+ P_PRDCR_SDBNDn_BAM_P_TOGGLE);
+ p_prd_sb_updated = bam_read_reg_field(base, P_PRDCR_SDBND(pipe),
+ P_PRDCR_SDBNDn_BAM_P_SB_UPDATED);
+ p_con_sdbd = bam_read_reg(base, P_CNSMR_SDBND(pipe));
+ p_bytes_avail = bam_read_reg_field(base, P_CNSMR_SDBND(pipe),
+ P_CNSMR_SDBNDn_BAM_P_BYTES_AVAIL);
+ p_con_ctrl = bam_read_reg_field(base, P_CNSMR_SDBND(pipe),
+ P_CNSMR_SDBNDn_BAM_P_CTRL);
+ p_con_toggle = bam_read_reg_field(base, P_CNSMR_SDBND(pipe),
+ P_CNSMR_SDBNDn_BAM_P_TOGGLE);
+ p_con_ack_toggle = bam_read_reg_field(base, P_CNSMR_SDBND(pipe),
+ P_CNSMR_SDBNDn_BAM_P_ACK_TOGGLE);
+ p_con_ack_toggle_r = bam_read_reg_field(base, P_CNSMR_SDBND(pipe),
+ P_CNSMR_SDBNDn_BAM_P_ACK_TOGGLE_R);
+ p_con_wait_4_ack = bam_read_reg_field(base, P_CNSMR_SDBND(pipe),
+ P_CNSMR_SDBNDn_BAM_P_WAIT_4_ACK);
+ p_con_sb_updated = bam_read_reg_field(base, P_CNSMR_SDBND(pipe),
+ P_CNSMR_SDBNDn_BAM_P_SB_UPDATED);
+
+ p_sw_offset = bam_read_reg(base, P_SW_OFSTS(pipe));
+ p_read_pointer = bam_read_reg_field(base, P_SW_OFSTS(pipe),
+ SW_DESC_OFST);
+ p_evnt_reg = bam_read_reg(base, P_EVNT_REG(pipe));
+ p_write_pointer = bam_read_reg_field(base, P_EVNT_REG(pipe),
+ P_DESC_FIFO_PEER_OFST);
+
+ p_evnt_dest = bam_read_reg(base, P_EVNT_DEST_ADDR(pipe));
+ p_desc_fifo_addr = bam_read_reg(base, P_DESC_FIFO_ADDR(pipe));
+ p_desc_fifo_size = bam_read_reg_field(base, P_FIFO_SIZES(pipe),
+ P_DESC_FIFO_SIZE);
+ p_data_fifo_addr = bam_read_reg(base, P_DATA_FIFO_ADDR(pipe));
+ p_data_fifo_size = bam_read_reg_field(base, P_FIFO_SIZES(pipe),
+ P_DATA_FIFO_SIZE);
+ p_fifo_sizes = bam_read_reg(base, P_FIFO_SIZES(pipe));
+
+ p_evnt_trd = bam_read_reg(base, P_EVNT_GEN_TRSHLD(pipe));
+ p_evnt_trd_val = bam_read_reg_field(base, P_EVNT_GEN_TRSHLD(pipe),
+ P_EVNT_GEN_TRSHLD_P_TRSHLD);
+
+ p_retr_ct = bam_read_reg(base, P_RETR_CNTXT(pipe));
+ p_retr_offset = bam_read_reg_field(base, P_RETR_CNTXT(pipe),
+ P_RETR_CNTXT_RETR_DESC_OFST);
+ p_si_ct = bam_read_reg(base, P_SI_CNTXT(pipe));
+ p_si_offset = bam_read_reg_field(base, P_SI_CNTXT(pipe),
+ P_SI_CNTXT_SI_DESC_OFST);
+ p_au_ct1 = bam_read_reg(base, P_AU_PSM_CNTXT_1(pipe));
+ p_psm_ct2 = bam_read_reg(base, P_PSM_CNTXT_2(pipe));
+ p_psm_ct3 = bam_read_reg(base, P_PSM_CNTXT_3(pipe));
+ p_psm_ct4 = bam_read_reg(base, P_PSM_CNTXT_4(pipe));
+ p_psm_ct5 = bam_read_reg(base, P_PSM_CNTXT_5(pipe));
+
+ p_timer = bam_read_reg(base, P_TIMER(pipe));
+ p_timer_ctrl = bam_read_reg(base, P_TIMER_CTRL(pipe));
+
#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
- "BAM_P_LOCK_GROUP: 0x%x (%d)\n"
+ p_lock_group = bam_read_reg_field(base, P_CTRL(pipe), P_LOCK_GROUP);
+ p_df_ct = bam_read_reg(base, P_DF_CNTXT(pipe));
+ p_df_offset = bam_read_reg_field(base, P_DF_CNTXT(pipe),
+ P_DF_CNTXT_DF_DESC_OFST);
#endif
- "BAM_P_EE: %d\n"
- "BAM_P_IRQ_STTS: 0x%x\n"
- "BAM_P_IRQ_STTS_P_TRNSFR_END_IRQ: 0x%x\n"
- "BAM_P_IRQ_STTS_P_PRCSD_DESC_IRQ: 0x%x\n"
- "BAM_P_IRQ_EN: 0x%x\n"
- "BAM_P_PRDCR_SDBNDn_BAM_P_BYTES_FREE: 0x%x (%d)\n"
- "BAM_P_CNSMR_SDBNDn_BAM_P_BYTES_AVAIL: 0x%x (%d)\n"
- "BAM_P_SW_DESC_OFST: 0x%x\n"
- "BAM_P_DESC_FIFO_PEER_OFST: 0x%x\n"
- "BAM_P_EVNT_DEST_ADDR: 0x%x\n"
- "BAM_P_DESC_FIFO_ADDR: 0x%x\n"
- "BAM_P_DESC_FIFO_SIZE: 0x%x (%d)\n"
- "BAM_P_DATA_FIFO_ADDR: 0x%x\n"
- "BAM_P_DATA_FIFO_SIZE: 0x%x (%d)\n"
- "BAM_P_EVNT_GEN_TRSHLD: 0x%x (%d)\n",
- bam_read_reg(base, P_CTRL(pipe)),
- bam_read_reg_field(base, P_CTRL(pipe), P_SYS_MODE),
- bam_read_reg_field(base, P_CTRL(pipe), P_DIRECTION),
-#ifdef CONFIG_SPS_SUPPORT_NDP_BAM
- bam_read_reg_field(base, P_CTRL(pipe), P_LOCK_GROUP),
- bam_read_reg_field(base, P_CTRL(pipe), P_LOCK_GROUP),
-#endif
- bam_read_reg_field(base, P_TRUST_REG(pipe), BAM_P_EE),
- bam_read_reg(base, P_IRQ_STTS(pipe)),
- bam_read_reg_field(base, P_IRQ_STTS(pipe),
- P_IRQ_STTS_P_TRNSFR_END_IRQ),
- bam_read_reg_field(base, P_IRQ_STTS(pipe),
- P_IRQ_STTS_P_PRCSD_DESC_IRQ),
- bam_read_reg(base, P_IRQ_EN(pipe)),
- bam_read_reg_field(base, P_PRDCR_SDBND(pipe),
- P_PRDCR_SDBNDn_BAM_P_BYTES_FREE),
- bam_read_reg_field(base, P_PRDCR_SDBND(pipe),
- P_PRDCR_SDBNDn_BAM_P_BYTES_FREE),
- bam_read_reg_field(base, P_CNSMR_SDBND(pipe),
- P_CNSMR_SDBNDn_BAM_P_BYTES_AVAIL),
- bam_read_reg_field(base, P_CNSMR_SDBND(pipe),
- P_CNSMR_SDBNDn_BAM_P_BYTES_AVAIL),
- bam_read_reg_field(base, P_SW_OFSTS(pipe), SW_DESC_OFST),
- bam_read_reg_field(base, P_EVNT_REG(pipe),
- P_DESC_FIFO_PEER_OFST),
- bam_read_reg(base, P_EVNT_DEST_ADDR(pipe)),
- bam_read_reg(base, P_DESC_FIFO_ADDR(pipe)),
- bam_read_reg_field(base, P_FIFO_SIZES(pipe), P_DESC_FIFO_SIZE),
- bam_read_reg_field(base, P_FIFO_SIZES(pipe), P_DESC_FIFO_SIZE),
- bam_read_reg(base, P_DATA_FIFO_ADDR(pipe)),
- bam_read_reg_field(base, P_FIFO_SIZES(pipe), P_DATA_FIFO_SIZE),
- bam_read_reg_field(base, P_FIFO_SIZES(pipe), P_DATA_FIFO_SIZE),
- bam_read_reg_field(base, P_EVNT_GEN_TRSHLD(pipe),
- P_EVNT_GEN_TRSHLD_P_TRSHLD),
- bam_read_reg_field(base, P_EVNT_GEN_TRSHLD(pipe),
- P_EVNT_GEN_TRSHLD_P_TRSHLD));
+
+ SPS_INFO("\nsps:<pipe-begin> --- Registers of Pipe %d ---\n\n", pipe);
+
+ SPS_INFO("BAM_P_CTRL: 0x%x\n", p_ctrl);
+ SPS_INFO(" SYS_MODE: %d\n", p_sys_mode);
+ if (p_direction)
+ SPS_INFO(" DIRECTION:%d->Producer\n", p_direction);
+ else
+ SPS_INFO(" DIRECTION:%d->Consumer\n", p_direction);
+ SPS_INFO(" LOCK_GROUP: 0x%x (%d)\n", p_lock_group, p_lock_group);
+
+ SPS_INFO("BAM_P_IRQ_EN: 0x%x\n", p_irq_en);
+ SPS_INFO("BAM_P_IRQ_STTS: 0x%x\n", p_irq_stts);
+ SPS_INFO(" TRNSFR_END_IRQ(EOT): 0x%x\n", p_irq_stts_eot);
+ SPS_INFO(" PRCSD_DESC_IRQ(INT): 0x%x\n", p_irq_stts_int);
+
+ SPS_INFO("BAM_P_PRDCR_SDBND: 0x%x\n", p_prd_sdbd);
+ SPS_INFO(" BYTES_FREE: 0x%x (%d)\n", p_bytes_free, p_bytes_free);
+ SPS_INFO(" CTRL: 0x%x\n", p_prd_ctrl);
+ SPS_INFO(" TOGGLE: %d\n", p_prd_toggle);
+ SPS_INFO(" SB_UPDATED: %d\n", p_prd_sb_updated);
+ SPS_INFO("BAM_P_CNSMR_SDBND: 0x%x\n", p_con_sdbd);
+ SPS_INFO(" WAIT_4_ACK: %d\n", p_con_wait_4_ack);
+ SPS_INFO(" BYTES_AVAIL: 0x%x (%d)\n", p_bytes_avail, p_bytes_avail);
+ SPS_INFO(" CTRL: 0x%x\n", p_con_ctrl);
+ SPS_INFO(" TOGGLE: %d\n", p_con_toggle);
+ SPS_INFO(" ACK_TOGGLE: %d\n", p_con_ack_toggle);
+ SPS_INFO(" ACK_TOGGLE_R: %d\n", p_con_ack_toggle_r);
+ SPS_INFO(" SB_UPDATED: %d\n", p_con_sb_updated);
+
+ SPS_INFO("BAM_P_SW_DESC_OFST: 0x%x\n", p_sw_offset);
+ SPS_INFO(" SW_DESC_OFST: 0x%x\n", p_read_pointer);
+ SPS_INFO("BAM_P_EVNT_REG: 0x%x\n", p_evnt_reg);
+ SPS_INFO(" DESC_FIFO_PEER_OFST: 0x%x\n", p_write_pointer);
+
+ SPS_INFO("BAM_P_RETR_CNTXT: 0x%x\n", p_retr_ct);
+ SPS_INFO(" RETR_OFFSET: 0x%x\n", p_retr_offset);
+ SPS_INFO("BAM_P_SI_CNTXT: 0x%x\n", p_si_ct);
+ SPS_INFO(" SI_OFFSET: 0x%x\n", p_si_offset);
+ SPS_INFO("BAM_P_DF_CNTXT: 0x%x\n", p_df_ct);
+ SPS_INFO(" DF_OFFSET: 0x%x\n", p_df_offset);
+
+ SPS_INFO("BAM_P_DESC_FIFO_ADDR: 0x%x\n", p_desc_fifo_addr);
+ SPS_INFO("BAM_P_DATA_FIFO_ADDR: 0x%x\n", p_data_fifo_addr);
+ SPS_INFO("BAM_P_FIFO_SIZES: 0x%x\n", p_fifo_sizes);
+ SPS_INFO(" DESC_FIFO_SIZE: 0x%x (%d)\n", p_desc_fifo_size,
+ p_desc_fifo_size);
+ SPS_INFO(" DATA_FIFO_SIZE: 0x%x (%d)\n", p_data_fifo_size,
+ p_data_fifo_size);
+
+ SPS_INFO("BAM_P_EVNT_DEST_ADDR: 0x%x\n", p_evnt_dest);
+ SPS_INFO("BAM_P_EVNT_GEN_TRSHLD: 0x%x\n", p_evnt_trd);
+ SPS_INFO(" EVNT_GEN_TRSHLD: 0x%x (%d)\n", p_evnt_trd_val,
+ p_evnt_trd_val);
+
+ SPS_INFO("BAM_P_AU_PSM_CNTXT_1: 0x%x\n", p_au_ct1);
+ SPS_INFO("BAM_P_PSM_CNTXT_2: 0x%x\n", p_psm_ct2);
+ SPS_INFO("BAM_P_PSM_CNTXT_3: 0x%x\n", p_psm_ct3);
+ SPS_INFO("BAM_P_PSM_CNTXT_4: 0x%x\n", p_psm_ct4);
+ SPS_INFO("BAM_P_PSM_CNTXT_5: 0x%x\n", p_psm_ct5);
+ SPS_INFO("BAM_P_TIMER: 0x%x\n", p_timer);
+ SPS_INFO("BAM_P_TIMER_CTRL: 0x%x\n", p_timer_ctrl);
+
+ SPS_INFO("\nsps:<pipe-end> --- Registers of Pipe %d ---\n\n", pipe);
}
/* output descriptor FIFO of a pipe */
@@ -1362,6 +1562,7 @@
u32 desc_fifo_size;
u32 *desc_fifo;
int i;
+ char desc_info[MAX_MSG_LEN];
if (base == NULL)
return;
@@ -1380,7 +1581,8 @@
return;
}
- SPS_INFO("\nsps:----- descriptor FIFO of Pipe %d -----\n", pipe);
+ SPS_INFO("\nsps:<desc-begin> --- descriptor FIFO of Pipe %d -----\n\n",
+ pipe);
SPS_INFO("BAM_P_DESC_FIFO_ADDR: 0x%x\n"
"BAM_P_DESC_FIFO_SIZE: 0x%x (%d)\n\n",
@@ -1428,17 +1630,49 @@
if (desc_fifo_size > current_desc + size / 2)
end = current_desc + size / 2;
- SPS_INFO("------------- begin of partial FIFO -------------\n");
+ SPS_INFO("------------ begin of partial FIFO ------------\n\n");
- for (i = begin; i < end; i += 0x10)
- SPS_INFO("addr 0x%x: 0x%x, 0x%x, 0x%x, 0x%x.\n",
+ SPS_INFO("desc addr; desc content; desc flags\n");
+ for (i = begin; i < end; i += 0x8) {
+ u32 offset;
+ u32 flags = desc_fifo[(i / 4) + 1] >> 16;
+
+ memset(desc_info, 0, sizeof(desc_info));
+ offset = scnprintf(desc_info, 40, "0x%x: 0x%x, 0x%x: ",
desc_fifo_addr + i,
- desc_fifo[i / 4], desc_fifo[(i / 4) + 1],
- desc_fifo[(i / 4) + 2], desc_fifo[(i / 4) + 3]);
+ desc_fifo[i / 4], desc_fifo[(i / 4) + 1]);
- SPS_INFO("------------- end of partial FIFO -------------\n");
+ if (flags & SPS_IOVEC_FLAG_INT)
+ offset += scnprintf(desc_info + offset, 5,
+ "INT ");
+ if (flags & SPS_IOVEC_FLAG_EOT)
+ offset += scnprintf(desc_info + offset, 5,
+ "EOT ");
+ if (flags & SPS_IOVEC_FLAG_EOB)
+ offset += scnprintf(desc_info + offset, 5,
+ "EOB ");
+ if (flags & SPS_IOVEC_FLAG_NWD)
+ offset += scnprintf(desc_info + offset, 5,
+ "NWD ");
+ if (flags & SPS_IOVEC_FLAG_CMD)
+ offset += scnprintf(desc_info + offset, 5,
+ "CMD ");
+ if (flags & SPS_IOVEC_FLAG_LOCK)
+ offset += scnprintf(desc_info + offset, 5,
+ "LCK ");
+ if (flags & SPS_IOVEC_FLAG_UNLOCK)
+ offset += scnprintf(desc_info + offset, 5,
+ "UNL ");
+ if (flags & SPS_IOVEC_FLAG_IMME)
+ offset += scnprintf(desc_info + offset, 5,
+ "IMM ");
+
+ SPS_INFO("%s\n", desc_info);
+ }
+
+ SPS_INFO("\n------------ end of partial FIFO ------------\n");
} else {
- SPS_INFO("----------------- begin of FIFO -----------------\n");
+ SPS_INFO("---------------- begin of FIFO ----------------\n\n");
for (i = 0; i < desc_fifo_size; i += 0x10)
SPS_INFO("addr 0x%x: 0x%x, 0x%x, 0x%x, 0x%x.\n",
@@ -1446,8 +1680,11 @@
desc_fifo[i / 4], desc_fifo[(i / 4) + 1],
desc_fifo[(i / 4) + 2], desc_fifo[(i / 4) + 3]);
- SPS_INFO("----------------- end of FIFO -----------------\n");
+ SPS_INFO("\n---------------- end of FIFO ----------------\n");
}
+
+ SPS_INFO("\nsps:<desc-end> --- descriptor FIFO of Pipe %d -----\n\n",
+ pipe);
}
/* output BAM_TEST_BUS_REG with specified TEST_BUS_SEL */
@@ -1476,14 +1713,18 @@
BAM_TESTBUS_SEL));
}
+ SPS_INFO("\nsps:<testbus-begin> --- BAM TEST_BUS dump -----\n\n");
+
/* output other selections */
for (i = 0; i < size; i++) {
bam_write_reg_field(base, TEST_BUS_SEL, BAM_TESTBUS_SEL,
test_bus_selection[i]);
- SPS_INFO("sps:bam 0x%x(va);TEST_BUS_REG:0x%x;TEST_BUS_SEL:0x%x",
- (u32) base, bam_read_reg(base, TEST_BUS_REG),
+ SPS_INFO("sps:TEST_BUS_REG:0x%x\t TEST_BUS_SEL:0x%x\n",
+ bam_read_reg(base, TEST_BUS_REG),
bam_read_reg_field(base, TEST_BUS_SEL,
BAM_TESTBUS_SEL));
}
+
+ SPS_INFO("\nsps:<testbus-end> --- BAM TEST_BUS dump -----\n\n");
}
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index b34f9dc..6f2e2a4 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -325,7 +325,7 @@
print_bam_reg(vir_addr);
break;
case 3: /* output selected BAM-level registers */
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
break;
case 4: /* output selected registers of all pipes */
for (i = 0; i < num_pipes; i++)
@@ -401,21 +401,14 @@
case 91: /* output testbus register, BAM global regisers
and registers of all pipes */
print_bam_test_bus_reg(vir_addr, testbus_sel);
- print_bam_reg(vir_addr);
- for (i = 0; i < num_pipes; i++)
- print_bam_pipe_reg(vir_addr, i);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
print_bam_pipe_selected_reg(vir_addr, i);
break;
case 92: /* output testbus register, BAM global regisers
and registers of selected pipes */
print_bam_test_bus_reg(vir_addr, testbus_sel);
- print_bam_reg(vir_addr);
- for (i = 0; i < num_pipes; i++)
- if (bam_pipe_sel & (1UL << i))
- print_bam_pipe_reg(vir_addr, i);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
if (bam_pipe_sel & (1UL << i))
print_bam_pipe_selected_reg(vir_addr, i);
@@ -425,11 +418,7 @@
if (desc_option == 0)
desc_option = 1;
print_bam_test_bus_reg(vir_addr, testbus_sel);
- print_bam_reg(vir_addr);
- for (i = 0; i < num_pipes; i++)
- if (bam_pipe_sel & (1UL << i))
- print_bam_pipe_reg(vir_addr, i);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
if (bam_pipe_sel & (1UL << i))
print_bam_pipe_selected_reg(vir_addr, i);
@@ -443,11 +432,9 @@
if (desc_option == 0)
desc_option = 1;
print_bam_test_bus_reg(vir_addr, testbus_sel);
- print_bam_reg(vir_addr);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
if (bam_pipe_sel & (1UL << i)) {
- print_bam_pipe_reg(vir_addr, i);
print_bam_pipe_selected_reg(vir_addr, i);
print_bam_pipe_desc_fifo(vir_addr, i,
desc_option);
@@ -456,11 +443,7 @@
case 95: /* output registers and desc FIFOs
of selected pipes: format 1 */
print_bam_test_bus_reg(vir_addr, testbus_sel);
- print_bam_reg(vir_addr);
- for (i = 0; i < num_pipes; i++)
- if (bam_pipe_sel & (1UL << i))
- print_bam_pipe_reg(vir_addr, i);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
if (bam_pipe_sel & (1UL << i))
print_bam_pipe_selected_reg(vir_addr, i);
@@ -471,11 +454,9 @@
case 96: /* output registers and desc FIFOs
of selected pipes: format 2 */
print_bam_test_bus_reg(vir_addr, testbus_sel);
- print_bam_reg(vir_addr);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
if (bam_pipe_sel & (1UL << i)) {
- print_bam_pipe_reg(vir_addr, i);
print_bam_pipe_selected_reg(vir_addr, i);
print_bam_pipe_desc_fifo(vir_addr, i, 0);
}
@@ -483,11 +464,7 @@
case 97: /* output registers, desc FIFOs and partial data blocks
of selected pipes: format 1 */
print_bam_test_bus_reg(vir_addr, testbus_sel);
- print_bam_reg(vir_addr);
- for (i = 0; i < num_pipes; i++)
- if (bam_pipe_sel & (1UL << i))
- print_bam_pipe_reg(vir_addr, i);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
if (bam_pipe_sel & (1UL << i))
print_bam_pipe_selected_reg(vir_addr, i);
@@ -501,11 +478,9 @@
case 98: /* output registers, desc FIFOs and partial data blocks
of selected pipes: format 2 */
print_bam_test_bus_reg(vir_addr, testbus_sel);
- print_bam_reg(vir_addr);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
if (bam_pipe_sel & (1UL << i)) {
- print_bam_pipe_reg(vir_addr, i);
print_bam_pipe_selected_reg(vir_addr, i);
print_bam_pipe_desc_fifo(vir_addr, i, 0);
print_bam_pipe_desc_fifo(vir_addr, i, 100);
@@ -516,7 +491,7 @@
print_bam_reg(vir_addr);
for (i = 0; i < num_pipes; i++)
print_bam_pipe_reg(vir_addr, i);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
print_bam_pipe_selected_reg(vir_addr, i);
for (i = 0; i < num_pipes; i++)
@@ -674,7 +649,7 @@
/* Get the debug info of BAM registers and descriptor FIFOs */
int sps_get_bam_debug_info(u32 dev, u32 option, u32 para,
- u32 tb_sel, u8 desc_sel)
+ u32 tb_sel, u32 desc_sel)
{
int res = 0;
struct sps_bam *bam;
@@ -700,6 +675,8 @@
vir_addr = bam->base;
num_pipes = bam->props.num_pipes;
+ SPS_INFO("sps:<bam-addr> dump BAM:0x%x.\n", bam->props.phys_addr);
+
switch (option) {
case 1: /* output all registers of this BAM */
print_bam_reg(vir_addr);
@@ -710,7 +687,7 @@
print_bam_reg(vir_addr);
break;
case 3: /* output selected BAM-level registers */
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
break;
case 4: /* output selected registers of all pipes */
for (i = 0; i < num_pipes; i++)
@@ -784,21 +761,14 @@
case 91: /* output testbus register, BAM global regisers
and registers of all pipes */
print_bam_test_bus_reg(vir_addr, tb_sel);
- print_bam_reg(vir_addr);
- for (i = 0; i < num_pipes; i++)
- print_bam_pipe_reg(vir_addr, i);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
print_bam_pipe_selected_reg(vir_addr, i);
break;
case 92: /* output testbus register, BAM global regisers
and registers of selected pipes */
print_bam_test_bus_reg(vir_addr, tb_sel);
- print_bam_reg(vir_addr);
- for (i = 0; i < num_pipes; i++)
- if (para & (1UL << i))
- print_bam_pipe_reg(vir_addr, i);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
if (para & (1UL << i))
print_bam_pipe_selected_reg(vir_addr, i);
@@ -808,11 +778,7 @@
if (desc_sel == 0)
desc_sel = 1;
print_bam_test_bus_reg(vir_addr, tb_sel);
- print_bam_reg(vir_addr);
- for (i = 0; i < num_pipes; i++)
- if (para & (1UL << i))
- print_bam_pipe_reg(vir_addr, i);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
if (para & (1UL << i))
print_bam_pipe_selected_reg(vir_addr, i);
@@ -826,11 +792,9 @@
if (desc_sel == 0)
desc_sel = 1;
print_bam_test_bus_reg(vir_addr, tb_sel);
- print_bam_reg(vir_addr);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
if (para & (1UL << i)) {
- print_bam_pipe_reg(vir_addr, i);
print_bam_pipe_selected_reg(vir_addr, i);
print_bam_pipe_desc_fifo(vir_addr, i,
desc_sel);
@@ -839,11 +803,7 @@
case 95: /* output registers and desc FIFOs
of selected pipes: format 1 */
print_bam_test_bus_reg(vir_addr, tb_sel);
- print_bam_reg(vir_addr);
- for (i = 0; i < num_pipes; i++)
- if (para & (1UL << i))
- print_bam_pipe_reg(vir_addr, i);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
if (para & (1UL << i))
print_bam_pipe_selected_reg(vir_addr, i);
@@ -854,11 +814,9 @@
case 96: /* output registers and desc FIFOs
of selected pipes: format 2 */
print_bam_test_bus_reg(vir_addr, tb_sel);
- print_bam_reg(vir_addr);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
if (para & (1UL << i)) {
- print_bam_pipe_reg(vir_addr, i);
print_bam_pipe_selected_reg(vir_addr, i);
print_bam_pipe_desc_fifo(vir_addr, i, 0);
}
@@ -866,11 +824,7 @@
case 97: /* output registers, desc FIFOs and partial data blocks
of selected pipes: format 1 */
print_bam_test_bus_reg(vir_addr, tb_sel);
- print_bam_reg(vir_addr);
- for (i = 0; i < num_pipes; i++)
- if (para & (1UL << i))
- print_bam_pipe_reg(vir_addr, i);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
if (para & (1UL << i))
print_bam_pipe_selected_reg(vir_addr, i);
@@ -884,11 +838,9 @@
case 98: /* output registers, desc FIFOs and partial data blocks
of selected pipes: format 2 */
print_bam_test_bus_reg(vir_addr, tb_sel);
- print_bam_reg(vir_addr);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
if (para & (1UL << i)) {
- print_bam_pipe_reg(vir_addr, i);
print_bam_pipe_selected_reg(vir_addr, i);
print_bam_pipe_desc_fifo(vir_addr, i, 0);
print_bam_pipe_desc_fifo(vir_addr, i, 100);
@@ -899,7 +851,7 @@
print_bam_reg(vir_addr);
for (i = 0; i < num_pipes; i++)
print_bam_pipe_reg(vir_addr, i);
- print_bam_selected_reg(vir_addr);
+ print_bam_selected_reg(vir_addr, bam->props.ee);
for (i = 0; i < num_pipes; i++)
print_bam_pipe_selected_reg(vir_addr, i);
for (i = 0; i < num_pipes; i++)
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index 5ad281d..3ebb1cd 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -403,8 +403,9 @@
}
dev->state |= BAM_STATE_ENABLED;
- SPS_INFO("sps:BAM 0x%x enabled: ver:0x%x, number of pipes:%d",
- BAM_ID(dev), dev->version, dev->props.num_pipes);
+ SPS_INFO("sps:BAM 0x%x (va:0x%x) enabled: ver:0x%x, number of pipes:%d",
+ BAM_ID(dev), (u32) dev->base, dev->version,
+ dev->props.num_pipes);
return 0;
}
@@ -826,9 +827,14 @@
}
if (bam_pipe_is_enabled(dev->base, pipe_index)) {
- SPS_ERR("sps:BAM 0x%x pipe %d sharing violation",
- BAM_ID(dev), pipe_index);
- return SPS_ERROR;
+ if (params->options & SPS_O_NO_DISABLE)
+ SPS_DBG("sps:BAM 0x%x pipe %d is already enabled\n",
+ BAM_ID(dev), pipe_index);
+ else {
+ SPS_ERR("sps:BAM 0x%x pipe %d sharing violation\n",
+ BAM_ID(dev), pipe_index);
+ return SPS_ERROR;
+ }
}
if (bam_pipe_init(dev->base, pipe_index, &hw_params, dev->props.ee)) {
@@ -881,8 +887,13 @@
bam_pipe->state |= BAM_STATE_INIT;
result = 0;
exit_err:
- if (result)
- bam_pipe_exit(dev->base, pipe_index, dev->props.ee);
+ if (result) {
+ if (params->options & SPS_O_NO_DISABLE)
+ SPS_DBG("sps:BAM 0x%x pipe %d connection exits\n",
+ BAM_ID(dev), pipe_index);
+ else
+ bam_pipe_exit(dev->base, pipe_index, dev->props.ee);
+ }
exit_init_err:
if (result) {
/* Clear the client pipe state */
@@ -915,7 +926,11 @@
dev->pipe_active_mask &= ~(1UL << pipe_index);
}
dev->pipe_remote_mask &= ~(1UL << pipe_index);
- bam_pipe_exit(dev->base, pipe_index, dev->props.ee);
+ if (pipe->connect.options & SPS_O_NO_DISABLE)
+ SPS_DBG("sps:BAM 0x%x pipe %d exits\n", BAM_ID(dev),
+ pipe_index);
+ else
+ bam_pipe_exit(dev->base, pipe_index, dev->props.ee);
if (pipe->sys.desc_cache != NULL) {
u32 size = pipe->num_descs * sizeof(void *);
if (pipe->desc_size + size <= PAGE_SIZE)
@@ -1113,7 +1128,12 @@
struct sps_pipe *pipe = dev->pipes[pipe_index];
/* Disable the BAM pipe */
- bam_pipe_disable(dev->base, pipe_index);
+ if (pipe->connect.options & SPS_O_NO_DISABLE)
+ SPS_DBG("sps:BAM 0x%x pipe %d enters disable state\n",
+ BAM_ID(dev), pipe_index);
+ else
+ bam_pipe_disable(dev->base, pipe_index);
+
pipe->state &= ~BAM_STATE_ENABLED;
return 0;
diff --git a/drivers/platform/msm/sps/spsi.h b/drivers/platform/msm/sps/spsi.h
index 5b70fb0..8da3b40 100644
--- a/drivers/platform/msm/sps/spsi.h
+++ b/drivers/platform/msm/sps/spsi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -40,6 +40,8 @@
/* "Clear" value for the connection parameter struct */
#define SPSRM_CLEAR 0xcccccccc
+#define MAX_MSG_LEN 80
+
extern u32 d_type;
#ifdef CONFIG_DEBUG_FS
@@ -48,25 +50,28 @@
extern u8 debug_level_option;
extern u8 print_limit_option;
-#define MAX_MSG_LEN 80
#define SPS_DEBUGFS(msg, args...) do { \
char buf[MAX_MSG_LEN]; \
snprintf(buf, MAX_MSG_LEN, msg"\n", ##args); \
sps_debugfs_record(buf); \
} while (0)
#define SPS_ERR(msg, args...) do { \
- if (unlikely(print_limit_option > 2)) \
- pr_err_ratelimited(msg, ##args); \
- else \
- pr_err(msg, ##args); \
+ if (logging_option != 1) { \
+ if (unlikely(print_limit_option > 2)) \
+ pr_err_ratelimited(msg, ##args); \
+ else \
+ pr_err(msg, ##args); \
+ } \
if (unlikely(debugfs_record_enabled)) \
SPS_DEBUGFS(msg, ##args); \
} while (0)
#define SPS_INFO(msg, args...) do { \
- if (unlikely(print_limit_option > 1)) \
- pr_info_ratelimited(msg, ##args); \
- else \
- pr_info(msg, ##args); \
+ if (logging_option != 1) { \
+ if (unlikely(print_limit_option > 1)) \
+ pr_info_ratelimited(msg, ##args); \
+ else \
+ pr_info(msg, ##args); \
+ } \
if (unlikely(debugfs_record_enabled)) \
SPS_DEBUGFS(msg, ##args); \
} while (0)
@@ -192,7 +197,7 @@
void print_bam_pipe_reg(void *, u32);
/* output the content of selected BAM-level registers */
-void print_bam_selected_reg(void *);
+void print_bam_selected_reg(void *, u32);
/* output the content of selected BAM pipe registers */
void print_bam_pipe_selected_reg(void *, u32);
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index a5fac9e..1d0fb5d 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -177,8 +177,8 @@
*usb_pipe_idx = pipe_connect->dst_pipe_index;
}
- /* If BAM is using dedicated SPS pipe memory, get it */
- if (pipe_connect->mem_type == SPS_PIPE_MEM) {
+ switch (pipe_connect->mem_type) {
+ case SPS_PIPE_MEM:
pr_debug("%s: USB BAM using SPS pipe memory\n", __func__);
ret = sps_setup_bam2bam_fifo(
data_buf,
@@ -199,7 +199,8 @@
ret);
goto free_sps_endpoint;
}
- } else if (pipe_connect->mem_type == USB_PRIVATE_MEM) {
+ break;
+ case USB_PRIVATE_MEM:
pr_debug("%s: USB BAM using private memory\n", __func__);
if (IS_ERR(ctx.mem_clk) || IS_ERR(ctx.mem_iface_clk)) {
@@ -227,10 +228,12 @@
pr_debug("Writing 0x%x to QSCRATCH_RAM1\n", ram1_value);
writel_relaxed(ram1_value, ctx.qscratch_ram1_reg);
-
+ /* fall through */
+ case OCI_MEM:
+ pr_debug("%s: USB BAM using oci memory\n", __func__);
data_buf->phys_base =
pipe_connect->data_fifo_base_offset +
- pdata->usb_base_address;
+ pdata->usb_bam_fifo_baseaddr;
data_buf->size = pipe_connect->data_fifo_size;
data_buf->base =
ioremap(data_buf->phys_base, data_buf->size);
@@ -238,12 +241,13 @@
desc_buf->phys_base =
pipe_connect->desc_fifo_base_offset +
- pdata->usb_base_address;
+ pdata->usb_bam_fifo_baseaddr;
desc_buf->size = pipe_connect->desc_fifo_size;
desc_buf->base =
ioremap(desc_buf->phys_base, desc_buf->size);
memset(desc_buf->base, 0, desc_buf->size);
- } else {
+ break;
+ case SYSTEM_MEM:
pr_debug("%s: USB BAM using system memory\n", __func__);
/* BAM would use system memory, allocate FIFOs */
data_buf->size = pipe_connect->data_fifo_size;
@@ -261,6 +265,10 @@
&(desc_buf->phys_base),
0);
memset(desc_buf->base, 0, pipe_connect->desc_fifo_size);
+ break;
+ default:
+ pr_err("%s: invalid mem type\n", __func__);
+ goto free_sps_endpoint;
}
sps_connection->data = *data_buf;
@@ -436,7 +444,8 @@
sps_disconnect(pipe);
sps_free_endpoint(pipe);
- if (pipe_connect->mem_type == SYSTEM_MEM) {
+ switch (pipe_connect->mem_type) {
+ case SYSTEM_MEM:
pr_debug("%s: Freeing system memory used by PIPE\n", __func__);
if (sps_connection->data.phys_base)
dma_free_coherent(&ctx.usb_bam_pdev->dev,
@@ -448,13 +457,20 @@
sps_connection->desc.size,
sps_connection->desc.base,
sps_connection->desc.phys_base);
- } else if (pipe_connect->mem_type == USB_PRIVATE_MEM) {
- pr_debug("Freeing USB private memory used by BAM PIPE\n");
+ break;
+ case USB_PRIVATE_MEM:
+ pr_debug("Freeing private memory used by BAM PIPE\n");
writel_relaxed(0x0, ctx.qscratch_ram1_reg);
- iounmap(sps_connection->data.base);
- iounmap(sps_connection->desc.base);
clk_disable_unprepare(ctx.mem_clk);
clk_disable_unprepare(ctx.mem_iface_clk);
+ case OCI_MEM:
+ pr_debug("Freeing oci memory used by BAM PIPE\n");
+ iounmap(sps_connection->data.base);
+ iounmap(sps_connection->desc.base);
+ break;
+ case SPS_PIPE_MEM:
+ pr_debug("%s: nothing to be be\n", __func__);
+ break;
}
sps_connection->options &= ~SPS_O_AUTO_ENABLE;
@@ -973,8 +989,8 @@
return NULL;
}
- rc = of_property_read_u32(node, "qcom,usb-base-address",
- &pdata->usb_base_address);
+ rc = of_property_read_u32(node, "qcom,usb-bam-fifo-baseaddr",
+ &pdata->usb_bam_fifo_baseaddr);
if (rc)
pr_debug("%s: Invalid usb base address property\n", __func__);
@@ -1012,11 +1028,13 @@
if (rc)
goto err;
- if (usb_bam_connections[i].mem_type == USB_PRIVATE_MEM &&
- !pdata->usb_base_address) {
- pr_err("%s: base address is missing for private mem\n",
- __func__);
- goto err;
+ if (usb_bam_connections[i].mem_type == USB_PRIVATE_MEM ||
+ usb_bam_connections[i].mem_type == OCI_MEM) {
+ if (!pdata->usb_bam_fifo_baseaddr) {
+ pr_err("%s: base address is missing\n",
+ __func__);
+ goto err;
+ }
}
rc = of_property_read_u32(node, "qcom,bam-type",
@@ -1148,6 +1166,7 @@
goto free_bam_regs;
}
}
+
props.phys_addr = res->start;
props.virt_addr = usb_virt_addr;
props.virt_size = resource_size(res);
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index a2701ce..c09373a 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -170,6 +170,9 @@
int disable_flat_portion_ocv;
int ocv_dis_high_soc;
int ocv_dis_low_soc;
+ int high_ocv_correction_limit_uv;
+ int low_ocv_correction_limit_uv;
+ int hold_soc_est;
int prev_vbat_batt_terminal_uv;
int vbatt_cutoff_count;
int low_voltage_detect;
@@ -1861,6 +1864,7 @@
int m = 0;
int rc = 0;
int delta_ocv_uv_limit = 0;
+ int correction_limit_uv = 0;
rc = pm8921_bms_get_simultaneous_battery_voltage_and_current(
&ibat_ua,
@@ -1905,17 +1909,13 @@
/*
* do not adjust
- * if soc is same as what bms calculated
- * if soc_est is between 45 and 25, this is the flat portion of the
- * curve where soc_est is not so accurate. We generally don't want to
- * adjust when soc_est is inaccurate except for the cases when soc is
- * way far off (higher than 50 or lesser than 20).
- * Also don't adjust soc if it is above 90 becuase we might pull it low
+ * if soc_est is same as what bms calculated
+ * OR if soc_est > 15
+ * OR if soc it is above 90 because we might pull it low
* and cause a bad user experience
*/
if (soc_est == soc
- || (is_between(45, chip->adjust_soc_low_threshold, soc_est)
- && is_between(50, chip->adjust_soc_low_threshold - 5, soc))
+ || soc_est > 15
|| soc >= 90)
goto out;
@@ -1964,6 +1964,22 @@
pr_debug("new delta ocv = %d\n", delta_ocv_uv);
}
+ if (chip->last_ocv_uv > 3800000)
+ correction_limit_uv = the_chip->high_ocv_correction_limit_uv;
+ else
+ correction_limit_uv = the_chip->low_ocv_correction_limit_uv;
+
+ if (abs(delta_ocv_uv) > correction_limit_uv) {
+ pr_debug("limiting delta ocv %d limit = %d\n", delta_ocv_uv,
+ correction_limit_uv);
+
+ if (delta_ocv_uv > 0)
+ delta_ocv_uv = correction_limit_uv;
+ else
+ delta_ocv_uv = -1 * correction_limit_uv;
+ pr_debug("new delta ocv = %d\n", delta_ocv_uv);
+ }
+
chip->last_ocv_uv -= delta_ocv_uv;
if (chip->last_ocv_uv >= chip->max_voltage_uv)
@@ -1980,7 +1996,7 @@
* if soc_new is ZERO force it higher so that phone doesnt report soc=0
* soc = 0 should happen only when soc_est == 0
*/
- if (soc_new == 0 && soc_est != 0)
+ if (soc_new == 0 && soc_est >= the_chip->hold_soc_est)
soc_new = 1;
soc = soc_new;
@@ -2479,9 +2495,18 @@
/* last_soc < soc ... scale and catch up */
if (last_soc != -EINVAL && last_soc < soc && soc != 100)
- soc = scale_soc_while_chg(chip, delta_time_us, soc, last_soc);
+ soc = scale_soc_while_chg(chip, delta_time_us,
+ soc, last_soc);
- last_soc = soc;
+ /* restrict soc to 1% change */
+ if (last_soc != -EINVAL) {
+ if (soc < last_soc && soc != 0)
+ soc = last_soc - 1;
+ if (soc > last_soc && soc != 100)
+ soc = last_soc + 1;
+ }
+
+ last_soc = bound_soc(soc);
backup_soc_and_iavg(chip, batt_temp, last_soc);
pr_debug("Reported SOC = %d\n", last_soc);
chip->t_soc_queried = now;
@@ -2489,6 +2514,65 @@
return last_soc;
}
+void pm8921_bms_battery_removed(void)
+{
+ if (!the_chip) {
+ pr_err("called before initialization\n");
+ return;
+ }
+ pr_info("Battery Removed Cleaning up\n");
+
+ cancel_delayed_work_sync(&the_chip->calculate_soc_delayed_work);
+ calculated_soc = 0;
+ the_chip->start_percent = -EINVAL;
+ the_chip->end_percent = -EINVAL;
+ /* cleanup for charge time catchup */
+ the_chip->charge_time_us = 0;
+ the_chip->catch_up_time_us = 0;
+ /* cleanup for charge time adjusting */
+ the_chip->soc_at_cv = -EINVAL;
+ the_chip->soc_at_cv = -EINVAL;
+ the_chip->prev_chg_soc = -EINVAL;
+ the_chip->ibat_at_cv_ua = 0;
+ the_chip->prev_vbat_batt_terminal_uv = 0;
+ /* ocv cleanups */
+ the_chip->ocv_reading_at_100 = OCV_RAW_UNINITIALIZED;
+ the_chip->prev_last_good_ocv_raw = OCV_RAW_UNINITIALIZED;
+ the_chip->last_ocv_temp_decidegc = -EINVAL;
+
+ /* cleanup delta time */
+ the_chip->tm_sec = 0;
+
+ /* cc and avg current cleanups */
+ the_chip->prev_iavg_ua = 0;
+ the_chip->last_cc_uah = INT_MIN;
+
+ /* report SOC cleanups */
+ the_chip->t_soc_queried.tv_sec = 0;
+ the_chip->t_soc_queried.tv_nsec = 0;
+
+ last_soc = -EINVAL;
+ /* store invalid soc */
+ pm8xxx_writeb(the_chip->dev->parent, TEMP_SOC_STORAGE, 0);
+
+ /* UUC related data is left as is - use the same historical load avg */
+ update_power_supply(the_chip);
+}
+EXPORT_SYMBOL(pm8921_bms_battery_removed);
+
+void pm8921_bms_battery_inserted(void)
+{
+ if (!the_chip) {
+ pr_err("called before initialization\n");
+ return;
+ }
+
+ pr_info("Battery Inserted\n");
+ the_chip->last_ocv_uv = estimate_ocv(the_chip);
+ schedule_delayed_work(&the_chip->calculate_soc_delayed_work, 0);
+}
+EXPORT_SYMBOL(pm8921_bms_battery_inserted);
+
void pm8921_bms_invalidate_shutdown_soc(void)
{
int calculate_soc = 0;
@@ -2986,6 +3070,8 @@
GET_VBAT_VSENSE_SIMULTANEOUS,
STOP_OCV,
START_OCV,
+ SET_OCV,
+ BATT_PRESENT,
};
static int test_batt_temp = 5;
@@ -3227,6 +3313,10 @@
(void *)STOP_OCV, &calc_fops);
debugfs_create_file("start_ocv", 0644, chip->dent,
(void *)START_OCV, &calc_fops);
+ debugfs_create_file("set_ocv", 0644, chip->dent,
+ (void *)SET_OCV, &calc_fops);
+ debugfs_create_file("batt_present", 0644, chip->dent,
+ (void *)BATT_PRESENT, &calc_fops);
debugfs_create_file("simultaneous", 0644, chip->dent,
(void *)GET_VBAT_VSENSE_SIMULTANEOUS, &calc_fops);
@@ -3372,6 +3462,11 @@
chip->ocv_dis_high_soc = pdata->ocv_dis_high_soc;
chip->ocv_dis_low_soc = pdata->ocv_dis_low_soc;
+ chip->high_ocv_correction_limit_uv
+ = pdata->high_ocv_correction_limit_uv;
+ chip->low_ocv_correction_limit_uv = pdata->low_ocv_correction_limit_uv;
+ chip->hold_soc_est = pdata->hold_soc_est;
+
chip->alarm_low_mv = pdata->alarm_low_mv;
chip->alarm_high_mv = pdata->alarm_high_mv;
chip->low_voltage_detect = pdata->low_voltage_detect;
@@ -3463,6 +3558,18 @@
return 0;
}
+static int pm8921_bms_suspend(struct device *dev)
+{
+ /*
+ * set the last reported soc to invalid, so that
+ * next time we resume we don't want to restrict
+ * the decrease of soc by only 1%
+ */
+ last_soc = -EINVAL;
+
+ return 0;
+}
+
static int pm8921_bms_resume(struct device *dev)
{
int rc;
@@ -3490,6 +3597,7 @@
static const struct dev_pm_ops pm8921_bms_pm_ops = {
.resume = pm8921_bms_resume,
+ .suspend = pm8921_bms_suspend,
};
static struct platform_driver pm8921_bms_driver = {
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 5136fdf..e9cf973 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -3181,6 +3181,7 @@
static int ichg_threshold_ua = -400000;
module_param(ichg_threshold_ua, int, 0644);
+#define MIN_DELTA_MV_TO_INCREASE_VDD_MAX 13
#define PM8921_CHG_VDDMAX_RES_MV 10
static void adjust_vdd_max_for_fastchg(struct pm8921_chg_chip *chip,
int vbat_batt_terminal_uv)
@@ -3212,6 +3213,14 @@
delta_mv = chip->max_voltage_mv - vbat_batt_terminal_mv;
+ if (delta_mv > 0) /* meaning we want to increase the vddmax */ {
+ if (delta_mv < MIN_DELTA_MV_TO_INCREASE_VDD_MAX) {
+ pr_debug("vterm = %d is not low enough to inc vdd\n",
+ vbat_batt_terminal_mv);
+ return;
+ }
+ }
+
adj_vdd_max_mv = programmed_vdd_max + delta_mv;
pr_debug("vdd_max needs to be changed by %d mv from %d to %d\n",
delta_mv,
@@ -3223,8 +3232,8 @@
return;
}
- adj_vdd_max_mv = DIV_ROUND_UP(adj_vdd_max_mv, PM8921_CHG_VDDMAX_RES_MV)
- * PM8921_CHG_VDDMAX_RES_MV;
+ adj_vdd_max_mv = (adj_vdd_max_mv / PM8921_CHG_VDDMAX_RES_MV)
+ * PM8921_CHG_VDDMAX_RES_MV;
if (adj_vdd_max_mv > (chip->max_voltage_mv + vdd_max_increase_mv))
adj_vdd_max_mv = chip->max_voltage_mv + vdd_max_increase_mv;
@@ -3382,9 +3391,11 @@
else
vbat_intended = chip->max_voltage_mv;
- if (vbat_batt_terminal_uv / 1000 < vbat_intended) {
- pr_debug("terminal_uv:%d < vbat_intended:%d.\n",
+ if (vbat_batt_terminal_uv / 1000
+ < vbat_intended - MIN_DELTA_MV_TO_INCREASE_VDD_MAX) {
+ pr_debug("terminal_uv:%d < vbat_intended:%d-hyst:%d\n",
vbat_batt_terminal_uv,
+ vbat_intended,
vbat_intended);
return CHG_IN_PROGRESS;
}
diff --git a/drivers/power/pm8xxx-ccadc.c b/drivers/power/pm8xxx-ccadc.c
index 7e37daa..5313593 100644
--- a/drivers/power/pm8xxx-ccadc.c
+++ b/drivers/power/pm8xxx-ccadc.c
@@ -81,6 +81,7 @@
int r_sense_uohm;
struct delayed_work calib_ccadc_work;
struct mutex calib_mutex;
+ bool periodic_wakeup;
};
static struct pm8xxx_ccadc_chip *the_chip;
@@ -367,7 +368,7 @@
return 0;
}
-void pm8xxx_calib_ccadc(void)
+static void __pm8xxx_calib_ccadc(int sample_count)
{
u8 data_msb, data_lsb, sec_cntrl;
int result_offset, result_gain;
@@ -379,6 +380,8 @@
return;
}
+ pr_debug("sample_count = %d\n", sample_count);
+
mutex_lock(&the_chip->calib_mutex);
rc = pm8xxx_readb(the_chip->dev->parent,
ADC_ARB_SECP_CNTRL, &sec_cntrl);
@@ -405,7 +408,7 @@
}
result_offset = 0;
- for (i = 0; i < SAMPLE_COUNT; i++) {
+ for (i = 0; i < sample_count; i++) {
/* Short analog inputs to CCADC internally to ground */
rc = pm8xxx_writeb(the_chip->dev->parent, ADC_ARB_SECP_RSV,
CCADC_CALIB_RSV_GND);
@@ -431,7 +434,7 @@
result_offset += result;
}
- result_offset = result_offset / SAMPLE_COUNT;
+ result_offset = result_offset / sample_count;
pr_debug("offset result_offset = 0x%x, voltage = %llduV\n",
@@ -470,7 +473,7 @@
}
result_gain = 0;
- for (i = 0; i < SAMPLE_COUNT; i++) {
+ for (i = 0; i < sample_count; i++) {
rc = pm8xxx_writeb(the_chip->dev->parent,
ADC_ARB_SECP_RSV, CCADC_CALIB_RSV_25MV);
if (rc < 0) {
@@ -494,7 +497,7 @@
result_gain += result;
}
- result_gain = result_gain / SAMPLE_COUNT;
+ result_gain = result_gain / sample_count;
/*
* result_offset includes INTRINSIC OFFSET
@@ -519,6 +522,16 @@
calibration_unlock:
mutex_unlock(&the_chip->calib_mutex);
}
+
+static void pm8xxx_calib_ccadc_quick(void)
+{
+ __pm8xxx_calib_ccadc(2);
+}
+
+void pm8xxx_calib_ccadc(void)
+{
+ __pm8xxx_calib_ccadc(SAMPLE_COUNT);
+}
EXPORT_SYMBOL(pm8xxx_calib_ccadc);
static void calibrate_ccadc_work(struct work_struct *work)
@@ -737,6 +750,7 @@
chip->r_sense_uohm = pdata->r_sense_uohm;
chip->calib_delay_ms = pdata->calib_delay_ms;
chip->batt_temp_channel = pdata->ccadc_cdata.batt_temp_channel;
+ chip->periodic_wakeup = pdata->periodic_wakeup;
mutex_init(&chip->calib_mutex);
calib_ccadc_read_offset_and_gain(chip,
@@ -793,6 +807,12 @@
pr_err("unable to get current time: %d\n", rc);
return 0;
}
+
+ if (the_chip->periodic_wakeup) {
+ pm8xxx_calib_ccadc_quick();
+ return 0;
+ }
+
if (current_time_sec > the_chip->last_calib_time) {
time_since_last_calib = current_time_sec -
the_chip->last_calib_time;
@@ -803,9 +823,11 @@
|| delta_temp > CCADC_CALIB_TEMP_THRESH) {
the_chip->last_calib_time = current_time_sec;
the_chip->last_calib_temp = batt_temp;
- pm8xxx_calib_ccadc();
+ cancel_delayed_work(&the_chip->calib_ccadc_work);
+ schedule_delayed_work(&the_chip->calib_ccadc_work, 0);
}
}
+
return 0;
}
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 08cf71e..210964e 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -71,9 +71,9 @@
#define BMS1_VBAT_AVG_DATA0 0x9E
#define BMS1_VBAT_AVG_DATA1 0x9F
/* Extra bms registers */
-#define BMS1_BMS_DATA_REG_0 0xB0
+#define SOC_STORAGE_REG 0xB0
#define IAVG_STORAGE_REG 0xB1
-#define SOC_STORAGE_REG 0xB2
+#define BMS1_BMS_DATA_REG_2 0xB2
#define BMS1_BMS_DATA_REG_3 0xB3
/* IADC Channel Select */
#define IADC1_BMS_ADC_CH_SEL_CTL 0x48
@@ -83,7 +83,7 @@
#define IAVG_STEP_SIZE_MA 50
#define IAVG_START 600
#define IAVG_INVALID 0xFF
-#define SOC_ZERO 0xFF
+#define SOC_INVALID 0xFF
#define IAVG_SAMPLES 16
@@ -135,6 +135,7 @@
struct sf_lut *pc_sf_lut;
struct sf_lut *rbatt_sf_lut;
int default_rbatt_mohm;
+ int rbatt_capacitive_mohm;
struct delayed_work calculate_soc_delayed_work;
struct work_struct recalc_work;
@@ -184,7 +185,6 @@
unsigned int vadc_v1250;
int ibat_max_ua;
- int prev_iavg_ua;
int prev_uuc_iavg_ma;
int prev_pc_unusable;
int ibat_at_cv_ua;
@@ -194,6 +194,8 @@
int prev_voltage_based_soc;
bool use_voltage_soc;
+ int prev_batt_terminal_uv;
+
int ocv_high_threshold_uv;
int ocv_low_threshold_uv;
unsigned long last_recalc_time;
@@ -486,7 +488,7 @@
static int calib_vadc(struct qpnp_bms_chip *chip)
{
- int rc;
+ int rc, raw_0625, raw_1250;
struct qpnp_vadc_result result;
rc = qpnp_vadc_read(REF_625MV, &result);
@@ -494,16 +496,19 @@
pr_debug("vadc read failed with rc = %d\n", rc);
return rc;
}
- chip->vadc_v0625 = result.physical;
+ raw_0625 = result.adc_code;
rc = qpnp_vadc_read(REF_125V, &result);
if (rc) {
pr_debug("vadc read failed with rc = %d\n", rc);
return rc;
}
- chip->vadc_v1250 = result.physical;
- pr_debug("vadc calib: 0625 = %d, 1250 = %d\n",
- chip->vadc_v0625, chip->vadc_v1250);
+ raw_1250 = result.adc_code;
+ chip->vadc_v0625 = vadc_reading_to_uv(raw_0625);
+ chip->vadc_v1250 = vadc_reading_to_uv(raw_1250);
+ pr_debug("vadc calib: 0625 = %d raw (%d uv), 1250 = %d raw (%d uv)\n",
+ raw_0625, chip->vadc_v0625,
+ raw_1250, chip->vadc_v1250);
return 0;
}
@@ -621,7 +626,8 @@
{
int ibat_ua, vbat_uv, ocv_est_uv;
int rc;
- int rbatt_mohm = chip->default_rbatt_mohm + chip->r_conn_mohm;
+ int rbatt_mohm = chip->default_rbatt_mohm + chip->r_conn_mohm
+ + chip->rbatt_capacitive_mohm;
rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
if (rc) {
@@ -647,6 +653,7 @@
chip->last_cc_uah = INT_MIN;
chip->last_ocv_temp = batt_temp;
chip->last_soc_invalid = true;
+ chip->prev_batt_terminal_uv = 0;
}
#define OCV_RAW_UNINITIALIZED 0xFFFF
@@ -841,38 +848,35 @@
rbatt_mohm += chip->r_conn_mohm;
pr_debug("adding r_conn_mohm = %d rbatt = %d\n",
chip->r_conn_mohm, rbatt_mohm);
+ rbatt_mohm += chip->rbatt_capacitive_mohm;
+ pr_debug("adding rbatt_capacitive_mohm = %d rbatt = %d\n",
+ chip->rbatt_capacitive_mohm, rbatt_mohm);
pr_debug("RBATT = %d\n", rbatt_mohm);
return rbatt_mohm;
}
+#define IAVG_MINIMAL_TIME 2
static void calculate_iavg(struct qpnp_bms_chip *chip, int cc_uah,
int *iavg_ua, int delta_time_s)
{
int delta_cc_uah = 0;
- /* if anything fails report the previous iavg_ua */
- *iavg_ua = chip->prev_iavg_ua;
-
- if (chip->last_cc_uah == INT_MIN) {
+ /*
+ * use the battery current if called too quickly
+ */
+ if (delta_time_s < IAVG_MINIMAL_TIME
+ || chip->last_cc_uah == INT_MIN) {
get_battery_current(chip, iavg_ua);
goto out;
}
- /* use the previous iavg if called within 15 seconds */
- if (delta_time_s < 15) {
- *iavg_ua = chip->prev_iavg_ua;
- goto out;
- }
-
delta_cc_uah = cc_uah - chip->last_cc_uah;
*iavg_ua = div_s64((s64)delta_cc_uah * 3600, delta_time_s);
out:
pr_debug("delta_cc = %d iavg_ua = %d\n", delta_cc_uah, (int)*iavg_ua);
- /* remember the iavg */
- chip->prev_iavg_ua = *iavg_ua;
/* remember cc_uah */
chip->last_cc_uah = cc_uah;
@@ -1225,6 +1229,10 @@
rc = get_simultaneous_batt_v_and_i(chip, &ibat_ua, &vbat_uv);
+ /*
+ * Don't include rbatt and rbatt_capacitative since we expect this to
+ * be used with a fake battery which does not have internal resistances
+ */
ocv_est_uv = vbat_uv + (ibat_ua * chip->r_conn_mohm) / 1000;
pr_debug("forcing ocv to be %d due to bms reset mode\n", ocv_est_uv);
chip->last_ocv_uv = ocv_est_uv;
@@ -1291,11 +1299,13 @@
pr_debug("CC_TO_CV ibat_ua = %d CHG SOC %d\n",
ibat_ua, soc);
}
+
+ chip->prev_batt_terminal_uv = batt_terminal_uv;
return soc;
}
/*
- * battery is in CV phase - begin liner inerpolation of soc based on
+ * battery is in CV phase - begin linear interpolation of soc based on
* battery charge current
*/
@@ -1303,10 +1313,11 @@
* if voltage lessened (possibly because of a system load)
* keep reporting the prev chg soc
*/
- if (batt_terminal_uv <= chip->max_voltage_uv - 10000) {
+ if (batt_terminal_uv <= chip->prev_batt_terminal_uv) {
pr_debug("batt_terminal_uv %d < (max = %d - 10000); CC CHG SOC %d\n",
- batt_terminal_uv,
- chip->max_voltage_uv, chip->prev_chg_soc);
+ batt_terminal_uv, chip->prev_batt_terminal_uv,
+ chip->prev_chg_soc);
+ chip->prev_batt_terminal_uv = batt_terminal_uv;
return chip->prev_chg_soc;
}
@@ -1329,6 +1340,7 @@
}
pr_debug("Reporting CHG SOC %d\n", chip->prev_chg_soc);
+ chip->prev_batt_terminal_uv = batt_terminal_uv;
return chip->prev_chg_soc;
}
@@ -1608,10 +1620,9 @@
pr_debug("SOC before adjustment = %d\n", soc);
new_calculated_soc = adjust_soc(chip, ¶ms, soc, batt_temp);
- /* clamp soc due to BMS HW inaccuracies in pm8941v2.0 */
- if (chip->revision1 == 0 && chip->revision2 == 0)
- new_calculated_soc = clamp_soc_based_on_voltage(chip,
- new_calculated_soc);
+ /* always clamp soc due to BMS hw/sw immaturities */
+ new_calculated_soc = clamp_soc_based_on_voltage(chip,
+ new_calculated_soc);
done_calculating:
if (new_calculated_soc != chip->calculated_soc
@@ -1732,10 +1743,7 @@
rc = qpnp_write_wrapper(chip, &temp,
chip->base + IAVG_STORAGE_REG, 1);
- if (soc == 0)
- temp = SOC_ZERO;
- else
- temp = soc;
+ temp = soc;
/* don't store soc if temperature is below 5degC */
if (batt_temp > IGNORE_SOC_TEMP_DECIDEG)
@@ -2067,12 +2075,10 @@
} else {
chip->shutdown_soc = temp;
- if (chip->shutdown_soc == 0) {
+ if (chip->shutdown_soc == SOC_INVALID) {
pr_debug("No shutdown soc available\n");
chip->shutdown_soc_invalid = true;
chip->shutdown_iavg_ma = 0;
- } else if (chip->shutdown_soc == SOC_ZERO) {
- chip->shutdown_soc = 0;
}
}
}
@@ -2143,6 +2149,7 @@
chip->pc_sf_lut = batt_data->pc_sf_lut;
chip->rbatt_sf_lut = batt_data->rbatt_sf_lut;
chip->default_rbatt_mohm = batt_data->default_rbatt_mohm;
+ chip->rbatt_capacitive_mohm = batt_data->rbatt_capacitive_mohm;
if (chip->pc_temp_ocv_lut == NULL) {
pr_err("temp ocv lut table is NULL\n");
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 35d8df9..f4efa756 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -24,6 +24,7 @@
#include <linux/qpnp/qpnp-adc.h>
#include <linux/power_supply.h>
#include <linux/bitops.h>
+#include <linux/ratelimit.h>
/* Interrupt offsets */
#define INT_RT_STS(base) (base + 0x10)
@@ -949,6 +950,7 @@
get_prop_capacity(struct qpnp_chg_chip *chip)
{
union power_supply_propval ret = {0,};
+ bool usb_online, dc_online;
if (chip->use_default_batt_values || !get_prop_batt_present(chip))
return DEFAULT_CAPACITY;
@@ -956,6 +958,14 @@
if (chip->bms_psy) {
chip->bms_psy->get_property(chip->bms_psy,
POWER_SUPPLY_PROP_CAPACITY, &ret);
+ if (ret.intval == 0) {
+ usb_online = chip->usb_psy->get_property(chip->usb_psy,
+ POWER_SUPPLY_PROP_ONLINE, &ret);
+ dc_online = chip->dc_psy.get_property(&chip->dc_psy,
+ POWER_SUPPLY_PROP_ONLINE, &ret);
+ if (!usb_online && !dc_online)
+ pr_warn_ratelimited("Battery 0, CHG absent\n");
+ }
return ret.intval;
} else {
pr_debug("No BMS supply registered return 50\n");
@@ -1025,13 +1035,15 @@
/* Only honour requests while USB is present */
if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
+ chip->usb_psy->get_property(chip->usb_psy,
+ POWER_SUPPLY_PROP_CURRENT_MAX, &ret);
if (ret.intval <= 2 && !chip->use_default_batt_values &&
get_prop_batt_present(chip)) {
- qpnp_chg_usb_suspend_enable(chip, 1);
qpnp_chg_iusbmax_set(chip, QPNP_CHG_I_MAX_MIN_100);
+ qpnp_chg_usb_suspend_enable(chip, 1);
} else {
- qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
qpnp_chg_usb_suspend_enable(chip, 0);
+ qpnp_chg_iusbmax_set(chip, ret.intval / 1000);
}
}
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 9b2f554..4251968 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -39,6 +39,13 @@
#include <linux/notifier.h>
#include <linux/mutex.h>
#include <linux/delay.h>
+#include <linux/swap.h>
+
+#ifdef CONFIG_HIGHMEM
+#define _ZONE ZONE_HIGHMEM
+#else
+#define _ZONE ZONE_NORMAL
+#endif
static uint32_t lowmem_debug_level = 1;
static int lowmem_adj[6] = {
@@ -55,6 +62,7 @@
16 * 1024, /* 64MB */
};
static int lowmem_minfree_size = 4;
+static int lmk_fast_run = 1;
static unsigned long lowmem_deathpending_timeout;
@@ -82,6 +90,141 @@
static DEFINE_MUTEX(scan_mutex);
+int can_use_cma_pages(gfp_t gfp_mask)
+{
+ int can_use = 0;
+ int mtype = allocflags_to_migratetype(gfp_mask);
+ int i = 0;
+ int *mtype_fallbacks = get_migratetype_fallbacks(mtype);
+
+ if (is_migrate_cma(mtype)) {
+ can_use = 1;
+ } else {
+ for (i = 0;; i++) {
+ int fallbacktype = mtype_fallbacks[i];
+
+ if (is_migrate_cma(fallbacktype)) {
+ can_use = 1;
+ break;
+ }
+
+ if (fallbacktype == MIGRATE_RESERVE)
+ break;
+ }
+ }
+ return can_use;
+}
+
+void tune_lmk_zone_param(struct zonelist *zonelist, int classzone_idx,
+ int *other_free, int *other_file,
+ int use_cma_pages)
+{
+ struct zone *zone;
+ struct zoneref *zoneref;
+ int zone_idx;
+
+ for_each_zone_zonelist(zone, zoneref, zonelist, MAX_NR_ZONES) {
+ zone_idx = zonelist_zone_idx(zoneref);
+ if (zone_idx == ZONE_MOVABLE) {
+ if (!use_cma_pages)
+ *other_free -=
+ zone_page_state(zone, NR_FREE_CMA_PAGES);
+ continue;
+ }
+
+ if (zone_idx > classzone_idx) {
+ if (other_free != NULL)
+ *other_free -= zone_page_state(zone,
+ NR_FREE_PAGES);
+ if (other_file != NULL)
+ *other_file -= zone_page_state(zone,
+ NR_FILE_PAGES)
+ - zone_page_state(zone, NR_SHMEM);
+ } else if (zone_idx < classzone_idx) {
+ if (zone_watermark_ok(zone, 0, 0, classzone_idx, 0)) {
+ if (!use_cma_pages) {
+ *other_free -= min(
+ zone->lowmem_reserve[classzone_idx] +
+ zone_page_state(
+ zone, NR_FREE_CMA_PAGES),
+ zone_page_state(
+ zone, NR_FREE_PAGES));
+ } else {
+ *other_free -=
+ zone->lowmem_reserve[classzone_idx];
+ }
+ } else {
+ *other_free -=
+ zone_page_state(zone, NR_FREE_PAGES);
+ }
+ }
+ }
+}
+
+void tune_lmk_param(int *other_free, int *other_file, struct shrink_control *sc)
+{
+ gfp_t gfp_mask;
+ struct zone *preferred_zone;
+ struct zonelist *zonelist;
+ enum zone_type high_zoneidx, classzone_idx;
+ unsigned long balance_gap;
+ int use_cma_pages;
+
+ gfp_mask = sc->gfp_mask;
+ zonelist = node_zonelist(0, gfp_mask);
+ high_zoneidx = gfp_zone(gfp_mask);
+ first_zones_zonelist(zonelist, high_zoneidx, NULL, &preferred_zone);
+ classzone_idx = zone_idx(preferred_zone);
+ use_cma_pages = can_use_cma_pages(gfp_mask);
+
+ balance_gap = min(low_wmark_pages(preferred_zone),
+ (preferred_zone->present_pages +
+ KSWAPD_ZONE_BALANCE_GAP_RATIO-1) /
+ KSWAPD_ZONE_BALANCE_GAP_RATIO);
+
+ if (likely(current_is_kswapd() && zone_watermark_ok(preferred_zone, 0,
+ high_wmark_pages(preferred_zone) + SWAP_CLUSTER_MAX +
+ balance_gap, 0, 0))) {
+ if (lmk_fast_run)
+ tune_lmk_zone_param(zonelist, classzone_idx, other_free,
+ other_file, use_cma_pages);
+ else
+ tune_lmk_zone_param(zonelist, classzone_idx, other_free,
+ NULL, use_cma_pages);
+
+ if (zone_watermark_ok(preferred_zone, 0, 0, _ZONE, 0)) {
+ if (!use_cma_pages) {
+ *other_free -= min(
+ preferred_zone->lowmem_reserve[_ZONE]
+ + zone_page_state(
+ preferred_zone, NR_FREE_CMA_PAGES),
+ zone_page_state(
+ preferred_zone, NR_FREE_PAGES));
+ } else {
+ *other_free -=
+ preferred_zone->lowmem_reserve[_ZONE];
+ }
+ } else {
+ *other_free -= zone_page_state(preferred_zone,
+ NR_FREE_PAGES);
+ }
+
+ lowmem_print(4, "lowmem_shrink of kswapd tunning for highmem "
+ "ofree %d, %d\n", *other_free, *other_file);
+ } else {
+ tune_lmk_zone_param(zonelist, classzone_idx, other_free,
+ other_file, use_cma_pages);
+
+ if (!use_cma_pages) {
+ *other_free -=
+ zone_page_state(preferred_zone, NR_FREE_CMA_PAGES);
+ }
+
+ lowmem_print(4, "lowmem_shrink tunning for others ofree %d, "
+ "%d\n", *other_free, *other_file);
+ }
+}
+
static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)
{
struct task_struct *tsk;
@@ -106,6 +249,8 @@
other_file = global_page_state(NR_FILE_PAGES) -
global_page_state(NR_SHMEM);
+ tune_lmk_param(&other_free, &other_file, sc);
+
if (lowmem_adj_size < array_size)
array_size = lowmem_adj_size;
if (lowmem_minfree_size < array_size)
@@ -311,6 +456,7 @@
module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size,
S_IRUGO | S_IWUSR);
module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR);
+module_param_named(lmk_fast_run, lmk_fast_run, int, S_IRUGO | S_IWUSR);
module_init(lowmem_init);
module_exit(lowmem_exit);
diff --git a/drivers/staging/android/switch/switch_class.c b/drivers/staging/android/switch/switch_class.c
index 7468044..3852c2c 100644
--- a/drivers/staging/android/switch/switch_class.c
+++ b/drivers/staging/android/switch/switch_class.c
@@ -151,8 +151,8 @@
{
device_remove_file(sdev->dev, &dev_attr_name);
device_remove_file(sdev->dev, &dev_attr_state);
- device_destroy(switch_class, MKDEV(0, sdev->index));
dev_set_drvdata(sdev->dev, NULL);
+ device_destroy(switch_class, MKDEV(0, sdev->index));
}
EXPORT_SYMBOL_GPL(switch_dev_unregister);
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 7d3664a..f7e5eee 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -74,6 +74,9 @@
#define TSENS_EEPROM_8X26_2(n) ((n) + 0x444)
#define TSENS_8X26_MAIN_CALIB_ADDR_RANGE 4
+#define TSENS_EEPROM_8X10_1(n) ((n) + 0x1a4)
+#define TSENS_EEPROM_8X10_1_OFFSET 8
+
/* TSENS calibration Mask data */
#define TSENS_BASE1_MASK 0xff
#define TSENS0_POINT1_MASK 0x3f00
@@ -191,6 +194,19 @@
#define TSENS5_8X26_POINT2_SHIFT 26
#define TSENS6_8X26_POINT2_SHIFT 17
+#define TSENS_8X10_CAL_SEL_SHIFT 28
+#define TSENS_8X10_BASE1_SHIFT 8
+#define TSENS0_8X10_POINT1_SHIFT 16
+#define TSENS0_8X10_POINT2_SHIFT 22
+#define TSENS1_8X10_POINT2_SHIFT 6
+#define TSENS_8X10_BASE0_MASK 0xf
+#define TSENS_8X10_BASE1_MASK 0xf0
+#define TSENS0_8X10_POINT1_MASK 0x3f0000
+#define TSENS0_8X10_POINT2_MASK 0xfc00000
+#define TSENS_8X10_TSENS_CAL_SEL 0x70000000
+#define TSENS1_8X10_POINT1_MASK 0x3f
+#define TSENS1_8X10_POINT2_MASK 0xfc0
+
#define TSENS_BIT_APPEND 0x3
#define TSENS_CAL_DEGC_POINT1 30
#define TSENS_CAL_DEGC_POINT2 120
@@ -599,6 +615,98 @@
TSENS_UPPER_LOWER_INTERRUPT_CTRL(tmdev->tsens_addr));
}
+static int tsens_calib_8x10_sensors(void)
+{
+ int i, tsens_base0_data = 0, tsens0_point1 = 0, tsens1_point1 = 0;
+ int tsens0_point2 = 0, tsens1_point2 = 0;
+ int tsens_base1_data = 0, tsens_calibration_mode = 0;
+ uint32_t calib_data[2];
+ uint32_t calib_tsens_point1_data[2], calib_tsens_point2_data[2];
+
+ if (tmdev->calibration_less_mode)
+ goto calibration_less_mode;
+
+ calib_data[0] = readl_relaxed(
+ TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr));
+ calib_data[1] = readl_relaxed(
+ (TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr) +
+ TSENS_EEPROM_8X10_1_OFFSET));
+
+ tsens_calibration_mode = (calib_data[0] & TSENS_8X10_TSENS_CAL_SEL)
+ >> TSENS_8X10_CAL_SEL_SHIFT;
+
+ if ((tsens_calibration_mode == TSENS_TWO_POINT_CALIB) ||
+ (tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2)) {
+ tsens_base0_data = (calib_data[0] & TSENS_8X10_BASE0_MASK);
+ tsens0_point1 = (calib_data[0] & TSENS0_8X10_POINT1_MASK) >>
+ TSENS0_8X10_POINT1_SHIFT;
+ tsens1_point1 = calib_data[1] & TSENS1_8X10_POINT1_MASK;
+ } else
+ goto calibration_less_mode;
+
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
+ tsens_base1_data = (calib_data[0] & TSENS_8X10_BASE1_MASK) >>
+ TSENS_8X10_BASE1_SHIFT;
+ tsens0_point2 = (calib_data[0] & TSENS0_8X10_POINT2_MASK) >>
+ TSENS0_8X10_POINT2_SHIFT;
+ tsens1_point2 = (calib_data[1] & TSENS1_8X10_POINT2_MASK) >>
+ TSENS1_8X10_POINT2_SHIFT;
+ }
+
+ if (tsens_calibration_mode == 0) {
+calibration_less_mode:
+ pr_debug("TSENS is calibrationless mode\n");
+ for (i = 0; i < tmdev->tsens_num_sensor; i++)
+ calib_tsens_point2_data[i] = 780;
+ calib_tsens_point1_data[0] = 595;
+ calib_tsens_point1_data[1] = 629;
+ goto compute_intercept_slope;
+ }
+
+ if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) ||
+ (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
+ calib_tsens_point1_data[0] =
+ ((((tsens_base0_data) + tsens0_point1) << 2) |
+ TSENS_BIT_APPEND);
+ calib_tsens_point1_data[1] =
+ ((((tsens_base0_data) + tsens1_point1) << 2) |
+ TSENS_BIT_APPEND);
+ }
+
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
+ pr_debug("two point calibration calculation\n");
+ calib_tsens_point2_data[0] =
+ (((tsens_base1_data + tsens0_point2) << 2) |
+ TSENS_BIT_APPEND);
+ calib_tsens_point2_data[1] =
+ (((tsens_base1_data + tsens1_point2) << 2) |
+ TSENS_BIT_APPEND);
+ }
+
+compute_intercept_slope:
+ for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+ int32_t num = 0, den = 0;
+ tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
+ tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
+ /* slope (m) = adc_code2 - adc_code1 (y2 - y1)/
+ temp_120_degc - temp_30_degc (x2 - x1) */
+ num = tmdev->sensor[i].calib_data_point2 -
+ tmdev->sensor[i].calib_data_point1;
+ num *= tmdev->tsens_factor;
+ den = TSENS_CAL_DEGC_POINT2 - TSENS_CAL_DEGC_POINT1;
+ tmdev->sensor[i].slope_mul_tsens_factor = num/den;
+ }
+ tmdev->sensor[i].offset = (tmdev->sensor[i].calib_data_point1 *
+ tmdev->tsens_factor) - (TSENS_CAL_DEGC_POINT1 *
+ tmdev->sensor[i].slope_mul_tsens_factor);
+ INIT_WORK(&tmdev->sensor[i].work, notify_uspace_tsens_fn);
+ tmdev->prev_reading_avail = false;
+ }
+
+ return 0;
+}
+
static int tsens_calib_8x26_sensors(void)
{
int i, tsens_base0_data = 0, tsens0_point1 = 0, tsens1_point1 = 0;
@@ -627,7 +735,6 @@
if ((tsens_calibration_mode == TSENS_TWO_POINT_CALIB) ||
(tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2)) {
- pr_debug("backup one point calibrationless mode\n");
tsens_base0_data = (calib_data[0] & TSENS_8X26_BASE0_MASK)
>> TSENS_8X26_BASE0_SHIFT;
tsens0_point1 = (calib_data[0] & TSENS0_8X26_POINT1_MASK) >>
@@ -647,7 +754,6 @@
goto calibration_less_mode;
if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
- pr_debug("backup two point calibrationless mode\n");
tsens_base1_data = (calib_data[3] & TSENS_8X26_BASE1_MASK);
tsens0_point2 = (calib_data[3] & TSENS0_8X26_POINT2_MASK) >>
TSENS0_8X26_POINT2_SHIFT;
@@ -670,10 +776,10 @@
pr_debug("TSENS is calibrationless mode\n");
for (i = 0; i < tmdev->tsens_num_sensor; i++)
calib_tsens_point2_data[i] = 780;
- calib_tsens_point1_data[0] = 502;
- calib_tsens_point1_data[1] = 509;
- calib_tsens_point1_data[2] = 503;
- calib_tsens_point1_data[3] = 509;
+ calib_tsens_point1_data[0] = 595;
+ calib_tsens_point1_data[1] = 625;
+ calib_tsens_point1_data[2] = 553;
+ calib_tsens_point1_data[3] = 578;
calib_tsens_point1_data[4] = 505;
calib_tsens_point1_data[5] = 509;
calib_tsens_point1_data[6] = 507;
@@ -682,7 +788,6 @@
if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) ||
(tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
- pr_debug("one and two point calibration calculation\n");
calib_tsens_point1_data[0] =
((((tsens_base0_data) + tsens0_point1) << 2) |
TSENS_BIT_APPEND);
@@ -800,7 +905,6 @@
TSENS_TWO_POINT_CALIB) ||
(tsens_calibration_mode ==
TSENS_ONE_POINT_CALIB_OPTION_2)) {
- pr_debug("backup one point calibrationless mode\n");
tsens_base1_data = (calib_data_backup[0] &
TSENS_BASE1_MASK);
tsens0_point1 = (calib_data_backup[0] &
@@ -833,7 +937,6 @@
goto calibration_less_mode;
if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
- pr_debug("backup two point calibrationless mode\n");
tsens_base2_data = (calib_data_backup[2] &
TSENS_BASE2_BACKUP_MASK) >>
TSENS_POINT2_BASE_BACKUP_SHIFT;
@@ -879,7 +982,6 @@
(tsens_calibration_mode ==
TSENS_ONE_POINT_CALIB_OPTION_2) ||
(tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
- pr_debug("TSENS is one point calibrationless mode\n");
tsens_base1_data = (calib_data[0] & TSENS_BASE1_MASK);
tsens0_point1 = (calib_data[0] & TSENS0_POINT1_MASK) >>
TSENS0_POINT1_SHIFT;
@@ -905,7 +1007,6 @@
goto calibration_less_mode;
if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
- pr_debug("TSENS is two point calibrationless mode\n");
tsens_base2_data = (calib_data[2] & TSENS_BASE2_MASK) >>
TSENS_POINT2_BASE_SHIFT;
tsens0_point2 = (calib_data[2] & TSENS0_POINT2_MASK) >>
@@ -951,7 +1052,6 @@
}
if (tsens_calibration_mode == TSENS_ONE_POINT_CALIB) {
- pr_debug("old one point calibration calculation\n");
calib_tsens_point1_data[0] =
(((tsens_base1_data) << 2) | TSENS_BIT_APPEND)
+ tsens0_point1;
@@ -989,7 +1089,6 @@
if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) ||
(tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
- pr_debug("one and two point calibration calculation\n");
calib_tsens_point1_data[0] =
((((tsens_base1_data) + tsens0_point1) << 2) |
TSENS_BIT_APPEND);
@@ -1097,6 +1196,8 @@
rc = tsens_calib_8974_sensors();
else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8X26)
rc = tsens_calib_8x26_sensors();
+ else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8X10)
+ rc = tsens_calib_8x10_sensors();
else
rc = -ENODEV;
@@ -1163,7 +1264,7 @@
"qcom,calibration-less-mode");
tmdev->calib_mode = calib_type;
tmdev->tsens_local_init = of_property_read_bool(of_node,
- "qcom,tsens_local_init");
+ "qcom,tsens-local-init");
tmdev->tsens_irq = platform_get_irq(pdev, 0);
if (tmdev->tsens_irq < 0) {
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index c02db14..e7d2e0f 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -35,7 +35,7 @@
#include <linux/platform_device.h>
/* QPNP VADC TM register definition */
-#define QPNP_REVISION3 0x3
+#define QPNP_REVISION3 0x2
#define QPNP_REVISION_EIGHT_CHANNEL_SUPPORT 2
#define QPNP_STATUS1 0x8
#define QPNP_STATUS1_OP_MODE 4
@@ -544,7 +544,7 @@
i++;
}
- if ((i == adc_tm->max_channels_available) && (!chan_found)) {
+ if (!chan_found) {
pr_err("Channel not found\n");
return -EINVAL;
}
@@ -1292,7 +1292,8 @@
{
struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
uint32_t channel, dt_index = 0, scale_type = 0;
- int rc = 0;
+ int rc = 0, i = 0;
+ bool chan_found = false;
if (!adc_tm || !adc_tm->adc_tm_initialized)
return -ENODEV;
@@ -1305,11 +1306,17 @@
mutex_lock(&adc_tm->adc->adc_lock);
channel = param->channel;
- while ((adc_tm->adc->adc_channels[dt_index].channel_num
- != channel) && (dt_index < adc_tm->max_channels_available))
- dt_index++;
+ while (i < adc_tm->max_channels_available) {
+ if (adc_tm->adc->adc_channels[i].channel_num ==
+ channel) {
+ dt_index = i;
+ chan_found = true;
+ i++;
+ } else
+ i++;
+ }
- if (dt_index >= adc_tm->max_channels_available) {
+ if (!chan_found) {
pr_err("not a valid ADC_TM channel\n");
rc = -EINVAL;
goto fail_unlock;
@@ -1330,11 +1337,11 @@
channel, scale_type, dt_index);
adc_tm->adc->amux_prop->amux_channel = channel;
adc_tm->adc->amux_prop->decimation =
- adc_tm->adc->adc_channels[channel].adc_decimation;
+ adc_tm->adc->adc_channels[dt_index].adc_decimation;
adc_tm->adc->amux_prop->hw_settle_time =
- adc_tm->adc->adc_channels[channel].hw_settle_time;
+ adc_tm->adc->adc_channels[dt_index].hw_settle_time;
adc_tm->adc->amux_prop->fast_avg_setup =
- adc_tm->adc->adc_channels[channel].fast_avg_setup;
+ adc_tm->adc->adc_channels[dt_index].fast_avg_setup;
adc_tm->adc->amux_prop->mode_sel =
ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
adc_tm->adc->amux_prop->chan_prop->meas_interval1 =
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index 8069b35..7aa14de 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -982,10 +982,6 @@
}
}
}
-#ifndef CONFIG_PM_RUNTIME
- msm_hsl_init_clock(port);
-#endif
- pm_runtime_get_sync(port->dev);
/*
* Set RFR Level as 3/4 of UARTDM FIFO Size
@@ -1038,10 +1034,6 @@
free_irq(port->irq, port);
-#ifndef CONFIG_PM_RUNTIME
- msm_hsl_deinit_clock(port);
-#endif
- pm_runtime_put_sync(port->dev);
if (!(is_console(port)) || (!port->cons) ||
(port->cons && (!(port->cons->flags & CON_ENABLED)))) {
/* Free UART GPIOs */
@@ -1714,6 +1706,30 @@
port->uartclk = 7372800;
msm_hsl_port = UART_TO_MSM(port);
+ msm_hsl_port->clk = clk_get(&pdev->dev, "core_clk");
+ if (unlikely(IS_ERR(msm_hsl_port->clk))) {
+ ret = PTR_ERR(msm_hsl_port->clk);
+ if (ret != -EPROBE_DEFER)
+ pr_err("Error getting clk\n");
+ return ret;
+ }
+
+ /* Interface clock is not required by all UART configurations.
+ * GSBI UART and BLSP UART needs interface clock but Legacy UART
+ * do not require interface clock. Hence, do not fail probe with
+ * iface clk_get failure.
+ */
+ msm_hsl_port->pclk = clk_get(&pdev->dev, "iface_clk");
+ if (unlikely(IS_ERR(msm_hsl_port->pclk))) {
+ ret = PTR_ERR(msm_hsl_port->pclk);
+ if (ret == -EPROBE_DEFER) {
+ clk_put(msm_hsl_port->clk);
+ return ret;
+ } else {
+ msm_hsl_port->pclk = NULL;
+ }
+ }
+
/* Identify UART functional mode as 2-wire or 4-wire. */
if (pdata && pdata->config_gpio == 4)
msm_hsl_port->func_mode = UART_FOUR_WIRE;
@@ -1751,22 +1767,12 @@
"gsbi_resource");
if (!gsbi_resource)
gsbi_resource = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- msm_hsl_port->clk = clk_get(&pdev->dev, "core_clk");
- msm_hsl_port->pclk = clk_get(&pdev->dev, "iface_clk");
if (gsbi_resource)
msm_hsl_port->uart_type = GSBI_HSUART;
else
msm_hsl_port->uart_type = LEGACY_HSUART;
- if (unlikely(IS_ERR(msm_hsl_port->clk))) {
- pr_err("Error getting clk\n");
- return PTR_ERR(msm_hsl_port->clk);
- }
- if (unlikely(IS_ERR(msm_hsl_port->pclk))) {
- pr_err("Error getting pclk\n");
- return PTR_ERR(msm_hsl_port->pclk);
- }
uart_resource = platform_get_resource_byname(pdev,
IORESOURCE_MEM,
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index f9a26cf..6619e96 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -461,6 +461,7 @@
#define DWC3_ALIGN_MASK (16 - 1)
+static u64 dwc3_dma_mask = DMA_BIT_MASK(64);
static int __devinit dwc3_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
@@ -483,6 +484,11 @@
dwc = PTR_ALIGN(mem, DWC3_ALIGN_MASK + 1);
dwc->mem = mem;
+ if (!dev->dma_mask)
+ dev->dma_mask = &dwc3_dma_mask;
+ if (!dev->coherent_dma_mask)
+ dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
dev_err(dev, "missing IRQ\n");
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 9fad90c..435ef3b 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -26,6 +26,7 @@
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/of.h>
+#include <linux/of_platform.h>
#include <linux/list.h>
#include <linux/debugfs.h>
#include <linux/uaccess.h>
@@ -63,6 +64,11 @@
module_param(override_phy_init, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(override_phy_init, "Override HSPHY Init Seq");
+/* Enable Proprietary charger detection */
+static bool prop_chg_detect;
+module_param(prop_chg_detect, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(prop_chg_detect, "Enable Proprietary charger detection");
+
/**
* USB DBM Hardware registers.
*
@@ -152,7 +158,6 @@
};
struct dwc3_msm {
- struct platform_device *dwc3;
struct device *dev;
void __iomem *base;
u32 resource_size;
@@ -220,7 +225,6 @@
#define USB_SSPHY_1P8_HPM_LOAD 23000 /* uA */
static struct dwc3_msm *context;
-static u64 dwc3_msm_dma_mask = DMA_BIT_MASK(64);
static struct usb_ext_notification *usb_ext;
@@ -1391,12 +1395,12 @@
static bool dwc3_chg_det_check_linestate(struct dwc3_msm *mdwc)
{
u32 chg_det;
- bool ret = false;
+
+ if (!prop_chg_detect)
+ return false;
chg_det = dwc3_msm_read_reg(mdwc->base, CHARGING_DET_OUTPUT_REG);
- ret = chg_det & (3 << 8);
-
- return ret;
+ return chg_det & (3 << 8);
}
static bool dwc3_chg_det_check_output(struct dwc3_msm *mdwc)
@@ -2214,10 +2218,10 @@
static int __devinit dwc3_msm_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
- struct platform_device *dwc3;
struct dwc3_msm *msm;
struct resource *res;
void __iomem *tcsr;
+ unsigned long flags;
int ret = 0;
int len = 0;
u32 tmp[3];
@@ -2430,6 +2434,11 @@
dev_err(&pdev->dev, "irqreq IDINT failed\n");
goto disable_hs_ldo;
}
+ local_irq_save(flags);
+ /* Update initial ID state */
+ msm->id_state = msm->ext_xceiv.id =
+ !!irq_read_line(msm->pmic_id_irq);
+ local_irq_restore(flags);
enable_irq_wake(msm->pmic_id_irq);
}
}
@@ -2476,19 +2485,7 @@
goto disable_hs_ldo;
}
- dwc3 = platform_device_alloc("dwc3", -1);
- if (!dwc3) {
- dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
- ret = -ENODEV;
- goto disable_hs_ldo;
- }
-
- dwc3->dev.parent = &pdev->dev;
- dwc3->dev.coherent_dma_mask = DMA_BIT_MASK(32);
- dwc3->dev.dma_mask = &dwc3_msm_dma_mask;
- dwc3->dev.dma_parms = pdev->dev.dma_parms;
msm->resource_size = resource_size(res);
- msm->dwc3 = dwc3;
if (of_property_read_u32(node, "qcom,dwc-hsphy-init",
&msm->hsphy_init_seq))
@@ -2514,7 +2511,7 @@
"max: %d, dbm_num_eps: %d\n",
DBM_MAX_EPS, msm->dbm_num_eps);
ret = -ENODEV;
- goto put_pdev;
+ goto disable_hs_ldo;
}
msm->usb_psy.name = "usb";
@@ -2534,20 +2531,16 @@
dev_err(&pdev->dev,
"%s:power_supply_register usb failed\n",
__func__);
- goto put_pdev;
+ goto disable_hs_ldo;
}
- ret = platform_device_add_resources(dwc3, pdev->resource,
- pdev->num_resources);
- if (ret) {
- dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n");
- goto put_psupply;
- }
-
- ret = platform_device_add(dwc3);
- if (ret) {
- dev_err(&pdev->dev, "failed to register dwc3 device\n");
- goto put_psupply;
+ if (node) {
+ ret = of_platform_populate(node, NULL, NULL, &pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "failed to add create dwc3 core\n");
+ goto put_psupply;
+ }
}
msm->bus_scale_table = msm_bus_cl_get_pdata(pdev);
@@ -2592,11 +2585,8 @@
put_xcvr:
usb_put_transceiver(msm->otg_xceiv);
- platform_device_del(dwc3);
put_psupply:
power_supply_unregister(&msm->usb_psy);
-put_pdev:
- platform_device_put(dwc3);
disable_hs_ldo:
dwc3_hsusb_ldo_enable(0);
free_hs_ldo_init:
@@ -2647,7 +2637,6 @@
}
pm_runtime_disable(msm->dev);
- platform_device_unregister(msm->dwc3);
wake_lock_destroy(&msm->wlock);
dwc3_hsusb_ldo_enable(0);
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index ca1f817..1d67cee 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -216,6 +216,8 @@
ext_xceiv->ext_block_reset)
ext_xceiv->ext_block_reset(true);
+ dwc3_otg_set_peripheral_regs(dotg);
+
/* re-init core and OTG registers as block reset clears these */
dwc3_post_host_reset_core_init(dwc);
if (ext_xceiv && !ext_xceiv->otg_capability)
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index a1d7a87..66854b2 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -756,6 +756,7 @@
dwc3_ep0_stall_and_restart(dwc);
}
+bool zlp_required;
static void dwc3_ep0_complete_data(struct dwc3 *dwc,
const struct dwc3_event_depevt *event)
{
@@ -775,12 +776,18 @@
r = next_request(&ep0->request_list);
ur = &r->request;
+ if ((epnum & 1) && ur->zero &&
+ (ur->length % ep0->endpoint.maxpacket == 0)) {
+ zlp_required = true;
+ ur->zero = false;
+ }
trb = dwc->ep0_trb;
status = DWC3_TRB_SIZE_TRBSTS(trb->size);
if (status == DWC3_TRBSTS_SETUP_PENDING) {
dev_dbg(dwc->dev, "Setup Pending received\n");
+ zlp_required = false;
if (r)
dwc3_gadget_giveback(ep0, r, -ECONNRESET);
@@ -788,6 +795,9 @@
return;
}
+ if (zlp_required)
+ return;
+
length = trb->size & DWC3_TRB_SIZE_MASK;
if (dwc->ep0_bounced) {
@@ -930,6 +940,10 @@
return;
}
+ if (dep->number &&
+ !(req->request.length % dwc->gadget.ep0->maxpacket))
+ req->request.zero = true;
+
ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma,
req->request.length, DWC3_TRBCTL_CONTROL_DATA);
}
@@ -993,7 +1007,11 @@
static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
const struct dwc3_event_depevt *event)
{
+ u8 epnum;
+ int ret;
+
dwc->setup_packet_pending = true;
+ epnum = event->endpoint_number;
switch (event->status) {
case DEPEVT_STATUS_CONTROL_DATA:
@@ -1017,6 +1035,15 @@
return;
}
+ if (zlp_required) {
+ zlp_required = false;
+ ret = dwc3_ep0_start_trans(dwc, epnum,
+ dwc->ctrl_req_addr, 0,
+ DWC3_TRBCTL_CONTROL_DATA);
+ dbg_event(epnum, "ZLP", ret);
+ WARN_ON(ret < 0);
+ }
+
break;
case DEPEVT_STATUS_CONTROL_STATUS:
@@ -1025,6 +1052,7 @@
dev_vdbg(dwc->dev, "Control Status\n");
+ zlp_required = false;
dwc->ep0state = EP0_STATUS_PHASE;
if (dwc->delayed_status &&
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 4b9dfbf..2dccca8 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -387,7 +387,7 @@
unsigned port_num;
enum transport_type cxport = rmnet_ports[dev->port_num].ctrl_xport;
enum transport_type dxport = rmnet_ports[dev->port_num].data_xport;
- u8 src_connection_idx, dst_connection_idx;
+ int src_connection_idx = 0, dst_connection_idx = 0;
struct usb_gadget *gadget = dev->cdev->gadget;
pr_debug("%s: ctrl xport: %s data xport: %s dev: %p portno: %d\n",
@@ -439,7 +439,6 @@
port_num = rmnet_ports[dev->port_num].data_xport_num;
switch (dxport) {
- case USB_GADGET_XPORT_BAM:
case USB_GADGET_XPORT_BAM2BAM:
src_connection_idx = usb_bam_get_connection_idx(gadget->name,
A2_P_BAM, USB_TO_PEER_PERIPHERAL, port_num);
@@ -451,6 +450,7 @@
gsmd_ctrl_disconnect(&dev->port, port_num);
return ret;
}
+ case USB_GADGET_XPORT_BAM:
ret = gbam_connect(&dev->port, port_num,
dxport, src_connection_idx, dst_connection_idx);
if (ret) {
diff --git a/drivers/usb/gadget/f_uac1.c b/drivers/usb/gadget/f_uac1.c
index 8c74381..e8c9667 100644
--- a/drivers/usb/gadget/f_uac1.c
+++ b/drivers/usb/gadget/f_uac1.c
@@ -463,6 +463,8 @@
struct list_head capture_queue;
struct usb_request *capture_req;
+ u8 alt_intf[F_AUDIO_NUM_INTERFACES];
+
/* Control Set command */
struct list_head fu_cs;
struct list_head ep_cs;
@@ -881,6 +883,18 @@
return value;
}
+static int f_audio_get_alt(struct usb_function *f, unsigned intf)
+{
+ struct f_audio *audio = func_to_audio(f);
+
+ if (intf == ac_header_desc.baInterfaceNr[0])
+ return audio->alt_intf[0];
+ if (intf == ac_header_desc.baInterfaceNr[1])
+ return audio->alt_intf[1];
+
+ return 0;
+}
+
static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
{
struct f_audio *audio = func_to_audio(f);
@@ -938,6 +952,7 @@
}
spin_unlock_irqrestore(&audio->capture_lock, flags);
}
+ audio->alt_intf[0] = alt;
} else if (intf == ac_header_desc.baInterfaceNr[1]) {
if (alt == 1) {
err = usb_ep_enable(out_ep);
@@ -986,10 +1001,12 @@
list_add_tail(&playback_copy_buf->list,
&audio->play_queue);
schedule_work(&audio->playback_work);
+ audio->playback_copy_buf = NULL;
} else {
pr_err("playback_buf is empty. Stop.");
}
}
+ audio->alt_intf[1] = alt;
} else {
pr_err("Interface %d. Do nothing. Return %d\n", intf, err);
}
@@ -1066,6 +1083,7 @@
microphone_as_interface_alt_0_desc.bInterfaceNumber = status;
microphone_as_interface_alt_1_desc.bInterfaceNumber = status;
ac_header_desc.baInterfaceNr[0] = status;
+ audio->alt_intf[0] = 0;
status = -ENODEV;
@@ -1077,6 +1095,7 @@
speaker_as_interface_alt_0_desc.bInterfaceNumber = status;
speaker_as_interface_alt_1_desc.bInterfaceNumber = status;
ac_header_desc.baInterfaceNr[1] = status;
+ audio->alt_intf[1] = 0;
status = -ENODEV;
@@ -1225,6 +1244,7 @@
audio->card.func.strings = audio_strings;
audio->card.func.bind = f_audio_bind;
audio->card.func.unbind = f_audio_unbind;
+ audio->card.func.get_alt = f_audio_get_alt;
audio->card.func.set_alt = f_audio_set_alt;
audio->card.func.setup = f_audio_setup;
audio->card.func.disable = f_audio_disable;
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 3c3fbca..67c9a1a 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -363,10 +363,13 @@
switch (status) {
case 0:
/* successful completion */
+ break;
case -ECONNRESET:
case -ESHUTDOWN:
/* connection gone */
- break;
+ dev_kfree_skb_any(skb);
+ usb_ep_free_request(ep, req);
+ return;
default:
pr_err("%s: data tx ep error %d\n",
__func__, status);
diff --git a/drivers/usb/gadget/u_rmnet_ctrl_smd.c b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
index 5817779..161634e 100644
--- a/drivers/usb/gadget/u_rmnet_ctrl_smd.c
+++ b/drivers/usb/gadget/u_rmnet_ctrl_smd.c
@@ -408,6 +408,11 @@
struct platform_driver *pdrv;
c = &port->ctrl_ch;
+ if (c->ch) {
+ smd_close(c->ch);
+ c->ch = NULL;
+ }
+
if (test_bit(CH_READY, &c->flags) ||
test_bit(CH_PREPARE_READY, &c->flags)) {
clear_bit(CH_PREPARE_READY, &c->flags);
@@ -422,6 +427,7 @@
unsigned long flags;
struct smd_ch_info *c;
struct rmnet_ctrl_pkt *cpkt;
+ int clear_bits;
pr_debug("%s: grmnet:%p port#%d\n", __func__, gr, port_num);
@@ -453,13 +459,10 @@
spin_unlock_irqrestore(&port->port_lock, flags);
- if (test_and_clear_bit(CH_OPENED, &c->flags))
+ if (test_and_clear_bit(CH_OPENED, &c->flags)) {
+ clear_bits = ~(c->cbits_tomodem | TIOCM_RTS);
/* send dtr zero */
- smd_tiocmset(c->ch, c->cbits_tomodem, ~c->cbits_tomodem);
-
- if (c->ch) {
- smd_close(c->ch);
- c->ch = NULL;
+ smd_tiocmset(c->ch, c->cbits_tomodem, clear_bits);
}
queue_delayed_work(grmnet_ctrl_wq, &port->disconnect_w, 0);
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 9879122..4a085aa 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -1332,44 +1332,48 @@
if (pdata->resume_gpio)
gpio_direction_output(pdata->resume_gpio, 1);
- mehci->resume_status = 0;
- resume_thread = kthread_run(msm_hsic_resume_thread,
- mehci, "hsic_resume_thread");
- if (IS_ERR(resume_thread)) {
- pr_err("Error creating resume thread:%lu\n",
- PTR_ERR(resume_thread));
- return PTR_ERR(resume_thread);
+ if (!mehci->ehci.resume_sof_bug) {
+ ehci_bus_resume(hcd);
+ } else {
+ mehci->resume_status = 0;
+ resume_thread = kthread_run(msm_hsic_resume_thread,
+ mehci, "hsic_resume_thread");
+ if (IS_ERR(resume_thread)) {
+ pr_err("Error creating resume thread:%lu\n",
+ PTR_ERR(resume_thread));
+ return PTR_ERR(resume_thread);
+ }
+
+ wait_for_completion(&mehci->rt_completion);
+
+ if (mehci->resume_status < 0)
+ return mehci->resume_status;
+
+ dbg_log_event(NULL, "FPR: Wokeup", 0);
+ spin_lock_irq(&ehci->lock);
+ (void) ehci_readl(ehci, &ehci->regs->command);
+
+ temp = 0;
+ if (ehci->async->qh_next.qh)
+ temp |= CMD_ASE;
+ if (ehci->periodic_sched)
+ temp |= CMD_PSE;
+ if (temp) {
+ ehci->command |= temp;
+ ehci_writel(ehci, ehci->command, &ehci->regs->command);
+ }
+
+ ehci->next_statechange = jiffies + msecs_to_jiffies(5);
+ hcd->state = HC_STATE_RUNNING;
+ ehci->rh_state = EHCI_RH_RUNNING;
+ ehci->command |= CMD_RUN;
+
+ /* Now we can safely re-enable irqs */
+ ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
+
+ spin_unlock_irq(&ehci->lock);
}
- wait_for_completion(&mehci->rt_completion);
-
- if (mehci->resume_status < 0)
- return mehci->resume_status;
-
- dbg_log_event(NULL, "FPR: Wokeup", 0);
- spin_lock_irq(&ehci->lock);
- (void) ehci_readl(ehci, &ehci->regs->command);
-
- temp = 0;
- if (ehci->async->qh_next.qh)
- temp |= CMD_ASE;
- if (ehci->periodic_sched)
- temp |= CMD_PSE;
- if (temp) {
- ehci->command |= temp;
- ehci_writel(ehci, ehci->command, &ehci->regs->command);
- }
-
- ehci->next_statechange = jiffies + msecs_to_jiffies(5);
- hcd->state = HC_STATE_RUNNING;
- ehci->rh_state = EHCI_RH_RUNNING;
- ehci->command |= CMD_RUN;
-
- /* Now we can safely re-enable irqs */
- ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
-
- spin_unlock_irq(&ehci->lock);
-
if (pdata->resume_gpio)
gpio_direction_output(pdata->resume_gpio, 0);
@@ -1808,6 +1812,8 @@
res_gpio = 0;
pdata->resume_gpio = res_gpio;
+ pdata->phy_sof_workaround = of_property_read_bool(node,
+ "qcom,phy-sof-workaround");
pdata->ignore_cal_pad_config = of_property_read_bool(node,
"hsic,ignore-cal-pad-config");
of_property_read_u32(node, "hsic,strobe-pad-offset",
@@ -1899,10 +1905,12 @@
spin_lock_init(&mehci->wakeup_lock);
- mehci->ehci.susp_sof_bug = 1;
- mehci->ehci.reset_sof_bug = 1;
+ if (pdata->phy_sof_workaround) {
+ mehci->ehci.susp_sof_bug = 1;
+ mehci->ehci.reset_sof_bug = 1;
+ mehci->ehci.resume_sof_bug = 1;
+ }
- mehci->ehci.resume_sof_bug = 1;
mehci->ehci.pool_64_bit_align = pdata->pool_64_bit_align;
mehci->enable_hbm = pdata->enable_hbm;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 5750e0d..cae2c17 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -3897,7 +3897,20 @@
ret = PTR_ERR(motg->core_clk);
goto put_clk;
}
- clk_set_rate(motg->core_clk, INT_MAX);
+
+ /*
+ * Get Max supported clk frequency for USB Core CLK and request
+ * to set the same.
+ */
+ motg->core_clk_rate = clk_round_rate(motg->core_clk, LONG_MAX);
+ if (IS_ERR_VALUE(motg->core_clk_rate)) {
+ dev_err(&pdev->dev, "fail to get core clk max freq.\n");
+ } else {
+ ret = clk_set_rate(motg->core_clk, motg->core_clk_rate);
+ if (ret)
+ dev_err(&pdev->dev, "fail to set core_clk freq:%d\n",
+ ret);
+ }
motg->pclk = clk_get(&pdev->dev, "iface_clk");
if (IS_ERR(motg->pclk)) {
diff --git a/drivers/video/msm/mdss/Makefile b/drivers/video/msm/mdss/Makefile
index a710fef..de765ea 100644
--- a/drivers/video/msm/mdss/Makefile
+++ b/drivers/video/msm/mdss/Makefile
@@ -1,12 +1,12 @@
mdss-mdp-objs := mdss_mdp.o mdss_mdp_ctl.o mdss_mdp_pipe.o mdss_mdp_util.o
mdss-mdp-objs += mdss_mdp_pp.o
mdss-mdp-objs += mdss_mdp_intf_video.o
+mdss-mdp-objs += mdss_mdp_intf_cmd.o
mdss-mdp-objs += mdss_mdp_intf_writeback.o
mdss-mdp-objs += mdss_mdp_rotator.o
mdss-mdp-objs += mdss_mdp_overlay.o
mdss-mdp-objs += mdss_mdp_wb.o
obj-$(CONFIG_FB_MSM_MDSS) += mdss-mdp.o
-obj-$(CONFIG_FB_MSM_MDSS) += mdss_fb.o
ifeq ($(CONFIG_FB_MSM_MDSS),y)
obj-$(CONFIG_DEBUG_FS) += mdss_debug.o
@@ -30,3 +30,5 @@
mdss-qpic-objs := mdss_qpic.o mdss_fb.o mdss_qpic_panel.o
obj-$(CONFIG_FB_MSM_QPIC) += mdss-qpic.o
obj-$(CONFIG_FB_MSM_QPIC_ILI_QVGA_PANEL) += qpic_panel_ili_qvga.o
+
+obj-$(CONFIG_FB_MSM_MDSS) += mdss_fb.o
diff --git a/drivers/video/msm/mdss/mdss_debug.c b/drivers/video/msm/mdss/mdss_debug.c
index 7dc4f49..0b2a7c0 100644
--- a/drivers/video/msm/mdss/mdss_debug.c
+++ b/drivers/video/msm/mdss/mdss_debug.c
@@ -24,7 +24,7 @@
#include "mdss_mdp.h"
#include "mdss_debug.h"
-#define DEFAULT_BASE_REG_CNT 128
+#define DEFAULT_BASE_REG_CNT 0x100
#define GROUP_BYTES 4
#define ROW_BYTES 16
@@ -67,7 +67,8 @@
const char __user *user_buf, size_t count, loff_t *ppos)
{
struct mdss_debug_base *dbg = file->private_data;
- u32 off, cnt;
+ u32 off = 0;
+ u32 cnt = DEFAULT_BASE_REG_CNT;
char buf[24];
if (!dbg)
@@ -81,14 +82,11 @@
buf[count] = 0; /* end of string */
- sscanf(buf, "%5x %d", &off, &cnt);
+ sscanf(buf, "%5x %x", &off, &cnt);
if (off > dbg->max_offset)
return -EINVAL;
- if (cnt <= 0)
- cnt = DEFAULT_BASE_REG_CNT;
-
if (cnt > (dbg->max_offset - off))
cnt = dbg->max_offset - off;
@@ -113,7 +111,7 @@
if (*ppos)
return 0; /* the end */
- len = snprintf(buf, sizeof(buf), "0x%08x %d\n", dbg->off, dbg->off);
+ len = snprintf(buf, sizeof(buf), "0x%08x %x\n", dbg->off, dbg->cnt);
if (len < 0)
return 0;
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index bfcd7ec..8bf8c95 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -25,6 +25,7 @@
#include "mdss.h"
#include "mdss_panel.h"
#include "mdss_dsi.h"
+#include "mdss_debug.h"
static unsigned char *mdss_dsi_base;
@@ -250,32 +251,6 @@
return 0;
}
-static int mdss_dsi_ctrl_unprepare(struct mdss_panel_data *pdata)
-{
- struct mdss_panel_info *pinfo;
- struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- int ret = 0;
-
- 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);
- pinfo = &pdata->panel_info;
-
- mdss_dsi_op_mode_config(DSI_CMD_MODE, pdata);
-
- ret = ctrl_pdata->off(pdata);
- if (ret) {
- pr_err("%s: Panel OFF failed\n", __func__);
- return ret;
- }
-
- return ret;
-}
-
static void mdss_dsi_put_dt_vreg_data(struct device *dev,
struct dss_module_power *module_power)
{
@@ -443,6 +418,10 @@
ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
panel_data);
+
+ pr_debug("%s+: ctrl=%p ndx=%d\n", __func__,
+ ctrl_pdata, ctrl_pdata->ndx);
+
mdss_dsi_clk_disable(pdata);
mdss_dsi_unprepare_clocks(ctrl_pdata);
@@ -498,7 +477,7 @@
struct mdss_panel_info *pinfo;
struct mipi_panel_info *mipi;
u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
- u32 ystride, bpp, data;
+ u32 ystride, bpp, data, dst_bpp;
u32 dummy_xres, dummy_yres;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
@@ -514,6 +493,10 @@
ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
panel_data);
+
+ pr_debug("%s+: ctrl=%p ndx=%d\n",
+ __func__, ctrl_pdata, ctrl_pdata->ndx);
+
pinfo = &pdata->panel_info;
ret = mdss_dsi_panel_power_on(pdata, 1);
@@ -533,13 +516,22 @@
clk_rate = pdata->panel_info.clk_rate;
clk_rate = min(clk_rate, pdata->panel_info.clk_max);
- hbp = pdata->panel_info.lcdc.h_back_porch;
- hfp = pdata->panel_info.lcdc.h_front_porch;
- vbp = pdata->panel_info.lcdc.v_back_porch;
- vfp = pdata->panel_info.lcdc.v_front_porch;
- hspw = pdata->panel_info.lcdc.h_pulse_width;
+ dst_bpp = pdata->panel_info.fbc.enabled ?
+ (pdata->panel_info.fbc.target_bpp) : (pinfo->bpp);
+
+ hbp = mult_frac(pdata->panel_info.lcdc.h_back_porch, dst_bpp,
+ pdata->panel_info.bpp);
+ hfp = mult_frac(pdata->panel_info.lcdc.h_front_porch, dst_bpp,
+ pdata->panel_info.bpp);
+ vbp = mult_frac(pdata->panel_info.lcdc.v_back_porch, dst_bpp,
+ pdata->panel_info.bpp);
+ vfp = mult_frac(pdata->panel_info.lcdc.v_front_porch, dst_bpp,
+ pdata->panel_info.bpp);
+ hspw = mult_frac(pdata->panel_info.lcdc.h_pulse_width, dst_bpp,
+ pdata->panel_info.bpp);
vspw = pdata->panel_info.lcdc.v_pulse_width;
- width = pdata->panel_info.xres;
+ width = mult_frac(pdata->panel_info.xres, dst_bpp,
+ pdata->panel_info.bpp);
height = pdata->panel_info.yres;
mipi = &pdata->panel_info.mipi;
@@ -597,6 +589,27 @@
wmb();
}
+ pr_debug("%s-:\n", __func__);
+ return 0;
+}
+
+static int mdss_dsi_unblank(struct mdss_panel_data *pdata)
+{
+ int ret = 0;
+ struct mipi_panel_info *mipi;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+
+ pr_debug("%s+:\n", __func__);
+
+ 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);
+ mipi = &pdata->panel_info.mipi;
+
ret = ctrl_pdata->on(pdata);
if (ret) {
pr_err("%s: unable to initialize the panel\n", __func__);
@@ -605,6 +618,34 @@
mdss_dsi_op_mode_config(mipi->mode, pdata);
+ pr_debug("%s-:\n", __func__);
+
+ return ret;
+}
+
+static int mdss_dsi_blank(struct mdss_panel_data *pdata)
+{
+ int ret = 0;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+
+ pr_debug("%s+:\n", __func__);
+
+ 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);
+
+ mdss_dsi_op_mode_config(DSI_CMD_MODE, pdata);
+
+ ret = ctrl_pdata->off(pdata);
+ if (ret) {
+ pr_err("%s: Panel OFF failed\n", __func__);
+ return ret;
+ }
+
pr_debug("%s-:End\n", __func__);
return ret;
}
@@ -621,33 +662,27 @@
}
ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
panel_data);
+ pr_debug("%s+:event=%d\n", __func__, event);
+
switch (event) {
case MDSS_EVENT_UNBLANK:
+ rc = mdss_dsi_on(pdata);
if (ctrl_pdata->on_cmds->ctrl_state == DSI_LP_MODE) {
- rc = mdss_dsi_on(pdata);
- } else {
- pr_debug("%s:event=%d, Dsi On not called: ctrl_state: %d\n",
- __func__, event,
- ctrl_pdata->on_cmds->ctrl_state);
- rc = -EINVAL;
+ rc = mdss_dsi_unblank(pdata);
}
break;
+ case MDSS_EVENT_PANEL_ON:
+ if (ctrl_pdata->on_cmds->ctrl_state == DSI_HS_MODE)
+ rc = mdss_dsi_unblank(pdata);
+ break;
case MDSS_EVENT_BLANK:
if (ctrl_pdata->off_cmds->ctrl_state == DSI_HS_MODE) {
- rc = mdss_dsi_ctrl_unprepare(pdata);
- } else {
- pr_debug("%s:event=%d,Unprepare not called.Ctrl_state: %d\n",
- __func__, event,
- ctrl_pdata->on_cmds->ctrl_state);
- rc = -EINVAL;
+ rc = mdss_dsi_blank(pdata);
}
break;
- case MDSS_EVENT_TIMEGEN_OFF:
+ case MDSS_EVENT_PANEL_OFF:
if (ctrl_pdata->off_cmds->ctrl_state == DSI_LP_MODE) {
- pr_debug("%s:event=%d, calling unprepare: ctrl_state: %d\n",
- __func__, event,
- ctrl_pdata->on_cmds->ctrl_state);
- rc = mdss_dsi_ctrl_unprepare(pdata);
+ rc = mdss_dsi_blank(pdata);
}
rc = mdss_dsi_off(pdata);
break;
@@ -665,6 +700,7 @@
pr_debug("%s: unhandled event=%d\n", __func__, event);
break;
}
+ pr_debug("%s-:event=%d, rc=%d\n", __func__, event, rc);
return rc;
}
@@ -674,8 +710,6 @@
u32 index;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- pr_debug("%s\n", __func__);
-
if (pdev->dev.of_node) {
struct resource *mdss_dsi_mres;
const char *ctrl_name;
@@ -789,7 +823,7 @@
struct device dsi_dev;
int mdss_dsi_retrieve_ctrl_resources(struct platform_device *pdev, int mode,
- unsigned char **ctrl_base)
+ struct mdss_dsi_ctrl_pdata *ctrl)
{
int rc = 0;
u32 index;
@@ -828,21 +862,25 @@
return -ENOMEM;
}
- *ctrl_base = ioremap(mdss_dsi_mres->start,
+ ctrl->ctrl_base = ioremap(mdss_dsi_mres->start,
resource_size(mdss_dsi_mres));
- if (!(*ctrl_base)) {
+ if (!(ctrl->ctrl_base)) {
pr_err("%s:%d unable to remap dsi resources",
__func__, __LINE__);
return -ENOMEM;
}
+ ctrl->reg_size = resource_size(mdss_dsi_mres);
+
+ pr_info("%s: dsi base=%x size=%x\n",
+ __func__, (int)ctrl->ctrl_base, ctrl->reg_size);
+
return 0;
}
int dsi_panel_device_register(struct platform_device *pdev,
- struct mdss_panel_common_pdata *panel_data,
- char backlight_ctrl)
+ struct mdss_panel_common_pdata *panel_data)
{
struct mipi_panel_info *mipi;
int rc;
@@ -851,7 +889,6 @@
struct mdss_dsi_ctrl_pdata *ctrl_pdata;
struct device_node *dsi_ctrl_np = NULL;
struct platform_device *ctrl_pdev = NULL;
- unsigned char *ctrl_addr;
bool broadcast;
bool cont_splash_enabled = false;
@@ -891,8 +928,7 @@
else
bpp = 3; /* Default format set to RGB888 */
- if (panel_data->panel_info.type == MIPI_VIDEO_PANEL &&
- !panel_data->panel_info.clk_rate) {
+ if (!panel_data->panel_info.clk_rate) {
h_period += panel_data->panel_info.lcdc.xres_pad;
v_period += panel_data->panel_info.lcdc.yres_pad;
@@ -961,6 +997,45 @@
}
}
+ ctrl_pdata->disp_te_gpio = of_get_named_gpio(pdev->dev.of_node,
+ "qcom,te-gpio", 0);
+ if (!gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
+ pr_err("%s:%d, Disp_te gpio not specified\n",
+ __func__, __LINE__);
+ } else {
+ rc = gpio_request(ctrl_pdata->disp_te_gpio, "disp_te");
+ if (rc) {
+ pr_err("request TE gpio failed, rc=%d\n",
+ rc);
+ gpio_free(ctrl_pdata->disp_te_gpio);
+ return -ENODEV;
+ }
+ rc = gpio_tlmm_config(GPIO_CFG(
+ ctrl_pdata->disp_te_gpio, 1,
+ GPIO_CFG_INPUT,
+ GPIO_CFG_PULL_DOWN,
+ GPIO_CFG_2MA),
+ GPIO_CFG_ENABLE);
+
+ 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);
+ return -ENODEV;
+ }
+ pr_debug("%s: te_gpio=%d\n", __func__,
+ ctrl_pdata->disp_te_gpio);
+ }
+
+
ctrl_pdata->rst_gpio = of_get_named_gpio(pdev->dev.of_node,
"qcom,rst-gpio", 0);
if (!gpio_is_valid(ctrl_pdata->rst_gpio)) {
@@ -985,12 +1060,11 @@
if (mdss_dsi_retrieve_ctrl_resources(ctrl_pdev,
panel_data->panel_info.pdest,
- &ctrl_addr)) {
+ ctrl_pdata)) {
pr_err("%s: unable to get Dsi controller res\n", __func__);
return -EPERM;
}
- pr_debug("%s: ctrl base address: 0x%x\n", __func__, (int)ctrl_addr);
ctrl_pdata->panel_data.event_handler = mdss_dsi_event_handler;
ctrl_pdata->on_cmds = panel_data->dsi_panel_on_cmds;
@@ -1001,9 +1075,16 @@
sizeof(struct mdss_panel_info));
mdss_dsi_irq_handler_config(ctrl_pdata);
- (ctrl_pdata->panel_data).set_backlight = panel_data->bl_fnc;
- (ctrl_pdata->ctrl_base) = ctrl_addr;
- (ctrl_pdata->bl_ctrl) = backlight_ctrl;
+ ctrl_pdata->panel_data.set_backlight = panel_data->bl_fnc;
+ ctrl_pdata->bklt_ctrl = panel_data->panel_info.bklt_ctrl;
+ ctrl_pdata->pwm_gpio = panel_data->panel_info.pwm_gpio;
+ ctrl_pdata->pwm_period = panel_data->panel_info.pwm_period;
+ ctrl_pdata->pwm_lpg_chan = panel_data->panel_info.pwm_lpg_chan;
+ ctrl_pdata->bklt_max = panel_data->panel_info.bl_max;
+
+ if (ctrl_pdata->bklt_ctrl == BL_PWM)
+ mdss_dsi_panel_pwm_cfg(ctrl_pdata);
+
/*
* register in mdp driver
*/
@@ -1047,6 +1128,16 @@
pr_debug("%s: pclk=%d, bclk=%d\n", __func__,
ctrl_pdata->pclk_rate, ctrl_pdata->byte_clk_rate);
+ if (panel_data->panel_info.pdest == DISPLAY_1) {
+ mdss_debug_register_base("dsi0",
+ ctrl_pdata->ctrl_base, ctrl_pdata->reg_size);
+ ctrl_pdata->ndx = 0;
+ } else {
+ mdss_debug_register_base("dsi1",
+ ctrl_pdata->ctrl_base, ctrl_pdata->reg_size);
+ ctrl_pdata->ndx = 1;
+ }
+
pr_debug("%s: Panal data initialized\n", __func__);
return 0;
}
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index b365f36..197ff7a 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -273,17 +273,27 @@
};
struct mdss_dsi_ctrl_pdata {
+ int ndx;
int (*on) (struct mdss_panel_data *pdata);
int (*off) (struct mdss_panel_data *pdata);
struct mdss_panel_data panel_data;
+ struct mdss_hw *mdss_hw;
unsigned char *ctrl_base;
- char bl_ctrl;
+ int reg_size;
struct clk *byte_clk;
struct clk *esc_clk;
struct clk *pixel_clk;
+ int irq_cnt;
int mdss_dsi_clk_on;
int rst_gpio;
int disp_en_gpio;
+ int disp_te_gpio;
+ int bklt_ctrl; /* backlight ctrl */
+ int pwm_period;
+ int pwm_gpio;
+ int pwm_lpg_chan;
+ int bklt_max;
+ struct pwm_device *pwm_bl;
struct dsi_panel_cmds_list *on_cmds;
struct dsi_panel_cmds_list *off_cmds;
struct dsi_drv_cm_data shared_pdata;
@@ -293,8 +303,7 @@
};
int dsi_panel_device_register(struct platform_device *pdev,
- struct mdss_panel_common_pdata *panel_data,
- char bl_ctrl);
+ struct mdss_panel_common_pdata *panel_data);
char *mdss_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen);
char *mdss_dsi_buf_init(struct dsi_buf *dp);
@@ -343,5 +352,7 @@
void mdss_dsi_phy_enable(unsigned char *ctrl_base, int on);
void mdss_dsi_phy_init(struct mdss_panel_data *pdata);
void mdss_dsi_phy_sw_reset(unsigned char *ctrl_base);
+void mdss_dsi_cmd_test_pattern(struct mdss_panel_data *pdata);
+void mdss_dsi_panel_pwm_cfg(struct mdss_dsi_ctrl_pdata *ctrl);
#endif /* MDSS_DSI_H */
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 6f7023c..ccec0fc 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -26,7 +26,6 @@
#include "mdss_dsi.h"
static struct completion dsi_dma_comp;
-static int dsi_irq_enabled;
static spinlock_t dsi_irq_lock;
static spinlock_t dsi_mdp_lock;
static int dsi_mdp_busy;
@@ -51,90 +50,47 @@
spin_lock_init(&dsi_mdp_lock);
}
-void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl)
{
- if (ctrl_pdata->panel_data.panel_info.pdest == DISPLAY_1)
- mdss_dsi0_hw.ptr = (void *)(ctrl_pdata);
- else
- mdss_dsi1_hw.ptr = (void *)(ctrl_pdata);
+ if (ctrl->panel_data.panel_info.pdest == DISPLAY_1) {
+ mdss_dsi0_hw.ptr = (void *)(ctrl);
+ ctrl->mdss_hw = &mdss_dsi0_hw;
+ } else {
+ mdss_dsi1_hw.ptr = (void *)(ctrl);
+ ctrl->mdss_hw = &mdss_dsi1_hw;
+ }
}
-void mdss_dsi_enable_irq(struct mdss_panel_data *pdata)
+void mdss_dsi_irq_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable, int isr)
{
unsigned long flags;
- struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
- if (pdata == NULL) {
- pr_err("%s: Invalid input data\n", __func__);
+ if (ctrl == NULL) {
+ pr_err("%s: Invalid ctrl\n", __func__);
return;
}
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
- panel_data);
-
spin_lock_irqsave(&dsi_irq_lock, flags);
- if (dsi_irq_enabled) {
- pr_debug("%s: IRQ aleady enabled\n", __func__);
- spin_unlock_irqrestore(&dsi_irq_lock, flags);
- return;
+ if (enable) {
+ if (ctrl->irq_cnt == 0)
+ mdss_enable_irq(ctrl->mdss_hw);
+ ctrl->irq_cnt++;
+ } else {
+ if (ctrl->irq_cnt) {
+ ctrl->irq_cnt--;
+ if (ctrl->irq_cnt == 0) {
+ if (isr)
+ mdss_disable_irq_nosync(ctrl->mdss_hw);
+ else
+ mdss_disable_irq(ctrl->mdss_hw);
+ }
+ }
}
-
- if ((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1)
- mdss_enable_irq(&mdss_dsi0_hw);
- else
- mdss_enable_irq(&mdss_dsi1_hw);
-
- dsi_irq_enabled = 1;
- /* TO DO: Check whether MDSS IRQ is enabled */
+ pr_debug("%s: ctrl=%d enable=%d cnt=%d\n", __func__,
+ ctrl->ndx, enable, ctrl->irq_cnt);
spin_unlock_irqrestore(&dsi_irq_lock, flags);
}
-void mdss_dsi_disable_irq(struct mdss_panel_data *pdata)
-{
- unsigned long flags;
- struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
-
- if (pdata == NULL) {
- pr_err("%s: Invalid input data\n", __func__);
- return;
- }
-
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
- panel_data);
-
- spin_lock_irqsave(&dsi_irq_lock, flags);
- if (dsi_irq_enabled == 0) {
- pr_debug("%s: IRQ already disabled\n", __func__);
- spin_unlock_irqrestore(&dsi_irq_lock, flags);
- return;
- }
- if (ctrl_pdata->panel_data.panel_info.pdest == DISPLAY_1)
- mdss_disable_irq(&mdss_dsi0_hw);
- else
- mdss_disable_irq(&mdss_dsi1_hw);
-
- dsi_irq_enabled = 0;
- /* TO DO: Check whether MDSS IRQ is Disabled */
- spin_unlock_irqrestore(&dsi_irq_lock, flags);
-}
-
-/*
- * mdss_dsi_disale_irq_nosync() should be called
- * from interrupt context
- */
-void mdss_dsi_disable_irq_nosync(void)
-{
- spin_lock(&dsi_irq_lock);
- if (dsi_irq_enabled == 0) {
- pr_debug("%s: IRQ cannot be disabled\n", __func__);
- spin_unlock(&dsi_irq_lock);
- return;
- }
-
- dsi_irq_enabled = 0;
- spin_unlock(&dsi_irq_lock);
-}
-
/*
* mipi dsi buf mechanism
*/
@@ -689,6 +645,30 @@
return len;
}
+void mdss_dsi_cmd_test_pattern(struct mdss_panel_data *pdata)
+{
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+ int i;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return;
+ }
+
+ ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ panel_data);
+
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x015c, 0x201);
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x016c, 0xff0000); /* red */
+ i = 0;
+ while (i++ < 50) {
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0184, 0x1);
+ /* Add sleep to get ~50 fps frame rate*/
+ msleep(20);
+ }
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x015c, 0x0);
+}
+
void mdss_dsi_host_init(struct mipi_panel_info *pinfo,
struct mdss_panel_data *pdata)
{
@@ -745,7 +725,7 @@
if (pinfo->r_sel)
data |= BIT(4);
data |= (pinfo->dst_format & 0x0f); /* 4 bits */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x003c, data);
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0040, data);
/* DSI_COMMAND_MODE_MDP_DCS_CMD_CTRL */
data = pinfo->wr_mem_continue & 0x0ff;
@@ -830,6 +810,7 @@
dsi_ctrl |= BIT(0); /* enable dsi */
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl);
+ mdss_dsi_irq_ctrl(ctrl_pdata, 1, 0); /* enable dsi irq */
wmb();
}
@@ -977,8 +958,6 @@
DSI_INTR_CMD_MDP_DONE_MASK;
}
- pr_debug("%s: dsi_ctrl=%x intr=%x\n", __func__, dsi_ctrl, intr_ctrl);
-
if (ctrl_pdata->shared_pdata.broadcast_enable)
if ((pdata->panel_info.pdest == DISPLAY_2)
&& (left_ctrl_pdata != NULL)) {
@@ -994,17 +973,6 @@
wmb();
}
-void mdss_dsi_cmd_mdp_start(struct mdss_panel_data *pdata)
-{
- unsigned long flag;
-
- spin_lock_irqsave(&dsi_mdp_lock, flag);
- mdss_dsi_enable_irq(pdata);
- dsi_mdp_busy = true;
- spin_unlock_irqrestore(&dsi_mdp_lock, flag);
-}
-
-
void mdss_dsi_cmd_bta_sw_trigger(struct mdss_panel_data *pdata)
{
u32 status;
@@ -1116,7 +1084,7 @@
}
spin_lock_irqsave(&dsi_mdp_lock, flag);
- mdss_dsi_enable_irq(pdata);
+ mdss_dsi_irq_ctrl(ctrl_pdata, 1, 0);
dsi_mdp_busy = true;
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
@@ -1134,7 +1102,7 @@
spin_lock_irqsave(&dsi_mdp_lock, flag);
dsi_mdp_busy = false;
- mdss_dsi_disable_irq(pdata);
+ mdss_dsi_irq_ctrl(ctrl_pdata, 0, 0);
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
if (video_mode)
@@ -1206,7 +1174,7 @@
}
spin_lock_irqsave(&dsi_mdp_lock, flag);
- mdss_dsi_enable_irq(pdata);
+ mdss_dsi_irq_ctrl(ctrl_pdata, 1, 0);
dsi_mdp_busy = true;
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
@@ -1243,7 +1211,7 @@
spin_lock_irqsave(&dsi_mdp_lock, flag);
dsi_mdp_busy = false;
- mdss_dsi_disable_irq(pdata);
+ mdss_dsi_irq_ctrl(ctrl_pdata, 0, 0);
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
if (pdata->panel_info.mipi.no_max_pkt_size) {
@@ -1288,7 +1256,6 @@
struct mdss_panel_data *pdata)
{
int len;
- int i;
int domain = MDSS_IOMMU_DOMAIN_UNSECURE;
char *bp;
unsigned long size, addr;
@@ -1303,12 +1270,6 @@
panel_data);
bp = tp->data;
- pr_debug("%s: ", __func__);
- for (i = 0; i < tp->len; i++)
- pr_debug("%x ", *bp++);
-
- pr_debug("\n");
-
len = ALIGN(tp->len, 4);
size = ALIGN(tp->len, SZ_4K);
@@ -1495,6 +1456,8 @@
MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0110, isr0);
}
+ pr_debug("%s: isr=%x %x", __func__, isr, (int)DSI_INTR_ERROR);
+
if (isr & DSI_INTR_ERROR)
mdss_dsi_error(dsi_base);
@@ -1510,7 +1473,6 @@
if (isr & DSI_INTR_CMD_MDP_DONE) {
spin_lock(&dsi_mdp_lock);
dsi_mdp_busy = false;
- mdss_dsi_disable_irq_nosync();
spin_unlock(&dsi_mdp_lock);
}
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 8d38737..c56cd41 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -13,11 +13,14 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/of.h>
-#include <linux/qpnp/pin.h>
+#include <linux/of_gpio.h>
#include <linux/gpio.h>
+#include <linux/qpnp/pin.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/leds.h>
+#include <linux/pwm.h>
+#include <linux/err.h>
#include "mdss_dsi.h"
@@ -30,6 +33,64 @@
static struct mdss_dsi_phy_ctrl phy_params;
+void mdss_dsi_panel_pwm_cfg(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ int ret;
+
+ if (!gpio_is_valid(ctrl->pwm_gpio)) {
+ pr_err("%s: pwm_gpio=%d Invalid\n", __func__,
+ ctrl->pwm_gpio);
+ return;
+ }
+
+ ret = gpio_request(ctrl->pwm_gpio, "disp_pwm");
+ if (ret) {
+ pr_err("%s: pwm_gpio=%d request failed\n", __func__,
+ ctrl->pwm_gpio);
+ return;
+ }
+
+ ctrl->pwm_bl = pwm_request(ctrl->pwm_lpg_chan, "lcd-bklt");
+ if (ctrl->pwm_bl == NULL || IS_ERR(ctrl->pwm_bl)) {
+ pr_err("%s: lpg_chan=%d pwm request failed", __func__,
+ ctrl->pwm_lpg_chan);
+ gpio_free(ctrl->pwm_gpio);
+ ctrl->pwm_gpio = -1;
+ }
+}
+
+static void mdss_dsi_panel_bklt_pwm(struct mdss_dsi_ctrl_pdata *ctrl, int level)
+{
+ int ret;
+ u32 duty;
+
+ if (ctrl->pwm_bl == NULL) {
+ pr_err("%s: no PWM\n", __func__);
+ return;
+ }
+
+ duty = level * ctrl->pwm_period;
+ duty /= ctrl->bklt_max;
+
+ pr_debug("%s: bklt_ctrl=%d pwm_period=%d pwm_gpio=%d pwm_lpg_chan=%d\n",
+ __func__, ctrl->bklt_ctrl, ctrl->pwm_period,
+ ctrl->pwm_gpio, ctrl->pwm_lpg_chan);
+
+ pr_debug("%s: ndx=%d level=%d duty=%d\n", __func__,
+ ctrl->ndx, level, duty);
+
+ ret = pwm_config(ctrl->pwm_bl, duty, ctrl->pwm_period);
+ if (ret) {
+ pr_err("%s: pwm_config() failed err=%d.\n", __func__, ret);
+ return;
+ }
+
+ ret = pwm_enable(ctrl->pwm_bl);
+ if (ret)
+ pr_err("%s: pwm_enable() failed err=%d\n", __func__, ret);
+}
+
+
void mdss_dsi_panel_reset(struct mdss_panel_data *pdata, int enable)
{
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
@@ -84,46 +145,51 @@
ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
panel_data);
- if (ctrl_pdata->bl_ctrl) {
- switch (ctrl_pdata->bl_ctrl) {
- case BL_WLED:
- led_trigger_event(bl_led_trigger, bl_level);
- break;
-
- default:
- pr_err("%s: Unknown bl_ctrl configuration\n",
- __func__);
- break;
- }
- } else
- pr_err("%s:%d, bl_ctrl not configured", __func__, __LINE__);
+ switch (ctrl_pdata->bklt_ctrl) {
+ case BL_WLED:
+ led_trigger_event(bl_led_trigger, bl_level);
+ break;
+ case BL_PWM:
+ mdss_dsi_panel_bklt_pwm(ctrl_pdata, bl_level);
+ break;
+ default:
+ pr_err("%s: Unknown bl_ctrl configuration\n",
+ __func__);
+ break;
+ }
}
+static char set_tear_on[2] = {0x35, 0x00};
+static struct dsi_cmd_desc dsi_tear_on_cmd = {
+ DTYPE_DCS_WRITE1, 1, 0, 0, 0, sizeof(set_tear_on), set_tear_on};
+
+static char set_tear_off[2] = {0x34, 0x00};
+static struct dsi_cmd_desc dsi_tear_off_cmd = {
+ DTYPE_DCS_WRITE, 1, 0, 0, 0, sizeof(set_tear_off), set_tear_off};
+
static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
{
struct mipi_panel_info *mipi;
- struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+ struct mdss_dsi_ctrl_pdata *ctrl = NULL;
if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
return -EINVAL;
}
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
panel_data);
mipi = &pdata->panel_info.mipi;
- pr_debug("%s:%d, debug info (mode) : %d\n", __func__, __LINE__,
- mipi->mode);
+ pr_debug("%s: ctrl=%p ndx=%d\n", __func__, ctrl, ctrl->ndx);
- if (mipi->mode == DSI_VIDEO_MODE) {
+ if (ctrl->on_cmds->size)
mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf,
- ctrl_pdata->on_cmds->buf,
- ctrl_pdata->on_cmds->size);
- } else {
- pr_err("%s:%d, CMD MODE NOT SUPPORTED", __func__, __LINE__);
- return -EINVAL;
- }
+ ctrl->on_cmds->buf,
+ ctrl->on_cmds->size);
+
+ mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf,
+ &dsi_tear_on_cmd, 1);
return 0;
}
@@ -131,37 +197,37 @@
static int mdss_dsi_panel_off(struct mdss_panel_data *pdata)
{
struct mipi_panel_info *mipi;
- struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+ struct mdss_dsi_ctrl_pdata *ctrl = NULL;
if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
return -EINVAL;
}
- ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
+ ctrl = container_of(pdata, struct mdss_dsi_ctrl_pdata,
panel_data);
+
+ pr_debug("%s: ctrl=%p ndx=%d\n", __func__, ctrl, ctrl->ndx);
+
mipi = &pdata->panel_info.mipi;
- pr_debug("%s:%d, debug info\n", __func__, __LINE__);
+ mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf,
+ &dsi_tear_off_cmd, 1);
- if (mipi->mode == DSI_VIDEO_MODE) {
+ if (ctrl->off_cmds->size)
mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf,
- ctrl_pdata->off_cmds->buf,
- ctrl_pdata->off_cmds->size);
- } else {
- pr_debug("%s:%d, CMD mode not supported", __func__, __LINE__);
- return -EINVAL;
- }
+ ctrl->off_cmds->buf,
+ ctrl->off_cmds->size);
return 0;
}
static int mdss_panel_parse_dt(struct platform_device *pdev,
- struct mdss_panel_common_pdata *panel_data,
- char *bl_ctrl)
+ struct mdss_panel_common_pdata *panel_data)
{
struct device_node *np = pdev->dev.of_node;
u32 res[6], tmp;
+ u32 fbc_res[7];
int rc, i, len;
int cmd_plen, data_offset;
const char *data;
@@ -169,6 +235,7 @@
static const char *on_cmds_state, *off_cmds_state;
char *on_cmds = NULL, *off_cmds = NULL;
int num_of_on_cmds = 0, num_of_off_cmds = 0;
+ bool fbc_enabled = false;
rc = of_property_read_u32_array(np, "qcom,mdss-pan-res", res, 2);
if (rc) {
@@ -229,7 +296,32 @@
if ((bl_ctrl_type) && (!strncmp(bl_ctrl_type, "bl_ctrl_wled", 12))) {
led_trigger_register_simple("bkl-trigger", &bl_led_trigger);
pr_debug("%s: SUCCESS-> WLED TRIGGER register\n", __func__);
- *bl_ctrl = BL_WLED;
+
+ panel_data->panel_info.bklt_ctrl = BL_WLED;
+ } else if (!strncmp(bl_ctrl_type, "bl_ctrl_pwm", 11)) {
+ panel_data->panel_info.bklt_ctrl = BL_PWM;
+
+ rc = of_property_read_u32(np, "qcom,dsi-pwm-period", &tmp);
+ if (rc) {
+ pr_err("%s:%d, Error, dsi pwm_period\n",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ panel_data->panel_info.pwm_period = tmp;
+
+ rc = of_property_read_u32(np, "qcom,dsi-lpg-channel", &tmp);
+ if (rc) {
+ pr_err("%s:%d, Error, dsi lpg channel\n",
+ __func__, __LINE__);
+ return -EINVAL;
+ }
+ panel_data->panel_info.pwm_lpg_chan = tmp;
+
+ tmp = of_get_named_gpio(np, "qcom,dsi-pwm-gpio", 0);
+ panel_data->panel_info.pwm_gpio = tmp;
+ } else {
+ pr_debug("%s: Unknown backlight control\n", __func__);
+ panel_data->panel_info.bklt_ctrl = UNKNOWN_CTRL;
}
rc = of_property_read_u32_array(np,
@@ -240,6 +332,13 @@
rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-mode", &tmp);
panel_data->panel_info.mipi.mode = (!rc ? tmp : DSI_VIDEO_MODE);
+ rc = of_property_read_u32(np, "qcom,mdss-vsync-enable", &tmp);
+ panel_data->panel_info.mipi.vsync_enable = (!rc ? tmp : 0);
+
+ rc = of_property_read_u32(np, "qcom,mdss-hw-vsync-mode", &tmp);
+ panel_data->panel_info.mipi.hw_vsync_mode = (!rc ? tmp : 0);
+
+
rc = of_property_read_u32(np,
"qcom,mdss-pan-dsi-h-pulse-mode", &tmp);
panel_data->panel_info.mipi.pulse_mode_hsa_he = (!rc ? tmp : false);
@@ -263,6 +362,26 @@
(!rc ? tmp : DSI_NON_BURST_SYNCH_PULSE);
rc = of_property_read_u32(np,
+ "qcom,mdss-pan-insert-dcs-cmd", &tmp);
+ panel_data->panel_info.mipi.insert_dcs_cmd =
+ (!rc ? tmp : 1);
+
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-wr-mem-continue", &tmp);
+ panel_data->panel_info.mipi.wr_mem_continue =
+ (!rc ? tmp : 0x3c);
+
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-wr-mem-start", &tmp);
+ panel_data->panel_info.mipi.wr_mem_start =
+ (!rc ? tmp : 0x2c);
+
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-te-sel", &tmp);
+ panel_data->panel_info.mipi.te_sel =
+ (!rc ? tmp : 1);
+
+ rc = of_property_read_u32(np,
"qcom,mdss-pan-dsi-dst-format", &tmp);
panel_data->panel_info.mipi.dst_format =
(!rc ? tmp : DSI_VIDEO_DST_FORMAT_RGB888);
@@ -313,6 +432,9 @@
rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-frame-rate", &tmp);
panel_data->panel_info.mipi.frame_rate = (!rc ? tmp : 60);
+ rc = of_property_read_u32(np, "qcom,mdss-pan-clk-rate", &tmp);
+ panel_data->panel_info.clk_rate = (!rc ? tmp : 0);
+
data = of_get_property(np, "qcom,panel-phy-regulatorSettings", &len);
if ((!data) || (len != 7)) {
pr_err("%s:%d, Unable to read Phy regulator settings",
@@ -360,6 +482,53 @@
panel_data->panel_info.mipi.dsi_phy_db = &phy_params;
+ fbc_enabled = of_property_read_bool(np,
+ "qcom,fbc-enabled");
+ if (fbc_enabled) {
+ pr_debug("%s:%d FBC panel enabled.\n", __func__, __LINE__);
+ panel_data->panel_info.fbc.enabled = 1;
+
+ rc = of_property_read_u32_array(np,
+ "qcom,fbc-mode", fbc_res, 7);
+ panel_data->panel_info.fbc.target_bpp =
+ (!rc ? fbc_res[0] : panel_data->panel_info.bpp);
+ panel_data->panel_info.fbc.comp_mode = (!rc ? fbc_res[1] : 0);
+ panel_data->panel_info.fbc.qerr_enable =
+ (!rc ? fbc_res[2] : 0);
+ panel_data->panel_info.fbc.cd_bias = (!rc ? fbc_res[3] : 0);
+ panel_data->panel_info.fbc.pat_enable = (!rc ? fbc_res[4] : 0);
+ panel_data->panel_info.fbc.vlc_enable = (!rc ? fbc_res[5] : 0);
+ panel_data->panel_info.fbc.bflc_enable =
+ (!rc ? fbc_res[6] : 0);
+
+ rc = of_property_read_u32_array(np,
+ "qcom,fbc-budget-ctl", fbc_res, 3);
+ panel_data->panel_info.fbc.line_x_budget =
+ (!rc ? fbc_res[0] : 0);
+ panel_data->panel_info.fbc.block_x_budget =
+ (!rc ? fbc_res[1] : 0);
+ panel_data->panel_info.fbc.block_budget =
+ (!rc ? fbc_res[2] : 0);
+
+ rc = of_property_read_u32_array(np,
+ "qcom,fbc-lossy-mode", fbc_res, 4);
+ panel_data->panel_info.fbc.lossless_mode_thd =
+ (!rc ? fbc_res[0] : 0);
+ panel_data->panel_info.fbc.lossy_mode_thd =
+ (!rc ? fbc_res[1] : 0);
+ panel_data->panel_info.fbc.lossy_rgb_thd =
+ (!rc ? fbc_res[2] : 0);
+ panel_data->panel_info.fbc.lossy_mode_idx =
+ (!rc ? fbc_res[3] : 0);
+
+ } else {
+ pr_debug("%s:%d Panel does not support FBC.\n",
+ __func__, __LINE__);
+ panel_data->panel_info.fbc.enabled = 0;
+ panel_data->panel_info.fbc.target_bpp =
+ panel_data->panel_info.bpp;
+ }
+
data = of_get_property(np, "qcom,panel-on-cmds", &len);
if (!data) {
pr_err("%s:%d, Unable to read ON cmds", __func__, __LINE__);
@@ -533,7 +702,6 @@
int rc = 0;
static struct mdss_panel_common_pdata vendor_pdata;
static const char *panel_name;
- char bl_ctrl = UNKNOWN_CTRL;
pr_debug("%s:%d, debug info id=%d", __func__, __LINE__, pdev->id);
if (!pdev->dev.of_node)
@@ -546,7 +714,7 @@
else
pr_info("%s: Panel Name = %s\n", __func__, panel_name);
- rc = mdss_panel_parse_dt(pdev, &vendor_pdata, &bl_ctrl);
+ rc = mdss_panel_parse_dt(pdev, &vendor_pdata);
if (rc)
return rc;
@@ -554,7 +722,7 @@
vendor_pdata.off = mdss_dsi_panel_off;
vendor_pdata.bl_fnc = mdss_dsi_panel_bl_ctrl;
- rc = dsi_panel_device_register(pdev, &vendor_pdata, bl_ctrl);
+ rc = dsi_panel_device_register(pdev, &vendor_pdata);
if (rc)
return rc;
diff --git a/drivers/video/msm/mdss/mdss_edp.c b/drivers/video/msm/mdss/mdss_edp.c
index 6986117..aea2de0 100644
--- a/drivers/video/msm/mdss/mdss_edp.c
+++ b/drivers/video/msm/mdss/mdss_edp.c
@@ -363,7 +363,7 @@
case MDSS_EVENT_UNBLANK:
rc = mdss_edp_on(pdata);
break;
- case MDSS_EVENT_TIMEGEN_OFF:
+ case MDSS_EVENT_PANEL_OFF:
rc = mdss_edp_off(pdata);
break;
}
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 4e74858..a5903cf 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -45,11 +45,8 @@
#include <mach/board.h>
#include <mach/memory.h>
-#include <mach/msm_memtypes.h>
-#include <mach/iommu_domains.h>
#include "mdss_fb.h"
-#include "mdss_mdp.h"
#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
#define MDSS_FB_NUM 3
@@ -68,6 +65,8 @@
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
};
+static struct msm_mdp_interface *mdp_instance;
+
static int mdss_fb_register(struct msm_fb_data_type *mfd);
static int mdss_fb_open(struct fb_info *info, int user);
static int mdss_fb_release(struct fb_info *info, int user);
@@ -261,6 +260,7 @@
mfd->pdev = pdev;
if (pdata->next)
mfd->split_display = true;
+ mfd->mdp = *mdp_instance;
mutex_init(&mfd->lock);
@@ -272,6 +272,14 @@
if (rc)
return rc;
+ if (mfd->mdp.init_fnc) {
+ rc = mfd->mdp.init_fnc(mfd);
+ if (rc) {
+ pr_err("init_fnc failed\n");
+ return rc;
+ }
+ }
+
rc = pm_runtime_set_active(mfd->fbi->dev);
if (rc < 0)
pr_err("pm_runtime: fail to set active.\n");
@@ -301,11 +309,7 @@
}
}
- rc = mdss_mdp_overlay_init(mfd);
- if (rc)
- pr_err("unable to init overlay\n");
-
- return 0;
+ return rc;
}
static int mdss_fb_remove(struct platform_device *pdev)
@@ -503,24 +507,6 @@
static int unset_bl_level, bl_updated;
static int bl_level_old;
-static int mdss_bl_scale_config(struct msm_fb_data_type *mfd,
- struct mdp_bl_scale_data *data)
-{
- int ret = 0;
- int curr_bl;
- mutex_lock(&mfd->lock);
- curr_bl = mfd->bl_level;
- mfd->bl_scale = data->scale;
- mfd->bl_min_lvl = data->min_lvl;
- pr_debug("update scale = %d, min_lvl = %d\n", mfd->bl_scale,
- mfd->bl_min_lvl);
-
- /* update current backlight to use new scaling*/
- mdss_fb_set_backlight(mfd, curr_bl);
- mutex_unlock(&mfd->lock);
- return ret;
-}
-
static void mdss_fb_scale_bl(struct msm_fb_data_type *mfd, u32 *bl_lvl)
{
u32 temp = *bl_lvl;
@@ -601,9 +587,8 @@
switch (blank_mode) {
case FB_BLANK_UNBLANK:
- if (!mfd->panel_power_on) {
- msleep(20);
- ret = mfd->on_fnc(mfd);
+ if (!mfd->panel_power_on && mfd->mdp.on_fnc) {
+ ret = mfd->mdp.on_fnc(mfd);
if (ret == 0)
mfd->panel_power_on = true;
}
@@ -614,7 +599,7 @@
case FB_BLANK_NORMAL:
case FB_BLANK_POWERDOWN:
default:
- if (mfd->panel_power_on) {
+ if (mfd->panel_power_on && mfd->mdp.off_fnc) {
int curr_pwr_state;
del_timer(&mfd->no_update.timer);
@@ -625,8 +610,7 @@
mfd->panel_power_on = false;
bl_updated = 0;
- msleep(20);
- ret = mfd->off_fnc(mfd);
+ ret = mfd->mdp.off_fnc(mfd);
if (ret)
mfd->panel_power_on = curr_pwr_state;
else
@@ -731,28 +715,11 @@
static int mdss_fb_alloc_fbmem(struct msm_fb_data_type *mfd)
{
- void *virt = NULL;
- unsigned long phys = 0;
- size_t size;
- u32 yres = mfd->fbi->var.yres_virtual;
-
- size = PAGE_ALIGN(mfd->fbi->fix.line_length * yres);
-
- if (mfd->index == 0) {
- if (mdss_mdp_alloc_fb_mem(mfd, size, (u32 *)&phys, &virt))
- return -ENOMEM;
- pr_info("allocating %u bytes at %p (%lx phys) for fb %d\n",
- size, virt, phys, mfd->index);
- } else {
- pr_debug("no memory allocated for fb%d\n", mfd->index);
- size = 0;
+ if (!mfd->mdp.fb_mem_alloc_fnc) {
+ pr_err("no fb memory allocator function defined\n");
+ return -ENOMEM;
}
-
- mfd->fbi->screen_base = virt;
- mfd->fbi->fix.smem_start = phys;
- mfd->fbi->fix.smem_len = size;
-
- return 0;
+ return mfd->mdp.fb_mem_alloc_fnc(mfd);
}
static int mdss_fb_register(struct msm_fb_data_type *mfd)
@@ -899,7 +866,11 @@
var->xres *= 2;
fix->type = panel_info->is_3d_panel;
- fix->line_length = mdss_mdp_fb_stride(mfd->index, var->xres, bpp);
+ if (mfd->mdp.fb_stride)
+ fix->line_length = mfd->mdp.fb_stride(mfd->index, var->xres,
+ bpp);
+ else
+ fix->line_length = var->xres * bpp;
var->yres = panel_info->yres;
var->xres_virtual = var->xres;
@@ -949,15 +920,13 @@
pr_err("error: not enough memory!\n");
return -ENOMEM;
}
- if (mfd->lut_update) {
- ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
- if (ret)
- pr_err("fb_alloc_cmap() failed!\n");
- }
+
+ ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
+ if (ret)
+ pr_err("fb_alloc_cmap() failed!\n");
if (register_framebuffer(fbi) < 0) {
- if (mfd->lut_update)
- fb_dealloc_cmap(&fbi->cmap);
+ fb_dealloc_cmap(&fbi->cmap);
mfd->op_enable = false;
return -EPERM;
@@ -1200,8 +1169,8 @@
(var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
mdss_fb_wait_for_fence(mfd);
- if (mfd->dma_fnc)
- mfd->dma_fnc(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);
@@ -1238,7 +1207,8 @@
if (fb_backup->disp_commit.flags &
MDP_DISPLAY_COMMIT_OVERLAY) {
mdss_fb_wait_for_fence(mfd);
- mdss_mdp_overlay_kickoff(mfd->ctl);
+ if (mfd->mdp.kickoff_fnc)
+ mfd->mdp.kickoff_fnc(mfd);
mdss_fb_signal_timeline(mfd);
} else {
var = &fb_backup->disp_commit.var;
@@ -1403,8 +1373,14 @@
return -EINVAL;
}
- mfd->fbi->fix.line_length = mdss_mdp_fb_stride(mfd->index, var->xres,
+
+ if (mfd->mdp.fb_stride)
+ mfd->fbi->fix.line_length = mfd->mdp.fb_stride(mfd->index,
+ var->xres,
var->bits_per_pixel / 8);
+ else
+ mfd->fbi->fix.line_length = var->xres * var->bits_per_pixel / 8;
+
if (mfd->panel_reconfig || (mfd->fb_imgType != old_imgType)) {
mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info, mfd->op_enable);
@@ -1422,14 +1398,14 @@
struct fb_cursor cursor;
int ret;
- if (!mfd->cursor_update)
+ if (!mfd->mdp.cursor_update)
return -ENODEV;
ret = copy_from_user(&cursor, p, sizeof(cursor));
if (ret)
return ret;
- return mfd->cursor_update(mfd, &cursor);
+ return mfd->mdp.cursor_update(mfd, &cursor);
}
static int mdss_fb_set_lut(struct fb_info *info, void __user *p)
@@ -1438,86 +1414,17 @@
struct fb_cmap cmap;
int ret;
- if (!mfd->lut_update)
+ if (!mfd->mdp.lut_update)
return -ENODEV;
ret = copy_from_user(&cmap, p, sizeof(cmap));
if (ret)
return ret;
- mfd->lut_update(mfd, &cmap);
+ mfd->mdp.lut_update(mfd, &cmap);
return 0;
}
-static int mdss_fb_handle_pp_ioctl(struct msm_fb_data_type *mfd,
- void __user *argp)
-{
- int ret;
- struct msmfb_mdp_pp mdp_pp;
- u32 copyback = 0;
-
- ret = copy_from_user(&mdp_pp, argp, sizeof(mdp_pp));
- if (ret)
- return ret;
-
- switch (mdp_pp.op) {
- case mdp_op_pa_cfg:
- ret = mdss_mdp_pa_config(mfd->ctl, &mdp_pp.data.pa_cfg_data,
- ©back);
- break;
-
- case mdp_op_pcc_cfg:
- ret = mdss_mdp_pcc_config(mfd->ctl, &mdp_pp.data.pcc_cfg_data,
- ©back);
- break;
-
- case mdp_op_lut_cfg:
- switch (mdp_pp.data.lut_cfg_data.lut_type) {
- case mdp_lut_igc:
- ret = mdss_mdp_igc_lut_config(mfd->ctl,
- (struct mdp_igc_lut_data *)
- &mdp_pp.data.lut_cfg_data.data,
- ©back);
- break;
-
- case mdp_lut_pgc:
- ret = mdss_mdp_argc_config(mfd->ctl,
- &mdp_pp.data.lut_cfg_data.data.pgc_lut_data,
- ©back);
- break;
-
- case mdp_lut_hist:
- ret = mdss_mdp_hist_lut_config(mfd->ctl,
- (struct mdp_hist_lut_data *)
- &mdp_pp.data.lut_cfg_data.data, ©back);
- break;
-
- default:
- ret = -ENOTSUPP;
- break;
- }
- break;
- case mdp_op_dither_cfg:
- ret = mdss_mdp_dither_config(mfd->ctl,
- &mdp_pp.data.dither_cfg_data, ©back);
- break;
- case mdp_op_gamut_cfg:
- ret = mdss_mdp_gamut_config(mfd->ctl,
- &mdp_pp.data.gamut_cfg_data, ©back);
- break;
- case mdp_bl_scale_cfg:
- ret = mdss_bl_scale_config(mfd, (struct mdp_bl_scale_data *)
- &mdp_pp.data.bl_scale_data);
- break;
- default:
- pr_err("Unsupported request to MDP_PP IOCTL.\n");
- ret = -EINVAL;
- break;
- }
- if ((ret == 0) && copyback)
- ret = copy_to_user(argp, &mdp_pp, sizeof(struct msmfb_mdp_pp));
- return ret;
-}
static int mdss_fb_handle_buf_sync_ioctl(struct msm_fb_data_type *mfd,
struct mdp_buf_sync *buf_sync)
{
@@ -1618,74 +1525,15 @@
return ret;
}
-static int mdss_fb_set_metadata(struct msm_fb_data_type *mfd,
- struct msmfb_metadata *metadata)
-{
- int ret = 0;
- switch (metadata->op) {
- case metadata_op_vic:
- if (mfd->panel_info)
- mfd->panel_info->vic =
- metadata->data.video_info_code;
- else
- ret = -EINVAL;
- break;
- default:
- pr_warn("unsupported request to MDP META IOCTL\n");
- ret = -EINVAL;
- break;
- }
- return ret;
-}
-
-static int mdss_fb_get_hw_caps(struct msm_fb_data_type *mfd,
- struct mdss_hw_caps *caps)
-{
- struct mdss_data_type *mdata = mfd->mdata;
-
- if (!mdata)
- return -ENODEV;
-
- caps->mdp_rev = mdata->mdp_rev;
- caps->vig_pipes = mdata->nvig_pipes;
- caps->rgb_pipes = mdata->nrgb_pipes;
- caps->dma_pipes = mdata->ndma_pipes;
-
- return 0;
-}
-
-static int mdss_fb_get_metadata(struct msm_fb_data_type *mfd,
- struct msmfb_metadata *metadata)
-{
- int ret = 0;
- switch (metadata->op) {
- case metadata_op_frame_rate:
- metadata->data.panel_frame_rate =
- mdss_get_panel_framerate(mfd);
- break;
- case metadata_op_get_caps:
- ret = mdss_fb_get_hw_caps(mfd, &metadata->data.caps);
- break;
- default:
- pr_warn("Unsupported request to MDP META IOCTL.\n");
- ret = -EINVAL;
- break;
- }
- return ret;
-}
static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
void __user *argp = (void __user *)arg;
- struct mdp_histogram_data hist;
- struct mdp_histogram_start_req hist_req;
- u32 block, hist_data_addr = 0;
struct mdp_page_protection fb_page_protection;
int ret = -ENOSYS;
struct mdp_buf_sync buf_sync;
- struct msmfb_metadata metadata;
mdss_fb_power_setting_idle(mfd);
@@ -1700,43 +1548,6 @@
ret = mdss_fb_set_lut(info, argp);
break;
- case MSMFB_HISTOGRAM:
- if (!mfd->panel_power_on)
- return -EPERM;
-
- ret = copy_from_user(&hist, argp, sizeof(hist));
- if (ret)
- return ret;
-
- ret = mdss_mdp_hist_collect(mfd->ctl, &hist, &hist_data_addr);
- if ((ret == 0) && hist_data_addr) {
- ret = copy_to_user(hist.c0, (u32 *)hist_data_addr,
- sizeof(u32) * hist.bin_cnt);
- if (ret == 0)
- ret = copy_to_user(argp, &hist,
- sizeof(hist));
- }
- break;
-
- case MSMFB_HISTOGRAM_START:
- if (!mfd->panel_power_on)
- return -EPERM;
-
- ret = copy_from_user(&hist_req, argp, sizeof(hist_req));
- if (ret)
- return ret;
-
- ret = mdss_mdp_histogram_start(mfd->ctl, &hist_req);
- break;
-
- case MSMFB_HISTOGRAM_STOP:
- ret = copy_from_user(&block, argp, sizeof(int));
- if (ret)
- return ret;
-
- ret = mdss_mdp_histogram_stop(mfd->ctl, block);
- break;
-
case MSMFB_GET_PAGE_PROTECTION:
fb_page_protection.page_protection =
mfd->mdp_fb_page_protection;
@@ -1746,10 +1557,6 @@
return ret;
break;
- case MSMFB_MDP_PP:
- ret = mdss_fb_handle_pp_ioctl(mfd, argp);
- break;
-
case MSMFB_BUFFER_SYNC:
ret = copy_from_user(&buf_sync, argp, sizeof(buf_sync));
if (ret)
@@ -1769,25 +1576,9 @@
ret = mdss_fb_display_commit(info, argp);
break;
- case MSMFB_METADATA_SET:
- ret = copy_from_user(&metadata, argp, sizeof(metadata));
- if (ret)
- return ret;
- ret = mdss_fb_set_metadata(mfd, &metadata);
- break;
-
- case MSMFB_METADATA_GET:
- ret = copy_from_user(&metadata, argp, sizeof(metadata));
- if (ret)
- return ret;
- ret = mdss_fb_get_metadata(mfd, &metadata);
- if (!ret)
- ret = copy_to_user(argp, &metadata, sizeof(metadata));
- break;
-
default:
- if (mfd->ioctl_handler)
- ret = mfd->ioctl_handler(mfd, cmd, argp);
+ if (mfd->mdp.ioctl_handler)
+ ret = mfd->mdp.ioctl_handler(mfd, cmd, argp);
break;
}
@@ -1853,6 +1644,11 @@
return -ENODEV;
}
+ if (!mdp_instance) {
+ pr_err("mdss mdp resource not initialized yet\n");
+ return -ENODEV;
+ }
+
node = of_parse_phandle(pdev->dev.of_node, "qcom,mdss-fb-map", 0);
if (!node) {
pr_err("Unable to find fb node for device: %s\n",
@@ -1876,23 +1672,27 @@
fb_pdev->dev.platform_data = pdata;
}
- /*
- * Clocks are already on if continuous splash is enabled,
- * increasing ref_cnt to help balance clocks once done.
- */
- if (pdata->panel_info.cont_splash_enabled) {
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
- mdss_mdp_footswitch_ctrl_splash(1);
- mdss_mdp_copy_splash_screen(pdata);
- }
+ if (mdp_instance->panel_register_done)
+ mdp_instance->panel_register_done(pdata);
mdss_notfound:
of_node_put(node);
-
return rc;
}
EXPORT_SYMBOL(mdss_register_panel);
+int mdss_fb_register_mdp_instance(struct msm_mdp_interface *mdp)
+{
+ if (mdp_instance) {
+ pr_err("multiple MDP instance registration");
+ return -EINVAL;
+ }
+
+ mdp_instance = mdp;
+ return 0;
+}
+EXPORT_SYMBOL(mdss_fb_register_mdp_instance);
+
int mdss_fb_get_phys_info(unsigned long *start, unsigned long *len, int fb_num)
{
struct fb_info *info;
@@ -1929,4 +1729,4 @@
return 0;
}
-device_initcall_sync(mdss_fb_init);
+module_init(mdss_fb_init);
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index db2e305..fdbbea9 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -19,7 +19,6 @@
#include <linux/msm_mdp.h>
#include <linux/types.h>
-#include "mdss_mdp.h"
#include "mdss_panel.h"
#define MSM_FB_DEFAULT_PAGE_SIZE 2
@@ -53,6 +52,26 @@
struct mutex lock;
};
+struct msm_fb_data_type;
+
+struct msm_mdp_interface {
+ int (*fb_mem_alloc_fnc)(struct msm_fb_data_type *mfd);
+ int (*init_fnc)(struct msm_fb_data_type *mfd);
+ int (*on_fnc)(struct msm_fb_data_type *mfd);
+ int (*off_fnc)(struct msm_fb_data_type *mfd);
+ int (*kickoff_fnc)(struct msm_fb_data_type *mfd);
+ 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,
+ struct fb_cursor *cursor);
+ int (*lut_update)(struct msm_fb_data_type *mfd, struct fb_cmap *cmap);
+ int (*do_histogram)(struct msm_fb_data_type *mfd,
+ struct mdp_histogram *hist);
+ int (*panel_register_done)(struct mdss_panel_data *pdata);
+ u32 (*fb_stride)(u32 fb_index, u32 xres, int bpp);
+ void *private1;
+};
+
struct msm_fb_data_type {
u32 key;
u32 index;
@@ -71,30 +90,9 @@
int panel_reconfig;
u32 dst_format;
- int vsync_pending;
- ktime_t vsync_time;
- struct completion vsync_comp;
- spinlock_t vsync_lock;
- int borderfill_enable;
-
- int hw_refresh;
-
- int overlay_play_enable;
-
int panel_power_on;
struct disp_info_type_suspend suspend;
- int (*on_fnc) (struct msm_fb_data_type *mfd);
- int (*off_fnc) (struct msm_fb_data_type *mfd);
- int (*kickoff_fnc) (struct mdss_mdp_ctl *ctl);
- 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,
- struct fb_cursor *cursor);
- int (*lut_update) (struct msm_fb_data_type *mfd, struct fb_cmap *cmap);
- int (*do_histogram) (struct msm_fb_data_type *mfd,
- struct mdp_histogram *hist);
-
struct ion_handle *ihdl;
unsigned long iova;
void *cursor_buf;
@@ -105,21 +103,16 @@
u32 bl_scale;
u32 bl_min_lvl;
struct mutex lock;
- struct mutex ov_lock;
struct platform_device *pdev;
u32 mdp_fb_page_protection;
- struct mdss_data_type *mdata;
- struct mdss_mdp_ctl *ctl;
- struct mdss_mdp_wb *wb;
- struct list_head overlay_list;
- struct list_head pipes_used;
- struct list_head pipes_cleanup;
struct disp_info_notify update;
struct disp_info_notify no_update;
+ struct msm_mdp_interface mdp;
+
u32 acq_fen_cnt;
struct sync_fence *acq_fen[MDP_MAX_FENCE_FD];
int cur_rel_fen_fd;
@@ -150,5 +143,5 @@
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);
-
+int mdss_fb_register_mdp_instance(struct msm_mdp_interface *mdp);
#endif /* MDSS_FB_H */
diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c
index 08be337..e87f028 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_edid.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -244,14 +244,14 @@
continue;
if (ret > 0)
ret += snprintf(buf+ret, PAGE_SIZE-ret, ",%d",
- *video_mode++ + 1);
+ *video_mode++);
else
ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d",
- *video_mode++ + 1);
+ *video_mode++);
}
} else {
ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d",
- edid_ctrl->video_resolution+1);
+ edid_ctrl->video_resolution);
}
DEV_DBG("%s: '%s'\n", __func__, buf);
@@ -324,16 +324,16 @@
buff_3d);
if (ret > 0)
ret += snprintf(buf+ret, PAGE_SIZE-ret,
- ",%d=%s", *video_mode++ + 1,
+ ",%d=%s", *video_mode++,
buff_3d);
else
ret += snprintf(buf+ret, PAGE_SIZE-ret,
- "%d=%s", *video_mode++ + 1,
+ "%d=%s", *video_mode++,
buff_3d);
}
} else {
ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d",
- edid_ctrl->video_resolution+1);
+ edid_ctrl->video_resolution);
}
DEV_DBG("%s: '%s'\n", __func__, buf);
@@ -817,25 +817,25 @@
hdmi_get_video_3d_fmt_2string(video_3d_format, string);
DEV_DBG("%s: EDID[3D]: format: %d [%s], %s %s\n", __func__,
- video_format, hdmi_get_video_fmt_2string(video_format),
+ video_format, msm_hdmi_mode_2string(video_format),
string, added ? "added" : "NOT added");
} /* hdmi_edid_add_sink_3d_format */
static void hdmi_edid_add_sink_video_format(
struct hdmi_edid_sink_data *sink_data, u32 video_format)
{
- const struct hdmi_disp_mode_timing_type *timing =
+ const struct msm_hdmi_mode_timing_info *timing =
hdmi_get_supported_mode(video_format);
u32 supported = timing != NULL;
if (video_format >= HDMI_VFRMT_MAX) {
DEV_ERR("%s: video format: %s is not supported\n", __func__,
- hdmi_get_video_fmt_2string(video_format));
+ msm_hdmi_mode_2string(video_format));
return;
}
DEV_DBG("%s: EDID: format: %d [%s], %s\n", __func__,
- video_format, hdmi_get_video_fmt_2string(video_format),
+ video_format, msm_hdmi_mode_2string(video_format),
supported ? "Supported" : "Not-Supported");
if (supported) {
@@ -1050,7 +1050,7 @@
* while the Video identification code is 1 based in the
* CEA_861D spec
*/
- video_format = (*svd & 0x7F) - 1;
+ video_format = (*svd & 0x7F);
hdmi_edid_add_sink_video_format(sink_data,
video_format);
/* Make a note of the preferred video format */
@@ -1096,7 +1096,7 @@
DEV_DBG("[%s:%d] Block-0 Adding vid fmt = [%s]\n",
__func__, __LINE__,
- hdmi_get_video_fmt_2string(video_format));
+ msm_hdmi_mode_2string(video_format));
hdmi_edid_add_sink_video_format(sink_data,
video_format);
@@ -1125,7 +1125,7 @@
DEV_DBG("[%s:%d] Block-0 Adding vid fmt = [%s]\n",
__func__, __LINE__,
- hdmi_get_video_fmt_2string(video_format));
+ msm_hdmi_mode_2string(video_format));
hdmi_edid_add_sink_video_format(sink_data,
video_format);
@@ -1158,7 +1158,7 @@
DEV_DBG("[%s:%d] Block-1 Adding vid fmt = [%s]\n",
__func__, __LINE__,
- hdmi_get_video_fmt_2string(video_format));
+ msm_hdmi_mode_2string(video_format));
hdmi_edid_add_sink_video_format(sink_data,
video_format);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index b93efd9..66936e5 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -207,7 +207,7 @@
{
int new_vic = -1;
u32 h_total, v_total;
- struct hdmi_disp_mode_timing_type timing;
+ struct msm_hdmi_mode_timing_info timing;
if (!hdmi_ctrl || !pinfo) {
DEV_ERR("%s: invalid input\n", __func__);
@@ -215,13 +215,13 @@
}
if (pinfo->vic) {
- if (hdmi_get_supported_mode(pinfo->vic - 1)) {
- new_vic = pinfo->vic - 1;
+ if (hdmi_get_supported_mode(pinfo->vic)) {
+ new_vic = pinfo->vic;
DEV_DBG("%s: %s is supported\n", __func__,
- hdmi_get_video_fmt_2string(new_vic));
+ msm_hdmi_mode_2string(new_vic));
} else {
- DEV_ERR("%s: invalid or not supported vic\n",
- __func__);
+ DEV_ERR("%s: invalid or not supported vic %d\n",
+ __func__, pinfo->vic);
return -EPERM;
}
} else {
@@ -397,13 +397,133 @@
return ret;
} /* hdmi_tx_sysfs_wta_hpd */
+static ssize_t hdmi_tx_sysfs_wta_vendor_name(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ ssize_t ret;
+ u8 *s = (u8 *) buf;
+ u8 *d = NULL;
+ struct hdmi_tx_ctrl *hdmi_ctrl =
+ hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ d = hdmi_ctrl->spd_vendor_name;
+ ret = strnlen(buf, PAGE_SIZE);
+ ret = (ret > 8) ? 8 : ret;
+
+ memset(hdmi_ctrl->spd_vendor_name, 0, 8);
+ while (*s) {
+ if (*s & 0x60 && *s ^ 0x7f) {
+ *d = *s;
+ } else {
+ /* stop copying if control character found */
+ break;
+ }
+
+ if (++s > (u8 *) (buf + ret))
+ break;
+
+ d++;
+ }
+
+ DEV_DBG("%s: '%s'\n", __func__, hdmi_ctrl->spd_vendor_name);
+
+ return ret;
+} /* hdmi_tx_sysfs_wta_vendor_name */
+
+static ssize_t hdmi_tx_sysfs_rda_vendor_name(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret;
+ struct hdmi_tx_ctrl *hdmi_ctrl =
+ hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = snprintf(buf, PAGE_SIZE, "%s\n", hdmi_ctrl->spd_vendor_name);
+ DEV_DBG("%s: '%s'\n", __func__, hdmi_ctrl->spd_vendor_name);
+
+ return ret;
+} /* hdmi_tx_sysfs_rda_vendor_name */
+
+static ssize_t hdmi_tx_sysfs_wta_product_description(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ ssize_t ret;
+ u8 *s = (u8 *) buf;
+ u8 *d = NULL;
+ struct hdmi_tx_ctrl *hdmi_ctrl =
+ hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ d = hdmi_ctrl->spd_product_description;
+ ret = strnlen(buf, PAGE_SIZE);
+ ret = (ret > 16) ? 16 : ret;
+
+ memset(hdmi_ctrl->spd_product_description, 0, 16);
+ while (*s) {
+ if (*s & 0x60 && *s ^ 0x7f) {
+ *d = *s;
+ } else {
+ /* stop copying if control character found */
+ break;
+ }
+
+ if (++s > (u8 *) (buf + ret))
+ break;
+
+ d++;
+ }
+
+ DEV_DBG("%s: '%s'\n", __func__, hdmi_ctrl->spd_product_description);
+
+ return ret;
+} /* hdmi_tx_sysfs_wta_product_description */
+
+static ssize_t hdmi_tx_sysfs_rda_product_description(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret;
+ struct hdmi_tx_ctrl *hdmi_ctrl =
+ hdmi_tx_get_drvdata_from_sysfs_dev(dev);
+
+ if (!hdmi_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ ret = snprintf(buf, PAGE_SIZE, "%s\n",
+ hdmi_ctrl->spd_product_description);
+ DEV_DBG("%s: '%s'\n", __func__, hdmi_ctrl->spd_product_description);
+
+ return ret;
+} /* hdmi_tx_sysfs_rda_product_description */
+
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);
+static DEVICE_ATTR(vendor_name, S_IRUGO | S_IWUSR,
+ hdmi_tx_sysfs_rda_vendor_name, hdmi_tx_sysfs_wta_vendor_name);
+static DEVICE_ATTR(product_description, S_IRUGO | S_IWUSR,
+ hdmi_tx_sysfs_rda_product_description,
+ hdmi_tx_sysfs_wta_product_description);
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,
NULL,
};
static struct attribute_group hdmi_tx_fs_attrs_group = {
@@ -580,7 +700,7 @@
static int hdmi_tx_init_panel_info(uint32_t resolution,
struct mdss_panel_info *pinfo)
{
- const struct hdmi_disp_mode_timing_type *timing =
+ const struct msm_hdmi_mode_timing_info *timing =
hdmi_get_supported_mode(resolution);
if (!timing || !pinfo) {
@@ -612,42 +732,12 @@
return 0;
} /* hdmi_tx_init_panel_info */
-/* Table indicating the video format supported by the HDMI TX Core */
-/* Valid pclk rates (Mhz): 25.2, 27, 27.03, 74.25, 148.5, 268.5, 297 */
-static void hdmi_tx_setup_video_mode_lut(void)
-{
- hdmi_init_supported_video_timings();
-
- hdmi_set_supported_mode(HDMI_VFRMT_640x480p60_4_3);
- hdmi_set_supported_mode(HDMI_VFRMT_720x480p60_4_3);
- hdmi_set_supported_mode(HDMI_VFRMT_720x480p60_16_9);
- hdmi_set_supported_mode(HDMI_VFRMT_720x576p50_4_3);
- hdmi_set_supported_mode(HDMI_VFRMT_720x576p50_16_9);
- hdmi_set_supported_mode(HDMI_VFRMT_1440x480i60_4_3);
- hdmi_set_supported_mode(HDMI_VFRMT_1440x480i60_16_9);
- hdmi_set_supported_mode(HDMI_VFRMT_1440x576i50_4_3);
- hdmi_set_supported_mode(HDMI_VFRMT_1440x576i50_16_9);
- hdmi_set_supported_mode(HDMI_VFRMT_1280x720p50_16_9);
- hdmi_set_supported_mode(HDMI_VFRMT_1280x720p60_16_9);
- hdmi_set_supported_mode(HDMI_VFRMT_1920x1080p24_16_9);
- hdmi_set_supported_mode(HDMI_VFRMT_1920x1080p25_16_9);
- hdmi_set_supported_mode(HDMI_VFRMT_1920x1080p30_16_9);
- hdmi_set_supported_mode(HDMI_VFRMT_1920x1080p50_16_9);
- hdmi_set_supported_mode(HDMI_VFRMT_1920x1080i60_16_9);
- hdmi_set_supported_mode(HDMI_VFRMT_1920x1080p60_16_9);
- hdmi_set_supported_mode(HDMI_VFRMT_2560x1600p60_16_9);
- hdmi_set_supported_mode(HDMI_VFRMT_3840x2160p30_16_9);
- hdmi_set_supported_mode(HDMI_VFRMT_3840x2160p25_16_9);
- hdmi_set_supported_mode(HDMI_VFRMT_3840x2160p24_16_9);
- hdmi_set_supported_mode(HDMI_VFRMT_4096x2160p24_16_9);
-} /* hdmi_tx_setup_video_mode_lut */
-
/* Table tuned to indicate video formats supported by the MHL Tx */
/* Valid pclk rates (Mhz): 25.2, 27, 27.03, 74.25 */
static void hdmi_tx_setup_mhl_video_mode_lut(struct hdmi_tx_ctrl *hdmi_ctrl)
{
u32 i;
- struct hdmi_disp_mode_timing_type *temp_timing;
+ struct msm_hdmi_mode_timing_info *temp_timing;
if (!hdmi_ctrl->mhl_max_pclk) {
DEV_WARN("%s: mhl max pclk not set!\n", __func__);
@@ -657,7 +747,7 @@
__func__, hdmi_ctrl->mhl_max_pclk);
for (i = 0; i < HDMI_VFRMT_MAX; i++) {
temp_timing =
- (struct hdmi_disp_mode_timing_type *)hdmi_get_supported_mode(i);
+ (struct msm_hdmi_mode_timing_info *)hdmi_get_supported_mode(i);
if (!temp_timing)
continue;
/* formats that exceed max mhl line clk bw */
@@ -765,7 +855,7 @@
struct mdss_panel_info *pinfo)
{
int new_vic = -1;
- const struct hdmi_disp_mode_timing_type *timing = NULL;
+ const struct msm_hdmi_mode_timing_info *timing = NULL;
if (!hdmi_ctrl || !pinfo) {
DEV_ERR("%s: invalid input\n", __func__);
@@ -779,8 +869,8 @@
}
DEV_DBG("%s: switching from %s => %s", __func__,
- hdmi_get_video_fmt_2string(hdmi_ctrl->video_resolution),
- hdmi_get_video_fmt_2string(new_vic));
+ msm_hdmi_mode_2string(hdmi_ctrl->video_resolution),
+ msm_hdmi_mode_2string(new_vic));
hdmi_ctrl->video_resolution = (u32)new_vic;
@@ -808,7 +898,7 @@
u32 end_v = 0;
struct dss_io_data *io = NULL;
- const struct hdmi_disp_mode_timing_type *timing =
+ const struct msm_hdmi_mode_timing_info *timing =
hdmi_get_supported_mode(video_format);
if (timing == NULL) {
DEV_ERR("%s: video format not supported: %d\n", __func__,
@@ -1521,7 +1611,7 @@
acr_pck_ctrl_reg = DSS_REG_R(io, HDMI_ACR_PKT_CTRL);
if (enabled) {
- const struct hdmi_disp_mode_timing_type *timing =
+ const struct msm_hdmi_mode_timing_info *timing =
hdmi_get_supported_mode(hdmi_ctrl->video_resolution);
const struct hdmi_tx_audio_acr_arry *audio_acr =
&hdmi_tx_audio_acr_lut[0];
@@ -2152,7 +2242,7 @@
hdmi_ctrl->hdcp_feature_on = hdcp_feature_on;
- DEV_INFO("power: ON (%s)\n", hdmi_get_video_fmt_2string(
+ DEV_INFO("power: ON (%s)\n", msm_hdmi_mode_2string(
hdmi_ctrl->video_resolution));
rc = hdmi_tx_core_on(hdmi_ctrl);
@@ -2381,7 +2471,7 @@
/* irq enable/disable will be handled in hpd on/off */
hdmi_tx_hw.ptr = (void *)hdmi_ctrl;
- hdmi_tx_setup_video_mode_lut();
+ hdmi_setup_video_mode_lut();
mutex_init(&hdmi_ctrl->mutex);
hdmi_ctrl->workq = create_workqueue("hdmi_tx_workq");
if (!hdmi_ctrl->workq) {
@@ -2539,7 +2629,7 @@
__func__, rc);
break;
- case MDSS_EVENT_TIMEGEN_ON:
+ case MDSS_EVENT_PANEL_ON:
if (hdmi_ctrl->hdcp_feature_on && hdmi_ctrl->present_hdcp) {
DEV_DBG("%s: Starting HDCP authentication\n", __func__);
rc = hdmi_hdcp_authenticate(
@@ -2575,7 +2665,7 @@
}
break;
- case MDSS_EVENT_TIMEGEN_OFF:
+ case MDSS_EVENT_PANEL_OFF:
hdmi_ctrl->timing_gen_on = false;
break;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.c b/drivers/video/msm/mdss/mdss_hdmi_util.c
index 07c2336..0c8b0f8 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.c
@@ -15,38 +15,22 @@
#include <mach/board.h>
#include "mdss_hdmi_util.h"
-static struct hdmi_disp_mode_timing_type
+static struct msm_hdmi_mode_timing_info
hdmi_supported_video_mode_lut[HDMI_VFRMT_MAX];
-#define HDMI_SETUP_LUT(MODE) do { \
- struct hdmi_disp_mode_timing_type mode = HDMI_SETTINGS_##MODE; \
- hdmi_supported_video_mode_lut[mode.video_format] = mode; \
- } while (0)
-
-void hdmi_init_supported_video_timings(void)
-{
- int i;
-
- for (i = 0; i < HDMI_VFRMT_MAX; i++) {
- struct hdmi_disp_mode_timing_type mode = VFRMT_NOT_SUPPORTED(i);
-
- hdmi_supported_video_mode_lut[i] = mode;
- }
-} /* hdmi_init_supported_video_timings */
-
void hdmi_del_supported_mode(u32 mode)
{
- struct hdmi_disp_mode_timing_type *ret = NULL;
+ struct msm_hdmi_mode_timing_info *ret = NULL;
DEV_DBG("%s: removing %s\n", __func__,
- hdmi_get_video_fmt_2string(mode));
+ msm_hdmi_mode_2string(mode));
ret = &hdmi_supported_video_mode_lut[mode];
if (ret != NULL && ret->supported)
ret->supported = false;
}
-const struct hdmi_disp_mode_timing_type *hdmi_get_supported_mode(u32 mode)
+const struct msm_hdmi_mode_timing_info *hdmi_get_supported_mode(u32 mode)
{
- const struct hdmi_disp_mode_timing_type *ret = NULL;
+ const struct msm_hdmi_mode_timing_info *ret = NULL;
if (mode >= HDMI_VFRMT_MAX)
return NULL;
@@ -59,7 +43,7 @@
return ret;
} /* hdmi_get_supported_mode */
-int hdmi_get_video_id_code(struct hdmi_disp_mode_timing_type *timing_in)
+int hdmi_get_video_id_code(struct msm_hdmi_mode_timing_info *timing_in)
{
int i, vic = -1;
@@ -70,7 +54,7 @@
/* active_low_h, active_low_v and interlaced are not checked against */
for (i = 0; i < HDMI_VFRMT_MAX; i++) {
- struct hdmi_disp_mode_timing_type *supported_timing =
+ struct msm_hdmi_mode_timing_info *supported_timing =
&hdmi_supported_video_mode_lut[i];
if (!supported_timing->supported)
@@ -105,155 +89,29 @@
exit:
DEV_DBG("%s: vic = %d timing = %s\n", __func__, vic,
- hdmi_get_video_fmt_2string((u32)vic));
+ msm_hdmi_mode_2string((u32)vic));
return vic;
} /* hdmi_get_video_id_code */
-void hdmi_set_supported_mode(u32 mode)
+/* Table indicating the video format supported by the HDMI TX Core */
+/* Valid pclk rates (Mhz): 25.2, 27, 27.03, 74.25, 148.5, 268.5, 297 */
+void hdmi_setup_video_mode_lut(void)
{
- switch (mode) {
- case HDMI_VFRMT_640x480p60_4_3:
- HDMI_SETUP_LUT(640x480p60_4_3);
- break;
- case HDMI_VFRMT_720x480p60_4_3:
- HDMI_SETUP_LUT(720x480p60_4_3);
- break;
- case HDMI_VFRMT_720x480p60_16_9:
- HDMI_SETUP_LUT(720x480p60_16_9);
- break;
- case HDMI_VFRMT_720x576p50_4_3:
- HDMI_SETUP_LUT(720x576p50_4_3);
- break;
- case HDMI_VFRMT_720x576p50_16_9:
- HDMI_SETUP_LUT(720x576p50_16_9);
- break;
- case HDMI_VFRMT_1440x480i60_4_3:
- HDMI_SETUP_LUT(1440x480i60_4_3);
- break;
- case HDMI_VFRMT_1440x480i60_16_9:
- HDMI_SETUP_LUT(1440x480i60_16_9);
- break;
- case HDMI_VFRMT_1440x576i50_4_3:
- HDMI_SETUP_LUT(1440x576i50_4_3);
- break;
- case HDMI_VFRMT_1440x576i50_16_9:
- HDMI_SETUP_LUT(1440x576i50_16_9);
- break;
- case HDMI_VFRMT_1280x720p50_16_9:
- HDMI_SETUP_LUT(1280x720p50_16_9);
- break;
- case HDMI_VFRMT_1280x720p60_16_9:
- HDMI_SETUP_LUT(1280x720p60_16_9);
- break;
- case HDMI_VFRMT_1920x1080p24_16_9:
- HDMI_SETUP_LUT(1920x1080p24_16_9);
- break;
- case HDMI_VFRMT_1920x1080p25_16_9:
- HDMI_SETUP_LUT(1920x1080p25_16_9);
- break;
- case HDMI_VFRMT_1920x1080p30_16_9:
- HDMI_SETUP_LUT(1920x1080p30_16_9);
- break;
- case HDMI_VFRMT_1920x1080p50_16_9:
- HDMI_SETUP_LUT(1920x1080p50_16_9);
- break;
- case HDMI_VFRMT_1920x1080i60_16_9:
- HDMI_SETUP_LUT(1920x1080i60_16_9);
- break;
- case HDMI_VFRMT_1920x1080p60_16_9:
- HDMI_SETUP_LUT(1920x1080p60_16_9);
- break;
- case HDMI_VFRMT_2560x1600p60_16_9:
- HDMI_SETUP_LUT(2560x1600p60_16_9);
- break;
- case HDMI_VFRMT_3840x2160p30_16_9:
- HDMI_SETUP_LUT(3840x2160p30_16_9);
- break;
- case HDMI_VFRMT_3840x2160p25_16_9:
- HDMI_SETUP_LUT(3840x2160p25_16_9);
- break;
- case HDMI_VFRMT_3840x2160p24_16_9:
- HDMI_SETUP_LUT(3840x2160p24_16_9);
- break;
- case HDMI_VFRMT_4096x2160p24_16_9:
- HDMI_SETUP_LUT(4096x2160p24_16_9);
- break;
- default:
- DEV_ERR("%s: unsupported mode=%d\n", __func__, mode);
- }
-} /* hdmi_set_supported_mode */
+ MSM_HDMI_MODES_INIT_TIMINGS(hdmi_supported_video_mode_lut);
-const char *hdmi_get_video_fmt_2string(u32 format)
-{
- switch (format) {
- case HDMI_VFRMT_640x480p60_4_3: return " 640x 480 p60 4/3";
- case HDMI_VFRMT_720x480p60_4_3: return " 720x 480 p60 4/3";
- case HDMI_VFRMT_720x480p60_16_9: return " 720x 480 p60 16/9";
- case HDMI_VFRMT_1280x720p60_16_9: return "1280x 720 p60 16/9";
- case HDMI_VFRMT_1920x1080i60_16_9: return "1920x1080 i60 16/9";
- case HDMI_VFRMT_1440x480i60_4_3: return "1440x 480 i60 4/3";
- case HDMI_VFRMT_1440x480i60_16_9: return "1440x 480 i60 16/9";
- case HDMI_VFRMT_1440x240p60_4_3: return "1440x 240 p60 4/3";
- case HDMI_VFRMT_1440x240p60_16_9: return "1440x 240 p60 16/9";
- case HDMI_VFRMT_2880x480i60_4_3: return "2880x 480 i60 4/3";
- case HDMI_VFRMT_2880x480i60_16_9: return "2880x 480 i60 16/9";
- case HDMI_VFRMT_2880x240p60_4_3: return "2880x 240 p60 4/3";
- case HDMI_VFRMT_2880x240p60_16_9: return "2880x 240 p60 16/9";
- case HDMI_VFRMT_1440x480p60_4_3: return "1440x 480 p60 4/3";
- case HDMI_VFRMT_1440x480p60_16_9: return "1440x 480 p60 16/9";
- case HDMI_VFRMT_1920x1080p60_16_9: return "1920x1080 p60 16/9";
- case HDMI_VFRMT_720x576p50_4_3: return " 720x 576 p50 4/3";
- case HDMI_VFRMT_720x576p50_16_9: return " 720x 576 p50 16/9";
- case HDMI_VFRMT_1280x720p50_16_9: return "1280x 720 p50 16/9";
- case HDMI_VFRMT_1920x1080i50_16_9: return "1920x1080 i50 16/9";
- case HDMI_VFRMT_1440x576i50_4_3: return "1440x 576 i50 4/3";
- case HDMI_VFRMT_1440x576i50_16_9: return "1440x 576 i50 16/9";
- case HDMI_VFRMT_1440x288p50_4_3: return "1440x 288 p50 4/3";
- case HDMI_VFRMT_1440x288p50_16_9: return "1440x 288 p50 16/9";
- case HDMI_VFRMT_2880x576i50_4_3: return "2880x 576 i50 4/3";
- case HDMI_VFRMT_2880x576i50_16_9: return "2880x 576 i50 16/9";
- case HDMI_VFRMT_2880x288p50_4_3: return "2880x 288 p50 4/3";
- case HDMI_VFRMT_2880x288p50_16_9: return "2880x 288 p50 16/9";
- case HDMI_VFRMT_1440x576p50_4_3: return "1440x 576 p50 4/3";
- case HDMI_VFRMT_1440x576p50_16_9: return "1440x 576 p50 16/9";
- case HDMI_VFRMT_1920x1080p50_16_9: return "1920x1080 p50 16/9";
- case HDMI_VFRMT_1920x1080p24_16_9: return "1920x1080 p24 16/9";
- case HDMI_VFRMT_1920x1080p25_16_9: return "1920x1080 p25 16/9";
- case HDMI_VFRMT_1920x1080p30_16_9: return "1920x1080 p30 16/9";
- case HDMI_VFRMT_2880x480p60_4_3: return "2880x 480 p60 4/3";
- case HDMI_VFRMT_2880x480p60_16_9: return "2880x 480 p60 16/9";
- case HDMI_VFRMT_2880x576p50_4_3: return "2880x 576 p50 4/3";
- case HDMI_VFRMT_2880x576p50_16_9: return "2880x 576 p50 16/9";
- case HDMI_VFRMT_1920x1250i50_16_9: return "1920x1250 i50 16/9";
- case HDMI_VFRMT_1920x1080i100_16_9:return "1920x1080 i100 16/9";
- case HDMI_VFRMT_1280x720p100_16_9: return "1280x 720 p100 16/9";
- case HDMI_VFRMT_720x576p100_4_3: return " 720x 576 p100 4/3";
- case HDMI_VFRMT_720x576p100_16_9: return " 720x 576 p100 16/9";
- case HDMI_VFRMT_1440x576i100_4_3: return "1440x 576 i100 4/3";
- case HDMI_VFRMT_1440x576i100_16_9: return "1440x 576 i100 16/9";
- case HDMI_VFRMT_1920x1080i120_16_9:return "1920x1080 i120 16/9";
- case HDMI_VFRMT_1280x720p120_16_9: return "1280x 720 p120 16/9";
- case HDMI_VFRMT_720x480p120_4_3: return " 720x 480 p120 4/3";
- case HDMI_VFRMT_720x480p120_16_9: return " 720x 480 p120 16/9";
- case HDMI_VFRMT_1440x480i120_4_3: return "1440x 480 i120 4/3";
- case HDMI_VFRMT_1440x480i120_16_9: return "1440x 480 i120 16/9";
- case HDMI_VFRMT_720x576p200_4_3: return " 720x 576 p200 4/3";
- case HDMI_VFRMT_720x576p200_16_9: return " 720x 576 p200 16/9";
- case HDMI_VFRMT_1440x576i200_4_3: return "1440x 576 i200 4/3";
- case HDMI_VFRMT_1440x576i200_16_9: return "1440x 576 i200 16/9";
- case HDMI_VFRMT_720x480p240_4_3: return " 720x 480 p240 4/3";
- case HDMI_VFRMT_720x480p240_16_9: return " 720x 480 p240 16/9";
- case HDMI_VFRMT_1440x480i240_4_3: return "1440x 480 i240 4/3";
- case HDMI_VFRMT_1440x480i240_16_9: return "1440x 480 i240 16/9";
- case HDMI_VFRMT_2560x1600p60_16_9: return "2560x1600 p60 16/9";
- case HDMI_VFRMT_3840x2160p30_16_9: return "3840x2160 p30 16/9";
- case HDMI_VFRMT_3840x2160p25_16_9: return "3840x2160 p25 16/9";
- case HDMI_VFRMT_3840x2160p24_16_9: return "3840x2160 p24 16/9";
- case HDMI_VFRMT_4096x2160p24_16_9: return "4096x2160 p24 16/9";
- default: return "???";
- }
-} /* hdmi_get_video_fmt_2string */
+ /* Add all supported CEA modes to the lut */
+ MSM_HDMI_MODES_SET_SUPP_TIMINGS(
+ hdmi_supported_video_mode_lut, MSM_HDMI_MODES_CEA);
+
+ /* Add all supported extended hdmi modes to the lut */
+ MSM_HDMI_MODES_SET_SUPP_TIMINGS(
+ hdmi_supported_video_mode_lut, MSM_HDMI_MODES_XTND);
+
+ /* Add any other specific DVI timings (DVI modes, etc.) */
+ MSM_HDMI_MODES_SET_TIMING(hdmi_supported_video_mode_lut,
+ HDMI_VFRMT_2560x1600p60_16_9);
+} /* hdmi_setup_video_mode_lut */
const char *hdmi_get_single_video_3d_fmt_2string(u32 format)
{
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.h b/drivers/video/msm/mdss/mdss_hdmi_util.h
index 914aac1..cf42346 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.h
@@ -13,6 +13,7 @@
#ifndef __HDMI_UTIL_H__
#define __HDMI_UTIL_H__
#include "mdss_io_util.h"
+#include "video/msm_hdmi_modes.h"
/* HDMI_TX Registers */
#define HDMI_CTRL (0x00000000)
@@ -218,166 +219,6 @@
#define HDCP_KSV_LSB (0x000060D8)
#define HDCP_KSV_MSB (0x000060DC)
-/* all video formats defined by EIA CEA-861-E */
-#define HDMI_VFRMT_640x480p60_4_3 0
-#define HDMI_VFRMT_720x480p60_4_3 1
-#define HDMI_VFRMT_720x480p60_16_9 2
-#define HDMI_VFRMT_1280x720p60_16_9 3
-#define HDMI_VFRMT_1920x1080i60_16_9 4
-#define HDMI_VFRMT_720x480i60_4_3 5
-#define HDMI_VFRMT_1440x480i60_4_3 HDMI_VFRMT_720x480i60_4_3
-#define HDMI_VFRMT_720x480i60_16_9 6
-#define HDMI_VFRMT_1440x480i60_16_9 HDMI_VFRMT_720x480i60_16_9
-#define HDMI_VFRMT_720x240p60_4_3 7
-#define HDMI_VFRMT_1440x240p60_4_3 HDMI_VFRMT_720x240p60_4_3
-#define HDMI_VFRMT_720x240p60_16_9 8
-#define HDMI_VFRMT_1440x240p60_16_9 HDMI_VFRMT_720x240p60_16_9
-#define HDMI_VFRMT_2880x480i60_4_3 9
-#define HDMI_VFRMT_2880x480i60_16_9 10
-#define HDMI_VFRMT_2880x240p60_4_3 11
-#define HDMI_VFRMT_2880x240p60_16_9 12
-#define HDMI_VFRMT_1440x480p60_4_3 13
-#define HDMI_VFRMT_1440x480p60_16_9 14
-#define HDMI_VFRMT_1920x1080p60_16_9 15
-#define HDMI_VFRMT_720x576p50_4_3 16
-#define HDMI_VFRMT_720x576p50_16_9 17
-#define HDMI_VFRMT_1280x720p50_16_9 18
-#define HDMI_VFRMT_1920x1080i50_16_9 19
-#define HDMI_VFRMT_720x576i50_4_3 20
-#define HDMI_VFRMT_1440x576i50_4_3 HDMI_VFRMT_720x576i50_4_3
-#define HDMI_VFRMT_720x576i50_16_9 21
-#define HDMI_VFRMT_1440x576i50_16_9 HDMI_VFRMT_720x576i50_16_9
-#define HDMI_VFRMT_720x288p50_4_3 22
-#define HDMI_VFRMT_1440x288p50_4_3 HDMI_VFRMT_720x288p50_4_3
-#define HDMI_VFRMT_720x288p50_16_9 23
-#define HDMI_VFRMT_1440x288p50_16_9 HDMI_VFRMT_720x288p50_16_9
-#define HDMI_VFRMT_2880x576i50_4_3 24
-#define HDMI_VFRMT_2880x576i50_16_9 25
-#define HDMI_VFRMT_2880x288p50_4_3 26
-#define HDMI_VFRMT_2880x288p50_16_9 27
-#define HDMI_VFRMT_1440x576p50_4_3 28
-#define HDMI_VFRMT_1440x576p50_16_9 29
-#define HDMI_VFRMT_1920x1080p50_16_9 30
-#define HDMI_VFRMT_1920x1080p24_16_9 31
-#define HDMI_VFRMT_1920x1080p25_16_9 32
-#define HDMI_VFRMT_1920x1080p30_16_9 33
-#define HDMI_VFRMT_2880x480p60_4_3 34
-#define HDMI_VFRMT_2880x480p60_16_9 35
-#define HDMI_VFRMT_2880x576p50_4_3 36
-#define HDMI_VFRMT_2880x576p50_16_9 37
-#define HDMI_VFRMT_1920x1250i50_16_9 38
-#define HDMI_VFRMT_1920x1080i100_16_9 39
-#define HDMI_VFRMT_1280x720p100_16_9 40
-#define HDMI_VFRMT_720x576p100_4_3 41
-#define HDMI_VFRMT_720x576p100_16_9 42
-#define HDMI_VFRMT_720x576i100_4_3 43
-#define HDMI_VFRMT_1440x576i100_4_3 HDMI_VFRMT_720x576i100_4_3
-#define HDMI_VFRMT_720x576i100_16_9 44
-#define HDMI_VFRMT_1440x576i100_16_9 HDMI_VFRMT_720x576i100_16_9
-#define HDMI_VFRMT_1920x1080i120_16_9 45
-#define HDMI_VFRMT_1280x720p120_16_9 46
-#define HDMI_VFRMT_720x480p120_4_3 47
-#define HDMI_VFRMT_720x480p120_16_9 48
-#define HDMI_VFRMT_720x480i120_4_3 49
-#define HDMI_VFRMT_1440x480i120_4_3 HDMI_VFRMT_720x480i120_4_3
-#define HDMI_VFRMT_720x480i120_16_9 50
-#define HDMI_VFRMT_1440x480i120_16_9 HDMI_VFRMT_720x480i120_16_9
-#define HDMI_VFRMT_720x576p200_4_3 51
-#define HDMI_VFRMT_720x576p200_16_9 52
-#define HDMI_VFRMT_720x576i200_4_3 53
-#define HDMI_VFRMT_1440x576i200_4_3 HDMI_VFRMT_720x576i200_4_3
-#define HDMI_VFRMT_720x576i200_16_9 54
-#define HDMI_VFRMT_1440x576i200_16_9 HDMI_VFRMT_720x576i200_16_9
-#define HDMI_VFRMT_720x480p240_4_3 55
-#define HDMI_VFRMT_720x480p240_16_9 56
-#define HDMI_VFRMT_720x480i240_4_3 57
-#define HDMI_VFRMT_1440x480i240_4_3 HDMI_VFRMT_720x480i240_4_3
-#define HDMI_VFRMT_720x480i240_16_9 58
-#define HDMI_VFRMT_1440x480i240_16_9 HDMI_VFRMT_720x480i240_16_9
-/* Video Identification Codes from 65-127 are reserved for the future */
-#define HDMI_VFRMT_END 127
-/* extended video formats */
-#define HDMI_VFRMT_3840x2160p30_16_9 (HDMI_VFRMT_END + 1)
-#define HDMI_VFRMT_3840x2160p25_16_9 (HDMI_VFRMT_END + 2)
-#define HDMI_VFRMT_3840x2160p24_16_9 (HDMI_VFRMT_END + 3)
-#define HDMI_VFRMT_4096x2160p24_16_9 (HDMI_VFRMT_END + 4)
-#define HDMI_EVFRMT_END HDMI_VFRMT_4096x2160p24_16_9
-/* DVI only resolutions */
-#define HDMI_VFRMT_2560x1600p60_16_9 (HDMI_EVFRMT_END + 1)
-#define DVI_VFRMT_END HDMI_VFRMT_2560x1600p60_16_9
-#define HDMI_VFRMT_MAX (DVI_VFRMT_END + 1)
-#define HDMI_VFRMT_FORCE_32BIT 0x7FFFFFFF
-
-#define VFRMT_NOT_SUPPORTED(VFRMT) \
- {VFRMT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false}
-
-#define HDMI_SETTINGS_640x480p60_4_3 \
- {HDMI_VFRMT_640x480p60_4_3, 640, 16, 96, 48, true, \
- 480, 10, 2, 33, true, 25200, 60000, false, true}
-#define HDMI_SETTINGS_720x480p60_4_3 \
- {HDMI_VFRMT_720x480p60_4_3, 720, 16, 62, 60, true, \
- 480, 9, 6, 30, true, 27030, 60000, false, true}
-#define HDMI_SETTINGS_720x480p60_16_9 \
- {HDMI_VFRMT_720x480p60_16_9, 720, 16, 62, 60, true, \
- 480, 9, 6, 30, true, 27030, 60000, false, true}
-#define HDMI_SETTINGS_1280x720p60_16_9 \
- {HDMI_VFRMT_1280x720p60_16_9, 1280, 110, 40, 220, false, \
- 720, 5, 5, 20, false, 74250, 60000, false, true}
-#define HDMI_SETTINGS_1920x1080i60_16_9 \
- {HDMI_VFRMT_1920x1080i60_16_9, 1920, 88, 44, 148, false, \
- 540, 2, 5, 5, false, 74250, 60000, false, true}
-#define HDMI_SETTINGS_1440x480i60_4_3 \
- {HDMI_VFRMT_1440x480i60_4_3, 1440, 38, 124, 114, true, \
- 240, 4, 3, 15, true, 27000, 60000, true, true}
-#define HDMI_SETTINGS_1440x480i60_16_9 \
- {HDMI_VFRMT_1440x480i60_16_9, 1440, 38, 124, 114, true, \
- 240, 4, 3, 15, true, 27000, 60000, true, true}
-#define HDMI_SETTINGS_1920x1080p60_16_9 \
- {HDMI_VFRMT_1920x1080p60_16_9, 1920, 88, 44, 148, false, \
- 1080, 4, 5, 36, false, 148500, 60000, false, true}
-#define HDMI_SETTINGS_720x576p50_4_3 \
- {HDMI_VFRMT_720x576p50_4_3, 720, 12, 64, 68, true, \
- 576, 5, 5, 39, true, 27000, 50000, false, true}
-#define HDMI_SETTINGS_720x576p50_16_9 \
- {HDMI_VFRMT_720x576p50_16_9, 720, 12, 64, 68, true, \
- 576, 5, 5, 39, true, 27000, 50000, false, true}
-#define HDMI_SETTINGS_1280x720p50_16_9 \
- {HDMI_VFRMT_1280x720p50_16_9, 1280, 440, 40, 220, false, \
- 720, 5, 5, 20, false, 74250, 50000, false, true}
-#define HDMI_SETTINGS_1440x576i50_4_3 \
- {HDMI_VFRMT_1440x576i50_4_3, 1440, 24, 126, 138, true, \
- 288, 2, 3, 19, true, 27000, 50000, true, true}
-#define HDMI_SETTINGS_1440x576i50_16_9 \
- {HDMI_VFRMT_1440x576i50_16_9, 1440, 24, 126, 138, true, \
- 288, 2, 3, 19, true, 27000, 50000, true, true}
-#define HDMI_SETTINGS_1920x1080p50_16_9 \
- {HDMI_VFRMT_1920x1080p50_16_9, 1920, 528, 44, 148, false, \
- 1080, 4, 5, 36, false, 148500, 50000, false, true}
-#define HDMI_SETTINGS_1920x1080p24_16_9 \
- {HDMI_VFRMT_1920x1080p24_16_9, 1920, 638, 44, 148, false, \
- 1080, 4, 5, 36, false, 74250, 24000, false, true}
-#define HDMI_SETTINGS_1920x1080p25_16_9 \
- {HDMI_VFRMT_1920x1080p25_16_9, 1920, 528, 44, 148, false, \
- 1080, 4, 5, 36, false, 74250, 25000, false, true}
-#define HDMI_SETTINGS_1920x1080p30_16_9 \
- {HDMI_VFRMT_1920x1080p30_16_9, 1920, 88, 44, 148, false, \
- 1080, 4, 5, 36, false, 74250, 30000, false, true}
-#define HDMI_SETTINGS_2560x1600p60_16_9 \
- {HDMI_VFRMT_2560x1600p60_16_9, 2560, 48, 32, 80, false, \
- 1600, 3, 6, 37, false, 268500, 60000, false, true}
-#define HDMI_SETTINGS_3840x2160p30_16_9 \
- {HDMI_VFRMT_3840x2160p30_16_9, 3840, 176, 88, 296, false, \
- 2160, 8, 10, 72, false, 297000, 30000, false, true}
-#define HDMI_SETTINGS_3840x2160p25_16_9 \
- {HDMI_VFRMT_3840x2160p25_16_9, 3840, 1056, 88, 296, false, \
- 2160, 8, 10, 72, false, 297000, 25000, false, true}
-#define HDMI_SETTINGS_3840x2160p24_16_9 \
- {HDMI_VFRMT_3840x2160p24_16_9, 3840, 1276, 88, 296, false, \
- 2160, 8, 10, 72, false, 297000, 24000, false, true}
-#define HDMI_SETTINGS_4096x2160p24_16_9 \
- {HDMI_VFRMT_4096x2160p24_16_9, 4096, 1020, 88, 296, false, \
- 2160, 8, 10, 72, false, 297000, 24000, false, true}
-
#define TOP_AND_BOTTOM 0x10
#define FRAME_PACKING 0x20
#define SIDE_BY_SIDE_HALF 0x40
@@ -389,26 +230,6 @@
HDMI_TX_FEAT_MAX,
};
-struct hdmi_disp_mode_timing_type {
- u32 video_format;
- u32 active_h;
- u32 front_porch_h;
- u32 pulse_width_h;
- u32 back_porch_h;
- u32 active_low_h;
- u32 active_v;
- u32 front_porch_v;
- u32 pulse_width_v;
- u32 back_porch_v;
- u32 active_low_v;
- /* Must divide by 1000 to get the actual frequency in MHZ */
- u32 pixel_freq;
- /* Must divide by 1000 to get the actual frequency in HZ */
- u32 refresh_rate;
- u32 interlaced;
- u32 supported;
-};
-
struct hdmi_tx_ddc_ctrl {
struct dss_io_data *io;
struct completion ddc_sw_done;
@@ -426,12 +247,10 @@
};
/* video timing related utility routines */
-void hdmi_init_supported_video_timings(void);
-int hdmi_get_video_id_code(struct hdmi_disp_mode_timing_type *timing_in);
-const struct hdmi_disp_mode_timing_type *hdmi_get_supported_mode(u32 mode);
-void hdmi_set_supported_mode(u32 mode);
+void hdmi_setup_video_mode_lut(void);
+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);
-const char *hdmi_get_video_fmt_2string(u32 format);
ssize_t hdmi_get_video_3d_fmt_2string(u32 format, char *buf);
/* todo: Fix this. Right now this is defined in mdss_hdmi_tx.c */
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index 217ac18..8be64b2 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -55,6 +55,12 @@
#include "mdss_debug.h"
struct mdss_data_type *mdss_res;
+struct msm_mdp_interface mdp5 = {
+ .init_fnc = mdss_mdp_overlay_init,
+ .fb_mem_alloc_fnc = mdss_mdp_alloc_fb_mem,
+ .panel_register_done = mdss_panel_register_done,
+ .fb_stride = mdss_mdp_fb_stride,
+};
#define IB_QUOTA 800000000
#define AB_QUOTA 800000000
@@ -129,23 +135,36 @@
static int mdss_mdp_parse_dt_smp(struct platform_device *pdev);
static int mdss_mdp_parse_dt_misc(struct platform_device *pdev);
-int mdss_mdp_alloc_fb_mem(struct msm_fb_data_type *mfd,
- u32 size, u32 *phys, void **virt)
+int mdss_mdp_alloc_fb_mem(struct msm_fb_data_type *mfd)
{
int dom;
- void *fb_virt;
- u32 fb_phys;
- fb_virt = allocate_contiguous_memory(size, MEMTYPE_EBI1, SZ_1M, 0);
- if (!fb_virt) {
- pr_err("unable to alloc fbmem size=%u\n", size);
- return -ENOMEM;
- }
- fb_phys = memory_pool_node_paddr(fb_virt);
- dom = mdss_get_iommu_domain(MDSS_IOMMU_DOMAIN_UNSECURE);
- msm_iommu_map_contig_buffer(fb_phys, dom, 0, size, SZ_4K,
- 0, &(mfd->iova));
- *phys = fb_phys;
- *virt = fb_virt;
+ void *virt = NULL;
+ unsigned long phys = 0;
+ size_t size;
+ u32 yres = mfd->fbi->var.yres_virtual;
+
+ size = PAGE_ALIGN(mfd->fbi->fix.line_length * yres);
+
+ if (mfd->index == 0) {
+ virt = allocate_contiguous_memory(size, MEMTYPE_EBI1, SZ_1M, 0);
+ if (!virt) {
+ pr_err("unable to alloc fbmem size=%u\n", size);
+ return -ENOMEM;
+ }
+ phys = memory_pool_node_paddr(virt);
+ dom = mdss_get_iommu_domain(MDSS_IOMMU_DOMAIN_UNSECURE);
+ msm_iommu_map_contig_buffer(phys, dom, 0, size, SZ_4K, 0,
+ &mfd->iova);
+
+ pr_debug("allocating %u bytes at %p (%lx phys) for fb %d\n",
+ size, virt, phys, mfd->index);
+ } else
+ size = 0;
+
+ mfd->fbi->screen_base = virt;
+ mfd->fbi->fix.smem_start = phys;
+ mfd->fbi->fix.smem_len = size;
+
return 0;
}
@@ -165,14 +184,15 @@
static inline int mdss_irq_dispatch(u32 hw_ndx, int irq, void *ptr)
{
struct mdss_hw *hw;
+ int rc = -ENODEV;
spin_lock(&mdss_lock);
hw = mdss_irq_handlers[hw_ndx];
- spin_unlock(&mdss_lock);
if (hw)
- return hw->irq_handler(irq, hw->ptr);
+ rc = hw->irq_handler(irq, hw->ptr);
+ spin_unlock(&mdss_lock);
- return -ENODEV;
+ return rc;
}
static irqreturn_t mdss_irq_handler(int irq, void *ptr)
@@ -185,8 +205,11 @@
mdata->irq_buzy = true;
- if (intr & MDSS_INTR_MDP)
+ if (intr & MDSS_INTR_MDP) {
+ spin_lock(&mdp_lock);
mdss_irq_dispatch(MDSS_HW_MDP, irq, ptr);
+ spin_unlock(&mdp_lock);
+ }
if (intr & MDSS_INTR_DSI0)
mdss_irq_dispatch(MDSS_HW_DSI0, irq, ptr);
@@ -265,6 +288,7 @@
}
EXPORT_SYMBOL(mdss_disable_irq);
+/* called from interrupt context */
void mdss_disable_irq_nosync(struct mdss_hw *hw)
{
u32 ndx_bit;
@@ -277,7 +301,6 @@
pr_debug("Disable HW=%d irq ena=%d mask=%x\n", hw->hw_ndx,
mdss_res->irq_ena, mdss_res->irq_mask);
- spin_lock(&mdss_lock);
if (!(mdss_res->irq_mask & ndx_bit)) {
pr_warn("MDSS HW ndx=%d is NOT set, mask=%x, hist mask=%x\n",
hw->hw_ndx, mdss_res->mdp_irq_mask,
@@ -290,7 +313,6 @@
disable_irq_nosync(mdss_res->irq);
}
}
- spin_unlock(&mdss_lock);
}
EXPORT_SYMBOL(mdss_disable_irq_nosync);
@@ -371,6 +393,21 @@
return 1 << (intr_type + intf_num);
}
+/* function assumes that mdp is clocked to access hw registers */
+void mdss_mdp_irq_clear(struct mdss_data_type *mdata,
+ u32 intr_type, u32 intf_num)
+{
+ unsigned long irq_flags;
+ u32 irq;
+
+ irq = mdss_mdp_irq_mask(intr_type, intf_num);
+
+ pr_debug("clearing mdp irq mask=%x\n", irq);
+ spin_lock_irqsave(&mdp_lock, irq_flags);
+ writel_relaxed(irq, mdata->mdp_base + MDSS_MDP_REG_INTR_CLEAR);
+ spin_unlock_irqrestore(&mdp_lock, irq_flags);
+}
+
int mdss_mdp_irq_enable(u32 intr_type, u32 intf_num)
{
u32 irq;
@@ -463,13 +500,13 @@
spin_unlock_irqrestore(&mdp_lock, irq_flags);
}
+/* called from interrupt context */
void mdss_mdp_irq_disable_nosync(u32 intr_type, u32 intf_num)
{
u32 irq;
irq = mdss_mdp_irq_mask(intr_type, intf_num);
- spin_lock(&mdp_lock);
if (!(mdss_res->mdp_irq_mask & irq)) {
pr_warn("MDSS MDP IRQ-%x is NOT set, mask=%x\n",
irq, mdss_res->mdp_irq_mask);
@@ -481,7 +518,6 @@
(mdss_res->mdp_hist_irq_mask == 0))
mdss_disable_irq_nosync(&mdss_mdp_hw);
}
- spin_unlock(&mdp_lock);
}
static inline struct clk *mdss_mdp_get_clk(u32 clk_idx)
@@ -574,6 +610,9 @@
}
mdata->clk_ena = enable;
+ if (enable)
+ pm_runtime_get_sync(&mdata->pdev->dev);
+
pr_debug("MDP CLKS %s\n", (enable ? "Enable" : "Disable"));
mb();
@@ -585,6 +624,9 @@
if (mdata->vsync_ena)
mdss_mdp_clk_update(MDSS_CLK_MDP_VSYNC, enable);
+ if (!enable)
+ pm_runtime_put(&mdata->pdev->dev);
+
mutex_unlock(&mdp_clk_lock);
}
@@ -876,13 +918,15 @@
void mdss_mdp_footswitch_ctrl_splash(int on)
{
- if (mdss_res != NULL) {
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ if (mdata != NULL) {
if (on) {
pr_debug("Enable MDP FS for splash.\n");
- regulator_enable(mdss_res->fs);
+ regulator_enable(mdata->fs);
+ mdss_hw_init(mdata);
} else {
pr_debug("Disable MDP FS for splash.\n");
- regulator_disable(mdss_res->fs);
+ regulator_disable(mdata->fs);
}
} else {
pr_warn("mdss mdata not initialized\n");
@@ -994,6 +1038,10 @@
if (!pm_runtime_enabled(&pdev->dev))
mdss_mdp_footswitch_ctrl(mdata, true);
+ rc = mdss_fb_register_mdp_instance(&mdp5);
+ if (rc)
+ pr_err("unable to register mdp instance\n");
+
probe_done:
if (IS_ERR_VALUE(rc)) {
mdss_res = NULL;
@@ -1212,9 +1260,10 @@
static int mdss_mdp_parse_dt_mixer(struct platform_device *pdev)
{
- u32 nmixers, ndspp;
+ u32 nmixers, ndspp, npingpong;
int rc = 0;
- u32 *mixer_offsets = NULL, *dspp_offsets = NULL;
+ u32 *mixer_offsets = NULL, *dspp_offsets = NULL,
+ *pingpong_offsets = NULL;
struct mdss_data_type *mdata = platform_get_drvdata(pdev);
@@ -1224,6 +1273,8 @@
"qcom,mdss-mixer-wb-off");
ndspp = mdss_mdp_parse_dt_prop_len(pdev,
"qcom,mdss-dspp-off");
+ npingpong = mdss_mdp_parse_dt_prop_len(pdev,
+ "qcom,mdss-pingpong-off");
nmixers = mdata->nmixers_intf + mdata->nmixers_wb;
if (mdata->nmixers_intf != ndspp) {
@@ -1231,6 +1282,11 @@
return -EINVAL;
}
+ if (mdata->nmixers_intf != npingpong) {
+ pr_err("device tree err: unequal no of pingpong and intf mixers\n");
+ return -EINVAL;
+ }
+
mixer_offsets = kzalloc(sizeof(u32) * nmixers, GFP_KERNEL);
if (!mixer_offsets) {
pr_err("no mem assigned: kzalloc fail\n");
@@ -1243,6 +1299,12 @@
rc = -ENOMEM;
goto dspp_alloc_fail;
}
+ pingpong_offsets = kzalloc(sizeof(u32) * npingpong, GFP_KERNEL);
+ if (!pingpong_offsets) {
+ pr_err("no mem assigned: kzalloc fail\n");
+ rc = -ENOMEM;
+ goto pingpong_alloc_fail;
+ }
rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-mixer-intf-off",
mixer_offsets, mdata->nmixers_intf);
@@ -1259,19 +1321,26 @@
if (rc)
goto parse_done;
+ rc = mdss_mdp_parse_dt_handler(pdev, "qcom,mdss-pingpong-off",
+ pingpong_offsets, npingpong);
+ if (rc)
+ goto parse_done;
+
rc = mdss_mdp_mixer_addr_setup(mdata, mixer_offsets,
- dspp_offsets, MDSS_MDP_MIXER_TYPE_INTF,
- mdata->nmixers_intf);
+ dspp_offsets, pingpong_offsets,
+ MDSS_MDP_MIXER_TYPE_INTF, mdata->nmixers_intf);
if (rc)
goto parse_done;
rc = mdss_mdp_mixer_addr_setup(mdata, mixer_offsets +
- mdata->nmixers_intf, NULL,
+ mdata->nmixers_intf, NULL, NULL,
MDSS_MDP_MIXER_TYPE_WRITEBACK, mdata->nmixers_wb);
if (rc)
goto parse_done;
parse_done:
+ kfree(pingpong_offsets);
+pingpong_alloc_fail:
kfree(dspp_offsets);
dspp_alloc_fail:
kfree(mixer_offsets);
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 14c1e52..07b083a 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -156,6 +156,7 @@
u32 ref_cnt;
char __iomem *base;
char __iomem *dspp_base;
+ char __iomem *pingpong_base;
u8 type;
u8 params_changed;
u16 width;
@@ -197,6 +198,8 @@
u32 plane_size[MAX_PLANES];
u32 total_size;
u32 ystride[MAX_PLANES];
+ u32 rau_cnt;
+ u32 rau_h[2];
};
struct mdss_mdp_img_data {
@@ -283,6 +286,24 @@
void *priv_data;
};
+struct mdss_overlay_private {
+ int vsync_pending;
+ ktime_t vsync_time;
+ struct completion vsync_comp;
+ spinlock_t vsync_lock;
+ int borderfill_enable;
+ int overlay_play_enable;
+ int hw_refresh;
+
+ struct mdss_data_type *mdata;
+ struct mutex ov_lock;
+ struct mdss_mdp_ctl *ctl;
+ struct mdss_mdp_wb *wb;
+ struct list_head overlay_list;
+ struct list_head pipes_used;
+ struct list_head pipes_cleanup;
+};
+
#define is_vig_pipe(_pipe_id_) ((_pipe_id_) <= MDSS_MDP_SSPP_VIG2)
static inline void mdss_mdp_ctl_write(struct mdss_mdp_ctl *ctl,
u32 reg, u32 val)
@@ -295,9 +316,22 @@
return readl_relaxed(ctl->base + reg);
}
+static inline void mdss_mdp_pingpong_write(struct mdss_mdp_mixer *mixer,
+ u32 reg, u32 val)
+{
+ writel_relaxed(val, mixer->pingpong_base + reg);
+}
+
+static inline u32 mdss_mdp_pingpong_read(struct mdss_mdp_mixer *mixer, u32 reg)
+{
+ return readl_relaxed(mixer->pingpong_base + reg);
+}
+
irqreturn_t mdss_mdp_isr(int irq, void *ptr);
int mdss_iommu_attach(struct mdss_data_type *mdata);
int mdss_mdp_copy_splash_screen(struct mdss_panel_data *pdata);
+void mdss_mdp_irq_clear(struct mdss_data_type *mdata,
+ u32 intr_type, u32 intf_num);
int mdss_mdp_irq_enable(u32 intr_type, u32 intf_num);
void mdss_mdp_irq_disable(u32 intr_type, u32 intf_num);
int mdss_mdp_hist_irq_enable(u32 irq);
@@ -319,11 +353,12 @@
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 mdss_mdp_ctl *ctl);
+int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd);
struct mdss_mdp_ctl *mdss_mdp_ctl_init(struct mdss_panel_data *pdata,
- struct msm_fb_data_type *mfd);
+ struct msm_fb_data_type *mfd);
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);
@@ -400,7 +435,7 @@
int mdss_mdp_pipe_addr_setup(struct mdss_data_type *mdata, u32 *offsets,
u32 *ftch_y_id, u32 type, u32 num_base, u32 len);
int mdss_mdp_mixer_addr_setup(struct mdss_data_type *mdata, u32 *mixer_offsets,
- u32 *dspp_offsets, u32 type, u32 len);
+ u32 *dspp_offsets, u32 *pingpong_offsets, u32 type, u32 len);
int mdss_mdp_ctl_addr_setup(struct mdss_data_type *mdata, u32 *ctl_offsets,
u32 *wb_offsets, u32 len);
@@ -411,17 +446,29 @@
int mdss_mdp_data_check(struct mdss_mdp_data *data,
struct mdss_mdp_plane_sizes *ps);
int mdss_mdp_get_plane_sizes(u32 format, u32 w, u32 h,
- struct mdss_mdp_plane_sizes *ps);
+ struct mdss_mdp_plane_sizes *ps, u32 bwc_mode);
+int mdss_mdp_get_rau_strides(u32 w, u32 h, struct mdss_mdp_format_params *fmt,
+ struct mdss_mdp_plane_sizes *ps);
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);
u32 mdss_get_panel_framerate(struct msm_fb_data_type *mfd);
-int mdss_mdp_wb_kickoff(struct mdss_mdp_ctl *ctl);
+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);
int mdss_mdp_get_ctl_mixers(u32 fb_num, u32 *mixer_id);
-int mdss_mdp_alloc_fb_mem(struct msm_fb_data_type *mfd,
- u32 size, u32 *phys, void **virt);
+int mdss_mdp_alloc_fb_mem(struct msm_fb_data_type *mfd);
u32 mdss_mdp_fb_stride(u32 fb_index, u32 xres, int bpp);
+
+int mdss_panel_register_done(struct mdss_panel_data *pdata);
+
+#define mfd_to_mdp5_data(mfd) (mfd->mdp.private1)
+#define mfd_to_mdata(mfd) (((struct mdss_overlay_private *)\
+ (mfd->mdp.private1))->mdata)
+#define mfd_to_ctl(mfd) (((struct mdss_overlay_private *)\
+ (mfd->mdp.private1))->ctl)
+#define mfd_to_wb(mfd) (((struct mdss_overlay_private *)\
+ (mfd->mdp.private1))->wb)
+
#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 e850321..1ced200 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -200,6 +200,20 @@
total_ib_quota += ib_quota;
if (clk_rate > max_clk_rate)
max_clk_rate = clk_rate;
+
+ if (ctl->intf_type) {
+ struct mdss_panel_info *pinfo;
+
+ pinfo = &ctl->panel_data->panel_info;
+ clk_rate = (ctl->intf_type == MDSS_INTF_DSI) ?
+ pinfo->mipi.dsi_pclk_rate :
+ pinfo->clk_rate;
+
+ /* minimum clock rate due to inefficiency in 3dmux */
+ clk_rate = mult_frac(clk_rate >> 1, 9, 8);
+ if (clk_rate > max_clk_rate)
+ max_clk_rate = clk_rate;
+ }
}
/* request minimum bandwidth to have bus clock on when display is on */
@@ -451,6 +465,54 @@
return NULL;
}
+static int mdss_mdp_ctl_fbc_enable(int enable,
+ struct mdss_mdp_mixer *mixer, struct mdss_panel_info *pdata)
+{
+ struct fbc_panel_info *fbc;
+ u32 mode = 0, budget_ctl = 0, lossy_mode = 0;
+
+ if (!pdata) {
+ pr_err("Invalid pdata\n");
+ return -EINVAL;
+ }
+
+ fbc = &pdata->fbc;
+
+ if (!fbc || !fbc->enabled) {
+ pr_err("Invalid FBC structure\n");
+ return -EINVAL;
+ }
+
+ if (mixer->num == MDSS_MDP_INTF_LAYERMIXER0)
+ pr_debug("Mixer supports FBC.\n");
+ else {
+ pr_debug("Mixer doesn't support FBC.\n");
+ return -EINVAL;
+ }
+
+ if (enable) {
+ mode = ((pdata->xres) << 16) | ((fbc->comp_mode) << 8) |
+ ((fbc->qerr_enable) << 7) | ((fbc->cd_bias) << 4) |
+ ((fbc->pat_enable) << 3) | ((fbc->vlc_enable) << 2) |
+ ((fbc->bflc_enable) << 1) | enable;
+
+ budget_ctl = ((fbc->line_x_budget) << 12) |
+ ((fbc->block_x_budget) << 8) | fbc->block_budget;
+
+ lossy_mode = ((fbc->lossless_mode_thd) << 16) |
+ ((fbc->lossy_mode_thd) << 8) |
+ ((fbc->lossy_rgb_thd) << 3) | fbc->lossy_mode_idx;
+ }
+
+ mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_FBC_MODE, mode);
+ mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_FBC_BUDGET_CTL,
+ budget_ctl);
+ mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_FBC_LOSSY_MODE,
+ lossy_mode);
+
+ return 0;
+}
+
int mdss_mdp_ctl_setup(struct mdss_mdp_ctl *ctl)
{
struct mdss_mdp_ctl *split_ctl;
@@ -575,7 +637,8 @@
struct mdss_mdp_ctl *ctl;
int ret = 0;
- ctl = mdss_mdp_ctl_alloc(mfd->mdata);
+ struct mdss_data_type *mdata = mfd_to_mdata(mfd);
+ ctl = mdss_mdp_ctl_alloc(mdata);
if (!ctl) {
pr_err("unable to allocate ctl\n");
return ERR_PTR(-ENOMEM);
@@ -599,6 +662,15 @@
ctl->opmode = MDSS_MDP_CTL_OP_VIDEO_MODE;
ctl->start_fnc = mdss_mdp_video_start;
break;
+ case MIPI_CMD_PANEL:
+ if (pdata->panel_info.pdest == DISPLAY_1)
+ ctl->intf_num = MDSS_MDP_INTF1;
+ else
+ ctl->intf_num = MDSS_MDP_INTF2;
+ ctl->intf_type = MDSS_INTF_DSI;
+ ctl->opmode = MDSS_MDP_CTL_OP_CMD_MODE;
+ ctl->start_fnc = mdss_mdp_cmd_start;
+ break;
case DTV_PANEL:
ctl->intf_num = MDSS_MDP_INTF3;
ctl->intf_type = MDSS_INTF_HDMI;
@@ -787,6 +859,7 @@
struct mdss_mdp_mixer *mixer;
u32 outsize, temp;
int ret = 0;
+ int i, nmixers;
if (ctl->start_fnc)
ret = ctl->start_fnc(ctl);
@@ -801,6 +874,10 @@
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);
+
mixer = ctl->mixer_left;
mdss_mdp_pp_resume(mixer->num);
mixer->params_changed++;
@@ -812,6 +889,11 @@
outsize = (mixer->height << 16) | mixer->width;
mdp_mixer_write(mixer, MDSS_MDP_REG_LM_OUT_SIZE, outsize);
+ if (ctl->panel_data->panel_info.fbc.enabled) {
+ ret = mdss_mdp_ctl_fbc_enable(1, ctl->mixer_left,
+ &ctl->panel_data->panel_info);
+ }
+
return ret;
}
@@ -821,7 +903,7 @@
int ret = 0;
if (ctl->power_on) {
- pr_debug("%s:%d already on!\n", __func__, __LINE__);
+ pr_debug("%d: panel already on!\n", __LINE__);
return 0;
}
@@ -907,14 +989,6 @@
ctl->power_on = false;
ctl->play_cnt = 0;
ctl->clk_rate = 0;
- if (ctl->mixer_left) {
- mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_LAYER(
- ctl->mixer_left->num), 0);
- }
- if (ctl->mixer_right) {
- mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_LAYER(
- ctl->mixer_right->num), 0);
- }
mdss_mdp_ctl_perf_commit(ctl->mdata, MDSS_MDP_PERF_UPDATE_ALL);
}
@@ -1032,7 +1106,8 @@
}
int mdss_mdp_mixer_addr_setup(struct mdss_data_type *mdata,
- u32 *mixer_offsets, u32 *dspp_offsets, u32 type, u32 len)
+ u32 *mixer_offsets, u32 *dspp_offsets, u32 *pingpong_offsets,
+ u32 type, u32 len)
{
struct mdss_mdp_mixer *head;
u32 i;
@@ -1052,8 +1127,11 @@
head[i].base = mdata->mdp_base + mixer_offsets[i];
head[i].ref_cnt = 0;
head[i].num = i;
- if (type == MDSS_MDP_MIXER_TYPE_INTF)
+ if (type == MDSS_MDP_MIXER_TYPE_INTF) {
head[i].dspp_base = mdata->mdp_base + dspp_offsets[i];
+ head[i].pingpong_base = mdata->mdp_base +
+ pingpong_offsets[i];
+ }
}
switch (type) {
diff --git a/drivers/video/msm/mdss/mdss_mdp_hwio.h b/drivers/video/msm/mdss/mdss_mdp_hwio.h
index 18c38a0..d50f47e 100644
--- a/drivers/video/msm/mdss/mdss_mdp_hwio.h
+++ b/drivers/video/msm/mdss/mdss_mdp_hwio.h
@@ -431,8 +431,6 @@
MDSS_MDP_MAX_PINGPONG
};
-#define MDSS_MDP_REG_PP_OFFSET(pp) (0x21B00 + ((pp) * 0x100))
-
#define MDSS_MDP_REG_PP_TEAR_CHECK_EN 0x000
#define MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC 0x004
#define MDSS_MDP_REG_PP_SYNC_CONFIG_HEIGHT 0x008
@@ -447,6 +445,10 @@
#define MDSS_MDP_REG_PP_LINE_COUNT 0x02C
#define MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG 0x030
+#define MDSS_MDP_REG_PP_FBC_MODE 0x034
+#define MDSS_MDP_REG_PP_FBC_BUDGET_CTL 0x038
+#define MDSS_MDP_REG_PP_FBC_LOSSY_MODE 0x03C
+
#define MDSS_MDP_REG_SMP_ALLOC_W0 0x00180
#define MDSS_MDP_REG_SMP_ALLOC_R0 0x00230
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
new file mode 100644
index 0000000..d6b0fb2
--- /dev/null
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -0,0 +1,333 @@
+/* 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 "mdss_panel.h"
+#include "mdss_mdp.h"
+
+#define START_THRESHOLD 4
+#define CONTINUE_TRESHOLD 4
+
+#define MAX_SESSIONS 2
+
+struct mdss_mdp_cmd_ctx {
+ u32 pp_num;
+ u8 ref_cnt;
+
+ struct completion pp_comp;
+ atomic_t vsync_ref;
+ spinlock_t vsync_lock;
+ mdp_vsync_handler_t vsync_handler;
+ int panel_on;
+
+ /* te config */
+ u8 tear_check;
+ u16 total_lcd_lines;
+ u16 v_porch; /* vertical porches */
+ u32 vsync_cnt;
+};
+
+struct mdss_mdp_cmd_ctx mdss_mdp_cmd_ctx_list[MAX_SESSIONS];
+
+static int mdss_mdp_cmd_tearcheck_cfg(struct mdss_mdp_mixer *mixer,
+ struct mdss_mdp_cmd_ctx *ctx, int enable)
+{
+ u32 cfg;
+
+ cfg = BIT(19); /* VSYNC_COUNTER_EN */
+ if (ctx->tear_check)
+ cfg |= BIT(20); /* VSYNC_IN_EN */
+ cfg |= ctx->vsync_cnt;
+
+ mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg);
+ mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_SYNC_CONFIG_HEIGHT,
+ 0xfff0); /* set to verh height */
+ mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_VSYNC_INIT_VAL, 0);
+ mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_RD_PTR_IRQ, 0);
+
+ mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_START_POS, ctx->v_porch);
+ mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_SYNC_THRESH,
+ (CONTINUE_TRESHOLD << 16) | (START_THRESHOLD));
+
+ mdss_mdp_pingpong_write(mixer, MDSS_MDP_REG_PP_TEAR_CHECK_EN, enable);
+ return 0;
+}
+
+static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_ctl *ctl, int enable)
+{
+ struct mdss_mdp_cmd_ctx *ctx = ctl->priv_data;
+ struct mdss_panel_info *pinfo;
+ struct mdss_mdp_mixer *mixer;
+
+ pinfo = &ctl->panel_data->panel_info;
+
+ if (pinfo->mipi.vsync_enable && enable) {
+ u32 mdp_vsync_clk_speed_hz, total_lines;
+ u32 vsync_cnt_cfg_dem;
+
+ mdss_mdp_vsync_clk_enable(1);
+
+ mdp_vsync_clk_speed_hz =
+ mdss_mdp_get_clk_rate(MDSS_CLK_MDP_VSYNC);
+ pr_debug("%s: vsync_clk_rate=%d\n", __func__,
+ mdp_vsync_clk_speed_hz);
+
+ if (mdp_vsync_clk_speed_hz == 0) {
+ pr_err("can't get clk speed\n");
+ return -EINVAL;
+ }
+
+ ctx->tear_check = pinfo->mipi.hw_vsync_mode;
+
+ total_lines = pinfo->lcdc.v_back_porch +
+ pinfo->lcdc.v_front_porch +
+ pinfo->lcdc.v_pulse_width + pinfo->yres;
+
+ vsync_cnt_cfg_dem =
+ mult_frac(pinfo->mipi.frame_rate * total_lines,
+ 1, 100);
+
+ ctx->vsync_cnt = mdp_vsync_clk_speed_hz / vsync_cnt_cfg_dem;
+
+ ctx->v_porch = pinfo->lcdc.v_back_porch +
+ pinfo->lcdc.v_front_porch +
+ pinfo->lcdc.v_pulse_width;
+ ctx->total_lcd_lines = total_lines;
+ } else {
+ enable = 0;
+ }
+
+ mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT);
+ if (mixer)
+ mdss_mdp_cmd_tearcheck_cfg(mixer, ctx, enable);
+
+ mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_RIGHT);
+ if (mixer)
+ mdss_mdp_cmd_tearcheck_cfg(mixer, ctx, enable);
+
+ return 0;
+}
+
+static inline void cmd_readptr_irq_enable(struct mdss_mdp_ctl *ctl)
+{
+ struct mdss_mdp_cmd_ctx *ctx = ctl->priv_data;
+
+ if (atomic_inc_return(&ctx->vsync_ref) == 1) {
+ pr_debug("%s:\n", __func__);
+ mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctx->pp_num);
+ }
+}
+
+static inline void cmd_readptr_irq_disable(struct mdss_mdp_ctl *ctl)
+{
+ struct mdss_mdp_cmd_ctx *ctx = ctl->priv_data;
+
+ if (atomic_dec_return(&ctx->vsync_ref) == 0) {
+ pr_debug("%s:\n", __func__);
+ mdss_mdp_irq_disable(MDSS_MDP_IRQ_PING_PONG_RD_PTR,
+ ctx->pp_num);
+ }
+}
+
+int mdss_mdp_cmd_set_vsync_handler(struct mdss_mdp_ctl *ctl,
+ mdp_vsync_handler_t vsync_handler)
+{
+ struct mdss_mdp_cmd_ctx *ctx;
+ unsigned long flags;
+
+ ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
+ if (!ctx) {
+ pr_err("invalid ctx for ctl=%d\n", ctl->num);
+ return -ENODEV;
+ }
+
+ spin_lock_irqsave(&ctx->vsync_lock, flags);
+
+ if (!ctx->vsync_handler && vsync_handler) {
+ ctx->vsync_handler = vsync_handler;
+ cmd_readptr_irq_enable(ctl);
+ } else if (ctx->vsync_handler && !vsync_handler) {
+ cmd_readptr_irq_disable(ctl);
+ ctx->vsync_handler = vsync_handler;
+ }
+
+ spin_unlock_irqrestore(&ctx->vsync_lock, flags);
+
+ return 0;
+}
+
+static void mdss_mdp_cmd_readptr_done(void *arg)
+{
+ struct mdss_mdp_ctl *ctl = arg;
+ struct mdss_mdp_cmd_ctx *ctx = ctl->priv_data;
+ ktime_t vsync_time;
+
+ if (!ctx) {
+ pr_err("invalid ctx\n");
+ return;
+ }
+
+ pr_debug("%s: ctl=%d intf_num=%d\n", __func__, ctl->num, ctl->intf_num);
+
+ vsync_time = ktime_get();
+
+ spin_lock(&ctx->vsync_lock);
+ if (ctx->vsync_handler)
+ ctx->vsync_handler(ctl, vsync_time);
+ spin_unlock(&ctx->vsync_lock);
+}
+
+static void mdss_mdp_cmd_pingpong_done(void *arg)
+{
+ struct mdss_mdp_ctl *ctl = arg;
+ struct mdss_mdp_cmd_ctx *ctx = ctl->priv_data;
+
+ pr_debug("%s: intf_num=%d ctx=%p\n", __func__, ctl->intf_num, ctx);
+
+ mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num);
+
+ if (ctx)
+ complete(&ctx->pp_comp);
+}
+
+int mdss_mdp_cmd_kickoff(struct mdss_mdp_ctl *ctl, void *arg)
+{
+ struct mdss_mdp_cmd_ctx *ctx;
+ int rc;
+
+ ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
+ pr_debug("%s: kickoff intf_num=%d ctx=%p\n", __func__,
+ ctl->intf_num, ctx);
+
+ if (!ctx) {
+ pr_err("invalid ctx\n");
+ return -ENODEV;
+ }
+
+ if (ctx->panel_on == 0) {
+ rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_UNBLANK, NULL);
+ WARN(rc, "intf %d unblank error (%d)\n", ctl->intf_num, rc);
+
+ ctx->panel_on++;
+
+ rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_ON, NULL);
+ WARN(rc, "intf %d panel on error (%d)\n", ctl->intf_num, rc);
+ }
+
+ INIT_COMPLETION(ctx->pp_comp);
+ mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num);
+
+ mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_START, 1);
+
+ wait_for_completion_interruptible(&ctx->pp_comp);
+
+ return 0;
+}
+
+int mdss_mdp_cmd_stop(struct mdss_mdp_ctl *ctl)
+{
+ struct mdss_mdp_cmd_ctx *ctx;
+ int ret;
+
+ pr_debug("%s: +\n", __func__);
+
+ ctx = (struct mdss_mdp_cmd_ctx *) ctl->priv_data;
+ if (!ctx) {
+ pr_err("invalid ctx\n");
+ return -ENODEV;
+ }
+
+ ctx->panel_on = 0;
+
+ mdss_mdp_cmd_set_vsync_handler(ctl, NULL);
+
+ mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctl->intf_num,
+ NULL, NULL);
+ mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num,
+ NULL, NULL);
+
+ memset(ctx, 0, sizeof(*ctx));
+ ctl->priv_data = NULL;
+
+ ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_BLANK, NULL);
+ WARN(ret, "intf %d unblank error (%d)\n", ctl->intf_num, ret);
+
+ ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_OFF, NULL);
+ WARN(ret, "intf %d unblank error (%d)\n", ctl->intf_num, ret);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+ pr_debug("%s:-\n", __func__);
+
+ return 0;
+}
+
+int mdss_mdp_cmd_start(struct mdss_mdp_ctl *ctl)
+{
+ struct mdss_mdp_cmd_ctx *ctx;
+ struct mdss_mdp_mixer *mixer;
+ int i, ret;
+
+ pr_debug("%s:+\n", __func__);
+
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+
+ mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT);
+ if (!mixer) {
+ pr_err("mixer not setup correctly\n");
+ return -ENODEV;
+ }
+
+ for (i = 0; i < MAX_SESSIONS; i++) {
+ ctx = &mdss_mdp_cmd_ctx_list[i];
+ if (ctx->ref_cnt == 0) {
+ ctx->ref_cnt++;
+ break;
+ }
+ }
+ if (i == MAX_SESSIONS) {
+ pr_err("too many sessions\n");
+ return -ENOMEM;
+ }
+
+ ctl->priv_data = ctx;
+ if (!ctx) {
+ pr_err("invalid ctx\n");
+ return -ENODEV;
+ }
+
+ ctx->pp_num = mixer->num;
+ init_completion(&ctx->pp_comp);
+ spin_lock_init(&ctx->vsync_lock);
+ atomic_set(&ctx->vsync_ref, 0);
+
+ mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_RD_PTR, ctx->pp_num,
+ mdss_mdp_cmd_readptr_done, ctl);
+
+ mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num,
+ mdss_mdp_cmd_pingpong_done, ctl);
+
+ ret = mdss_mdp_cmd_tearcheck_setup(ctl, 1);
+ if (ret) {
+ pr_err("tearcheck setup failed\n");
+ return ret;
+ }
+
+ ctl->stop_fnc = mdss_mdp_cmd_stop;
+ ctl->display_fnc = mdss_mdp_cmd_kickoff;
+ ctl->set_vsync_handler = mdss_mdp_cmd_set_vsync_handler;
+
+ pr_debug("%s:-\n", __func__);
+
+ return 0;
+}
+
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index dab8674..0426784 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -182,6 +182,9 @@
if (atomic_inc_return(&ctx->vsync_ref) == 1)
mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num);
+ else
+ mdss_mdp_irq_clear(ctl->mdata, MDSS_MDP_IRQ_INTF_VSYNC,
+ ctl->intf_num);
}
static inline void video_vsync_irq_disable(struct mdss_mdp_ctl *ctl)
@@ -197,6 +200,7 @@
{
struct mdss_mdp_video_ctx *ctx;
unsigned long flags;
+ int need_update;
ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
if (!ctx) {
@@ -205,14 +209,18 @@
}
spin_lock_irqsave(&ctx->vsync_lock, flags);
- if (!ctx->vsync_handler && vsync_handler)
- video_vsync_irq_enable(ctl);
- else if (ctx->vsync_handler && !vsync_handler)
- video_vsync_irq_disable(ctl);
-
+ need_update = (!ctx->vsync_handler && vsync_handler) ||
+ (ctx->vsync_handler && !vsync_handler);
ctx->vsync_handler = vsync_handler;
spin_unlock_irqrestore(&ctx->vsync_lock, flags);
+ if (need_update) {
+ if (vsync_handler)
+ video_vsync_irq_enable(ctl);
+ else
+ video_vsync_irq_disable(ctl);
+ }
+
return 0;
}
@@ -242,7 +250,7 @@
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
ctx->timegen_en = false;
- rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_TIMEGEN_OFF, NULL);
+ rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_OFF, NULL);
WARN(rc, "intf %d timegen off error (%d)\n", ctl->intf_num, rc);
mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_UNDER_RUN,
@@ -335,8 +343,8 @@
if (!ctx->wait_pending) {
ctx->wait_pending++;
- INIT_COMPLETION(ctx->vsync_comp);
video_vsync_irq_enable(ctl);
+ INIT_COMPLETION(ctx->vsync_comp);
} else {
WARN(1, "commit without wait! ctl=%d", ctl->num);
}
@@ -359,8 +367,8 @@
rc, ctl->num);
ctx->timegen_en = true;
- rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_TIMEGEN_ON, NULL);
- WARN(rc, "intf %d timegen on error (%d)\n", ctl->intf_num, rc);
+ rc = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_ON, NULL);
+ WARN(rc, "intf %d panel on error (%d)\n", ctl->intf_num, rc);
}
return 0;
@@ -373,6 +381,7 @@
struct mdss_mdp_video_ctx *ctx;
struct mdss_mdp_mixer *mixer;
struct intf_timing_params itp = {0};
+ u32 dst_bpp;
int i;
mdata = ctl->mdata;
@@ -411,19 +420,27 @@
mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_UNDER_RUN, ctl->intf_num,
mdss_mdp_video_underrun_intr_done, ctl);
- itp.width = pinfo->xres + pinfo->lcdc.xres_pad;
+ dst_bpp = pinfo->fbc.enabled ? (pinfo->fbc.target_bpp) : (pinfo->bpp);
+
+ itp.width = mult_frac((pinfo->xres + pinfo->lcdc.xres_pad),
+ dst_bpp, pinfo->bpp);
itp.height = pinfo->yres + pinfo->lcdc.yres_pad;
itp.border_clr = pinfo->lcdc.border_clr;
itp.underflow_clr = pinfo->lcdc.underflow_clr;
itp.hsync_skew = pinfo->lcdc.hsync_skew;
- itp.xres = pinfo->xres;
+ itp.xres = mult_frac(pinfo->xres, dst_bpp, pinfo->bpp);
itp.yres = pinfo->yres;
- itp.h_back_porch = pinfo->lcdc.h_back_porch;
- itp.h_front_porch = pinfo->lcdc.h_front_porch;
- itp.v_back_porch = pinfo->lcdc.v_back_porch;
- itp.v_front_porch = pinfo->lcdc.v_front_porch;
- itp.hsync_pulse_width = pinfo->lcdc.h_pulse_width;
+ itp.h_back_porch = mult_frac(pinfo->lcdc.h_back_porch, dst_bpp,
+ pinfo->bpp);
+ itp.h_front_porch = mult_frac(pinfo->lcdc.h_front_porch, dst_bpp,
+ pinfo->bpp);
+ itp.v_back_porch = mult_frac(pinfo->lcdc.v_back_porch, dst_bpp,
+ pinfo->bpp);
+ itp.v_front_porch = mult_frac(pinfo->lcdc.v_front_porch, dst_bpp,
+ pinfo->bpp);
+ itp.hsync_pulse_width = mult_frac(pinfo->lcdc.h_pulse_width, dst_bpp,
+ pinfo->bpp);
itp.vsync_pulse_width = pinfo->lcdc.v_pulse_width;
if (mdss_mdp_video_timegen_setup(ctx, &itp)) {
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index b7b3c23..7fbb031 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -37,7 +37,7 @@
u16 width;
u16 height;
u8 rot90;
-
+ u32 bwc_mode;
int initialized;
struct mdss_mdp_plane_sizes dst_planes;
@@ -90,6 +90,9 @@
pr_debug("wb_num=%d addr=0x%x\n", ctx->wb_num, data->p[0].addr);
+ if (ctx->bwc_mode)
+ data->bwc_enabled = 1;
+
ret = mdss_mdp_data_check(data, &ctx->dst_planes);
if (ret)
return ret;
@@ -112,7 +115,8 @@
pr_debug("wb_num=%d format=%d\n", ctx->wb_num, ctx->format);
mdss_mdp_get_plane_sizes(ctx->format, ctx->width, ctx->height,
- &ctx->dst_planes);
+ &ctx->dst_planes,
+ ctx->opmode & MDSS_MDP_OP_BWC_EN);
fmt = mdss_mdp_get_format_params(ctx->format);
if (!fmt) {
@@ -252,7 +256,8 @@
if (ctl->mdata->rot_block_size == 128)
ctx->opmode |= BIT(4); /* block size 128 */
- ctx->opmode |= rot->bwc_mode;
+ ctx->bwc_mode = rot->bwc_mode;
+ ctx->opmode |= ctx->bwc_mode;
ctx->width = rot->src_rect.w;
ctx->height = rot->src_rect.h;
@@ -260,12 +265,15 @@
ctx->format = rot->format;
ctx->rot90 = !!(rot->flags & MDP_ROT_90);
+
+ if (ctx->bwc_mode || ctx->rot90)
+ ctx->format = mdss_mdp_get_rotator_dst_format(rot->format);
+ else
+ ctx->format = rot->format;
+
if (ctx->rot90) {
ctx->opmode |= BIT(5); /* ROT 90 */
swap(ctx->width, ctx->height);
- ctx->format = mdss_mdp_get_rotator_dst_format(rot->format);
- } else {
- ctx->format = rot->format;
}
return mdss_mdp_writeback_format_setup(ctx);
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 0749f0c..dae3e05 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -21,6 +21,7 @@
#include <linux/pm_runtime.h>
#include <linux/uaccess.h>
#include <linux/delay.h>
+#include <linux/msm_mdp.h>
#include <mach/iommu_domains.h>
@@ -41,8 +42,9 @@
struct mdp_overlay *req)
{
struct mdss_mdp_pipe *pipe;
+ struct mdss_data_type *mdata = mfd_to_mdata(mfd);
- pipe = mdss_mdp_pipe_get(mfd->mdata, req->id);
+ pipe = mdss_mdp_pipe_get(mdata, req->id);
if (IS_ERR_OR_NULL(pipe)) {
pr_err("invalid pipe ndx=%x\n", req->id);
return pipe ? PTR_ERR(pipe) : -ENODEV;
@@ -60,11 +62,12 @@
{
u32 xres, yres;
u32 min_src_size, min_dst_size;
+ struct mdss_data_type *mdata = mfd_to_mdata(mfd);
xres = mfd->fbi->var.xres;
yres = mfd->fbi->var.yres;
- if (mfd->mdata->mdp_rev >= MDSS_MDP_HW_REV_102) {
+ if (mdata->mdp_rev >= MDSS_MDP_HW_REV_102) {
min_src_size = fmt->is_yuv ? 2 : 1;
min_dst_size = 1;
} else {
@@ -170,11 +173,12 @@
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;
- pr_debug("rot ctl=%u req id=%x\n", mfd->ctl->num, req->id);
+ 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) {
@@ -209,6 +213,7 @@
rot->flags = req->flags & (MDP_ROT_90 | MDP_FLIP_LR | MDP_FLIP_UD |
MDP_SECURE_OVERLAY_SESSION);
+ rot->bwc_mode = (req->flags & MDP_BWC_EN) ? 1 : 0;
rot->format = fmt->format;
rot->img_width = req->src.width;
rot->img_height = req->src.height;
@@ -237,9 +242,10 @@
struct mdss_mdp_pipe *pipe;
struct mdss_mdp_mixer *mixer = NULL;
u32 pipe_type, mixer_mux, len, src_format;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
int ret;
- if (mfd == NULL || mfd->ctl == NULL)
+ if (mdp5_data->ctl == NULL)
return -ENODEV;
if (req->flags & MDSS_MDP_RIGHT_MIXER)
@@ -247,7 +253,7 @@
else
mixer_mux = MDSS_MDP_MIXER_MUX_LEFT;
- pr_debug("pipe ctl=%u req id=%x mux=%d\n", mfd->ctl->num, req->id,
+ pr_debug("pipe ctl=%u req id=%x mux=%d\n", mdp5_data->ctl->num, req->id,
mixer_mux);
if (req->flags & MDP_ROT_90) {
@@ -256,7 +262,7 @@
}
src_format = req->src.format;
- if (req->flags & MDP_SOURCE_ROTATED_90)
+ if (req->flags & (MDP_SOURCE_ROTATED_90 | MDP_BWC_EN))
src_format = mdss_mdp_get_rotator_dst_format(src_format);
fmt = mdss_mdp_get_format_params(src_format);
@@ -269,14 +275,15 @@
if (ret)
return ret;
- pipe = mdss_mdp_mixer_stage_pipe(mfd->ctl, mixer_mux, req->z_order);
+ pipe = mdss_mdp_mixer_stage_pipe(mdp5_data->ctl, mixer_mux,
+ req->z_order);
if (pipe && pipe->ndx != req->id) {
pr_debug("replacing pnum=%d at stage=%d mux=%d\n",
pipe->num, req->z_order, mixer_mux);
pipe->params_changed = true;
}
- mixer = mdss_mdp_mixer_get(mfd->ctl, mixer_mux);
+ mixer = mdss_mdp_mixer_get(mdp5_data->ctl, mixer_mux);
if (!mixer) {
pr_err("unable to get mixer\n");
return -ENODEV;
@@ -310,13 +317,13 @@
}
mutex_lock(&mfd->lock);
- list_add(&pipe->used_list, &mfd->pipes_used);
+ list_add(&pipe->used_list, &mdp5_data->pipes_used);
mutex_unlock(&mfd->lock);
pipe->mixer = mixer;
pipe->mfd = mfd;
pipe->play_cnt = 0;
} else {
- pipe = mdss_mdp_pipe_get(mfd->mdata, req->id);
+ pipe = mdss_mdp_pipe_get(mdp5_data->mdata, req->id);
if (IS_ERR_OR_NULL(pipe)) {
pr_err("invalid pipe ndx=%x\n", req->id);
return pipe ? PTR_ERR(pipe) : -ENODEV;
@@ -339,7 +346,8 @@
}
pipe->flags = req->flags;
-
+ pipe->bwc_mode = pipe->mixer->rotator_mode ?
+ 0 : (req->flags & MDP_BWC_EN ? 1 : 0) ;
pipe->img_width = req->src.width & 0x3fff;
pipe->img_height = req->src.height & 0x3fff;
pipe->src.x = req->src_rect.x;
@@ -406,14 +414,15 @@
static int mdss_mdp_overlay_set(struct msm_fb_data_type *mfd,
struct mdp_overlay *req)
{
- int ret = 0;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ int ret;
- ret = mutex_lock_interruptible(&mfd->ov_lock);
+ ret = mutex_lock_interruptible(&mdp5_data->ov_lock);
if (ret)
return ret;
if (!mfd->panel_power_on) {
- mutex_unlock(&mfd->ov_lock);
+ mutex_unlock(&mdp5_data->ov_lock);
return -EPERM;
}
@@ -432,7 +441,7 @@
req->z_order -= MDSS_MDP_STAGE_0;
}
- mutex_unlock(&mfd->ov_lock);
+ mutex_unlock(&mdp5_data->ov_lock);
return ret;
}
@@ -481,16 +490,18 @@
static int mdss_mdp_overlay_cleanup(struct msm_fb_data_type *mfd)
{
struct mdss_mdp_pipe *pipe, *tmp;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
LIST_HEAD(destroy_pipes);
mutex_lock(&mfd->lock);
- list_for_each_entry_safe(pipe, tmp, &mfd->pipes_cleanup, cleanup_list) {
+ list_for_each_entry_safe(pipe, tmp, &mdp5_data->pipes_cleanup,
+ cleanup_list) {
list_move(&pipe->cleanup_list, &destroy_pipes);
mdss_mdp_overlay_free_buf(&pipe->back_buf);
mdss_mdp_overlay_free_buf(&pipe->front_buf);
}
- list_for_each_entry(pipe, &mfd->pipes_used, used_list) {
+ list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) {
if (pipe->back_buf.num_planes) {
/* make back buffer active */
mdss_mdp_overlay_free_buf(&pipe->front_buf);
@@ -595,8 +606,9 @@
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);
- if (mfd->ctl->power_on)
+ if (mdp5_data->ctl->power_on)
return 0;
pr_debug("starting fb%d overlay\n", mfd->index);
@@ -608,20 +620,20 @@
}
if (mfd->panel_info->cont_splash_enabled)
- mdss_mdp_reconfigure_splash_done(mfd->ctl);
+ mdss_mdp_reconfigure_splash_done(mdp5_data->ctl);
if (!is_mdss_iommu_attached()) {
mdss_iommu_attach(mdss_res);
mdss_hw_init(mdss_res);
}
- rc = mdss_mdp_ctl_start(mfd->ctl);
+ rc = mdss_mdp_ctl_start(mdp5_data->ctl);
if (rc == 0) {
atomic_inc(&ov_active_panels);
} else {
pr_err("overlay start failed.\n");
- mdss_mdp_ctl_destroy(mfd->ctl);
- mfd->ctl = NULL;
+ mdss_mdp_ctl_destroy(mdp5_data->ctl);
+ mdp5_data->ctl = NULL;
pm_runtime_put(&mfd->pdev->dev);
}
@@ -629,15 +641,15 @@
return rc;
}
-int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl)
+int mdss_mdp_overlay_kickoff(struct msm_fb_data_type *mfd)
{
- struct msm_fb_data_type *mfd = ctl->mfd;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
struct mdss_mdp_pipe *pipe;
int ret;
- mutex_lock(&mfd->ov_lock);
+ mutex_lock(&mdp5_data->ov_lock);
mutex_lock(&mfd->lock);
- list_for_each_entry(pipe, &mfd->pipes_used, used_list) {
+ list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) {
struct mdss_mdp_data *buf;
if (pipe->back_buf.num_planes) {
buf = &pipe->back_buf;
@@ -658,16 +670,17 @@
}
}
- if (mfd->kickoff_fnc)
- ret = mfd->kickoff_fnc(ctl);
+ if (mfd->panel.type == WRITEBACK_PANEL)
+ ret = mdss_mdp_wb_kickoff(mfd);
else
- ret = mdss_mdp_display_commit(ctl, NULL);
+ ret = mdss_mdp_display_commit(mdp5_data->ctl, NULL);
+
mutex_unlock(&mfd->lock);
if (IS_ERR_VALUE(ret))
goto commit_fail;
- ret = mdss_mdp_display_wait4comp(ctl);
+ ret = mdss_mdp_display_wait4comp(mdp5_data->ctl);
complete(&mfd->update.comp);
mutex_lock(&mfd->no_update.lock);
@@ -681,7 +694,7 @@
commit_fail:
ret = mdss_mdp_overlay_cleanup(mfd);
- mutex_unlock(&mfd->ov_lock);
+ mutex_unlock(&mdp5_data->ov_lock);
return ret;
}
@@ -689,6 +702,7 @@
static int mdss_mdp_overlay_release(struct msm_fb_data_type *mfd, int ndx)
{
struct mdss_mdp_pipe *pipe;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
u32 pipe_ndx, unset_ndx = 0;
int i;
@@ -696,14 +710,15 @@
pipe_ndx = BIT(i);
if (pipe_ndx & ndx) {
unset_ndx |= pipe_ndx;
- pipe = mdss_mdp_pipe_get(mfd->mdata, pipe_ndx);
+ pipe = mdss_mdp_pipe_get(mdp5_data->mdata, pipe_ndx);
if (IS_ERR_OR_NULL(pipe)) {
pr_warn("unknown pipe ndx=%x\n", pipe_ndx);
continue;
}
mutex_lock(&mfd->lock);
list_del(&pipe->used_list);
- list_add(&pipe->cleanup_list, &mfd->pipes_cleanup);
+ list_add(&pipe->cleanup_list,
+ &mdp5_data->pipes_cleanup);
mutex_unlock(&mfd->lock);
mdss_mdp_mixer_pipe_unstage(pipe);
mdss_mdp_pipe_unmap(pipe);
@@ -715,22 +730,23 @@
static int mdss_mdp_overlay_unset(struct msm_fb_data_type *mfd, int ndx)
{
int ret = 0;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
- if (!mfd || !mfd->ctl)
+ if (!mfd || !mdp5_data->ctl)
return -ENODEV;
- ret = mutex_lock_interruptible(&mfd->ov_lock);
+ ret = mutex_lock_interruptible(&mdp5_data->ov_lock);
if (ret)
return ret;
if (ndx == BORDERFILL_NDX) {
pr_debug("borderfill disable\n");
- mfd->borderfill_enable = false;
+ mdp5_data->borderfill_enable = false;
return 0;
}
if (!mfd->panel_power_on) {
- mutex_unlock(&mfd->ov_lock);
+ mutex_unlock(&mdp5_data->ov_lock);
return -EPERM;
}
@@ -741,7 +757,7 @@
else
ret = mdss_mdp_overlay_release(mfd, ndx);
- mutex_unlock(&mfd->ov_lock);
+ mutex_unlock(&mdp5_data->ov_lock);
return ret;
}
@@ -749,18 +765,19 @@
static int mdss_mdp_overlay_release_all(struct msm_fb_data_type *mfd)
{
struct mdss_mdp_pipe *pipe;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
u32 unset_ndx = 0;
int cnt = 0;
- mutex_lock(&mfd->ov_lock);
+ mutex_lock(&mdp5_data->ov_lock);
mutex_lock(&mfd->lock);
- list_for_each_entry(pipe, &mfd->pipes_used, used_list) {
+ list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) {
unset_ndx |= pipe->ndx;
cnt++;
}
- if (cnt == 0 && !list_empty(&mfd->pipes_cleanup)) {
- pr_warn("overlay release on fb%d called without commit!",
+ if (cnt == 0 && !list_empty(&mdp5_data->pipes_cleanup)) {
+ pr_debug("overlay release on fb%d called without commit!",
mfd->index);
cnt++;
}
@@ -771,10 +788,10 @@
pr_debug("%d pipes need cleanup (%x)\n", cnt, unset_ndx);
mdss_mdp_overlay_release(mfd, unset_ndx);
}
- mutex_unlock(&mfd->ov_lock);
+ mutex_unlock(&mdp5_data->ov_lock);
if (cnt)
- mdss_mdp_overlay_kickoff(mfd->ctl);
+ mfd->mdp.kickoff_fnc(mfd);
return 0;
}
@@ -782,12 +799,12 @@
static int mdss_mdp_overlay_play_wait(struct msm_fb_data_type *mfd,
struct msmfb_overlay_data *req)
{
- int ret;
+ int ret = 0;
- if (!mfd || !mfd->ctl)
+ if (!mfd)
return -ENODEV;
- ret = mdss_mdp_overlay_kickoff(mfd->ctl);
+ ret = mfd->mdp.kickoff_fnc(mfd);
if (!ret)
pr_err("error displaying\n");
@@ -840,8 +857,9 @@
struct mdss_mdp_data *src_data;
int ret;
u32 flags;
+ struct mdss_data_type *mdata = mfd_to_mdata(mfd);
- pipe = mdss_mdp_pipe_get(mfd->mdata, req->id);
+ pipe = mdss_mdp_pipe_get(mdata, req->id);
if (IS_ERR_OR_NULL(pipe)) {
pr_err("pipe ndx=%x doesn't exist\n", req->id);
return pipe ? PTR_ERR(pipe) : -ENODEV;
@@ -870,16 +888,17 @@
static int mdss_mdp_overlay_play(struct msm_fb_data_type *mfd,
struct msmfb_overlay_data *req)
{
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
int ret = 0;
pr_debug("play req id=%x\n", req->id);
- ret = mutex_lock_interruptible(&mfd->ov_lock);
+ ret = mutex_lock_interruptible(&mdp5_data->ov_lock);
if (ret)
return ret;
if (!mfd->panel_power_on) {
- mutex_unlock(&mfd->ov_lock);
+ mutex_unlock(&mdp5_data->ov_lock);
return -EPERM;
}
@@ -893,13 +912,13 @@
ret = mdss_mdp_overlay_rotate(mfd, req);
} else if (req->id == BORDERFILL_NDX) {
pr_debug("borderfill enable\n");
- mfd->borderfill_enable = true;
+ mdp5_data->borderfill_enable = true;
ret = mdss_mdp_overlay_free_fb_pipe(mfd);
} else {
ret = mdss_mdp_overlay_queue(mfd, req);
}
- mutex_unlock(&mfd->ov_lock);
+ mutex_unlock(&mdp5_data->ov_lock);
return ret;
}
@@ -908,13 +927,16 @@
{
struct mdss_mdp_pipe *pipe;
u32 fb_ndx = 0;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
- pipe = mdss_mdp_mixer_stage_pipe(mfd->ctl, MDSS_MDP_MIXER_MUX_LEFT,
+ pipe = mdss_mdp_mixer_stage_pipe(mdp5_data->ctl,
+ MDSS_MDP_MIXER_MUX_LEFT,
MDSS_MDP_STAGE_BASE);
if (pipe)
fb_ndx |= pipe->ndx;
- pipe = mdss_mdp_mixer_stage_pipe(mfd->ctl, MDSS_MDP_MIXER_MUX_RIGHT,
+ pipe = mdss_mdp_mixer_stage_pipe(mdp5_data->ctl,
+ MDSS_MDP_MIXER_MUX_RIGHT,
MDSS_MDP_STAGE_BASE);
if (pipe)
fb_ndx |= pipe->ndx;
@@ -930,9 +952,10 @@
struct mdss_mdp_pipe **ppipe,
int mixer_mux)
{
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
struct mdss_mdp_pipe *pipe;
- pipe = mdss_mdp_mixer_stage_pipe(mfd->ctl, mixer_mux,
+ pipe = mdss_mdp_mixer_stage_pipe(mdp5_data->ctl, mixer_mux,
MDSS_MDP_STAGE_BASE);
if (pipe == NULL) {
struct mdp_overlay req;
@@ -940,7 +963,8 @@
struct mdss_mdp_mixer *mixer;
int ret, bpp;
- mixer = mdss_mdp_mixer_get(mfd->ctl, MDSS_MDP_MIXER_MUX_LEFT);
+ mixer = mdss_mdp_mixer_get(mdp5_data->ctl,
+ MDSS_MDP_MIXER_MUX_LEFT);
if (!mixer) {
pr_err("unable to retrieve mixer\n");
return -ENODEV;
@@ -981,7 +1005,7 @@
if (ret)
return ret;
- pr_debug("ctl=%d pnum=%d\n", mfd->ctl->num, pipe->num);
+ pr_debug("ctl=%d pnum=%d\n", mdp5_data->ctl->num, pipe->num);
}
*ppipe = pipe;
@@ -993,24 +1017,25 @@
struct mdss_mdp_data data;
struct mdss_mdp_pipe *pipe;
struct fb_info *fbi;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
u32 offset;
int bpp, ret;
- if (!mfd || !mfd->ctl)
+ if (!mfd || !mdp5_data->ctl)
return;
fbi = mfd->fbi;
- if (fbi->fix.smem_len == 0 || mfd->borderfill_enable) {
- mdss_mdp_overlay_kickoff(mfd->ctl);
+ if (fbi->fix.smem_len == 0 || mdp5_data->borderfill_enable) {
+ mfd->mdp.kickoff_fnc(mfd);
return;
}
- if (mutex_lock_interruptible(&mfd->ov_lock))
+ if (mutex_lock_interruptible(&mdp5_data->ov_lock))
return;
if (!mfd->panel_power_on) {
- mutex_unlock(&mfd->ov_lock);
+ mutex_unlock(&mdp5_data->ov_lock);
return;
}
@@ -1076,37 +1101,43 @@
goto pan_display_error;
}
}
- mutex_unlock(&mfd->ov_lock);
+ mutex_unlock(&mdp5_data->ov_lock);
if ((fbi->var.activate & FB_ACTIVATE_VBL) ||
(fbi->var.activate & FB_ACTIVATE_FORCE))
- mdss_mdp_overlay_kickoff(mfd->ctl);
+ mfd->mdp.kickoff_fnc(mfd);
+
return;
pan_display_error:
- mutex_unlock(&mfd->ov_lock);
+ mutex_unlock(&mdp5_data->ov_lock);
}
/* function is called in irq context should have minimum processing */
-static void mdss_mdp_overlay_handle_vsync(struct mdss_mdp_ctl *ctl, ktime_t t)
+static void mdss_mdp_overlay_handle_vsync(struct mdss_mdp_ctl *ctl,
+ ktime_t t)
{
struct msm_fb_data_type *mfd = ctl->mfd;
- if (!mfd) {
+ struct mdss_overlay_private *mdp5_data;
+
+ if (!mfd || !mfd->mdp.private1) {
pr_warn("Invalid handle for vsync\n");
return;
}
+ mdp5_data = mfd_to_mdp5_data(mfd);
pr_debug("vsync on fb%d play_cnt=%d\n", mfd->index, ctl->play_cnt);
- spin_lock(&mfd->vsync_lock);
- mfd->vsync_time = t;
- complete(&mfd->vsync_comp);
- spin_unlock(&mfd->vsync_lock);
+ spin_lock(&mdp5_data->vsync_lock);
+ mdp5_data->vsync_time = t;
+ complete(&mdp5_data->vsync_comp);
+ spin_unlock(&mdp5_data->vsync_lock);
}
int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en)
{
- struct mdss_mdp_ctl *ctl = mfd->ctl;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
unsigned long flags;
int rc;
@@ -1122,16 +1153,16 @@
if (!ctl->power_on) {
pr_debug("fb%d vsync pending first update en=%d\n",
mfd->index, en);
- mfd->vsync_pending = en;
+ mdp5_data->vsync_pending = en;
mutex_unlock(&ctl->lock);
return 0;
}
pr_debug("fb%d vsync en=%d\n", mfd->index, en);
- spin_lock_irqsave(&mfd->vsync_lock, flags);
- INIT_COMPLETION(mfd->vsync_comp);
- spin_unlock_irqrestore(&mfd->vsync_lock, flags);
+ spin_lock_irqsave(&mdp5_data->vsync_lock, flags);
+ INIT_COMPLETION(mdp5_data->vsync_comp);
+ spin_unlock_irqrestore(&mdp5_data->vsync_lock, flags);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
if (en)
@@ -1150,26 +1181,27 @@
{
struct fb_info *fbi = dev_get_drvdata(dev);
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)fbi->par;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
unsigned long flags;
u64 vsync_ticks;
unsigned long timeout;
int ret;
- if (!mfd->ctl || !mfd->ctl->power_on)
+ if (!mdp5_data->ctl || !mdp5_data->ctl->power_on)
return 0;
timeout = msecs_to_jiffies(VSYNC_PERIOD * 5);
- ret = wait_for_completion_interruptible_timeout(&mfd->vsync_comp,
+ ret = wait_for_completion_interruptible_timeout(&mdp5_data->vsync_comp,
timeout);
if (ret <= 0) {
pr_debug("Sending current time as vsync timestamp for fb%d\n",
mfd->index);
- mfd->vsync_time = ktime_get();
+ mdp5_data->vsync_time = ktime_get();
}
- spin_lock_irqsave(&mfd->vsync_lock, flags);
- vsync_ticks = ktime_to_ns(mfd->vsync_time);
- spin_unlock_irqrestore(&mfd->vsync_lock, flags);
+ spin_lock_irqsave(&mdp5_data->vsync_lock, flags);
+ vsync_ticks = ktime_to_ns(mdp5_data->vsync_time);
+ spin_unlock_irqrestore(&mdp5_data->vsync_lock, flags);
pr_debug("fb%d vsync=%llu", mfd->index, vsync_ticks);
ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_ticks);
@@ -1191,6 +1223,7 @@
static int mdss_mdp_hw_cursor_update(struct msm_fb_data_type *mfd,
struct fb_cursor *cursor)
{
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
struct mdss_mdp_mixer *mixer;
struct fb_image *img = &cursor->image;
u32 blendcfg;
@@ -1219,12 +1252,12 @@
}
}
- mixer = mdss_mdp_mixer_get(mfd->ctl, MDSS_MDP_MIXER_MUX_DEFAULT);
+ mixer = mdss_mdp_mixer_get(mdp5_data->ctl, MDSS_MDP_MIXER_MUX_DEFAULT);
off = MDSS_MDP_REG_LM_OFFSET(mixer->num);
if ((img->width > MDSS_MDP_CURSOR_WIDTH) ||
- (img->height > MDSS_MDP_CURSOR_HEIGHT) ||
- (img->depth != 32))
+ (img->height > MDSS_MDP_CURSOR_HEIGHT) ||
+ (img->depth != 32))
return -EINVAL;
pr_debug("mixer=%d enable=%x set=%x\n", mixer->num, cursor->enable,
@@ -1320,13 +1353,227 @@
return 0;
}
+static int mdss_bl_scale_config(struct msm_fb_data_type *mfd,
+ struct mdp_bl_scale_data *data)
+{
+ int ret = 0;
+ int curr_bl;
+ mutex_lock(&mfd->lock);
+ curr_bl = mfd->bl_level;
+ mfd->bl_scale = data->scale;
+ mfd->bl_min_lvl = data->min_lvl;
+ pr_debug("update scale = %d, min_lvl = %d\n", mfd->bl_scale,
+ mfd->bl_min_lvl);
+
+ /* update current backlight to use new scaling*/
+ mdss_fb_set_backlight(mfd, curr_bl);
+ mutex_unlock(&mfd->lock);
+ return ret;
+}
+
+static int mdss_mdp_pp_ioctl(struct msm_fb_data_type *mfd,
+ void __user *argp)
+{
+ int ret;
+ struct msmfb_mdp_pp mdp_pp;
+ u32 copyback = 0;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+
+ ret = copy_from_user(&mdp_pp, argp, sizeof(mdp_pp));
+ if (ret)
+ return ret;
+
+ switch (mdp_pp.op) {
+ case mdp_op_pa_cfg:
+ ret = mdss_mdp_pa_config(mdp5_data->ctl,
+ &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,
+ ©back);
+ break;
+
+ case mdp_op_lut_cfg:
+ 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);
+ break;
+
+ 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;
+
+ default:
+ ret = -ENOTSUPP;
+ break;
+ }
+ 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;
+ case mdp_bl_scale_cfg:
+ ret = mdss_bl_scale_config(mfd, (struct mdp_bl_scale_data *)
+ &mdp_pp.data.bl_scale_data);
+ break;
+ default:
+ pr_err("Unsupported request to MDP_PP IOCTL.\n");
+ ret = -EINVAL;
+ break;
+ }
+ if ((ret == 0) && copyback)
+ ret = copy_to_user(argp, &mdp_pp, sizeof(struct msmfb_mdp_pp));
+ return ret;
+}
+
+static int mdss_mdp_histo_ioctl(struct msm_fb_data_type *mfd, u32 cmd,
+ void __user *argp)
+{
+ int ret = -ENOSYS;
+ struct mdp_histogram_data hist;
+ struct mdp_histogram_start_req hist_req;
+ u32 block, hist_data_addr = 0;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+
+ switch (cmd) {
+ case MSMFB_HISTOGRAM_START:
+ if (!mfd->panel_power_on)
+ return -EPERM;
+
+ ret = copy_from_user(&hist_req, argp, sizeof(hist_req));
+ if (ret)
+ return ret;
+
+ ret = mdss_mdp_histogram_start(mdp5_data->ctl, &hist_req);
+ break;
+
+ case MSMFB_HISTOGRAM_STOP:
+ ret = copy_from_user(&block, argp, sizeof(int));
+ if (ret)
+ return ret;
+
+ ret = mdss_mdp_histogram_stop(mdp5_data->ctl, block);
+ break;
+
+ case MSMFB_HISTOGRAM:
+ if (!mfd->panel_power_on)
+ return -EPERM;
+
+ ret = copy_from_user(&hist, argp, sizeof(hist));
+ if (ret)
+ return ret;
+
+ ret = mdss_mdp_hist_collect(mdp5_data->ctl, &hist,
+ &hist_data_addr);
+ if ((ret == 0) && hist_data_addr) {
+ ret = copy_to_user(hist.c0, (u32 *)hist_data_addr,
+ sizeof(u32) * hist.bin_cnt);
+ if (ret == 0)
+ ret = copy_to_user(argp, &hist,
+ sizeof(hist));
+ }
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+static int mdss_fb_set_metadata(struct msm_fb_data_type *mfd,
+ struct msmfb_metadata *metadata)
+{
+ int ret = 0;
+ switch (metadata->op) {
+ case metadata_op_vic:
+ if (mfd->panel_info)
+ mfd->panel_info->vic =
+ metadata->data.video_info_code;
+ else
+ ret = -EINVAL;
+ break;
+ default:
+ pr_warn("unsupported request to MDP META IOCTL\n");
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int mdss_fb_get_hw_caps(struct msm_fb_data_type *mfd,
+ struct mdss_hw_caps *caps)
+{
+ struct mdss_data_type *mdata = mfd_to_mdata(mfd);
+ caps->mdp_rev = mdata->mdp_rev;
+ caps->vig_pipes = mdata->nvig_pipes;
+ caps->rgb_pipes = mdata->nrgb_pipes;
+ caps->dma_pipes = mdata->ndma_pipes;
+ return 0;
+}
+
+static int mdss_fb_get_metadata(struct msm_fb_data_type *mfd,
+ struct msmfb_metadata *metadata)
+{
+ int ret = 0;
+ switch (metadata->op) {
+ case metadata_op_frame_rate:
+ metadata->data.panel_frame_rate =
+ mdss_get_panel_framerate(mfd);
+ break;
+ case metadata_op_get_caps:
+ ret = mdss_fb_get_hw_caps(mfd, &metadata->data.caps);
+ break;
+ default:
+ pr_warn("Unsupported request to MDP META IOCTL.\n");
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
static int mdss_mdp_overlay_ioctl_handler(struct msm_fb_data_type *mfd,
u32 cmd, void __user *argp)
{
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
struct mdp_overlay req;
int val, ret = -ENOSYS;
+ struct msmfb_metadata metadata;
switch (cmd) {
+ case MSMFB_MDP_PP:
+ ret = mdss_mdp_pp_ioctl(mfd, argp);
+ break;
+
+ case MSMFB_HISTOGRAM_START:
+ case MSMFB_HISTOGRAM_STOP:
+ case MSMFB_HISTOGRAM:
+ ret = mdss_mdp_histo_ioctl(mfd, cmd, argp);
+ break;
+
case MSMFB_OVERLAY_GET:
ret = copy_from_user(&req, argp, sizeof(req));
if (!ret) {
@@ -1364,7 +1611,7 @@
case MSMFB_OVERLAY_PLAY_ENABLE:
if (!copy_from_user(&val, argp, sizeof(val))) {
- mfd->overlay_play_enable = val;
+ mdp5_data->overlay_play_enable = val;
} else {
pr_err("OVERLAY_PLAY_ENABLE failed (%d)\n", ret);
ret = -EFAULT;
@@ -1372,7 +1619,7 @@
break;
case MSMFB_OVERLAY_PLAY:
- if (mfd->overlay_play_enable) {
+ if (mdp5_data->overlay_play_enable) {
struct msmfb_overlay_data data;
ret = copy_from_user(&data, argp, sizeof(data));
@@ -1392,7 +1639,7 @@
break;
case MSMFB_OVERLAY_PLAY_WAIT:
- if (mfd->overlay_play_enable) {
+ if (mdp5_data->overlay_play_enable) {
struct msmfb_overlay_data data;
ret = copy_from_user(&data, argp, sizeof(data));
@@ -1419,9 +1666,23 @@
break;
case MSMFB_OVERLAY_COMMIT:
mdss_fb_wait_for_fence(mfd);
- ret = mdss_mdp_overlay_kickoff(mfd->ctl);
+ ret = mfd->mdp.kickoff_fnc(mfd);
mdss_fb_signal_timeline(mfd);
break;
+ case MSMFB_METADATA_SET:
+ ret = copy_from_user(&metadata, argp, sizeof(metadata));
+ if (ret)
+ return ret;
+ ret = mdss_fb_set_metadata(mfd, &metadata);
+ break;
+ case MSMFB_METADATA_GET:
+ ret = copy_from_user(&metadata, argp, sizeof(metadata));
+ if (ret)
+ return ret;
+ ret = mdss_fb_get_metadata(mfd, &metadata);
+ if (!ret)
+ ret = copy_to_user(argp, &metadata, sizeof(metadata));
+ break;
default:
if (mfd->panel.type == WRITEBACK_PANEL)
ret = mdss_mdp_wb_ioctl_handler(mfd, cmd, argp);
@@ -1433,7 +1694,8 @@
static int mdss_mdp_overlay_on(struct msm_fb_data_type *mfd)
{
- int rc = 0;
+ int rc;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
if (!mfd)
return -ENODEV;
@@ -1441,7 +1703,7 @@
if (mfd->key != MFD_KEY)
return -EINVAL;
- if (!mfd->ctl) {
+ if (!mdp5_data->ctl) {
struct mdss_mdp_ctl *ctl;
struct mdss_panel_data *pdata;
@@ -1466,22 +1728,22 @@
return rc;
}
}
- mfd->ctl = ctl;
+ mdp5_data->ctl = ctl;
}
if (!mfd->panel_info->cont_splash_enabled) {
rc = mdss_mdp_overlay_start(mfd);
if (!IS_ERR_VALUE(rc) && (mfd->panel_info->type != DTV_PANEL))
- rc = mdss_mdp_overlay_kickoff(mfd->ctl);
+ rc = mdss_mdp_overlay_kickoff(mfd);
} else {
- rc = mdss_mdp_ctl_setup(mfd->ctl);
+ rc = mdss_mdp_ctl_setup(mdp5_data->ctl);
if (rc)
return rc;
}
- if (!IS_ERR_VALUE(rc) && mfd->vsync_pending) {
- mfd->vsync_pending = 0;
- mdss_mdp_overlay_vsync_ctrl(mfd, mfd->vsync_pending);
+ if (!IS_ERR_VALUE(rc) && mdp5_data->vsync_pending) {
+ mdp5_data->vsync_pending = 0;
+ mdss_mdp_overlay_vsync_ctrl(mfd, mdp5_data->vsync_pending);
}
return rc;
@@ -1490,6 +1752,7 @@
static int mdss_mdp_overlay_off(struct msm_fb_data_type *mfd)
{
int rc;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
if (!mfd)
return -ENODEV;
@@ -1497,22 +1760,22 @@
if (mfd->key != MFD_KEY)
return -EINVAL;
- if (!mfd->ctl) {
+ if (!mdp5_data->ctl) {
pr_err("ctl not initialized\n");
return -ENODEV;
}
- if (!mfd->ctl->power_on)
+ if (!mdp5_data->ctl->power_on)
return 0;
mdss_mdp_overlay_release_all(mfd);
- rc = mdss_mdp_ctl_stop(mfd->ctl);
+ rc = mdss_mdp_ctl_stop(mdp5_data->ctl);
if (rc == 0) {
if (!mfd->ref_cnt) {
- mfd->borderfill_enable = false;
- mdss_mdp_ctl_destroy(mfd->ctl);
- mfd->ctl = NULL;
+ mdp5_data->borderfill_enable = false;
+ mdss_mdp_ctl_destroy(mdp5_data->ctl);
+ mdp5_data->ctl = NULL;
}
if (atomic_dec_return(&ov_active_panels) == 0)
@@ -1526,39 +1789,63 @@
return rc;
}
+int mdss_panel_register_done(struct mdss_panel_data *pdata)
+{
+ /*
+ * Clocks are already on if continuous splash is enabled,
+ * increasing ref_cnt to help balance clocks once done.
+ */
+ if (pdata->panel_info.cont_splash_enabled) {
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+ mdss_mdp_footswitch_ctrl_splash(1);
+ mdss_mdp_copy_splash_screen(pdata);
+ }
+ return 0;
+}
+
int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd)
{
struct device *dev = mfd->fbi->dev;
+ struct msm_mdp_interface *mdp5_interface = &mfd->mdp;
+ struct mdss_overlay_private *mdp5_data = NULL;
int rc;
- mfd->mdata = dev_get_drvdata(mfd->pdev->dev.parent);
- if (!mfd->mdata) {
- pr_err("unable to initialize overlay for fb%d\n", mfd->index);
- return -ENODEV;
+ mdp5_interface->on_fnc = mdss_mdp_overlay_on;
+ mdp5_interface->off_fnc = mdss_mdp_overlay_off;
+ mdp5_interface->do_histogram = NULL;
+ mdp5_interface->cursor_update = mdss_mdp_hw_cursor_update;
+ mdp5_interface->dma_fnc = mdss_mdp_overlay_pan_display;
+ 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_data = kmalloc(sizeof(struct mdss_overlay_private), GFP_KERNEL);
+ if (!mdp5_data) {
+ pr_err("fail to allocate mdp5 private data structure");
+ return -ENOMEM;
}
+ memset(mdp5_data, 0, sizeof(struct mdss_overlay_private));
- mfd->on_fnc = mdss_mdp_overlay_on;
- mfd->off_fnc = mdss_mdp_overlay_off;
- mfd->hw_refresh = true;
- mfd->do_histogram = NULL;
- mfd->overlay_play_enable = true;
- mfd->cursor_update = mdss_mdp_hw_cursor_update;
- mfd->dma_fnc = mdss_mdp_overlay_pan_display;
- mfd->ioctl_handler = mdss_mdp_overlay_ioctl_handler;
+ INIT_LIST_HEAD(&mdp5_data->pipes_used);
+ INIT_LIST_HEAD(&mdp5_data->pipes_cleanup);
+ init_completion(&mdp5_data->vsync_comp);
+ spin_lock_init(&mdp5_data->vsync_lock);
+ mutex_init(&mdp5_data->ov_lock);
+ mdp5_data->hw_refresh = true;
+ mdp5_data->overlay_play_enable = true;
- if (mfd->panel.type == WRITEBACK_PANEL)
- mfd->kickoff_fnc = mdss_mdp_wb_kickoff;
-
- INIT_LIST_HEAD(&mfd->pipes_used);
- INIT_LIST_HEAD(&mfd->pipes_cleanup);
- init_completion(&mfd->vsync_comp);
- spin_lock_init(&mfd->vsync_lock);
- mutex_init(&mfd->ov_lock);
+ mdp5_data->mdata = dev_get_drvdata(mfd->pdev->dev.parent);
+ if (!mdp5_data->mdata) {
+ pr_err("unable to initialize overlay for fb%d\n", mfd->index);
+ rc = -ENODEV;
+ goto init_fail;
+ }
+ mfd->mdp.private1 = mdp5_data;
rc = sysfs_create_group(&dev->kobj, &vsync_fs_attr_group);
if (rc) {
pr_err("vsync sysfs group creation failed, ret=%d\n", rc);
- return rc;
+ goto init_fail;
}
pm_runtime_set_suspended(&mfd->pdev->dev);
@@ -1568,4 +1855,7 @@
pr_debug("vsync kobject_uevent(KOBJ_ADD)\n");
return rc;
+init_fail:
+ kfree(mdp5_data);
+ return rc;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index ca741b1..b169c43 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -119,25 +119,32 @@
u32 num_blks = 0, reserved = 0;
struct mdss_mdp_plane_sizes ps;
int i, rc;
+ u32 nlines;
- if ((mdata->mdp_rev >= MDSS_MDP_HW_REV_102) &&
+ if (pipe->bwc_mode) {
+ rc = mdss_mdp_get_rau_strides(pipe->src.w, pipe->src.h,
+ pipe->src_fmt, &ps);
+ if (rc)
+ return rc;
+ pr_debug("BWC SMP strides ystride0=%x ystride1=%x\n",
+ ps.ystride[0], ps.ystride[1]);
+ } else if ((mdata->mdp_rev >= MDSS_MDP_HW_REV_102) &&
pipe->src_fmt->is_yuv) {
ps.num_planes = 2;
ps.ystride[0] = pipe->src.w;
ps.ystride[1] = pipe->src.w;
} else {
rc = mdss_mdp_get_plane_sizes(pipe->src_fmt->format,
- pipe->src.w, pipe->src.h, &ps);
+ pipe->src.w, pipe->src.h, &ps, 0);
if (rc)
return rc;
}
- if ((ps.num_planes > 1) && (pipe->type == MDSS_MDP_PIPE_TYPE_RGB))
- return -EINVAL;
-
mutex_lock(&mdss_mdp_smp_lock);
for (i = 0; i < ps.num_planes; i++) {
- num_blks = DIV_ROUND_UP(2 * ps.ystride[i], SMP_MB_SIZE);
+ nlines = pipe->bwc_mode ? ps.rau_h[i] : 2;
+ num_blks = DIV_ROUND_UP(nlines * ps.ystride[i],
+ mdss_res->smp_mb_size);
if (mdata->mdp_rev == MDSS_MDP_HW_REV_100)
num_blks = roundup_pow_of_two(num_blks);
@@ -341,6 +348,8 @@
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
mdss_mdp_pipe_sspp_term(pipe);
mdss_mdp_smp_free(pipe);
+ pipe->flags = 0;
+ pipe->bwc_mode = 0;
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
return 0;
@@ -376,7 +385,7 @@
width = pipe->img_width;
height = pipe->img_height;
mdss_mdp_get_plane_sizes(pipe->src_fmt->format, width, height,
- &pipe->src_planes);
+ &pipe->src_planes, pipe->bwc_mode);
if ((pipe->flags & MDP_DEINTERLACE) &&
!(pipe->flags & MDP_SOURCE_ROTATED_90)) {
@@ -416,8 +425,9 @@
static int mdss_mdp_format_setup(struct mdss_mdp_pipe *pipe)
{
struct mdss_mdp_format_params *fmt;
- u32 opmode, chroma_samp, unpack, src_format;
+ u32 chroma_samp, unpack, src_format;
u32 secure = 0;
+ u32 opmode;
fmt = pipe->src_fmt;
@@ -554,8 +564,7 @@
pr_debug("pnum=%d\n", pipe->num);
- if (!is_rot)
- data->bwc_enabled = pipe->bwc_mode;
+ data->bwc_enabled = pipe->bwc_mode;
ret = mdss_mdp_data_check(data, &pipe->src_planes);
if (ret)
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index 8bff5cb..5711653 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -203,7 +203,6 @@
rot_pipe->img_height = rot->img_height;
rot_pipe->src = rot->src_rect;
rot_pipe->dst = rot->src_rect;
- rot_pipe->bwc_mode = rot->bwc_mode;
rot_pipe->params_changed++;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.h b/drivers/video/msm/mdss/mdss_mdp_rotator.h
index c46f271..21ee9bb 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.h
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.h
@@ -45,10 +45,14 @@
static inline u32 mdss_mdp_get_rotator_dst_format(u32 in_format)
{
switch (in_format) {
+ case MDP_RGB_565:
+ case MDP_BGR_565:
+ return MDP_RGB_888;
case MDP_Y_CBCR_H2V2_VENUS:
- return MDP_Y_CBCR_H2V2;
+ case MDP_Y_CB_CR_H2V2:
case MDP_Y_CR_CB_GH2V2:
- return MDP_Y_CR_CB_H2V2;
+ case MDP_Y_CR_CB_H2V2:
+ return MDP_Y_CRCB_H2V2;
default:
return in_format;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index b54e0ec..5915f61 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -42,6 +42,9 @@
MDP_INTR_PING_PONG_0,
MDP_INTR_PING_PONG_1,
MDP_INTR_PING_PONG_2,
+ MDP_INTR_PING_PONG_0_RD_PTR,
+ MDP_INTR_PING_PONG_1_RD_PTR,
+ MDP_INTR_PING_PONG_2_RD_PTR,
MDP_INTR_WB_0,
MDP_INTR_WB_1,
MDP_INTR_WB_2,
@@ -69,6 +72,9 @@
case MDSS_MDP_IRQ_PING_PONG_COMP:
index = MDP_INTR_PING_PONG_0 + intf_num;
break;
+ case MDSS_MDP_IRQ_PING_PONG_RD_PTR:
+ index = MDP_INTR_PING_PONG_0_RD_PTR + intf_num;
+ break;
case MDSS_MDP_IRQ_WB_ROT_COMP:
index = MDP_INTR_WB_0 + intf_num;
break;
@@ -126,11 +132,12 @@
if (isr == 0)
goto mdp_isr_done;
- pr_debug("isr=%x\n", isr);
mask = MDSS_MDP_REG_READ(MDSS_MDP_REG_INTR_EN);
MDSS_MDP_REG_WRITE(MDSS_MDP_REG_INTR_CLEAR, isr);
+ pr_debug("%s: isr=%x mask=%x\n", __func__, isr, mask);
+
isr &= mask;
if (isr == 0)
goto mdp_isr_done;
@@ -156,6 +163,15 @@
if (isr & MDSS_MDP_INTR_PING_PONG_2_DONE)
mdss_mdp_intr_done(MDP_INTR_PING_PONG_2);
+ if (isr & MDSS_MDP_INTR_PING_PONG_0_RD_PTR)
+ mdss_mdp_intr_done(MDP_INTR_PING_PONG_0_RD_PTR);
+
+ if (isr & MDSS_MDP_INTR_PING_PONG_1_RD_PTR)
+ mdss_mdp_intr_done(MDP_INTR_PING_PONG_1_RD_PTR);
+
+ if (isr & MDSS_MDP_INTR_PING_PONG_2_RD_PTR)
+ mdss_mdp_intr_done(MDP_INTR_PING_PONG_2_RD_PTR);
+
if (isr & MDSS_MDP_INTR_INTF_0_VSYNC)
mdss_mdp_intr_done(MDP_INTR_VSYNC_INTF_0);
@@ -205,11 +221,48 @@
return NULL;
}
+int mdss_mdp_get_rau_strides(u32 w, u32 h,
+ struct mdss_mdp_format_params *fmt,
+ struct mdss_mdp_plane_sizes *ps)
+{
+ u32 stride_off;
+ if (fmt->is_yuv) {
+ ps->rau_cnt = DIV_ROUND_UP(w, 64);
+ ps->ystride[0] = 64 * 4;
+ ps->rau_h[0] = 4;
+ ps->rau_h[1] = 2;
+ if (fmt->chroma_sample == MDSS_MDP_CHROMA_H1V2)
+ ps->ystride[1] = 64 * 2;
+ else if (fmt->chroma_sample == MDSS_MDP_CHROMA_H2V1) {
+ ps->ystride[1] = 32 * 4;
+ ps->rau_h[1] = 4;
+ } else
+ ps->ystride[1] = 32 * 2;
+ } else if (fmt->fetch_planes == MDSS_MDP_PLANE_INTERLEAVED) {
+ ps->rau_cnt = DIV_ROUND_UP(w, 32);
+ ps->ystride[0] = 32 * 4;
+ ps->ystride[1] = 0;
+ ps->rau_h[0] = 4;
+ ps->rau_h[1] = 0;
+ } else {
+ pr_err("Invalid format=%d\n", fmt->format);
+ return -EINVAL;
+ }
+
+ stride_off = DIV_ROUND_UP(ps->rau_cnt, 8);
+ ps->ystride[0] = ps->ystride[0] * ps->rau_cnt * fmt->bpp + stride_off;
+ ps->ystride[1] = ps->ystride[1] * ps->rau_cnt * fmt->bpp + stride_off;
+ ps->num_planes = 2;
+
+ return 0;
+}
+
int mdss_mdp_get_plane_sizes(u32 format, u32 w, u32 h,
- struct mdss_mdp_plane_sizes *ps)
+ struct mdss_mdp_plane_sizes *ps, u32 bwc_mode)
{
struct mdss_mdp_format_params *fmt;
- int i;
+ int i, rc;
+ u32 bpp, stride_off;
if (ps == NULL)
return -EINVAL;
@@ -221,55 +274,69 @@
if (!fmt)
return -EINVAL;
+ bpp = fmt->bpp;
memset(ps, 0, sizeof(struct mdss_mdp_plane_sizes));
- if (fmt->fetch_planes == MDSS_MDP_PLANE_INTERLEAVED) {
- u32 bpp = fmt->bpp;
- ps->num_planes = 1;
- ps->plane_size[0] = w * h * bpp;
- ps->ystride[0] = w * bpp;
- } else if (format == MDP_Y_CBCR_H2V2_VENUS) {
- int cf = COLOR_FMT_NV12;
- ps->num_planes = 2;
- ps->ystride[0] = VENUS_Y_STRIDE(cf, w);
- ps->ystride[1] = VENUS_UV_STRIDE(cf, w);
- ps->plane_size[0] = VENUS_Y_SCANLINES(cf, h) * ps->ystride[0];
- ps->plane_size[1] = VENUS_UV_SCANLINES(cf, h) * ps->ystride[1];
+ if (bwc_mode) {
+ rc = mdss_mdp_get_rau_strides(w, h, fmt, ps);
+ if (rc)
+ return rc;
+ stride_off = DIV_ROUND_UP(h, ps->rau_h[0]);
+ ps->ystride[0] = ps->ystride[0] + ps->ystride[1];
+ ps->plane_size[0] = ps->ystride[0] * stride_off;
+ ps->ystride[1] = 2;
+ ps->plane_size[1] = ps->rau_cnt * ps->ystride[1] * stride_off;
+
} else {
- u8 hmap[] = { 1, 2, 1, 2 };
- u8 vmap[] = { 1, 1, 2, 2 };
- u8 horiz, vert, stride_align, height_align;
-
- horiz = hmap[fmt->chroma_sample];
- vert = vmap[fmt->chroma_sample];
-
- switch (format) {
- case MDP_Y_CR_CB_GH2V2:
- stride_align = 16;
- height_align = 1;
- break;
- default:
- stride_align = 1;
- height_align = 1;
- break;
- }
-
- ps->ystride[0] = ALIGN(w, stride_align);
- ps->ystride[1] = ALIGN(w / horiz, stride_align);
- ps->plane_size[0] = ps->ystride[0] * ALIGN(h, height_align);
- ps->plane_size[1] = ps->ystride[1] * (h / vert);
-
- if (fmt->fetch_planes == MDSS_MDP_PLANE_PSEUDO_PLANAR) {
+ if (fmt->fetch_planes == MDSS_MDP_PLANE_INTERLEAVED) {
+ ps->num_planes = 1;
+ ps->plane_size[0] = w * h * bpp;
+ ps->ystride[0] = w * bpp;
+ } else if (format == MDP_Y_CBCR_H2V2_VENUS) {
+ int cf = COLOR_FMT_NV12;
ps->num_planes = 2;
- ps->plane_size[1] *= 2;
- ps->ystride[1] *= 2;
- } else { /* planar */
- ps->num_planes = 3;
- ps->plane_size[2] = ps->plane_size[1];
- ps->ystride[2] = ps->ystride[1];
+ ps->ystride[0] = VENUS_Y_STRIDE(cf, w);
+ ps->ystride[1] = VENUS_UV_STRIDE(cf, w);
+ ps->plane_size[0] = VENUS_Y_SCANLINES(cf, h) *
+ ps->ystride[0];
+ ps->plane_size[1] = VENUS_UV_SCANLINES(cf, h) *
+ ps->ystride[1];
+ } else {
+ u8 hmap[] = { 1, 2, 1, 2 };
+ u8 vmap[] = { 1, 1, 2, 2 };
+ u8 horiz, vert, stride_align, height_align;
+
+ horiz = hmap[fmt->chroma_sample];
+ vert = vmap[fmt->chroma_sample];
+
+ switch (format) {
+ case MDP_Y_CR_CB_GH2V2:
+ stride_align = 16;
+ height_align = 1;
+ break;
+ default:
+ stride_align = 1;
+ height_align = 1;
+ break;
+ }
+
+ ps->ystride[0] = ALIGN(w, stride_align);
+ ps->ystride[1] = ALIGN(w / horiz, stride_align);
+ ps->plane_size[0] = ps->ystride[0] *
+ ALIGN(h, height_align);
+ ps->plane_size[1] = ps->ystride[1] * (h / vert);
+
+ if (fmt->fetch_planes == MDSS_MDP_PLANE_PSEUDO_PLANAR) {
+ ps->num_planes = 2;
+ ps->plane_size[1] *= 2;
+ ps->ystride[1] *= 2;
+ } else { /* planar */
+ ps->num_planes = 3;
+ ps->plane_size[2] = ps->plane_size[1];
+ ps->ystride[2] = ps->ystride[1];
+ }
}
}
-
for (i = 0; i < ps->num_planes; i++)
ps->total_size += ps->plane_size[i];
@@ -286,7 +353,8 @@
return -ENOMEM;
if (data->bwc_enabled) {
- return -EPERM; /* not supported */
+ data->num_planes = ps->num_planes;
+ data->p[1].addr = data->p[0].addr + ps->plane_size[0];
} else {
struct mdss_mdp_img_data *prev, *curr;
int i;
diff --git a/drivers/video/msm/mdss/mdss_mdp_wb.c b/drivers/video/msm/mdss/mdss_mdp_wb.c
index d24a7c9..88e7605 100644
--- a/drivers/video/msm/mdss/mdss_mdp_wb.c
+++ b/drivers/video/msm/mdss/mdss_mdp_wb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -124,18 +124,13 @@
int mdss_mdp_wb_set_secure(struct msm_fb_data_type *mfd, int enable)
{
- struct mdss_mdp_wb *wb;
+ struct mdss_mdp_wb *wb = mfd_to_wb(mfd);
+ struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
struct mdss_mdp_pipe *pipe;
struct mdss_mdp_mixer *mixer;
pr_debug("setting secure=%d\n", enable);
- wb = mfd->wb;
- if (wb == NULL) {
- pr_err("Invalid writeback session\n");
- return -ENODEV;
- }
-
wb->is_secure = enable;
pipe = wb->secure_pipe;
@@ -149,7 +144,7 @@
return 0;
}
- mixer = mdss_mdp_mixer_get(mfd->ctl, MDSS_MDP_MIXER_MUX_DEFAULT);
+ mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_DEFAULT);
if (!mixer) {
pr_err("Unable to find mixer for wb\n");
return -ENOENT;
@@ -190,14 +185,14 @@
static int mdss_mdp_wb_init(struct msm_fb_data_type *mfd)
{
- struct mdss_mdp_wb *wb;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ struct mdss_mdp_wb *wb = mfd_to_wb(mfd);
mutex_lock(&mdss_mdp_wb_buf_lock);
- wb = mfd->wb;
if (wb == NULL) {
wb = &mdss_mdp_wb_info;
wb->fb_ndx = mfd->index;
- mfd->wb = wb;
+ mdp5_data->wb = wb;
} else if (mfd->index != wb->fb_ndx) {
pr_err("only one writeback intf supported at a time\n");
return -EMLINK;
@@ -214,14 +209,15 @@
wb->state = WB_OPEN;
init_waitqueue_head(&wb->wait_q);
- mfd->wb = wb;
+ mdp5_data->wb = wb;
mutex_unlock(&mdss_mdp_wb_buf_lock);
return 0;
}
static int mdss_mdp_wb_terminate(struct msm_fb_data_type *mfd)
{
- struct mdss_mdp_wb *wb = mfd->wb;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
+ struct mdss_mdp_wb *wb = mfd_to_wb(mfd);
if (!wb) {
pr_err("unable to terminate, writeback is not initialized\n");
@@ -246,7 +242,7 @@
mdss_mdp_pipe_destroy(wb->secure_pipe);
mutex_unlock(&wb->lock);
- mfd->wb = NULL;
+ mdp5_data->wb = NULL;
mutex_unlock(&mdss_mdp_wb_buf_lock);
return 0;
@@ -254,7 +250,7 @@
static int mdss_mdp_wb_start(struct msm_fb_data_type *mfd)
{
- struct mdss_mdp_wb *wb = mfd->wb;
+ struct mdss_mdp_wb *wb = mfd_to_wb(mfd);
if (!wb) {
pr_err("unable to start, writeback is not initialized\n");
@@ -271,7 +267,7 @@
static int mdss_mdp_wb_stop(struct msm_fb_data_type *mfd)
{
- struct mdss_mdp_wb *wb = mfd->wb;
+ struct mdss_mdp_wb *wb = mfd_to_wb(mfd);
if (!wb) {
pr_err("unable to stop, writeback is not initialized\n");
@@ -343,8 +339,10 @@
}
static struct mdss_mdp_wb_data *get_user_node(struct msm_fb_data_type *mfd,
- struct msmfb_data *data) {
- struct mdss_mdp_wb *wb = mfd->wb;
+ struct msmfb_data *data)
+{
+
+ struct mdss_mdp_wb *wb = mfd_to_wb(mfd);
struct mdss_mdp_wb_data *node;
struct mdss_mdp_img_data *buf;
int ret;
@@ -383,9 +381,9 @@
}
static int mdss_mdp_wb_queue(struct msm_fb_data_type *mfd,
- struct msmfb_data *data, int local)
+ struct msmfb_data *data, int local)
{
- struct mdss_mdp_wb *wb = mfd->wb;
+ struct mdss_mdp_wb *wb = mfd_to_wb(mfd);
struct mdss_mdp_wb_data *node = NULL;
int ret = 0;
@@ -426,9 +424,9 @@
}
static int mdss_mdp_wb_dequeue(struct msm_fb_data_type *mfd,
- struct msmfb_data *data)
+ struct msmfb_data *data)
{
- struct mdss_mdp_wb *wb = mfd->wb;
+ struct mdss_mdp_wb *wb = mfd_to_wb(mfd);
struct mdss_mdp_wb_data *node = NULL;
int ret;
@@ -473,9 +471,10 @@
complete((struct completion *) arg);
}
-int mdss_mdp_wb_kickoff(struct mdss_mdp_ctl *ctl)
+int mdss_mdp_wb_kickoff(struct msm_fb_data_type *mfd)
{
- struct mdss_mdp_wb *wb;
+ struct mdss_mdp_wb *wb = mfd_to_wb(mfd);
+ struct mdss_mdp_ctl *ctl = mfd_to_ctl(mfd);
struct mdss_mdp_wb_data *node = NULL;
int ret = 0;
DECLARE_COMPLETION_ONSTACK(comp);
@@ -484,14 +483,10 @@
.priv_data = &comp,
};
- if (!ctl || !ctl->mfd)
- return -ENODEV;
-
if (!ctl->power_on)
return 0;
mutex_lock(&mdss_mdp_wb_buf_lock);
- wb = ctl->mfd->wb;
if (wb) {
mutex_lock(&wb->lock);
/* in case of reinit of control path need to reset secure */
@@ -540,7 +535,8 @@
return ret;
}
-int mdss_mdp_wb_ioctl_handler(struct msm_fb_data_type *mfd, u32 cmd, void *arg)
+int mdss_mdp_wb_ioctl_handler(struct msm_fb_data_type *mfd, u32 cmd,
+ void *arg)
{
struct msmfb_data data;
int ret = -ENOSYS;
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index 31fb2e7..d230100 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -58,9 +58,9 @@
enum mdss_intf_events {
MDSS_EVENT_RESET,
MDSS_EVENT_UNBLANK,
- MDSS_EVENT_TIMEGEN_ON,
+ MDSS_EVENT_PANEL_ON,
MDSS_EVENT_BLANK,
- MDSS_EVENT_TIMEGEN_OFF,
+ MDSS_EVENT_PANEL_OFF,
MDSS_EVENT_CLOSE,
MDSS_EVENT_SUSPEND,
MDSS_EVENT_RESUME,
@@ -69,19 +69,7 @@
MDSS_EVENT_FB_REGISTERED,
};
-/* panel info type */
struct lcd_panel_info {
- u32 vsync_enable;
- u32 refx100;
- u32 v_back_porch;
- u32 v_front_porch;
- u32 v_pulse_width;
- u32 hw_vsync_mode;
- u32 vsync_notifier_period;
- u32 rev;
-};
-
-struct lcdc_panel_info {
u32 h_back_porch;
u32 h_front_porch;
u32 h_pulse_width;
@@ -153,6 +141,9 @@
char no_max_pkt_size;
/* Clock required during LP commands */
char force_clk_lane_hs;
+
+ char vsync_enable;
+ char hw_vsync_mode;
};
enum lvds_mode {
@@ -166,6 +157,26 @@
char channel_swap;
};
+struct fbc_panel_info {
+ u32 enabled;
+ u32 target_bpp;
+ u32 comp_mode;
+ u32 qerr_enable;
+ u32 cd_bias;
+ u32 pat_enable;
+ u32 vlc_enable;
+ u32 bflc_enable;
+
+ u32 line_x_budget;
+ u32 block_x_budget;
+ u32 block_budget;
+
+ u32 lossless_mode_thd;
+ u32 lossy_mode_thd;
+ u32 lossy_rgb_thd;
+ u32 lossy_mode_idx;
+};
+
struct mdss_panel_info {
u32 xres;
u32 yres;
@@ -183,13 +194,17 @@
u32 is_3d_panel;
u32 out_format;
u32 vic; /* video identification code */
+ int bklt_ctrl; /* backlight ctrl */
+ int pwm_gpio;
+ int pwm_lpg_chan;
+ int pwm_period;
u32 cont_splash_enabled;
struct ion_handle *splash_ihdl;
u32 panel_power_on;
- struct lcd_panel_info lcd;
- struct lcdc_panel_info lcdc;
+ struct lcd_panel_info lcdc;
+ struct fbc_panel_info fbc;
struct mipi_panel_info mipi;
struct lvds_panel_info lvds;
};
diff --git a/drivers/video/msm/mdss/mdss_qpic.c b/drivers/video/msm/mdss/mdss_qpic.c
index 647504f..be02113 100644
--- a/drivers/video/msm/mdss/mdss_qpic.c
+++ b/drivers/video/msm/mdss/mdss_qpic.c
@@ -113,11 +113,24 @@
(u32 *)fb_offset, size);
}
-int mdss_mdp_alloc_fb_mem(struct msm_fb_data_type *mfd,
- u32 size, u32 *phys, void **virt)
+int mdss_qpic_alloc_fb_mem(struct msm_fb_data_type *mfd)
{
+ size_t size;
+ u32 yres = mfd->fbi->var.yres_virtual;
+
+ size = PAGE_ALIGN(mfd->fbi->fix.line_length * yres);
+
if (!qpic_res->res_init)
return -EINVAL;
+
+ if (mfd->index != 0) {
+ mfd->fbi->fix.smem_start = 0;
+ mfd->fbi->screen_base = NULL;
+ mfd->fbi->fix.smem_len = 0;
+ mfd->iova = 0;
+ return 0;
+ }
+
if (!qpic_res->fb_virt) {
qpic_res->fb_virt = (void *)dmam_alloc_coherent(
&qpic_res->pdev->dev,
@@ -132,29 +145,31 @@
qpic_res->cmd_buf_virt = qpic_res->fb_virt + size;
qpic_res->cmd_buf_phys = qpic_res->fb_phys + size;
}
- *phys = qpic_res->fb_phys;
- *virt = qpic_res->fb_virt;
+ mfd->fbi->fix.smem_start = qpic_res->fb_phys;
+ mfd->fbi->screen_base = qpic_res->fb_virt;
+ mfd->fbi->fix.smem_len = size;
+ mfd->iova = 0;
return 0;
}
-u32 mdss_mdp_fb_stride(u32 fb_index, u32 xres, int bpp)
+u32 mdss_qpic_fb_stride(u32 fb_index, u32 xres, int bpp)
{
return xres * bpp;
}
-int mdss_mdp_overlay_init(struct msm_fb_data_type *mfd)
+int mdss_qpic_overlay_init(struct msm_fb_data_type *mfd)
{
- mfd->on_fnc = qpic_on;
- mfd->off_fnc = qpic_off;
- mfd->dma_fnc = mdss_qpic_pan_display;
+ struct msm_mdp_interface *qpic_interface = &mfd->mdp;
+ qpic_interface->on_fnc = qpic_on;
+ qpic_interface->off_fnc = qpic_off;
+ qpic_interface->do_histogram = NULL;
+ qpic_interface->cursor_update = NULL;
+ qpic_interface->dma_fnc = mdss_qpic_pan_display;
+ qpic_interface->ioctl_handler = NULL;
+ qpic_interface->kickoff_fnc = NULL;
return 0;
}
-u32 mdss_get_panel_framerate(struct msm_fb_data_type *mfd)
-{
- return qpic_panel_get_framerate();
-}
-
int qpic_register_panel(struct mdss_panel_data *pdata)
{
struct platform_device *mdss_fb_dev = NULL;
@@ -511,6 +526,12 @@
{
struct resource *res;
int rc = 0;
+ static struct msm_mdp_interface qpic_interface = {
+ .init_fnc = mdss_qpic_overlay_init,
+ .fb_mem_alloc_fnc = mdss_qpic_alloc_fb_mem,
+ .fb_stride = mdss_qpic_fb_stride,
+ };
+
if (!pdev->dev.of_node) {
pr_err("qpic driver only supports device tree probe\n");
@@ -564,6 +585,11 @@
qpic_res->irq = res->start;
qpic_res->res_init = true;
+
+ rc = mdss_fb_register_mdp_instance(&qpic_interface);
+ if (rc)
+ pr_err("unable to register QPIC instance\n");
+
probe_done:
return rc;
}
@@ -585,124 +611,4 @@
module_init(mdss_qpic_driver_init);
-int mdss_mdp_pa_config(struct mdss_mdp_ctl *ctl,
- struct mdp_pa_cfg_data *config, u32 *copyback)
-{
- return 0;
-}
-int mdss_mdp_pcc_config(struct mdss_mdp_ctl *ctl,
- struct mdp_pcc_cfg_data *cfg_ptr, u32 *copyback)
-{
- return 0;
-}
-
-int mdss_mdp_igc_lut_config(struct mdss_mdp_ctl *ctl,
- struct mdp_igc_lut_data *config, u32 *copyback)
-{
- return 0;
-}
-
-int mdss_mdp_argc_config(struct mdss_mdp_ctl *ctl,
- struct mdp_pgc_lut_data *config, u32 *copyback)
-{
- return 0;
-}
-
-int mdss_mdp_hist_lut_config(struct mdss_mdp_ctl *ctl,
- struct mdp_hist_lut_data *config, u32 *copyback)
-{
- return 0;
-}
-
-int mdss_mdp_dither_config(struct mdss_mdp_ctl *ctl,
- struct mdp_dither_cfg_data *config, u32 *copyback)
-{
- return 0;
-}
-
-int mdss_mdp_gamut_config(struct mdss_mdp_ctl *ctl,
- struct mdp_gamut_cfg_data *config, u32 *copyback)
-{
- return 0;
-}
-
-int mdss_mdp_histogram_start(struct mdss_mdp_ctl *ctl,
- struct mdp_histogram_start_req *req)
-{
- return 0;
-}
-
-int mdss_mdp_histogram_stop(struct mdss_mdp_ctl *ctl, u32 block)
-{
- return 0;
-}
-
-int mdss_mdp_hist_collect(struct mdss_mdp_ctl *ctl,
- struct mdp_histogram_data *hist,
- u32 *hist_data_addr)
-{
- return 0;
-}
-
-int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl)
-{
- return 0;
-}
-
-void mdss_mdp_clk_ctrl(int enable, int isr)
-{
-}
-
-int mdss_mdp_copy_splash_screen(struct mdss_panel_data *pdata)
-{
- return 0;
-}
-
-void mdss_mdp_footswitch_ctrl_splash(int on)
-{
-}
-
-int msm_fb_writeback_init(struct fb_info *info)
-{
- return 0;
-}
-EXPORT_SYMBOL(msm_fb_writeback_init);
-
-int msm_fb_writeback_start(struct fb_info *info)
-{
- return 0;
-}
-EXPORT_SYMBOL(msm_fb_writeback_start);
-
-int msm_fb_writeback_queue_buffer(struct fb_info *info,
- struct msmfb_data *data)
-{
- return 0;
-}
-EXPORT_SYMBOL(msm_fb_writeback_queue_buffer);
-
-int msm_fb_writeback_dequeue_buffer(struct fb_info *info,
- struct msmfb_data *data)
-{
- return 0;
-}
-EXPORT_SYMBOL(msm_fb_writeback_dequeue_buffer);
-
-int msm_fb_writeback_stop(struct fb_info *info)
-{
- return 0;
-}
-EXPORT_SYMBOL(msm_fb_writeback_stop);
-
-int msm_fb_writeback_terminate(struct fb_info *info)
-{
- return 0;
-}
-EXPORT_SYMBOL(msm_fb_writeback_terminate);
-
-int msm_fb_get_iommu_domain(struct fb_info *info, int domain)
-{
- return 0;
-}
-EXPORT_SYMBOL(msm_fb_get_iommu_domain);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
index 69120e8..b6dc085 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
@@ -14,7 +14,6 @@
#ifndef _VCD_DDL_H_
#define _VCD_DDL_H_
-#include <mach/msm_subsystem_map.h>
#include "vcd_ddl_api.h"
#include "vcd_ddl_core.h"
#include "vcd_ddl_utils.h"
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
index 61099b0..54b256d 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -12,7 +12,7 @@
*/
#include <linux/memory_alloc.h>
#include <linux/delay.h>
-#include <mach/msm_subsystem_map.h>
+#include <mach/iommu_domains.h>
#include <mach/subsystem_restart.h>
#include "vcd_ddl_utils.h"
#include "vcd_ddl.h"
@@ -25,8 +25,6 @@
};
static struct time_data proc_time[MAX_TIME_DATA];
#define DDL_MSG_TIME(x...) printk(KERN_DEBUG x)
-static unsigned int vidc_mmu_subsystem[] = {
- MSM_SUBSYSTEM_VIDEO, MSM_SUBSYSTEM_VIDEO_FWARE};
#ifdef DDL_BUF_LOG
static void ddl_print_buffer(struct ddl_context *ddl_context,
@@ -39,13 +37,10 @@
void *ddl_pmem_alloc(struct ddl_buf_addr *addr, size_t sz, u32 alignment)
{
u32 alloc_size, offset = 0 ;
- u32 index = 0;
struct ddl_context *ddl_context;
- struct msm_mapped_buffer *mapped_buffer = NULL;
unsigned long iova = 0;
unsigned long buffer_size = 0;
unsigned long *kernel_vaddr = NULL;
- unsigned long flags = 0;
int ret = 0;
ion_phys_addr_t phyaddr = 0;
size_t len = 0;
@@ -128,51 +123,10 @@
addr->align_virtual_addr = addr->virtual_base_addr + offset;
addr->buffer_size = alloc_size;
} else {
- addr->alloced_phys_addr = (phys_addr_t)
- allocate_contiguous_memory_nomap(alloc_size,
- res_trk_get_mem_type(), SZ_4K);
- if (!addr->alloced_phys_addr) {
- DDL_MSG_ERROR("%s() : acm alloc failed (%d)\n",
- __func__, alloc_size);
- goto bail_out;
- }
- flags = MSM_SUBSYSTEM_MAP_IOVA | MSM_SUBSYSTEM_MAP_KADDR;
- if (alignment == DDL_KILO_BYTE(128))
- index = 1;
- else if (alignment > SZ_4K)
- flags |= MSM_SUBSYSTEM_ALIGN_IOVA_8K;
-
- addr->mapped_buffer =
- msm_subsystem_map_buffer((unsigned long)addr->alloced_phys_addr,
- alloc_size, flags, &vidc_mmu_subsystem[index],
- sizeof(vidc_mmu_subsystem[index])/sizeof(unsigned int));
- if (IS_ERR(addr->mapped_buffer)) {
- pr_err(" %s() buffer map failed", __func__);
- goto free_acm_alloc;
- }
- mapped_buffer = addr->mapped_buffer;
- if (!mapped_buffer->vaddr || !mapped_buffer->iova[0]) {
- pr_err("%s() map buffers failed\n", __func__);
- goto free_map_buffers;
- }
- addr->physical_base_addr = (u8 *)mapped_buffer->iova[0];
- addr->virtual_base_addr = mapped_buffer->vaddr;
- addr->align_physical_addr = (u8 *) DDL_ALIGN((u32)
- addr->physical_base_addr, alignment);
- offset = (u32)(addr->align_physical_addr -
- addr->physical_base_addr);
- addr->align_virtual_addr = addr->virtual_base_addr + offset;
- addr->buffer_size = sz;
+ pr_err("ION must be enabled.");
+ goto bail_out;
}
return addr->virtual_base_addr;
-free_map_buffers:
- msm_subsystem_unmap_buffer(addr->mapped_buffer);
- addr->mapped_buffer = NULL;
-free_acm_alloc:
- free_contiguous_memory_by_paddr(
- (unsigned long)addr->alloced_phys_addr);
- addr->alloced_phys_addr = (phys_addr_t)NULL;
- return NULL;
unmap_ion_alloc:
ion_unmap_kernel(ddl_context->video_ion_client,
addr->alloc_handle);
@@ -207,12 +161,6 @@
ion_free(ddl_context->video_ion_client,
addr->alloc_handle);
}
- } else {
- if (addr->mapped_buffer)
- msm_subsystem_unmap_buffer(addr->mapped_buffer);
- if (addr->alloced_phys_addr)
- free_contiguous_memory_by_paddr(
- (unsigned long)addr->alloced_phys_addr);
}
memset(addr, 0, sizeof(struct ddl_buf_addr));
}
diff --git a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
index c15218d..5c15d9a 100644
--- a/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
+++ b/drivers/video/msm/vidc/1080p/resource_tracker/vcd_res_tracker.c
@@ -18,6 +18,7 @@
#include <linux/pm_runtime.h>
#include <mach/clk.h>
#include <mach/msm_memtypes.h>
+#include <mach/iommu_domains.h>
#include <linux/interrupt.h>
#include <linux/memory_alloc.h>
#include <asm/sizes.h>
@@ -30,8 +31,6 @@
static unsigned int vidc_clk_table[5] = {
48000000, 133330000, 200000000, 228570000, 266670000,
};
-static unsigned int restrk_mmu_subsystem[] = {
- MSM_SUBSYSTEM_VIDEO, MSM_SUBSYSTEM_VIDEO_FWARE};
static struct res_trk_context resource_context;
#define VIDC_FW "vidc_1080p.fw"
@@ -56,10 +55,8 @@
static void *res_trk_pmem_map
(struct ddl_buf_addr *addr, size_t sz, u32 alignment)
{
- u32 offset = 0, flags = 0;
- u32 index = 0;
+ u32 offset = 0;
struct ddl_context *ddl_context;
- struct msm_mapped_buffer *mapped_buffer = NULL;
int ret = 0;
unsigned long iova = 0;
unsigned long buffer_size = 0;
@@ -100,53 +97,11 @@
addr->align_virtual_addr = addr->virtual_base_addr + offset;
addr->buffer_size = buffer_size;
} else {
- if (!res_trk_check_for_sec_session()) {
- if (!addr->alloced_phys_addr) {
- pr_err(" %s() alloced addres NULL", __func__);
- goto bail_out;
- }
- flags = MSM_SUBSYSTEM_MAP_IOVA |
- MSM_SUBSYSTEM_MAP_KADDR;
- if (alignment == DDL_KILO_BYTE(128))
- index = 1;
- else if (alignment > SZ_4K)
- flags |= MSM_SUBSYSTEM_ALIGN_IOVA_8K;
- addr->mapped_buffer =
- msm_subsystem_map_buffer(
- (unsigned long)addr->alloced_phys_addr,
- sz, flags, &restrk_mmu_subsystem[index],
- sizeof(restrk_mmu_subsystem[index])/
- sizeof(unsigned int));
- if (IS_ERR(addr->mapped_buffer)) {
- pr_err(" %s() buffer map failed", __func__);
- goto bail_out;
- }
- mapped_buffer = addr->mapped_buffer;
- if (!mapped_buffer->vaddr || !mapped_buffer->iova[0]) {
- pr_err("%s() map buffers failed\n", __func__);
- goto bail_out;
- }
- addr->physical_base_addr =
- (u8 *)mapped_buffer->iova[0];
- addr->virtual_base_addr =
- mapped_buffer->vaddr;
- } else {
- addr->physical_base_addr =
- (u8 *) addr->alloced_phys_addr;
- addr->virtual_base_addr =
- (u8 *)addr->alloced_phys_addr;
- }
- addr->align_physical_addr = (u8 *) DDL_ALIGN((u32)
- addr->physical_base_addr, alignment);
- offset = (u32)(addr->align_physical_addr -
- addr->physical_base_addr);
- addr->align_virtual_addr = addr->virtual_base_addr + offset;
- addr->buffer_size = sz;
+ pr_err("ION must be enabled.");
+ goto bail_out;
}
return addr->virtual_base_addr;
bail_out:
- if (IS_ERR(addr->mapped_buffer))
- msm_subsystem_unmap_buffer(addr->mapped_buffer);
return NULL;
ion_unmap_bail_out:
if (!IS_ERR_OR_NULL(addr->alloc_handle)) {
@@ -171,12 +126,6 @@
addr->alloc_handle);
addr->alloc_handle = NULL;
}
- } else {
- if (addr->mapped_buffer)
- msm_subsystem_unmap_buffer(addr->mapped_buffer);
- if (addr->alloced_phys_addr)
- free_contiguous_memory_by_paddr(
- (unsigned long)addr->alloced_phys_addr);
}
memset(addr, 0 , sizeof(struct ddl_buf_addr));
}
@@ -263,8 +212,7 @@
addr->virtual_base_addr = NULL;
addr->physical_base_addr = NULL;
}
- } else if (addr->mapped_buffer)
- msm_subsystem_unmap_buffer(addr->mapped_buffer);
+ }
addr->mapped_buffer = NULL;
}
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
index 7a79a40..383a91b 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl.h
@@ -12,7 +12,6 @@
*/
#ifndef _VCD_DDL_H_
#define _VCD_DDL_H_
-#include <mach/msm_subsystem_map.h>
#include "vcd_ddl_api.h"
#include "vcd_ddl_utils.h"
#include "vcd_ddl_firmware.h"
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
index 672c049..edc8112 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -87,11 +87,9 @@
void ddl_pmem_alloc(struct ddl_buf_addr *buff_addr, size_t sz, u32 align)
{
u32 guard_bytes, align_mask;
- u32 physical_addr;
u32 align_offset;
- u32 alloc_size, flags = 0;
+ u32 alloc_size;
struct ddl_context *ddl_context;
- struct msm_mapped_buffer *mapped_buffer = NULL;
unsigned long *kernel_vaddr = NULL;
ion_phys_addr_t phyaddr = 0;
size_t len = 0;
@@ -155,36 +153,8 @@
(u32)buff_addr->virtual_base_addr,
alloc_size, align, len);
} else {
- physical_addr = (u32)
- allocate_contiguous_memory_nomap(alloc_size,
- ddl_context->memtype, SZ_4K);
- if (!physical_addr) {
- ERR("\n%s(): DDL pmem allocate failed\n",
- __func__);
- goto bailout;
- }
- buff_addr->physical_base_addr = (u32 *) physical_addr;
- flags = MSM_SUBSYSTEM_MAP_KADDR;
- buff_addr->mapped_buffer =
- msm_subsystem_map_buffer((unsigned long)physical_addr,
- alloc_size, flags, NULL, 0);
- if (IS_ERR(buff_addr->mapped_buffer)) {
- ERR("\n%s() buffer map failed\n", __func__);
- goto free_pmem_buffer;
- }
- mapped_buffer = buff_addr->mapped_buffer;
- if (!mapped_buffer->vaddr) {
- ERR("\n%s() mapped virtual address is NULL\n",
- __func__);
- goto unmap_pmem_buffer;
- }
- buff_addr->virtual_base_addr = mapped_buffer->vaddr;
- DBG("ddl_pmem_alloc: mem_type(0x%x), phys(0x%x),"\
- " virt(0x%x), sz(%u), align(%u)",
- (u32)buff_addr->mem_type,
- (u32)buff_addr->physical_base_addr,
- (u32)buff_addr->virtual_base_addr,
- alloc_size, SZ_4K);
+ pr_err("ION must be enabled.");
+ goto bailout;
}
memset(buff_addr->virtual_base_addr, 0 , sz + guard_bytes);
@@ -205,16 +175,6 @@
(u32)buff_addr->align_virtual_addr);
return;
-unmap_pmem_buffer:
- if (buff_addr->mapped_buffer)
- msm_subsystem_unmap_buffer(buff_addr->mapped_buffer);
-free_pmem_buffer:
- if (buff_addr->physical_base_addr)
- free_contiguous_memory_by_paddr((unsigned long)
- buff_addr->physical_base_addr);
- memset(buff_addr, 0, sizeof(struct ddl_buf_addr));
- return;
-
unmap_ion_buffer:
if (ddl_context->video_ion_client) {
if (buff_addr->alloc_handle)
@@ -253,13 +213,6 @@
ion_free(ddl_context->video_ion_client,
buff_addr->alloc_handle);
}
- } else {
- if (buff_addr->mapped_buffer)
- msm_subsystem_unmap_buffer(
- buff_addr->mapped_buffer);
- if (buff_addr->physical_base_addr)
- free_contiguous_memory_by_paddr((unsigned long)
- buff_addr->physical_base_addr);
}
memset(buff_addr, 0, sizeof(struct ddl_buf_addr));
}
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index 1c69d8f..ec27b00 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -28,10 +28,10 @@
#include <linux/clk.h>
#include <linux/timer.h>
-#include <mach/msm_subsystem_map.h>
#include <media/msm/vidc_type.h>
#include <media/msm/vcd_api.h>
#include <media/msm/vidc_init.h>
+#include <mach/iommu_domains.h>
#include "vcd_res_tracker_api.h"
#include "vdec_internal.h"
@@ -1241,13 +1241,6 @@
if (!client_ctx)
return false;
- if (client_ctx->vcd_meta_buffer.client_data)
- msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
- client_ctx->vcd_meta_buffer.client_data);
-
- if (client_ctx->vcd_meta_buffer.client_data_iommu)
- msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
- client_ctx->vcd_meta_buffer.client_data_iommu);
vcd_property_hdr.prop_id = VCD_I_FREE_EXT_METABUFFER;
vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
@@ -1300,9 +1293,6 @@
if (!client_ctx)
return false;
- if (client_ctx->vcd_h264_mv_buffer.client_data)
- msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
- client_ctx->vcd_h264_mv_buffer.client_data);
vcd_property_hdr.prop_id = VCD_I_FREE_H264_MV_BUFFER;
vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
index 3dae4be1..06b690d 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -27,10 +27,10 @@
#include <linux/workqueue.h>
#include <linux/clk.h>
-#include <mach/msm_subsystem_map.h>
#include <media/msm/vidc_type.h>
#include <media/msm/vcd_api.h>
#include <media/msm/vidc_init.h>
+#include <mach/iommu_domains.h>
#include "vcd_res_tracker_api.h"
#include "venc_internal.h"
@@ -1948,9 +1948,6 @@
venc_recon->pbuffer);
return false;
}
- if (control->client_data)
- msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
- control->client_data);
vcd_property_hdr.prop_id = VCD_I_FREE_RECON_BUFFERS;
vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index 72a1d5f..cf01622 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -30,7 +30,7 @@
#include <linux/debugfs.h>
#include <mach/clk.h>
#include <linux/pm_runtime.h>
-#include <mach/msm_subsystem_map.h>
+#include <mach/iommu_domains.h>
#include <media/msm/vcd_api.h>
#include <media/msm/vidc_init.h>
#include "vidc_init_internal.h"
@@ -420,12 +420,6 @@
if (!client_ctx->user_ion_client)
goto bail_out_cleanup;
for (i = 0; i < *num_of_buffers; ++i) {
- if (buf_addr_table[i].client_data) {
- msm_subsystem_unmap_buffer(
- (struct msm_mapped_buffer *)
- buf_addr_table[i].client_data);
- buf_addr_table[i].client_data = NULL;
- }
if (!IS_ERR_OR_NULL(buf_addr_table[i].buff_ion_handle)) {
if (!IS_ERR_OR_NULL(client_ctx->user_ion_client)) {
ion_unmap_kernel(client_ctx->user_ion_client,
@@ -448,11 +442,6 @@
}
}
}
- if (client_ctx->vcd_h264_mv_buffer.client_data) {
- msm_subsystem_unmap_buffer((struct msm_mapped_buffer *)
- client_ctx->vcd_h264_mv_buffer.client_data);
- client_ctx->vcd_h264_mv_buffer.client_data = NULL;
- }
if (!IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
if (!IS_ERR_OR_NULL(client_ctx->user_ion_client)) {
ion_unmap_kernel(client_ctx->user_ion_client,
@@ -608,7 +597,7 @@
} else {
if (!vcd_get_ion_status()) {
pr_err("PMEM not available\n");
- return false;
+ goto bail_out_add;
} else {
buff_ion_handle = ion_import_dma_buf(
client_ctx->user_ion_client, pmem_fd);
@@ -808,11 +797,6 @@
__func__, client_ctx, user_vaddr);
goto bail_out_del;
}
- if (buf_addr_table[i].client_data) {
- msm_subsystem_unmap_buffer(
- (struct msm_mapped_buffer *)buf_addr_table[i].client_data);
- buf_addr_table[i].client_data = NULL;
- }
*kernel_vaddr = buf_addr_table[i].kernel_vaddr;
if (buf_addr_table[i].buff_ion_handle) {
ion_unmap_kernel(client_ctx->user_ion_client,
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 09cd91d..f7424ed 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -11,9 +11,9 @@
*
*/
#include <linux/memory_alloc.h>
-#include <mach/msm_subsystem_map.h>
#include <asm/div64.h>
#include <media/msm/vidc_type.h>
+#include <mach/iommu_domains.h>
#include "vcd.h"
#include "vdec_internal.h"
@@ -24,19 +24,17 @@
struct vcd_msm_map_buffer {
phys_addr_t phy_addr;
- struct msm_mapped_buffer *mapped_buffer;
+ void *vaddr;
struct ion_handle *alloc_handle;
u32 in_use;
};
static struct vcd_msm_map_buffer msm_mapped_buffer_table[MAP_TABLE_SZ];
-static unsigned int vidc_mmu_subsystem[] = {MSM_SUBSYSTEM_VIDEO};
static int vcd_pmem_alloc(size_t sz, u8 **kernel_vaddr, u8 **phy_addr,
struct vcd_clnt_ctxt *cctxt)
{
- u32 memtype, i = 0, flags = 0;
+ u32 memtype, i = 0;
struct vcd_msm_map_buffer *map_buffer = NULL;
- struct msm_mapped_buffer *mapped_buffer = NULL;
unsigned long iova = 0;
unsigned long buffer_size = 0;
int ret = 0;
@@ -64,31 +62,8 @@
res_trk_set_mem_type(DDL_MM_MEM);
memtype = res_trk_get_mem_type();
if (!cctxt->vcd_enable_ion) {
- map_buffer->phy_addr = (phys_addr_t)
- allocate_contiguous_memory_nomap(sz, memtype, SZ_4K);
- if (!map_buffer->phy_addr) {
- pr_err("%s() acm alloc failed", __func__);
- goto free_map_table;
- }
- flags = MSM_SUBSYSTEM_MAP_IOVA | MSM_SUBSYSTEM_MAP_KADDR;
- map_buffer->mapped_buffer =
- msm_subsystem_map_buffer((unsigned long)map_buffer->phy_addr,
- sz, flags, vidc_mmu_subsystem,
- sizeof(vidc_mmu_subsystem)/sizeof(unsigned int));
- if (IS_ERR(map_buffer->mapped_buffer)) {
- pr_err(" %s() buffer map failed", __func__);
- goto free_acm_alloc;
- }
- mapped_buffer = map_buffer->mapped_buffer;
- if (!mapped_buffer->vaddr || !mapped_buffer->iova[0]) {
- pr_err("%s() map buffers failed", __func__);
- goto free_map_buffers;
- }
- *phy_addr = (u8 *) mapped_buffer->iova[0];
- *kernel_vaddr = (u8 *) mapped_buffer->vaddr;
- VCD_MSG_LOW("vcd_pmem_alloc: phys(0x%x), virt(0x%x), "\
- "sz(%u), flags(0x%x)", (u32)*phy_addr,
- (u32)*kernel_vaddr, sz, (u32)flags);
+ pr_err("ION must be enabled\n");
+ goto free_map_table;
} else {
map_buffer->alloc_handle = ion_alloc(
cctxt->vcd_ion_client, sz, SZ_4K,
@@ -106,6 +81,7 @@
*kernel_vaddr = (u8 *) ion_map_kernel(
cctxt->vcd_ion_client,
map_buffer->alloc_handle);
+ map_buffer->vaddr = *kernel_vaddr;
if (!(*kernel_vaddr)) {
pr_err("%s() ION map failed", __func__);
goto ion_free_bailout;
@@ -143,8 +119,6 @@
goto free_map_table;
}
*phy_addr = (u8 *)map_buffer->phy_addr;
- mapped_buffer = NULL;
- map_buffer->mapped_buffer = NULL;
VCD_MSG_LOW("vcd_ion_alloc: phys(0x%x), virt(0x%x), "\
"sz(%u), ionflags(0x%x)", (u32)*phy_addr,
(u32)*kernel_vaddr, sz, (u32)ionflag);
@@ -152,15 +126,6 @@
return 0;
-free_map_buffers:
- if (map_buffer->mapped_buffer)
- msm_subsystem_unmap_buffer(map_buffer->mapped_buffer);
-free_acm_alloc:
- if (!cctxt->vcd_enable_ion) {
- free_contiguous_memory_by_paddr(
- (unsigned long)map_buffer->phy_addr);
- }
- return -ENOMEM;
ion_map_bailout:
ion_unmap_kernel(cctxt->vcd_ion_client, map_buffer->alloc_handle);
ion_free_bailout:
@@ -183,8 +148,7 @@
}
for (i = 0; i < MAP_TABLE_SZ; i++) {
if (msm_mapped_buffer_table[i].in_use &&
- (msm_mapped_buffer_table[i]
- .mapped_buffer->vaddr == kernel_vaddr)) {
+ (msm_mapped_buffer_table[i].vaddr == kernel_vaddr)) {
map_buffer = &msm_mapped_buffer_table[i];
map_buffer->in_use = 0;
break;
@@ -194,8 +158,6 @@
pr_err("%s() Entry not found", __func__);
goto bailout;
}
- if (map_buffer->mapped_buffer)
- msm_subsystem_unmap_buffer(map_buffer->mapped_buffer);
if (cctxt->vcd_enable_ion) {
VCD_MSG_LOW("vcd_ion_free: phys(0x%x), virt(0x%x)",
(u32)phy_addr, (u32)kernel_vaddr);
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index ddcd354..de8b4cb 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -209,7 +209,8 @@
if (!new_transaction)
goto alloc_transaction;
write_lock(&journal->j_state_lock);
- if (!journal->j_running_transaction) {
+ if (!journal->j_running_transaction &&
+ !journal->j_barrier_count) {
jbd2_get_transaction(journal, new_transaction);
new_transaction = NULL;
}
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 7939832..969b400 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -20,6 +20,7 @@
#define DEINIT_TYPE 16
#define USER_SPACE_DATA_TYPE 32
#define DCI_DATA_TYPE 64
+#define CALLBACK_DATA_TYPE 128
#define USB_MODE 1
#define MEMORY_DEVICE_MODE 2
#define NO_LOGGING_MODE 3
diff --git a/include/linux/input/synaptics_dsx.h b/include/linux/input/synaptics_dsx.h
index 56616d7..f90f59e 100644
--- a/include/linux/input/synaptics_dsx.h
+++ b/include/linux/input/synaptics_dsx.h
@@ -55,6 +55,7 @@
unsigned reset_gpio;
unsigned panel_x;
unsigned panel_y;
+ const char *fw_image_name;
int (*gpio_config)(unsigned gpio, bool configure);
struct synaptics_rmi4_capacitance_button_map *capacitance_button_map;
};
diff --git a/include/linux/ion.h b/include/linux/ion.h
index fb1c5f6..67b5e6c 100644
--- a/include/linux/ion.h
+++ b/include/linux/ion.h
@@ -33,14 +33,12 @@
* @ION_HEAP_TYPE_CP: memory allocated from a prereserved
* carveout heap, allocations are physically
* contiguous. Used for content protection.
- * @ION_HEAP_TYPE_DMA: memory allocated via DMA API
* @ION_HEAP_END: helper for iterating over heaps
*/
enum ion_heap_type {
ION_HEAP_TYPE_SYSTEM,
ION_HEAP_TYPE_SYSTEM_CONTIG,
ION_HEAP_TYPE_CARVEOUT,
- ION_HEAP_TYPE_DMA,
ION_HEAP_TYPE_CUSTOM, /* must be last so device specific heaps always
are at the end of this enum */
ION_NUM_HEAPS,
@@ -49,7 +47,6 @@
#define ION_HEAP_SYSTEM_MASK (1 << ION_HEAP_TYPE_SYSTEM)
#define ION_HEAP_SYSTEM_CONTIG_MASK (1 << ION_HEAP_TYPE_SYSTEM_CONTIG)
#define ION_HEAP_CARVEOUT_MASK (1 << ION_HEAP_TYPE_CARVEOUT)
-#define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA)
/**
* heap flags - the lower 16 bits are used by core ion, the upper 16
@@ -59,6 +56,9 @@
cached, ion will do cache
maintenance when the buffer is
mapped for dma */
+#define ION_FLAG_CACHED_NEEDS_SYNC 2 /* mappings of this buffer will created
+ at mmap time, if this is set
+ caches must be managed manually */
#ifdef __KERNEL__
#include <linux/err.h>
@@ -606,6 +606,16 @@
#define ION_IOC_IMPORT _IOWR(ION_IOC_MAGIC, 5, struct ion_fd_data)
/**
+ * DOC: ION_IOC_SYNC - syncs a shared file descriptors to memory
+ *
+ * Deprecated in favor of using the dma_buf api's correctly (syncing
+ * will happend automatically when the buffer is mapped to a device).
+ * If necessary should be used after touching a cached buffer from the cpu,
+ * this will make the buffer in memory coherent.
+ */
+#define ION_IOC_SYNC _IOWR(ION_IOC_MAGIC, 7, struct ion_fd_data)
+
+/**
* DOC: ION_IOC_CUSTOM - call architecture specific ion ioctl
*
* Takes the argument of the architecture specific ioctl to call and
diff --git a/include/linux/mfd/pm8xxx/ccadc.h b/include/linux/mfd/pm8xxx/ccadc.h
index 955e286..a29486f 100644
--- a/include/linux/mfd/pm8xxx/ccadc.h
+++ b/include/linux/mfd/pm8xxx/ccadc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -26,11 +26,15 @@
* @ccadc_cdata: core data for the ccadc driver containing channel info
* @r_sense_uohm: sense resistor value in (micro Ohms)
* @calib_delay_ms: how often should the adc calculate gain and offset
+ * @periodic_wakeup: a flag to indicate that this system wakeups periodically
+ * for calibration/other housekeeping activities. The ccadc
+ * does a quick calibration while resuming
*/
struct pm8xxx_ccadc_platform_data {
struct pm8xxx_ccadc_core_data ccadc_cdata;
int r_sense_uohm;
unsigned int calib_delay_ms;
+ bool periodic_wakeup;
};
#define CCADC_READING_RESOLUTION_N 542535
diff --git a/include/linux/mfd/pm8xxx/misc.h b/include/linux/mfd/pm8xxx/misc.h
index fa97ba9..98ec93f 100644
--- a/include/linux/mfd/pm8xxx/misc.h
+++ b/include/linux/mfd/pm8xxx/misc.h
@@ -1,5 +1,5 @@
/*
- * 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
@@ -224,6 +224,16 @@
* RETURNS: an appropriate -ERRNO error value on error, or zero for success.
*/
int pm8xxx_hsed_bias_control(enum pm8xxx_hsed_bias bias, bool enable);
+
+/**
+ * pm8xxx_read_register - Read a PMIC register
+ * @addr: PMIC register address
+ * @value: Output parameter which gets the value of the register read.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_read_register(u16 addr, u8 *value);
+
#else
static inline int pm8xxx_reset_pwr_off(int reset)
@@ -278,6 +288,10 @@
{
return -ENODEV;
}
+static inline int pm8xxx_read_register(u16 addr, u8 *value)
+{
+ return -ENODEV;
+}
#endif
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index 9461c76..a19c0b6 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -46,6 +46,14 @@
* @ocv_dis_low_soc: the low soc percent when ocv should be enabled
* @low_voltage_detect: feature to enable 0 SOC reporting on low volatge
* @vbatt_cutoff_retries: number of tries before we report a 0 SOC
+ * @high_ocv_correction_limit_uv: the max amount of OCV corrections
+ * allowed when ocv is high
+ * (higher than 3.8V)
+ * @low_ocv_correction_limit_uv: the max amount of OCV corrections
+ * allowed when ocv is low
+ * (lower or equal to 3.8V)
+ * @hold_soc_est: the min est soc below which the calculated soc
+ * is allowed to go to 0%
*/
struct pm8921_bms_platform_data {
struct pm8xxx_bms_core_data bms_cdata;
@@ -69,6 +77,9 @@
int ocv_dis_low_soc;
int low_voltage_detect;
int vbatt_cutoff_retries;
+ int high_ocv_correction_limit_uv;
+ int low_ocv_correction_limit_uv;
+ int hold_soc_est;
};
#if defined(CONFIG_PM8921_BMS) || defined(CONFIG_PM8921_BMS_MODULE)
@@ -156,6 +167,19 @@
* value upon wakeup from sleep.
*/
int pm8921_bms_cc_uah(int *cc_uah);
+
+/**
+ * pm8921_bms_battery_removed - function to be called to tell the bms that
+ * the battery is removed. The bms resets its internal
+ * history data used to report soc.
+ */
+void pm8921_bms_battery_removed(void);
+/**
+ * pm8921_bms_battery_inseted - function to be called to tell the bms that
+ * the battery was inserted. The bms initiates calculations
+ * for reporting soc.
+ */
+void pm8921_bms_battery_inserted(void);
#else
static inline int pm8921_bms_get_vsense_avg(int *result)
{
@@ -202,6 +226,8 @@
{
return -ENXIO;
}
+static inline void pm8921_bms_battery_removed(void) {}
+static inline void pm8921_bms_battery_inserted(void) {}
#endif
#endif
diff --git a/include/linux/mfd/wcd9xxx/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h
index 392c0ae..813cac3 100644
--- a/include/linux/mfd/wcd9xxx/pdata.h
+++ b/include/linux/mfd/wcd9xxx/pdata.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -69,6 +69,21 @@
#define TABLA_DCYCLE_3839 0xE
#define TABLA_DCYCLE_4095 0xF
+#define TAIKO_MCLK_CLK_12P288MHZ 12288000
+#define TAIKO_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
+
+/* 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 TAIKO_DMIC_SAMPLE_RATE_UNDEFINED 0
+
struct wcd9xxx_amic {
/*legacy mode, txfe_enable and txfe_buff take 7 input
* each bit represent the channel / TXFE number
@@ -155,6 +170,7 @@
struct wcd9xxx_ocp_setting ocp;
struct wcd9xxx_regulator regulator[MAX_REGULATOR];
u32 mclk_rate;
+ u32 dmic_sample_rate;
};
#endif
diff --git a/include/linux/mfd/wcd9xxx/wcd9310_registers.h b/include/linux/mfd/wcd9xxx/wcd9310_registers.h
index 46336e2..cec0ce2 100644
--- a/include/linux/mfd/wcd9xxx/wcd9310_registers.h
+++ b/include/linux/mfd/wcd9xxx/wcd9310_registers.h
@@ -1,14 +1,3 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
#ifndef TABLA_CODEC_DIGITAL_H
#define TABLA_CODEC_DIGITAL_H
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index a5f36b5..407a005 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -116,6 +116,12 @@
* required frequency.
*/
#define SDHCI_QUIRK2_ALWAYS_USE_BASE_CLOCK (1<<4)
+/*
+ * Dont use the max_discard_to in sdhci driver so that the maximum discard
+ * unit gets picked by the mmc queue. Otherwise, it takes a long time for
+ * secure discard kind of operations to complete.
+ */
+#define SDHCI_QUIRK2_USE_MAX_DISCARD_SIZE (1<<5)
int irq; /* Device IRQ */
void __iomem *ioaddr; /* Mapped address */
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 5dc65bd..ca7a586 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -61,6 +61,14 @@
MIGRATE_TYPES
};
+/*
+ * Returns a list which contains the migrate types on to which
+ * an allocation falls back when the free list for the migrate
+ * type mtype is depleted.
+ * The end of the list is delimited by the type MIGRATE_RESERVE.
+ */
+extern int *get_migratetype_fallbacks(int mtype);
+
#ifdef CONFIG_CMA
bool is_cma_pageblock(struct page *page);
# define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
diff --git a/include/linux/msm_audio_ion.h b/include/linux/msm_audio_ion.h
new file mode 100644
index 0000000..83e5dff
--- /dev/null
+++ b/include/linux/msm_audio_ion.h
@@ -0,0 +1,61 @@
+/*
+ * 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 _LINUX_MSM_AUDIO_ION_H
+#define _LINUX_MSM_AUDIO_ION_H
+
+#include <linux/msm_ion.h>
+
+
+int msm_audio_ion_alloc(const char *name, struct ion_client **client,
+ struct ion_handle **handle, size_t bufsz,
+ ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr);
+
+int msm_audio_ion_import(const char *name, struct ion_client **client,
+ struct ion_handle **handle, int fd,
+ unsigned long *ionflag, size_t bufsz,
+ ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr);
+int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle);
+
+
+bool msm_audio_ion_is_smmu_available(void);
+
+#ifdef CONFIG_SND_SOC_QDSP6V2
+struct ion_client *msm_audio_ion_client_create(unsigned int heap_mask,
+ const char *name);
+void msm_audio_ion_client_destroy(struct ion_client *client);
+int msm_audio_ion_import_legacy(const char *name, struct ion_client *client,
+ struct ion_handle **handle, int fd,
+ unsigned long *ionflag, size_t bufsz,
+ ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr);
+int msm_audio_ion_free_legacy(struct ion_client *client,
+ struct ion_handle *handle);
+#else
+static struct ion_client *msm_audio_ion_client_create(unsigned int heap_mask,
+ const char *name)
+{ return NULL; }
+static void msm_audio_ion_client_destroy(struct ion_client *client)
+{}
+static int msm_audio_ion_import_legacy(const char *name,
+ struct ion_client *client,
+ struct ion_handle **handle, int fd,
+ unsigned long *ionflag, size_t bufsz,
+ ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr)
+{ return 0; }
+static int msm_audio_ion_free_legacy(struct ion_client *client,
+ struct ion_handle *handle)
+{ return 0; }
+
+#endif /* CONFIG_MSM_QDSP6V2_CODECS */
+#endif /* _LINUX_MSM_AUDIO_ION_H */
+
diff --git a/include/linux/msm_ion.h b/include/linux/msm_ion.h
index 95c4e6a..37c935d 100644
--- a/include/linux/msm_ion.h
+++ b/include/linux/msm_ion.h
@@ -1,18 +1,3 @@
-/*
- *
- * Copyright (c) 2012-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
- * may be copied, distributed, and modified under those terms.
- *
- * 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 _LINUX_MSM_ION_H
#define _LINUX_MSM_ION_H
@@ -21,6 +6,7 @@
enum msm_ion_heap_types {
ION_HEAP_TYPE_MSM_START = ION_HEAP_TYPE_CUSTOM + 1,
ION_HEAP_TYPE_IOMMU = ION_HEAP_TYPE_MSM_START,
+ ION_HEAP_TYPE_DMA,
ION_HEAP_TYPE_CP,
ION_HEAP_TYPE_SECURE_DMA,
};
@@ -71,18 +57,25 @@
};
#define ION_HEAP_CP_MASK (1 << ION_HEAP_TYPE_CP)
+#define ION_HEAP_TYPE_DMA_MASK (1 << ION_HEAP_TYPE_DMA)
/**
* Flag to use when allocating to indicate that a heap is secure.
*/
-#define ION_SECURE (1 << ION_HEAP_ID_RESERVED)
+#define ION_FLAG_SECURE (1 << ION_HEAP_ID_RESERVED)
/**
* Flag for clients to force contiguous memort allocation
*
* Use of this flag is carefully monitored!
*/
-#define ION_FORCE_CONTIGUOUS (1 << 30)
+#define ION_FLAG_FORCE_CONTIGUOUS (1 << 30)
+
+/**
+* Deprecated! Please use the corresponding ION_FLAG_*
+*/
+#define ION_SECURE ION_FLAG_SECURE
+#define ION_FORCE_CONTIGUOUS ION_FLAG_FORCE_CONTIGUOUS
/**
* Macro should be used with ion_heap_ids defined above.
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 2732690..2ad040e 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -208,6 +208,26 @@
unsigned int dev_minor;
};
+/* Performance counter groups */
+
+#define KGSL_PERFCOUNTER_GROUP_CP 0x0
+#define KGSL_PERFCOUNTER_GROUP_RBBM 0x1
+#define KGSL_PERFCOUNTER_GROUP_PC 0x2
+#define KGSL_PERFCOUNTER_GROUP_VFD 0x3
+#define KGSL_PERFCOUNTER_GROUP_HLSQ 0x4
+#define KGSL_PERFCOUNTER_GROUP_VPC 0x5
+#define KGSL_PERFCOUNTER_GROUP_TSE 0x6
+#define KGSL_PERFCOUNTER_GROUP_RAS 0x7
+#define KGSL_PERFCOUNTER_GROUP_UCHE 0x8
+#define KGSL_PERFCOUNTER_GROUP_TP 0x9
+#define KGSL_PERFCOUNTER_GROUP_SP 0xA
+#define KGSL_PERFCOUNTER_GROUP_RB 0xB
+#define KGSL_PERFCOUNTER_GROUP_PWR 0xC
+#define KGSL_PERFCOUNTER_GROUP_VBIF 0xD
+#define KGSL_PERFCOUNTER_GROUP_VBIF_PWR 0xE
+
+#define KGSL_PERFCOUNTER_NOT_USED 0xFFFFFFFF
+
/* structure holds list of ibs */
struct kgsl_ibdesc {
unsigned int gpuaddr;
@@ -658,6 +678,110 @@
#define IOCTL_KGSL_GPUMEM_SYNC_CACHE \
_IOW(KGSL_IOC_TYPE, 0x37, struct kgsl_gpumem_sync_cache)
+/**
+ * struct kgsl_perfcounter_get - argument to IOCTL_KGSL_PERFCOUNTER_GET
+ * @groupid: Performance counter group ID
+ * @countable: Countable to select within the group
+ * @offset: Return offset of the reserved counter
+ *
+ * Get an available performance counter from a specified groupid. The offset
+ * of the performance counter will be returned after successfully assigning
+ * the countable to the counter for the specified group. An error will be
+ * returned and an offset of 0 if the groupid is invalid or there are no
+ * more counters left. After successfully getting a perfcounter, the user
+ * must call kgsl_perfcounter_put(groupid, contable) when finished with
+ * the perfcounter to clear up perfcounter resources.
+ *
+ */
+struct kgsl_perfcounter_get {
+ unsigned int groupid;
+ unsigned int countable;
+ unsigned int offset;
+/* private: reserved for future use */
+ unsigned int __pad[2]; /* For future binary compatibility */
+};
+
+#define IOCTL_KGSL_PERFCOUNTER_GET \
+ _IOWR(KGSL_IOC_TYPE, 0x38, struct kgsl_perfcounter_get)
+
+/**
+ * struct kgsl_perfcounter_put - argument to IOCTL_KGSL_PERFCOUNTER_PUT
+ * @groupid: Performance counter group ID
+ * @countable: Countable to release within the group
+ *
+ * Put an allocated performance counter to allow others to have access to the
+ * resource that was previously taken. This is only to be called after
+ * successfully getting a performance counter from kgsl_perfcounter_get().
+ *
+ */
+struct kgsl_perfcounter_put {
+ unsigned int groupid;
+ unsigned int countable;
+/* private: reserved for future use */
+ unsigned int __pad[2]; /* For future binary compatibility */
+};
+
+#define IOCTL_KGSL_PERFCOUNTER_PUT \
+ _IOW(KGSL_IOC_TYPE, 0x39, struct kgsl_perfcounter_put)
+
+/**
+ * struct kgsl_perfcounter_query - argument to IOCTL_KGSL_PERFCOUNTER_QUERY
+ * @groupid: Performance counter group ID
+ * @countable: Return active countables array
+ * @size: Size of active countables array
+ * @max_counters: Return total number counters for the group ID
+ *
+ * Query the available performance counters given a groupid. The array
+ * *countables is used to return the current active countables in counters.
+ * The size of the array is passed in so the kernel will only write at most
+ * size or counter->size for the group id. The total number of available
+ * counters for the group ID is returned in max_counters.
+ * If the array or size passed in are invalid, then only the maximum number
+ * of counters will be returned, no data will be written to *countables.
+ * If the groupid is invalid an error code will be returned.
+ *
+ */
+struct kgsl_perfcounter_query {
+ unsigned int groupid;
+ /* Array to return the current countable for up to size counters */
+ unsigned int *countables;
+ unsigned int count;
+ unsigned int max_counters;
+/* private: reserved for future use */
+ unsigned int __pad[2]; /* For future binary compatibility */
+};
+
+#define IOCTL_KGSL_PERFCOUNTER_QUERY \
+ _IOWR(KGSL_IOC_TYPE, 0x3A, struct kgsl_perfcounter_query)
+
+/**
+ * struct kgsl_perfcounter_query - argument to IOCTL_KGSL_PERFCOUNTER_QUERY
+ * @groupid: Performance counter group IDs
+ * @countable: Performance counter countable IDs
+ * @value: Return performance counter reads
+ * @size: Size of all arrays (groupid/countable pair and return value)
+ *
+ * Read in the current value of a performance counter given by the groupid
+ * and countable.
+ *
+ */
+
+struct kgsl_perfcounter_read_group {
+ unsigned int groupid;
+ unsigned int countable;
+ uint64_t value;
+};
+
+struct kgsl_perfcounter_read {
+ struct kgsl_perfcounter_read_group *reads;
+ unsigned int count;
+/* private: reserved for future use */
+ unsigned int __pad[2]; /* For future binary compatibility */
+};
+
+#define IOCTL_KGSL_PERFCOUNTER_READ \
+ _IOWR(KGSL_IOC_TYPE, 0x3B, struct kgsl_perfcounter_read)
+
#ifdef __KERNEL__
#ifdef CONFIG_MSM_KGSL_DRM
int kgsl_gem_obj_addr(int drm_fd, int handle, unsigned long *start,
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 5deff7a..7e1a709 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -170,7 +170,7 @@
#define MDP_SECURE_OVERLAY_SESSION 0x00008000
#define MDP_OV_PIPE_FORCE_DMA 0x00004000
#define MDP_MEMORY_ID_TYPE_FB 0x00001000
-
+#define MDP_BWC_EN 0x00000400
#define MDP_TRANSP_NOP 0xffffffff
#define MDP_ALPHA_NOP 0xff
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 0ab5143..f551e75 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -170,6 +170,9 @@
* %NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS,
* %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY,
* %NL80211_ATTR_AUTH_TYPE and %NL80211_ATTR_INACTIVITY_TIMEOUT.
+ * %NL80211_ATTR_ACL_POLICY and %NL80211_ATTR_MAC_ADDRS.
+ * The channel to use can be set on the interface or be given using the
+ * %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width.
* @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP
* @NL80211_CMD_STOP_AP: Stop AP operation on the given interface
* @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP
@@ -554,6 +557,57 @@
* @NL80211_CMD_SET_NOACK_MAP: sets a bitmap for the individual TIDs whether
* No Acknowledgement Policy should be applied.
*
+ * @NL80211_CMD_CH_SWITCH_NOTIFY: An AP or GO may decide to switch channels
+ * independently of the userspace SME, send this event indicating
+ * %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ and the
+ * attributes determining channel width.
+ *
+ * @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by
+ * its %NL80211_ATTR_WDEV identifier. It must have been created with
+ * %NL80211_CMD_NEW_INTERFACE previously. After it has been started, the
+ * P2P Device can be used for P2P operations, e.g. remain-on-channel and
+ * public action frame TX.
+ * @NL80211_CMD_STOP_P2P_DEVICE: Stop the given P2P Device, identified by
+ * its %NL80211_ATTR_WDEV identifier.
+ *
+ * @NL80211_CMD_CONN_FAILED: connection request to an AP failed; used to
+ * notify userspace that AP has rejected the connection request from a
+ * station, due to particular reason. %NL80211_ATTR_CONN_FAILED_REASON
+ * is used for this.
+ *
+ * @NL80211_CMD_SET_MCAST_RATE: Change the rate used to send multicast frames
+ * for IBSS or MESH vif.
+ *
+ * @NL80211_CMD_SET_MAC_ACL: sets ACL for MAC address based access control.
+ * This is to be used with the drivers advertising the support of MAC
+ * address based access control. List of MAC addresses is passed in
+ * %NL80211_ATTR_MAC_ADDRS and ACL policy is passed in
+ * %NL80211_ATTR_ACL_POLICY. Driver will enable ACL with this list, if it
+ * is not already done. The new list will replace any existing list. Driver
+ * will clear its ACL when the list of MAC addresses passed is empty. This
+ * command is used in AP/P2P GO mode. Driver has to make sure to clear its
+ * ACL list during %NL80211_CMD_STOP_AP.
+ *
+ * @NL80211_CMD_RADAR_DETECT: Start a Channel availability check (CAC). Once
+ * a radar is detected or the channel availability scan (CAC) has finished
+ * or was aborted, or a radar was detected, usermode will be notified with
+ * this event. This command is also used to notify userspace about radars
+ * while operating on this channel.
+ * %NL80211_ATTR_RADAR_EVENT is used to inform about the type of the
+ * event.
+ *
+ * @NL80211_CMD_GET_PROTOCOL_FEATURES: Get global nl80211 protocol features,
+ * i.e. features for the nl80211 protocol rather than device features.
+ * Returns the features in the %NL80211_ATTR_PROTOCOL_FEATURES bitmap.
+ *
+ * @NL80211_CMD_UPDATE_FT_IES: Pass down the most up-to-date Fast Transition
+ * Information Element to the WLAN driver
+ *
+ * @NL80211_CMD_FT_EVENT: Send a Fast transition event from the WLAN driver
+ * to the supplicant. This will carry the target AP's MAC address along
+ * with the relevant Information Elements. This event is used to report
+ * received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE).
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -695,6 +749,25 @@
NL80211_CMD_SET_NOACK_MAP,
+
+ NL80211_CMD_CH_SWITCH_NOTIFY,
+
+ NL80211_CMD_START_P2P_DEVICE,
+ NL80211_CMD_STOP_P2P_DEVICE,
+
+ NL80211_CMD_CONN_FAILED,
+
+ NL80211_CMD_SET_MCAST_RATE,
+
+ NL80211_CMD_SET_MAC_ACL,
+
+ NL80211_CMD_RADAR_DETECT,
+
+ NL80211_CMD_GET_PROTOCOL_FEATURES,
+
+ NL80211_CMD_UPDATE_FT_IES,
+ NL80211_CMD_FT_EVENT,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -1275,6 +1348,18 @@
* advertised to the driver, e.g., to enable TDLS off channel operations
* and PU-APSD.
*
+ * @NL80211_ATTR_PROTOCOL_FEATURES: global nl80211 feature flags, see
+ * &enum nl80211_protocol_features, the attribute is a u32.
+ *
+ * @NL80211_ATTR_SPLIT_WIPHY_DUMP: flag attribute, userspace supports
+ * receiving the data for a single wiphy split across multiple
+ * messages, given with wiphy dump message
+ *
+ * @NL80211_ATTR_MDID: Mobility Domain Identifier
+ *
+ * @NL80211_ATTR_IE_RIC: Resource Information Container Information
+ * Element
+ *
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -1561,6 +1646,15 @@
NL80211_ATTR_STA_CAPABILITY,
NL80211_ATTR_STA_EXT_CAPABILITY,
+ NL80211_ATTR_PROTOCOL_FEATURES,
+ NL80211_ATTR_SPLIT_WIPHY_DUMP,
+
+ NL80211_ATTR_DISABLE_VHT,
+ NL80211_ATTR_VHT_CAPABILITY_MASK,
+
+ NL80211_ATTR_MDID,
+ NL80211_ATTR_IE_RIC,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -1704,9 +1798,14 @@
* @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved
* @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s)
* @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8)
- * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate
+ * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 MHz dualchannel bitrate
* @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval
* @NL80211_RATE_INFO_MAX: highest rate_info number currently defined
+ * @NL80211_RATE_INFO_VHT_MCS: MCS index for VHT (u8)
+ * @NL80211_RATE_INFO_VHT_NSS: number of streams in VHT (u8)
+ * @NL80211_RATE_INFO_80_MHZ_WIDTH: 80 MHz VHT rate
+ * @NL80211_RATE_INFO_80P80_MHZ_WIDTH: 80+80 MHz VHT rate
+ * @NL80211_RATE_INFO_160_MHZ_WIDTH: 160 MHz VHT rate
* @__NL80211_RATE_INFO_AFTER_LAST: internal use
*/
enum nl80211_rate_info {
@@ -1715,6 +1814,11 @@
NL80211_RATE_INFO_MCS,
NL80211_RATE_INFO_40_MHZ_WIDTH,
NL80211_RATE_INFO_SHORT_GI,
+ NL80211_RATE_INFO_VHT_MCS,
+ NL80211_RATE_INFO_VHT_NSS,
+ NL80211_RATE_INFO_80_MHZ_WIDTH,
+ NL80211_RATE_INFO_80P80_MHZ_WIDTH,
+ NL80211_RATE_INFO_160_MHZ_WIDTH,
/* keep last */
__NL80211_RATE_INFO_AFTER_LAST,
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index fc6ab91..15e5dc9 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -1359,6 +1359,12 @@
int32_t qpnp_iadc_vadc_sync_read(
enum qpnp_iadc_channels i_channel, struct qpnp_iadc_result *i_result,
enum qpnp_vadc_channels v_channel, struct qpnp_vadc_result *v_result);
+/**
+ * qpnp_iadc_calibrate_for_trim() - Clients can use this API to re-calibrate
+ * IADC.
+ * @result: 0 on success.
+ */
+int32_t qpnp_iadc_calibrate_for_trim(void);
#else
static inline int32_t qpnp_iadc_read(enum qpnp_iadc_channels channel,
struct qpnp_iadc_result *result)
@@ -1374,6 +1380,8 @@
enum qpnp_iadc_channels i_channel, struct qpnp_iadc_result *i_result,
enum qpnp_vadc_channels v_channel, struct qpnp_vadc_result *v_result)
{ return -ENXIO; }
+static inline int32_t qpnp_iadc_calibrate_for_trim(void)
+{ return -ENXIO; }
#endif
/* Public API */
diff --git a/include/linux/qseecom.h b/include/linux/qseecom.h
index b0f089b..c399b81 100644
--- a/include/linux/qseecom.h
+++ b/include/linux/qseecom.h
@@ -6,7 +6,7 @@
#define MAX_ION_FD 4
#define MAX_APP_NAME_SIZE 32
-
+#define QSEECOM_HASH_SIZE 32
/*
* struct qseecom_register_listener_req -
* for register listener ioctl request
@@ -117,6 +117,27 @@
int app_id; /* out */
};
+struct qseecom_send_svc_cmd_req {
+ uint32_t cmd_id;
+ void *cmd_req_buf; /* in */
+ unsigned int cmd_req_len; /* in */
+ void *resp_buf; /* in/out */
+ unsigned int resp_len; /* in/out */
+};
+
+enum qseecom_key_management_usage_type {
+ QSEOS_KM_USAGE_DISK_ENCRYPTION = 0x01,
+};
+
+struct qseecom_create_key_req {
+ unsigned char hash32[QSEECOM_HASH_SIZE];
+ enum qseecom_key_management_usage_type usage;
+};
+
+struct qseecom_wipe_key_req {
+ enum qseecom_key_management_usage_type usage;
+};
+
#define QSEECOM_IOC_MAGIC 0x97
@@ -165,5 +186,14 @@
#define QSEECOM_IOCTL_APP_LOADED_QUERY_REQ \
_IOWR(QSEECOM_IOC_MAGIC, 15, struct qseecom_qseos_app_load_query)
+#define QSEECOM_IOCTL_SEND_CMD_SERVICE_REQ \
+ _IOWR(QSEECOM_IOC_MAGIC, 16, struct qseecom_send_svc_cmd_req)
+
+#define QSEECOM_IOCTL_CREATE_KEY_REQ \
+ _IOWR(QSEECOM_IOC_MAGIC, 17, struct qseecom_create_key_req)
+
+#define QSEECOM_IOCTL_WIPE_KEY_REQ \
+ _IOWR(QSEECOM_IOC_MAGIC, 18, struct qseecom_wipe_key_req)
+
#endif /* __QSEECOM_H_ */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 79fe16b..c8a20da 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -279,6 +279,7 @@
* @pclk: clock struct of iface_clk.
* @phy_reset_clk: clock struct of phy_clk.
* @core_clk: clock struct of core_bus_clk.
+ * @core_clk_rate: core clk max frequency
* @regs: ioremapped register base address.
* @inputs: OTG state machine inputs(Id, SessValid etc).
* @sm_work: OTG state machine work.
@@ -313,6 +314,7 @@
struct clk *pclk;
struct clk *phy_reset_clk;
struct clk *core_clk;
+ long core_clk_rate;
void __iomem *regs;
#define ID 0
#define B_SESS_VLD 1
@@ -400,6 +402,7 @@
unsigned strobe;
unsigned data;
bool ignore_cal_pad_config;
+ bool phy_sof_workaround;
int strobe_pad_offset;
int data_pad_offset;
diff --git a/include/media/msm/vcd_api.h b/include/media/msm/vcd_api.h
index 944446f..09e1a53 100644
--- a/include/media/msm/vcd_api.h
+++ b/include/media/msm/vcd_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -12,6 +12,7 @@
*/
#ifndef _VCD_API_H_
#define _VCD_API_H_
+#include <linux/types.h>
#include "vcd_property.h"
#include "vcd_status.h"
diff --git a/include/media/msm/vcd_property.h b/include/media/msm/vcd_property.h
index 5fcb049..ce6c479 100644
--- a/include/media/msm/vcd_property.h
+++ b/include/media/msm/vcd_property.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -13,6 +13,8 @@
#ifndef _VCD_DRIVER_PROPERTY_H_
#define _VCD_DRIVER_PROPERTY_H_
+#include <linux/types.h>
+
#define VCD_START_BASE 0x0
#define VCD_I_LIVE (VCD_START_BASE + 0x1)
#define VCD_I_CODEC (VCD_START_BASE + 0x2)
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index 4e1fb31..bce6af3 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -44,9 +44,12 @@
#define MOVE_NEAR 0
#define MOVE_FAR 1
+#define MAX_EEPROM_NAME 32
+
enum msm_camera_i2c_reg_addr_type {
MSM_CAMERA_I2C_BYTE_ADDR = 1,
MSM_CAMERA_I2C_WORD_ADDR,
+ MSM_CAMERA_I2C_3B_ADDR,
};
enum msm_camera_i2c_data_type {
@@ -283,6 +286,37 @@
} cfg;
};
+enum eeprom_cfg_type_t {
+ CFG_EEPROM_GET_INFO,
+ CFG_EEPROM_GET_DATA,
+ CFG_EEPROM_READ_DATA,
+ CFG_EEPROM_WRITE_DATA,
+};
+struct eeprom_get_t {
+ uint16_t num_bytes;
+};
+
+struct eeprom_read_t {
+ uint8_t *dbuffer;
+ uint16_t num_bytes;
+};
+
+struct eeprom_write_t {
+ uint8_t *dbuffer;
+ uint16_t num_bytes;
+};
+
+struct msm_eeprom_cfg_data {
+ enum eeprom_cfg_type_t cfgtype;
+ uint8_t is_supported;
+ union {
+ char eeprom_name[MAX_SENSOR_NAME];
+ struct eeprom_get_t get_data;
+ struct eeprom_read_t read_data;
+ struct eeprom_write_t write_data;
+ } cfg;
+};
+
enum msm_sensor_cfg_type_t {
CFG_SET_SLAVE_INFO,
CFG_WRITE_I2C_ARRAY,
@@ -456,6 +490,9 @@
#define VIDIOC_MSM_FLASH_LED_DATA_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct msm_camera_led_cfg_t)
+#define VIDIOC_MSM_EEPROM_CFG \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct msm_eeprom_cfg_data)
+
#define MSM_V4L2_PIX_FMT_META v4l2_fourcc('M', 'E', 'T', 'A') /* META */
#endif /* __LINUX_MSM_CAM_SENSOR_H */
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 9c310a9..afd5a42 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -1550,6 +1550,7 @@
enum msm_camera_i2c_reg_addr_type {
MSM_CAMERA_I2C_BYTE_ADDR = 1,
MSM_CAMERA_I2C_WORD_ADDR,
+ MSM_CAMERA_I2C_3B_ADDR,
};
struct msm_camera_i2c_reg_array {
diff --git a/include/media/msm_gestures.h b/include/media/msm_gestures.h
index a6efd4f..9388d99 100644
--- a/include/media/msm_gestures.h
+++ b/include/media/msm_gestures.h
@@ -1,15 +1,3 @@
-/* Copyright (c) 2012, 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 __LINUX_MSM_GESTURES_H
#define __LINUX_MSM_GESTURES_H
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 77455ca..99f418c 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -1,15 +1,3 @@
-/* Copyright (c) 2011-2012, 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_ISP_H__
#define __MSM_ISP_H__
diff --git a/include/media/msmb_generic_buf_mgr.h b/include/media/msmb_generic_buf_mgr.h
index 17cb947..efcb425 100644
--- a/include/media/msmb_generic_buf_mgr.h
+++ b/include/media/msmb_generic_buf_mgr.h
@@ -9,6 +9,7 @@
uint32_t index;
};
+struct v4l2_subdev *msm_buf_mngr_get_subdev(void);
#define VIDIOC_MSM_BUF_MNGR_GET_BUF \
_IOWR('V', BASE_VIDIOC_PRIVATE + 33, struct msm_buf_mngr_info)
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
index 7f70a01..6fb1a65 100644
--- a/include/media/msmb_isp.h
+++ b/include/media/msmb_isp.h
@@ -109,6 +109,7 @@
struct msm_vfe_rdi_cfg rdi_cfg;
} d;
enum msm_vfe_input_src input_src;
+ uint32_t input_pix_clk;
};
struct msm_vfe_axi_plane_cfg {
diff --git a/include/media/msmb_ispif.h b/include/media/msmb_ispif.h
index 3546004..c9eb12a 100644
--- a/include/media/msmb_ispif.h
+++ b/include/media/msmb_ispif.h
@@ -20,6 +20,8 @@
RDI2,
INTF_MAX
};
+#define MAX_PARAM_ENTRIES (INTF_MAX * 2)
+
#define PIX0_MASK (1 << PIX0)
#define PIX1_MASK (1 << PIX1)
#define RDI0_MASK (1 << RDI0)
@@ -64,16 +66,19 @@
};
struct msm_ispif_params_entry {
+ enum msm_ispif_vfe_intf vfe_intf;
enum msm_ispif_intftype intftype;
int num_cids;
enum msm_ispif_cid cids[3];
enum msm_ispif_csid csid;
+ int crop_enable;
+ uint16_t crop_start_pixel;
+ uint16_t crop_end_pixel;
};
struct msm_ispif_param_data {
- enum msm_ispif_vfe_intf vfe_intf;
uint32_t num;
- struct msm_ispif_params_entry entries[INTF_MAX];
+ struct msm_ispif_params_entry entries[MAX_PARAM_ENTRIES];
};
struct msm_isp_info {
diff --git a/include/media/msmb_pproc.h b/include/media/msmb_pproc.h
index 6f8e865..c185096 100644
--- a/include/media/msmb_pproc.h
+++ b/include/media/msmb_pproc.h
@@ -11,6 +11,7 @@
#define MAX_PLANES VIDEO_MAX_PLANES
#define MAX_NUM_CPP_STRIPS 8
+#define MSM_CPP_MAX_NUM_PLANES 3
enum msm_cpp_frame_type {
MSM_CPP_OFFLINE_FRAME,
@@ -74,9 +75,25 @@
int postscale_crop_en;
};
+struct msm_cpp_buffer_info_t {
+ int fd;
+ uint32_t index;
+ uint32_t offset;
+ uint8_t native_buff;
+ uint8_t processed_divert;
+};
+
+struct msm_cpp_stream_buff_info_t {
+ uint32_t identity;
+ uint32_t num_buffs;
+ struct msm_cpp_buffer_info_t *buffer_info;
+};
+
struct msm_cpp_frame_info_t {
int32_t frame_id;
+ struct timeval timestamp;
uint32_t inst_id;
+ uint32_t identity;
uint32_t client_id;
enum msm_cpp_frame_type frame_type;
uint32_t num_strips;
@@ -87,6 +104,12 @@
int dst_fd;
struct ion_handle *src_ion_handle;
struct ion_handle *dest_ion_handle;
+ struct timeval in_time, out_time;
+ void *cookie;
+ int32_t *status;
+
+ struct msm_cpp_buffer_info_t input_buffer_info;
+ struct msm_cpp_buffer_info_t output_buffer_info;
};
struct cpp_hw_info {
@@ -112,12 +135,18 @@
#define VIDIOC_MSM_CPP_FLUSH_QUEUE \
_IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct msm_camera_v4l2_ioctl_t)
+#define VIDIOC_MSM_CPP_ENQUEUE_STREAM_BUFF_INFO \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct msm_camera_v4l2_ioctl_t)
+
+#define VIDIOC_MSM_CPP_DEQUEUE_STREAM_BUFF_INFO \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct msm_camera_v4l2_ioctl_t)
+
#define V4L2_EVENT_CPP_FRAME_DONE (V4L2_EVENT_PRIVATE_START + 0)
struct msm_camera_v4l2_ioctl_t {
uint32_t id;
uint32_t len;
- uint32_t trans_code;
+ int32_t trans_code;
void __user *ioctl_ptr;
};
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 52811ae..dc29eb9 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -578,14 +578,24 @@
* Used by the driver to indicate the specific rate transmission
* type for 802.11n transmissions.
*
- * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
- * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_MCS: mcs field filled with HT MCS
+ * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 MHz width transmission
+ * @RATE_INFO_FLAGS_80_MHZ_WIDTH: 80 MHz width transmission
+ * @RATE_INFO_FLAGS_80P80_MHZ_WIDTH: 80+80 MHz width transmission
+ * @RATE_INFO_FLAGS_160_MHZ_WIDTH: 160 MHz width transmission
* @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
+ * @RATE_INFO_FLAGS_60G: 60GHz MCS
*/
enum rate_info_flags {
- RATE_INFO_FLAGS_MCS = 1<<0,
- RATE_INFO_FLAGS_40_MHZ_WIDTH = 1<<1,
- RATE_INFO_FLAGS_SHORT_GI = 1<<2,
+ RATE_INFO_FLAGS_MCS = BIT(0),
+ RATE_INFO_FLAGS_VHT_MCS = BIT(1),
+ RATE_INFO_FLAGS_40_MHZ_WIDTH = BIT(2),
+ RATE_INFO_FLAGS_80_MHZ_WIDTH = BIT(3),
+ RATE_INFO_FLAGS_80P80_MHZ_WIDTH = BIT(4),
+ RATE_INFO_FLAGS_160_MHZ_WIDTH = BIT(5),
+ RATE_INFO_FLAGS_SHORT_GI = BIT(6),
+ RATE_INFO_FLAGS_60G = BIT(7),
};
/**
@@ -596,11 +606,13 @@
* @flags: bitflag of flags from &enum rate_info_flags
* @mcs: mcs index if struct describes a 802.11n bitrate
* @legacy: bitrate in 100kbit/s for 802.11abg
+ * @nss: number of streams (VHT only)
*/
struct rate_info {
u8 flags;
u8 mcs;
u16 legacy;
+ u8 nss;
};
/**
@@ -1349,6 +1361,21 @@
};
/**
+ * struct cfg80211_update_ft_ies_params - FT IE Information
+ *
+ * This structure provides information needed to update the fast transition IE
+ *
+ * @md: The Mobility Domain ID, 2 Octet value
+ * @ie: Fast Transition IEs
+ * @ie_len: Length of ft_ie in octets
+ */
+struct cfg80211_update_ft_ies_params {
+ u16 md;
+ const u8 *ie;
+ size_t ie_len;
+};
+
+/**
* struct cfg80211_ops - backend description for wireless configuration
*
* This struct is registered by fullmac card drivers and/or wireless stacks
@@ -1728,6 +1755,8 @@
u16 noack_map);
struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy);
+ int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_update_ft_ies_params *ftie);
};
/*
@@ -3398,6 +3427,31 @@
*/
u16 cfg80211_calculate_bitrate(struct rate_info *rate);
+/**
+ * struct cfg80211_ft_event - FT Information Elements
+ * @ies: FT IEs
+ * @ies_len: length of the FT IE in bytes
+ * @target_ap: target AP's MAC address
+ * @ric_ies: RIC IE
+ * @ric_ies_len: length of the RIC IE in bytes
+ */
+struct cfg80211_ft_event_params {
+ const u8 *ies;
+ size_t ies_len;
+ const u8 *target_ap;
+ const u8 *ric_ies;
+ size_t ric_ies_len;
+};
+
+/**
+ * cfg80211_ft_event - notify userspace about FT IE and RIC IE
+ * @netdev: network device
+ * @ft_event: IE information
+ */
+void cfg80211_ft_event(struct net_device *netdev,
+ struct cfg80211_ft_event_params *ft_event);
+
+
/* Logging, debugging and troubleshooting/diagnostic helpers. */
/* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 04e683f..fa4dedc 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -335,6 +335,7 @@
/* Payload an #ADM_CMD_GET_PP_PARAMS_V5 command.
*/
struct adm_cmd_get_pp_params_v5 {
+ struct apr_hdr hdr;
u32 data_payload_addr_lsw;
/* LSW of parameter data payload address.*/
@@ -2593,6 +2594,14 @@
} __packed;
+/* @brief Dolby Digital Plus end point configuration structure
+ */
+struct asm_dec_ddp_endp_param_v2 {
+ struct apr_hdr hdr;
+ struct asm_stream_cmd_set_encdec_param encdec;
+ int endp_param_value;
+} __packed;
+
/* @brief Multichannel PCM encoder configuration structure used
* in the #ASM_STREAM_CMD_OPEN_READ_V2 command.
*/
@@ -6913,4 +6922,7 @@
struct afe_port_cmd_set_param_v2 param;
} __packed;
+/* Dolby DAP topology */
+#define DOLBY_ADM_COPP_TOPOLOGY_ID 0x0001033B
+
#endif /*_APR_AUDIO_V2_H_ */
diff --git a/include/sound/compress_params.h b/include/sound/compress_params.h
index b95fa3c..f5ab179 100644
--- a/include/sound/compress_params.h
+++ b/include/sound/compress_params.h
@@ -89,6 +89,8 @@
#define SND_AUDIOCODEC_PASS_THROUGH ((__u32) 0x00000015)
#define SND_AUDIOCODEC_MP2 ((__u32) 0x00000016)
#define SND_AUDIOCODEC_DTS_LBR_PASS_THROUGH ((__u32) 0x00000017)
+#define SND_AUDIOCODEC_EAC3 ((__u32) 0x00000018)
+#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_EAC3
/*
* Profile and modes are listed with bit masks. This allows for a
* more compact representation of fields that will not evolve
@@ -337,7 +339,12 @@
__u32 modelIdLength;
__u8 *modelId;
};
-
+struct snd_dec_ddp {
+ __u32 params_length;
+ __u8 *params;
+ __u32 params_id[18];
+ __u32 params_value[18];
+};
union snd_codec_options {
struct snd_enc_wma wma;
struct snd_enc_vorbis vorbis;
@@ -345,6 +352,7 @@
struct snd_enc_flac flac;
struct snd_enc_generic generic;
struct snd_dec_dts dts;
+ struct snd_dec_ddp ddp;
};
/** struct snd_codec_desc - description of codec capabilities
diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h
index 77a805c..4bea1e1 100644
--- a/include/sound/q6adm-v2.h
+++ b/include/sound/q6adm-v2.h
@@ -32,6 +32,12 @@
int adm_open(int port, int path, int rate, int mode, int topology,
bool perf_mode, uint16_t bits_per_sample);
+int adm_dolby_dap_get_params(int port_id, uint32_t module_id, uint32_t param_id,
+ uint32_t params_length, char *params);
+
+int adm_dolby_dap_send_params(int port_id, char *params,
+ uint32_t params_length);
+
int adm_multi_ch_copp_open(int port, int path, int rate, int mode,
int topology, bool perf_mode, uint16_t bits_per_sample);
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 9c86e1d..2a740f4 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -81,6 +81,8 @@
IDX_AFE_PORT_ID_TERTIARY_MI2S_TX = 39,
IDX_AFE_PORT_ID_PRIMARY_MI2S_RX = 40,
IDX_AFE_PORT_ID_PRIMARY_MI2S_TX = 41,
+ IDX_AFE_PORT_ID_SECONDARY_PCM_RX = 42,
+ IDX_AFE_PORT_ID_SECONDARY_PCM_TX = 43,
IDX_GLOBAL_CFG,
AFE_MAX_PORTS
};
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index f9d2a40..0dd14e6 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -13,7 +13,6 @@
#define __Q6_ASM_V2_H__
#include <mach/qdsp6v2/apr.h>
-#include <mach/msm_subsystem_map.h>
#include <sound/apr_audio-v2.h>
#include <linux/list.h>
#include <linux/msm_ion.h>
@@ -42,6 +41,8 @@
#define FORMAT_AMR_WB_PLUS 0x0010
#define FORMAT_MPEG4_MULTI_AAC 0x0011
#define FORMAT_MULTI_CHANNEL_LINEAR_PCM 0x0012
+#define FORMAT_AC3 0x0013
+#define FORMAT_EAC3 0x0014
#define ENCDEC_SBCBITRATE 0x0001
#define ENCDEC_IMMEDIATE_DECODE 0x0002
@@ -296,6 +297,10 @@
int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
struct asm_amrwbplus_cfg *cfg);
+
+int q6asm_ds1_set_endp_params(struct audio_client *ac,
+ int param_id, int param_value);
+
/* PP specific */
int q6asm_equalizer(struct audio_client *ac, void *eq);
diff --git a/include/sound/q6lsm.h b/include/sound/q6lsm.h
index 5c9d4b9..e9ca91d 100644
--- a/include/sound/q6lsm.h
+++ b/include/sound/q6lsm.h
@@ -18,7 +18,6 @@
#include <sound/apr_audio-v2.h>
#include <sound/lsm_params.h>
#include <mach/qdsp6v2/apr.h>
-#include <mach/msm_subsystem_map.h>
typedef void (*app_cb)(uint32_t opcode, uint32_t token,
uint32_t *payload, void *priv);
diff --git a/include/video/Kbuild b/include/video/Kbuild
index ad3e622..53e13cb 100644
--- a/include/video/Kbuild
+++ b/include/video/Kbuild
@@ -1,3 +1,4 @@
header-y += edid.h
header-y += sisfb.h
header-y += uvesafb.h
+header-y += msm_hdmi_modes.h
diff --git a/include/video/msm_hdmi_modes.h b/include/video/msm_hdmi_modes.h
new file mode 100644
index 0000000..a15272b
--- /dev/null
+++ b/include/video/msm_hdmi_modes.h
@@ -0,0 +1,334 @@
+#ifndef __MSM_HDMI_MODES_H__
+#define __MSM_HDMI_MODES_H__
+#include <linux/types.h>
+
+struct msm_hdmi_mode_timing_info {
+ uint32_t video_format;
+ uint32_t active_h;
+ uint32_t front_porch_h;
+ uint32_t pulse_width_h;
+ uint32_t back_porch_h;
+ uint32_t active_low_h;
+ uint32_t active_v;
+ uint32_t front_porch_v;
+ uint32_t pulse_width_v;
+ uint32_t back_porch_v;
+ uint32_t active_low_v;
+ /* Must divide by 1000 to get the actual frequency in MHZ */
+ uint32_t pixel_freq;
+ /* Must divide by 1000 to get the actual frequency in HZ */
+ uint32_t refresh_rate;
+ uint32_t interlaced;
+ uint32_t supported;
+};
+
+#define MSM_HDMI_MODES_CEA (1 << 0)
+#define MSM_HDMI_MODES_XTND (1 << 1)
+#define MSM_HDMI_MODES_DVI (1 << 2)
+#define MSM_HDMI_MODES_ALL (MSM_HDMI_MODES_CEA |\
+ MSM_HDMI_MODES_XTND |\
+ MSM_HDMI_MODES_DVI)
+
+/* all video formats defined by CEA 861D */
+#define HDMI_VFRMT_UNKNOWN 0
+#define HDMI_VFRMT_640x480p60_4_3 1
+#define HDMI_VFRMT_720x480p60_4_3 2
+#define HDMI_VFRMT_720x480p60_16_9 3
+#define HDMI_VFRMT_1280x720p60_16_9 4
+#define HDMI_VFRMT_1920x1080i60_16_9 5
+#define HDMI_VFRMT_720x480i60_4_3 6
+#define HDMI_VFRMT_1440x480i60_4_3 HDMI_VFRMT_720x480i60_4_3
+#define HDMI_VFRMT_720x480i60_16_9 7
+#define HDMI_VFRMT_1440x480i60_16_9 HDMI_VFRMT_720x480i60_16_9
+#define HDMI_VFRMT_720x240p60_4_3 8
+#define HDMI_VFRMT_1440x240p60_4_3 HDMI_VFRMT_720x240p60_4_3
+#define HDMI_VFRMT_720x240p60_16_9 9
+#define HDMI_VFRMT_1440x240p60_16_9 HDMI_VFRMT_720x240p60_16_9
+#define HDMI_VFRMT_2880x480i60_4_3 10
+#define HDMI_VFRMT_2880x480i60_16_9 11
+#define HDMI_VFRMT_2880x240p60_4_3 12
+#define HDMI_VFRMT_2880x240p60_16_9 13
+#define HDMI_VFRMT_1440x480p60_4_3 14
+#define HDMI_VFRMT_1440x480p60_16_9 15
+#define HDMI_VFRMT_1920x1080p60_16_9 16
+#define HDMI_VFRMT_720x576p50_4_3 17
+#define HDMI_VFRMT_720x576p50_16_9 18
+#define HDMI_VFRMT_1280x720p50_16_9 19
+#define HDMI_VFRMT_1920x1080i50_16_9 20
+#define HDMI_VFRMT_720x576i50_4_3 21
+#define HDMI_VFRMT_1440x576i50_4_3 HDMI_VFRMT_720x576i50_4_3
+#define HDMI_VFRMT_720x576i50_16_9 22
+#define HDMI_VFRMT_1440x576i50_16_9 HDMI_VFRMT_720x576i50_16_9
+#define HDMI_VFRMT_720x288p50_4_3 23
+#define HDMI_VFRMT_1440x288p50_4_3 HDMI_VFRMT_720x288p50_4_3
+#define HDMI_VFRMT_720x288p50_16_9 24
+#define HDMI_VFRMT_1440x288p50_16_9 HDMI_VFRMT_720x288p50_16_9
+#define HDMI_VFRMT_2880x576i50_4_3 25
+#define HDMI_VFRMT_2880x576i50_16_9 26
+#define HDMI_VFRMT_2880x288p50_4_3 27
+#define HDMI_VFRMT_2880x288p50_16_9 28
+#define HDMI_VFRMT_1440x576p50_4_3 29
+#define HDMI_VFRMT_1440x576p50_16_9 30
+#define HDMI_VFRMT_1920x1080p50_16_9 31
+#define HDMI_VFRMT_1920x1080p24_16_9 32
+#define HDMI_VFRMT_1920x1080p25_16_9 33
+#define HDMI_VFRMT_1920x1080p30_16_9 34
+#define HDMI_VFRMT_2880x480p60_4_3 35
+#define HDMI_VFRMT_2880x480p60_16_9 36
+#define HDMI_VFRMT_2880x576p50_4_3 37
+#define HDMI_VFRMT_2880x576p50_16_9 38
+#define HDMI_VFRMT_1920x1250i50_16_9 39
+#define HDMI_VFRMT_1920x1080i100_16_9 40
+#define HDMI_VFRMT_1280x720p100_16_9 41
+#define HDMI_VFRMT_720x576p100_4_3 42
+#define HDMI_VFRMT_720x576p100_16_9 43
+#define HDMI_VFRMT_720x576i100_4_3 44
+#define HDMI_VFRMT_1440x576i100_4_3 HDMI_VFRMT_720x576i100_4_3
+#define HDMI_VFRMT_720x576i100_16_9 45
+#define HDMI_VFRMT_1440x576i100_16_9 HDMI_VFRMT_720x576i100_16_9
+#define HDMI_VFRMT_1920x1080i120_16_9 46
+#define HDMI_VFRMT_1280x720p120_16_9 47
+#define HDMI_VFRMT_720x480p120_4_3 48
+#define HDMI_VFRMT_720x480p120_16_9 49
+#define HDMI_VFRMT_720x480i120_4_3 50
+#define HDMI_VFRMT_1440x480i120_4_3 HDMI_VFRMT_720x480i120_4_3
+#define HDMI_VFRMT_720x480i120_16_9 51
+#define HDMI_VFRMT_1440x480i120_16_9 HDMI_VFRMT_720x480i120_16_9
+#define HDMI_VFRMT_720x576p200_4_3 52
+#define HDMI_VFRMT_720x576p200_16_9 53
+#define HDMI_VFRMT_720x576i200_4_3 54
+#define HDMI_VFRMT_1440x576i200_4_3 HDMI_VFRMT_720x576i200_4_3
+#define HDMI_VFRMT_720x576i200_16_9 55
+#define HDMI_VFRMT_1440x576i200_16_9 HDMI_VFRMT_720x576i200_16_9
+#define HDMI_VFRMT_720x480p240_4_3 56
+#define HDMI_VFRMT_720x480p240_16_9 57
+#define HDMI_VFRMT_720x480i240_4_3 58
+#define HDMI_VFRMT_1440x480i240_4_3 HDMI_VFRMT_720x480i240_4_3
+#define HDMI_VFRMT_720x480i240_16_9 59
+#define HDMI_VFRMT_1440x480i240_16_9 HDMI_VFRMT_720x480i240_16_9
+#define HDMI_VFRMT_1280x720p24_16_9 60
+#define HDMI_VFRMT_1280x720p25_16_9 61
+#define HDMI_VFRMT_1280x720p30_16_9 62
+#define HDMI_VFRMT_1920x1080p120_16_9 63
+#define HDMI_VFRMT_1920x1080p100_16_9 64
+/* Video Identification Codes from 65-127 are reserved for the future */
+#define HDMI_VFRMT_END 127
+
+/* extended video formats */
+#define HDMI_VFRMT_3840x2160p30_16_9 (HDMI_VFRMT_END + 1)
+#define HDMI_VFRMT_3840x2160p25_16_9 (HDMI_VFRMT_END + 2)
+#define HDMI_VFRMT_3840x2160p24_16_9 (HDMI_VFRMT_END + 3)
+#define HDMI_VFRMT_4096x2160p24_16_9 (HDMI_VFRMT_END + 4)
+#define HDMI_EVFRMT_END HDMI_VFRMT_4096x2160p24_16_9
+
+/* VESA DMT TIMINGS */
+#define HDMI_VFRMT_2560x1600p60_16_9 (HDMI_EVFRMT_END + 1)
+#define HDMI_VFRMT_1280x1024p60_5_4 (HDMI_EVFRMT_END + 2)
+#define VESA_DMT_VFRMT_END HDMI_VFRMT_1280x1024p60_5_4
+#define HDMI_VFRMT_MAX (VESA_DMT_VFRMT_END + 1)
+#define HDMI_VFRMT_FORCE_32BIT 0x7FFFFFFF
+
+/* Timing information for supported modes */
+#define VFRMT_NOT_SUPPORTED(VFRMT) \
+ {VFRMT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, false}
+
+#define HDMI_VFRMT_640x480p60_4_3_TIMING \
+ {HDMI_VFRMT_640x480p60_4_3, 640, 16, 96, 48, true, \
+ 480, 10, 2, 33, true, 25200, 60000, false, true}
+#define HDMI_VFRMT_720x480p60_4_3_TIMING \
+ {HDMI_VFRMT_720x480p60_4_3, 720, 16, 62, 60, true, \
+ 480, 9, 6, 30, true, 27030, 60000, false, true}
+#define HDMI_VFRMT_720x480p60_16_9_TIMING \
+ {HDMI_VFRMT_720x480p60_16_9, 720, 16, 62, 60, true, \
+ 480, 9, 6, 30, true, 27030, 60000, false, true}
+#define HDMI_VFRMT_1280x720p60_16_9_TIMING \
+ {HDMI_VFRMT_1280x720p60_16_9, 1280, 110, 40, 220, false, \
+ 720, 5, 5, 20, false, 74250, 60000, false, true}
+#define HDMI_VFRMT_1920x1080i60_16_9_TIMING \
+ {HDMI_VFRMT_1920x1080i60_16_9, 1920, 88, 44, 148, false, \
+ 540, 2, 5, 5, false, 74250, 60000, false, true}
+#define HDMI_VFRMT_1440x480i60_4_3_TIMING \
+ {HDMI_VFRMT_1440x480i60_4_3, 1440, 38, 124, 114, true, \
+ 240, 4, 3, 15, true, 27000, 60000, true, true}
+#define HDMI_VFRMT_1440x480i60_16_9_TIMING \
+ {HDMI_VFRMT_1440x480i60_16_9, 1440, 38, 124, 114, true, \
+ 240, 4, 3, 15, true, 27000, 60000, true, true}
+#define HDMI_VFRMT_1920x1080p60_16_9_TIMING \
+ {HDMI_VFRMT_1920x1080p60_16_9, 1920, 88, 44, 148, false, \
+ 1080, 4, 5, 36, false, 148500, 60000, false, true}
+#define HDMI_VFRMT_720x576p50_4_3_TIMING \
+ {HDMI_VFRMT_720x576p50_4_3, 720, 12, 64, 68, true, \
+ 576, 5, 5, 39, true, 27000, 50000, false, true}
+#define HDMI_VFRMT_720x576p50_16_9_TIMING \
+ {HDMI_VFRMT_720x576p50_16_9, 720, 12, 64, 68, true, \
+ 576, 5, 5, 39, true, 27000, 50000, false, true}
+#define HDMI_VFRMT_1280x720p50_16_9_TIMING \
+ {HDMI_VFRMT_1280x720p50_16_9, 1280, 440, 40, 220, false, \
+ 720, 5, 5, 20, false, 74250, 50000, false, true}
+#define HDMI_VFRMT_1440x576i50_4_3_TIMING \
+ {HDMI_VFRMT_1440x576i50_4_3, 1440, 24, 126, 138, true, \
+ 288, 2, 3, 19, true, 27000, 50000, true, true}
+#define HDMI_VFRMT_1440x576i50_16_9_TIMING \
+ {HDMI_VFRMT_1440x576i50_16_9, 1440, 24, 126, 138, true, \
+ 288, 2, 3, 19, true, 27000, 50000, true, true}
+#define HDMI_VFRMT_1920x1080p50_16_9_TIMING \
+ {HDMI_VFRMT_1920x1080p50_16_9, 1920, 528, 44, 148, false, \
+ 1080, 4, 5, 36, false, 148500, 50000, false, true}
+#define HDMI_VFRMT_1920x1080p24_16_9_TIMING \
+ {HDMI_VFRMT_1920x1080p24_16_9, 1920, 638, 44, 148, false, \
+ 1080, 4, 5, 36, false, 74250, 24000, false, true}
+#define HDMI_VFRMT_1920x1080p25_16_9_TIMING \
+ {HDMI_VFRMT_1920x1080p25_16_9, 1920, 528, 44, 148, false, \
+ 1080, 4, 5, 36, false, 74250, 25000, false, true}
+#define HDMI_VFRMT_1920x1080p30_16_9_TIMING \
+ {HDMI_VFRMT_1920x1080p30_16_9, 1920, 88, 44, 148, false, \
+ 1080, 4, 5, 36, false, 74250, 30000, false, true}
+#define HDMI_VFRMT_1280x1024p60_5_4_TIMING \
+ {HDMI_VFRMT_1280x1024p60_5_4, 1280, 48, 112, 248, false, \
+ 1024, 1, 3, 38, false, 108000, 60000, false, true}
+#define HDMI_VFRMT_2560x1600p60_16_9_TIMING \
+ {HDMI_VFRMT_2560x1600p60_16_9, 2560, 48, 32, 80, false, \
+ 1600, 3, 6, 37, false, 268500, 60000, false, true}
+#define HDMI_VFRMT_3840x2160p30_16_9_TIMING \
+ {HDMI_VFRMT_3840x2160p30_16_9, 3840, 176, 88, 296, false, \
+ 2160, 8, 10, 72, false, 297000, 30000, false, true}
+#define HDMI_VFRMT_3840x2160p25_16_9_TIMING \
+ {HDMI_VFRMT_3840x2160p25_16_9, 3840, 1056, 88, 296, false, \
+ 2160, 8, 10, 72, false, 297000, 25000, false, true}
+#define HDMI_VFRMT_3840x2160p24_16_9_TIMING \
+ {HDMI_VFRMT_3840x2160p24_16_9, 3840, 1276, 88, 296, false, \
+ 2160, 8, 10, 72, false, 297000, 24000, false, true}
+#define HDMI_VFRMT_4096x2160p24_16_9_TIMING \
+ {HDMI_VFRMT_4096x2160p24_16_9, 4096, 1020, 88, 296, false, \
+ 2160, 8, 10, 72, false, 297000, 24000, false, true}
+
+#define MSM_HDMI_MODES_SET_TIMING(LUT, MODE) do { \
+ struct msm_hdmi_mode_timing_info mode = MODE##_TIMING; \
+ LUT[MODE] = mode;\
+ } while (0)
+
+static inline void MSM_HDMI_MODES_INIT_TIMINGS(
+ struct msm_hdmi_mode_timing_info *lut)
+{
+ int i;
+
+ for (i = 0; i < HDMI_VFRMT_MAX; i++) {
+ struct msm_hdmi_mode_timing_info mode = VFRMT_NOT_SUPPORTED(i);
+ lut[i] = mode;
+ }
+}
+
+static inline void MSM_HDMI_MODES_SET_SUPP_TIMINGS(
+ struct msm_hdmi_mode_timing_info *lut, int type)
+{
+ if (type & MSM_HDMI_MODES_CEA) {
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_640x480p60_4_3);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_720x480p60_4_3);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_720x480p60_16_9);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1280x720p60_16_9);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1920x1080i60_16_9);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1440x480i60_4_3);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1440x480i60_16_9);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1920x1080p60_16_9);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_720x576p50_4_3);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_720x576p50_16_9);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1280x720p50_16_9);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1440x576i50_4_3);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1440x576i50_16_9);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1920x1080p50_16_9);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1920x1080p24_16_9);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1920x1080p25_16_9);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1920x1080p30_16_9);
+ }
+
+ if (type & MSM_HDMI_MODES_XTND) {
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_3840x2160p30_16_9);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_3840x2160p25_16_9);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_3840x2160p24_16_9);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_4096x2160p24_16_9);
+ }
+
+ if (type & MSM_HDMI_MODES_DVI) {
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_1280x1024p60_5_4);
+ MSM_HDMI_MODES_SET_TIMING(lut, HDMI_VFRMT_2560x1600p60_16_9);
+ }
+}
+
+static inline const char *msm_hdmi_mode_2string(uint32_t mode)
+{
+ switch (mode) {
+ case HDMI_VFRMT_UNKNOWN: return "Unknown";
+ case HDMI_VFRMT_640x480p60_4_3: return "640x480 p60 4/3";
+ case HDMI_VFRMT_720x480p60_4_3: return "720x480 p60 4/3";
+ case HDMI_VFRMT_720x480p60_16_9: return "720x480 p60 16/9";
+ case HDMI_VFRMT_1280x720p60_16_9: return "1280x 720 p60 16/9";
+ case HDMI_VFRMT_1920x1080i60_16_9: return "1920x1080 i60 16/9";
+ case HDMI_VFRMT_1440x480i60_4_3: return "1440x480 i60 4/3";
+ case HDMI_VFRMT_1440x480i60_16_9: return "1440x480 i60 16/9";
+ case HDMI_VFRMT_1440x240p60_4_3: return "1440x240 p60 4/3";
+ case HDMI_VFRMT_1440x240p60_16_9: return "1440x240 p60 16/9";
+ case HDMI_VFRMT_2880x480i60_4_3: return "2880x480 i60 4/3";
+ case HDMI_VFRMT_2880x480i60_16_9: return "2880x480 i60 16/9";
+ case HDMI_VFRMT_2880x240p60_4_3: return "2880x240 p60 4/3";
+ case HDMI_VFRMT_2880x240p60_16_9: return "2880x240 p60 16/9";
+ case HDMI_VFRMT_1440x480p60_4_3: return "1440x480 p60 4/3";
+ case HDMI_VFRMT_1440x480p60_16_9: return "1440x480 p60 16/9";
+ case HDMI_VFRMT_1920x1080p60_16_9: return "1920x1080 p60 16/9";
+ case HDMI_VFRMT_720x576p50_4_3: return "720x576 p50 4/3";
+ case HDMI_VFRMT_720x576p50_16_9: return "720x576 p50 16/9";
+ case HDMI_VFRMT_1280x720p50_16_9: return "1280x720 p50 16/9";
+ case HDMI_VFRMT_1920x1080i50_16_9: return "1920x1080 i50 16/9";
+ case HDMI_VFRMT_1440x576i50_4_3: return "1440x576 i50 4/3";
+ case HDMI_VFRMT_1440x576i50_16_9: return "1440x576 i50 16/9";
+ case HDMI_VFRMT_1440x288p50_4_3: return "1440x288 p50 4/3";
+ case HDMI_VFRMT_1440x288p50_16_9: return "1440x288 p50 16/9";
+ case HDMI_VFRMT_2880x576i50_4_3: return "2880x576 i50 4/3";
+ case HDMI_VFRMT_2880x576i50_16_9: return "2880x576 i50 16/9";
+ case HDMI_VFRMT_2880x288p50_4_3: return "2880x288 p50 4/3";
+ case HDMI_VFRMT_2880x288p50_16_9: return "2880x288 p50 16/9";
+ case HDMI_VFRMT_1440x576p50_4_3: return "1440x576 p50 4/3";
+ case HDMI_VFRMT_1440x576p50_16_9: return "1440x576 p50 16/9";
+ case HDMI_VFRMT_1920x1080p50_16_9: return "1920x1080 p50 16/9";
+ case HDMI_VFRMT_1920x1080p24_16_9: return "1920x1080 p24 16/9";
+ case HDMI_VFRMT_1920x1080p25_16_9: return "1920x1080 p25 16/9";
+ case HDMI_VFRMT_1920x1080p30_16_9: return "1920x1080 p30 16/9";
+ case HDMI_VFRMT_2880x480p60_4_3: return "2880x480 p60 4/3";
+ case HDMI_VFRMT_2880x480p60_16_9: return "2880x480 p60 16/9";
+ case HDMI_VFRMT_2880x576p50_4_3: return "2880x576 p50 4/3";
+ case HDMI_VFRMT_2880x576p50_16_9: return "2880x576 p50 16/9";
+ case HDMI_VFRMT_1920x1250i50_16_9: return "1920x1250 i50 16/9";
+ case HDMI_VFRMT_1920x1080i100_16_9: return "1920x1080 i100 16/9";
+ case HDMI_VFRMT_1280x720p100_16_9: return "1280x720 p100 16/9";
+ case HDMI_VFRMT_720x576p100_4_3: return "720x576 p100 4/3";
+ case HDMI_VFRMT_720x576p100_16_9: return "720x576 p100 16/9";
+ case HDMI_VFRMT_1440x576i100_4_3: return "1440x576 i100 4/3";
+ case HDMI_VFRMT_1440x576i100_16_9: return "1440x576 i100 16/9";
+ case HDMI_VFRMT_1920x1080i120_16_9: return "1920x1080 i120 16/9";
+ case HDMI_VFRMT_1280x720p120_16_9: return "1280x720 p120 16/9";
+ case HDMI_VFRMT_720x480p120_4_3: return "720x480 p120 4/3";
+ case HDMI_VFRMT_720x480p120_16_9: return "720x480 p120 16/9";
+ case HDMI_VFRMT_1440x480i120_4_3: return "1440x480 i120 4/3";
+ case HDMI_VFRMT_1440x480i120_16_9: return "1440x480 i120 16/9";
+ case HDMI_VFRMT_720x576p200_4_3: return "720x576 p200 4/3";
+ case HDMI_VFRMT_720x576p200_16_9: return "720x576 p200 16/9";
+ case HDMI_VFRMT_1440x576i200_4_3: return "1440x576 i200 4/3";
+ case HDMI_VFRMT_1440x576i200_16_9: return "1440x576 i200 16/9";
+ case HDMI_VFRMT_720x480p240_4_3: return "720x480 p240 4/3";
+ case HDMI_VFRMT_720x480p240_16_9: return "720x480 p240 16/9";
+ case HDMI_VFRMT_1440x480i240_4_3: return "1440x480 i240 4/3";
+ case HDMI_VFRMT_1440x480i240_16_9: return "1440x480 i240 16/9";
+ case HDMI_VFRMT_1280x720p24_16_9: return "1280x720 p24 16/9";
+ case HDMI_VFRMT_1280x720p25_16_9: return "1280x720 p25 16/9";
+ case HDMI_VFRMT_1280x720p30_16_9: return "1280x720 p30 16/9";
+ case HDMI_VFRMT_1920x1080p120_16_9: return "1920x1080 p120 16/9";
+ case HDMI_VFRMT_1920x1080p100_16_9: return "1920x1080 p100 16/9";
+ case HDMI_VFRMT_3840x2160p30_16_9: return "3840x2160 p30 16/9";
+ case HDMI_VFRMT_3840x2160p25_16_9: return "3840x2160 p25 16/9";
+ case HDMI_VFRMT_3840x2160p24_16_9: return "3840x2160 p24 16/9";
+ case HDMI_VFRMT_4096x2160p24_16_9: return "4096x2160 p24 16/9";
+ case HDMI_VFRMT_2560x1600p60_16_9: return "2560x1600 p60 16/9";
+ case HDMI_VFRMT_1280x1024p60_5_4: return "1280x1042 p60 5/4";
+ default: return "???";
+ }
+}
+#endif /* __MSM_HDMI_MODES_H__ */
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c
index d1e73a4..edd656c 100644
--- a/kernel/hrtimer.c
+++ b/kernel/hrtimer.c
@@ -641,21 +641,9 @@
* and expiry check is done in the hrtimer_interrupt or in the softirq.
*/
static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
- struct hrtimer_clock_base *base,
- int wakeup)
+ struct hrtimer_clock_base *base)
{
- if (base->cpu_base->hres_active && hrtimer_reprogram(timer, base)) {
- if (wakeup) {
- raw_spin_unlock(&base->cpu_base->lock);
- raise_softirq_irqoff(HRTIMER_SOFTIRQ);
- raw_spin_lock(&base->cpu_base->lock);
- } else
- __raise_softirq_irqoff(HRTIMER_SOFTIRQ);
-
- return 1;
- }
-
- return 0;
+ return base->cpu_base->hres_active && hrtimer_reprogram(timer, base);
}
/*
@@ -726,8 +714,7 @@
static inline void
hrtimer_force_reprogram(struct hrtimer_cpu_base *base, int skip_equal) { }
static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer,
- struct hrtimer_clock_base *base,
- int wakeup)
+ struct hrtimer_clock_base *base)
{
return 0;
}
@@ -986,8 +973,21 @@
*
* XXX send_remote_softirq() ?
*/
- if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases))
- hrtimer_enqueue_reprogram(timer, new_base, wakeup);
+ if (leftmost && new_base->cpu_base == &__get_cpu_var(hrtimer_bases)
+ && hrtimer_enqueue_reprogram(timer, new_base)) {
+ if (wakeup) {
+ /*
+ * We need to drop cpu_base->lock to avoid a
+ * lock ordering issue vs. rq->lock.
+ */
+ raw_spin_unlock(&new_base->cpu_base->lock);
+ raise_softirq_irqoff(HRTIMER_SOFTIRQ);
+ local_irq_restore(flags);
+ return ret;
+ } else {
+ __raise_softirq_irqoff(HRTIMER_SOFTIRQ);
+ }
+ }
unlock_hrtimer_base(timer, &flags);
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index b179e71..d6dd07a 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -926,6 +926,11 @@
[MIGRATE_ISOLATE] = { MIGRATE_RESERVE }, /* Never used */
};
+int *get_migratetype_fallbacks(int mtype)
+{
+ return fallbacks[mtype];
+}
+
/*
* Move the free pages in a range to the free lists of the requested type.
* Note that start_page and end_pages are not aligned on a pageblock
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 69318b0..e1fa62e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -212,6 +212,14 @@
[NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN },
[NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 },
[NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, },
+ [NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, },
+ [NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG },
+ [NL80211_ATTR_VHT_CAPABILITY_MASK] = {
+ .len = NL80211_VHT_CAPABILITY_LEN,
+ },
+ [NL80211_ATTR_MDID] = { .type = NLA_U16 },
+ [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY,
+ .len = IEEE80211_MAX_DATA_LEN },
};
/* policy for the key attributes */
@@ -2384,25 +2392,46 @@
rate = nla_nest_start(msg, attr);
if (!rate)
- goto nla_put_failure;
+ return false;
/* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
bitrate = cfg80211_calculate_bitrate(info);
if (bitrate > 0)
- NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
+ nla_put_u16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
- if (info->flags & RATE_INFO_FLAGS_MCS)
- NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS, info->mcs);
- if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
- NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
- if (info->flags & RATE_INFO_FLAGS_SHORT_GI)
- NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
+ if (info->flags & RATE_INFO_FLAGS_MCS) {
+ if (nla_put_u8(msg, NL80211_RATE_INFO_MCS, info->mcs))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH &&
+ nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
+ nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
+ return false;
+ } else if (info->flags & RATE_INFO_FLAGS_VHT_MCS) {
+ if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_MCS, info->mcs))
+ return false;
+ if (nla_put_u8(msg, NL80211_RATE_INFO_VHT_NSS, info->nss))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH &&
+ nla_put_flag(msg, NL80211_RATE_INFO_40_MHZ_WIDTH))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH &&
+ nla_put_flag(msg, NL80211_RATE_INFO_80_MHZ_WIDTH))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_80P80_MHZ_WIDTH &&
+ nla_put_flag(msg, NL80211_RATE_INFO_80P80_MHZ_WIDTH))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_160_MHZ_WIDTH &&
+ nla_put_flag(msg, NL80211_RATE_INFO_160_MHZ_WIDTH))
+ return false;
+ if (info->flags & RATE_INFO_FLAGS_SHORT_GI &&
+ nla_put_flag(msg, NL80211_RATE_INFO_SHORT_GI))
+ return false;
+ }
nla_nest_end(msg, rate);
return true;
-
-nla_put_failure:
- return false;
}
static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
@@ -6424,6 +6453,27 @@
return 0;
}
+static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct cfg80211_update_ft_ies_params ft_params;
+ struct net_device *dev = info->user_ptr[1];
+
+ if (!rdev->ops->update_ft_ies)
+ return -EOPNOTSUPP;
+
+ if (!info->attrs[NL80211_ATTR_MDID] ||
+ !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
+ return -EINVAL;
+
+ memset(&ft_params, 0, sizeof(ft_params));
+ ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]);
+ ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]);
+ ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+
+ return rdev->ops->update_ft_ies(&rdev->wiphy, dev, &ft_params);
+}
+
#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
@@ -7012,6 +7062,14 @@
.internal_flags = NL80211_FLAG_NEED_NETDEV |
NL80211_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL80211_CMD_UPDATE_FT_IES,
+ .doit = nl80211_update_ft_ies,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
};
@@ -8249,6 +8307,48 @@
.notifier_call = nl80211_netlink_notify,
};
+void cfg80211_ft_event(struct net_device *netdev,
+ struct cfg80211_ft_event_params *ft_event)
+{
+ struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy;
+ struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+ struct sk_buff *msg;
+ void *hdr;
+ int err;
+
+ if (!ft_event->target_ap)
+ return;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
+ nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
+ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap);
+ if (ft_event->ies)
+ nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies);
+ if (ft_event->ric_ies)
+ nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len,
+ ft_event->ric_ies);
+
+ err = genlmsg_end(msg, hdr);
+ if (err < 0) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+ nl80211_mlme_mcgrp.id, GFP_KERNEL);
+}
+EXPORT_SYMBOL(cfg80211_ft_event);
+
/* initialisation/exit functions */
int nl80211_init(void)
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 017d4fc..b89fb94 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -876,13 +876,86 @@
return err;
}
+static u32 cfg80211_calculate_bitrate_vht(struct rate_info *rate)
+{
+ static const u32 base[4][10] = {
+ { 6500000,
+ 13000000,
+ 19500000,
+ 26000000,
+ 39000000,
+ 52000000,
+ 58500000,
+ 65000000,
+ 78000000,
+ 0,
+ },
+ { 13500000,
+ 27000000,
+ 40500000,
+ 54000000,
+ 81000000,
+ 108000000,
+ 121500000,
+ 135000000,
+ 162000000,
+ 180000000,
+ },
+ { 29300000,
+ 58500000,
+ 87800000,
+ 117000000,
+ 175500000,
+ 234000000,
+ 263300000,
+ 292500000,
+ 351000000,
+ 390000000,
+ },
+ { 58500000,
+ 117000000,
+ 175500000,
+ 234000000,
+ 351000000,
+ 468000000,
+ 526500000,
+ 585000000,
+ 702000000,
+ 780000000,
+ },
+ };
+ u32 bitrate;
+ int idx;
+
+ if (WARN_ON_ONCE(rate->mcs > 9))
+ return 0;
+
+ idx = rate->flags & (RATE_INFO_FLAGS_160_MHZ_WIDTH |
+ RATE_INFO_FLAGS_80P80_MHZ_WIDTH) ? 3 :
+ rate->flags & RATE_INFO_FLAGS_80_MHZ_WIDTH ? 2 :
+ rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH ? 1 : 0;
+
+ bitrate = base[idx][rate->mcs];
+ bitrate *= rate->nss;
+
+ if (rate->flags & RATE_INFO_FLAGS_SHORT_GI)
+ bitrate = (bitrate / 9) * 10;
+
+ /* do NOT round down here */
+ return (bitrate + 50000) / 100000;
+}
+
u16 cfg80211_calculate_bitrate(struct rate_info *rate)
{
int modulation, streams, bitrate;
- if (!(rate->flags & RATE_INFO_FLAGS_MCS))
+ if (!(rate->flags & RATE_INFO_FLAGS_MCS) &&
+ !(rate->flags & RATE_INFO_FLAGS_VHT_MCS))
return rate->legacy;
+ if (rate->flags & RATE_INFO_FLAGS_VHT_MCS)
+ return cfg80211_calculate_bitrate_vht(rate);
+
/* the formula below does only work for MCS values smaller than 32 */
if (rate->mcs >= 32)
return 0;
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 36d5d6b..866f524 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -4850,8 +4850,10 @@
if (sitar) {
codec = sitar->codec;
- if (sitar->hphlocp_cnt++ < SITAR_OCP_ATTEMPT) {
+ if ((sitar->hphlocp_cnt < SITAR_OCP_ATTEMPT) &&
+ (!sitar->hphrocp_cnt)) {
pr_info("%s: retry\n", __func__);
+ sitar->hphlocp_cnt++;
snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
0x00);
snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
@@ -4859,7 +4861,6 @@
} else {
wcd9xxx_disable_irq(codec->control_data,
WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
- sitar->hphlocp_cnt = 0;
sitar->hph_status |= SND_JACK_OC_HPHL;
if (sitar->mbhc_cfg.headset_jack)
sitar_snd_soc_jack_report(sitar,
@@ -4883,8 +4884,10 @@
if (sitar) {
codec = sitar->codec;
- if (sitar->hphrocp_cnt++ < SITAR_OCP_ATTEMPT) {
+ if ((sitar->hphrocp_cnt < SITAR_OCP_ATTEMPT) &&
+ (!sitar->hphlocp_cnt)) {
pr_info("%s: retry\n", __func__);
+ sitar->hphrocp_cnt++;
snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
0x00);
snd_soc_update_bits(codec, SITAR_A_RX_HPH_OCP_CTL, 0x10,
@@ -4892,7 +4895,6 @@
} else {
wcd9xxx_disable_irq(codec->control_data,
WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
- sitar->hphrocp_cnt = 0;
sitar->hph_status |= SND_JACK_OC_HPHR;
if (sitar->mbhc_cfg.headset_jack)
sitar_snd_soc_jack_report(sitar,
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 5f4490b..8f63250 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -204,8 +204,21 @@
#define TAIKO_TX_PORT_NUMBER 16
#define TAIKO_I2S_MASTER_MODE_MASK 0x08
-#define TAIKO_MCLK_CLK_12P288MHZ 12288000
-#define TAIKO_MCLK_CLK_9P6HZ 9600000
+
+#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)
@@ -1061,6 +1074,21 @@
40, digital_gain),
SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TAIKO_A_CDC_IIR1_GAIN_B4_CTL, -84,
40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR2 INP1 Volume", TAIKO_A_CDC_IIR2_GAIN_B1_CTL, -84,
+ 40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR2 INP2 Volume", TAIKO_A_CDC_IIR2_GAIN_B2_CTL, -84,
+ 40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR2 INP3 Volume", TAIKO_A_CDC_IIR2_GAIN_B3_CTL, -84,
+ 40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR2 INP4 Volume", TAIKO_A_CDC_IIR2_GAIN_B4_CTL, -84,
+ 40, digital_gain),
+ SOC_SINGLE_TLV("ADC1 Volume", TAIKO_A_TX_1_2_EN, 5, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC2 Volume", TAIKO_A_TX_1_2_EN, 1, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC3 Volume", TAIKO_A_TX_3_4_EN, 5, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC4 Volume", TAIKO_A_TX_3_4_EN, 1, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_TX_5_6_EN, 5, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_TX_5_6_EN, 1, 3, 0, analog_gain),
+
SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 100, 0, taiko_get_anc_slot,
taiko_put_anc_slot),
@@ -1375,7 +1403,7 @@
"ZERO", "EAR_HPH_L", "EAR_LINE_1",
};
-static const char * const iir1_inp1_text[] = {
+static const char * const iir_inp1_text[] = {
"ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
"DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
};
@@ -1523,7 +1551,10 @@
SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B2_CTL, 0, 3, anc1_fb_mux_text);
static const struct soc_enum iir1_inp1_mux_enum =
- SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir1_inp1_text);
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir_inp1_text);
+
+static const struct soc_enum iir2_inp1_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ2_B1_CTL, 0, 18, iir_inp1_text);
static const struct snd_kcontrol_new rx_mix1_inp1_mux =
SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
@@ -1747,6 +1778,9 @@
static const struct snd_kcontrol_new iir1_inp1_mux =
SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
+static const struct snd_kcontrol_new iir2_inp1_mux =
+ SOC_DAPM_ENUM("IIR2 INP1 Mux", iir2_inp1_mux_enum);
+
static const struct snd_kcontrol_new anc1_mux =
SOC_DAPM_ENUM("ANC1 MUX Mux", anc1_mux_enum);
@@ -3359,6 +3393,7 @@
{"RX1 MIX1 INP1", "RX6", "SLIM RX6"},
{"RX1 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX1 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX1 MIX1 INP1", "IIR2", "IIR2"},
{"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3367,6 +3402,7 @@
{"RX1 MIX1 INP2", "RX6", "SLIM RX6"},
{"RX1 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX1 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX1 MIX1 INP2", "IIR2", "IIR2"},
{"RX1 MIX1 INP3", "RX1", "SLIM RX1"},
{"RX1 MIX1 INP3", "RX2", "SLIM RX2"},
{"RX1 MIX1 INP3", "RX3", "SLIM RX3"},
@@ -3382,6 +3418,7 @@
{"RX2 MIX1 INP1", "RX6", "SLIM RX6"},
{"RX2 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX2 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX2 MIX1 INP1", "IIR2", "IIR2"},
{"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3390,6 +3427,7 @@
{"RX2 MIX1 INP2", "RX6", "SLIM RX6"},
{"RX2 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX2 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX2 MIX1 INP2", "IIR2", "IIR2"},
{"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
@@ -3398,6 +3436,7 @@
{"RX3 MIX1 INP1", "RX6", "SLIM RX6"},
{"RX3 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX3 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX3 MIX1 INP1", "IIR2", "IIR2"},
{"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3406,6 +3445,7 @@
{"RX3 MIX1 INP2", "RX6", "SLIM RX6"},
{"RX3 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX3 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX3 MIX1 INP2", "IIR2", "IIR2"},
{"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
@@ -3414,6 +3454,7 @@
{"RX4 MIX1 INP1", "RX6", "SLIM RX6"},
{"RX4 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX4 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX4 MIX1 INP1", "IIR2", "IIR2"},
{"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3422,6 +3463,7 @@
{"RX4 MIX1 INP2", "RX6", "SLIM RX6"},
{"RX4 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX4 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX4 MIX1 INP2", "IIR2", "IIR2"},
{"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
@@ -3430,6 +3472,7 @@
{"RX5 MIX1 INP1", "RX6", "SLIM RX6"},
{"RX5 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX5 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX5 MIX1 INP1", "IIR2", "IIR2"},
{"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3438,6 +3481,7 @@
{"RX5 MIX1 INP2", "RX6", "SLIM RX6"},
{"RX5 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX5 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX5 MIX1 INP2", "IIR2", "IIR2"},
{"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
@@ -3446,6 +3490,7 @@
{"RX6 MIX1 INP1", "RX6", "SLIM RX6"},
{"RX6 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX6 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX6 MIX1 INP1", "IIR2", "IIR2"},
{"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3454,6 +3499,7 @@
{"RX6 MIX1 INP2", "RX6", "SLIM RX6"},
{"RX6 MIX1 INP2", "RX7", "SLIM RX7"},
{"RX6 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX6 MIX1 INP2", "IIR2", "IIR2"},
{"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
{"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
{"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
@@ -3462,6 +3508,7 @@
{"RX7 MIX1 INP1", "RX6", "SLIM RX6"},
{"RX7 MIX1 INP1", "RX7", "SLIM RX7"},
{"RX7 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX7 MIX1 INP1", "IIR2", "IIR2"},
{"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
{"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
{"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
@@ -3476,6 +3523,13 @@
{"RX2 MIX2 INP2", "IIR1", "IIR1"},
{"RX7 MIX2 INP1", "IIR1", "IIR1"},
{"RX7 MIX2 INP2", "IIR1", "IIR1"},
+ {"RX7 MIX1 INP2", "IIR2", "IIR2"},
+ {"RX1 MIX2 INP1", "IIR2", "IIR2"},
+ {"RX1 MIX2 INP2", "IIR2", "IIR2"},
+ {"RX2 MIX2 INP1", "IIR2", "IIR2"},
+ {"RX2 MIX2 INP2", "IIR2", "IIR2"},
+ {"RX7 MIX2 INP1", "IIR2", "IIR2"},
+ {"RX7 MIX2 INP2", "IIR2", "IIR2"},
/* Decimator Inputs */
{"DEC1 MUX", "DMIC1", "DMIC1"},
@@ -3548,6 +3602,18 @@
{"IIR1 INP1 MUX", "DEC9", "DEC9 MUX"},
{"IIR1 INP1 MUX", "DEC10", "DEC10 MUX"},
+ {"IIR2", NULL, "IIR2 INP1 MUX"},
+ {"IIR2 INP1 MUX", "DEC1", "DEC1 MUX"},
+ {"IIR2 INP1 MUX", "DEC2", "DEC2 MUX"},
+ {"IIR2 INP1 MUX", "DEC3", "DEC3 MUX"},
+ {"IIR2 INP1 MUX", "DEC4", "DEC4 MUX"},
+ {"IIR2 INP1 MUX", "DEC5", "DEC5 MUX"},
+ {"IIR2 INP1 MUX", "DEC6", "DEC6 MUX"},
+ {"IIR2 INP1 MUX", "DEC7", "DEC7 MUX"},
+ {"IIR2 INP1 MUX", "DEC8", "DEC8 MUX"},
+ {"IIR2 INP1 MUX", "DEC9", "DEC9 MUX"},
+ {"IIR2 INP1 MUX", "DEC10", "DEC10 MUX"},
+
{"MIC BIAS1 Internal1", NULL, "LDO_H"},
{"MIC BIAS1 Internal2", NULL, "LDO_H"},
{"MIC BIAS1 External", NULL, "LDO_H"},
@@ -5101,6 +5167,9 @@
SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
SND_SOC_DAPM_PGA("IIR1", TAIKO_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MUX("IIR2 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir2_inp1_mux),
+ SND_SOC_DAPM_PGA("IIR2", TAIKO_A_CDC_CLK_SD_CTL, 1, 0, NULL, 0),
+
/* AUX PGA */
SND_SOC_DAPM_ADC_E("AUX_PGA_Left", NULL, TAIKO_A_RX_AUX_SW_CTL, 7, 0,
taiko_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
@@ -5208,6 +5277,9 @@
u8 leg_mode, txfe_bypass, txfe_buff, flag;
u8 i = 0, j = 0;
u8 val_txfe = 0, value = 0;
+ u8 dmic_sample_rate_value = 0;
+ u8 dmic_b1_ctl_value = 0, dmic_b2_ctl_value = 0;
+ u8 anc_ctl_value = 0;
if (!pdata) {
pr_err("%s: NULL pdata\n", __func__);
@@ -5338,6 +5410,96 @@
0x00 : 0x16);
snd_soc_update_bits(codec, TAIKO_A_MICB_4_CTL, 0x1E, value);
+ /* Set the DMIC sample rate */
+ if (pdata->mclk_rate == TAIKO_MCLK_CLK_9P6HZ) {
+ 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;
+ 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;
+ 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;
+ break;
+ default:
+ pr_err("%s Invalid sample rate %d for mclk %d\n",
+ __func__, pdata->dmic_sample_rate, pdata->mclk_rate);
+ rc = -EINVAL;
+ goto done;
+ break;
+ }
+ } 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;
+ 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;
+ 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;
+ break;
+ default:
+ pr_err("%s Invalid sample rate %d for mclk %d\n",
+ __func__, pdata->dmic_sample_rate, pdata->mclk_rate);
+ rc = -EINVAL;
+ goto done;
+ break;
+ }
+ } else {
+ pr_err("%s MCLK is not set!\n", __func__);
+ rc = -EINVAL;
+ goto done;
+ }
+
+ snd_soc_update_bits(codec, TAIKO_A_CDC_TX1_DMIC_CTL,
+ 0x7, dmic_sample_rate_value);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_TX2_DMIC_CTL,
+ 0x7, dmic_sample_rate_value);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_TX3_DMIC_CTL,
+ 0x7, dmic_sample_rate_value);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_TX4_DMIC_CTL,
+ 0x7, dmic_sample_rate_value);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_TX5_DMIC_CTL,
+ 0x7, dmic_sample_rate_value);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_TX6_DMIC_CTL,
+ 0x7, dmic_sample_rate_value);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_TX7_DMIC_CTL,
+ 0x7, dmic_sample_rate_value);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_TX8_DMIC_CTL,
+ 0x7, dmic_sample_rate_value);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_TX9_DMIC_CTL,
+ 0x7, dmic_sample_rate_value);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_TX10_DMIC_CTL,
+ 0x7, dmic_sample_rate_value);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_DMIC_B1_CTL,
+ 0xEE, dmic_b1_ctl_value);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_DMIC_B2_CTL,
+ 0xE, dmic_b2_ctl_value);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_ANC1_B2_CTL,
+ 0x1, anc_ctl_value);
+
done:
return rc;
}
@@ -5568,22 +5730,6 @@
{TAIKO_A_CDC_TX9_MUX_CTL, 0x8, 0x0},
{TAIKO_A_CDC_TX10_MUX_CTL, 0x8, 0x0},
- /* config Decimator for DMIC CLK_MODE_1(3.2Mhz@9.6Mhz mclk) */
- {TAIKO_A_CDC_TX1_DMIC_CTL, 0x7, 0x1},
- {TAIKO_A_CDC_TX2_DMIC_CTL, 0x7, 0x1},
- {TAIKO_A_CDC_TX3_DMIC_CTL, 0x7, 0x1},
- {TAIKO_A_CDC_TX4_DMIC_CTL, 0x7, 0x1},
- {TAIKO_A_CDC_TX5_DMIC_CTL, 0x7, 0x1},
- {TAIKO_A_CDC_TX6_DMIC_CTL, 0x7, 0x1},
- {TAIKO_A_CDC_TX7_DMIC_CTL, 0x7, 0x1},
- {TAIKO_A_CDC_TX8_DMIC_CTL, 0x7, 0x1},
- {TAIKO_A_CDC_TX9_DMIC_CTL, 0x7, 0x1},
- {TAIKO_A_CDC_TX10_DMIC_CTL, 0x7, 0x1},
-
- /* config DMIC clk to CLK_MODE_1 (3.2Mhz@9.6Mhz mclk) */
- {TAIKO_A_CDC_CLK_DMIC_B1_CTL, 0xEE, 0x22},
- {TAIKO_A_CDC_CLK_DMIC_B2_CTL, 0x0E, 0x02},
-
/* Compander zone selection */
{TAIKO_A_CDC_COMP0_B4_CTL, 0x3F, 0x37},
{TAIKO_A_CDC_COMP1_B4_CTL, 0x3F, 0x37},
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index 764f4c6..cbfff1c 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -604,8 +604,12 @@
ins ? "insert" : "removal");
/* Disable detection to avoid glitch */
snd_soc_update_bits(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DETECT, 1, 0);
- snd_soc_write(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DETECT,
- (0x68 | (ins ? (1 << 1) : 0)));
+ if (mbhc->mbhc_cfg->gpio_level_insert)
+ snd_soc_write(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DETECT,
+ (0x68 | (ins ? (1 << 1) : 0)));
+ else
+ snd_soc_write(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DETECT,
+ (0x6C | (ins ? (1 << 1) : 0)));
/* Re-enable detection */
snd_soc_update_bits(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DETECT, 1, 1);
}
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 35a9646..66c475f 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -163,6 +163,16 @@
OCMEM gets exercised for low-power
audio and voice use cases.
+config DOLBY_DAP
+ bool "Enable Dolby DAP"
+ depends on SND_SOC_MSM8974
+ help
+ To add support for dolby DAP post processing.
+ This support is to configure the post processing parameters
+ to DSP. The configuration includes sending the end point
+ device, end point dependent post processing parameters and
+ the various posrt processing parameters
+
config SND_SOC_MSM8974
tristate "SoC Machine driver for MSM8974 boards"
depends on ARCH_MSM8974
@@ -173,6 +183,7 @@
select SND_SOC_MSM_HDMI_CODEC_RX
select SND_DYNAMIC_MINORS
select AUDIO_OCMEM
+ select DOLBY_DAP
help
To add support for SoC audio on MSM8974.
This will enable sound soc drivers which
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index c26eafc..ebde90b 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -62,12 +62,13 @@
snd-soc-qdsp6-objs += msm-pcm-lpa.o msm-pcm-afe.o
obj-$(CONFIG_SND_SOC_QDSP6) += snd-soc-qdsp6.o
+snd-soc-hostless-pcm-objs := msm-pcm-hostless.o
+obj-$(CONFIG_SND_SOC_MSM_HOSTLESS_PCM) += snd-soc-hostless-pcm.o
+
snd-soc-msm8960-objs := msm8960.o apq8064.o msm8930.o mpq8064.o apq8064-i2s.o
obj-$(CONFIG_SND_SOC_MSM8960) += snd-soc-msm8960.o
# Generic MSM drivers
-snd-soc-hostless-pcm-objs := msm-pcm-hostless.o
-obj-$(CONFIG_SND_SOC_MSM_HOSTLESS_PCM) += snd-soc-hostless-pcm.o
snd-soc-msm8660-apq-objs := msm8660-apq-wm8903.o
obj-$(CONFIG_SND_SOC_MSM8660_APQ) += snd-soc-msm8660-apq.o
diff --git a/sound/soc/msm/apq8064-i2s.c b/sound/soc/msm/apq8064-i2s.c
index f9e0402..99defcd 100644
--- a/sound/soc/msm/apq8064-i2s.c
+++ b/sound/soc/msm/apq8064-i2s.c
@@ -2636,6 +2636,7 @@
pr_info("%s: Not APQ8064 in I2S mode\n", __func__);
return -ENODEV;
}
+ mutex_init(&cdc_mclk_mutex);
pr_debug("%s: APQ8064 is in I2S mode\n", __func__);
mbhc_cfg.calibration = def_tabla_mbhc_cal();
if (!mbhc_cfg.calibration) {
@@ -2680,7 +2681,6 @@
return ret;
}
- mutex_init(&cdc_mclk_mutex);
atomic_set(&mi2s_rsc_ref, 0);
atomic_set(&auxpcm_rsc_ref, 0);
return ret;
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index cafc5c3..7960f13 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -2187,6 +2187,8 @@
if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
bottom_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(16);
+ mutex_init(&cdc_mclk_mutex);
+
mbhc_cfg.calibration = def_tabla_mbhc_cal();
if (!mbhc_cfg.calibration) {
pr_err("Calibration data allocation failed\n");
@@ -2208,7 +2210,6 @@
return ret;
}
- mutex_init(&cdc_mclk_mutex);
atomic_set(&auxpcm_rsc_ref, 0);
return ret;
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 734bd39..8db13f6 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -25,7 +25,7 @@
/* Conventional and unconventional sample rate supported */
static unsigned int supported_sample_rates[] = {
8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
- 96000
+ 96000, 192000
};
static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
@@ -53,14 +53,14 @@
.playback = {
.stream_name = "Multimedia1 Playback",
.aif_name = "MM_DL1",
- .rates = (SNDRV_PCM_RATE_8000_96000|
+ .rates = (SNDRV_PCM_RATE_8000_192000|
SNDRV_PCM_RATE_KNOT),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 8,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "Multimedia1 Capture",
@@ -80,14 +80,14 @@
.playback = {
.stream_name = "Multimedia2 Playback",
.aif_name = "MM_DL2",
- .rates = (SNDRV_PCM_RATE_8000_96000|
+ .rates = (SNDRV_PCM_RATE_8000_192000|
SNDRV_PCM_RATE_KNOT),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 8,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "Multimedia2 Capture",
@@ -157,14 +157,14 @@
.playback = {
.stream_name = "MultiMedia3 Playback",
.aif_name = "MM_DL3",
- .rates = (SNDRV_PCM_RATE_8000_96000 |
+ .rates = (SNDRV_PCM_RATE_8000_192000 |
SNDRV_PCM_RATE_KNOT),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 6,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.ops = &msm_fe_Multimedia_dai_ops,
.name = "MultiMedia3",
@@ -173,14 +173,14 @@
.playback = {
.stream_name = "MultiMedia4 Playback",
.aif_name = "MM_DL4",
- .rates = (SNDRV_PCM_RATE_8000_96000 |
+ .rates = (SNDRV_PCM_RATE_8000_192000 |
SNDRV_PCM_RATE_KNOT),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 8,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "MultiMedia4 Capture",
@@ -200,14 +200,14 @@
.playback = {
.stream_name = "MultiMedia5 Playback",
.aif_name = "MM_DL5",
- .rates = (SNDRV_PCM_RATE_8000_96000 |
+ .rates = (SNDRV_PCM_RATE_8000_192000 |
SNDRV_PCM_RATE_KNOT),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 8,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "MultiMedia5 Capture",
@@ -227,14 +227,14 @@
.playback = {
.stream_name = "MultiMedia6 Playback",
.aif_name = "MM_DL6",
- .rates = (SNDRV_PCM_RATE_8000_96000 |
+ .rates = (SNDRV_PCM_RATE_8000_192000 |
SNDRV_PCM_RATE_KNOT),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 8,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.ops = &msm_fe_Multimedia_dai_ops,
.name = "MultiMedia6",
@@ -243,14 +243,14 @@
.playback = {
.stream_name = "MultiMedia7 Playback",
.aif_name = "MM_DL7",
- .rates = (SNDRV_PCM_RATE_8000_96000 |
+ .rates = (SNDRV_PCM_RATE_8000_192000 |
SNDRV_PCM_RATE_KNOT),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 8,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.ops = &msm_fe_Multimedia_dai_ops,
.name = "MultiMedia7",
@@ -259,14 +259,14 @@
.playback = {
.stream_name = "MultiMedia8 Playback",
.aif_name = "MM_DL8",
- .rates = (SNDRV_PCM_RATE_8000_96000 |
+ .rates = (SNDRV_PCM_RATE_8000_192000 |
SNDRV_PCM_RATE_KNOT),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 8,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.ops = &msm_fe_Multimedia_dai_ops,
.name = "MultiMedia8",
@@ -276,7 +276,7 @@
.playback = {
.stream_name = "SLIMBUS0 Hostless Playback",
.aif_name = "SLIM0_DL_HL",
- .rates = SNDRV_PCM_RATE_8000_96000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
@@ -301,13 +301,13 @@
.playback = {
.stream_name = "SLIMBUS1 Hostless Playback",
.aif_name = "SLIM1_DL_HL",
- .rates = SNDRV_PCM_RATE_8000_96000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 2,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "SLIMBUS1 Hostless Capture",
@@ -326,13 +326,13 @@
.playback = {
.stream_name = "SLIMBUS3 Hostless Playback",
.aif_name = "SLIM3_DL_HL",
- .rates = SNDRV_PCM_RATE_8000_48000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 2,
.rate_min = 8000,
- .rate_max = 48000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "SLIMBUS3 Hostless Capture",
@@ -351,13 +351,13 @@
.playback = {
.stream_name = "SLIMBUS4 Hostless Playback",
.aif_name = "SLIM4_DL_HL",
- .rates = SNDRV_PCM_RATE_8000_96000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 2,
.rate_min = 8000,
- .rate_max = 48000,
+ .rate_max = 192000,
},
.capture = {
.stream_name = "SLIMBUS4 Hostless Capture",
diff --git a/sound/soc/msm/msm-pcm-afe.c b/sound/soc/msm/msm-pcm-afe.c
index a3bcf23..35b5dcf 100644
--- a/sound/soc/msm/msm-pcm-afe.c
+++ b/sound/soc/msm/msm-pcm-afe.c
@@ -30,7 +30,6 @@
#include <sound/q6adm.h>
#include <asm/dma.h>
#include <linux/memory_alloc.h>
-#include <mach/msm_subsystem_map.h>
#include "msm-pcm-afe.h"
#include "msm-pcm-q6.h"
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index 2bd5c88..737317c 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -63,6 +63,7 @@
static int clk_users;
static int msm8930_headset_gpios_configured;
+static struct mutex cdc_mclk_mutex;
static struct snd_soc_jack hs_jack;
static struct snd_soc_jack button_jack;
@@ -265,35 +266,42 @@
struct snd_soc_codec *codec, int enable,
bool dapm)
{
+ int r = 0;
pr_debug("%s: enable = %d\n", __func__, enable);
+
+ mutex_lock(&cdc_mclk_mutex);
if (enable) {
clk_users++;
pr_debug("%s: clk_users = %d\n", __func__, clk_users);
- if (clk_users != 1)
- return 0;
-
- if (codec_clk) {
- clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
- clk_prepare_enable(codec_clk);
- sitar_mclk_enable(codec, 1, dapm);
- } else {
- pr_err("%s: Error setting Sitar MCLK\n", __func__);
- clk_users--;
- return -EINVAL;
+ if (clk_users == 1) {
+ if (codec_clk) {
+ clk_set_rate(codec_clk, SITAR_EXT_CLK_RATE);
+ clk_prepare_enable(codec_clk);
+ sitar_mclk_enable(codec, 1, dapm);
+ } else {
+ pr_err("%s: Error setting Sitar MCLK\n",
+ __func__);
+ clk_users--;
+ r = -EINVAL;
+ }
}
} else {
- pr_debug("%s: clk_users = %d\n", __func__, clk_users);
- if (clk_users == 0)
- return 0;
- clk_users--;
- if (!clk_users) {
- pr_debug("%s: disabling MCLK. clk_users = %d\n",
+ if (clk_users > 0) {
+ clk_users--;
+ pr_debug("%s: clk_users = %d\n", __func__, clk_users);
+ if (clk_users == 0) {
+ pr_debug("%s: disabling MCLK. clk_users = %d\n",
__func__, clk_users);
- sitar_mclk_enable(codec, 0, dapm);
- clk_disable_unprepare(codec_clk);
+ sitar_mclk_enable(codec, 0, dapm);
+ clk_disable_unprepare(codec_clk);
+ }
+ } else {
+ pr_err("%s: Error releasing Sitar MCLK\n", __func__);
+ r = -EINVAL;
}
}
- return 0;
+ mutex_unlock(&cdc_mclk_mutex);
+ return r;
}
static int msm8930_mclk_event(struct snd_soc_dapm_widget *w,
@@ -1378,6 +1386,7 @@
msm8930_headset_gpios_configured = 1;
atomic_set(&auxpcm_rsc_ref, 0);
+ mutex_init(&cdc_mclk_mutex);
return ret;
}
@@ -1392,6 +1401,7 @@
msm8930_free_headset_mic_gpios();
platform_device_unregister(msm8930_snd_device);
kfree(mbhc_cfg.calibration);
+ mutex_destroy(&cdc_mclk_mutex);
}
module_exit(msm8930_audio_exit);
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 8c0d1a9..c7fbc43 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -746,21 +746,21 @@
btn_low = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_LOW);
btn_high = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_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] = 21;
+ btn_low[1] = 22;
+ btn_high[1] = 67;
+ btn_low[2] = 68;
+ btn_high[2] = 111;
+ btn_low[3] = 112;
+ btn_high[3] = 153;
+ btn_low[4] = 154;
+ btn_high[4] = 191;
+ btn_low[5] = 192;
+ btn_high[5] = 233;
+ btn_low[6] = 234;
+ btn_high[6] = 272;
+ btn_low[7] = 273;
+ btn_high[7] = 400;
n_ready = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_READY);
n_ready[0] = 80;
n_ready[1] = 68;
@@ -1778,6 +1778,7 @@
return -ENODEV ;
}
+ mutex_init(&cdc_mclk_mutex);
mbhc_cfg.calibration = def_tabla_mbhc_cal();
if (!mbhc_cfg.calibration) {
pr_err("Calibration data allocation failed\n");
@@ -1837,7 +1838,6 @@
__func__);
}
- mutex_init(&cdc_mclk_mutex);
atomic_set(&auxpcm_rsc_ref, 0);
return ret;
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 30e9629..9ff968f 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -48,6 +48,7 @@
#define SAMPLING_RATE_48KHZ 48000
#define SAMPLING_RATE_96KHZ 96000
+#define SAMPLING_RATE_192KHZ 192000
static int msm8974_auxpcm_rate = 8000;
#define LO_1_SPK_AMP 0x1
@@ -137,19 +138,28 @@
u32 mclk_freq;
int us_euro_gpio;
struct msm_auxpcm_ctrl *pri_auxpcm_ctrl;
+ struct msm_auxpcm_ctrl *sec_auxpcm_ctrl;
};
#define GPIO_NAME_INDEX 0
#define DT_PARSE_INDEX 1
-static char *msm_auxpcm_gpio_name[][2] = {
- {"PRIM_AUXPCM_CLK", "prim-auxpcm-gpio-clk"},
- {"PRIM_AUXPCM_SYNC", "prim-auxpcm-gpio-sync"},
- {"PRIM_AUXPCM_DIN", "prim-auxpcm-gpio-din"},
- {"PRIM_AUXPCM_DOUT", "prim-auxpcm-gpio-dout"},
+static char *msm_prim_auxpcm_gpio_name[][2] = {
+ {"PRIM_AUXPCM_CLK", "qcom,prim-auxpcm-gpio-clk"},
+ {"PRIM_AUXPCM_SYNC", "qcom,prim-auxpcm-gpio-sync"},
+ {"PRIM_AUXPCM_DIN", "qcom,prim-auxpcm-gpio-din"},
+ {"PRIM_AUXPCM_DOUT", "qcom,prim-auxpcm-gpio-dout"},
+};
+
+static char *msm_sec_auxpcm_gpio_name[][2] = {
+ {"SEC_AUXPCM_CLK", "qcom,sec-auxpcm-gpio-clk"},
+ {"SEC_AUXPCM_SYNC", "qcom,sec-auxpcm-gpio-sync"},
+ {"SEC_AUXPCM_DIN", "qcom,sec-auxpcm-gpio-din"},
+ {"SEC_AUXPCM_DOUT", "qcom,sec-auxpcm-gpio-dout"},
};
void *lpaif_pri_muxsel_virt_addr;
+void *lpaif_sec_muxsel_virt_addr;
struct msm8974_liquid_dock_dev {
int dock_plug_gpio;
@@ -187,7 +197,8 @@
static struct mutex cdc_mclk_mutex;
static struct q_clkdiv *codec_clk;
static int clk_users;
-static atomic_t auxpcm_rsc_ref;
+static atomic_t prim_auxpcm_rsc_ref;
+static atomic_t sec_auxpcm_rsc_ref;
static int msm8974_liquid_ext_spk_power_amp_init(void)
@@ -577,13 +588,8 @@
static char const *hdmi_rx_ch_text[] = {"Two", "Three", "Four", "Five",
"Six", "Seven", "Eight"};
static char const *rx_bit_format_text[] = {"S16_LE", "S24_LE"};
-static char const *slim0_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96"};
-
-static const struct soc_enum msm_enum[] = {
- SOC_ENUM_SINGLE_EXT(2, spk_function),
- SOC_ENUM_SINGLE_EXT(2, slim0_rx_ch_text),
- SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
-};
+static char const *slim0_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96",
+ "KHZ_192"};
static const char *const btsco_rate_text[] = {"8000", "16000"};
static const struct soc_enum msm_btsco_enum[] = {
@@ -596,6 +602,10 @@
int sample_rate_val = 0;
switch (slim0_rx_sample_rate) {
+ case SAMPLING_RATE_192KHZ:
+ sample_rate_val = 2;
+ break;
+
case SAMPLING_RATE_96KHZ:
sample_rate_val = 1;
break;
@@ -620,6 +630,9 @@
ucontrol->value.integer.value[0]);
switch (ucontrol->value.integer.value[0]) {
+ case 2:
+ slim0_rx_sample_rate = SAMPLING_RATE_192KHZ;
+ break;
case 1:
slim0_rx_sample_rate = SAMPLING_RATE_96KHZ;
break;
@@ -891,30 +904,13 @@
return 0;
}
-static int msm_aux_pcm_get_gpios(struct snd_pcm_substream *substream)
+static int msm_aux_pcm_get_gpios(struct msm_auxpcm_ctrl *auxpcm_ctrl)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_card *card = rtd->card;
- struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
- struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
struct msm_auxpcm_gpio *pin_data = NULL;
int ret = 0;
int i;
int j;
- if (pdata == NULL) {
- pr_err("%s: pdata is NULL\n", __func__);
- ret = -EINVAL;
- goto err;
- }
-
- auxpcm_ctrl = pdata->pri_auxpcm_ctrl;
-
- if (auxpcm_ctrl == NULL || auxpcm_ctrl->pin_data == NULL) {
- pr_err("%s: Ctrl pointers are NULL\n", __func__);
- ret = -EINVAL;
- goto err;
- }
pin_data = auxpcm_ctrl->pin_data;
for (i = 0; i < auxpcm_ctrl->cnt; i++, pin_data++) {
ret = gpio_request(pin_data->gpio_no,
@@ -930,31 +926,17 @@
/* Release all GPIOs on failure */
for (j = i; j >= 0; j--)
gpio_free(pin_data->gpio_no);
- goto err;
+ return ret;
}
}
-
-err:
- return ret;
+ return 0;
}
-static int msm_aux_pcm_free_gpios(struct snd_pcm_substream *substream)
+static int msm_aux_pcm_free_gpios(struct msm_auxpcm_ctrl *auxpcm_ctrl)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_card *card = rtd->card;
- struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
- struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
struct msm_auxpcm_gpio *pin_data = NULL;
- int ret = 0;
int i;
-
- if (pdata == NULL) {
- pr_err("%s: pdata is NULL\n", __func__);
- ret = -EINVAL;
- goto err;
- }
-
- auxpcm_ctrl = pdata->pri_auxpcm_ctrl;
+ int ret = 0;
if (auxpcm_ctrl == NULL || auxpcm_ctrl->pin_data == NULL) {
pr_err("%s: Ctrl pointers are NULL\n", __func__);
@@ -973,40 +955,115 @@
return ret;
}
-static int msm_auxpcm_startup(struct snd_pcm_substream *substream)
+static int msm_prim_auxpcm_startup(struct snd_pcm_substream *substream)
{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+ struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
int ret = 0;
- pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
- __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
+ pr_debug("%s(): substream = %s, prim_auxpcm_rsc_ref counter = %d\n",
+ __func__, substream->name, atomic_read(&prim_auxpcm_rsc_ref));
- if (atomic_inc_return(&auxpcm_rsc_ref) == 1) {
+ auxpcm_ctrl = pdata->pri_auxpcm_ctrl;
+
+ if (auxpcm_ctrl == NULL || auxpcm_ctrl->pin_data == NULL) {
+ pr_err("%s: Ctrl pointers are NULL\n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+ if (atomic_inc_return(&prim_auxpcm_rsc_ref) == 1) {
if (lpaif_pri_muxsel_virt_addr != NULL)
iowrite32(I2S_PCM_SEL << I2S_PCM_SEL_OFFSET,
lpaif_pri_muxsel_virt_addr);
else
pr_err("%s lpaif_pri_muxsel_virt_addr is NULL\n",
__func__);
- ret = msm_aux_pcm_get_gpios(substream);
+ ret = msm_aux_pcm_get_gpios(auxpcm_ctrl);
}
if (ret < 0) {
pr_err("%s: Aux PCM GPIO request failed\n", __func__);
return -EINVAL;
}
+err:
return ret;
}
-static void msm_auxpcm_shutdown(struct snd_pcm_substream *substream)
+static void msm_prim_auxpcm_shutdown(struct snd_pcm_substream *substream)
{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+ struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
- pr_debug("%s(): substream = %s, auxpcm_rsc_ref counter = %d\n",
- __func__, substream->name, atomic_read(&auxpcm_rsc_ref));
- if (atomic_dec_return(&auxpcm_rsc_ref) == 0)
- msm_aux_pcm_free_gpios(substream);
+ pr_debug("%s(): substream = %s, prim_auxpcm_rsc_ref counter = %d\n",
+ __func__, substream->name, atomic_read(&prim_auxpcm_rsc_ref));
+
+ auxpcm_ctrl = pdata->pri_auxpcm_ctrl;
+
+ if (atomic_dec_return(&prim_auxpcm_rsc_ref) == 0)
+ msm_aux_pcm_free_gpios(auxpcm_ctrl);
}
-static struct snd_soc_ops msm_auxpcm_be_ops = {
- .startup = msm_auxpcm_startup,
- .shutdown = msm_auxpcm_shutdown,
+static struct snd_soc_ops msm_pri_auxpcm_be_ops = {
+ .startup = msm_prim_auxpcm_startup,
+ .shutdown = msm_prim_auxpcm_shutdown,
+};
+
+static int msm_sec_auxpcm_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+ struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
+ int ret = 0;
+
+ pr_debug("%s(): substream = %s, sec_auxpcm_rsc_ref counter = %d\n",
+ __func__, substream->name, atomic_read(&sec_auxpcm_rsc_ref));
+
+ auxpcm_ctrl = pdata->sec_auxpcm_ctrl;
+
+ if (auxpcm_ctrl == NULL || auxpcm_ctrl->pin_data == NULL) {
+ pr_err("%s: Ctrl pointers are NULL\n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
+ if (atomic_inc_return(&sec_auxpcm_rsc_ref) == 1) {
+ if (lpaif_sec_muxsel_virt_addr != NULL)
+ iowrite32(I2S_PCM_SEL << I2S_PCM_SEL_OFFSET,
+ lpaif_sec_muxsel_virt_addr);
+ else
+ pr_err("%s lpaif_sec_muxsel_virt_addr is NULL\n",
+ __func__);
+ ret = msm_aux_pcm_get_gpios(auxpcm_ctrl);
+ }
+ if (ret < 0) {
+ pr_err("%s: Aux PCM GPIO request failed\n", __func__);
+ return -EINVAL;
+ }
+err:
+ return ret;
+}
+
+static void msm_sec_auxpcm_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_card *card = rtd->card;
+ struct msm8974_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card);
+ struct msm_auxpcm_ctrl *auxpcm_ctrl = NULL;
+
+ pr_debug("%s(): substream = %s, sec_auxpcm_rsc_ref counter = %d\n",
+ __func__, substream->name, atomic_read(&sec_auxpcm_rsc_ref));
+
+ auxpcm_ctrl = pdata->sec_auxpcm_ctrl;
+
+ if (atomic_dec_return(&sec_auxpcm_rsc_ref) == 0)
+ msm_aux_pcm_free_gpios(auxpcm_ctrl);
+}
+
+static struct snd_soc_ops msm_sec_auxpcm_be_ops = {
+ .startup = msm_sec_auxpcm_startup,
+ .shutdown = msm_sec_auxpcm_shutdown,
};
static int msm_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
@@ -1092,7 +1149,7 @@
SOC_ENUM_SINGLE_EXT(4, slim0_tx_ch_text),
SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text),
SOC_ENUM_SINGLE_EXT(2, rx_bit_format_text),
- SOC_ENUM_SINGLE_EXT(2, slim0_rx_sample_rate_text),
+ SOC_ENUM_SINGLE_EXT(3, slim0_rx_sample_rate_text),
};
static const struct snd_kcontrol_new msm_snd_controls[] = {
@@ -1784,7 +1841,7 @@
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
},
- /* AUX PCM Backend DAI Links */
+ /* Primary AUX PCM Backend DAI Links */
{
.name = LPASS_BE_AUXPCM_RX,
.stream_name = "AUX PCM Playback",
@@ -1795,7 +1852,7 @@
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_AUXPCM_RX,
.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
- .ops = &msm_auxpcm_be_ops,
+ .ops = &msm_pri_auxpcm_be_ops,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
/* this dainlink has playback support */
@@ -1810,9 +1867,39 @@
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
.be_hw_params_fixup = msm_auxpcm_be_params_fixup,
- .ops = &msm_auxpcm_be_ops,
+ .ops = &msm_pri_auxpcm_be_ops,
.ignore_suspend = 1,
},
+ /* Secondary AUX PCM Backend DAI Links */
+ {
+ .name = LPASS_BE_SEC_AUXPCM_RX,
+ .stream_name = "Sec AUX PCM Playback",
+ .cpu_dai_name = "msm-dai-q6.4108",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
+ .ops = &msm_sec_auxpcm_be_ops,
+ .ignore_pmdown_time = 1,
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ },
+ {
+ .name = LPASS_BE_SEC_AUXPCM_TX,
+ .stream_name = "Sec AUX PCM Capture",
+ .cpu_dai_name = "msm-dai-q6.4109",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ .be_hw_params_fixup = msm_auxpcm_be_params_fixup,
+ .ops = &msm_sec_auxpcm_be_ops,
+ .ignore_suspend = 1,
+ },
+
/* Backend DAI Links */
{
.name = LPASS_BE_SLIMBUS_0_RX,
@@ -2030,7 +2117,8 @@
};
static int msm8974_dtparse_auxpcm(struct platform_device *pdev,
- struct msm8974_asoc_mach_data **pdata)
+ struct msm_auxpcm_ctrl **auxpcm_ctrl,
+ char *msm_auxpcm_gpio_name[][2])
{
int ret = 0;
int i = 0;
@@ -2038,7 +2126,7 @@
struct msm_auxpcm_ctrl *ctrl;
unsigned int gpio_no[NUM_OF_AUXPCM_GPIOS];
enum of_gpio_flags flags = OF_GPIO_ACTIVE_LOW;
- int prim_cnt = 0;
+ int auxpcm_cnt = 0;
pin_data = devm_kzalloc(&pdev->dev, (ARRAY_SIZE(gpio_no) *
sizeof(struct msm_auxpcm_gpio)),
@@ -2056,13 +2144,13 @@
if (gpio_no[i] > 0) {
pin_data[i].gpio_name =
- msm_auxpcm_gpio_name[prim_cnt][GPIO_NAME_INDEX];
+ msm_auxpcm_gpio_name[auxpcm_cnt][GPIO_NAME_INDEX];
pin_data[i].gpio_no = gpio_no[i];
dev_dbg(&pdev->dev, "%s:GPIO gpio[%s] =\n"
"0x%x\n", __func__,
pin_data[i].gpio_name,
pin_data[i].gpio_no);
- prim_cnt++;
+ auxpcm_cnt++;
} else {
dev_err(&pdev->dev, "%s:Invalid AUXPCM GPIO[%s]= %x\n",
__func__,
@@ -2082,8 +2170,8 @@
}
ctrl->pin_data = pin_data;
- ctrl->cnt = prim_cnt;
- (*pdata)->pri_auxpcm_ctrl = ctrl;
+ ctrl->cnt = auxpcm_cnt;
+ *auxpcm_ctrl = ctrl;
return ret;
err:
@@ -2160,10 +2248,21 @@
return -ENOMEM;
}
- ret = msm8974_dtparse_auxpcm(pdev, &pdata);
+ /* Parse Primary AUXPCM info from DT */
+ ret = msm8974_dtparse_auxpcm(pdev, &pdata->pri_auxpcm_ctrl,
+ msm_prim_auxpcm_gpio_name);
if (ret) {
dev_err(&pdev->dev,
- "%s: Auxpcm pin data parse failed\n", __func__);
+ "%s: Primary Auxpcm pin data parse failed\n", __func__);
+ goto err;
+ }
+
+ /* Parse Secondary AUXPCM info from DT */
+ ret = msm8974_dtparse_auxpcm(pdev, &pdata->sec_auxpcm_ctrl,
+ msm_sec_auxpcm_gpio_name);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s: Secondary Auxpcm pin data parse failed\n", __func__);
goto err;
}
@@ -2248,7 +2347,8 @@
ret);
mutex_init(&cdc_mclk_mutex);
- atomic_set(&auxpcm_rsc_ref, 0);
+ atomic_set(&prim_auxpcm_rsc_ref, 0);
+ atomic_set(&sec_auxpcm_rsc_ref, 0);
spdev = pdev;
ext_spk_amp_regulator = NULL;
msm8974_liquid_dock_dev = NULL;
@@ -2266,6 +2366,12 @@
ret = -EINVAL;
goto err;
}
+ lpaif_sec_muxsel_virt_addr = ioremap(LPAIF_SEC_MODE_MUXSEL, 4);
+ if (lpaif_sec_muxsel_virt_addr == NULL) {
+ pr_err("%s Sec muxsel virt addr is null\n", __func__);
+ ret = -EINVAL;
+ goto err;
+ }
return 0;
err:
if (pdata->mclk_gpio > 0) {
@@ -2310,6 +2416,7 @@
}
iounmap(lpaif_pri_muxsel_virt_addr);
+ iounmap(lpaif_sec_muxsel_virt_addr);
snd_soc_unregister_card(card);
return 0;
diff --git a/sound/soc/msm/qdsp6v2/Makefile b/sound/soc/msm/qdsp6v2/Makefile
index 391b3da..f3dcf95 100644
--- a/sound/soc/msm/qdsp6v2/Makefile
+++ b/sound/soc/msm/qdsp6v2/Makefile
@@ -5,6 +5,7 @@
msm-lsm-client.o
obj-$(CONFIG_SND_SOC_QDSP6V2) += snd-soc-qdsp6v2.o msm-pcm-dtmf-v2.o \
msm-dai-stub-v2.o
+obj-$(CONFIG_DOLBY_DAP) += msm-dolby-dap-config.o
obj-y += q6adm.o q6afe.o q6asm.o q6audio-v2.o q6voice.o q6core.o audio_acdb.o \
rtac.o q6lsm.o
ocmem-audio-objs += audio_ocmem.o
diff --git a/sound/soc/msm/qdsp6v2/audio_acdb.c b/sound/soc/msm/qdsp6v2/audio_acdb.c
index 16d6e81..96da2f1 100644
--- a/sound/soc/msm/qdsp6v2/audio_acdb.c
+++ b/sound/soc/msm/qdsp6v2/audio_acdb.c
@@ -18,6 +18,7 @@
#include <linux/uaccess.h>
#include <linux/msm_ion.h>
#include <linux/mm.h>
+#include <linux/msm_audio_ion.h>
#include "audio_acdb.h"
@@ -870,9 +871,7 @@
kfree(acdb_data.col_data[i]);
acdb_data.col_data[i] = NULL;
}
- ion_unmap_kernel(acdb_data.ion_client, acdb_data.ion_handle);
- ion_free(acdb_data.ion_client, acdb_data.ion_handle);
- ion_client_destroy(acdb_data.ion_client);
+ msm_audio_ion_free(acdb_data.ion_client, acdb_data.ion_handle);
mutex_unlock(&acdb_data.acdb_mutex);
}
return 0;
@@ -894,34 +893,16 @@
(uint32_t)acdb_data.col_data[i]);
}
- acdb_data.ion_client =
- msm_ion_client_create(UINT_MAX, "audio_acdb_client");
- if (IS_ERR_OR_NULL(acdb_data.ion_client)) {
- pr_err("%s: Could not register ION client!!!\n", __func__);
+ result = msm_audio_ion_import("audio_acdb_client",
+ &acdb_data.ion_client,
+ &acdb_data.ion_handle,
+ atomic_read(&acdb_data.map_handle),
+ NULL, 0,
+ &paddr, (size_t *)&mem_len, &kvptr);
+ if (result) {
+ pr_err("%s: audio ION alloc failed, rc = %d\n",
+ __func__, result);
result = PTR_ERR(acdb_data.ion_client);
- goto err;
- }
-
- acdb_data.ion_handle = ion_import_dma_buf(acdb_data.ion_client,
- atomic_read(&acdb_data.map_handle));
- if (IS_ERR_OR_NULL(acdb_data.ion_handle)) {
- pr_err("%s: Could not import map handle!!!\n", __func__);
- result = PTR_ERR(acdb_data.ion_handle);
- goto err_ion_client;
- }
-
- result = ion_phys(acdb_data.ion_client, acdb_data.ion_handle,
- &paddr, (size_t *)&mem_len);
- if (result != 0) {
- pr_err("%s: Could not get phys addr!!!\n", __func__);
- goto err_ion_handle;
- }
-
- kvptr = ion_map_kernel(acdb_data.ion_client,
- acdb_data.ion_handle);
- if (IS_ERR_OR_NULL(kvptr)) {
- pr_err("%s: Could not get kernel virt addr!!!\n", __func__);
- result = PTR_ERR(kvptr);
goto err_ion_handle;
}
kvaddr = (unsigned long)kvptr;
@@ -938,10 +919,8 @@
return result;
err_ion_handle:
- ion_free(acdb_data.ion_client, acdb_data.ion_handle);
-err_ion_client:
- ion_client_destroy(acdb_data.ion_client);
-err:
+ msm_audio_ion_free(acdb_data.ion_client, acdb_data.ion_handle);
+
atomic64_set(&acdb_data.mem_len, 0);
mutex_unlock(&acdb_data.acdb_mutex);
return result;
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 5dc5f96..9359ed7 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -321,6 +321,23 @@
}
}
+static int msm_compr_send_ddp_cfg(struct audio_client *ac,
+ struct snd_dec_ddp *ddp)
+{
+ int i, rc;
+ pr_debug("%s\n", __func__);
+ for (i = 0; i < ddp->params_length/2; i++) {
+ rc = q6asm_ds1_set_endp_params(ac, ddp->params_id[i],
+ ddp->params_value[i]);
+ if (rc) {
+ pr_err("sending params_id: %d failed\n",
+ ddp->params_id[i]);
+ return rc;
+ }
+ }
+ return 0;
+}
+
static int msm_compr_playback_prepare(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -358,6 +375,24 @@
if (ret < 0)
pr_err("%s: CMD Format block failed\n", __func__);
break;
+ case SND_AUDIOCODEC_AC3: {
+ struct snd_dec_ddp *ddp =
+ &compr->info.codec_param.codec.options.ddp;
+ pr_debug("%s: SND_AUDIOCODEC_AC3\n", __func__);
+ ret = msm_compr_send_ddp_cfg(prtd->audio_client, ddp);
+ if (ret < 0)
+ pr_err("%s: DDP CMD CFG failed\n", __func__);
+ break;
+ }
+ case SND_AUDIOCODEC_EAC3: {
+ struct snd_dec_ddp *ddp =
+ &compr->info.codec_param.codec.options.ddp;
+ pr_debug("%s: SND_AUDIOCODEC_EAC3\n", __func__);
+ ret = msm_compr_send_ddp_cfg(prtd->audio_client, ddp);
+ if (ret < 0)
+ pr_err("%s: DDP CMD CFG failed\n", __func__);
+ break;
+ }
default:
return -EINVAL;
}
@@ -511,13 +546,15 @@
{
pr_debug("%s\n", __func__);
/* MP3 Block */
- compr->info.compr_cap.num_codecs = 2;
+ compr->info.compr_cap.num_codecs = 4;
compr->info.compr_cap.min_fragment_size = runtime->hw.period_bytes_min;
compr->info.compr_cap.max_fragment_size = runtime->hw.period_bytes_max;
compr->info.compr_cap.min_fragments = runtime->hw.periods_min;
compr->info.compr_cap.max_fragments = runtime->hw.periods_max;
compr->info.compr_cap.codecs[0] = SND_AUDIOCODEC_MP3;
compr->info.compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
+ compr->info.compr_cap.codecs[2] = SND_AUDIOCODEC_AC3;
+ compr->info.compr_cap.codecs[3] = SND_AUDIOCODEC_EAC3;
/* Add new codecs here */
}
@@ -897,7 +934,7 @@
}
return 0;
case SNDRV_COMPRESS_SET_PARAMS:
- pr_debug("SNDRV_COMPRESS_SET_PARAMS: ");
+ pr_debug("SNDRV_COMPRESS_SET_PARAMS:\n");
if (copy_from_user(&compr->info.codec_param, (void *) arg,
sizeof(struct snd_compr_params))) {
rc = -EFAULT;
@@ -914,6 +951,68 @@
pr_debug("SND_AUDIOCODEC_AAC\n");
compr->codec = FORMAT_MPEG4_AAC;
break;
+ case SND_AUDIOCODEC_AC3: {
+ char params_value[18*2*sizeof(int)];
+ int *params_value_data = (int *)params_value;
+ /* 36 is the max param length for ddp */
+ int i;
+ struct snd_dec_ddp *ddp =
+ &compr->info.codec_param.codec.options.ddp;
+ int params_length = ddp->params_length*sizeof(int);
+ pr_debug("SND_AUDIOCODEC_AC3\n");
+ compr->codec = FORMAT_AC3;
+ if (copy_from_user(params_value, (void *)ddp->params,
+ params_length))
+ pr_err("%s: ERROR: copy ddp params value\n",
+ __func__);
+ pr_debug("params_length: %d\n", ddp->params_length);
+ for (i = 0; i < params_length; i++)
+ pr_debug("params_value[%d]: %x\n", i,
+ params_value_data[i]);
+ for (i = 0; i < ddp->params_length/2; i++) {
+ ddp->params_id[i] = params_value_data[2*i];
+ ddp->params_value[i] = params_value_data[2*i+1];
+ }
+ if (atomic_read(&prtd->start)) {
+ rc = msm_compr_send_ddp_cfg(prtd->audio_client,
+ ddp);
+ if (rc < 0)
+ pr_err("%s: DDP CMD CFG failed\n",
+ __func__);
+ }
+ break;
+ }
+ case SND_AUDIOCODEC_EAC3: {
+ char params_value[18*2*sizeof(int)];
+ int *params_value_data = (int *)params_value;
+ /* 36 is the max param length for ddp */
+ int i;
+ struct snd_dec_ddp *ddp =
+ &compr->info.codec_param.codec.options.ddp;
+ int params_length = ddp->params_length*sizeof(int);
+ pr_debug("SND_AUDIOCODEC_EAC3\n");
+ compr->codec = FORMAT_EAC3;
+ if (copy_from_user(params_value, (void *)ddp->params,
+ params_length))
+ pr_err("%s: ERROR: copy ddp params value\n",
+ __func__);
+ pr_debug("params_length: %d\n", ddp->params_length);
+ for (i = 0; i < ddp->params_length; i++)
+ pr_debug("params_value[%d]: %x\n", i,
+ params_value_data[i]);
+ for (i = 0; i < ddp->params_length/2; i++) {
+ ddp->params_id[i] = params_value_data[2*i];
+ ddp->params_value[i] = params_value_data[2*i+1];
+ }
+ if (atomic_read(&prtd->start)) {
+ rc = msm_compr_send_ddp_cfg(prtd->audio_client,
+ ddp);
+ if (rc < 0)
+ pr_err("%s: DDP CMD CFG failed\n",
+ __func__);
+ }
+ break;
+ }
default:
pr_debug("FORMAT_LINEAR_PCM\n");
compr->codec = FORMAT_LINEAR_PCM;
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 5b18311..80caaf7 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -155,6 +155,8 @@
struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
struct afe_clk_cfg lpass_pcm_oe_clk;
struct msm_dai_auxpcm_pdata *auxpcm_pdata = NULL;
+ unsigned int rx_port = 0;
+ unsigned int tx_port = 0;
mutex_lock(&aux_pcm_mutex);
@@ -186,22 +188,32 @@
auxpcm_pdata = (struct msm_dai_auxpcm_pdata *)dai->dev->platform_data;
lpass_pcm_src_clk = (struct afe_clk_cfg *)auxpcm_pdata->clk_cfg;
- rc = afe_close(PCM_RX); /* can block */
+ if (dai->id == AFE_PORT_ID_PRIMARY_PCM_RX
+ || dai->id == AFE_PORT_ID_PRIMARY_PCM_TX) {
+ rx_port = PCM_RX;
+ tx_port = PCM_TX;
+ } else if (dai->id == AFE_PORT_ID_SECONDARY_PCM_RX
+ || dai->id == AFE_PORT_ID_SECONDARY_PCM_TX) {
+ rx_port = AFE_PORT_ID_SECONDARY_PCM_RX;
+ tx_port = AFE_PORT_ID_SECONDARY_PCM_TX;
+ }
+
+ rc = afe_close(rx_port); /* can block */
if (IS_ERR_VALUE(rc))
dev_err(dai->dev, "fail to close PCM_RX AFE port\n");
- rc = afe_close(PCM_TX);
+ rc = afe_close(tx_port);
if (IS_ERR_VALUE(rc))
dev_err(dai->dev, "fail to close AUX PCM TX port\n");
lpass_pcm_src_clk->clk_val1 = 0;
- afe_set_lpass_clock(PCM_TX, lpass_pcm_src_clk);
- afe_set_lpass_clock(PCM_RX, lpass_pcm_src_clk);
+ afe_set_lpass_clock(tx_port, lpass_pcm_src_clk);
+ afe_set_lpass_clock(rx_port, lpass_pcm_src_clk);
memcpy(&lpass_pcm_oe_clk, &lpass_clk_cfg_default,
sizeof(struct afe_clk_cfg));
lpass_pcm_oe_clk.clk_val1 = 0;
- afe_set_lpass_clock(PCM_RX, &lpass_pcm_oe_clk);
+ afe_set_lpass_clock(rx_port, &lpass_pcm_oe_clk);
mutex_unlock(&aux_pcm_mutex);
}
@@ -215,6 +227,8 @@
unsigned long pcm_clk_rate;
struct afe_clk_cfg lpass_pcm_oe_clk;
struct afe_clk_cfg *lpass_pcm_src_clk = NULL;
+ unsigned int rx_port = 0;
+ unsigned int tx_port = 0;
auxpcm_pdata = dai->dev->platform_data;
lpass_pcm_src_clk = (struct afe_clk_cfg *)auxpcm_pdata->clk_cfg;
@@ -279,30 +293,39 @@
sizeof(struct afe_clk_cfg));
lpass_pcm_oe_clk.clk_val1 = Q6AFE_LPASS_OSR_CLK_12_P288_MHZ;
- rc = afe_set_lpass_clock(PCM_RX, lpass_pcm_src_clk);
+ if (dai->id == AFE_PORT_ID_PRIMARY_PCM_RX ||
+ dai->id == AFE_PORT_ID_PRIMARY_PCM_TX) {
+ rx_port = PCM_RX;
+ tx_port = PCM_TX;
+ } else if (dai->id == AFE_PORT_ID_SECONDARY_PCM_RX ||
+ dai->id == AFE_PORT_ID_SECONDARY_PCM_TX) {
+ rx_port = AFE_PORT_ID_SECONDARY_PCM_RX;
+ tx_port = AFE_PORT_ID_SECONDARY_PCM_TX;
+ }
+
+ rc = afe_set_lpass_clock(rx_port, lpass_pcm_src_clk);
if (rc < 0) {
pr_err("%s:afe_set_lpass_clock on RX pcm_src_clk failed\n",
__func__);
goto fail;
}
- rc = afe_set_lpass_clock(PCM_TX, lpass_pcm_src_clk);
+ rc = afe_set_lpass_clock(tx_port, lpass_pcm_src_clk);
if (rc < 0) {
pr_err("%s:afe_set_lpass_clock on TX pcm_src_clk failed\n",
__func__);
goto fail;
}
- rc = afe_set_lpass_clock(PCM_RX, &lpass_pcm_oe_clk);
+ rc = afe_set_lpass_clock(rx_port, &lpass_pcm_oe_clk);
if (rc < 0) {
pr_err("%s:afe_set_lpass_clock on pcm_oe_clk failed\n",
__func__);
goto fail;
}
- afe_open(PCM_RX, &dai_data->port_config, dai_data->rate);
-
- afe_open(PCM_TX, &dai_data->port_config, dai_data->rate);
+ afe_open(rx_port, &dai_data->port_config, dai_data->rate);
+ afe_open(tx_port, &dai_data->port_config, dai_data->rate);
fail:
mutex_unlock(&aux_pcm_mutex);
@@ -314,7 +337,7 @@
{
int rc = 0;
- pr_debug("%s:port:%d cmd:%d aux_pcm_count= %d",
+ pr_debug("%s:port:%d cmd:%d aux_pcm_count= %d\n",
__func__, dai->id, cmd, aux_pcm_count);
switch (cmd) {
@@ -359,7 +382,7 @@
} else
dev_set_drvdata(dai->dev, dai_data);
- pr_err("%s : probe done for dai->id %d\n", __func__, dai->id);
+ pr_debug("%s : probe done for dai->id %d\n", __func__, dai->id);
return rc;
}
@@ -367,6 +390,8 @@
{
struct msm_dai_q6_dai_data *dai_data;
int rc;
+ unsigned int rx_port = 0;
+ unsigned int tx_port = 0;
dai_data = dev_get_drvdata(dai->dev);
@@ -393,14 +418,22 @@
dev_dbg(dai->dev, "%s(): dai->id %d aux_pcm_count = %d.closing afe\n",
__func__, dai->id, aux_pcm_count);
- rc = afe_close(PCM_RX); /* can block */
+ if (dai->id == AFE_PORT_ID_PRIMARY_PCM_RX ||
+ dai->id == AFE_PORT_ID_PRIMARY_PCM_TX) {
+ rx_port = PCM_RX;
+ tx_port = PCM_TX;
+ } else if (dai->id == AFE_PORT_ID_SECONDARY_PCM_RX ||
+ dai->id == AFE_PORT_ID_SECONDARY_PCM_TX) {
+ rx_port = AFE_PORT_ID_SECONDARY_PCM_RX;
+ tx_port = AFE_PORT_ID_SECONDARY_PCM_TX;
+ }
+ rc = afe_close(rx_port); /* can block */
if (IS_ERR_VALUE(rc))
dev_err(dai->dev, "fail to close AUX PCM RX AFE port\n");
- rc = afe_close(PCM_TX);
+ rc = afe_close(tx_port);
if (IS_ERR_VALUE(rc))
dev_err(dai->dev, "fail to close AUX PCM TX AFE port\n");
-
done:
kfree(dai_data);
snd_soc_unregister_dai(dai->dev);
@@ -941,12 +974,13 @@
static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_rx_dai = {
.playback = {
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
- SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000,
+ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
.channels_min = 1,
.channels_max = 2,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
},
.ops = &msm_dai_q6_ops,
.probe = msm_dai_q6_dai_probe,
@@ -1084,10 +1118,12 @@
switch (id) {
case AFE_PORT_ID_PRIMARY_PCM_RX:
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
rc = snd_soc_register_dai(&pdev->dev,
&msm_dai_q6_aux_pcm_rx_dai);
break;
case AFE_PORT_ID_PRIMARY_PCM_TX:
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
rc = snd_soc_register_dai(&pdev->dev,
&msm_dai_q6_aux_pcm_tx_dai);
break;
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
new file mode 100644
index 0000000..b43c3bd
--- /dev/null
+++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.c
@@ -0,0 +1,707 @@
+/* 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/init.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/platform_device.h>
+#include <linux/bitops.h>
+#include <linux/mutex.h>
+#include <linux/of_device.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#include <sound/q6adm-v2.h>
+#include <sound/q6asm-v2.h>
+#include <sound/q6afe-v2.h>
+
+#include "msm-dolby-dap-config.h"
+
+/* dolby endp based parameters */
+struct dolby_dap_endp_params_s {
+ int device;
+ int device_ch_caps;
+ int dap_device;
+ int params_id[DOLBY_NUM_ENDP_DEPENDENT_PARAMS];
+ int params_len[DOLBY_NUM_ENDP_DEPENDENT_PARAMS];
+ int params_offset[DOLBY_NUM_ENDP_DEPENDENT_PARAMS];
+ int params_val[DOLBY_ENDDEP_PARAM_LENGTH];
+};
+
+const struct dolby_dap_endp_params_s
+ dolby_dap_endp_params[NUM_DOLBY_ENDP_DEVICE] = {
+ {EARPIECE, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {SPEAKER, 2, DOLBY_ENDP_INT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {WIRED_HEADSET, 2, DOLBY_ENDP_HEADPHONES,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {WIRED_HEADPHONE, 2, DOLBY_ENDP_HEADPHONES,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {BLUETOOTH_SCO, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {BLUETOOTH_SCO_HEADSET, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {BLUETOOTH_SCO_CARKIT, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {BLUETOOTH_A2DP, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {BLUETOOTH_A2DP_HEADPHONES, 2, DOLBY_ENDP_HEADPHONES,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {BLUETOOTH_A2DP_SPEAKER, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {AUX_DIGITAL, 2, DOLBY_ENDP_HDMI,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-640} },
+ {AUX_DIGITAL, 6, DOLBY_ENDP_HDMI,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-640} },
+ {AUX_DIGITAL, 8, DOLBY_ENDP_HDMI,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-640} },
+ {ANLG_DOCK_HEADSET, 2, DOLBY_ENDP_HEADPHONES,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {DGTL_DOCK_HEADSET, 2, DOLBY_ENDP_HEADPHONES,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {USB_ACCESSORY, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {USB_DEVICE, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {REMOTE_SUBMIX, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {ANC_HEADSET, 2, DOLBY_ENDP_HEADPHONES,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {ANC_HEADPHONE, 2, DOLBY_ENDP_HEADPHONES,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {PROXY, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {FM, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+ {FM_TX, 2, DOLBY_ENDP_EXT_SPEAKERS,
+ {DOLBY_PARAM_ID_DVLO}, {DOLBY_ENDDEP_PARAM_DVLO_LENGTH},
+ {DOLBY_ENDDEP_PARAM_DVLO_OFFSET}, {-320} },
+};
+
+/* dolby param ids to/from dsp */
+static uint32_t dolby_dap_params_id[ALL_DOLBY_PARAMS] = {
+ DOLBY_PARAM_ID_VDHE, DOLBY_PARAM_ID_VSPE, DOLBY_PARAM_ID_DSSF,
+ DOLBY_PARAM_ID_DVLI, DOLBY_PARAM_ID_DVLO, DOLBY_PARAM_ID_DVLE,
+ DOLBY_PARAM_ID_DVMC, DOLBY_PARAM_ID_DVME, DOLBY_PARAM_ID_IENB,
+ DOLBY_PARAM_ID_IEBF, DOLBY_PARAM_ID_IEON, DOLBY_PARAM_ID_DEON,
+ DOLBY_PARAM_ID_NGON, DOLBY_PARAM_ID_GEON, DOLBY_PARAM_ID_GENB,
+ DOLBY_PARAM_ID_GEBF, DOLBY_PARAM_ID_AONB, DOLBY_PARAM_ID_AOBF,
+ DOLBY_PARAM_ID_AOBG, DOLBY_PARAM_ID_AOON, DOLBY_PARAM_ID_ARNB,
+ DOLBY_PARAM_ID_ARBF, DOLBY_PARAM_ID_PLB, DOLBY_PARAM_ID_PLMD,
+ DOLBY_PARAM_ID_DHSB, DOLBY_PARAM_ID_DHRG, DOLBY_PARAM_ID_DSSB,
+ DOLBY_PARAM_ID_DSSA, DOLBY_PARAM_ID_DVLA, DOLBY_PARAM_ID_IEBT,
+ DOLBY_PARAM_ID_IEA, DOLBY_PARAM_ID_DEA, DOLBY_PARAM_ID_DED,
+ DOLBY_PARAM_ID_GEBG, DOLBY_PARAM_ID_AOCC, DOLBY_PARAM_ID_ARBI,
+ DOLBY_PARAM_ID_ARBL, DOLBY_PARAM_ID_ARBH, DOLBY_PARAM_ID_AROD,
+ DOLBY_PARAM_ID_ARTP, DOLBY_PARAM_ID_VMON, DOLBY_PARAM_ID_VMB,
+ DOLBY_PARAM_ID_VCNB, DOLBY_PARAM_ID_VCBF, DOLBY_PARAM_ID_PREG,
+ DOLBY_PARAM_ID_VEN, DOLBY_PARAM_ID_PSTG, DOLBY_COMMIT_ALL_TO_DSP,
+ DOLBY_COMMIT_TO_DSP, DOLBY_USE_CACHE, DOLBY_AUTO_ENDP,
+ DOLBY_AUTO_ENDDEP_PARAMS
+};
+
+/* modifed state: 0x00000000 - Not updated
+* > 0x00000000 && < 0x00010000
+* Updated and not commited to DSP
+* 0x00010001 - Updated and commited to DSP
+* > 0x00010001 - Modified the commited value
+*/
+static int dolby_dap_params_modified[MAX_DOLBY_PARAMS] = { 0 };
+/* param offset */
+static uint32_t dolby_dap_params_offset[MAX_DOLBY_PARAMS] = {
+ DOLBY_PARAM_VDHE_OFFSET, DOLBY_PARAM_VSPE_OFFSET,
+ DOLBY_PARAM_DSSF_OFFSET, DOLBY_PARAM_DVLI_OFFSET,
+ DOLBY_PARAM_DVLO_OFFSET, DOLBY_PARAM_DVLE_OFFSET,
+ DOLBY_PARAM_DVMC_OFFSET, DOLBY_PARAM_DVME_OFFSET,
+ DOLBY_PARAM_IENB_OFFSET, DOLBY_PARAM_IEBF_OFFSET,
+ DOLBY_PARAM_IEON_OFFSET, DOLBY_PARAM_DEON_OFFSET,
+ DOLBY_PARAM_NGON_OFFSET, DOLBY_PARAM_GEON_OFFSET,
+ DOLBY_PARAM_GENB_OFFSET, DOLBY_PARAM_GEBF_OFFSET,
+ DOLBY_PARAM_AONB_OFFSET, DOLBY_PARAM_AOBF_OFFSET,
+ DOLBY_PARAM_AOBG_OFFSET, DOLBY_PARAM_AOON_OFFSET,
+ DOLBY_PARAM_ARNB_OFFSET, DOLBY_PARAM_ARBF_OFFSET,
+ DOLBY_PARAM_PLB_OFFSET, DOLBY_PARAM_PLMD_OFFSET,
+ DOLBY_PARAM_DHSB_OFFSET, DOLBY_PARAM_DHRG_OFFSET,
+ DOLBY_PARAM_DSSB_OFFSET, DOLBY_PARAM_DSSA_OFFSET,
+ DOLBY_PARAM_DVLA_OFFSET, DOLBY_PARAM_IEBT_OFFSET,
+ DOLBY_PARAM_IEA_OFFSET, DOLBY_PARAM_DEA_OFFSET,
+ DOLBY_PARAM_DED_OFFSET, DOLBY_PARAM_GEBG_OFFSET,
+ DOLBY_PARAM_AOCC_OFFSET, DOLBY_PARAM_ARBI_OFFSET,
+ DOLBY_PARAM_ARBL_OFFSET, DOLBY_PARAM_ARBH_OFFSET,
+ DOLBY_PARAM_AROD_OFFSET, DOLBY_PARAM_ARTP_OFFSET,
+ DOLBY_PARAM_VMON_OFFSET, DOLBY_PARAM_VMB_OFFSET,
+ DOLBY_PARAM_VCNB_OFFSET, DOLBY_PARAM_VCBF_OFFSET,
+ DOLBY_PARAM_PREG_OFFSET, DOLBY_PARAM_VEN_OFFSET,
+ DOLBY_PARAM_PSTG_OFFSET
+};
+/* param_length */
+static uint32_t dolby_dap_params_length[MAX_DOLBY_PARAMS] = {
+ DOLBY_PARAM_VDHE_LENGTH, DOLBY_PARAM_VSPE_LENGTH,
+ DOLBY_PARAM_DSSF_LENGTH, DOLBY_PARAM_DVLI_LENGTH,
+ DOLBY_PARAM_DVLO_LENGTH, DOLBY_PARAM_DVLE_LENGTH,
+ DOLBY_PARAM_DVMC_LENGTH, DOLBY_PARAM_DVME_LENGTH,
+ DOLBY_PARAM_IENB_LENGTH, DOLBY_PARAM_IEBF_LENGTH,
+ DOLBY_PARAM_IEON_LENGTH, DOLBY_PARAM_DEON_LENGTH,
+ DOLBY_PARAM_NGON_LENGTH, DOLBY_PARAM_GEON_LENGTH,
+ DOLBY_PARAM_GENB_LENGTH, DOLBY_PARAM_GEBF_LENGTH,
+ DOLBY_PARAM_AONB_LENGTH, DOLBY_PARAM_AOBF_LENGTH,
+ DOLBY_PARAM_AOBG_LENGTH, DOLBY_PARAM_AOON_LENGTH,
+ DOLBY_PARAM_ARNB_LENGTH, DOLBY_PARAM_ARBF_LENGTH,
+ DOLBY_PARAM_PLB_LENGTH, DOLBY_PARAM_PLMD_LENGTH,
+ DOLBY_PARAM_DHSB_LENGTH, DOLBY_PARAM_DHRG_LENGTH,
+ DOLBY_PARAM_DSSB_LENGTH, DOLBY_PARAM_DSSA_LENGTH,
+ DOLBY_PARAM_DVLA_LENGTH, DOLBY_PARAM_IEBT_LENGTH,
+ DOLBY_PARAM_IEA_LENGTH, DOLBY_PARAM_DEA_LENGTH,
+ DOLBY_PARAM_DED_LENGTH, DOLBY_PARAM_GEBG_LENGTH,
+ DOLBY_PARAM_AOCC_LENGTH, DOLBY_PARAM_ARBI_LENGTH,
+ DOLBY_PARAM_ARBL_LENGTH, DOLBY_PARAM_ARBH_LENGTH,
+ DOLBY_PARAM_AROD_LENGTH, DOLBY_PARAM_ARTP_LENGTH,
+ DOLBY_PARAM_VMON_LENGTH, DOLBY_PARAM_VMB_LENGTH,
+ DOLBY_PARAM_VCNB_LENGTH, DOLBY_PARAM_VCBF_LENGTH,
+ DOLBY_PARAM_PREG_LENGTH, DOLBY_PARAM_VEN_LENGTH,
+ DOLBY_PARAM_PSTG_LENGTH
+};
+
+/* param_value */
+static uint32_t dolby_dap_params_value[TOTAL_LENGTH_DOLBY_PARAM] = {0};
+
+struct dolby_dap_params_get_s {
+ int32_t port_id;
+ uint32_t device_id;
+ uint32_t param_id;
+ uint32_t offset;
+ uint32_t length;
+};
+
+struct dolby_dap_params_states_s {
+ bool use_cache;
+ bool auto_endp;
+ bool enddep_params;
+ int port_id;
+ int port_open_count;
+ int port_ids_dolby_can_be_enabled;
+ int device;
+};
+
+static struct dolby_dap_params_get_s dolby_dap_params_get = {-1, DEVICE_OUT_ALL,
+ 0, 0, 0};
+static struct dolby_dap_params_states_s dolby_dap_params_states = { true, true,
+ true, DOLBY_INVALID_PORT_ID,
+ 0, DEVICE_OUT_ALL, 0 };
+/*
+port_ids_dolby_can_be_enabled is set to 0x7FFFFFFF.
+this needs to be removed after interface validation
+*/
+
+static int map_device_to_dolby_endpoint(int device)
+{
+ int i, dolby_dap_device = DOLBY_ENDP_INT_SPEAKERS;
+ for (i = 0; i < NUM_DOLBY_ENDP_DEVICE; i++) {
+ if (dolby_dap_endp_params[i].device == device) {
+ dolby_dap_device = dolby_dap_endp_params[i].dap_device;
+ break;
+ }
+ }
+ /* default the endpoint to speaker if corresponding device entry */
+ /* not found */
+ if (i >= NUM_DOLBY_ENDP_DEVICE)
+ dolby_dap_params_states.device = SPEAKER;
+ return dolby_dap_device;
+}
+
+static int dolby_dap_send_end_point(int port_id)
+{
+ int rc = 0;
+ char *params_value;
+ int *update_params_value;
+ uint32_t params_length = (DOLBY_PARAM_INT_ENDP_LENGTH +
+ DOLBY_PARAM_PAYLOAD_SIZE) * sizeof(uint32_t);
+
+ pr_debug("%s\n", __func__);
+ params_value = kzalloc(params_length, GFP_KERNEL);
+ if (!params_value) {
+ pr_err("%s, params memory alloc failed", __func__);
+ return -ENOMEM;
+ }
+ update_params_value = (int *)params_value;
+ *update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
+ *update_params_value++ = DOLBY_PARAM_ID_INIT_ENDP;
+ *update_params_value++ = DOLBY_PARAM_INT_ENDP_LENGTH * sizeof(uint32_t);
+ *update_params_value++ =
+ map_device_to_dolby_endpoint(dolby_dap_params_states.device);
+ rc = adm_dolby_dap_send_params(port_id, params_value, params_length);
+ if (rc) {
+ pr_err("%s: send dolby params failed\n", __func__);
+ rc = -EINVAL;
+ }
+ kfree(params_value);
+ return rc;
+}
+
+static int dolby_dap_send_enddep_params(int port_id, int device_channels)
+{
+ int i, j, rc = 0, idx, offset;
+ char *params_value;
+ int *update_params_value;
+ uint32_t params_length = (DOLBY_ENDDEP_PARAM_LENGTH +
+ DOLBY_NUM_ENDP_DEPENDENT_PARAMS *
+ DOLBY_PARAM_PAYLOAD_SIZE) *
+ sizeof(uint32_t);
+
+ pr_debug("%s\n", __func__);
+ params_value = kzalloc(params_length, GFP_KERNEL);
+ if (!params_value) {
+ pr_err("%s, params memory alloc failed", __func__);
+ return -ENOMEM;
+ }
+ update_params_value = (int *)params_value;
+ for (idx = 0; idx < NUM_DOLBY_ENDP_DEVICE; idx++) {
+ if (dolby_dap_endp_params[idx].device ==
+ dolby_dap_params_states.device) {
+ if (dolby_dap_params_states.device == AUX_DIGITAL) {
+ if (dolby_dap_endp_params[idx].device_ch_caps ==
+ device_channels)
+ break;
+ } else {
+ break;
+ }
+ }
+ }
+ if (idx >= NUM_DOLBY_ENDP_DEVICE) {
+ pr_err("%s: device is not set accordingly\n", __func__);
+ return -EINVAL;
+ }
+ for (i = 0; i < DOLBY_ENDDEP_PARAM_LENGTH; i++) {
+ *update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
+ *update_params_value++ =
+ dolby_dap_endp_params[idx].params_id[i];
+ *update_params_value++ =
+ dolby_dap_endp_params[idx].params_len[i] *
+ sizeof(uint32_t);
+ offset = dolby_dap_endp_params[idx].params_offset[i];
+ for (j = 0; j < dolby_dap_endp_params[idx].params_len[i]; j++)
+ *update_params_value++ =
+ dolby_dap_endp_params[idx].params_val[offset+j];
+ }
+ rc = adm_dolby_dap_send_params(port_id, params_value, params_length);
+ if (rc) {
+ pr_err("%s: send dolby params failed\n", __func__);
+ rc = -EINVAL;
+ }
+ kfree(params_value);
+ return rc;
+}
+
+static int dolby_dap_send_cached_params(int port_id, int commit)
+{
+ char *params_value;
+ int *update_params_value, rc = 0;
+ uint32_t index_offset, i, j;
+ uint32_t params_length = (TOTAL_LENGTH_DOLBY_PARAM +
+ MAX_DOLBY_PARAMS * DOLBY_PARAM_PAYLOAD_SIZE) *
+ sizeof(uint32_t);
+
+ params_value = kzalloc(params_length, GFP_KERNEL);
+ if (!params_value) {
+ pr_err("%s, params memory alloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ update_params_value = (int *)params_value;
+ params_length = 0;
+ for (i = 0; i < MAX_DOLBY_PARAMS; i++) {
+ if ((dolby_dap_params_modified[i] == 0) ||
+ ((commit) &&
+ ((dolby_dap_params_modified[i] & 0x00010000) &&
+ ((dolby_dap_params_modified[i] & 0x0000FFFF) <= 1))))
+ continue;
+ *update_params_value++ = DOLBY_BUNDLE_MODULE_ID;
+ *update_params_value++ = dolby_dap_params_id[i];
+ *update_params_value++ = dolby_dap_params_length[i] *
+ sizeof(uint32_t);
+ index_offset = dolby_dap_params_offset[i];
+ for (j = 0; j < dolby_dap_params_length[i]; j++)
+ *update_params_value++ =
+ dolby_dap_params_value[index_offset+j];
+ params_length += (DOLBY_PARAM_PAYLOAD_SIZE +
+ dolby_dap_params_length[i]) * sizeof(uint32_t);
+ }
+ pr_debug("%s, valid param length: %d", __func__, params_length);
+ if (params_length) {
+ rc = adm_dolby_dap_send_params(port_id, params_value,
+ params_length);
+ if (rc) {
+ pr_err("%s: send dolby params failed\n", __func__);
+ return -EINVAL;
+ }
+ for (i = 0; i < MAX_DOLBY_PARAMS; i++) {
+ if ((dolby_dap_params_modified[i] == 0) ||
+ ((commit) &&
+ ((dolby_dap_params_modified[i] & 0x00010000) &&
+ ((dolby_dap_params_modified[i] & 0x0000FFFF) <= 1))
+ ))
+ continue;
+ dolby_dap_params_modified[i] = 0x00010001;
+ }
+ }
+ kfree(params_value);
+ return 0;
+}
+
+int dolby_dap_init(int port_id, int channels)
+{
+ int ret = 0;
+ if ((port_id != DOLBY_INVALID_PORT_ID) &&
+ (port_id &
+ dolby_dap_params_states.port_ids_dolby_can_be_enabled)) {
+ dolby_dap_params_states.port_id = port_id;
+ dolby_dap_params_states.port_open_count++;
+ if (dolby_dap_params_states.auto_endp) {
+ ret = dolby_dap_send_end_point(port_id);
+ if (ret) {
+ pr_err("%s: err sending endppoint\n", __func__);
+ return ret;
+ }
+ }
+ if (dolby_dap_params_states.use_cache) {
+ ret = dolby_dap_send_cached_params(port_id, 0);
+ if (ret) {
+ pr_err("%s: err sending cached params\n",
+ __func__);
+ return ret;
+ }
+ }
+ if (dolby_dap_params_states.enddep_params) {
+ dolby_dap_send_enddep_params(port_id,
+ channels);
+ if (ret) {
+ pr_err("%s: err sending endp dependent params\n",
+ __func__);
+ return ret;
+ }
+ }
+ }
+ return ret;
+}
+
+void dolby_dap_deinit(int port_id)
+{
+ dolby_dap_params_states.port_open_count--;
+ if ((dolby_dap_params_states.port_id == port_id) &&
+ (!dolby_dap_params_states.port_open_count))
+ dolby_dap_params_states.port_id = DOLBY_INVALID_PORT_ID;
+}
+
+static int map_device_to_port_id(int device)
+{
+ int port_id = SLIMBUS_0_RX;
+ device = DEVICE_OUT_ALL;
+ /*update the device when single stream to multiple device is handled*/
+ if (device == DEVICE_OUT_ALL) {
+ port_id = PRIMARY_I2S_RX | SLIMBUS_0_RX | HDMI_RX |
+ INT_BT_SCO_RX | INT_FM_RX |
+ RT_PROXY_PORT_001_RX | PCM_RX |
+ MI2S_RX | SECONDARY_I2S_RX |
+ SLIMBUS_1_RX | SLIMBUS_4_RX | SLIMBUS_3_RX |
+ AFE_PORT_ID_SECONDARY_MI2S_RX;
+ } else {
+ /* update port_id based on the device */
+ }
+ return port_id;
+}
+
+int msm_routing_get_dolby_dap_param_to_set_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ /* not used while setting the parameters */
+ return 0;
+}
+
+int msm_routing_put_dolby_dap_param_to_set_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ int rc = 0;
+ uint32_t idx, j;
+ uint32_t device = ucontrol->value.integer.value[0];
+ uint32_t param_id = ucontrol->value.integer.value[1];
+ uint32_t offset = ucontrol->value.integer.value[2];
+ uint32_t length = ucontrol->value.integer.value[3];
+
+ int port_id = dolby_dap_params_states.port_id;
+
+ dolby_dap_params_states.port_ids_dolby_can_be_enabled =
+ map_device_to_port_id(device);
+ for (idx = 0; idx < ALL_DOLBY_PARAMS; idx++) {
+ /*paramid from user space*/
+ if (param_id == dolby_dap_params_id[idx])
+ break;
+ }
+ if (idx > ALL_DOLBY_PARAMS-1) {
+ pr_err("%s: invalid param id 0x%x to set\n", __func__,
+ param_id);
+ return -EINVAL;
+ }
+ switch (idx) {
+ case DOLBY_COMMIT_ALL_IDX: {
+ /* COMIIT ALL: Send all parameters to DSP */
+ pr_debug("%s: COMMIT_ALL recvd\n", __func__);
+ if (port_id != DOLBY_INVALID_PORT_ID)
+ rc = dolby_dap_send_cached_params(port_id, 0);
+ }
+ break;
+ case DOLBY_COMMIT_IDX: {
+ pr_debug("%s: COMMIT recvd\n", __func__);
+ /* COMMIT: Send only modified paramters to DSP */
+ if (port_id != DOLBY_INVALID_PORT_ID)
+ rc = dolby_dap_send_cached_params(port_id, 1);
+ }
+ break;
+ case DOLBY_USE_CACHE_IDX: {
+ pr_debug("%s: USE CACHE recvd val: %ld\n", __func__,
+ ucontrol->value.integer.value[4]);
+ dolby_dap_params_states.use_cache =
+ ucontrol->value.integer.value[4];
+ }
+ break;
+ case DOLBY_AUTO_ENDP_IDX: {
+ pr_debug("%s: AUTO_ENDP recvd val: %ld\n", __func__,
+ ucontrol->value.integer.value[4]);
+ dolby_dap_params_states.auto_endp =
+ ucontrol->value.integer.value[4];
+ }
+ break;
+ case DOLBY_AUTO_ENDDEP_IDX: {
+ pr_debug("%s: USE_ENDDEP_PARAMS recvd val: %ld\n",
+ __func__, ucontrol->value.integer.value[4]);
+ dolby_dap_params_states.enddep_params =
+ ucontrol->value.integer.value[4];
+ }
+ break;
+ default: {
+ /* cache the parameters */
+ dolby_dap_params_modified[idx] += 1;
+ dolby_dap_params_length[idx] = length;
+ pr_debug("%s: param recvd deviceId=0x%x paramId=0x%x offset=%d length=%d\n",
+ __func__, device, param_id, offset, length);
+ for (j = 0; j < length; j++) {
+ dolby_dap_params_value[
+ dolby_dap_params_offset[idx] +
+ offset + j]
+ = ucontrol->value.integer.value[4+j];
+ pr_debug("value[%d]: %ld\n", j,
+ ucontrol->value.integer.value[4+j]);
+ }
+ }
+ }
+
+ return rc;
+}
+
+int msm_routing_get_dolby_dap_param_to_get_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ int rc = 0, i;
+ char *params_value;
+ int *update_params_value;
+ uint32_t params_length = DOLBY_MAX_LENGTH_INDIVIDUAL_PARAM *
+ sizeof(uint32_t);
+ uint32_t param_payload_len =
+ DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t);
+ int port_id = dolby_dap_params_states.port_id;
+
+ if (port_id == DOLBY_INVALID_PORT_ID) {
+ pr_err("%s, port_id not set, returning error", __func__);
+ return -EINVAL;
+ }
+ params_value = kzalloc(params_length, GFP_KERNEL);
+ if (!params_value) {
+ pr_err("%s, params memory alloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ if (DOLBY_PARAM_ID_VER == dolby_dap_params_get.param_id) {
+ rc = adm_dolby_dap_get_params(dolby_dap_params_get.port_id,
+ DOLBY_BUNDLE_MODULE_ID,
+ DOLBY_PARAM_ID_VER,
+ params_length +
+ param_payload_len,
+ params_value);
+ } else {
+ for (i = 0; i < MAX_DOLBY_PARAMS; i++)
+ if (dolby_dap_params_id[i] ==
+ dolby_dap_params_get.param_id)
+ break;
+ if (i > MAX_DOLBY_PARAMS-1) {
+ pr_err("%s: invalid param id to set", __func__);
+ rc = -EINVAL;
+ } else {
+ params_length = (dolby_dap_params_length[i] +
+ DOLBY_PARAM_PAYLOAD_SIZE) *
+ sizeof(uint32_t);
+ rc = adm_dolby_dap_get_params(
+ dolby_dap_params_get.port_id,
+ DOLBY_BUNDLE_MODULE_ID,
+ dolby_dap_params_id[i],
+ params_length +
+ param_payload_len,
+ params_value);
+ }
+ }
+ if (rc) {
+ pr_err("%s: get parameters failed\n", __func__);
+ kfree(params_value);
+ rc = -EINVAL;
+ }
+ update_params_value = (int *)params_value;
+ ucontrol->value.integer.value[0] = dolby_dap_params_get.device_id;
+ ucontrol->value.integer.value[1] = dolby_dap_params_get.param_id;
+ ucontrol->value.integer.value[2] = dolby_dap_params_get.offset;
+ ucontrol->value.integer.value[3] = dolby_dap_params_get.length;
+
+ pr_debug("%s: FROM DSP value[0] 0x%x value[1] %d value[2] 0x%x\n",
+ __func__, update_params_value[0],
+ update_params_value[1], update_params_value[2]);
+ for (i = 0; i < dolby_dap_params_get.length; i++) {
+ ucontrol->value.integer.value[DOLBY_PARAM_PAYLOAD_SIZE+i] =
+ update_params_value[i];
+ pr_debug("value[%d]:%d\n", i, update_params_value[i]);
+ }
+ pr_debug("%s: Returning param_id=0x%x offset=%d length=%d\n",
+ __func__, dolby_dap_params_get.param_id,
+ dolby_dap_params_get.offset,
+ dolby_dap_params_get.length);
+ kfree(params_value);
+ return 0;
+}
+
+int msm_routing_put_dolby_dap_param_to_get_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ dolby_dap_params_get.device_id = ucontrol->value.integer.value[0];
+ dolby_dap_params_get.port_id =
+ (dolby_dap_params_get.device_id == DEVICE_OUT_ALL) ?
+ dolby_dap_params_states.port_id :
+ map_device_to_port_id(dolby_dap_params_get.device_id);
+ dolby_dap_params_get.param_id = ucontrol->value.integer.value[1];
+ dolby_dap_params_get.offset = ucontrol->value.integer.value[2];
+ dolby_dap_params_get.length = ucontrol->value.integer.value[3];
+ pr_debug("%s: param_id=0x%x offset=%d length=%d\n", __func__,
+ dolby_dap_params_get.param_id, dolby_dap_params_get.offset,
+ dolby_dap_params_get.length);
+ return 0;
+}
+
+int msm_routing_get_dolby_dap_param_visualizer_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ uint32_t length = dolby_dap_params_value[DOLBY_PARAM_VCNB_OFFSET];
+ char *visualizer_data;
+ int i, rc;
+ int *update_visualizer_data;
+ uint32_t offset, params_length =
+ (2*length + DOLBY_VIS_PARAM_HEADER_SIZE)*sizeof(uint32_t);
+ uint32_t param_payload_len =
+ DOLBY_PARAM_PAYLOAD_SIZE * sizeof(uint32_t);
+ int port_id = dolby_dap_params_states.port_id;
+ if (port_id == DOLBY_INVALID_PORT_ID) {
+ pr_err("%s, port_id not set, returning error", __func__);
+ ucontrol->value.integer.value[0] = 0;
+ return -EINVAL;
+ }
+ visualizer_data = kzalloc(params_length, GFP_KERNEL);
+ if (!visualizer_data) {
+ pr_err("%s, params memory alloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ offset = 0;
+ params_length = length * sizeof(uint32_t);
+ rc = adm_dolby_dap_get_params(dolby_dap_params_states.port_id,
+ DOLBY_BUNDLE_MODULE_ID,
+ DOLBY_PARAM_ID_VCBG,
+ params_length + param_payload_len,
+ visualizer_data + offset);
+ if (rc) {
+ pr_err("%s: get parameters failed\n", __func__);
+ kfree(visualizer_data);
+ return -EINVAL;
+ }
+
+ offset = length * sizeof(uint32_t);
+ rc = adm_dolby_dap_get_params(dolby_dap_params_states.port_id,
+ DOLBY_BUNDLE_MODULE_ID,
+ DOLBY_PARAM_ID_VCBE,
+ params_length + param_payload_len,
+ visualizer_data + offset);
+ if (rc) {
+ pr_err("%s: get parameters failed\n", __func__);
+ kfree(visualizer_data);
+ return -EINVAL;
+ }
+
+ ucontrol->value.integer.value[0] = 2*length;
+ pr_debug("%s: visualizer data length %ld\n", __func__,
+ ucontrol->value.integer.value[0]);
+ update_visualizer_data = (int *)visualizer_data;
+ for (i = 0; i < 2*length; i++) {
+ ucontrol->value.integer.value[1+i] = update_visualizer_data[i];
+ pr_debug("value[%d] %d\n", i, update_visualizer_data[i]);
+ }
+ kfree(visualizer_data);
+ return 0;
+}
+
+int msm_routing_put_dolby_dap_param_visualizer_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ /* not used while getting the visualizer data */
+ return 0;
+}
+
+int msm_routing_get_dolby_dap_endpoint_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ /* not used while setting the endpoint */
+ return 0;
+}
+
+int msm_routing_put_dolby_dap_endpoint_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ int device = ucontrol->value.integer.value[0];
+ dolby_dap_params_states.device = device;
+ return 0;
+}
diff --git a/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.h b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.h
new file mode 100644
index 0000000..58ea36d
--- /dev/null
+++ b/sound/soc/msm/qdsp6v2/msm-dolby-dap-config.h
@@ -0,0 +1,348 @@
+/* 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_DOLBY_DAP_CONFIG_H_
+#define _MSM_DOLBY_DAP_CONFIG_H_
+
+#ifdef CONFIG_DOLBY_DAP
+/* DOLBY DOLBY GUIDS */
+#define DOLBY_ADM_COPP_TOPOLOGY_ID 0x0001033B
+#define DOLBY_BUNDLE_MODULE_ID 0x00010723
+#define DOLBY_VISUALIZER_MODULE_ID 0x0001072B
+
+#define DOLBY_PARAM_ID_VDHE 0x0001074D
+#define DOLBY_PARAM_ID_VSPE 0x00010750
+#define DOLBY_PARAM_ID_DSSF 0x00010753
+#define DOLBY_PARAM_ID_DVLI 0x0001073E
+#define DOLBY_PARAM_ID_DVLO 0x0001073F
+#define DOLBY_PARAM_ID_DVLE 0x0001073C
+#define DOLBY_PARAM_ID_DVMC 0x00010741
+#define DOLBY_PARAM_ID_DVME 0x00010740
+#define DOLBY_PARAM_ID_IENB 0x00010744
+#define DOLBY_PARAM_ID_IEBF 0x00010745
+#define DOLBY_PARAM_ID_IEON 0x00010743
+#define DOLBY_PARAM_ID_DEON 0x00010738
+#define DOLBY_PARAM_ID_NGON 0x00010736
+#define DOLBY_PARAM_ID_GEON 0x00010748
+#define DOLBY_PARAM_ID_GENB 0x00010749
+#define DOLBY_PARAM_ID_GEBF 0x0001074A
+#define DOLBY_PARAM_ID_AONB 0x0001075B
+#define DOLBY_PARAM_ID_AOBF 0x0001075C
+#define DOLBY_PARAM_ID_AOBG 0x0001075D
+#define DOLBY_PARAM_ID_AOON 0x00010759
+#define DOLBY_PARAM_ID_ARNB 0x0001075F
+#define DOLBY_PARAM_ID_ARBF 0x00010760
+#define DOLBY_PARAM_ID_PLB 0x00010768
+#define DOLBY_PARAM_ID_PLMD 0x00010767
+#define DOLBY_PARAM_ID_DHSB 0x0001074E
+#define DOLBY_PARAM_ID_DHRG 0x0001074F
+#define DOLBY_PARAM_ID_DSSB 0x00010751
+#define DOLBY_PARAM_ID_DSSA 0x00010752
+#define DOLBY_PARAM_ID_DVLA 0x0001073D
+#define DOLBY_PARAM_ID_IEBT 0x00010746
+#define DOLBY_PARAM_ID_IEA 0x0001076A
+#define DOLBY_PARAM_ID_DEA 0x00010739
+#define DOLBY_PARAM_ID_DED 0x0001073A
+#define DOLBY_PARAM_ID_GEBG 0x0001074B
+#define DOLBY_PARAM_ID_AOCC 0x0001075A
+#define DOLBY_PARAM_ID_ARBI 0x00010761
+#define DOLBY_PARAM_ID_ARBL 0x00010762
+#define DOLBY_PARAM_ID_ARBH 0x00010763
+#define DOLBY_PARAM_ID_AROD 0x00010764
+#define DOLBY_PARAM_ID_ARTP 0x00010765
+#define DOLBY_PARAM_ID_VMON 0x00010756
+#define DOLBY_PARAM_ID_VMB 0x00010757
+#define DOLBY_PARAM_ID_VCNB 0x00010733
+#define DOLBY_PARAM_ID_VCBF 0x00010734
+#define DOLBY_PARAM_ID_PREG 0x00010728
+#define DOLBY_PARAM_ID_VEN 0x00010732
+#define DOLBY_PARAM_ID_PSTG 0x00010729
+#define DOLBY_PARAM_ID_INIT_ENDP 0x00010727
+
+/* Not Used with Set Param kcontrol, only to query using Get Param */
+#define DOLBY_PARAM_ID_VER 0x00010726
+
+#define DOLBY_PARAM_ID_VCBG 0x00010730
+#define DOLBY_PARAM_ID_VCBE 0x00010731
+
+/* DOLBY DAP control params */
+#define DOLBY_COMMIT_ALL_TO_DSP 0x70000001
+#define DOLBY_COMMIT_TO_DSP 0x70000002
+#define DOLBY_USE_CACHE 0x70000003
+#define DOLBY_AUTO_ENDP 0x70000004
+#define DOLBY_AUTO_ENDDEP_PARAMS 0x70000005
+
+/* DOLBY DAP offsets start */
+#define DOLBY_PARAM_VDHE_LENGTH 1
+#define DOLBY_PARAM_VDHE_OFFSET 0
+#define DOLBY_PARAM_VSPE_LENGTH 1
+#define DOLBY_PARAM_VSPE_OFFSET (DOLBY_PARAM_VDHE_OFFSET + \
+ DOLBY_PARAM_VDHE_LENGTH)
+#define DOLBY_PARAM_DSSF_LENGTH 1
+#define DOLBY_PARAM_DSSF_OFFSET (DOLBY_PARAM_VSPE_OFFSET + \
+ DOLBY_PARAM_VSPE_LENGTH)
+#define DOLBY_PARAM_DVLI_LENGTH 1
+#define DOLBY_PARAM_DVLI_OFFSET (DOLBY_PARAM_DSSF_OFFSET + \
+ DOLBY_PARAM_DSSF_LENGTH)
+#define DOLBY_PARAM_DVLO_LENGTH 1
+#define DOLBY_PARAM_DVLO_OFFSET (DOLBY_PARAM_DVLI_OFFSET + \
+ DOLBY_PARAM_DVLI_LENGTH)
+#define DOLBY_PARAM_DVLE_LENGTH 1
+#define DOLBY_PARAM_DVLE_OFFSET (DOLBY_PARAM_DVLO_OFFSET + \
+ DOLBY_PARAM_DVLO_LENGTH)
+#define DOLBY_PARAM_DVMC_LENGTH 1
+#define DOLBY_PARAM_DVMC_OFFSET (DOLBY_PARAM_DVLE_OFFSET + \
+ DOLBY_PARAM_DVLE_LENGTH)
+#define DOLBY_PARAM_DVME_LENGTH 1
+#define DOLBY_PARAM_DVME_OFFSET (DOLBY_PARAM_DVMC_OFFSET + \
+ DOLBY_PARAM_DVMC_LENGTH)
+#define DOLBY_PARAM_IENB_LENGTH 1
+#define DOLBY_PARAM_IENB_OFFSET (DOLBY_PARAM_DVME_OFFSET + \
+ DOLBY_PARAM_DVME_LENGTH)
+#define DOLBY_PARAM_IEBF_LENGTH 40
+#define DOLBY_PARAM_IEBF_OFFSET (DOLBY_PARAM_IENB_OFFSET + \
+ DOLBY_PARAM_IENB_LENGTH)
+#define DOLBY_PARAM_IEON_LENGTH 1
+#define DOLBY_PARAM_IEON_OFFSET (DOLBY_PARAM_IEBF_OFFSET + \
+ DOLBY_PARAM_IEBF_LENGTH)
+#define DOLBY_PARAM_DEON_LENGTH 1
+#define DOLBY_PARAM_DEON_OFFSET (DOLBY_PARAM_IEON_OFFSET + \
+ DOLBY_PARAM_IEON_LENGTH)
+#define DOLBY_PARAM_NGON_LENGTH 1
+#define DOLBY_PARAM_NGON_OFFSET (DOLBY_PARAM_DEON_OFFSET + \
+ DOLBY_PARAM_DEON_LENGTH)
+#define DOLBY_PARAM_GEON_LENGTH 1
+#define DOLBY_PARAM_GEON_OFFSET (DOLBY_PARAM_NGON_OFFSET + \
+ DOLBY_PARAM_NGON_LENGTH)
+#define DOLBY_PARAM_GENB_LENGTH 1
+#define DOLBY_PARAM_GENB_OFFSET (DOLBY_PARAM_GEON_OFFSET + \
+ DOLBY_PARAM_GEON_LENGTH)
+#define DOLBY_PARAM_GEBF_LENGTH 40
+#define DOLBY_PARAM_GEBF_OFFSET (DOLBY_PARAM_GENB_OFFSET + \
+ DOLBY_PARAM_GENB_LENGTH)
+#define DOLBY_PARAM_AONB_LENGTH 1
+#define DOLBY_PARAM_AONB_OFFSET (DOLBY_PARAM_GEBF_OFFSET + \
+ DOLBY_PARAM_GEBF_LENGTH)
+#define DOLBY_PARAM_AOBF_LENGTH 40
+#define DOLBY_PARAM_AOBF_OFFSET (DOLBY_PARAM_AONB_OFFSET + \
+ DOLBY_PARAM_AONB_LENGTH)
+#define DOLBY_PARAM_AOBG_LENGTH 329
+#define DOLBY_PARAM_AOBG_OFFSET (DOLBY_PARAM_AOBF_OFFSET + \
+ DOLBY_PARAM_AOBF_LENGTH)
+#define DOLBY_PARAM_AOON_LENGTH 1
+#define DOLBY_PARAM_AOON_OFFSET (DOLBY_PARAM_AOBG_OFFSET + \
+ DOLBY_PARAM_AOBG_LENGTH)
+#define DOLBY_PARAM_ARNB_LENGTH 1
+#define DOLBY_PARAM_ARNB_OFFSET (DOLBY_PARAM_AOON_OFFSET + \
+ DOLBY_PARAM_AOON_LENGTH)
+#define DOLBY_PARAM_ARBF_LENGTH 40
+#define DOLBY_PARAM_ARBF_OFFSET (DOLBY_PARAM_ARNB_OFFSET + \
+ DOLBY_PARAM_ARNB_LENGTH)
+#define DOLBY_PARAM_PLB_LENGTH 1
+#define DOLBY_PARAM_PLB_OFFSET (DOLBY_PARAM_ARBF_OFFSET + \
+ DOLBY_PARAM_ARBF_LENGTH)
+#define DOLBY_PARAM_PLMD_LENGTH 1
+#define DOLBY_PARAM_PLMD_OFFSET (DOLBY_PARAM_PLB_OFFSET + \
+ DOLBY_PARAM_PLB_LENGTH)
+#define DOLBY_PARAM_DHSB_LENGTH 1
+#define DOLBY_PARAM_DHSB_OFFSET (DOLBY_PARAM_PLMD_OFFSET + \
+ DOLBY_PARAM_PLMD_LENGTH)
+#define DOLBY_PARAM_DHRG_LENGTH 1
+#define DOLBY_PARAM_DHRG_OFFSET (DOLBY_PARAM_DHSB_OFFSET + \
+ DOLBY_PARAM_DHSB_LENGTH)
+#define DOLBY_PARAM_DSSB_LENGTH 1
+#define DOLBY_PARAM_DSSB_OFFSET (DOLBY_PARAM_DHRG_OFFSET + \
+ DOLBY_PARAM_DHRG_LENGTH)
+#define DOLBY_PARAM_DSSA_LENGTH 1
+#define DOLBY_PARAM_DSSA_OFFSET (DOLBY_PARAM_DSSB_OFFSET + \
+ DOLBY_PARAM_DSSB_LENGTH)
+#define DOLBY_PARAM_DVLA_LENGTH 1
+#define DOLBY_PARAM_DVLA_OFFSET (DOLBY_PARAM_DSSA_OFFSET + \
+ DOLBY_PARAM_DSSA_LENGTH)
+#define DOLBY_PARAM_IEBT_LENGTH 40
+#define DOLBY_PARAM_IEBT_OFFSET (DOLBY_PARAM_DVLA_OFFSET + \
+ DOLBY_PARAM_DVLA_LENGTH)
+#define DOLBY_PARAM_IEA_LENGTH 1
+#define DOLBY_PARAM_IEA_OFFSET (DOLBY_PARAM_IEBT_OFFSET + \
+ DOLBY_PARAM_IEBT_LENGTH)
+#define DOLBY_PARAM_DEA_LENGTH 1
+#define DOLBY_PARAM_DEA_OFFSET (DOLBY_PARAM_IEA_OFFSET + \
+ DOLBY_PARAM_IEA_LENGTH)
+#define DOLBY_PARAM_DED_LENGTH 1
+#define DOLBY_PARAM_DED_OFFSET (DOLBY_PARAM_DEA_OFFSET + \
+ DOLBY_PARAM_DEA_LENGTH)
+#define DOLBY_PARAM_GEBG_LENGTH 40
+#define DOLBY_PARAM_GEBG_OFFSET (DOLBY_PARAM_DED_OFFSET + \
+ DOLBY_PARAM_DED_LENGTH)
+#define DOLBY_PARAM_AOCC_LENGTH 1
+#define DOLBY_PARAM_AOCC_OFFSET (DOLBY_PARAM_GEBG_OFFSET + \
+ DOLBY_PARAM_GEBG_LENGTH)
+#define DOLBY_PARAM_ARBI_LENGTH 40
+#define DOLBY_PARAM_ARBI_OFFSET (DOLBY_PARAM_AOCC_OFFSET + \
+ DOLBY_PARAM_AOCC_LENGTH)
+#define DOLBY_PARAM_ARBL_LENGTH 40
+#define DOLBY_PARAM_ARBL_OFFSET (DOLBY_PARAM_ARBI_OFFSET + \
+ DOLBY_PARAM_ARBI_LENGTH)
+#define DOLBY_PARAM_ARBH_LENGTH 40
+#define DOLBY_PARAM_ARBH_OFFSET (DOLBY_PARAM_ARBL_OFFSET + \
+ DOLBY_PARAM_ARBL_LENGTH)
+#define DOLBY_PARAM_AROD_LENGTH 1
+#define DOLBY_PARAM_AROD_OFFSET (DOLBY_PARAM_ARBH_OFFSET + \
+ DOLBY_PARAM_ARBH_LENGTH)
+#define DOLBY_PARAM_ARTP_LENGTH 1
+#define DOLBY_PARAM_ARTP_OFFSET (DOLBY_PARAM_AROD_OFFSET + \
+ DOLBY_PARAM_AROD_LENGTH)
+#define DOLBY_PARAM_VMON_LENGTH 1
+#define DOLBY_PARAM_VMON_OFFSET (DOLBY_PARAM_ARTP_OFFSET + \
+ DOLBY_PARAM_ARTP_LENGTH)
+#define DOLBY_PARAM_VMB_LENGTH 1
+#define DOLBY_PARAM_VMB_OFFSET (DOLBY_PARAM_VMON_OFFSET + \
+ DOLBY_PARAM_VMON_LENGTH)
+#define DOLBY_PARAM_VCNB_LENGTH 1
+#define DOLBY_PARAM_VCNB_OFFSET (DOLBY_PARAM_VMB_OFFSET + \
+ DOLBY_PARAM_VMB_LENGTH)
+#define DOLBY_PARAM_VCBF_LENGTH 20
+#define DOLBY_PARAM_VCBF_OFFSET (DOLBY_PARAM_VCNB_OFFSET + \
+ DOLBY_PARAM_VCNB_LENGTH)
+#define DOLBY_PARAM_PREG_LENGTH 1
+#define DOLBY_PARAM_PREG_OFFSET (DOLBY_PARAM_VCBF_OFFSET + \
+ DOLBY_PARAM_VCBF_LENGTH)
+#define DOLBY_PARAM_VEN_LENGTH 1
+#define DOLBY_PARAM_VEN_OFFSET (DOLBY_PARAM_PREG_OFFSET + \
+ DOLBY_PARAM_PREG_LENGTH)
+#define DOLBY_PARAM_PSTG_LENGTH 1
+#define DOLBY_PARAM_PSTG_OFFSET (DOLBY_PARAM_VEN_OFFSET + \
+ DOLBY_PARAM_VEN_LENGTH)
+
+#define DOLBY_PARAM_INT_ENDP_LENGTH 1
+#define DOLBY_PARAM_PAYLOAD_SIZE 4
+#define DOLBY_MAX_LENGTH_INDIVIDUAL_PARAM 329
+
+#define DOLBY_NUM_ENDP_DEPENDENT_PARAMS 1
+#define DOLBY_ENDDEP_PARAM_DVLO_OFFSET 0
+#define DOLBY_ENDDEP_PARAM_DVLO_LENGTH 1
+#define DOLBY_ENDDEP_PARAM_LENGTH DOLBY_ENDDEP_PARAM_DVLO_LENGTH
+
+#define MAX_DOLBY_PARAMS 47
+#define MAX_DOLBY_CTRL_PARAMS 5
+#define ALL_DOLBY_PARAMS (MAX_DOLBY_PARAMS + \
+ MAX_DOLBY_CTRL_PARAMS)
+#define DOLBY_COMMIT_ALL_IDX MAX_DOLBY_PARAMS
+#define DOLBY_COMMIT_IDX (MAX_DOLBY_PARAMS+1)
+#define DOLBY_USE_CACHE_IDX (MAX_DOLBY_PARAMS+2)
+#define DOLBY_AUTO_ENDP_IDX (MAX_DOLBY_PARAMS+3)
+#define DOLBY_AUTO_ENDDEP_IDX (MAX_DOLBY_PARAMS+4)
+
+#define TOTAL_LENGTH_DOLBY_PARAM 745
+#define NUM_DOLBY_ENDP_DEVICE 23
+#define DOLBY_VIS_PARAM_HEADER_SIZE 25
+
+#define DOLBY_INVALID_PORT_ID -1
+/* DOLBY device definitions */
+enum {
+ DOLBY_ENDP_INT_SPEAKERS = 0,
+ DOLBY_ENDP_EXT_SPEAKERS,
+ DOLBY_ENDP_HEADPHONES,
+ DOLBY_ENDP_HDMI,
+ DOLBY_ENDP_SPDIF,
+ DOLBY_ENDP_DLNA,
+ DOLBY_ENDP_ANALOG,
+};
+
+enum {
+ DEVICE_NONE = 0x0,
+ /* output devices */
+ EARPIECE = 0x1,
+ SPEAKER = 0x2,
+ WIRED_HEADSET = 0x4,
+ WIRED_HEADPHONE = 0x8,
+ BLUETOOTH_SCO = 0x10,
+ BLUETOOTH_SCO_HEADSET = 0x20,
+ BLUETOOTH_SCO_CARKIT = 0x40,
+ BLUETOOTH_A2DP = 0x80,
+ BLUETOOTH_A2DP_HEADPHONES = 0x100,
+ BLUETOOTH_A2DP_SPEAKER = 0x200,
+ AUX_DIGITAL = 0x400,
+ ANLG_DOCK_HEADSET = 0x800,
+ DGTL_DOCK_HEADSET = 0x1000,
+ USB_ACCESSORY = 0x2000,
+ USB_DEVICE = 0x4000,
+ REMOTE_SUBMIX = 0x8000,
+ ANC_HEADSET = 0x10000,
+ ANC_HEADPHONE = 0x20000,
+ PROXY = 0x40000,
+ FM = 0x80000,
+ FM_TX = 0x100000,
+ DEVICE_OUT_ALL = 0x7FFFFFFF,
+};
+/* DOLBY device definitions end */
+
+struct dolby_dap_params {
+ uint32_t value[TOTAL_LENGTH_DOLBY_PARAM + MAX_DOLBY_PARAMS];
+} __packed;
+int dolby_dap_init(int port_id, int channels);
+int msm_routing_get_dolby_dap_param_to_set_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int msm_routing_put_dolby_dap_param_to_set_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int msm_routing_get_dolby_dap_param_to_get_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int msm_routing_put_dolby_dap_param_to_get_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int msm_routing_get_dolby_dap_param_visualizer_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int msm_routing_put_dolby_dap_param_visualizer_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int msm_routing_get_dolby_dap_endpoint_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+int msm_routing_put_dolby_dap_endpoint_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol);
+void dolby_dap_deinit(int port_id);
+/* Dolby DOLBY end */
+#else
+int dolby_dap_init(int port_id, int channels) { return 0; }
+int msm_routing_get_dolby_dap_param_to_set_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_put_dolby_dap_param_to_set_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_get_dolby_dap_param_to_get_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_put_dolby_dap_param_to_get_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_get_dolby_dap_param_visualizer_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_put_dolby_dap_param_visualizer_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_get_dolby_dap_endpoint_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) { return 0; }
+int msm_routing_put_dolby_dap_endpoint_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) { return 0; }
+void dolby_dap_deinit(int port_id) { return; }
+#endif
+
+#endif
+
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
index e4f3f94..96ddcf6 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
@@ -30,7 +30,6 @@
#include <sound/q6adm-v2.h>
#include <asm/dma.h>
#include <linux/memory_alloc.h>
-#include <mach/msm_subsystem_map.h>
#include "msm-pcm-afe-v2.h"
#define MIN_PERIOD_SIZE (128 * 2)
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
index 64f19ad..c8de460 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-lpa-v2.c
@@ -349,7 +349,7 @@
atomic_set(&lpa_audio.audio_ocmem_req, 0);
runtime->private_data = prtd;
lpa_audio.prtd = prtd;
- lpa_set_volume(lpa_audio.volume);
+ lpa_set_volume(0);
ret = q6asm_set_softpause(lpa_audio.prtd->audio_client, &softpause);
if (ret < 0)
pr_err("%s: Send SoftPause Param failed ret=%d\n",
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index ca91fe5..717e63b 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -82,9 +82,9 @@
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
- .rates = SNDRV_PCM_RATE_8000_96000,
+ .rates = SNDRV_PCM_RATE_8000_192000,
.rate_min = 8000,
- .rate_max = 96000,
+ .rate_max = 192000,
.channels_min = 1,
.channels_max = 8,
.buffer_bytes_max = PLAYBACK_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
@@ -98,7 +98,7 @@
/* Conventional and unconventional sample rate supported */
static unsigned int supported_sample_rates[] = {
8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
- 96000
+ 96000, 192000
};
static uint32_t in_frame_info[CAPTURE_NUM_PERIODS][2];
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index d8f2759..8257023 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -10,7 +10,6 @@
* GNU General Public License for more details.
*/
-
#include <linux/init.h>
#include <linux/err.h>
#include <linux/module.h>
@@ -31,8 +30,10 @@
#include <sound/tlv.h>
#include <sound/asound.h>
#include <sound/pcm_params.h>
+#include <mach/qdsp6v2/q6core.h>
#include "msm-pcm-routing-v2.h"
+#include "msm-dolby-dap-config.h"
#include "q6voice.h"
struct msm_pcm_routing_bdai_data {
@@ -185,6 +186,20 @@
(void *)&msm_srs_trumedia_params[param_block_idx].srs_params.global);
}
+int get_topology(int path_type)
+{
+ int topology_id = 0;
+ if (path_type == ADM_PATH_PLAYBACK)
+ topology_id = get_adm_rx_topology();
+ else
+ topology_id = get_adm_tx_topology();
+
+ if (topology_id == 0)
+ topology_id = DEFAULT_COPP_TOPOLOGY;
+
+ return topology_id;
+}
+
#define SLIMBUS_EXTPROC_RX AFE_PORT_INVALID
static struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
{ PRIMARY_I2S_RX, 0, 0, 0, 0, 0},
@@ -225,6 +240,8 @@
{ AFE_PORT_ID_TERTIARY_MI2S_RX, 0, 0, 0, 0, 0},
{ AFE_PORT_ID_TERTIARY_MI2S_TX, 0, 0, 0, 0, 0},
{ AUDIO_PORT_ID_I2S_RX, 0, 0, 0, 0, 0},
+ { AFE_PORT_ID_SECONDARY_PCM_RX, 0, 0, 0, 0, 0},
+ { AFE_PORT_ID_SECONDARY_PCM_TX, 0, 0, 0, 0, 0},
};
@@ -318,7 +335,7 @@
void msm_pcm_routing_reg_phy_stream(int fedai_id, bool perf_mode,
int dspst_id, int stream_type)
{
- int i, session_type, path_type, port_type;
+ int i, session_type, path_type, port_type, port_id, topology;
struct route_payload payload;
u32 channels;
uint16_t bits_per_sample = 16;
@@ -346,6 +363,7 @@
/* re-enable EQ if active */
if (eq_data[fedai_id].enable)
msm_send_eq_values(fedai_id);
+ topology = get_topology(path_type);
for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
if (test_bit(fedai_id, &msm_bedais[i].fe_sessions))
msm_bedais[i].perf_mode = perf_mode;
@@ -361,27 +379,31 @@
else if (msm_bedais[i].format ==
SNDRV_PCM_FORMAT_S24_LE)
bits_per_sample = 24;
-
if ((stream_type == SNDRV_PCM_STREAM_PLAYBACK) &&
(channels > 0))
adm_multi_ch_copp_open(msm_bedais[i].port_id,
path_type,
msm_bedais[i].sample_rate,
msm_bedais[i].channel,
- DEFAULT_COPP_TOPOLOGY, msm_bedais[i].perf_mode,
+ topology, msm_bedais[i].perf_mode,
bits_per_sample);
else
adm_open(msm_bedais[i].port_id,
path_type,
msm_bedais[i].sample_rate,
msm_bedais[i].channel,
- DEFAULT_COPP_TOPOLOGY, false,
+ topology, false,
bits_per_sample);
payload.copp_ids[payload.num_copps++] =
msm_bedais[i].port_id;
- srs_port_id = msm_bedais[i].port_id;
+ port_id = srs_port_id = msm_bedais[i].port_id;
srs_send_params(srs_port_id, 1, 0);
+ if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ if (dolby_dap_init(port_id,
+ msm_bedais[i].channel) < 0)
+ pr_err("%s: Err init dolby dap\n",
+ __func__);
}
}
if (payload.num_copps)
@@ -393,7 +415,7 @@
void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type)
{
- int i, port_type, session_type;
+ int i, port_type, session_type, path_type, topology;
if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
/* bad ID assigned in machine driver */
@@ -404,19 +426,24 @@
if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
port_type = MSM_AFE_PORT_TYPE_RX;
session_type = SESSION_TYPE_RX;
+ path_type = ADM_PATH_PLAYBACK;
} else {
port_type = MSM_AFE_PORT_TYPE_TX;
session_type = SESSION_TYPE_TX;
+ path_type = ADM_PATH_LIVE_REC;
}
mutex_lock(&routing_lock);
-
+ topology = get_topology(path_type);
for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
if (!is_be_dai_extproc(i) &&
(afe_get_port_type(msm_bedais[i].port_id) == port_type) &&
(msm_bedais[i].active) &&
- (test_bit(fedai_id, &msm_bedais[i].fe_sessions)))
+ (test_bit(fedai_id, &msm_bedais[i].fe_sessions))) {
adm_close(msm_bedais[i].port_id);
+ if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ dolby_dap_deinit(msm_bedais[i].port_id);
+ }
}
fe_dai_map[fedai_id][session_type] = INVALID_SESSION;
@@ -443,7 +470,7 @@
static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
{
- int session_type, path_type;
+ int session_type, path_type, port_id, topology;
u32 channels;
uint16_t bits_per_sample = 16;
@@ -465,7 +492,7 @@
}
mutex_lock(&routing_lock);
-
+ topology = get_topology(path_type);
if (set) {
if (!test_bit(val, &msm_bedais[reg].fe_sessions) &&
(msm_bedais[reg].port_id == VOICE_PLAYBACK_TX))
@@ -484,19 +511,23 @@
path_type,
msm_bedais[reg].sample_rate,
channels,
- DEFAULT_COPP_TOPOLOGY,
+ topology,
msm_bedais[reg].perf_mode,
bits_per_sample);
} else
adm_open(msm_bedais[reg].port_id,
path_type,
msm_bedais[reg].sample_rate, channels,
- DEFAULT_COPP_TOPOLOGY, false, bits_per_sample);
+ topology, false, bits_per_sample);
msm_pcm_routing_build_matrix(val,
fe_dai_map[val][session_type], path_type);
- srs_port_id = msm_bedais[reg].port_id;
+ port_id = srs_port_id = msm_bedais[reg].port_id;
srs_send_params(srs_port_id, 1, 0);
+ if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ if (dolby_dap_init(port_id, channels) < 0)
+ pr_err("%s: Err init dolby dap\n",
+ __func__);
}
} else {
if (test_bit(val, &msm_bedais[reg].fe_sessions) &&
@@ -506,6 +537,8 @@
if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
INVALID_SESSION) {
adm_close(msm_bedais[reg].port_id);
+ if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ dolby_dap_deinit(msm_bedais[reg].port_id);
msm_pcm_routing_build_matrix(val,
fe_dai_map[val][session_type], path_type);
}
@@ -1513,6 +1546,24 @@
msm_routing_put_audio_mixer),
};
+static const struct snd_kcontrol_new sec_auxpcm_rx_mixer_controls[] = {
+ SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+};
+
static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
SOC_SINGLE_EXT("PRI_TX", MSM_BACKEND_DAI_PRI_I2S_TX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -1532,6 +1583,9 @@
SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_AUXPCM_TX,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA1, 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_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
@@ -1583,6 +1637,9 @@
SOC_SINGLE_EXT("AUX_PCM_TX", MSM_BACKEND_DAI_AUXPCM_TX,
MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("SEC_AUX_PCM_TX", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = {
@@ -1723,6 +1780,24 @@
msm_routing_put_voice_mixer),
};
+static const struct snd_kcontrol_new sec_aux_pcm_rx_voice_mixer_controls[] = {
+ SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("DTMF", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_FRONTEND_DAI_DTMF_RX, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
+};
+
static const struct snd_kcontrol_new hdmi_rx_voice_mixer_controls[] = {
SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_HDMI_RX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
@@ -1781,6 +1856,9 @@
SOC_SINGLE_EXT("AUX_PCM_TX_Voice", MSM_BACKEND_DAI_AUXPCM_TX,
MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("SEC_AUX_PCM_TX_Voice", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new tx_voice2_mixer_controls[] = {
@@ -1820,6 +1898,9 @@
SOC_SINGLE_EXT("AUX_PCM_TX_VoLTE", MSM_BACKEND_DAI_AUXPCM_TX,
MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("SEC_AUX_PCM_TX_VoLTE", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
SOC_SINGLE_EXT("MI2S_TX_VoLTE", MSM_BACKEND_DAI_MI2S_TX,
MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
@@ -1844,6 +1925,9 @@
SOC_SINGLE_EXT("AUX_PCM_TX_Voip", MSM_BACKEND_DAI_AUXPCM_TX,
MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("SEC_AUX_PCM_TX_Voip", MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
+ msm_routing_put_voice_mixer),
};
static const struct snd_kcontrol_new tx_voice_stub_mixer_controls[] = {
@@ -1874,6 +1958,9 @@
SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
+ SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
MSM_BACKEND_DAI_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
@@ -1888,6 +1975,15 @@
msm_routing_put_port_mixer),
};
+static const struct snd_kcontrol_new sec_auxpcm_rx_port_mixer_controls[] = {
+ SOC_SINGLE_EXT("SEC_AUX_PCM_UL_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
+ SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
+};
+
static const struct snd_kcontrol_new sbus_1_rx_port_mixer_controls[] = {
SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_SLIMBUS_1_RX,
MSM_BACKEND_DAI_INT_BT_SCO_TX, 1, 0, msm_routing_get_port_mixer,
@@ -2090,6 +2186,51 @@
}
};
+int msm_routing_get_dolby_security_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ /* not used while setting the manfr id*/
+ return 0;
+}
+
+int msm_routing_put_dolby_security_control(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol) {
+ int manufacturer_id = ucontrol->value.integer.value[0];
+ core_set_dolby_manufacturer_id(manufacturer_id);
+ return 0;
+}
+
+static const struct snd_kcontrol_new dolby_security_controls[] = {
+ SOC_SINGLE_MULTI_EXT("DS1 Security", SND_SOC_NOPM, 0,
+ 0xFFFFFFFF, 0, 1, msm_routing_get_dolby_security_control,
+ msm_routing_put_dolby_security_control),
+};
+
+static const struct snd_kcontrol_new dolby_dap_param_to_set_controls[] = {
+ SOC_SINGLE_MULTI_EXT("DS1 DAP Set Param", SND_SOC_NOPM, 0, 0xFFFFFFFF,
+ 0, 128, msm_routing_get_dolby_dap_param_to_set_control,
+ msm_routing_put_dolby_dap_param_to_set_control),
+};
+
+static const struct snd_kcontrol_new dolby_dap_param_to_get_controls[] = {
+ SOC_SINGLE_MULTI_EXT("DS1 DAP Get Param", SND_SOC_NOPM, 0, 0xFFFFFFFF,
+ 0, 128, msm_routing_get_dolby_dap_param_to_get_control,
+ msm_routing_put_dolby_dap_param_to_get_control),
+};
+
+static const struct snd_kcontrol_new dolby_dap_param_visualizer_controls[] = {
+ SOC_SINGLE_MULTI_EXT("DS1 DAP Get Visualizer", SND_SOC_NOPM, 0,
+ 0xFFFFFFFF, 0, 41, msm_routing_get_dolby_dap_param_visualizer_control,
+ msm_routing_put_dolby_dap_param_visualizer_control),
+};
+
+static const struct snd_kcontrol_new dolby_dap_param_end_point_controls[] = {
+ SOC_SINGLE_MULTI_EXT("DS1 DAP Endpoint", SND_SOC_NOPM, 0,
+ 0xFFFFFFFF, 0, 1, msm_routing_get_dolby_dap_endpoint_control,
+ msm_routing_put_dolby_dap_endpoint_control),
+};
+
static const struct snd_kcontrol_new eq_enable_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia1 EQ Enable", SND_SOC_NOPM,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_eq_enable_mixer,
@@ -2425,6 +2566,10 @@
SND_SOC_DAPM_AIF_OUT("AUX_PCM_RX", "AUX PCM Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("AUX_PCM_TX", "AUX PCM Capture", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("SEC_AUX_PCM_RX", "Sec AUX PCM Playback",
+ 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("SEC_AUX_PCM_TX", "Sec AUX PCM Capture",
+ 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("VOICE_STUB_DL", "VOICE_STUB Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("VOICE_STUB_UL", "VOICE_STUB Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("STUB_RX", "Stub Playback", 0, 0, 0, 0),
@@ -2480,6 +2625,8 @@
mmul5_mixer_controls, ARRAY_SIZE(mmul5_mixer_controls)),
SND_SOC_DAPM_MIXER("AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
auxpcm_rx_mixer_controls, ARRAY_SIZE(auxpcm_rx_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SEC_AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
+ sec_auxpcm_rx_mixer_controls, ARRAY_SIZE(sec_auxpcm_rx_mixer_controls)),
/* incall */
SND_SOC_DAPM_MIXER("Incall_Music Audio Mixer", SND_SOC_NOPM, 0, 0,
incall_music_delivery_mixer_controls,
@@ -2511,6 +2658,10 @@
SND_SOC_NOPM, 0, 0,
aux_pcm_rx_voice_mixer_controls,
ARRAY_SIZE(aux_pcm_rx_voice_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SEC_AUX_PCM_RX_Voice Mixer",
+ SND_SOC_NOPM, 0, 0,
+ sec_aux_pcm_rx_voice_mixer_controls,
+ ARRAY_SIZE(sec_aux_pcm_rx_voice_mixer_controls)),
SND_SOC_DAPM_MIXER("HDMI_RX_Voice Mixer",
SND_SOC_NOPM, 0, 0,
hdmi_rx_voice_mixer_controls,
@@ -2551,6 +2702,9 @@
SND_SOC_DAPM_MIXER("AUXPCM_RX Port Mixer",
SND_SOC_NOPM, 0, 0, auxpcm_rx_port_mixer_controls,
ARRAY_SIZE(auxpcm_rx_port_mixer_controls)),
+ SND_SOC_DAPM_MIXER("SEC_AUXPCM_RX Port Mixer",
+ SND_SOC_NOPM, 0, 0, sec_auxpcm_rx_port_mixer_controls,
+ ARRAY_SIZE(sec_auxpcm_rx_port_mixer_controls)),
SND_SOC_DAPM_MIXER("SLIMBUS_1_RX Port Mixer", SND_SOC_NOPM, 0, 0,
sbus_1_rx_port_mixer_controls,
ARRAY_SIZE(sbus_1_rx_port_mixer_controls)),
@@ -2657,6 +2811,8 @@
{"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
{"MultiMedia5 Mixer", "AUX_PCM_TX", "AUX_PCM_TX"},
+ {"MultiMedia1 Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
+ {"MultiMedia5 Mixer", "SEC_AUX_PCM_TX", "SEC_AUX_PCM_TX"},
{"MultiMedia2 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"MultiMedia1 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"},
@@ -2700,6 +2856,13 @@
{"AUX_PCM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
{"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
+ {"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
+ {"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
+ {"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
+ {"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"SEC_AUX_PCM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+ {"SEC_AUX_PCM_RX", NULL, "SEC_AUX_PCM_RX Audio Mixer"},
+
{"MI2S_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
{"MI2S_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"MI2S_RX_Voice Mixer", "Voip", "VOIP_DL"},
@@ -2749,6 +2912,12 @@
{"AUX_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
{"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
+ {"SEC_AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
+ {"SEC_AUX_PCM_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
+ {"SEC_AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
+ {"SEC_AUX_PCM_RX_Voice Mixer", "DTMF", "DTMF_DL_HL"},
+ {"SEC_AUX_PCM_RX", NULL, "SEC_AUX_PCM_RX_Voice Mixer"},
+
{"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
{"HDMI_RX_Voice Mixer", "Voice2", "VOICE2_DL"},
{"HDMI_RX_Voice Mixer", "VoLTE", "VoLTE_DL"},
@@ -2770,6 +2939,7 @@
{"Voice_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice", "INT_BT_SCO_TX"},
{"Voice_Tx Mixer", "AFE_PCM_TX_Voice", "PCM_TX"},
{"Voice_Tx Mixer", "AUX_PCM_TX_Voice", "AUX_PCM_TX"},
+ {"Voice_Tx Mixer", "SEC_AUX_PCM_TX_Voice", "SEC_AUX_PCM_TX"},
{"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
{"Voice2_Tx Mixer", "PRI_TX_Voice2", "PRI_I2S_TX"},
@@ -2785,6 +2955,7 @@
{"VoLTE_Tx Mixer", "INTERNAL_BT_SCO_TX_VoLTE", "INT_BT_SCO_TX"},
{"VoLTE_Tx Mixer", "AFE_PCM_TX_VoLTE", "PCM_TX"},
{"VoLTE_Tx Mixer", "AUX_PCM_TX_VoLTE", "AUX_PCM_TX"},
+ {"VoLTE_Tx Mixer", "SEC_AUX_PCM_TX_VoLTE", "SEC_AUX_PCM_TX"},
{"VoLTE_Tx Mixer", "MI2S_TX_VoLTE", "MI2S_TX"},
{"VoLTE_UL", NULL, "VoLTE_Tx Mixer"},
{"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"},
@@ -2793,6 +2964,7 @@
{"Voip_Tx Mixer", "INTERNAL_BT_SCO_TX_Voip", "INT_BT_SCO_TX"},
{"Voip_Tx Mixer", "AFE_PCM_TX_Voip", "PCM_TX"},
{"Voip_Tx Mixer", "AUX_PCM_TX_Voip", "AUX_PCM_TX"},
+ {"Voip_Tx Mixer", "SEC_AUX_PCM_TX_Voip", "SEC_AUX_PCM_TX"},
{"VOIP_UL", NULL, "Voip_Tx Mixer"},
{"SLIMBUS_DL_HL", "Switch", "SLIM0_DL_HL"},
@@ -2828,6 +3000,7 @@
{"SLIMBUS_0_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"SLIMBUS_0_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"SLIMBUS_0_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
+ {"SLIMBUS_0_RX Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
{"SLIMBUS_0_RX Port Mixer", "MI2S_TX", "MI2S_TX"},
{"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Port Mixer"},
{"AFE_PCM_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
@@ -2837,6 +3010,10 @@
{"AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"AUX_PCM_RX", NULL, "AUXPCM_RX Port Mixer"},
+ {"SEC_AUXPCM_RX Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"},
+ {"SEC_AUXPCM_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+ {"SEC_AUX_PCM_RX", NULL, "SEC_AUXPCM_RX Port Mixer"},
+
{"Voice Stub Tx Mixer", "STUB_TX_HL", "STUB_TX"},
{"Voice Stub Tx Mixer", "SLIM_1_TX", "SLIMBUS_1_TX"},
{"Voice Stub Tx Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
@@ -2892,6 +3069,7 @@
{"BE_OUT", NULL, "PCM_RX"},
{"BE_OUT", NULL, "SLIMBUS_3_RX"},
{"BE_OUT", NULL, "AUX_PCM_RX"},
+ {"BE_OUT", NULL, "SEC_AUX_PCM_RX"},
{"PRI_I2S_TX", NULL, "BE_IN"},
{"MI2S_TX", NULL, "BE_IN"},
@@ -2911,6 +3089,8 @@
{"BE_OUT", NULL, "SLIMBUS_3_RX"},
{"BE_OUT", NULL, "AUX_PCM_RX"},
{"AUX_PCM_TX", NULL, "BE_IN"},
+ {"BE_OUT", NULL, "SEC_AUX_PCM_RX"},
+ {"SEC_AUX_PCM_TX", NULL, "BE_IN"},
{"INCALL_RECORD_TX", NULL, "BE_IN"},
{"INCALL_RECORD_RX", NULL, "BE_IN"},
{"BE_OUT", NULL, "VOICE_PLAYBACK_TX"},
@@ -2941,7 +3121,7 @@
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
unsigned int be_id = rtd->dai_link->be_id;
- int i, session_type;
+ int i, session_type, path_type, topology;
struct msm_pcm_routing_bdai_data *bedai;
if (be_id >= MSM_BACKEND_DAI_MAX) {
@@ -2952,13 +3132,20 @@
bedai = &msm_bedais[be_id];
session_type = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
0 : 1);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ path_type = ADM_PATH_PLAYBACK;
+ else
+ path_type = ADM_PATH_LIVE_REC;
mutex_lock(&routing_lock);
-
+ topology = get_topology(path_type);
for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
- if (fe_dai_map[i][session_type] != INVALID_SESSION)
+ if (fe_dai_map[i][session_type] != INVALID_SESSION) {
adm_close(bedai->port_id);
srs_port_id = -1;
+ if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ dolby_dap_deinit(bedai->port_id);
+ }
}
bedai->active = 0;
@@ -2974,7 +3161,7 @@
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
unsigned int be_id = rtd->dai_link->be_id;
- int i, path_type, session_type;
+ int i, path_type, session_type, port_id, topology;
struct msm_pcm_routing_bdai_data *bedai;
u32 channels;
bool playback, capture;
@@ -2996,7 +3183,7 @@
}
mutex_lock(&routing_lock);
-
+ topology = get_topology(path_type);
if (bedai->active == 1)
goto done; /* Ignore prepare if back-end already active */
@@ -3021,21 +3208,25 @@
path_type,
bedai->sample_rate,
channels,
- DEFAULT_COPP_TOPOLOGY, bedai->perf_mode,
+ topology, bedai->perf_mode,
bits_per_sample);
} else if (capture) {
adm_open(bedai->port_id,
path_type,
bedai->sample_rate,
channels,
- DEFAULT_COPP_TOPOLOGY, false,
+ topology, false,
bits_per_sample);
}
msm_pcm_routing_build_matrix(i,
fe_dai_map[i][session_type], path_type);
- srs_port_id = bedai->port_id;
+ port_id = srs_port_id = bedai->port_id;
srs_send_params(srs_port_id, 1, 0);
+ if (DOLBY_ADM_COPP_TOPOLOGY_ID == topology)
+ if (dolby_dap_init(port_id, channels) < 0)
+ pr_err("%s: Err init dolby dap\n",
+ __func__);
}
}
@@ -3130,6 +3321,27 @@
snd_soc_add_platform_controls(platform,
aanc_slim_0_rx_mux,
ARRAY_SIZE(aanc_slim_0_rx_mux));
+
+ snd_soc_add_platform_controls(platform,
+ dolby_security_controls,
+ ARRAY_SIZE(dolby_security_controls));
+
+ snd_soc_add_platform_controls(platform,
+ dolby_dap_param_to_set_controls,
+ ARRAY_SIZE(dolby_dap_param_to_set_controls));
+
+ snd_soc_add_platform_controls(platform,
+ dolby_dap_param_to_get_controls,
+ ARRAY_SIZE(dolby_dap_param_to_get_controls));
+
+ snd_soc_add_platform_controls(platform,
+ dolby_dap_param_visualizer_controls,
+ ARRAY_SIZE(dolby_dap_param_visualizer_controls));
+
+ snd_soc_add_platform_controls(platform,
+ dolby_dap_param_end_point_controls,
+ ARRAY_SIZE(dolby_dap_param_end_point_controls));
+
return 0;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
index 1c1029c..4a58369 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h
@@ -26,6 +26,8 @@
#define LPASS_BE_AFE_PCM_TX "RT_PROXY_DAI_002_TX"
#define LPASS_BE_AUXPCM_RX "AUX_PCM_RX"
#define LPASS_BE_AUXPCM_TX "AUX_PCM_TX"
+#define LPASS_BE_SEC_AUXPCM_RX "SEC_AUX_PCM_RX"
+#define LPASS_BE_SEC_AUXPCM_TX "SEC_AUX_PCM_TX"
#define LPASS_BE_VOICE_PLAYBACK_TX "VOICE_PLAYBACK_TX"
#define LPASS_BE_INCALL_RECORD_RX "INCALL_RECORD_TX"
#define LPASS_BE_INCALL_RECORD_TX "INCALL_RECORD_RX"
@@ -119,6 +121,8 @@
MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
MSM_BACKEND_DAI_AUDIO_I2S_RX,
+ MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ MSM_BACKEND_DAI_SEC_AUXPCM_TX,
MSM_BACKEND_DAI_MAX,
};
@@ -141,4 +145,7 @@
int compressed_set_volume(unsigned volume);
+uint32_t get_adm_rx_topology(void);
+
+uint32_t get_adm_tx_topology(void);
#endif /*_MSM_PCM_H*/
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index b1db277..1bd3eac 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -33,6 +33,7 @@
#define RESET_COPP_ID 99
#define INVALID_COPP_ID 0xFF
+#define ADM_GET_PARAMETER_LENGTH 350
struct adm_ctl {
void *apr;
@@ -64,6 +65,8 @@
{0, 0, 0, 0, 0, 0, 0, 0}
};
+static int adm_dolby_get_parameters[ADM_GET_PARAMETER_LENGTH];
+
int srs_trumedia_open(int port_id, int srs_tech_id, void *srs_params)
{
struct adm_cmd_set_pp_params_inband_v5 *adm_params = NULL;
@@ -266,6 +269,134 @@
return ret;
}
+int adm_dolby_dap_send_params(int port_id, char *params, uint32_t params_length)
+{
+ struct adm_cmd_set_pp_params_v5 *adm_params = NULL;
+ int sz, rc = 0, index = afe_get_port_index(port_id);
+
+ pr_debug("%s\n", __func__);
+ if (index < 0 || index >= AFE_MAX_PORTS) {
+ pr_err("%s: invalid port idx %d portid %#x\n",
+ __func__, index, port_id);
+ return -EINVAL;
+ }
+ sz = sizeof(struct adm_cmd_set_pp_params_v5) + params_length;
+ adm_params = kzalloc(sz, GFP_KERNEL);
+ if (!adm_params) {
+ pr_err("%s, adm params memory alloc failed", __func__);
+ return -ENOMEM;
+ }
+
+ memcpy(((u8 *)adm_params + sizeof(struct adm_cmd_set_pp_params_v5)),
+ params, params_length);
+ adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ adm_params->hdr.pkt_size = sz;
+ adm_params->hdr.src_svc = APR_SVC_ADM;
+ adm_params->hdr.src_domain = APR_DOMAIN_APPS;
+ adm_params->hdr.src_port = port_id;
+ adm_params->hdr.dest_svc = APR_SVC_ADM;
+ adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
+ adm_params->hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
+ adm_params->hdr.token = port_id;
+ adm_params->hdr.opcode = ADM_CMD_SET_PP_PARAMS_V5;
+ adm_params->payload_addr_lsw = 0;
+ adm_params->payload_addr_msw = 0;
+ adm_params->mem_map_handle = 0;
+ adm_params->payload_size = params_length;
+
+ atomic_set(&this_adm.copp_stat[index], 0);
+ rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
+ if (rc < 0) {
+ pr_err("%s: Set params failed port = %#x\n",
+ __func__, port_id);
+ rc = -EINVAL;
+ goto dolby_dap_send_param_return;
+ }
+ /* Wait for the callback */
+ rc = wait_event_timeout(this_adm.wait[index],
+ atomic_read(&this_adm.copp_stat[index]),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!rc) {
+ pr_err("%s: Set params timed out port = %#x\n",
+ __func__, port_id);
+ rc = -EINVAL;
+ goto dolby_dap_send_param_return;
+ }
+ rc = 0;
+dolby_dap_send_param_return:
+ kfree(adm_params);
+ return rc;
+}
+
+int adm_dolby_dap_get_params(int port_id, uint32_t module_id, uint32_t param_id,
+ uint32_t params_length, char *params)
+{
+ struct adm_cmd_get_pp_params_v5 *adm_params = NULL;
+ int sz, rc = 0, i = 0, index = afe_get_port_index(port_id);
+ int *params_data = (int *)params;
+
+ if (index < 0 || index >= AFE_MAX_PORTS) {
+ pr_err("%s: invalid port idx %d portid %#x\n",
+ __func__, index, port_id);
+ return -EINVAL;
+ }
+ sz = sizeof(struct adm_cmd_set_pp_params_v5) + params_length;
+ adm_params = kzalloc(sz, GFP_KERNEL);
+ if (!adm_params) {
+ pr_err("%s, adm params memory alloc failed", __func__);
+ return -ENOMEM;
+ }
+
+ memcpy(((u8 *)adm_params + sizeof(struct adm_cmd_set_pp_params_v5)),
+ params, params_length);
+ adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ adm_params->hdr.pkt_size = sz;
+ adm_params->hdr.src_svc = APR_SVC_ADM;
+ adm_params->hdr.src_domain = APR_DOMAIN_APPS;
+ adm_params->hdr.src_port = port_id;
+ adm_params->hdr.dest_svc = APR_SVC_ADM;
+ adm_params->hdr.dest_domain = APR_DOMAIN_ADSP;
+ adm_params->hdr.dest_port = atomic_read(&this_adm.copp_id[index]);
+ adm_params->hdr.token = port_id;
+ adm_params->hdr.opcode = ADM_CMD_GET_PP_PARAMS_V5;
+ adm_params->data_payload_addr_lsw = 0;
+ adm_params->data_payload_addr_msw = 0;
+ adm_params->mem_map_handle = 0;
+ adm_params->module_id = module_id;
+ adm_params->param_id = param_id;
+ adm_params->param_max_size = params_length;
+ adm_params->reserved = 0;
+
+ atomic_set(&this_adm.copp_stat[index], 0);
+ rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params);
+ if (rc < 0) {
+ pr_err("%s: Failed to Get DOLBY Params on port %d\n", __func__,
+ port_id);
+ rc = -EINVAL;
+ goto dolby_dap_get_param_return;
+ }
+ /* Wait for the callback with copp id */
+ rc = wait_event_timeout(this_adm.wait[index],
+ atomic_read(&this_adm.copp_stat[index]),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!rc) {
+ pr_err("%s: DOLBY get params timed out port = %d\n", __func__,
+ port_id);
+ rc = -EINVAL;
+ goto dolby_dap_get_param_return;
+ }
+ if (params_data) {
+ for (i = 0; i < adm_dolby_get_parameters[0]; i++)
+ params_data[i] = adm_dolby_get_parameters[1+i];
+ }
+ rc = 0;
+dolby_dap_get_param_return:
+ kfree(adm_params);
+ return rc;
+}
+
static void adm_callback_debug_print(struct apr_client_data *data)
{
uint32_t *payload;
@@ -428,6 +559,13 @@
__func__, payload[0]);
rtac_make_adm_callback(payload,
data->payload_size);
+ adm_dolby_get_parameters[0] = payload[3];
+ pr_debug("GET_PP PARAM:received parameter length: %x\n",
+ adm_dolby_get_parameters[0]);
+ for (i = 0; i < payload[3]; i++)
+ adm_dolby_get_parameters[1+i] = payload[4+i];
+ atomic_set(&this_adm.copp_stat[index], 1);
+ wake_up(&this_adm.wait[index]);
break;
case ADM_CMDRSP_SHARED_MEM_MAP_REGIONS:
pr_debug("%s: ADM_CMDRSP_SHARED_MEM_MAP_REGIONS\n",
@@ -807,20 +945,10 @@
open.endpoint_id_1 = tmp_port;
open.endpoint_id_2 = 0xFFFF;
- /* convert path to acdb path */
- if (path == ADM_PATH_PLAYBACK)
- open.topology_id = get_adm_rx_topology();
- else {
- open.topology_id = get_adm_tx_topology();
- if ((open.topology_id ==
- VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
- (open.topology_id ==
- VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
+ open.topology_id = topology;
+ if ((open.topology_id == VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
+ (open.topology_id == VPM_TX_DM_FLUENCE_COPP_TOPOLOGY))
rate = 16000;
- }
-
- if (open.topology_id == 0)
- open.topology_id = topology;
open.dev_num_channel = channel_mode & 0x00FF;
open.bit_width = bits_per_sample;
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 3b1727c..09d6a0f 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -17,7 +17,7 @@
#include <linux/wait.h>
#include <linux/jiffies.h>
#include <linux/sched.h>
-#include <linux/msm_ion.h>
+#include <linux/msm_audio_ion.h>
#include <sound/apr_audio-v2.h>
#include <sound/q6afe-v2.h>
#include <sound/q6audio-v2.h>
@@ -224,6 +224,7 @@
case AFE_PORT_ID_SECONDARY_MI2S_RX:
case AFE_PORT_ID_TERTIARY_MI2S_RX:
case AFE_PORT_ID_QUATERNARY_MI2S_RX:
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
ret = MSM_AFE_PORT_TYPE_RX;
break;
@@ -247,6 +248,7 @@
case AFE_PORT_ID_SECONDARY_MI2S_TX:
case AFE_PORT_ID_TERTIARY_MI2S_TX:
case AFE_PORT_ID_QUATERNARY_MI2S_TX:
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
ret = MSM_AFE_PORT_TYPE_TX;
break;
@@ -295,6 +297,8 @@
break;
case PCM_RX:
case PCM_TX:
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
default:
ret_size = SIZEOF_CFG_CMD(afe_param_id_pcm_cfg);
break;
@@ -1120,7 +1124,9 @@
break;
case PCM_RX:
case PCM_TX:
- cfg_type = AFE_PARAM_ID_HDMI_CONFIG;
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
+ cfg_type = AFE_PARAM_ID_PCM_CONFIG;
break;
case SECONDARY_I2S_RX:
case SECONDARY_I2S_TX:
@@ -1215,6 +1221,10 @@
case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
case PCM_RX: return IDX_PCM_RX;
case PCM_TX: return IDX_PCM_TX;
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ return IDX_AFE_PORT_ID_SECONDARY_PCM_RX;
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
+ return IDX_AFE_PORT_ID_SECONDARY_PCM_TX;
case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
case MI2S_RX: return IDX_MI2S_RX;
@@ -1310,6 +1320,8 @@
break;
case PCM_RX:
case PCM_TX:
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
cfg_type = AFE_PARAM_ID_PCM_CONFIG;
break;
case SECONDARY_I2S_RX:
@@ -1707,35 +1719,13 @@
ac->port[dir].buf = buf;
- buf[0].client = msm_ion_client_create(UINT_MAX, "audio_client");
- if (IS_ERR_OR_NULL((void *)buf[0].client)) {
- pr_err("%s: ION create client for AUDIO failed\n", __func__);
- goto fail;
- }
- buf[0].handle = ion_alloc(buf[0].client, bufsz * bufcnt, SZ_4K,
- (0x1 << ION_AUDIO_HEAP_ID), 0);
- if (IS_ERR_OR_NULL((void *) buf[0].handle)) {
- pr_err("%s: ION memory allocation for AUDIO failed\n",
- __func__);
- goto fail;
- }
-
- rc = ion_phys(buf[0].client, buf[0].handle,
- (ion_phys_addr_t *)&buf[0].phys, (size_t *)&len);
+ rc = msm_audio_ion_alloc("audio_client", &buf[0].client,
+ &buf[0].handle, bufsz*bufcnt,
+ (ion_phys_addr_t *)&buf[0].phys, (size_t *)&len,
+ &buf[0].data);
if (rc) {
- pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+ pr_err("%s: audio ION alloc failed, rc = %d\n",
__func__, rc);
- goto fail;
- }
-
- buf[0].data = ion_map_kernel(buf[0].client, buf[0].handle);
- if (IS_ERR_OR_NULL((void *) buf[0].data)) {
- pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
- goto fail;
- }
- memset((void *)buf[0].data, 0, (bufsz * bufcnt));
- if (!buf[0].data) {
- pr_err("%s:invalid vaddr, iomap failed\n", __func__);
mutex_unlock(&ac->cmd_lock);
goto fail;
}
@@ -1944,9 +1934,7 @@
cnt = port->max_buf_cnt - 1;
if (port->buf[0].data) {
- ion_unmap_kernel(port->buf[0].client, port->buf[0].handle);
- ion_free(port->buf[0].client, port->buf[0].handle);
- ion_client_destroy(port->buf[0].client);
+ msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
pr_debug("%s:data[%p]phys[%p][%p] , client[%p] handle[%p]\n",
__func__,
(void *)port->buf[0].data,
@@ -2363,11 +2351,11 @@
static void config_debug_fs_init(void)
{
debugfs_afelb = debugfs_create_file("afe_loopback",
- S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback",
+ S_IRUGO | S_IWUSR | S_IWGRP, NULL, (void *) "afe_loopback",
&afe_debug_fops);
debugfs_afelb_gain = debugfs_create_file("afe_loopback_gain",
- S_IFREG | S_IWUGO, NULL, (void *) "afe_loopback_gain",
+ S_IRUGO | S_IWUSR | S_IWGRP, NULL, (void *) "afe_loopback_gain",
&afe_debug_fops);
}
static void config_debug_fs_exit(void)
@@ -2521,6 +2509,8 @@
case PRIMARY_I2S_TX:
case PCM_RX:
case PCM_TX:
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
case SECONDARY_I2S_RX:
case SECONDARY_I2S_TX:
case MI2S_RX:
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index ea2b5c6..fffd0b3 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -29,13 +29,13 @@
#include <linux/debugfs.h>
#include <linux/time.h>
#include <linux/atomic.h>
+#include <linux/msm_audio_ion.h>
#include <asm/ioctls.h>
#include <mach/memory.h>
#include <mach/debug_mm.h>
#include <mach/qdsp6v2/rtac.h>
-#include <mach/msm_subsystem_map.h>
#include <sound/apr_audio-v2.h>
#include <sound/q6asm-v2.h>
@@ -279,13 +279,13 @@
{
out_buffer = kmalloc(OUT_BUFFER_SIZE, GFP_KERNEL);
out_dentry = debugfs_create_file("audio_out_latency_measurement_node",\
- S_IFREG | S_IRUGO | S_IWUGO,\
+ S_IRUGO | S_IWUSR | S_IWGRP,\
NULL, NULL, &audio_output_latency_debug_fops);
if (IS_ERR(out_dentry))
pr_err("debugfs_create_file failed\n");
in_buffer = kmalloc(IN_BUFFER_SIZE, GFP_KERNEL);
in_dentry = debugfs_create_file("audio_in_latency_measurement_node",\
- S_IFREG | S_IRUGO | S_IWUGO,\
+ S_IRUGO | S_IWUSR | S_IWGRP,\
NULL, NULL, &audio_input_latency_debug_fops);
if (IS_ERR(in_dentry))
pr_err("debugfs_create_file failed\n");
@@ -456,11 +456,8 @@
while (cnt >= 0) {
if (port->buf[cnt].data) {
- ion_unmap_kernel(port->buf[cnt].client,
- port->buf[cnt].handle);
- ion_free(port->buf[cnt].client,
- port->buf[cnt].handle);
- ion_client_destroy(port->buf[cnt].client);
+ msm_audio_ion_free(port->buf[cnt].client,
+ port->buf[cnt].handle);
port->buf[cnt].data = NULL;
port->buf[cnt].phys = 0;
--(port->max_buf_cnt);
@@ -497,9 +494,7 @@
}
if (port->buf[0].data) {
- ion_unmap_kernel(port->buf[0].client, port->buf[0].handle);
- ion_free(port->buf[0].client, port->buf[0].handle);
- ion_client_destroy(port->buf[0].client);
+ msm_audio_ion_free(port->buf[0].client, port->buf[0].handle);
pr_debug("%s:data[%p]phys[%p][%p] , client[%p] handle[%p]\n",
__func__,
(void *)port->buf[0].data,
@@ -724,44 +719,19 @@
while (cnt < bufcnt) {
if (bufsz > 0) {
if (!buf[cnt].data) {
- buf[cnt].client = msm_ion_client_create
- (UINT_MAX, "audio_client");
- if (IS_ERR_OR_NULL((void *)
- buf[cnt].client)) {
- pr_err("%s: ION create client for AUDIO failed\n",
- __func__);
- goto fail;
- }
- buf[cnt].handle = ion_alloc
- (buf[cnt].client, bufsz, SZ_4K,
- (0x1 << ION_AUDIO_HEAP_ID), 0);
- if (IS_ERR_OR_NULL((void *)
- buf[cnt].handle)) {
- pr_err("%s: ION memory allocation for AUDIO failed\n",
- __func__);
- goto fail;
- }
-
- rc = ion_phys(buf[cnt].client,
- buf[cnt].handle,
- (ion_phys_addr_t *)
- &buf[cnt].phys,
- (size_t *)&len);
+ msm_audio_ion_alloc("audio_client",
+ &buf[cnt].client, &buf[cnt].handle,
+ bufsz,
+ (ion_phys_addr_t *)&buf[cnt].phys,
+ (size_t *)&len,
+ &buf[cnt].data);
if (rc) {
pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
__func__, rc);
- goto fail;
+ mutex_unlock(&ac->cmd_lock);
+ goto fail;
}
- buf[cnt].data = ion_map_kernel
- (buf[cnt].client, buf[cnt].handle);
- if (IS_ERR_OR_NULL((void *)
- buf[cnt].data)) {
- pr_err("%s: ION memory mapping for AUDIO failed\n",
- __func__);
- goto fail;
- }
- memset((void *)buf[cnt].data, 0, bufsz);
buf[cnt].used = 1;
buf[cnt].size = bufsz;
buf[cnt].actual_size = bufsz;
@@ -824,35 +794,13 @@
ac->port[dir].buf = buf;
- buf[0].client = msm_ion_client_create(UINT_MAX, "audio_client");
- if (IS_ERR_OR_NULL((void *)buf[0].client)) {
- pr_err("%s: ION create client for AUDIO failed\n", __func__);
- goto fail;
- }
- buf[0].handle = ion_alloc(buf[0].client, bufsz * bufcnt, SZ_4K,
- (0x1 << ION_AUDIO_HEAP_ID), 0);
- if (IS_ERR_OR_NULL((void *) buf[0].handle)) {
- pr_err("%s: ION memory allocation for AUDIO failed\n",
- __func__);
- goto fail;
- }
-
- rc = ion_phys(buf[0].client, buf[0].handle,
- (ion_phys_addr_t *)&buf[0].phys, (size_t *)&len);
+ rc = msm_audio_ion_alloc("audio_client", &buf[0].client, &buf[0].handle,
+ bufsz*bufcnt,
+ (ion_phys_addr_t *)&buf[0].phys, (size_t *)&len,
+ &buf[0].data);
if (rc) {
- pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+ pr_err("%s: Audio ION alloc is failed, rc = %d\n",
__func__, rc);
- goto fail;
- }
-
- buf[0].data = ion_map_kernel(buf[0].client, buf[0].handle);
- if (IS_ERR_OR_NULL((void *) buf[0].data)) {
- pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
- goto fail;
- }
- memset((void *)buf[0].data, 0, (bufsz * bufcnt));
- if (!buf[0].data) {
- pr_err("%s:invalid vaddr, iomap failed\n", __func__);
mutex_unlock(&ac->cmd_lock);
goto fail;
}
@@ -1570,6 +1518,12 @@
case FORMAT_MP3:
open.dec_fmt_id = ASM_MEDIA_FMT_MP3;
break;
+ case FORMAT_AC3:
+ open.dec_fmt_id = ASM_MEDIA_FMT_EAC3_DEC;
+ break;
+ case FORMAT_EAC3:
+ open.dec_fmt_id = ASM_MEDIA_FMT_EAC3_DEC;
+ break;
default:
pr_err("%s: Invalid format[%d]\n", __func__, format);
goto fail_cmd;
@@ -2571,6 +2525,40 @@
return -EINVAL;
}
+int q6asm_ds1_set_endp_params(struct audio_client *ac,
+ int param_id, int param_value)
+{
+ struct asm_dec_ddp_endp_param_v2 ddp_cfg;
+ int rc = 0;
+
+ pr_debug("%s: session[%d]param_id[%d]param_value[%d]", __func__,
+ ac->session, param_id, param_value);
+ q6asm_add_hdr(ac, &ddp_cfg.hdr, sizeof(ddp_cfg), TRUE);
+ ddp_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM;
+ ddp_cfg.encdec.param_id = param_id;
+ ddp_cfg.encdec.param_size = sizeof(struct asm_dec_ddp_endp_param_v2) -
+ (sizeof(struct apr_hdr) +
+ sizeof(struct asm_stream_cmd_set_encdec_param));
+ ddp_cfg.endp_param_value = param_value;
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &ddp_cfg);
+ if (rc < 0) {
+ pr_err("%s:Command opcode[0x%x] failed\n",
+ __func__, ASM_STREAM_CMD_SET_ENCDEC_PARAM);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s:timeout opcode[0x%x]\n", __func__,
+ ddp_cfg.hdr.opcode);
+ rc = -ETIMEDOUT;
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return rc;
+}
+
int q6asm_memory_map(struct audio_client *ac, uint32_t buf_add, int dir,
uint32_t bufsz, uint32_t bufcnt)
{
diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c
index d3d335d..faf5f35 100644
--- a/sound/soc/msm/qdsp6v2/q6audio-v2.c
+++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c
@@ -26,6 +26,10 @@
case PRIMARY_I2S_TX: return IDX_PRIMARY_I2S_TX;
case PCM_RX: return IDX_PCM_RX;
case PCM_TX: return IDX_PCM_TX;
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ return IDX_AFE_PORT_ID_SECONDARY_PCM_RX;
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
+ return IDX_AFE_PORT_ID_SECONDARY_PCM_TX;
case SECONDARY_I2S_RX: return IDX_SECONDARY_I2S_RX;
case SECONDARY_I2S_TX: return IDX_SECONDARY_I2S_TX;
case MI2S_RX: return IDX_MI2S_RX;
@@ -74,6 +78,10 @@
case PRIMARY_I2S_TX: return AFE_PORT_ID_PRIMARY_MI2S_TX;
case PCM_RX: return AFE_PORT_ID_PRIMARY_PCM_RX;
case PCM_TX: return AFE_PORT_ID_PRIMARY_PCM_TX;
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ return AFE_PORT_ID_SECONDARY_PCM_RX;
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
+ return AFE_PORT_ID_SECONDARY_PCM_TX;
case SECONDARY_I2S_RX: return AFE_PORT_ID_SECONDARY_MI2S_RX;
case SECONDARY_I2S_TX: return AFE_PORT_ID_SECONDARY_MI2S_TX;
case MI2S_RX: return AFE_PORT_ID_PRIMARY_MI2S_RX;
@@ -146,6 +154,8 @@
case PRIMARY_I2S_TX:
case PCM_RX:
case PCM_TX:
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
case SECONDARY_I2S_RX:
case SECONDARY_I2S_TX:
case MI2S_RX:
@@ -171,6 +181,8 @@
case PRIMARY_I2S_TX:
case PCM_RX:
case PCM_TX:
+ case AFE_PORT_ID_SECONDARY_PCM_RX:
+ case AFE_PORT_ID_SECONDARY_PCM_TX:
case SECONDARY_I2S_RX:
case SECONDARY_I2S_TX:
case MI2S_RX:
diff --git a/sound/soc/msm/qdsp6v2/q6lsm.c b/sound/soc/msm/qdsp6v2/q6lsm.c
index f2b531a..49e5ede 100644
--- a/sound/soc/msm/qdsp6v2/q6lsm.c
+++ b/sound/soc/msm/qdsp6v2/q6lsm.c
@@ -30,7 +30,6 @@
#include <asm/ioctls.h>
#include <mach/memory.h>
#include <mach/debug_mm.h>
-#include <mach/msm_subsystem_map.h>
#include "audio_acdb.h"
#define APR_TIMEOUT (5 * HZ)
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 754a4fa..a417b26 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -16,6 +16,7 @@
#include <linux/uaccess.h>
#include <linux/wait.h>
#include <linux/mutex.h>
+#include <linux/msm_audio_ion.h>
#include <asm/mach-types.h>
#include <mach/qdsp6v2/rtac.h>
@@ -2532,14 +2533,8 @@
mvm_set_voice_timing.hdr.opcode = VSS_ICOMMON_CMD_SET_VOICE_TIMING;
mvm_set_voice_timing.timing.mode = 0;
mvm_set_voice_timing.timing.enc_offset = 8000;
- if ((machine_is_apq8064_sim()) || (machine_is_msm8974_sim())) {
- pr_debug("%s: Machine is MSM8974 sim\n", __func__);
- mvm_set_voice_timing.timing.dec_req_offset = 0;
- mvm_set_voice_timing.timing.dec_offset = 18000;
- } else {
- mvm_set_voice_timing.timing.dec_req_offset = 3300;
- mvm_set_voice_timing.timing.dec_offset = 8300;
- }
+ mvm_set_voice_timing.timing.dec_req_offset = 3300;
+ mvm_set_voice_timing.timing.dec_offset = 8300;
v->mvm_state = CMD_STATUS_FAIL;
@@ -4639,35 +4634,16 @@
pr_err("%s: v is NULL\n", __func__);
return -EINVAL;
}
- v->shmem_info.sh_buf.client = msm_ion_client_create(UINT_MAX,
- "voip_client");
- if (IS_ERR_OR_NULL((void *)v->shmem_info.sh_buf.client)) {
- pr_err("%s: ION create client failed\n", __func__);
- goto err;
- }
- v->shmem_info.sh_buf.handle = ion_alloc(v->shmem_info.sh_buf.client,
- bufsz * bufcnt, SZ_4K,
- (0x1 << ION_AUDIO_HEAP_ID), 0);
- if (IS_ERR_OR_NULL((void *)v->shmem_info.sh_buf.handle)) {
- pr_err("%s: ION memory allocation failed\n",
- __func__);
- goto err_ion_client;
- }
-
- rc = ion_phys(v->shmem_info.sh_buf.client, v->shmem_info.sh_buf.handle,
- (ion_phys_addr_t *)&phys, (size_t *)&len);
+ rc = msm_audio_ion_alloc("voip_client", &(v->shmem_info.sh_buf.client),
+ &(v->shmem_info.sh_buf.handle),
+ bufsz*bufcnt,
+ (ion_phys_addr_t *)&phys, (size_t *)&len,
+ &mem_addr);
if (rc) {
- pr_err("%s: ION Get Physical failed, rc = %d\n",
+ pr_err("%s: audio ION alloc failed, rc = %d\n",
__func__, rc);
- goto err_ion_handle;
- }
-
- mem_addr = ion_map_kernel(v->shmem_info.sh_buf.client,
- v->shmem_info.sh_buf.handle);
- if (IS_ERR_OR_NULL(mem_addr)) {
- pr_err("%s: ION memory mapping failed\n", __func__);
- goto err_ion_handle;
+ return -EINVAL;
}
while (cnt < bufcnt) {
@@ -4691,13 +4667,6 @@
memset((void *)v->shmem_info.sh_buf.buf[0].data, 0, (bufsz * bufcnt));
return 0;
-
-err_ion_handle:
- ion_free(v->shmem_info.sh_buf.client, v->shmem_info.sh_buf.handle);
-err_ion_client:
- ion_client_destroy(v->shmem_info.sh_buf.client);
-err:
- return -EINVAL;
}
static int voice_alloc_oob_mem_table(void)
@@ -4711,41 +4680,19 @@
pr_err("%s: v is NULL\n", __func__);
return -EINVAL;
}
- v->shmem_info.memtbl.client = msm_ion_client_create(UINT_MAX,
- "voip_client");
- if (IS_ERR_OR_NULL((void *)v->shmem_info.memtbl.client)) {
- pr_err("%s: ION create client for memtbl failed\n", __func__);
- goto err;
- }
- v->shmem_info.memtbl.handle = ion_alloc(v->shmem_info.memtbl.client,
- sizeof(struct vss_imemory_table_t), SZ_4K,
- (0x1 << ION_AUDIO_HEAP_ID), 0);
- if (IS_ERR_OR_NULL((void *) v->shmem_info.memtbl.handle)) {
- pr_err("%s: ION memory allocation for memtbl failed\n",
- __func__);
- goto err_ion_client;
- }
-
- rc = ion_phys(v->shmem_info.memtbl.client, v->shmem_info.memtbl.handle,
- (ion_phys_addr_t *)&v->shmem_info.memtbl.phys, (size_t *)&len);
+ rc = msm_audio_ion_alloc("voip_client", &(v->shmem_info.memtbl.client),
+ &(v->shmem_info.memtbl.handle),
+ sizeof(struct vss_imemory_table_t),
+ (ion_phys_addr_t *)&v->shmem_info.memtbl.phys,
+ (size_t *)&len,
+ &(v->shmem_info.memtbl.data));
if (rc) {
- pr_err("%s: ION Get Physical for memtbl failed, rc = %d\n",
+ pr_err("%s: audio ION alloc failed, rc = %d\n",
__func__, rc);
- goto err_ion_handle;
+ return -EINVAL;
}
- v->shmem_info.memtbl.data = ion_map_kernel(v->shmem_info.memtbl.client,
- v->shmem_info.memtbl.handle);
- if (IS_ERR_OR_NULL((void *)v->shmem_info.memtbl.data)) {
- pr_err("%s: ION memory mapping for memtbl failed\n",
- __func__);
- goto err_ion_handle;
- }
-
- memset(v->shmem_info.memtbl.data, 0,
- sizeof(struct vss_imemory_table_t));
-
v->shmem_info.memtbl.size = sizeof(struct vss_imemory_table_t);
pr_debug("%s data[%p]phys[%p][%p]\n", __func__,
@@ -4755,12 +4702,6 @@
return 0;
-err_ion_handle:
- ion_free(v->shmem_info.memtbl.client, v->shmem_info.memtbl.handle);
-err_ion_client:
- ion_client_destroy(v->shmem_info.memtbl.client);
-err:
- return -EINVAL;
}
static int voice_alloc_cal_mem_map_table(void)
@@ -4768,67 +4709,25 @@
int ret = 0;
int len;
- common.cal_mem_map_table.client = msm_ion_client_create(UINT_MAX,
- "voc_client");
-
- if (IS_ERR_OR_NULL((void *) common.cal_mem_map_table.client)) {
- pr_err("%s: ION create client for cal mem map table failed\n",
- __func__);
-
- goto err;
- }
-
- common.cal_mem_map_table.handle =
- ion_alloc(common.cal_mem_map_table.client,
- sizeof(struct vss_imemory_table_t),
- SZ_4K, (0x1 << ION_AUDIO_HEAP_ID), 0);
- if (IS_ERR_OR_NULL((void *) common.cal_mem_map_table.handle)) {
- pr_err("%s: ION memory alloc for cal mem map table failed\n",
- __func__);
-
- goto err_ion_client;
- }
-
- ret = ion_phys(common.cal_mem_map_table.client,
- common.cal_mem_map_table.handle,
- (ion_phys_addr_t *) &common.cal_mem_map_table.phys,
- (size_t *) &len);
+ ret = msm_audio_ion_alloc("voip_client",
+ &(common.cal_mem_map_table.client),
+ &(common.cal_mem_map_table.handle),
+ sizeof(struct vss_imemory_table_t),
+ (ion_phys_addr_t *)&common.cal_mem_map_table.phys,
+ (size_t *) &len,
+ &(common.cal_mem_map_table.data));
if (ret) {
- pr_err("%s: Phy addr for cal mem map table failed %d\n",
- __func__, ret);
-
- goto err_ion_handle;
+ pr_err("%s: audio ION alloc failed, rc = %d\n",
+ __func__, ret);
+ return -EINVAL;
}
- common.cal_mem_map_table.data =
- ion_map_kernel(common.cal_mem_map_table.client,
- common.cal_mem_map_table.handle);
- if (IS_ERR_OR_NULL((void *) common.cal_mem_map_table.data)) {
- pr_err("%s: Virtual addr for cal memory map table failed\n",
- __func__);
-
- goto err_ion_handle;
- }
-
- memset(common.cal_mem_map_table.data, 0,
- sizeof(struct vss_imemory_table_t));
-
common.cal_mem_map_table.size = sizeof(struct vss_imemory_table_t);
-
pr_debug("%s: data 0x%x phys 0x%x\n", __func__,
(unsigned int) common.cal_mem_map_table.data,
common.cal_mem_map_table.phys);
return 0;
-
-err_ion_handle:
- ion_free(common.cal_mem_map_table.client,
- common.cal_mem_map_table.handle);
-err_ion_client:
- ion_client_destroy(common.cal_mem_map_table.client);
- memset(&common.cal_mem_map_table, 0, sizeof(common.cal_mem_map_table));
-err:
- return -EINVAL;
}
static int __init voice_init(void)
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index babfddc..ef5c6e3 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1339,7 +1339,7 @@
#define VOLTE_SESSION_NAME "VoLTE session"
#define VOICE2_SESSION_NAME "Voice2 session"
-#define VOICE2_SESSION_VSID "10dc1000"
+#define VOICE2_SESSION_VSID "10DC1000"
/* called by alsa driver */
int voc_set_pp_enable(uint16_t session_id, uint32_t module_id,
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 915c3c2..40595bf 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1649,9 +1649,11 @@
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
fe->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP;
break;
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED;
+ break;
}
out: