Merge "msm_fb: display: Removing clk_set_rate in atomic context" into msm-3.4
diff --git a/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt b/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
new file mode 100644
index 0000000..d82284d
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/bam_dmux.txt
@@ -0,0 +1,14 @@
+Qualcomm BAM Data Multiplexer Driver
+
+Required properties:
+- compatible : should be "qcom,bam_dmux"
+- reg : the location and size of the BAM hardware
+- interrupts : the BAM hardware to apps processor interrupt line
+
+Example:
+
+ qcom,bam_dmux@fc834000 {
+ compatible = "qcom,bam_dmux";
+ reg = <0xfc834000 0x7000>;
+ interrupts = <0 29 1>;
+ };
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 6db1150..82e76fc 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -14,6 +14,16 @@
- qcom,mdss-pan-bpp: Specifies the panel bits per pixel. Default value is 24(rgb888).
18 = for rgb666
16 = for rgb565
+- qcom,panel-phy-regulatorSettings: An array of length 8 that specifies the PHY
+ regulator settings for the panel.
+- qcom,panel-phy-timingSettings: An array of length 12 that specifies the PHY
+ timing settings for the panel.
+- qcom,panel-phy-strengthCtrl: An array of length 2 that specifies the PHY
+ strengthCtrl settings for the panel.
+- qcom,panel-phy-bistCtrl: An array of length 6 that specifies the PHY
+ BIST ctrl settings for the panel.
+- qcom,panel-phy-laneConfig: An array of length 45 that specifies the PHY
+ lane configuration settings for the panel.
- qcom,mdss-panel-on-cmds: An array of variable length that lists the init commands
of the panel. Each command will have the format specified
as below:
@@ -42,9 +52,16 @@
Optional properties:
- label: A string used as a descriptive name of the panel
+- qcom,enable-gpio: Specifies the panel lcd/display enable gpio.
+- qcom,rst-gpio: Specifies the panel reset gpio.
- qcom,mdss-pan-porch-values: An array of size 6 that specifies the panel blanking values.
- qcom,mdss-pan-underflow-clr: Specifies the controller settings for the panel underflow clear
settings. Default value is 0xff.
+- qcom,mdss-pan-bl-ctrl: A string that specifies the implementation of backlight
+ control for this panel.
+ "bl_ctrl_pwm" = Backlight controlled by PWM gpio.
+ "bl_ctrl_wled" = Backlight controlled by WLED.
+ "bl_ctrl_dcs_cmds" = Backlight controlled by DCS commands.
- qcom,mdss-pan-bl-levels: Specifies the backlight levels supported by the panel.
Default range is 1 to 255.
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
new file mode 100644
index 0000000..478e335
--- /dev/null
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -0,0 +1,23 @@
+Qualcomm MDSS MDP
+
+MDSS is Mobile Display SubSystem which implements Linux framebuffer APIs to
+drive user interface to different panel interfaces. MDP driver is the core of
+MDSS which manage all data paths to different panel interfaces.
+
+Required properties
+- compatible : Must be "qcom,mdss_mdp"
+- reg : offset and length of the register set for the device.
+- reg-names : names to refer to register sets related to this device
+- interrupts : Interrupt associated with MDSS.
+- vdd-supply : Phandle for vdd regulator device node.
+
+Example:
+ qcom,mdss_mdp@fd900000 {
+ compatible = "qcom,mdss_mdp";
+ reg = <0xfd900000 0x22100>,
+ <0xfd924000 0x1000>;
+ reg-names = "mdp_phys", "vbif_phys";
+ interrupts = <0 72 0>;
+ vdd-supply = <&gdsc_mdss>;
+ };
+
diff --git a/Documentation/devicetree/bindings/leds/leds-qpnp.txt b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
new file mode 100644
index 0000000..51bf9e6
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/leds-qpnp.txt
@@ -0,0 +1,57 @@
+Qualcomm QPNP Leds
+
+QPNP (Qualcomm Plug N Play) LEDs driver is used for
+controlling LEDs that are part of PMIC on Qualcomm reference
+platforms. The PMIC is connected to Host processor via
+SPMI bus. This driver supports various LED modules such as
+WLED (white LED), RGB LED and flash LED. The first version of
+the driver supports WLED and other features are added in the
+next versions.
+
+Required Properties:
+- compatible : should be "qcom,leds-qpnp"
+
+Each LED module is represented as a node of "leds-qpnp". This
+node will furthur contain the type of LED supported and its
+properties.
+
+Required properties:
+- qcom,id : must be one of values supported in enum qpnp_led
+- qcom,label : type of led that will be used, ie "wled"
+- qcom,max-current : maximum current that the LED can sustain
+= qcom,name : name the led will be called by in sysfs entry
+
+WLED is primarily used as display backlight. Display subsystem uses
+LED triggers for WLED to control the brightness as needed.
+
+Optional properties for WLED:
+- qcom,num-strings: number of wled strings supported
+- qcom,ovp_val: over voltage protection threshold,
+ follows enum wled_ovp_threshold
+- qcom,boost_curr_lim: boot currnet limit, follows enum wled_current_bost_limit
+- 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,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"
+
+Example:
+
+ qcom,leds@d800 {
+ compatible = "qcom,leds-qpnp";
+ reg = <0xD800 0x100>;
+ linux,default-trigger = "bkl-trigger"
+ qcom,label = "wled";
+ qcom,cs-out-en;
+ qcom,op-fdbck;
+ qcom,default-state "off";
+ qcom,max-current = <25>;
+ qcom,ctrl-delay-us = <0>;
+ qcom,boost-curr-lim = <3>;
+ qcom,cp-sel = <0>;
+ qcom,switch-freq = <2>;
+ qcom,ovp-val = <2>;
+ qcom,num-strings = <1>;
+ }
diff --git a/Documentation/devicetree/bindings/media/video/msm-sensor.txt b/Documentation/devicetree/bindings/media/video/msm-sensor.txt
new file mode 100644
index 0000000..e242d51
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/video/msm-sensor.txt
@@ -0,0 +1,137 @@
+* Qualcomm MSM Sensor
+
+MSM sensor node contains properties of camera sensor
+
+Required properties:
+- compatible : should be "qcom" followed by sensor name
+ - "qcom,s5k3l1yx"
+- reg : should contain i2c slave address of the camera sensor and
+ length of data field which is 0x0
+- qcom,csi-if : should contain number of csid cores required at the receiver
+ side
+ - 1 for 2D sensor
+ - 2 for 3D sensor
+- qcom,csid-core : should contain csid core instance that will used to receive
+ sensor data
+ - 0, 1, 2, 3
+- qcom,is-vpe : should be enabled if VPE module is required for post processing
+ of this sensor
+ - 1 if required, 0 otherwise
+- qcom,sensor-name : should contain unique sensor name to differentiate from
+ other sensor
+ - "s5k3l1yx"
+- cam_vdig-supply : should contain regulator from which digital voltage is
+ supplied
+- cam_vana-supply : should contain regulator from which analog voltage is
+ supplied
+- cam_vio-supply : should contain regulator from which IO voltage is supplied
+- qcom,cam-vreg-name : should contain names of all regulators needed by this
+ sensor
+ - "cam_vdig", "cam_vana", "cam_vio", "cam_vaf"
+- qcom,cam-vreg-type : should contain regulator type for regulators mentioned in
+ qcom,cam-vreg-name property (in the same order)
+ - 0 for LDO and 1 for LVS
+- qcom,cam-vreg-min-voltage : should contain minimum voltage level for
+ regulators mentioned in qcom,cam-vreg-name property (in the same order)
+- qcom,cam-vreg-max-voltage : should contain maximum voltage level for
+ regulators mentioned in qcom,cam-vreg-name property (in the same order)
+- qcom,cam-vreg-op-mode : should contain optimum voltage level for regulators
+ mentioned in qcom,cam-vreg-name property (in the same order)
+- qcom,camera-type : should contain sensor type
+ - 0 -> back camera 2D
+ - 1 -> front camera 2D
+ - 2 -> back camera 3D
+ - 3 -> back camera int 3D
+- qcom,sensor-type : should contain format of data that sensor streams
+ - 0 -> bayer format
+ - 1 -> yuv format
+
+Optional properties:
+- qcom,flash-type : should contain flash type if flash is supported for this
+ sensor
+ - 0 if flash is not supported, 1 if flash is supported
+- qcom,mount-angle : should contain the physical mount angle of the sensor on
+ the target
+ - 0, 90, 180, 360
+- qcom,gpio-no-mux : should contain field to indicate whether gpio mux table is
+ available
+ - 1 if gpio mux is not available, 0 otherwise
+- cam_vaf-supply : should contain regulator from which AF voltage is supplied
+- gpios : should contain phandle to gpio controller node and array of
+ #gpio-cells specifying specific gpio (controller specific)
+- qcom,gpio-common-tbl-num : should contain index to gpios shared between
+ different sensors
+- qcom,gpio-common-tbl-flags : should contain direction of gpios present in
+ qcom,gpio-common-tbl-num property (in the same order)
+- qcom,gpio-common-tbl-label : should contain name of gpios present in
+ qcom,gpio-common-tbl-num property (in the same order)
+- qcom,gpio-req-tbl-num : should contain index to gpios specific to this sensor
+- qcom,gpio-req-tbl-flags : should contain direction of gpios present in
+ qcom,gpio-req-tbl-num property (in the same order)
+- qcom,gpio-req-tbl-label : should contain name of gpios present in
+ qcom,gpio-req-tbl-num property (in the same order)
+- qcom,gpio-set-tbl-num : should contain index of gpios that need to be
+ configured by msm
+- qcom,gpio-set-tbl-flags : should contain value to be configured for the gpios
+ present in qcom,gpio-set-tbl-num property (in the same order)
+- qcom,gpio-set-tbl-delay : should contain amount of delay after configuring
+ gpios as specified in gpio_set_tbl_flags property (in the same order)
+- qcom,csi-lane-assign : should contain lane assignment value to map CSIPHY
+ lanes to CSID lanes
+ - 0x4320
+- qcom,csi-lane-mask : should contain lane mask that specifies CSIPHY lanes to
+ be enabled
+- qcom,csi-phy-sel : should contain CSIPHY core instance from which CSID should
+ receive data
+- qcom,actuator-cam-name : should contain actuator cam name associated with
+ this sensor
+ - If actuator does not exist, this property should not be initialized
+ - If actuator exist, this field should indicate the index of actuator to
+ be used
+- qcom,actuator-vcm-pwd : should contain the gpio pin of vcm power to be enabled
+ for actuator
+- qcom,actuator-vcm-enable : should contain value to be set for actuator vcm
+ gpio
+
+Example:
+
+qcom,s5k3l1yx@6e {
+ compatible = "qcom,s5k3l1yx";
+ reg = <0x6e 0x0>;
+ qcom,csi-if = <1>;
+ qcom,csid-core = <0>;
+ qcom,is-vpe = <1>;
+ qcom,flash-type = <0>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "s5k3l1yx";
+ 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_vana", "cam_vio", "cam_vaf";
+ qcom,cam-vreg-type = <0 0 1 0>;
+ qcom,cam-vreg-min-voltage = <1225000 2850000 0 3000000>;
+ qcom,cam-vreg-max-voltage = <1225000 2850000 0 3000000>;
+ qcom,cam-vreg-op-mode = <105000 80000 0 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 15 0>,
+ <&msmgpio 19 0>,
+ <&msmgpio 20 0>,
+ <&msmgpio 90 0>;
+ qcom,gpio-common-tbl-num = <0 1 2>;
+ qcom,gpio-common-tbl-flags = <1 1 1>;
+ qcom,gpio-common-tbl-label = "CAMIF_MCLK", "CAMIF_I2C_DATA",
+ "CAMIF_I2C_CLK";
+ qcom,gpio-req-tbl-num = <3>;
+ qcom,gpio-req-tbl-flags = <0>;
+ qcom,gpio-req-tbl-label = "CAM_RESET1";
+ qcom,gpio-set-tbl-num = <3 3>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 4000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x1F>;
+ qcom,csi-phy-sel = <0>;
+ qcom,camera-type = <0>;
+ qcom,sensor-type = <0>;
+};
+
diff --git a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
index c674a13..5f7651a 100644
--- a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
+++ b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
@@ -5,8 +5,12 @@
Required properties:
- compatible : should be "qcom,msm-sdcc"
- - reg : should contain SDCC, BAM register map.
+ - reg : should contain SDCC, SDCC-DML and BAM register map.
+ - reg-names : indicates various resources passed to driver (via reg proptery) by name.
+ "reg-names" examples are "core_mem", "dml_mem" and "bam_mem"
- interrupts : should contain SDCC core interrupt.
+ - interrupt-names : indicates interrupts passed to driver (via interrupts property) by name.
+ "interrupt-names" examples are "core_irq", "bam_irq" and "status_irq"
- qcom,sdcc-clk-rates : specifies supported SDCC clock frequencies, Units - Hz.
- qcom,sdcc-sup-voltages: specifies supported voltage ranges for card. Should always be
specified in pairs (min, max), Units - mV.
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 84f0c24..f082a0f 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -30,6 +30,12 @@
- compatible : "qcom,msm-voip-dsp"
+* msm-pcm-voice
+
+Required properties:
+
+ - compatible : "qcom,msm-pcm-voice"
+
* msm-stub-codec
Required properties:
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index ed84219..43e87a8 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -60,7 +60,9 @@
- reg : pairs of physical base addresses and region sizes
of all the memory mapped BAM devices present
- reg-names : Register region name(s) referenced in reg above
- SSUSB BAM expects "ssusb" and "hsusb" for HSSUB BAM
+ SSUSB BAM expects "ssusb" and "hsusb" for HSSUB BAM.
+ Specify "qscratch_ram1_reg" to provide QSCRATCH's RAM1
+ register to control USB3 private memory for uses as BAM FIFOs.
- interrupts: IRQ lines for BAM devices
- interrupt-names: BAM interrupt name(s) referenced in interrupts above
SSUSB BAM expects "ssusb" and "hsusb" for HSSUB BAM
@@ -93,19 +95,25 @@
- qcom,descriptor-fifo-offset: descriptor fifo offset address
- qcom,descriptor-fifo-size: descriptor fifo size
+Optional properties :
+- qcom,ignore-core-reset-ack: If present then BAM ignores ACK from USB core
+ while performing PIPE RESET
+
Example USB BAM controller device node:
qcom,usbbam@f9304000 {
compatible = "qcom,usb-bam-msm";
reg = <0xf9304000 0x5000>,
- <0xf9a44000 0x11000>;
- reg-names = "ssusb", "hsusb";
+ <0xf9a44000 0x11000>,
+ <0xf92f880c 0x4>;
+ reg-names = "ssusb", "hsusb", "qscratch_ram1_reg";
interrupts = <0 132 0 0 135 0>;
interrupt-names = "ssusb", "hsusb";
qcom,usb-active-bam = <0>;
qcom,usb-total-bam-num = <2>;
qcom,usb-bam-num-pipes = <16>;
qcom,usb-base-address = <0xf9200000>;
+ qcom,ignore-core-reset-ack;
qcom,pipe1 {
label = "usb-to-peri-qdss-dwc3";
@@ -138,7 +146,7 @@
qcom,pipe3 {
label = "usb-to-peri-qdss-hsusb";
qcom,usb-bam-type = <1>;
- qcom,usb-bam-mem-type = <2>;
+ qcom,usb-bam-mem-type = <1>;
qcom,src-bam-physical-address = <0>;
qcom,src-bam-pipe-index = <0>;
qcom,dst-bam-physical-address = <0>;
@@ -152,14 +160,14 @@
qcom,pipe4 {
label = "peri-to-usb-qdss-hsusb";
qcom,usb-bam-type = <1>;
- qcom,usb-bam-mem-type = <2>;
+ qcom,usb-bam-mem-type = <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 = <0>;
- qcom,data-fifo-size = <0x4000>;
- qcom,descriptor-fifo-offset = <0>;
- qcom,descriptor-fifo-size = <0x1400>;
+ qcom,data-fifo-offset = <0xf4000>;
+ qcom,data-fifo-size = <0x1000>;
+ qcom,descriptor-fifo-offset = <0xf5000>;
+ qcom,descriptor-fifo-size = <0x400>;
};
};
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index a2b7dfc..bff3732 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -3,6 +3,8 @@
Required properties :
- compatible : should be "qcom,dwc-usb3-msm"
- reg : offset and length of the register set in the memory map
+ 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
@@ -18,7 +20,8 @@
Example MSM USB3.0 controller device node :
usb@f9200000 {
compatible = "qcom,dwc-usb3-msm";
- reg = <0xF9200000 0xFA000>;
+ reg = <0xF9200000 0xFA000>,
+ <0xFD4AB000 0x4>;
interrupts = <0 131 0 0 179 0>;
interrupt-names = "irq", "otg_irq";
SSUSB_VDDCX-supply = <&pm8841_s2>;
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 7930de5..d249f21 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -4,7 +4,7 @@
select HAVE_AOUT
select HAVE_DMA_API_DEBUG
select HAVE_IDE if PCI || ISA || PCMCIA
- select HAVE_DMA_CONTIGUOUS if (CPU_V6 || CPU_V6K || CPU_V7)
+ select HAVE_DMA_ATTRS
select HAVE_MEMBLOCK
select RTC_LIB
select SYS_SUPPORTS_APM_EMULATION
@@ -46,6 +46,14 @@
config ARM_HAS_SG_CHAIN
bool
+config NEED_SG_DMA_LENGTH
+ bool
+
+config ARM_DMA_USE_IOMMU
+ select NEED_SG_DMA_LENGTH
+ select ARM_HAS_SG_CHAIN
+ bool
+
config HAVE_PWM
bool
diff --git a/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
new file mode 100644
index 0000000..1f7e488
--- /dev/null
+++ b/arch/arm/boot/dts/dsi-panel-toshiba-720p-video.dtsi
@@ -0,0 +1,119 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+&mdss_dsi {
+
+ qcom,mdss_dsi_toshiba_720p_video {
+ compatible = "qcom,mdss-dsi-panel";
+ label = "toshiba 720p video mode dsi panel";
+ status = "disable";
+ qcom,enable-gpio = <&msmgpio 58 0>;
+ qcom,rst-gpio = <&pm8941_gpios 19 0>;
+ qcom,mdss-pan-res = <720 1280>;
+ qcom,mdss-pan-bpp = <24>;
+ qcom,mdss-pan-porch-values = <32 12 144 3 4 9>;
+ qcom,mdss-pan-underflow-clr = <0xff>;
+ qcom,mdss-pan-bl-ctrl = "bl_ctrl_wled";
+ qcom,mdss-pan-bl-levels = <1 255>;
+ qcom,mdss-pan-dsi-mode = <0>;
+ qcom,mdss-pan-dsi-h-pulse-mode = <0>;
+ qcom,mdss-pan-dsi-h-power-stop = <0 0 0>;
+ qcom,mdss-pan-dsi-bllp-power-stop = <1 1>;
+ qcom,mdss-pan-dsi-traffic-mode = <1>;
+ qcom,mdss-pan-dsi-dst-format = <3>;
+ qcom,mdss-pan-dsi-vc = <0>;
+ qcom,mdss-pan-dsi-rgb-swap = <0>;
+ qcom,mdss-pan-dsi-data-lanes = <1 1 1 1>;
+ qcom,mdss-pan-dsi-t-clk = <0x1b 0x04>;
+ qcom,mdss-pan-dsi-stream = <0>;
+ qcom,mdss-pan-dsi-mdp-tr = <0x0>;
+ qcom,mdss-pan-dsi-dma-tr = <0x04>;
+ qcom,mdss-pan-frame-rate = <60>;
+ qcom,panel-phy-regulatorSettings = [03 01 01 00 /* Regualotor settings */
+ 20 00 01 00];
+ qcom,panel-phy-timingSettings = [69 29 1f 00 55 55
+ 19 2a 2a 03 04 00];
+ qcom,panel-phy-strengthCtrl = [77 06];
+ qcom,panel-phy-bistCtrl = [00 00 01 ff /* BIST Ctrl settings */
+ 00 00];
+ qcom,panel-phy-laneConfig = [05 c2 00 00 00 00 00 01 75 /* lane0 config */
+ 05 c2 00 00 00 00 00 01 75 /* lane1 config */
+ 05 c2 00 00 00 00 00 01 75 /* lane2 config */
+ 05 c2 00 00 00 00 00 01 75 /* lane3 config */
+ 00 c2 00 00 00 00 00 01 97]; /* Clk ln config */
+
+ qcom,panel-on-cmds = [23 01 00 00 0a 02 b0 00
+ 23 01 00 00 0a 02 b2 00
+ 23 01 00 00 0a 02 b3 0c
+ 23 01 00 00 0a 02 b4 02
+ 29 01 00 00 00 06
+ c0 40 02 7f c8 08
+ 29 01 00 00 00 10
+ c1 00 a8 00 00 00
+ 00 00 9d 08 27 00
+ 00 00 00 00
+ 29 01 00 00 00 06
+ c2 00 00 09 00 00
+ 23 01 00 00 0a 02 c3 04
+ 29 01 00 00 00 04
+ c4 4d 83 00
+ 29 01 00 00 00 0b
+ c6 12 00 08 71 00
+ 00 00 80 00 04
+ 23 01 00 00 0a 02 c7 22
+ 29 01 00 00 00 05
+ c8 4c 0c 0c 0c
+ 29 01 00 00 00 0e
+ c9 00 40 00 16 32
+ 2e 3a 43 3e 3c 45
+ 79 3f
+ 29 01 00 00 00 0e
+ ca 00 46 1a 23 21
+ 1c 25 31 2d 49 5f
+ 7f 3f
+ 29 01 00 00 00 0e
+ cb 00 4c 20 3a 42
+ 40 47 4b 42 3e 46
+ 7e 3f
+ 29 01 00 00 00 0e
+ cc 00 41 19 21 1d
+ 14 18 1f 1d 25 3f
+ 73 3f
+ 29 01 00 00 00 0e
+ cd 23 79 5a 5f 57
+ 4c 51 51 45 3f 4b
+ 7f 3f
+ 29 01 00 00 00 0e
+ ce 00 40 14 20 1a
+ 0e 0e 13 08 00 05
+ 46 1c
+ 29 01 00 00 00 04
+ d0 6a 64 01
+ 29 01 00 00 00 03 d1 77 d4
+ 23 01 00 00 0a 02 d3 33
+ 29 01 00 00 00 03 d5 0f 0f
+ 29 01 00 00 00 07
+ d8 34 64 23 25 62
+ 32
+ 29 01 00 00 00 0c
+ de 10 7b 11 0a 00
+ 00 00 00 00 00 00
+ 29 01 00 00 00 09
+ fd 04 55 53 00 70
+ ff 10 73
+ 23 01 00 00 0a 02 e2 00
+ 05 01 00 00 78 02 11 00
+ 05 01 00 00 32 02 29 00];
+ qcom,panel-off-cmds = [05 01 00 00 32 02 28 00
+ 05 01 00 00 78 02 10 00];
+ };
+};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 84bc68b..030d0e3 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -48,6 +48,24 @@
};
};
+ clkdiv@5b00 {
+ reg = <0x5b00 0x100>;
+ compatible = "qcom,qpnp-clkdiv";
+ qcom,cxo-freq = <19200000>;
+ };
+
+ clkdiv@5c00 {
+ reg = <0x5c00 0x100>;
+ compatible = "qcom,qpnp-clkdiv";
+ qcom,cxo-freq = <19200000>;
+ };
+
+ clkdiv@5d00 {
+ reg = <0x5d00 0x1000>;
+ compatible = "qcom,qpnp-clkdiv";
+ qcom,cxo-freq = <19200000>;
+ };
+
pm8941_gpios {
spmi-dev-container;
compatible = "qcom,qpnp-pin";
diff --git a/arch/arm/boot/dts/msm8974-camera.dtsi b/arch/arm/boot/dts/msm8974-camera.dtsi
index 0375e93..cf4f098 100644
--- a/arch/arm/boot/dts/msm8974-camera.dtsi
+++ b/arch/arm/boot/dts/msm8974-camera.dtsi
@@ -19,6 +19,7 @@
reg = <0xfd8C0000 0x10000>;
reg-names = "server";
};
+
qcom,csiphy@fda0ac00 {
cell-index = <0>;
compatible = "qcom,csiphy";
@@ -27,6 +28,7 @@
interrupts = <0 78 0>;
interrupt-names = "csiphy";
};
+
qcom,csiphy@fda0b000 {
cell-index = <1>;
compatible = "qcom,csiphy";
@@ -35,6 +37,7 @@
interrupts = <0 79 0>;
interrupt-names = "csiphy";
};
+
qcom,csiphy@fda0b400 {
cell-index = <2>;
compatible = "qcom,csiphy";
@@ -43,6 +46,7 @@
interrupts = <0 80 0>;
interrupt-names = "csiphy";
};
+
qcom,csid@fda08000 {
cell-index = <0>;
compatible = "qcom,csid";
@@ -50,7 +54,9 @@
reg-names = "csid";
interrupts = <0 51 0>;
interrupt-names = "csid";
+ mipi_csi_vdd-supply = <&pm8941_l12>;
};
+
qcom,csid@fda08400 {
cell-index = <1>;
compatible = "qcom,csid";
@@ -58,7 +64,9 @@
reg-names = "csid";
interrupts = <0 52 0>;
interrupt-names = "csid";
+ mipi_csi_vdd-supply = <&pm8941_l12>;
};
+
qcom,csid@fda08800 {
cell-index = <2>;
compatible = "qcom,csid";
@@ -66,7 +74,9 @@
reg-names = "csid";
interrupts = <0 53 0>;
interrupt-names = "csid";
+ mipi_csi_vdd-supply = <&pm8941_l12>;
};
+
qcom,csid@fda08C00 {
cell-index = <3>;
compatible = "qcom,csid";
@@ -74,7 +84,9 @@
reg-names = "csid";
interrupts = <0 54 0>;
interrupt-names = "csid";
+ mipi_csi_vdd-supply = <&pm8941_l12>;
};
+
qcom,ispif@fda0A000 {
cell-index = <0>;
compatible = "qcom,ispif";
@@ -83,32 +95,29 @@
interrupts = <0 55 0>;
interrupt-names = "ispif";
};
- qcom,cci@fda0C000 {
- cell-index = <0>;
- compatible = "qcom,cci";
- reg = <0xfda0C000 0x1000>;
- reg-names = "cci";
- interrupts = <0 50 0>;
- interrupt-names = "cci";
- };
+
qcom,vfe@fda10000 {
cell-index = <0>;
compatible = "qcom,vfe40";
- reg = <0xfda10000 0x1000>;
- reg-names = "vfe";
+ reg = <0xfda10000 0x1000>,
+ <0xfda40000 0x200>;
+ reg-names = "vfe", "vfe_vbif";
interrupts = <0 57 0>;
interrupt-names = "vfe";
vdd-supply = <&gdsc_vfe>;
};
+
qcom,vfe@fda14000 {
cell-index = <1>;
compatible = "qcom,vfe40";
- reg = <0xfda14000 0x1000>;
- reg-names = "vfe";
+ reg = <0xfda14000 0x1000>,
+ <0xfda40000 0x200>;
+ reg-names = "vfe", "vfe_vbif";
interrupts = <0 58 0>;
interrupt-names = "vfe";
vdd-supply = <&gdsc_vfe>;
};
+
qcom,jpeg@fda1c000 {
cell-index = <0>;
compatible = "qcom,jpeg";
@@ -117,6 +126,7 @@
interrupts = <0 59 0>;
interrupt-names = "jpeg";
};
+
qcom,jpeg@fda20000 {
cell-index = <1>;
compatible = "qcom,jpeg";
@@ -125,6 +135,7 @@
interrupts = <0 60 0>;
interrupt-names = "jpeg";
};
+
qcom,jpeg@fda24000 {
cell-index = <2>;
compatible = "qcom,jpeg";
@@ -133,12 +144,14 @@
interrupts = <0 61 0>;
interrupt-names = "jpeg";
};
+
qcom,irqrouter@fda00000 {
cell-index = <0>;
compatible = "qcom,irqrouter";
reg = <0xfda00000 0x100>;
reg-names = "irqrouter";
};
+
qcom,cpp@fda04000 {
cell-index = <0>;
compatible = "qcom,cpp";
@@ -148,4 +161,98 @@
interrupt-names = "cpp";
vdd-supply = <&gdsc_vfe>;
};
+
+ qcom,cci@fda0C000 {
+ cell-index = <0>;
+ compatible = "qcom,cci";
+ reg = <0xfda0C000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ reg-names = "cci";
+ interrupts = <0 50 0>;
+ interrupt-names = "cci";
+
+ qcom,camera@6e {
+ compatible = "qcom,s5k3l1yx";
+ reg = <0x6e 0x0>;
+ qcom,csi-if = <1>;
+ qcom,csid-core = <0>;
+ qcom,is-vpe = <1>;
+ qcom,flash-type = <0>;
+ qcom,mount-angle = <90>;
+ qcom,sensor-name = "s5k3l1yx";
+ 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_vana", "cam_vio",
+ "cam_vaf";
+ qcom,cam-vreg-type = <0 0 1 0>;
+ qcom,cam-vreg-min-voltage = <1225000 2850000 0 3000000>;
+ qcom,cam-vreg-max-voltage = <1225000 2850000 0 3000000>;
+ qcom,cam-vreg-op-mode = <105000 80000 0 100000>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 15 0>,
+ <&msmgpio 19 0>,
+ <&msmgpio 20 0>,
+ <&msmgpio 90 0>;
+ qcom,gpio-common-tbl-num = <0 1 2>;
+ qcom,gpio-common-tbl-flags = <1 1 1>;
+ qcom,gpio-common-tbl-label = "CAMIF_MCLK",
+ "CAMIF_I2C_DATA",
+ "CAMIF_I2C_CLK";
+ qcom,gpio-req-tbl-num = <3>;
+ qcom,gpio-req-tbl-flags = <0>;
+ qcom,gpio-req-tbl-label = "CAM_RESET1";
+ qcom,gpio-set-tbl-num = <3 3>;
+ 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,csi-phy-sel = <0>;
+ qcom,camera-type = <0>;
+ qcom,sensor-type = <0>;
+ };
+
+ qcom,camera@6c {
+ compatible = "qcom,ov2720";
+ reg = <0x6c 0x0>;
+ qcom,csi-if = <1>;
+ qcom,csid-core = <1>;
+ qcom,is-vpe = <1>;
+ qcom,flash-type = <0>;
+ qcom,mount-angle = <0>;
+ qcom,sensor-name = "ov2720";
+ cam_vdig-supply = <&pm8941_l3>;
+ cam_vana-supply = <&pm8941_l17>;
+ cam_vio-supply = <&pm8941_lvs3>;
+ 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>;
+ qcom,cam-vreg-max-voltage = <1225000 2850000 0>;
+ qcom,cam-vreg-op-mode = <105000 80000 0>;
+ qcom,gpio-no-mux = <0>;
+ gpios = <&msmgpio 16 0>,
+ <&msmgpio 19 0>,
+ <&msmgpio 20 0>,
+ <&msmgpio 92 0>;
+ qcom,gpio-common-tbl-num = <0 1 2>;
+ qcom,gpio-common-tbl-flags = <1 1 1>;
+ qcom,gpio-common-tbl-label = "CAMIF_MCLK",
+ "CAMIF_I2C_DATA",
+ "CAMIF_I2C_CLK";
+ qcom,gpio-req-tbl-num = <3>;
+ qcom,gpio-req-tbl-flags = <0>;
+ qcom,gpio-req-tbl-label = "CAM_RESET1";
+ qcom,gpio-set-tbl-num = <3 3>;
+ qcom,gpio-set-tbl-flags = <0 2>;
+ qcom,gpio-set-tbl-delay = <1000 4000>;
+ qcom,csi-lane-assign = <0x4320>;
+ qcom,csi-lane-mask = <0x7>;
+ qcom,csi-phy-sel = <1>;
+ qcom,camera-type = <0>;
+ qcom,sensor-type = <0>;
+ };
+ };
};
diff --git a/arch/arm/boot/dts/msm8974-cdp.dts b/arch/arm/boot/dts/msm8974-cdp.dts
index bfe24d2..e764e01 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-cdp.dts
@@ -13,6 +13,7 @@
/dts-v1/;
/include/ "msm8974.dtsi"
+/include/ "dsi-panel-toshiba-720p-video.dtsi"
/ {
model = "Qualcomm MSM 8974 CDP";
@@ -22,4 +23,23 @@
serial@f991e000 {
status = "ok";
};
+
+ qcom,mdss_dsi@fd922800 {
+ qcom,mdss_dsi_toshiba_720p_video {
+ status = "ok";
+ };
+ };
+};
+
+&sdcc2 {
+ #address-cells = <0>;
+ interrupt-parent = <&sdcc2>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 125 0
+ 1 &intc 0 220 0
+ 2 &msmgpio 62 0x3>;
+ interrupt-names = "core_irq", "bam_irq", "status_irq";
+ cd-gpios = <&msmgpio 62 0x1>;
};
diff --git a/arch/arm/boot/dts/msm8974-clock.dtsi b/arch/arm/boot/dts/msm8974-clock.dtsi
new file mode 100644
index 0000000..bdc5d9b
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-clock.dtsi
@@ -0,0 +1,26 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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.
+ */
+
+&spmi_bus {
+
+ qcom,pm8941@0 {
+
+ pm8941_clkdiv1: clkdiv@5b00 {
+ };
+
+ pm8941_clkdiv2: clkdiv@5c00 {
+ };
+
+ pm8941_clkdiv3: clkdiv@5d00 {
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msm8974-gpio.dtsi b/arch/arm/boot/dts/msm8974-gpio.dtsi
index 5d93fa3..b36859e 100644
--- a/arch/arm/boot/dts/msm8974-gpio.dtsi
+++ b/arch/arm/boot/dts/msm8974-gpio.dtsi
@@ -205,6 +205,12 @@
mpp@a400 {
status = "ok";
+ /* SPI_ETH config */
+ qcom,mode = <1>; /* DIG_OUT */
+ qcom,output-type = <0>; /* CMOS */
+ qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+ qcom,src-select = <0>; /* CONSTANT */
+ qcom,master-en = <1>; /* ENABLE MPP */
};
mpp@a500 {
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index d14e014..dbaa492 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -13,15 +13,20 @@
/ {
qcom,mdss_mdp@fd900000 {
compatible = "qcom,mdss_mdp";
- reg = <0xfd900000 0x22100>;
+ reg = <0xfd900000 0x22100>,
+ <0xfd924000 0x1000>;
+ reg-names = "mdp_phys", "vbif_phys";
interrupts = <0 72 0>;
vdd-supply = <&gdsc_mdss>;
};
mdss_dsi: qcom,mdss_dsi@fd922800 {
compatible = "qcom,msm-mdss-dsi";
- reg = <0xfd922800 0x5ac>,
+ reg = <0xfd922800 0x600>,
<0xfd8c2000 0x01000>;
+ vdd-supply = <&pm8941_l22>;
+ vdd_io-supply = <&pm8941_l12>;
+ vreg-supply = <&pm8941_l2>;
};
qcom,mdss_wb_panel {
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index eb269eb..1fd96f9 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -10,38 +10,13 @@
* GNU General Public License for more details.
*/
+
+/* QPNP controlled regulators: */
+
&spmi_bus {
+
qcom,pm8941@1 {
- pm8941_s1: regulator@1400 {
- regulator-min-microvolt = <1300000>;
- regulator-max-microvolt = <1300000>;
- qcom,enable-time = <500>;
- qcom,pull-down-enable = <1>;
- regulator-always-on;
- status = "okay";
- };
-
- regulator@1700 {
- regulator-min-microvolt = <2150000>;
- regulator-max-microvolt = <2150000>;
- qcom,enable-time = <500>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- regulator-name = "8941_s2_local";
- regulator-always-on;
- qcom,system-load = <100000>;
- };
-
- pm8941_s3: regulator@1a00 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,enable-time = <500>;
- qcom,pull-down-enable = <1>;
- regulator-always-on;
- status = "okay";
- };
-
pm8941_boost: regulator@a000 {
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
@@ -49,216 +24,6 @@
status = "okay";
};
- pm8941_l1: regulator@4000 {
- parent-supply = <&pm8941_s1>;
- regulator-min-microvolt = <1225000>;
- regulator-max-microvolt = <1225000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- regulator-always-on;
- status = "okay";
- };
-
- pm8941_l2: regulator@4100 {
- parent-supply = <&pm8941_s3>;
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l3: regulator@4200 {
- parent-supply = <&pm8941_s1>;
- regulator-min-microvolt = <1225000>;
- regulator-max-microvolt = <1225000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l4: regulator@4300 {
- parent-supply = <&pm8941_s1>;
- regulator-min-microvolt = <1225000>;
- regulator-max-microvolt = <1225000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l6: regulator@4500 {
- parent-supply = <&pm8941_s2>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l8: regulator@4700 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l9: regulator@4800 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l10: regulator@4900 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l11: regulator@4a00 {
- parent-supply = <&pm8941_s1>;
- regulator-min-microvolt = <1300000>;
- regulator-max-microvolt = <1300000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- regulator@4b00 {
- parent-supply = <&pm8941_s2>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- regulator-name = "8941_l12_local";
- regulator-always-on;
- qcom,system-load = <100000>;
- };
-
- pm8941_l13: regulator@4c00 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l14: regulator@4d00 {
- parent-supply = <&pm8941_s2>;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l15: regulator@4e00 {
- parent-supply = <&pm8941_s2>;
- regulator-min-microvolt = <2050000>;
- regulator-max-microvolt = <2050000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l16: regulator@4f00 {
- regulator-min-microvolt = <2700000>;
- regulator-max-microvolt = <2700000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l17: regulator@5000 {
- regulator-min-microvolt = <2850000>;
- regulator-max-microvolt = <2850000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l18: regulator@5100 {
- regulator-min-microvolt = <2850000>;
- regulator-max-microvolt = <2850000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l19: regulator@5200 {
- regulator-min-microvolt = <2900000>;
- regulator-max-microvolt = <2900000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l20: regulator@5300 {
- regulator-min-microvolt = <2950000>;
- regulator-max-microvolt = <2950000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l21: regulator@5400 {
- regulator-min-microvolt = <2950000>;
- regulator-max-microvolt = <2950000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l22: regulator@5500 {
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l23: regulator@5600 {
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_l24: regulator@5700 {
- regulator-min-microvolt = <3075000>;
- regulator-max-microvolt = <3075000>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_lvs1: regulator@8000 {
- parent-supply = <&pm8941_s3>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_lvs2: regulator@8100 {
- parent-supply = <&pm8941_s3>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
- pm8941_lvs3: regulator@8200 {
- parent-supply = <&pm8941_s3>;
- qcom,enable-time = <200>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
-
pm8941_mvs1: regulator@8300 {
parent-supply = <&pm8941_boost>;
qcom,enable-time = <200>;
@@ -273,48 +38,6 @@
status = "okay";
};
};
-
- qcom,pm8841@5 {
-
- regulator@1400 {
- regulator-min-microvolt = <1050000>;
- regulator-max-microvolt = <1050000>;
- qcom,enable-time = <500>;
- qcom,pull-down-enable = <1>;
- regulator-always-on;
- status = "okay";
- regulator-name = "8841_s1_local";
- qcom,system-load = <100000>;
- };
-
- regulator@1700 {
- regulator-min-microvolt = <1050000>;
- regulator-max-microvolt = <1050000>;
- qcom,enable-time = <500>;
- qcom,pull-down-enable = <1>;
- regulator-always-on;
- regulator-name = "8841_s2_local";
- qcom,system-load = <100000>;
- status = "okay";
- };
-
- pm8841_s3: regulator@1a00 {
- regulator-min-microvolt = <1050000>;
- regulator-max-microvolt = <1050000>;
- qcom,enable-time = <500>;
- qcom,pull-down-enable = <1>;
- regulator-always-on;
- status = "okay";
- };
-
- pm8841_s4: regulator@1d00 {
- regulator-min-microvolt = <900000>;
- regulator-max-microvolt = <900000>;
- qcom,enable-time = <500>;
- qcom,pull-down-enable = <1>;
- status = "okay";
- };
- };
};
/* RPM controlled regulators: */
@@ -364,6 +87,39 @@
};
};
+ rpm-regulator-smpb3 {
+ status = "okay";
+ pm8841_s3: regulator-s3 {
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ qcom,init-voltage = <1050000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-smpb4 {
+ status = "okay";
+ pm8841_s4: regulator-s4 {
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ qcom,init-voltage = <900000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-smpa1 {
+ status = "okay";
+ pm8941_s1: regulator-s1 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,init-voltage = <1300000>;
+ qcom,init-current = <100>;
+ qcom,system-load = <100000>;
+ regulator-always-on;
+ status = "okay";
+ };
+ };
+
rpm-regulator-smpa2 {
status = "okay";
qcom,allow-atomic = <1>;
@@ -383,6 +139,140 @@
};
};
+ rpm-regulator-smpa3 {
+ status = "okay";
+ pm8941_s3: regulator-s3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ qcom,init-current = <100>;
+ qcom,system-load = <100000>;
+ regulator-always-on;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa1 {
+ status = "okay";
+ pm8941_l1: regulator-l1 {
+ parent-supply = <&pm8941_s1>;
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,init-voltage = <1225000>;
+ qcom,init-current = <10>;
+ qcom,system-load = <10000>;
+ regulator-always-on;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa2 {
+ status = "okay";
+ pm8941_l2: regulator-l2 {
+ parent-supply = <&pm8941_s3>;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ qcom,init-voltage = <1200000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa3 {
+ status = "okay";
+ pm8941_l3: regulator-l3 {
+ parent-supply = <&pm8941_s1>;
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,init-voltage = <1225000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa4 {
+ status = "okay";
+ pm8941_l4: regulator-l4 {
+ parent-supply = <&pm8941_s1>;
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,init-voltage = <1225000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa5 {
+ status = "okay";
+ pm8941_l5: regulator-l5 {
+ parent-supply = <&pm8941_s2>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa6 {
+ status = "okay";
+ pm8941_l6: regulator-l6 {
+ parent-supply = <&pm8941_s2>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa7 {
+ status = "okay";
+ pm8941_l7: regulator-l7 {
+ parent-supply = <&pm8941_s2>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa8 {
+ status = "okay";
+ pm8941_l8: regulator-l8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa9 {
+ status = "okay";
+ pm8941_l9: regulator-l9 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa10 {
+ status = "okay";
+ pm8941_l10: regulator-l10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa11 {
+ status = "okay";
+ pm8941_l11: regulator-l11 {
+ parent-supply = <&pm8941_s1>;
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,init-voltage = <1300000>;
+ status = "okay";
+ };
+ };
+
rpm-regulator-ldoa12 {
status = "okay";
qcom,allow-atomic = <1>;
@@ -402,6 +292,152 @@
compatible = "qcom,rpm-regulator-smd";
};
};
+
+ rpm-regulator-ldoa13 {
+ status = "okay";
+ pm8941_l13: regulator-l13 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa14 {
+ status = "okay";
+ pm8941_l14: regulator-l14 {
+ parent-supply = <&pm8941_s2>;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,init-voltage = <1800000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa15 {
+ status = "okay";
+ pm8941_l15: regulator-l15 {
+ parent-supply = <&pm8941_s2>;
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ qcom,init-voltage = <2050000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa16 {
+ status = "okay";
+ pm8941_l16: regulator-l16 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ qcom,init-voltage = <2700000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa17 {
+ status = "okay";
+ pm8941_l17: regulator-l17 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ qcom,init-voltage = <2850000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa18 {
+ status = "okay";
+ pm8941_l18: regulator-l18 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ qcom,init-voltage = <2850000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa19 {
+ status = "okay";
+ pm8941_l19: regulator-l19 {
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ qcom,init-voltage = <2900000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa20 {
+ status = "okay";
+ pm8941_l20: regulator-l20 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa21 {
+ status = "okay";
+ pm8941_l21: regulator-l21 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ qcom,init-voltage = <2950000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa22 {
+ status = "okay";
+ pm8941_l22: regulator-l22 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ qcom,init-voltage = <3000000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa23 {
+ status = "okay";
+ pm8941_l23: regulator-l23 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ qcom,init-voltage = <3000000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-ldoa24 {
+ status = "okay";
+ pm8941_l24: regulator-l24 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ qcom,init-voltage = <3075000>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-vsa1 {
+ status = "okay";
+ pm8941_lvs1: regulator-lvs1 {
+ parent-supply = <&pm8941_s3>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-vsa2 {
+ status = "okay";
+ pm8941_lvs2: regulator-lvs2 {
+ parent-supply = <&pm8941_s3>;
+ status = "okay";
+ };
+ };
+
+ rpm-regulator-vsa3 {
+ status = "okay";
+ pm8941_lvs3: regulator-lvs3 {
+ parent-supply = <&pm8941_s3>;
+ status = "okay";
+ };
+ };
};
/ {
@@ -436,4 +472,11 @@
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <1100000>;
};
+
+ spi_eth_vreg: spi_eth_phy_vreg {
+ compatible = "regulator-fixed";
+ regulator-name = "ethernet_phy";
+ gpio = <&pm8941_mpps 5 0>;
+ enable-active-high;
+ };
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 5620648..b4ac3d6 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -98,13 +98,15 @@
qcom,hsusb-otg-disable-reset;
};
- qcom,sdcc@f9824000 {
+ sdcc1: qcom,sdcc@f9824000 {
cell-index = <1>; /* SDC1 eMMC slot */
compatible = "qcom,msm-sdcc";
- reg = <0xf9824000 0x1000>;
- reg-names = "core_mem";
- interrupts = <0 123 0>;
- interrupt-names = "core_irq";
+ reg = <0xf9824000 0x800>,
+ <0xf9824800 0x100>,
+ <0xf9804000 0x7000>;
+ reg-names = "core_mem", "dml_mem", "bam_mem";
+ interrupts = <0 123 0>, <0 137 0>;
+ interrupt-names = "core_irq", "bam_irq";
vdd-supply = <&pm8941_l20>;
vdd-io-supply = <&pm8941_s3>;
@@ -127,13 +129,15 @@
qcom,sdcc-bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
};
- qcom,sdcc@f98a4000 {
+ sdcc2: qcom,sdcc@f98a4000 {
cell-index = <2>; /* SDC2 SD card slot */
compatible = "qcom,msm-sdcc";
- reg = <0xf98a4000 0x1000>;
- reg-names = "core_mem";
- interrupts = <0 125 0>;
- interrupt-names = "core_irq";
+ reg = <0xf98a4000 0x800>,
+ <0xf98a4800 0x100>,
+ <0xf9884000 0x7000>;
+ reg-names = "core_mem", "dml_mem", "bam_mem";
+ interrupts = <0 125 0>, <0 220 0>;
+ interrupt-names = "core_irq", "bam_irq";
vdd-supply = <&pm8941_l21>;
vdd-io-supply = <&pm8941_l13>;
@@ -158,13 +162,15 @@
qcom,sdcc-current-limit = <800>;
};
- qcom,sdcc@f9864000 {
+ sdcc3: qcom,sdcc@f9864000 {
cell-index = <3>; /* SDC3 SDIO slot */
compatible = "qcom,msm-sdcc";
- reg = <0xf9864000 0x1000>;
- reg-names = "core_mem";
- interrupts = <0 127 0>;
- interrupt-names = "core_irq";
+ reg = <0xf9864000 0x800>,
+ <0xf9864800 0x100>,
+ <0xf9844000 0x7000>;
+ reg-names = "core_mem", "dml_mem", "bam_mem";
+ interrupts = <0 127 0>, <0 223 0>;
+ interrupt-names = "core_irq", "bam_irq";
gpios = <&msmgpio 40 0>, /* CLK */
<&msmgpio 39 0>, /* CMD */
@@ -181,13 +187,15 @@
status = "disable";
};
- qcom,sdcc@f98e4000 {
+ sdcc4: qcom,sdcc@f98e4000 {
cell-index = <4>; /* SDC4 SDIO slot */
compatible = "qcom,msm-sdcc";
- reg = <0xf98e4000 0x1000>;
- reg-names = "core_mem";
- interrupts = <0 129 0>;
- interrupt-names = "core_irq";
+ reg = <0xf98e4000 0x800>,
+ <0xf98e4800 0x100>,
+ <0xf98c4000 0x7000>;
+ reg-names = "core_mem", "dml_mem", "bam_mem";
+ interrupts = <0 129 0>, <0 226 0>;
+ interrupt-names = "core_irq", "bam_irq";
gpios = <&msmgpio 93 0>, /* CLK */
<&msmgpio 91 0>, /* CMD */
@@ -214,13 +222,6 @@
};
- spi@f9924000 {
- compatible = "qcom,spi-qup-v2";
- reg = <0xf9924000 0x1000>;
- interrupts = <0 96 0>;
- spi-max-frequency = <25000000>;
- };
-
slim@fe12f000 {
cell-index = <1>;
compatible = "qcom,slim-msm";
@@ -428,17 +429,108 @@
<0x1e70008c>; /* LPG_CHAN12 */
};
- i2c@f9966000 {
+ i2c@f9967000 {
cell-index = <0>;
compatible = "qcom,i2c-qup";
- reg = <0Xf9966000 0x1000>;
+ reg = <0Xf9967000 0x1000>;
reg-names = "qup_phys_addr";
- interrupts = <0 104 0>;
+ interrupts = <0 105 0>;
interrupt-names = "qup_err_intr";
qcom,i2c-bus-freq = <100000>;
qcom,i2c-src-freq = <24000000>;
};
+ i2c@f9924000 {
+ cell-index = <2>;
+ compatible = "qcom,i2c-qup";
+ reg = <0xf9924000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "qup_phys_addr";
+ interrupts = <0 96 0>;
+ interrupt-names = "qup_err_intr";
+ qcom,i2c-bus-freq = <100000>;
+ qcom,i2c-src-freq = <24000000>;
+
+ atmel_mxt_ts@4a {
+ compatible = "atmel,mxt-ts";
+ reg = <0x4a>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <61 0x2>;
+ vdd_ana-supply = <&pm8941_l18>;
+ vcc_i2c-supply = <&pm8941_lvs1>;
+ atmel,reset-gpio = <&msmgpio 60 0x00>;
+ atmel,irq-gpio = <&msmgpio 61 0x00>;
+ atmel,panel-coords = <0 0 760 1424>;
+ atmel,display-coords = <0 0 720 1280>;
+ atmel,i2c-pull-up = <1>;
+ atmel,cfg_1 {
+ atmel,family-id = <0x82>;
+ atmel,variant-id = <0x19>;
+ atmel,version = <0x10>;
+ atmel,build = <0xaa>;
+ atmel,config = [
+ /* Object 6, Instance = 0 */
+ 00 00 00 00 00 00
+ /* Object 38, Instance = 0 */
+ 15 00 02 10 08 0C 00 00
+ /* Object 7, Instance = 0 */
+ FF FF 32 03
+ /* Object 8, Instance = 0 */
+ 0F 00 0A 0A 00 00 0A 00 00 00
+ /* Object 9, Instance = 0 */
+ 83 00 00 18 0E 00 70 32 02 01
+ 00 03 01 01 05 0A 0A 0A 90 05
+ F8 02 00 00 0F 0F 00 00 48 2D
+ 07 0C 00 00 00 00
+ /* Object 15, Instance = 0 */
+ 00 00 00 00 00 00 00 00 00 00
+ 00
+ /* Object 18, Instance = 0 */
+ 00 00
+ /* Object 19, Instance = 0 */
+ 00 00 00 00 00 00
+ /* Object 23, Instance = 0 */
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00
+ /* Object 25, Instance = 0 */
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00 00 00 00
+ /* Object 40, Instance = 0 */
+ 00 00 00 00 00
+ /* Object 42, Instance = 0 */
+ 00 00 00 00 00 00 00 00 00 00
+ /* Object 46, Instance = 0 */
+ 00 00 10 10 00 00 03 00 00 01
+ /* Object 47, Instance = 0 */
+ 08 0A 28 0A 02 0A 00 8C 00 20
+ 00 00 00
+ /* Object 55, Instance = 0 */
+ 00 00 00 00 00 00
+ /* Object 56, Instance = 0 */
+ 03 00 01 18 05 05 05 05 05 05
+ 05 05 05 05 05 05 05 05 05 05
+ 05 05 05 05 05 05 05 05 00 00
+ 00 00 00 00 00 00 00 00 00 00
+ 00 00
+ /* Object 57, Instance = 0 */
+ 00 00 00
+ /* Object 61, Instance = 0 */
+ 00 00 00 00 00
+ /* Object 61, Instance = 1 */
+ 00 00 00 00 00
+ /* Object 62, Instance = 0 */
+ 7F 03 00 16 00 00 00 00 00 00
+ 04 08 10 18 05 00 0A 05 05 50
+ 14 19 34 1A 64 00 00 04 40 00
+ 00 00 00 00 30 32 02 00 01 00
+ 05 00 00 00 00 00 00 00 00 00
+ 00 00 0C 00
+ ];
+ };
+ };
+ };
+
qcom,acpuclk@f9000000 {
compatible = "qcom,acpuclk-8974";
krait0-supply = <&krait0_vreg>;
@@ -467,7 +559,8 @@
qcom,ssusb@f9200000 {
compatible = "qcom,dwc-usb3-msm";
- reg = <0xf9200000 0xfc000>;
+ reg = <0xf9200000 0xfc000>,
+ <0xfd4ab000 0x4>;
interrupts = <0 131 0 0 179 0>;
interrupt-names = "irq", "otg_irq";
SSUSB_VDDCX-supply = <&pm8841_s2>;
@@ -490,6 +583,10 @@
qcom,firmware-name = "adsp";
};
+ qcom,msm-adsp-loader {
+ compatible = "qcom,adsp-loader";
+ };
+
qcom,msm-pcm {
compatible = "qcom,msm-pcm-dsp";
};
@@ -510,6 +607,10 @@
compatible = "qcom,msm-voip-dsp";
};
+ qcom,msm-pcm-voice {
+ compatible = "qcom,msm-pcm-voice";
+ };
+
qcom,msm-stub-codec {
compatible = "qcom,msm-stub-codec";
};
@@ -727,14 +828,16 @@
qcom,usbbam@f9304000 {
compatible = "qcom,usb-bam-msm";
reg = <0xf9304000 0x5000>,
- <0xf9a44000 0x11000>;
- reg-names = "ssusb", "hsusb";
+ <0xf9a44000 0x11000>,
+ <0xf92f880c 0x4>;
+ reg-names = "ssusb", "hsusb", "qscratch_ram1_reg";
interrupts = <0 132 0 0 135 0>;
interrupt-names = "ssusb", "hsusb";
qcom,usb-active-bam = <0>;
qcom,usb-total-bam-num = <2>;
qcom,usb-bam-num-pipes = <16>;
qcom,usb-base-address = <0xf9200000>;
+ qcom,ignore-core-reset-ack;
qcom,pipe1 {
label = "usb-to-peri-qdss-dwc3";
@@ -767,7 +870,7 @@
qcom,pipe3 {
label = "usb-to-peri-qdss-hsusb";
qcom,usb-bam-type = <1>;
- qcom,usb-bam-mem-type = <2>;
+ qcom,usb-bam-mem-type = <1>;
qcom,src-bam-physical-address = <0>;
qcom,src-bam-pipe-index = <0>;
qcom,dst-bam-physical-address = <0>;
@@ -781,15 +884,15 @@
qcom,pipe4 {
label = "peri-to-usb-qdss-hsusb";
qcom,usb-bam-type = <1>;
- qcom,usb-bam-mem-type = <2>;
+ qcom,usb-bam-mem-type = <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 = <0>;
- qcom,data-fifo-size = <0x4000>;
- qcom,descriptor-fifo-offset = <0>;
- qcom,descriptor-fifo-size = <0x1400>;
+ qcom,data-fifo-offset = <0xf4000>;
+ qcom,data-fifo-size = <0x1000>;
+ qcom,descriptor-fifo-offset = <0xf5000>;
+ qcom,descriptor-fifo-size = <0x400>;
};
};
@@ -839,3 +942,4 @@
/include/ "msm-pm8941.dtsi"
/include/ "msm8974-regulator.dtsi"
/include/ "msm8974-gpio.dtsi"
+/include/ "msm8974-clock.dtsi"
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 32e9cc6..9d7eb53 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -308,8 +308,9 @@
* substitute the safe buffer for the unsafe one.
* (basically move the buffer from an unsafe area to a safe one)
*/
-dma_addr_t __dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size, enum dma_data_direction dir)
+static dma_addr_t dmabounce_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
{
dma_addr_t dma_addr;
int ret;
@@ -324,7 +325,7 @@
return DMA_ERROR_CODE;
if (ret == 0) {
- __dma_page_cpu_to_dev(page, offset, size, dir);
+ arm_dma_ops.sync_single_for_device(dev, dma_addr, size, dir);
return dma_addr;
}
@@ -335,7 +336,6 @@
return map_single(dev, page_address(page) + offset, size, dir);
}
-EXPORT_SYMBOL(__dma_map_page);
/*
* see if a mapped address was really a "safe" buffer and if so, copy
@@ -343,8 +343,8 @@
* the safe buffer. (basically return things back to the way they
* should be)
*/
-void __dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
- enum dma_data_direction dir)
+static void dmabounce_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
{
struct safe_buffer *buf;
@@ -353,16 +353,14 @@
buf = find_safe_buffer_dev(dev, dma_addr, __func__);
if (!buf) {
- __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, dma_addr)),
- dma_addr & ~PAGE_MASK, size, dir);
+ arm_dma_ops.sync_single_for_cpu(dev, dma_addr, size, dir);
return;
}
unmap_single(dev, buf, size, dir);
}
-EXPORT_SYMBOL(__dma_unmap_page);
-int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr,
+static int __dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr,
size_t sz, enum dma_data_direction dir)
{
struct safe_buffer *buf;
@@ -392,9 +390,17 @@
}
return 0;
}
-EXPORT_SYMBOL(dmabounce_sync_for_cpu);
-int dmabounce_sync_for_device(struct device *dev, dma_addr_t addr,
+static void dmabounce_sync_for_cpu(struct device *dev,
+ dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+ if (!__dmabounce_sync_for_cpu(dev, handle, size, dir))
+ return;
+
+ arm_dma_ops.sync_single_for_cpu(dev, handle, size, dir);
+}
+
+static int __dmabounce_sync_for_device(struct device *dev, dma_addr_t addr,
size_t sz, enum dma_data_direction dir)
{
struct safe_buffer *buf;
@@ -424,7 +430,38 @@
}
return 0;
}
-EXPORT_SYMBOL(dmabounce_sync_for_device);
+
+static void dmabounce_sync_for_device(struct device *dev,
+ dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+ if (!__dmabounce_sync_for_device(dev, handle, size, dir))
+ return;
+
+ arm_dma_ops.sync_single_for_device(dev, handle, size, dir);
+}
+
+static int dmabounce_set_mask(struct device *dev, u64 dma_mask)
+{
+ if (dev->archdata.dmabounce)
+ return 0;
+
+ return arm_dma_ops.set_dma_mask(dev, dma_mask);
+}
+
+static struct dma_map_ops dmabounce_ops = {
+ .alloc = arm_dma_alloc,
+ .free = arm_dma_free,
+ .mmap = arm_dma_mmap,
+ .map_page = dmabounce_map_page,
+ .unmap_page = dmabounce_unmap_page,
+ .sync_single_for_cpu = dmabounce_sync_for_cpu,
+ .sync_single_for_device = dmabounce_sync_for_device,
+ .map_sg = arm_dma_map_sg,
+ .unmap_sg = arm_dma_unmap_sg,
+ .sync_sg_for_cpu = arm_dma_sync_sg_for_cpu,
+ .sync_sg_for_device = arm_dma_sync_sg_for_device,
+ .set_dma_mask = dmabounce_set_mask,
+};
static int dmabounce_init_pool(struct dmabounce_pool *pool, struct device *dev,
const char *name, unsigned long size)
@@ -486,6 +523,7 @@
#endif
dev->archdata.dmabounce = device_info;
+ set_dma_ops(dev, &dmabounce_ops);
dev_info(dev, "dmabounce: registered device\n");
@@ -504,6 +542,7 @@
struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
dev->archdata.dmabounce = NULL;
+ set_dma_ops(dev, NULL);
if (!device_info) {
dev_warn(dev,
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index a8abb30..8363b7f 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -154,10 +154,14 @@
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
CONFIG_BT=y
CONFIG_BT_RFCOMM=y
CONFIG_BT_RFCOMM_TTY=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 00325c9..d7735f5 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -154,10 +154,14 @@
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_FILTER=y
CONFIG_BT=y
CONFIG_BT_RFCOMM=y
CONFIG_BT_RFCOMM_TTY=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index a51b76d..c8f9212 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -181,12 +181,14 @@
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_FILTER=y
CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 0efe658..2eba8ab 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -181,12 +181,14 @@
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_FILTER=y
CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 3fad6b7..1ac8f02 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -203,6 +203,7 @@
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
@@ -211,6 +212,7 @@
CONFIG_IP6_NF_FILTER=y
CONFIG_IP6_NF_TARGET_REJECT=y
CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
@@ -291,6 +293,7 @@
CONFIG_STM_LIS3DH=y
CONFIG_INPUT_MPU3050=y
# CONFIG_LEGACY_PTYS is not set
+CONFIG_MSM_IPC_LOGGING=y
CONFIG_N_SMUX=y
CONFIG_N_SMUX_LOOPBACK=y
CONFIG_SMUX_CTL=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index cd79e98..8ac8f1a 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -207,6 +207,7 @@
CONFIG_IP_NF_TARGET_NETMAP=y
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
CONFIG_IP_NF_ARPTABLES=y
CONFIG_IP_NF_ARPFILTER=y
CONFIG_IP_NF_ARP_MANGLE=y
@@ -215,6 +216,7 @@
CONFIG_IP6_NF_FILTER=y
CONFIG_IP6_NF_TARGET_REJECT=y
CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
@@ -295,6 +297,7 @@
CONFIG_STM_LIS3DH=y
CONFIG_INPUT_MPU3050=y
# CONFIG_LEGACY_PTYS is not set
+CONFIG_MSM_IPC_LOGGING=y
CONFIG_N_SMUX=y
CONFIG_N_SMUX_LOOPBACK=y
CONFIG_SMUX_CTL=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 53193a1..cfc8963 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -56,10 +56,13 @@
CONFIG_MSM_OCMEM_POWER_DISABLE=y
CONFIG_MSM_MEMORY_DUMP=y
CONFIG_MSM_WATCHDOG_V2=y
+CONFIG_MSM_DLOAD_MODE=y
+CONFIG_PANIC_TIMEOUT=5
CONFIG_MSM_CACHE_ERP=y
CONFIG_MSM_L1_ERR_PANIC=y
CONFIG_MSM_L2_ERP_PRINT_ACCESS_ERRORS=y
CONFIG_MSM_L2_ERP_2BIT_PANIC=y
+CONFIG_MSM_ADSP_LOADER=m
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
@@ -131,6 +134,8 @@
CONFIG_KEYBOARD_GPIO=y
CONFIG_INPUT_JOYSTICK=y
CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=n
+CONFIG_TOUCHSCREEN_ATMEL_MXT=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_SERIAL_MSM_HSL=y
@@ -163,12 +168,22 @@
CONFIG_REGULATOR_STUB=y
CONFIG_REGULATOR_QPNP=y
CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_DEV=y
-# CONFIG_RC_CORE is not set
-# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_VIDEOBUF2_MSM_MEM=y
-# CONFIG_VIDEO_CAPTURE_DRIVERS is not set
-# CONFIG_RADIO_ADAPTERS is not set
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MSM_CAMERA_V4L2=y
+CONFIG_MSM_CAMERA_SENSOR=y
+CONFIG_MSM_ACTUATOR=y
+CONFIG_MSM_CAM_IRQ_ROUTER=n
+CONFIG_MSM_CCI=y
+CONFIG_MSM_CSI30_HEADER=y
+CONFIG_MSM_CSIPHY=y
+CONFIG_MSM_CSID=y
+CONFIG_MSM_CSI2_REGISTER=y
+CONFIG_MSM_ISPIF=y
+CONFIG_S5K3L1YX=y
CONFIG_ION=y
CONFIG_ION_MSM=y
CONFIG_MSM_KGSL=y
@@ -213,6 +228,7 @@
# CONFIG_MMC_BLOCK_BOUNCE is not set
CONFIG_MMC_TEST=m
CONFIG_MMC_MSM=y
+CONFIG_MMC_MSM_SPS_SUPPORT=y
CONFIG_SWITCH=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_DRV_MSM is not set
@@ -226,9 +242,11 @@
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
CONFIG_MSM_SSBI=y
CONFIG_SPS=y
+CONFIG_USB_BAM=y
CONFIG_SPS_SUPPORT_BAMDMA=y
CONFIG_SPS_SUPPORT_NDP_BAM=y
CONFIG_QPNP_POWER_ON=y
+CONFIG_QPNP_CLKDIV=y
CONFIG_MSM_IOMMU=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index db94f13..b8417fe 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -147,6 +147,10 @@
CONFIG_IP6_NF_TARGET_REJECT_SKERR=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_RAW=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_CLS_FW=y
CONFIG_MTD=y
CONFIG_MTD_TESTS=m
CONFIG_MTD_CMDLINE_PARTS=y
diff --git a/arch/arm/include/asm/device.h b/arch/arm/include/asm/device.h
index 7aa3680..b69c0d3 100644
--- a/arch/arm/include/asm/device.h
+++ b/arch/arm/include/asm/device.h
@@ -7,12 +7,16 @@
#define ASMARM_DEVICE_H
struct dev_archdata {
+ struct dma_map_ops *dma_ops;
#ifdef CONFIG_DMABOUNCE
struct dmabounce_device_info *dmabounce;
#endif
#ifdef CONFIG_IOMMU_API
void *iommu; /* private IOMMU data */
#endif
+#ifdef CONFIG_ARM_DMA_USE_IOMMU
+ struct dma_iommu_mapping *mapping;
+#endif
};
struct omap_device;
diff --git a/arch/arm/include/asm/dma-iommu.h b/arch/arm/include/asm/dma-iommu.h
new file mode 100644
index 0000000..799b094
--- /dev/null
+++ b/arch/arm/include/asm/dma-iommu.h
@@ -0,0 +1,34 @@
+#ifndef ASMARM_DMA_IOMMU_H
+#define ASMARM_DMA_IOMMU_H
+
+#ifdef __KERNEL__
+
+#include <linux/mm_types.h>
+#include <linux/scatterlist.h>
+#include <linux/dma-debug.h>
+#include <linux/kmemcheck.h>
+
+struct dma_iommu_mapping {
+ /* iommu specific data */
+ struct iommu_domain *domain;
+
+ void *bitmap;
+ size_t bits;
+ unsigned int order;
+ dma_addr_t base;
+
+ spinlock_t lock;
+ struct kref kref;
+};
+
+struct dma_iommu_mapping *
+arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size,
+ int order);
+
+void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping);
+
+int arm_iommu_attach_device(struct device *dev,
+ struct dma_iommu_mapping *mapping);
+
+#endif /* __KERNEL__ */
+#endif
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index d055a53..5f28327 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -5,12 +5,34 @@
#include <linux/mm_types.h>
#include <linux/scatterlist.h>
+#include <linux/dma-attrs.h>
#include <linux/dma-debug.h>
#include <asm-generic/dma-coherent.h>
#include <asm/memory.h>
#define DMA_ERROR_CODE (~0)
+extern struct dma_map_ops arm_dma_ops;
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+ if (dev && dev->archdata.dma_ops)
+ return dev->archdata.dma_ops;
+ return &arm_dma_ops;
+}
+
+static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
+{
+ BUG_ON(!dev);
+ dev->archdata.dma_ops = ops;
+}
+
+#include <asm-generic/dma-mapping-common.h>
+
+static inline int dma_set_mask(struct device *dev, u64 mask)
+{
+ return get_dma_ops(dev)->set_dma_mask(dev, mask);
+}
#ifdef __arch_page_to_dma
#error Please update to __arch_pfn_to_dma
@@ -64,63 +86,6 @@
#endif
/*
- * The DMA API is built upon the notion of "buffer ownership". A buffer
- * is either exclusively owned by the CPU (and therefore may be accessed
- * by it) or exclusively owned by the DMA device. These helper functions
- * represent the transitions between these two ownership states.
- *
- * Note, however, that on later ARMs, this notion does not work due to
- * speculative prefetches. We model our approach on the assumption that
- * the CPU does do speculative prefetches, which means we clean caches
- * before transfers and delay cache invalidation until transfer completion.
- *
- * Private support functions: these are not part of the API and are
- * liable to change. Drivers must not use these.
- */
-static inline void __dma_single_cpu_to_dev(const void *kaddr, size_t size,
- enum dma_data_direction dir)
-{
- extern void ___dma_single_cpu_to_dev(const void *, size_t,
- enum dma_data_direction);
-
- if (!arch_is_coherent())
- ___dma_single_cpu_to_dev(kaddr, size, dir);
-}
-
-static inline void __dma_single_dev_to_cpu(const void *kaddr, size_t size,
- enum dma_data_direction dir)
-{
- extern void ___dma_single_dev_to_cpu(const void *, size_t,
- enum dma_data_direction);
-
- if (!arch_is_coherent())
- ___dma_single_dev_to_cpu(kaddr, size, dir);
-}
-
-static inline void __dma_page_cpu_to_dev(struct page *page, unsigned long off,
- size_t size, enum dma_data_direction dir)
-{
- extern void ___dma_page_cpu_to_dev(struct page *, unsigned long,
- size_t, enum dma_data_direction);
-
- if (!arch_is_coherent())
- ___dma_page_cpu_to_dev(page, off, size, dir);
-}
-
-static inline void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
- size_t size, enum dma_data_direction dir)
-{
- extern void ___dma_page_dev_to_cpu(struct page *, unsigned long,
- size_t, enum dma_data_direction);
-
- if (!arch_is_coherent())
- ___dma_page_dev_to_cpu(page, off, size, dir);
-}
-
-extern int dma_supported(struct device *, u64);
-extern int dma_set_mask(struct device *, u64);
-
-/*
* DMA errors are defined by all-bits-set in the DMA address.
*/
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
@@ -183,69 +148,118 @@
#endif
}
+extern int dma_supported(struct device *dev, u64 mask);
+
/**
- * dma_alloc_coherent - allocate consistent memory for DMA
+ * arm_dma_alloc - allocate consistent memory for DMA
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
* @size: required memory size
* @handle: bus-specific DMA address
+ * @attrs: optinal attributes that specific mapping properties
*
- * Allocate some uncached, unbuffered memory for a device for
- * performing DMA. This function allocates pages, and will
- * return the CPU-viewed address, and sets @handle to be the
- * device-viewed address.
+ * Allocate some memory for a device for performing DMA. This function
+ * allocates pages, and will return the CPU-viewed address, and sets @handle
+ * to be the device-viewed address.
*/
-extern void *dma_alloc_coherent(struct device *, size_t, dma_addr_t *, gfp_t);
+extern void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
+ gfp_t gfp, struct dma_attrs *attrs);
+
+#define dma_alloc_coherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag,
+ struct dma_attrs *attrs)
+{
+ struct dma_map_ops *ops = get_dma_ops(dev);
+ void *cpu_addr;
+ BUG_ON(!ops);
+
+ cpu_addr = ops->alloc(dev, size, dma_handle, flag, attrs);
+ debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr);
+ return cpu_addr;
+}
/**
- * dma_free_coherent - free memory allocated by dma_alloc_coherent
+ * arm_dma_free - free memory allocated by arm_dma_alloc
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
* @size: size of memory originally requested in dma_alloc_coherent
* @cpu_addr: CPU-view address returned from dma_alloc_coherent
* @handle: device-view address returned from dma_alloc_coherent
+ * @attrs: optinal attributes that specific mapping properties
*
* Free (and unmap) a DMA buffer previously allocated by
- * dma_alloc_coherent().
+ * arm_dma_alloc().
*
* References to memory and mappings associated with cpu_addr/handle
* during and after this call executing are illegal.
*/
-extern void dma_free_coherent(struct device *, size_t, void *, dma_addr_t);
+extern void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
+ dma_addr_t handle, struct dma_attrs *attrs);
+
+#define dma_free_coherent(d, s, c, h) dma_free_attrs(d, s, c, h, NULL)
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
+{
+ struct dma_map_ops *ops = get_dma_ops(dev);
+ BUG_ON(!ops);
+
+ debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+ ops->free(dev, size, cpu_addr, dma_handle, attrs);
+}
/**
- * dma_mmap_coherent - map a coherent DMA allocation into user space
+ * arm_dma_mmap - map a coherent DMA allocation into user space
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
* @vma: vm_area_struct describing requested user mapping
* @cpu_addr: kernel CPU-view address returned from dma_alloc_coherent
* @handle: device-view address returned from dma_alloc_coherent
* @size: size of memory originally requested in dma_alloc_coherent
+ * @attrs: optinal attributes that specific mapping properties
*
* Map a coherent DMA buffer previously allocated by dma_alloc_coherent
* into user space. The coherent DMA buffer must not be freed by the
* driver until the user space mapping has been released.
*/
-int dma_mmap_coherent(struct device *, struct vm_area_struct *,
- void *, dma_addr_t, size_t);
+extern int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
+ void *cpu_addr, dma_addr_t dma_addr, size_t size,
+ struct dma_attrs *attrs);
+#define dma_mmap_coherent(d, v, c, h, s) dma_mmap_attrs(d, v, c, h, s, NULL)
-/**
- * dma_alloc_writecombine - allocate writecombining memory for DMA
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @size: required memory size
- * @handle: bus-specific DMA address
- *
- * Allocate some uncached, buffered memory for a device for
- * performing DMA. This function allocates pages, and will
- * return the CPU-viewed address, and sets @handle to be the
- * device-viewed address.
- */
-extern void *dma_alloc_writecombine(struct device *, size_t, dma_addr_t *,
- gfp_t);
+static inline int dma_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
+ void *cpu_addr, dma_addr_t dma_addr,
+ size_t size, struct dma_attrs *attrs)
+{
+ struct dma_map_ops *ops = get_dma_ops(dev);
+ BUG_ON(!ops);
+ return ops->mmap(dev, vma, cpu_addr, dma_addr, size, attrs);
+}
-#define dma_free_writecombine(dev,size,cpu_addr,handle) \
- dma_free_coherent(dev,size,cpu_addr,handle)
+static inline void *dma_alloc_writecombine(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
+{
+ DEFINE_DMA_ATTRS(attrs);
+ dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
+ return dma_alloc_attrs(dev, size, dma_handle, flag, &attrs);
+}
-int dma_mmap_writecombine(struct device *, struct vm_area_struct *,
- void *, dma_addr_t, size_t);
+static inline void dma_free_writecombine(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle)
+{
+ DEFINE_DMA_ATTRS(attrs);
+ dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
+ return dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs);
+}
+
+static inline int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma,
+ void *cpu_addr, dma_addr_t dma_addr, size_t size)
+{
+ DEFINE_DMA_ATTRS(attrs);
+ dma_set_attr(DMA_ATTR_WRITE_COMBINE, &attrs);
+ return dma_mmap_attrs(dev, vma, cpu_addr, dma_addr, size, &attrs);
+}
/*
* This can be called during boot to increase the size of the consistent
@@ -254,8 +268,6 @@
*/
extern void __init init_consistent_dma_size(unsigned long size);
-
-#ifdef CONFIG_DMABOUNCE
/*
* For SA-1111, IXP425, and ADI systems the dma-mapping functions are "magic"
* and utilize bounce buffers as needed to work around limited DMA windows.
@@ -295,80 +307,7 @@
*/
extern void dmabounce_unregister_dev(struct device *);
-/*
- * The DMA API, implemented by dmabounce.c. See below for descriptions.
- */
-extern dma_addr_t __dma_map_page(struct device *, struct page *,
- unsigned long, size_t, enum dma_data_direction);
-extern void __dma_unmap_page(struct device *, dma_addr_t, size_t,
- enum dma_data_direction);
-/*
- * Private functions
- */
-int dmabounce_sync_for_cpu(struct device *, dma_addr_t, size_t, enum dma_data_direction);
-int dmabounce_sync_for_device(struct device *, dma_addr_t, size_t, enum dma_data_direction);
-#else
-static inline int dmabounce_sync_for_cpu(struct device *d, dma_addr_t addr,
- size_t size, enum dma_data_direction dir)
-{
- return 1;
-}
-
-static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr,
- size_t size, enum dma_data_direction dir)
-{
- return 1;
-}
-
-
-static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size, enum dma_data_direction dir)
-{
- __dma_page_cpu_to_dev(page, offset, size, dir);
- return pfn_to_dma(dev, page_to_pfn(page)) + offset;
-}
-
-static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
- size_t size, enum dma_data_direction dir)
-{
- __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
- handle & ~PAGE_MASK, size, dir);
-}
-#endif /* CONFIG_DMABOUNCE */
-
-/**
- * dma_map_single - map a single buffer for streaming DMA
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @cpu_addr: CPU direct mapped address of buffer
- * @size: size of buffer to map
- * @dir: DMA transfer direction
- *
- * Ensure that any data held in the cache is appropriately discarded
- * or written back.
- *
- * The device owns this memory once this call has completed. The CPU
- * can regain ownership by calling dma_unmap_single() or
- * dma_sync_single_for_cpu().
- */
-static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
- size_t size, enum dma_data_direction dir)
-{
- unsigned long offset;
- struct page *page;
- dma_addr_t addr;
-
- BUG_ON(!virt_addr_valid(cpu_addr));
- BUG_ON(!virt_addr_valid(cpu_addr + size - 1));
- BUG_ON(!valid_dma_direction(dir));
-
- page = virt_to_page(cpu_addr);
- offset = (unsigned long)cpu_addr & ~PAGE_MASK;
- addr = __dma_map_page(dev, page, offset, size, dir);
- debug_dma_map_page(dev, page, offset, size, dir, addr, true);
-
- return addr;
-}
/**
* dma_cache_pre_ops - clean or invalidate cache before dma transfer is
@@ -421,147 +360,17 @@
___dma_single_cpu_to_dev(virtual_addr,
size, DMA_FROM_DEVICE);
}
-
-/**
- * dma_map_page - map a portion of a page for streaming DMA
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @page: page that buffer resides in
- * @offset: offset into page for start of buffer
- * @size: size of buffer to map
- * @dir: DMA transfer direction
- *
- * Ensure that any data held in the cache is appropriately discarded
- * or written back.
- *
- * The device owns this memory once this call has completed. The CPU
- * can regain ownership by calling dma_unmap_page().
- */
-static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size, enum dma_data_direction dir)
-{
- dma_addr_t addr;
-
- BUG_ON(!valid_dma_direction(dir));
-
- addr = __dma_map_page(dev, page, offset, size, dir);
- debug_dma_map_page(dev, page, offset, size, dir, addr, false);
-
- return addr;
-}
-
-/**
- * dma_unmap_single - unmap a single buffer previously mapped
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @handle: DMA address of buffer
- * @size: size of buffer (same as passed to dma_map_single)
- * @dir: DMA transfer direction (same as passed to dma_map_single)
- *
- * Unmap a single streaming mode DMA translation. The handle and size
- * must match what was provided in the previous dma_map_single() call.
- * All other usages are undefined.
- *
- * After this call, reads by the CPU to the buffer are guaranteed to see
- * whatever the device wrote there.
- */
-static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
- size_t size, enum dma_data_direction dir)
-{
- debug_dma_unmap_page(dev, handle, size, dir, true);
- __dma_unmap_page(dev, handle, size, dir);
-}
-
-/**
- * dma_unmap_page - unmap a buffer previously mapped through dma_map_page()
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @handle: DMA address of buffer
- * @size: size of buffer (same as passed to dma_map_page)
- * @dir: DMA transfer direction (same as passed to dma_map_page)
- *
- * Unmap a page streaming mode DMA translation. The handle and size
- * must match what was provided in the previous dma_map_page() call.
- * All other usages are undefined.
- *
- * After this call, reads by the CPU to the buffer are guaranteed to see
- * whatever the device wrote there.
- */
-static inline void dma_unmap_page(struct device *dev, dma_addr_t handle,
- size_t size, enum dma_data_direction dir)
-{
- debug_dma_unmap_page(dev, handle, size, dir, false);
- __dma_unmap_page(dev, handle, size, dir);
-}
-
-
-static inline void dma_sync_single_for_cpu(struct device *dev,
- dma_addr_t handle, size_t size, enum dma_data_direction dir)
-{
- BUG_ON(!valid_dma_direction(dir));
-
- debug_dma_sync_single_for_cpu(dev, handle, size, dir);
-
- if (!dmabounce_sync_for_cpu(dev, handle, size, dir))
- return;
-
- __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
-}
-
-static inline void dma_sync_single_for_device(struct device *dev,
- dma_addr_t handle, size_t size, enum dma_data_direction dir)
-{
- BUG_ON(!valid_dma_direction(dir));
-
- debug_dma_sync_single_for_device(dev, handle, size, dir);
-
- if (!dmabounce_sync_for_device(dev, handle, size, dir))
- return;
-
- __dma_single_cpu_to_dev(dma_to_virt(dev, handle), size, dir);
-}
-
-/**
- * dma_sync_single_range_for_cpu
- * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
- * @handle: DMA address of buffer
- * @offset: offset of region to start sync
- * @size: size of region to sync
- * @dir: DMA transfer direction (same as passed to dma_map_single)
- *
- * Make physical memory consistent for a single streaming mode DMA
- * translation after a transfer.
- *
- * If you perform a dma_map_single() but wish to interrogate the
- * buffer using the cpu, yet do not wish to teardown the PCI dma
- * mapping, you must call this function before doing so. At the
- * next point you give the PCI dma address back to the card, you
- * must first the perform a dma_sync_for_device, and then the
- * device again owns the buffer.
- */
-static inline void dma_sync_single_range_for_cpu(struct device *dev,
- dma_addr_t handle, unsigned long offset, size_t size,
- enum dma_data_direction dir)
-{
- dma_sync_single_for_cpu(dev, handle + offset, size, dir);
-}
-
-static inline void dma_sync_single_range_for_device(struct device *dev,
- dma_addr_t handle, unsigned long offset, size_t size,
- enum dma_data_direction dir)
-{
- dma_sync_single_for_device(dev, handle + offset, size, dir);
-}
-
/*
* The scatter list versions of the above methods.
*/
-extern int dma_map_sg(struct device *, struct scatterlist *, int,
+extern int arm_dma_map_sg(struct device *, struct scatterlist *, int,
+ enum dma_data_direction, struct dma_attrs *attrs);
+extern void arm_dma_unmap_sg(struct device *, struct scatterlist *, int,
+ enum dma_data_direction, struct dma_attrs *attrs);
+extern void arm_dma_sync_sg_for_cpu(struct device *, struct scatterlist *, int,
enum dma_data_direction);
-extern void dma_unmap_sg(struct device *, struct scatterlist *, int,
+extern void arm_dma_sync_sg_for_device(struct device *, struct scatterlist *, int,
enum dma_data_direction);
-extern void dma_sync_sg_for_cpu(struct device *, struct scatterlist *, int,
- enum dma_data_direction);
-extern void dma_sync_sg_for_device(struct device *, struct scatterlist *, int,
- enum dma_data_direction);
-
#endif /* __KERNEL__ */
#endif
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 7411e0b..e41ab0a 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -2115,7 +2115,7 @@
config MSM_DLOAD_MODE
bool "Enable download mode on crashes"
- depends on ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_MSM9615
+ depends on ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_MSM9615 || ARCH_MSM8974
default n
help
This makes the SoC enter download mode when it resets
@@ -2341,6 +2341,16 @@
Choosing one of these options allows debugging of each
individual subsystem separately.
+config MSM_OCMEM_NONSECURE
+ bool "OCMEM Non Secure Mode"
+ depends on MSM_OCMEM_DEBUG
+ help
+ Disable OCMEM interaction with secure processor.
+ By default OCMEM is secured and accesses for each master
+ is requested by the OCMEM driver. Selecting this option
+ causes the OCMEM memory to be in non-secure state unless
+ its locked down by the secure processor.
+
config MSM_OCMEM_POWER_DEBUG
bool "OCMEM Power Debug Support"
depends on MSM_OCMEM_DEBUG
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index f763d49..da3d3c4 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -276,9 +276,9 @@
obj-$(CONFIG_MACH_MSM8960_CDP) += board-8960-all.o board-8960-regulator.o
obj-$(CONFIG_MACH_MSM8960_MTP) += board-8960-all.o board-8960-regulator.o
obj-$(CONFIG_MACH_MSM8960_FLUID) += board-8960-all.o board-8960-regulator.o
-obj-$(CONFIG_MACH_MSM8930_CDP) += board-8930-all.o board-8930-regulator.o
-obj-$(CONFIG_MACH_MSM8930_MTP) += board-8930-all.o board-8930-regulator.o
-obj-$(CONFIG_MACH_MSM8930_FLUID) += board-8930-all.o board-8930-regulator.o
+obj-$(CONFIG_MACH_MSM8930_CDP) += board-8930-all.o board-8930-regulator-pm8038.o board-8930-regulator-pm8917.o
+obj-$(CONFIG_MACH_MSM8930_MTP) += board-8930-all.o board-8930-regulator-pm8038.o board-8930-regulator-pm8917.o
+obj-$(CONFIG_MACH_MSM8930_FLUID) += board-8930-all.o board-8930-regulator-pm8038.o board-8930-regulator-pm8917.o
obj-$(CONFIG_PM8921_BMS) += bms-batterydata.o bms-batterydata-desay.o
obj-$(CONFIG_MACH_APQ8064_CDP) += board-8064-all.o board-8064-regulator.o
obj-$(CONFIG_MACH_APQ8064_MTP) += board-8064-all.o board-8064-regulator.o
@@ -289,7 +289,7 @@
obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
obj-$(CONFIG_ARCH_MSM8974) += board-8974.o board-dt.o board-8974-gpiomux.o
obj-$(CONFIG_ARCH_MSM8974) += acpuclock-8974.o
-obj-$(CONFIG_ARCH_MSM8974) += clock-local2.o clock-pll.o clock-8974.o clock-rpm.o clock-voter.o
+obj-$(CONFIG_ARCH_MSM8974) += clock-local2.o clock-pll.o clock-8974.o clock-rpm.o clock-voter.o clock-mdss-8974.o
obj-$(CONFIG_ARCH_MSM8974) += gdsc.o
obj-$(CONFIG_ARCH_MSM8974) += krait-regulator.o
obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
diff --git a/arch/arm/mach-msm/acpuclock-8930.c b/arch/arm/mach-msm/acpuclock-8930.c
index 5647d14..782ee60 100644
--- a/arch/arm/mach-msm/acpuclock-8930.c
+++ b/arch/arm/mach-msm/acpuclock-8930.c
@@ -45,6 +45,39 @@
.vdd[HFPLL_VDD_HIGH] = LVL_HIGH,
};
+static struct scalable scalable_pm8917[] __initdata = {
+ [CPU0] = {
+ .hfpll_phys_base = 0x00903200,
+ .aux_clk_sel_phys = 0x02088014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x4501,
+ .vreg[VREG_CORE] = { "krait0", 1300000 },
+ .vreg[VREG_MEM] = { "krait0_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait0_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait0_s8", 2050000 },
+ .vreg[VREG_HFPLL_B] = { "krait0_l23", 1800000 },
+ },
+ [CPU1] = {
+ .hfpll_phys_base = 0x00903300,
+ .aux_clk_sel_phys = 0x02098014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x5501,
+ .vreg[VREG_CORE] = { "krait1", 1300000 },
+ .vreg[VREG_MEM] = { "krait1_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait1_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait1_s8", 2050000 },
+ .vreg[VREG_HFPLL_B] = { "krait1_l23", 1800000 },
+ },
+ [L2] = {
+ .hfpll_phys_base = 0x00903400,
+ .aux_clk_sel_phys = 0x02011028,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x0500,
+ .vreg[VREG_HFPLL_A] = { "l2_s8", 2050000 },
+ .vreg[VREG_HFPLL_B] = { "l2_l23", 1800000 },
+ },
+};
+
static struct scalable scalable[] __initdata = {
[CPU0] = {
.hfpll_phys_base = 0x00903200,
@@ -193,6 +226,10 @@
static int __init acpuclk_8930_probe(struct platform_device *pdev)
{
+ struct acpuclk_platform_data *pdata = pdev->dev.platform_data;
+ if (pdata && pdata->uses_pm8917)
+ acpuclk_8930_params.scalable = scalable_pm8917;
+
return acpuclk_krait_init(&pdev->dev, &acpuclk_8930_params);
}
diff --git a/arch/arm/mach-msm/acpuclock-8960ab.c b/arch/arm/mach-msm/acpuclock-8960ab.c
index 6366376..3c42090 100644
--- a/arch/arm/mach-msm/acpuclock-8960ab.c
+++ b/arch/arm/mach-msm/acpuclock-8960ab.c
@@ -124,6 +124,10 @@
{ 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(9), 1237500 },
{ 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(9), 1237500 },
{ 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(9), 1250000 },
+ { 1, { 1566000, HFPLL, 1, 0, 0x3A }, L2(9), 1250000 },
+ { 1, { 1620000, HFPLL, 1, 0, 0x3C }, L2(9), 1250000 },
+ { 1, { 1674000, HFPLL, 1, 0, 0x3E }, L2(9), 1250000 },
+ { 1, { 1728000, HFPLL, 1, 0, 0x40 }, L2(9), 1250000 },
{ 0, { 0 } }
};
@@ -142,6 +146,7 @@
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
.qfprom_phys_base = 0x00700000,
+ .stby_khz = 384000,
};
static int __init acpuclk_8960ab_probe(struct platform_device *pdev)
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 22275b4..f0b1231 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -148,12 +148,12 @@
{ 1, { 883200, HFPLL, 1, 0, 46 }, L2(7), 950000, 3200000 },
{ 1, { 960000, HFPLL, 1, 0, 50 }, L2(7), 950000, 3200000 },
{ 1, { 1036800, HFPLL, 1, 0, 54 }, L2(7), 950000, 3200000 },
- { 0, { 1113600, HFPLL, 1, 0, 58 }, L2(12), 1050000, 3200000 },
- { 0, { 1190400, HFPLL, 1, 0, 62 }, L2(12), 1050000, 3200000 },
- { 0, { 1267200, HFPLL, 1, 0, 66 }, L2(12), 1050000, 3200000 },
- { 0, { 1344000, HFPLL, 1, 0, 70 }, L2(15), 1050000, 3200000 },
- { 0, { 1420800, HFPLL, 1, 0, 74 }, L2(15), 1050000, 3200000 },
- { 0, { 1497600, HFPLL, 1, 0, 78 }, L2(15), 1050000, 3200000 },
+ { 1, { 1113600, HFPLL, 1, 0, 58 }, L2(12), 1050000, 3200000 },
+ { 1, { 1190400, HFPLL, 1, 0, 62 }, L2(12), 1050000, 3200000 },
+ { 1, { 1267200, HFPLL, 1, 0, 66 }, L2(12), 1050000, 3200000 },
+ { 1, { 1344000, HFPLL, 1, 0, 70 }, L2(15), 1050000, 3200000 },
+ { 1, { 1420800, HFPLL, 1, 0, 74 }, L2(15), 1050000, 3200000 },
+ { 1, { 1497600, HFPLL, 1, 0, 78 }, L2(16), 1050000, 3200000 },
{ 0, { 1574400, HFPLL, 1, 0, 82 }, L2(20), 1050000, 3200000 },
{ 0, { 1651200, HFPLL, 1, 0, 86 }, L2(20), 1050000, 3200000 },
{ 0, { 1728000, HFPLL, 1, 0, 90 }, L2(20), 1050000, 3200000 },
diff --git a/arch/arm/mach-msm/acpuclock-krait.h b/arch/arm/mach-msm/acpuclock-krait.h
index 5a95e76..1b891b1 100644
--- a/arch/arm/mach-msm/acpuclock-krait.h
+++ b/arch/arm/mach-msm/acpuclock-krait.h
@@ -253,9 +253,16 @@
};
/**
+ * struct acpuclk_platform_data - PMIC configuration data.
+ * @uses_pm8917: Boolean indicates presence of pm8917.
+ */
+struct acpuclk_platform_data {
+ bool uses_pm8917;
+};
+
+/**
* acpuclk_krait_init - Initialize the Krait CPU clock driver give SoC params.
*/
extern int acpuclk_krait_init(struct device *dev,
const struct acpuclk_krait_params *params);
-
#endif
diff --git a/arch/arm/mach-msm/acpuclock.c b/arch/arm/mach-msm/acpuclock.c
index be056e6..2b33c4c 100644
--- a/arch/arm/mach-msm/acpuclock.c
+++ b/arch/arm/mach-msm/acpuclock.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. 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,7 @@
#include <linux/cpu.h>
#include <linux/smp.h>
#include "acpuclock.h"
+#include <trace/events/power.h>
static struct acpuclk_data *acpuclk_data;
@@ -26,10 +27,19 @@
int acpuclk_set_rate(int cpu, unsigned long rate, enum setrate_reason reason)
{
+ int ret;
+
if (!acpuclk_data->set_rate)
return 0;
- return acpuclk_data->set_rate(cpu, rate, reason);
+ trace_cpu_frequency_switch_start(acpuclk_get_rate(cpu), rate, cpu);
+ ret = acpuclk_data->set_rate(cpu, rate, reason);
+ if (!ret) {
+ trace_cpu_frequency_switch_end(cpu);
+ trace_cpu_frequency(rate, cpu);
+ }
+
+ return ret;
}
uint32_t acpuclk_get_switch_time(void)
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 04e751a..fbc3e25 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -27,6 +27,7 @@
#include <linux/clk.h>
#include <linux/wakelock.h>
#include <linux/kfifo.h>
+#include <linux/of.h>
#include <mach/sps.h>
#include <mach/bam_dmux.h>
@@ -175,6 +176,14 @@
#define A2_PHYS_SIZE 0x2000
#define BUFFER_SIZE 2048
#define NUM_BUFFERS 32
+
+#ifndef A2_BAM_IRQ
+#define A2_BAM_IRQ -1
+#endif
+
+static void *a2_phys_base;
+static uint32_t a2_phys_size;
+static int a2_bam_irq;
static struct sps_bam_props a2_props;
static u32 a2_device_handle;
static struct sps_pipe *bam_tx_pipe;
@@ -1876,12 +1885,18 @@
mutex_unlock(&dfab_status_lock);
return;
}
- rc = clk_prepare_enable(dfab_clk);
- if (rc)
- DMUX_LOG_KERR("bam_dmux vote for dfab failed rc = %d\n", rc);
- rc = clk_prepare_enable(xo_clk);
- if (rc)
- DMUX_LOG_KERR("bam_dmux vote for xo failed rc = %d\n", rc);
+ if (dfab_clk) {
+ rc = clk_prepare_enable(dfab_clk);
+ if (rc)
+ DMUX_LOG_KERR("bam_dmux vote for dfab failed rc = %d\n",
+ rc);
+ }
+ if (xo_clk) {
+ rc = clk_prepare_enable(xo_clk);
+ if (rc)
+ DMUX_LOG_KERR("bam_dmux vote for xo failed rc = %d\n",
+ rc);
+ }
dfab_is_on = 1;
mutex_unlock(&dfab_status_lock);
}
@@ -1896,8 +1911,10 @@
mutex_unlock(&dfab_status_lock);
return;
}
- clk_disable_unprepare(dfab_clk);
- clk_disable_unprepare(xo_clk);
+ if (dfab_clk)
+ clk_disable_unprepare(dfab_clk);
+ if (xo_clk)
+ clk_disable_unprepare(xo_clk);
dfab_is_on = 0;
mutex_unlock(&dfab_status_lock);
}
@@ -2020,16 +2037,17 @@
vote_dfab();
/* init BAM */
- a2_virt_addr = ioremap_nocache(A2_PHYS_BASE, A2_PHYS_SIZE);
+ a2_virt_addr = ioremap_nocache((unsigned long)(a2_phys_base),
+ a2_phys_size);
if (!a2_virt_addr) {
pr_err("%s: ioremap failed\n", __func__);
ret = -ENOMEM;
goto ioremap_failed;
}
- a2_props.phys_addr = A2_PHYS_BASE;
+ a2_props.phys_addr = (u32)(a2_phys_base);
a2_props.virt_addr = a2_virt_addr;
- a2_props.virt_size = A2_PHYS_SIZE;
- a2_props.irq = A2_BAM_IRQ;
+ a2_props.virt_size = a2_phys_size;
+ a2_props.irq = a2_bam_irq;
a2_props.options = SPS_BAM_OPT_IRQ_WAKEUP;
a2_props.num_pipes = A2_NUM_PIPES;
a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
@@ -2191,16 +2209,17 @@
void *a2_virt_addr;
/* init BAM */
- a2_virt_addr = ioremap_nocache(A2_PHYS_BASE, A2_PHYS_SIZE);
+ a2_virt_addr = ioremap_nocache((unsigned long)(a2_phys_base),
+ a2_phys_size);
if (!a2_virt_addr) {
pr_err("%s: ioremap failed\n", __func__);
ret = -ENOMEM;
goto ioremap_failed;
}
- a2_props.phys_addr = A2_PHYS_BASE;
+ a2_props.phys_addr = (u32)(a2_phys_base);
a2_props.virt_addr = a2_virt_addr;
- a2_props.virt_size = A2_PHYS_SIZE;
- a2_props.irq = A2_BAM_IRQ;
+ a2_props.virt_size = a2_phys_size;
+ a2_props.irq = a2_bam_irq;
a2_props.options = SPS_BAM_OPT_IRQ_WAKEUP;
a2_props.num_pipes = A2_NUM_PIPES;
a2_props.summing_threshold = A2_SUMMING_THRESHOLD;
@@ -2313,26 +2332,50 @@
static int bam_dmux_probe(struct platform_device *pdev)
{
int rc;
+ struct resource *r;
DBG("%s probe called\n", __func__);
if (bam_mux_initialized)
return 0;
+ if (pdev->dev.of_node) {
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r) {
+ pr_err("%s: reg field missing\n", __func__);
+ return -ENODEV;
+ }
+ a2_phys_base = (void *)(r->start);
+ a2_phys_size = (uint32_t)(resource_size(r));
+ a2_bam_irq = platform_get_irq(pdev, 0);
+ if (a2_bam_irq == -ENXIO) {
+ pr_err("%s: irq field missing\n", __func__);
+ return -ENODEV;
+ }
+ DBG("%s: base:%p size:%x irq:%d\n", __func__,
+ a2_phys_base,
+ a2_phys_size,
+ a2_bam_irq);
+ } 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;
+ }
+
xo_clk = clk_get(&pdev->dev, "xo");
if (IS_ERR(xo_clk)) {
- pr_err("%s: did not get xo clock\n", __func__);
- return PTR_ERR(xo_clk);
+ bam_dmux_log("%s: did not get xo clock\n", __func__);
+ xo_clk = NULL;
}
dfab_clk = clk_get(&pdev->dev, "bus_clk");
if (IS_ERR(dfab_clk)) {
- pr_err("%s: did not get dfab clock\n", __func__);
- return -EFAULT;
+ bam_dmux_log("%s: did not get dfab clock\n", __func__);
+ dfab_clk = NULL;
+ } else {
+ rc = clk_set_rate(dfab_clk, 64000000);
+ if (rc)
+ pr_err("%s: unable to set dfab clock rate\n", __func__);
}
- rc = clk_set_rate(dfab_clk, 64000000);
- if (rc)
- pr_err("%s: unable to set dfab clock rate\n", __func__);
-
/*
* setup the workqueue so that it can be pinned to core 0 and not
* block the watchdog pet function, so that netif_rx() in rmnet
@@ -2401,11 +2444,17 @@
return 0;
}
+static struct of_device_id msm_match_table[] = {
+ {.compatible = "qcom,bam_dmux"},
+ {},
+};
+
static struct platform_driver bam_dmux_driver = {
.probe = bam_dmux_probe,
.driver = {
.name = "BAM_RMNT",
.owner = THIS_MODULE,
+ .of_match_table = msm_match_table,
},
};
diff --git a/arch/arm/mach-msm/board-8064-camera.c b/arch/arm/mach-msm/board-8064-camera.c
index 40995bb..722b8ea 100644
--- a/arch/arm/mach-msm/board-8064-camera.c
+++ b/arch/arm/mach-msm/board-8064-camera.c
@@ -16,7 +16,7 @@
#include <asm/mach-types.h>
-#include <mach/board.h>
+#include <mach/camera.h>
#include <mach/msm_bus_board.h>
#include <mach/gpiomux.h>
@@ -369,20 +369,13 @@
},
};
-static struct camera_vreg_t apq_8064_back_cam_vreg[] = {
+static struct camera_vreg_t apq_8064_cam_vreg[] = {
{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
{"cam_vio", REG_VS, 0, 0, 0},
{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
};
-static struct camera_vreg_t apq_8064_front_cam_vreg[] = {
- {"cam_vio", REG_VS, 0, 0, 0},
- {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
- {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
- {"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
-};
-
#define CAML_RSTN PM8921_GPIO_PM_TO_SYS(28)
#define CAMR_RSTN 34
@@ -482,8 +475,8 @@
static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
.mount_angle = 90,
- .cam_vreg = apq_8064_back_cam_vreg,
- .num_vreg = ARRAY_SIZE(apq_8064_back_cam_vreg),
+ .cam_vreg = apq_8064_cam_vreg,
+ .num_vreg = ARRAY_SIZE(apq_8064_cam_vreg),
.gpio_conf = &apq8064_back_cam_gpio_conf,
.i2c_conf = &apq8064_back_cam_i2c_conf,
.csi_lane_params = &imx074_csi_lane_params,
@@ -515,21 +508,14 @@
.csi_lane_mask = 0xF,
};
-static struct camera_vreg_t apq_8064_imx091_vreg[] = {
- {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
- {"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
- {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
- {"cam_vio", REG_VS, 0, 0, 0},
-};
-
static struct msm_camera_sensor_flash_data flash_imx091 = {
.flash_type = MSM_CAMERA_FLASH_NONE,
};
static struct msm_camera_sensor_platform_info sensor_board_info_imx091 = {
.mount_angle = 0,
- .cam_vreg = apq_8064_imx091_vreg,
- .num_vreg = ARRAY_SIZE(apq_8064_imx091_vreg),
+ .cam_vreg = apq_8064_cam_vreg,
+ .num_vreg = ARRAY_SIZE(apq_8064_cam_vreg),
.gpio_conf = &apq8064_back_cam_gpio_conf,
.i2c_conf = &apq8064_back_cam_i2c_conf,
.csi_lane_params = &imx091_csi_lane_params,
@@ -556,13 +542,6 @@
.eeprom_info = &imx091_eeprom_info,
};
-static struct camera_vreg_t apq_8064_s5k3l1yx_vreg[] = {
- {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
- {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
- {"cam_vio", REG_VS, 0, 0, 0},
- {"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
-};
-
static struct msm_camera_sensor_flash_data flash_s5k3l1yx = {
.flash_type = MSM_CAMERA_FLASH_NONE,
};
@@ -574,8 +553,8 @@
static struct msm_camera_sensor_platform_info sensor_board_info_s5k3l1yx = {
.mount_angle = 90,
- .cam_vreg = apq_8064_s5k3l1yx_vreg,
- .num_vreg = ARRAY_SIZE(apq_8064_s5k3l1yx_vreg),
+ .cam_vreg = apq_8064_cam_vreg,
+ .num_vreg = ARRAY_SIZE(apq_8064_cam_vreg),
.gpio_conf = &apq8064_back_cam_gpio_conf,
.i2c_conf = &apq8064_back_cam_i2c_conf,
.csi_lane_params = &s5k3l1yx_csi_lane_params,
@@ -591,13 +570,6 @@
.sensor_type = BAYER_SENSOR,
};
-static struct camera_vreg_t apq_8064_mt9m114_vreg[] = {
- {"cam_vio", REG_VS, 0, 0, 0},
- {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
- {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
- {"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
-};
-
static struct msm_camera_sensor_flash_data flash_mt9m114 = {
.flash_type = MSM_CAMERA_FLASH_NONE
};
@@ -609,8 +581,8 @@
static struct msm_camera_sensor_platform_info sensor_board_info_mt9m114 = {
.mount_angle = 90,
- .cam_vreg = apq_8064_mt9m114_vreg,
- .num_vreg = ARRAY_SIZE(apq_8064_mt9m114_vreg),
+ .cam_vreg = apq_8064_cam_vreg,
+ .num_vreg = ARRAY_SIZE(apq_8064_cam_vreg),
.gpio_conf = &apq8064_front_cam_gpio_conf,
.i2c_conf = &apq8064_front_cam_i2c_conf,
.csi_lane_params = &mt9m114_csi_lane_params,
@@ -637,8 +609,8 @@
static struct msm_camera_sensor_platform_info sensor_board_info_ov2720 = {
.mount_angle = 0,
- .cam_vreg = apq_8064_front_cam_vreg,
- .num_vreg = ARRAY_SIZE(apq_8064_front_cam_vreg),
+ .cam_vreg = apq_8064_cam_vreg,
+ .num_vreg = ARRAY_SIZE(apq_8064_cam_vreg),
.gpio_conf = &apq8064_front_cam_gpio_conf,
.i2c_conf = &apq8064_front_cam_i2c_conf,
.csi_lane_params = &ov2720_csi_lane_params,
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index 5780ca1..d0f1e87 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -62,6 +62,7 @@
#define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME "mipi_video_toshiba_wsvga"
#define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
#define HDMI_PANEL_NAME "hdmi_msm"
+#define MHL_PANEL_NAME "hdmi_msm,mhl_8334"
#define TVOUT_PANEL_NAME "tvout_msm"
#define LVDS_PIXEL_MAP_PATTERN_1 1
@@ -73,11 +74,18 @@
static unsigned char hdmi_is_primary;
#endif
+static unsigned char mhl_display_enabled;
+
unsigned char apq8064_hdmi_as_primary_selected(void)
{
return hdmi_is_primary;
}
+unsigned char apq8064_mhl_display_enabled(void)
+{
+ return mhl_display_enabled;
+}
+
static void set_mdp_clocks_for_wuxga(void);
static int msm_fb_detect_panel(const char *name)
@@ -460,7 +468,11 @@
gpio_set_value_cansleep(gpio36, 0);
gpio_set_value_cansleep(gpio25, 1);
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
+ gpio_set_value_cansleep(gpio26, 1);
} else {
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
+ gpio_set_value_cansleep(gpio26, 0);
gpio_set_value_cansleep(gpio25, 0);
gpio_set_value_cansleep(gpio36, 1);
@@ -591,7 +603,11 @@
gpio_set_value_cansleep(gpio36, 0);
gpio_set_value_cansleep(mpp3, 1);
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
+ gpio_set_value_cansleep(gpio26, 1);
} else {
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
+ gpio_set_value_cansleep(gpio26, 0);
gpio_set_value_cansleep(mpp3, 0);
gpio_set_value_cansleep(gpio36, 1);
@@ -1067,7 +1083,15 @@
PANEL_NAME_MAX_LEN);
pr_debug("msm_fb_pdata.ext_panel_name %s\n",
msm_fb_pdata.ext_panel_name);
+
+ if (!strncmp((char *)msm_fb_pdata.ext_panel_name,
+ MHL_PANEL_NAME, strnlen(MHL_PANEL_NAME,
+ PANEL_NAME_MAX_LEN))) {
+ pr_debug("MHL is external display by boot parameter\n");
+ mhl_display_enabled = 1;
+ }
}
msm_fb_pdata.ext_resolution = resolution;
+ hdmi_msm_data.is_mhl_enabled = mhl_display_enabled;
}
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 0f1ddc0..04326aa 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -26,6 +26,7 @@
#include <mach/board.h>
#include <mach/gpiomux.h>
#include <mach/restart.h>
+#include <mach/socinfo.h>
#include "devices.h"
#include "board-8064.h"
@@ -125,7 +126,7 @@
PM8921_GPIO_INPUT(35, PM_GPIO_PULL_UP_30),
PM8921_GPIO_INPUT(38, PM_GPIO_PULL_UP_30),
/* TABLA CODEC RESET */
- PM8921_GPIO_OUTPUT(34, 1, MED),
+ PM8921_GPIO_OUTPUT(34, 0, MED),
PM8921_GPIO_OUTPUT(13, 0, HIGH), /* PCIE_CLK_PWR_EN */
PM8921_GPIO_INPUT(12, PM_GPIO_PULL_UP_30), /* PCIE_WAKE_N */
};
@@ -141,6 +142,31 @@
PM8921_GPIO_INPUT(17, PM_GPIO_PULL_UP_1P5), /* SD_WP */
};
+/* Initial PM8917 GPIO configurations */
+static struct pm8xxx_gpio_init pm8917_gpios[] __initdata = {
+ PM8921_GPIO_OUTPUT(14, 1, HIGH), /* HDMI Mux Selector */
+ PM8921_GPIO_OUTPUT(23, 0, HIGH), /* touchscreen power FET */
+ PM8921_GPIO_OUTPUT_BUFCONF(25, 0, LOW, CMOS), /* DISP_RESET_N */
+ PM8921_GPIO_OUTPUT(26, 1, HIGH), /* Backlight: on */
+ PM8921_GPIO_OUTPUT_BUFCONF(36, 1, LOW, OPEN_DRAIN),
+ PM8921_GPIO_OUTPUT_FUNC(38, 0, PM_GPIO_FUNC_2),
+ PM8921_GPIO_OUTPUT(33, 0, HIGH),
+ PM8921_GPIO_OUTPUT(20, 0, HIGH),
+ PM8921_GPIO_INPUT(35, PM_GPIO_PULL_UP_30),
+ PM8921_GPIO_INPUT(30, PM_GPIO_PULL_UP_30),
+ /* TABLA CODEC RESET */
+ PM8921_GPIO_OUTPUT(34, 1, MED),
+ PM8921_GPIO_OUTPUT(13, 0, HIGH), /* PCIE_CLK_PWR_EN */
+ PM8921_GPIO_INPUT(12, PM_GPIO_PULL_UP_30), /* PCIE_WAKE_N */
+};
+
+/* PM8921 GPIO 42 remaps to PM8917 GPIO 8 */
+static struct pm8xxx_gpio_init pm8917_cdp_kp_gpios[] __initdata = {
+ PM8921_GPIO_INPUT(27, PM_GPIO_PULL_UP_30),
+ PM8921_GPIO_INPUT(8, PM_GPIO_PULL_UP_30),
+ PM8921_GPIO_INPUT(17, PM_GPIO_PULL_UP_1P5), /* SD_WP */
+};
+
static struct pm8xxx_gpio_init pm8921_mpq_gpios[] __initdata = {
PM8921_GPIO_INIT(27, PM_GPIO_DIR_IN, PM_GPIO_OUT_BUF_CMOS, 0,
PM_GPIO_PULL_NO, PM_GPIO_VIN_VPH, PM_GPIO_STRENGTH_NO,
@@ -157,52 +183,45 @@
PM8921_MPP_INIT(1, D_OUTPUT, PM8921_MPP_DIG_LEVEL_VPH, DOUT_CTRL_HIGH),
};
+
+void __init apq8064_configure_gpios(struct pm8xxx_gpio_init *data, int len)
+{
+ int i, rc;
+
+ for (i = 0; i < len; i++) {
+ rc = pm8xxx_gpio_config(data[i].gpio, &data[i].config);
+ if (rc)
+ pr_err("%s: pm8xxx_gpio_config(%u) failed: rc=%d\n",
+ __func__, data[i].gpio, rc);
+ }
+}
+
void __init apq8064_pm8xxx_gpio_mpp_init(void)
{
int i, rc;
- for (i = 0; i < ARRAY_SIZE(pm8921_gpios); i++) {
- rc = pm8xxx_gpio_config(pm8921_gpios[i].gpio,
- &pm8921_gpios[i].config);
- if (rc) {
- pr_err("%s: pm8xxx_gpio_config: rc=%d\n", __func__, rc);
- break;
- }
+ if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917)
+ apq8064_configure_gpios(pm8921_gpios, ARRAY_SIZE(pm8921_gpios));
+ else
+ apq8064_configure_gpios(pm8917_gpios, ARRAY_SIZE(pm8917_gpios));
+
+ if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid()) {
+ if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917)
+ apq8064_configure_gpios(pm8921_cdp_kp_gpios,
+ ARRAY_SIZE(pm8921_cdp_kp_gpios));
+ else
+ apq8064_configure_gpios(pm8917_cdp_kp_gpios,
+ ARRAY_SIZE(pm8917_cdp_kp_gpios));
}
- if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
- for (i = 0; i < ARRAY_SIZE(pm8921_cdp_kp_gpios); i++) {
- rc = pm8xxx_gpio_config(pm8921_cdp_kp_gpios[i].gpio,
- &pm8921_cdp_kp_gpios[i].config);
- if (rc) {
- pr_err("%s: pm8xxx_gpio_config: rc=%d\n",
- __func__, rc);
- break;
- }
- }
-
if (machine_is_apq8064_mtp())
- for (i = 0; i < ARRAY_SIZE(pm8921_mtp_kp_gpios); i++) {
- rc = pm8xxx_gpio_config(pm8921_mtp_kp_gpios[i].gpio,
- &pm8921_mtp_kp_gpios[i].config);
- if (rc) {
- pr_err("%s: pm8xxx_gpio_config: rc=%d\n",
- __func__, rc);
- break;
- }
- }
+ apq8064_configure_gpios(pm8921_mtp_kp_gpios,
+ ARRAY_SIZE(pm8921_mtp_kp_gpios));
if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd()
- || machine_is_mpq8064_dtv())
- for (i = 0; i < ARRAY_SIZE(pm8921_mpq_gpios); i++) {
- rc = pm8xxx_gpio_config(pm8921_mpq_gpios[i].gpio,
- &pm8921_mpq_gpios[i].config);
- if (rc) {
- pr_err("%s: pm8xxx_gpio_config: rc=%d\n",
- __func__, rc);
- break;
- }
- }
+ || machine_is_mpq8064_dtv())
+ apq8064_configure_gpios(pm8921_mpq_gpios,
+ ARRAY_SIZE(pm8921_mpq_gpios));
for (i = 0; i < ARRAY_SIZE(pm8xxx_mpps); i++) {
rc = pm8xxx_mpp_config(pm8xxx_mpps[i].mpp,
@@ -380,6 +399,7 @@
.warm_bat_voltage = 4100,
.thermal_mitigation = apq8064_pm8921_therm_mitigation,
.thermal_levels = ARRAY_SIZE(apq8064_pm8921_therm_mitigation),
+ .rconn_mohm = 18,
};
static struct pm8xxx_ccadc_platform_data
@@ -402,7 +422,6 @@
static struct pm8921_platform_data
apq8064_pm8921_platform_data __devinitdata = {
- .regulator_pdatas = msm8064_pm8921_regulator_pdata,
.irq_pdata = &apq8064_pm8921_irq_pdata,
.gpio_pdata = &apq8064_pm8921_gpio_pdata,
.mpp_pdata = &apq8064_pm8921_mpp_pdata,
@@ -459,12 +478,23 @@
&apq8064_ssbi_pm8921_pdata;
apq8064_device_ssbi_pmic2.dev.platform_data =
&apq8064_ssbi_pm8821_pdata;
- apq8064_pm8921_platform_data.num_regulators =
- msm8064_pm8921_regulator_pdata_len;
+ if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917) {
+ apq8064_pm8921_platform_data.regulator_pdatas
+ = msm8064_pm8921_regulator_pdata;
+ apq8064_pm8921_platform_data.num_regulators
+ = msm8064_pm8921_regulator_pdata_len;
+ } else {
+ apq8064_pm8921_platform_data.regulator_pdatas
+ = msm8064_pm8917_regulator_pdata;
+ apq8064_pm8921_platform_data.num_regulators
+ = msm8064_pm8917_regulator_pdata_len;
+ }
if (machine_is_apq8064_mtp()) {
apq8064_pm8921_bms_pdata.battery_type = BATT_PALLADIUM;
} else if (machine_is_apq8064_liquid()) {
apq8064_pm8921_bms_pdata.battery_type = BATT_DESAY;
+ } else if (machine_is_apq8064_cdp()) {
+ apq8064_pm8921_chg_pdata.has_dc_supply = true;
}
}
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 10b7034..819f5d9 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -18,6 +18,7 @@
#define VREG_CONSUMERS(_id) \
static struct regulator_consumer_supply vreg_consumers_##_id[]
+/* Regulators that are present when using either PM8921 or PM8917 */
/*
* Consumer specific regulator names:
* regulator name consumer dev_name
@@ -143,9 +144,6 @@
VREG_CONSUMERS(L29) = {
REGULATOR_SUPPLY("8921_l29", NULL),
};
-VREG_CONSUMERS(S1) = {
- REGULATOR_SUPPLY("8921_s1", NULL),
-};
VREG_CONSUMERS(S2) = {
REGULATOR_SUPPLY("8921_s2", NULL),
REGULATOR_SUPPLY("iris_vddrfa", "wcnss_wlan.0"),
@@ -195,10 +193,6 @@
REGULATOR_SUPPLY("8921_lvs1", NULL),
REGULATOR_SUPPLY("iris_vddio", "wcnss_wlan.0"),
};
-VREG_CONSUMERS(LVS2) = {
- REGULATOR_SUPPLY("8921_lvs2", NULL),
- REGULATOR_SUPPLY("iris_vdddig", "wcnss_wlan.0"),
-};
VREG_CONSUMERS(LVS3) = {
REGULATOR_SUPPLY("8921_lvs3", NULL),
};
@@ -228,13 +222,6 @@
REGULATOR_SUPPLY("8921_usb_otg", NULL),
REGULATOR_SUPPLY("vbus_otg", "msm_otg"),
};
-VREG_CONSUMERS(HDMI_MVS) = {
- REGULATOR_SUPPLY("8921_hdmi_mvs", NULL),
- REGULATOR_SUPPLY("hdmi_mvs", "hdmi_msm.0"),
-};
-VREG_CONSUMERS(NCP) = {
- REGULATOR_SUPPLY("8921_ncp", NULL),
-};
VREG_CONSUMERS(8821_S0) = {
REGULATOR_SUPPLY("8821_s0", NULL),
REGULATOR_SUPPLY("krait2", "acpuclk-8064"),
@@ -243,11 +230,6 @@
REGULATOR_SUPPLY("8821_s1", NULL),
REGULATOR_SUPPLY("krait3", "acpuclk-8064"),
};
-VREG_CONSUMERS(EXT_5V) = {
- REGULATOR_SUPPLY("ext_5v", NULL),
- REGULATOR_SUPPLY("ext_ddr3", NULL),
- REGULATOR_SUPPLY("vbus", "msm_ehci_host.0"),
-};
VREG_CONSUMERS(EXT_MPP8) = {
REGULATOR_SUPPLY("ext_mpp8", NULL),
REGULATOR_SUPPLY("vbus", "msm_ehci_host.1"),
@@ -281,6 +263,60 @@
REGULATOR_SUPPLY("avc_3p3v", NULL),
};
+/* Regulators that are only present when using PM8921 */
+VREG_CONSUMERS(S1) = {
+ REGULATOR_SUPPLY("8921_s1", NULL),
+};
+VREG_CONSUMERS(LVS2) = {
+ REGULATOR_SUPPLY("8921_lvs2", NULL),
+ REGULATOR_SUPPLY("iris_vdddig", "wcnss_wlan.0"),
+};
+VREG_CONSUMERS(HDMI_MVS) = {
+ REGULATOR_SUPPLY("8921_hdmi_mvs", NULL),
+ REGULATOR_SUPPLY("hdmi_mvs", "hdmi_msm.0"),
+};
+VREG_CONSUMERS(NCP) = {
+ REGULATOR_SUPPLY("8921_ncp", NULL),
+};
+VREG_CONSUMERS(EXT_5V) = {
+ REGULATOR_SUPPLY("ext_5v", NULL),
+ REGULATOR_SUPPLY("ext_ddr3", NULL),
+ REGULATOR_SUPPLY("vbus", "msm_ehci_host.0"),
+};
+
+/* Regulators that are only present when using PM8917 */
+VREG_CONSUMERS(8917_S1) = {
+ REGULATOR_SUPPLY("8921_s1", NULL),
+ REGULATOR_SUPPLY("iris_vdddig", "wcnss_wlan.0"),
+};
+VREG_CONSUMERS(L30) = {
+ REGULATOR_SUPPLY("8917_l30", NULL),
+};
+VREG_CONSUMERS(L31) = {
+ REGULATOR_SUPPLY("8917_l31", NULL),
+};
+VREG_CONSUMERS(L32) = {
+ REGULATOR_SUPPLY("8917_l32", NULL),
+};
+VREG_CONSUMERS(L33) = {
+ REGULATOR_SUPPLY("8917_l33", NULL),
+};
+VREG_CONSUMERS(L34) = {
+ REGULATOR_SUPPLY("8917_l34", NULL),
+};
+VREG_CONSUMERS(L35) = {
+ REGULATOR_SUPPLY("8917_l35", NULL),
+};
+VREG_CONSUMERS(L36) = {
+ REGULATOR_SUPPLY("8917_l36", NULL),
+};
+VREG_CONSUMERS(BOOST) = {
+ REGULATOR_SUPPLY("8917_boost", NULL),
+ REGULATOR_SUPPLY("ext_ddr3", NULL),
+ REGULATOR_SUPPLY("vbus", "msm_ehci_host.0"),
+ REGULATOR_SUPPLY("hdmi_mvs", "hdmi_msm.0"),
+};
+
#define PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
_apply_uV, _pull_down, _always_on, _supply_regulator, \
_system_uA, _enable_time, _reg_id) \
@@ -356,6 +392,12 @@
REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, 0, 0, \
_always_on, _supply_regulator, 0, _enable_time, _reg_id)
+#define PM8XXX_BOOST(_id, _name, _always_on, _min_uV, _max_uV, _enable_time, \
+ _supply_regulator, _reg_id) \
+ PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, 0, \
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, 0, 0, \
+ _always_on, _supply_regulator, 0, _enable_time, _reg_id)
+
/* Pin control initialization */
#define PM8XXX_PC(_id, _name, _always_on, _pin_fn, _pin_ctrl, \
_supply_regulator, _reg_id) \
@@ -553,6 +595,39 @@
PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1, 0, "ext_5v", 3),
};
+/* PM8917 regulator constraints */
+struct pm8xxx_regulator_platform_data
+msm8064_pm8917_regulator_pdata[] __devinitdata = {
+ /*
+ * ID name always_on pd min_uV max_uV en_t supply
+ * system_uA reg_ID
+ */
+ PM8XXX_NLDO1200(L26, "8921_l26", 0, 1, 375000, 1050000, 200, "8921_s7",
+ 0, 1),
+ PM8XXX_LDO(L30, "8917_l30", 0, 1, 1800000, 1800000, 200, NULL,
+ 0, 2),
+ PM8XXX_LDO(L31, "8917_l31", 0, 1, 1800000, 1800000, 200, NULL,
+ 0, 3),
+ PM8XXX_LDO(L32, "8917_l32", 0, 1, 2800000, 2800000, 200, NULL,
+ 0, 4),
+ PM8XXX_LDO(L33, "8917_l33", 0, 1, 2800000, 2800000, 200, NULL,
+ 0, 5),
+ PM8XXX_LDO(L34, "8917_l34", 0, 1, 1800000, 1800000, 200, NULL,
+ 0, 6),
+ PM8XXX_LDO(L35, "8917_l35", 0, 1, 3000000, 3000000, 200, NULL,
+ 0, 7),
+ PM8XXX_LDO(L36, "8917_l36", 0, 1, 1800000, 1800000, 200, NULL,
+ 0, 8),
+
+ /*
+ * ID name always_on min_uV max_uV en_t supply reg_ID
+ */
+ PM8XXX_BOOST(BOOST, "8917_boost", 0, 5000000, 5000000, 500, NULL, 9),
+
+ /* ID name always_on pd en_t supply reg_ID */
+ PM8XXX_VS300(USB_OTG, "8921_usb_otg", 0, 1, 0, "8917_boost", 10),
+};
+
static struct rpm_regulator_init_data
apq8064_rpm_regulator_init_data[] __devinitdata = {
/* ID a_on pd ss min_uV max_uV supply sys_uA freq fm ss_fm */
@@ -592,12 +667,17 @@
/* ID a_on pd ss supply */
RPM_VS(LVS1, 0, 1, 0, "8921_s4"),
- RPM_VS(LVS2, 0, 1, 0, "8921_s1"),
RPM_VS(LVS3, 0, 1, 0, "8921_s4"),
RPM_VS(LVS4, 0, 1, 0, "8921_s4"),
RPM_VS(LVS5, 0, 1, 0, "8921_s4"),
RPM_VS(LVS6, 0, 1, 0, "8921_s4"),
RPM_VS(LVS7, 0, 1, 1, "8921_s4"),
+};
+
+static struct rpm_regulator_init_data
+apq8064_rpm_regulator_pm8921_init_data[] __devinitdata = {
+ /* ID a_on pd ss supply */
+ RPM_VS(LVS2, 0, 1, 0, "8921_s1"),
/* ID a_on ss min_uV max_uV supply freq */
RPM_NCP(NCP, 0, 0, 1800000, 1800000, "8921_l6", 1p60),
@@ -605,6 +685,8 @@
int msm8064_pm8921_regulator_pdata_len __devinitdata =
ARRAY_SIZE(msm8064_pm8921_regulator_pdata);
+int msm8064_pm8917_regulator_pdata_len __devinitdata =
+ ARRAY_SIZE(msm8064_pm8917_regulator_pdata);
#define RPM_REG_MAP(_id, _sleep_also, _voter, _supply, _dev_name) \
{ \
@@ -641,3 +723,34 @@
.consumer_map = msm_rpm_regulator_consumer_mapping,
.consumer_map_len = ARRAY_SIZE(msm_rpm_regulator_consumer_mapping),
};
+
+/* Regulators that are only present when using PM8921 */
+struct rpm_regulator_platform_data
+apq8064_rpm_regulator_pm8921_pdata __devinitdata = {
+ .init_data = apq8064_rpm_regulator_pm8921_init_data,
+ .num_regulators = ARRAY_SIZE(apq8064_rpm_regulator_pm8921_init_data),
+ .version = RPM_VREG_VERSION_8960,
+ .vreg_id_vdd_mem = RPM_VREG_ID_PM8921_L24,
+ .vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3,
+ .requires_tcxo_workaround = true,
+};
+
+/*
+ * Fix up regulator consumer data that moves to a different regulator when
+ * PM8917 is used.
+ */
+void __init configure_apq8064_pm8917_power_grid(void)
+{
+ static struct rpm_regulator_init_data *rpm_data;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(apq8064_rpm_regulator_init_data); i++) {
+ rpm_data = &apq8064_rpm_regulator_init_data[i];
+ if (rpm_data->id == RPM_VREG_ID_PM8921_S1) {
+ rpm_data->init_data.consumer_supplies
+ = vreg_consumers_8917_S1;
+ rpm_data->init_data.num_consumer_supplies
+ = ARRAY_SIZE(vreg_consumers_8917_S1);
+ }
+ }
+}
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index ab9004f..7070b42 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1181,13 +1181,18 @@
#define HAP_SHIFT_LVL_OE_GPIO PM8921_MPP_PM_TO_SYS(8)
#define ISA1200_HAP_EN_GPIO PM8921_GPIO_PM_TO_SYS(33)
#define ISA1200_HAP_LEN_GPIO PM8921_GPIO_PM_TO_SYS(20)
-#define ISA1200_HAP_CLK PM8921_GPIO_PM_TO_SYS(44)
+#define ISA1200_HAP_CLK_PM8921 PM8921_GPIO_PM_TO_SYS(44)
+#define ISA1200_HAP_CLK_PM8917 PM8921_GPIO_PM_TO_SYS(38)
static int isa1200_clk_enable(bool on)
{
+ unsigned int gpio = ISA1200_HAP_CLK_PM8921;
int rc = 0;
- gpio_set_value_cansleep(ISA1200_HAP_CLK, on);
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
+ gpio = ISA1200_HAP_CLK_PM8917;
+
+ gpio_set_value_cansleep(gpio, on);
if (on) {
rc = pm8xxx_aux_clk_control(CLK_MP3_2, XO_DIV_1, true);
@@ -1206,25 +1211,29 @@
return rc;
err_gpio_dis:
- gpio_set_value_cansleep(ISA1200_HAP_CLK, !on);
+ gpio_set_value_cansleep(gpio, !on);
return rc;
}
static int isa1200_dev_setup(bool enable)
{
+ unsigned int gpio = ISA1200_HAP_CLK_PM8921;
int rc = 0;
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
+ gpio = ISA1200_HAP_CLK_PM8917;
+
if (!enable)
goto free_gpio;
- rc = gpio_request(ISA1200_HAP_CLK, "haptics_clk");
+ rc = gpio_request(gpio, "haptics_clk");
if (rc) {
pr_err("%s: unable to request gpio %d config(%d)\n",
- __func__, ISA1200_HAP_CLK, rc);
+ __func__, gpio, rc);
return rc;
}
- rc = gpio_direction_output(ISA1200_HAP_CLK, 0);
+ rc = gpio_direction_output(gpio, 0);
if (rc) {
pr_err("%s: unable to set direction\n", __func__);
goto free_gpio;
@@ -1233,7 +1242,7 @@
return 0;
free_gpio:
- gpio_free(ISA1200_HAP_CLK);
+ gpio_free(gpio);
return rc;
}
@@ -2147,12 +2156,21 @@
static struct platform_device apq8064_device_rpm_regulator __devinitdata = {
.name = "rpm-regulator",
- .id = -1,
+ .id = 0,
.dev = {
.platform_data = &apq8064_rpm_regulator_pdata,
},
};
+static struct platform_device
+apq8064_pm8921_device_rpm_regulator __devinitdata = {
+ .name = "rpm-regulator",
+ .id = 1,
+ .dev = {
+ .platform_data = &apq8064_rpm_regulator_pm8921_pdata,
+ },
+};
+
static struct gpio_ir_recv_platform_data gpio_ir_recv_pdata = {
.gpio_nr = 88,
.active_low = 1,
@@ -2171,16 +2189,30 @@
&apq8064_device_qup_i2c_gsbi4,
};
-static struct platform_device *common_devices[] __initdata = {
+static struct platform_device *early_common_devices[] __initdata = {
&apq8064_device_acpuclk,
&apq8064_device_dmov,
&apq8064_device_qup_spi_gsbi5,
+};
+
+static struct platform_device *pm8921_common_devices[] __initdata = {
&apq8064_device_ext_5v_vreg,
&apq8064_device_ext_mpp8_vreg,
&apq8064_device_ext_3p3v_vreg,
&apq8064_device_ssbi_pmic1,
&apq8064_device_ssbi_pmic2,
&apq8064_device_ext_ts_sw_vreg,
+};
+
+static struct platform_device *pm8917_common_devices[] __initdata = {
+ &apq8064_device_ext_mpp8_vreg,
+ &apq8064_device_ext_3p3v_vreg,
+ &apq8064_device_ssbi_pmic1,
+ &apq8064_device_ssbi_pmic2,
+ &apq8064_device_ext_ts_sw_vreg,
+};
+
+static struct platform_device *common_devices[] __initdata = {
&msm_device_smd_apq8064,
&apq8064_device_otg,
&apq8064_device_gadget_peripheral,
@@ -2506,14 +2538,16 @@
}
#endif
-#define GPIO_KEY_HOME PM8921_GPIO_PM_TO_SYS(27)
-#define GPIO_KEY_VOLUME_UP PM8921_GPIO_PM_TO_SYS(35)
-#define GPIO_KEY_VOLUME_DOWN PM8921_GPIO_PM_TO_SYS(38)
-#define GPIO_KEY_CAM_FOCUS PM8921_GPIO_PM_TO_SYS(3)
-#define GPIO_KEY_CAM_SNAP PM8921_GPIO_PM_TO_SYS(4)
-#define GPIO_KEY_ROTATION PM8921_GPIO_PM_TO_SYS(42)
+#define GPIO_KEY_HOME PM8921_GPIO_PM_TO_SYS(27)
+#define GPIO_KEY_VOLUME_UP PM8921_GPIO_PM_TO_SYS(35)
+#define GPIO_KEY_VOLUME_DOWN_PM8921 PM8921_GPIO_PM_TO_SYS(38)
+#define GPIO_KEY_VOLUME_DOWN_PM8917 PM8921_GPIO_PM_TO_SYS(30)
+#define GPIO_KEY_CAM_FOCUS PM8921_GPIO_PM_TO_SYS(3)
+#define GPIO_KEY_CAM_SNAP PM8921_GPIO_PM_TO_SYS(4)
+#define GPIO_KEY_ROTATION_PM8921 PM8921_GPIO_PM_TO_SYS(42)
+#define GPIO_KEY_ROTATION_PM8917 PM8921_GPIO_PM_TO_SYS(8)
-static struct gpio_keys_button cdp_keys[] = {
+static struct gpio_keys_button cdp_keys_pm8921[] = {
{
.code = KEY_HOME,
.gpio = GPIO_KEY_HOME,
@@ -2534,7 +2568,7 @@
},
{
.code = KEY_VOLUMEDOWN,
- .gpio = GPIO_KEY_VOLUME_DOWN,
+ .gpio = GPIO_KEY_VOLUME_DOWN_PM8921,
.desc = "volume_down_key",
.active_low = 1,
.type = EV_KEY,
@@ -2543,7 +2577,45 @@
},
{
.code = SW_ROTATE_LOCK,
- .gpio = GPIO_KEY_ROTATION,
+ .gpio = GPIO_KEY_ROTATION_PM8921,
+ .desc = "rotate_key",
+ .active_low = 1,
+ .type = EV_SW,
+ .debounce_interval = 15,
+ },
+};
+
+static struct gpio_keys_button cdp_keys_pm8917[] = {
+ {
+ .code = KEY_HOME,
+ .gpio = GPIO_KEY_HOME,
+ .desc = "home_key",
+ .active_low = 1,
+ .type = EV_KEY,
+ .wakeup = 1,
+ .debounce_interval = 15,
+ },
+ {
+ .code = KEY_VOLUMEUP,
+ .gpio = GPIO_KEY_VOLUME_UP,
+ .desc = "volume_up_key",
+ .active_low = 1,
+ .type = EV_KEY,
+ .wakeup = 1,
+ .debounce_interval = 15,
+ },
+ {
+ .code = KEY_VOLUMEDOWN,
+ .gpio = GPIO_KEY_VOLUME_DOWN_PM8917,
+ .desc = "volume_down_key",
+ .active_low = 1,
+ .type = EV_KEY,
+ .wakeup = 1,
+ .debounce_interval = 15,
+ },
+ {
+ .code = SW_ROTATE_LOCK,
+ .gpio = GPIO_KEY_ROTATION_PM8917,
.desc = "rotate_key",
.active_low = 1,
.type = EV_SW,
@@ -2552,8 +2624,8 @@
};
static struct gpio_keys_platform_data cdp_keys_data = {
- .buttons = cdp_keys,
- .nbuttons = ARRAY_SIZE(cdp_keys),
+ .buttons = cdp_keys_pm8921,
+ .nbuttons = ARRAY_SIZE(cdp_keys_pm8921),
};
static struct platform_device cdp_kp_pdev = {
@@ -2585,7 +2657,7 @@
},
{
.code = KEY_VOLUMEDOWN,
- .gpio = GPIO_KEY_VOLUME_DOWN,
+ .gpio = GPIO_KEY_VOLUME_DOWN_PM8921,
.desc = "volume_down_key",
.active_low = 1,
.type = EV_KEY,
@@ -2618,7 +2690,7 @@
static struct gpio_keys_button mpq_keys[] = {
{
.code = KEY_VOLUMEDOWN,
- .gpio = GPIO_KEY_VOLUME_DOWN,
+ .gpio = GPIO_KEY_VOLUME_DOWN_PM8921,
.desc = "volume_down_key",
.active_low = 1,
.type = EV_KEY,
@@ -2912,9 +2984,19 @@
gpio_set_value_cansleep(avc_i2c_en_mpp, 1);
}
+/* Modify platform data values to match requirements for PM8917. */
+static void __init apq8064_pm8917_pdata_fixup(void)
+{
+ cdp_keys_data.buttons = cdp_keys_pm8917;
+ cdp_keys_data.nbuttons = ARRAY_SIZE(cdp_keys_pm8917);
+}
+
static void __init apq8064_common_init(void)
{
u32 platform_version;
+
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
+ apq8064_pm8917_pdata_fixup();
platform_device_register(&msm_gpio_device);
msm_tsens_early_init(&apq_tsens_pdata);
msm_thermal_init(&msm_thermal_pdata);
@@ -2923,7 +3005,11 @@
BUG_ON(msm_rpm_init(&apq8064_rpm_data));
BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
regulator_suppress_info_printing();
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
+ configure_apq8064_pm8917_power_grid();
platform_device_register(&apq8064_device_rpm_regulator);
+ if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917)
+ platform_device_register(&apq8064_pm8921_device_rpm_regulator);
if (msm_xo_init())
pr_err("Failed to initialize XO votes\n");
msm_clock_init(&apq8064_clock_init_data);
@@ -2943,6 +3029,15 @@
apq8064_device_otg.dev.platform_data = &msm_otg_pdata;
apq8064_ehci_host_init();
apq8064_init_buses();
+
+ platform_add_devices(early_common_devices,
+ ARRAY_SIZE(early_common_devices));
+ if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917)
+ platform_add_devices(pm8921_common_devices,
+ ARRAY_SIZE(pm8921_common_devices));
+ else
+ platform_add_devices(pm8917_common_devices,
+ ARRAY_SIZE(pm8917_common_devices));
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
if (!(machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
machine_is_mpq8064_dtv()))
@@ -2950,6 +3045,7 @@
ARRAY_SIZE(common_not_mpq_devices));
enable_ddr3_regulator();
if (machine_is_apq8064_mtp()) {
+ msm_hsic_pdata.log2_irq_thresh = 5,
apq8064_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
device_initialize(&apq8064_device_hsic_host.dev);
}
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index 2258b8d..1437b3b 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -40,6 +40,11 @@
extern int msm8064_pm8921_regulator_pdata_len __devinitdata;
+extern struct pm8xxx_regulator_platform_data
+ msm8064_pm8917_regulator_pdata[] __devinitdata;
+
+extern int msm8064_pm8917_regulator_pdata_len __devinitdata;
+
#define GPIO_VREG_ID_EXT_5V 0
#define GPIO_VREG_ID_EXT_3P3V 1
#define GPIO_VREG_ID_EXT_TS_SW 2
@@ -62,6 +67,9 @@
extern struct rpm_regulator_platform_data
apq8064_rpm_regulator_pdata __devinitdata;
+extern struct rpm_regulator_platform_data
+ apq8064_rpm_regulator_pm8921_pdata __devinitdata;
+
extern struct regulator_init_data msm8064_saw_regulator_pdata_8921_s5;
extern struct regulator_init_data msm8064_saw_regulator_pdata_8921_s6;
extern struct regulator_init_data msm8064_saw_regulator_pdata_8821_s0;
@@ -84,6 +92,7 @@
#define APQ_8064_GSBI5_QUP_I2C_BUS_ID 5
unsigned char apq8064_hdmi_as_primary_selected(void);
+unsigned char apq8064_mhl_display_enabled(void);
void apq8064_init_fb(void);
void apq8064_allocate_fb_region(void);
void apq8064_mdp_writeback(struct memtype_reserve *reserve_table);
@@ -92,6 +101,7 @@
void apq8064_init_gpu(void);
void apq8064_pm8xxx_gpio_mpp_init(void);
+void __init configure_apq8064_pm8917_power_grid(void);
#define PLATFORM_IS_MPQ8064() \
(machine_is_mpq8064_hrd() || \
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index d3e37cd..1352928 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -13,7 +13,7 @@
#include <asm/mach-types.h>
#include <linux/gpio.h>
-#include <mach/board.h>
+#include <mach/camera.h>
#include <mach/msm_bus_board.h>
#include <mach/gpiomux.h>
#include "devices.h"
@@ -377,19 +377,13 @@
},
};
-static struct camera_vreg_t msm_8930_back_cam_vreg[] = {
+static struct camera_vreg_t msm_8930_cam_vreg[] = {
{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
{"cam_vio", REG_VS, 0, 0, 0},
{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
{"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
};
-static struct camera_vreg_t msm_8930_front_cam_vreg[] = {
- {"cam_vio", REG_VS, 0, 0, 0},
- {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
- {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
-};
-
static struct gpio msm8930_common_cam_gpio[] = {
{20, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
{21, GPIOF_DIR_IN, "CAMIF_I2C_CLK"},
@@ -466,8 +460,8 @@
static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
.mount_angle = 90,
- .cam_vreg = msm_8930_back_cam_vreg,
- .num_vreg = ARRAY_SIZE(msm_8930_back_cam_vreg),
+ .cam_vreg = msm_8930_cam_vreg,
+ .num_vreg = ARRAY_SIZE(msm_8930_cam_vreg),
.gpio_conf = &msm_8930_back_cam_gpio_conf,
.csi_lane_params = &imx074_csi_lane_params,
};
@@ -484,13 +478,6 @@
.actuator_info = &msm_act_main_cam_0_info,
};
-static struct camera_vreg_t msm_8930_mt9m114_vreg[] = {
- {"cam_vio", REG_VS, 0, 0, 0},
- {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
- {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
- {"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
-};
-
static struct msm_camera_sensor_flash_data flash_mt9m114 = {
.flash_type = MSM_CAMERA_FLASH_NONE
};
@@ -502,8 +489,8 @@
static struct msm_camera_sensor_platform_info sensor_board_info_mt9m114 = {
.mount_angle = 90,
- .cam_vreg = msm_8930_mt9m114_vreg,
- .num_vreg = ARRAY_SIZE(msm_8930_mt9m114_vreg),
+ .cam_vreg = msm_8930_cam_vreg,
+ .num_vreg = ARRAY_SIZE(msm_8930_cam_vreg),
.gpio_conf = &msm_8930_front_cam_gpio_conf,
.csi_lane_params = &mt9m114_csi_lane_params,
};
@@ -529,8 +516,8 @@
static struct msm_camera_sensor_platform_info sensor_board_info_ov2720 = {
.mount_angle = 0,
- .cam_vreg = msm_8930_front_cam_vreg,
- .num_vreg = ARRAY_SIZE(msm_8930_front_cam_vreg),
+ .cam_vreg = msm_8930_cam_vreg,
+ .num_vreg = ARRAY_SIZE(msm_8930_cam_vreg),
.gpio_conf = &msm_8930_front_cam_gpio_conf,
.csi_lane_params = &ov2720_csi_lane_params,
};
@@ -545,13 +532,6 @@
.sensor_type = BAYER_SENSOR,
};
-static struct camera_vreg_t msm_8930_s5k3l1yx_vreg[] = {
- {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
- {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
- {"cam_vio", REG_VS, 0, 0, 0},
- {"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
-};
-
static struct msm_camera_sensor_flash_data flash_s5k3l1yx = {
.flash_type = MSM_CAMERA_FLASH_LED,
.flash_src = &msm_flash_src
@@ -564,8 +544,8 @@
static struct msm_camera_sensor_platform_info sensor_board_info_s5k3l1yx = {
.mount_angle = 90,
- .cam_vreg = msm_8930_s5k3l1yx_vreg,
- .num_vreg = ARRAY_SIZE(msm_8930_s5k3l1yx_vreg),
+ .cam_vreg = msm_8930_cam_vreg,
+ .num_vreg = ARRAY_SIZE(msm_8930_cam_vreg),
.gpio_conf = &msm_8930_back_cam_gpio_conf,
.csi_lane_params = &s5k3l1yx_csi_lane_params,
};
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index 2a8e918..4b4a51a 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -135,6 +135,8 @@
static int mipi_dsi_cdp_panel_power(int on)
{
static struct regulator *reg_l8, *reg_l23, *reg_l2;
+ /* Control backlight GPIO (24) directly when using PM8917 */
+ int gpio24 = PM8917_GPIO_PM_TO_SYS(24);
int rc;
pr_debug("%s: state : %d\n", __func__, on);
@@ -190,13 +192,21 @@
rc);
gpio_free(DISP_3D_2D_MODE);
return -ENODEV;
- }
+ }
rc = gpio_direction_output(DISP_3D_2D_MODE, 0);
if (rc) {
pr_err("gpio_direction_output failed for %d gpio rc=%d\n",
DISP_3D_2D_MODE, rc);
return -ENODEV;
+ }
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
+ rc = gpio_request(gpio24, "disp_bl");
+ if (rc) {
+ pr_err("request for gpio 24 failed, rc=%d\n",
+ rc);
+ return -ENODEV;
}
+ }
dsi_power_on = true;
}
if (on) {
@@ -238,6 +248,8 @@
gpio_set_value(DISP_RST_GPIO, 1);
gpio_set_value(DISP_3D_2D_MODE, 1);
usleep(20);
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
+ gpio_set_value_cansleep(gpio24, 1);
} else {
gpio_set_value(DISP_RST_GPIO, 0);
@@ -274,6 +286,8 @@
}
gpio_set_value(DISP_3D_2D_MODE, 0);
usleep(20);
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
+ gpio_set_value_cansleep(gpio24, 0);
}
return 0;
}
diff --git a/arch/arm/mach-msm/board-8930-gpiomux.c b/arch/arm/mach-msm/board-8930-gpiomux.c
index ff0a61f..2331b0b 100644
--- a/arch/arm/mach-msm/board-8930-gpiomux.c
+++ b/arch/arm/mach-msm/board-8930-gpiomux.c
@@ -45,14 +45,14 @@
static struct gpiomux_setting gsbi5 = {
.func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_NONE,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
};
static struct gpiomux_setting gsbi9 = {
.func = GPIOMUX_FUNC_2,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_NONE,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
};
static struct gpiomux_setting gsbi10 = {
@@ -96,14 +96,20 @@
static struct gpiomux_setting audio_spkr_boost = {
.func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_8MA,
- .pull = GPIOMUX_PULL_NONE,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
};
#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
-static struct gpiomux_setting gpio_eth_config = {
+static struct gpiomux_setting gpio_eth_suspend_1_cfg = {
+ .pull = GPIOMUX_PULL_DOWN,
+ .drv = GPIOMUX_DRV_2MA,
+ .func = GPIOMUX_FUNC_GPIO,
+};
+
+static struct gpiomux_setting gpio_eth_suspend_2_cfg = {
.pull = GPIOMUX_PULL_NONE,
- .drv = GPIOMUX_DRV_8MA,
+ .drv = GPIOMUX_DRV_2MA,
.func = GPIOMUX_FUNC_GPIO,
};
#endif
@@ -274,18 +280,25 @@
#endif
+static struct gpiomux_setting sitar_reset = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_NONE,
+ .dir = GPIOMUX_OUT_LOW,
+};
+
#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
static struct msm_gpiomux_config msm8960_ethernet_configs[] = {
{
- .gpio = 90,
+ .gpio = 89,
.settings = {
- [GPIOMUX_SUSPENDED] = &gpio_eth_config,
+ [GPIOMUX_SUSPENDED] = &gpio_eth_suspend_1_cfg,
}
},
{
- .gpio = 89,
+ .gpio = 90,
.settings = {
- [GPIOMUX_SUSPENDED] = &gpio_eth_config,
+ [GPIOMUX_SUSPENDED] = &gpio_eth_suspend_2_cfg,
}
},
};
@@ -704,6 +717,15 @@
},
};
+static struct msm_gpiomux_config msm_sitar_config[] __initdata = {
+ {
+ .gpio = 42, /* SYS_RST_N */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &sitar_reset,
+ },
+ }
+};
+
int __init msm8930_init_gpiomux(void)
{
int rc = msm_gpiomux_init(NR_GPIO_IRQS);
@@ -778,5 +800,7 @@
msm_gpiomux_install(msm8930_gyro_int_config,
ARRAY_SIZE(msm8930_gyro_int_config));
+ msm_gpiomux_install(msm_sitar_config, ARRAY_SIZE(msm_sitar_config));
+
return 0;
}
diff --git a/arch/arm/mach-msm/board-8930-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
index e3479eb..b6e20fd 100644
--- a/arch/arm/mach-msm/board-8930-pmic.c
+++ b/arch/arm/mach-msm/board-8930-pmic.c
@@ -18,6 +18,7 @@
#include <asm/mach-types.h>
#include <mach/msm_bus_board.h>
#include <mach/restart.h>
+#include <mach/socinfo.h>
#include "devices.h"
#include "board-8930.h"
@@ -31,7 +32,7 @@
struct pm8xxx_mpp_config_data config;
};
-#define PM8XXX_GPIO_INIT(_gpio, _dir, _buf, _val, _pull, _vin, _out_strength, \
+#define PM8038_GPIO_INIT(_gpio, _dir, _buf, _val, _pull, _vin, _out_strength, \
_func, _inv, _disable) \
{ \
.gpio = PM8038_GPIO_PM_TO_SYS(_gpio), \
@@ -48,7 +49,7 @@
} \
}
-#define PM8XXX_MPP_INIT(_mpp, _type, _level, _control) \
+#define PM8038_MPP_INIT(_mpp, _type, _level, _control) \
{ \
.mpp = PM8038_MPP_PM_TO_SYS(_mpp), \
.config = { \
@@ -58,49 +59,128 @@
} \
}
-#define PM8XXX_GPIO_DISABLE(_gpio) \
- PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, 0, 0, 0, PM8038_GPIO_VIN_L11, \
+#define PM8038_GPIO_DISABLE(_gpio) \
+ PM8038_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, 0, 0, 0, PM8038_GPIO_VIN_L11, \
0, 0, 0, 1)
-#define PM8XXX_GPIO_OUTPUT(_gpio, _val) \
- PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+#define PM8038_GPIO_OUTPUT(_gpio, _val) \
+ PM8038_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
PM_GPIO_PULL_NO, PM8038_GPIO_VIN_L11, \
PM_GPIO_STRENGTH_HIGH, \
PM_GPIO_FUNC_NORMAL, 0, 0)
-#define PM8XXX_GPIO_INPUT(_gpio, _pull) \
- PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, PM_GPIO_OUT_BUF_CMOS, 0, \
+#define PM8038_GPIO_INPUT(_gpio, _pull) \
+ PM8038_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, PM_GPIO_OUT_BUF_CMOS, 0, \
_pull, PM8038_GPIO_VIN_L11, \
PM_GPIO_STRENGTH_NO, \
PM_GPIO_FUNC_NORMAL, 0, 0)
-#define PM8XXX_GPIO_OUTPUT_FUNC(_gpio, _val, _func) \
- PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+#define PM8038_GPIO_OUTPUT_FUNC(_gpio, _val, _func) \
+ PM8038_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
PM_GPIO_PULL_NO, PM8038_GPIO_VIN_L11, \
PM_GPIO_STRENGTH_HIGH, \
_func, 0, 0)
-#define PM8XXX_GPIO_OUTPUT_VIN(_gpio, _val, _vin) \
- PM8XXX_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+#define PM8038_GPIO_OUTPUT_VIN(_gpio, _val, _vin) \
+ PM8038_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
PM_GPIO_PULL_NO, _vin, \
PM_GPIO_STRENGTH_HIGH, \
PM_GPIO_FUNC_NORMAL, 0, 0)
-/* Initial pm8038 GPIO configurations */
+#define PM8917_GPIO_INIT(_gpio, _dir, _buf, _val, _pull, _vin, _out_strength, \
+ _func, _inv, _disable) \
+{ \
+ .gpio = PM8917_GPIO_PM_TO_SYS(_gpio), \
+ .config = { \
+ .direction = _dir, \
+ .output_buffer = _buf, \
+ .output_value = _val, \
+ .pull = _pull, \
+ .vin_sel = _vin, \
+ .out_strength = _out_strength, \
+ .function = _func, \
+ .inv_int_pol = _inv, \
+ .disable_pin = _disable, \
+ } \
+}
+
+#define PM8917_MPP_INIT(_mpp, _type, _level, _control) \
+{ \
+ .mpp = PM8917_MPP_PM_TO_SYS(_mpp), \
+ .config = { \
+ .type = PM8XXX_MPP_TYPE_##_type, \
+ .level = _level, \
+ .control = PM8XXX_MPP_##_control, \
+ } \
+}
+
+#define PM8917_GPIO_DISABLE(_gpio) \
+ PM8917_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, 0, 0, 0, PM_GPIO_VIN_S4, \
+ 0, 0, 0, 1)
+
+#define PM8917_GPIO_OUTPUT(_gpio, _val) \
+ PM8917_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+ PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+ PM_GPIO_STRENGTH_HIGH, \
+ PM_GPIO_FUNC_NORMAL, 0, 0)
+
+#define PM8917_GPIO_INPUT(_gpio, _pull) \
+ PM8917_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, PM_GPIO_OUT_BUF_CMOS, 0, \
+ _pull, PM_GPIO_VIN_S4, \
+ PM_GPIO_STRENGTH_NO, \
+ PM_GPIO_FUNC_NORMAL, 0, 0)
+
+#define PM8917_GPIO_OUTPUT_FUNC(_gpio, _val, _func) \
+ PM8917_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+ PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+ PM_GPIO_STRENGTH_HIGH, \
+ _func, 0, 0)
+
+#define PM8917_GPIO_OUTPUT_VIN(_gpio, _val, _vin) \
+ PM8917_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT, PM_GPIO_OUT_BUF_CMOS, _val, \
+ PM_GPIO_PULL_NO, _vin, \
+ PM_GPIO_STRENGTH_HIGH, \
+ PM_GPIO_FUNC_NORMAL, 0, 0)
+
+/* GPIO and MPP configurations for MSM8930 + PM8038 targets */
+
+/* Initial PM8038 GPIO configurations */
static struct pm8xxx_gpio_init pm8038_gpios[] __initdata = {
/* keys GPIOs */
- PM8XXX_GPIO_INPUT(3, PM_GPIO_PULL_UP_30),
- PM8XXX_GPIO_INPUT(8, PM_GPIO_PULL_UP_30),
- PM8XXX_GPIO_INPUT(10, PM_GPIO_PULL_UP_30),
- PM8XXX_GPIO_INPUT(11, PM_GPIO_PULL_UP_30),
+ PM8038_GPIO_INPUT(3, PM_GPIO_PULL_UP_30),
+ PM8038_GPIO_INPUT(8, PM_GPIO_PULL_UP_30),
+ PM8038_GPIO_INPUT(10, PM_GPIO_PULL_UP_30),
+ PM8038_GPIO_INPUT(11, PM_GPIO_PULL_UP_30),
/* haptics gpio */
- PM8XXX_GPIO_OUTPUT_FUNC(7, 0, PM_GPIO_FUNC_1),
+ PM8038_GPIO_OUTPUT_FUNC(7, 0, PM_GPIO_FUNC_1),
/* MHL PWR EN */
- PM8XXX_GPIO_OUTPUT_VIN(5, 1, PM_GPIO_VIN_VPH),
+ PM8038_GPIO_OUTPUT_VIN(5, 1, PM8038_GPIO_VIN_VPH),
};
-/* Initial pm8038 MPP configurations */
-static struct pm8xxx_mpp_init pm8038_mpps[] __initdata = {};
+/* Initial PM8038 MPP configurations */
+static struct pm8xxx_mpp_init pm8038_mpps[] __initdata = {
+};
+
+/* GPIO and MPP configurations for MSM8930 + PM8917 targets */
+
+/* Initial PM8917 GPIO configurations */
+static struct pm8xxx_gpio_init pm8917_gpios[] __initdata = {
+ /* Backlight enable control */
+ PM8917_GPIO_OUTPUT(24, 1),
+ /* keys GPIOs */
+ PM8917_GPIO_INPUT(27, PM_GPIO_PULL_UP_30),
+ PM8917_GPIO_INPUT(28, PM_GPIO_PULL_UP_30),
+ PM8917_GPIO_INPUT(36, PM_GPIO_PULL_UP_30),
+ PM8917_GPIO_INPUT(37, PM_GPIO_PULL_UP_30),
+ /* haptics gpio */
+ PM8917_GPIO_OUTPUT_FUNC(38, 0, PM_GPIO_FUNC_2),
+ /* MHL PWR EN */
+ PM8917_GPIO_OUTPUT_VIN(25, 1, PM_GPIO_VIN_VPH),
+};
+
+/* Initial PM8917 MPP configurations */
+static struct pm8xxx_mpp_init pm8917_mpps[] __initdata = {
+};
void __init msm8930_pm8038_gpio_mpp_init(void)
{
@@ -126,7 +206,31 @@
}
}
-static struct pm8xxx_adc_amux pm8xxx_adc_channels_data[] = {
+void __init msm8930_pm8917_gpio_mpp_init(void)
+{
+ int i, rc;
+
+ for (i = 0; i < ARRAY_SIZE(pm8917_gpios); i++) {
+ rc = pm8xxx_gpio_config(pm8917_gpios[i].gpio,
+ &pm8917_gpios[i].config);
+ if (rc) {
+ pr_err("%s: pm8xxx_gpio_config: rc=%d\n", __func__, rc);
+ break;
+ }
+ }
+
+ /* Initial MPP configuration. */
+ for (i = 0; i < ARRAY_SIZE(pm8917_mpps); i++) {
+ rc = pm8xxx_mpp_config(pm8917_mpps[i].mpp,
+ &pm8917_mpps[i].config);
+ if (rc) {
+ pr_err("%s: pm8xxx_mpp_config: rc=%d\n", __func__, rc);
+ break;
+ }
+ }
+}
+
+static struct pm8xxx_adc_amux pm8038_adc_channels_data[] = {
{"vcoin", CHANNEL_VCOIN, CHAN_PATH_SCALING2, AMUX_RSV1,
ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
{"vbat", CHANNEL_VBAT, CHAN_PATH_SCALING2, AMUX_RSV1,
@@ -161,16 +265,16 @@
ADC_DECIMATION_TYPE2, ADC_SCALE_PA_THERM},
};
-static struct pm8xxx_adc_properties pm8xxx_adc_data = {
+static struct pm8xxx_adc_properties pm8038_adc_data = {
.adc_vdd_reference = 1800, /* milli-voltage for this adc */
.bitresolution = 15,
.bipolar = 0,
};
-static struct pm8xxx_adc_platform_data pm8xxx_adc_pdata = {
- .adc_channel = pm8xxx_adc_channels_data,
- .adc_num_board_channel = ARRAY_SIZE(pm8xxx_adc_channels_data),
- .adc_prop = &pm8xxx_adc_data,
+static struct pm8xxx_adc_platform_data pm8038_adc_pdata = {
+ .adc_channel = pm8038_adc_channels_data,
+ .adc_num_board_channel = ARRAY_SIZE(pm8038_adc_channels_data),
+ .adc_prop = &pm8038_adc_data,
.adc_mpp_base = PM8038_MPP_PM_TO_SYS(1),
};
@@ -227,6 +331,7 @@
.thermal_mitigation = pm8921_therm_mitigation,
.thermal_levels = ARRAY_SIZE(pm8921_therm_mitigation),
.led_src_config = LED_SRC_VPH_PWR,
+ .rconn_mohm = 18,
};
#define PM8038_WLED_MAX_CURRENT 25
@@ -348,6 +453,7 @@
.shutdown_soc_valid_limit = 20,
.adjust_soc_low_threshold = 25,
.chg_term_ua = CHG_TERM_MA * 1000,
+ .rconn_mohm = 18,
};
static struct pm8038_platform_data pm8038_platform_data __devinitdata = {
@@ -360,7 +466,7 @@
.regulator_pdatas = msm8930_pm8038_regulator_pdata,
.charger_pdata = &pm8921_chg_pdata,
.bms_pdata = &pm8921_bms_pdata,
- .adc_pdata = &pm8xxx_adc_pdata,
+ .adc_pdata = &pm8038_adc_pdata,
.leds_pdata = &pm8xxx_leds_pdata,
.ccadc_pdata = &pm8xxx_ccadc_pdata,
.spk_pdata = &pm8xxx_spk_pdata,
@@ -374,15 +480,99 @@
},
};
+/* PM8917 platform data */
+
+static struct pm8xxx_adc_amux pm8917_adc_channels_data[] = {
+ {"vcoin", CHANNEL_VCOIN, CHAN_PATH_SCALING2, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"vbat", CHANNEL_VBAT, CHAN_PATH_SCALING2, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"dcin", CHANNEL_DCIN, CHAN_PATH_SCALING4, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"ichg", CHANNEL_ICHG, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"vph_pwr", CHANNEL_VPH_PWR, CHAN_PATH_SCALING2, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"ibat", CHANNEL_IBAT, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"batt_therm", CHANNEL_BATT_THERM, CHAN_PATH_SCALING1, AMUX_RSV2,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_BATT_THERM},
+ {"batt_id", CHANNEL_BATT_ID, CHAN_PATH_SCALING1, AMUX_RSV2,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"usbin", CHANNEL_USBIN, CHAN_PATH_SCALING3, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"pmic_therm", CHANNEL_DIE_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_PMIC_THERM},
+ {"625mv", CHANNEL_625MV, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"125v", CHANNEL_125V, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"chg_temp", CHANNEL_CHG_TEMP, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_DEFAULT},
+ {"xo_therm", CHANNEL_MUXOFF, CHAN_PATH_SCALING1, AMUX_RSV0,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_XOTHERM},
+ {"pa_therm0", ADC_MPP_1_AMUX3, CHAN_PATH_SCALING1, AMUX_RSV1,
+ ADC_DECIMATION_TYPE2, ADC_SCALE_PA_THERM},
+};
+
+static struct pm8xxx_adc_properties pm8917_adc_data = {
+ .adc_vdd_reference = 1800, /* milli-voltage for this adc */
+ .bitresolution = 15,
+ .bipolar = 0,
+};
+
+static struct pm8xxx_adc_platform_data pm8917_adc_pdata = {
+ .adc_channel = pm8917_adc_channels_data,
+ .adc_num_board_channel = ARRAY_SIZE(pm8917_adc_channels_data),
+ .adc_prop = &pm8917_adc_data,
+ .adc_mpp_base = PM8917_MPP_PM_TO_SYS(1),
+};
+
+static struct pm8921_platform_data pm8917_platform_data __devinitdata = {
+ .irq_pdata = &pm8xxx_irq_pdata,
+ .gpio_pdata = &pm8xxx_gpio_pdata,
+ .mpp_pdata = &pm8xxx_mpp_pdata,
+ .rtc_pdata = &pm8xxx_rtc_pdata,
+ .pwrkey_pdata = &pm8xxx_pwrkey_pdata,
+ .misc_pdata = &pm8xxx_misc_pdata,
+ .regulator_pdatas = msm8930_pm8917_regulator_pdata,
+ .charger_pdata = &pm8921_chg_pdata,
+ .bms_pdata = &pm8921_bms_pdata,
+ .adc_pdata = &pm8917_adc_pdata,
+ .ccadc_pdata = &pm8xxx_ccadc_pdata,
+};
+
+static struct msm_ssbi_platform_data msm8930_ssbi_pm8917_pdata __devinitdata = {
+ .controller_type = MSM_SBI_CTRL_PMIC_ARBITER,
+ .slave = {
+ .name = "pm8921-core",
+ .platform_data = &pm8917_platform_data,
+ },
+};
+
void __init msm8930_init_pmic(void)
{
- pmic_reset_irq = PM8038_IRQ_BASE + PM8038_RESOUT_IRQ;
- msm8960_device_ssbi_pmic.dev.platform_data =
- &msm8930_ssbi_pm8038_pdata;
- pm8038_platform_data.num_regulators
- = msm8930_pm8038_regulator_pdata_len;
- if (machine_is_apq8064_mtp())
- pm8921_bms_pdata.battery_type = BATT_PALLADIUM;
- else if (machine_is_apq8064_liquid())
- pm8921_bms_pdata.battery_type = BATT_DESAY;
+ if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917) {
+ /* PM8038 configuration */
+ pmic_reset_irq = PM8038_IRQ_BASE + PM8038_RESOUT_IRQ;
+ msm8960_device_ssbi_pmic.dev.platform_data =
+ &msm8930_ssbi_pm8038_pdata;
+ pm8038_platform_data.num_regulators
+ = msm8930_pm8038_regulator_pdata_len;
+ if (machine_is_msm8930_mtp())
+ pm8921_bms_pdata.battery_type = BATT_PALLADIUM;
+ else if (machine_is_msm8930_cdp())
+ pm8921_chg_pdata.has_dc_supply = true;
+ } else {
+ /* PM8917 configuration */
+ pmic_reset_irq = PM8917_IRQ_BASE + PM8921_RESOUT_IRQ;
+ msm8960_device_ssbi_pmic.dev.platform_data =
+ &msm8930_ssbi_pm8917_pdata;
+ pm8917_platform_data.num_regulators
+ = msm8930_pm8917_regulator_pdata_len;
+ if (machine_is_msm8930_mtp())
+ pm8921_bms_pdata.battery_type = BATT_PALLADIUM;
+ else if (machine_is_msm8930_cdp())
+ pm8921_chg_pdata.has_dc_supply = true;
+ }
}
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator-pm8038.c
similarity index 97%
rename from arch/arm/mach-msm/board-8930-regulator.c
rename to arch/arm/mach-msm/board-8930-regulator-pm8038.c
index d4bd18f..ed9d802 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator-pm8038.c
@@ -11,6 +11,11 @@
* GNU General Public License for more details.
*/
+/*
+ * This file contains regulator configuration and mappings for targets
+ * consisting of MSM8930 and PM8038.
+ */
+
#include <linux/regulator/pm8xxx-regulator.h>
#include "board-8930.h"
@@ -449,17 +454,17 @@
/* GPIO regulator constraints */
struct gpio_regulator_platform_data
-msm8930_gpio_regulator_pdata[] __devinitdata = {
+msm8930_pm8038_gpio_regulator_pdata[] __devinitdata = {
/* ID vreg_name gpio_label gpio supply */
GPIO_VREG(EXT_5V, "ext_5v", "ext_5v_en", 63, NULL),
GPIO_VREG(EXT_OTG_SW, "ext_otg_sw", "ext_otg_sw_en", 97, "ext_5v"),
};
/* SAW regulator constraints */
-struct regulator_init_data msm8930_saw_regulator_core0_pdata =
+struct regulator_init_data msm8930_pm8038_saw_regulator_core0_pdata =
/* ID vreg_name min_uV max_uV */
SAW_VREG_INIT(S5, "8038_s5", 850000, 1300000);
-struct regulator_init_data msm8930_saw_regulator_core1_pdata =
+struct regulator_init_data msm8930_pm8038_saw_regulator_core1_pdata =
SAW_VREG_INIT(S6, "8038_s6", 850000, 1300000);
/* PM8038 regulator constraints */
@@ -558,7 +563,8 @@
RPM_REG_MAP(VDD_DIG_CORNER, 0, 2, "krait1_dig", "acpuclk-8930aa"),
};
-struct rpm_regulator_platform_data msm8930_rpm_regulator_pdata __devinitdata = {
+struct rpm_regulator_platform_data
+msm8930_pm8038_rpm_regulator_pdata __devinitdata = {
.init_data = msm8930_rpm_regulator_init_data,
.num_regulators = ARRAY_SIZE(msm8930_rpm_regulator_init_data),
.version = RPM_VREG_VERSION_8930,
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator-pm8917.c
similarity index 72%
copy from arch/arm/mach-msm/board-8930-regulator.c
copy to arch/arm/mach-msm/board-8930-regulator-pm8917.c
index d4bd18f..db40e5d 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator-pm8917.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2012, Code Aurora Forum. 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
@@ -11,6 +11,11 @@
* GNU General Public License for more details.
*/
+/*
+ * This file contains regulator configuration and mappings for targets
+ * consisting of MSM8930 and PM8917.
+ */
+
#include <linux/regulator/pm8xxx-regulator.h>
#include "board-8930.h"
@@ -23,11 +28,10 @@
* regulator name consumer dev_name
*/
VREG_CONSUMERS(L1) = {
- REGULATOR_SUPPLY("8038_l1", NULL),
- REGULATOR_SUPPLY("iris_vddrfa", "wcnss_wlan.0"),
+ REGULATOR_SUPPLY("8917_l1", NULL),
};
VREG_CONSUMERS(L2) = {
- REGULATOR_SUPPLY("8038_l2", NULL),
+ REGULATOR_SUPPLY("8917_l2", NULL),
REGULATOR_SUPPLY("iris_vdddig", "wcnss_wlan.0"),
REGULATOR_SUPPLY("dsi_vdda", "mipi_dsi.1"),
REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.0"),
@@ -35,53 +39,152 @@
REGULATOR_SUPPLY("mipi_csi_vdd", "msm_csid.2"),
};
VREG_CONSUMERS(L3) = {
- REGULATOR_SUPPLY("8038_l3", NULL),
+ REGULATOR_SUPPLY("8917_l3", NULL),
REGULATOR_SUPPLY("HSUSB_3p3", "msm_otg"),
};
VREG_CONSUMERS(L4) = {
- REGULATOR_SUPPLY("8038_l4", NULL),
+ REGULATOR_SUPPLY("8917_l4", NULL),
REGULATOR_SUPPLY("HSUSB_1p8", "msm_otg"),
REGULATOR_SUPPLY("iris_vddxo", "wcnss_wlan.0"),
};
VREG_CONSUMERS(L5) = {
- REGULATOR_SUPPLY("8038_l5", NULL),
+ REGULATOR_SUPPLY("8917_l5", NULL),
REGULATOR_SUPPLY("sdc_vdd", "msm_sdcc.1"),
};
VREG_CONSUMERS(L6) = {
- REGULATOR_SUPPLY("8038_l6", NULL),
+ REGULATOR_SUPPLY("8917_l6", NULL),
REGULATOR_SUPPLY("sdc_vdd", "msm_sdcc.3"),
};
VREG_CONSUMERS(L7) = {
- REGULATOR_SUPPLY("8038_l7", NULL),
+ REGULATOR_SUPPLY("8917_l7", NULL),
+ REGULATOR_SUPPLY("sdc_vdd_io", "msm_sdcc.3"),
};
VREG_CONSUMERS(L8) = {
- REGULATOR_SUPPLY("8038_l8", NULL),
+ REGULATOR_SUPPLY("8917_l8", NULL),
REGULATOR_SUPPLY("dsi_vdc", "mipi_dsi.1"),
};
VREG_CONSUMERS(L9) = {
- REGULATOR_SUPPLY("8038_l9", NULL),
+ REGULATOR_SUPPLY("8917_l9", NULL),
REGULATOR_SUPPLY("vdd_ana", "3-004a"),
REGULATOR_SUPPLY("vdd", "3-0024"),
- REGULATOR_SUPPLY("cam_vana", "4-001a"),
- REGULATOR_SUPPLY("cam_vana", "4-006c"),
- REGULATOR_SUPPLY("cam_vana", "4-0048"),
- REGULATOR_SUPPLY("cam_vaf", "4-001a"),
- REGULATOR_SUPPLY("cam_vaf", "4-006c"),
- REGULATOR_SUPPLY("cam_vaf", "4-0048"),
- REGULATOR_SUPPLY("cam_vana", "4-0020"),
- REGULATOR_SUPPLY("cam_vaf", "4-0020"),
REGULATOR_SUPPLY("vdd", "12-0018"),
REGULATOR_SUPPLY("vdd", "12-0068"),
};
VREG_CONSUMERS(L10) = {
- REGULATOR_SUPPLY("8038_l10", NULL),
+ REGULATOR_SUPPLY("8917_l10", NULL),
REGULATOR_SUPPLY("iris_vddpa", "wcnss_wlan.0"),
};
VREG_CONSUMERS(L11) = {
- REGULATOR_SUPPLY("8038_l11", NULL),
+ REGULATOR_SUPPLY("8917_l11", NULL),
+ REGULATOR_SUPPLY("cam_vana", "4-001a"),
+ REGULATOR_SUPPLY("cam_vana", "4-006c"),
+ REGULATOR_SUPPLY("cam_vana", "4-0048"),
+ REGULATOR_SUPPLY("cam_vana", "4-0020"),
+};
+VREG_CONSUMERS(L12) = {
+ REGULATOR_SUPPLY("8917_l12", NULL),
+ REGULATOR_SUPPLY("cam_vdig", "4-001a"),
+ REGULATOR_SUPPLY("cam_vdig", "4-006c"),
+ REGULATOR_SUPPLY("cam_vdig", "4-0048"),
+ REGULATOR_SUPPLY("cam_vdig", "4-0020"),
+};
+VREG_CONSUMERS(L14) = {
+ REGULATOR_SUPPLY("8917_l14", NULL),
+ REGULATOR_SUPPLY("pa_therm", "pm8xxx-adc"),
+};
+VREG_CONSUMERS(L15) = {
+ REGULATOR_SUPPLY("8917_l15", NULL),
+};
+VREG_CONSUMERS(L16) = {
+ REGULATOR_SUPPLY("8917_l16", NULL),
+ REGULATOR_SUPPLY("cam_vaf", "4-001a"),
+ REGULATOR_SUPPLY("cam_vaf", "4-006c"),
+ REGULATOR_SUPPLY("cam_vaf", "4-0048"),
+ REGULATOR_SUPPLY("cam_vaf", "4-0020"),
+};
+VREG_CONSUMERS(L17) = {
+ REGULATOR_SUPPLY("8917_l17", NULL),
+};
+VREG_CONSUMERS(L18) = {
+ REGULATOR_SUPPLY("8917_l18", NULL),
+};
+VREG_CONSUMERS(L21) = {
+ REGULATOR_SUPPLY("8917_l21", NULL),
+};
+VREG_CONSUMERS(L22) = {
+ REGULATOR_SUPPLY("8917_l22", NULL),
+};
+VREG_CONSUMERS(L23) = {
+ REGULATOR_SUPPLY("8917_l23", NULL),
+ REGULATOR_SUPPLY("dsi_vddio", "mipi_dsi.1"),
+ REGULATOR_SUPPLY("hdmi_avdd", "hdmi_msm.0"),
+ REGULATOR_SUPPLY("hdmi_vcc", "hdmi_msm.0"),
+ REGULATOR_SUPPLY("pll_vdd", "pil_riva"),
+ REGULATOR_SUPPLY("pll_vdd", "pil_qdsp6v4.1"),
+ REGULATOR_SUPPLY("pll_vdd", "pil_qdsp6v4.2"),
+};
+VREG_CONSUMERS(L24) = {
+ REGULATOR_SUPPLY("8917_l24", NULL),
+ REGULATOR_SUPPLY("riva_vddmx", "wcnss_wlan.0"),
+};
+VREG_CONSUMERS(L25) = {
+ REGULATOR_SUPPLY("8917_l25", NULL),
+ REGULATOR_SUPPLY("VDDD_CDC_D", "sitar-slim"),
+ REGULATOR_SUPPLY("CDC_VDDA_A_1P2V", "sitar-slim"),
+ REGULATOR_SUPPLY("VDDD_CDC_D", "sitar1p1-slim"),
+ REGULATOR_SUPPLY("CDC_VDDA_A_1P2V", "sitar1p1-slim"),
+ REGULATOR_SUPPLY("mhl_avcc12", "0-0039"),
+};
+VREG_CONSUMERS(L26) = {
+ REGULATOR_SUPPLY("8921_l26", NULL),
+ REGULATOR_SUPPLY("core_vdd", "pil_qdsp6v4.0"),
+};
+VREG_CONSUMERS(L27) = {
+ REGULATOR_SUPPLY("8921_l27", NULL),
+ REGULATOR_SUPPLY("core_vdd", "pil_qdsp6v4.2"),
+};
+VREG_CONSUMERS(L28) = {
+ REGULATOR_SUPPLY("8921_l28", NULL),
+ REGULATOR_SUPPLY("core_vdd", "pil_qdsp6v4.1"),
+};
+VREG_CONSUMERS(L29) = {
+ REGULATOR_SUPPLY("8921_l29", NULL),
+};
+VREG_CONSUMERS(L30) = {
+ REGULATOR_SUPPLY("8917_l30", NULL),
+};
+VREG_CONSUMERS(L31) = {
+ REGULATOR_SUPPLY("8917_l31", NULL),
+};
+VREG_CONSUMERS(L32) = {
+ REGULATOR_SUPPLY("8917_l32", NULL),
+};
+VREG_CONSUMERS(L33) = {
+ REGULATOR_SUPPLY("8917_l33", NULL),
+};
+VREG_CONSUMERS(L34) = {
+ REGULATOR_SUPPLY("8917_l34", NULL),
+};
+VREG_CONSUMERS(L35) = {
+ REGULATOR_SUPPLY("8917_l35", NULL),
+};
+VREG_CONSUMERS(L36) = {
+ REGULATOR_SUPPLY("8917_l36", NULL),
+};
+VREG_CONSUMERS(S1) = {
+ REGULATOR_SUPPLY("8917_s1", NULL),
+};
+VREG_CONSUMERS(S2) = {
+ REGULATOR_SUPPLY("8917_s2", NULL),
+ REGULATOR_SUPPLY("iris_vddrfa", "wcnss_wlan.0"),
+};
+VREG_CONSUMERS(S3) = {
+ REGULATOR_SUPPLY("8917_s3", NULL),
+ REGULATOR_SUPPLY("riva_vddcx", "wcnss_wlan.0"),
+};
+VREG_CONSUMERS(S4) = {
+ REGULATOR_SUPPLY("8917_s4", NULL),
REGULATOR_SUPPLY("vdd_dig", "3-004a"),
- REGULATOR_SUPPLY("iris_vddio", "wcnss_wlan.0"),
- REGULATOR_SUPPLY("riva_vddpx", "wcnss_wlan.0"),
REGULATOR_SUPPLY("sdc_vdd_io", "msm_sdcc.1"),
REGULATOR_SUPPLY("VDDIO_CDC", "sitar-slim"),
REGULATOR_SUPPLY("CDC_VDDA_TX", "sitar-slim"),
@@ -91,132 +194,71 @@
REGULATOR_SUPPLY("CDC_VDDA_RX", "sitar1p1-slim"),
REGULATOR_SUPPLY("vddp", "0-0048"),
REGULATOR_SUPPLY("mhl_iovcc18", "0-0039"),
-};
-VREG_CONSUMERS(L12) = {
- REGULATOR_SUPPLY("8038_l12", NULL),
- REGULATOR_SUPPLY("cam_vdig", "4-001a"),
- REGULATOR_SUPPLY("cam_vdig", "4-006c"),
- REGULATOR_SUPPLY("cam_vdig", "4-0048"),
- REGULATOR_SUPPLY("cam_vdig", "4-0020"),
-};
-VREG_CONSUMERS(L13) = {
- REGULATOR_SUPPLY("8038_l13", NULL),
-};
-VREG_CONSUMERS(L14) = {
- REGULATOR_SUPPLY("8038_l14", NULL),
- REGULATOR_SUPPLY("pa_therm", "pm8xxx-adc"),
-};
-VREG_CONSUMERS(L15) = {
- REGULATOR_SUPPLY("8038_l15", NULL),
-};
-VREG_CONSUMERS(L16) = {
- REGULATOR_SUPPLY("8038_l16", NULL),
- REGULATOR_SUPPLY("core_vdd", "pil_qdsp6v4.2"),
-};
-VREG_CONSUMERS(L17) = {
- REGULATOR_SUPPLY("8038_l17", NULL),
-};
-VREG_CONSUMERS(L18) = {
- REGULATOR_SUPPLY("8038_l18", NULL),
-};
-VREG_CONSUMERS(L19) = {
- REGULATOR_SUPPLY("8038_l19", NULL),
- REGULATOR_SUPPLY("core_vdd", "pil_qdsp6v4.1"),
-};
-VREG_CONSUMERS(L20) = {
- REGULATOR_SUPPLY("8038_l20", NULL),
- REGULATOR_SUPPLY("VDDD_CDC_D", "sitar-slim"),
- REGULATOR_SUPPLY("CDC_VDDA_A_1P2V", "sitar-slim"),
- REGULATOR_SUPPLY("VDDD_CDC_D", "sitar1p1-slim"),
- REGULATOR_SUPPLY("CDC_VDDA_A_1P2V", "sitar1p1-slim"),
- REGULATOR_SUPPLY("mhl_avcc12", "0-0039"),
-};
-VREG_CONSUMERS(L21) = {
- REGULATOR_SUPPLY("8038_l21", NULL),
-};
-VREG_CONSUMERS(L22) = {
- REGULATOR_SUPPLY("8038_l22", NULL),
- REGULATOR_SUPPLY("sdc_vdd_io", "msm_sdcc.3"),
-};
-VREG_CONSUMERS(L23) = {
- REGULATOR_SUPPLY("8038_l23", NULL),
- REGULATOR_SUPPLY("dsi_vddio", "mipi_dsi.1"),
- REGULATOR_SUPPLY("hdmi_avdd", "hdmi_msm.0"),
- REGULATOR_SUPPLY("hdmi_vcc", "hdmi_msm.0"),
- REGULATOR_SUPPLY("pll_vdd", "pil_riva"),
- REGULATOR_SUPPLY("pll_vdd", "pil_qdsp6v4.1"),
- REGULATOR_SUPPLY("pll_vdd", "pil_qdsp6v4.2"),
-};
-VREG_CONSUMERS(L24) = {
- REGULATOR_SUPPLY("8038_l24", NULL),
- REGULATOR_SUPPLY("riva_vddmx", "wcnss_wlan.0"),
-};
-VREG_CONSUMERS(L25) = {
- REGULATOR_SUPPLY("8038_l25", NULL),
-};
-VREG_CONSUMERS(L26) = {
- REGULATOR_SUPPLY("8038_l26", NULL),
-};
-VREG_CONSUMERS(L27) = {
- REGULATOR_SUPPLY("8038_l27", NULL),
- REGULATOR_SUPPLY("core_vdd", "pil_qdsp6v4.0"),
-};
-VREG_CONSUMERS(S1) = {
- REGULATOR_SUPPLY("8038_s1", NULL),
- REGULATOR_SUPPLY("riva_vddcx", "wcnss_wlan.0"),
-};
-VREG_CONSUMERS(S2) = {
- REGULATOR_SUPPLY("8038_s2", NULL),
-};
-VREG_CONSUMERS(S3) = {
- REGULATOR_SUPPLY("8038_s3", NULL),
-};
-VREG_CONSUMERS(S4) = {
- REGULATOR_SUPPLY("8038_s4", NULL),
REGULATOR_SUPPLY("CDC_VDD_CP", "sitar-slim"),
REGULATOR_SUPPLY("CDC_VDD_CP", "sitar1p1-slim"),
};
VREG_CONSUMERS(S5) = {
- REGULATOR_SUPPLY("8038_s5", NULL),
+ REGULATOR_SUPPLY("8917_s5", NULL),
REGULATOR_SUPPLY("krait0", "acpuclk-8627"),
REGULATOR_SUPPLY("krait0", "acpuclk-8930"),
REGULATOR_SUPPLY("krait0", "acpuclk-8930aa"),
};
VREG_CONSUMERS(S6) = {
- REGULATOR_SUPPLY("8038_s6", NULL),
+ REGULATOR_SUPPLY("8917_s6", NULL),
REGULATOR_SUPPLY("krait1", "acpuclk-8627"),
REGULATOR_SUPPLY("krait1", "acpuclk-8930"),
REGULATOR_SUPPLY("krait1", "acpuclk-8930aa"),
};
-VREG_CONSUMERS(LVS1) = {
- REGULATOR_SUPPLY("8038_lvs1", NULL),
- REGULATOR_SUPPLY("cam_vio", "4-001a"),
- REGULATOR_SUPPLY("cam_vio", "4-006c"),
- REGULATOR_SUPPLY("cam_vio", "4-0048"),
- REGULATOR_SUPPLY("cam_vio", "4-0020"),
+VREG_CONSUMERS(S7) = {
+ REGULATOR_SUPPLY("8917_s7", NULL),
};
-VREG_CONSUMERS(LVS2) = {
- REGULATOR_SUPPLY("8038_lvs2", NULL),
+VREG_CONSUMERS(S8) = {
+ REGULATOR_SUPPLY("8917_s8", NULL),
+};
+VREG_CONSUMERS(LVS1) = {
+ REGULATOR_SUPPLY("8917_lvs1", NULL),
+ REGULATOR_SUPPLY("iris_vddio", "wcnss_wlan.0"),
+ REGULATOR_SUPPLY("riva_vddpx", "wcnss_wlan.0"),
+};
+VREG_CONSUMERS(LVS3) = {
+ REGULATOR_SUPPLY("8917_lvs3", NULL),
+};
+VREG_CONSUMERS(LVS4) = {
+ REGULATOR_SUPPLY("8917_lvs4", NULL),
REGULATOR_SUPPLY("vcc_i2c", "3-004a"),
REGULATOR_SUPPLY("vcc_i2c", "3-0024"),
REGULATOR_SUPPLY("vcc_i2c", "0-0048"),
REGULATOR_SUPPLY("vddio", "12-0018"),
REGULATOR_SUPPLY("vlogic", "12-0068"),
};
-VREG_CONSUMERS(EXT_5V) = {
- REGULATOR_SUPPLY("ext_5v", NULL),
+VREG_CONSUMERS(LVS5) = {
+ REGULATOR_SUPPLY("8917_lvs5", NULL),
+ REGULATOR_SUPPLY("cam_vio", "4-001a"),
+ REGULATOR_SUPPLY("cam_vio", "4-006c"),
+ REGULATOR_SUPPLY("cam_vio", "4-0048"),
+ REGULATOR_SUPPLY("cam_vio", "4-0020"),
+};
+VREG_CONSUMERS(LVS6) = {
+ REGULATOR_SUPPLY("8917_lvs6", NULL),
+};
+VREG_CONSUMERS(LVS7) = {
+ REGULATOR_SUPPLY("8917_lvs7", NULL),
+};
+VREG_CONSUMERS(USB_OTG) = {
+ REGULATOR_SUPPLY("8921_usb_otg", NULL),
+ REGULATOR_SUPPLY("vbus_otg", "msm_otg"),
+};
+VREG_CONSUMERS(BOOST) = {
+ REGULATOR_SUPPLY("8917_boost", NULL),
REGULATOR_SUPPLY("hdmi_mvs", "hdmi_msm.0"),
REGULATOR_SUPPLY("mhl_usb_hs_switch", "msm_otg"),
};
-VREG_CONSUMERS(EXT_OTG_SW) = {
- REGULATOR_SUPPLY("ext_otg_sw", NULL),
- REGULATOR_SUPPLY("vbus_otg", "msm_otg"),
-};
VREG_CONSUMERS(VDD_DIG_CORNER) = {
REGULATOR_SUPPLY("vdd_dig_corner", NULL),
REGULATOR_SUPPLY("hsusb_vdd_dig", "msm_otg"),
};
+
#define PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
_apply_uV, _pull_down, _always_on, _supply_regulator, \
_system_uA, _enable_time, _reg_id) \
@@ -286,7 +328,7 @@
_pull_down, _always_on, _supply_regulator, 0, _enable_time, \
_reg_id)
-#define PM8XXX_NCP(_id, _name, _always_on, _min_uV, _max_uV, _enable_time, \
+#define PM8XXX_BOOST(_id, _name, _always_on, _min_uV, _max_uV, _enable_time, \
_supply_regulator, _reg_id) \
PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, 0, \
REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS, 0, 0, \
@@ -332,7 +374,7 @@
.consumer_supplies = vreg_consumers_##_id, \
.supply_regulator = _supply_regulator, \
}, \
- .id = RPM_VREG_ID_PM8038_##_id, \
+ .id = RPM_VREG_ID_PM8917_##_id, \
.default_uV = _default_uV, \
.peak_uA = _peak_uA, \
.avg_uA = _avg_uA, \
@@ -414,7 +456,7 @@
.consumer_supplies = vreg_consumers_##_id##_PC, \
.supply_regulator = _supply_regulator, \
}, \
- .id = RPM_VREG_ID_PM8038_##_id##_PC, \
+ .id = RPM_VREG_ID_PM8917_##_id##_PC, \
.pin_fn = RPM_VREG_PIN_FN_8930_##_pin_fn, \
.pin_ctrl = _pin_ctrl, \
}
@@ -449,93 +491,122 @@
/* GPIO regulator constraints */
struct gpio_regulator_platform_data
-msm8930_gpio_regulator_pdata[] __devinitdata = {
+msm8930_pm8917_gpio_regulator_pdata[] __devinitdata = {
/* ID vreg_name gpio_label gpio supply */
- GPIO_VREG(EXT_5V, "ext_5v", "ext_5v_en", 63, NULL),
- GPIO_VREG(EXT_OTG_SW, "ext_otg_sw", "ext_otg_sw_en", 97, "ext_5v"),
};
/* SAW regulator constraints */
-struct regulator_init_data msm8930_saw_regulator_core0_pdata =
+struct regulator_init_data msm8930_pm8917_saw_regulator_core0_pdata =
/* ID vreg_name min_uV max_uV */
- SAW_VREG_INIT(S5, "8038_s5", 850000, 1300000);
-struct regulator_init_data msm8930_saw_regulator_core1_pdata =
- SAW_VREG_INIT(S6, "8038_s6", 850000, 1300000);
+ SAW_VREG_INIT(S5, "8917_s5", 850000, 1300000);
+struct regulator_init_data msm8930_pm8917_saw_regulator_core1_pdata =
+ SAW_VREG_INIT(S6, "8917_s6", 850000, 1300000);
-/* PM8038 regulator constraints */
+/* PM8917 regulator constraints */
struct pm8xxx_regulator_platform_data
-msm8930_pm8038_regulator_pdata[] __devinitdata = {
+msm8930_pm8917_regulator_pdata[] __devinitdata = {
/*
- * ID name always_on pd min_uV max_uV en_t supply
+ * ID name always_on pd min_uV max_uV en_t supply
* system_uA reg_ID
*/
- PM8XXX_NLDO1200(L16, "8038_l16", 0, 1, 375000, 1050000, 200, "8038_s3",
+ PM8XXX_NLDO1200(L26, "8921_l26", 0, 1, 375000, 1050000, 200, "8917_s7",
0, 0),
- PM8XXX_NLDO1200(L19, "8038_l19", 0, 1, 375000, 1050000, 200, "8038_s3",
+ PM8XXX_NLDO1200(L27, "8921_l27", 0, 1, 375000, 1050000, 200, "8917_s7",
0, 1),
- PM8XXX_NLDO1200(L27, "8038_l27", 0, 1, 375000, 1050000, 200, "8038_s3",
+ PM8XXX_NLDO1200(L28, "8921_l28", 0, 1, 375000, 1050000, 200, "8917_s7",
0, 2),
+ PM8XXX_LDO(L29, "8921_l29", 0, 1, 1800000, 1800000, 200, "8917_s8",
+ 0, 3),
+ PM8XXX_LDO(L30, "8917_l30", 0, 1, 1800000, 1800000, 200, NULL,
+ 0, 4),
+ PM8XXX_LDO(L31, "8917_l31", 0, 1, 1800000, 1800000, 200, NULL,
+ 0, 5),
+ PM8XXX_LDO(L32, "8917_l32", 0, 1, 2800000, 2800000, 200, NULL,
+ 0, 6),
+ PM8XXX_LDO(L33, "8917_l33", 0, 1, 2800000, 2800000, 200, NULL,
+ 0, 7),
+ PM8XXX_LDO(L34, "8917_l34", 0, 1, 1800000, 1800000, 200, NULL,
+ 0, 8),
+ PM8XXX_LDO(L35, "8917_l35", 0, 1, 3000000, 3000000, 200, NULL,
+ 0, 9),
+ PM8XXX_LDO(L36, "8917_l36", 0, 1, 1800000, 1800000, 200, NULL,
+ 0, 10),
+ /*
+ * ID name always_on min_uV max_uV en_t supply reg_ID
+ */
+ PM8XXX_BOOST(BOOST, "8917_boost", 0, 5000000, 5000000, 500, NULL, 11),
+
+ /* ID name always_on pd en_t supply reg_ID */
+ PM8XXX_VS300(USB_OTG, "8921_usb_otg", 0, 1, 0, "8917_boost", 12),
};
static struct rpm_regulator_init_data
msm8930_rpm_regulator_init_data[] __devinitdata = {
/* ID a_on pd ss min_uV max_uV supply sys_uA freq fm ss_fm */
- RPM_SMPS(S1, 0, 1, 1, 500000, 1150000, NULL, 100000, 4p80, AUTO, LPM),
- RPM_SMPS(S2, 1, 1, 1, 1400000, 1400000, NULL, 100000, 1p60, AUTO, LPM),
- RPM_SMPS(S3, 0, 1, 1, 1150000, 1150000, NULL, 100000, 3p20, AUTO, LPM),
- RPM_SMPS(S4, 1, 1, 1, 1950000, 2200000, NULL, 100000, 1p60, AUTO, LPM),
+ RPM_SMPS(S1, 1, 1, 0, 1300000, 1300000, NULL, 100000, 3p20, NONE, NONE),
+ RPM_SMPS(S2, 0, 1, 0, 1300000, 1300000, NULL, 0, 1p60, NONE, NONE),
+ RPM_SMPS(S3, 0, 1, 1, 500000, 1150000, NULL, 100000, 4p80, AUTO, LPM),
+ RPM_SMPS(S4, 1, 1, 0, 1800000, 1800000, NULL, 100000, 1p60, AUTO, LPM),
+ RPM_SMPS(S7, 0, 1, 0, 1150000, 1150000, NULL, 100000, 3p20, NONE, NONE),
+ RPM_SMPS(S8, 1, 1, 1, 2050000, 2050000, NULL, 100000, 1p60, NONE, NONE),
/* ID a_on pd ss min_uV max_uV supply sys_uA init_ip */
- RPM_LDO(L1, 0, 1, 0, 1300000, 1300000, "8038_s2", 0, 0),
- RPM_LDO(L2, 0, 1, 0, 1200000, 1200000, "8038_s2", 0, 0),
+ RPM_LDO(L1, 1, 1, 0, 1050000, 1050000, "8917_s4", 0, 10000),
+ RPM_LDO(L2, 0, 1, 0, 1200000, 1200000, "8917_s4", 0, 0),
RPM_LDO(L3, 0, 1, 0, 3075000, 3075000, NULL, 0, 0),
RPM_LDO(L4, 1, 1, 0, 1800000, 1800000, NULL, 10000, 10000),
RPM_LDO(L5, 0, 1, 0, 2950000, 2950000, NULL, 0, 0),
RPM_LDO(L6, 0, 1, 0, 2950000, 2950000, NULL, 0, 0),
- RPM_LDO(L7, 0, 1, 0, 2050000, 2050000, "8038_s4", 0, 0),
+ RPM_LDO(L7, 1, 1, 0, 1850000, 2950000, NULL, 10000, 10000),
RPM_LDO(L8, 0, 1, 0, 2800000, 2800000, NULL, 0, 0),
RPM_LDO(L9, 0, 1, 0, 2850000, 2850000, NULL, 0, 0),
RPM_LDO(L10, 0, 1, 0, 2900000, 2900000, NULL, 0, 0),
- RPM_LDO(L11, 1, 1, 0, 1800000, 1800000, "8038_s4", 10000, 10000),
- RPM_LDO(L12, 0, 1, 0, 1200000, 1200000, "8038_s2", 0, 0),
- RPM_LDO(L13, 0, 0, 0, 2220000, 2220000, NULL, 0, 0),
+ RPM_LDO(L11, 0, 1, 0, 2850000, 2850000, NULL, 0, 0),
+ RPM_LDO(L12, 0, 1, 0, 1200000, 1200000, "8917_s4", 0, 0),
RPM_LDO(L14, 0, 1, 0, 1800000, 1800000, NULL, 0, 0),
RPM_LDO(L15, 0, 1, 0, 1800000, 2950000, NULL, 0, 0),
+ RPM_LDO(L16, 0, 1, 0, 2850000, 2850000, NULL, 0, 0),
RPM_LDO(L17, 0, 1, 0, 1800000, 2950000, NULL, 0, 0),
- RPM_LDO(L18, 0, 1, 0, 1800000, 1800000, NULL, 0, 0),
- RPM_LDO(L20, 1, 1, 0, 1250000, 1250000, "8038_s2", 10000, 10000),
- RPM_LDO(L21, 0, 1, 0, 1900000, 1900000, "8038_s4", 0, 0),
- RPM_LDO(L22, 1, 1, 0, 1850000, 2950000, NULL, 10000, 10000),
- RPM_LDO(L23, 1, 1, 1, 1800000, 1800000, "8038_s4", 0, 0),
- RPM_LDO(L24, 0, 1, 1, 500000, 1150000, "8038_s2", 10000, 10000),
- RPM_LDO(L25, 0, 0, 0, 1740000, 1740000, "8038_l13", 0, 0),
- RPM_LDO(L26, 1, 1, 0, 1050000, 1050000, "8038_s2", 10000, 10000),
+ RPM_LDO(L18, 0, 1, 0, 1200000, 1200000, "8917_s4", 0, 0),
+ RPM_LDO(L21, 0, 1, 0, 1900000, 1900000, "8917_s8", 0, 0),
+ RPM_LDO(L22, 0, 1, 0, 2750000, 2750000, NULL, 0, 0),
+ RPM_LDO(L23, 1, 1, 1, 1800000, 1800000, "8917_s8", 10000, 10000),
+ RPM_LDO(L24, 0, 1, 1, 500000, 1150000, "8917_s1", 10000, 10000),
+ RPM_LDO(L25, 1, 1, 0, 1250000, 1250000, "8917_s1", 10000, 10000),
/* ID a_on pd ss supply */
- RPM_VS(LVS1, 0, 1, 0, "8038_l11"),
- RPM_VS(LVS2, 0, 1, 0, "8038_l11"),
+ RPM_VS(LVS1, 0, 1, 0, "8917_s4"),
+ RPM_VS(LVS3, 0, 1, 0, "8917_s4"),
+ RPM_VS(LVS4, 0, 1, 0, "8917_s4"),
+ RPM_VS(LVS5, 0, 1, 0, "8917_s4"),
+ RPM_VS(LVS6, 0, 1, 0, "8917_s4"),
+ RPM_VS(LVS7, 0, 1, 0, "8917_s4"),
/* ID a_on ss min_corner max_corner supply */
RPM_CORNER(VDD_DIG_CORNER, 0, 1, RPM_VREG_CORNER_NONE,
RPM_VREG_CORNER_HIGH, NULL),
};
-int msm8930_pm8038_regulator_pdata_len __devinitdata =
- ARRAY_SIZE(msm8930_pm8038_regulator_pdata);
+int msm8930_pm8917_regulator_pdata_len __devinitdata =
+ ARRAY_SIZE(msm8930_pm8917_regulator_pdata);
#define RPM_REG_MAP(_id, _sleep_also, _voter, _supply, _dev_name) \
{ \
- .vreg_id = RPM_VREG_ID_PM8038_##_id, \
+ .vreg_id = RPM_VREG_ID_PM8917_##_id, \
.sleep_also = _sleep_also, \
.voter = _voter, \
.supply = _supply, \
.dev_name = _dev_name, \
}
+
static struct rpm_regulator_consumer_mapping
msm_rpm_regulator_consumer_mapping[] __devinitdata = {
- RPM_REG_MAP(L23, 0, 1, "krait0_hfpll", "acpuclk-8930"),
- RPM_REG_MAP(L23, 0, 2, "krait1_hfpll", "acpuclk-8930"),
- RPM_REG_MAP(L23, 0, 6, "l2_hfpll", "acpuclk-8930"),
+ RPM_REG_MAP(L23, 0, 1, "krait0_l23", "acpuclk-8930"),
+ RPM_REG_MAP(S8, 0, 1, "krait0_s8", "acpuclk-8930"),
+ RPM_REG_MAP(L23, 0, 2, "krait1_l23", "acpuclk-8930"),
+ RPM_REG_MAP(S8, 0, 2, "krait1_s8", "acpuclk-8930"),
+ RPM_REG_MAP(L23, 0, 6, "l2_l23", "acpuclk-8930"),
+ RPM_REG_MAP(S8, 0, 6, "l2_s8", "acpuclk-8930"),
RPM_REG_MAP(L24, 0, 1, "krait0_mem", "acpuclk-8930"),
RPM_REG_MAP(L24, 0, 2, "krait1_mem", "acpuclk-8930"),
RPM_REG_MAP(VDD_DIG_CORNER, 0, 1, "krait0_dig", "acpuclk-8930"),
@@ -558,12 +629,13 @@
RPM_REG_MAP(VDD_DIG_CORNER, 0, 2, "krait1_dig", "acpuclk-8930aa"),
};
-struct rpm_regulator_platform_data msm8930_rpm_regulator_pdata __devinitdata = {
+struct rpm_regulator_platform_data
+msm8930_pm8917_rpm_regulator_pdata __devinitdata = {
.init_data = msm8930_rpm_regulator_init_data,
.num_regulators = ARRAY_SIZE(msm8930_rpm_regulator_init_data),
- .version = RPM_VREG_VERSION_8930,
- .vreg_id_vdd_mem = RPM_VREG_ID_PM8038_L24,
- .vreg_id_vdd_dig = RPM_VREG_ID_PM8038_VDD_DIG_CORNER,
+ .version = RPM_VREG_VERSION_8930_PM8917,
+ .vreg_id_vdd_mem = RPM_VREG_ID_PM8917_L24,
+ .vreg_id_vdd_dig = RPM_VREG_ID_PM8917_VDD_DIG_CORNER,
.consumer_map = msm_rpm_regulator_consumer_mapping,
.consumer_map_len = ARRAY_SIZE(msm_rpm_regulator_consumer_mapping),
};
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index a7147b5..2b1c665 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -100,6 +100,7 @@
#include "pm-boot.h"
#include "msm_watchdog.h"
#include "board-8930.h"
+#include "acpuclock-krait.h"
static struct platform_device msm_fm_platform_init = {
.name = "iris_fm",
@@ -791,7 +792,7 @@
.regulator = {
{
.name = "CDC_VDD_CP",
- .min_uV = 1950000,
+ .min_uV = 1800000,
.max_uV = 2200000,
.optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
},
@@ -857,7 +858,7 @@
.regulator = {
{
.name = "CDC_VDD_CP",
- .min_uV = 1950000,
+ .min_uV = 1800000,
.max_uV = 2200000,
.optimum_uA = WCD9XXX_CDC_VDDA_CP_CUR_MAX,
},
@@ -1656,18 +1657,26 @@
#define ISA1200_HAP_EN_GPIO 77
#define ISA1200_HAP_LEN_GPIO 78
-#define ISA1200_HAP_CLK PM8038_GPIO_PM_TO_SYS(7)
+#define ISA1200_HAP_CLK_PM8038 PM8038_GPIO_PM_TO_SYS(7)
+#define ISA1200_HAP_CLK_PM8917 PM8917_GPIO_PM_TO_SYS(38)
static int isa1200_power(int on)
{
+ unsigned int gpio = ISA1200_HAP_CLK_PM8038;
+ enum pm8xxx_aux_clk_id clk_id = CLK_MP3_1;
int rc = 0;
- gpio_set_value_cansleep(ISA1200_HAP_CLK, !!on);
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
+ gpio = ISA1200_HAP_CLK_PM8917;
+ clk_id = CLK_MP3_2;
+ }
+
+ gpio_set_value_cansleep(gpio, !!on);
if (on)
- rc = pm8xxx_aux_clk_control(CLK_MP3_1, XO_DIV_1, true);
+ rc = pm8xxx_aux_clk_control(clk_id, XO_DIV_1, true);
else
- rc = pm8xxx_aux_clk_control(CLK_MP3_1, XO_DIV_NONE, true);
+ rc = pm8xxx_aux_clk_control(clk_id, XO_DIV_NONE, true);
if (rc) {
pr_err("%s: unable to write aux clock register(%d)\n",
@@ -1679,29 +1688,33 @@
static int isa1200_dev_setup(bool enable)
{
+ unsigned int gpio = ISA1200_HAP_CLK_PM8038;
int rc = 0;
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
+ gpio = ISA1200_HAP_CLK_PM8917;
+
if (!enable)
goto fail_gpio_dir;
- rc = gpio_request(ISA1200_HAP_CLK, "haptics_clk");
+ rc = gpio_request(gpio, "haptics_clk");
if (rc) {
pr_err("%s: gpio_request for %d gpio failed rc(%d)\n",
- __func__, ISA1200_HAP_CLK, rc);
+ __func__, gpio, rc);
goto fail_gpio_req;
}
- rc = gpio_direction_output(ISA1200_HAP_CLK, 0);
+ rc = gpio_direction_output(gpio, 0);
if (rc) {
pr_err("%s: gpio_direction_output failed for %d gpio rc(%d)\n",
- __func__, ISA1200_HAP_CLK, rc);
+ __func__, gpio, rc);
goto fail_gpio_dir;
}
return 0;
fail_gpio_dir:
- gpio_free(ISA1200_HAP_CLK);
+ gpio_free(gpio);
fail_gpio_req:
return rc;
@@ -1938,12 +1951,13 @@
},
};
-#define MHL_POWER_GPIO PM8038_GPIO_PM_TO_SYS(MHL_GPIO_PWR_EN)
+#define MHL_POWER_GPIO_PM8038 PM8038_GPIO_PM_TO_SYS(MHL_GPIO_PWR_EN)
+#define MHL_POWER_GPIO_PM8917 PM8917_GPIO_PM_TO_SYS(25)
static struct msm_mhl_platform_data mhl_platform_data = {
.irq = MSM_GPIO_TO_INT(MHL_GPIO_INT),
.gpio_mhl_int = MHL_GPIO_INT,
.gpio_mhl_reset = MHL_GPIO_RESET,
- .gpio_mhl_power = MHL_POWER_GPIO,
+ .gpio_mhl_power = MHL_POWER_GPIO_PM8038,
.gpio_hdmi_mhl_mux = HDMI_MHL_MUX_GPIO,
};
@@ -1962,17 +1976,22 @@
#ifdef MSM8930_PHASE_2
-#define GPIO_VOLUME_UP PM8038_GPIO_PM_TO_SYS(3)
-#define GPIO_VOLUME_DOWN PM8038_GPIO_PM_TO_SYS(8)
-#define GPIO_CAMERA_SNAPSHOT PM8038_GPIO_PM_TO_SYS(10)
-#define GPIO_CAMERA_FOCUS PM8038_GPIO_PM_TO_SYS(11)
+#define GPIO_VOLUME_UP_PM8038 PM8038_GPIO_PM_TO_SYS(3)
+#define GPIO_VOLUME_DOWN_PM8038 PM8038_GPIO_PM_TO_SYS(8)
+#define GPIO_CAMERA_SNAPSHOT_PM8038 PM8038_GPIO_PM_TO_SYS(10)
+#define GPIO_CAMERA_FOCUS_PM8038 PM8038_GPIO_PM_TO_SYS(11)
-static struct gpio_keys_button keys_8930[] = {
+#define GPIO_VOLUME_UP_PM8917 PM8917_GPIO_PM_TO_SYS(27)
+#define GPIO_VOLUME_DOWN_PM8917 PM8917_GPIO_PM_TO_SYS(28)
+#define GPIO_CAMERA_SNAPSHOT_PM8917 PM8917_GPIO_PM_TO_SYS(36)
+#define GPIO_CAMERA_FOCUS_PM8917 PM8917_GPIO_PM_TO_SYS(37)
+
+static struct gpio_keys_button keys_8930_pm8038[] = {
{
.code = KEY_VOLUMEUP,
.type = EV_KEY,
.desc = "volume_up",
- .gpio = GPIO_VOLUME_UP,
+ .gpio = GPIO_VOLUME_UP_PM8038,
.wakeup = 1,
.active_low = 1,
.debounce_interval = 15,
@@ -1981,7 +2000,7 @@
.code = KEY_VOLUMEDOWN,
.type = EV_KEY,
.desc = "volume_down",
- .gpio = GPIO_VOLUME_DOWN,
+ .gpio = GPIO_VOLUME_DOWN_PM8038,
.wakeup = 1,
.active_low = 1,
.debounce_interval = 15,
@@ -1990,7 +2009,7 @@
.code = KEY_CAMERA_FOCUS,
.type = EV_KEY,
.desc = "camera_focus",
- .gpio = GPIO_CAMERA_FOCUS,
+ .gpio = GPIO_CAMERA_FOCUS_PM8038,
.wakeup = 1,
.active_low = 1,
.debounce_interval = 15,
@@ -1999,7 +2018,46 @@
.code = KEY_CAMERA_SNAPSHOT,
.type = EV_KEY,
.desc = "camera_snapshot",
- .gpio = GPIO_CAMERA_SNAPSHOT,
+ .gpio = GPIO_CAMERA_SNAPSHOT_PM8038,
+ .wakeup = 1,
+ .active_low = 1,
+ .debounce_interval = 15,
+ },
+};
+
+static struct gpio_keys_button keys_8930_pm8917[] = {
+ {
+ .code = KEY_VOLUMEUP,
+ .type = EV_KEY,
+ .desc = "volume_up",
+ .gpio = GPIO_VOLUME_UP_PM8917,
+ .wakeup = 1,
+ .active_low = 1,
+ .debounce_interval = 15,
+ },
+ {
+ .code = KEY_VOLUMEDOWN,
+ .type = EV_KEY,
+ .desc = "volume_down",
+ .gpio = GPIO_VOLUME_DOWN_PM8917,
+ .wakeup = 1,
+ .active_low = 1,
+ .debounce_interval = 15,
+ },
+ {
+ .code = KEY_CAMERA_FOCUS,
+ .type = EV_KEY,
+ .desc = "camera_focus",
+ .gpio = GPIO_CAMERA_FOCUS_PM8917,
+ .wakeup = 1,
+ .active_low = 1,
+ .debounce_interval = 15,
+ },
+ {
+ .code = KEY_CAMERA_SNAPSHOT,
+ .type = EV_KEY,
+ .desc = "camera_snapshot",
+ .gpio = GPIO_CAMERA_SNAPSHOT_PM8917,
.wakeup = 1,
.active_low = 1,
.debounce_interval = 15,
@@ -2008,8 +2066,8 @@
/* Add GPIO keys for 8930 */
static struct gpio_keys_platform_data gpio_keys_8930_pdata = {
- .buttons = keys_8930,
- .nbuttons = 4,
+ .buttons = keys_8930_pm8038,
+ .nbuttons = ARRAY_SIZE(keys_8930_pm8038),
};
static struct platform_device gpio_keys_8930 = {
@@ -2075,7 +2133,7 @@
.name = "saw-regulator",
.id = 0,
.dev = {
- .platform_data = &msm8930_saw_regulator_core0_pdata,
+ .platform_data = &msm8930_pm8038_saw_regulator_core0_pdata,
},
};
@@ -2083,7 +2141,7 @@
.name = "saw-regulator",
.id = 1,
.dev = {
- .platform_data = &msm8930_saw_regulator_core1_pdata,
+ .platform_data = &msm8930_pm8038_saw_regulator_core1_pdata,
},
};
@@ -2140,8 +2198,8 @@
.name = GPIO_REGULATOR_DEV_NAME,
.id = 63,
.dev = {
- .platform_data =
- &msm8930_gpio_regulator_pdata[MSM8930_GPIO_VREG_ID_EXT_5V],
+ .platform_data = &msm8930_pm8038_gpio_regulator_pdata[
+ MSM8930_GPIO_VREG_ID_EXT_5V],
},
};
@@ -2149,8 +2207,8 @@
.name = GPIO_REGULATOR_DEV_NAME,
.id = 97,
.dev = {
- .platform_data =
- &msm8930_gpio_regulator_pdata[MSM8930_GPIO_VREG_ID_EXT_OTG_SW],
+ .platform_data = &msm8930_pm8038_gpio_regulator_pdata[
+ MSM8930_GPIO_VREG_ID_EXT_OTG_SW],
},
};
@@ -2163,18 +2221,22 @@
#ifndef MSM8930_PHASE_2
.platform_data = &msm_rpm_regulator_pdata,
#else
- .platform_data = &msm8930_rpm_regulator_pdata,
+ .platform_data = &msm8930_pm8038_rpm_regulator_pdata,
#endif
},
};
-static struct platform_device *common_devices[] __initdata = {
+static struct platform_device *early_common_devices[] __initdata = {
&msm8960_device_dmov,
&msm_device_smd,
&msm8960_device_uart_gsbi5,
&msm_device_uart_dm6,
&msm_device_saw_core0,
&msm_device_saw_core1,
+};
+
+/* ext_5v and ext_otg_sw are present when using PM8038 */
+static struct platform_device *pmic_pm8038_devices[] __initdata = {
&msm8930_device_ext_5v_vreg,
#ifndef MSM8930_PHASE_2
&msm8930_device_ext_l2_vreg,
@@ -2183,6 +2245,14 @@
#ifdef MSM8930_PHASE_2
&msm8930_device_ext_otg_sw_vreg,
#endif
+};
+
+/* ext_5v and ext_otg_sw are not present when using PM8917 */
+static struct platform_device *pmic_pm8917_devices[] __initdata = {
+ &msm8960_device_ssbi_pmic,
+};
+
+static struct platform_device *common_devices[] __initdata = {
&msm_8960_q6_lpass,
&msm_8960_q6_mss_fw,
&msm_8960_q6_mss_sw,
@@ -2404,6 +2474,33 @@
},
};
+static struct msm_rpmrs_platform_data msm_rpmrs_data_pm8917 __initdata = {
+ .levels = &msm_rpmrs_levels[0],
+ .num_levels = ARRAY_SIZE(msm_rpmrs_levels),
+ .vdd_mem_levels = {
+ [MSM_RPMRS_VDD_MEM_RET_LOW] = 750000,
+ [MSM_RPMRS_VDD_MEM_RET_HIGH] = 750000,
+ [MSM_RPMRS_VDD_MEM_ACTIVE] = 1050000,
+ [MSM_RPMRS_VDD_MEM_MAX] = 1150000,
+ },
+ .vdd_dig_levels = {
+ [MSM_RPMRS_VDD_DIG_RET_LOW] = 0,
+ [MSM_RPMRS_VDD_DIG_RET_HIGH] = 0,
+ [MSM_RPMRS_VDD_DIG_ACTIVE] = 1,
+ [MSM_RPMRS_VDD_DIG_MAX] = 3,
+ },
+ .vdd_mask = 0x7FFFFF,
+ .rpmrs_target_id = {
+ [MSM_RPMRS_ID_PXO_CLK] = MSM_RPM_ID_PXO_CLK,
+ [MSM_RPMRS_ID_L2_CACHE_CTL] = MSM_RPM_ID_LAST,
+ [MSM_RPMRS_ID_VDD_DIG_0] = MSM_RPM_ID_VOLTAGE_CORNER,
+ [MSM_RPMRS_ID_VDD_DIG_1] = MSM_RPM_ID_LAST,
+ [MSM_RPMRS_ID_VDD_MEM_0] = MSM_RPM_ID_PM8917_L24_0,
+ [MSM_RPMRS_ID_VDD_MEM_1] = MSM_RPM_ID_PM8917_L24_1,
+ [MSM_RPMRS_ID_RPM_CTL] = MSM_RPM_ID_RPM_CTL,
+ },
+};
+
static struct msm_pm_boot_platform_data msm_pm_boot_pdata __initdata = {
.mode = MSM_PM_BOOT_CONFIG_TZ,
};
@@ -2570,22 +2667,54 @@
#endif
}
+/* Modify platform data values to match requirements for PM8917. */
+static void __init msm8930_pm8917_pdata_fixup(void)
+{
+ struct acpuclk_platform_data *pdata;
+
+ mhl_platform_data.gpio_mhl_power = MHL_POWER_GPIO_PM8917;
+
+ gpio_keys_8930_pdata.buttons = keys_8930_pm8917;
+ gpio_keys_8930_pdata.nbuttons = ARRAY_SIZE(keys_8930_pm8917);
+
+ msm_device_saw_core0.dev.platform_data
+ = &msm8930_pm8038_saw_regulator_core0_pdata;
+ msm_device_saw_core1.dev.platform_data
+ = &msm8930_pm8038_saw_regulator_core1_pdata;
+
+ msm8930_device_rpm_regulator.dev.platform_data
+ = &msm8930_pm8917_rpm_regulator_pdata;
+
+ pdata = msm8930_device_acpuclk.dev.platform_data;
+ pdata->uses_pm8917 = true;
+}
+
static void __init msm8930_cdp_init(void)
{
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
+ msm8930_pm8917_pdata_fixup();
if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
pr_err("meminfo_init() failed!\n");
platform_device_register(&msm_gpio_device);
msm_tsens_early_init(&msm_tsens_pdata);
msm_thermal_init(&msm_thermal_pdata);
- BUG_ON(msm_rpm_init(&msm8930_rpm_data));
- BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
+ if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917) {
+ BUG_ON(msm_rpm_init(&msm8930_rpm_data));
+ BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
+ } else {
+ BUG_ON(msm_rpm_init(&msm8930_rpm_data_pm8917));
+ BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data_pm8917));
+ }
regulator_suppress_info_printing();
if (msm_xo_init())
pr_err("Failed to initialize XO votes\n");
platform_device_register(&msm8930_device_rpm_regulator);
- msm_clock_init(&msm8930_clock_init_data);
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
+ msm_clock_init(&msm8930_pm8917_clock_init_data);
+ else
+ msm_clock_init(&msm8930_clock_init_data);
msm_otg_pdata.phy_init_seq = hsusb_phy_init_seq;
msm8960_device_otg.dev.platform_data = &msm_otg_pdata;
android_usb_pdata.swfi_latency =
@@ -2622,6 +2751,14 @@
platform_device_register(&msm8930_device_acpuclk);
else if (cpu_is_msm8930aa())
platform_device_register(&msm8930aa_device_acpuclk);
+ platform_add_devices(early_common_devices,
+ ARRAY_SIZE(early_common_devices));
+ if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917)
+ platform_add_devices(pmic_pm8038_devices,
+ ARRAY_SIZE(pmic_pm8038_devices));
+ else
+ platform_add_devices(pmic_pm8917_devices,
+ ARRAY_SIZE(pmic_pm8917_devices));
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
msm8930_add_vidc_device();
/*
@@ -2632,7 +2769,10 @@
#ifndef MSM8930_PHASE_2
msm8960_pm8921_gpio_mpp_init();
#else
- msm8930_pm8038_gpio_mpp_init();
+ if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917)
+ msm8930_pm8038_gpio_mpp_init();
+ else
+ msm8930_pm8917_gpio_mpp_init();
#endif
platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
#ifdef CONFIG_MSM_CAMERA
diff --git a/arch/arm/mach-msm/board-8930.h b/arch/arm/mach-msm/board-8930.h
index 9f6276c..7c1ad5b 100644
--- a/arch/arm/mach-msm/board-8930.h
+++ b/arch/arm/mach-msm/board-8930.h
@@ -17,6 +17,7 @@
#include <linux/regulator/msm-gpio-regulator.h>
#include <linux/mfd/pm8xxx/pm8038.h>
+#include <linux/mfd/pm8xxx/pm8921.h>
#include <linux/i2c.h>
#include <linux/i2c/sx150x.h>
#include <mach/irqs.h>
@@ -37,12 +38,23 @@
#endif
/* Macros assume PMIC GPIOs and MPPs start at 1 */
+/*
+ * PM8917 has more GPIOs and MPPs than PM8038; therefore, use PM8038 sizes at
+ * all times so that PM8038 vs PM8917 can be chosen at runtime. This results in
+ * the Linux GPIO address space being contiguous for PM8917 and discontiguous
+ * for PM8038.
+ */
#define PM8038_GPIO_BASE NR_GPIO_IRQS
#define PM8038_GPIO_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8038_GPIO_BASE)
-#define PM8038_MPP_BASE (PM8038_GPIO_BASE + PM8038_NR_GPIOS)
+#define PM8038_MPP_BASE (PM8038_GPIO_BASE + PM8917_NR_GPIOS)
#define PM8038_MPP_PM_TO_SYS(pm_gpio) (pm_gpio - 1 + PM8038_MPP_BASE)
#define PM8038_IRQ_BASE (NR_MSM_IRQS + NR_GPIO_IRQS)
+/* These PM8917 alias macros are used to provide context in board files. */
+#define PM8917_GPIO_PM_TO_SYS(pm_gpio) PM8038_GPIO_PM_TO_SYS(pm_gpio)
+#define PM8917_MPP_PM_TO_SYS(pm_gpio) PM8038_MPP_PM_TO_SYS(pm_gpio)
+#define PM8917_IRQ_BASE PM8038_IRQ_BASE
+
/*
* TODO: When physical 8930/PM8038 hardware becomes
* available, replace this block with 8930/pm8038 regulator
@@ -64,27 +76,36 @@
#define GPIO_VREG_ID_EXT_3P3V 2
#endif
-extern struct regulator_init_data msm8930_saw_regulator_core0_pdata;
-extern struct regulator_init_data msm8930_saw_regulator_core1_pdata;
+extern struct regulator_init_data msm8930_pm8038_saw_regulator_core0_pdata;
+extern struct regulator_init_data msm8930_pm8038_saw_regulator_core1_pdata;
+extern struct regulator_init_data msm8930_pm8917_saw_regulator_core0_pdata;
+extern struct regulator_init_data msm8930_pm8917_saw_regulator_core1_pdata;
extern struct pm8xxx_regulator_platform_data
msm8930_pm8038_regulator_pdata[] __devinitdata;
-
extern int msm8930_pm8038_regulator_pdata_len __devinitdata;
+extern struct pm8xxx_regulator_platform_data
+ msm8930_pm8917_regulator_pdata[] __devinitdata;
+extern int msm8930_pm8917_regulator_pdata_len __devinitdata;
+
#define MSM8930_GPIO_VREG_ID_EXT_5V 0
#define MSM8930_GPIO_VREG_ID_EXT_OTG_SW 1
extern struct gpio_regulator_platform_data
- msm8930_gpio_regulator_pdata[] __devinitdata;
+ msm8930_pm8038_gpio_regulator_pdata[] __devinitdata;
+extern struct gpio_regulator_platform_data
+ msm8930_pm8917_gpio_regulator_pdata[] __devinitdata;
extern struct rpm_regulator_platform_data
- msm8930_rpm_regulator_pdata __devinitdata;
+ msm8930_pm8038_rpm_regulator_pdata __devinitdata;
+extern struct rpm_regulator_platform_data
+ msm8930_pm8917_rpm_regulator_pdata __devinitdata;
#if defined(CONFIG_GPIO_SX150X) || defined(CONFIG_GPIO_SX150X_MODULE)
enum {
GPIO_EXPANDER_IRQ_BASE = (PM8038_IRQ_BASE + PM8038_NR_IRQS),
- GPIO_EXPANDER_GPIO_BASE = (PM8038_MPP_BASE + PM8038_NR_MPPS),
+ GPIO_EXPANDER_GPIO_BASE = (PM8038_MPP_BASE + PM8917_NR_MPPS),
/* CAM Expander */
GPIO_CAM_EXPANDER_BASE = GPIO_EXPANDER_GPIO_BASE,
GPIO_CAM_GP_STROBE_READY = GPIO_CAM_EXPANDER_BASE,
@@ -126,6 +147,7 @@
int msm8930_init_gpiomux(void);
void msm8930_allocate_fb_region(void);
void msm8930_pm8038_gpio_mpp_init(void);
+void msm8930_pm8917_gpio_mpp_init(void);
void msm8930_mdp_writeback(struct memtype_reserve *reserve_table);
void __init msm8930_init_gpu(void);
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index a21c4c3..c00535b 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -13,7 +13,7 @@
#include <asm/mach-types.h>
#include <linux/gpio.h>
-#include <mach/board.h>
+#include <mach/camera.h>
#include <mach/msm_bus_board.h>
#include <mach/gpiomux.h>
#include "devices.h"
@@ -452,19 +452,13 @@
},
};
-static struct camera_vreg_t msm_8960_back_cam_vreg[] = {
+static struct camera_vreg_t msm_8960_cam_vreg[] = {
{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
{"cam_vio", REG_VS, 0, 0, 0},
{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
{"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
};
-static struct camera_vreg_t msm_8960_front_cam_vreg[] = {
- {"cam_vio", REG_VS, 0, 0, 0},
- {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
- {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
-};
-
static struct gpio msm8960_common_cam_gpio[] = {
{5, GPIOF_DIR_IN, "CAMIF_MCLK"},
{20, GPIOF_DIR_IN, "CAMIF_I2C_DATA"},
@@ -549,8 +543,8 @@
static struct msm_camera_sensor_platform_info sensor_board_info_imx074 = {
.mount_angle = 90,
- .cam_vreg = msm_8960_back_cam_vreg,
- .num_vreg = ARRAY_SIZE(msm_8960_back_cam_vreg),
+ .cam_vreg = msm_8960_cam_vreg,
+ .num_vreg = ARRAY_SIZE(msm_8960_cam_vreg),
.gpio_conf = &msm_8960_back_cam_gpio_conf,
.csi_lane_params = &imx074_csi_lane_params,
};
@@ -577,13 +571,6 @@
.eeprom_info = &imx074_eeprom_info,
};
-static struct camera_vreg_t msm_8960_mt9m114_vreg[] = {
- {"cam_vio", REG_VS, 0, 0, 0},
- {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
- {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
- {"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
-};
-
static struct msm_camera_sensor_flash_data flash_mt9m114 = {
.flash_type = MSM_CAMERA_FLASH_NONE
};
@@ -593,10 +580,16 @@
.csi_lane_mask = 0x1,
};
+static struct camera_vreg_t mt9m114_cam_vreg[] = {
+ {"cam_vdig", REG_LDO, 1200000, 1200000, 105000, 50},
+ {"cam_vio", REG_VS, 0, 0, 0, 50},
+ {"cam_vana", REG_LDO, 2800000, 2850000, 85600, 50},
+};
+
static struct msm_camera_sensor_platform_info sensor_board_info_mt9m114 = {
.mount_angle = 90,
- .cam_vreg = msm_8960_mt9m114_vreg,
- .num_vreg = ARRAY_SIZE(msm_8960_mt9m114_vreg),
+ .cam_vreg = mt9m114_cam_vreg,
+ .num_vreg = ARRAY_SIZE(mt9m114_cam_vreg),
.gpio_conf = &msm_8960_front_cam_gpio_conf,
.csi_lane_params = &mt9m114_csi_lane_params,
};
@@ -622,8 +615,8 @@
static struct msm_camera_sensor_platform_info sensor_board_info_ov2720 = {
.mount_angle = 0,
- .cam_vreg = msm_8960_front_cam_vreg,
- .num_vreg = ARRAY_SIZE(msm_8960_front_cam_vreg),
+ .cam_vreg = msm_8960_cam_vreg,
+ .num_vreg = ARRAY_SIZE(msm_8960_cam_vreg),
.gpio_conf = &msm_8960_front_cam_gpio_conf,
.csi_lane_params = &ov2720_csi_lane_params,
};
@@ -638,13 +631,6 @@
.sensor_type = BAYER_SENSOR,
};
-static struct camera_vreg_t msm_8960_s5k3l1yx_vreg[] = {
- {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
- {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
- {"cam_vio", REG_VS, 0, 0, 0},
- {"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
-};
-
static struct msm_camera_sensor_flash_data flash_s5k3l1yx = {
.flash_type = MSM_CAMERA_FLASH_NONE,
};
@@ -656,8 +642,8 @@
static struct msm_camera_sensor_platform_info sensor_board_info_s5k3l1yx = {
.mount_angle = 0,
- .cam_vreg = msm_8960_s5k3l1yx_vreg,
- .num_vreg = ARRAY_SIZE(msm_8960_s5k3l1yx_vreg),
+ .cam_vreg = msm_8960_cam_vreg,
+ .num_vreg = ARRAY_SIZE(msm_8960_cam_vreg),
.gpio_conf = &msm_8960_back_cam_gpio_conf,
.csi_lane_params = &s5k3l1yx_csi_lane_params,
};
@@ -686,13 +672,6 @@
.csi_lane_mask = 0xF,
};
-static struct camera_vreg_t msm_8960_imx091_vreg[] = {
- {"cam_vana", REG_LDO, 2800000, 2850000, 85600},
- {"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
- {"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
- {"cam_vio", REG_VS, 0, 0, 0},
-};
-
static struct msm_camera_sensor_flash_data flash_imx091 = {
.flash_type = MSM_CAMERA_FLASH_LED,
#ifdef CONFIG_MSM_CAMERA_FLASH
@@ -702,8 +681,8 @@
static struct msm_camera_sensor_platform_info sensor_board_info_imx091 = {
.mount_angle = 0,
- .cam_vreg = msm_8960_imx091_vreg,
- .num_vreg = ARRAY_SIZE(msm_8960_imx091_vreg),
+ .cam_vreg = msm_8960_cam_vreg,
+ .num_vreg = ARRAY_SIZE(msm_8960_cam_vreg),
.gpio_conf = &msm_8960_back_cam_gpio_conf,
.csi_lane_params = &imx091_csi_lane_params,
};
@@ -715,6 +694,9 @@
static struct msm_eeprom_info imx091_eeprom_info = {
.board_info = &imx091_eeprom_i2c_info,
.bus_id = MSM_8960_GSBI4_QUP_I2C_BUS_ID,
+ .eeprom_i2c_slave_addr = 0xA1,
+ .eeprom_reg_addr = 0x05,
+ .eeprom_read_length = 6,
};
static struct msm_camera_sensor_info msm_camera_sensor_imx091_data = {
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index 8d75ee9..244125c 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -109,7 +109,7 @@
PM8XXX_GPIO_OUTPUT(43, 1), /* DISP_RESET_N */
PM8XXX_GPIO_OUTPUT(42, 0), /* USB 5V reg enable */
/* TABLA CODEC RESET */
- PM8XXX_GPIO_OUTPUT_STRENGTH(34, 1, PM_GPIO_STRENGTH_MED)
+ PM8XXX_GPIO_OUTPUT_STRENGTH(34, 0, PM_GPIO_STRENGTH_MED)
};
/* Initial PM8921 MPP configurations */
@@ -603,6 +603,8 @@
pm8921_platform_data.bms_pdata->battery_type = BATT_DESAY;
} else if (machine_is_msm8960_mtp()) {
pm8921_platform_data.bms_pdata->battery_type = BATT_PALLADIUM;
+ } else if (machine_is_msm8960_cdp()) {
+ pm8921_chg_pdata.has_dc_supply = true;
}
if (machine_is_msm8960_fluid())
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 641c144..77f94f4 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2324,6 +2324,7 @@
static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi4_pdata = {
.clk_freq = 100000,
.src_clk_rate = 24000000,
+ .keep_ahb_clk_on = 1,
};
static struct msm_i2c_platform_data msm8960_i2c_qup_gsbi3_pdata = {
@@ -2550,43 +2551,42 @@
{
int rc;
+ pr_debug("%s on= %d\n", __func__, on);
+
if (on) {
- rc = gpio_direction_output(gpio_bt_sys_rest_en, 1);
+ rc = gpio_request(gpio_bt_sys_rest_en, "bt sys_rst_n");
+ if (rc) {
+ pr_err("%s: unable to request gpio %d (%d)\n",
+ __func__, gpio_bt_sys_rest_en, rc);
+ goto out;
+ }
+ rc = gpio_direction_output(gpio_bt_sys_rest_en, 0);
+ if (rc) {
+ pr_err("%s: Unable to set gpio %d direction\n",
+ __func__, gpio_bt_sys_rest_en);
+ goto free_gpio;
+ }
msleep(100);
+ gpio_set_value(gpio_bt_sys_rest_en, 1);
+ msleep(100);
+ goto out;
} else {
gpio_set_value(gpio_bt_sys_rest_en, 0);
rc = gpio_direction_input(gpio_bt_sys_rest_en);
msleep(100);
}
- pr_err("%s on= %d rc = %d\n", __func__, on, rc);
- return 0;
+
+free_gpio:
+ gpio_free(gpio_bt_sys_rest_en);
+out:
+ return rc;
}
static void __init bt_power_init(void)
{
- int rc;
-
+ pr_debug("%s enter\n", __func__);
msm_bt_power_device.dev.platform_data = &bluetooth_power;
- pr_err("%s enter\n", __func__);
- rc = gpio_request(gpio_bt_sys_rest_en, "bt sys_rst_n");
- if (rc) {
- pr_err("%s: unable to request gpio %d (%d)\n",
- __func__, gpio_bt_sys_rest_en, rc);
- return;
- }
-
- /* When booting up, de-assert BT reset pin */
- rc = gpio_direction_output(gpio_bt_sys_rest_en, 0);
- if (rc) {
- pr_err("%s: Unable to set direction\n", __func__);
- goto free_gpio;
- }
- pr_err("%s done\n", __func__);
- return;
-
-free_gpio:
- gpio_free(gpio_bt_sys_rest_en);
return;
}
#else
@@ -2642,7 +2642,6 @@
&msm8960_android_pmem_audio_device,
#endif
#endif
- &msm_device_vidc,
&msm_device_bam_dmux,
&msm_fm_platform_init,
#if defined(CONFIG_TSIF) || defined(CONFIG_TSIF_MODULE)
@@ -2710,11 +2709,6 @@
&msm_cpudai_auxpcm_tx,
&msm_cpu_fe,
&msm_stub_codec,
- &msm_kgsl_3d0,
-#ifdef CONFIG_MSM_KGSL_2D
- &msm_kgsl_2d0,
- &msm_kgsl_2d1,
-#endif
#ifdef CONFIG_MSM_GEMINI
&msm8960_gemini_device,
#endif
@@ -2762,21 +2756,26 @@
msm_kgsl_3d0.dev.platform_data;
uint32_t soc_platform_version = socinfo_get_version();
- if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
- kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
- kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
- }
if (cpu_is_msm8960ab()) {
kgsl_3d0_pdata->chipid = ADRENO_CHIPID(3, 2, 1, 0);
- } else {
-
+ } else if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
+ kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
+ kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
+ } else if (SOCINFO_VERSION_MAJOR(soc_platform_version) >= 3) {
/* 8960v3 GPU registers returns 5 for patch release
* but it should be 6, so dummy up the chipid here
* based the platform type
*/
+ kgsl_3d0_pdata->chipid = ADRENO_CHIPID(2, 2, 0, 6);
+ }
- if (SOCINFO_VERSION_MAJOR(soc_platform_version) >= 3)
- kgsl_3d0_pdata->chipid = ADRENO_CHIPID(2, 2, 0, 6);
+ /* Register the 3D core */
+ platform_device_register(&msm_kgsl_3d0);
+
+ /* Register the 2D cores if we are not 8960PRO */
+ if (!cpu_is_msm8960ab()) {
+ platform_device_register(&msm_kgsl_2d0);
+ platform_device_register(&msm_kgsl_2d1);
}
}
@@ -3153,6 +3152,7 @@
else
platform_device_register(&msm8960_device_acpuclk);
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
+ msm8960_add_vidc_device();
msm8960_pm8921_gpio_mpp_init();
platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
diff --git a/arch/arm/mach-msm/board-8960.h b/arch/arm/mach-msm/board-8960.h
index d986670..8f1c619 100644
--- a/arch/arm/mach-msm/board-8960.h
+++ b/arch/arm/mach-msm/board-8960.h
@@ -92,3 +92,4 @@
extern struct msm_rtb_platform_data msm8960_rtb_pdata;
extern struct msm_cache_dump_platform_data msm8960_cache_dump_pdata;
+extern void msm8960_add_vidc_device(void);
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index bcea1c3..74c503d 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -78,6 +78,54 @@
.pull = GPIOMUX_PULL_DOWN,
};
+static struct gpiomux_setting atmel_resout_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting atmel_resout_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting atmel_int_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting atmel_int_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting taiko_reset = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_NONE,
+ .dir = GPIOMUX_OUT_LOW,
+};
+
+static struct msm_gpiomux_config msm_touch_configs[] __initdata = {
+ {
+ .gpio = 60, /* TOUCH RESET */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &atmel_resout_act_cfg,
+ [GPIOMUX_SUSPENDED] = &atmel_resout_sus_cfg,
+ },
+ },
+ {
+ .gpio = 61, /* TOUCH IRQ */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &atmel_int_act_cfg,
+ [GPIOMUX_SUSPENDED] = &atmel_int_sus_cfg,
+ },
+ },
+
+};
static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
{
@@ -113,6 +161,18 @@
},
},
{
+ .gpio = 6, /* BLSP1 QUP2 I2C_DAT */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_i2c_config,
+ },
+ },
+ {
+ .gpio = 7, /* BLSP1 QUP2 I2C_CLK */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_i2c_config,
+ },
+ },
+ {
.gpio = 83, /* BLSP11 QUP I2C_DAT */
.settings = {
[GPIOMUX_SUSPENDED] = &gpio_i2c_config,
@@ -153,6 +213,164 @@
},
};
+static struct gpiomux_setting cam_settings[] = {
+ {
+ .func = GPIOMUX_FUNC_1, /*active 1*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_NONE,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_1, /*suspend*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+ },
+
+ {
+ .func = GPIOMUX_FUNC_1, /*i2c suspend*/
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_KEEPER,
+ },
+};
+
+static struct msm_gpiomux_config msm_sensor_configs[] __initdata = {
+ {
+ .gpio = 15, /* CAM_MCLK0 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 16, /* CAM_MCLK1 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 17, /* CAM_MCLK2 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 18, /* WEBCAM1_RESET_N / CAM_MCLK3 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 19, /* CCI_I2C_SDA0 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[2],
+ },
+ },
+ {
+ .gpio = 20, /* CCI_I2C_SCL0 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[2],
+ },
+ },
+ {
+ .gpio = 21, /* CCI_I2C_SDA1 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[2],
+ },
+ },
+ {
+ .gpio = 22, /* CCI_I2C_SCL1 */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[2],
+ },
+ },
+ {
+ .gpio = 23, /* FLASH_LED_EN */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 24, /* FLASH_LED_NOW */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 25, /* WEBCAM2_RESET_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 26, /* CAM_IRQ */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 27, /* OIS_SYNC */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 28, /* WEBCAM1_STANDBY */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 89, /* CAM1_STANDBY_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 90, /* CAM1_RST_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 91, /* CAM2_STANDBY_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+ {
+ .gpio = 92, /* CAM2_RST_N */
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cam_settings[0],
+ [GPIOMUX_SUSPENDED] = &cam_settings[1],
+ },
+ },
+};
+
+static struct msm_gpiomux_config msm_taiko_config[] __initdata = {
+ {
+ .gpio = 63, /* SYS_RST_N */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &taiko_reset,
+ },
+ }
+};
+
void __init msm_8974_init_gpiomux(void)
{
int rc;
@@ -171,4 +389,9 @@
msm_gpiomux_install(msm8974_slimbus_config,
ARRAY_SIZE(msm8974_slimbus_config));
+ msm_gpiomux_install(msm_touch_configs, ARRAY_SIZE(msm_touch_configs));
+
+ msm_gpiomux_install(msm_sensor_configs, ARRAY_SIZE(msm_sensor_configs));
+
+ msm_gpiomux_install(msm_taiko_config, ARRAY_SIZE(msm_taiko_config));
}
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 388307b..c3eb10c 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -393,6 +393,51 @@
&msm_bus_ocmem_vnoc,
};
+static ssize_t mxt336s_vkeys_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, 200,
+ __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":62:1345:90:90" \
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":240:1345:90:90" \
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":470:1345:90:90" \
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":658:1345:90:90" \
+ "\n");
+}
+
+static struct kobj_attribute mxt336s_vkeys_attr = {
+ .attr = {
+ .mode = S_IRUGO,
+ },
+ .show = &mxt336s_vkeys_show,
+};
+
+static struct attribute *mxt336s_properties_attrs[] = {
+ &mxt336s_vkeys_attr.attr,
+ NULL
+};
+
+static struct attribute_group mxt336s_properties_attr_group = {
+ .attrs = mxt336s_properties_attrs,
+};
+
+static void mxt_init_vkeys_8974(void)
+{
+ int rc = 0;
+ static struct kobject *mxt336s_properties_kobj;
+
+ mxt336s_vkeys_attr.attr.name = "virtualkeys.atmel_mxt_ts";
+ mxt336s_properties_kobj = kobject_create_and_add("board_properties",
+ NULL);
+ if (mxt336s_properties_kobj)
+ rc = sysfs_create_group(mxt336s_properties_kobj,
+ &mxt336s_properties_attr_group);
+ if (!mxt336s_properties_kobj || rc)
+ pr_err("%s: failed to create board_properties\n",
+ __func__);
+
+ return;
+}
+
static void __init msm8974_init_buses(void)
{
#ifdef CONFIG_MSM_BUS_SCALING
@@ -436,6 +481,7 @@
msm_clock_init(&msm8974_clock_init_data);
msm8974_init_buses();
msm_thermal_device_init();
+ mxt_init_vkeys_8974();
}
static struct of_device_id irq_match[] __initdata = {
diff --git a/arch/arm/mach-msm/board-9615-gpiomux.c b/arch/arm/mach-msm/board-9615-gpiomux.c
index 47a9835..9339638 100644
--- a/arch/arm/mach-msm/board-9615-gpiomux.c
+++ b/arch/arm/mach-msm/board-9615-gpiomux.c
@@ -119,6 +119,13 @@
.dir = GPIOMUX_IN,
};
+static struct gpiomux_setting tabla_reset = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_NONE,
+ .dir = GPIOMUX_OUT_LOW,
+};
+
static struct msm_gpiomux_config msm9615_audio_codec_configs[] __initdata = {
{
.gpio = 24,
@@ -126,6 +133,12 @@
[GPIOMUX_SUSPENDED] = &cdc_mclk,
},
},
+ {
+ .gpio = 84, /* SYS_RST_N */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &tabla_reset,
+ },
+ }
};
static struct msm_gpiomux_config msm9615_sdcc2_configs[] __initdata = {
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index 1e198a7..d1d85fc 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -19,7 +19,7 @@
#include <linux/module.h>
#include <asm/mach-types.h>
#include <mach/msm_iomap.h>
-#include <mach/board.h>
+#include <mach/camera.h>
#include <mach/irqs-7xxx.h>
#include "devices-msm7x2xa.h"
#include "board-msm7627a.h"
@@ -396,7 +396,7 @@
sensor_board_info_ov8825.num_vreg = 0;
}
- if (machine_is_msm8625_evb()
+ if (machine_is_msm8625_evb() || machine_is_msm7627a_evb()
|| machine_is_msm8625_evt()) {
sensor_board_info_ov7692.cam_vreg =
ov7692_gpio_vreg;
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index b67d982..e00f150 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -63,6 +63,13 @@
#define PMEM_KERNEL_EBI1_SIZE 0x3A000
#define MSM_PMEM_AUDIO_SIZE 0x1F4000
+#define SNDDEV_CAP_NONE 0x0
+#define SNDDEV_CAP_RX 0x1 /* RX direction */
+#define SNDDEV_CAP_TX 0x2 /* TX direction */
+#define SNDDEV_CAP_VOICE 0x4 /* Support voice call */
+#define SNDDEV_CAP_FM 0x10 /* Support FM radio */
+#define SNDDEV_CAP_TTY 0x20 /* Support TTY */
+
#if defined(CONFIG_GPIO_SX150X)
enum {
SX150X_CORE,
@@ -494,7 +501,6 @@
SND(FM_ANALOG_STEREO_HEADSET_CODEC, 36),
};
#undef SND
-
static struct msm_snd_endpoints msm_device_snd_endpoints = {
.endpoints = snd_endpoints_list,
.num = sizeof(snd_endpoints_list) / sizeof(struct snd_endpoint)
@@ -508,6 +514,55 @@
},
};
+#define CAD(desc, num, cap) { .name = #desc, .id = num, .capability = cap, }
+static struct cad_endpoint cad_endpoints_list[] = {
+ CAD(NONE, 0, SNDDEV_CAP_NONE),
+ CAD(HANDSET_SPKR, 1, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(HANDSET_MIC, 2, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(HEADSET_MIC, 3, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(HEADSET_SPKR_MONO, 4, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(HEADSET_SPKR_STEREO, 5, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(SPEAKER_PHONE_MIC, 6, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(SPEAKER_PHONE_MONO, 7, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(SPEAKER_PHONE_STEREO, 8, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(BT_SCO_MIC, 9, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(BT_SCO_SPKR, 10, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(BT_A2DP_SPKR, 11, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(TTY_HEADSET_MIC, 12, (SNDDEV_CAP_TX | \
+ SNDDEV_CAP_VOICE | SNDDEV_CAP_TTY)),
+ CAD(TTY_HEADSET_SPKR, 13, (SNDDEV_CAP_RX | \
+ SNDDEV_CAP_VOICE | SNDDEV_CAP_TTY)),
+ CAD(HEADSET_STEREO_PLUS_SPKR_MONO_RX, 19, (SNDDEV_CAP_TX | \
+ SNDDEV_CAP_VOICE)),
+ CAD(LP_FM_HEADSET_SPKR_STEREO_RX, 25, (SNDDEV_CAP_TX | SNDDEV_CAP_FM)),
+ CAD(I2S_RX, 26, (SNDDEV_CAP_RX)),
+ CAD(SPEAKER_PHONE_MIC_ENDFIRE, 45, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(HANDSET_MIC_ENDFIRE, 46, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(I2S_TX, 48, (SNDDEV_CAP_TX)),
+ CAD(LP_FM_HEADSET_SPKR_STEREO_PLUS_HEADSET_SPKR_STEREO_RX, 57, \
+ (SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+ CAD(FM_DIGITAL_HEADSET_SPKR_STEREO, 65, \
+ (SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+ CAD(FM_DIGITAL_SPEAKER_PHONE_MONO, 67, \
+ (SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+ CAD(FM_DIGITAL_BT_A2DP_SPKR, 69, \
+ (SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+ CAD(MAX, 80, SNDDEV_CAP_NONE),
+};
+#undef CAD
+static struct msm_cad_endpoints msm_device_cad_endpoints = {
+ .endpoints = cad_endpoints_list,
+ .num = sizeof(cad_endpoints_list) / sizeof(struct cad_endpoint)
+};
+
+static struct platform_device msm_device_cad = {
+ .name = "msm_cad",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_device_cad_endpoints
+ },
+};
+
#define DEC0_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
(1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
(1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
@@ -814,6 +869,7 @@
&android_pmem_audio_device,
&msm_device_nand,
&msm_device_snd,
+ &msm_device_cad,
&msm_device_adspdec,
&asoc_msm_pcm,
&asoc_msm_dai0,
diff --git a/arch/arm/mach-msm/board-msm8x60-camera.c b/arch/arm/mach-msm/board-msm8x60-camera.c
index cd95630..acd7f74 100644
--- a/arch/arm/mach-msm/board-msm8x60-camera.c
+++ b/arch/arm/mach-msm/board-msm8x60-camera.c
@@ -15,7 +15,7 @@
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/mfd/pmic8901.h>
-#include <mach/board.h>
+#include <mach/camera.h>
#include <mach/board-msm8660.h>
#include <mach/gpiomux.h>
#include <mach/msm_bus_board.h>
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 6fa45c6..1da9ede 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -75,6 +75,13 @@
#define I2C_PIN_CTL 0x15
#define I2C_NORMAL 0x40
+#define SNDDEV_CAP_NONE 0x0
+#define SNDDEV_CAP_RX 0x1 /* RX direction */
+#define SNDDEV_CAP_TX 0x2 /* TX direction */
+#define SNDDEV_CAP_VOICE 0x4 /* Support voice call */
+#define SNDDEV_CAP_FM 0x10 /* Support FM radio */
+#define SNDDEV_CAP_TTY 0x20 /* Support TTY */
+
static struct platform_device msm_wlan_ar6000_pm_device = {
.name = "wlan_ar6000_pm_dev",
.id = -1,
@@ -132,12 +139,12 @@
#define MSM_PMEM_MDP_SIZE 0x1B00000
#define MSM_PMEM_ADSP_SIZE 0x1200000
-#define MSM_ION_AUDIO_SIZE (MSM_PMEM_AUDIO_SIZE + PMEM_KERNEL_EBI1_SIZE)
-#define MSM_ION_CAMERA_SIZE MSM_PMEM_ADSP_SIZE
-#define MSM_ION_SF_SIZE MSM_PMEM_MDP_SIZE
-#define MSM_ION_HEAP_NUM 4
#ifdef CONFIG_ION_MSM
+#define MSM_ION_HEAP_NUM 4
static struct platform_device ion_dev;
+static int msm_ion_camera_size;
+static int msm_ion_audio_size;
+static int msm_ion_sf_size;
#endif
#endif
@@ -454,6 +461,56 @@
},
};
+#define CAD(desc, num, cap) { .name = #desc, .id = num, .capability = cap, }
+static struct cad_endpoint cad_endpoints_list[] = {
+ CAD(NONE, 0, SNDDEV_CAP_NONE),
+ CAD(HANDSET_SPKR, 1, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(HANDSET_MIC, 2, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(HEADSET_MIC, 3, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(HEADSET_SPKR_MONO, 4, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(HEADSET_SPKR_STEREO, 5, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(SPEAKER_PHONE_MIC, 6, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(SPEAKER_PHONE_MONO, 7, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(SPEAKER_PHONE_STEREO, 8, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(BT_SCO_MIC, 9, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(BT_SCO_SPKR, 10, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(BT_A2DP_SPKR, 11, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(TTY_HEADSET_MIC, 12, (SNDDEV_CAP_TX | \
+ SNDDEV_CAP_VOICE | SNDDEV_CAP_TTY)),
+ CAD(TTY_HEADSET_SPKR, 13, (SNDDEV_CAP_RX | \
+ SNDDEV_CAP_VOICE | SNDDEV_CAP_TTY)),
+ CAD(HEADSET_STEREO_PLUS_SPKR_MONO_RX, 19, (SNDDEV_CAP_TX | \
+ SNDDEV_CAP_VOICE)),
+ CAD(LP_FM_HEADSET_SPKR_STEREO_RX, 25, (SNDDEV_CAP_TX | SNDDEV_CAP_FM)),
+ CAD(I2S_RX, 26, (SNDDEV_CAP_RX)),
+ CAD(SPEAKER_PHONE_MIC_ENDFIRE, 45, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(HANDSET_MIC_ENDFIRE, 46, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(I2S_TX, 48, (SNDDEV_CAP_TX)),
+ CAD(LP_FM_HEADSET_SPKR_STEREO_PLUS_HEADSET_SPKR_STEREO_RX, 57, \
+ (SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+ CAD(FM_DIGITAL_HEADSET_SPKR_STEREO, 65, \
+ (SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+ CAD(FM_DIGITAL_SPEAKER_PHONE_MONO, 67, \
+ (SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+ CAD(FM_DIGITAL_BT_A2DP_SPKR, 69, \
+ (SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+ CAD(MAX, 80, SNDDEV_CAP_NONE),
+};
+#undef CAD
+
+static struct msm_cad_endpoints msm_device_cad_endpoints = {
+ .endpoints = cad_endpoints_list,
+ .num = sizeof(cad_endpoints_list) / sizeof(struct cad_endpoint)
+};
+
+static struct platform_device msm_device_cad = {
+ .name = "msm_cad",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_device_cad_endpoints
+ },
+};
+
#define DEC0_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
(1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
(1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
@@ -702,6 +759,7 @@
&msm_batt_device,
&msm_device_adspdec,
&msm_device_snd,
+ &msm_device_cad,
&asoc_msm_pcm,
&asoc_msm_dai0,
&asoc_msm_dai1,
@@ -759,6 +817,15 @@
}
early_param("pmem_audio_size", pmem_audio_size_setup);
+static void fix_sizes(void)
+{
+#ifdef CONFIG_ION_MSM
+ msm_ion_camera_size = pmem_adsp_size;
+ msm_ion_audio_size = (MSM_PMEM_AUDIO_SIZE + PMEM_KERNEL_EBI1_SIZE);
+ msm_ion_sf_size = pmem_mdp_size;
+#endif
+}
+
#ifdef CONFIG_ION_MSM
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
static struct ion_co_heap_pdata co_ion_pdata = {
@@ -786,7 +853,6 @@
.id = ION_CAMERA_HEAP_ID,
.type = ION_HEAP_TYPE_CARVEOUT,
.name = ION_CAMERA_HEAP_NAME,
- .size = MSM_ION_CAMERA_SIZE,
.memory_type = ION_EBI_TYPE,
.extra_data = (void *)&co_ion_pdata,
},
@@ -795,7 +861,6 @@
.id = ION_AUDIO_HEAP_ID,
.type = ION_HEAP_TYPE_CARVEOUT,
.name = ION_AUDIO_HEAP_NAME,
- .size = MSM_ION_AUDIO_SIZE,
.memory_type = ION_EBI_TYPE,
.extra_data = (void *)&co_ion_pdata,
},
@@ -804,7 +869,6 @@
.id = ION_SF_HEAP_ID,
.type = ION_HEAP_TYPE_CARVEOUT,
.name = ION_SF_HEAP_NAME,
- .size = MSM_ION_SF_SIZE,
.memory_type = ION_EBI_TYPE,
.extra_data = (void *)&co_ion_pdata,
},
@@ -873,19 +937,30 @@
#endif
}
+static void __init size_ion_devices(void)
+{
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ ion_pdata.heaps[1].size = msm_ion_camera_size;
+ ion_pdata.heaps[2].size = msm_ion_audio_size;
+ ion_pdata.heaps[3].size = msm_ion_sf_size;
+#endif
+}
+
static void __init reserve_ion_memory(void)
{
#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
- msm7627a_reserve_table[MEMTYPE_EBI1].size += MSM_ION_CAMERA_SIZE;
- msm7627a_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE;
- msm7627a_reserve_table[MEMTYPE_EBI1].size += MSM_ION_SF_SIZE;
+ msm7627a_reserve_table[MEMTYPE_EBI1].size += msm_ion_camera_size;
+ msm7627a_reserve_table[MEMTYPE_EBI1].size += msm_ion_audio_size;
+ msm7627a_reserve_table[MEMTYPE_EBI1].size += msm_ion_sf_size;
#endif
}
static void __init msm7627a_calculate_reserve_sizes(void)
{
+ fix_sizes();
size_pmem_devices();
reserve_pmem_memory();
+ size_ion_devices();
reserve_ion_memory();
}
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index df5f748..e6229d5 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -393,6 +393,7 @@
static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig_8960);
+static int rpm_vreg_dig_8930 = RPM_VREG_ID_PM8038_VDD_DIG_CORNER;
static int set_vdd_dig_8930(struct clk_vdd_class *vdd_class, int level)
{
static const int vdd_corner[] = {
@@ -401,7 +402,7 @@
[VDD_DIG_NOMINAL] = RPM_VREG_CORNER_NOMINAL,
[VDD_DIG_HIGH] = RPM_VREG_CORNER_HIGH,
};
- return rpm_vreg_set_voltage(RPM_VREG_ID_PM8038_VDD_DIG_CORNER,
+ return rpm_vreg_set_voltage(rpm_vreg_dig_8930,
RPM_VREG_VOTER3,
vdd_corner[level],
RPM_VREG_CORNER_HIGH, 1);
@@ -467,6 +468,36 @@
sr2_lreg_uv[level], sr2_lreg_uv[level], 1);
}
+static int set_vdd_sr2_hdmi_pll_8930_pm8917(struct clk_vdd_class *vdd_class,
+ int level)
+{
+ int rc = 0;
+
+ if (level == VDD_SR2_HDMI_PLL_OFF) {
+ rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8917_L23,
+ RPM_VREG_VOTER3, 0, 0, 1);
+ if (rc)
+ return rc;
+ rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8917_S8,
+ RPM_VREG_VOTER3, 0, 0, 1);
+ if (rc)
+ rpm_vreg_set_voltage(RPM_VREG_ID_PM8917_L23,
+ RPM_VREG_VOTER3, 1800000, 1800000, 1);
+ } else {
+ rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8917_S8,
+ RPM_VREG_VOTER3, 2050000, 2100000, 1);
+ if (rc)
+ return rc;
+ rc = rpm_vreg_set_voltage(RPM_VREG_ID_PM8917_L23,
+ RPM_VREG_VOTER3, 1800000, 1800000, 1);
+ if (rc)
+ rpm_vreg_set_voltage(RPM_VREG_ID_PM8917_S8,
+ RPM_VREG_VOTER3, 0, 0, 1);
+ }
+
+ return rc;
+}
+
static int set_vdd_sr2_hdmi_pll_8930(struct clk_vdd_class *vdd_class, int level)
{
return rpm_vreg_set_voltage(RPM_VREG_ID_PM8038_L23, RPM_VREG_VOTER3,
@@ -5818,6 +5849,7 @@
static struct clk_lookup msm_clocks_8960ab_only[] __initdata = {
CLK_LOOKUP("bus_clk", gfx3d_axi_clk.c, "footswitch-8x60.2"),
+ CLK_LOOKUP("core_clk", gfx3d_axi_clk.c, "msm_iommu.10"),
CLK_LOOKUP("div_clk", tv_src_div_clk.c, ""),
};
@@ -6236,7 +6268,7 @@
rmwreg(0x00000003, AHB_EN_REG, 0x6C000103);
writel_relaxed(0x000007F9, AHB_EN2_REG);
} else {
- rmwreg(0x44000000, AHB_EN_REG, 0x6C000103);
+ rmwreg(0x40000000, AHB_EN_REG, 0x6C000103);
writel_relaxed(0x3C7097F9, AHB_EN2_REG);
}
@@ -6420,12 +6452,8 @@
/* Initialize clock registers. */
reg_init();
- if (cpu_is_apq8064()) {
+ if (cpu_is_apq8064())
vdd_sr2_hdmi_pll.set_vdd = set_vdd_sr2_hdmi_pll_8064;
- } else if (cpu_is_msm8930() || cpu_is_msm8930aa() || cpu_is_msm8627()) {
- vdd_dig.set_vdd = set_vdd_dig_8930;
- vdd_sr2_hdmi_pll.set_vdd = set_vdd_sr2_hdmi_pll_8930;
- }
/* Detect PLL4 programmed for alternate 491.52MHz clock plan. */
if (readl_relaxed(LCC_PLL0_L_VAL_REG) == 0x12) {
@@ -6456,6 +6484,8 @@
msm_clocks_8960ab_only, sizeof(msm_clocks_8960ab_only));
msm8960_clock_init_data.size -=
ARRAY_SIZE(msm_clocks_8960_only);
+
+ gmem_axi_clk.c.depends = &gfx3d_axi_clk.c;
} else if (cpu_is_msm8960()) {
memcpy(msm_clocks_8960 + ARRAY_SIZE(msm_clocks_8960_common),
msm_clocks_8960_only, sizeof(msm_clocks_8960_only));
@@ -6507,6 +6537,25 @@
clk_ops_local_pll.enable = sr_pll_clk_enable;
}
+static void __init msm8930_pm8917_clock_pre_init(void)
+{
+ /* detect pmic8917 from board file, and call this init function */
+
+ vdd_dig.set_vdd = set_vdd_dig_8930;
+ rpm_vreg_dig_8930 = RPM_VREG_ID_PM8917_VDD_DIG_CORNER;
+ vdd_sr2_hdmi_pll.set_vdd = set_vdd_sr2_hdmi_pll_8930_pm8917;
+
+ msm8960_clock_pre_init();
+}
+
+static void __init msm8930_clock_pre_init(void)
+{
+ vdd_dig.set_vdd = set_vdd_dig_8930;
+ vdd_sr2_hdmi_pll.set_vdd = set_vdd_sr2_hdmi_pll_8930;
+
+ msm8960_clock_pre_init();
+}
+
static void __init msm8960_clock_post_init(void)
{
/* Keep PXO on whenever APPS cpu is active */
@@ -6617,7 +6666,15 @@
struct clock_init_data msm8930_clock_init_data __initdata = {
.table = msm_clocks_8930,
.size = ARRAY_SIZE(msm_clocks_8930),
- .pre_init = msm8960_clock_pre_init,
+ .pre_init = msm8930_clock_pre_init,
+ .post_init = msm8960_clock_post_init,
+ .late_init = msm8960_clock_late_init,
+};
+
+struct clock_init_data msm8930_pm8917_clock_init_data __initdata = {
+ .table = msm_clocks_8930,
+ .size = ARRAY_SIZE(msm_clocks_8930),
+ .pre_init = msm8930_pm8917_clock_pre_init,
.post_init = msm8960_clock_post_init,
.late_init = msm8960_clock_late_init,
};
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index e4bcfa9..9eb3e8b 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -29,6 +29,7 @@
#include "clock-pll.h"
#include "clock-rpm.h"
#include "clock-voter.h"
+#include "clock-mdss-8974.h"
enum {
GCC_BASE,
@@ -121,6 +122,10 @@
#define USB_HSIC_CMD_RCGR 0x0440
#define USB_HSIC_IO_CAL_CMD_RCGR 0x0458
#define USB_HS_SYSTEM_CMD_RCGR 0x0490
+#define SYS_NOC_USB3_AXI_CBCR 0x0108
+#define USB30_SLEEP_CBCR 0x03CC
+#define USB2A_PHY_SLEEP_CBCR 0x04AC
+#define USB2B_PHY_SLEEP_CBCR 0x04B4
#define SDCC1_APPS_CMD_RCGR 0x04D0
#define SDCC2_APPS_CMD_RCGR 0x0510
#define SDCC3_APPS_CMD_RCGR 0x0550
@@ -492,6 +497,7 @@
#define LPASS_Q6SS_XO_CBCR 0x26000
#define LPASS_Q6_AXI_CBCR 0x11C0
#define Q6SS_AHBM_CBCR 0x22004
+#define AUDIO_WRAPPER_BR_CBCR 0x24000
#define MSS_XO_Q6_CBCR 0x108C
#define MSS_BUS_Q6_CBCR 0x10A4
#define MSS_CFG_AHB_CBCR 0x0280
@@ -518,7 +524,8 @@
#define edppll_270_mm_source_val 4
#define edppll_350_mm_source_val 4
#define dsipll_750_mm_source_val 1
-#define dsipll_250_mm_source_val 2
+#define dsipll0_byte_mm_source_val 1
+#define dsipll0_pixel_mm_source_val 1
#define hdmipll_297_mm_source_val 3
#define F(f, s, div, m, n) \
@@ -628,7 +635,8 @@
#define MMSSNOC_AHB_ID 0x3
#define BIMC_ID 0x0
-#define OCMEM_ID 0x1
+#define OXILI_ID 0x1
+#define OCMEM_ID 0x2
enum {
D0_ID = 1,
@@ -647,6 +655,8 @@
DEFINE_CLK_RPM_SMD(bimc_clk, bimc_a_clk, RPM_MEM_CLK_TYPE, BIMC_ID, NULL);
DEFINE_CLK_RPM_SMD(ocmemgx_clk, ocmemgx_a_clk, RPM_MEM_CLK_TYPE, OCMEM_ID,
NULL);
+DEFINE_CLK_RPM_SMD(gfx3d_clk_src, gfx3d_a_clk_src, RPM_MEM_CLK_TYPE, OXILI_ID,
+ NULL);
DEFINE_CLK_RPM_SMD_BRANCH(cxo_clk_src, cxo_a_clk_src,
RPM_MISC_CLK_TYPE, CXO_ID, 19200000);
@@ -767,7 +777,7 @@
static DEFINE_CLK_VOTER(bimc_msmbus_clk, &bimc_clk.c, LONG_MAX);
static DEFINE_CLK_VOTER(bimc_msmbus_a_clk, &bimc_a_clk.c, LONG_MAX);
static DEFINE_CLK_VOTER(bimc_acpu_a_clk, &bimc_a_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(ocmemgx_gfx3d_clk, &ocmemgx_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(oxili_gfx3d_clk_src, &gfx3d_clk_src.c, LONG_MAX);
static DEFINE_CLK_VOTER(ocmemgx_msmbus_clk, &ocmemgx_clk.c, LONG_MAX);
static DEFINE_CLK_VOTER(ocmemgx_msmbus_a_clk, &ocmemgx_a_clk.c, LONG_MAX);
static DEFINE_CLK_VOTER(ocmemgx_core_clk, &ocmemgx_clk.c, LONG_MAX);
@@ -2196,6 +2206,51 @@
},
};
+struct branch_clk gcc_sys_noc_usb3_axi_clk = {
+ .cbcr_reg = SYS_NOC_USB3_AXI_CBCR,
+ .parent = &usb30_master_clk_src.c,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_sys_noc_usb3_axi_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_sys_noc_usb3_axi_clk.c),
+ },
+};
+
+struct branch_clk gcc_usb30_sleep_clk = {
+ .cbcr_reg = USB30_SLEEP_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_usb30_sleep_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_usb30_sleep_clk.c),
+ },
+};
+
+struct branch_clk gcc_usb2a_phy_sleep_clk = {
+ .cbcr_reg = USB2A_PHY_SLEEP_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_usb2a_phy_sleep_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_usb2a_phy_sleep_clk.c),
+ },
+};
+
+struct branch_clk gcc_usb2b_phy_sleep_clk = {
+ .cbcr_reg = USB2B_PHY_SLEEP_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_usb2b_phy_sleep_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_usb2b_phy_sleep_clk.c),
+ },
+};
+
static struct branch_clk gcc_usb_hs_ahb_clk = {
.cbcr_reg = USB_HS_AHB_CBCR,
.has_sibling = 1,
@@ -2604,6 +2659,7 @@
};
static struct clk_freq_tbl ftbl_camss_mclk0_3_clk[] = {
+ F_MM(19200000, cxo, 1, 0, 0),
F_MM(66670000, gpll0, 9, 0, 0),
F_END
};
@@ -2734,21 +2790,101 @@
},
};
-static struct clk_freq_tbl ftbl_mdss_byte0_1_clk[] = {
- F_MDSS( 93750000, dsipll_750, 8, 0, 0),
- F_MDSS(187500000, dsipll_750, 4, 0, 0),
- F_END
+static struct clk *dsi_pll_clk_get_parent(struct clk *c)
+{
+ return &cxo_clk_src.c;
+}
+
+static struct clk dsipll0_byte_clk_src = {
+ .dbg_name = "dsipll0_byte_clk_src",
+ .ops = &clk_ops_dsi_byte_pll,
+ CLK_INIT(dsipll0_byte_clk_src),
};
+static struct clk dsipll0_pixel_clk_src = {
+ .dbg_name = "dsipll0_pixel_clk_src",
+ .ops = &clk_ops_dsi_pixel_pll,
+ CLK_INIT(dsipll0_pixel_clk_src),
+};
+
+static struct clk_freq_tbl byte_freq = {
+ .src_clk = &dsipll0_byte_clk_src,
+ .div_src_val = BVAL(10, 8, dsipll0_byte_mm_source_val),
+};
+static struct clk_freq_tbl pixel_freq = {
+ .src_clk = &dsipll0_byte_clk_src,
+ .div_src_val = BVAL(10, 8, dsipll0_byte_mm_source_val),
+};
+static struct clk_ops clk_ops_byte;
+static struct clk_ops clk_ops_pixel;
+
+#define CFG_RCGR_DIV_MASK BM(4, 0)
+
+static int set_rate_byte(struct clk *clk, unsigned long rate)
+{
+ struct rcg_clk *rcg = to_rcg_clk(clk);
+ struct clk *pll = &dsipll0_byte_clk_src;
+ unsigned long source_rate, div;
+ int rc;
+
+ if (rate == 0)
+ return -EINVAL;
+
+ rc = clk_set_rate(pll, rate);
+ if (rc)
+ return rc;
+
+ source_rate = clk_round_rate(pll, rate);
+ if ((2 * source_rate) % rate)
+ return -EINVAL;
+
+ div = ((2 * source_rate)/rate) - 1;
+ if (div > CFG_RCGR_DIV_MASK)
+ return -EINVAL;
+
+ byte_freq.div_src_val &= ~CFG_RCGR_DIV_MASK;
+ byte_freq.div_src_val |= BVAL(4, 0, div);
+ set_rate_mnd(rcg, &byte_freq);
+
+ return 0;
+}
+
+static int set_rate_pixel(struct clk *clk, unsigned long rate)
+{
+ struct rcg_clk *rcg = to_rcg_clk(clk);
+ struct clk *pll = &dsipll0_pixel_clk_src;
+ unsigned long source_rate, div;
+ int rc;
+
+ if (rate == 0)
+ return -EINVAL;
+
+ rc = clk_set_rate(pll, rate);
+ if (rc)
+ return rc;
+
+ source_rate = clk_round_rate(pll, rate);
+ if ((2 * source_rate) % rate)
+ return -EINVAL;
+
+ div = ((2 * source_rate)/rate) - 1;
+ if (div > CFG_RCGR_DIV_MASK)
+ return -EINVAL;
+
+ pixel_freq.div_src_val &= ~CFG_RCGR_DIV_MASK;
+ pixel_freq.div_src_val |= BVAL(4, 0, div);
+ set_rate_hid(rcg, &pixel_freq);
+
+ return 0;
+}
+
static struct rcg_clk byte0_clk_src = {
.cmd_rcgr_reg = BYTE0_CMD_RCGR,
- .set_rate = set_rate_hid,
- .freq_tbl = ftbl_mdss_byte0_1_clk,
- .current_freq = &rcg_dummy_freq,
+ .current_freq = &byte_freq,
.base = &virt_bases[MMSS_BASE],
.c = {
.dbg_name = "byte0_clk_src",
- .ops = &clk_ops_rcg,
+ .ops = &clk_ops_byte,
VDD_DIG_FMAX_MAP3(LOW, 93800000, NOMINAL, 187500000,
HIGH, 188000000),
CLK_INIT(byte0_clk_src.c),
@@ -2757,13 +2893,11 @@
static struct rcg_clk byte1_clk_src = {
.cmd_rcgr_reg = BYTE1_CMD_RCGR,
- .set_rate = set_rate_hid,
- .freq_tbl = ftbl_mdss_byte0_1_clk,
- .current_freq = &rcg_dummy_freq,
+ .current_freq = &byte_freq,
.base = &virt_bases[MMSS_BASE],
.c = {
.dbg_name = "byte1_clk_src",
- .ops = &clk_ops_rcg,
+ .ops = &clk_ops_byte,
VDD_DIG_FMAX_MAP3(LOW, 93800000, NOMINAL, 187500000,
HIGH, 188000000),
CLK_INIT(byte1_clk_src.c),
@@ -2900,21 +3034,14 @@
},
};
-static struct clk_freq_tbl ftbl_mdss_pclk0_1_clk[] = {
- F_MDSS(125000000, dsipll_250, 2, 0, 0),
- F_MDSS(250000000, dsipll_250, 1, 0, 0),
- F_END
-};
static struct rcg_clk pclk0_clk_src = {
.cmd_rcgr_reg = PCLK0_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_mdss_pclk0_1_clk,
- .current_freq = &rcg_dummy_freq,
+ .current_freq = &pixel_freq,
.base = &virt_bases[MMSS_BASE],
.c = {
.dbg_name = "pclk0_clk_src",
- .ops = &clk_ops_rcg_mnd,
+ .ops = &clk_ops_pixel,
VDD_DIG_FMAX_MAP2(LOW, 125000000, NOMINAL, 250000000),
CLK_INIT(pclk0_clk_src.c),
},
@@ -2922,13 +3049,11 @@
static struct rcg_clk pclk1_clk_src = {
.cmd_rcgr_reg = PCLK1_CMD_RCGR,
- .set_rate = set_rate_mnd,
- .freq_tbl = ftbl_mdss_pclk0_1_clk,
- .current_freq = &rcg_dummy_freq,
+ .current_freq = &pixel_freq,
.base = &virt_bases[MMSS_BASE],
.c = {
.dbg_name = "pclk1_clk_src",
- .ops = &clk_ops_rcg_mnd,
+ .ops = &clk_ops_pixel,
VDD_DIG_FMAX_MAP2(LOW, 125000000, NOMINAL, 250000000),
CLK_INIT(pclk1_clk_src.c),
},
@@ -3891,7 +4016,7 @@
static struct branch_clk oxili_gfx3d_clk = {
.cbcr_reg = OXILI_GFX3D_CBCR,
- .parent = &ocmemgx_gfx3d_clk.c,
+ .parent = &oxili_gfx3d_clk_src.c,
.base = &virt_bases[MMSS_BASE],
.c = {
.dbg_name = "oxili_gfx3d_clk",
@@ -4373,6 +4498,17 @@
},
};
+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 mss_xo_q6_clk = {
.cbcr_reg = MSS_XO_Q6_CBCR,
.bcr_reg = MSS_Q6SS_BCR,
@@ -4481,6 +4617,10 @@
{&gcc_blsp1_qup1_i2c_apps_clk.c, GCC_BASE, 0x008b},
{&gcc_blsp2_uart6_apps_clk.c, GCC_BASE, 0x00c3},
{&gcc_sdcc2_ahb_clk.c, GCC_BASE, 0x0071},
+ {&gcc_usb30_sleep_clk.c, GCC_BASE, 0x0051},
+ {&gcc_usb2a_phy_sleep_clk.c, GCC_BASE, 0x0063},
+ {&gcc_usb2b_phy_sleep_clk.c, GCC_BASE, 0x0064},
+ {&gcc_sys_noc_usb3_axi_clk.c, GCC_BASE, 0x0001},
{&gcc_ocmem_noc_cfg_ahb_clk.c, GCC_BASE, 0x0029},
{&gcc_ce1_clk.c, GCC_BASE, 0x0138},
{&gcc_lpass_q6_axi_clk.c, GCC_BASE, 0x0160},
@@ -4577,7 +4717,8 @@
{&q6ss_ahb_lfabif_clk.c, LPASS_BASE, 0x001e},
{&q6ss_ahbm_clk.c, LPASS_BASE, 0x001d},
{&audio_core_ixfabric_clk.c, LPASS_BASE, 0x0059},
- {&mss_bus_q6_clk.c, MSS_BASE, 0x003c},
+ {&audio_wrapper_br_clk.c, LPASS_BASE, 0x0022},
+ {&mss_bus_q6_clk.c, MSS_BASE, 0x003b},
{&mss_xo_q6_clk.c, MSS_BASE, 0x0007},
{&l2_m_clk, APCS_BASE, 0x0081},
@@ -4613,18 +4754,15 @@
clk->sample_ticks = 0x10000;
clk->multiplier = 1;
- writel_relaxed(0, MSS_REG_BASE(MSS_DEBUG_CLK_CTL_REG));
- writel_relaxed(0, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
- writel_relaxed(0, MMSS_REG_BASE(MMSS_DEBUG_CLK_CTL_REG));
- writel_relaxed(0, GCC_REG_BASE(GCC_DEBUG_CLK_CTL_REG));
-
switch (measure_mux[i].base) {
case GCC_BASE:
+ writel_relaxed(0, GCC_REG_BASE(GCC_DEBUG_CLK_CTL_REG));
clk_sel = measure_mux[i].debug_mux;
break;
case MMSS_BASE:
+ writel_relaxed(0, MMSS_REG_BASE(MMSS_DEBUG_CLK_CTL_REG));
clk_sel = 0x02C;
regval = BVAL(11, 0, measure_mux[i].debug_mux);
writel_relaxed(regval, MMSS_REG_BASE(MMSS_DEBUG_CLK_CTL_REG));
@@ -4635,6 +4773,7 @@
break;
case LPASS_BASE:
+ writel_relaxed(0, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
clk_sel = 0x161;
regval = BVAL(11, 0, measure_mux[i].debug_mux);
writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
@@ -4645,6 +4784,7 @@
break;
case MSS_BASE:
+ writel_relaxed(0, MSS_REG_BASE(MSS_DEBUG_CLK_CTL_REG));
clk_sel = 0x32;
regval = BVAL(5, 0, measure_mux[i].debug_mux);
writel_relaxed(regval, MSS_REG_BASE(MSS_DEBUG_CLK_CTL_REG));
@@ -4831,12 +4971,12 @@
CLK_LOOKUP("dma_bam_pclk", gcc_bam_dma_ahb_clk.c, "msm_sps"),
CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f991f000.serial"),
+ CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f9924000.i2c"),
CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f991e000.serial"),
- CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "spi_qsd.1"),
CLK_LOOKUP("core_clk", gcc_blsp1_qup1_i2c_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp1_qup1_spi_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_qup2_i2c_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp1_qup2_spi_apps_clk.c, "spi_qsd.1"),
+ CLK_LOOKUP("core_clk", gcc_blsp1_qup2_i2c_apps_clk.c, "f9924000.i2c"),
+ CLK_LOOKUP("core_clk", gcc_blsp1_qup2_spi_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp1_qup3_i2c_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp1_qup3_spi_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp1_qup4_i2c_apps_clk.c, ""),
@@ -4852,7 +4992,7 @@
CLK_LOOKUP("core_clk", gcc_blsp1_uart5_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp1_uart6_apps_clk.c, ""),
- CLK_LOOKUP("iface_clk", gcc_blsp2_ahb_clk.c, "f9966000.i2c"),
+ CLK_LOOKUP("iface_clk", gcc_blsp2_ahb_clk.c, "f9967000.i2c"),
CLK_LOOKUP("iface_clk", gcc_blsp2_ahb_clk.c, "f995e000.serial"),
CLK_LOOKUP("core_clk", gcc_blsp2_qup1_i2c_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp2_qup1_spi_apps_clk.c, ""),
@@ -4860,9 +5000,9 @@
CLK_LOOKUP("core_clk", gcc_blsp2_qup2_spi_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp2_qup3_i2c_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp2_qup3_spi_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp2_qup4_i2c_apps_clk.c, "f9966000.i2c"),
+ CLK_LOOKUP("core_clk", gcc_blsp2_qup4_i2c_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp2_qup4_spi_apps_clk.c, ""),
- CLK_LOOKUP("core_clk", gcc_blsp2_qup5_i2c_apps_clk.c, ""),
+ CLK_LOOKUP("core_clk", gcc_blsp2_qup5_i2c_apps_clk.c, "f9967000.i2c"),
CLK_LOOKUP("core_clk", gcc_blsp2_qup5_spi_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp2_qup6_i2c_apps_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_blsp2_qup6_spi_apps_clk.c, ""),
@@ -4914,8 +5054,14 @@
CLK_LOOKUP("iface_clk", gcc_tsif_ahb_clk.c, ""),
CLK_LOOKUP("ref_clk", gcc_tsif_ref_clk.c, ""),
+ CLK_LOOKUP("mem_clk", gcc_usb30_master_clk.c, "usb_bam"),
+ CLK_LOOKUP("mem_iface_clk", gcc_sys_noc_usb3_axi_clk.c, "usb_bam"),
CLK_LOOKUP("core_clk", gcc_usb30_master_clk.c, "msm_dwc3"),
CLK_LOOKUP("utmi_clk", gcc_usb30_mock_utmi_clk.c, "msm_dwc3"),
+ CLK_LOOKUP("iface_clk", gcc_sys_noc_usb3_axi_clk.c, "msm_dwc3"),
+ CLK_LOOKUP("sleep_clk", gcc_usb30_sleep_clk.c, "msm_dwc3"),
+ CLK_LOOKUP("sleep_a_clk", gcc_usb2a_phy_sleep_clk.c, "msm_dwc3"),
+ CLK_LOOKUP("sleep_b_clk", gcc_usb2b_phy_sleep_clk.c, "msm_dwc3"),
CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c, "msm_otg"),
CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c, "msm_otg"),
CLK_LOOKUP("iface_clk", gcc_usb_hsic_ahb_clk.c, "msm_hsic_host"),
@@ -4932,43 +5078,100 @@
CLK_LOOKUP("byte_clk", mdss_byte1_clk.c, ""),
CLK_LOOKUP("core_clk", mdss_esc0_clk.c, "fd922800.qcom,mdss_dsi"),
CLK_LOOKUP("core_clk", mdss_esc1_clk.c, ""),
+ CLK_LOOKUP("pixel_clk", mdss_pclk0_clk.c, "fd922800.qcom,mdss_dsi"),
+ CLK_LOOKUP("pixel_clk", mdss_pclk1_clk.c, ""),
CLK_LOOKUP("iface_clk", mdss_hdmi_ahb_clk.c, ""),
CLK_LOOKUP("core_clk", mdss_hdmi_clk.c, ""),
CLK_LOOKUP("core_clk", mdss_mdp_clk.c, "mdp.0"),
CLK_LOOKUP("lut_clk", mdss_mdp_lut_clk.c, "mdp.0"),
CLK_LOOKUP("core_clk_src", mdp_clk_src.c, "mdp.0"),
CLK_LOOKUP("vsync_clk", mdss_vsync_clk.c, "mdp.0"),
- CLK_LOOKUP("iface_clk", camss_cci_cci_ahb_clk.c, ""),
- CLK_LOOKUP("core_clk", camss_cci_cci_clk.c, ""),
- CLK_LOOKUP("iface_clk", camss_csi0_ahb_clk.c, ""),
- CLK_LOOKUP("camss_csi0_clk", camss_csi0_clk.c, ""),
- CLK_LOOKUP("camss_csi0phy_clk", camss_csi0phy_clk.c, ""),
- CLK_LOOKUP("camss_csi0pix_clk", camss_csi0pix_clk.c, ""),
- CLK_LOOKUP("camss_csi0rdi_clk", camss_csi0rdi_clk.c, ""),
- CLK_LOOKUP("iface_clk", camss_csi1_ahb_clk.c, ""),
- CLK_LOOKUP("camss_csi1_clk", camss_csi1_clk.c, ""),
- CLK_LOOKUP("camss_csi1phy_clk", camss_csi1phy_clk.c, ""),
- CLK_LOOKUP("camss_csi1pix_clk", camss_csi1pix_clk.c, ""),
- CLK_LOOKUP("camss_csi1rdi_clk", camss_csi1rdi_clk.c, ""),
- CLK_LOOKUP("iface_clk", camss_csi2_ahb_clk.c, ""),
- CLK_LOOKUP("camss_csi2_clk", camss_csi2_clk.c, ""),
- CLK_LOOKUP("camss_csi2phy_clk", camss_csi2phy_clk.c, ""),
- CLK_LOOKUP("camss_csi2pix_clk", camss_csi2pix_clk.c, ""),
- CLK_LOOKUP("camss_csi2rdi_clk", camss_csi2rdi_clk.c, ""),
- CLK_LOOKUP("iface_clk", camss_csi3_ahb_clk.c, ""),
- CLK_LOOKUP("camss_csi3_clk", camss_csi3_clk.c, ""),
- CLK_LOOKUP("camss_csi3phy_clk", camss_csi3phy_clk.c, ""),
- CLK_LOOKUP("camss_csi3pix_clk", camss_csi3pix_clk.c, ""),
- CLK_LOOKUP("camss_csi3rdi_clk", camss_csi3rdi_clk.c, ""),
- CLK_LOOKUP("camss_csi0_clk_src", csi0_clk_src.c, ""),
- CLK_LOOKUP("camss_csi1_clk_src", csi1_clk_src.c, ""),
- CLK_LOOKUP("camss_csi2_clk_src", csi2_clk_src.c, ""),
- CLK_LOOKUP("camss_csi3_clk_src", csi3_clk_src.c, ""),
- CLK_LOOKUP("camss_csi_vfe0_clk", camss_csi_vfe0_clk.c, ""),
- CLK_LOOKUP("camss_csi_vfe1_clk", camss_csi_vfe1_clk.c, ""),
- CLK_LOOKUP("core_clk", camss_gp0_clk.c, ""),
- CLK_LOOKUP("core_clk", camss_gp1_clk.c, ""),
- CLK_LOOKUP("iface_clk", camss_ispif_ahb_clk.c, ""),
+
+ /* MM sensor clocks */
+ CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6e.qcom,s5k3l1yx"),
+ CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6c.qcom,ov2720"),
+ CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6e.qcom,s5k3l1yx"),
+ CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6c.qcom,ov2720"),
+ CLK_LOOKUP("cam_clk", camss_mclk1_clk.c, ""),
+ CLK_LOOKUP("cam_clk", camss_mclk2_clk.c, ""),
+ CLK_LOOKUP("cam_clk", camss_mclk3_clk.c, ""),
+ CLK_LOOKUP("cam_gp0_src_clk", mmss_gp0_clk_src.c, ""),
+ CLK_LOOKUP("cam_gp1_src_clk", mmss_gp1_clk_src.c, ""),
+ CLK_LOOKUP("cam_gp0_clk", camss_gp0_clk.c, ""),
+ CLK_LOOKUP("cam_gp1_clk", camss_gp1_clk.c, ""),
+ /* CCI clocks */
+ CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+ "fda0c000.qcom,cci"),
+ CLK_LOOKUP("cci_ahb_clk", camss_cci_cci_ahb_clk.c, "fda0c000.qcom,cci"),
+ CLK_LOOKUP("cci_src_clk", cci_clk_src.c, "fda0c000.qcom,cci"),
+ CLK_LOOKUP("cci_clk", camss_cci_cci_clk.c, "fda0c000.qcom,cci"),
+ /* CSIPHY clocks */
+ CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
+ "fda0ac00.qcom,csiphy"),
+ CLK_LOOKUP("csiphy_timer_src_clk", csi0phytimer_clk_src.c,
+ "fda0ac00.qcom,csiphy"),
+ CLK_LOOKUP("csiphy_timer_clk", camss_phy0_csi0phytimer_clk.c,
+ "fda0ac00.qcom,csiphy"),
+ CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
+ "fda0b000.qcom,csiphy"),
+ CLK_LOOKUP("csiphy_timer_src_clk", csi1phytimer_clk_src.c,
+ "fda0b000.qcom,csiphy"),
+ CLK_LOOKUP("csiphy_timer_clk", camss_phy1_csi1phytimer_clk.c,
+ "fda0b000.qcom,csiphy"),
+ CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
+ "fda0b400.qcom,csiphy"),
+ CLK_LOOKUP("csiphy_timer_src_clk", csi2phytimer_clk_src.c,
+ "fda0b400.qcom,csiphy"),
+ CLK_LOOKUP("csiphy_timer_clk", camss_phy2_csi2phytimer_clk.c,
+ "fda0b400.qcom,csiphy"),
+ /* CSID clocks */
+ CLK_LOOKUP("csi_ahb_clk", camss_csi0_ahb_clk.c, "fda08000.qcom,csid"),
+ CLK_LOOKUP("csi_src_clk", csi0_clk_src.c, "fda08000.qcom,csid"),
+ CLK_LOOKUP("csi_phy_clk", camss_csi0phy_clk.c, "fda08000.qcom,csid"),
+ CLK_LOOKUP("csi_clk", camss_csi0_clk.c, "fda08000.qcom,csid"),
+ CLK_LOOKUP("csi_pix_clk", camss_csi0pix_clk.c, "fda08000.qcom,csid"),
+ CLK_LOOKUP("csi_rdi_clk", camss_csi0rdi_clk.c, "fda08000.qcom,csid"),
+ CLK_LOOKUP("csi_ahb_clk", camss_csi1_ahb_clk.c, "fda08400.qcom,csid"),
+ CLK_LOOKUP("csi_src_clk", csi1_clk_src.c, "fda08400.qcom,csid"),
+ CLK_LOOKUP("csi_phy_clk", camss_csi1phy_clk.c, "fda08400.qcom,csid"),
+ CLK_LOOKUP("csi_clk", camss_csi1_clk.c, "fda08400.qcom,csid"),
+ CLK_LOOKUP("csi_pix_clk", camss_csi1pix_clk.c, "fda08400.qcom,csid"),
+ CLK_LOOKUP("csi_rdi_clk", camss_csi1rdi_clk.c, "fda08400.qcom,csid"),
+ CLK_LOOKUP("csi_ahb_clk", camss_csi2_ahb_clk.c, "fda08800.qcom,csid"),
+ CLK_LOOKUP("csi_src_clk", csi2_clk_src.c, "fda08800.qcom,csid"),
+ CLK_LOOKUP("csi_phy_clk", camss_csi2phy_clk.c, "fda08800.qcom,csid"),
+ CLK_LOOKUP("csi_clk", camss_csi2_clk.c, "fda08800.qcom,csid"),
+ CLK_LOOKUP("csi_pix_clk", camss_csi2pix_clk.c, "fda08800.qcom,csid"),
+ CLK_LOOKUP("csi_rdi_clk", camss_csi2rdi_clk.c, "fda08800.qcom,csid"),
+ CLK_LOOKUP("csi_ahb_clk", camss_csi3_ahb_clk.c, "fda08c00.qcom,csid"),
+ CLK_LOOKUP("csi_src_clk", csi3_clk_src.c, "fda08c00.qcom,csid"),
+ CLK_LOOKUP("csi_phy_clk", camss_csi3phy_clk.c, "fda08c00.qcom,csid"),
+ CLK_LOOKUP("csi_clk", camss_csi3_clk.c, "fda08c00.qcom,csid"),
+ CLK_LOOKUP("csi_pix_clk", camss_csi3pix_clk.c, "fda08c00.qcom,csid"),
+ CLK_LOOKUP("csi_rdi_clk", camss_csi3rdi_clk.c, "fda08c00.qcom,csid"),
+ /*VFE clocks*/
+ CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+ "fda10000.qcom,vfe"),
+ CLK_LOOKUP("vfe_clk_src", vfe0_clk_src.c, "fda10000.qcom,vfe"),
+ CLK_LOOKUP("camss_vfe_vfe_clk", camss_vfe_vfe0_clk.c,
+ "fda10000.qcom,vfe"),
+ CLK_LOOKUP("camss_csi_vfe_clk", camss_csi_vfe0_clk.c,
+ "fda10000.qcom,vfe"),
+ CLK_LOOKUP("iface_clk", camss_vfe_vfe_ahb_clk.c, "fda10000.qcom,vfe"),
+ CLK_LOOKUP("bus_clk", camss_vfe_vfe_axi_clk.c, "fda10000.qcom,vfe"),
+ CLK_LOOKUP("alt_bus_clk", camss_vfe_vfe_ocmemnoc_clk.c,
+ "fda10000.qcom,vfe"),
+ CLK_LOOKUP("camss_top_ahb_clk", camss_top_ahb_clk.c,
+ "fda14000.qcom,vfe"),
+ CLK_LOOKUP("vfe_clk_src", vfe1_clk_src.c, "fda14000.qcom,vfe"),
+ CLK_LOOKUP("camss_vfe_vfe_clk", camss_vfe_vfe1_clk.c,
+ "fda14000.qcom,vfe"),
+ CLK_LOOKUP("camss_csi_vfe_clk", camss_csi_vfe1_clk.c,
+ "fda14000.qcom,vfe"),
+ CLK_LOOKUP("iface_clk", camss_vfe_vfe_ahb_clk.c, "fda14000.qcom,vfe"),
+ CLK_LOOKUP("bus_clk", camss_vfe_vfe_axi_clk.c, "fda14000.qcom,vfe"),
+ CLK_LOOKUP("alt_bus_clk", camss_vfe_vfe_ocmemnoc_clk.c,
+ "fda14000.qcom,vfe"),
CLK_LOOKUP("core_clk", camss_jpeg_jpeg0_clk.c, ""),
CLK_LOOKUP("core_clk", camss_jpeg_jpeg1_clk.c, ""),
CLK_LOOKUP("core_clk", camss_jpeg_jpeg2_clk.c, ""),
@@ -4978,25 +5181,12 @@
"fda64000.qcom,iommu"),
CLK_LOOKUP("bus_clk", camss_jpeg_jpeg_axi_clk.c, ""),
CLK_LOOKUP("bus_clk", camss_jpeg_jpeg_ocmemnoc_clk.c, ""),
- CLK_LOOKUP("core_clk", camss_mclk0_clk.c, ""),
- CLK_LOOKUP("core_clk", camss_mclk1_clk.c, ""),
- CLK_LOOKUP("core_clk", camss_mclk2_clk.c, ""),
- CLK_LOOKUP("core_clk", camss_mclk3_clk.c, ""),
CLK_LOOKUP("iface_clk", camss_micro_ahb_clk.c, ""),
- CLK_LOOKUP("core_clk", camss_phy0_csi0phytimer_clk.c, ""),
- CLK_LOOKUP("core_clk", camss_phy1_csi1phytimer_clk.c, ""),
- CLK_LOOKUP("core_clk", camss_phy2_csi2phytimer_clk.c, ""),
CLK_LOOKUP("iface_clk", camss_top_ahb_clk.c, ""),
CLK_LOOKUP("iface_clk", camss_vfe_cpp_ahb_clk.c, "fda44000.qcom,iommu"),
CLK_LOOKUP("core_clk", camss_vfe_cpp_clk.c, "fda44000.qcom,iommu"),
- CLK_LOOKUP("camss_vfe_vfe0_clk", camss_vfe_vfe0_clk.c, ""),
- CLK_LOOKUP("camss_vfe_vfe1_clk", camss_vfe_vfe1_clk.c, ""),
- CLK_LOOKUP("vfe0_clk_src", vfe0_clk_src.c, ""),
- CLK_LOOKUP("vfe1_clk_src", vfe1_clk_src.c, ""),
- CLK_LOOKUP("iface_clk", camss_vfe_vfe_ahb_clk.c, ""),
- CLK_LOOKUP("bus_clk", camss_vfe_vfe_axi_clk.c, ""),
- CLK_LOOKUP("bus_clk", camss_vfe_vfe_ocmemnoc_clk.c, ""),
CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "mdp.0"),
+ CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "mdss_dsi_clk_ctrl"),
CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "fd928000.qcom,iommu"),
CLK_LOOKUP("core_clk", mdss_axi_clk.c, "fd928000.qcom,iommu"),
CLK_LOOKUP("bus_clk", mdss_axi_clk.c, "mdp.0"),
@@ -5062,7 +5252,7 @@
"msm-dai-q6.4106"),
CLK_LOOKUP("core_oe_clk", audio_core_lpaif_pcmoe_clk.c,
"msm-dai-q6.4106"),
-
+ CLK_LOOKUP("br_clk", audio_wrapper_br_clk.c, "fdd00000.qcom,ocmem"),
CLK_LOOKUP("core_clk", mss_xo_q6_clk.c, "pil-q6v5-mss"),
CLK_LOOKUP("bus_clk", gcc_mss_q6_bimc_axi_clk.c, "pil-q6v5-mss"),
CLK_LOOKUP("iface_clk", gcc_mss_cfg_ahb_clk.c, "pil-q6v5-mss"),
@@ -5375,6 +5565,19 @@
WARN(ret, "LPASS Audio Core GDSC did not power on.\n");
}
+static void __init mdss_clock_setup(void)
+{
+ clk_ops_byte = clk_ops_rcg_mnd;
+ clk_ops_byte.set_rate = set_rate_byte;
+ clk_ops_dsi_byte_pll.get_parent = dsi_pll_clk_get_parent;
+
+ clk_ops_pixel = clk_ops_rcg;
+ clk_ops_pixel.set_rate = set_rate_pixel;
+ clk_ops_dsi_pixel_pll.get_parent = dsi_pll_clk_get_parent;
+
+ mdss_clk_ctrl_init();
+}
+
static void __init msm8974_clock_post_init(void)
{
clk_set_rate(&axi_clk_src.c, 282000000);
@@ -5405,6 +5608,8 @@
clk_prepare_enable(&gcc_mmss_noc_cfg_ahb_clk.c);
clk_prepare_enable(&gcc_ocmem_noc_cfg_ahb_clk.c);
+ mdss_clock_setup();
+
/* Set rates for single-rate clocks. */
clk_set_rate(&usb30_master_clk_src.c,
usb30_master_clk_src.freq_tbl[0].freq_hz);
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index d5ee35b..42b36f6 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -110,20 +110,26 @@
void set_rate_hid(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
{
u32 cfg_regval;
+ unsigned long flags;
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg));
cfg_regval &= ~(CFG_RCGR_DIV_MASK | CFG_RCGR_SRC_SEL_MASK);
cfg_regval |= nf->div_src_val;
writel_relaxed(cfg_regval, CFG_RCGR_REG(rcg));
rcg_update_config(rcg);
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
/* RCG set rate function for clocks with MND & Half Integer Dividers. */
void set_rate_mnd(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
{
u32 cfg_regval;
+ unsigned long flags;
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+ cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg));
writel_relaxed(nf->m_val, M_REG(rcg));
writel_relaxed(nf->n_val, N_REG(rcg));
writel_relaxed(nf->d_val, D_REG(rcg));
@@ -139,6 +145,7 @@
writel_relaxed(cfg_regval, CFG_RCGR_REG(rcg));
rcg_update_config(rcg);
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
static int rcg_clk_enable(struct clk *c)
@@ -157,7 +164,6 @@
struct clk_freq_tbl *cf, *nf;
struct rcg_clk *rcg = to_rcg_clk(c);
int rc = 0;
- unsigned long flags;
for (nf = rcg->freq_tbl; nf->freq_hz != FREQ_END
&& nf->freq_hz != rate; nf++)
@@ -178,13 +184,9 @@
BUG_ON(!rcg->set_rate);
- spin_lock_irqsave(&local_clock_reg_lock, flags);
-
/* Perform clock-specific frequency switch operations. */
rcg->set_rate(rcg, nf);
- spin_unlock_irqrestore(&local_clock_reg_lock, flags);
-
/* Release source requirements of the old freq. */
if (rcg->c.count)
clk_disable(cf->src_clk);
diff --git a/arch/arm/mach-msm/clock-local2.h b/arch/arm/mach-msm/clock-local2.h
index 572cec6f..46e9e0c 100644
--- a/arch/arm/mach-msm/clock-local2.h
+++ b/arch/arm/mach-msm/clock-local2.h
@@ -36,7 +36,7 @@
const u32 m_val;
const u32 n_val;
const u32 d_val;
- const u32 div_src_val;
+ u32 div_src_val;
const unsigned sys_vdd;
};
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
new file mode 100644
index 0000000..e8aa790
--- /dev/null
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -0,0 +1,225 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/iopoll.h>
+#include <linux/clk.h>
+
+#include <asm/processor.h>
+#include <mach/msm_iomap.h>
+
+#include "clock.h"
+#include "clock-mdss-8974.h"
+
+#define MDSS_DSI_PHY_BASE_ADR 0xFD922800
+#define DSI_REG_SIZE 2048
+
+#define VCO_CLK 424000000
+static unsigned char *mdss_dsi_base;
+static int pll_byte_clk_rate;
+static int pll_pclk_rate;
+static int pll_initialized;
+static struct clk *mdss_dsi_ahb_clk;
+
+void __init mdss_clk_ctrl_init(void)
+{
+ mdss_dsi_base = ioremap(MDSS_DSI_PHY_BASE_ADR,
+ DSI_REG_SIZE);
+ if (!mdss_dsi_base)
+ pr_err("%s:%d unable to remap dsi base",
+ __func__, __LINE__);
+
+ mdss_dsi_ahb_clk = clk_get_sys("mdss_dsi_clk_ctrl", "iface_clk");
+ if (!IS_ERR(mdss_dsi_ahb_clk)) {
+ clk_prepare(mdss_dsi_ahb_clk);
+ } else {
+ mdss_dsi_ahb_clk = NULL;
+ pr_err("%s:%d unable to get iface clock\n",
+ __func__, __LINE__);
+ }
+}
+
+static long mdss_dsi_pll_byte_round_rate(struct clk *c, unsigned long rate)
+{
+ if (pll_initialized)
+ return pll_byte_clk_rate;
+ else {
+ pr_err("%s: DSI PLL not configured\n",
+ __func__);
+ return -EINVAL;
+ }
+}
+
+static long mdss_dsi_pll_pixel_round_rate(struct clk *c, unsigned long rate)
+{
+ if (pll_initialized)
+ return pll_pclk_rate;
+ else {
+ pr_err("%s: Configure Byte clk first\n",
+ __func__);
+ return -EINVAL;
+ }
+}
+
+static int mdss_dsi_pll_pixel_set_rate(struct clk *c, unsigned long rate)
+{
+ if (pll_initialized)
+ return 0;
+ else {
+ pr_err("%s: Configure Byte clk first\n",
+ __func__);
+ return -EINVAL;
+ }
+}
+
+static int mdss_dsi_pll_byte_set_rate(struct clk *c, unsigned long rate)
+{
+ int pll_divcfg1, pll_divcfg2;
+ int half_bitclk_rate;
+
+ if (pll_initialized)
+ return 0;
+
+ if (!mdss_dsi_ahb_clk) {
+ pr_err("%s: mdss_dsi_ahb_clk not initialized\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ clk_enable(mdss_dsi_ahb_clk);
+
+ half_bitclk_rate = rate * 4;
+
+ pll_divcfg1 = (VCO_CLK / half_bitclk_rate) - 2;
+
+ /* Configuring the VCO to 424 Mhz */
+ /* Configuring the half rate Bit clk to 212 Mhz */
+
+ pll_divcfg2 = 3; /* ByteClk is 1/4 the half-bitClk rate */
+
+ /* Configure the Loop filter */
+ /* Loop filter resistance value */
+ writel_relaxed(0x08, mdss_dsi_base + 0x022c);
+ /* Loop filter capacitance values : c1 and c2 */
+ writel_relaxed(0x70, mdss_dsi_base + 0x0230);
+ writel_relaxed(0x15, mdss_dsi_base + 0x0234);
+
+ writel_relaxed(0x02, mdss_dsi_base + 0x0208); /* ChgPump */
+ writel_relaxed(pll_divcfg1, mdss_dsi_base + 0x0204); /* postDiv1 */
+ writel_relaxed(pll_divcfg2, mdss_dsi_base + 0x0224); /* postDiv2 */
+ writel_relaxed(0x03, mdss_dsi_base + 0x0228); /* postDiv3 */
+
+ writel_relaxed(0x2b, mdss_dsi_base + 0x0278); /* Cal CFG3 */
+ writel_relaxed(0x06, mdss_dsi_base + 0x027c); /* Cal CFG4 */
+ writel_relaxed(0x05, mdss_dsi_base + 0x0264); /* Cal CFG4 */
+
+ writel_relaxed(0x0a, mdss_dsi_base + 0x023c); /* SDM CFG1 */
+ writel_relaxed(0xab, mdss_dsi_base + 0x0240); /* SDM CFG2 */
+ writel_relaxed(0x0a, mdss_dsi_base + 0x0244); /* SDM CFG3 */
+ writel_relaxed(0x00, mdss_dsi_base + 0x0248); /* SDM CFG4 */
+
+ udelay(10);
+
+ writel_relaxed(0x01, mdss_dsi_base + 0x0200); /* REFCLK CFG */
+ writel_relaxed(0x00, mdss_dsi_base + 0x0214); /* PWRGEN CFG */
+ writel_relaxed(0x01, mdss_dsi_base + 0x020c); /* VCOLPF CFG */
+ writel_relaxed(0x02, mdss_dsi_base + 0x0210); /* VREG CFG */
+ writel_relaxed(0x00, mdss_dsi_base + 0x0238); /* SDM CFG0 */
+
+ writel_relaxed(0x5f, mdss_dsi_base + 0x028c); /* CAL CFG8 */
+ writel_relaxed(0xa8, mdss_dsi_base + 0x0294); /* CAL CFG10 */
+ writel_relaxed(0x01, mdss_dsi_base + 0x0298); /* CAL CFG11 */
+ writel_relaxed(0x0a, mdss_dsi_base + 0x026c); /* CAL CFG0 */
+ writel_relaxed(0x30, mdss_dsi_base + 0x0284); /* CAL CFG6 */
+ writel_relaxed(0x00, mdss_dsi_base + 0x0288); /* CAL CFG7 */
+ writel_relaxed(0x00, mdss_dsi_base + 0x0290); /* CAL CFG9 */
+ writel_relaxed(0x20, mdss_dsi_base + 0x029c); /* EFUSE CFG */
+
+ pll_byte_clk_rate = 53000000;
+ pll_pclk_rate = 105000000;
+
+ clk_disable(mdss_dsi_ahb_clk);
+ pll_initialized = 1;
+
+ return 0;
+}
+
+static int mdss_dsi_pll_enable(struct clk *c)
+{
+ u32 status;
+ u32 max_reads, timeout_us;
+ static int pll_enabled;
+
+ if (pll_enabled)
+ return 0;
+
+ if (!mdss_dsi_ahb_clk) {
+ pr_err("%s: mdss_dsi_ahb_clk not initialized\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ clk_enable(mdss_dsi_ahb_clk);
+ /* PLL power up */
+ writel_relaxed(0x01, mdss_dsi_base + 0x0220); /* GLB CFG */
+ writel_relaxed(0x05, mdss_dsi_base + 0x0220); /* GLB CFG */
+ udelay(20);
+ writel_relaxed(0x07, mdss_dsi_base + 0x0220); /* GLB CFG */
+ udelay(20);
+ writel_relaxed(0x0f, mdss_dsi_base + 0x0220); /* GLB CFG */
+
+ /* poll for PLL ready status */
+ max_reads = 20;
+ timeout_us = 100;
+ if (readl_poll_timeout_noirq((mdss_dsi_base + 0x02c0),
+ status,
+ ((status & 0x01) == 1),
+ max_reads, timeout_us)) {
+ pr_err("%s: DSI PLL status=%x failed to Lock\n",
+ __func__, status);
+ clk_disable(mdss_dsi_ahb_clk);
+ return -EINVAL;
+ }
+ clk_disable(mdss_dsi_ahb_clk);
+ pll_enabled = 1;
+
+ return 0;
+}
+
+static void mdss_dsi_pll_disable(struct clk *c)
+{
+ if (!mdss_dsi_ahb_clk)
+ pr_err("%s: mdss_dsi_ahb_clk not initialized\n",
+ __func__);
+
+ clk_enable(mdss_dsi_ahb_clk);
+ writel_relaxed(0x00, mdss_dsi_base + 0x0220); /* GLB CFG */
+ clk_disable(mdss_dsi_ahb_clk);
+}
+
+struct clk_ops clk_ops_dsi_pixel_pll = {
+ .enable = mdss_dsi_pll_enable,
+ .disable = mdss_dsi_pll_disable,
+ .set_rate = mdss_dsi_pll_pixel_set_rate,
+ .round_rate = mdss_dsi_pll_pixel_round_rate,
+};
+
+struct clk_ops clk_ops_dsi_byte_pll = {
+ .enable = mdss_dsi_pll_enable,
+ .disable = mdss_dsi_pll_disable,
+ .set_rate = mdss_dsi_pll_byte_set_rate,
+ .round_rate = mdss_dsi_pll_byte_round_rate,
+};
diff --git a/arch/arm/mach-msm/clock-mdss-8974.h b/arch/arm/mach-msm/clock-mdss-8974.h
new file mode 100644
index 0000000..aaf72d2
--- /dev/null
+++ b/arch/arm/mach-msm/clock-mdss-8974.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_CLOCK_MDSS_8974
+#define __ARCH_ARM_MACH_MSM_CLOCK_MDSS_8974
+
+void mdss_clk_ctrl_init(void);
+extern struct clk_ops clk_ops_dsi_byte_pll;
+extern struct clk_ops clk_ops_dsi_pixel_pll;
+
+#endif
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index be69827..149a0511 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -64,7 +64,8 @@
if (!r->branch) {
r->last_set_khz = iv.value;
- r->last_set_sleep_khz = iv.value;
+ if (!r->active_only)
+ r->last_set_sleep_khz = iv.value;
r->c.rate = iv.value * r->factor;
}
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index d88466d..4e3d83b 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -169,6 +169,7 @@
extern struct clock_init_data qds8x50_clock_init_data;
extern struct clock_init_data msm8625_dummy_clock_init_data;
extern struct clock_init_data msm8930_clock_init_data;
+extern struct clock_init_data msm8930_pm8917_clock_init_data;
extern struct clock_init_data msm8974_clock_init_data;
extern struct clock_init_data msm8974_rumi_clock_init_data;
diff --git a/arch/arm/mach-msm/cpuidle.c b/arch/arm/mach-msm/cpuidle.c
index de97186..a3a1574 100644
--- a/arch/arm/mach-msm/cpuidle.c
+++ b/arch/arm/mach-msm/cpuidle.c
@@ -76,8 +76,6 @@
enum msm_pm_sleep_mode pm_mode;
struct cpuidle_state_usage *st_usage = NULL;
- local_irq_disable();
-
#ifdef CONFIG_CPU_PM
cpu_pm_enter();
#endif
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index c6a0441..3b262bc 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -2848,26 +2848,6 @@
struct msm_iommu_domain_name apq8064_iommu_ctx_names[] = {
/* Camera */
{
- .name = "vpe_src",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vpe_dst",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_imgwr",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_misc",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
.name = "ijpeg_src",
.domain = CAMERA_DOMAIN,
},
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index eac2140..867e8fc 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -32,6 +32,7 @@
#include "rpm_stats.h"
#include "rpm_rbcpr_stats.h"
#include "footswitch.h"
+#include "acpuclock-krait.h"
#ifdef CONFIG_MSM_MPM
#include <mach/mpm.h>
@@ -228,13 +229,13 @@
MSM_RPM_STATUS_ID_MAP(8930, PM8038_CLK2_1),
MSM_RPM_STATUS_ID_MAP(8930, PM8038_LVS1),
MSM_RPM_STATUS_ID_MAP(8930, PM8038_LVS2),
- MSM_RPM_STATUS_ID_MAP(8930, NCP_0),
- MSM_RPM_STATUS_ID_MAP(8930, NCP_1),
- MSM_RPM_STATUS_ID_MAP(8930, CXO_BUFFERS),
- MSM_RPM_STATUS_ID_MAP(8930, USB_OTG_SWITCH),
- MSM_RPM_STATUS_ID_MAP(8930, HDMI_SWITCH),
- MSM_RPM_STATUS_ID_MAP(8930, QDSS_CLK),
- MSM_RPM_STATUS_ID_MAP(8930, VOLTAGE_CORNER),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8038_NCP_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8038_NCP_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8038_CXO_BUFFERS),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8038_USB_OTG_SWITCH),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8038_HDMI_SWITCH),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8038_QDSS_CLK),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8038_VOLTAGE_CORNER),
},
.target_ctrl_id = {
MSM_RPM_CTRL_MAP(8930, VERSION_MAJOR),
@@ -251,6 +252,259 @@
.ver = {3, 0, 0},
};
+struct msm_rpm_platform_data msm8930_rpm_data_pm8917 __initdata = {
+ .reg_base_addrs = {
+ [MSM_RPM_PAGE_STATUS] = MSM_RPM_BASE,
+ [MSM_RPM_PAGE_CTRL] = MSM_RPM_BASE + 0x400,
+ [MSM_RPM_PAGE_REQ] = MSM_RPM_BASE + 0x600,
+ [MSM_RPM_PAGE_ACK] = MSM_RPM_BASE + 0xa00,
+ },
+ .irq_ack = RPM_APCC_CPU0_GP_HIGH_IRQ,
+ .irq_err = RPM_APCC_CPU0_GP_LOW_IRQ,
+ .irq_wakeup = RPM_APCC_CPU0_WAKE_UP_IRQ,
+ .ipc_rpm_reg = MSM_APCS_GCC_BASE + 0x008,
+ .ipc_rpm_val = 4,
+ .target_id = {
+ MSM_RPM_MAP(8930, NOTIFICATION_CONFIGURED_0, NOTIFICATION, 4),
+ MSM_RPM_MAP(8930, NOTIFICATION_REGISTERED_0, NOTIFICATION, 4),
+ MSM_RPM_MAP(8930, INVALIDATE_0, INVALIDATE, 8),
+ MSM_RPM_MAP(8960, TRIGGER_TIMED_TO, TRIGGER_TIMED, 1),
+ MSM_RPM_MAP(8960, TRIGGER_TIMED_SCLK_COUNT, TRIGGER_TIMED, 1),
+ MSM_RPM_MAP(8930, RPM_CTL, RPM_CTL, 1),
+ MSM_RPM_MAP(8930, CXO_CLK, CXO_CLK, 1),
+ MSM_RPM_MAP(8930, PXO_CLK, PXO_CLK, 1),
+ MSM_RPM_MAP(8930, APPS_FABRIC_CLK, APPS_FABRIC_CLK, 1),
+ MSM_RPM_MAP(8930, SYSTEM_FABRIC_CLK, SYSTEM_FABRIC_CLK, 1),
+ MSM_RPM_MAP(8930, MM_FABRIC_CLK, MM_FABRIC_CLK, 1),
+ MSM_RPM_MAP(8930, DAYTONA_FABRIC_CLK, DAYTONA_FABRIC_CLK, 1),
+ MSM_RPM_MAP(8930, SFPB_CLK, SFPB_CLK, 1),
+ MSM_RPM_MAP(8930, CFPB_CLK, CFPB_CLK, 1),
+ MSM_RPM_MAP(8930, MMFPB_CLK, MMFPB_CLK, 1),
+ MSM_RPM_MAP(8930, EBI1_CLK, EBI1_CLK, 1),
+ MSM_RPM_MAP(8930, APPS_FABRIC_CFG_HALT_0,
+ APPS_FABRIC_CFG_HALT, 2),
+ MSM_RPM_MAP(8930, APPS_FABRIC_CFG_CLKMOD_0,
+ APPS_FABRIC_CFG_CLKMOD, 3),
+ MSM_RPM_MAP(8930, APPS_FABRIC_CFG_IOCTL,
+ APPS_FABRIC_CFG_IOCTL, 1),
+ MSM_RPM_MAP(8930, APPS_FABRIC_ARB_0, APPS_FABRIC_ARB, 6),
+ MSM_RPM_MAP(8930, SYS_FABRIC_CFG_HALT_0,
+ SYS_FABRIC_CFG_HALT, 2),
+ MSM_RPM_MAP(8930, SYS_FABRIC_CFG_CLKMOD_0,
+ SYS_FABRIC_CFG_CLKMOD, 3),
+ MSM_RPM_MAP(8930, SYS_FABRIC_CFG_IOCTL,
+ SYS_FABRIC_CFG_IOCTL, 1),
+ MSM_RPM_MAP(8930, SYSTEM_FABRIC_ARB_0,
+ SYSTEM_FABRIC_ARB, 20),
+ MSM_RPM_MAP(8930, MMSS_FABRIC_CFG_HALT_0,
+ MMSS_FABRIC_CFG_HALT, 2),
+ MSM_RPM_MAP(8930, MMSS_FABRIC_CFG_CLKMOD_0,
+ MMSS_FABRIC_CFG_CLKMOD, 3),
+ MSM_RPM_MAP(8930, MMSS_FABRIC_CFG_IOCTL,
+ MMSS_FABRIC_CFG_IOCTL, 1),
+ MSM_RPM_MAP(8930, MM_FABRIC_ARB_0, MM_FABRIC_ARB, 11),
+ MSM_RPM_MAP(8930, PM8917_S1_0, PM8917_S1, 2),
+ MSM_RPM_MAP(8930, PM8917_S2_0, PM8917_S2, 2),
+ MSM_RPM_MAP(8930, PM8917_S3_0, PM8917_S3, 2),
+ MSM_RPM_MAP(8930, PM8917_S4_0, PM8917_S4, 2),
+ MSM_RPM_MAP(8930, PM8917_S5_0, PM8917_S5, 2),
+ MSM_RPM_MAP(8930, PM8917_S6_0, PM8917_S6, 2),
+ MSM_RPM_MAP(8930, PM8917_S7_0, PM8917_S7, 2),
+ MSM_RPM_MAP(8930, PM8917_S8_0, PM8917_S8, 2),
+ MSM_RPM_MAP(8930, PM8917_L1_0, PM8917_L1, 2),
+ MSM_RPM_MAP(8930, PM8917_L2_0, PM8917_L2, 2),
+ MSM_RPM_MAP(8930, PM8917_L3_0, PM8917_L3, 2),
+ MSM_RPM_MAP(8930, PM8917_L4_0, PM8917_L4, 2),
+ MSM_RPM_MAP(8930, PM8917_L5_0, PM8917_L5, 2),
+ MSM_RPM_MAP(8930, PM8917_L6_0, PM8917_L6, 2),
+ MSM_RPM_MAP(8930, PM8917_L7_0, PM8917_L7, 2),
+ MSM_RPM_MAP(8930, PM8917_L8_0, PM8917_L8, 2),
+ MSM_RPM_MAP(8930, PM8917_L9_0, PM8917_L9, 2),
+ MSM_RPM_MAP(8930, PM8917_L10_0, PM8917_L10, 2),
+ MSM_RPM_MAP(8930, PM8917_L11_0, PM8917_L11, 2),
+ MSM_RPM_MAP(8930, PM8917_L12_0, PM8917_L12, 2),
+ MSM_RPM_MAP(8930, PM8917_L14_0, PM8917_L14, 2),
+ MSM_RPM_MAP(8930, PM8917_L15_0, PM8917_L15, 2),
+ MSM_RPM_MAP(8930, PM8917_L16_0, PM8917_L16, 2),
+ MSM_RPM_MAP(8930, PM8917_L17_0, PM8917_L17, 2),
+ MSM_RPM_MAP(8930, PM8917_L18_0, PM8917_L18, 2),
+ MSM_RPM_MAP(8930, PM8917_L21_0, PM8917_L21, 2),
+ MSM_RPM_MAP(8930, PM8917_L22_0, PM8917_L22, 2),
+ MSM_RPM_MAP(8930, PM8917_L23_0, PM8917_L23, 2),
+ MSM_RPM_MAP(8930, PM8917_L24_0, PM8917_L24, 2),
+ MSM_RPM_MAP(8930, PM8917_L25_0, PM8917_L25, 2),
+ MSM_RPM_MAP(8930, PM8917_L26_0, PM8917_L26, 2),
+ MSM_RPM_MAP(8930, PM8917_L27_0, PM8917_L27, 2),
+ MSM_RPM_MAP(8930, PM8917_L28_0, PM8917_L28, 2),
+ MSM_RPM_MAP(8930, PM8917_L29_0, PM8917_L29, 2),
+ MSM_RPM_MAP(8930, PM8917_L30_0, PM8917_L30, 2),
+ MSM_RPM_MAP(8930, PM8917_L31_0, PM8917_L31, 2),
+ MSM_RPM_MAP(8930, PM8917_L32_0, PM8917_L32, 2),
+ MSM_RPM_MAP(8930, PM8917_L33_0, PM8917_L33, 2),
+ MSM_RPM_MAP(8930, PM8917_L34_0, PM8917_L34, 2),
+ MSM_RPM_MAP(8930, PM8917_L35_0, PM8917_L35, 2),
+ MSM_RPM_MAP(8930, PM8917_L36_0, PM8917_L36, 2),
+ MSM_RPM_MAP(8930, PM8917_CLK1_0, PM8917_CLK1, 2),
+ MSM_RPM_MAP(8930, PM8917_CLK2_0, PM8917_CLK2, 2),
+ MSM_RPM_MAP(8930, PM8917_LVS1, PM8917_LVS1, 1),
+ MSM_RPM_MAP(8930, PM8917_LVS3, PM8917_LVS3, 1),
+ MSM_RPM_MAP(8930, PM8917_LVS4, PM8917_LVS4, 1),
+ MSM_RPM_MAP(8930, PM8917_LVS5, PM8917_LVS5, 1),
+ MSM_RPM_MAP(8930, PM8917_LVS6, PM8917_LVS6, 1),
+ MSM_RPM_MAP(8930, PM8917_LVS7, PM8917_LVS7, 1),
+ MSM_RPM_MAP(8930, NCP_0, NCP, 2),
+ MSM_RPM_MAP(8930, CXO_BUFFERS, CXO_BUFFERS, 1),
+ MSM_RPM_MAP(8930, USB_OTG_SWITCH, USB_OTG_SWITCH, 1),
+ MSM_RPM_MAP(8930, HDMI_SWITCH, HDMI_SWITCH, 1),
+ MSM_RPM_MAP(8930, QDSS_CLK, QDSS_CLK, 1),
+ MSM_RPM_MAP(8930, VOLTAGE_CORNER, VOLTAGE_CORNER, 1),
+ },
+ .target_status = {
+ MSM_RPM_STATUS_ID_MAP(8930, VERSION_MAJOR),
+ MSM_RPM_STATUS_ID_MAP(8930, VERSION_MINOR),
+ MSM_RPM_STATUS_ID_MAP(8930, VERSION_BUILD),
+ MSM_RPM_STATUS_ID_MAP(8930, SUPPORTED_RESOURCES_0),
+ MSM_RPM_STATUS_ID_MAP(8930, SUPPORTED_RESOURCES_1),
+ MSM_RPM_STATUS_ID_MAP(8930, SUPPORTED_RESOURCES_2),
+ MSM_RPM_STATUS_ID_MAP(8930, RESERVED_SUPPORTED_RESOURCES_0),
+ MSM_RPM_STATUS_ID_MAP(8930, SEQUENCE),
+ MSM_RPM_STATUS_ID_MAP(8930, RPM_CTL),
+ MSM_RPM_STATUS_ID_MAP(8930, CXO_CLK),
+ MSM_RPM_STATUS_ID_MAP(8930, PXO_CLK),
+ MSM_RPM_STATUS_ID_MAP(8930, APPS_FABRIC_CLK),
+ MSM_RPM_STATUS_ID_MAP(8930, SYSTEM_FABRIC_CLK),
+ MSM_RPM_STATUS_ID_MAP(8930, MM_FABRIC_CLK),
+ MSM_RPM_STATUS_ID_MAP(8930, DAYTONA_FABRIC_CLK),
+ MSM_RPM_STATUS_ID_MAP(8930, SFPB_CLK),
+ MSM_RPM_STATUS_ID_MAP(8930, CFPB_CLK),
+ MSM_RPM_STATUS_ID_MAP(8930, MMFPB_CLK),
+ MSM_RPM_STATUS_ID_MAP(8930, EBI1_CLK),
+ MSM_RPM_STATUS_ID_MAP(8930, APPS_FABRIC_CFG_HALT),
+ MSM_RPM_STATUS_ID_MAP(8930, APPS_FABRIC_CFG_CLKMOD),
+ MSM_RPM_STATUS_ID_MAP(8930, APPS_FABRIC_CFG_IOCTL),
+ MSM_RPM_STATUS_ID_MAP(8930, APPS_FABRIC_ARB),
+ MSM_RPM_STATUS_ID_MAP(8930, SYS_FABRIC_CFG_HALT),
+ MSM_RPM_STATUS_ID_MAP(8930, SYS_FABRIC_CFG_CLKMOD),
+ MSM_RPM_STATUS_ID_MAP(8930, SYS_FABRIC_CFG_IOCTL),
+ MSM_RPM_STATUS_ID_MAP(8930, SYSTEM_FABRIC_ARB),
+ MSM_RPM_STATUS_ID_MAP(8930, MMSS_FABRIC_CFG_HALT),
+ MSM_RPM_STATUS_ID_MAP(8930, MMSS_FABRIC_CFG_CLKMOD),
+ MSM_RPM_STATUS_ID_MAP(8930, MMSS_FABRIC_CFG_IOCTL),
+ MSM_RPM_STATUS_ID_MAP(8930, MM_FABRIC_ARB),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_S1_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_S1_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_S2_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_S2_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_S3_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_S3_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_S4_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_S4_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_S5_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_S5_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_S6_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_S6_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_S7_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_S7_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_S8_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_S8_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L1_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L1_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L2_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L2_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L3_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L3_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L4_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L4_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L5_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L5_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L6_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L6_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L7_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L7_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L8_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L8_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L9_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L9_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L10_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L10_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L11_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L11_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L12_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L12_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L14_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L14_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L15_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L15_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L16_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L16_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L17_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L17_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L18_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L18_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L21_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L21_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L22_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L22_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L23_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L23_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L24_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L24_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L25_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L25_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L26_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L26_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L27_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L27_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L28_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L28_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L29_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L29_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L30_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L30_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L31_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L31_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L32_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L32_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L33_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L33_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L34_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L34_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L35_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L35_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L36_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_L36_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_CLK1_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_CLK1_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_CLK2_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_CLK2_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_LVS1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_LVS3),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_LVS4),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_LVS5),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_LVS6),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_LVS7),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_NCP_0),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_NCP_1),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_CXO_BUFFERS),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_USB_OTG_SWITCH),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_HDMI_SWITCH),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_QDSS_CLK),
+ MSM_RPM_STATUS_ID_MAP(8930, PM8917_VOLTAGE_CORNER),
+ },
+ .target_ctrl_id = {
+ MSM_RPM_CTRL_MAP(8930, VERSION_MAJOR),
+ MSM_RPM_CTRL_MAP(8930, VERSION_MINOR),
+ MSM_RPM_CTRL_MAP(8930, VERSION_BUILD),
+ MSM_RPM_CTRL_MAP(8930, REQ_CTX_0),
+ MSM_RPM_CTRL_MAP(8930, REQ_SEL_0),
+ MSM_RPM_CTRL_MAP(8930, ACK_CTX_0),
+ MSM_RPM_CTRL_MAP(8930, ACK_SEL_0),
+ },
+ .sel_invalidate = MSM_RPM_8930_SEL_INVALIDATE,
+ .sel_notification = MSM_RPM_8930_SEL_NOTIFICATION,
+ .sel_last = MSM_RPM_8930_SEL_LAST,
+ .ver = {3, 0, 0},
+};
struct platform_device msm8930_rpm_device = {
.name = "msm_rpm",
.id = -1,
@@ -386,9 +640,16 @@
.id = -1,
};
+static struct acpuclk_platform_data acpuclk_8930_pdata = {
+ .uses_pm8917 = false,
+};
+
struct platform_device msm8930_device_acpuclk = {
.name = "acpuclk-8930",
.id = -1,
+ .dev = {
+ .platform_data = &acpuclk_8930_pdata,
+ },
};
struct platform_device msm8930aa_device_acpuclk = {
@@ -853,26 +1114,6 @@
struct msm_iommu_domain_name msm8930_iommu_ctx_names[] = {
/* Camera */
{
- .name = "vpe_src",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vpe_dst",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_imgwr",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_misc",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
.name = "ijpeg_src",
.domain = CAMERA_DOMAIN,
},
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 8a4b3f4..377ecae 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -50,6 +50,7 @@
#include "scm-pas.h"
#include <mach/msm_dcvs.h>
#include <mach/iommu_domains.h>
+#include <mach/socinfo.h>
#ifdef CONFIG_MSM_MPM
#include <mach/mpm.h>
@@ -717,7 +718,7 @@
},
{
ARRAY_SIZE(vidc_venc_1080p_turbo_vectors),
- vidc_vdec_1080p_turbo_vectors,
+ vidc_venc_1080p_turbo_vectors,
},
{
ARRAY_SIZE(vidc_vdec_1080p_turbo_vectors),
@@ -730,6 +731,286 @@
ARRAY_SIZE(vidc_bus_client_config),
.name = "vidc",
};
+
+static struct msm_bus_vectors vidc_pro_init_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VIDEO_DEC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+static struct msm_bus_vectors vidc_pro_venc_vga_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 54525952,
+ .ib = 436207616,
+ },
+ {
+ .src = MSM_BUS_MASTER_VIDEO_DEC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 72351744,
+ .ib = 289406976,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 500000,
+ .ib = 1000000,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 500000,
+ .ib = 1000000,
+ },
+};
+static struct msm_bus_vectors vidc_pro_vdec_vga_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 40894464,
+ .ib = 327155712,
+ },
+ {
+ .src = MSM_BUS_MASTER_VIDEO_DEC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 48234496,
+ .ib = 192937984,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 500000,
+ .ib = 2000000,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 500000,
+ .ib = 2000000,
+ },
+};
+static struct msm_bus_vectors vidc_pro_venc_720p_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 163577856,
+ .ib = 1308622848,
+ },
+ {
+ .src = MSM_BUS_MASTER_VIDEO_DEC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 219152384,
+ .ib = 876609536,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 1750000,
+ .ib = 3500000,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 1750000,
+ .ib = 3500000,
+ },
+};
+static struct msm_bus_vectors vidc_pro_vdec_720p_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 121634816,
+ .ib = 973078528,
+ },
+ {
+ .src = MSM_BUS_MASTER_VIDEO_DEC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 155189248,
+ .ib = 620756992,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 1750000,
+ .ib = 7000000,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 1750000,
+ .ib = 7000000,
+ },
+};
+static struct msm_bus_vectors vidc_pro_venc_1080p_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 372244480,
+ .ib = 2560000000U,
+ },
+ {
+ .src = MSM_BUS_MASTER_VIDEO_DEC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 501219328,
+ .ib = 2560000000U,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 2500000,
+ .ib = 5000000,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 2500000,
+ .ib = 5000000,
+ },
+};
+static struct msm_bus_vectors vidc_pro_vdec_1080p_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 222298112,
+ .ib = 2560000000U,
+ },
+ {
+ .src = MSM_BUS_MASTER_VIDEO_DEC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 330301440,
+ .ib = 2560000000U,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 2500000,
+ .ib = 700000000,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 2500000,
+ .ib = 10000000,
+ },
+};
+static struct msm_bus_vectors vidc_pro_venc_1080p_turbo_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 222298112,
+ .ib = 3522000000U,
+ },
+ {
+ .src = MSM_BUS_MASTER_VIDEO_DEC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 330301440,
+ .ib = 3522000000U,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 2500000,
+ .ib = 700000000,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 2500000,
+ .ib = 10000000,
+ },
+};
+static struct msm_bus_vectors vidc_pro_vdec_1080p_turbo_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_ENC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 222298112,
+ .ib = 3522000000U,
+ },
+ {
+ .src = MSM_BUS_MASTER_VIDEO_DEC,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 330301440,
+ .ib = 3522000000U,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 2500000,
+ .ib = 700000000,
+ },
+ {
+ .src = MSM_BUS_MASTER_AMPSS_M0,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 2500000,
+ .ib = 10000000,
+ },
+};
+
+static struct msm_bus_paths vidc_pro_bus_client_config[] = {
+ {
+ ARRAY_SIZE(vidc_pro_init_vectors),
+ vidc_pro_init_vectors,
+ },
+ {
+ ARRAY_SIZE(vidc_pro_venc_vga_vectors),
+ vidc_pro_venc_vga_vectors,
+ },
+ {
+ ARRAY_SIZE(vidc_pro_vdec_vga_vectors),
+ vidc_pro_vdec_vga_vectors,
+ },
+ {
+ ARRAY_SIZE(vidc_pro_venc_720p_vectors),
+ vidc_pro_venc_720p_vectors,
+ },
+ {
+ ARRAY_SIZE(vidc_pro_vdec_720p_vectors),
+ vidc_pro_vdec_720p_vectors,
+ },
+ {
+ ARRAY_SIZE(vidc_pro_venc_1080p_vectors),
+ vidc_pro_venc_1080p_vectors,
+ },
+ {
+ ARRAY_SIZE(vidc_pro_vdec_1080p_vectors),
+ vidc_pro_vdec_1080p_vectors,
+ },
+ {
+ ARRAY_SIZE(vidc_pro_venc_1080p_turbo_vectors),
+ vidc_pro_venc_1080p_turbo_vectors,
+ },
+ {
+ ARRAY_SIZE(vidc_vdec_1080p_turbo_vectors),
+ vidc_pro_vdec_1080p_turbo_vectors,
+ },
+};
+
+static struct msm_bus_scale_pdata vidc_pro_bus_client_data = {
+ vidc_pro_bus_client_config,
+ ARRAY_SIZE(vidc_bus_client_config),
+ .name = "vidc",
+};
#endif
#ifdef CONFIG_HW_RANDOM_MSM
@@ -2033,20 +2314,20 @@
.mode_8k = {
.mode = AFE_PCM_CFG_MODE_PCM,
.sync = AFE_PCM_CFG_SYNC_INT,
- .frame = AFE_PCM_CFG_FRM_256BPF,
+ .frame = AFE_PCM_CFG_FRM_32BPF,
.quant = AFE_PCM_CFG_QUANT_LINEAR_NOPAD,
.slot = 0,
.data = AFE_PCM_CFG_CDATAOE_MASTER,
- .pcm_clk_rate = 2048000,
+ .pcm_clk_rate = 256000,
},
.mode_16k = {
.mode = AFE_PCM_CFG_MODE_PCM,
.sync = AFE_PCM_CFG_SYNC_INT,
- .frame = AFE_PCM_CFG_FRM_256BPF,
+ .frame = AFE_PCM_CFG_FRM_32BPF,
.quant = AFE_PCM_CFG_QUANT_LINEAR_NOPAD,
.slot = 0,
.data = AFE_PCM_CFG_CDATAOE_MASTER,
- .pcm_clk_rate = 4096000,
+ .pcm_clk_rate = 512000,
}
};
@@ -3780,26 +4061,6 @@
struct msm_iommu_domain_name msm8960_iommu_ctx_names[] = {
/* Camera */
{
- .name = "vpe_src",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vpe_dst",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_imgwr",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_misc",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
.name = "ijpeg_src",
.domain = CAMERA_DOMAIN,
},
@@ -4049,3 +4310,19 @@
.num_resources = ARRAY_SIZE(sglte_resources),
.resource = sglte_resources,
};
+
+struct platform_device *msm8960_vidc_device[] __initdata = {
+ &msm_device_vidc
+};
+
+void __init msm8960_add_vidc_device(void)
+{
+ if (cpu_is_msm8960ab()) {
+ struct msm_vidc_platform_data *pdata;
+ pdata = (struct msm_vidc_platform_data *)
+ msm_device_vidc.dev.platform_data;
+ pdata->vidc_bus_client_pdata = &vidc_pro_bus_client_data;
+ }
+ platform_add_devices(msm8960_vidc_device,
+ ARRAY_SIZE(msm8960_vidc_device));
+}
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index ae8a8fe..b65bd1f 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -939,8 +939,11 @@
&msm_device_iommu_gfx2d1,
};
-static struct platform_device *msm_iommu_8064_devs[] = {
+static struct platform_device *msm_iommu_adreno3xx_gfx_devs[] = {
&msm_device_iommu_gfx3d1,
+};
+
+static struct platform_device *msm_iommu_vcap_devs[] = {
&msm_device_iommu_vcap,
};
@@ -973,9 +976,12 @@
&msm_device_gfx2d1_2d1_ctx,
};
-static struct platform_device *msm_iommu_8064_ctx_devs[] = {
+static struct platform_device *msm_iommu_adreno3xx_ctx_devs[] = {
&msm_device_gfx3d1_user_ctx,
&msm_device_gfx3d1_priv_ctx,
+};
+
+static struct platform_device *msm_iommu_vcap_ctx_devs[] = {
&msm_device_vcap_vc_ctx,
&msm_device_vcap_vp_ctx,
};
@@ -1014,9 +1020,12 @@
if (cpu_is_apq8064() || cpu_is_msm8960ab()) {
platform_add_devices(msm_iommu_jpegd_devs,
ARRAY_SIZE(msm_iommu_jpegd_devs));
- platform_add_devices(msm_iommu_8064_devs,
- ARRAY_SIZE(msm_iommu_8064_devs));
+ platform_add_devices(msm_iommu_adreno3xx_gfx_devs,
+ ARRAY_SIZE(msm_iommu_adreno3xx_gfx_devs));
}
+ if (cpu_is_apq8064())
+ platform_add_devices(msm_iommu_vcap_devs,
+ ARRAY_SIZE(msm_iommu_vcap_devs));
/* Initialize common ctx_devs */
ret = platform_add_devices(msm_iommu_common_ctx_devs,
@@ -1033,9 +1042,13 @@
if (cpu_is_apq8064() || cpu_is_msm8960ab()) {
platform_add_devices(msm_iommu_jpegd_ctx_devs,
ARRAY_SIZE(msm_iommu_jpegd_ctx_devs));
- platform_add_devices(msm_iommu_8064_ctx_devs,
- ARRAY_SIZE(msm_iommu_8064_ctx_devs));
+
+ platform_add_devices(msm_iommu_adreno3xx_ctx_devs,
+ ARRAY_SIZE(msm_iommu_adreno3xx_ctx_devs));
}
+ if (cpu_is_apq8064())
+ platform_add_devices(msm_iommu_vcap_ctx_devs,
+ ARRAY_SIZE(msm_iommu_vcap_ctx_devs));
return 0;
@@ -1068,16 +1081,33 @@
for (i = 0; i < ARRAY_SIZE(msm_iommu_jpegd_devs); i++)
platform_device_unregister(msm_iommu_jpegd_devs[i]);
}
+ if (cpu_is_apq8064()) {
+ for (i = 0; i < ARRAY_SIZE(msm_iommu_vcap_ctx_devs); i++)
+ platform_device_unregister(msm_iommu_vcap_ctx_devs[i]);
+ }
if (cpu_is_apq8064() || cpu_is_msm8960ab()) {
- for (i = 0; i < ARRAY_SIZE(msm_iommu_8064_ctx_devs); i++)
- platform_device_unregister(msm_iommu_8064_ctx_devs[i]);
+ for (i = 0; i < ARRAY_SIZE(msm_iommu_adreno3xx_ctx_devs);
+ i++)
+ platform_device_unregister(
+ msm_iommu_adreno3xx_ctx_devs[i]);
- for (i = 0; i < ARRAY_SIZE(msm_iommu_jpegd_ctx_devs); i++)
- platform_device_unregister(msm_iommu_jpegd_ctx_devs[i]);
+ for (i = 0; i < ARRAY_SIZE(msm_iommu_jpegd_ctx_devs);
+ i++)
+ platform_device_unregister(
+ msm_iommu_jpegd_ctx_devs[i]);
- for (i = 0; i < ARRAY_SIZE(msm_iommu_8064_devs); i++)
- platform_device_unregister(msm_iommu_8064_devs[i]);
+ if (cpu_is_apq8064()) {
+ for (i = 0; i < ARRAY_SIZE(msm_iommu_vcap_devs);
+ i++)
+ platform_device_unregister(
+ msm_iommu_vcap_devs[i]);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(msm_iommu_adreno3xx_gfx_devs);
+ i++)
+ platform_device_unregister(
+ msm_iommu_adreno3xx_gfx_devs[i]);
for (i = 0; i < ARRAY_SIZE(msm_iommu_jpegd_devs); i++)
platform_device_unregister(msm_iommu_jpegd_devs[i]);
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 93fd12d..27de697 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -905,8 +905,13 @@
if (cpu_is_msm8625()) {
kgsl_3d0_pdata.idle_timeout = HZ/5;
kgsl_3d0_pdata.strtstp_sleepwake = false;
- /* 8x25 supports a higher GPU frequency */
- kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 320000000;
+
+ if (SOCINFO_VERSION_MAJOR(socinfo_get_version()) >= 2)
+ /* 8x25 v2.0 & above supports a higher GPU frequency */
+ kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 320000000;
+ else
+ kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 300000000;
+
kgsl_3d0_pdata.pwrlevel[0].bus_freq = 200000000;
}
}
@@ -1258,8 +1263,8 @@
},
{
.name = "dma_chnl",
- .start = DMOV_SDC3_CHAN,
- .end = DMOV_SDC3_CHAN,
+ .start = DMOV_NAND_CHAN,
+ .end = DMOV_NAND_CHAN,
.flags = IORESOURCE_DMA,
},
{
@@ -1587,6 +1592,47 @@
},
};
+enum {
+ MSM8625,
+ MSM8625A,
+ MSM8625AB,
+};
+
+static int __init msm8625_cpu_id(void)
+{
+ int raw_id, cpu;
+
+ raw_id = socinfo_get_raw_id();
+ switch (raw_id) {
+ /* Part number for 1GHz part */
+ case 0x770:
+ case 0x771:
+ case 0x77C:
+ case 0x780:
+ case 0x8D0:
+ cpu = MSM8625;
+ break;
+ /* Part number for 1.2GHz part */
+ case 0x773:
+ case 0x774:
+ case 0x781:
+ case 0x8D1:
+ cpu = MSM8625A;
+ break;
+ case 0x775:
+ case 0x776:
+ case 0x77D:
+ case 0x782:
+ case 0x8D2:
+ cpu = MSM8625AB;
+ break;
+ default:
+ pr_err("Invalid Raw ID\n");
+ return -ENODEV;
+ }
+ return cpu;
+}
+
static struct resource cpr_resources[] = {
{
.start = MSM8625_INT_CPR_IRQ0,
@@ -1603,12 +1649,12 @@
* These are various Vdd levels supported by PMIC
*/
static uint32_t msm_c2_pmic_mv[] __initdata = {
- 1300, 12875 / 10, 1275, 12625 / 10, 1250,
- 12375 / 10, 1225, 12125 / 10, 1200, 11875 / 10,
- 1175, 11625 / 10, 1150, 11375 / 10, 1125,
- 11125 / 10, 1100, 10875 / 10, 1075, 10625 / 10,
- 1050, 10375 / 10, 1025, 10125 / 10, 0, 0, 0, 0,
- 0, 0, 0, 1000,
+ 1300000, 1287500, 1275000, 1262500, 1250000,
+ 1237500, 1225000, 1212500, 1200000, 1187500,
+ 1175000, 1162500, 1150000, 1137500, 1125000,
+ 1112500, 1100000, 1087500, 1075000, 1062500,
+ 1050000, 1037500, 1025000, 1012500, 0, 0, 0,
+ 0, 0, 0, 0, 1000,
};
/**
@@ -1628,10 +1674,10 @@
},
.ring_osc = 0,
.step_quot = ~0,
- .tgt_volt_offset = 1,
- .Vmax = 1200,
- .Vmin = 1000,
- .calibrated_mV = 1100,
+ .tgt_volt_offset = 0,
+ .Vmax = 1200000,
+ .Vmin = 1000000,
+ .calibrated_uV = 1100000,
},
[TURBO_MODE] = {
.ring_osc_data = {
@@ -1646,23 +1692,47 @@
},
.ring_osc = 0,
.step_quot = ~0,
- .tgt_volt_offset = 1,
- .Vmax = 1350,
- .Vmin = 1250,
- .calibrated_mV = 1300,
+ .tgt_volt_offset = 0,
+ .Vmax = 1350000,
+ .Vmin = 1150000,
+ .calibrated_uV = 1300000,
},
};
struct msm_cpr_vp_data vp_data = {
- .min_volt = 1000,
- .max_volt = 1350,
- .default_volt = 1300,
- .step_size = (12500 / 1000),
+ .min_volt = 1000000,
+ .max_volt = 1350000,
+ .default_volt = 1300000,
+ .step_size = 12500,
};
+static uint32_t
+msm_cpr_get_quot(uint32_t max_quot, uint32_t max_freq, uint32_t new_freq)
+{
+ uint32_t quot;
+
+ /* This formula is as per chip characterization data */
+ quot = max_quot - ((max_freq / 10 - new_freq / 10) * 9) + 20;
+
+ return quot;
+}
+
+static void msm_cpr_clk_enable(void)
+{
+ uint32_t reg_val;
+
+ /* Select TCXO (19.2MHz) as clock source */
+ reg_val = readl_relaxed(A11S_TEST_BUS_SEL_ADDR);
+ reg_val |= RBCPR_CLK_MUX_SEL;
+ writel_relaxed(reg_val, A11S_TEST_BUS_SEL_ADDR);
+
+ /* Get CPR out of reset */
+ writel_relaxed(0x1, RBCPR_SW_RESET_N);
+}
+
static struct msm_cpr_config msm_cpr_pdata = {
.ref_clk_khz = 19200,
- .delay_us = 10000,
+ .delay_us = 25000,
.irq_line = 0,
.cpr_mode_data = msm_cpr_mode_data,
.tgt_count_div_N = 1,
@@ -1673,8 +1743,12 @@
.dn_threshold = 2,
.up_margin = 0,
.dn_margin = 0,
- .nom_freq_limit = 1008000,
+ .max_nom_freq = 700800,
+ .max_freq = 1401600,
+ .max_quot = 0,
.vp_data = &vp_data,
+ .get_quot = msm_cpr_get_quot,
+ .clk_enable = msm_cpr_clk_enable,
};
static struct platform_device msm8625_device_cpr = {
@@ -1696,7 +1770,6 @@
{
struct cpr_info_type *cpr_info = NULL;
uint8_t ring_osc = 0;
- uint32_t reg_val;
cpr_info = kzalloc(sizeof(struct cpr_info_type), GFP_KERNEL);
if (!cpr_info) {
@@ -1723,35 +1796,32 @@
msm_cpr_mode_data[TURBO_MODE].ring_osc_data[ring_osc].gcnt = 19;
msm_cpr_mode_data[NORMAL_MODE].ring_osc_data[ring_osc].gcnt = 19;
- /* The multiplier and offset are as per PTE data */
- msm_cpr_mode_data[TURBO_MODE].ring_osc_data[ring_osc].target_count =
- cpr_info->turbo_quot * 10 + 440;
- msm_cpr_mode_data[NORMAL_MODE].ring_osc_data[ring_osc].target_count =
- cpr_info->turbo_quot / msm_cpr_pdata.tgt_count_div_N;
+ /**
+ * The scaling factor and offset are as per chip characterization data
+ * This formula is used since available fuse bits in the chip are not
+ * enough to represent the value of maximum quot
+ */
+ msm_cpr_pdata.max_quot = cpr_info->turbo_quot * 10 + 610;
/**
* Bits 4:0 of pvs_fuse provide mapping to the safe boot up voltage.
* Boot up mode is by default Turbo.
*/
- msm_cpr_mode_data[TURBO_MODE].calibrated_mV =
+ msm_cpr_mode_data[TURBO_MODE].calibrated_uV =
msm_c2_pmic_mv[cpr_info->pvs_fuse & 0x1F];
- /* TODO: Store the tgt_volt_offset values for the modes from PTE */
-
-
pr_debug("%s: cpr: ring_osc: 0x%x\n", __func__,
msm_cpr_mode_data[TURBO_MODE].ring_osc);
pr_debug("%s: cpr: turbo_quot: 0x%x\n", __func__, cpr_info->turbo_quot);
pr_debug("%s: cpr: pvs_fuse: 0x%x\n", __func__, cpr_info->pvs_fuse);
kfree(cpr_info);
- /* Select TCXO (19.2MHz) as clock source */
- reg_val = readl_relaxed(A11S_TEST_BUS_SEL_ADDR);
- reg_val |= RBCPR_CLK_MUX_SEL;
- writel_relaxed(reg_val, A11S_TEST_BUS_SEL_ADDR);
+ if (msm8625_cpu_id() == MSM8625A)
+ msm_cpr_pdata.max_freq = 1209600;
+ else if (msm8625_cpu_id() == MSM8625)
+ msm_cpr_pdata.max_freq = 1008000;
- /* Get CPR out of reset */
- writel_relaxed(0x1, RBCPR_SW_RESET_N);
+ msm_cpr_clk_enable();
platform_device_register(&msm8625_vp_device);
platform_device_register(&msm8625_device_cpr);
@@ -1823,46 +1893,6 @@
.table = msm_clock_8625_dummy,
.size = ARRAY_SIZE(msm_clock_8625_dummy),
};
-enum {
- MSM8625,
- MSM8625A,
- MSM8625AB,
-};
-
-static int __init msm8625_cpu_id(void)
-{
- int raw_id, cpu;
-
- raw_id = socinfo_get_raw_id();
- switch (raw_id) {
- /* Part number for 1GHz part */
- case 0x770:
- case 0x771:
- case 0x77C:
- case 0x780:
- case 0x8D0:
- cpu = MSM8625;
- break;
- /* Part number for 1.2GHz part */
- case 0x773:
- case 0x774:
- case 0x781:
- case 0x8D1:
- cpu = MSM8625A;
- break;
- case 0x775:
- case 0x776:
- case 0x77D:
- case 0x782:
- case 0x8D2:
- cpu = MSM8625AB;
- break;
- default:
- pr_err("Invalid Raw ID\n");
- return -ENODEV;
- }
- return cpu;
-}
int __init msm7x2x_misc_init(void)
{
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index a6473c6..45486f4 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -1329,7 +1329,7 @@
static struct kgsl_device_platform_data kgsl_2d0_pdata = {
.pwrlevel = {
{
- .gpu_freq = 192000000,
+ .gpu_freq = 0,
.bus_freq = 192000000,
},
},
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 9f31a18..57d7f08 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -3003,26 +3003,6 @@
struct msm_iommu_domain_name msm8660_iommu_ctx_names[] = {
/* Camera */
{
- .name = "vpe_src",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vpe_dst",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_imgwr",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_misc",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
.name = "ijpeg_src",
.domain = CAMERA_DOMAIN,
},
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index ab246a5..3311ea1 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -64,18 +64,6 @@
uint8_t is_vpe;
struct msm_bus_scale_pdata *cam_bus_scale_table;
};
-enum msm_camera_csi_data_format {
- CSI_8BIT,
- CSI_10BIT,
- CSI_12BIT,
-};
-struct msm_camera_csi_params {
- enum msm_camera_csi_data_format data_format;
- uint8_t lane_cnt;
- uint8_t lane_assign;
- uint8_t settle_cnt;
- uint8_t dpcm_scheme;
-};
#ifdef CONFIG_SENSORS_MT9T013
struct msm_camera_legacy_device_platform_data {
@@ -180,21 +168,6 @@
YUV_SENSOR,
};
-enum camera_vreg_type {
- REG_LDO,
- REG_VS,
- REG_GPIO,
- REG_MAX
-};
-
-struct camera_vreg_t {
- const char *reg_name;
- enum camera_vreg_type type;
- int min_voltage;
- int max_voltage;
- int op_mode;
-};
-
struct msm_gpio_set_tbl {
unsigned gpio;
unsigned long flags;
@@ -234,6 +207,13 @@
enum msm_camera_i2c_mux_mode i2c_mux_mode;
};
+enum msm_camera_vreg_name_t {
+ CAM_VDIG,
+ CAM_VIO,
+ CAM_VANA,
+ CAM_VAF,
+};
+
struct msm_camera_sensor_platform_info {
int mount_angle;
int sensor_reset;
@@ -268,6 +248,9 @@
struct msm_eeprom_info {
struct i2c_board_info const *board_info;
int bus_id;
+ int eeprom_reg_addr;
+ int eeprom_read_length;
+ int eeprom_i2c_slave_addr;
};
struct msm_camera_sensor_info {
@@ -285,7 +268,6 @@
uint8_t num_resources;
struct msm_camera_sensor_flash_data *flash_data;
int csi_if;
- struct msm_camera_csi_params csi_params;
struct msm_camera_sensor_strobe_flash_data *strobe_flash_data;
char *eeprom_data;
enum msm_camera_type camera_type;
@@ -314,6 +296,17 @@
unsigned num;
};
+struct cad_endpoint {
+ int id;
+ const char *name;
+ uint32_t capability;
+};
+
+struct msm_cad_endpoints {
+ struct cad_endpoint *endpoints;
+ unsigned num;
+};
+
#define MSM_MAX_DEC_CNT 14
/* 7k target ADSP information */
/* Bit 23:0, for codec identification like mp3, wav etc *
@@ -522,6 +515,7 @@
int aux_dat;
int src_clk_rate;
int use_gsbi_shared_mode;
+ int keep_ahb_clk_on;
void (*msm_i2c_config_gpio)(int iface, int config_type);
};
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index a51a6b5..6298d94 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -127,30 +127,6 @@
uint32_t frame_id;
};
-struct msm_camera_csid_lut_params {
- uint8_t num_cid;
- struct msm_camera_csid_vc_cfg *vc_cfg;
-};
-
-struct msm_camera_csid_params {
- uint8_t lane_cnt;
- uint16_t lane_assign;
- uint8_t phy_sel;
- struct msm_camera_csid_lut_params lut_params;
-};
-
-struct msm_camera_csiphy_params {
- uint8_t lane_cnt;
- uint8_t settle_cnt;
- uint16_t lane_mask;
- uint8_t combo_mode;
-};
-
-struct msm_camera_csi2_params {
- struct msm_camera_csid_params csid_params;
- struct msm_camera_csiphy_params csiphy_params;
-};
-
#ifndef CONFIG_MSM_CAMERA_V4L2
#define VFE31_OUTPUT_MODE_PT (0x1 << 0)
#define VFE31_OUTPUT_MODE_S (0x1 << 1)
@@ -332,21 +308,6 @@
uint16_t i2c_queue;
};
-enum msm_camera_i2c_reg_addr_type {
- MSM_CAMERA_I2C_BYTE_ADDR = 1,
- MSM_CAMERA_I2C_WORD_ADDR,
-};
-
-enum msm_camera_i2c_data_type {
- MSM_CAMERA_I2C_BYTE_DATA = 1,
- MSM_CAMERA_I2C_WORD_DATA,
- MSM_CAMERA_I2C_SET_BYTE_MASK,
- MSM_CAMERA_I2C_UNSET_BYTE_MASK,
- MSM_CAMERA_I2C_SET_WORD_MASK,
- MSM_CAMERA_I2C_UNSET_WORD_MASK,
- MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA,
-};
-
enum msm_camera_i2c_cmd_type {
MSM_CAMERA_I2C_CMD_WRITE,
MSM_CAMERA_I2C_CMD_POLL,
@@ -406,6 +367,7 @@
atomic_t on_heap;
struct timespec ts;
uint32_t error_code;
+ uint32_t trans_code;
};
struct msm_device_queue {
@@ -673,11 +635,6 @@
S_EXIT
};
-struct msm_cam_clk_info {
- const char *clk_name;
- long clk_rate;
-};
-
int msm_camio_enable(struct platform_device *dev);
int msm_camio_vpe_clk_enable(uint32_t);
int msm_camio_vpe_clk_disable(void);
@@ -733,12 +690,16 @@
int msm_cam_core_reset(void);
int msm_camera_config_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
- int num_vreg, struct regulator **reg_ptr, int config);
+ int num_vreg, enum msm_camera_vreg_name_t *vreg_seq,
+ int num_vreg_seq, struct regulator **reg_ptr, int config);
int msm_camera_enable_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
- int num_vreg, struct regulator **reg_ptr, int enable);
+ int num_vreg, enum msm_camera_vreg_name_t *vreg_seq,
+ int num_vreg_seq, struct regulator **reg_ptr, int enable);
int msm_camera_config_gpio_table
(struct msm_camera_sensor_info *sinfo, int gpio_en);
int msm_camera_request_gpio_table
(struct msm_camera_sensor_info *sinfo, int gpio_en);
+void msm_camera_bus_scale_cfg(uint32_t bus_perf_client,
+ enum msm_bus_perf_setting perf_setting);
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
index 1458afe..7f04be8 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8974.h
@@ -40,6 +40,15 @@
#define MSM8974_MPM2_PSHOLD_PHYS 0xFC4AB000
#define MSM8974_MPM2_PSHOLD_SIZE SZ_4K
+/*
+ * TODO: Revert IMEM_PHYS back to actual
+ * address 0xfe805000
+ * after IMEM issues resolved.
+ *
+ */
+#define MSM8974_IMEM_PHYS 0xFC42B000
+#define MSM8974_IMEM_SIZE SZ_4K
+
#ifdef CONFIG_DEBUG_MSM8974_UART
#define MSM_DEBUG_UART_BASE IOMEM(0xFA71E000)
#define MSM_DEBUG_UART_PHYS 0xF991E000
diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h
index 97c03e7..0c452f8 100644
--- a/arch/arm/mach-msm/include/mach/msm_smd.h
+++ b/arch/arm/mach-msm/include/mach/msm_smd.h
@@ -309,6 +309,24 @@
*/
int smd_is_pkt_avail(smd_channel_t *ch);
+/**
+ * smd_module_init_notifier_register() - Register a smd module
+ * init notifier block
+ * @nb: Notifier block to be registered
+ *
+ * In order to mark the dependency on SMD Driver module initialization
+ * register a notifier using this API. Once the smd module_init is
+ * done, notification will be passed to the registered module.
+ */
+int smd_module_init_notifier_register(struct notifier_block *nb);
+
+/**
+ * smd_module_init_notifier_register() - Unregister a smd module
+ * init notifier block
+ * @nb: Notifier block to be registered
+ */
+int smd_module_init_notifier_unregister(struct notifier_block *nb);
+
/*
* SMD initialization function that registers for a SMD platform driver.
*
@@ -438,6 +456,16 @@
return -ENODEV;
}
+static inline int smd_module_init_notifier_register(struct notifier_block *nb)
+{
+ return -ENODEV;
+}
+
+static inline int smd_module_init_notifier_unregister(struct notifier_block *nb)
+{
+ return -ENODEV;
+}
+
static inline int __init msm_smd_init(void)
{
return 0;
diff --git a/arch/arm/mach-msm/include/mach/msm_smsm.h b/arch/arm/mach-msm/include/mach/msm_smsm.h
index e19f39d..133a1b3 100644
--- a/arch/arm/mach-msm/include/mach/msm_smsm.h
+++ b/arch/arm/mach-msm/include/mach/msm_smsm.h
@@ -133,8 +133,6 @@
void *data);
int smsm_state_cb_deregister(uint32_t smsm_entry, uint32_t mask,
void (*notify)(void *, uint32_t, uint32_t), void *data);
-int smsm_driver_state_notifier_register(struct notifier_block *nb);
-int smsm_driver_state_notifier_unregister(struct notifier_block *nb);
void smsm_print_sleep_info(uint32_t sleep_delay, uint32_t sleep_limit,
uint32_t irq_mask, uint32_t wakeup_reason, uint32_t pending_irqs);
void smsm_reset_modem(unsigned mode);
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index a5b0275..47f9b10 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -10,8 +10,8 @@
* GNU General Public License for more details.
*/
-#ifndef _ARCH_ARM_MACH_MSM_OCMEM_CORE_H
-#define _ARCH_ARM_MACH_MSM_OCMEM_CORE_H
+#ifndef _ARCH_ARM_MACH_MSM_OCMEM_PRIV_H
+#define _ARCH_ARM_MACH_MSM_OCMEM_PRIV_H
/** All interfaces in this header should only be used by OCMEM driver
* Client drivers should use wrappers available in ocmem.h
@@ -36,6 +36,29 @@
int (*free) (struct ocmem_zone *, unsigned long, unsigned long);
};
+/* OCMEM Zone specific counters */
+/* Must be in sync with zstat_names */
+enum ocmem_zstat_item {
+ NR_REQUESTS = 0x0,
+ NR_SYNC_ALLOCATIONS,
+ NR_RANGE_ALLOCATIONS,
+ NR_ASYNC_ALLOCATIONS,
+ NR_ALLOCATION_FAILS,
+ NR_GROWTHS,
+ NR_FREES,
+ NR_SHRINKS,
+ NR_MAPS,
+ NR_MAP_FAILS,
+ NR_UNMAPS,
+ NR_UNMAP_FAILS,
+ NR_TRANSFERS_TO_OCMEM,
+ NR_TRANSFERS_TO_DDR,
+ NR_TRANSFER_FAILS,
+ NR_EVICTIONS,
+ NR_RESTORES,
+ NR_OCMEM_ZSTAT_ITEMS,
+};
+
struct ocmem_zone {
bool active;
int owner;
@@ -47,6 +70,7 @@
unsigned long z_head;
unsigned long z_tail;
unsigned long z_free;
+ atomic_long_t z_stat[NR_OCMEM_ZSTAT_ITEMS];
struct gen_pool *z_pool;
struct ocmem_zone_ops *z_ops;
};
@@ -82,6 +106,7 @@
void __iomem *reg_base;
void __iomem *br_base;
void __iomem *dm_base;
+ struct dentry *debug_node;
unsigned nr_regions;
unsigned nr_macros;
unsigned nr_ports;
@@ -137,50 +162,15 @@
struct ocmem_req *req;
};
-static inline struct ocmem_buf *handle_to_buffer(struct ocmem_handle *handle)
-{
- if (handle)
- return &handle->buffer;
- else
- return NULL;
-}
-
-static inline struct ocmem_handle *buffer_to_handle(struct ocmem_buf *buffer)
-{
- if (buffer)
- return container_of(buffer, struct ocmem_handle, buffer);
- else
- return NULL;
-}
-
-static inline struct ocmem_req *handle_to_req(struct ocmem_handle *handle)
-{
- if (handle)
- return handle->req;
- else
- return NULL;
-}
-
-static inline struct ocmem_handle *req_to_handle(struct ocmem_req *req)
-{
- if (req && req->buffer)
- return container_of(req->buffer, struct ocmem_handle, buffer);
- else
- return NULL;
-}
-
-/* Simple wrappers which will have debug features added later */
-static inline int ocmem_read(void *at)
-{
- return readl_relaxed(at);
-}
-
-static inline int ocmem_write(unsigned long val, void *at)
-{
- writel_relaxed(val, at);
- return 0;
-}
-
+struct ocmem_buf *handle_to_buffer(struct ocmem_handle *);
+struct ocmem_handle *buffer_to_handle(struct ocmem_buf *);
+struct ocmem_req *handle_to_req(struct ocmem_handle *);
+struct ocmem_handle *req_to_handle(struct ocmem_req *);
+int ocmem_read(void *);
+int ocmem_write(unsigned long, void *);
+void inc_ocmem_stat(struct ocmem_zone *, enum ocmem_zstat_item);
+unsigned long get_ocmem_stat(struct ocmem_zone *z,
+ enum ocmem_zstat_item item);
struct ocmem_zone *get_zone(unsigned);
int zone_active(int);
unsigned long offset_to_phys(unsigned long);
@@ -196,7 +186,7 @@
int check_id(int);
int dispatch_notification(int, enum ocmem_notif_type, struct ocmem_buf *);
-int ocmem_sched_init(void);
+int ocmem_sched_init(struct platform_device *);
int ocmem_rdm_init(struct platform_device *);
int ocmem_core_init(struct platform_device *);
int process_allocate(int, struct ocmem_handle *, unsigned long, unsigned long,
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/acdb_commands.h b/arch/arm/mach-msm/include/mach/qdsp5/acdb_commands.h
new file mode 100644
index 0000000..188af9f
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/qdsp5/acdb_commands.h
@@ -0,0 +1,303 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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 _MACH_QDSP5_V2_ACDB_COMMANDS_H
+#define _MACH_QDSP5_V2_ACDB_COMMANDS_H
+
+#define ACDB_VOICE_NETWORK_ID_DEFAULT 0x00010037
+#define ACDB_INITIALISING 0
+#define ACDB_READY 1
+
+
+/* 4KB */
+#define ACDB_PAGE_SIZE 0x1000
+
+#define ACDB_CDMA_NB 0x0108b153
+#define ACDB_CDMA_WB 0x0108b154
+#define ACDB_GSM_NB 0x0108b155
+#define ACDB_GSM_WB 0x0108b156
+#define ACDB_WCDMA_NB 0x0108b157
+#define ACDB_WCDMA_WB 0x0108b158
+
+
+/* ACDB commands */
+
+
+/* struct acdb_cmd_install_device */
+#define ACDB_INSTALL_DEVICE 0x0108d245
+
+/* struct acdb_cmd_install_device */
+#define ACDB_UNINSTALL_DEVICE 0x0108d246
+
+/* struct acdb_cmd_device */
+#define ACDB_GET_DEVICE 0x0108bb92
+
+/* struct acdb_cmd_device */
+#define ACDB_SET_DEVICE 0x0108bb93
+
+/* struct acdb_cmd_get_device_table */
+#define ACDB_GET_DEVICE_TABLE 0x0108bb97
+
+/* struct acdb_cmd_get_device_capabilities */
+#define ACDB_GET_DEVICE_CAPABILITIES 0x0108f5ca
+
+/* struct acdb_cmd_get_device_info */
+#define ACDB_GET_DEVICE_INFO 0x0108f5cb
+
+/*command to intitialize ACDB based on codec type*/
+#define ACDB_CMD_INITIALIZE_FOR_ADIE 0x00011283
+
+
+/* ACDB Error codes */
+
+#define ACDB_RES_SUCCESS 0
+#define ACDB_RES_FAILURE -1
+#define ACDB_RES_BADPARM -2
+#define ACDB_RES_BADSTATE -3
+
+#define TGTVERS_MSM7x30_BRING_UP 0x00010064
+
+
+
+/* Algorithm Aspect IDs */
+
+#define IID_ENABLE_FLAG 0x0108b6b9
+
+
+#define IID_ENABLE_FLAG_SIZE 1
+#define IID_ECHO_CANCELLER_VERSION_SIZE 2
+#define IID_ECHO_CANCELLER_MODE_SIZE 2
+#define IID_ECHO_CANCELLER_NOISE_SUPPRESSOR_ENABLE_SIZE 1
+#define IID_ECHO_CANCELLER_PARAMETERS_SIZE 32
+#define IID_ECHO_CANCELLER_NEXTGEN_NB_PARAMETERS_SIZE (38 * 2)
+#define IID_ECHO_CANCELLER_NEXTGEN_WB_PARAMETERS_SIZE (38 * 2)
+#define IID_FLUENCE_PARAMETERS_SIZE 486
+#define IID_AFE_VOLUME_CONTROL_SIZE 6
+#define IID_GAIN_SIZE 2
+#define IID_VOICE_FIR_FILTER_SIZE 14
+#define IID_VOICE_IIR_FILTER_SIZE 114
+#define IID_RX_DBM_OFFSET_SIZE 2
+#define IID_AGC_SIZE 36
+#define IID_AVC_SIZE 80
+
+#define IID_AUDIO_IIR_COEFF_SIZE 100
+#define IID_MBADRC_PARAMETERS_SIZE 8
+#define IID_MBADRC_EXT_BUFF_SIZE 392
+#define IID_MBADRC_BAND_CONFIG_SIZE 100
+#define IID_QAFX_PARAMETERS_SIZE 2
+#define IID_QCONCERT_PARAMETERS_SIZE 2
+#define IID_AUDIO_AGC_PARAMETERS_SIZE 42
+#define IID_NS_PARAMETERS_SIZE 14
+
+#define IID_ECHO_CANCELLER_VERSION 0x00010042
+#define IID_ECHO_CANCELLER_MODE 0x00010043
+#define IID_ECHO_CANCELLER_NOISE_SUPPRESSOR_ENABLE 0x00010044
+#define IID_ECHO_CANCELLER_PARAMETERS 0x00010045
+#define IID_ECHO_CANCELLER_NEXTGEN_NB_PARAMETERS 0x00010046
+#define IID_ECHO_CANCELLER_NEXTGEN_WB_PARAMETERS 0x00010047
+#define IID_FLUENCE_PARAMETERS 0x00010048
+#define IID_AFE_VOLUME_CONTROL 0x00010049
+#define IID_GAIN 0x0001004A
+#define IID_VOICE_FIR_FILTER 0x0001004B
+#define IID_VOICE_IIR_FILTER 0x0001004C
+#define IID_AGC 0x0001004E
+#define IID_AVC 0x0001004F
+#define ABID_SIDETONE_GAIN 0x00010050
+#define ABID_TX_VOICE_GAIN 0x00010051
+#define ABID_TX_DTMF_GAIN 0x00010052
+#define ABID_CODEC_TX_GAIN 0x00010053
+#define ABID_HSSD 0x00010054
+#define ABID_TX_AGC 0x00010055
+#define ABID_TX_VOICE_FIR 0x00010056
+#define ABID_TX_VOICE_IIR 0x00010057
+#define ABID_ECHO_CANCELLER 0x00010058
+#define ABID_ECHO_CANCELLER_NB_LVHF 0x00010059
+#define ABID_ECHO_CANCELLER_WB_LVHF 0x0001005A
+#define ABID_FLUENCE 0x0001005B
+#define ABID_CODEC_RX_GAIN 0x0001005C
+#define ABID_RX_DBM_OFFSET 0x0001005D
+#define ABID_RX_AGC 0x0001005E
+#define ABID_AVC 0x0001005F
+#define ABID_RX_VOICE_FIR 0x00010060
+#define ABID_RX_VOICE_IIR 0x00010061
+#define ABID_AFE_VOL_CTRL 0x00010067
+
+
+/* AUDIO IDs */
+#define ABID_AUDIO_AGC_TX 0x00010068
+#define ABID_AUDIO_NS_TX 0x00010069
+#define ABID_VOICE_NS 0x0001006A
+#define ABID_AUDIO_IIR_TX 0x0001006B
+#define ABID_AUDIO_IIR_RX 0x0001006C
+#define ABID_AUDIO_MBADRC_RX 0x0001006E
+#define ABID_AUDIO_QAFX_RX 0x0001006F
+#define ABID_AUDIO_QCONCERT_RX 0x00010070
+#define ABID_AUDIO_STF_RX 0x00010071
+#define ABID_AUDIO_CALIBRATION_GAIN_RX 0x00011162
+#define ABID_AUDIO_CALIBRATION_GAIN_TX 0x00011149
+#define ABID_AUDIO_PBE_RX 0x00011197
+#define ABID_AUDIO_RMC_TX 0x00011226
+#define ABID_AUDIO_FLUENCE_TX 0x00011244
+
+
+#define IID_AUDIO_AGC_PARAMETERS 0x0001007E
+#define IID_NS_PARAMETERS 0x00010072
+#define IID_AUDIO_IIR_COEFF 0x00010073
+#define IID_MBADRC_EXT_BUFF 0x00010075
+#define IID_MBADRC_BAND_CONFIG 0x00010076
+#define IID_MBADRC_PARAMETERS 0x00010077
+#define IID_QAFX_PARAMETERS 0x00010079
+#define IID_QCONCERT_PARAMETERS 0x0001007A
+#define IID_STF_COEFF 0x0001007B
+#define IID_AUDIO_CALIBRATION_GAIN_RX 0x00011163
+#define IID_AUDIO_CALIBRATION_GAIN_TX 0x00011171
+#define IID_PBE_CONFIG_PARAMETERS 0x00011198
+#define IID_AUDIO_PBE_RX_ENABLE_FLAG 0x00011199
+#define IID_AUDIO_RMC_PARAM 0x00011227
+#define IID_AUDIO_FLUENCE_TX 0x00011245
+
+
+#define TOPID_RX_TOPOLOGY_1 0x00010062
+#define TOPID_TX_TOPOLOGY_1 0x00010063
+#define AFERID_INT_SINK 0x00010065
+#define AFERID_INT_SOURCE 0x00010066
+#define AFERID_NO_SINK 0x00000000
+#define AFERID_NULL_SINK 0x0108ea92
+
+
+struct acdb_cmd_install_device {
+ u32 command_id;
+ u32 device_id;
+ u32 topology_id;
+ u32 afe_routing_id;
+ u32 cad_routing_id; /* see "Sample Rate Bit Mask" below */
+ u32 sample_rate_mask;
+
+ /* represents device direction: Tx, Rx (aux pga - loopback) */
+ u8 device_type;
+ u8 channel_config; /* Mono or Stereo */
+ u32 adie_codec_path_id;
+};
+
+
+struct acdb_cmd_get_device_capabilities {
+ u32 command_id;
+ u32 total_bytes; /* Length in bytes allocated for buffer */
+ u32 *phys_buf; /* Physical Address of data */
+};
+
+
+struct acdb_cmd_get_device_info {
+ u32 command_id;
+ u32 device_id;
+ u32 total_bytes; /* Length in bytes allocated for buffer */
+ u32 *phys_buf; /* Physical Address of data */
+};
+
+struct acdb_cmd_device {
+ u32 command_id;
+ u32 device_id;
+ u32 network_id;
+ u32 sample_rate_id; /* Actual sample rate value */
+ u32 interface_id; /* See interface id's above */
+ u32 algorithm_block_id; /* See enumerations above */
+ u32 total_bytes; /* Length in bytes used by buffer */
+ u32 *phys_buf; /* Physical Address of data */
+};
+
+struct acdb_cmd_get_device_table {
+ u32 command_id;
+ u32 device_id;
+ u32 network_id;
+ u32 sample_rate_id; /* Actual sample rate value */
+ u32 total_bytes; /* Length in bytes used by buffer */
+ u32 *phys_buf; /* Physical Address of data */
+};
+
+struct acdb_result {
+ /* This field is populated in response to the */
+ /* ACDB_GET_DEVICE_CAPABILITIES command and indicates the total */
+ /* devices whose capabilities are copied to the physical memory. */
+ u32 total_devices;
+ u32 *buf; /* Physical Address of data */
+ u32 used_bytes; /* The size in bytes of the data */
+ u32 result; /* See ACDB Error codes above */
+};
+
+struct acdb_device_capability {
+ u32 device_id;
+ u32 sample_rate_mask; /* See "Sample Rate Bit Mask" below */
+};
+
+struct acdb_dev_info {
+ u32 cad_routing_id;
+ u32 sample_rate_mask; /* See "Sample Rate Bit Mask" below */
+ u32 adsp_device_id; /* QDSP6 device ID */
+ u32 device_type; /* Tx, Rx (aux pga - loopback) */
+ u32 channel_config; /* Mono or Stereo */
+ s32 min_volume; /* Min volume (mB) */
+ s32 max_volume; /* Max volume (mB) */
+};
+
+/*structure is used to intialize ACDB software on modem
+based on adie type detected*/
+struct acdb_cmd_init_adie {
+ u32 command_id;
+ u32 adie_type;
+};
+
+#define ACDB_CURRENT_ADIE_MODE_UNKNOWN 0
+#define ACDB_CURRENT_ADIE_MODE_TIMPANI 1
+#define ACDB_CURRENT_ADIE_MODE_MARIMBA 2
+
+/* Sample Rate Bit Mask */
+
+/* AUX PGA devices will have a sample rate mask of 0xFFFFFFFF */
+/* 8kHz 0x00000001 */
+/* 11.025kHz 0x00000002 */
+/* 12kHz 0x00000004 */
+/* 16kHz 0x00000008 */
+/* 22.5kHz 0x00000010 */
+/* 24kHz 0x00000020 */
+/* 32kHz 0x00000040 */
+/* 44.1kHz 0x00000080 */
+/* 48kHz 0x00000100 */
+
+
+/* Device type enumeration */
+enum {
+ RX_DEVICE = 1,
+ TX_DEVICE,
+ AUXPGA_DEVICE,
+ DEVICE_TYPE_MAX
+};
+
+#ifdef CONFIG_DEBUG_FS
+/*These are ABID used for RTC*/
+#define ABID_AUDIO_RTC_MBADRC_RX 0x0001118A
+#define ABID_AUDIO_RTC_VOLUME_PAN_RX 0x0001118C
+#define ABID_AUDIO_RTC_SPA 0x0001118E
+#define ABID_AUDIO_RTC_EQUALIZER_PARAMETERS 0x0001119F
+
+/*These are IID used for RTC*/
+#define IID_AUDIO_RTC_MBADRC_PARAMETERS 0x0001118B
+#define IID_AUDIO_RTC_VOLUME_PAN_PARAMETERS 0x0001118D
+#define IID_AUDIO_RTC_SPA_PARAMETERS 0x0001118F
+#define IID_AUDIO_RTC_EQUALIZER_PARAMETERS 0x0001119E
+#define IID_AUDIO_RTC_AGC_PARAMETERS 0x000111A7
+#define IID_AUDIO_RTC_TX_IIR_COEFF 0x000111A8
+
+#endif
+
+
+#endif
+
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/audio_acdb_def.h b/arch/arm/mach-msm/include/mach/qdsp5/audio_acdb_def.h
new file mode 100644
index 0000000..e1fc0cd
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/qdsp5/audio_acdb_def.h
@@ -0,0 +1,51 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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 _MACH_QDSP5_V2_AUDIO_ACDB_DEF_H
+#define _MACH_QDSP5_V2_AUDIO_ACDB_DEF_H
+
+/* Define ACDB device ID */
+#define ACDB_ID_HANDSET_SPKR 1
+#define ACDB_ID_HANDSET_MIC 2
+#define ACDB_ID_HEADSET_MIC 3
+#define ACDB_ID_HEADSET_SPKR_MONO 4
+#define ACDB_ID_HEADSET_SPKR_STEREO 5
+#define ACDB_ID_SPKR_PHONE_MIC 6
+#define ACDB_ID_SPKR_PHONE_MONO 7
+#define ACDB_ID_SPKR_PHONE_STEREO 8
+#define ACDB_ID_BT_SCO_MIC 9
+#define ACDB_ID_BT_SCO_SPKR 0x0A
+#define ACDB_ID_BT_A2DP_SPKR 0x0B
+#define ACDB_ID_BT_A2DP_TX 0x10
+#define ACDB_ID_TTY_HEADSET_MIC 0x0C
+#define ACDB_ID_TTY_HEADSET_SPKR 0x0D
+#define ACDB_ID_HEADSET_MONO_PLUS_SPKR_MONO_RX 0x11
+#define ACDB_ID_HEADSET_STEREO_PLUS_SPKR_STEREO_RX 0x14
+#define ACDB_ID_FM_TX_LOOPBACK 0x17
+#define ACDB_ID_FM_TX 0x18
+#define ACDB_ID_LP_FM_SPKR_PHONE_STEREO_RX 0x19
+#define ACDB_ID_LP_FM_HEADSET_SPKR_STEREO_RX 0x1A
+#define ACDB_ID_I2S_RX 0x20
+#define ACDB_ID_SPKR_PHONE_MIC_BROADSIDE 0x2B
+#define ACDB_ID_HANDSET_MIC_BROADSIDE 0x2C
+#define ACDB_ID_SPKR_PHONE_MIC_ENDFIRE 0x2D
+#define ACDB_ID_HANDSET_MIC_ENDFIRE 0x2E
+#define ACDB_ID_I2S_TX 0x30
+#define ACDB_ID_HDMI 0x40
+#define ACDB_ID_FM_RX 0x4F
+/*Replace the max device ID,if any new device is added Specific to RTC only*/
+#define ACDB_ID_MAX ACDB_ID_FM_RX
+
+/* ID used for virtual devices */
+#define PSEUDO_ACDB_ID 0xFFFF
+
+#endif /* _MACH_QDSP5_V2_AUDIO_ACDB_DEF_H */
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/audio_acdbi.h b/arch/arm/mach-msm/include/mach/qdsp5/audio_acdbi.h
new file mode 100644
index 0000000..5bad4fa
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/qdsp5/audio_acdbi.h
@@ -0,0 +1,132 @@
+/* Copyright (c) 2012 Code Aurora Forum. 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 _MACH_QDSP5_V2_AUDIO_ACDBI_H
+#define _MACH_QDSP5_V2_AUDIO_ACDBI_H
+
+#define DBOR_SIGNATURE 0x524F4244
+
+void acdb_rtc_set_err(u32 err_code);
+
+
+struct header {
+ u32 dbor_signature;
+ u32 abid;
+ u32 iid;
+ u32 data_len;
+};
+
+enum {
+ ACDB_AGC_BLOCK = 197,
+ ACDB_IIR_BLOCK = 245,
+ ACDB_MBADRC_BLOCK = 343
+};
+
+/* Structure to query for acdb parameter */
+struct acdb_get_block {
+ u32 acdb_id;
+ u32 sample_rate_id; /* Actual sample rate value */
+ u32 interface_id; /* Interface id's */
+ u32 algorithm_block_id; /* Algorithm block id */
+ u32 total_bytes; /* Length in bytes used by buffer for
+ configuration */
+ u32 *buf_ptr; /* Address for storing configuration
+ data */
+};
+
+struct acdb_agc_block {
+ u16 enable_status;
+ u16 comp_rlink_static_gain;
+ u16 comp_rlink_aig_flag;
+ u16 exp_rlink_threshold;
+ u16 exp_rlink_slope;
+ u16 comp_rlink_threshold;
+ u16 comp_rlink_slope;
+ u16 comp_rlink_aig_attack_k;
+ u16 comp_rlink_aig_leak_down;
+ u16 comp_rlink_aig_leak_up;
+ u16 comp_rlink_aig_max;
+ u16 comp_rlink_aig_min;
+ u16 comp_rlink_aig_release_k;
+ u16 comp_rlink_aig_sm_leak_rate_fast;
+ u16 comp_rlink_aig_sm_leak_rate_slow;
+ u16 comp_rlink_attack_k_msw;
+ u16 comp_rlink_attack_k_lsw;
+ u16 comp_rlink_delay;
+ u16 comp_rlink_release_k_msw;
+ u16 comp_rlink_release_k_lsw;
+ u16 comp_rlink_rms_trav;
+};
+
+
+struct iir_coeff_type {
+ u16 b0_lo;
+ u16 b0_hi;
+ u16 b1_lo;
+ u16 b1_hi;
+ u16 b2_lo;
+ u16 b2_hi;
+};
+
+struct iir_coeff_stage_a {
+ u16 a1_lo;
+ u16 a1_hi;
+ u16 a2_lo;
+ u16 a2_hi;
+};
+
+struct acdb_iir_block {
+ u16 enable_flag;
+ u16 stage_count;
+ struct iir_coeff_type stages[4];
+ struct iir_coeff_stage_a stages_a[4];
+ u16 shift_factor[4];
+ u16 pan[4];
+};
+
+struct mbadrc_band_config_type {
+ u16 mbadrc_sub_band_enable;
+ u16 mbadrc_sub_mute;
+ u16 mbadrc_comp_rms_tav;
+ u16 mbadrc_comp_threshold;
+ u16 mbadrc_comp_slop;
+ u16 mbadrc_comp_attack_msw;
+ u16 mbadrc_comp_attack_lsw;
+ u16 mbadrc_comp_release_msw;
+ u16 mbadrc_comp_release_lsw;
+ u16 mbadrc_make_up_gain;
+};
+
+struct mbadrc_parameter {
+ u16 mbadrc_enable;
+ u16 mbadrc_num_bands;
+ u16 mbadrc_down_sample_level;
+ u16 mbadrc_delay;
+};
+
+struct acdb_mbadrc_block {
+ u16 ext_buf[196];
+ struct mbadrc_band_config_type band_config[5];
+ struct mbadrc_parameter parameters;
+};
+
+struct acdb_ns_tx_block {
+ unsigned short ec_mode_new;
+ unsigned short dens_gamma_n;
+ unsigned short dens_nfe_block_size;
+ unsigned short dens_limit_ns;
+ unsigned short dens_limit_ns_d;
+ unsigned short wb_gamma_e;
+ unsigned short wb_gamma_n;
+};
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpp.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpp.h
new file mode 100644
index 0000000..bbd82a0
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpp.h
@@ -0,0 +1,93 @@
+/*arch/arm/mach-msm/qdsp5audpp.h
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Copyright (c) 2012, Code Aurora Forum. 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 _MACH_QDSP5_AUDPP_H
+#define _MACH_QDSP5_AUDPP_H
+
+#include <mach/qdsp5/qdsp5audppcmdi.h>
+
+typedef void (*audpp_event_func)(void *private, unsigned id, uint16_t *msg);
+
+/* worst case delay of 1sec for response */
+#define MSM_AUD_DECODER_WAIT_MS 1000
+#define MSM_AUD_MODE_TUNNEL 0x00000100
+#define MSM_AUD_MODE_NONTUNNEL 0x00000200
+#define MSM_AUD_DECODER_MASK 0x0000FFFF
+#define MSM_AUD_OP_MASK 0xFFFF0000
+
+/*Playback mode*/
+#define NON_TUNNEL_MODE_PLAYBACK 1
+#define TUNNEL_MODE_PLAYBACK 0
+
+enum msm_aud_decoder_state {
+ MSM_AUD_DECODER_STATE_NONE = 0,
+ MSM_AUD_DECODER_STATE_FAILURE = 1,
+ MSM_AUD_DECODER_STATE_SUCCESS = 2,
+ MSM_AUD_DECODER_STATE_CLOSE = 3,
+};
+
+int audpp_adec_alloc(unsigned dec_attrb, const char **module_name,
+ unsigned *queueid);
+void audpp_adec_free(int decid);
+
+struct audpp_event_callback {
+ audpp_event_func fn;
+ void *private;
+};
+
+int audpp_register_event_callback(struct audpp_event_callback *eh);
+int audpp_unregister_event_callback(struct audpp_event_callback *eh);
+int is_audpp_enable(void);
+
+int audpp_enable(int id, audpp_event_func func, void *private);
+void audpp_disable(int id, void *private);
+
+int audpp_send_queue1(void *cmd, unsigned len);
+int audpp_send_queue2(void *cmd, unsigned len);
+int audpp_send_queue3(void *cmd, unsigned len);
+
+int audpp_set_volume_and_pan(unsigned id, unsigned volume, int pan);
+int audpp_pause(unsigned id, int pause);
+int audpp_flush(unsigned id);
+void audpp_avsync(int id, unsigned rate);
+unsigned audpp_avsync_sample_count(int id);
+unsigned audpp_avsync_byte_count(int id);
+int audpp_dsp_set_mbadrc(unsigned id, unsigned enable,
+ audpp_cmd_cfg_object_params_mbadrc *mbadrc);
+int audpp_dsp_set_eq(unsigned id, unsigned enable,
+ audpp_cmd_cfg_object_params_eqalizer *eq);
+int audpp_dsp_set_rx_iir(unsigned id, unsigned enable,
+ audpp_cmd_cfg_object_params_pcm *iir);
+
+int audpp_dsp_set_rx_srs_trumedia_g
+ (struct audpp_cmd_cfg_object_params_srstm_g *srstm);
+int audpp_dsp_set_rx_srs_trumedia_w
+ (struct audpp_cmd_cfg_object_params_srstm_w *srstm);
+int audpp_dsp_set_rx_srs_trumedia_c
+ (struct audpp_cmd_cfg_object_params_srstm_c *srstm);
+int audpp_dsp_set_rx_srs_trumedia_h
+ (struct audpp_cmd_cfg_object_params_srstm_h *srstm);
+int audpp_dsp_set_rx_srs_trumedia_p
+ (struct audpp_cmd_cfg_object_params_srstm_p *srstm);
+int audpp_dsp_set_rx_srs_trumedia_l
+ (struct audpp_cmd_cfg_object_params_srstm_l *srstm);
+
+int audpp_dsp_set_vol_pan(unsigned id,
+ audpp_cmd_cfg_object_params_volume *vol_pan);
+int audpp_dsp_set_qconcert_plus(unsigned id, unsigned enable,
+ audpp_cmd_cfg_object_params_qconcert *qconcert_plus);
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppcmdi.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppcmdi.h
index 3115299..de30c65 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppcmdi.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppcmdi.h
@@ -530,6 +530,18 @@
unsigned short arm_to_dsp_buf_len;
} __attribute__((packed)) audpp_cmd_pcm_intf_send_buffer;
+#define AUDPP_CMD_PP_FEAT_QUERY_PARAMS 0x0003
+
+struct rtc_audpp_read_data {
+ unsigned short cmd_id;
+ unsigned short obj_id;
+ unsigned short feature_id;
+ unsigned short extbufsizemsw;
+ unsigned short extbufsizelsw;
+ unsigned short extpart;
+ unsigned short extbufstartmsw;
+ unsigned short extbufstartlsw;
+} __packed ;
/*
* Commands Related to uPAudPPCmd3Queue
@@ -564,6 +576,8 @@
#define AUDPP_CMD_COMMON_CFG_UPDATE 0x8000
#define AUDPP_CMD_COMMON_CFG_DONT_UPDATE 0x0000
+#define AUDPP_CMD_COPP_STREAM 0x0006
+
typedef struct {
unsigned short cmd_id;
unsigned short obj0_cfg;
@@ -580,6 +594,7 @@
* Command Structure to configure post processing params (Volume)
*/
+#define AUDPP_CMD_VOLUME_PAN 0
#define AUDPP_CMD_CFG_OBJECT_PARAMS_VOLUME_LEN \
sizeof(audpp_cmd_cfg_object_params_volume)
@@ -645,6 +660,7 @@
pan pan_filter[4];
} __attribute__((packed)) filter_4;
+#define AUDPP_CMD_IIR_TUNING_FILTER 1
#define AUDPP_CMD_CFG_OBJECT_PARAMS_PCM_LEN \
sizeof(audpp_cmd_cfg_object_params_pcm)
@@ -666,6 +682,7 @@
* Command Structure to configure post processing parameters (equalizer)
*/
+#define AUDPP_CMD_EQUALIZER 2
#define AUDPP_CMD_CFG_OBJECT_PARAMS_EQALIZER_LEN \
sizeof(audpp_cmd_cfg_object_params_eqalizer)
@@ -787,6 +804,7 @@
* Command Structure to configure post processing parameters (ADRC)
*/
+#define AUDPP_CMD_ADRC 3
#define AUDPP_CMD_CFG_OBJECT_PARAMS_ADRC_LEN \
sizeof(audpp_cmd_cfg_object_params_adrc)
@@ -794,6 +812,7 @@
#define AUDPP_CMD_ADRC_FLAG_DIS 0x0000
#define AUDPP_CMD_ADRC_FLAG_ENA -1
+#define AUDPP_CMD_MBADRC 10
#define AUDPP_MAX_MBADRC_BANDS 5
#define AUDPP_MBADRC_EXTERNAL_BUF_SIZE 196
@@ -839,6 +858,7 @@
* Command Structure to configure post processing parameters(Spectrum Analizer)
*/
+#define AUDPP_CMD_SPECTROGRAM 4
#define AUDPP_CMD_CFG_OBJECT_PARAMS_SPECTRAM_LEN \
sizeof(audpp_cmd_cfg_object_params_spectram)
@@ -853,6 +873,7 @@
* Command Structure to configure post processing parameters (QConcert)
*/
+#define AUDPP_CMD_QCONCERT 5
#define AUDPP_CMD_CFG_OBJECT_PARAMS_QCONCERT_LEN \
sizeof(audpp_cmd_cfg_object_params_qconcert)
@@ -899,6 +920,7 @@
* Command Structure to configure post processing parameters (Side Chain)
*/
+#define AUDPP_CMD_SIDECHAIN_TUNING_FILTER 6
#define AUDPP_CMD_CFG_OBJECT_PARAMS_SIDECHAIN_LEN \
sizeof(audpp_cmd_cfg_object_params_sidechain)
@@ -923,6 +945,7 @@
* Command Structure to configure post processing parameters (QAFX)
*/
+#define AUDPP_CMD_QAFX 8
#define AUDPP_CMD_CFG_OBJECT_PARAMS_QAFX_LEN \
sizeof(audpp_cmd_cfg_object_params_qafx)
@@ -1046,6 +1069,8 @@
audpp_cmd_cfg_object_params_common common;
unsigned short v[SRS_PARAMS_MAX_L];
} __packed;
+#define AUDPP_CMD_SAMPLING_FREQUENCY 7
+#define AUDPP_CMD_QRUMBLE 9
#endif /* QDSP5AUDPPCMDI_H */
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppmsg.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppmsg.h
index 0ba8261..fef4c35 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppmsg.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audppmsg.h
@@ -2,29 +2,29 @@
#define QDSP5AUDPPMSG_H
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
-
- Q D S P 5 A U D I O P O S T P R O C E S S I N G M S G
-
-GENERAL DESCRIPTION
- Messages sent by AUDPPTASK to ARM
-
-REFERENCES
- None
-
-EXTERNALIZED FUNCTIONS
- None
-
-Copyright (c) 1992-2009, Code Aurora Forum. 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.
-
+*
+* Q D S P 5 A U D I O P O S T P R O C E S S I N G M S G
+*
+* GENERAL DESCRIPTION
+* Messages sent by AUDPPTASK to ARM
+*
+* REFERENCES
+* None
+*
+* EXTERNALIZED FUNCTIONS
+* None
+*
+* Copyright (c) 1992-2009, 2012 Code Aurora Forum. 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.
+*
*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
/*===========================================================================
@@ -318,4 +318,5 @@
#define ADSP_MESSAGE_ID 0xFFFF
+#define AUDPP_MSG_FEAT_QUERY_DM_DONE 0x000b
#endif /* QDSP5AUDPPMSG_H */
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproc.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproc.h
index 234c4ac..5c7c5dc 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproc.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -25,9 +25,49 @@
#define MSM_ADSP_ENC_MODE_TUNNEL 24
#define MSM_ADSP_ENC_MODE_NON_TUNNEL 25
+/* event callback routine prototype*/
+typedef void (*audpreproc_event_func)(void *private, unsigned id, void *msg);
+
+struct audpreproc_event_callback {
+ audpreproc_event_func fn;
+ void *private;
+};
+
+/*holds audrec information*/
+struct audrec_session_info {
+ int session_id;
+ int sampling_freq;
+};
+
/* Exported common api's from audpreproc layer */
int audpreproc_aenc_alloc(unsigned enc_type, const char **module_name,
unsigned *queue_id);
void audpreproc_aenc_free(int enc_id);
+int audpreproc_enable(int enc_id, audpreproc_event_func func, void *private);
+void audpreproc_disable(int enc_id, void *private);
+
+int audpreproc_unregister_event_callback(struct audpreproc_event_callback *ecb);
+
+int audpreproc_register_event_callback(struct audpreproc_event_callback *ecb);
+
+int audpreproc_update_audrec_info(struct audrec_session_info
+ *audrec_session_info);
+int get_audrec_session_info(struct audrec_session_info *info);
+
+int audpreproc_dsp_set_agc(audpreproc_cmd_cfg_agc_params *agc,
+ unsigned len);
+int audpreproc_dsp_set_ns(audpreproc_cmd_cfg_ns_params *ns,
+ unsigned len);
+int audpreproc_dsp_set_iir(audpreproc_cmd_cfg_iir_tuning_filter_params *iir,
+ unsigned len);
+
+int audpreproc_send_preproccmdqueue(void *cmd, unsigned len);
+typedef void (*audrec_event_func)(void *private, unsigned id, uint16_t *msg);
+int audrectask_enable(unsigned enc_type, audrec_event_func func, void *private);
+void audrectask_disable(unsigned enc_type, void *private);
+
+int audrectask_send_cmdqueue(void *cmd, unsigned len);
+int audrectask_send_bitstreamqueue(void *cmd, unsigned len);
+
#endif /* QDSP5AUDPREPROC_H */
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproccmdi.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproccmdi.h
index 8efc916..a38d224 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproccmdi.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreproccmdi.h
@@ -2,30 +2,30 @@
#define QDSP5AUDPREPROCCMDI_H
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
-
- A U D I O P R E P R O C E S S I N G I N T E R N A L C O M M A N D S
-
-GENERAL DESCRIPTION
- This file contains defintions of format blocks of commands
- that are accepted by AUDPREPROC Task
-
-REFERENCES
- None
-
-EXTERNALIZED FUNCTIONS
- None
-
-Copyright (c) 1992-2009, Code Aurora Forum. 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.
-
+*
+* A U D I O P R E P R O C E S S I N G I N T E R N A L C O M M A N D S
+*
+* GENERAL DESCRIPTION
+* This file contains defintions of format blocks of commands
+* that are accepted by AUDPREPROC Task
+*
+* REFERENCES
+* None
+*
+* EXTERNALIZED FUNCTIONS
+* None
+*
+* Copyright (c) 1992-2009, 2012 Code Aurora Forum. 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.
+*
*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
/*===========================================================================
@@ -84,29 +84,29 @@
typedef struct {
unsigned short cmd_id;
unsigned short tx_agc_param_mask;
- unsigned short tx_agc_enable_flag;
- unsigned short static_gain;
- signed short adaptive_gain_flag;
- unsigned short expander_th;
- unsigned short expander_slope;
- unsigned short compressor_th;
- unsigned short compressor_slope;
- unsigned short param_mask;
- unsigned short aig_attackk;
- unsigned short aig_leak_down;
- unsigned short aig_leak_up;
- unsigned short aig_max;
- unsigned short aig_min;
- unsigned short aig_releasek;
- unsigned short aig_leakrate_fast;
- unsigned short aig_leakrate_slow;
- unsigned short attackk_msw;
- unsigned short attackk_lsw;
- unsigned short delay;
- unsigned short releasek_msw;
- unsigned short releasek_lsw;
- unsigned short rms_tav;
-} __attribute__((packed)) audpreproc_cmd_cfg_agc_params;
+ signed short tx_agc_enable_flag;
+ unsigned short comp_rlink_static_gain;
+ signed short comp_rlink_aig_flag;
+ unsigned short expander_rlink_th;
+ unsigned short expander_rlink_slope;
+ unsigned short compressor_rlink_th;
+ unsigned short compressor_rlink_slope;
+ unsigned short tx_adc_agc_param_mask;
+ unsigned short comp_rlink_aig_attackk;
+ unsigned short comp_rlink_aig_leak_down;
+ unsigned short comp_rlink_aig_leak_up;
+ unsigned short comp_rlink_aig_max;
+ unsigned short comp_rlink_aig_min;
+ unsigned short comp_rlink_aig_releasek;
+ unsigned short comp_rlink_aig_leakrate_fast;
+ unsigned short comp_rlink_aig_leakrate_slow;
+ unsigned short comp_rlink_attackk_msw;
+ unsigned short comp_rlink_attackk_lsw;
+ unsigned short comp_rlink_delay;
+ unsigned short comp_rlink_releasek_msw;
+ unsigned short comp_rlink_releasek_lsw;
+ unsigned short comp_rlink_rms_tav;
+} __packed audpreproc_cmd_cfg_agc_params;
/*
@@ -253,4 +253,16 @@
unsigned short channel_selected3;
} __attribute__((packed))audpreproc_cmd_cfg_iir_tuning_filter_params;
+#define AUDPREPROC_CMD_FEAT_QUERY_PARAMS 0x0004
+
+struct rtc_audpreproc_read_data {
+ unsigned short cmd_id;
+ unsigned short stream_id;
+ unsigned short feature_id;
+ unsigned short extbufsizemsw;
+ unsigned short extbufsizelsw;
+ unsigned short extpart;
+ unsigned short extbufstartmsw;
+ unsigned short extbufstartlsw;
+} __packed ;
#endif
diff --git a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreprocmsg.h b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreprocmsg.h
index 0696066..d299995 100644
--- a/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreprocmsg.h
+++ b/arch/arm/mach-msm/include/mach/qdsp5/qdsp5audpreprocmsg.h
@@ -2,30 +2,30 @@
#define QDSP5AUDPREPROCMSG_H
/*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*
-
- A U D I O P R E P R O C E S S I N G M E S S A G E S
-
-GENERAL DESCRIPTION
- This file contains defintions of format blocks of messages
- that are rcvd by AUDPREPROC Task
-
-REFERENCES
- None
-
-EXTERNALIZED FUNCTIONS
- None
-
-Copyright (c) 1992-2009, Code Aurora Forum. 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.
-
+*
+* A U D I O P R E P R O C E S S I N G M E S S A G E S
+*
+* GENERAL DESCRIPTION
+* This file contains defintions of format blocks of messages
+* that are rcvd by AUDPREPROC Task
+*
+* REFERENCES
+* None
+*
+* EXTERNALIZED FUNCTIONS
+* None
+*
+* Copyright (c) 1992-2009, 2012 Code Aurora Forum. 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.
+*
*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/
/*===========================================================================
@@ -82,4 +82,5 @@
unsigned short err_index;
} __attribute__((packed)) audpreproc_msg_error_msg_id;
+#define AUDPREPROC_MSG_FEAT_QUERY_DM_DONE 0x0003
#endif
diff --git a/arch/arm/mach-msm/include/mach/rpm-8930.h b/arch/arm/mach-msm/include/mach/rpm-8930.h
index 6fd9cf4..4ac9192 100644
--- a/arch/arm/mach-msm/include/mach/rpm-8930.h
+++ b/arch/arm/mach-msm/include/mach/rpm-8930.h
@@ -59,6 +59,8 @@
MSM_RPM_8930_SEL_MMSS_FABRIC_CFG_CLKMOD = 27,
MSM_RPM_8930_SEL_MMSS_FABRIC_CFG_IOCTL = 28,
MSM_RPM_8930_SEL_MM_FABRIC_ARB = 29,
+
+ /* PMIC 8038 */
MSM_RPM_8930_SEL_PM8038_S1 = 30,
MSM_RPM_8930_SEL_PM8038_S2 = 31,
MSM_RPM_8930_SEL_PM8038_S3 = 32,
@@ -96,12 +98,65 @@
MSM_RPM_8930_SEL_PM8038_CLK2 = 64,
MSM_RPM_8930_SEL_PM8038_LVS1 = 65,
MSM_RPM_8930_SEL_PM8038_LVS2 = 66,
+
+ /* PMIC 8917 */
+ MSM_RPM_8930_SEL_PM8917_S1 = 30,
+ MSM_RPM_8930_SEL_PM8917_S2 = 31,
+ MSM_RPM_8930_SEL_PM8917_S3 = 32,
+ MSM_RPM_8930_SEL_PM8917_S4 = 33,
+ MSM_RPM_8930_SEL_PM8917_S5 = 34,
+ MSM_RPM_8930_SEL_PM8917_S6 = 35,
+ MSM_RPM_8930_SEL_PM8917_S7 = 36,
+ MSM_RPM_8930_SEL_PM8917_S8 = 37,
+ MSM_RPM_8930_SEL_PM8917_L1 = 38,
+ MSM_RPM_8930_SEL_PM8917_L2 = 39,
+ MSM_RPM_8930_SEL_PM8917_L3 = 40,
+ MSM_RPM_8930_SEL_PM8917_L4 = 41,
+ MSM_RPM_8930_SEL_PM8917_L5 = 42,
+ MSM_RPM_8930_SEL_PM8917_L6 = 43,
+ MSM_RPM_8930_SEL_PM8917_L7 = 44,
+ MSM_RPM_8930_SEL_PM8917_L8 = 45,
+ MSM_RPM_8930_SEL_PM8917_L9 = 46,
+ MSM_RPM_8930_SEL_PM8917_L10 = 47,
+ MSM_RPM_8930_SEL_PM8917_L11 = 48,
+ MSM_RPM_8930_SEL_PM8917_L12 = 49,
+ MSM_RPM_8930_SEL_PM8917_L14 = 50,
+ MSM_RPM_8930_SEL_PM8917_L15 = 51,
+ MSM_RPM_8930_SEL_PM8917_L16 = 52,
+ MSM_RPM_8930_SEL_PM8917_L17 = 53,
+ MSM_RPM_8930_SEL_PM8917_L18 = 54,
+ MSM_RPM_8930_SEL_PM8917_L21 = 55,
+ MSM_RPM_8930_SEL_PM8917_L22 = 56,
+ MSM_RPM_8930_SEL_PM8917_L23 = 57,
+ MSM_RPM_8930_SEL_PM8917_L24 = 58,
+ MSM_RPM_8930_SEL_PM8917_L25 = 59,
+ MSM_RPM_8930_SEL_PM8917_L26 = 60,
+ MSM_RPM_8930_SEL_PM8917_L27 = 61,
+ MSM_RPM_8930_SEL_PM8917_L28 = 62,
+ MSM_RPM_8930_SEL_PM8917_L29 = 63,
+ MSM_RPM_8930_SEL_PM8917_L30 = 64,
+ MSM_RPM_8930_SEL_PM8917_L31 = 65,
+ MSM_RPM_8930_SEL_PM8917_L32 = 66,
+ MSM_RPM_8930_SEL_PM8917_L33 = 67,
+ MSM_RPM_8930_SEL_PM8917_L34 = 68,
+ MSM_RPM_8930_SEL_PM8917_L35 = 69,
+ MSM_RPM_8930_SEL_PM8917_L36 = 70,
+ MSM_RPM_8930_SEL_PM8917_CLK1 = 71,
+ MSM_RPM_8930_SEL_PM8917_CLK2 = 72,
+ MSM_RPM_8930_SEL_PM8917_LVS1 = 73,
+ MSM_RPM_8930_SEL_PM8917_LVS3 = 74,
+ MSM_RPM_8930_SEL_PM8917_LVS4 = 75,
+ MSM_RPM_8930_SEL_PM8917_LVS5 = 76,
+ MSM_RPM_8930_SEL_PM8917_LVS6 = 77,
+ MSM_RPM_8930_SEL_PM8917_LVS7 = 78,
+
MSM_RPM_8930_SEL_NCP = 80,
MSM_RPM_8930_SEL_CXO_BUFFERS = 81,
MSM_RPM_8930_SEL_USB_OTG_SWITCH = 82,
MSM_RPM_8930_SEL_HDMI_SWITCH = 83,
MSM_RPM_8930_SEL_DDR_DMM = 84,
MSM_RPM_8930_SEL_VOLTAGE_CORNER = 87,
+
MSM_RPM_8930_SEL_LAST = MSM_RPM_8930_SEL_VOLTAGE_CORNER,
};
@@ -163,6 +218,7 @@
MSM_RPM_8930_ID_MM_FABRIC_ARB_10 =
MSM_RPM_8930_ID_MM_FABRIC_ARB_0 + 10,
+ /* PMIC 8038 */
MSM_RPM_8930_ID_PM8038_S1_0 = 90,
MSM_RPM_8930_ID_PM8038_S1_1 = 91,
MSM_RPM_8930_ID_PM8038_S2_0 = 92,
@@ -235,13 +291,109 @@
MSM_RPM_8930_ID_PM8038_CLK2_1 = 159,
MSM_RPM_8930_ID_PM8038_LVS1 = 160,
MSM_RPM_8930_ID_PM8038_LVS2 = 161,
- MSM_RPM_8930_ID_NCP_0 = 162,
- MSM_RPM_8930_ID_NCP_1 = 163,
- MSM_RPM_8930_ID_CXO_BUFFERS = 164,
- MSM_RPM_8930_ID_USB_OTG_SWITCH = 165,
- MSM_RPM_8930_ID_HDMI_SWITCH = 166,
- MSM_RPM_8930_ID_QDSS_CLK = 167,
- MSM_RPM_8930_ID_VOLTAGE_CORNER = 168,
+
+ /* PMIC 8917 */
+ MSM_RPM_8930_ID_PM8917_S1_0 = 90,
+ MSM_RPM_8930_ID_PM8917_S1_1 = 91,
+ MSM_RPM_8930_ID_PM8917_S2_0 = 92,
+ MSM_RPM_8930_ID_PM8917_S2_1 = 93,
+ MSM_RPM_8930_ID_PM8917_S3_0 = 94,
+ MSM_RPM_8930_ID_PM8917_S3_1 = 95,
+ MSM_RPM_8930_ID_PM8917_S4_0 = 96,
+ MSM_RPM_8930_ID_PM8917_S4_1 = 97,
+ MSM_RPM_8930_ID_PM8917_S5_0 = 98,
+ MSM_RPM_8930_ID_PM8917_S5_1 = 99,
+ MSM_RPM_8930_ID_PM8917_S6_0 = 100,
+ MSM_RPM_8930_ID_PM8917_S6_1 = 101,
+ MSM_RPM_8930_ID_PM8917_S7_0 = 102,
+ MSM_RPM_8930_ID_PM8917_S7_1 = 103,
+ MSM_RPM_8930_ID_PM8917_S8_0 = 104,
+ MSM_RPM_8930_ID_PM8917_S8_1 = 105,
+ MSM_RPM_8930_ID_PM8917_L1_0 = 106,
+ MSM_RPM_8930_ID_PM8917_L1_1 = 107,
+ MSM_RPM_8930_ID_PM8917_L2_0 = 108,
+ MSM_RPM_8930_ID_PM8917_L2_1 = 109,
+ MSM_RPM_8930_ID_PM8917_L3_0 = 110,
+ MSM_RPM_8930_ID_PM8917_L3_1 = 111,
+ MSM_RPM_8930_ID_PM8917_L4_0 = 112,
+ MSM_RPM_8930_ID_PM8917_L4_1 = 113,
+ MSM_RPM_8930_ID_PM8917_L5_0 = 114,
+ MSM_RPM_8930_ID_PM8917_L5_1 = 115,
+ MSM_RPM_8930_ID_PM8917_L6_0 = 116,
+ MSM_RPM_8930_ID_PM8917_L6_1 = 117,
+ MSM_RPM_8930_ID_PM8917_L7_0 = 118,
+ MSM_RPM_8930_ID_PM8917_L7_1 = 119,
+ MSM_RPM_8930_ID_PM8917_L8_0 = 120,
+ MSM_RPM_8930_ID_PM8917_L8_1 = 121,
+ MSM_RPM_8930_ID_PM8917_L9_0 = 122,
+ MSM_RPM_8930_ID_PM8917_L9_1 = 123,
+ MSM_RPM_8930_ID_PM8917_L10_0 = 124,
+ MSM_RPM_8930_ID_PM8917_L10_1 = 125,
+ MSM_RPM_8930_ID_PM8917_L11_0 = 126,
+ MSM_RPM_8930_ID_PM8917_L11_1 = 127,
+ MSM_RPM_8930_ID_PM8917_L12_0 = 128,
+ MSM_RPM_8930_ID_PM8917_L12_1 = 129,
+ MSM_RPM_8930_ID_PM8917_L14_0 = 130,
+ MSM_RPM_8930_ID_PM8917_L14_1 = 131,
+ MSM_RPM_8930_ID_PM8917_L15_0 = 132,
+ MSM_RPM_8930_ID_PM8917_L15_1 = 133,
+ MSM_RPM_8930_ID_PM8917_L16_0 = 134,
+ MSM_RPM_8930_ID_PM8917_L16_1 = 135,
+ MSM_RPM_8930_ID_PM8917_L17_0 = 136,
+ MSM_RPM_8930_ID_PM8917_L17_1 = 137,
+ MSM_RPM_8930_ID_PM8917_L18_0 = 138,
+ MSM_RPM_8930_ID_PM8917_L18_1 = 139,
+ MSM_RPM_8930_ID_PM8917_L21_0 = 140,
+ MSM_RPM_8930_ID_PM8917_L21_1 = 141,
+ MSM_RPM_8930_ID_PM8917_L22_0 = 142,
+ MSM_RPM_8930_ID_PM8917_L22_1 = 143,
+ MSM_RPM_8930_ID_PM8917_L23_0 = 144,
+ MSM_RPM_8930_ID_PM8917_L23_1 = 145,
+ MSM_RPM_8930_ID_PM8917_L24_0 = 146,
+ MSM_RPM_8930_ID_PM8917_L24_1 = 147,
+ MSM_RPM_8930_ID_PM8917_L25_0 = 148,
+ MSM_RPM_8930_ID_PM8917_L25_1 = 149,
+ MSM_RPM_8930_ID_PM8917_L26_0 = 150,
+ MSM_RPM_8930_ID_PM8917_L26_1 = 151,
+ MSM_RPM_8930_ID_PM8917_L27_0 = 152,
+ MSM_RPM_8930_ID_PM8917_L27_1 = 153,
+ MSM_RPM_8930_ID_PM8917_L28_0 = 154,
+ MSM_RPM_8930_ID_PM8917_L28_1 = 155,
+ MSM_RPM_8930_ID_PM8917_L29_0 = 156,
+ MSM_RPM_8930_ID_PM8917_L29_1 = 157,
+ MSM_RPM_8930_ID_PM8917_L30_0 = 158,
+ MSM_RPM_8930_ID_PM8917_L30_1 = 159,
+ MSM_RPM_8930_ID_PM8917_L31_0 = 160,
+ MSM_RPM_8930_ID_PM8917_L31_1 = 161,
+ MSM_RPM_8930_ID_PM8917_L32_0 = 162,
+ MSM_RPM_8930_ID_PM8917_L32_1 = 163,
+ MSM_RPM_8930_ID_PM8917_L33_0 = 164,
+ MSM_RPM_8930_ID_PM8917_L33_1 = 165,
+ MSM_RPM_8930_ID_PM8917_L34_0 = 166,
+ MSM_RPM_8930_ID_PM8917_L34_1 = 167,
+ MSM_RPM_8930_ID_PM8917_L35_0 = 168,
+ MSM_RPM_8930_ID_PM8917_L35_1 = 169,
+ MSM_RPM_8930_ID_PM8917_L36_0 = 170,
+ MSM_RPM_8930_ID_PM8917_L36_1 = 171,
+ MSM_RPM_8930_ID_PM8917_CLK1_0 = 172,
+ MSM_RPM_8930_ID_PM8917_CLK1_1 = 173,
+ MSM_RPM_8930_ID_PM8917_CLK2_0 = 174,
+ MSM_RPM_8930_ID_PM8917_CLK2_1 = 175,
+ MSM_RPM_8930_ID_PM8917_LVS1 = 176,
+ MSM_RPM_8930_ID_PM8917_LVS3 = 177,
+ MSM_RPM_8930_ID_PM8917_LVS4 = 178,
+ MSM_RPM_8930_ID_PM8917_LVS5 = 179,
+ MSM_RPM_8930_ID_PM8917_LVS6 = 180,
+ MSM_RPM_8930_ID_PM8917_LVS7 = 181,
+
+ MSM_RPM_8930_ID_NCP_0 = 182,
+ MSM_RPM_8930_ID_NCP_1 = 183,
+ MSM_RPM_8930_ID_CXO_BUFFERS = 184,
+ MSM_RPM_8930_ID_USB_OTG_SWITCH = 185,
+ MSM_RPM_8930_ID_HDMI_SWITCH = 186,
+ MSM_RPM_8930_ID_QDSS_CLK = 187,
+ MSM_RPM_8930_ID_VOLTAGE_CORNER = 188,
+
MSM_RPM_8930_ID_LAST = MSM_RPM_8930_ID_VOLTAGE_CORNER,
};
@@ -278,6 +430,8 @@
MSM_RPM_8930_STATUS_ID_MMSS_FABRIC_CFG_CLKMOD = 28,
MSM_RPM_8930_STATUS_ID_MMSS_FABRIC_CFG_IOCTL = 29,
MSM_RPM_8930_STATUS_ID_MM_FABRIC_ARB = 30,
+
+ /* PMIC 8038 */
MSM_RPM_8930_STATUS_ID_PM8038_S1_0 = 31,
MSM_RPM_8930_STATUS_ID_PM8038_S1_1 = 32,
MSM_RPM_8930_STATUS_ID_PM8038_S2_0 = 33,
@@ -346,14 +500,119 @@
MSM_RPM_8930_STATUS_ID_PM8038_CLK2_1 = 100,
MSM_RPM_8930_STATUS_ID_PM8038_LVS1 = 101,
MSM_RPM_8930_STATUS_ID_PM8038_LVS2 = 102,
- MSM_RPM_8930_STATUS_ID_NCP_0 = 103,
- MSM_RPM_8930_STATUS_ID_NCP_1 = 104,
- MSM_RPM_8930_STATUS_ID_CXO_BUFFERS = 105,
- MSM_RPM_8930_STATUS_ID_USB_OTG_SWITCH = 106,
- MSM_RPM_8930_STATUS_ID_HDMI_SWITCH = 107,
- MSM_RPM_8930_STATUS_ID_QDSS_CLK = 108,
- MSM_RPM_8930_STATUS_ID_VOLTAGE_CORNER = 109,
- MSM_RPM_8930_STATUS_ID_LAST = MSM_RPM_8930_STATUS_ID_VOLTAGE_CORNER,
+ MSM_RPM_8930_STATUS_ID_PM8038_NCP_0 = 103,
+ MSM_RPM_8930_STATUS_ID_PM8038_NCP_1 = 104,
+ MSM_RPM_8930_STATUS_ID_PM8038_CXO_BUFFERS = 105,
+ MSM_RPM_8930_STATUS_ID_PM8038_USB_OTG_SWITCH = 106,
+ MSM_RPM_8930_STATUS_ID_PM8038_HDMI_SWITCH = 107,
+ MSM_RPM_8930_STATUS_ID_PM8038_QDSS_CLK = 108,
+ MSM_RPM_8930_STATUS_ID_PM8038_VOLTAGE_CORNER = 109,
+
+ MSM_RPM_8930_STATUS_ID_PM8038_LAST
+ = MSM_RPM_8930_STATUS_ID_PM8038_VOLTAGE_CORNER,
+
+ /* PMIC 8917 */
+ MSM_RPM_8930_STATUS_ID_PM8917_S1_0 = 31,
+ MSM_RPM_8930_STATUS_ID_PM8917_S1_1 = 32,
+ MSM_RPM_8930_STATUS_ID_PM8917_S2_0 = 33,
+ MSM_RPM_8930_STATUS_ID_PM8917_S2_1 = 34,
+ MSM_RPM_8930_STATUS_ID_PM8917_S3_0 = 35,
+ MSM_RPM_8930_STATUS_ID_PM8917_S3_1 = 36,
+ MSM_RPM_8930_STATUS_ID_PM8917_S4_0 = 37,
+ MSM_RPM_8930_STATUS_ID_PM8917_S4_1 = 38,
+ MSM_RPM_8930_STATUS_ID_PM8917_S5_0 = 39,
+ MSM_RPM_8930_STATUS_ID_PM8917_S5_1 = 40,
+ MSM_RPM_8930_STATUS_ID_PM8917_S6_0 = 41,
+ MSM_RPM_8930_STATUS_ID_PM8917_S6_1 = 42,
+ MSM_RPM_8930_STATUS_ID_PM8917_S7_0 = 43,
+ MSM_RPM_8930_STATUS_ID_PM8917_S7_1 = 44,
+ MSM_RPM_8930_STATUS_ID_PM8917_S8_0 = 45,
+ MSM_RPM_8930_STATUS_ID_PM8917_S8_1 = 46,
+ MSM_RPM_8930_STATUS_ID_PM8917_L1_0 = 47,
+ MSM_RPM_8930_STATUS_ID_PM8917_L1_1 = 48,
+ MSM_RPM_8930_STATUS_ID_PM8917_L2_0 = 49,
+ MSM_RPM_8930_STATUS_ID_PM8917_L2_1 = 50,
+ MSM_RPM_8930_STATUS_ID_PM8917_L3_0 = 51,
+ MSM_RPM_8930_STATUS_ID_PM8917_L3_1 = 52,
+ MSM_RPM_8930_STATUS_ID_PM8917_L4_0 = 53,
+ MSM_RPM_8930_STATUS_ID_PM8917_L4_1 = 54,
+ MSM_RPM_8930_STATUS_ID_PM8917_L5_0 = 55,
+ MSM_RPM_8930_STATUS_ID_PM8917_L5_1 = 56,
+ MSM_RPM_8930_STATUS_ID_PM8917_L6_0 = 57,
+ MSM_RPM_8930_STATUS_ID_PM8917_L6_1 = 58,
+ MSM_RPM_8930_STATUS_ID_PM8917_L7_0 = 59,
+ MSM_RPM_8930_STATUS_ID_PM8917_L7_1 = 60,
+ MSM_RPM_8930_STATUS_ID_PM8917_L8_0 = 61,
+ MSM_RPM_8930_STATUS_ID_PM8917_L8_1 = 62,
+ MSM_RPM_8930_STATUS_ID_PM8917_L9_0 = 63,
+ MSM_RPM_8930_STATUS_ID_PM8917_L9_1 = 64,
+ MSM_RPM_8930_STATUS_ID_PM8917_L10_0 = 65,
+ MSM_RPM_8930_STATUS_ID_PM8917_L10_1 = 66,
+ MSM_RPM_8930_STATUS_ID_PM8917_L11_0 = 67,
+ MSM_RPM_8930_STATUS_ID_PM8917_L11_1 = 68,
+ MSM_RPM_8930_STATUS_ID_PM8917_L12_0 = 69,
+ MSM_RPM_8930_STATUS_ID_PM8917_L12_1 = 70,
+ MSM_RPM_8930_STATUS_ID_PM8917_L14_0 = 71,
+ MSM_RPM_8930_STATUS_ID_PM8917_L14_1 = 72,
+ MSM_RPM_8930_STATUS_ID_PM8917_L15_0 = 73,
+ MSM_RPM_8930_STATUS_ID_PM8917_L15_1 = 74,
+ MSM_RPM_8930_STATUS_ID_PM8917_L16_0 = 75,
+ MSM_RPM_8930_STATUS_ID_PM8917_L16_1 = 76,
+ MSM_RPM_8930_STATUS_ID_PM8917_L17_0 = 77,
+ MSM_RPM_8930_STATUS_ID_PM8917_L17_1 = 78,
+ MSM_RPM_8930_STATUS_ID_PM8917_L18_0 = 79,
+ MSM_RPM_8930_STATUS_ID_PM8917_L18_1 = 80,
+ MSM_RPM_8930_STATUS_ID_PM8917_L21_0 = 81,
+ MSM_RPM_8930_STATUS_ID_PM8917_L21_1 = 82,
+ MSM_RPM_8930_STATUS_ID_PM8917_L22_0 = 83,
+ MSM_RPM_8930_STATUS_ID_PM8917_L22_1 = 84,
+ MSM_RPM_8930_STATUS_ID_PM8917_L23_0 = 85,
+ MSM_RPM_8930_STATUS_ID_PM8917_L23_1 = 86,
+ MSM_RPM_8930_STATUS_ID_PM8917_L24_0 = 87,
+ MSM_RPM_8930_STATUS_ID_PM8917_L24_1 = 88,
+ MSM_RPM_8930_STATUS_ID_PM8917_L25_0 = 89,
+ MSM_RPM_8930_STATUS_ID_PM8917_L25_1 = 90,
+ MSM_RPM_8930_STATUS_ID_PM8917_L26_0 = 91,
+ MSM_RPM_8930_STATUS_ID_PM8917_L26_1 = 92,
+ MSM_RPM_8930_STATUS_ID_PM8917_L27_0 = 93,
+ MSM_RPM_8930_STATUS_ID_PM8917_L27_1 = 94,
+ MSM_RPM_8930_STATUS_ID_PM8917_L28_0 = 95,
+ MSM_RPM_8930_STATUS_ID_PM8917_L28_1 = 96,
+ MSM_RPM_8930_STATUS_ID_PM8917_L29_0 = 97,
+ MSM_RPM_8930_STATUS_ID_PM8917_L29_1 = 98,
+ MSM_RPM_8930_STATUS_ID_PM8917_L30_0 = 99,
+ MSM_RPM_8930_STATUS_ID_PM8917_L30_1 = 100,
+ MSM_RPM_8930_STATUS_ID_PM8917_L31_0 = 101,
+ MSM_RPM_8930_STATUS_ID_PM8917_L31_1 = 102,
+ MSM_RPM_8930_STATUS_ID_PM8917_L32_0 = 103,
+ MSM_RPM_8930_STATUS_ID_PM8917_L32_1 = 104,
+ MSM_RPM_8930_STATUS_ID_PM8917_L33_0 = 105,
+ MSM_RPM_8930_STATUS_ID_PM8917_L33_1 = 106,
+ MSM_RPM_8930_STATUS_ID_PM8917_L34_0 = 107,
+ MSM_RPM_8930_STATUS_ID_PM8917_L34_1 = 108,
+ MSM_RPM_8930_STATUS_ID_PM8917_L35_0 = 109,
+ MSM_RPM_8930_STATUS_ID_PM8917_L35_1 = 110,
+ MSM_RPM_8930_STATUS_ID_PM8917_L36_0 = 111,
+ MSM_RPM_8930_STATUS_ID_PM8917_L36_1 = 112,
+ MSM_RPM_8930_STATUS_ID_PM8917_CLK1_0 = 113,
+ MSM_RPM_8930_STATUS_ID_PM8917_CLK1_1 = 114,
+ MSM_RPM_8930_STATUS_ID_PM8917_CLK2_0 = 115,
+ MSM_RPM_8930_STATUS_ID_PM8917_CLK2_1 = 116,
+ MSM_RPM_8930_STATUS_ID_PM8917_LVS1 = 117,
+ MSM_RPM_8930_STATUS_ID_PM8917_LVS3 = 118,
+ MSM_RPM_8930_STATUS_ID_PM8917_LVS4 = 119,
+ MSM_RPM_8930_STATUS_ID_PM8917_LVS5 = 120,
+ MSM_RPM_8930_STATUS_ID_PM8917_LVS6 = 121,
+ MSM_RPM_8930_STATUS_ID_PM8917_LVS7 = 122,
+ MSM_RPM_8930_STATUS_ID_PM8917_NCP_0 = 123,
+ MSM_RPM_8930_STATUS_ID_PM8917_NCP_1 = 124,
+ MSM_RPM_8930_STATUS_ID_PM8917_CXO_BUFFERS = 125,
+ MSM_RPM_8930_STATUS_ID_PM8917_USB_OTG_SWITCH = 126,
+ MSM_RPM_8930_STATUS_ID_PM8917_HDMI_SWITCH = 127,
+ MSM_RPM_8930_STATUS_ID_PM8917_QDSS_CLK = 128,
+ MSM_RPM_8930_STATUS_ID_PM8917_VOLTAGE_CORNER = 129,
+ MSM_RPM_8930_STATUS_ID_PM8917_PM8917_LAST
+ = MSM_RPM_8930_STATUS_ID_PM8917_VOLTAGE_CORNER,
};
#endif /* __ARCH_ARM_MACH_MSM_RPM_8930_H */
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h b/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h
index 47056a8..f8f53f6 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h
@@ -85,9 +85,10 @@
};
/**
- * enum rpm_vreg_id - RPM regulator ID numbers (both real and pin control)
+ * enum rpm_vreg_id_8930_pm8038 - RPM regulator ID numbers (both real and
+ * pin control) used with MSM8930 + PM8038
*/
-enum rpm_vreg_id_8930 {
+enum rpm_vreg_id_8930_pm8038 {
RPM_VREG_ID_PM8038_L1,
RPM_VREG_ID_PM8038_L2,
RPM_VREG_ID_PM8038_L3,
@@ -155,6 +156,109 @@
RPM_VREG_ID_PM8038_MAX = RPM_VREG_ID_PM8038_LVS2_PC,
};
+/**
+ * enum rpm_vreg_id_8930_pm8917 - RPM regulator ID numbers (both real and
+ * pin control) used with MSM8930 + PM8917
+ */
+enum rpm_vreg_id_8930_pm8917 {
+ RPM_VREG_ID_PM8917_L1,
+ RPM_VREG_ID_PM8917_L2,
+ RPM_VREG_ID_PM8917_L3,
+ RPM_VREG_ID_PM8917_L4,
+ RPM_VREG_ID_PM8917_L5,
+ RPM_VREG_ID_PM8917_L6,
+ RPM_VREG_ID_PM8917_L7,
+ RPM_VREG_ID_PM8917_L8,
+ RPM_VREG_ID_PM8917_L9,
+ RPM_VREG_ID_PM8917_L10,
+ RPM_VREG_ID_PM8917_L11,
+ RPM_VREG_ID_PM8917_L12,
+ RPM_VREG_ID_PM8917_L14,
+ RPM_VREG_ID_PM8917_L15,
+ RPM_VREG_ID_PM8917_L16,
+ RPM_VREG_ID_PM8917_L17,
+ RPM_VREG_ID_PM8917_L18,
+ RPM_VREG_ID_PM8917_L21,
+ RPM_VREG_ID_PM8917_L22,
+ RPM_VREG_ID_PM8917_L23,
+ RPM_VREG_ID_PM8917_L24,
+ RPM_VREG_ID_PM8917_L25,
+ RPM_VREG_ID_PM8917_L26,
+ RPM_VREG_ID_PM8917_L27,
+ RPM_VREG_ID_PM8917_L28,
+ RPM_VREG_ID_PM8917_L29,
+ RPM_VREG_ID_PM8917_L30,
+ RPM_VREG_ID_PM8917_L31,
+ RPM_VREG_ID_PM8917_L32,
+ RPM_VREG_ID_PM8917_L33,
+ RPM_VREG_ID_PM8917_L34,
+ RPM_VREG_ID_PM8917_L35,
+ RPM_VREG_ID_PM8917_L36,
+ RPM_VREG_ID_PM8917_S1,
+ RPM_VREG_ID_PM8917_S2,
+ RPM_VREG_ID_PM8917_S3,
+ RPM_VREG_ID_PM8917_S4,
+ RPM_VREG_ID_PM8917_S5,
+ RPM_VREG_ID_PM8917_S6,
+ RPM_VREG_ID_PM8917_S7,
+ RPM_VREG_ID_PM8917_S8,
+ RPM_VREG_ID_PM8917_LVS1,
+ RPM_VREG_ID_PM8917_LVS3,
+ RPM_VREG_ID_PM8917_LVS4,
+ RPM_VREG_ID_PM8917_LVS5,
+ RPM_VREG_ID_PM8917_LVS6,
+ RPM_VREG_ID_PM8917_LVS7,
+ RPM_VREG_ID_PM8917_USB_OTG,
+ RPM_VREG_ID_PM8917_VDD_DIG_CORNER,
+ RPM_VREG_ID_PM8917_MAX_REAL = RPM_VREG_ID_PM8917_VDD_DIG_CORNER,
+
+ /* The following are IDs for regulator devices to enable pin control. */
+ RPM_VREG_ID_PM8917_L1_PC,
+ RPM_VREG_ID_PM8917_L2_PC,
+ RPM_VREG_ID_PM8917_L3_PC,
+ RPM_VREG_ID_PM8917_L4_PC,
+ RPM_VREG_ID_PM8917_L5_PC,
+ RPM_VREG_ID_PM8917_L6_PC,
+ RPM_VREG_ID_PM8917_L7_PC,
+ RPM_VREG_ID_PM8917_L8_PC,
+ RPM_VREG_ID_PM8917_L9_PC,
+ RPM_VREG_ID_PM8917_L10_PC,
+ RPM_VREG_ID_PM8917_L11_PC,
+ RPM_VREG_ID_PM8917_L12_PC,
+ RPM_VREG_ID_PM8917_L14_PC,
+ RPM_VREG_ID_PM8917_L15_PC,
+ RPM_VREG_ID_PM8917_L16_PC,
+ RPM_VREG_ID_PM8917_L17_PC,
+ RPM_VREG_ID_PM8917_L18_PC,
+ RPM_VREG_ID_PM8917_L21_PC,
+ RPM_VREG_ID_PM8917_L22_PC,
+ RPM_VREG_ID_PM8917_L23_PC,
+
+ RPM_VREG_ID_PM8917_L29_PC,
+ RPM_VREG_ID_PM8917_L30_PC,
+ RPM_VREG_ID_PM8917_L31_PC,
+ RPM_VREG_ID_PM8917_L32_PC,
+ RPM_VREG_ID_PM8917_L33_PC,
+ RPM_VREG_ID_PM8917_L34_PC,
+ RPM_VREG_ID_PM8917_L35_PC,
+ RPM_VREG_ID_PM8917_L36_PC,
+ RPM_VREG_ID_PM8917_S1_PC,
+ RPM_VREG_ID_PM8917_S2_PC,
+ RPM_VREG_ID_PM8917_S3_PC,
+ RPM_VREG_ID_PM8917_S4_PC,
+
+ RPM_VREG_ID_PM8917_S7_PC,
+ RPM_VREG_ID_PM8917_S8_PC,
+ RPM_VREG_ID_PM8917_LVS1_PC,
+ RPM_VREG_ID_PM8917_LVS3_PC,
+ RPM_VREG_ID_PM8917_LVS4_PC,
+ RPM_VREG_ID_PM8917_LVS5_PC,
+ RPM_VREG_ID_PM8917_LVS6_PC,
+ RPM_VREG_ID_PM8917_LVS7_PC,
+
+ RPM_VREG_ID_PM8917_MAX = RPM_VREG_ID_PM8917_LVS7_PC,
+};
+
/* Minimum high power mode loads in uA. */
#define RPM_VREG_8930_LDO_5_HPM_MIN_LOAD 0
#define RPM_VREG_8930_LDO_50_HPM_MIN_LOAD 5000
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator.h b/arch/arm/mach-msm/include/mach/rpm-regulator.h
index d2ff2fe..f6e082d 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator.h
@@ -31,7 +31,8 @@
RPM_VREG_VERSION_8960,
RPM_VREG_VERSION_9615,
RPM_VREG_VERSION_8930,
- RPM_VREG_VERSION_MAX = RPM_VREG_VERSION_8930,
+ RPM_VREG_VERSION_8930_PM8917,
+ RPM_VREG_VERSION_MAX = RPM_VREG_VERSION_8930_PM8917,
};
#define RPM_VREG_PIN_CTRL_NONE 0x00
diff --git a/arch/arm/mach-msm/include/mach/rpm.h b/arch/arm/mach-msm/include/mach/rpm.h
index f6b9a6e..4ee1997 100644
--- a/arch/arm/mach-msm/include/mach/rpm.h
+++ b/arch/arm/mach-msm/include/mach/rpm.h
@@ -451,6 +451,100 @@
MSM_RPM_ID_PM8038_CLK2_1,
MSM_RPM_ID_PM8038_LVS1,
MSM_RPM_ID_PM8038_LVS2,
+
+ /* PM8917 specific */
+ MSM_RPM_ID_PM8917_S1_0,
+ MSM_RPM_ID_PM8917_S1_1,
+ MSM_RPM_ID_PM8917_S2_0,
+ MSM_RPM_ID_PM8917_S2_1,
+ MSM_RPM_ID_PM8917_S3_0,
+ MSM_RPM_ID_PM8917_S3_1,
+ MSM_RPM_ID_PM8917_S4_0,
+ MSM_RPM_ID_PM8917_S4_1,
+ MSM_RPM_ID_PM8917_S5_0,
+ MSM_RPM_ID_PM8917_S5_1,
+ MSM_RPM_ID_PM8917_S6_0,
+ MSM_RPM_ID_PM8917_S6_1,
+ MSM_RPM_ID_PM8917_S7_0,
+ MSM_RPM_ID_PM8917_S7_1,
+ MSM_RPM_ID_PM8917_S8_0,
+ MSM_RPM_ID_PM8917_S8_1,
+ MSM_RPM_ID_PM8917_L1_0,
+ MSM_RPM_ID_PM8917_L1_1,
+ MSM_RPM_ID_PM8917_L2_0,
+ MSM_RPM_ID_PM8917_L2_1,
+ MSM_RPM_ID_PM8917_L3_0,
+ MSM_RPM_ID_PM8917_L3_1,
+ MSM_RPM_ID_PM8917_L4_0,
+ MSM_RPM_ID_PM8917_L4_1,
+ MSM_RPM_ID_PM8917_L5_0,
+ MSM_RPM_ID_PM8917_L5_1,
+ MSM_RPM_ID_PM8917_L6_0,
+ MSM_RPM_ID_PM8917_L6_1,
+ MSM_RPM_ID_PM8917_L7_0,
+ MSM_RPM_ID_PM8917_L7_1,
+ MSM_RPM_ID_PM8917_L8_0,
+ MSM_RPM_ID_PM8917_L8_1,
+ MSM_RPM_ID_PM8917_L9_0,
+ MSM_RPM_ID_PM8917_L9_1,
+ MSM_RPM_ID_PM8917_L10_0,
+ MSM_RPM_ID_PM8917_L10_1,
+ MSM_RPM_ID_PM8917_L11_0,
+ MSM_RPM_ID_PM8917_L11_1,
+ MSM_RPM_ID_PM8917_L12_0,
+ MSM_RPM_ID_PM8917_L12_1,
+ MSM_RPM_ID_PM8917_L14_0,
+ MSM_RPM_ID_PM8917_L14_1,
+ MSM_RPM_ID_PM8917_L15_0,
+ MSM_RPM_ID_PM8917_L15_1,
+ MSM_RPM_ID_PM8917_L16_0,
+ MSM_RPM_ID_PM8917_L16_1,
+ MSM_RPM_ID_PM8917_L17_0,
+ MSM_RPM_ID_PM8917_L17_1,
+ MSM_RPM_ID_PM8917_L18_0,
+ MSM_RPM_ID_PM8917_L18_1,
+ MSM_RPM_ID_PM8917_L21_0,
+ MSM_RPM_ID_PM8917_L21_1,
+ MSM_RPM_ID_PM8917_L22_0,
+ MSM_RPM_ID_PM8917_L22_1,
+ MSM_RPM_ID_PM8917_L23_0,
+ MSM_RPM_ID_PM8917_L23_1,
+ MSM_RPM_ID_PM8917_L24_0,
+ MSM_RPM_ID_PM8917_L24_1,
+ MSM_RPM_ID_PM8917_L25_0,
+ MSM_RPM_ID_PM8917_L25_1,
+ MSM_RPM_ID_PM8917_L26_0,
+ MSM_RPM_ID_PM8917_L26_1,
+ MSM_RPM_ID_PM8917_L27_0,
+ MSM_RPM_ID_PM8917_L27_1,
+ MSM_RPM_ID_PM8917_L28_0,
+ MSM_RPM_ID_PM8917_L28_1,
+ MSM_RPM_ID_PM8917_L29_0,
+ MSM_RPM_ID_PM8917_L29_1,
+ MSM_RPM_ID_PM8917_L30_0,
+ MSM_RPM_ID_PM8917_L30_1,
+ MSM_RPM_ID_PM8917_L31_0,
+ MSM_RPM_ID_PM8917_L31_1,
+ MSM_RPM_ID_PM8917_L32_0,
+ MSM_RPM_ID_PM8917_L32_1,
+ MSM_RPM_ID_PM8917_L33_0,
+ MSM_RPM_ID_PM8917_L33_1,
+ MSM_RPM_ID_PM8917_L34_0,
+ MSM_RPM_ID_PM8917_L34_1,
+ MSM_RPM_ID_PM8917_L35_0,
+ MSM_RPM_ID_PM8917_L35_1,
+ MSM_RPM_ID_PM8917_L36_0,
+ MSM_RPM_ID_PM8917_L36_1,
+ MSM_RPM_ID_PM8917_CLK1_0,
+ MSM_RPM_ID_PM8917_CLK1_1,
+ MSM_RPM_ID_PM8917_CLK2_0,
+ MSM_RPM_ID_PM8917_CLK2_1,
+ MSM_RPM_ID_PM8917_LVS1,
+ MSM_RPM_ID_PM8917_LVS3,
+ MSM_RPM_ID_PM8917_LVS4,
+ MSM_RPM_ID_PM8917_LVS5,
+ MSM_RPM_ID_PM8917_LVS6,
+ MSM_RPM_ID_PM8917_LVS7,
MSM_RPM_ID_VOLTAGE_CORNER,
/* 8064 specific */
@@ -605,6 +699,29 @@
MSM_RPM_STATUS_ID_EBI1_CH1_RANGE,
MSM_RPM_STATUS_ID_QDSS_CLK,
+ /* 8930 aliases to simplify device mapping */
+ MSM_RPM_STATUS_ID_PM8038_NCP_0 = MSM_RPM_STATUS_ID_NCP_0,
+ MSM_RPM_STATUS_ID_PM8038_NCP_1 = MSM_RPM_STATUS_ID_NCP_1,
+ MSM_RPM_STATUS_ID_PM8038_CXO_BUFFERS
+ = MSM_RPM_STATUS_ID_CXO_BUFFERS,
+ MSM_RPM_STATUS_ID_PM8038_USB_OTG_SWITCH
+ = MSM_RPM_STATUS_ID_USB_OTG_SWITCH,
+ MSM_RPM_STATUS_ID_PM8038_HDMI_SWITCH
+ = MSM_RPM_STATUS_ID_HDMI_SWITCH,
+ MSM_RPM_STATUS_ID_PM8038_QDSS_CLK
+ = MSM_RPM_STATUS_ID_QDSS_CLK,
+
+ MSM_RPM_STATUS_ID_PM8917_NCP_0 = MSM_RPM_STATUS_ID_NCP_0,
+ MSM_RPM_STATUS_ID_PM8917_NCP_1 = MSM_RPM_STATUS_ID_NCP_1,
+ MSM_RPM_STATUS_ID_PM8917_CXO_BUFFERS
+ = MSM_RPM_STATUS_ID_CXO_BUFFERS,
+ MSM_RPM_STATUS_ID_PM8917_USB_OTG_SWITCH
+ = MSM_RPM_STATUS_ID_USB_OTG_SWITCH,
+ MSM_RPM_STATUS_ID_PM8917_HDMI_SWITCH
+ = MSM_RPM_STATUS_ID_HDMI_SWITCH,
+ MSM_RPM_STATUS_ID_PM8917_QDSS_CLK
+ = MSM_RPM_STATUS_ID_QDSS_CLK,
+
/* 8660 Specific */
MSM_RPM_STATUS_ID_PLL_4,
MSM_RPM_STATUS_ID_SMI_CLK,
@@ -817,7 +934,105 @@
MSM_RPM_STATUS_ID_PM8038_CLK2_1,
MSM_RPM_STATUS_ID_PM8038_LVS1,
MSM_RPM_STATUS_ID_PM8038_LVS2,
+
+ /* PMIC 8917 */
+ MSM_RPM_STATUS_ID_PM8917_S1_0,
+ MSM_RPM_STATUS_ID_PM8917_S1_1,
+ MSM_RPM_STATUS_ID_PM8917_S2_0,
+ MSM_RPM_STATUS_ID_PM8917_S2_1,
+ MSM_RPM_STATUS_ID_PM8917_S3_0,
+ MSM_RPM_STATUS_ID_PM8917_S3_1,
+ MSM_RPM_STATUS_ID_PM8917_S4_0,
+ MSM_RPM_STATUS_ID_PM8917_S4_1,
+ MSM_RPM_STATUS_ID_PM8917_S5_0,
+ MSM_RPM_STATUS_ID_PM8917_S5_1,
+ MSM_RPM_STATUS_ID_PM8917_S6_0,
+ MSM_RPM_STATUS_ID_PM8917_S6_1,
+ MSM_RPM_STATUS_ID_PM8917_S7_0,
+ MSM_RPM_STATUS_ID_PM8917_S7_1,
+ MSM_RPM_STATUS_ID_PM8917_S8_0,
+ MSM_RPM_STATUS_ID_PM8917_S8_1,
+ MSM_RPM_STATUS_ID_PM8917_L1_0,
+ MSM_RPM_STATUS_ID_PM8917_L1_1,
+ MSM_RPM_STATUS_ID_PM8917_L2_0,
+ MSM_RPM_STATUS_ID_PM8917_L2_1,
+ MSM_RPM_STATUS_ID_PM8917_L3_0,
+ MSM_RPM_STATUS_ID_PM8917_L3_1,
+ MSM_RPM_STATUS_ID_PM8917_L4_0,
+ MSM_RPM_STATUS_ID_PM8917_L4_1,
+ MSM_RPM_STATUS_ID_PM8917_L5_0,
+ MSM_RPM_STATUS_ID_PM8917_L5_1,
+ MSM_RPM_STATUS_ID_PM8917_L6_0,
+ MSM_RPM_STATUS_ID_PM8917_L6_1,
+ MSM_RPM_STATUS_ID_PM8917_L7_0,
+ MSM_RPM_STATUS_ID_PM8917_L7_1,
+ MSM_RPM_STATUS_ID_PM8917_L8_0,
+ MSM_RPM_STATUS_ID_PM8917_L8_1,
+ MSM_RPM_STATUS_ID_PM8917_L9_0,
+ MSM_RPM_STATUS_ID_PM8917_L9_1,
+ MSM_RPM_STATUS_ID_PM8917_L10_0,
+ MSM_RPM_STATUS_ID_PM8917_L10_1,
+ MSM_RPM_STATUS_ID_PM8917_L11_0,
+ MSM_RPM_STATUS_ID_PM8917_L11_1,
+ MSM_RPM_STATUS_ID_PM8917_L12_0,
+ MSM_RPM_STATUS_ID_PM8917_L12_1,
+ MSM_RPM_STATUS_ID_PM8917_L14_0,
+ MSM_RPM_STATUS_ID_PM8917_L14_1,
+ MSM_RPM_STATUS_ID_PM8917_L15_0,
+ MSM_RPM_STATUS_ID_PM8917_L15_1,
+ MSM_RPM_STATUS_ID_PM8917_L16_0,
+ MSM_RPM_STATUS_ID_PM8917_L16_1,
+ MSM_RPM_STATUS_ID_PM8917_L17_0,
+ MSM_RPM_STATUS_ID_PM8917_L17_1,
+ MSM_RPM_STATUS_ID_PM8917_L18_0,
+ MSM_RPM_STATUS_ID_PM8917_L18_1,
+ MSM_RPM_STATUS_ID_PM8917_L21_0,
+ MSM_RPM_STATUS_ID_PM8917_L21_1,
+ MSM_RPM_STATUS_ID_PM8917_L22_0,
+ MSM_RPM_STATUS_ID_PM8917_L22_1,
+ MSM_RPM_STATUS_ID_PM8917_L23_0,
+ MSM_RPM_STATUS_ID_PM8917_L23_1,
+ MSM_RPM_STATUS_ID_PM8917_L24_0,
+ MSM_RPM_STATUS_ID_PM8917_L24_1,
+ MSM_RPM_STATUS_ID_PM8917_L25_0,
+ MSM_RPM_STATUS_ID_PM8917_L25_1,
+ MSM_RPM_STATUS_ID_PM8917_L26_0,
+ MSM_RPM_STATUS_ID_PM8917_L26_1,
+ MSM_RPM_STATUS_ID_PM8917_L27_0,
+ MSM_RPM_STATUS_ID_PM8917_L27_1,
+ MSM_RPM_STATUS_ID_PM8917_L28_0,
+ MSM_RPM_STATUS_ID_PM8917_L28_1,
+ MSM_RPM_STATUS_ID_PM8917_L29_0,
+ MSM_RPM_STATUS_ID_PM8917_L29_1,
+ MSM_RPM_STATUS_ID_PM8917_L30_0,
+ MSM_RPM_STATUS_ID_PM8917_L30_1,
+ MSM_RPM_STATUS_ID_PM8917_L31_0,
+ MSM_RPM_STATUS_ID_PM8917_L31_1,
+ MSM_RPM_STATUS_ID_PM8917_L32_0,
+ MSM_RPM_STATUS_ID_PM8917_L32_1,
+ MSM_RPM_STATUS_ID_PM8917_L33_0,
+ MSM_RPM_STATUS_ID_PM8917_L33_1,
+ MSM_RPM_STATUS_ID_PM8917_L34_0,
+ MSM_RPM_STATUS_ID_PM8917_L34_1,
+ MSM_RPM_STATUS_ID_PM8917_L35_0,
+ MSM_RPM_STATUS_ID_PM8917_L35_1,
+ MSM_RPM_STATUS_ID_PM8917_L36_0,
+ MSM_RPM_STATUS_ID_PM8917_L36_1,
+ MSM_RPM_STATUS_ID_PM8917_CLK1_0,
+ MSM_RPM_STATUS_ID_PM8917_CLK1_1,
+ MSM_RPM_STATUS_ID_PM8917_CLK2_0,
+ MSM_RPM_STATUS_ID_PM8917_CLK2_1,
+ MSM_RPM_STATUS_ID_PM8917_LVS1,
+ MSM_RPM_STATUS_ID_PM8917_LVS3,
+ MSM_RPM_STATUS_ID_PM8917_LVS4,
+ MSM_RPM_STATUS_ID_PM8917_LVS5,
+ MSM_RPM_STATUS_ID_PM8917_LVS6,
+ MSM_RPM_STATUS_ID_PM8917_LVS7,
MSM_RPM_STATUS_ID_VOLTAGE_CORNER,
+ MSM_RPM_STATUS_ID_PM8917_VOLTAGE_CORNER
+ = MSM_RPM_STATUS_ID_VOLTAGE_CORNER,
+ MSM_RPM_STATUS_ID_PM8038_VOLTAGE_CORNER
+ = MSM_RPM_STATUS_ID_VOLTAGE_CORNER,
/* 8064 specific */
MSM_RPM_STATUS_ID_PM8821_S1_0,
@@ -899,6 +1114,7 @@
extern struct msm_rpm_platform_data msm8960_rpm_data;
extern struct msm_rpm_platform_data msm9615_rpm_data;
extern struct msm_rpm_platform_data msm8930_rpm_data;
+extern struct msm_rpm_platform_data msm8930_rpm_data_pm8917;
extern struct msm_rpm_platform_data apq8064_rpm_data;
#if defined(CONFIG_MSM_RPM)
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index f7ba507..a9598b1 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -83,6 +83,23 @@
MSM_CPU_9625
};
+enum pmic_model {
+ PMIC_MODEL_PM8058 = 13,
+ PMIC_MODEL_PM8028 = 14,
+ PMIC_MODEL_PM8901 = 15,
+ PMIC_MODEL_PM8027 = 16,
+ PMIC_MODEL_ISL_9519 = 17,
+ PMIC_MODEL_PM8921 = 18,
+ PMIC_MODEL_PM8018 = 19,
+ PMIC_MODEL_PM8015 = 20,
+ PMIC_MODEL_PM8014 = 21,
+ PMIC_MODEL_PM8821 = 22,
+ PMIC_MODEL_PM8038 = 23,
+ PMIC_MODEL_PM8922 = 24,
+ PMIC_MODEL_PM8917 = 25,
+ PMIC_MODEL_UNKNOWN = 0xFFFFFFFF
+};
+
enum msm_cpu socinfo_get_msm_cpu(void);
uint32_t socinfo_get_id(void);
uint32_t socinfo_get_version(void);
@@ -91,12 +108,15 @@
uint32_t socinfo_get_platform_type(void);
uint32_t socinfo_get_platform_subtype(void);
uint32_t socinfo_get_platform_version(void);
+enum pmic_model socinfo_get_pmic_model(void);
+uint32_t socinfo_get_pmic_die_revision(void);
int __init socinfo_init(void) __must_check;
const int read_msm_cpu_type(void);
const int get_core_count(void);
const int cpu_is_krait(void);
const int cpu_is_krait_v1(void);
const int cpu_is_krait_v2(void);
+const int cpu_is_krait_v3(void);
static inline int cpu_is_msm7x01(void)
{
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index edc4b39..5333c2e 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -75,6 +75,8 @@
#define SPS_BAM_OPT_BAMDMA (1UL << 2)
/* BAM IRQ is registered for apps wakeup */
#define SPS_BAM_OPT_IRQ_WAKEUP (1UL << 3)
+/* Ignore external block pipe reset */
+#define SPS_BAM_NO_EXT_P_RST (1UL << 4)
/* BAM device management flags */
@@ -1247,10 +1249,15 @@
*
* @para - parameter used for an option (such as pipe combination)
*
+ * @tb_sel - testbus selection
+ *
+ * @pre_level - prescreening level
+ *
* @return 0 on success, negative value on error
*
*/
-int sps_get_bam_debug_info(u32 dev, u32 option, u32 para);
+int sps_get_bam_debug_info(u32 dev, u32 option, u32 para,
+ u32 tb_sel, u8 pre_level);
#else
static inline int sps_register_bam_device(const struct sps_bam_props
@@ -1409,7 +1416,8 @@
return -EPERM;
}
-static inline int sps_get_bam_debug_info(u32 dev, u32 option, u32 para)
+static inline int sps_get_bam_debug_info(u32 dev, u32 option, u32 para,
+ u32 tb_sel, u8 pre_level)
{
return -EPERM;
}
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 89964de..2035d3f 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -301,6 +301,7 @@
MSM_CHIP_DEVICE(APCS_GCC, MSM8974),
MSM_CHIP_DEVICE(TLMM, MSM8974),
MSM_CHIP_DEVICE(MPM2_PSHOLD, MSM8974),
+ MSM_CHIP_DEVICE(IMEM, MSM8974),
{
.virtual = (unsigned long) MSM_SHARED_RAM_BASE,
.length = MSM_SHARED_RAM_SIZE,
diff --git a/arch/arm/mach-msm/ipc_logging_debug.c b/arch/arm/mach-msm/ipc_logging_debug.c
index 5f7a95e..ee3672e 100644
--- a/arch/arm/mach-msm/ipc_logging_debug.c
+++ b/arch/arm/mach-msm/ipc_logging_debug.c
@@ -186,6 +186,15 @@
{
tsv_timestamp_read(ectxt, dctxt, " ");
tsv_byte_array_read(ectxt, dctxt, "");
+
+ /* add trailing \n if necessary */
+ if (*(dctxt->buff - 1) != '\n') {
+ if (dctxt->size) {
+ ++dctxt->buff;
+ --dctxt->size;
+ }
+ *(dctxt->buff - 1) = '\n';
+ }
}
void check_and_create_debugfs(void)
diff --git a/arch/arm/mach-msm/lpm_resources.c b/arch/arm/mach-msm/lpm_resources.c
index 0758651..7d432f4 100644
--- a/arch/arm/mach-msm/lpm_resources.c
+++ b/arch/arm/mach-msm/lpm_resources.c
@@ -353,18 +353,21 @@
/* lpm resource handling functions */
/* Common */
-static void msm_lpm_notify_common(struct msm_rpm_notifier_data *rpm_notifier_cb,
+static void msm_lpm_notify_common(struct msm_rpm_notifier_data *cb,
struct msm_lpm_resource *rs)
{
- if ((rpm_notifier_cb->rsc_type == rs->rs_data.type) &&
- (rpm_notifier_cb->rsc_id == rs->rs_data.id) &&
- (rpm_notifier_cb->key == rs->rs_data.key)) {
- BUG_ON(rpm_notifier_cb->size > MAX_RS_SIZE);
+ if ((cb->rsc_type == rs->rs_data.type) &&
+ (cb->rsc_id == rs->rs_data.id) &&
+ (cb->key == rs->rs_data.key)) {
+
+ BUG_ON(cb->size > MAX_RS_SIZE);
if (rs->valid) {
- if (rpm_notifier_cb->value)
- memcpy(&rs->rs_data.value,
- rpm_notifier_cb->value, rpm_notifier_cb->size);
+ if (cb->value) {
+ memcpy(&rs->rs_data.value, cb->value, cb->size);
+ msm_rpm_add_kvp_data_noirq(rs->rs_data.handle,
+ cb->key, cb->value, cb->size);
+ }
else
rs->rs_data.value = rs->rs_data.default_value;
@@ -848,6 +851,7 @@
msm_lpm_l2.rs_data.default_value = MSM_LPM_L2_CACHE_HSFS_OPEN;
msm_lpm_l2.rs_data.value = MSM_LPM_L2_CACHE_HSFS_OPEN;
}
+ msm_pm_set_l2_flush_flag(0);
return 0;
fail:
return ret;
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index 2073856..43c85bb 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -108,6 +108,8 @@
int soft_reset_direction =
mdm_drv->pdata->soft_reset_inverted ? 1 : 0;
+ mdm_peripheral_disconnect(mdm_drv);
+
/* Wait for the modem to complete its power down actions. */
for (i = 20; i > 0; i--) {
if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
@@ -127,7 +129,6 @@
*/
msleep(4000);
}
- mdm_peripheral_disconnect(mdm_drv);
}
static void mdm_do_first_power_on(struct mdm_modem_drv *mdm_drv)
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
index 9ba9f7b1..70bb406 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
@@ -21,7 +21,7 @@
#include <mach/rpm.h>
#include "msm_bus_core.h"
-#define NMASTERS 45
+#define NMASTERS 55
#define NSLAVES 75
#define NFAB_8960 5
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index 9dcd51f..012bf5a 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
@@ -26,6 +26,7 @@
enum {
SLAVE_NODE,
MASTER_NODE,
+ CLK_NODE,
};
enum {
@@ -57,7 +58,7 @@
static int msm_bus_fabric_add_node(struct msm_bus_fabric *fabric,
struct msm_bus_inode_info *info)
{
- int status = -ENOMEM;
+ int status = -ENOMEM, ctx;
MSM_BUS_DBG("msm_bus_fabric_add_node: ID %d Gw: %d\n",
info->node_info->priv_id, info->node_info->gateway);
status = radix_tree_preload(GFP_ATOMIC);
@@ -71,17 +72,15 @@
radix_tree_tag_set(&fabric->fab_tree, info->node_info->priv_id,
SLAVE_NODE);
- if (info->node_info->slaveclk[DUAL_CTX]) {
- info->nodeclk[DUAL_CTX].clk = clk_get_sys("msm_bus",
- info->node_info->slaveclk[DUAL_CTX]);
- if (IS_ERR(info->nodeclk[DUAL_CTX].clk)) {
- MSM_BUS_ERR("Could not get clock for %s\n",
- info->node_info->slaveclk[DUAL_CTX]);
- status = -EINVAL;
- goto out;
+ for (ctx = 0; ctx < NUM_CTX; ctx++) {
+ if (info->node_info->slaveclk[ctx]) {
+ radix_tree_tag_set(&fabric->fab_tree,
+ info->node_info->priv_id, CLK_NODE);
+ break;
}
- info->nodeclk[DUAL_CTX].enable = false;
- info->nodeclk[DUAL_CTX].dirty = false;
+
+ info->nodeclk[ctx].enable = false;
+ info->nodeclk[ctx].dirty = false;
}
out:
@@ -435,11 +434,7 @@
unsigned int i, nfound = 0, status = 0;
struct msm_bus_inode_info *info[fabric->pdata->nslaves];
- if (fabric->clk_dirty == false) {
- MSM_BUS_DBG("No clocks have been touched for fabric: %d\n",
- fabric->fabdev.id);
- goto out;
- } else
+ if (fabric->clk_dirty == true)
status = msm_bus_fabric_clk_set(enable, &fabric->info);
if (status)
@@ -447,9 +442,9 @@
fabric->fabdev.id);
nfound = radix_tree_gang_lookup_tag(&fabric->fab_tree, (void **)&info,
- fabric->fabdev.id, fabric->pdata->nslaves, SLAVE_NODE);
+ fabric->fabdev.id, fabric->pdata->nslaves, CLK_NODE);
if (nfound == 0) {
- MSM_BUS_DBG("No slaves found for fabric: %d\n",
+ MSM_BUS_DBG("No clock nodes found for fabric: %d\n",
fabric->fabdev.id);
goto out;
}
@@ -503,7 +498,7 @@
*/
status = msm_bus_fabric_clk_commit(DISABLE, fabric);
if (status)
- MSM_BUS_DBG("Error disabling clocks on fabric: %d\n",
+ MSM_BUS_WARN("Error disabling clocks on fabric: %d\n",
fabric->fabdev.id);
fabric->clk_dirty = false;
return status;
diff --git a/arch/arm/mach-msm/msm_cpr.c b/arch/arm/mach-msm/msm_cpr.c
index f4272f3..b6c05f4 100644
--- a/arch/arm/mach-msm/msm_cpr.c
+++ b/arch/arm/mach-msm/msm_cpr.c
@@ -36,6 +36,14 @@
#define MODULE_NAME "msm-cpr"
+/**
+ * Convert the Delay time to Timer Count Register
+ * e.g if frequency is 19200 kHz and delay required is
+ * 20000us, so timer count will be 19200 * 20000 / 1000
+ */
+#define TIMER_COUNT(freq, delay) ((freq * delay) / 1000)
+#define ALL_CPR_IRQ 0x3F
+
/* Need platform device handle for suspend and resume APIs */
static struct platform_device *cpr_pdev;
@@ -45,6 +53,7 @@
int prev_mode;
uint32_t floor;
uint32_t ceiling;
+ bool max_volt_set;
void __iomem *base;
unsigned int irq;
struct mutex cpr_mutex;
@@ -157,7 +166,7 @@
static void
cpr_2pt_kv_analysis(struct msm_cpr *cpr, struct msm_cpr_mode *chip_data)
{
- int32_t tgt_volt_mV = 0, level_uV, rc;
+ int32_t level_uV = 0, rc;
uint32_t quot1, quot2;
/**
@@ -180,15 +189,10 @@
* voltage, offset is always subtracted from it.
*
*/
- if (chip_data->tgt_volt_offset > 0) {
- tgt_volt_mV = chip_data->calibrated_mV -
- (chip_data->tgt_volt_offset * cpr->vp->step_size);
- }
- pr_debug("tgt_volt_mV = %d, calibrated_mV = %d", tgt_volt_mV,
- chip_data->calibrated_mV);
+ level_uV = chip_data->Vmax -
+ (chip_data->tgt_volt_offset * cpr->vp->step_size);
+ pr_debug("tgt_volt_uV = %d\n", level_uV);
- /* level_uV = tgt_volt_mV * 1000; */
- level_uV = 1350000;
/* Call the PMIC specific routine to set the voltage */
rc = regulator_set_voltage(cpr->vreg_cx, level_uV, level_uV);
if (rc) {
@@ -202,10 +206,7 @@
return;
}
- /* Store the adjusted value of voltage */
- chip_data->calibrated_mV = 1300;
-
- /* Take first CPR measurement at a higher voltage to get QUOT1 */
+ /* First CPR measurement at a higher voltage to get QUOT1 */
/* Enable the Software mode of operation */
cpr_modify_reg(cpr, RBCPR_CTL, HW_TO_PMIC_EN_M, SW_MODE);
@@ -231,7 +232,8 @@
quot1 = (cpr_read_reg(cpr, RBCPR_DEBUG1) & QUOT_SLOW_M) >> 12;
/* Take second CPR measurement at a lower voltage to get QUOT2 */
- level_uV = 1300000;
+ level_uV -= 4 * cpr->vp->step_size;
+ pr_debug("tgt_volt_uV = %d\n", level_uV);
cpr_modify_reg(cpr, RBCPR_CTL, LOOP_EN_M, DISABLE_CPR);
/* Call the PMIC specific routine to set the voltage */
@@ -261,7 +263,7 @@
}
quot2 = (cpr_read_reg(cpr, RBCPR_DEBUG1) & QUOT_SLOW_M) >> 12;
chip_data->step_quot = (quot1 - quot2) / 4;
- pr_debug("%s: Calculated Step Quot is %d\n",
+ pr_info("%s: Calculated Step Quot is %d\n",
__func__, chip_data->step_quot);
/* Disable the cpr */
cpr_modify_reg(cpr, RBCPR_CTL, LOOP_EN_M, DISABLE_CPR);
@@ -279,7 +281,7 @@
void cpr_irq_clr_and_ack(struct msm_cpr *cpr, uint32_t mask)
{
/* Clear the interrupt */
- cpr_write_reg(cpr, RBIF_IRQ_CLEAR, 0x3F);
+ cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
/* Acknowledge the Recommendation */
cpr_write_reg(cpr, RBIF_CONT_ACK_CMD, 0x1);
}
@@ -287,7 +289,7 @@
static inline
void cpr_irq_clr_and_nack(struct msm_cpr *cpr, uint32_t mask)
{
- cpr_write_reg(cpr, RBIF_IRQ_CLEAR, 0x3F);
+ cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
cpr_write_reg(cpr, RBIF_CONT_NACK_CMD, 0x1);
}
@@ -307,7 +309,7 @@
static void
cpr_up_event_handler(struct msm_cpr *cpr, uint32_t new_volt)
{
- int rc, set_volt_mV;
+ int rc, set_volt_uV;
struct msm_cpr_mode *chip_data;
chip_data = &cpr->config->cpr_mode_data[cpr->cpr_mode];
@@ -317,26 +319,28 @@
* freq switch handler and CPR interrupt handler here
*/
/* Set New PMIC voltage */
- set_volt_mV = (new_volt < chip_data->Vmax ? new_volt
+ set_volt_uV = (new_volt < chip_data->Vmax ? new_volt
: chip_data->Vmax);
- rc = regulator_set_voltage(cpr->vreg_cx, set_volt_mV * 1000,
- set_volt_mV * 1000);
+ rc = regulator_set_voltage(cpr->vreg_cx, set_volt_uV,
+ set_volt_uV);
if (rc) {
- pr_err("%s: Voltage set at %dmV failed. %d\n",
- __func__, set_volt_mV, rc);
+ pr_err("%s: Voltage set at %duV failed. %d\n",
+ __func__, set_volt_uV, rc);
cpr_irq_clr_and_nack(cpr, BIT(4) | BIT(0));
return;
}
- pr_debug("%s: Voltage set at %dmV\n", __func__, set_volt_mV);
+ pr_info("(railway_voltage: %d uV)\n", set_volt_uV);
+
+ cpr->max_volt_set = (set_volt_uV == chip_data->Vmax) ? 1 : 0;
/**
* Save the new calibrated voltage to be re-used
* whenever we return to same mode after a mode switch.
*/
- chip_data->calibrated_mV = set_volt_mV;
+ chip_data->calibrated_uV = set_volt_uV;
/* Clear all the interrupts */
- cpr_write_reg(cpr, RBIF_IRQ_CLEAR, 0x3F);
+ cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
/* Disable Auto ACK for Down interrupts */
cpr_modify_reg(cpr, RBCPR_CTL, SW_AUTO_CONT_NACK_DN_EN_M, 0);
@@ -353,7 +357,7 @@
static void
cpr_dn_event_handler(struct msm_cpr *cpr, uint32_t new_volt)
{
- int rc, set_volt_mV;
+ int rc, set_volt_uV;
struct msm_cpr_mode *chip_data;
chip_data = &cpr->config->cpr_mode_data[cpr->cpr_mode];
@@ -363,26 +367,28 @@
* freq switch handler and CPR interrupt handler here
*/
/* Set New PMIC volt */
- set_volt_mV = (new_volt > chip_data->Vmin ? new_volt
+ set_volt_uV = (new_volt > chip_data->Vmin ? new_volt
: chip_data->Vmin);
- rc = regulator_set_voltage(cpr->vreg_cx, set_volt_mV * 1000,
- set_volt_mV * 1000);
+ rc = regulator_set_voltage(cpr->vreg_cx, set_volt_uV,
+ set_volt_uV);
if (rc) {
- pr_err("%s: Voltage at %dmV failed %d\n",
- __func__, set_volt_mV, rc);
+ pr_err("%s: Voltage at %duV failed %d\n",
+ __func__, set_volt_uV, rc);
cpr_irq_clr_and_nack(cpr, BIT(2) | BIT(0));
return;
}
- pr_debug("%s: Voltage set at %dmV\n", __func__, set_volt_mV);
+ pr_info("(railway_voltage: %d uV)\n", set_volt_uV);
+
+ cpr->max_volt_set = 0;
/**
* Save the new calibrated voltage to be re-used
* whenever we return to same mode after a mode switch.
*/
- chip_data->calibrated_mV = set_volt_mV;
+ chip_data->calibrated_uV = set_volt_uV;
/* Clear all the interrupts */
- cpr_write_reg(cpr, RBIF_IRQ_CLEAR, 0x3F);
+ cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
if (new_volt <= chip_data->Vmin) {
/*
@@ -416,16 +422,22 @@
chip_data = &cpr->config->cpr_mode_data[cpr->cpr_mode];
error_step = cpr_read_reg(cpr, RBCPR_RESULT_0) >> 2;
error_step &= 0xF;
- curr_volt = chip_data->calibrated_mV;
+ curr_volt = chip_data->calibrated_uV;
if (action == UP) {
+ /* Clear IRQ, ACK and return if Vdd already at Vmax */
+ if (cpr->max_volt_set == 1) {
+ cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
+ cpr_write_reg(cpr, RBIF_CONT_NACK_CMD, 0x1);
+ return;
+ }
+
/**
* Using up margin in the comparison helps avoid having to
* change up threshold values in chip register.
*/
if (error_step < (cpr->config->up_threshold +
cpr->config->up_margin)) {
- /* FIXME: Avoid repeated dn interrupts if we are here */
pr_debug("UP_INT error step too small to set\n");
cpr_irq_clr_and_nack(cpr, BIT(4) | BIT(0));
return;
@@ -434,6 +446,7 @@
/* Calculte new PMIC voltage */
new_volt = curr_volt + (error_step * cpr->vp->step_size);
pr_debug("UP_INT: new_volt: %d\n", new_volt);
+ pr_info("(UP Voltage recommended by CPR: %d uV)\n", new_volt);
cpr_up_event_handler(cpr, new_volt);
} else if (action == DOWN) {
@@ -443,7 +456,6 @@
*/
if (error_step < (cpr->config->dn_threshold +
cpr->config->dn_margin)) {
- /* FIXME: Avoid repeated dn interrupts if we are here */
pr_debug("DOWN_INT error_step too small to set\n");
cpr_irq_clr_and_nack(cpr, BIT(2) | BIT(0));
return;
@@ -452,6 +464,7 @@
/* Calculte new PMIC voltage */
new_volt = curr_volt - (error_step * cpr->vp->step_size);
pr_debug("DOWN_INT: new_volt: %d\n", new_volt);
+ pr_info("(DN Voltage recommended by CPR: %d uV)\n", new_volt);
cpr_dn_event_handler(cpr, new_volt);
}
}
@@ -513,6 +526,8 @@
cpr->config->dn_threshold << 28);
cpr->curr_osc = chip_data->ring_osc;
+ chip_data->ring_osc_data[cpr->curr_osc].quot =
+ cpr->config->max_quot;
/**
* Program the gate count and target values
@@ -522,7 +537,7 @@
cpr_modify_reg(cpr, RBCPR_GCNT_TARGET(cnt),
(GCNT_M | TARGET_M),
(chip_data->ring_osc_data[cnt].gcnt << 12 |
- chip_data->ring_osc_data[cnt].target_count));
+ chip_data->ring_osc_data[cnt].quot));
pr_debug("RBCPR_GCNT_TARGET(%d): = 0x%x\n", cnt,
readl_relaxed(cpr->base + RBCPR_GCNT_TARGET(cnt)));
cnt++;
@@ -536,14 +551,19 @@
* Set with an extra step since it helps as per
* characterization data.
*/
- chip_data->calibrated_mV += cpr->vp->step_size;
- tmp_uV = chip_data->calibrated_mV * 1000;
+ chip_data->calibrated_uV += cpr->vp->step_size;
+ tmp_uV = chip_data->calibrated_uV;
rc = regulator_set_voltage(cpr->vreg_cx, tmp_uV, tmp_uV);
if (rc)
pr_err("%s: Voltage set failed %d\n", __func__, rc);
- /* Program the Timer for default delay between CPR measurements */
- delay_count = 0xFFFF;
+ /*
+ * Program the Timer Register for delay between CPR measurements
+ * This is required to allow the device sufficient time for idle
+ * power collapse.
+ */
+ delay_count = TIMER_COUNT(cpr->config->ref_clk_khz,
+ cpr->config->delay_us);
cpr_write_reg(cpr, RBCPR_TIMER_INTERVAL, delay_count);
/* Enable the Timer */
@@ -554,53 +574,69 @@
SW_AUTO_CONT_ACK_EN);
}
-static void cpr_mode_config(struct msm_cpr *cpr, enum cpr_mode mode)
-{
- if (cpr->cpr_mode == mode)
- return;
-
- cpr->cpr_mode = mode;
- pr_debug("%s: Switching to %s mode\n", __func__,
- (mode == TURBO_MODE ? "TURBO" : "NORMAL"));
-
- /* Configure the new mode */
- cpr_config(cpr);
-}
-
static int
cpr_freq_transition(struct notifier_block *nb, unsigned long val,
void *data)
{
struct msm_cpr *cpr = container_of(nb, struct msm_cpr, freq_transition);
struct cpufreq_freqs *freqs = data;
+ uint32_t quot, new_freq;
switch (val) {
case CPUFREQ_PRECHANGE:
- return 0;
pr_debug("pre freq change notification to cpr\n");
- disable_irq(cpr->irq);
+ /* Disable Measurement to stop generation of CPR IRQs */
cpr_disable(cpr);
+ /* Disable routing of IRQ to App */
+ cpr_irq_set(cpr, INT_MASK & ~MID_INT, 0);
+ disable_irq(cpr->irq);
+ cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
+ pr_debug("RBCPR_CTL: 0x%x\n",
+ readl_relaxed(cpr->base + RBCPR_CTL));
+ pr_debug("RBIF_IRQ_STATUS: 0x%x\n",
+ cpr_read_reg(cpr, RBIF_IRQ_STATUS));
+ pr_debug("RBIF_IRQ_EN(0): 0x%x\n",
+ cpr_read_reg(cpr, RBIF_IRQ_EN(cpr->config->irq_line)));
+
cpr->prev_mode = cpr->cpr_mode;
break;
- case CPUFREQ_POSTCHANGE:
- return 0;
- pr_debug("post freq change notification to cpr\n");
- if (freqs->new >= cpr->config->nom_freq_limit)
- cpr_mode_config(cpr, TURBO_MODE);
- else
- cpr_mode_config(cpr, NORMAL_MODE);
+ case CPUFREQ_POSTCHANGE:
+ pr_debug("post freq change notification to cpr\n");
+ /**
+ * As per chip characterization data, use max nominal freq
+ * to calculate quot for all lower frequencies too
+ */
+ new_freq = (freqs->new > cpr->config->max_nom_freq)
+ ? freqs->new
+ : cpr->config->max_nom_freq;
+
+ /* Configure CPR for the new frequency */
+ quot = cpr->config->get_quot(cpr->config->max_quot,
+ cpr->config->max_freq / 1000,
+ new_freq / 1000);
+ cpr_modify_reg(cpr, RBCPR_GCNT_TARGET(cpr->curr_osc), TARGET_M,
+ quot);
+ pr_debug("RBCPR_GCNT_TARGET(%d): = 0x%x\n", cpr->curr_osc,
+ readl_relaxed(cpr->base +
+ RBCPR_GCNT_TARGET(cpr->curr_osc)));
+ pr_debug("%s: new_freq: %d, set_freq: %d, quot: %d\n", __func__,
+ freqs->new, new_freq, quot);
+
+ enable_irq(cpr->irq);
/**
* Enable all interrupts. One of them could be in a disabled
* state if vdd had hit Vmax / Vmin earlier
*/
- cpr_irq_set(cpr, (UP_INT | DOWN_INT), 1);
-
- enable_irq(cpr->irq);
-
+ cpr_irq_set(cpr, INT_MASK & ~MID_INT, 1);
+ pr_debug("RBIF_IRQ_EN(0): 0x%x\n",
+ cpr_read_reg(cpr, RBIF_IRQ_EN(cpr->config->irq_line)));
+ pr_debug("RBCPR_CTL: 0x%x\n",
+ readl_relaxed(cpr->base + RBCPR_CTL));
+ pr_debug("RBIF_IRQ_STATUS: 0x%x\n",
+ cpr_read_reg(cpr, RBIF_IRQ_STATUS));
cpr_enable(cpr);
-
break;
default:
break;
@@ -614,6 +650,8 @@
struct msm_cpr *cpr = dev_get_drvdata(dev);
int osc_num = cpr->config->cpr_mode_data->ring_osc;
+ cpr->config->clk_enable();
+
cpr_write_reg(cpr, RBCPR_TIMER_INTERVAL,
cpr_save_state.rbif_timer_interval);
cpr_write_reg(cpr, RBIF_IRQ_EN(cpr->config->irq_line),
@@ -628,11 +666,11 @@
cpr_save_state.rbcpr_step_quot);
cpr_write_reg(cpr, RBIF_SW_VLEVEL,
cpr_save_state.rbif_sw_level);
-
- cpr_enable(cpr);
cpr_write_reg(cpr, RBCPR_CTL,
cpr_save_state.rbcpr_ctl);
+
enable_irq(cpr->irq);
+ cpr_enable(cpr);
return 0;
}
@@ -643,6 +681,10 @@
struct msm_cpr *cpr = dev_get_drvdata(dev);
int osc_num = cpr->config->cpr_mode_data->ring_osc;
+ /* Disable CPR measurement before IRQ to avoid pending interrupts */
+ cpr_disable(cpr);
+ disable_irq(cpr->irq);
+
cpr_save_state.rbif_timer_interval =
cpr_read_reg(cpr, RBCPR_TIMER_INTERVAL);
cpr_save_state.rbif_int_en =
@@ -660,9 +702,6 @@
cpr_save_state.rbcpr_ctl =
cpr_read_reg(cpr, RBCPR_CTL);
- disable_irq(cpr->irq);
- cpr_disable(cpr);
-
return 0;
}
@@ -700,6 +739,7 @@
const struct msm_cpr_config *pdata = pdev->dev.platform_data;
void __iomem *base;
struct resource *mem;
+ struct msm_cpr_mode *chip_data;
if (!pdata) {
pr_err("CPR: Platform data is not available\n");
@@ -766,6 +806,16 @@
platform_set_drvdata(pdev, cpr);
+ chip_data = &cpr->config->cpr_mode_data[cpr->cpr_mode];
+ pr_info("CPR Platform Data (upside_steps: %d) (downside_steps: %d) ",
+ cpr->config->up_threshold, cpr->config->dn_threshold);
+ pr_info("(nominal_voltage: %duV) (turbo_voltage: %duV)\n",
+ cpr->config->cpr_mode_data[NORMAL_MODE].calibrated_uV,
+ cpr->config->cpr_mode_data[TURBO_MODE].calibrated_uV);
+ pr_info("(Current corner: TURBO) (gcnt_target: %d) (quot: %d)\n",
+ chip_data->ring_osc_data[chip_data->ring_osc].gcnt,
+ chip_data->ring_osc_data[chip_data->ring_osc].quot);
+
/* Initialze the Debugfs Entry for cpr */
res = msm_cpr_debug_init(cpr->base);
if (res) {
@@ -793,7 +843,6 @@
/* Enable the cpr */
cpr_modify_reg(cpr, RBCPR_CTL, LOOP_EN_M, ENABLE_CPR);
-
cpr->freq_transition.notifier_call = cpr_freq_transition;
cpufreq_register_notifier(&cpr->freq_transition,
CPUFREQ_TRANSITION_NOTIFIER);
diff --git a/arch/arm/mach-msm/msm_cpr.h b/arch/arm/mach-msm/msm_cpr.h
index 2642b9c..cb665b7 100644
--- a/arch/arm/mach-msm/msm_cpr.h
+++ b/arch/arm/mach-msm/msm_cpr.h
@@ -120,10 +120,10 @@
/**
* struct msm_vp_data - structure for VP configuration
- * @min_volt_mV: minimum milivolt level for VP
- * @max_volt_mV: maximum milivolt level for VP
- * @default_volt_mV: default milivolt for VP
- * @step_size_mV: step size of voltage
+ * @min_volt: minimum microvolt level for VP
+ * @max_volt: maximum microvolt level for VP
+ * @default_volt: default microvolt for VP
+ * @step_size: step size of voltage in microvolt
*/
struct msm_cpr_vp_data {
int min_volt;
@@ -135,11 +135,11 @@
/**
* struct msm_cpr_osc - Data for CPR ring oscillator
* @gcnt: gate count value for the oscillator
- * @target_count: target value for ring oscillator
+ * @quot: target value for ring oscillator
*/
struct msm_cpr_osc {
int gcnt;
- uint32_t target_count;
+ uint32_t quot;
};
/**
@@ -156,7 +156,7 @@
uint32_t step_quot;
uint32_t Vmax;
uint32_t Vmin;
- uint32_t calibrated_mV;
+ uint32_t calibrated_uV;
};
/**
@@ -180,8 +180,13 @@
uint32_t dn_threshold;
uint32_t up_margin;
uint32_t dn_margin;
- uint32_t nom_freq_limit;
+ uint32_t max_nom_freq;
+ uint32_t max_freq;
+ uint32_t max_quot;
struct msm_cpr_vp_data *vp_data;
+ uint32_t (*get_quot)(uint32_t max_quot, uint32_t max_freq,
+ uint32_t new_freq);
+ void (*clk_enable)(void);
};
/**
diff --git a/arch/arm/mach-msm/msm_memory_dump.c b/arch/arm/mach-msm/msm_memory_dump.c
index 4f48a0d..17cb2da 100644
--- a/arch/arm/mach-msm/msm_memory_dump.c
+++ b/arch/arm/mach-msm/msm_memory_dump.c
@@ -20,7 +20,7 @@
/*TODO: Needs to be set to correct value */
-#define DUMP_TABLE_OFFSET 0x20
+#define DUMP_TABLE_OFFSET 0x14
#define MSM_DUMP_TABLE_VERSION MK_TABLE(1, 0)
static struct msm_memory_dump mem_dump_data;
@@ -67,7 +67,8 @@
table = mem_dump_data.dump_table_ptr;
table->version = MSM_DUMP_TABLE_VERSION;
mem_dump_data.dump_table_phys = virt_to_phys(table);
- /* TODO: Need to write physical address of table to IMEM */
+ writel_relaxed(mem_dump_data.dump_table_phys,
+ MSM_IMEM_BASE + DUMP_TABLE_OFFSET);
atomic_notifier_chain_register(&panic_notifier_list,
&msm_memory_dump_blk);
printk(KERN_INFO "MSM Memory Dump table set up\n");
diff --git a/arch/arm/mach-msm/msm_watchdog_v2.c b/arch/arm/mach-msm/msm_watchdog_v2.c
index ea408f7..af903f8 100644
--- a/arch/arm/mach-msm/msm_watchdog_v2.c
+++ b/arch/arm/mach-msm/msm_watchdog_v2.c
@@ -19,6 +19,8 @@
#include <linux/jiffies.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/percpu.h>
#include <linux/of.h>
#include <linux/cpu.h>
#include <linux/platform_device.h>
@@ -54,6 +56,8 @@
cpumask_t alive_mask;
struct work_struct init_dogwork_struct;
struct delayed_work dogwork_struct;
+ bool irq_ppi;
+ struct msm_watchdog_data __percpu **wdog_cpu_dd;
struct notifier_block panic_blk;
};
@@ -199,7 +203,7 @@
ping_other_cpus(wdog_dd);
pet_watchdog(wdog_dd);
if (enable)
- schedule_delayed_work(&wdog_dd->dogwork_struct,
+ schedule_delayed_work_on(0, &wdog_dd->dogwork_struct,
delay_time);
}
@@ -218,6 +222,8 @@
/* In case we got suspended mid-exit */
__raw_writel(0, wdog_dd->base + WDT0_EN);
}
+ if (wdog_dd->irq_ppi)
+ free_percpu(wdog_dd->wdog_cpu_dd);
printk(KERN_INFO "MSM Watchdog Exit - Deactivated\n");
kzfree(wdog_dd);
return 0;
@@ -242,6 +248,13 @@
return IRQ_HANDLED;
}
+static irqreturn_t wdog_ppi_bark(int irq, void *dev_id)
+{
+ struct msm_watchdog_data *wdog_dd =
+ *(struct msm_watchdog_data **)(dev_id);
+ return wdog_bark_handler(irq, wdog_dd);
+}
+
static void configure_bark_dump(struct msm_watchdog_data *wdog_dd)
{
int ret;
@@ -287,6 +300,32 @@
init_dogwork_struct);
unsigned long delay_time;
u64 timeout;
+ int ret;
+
+ if (wdog_dd->irq_ppi) {
+ wdog_dd->wdog_cpu_dd = alloc_percpu(struct msm_watchdog_data *);
+ if (!wdog_dd->wdog_cpu_dd) {
+ dev_err(wdog_dd->dev, "fail to allocate cpu data\n");
+ return;
+ }
+ *__this_cpu_ptr(wdog_dd->wdog_cpu_dd) = wdog_dd;
+ ret = request_percpu_irq(wdog_dd->bark_irq, wdog_ppi_bark,
+ "apps_wdog_bark",
+ wdog_dd->wdog_cpu_dd);
+ if (ret) {
+ dev_err(wdog_dd->dev, "failed to request bark irq\n");
+ free_percpu(wdog_dd->wdog_cpu_dd);
+ return;
+ }
+ } else {
+ ret = devm_request_irq(wdog_dd->dev, wdog_dd->bark_irq,
+ wdog_bark_handler, IRQF_TRIGGER_RISING,
+ "apps_wdog_bark", wdog_dd);
+ if (ret) {
+ dev_err(wdog_dd->dev, "failed to request bark irq\n");
+ return;
+ }
+ }
delay_time = msecs_to_jiffies(wdog_dd->pet_time);
wdog_dd->min_slack_ticks = UINT_MAX;
wdog_dd->min_slack_ns = ULLONG_MAX;
@@ -298,12 +337,14 @@
wdog_dd->panic_blk.notifier_call = panic_wdog_handler;
atomic_notifier_chain_register(&panic_notifier_list,
&wdog_dd->panic_blk);
- schedule_delayed_work(&wdog_dd->dogwork_struct, delay_time);
+ schedule_delayed_work_on(0, &wdog_dd->dogwork_struct, delay_time);
__raw_writel(1, wdog_dd->base + WDT0_EN);
__raw_writel(1, wdog_dd->base + WDT0_RST);
wdog_dd->last_pet = sched_clock();
printk(KERN_INFO "MSM Watchdog Initialized\n");
+ if (wdog_dd->irq_ppi)
+ enable_percpu_irq(wdog_dd->bark_irq, 0);
return;
}
@@ -377,6 +418,7 @@
__func__);
return -ENXIO;
}
+ pdata->irq_ppi = irq_is_per_cpu(pdata->bark_irq);
dump_pdata(pdata);
return 0;
}
@@ -396,13 +438,6 @@
goto err;
wdog_dd->dev = &pdev->dev;
platform_set_drvdata(pdev, wdog_dd);
- ret = devm_request_irq(&pdev->dev, wdog_dd->bark_irq, wdog_bark_handler,
- IRQF_TRIGGER_RISING, "apps_wdog_bark", wdog_dd);
- if (ret) {
- dev_err(&pdev->dev, "failed to request bark irq\n");
- ret = -ENXIO;
- goto err;
- }
cpumask_clear(&wdog_dd->alive_mask);
INIT_WORK(&wdog_dd->init_dogwork_struct, init_watchdog_work);
INIT_DELAYED_WORK(&wdog_dd->dogwork_struct, pet_watchdog_work);
diff --git a/arch/arm/mach-msm/ocmem.c b/arch/arm/mach-msm/ocmem.c
index 82fe2f8..51445aa 100644
--- a/arch/arm/mach-msm/ocmem.c
+++ b/arch/arm/mach-msm/ocmem.c
@@ -63,6 +63,27 @@
"other_os",
};
+/* Must be in sync with enum ocmem_zstat_item */
+static const char *zstat_names[NR_OCMEM_ZSTAT_ITEMS] = {
+ "Allocation requests",
+ "Synchronous allocations",
+ "Ranged allocations",
+ "Asynchronous allocations",
+ "Allocation failures",
+ "Allocations grown",
+ "Allocations freed",
+ "Allocations shrunk",
+ "OCMEM maps",
+ "Map failures",
+ "OCMEM unmaps",
+ "Unmap failures",
+ "Transfers to OCMEM",
+ "Transfers to DDR",
+ "Transfer failures",
+ "Evictions",
+ "Restorations",
+};
+
struct ocmem_quota_table {
const char *name;
int id;
@@ -135,6 +156,23 @@
return 0;
}
+inline void inc_ocmem_stat(struct ocmem_zone *z,
+ enum ocmem_zstat_item item)
+{
+ if (!z)
+ return;
+ atomic_long_inc(&z->z_stat[item]);
+}
+
+inline unsigned long get_ocmem_stat(struct ocmem_zone *z,
+ enum ocmem_zstat_item item)
+{
+ if (!z)
+ return 0;
+ else
+ return atomic_long_read(&z->z_stat[item]);
+}
+
static struct ocmem_plat_data *parse_static_config(struct platform_device *pdev)
{
struct ocmem_plat_data *pdata = NULL;
@@ -473,6 +511,60 @@
return NULL;
}
+static int ocmem_zones_show(struct seq_file *f, void *dummy)
+{
+ unsigned i = 0;
+ for (i = OCMEM_GRAPHICS; i < OCMEM_CLIENT_MAX; i++) {
+ struct ocmem_zone *z = get_zone(i);
+ if (z && z->active == true)
+ seq_printf(f, "zone %s\t:0x%08lx - 0x%08lx (%4ld KB)\n",
+ get_name(z->owner), z->z_start, z->z_end - 1,
+ (z->z_end - z->z_start)/SZ_1K);
+ }
+ return 0;
+}
+
+static int ocmem_zones_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ocmem_zones_show, inode->i_private);
+}
+
+static const struct file_operations zones_show_fops = {
+ .open = ocmem_zones_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static int ocmem_stats_show(struct seq_file *f, void *dummy)
+{
+ unsigned i = 0;
+ unsigned j = 0;
+ for (i = OCMEM_GRAPHICS; i < OCMEM_CLIENT_MAX; i++) {
+ struct ocmem_zone *z = get_zone(i);
+ if (z && z->active == true) {
+ seq_printf(f, "zone %s:\n", get_name(z->owner));
+ for (j = 0 ; j < ARRAY_SIZE(zstat_names); j++) {
+ seq_printf(f, "\t %s: %lu\n", zstat_names[j],
+ get_ocmem_stat(z, j));
+ }
+ }
+ }
+ return 0;
+}
+
+static int ocmem_stats_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ocmem_stats_show, inode->i_private);
+}
+
+static const struct file_operations stats_show_fops = {
+ .open = ocmem_stats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
static int ocmem_zone_init(struct platform_device *pdev)
{
@@ -549,6 +641,8 @@
z_ops->allocate = allocate_head;
z_ops->free = free_head;
}
+ /* zap the counters */
+ memset(zone->z_stat, 0 , sizeof(zone->z_stat));
zone->active = true;
active_zones++;
@@ -557,7 +651,19 @@
pr_info(" zone %s\t: 0x%08lx - 0x%08lx (%4ld KB)\n",
client_names[part->id], zone->z_start,
- zone->z_end, part->p_size/SZ_1K);
+ zone->z_end - 1, part->p_size/SZ_1K);
+ }
+
+ if (!debugfs_create_file("zones", S_IRUGO, pdata->debug_node,
+ NULL, &zones_show_fops)) {
+ dev_err(dev, "Unable to create debugfs node for zones\n");
+ return -EBUSY;
+ }
+
+ if (!debugfs_create_file("stats", S_IRUGO, pdata->debug_node,
+ NULL, &stats_show_fops)) {
+ dev_err(dev, "Unable to create debugfs node for stats\n");
+ return -EBUSY;
}
dev_dbg(dev, "Total active zones = %d\n", active_zones);
@@ -587,6 +693,27 @@
return 0;
}
+static int __devinit ocmem_debugfs_init(struct platform_device *pdev)
+{
+ struct dentry *debug_dir = NULL;
+ struct ocmem_plat_data *pdata = platform_get_drvdata(pdev);
+
+ debug_dir = debugfs_create_dir("ocmem", NULL);
+ if (!debug_dir || IS_ERR(debug_dir)) {
+ pr_err("ocmem: Unable to create debugfs root\n");
+ return PTR_ERR(debug_dir);
+ }
+
+ pdata->debug_node = debug_dir;
+ return 0;
+}
+
+static void __devexit ocmem_debugfs_exit(struct platform_device *pdev)
+{
+ struct ocmem_plat_data *pdata = platform_get_drvdata(pdev);
+ debugfs_remove_recursive(pdata->debug_node);
+}
+
static int __devinit msm_ocmem_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -635,6 +762,9 @@
platform_set_drvdata(pdev, ocmem_pdata);
+ if (ocmem_debugfs_init(pdev))
+ return -EBUSY;
+
if (ocmem_core_init(pdev))
return -EBUSY;
@@ -644,7 +774,7 @@
if (ocmem_notifier_init())
return -EBUSY;
- if (ocmem_sched_init())
+ if (ocmem_sched_init(pdev))
return -EBUSY;
if (ocmem_rdm_init(pdev))
@@ -661,6 +791,7 @@
static int __devexit msm_ocmem_remove(struct platform_device *pdev)
{
+ ocmem_debugfs_exit(pdev);
return 0;
}
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
index c7cc57e..de9856d 100644
--- a/arch/arm/mach-msm/ocmem_core.c
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -50,6 +50,7 @@
#define OCMEM_V1_REGIONS 3
#define OCMEM_V1_MACROS 8
+#define OCMEM_V1_MACRO_SZ (SZ_64K)
#define OC_HW_VERS (0x0)
#define OC_HW_PROFILE (0x4)
@@ -92,7 +93,7 @@
#define REGION_SLEEP_PERI_ON 0x00007777
#define REGION_DEFAULT_OFF REGION_SLEEP_NO_RETENTION
-#define REGION_DEFAULT_ON REGION_FORCE_ALL_ON
+#define REGION_DEFAULT_ON REGION_NORMAL_PASSTHROUGH
#define REGION_DEFAULT_RETENTION REGION_SLEEP_PERI_OFF
enum rpm_macro_state {
@@ -664,6 +665,81 @@
return switch_power_state(id, offset, len, REGION_DEFAULT_RETENTION);
}
+static int ocmem_power_show_sw_state(struct seq_file *f, void *dummy)
+{
+ unsigned i, j;
+ unsigned m_state;
+ mutex_lock(®ion_ctrl_lock);
+
+ seq_printf(f, "OCMEM Aggregated Power States\n");
+ for (i = 0 ; i < num_regions; i++) {
+ struct ocmem_hw_region *region = ®ion_ctrl[i];
+ seq_printf(f, "Region %u mode %x\n", i, region->mode);
+ for (j = 0; j < num_banks; j++) {
+ m_state = read_macro_state(i, j);
+ if (m_state == MACRO_ON)
+ seq_printf(f, "M%u:%s\t", j, "ON");
+ else if (m_state == MACRO_SLEEP_RETENTION)
+ seq_printf(f, "M%u:%s\t", j, "RETENTION");
+ else
+ seq_printf(f, "M%u:%s\t", j, "OFF");
+ }
+ seq_printf(f, "\n");
+ }
+ mutex_unlock(®ion_ctrl_lock);
+ return 0;
+}
+
+#ifdef CONFIG_MSM_OCMEM_POWER_DEBUG
+static int ocmem_power_show_hw_state(struct seq_file *f, void *dummy)
+{
+ unsigned i = 0;
+ unsigned r_state;
+
+ mutex_lock(®ion_ctrl_lock);
+
+ seq_printf(f, "OCMEM Hardware Power States\n");
+ for (i = 0 ; i < num_regions; i++) {
+ struct ocmem_hw_region *region = ®ion_ctrl[i];
+ seq_printf(f, "Region %u mode %x ", i, region->mode);
+ r_state = read_hw_region_state(i);
+ if (r_state == REGION_DEFAULT_ON)
+ seq_printf(f, "state: %s\t", "REGION_ON");
+ else if (r_state == MACRO_SLEEP_RETENTION)
+ seq_printf(f, "state: %s\t", "REGION_RETENTION");
+ else
+ seq_printf(f, "state: %s\t", "REGION_OFF");
+ seq_printf(f, "\n");
+ }
+ mutex_unlock(®ion_ctrl_lock);
+ return 0;
+}
+#else
+static int ocmem_power_show_hw_state(struct seq_file *f, void *dummy)
+{
+ return 0;
+}
+#endif
+
+static int ocmem_power_show(struct seq_file *f, void *dummy)
+{
+ ocmem_power_show_sw_state(f, dummy);
+ ocmem_power_show_hw_state(f, dummy);
+ return 0;
+}
+
+static int ocmem_power_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ocmem_power_show, inode->i_private);
+}
+
+static const struct file_operations power_show_fops = {
+ .open = ocmem_power_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
int ocmem_core_init(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -709,9 +785,9 @@
pdata->interleaved = true;
pdata->nr_macros = num_macros;
pdata->nr_ports = num_ports;
- macro_size = SZ_64K;
- region_size = macro_size * num_ports;
+ macro_size = OCMEM_V1_MACRO_SZ * 2;
num_banks = num_ports / 2;
+ region_size = macro_size * num_banks;
rsc_type = pdata->rpm_rsc_type;
pr_debug("ocmem_core: ports %d regions %d macros %d interleaved %d\n",
@@ -784,8 +860,14 @@
return rc;
ocmem_disable_core_clock();
- return 0;
+ if (!debugfs_create_file("power_state", S_IRUGO, pdata->debug_node,
+ NULL, &power_show_fops)) {
+ dev_err(dev, "Unable to create debugfs node for power state\n");
+ return -EBUSY;
+ }
+
+ return 0;
err_no_mem:
pr_err("ocmem: Unable to allocate memory\n");
region_init_error:
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index 3ac8e0a..c95728e 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -158,6 +158,50 @@
return ocmem_client_table[id].hw_interconnect == OCMEM_BLOCKED ? 1 : 0;
}
+inline struct ocmem_buf *handle_to_buffer(struct ocmem_handle *handle)
+{
+ if (handle)
+ return &handle->buffer;
+ else
+ return NULL;
+}
+
+inline struct ocmem_handle *buffer_to_handle(struct ocmem_buf *buffer)
+{
+ if (buffer)
+ return container_of(buffer, struct ocmem_handle, buffer);
+ else
+ return NULL;
+}
+
+inline struct ocmem_req *handle_to_req(struct ocmem_handle *handle)
+{
+ if (handle)
+ return handle->req;
+ else
+ return NULL;
+}
+
+inline struct ocmem_handle *req_to_handle(struct ocmem_req *req)
+{
+ if (req && req->buffer)
+ return container_of(req->buffer, struct ocmem_handle, buffer);
+ else
+ return NULL;
+}
+
+/* Simple wrappers which will have debug features added later */
+inline int ocmem_read(void *at)
+{
+ return readl_relaxed(at);
+}
+
+inline int ocmem_write(unsigned long val, void *at)
+{
+ writel_relaxed(val, at);
+ return 0;
+}
+
/* Returns the address that can be used by a device core to access OCMEM */
static unsigned long device_address(int id, unsigned long addr)
{
@@ -200,6 +244,15 @@
return ret_addr;
}
+static inline struct ocmem_zone *zone_of(struct ocmem_req *req)
+{
+ int owner;
+ if (!req)
+ return NULL;
+ owner = req->owner;
+ return get_zone(owner);
+}
+
static int insert_region(struct ocmem_region *region)
{
@@ -794,7 +847,6 @@
if (matched_req != req)
goto invalid_op_error;
-
ret = zone->z_ops->free(zone,
matched_req->req_start, matched_req->req_sz);
@@ -1273,6 +1325,8 @@
if (rc < 0)
return -EINVAL;
+ inc_ocmem_stat(zone_of(req), NR_FREES);
+
ocmem_destroy_req(req);
handle->req = NULL;
@@ -1349,14 +1403,16 @@
goto transfer_out_error;
}
+ inc_ocmem_stat(zone_of(req), NR_TRANSFERS_TO_DDR);
+
rc = queue_transfer(req, handle, list, TO_DDR);
if (rc < 0) {
pr_err("Failed to queue rdm transfer to DDR\n");
+ inc_ocmem_stat(zone_of(req), NR_TRANSFER_FAILS);
goto transfer_out_error;
}
-
return 0;
transfer_out_error:
@@ -1385,10 +1441,13 @@
goto transfer_in_error;
}
+ inc_ocmem_stat(zone_of(req), NR_TRANSFERS_TO_OCMEM);
+
rc = queue_transfer(req, handle, list, TO_OCMEM);
if (rc < 0) {
pr_err("Failed to queue rdm transfer to OCMEM\n");
+ inc_ocmem_stat(zone_of(req), NR_TRANSFER_FAILS);
goto transfer_in_error;
}
@@ -1425,6 +1484,8 @@
if (is_tcm(req->owner))
do_unmap(req);
+ inc_ocmem_stat(zone_of(req), NR_SHRINKS);
+
if (size == 0) {
pr_info("req %p being shrunk to zero\n", req);
rc = do_free(req);
@@ -1507,6 +1568,8 @@
req->edata = edata;
buffer.addr = req->req_start;
buffer.len = 0x0;
+ inc_ocmem_stat(zone_of(req),
+ NR_EVICTIONS);
dispatch_notification(req->owner,
OCMEM_ALLOC_SHRINK, &buffer);
}
@@ -1536,8 +1599,10 @@
rc = __sched_allocate(req, can_block, can_wait);
mutex_unlock(&sched_mutex);
- if (rc == OP_FAIL)
+ if (rc == OP_FAIL) {
+ inc_ocmem_stat(zone_of(req), NR_ALLOCATION_FAILS);
goto err_allocate_fail;
+ }
if (rc == OP_RESCHED) {
buffer->addr = 0x0;
@@ -1547,6 +1612,7 @@
} else if (rc == OP_PARTIAL) {
buffer->addr = device_address(req->owner, req->req_start);
buffer->len = req->req_sz;
+ inc_ocmem_stat(zone_of(req), NR_RANGE_ALLOCATIONS);
pr_debug("ocmem: Enqueuing req %p\n", req);
sched_enqueue(req);
} else if (rc == OP_COMPLETE) {
@@ -1578,6 +1644,7 @@
list_del(&req->sched_list);
req->op = SCHED_ALLOCATE;
sched_enqueue(req);
+ inc_ocmem_stat(zone_of(req), NR_RESTORES);
}
}
kfree(edata);
@@ -1624,11 +1691,15 @@
req->op = SCHED_ALLOCATE;
req->buffer = buffer;
+ inc_ocmem_stat(zone_of(req), NR_REQUESTS);
+
rc = do_allocate(req, can_block, can_wait);
if (rc < 0)
goto do_allocate_error;
+ inc_ocmem_stat(zone_of(req), NR_SYNC_ALLOCATIONS);
+
handle->req = req;
if (is_tcm(id)) {
@@ -1673,10 +1744,11 @@
rc = do_allocate(req, true, false);
-
if (rc < 0)
goto do_allocate_error;
+ inc_ocmem_stat(zone_of(req), NR_ASYNC_ALLOCATIONS);
+
if (is_tcm(id)) {
rc = process_map(req, req->req_start, req->req_end);
if (rc < 0)
@@ -1744,10 +1816,51 @@
return;
}
-int ocmem_sched_init(void)
+static int ocmem_allocations_show(struct seq_file *f, void *dummy)
+{
+ struct rb_node *rb_node = NULL;
+ struct ocmem_req *req = NULL;
+ unsigned j;
+ mutex_lock(&sched_mutex);
+ for (rb_node = rb_first(&sched_tree); rb_node;
+ rb_node = rb_next(rb_node)) {
+ struct ocmem_region *tmp_region = NULL;
+ tmp_region = rb_entry(rb_node, struct ocmem_region, region_rb);
+ for (j = MAX_OCMEM_PRIO - 1; j > NO_PRIO; j--) {
+ req = find_req_match(j, tmp_region);
+ if (req) {
+ seq_printf(f,
+ "owner: %s 0x%lx -- 0x%lx size 0x%lx [state: %2lx]\n",
+ get_name(req->owner),
+ req->req_start, req->req_end,
+ req->req_sz, req->state);
+ }
+ }
+ }
+ mutex_unlock(&sched_mutex);
+ return 0;
+}
+
+static int ocmem_allocations_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, ocmem_allocations_show, inode->i_private);
+}
+
+static const struct file_operations allocations_show_fops = {
+ .open = ocmem_allocations_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+int ocmem_sched_init(struct platform_device *pdev)
{
int i = 0;
+ struct ocmem_plat_data *pdata = NULL;
+ struct device *dev = &pdev->dev;
+
sched_tree = RB_ROOT;
+ pdata = platform_get_drvdata(pdev);
mutex_init(&sched_mutex);
mutex_init(&sched_queue_mutex);
for (i = MIN_PRIO; i < MAX_OCMEM_PRIO; i++)
@@ -1761,5 +1874,11 @@
ocmem_eviction_wq = alloc_workqueue("ocmem_eviction_wq", 0, 0);
if (!ocmem_eviction_wq)
return -ENOMEM;
+
+ if (!debugfs_create_file("allocations", S_IRUGO, pdata->debug_node,
+ NULL, &allocations_show_fops)) {
+ dev_err(dev, "Unable to create debugfs node for scheduler\n");
+ return -EBUSY;
+ }
return 0;
}
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 540ffbb..4ff34bf 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -34,6 +34,15 @@
#include "peripheral-loader.h"
+/**
+ * proxy_timeout - Override for proxy vote timeouts
+ * -1: Use driver-specified timeout
+ * 0: Hold proxy votes until shutdown
+ * >0: Specify a custom timeout in ms
+ */
+static int proxy_timeout_ms = -1;
+module_param(proxy_timeout_ms, int, S_IRUGO | S_IWUSR);
+
enum pil_state {
PIL_OFFLINE,
PIL_ONLINE,
@@ -127,7 +136,10 @@
static void pil_proxy_unvote(struct pil_device *pil, unsigned long timeout)
{
- if (pil->desc->ops->proxy_unvote)
+ if (proxy_timeout_ms >= 0)
+ timeout = proxy_timeout_ms;
+
+ if (timeout && pil->desc->ops->proxy_unvote)
schedule_delayed_work(&pil->proxy, msecs_to_jiffies(timeout));
}
@@ -393,7 +405,11 @@
static void pil_shutdown(struct pil_device *pil)
{
pil->desc->ops->shutdown(pil->desc);
- flush_delayed_work(&pil->proxy);
+ if (proxy_timeout_ms == 0 && pil->desc->ops->proxy_unvote)
+ pil->desc->ops->proxy_unvote(pil->desc);
+ else
+ flush_delayed_work(&pil->proxy);
+
pil_set_state(pil, PIL_OFFLINE);
}
diff --git a/arch/arm/mach-msm/pil-mba.c b/arch/arm/mach-msm/pil-mba.c
index 2176b26..5e67d4f 100644
--- a/arch/arm/mach-msm/pil-mba.c
+++ b/arch/arm/mach-msm/pil-mba.c
@@ -38,10 +38,12 @@
#define STATUS_META_DATA_AUTH_SUCCESS 0x3
#define STATUS_AUTH_COMPLETE 0x4
-#define AUTH_TIMEOUT_US 10000000
#define PROXY_TIMEOUT_MS 10000
#define POLL_INTERVAL_US 50
+static int modem_auth_timeout_ms = 10000;
+module_param(modem_auth_timeout_ms, int, S_IRUGO | S_IWUSR);
+
struct mba_data {
void __iomem *reg_base;
void __iomem *metadata_base;
@@ -89,7 +91,7 @@
writel_relaxed(CMD_META_DATA_READY, drv->reg_base + RMB_MBA_COMMAND);
ret = readl_poll_timeout(drv->reg_base + RMB_MBA_STATUS, status,
status == STATUS_META_DATA_AUTH_SUCCESS || status < 0,
- POLL_INTERVAL_US, AUTH_TIMEOUT_US);
+ POLL_INTERVAL_US, modem_auth_timeout_ms * 1000);
if (ret) {
dev_err(pil->dev, "MBA authentication timed out\n");
} else if (status < 0) {
@@ -133,7 +135,7 @@
/* Wait for all segments to be authenticated or an error to occur */
ret = readl_poll_timeout(drv->reg_base + RMB_MBA_STATUS, status,
status == STATUS_AUTH_COMPLETE || status < 0,
- 50, AUTH_TIMEOUT_US);
+ 50, modem_auth_timeout_ms * 1000);
if (ret) {
dev_err(pil->dev, "MBA authentication timed out\n");
} else if (status < 0) {
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 6a30940..1720729 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -51,10 +51,12 @@
#define RMB_PBL_STATUS 0x04
#define RMB_MBA_STATUS 0x0C
-#define PBL_MBA_WAIT_TIMEOUT_US 100000
#define PROXY_TIMEOUT_MS 10000
#define POLL_INTERVAL_US 50
+static int pbl_mba_boot_timeout_ms = 100;
+module_param(pbl_mba_boot_timeout_ms, int, S_IRUGO | S_IWUSR);
+
static int pil_mss_power_up(struct device *dev)
{
int ret;
@@ -77,6 +79,7 @@
static int pil_mss_enable_clks(struct q6v5_data *drv)
{
int ret;
+ void __iomem *mpll1_config_ctl;
ret = clk_prepare_enable(drv->ahb_clk);
if (ret)
@@ -97,6 +100,12 @@
if (ret)
goto err_rom_clk;
+ /* TODO: Remove when support for 8974v1.0 HW is dropped. */
+ mpll1_config_ctl = ioremap(0xFC981034, 0x4);
+ writel_relaxed(0x0300403D, mpll1_config_ctl);
+ mb();
+ iounmap(mpll1_config_ctl);
+
return 0;
err_rom_clk:
@@ -131,7 +140,7 @@
/* Wait for PBL completion. */
ret = readl_poll_timeout(drv->rmb_base + RMB_PBL_STATUS, status,
- status != 0, POLL_INTERVAL_US, PBL_MBA_WAIT_TIMEOUT_US);
+ status != 0, POLL_INTERVAL_US, pbl_mba_boot_timeout_ms * 1000);
if (ret) {
dev_err(dev, "PBL boot timed out\n");
return ret;
@@ -143,7 +152,7 @@
/* Wait for MBA completion. */
ret = readl_poll_timeout(drv->rmb_base + RMB_MBA_STATUS, status,
- status != 0, POLL_INTERVAL_US, PBL_MBA_WAIT_TIMEOUT_US);
+ status != 0, POLL_INTERVAL_US, pbl_mba_boot_timeout_ms * 1000);
if (ret) {
dev_err(dev, "MBA boot timed out\n");
return ret;
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index b2d3dfa..f6b44c6 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -102,17 +102,23 @@
msm_spm_turn_on_cpu_rail(cpu);
- writel_relaxed(0x109, base_ptr+0x04);
- writel_relaxed(0x101, base_ptr+0x04);
- ndelay(300);
-
- writel_relaxed(0x121, base_ptr+0x04);
+ if (cpu_is_krait_v1() || cpu_is_krait_v2()) {
+ writel_relaxed(0x109, base_ptr+0x04);
+ writel_relaxed(0x101, base_ptr+0x04);
+ mb();
+ ndelay(300);
+ writel_relaxed(0x121, base_ptr+0x04);
+ } else
+ writel_relaxed(0x021, base_ptr+0x04);
+ mb();
udelay(2);
writel_relaxed(0x020, base_ptr+0x04);
+ mb();
udelay(2);
writel_relaxed(0x000, base_ptr+0x04);
+ mb();
udelay(100);
writel_relaxed(0x080, base_ptr+0x04);
@@ -178,7 +184,7 @@
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
int ret;
- int flag = 0;
+ unsigned int flag = 0;
unsigned long timeout;
pr_debug("Starting secondary CPU %d\n", cpu);
@@ -192,8 +198,7 @@
__WARN();
if (per_cpu(cold_boot_done, cpu) == false) {
- ret = scm_set_boot_addr((void *)
- virt_to_phys(msm_secondary_startup),
+ ret = scm_set_boot_addr(virt_to_phys(msm_secondary_startup),
flag);
if (ret == 0)
release_secondary(cpu);
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index d73764f..40929cc 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -27,6 +27,8 @@
#include <mach/msm_iomap.h>
#include <mach/socinfo.h>
#include <mach/system.h>
+#include <mach/scm.h>
+#include <mach/socinfo.h>
#include <asm/cacheflush.h>
#include <asm/hardware/gic.h>
#include <asm/pgtable.h>
@@ -67,6 +69,7 @@
module_param_named(
debug_mask, msm_pm_debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP
);
+static int msm_pm_retention_tz_call;
/******************************************************************************
@@ -78,6 +81,9 @@
MSM_PM_MODE_ATTR_NR,
};
+#define SCM_L2_RETENTION (0x2)
+#define SCM_CMD_TERMINATE_PC (0x2)
+
static char *msm_pm_mode_attr_labels[MSM_PM_MODE_ATTR_NR] = {
[MSM_PM_MODE_ATTR_SUSPEND] = "suspend_enabled",
[MSM_PM_MODE_ATTR_IDLE] = "idle_enabled",
@@ -332,7 +338,6 @@
*/
static void msm_pm_config_hw_after_power_up(void)
{
- return;
}
/*
@@ -343,6 +348,22 @@
return;
}
+/*
+ * Configure/Restore hardware registers in preparation for Retention.
+ */
+
+static void msm_pm_config_hw_after_retention(void)
+{
+ int ret;
+ ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING, false);
+ WARN_ON(ret);
+}
+
+static void msm_pm_config_hw_before_retention(void)
+{
+ return;
+}
+
/******************************************************************************
* Suspend Max Sleep Time
@@ -409,12 +430,17 @@
{
int ret = 0;
- msm_pm_config_hw_before_swfi();
+ msm_pm_config_hw_before_retention();
ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_POWER_RETENTION, false);
WARN_ON(ret);
- msm_arch_idle();
- ret = msm_spm_set_low_power_mode(MSM_SPM_MODE_CLOCK_GATING, false);
- WARN_ON(ret);
+
+ if (msm_pm_retention_tz_call)
+ scm_call_atomic1(SCM_SVC_BOOT, SCM_CMD_TERMINATE_PC,
+ SCM_L2_RETENTION);
+ else
+ msm_arch_idle();
+
+ msm_pm_config_hw_after_retention();
}
#ifdef CONFIG_CACHE_L2X0
@@ -676,6 +702,10 @@
case MSM_PM_SLEEP_MODE_RETENTION:
if (!allow)
break;
+ if (num_online_cpus() > 1) {
+ allow = false;
+ break;
+ }
/* fall through */
case MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT:
@@ -923,6 +953,11 @@
pm_sleep_ops = *ops;
}
+void __init msm_pm_set_tz_retention_flag(unsigned int flag)
+{
+ msm_pm_retention_tz_call = flag;
+}
+
static int __init msm_pm_init(void)
{
pgd_t *pc_pgd;
diff --git a/arch/arm/mach-msm/pm-boot.c b/arch/arm/mach-msm/pm-boot.c
index 079ed9c..ed15a0c 100644
--- a/arch/arm/mach-msm/pm-boot.c
+++ b/arch/arm/mach-msm/pm-boot.c
@@ -43,7 +43,7 @@
#ifdef CONFIG_MSM_SCM
static int __devinit msm_pm_tz_boot_init(void)
{
- int flag = 0;
+ unsigned int flag = 0;
if (num_possible_cpus() == 1)
flag = SCM_FLAG_WARMBOOT_CPU0;
else if (num_possible_cpus() == 2)
@@ -54,7 +54,7 @@
else
__WARN();
- return scm_set_boot_addr((void *)virt_to_phys(msm_pm_boot_entry), flag);
+ return scm_set_boot_addr(virt_to_phys(msm_pm_boot_entry), flag);
}
static void msm_pm_config_tz_before_pc(unsigned int cpu,
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index c722ff6..4dd6df3 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -86,6 +86,7 @@
void msm_pm_set_irq_extns(struct msm_pm_irq_calls *irq_calls);
int msm_pm_idle_enter(enum msm_pm_sleep_mode sleep_mode);
void msm_pm_cpu_enter_lowpower(unsigned int cpu);
+void __init msm_pm_set_tz_retention_flag(unsigned int flag);
#ifdef CONFIG_MSM_PM8X60
void msm_pm_set_rpm_wakeup_irq(unsigned int irq);
diff --git a/arch/arm/mach-msm/qdsp5/Makefile b/arch/arm/mach-msm/qdsp5/Makefile
index 89648fe..f4fe052 100644
--- a/arch/arm/mach-msm/qdsp5/Makefile
+++ b/arch/arm/mach-msm/qdsp5/Makefile
@@ -14,7 +14,7 @@
obj-y += audio_out.o audio_mp3.o audmgr.o audpp.o audrec.o audpreproc.o
obj-y += audio_evrc.o audio_qcelp.o audio_amrnb.o audio_aac.o audio_amrnb_in.o
obj-y += audio_wma.o audio_voicememo.o audio_pcm.o audio_amrwb.o audio_wmapro.o
-obj-y += snd.o snd_adie.o
+obj-y += snd.o snd_cad.o snd_adie.o audio_acdb.o
obj-$(CONFIG_ARCH_MSM7X27A) += audio_fm.o
obj-$(CONFIG_ARCH_MSM7X27A) += audio_mvs.o
obj-$(CONFIG_ARCH_MSM7X27A) += audio_lpa.o audio_ac3.o
diff --git a/arch/arm/mach-msm/qdsp5/audio_aac.c b/arch/arm/mach-msm/qdsp5/audio_aac.c
index 15e0590..01e529f 100644
--- a/arch/arm/mach-msm/qdsp5/audio_aac.c
+++ b/arch/arm/mach-msm/qdsp5/audio_aac.c
@@ -41,6 +41,7 @@
#include <mach/iommu_domains.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_aac_in.c b/arch/arm/mach-msm/qdsp5/audio_aac_in.c
index 99e10a4..4a35939 100644
--- a/arch/arm/mach-msm/qdsp5/audio_aac_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_aac_in.c
@@ -109,7 +109,6 @@
int out_frame_cnt;
struct msm_adsp_module *audrec;
- struct msm_adsp_module *audpre;
/* configuration to use on next enable */
@@ -150,6 +149,8 @@
struct ion_client *client;
struct ion_handle *input_buff_handle;
struct ion_handle *output_buff_handle;
+
+ struct audrec_session_info session_info; /*audrec session info*/
};
struct audio_frame {
@@ -273,6 +274,31 @@
return temp;
}
+/* ------------------- dsp --------------------- */
+static void audpre_dsp_event(void *data, unsigned id, void *event_data)
+{
+
+ uint16_t *msg = event_data;
+
+ if (!msg)
+ return;
+
+ switch (id) {
+ case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
+ MM_DBG("type %d, status_flag %d\n",\
+ msg[0], msg[1]);
+ break;
+ case AUDPREPROC_MSG_ERROR_MSG_ID:
+ MM_INFO("err_index %d\n", msg[0]);
+ break;
+ case ADSP_MESSAGE_ID:
+ MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
+ break;
+ default:
+ MM_ERR("unknown event %d\n", id);
+ }
+}
+
/* must be called with audio->lock held */
static int audaac_in_enable(struct audio_aac_in *audio)
{
@@ -293,16 +319,24 @@
if (rc < 0)
return rc;
- if (msm_adsp_enable(audio->audpre)) {
+ if (audpreproc_enable(audio->enc_id,
+ &audpre_dsp_event, audio)) {
+ MM_ERR("msm_adsp_enable(audpreproc) failed\n");
audmgr_disable(&audio->audmgr);
- MM_ERR("msm_adsp_enable(audpre) failed\n");
return -ENODEV;
}
+
+ /*update aurec session info in audpreproc layer*/
+ audio->session_info.session_id = audio->enc_id;
+ audio->session_info.sampling_freq =
+ convert_samp_index(audio->samp_rate);
+ audpreproc_update_audrec_info(&audio->session_info);
}
+
if (msm_adsp_enable(audio->audrec)) {
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
+ audpreproc_disable(audio->enc_id, audio);
audmgr_disable(&audio->audmgr);
- msm_adsp_disable(audio->audpre);
}
MM_ERR("msm_adsp_enable(audrec) failed\n");
return -ENODEV;
@@ -328,36 +362,17 @@
wake_up(&audio->wait);
msm_adsp_disable(audio->audrec);
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
- msm_adsp_disable(audio->audpre);
+ audpreproc_disable(audio->enc_id, audio);
+ /*reset the sampling frequency information at
+ audpreproc layer*/
+ audio->session_info.sampling_freq = 0;
+ audpreproc_update_audrec_info(&audio->session_info);
audmgr_disable(&audio->audmgr);
}
}
return 0;
}
-/* ------------------- dsp --------------------- */
-static void audpre_dsp_event(void *data, unsigned id, size_t len,
- void (*getevent)(void *ptr, size_t len))
-{
- uint16_t msg[2];
- getevent(msg, sizeof(msg));
-
- switch (id) {
- case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
- MM_DBG("type %d, status_flag %d\n", msg[0], msg[1]);
- break;
- case AUDPREPROC_MSG_ERROR_MSG_ID:
- MM_ERR("err_index %d\n", msg[0]);
- break;
- case ADSP_MESSAGE_ID:
- MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
- break;
- default:
- MM_ERR("unknown event %d\n", id);
- }
-}
-
-
static void audaac_in_get_dsp_frames(struct audio_aac_in *audio)
{
struct audio_frame *frame;
@@ -596,11 +611,7 @@
}
}
-struct msm_adsp_ops audpre_aac_adsp_ops = {
- .event = audpre_dsp_event,
-};
-
-struct msm_adsp_ops audrec_aac_adsp_ops = {
+static struct msm_adsp_ops audrec_aac_adsp_ops = {
.event = audrec_dsp_event,
};
@@ -1241,12 +1252,9 @@
audaac_in_flush(audio);
msm_adsp_put(audio->audrec);
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
- msm_adsp_put(audio->audpre);
audpreproc_aenc_free(audio->enc_id);
audio->audrec = NULL;
- audio->audpre = NULL;
audio->opened = 0;
if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) && \
@@ -1342,16 +1350,6 @@
goto done;
}
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
- rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
- &audpre_aac_adsp_ops, audio);
- if (rc) {
- msm_adsp_put(audio->audrec);
- audpreproc_aenc_free(audio->enc_id);
- goto done;
- }
- }
-
audio->dsp_cnt = 0;
audio->stopped = 0;
audio->wflush = 0;
@@ -1493,8 +1491,6 @@
ion_client_destroy(client);
client_create_error:
msm_adsp_put(audio->audrec);
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
- msm_adsp_put(audio->audpre);
audpreproc_aenc_free(audio->enc_id);
mutex_unlock(&audio->lock);
diff --git a/arch/arm/mach-msm/qdsp5/audio_ac3.c b/arch/arm/mach-msm/qdsp5/audio_ac3.c
index ee085c5..c0e2059 100644
--- a/arch/arm/mach-msm/qdsp5/audio_ac3.c
+++ b/arch/arm/mach-msm/qdsp5/audio_ac3.c
@@ -44,6 +44,7 @@
#include <mach/iommu_domains.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_acdb.c b/arch/arm/mach-msm/qdsp5/audio_acdb.c
new file mode 100644
index 0000000..16f23f4
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp5/audio_acdb.c
@@ -0,0 +1,2646 @@
+/* Copyright (c) 2012, Code Aurora Forum. 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/miscdevice.h>
+#include <linux/kthread.h>
+#include <linux/wait.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/android_pmem.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/uaccess.h>
+#include <linux/msm_audio.h>
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include <linux/memory_alloc.h>
+#include <linux/mfd/marimba.h>
+#include <mach/dal.h>
+#include <mach/iommu.h>
+#include <mach/iommu_domains.h>
+#include <mach/socinfo.h>
+#include <mach/qdsp5/qdsp5audpp.h>
+#include <mach/qdsp5/qdsp5audpreproc.h>
+#include <mach/qdsp5/qdsp5audppcmdi.h>
+#include <mach/qdsp5/qdsp5audpreproccmdi.h>
+#include <mach/qdsp5/qdsp5audpreprocmsg.h>
+#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/audio_acdbi.h>
+#include <mach/qdsp5/acdb_commands.h>
+#include <mach/qdsp5/audio_acdb_def.h>
+#include <mach/debug_mm.h>
+#include <mach/msm_memtypes.h>
+
+#include "audmgr.h"
+
+/* this is the ACDB device ID */
+#define DALDEVICEID_ACDB 0x02000069
+#define ACDB_PORT_NAME "DAL00"
+#define ACDB_CPU SMD_APPS_MODEM
+#define ACDB_BUF_SIZE 4096
+#define FLUENCE_BUF_SIZE 498
+
+#define ACDB_VALUES_NOT_FILLED 0
+#define ACDB_VALUES_FILLED 1
+#define MAX_RETRY 10
+
+#define COMMON_OBJ_ID 6
+
+/*below macro is used to align the session info received from
+Devctl driver with the state mentioned as not to alter the
+Existing code*/
+#define AUDREC_OFFSET 2
+/* rpc table index */
+enum {
+ ACDB_DAL_IOCTL = DALDEVICE_FIRST_DEVICE_API_IDX
+};
+
+enum {
+ CAL_DATA_READY = 0x1,
+ AUDPP_READY = 0x2,
+ AUDREC_READY = 0x4,
+};
+
+struct acdb_data {
+ void *handle;
+
+ u32 phys_addr;
+ u8 *virt_addr;
+
+ struct task_struct *cb_thread_task;
+ struct device_info_callback dev_cb;
+
+ u32 acdb_state;
+ struct audpp_event_callback audpp_cb;
+ struct audpreproc_event_callback audpreproc_cb;
+ struct dev_evt_msg *device_info;
+
+ audpp_cmd_cfg_object_params_pcm *pp_iir;
+ audpp_cmd_cfg_object_params_mbadrc *pp_mbadrc;
+ audpreproc_cmd_cfg_agc_params *preproc_agc;
+ audpreproc_cmd_cfg_iir_tuning_filter_params *preproc_iir;
+ audpreproc_cmd_cfg_ns_params *preproc_ns;
+ struct acdb_mbadrc_block mbadrc_block;
+
+ wait_queue_head_t wait;
+ struct mutex acdb_mutex;
+ u32 device_cb_compl;
+ u32 audpp_cb_compl;
+ u32 preproc_cb_compl;
+ u8 preproc_stream_id;
+ u8 audrec_applied;
+ u32 multiple_sessions;
+ u32 cur_tx_session;
+ struct acdb_result acdb_result;
+
+ spinlock_t dsp_lock;
+ int dec_id;
+ audpp_cmd_cfg_object_params_eqalizer eq;
+ struct audrec_session_info session_info;
+ /*pmem info*/
+ int pmem_fd;
+ unsigned long paddr;
+ unsigned long kvaddr;
+ unsigned long pmem_len;
+ struct file *file;
+ /* pmem for get acdb blk */
+ unsigned long get_blk_paddr;
+ u8 *get_blk_kvaddr;
+ void *map_v_get_blk;
+};
+
+static struct acdb_data acdb_data;
+
+struct acdb_cache_node {
+ u32 node_status;
+ s32 stream_id;
+ u32 phys_addr_acdb_values;
+ void *map_v_addr;
+ u8 *virt_addr_acdb_values;
+ struct dev_evt_msg device_info;
+};
+
+struct acdb_cache_node acdb_cache_rx;
+
+/*for TX devices acdb values are applied based on AUDREC session and
+the depth of the tx cache is define by number of AUDREC sessions supported*/
+struct acdb_cache_node acdb_cache_tx;
+
+/*Audrec session info includes Attributes Sampling frequency and enc_id */
+struct audrec_session_info session_info;
+#ifdef CONFIG_DEBUG_FS
+
+#define RTC_MAX_TIMEOUT 500 /* 500 ms */
+#define PMEM_RTC_ACDB_QUERY_MEM 4096
+#define EXTRACT_HIGH_WORD(x) ((x & 0xFFFF0000)>>16)
+#define EXTRACT_LOW_WORD(x) (0x0000FFFF & x)
+#define ACDB_RTC_TX 0xF1
+#define ACDB_RTC_RX 0x1F
+
+
+static u32 acdb_audpp_entry[][4] = {
+
+ {
+ ABID_AUDIO_RTC_VOLUME_PAN_RX,\
+ IID_AUDIO_RTC_VOLUME_PAN_PARAMETERS,\
+ AUDPP_CMD_VOLUME_PAN,\
+ ACDB_RTC_RX
+ },
+ {
+ ABID_AUDIO_IIR_RX,\
+ IID_AUDIO_IIR_COEFF,\
+ AUDPP_CMD_IIR_TUNING_FILTER,
+ ACDB_RTC_RX
+ },
+ {
+ ABID_AUDIO_RTC_EQUALIZER_PARAMETERS,\
+ IID_AUDIO_RTC_EQUALIZER_PARAMETERS,\
+ AUDPP_CMD_EQUALIZER,\
+ ACDB_RTC_RX
+ },
+ {
+ ABID_AUDIO_RTC_SPA,\
+ IID_AUDIO_RTC_SPA_PARAMETERS,\
+ AUDPP_CMD_SPECTROGRAM,
+ ACDB_RTC_RX
+ },
+ {
+ ABID_AUDIO_STF_RX,\
+ IID_AUDIO_IIR_COEFF,\
+ AUDPP_CMD_SIDECHAIN_TUNING_FILTER,\
+ ACDB_RTC_RX
+ },
+ {
+ ABID_AUDIO_MBADRC_RX,\
+ IID_AUDIO_RTC_MBADRC_PARAMETERS,\
+ AUDPP_CMD_MBADRC,\
+ ACDB_RTC_RX
+ },
+ {
+ ABID_AUDIO_AGC_TX,\
+ IID_AUDIO_AGC_PARAMETERS,\
+ AUDPREPROC_CMD_CFG_AGC_PARAMS,\
+ ACDB_RTC_TX
+ },
+ {
+ ABID_AUDIO_AGC_TX,\
+ IID_AUDIO_RTC_AGC_PARAMETERS,\
+ AUDPREPROC_CMD_CFG_AGC_PARAMS,\
+ ACDB_RTC_TX
+ },
+ {
+ ABID_AUDIO_NS_TX,\
+ IID_NS_PARAMETERS,\
+ AUDPREPROC_CMD_CFG_NS_PARAMS,\
+ ACDB_RTC_TX
+ },
+ {
+ ABID_AUDIO_IIR_TX,\
+ IID_AUDIO_RTC_TX_IIR_COEFF,\
+ AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS,\
+ ACDB_RTC_TX
+ },
+ {
+ ABID_AUDIO_IIR_TX,\
+ IID_AUDIO_IIR_COEFF,\
+ AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS,\
+ ACDB_RTC_TX
+ }
+ /*Any new entries should be added here*/
+};
+
+static struct dentry *get_set_abid_dentry;
+static struct dentry *get_set_abid_data_dentry;
+
+struct rtc_acdb_pmem {
+ u8 *viraddr;
+ int32_t phys;
+ void *map_v_rtc;
+};
+
+struct rtc_acdb_data {
+ u32 acdb_id;
+ u32 cmd_id;
+ u32 set_abid;
+ u32 set_iid;
+ u32 abid;
+ u32 err;
+ bool valid_abid;
+ u32 tx_rx_ctl;
+ struct rtc_acdb_pmem rtc_read;
+ struct rtc_acdb_pmem rtc_write;
+ wait_queue_head_t wait;
+};
+
+struct get_abid {
+ u32 cmd_id;
+ u32 acdb_id;
+ u32 set_abid;
+ u32 set_iid;
+};
+
+struct acdb_block_mbadrc_rtc {
+ u16 enable;
+ u16 num_bands;
+ u16 down_samp_level;
+ u16 adrc_delay;
+ u16 ext_buf_size;
+ u16 ext_partition;
+ u16 ext_buf_msw;
+ u16 ext_buf_lsw;
+ struct adrc_config adrc_band[AUDPP_MAX_MBADRC_BANDS];
+ signed int ext_buff[196];
+} __packed;
+
+enum {
+ ACDB_RTC_SUCCESS,
+ ACDB_RTC_ERR_INVALID_DEVICE,
+ ACDB_RTC_ERR_DEVICE_INACTIVE,
+ ACDB_RTC_ERR_INVALID_ABID,
+ ACDB_RTC_DSP_FAILURE,
+ ACDB_RTC_DSP_FEATURE_NOT_AVAILABLE,
+ ACDB_RTC_ERR_INVALID_LEN,
+ ACDB_RTC_ERR_UNKNOWN_FAILURE,
+ ACDB_RTC_PENDING_RESPONSE,
+ ACDB_RTC_INIT_FAILURE,
+};
+
+static struct rtc_acdb_data rtc_acdb;
+
+static int rtc_getsetabid_dbg_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ MM_DBG("GET-SET ABID Open debug intf %s\n",\
+ (char *) file->private_data);
+ return 0;
+}
+
+static bool get_feature_id(u32 set_abid, u32 iid, unsigned short *feature_id)
+{
+ bool ret_value = false;
+ int i = 0;
+
+ for (; i < (sizeof(acdb_audpp_entry) / sizeof(acdb_audpp_entry[0]));\
+ i++) {
+ if (acdb_audpp_entry[i][0] == set_abid &&
+ acdb_audpp_entry[i][1] == iid) {
+ *feature_id = acdb_audpp_entry[i][2];
+ rtc_acdb.tx_rx_ctl = acdb_audpp_entry[i][3];
+ ret_value = true;
+ break;
+ }
+ }
+ return ret_value;
+}
+static ssize_t rtc_getsetabid_dbg_write(struct file *filp,
+ const char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ struct get_abid write_abid;
+ unsigned short feat_id = 0;
+ rtc_acdb.valid_abid = false;
+
+ if (copy_from_user(&write_abid, \
+ (void *)ubuf, sizeof(struct get_abid))) {
+ MM_ERR("ACDB DATA WRITE - INVALID READ LEN\n");
+ rtc_acdb.err = ACDB_RTC_ERR_INVALID_LEN;
+ return cnt;
+ }
+ MM_DBG("SET ABID : Cmd ID: %d Device:%d ABID:%d IID : %d cnt: %d\n",\
+ write_abid.cmd_id, write_abid.acdb_id,\
+ write_abid.set_abid, write_abid.set_iid, cnt);
+ if (write_abid.acdb_id > ACDB_ID_MAX ||
+ write_abid.acdb_id < ACDB_ID_HANDSET_SPKR){
+ rtc_acdb.err = ACDB_RTC_ERR_INVALID_DEVICE;
+ return cnt;
+ }
+
+ rtc_acdb.err = ACDB_RTC_ERR_INVALID_ABID;
+ rtc_acdb.abid = write_abid.set_abid;
+ if (get_feature_id(write_abid.set_abid, \
+ write_abid.set_iid, &feat_id)) {
+ rtc_acdb.err = ACDB_RTC_SUCCESS;
+ rtc_acdb.cmd_id = write_abid.cmd_id;
+ rtc_acdb.acdb_id = write_abid.acdb_id;
+ rtc_acdb.set_abid = feat_id;
+ rtc_acdb.valid_abid = true;
+ rtc_acdb.set_iid = write_abid.set_iid;
+ }
+ return cnt;
+}
+static ssize_t rtc_getsetabid_dbg_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ static char buffer[1024];
+ int n = 0;
+ u32 msg = rtc_acdb.err;
+ memcpy(buffer, &rtc_acdb.cmd_id, sizeof(struct get_abid));
+ memcpy(buffer+16, &msg, 4);
+ n = 20;
+ MM_INFO("SET ABID : Cmd ID: %x Device:%x ABID:%x IID : %x Err: %d\n",\
+ rtc_acdb.cmd_id, rtc_acdb.acdb_id, rtc_acdb.set_abid,\
+ rtc_acdb.set_iid, rtc_acdb.err);
+ return simple_read_from_buffer(buf, count, ppos, buffer, n);
+}
+
+static int rtc_getsetabid_data_dbg_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ MM_INFO("GET-SET ABID DATA Open debug intf %s\n",
+ (char *) file->private_data);
+ return 0;
+}
+
+void acdb_rtc_set_err(u32 err_code)
+{
+ if (rtc_acdb.err == ACDB_RTC_PENDING_RESPONSE) {
+ if (err_code == 0xFFFF) {
+ rtc_acdb.err = ACDB_RTC_SUCCESS;
+ MM_INFO("RTC READ SUCCESS---\n");
+ } else if (err_code == 0) {
+ rtc_acdb.err = ACDB_RTC_DSP_FAILURE;
+ MM_INFO("RTC READ FAIL---\n");
+ } else if (err_code == 1) {
+ rtc_acdb.err = ACDB_RTC_DSP_FEATURE_NOT_AVAILABLE;
+ MM_INFO("RTC READ FEAT UNAVAILABLE---\n");
+ } else {
+ rtc_acdb.err = ACDB_RTC_DSP_FAILURE;
+ MM_INFO("RTC Err CODE---\n");
+ }
+ } else {
+ rtc_acdb.err = ACDB_RTC_DSP_FAILURE;
+ MM_ERR("RTC Err code Invalid State\n");
+ }
+ wake_up(&rtc_acdb.wait);
+}
+
+static ssize_t rtc_getsetabid_data_dbg_read(struct file *file,
+ char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ static char buffer[PMEM_RTC_ACDB_QUERY_MEM];
+ int rc, n = 0;
+ int counter = 0;
+ struct rtc_acdb_pmem *rtc_read = &rtc_acdb.rtc_read;
+ memset(&buffer, 0, PMEM_RTC_ACDB_QUERY_MEM);
+
+ if (rtc_acdb.valid_abid != true) {
+ MM_ERR("ACDB DATA READ ---INVALID ABID\n");
+ n = 0;
+ rtc_acdb.err = ACDB_RTC_ERR_INVALID_ABID;
+ } else {
+ if (PMEM_RTC_ACDB_QUERY_MEM < count) {
+ MM_ERR("ACDB DATA READ ---"\
+ "INVALID READ LEN %x\n", count);
+ n = 0;
+ rtc_acdb.err = ACDB_RTC_ERR_INVALID_LEN;
+ } else {
+ rtc_acdb.err = ACDB_RTC_PENDING_RESPONSE;
+ if (rtc_read->viraddr != NULL) {
+ memset(rtc_read->viraddr,
+ 0, PMEM_RTC_ACDB_QUERY_MEM);
+ }
+ if (rtc_acdb.tx_rx_ctl == ACDB_RTC_RX) {
+ struct rtc_audpp_read_data rtc_read_cmd;
+ rtc_read_cmd.cmd_id =
+ AUDPP_CMD_PP_FEAT_QUERY_PARAMS;
+ rtc_read_cmd.obj_id =
+ AUDPP_CMD_COPP_STREAM;
+ rtc_read_cmd.feature_id = rtc_acdb.set_abid;
+ rtc_read_cmd.extbufsizemsw =
+ EXTRACT_HIGH_WORD(\
+ PMEM_RTC_ACDB_QUERY_MEM);
+ rtc_read_cmd.extbufsizelsw =
+ EXTRACT_LOW_WORD(\
+ PMEM_RTC_ACDB_QUERY_MEM);
+ rtc_read_cmd.extpart = 0x0000;
+ rtc_read_cmd.extbufstartmsw =
+ EXTRACT_HIGH_WORD(rtc_read->phys);
+ rtc_read_cmd.extbufstartlsw =
+ EXTRACT_LOW_WORD(rtc_read->phys);
+ rc = audpp_send_queue2(&rtc_read_cmd,
+ sizeof(rtc_read_cmd));
+ } else if (rtc_acdb.tx_rx_ctl == ACDB_RTC_TX) {
+ struct rtc_audpreproc_read_data rtc_audpreproc;
+ rtc_audpreproc.cmd_id =
+ AUDPREPROC_CMD_FEAT_QUERY_PARAMS;
+ rtc_audpreproc.feature_id = rtc_acdb.set_abid;
+ /*AUDREC1 is used for pcm recording */
+ rtc_audpreproc.stream_id = 1;
+ rtc_audpreproc.extbufsizemsw =
+ EXTRACT_HIGH_WORD(\
+ PMEM_RTC_ACDB_QUERY_MEM);
+ rtc_audpreproc.extbufsizelsw =
+ EXTRACT_LOW_WORD(\
+ PMEM_RTC_ACDB_QUERY_MEM);
+ rtc_audpreproc.extpart = 0x0000;
+ rtc_audpreproc.extbufstartmsw =
+ EXTRACT_HIGH_WORD(rtc_read->phys);
+ rtc_audpreproc.extbufstartlsw =
+ EXTRACT_LOW_WORD(rtc_read->phys);
+ rc = audpreproc_send_preproccmdqueue(
+ &rtc_audpreproc,\
+ sizeof(rtc_audpreproc));
+ MM_INFO("ACDB READ Command RC --->%x,"\
+ "stream_id %x\n", rc,
+ acdb_data.preproc_stream_id);
+ }
+ rc = wait_event_timeout(rtc_acdb.wait,
+ (rtc_acdb.err !=
+ ACDB_RTC_PENDING_RESPONSE),
+ msecs_to_jiffies(RTC_MAX_TIMEOUT));
+ MM_INFO("ACDB READ ACK Count = %x Err = %x\n",
+ count, rtc_acdb.err);
+ {
+ if (rtc_acdb.err == ACDB_RTC_SUCCESS
+ && rtc_read->viraddr != NULL) {
+ memcpy(buffer, rtc_read->viraddr, count);
+ n = count;
+ while (counter < count) {
+ MM_DBG("%x", \
+ rtc_read->viraddr[counter]);
+ counter++;
+ }
+ }
+ }
+ }
+ }
+ return simple_read_from_buffer(buf, count, ppos, buffer, n);
+}
+
+static bool acdb_set_tx_rtc(const char *ubuf, size_t writecount)
+{
+ audpreproc_cmd_cfg_iir_tuning_filter_params *preproc_iir;
+ audpreproc_cmd_cfg_agc_params *preproc_agc;
+ audpreproc_cmd_cfg_ns_params *preproc_ns;
+ s32 result = 0;
+ bool retval = false;
+ unsigned short iircmdsize =
+ sizeof(audpreproc_cmd_cfg_iir_tuning_filter_params);
+ unsigned short iircmdid = AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS;
+
+ rtc_acdb.err = ACDB_RTC_ERR_UNKNOWN_FAILURE;
+
+ switch (rtc_acdb.set_abid) {
+
+ case AUDPREPROC_CMD_CFG_AGC_PARAMS:
+ {
+ preproc_agc = kmalloc(sizeof(\
+ audpreproc_cmd_cfg_agc_params),\
+ GFP_KERNEL);
+ if ((sizeof(audpreproc_cmd_cfg_agc_params) -\
+ (sizeof(unsigned short)))
+ < writecount) {
+ MM_ERR("ACDB DATA WRITE --"\
+ "AGC TX writecount > DSP struct\n");
+ } else {
+ if (preproc_agc != NULL) {
+ char *base; unsigned short offset;
+ unsigned short *offset_addr;
+ base = (char *)preproc_agc;
+ offset = offsetof(\
+ audpreproc_cmd_cfg_agc_params,\
+ tx_agc_param_mask);
+ offset_addr = (unsigned short *)(base + offset);
+ if ((copy_from_user(offset_addr,\
+ (void *)ubuf, writecount)) == 0x00) {
+ preproc_agc->cmd_id =
+ AUDPREPROC_CMD_CFG_AGC_PARAMS;
+
+ result = audpreproc_dsp_set_agc(
+ preproc_agc,
+ sizeof(\
+ audpreproc_cmd_cfg_agc_params));
+ if (result) {
+ MM_ERR("ACDB=> Failed to "\
+ "send AGC data to "\
+ "preproc)\n");
+ } else {
+ retval = true;
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE ---"\
+ "GC Tx copy_from_user Fail\n");
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE --"\
+ "AGC TX kalloc Failed LEN\n");
+ }
+ }
+ if (preproc_agc != NULL)
+ kfree(preproc_agc);
+ break;
+ }
+ case AUDPREPROC_CMD_CFG_NS_PARAMS:
+ {
+
+ preproc_ns = kmalloc(sizeof(\
+ audpreproc_cmd_cfg_ns_params),\
+ GFP_KERNEL);
+ if ((sizeof(audpreproc_cmd_cfg_ns_params) -\
+ (sizeof(unsigned short)))
+ < writecount) {
+ MM_ERR("ACDB DATA WRITE --"\
+ "NS TX writecount > DSP struct\n");
+ } else {
+ if (preproc_ns != NULL) {
+ char *base; unsigned short offset;
+ unsigned short *offset_addr;
+ base = (char *)preproc_ns;
+ offset = offsetof(\
+ audpreproc_cmd_cfg_ns_params,\
+ ec_mode_new);
+ offset_addr = (unsigned short *)(base + offset);
+ if ((copy_from_user(offset_addr,\
+ (void *)ubuf, writecount)) == 0x00) {
+ preproc_ns->cmd_id =
+ AUDPREPROC_CMD_CFG_NS_PARAMS;
+ result = audpreproc_dsp_set_ns(
+ preproc_ns,
+ sizeof(\
+ audpreproc_cmd_cfg_ns_params));
+ if (result) {
+ MM_ERR("ACDB=> Failed to send "\
+ "NS data to preproc\n");
+ } else {
+ retval = true;
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE ---NS Tx "\
+ "copy_from_user Fail\n");
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE --NS TX "\
+ "kalloc Failed LEN\n");
+ }
+ }
+ if (preproc_ns != NULL)
+ kfree(preproc_ns);
+ break;
+ }
+ case AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS:
+ {
+
+ preproc_iir = kmalloc(sizeof(\
+ audpreproc_cmd_cfg_iir_tuning_filter_params),\
+ GFP_KERNEL);
+ if ((sizeof(\
+ audpreproc_cmd_cfg_iir_tuning_filter_params)-\
+ (sizeof(unsigned short)))
+ < writecount) {
+ MM_ERR("ACDB DATA WRITE --IIR TX writecount "\
+ "> DSP struct\n");
+ } else {
+ if (preproc_iir != NULL) {
+ char *base; unsigned short offset;
+ unsigned short *offset_addr;
+ base = (char *)preproc_iir;
+ offset = offsetof(\
+ audpreproc_cmd_cfg_iir_tuning_filter_params,\
+ active_flag);
+ offset_addr = (unsigned short *)(base + \
+ offset);
+ if ((copy_from_user(offset_addr,\
+ (void *)ubuf, writecount)) == 0x00) {
+ preproc_iir->cmd_id = iircmdid;
+ result = audpreproc_dsp_set_iir(\
+ preproc_iir,
+ iircmdsize);
+ if (result) {
+ MM_ERR("ACDB=> Failed to send "\
+ "IIR data to preproc\n");
+ } else {
+ retval = true;
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE ---IIR Tx "\
+ "copy_from_user Fail\n");
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE --IIR TX kalloc "\
+ "Failed LEN\n");
+ }
+ }
+ if (preproc_iir != NULL)
+ kfree(preproc_iir);
+ break;
+ }
+ }
+ return retval;
+}
+
+static bool acdb_set_rx_rtc(const char *ubuf, size_t writecount)
+{
+
+ audpp_cmd_cfg_object_params_volume *volpan_config;
+ audpp_cmd_cfg_object_params_mbadrc *mbadrc_config;
+ struct acdb_block_mbadrc_rtc *acdb_mbadrc_rtc;
+ audpp_cmd_cfg_object_params_eqalizer *eq_config;
+ audpp_cmd_cfg_object_params_pcm *iir_config;
+ struct rtc_acdb_pmem *rtc_write = &rtc_acdb.rtc_write;
+ s32 result = 0;
+ bool retval = false;
+
+ switch (rtc_acdb.set_abid) {
+ case AUDPP_CMD_VOLUME_PAN:
+ {
+ volpan_config = kmalloc(sizeof(\
+ audpp_cmd_cfg_object_params_volume),\
+ GFP_KERNEL);
+ if ((sizeof(audpp_cmd_cfg_object_params_volume) -\
+ sizeof(audpp_cmd_cfg_object_params_common))
+ < writecount) {
+ MM_ERR("ACDB DATA WRITE -- "\
+ "VolPan writecount > DSP struct\n");
+ } else {
+ if (volpan_config != NULL) {
+ char *base; unsigned short offset;
+ unsigned short *offset_addr;
+ base = (char *)volpan_config;
+ offset = offsetof(\
+ audpp_cmd_cfg_object_params_volume,\
+ volume);
+ offset_addr = (unsigned short *)(base+offset);
+ if ((copy_from_user(offset_addr,\
+ (void *)ubuf, writecount)) == 0x00) {
+ MM_ERR("ACDB RX WRITE DATA: "\
+ "AUDPP_CMD_VOLUME_PAN\n");
+ result = audpp_set_volume_and_pan(
+ COMMON_OBJ_ID,
+ volpan_config->volume,
+ volpan_config->pan);
+ if (result) {
+ MM_ERR("ACDB=> Failed to "\
+ "send VOLPAN data to"
+ " postproc\n");
+ } else {
+ retval = true;
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE ---"\
+ "copy_from_user Fail\n");
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE --"\
+ "Vol Pan kalloc Failed LEN\n");
+ }
+ }
+ if (volpan_config != NULL)
+ kfree(volpan_config);
+ break;
+ }
+
+ case AUDPP_CMD_IIR_TUNING_FILTER:
+ {
+ iir_config = kmalloc(sizeof(\
+ audpp_cmd_cfg_object_params_pcm),\
+ GFP_KERNEL);
+ if ((sizeof(audpp_cmd_cfg_object_params_pcm) -\
+ sizeof(audpp_cmd_cfg_object_params_common))
+ < writecount) {
+ MM_ERR("ACDB DATA WRITE --"\
+ "IIR RX writecount > DSP struct\n");
+ } else {
+ if (iir_config != NULL) {
+ char *base; unsigned short offset;
+ unsigned short *offset_addr;
+ base = (char *)iir_config;
+ offset = offsetof(\
+ audpp_cmd_cfg_object_params_pcm,\
+ active_flag);
+ offset_addr = (unsigned short *)(base+offset);
+ if ((copy_from_user(offset_addr,\
+ (void *)ubuf, writecount)) == 0x00) {
+ MM_ERR("ACDB RX WRITE DATA:"\
+ "AUDPP_CMD_IIR_TUNING_FILTER\n");
+ result = audpp_dsp_set_rx_iir(
+ COMMON_OBJ_ID,
+ iir_config->active_flag,\
+ iir_config);
+ if (result) {
+ MM_ERR("ACDB=> Failed to send"\
+ "IIR data to"\
+ "postproc\n");
+ } else {
+ retval = true;
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE ---"\
+ "IIR Rx copy_from_user Fail\n");
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE --"\
+ "acdb_iir_block kalloc Failed LEN\n");
+ }
+ }
+ if (iir_config != NULL)
+ kfree(iir_config);
+ break;
+ }
+ case AUDPP_CMD_EQUALIZER:
+ {
+ eq_config = kmalloc(sizeof(\
+ audpp_cmd_cfg_object_params_eqalizer),\
+ GFP_KERNEL);
+ if ((sizeof(audpp_cmd_cfg_object_params_eqalizer) -\
+ sizeof(audpp_cmd_cfg_object_params_common))
+ < writecount) {
+ MM_ERR("ACDB DATA WRITE --"\
+ "EQ RX writecount > DSP struct\n");
+ } else {
+ if (eq_config != NULL) {
+ char *base; unsigned short offset;
+ unsigned short *offset_addr;
+ base = (char *)eq_config;
+ offset = offsetof(\
+ audpp_cmd_cfg_object_params_eqalizer,\
+ eq_flag);
+ offset_addr = (unsigned short *)(base+offset);
+ if ((copy_from_user(offset_addr,\
+ (void *)ubuf, writecount)) == 0x00) {
+ MM_ERR("ACDB RX WRITE"\
+ "DATA:AUDPP_CMD_EQUALIZER\n");
+ result = audpp_dsp_set_eq(
+ COMMON_OBJ_ID,
+ eq_config->eq_flag,\
+ eq_config);
+ if (result) {
+ MM_ERR("ACDB=> Failed to "\
+ "send EQ data to postproc\n");
+ } else {
+ retval = true;
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE ---"\
+ "EQ Rx copy_from_user Fail\n");
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE --"\
+ "EQ kalloc Failed LEN\n");
+ }
+ }
+ if (eq_config != NULL)
+ kfree(eq_config);
+ break;
+ }
+
+ case AUDPP_CMD_MBADRC:
+ {
+ acdb_mbadrc_rtc = kmalloc(sizeof(struct \
+ acdb_block_mbadrc_rtc),\
+ GFP_KERNEL);
+ mbadrc_config = kmalloc(sizeof(\
+ audpp_cmd_cfg_object_params_mbadrc),\
+ GFP_KERNEL);
+ if (mbadrc_config != NULL && acdb_mbadrc_rtc != NULL) {
+ if ((copy_from_user(acdb_mbadrc_rtc,\
+ (void *)ubuf,
+ sizeof(struct acdb_block_mbadrc_rtc)))
+ == 0x00) {
+
+ memset(mbadrc_config, 0,
+ sizeof(\
+ audpp_cmd_cfg_object_params_mbadrc));
+
+ mbadrc_config->enable =
+ acdb_mbadrc_rtc->enable;
+ mbadrc_config->num_bands =
+ acdb_mbadrc_rtc->num_bands;
+ mbadrc_config->down_samp_level =
+ acdb_mbadrc_rtc->down_samp_level;
+ mbadrc_config->adrc_delay =
+ acdb_mbadrc_rtc->adrc_delay;
+ memcpy(mbadrc_config->adrc_band,\
+ acdb_mbadrc_rtc->adrc_band,\
+ AUDPP_MAX_MBADRC_BANDS *\
+ sizeof(struct adrc_config));
+ if (mbadrc_config->num_bands > 1) {
+ mbadrc_config->ext_buf_size =
+ (97 * 2) + (33 * 2 * \
+ (mbadrc_config->num_bands - 2));
+ }
+ mbadrc_config->ext_partition = 0;
+ mbadrc_config->ext_buf_lsw =
+ (u16) EXTRACT_LOW_WORD(\
+ rtc_write->phys);
+ mbadrc_config->ext_buf_msw =
+ (u16) EXTRACT_HIGH_WORD(\
+ rtc_write->phys);
+ memcpy(rtc_write->viraddr,
+ acdb_mbadrc_rtc->ext_buff,
+ (196*sizeof(signed int)));
+ result = audpp_dsp_set_mbadrc(
+ COMMON_OBJ_ID,
+ mbadrc_config->enable,
+ mbadrc_config);
+ if (result) {
+ MM_ERR("ACDB=> Failed to "\
+ "Send MBADRC data "\
+ "to postproc\n");
+ } else {
+ retval = true;
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE ---"\
+ "MBADRC Rx copy_from_user Fail\n");
+ }
+ } else {
+ MM_ERR("ACDB DATA WRITE --MBADRC kalloc Failed LEN\n");
+ }
+ if (mbadrc_config != NULL)
+ kfree(mbadrc_config);
+ if (acdb_mbadrc_rtc != NULL)
+ kfree(acdb_mbadrc_rtc);
+ break;
+ }
+ }
+ return retval;
+}
+static ssize_t rtc_getsetabid_data_dbg_write(struct file *filp,
+ const char __user *ubuf,
+ size_t cnt, loff_t *ppos)
+{
+ if (rtc_acdb.valid_abid != true) {
+ MM_INFO("ACDB DATA READ ---INVALID ABID\n");
+ rtc_acdb.err = ACDB_RTC_ERR_INVALID_ABID;
+ } else {
+ if (rtc_acdb.tx_rx_ctl == ACDB_RTC_RX) {
+ if (acdb_set_rx_rtc(ubuf, cnt)) {
+ rtc_acdb.err = ACDB_RTC_SUCCESS;
+ } else {
+ rtc_acdb.err = ACDB_RTC_ERR_UNKNOWN_FAILURE;
+ cnt = 0;
+ }
+ } else if (rtc_acdb.tx_rx_ctl == ACDB_RTC_TX) {
+ if (acdb_set_tx_rtc(ubuf, cnt)) {
+ rtc_acdb.err = ACDB_RTC_SUCCESS;
+ } else {
+ rtc_acdb.err = ACDB_RTC_ERR_UNKNOWN_FAILURE;
+ cnt = 0;
+ }
+ }
+ }
+ return cnt;
+}
+
+
+static const struct file_operations rtc_acdb_data_debug_fops = {
+ .open = rtc_getsetabid_data_dbg_open,
+ .write = rtc_getsetabid_data_dbg_write,
+ .read = rtc_getsetabid_data_dbg_read
+};
+
+static const struct file_operations rtc_acdb_debug_fops = {
+ .open = rtc_getsetabid_dbg_open,
+ .write = rtc_getsetabid_dbg_write,
+ .read = rtc_getsetabid_dbg_read
+};
+
+static void rtc_acdb_deinit(void)
+{
+ struct rtc_acdb_pmem *rtc_read = &rtc_acdb.rtc_read;
+ struct rtc_acdb_pmem *rtc_write = &rtc_acdb.rtc_write;
+ if (get_set_abid_dentry) {
+ MM_DBG("GetSet ABID remove debugfs\n");
+ debugfs_remove(get_set_abid_dentry);
+ }
+
+ if (get_set_abid_data_dentry) {
+ MM_DBG("GetSet ABID remove debugfs\n");
+ debugfs_remove(get_set_abid_data_dentry);
+ }
+ rtc_acdb.abid = 0;
+ rtc_acdb.acdb_id = 0;
+ rtc_acdb.cmd_id = 0;
+ rtc_acdb.err = 1;
+ rtc_acdb.set_abid = 0;
+ rtc_acdb.set_iid = 0;
+ rtc_acdb.tx_rx_ctl = 0;
+ rtc_acdb.valid_abid = false;
+
+ if (rtc_read->viraddr != NULL || ((void *)rtc_read->phys) != NULL) {
+ iounmap(rtc_read->map_v_rtc);
+ free_contiguous_memory_by_paddr(rtc_read->phys);
+ }
+ if (rtc_write->viraddr != NULL || ((void *)rtc_write->phys) != NULL) {
+ iounmap(rtc_write->map_v_rtc);
+ free_contiguous_memory_by_paddr(rtc_write->phys);
+ }
+}
+
+static bool rtc_acdb_init(void)
+{
+ struct rtc_acdb_pmem *rtc_read = &rtc_acdb.rtc_read;
+ struct rtc_acdb_pmem *rtc_write = &rtc_acdb.rtc_write;
+ s32 result = 0;
+ char name[sizeof "get_set_abid"+1];
+ char name1[sizeof "get_set_abid_data"+1];
+ rtc_acdb.abid = 0;
+ rtc_acdb.acdb_id = 0;
+ rtc_acdb.cmd_id = 0;
+ rtc_acdb.err = 1;
+ rtc_acdb.set_abid = 0;
+ rtc_acdb.set_iid = 0;
+ rtc_acdb.valid_abid = false;
+ rtc_acdb.tx_rx_ctl = 0;
+
+ snprintf(name, sizeof name, "get_set_abid");
+ get_set_abid_dentry = debugfs_create_file(name,
+ S_IFREG | S_IRUGO | S_IWUGO,
+ NULL, NULL, &rtc_acdb_debug_fops);
+ if (IS_ERR(get_set_abid_dentry)) {
+ MM_ERR("SET GET ABID debugfs_create_file failed\n");
+ return false;
+ }
+
+ snprintf(name1, sizeof name1, "get_set_abid_data");
+ get_set_abid_data_dentry = debugfs_create_file(name1,
+ S_IFREG | S_IRUGO | S_IWUGO,
+ NULL, NULL,
+ &rtc_acdb_data_debug_fops);
+ if (IS_ERR(get_set_abid_data_dentry)) {
+ MM_ERR("SET GET ABID DATA"\
+ " debugfs_create_file failed\n");
+ return false;
+ }
+
+ rtc_read->phys = allocate_contiguous_ebi_nomap(PMEM_RTC_ACDB_QUERY_MEM,
+ SZ_4K);
+
+ if (!rtc_read->phys) {
+ MM_ERR("ACDB Cannot allocate physical memory\n");
+ result = -ENOMEM;
+ goto error;
+ }
+ rtc_read->map_v_rtc = ioremap(rtc_read->phys,
+ PMEM_RTC_ACDB_QUERY_MEM);
+
+ if (IS_ERR(rtc_read->map_v_rtc)) {
+ MM_ERR("ACDB Could not map physical address\n");
+ result = -ENOMEM;
+ goto error;
+ }
+ rtc_read->viraddr = rtc_read->map_v_rtc;
+ memset(rtc_read->viraddr, 0, PMEM_RTC_ACDB_QUERY_MEM);
+
+ rtc_write->phys = allocate_contiguous_ebi_nomap(PMEM_RTC_ACDB_QUERY_MEM,
+ SZ_4K);
+
+ if (!rtc_write->phys) {
+ MM_ERR("ACDB Cannot allocate physical memory\n");
+ result = -ENOMEM;
+ goto error;
+ }
+ rtc_write->map_v_rtc = ioremap(rtc_write->phys,
+ PMEM_RTC_ACDB_QUERY_MEM);
+
+ if (IS_ERR(rtc_write->map_v_rtc)) {
+ MM_ERR("ACDB Could not map physical address\n");
+ result = -ENOMEM;
+ goto error;
+ }
+ rtc_write->viraddr = rtc_write->map_v_rtc;
+ memset(rtc_write->viraddr, 0, PMEM_RTC_ACDB_QUERY_MEM);
+ init_waitqueue_head(&rtc_acdb.wait);
+ return true;
+error:
+ MM_DBG("INIT RTC FAILED REMOVING RTC DEBUG FS\n");
+ if (get_set_abid_dentry) {
+ MM_DBG("GetSet ABID remove debugfs\n");
+ debugfs_remove(get_set_abid_dentry);
+ }
+
+ if (get_set_abid_data_dentry) {
+ MM_DBG("GetSet ABID remove debugfs\n");
+ debugfs_remove(get_set_abid_data_dentry);
+ }
+ if (rtc_read->viraddr != NULL || ((void *)rtc_read->phys) != NULL) {
+ iounmap(rtc_read->map_v_rtc);
+ free_contiguous_memory_by_paddr(rtc_read->phys);
+ }
+ if (rtc_write->viraddr != NULL || ((void *)rtc_write->phys) != NULL) {
+ iounmap(rtc_write->map_v_rtc);
+ free_contiguous_memory_by_paddr(rtc_write->phys);
+ }
+ return false;
+}
+#else
+void acdb_rtc_set_err(u32 err_code)
+{
+ return 0
+}
+#endif /*CONFIG_DEBUG_FS*/
+static s32 acdb_set_calibration_blk(unsigned long arg)
+{
+ struct acdb_cmd_device acdb_cmd;
+ s32 result = 0;
+
+ MM_DBG("acdb_set_calibration_blk\n");
+ if (copy_from_user(&acdb_cmd, (struct acdb_cmd_device *)arg,
+ sizeof(acdb_cmd))) {
+ MM_ERR("Failed copy command struct from user in"\
+ "acdb_set_calibration_blk\n");
+ return -EFAULT;
+ }
+ acdb_cmd.phys_buf = (u32 *)acdb_data.paddr;
+
+ MM_DBG("acdb_cmd.phys_buf %x\n", (u32)acdb_cmd.phys_buf);
+
+ result = dalrpc_fcn_8(ACDB_DAL_IOCTL, acdb_data.handle,
+ (const void *)&acdb_cmd, sizeof(acdb_cmd),
+ &acdb_data.acdb_result,
+ sizeof(acdb_data.acdb_result));
+
+ if (result < 0) {
+ MM_ERR("ACDB=> Device Set RPC failure"\
+ " result = %d\n", result);
+ return -EINVAL;
+ } else {
+ MM_ERR("ACDB=> Device Set RPC success\n");
+ if (acdb_data.acdb_result.result == ACDB_RES_SUCCESS)
+ MM_DBG("ACDB_SET_DEVICE Success\n");
+ else if (acdb_data.acdb_result.result == ACDB_RES_FAILURE)
+ MM_ERR("ACDB_SET_DEVICE Failure\n");
+ else if (acdb_data.acdb_result.result == ACDB_RES_BADPARM)
+ MM_ERR("ACDB_SET_DEVICE BadParams\n");
+ else
+ MM_ERR("Unknown error\n");
+ }
+ return result;
+}
+
+static s32 acdb_get_calibration_blk(unsigned long arg)
+{
+ s32 result = 0;
+ struct acdb_cmd_device acdb_cmd;
+
+ MM_DBG("acdb_get_calibration_blk\n");
+
+ if (copy_from_user(&acdb_cmd, (struct acdb_cmd_device *)arg,
+ sizeof(acdb_cmd))) {
+ MM_ERR("Failed copy command struct from user in"\
+ "acdb_get_calibration_blk\n");
+ return -EFAULT;
+ }
+ acdb_cmd.phys_buf = (u32 *)acdb_data.paddr;
+ MM_ERR("acdb_cmd.phys_buf %x\n", (u32)acdb_cmd.phys_buf);
+
+ result = dalrpc_fcn_8(ACDB_DAL_IOCTL, acdb_data.handle,
+ (const void *)&acdb_cmd, sizeof(acdb_cmd),
+ &acdb_data.acdb_result,
+ sizeof(acdb_data.acdb_result));
+
+ if (result < 0) {
+ MM_ERR("ACDB=> Device Get RPC failure"\
+ " result = %d\n", result);
+ return -EINVAL;
+ } else {
+ MM_ERR("ACDB=> Device Get RPC Success\n");
+ if (acdb_data.acdb_result.result == ACDB_RES_SUCCESS)
+ MM_DBG("ACDB_GET_DEVICE Success\n");
+ else if (acdb_data.acdb_result.result == ACDB_RES_FAILURE)
+ MM_ERR("ACDB_GET_DEVICE Failure\n");
+ else if (acdb_data.acdb_result.result == ACDB_RES_BADPARM)
+ MM_ERR("ACDB_GET_DEVICE BadParams\n");
+ else
+ MM_ERR("Unknown error\n");
+ }
+ return result;
+}
+
+static int audio_acdb_open(struct inode *inode, struct file *file)
+{
+ MM_DBG("%s\n", __func__);
+ return 0;
+}
+static int audio_acdb_release(struct inode *inode, struct file *file)
+{
+ MM_DBG("%s\n", __func__);
+ return 0;
+}
+
+static long audio_acdb_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int rc = 0;
+ unsigned long flags = 0;
+ struct msm_audio_pmem_info info;
+
+ MM_DBG("%s\n", __func__);
+
+ switch (cmd) {
+ case AUDIO_SET_EQ:
+ MM_DBG("IOCTL SET_EQ_CONFIG\n");
+ if (copy_from_user(&acdb_data.eq.num_bands, (void *) arg,
+ sizeof(acdb_data.eq) -
+ (AUDPP_CMD_CFG_OBJECT_PARAMS_COMMON_LEN + 2))) {
+ rc = -EFAULT;
+ break;
+ }
+ spin_lock_irqsave(&acdb_data.dsp_lock, flags);
+ rc = audpp_dsp_set_eq(COMMON_OBJ_ID, 1,
+ &acdb_data.eq);
+ if (rc < 0)
+ MM_ERR("AUDPP returned err =%d\n", rc);
+ spin_unlock_irqrestore(&acdb_data.dsp_lock, flags);
+ break;
+ case AUDIO_REGISTER_PMEM:
+ MM_DBG("AUDIO_REGISTER_PMEM\n");
+ if (copy_from_user(&info, (void *) arg, sizeof(info))) {
+ MM_ERR("Cannot copy from user\n");
+ return -EFAULT;
+ }
+ rc = get_pmem_file(info.fd, &acdb_data.paddr,
+ &acdb_data.kvaddr,
+ &acdb_data.pmem_len,
+ &acdb_data.file);
+ if (rc == 0)
+ acdb_data.pmem_fd = info.fd;
+ break;
+ case AUDIO_DEREGISTER_PMEM:
+ if (acdb_data.pmem_fd)
+ put_pmem_file(acdb_data.file);
+ break;
+ case AUDIO_SET_ACDB_BLK:
+ MM_DBG("IOCTL AUDIO_SET_ACDB_BLK\n");
+ rc = acdb_set_calibration_blk(arg);
+ break;
+ case AUDIO_GET_ACDB_BLK:
+ MM_DBG("IOiCTL AUDIO_GET_ACDB_BLK\n");
+ rc = acdb_get_calibration_blk(arg);
+ break;
+ default:
+ MM_DBG("Unknown IOCTL%d\n", cmd);
+ rc = -EINVAL;
+ }
+ return rc;
+}
+
+static const struct file_operations acdb_fops = {
+ .owner = THIS_MODULE,
+ .open = audio_acdb_open,
+ .release = audio_acdb_release,
+ .llseek = no_llseek,
+ .unlocked_ioctl = audio_acdb_ioctl
+};
+
+struct miscdevice acdb_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "msm_acdb",
+ .fops = &acdb_fops,
+};
+
+static s32 acdb_get_calibration(void)
+{
+ struct acdb_cmd_get_device_table acdb_cmd;
+ s32 result = 0;
+ u32 iterations = 0;
+
+ MM_DBG("acdb state = %d\n", acdb_data.acdb_state);
+
+ acdb_cmd.command_id = ACDB_GET_DEVICE_TABLE;
+ acdb_cmd.device_id = acdb_data.device_info->acdb_id;
+ acdb_cmd.network_id = 0x0108B153;
+ acdb_cmd.sample_rate_id = acdb_data.device_info->sample_rate;
+ acdb_cmd.total_bytes = ACDB_BUF_SIZE;
+ acdb_cmd.phys_buf = (u32 *)acdb_data.phys_addr;
+ MM_DBG("device_id = %d, sampling_freq = %d\n",
+ acdb_cmd.device_id, acdb_cmd.sample_rate_id);
+
+ do {
+ result = dalrpc_fcn_8(ACDB_DAL_IOCTL, acdb_data.handle,
+ (const void *)&acdb_cmd, sizeof(acdb_cmd),
+ &acdb_data.acdb_result,
+ sizeof(acdb_data.acdb_result));
+
+ if (result < 0) {
+ MM_ERR("ACDB=> Device table RPC failure"\
+ " result = %d\n", result);
+ goto error;
+ }
+ /*following check is introduced to handle boot up race
+ condition between AUDCAL SW peers running on apps
+ and modem (ACDB_RES_BADSTATE indicates modem AUDCAL SW is
+ not in initialized sate) we need to retry to get ACDB
+ values*/
+ if (acdb_data.acdb_result.result == ACDB_RES_BADSTATE) {
+ msleep(500);
+ iterations++;
+ } else if (acdb_data.acdb_result.result == ACDB_RES_SUCCESS) {
+ MM_DBG("Modem query for acdb values is successful"\
+ " (iterations = %d)\n", iterations);
+ acdb_data.acdb_state |= CAL_DATA_READY;
+ return result;
+ } else {
+ MM_ERR("ACDB=> modem failed to fill acdb values,"\
+ " reuslt = %d, (iterations = %d)\n",
+ acdb_data.acdb_result.result,
+ iterations);
+ goto error;
+ }
+ } while (iterations < MAX_RETRY);
+ MM_ERR("ACDB=> AUDCAL SW on modem is not in intiailized state (%d)\n",
+ acdb_data.acdb_result.result);
+error:
+ result = -EINVAL;
+ return result;
+}
+
+s32 acdb_get_calibration_data(struct acdb_get_block *get_block)
+{
+ s32 result = -EINVAL;
+ struct acdb_cmd_device acdb_cmd;
+ struct acdb_result acdb_result;
+
+ MM_DBG("acdb_get_calibration_data\n");
+
+ acdb_cmd.command_id = ACDB_GET_DEVICE;
+ acdb_cmd.network_id = 0x0108B153;
+ acdb_cmd.device_id = get_block->acdb_id;
+ acdb_cmd.sample_rate_id = get_block->sample_rate_id;
+ acdb_cmd.interface_id = get_block->interface_id;
+ acdb_cmd.algorithm_block_id = get_block->algorithm_block_id;
+ acdb_cmd.total_bytes = get_block->total_bytes;
+ acdb_cmd.phys_buf = (u32 *)acdb_data.get_blk_paddr;
+
+ result = dalrpc_fcn_8(ACDB_DAL_IOCTL, acdb_data.handle,
+ (const void *)&acdb_cmd, sizeof(acdb_cmd),
+ &acdb_result,
+ sizeof(acdb_result));
+
+ if (result < 0) {
+ MM_ERR("ACDB=> Device Get RPC failure"\
+ " result = %d\n", result);
+ goto err_state;
+ } else {
+ MM_DBG("ACDB=> Device Get RPC Success\n");
+ if (acdb_result.result == ACDB_RES_SUCCESS) {
+ MM_DBG("ACDB_GET_DEVICE Success\n");
+ result = 0;
+ memcpy(get_block->buf_ptr, acdb_data.get_blk_kvaddr,
+ get_block->total_bytes);
+ } else if (acdb_result.result == ACDB_RES_FAILURE)
+ MM_ERR("ACDB_GET_DEVICE Failure\n");
+ else if (acdb_result.result == ACDB_RES_BADPARM)
+ MM_ERR("ACDB_GET_DEVICE BadParams\n");
+ else
+ MM_ERR("Unknown error\n");
+ }
+err_state:
+ return result;
+}
+EXPORT_SYMBOL(acdb_get_calibration_data);
+
+static u8 check_device_info_already_present(
+ struct dev_evt_msg device_info,
+ struct acdb_cache_node *acdb_cache_free_node)
+{
+ if ((device_info.sample_rate ==
+ acdb_cache_free_node->device_info.\
+ sample_rate) &&
+ (device_info.acdb_id ==
+ acdb_cache_free_node->device_info.acdb_id)) {
+ MM_DBG("acdb values are already present\n");
+ /*if acdb state is not set for CAL_DATA_READY and node status
+ is filled, acdb state should be updated with CAL_DATA_READY
+ state*/
+ acdb_data.acdb_state |= CAL_DATA_READY;
+ return 1; /*node is present but status as filled*/
+ }
+ MM_DBG("copying device info into node\n");
+ /*as device information is not present in cache copy
+ the current device information into the node*/
+ memcpy(&acdb_cache_free_node->device_info,
+ &device_info, sizeof(device_info));
+ return 0; /*cant find the node*/
+}
+
+static struct acdb_iir_block *get_audpp_irr_block(void)
+{
+ struct header *prs_hdr;
+ u32 index = 0;
+
+ while (index < acdb_data.acdb_result.used_bytes) {
+ prs_hdr = (struct header *)(acdb_data.virt_addr + index);
+ if (prs_hdr->dbor_signature == DBOR_SIGNATURE) {
+ if (prs_hdr->abid == ABID_AUDIO_IIR_RX) {
+ if (prs_hdr->iid == IID_AUDIO_IIR_COEFF)
+ return (struct acdb_iir_block *)
+ (acdb_data.virt_addr + index
+ + sizeof(struct header));
+ } else {
+ index += prs_hdr->data_len +
+ sizeof(struct header);
+ }
+ } else {
+ break;
+ }
+ }
+ return NULL;
+}
+
+
+static s32 acdb_fill_audpp_iir(void)
+{
+ struct acdb_iir_block *acdb_iir;
+ s32 i = 0;
+
+ acdb_iir = get_audpp_irr_block();
+ if (acdb_iir == NULL) {
+ MM_ERR("unable to find audpp iir block returning\n");
+ return -EINVAL;
+ }
+ memset(acdb_data.pp_iir, 0, sizeof(*acdb_data.pp_iir));
+
+ acdb_data.pp_iir->active_flag = acdb_iir->enable_flag;
+ acdb_data.pp_iir->num_bands = acdb_iir->stage_count;
+ for (; i < acdb_iir->stage_count; i++) {
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ numerator_filter[i].numerator_b0_filter_lsw =
+ acdb_iir->stages[i].b0_lo;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ numerator_filter[i].numerator_b0_filter_msw =
+ acdb_iir->stages[i].b0_hi;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ numerator_filter[i].numerator_b1_filter_lsw =
+ acdb_iir->stages[i].b1_lo;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ numerator_filter[i].numerator_b1_filter_msw =
+ acdb_iir->stages[i].b1_hi;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ numerator_filter[i].numerator_b2_filter_lsw =
+ acdb_iir->stages[i].b2_lo;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ numerator_filter[i].numerator_b2_filter_msw =
+ acdb_iir->stages[i].b2_hi;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ denominator_filter[i].denominator_a0_filter_lsw =
+ acdb_iir->stages_a[i].a1_lo;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ denominator_filter[i].denominator_a0_filter_msw =
+ acdb_iir->stages_a[i].a1_hi;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ denominator_filter[i].denominator_a1_filter_lsw =
+ acdb_iir->stages_a[i].a2_lo;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ denominator_filter[i].denominator_a1_filter_msw =
+ acdb_iir->stages_a[i].a2_hi;
+ acdb_data.pp_iir->params_filter.filter_4_params.
+ shift_factor_filter[i].shift_factor_0 =
+ acdb_iir->shift_factor[i];
+ acdb_data.pp_iir->params_filter.filter_4_params.pan_filter[i].
+ pan_filter_0 = acdb_iir->pan[i];
+ }
+ return 0;
+}
+
+static void extract_mbadrc(u32 *phy_addr, struct header *prs_hdr, u32 *index)
+{
+ if (prs_hdr->iid == IID_MBADRC_EXT_BUFF) {
+ MM_DBG("Got IID = IID_MBADRC_EXT_BUFF\n");
+ *phy_addr = acdb_data.phys_addr + *index +
+ sizeof(struct header);
+ memcpy(acdb_data.mbadrc_block.ext_buf,
+ (acdb_data.virt_addr + *index +
+ sizeof(struct header)), 196*2);
+ MM_DBG("phy_addr = %x\n", *phy_addr);
+ *index += prs_hdr->data_len + sizeof(struct header);
+ } else if (prs_hdr->iid == IID_MBADRC_BAND_CONFIG) {
+ MM_DBG("Got IID == IID_MBADRC_BAND_CONFIG\n");
+ memcpy(acdb_data.mbadrc_block.band_config, (acdb_data.virt_addr
+ + *index + sizeof(struct header)),
+ sizeof(struct mbadrc_band_config_type) *
+ acdb_data.mbadrc_block.parameters.\
+ mbadrc_num_bands);
+ *index += prs_hdr->data_len + sizeof(struct header);
+ } else if (prs_hdr->iid == IID_MBADRC_PARAMETERS) {
+ struct mbadrc_parameter *tmp;
+ tmp = (struct mbadrc_parameter *)(acdb_data.virt_addr + *index
+ + sizeof(struct header));
+ MM_DBG("Got IID == IID_MBADRC_PARAMETERS");
+ acdb_data.mbadrc_block.parameters.mbadrc_enable =
+ tmp->mbadrc_enable;
+ acdb_data.mbadrc_block.parameters.mbadrc_num_bands =
+ tmp->mbadrc_num_bands;
+ acdb_data.mbadrc_block.parameters.mbadrc_down_sample_level =
+ tmp->mbadrc_down_sample_level;
+ acdb_data.mbadrc_block.parameters.mbadrc_delay =
+ tmp->mbadrc_delay;
+ *index += prs_hdr->data_len + sizeof(struct header);
+ }
+}
+
+static void get_audpp_mbadrc_block(u32 *phy_addr)
+{
+ struct header *prs_hdr;
+ u32 index = 0;
+
+ while (index < acdb_data.acdb_result.used_bytes) {
+ prs_hdr = (struct header *)(acdb_data.virt_addr + index);
+
+ if (prs_hdr->dbor_signature == DBOR_SIGNATURE) {
+ if (prs_hdr->abid == ABID_AUDIO_MBADRC_RX) {
+ if ((prs_hdr->iid == IID_MBADRC_EXT_BUFF)
+ || (prs_hdr->iid ==
+ IID_MBADRC_BAND_CONFIG)
+ || (prs_hdr->iid ==
+ IID_MBADRC_PARAMETERS)) {
+ extract_mbadrc(phy_addr, prs_hdr,
+ &index);
+ }
+ } else {
+ index += prs_hdr->data_len +
+ sizeof(struct header);
+ }
+ } else {
+ break;
+ }
+ }
+}
+
+static s32 acdb_fill_audpp_mbadrc(void)
+{
+ u32 mbadrc_phys_addr = -1;
+ get_audpp_mbadrc_block(&mbadrc_phys_addr);
+ if (IS_ERR_VALUE(mbadrc_phys_addr)) {
+ MM_ERR("failed to get mbadrc block\n");
+ return -EINVAL;
+ }
+
+ memset(acdb_data.pp_mbadrc, 0, sizeof(*acdb_data.pp_mbadrc));
+
+ acdb_data.pp_mbadrc->enable = acdb_data.mbadrc_block.\
+ parameters.mbadrc_enable;
+ acdb_data.pp_mbadrc->num_bands =
+ acdb_data.mbadrc_block.\
+ parameters.mbadrc_num_bands;
+ acdb_data.pp_mbadrc->down_samp_level =
+ acdb_data.mbadrc_block.parameters.\
+ mbadrc_down_sample_level;
+ acdb_data.pp_mbadrc->adrc_delay =
+ acdb_data.mbadrc_block.parameters.\
+ mbadrc_delay;
+
+ if (acdb_data.mbadrc_block.parameters.mbadrc_num_bands > 1)
+ acdb_data.pp_mbadrc->ext_buf_size = (97 * 2) +
+ (33 * 2 * (acdb_data.mbadrc_block.parameters.\
+ mbadrc_num_bands - 2));
+
+ acdb_data.pp_mbadrc->ext_partition = 0;
+ acdb_data.pp_mbadrc->ext_buf_lsw = (u16)(mbadrc_phys_addr\
+ & 0xFFFF);
+ acdb_data.pp_mbadrc->ext_buf_msw = (u16)((mbadrc_phys_addr\
+ & 0xFFFF0000) >> 16);
+ memcpy(acdb_data.pp_mbadrc->adrc_band, acdb_data.mbadrc_block.\
+ band_config,
+ sizeof(struct mbadrc_band_config_type) *
+ acdb_data.mbadrc_block.parameters.mbadrc_num_bands);
+ return 0;
+}
+
+static s32 acdb_calibrate_audpp(void)
+{
+ s32 result = 0;
+
+ result = acdb_fill_audpp_iir();
+ if (!IS_ERR_VALUE(result)) {
+ result = audpp_dsp_set_rx_iir(COMMON_OBJ_ID,
+ acdb_data.pp_iir->active_flag,
+ acdb_data.pp_iir);
+ if (result) {
+ MM_ERR("ACDB=> Failed to send IIR data to postproc\n");
+ result = -EINVAL;
+ goto done;
+ } else
+ MM_DBG("AUDPP is calibrated with IIR parameters");
+ }
+ result = acdb_fill_audpp_mbadrc();
+ if (!IS_ERR_VALUE(result)) {
+ result = audpp_dsp_set_mbadrc(COMMON_OBJ_ID,
+ acdb_data.pp_mbadrc->enable,
+ acdb_data.pp_mbadrc);
+ if (result) {
+ MM_ERR("ACDB=> Failed to send MBADRC data to"\
+ " postproc\n");
+ result = -EINVAL;
+ goto done;
+ } else
+ MM_DBG("AUDPP is calibrated with MBADRC parameters");
+ }
+done:
+ return result;
+}
+
+static struct acdb_agc_block *get_audpreproc_agc_block(void)
+{
+ struct header *prs_hdr;
+ u32 index = 0;
+
+ while (index < acdb_data.acdb_result.used_bytes) {
+ prs_hdr = (struct header *)(acdb_data.virt_addr + index);
+ if (prs_hdr->dbor_signature == DBOR_SIGNATURE) {
+ if (prs_hdr->abid == ABID_AUDIO_AGC_TX) {
+ if (prs_hdr->iid == IID_AUDIO_AGC_PARAMETERS) {
+ MM_DBG("GOT ABID_AUDIO_AGC_TX\n");
+ return (struct acdb_agc_block *)
+ (acdb_data.virt_addr + index
+ + sizeof(struct header));
+ }
+ } else {
+ index += prs_hdr->data_len +
+ sizeof(struct header);
+ }
+ } else {
+ break;
+ }
+ }
+ return NULL;
+}
+
+static s32 acdb_fill_audpreproc_agc(void)
+{
+ struct acdb_agc_block *acdb_agc;
+
+ acdb_agc = get_audpreproc_agc_block();
+ if (!acdb_agc) {
+ MM_DBG("unable to find preproc agc parameters winding up\n");
+ return -EINVAL;
+ }
+ memset(acdb_data.preproc_agc, 0, sizeof(*acdb_data.preproc_agc));
+ acdb_data.preproc_agc->cmd_id = AUDPREPROC_CMD_CFG_AGC_PARAMS;
+ /* 0xFE00 to configure all parameters */
+ acdb_data.preproc_agc->tx_agc_param_mask = 0xFFFF;
+ if (acdb_agc->enable_status)
+ acdb_data.preproc_agc->tx_agc_enable_flag =
+ AUDPREPROC_CMD_TX_AGC_ENA_FLAG_ENA;
+ else
+ acdb_data.preproc_agc->tx_agc_enable_flag =
+ AUDPREPROC_CMD_TX_AGC_ENA_FLAG_DIS;
+
+ acdb_data.preproc_agc->comp_rlink_static_gain =
+ acdb_agc->comp_rlink_static_gain;
+ acdb_data.preproc_agc->comp_rlink_aig_flag =
+ acdb_agc->comp_rlink_aig_flag;
+ acdb_data.preproc_agc->expander_rlink_th =
+ acdb_agc->exp_rlink_threshold;
+ acdb_data.preproc_agc->expander_rlink_slope =
+ acdb_agc->exp_rlink_slope;
+ acdb_data.preproc_agc->compressor_rlink_th =
+ acdb_agc->comp_rlink_threshold;
+ acdb_data.preproc_agc->compressor_rlink_slope =
+ acdb_agc->comp_rlink_slope;
+
+ /* 0xFFF0 to configure all parameters */
+ acdb_data.preproc_agc->tx_adc_agc_param_mask = 0xFFFF;
+
+ acdb_data.preproc_agc->comp_rlink_aig_attackk =
+ acdb_agc->comp_rlink_aig_attack_k;
+ acdb_data.preproc_agc->comp_rlink_aig_leak_down =
+ acdb_agc->comp_rlink_aig_leak_down;
+ acdb_data.preproc_agc->comp_rlink_aig_leak_up =
+ acdb_agc->comp_rlink_aig_leak_up;
+ acdb_data.preproc_agc->comp_rlink_aig_max =
+ acdb_agc->comp_rlink_aig_max;
+ acdb_data.preproc_agc->comp_rlink_aig_min =
+ acdb_agc->comp_rlink_aig_min;
+ acdb_data.preproc_agc->comp_rlink_aig_releasek =
+ acdb_agc->comp_rlink_aig_release_k;
+ acdb_data.preproc_agc->comp_rlink_aig_leakrate_fast =
+ acdb_agc->comp_rlink_aig_sm_leak_rate_fast;
+ acdb_data.preproc_agc->comp_rlink_aig_leakrate_slow =
+ acdb_agc->comp_rlink_aig_sm_leak_rate_slow;
+ acdb_data.preproc_agc->comp_rlink_attackk_msw =
+ acdb_agc->comp_rlink_attack_k_msw;
+ acdb_data.preproc_agc->comp_rlink_attackk_lsw =
+ acdb_agc->comp_rlink_attack_k_lsw;
+ acdb_data.preproc_agc->comp_rlink_delay =
+ acdb_agc->comp_rlink_delay;
+ acdb_data.preproc_agc->comp_rlink_releasek_msw =
+ acdb_agc->comp_rlink_release_k_msw;
+ acdb_data.preproc_agc->comp_rlink_releasek_lsw =
+ acdb_agc->comp_rlink_release_k_lsw;
+ acdb_data.preproc_agc->comp_rlink_rms_tav =
+ acdb_agc->comp_rlink_rms_trav;
+ return 0;
+}
+
+static struct acdb_iir_block *get_audpreproc_irr_block(void)
+{
+
+ struct header *prs_hdr;
+ u32 index = 0;
+
+ while (index < acdb_data.acdb_result.used_bytes) {
+ prs_hdr = (struct header *)(acdb_data.virt_addr + index);
+
+ if (prs_hdr->dbor_signature == DBOR_SIGNATURE) {
+ if (prs_hdr->abid == ABID_AUDIO_IIR_TX) {
+ if (prs_hdr->iid == IID_AUDIO_IIR_COEFF)
+ return (struct acdb_iir_block *)
+ (acdb_data.virt_addr + index
+ + sizeof(struct header));
+ } else {
+ index += prs_hdr->data_len +
+ sizeof(struct header);
+ }
+ } else {
+ break;
+ }
+ }
+ return NULL;
+}
+
+
+static s32 acdb_fill_audpreproc_iir(void)
+{
+ struct acdb_iir_block *acdb_iir;
+
+
+ acdb_iir = get_audpreproc_irr_block();
+ if (!acdb_iir) {
+ MM_DBG("unable to find preproc iir parameters winding up\n");
+ return -EINVAL;
+ }
+ memset(acdb_data.preproc_iir, 0, sizeof(*acdb_data.preproc_iir));
+
+ acdb_data.preproc_iir->cmd_id =
+ AUDPREPROC_CMD_CFG_IIR_TUNING_FILTER_PARAMS;
+ acdb_data.preproc_iir->active_flag = acdb_iir->enable_flag;
+ acdb_data.preproc_iir->num_bands = acdb_iir->stage_count;
+
+ acdb_data.preproc_iir->numerator_coeff_b0_filter0_lsw =
+ acdb_iir->stages[0].b0_lo;
+ acdb_data.preproc_iir->numerator_coeff_b0_filter0_msw =
+ acdb_iir->stages[0].b0_hi;
+ acdb_data.preproc_iir->numerator_coeff_b1_filter0_lsw =
+ acdb_iir->stages[0].b1_lo;
+ acdb_data.preproc_iir->numerator_coeff_b1_filter0_msw =
+ acdb_iir->stages[0].b1_hi;
+ acdb_data.preproc_iir->numerator_coeff_b2_filter0_lsw =
+ acdb_iir->stages[0].b2_lo;
+ acdb_data.preproc_iir->numerator_coeff_b2_filter0_msw =
+ acdb_iir->stages[0].b2_hi;
+
+ acdb_data.preproc_iir->numerator_coeff_b0_filter1_lsw =
+ acdb_iir->stages[1].b0_lo;
+ acdb_data.preproc_iir->numerator_coeff_b0_filter1_msw =
+ acdb_iir->stages[1].b0_hi;
+ acdb_data.preproc_iir->numerator_coeff_b1_filter1_lsw =
+ acdb_iir->stages[1].b1_lo;
+ acdb_data.preproc_iir->numerator_coeff_b1_filter1_msw =
+ acdb_iir->stages[1].b1_hi;
+ acdb_data.preproc_iir->numerator_coeff_b2_filter1_lsw =
+ acdb_iir->stages[1].b2_lo;
+ acdb_data.preproc_iir->numerator_coeff_b2_filter1_msw =
+ acdb_iir->stages[1].b2_hi;
+
+ acdb_data.preproc_iir->numerator_coeff_b0_filter2_lsw =
+ acdb_iir->stages[2].b0_lo;
+ acdb_data.preproc_iir->numerator_coeff_b0_filter2_msw =
+ acdb_iir->stages[2].b0_hi;
+ acdb_data.preproc_iir->numerator_coeff_b1_filter2_lsw =
+ acdb_iir->stages[2].b1_lo;
+ acdb_data.preproc_iir->numerator_coeff_b1_filter2_msw =
+ acdb_iir->stages[2].b1_hi;
+ acdb_data.preproc_iir->numerator_coeff_b2_filter2_lsw =
+ acdb_iir->stages[2].b2_lo;
+ acdb_data.preproc_iir->numerator_coeff_b2_filter2_msw =
+ acdb_iir->stages[2].b2_hi;
+
+ acdb_data.preproc_iir->numerator_coeff_b0_filter3_lsw =
+ acdb_iir->stages[3].b0_lo;
+ acdb_data.preproc_iir->numerator_coeff_b0_filter3_msw =
+ acdb_iir->stages[3].b0_hi;
+ acdb_data.preproc_iir->numerator_coeff_b1_filter3_lsw =
+ acdb_iir->stages[3].b1_lo;
+ acdb_data.preproc_iir->numerator_coeff_b1_filter3_msw =
+ acdb_iir->stages[3].b1_hi;
+ acdb_data.preproc_iir->numerator_coeff_b2_filter3_lsw =
+ acdb_iir->stages[3].b2_lo;
+ acdb_data.preproc_iir->numerator_coeff_b2_filter3_msw =
+ acdb_iir->stages[3].b2_hi;
+
+ acdb_data.preproc_iir->denominator_coeff_a0_filter0_lsw =
+ acdb_iir->stages_a[0].a1_lo;
+ acdb_data.preproc_iir->denominator_coeff_a0_filter0_msw =
+ acdb_iir->stages_a[0].a1_hi;
+ acdb_data.preproc_iir->denominator_coeff_a1_filter0_lsw =
+ acdb_iir->stages_a[0].a2_lo;
+ acdb_data.preproc_iir->denominator_coeff_a1_filter0_msw =
+ acdb_iir->stages_a[0].a2_hi;
+
+ acdb_data.preproc_iir->denominator_coeff_a0_filter1_lsw =
+ acdb_iir->stages_a[1].a1_lo;
+ acdb_data.preproc_iir->denominator_coeff_a0_filter1_msw =
+ acdb_iir->stages_a[1].a1_hi;
+ acdb_data.preproc_iir->denominator_coeff_a1_filter1_lsw =
+ acdb_iir->stages_a[1].a2_lo;
+ acdb_data.preproc_iir->denominator_coeff_a1_filter1_msw =
+ acdb_iir->stages_a[1].a2_hi;
+
+ acdb_data.preproc_iir->denominator_coeff_a0_filter2_lsw =
+ acdb_iir->stages_a[2].a1_lo;
+ acdb_data.preproc_iir->denominator_coeff_a0_filter2_msw =
+ acdb_iir->stages_a[2].a1_hi;
+ acdb_data.preproc_iir->denominator_coeff_a1_filter2_lsw =
+ acdb_iir->stages_a[2].a2_lo;
+ acdb_data.preproc_iir->denominator_coeff_a1_filter2_msw =
+ acdb_iir->stages_a[2].a2_hi;
+
+ acdb_data.preproc_iir->denominator_coeff_a0_filter3_lsw =
+ acdb_iir->stages_a[3].a1_lo;
+ acdb_data.preproc_iir->denominator_coeff_a0_filter3_msw =
+ acdb_iir->stages_a[3].a1_hi;
+ acdb_data.preproc_iir->denominator_coeff_a1_filter3_lsw =
+ acdb_iir->stages_a[3].a2_lo;
+ acdb_data.preproc_iir->denominator_coeff_a1_filter3_msw =
+ acdb_iir->stages_a[3].a2_hi;
+
+ acdb_data.preproc_iir->shift_factor_filter0 =
+ acdb_iir->shift_factor[0];
+ acdb_data.preproc_iir->shift_factor_filter1 =
+ acdb_iir->shift_factor[1];
+ acdb_data.preproc_iir->shift_factor_filter2 =
+ acdb_iir->shift_factor[2];
+ acdb_data.preproc_iir->shift_factor_filter3 =
+ acdb_iir->shift_factor[3];
+
+ acdb_data.preproc_iir->channel_selected0 =
+ acdb_iir->pan[0];
+ acdb_data.preproc_iir->channel_selected1 =
+ acdb_iir->pan[1];
+ acdb_data.preproc_iir->channel_selected2 =
+ acdb_iir->pan[2];
+ acdb_data.preproc_iir->channel_selected3 =
+ acdb_iir->pan[3];
+ return 0;
+}
+
+static struct acdb_ns_tx_block *get_audpreproc_ns_block(void)
+{
+
+ struct header *prs_hdr;
+ u32 index = 0;
+
+ while (index < acdb_data.acdb_result.used_bytes) {
+ prs_hdr = (struct header *)(acdb_data.virt_addr + index);
+
+ if (prs_hdr->dbor_signature == DBOR_SIGNATURE) {
+ if (prs_hdr->abid == ABID_AUDIO_NS_TX) {
+ if (prs_hdr->iid == IID_NS_PARAMETERS)
+ return (struct acdb_ns_tx_block *)
+ (acdb_data.virt_addr + index
+ + sizeof(struct header));
+ } else {
+ index += prs_hdr->data_len +
+ sizeof(struct header);
+ }
+ } else {
+ break;
+ }
+ }
+ return NULL;
+}
+
+static s32 acdb_fill_audpreproc_ns(void)
+{
+ struct acdb_ns_tx_block *acdb_ns;
+ /* TO DO: do we enable_status_filled */
+ acdb_ns = get_audpreproc_ns_block();
+ if (!acdb_ns) {
+ MM_DBG("unable to find preproc ns parameters winding up\n");
+ return -EINVAL;
+ }
+ memset(acdb_data.preproc_ns, 0, sizeof(*acdb_data.preproc_ns));
+ acdb_data.preproc_ns->cmd_id = AUDPREPROC_CMD_CFG_NS_PARAMS;
+
+ acdb_data.preproc_ns->ec_mode_new = acdb_ns->ec_mode_new;
+ acdb_data.preproc_ns->dens_gamma_n = acdb_ns->dens_gamma_n;
+ acdb_data.preproc_ns->dens_nfe_block_size =
+ acdb_ns->dens_nfe_block_size;
+ acdb_data.preproc_ns->dens_limit_ns = acdb_ns->dens_limit_ns;
+ acdb_data.preproc_ns->dens_limit_ns_d = acdb_ns->dens_limit_ns_d;
+ acdb_data.preproc_ns->wb_gamma_e = acdb_ns->wb_gamma_e;
+ acdb_data.preproc_ns->wb_gamma_n = acdb_ns->wb_gamma_n;
+
+ return 0;
+}
+
+s32 acdb_calibrate_audpreproc(void)
+{
+ s32 result = 0;
+
+ result = acdb_fill_audpreproc_agc();
+ if (!IS_ERR_VALUE(result)) {
+ result = audpreproc_dsp_set_agc(acdb_data.preproc_agc, sizeof(
+ audpreproc_cmd_cfg_agc_params));
+ if (result) {
+ MM_ERR("ACDB=> Failed to send AGC data to preproc)\n");
+ result = -EINVAL;
+ goto done;
+ } else
+ MM_DBG("AUDPREC is calibrated with AGC parameters");
+ }
+ result = acdb_fill_audpreproc_iir();
+ if (!IS_ERR_VALUE(result)) {
+ result = audpreproc_dsp_set_iir(acdb_data.preproc_iir,
+ sizeof(\
+ audpreproc_cmd_cfg_iir_tuning_filter_params));
+ if (result) {
+ MM_ERR("ACDB=> Failed to send IIR data to preproc\n");
+ result = -EINVAL;
+ goto done;
+ } else
+ MM_DBG("audpreproc is calibrated with iir parameters");
+ }
+
+ result = acdb_fill_audpreproc_ns();
+ if (!IS_ERR_VALUE(result)) {
+ result = audpreproc_dsp_set_ns(acdb_data.preproc_ns,
+ sizeof(\
+ audpreproc_cmd_cfg_ns_params));
+ if (result) {
+ MM_ERR("ACDB=> Failed to send NS data to preproc\n");
+ result = -EINVAL;
+ goto done;
+ } else
+ MM_DBG("audpreproc is calibrated with NS parameters");
+ }
+done:
+ return result;
+}
+
+static s32 acdb_send_calibration(void)
+{
+ s32 result = 0;
+
+ if (acdb_data.device_info->dev_type.rx_device) {
+ result = acdb_calibrate_audpp();
+ if (result)
+ goto done;
+ } else if (acdb_data.device_info->dev_type.tx_device) {
+ result = acdb_calibrate_audpreproc();
+ if (result)
+ goto done;
+ acdb_data.audrec_applied |= AUDREC_READY;
+ MM_DBG("acdb_data.audrec_applied = %x\n",
+ acdb_data.audrec_applied);
+ }
+done:
+ return result;
+}
+
+static u8 check_tx_acdb_values_cached(void)
+{
+ if ((acdb_data.device_info->sample_rate ==
+ acdb_cache_tx.device_info.sample_rate) &&
+ (acdb_data.device_info->acdb_id ==
+ acdb_cache_tx.device_info.acdb_id) &&
+ (acdb_cache_tx.node_status ==
+ ACDB_VALUES_FILLED))
+ return 0;
+ else
+ return 1;
+}
+
+static void handle_tx_device_ready_callback(void)
+{
+ u8 acdb_value_apply = 0;
+ u8 result = 0;
+
+ /*check wheather AUDREC enabled before device call backs*/
+ if ((acdb_data.acdb_state & AUDREC_READY) &&
+ !(acdb_data.audrec_applied & AUDREC_READY)) {
+ MM_DBG("AUDREC already enabled apply acdb values\n");
+ acdb_value_apply |= AUDREC_READY;
+ }
+ if (acdb_value_apply) {
+ if (session_info.sampling_freq)
+ acdb_data.device_info->sample_rate =
+ session_info.sampling_freq;
+ result = check_tx_acdb_values_cached();
+ if (result) {
+ result = acdb_get_calibration();
+ if (result < 0) {
+ MM_ERR("Not able to get calibration"\
+ " data continue\n");
+ return;
+ }
+ }
+ acdb_cache_tx.node_status = ACDB_VALUES_FILLED;
+ acdb_send_calibration();
+ }
+}
+
+static struct acdb_cache_node *get_acdb_values_from_cache_tx(u32 stream_id)
+{
+ MM_DBG("searching node with stream_id");
+ if ((acdb_cache_tx.stream_id == stream_id) &&
+ (acdb_cache_tx.node_status ==
+ ACDB_VALUES_NOT_FILLED)) {
+ return &acdb_cache_tx;
+ }
+ MM_DBG("Error! in finding node\n");
+ return NULL;
+}
+
+static void update_acdb_data_struct(struct acdb_cache_node *cur_node)
+{
+ if (cur_node) {
+ acdb_data.device_info = &cur_node->device_info;
+ acdb_data.virt_addr = cur_node->virt_addr_acdb_values;
+ acdb_data.phys_addr = cur_node->phys_addr_acdb_values;
+ } else
+ MM_ERR("error in curent node\n");
+}
+
+static void send_acdb_values_for_active_devices(void)
+{
+ if (acdb_cache_rx.node_status ==
+ ACDB_VALUES_FILLED) {
+ update_acdb_data_struct(&acdb_cache_rx);
+ if (acdb_data.acdb_state & CAL_DATA_READY)
+ acdb_send_calibration();
+ }
+}
+
+static s32 initialize_rpc(void)
+{
+ s32 result = 0;
+
+ result = daldevice_attach(DALDEVICEID_ACDB, ACDB_PORT_NAME,
+ ACDB_CPU, &acdb_data.handle);
+
+ if (result) {
+ MM_ERR("ACDB=> Device Attach failed\n");
+ result = -ENODEV;
+ goto done;
+ }
+done:
+ return result;
+}
+
+static u32 allocate_memory_acdb_cache_tx(void)
+{
+ u32 result = 0;
+ /*initialize local cache */
+ acdb_cache_tx.phys_addr_acdb_values =
+ allocate_contiguous_ebi_nomap(ACDB_BUF_SIZE,
+ SZ_4K);
+
+ if (!acdb_cache_tx.phys_addr_acdb_values) {
+ MM_ERR("ACDB=> Cannot allocate physical memory\n");
+ result = -ENOMEM;
+ goto error;
+ }
+ acdb_cache_tx.map_v_addr = ioremap(
+ acdb_cache_tx.phys_addr_acdb_values,
+ ACDB_BUF_SIZE);
+ if (IS_ERR(acdb_cache_tx.map_v_addr)) {
+ MM_ERR("ACDB=> Could not map physical address\n");
+ result = -ENOMEM;
+ free_contiguous_memory_by_paddr(
+ acdb_cache_tx.phys_addr_acdb_values);
+ goto error;
+ }
+ acdb_cache_tx.virt_addr_acdb_values =
+ acdb_cache_tx.map_v_addr;
+ memset(acdb_cache_tx.virt_addr_acdb_values, 0,
+ ACDB_BUF_SIZE);
+ return result;
+error:
+ iounmap(acdb_cache_tx.map_v_addr);
+ free_contiguous_memory_by_paddr(
+ acdb_cache_tx.phys_addr_acdb_values);
+ return result;
+}
+
+static u32 allocate_memory_acdb_cache_rx(void)
+{
+ u32 result = 0;
+
+ /*initialize local cache */
+ acdb_cache_rx.phys_addr_acdb_values =
+ allocate_contiguous_ebi_nomap(
+ ACDB_BUF_SIZE, SZ_4K);
+
+ if (!acdb_cache_rx.phys_addr_acdb_values) {
+ MM_ERR("ACDB=> Can not allocate physical memory\n");
+ result = -ENOMEM;
+ goto error;
+ }
+ acdb_cache_rx.map_v_addr =
+ ioremap(acdb_cache_rx.phys_addr_acdb_values,
+ ACDB_BUF_SIZE);
+ if (IS_ERR(acdb_cache_rx.map_v_addr)) {
+ MM_ERR("ACDB=> Could not map physical address\n");
+ result = -ENOMEM;
+ free_contiguous_memory_by_paddr(
+ acdb_cache_rx.phys_addr_acdb_values);
+ goto error;
+ }
+ acdb_cache_rx.virt_addr_acdb_values =
+ acdb_cache_rx.map_v_addr;
+ memset(acdb_cache_rx.virt_addr_acdb_values, 0,
+ ACDB_BUF_SIZE);
+ return result;
+error:
+ iounmap(acdb_cache_rx.map_v_addr);
+ free_contiguous_memory_by_paddr(
+ acdb_cache_rx.phys_addr_acdb_values);
+ return result;
+}
+
+static u32 allocate_memory_acdb_get_blk(void)
+{
+ u32 result = 0;
+ acdb_data.get_blk_paddr = allocate_contiguous_ebi_nomap(
+ ACDB_BUF_SIZE, SZ_4K);
+ if (!acdb_data.get_blk_paddr) {
+ MM_ERR("ACDB=> Cannot allocate physical memory\n");
+ result = -ENOMEM;
+ goto error;
+ }
+ acdb_data.map_v_get_blk = ioremap(acdb_data.get_blk_paddr,
+ ACDB_BUF_SIZE);
+ if (IS_ERR(acdb_data.map_v_get_blk)) {
+ MM_ERR("ACDB=> Could not map physical address\n");
+ result = -ENOMEM;
+ free_contiguous_memory_by_paddr(
+ acdb_data.get_blk_paddr);
+ goto error;
+ }
+ acdb_data.get_blk_kvaddr = acdb_data.map_v_get_blk;
+ memset(acdb_data.get_blk_kvaddr, 0, ACDB_BUF_SIZE);
+error:
+ return result;
+}
+
+static void free_memory_acdb_cache_rx(void)
+{
+ iounmap(acdb_cache_rx.map_v_addr);
+ free_contiguous_memory_by_paddr(
+ acdb_cache_rx.phys_addr_acdb_values);
+}
+
+static void free_memory_acdb_cache_tx(void)
+{
+
+ iounmap(acdb_cache_tx.map_v_addr);
+ free_contiguous_memory_by_paddr(
+ acdb_cache_tx.phys_addr_acdb_values);
+}
+
+static void free_memory_acdb_get_blk(void)
+{
+ iounmap(acdb_data.map_v_get_blk);
+ free_contiguous_memory_by_paddr(acdb_data.get_blk_paddr);
+}
+
+static s32 initialize_memory(void)
+{
+ s32 result = 0;
+
+ result = allocate_memory_acdb_get_blk();
+ if (result < 0) {
+ MM_ERR("memory allocation for get blk failed\n");
+ goto done;
+ }
+
+ result = allocate_memory_acdb_cache_rx();
+ if (result < 0) {
+ MM_ERR("memory allocation for rx cache is failed\n");
+ free_memory_acdb_get_blk();
+ goto done;
+ }
+ result = allocate_memory_acdb_cache_tx();
+ if (result < 0) {
+ MM_ERR("memory allocation for tx cache is failed\n");
+ free_memory_acdb_get_blk();
+ free_memory_acdb_cache_rx();
+ goto done;
+ }
+ acdb_data.pp_iir = kmalloc(sizeof(*acdb_data.pp_iir),
+ GFP_KERNEL);
+ if (acdb_data.pp_iir == NULL) {
+ MM_ERR("ACDB=> Could not allocate postproc iir memory\n");
+ free_memory_acdb_get_blk();
+ free_memory_acdb_cache_rx();
+ free_memory_acdb_cache_tx();
+ result = -ENOMEM;
+ goto done;
+ }
+
+ acdb_data.pp_mbadrc = kmalloc(sizeof(*acdb_data.pp_mbadrc), GFP_KERNEL);
+ if (acdb_data.pp_mbadrc == NULL) {
+ MM_ERR("ACDB=> Could not allocate postproc mbadrc memory\n");
+ free_memory_acdb_get_blk();
+ free_memory_acdb_cache_rx();
+ free_memory_acdb_cache_tx();
+ kfree(acdb_data.pp_iir);
+ result = -ENOMEM;
+ goto done;
+ }
+
+ acdb_data.preproc_agc = kmalloc(sizeof(*acdb_data.preproc_agc),
+ GFP_KERNEL);
+ if (acdb_data.preproc_agc == NULL) {
+ MM_ERR("ACDB=> Could not allocate preproc agc memory\n");
+ free_memory_acdb_get_blk();
+ free_memory_acdb_cache_rx();
+ free_memory_acdb_cache_tx();
+ kfree(acdb_data.pp_iir);
+ kfree(acdb_data.pp_mbadrc);
+ result = -ENOMEM;
+ goto done;
+ }
+
+ acdb_data.preproc_iir = kmalloc(sizeof(*acdb_data.preproc_iir),
+ GFP_KERNEL);
+ if (acdb_data.preproc_iir == NULL) {
+ MM_ERR("ACDB=> Could not allocate preproc iir memory\n");
+ free_memory_acdb_get_blk();
+ free_memory_acdb_cache_rx();
+ free_memory_acdb_cache_tx();
+ kfree(acdb_data.pp_iir);
+ kfree(acdb_data.pp_mbadrc);
+ kfree(acdb_data.preproc_agc);
+ result = -ENOMEM;
+ goto done;
+ }
+
+ acdb_data.preproc_ns = kmalloc(sizeof(*acdb_data.preproc_ns),
+ GFP_KERNEL);
+ if (acdb_data.preproc_ns == NULL) {
+ MM_ERR("ACDB=> Could not allocate preproc ns memory\n");
+ free_memory_acdb_get_blk();
+ free_memory_acdb_cache_rx();
+ free_memory_acdb_cache_tx();
+ kfree(acdb_data.pp_iir);
+ kfree(acdb_data.pp_mbadrc);
+ kfree(acdb_data.preproc_agc);
+ kfree(acdb_data.preproc_iir);
+ result = -ENOMEM;
+ goto done;
+ }
+done:
+ return result;
+}
+
+static u8 check_device_change(struct dev_evt_msg device_info)
+{
+ if (!acdb_data.device_info) {
+ MM_ERR("not pointing to previous valid device detail\n");
+ return 1; /*device info will not be pointing to*/
+ /* valid device when acdb driver comes up*/
+ }
+ if ((device_info.sample_rate ==
+ acdb_data.device_info->sample_rate) &&
+ (device_info.acdb_id == acdb_data.device_info->acdb_id)) {
+ return 0;
+ }
+ return 1;
+}
+
+static void device_cb(struct dev_evt_msg *evt, void *private)
+{
+ struct cad_device_info_type dev_type;
+ struct acdb_cache_node *acdb_cache_free_node = NULL;
+ u32 session_id = 0;
+ u8 ret = 0;
+ u8 device_change = 0;
+
+ /*if session value is zero it indicates that device call back is for
+ voice call we will drop the request as acdb values for voice call is
+ not applied from acdb driver*/
+ if (!evt->session_info) {
+ MM_DBG("no active sessions and call back is for"\
+ " voice call\n");
+ goto done;
+ }
+
+ if ((evt->dev_type.rx_device) &&
+ (evt->acdb_id == PSEUDO_ACDB_ID)) {
+ MM_INFO("device cb is for rx device with pseudo acdb id\n");
+ goto done;
+ }
+ dev_type = evt->dev_type;
+ MM_DBG("sample_rate = %d\n", evt->sample_rate);
+ MM_DBG("acdb_id = %d\n", evt->acdb_id);
+ MM_DBG("sessions = %d\n", evt->session_info);
+ MM_DBG("acdb_state = %x\n", acdb_data.acdb_state);
+ mutex_lock(&acdb_data.acdb_mutex);
+ device_change = check_device_change(*evt);
+ if (!device_change) {
+ if (dev_type.tx_device) {
+ if (!(acdb_data.acdb_state & AUDREC_READY))
+ acdb_data.audrec_applied &= ~AUDREC_READY;
+
+ acdb_data.acdb_state &= ~CAL_DATA_READY;
+ goto update_cache;
+ }
+ } else
+ /* state is updated to query the modem for values */
+ acdb_data.acdb_state &= ~CAL_DATA_READY;
+
+update_cache:
+ if (dev_type.tx_device) {
+ /*Only one recording session possible*/
+ session_id = 0;
+ acdb_cache_free_node = &acdb_cache_tx;
+ ret = check_device_info_already_present(
+ *evt,
+ acdb_cache_free_node);
+ acdb_cache_free_node->stream_id = session_id;
+ acdb_data.cur_tx_session = session_id;
+ } else {
+ acdb_cache_free_node = &acdb_cache_rx;
+ ret = check_device_info_already_present(*evt,
+ acdb_cache_free_node);
+ if (ret == 1) {
+ MM_DBG("got device ready call back for another "\
+ "audplay task sessions on same COPP\n");
+ /*stream_id is used to keep track of number of active*/
+ /*sessions active on this device*/
+ acdb_cache_free_node->stream_id++;
+ mutex_unlock(&acdb_data.acdb_mutex);
+ goto done;
+ }
+ acdb_cache_free_node->stream_id++;
+ }
+ update_acdb_data_struct(acdb_cache_free_node);
+ acdb_data.device_cb_compl = 1;
+ mutex_unlock(&acdb_data.acdb_mutex);
+ wake_up(&acdb_data.wait);
+done:
+ return;
+}
+
+static s32 register_device_cb(void)
+{
+ s32 result = 0;
+ acdb_data.dev_cb.func = device_cb;
+ acdb_data.dev_cb.private = (void *)&acdb_data;
+
+ result = audmgr_register_device_info_callback(&acdb_data.dev_cb);
+
+ if (result) {
+ MM_ERR("ACDB=> Could not register device callback\n");
+ result = -ENODEV;
+ goto done;
+ }
+done:
+ return result;
+}
+
+static void audpp_cb(void *private, u32 id, u16 *msg)
+{
+ MM_DBG("\n");
+ if (id != AUDPP_MSG_CFG_MSG)
+ goto done;
+
+ if (msg[0] == AUDPP_MSG_ENA_DIS) {
+ if (--acdb_cache_rx.stream_id <= 0) {
+ acdb_data.acdb_state &= ~AUDPP_READY;
+ acdb_cache_rx.stream_id = 0;
+ MM_DBG("AUDPP_MSG_ENA_DIS\n");
+ }
+ goto done;
+ }
+
+ acdb_data.acdb_state |= AUDPP_READY;
+ acdb_data.audpp_cb_compl = 1;
+ wake_up(&acdb_data.wait);
+done:
+ return;
+}
+
+static s8 handle_audpreproc_cb(void)
+{
+ struct acdb_cache_node *acdb_cached_values;
+ s8 result = 0;
+ u8 stream_id = acdb_data.preproc_stream_id;
+ acdb_data.preproc_cb_compl = 0;
+ acdb_cached_values = get_acdb_values_from_cache_tx(stream_id);
+ if (acdb_cached_values == NULL) {
+ MM_DBG("ERROR: to get chached acdb values\n");
+ return -EPERM;
+ }
+ update_acdb_data_struct(acdb_cached_values);
+
+ if (session_info.sampling_freq)
+ acdb_data.device_info->sample_rate =
+ session_info.sampling_freq;
+
+ if (!(acdb_data.acdb_state & CAL_DATA_READY)) {
+ result = check_tx_acdb_values_cached();
+ if (result) {
+ result = acdb_get_calibration();
+ if (result < 0) {
+ MM_ERR("failed to get calibration data\n");
+ return result;
+ }
+ }
+ acdb_cached_values->node_status = ACDB_VALUES_FILLED;
+ }
+ return result;
+}
+
+static void audpreproc_cb(void *private, u32 id, void *event_data)
+{
+ u8 result = 0;
+ uint16_t *msg = event_data;
+ int stream_id = 0; /* Only single tunnel mode recording supported */
+ if (id != AUDPREPROC_MSG_CMD_CFG_DONE_MSG)
+ goto done;
+
+ acdb_data.preproc_stream_id = stream_id;
+ get_audrec_session_info(&session_info);
+ MM_DBG("status_flag = %x\n", msg[0]);
+ if (msg[0] == AUDPREPROC_MSG_STATUS_FLAG_DIS) {
+ acdb_data.acdb_state &= ~AUDREC_READY;
+ acdb_cache_tx.node_status =\
+ ACDB_VALUES_NOT_FILLED;
+ acdb_data.acdb_state &= ~CAL_DATA_READY;
+ goto done;
+ }
+ /*Following check is added to make sure that device info
+ is updated. audpre proc layer enabled without device
+ callback at this scenario we should not access
+ device information
+ */
+ if (acdb_data.device_info &&
+ session_info.sampling_freq) {
+ acdb_data.device_info->sample_rate =
+ session_info.sampling_freq;
+ result = check_tx_acdb_values_cached();
+ if (!result) {
+ MM_INFO("acdb values for the stream is" \
+ " querried from modem");
+ acdb_data.acdb_state |= CAL_DATA_READY;
+ } else {
+ acdb_data.acdb_state &= ~CAL_DATA_READY;
+ }
+ }
+ acdb_data.acdb_state |= AUDREC_READY;
+
+ acdb_data.preproc_cb_compl = 1;
+ MM_DBG("acdb_data.acdb_state = %x\n", acdb_data.acdb_state);
+ wake_up(&acdb_data.wait);
+done:
+ return;
+}
+
+static s32 register_audpp_cb(void)
+{
+ s32 result = 0;
+
+ acdb_data.audpp_cb.fn = audpp_cb;
+ acdb_data.audpp_cb.private = NULL;
+ result = audpp_register_event_callback(&acdb_data.audpp_cb);
+ if (result) {
+ MM_ERR("ACDB=> Could not register audpp callback\n");
+ result = -ENODEV;
+ goto done;
+ }
+done:
+ return result;
+}
+
+static s32 register_audpreproc_cb(void)
+{
+ s32 result = 0;
+
+ acdb_data.audpreproc_cb.fn = audpreproc_cb;
+ acdb_data.audpreproc_cb.private = NULL;
+ result = audpreproc_register_event_callback(&acdb_data.audpreproc_cb);
+ if (result) {
+ MM_ERR("ACDB=> Could not register audpreproc callback\n");
+ result = -ENODEV;
+ goto done;
+ }
+
+done:
+ return result;
+}
+
+static s32 acdb_initialize_data(void)
+{
+ s32 result = 0;
+
+ mutex_init(&acdb_data.acdb_mutex);
+
+ result = initialize_rpc();
+ if (result)
+ goto err;
+
+ result = initialize_memory();
+ if (result)
+ goto err1;
+
+ result = register_device_cb();
+ if (result)
+ goto err2;
+
+ result = register_audpp_cb();
+ if (result)
+ goto err3;
+
+ result = register_audpreproc_cb();
+ if (result)
+ goto err4;
+
+
+ return result;
+
+err4:
+ result = audpreproc_unregister_event_callback(&acdb_data.audpreproc_cb);
+ if (result)
+ MM_ERR("ACDB=> Could not unregister audpreproc callback\n");
+err3:
+ result = audpp_unregister_event_callback(&acdb_data.audpp_cb);
+ if (result)
+ MM_ERR("ACDB=> Could not unregister audpp callback\n");
+err2:
+ result = audmgr_deregister_device_info_callback(&acdb_data.dev_cb);
+ if (result)
+ MM_ERR("ACDB=> Could not unregister device callback\n");
+err1:
+ daldevice_detach(acdb_data.handle);
+ acdb_data.handle = NULL;
+err:
+ return result;
+}
+
+static s32 acdb_calibrate_device(void *data)
+{
+ s32 result = 0;
+
+ /* initialize driver */
+ result = acdb_initialize_data();
+ if (result)
+ goto done;
+
+ while (!kthread_should_stop()) {
+ MM_DBG("Waiting for call back events\n");
+ wait_event_interruptible(acdb_data.wait,
+ (acdb_data.device_cb_compl
+ | acdb_data.audpp_cb_compl
+ | acdb_data.preproc_cb_compl));
+ mutex_lock(&acdb_data.acdb_mutex);
+ if (acdb_data.device_cb_compl) {
+ acdb_data.device_cb_compl = 0;
+ if (!(acdb_data.acdb_state & CAL_DATA_READY)) {
+ if (acdb_data.device_info->dev_type.rx_device) {
+ /*we need to get calibration values
+ only for RX device as resampler
+ moved to start of the pre - proc chain
+ tx calibration value will be based on
+ sampling frequency what audrec is
+ configured, calibration values for tx
+ device are fetch in audpreproc
+ callback*/
+ result = acdb_get_calibration();
+ if (result < 0) {
+ mutex_unlock(
+ &acdb_data.acdb_mutex);
+ MM_ERR("Not able to get "\
+ "calibration "\
+ "data continue\n");
+ continue;
+ }
+ }
+ }
+ MM_DBG("acdb state = %d\n",
+ acdb_data.acdb_state);
+ if (acdb_data.device_info->dev_type.tx_device)
+ handle_tx_device_ready_callback();
+ else {
+ acdb_cache_rx.node_status =\
+ ACDB_VALUES_FILLED;
+ if (acdb_data.acdb_state &
+ AUDPP_READY) {
+ MM_DBG("AUDPP already enabled "\
+ "apply acdb values\n");
+ goto apply;
+ }
+ }
+ }
+
+ if (!(acdb_data.audpp_cb_compl ||
+ acdb_data.preproc_cb_compl)) {
+ MM_DBG("need to wait for either AUDPP / AUDPREPROC "\
+ "Event\n");
+ mutex_unlock(&acdb_data.acdb_mutex);
+ continue;
+ } else {
+ MM_DBG("got audpp / preproc call back\n");
+ if (acdb_data.audpp_cb_compl) {
+ send_acdb_values_for_active_devices();
+ acdb_data.audpp_cb_compl = 0;
+ mutex_unlock(&acdb_data.acdb_mutex);
+ continue;
+ } else {
+ result = handle_audpreproc_cb();
+ if (result < 0) {
+ mutex_unlock(&acdb_data.acdb_mutex);
+ continue;
+ }
+ }
+ }
+apply:
+ if (acdb_data.acdb_state & CAL_DATA_READY)
+ result = acdb_send_calibration();
+
+ mutex_unlock(&acdb_data.acdb_mutex);
+ }
+done:
+ return 0;
+}
+
+static int __init acdb_init(void)
+{
+
+ s32 result = 0;
+
+ memset(&acdb_data, 0, sizeof(acdb_data));
+ spin_lock_init(&acdb_data.dsp_lock);
+ acdb_data.cb_thread_task = kthread_run(acdb_calibrate_device,
+ NULL, "acdb_cb_thread");
+
+ if (IS_ERR(acdb_data.cb_thread_task)) {
+ MM_ERR("ACDB=> Could not register cb thread\n");
+ result = -ENODEV;
+ goto err;
+ }
+
+#ifdef CONFIG_DEBUG_FS
+ /*This is RTC specific INIT used only with debugfs*/
+ if (!rtc_acdb_init())
+ MM_ERR("RTC ACDB=>INIT Failure\n");
+
+#endif
+ init_waitqueue_head(&acdb_data.wait);
+
+ return misc_register(&acdb_misc);
+err:
+ return result;
+}
+
+static void __exit acdb_exit(void)
+{
+ s32 result = 0;
+
+ result = audmgr_deregister_device_info_callback(&acdb_data.dev_cb);
+ if (result)
+ MM_ERR("ACDB=> Could not unregister device callback\n");
+
+ result = audpp_unregister_event_callback(&acdb_data.audpp_cb);
+ if (result)
+ MM_ERR("ACDB=> Could not unregister audpp callback\n");
+
+ result = audpreproc_unregister_event_callback(&acdb_data.\
+ audpreproc_cb);
+ if (result)
+ MM_ERR("ACDB=> Could not unregister audpreproc callback\n");
+
+ result = kthread_stop(acdb_data.cb_thread_task);
+ if (result)
+ MM_ERR("ACDB=> Could not stop kthread\n");
+
+ free_memory_acdb_get_blk();
+
+ iounmap(acdb_cache_tx.map_v_addr);
+ free_contiguous_memory_by_paddr(
+ acdb_cache_tx.phys_addr_acdb_values);
+ iounmap(acdb_cache_rx.map_v_addr);
+ free_contiguous_memory_by_paddr(
+ acdb_cache_rx.phys_addr_acdb_values);
+ kfree(acdb_data.device_info);
+ kfree(acdb_data.pp_iir);
+ kfree(acdb_data.pp_mbadrc);
+ kfree(acdb_data.preproc_agc);
+ kfree(acdb_data.preproc_iir);
+ kfree(acdb_data.preproc_ns);
+ mutex_destroy(&acdb_data.acdb_mutex);
+ memset(&acdb_data, 0, sizeof(acdb_data));
+ #ifdef CONFIG_DEBUG_FS
+ rtc_acdb_deinit();
+ #endif
+}
+
+late_initcall(acdb_init);
+module_exit(acdb_exit);
+
+MODULE_DESCRIPTION("MSM 8x25 Audio ACDB driver");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb.c b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
index 45fa045..7e6c9ce 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb.c
@@ -51,6 +51,7 @@
#include <mach/qdsp5/qdsp5audppmsg.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
#include <mach/debug_mm.h>
#include <mach/msm_memtypes.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c b/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
index 39578c1..05ad373 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrnb_in.c
@@ -114,8 +114,6 @@
uint32_t out_frame_cnt;
struct msm_adsp_module *audrec;
- struct msm_adsp_module *audpre;
-
/* configuration to use on next enable */
uint32_t samp_rate;
@@ -154,6 +152,7 @@
struct ion_client *client;
struct ion_handle *input_buff_handle;
+ struct audrec_session_info session_info; /*audrec session info*/
};
struct audio_frame {
@@ -232,6 +231,30 @@
}
}
+/* ------------------- dsp --------------------- */
+static void audpre_dsp_event(void *data, unsigned id, void *event_data)
+{
+
+ uint16_t *msg = event_data;
+
+ if (!msg)
+ return;
+
+ switch (id) {
+ case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
+ MM_DBG("type %d, status_flag %d\n",\
+ msg[0], msg[1]);
+ break;
+ case AUDPREPROC_MSG_ERROR_MSG_ID:
+ MM_INFO("err_index %d\n", msg[0]);
+ break;
+ case ADSP_MESSAGE_ID:
+ MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
+ break;
+ default:
+ MM_ERR("unknown event %d\n", id);
+ }
+}
/* must be called with audio->lock held */
static int audamrnb_in_enable(struct audio_amrnb_in *audio)
{
@@ -252,16 +275,23 @@
if (rc < 0)
return rc;
- if (msm_adsp_enable(audio->audpre)) {
+ if (audpreproc_enable(audio->enc_id,
+ &audpre_dsp_event, audio)) {
+ MM_ERR("msm_adsp_enable(audpreproc) failed\n");
audmgr_disable(&audio->audmgr);
- MM_ERR("msm_adsp_enable(audpre) failed\n");
return -ENODEV;
}
+ /*update aurec session info in audpreproc layer*/
+ audio->session_info.session_id = audio->enc_id;
+ audio->session_info.sampling_freq =
+ convert_samp_index(audio->samp_rate);
+ audpreproc_update_audrec_info(&audio->session_info);
}
+
if (msm_adsp_enable(audio->audrec)) {
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
+ audpreproc_disable(audio->enc_id, audio);
audmgr_disable(&audio->audmgr);
- msm_adsp_disable(audio->audpre);
}
MM_ERR("msm_adsp_enable(audrec) failed\n");
return -ENODEV;
@@ -286,35 +316,17 @@
audio->running == 0, 1*HZ);
msm_adsp_disable(audio->audrec);
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
- msm_adsp_disable(audio->audpre);
+ /*reset the sampling frequency information at
+ audpreproc layer*/
+ audio->session_info.sampling_freq = 0;
+ audpreproc_update_audrec_info(&audio->session_info);
+ audpreproc_disable(audio->enc_id, audio);
audmgr_disable(&audio->audmgr);
}
}
return 0;
}
-/* ------------------- dsp --------------------- */
-static void audpre_dsp_event(void *data, unsigned id, size_t len,
- void (*getevent)(void *ptr, size_t len))
-{
- uint16_t msg[2];
- getevent(msg, sizeof(msg));
-
- switch (id) {
- case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
- MM_DBG("type %d, status_flag %d\n", msg[0], msg[1]);
- break;
- case AUDPREPROC_MSG_ERROR_MSG_ID:
- MM_ERR("err_index %d\n", msg[0]);
- break;
- case ADSP_MESSAGE_ID:
- MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
- break;
- default:
- MM_ERR("unknown event %d\n", id);
- }
-}
-
static void audamrnb_in_get_dsp_frames(struct audio_amrnb_in *audio)
{
struct audio_frame *frame;
@@ -555,10 +567,6 @@
}
}
-struct msm_adsp_ops audpre_amrnb_adsp_ops = {
- .event = audpre_dsp_event,
-};
-
struct msm_adsp_ops audrec_amrnb_adsp_ops = {
.event = audrec_dsp_event,
};
@@ -1201,12 +1209,8 @@
audamrnb_in_flush(audio);
msm_adsp_put(audio->audrec);
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
- msm_adsp_put(audio->audpre);
-
audpreproc_aenc_free(audio->enc_id);
audio->audrec = NULL;
- audio->audpre = NULL;
audio->opened = 0;
if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) && \
(audio->out_data)) {
@@ -1304,15 +1308,6 @@
goto done;
}
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
- rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
- &audpre_amrnb_adsp_ops, audio);
- if (rc) {
- msm_adsp_put(audio->audrec);
- audpreproc_aenc_free(audio->enc_id);
- goto done;
- }
- }
audio->dsp_cnt = 0;
audio->stopped = 0;
audio->wflush = 0;
@@ -1414,8 +1409,6 @@
dma_free_coherent(NULL, dma_size, audio->data, audio->phys);
evt_error:
msm_adsp_put(audio->audrec);
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
- msm_adsp_put(audio->audpre);
audpreproc_aenc_free(audio->enc_id);
mutex_unlock(&audio->lock);
diff --git a/arch/arm/mach-msm/qdsp5/audio_amrwb.c b/arch/arm/mach-msm/qdsp5/audio_amrwb.c
index 66b9354..f18aca7 100644
--- a/arch/arm/mach-msm/qdsp5/audio_amrwb.c
+++ b/arch/arm/mach-msm/qdsp5/audio_amrwb.c
@@ -48,6 +48,7 @@
#include <mach/iommu_domains.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_evrc.c b/arch/arm/mach-msm/qdsp5/audio_evrc.c
index 1d4148a..7aeadac 100644
--- a/arch/arm/mach-msm/qdsp5/audio_evrc.c
+++ b/arch/arm/mach-msm/qdsp5/audio_evrc.c
@@ -43,6 +43,7 @@
#include <mach/iommu_domains.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_evrc_in.c b/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
index e955c4b..3310743 100644
--- a/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_evrc_in.c
@@ -111,7 +111,6 @@
int out_frame_cnt;
struct msm_adsp_module *audrec;
- struct msm_adsp_module *audpre;
/* configuration to use on next enable */
@@ -154,6 +153,8 @@
struct ion_client *client;
struct ion_handle *input_buff_handle;
struct ion_handle *output_buff_handle;
+
+ struct audrec_session_info session_info; /*audrec session info*/
};
struct audio_frame {
@@ -232,6 +233,32 @@
}
}
+/* ------------------- dsp --------------------- */
+static void audpre_dsp_event(void *data, unsigned id, void *event_data)
+{
+
+ uint16_t *msg = event_data;
+
+ if (!msg)
+ return;
+
+ switch (id) {
+ case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
+ MM_DBG("type %d, status_flag %d\n",\
+ msg[0], msg[1]);
+ break;
+ case AUDPREPROC_MSG_ERROR_MSG_ID:
+ MM_INFO("err_index %d\n", msg[0]);
+ break;
+ case ADSP_MESSAGE_ID:
+ MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
+ break;
+ default:
+ MM_ERR("unknown event %d\n", id);
+ }
+}
+
+
/* must be called with audio->lock held */
static int audevrc_in_enable(struct audio_evrc_in *audio)
{
@@ -252,16 +279,24 @@
if (rc < 0)
return rc;
- if (msm_adsp_enable(audio->audpre)) {
+ if (audpreproc_enable(audio->enc_id,
+ &audpre_dsp_event, audio)) {
+ MM_ERR("msm_adsp_enable(audpreproc) failed\n");
audmgr_disable(&audio->audmgr);
- MM_ERR("msm_adsp_enable(audpre) failed\n");
return -ENODEV;
}
+
+ /*update aurec session info in audpreproc layer*/
+ audio->session_info.session_id = audio->enc_id;
+ audio->session_info.sampling_freq =
+ convert_samp_index(audio->samp_rate);
+ audpreproc_update_audrec_info(&audio->session_info);
}
+
if (msm_adsp_enable(audio->audrec)) {
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
+ audpreproc_disable(audio->enc_id, audio);
audmgr_disable(&audio->audmgr);
- msm_adsp_disable(audio->audpre);
}
MM_ERR("msm_adsp_enable(audrec) failed\n");
return -ENODEV;
@@ -288,35 +323,17 @@
wake_up(&audio->wait);
msm_adsp_disable(audio->audrec);
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
- msm_adsp_disable(audio->audpre);
+ audpreproc_disable(audio->enc_id, audio);
+ /*reset the sampling frequency information at
+ audpreproc layer*/
+ audio->session_info.sampling_freq = 0;
+ audpreproc_update_audrec_info(&audio->session_info);
audmgr_disable(&audio->audmgr);
}
}
return 0;
}
-/* ------------------- dsp --------------------- */
-static void audpre_dsp_event(void *data, unsigned id, size_t len,
- void (*getevent)(void *ptr, size_t len))
-{
- uint16_t msg[2];
- getevent(msg, sizeof(msg));
-
- switch (id) {
- case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
- MM_DBG("type %d, status_flag %d\n", msg[0], msg[1]);
- break;
- case AUDPREPROC_MSG_ERROR_MSG_ID:
- MM_ERR("err_index %d\n", msg[0]);
- break;
- case ADSP_MESSAGE_ID:
- MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
- break;
- default:
- MM_ERR("unknown event %d\n", id);
- }
-}
-
static void audevrc_in_get_dsp_frames(struct audio_evrc_in *audio)
{
struct audio_frame *frame;
@@ -557,10 +574,6 @@
}
}
-static struct msm_adsp_ops audpre_evrc_adsp_ops = {
- .event = audpre_dsp_event,
-};
-
static struct msm_adsp_ops audrec_evrc_adsp_ops = {
.event = audrec_dsp_event,
};
@@ -1186,12 +1199,8 @@
audevrc_in_flush(audio);
msm_adsp_put(audio->audrec);
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
- msm_adsp_put(audio->audpre);
-
audpreproc_aenc_free(audio->enc_id);
audio->audrec = NULL;
- audio->audpre = NULL;
audio->opened = 0;
if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) && \
(audio->out_data)) {
@@ -1282,16 +1291,6 @@
goto done;
}
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
- rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
- &audpre_evrc_adsp_ops, audio);
- if (rc) {
- msm_adsp_put(audio->audrec);
- audpreproc_aenc_free(audio->enc_id);
- goto done;
- }
- }
-
audio->dsp_cnt = 0;
audio->stopped = 0;
audio->wflush = 0;
@@ -1429,8 +1428,6 @@
ion_client_destroy(client);
client_create_error:
msm_adsp_put(audio->audrec);
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
- msm_adsp_put(audio->audpre);
audpreproc_aenc_free(audio->enc_id);
mutex_unlock(&audio->lock);
diff --git a/arch/arm/mach-msm/qdsp5/audio_lpa.c b/arch/arm/mach-msm/qdsp5/audio_lpa.c
index fe7b270..6cbb981a3 100644
--- a/arch/arm/mach-msm/qdsp5/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp5/audio_lpa.c
@@ -48,6 +48,7 @@
#include <mach/iommu_domains.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_mp3.c b/arch/arm/mach-msm/qdsp5/audio_mp3.c
index 427dc8f..167de9c 100644
--- a/arch/arm/mach-msm/qdsp5/audio_mp3.c
+++ b/arch/arm/mach-msm/qdsp5/audio_mp3.c
@@ -42,6 +42,7 @@
#include <mach/msm_memtypes.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_out.c b/arch/arm/mach-msm/qdsp5/audio_out.c
index 0c8034c..6f3bf91 100644
--- a/arch/arm/mach-msm/qdsp5/audio_out.c
+++ b/arch/arm/mach-msm/qdsp5/audio_out.c
@@ -41,6 +41,7 @@
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/htc_pwrsink.h>
#include <mach/debug_mm.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm.c b/arch/arm/mach-msm/qdsp5/audio_pcm.c
index 880de09..3a92e0c 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm.c
@@ -48,6 +48,7 @@
#include <mach/iommu_domains.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
index 716dbd2..4dcbc7b 100644
--- a/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_pcm_in.c
@@ -75,7 +75,6 @@
struct mutex read_lock;
wait_queue_head_t wait;
- struct msm_adsp_module *audpre;
struct msm_adsp_module *audrec;
const char *module_name;
unsigned queue_ids;
@@ -105,6 +104,7 @@
int enabled;
int running;
int stopped; /* set when stopped, cleared on flush */
+ struct audrec_session_info session_info; /*audrec session info*/
/* audpre settings */
int tx_agc_enable;
@@ -176,6 +176,32 @@
}
}
+/* ------------------- dsp --------------------- */
+static void audpre_dsp_event(void *data, unsigned id, void *event_data)
+{
+
+ uint16_t *msg = event_data;
+
+ if (!msg)
+ return;
+
+ switch (id) {
+ case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
+ MM_DBG("type %d, status_flag %d\n",\
+ msg[0], msg[1]);
+ break;
+ case AUDPREPROC_MSG_ERROR_MSG_ID:
+ MM_INFO("err_index %d\n", msg[0]);
+ break;
+ case ADSP_MESSAGE_ID:
+ MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
+ break;
+ default:
+ MM_ERR("unknown event %d\n", id);
+ }
+}
+
+
/* must be called with audio->lock held */
static int audpcm_in_enable(struct audio_in *audio)
{
@@ -195,14 +221,15 @@
if (rc < 0)
return rc;
- if (msm_adsp_enable(audio->audpre)) {
- MM_ERR("msm_adsp_enable(audpre) failed\n");
+ if (audpreproc_enable(audio->enc_id, &audpre_dsp_event, audio)) {
+ MM_ERR("msm_adsp_enable(audpreproc) failed\n");
audmgr_disable(&audio->audmgr);
return -ENODEV;
}
+
if (msm_adsp_enable(audio->audrec)) {
+ audpreproc_disable(audio->enc_id, audio);
audmgr_disable(&audio->audmgr);
- msm_adsp_disable(audio->audpre);
MM_ERR("msm_adsp_enable(audrec) failed\n");
return -ENODEV;
}
@@ -210,6 +237,12 @@
audio->enabled = 1;
audpcm_in_dsp_enable(audio, 1);
+ /*update aurec session info in audpreproc layer*/
+ audio->session_info.session_id = audio->enc_id;
+ audio->session_info.sampling_freq =
+ convert_samp_index(audio->samp_rate);
+ audpreproc_update_audrec_info(&audio->session_info);
+
return 0;
}
@@ -225,34 +258,15 @@
wake_up(&audio->wait);
msm_adsp_disable(audio->audrec);
- msm_adsp_disable(audio->audpre);
+ audpreproc_disable(audio->enc_id, audio);
+ /*reset the sampling frequency information at audpreproc layer*/
+ audio->session_info.sampling_freq = 0;
+ audpreproc_update_audrec_info(&audio->session_info);
audmgr_disable(&audio->audmgr);
}
return 0;
}
-/* ------------------- dsp --------------------- */
-static void audpre_dsp_event(void *data, unsigned id, size_t len,
- void (*getevent)(void *ptr, size_t len))
-{
- uint16_t msg[2];
- getevent(msg, sizeof(msg));
-
- switch (id) {
- case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
- MM_INFO("type %d, status_flag %d\n", msg[0], msg[1]);
- break;
- case AUDPREPROC_MSG_ERROR_MSG_ID:
- MM_ERR("err_index %d\n", msg[0]);
- break;
- case ADSP_MESSAGE_ID:
- MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
- break;
- default:
- MM_ERR("unknown event %d\n", id);
- }
-}
-
struct audio_frame {
uint16_t count_low;
uint16_t count_high;
@@ -360,18 +374,10 @@
}
}
-static struct msm_adsp_ops audpre_adsp_ops = {
- .event = audpre_dsp_event,
-};
-
static struct msm_adsp_ops audrec_adsp_ops = {
.event = audrec_dsp_event,
};
-
-#define audio_send_queue_pre(audio, cmd, len) \
- msm_adsp_write(audio->audpre, QDSP_uPAudPreProcCmdQueue, cmd, len)
-
#define audio_send_queue_recbs(audio, cmd, len) \
msm_adsp_write(audio->audrec, ((audio->queue_ids & 0xFFFF0000) >> 16),\
cmd, len)
@@ -399,7 +405,7 @@
audio->tx_agc_cfg.tx_agc_enable_flag =
AUDPREPROC_CMD_TX_AGC_ENA_FLAG_ENA;
/* cmd.param_mask = 0xFFF0 from sample code */
- audio->tx_agc_cfg.param_mask =
+ audio->tx_agc_cfg.tx_agc_param_mask =
(1 << AUDPREPROC_CMD_PARAM_MASK_RMS_TAY) |
(1 << AUDPREPROC_CMD_PARAM_MASK_RELEASEK) |
(1 << AUDPREPROC_CMD_PARAM_MASK_DELAY) |
@@ -420,7 +426,7 @@
}
cmd = audio->tx_agc_cfg;
- return audio_send_queue_pre(audio, &cmd, sizeof(cmd));
+ return audpreproc_dsp_set_agc(&cmd, sizeof(cmd));
}
static int audio_enable_tx_agc(struct audio_in *audio, int enable)
@@ -466,7 +472,7 @@
}
cmd = audio->ns_cfg;
- return audio_send_queue_pre(audio, &cmd, sizeof(cmd));
+ return audpreproc_dsp_set_ns(&cmd, sizeof(cmd));
}
static int audio_enable_ns(struct audio_in *audio, int enable)
@@ -495,7 +501,7 @@
cmd = audio->iir_cfg;
- return audio_send_queue_pre(audio, &cmd, sizeof(cmd));
+ return audpreproc_dsp_set_iir(&cmd, sizeof(cmd));
}
static int audio_enable_iir(struct audio_in *audio, int enable)
@@ -762,9 +768,7 @@
audpcm_in_flush(audio);
audpreproc_aenc_free(audio->enc_id);
msm_adsp_put(audio->audrec);
- msm_adsp_put(audio->audpre);
audio->audrec = NULL;
- audio->audpre = NULL;
audio->opened = 0;
if (audio->data) {
ion_unmap_kernel(audio->client, audio->output_buff_handle);
@@ -824,14 +828,6 @@
goto done;
}
- rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
- &audpre_adsp_ops, audio);
- if (rc) {
- msm_adsp_put(audio->audrec);
- audpreproc_aenc_free(audio->enc_id);
- goto done;
- }
-
audio->dsp_cnt = 0;
audio->stopped = 0;
@@ -899,7 +895,6 @@
ion_client_destroy(client);
client_create_error:
msm_adsp_put(audio->audrec);
- msm_adsp_put(audio->audpre);
audpreproc_aenc_free(audio->enc_id);
mutex_unlock(&audio->lock);
return rc;
diff --git a/arch/arm/mach-msm/qdsp5/audio_qcelp.c b/arch/arm/mach-msm/qdsp5/audio_qcelp.c
index dc257cd..e1a6299 100644
--- a/arch/arm/mach-msm/qdsp5/audio_qcelp.c
+++ b/arch/arm/mach-msm/qdsp5/audio_qcelp.c
@@ -44,6 +44,7 @@
#include <mach/iommu_domains.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c b/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
index 99a169d..57ae772 100644
--- a/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
+++ b/arch/arm/mach-msm/qdsp5/audio_qcelp_in.c
@@ -112,7 +112,6 @@
int out_frame_cnt;
struct msm_adsp_module *audrec;
- struct msm_adsp_module *audpre;
/* configuration to use on next enable */
@@ -155,6 +154,8 @@
struct ion_client *client;
struct ion_handle *input_buff_handle;
struct ion_handle *output_buff_handle;
+
+ struct audrec_session_info session_info; /*audrec session info*/
};
struct audio_frame {
@@ -233,6 +234,32 @@
}
}
+/* ------------------- dsp --------------------- */
+static void audpre_dsp_event(void *data, unsigned id, void *event_data)
+{
+
+ uint16_t *msg = event_data;
+
+ if (!msg)
+ return;
+
+ switch (id) {
+ case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
+ MM_DBG("type %d, status_flag %d\n",\
+ msg[0], msg[1]);
+ break;
+ case AUDPREPROC_MSG_ERROR_MSG_ID:
+ MM_INFO("err_index %d\n", msg[0]);
+ break;
+ case ADSP_MESSAGE_ID:
+ MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
+ break;
+ default:
+ MM_ERR("unknown event %d\n", id);
+ }
+}
+
+
/* must be called with audio->lock held */
static int audqcelp_in_enable(struct audio_qcelp_in *audio)
{
@@ -253,16 +280,23 @@
if (rc < 0)
return rc;
- if (msm_adsp_enable(audio->audpre)) {
+ if (audpreproc_enable(audio->enc_id,
+ &audpre_dsp_event, audio)) {
+ MM_ERR("msm_adsp_enable(audpreproc) failed\n");
audmgr_disable(&audio->audmgr);
- MM_ERR("msm_adsp_enable(audpre) failed\n");
return -ENODEV;
}
+
+ /*update aurec session info in audpreproc layer*/
+ audio->session_info.session_id = audio->enc_id;
+ audio->session_info.sampling_freq =
+ convert_samp_index(audio->samp_rate);
+ audpreproc_update_audrec_info(&audio->session_info);
}
if (msm_adsp_enable(audio->audrec)) {
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
+ audpreproc_disable(audio->enc_id, audio);
audmgr_disable(&audio->audmgr);
- msm_adsp_disable(audio->audpre);
}
MM_ERR("msm_adsp_enable(audrec) failed\n");
return -ENODEV;
@@ -288,35 +322,17 @@
wake_up(&audio->wait);
msm_adsp_disable(audio->audrec);
if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
- msm_adsp_disable(audio->audpre);
+ audpreproc_disable(audio->enc_id, audio);
audmgr_disable(&audio->audmgr);
+ /*reset the sampling frequency information at
+ audpreproc layer*/
+ audio->session_info.sampling_freq = 0;
+ audpreproc_update_audrec_info(&audio->session_info);
}
}
return 0;
}
-/* ------------------- dsp --------------------- */
-static void audpre_dsp_event(void *data, unsigned id, size_t len,
- void (*getevent)(void *ptr, size_t len))
-{
- uint16_t msg[2];
- getevent(msg, sizeof(msg));
-
- switch (id) {
- case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
- MM_DBG("type %d, status_flag %d\n", msg[0], msg[1]);
- break;
- case AUDPREPROC_MSG_ERROR_MSG_ID:
- MM_ERR("err_index %d\n", msg[0]);
- break;
- case ADSP_MESSAGE_ID:
- MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
- break;
- default:
- MM_ERR("unknown event %d\n", id);
- }
-}
-
static void audqcelp_in_get_dsp_frames(struct audio_qcelp_in *audio)
{
struct audio_frame *frame;
@@ -557,10 +573,6 @@
}
}
-static struct msm_adsp_ops audpre_qcelp_adsp_ops = {
- .event = audpre_dsp_event,
-};
-
static struct msm_adsp_ops audrec_qcelp_adsp_ops = {
.event = audrec_dsp_event,
};
@@ -1187,12 +1199,8 @@
audqcelp_in_flush(audio);
msm_adsp_put(audio->audrec);
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
- msm_adsp_put(audio->audpre);
-
audpreproc_aenc_free(audio->enc_id);
audio->audrec = NULL;
- audio->audpre = NULL;
audio->opened = 0;
if ((audio->mode == MSM_AUD_ENC_MODE_NONTUNNEL) && \
@@ -1285,16 +1293,6 @@
goto done;
}
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL) {
- rc = msm_adsp_get("AUDPREPROCTASK", &audio->audpre,
- &audpre_qcelp_adsp_ops, audio);
- if (rc) {
- msm_adsp_put(audio->audrec);
- audpreproc_aenc_free(audio->enc_id);
- goto done;
- }
- }
-
audio->dsp_cnt = 0;
audio->stopped = 0;
audio->wflush = 0;
@@ -1434,8 +1432,6 @@
ion_client_destroy(client);
client_create_error:
msm_adsp_put(audio->audrec);
- if (audio->mode == MSM_AUD_ENC_MODE_TUNNEL)
- msm_adsp_put(audio->audpre);
audpreproc_aenc_free(audio->enc_id);
mutex_unlock(&audio->lock);
diff --git a/arch/arm/mach-msm/qdsp5/audio_wma.c b/arch/arm/mach-msm/qdsp5/audio_wma.c
index e28e704..276c9d4 100644
--- a/arch/arm/mach-msm/qdsp5/audio_wma.c
+++ b/arch/arm/mach-msm/qdsp5/audio_wma.c
@@ -48,6 +48,7 @@
#include <mach/iommu_domains.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audio_wmapro.c b/arch/arm/mach-msm/qdsp5/audio_wmapro.c
index 87afcf0..b881c59 100644
--- a/arch/arm/mach-msm/qdsp5/audio_wmapro.c
+++ b/arch/arm/mach-msm/qdsp5/audio_wmapro.c
@@ -45,6 +45,7 @@
#include <mach/msm_adsp.h>
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
#include <mach/qdsp5/qdsp5audplaycmdi.h>
#include <mach/qdsp5/qdsp5audplaymsg.h>
#include <mach/qdsp5/qdsp5rmtcmdi.h>
diff --git a/arch/arm/mach-msm/qdsp5/audmgr.c b/arch/arm/mach-msm/qdsp5/audmgr.c
index 231a28c..666323b 100644
--- a/arch/arm/mach-msm/qdsp5/audmgr.c
+++ b/arch/arm/mach-msm/qdsp5/audmgr.c
@@ -3,7 +3,7 @@
* interface to "audmgr" service on the baseband cpu
*
* Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009, 2012 Code Aurora Forum. 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
@@ -35,6 +35,10 @@
#define STATE_ENABLED 3
#define STATE_DISABLING 4
#define STATE_ERROR 5
+#define MAX_DEVICE_INFO_CALLBACK 1
+#define SESSION_VOICE 0
+#define SESSION_PLAYBACK 1
+#define SESSION_RECORDING 2
/* store information used across complete audmgr sessions */
struct audmgr_global {
@@ -42,6 +46,9 @@
struct msm_rpc_endpoint *ept;
struct task_struct *task;
uint32_t rpc_version;
+ int cad;
+ struct device_info_callback *device_cb[MAX_DEVICE_INFO_CALLBACK];
+
};
static DEFINE_MUTEX(audmgr_lock);
@@ -49,6 +56,59 @@
.lock = &audmgr_lock,
};
+static void audmgr_rpc_connect(struct audmgr_global *amg)
+{
+ amg->cad = 0;
+ amg->ept = msm_rpc_connect_compatible(AUDMGR_PROG,
+ AUDMGR_VERS_COMP_VER3,
+ MSM_RPC_UNINTERRUPTIBLE);
+ if (IS_ERR(amg->ept)) {
+ MM_DBG("connect failed with current VERS"\
+ "= %x, trying again with Cad API\n",
+ AUDMGR_VERS_COMP_VER3);
+ amg->ept = msm_rpc_connect_compatible(AUDMGR_PROG,
+ AUDMGR_VERS_COMP_VER4,
+ MSM_RPC_UNINTERRUPTIBLE);
+ if (IS_ERR(amg->ept)) {
+ amg->ept = msm_rpc_connect_compatible(AUDMGR_PROG,
+ AUDMGR_VERS_COMP_VER2,
+ MSM_RPC_UNINTERRUPTIBLE);
+ if (IS_ERR(amg->ept)) {
+ MM_ERR("connect failed with current VERS" \
+ "= %x, trying again with another API\n",
+ AUDMGR_VERS_COMP_VER2);
+ amg->ept = msm_rpc_connect_compatible(
+ AUDMGR_PROG,
+ AUDMGR_VERS_COMP,
+ MSM_RPC_UNINTERRUPTIBLE);
+ if (IS_ERR(amg->ept)) {
+ MM_ERR("connect failed with current" \
+ "VERS=%x, trying again with" \
+ "another API\n",
+ AUDMGR_VERS_COMP);
+ amg->ept = msm_rpc_connect(AUDMGR_PROG,
+ AUDMGR_VERS,
+ MSM_RPC_UNINTERRUPTIBLE);
+ amg->rpc_version = AUDMGR_VERS;
+ } else
+ amg->rpc_version = AUDMGR_VERS_COMP;
+ } else
+ amg->rpc_version = AUDMGR_VERS_COMP_VER2;
+ } else {
+ amg->rpc_version = AUDMGR_VERS_COMP_VER4;
+ amg->cad = 1;
+ }
+ } else
+ amg->rpc_version = AUDMGR_VERS_COMP_VER3;
+
+ if (IS_ERR(amg->ept)) {
+ amg->ept = NULL;
+ MM_ERR("failed to connect to audmgr svc\n");
+ }
+
+ return;
+}
+
static void rpc_ack(struct msm_rpc_endpoint *ept, uint32_t xid)
{
uint32_t rep[6];
@@ -64,34 +124,45 @@
}
static void process_audmgr_callback(struct audmgr_global *amg,
- struct rpc_audmgr_cb_func_ptr *args,
- int len)
+ void *args, int len)
{
struct audmgr *am;
+ int i = 0;
+ struct rpc_audmgr_cb_device_info *temp;
- /* Allow only if complete arguments recevied */
- if (len < (sizeof(struct rpc_audmgr_cb_func_ptr)))
+ /* Allow only if complete arguments recevied*/
+ if (len < MIN_RPC_DATA_LENGTH)
return;
/* Allow only if valid argument */
- if (be32_to_cpu(args->set_to_one) != 1)
+ if (be32_to_cpu(((struct rpc_audmgr_cb_common *)args)->set_to_one) != 1)
return;
- am = (struct audmgr *) be32_to_cpu(args->client_data);
-
- if (!am)
- return;
-
- switch (be32_to_cpu(args->status)) {
+ switch (be32_to_cpu(((struct rpc_audmgr_cb_common *)args)->status)) {
case RPC_AUDMGR_STATUS_READY:
- am->handle = be32_to_cpu(args->u.handle);
+ am = (struct audmgr *) be32_to_cpu(
+ ((struct rpc_audmgr_cb_ready *)args)->client_data);
+ if (!am)
+ return;
+ am->handle = be32_to_cpu(
+ ((struct rpc_audmgr_cb_ready *)args)->u.handle);
MM_INFO("rpc READY handle=0x%08x\n", am->handle);
break;
case RPC_AUDMGR_STATUS_CODEC_CONFIG: {
- uint32_t volume;
- volume = be32_to_cpu(args->u.volume);
- MM_INFO("rpc CODEC_CONFIG volume=0x%08x\n", volume);
- am->state = STATE_ENABLED;
+ MM_INFO("rpc CODEC_CONFIG\n");
+ am = (struct audmgr *) be32_to_cpu(
+ ((struct rpc_audmgr_cb_ready *)args)->client_data);
+ if (!am)
+ return;
+ if (am->state != STATE_ENABLED)
+ am->state = STATE_ENABLED;
+ while ((amg->device_cb[i] != NULL) &&
+ (i < MAX_DEVICE_INFO_CALLBACK) &&
+ (amg->cad)) {
+ amg->device_cb[i]->func(&(am->evt),
+ amg->device_cb[i]->private);
+ i++;
+ }
wake_up(&am->wait);
break;
}
@@ -109,14 +180,51 @@
break;
case RPC_AUDMGR_STATUS_DISABLED:
MM_ERR("DISABLED\n");
+ am = (struct audmgr *) be32_to_cpu(
+ ((struct rpc_audmgr_cb_ready *)args)->client_data);
+ if (!am)
+ return;
am->state = STATE_DISABLED;
wake_up(&am->wait);
break;
case RPC_AUDMGR_STATUS_ERROR:
MM_ERR("ERROR?\n");
+ am = (struct audmgr *) be32_to_cpu(
+ ((struct rpc_audmgr_cb_ready *)args)->client_data);
+ if (!am)
+ return;
am->state = STATE_ERROR;
wake_up(&am->wait);
break;
+ case RPC_AUDMGR_STATUS_DEVICE_INFO:
+ MM_INFO("rpc DEVICE_INFO\n");
+ if (!amg->cad)
+ break;
+ temp = (struct rpc_audmgr_cb_device_info *)args;
+ am = (struct audmgr *) be32_to_cpu(temp->client_data);
+ if (!am)
+ return;
+ if (am->evt.session_info == SESSION_PLAYBACK) {
+ am->evt.dev_type.rx_device =
+ be32_to_cpu(temp->d.rx_device);
+ am->evt.dev_type.tx_device = 0;
+ am->evt.acdb_id = am->evt.dev_type.rx_device;
+ } else if (am->evt.session_info == SESSION_RECORDING) {
+ am->evt.dev_type.rx_device = 0;
+ am->evt.dev_type.tx_device =
+ be32_to_cpu(temp->d.tx_device);
+ am->evt.acdb_id = am->evt.dev_type.tx_device;
+ }
+ am->evt.dev_type.ear_mute =
+ be32_to_cpu(temp->d.ear_mute);
+ am->evt.dev_type.mic_mute =
+ be32_to_cpu(temp->d.mic_mute);
+ am->evt.dev_type.volume =
+ be32_to_cpu(temp->d.volume);
+ break;
+ case RPC_AUDMGR_STATUS_DEVICE_CONFIG:
+ MM_ERR("rpc DEVICE_CONFIG\n");
+ break;
default:
break;
}
@@ -201,6 +309,36 @@
return 0;
}
+static unsigned convert_samp_index(unsigned index)
+{
+ switch (index) {
+ case RPC_AUD_DEF_SAMPLE_RATE_48000: return 48000;
+ case RPC_AUD_DEF_SAMPLE_RATE_44100: return 44100;
+ case RPC_AUD_DEF_SAMPLE_RATE_32000: return 32000;
+ case RPC_AUD_DEF_SAMPLE_RATE_24000: return 24000;
+ case RPC_AUD_DEF_SAMPLE_RATE_22050: return 22050;
+ case RPC_AUD_DEF_SAMPLE_RATE_16000: return 16000;
+ case RPC_AUD_DEF_SAMPLE_RATE_12000: return 12000;
+ case RPC_AUD_DEF_SAMPLE_RATE_11025: return 11025;
+ case RPC_AUD_DEF_SAMPLE_RATE_8000: return 8000;
+ default: return 11025;
+ }
+}
+
+static void get_current_session_info(struct audmgr *am,
+ struct audmgr_config *cfg)
+{
+ if (cfg->def_method == RPC_AUD_DEF_METHOD_PLAYBACK ||
+ (cfg->def_method == RPC_AUD_DEF_METHOD_HOST_PCM && cfg->rx_rate)) {
+ am->evt.session_info = SESSION_PLAYBACK; /* playback */
+ am->evt.sample_rate = convert_samp_index(cfg->rx_rate);
+ } else if (cfg->def_method == RPC_AUD_DEF_METHOD_RECORD) {
+ am->evt.session_info = SESSION_RECORDING; /* recording */
+ am->evt.sample_rate = convert_samp_index(cfg->tx_rate);
+ } else
+ am->evt.session_info = SESSION_VOICE;
+}
+
struct audmgr_enable_msg {
struct rpc_request_hdr hdr;
struct rpc_audmgr_enable_client_args args;
@@ -223,39 +361,7 @@
/* connect to audmgr end point and polling thread only once */
if (amg->ept == NULL) {
- amg->ept = msm_rpc_connect_compatible(AUDMGR_PROG,
- AUDMGR_VERS_COMP_VER3,
- MSM_RPC_UNINTERRUPTIBLE);
- if (IS_ERR(amg->ept)) {
- MM_ERR("connect failed with current VERS \
- = %x, trying again with another API\n",
- AUDMGR_VERS_COMP_VER3);
- amg->ept = msm_rpc_connect_compatible(AUDMGR_PROG,
- AUDMGR_VERS_COMP_VER2,
- MSM_RPC_UNINTERRUPTIBLE);
- if (IS_ERR(amg->ept)) {
- MM_ERR("connect failed with current VERS \
- = %x, trying again with another API\n",
- AUDMGR_VERS_COMP_VER2);
- amg->ept = msm_rpc_connect_compatible(
- AUDMGR_PROG,
- AUDMGR_VERS_COMP,
- MSM_RPC_UNINTERRUPTIBLE);
- if (IS_ERR(amg->ept)) {
- MM_ERR("connect failed with current \
- VERS=%x, trying again with another \
- API\n", AUDMGR_VERS_COMP);
- amg->ept = msm_rpc_connect(AUDMGR_PROG,
- AUDMGR_VERS,
- MSM_RPC_UNINTERRUPTIBLE);
- amg->rpc_version = AUDMGR_VERS;
- } else
- amg->rpc_version = AUDMGR_VERS_COMP;
- } else
- amg->rpc_version = AUDMGR_VERS_COMP_VER2;
- } else
- amg->rpc_version = AUDMGR_VERS_COMP_VER3;
-
+ audmgr_rpc_connect(amg);
if (IS_ERR(amg->ept)) {
rc = PTR_ERR(amg->ept);
amg->ept = NULL;
@@ -312,6 +418,7 @@
msg.args.cb_func = cpu_to_be32(0x11111111);
msg.args.client_data = cpu_to_be32((int)am);
+ get_current_session_info(am, cfg);
msm_rpc_setup_req(&msg.hdr, AUDMGR_PROG, amg->rpc_version,
AUDMGR_ENABLE_CLIENT);
@@ -326,6 +433,7 @@
if (am->state == STATE_ENABLED)
return 0;
+ am->evt.session_info = -1;
MM_ERR("unexpected state %d while enabling?!\n", am->state);
return -ENODEV;
}
@@ -341,6 +449,7 @@
return 0;
MM_INFO("session 0x%08x\n", (int) am);
+ am->evt.session_info = -1;
msg.handle = cpu_to_be32(am->handle);
msm_rpc_setup_req(&msg.hdr, AUDMGR_PROG, amg->rpc_version,
AUDMGR_DISABLE_CLIENT);
@@ -363,3 +472,33 @@
return -ENODEV;
}
EXPORT_SYMBOL(audmgr_disable);
+
+int audmgr_register_device_info_callback(struct device_info_callback *dcb)
+{
+ struct audmgr_global *amg = &the_audmgr_state;
+ int i;
+
+ for (i = 0; i < MAX_DEVICE_INFO_CALLBACK; i++) {
+ if (NULL == amg->device_cb[i]) {
+ amg->device_cb[i] = dcb;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(audmgr_register_device_info_callback);
+
+int audmgr_deregister_device_info_callback(struct device_info_callback *dcb)
+{
+ struct audmgr_global *amg = &the_audmgr_state;
+ int i;
+
+ for (i = 0; i < MAX_DEVICE_INFO_CALLBACK; i++) {
+ if (dcb == amg->device_cb[i]) {
+ amg->device_cb[i] = NULL;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(audmgr_deregister_device_info_callback);
diff --git a/arch/arm/mach-msm/qdsp5/audmgr.h b/arch/arm/mach-msm/qdsp5/audmgr.h
index 3d8c560..15dd954 100644
--- a/arch/arm/mach-msm/qdsp5/audmgr.h
+++ b/arch/arm/mach-msm/qdsp5/audmgr.h
@@ -125,6 +125,9 @@
RPC_AUDMGR_STATUS_VOLUME_CHANGE,
RPC_AUDMGR_STATUS_DISABLED,
RPC_AUDMGR_STATUS_ERROR,
+ RPC_AUDMGR_STATUS_DEVICE_CONFIG,
+ RPC_AUDMGR_STATUS_DEVICE_INFO
+
};
struct rpc_audmgr_enable_client_args {
@@ -148,6 +151,7 @@
#define AUDMGR_GET_RX_SAMPLE_RATE 8
#define AUDMGR_GET_TX_SAMPLE_RATE 9
#define AUDMGR_SET_DEVICE_MODE 10
+#define MIN_RPC_DATA_LENGTH 16
#define AUDMGR_PROG_VERS "rs30000013:0x7feccbff"
#define AUDMGR_PROG 0x30000013
@@ -155,8 +159,17 @@
#define AUDMGR_VERS_COMP 0x00010001
#define AUDMGR_VERS_COMP_VER2 0x00020001
#define AUDMGR_VERS_COMP_VER3 0x00030001
+#define AUDMGR_VERS_COMP_VER4 0x00040001
-struct rpc_audmgr_cb_func_ptr {
+struct cad_device_info_type {
+ uint32_t rx_device;
+ uint32_t tx_device;
+ uint32_t ear_mute;
+ uint32_t mic_mute;
+ uint32_t volume;
+};
+
+struct rpc_audmgr_cb_common {
uint32_t cb_id; /* cb_func */
uint32_t status; /* Audmgr status */
uint32_t set_to_one; /* Pointer status (1 = valid, 0 = invalid) */
@@ -165,6 +178,10 @@
disc = AUDMGR_STATUS_CODEC_CONFIG => data = volume
disc = AUDMGR_STATUS_DISABLED => data =status_disabled
disc = AUDMGR_STATUS_VOLUME_CHANGE => data = volume_change */
+};
+
+struct rpc_audmgr_cb_ready {
+ struct rpc_audmgr_cb_common c_data;
union {
uint32_t handle;
uint32_t volume;
@@ -174,18 +191,35 @@
uint32_t client_data;
};
+struct rpc_audmgr_cb_device_info {
+ struct rpc_audmgr_cb_common c_data;
+ struct cad_device_info_type d;
+ uint32_t client_data;
+};
+
#define AUDMGR_CB_FUNC_PTR 1
#define AUDMGR_OPR_LSTNR_CB_FUNC_PTR 2
#define AUDMGR_CODEC_LSTR_FUNC_PTR 3
-#define AUDMGR_CB_PROG_VERS "rs31000013:0xf8e3e2d9"
-#define AUDMGR_CB_PROG 0x31000013
-#define AUDMGR_CB_VERS 0xf8e3e2d9
+struct dev_evt_msg {
+ struct cad_device_info_type dev_type;
+ uint32_t acdb_id;
+ int session_info;
+ uint32_t sample_rate;
+};
+
+typedef void (*device_info_func)(struct dev_evt_msg *evt_msg, void *private);
+
+struct device_info_callback {
+ device_info_func func;
+ void *private;
+};
struct audmgr {
wait_queue_head_t wait;
uint32_t handle;
int state;
+ struct dev_evt_msg evt;
};
struct audmgr_config {
@@ -196,86 +230,11 @@
uint32_t snd_method;
};
+int audmgr_register_device_info_callback(struct device_info_callback *dcb);
+int audmgr_deregister_device_info_callback(struct device_info_callback *dcb);
+
int audmgr_open(struct audmgr *am);
int audmgr_close(struct audmgr *am);
int audmgr_enable(struct audmgr *am, struct audmgr_config *cfg);
int audmgr_disable(struct audmgr *am);
-
-typedef void (*audpp_event_func)(void *private, unsigned id, uint16_t *msg);
-typedef void (*audrec_event_func)(void *private, unsigned id, uint16_t *msg);
-
-/* worst case delay of 1sec for response */
-#define MSM_AUD_DECODER_WAIT_MS 1000
-#define MSM_AUD_MODE_TUNNEL 0x00000100
-#define MSM_AUD_MODE_NONTUNNEL 0x00000200
-#define MSM_AUD_DECODER_MASK 0x0000FFFF
-#define MSM_AUD_OP_MASK 0xFFFF0000
-
-/*Playback mode*/
-#define NON_TUNNEL_MODE_PLAYBACK 1
-#define TUNNEL_MODE_PLAYBACK 0
-
-enum msm_aud_decoder_state {
- MSM_AUD_DECODER_STATE_NONE = 0,
- MSM_AUD_DECODER_STATE_FAILURE = 1,
- MSM_AUD_DECODER_STATE_SUCCESS = 2,
- MSM_AUD_DECODER_STATE_CLOSE = 3,
-};
-
-int audpp_adec_alloc(unsigned dec_attrb, const char **module_name,
- unsigned *queueid);
-void audpp_adec_free(int decid);
-
-struct audpp_event_callback {
- audpp_event_func fn;
- void *private;
-};
-
-int audpp_register_event_callback(struct audpp_event_callback *eh);
-int audpp_unregister_event_callback(struct audpp_event_callback *eh);
-int is_audpp_enable(void);
-
-int audpp_enable(int id, audpp_event_func func, void *private);
-void audpp_disable(int id, void *private);
-
-int audpp_send_queue1(void *cmd, unsigned len);
-int audpp_send_queue2(void *cmd, unsigned len);
-int audpp_send_queue3(void *cmd, unsigned len);
-
-int audpp_set_volume_and_pan(unsigned id, unsigned volume, int pan);
-int audpp_pause(unsigned id, int pause);
-int audpp_flush(unsigned id);
-void audpp_avsync(int id, unsigned rate);
-unsigned audpp_avsync_sample_count(int id);
-unsigned audpp_avsync_byte_count(int id);
-int audpp_dsp_set_mbadrc(unsigned id, unsigned enable,
- audpp_cmd_cfg_object_params_mbadrc *mbadrc);
-int audpp_dsp_set_eq(unsigned id, unsigned enable,
- audpp_cmd_cfg_object_params_eqalizer *eq);
-int audpp_dsp_set_rx_iir(unsigned id, unsigned enable,
- audpp_cmd_cfg_object_params_pcm *iir);
-
-int audpp_dsp_set_rx_srs_trumedia_g
- (struct audpp_cmd_cfg_object_params_srstm_g *srstm);
-int audpp_dsp_set_rx_srs_trumedia_w
- (struct audpp_cmd_cfg_object_params_srstm_w *srstm);
-int audpp_dsp_set_rx_srs_trumedia_c
- (struct audpp_cmd_cfg_object_params_srstm_c *srstm);
-int audpp_dsp_set_rx_srs_trumedia_h
- (struct audpp_cmd_cfg_object_params_srstm_h *srstm);
-int audpp_dsp_set_rx_srs_trumedia_p
- (struct audpp_cmd_cfg_object_params_srstm_p *srstm);
-int audpp_dsp_set_rx_srs_trumedia_l
- (struct audpp_cmd_cfg_object_params_srstm_l *srstm);
-
-int audpp_dsp_set_vol_pan(unsigned id,
- audpp_cmd_cfg_object_params_volume *vol_pan);
-int audpp_dsp_set_qconcert_plus(unsigned id, unsigned enable,
- audpp_cmd_cfg_object_params_qconcert *qconcert_plus);
-int audrectask_enable(unsigned enc_type, audrec_event_func func, void *private);
-void audrectask_disable(unsigned enc_type, void *private);
-
-int audrectask_send_cmdqueue(void *cmd, unsigned len);
-int audrectask_send_bitstreamqueue(void *cmd, unsigned len);
-
#endif
diff --git a/arch/arm/mach-msm/qdsp5/audmgr_new.h b/arch/arm/mach-msm/qdsp5/audmgr_new.h
index 2453022..20e27f1 100644
--- a/arch/arm/mach-msm/qdsp5/audmgr_new.h
+++ b/arch/arm/mach-msm/qdsp5/audmgr_new.h
@@ -1,6 +1,6 @@
/* arch/arm/mach-msm/qdsp5/audmgr.h
*
- * Copyright 2008 (c) Code Aurora Forum. All rights reserved.
+ * Copyright 2008,2012 (c) Code Aurora Forum. All rights reserved.
* Copyright (C) 2008 Google, Inc.
*
* This software is licensed under the terms of the GNU General Public
@@ -194,21 +194,4 @@
int audmgr_close(struct audmgr *am);
int audmgr_enable(struct audmgr *am, struct audmgr_config *cfg);
int audmgr_disable(struct audmgr *am);
-
-typedef void (*audpp_event_func)(void *private, unsigned id, uint16_t *msg);
-
-int audpp_enable(int id, audpp_event_func func, void *private);
-void audpp_disable(int id, void *private);
-
-int audpp_send_queue1(void *cmd, unsigned len);
-int audpp_send_queue2(void *cmd, unsigned len);
-int audpp_send_queue3(void *cmd, unsigned len);
-
-int audpp_set_volume_and_pan(unsigned id, unsigned volume, int pan);
-int audpp_pause(unsigned id, int pause);
-int audpp_flush(unsigned id);
-void audpp_avsync(int id, unsigned rate);
-unsigned audpp_avsync_sample_count(int id);
-unsigned audpp_avsync_byte_count(int id);
-
#endif
diff --git a/arch/arm/mach-msm/qdsp5/audpp.c b/arch/arm/mach-msm/qdsp5/audpp.c
index 1616ad0..b4ead5c 100644
--- a/arch/arm/mach-msm/qdsp5/audpp.c
+++ b/arch/arm/mach-msm/qdsp5/audpp.c
@@ -34,6 +34,8 @@
#include <mach/qdsp5/qdsp5audppcmdi.h>
#include <mach/qdsp5/qdsp5audppmsg.h>
+#include <mach/qdsp5/qdsp5audpp.h>
+#include <mach/qdsp5v2/audio_acdbi.h>
#include <mach/debug_mm.h>
#include "evlog.h"
@@ -85,19 +87,7 @@
#define AUDPP_CMD_IIR_FLAG_DIS 0x0000
#define AUDPP_CMD_IIR_FLAG_ENA -1
-#define AUDPP_CMD_VOLUME_PAN 0
-#define AUDPP_CMD_IIR_TUNING_FILTER 1
-#define AUDPP_CMD_EQUALIZER 2
-#define AUDPP_CMD_ADRC 3
-#define AUDPP_CMD_SPECTROGRAM 4
-#define AUDPP_CMD_QCONCERT 5
-#define AUDPP_CMD_SIDECHAIN_TUNING_FILTER 6
-#define AUDPP_CMD_SAMPLING_FREQUENCY 7
-#define AUDPP_CMD_QAFX 8
-#define AUDPP_CMD_QRUMBLE 9
-#define AUDPP_CMD_MBADRC 10
-
-#define MAX_EVENT_CALLBACK_CLIENTS 1
+#define MAX_EVENT_CALLBACK_CLIENTS 2
#define AUDPP_CONCURRENCY_DEFAULT 6 /* All non tunnel mode */
#define AUDPP_MAX_DECODER_CNT 5
@@ -335,6 +325,11 @@
case ADSP_MESSAGE_ID:
MM_DBG("Received ADSP event: module enable/disable(audpptask)");
break;
+ case AUDPP_MSG_FEAT_QUERY_DM_DONE:
+ MM_INFO(" RTC ACK --> %x %x %x\n", msg[0],\
+ msg[1], msg[2]);
+ acdb_rtc_set_err(msg[2]);
+ break;
default:
MM_ERR("unhandled msg id %x\n", id);
}
diff --git a/arch/arm/mach-msm/qdsp5/audpreproc.c b/arch/arm/mach-msm/qdsp5/audpreproc.c
index 230429f..92e54f8 100644
--- a/arch/arm/mach-msm/qdsp5/audpreproc.c
+++ b/arch/arm/mach-msm/qdsp5/audpreproc.c
@@ -1,7 +1,7 @@
/*
* Common code to deal with the AUDPREPROC dsp task (audio preprocessing)
*
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* Based on the audpp layer in arch/arm/mach-msm/qdsp5/audpp.c
*
@@ -23,6 +23,8 @@
#include <mach/debug_mm.h>
#include <mach/qdsp5/qdsp5audpreproc.h>
#include <mach/qdsp5/qdsp5audreccmdi.h>
+#include <mach/qdsp5v2/audio_acdbi.h>
+
static DEFINE_MUTEX(audpreproc_lock);
@@ -56,6 +58,9 @@
(1<<AUDREC_CMD_TYPE_0_INDEX_QCELP))
#endif
+#define MAX_ENC_COUNT 2
+#define MAX_EVENT_CALLBACK_CLIENTS 2
+
struct msm_adspenc_database {
unsigned num_enc;
struct msm_adspenc_info *enc_info_list;
@@ -90,15 +95,237 @@
struct audpreproc_state {
struct msm_adsp_module *mod;
+ audpreproc_event_func func[MAX_ENC_COUNT];
+ void *private[MAX_ENC_COUNT];
struct mutex *lock;
unsigned open_count;
unsigned enc_inuse;
+ struct audpreproc_event_callback *cb_tbl[MAX_EVENT_CALLBACK_CLIENTS];
};
+static struct audrec_session_info session_info;
+
static struct audpreproc_state the_audpreproc_state = {
.lock = &audpreproc_lock,
};
+/* DSP preproc event handler */
+static void audpreproc_dsp_event(void *data, unsigned id, size_t len,
+ void (*getevent)(void *ptr, size_t len))
+{
+ struct audpreproc_state *audpreproc = data;
+ uint16_t msg[2];
+ MM_ERR("audpreproc_dsp_event %id", id);
+
+ getevent(msg, sizeof(msg));
+
+ switch (id) {
+ case AUDPREPROC_MSG_CMD_CFG_DONE_MSG:
+ MM_DBG("type %d, status_flag %d\n", msg[0], msg[1]);
+ if (audpreproc->func[0])
+ audpreproc->func[0](
+ audpreproc->private[0], id,
+ &msg);
+ break;
+ case AUDPREPROC_MSG_ERROR_MSG_ID:
+ MM_INFO("err_index %d\n", msg[0]);
+ if (audpreproc->func[0])
+ audpreproc->func[0](
+ audpreproc->private[0], id,
+ &msg);
+ break;
+ case ADSP_MESSAGE_ID:
+ MM_DBG("Received ADSP event: module enable(audpreproctask)\n");
+ if (audpreproc->func[0])
+ audpreproc->func[0](
+ audpreproc->private[0], id,
+ &msg);
+ break;
+ case AUDPREPROC_MSG_FEAT_QUERY_DM_DONE:
+ {
+ uint16_t msg[3];
+ getevent(msg, sizeof(msg));
+ MM_INFO("RTC ACK --> %x %x %x\n", msg[0], msg[1], msg[2]);
+ acdb_rtc_set_err(msg[2]);
+ }
+ break;
+ default:
+ MM_ERR("unknown event %d\n", id);
+ }
+ return;
+}
+
+static struct msm_adsp_ops adsp_ops = {
+ .event = audpreproc_dsp_event,
+};
+
+/* EXPORTED API's */
+int audpreproc_enable(int enc_id, audpreproc_event_func func, void *private)
+{
+ struct audpreproc_state *audpreproc = &the_audpreproc_state;
+ int res = 0;
+ uint16_t msg[2];
+ int n = 0;
+ MM_DBG("audpreproc_enable %d\n", enc_id);
+
+ if (enc_id < 0 || enc_id > (MAX_ENC_COUNT - 1))
+ return -EINVAL;
+
+ mutex_lock(audpreproc->lock);
+ if (audpreproc->func[enc_id]) {
+ res = -EBUSY;
+ goto out;
+ }
+
+ audpreproc->func[enc_id] = func;
+ audpreproc->private[enc_id] = private;
+
+ /* First client to enable preproc task */
+ if (audpreproc->open_count++ == 0) {
+ MM_DBG("Get AUDPREPROCTASK\n");
+ res = msm_adsp_get("AUDPREPROCTASK", &audpreproc->mod,
+ &adsp_ops, audpreproc);
+ if (res < 0) {
+ MM_ERR("Can not get AUDPREPROCTASK\n");
+ audpreproc->open_count = 0;
+ audpreproc->func[enc_id] = NULL;
+ audpreproc->private[enc_id] = NULL;
+ goto out;
+ }
+ if (msm_adsp_enable(audpreproc->mod)) {
+ audpreproc->open_count = 0;
+ audpreproc->func[enc_id] = NULL;
+ audpreproc->private[enc_id] = NULL;
+ msm_adsp_put(audpreproc->mod);
+ audpreproc->mod = NULL;
+ res = -ENODEV;
+ goto out;
+ }
+ }
+ msg[0] = AUDPREPROC_MSG_STATUS_FLAG_ENA;
+ /* Generate audpre enabled message for registered clients */
+ for (n = 0; n < MAX_EVENT_CALLBACK_CLIENTS; ++n) {
+ if (audpreproc->cb_tbl[n] &&
+ audpreproc->cb_tbl[n]->fn) {
+ audpreproc->cb_tbl[n]->fn( \
+ audpreproc->cb_tbl[n]->private,\
+ AUDPREPROC_MSG_CMD_CFG_DONE_MSG,
+ (void *) &msg);
+ }
+ }
+ res = 0;
+out:
+ mutex_unlock(audpreproc->lock);
+ return res;
+}
+EXPORT_SYMBOL(audpreproc_enable);
+
+
+void audpreproc_disable(int enc_id, void *private)
+{
+ struct audpreproc_state *audpreproc = &the_audpreproc_state;
+ uint16_t msg[2];
+ int n = 0;
+
+ if (enc_id < 0 || enc_id > (MAX_ENC_COUNT - 1))
+ return;
+
+ mutex_lock(audpreproc->lock);
+ if (!audpreproc->func[enc_id])
+ goto out;
+ if (audpreproc->private[enc_id] != private)
+ goto out;
+
+ audpreproc->func[enc_id] = NULL;
+ audpreproc->private[enc_id] = NULL;
+
+ /* Last client then disable preproc task */
+ if (--audpreproc->open_count == 0) {
+ msm_adsp_disable(audpreproc->mod);
+ MM_DBG("Put AUDPREPROCTASK\n");
+ msm_adsp_put(audpreproc->mod);
+ audpreproc->mod = NULL;
+ }
+ msg[0] = AUDPREPROC_MSG_STATUS_FLAG_DIS;
+ /* Generate audpre enabled message for registered clients */
+ for (n = 0; n < MAX_EVENT_CALLBACK_CLIENTS; ++n) {
+ if (audpreproc->cb_tbl[n] &&
+ audpreproc->cb_tbl[n]->fn) {
+ audpreproc->cb_tbl[n]->fn( \
+ audpreproc->cb_tbl[n]->private,\
+ AUDPREPROC_MSG_CMD_CFG_DONE_MSG,
+ (void *) &msg);
+ }
+ }
+out:
+ mutex_unlock(audpreproc->lock);
+ return;
+}
+EXPORT_SYMBOL(audpreproc_disable);
+
+int audpreproc_update_audrec_info(
+ struct audrec_session_info *audrec_session_info)
+{
+ if (!audrec_session_info) {
+ MM_ERR("error in audrec session info address\n");
+ return -EINVAL;
+ }
+ if (audrec_session_info->session_id < MAX_ENC_COUNT) {
+ memcpy(&session_info,
+ audrec_session_info,
+ sizeof(struct audrec_session_info));
+ return 0;
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(audpreproc_update_audrec_info);
+
+int get_audrec_session_info(struct audrec_session_info *info)
+{
+ if (!info) {
+ MM_ERR("error in audrec session info address\n");
+ return -EINVAL;
+ }
+
+ if (the_audpreproc_state.open_count == 0) {
+ MM_ERR("No aud pre session active\n");
+ return -EINVAL;
+ }
+
+ memcpy(info, &session_info, sizeof(struct audrec_session_info));
+
+ return 0;
+}
+EXPORT_SYMBOL(get_audrec_session_info);
+
+int audpreproc_register_event_callback(struct audpreproc_event_callback *ecb)
+{
+ struct audpreproc_state *audpreproc = &the_audpreproc_state;
+ int i;
+
+ for (i = 0; i < MAX_EVENT_CALLBACK_CLIENTS; ++i) {
+ if (NULL == audpreproc->cb_tbl[i]) {
+ audpreproc->cb_tbl[i] = ecb;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(audpreproc_register_event_callback);
+
+int audpreproc_unregister_event_callback(struct audpreproc_event_callback *ecb)
+{
+ struct audpreproc_state *audpreproc = &the_audpreproc_state;
+ int i;
+
+ for (i = 0; i < MAX_EVENT_CALLBACK_CLIENTS; ++i) {
+ if (ecb == audpreproc->cb_tbl[i]) {
+ audpreproc->cb_tbl[i] = NULL;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
/* enc_type = supported encode format *
* like pcm, aac, sbc, evrc, qcelp, amrnb etc ... *
*/
@@ -167,3 +394,37 @@
}
EXPORT_SYMBOL(audpreproc_aenc_free);
+
+int audpreproc_dsp_set_agc(
+ audpreproc_cmd_cfg_agc_params *agc_cfg,
+ unsigned len)
+{
+ return msm_adsp_write(the_audpreproc_state.mod,
+ QDSP_uPAudPreProcCmdQueue, agc_cfg, len);
+}
+EXPORT_SYMBOL(audpreproc_dsp_set_agc);
+
+int audpreproc_dsp_set_ns(
+ audpreproc_cmd_cfg_ns_params *ns_cfg,
+ unsigned len)
+{
+ return msm_adsp_write(the_audpreproc_state.mod,
+ QDSP_uPAudPreProcCmdQueue, ns_cfg, len);
+}
+EXPORT_SYMBOL(audpreproc_dsp_set_ns);
+
+int audpreproc_dsp_set_iir(
+ audpreproc_cmd_cfg_iir_tuning_filter_params *iir_cfg,
+ unsigned len)
+{
+ return msm_adsp_write(the_audpreproc_state.mod,
+ QDSP_uPAudPreProcCmdQueue, iir_cfg, len);
+}
+EXPORT_SYMBOL(audpreproc_dsp_set_iir);
+
+int audpreproc_send_preproccmdqueue(void *cmd, unsigned len)
+{
+ return msm_adsp_write(the_audpreproc_state.mod,
+ QDSP_uPAudPreProcCmdQueue, cmd, len);
+}
+EXPORT_SYMBOL(audpreproc_send_preproccmdqueue);
diff --git a/arch/arm/mach-msm/qdsp5/audrec.c b/arch/arm/mach-msm/qdsp5/audrec.c
index d5cb168..e238e32 100644
--- a/arch/arm/mach-msm/qdsp5/audrec.c
+++ b/arch/arm/mach-msm/qdsp5/audrec.c
@@ -2,7 +2,7 @@
*
* common code to deal with the AUDREC dsp task (audio recording)
*
- * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009,2012 Code Aurora Forum. All rights reserved.
*
* Based on the audpp layer in arch/arm/mach-msm/qdsp5/audpp.c
*
@@ -34,6 +34,7 @@
#include <mach/qdsp5/qdsp5audreccmdi.h>
#include <mach/qdsp5/qdsp5audrecmsg.h>
+#include <mach/qdsp5/qdsp5audpreproc.h>
#include "audmgr.h"
#include <mach/debug_mm.h>
diff --git a/arch/arm/mach-msm/qdsp5/snd_cad.c b/arch/arm/mach-msm/qdsp5/snd_cad.c
new file mode 100644
index 0000000..c0efa3b
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp5/snd_cad.c
@@ -0,0 +1,607 @@
+/* arch/arm/mach-msm/qdsp5/snd_cad.c
+ *
+ * interface to "snd" service on the baseband cpu
+ * This code also borrows from snd.c, which is
+ * Copyright (C) 2008 HTC Corporation
+ * Copyright (c) 2009, 2012 Code Aurora Forum. 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/kthread.h>
+#include <linux/delay.h>
+#include <linux/msm_audio.h>
+#include <linux/seq_file.h>
+#include <asm/atomic.h>
+#include <asm/ioctls.h>
+#include <mach/board.h>
+#include <mach/msm_rpcrouter.h>
+#include <mach/debug_mm.h>
+#include <linux/debugfs.h>
+
+struct snd_cad_ctxt {
+ struct mutex lock;
+ int opened;
+ struct msm_rpc_endpoint *ept;
+ struct msm_cad_endpoints *cad_epts;
+};
+
+struct snd_cad_sys_ctxt {
+ struct mutex lock;
+ struct msm_rpc_endpoint *ept;
+};
+
+struct snd_curr_dev_info {
+ int rx_dev;
+ int tx_dev;
+};
+
+static struct snd_cad_sys_ctxt the_snd_cad_sys;
+
+static struct snd_cad_ctxt the_snd;
+static struct snd_curr_dev_info curr_dev;
+
+#define RPC_SND_PROG 0x30000002
+#define RPC_SND_CB_PROG 0x31000002
+
+#define RPC_SND_VERS 0x00030003
+
+#define SND_CAD_SET_DEVICE_PROC 40
+#define SND_CAD_SET_VOLUME_PROC 39
+#define MAX_SND_ACTIVE_DEVICE 2
+
+struct rpc_cad_set_device_args {
+ struct cad_devices_type device;
+ uint32_t ear_mute;
+ uint32_t mic_mute;
+
+ uint32_t cb_func;
+ uint32_t client_data;
+};
+
+struct rpc_cad_set_volume_args {
+ struct cad_devices_type device;
+ uint32_t method;
+ uint32_t volume;
+
+ uint32_t cb_func;
+ uint32_t client_data;
+};
+
+struct snd_cad_set_device_msg {
+ struct rpc_request_hdr hdr;
+ struct rpc_cad_set_device_args args;
+};
+
+struct snd_cad_set_volume_msg {
+ struct rpc_request_hdr hdr;
+ struct rpc_cad_set_volume_args args;
+};
+
+struct cad_endpoint *get_cad_endpoints(int *size);
+
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *dentry;
+
+static int rtc_getdevice_dbg_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ MM_INFO("debug intf %s\n", (char *) file->private_data);
+ return 0;
+}
+
+static ssize_t rtc_getdevice_dbg_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int n = 0;
+ static char *buffer;
+ static char *swap_buf;
+ const int debug_bufmax = 1024;
+ int swap_count = 0;
+ int rc = 0;
+ int dev_count = 0;
+ int dev_id = 0;
+ struct msm_cad_endpoints *msm_cad_epts = the_snd.cad_epts;
+ struct cad_endpoint *cad_epts;
+
+ buffer = kmalloc(sizeof(char) * 1024, GFP_KERNEL);
+ if (buffer == NULL) {
+ MM_ERR("Memory allocation failed for buffer failed\n");
+ return -EFAULT;
+ }
+
+ swap_buf = kmalloc(sizeof(char) * 1024, GFP_KERNEL);
+ if (swap_buf == NULL) {
+ MM_ERR("Memory allocation failed for swap buffer failed\n");
+ kfree(buffer);
+ return -EFAULT;
+ }
+
+ if (msm_cad_epts->num <= 0) {
+ dev_count = 0;
+ n = scnprintf(buffer, debug_bufmax, "DEV_NO:0x%x\n",
+ msm_cad_epts->num);
+ } else {
+ for (dev_id = 0; dev_id < msm_cad_epts->num; dev_id++) {
+ cad_epts = &msm_cad_epts->endpoints[dev_id];
+ if (IS_ERR(cad_epts)) {
+ MM_ERR("invalid snd endpoint for dev_id %d\n",
+ dev_id);
+ rc = PTR_ERR(cad_epts);
+ continue;
+ }
+
+ if ((cad_epts->id != curr_dev.tx_dev) &&
+ (cad_epts->id != curr_dev.rx_dev))
+ continue;
+
+ n += scnprintf(swap_buf + n, debug_bufmax - n,
+ "ACDB_ID:0x%x;CAPB:0x%x\n",
+ cad_epts->id,
+ cad_epts->capability);
+ dev_count++;
+ MM_DBG("RTC Get Device %x Capb %x Dev Count %x\n",
+ dev_id, cad_epts->capability,
+ dev_count);
+
+ }
+ }
+ swap_count = scnprintf(buffer, debug_bufmax, \
+ "DEV_NO:0x%x\n", dev_count);
+
+ memcpy(buffer+swap_count, swap_buf, n*sizeof(char));
+ n = n+swap_count;
+
+ buffer[n] = 0;
+ rc = simple_read_from_buffer(buf, count, ppos, buffer, n);
+ kfree(buffer);
+ kfree(swap_buf);
+ return rc;
+}
+
+static const struct file_operations rtc_acdb_debug_fops = {
+ .open = rtc_getdevice_dbg_open,
+ .read = rtc_getdevice_dbg_read
+};
+
+static int rtc_debugfs_create_entry(void)
+{
+ int rc = 0;
+ char name[sizeof "rtc_get_device"+1];
+
+ snprintf(name, sizeof name, "rtc_get_device");
+ dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
+ NULL, NULL, &rtc_acdb_debug_fops);
+ if (IS_ERR(dentry)) {
+ MM_ERR("debugfs_create_file failed\n");
+ rc = PTR_ERR(dentry);
+ }
+ return rc;
+}
+#else
+static int rtc_debugfs_create_entry()
+{
+ return 0;
+}
+#endif
+
+static inline int check_mute(int mute)
+{
+ return (mute == SND_MUTE_MUTED ||
+ mute == SND_MUTE_UNMUTED) ? 0 : -EINVAL;
+}
+
+static int get_endpoint(struct snd_cad_ctxt *snd, unsigned long arg)
+{
+ int rc = 0, index;
+ struct msm_cad_endpoint ept;
+
+ if (copy_from_user(&ept, (void __user *)arg, sizeof(ept))) {
+ MM_ERR("cad_ioctl get endpoint: invalid read pointer\n");
+ return -EFAULT;
+ }
+
+ index = ept.id;
+ if (index < 0 || index >= snd->cad_epts->num) {
+ MM_ERR("snd_ioctl get endpoint: invalid index!\n");
+ return -EINVAL;
+ }
+
+ ept.id = snd->cad_epts->endpoints[index].id;
+ strlcpy(ept.name,
+ snd->cad_epts->endpoints[index].name,
+ sizeof(ept.name));
+
+ if (copy_to_user((void __user *)arg, &ept, sizeof(ept))) {
+ MM_ERR("snd_ioctl get endpoint: invalid write pointer\n");
+ rc = -EFAULT;
+ }
+
+ return rc;
+}
+
+static long snd_cad_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct snd_cad_set_device_msg dmsg;
+ struct snd_cad_set_volume_msg vmsg;
+
+ struct msm_cad_device_config dev;
+ struct msm_cad_volume_config vol;
+ struct snd_cad_ctxt *snd = file->private_data;
+ int rc = 0;
+
+ mutex_lock(&snd->lock);
+ switch (cmd) {
+ case SND_SET_DEVICE:
+ if (copy_from_user(&dev, (void __user *) arg, sizeof(dev))) {
+ MM_ERR("set device: invalid pointer\n");
+ rc = -EFAULT;
+ break;
+ }
+
+ dmsg.args.device.rx_device = cpu_to_be32(dev.device.rx_device);
+ dmsg.args.device.tx_device = cpu_to_be32(dev.device.tx_device);
+ dmsg.args.device.pathtype = cpu_to_be32(dev.device.pathtype);
+ dmsg.args.ear_mute = cpu_to_be32(dev.ear_mute);
+ dmsg.args.mic_mute = cpu_to_be32(dev.mic_mute);
+ if (check_mute(dev.ear_mute) < 0 ||
+ check_mute(dev.mic_mute) < 0) {
+ MM_ERR("set device: invalid mute status\n");
+ rc = -EINVAL;
+ break;
+ }
+ dmsg.args.cb_func = -1;
+ dmsg.args.client_data = 0;
+ curr_dev.tx_dev = dev.device.tx_device;
+ curr_dev.rx_dev = dev.device.rx_device;
+ MM_ERR("snd_cad_set_device %d %d %d %d\n", dev.device.rx_device,
+ dev.device.tx_device, dev.ear_mute, dev.mic_mute);
+
+ rc = msm_rpc_call(snd->ept,
+ SND_CAD_SET_DEVICE_PROC,
+ &dmsg, sizeof(dmsg), 5 * HZ);
+ break;
+
+ case SND_SET_VOLUME:
+ if (copy_from_user(&vol, (void __user *) arg, sizeof(vol))) {
+ MM_ERR("set volume: invalid pointer\n");
+ rc = -EFAULT;
+ break;
+ }
+
+ vmsg.args.device.rx_device = cpu_to_be32(dev.device.rx_device);
+ vmsg.args.device.tx_device = cpu_to_be32(dev.device.tx_device);
+ vmsg.args.method = cpu_to_be32(vol.method);
+ if (vol.method != SND_METHOD_VOICE) {
+ MM_ERR("set volume: invalid method\n");
+ rc = -EINVAL;
+ break;
+ }
+
+ vmsg.args.volume = cpu_to_be32(vol.volume);
+ vmsg.args.cb_func = -1;
+ vmsg.args.client_data = 0;
+
+ MM_ERR("snd_cad_set_volume %d %d %d %d\n", vol.device.rx_device,
+ vol.device.tx_device, vol.method, vol.volume);
+
+ rc = msm_rpc_call(snd->ept,
+ SND_CAD_SET_VOLUME_PROC,
+ &vmsg, sizeof(vmsg), 5 * HZ);
+
+ break;
+
+ case SND_GET_NUM_ENDPOINTS:
+ if (copy_to_user((void __user *)arg,
+ &snd->cad_epts->num, sizeof(unsigned))) {
+ MM_ERR("get endpoint: invalid pointer\n");
+ rc = -EFAULT;
+ }
+ break;
+
+ case SND_GET_ENDPOINT:
+ rc = get_endpoint(snd, arg);
+ break;
+
+ default:
+ MM_ERR("unknown command\n");
+ rc = -EINVAL;
+ break;
+ }
+ mutex_unlock(&snd->lock);
+
+ return rc;
+}
+
+static int snd_cad_release(struct inode *inode, struct file *file)
+{
+ struct snd_cad_ctxt *snd = file->private_data;
+ int rc;
+
+ mutex_lock(&snd->lock);
+ rc = msm_rpc_close(snd->ept);
+ if (rc < 0)
+ MM_ERR("msm_rpc_close failed\n");
+ snd->ept = NULL;
+ snd->opened = 0;
+ mutex_unlock(&snd->lock);
+ return 0;
+}
+static int snd_cad_sys_release(void)
+{
+ struct snd_cad_sys_ctxt *snd_cad_sys = &the_snd_cad_sys;
+ int rc = 0;
+
+ mutex_lock(&snd_cad_sys->lock);
+ rc = msm_rpc_close(snd_cad_sys->ept);
+ if (rc < 0)
+ MM_ERR("msm_rpc_close failed\n");
+ snd_cad_sys->ept = NULL;
+ mutex_unlock(&snd_cad_sys->lock);
+ return rc;
+}
+static int snd_cad_open(struct inode *inode, struct file *file)
+{
+ struct snd_cad_ctxt *snd = &the_snd;
+ int rc = 0;
+
+ mutex_lock(&snd->lock);
+ if (snd->opened == 0) {
+ if (snd->ept == NULL) {
+ snd->ept = msm_rpc_connect_compatible(RPC_SND_PROG,
+ RPC_SND_VERS, 0);
+ if (IS_ERR(snd->ept)) {
+ rc = PTR_ERR(snd->ept);
+ snd->ept = NULL;
+ MM_ERR("cad connect failed with VERS %x\n",
+ RPC_SND_VERS);
+ goto err;
+ }
+ }
+ file->private_data = snd;
+ snd->opened = 1;
+ } else {
+ MM_ERR("snd already opened\n");
+ rc = -EBUSY;
+ }
+
+err:
+ mutex_unlock(&snd->lock);
+ return rc;
+}
+static int snd_cad_sys_open(void)
+{
+ struct snd_cad_sys_ctxt *snd_cad_sys = &the_snd_cad_sys;
+ int rc = 0;
+
+ mutex_lock(&snd_cad_sys->lock);
+ if (snd_cad_sys->ept == NULL) {
+ snd_cad_sys->ept = msm_rpc_connect_compatible(RPC_SND_PROG,
+ RPC_SND_VERS, 0);
+ if (IS_ERR(snd_cad_sys->ept)) {
+ rc = PTR_ERR(snd_cad_sys->ept);
+ snd_cad_sys->ept = NULL;
+ MM_ERR("func %s : cad connect failed with VERS %x\n",
+ __func__, RPC_SND_VERS);
+ goto err;
+ }
+ } else
+ MM_DBG("snd already opened\n");
+err:
+ mutex_unlock(&snd_cad_sys->lock);
+ return rc;
+}
+
+static const struct file_operations snd_cad_fops = {
+ .owner = THIS_MODULE,
+ .open = snd_cad_open,
+ .release = snd_cad_release,
+ .unlocked_ioctl = snd_cad_ioctl,
+};
+
+struct miscdevice snd_cad_misc = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "msm_cad",
+ .fops = &snd_cad_fops,
+};
+
+static long snd_cad_vol_enable(const char *arg)
+{
+ struct snd_cad_sys_ctxt *snd_cad_sys = &the_snd_cad_sys;
+ struct snd_cad_set_volume_msg vmsg;
+ struct msm_cad_volume_config vol;
+ int rc = 0;
+
+ rc = sscanf(arg, "%d %d %d %d", &vol.device.rx_device,
+ &vol.device.tx_device, &vol.method, &vol.volume);
+ if (rc != 4) {
+ MM_ERR("Invalid arguments. Usage: <rx_device> <tx_device>" \
+ "method> <volume>\n");
+ rc = -EINVAL;
+ return rc;
+ }
+
+ vmsg.args.device.rx_device = cpu_to_be32(vol.device.rx_device);
+ vmsg.args.device.tx_device = cpu_to_be32(vol.device.tx_device);
+ vmsg.args.method = cpu_to_be32(vol.method);
+ if (vol.method != SND_METHOD_VOICE) {
+ MM_ERR("snd_cad_ioctl set volume: invalid method\n");
+ rc = -EINVAL;
+ return rc;
+ }
+
+ vmsg.args.volume = cpu_to_be32(vol.volume);
+ vmsg.args.cb_func = -1;
+ vmsg.args.client_data = 0;
+
+ MM_DBG("snd_cad_set_volume %d %d %d %d\n", vol.device.rx_device,
+ vol.device.rx_device, vol.method, vol.volume);
+
+ rc = msm_rpc_call(snd_cad_sys->ept,
+ SND_CAD_SET_VOLUME_PROC,
+ &vmsg, sizeof(vmsg), 5 * HZ);
+ return rc;
+}
+
+static long snd_cad_dev_enable(const char *arg)
+{
+ struct snd_cad_sys_ctxt *snd_cad_sys = &the_snd_cad_sys;
+ struct snd_cad_set_device_msg dmsg;
+ struct msm_cad_device_config dev;
+ int rc = 0;
+
+
+ rc = sscanf(arg, "%d %d %d %d", &dev.device.rx_device,
+ &dev.device.tx_device, &dev.ear_mute, &dev.mic_mute);
+ if (rc != 4) {
+ MM_ERR("Invalid arguments. Usage: <rx_device> <tx_device> "\
+ "<ear_mute> <mic_mute>\n");
+ rc = -EINVAL;
+ return rc;
+ }
+ dmsg.args.device.rx_device = cpu_to_be32(dev.device.rx_device);
+ dmsg.args.device.tx_device = cpu_to_be32(dev.device.tx_device);
+ dmsg.args.device.pathtype = cpu_to_be32(CAD_DEVICE_PATH_RX_TX);
+ dmsg.args.ear_mute = cpu_to_be32(dev.ear_mute);
+ dmsg.args.mic_mute = cpu_to_be32(dev.mic_mute);
+ if (check_mute(dev.ear_mute) < 0 ||
+ check_mute(dev.mic_mute) < 0) {
+ MM_ERR("snd_cad_ioctl set device: invalid mute status\n");
+ rc = -EINVAL;
+ return rc;
+ }
+ dmsg.args.cb_func = -1;
+ dmsg.args.client_data = 0;
+ curr_dev.tx_dev = dev.device.tx_device;
+ curr_dev.rx_dev = dev.device.rx_device;
+
+ MM_INFO("snd_cad_set_device %d %d %d %d\n", dev.device.rx_device,
+ dev.device.tx_device, dev.ear_mute, dev.mic_mute);
+
+ rc = msm_rpc_call(snd_cad_sys->ept,
+ SND_CAD_SET_DEVICE_PROC,
+ &dmsg, sizeof(dmsg), 5 * HZ);
+ return rc;
+}
+
+static ssize_t snd_cad_dev_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ ssize_t status;
+ struct snd_cad_sys_ctxt *snd_cad_sys = &the_snd_cad_sys;
+ int rc = 0;
+
+ rc = snd_cad_sys_open();
+ if (rc)
+ return rc;
+
+ mutex_lock(&snd_cad_sys->lock);
+ status = snd_cad_dev_enable(buf);
+ mutex_unlock(&snd_cad_sys->lock);
+
+ rc = snd_cad_sys_release();
+ if (rc)
+ return rc;
+
+ return status ? : size;
+}
+
+static ssize_t snd_cad_vol_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ ssize_t status;
+ struct snd_cad_sys_ctxt *snd_cad_sys = &the_snd_cad_sys;
+ int rc = 0;
+
+ rc = snd_cad_sys_open();
+ if (rc)
+ return rc;
+
+ mutex_lock(&snd_cad_sys->lock);
+ status = snd_cad_vol_enable(buf);
+ mutex_unlock(&snd_cad_sys->lock);
+
+ rc = snd_cad_sys_release();
+ if (rc)
+ return rc;
+
+ return status ? : size;
+}
+
+static DEVICE_ATTR(device, S_IWUSR | S_IRUGO,
+ NULL, snd_cad_dev_store);
+
+static DEVICE_ATTR(volume, S_IWUSR | S_IRUGO,
+ NULL, snd_cad_vol_store);
+
+static int snd_cad_probe(struct platform_device *pdev)
+{
+ struct snd_cad_ctxt *snd = &the_snd;
+ struct snd_cad_sys_ctxt *snd_cad_sys = &the_snd_cad_sys;
+ int rc = 0;
+
+ mutex_init(&snd->lock);
+ mutex_init(&snd_cad_sys->lock);
+ snd_cad_sys->ept = NULL;
+ snd->cad_epts =
+ (struct msm_cad_endpoints *)pdev->dev.platform_data;
+ rc = misc_register(&snd_cad_misc);
+ if (rc)
+ return rc;
+
+ rc = device_create_file(snd_cad_misc.this_device, &dev_attr_device);
+ if (rc) {
+ misc_deregister(&snd_cad_misc);
+ return rc;
+ }
+
+ rc = device_create_file(snd_cad_misc.this_device, &dev_attr_volume);
+ if (rc) {
+ device_remove_file(snd_cad_misc.this_device,
+ &dev_attr_device);
+ misc_deregister(&snd_cad_misc);
+ }
+
+#ifdef CONFIG_DEBUG_FS
+ rc = rtc_debugfs_create_entry();
+ if (rc) {
+ device_remove_file(snd_cad_misc.this_device,
+ &dev_attr_volume);
+ device_remove_file(snd_cad_misc.this_device,
+ &dev_attr_device);
+ misc_deregister(&snd_cad_misc);
+ }
+#endif
+ return rc;
+}
+
+static struct platform_driver snd_cad_plat_driver = {
+ .probe = snd_cad_probe,
+ .driver = {
+ .name = "msm_cad",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init snd_cad_init(void)
+{
+ return platform_driver_register(&snd_cad_plat_driver);
+}
+
+module_init(snd_cad_init);
+
+MODULE_DESCRIPTION("MSM CAD SND driver");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index d70da19..8ac1fea 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -687,6 +687,7 @@
spin_lock_init(&client[i][j].svc[k].w_lock);
}
}
+ apr_set_subsys_state();
mutex_init(&q6.lock);
dsp_debug_register(adsp_state);
apr_reset_workqueue = create_singlethread_workqueue("apr_driver");
@@ -703,7 +704,6 @@
init_waitqueue_head(&modem_wait);
subsys_notif_register_notifier("modem", &mnb);
subsys_notif_register_notifier("lpass", &lnb);
- apr_set_subsys_state();
return ret;
}
late_initcall(apr_late_init);
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index 519dbb3..aac83e5 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -223,8 +223,9 @@
{
printk(KERN_NOTICE "Going down for restart now\n");
+ msm_restart_prepare(cmd);
+
if (!use_restart_v2()) {
- msm_restart_prepare(cmd);
__raw_writel(0, msm_tmr0_base + WDT0_EN);
if (!(machine_is_msm8x60_fusion() ||
machine_is_msm8x60_fusn_ffa())) {
diff --git a/arch/arm/mach-msm/rpm-regulator-8930.c b/arch/arm/mach-msm/rpm-regulator-8930.c
index 3878e22..9133856 100644
--- a/arch/arm/mach-msm/rpm-regulator-8930.c
+++ b/arch/arm/mach-msm/rpm-regulator-8930.c
@@ -111,51 +111,64 @@
};
#define LDO(_id, _name, _name_pc, _ranges, _hpm_min_load, _requires_cxo) \
- [RPM_VREG_ID_PM8038_##_id] = { \
+ [RPM_VREG_ID_PM##_id] = { \
.req = { \
- [0] = { .id = MSM_RPM_ID_PM8038_##_id##_0, }, \
- [1] = { .id = MSM_RPM_ID_PM8038_##_id##_1, }, \
+ [0] = { .id = MSM_RPM_ID_PM##_id##_0, }, \
+ [1] = { .id = MSM_RPM_ID_PM##_id##_1, }, \
}, \
.hpm_min_load = RPM_VREG_8930_##_hpm_min_load##_HPM_MIN_LOAD, \
.type = RPM_REGULATOR_TYPE_LDO, \
.set_points = &_ranges##_set_points, \
.part = &ldo_parts, \
- .id = RPM_VREG_ID_PM8038_##_id, \
+ .id = RPM_VREG_ID_PM##_id, \
.rdesc.name = _name, \
.rdesc_pc.name = _name_pc, \
.requires_cxo = _requires_cxo, \
}
#define SMPS(_id, _name, _name_pc, _ranges, _hpm_min_load) \
- [RPM_VREG_ID_PM8038_##_id] = { \
+ [RPM_VREG_ID_PM##_id] = { \
.req = { \
- [0] = { .id = MSM_RPM_ID_PM8038_##_id##_0, }, \
- [1] = { .id = MSM_RPM_ID_PM8038_##_id##_1, }, \
+ [0] = { .id = MSM_RPM_ID_PM##_id##_0, }, \
+ [1] = { .id = MSM_RPM_ID_PM##_id##_1, }, \
}, \
.hpm_min_load = RPM_VREG_8930_##_hpm_min_load##_HPM_MIN_LOAD, \
.type = RPM_REGULATOR_TYPE_SMPS, \
.set_points = &_ranges##_set_points, \
.part = &smps_parts, \
- .id = RPM_VREG_ID_PM8038_##_id, \
+ .id = RPM_VREG_ID_PM##_id, \
.rdesc.name = _name, \
.rdesc_pc.name = _name_pc, \
}
#define LVS(_id, _name, _name_pc) \
- [RPM_VREG_ID_PM8038_##_id] = { \
+ [RPM_VREG_ID_PM##_id] = { \
.req = { \
- [0] = { .id = MSM_RPM_ID_PM8038_##_id, }, \
+ [0] = { .id = MSM_RPM_ID_PM##_id, }, \
[1] = { .id = -1, }, \
}, \
.type = RPM_REGULATOR_TYPE_VS, \
.part = &switch_parts, \
- .id = RPM_VREG_ID_PM8038_##_id, \
+ .id = RPM_VREG_ID_PM##_id, \
+ .rdesc.name = _name, \
+ .rdesc_pc.name = _name_pc, \
+ }
+
+#define MVS(_vreg_id, _name, _name_pc, _rpm_id) \
+ [RPM_VREG_ID_PM##_vreg_id] = { \
+ .req = { \
+ [0] = { .id = MSM_RPM_ID_##_rpm_id, }, \
+ [1] = { .id = -1, }, \
+ }, \
+ .type = RPM_REGULATOR_TYPE_VS, \
+ .part = &switch_parts, \
+ .id = RPM_VREG_ID_PM##_vreg_id, \
.rdesc.name = _name, \
.rdesc_pc.name = _name_pc, \
}
#define CORNER(_id, _rpm_id, _name, _ranges) \
- [RPM_VREG_ID_PM8038_##_id] = { \
+ [RPM_VREG_ID_PM##_id] = { \
.req = { \
[0] = { .id = MSM_RPM_ID_##_rpm_id, }, \
[1] = { .id = -1, }, \
@@ -163,50 +176,105 @@
.type = RPM_REGULATOR_TYPE_CORNER, \
.set_points = &_ranges##_set_points, \
.part = &corner_parts, \
- .id = RPM_VREG_ID_PM8038_##_id, \
+ .id = RPM_VREG_ID_PM##_id, \
.rdesc.name = _name, \
}
-static struct vreg vregs[] = {
- LDO(L1, "8038_l1", NULL, nldo1200, LDO_1200, 1),
- LDO(L2, "8038_l2", "8038_l2_pc", nldo, LDO_150, 1),
- LDO(L3, "8038_l3", "8038_l3_pc", pldo, LDO_50, 0),
- LDO(L4, "8038_l4", "8038_l4_pc", pldo, LDO_50, 0),
- LDO(L5, "8038_l5", "8038_l5_pc", pldo, LDO_600, 0),
- LDO(L6, "8038_l6", "8038_l6_pc", pldo, LDO_600, 0),
- LDO(L7, "8038_l7", "8038_l7_pc", pldo, LDO_600, 0),
- LDO(L8, "8038_l8", "8038_l8_pc", pldo, LDO_300, 0),
- LDO(L9, "8038_l9", "8038_l9_pc", pldo, LDO_300, 0),
- LDO(L10, "8038_l10", "8038_l10_pc", pldo, LDO_600, 0),
- LDO(L11, "8038_l11", "8038_l11_pc", pldo, LDO_600, 0),
- LDO(L12, "8038_l12", "8038_l12_pc", nldo, LDO_300, 1),
- LDO(L13, "8038_l13", NULL, ln_ldo, LDO_5, 0),
- LDO(L14, "8038_l14", "8038_l14_pc", pldo, LDO_50, 0),
- LDO(L15, "8038_l15", "8038_l15_pc", pldo, LDO_150, 0),
- LDO(L16, "8038_l16", NULL, nldo1200, LDO_1200, 1),
- LDO(L17, "8038_l17", "8038_l17_pc", pldo, LDO_150, 0),
- LDO(L18, "8038_l18", "8038_l18_pc", pldo, LDO_50, 0),
- LDO(L19, "8038_l19", NULL, nldo1200, LDO_1200, 1),
- LDO(L20, "8038_l20", NULL, nldo1200, LDO_1200, 1),
- LDO(L21, "8038_l21", "8038_l21_pc", pldo, LDO_150, 0),
- LDO(L22, "8038_l22", "8038_l22_pc", pldo, LDO_50, 0),
- LDO(L23, "8038_l23", "8038_l23_pc", pldo, LDO_50, 0),
- LDO(L24, "8038_l24", NULL, nldo1200, LDO_1200, 1),
- LDO(L25, "8038_l25", NULL, ln_ldo, LDO_5, 0),
- LDO(L26, "8038_l26", "8038_l26_pc", nldo, LDO_150, 1),
- LDO(L27, "8038_l27", NULL, nldo1200, LDO_1200, 1),
+static struct vreg vregs_msm8930_pm8038[] = {
+ LDO(8038_L1, "8038_l1", NULL, nldo1200, LDO_1200, 1),
+ LDO(8038_L2, "8038_l2", "8038_l2_pc", nldo, LDO_150, 1),
+ LDO(8038_L3, "8038_l3", "8038_l3_pc", pldo, LDO_50, 0),
+ LDO(8038_L4, "8038_l4", "8038_l4_pc", pldo, LDO_50, 0),
+ LDO(8038_L5, "8038_l5", "8038_l5_pc", pldo, LDO_600, 0),
+ LDO(8038_L6, "8038_l6", "8038_l6_pc", pldo, LDO_600, 0),
+ LDO(8038_L7, "8038_l7", "8038_l7_pc", pldo, LDO_600, 0),
+ LDO(8038_L8, "8038_l8", "8038_l8_pc", pldo, LDO_300, 0),
+ LDO(8038_L9, "8038_l9", "8038_l9_pc", pldo, LDO_300, 0),
+ LDO(8038_L10, "8038_l10", "8038_l10_pc", pldo, LDO_600, 0),
+ LDO(8038_L11, "8038_l11", "8038_l11_pc", pldo, LDO_600, 0),
+ LDO(8038_L12, "8038_l12", "8038_l12_pc", nldo, LDO_300, 1),
+ LDO(8038_L13, "8038_l13", NULL, ln_ldo, LDO_5, 0),
+ LDO(8038_L14, "8038_l14", "8038_l14_pc", pldo, LDO_50, 0),
+ LDO(8038_L15, "8038_l15", "8038_l15_pc", pldo, LDO_150, 0),
+ LDO(8038_L16, "8038_l16", NULL, nldo1200, LDO_1200, 1),
+ LDO(8038_L17, "8038_l17", "8038_l17_pc", pldo, LDO_150, 0),
+ LDO(8038_L18, "8038_l18", "8038_l18_pc", pldo, LDO_50, 0),
+ LDO(8038_L19, "8038_l19", NULL, nldo1200, LDO_1200, 1),
+ LDO(8038_L20, "8038_l20", NULL, nldo1200, LDO_1200, 1),
+ LDO(8038_L21, "8038_l21", "8038_l21_pc", pldo, LDO_150, 0),
+ LDO(8038_L22, "8038_l22", "8038_l22_pc", pldo, LDO_50, 0),
+ LDO(8038_L23, "8038_l23", "8038_l23_pc", pldo, LDO_50, 0),
+ LDO(8038_L24, "8038_l24", NULL, nldo1200, LDO_1200, 1),
+ LDO(8038_L25, "8038_l25", NULL, ln_ldo, LDO_5, 0),
+ LDO(8038_L26, "8038_l26", "8038_l26_pc", nldo, LDO_150, 1),
+ LDO(8038_L27, "8038_l27", NULL, nldo1200, LDO_1200, 1),
- SMPS(S1, "8038_s1", "8038_s1_pc", smps, SMPS_1500),
- SMPS(S2, "8038_s2", "8038_s2_pc", smps, SMPS_1500),
- SMPS(S3, "8038_s3", "8038_s3_pc", smps, SMPS_1500),
- SMPS(S4, "8038_s4", "8038_s4_pc", smps, SMPS_1500),
- SMPS(S5, "8038_s5", NULL, ftsmps, SMPS_2000),
- SMPS(S6, "8038_s6", NULL, ftsmps, SMPS_2000),
+ SMPS(8038_S1, "8038_s1", "8038_s1_pc", smps, SMPS_1500),
+ SMPS(8038_S2, "8038_s2", "8038_s2_pc", smps, SMPS_1500),
+ SMPS(8038_S3, "8038_s3", "8038_s3_pc", smps, SMPS_1500),
+ SMPS(8038_S4, "8038_s4", "8038_s4_pc", smps, SMPS_1500),
+ SMPS(8038_S5, "8038_s5", NULL, ftsmps, SMPS_2000),
+ SMPS(8038_S6, "8038_s6", NULL, ftsmps, SMPS_2000),
- LVS(LVS1, "8038_lvs1", "8038_lvs1_pc"),
- LVS(LVS2, "8038_lvs2", "8038_lvs2_pc"),
+ LVS(8038_LVS1, "8038_lvs1", "8038_lvs1_pc"),
+ LVS(8038_LVS2, "8038_lvs2", "8038_lvs2_pc"),
- CORNER(VDD_DIG_CORNER, VOLTAGE_CORNER, "vdd_dig_corner", corner),
+ CORNER(8038_VDD_DIG_CORNER, VOLTAGE_CORNER, "vdd_dig_corner", corner),
+};
+
+static struct vreg vregs_msm8930_pm8917[] = {
+ LDO(8917_L1, "8917_l1", "8917_l1_pc", nldo, LDO_150, 1),
+ LDO(8917_L2, "8917_l2", "8917_l2_pc", nldo, LDO_150, 1),
+ LDO(8917_L3, "8917_l3", "8917_l3_pc", pldo, LDO_150, 0),
+ LDO(8917_L4, "8917_l4", "8917_l4_pc", pldo, LDO_50, 0),
+ LDO(8917_L5, "8917_l5", "8917_l5_pc", pldo, LDO_300, 0),
+ LDO(8917_L6, "8917_l6", "8917_l6_pc", pldo, LDO_600, 0),
+ LDO(8917_L7, "8917_l7", "8917_l7_pc", pldo, LDO_150, 0),
+ LDO(8917_L8, "8917_l8", "8917_l8_pc", pldo, LDO_300, 0),
+ LDO(8917_L9, "8917_l9", "8917_l9_pc", pldo, LDO_300, 0),
+ LDO(8917_L10, "8917_l10", "8917_l10_pc", pldo, LDO_600, 0),
+ LDO(8917_L11, "8917_l11", "8917_l11_pc", pldo, LDO_150, 0),
+ LDO(8917_L12, "8917_l12", "8917_l12_pc", nldo, LDO_150, 1),
+ LDO(8917_L14, "8917_l14", "8917_l14_pc", pldo, LDO_50, 0),
+ LDO(8917_L15, "8917_l15", "8917_l15_pc", pldo, LDO_150, 0),
+ LDO(8917_L16, "8917_l16", "8917_l16_pc", pldo, LDO_300, 0),
+ LDO(8917_L17, "8917_l17", "8917_l17_pc", pldo, LDO_150, 0),
+ LDO(8917_L18, "8917_l18", "8917_l18_pc", nldo, LDO_150, 1),
+ LDO(8917_L21, "8917_l21", "8917_l21_pc", pldo, LDO_150, 0),
+ LDO(8917_L22, "8917_l22", "8917_l22_pc", pldo, LDO_150, 0),
+ LDO(8917_L23, "8917_l23", "8917_l23_pc", pldo, LDO_150, 0),
+ LDO(8917_L24, "8917_l24", NULL, nldo1200, LDO_1200, 0),
+ LDO(8917_L25, "8917_l25", NULL, nldo1200, LDO_1200, 0),
+ LDO(8917_L26, "8917_l26", NULL, nldo1200, LDO_1200, 0),
+ LDO(8917_L27, "8917_l27", NULL, nldo1200, LDO_1200, 0),
+ LDO(8917_L28, "8917_l28", NULL, nldo1200, LDO_1200, 0),
+ LDO(8917_L29, "8917_l29", "8917_l29_pc", pldo, LDO_150, 0),
+ LDO(8917_L30, "8917_l30", "8917_l30_pc", pldo, LDO_150, 0),
+ LDO(8917_L31, "8917_l31", "8917_l31_pc", pldo, LDO_150, 0),
+ LDO(8917_L32, "8917_l32", "8917_l32_pc", pldo, LDO_150, 0),
+ LDO(8917_L33, "8917_l33", "8917_l33_pc", pldo, LDO_150, 0),
+ LDO(8917_L34, "8917_l34", "8917_l34_pc", pldo, LDO_150, 0),
+ LDO(8917_L35, "8917_l35", "8917_l35_pc", pldo, LDO_300, 0),
+ LDO(8917_L36, "8917_l36", "8917_l36_pc", pldo, LDO_50, 0),
+
+ SMPS(8917_S1, "8917_s1", "8917_s1_pc", smps, SMPS_1500),
+ SMPS(8917_S2, "8917_s2", "8917_s2_pc", smps, SMPS_1500),
+ SMPS(8917_S3, "8917_s3", "8917_s3_pc", smps, SMPS_1500),
+ SMPS(8917_S4, "8917_s4", "8917_s4_pc", smps, SMPS_1500),
+ SMPS(8917_S5, "8917_s5", NULL, ftsmps, SMPS_2000),
+ SMPS(8917_S6, "8917_s6", NULL, ftsmps, SMPS_2000),
+ SMPS(8917_S7, "8917_s7", "8917_s7_pc", smps, SMPS_1500),
+ SMPS(8917_S8, "8917_s8", "8917_s8_pc", smps, SMPS_1500),
+
+ LVS(8917_LVS1, "8917_lvs1", "8917_lvs1_pc"),
+ LVS(8917_LVS3, "8917_lvs3", "8917_lvs3_pc"),
+ LVS(8917_LVS4, "8917_lvs4", "8917_lvs4_pc"),
+ LVS(8917_LVS5, "8917_lvs5", "8917_lvs5_pc"),
+ LVS(8917_LVS6, "8917_lvs6", "8917_lvs6_pc"),
+ LVS(8917_LVS7, "8917_lvs7", "8917_lvs7_pc"),
+ MVS(8917_USB_OTG, "8917_usb_otg", NULL, USB_OTG_SWITCH),
+
+ CORNER(8917_VDD_DIG_CORNER, VOLTAGE_CORNER, "vdd_dig_corner", corner),
};
static const char *pin_func_label[] = {
@@ -237,17 +305,18 @@
" A2",
};
-static int is_real_id(int id)
+static int is_real_id_msm8930_pm8038(int id)
{
return (id >= 0) && (id <= RPM_VREG_ID_PM8038_MAX_REAL);
}
-static int pc_id_to_real_id(int id)
+static int pc_id_to_real_id_msm8930_pm8038(int id)
{
int real_id = 0;
if (id >= RPM_VREG_ID_PM8038_L2_PC && id <= RPM_VREG_ID_PM8038_L12_PC)
- real_id = id - RPM_VREG_ID_PM8038_L2_PC;
+ real_id = id - RPM_VREG_ID_PM8038_L2_PC
+ + RPM_VREG_ID_PM8038_L2;
else if (id >= RPM_VREG_ID_PM8038_L14_PC
&& id <= RPM_VREG_ID_PM8038_L15_PC)
real_id = id - RPM_VREG_ID_PM8038_L14_PC
@@ -274,9 +343,33 @@
return real_id;
}
-static struct vreg_config config = {
- .vregs = vregs,
- .vregs_len = ARRAY_SIZE(vregs),
+static int is_real_id_msm8930_pm8917(int id)
+{
+ return (id >= 0) && (id <= RPM_VREG_ID_PM8917_MAX_REAL);
+}
+
+static int pc_id_to_real_id_msm8930_pm8917(int id)
+{
+ int real_id = 0;
+
+ if (id >= RPM_VREG_ID_PM8917_L1_PC && id <= RPM_VREG_ID_PM8917_L23_PC)
+ real_id = id - RPM_VREG_ID_PM8917_L1_PC
+ + RPM_VREG_ID_PM8917_L1;
+ else if (id >= RPM_VREG_ID_PM8917_L29_PC
+ && id <= RPM_VREG_ID_PM8917_S4_PC)
+ real_id = id - RPM_VREG_ID_PM8917_L29_PC
+ + RPM_VREG_ID_PM8917_L29;
+ else if (id >= RPM_VREG_ID_PM8917_S7_PC
+ && id <= RPM_VREG_ID_PM8917_LVS7_PC)
+ real_id = id - RPM_VREG_ID_PM8917_S7_PC
+ + RPM_VREG_ID_PM8917_S7;
+
+ return real_id;
+}
+
+static struct vreg_config config_msm8930_pm8038 = {
+ .vregs = vregs_msm8930_pm8038,
+ .vregs_len = ARRAY_SIZE(vregs_msm8930_pm8038),
.vreg_id_min = RPM_VREG_ID_PM8038_L1,
.vreg_id_max = RPM_VREG_ID_PM8038_MAX,
@@ -299,11 +392,45 @@
.label_power_mode = power_mode_label,
.label_power_mode_len = ARRAY_SIZE(power_mode_label),
- .is_real_id = is_real_id,
- .pc_id_to_real_id = pc_id_to_real_id,
+ .is_real_id = is_real_id_msm8930_pm8038,
+ .pc_id_to_real_id = pc_id_to_real_id_msm8930_pm8038,
+};
+
+static struct vreg_config config_msm8930_pm8917 = {
+ .vregs = vregs_msm8930_pm8917,
+ .vregs_len = ARRAY_SIZE(vregs_msm8930_pm8917),
+
+ .vreg_id_min = RPM_VREG_ID_PM8917_L1,
+ .vreg_id_max = RPM_VREG_ID_PM8917_MAX,
+
+ .pin_func_none = RPM_VREG_PIN_FN_8930_NONE,
+ .pin_func_sleep_b = RPM_VREG_PIN_FN_8930_SLEEP_B,
+
+ .mode_lpm = REGULATOR_MODE_IDLE,
+ .mode_hpm = REGULATOR_MODE_NORMAL,
+
+ .set_points = all_set_points,
+ .set_points_len = ARRAY_SIZE(all_set_points),
+
+ .label_pin_ctrl = pin_control_label,
+ .label_pin_ctrl_len = ARRAY_SIZE(pin_control_label),
+ .label_pin_func = pin_func_label,
+ .label_pin_func_len = ARRAY_SIZE(pin_func_label),
+ .label_force_mode = force_mode_label,
+ .label_force_mode_len = ARRAY_SIZE(force_mode_label),
+ .label_power_mode = power_mode_label,
+ .label_power_mode_len = ARRAY_SIZE(power_mode_label),
+
+ .is_real_id = is_real_id_msm8930_pm8917,
+ .pc_id_to_real_id = pc_id_to_real_id_msm8930_pm8917,
};
struct vreg_config *get_config_8930(void)
{
- return &config;
+ return &config_msm8930_pm8038;
+}
+
+struct vreg_config *get_config_8930_pm8917(void)
+{
+ return &config_msm8930_pm8917;
}
diff --git a/arch/arm/mach-msm/rpm-regulator-private.h b/arch/arm/mach-msm/rpm-regulator-private.h
index c3ddc33..d55bd73 100644
--- a/arch/arm/mach-msm/rpm-regulator-private.h
+++ b/arch/arm/mach-msm/rpm-regulator-private.h
@@ -176,11 +176,16 @@
#if defined(CONFIG_MSM_RPM_REGULATOR) && defined(CONFIG_ARCH_MSM8930)
struct vreg_config *get_config_8930(void);
+struct vreg_config *get_config_8930_pm8917(void);
#else
static inline struct vreg_config *get_config_8930(void)
{
return NULL;
}
+static inline struct vreg_config *get_config_8930_pm8917(void)
+{
+ return NULL;
+}
#endif
#endif
diff --git a/arch/arm/mach-msm/rpm-regulator.c b/arch/arm/mach-msm/rpm-regulator.c
index 68ff55b..424a4fe 100644
--- a/arch/arm/mach-msm/rpm-regulator.c
+++ b/arch/arm/mach-msm/rpm-regulator.c
@@ -62,6 +62,7 @@
[RPM_VREG_VERSION_8960] = get_config_8960,
[RPM_VREG_VERSION_9615] = get_config_9615,
[RPM_VREG_VERSION_8930] = get_config_8930,
+ [RPM_VREG_VERSION_8930_PM8917] = get_config_8930_pm8917,
};
static struct rpm_regulator_consumer_mapping *consumer_map;
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index 1225fec..cd5556a 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -62,7 +62,7 @@
#define DEFAULT_BUFFER_SIZE 256
#define GFP_FLAG(noirq) (noirq ? GFP_ATOMIC : GFP_KERNEL)
-#define INV_HDR "resource does not exist"
+#define INV_RSC "resource does not exist"
#define ERR "err\0"
#define MAX_ERR_BUFFER_SIZE 128
#define INIT_ERROR 1
@@ -172,8 +172,10 @@
int i;
int data_size, msg_size;
- if (!handle)
+ if (!handle) {
+ pr_err("%s(): Invalid handle\n", __func__);
return -EINVAL;
+ }
data_size = ALIGN(size, SZ_4);
msg_size = data_size + sizeof(struct rpm_request_header);
@@ -191,8 +193,11 @@
break;
}
- if (i >= handle->num_elements)
+ if (i >= handle->num_elements) {
+ pr_err("%s(): Number of resources exceeds max allocated\n",
+ __func__);
return -ENOMEM;
+ }
if (i == handle->write_idx)
handle->write_idx++;
@@ -200,8 +205,10 @@
if (!handle->kvp[i].value) {
handle->kvp[i].value = kzalloc(data_size, GFP_FLAG(noirq));
- if (!handle->kvp[i].value)
+ if (!handle->kvp[i].value) {
+ pr_err("%s(): Failed malloc\n", __func__);
return -ENOMEM;
+ }
} else {
/* We enter the else case, if a key already exists but the
* data doesn't match. In which case, we should zero the data
@@ -366,13 +373,20 @@
return elem;
}
-static int msm_rpm_get_next_msg_id(void)
+static uint32_t msm_rpm_get_next_msg_id(void)
{
- int id;
+ uint32_t id;
+
+ /*
+ * A message id of 0 is used by the driver to indicate a error
+ * condition. The RPM driver uses a id of 1 to indicate unsent data
+ * when the data sent over hasn't been modified. This isn't a error
+ * scenario and wait for ack returns a success when the message id is 1.
+ */
do {
id = atomic_inc_return(&msm_rpm_msg_id);
- } while ((id == 0) || msm_rpm_get_entry_from_msg_id(id));
+ } while ((id == 0) || (id == 1) || msm_rpm_get_entry_from_msg_id(id));
return id;
}
@@ -459,8 +473,12 @@
tmp += 2 * sizeof(uint32_t);
- if (!(memcmp(tmp, INV_HDR, min(req_len, sizeof(INV_HDR))-1)))
+ if (!(memcmp(tmp, INV_RSC, min(req_len, sizeof(INV_RSC))-1))) {
+ pr_err("%s(): RPM NACK Unsupported resource\n", __func__);
rc = -EINVAL;
+ } else {
+ pr_err("%s(): RPM NACK Invalid header\n", __func__);
+ }
return rc;
}
@@ -658,7 +676,8 @@
int req_hdr_sz, msg_hdr_sz;
if (!cdata->msg_hdr.data_len)
- return 0;
+ return 1;
+
req_hdr_sz = sizeof(cdata->req_hdr);
msg_hdr_sz = sizeof(cdata->msg_hdr);
@@ -676,8 +695,10 @@
cdata->buf = kzalloc(msg_size, GFP_FLAG(noirq));
}
- if (!cdata->buf)
+ if (!cdata->buf) {
+ pr_err("%s(): Failed malloc\n", __func__);
return 0;
+ }
tmpbuff = cdata->buf;
@@ -722,7 +743,7 @@
ret = smd_write_avail(msm_rpm_data.ch_info);
if (ret < 0) {
- pr_warn("%s(): SMD not initialized\n", __func__);
+ pr_err("%s(): SMD not initialized\n", __func__);
spin_unlock_irqrestore(&msm_rpm_data.smd_lock_write, flags);
return 0;
}
@@ -749,7 +770,7 @@
} else if (ret < msg_size) {
struct msm_rpm_wait_data *rc;
ret = 0;
- pr_info("Failed to write data msg_size:%d ret:%d\n",
+ pr_err("Failed to write data msg_size:%d ret:%d\n",
msg_size, ret);
rc = msm_rpm_get_entry_from_msg_id(cdata->msg_hdr.msg_id);
if (rc)
@@ -773,10 +794,14 @@
int msm_rpm_wait_for_ack(uint32_t msg_id)
{
struct msm_rpm_wait_data *elem;
- int rc = 0;
- if (!msg_id)
- return -EINVAL;
+ if (!msg_id) {
+ pr_err("%s(): Invalid msg id\n", __func__);
+ return -ENOMEM;
+ }
+
+ if (msg_id == 1)
+ return 0;
if (standalone)
return 0;
@@ -785,15 +810,9 @@
if (!elem)
return 0;
- rc = wait_for_completion_timeout(&elem->ack, msecs_to_jiffies(1));
- if (!rc) {
- pr_warn("%s(): Timed out after 1 ms\n", __func__);
- rc = -ETIMEDOUT;
- } else {
- rc = elem->errno;
- msm_rpm_free_list_entry(elem);
- }
- return rc;
+ wait_for_completion(&elem->ack);
+ msm_rpm_free_list_entry(elem);
+ return elem->errno;
}
EXPORT_SYMBOL(msm_rpm_wait_for_ack);
@@ -805,8 +824,13 @@
uint32_t id = 0;
int count = 0;
- if (!msg_id)
- return -EINVAL;
+ if (!msg_id) {
+ pr_err("%s(): Invalid msg id\n", __func__);
+ return -ENOMEM;
+ }
+
+ if (msg_id == 1)
+ return 0;
if (standalone)
return 0;
@@ -964,10 +988,7 @@
complete(&msm_rpm_data.smd_open);
}
- ret = wait_for_completion_timeout(&msm_rpm_data.smd_open,
- msecs_to_jiffies(5));
-
- BUG_ON(!ret);
+ wait_for_completion(&msm_rpm_data.smd_open);
smd_disable_read_intr(msm_rpm_data.ch_info);
diff --git a/arch/arm/mach-msm/scm-boot.c b/arch/arm/mach-msm/scm-boot.c
index e377633..01d0853 100644
--- a/arch/arm/mach-msm/scm-boot.c
+++ b/arch/arm/mach-msm/scm-boot.c
@@ -19,11 +19,11 @@
/*
* Set the cold/warm boot address for one of the CPU cores.
*/
-int scm_set_boot_addr(void *addr, int flags)
+int scm_set_boot_addr(phys_addr_t addr, unsigned int flags)
{
struct {
unsigned int flags;
- void *addr;
+ unsigned long addr;
} cmd;
cmd.addr = addr;
diff --git a/arch/arm/mach-msm/scm-boot.h b/arch/arm/mach-msm/scm-boot.h
index 221ffca..0d0e6aa 100644
--- a/arch/arm/mach-msm/scm-boot.h
+++ b/arch/arm/mach-msm/scm-boot.h
@@ -22,9 +22,12 @@
#define SCM_FLAG_WARMBOOT_CPU3 0x40
#ifdef CONFIG_MSM_SCM
-int scm_set_boot_addr(void *addr, int flags);
+int scm_set_boot_addr(phys_addr_t addr, unsigned int flags);
#else
-static inline int scm_set_boot_addr(void *addr, int flags) { return 0; }
+static inline int scm_set_boot_addr(phys_addr_t addr, unsigned int flags)
+{
+ return 0;
+}
#endif
#endif
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index e82e44b..eeac2b9 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -361,9 +361,15 @@
static DEFINE_MUTEX(smsm_lock);
static struct smsm_state_info *smsm_states;
static int spinlocks_initialized;
-static RAW_NOTIFIER_HEAD(smsm_driver_state_notifier_list);
-static DEFINE_MUTEX(smsm_driver_state_notifier_lock);
-static void smsm_driver_state_notify(uint32_t state, void *data);
+
+/**
+ * Variables to indicate smd module initialization.
+ * Dependents to register for smd module init notifier.
+ */
+static int smd_module_inited;
+static RAW_NOTIFIER_HEAD(smd_module_init_notifier_list);
+static DEFINE_MUTEX(smd_module_init_notifier_lock);
+static void smd_module_init_notify(uint32_t state, void *data);
static inline void smd_write_intr(unsigned int val,
const void __iomem *addr)
@@ -2465,13 +2471,6 @@
int i;
struct smsm_size_info_type *smsm_size_info;
- i = remote_spin_lock_init(&remote_spinlock, SMEM_SPINLOCK_SMEM_ALLOC);
- if (i) {
- pr_err("%s: remote spinlock init failed %d\n", __func__, i);
- return i;
- }
- spinlocks_initialized = 1;
-
smsm_size_info = smem_alloc(SMEM_SMSM_SIZE_INFO,
sizeof(struct smsm_size_info_type));
if (smsm_size_info) {
@@ -2530,7 +2529,6 @@
return i;
wmb();
- smsm_driver_state_notify(SMSM_INIT, NULL);
return 0;
}
@@ -3104,37 +3102,40 @@
}
EXPORT_SYMBOL(smsm_state_cb_deregister);
-int smsm_driver_state_notifier_register(struct notifier_block *nb)
+int smd_module_init_notifier_register(struct notifier_block *nb)
{
int ret;
if (!nb)
return -EINVAL;
- mutex_lock(&smsm_driver_state_notifier_lock);
- ret = raw_notifier_chain_register(&smsm_driver_state_notifier_list, nb);
- mutex_unlock(&smsm_driver_state_notifier_lock);
+ mutex_lock(&smd_module_init_notifier_lock);
+ ret = raw_notifier_chain_register(&smd_module_init_notifier_list, nb);
+ if (smd_module_inited)
+ nb->notifier_call(nb, 0, NULL);
+ mutex_unlock(&smd_module_init_notifier_lock);
return ret;
}
-EXPORT_SYMBOL(smsm_driver_state_notifier_register);
+EXPORT_SYMBOL(smd_module_init_notifier_register);
-int smsm_driver_state_notifier_unregister(struct notifier_block *nb)
+int smd_module_init_notifier_unregister(struct notifier_block *nb)
{
int ret;
if (!nb)
return -EINVAL;
- mutex_lock(&smsm_driver_state_notifier_lock);
- ret = raw_notifier_chain_unregister(&smsm_driver_state_notifier_list,
+ mutex_lock(&smd_module_init_notifier_lock);
+ ret = raw_notifier_chain_unregister(&smd_module_init_notifier_list,
nb);
- mutex_unlock(&smsm_driver_state_notifier_lock);
+ mutex_unlock(&smd_module_init_notifier_lock);
return ret;
}
-EXPORT_SYMBOL(smsm_driver_state_notifier_unregister);
+EXPORT_SYMBOL(smd_module_init_notifier_unregister);
-static void smsm_driver_state_notify(uint32_t state, void *data)
+static void smd_module_init_notify(uint32_t state, void *data)
{
- mutex_lock(&smsm_driver_state_notifier_lock);
- raw_notifier_call_chain(&smsm_driver_state_notifier_list,
+ mutex_lock(&smd_module_init_notifier_lock);
+ smd_module_inited = 1;
+ raw_notifier_call_chain(&smd_module_init_notifier_list,
state, data);
- mutex_unlock(&smsm_driver_state_notifier_lock);
+ mutex_unlock(&smd_module_init_notifier_lock);
}
int smd_core_init(void)
@@ -3547,12 +3548,29 @@
int __init msm_smd_init(void)
{
static bool registered;
+ int rc;
if (registered)
return 0;
registered = true;
- return platform_driver_register(&msm_smd_driver);
+ rc = remote_spin_lock_init(&remote_spinlock, SMEM_SPINLOCK_SMEM_ALLOC);
+ if (rc) {
+ pr_err("%s: remote spinlock init failed %d\n", __func__, rc);
+ return rc;
+ }
+ spinlocks_initialized = 1;
+
+ rc = platform_driver_register(&msm_smd_driver);
+ if (rc) {
+ pr_err("%s: msm_smd_driver register failed %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ smd_module_init_notify(0, NULL);
+
+ return 0;
}
module_init(msm_smd_init);
diff --git a/arch/arm/mach-msm/smem_log.c b/arch/arm/mach-msm/smem_log.c
index 2e9a97c..fd8144a 100644
--- a/arch/arm/mach-msm/smem_log.c
+++ b/arch/arm/mach-msm/smem_log.c
@@ -2008,25 +2008,23 @@
return ret;
}
-static int smsm_driver_state_notifier(struct notifier_block *this,
- unsigned long code,
- void *_cmd)
+static int smd_module_init_notifier(struct notifier_block *this,
+ unsigned long code,
+ void *_cmd)
{
int ret = 0;
- if (code & SMSM_INIT) {
- if (!smem_log_initialized)
- ret = smem_log_initialize();
- }
+ if (!smem_log_initialized)
+ ret = smem_log_initialize();
return ret;
}
static struct notifier_block nb = {
- .notifier_call = smsm_driver_state_notifier,
+ .notifier_call = smd_module_init_notifier,
};
static int __init smem_log_init(void)
{
- return smsm_driver_state_notifier_register(&nb);
+ return smd_module_init_notifier_register(&nb);
}
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 39fbba8..ea0b7a3 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -114,6 +114,14 @@
uint32_t hw_platform_subtype;
};
+struct socinfo_v7 {
+ struct socinfo_v6 v6;
+
+ /* only valid when format==7 */
+ uint32_t pmic_model;
+ uint32_t pmic_die_revision;
+};
+
static union {
struct socinfo_v1 v1;
struct socinfo_v2 v2;
@@ -121,6 +129,7 @@
struct socinfo_v4 v4;
struct socinfo_v5 v5;
struct socinfo_v6 v6;
+ struct socinfo_v7 v7;
} *socinfo;
static enum msm_cpu cpu_of_id[] = {
@@ -246,6 +255,7 @@
[127] = MSM_CPU_8625,
[128] = MSM_CPU_8625,
[129] = MSM_CPU_8625,
+ [137] = MSM_CPU_8625,
/* 8064 MPQ ID */
[130] = MSM_CPU_8064,
@@ -343,6 +353,21 @@
: 0;
}
+enum pmic_model socinfo_get_pmic_model(void)
+{
+ return socinfo ?
+ (socinfo->v1.format >= 7 ? socinfo->v7.pmic_model
+ : PMIC_MODEL_UNKNOWN)
+ : PMIC_MODEL_UNKNOWN;
+}
+
+uint32_t socinfo_get_pmic_die_revision(void)
+{
+ return socinfo ?
+ (socinfo->v1.format >= 7 ? socinfo->v7.pmic_die_revision : 0)
+ : 0;
+}
+
enum msm_cpu socinfo_get_msm_cpu(void)
{
return cur_cpu;
@@ -515,6 +540,42 @@
hw_platform_subtype[hw_subtype]);
}
+static ssize_t
+socinfo_show_pmic_model(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ char *buf)
+{
+ if (!socinfo) {
+ pr_err("%s: No socinfo found!\n", __func__);
+ return 0;
+ }
+ if (socinfo->v1.format < 7) {
+ pr_err("%s: pmic_model not available!\n", __func__);
+ return 0;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ socinfo_get_pmic_model());
+}
+
+static ssize_t
+socinfo_show_pmic_die_revision(struct sys_device *dev,
+ struct sysdev_attribute *attr,
+ char *buf)
+{
+ if (!socinfo) {
+ pr_err("%s: No socinfo found!\n", __func__);
+ return 0;
+ }
+ if (socinfo->v1.format < 7) {
+ pr_err("%s: pmic_die_revision not available!\n", __func__);
+ return 0;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%u\n",
+ socinfo_get_pmic_die_revision());
+}
+
static struct sysdev_attribute socinfo_v1_files[] = {
_SYSDEV_ATTR(id, 0444, socinfo_show_id, NULL),
_SYSDEV_ATTR(version, 0444, socinfo_show_version, NULL),
@@ -545,6 +606,13 @@
socinfo_show_platform_subtype, NULL),
};
+static struct sysdev_attribute socinfo_v7_files[] = {
+ _SYSDEV_ATTR(pmic_model, 0444,
+ socinfo_show_pmic_model, NULL),
+ _SYSDEV_ATTR(pmic_die_revision, 0444,
+ socinfo_show_pmic_die_revision, NULL),
+};
+
static struct sysdev_class soc_sysdev_class = {
.name = "soc",
};
@@ -619,9 +687,14 @@
if (socinfo->v1.format < 6)
return err;
- return socinfo_create_files(&soc_sys_device, socinfo_v6_files,
+ socinfo_create_files(&soc_sys_device, socinfo_v6_files,
ARRAY_SIZE(socinfo_v6_files));
+ if (socinfo->v1.format < 7)
+ return err;
+
+ return socinfo_create_files(&soc_sys_device, socinfo_v7_files,
+ ARRAY_SIZE(socinfo_v7_files));
}
arch_initcall(socinfo_init_sysdev);
@@ -649,7 +722,11 @@
int __init socinfo_init(void)
{
- socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID, sizeof(struct socinfo_v6));
+ socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID, sizeof(struct socinfo_v7));
+
+ if (!socinfo)
+ socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
+ sizeof(struct socinfo_v6));
if (!socinfo)
socinfo = smem_alloc(SMEM_HW_SW_BUILD_ID,
@@ -741,6 +818,20 @@
socinfo->v5.accessory_chip,
socinfo->v6.hw_platform_subtype);
break;
+ case 7:
+ pr_info("%s: v%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n accessory_chip=%u, hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u\n",
+ __func__,
+ socinfo->v1.format,
+ socinfo->v1.id,
+ SOCINFO_VERSION_MAJOR(socinfo->v1.version),
+ SOCINFO_VERSION_MINOR(socinfo->v1.version),
+ socinfo->v2.raw_id, socinfo->v2.raw_version,
+ socinfo->v3.hw_platform, socinfo->v4.platform_version,
+ socinfo->v5.accessory_chip,
+ socinfo->v6.hw_platform_subtype,
+ socinfo->v7.pmic_model,
+ socinfo->v7.pmic_die_revision);
+ break;
default:
pr_err("%s: Unknown format found\n", __func__);
break;
@@ -830,3 +921,17 @@
return 0;
};
}
+
+const int cpu_is_krait_v3(void)
+{
+ switch (read_cpuid_id()) {
+ case 0x512F04D0:
+ case 0x511F06F0:
+ case 0x511F06F1:
+ case 0x510F05D0:
+ return 1;
+
+ default:
+ return 0;
+ };
+}
diff --git a/arch/arm/mach-msm/spm-v2.c b/arch/arm/mach-msm/spm-v2.c
index b6d5324..9f5aa99 100644
--- a/arch/arm/mach-msm/spm-v2.c
+++ b/arch/arm/mach-msm/spm-v2.c
@@ -139,6 +139,10 @@
dev->reg_shadow[MSM_SPM_REG_SAW2_PMIC_DATA_1] &= ~0x3F;
dev->reg_shadow[MSM_SPM_REG_SAW2_PMIC_DATA_1] |= (vlevel & 0x3F);
+
+ dev->reg_shadow[MSM_SPM_REG_SAW2_PMIC_DATA_1] &= ~0x3F0000;
+ dev->reg_shadow[MSM_SPM_REG_SAW2_PMIC_DATA_1] |=
+ ((vlevel & 0x3F) << 16);
}
static inline void msm_spm_drv_set_vctl2(struct msm_spm_driver_data *dev,
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 553bece..8404601 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -21,6 +21,8 @@
#include <linux/highmem.h>
#include <linux/memblock.h>
#include <linux/slab.h>
+#include <linux/iommu.h>
+#include <linux/vmalloc.h>
#include <asm/memory.h>
#include <asm/highmem.h>
@@ -31,9 +33,109 @@
#include <asm/mach/map.h>
#include <asm/system_info.h>
#include <asm/dma-contiguous.h>
+#include <asm/dma-iommu.h>
#include "mm.h"
+/*
+ * The DMA API is built upon the notion of "buffer ownership". A buffer
+ * is either exclusively owned by the CPU (and therefore may be accessed
+ * by it) or exclusively owned by the DMA device. These helper functions
+ * represent the transitions between these two ownership states.
+ *
+ * Note, however, that on later ARMs, this notion does not work due to
+ * speculative prefetches. We model our approach on the assumption that
+ * the CPU does do speculative prefetches, which means we clean caches
+ * before transfers and delay cache invalidation until transfer completion.
+ *
+ */
+static void __dma_page_cpu_to_dev(struct page *, unsigned long,
+ size_t, enum dma_data_direction);
+static void __dma_page_dev_to_cpu(struct page *, unsigned long,
+ size_t, enum dma_data_direction);
+
+/**
+ * arm_dma_map_page - map a portion of a page for streaming DMA
+ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
+ * @page: page that buffer resides in
+ * @offset: offset into page for start of buffer
+ * @size: size of buffer to map
+ * @dir: DMA transfer direction
+ *
+ * Ensure that any data held in the cache is appropriately discarded
+ * or written back.
+ *
+ * The device owns this memory once this call has completed. The CPU
+ * can regain ownership by calling dma_unmap_page().
+ */
+static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ if (!arch_is_coherent())
+ __dma_page_cpu_to_dev(page, offset, size, dir);
+ return pfn_to_dma(dev, page_to_pfn(page)) + offset;
+}
+
+/**
+ * arm_dma_unmap_page - unmap a buffer previously mapped through dma_map_page()
+ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
+ * @handle: DMA address of buffer
+ * @size: size of buffer (same as passed to dma_map_page)
+ * @dir: DMA transfer direction (same as passed to dma_map_page)
+ *
+ * Unmap a page streaming mode DMA translation. The handle and size
+ * must match what was provided in the previous dma_map_page() call.
+ * All other usages are undefined.
+ *
+ * After this call, reads by the CPU to the buffer are guaranteed to see
+ * whatever the device wrote there.
+ */
+static void arm_dma_unmap_page(struct device *dev, dma_addr_t handle,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ if (!arch_is_coherent())
+ __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
+ handle & ~PAGE_MASK, size, dir);
+}
+
+static void arm_dma_sync_single_for_cpu(struct device *dev,
+ dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+ unsigned int offset = handle & (PAGE_SIZE - 1);
+ struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset));
+ if (!arch_is_coherent())
+ __dma_page_dev_to_cpu(page, offset, size, dir);
+}
+
+static void arm_dma_sync_single_for_device(struct device *dev,
+ dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+ unsigned int offset = handle & (PAGE_SIZE - 1);
+ struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset));
+ if (!arch_is_coherent())
+ __dma_page_cpu_to_dev(page, offset, size, dir);
+}
+
+static int arm_dma_set_mask(struct device *dev, u64 dma_mask);
+
+struct dma_map_ops arm_dma_ops = {
+ .alloc = arm_dma_alloc,
+ .free = arm_dma_free,
+ .mmap = arm_dma_mmap,
+ .map_page = arm_dma_map_page,
+ .unmap_page = arm_dma_unmap_page,
+ .map_sg = arm_dma_map_sg,
+ .unmap_sg = arm_dma_unmap_sg,
+ .sync_single_for_cpu = arm_dma_sync_single_for_cpu,
+ .sync_single_for_device = arm_dma_sync_single_for_device,
+ .sync_sg_for_cpu = arm_dma_sync_sg_for_cpu,
+ .sync_sg_for_device = arm_dma_sync_sg_for_device,
+ .set_dma_mask = arm_dma_set_mask,
+};
+EXPORT_SYMBOL(arm_dma_ops);
+
static u64 get_coherent_dma_mask(struct device *dev)
{
u64 mask = (u64)arm_dma_limit;
@@ -69,9 +171,11 @@
* lurking in the kernel direct-mapped region is invalidated.
*/
ptr = page_address(page);
- memset(ptr, 0, size);
- dmac_flush_range(ptr, ptr + size);
- outer_flush_range(__pa(ptr), __pa(ptr) + size);
+ if (ptr) {
+ memset(ptr, 0, size);
+ dmac_flush_range(ptr, ptr + size);
+ outer_flush_range(__pa(ptr), __pa(ptr) + size);
+ }
}
/*
@@ -124,7 +228,7 @@
#define DEFAULT_CONSISTENT_DMA_SIZE (7*SZ_2M)
-unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE;
+static unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE;
void __init init_consistent_dma_size(unsigned long size)
{
@@ -217,7 +321,7 @@
.vm_list = LIST_HEAD_INIT(coherent_head.vm_list),
};
-size_t coherent_pool_size = DEFAULT_CONSISTENT_DMA_SIZE / 8;
+static size_t coherent_pool_size = DEFAULT_CONSISTENT_DMA_SIZE / 8;
static int __init early_coherent_pool(char *p)
{
@@ -295,7 +399,7 @@
* Clear previous low-memory mapping
*/
for (addr = __phys_to_virt(start); addr < __phys_to_virt(end);
- addr += PGDIR_SIZE)
+ addr += PMD_SIZE)
pmd_clear(pmd_off_k(addr));
iotable_init(&map, 1);
@@ -338,7 +442,7 @@
u32 off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);
pte = consistent_pte[idx] + off;
- c->vm_pages = page;
+ c->priv = page;
do {
BUG_ON(!pte_none(*pte));
@@ -524,6 +628,14 @@
dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
}
+static inline pgprot_t __get_dma_pgprot(struct dma_attrs *attrs, pgprot_t prot)
+{
+ prot = dma_get_attr(DMA_ATTR_WRITE_COMBINE, attrs) ?
+ pgprot_writecombine(prot) :
+ pgprot_dmacoherent(prot);
+ return prot;
+}
+
#define nommu() 0
#else /* !CONFIG_MMU */
@@ -536,6 +648,7 @@
#define __free_from_pool(cpu_addr, size) 0
#define __free_from_contiguous(dev, page, size) do { } while (0)
#define __dma_free_remap(cpu_addr, size) do { } while (0)
+#define __get_dma_pgprot(attrs, prot) __pgprot(0)
#endif /* CONFIG_MMU */
@@ -606,39 +719,30 @@
* Allocate DMA-coherent memory space and return both the kernel remapped
* virtual and bus address for that space.
*/
-void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle,
- gfp_t gfp)
+void *arm_dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
+ gfp_t gfp, struct dma_attrs *attrs)
{
+ pgprot_t prot = __get_dma_pgprot(attrs, pgprot_kernel);
void *memory;
if (dma_alloc_from_coherent(dev, size, handle, &memory))
return memory;
- return __dma_alloc(dev, size, handle, gfp,
- pgprot_dmacoherent(pgprot_kernel),
+ return __dma_alloc(dev, size, handle, gfp, prot,
__builtin_return_address(0));
}
-EXPORT_SYMBOL(dma_alloc_coherent);
/*
- * Allocate a writecombining region, in much the same way as
- * dma_alloc_coherent above.
+ * Create userspace mapping for the DMA-coherent memory.
*/
-void *
-dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
-{
- return __dma_alloc(dev, size, handle, gfp,
- pgprot_writecombine(pgprot_kernel),
- __builtin_return_address(0));
-}
-EXPORT_SYMBOL(dma_alloc_writecombine);
-
-static int dma_mmap(struct device *dev, struct vm_area_struct *vma,
- void *cpu_addr, dma_addr_t dma_addr, size_t size)
+int arm_dma_mmap(struct device *dev, struct vm_area_struct *vma,
+ void *cpu_addr, dma_addr_t dma_addr, size_t size,
+ struct dma_attrs *attrs)
{
int ret = -ENXIO;
#ifdef CONFIG_MMU
unsigned long pfn = dma_to_pfn(dev, dma_addr);
+ vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
return ret;
@@ -652,27 +756,11 @@
return ret;
}
-int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
- void *cpu_addr, dma_addr_t dma_addr, size_t size)
-{
- vma->vm_page_prot = pgprot_dmacoherent(vma->vm_page_prot);
- return dma_mmap(dev, vma, cpu_addr, dma_addr, size);
-}
-EXPORT_SYMBOL(dma_mmap_coherent);
-
-int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma,
- void *cpu_addr, dma_addr_t dma_addr, size_t size)
-{
- vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- return dma_mmap(dev, vma, cpu_addr, dma_addr, size);
-}
-EXPORT_SYMBOL(dma_mmap_writecombine);
-
-
/*
* Free a buffer as defined by the above mapping.
*/
-void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle)
+void arm_dma_free(struct device *dev, size_t size, void *cpu_addr,
+ dma_addr_t handle, struct dma_attrs *attrs)
{
struct page *page = pfn_to_page(dma_to_pfn(dev, handle));
@@ -696,53 +784,6 @@
__free_from_contiguous(dev, page, size);
}
}
-EXPORT_SYMBOL(dma_free_coherent);
-
-/*
- * Make an area consistent for devices.
- * Note: Drivers should NOT use this function directly, as it will break
- * platforms with CONFIG_DMABOUNCE.
- * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
- */
-void ___dma_single_cpu_to_dev(const void *kaddr, size_t size,
- enum dma_data_direction dir)
-{
-#ifdef CONFIG_OUTER_CACHE
- unsigned long paddr;
-
- BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1));
-#endif
-
- dmac_map_area(kaddr, size, dir);
-
-#ifdef CONFIG_OUTER_CACHE
- paddr = __pa(kaddr);
- if (dir == DMA_FROM_DEVICE) {
- outer_inv_range(paddr, paddr + size);
- } else {
- outer_clean_range(paddr, paddr + size);
- }
-#endif
- /* FIXME: non-speculating: flush on bidirectional mappings? */
-}
-EXPORT_SYMBOL(___dma_single_cpu_to_dev);
-
-void ___dma_single_dev_to_cpu(const void *kaddr, size_t size,
- enum dma_data_direction dir)
-{
-#ifdef CONFIG_OUTER_CACHE
- BUG_ON(!virt_addr_valid(kaddr) || !virt_addr_valid(kaddr + size - 1));
-
- /* FIXME: non-speculating: not required */
- /* don't bother invalidating if DMA to device */
- if (dir != DMA_TO_DEVICE) {
- unsigned long paddr = __pa(kaddr);
- outer_inv_range(paddr, paddr + size);
- }
-#endif
- dmac_unmap_area(kaddr, size, dir);
-}
-EXPORT_SYMBOL(___dma_single_dev_to_cpu);
static void dma_cache_maint_page(struct page *page, unsigned long offset,
size_t size, enum dma_data_direction dir,
@@ -788,7 +829,13 @@
} while (left);
}
-void ___dma_page_cpu_to_dev(struct page *page, unsigned long off,
+/*
+ * Make an area consistent for devices.
+ * Note: Drivers should NOT use this function directly, as it will break
+ * platforms with CONFIG_DMABOUNCE.
+ * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
+ */
+static void __dma_page_cpu_to_dev(struct page *page, unsigned long off,
size_t size, enum dma_data_direction dir)
{
unsigned long paddr;
@@ -803,9 +850,8 @@
}
/* FIXME: non-speculating: flush on bidirectional mappings? */
}
-EXPORT_SYMBOL(___dma_page_cpu_to_dev);
-void ___dma_page_dev_to_cpu(struct page *page, unsigned long off,
+static void __dma_page_dev_to_cpu(struct page *page, unsigned long off,
size_t size, enum dma_data_direction dir)
{
unsigned long paddr = page_to_phys(page) + off;
@@ -823,10 +869,9 @@
if (dir != DMA_TO_DEVICE && off == 0 && size >= PAGE_SIZE)
set_bit(PG_dcache_clean, &page->flags);
}
-EXPORT_SYMBOL(___dma_page_dev_to_cpu);
/**
- * dma_map_sg - map a set of SG buffers for streaming mode DMA
+ * arm_dma_map_sg - map a set of SG buffers for streaming mode DMA
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
* @sg: list of buffers
* @nents: number of buffers to map
@@ -841,32 +886,32 @@
* Device ownership issues as mentioned for dma_map_single are the same
* here.
*/
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir)
+int arm_dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
{
+ struct dma_map_ops *ops = get_dma_ops(dev);
struct scatterlist *s;
int i, j;
- BUG_ON(!valid_dma_direction(dir));
-
for_each_sg(sg, s, nents, i) {
- s->dma_address = __dma_map_page(dev, sg_page(s), s->offset,
- s->length, dir);
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
+ s->dma_length = s->length;
+#endif
+ s->dma_address = ops->map_page(dev, sg_page(s), s->offset,
+ s->length, dir, attrs);
if (dma_mapping_error(dev, s->dma_address))
goto bad_mapping;
}
- debug_dma_map_sg(dev, sg, nents, nents, dir);
return nents;
bad_mapping:
for_each_sg(sg, s, i, j)
- __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
+ ops->unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir, attrs);
return 0;
}
-EXPORT_SYMBOL(dma_map_sg);
/**
- * dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
+ * arm_dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
* @sg: list of buffers
* @nents: number of buffers to unmap (same as was passed to dma_map_sg)
@@ -875,70 +920,55 @@
* Unmap a set of streaming mode DMA translations. Again, CPU access
* rules concerning calls here are the same as for dma_unmap_single().
*/
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction dir)
+void arm_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
{
+ struct dma_map_ops *ops = get_dma_ops(dev);
struct scatterlist *s;
- int i;
- debug_dma_unmap_sg(dev, sg, nents, dir);
+ int i;
for_each_sg(sg, s, nents, i)
- __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
+ ops->unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir, attrs);
}
-EXPORT_SYMBOL(dma_unmap_sg);
/**
- * dma_sync_sg_for_cpu
+ * arm_dma_sync_sg_for_cpu
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
* @sg: list of buffers
* @nents: number of buffers to map (returned from dma_map_sg)
* @dir: DMA transfer direction (same as was passed to dma_map_sg)
*/
-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
+void arm_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir)
{
+ struct dma_map_ops *ops = get_dma_ops(dev);
struct scatterlist *s;
int i;
- for_each_sg(sg, s, nents, i) {
- if (!dmabounce_sync_for_cpu(dev, sg_dma_address(s),
- sg_dma_len(s), dir))
- continue;
-
- __dma_page_dev_to_cpu(sg_page(s), s->offset,
- s->length, dir);
- }
-
- debug_dma_sync_sg_for_cpu(dev, sg, nents, dir);
+ for_each_sg(sg, s, nents, i)
+ ops->sync_single_for_cpu(dev, sg_dma_address(s), s->length,
+ dir);
}
-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
/**
- * dma_sync_sg_for_device
+ * arm_dma_sync_sg_for_device
* @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
* @sg: list of buffers
* @nents: number of buffers to map (returned from dma_map_sg)
* @dir: DMA transfer direction (same as was passed to dma_map_sg)
*/
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
+void arm_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction dir)
{
+ struct dma_map_ops *ops = get_dma_ops(dev);
struct scatterlist *s;
int i;
- for_each_sg(sg, s, nents, i) {
- if (!dmabounce_sync_for_device(dev, sg_dma_address(s),
- sg_dma_len(s), dir))
- continue;
-
- __dma_page_cpu_to_dev(sg_page(s), s->offset,
- s->length, dir);
- }
-
- debug_dma_sync_sg_for_device(dev, sg, nents, dir);
+ for_each_sg(sg, s, nents, i)
+ ops->sync_single_for_device(dev, sg_dma_address(s), s->length,
+ dir);
}
-EXPORT_SYMBOL(dma_sync_sg_for_device);
/*
* Return whether the given device DMA address mask can be supported
@@ -954,18 +984,15 @@
}
EXPORT_SYMBOL(dma_supported);
-int dma_set_mask(struct device *dev, u64 dma_mask)
+static int arm_dma_set_mask(struct device *dev, u64 dma_mask)
{
if (!dev->dma_mask || !dma_supported(dev, dma_mask))
return -EIO;
-#ifndef CONFIG_DMABOUNCE
*dev->dma_mask = dma_mask;
-#endif
return 0;
}
-EXPORT_SYMBOL(dma_set_mask);
#define PREALLOC_DMA_DEBUG_ENTRIES 4096
@@ -978,3 +1005,679 @@
return 0;
}
fs_initcall(dma_debug_do_init);
+
+#ifdef CONFIG_ARM_DMA_USE_IOMMU
+
+/* IOMMU */
+
+static inline dma_addr_t __alloc_iova(struct dma_iommu_mapping *mapping,
+ size_t size)
+{
+ unsigned int order = get_order(size);
+ unsigned int align = 0;
+ unsigned int count, start;
+ unsigned long flags;
+
+ count = ((PAGE_ALIGN(size) >> PAGE_SHIFT) +
+ (1 << mapping->order) - 1) >> mapping->order;
+
+ if (order > mapping->order)
+ align = (1 << (order - mapping->order)) - 1;
+
+ spin_lock_irqsave(&mapping->lock, flags);
+ start = bitmap_find_next_zero_area(mapping->bitmap, mapping->bits, 0,
+ count, align);
+ if (start > mapping->bits) {
+ spin_unlock_irqrestore(&mapping->lock, flags);
+ return DMA_ERROR_CODE;
+ }
+
+ bitmap_set(mapping->bitmap, start, count);
+ spin_unlock_irqrestore(&mapping->lock, flags);
+
+ return mapping->base + (start << (mapping->order + PAGE_SHIFT));
+}
+
+static inline void __free_iova(struct dma_iommu_mapping *mapping,
+ dma_addr_t addr, size_t size)
+{
+ unsigned int start = (addr - mapping->base) >>
+ (mapping->order + PAGE_SHIFT);
+ unsigned int count = ((size >> PAGE_SHIFT) +
+ (1 << mapping->order) - 1) >> mapping->order;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mapping->lock, flags);
+ bitmap_clear(mapping->bitmap, start, count);
+ spin_unlock_irqrestore(&mapping->lock, flags);
+}
+
+static struct page **__iommu_alloc_buffer(struct device *dev, size_t size, gfp_t gfp)
+{
+ struct page **pages;
+ int count = size >> PAGE_SHIFT;
+ int array_size = count * sizeof(struct page *);
+ int i = 0;
+
+ if (array_size <= PAGE_SIZE)
+ pages = kzalloc(array_size, gfp);
+ else
+ pages = vzalloc(array_size);
+ if (!pages)
+ return NULL;
+
+ while (count) {
+ int j, order = __fls(count);
+
+ pages[i] = alloc_pages(gfp | __GFP_NOWARN, order);
+ while (!pages[i] && order)
+ pages[i] = alloc_pages(gfp | __GFP_NOWARN, --order);
+ if (!pages[i])
+ goto error;
+
+ if (order)
+ split_page(pages[i], order);
+ j = 1 << order;
+ while (--j)
+ pages[i + j] = pages[i] + j;
+
+ __dma_clear_buffer(pages[i], PAGE_SIZE << order);
+ i += 1 << order;
+ count -= 1 << order;
+ }
+
+ return pages;
+error:
+ while (--i)
+ if (pages[i])
+ __free_pages(pages[i], 0);
+ if (array_size < PAGE_SIZE)
+ kfree(pages);
+ else
+ vfree(pages);
+ return NULL;
+}
+
+static int __iommu_free_buffer(struct device *dev, struct page **pages, size_t size)
+{
+ int count = size >> PAGE_SHIFT;
+ int array_size = count * sizeof(struct page *);
+ int i;
+ for (i = 0; i < count; i++)
+ if (pages[i])
+ __free_pages(pages[i], 0);
+ if (array_size < PAGE_SIZE)
+ kfree(pages);
+ else
+ vfree(pages);
+ return 0;
+}
+
+/*
+ * Create a CPU mapping for a specified pages
+ */
+static void *
+__iommu_alloc_remap(struct page **pages, size_t size, gfp_t gfp, pgprot_t prot)
+{
+ struct arm_vmregion *c;
+ size_t align;
+ size_t count = size >> PAGE_SHIFT;
+ int bit;
+
+ if (!consistent_pte[0]) {
+ pr_err("%s: not initialised\n", __func__);
+ dump_stack();
+ return NULL;
+ }
+
+ /*
+ * Align the virtual region allocation - maximum alignment is
+ * a section size, minimum is a page size. This helps reduce
+ * fragmentation of the DMA space, and also prevents allocations
+ * smaller than a section from crossing a section boundary.
+ */
+ bit = fls(size - 1);
+ if (bit > SECTION_SHIFT)
+ bit = SECTION_SHIFT;
+ align = 1 << bit;
+
+ /*
+ * Allocate a virtual address in the consistent mapping region.
+ */
+ c = arm_vmregion_alloc(&consistent_head, align, size,
+ gfp & ~(__GFP_DMA | __GFP_HIGHMEM), NULL);
+ if (c) {
+ pte_t *pte;
+ int idx = CONSISTENT_PTE_INDEX(c->vm_start);
+ int i = 0;
+ u32 off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1);
+
+ pte = consistent_pte[idx] + off;
+ c->priv = pages;
+
+ do {
+ BUG_ON(!pte_none(*pte));
+
+ set_pte_ext(pte, mk_pte(pages[i], prot), 0);
+ pte++;
+ off++;
+ i++;
+ if (off >= PTRS_PER_PTE) {
+ off = 0;
+ pte = consistent_pte[++idx];
+ }
+ } while (i < count);
+
+ dsb();
+
+ return (void *)c->vm_start;
+ }
+ return NULL;
+}
+
+/*
+ * Create a mapping in device IO address space for specified pages
+ */
+static dma_addr_t
+__iommu_create_mapping(struct device *dev, struct page **pages, size_t size)
+{
+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
+ unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ dma_addr_t dma_addr, iova;
+ int i, ret = DMA_ERROR_CODE;
+
+ dma_addr = __alloc_iova(mapping, size);
+ if (dma_addr == DMA_ERROR_CODE)
+ return dma_addr;
+
+ iova = dma_addr;
+ for (i = 0; i < count; ) {
+ unsigned int next_pfn = page_to_pfn(pages[i]) + 1;
+ phys_addr_t phys = page_to_phys(pages[i]);
+ unsigned int len, j;
+
+ for (j = i + 1; j < count; j++, next_pfn++)
+ if (page_to_pfn(pages[j]) != next_pfn)
+ break;
+
+ len = (j - i) << PAGE_SHIFT;
+ ret = iommu_map(mapping->domain, iova, phys, len, 0);
+ if (ret < 0)
+ goto fail;
+ iova += len;
+ i = j;
+ }
+ return dma_addr;
+fail:
+ iommu_unmap(mapping->domain, dma_addr, iova-dma_addr);
+ __free_iova(mapping, dma_addr, size);
+ return DMA_ERROR_CODE;
+}
+
+static int __iommu_remove_mapping(struct device *dev, dma_addr_t iova, size_t size)
+{
+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
+
+ /*
+ * add optional in-page offset from iova to size and align
+ * result to page size
+ */
+ size = PAGE_ALIGN((iova & ~PAGE_MASK) + size);
+ iova &= PAGE_MASK;
+
+ iommu_unmap(mapping->domain, iova, size);
+ __free_iova(mapping, iova, size);
+ return 0;
+}
+
+static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
+ dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
+{
+ pgprot_t prot = __get_dma_pgprot(attrs, pgprot_kernel);
+ struct page **pages;
+ void *addr = NULL;
+
+ *handle = DMA_ERROR_CODE;
+ size = PAGE_ALIGN(size);
+
+ pages = __iommu_alloc_buffer(dev, size, gfp);
+ if (!pages)
+ return NULL;
+
+ *handle = __iommu_create_mapping(dev, pages, size);
+ if (*handle == DMA_ERROR_CODE)
+ goto err_buffer;
+
+ addr = __iommu_alloc_remap(pages, size, gfp, prot);
+ if (!addr)
+ goto err_mapping;
+
+ return addr;
+
+err_mapping:
+ __iommu_remove_mapping(dev, *handle, size);
+err_buffer:
+ __iommu_free_buffer(dev, pages, size);
+ return NULL;
+}
+
+static int arm_iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
+ void *cpu_addr, dma_addr_t dma_addr, size_t size,
+ struct dma_attrs *attrs)
+{
+ struct arm_vmregion *c;
+
+ vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot);
+ c = arm_vmregion_find(&consistent_head, (unsigned long)cpu_addr);
+
+ if (c) {
+ struct page **pages = c->priv;
+
+ unsigned long uaddr = vma->vm_start;
+ unsigned long usize = vma->vm_end - vma->vm_start;
+ int i = 0;
+
+ do {
+ int ret;
+
+ ret = vm_insert_page(vma, uaddr, pages[i++]);
+ if (ret) {
+ pr_err("Remapping memory, error: %d\n", ret);
+ return ret;
+ }
+
+ uaddr += PAGE_SIZE;
+ usize -= PAGE_SIZE;
+ } while (usize > 0);
+ }
+ return 0;
+}
+
+/*
+ * free a page as defined by the above mapping.
+ * Must not be called with IRQs disabled.
+ */
+void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
+ dma_addr_t handle, struct dma_attrs *attrs)
+{
+ struct arm_vmregion *c;
+ size = PAGE_ALIGN(size);
+
+ c = arm_vmregion_find(&consistent_head, (unsigned long)cpu_addr);
+ if (c) {
+ struct page **pages = c->priv;
+ __dma_free_remap(cpu_addr, size);
+ __iommu_remove_mapping(dev, handle, size);
+ __iommu_free_buffer(dev, pages, size);
+ }
+}
+
+/*
+ * Map a part of the scatter-gather list into contiguous io address space
+ */
+static int __map_sg_chunk(struct device *dev, struct scatterlist *sg,
+ size_t size, dma_addr_t *handle,
+ enum dma_data_direction dir)
+{
+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
+ dma_addr_t iova, iova_base;
+ int ret = 0;
+ unsigned int count;
+ struct scatterlist *s;
+
+ size = PAGE_ALIGN(size);
+ *handle = DMA_ERROR_CODE;
+
+ iova_base = iova = __alloc_iova(mapping, size);
+ if (iova == DMA_ERROR_CODE)
+ return -ENOMEM;
+
+ for (count = 0, s = sg; count < (size >> PAGE_SHIFT); s = sg_next(s)) {
+ phys_addr_t phys = page_to_phys(sg_page(s));
+ unsigned int len = PAGE_ALIGN(s->offset + s->length);
+
+ if (!arch_is_coherent())
+ __dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir);
+
+ ret = iommu_map(mapping->domain, iova, phys, len, 0);
+ if (ret < 0)
+ goto fail;
+ count += len >> PAGE_SHIFT;
+ iova += len;
+ }
+ *handle = iova_base;
+
+ return 0;
+fail:
+ iommu_unmap(mapping->domain, iova_base, count * PAGE_SIZE);
+ __free_iova(mapping, iova_base, size);
+ return ret;
+}
+
+/**
+ * arm_iommu_map_sg - map a set of SG buffers for streaming mode DMA
+ * @dev: valid struct device pointer
+ * @sg: list of buffers
+ * @nents: number of buffers to map
+ * @dir: DMA transfer direction
+ *
+ * Map a set of buffers described by scatterlist in streaming mode for DMA.
+ * The scatter gather list elements are merged together (if possible) and
+ * tagged with the appropriate dma address and length. They are obtained via
+ * sg_dma_{address,length}.
+ */
+int arm_iommu_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+ struct scatterlist *s = sg, *dma = sg, *start = sg;
+ int i, count = 0;
+ unsigned int offset = s->offset;
+ unsigned int size = s->offset + s->length;
+ unsigned int max = dma_get_max_seg_size(dev);
+
+ for (i = 1; i < nents; i++) {
+ s = sg_next(s);
+
+ s->dma_address = DMA_ERROR_CODE;
+ s->dma_length = 0;
+
+ if (s->offset || (size & ~PAGE_MASK) || size + s->length > max) {
+ if (__map_sg_chunk(dev, start, size, &dma->dma_address,
+ dir) < 0)
+ goto bad_mapping;
+
+ dma->dma_address += offset;
+ dma->dma_length = size - offset;
+
+ size = offset = s->offset;
+ start = s;
+ dma = sg_next(dma);
+ count += 1;
+ }
+ size += s->length;
+ }
+ if (__map_sg_chunk(dev, start, size, &dma->dma_address, dir) < 0)
+ goto bad_mapping;
+
+ dma->dma_address += offset;
+ dma->dma_length = size - offset;
+
+ return count+1;
+
+bad_mapping:
+ for_each_sg(sg, s, count, i)
+ __iommu_remove_mapping(dev, sg_dma_address(s), sg_dma_len(s));
+ return 0;
+}
+
+/**
+ * arm_iommu_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
+ * @dev: valid struct device pointer
+ * @sg: list of buffers
+ * @nents: number of buffers to unmap (same as was passed to dma_map_sg)
+ * @dir: DMA transfer direction (same as was passed to dma_map_sg)
+ *
+ * Unmap a set of streaming mode DMA translations. Again, CPU access
+ * rules concerning calls here are the same as for dma_unmap_single().
+ */
+void arm_iommu_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+ struct scatterlist *s;
+ int i;
+
+ for_each_sg(sg, s, nents, i) {
+ if (sg_dma_len(s))
+ __iommu_remove_mapping(dev, sg_dma_address(s),
+ sg_dma_len(s));
+ if (!arch_is_coherent())
+ __dma_page_dev_to_cpu(sg_page(s), s->offset,
+ s->length, dir);
+ }
+}
+
+/**
+ * arm_iommu_sync_sg_for_cpu
+ * @dev: valid struct device pointer
+ * @sg: list of buffers
+ * @nents: number of buffers to map (returned from dma_map_sg)
+ * @dir: DMA transfer direction (same as was passed to dma_map_sg)
+ */
+void arm_iommu_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir)
+{
+ struct scatterlist *s;
+ int i;
+
+ for_each_sg(sg, s, nents, i)
+ if (!arch_is_coherent())
+ __dma_page_dev_to_cpu(sg_page(s), s->offset, s->length, dir);
+
+}
+
+/**
+ * arm_iommu_sync_sg_for_device
+ * @dev: valid struct device pointer
+ * @sg: list of buffers
+ * @nents: number of buffers to map (returned from dma_map_sg)
+ * @dir: DMA transfer direction (same as was passed to dma_map_sg)
+ */
+void arm_iommu_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir)
+{
+ struct scatterlist *s;
+ int i;
+
+ for_each_sg(sg, s, nents, i)
+ if (!arch_is_coherent())
+ __dma_page_cpu_to_dev(sg_page(s), s->offset, s->length, dir);
+}
+
+
+/**
+ * arm_iommu_map_page
+ * @dev: valid struct device pointer
+ * @page: page that buffer resides in
+ * @offset: offset into page for start of buffer
+ * @size: size of buffer to map
+ * @dir: DMA transfer direction
+ *
+ * IOMMU aware version of arm_dma_map_page()
+ */
+static dma_addr_t arm_iommu_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
+ dma_addr_t dma_addr;
+ int ret, len = PAGE_ALIGN(size + offset);
+
+ if (!arch_is_coherent())
+ __dma_page_cpu_to_dev(page, offset, size, dir);
+
+ dma_addr = __alloc_iova(mapping, len);
+ if (dma_addr == DMA_ERROR_CODE)
+ return dma_addr;
+
+ ret = iommu_map(mapping->domain, dma_addr, page_to_phys(page), len, 0);
+ if (ret < 0)
+ goto fail;
+
+ return dma_addr + offset;
+fail:
+ __free_iova(mapping, dma_addr, len);
+ return DMA_ERROR_CODE;
+}
+
+/**
+ * arm_iommu_unmap_page
+ * @dev: valid struct device pointer
+ * @handle: DMA address of buffer
+ * @size: size of buffer (same as passed to dma_map_page)
+ * @dir: DMA transfer direction (same as passed to dma_map_page)
+ *
+ * IOMMU aware version of arm_dma_unmap_page()
+ */
+static void arm_iommu_unmap_page(struct device *dev, dma_addr_t handle,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
+ dma_addr_t iova = handle & PAGE_MASK;
+ struct page *page = phys_to_page(iommu_iova_to_phys(mapping->domain, iova));
+ int offset = handle & ~PAGE_MASK;
+ int len = PAGE_ALIGN(size + offset);
+
+ if (!iova)
+ return;
+
+ if (!arch_is_coherent())
+ __dma_page_dev_to_cpu(page, offset, size, dir);
+
+ iommu_unmap(mapping->domain, iova, len);
+ __free_iova(mapping, iova, len);
+}
+
+static void arm_iommu_sync_single_for_cpu(struct device *dev,
+ dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
+ dma_addr_t iova = handle & PAGE_MASK;
+ struct page *page = phys_to_page(iommu_iova_to_phys(mapping->domain, iova));
+ unsigned int offset = handle & ~PAGE_MASK;
+
+ if (!iova)
+ return;
+
+ if (!arch_is_coherent())
+ __dma_page_dev_to_cpu(page, offset, size, dir);
+}
+
+static void arm_iommu_sync_single_for_device(struct device *dev,
+ dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
+ dma_addr_t iova = handle & PAGE_MASK;
+ struct page *page = phys_to_page(iommu_iova_to_phys(mapping->domain, iova));
+ unsigned int offset = handle & ~PAGE_MASK;
+
+ if (!iova)
+ return;
+
+ __dma_page_cpu_to_dev(page, offset, size, dir);
+}
+
+struct dma_map_ops iommu_ops = {
+ .alloc = arm_iommu_alloc_attrs,
+ .free = arm_iommu_free_attrs,
+ .mmap = arm_iommu_mmap_attrs,
+
+ .map_page = arm_iommu_map_page,
+ .unmap_page = arm_iommu_unmap_page,
+ .sync_single_for_cpu = arm_iommu_sync_single_for_cpu,
+ .sync_single_for_device = arm_iommu_sync_single_for_device,
+
+ .map_sg = arm_iommu_map_sg,
+ .unmap_sg = arm_iommu_unmap_sg,
+ .sync_sg_for_cpu = arm_iommu_sync_sg_for_cpu,
+ .sync_sg_for_device = arm_iommu_sync_sg_for_device,
+};
+
+/**
+ * arm_iommu_create_mapping
+ * @bus: pointer to the bus holding the client device (for IOMMU calls)
+ * @base: start address of the valid IO address space
+ * @size: size of the valid IO address space
+ * @order: accuracy of the IO addresses allocations
+ *
+ * Creates a mapping structure which holds information about used/unused
+ * IO address ranges, which is required to perform memory allocation and
+ * mapping with IOMMU aware functions.
+ *
+ * The client device need to be attached to the mapping with
+ * arm_iommu_attach_device function.
+ */
+struct dma_iommu_mapping *
+arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size,
+ int order)
+{
+ unsigned int count = size >> (PAGE_SHIFT + order);
+ unsigned int bitmap_size = BITS_TO_LONGS(count) * sizeof(long);
+ struct dma_iommu_mapping *mapping;
+ int err = -ENOMEM;
+
+ if (!count)
+ return ERR_PTR(-EINVAL);
+
+ mapping = kzalloc(sizeof(struct dma_iommu_mapping), GFP_KERNEL);
+ if (!mapping)
+ goto err;
+
+ mapping->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+ if (!mapping->bitmap)
+ goto err2;
+
+ mapping->base = base;
+ mapping->bits = BITS_PER_BYTE * bitmap_size;
+ mapping->order = order;
+ spin_lock_init(&mapping->lock);
+
+ mapping->domain = iommu_domain_alloc(bus);
+ if (!mapping->domain)
+ goto err3;
+
+ kref_init(&mapping->kref);
+ return mapping;
+err3:
+ kfree(mapping->bitmap);
+err2:
+ kfree(mapping);
+err:
+ return ERR_PTR(err);
+}
+
+static void release_iommu_mapping(struct kref *kref)
+{
+ struct dma_iommu_mapping *mapping =
+ container_of(kref, struct dma_iommu_mapping, kref);
+
+ iommu_domain_free(mapping->domain);
+ kfree(mapping->bitmap);
+ kfree(mapping);
+}
+
+void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping)
+{
+ if (mapping)
+ kref_put(&mapping->kref, release_iommu_mapping);
+}
+
+/**
+ * arm_iommu_attach_device
+ * @dev: valid struct device pointer
+ * @mapping: io address space mapping structure (returned from
+ * arm_iommu_create_mapping)
+ *
+ * Attaches specified io address space mapping to the provided device,
+ * this replaces the dma operations (dma_map_ops pointer) with the
+ * IOMMU aware version. More than one client might be attached to
+ * the same io address space mapping.
+ */
+int arm_iommu_attach_device(struct device *dev,
+ struct dma_iommu_mapping *mapping)
+{
+ int err;
+
+ err = iommu_attach_device(mapping->domain, dev);
+ if (err)
+ return err;
+
+ kref_get(&mapping->kref);
+ dev->archdata.mapping = mapping;
+ set_dma_ops(dev, &iommu_ops);
+
+ pr_info("Attached IOMMU controller to %s device.\n", dev_name(dev));
+ return 0;
+}
+
+#endif
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h
index bd41abc..8877ddd 100644
--- a/arch/arm/mm/mm.h
+++ b/arch/arm/mm/mm.h
@@ -55,6 +55,9 @@
/* permanent static mappings from iotable_init() */
#define VM_ARM_STATIC_MAPPING 0x40000000
+/* empty mapping */
+#define VM_ARM_EMPTY_MAPPING 0x20000000
+
/* mapping type (attributes) for permanent static mappings */
#define VM_ARM_MTYPE(mt) ((mt) << 20)
#define VM_ARM_MTYPE_MASK (0x1f << 20)
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index da33be0..bae23b0 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -861,7 +861,7 @@
vm = early_alloc_aligned(sizeof(*vm), __alignof__(*vm));
vm->addr = (void *)addr;
vm->size = SECTION_SIZE;
- vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;
+ vm->flags = VM_IOREMAP | VM_ARM_EMPTY_MAPPING;
vm->caller = pmd_empty_section_gap;
vm_area_add_early(vm);
}
@@ -874,7 +874,7 @@
/* we're still single threaded hence no lock needed here */
for (vm = vmlist; vm; vm = vm->next) {
- if (!(vm->flags & VM_ARM_STATIC_MAPPING))
+ if (!(vm->flags & (VM_ARM_STATIC_MAPPING | VM_ARM_EMPTY_MAPPING)))
continue;
addr = (unsigned long)vm->addr;
if (addr < next)
diff --git a/arch/arm/mm/vmregion.h b/arch/arm/mm/vmregion.h
index 162be66..bf312c3 100644
--- a/arch/arm/mm/vmregion.h
+++ b/arch/arm/mm/vmregion.h
@@ -17,7 +17,7 @@
struct list_head vm_list;
unsigned long vm_start;
unsigned long vm_end;
- struct page *vm_pages;
+ void *priv;
int vm_active;
const void *caller;
};
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index cfcacff..50b3362 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -93,7 +93,7 @@
static void hostwake_interrupt(unsigned long data)
{
- printk(KERN_INFO " wakeup host\n");
+ BT_INFO(" wakeup host\n");
}
static void modify_timer_task(void)
@@ -109,7 +109,7 @@
{
int status = 0;
if (test_bit(BT_TXEXPIRED, &flags)) {
- printk(KERN_INFO "wakeup device\n");
+ BT_INFO("wakeup device\n");
gpio_set_value(bsi->ext_wake, 0);
msleep(20);
gpio_set_value(bsi->ext_wake, 1);
@@ -138,12 +138,114 @@
hci_uart_tx_wakeup(hu);
}
+static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id)
+{
+ /* schedule a tasklet to handle the change in the host wake line */
+ tasklet_schedule(&hostwake_task);
+ return IRQ_HANDLED;
+}
+
+static int ath_bluesleep_gpio_config(int on)
+{
+ int ret = 0;
+
+ BT_INFO("%s config: %d", __func__, on);
+ if (!on) {
+ if (disable_irq_wake(bsi->host_wake_irq))
+ BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n");
+ goto free_host_wake_irq;
+ }
+
+ ret = gpio_request(bsi->host_wake, "bt_host_wake");
+ if (ret < 0) {
+ BT_ERR("failed to request gpio pin %d, error %d\n",
+ bsi->host_wake, ret);
+ goto gpio_config_failed;
+ }
+
+ /* configure host_wake as input */
+ ret = gpio_direction_input(bsi->host_wake);
+ if (ret < 0) {
+ BT_ERR("failed to config GPIO %d as input pin, err %d\n",
+ bsi->host_wake, ret);
+ goto gpio_host_wake;
+ }
+
+ ret = gpio_request(bsi->ext_wake, "bt_ext_wake");
+ if (ret < 0) {
+ BT_ERR("failed to request gpio pin %d, error %d\n",
+ bsi->ext_wake, ret);
+ goto gpio_host_wake;
+ }
+
+ ret = gpio_direction_output(bsi->ext_wake, 1);
+ if (ret < 0) {
+ BT_ERR("failed to config GPIO %d as output pin, err %d\n",
+ bsi->ext_wake, ret);
+ goto gpio_ext_wake;
+ }
+
+ gpio_set_value(bsi->ext_wake, 1);
+
+ /* Initialize spinlock. */
+ spin_lock_init(&rw_lock);
+
+ /* Initialize timer */
+ init_timer(&tx_timer);
+ tx_timer.function = bluesleep_tx_timer_expire;
+ tx_timer.data = 0;
+
+ /* initialize host wake tasklet */
+ tasklet_init(&hostwake_task, hostwake_interrupt, 0);
+
+ if (bsi->irq_polarity == POLARITY_LOW) {
+ ret = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
+ IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+ "bluetooth hostwake", NULL);
+ } else {
+ ret = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
+ IRQF_DISABLED | IRQF_TRIGGER_RISING,
+ "bluetooth hostwake", NULL);
+ }
+ if (ret < 0) {
+ BT_ERR("Couldn't acquire BT_HOST_WAKE IRQ");
+ goto delete_timer;
+ }
+
+ ret = enable_irq_wake(bsi->host_wake_irq);
+ if (ret < 0) {
+ BT_ERR("Couldn't enable BT_HOST_WAKE as wakeup interrupt");
+ goto free_host_wake_irq;
+ }
+
+ return 0;
+
+free_host_wake_irq:
+ free_irq(bsi->host_wake_irq, NULL);
+delete_timer:
+ del_timer(&tx_timer);
+gpio_ext_wake:
+ gpio_free(bsi->ext_wake);
+gpio_host_wake:
+ gpio_free(bsi->host_wake);
+gpio_config_failed:
+ return ret;
+}
+
/* Initialize protocol */
static int ath_open(struct hci_uart *hu)
{
struct ath_struct *ath;
- BT_DBG("hu %p", hu);
+ BT_DBG("hu %p, bsi %p", hu, bsi);
+
+ if (!bsi)
+ return -EIO;
+
+ if (ath_bluesleep_gpio_config(1) < 0) {
+ BT_ERR("HCIATH3K GPIO Config failed");
+ return -EIO;
+ }
ath = kzalloc(sizeof(*ath), GFP_ATOMIC);
if (!ath)
@@ -190,6 +292,9 @@
hu->priv = NULL;
kfree(ath);
+ if (bsi)
+ ath_bluesleep_gpio_config(0);
+
return 0;
}
@@ -200,6 +305,8 @@
{
struct ath_struct *ath = hu->priv;
+ BT_DBG("");
+
if (bt_cb(skb)->pkt_type == HCI_SCODATA_PKT) {
kfree_skb(skb);
return 0;
@@ -243,6 +350,8 @@
struct ath_struct *ath = hu->priv;
unsigned int type;
+ BT_DBG("");
+
if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
BT_ERR("Frame Reassembly Failed");
@@ -260,7 +369,7 @@
if (type == HCI_EVENT_PKT) {
clear_bit(BT_SLEEPCMD, &flags);
- printk(KERN_INFO "cur_sleep:%d\n", ath->cur_sleep);
+ BT_INFO("cur_sleep:%d\n", ath->cur_sleep);
if (ath->cur_sleep == 1)
set_bit(BT_SLEEPENABLE, &flags);
else
@@ -276,19 +385,11 @@
{
if (!test_bit(BT_SLEEPENABLE, &flags))
return;
- BT_DBG("Tx timer expired");
- printk(KERN_INFO "Tx timer expired\n");
+ BT_INFO("Tx timer expired\n");
set_bit(BT_TXEXPIRED, &flags);
}
-static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id)
-{
- /* schedule a tasklet to handle the change in the host wake line */
- tasklet_schedule(&hostwake_task);
- return IRQ_HANDLED;
-}
-
static struct hci_uart_proto athp = {
.id = HCI_UART_ATH3K,
.open = ath_open,
@@ -304,6 +405,8 @@
int ret;
struct resource *res;
+ BT_DBG("");
+
bsi = kzalloc(sizeof(struct bluesleep_info), GFP_KERNEL);
if (!bsi) {
ret = -ENOMEM;
@@ -319,107 +422,35 @@
}
bsi->host_wake = res->start;
- ret = gpio_request(bsi->host_wake, "bt_host_wake");
- if (ret)
- goto free_bsi;
-
- /* configure host_wake as input */
- ret = gpio_direction_input(bsi->host_wake);
- if (ret < 0) {
- pr_err("%s: gpio_direction_input failed for GPIO %d, error %d\n",
- __func__, bsi->host_wake, ret);
- gpio_free(bsi->host_wake);
- goto free_bsi;
- }
-
res = platform_get_resource_byname(pdev, IORESOURCE_IO,
"gpio_ext_wake");
if (!res) {
BT_ERR("couldn't find ext_wake gpio\n");
ret = -ENODEV;
- goto free_bt_host_wake;
+ goto free_bsi;
}
bsi->ext_wake = res->start;
- ret = gpio_request(bsi->ext_wake, "bt_ext_wake");
- if (ret)
- goto free_bt_host_wake;
-
- /* configure ext_wake as output mode*/
- ret = gpio_direction_output(bsi->ext_wake, 1);
- if (ret < 0) {
- pr_err("%s: gpio_direction_output failed for GPIO %d, error %d\n",
- __func__, bsi->ext_wake, ret);
- gpio_free(bsi->ext_wake);
- goto free_bt_host_wake;
- }
- gpio_set_value(bsi->ext_wake, 1);
-
bsi->host_wake_irq = platform_get_irq_byname(pdev, "host_wake");
if (bsi->host_wake_irq < 0) {
BT_ERR("couldn't find host_wake irq\n");
ret = -ENODEV;
- goto free_bt_ext_wake;
+ goto free_bsi;
}
bsi->irq_polarity = POLARITY_LOW; /* low edge (falling edge) */
- /* Initialize spinlock. */
- spin_lock_init(&rw_lock);
-
- /* Initialize timer */
- init_timer(&tx_timer);
- tx_timer.function = bluesleep_tx_timer_expire;
- tx_timer.data = 0;
-
- /* initialize host wake tasklet */
- tasklet_init(&hostwake_task, hostwake_interrupt, 0);
-
- if (bsi->irq_polarity == POLARITY_LOW) {
- ret = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
- IRQF_DISABLED | IRQF_TRIGGER_FALLING,
- "bluetooth hostwake", NULL);
- } else {
- ret = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
- IRQF_DISABLED | IRQF_TRIGGER_RISING,
- "bluetooth hostwake", NULL);
- }
- if (ret < 0) {
- BT_ERR("Couldn't acquire BT_HOST_WAKE IRQ");
- goto free_bt_timer;
- }
-
- ret = enable_irq_wake(bsi->host_wake_irq);
- if (ret < 0) {
- BT_ERR("Couldn't enable BT_HOST_WAKE as wakeup interrupt");
- free_irq(bsi->host_wake_irq, NULL);
- goto free_bt_timer;
- }
-
return 0;
-free_bt_timer:
- del_timer(&tx_timer);
-free_bt_ext_wake:
- gpio_free(bsi->ext_wake);
-free_bt_host_wake:
- gpio_free(bsi->host_wake);
free_bsi:
kfree(bsi);
+ bsi = NULL;
failed:
return ret;
}
static int bluesleep_remove(struct platform_device *pdev)
{
- /* assert bt wake */
- gpio_set_value(bsi->ext_wake, 0);
- if (disable_irq_wake(bsi->host_wake_irq))
- BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n");
- free_irq(bsi->host_wake_irq, NULL);
- del_timer_sync(&tx_timer);
- gpio_free(bsi->host_wake);
- gpio_free(bsi->ext_wake);
kfree(bsi);
return 0;
}
diff --git a/drivers/bluetooth/hci_ibs.c b/drivers/bluetooth/hci_ibs.c
index fb084f5..6253605 100644
--- a/drivers/bluetooth/hci_ibs.c
+++ b/drivers/bluetooth/hci_ibs.c
@@ -112,6 +112,13 @@
unsigned long rx_vote; /* clock must be on for RX */
struct timer_list tx_idle_timer;
struct timer_list wake_retrans_timer;
+ struct workqueue_struct *workqueue;
+ struct work_struct ws_awake_rx;
+ struct work_struct ws_awake_device;
+ struct work_struct ws_rx_vote_off;
+ struct work_struct ws_tx_vote_off;
+ void *ibs_hu; /* keeps the hci_uart pointer for reference */
+
/* debug */
unsigned long ibs_sent_wacks;
unsigned long ibs_sent_slps;
@@ -242,12 +249,90 @@
return err;
}
+static void ibs_wq_awake_device(struct work_struct *work)
+{
+ struct ibs_struct *ibs = container_of(work, struct ibs_struct,
+ ws_awake_device);
+ struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;
+
+ BT_DBG(" %p ", hu);
+
+ /* Vote for serial clock */
+ ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu);
+
+ spin_lock(&ibs->hci_ibs_lock);
+
+ /* send wake indication to device */
+ if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0)
+ BT_ERR("cannot send WAKE to device");
+
+ ibs->ibs_sent_wakes++; /* debug */
+
+ /* start retransmit timer */
+ mod_timer(&ibs->wake_retrans_timer, jiffies + wake_retrans);
+
+ spin_unlock(&ibs->hci_ibs_lock);
+}
+
+static void ibs_wq_awake_rx(struct work_struct *work)
+{
+ struct ibs_struct *ibs = container_of(work, struct ibs_struct,
+ ws_awake_rx);
+ struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;
+
+ BT_DBG(" %p ", hu);
+
+ ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);
+
+ spin_lock(&ibs->hci_ibs_lock);
+ ibs->rx_ibs_state = HCI_IBS_RX_AWAKE;
+ /* Always acknowledge device wake up,
+ * sending IBS message doesn't count as TX ON
+ */
+ if (send_hci_ibs_cmd(HCI_IBS_WAKE_ACK, hu) < 0)
+ BT_ERR("cannot acknowledge device wake up");
+
+ ibs->ibs_sent_wacks++; /* debug */
+
+ spin_unlock(&ibs->hci_ibs_lock);
+ /* actually send the packets */
+ hci_uart_tx_wakeup(hu);
+
+}
+
+static void ibs_wq_serial_rx_clock_vote_off(struct work_struct *work)
+{
+ struct ibs_struct *ibs = container_of(work, struct ibs_struct,
+ ws_rx_vote_off);
+ struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;
+
+ BT_DBG(" %p ", hu);
+
+ ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_OFF, hu);
+
+}
+
+static void ibs_wq_serial_tx_clock_vote_off(struct work_struct *work)
+{
+ struct ibs_struct *ibs = container_of(work, struct ibs_struct,
+ ws_tx_vote_off);
+ struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;
+
+ BT_DBG(" %p ", hu);
+
+ hci_uart_tx_wakeup(hu); /* run HCI tx handling unlocked */
+
+ /* now that message queued to tty driver, vote for tty clocks off */
+ /* It is up to the tty driver to pend the clocks off until tx done. */
+ ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu);
+
+}
+
static void hci_ibs_tx_idle_timeout(unsigned long arg)
{
struct hci_uart *hu = (struct hci_uart *) arg;
struct ibs_struct *ibs = hu->priv;
unsigned long flags;
- unsigned long vote_tx_sleep = 0;
BT_DBG("hu %p idle timeout in %lu state", hu, ibs->tx_ibs_state);
@@ -267,22 +352,11 @@
}
ibs->tx_ibs_state = HCI_IBS_TX_ASLEEP;
ibs->ibs_sent_slps++; /* debug */
- vote_tx_sleep = 1;
break;
}
- spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
+ queue_work(ibs->workqueue, &ibs->ws_tx_vote_off);
- hci_uart_tx_wakeup(hu); /* run HCI tx handling unlocked */
-
- if (!vote_tx_sleep)
- return;
- /* now that message queued to tty driver, vote for tty clocks off */
- /* It is up to the tty driver to pend the clocks off until tx done. */
-
- spin_lock_irqsave_nested(&ibs->hci_ibs_lock,
- flags, SINGLE_DEPTH_NESTING);
- ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu);
out:
spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
}
@@ -336,6 +410,19 @@
skb_queue_head_init(&ibs->txq);
skb_queue_head_init(&ibs->tx_wait_q);
spin_lock_init(&ibs->hci_ibs_lock);
+ ibs->workqueue = create_singlethread_workqueue("ibs_wq");
+ if (!ibs->workqueue) {
+ BT_ERR("IBS Workqueue not initialized properly");
+ kfree(ibs);
+ return -ENOMEM;
+ }
+
+ INIT_WORK(&ibs->ws_awake_rx, ibs_wq_awake_rx);
+ INIT_WORK(&ibs->ws_awake_device, ibs_wq_awake_device);
+ INIT_WORK(&ibs->ws_rx_vote_off, ibs_wq_serial_rx_clock_vote_off);
+ INIT_WORK(&ibs->ws_tx_vote_off, ibs_wq_serial_tx_clock_vote_off);
+
+ ibs->ibs_hu = (void *)hu;
/* Assume we start with both sides asleep -- extra wakes OK */
ibs->tx_ibs_state = HCI_IBS_TX_ASLEEP;
@@ -432,6 +519,8 @@
skb_queue_purge(&ibs->txq);
del_timer(&ibs->tx_idle_timer);
del_timer(&ibs->wake_retrans_timer);
+ destroy_workqueue(ibs->workqueue);
+ ibs->ibs_hu = NULL;
kfree_skb(ibs->rx_skb);
@@ -463,9 +552,10 @@
/* Make sure clock is on - we may have turned clock off since
* receiving the wake up indicator
*/
- ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);
- ibs->rx_ibs_state = HCI_IBS_RX_AWAKE;
- /* deliberate fall-through */
+ /* awake rx clock */
+ queue_work(ibs->workqueue, &ibs->ws_awake_rx);
+ spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
+ return;
case HCI_IBS_RX_AWAKE:
/* Always acknowledge device wake up,
* sending IBS message doesn't count as TX ON.
@@ -510,7 +600,8 @@
case HCI_IBS_RX_AWAKE:
/* update state */
ibs->rx_ibs_state = HCI_IBS_RX_ASLEEP;
- ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_OFF, hu);
+ /* vote off rx clock under workqueue */
+ queue_work(ibs->workqueue, &ibs->ws_rx_vote_off);
break;
case HCI_IBS_RX_ASLEEP:
/* deliberate fall-through */
@@ -595,20 +686,12 @@
case HCI_IBS_TX_ASLEEP:
BT_DBG("device asleep, waking up and queueing packet");
- ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu);
/* save packet for later */
skb_queue_tail(&ibs->tx_wait_q, skb);
- /* awake device */
- if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0) {
- BT_ERR("cannot send WAKE to device");
- break;
- }
- ibs->ibs_sent_wakes++; /* debug */
-
- /* start retransmit timer */
- mod_timer(&ibs->wake_retrans_timer, jiffies + wake_retrans);
ibs->tx_ibs_state = HCI_IBS_TX_WAKING;
+ /* schedule a work queue to wake up device */
+ queue_work(ibs->workqueue, &ibs->ws_awake_device);
break;
case HCI_IBS_TX_WAKING:
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 0febaf3..4495eb0 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -35,6 +35,8 @@
#define POOL_TYPE_COPY 1
#define POOL_TYPE_HDLC 2
#define POOL_TYPE_WRITE_STRUCT 4
+#define POOL_TYPE_HSIC 8
+#define POOL_TYPE_HSIC_WRITE 16
#define POOL_TYPE_ALL 7
#define MODEM_DATA 1
#define QDSP_DATA 2
@@ -272,20 +274,20 @@
unsigned char *buf_in_smux;
int in_busy_smux;
int diag_smux_enabled;
+ int smux_connected;
+ struct diag_request *write_ptr_mdm;
/* HSIC variables */
- unsigned char *buf_in_hsic;
int hsic_ch;
int hsic_device_enabled;
int hsic_device_opened;
int hsic_suspend;
int in_busy_hsic_read_on_device;
- int in_busy_hsic_write_on_device;
int in_busy_hsic_write;
- int in_busy_hsic_read;
struct work_struct diag_read_hsic_work;
/* USB MDM channel variables */
int usb_mdm_connected;
int read_len_mdm;
+ int write_len_mdm;
unsigned char *usb_buf_mdm_out;
struct usb_diag_ch *mdm_ch;
struct workqueue_struct *diag_bridge_wq;
@@ -293,7 +295,16 @@
struct work_struct diag_disconnect_work;
struct work_struct diag_usb_read_complete_work;
struct diag_request *usb_read_mdm_ptr;
- struct diag_request *write_ptr_mdm;
+ int count_hsic_pool;
+ int count_hsic_write_pool;
+ unsigned int poolsize_hsic;
+ unsigned int poolsize_hsic_write;
+ unsigned int itemsize_hsic;
+ unsigned int itemsize_hsic_write;
+ mempool_t *diag_hsic_pool;
+ mempool_t *diag_hsic_write_pool;
+ int num_hsic_buf_tbl_entries;
+ struct diag_write_device *hsic_buf_tbl;
#endif
};
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 30504bc..2dc1929 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -243,6 +243,17 @@
driver->logging_mode = USB_MODE;
diagfwd_connect();
#ifdef CONFIG_DIAG_BRIDGE_CODE
+ driver->num_hsic_buf_tbl_entries = 0;
+ for (i = 0; i < driver->poolsize_hsic_write; i++) {
+ if (driver->hsic_buf_tbl[i].buf) {
+ /* Return the buffer to the pool */
+ diagmem_free(driver, (unsigned char *)
+ (driver->hsic_buf_tbl[i].buf),
+ POOL_TYPE_HSIC);
+ driver->hsic_buf_tbl[i].buf = 0;
+ driver->hsic_buf_tbl[i].length = 0;
+ }
+ }
diagfwd_cancel_hsic();
diagfwd_connect_bridge(0);
#endif
@@ -528,6 +539,17 @@
driver->in_busy_sdio = 1;
#endif
#ifdef CONFIG_DIAG_BRIDGE_CODE
+ driver->num_hsic_buf_tbl_entries = 0;
+ for (i = 0; i < driver->poolsize_hsic_write; i++) {
+ if (driver->hsic_buf_tbl[i].buf) {
+ /* Return the buffer to the pool */
+ diagmem_free(driver, (unsigned char *)
+ (driver->hsic_buf_tbl[i].buf),
+ POOL_TYPE_HSIC);
+ driver->hsic_buf_tbl[i].buf = 0;
+ driver->hsic_buf_tbl[i].length = 0;
+ }
+ }
diagfwd_disconnect_bridge(0);
#endif
} else if (temp == NO_LOGGING_MODE && driver->logging_mode
@@ -556,6 +578,11 @@
&(driver->diag_read_sdio_work));
#endif
#ifdef CONFIG_DIAG_BRIDGE_CODE
+ driver->num_hsic_buf_tbl_entries = 0;
+ for (i = 0; i < driver->poolsize_hsic_write; i++) {
+ driver->hsic_buf_tbl[i].buf = 0;
+ driver->hsic_buf_tbl[i].length = 0;
+ }
diagfwd_connect_bridge(0);
#endif
}
@@ -581,6 +608,7 @@
driver->in_busy_qdsp_2 = 0;
driver->in_busy_wcnss_1 = 0;
driver->in_busy_wcnss_2 = 0;
+
/* Poll SMD channels to check for data*/
if (driver->ch)
queue_work(driver->diag_wq,
@@ -599,6 +627,11 @@
&(driver->diag_read_sdio_work));
#endif
#ifdef CONFIG_DIAG_BRIDGE_CODE
+ driver->num_hsic_buf_tbl_entries = 0;
+ for (i = 0; i < driver->poolsize_hsic_write; i++) {
+ driver->hsic_buf_tbl[i].buf = 0;
+ driver->hsic_buf_tbl[i].length = 0;
+ }
diagfwd_cancel_hsic();
diagfwd_connect_bridge(0);
#endif
@@ -606,6 +639,17 @@
driver->logging_mode == USB_MODE) {
diagfwd_connect();
#ifdef CONFIG_DIAG_BRIDGE_CODE
+ driver->num_hsic_buf_tbl_entries = 0;
+ for (i = 0; i < driver->poolsize_hsic_write; i++) {
+ if (driver->hsic_buf_tbl[i].buf) {
+ /* Return the buffer to the pool */
+ diagmem_free(driver, (unsigned char *)
+ (driver->hsic_buf_tbl[i].buf),
+ POOL_TYPE_HSIC);
+ driver->hsic_buf_tbl[i].buf = 0;
+ driver->hsic_buf_tbl[i].length = 0;
+ }
+ }
diagfwd_cancel_hsic();
diagfwd_connect_bridge(0);
#endif
@@ -767,20 +811,44 @@
}
#endif
#ifdef CONFIG_DIAG_BRIDGE_CODE
- pr_debug("diag: Copy data to user space %d\n",
- driver->in_busy_hsic_write_on_device);
- if (driver->in_busy_hsic_write_on_device == 1) {
- num_data++;
- /*Copy the length of data being passed*/
- COPY_USER_SPACE_OR_EXIT(buf+ret,
- (driver->write_ptr_mdm->length), 4);
- /*Copy the actual data being passed*/
- COPY_USER_SPACE_OR_EXIT(buf+ret,
- *(driver->buf_in_hsic),
- driver->write_ptr_mdm->length);
- pr_debug("diag: data copied\n");
- /* call the write complete function */
- diagfwd_write_complete_hsic();
+
+ for (i = 0; i < driver->poolsize_hsic_write; i++) {
+ if (driver->hsic_buf_tbl[i].length > 0) {
+ pr_debug("diag: HSIC copy to user, i: %d, buf: %x, len: %d\n",
+ i, (unsigned int)
+ (driver->hsic_buf_tbl[i].buf),
+ driver->hsic_buf_tbl[i].length);
+ num_data++;
+ /* Copy the length of data being passed */
+ if (copy_to_user(buf+ret, (void *)&(driver->
+ hsic_buf_tbl[i].length), 4)) {
+ num_data--;
+ goto drop_hsic;
+ }
+ ret += 4;
+
+ /* Copy the actual data being passed */
+ if (copy_to_user(buf+ret,
+ (void *)driver->hsic_buf_tbl[i].buf,
+ driver->hsic_buf_tbl[i].length)) {
+ ret -= 4;
+ num_data--;
+ goto drop_hsic;
+ }
+ ret += driver->hsic_buf_tbl[i].length;
+drop_hsic:
+ /* Return the buffer to the pool */
+ diagmem_free(driver, (unsigned char *)
+ (driver->hsic_buf_tbl[i].buf),
+ POOL_TYPE_HSIC);
+
+ driver->hsic_buf_tbl[i].length = 0;
+ driver->hsic_buf_tbl[i].buf = 0;
+ driver->num_hsic_buf_tbl_entries--;
+
+ /* Call the write complete function */
+ diagfwd_write_complete_hsic(NULL);
+ }
}
#endif
/* copy number of data fields */
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 5a74e8c..4419309 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -307,6 +307,26 @@
break;
}
}
+
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+ else if (proc_num == HSIC_DATA) {
+ for (i = 0; i < driver->poolsize_hsic_write; i++) {
+ if (driver->hsic_buf_tbl[i].length == 0) {
+ driver->hsic_buf_tbl[i].buf = buf;
+ driver->hsic_buf_tbl[i].length =
+ driver->write_len_mdm;
+ driver->num_hsic_buf_tbl_entries++;
+#ifdef DIAG_DEBUG
+ pr_debug("diag: ENQUEUE HSIC buf ptr and length is %x , %d\n",
+ (unsigned int)
+ (driver->hsic_buf_tbl[i].buf),
+ driver->hsic_buf_tbl[i].length);
+#endif
+ break;
+ }
+ }
+ }
+#endif
for (i = 0; i < driver->num_clients; i++)
if (driver->client_map[i].pid ==
driver->logging_process_id)
@@ -343,8 +363,6 @@
#endif
#ifdef CONFIG_DIAG_BRIDGE_CODE
else if (proc_num == HSIC_DATA) {
- driver->in_busy_hsic_read = 0;
- driver->in_busy_hsic_write_on_device = 0;
if (driver->hsic_ch)
queue_work(driver->diag_bridge_wq,
&(driver->diag_read_hsic_work));
@@ -396,11 +414,33 @@
#ifdef CONFIG_DIAG_BRIDGE_CODE
else if (proc_num == HSIC_DATA) {
if (driver->hsic_device_enabled) {
- write_ptr->buf = buf;
- err = usb_diag_write(driver->mdm_ch, write_ptr);
- } else
+ struct diag_request *write_ptr_mdm;
+ write_ptr_mdm = (struct diag_request *)
+ diagmem_alloc(driver,
+ sizeof(struct diag_request),
+ POOL_TYPE_HSIC_WRITE);
+ if (write_ptr_mdm) {
+ write_ptr_mdm->buf = buf;
+ write_ptr_mdm->length =
+ driver->write_len_mdm;
+ err = usb_diag_write(driver->mdm_ch,
+ write_ptr_mdm);
+ /* Return to the pool immediately */
+ if (err) {
+ diagmem_free(driver,
+ write_ptr_mdm,
+ POOL_TYPE_HSIC_WRITE);
+ pr_err("diag: HSIC write failure\n");
+ }
+ } else {
+ pr_err("diag: allocate write fail\n");
+ err = -1;
+ }
+ } else {
pr_err("diag: Incorrect hsic data "
"while USB write\n");
+ err = -1;
+ }
} else if (proc_num == SMUX_DATA) {
write_ptr->buf = buf;
pr_debug("diag: writing SMUX data\n");
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 95abd21..52fd673 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -401,7 +401,8 @@
"in_busy_qdsp_2: %d\n"
"in_busy_wcnss_1: %d\n"
"in_busy_wcnss_2: %d\n"
- "in_busy_dci: %d\n",
+ "in_busy_dci: %d\n"
+ "logging_mode: %d\n",
(unsigned int)driver->ch,
(unsigned int)driver->chqdsp,
(unsigned int)driver->ch_wcnss,
@@ -421,7 +422,8 @@
driver->in_busy_qdsp_2,
driver->in_busy_wcnss_1,
driver->in_busy_wcnss_2,
- driver->in_busy_dci);
+ driver->in_busy_dci,
+ driver->logging_mode);
#ifdef CONFIG_DIAG_OVER_USB
ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
@@ -541,7 +543,7 @@
return ret;
}
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
static ssize_t diag_dbgfs_read_hsic(struct file *file, char __user *ubuf,
size_t count, loff_t *ppos)
{
@@ -555,29 +557,35 @@
}
ret = scnprintf(buf, DEBUG_BUF_SIZE,
- "hsic initialized: %d\n"
"hsic ch: %d\n"
"hsic enabled: %d\n"
"hsic_opened: %d\n"
- "hisc_suspend: %d\n"
- "in_busy_hsic_read_on_mdm: %d\n"
- "in_busy_hsic_write_on_mdm: %d\n"
+ "hsic_suspend: %d\n"
+ "in_busy_hsic_read_on_device: %d\n"
"in_busy_hsic_write: %d\n"
- "in_busy_hsic_read: %d\n"
+ "count_hsic_pool: %d\n"
+ "count_hsic_write_pool: %d\n"
+ "diag_hsic_pool: %x\n"
+ "diag_hsic_write_pool: %x\n"
+ "write_len_mdm: %d\n"
+ "num_hsic_buf_tbl_entries: %d\n"
"usb_mdm_connected: %d\n"
"diag_read_mdm_work: %d\n"
"diag_read_hsic_work: %d\n"
"diag_disconnect_work: %d\n"
"diag_usb_read_complete_work: %d\n",
- driver->hsic_initialized,
driver->hsic_ch,
driver->hsic_device_enabled,
driver->hsic_device_opened,
driver->hsic_suspend,
driver->in_busy_hsic_read_on_device,
- driver->in_busy_hsic_write_on_device,
driver->in_busy_hsic_write,
- driver->in_busy_hsic_read,
+ driver->count_hsic_pool,
+ driver->count_hsic_write_pool,
+ (unsigned int)driver->diag_hsic_pool,
+ (unsigned int)driver->diag_hsic_write_pool,
+ driver->write_len_mdm,
+ driver->num_hsic_buf_tbl_entries,
driver->usb_mdm_connected,
work_pending(&(driver->diag_read_mdm_work)),
work_pending(&(driver->diag_read_hsic_work)),
@@ -622,7 +630,7 @@
debugfs_create_file("work_pending", 0444, diag_dbgfs_dent, 0,
&diag_dbgfs_workpending_ops);
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
debugfs_create_file("hsic", 0444, diag_dbgfs_dent, 0,
&diag_dbgfs_hsic_ops);
#endif
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index fedcf03..54a667e 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -32,48 +32,87 @@
#include "diagfwd_hsic.h"
#include "diagfwd_smux.h"
+#define N_MDM_WRITE 8
+#define N_MDM_READ 1
+
+#define READ_HSIC_BUF_SIZE 2048
+
+#define NUM_HSIC_BUF_TBL_ENTRIES N_MDM_WRITE
+
static void diag_read_hsic_work_fn(struct work_struct *work)
{
+ unsigned char *buf_in_hsic = NULL;
+ int num_reads_submitted = 0;
+ int err = 0;
+ int write_ptrs_available;
+
if (!driver->hsic_ch) {
pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
return;
}
- /* If there is no hsic data being read from the hsic and there
- * is no hsic data being written to the device
+ /*
+ * Determine the current number of available buffers for writing after
+ * reading from the HSIC has completed.
*/
- if (!driver->in_busy_hsic_read &&
- !driver->in_busy_hsic_write_on_device) {
- /*
- * Initiate the read from the hsic. The hsic read is
- * asynchronous. Once the read is complete the read
- * callback function will be called.
- */
- int err;
- driver->in_busy_hsic_read = 1;
- APPEND_DEBUG('i');
- pr_debug("diag: read from HSIC\n");
- err = diag_bridge_read((char *)driver->buf_in_hsic,
- IN_BUF_SIZE);
- if (err) {
- pr_err_ratelimited("DIAG: Error initiating HSIC read, err: %d\n",
- err);
- /*
- * If the error is recoverable, then clear
- * the read flag, so we will resubmit a
- * read on the next frame. Otherwise, don't
- * resubmit a read on the next frame.
- */
- if ((-ENODEV) != err)
- driver->in_busy_hsic_read = 0;
- }
- }
+ if (driver->logging_mode == MEMORY_DEVICE_MODE)
+ write_ptrs_available = driver->poolsize_hsic_write -
+ driver->num_hsic_buf_tbl_entries;
+ else
+ write_ptrs_available = driver->poolsize_hsic_write -
+ driver->count_hsic_write_pool;
/*
- * If for some reason there was no hsic data, set up
- * the next read
+ * Queue up a read on the HSIC for all available buffers in the
+ * pool, exhausting the pool.
*/
- if (!driver->in_busy_hsic_read)
+ do {
+ /*
+ * If no more write buffers are available,
+ * stop queuing reads
+ */
+ if (write_ptrs_available <= 0)
+ break;
+
+ write_ptrs_available--;
+
+ buf_in_hsic = diagmem_alloc(driver, READ_HSIC_BUF_SIZE,
+ POOL_TYPE_HSIC);
+ if (buf_in_hsic) {
+ /*
+ * Initiate the read from the hsic. The hsic read is
+ * asynchronous. Once the read is complete the read
+ * callback function will be called.
+ */
+ int err;
+ pr_debug("diag: read from HSIC\n");
+ num_reads_submitted++;
+ err = diag_bridge_read((char *)buf_in_hsic,
+ READ_HSIC_BUF_SIZE);
+ if (err) {
+ num_reads_submitted--;
+
+ /* Return the buffer to the pool */
+ diagmem_free(driver, buf_in_hsic,
+ POOL_TYPE_HSIC);
+
+ pr_err_ratelimited("diag: Error initiating HSIC read, err: %d\n",
+ err);
+ /*
+ * An error occurred, discontinue queuing
+ * reads
+ */
+ break;
+ }
+ }
+ } while (buf_in_hsic);
+
+ /*
+ * If there are no buffers available or for some reason there
+ * was no hsic data, and if no unrecoverable error occurred
+ * (-ENODEV is an unrecoverable error), then set up the next read
+ */
+ if ((num_reads_submitted == 0) && (err != -ENODEV))
queue_work(driver->diag_bridge_wq,
&driver->diag_read_hsic_work);
}
@@ -81,45 +120,58 @@
static void diag_hsic_read_complete_callback(void *ctxt, char *buf,
int buf_size, int actual_size)
{
- /* The read of the data from the HSIC bridge is complete */
- driver->in_busy_hsic_read = 0;
+ int err = -2;
if (!driver->hsic_ch) {
- pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
+ /*
+ * The hsic channel is closed. Return the buffer to
+ * the pool. Do not send it on.
+ */
+ diagmem_free(driver, buf, POOL_TYPE_HSIC);
+ pr_debug("diag: In %s: driver->hsic_ch == 0, actual_size: %d\n",
+ __func__, actual_size);
return;
}
- APPEND_DEBUG('j');
- if (actual_size > 0) {
+ /* Note that zero length is valid and still needs to be sent */
+ if (actual_size >= 0) {
if (!buf) {
- pr_err("Out of diagmem for HSIC\n");
+ pr_err("diag: Out of diagmem for HSIC\n");
} else {
- driver->write_ptr_mdm->length = actual_size;
/*
- * Set flag to denote hsic data is currently
- * being written to the usb mdm channel.
- * driver->buf_in_hsic was given to
- * diag_bridge_read(), so buf here should be
- * driver->buf_in_hsic
+ * Send data in buf to be written on the
+ * appropriate device, e.g. USB MDM channel
*/
- driver->in_busy_hsic_write_on_device = 1;
- pr_debug("diag: write to device\n");
- diag_device_write((void *)buf, HSIC_DATA,
- driver->write_ptr_mdm);
+ driver->write_len_mdm = actual_size;
+ err = diag_device_write((void *)buf, HSIC_DATA, NULL);
+ /* If an error, return buffer to the pool */
+ if (err) {
+ diagmem_free(driver, buf, POOL_TYPE_HSIC);
+ pr_err("diag: In %s, error calling diag_device_write, err: %d\n",
+ __func__, err);
+ }
}
} else {
- pr_debug("%s: actual_size: %d\n", __func__, actual_size);
+ /*
+ * The buffer has an error status associated with it. Do not
+ * pass it on. Note that -ENOENT is sent when the diag bridge
+ * is closed.
+ */
+ diagmem_free(driver, buf, POOL_TYPE_HSIC);
+ pr_debug("diag: In %s: error status: %d\n", __func__,
+ actual_size);
}
/*
* If for some reason there was no hsic data to write to the
* mdm channel, set up another read
*/
- if (!driver->in_busy_hsic_write_on_device && ((driver->logging_mode
- == MEMORY_DEVICE_MODE) || (driver->usb_mdm_connected &&
- !driver->hsic_suspend)))
+ if (err &&
+ ((driver->logging_mode == MEMORY_DEVICE_MODE) ||
+ (driver->usb_mdm_connected && !driver->hsic_suspend))) {
queue_work(driver->diag_bridge_wq,
&driver->diag_read_hsic_work);
+ }
}
static void diag_hsic_write_complete_callback(void *ctxt, char *buf,
@@ -143,6 +195,8 @@
static int diag_hsic_suspend(void *ctxt)
{
pr_debug("diag: hsic_suspend\n");
+
+ /* Don't allow suspend if a write in the HSIC is in progress */
if (driver->in_busy_hsic_write)
return -EBUSY;
@@ -160,8 +214,8 @@
pr_debug("diag: hsic_resume\n");
driver->hsic_suspend = 0;
- if (!driver->in_busy_hsic_write_on_device && (driver->logging_mode
- == MEMORY_DEVICE_MODE || driver->usb_mdm_connected))
+ if ((driver->logging_mode == MEMORY_DEVICE_MODE) ||
+ (driver->usb_mdm_connected))
queue_work(driver->diag_bridge_wq,
&driver->diag_read_hsic_work);
}
@@ -202,10 +256,10 @@
diag_bridge_close();
err = diag_bridge_open(&hsic_diag_bridge_ops);
if (err) {
- pr_err("DIAG: HSIC channel open error: %d\n",
+ pr_err("diag: HSIC channel open error: %d\n",
err);
} else {
- pr_debug("DIAG: opened HSIC channel\n");
+ pr_debug("diag: opened HSIC channel\n");
driver->hsic_device_opened = 1;
driver->hsic_ch = 1;
}
@@ -234,10 +288,8 @@
}
if (driver->hsic_device_enabled) {
- driver->in_busy_hsic_write_on_device = 0;
driver->in_busy_hsic_read_on_device = 0;
driver->in_busy_hsic_write = 0;
- driver->in_busy_hsic_read = 0;
} else if (driver->diag_smux_enabled) {
driver->in_busy_smux = 0;
diagfwd_connect_smux();
@@ -288,7 +340,7 @@
*/
int diagfwd_disconnect_bridge(int process_cable)
{
- pr_debug("DIAG in %s\n", __func__);
+ pr_debug("diag: In %s, process_cable: %d\n", __func__, process_cable);
/* If the usb cable is being disconnected */
if (process_cable) {
@@ -296,17 +348,16 @@
usb_diag_free_req(driver->mdm_ch);
}
- if (driver->logging_mode != MEMORY_DEVICE_MODE) {
+ if (driver->logging_mode == USB_MODE) {
if (driver->hsic_device_enabled) {
- driver->in_busy_hsic_write_on_device = 1;
driver->in_busy_hsic_read_on_device = 1;
driver->in_busy_hsic_write = 1;
- driver->in_busy_hsic_read = 1;
/* Turn off communication over usb mdm and hsic */
return diag_hsic_close();
} else if (driver->diag_smux_enabled) {
driver->in_busy_smux = 1;
driver->lcid = LCID_INVALID;
+ driver->smux_connected = 0;
/* Turn off communication over usb mdm and smux */
msm_smux_close(LCID_VALID);
}
@@ -318,19 +369,21 @@
* diagfwd_write_complete_hsic is called after the asynchronous
* usb_diag_write() on mdm channel is complete
*/
-int diagfwd_write_complete_hsic(void)
+int diagfwd_write_complete_hsic(struct diag_request *diag_write_ptr)
{
- /*
- * Clear flag to denote that the write of the hsic data on the
- * usb mdm channel is complete
- */
- driver->in_busy_hsic_write_on_device = 0;
- if (!driver->hsic_ch) {
- pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
- return 0;
+ unsigned char *buf = (diag_write_ptr) ? diag_write_ptr->buf : NULL;
+
+ if (buf) {
+ /* Return buffers to their pools */
+ diagmem_free(driver, (unsigned char *)buf, POOL_TYPE_HSIC);
+ diagmem_free(driver, (unsigned char *)diag_write_ptr,
+ POOL_TYPE_HSIC_WRITE);
}
- APPEND_DEBUG('q');
+ if (!driver->hsic_ch) {
+ pr_err("diag: In %s: driver->hsic_ch == 0\n", __func__);
+ return 0;
+ }
/* Read data from the hsic */
queue_work(driver->diag_bridge_wq, &driver->diag_read_hsic_work);
@@ -374,7 +427,7 @@
err = diag_bridge_write(driver->usb_buf_mdm_out,
driver->read_len_mdm);
if (err) {
- pr_err_ratelimited("DIAG: mdm data on hsic write err: %d\n",
+ pr_err_ratelimited("diag: mdm data on hsic write err: %d\n",
err);
/*
* If the error is recoverable, then clear
@@ -414,7 +467,7 @@
break;
case USB_DIAG_WRITE_DONE:
if (driver->hsic_device_enabled)
- diagfwd_write_complete_hsic();
+ diagfwd_write_complete_hsic(d_req);
else if (driver->diag_smux_enabled)
diagfwd_write_complete_smux();
break;
@@ -440,7 +493,8 @@
int ret;
if (driver->diag_smux_enabled) {
if (driver->lcid && driver->usb_buf_mdm_out &&
- (driver->read_len_mdm > 0)) {
+ (driver->read_len_mdm > 0) &&
+ driver->smux_connected) {
ret = msm_smux_write(driver->lcid, NULL,
driver->usb_buf_mdm_out, driver->read_len_mdm);
if (ret)
@@ -490,8 +544,7 @@
int err = 0;
pr_debug("diag: in %s\n", __func__);
if (!driver->hsic_device_enabled) {
- if (driver->buf_in_hsic == NULL)
- driver->buf_in_hsic = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
+ diagmem_hsic_init(driver);
INIT_WORK(&(driver->diag_read_hsic_work),
diag_read_hsic_work_fn);
driver->hsic_device_enabled = 1;
@@ -515,10 +568,9 @@
pr_info("diag: opened HSIC channel\n");
driver->hsic_device_opened = 1;
driver->hsic_ch = 1;
- driver->in_busy_hsic_write_on_device = 0;
+
driver->in_busy_hsic_read_on_device = 0;
driver->in_busy_hsic_write = 0;
- driver->in_busy_hsic_read = 0;
if (driver->usb_mdm_connected) {
/* Poll USB mdm channel to check for data */
@@ -536,7 +588,7 @@
static int diag_hsic_remove(struct platform_device *pdev)
{
- pr_debug("DIAG: %s called\n", __func__);
+ pr_debug("diag: %s called\n", __func__);
diag_hsic_close();
return 0;
}
@@ -576,11 +628,14 @@
driver->diag_bridge_wq = create_singlethread_workqueue(
"diag_bridge_wq");
driver->read_len_mdm = 0;
+ driver->write_len_mdm = 0;
+ driver->num_hsic_buf_tbl_entries = 0;
if (driver->usb_buf_mdm_out == NULL)
driver->usb_buf_mdm_out = kzalloc(USB_MAX_OUT_BUF,
GFP_KERNEL);
if (driver->usb_buf_mdm_out == NULL)
goto err;
+ /* Only used by smux move to smux probe function */
if (driver->write_ptr_mdm == NULL)
driver->write_ptr_mdm = kzalloc(
sizeof(struct diag_request), GFP_KERNEL);
@@ -592,6 +647,20 @@
if (driver->usb_read_mdm_ptr == NULL)
goto err;
+ if (driver->hsic_buf_tbl == NULL)
+ driver->hsic_buf_tbl = kzalloc(NUM_HSIC_BUF_TBL_ENTRIES *
+ sizeof(struct diag_write_device), GFP_KERNEL);
+ if (driver->hsic_buf_tbl == NULL)
+ goto err;
+
+ driver->count_hsic_pool = 0;
+ driver->count_hsic_write_pool = 0;
+
+ driver->itemsize_hsic = READ_HSIC_BUF_SIZE;
+ driver->poolsize_hsic = N_MDM_WRITE;
+ driver->itemsize_hsic_write = sizeof(struct diag_request);
+ driver->poolsize_hsic_write = N_MDM_WRITE;
+
#ifdef CONFIG_DIAG_OVER_USB
INIT_WORK(&(driver->diag_read_mdm_work), diag_read_mdm_work_fn);
#endif
@@ -606,10 +675,6 @@
goto err;
}
#endif
-#ifdef CONFIG_DIAG_BRIDGE_CODE
- INIT_WORK(&(driver->diag_disconnect_work), diag_disconnect_work_fn);
- INIT_WORK(&(driver->diag_usb_read_complete_work),
- diag_usb_read_complete_fn);
/* register HSIC device */
ret = platform_driver_register(&msm_hsic_ch_driver);
if (ret)
@@ -618,11 +683,12 @@
ret = platform_driver_register(&msm_diagfwd_smux_driver);
if (ret)
pr_err("diag: could not register SMUX device, ret: %d\n", ret);
-#endif
+
return;
err:
pr_err("diag: Could not initialize for bridge forwarding\n");
kfree(driver->usb_buf_mdm_out);
+ kfree(driver->hsic_buf_tbl);
kfree(driver->write_ptr_mdm);
kfree(driver->usb_read_mdm_ptr);
if (driver->diag_bridge_wq)
@@ -637,8 +703,8 @@
if (driver->hsic_device_enabled) {
diag_hsic_close();
- kfree(driver->buf_in_hsic);
driver->hsic_device_enabled = 0;
+ diagmem_exit(driver, POOL_TYPE_ALL);
}
if (driver->diag_smux_enabled) {
driver->lcid = LCID_INVALID;
@@ -654,6 +720,7 @@
usb_diag_close(driver->mdm_ch);
#endif
kfree(driver->usb_buf_mdm_out);
+ kfree(driver->hsic_buf_tbl);
kfree(driver->write_ptr_mdm);
kfree(driver->usb_read_mdm_ptr);
destroy_workqueue(driver->diag_bridge_wq);
diff --git a/drivers/char/diag/diagfwd_hsic.h b/drivers/char/diag/diagfwd_hsic.h
index b189c94..b2d9c9f 100644
--- a/drivers/char/diag/diagfwd_hsic.h
+++ b/drivers/char/diag/diagfwd_hsic.h
@@ -14,12 +14,10 @@
#define DIAGFWD_HSIC_H
#include <mach/diag_bridge.h>
-#define N_MDM_WRITE 1 /* Upgrade to 2 with ping pong buffer */
-#define N_MDM_READ 1
int diagfwd_connect_bridge(int);
int diagfwd_disconnect_bridge(int);
-int diagfwd_write_complete_hsic(void);
+int diagfwd_write_complete_hsic(struct diag_request *);
int diagfwd_cancel_hsic(void);
void diagfwd_bridge_init(void);
void diagfwd_bridge_exit(void);
diff --git a/drivers/char/diag/diagfwd_smux.c b/drivers/char/diag/diagfwd_smux.c
index 8bbc67e..ae90686 100644
--- a/drivers/char/diag/diagfwd_smux.c
+++ b/drivers/char/diag/diagfwd_smux.c
@@ -26,13 +26,17 @@
switch (event_type) {
case SMUX_CONNECTED:
- pr_debug("diag: SMUX_CONNECTED received\n");
+ pr_info("diag: SMUX_CONNECTED received\n");
+ driver->smux_connected = 1;
driver->in_busy_smux = 0;
/* read data from USB MDM channel & Initiate first write */
queue_work(driver->diag_bridge_wq,
&(driver->diag_read_mdm_work));
break;
case SMUX_DISCONNECTED:
+ driver->smux_connected = 0;
+ driver->lcid = LCID_INVALID;
+ msm_smux_close(LCID_VALID);
pr_info("diag: SMUX_DISCONNECTED received\n");
break;
case SMUX_WRITE_DONE:
@@ -112,6 +116,7 @@
pr_info("diag: open SMUX ch, r = %d\n", ret);
} else {
pr_err("diag: failed to open SMUX ch, r = %d\n", ret);
+ return ret;
}
}
/* Poll USB channel to check for data*/
@@ -146,8 +151,20 @@
return ret;
}
+static int diagfwd_smux_remove(struct platform_device *pdev)
+{
+ driver->lcid = LCID_INVALID;
+ driver->smux_connected = 0;
+ driver->diag_smux_enabled = 0;
+ driver->in_busy_smux = 1;
+ kfree(driver->buf_in_smux);
+ driver->buf_in_smux = NULL;
+ return 0;
+}
+
struct platform_driver msm_diagfwd_smux_driver = {
.probe = diagfwd_smux_probe,
+ .remove = diagfwd_smux_remove,
.driver = {
.name = "SMUX_DIAG",
.owner = THIS_MODULE,
diff --git a/drivers/char/diag/diagmem.c b/drivers/char/diag/diagmem.c
index 0b5c27a..82c47af 100644
--- a/drivers/char/diag/diagmem.c
+++ b/drivers/char/diag/diagmem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2012, Code Aurora Forum. 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
@@ -51,6 +51,28 @@
driver->diag_write_struct_pool, GFP_ATOMIC);
}
}
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+ } else if (pool_type == POOL_TYPE_HSIC) {
+ if (driver->diag_hsic_pool) {
+ if (driver->count_hsic_pool < driver->poolsize_hsic) {
+ atomic_add(1,
+ (atomic_t *)&driver->count_hsic_pool);
+ buf = mempool_alloc(driver->diag_hsic_pool,
+ GFP_ATOMIC);
+ }
+ }
+ } else if (pool_type == POOL_TYPE_HSIC_WRITE) {
+ if (driver->diag_hsic_write_pool) {
+ if (driver->count_hsic_write_pool <
+ driver->poolsize_hsic_write) {
+ atomic_add(1, (atomic_t *)
+ &driver->count_hsic_write_pool);
+ buf = mempool_alloc(
+ driver->diag_hsic_write_pool,
+ GFP_ATOMIC);
+ }
+ }
+#endif
}
return buf;
}
@@ -63,7 +85,7 @@
driver->diagpool = NULL;
} else if (driver->ref_count == 0 && pool_type == POOL_TYPE_ALL)
printk(KERN_ALERT "Unable to destroy COPY mempool");
- }
+ }
if (driver->diag_hdlc_pool) {
if (driver->count_hdlc_pool == 0 && driver->ref_count == 0) {
@@ -71,7 +93,7 @@
driver->diag_hdlc_pool = NULL;
} else if (driver->ref_count == 0 && pool_type == POOL_TYPE_ALL)
printk(KERN_ALERT "Unable to destroy HDLC mempool");
- }
+ }
if (driver->diag_write_struct_pool) {
/* Free up struct pool ONLY if there are no outstanding
@@ -82,7 +104,30 @@
driver->diag_write_struct_pool = NULL;
} else if (driver->ref_count == 0 && pool_type == POOL_TYPE_ALL)
printk(KERN_ALERT "Unable to destroy STRUCT mempool");
- }
+ }
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+ if (driver->diag_hsic_pool && (driver->hsic_device_enabled == 0)) {
+ if (driver->count_hsic_pool == 0) {
+ mempool_destroy(driver->diag_hdlc_pool);
+ driver->diag_hdlc_pool = NULL;
+ } else if (pool_type == POOL_TYPE_ALL)
+ pr_err("Unable to destroy HDLC mempool");
+ }
+
+ if (driver->diag_hsic_write_pool &&
+ (driver->hsic_device_enabled == 0)) {
+ /*
+ * Free up struct pool ONLY if there are no outstanding
+ * transactions(aggregation buffer) with USB
+ */
+ if (driver->count_hsic_write_pool == 0 &&
+ driver->count_hsic_pool == 0) {
+ mempool_destroy(driver->diag_hsic_write_pool);
+ driver->diag_hsic_write_pool = NULL;
+ } else if (pool_type == POOL_TYPE_ALL)
+ pr_err("Unable to destroy HSIC USB struct mempool");
+ }
+#endif
}
void diagmem_free(struct diagchar_dev *driver, void *buf, int pool_type)
@@ -112,6 +157,29 @@
pr_err("diag: Attempt to free up DIAG driver "
"USB structure mempool which is already free %d ",
driver->count_write_struct_pool);
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+ } else if (pool_type == POOL_TYPE_HSIC) {
+ if (driver->diag_hsic_pool != NULL &&
+ driver->count_hsic_pool > 0) {
+ mempool_free(buf, driver->diag_hsic_pool);
+ atomic_add(-1, (atomic_t *)&driver->count_hsic_pool);
+ } else
+ pr_err("diag: Attempt to free up DIAG driver HSIC mempool which is already free %d ",
+ driver->count_hsic_pool);
+ } else if (pool_type == POOL_TYPE_HSIC_WRITE) {
+ if (driver->diag_hsic_write_pool != NULL &&
+ driver->count_hsic_write_pool > 0) {
+ mempool_free(buf, driver->diag_hsic_write_pool);
+ atomic_add(-1,
+ (atomic_t *)&driver->count_hsic_write_pool);
+ } else
+ pr_err("diag: Attempt to free up DIAG driver HSIC USB structure mempool which is already free %d ",
+ driver->count_write_struct_pool);
+#endif
+ } else {
+ pr_err("diag: In %s, unknown pool type: %d\n",
+ __func__, pool_type);
+
}
diagmem_exit(driver, pool_type);
@@ -143,3 +211,25 @@
printk(KERN_INFO "Cannot allocate diag USB struct mempool\n");
}
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+void diagmem_hsic_init(struct diagchar_dev *driver)
+{
+ if (driver->count_hsic_pool == 0)
+ driver->diag_hsic_pool = mempool_create_kmalloc_pool(
+ driver->poolsize_hsic,
+ driver->itemsize_hsic);
+
+ if (driver->count_hsic_write_pool == 0)
+ driver->diag_hsic_write_pool = mempool_create_kmalloc_pool(
+ driver->poolsize_hsic_write,
+ driver->itemsize_hsic_write);
+
+ if (!driver->diag_hsic_pool)
+ pr_err("Cannot allocate diag HSIC mempool\n");
+
+ if (!driver->diag_hsic_write_pool)
+ pr_err("Cannot allocate diag HSIC struct mempool\n");
+
+}
+#endif
+
diff --git a/drivers/char/diag/diagmem.h b/drivers/char/diag/diagmem.h
index 43829ae..8665c75 100644
--- a/drivers/char/diag/diagmem.h
+++ b/drivers/char/diag/diagmem.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -18,5 +18,7 @@
void diagmem_free(struct diagchar_dev *driver, void *buf, int pool_type);
void diagmem_init(struct diagchar_dev *driver);
void diagmem_exit(struct diagchar_dev *driver, int pool_type);
-
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+void diagmem_hsic_init(struct diagchar_dev *driver);
+#endif
#endif
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index e805c7f..46d3e5d 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -1516,6 +1516,12 @@
static int etm_count;
struct coresight_desc *desc;
+ /* Fail probe for Krait pass3 until supported */
+ if (cpu_is_krait_v3()) {
+ dev_info(dev, "ETM: failing probe for Krait pass3\n");
+ return -EINVAL;
+ }
+
if (pdev->dev.of_node) {
pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
if (IS_ERR(pdata))
diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c
index 63f7fd9..f1c31c1 100644
--- a/drivers/crypto/msm/qcedev.c
+++ b/drivers/crypto/msm/qcedev.c
@@ -2038,18 +2038,6 @@
podev->pdev = pdev;
platform_set_drvdata(pdev, podev);
- if (podev->platform_support.bus_scale_table != NULL) {
- podev->bus_scale_handle =
- msm_bus_scale_register_client(
- (struct msm_bus_scale_pdata *)
- podev->platform_support.bus_scale_table);
- if (!podev->bus_scale_handle) {
- printk(KERN_ERR "%s not able to get bus scale\n",
- __func__);
- rc = -ENOMEM;
- goto err;
- }
- }
rc = misc_register(&podev->miscdevice);
qce_hw_support(podev->qce, &podev->ce_support);
if (podev->ce_support.bam) {
@@ -2070,6 +2058,18 @@
platform_support->bus_scale_table;
podev->platform_support.sha_hmac = platform_support->sha_hmac;
}
+ if (podev->platform_support.bus_scale_table != NULL) {
+ podev->bus_scale_handle =
+ msm_bus_scale_register_client(
+ (struct msm_bus_scale_pdata *)
+ podev->platform_support.bus_scale_table);
+ if (!podev->bus_scale_handle) {
+ pr_err("%s not able to get bus scale\n",
+ __func__);
+ rc = -ENOMEM;
+ goto err;
+ }
+ }
if (rc >= 0)
return 0;
else
diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c
index 7bfb208..67a2e6b 100644
--- a/drivers/gpio/qpnp-pin.c
+++ b/drivers/gpio/qpnp-pin.c
@@ -32,11 +32,17 @@
#define Q_REG_STATUS1 0x8
#define Q_REG_STATUS1_VAL_MASK 0x1
-#define Q_REG_STATUS1_GPIO_EN_MASK 0x2
+#define Q_REG_STATUS1_GPIO_EN_REV0_MASK 0x2
+#define Q_REG_STATUS1_GPIO_EN_MASK 0x80
#define Q_REG_STATUS1_MPP_EN_MASK 0x80
#define Q_NUM_CTL_REGS 0xD
+/* revision registers base address offsets */
+#define Q_REG_DIG_MINOR_REV 0x0
+#define Q_REG_DIG_MAJOR_REV 0x1
+#define Q_REG_ANA_MINOR_REV 0x2
+
/* type registers base address offsets */
#define Q_REG_TYPE 0x4
#define Q_REG_SUBTYPE 0x5
@@ -158,6 +164,7 @@
u8 num_ctl_regs; /* usable number on this pin */
u8 type; /* peripheral type */
u8 subtype; /* peripheral subtype */
+ u8 dig_major_rev;
struct device_node *node;
enum qpnp_pin_param_type params[Q_NUM_PARAMS];
struct qpnp_pin_chip *q_chip;
@@ -646,9 +653,14 @@
Q_REG_ADDR(q_spec, Q_REG_STATUS1),
&buf[0], 1);
- en_mask = q_spec->type == Q_GPIO_TYPE ?
- Q_REG_STATUS1_GPIO_EN_MASK :
- Q_REG_STATUS1_MPP_EN_MASK;
+ if (q_spec->type == Q_GPIO_TYPE && q_spec->dig_major_rev == 0)
+ en_mask = Q_REG_STATUS1_GPIO_EN_REV0_MASK;
+ else if (q_spec->type == Q_GPIO_TYPE &&
+ q_spec->dig_major_rev > 0)
+ en_mask = Q_REG_STATUS1_GPIO_EN_MASK;
+ else /* MPP */
+ en_mask = Q_REG_STATUS1_MPP_EN_MASK;
+
if (!(buf[0] & en_mask))
return -EPERM;
@@ -1099,6 +1111,28 @@
}
#endif
+static int qpnp_pin_is_valid_pin(struct qpnp_pin_spec *q_spec)
+{
+ if (q_spec->type == Q_GPIO_TYPE)
+ switch (q_spec->subtype) {
+ case Q_GPIO_SUBTYPE_GPIO_4CH:
+ case Q_GPIO_SUBTYPE_GPIOC_4CH:
+ case Q_GPIO_SUBTYPE_GPIO_8CH:
+ case Q_GPIO_SUBTYPE_GPIOC_8CH:
+ return 1;
+ }
+ else if (q_spec->type == Q_MPP_TYPE)
+ switch (q_spec->subtype) {
+ case Q_MPP_SUBTYPE_4CH_NO_ANA_OUT:
+ case Q_MPP_SUBTYPE_4CH_NO_SINK:
+ case Q_MPP_SUBTYPE_4CH_FULL_FUNC:
+ case Q_MPP_SUBTYPE_8CH_FULL_FUNC:
+ return 1;
+ }
+
+ return 0;
+}
+
static int qpnp_pin_probe(struct spmi_device *spmi)
{
struct qpnp_pin_chip *q_chip;
@@ -1108,7 +1142,7 @@
int i, rc;
int lowest_gpio = UINT_MAX, highest_gpio = 0;
u32 intspec[3], gpio;
- char buf[2];
+ char version[Q_REG_SUBTYPE - Q_REG_DIG_MAJOR_REV + 1];
const char *dev_name;
dev_name = spmi_get_primary_dev_name(spmi);
@@ -1218,14 +1252,23 @@
q_spec->q_chip = q_chip;
rc = spmi_ext_register_readl(spmi->ctrl, q_spec->slave,
- Q_REG_ADDR(q_spec, Q_REG_TYPE), &buf[0], 2);
+ Q_REG_ADDR(q_spec, Q_REG_DIG_MAJOR_REV),
+ &version[0], ARRAY_SIZE(version));
if (rc) {
dev_err(&spmi->dev, "%s: unable to read type regs\n",
__func__);
goto err_probe;
}
- q_spec->type = buf[0];
- q_spec->subtype = buf[1];
+ q_spec->dig_major_rev = version[Q_REG_DIG_MAJOR_REV -
+ Q_REG_DIG_MAJOR_REV];
+ q_spec->type = version[Q_REG_TYPE - Q_REG_DIG_MAJOR_REV];
+ q_spec->subtype = version[Q_REG_SUBTYPE - Q_REG_DIG_MAJOR_REV];
+
+ if (!qpnp_pin_is_valid_pin(q_spec)) {
+ dev_err(&spmi->dev, "%s: invalid pin type (type=0x%x subtype=0x%x)\n",
+ __func__, q_spec->type, q_spec->subtype);
+ goto err_probe;
+ }
rc = qpnp_pin_ctl_regs_init(q_spec);
if (rc)
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index 33fcbfd..1bb33b6 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -234,6 +234,7 @@
#define A3XX_TPL1_TP_VS_TEX_OFFSET 0x2340
#define A3XX_TPL1_TP_FS_TEX_OFFSET 0x2342
#define A3XX_TPL1_TP_FS_BORDER_COLOR_BASE_ADDR 0x2343
+#define A3XX_VBIF_CLKON 0x3001
#define A3XX_VBIF_FIXED_SORT_EN 0x300C
#define A3XX_VBIF_FIXED_SORT_SEL0 0x300D
#define A3XX_VBIF_FIXED_SORT_SEL1 0x300E
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 3d1fbc8..6e95fff 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -179,7 +179,7 @@
"a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev,
512, 0, 2, SZ_256K },
/* A3XX doesn't use the pix_shader_start */
- { ADRENO_REV_A320, 3, 2, 0, ANY_ID,
+ { ADRENO_REV_A320, 3, 2, ANY_ID, ANY_ID,
"a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev,
512, 0, 2, SZ_512K },
{ ADRENO_REV_A330, 3, 3, 0, 0,
@@ -275,25 +275,20 @@
unsigned int *cmds = &link[0];
int sizedwords = 0;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- struct kgsl_memdesc **reg_map_desc;
- void *reg_map_array = NULL;
int num_iommu_units, i;
struct kgsl_context *context;
struct adreno_context *adreno_ctx = NULL;
if (!adreno_dev->drawctxt_active)
return kgsl_mmu_device_setstate(&device->mmu, flags);
- num_iommu_units = kgsl_mmu_get_reg_map_desc(&device->mmu,
- ®_map_array);
+ num_iommu_units = kgsl_mmu_get_num_iommu_units(&device->mmu);
context = idr_find(&device->context_idr, context_id);
adreno_ctx = context->devctxt;
- reg_map_desc = reg_map_array;
-
if (kgsl_mmu_enable_clk(&device->mmu,
KGSL_IOMMU_CONTEXT_USER))
- goto done;
+ return;
cmds += __adreno_add_idle_indirect_cmds(cmds,
device->mmu.setstate_memory.gpuaddr +
@@ -309,26 +304,23 @@
device->mmu.setstate_memory.gpuaddr +
KGSL_IOMMU_SETSTATE_NOP_OFFSET);
- pt_val = kgsl_mmu_pt_get_base_addr(device->mmu.hwpagetable);
+ pt_val = kgsl_mmu_get_pt_base_addr(&device->mmu,
+ device->mmu.hwpagetable);
if (flags & KGSL_MMUFLAGS_PTUPDATE) {
/*
* We need to perfrom the following operations for all
* IOMMU units
*/
for (i = 0; i < num_iommu_units; i++) {
- reg_pt_val = (pt_val &
- (KGSL_IOMMU_TTBR0_PA_MASK <<
- KGSL_IOMMU_TTBR0_PA_SHIFT)) +
- kgsl_mmu_get_pt_lsb(&device->mmu, i,
- KGSL_IOMMU_CONTEXT_USER);
+ reg_pt_val = (pt_val + kgsl_mmu_get_pt_lsb(&device->mmu,
+ i, KGSL_IOMMU_CONTEXT_USER));
/*
* Set address of the new pagetable by writng to IOMMU
* TTBR0 register
*/
*cmds++ = cp_type3_packet(CP_MEM_WRITE, 2);
- *cmds++ = reg_map_desc[i]->gpuaddr +
- (KGSL_IOMMU_CONTEXT_USER <<
- KGSL_IOMMU_CTX_SHIFT) + KGSL_IOMMU_TTBR0;
+ *cmds++ = kgsl_mmu_get_reg_gpuaddr(&device->mmu, i,
+ KGSL_IOMMU_CONTEXT_USER, KGSL_IOMMU_CTX_TTBR0);
*cmds++ = reg_pt_val;
*cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
*cmds++ = 0x00000000;
@@ -338,9 +330,8 @@
* above writes have completed
*/
cmds += adreno_add_read_cmds(device, cmds,
- reg_map_desc[i]->gpuaddr +
- (KGSL_IOMMU_CONTEXT_USER <<
- KGSL_IOMMU_CTX_SHIFT) + KGSL_IOMMU_TTBR0,
+ kgsl_mmu_get_reg_gpuaddr(&device->mmu, i,
+ KGSL_IOMMU_CONTEXT_USER, KGSL_IOMMU_CTX_TTBR0),
reg_pt_val,
device->mmu.setstate_memory.gpuaddr +
KGSL_IOMMU_SETSTATE_NOP_OFFSET);
@@ -358,16 +349,12 @@
* tlb flush
*/
for (i = 0; i < num_iommu_units; i++) {
- reg_pt_val = (pt_val &
- (KGSL_IOMMU_TTBR0_PA_MASK <<
- KGSL_IOMMU_TTBR0_PA_SHIFT)) +
- kgsl_mmu_get_pt_lsb(&device->mmu, i,
- KGSL_IOMMU_CONTEXT_USER);
+ reg_pt_val = (pt_val + kgsl_mmu_get_pt_lsb(&device->mmu,
+ i, KGSL_IOMMU_CONTEXT_USER));
*cmds++ = cp_type3_packet(CP_MEM_WRITE, 2);
- *cmds++ = (reg_map_desc[i]->gpuaddr +
- (KGSL_IOMMU_CONTEXT_USER <<
- KGSL_IOMMU_CTX_SHIFT) +
+ *cmds++ = kgsl_mmu_get_reg_gpuaddr(&device->mmu, i,
+ KGSL_IOMMU_CONTEXT_USER,
KGSL_IOMMU_CTX_TLBIALL);
*cmds++ = 1;
@@ -376,9 +363,9 @@
KGSL_IOMMU_SETSTATE_NOP_OFFSET);
cmds += adreno_add_read_cmds(device, cmds,
- reg_map_desc[i]->gpuaddr +
- (KGSL_IOMMU_CONTEXT_USER <<
- KGSL_IOMMU_CTX_SHIFT) + KGSL_IOMMU_TTBR0,
+ kgsl_mmu_get_reg_gpuaddr(&device->mmu, i,
+ KGSL_IOMMU_CONTEXT_USER,
+ KGSL_IOMMU_CTX_TTBR0),
reg_pt_val,
device->mmu.setstate_memory.gpuaddr +
KGSL_IOMMU_SETSTATE_NOP_OFFSET);
@@ -387,7 +374,8 @@
if (cpu_is_msm8960())
cmds += adreno_add_change_mh_phys_limit_cmds(cmds,
- reg_map_desc[num_iommu_units - 1]->gpuaddr - PAGE_SIZE,
+ kgsl_mmu_get_reg_gpuaddr(&device->mmu, 0,
+ 0, KGSL_IOMMU_GLOBAL_BASE),
device->mmu.setstate_memory.gpuaddr +
KGSL_IOMMU_SETSTATE_NOP_OFFSET);
else
@@ -413,9 +401,6 @@
kgsl_mmu_disable_clk_on_ts(&device->mmu,
adreno_dev->ringbuffer.timestamp[KGSL_MEMSTORE_GLOBAL], true);
}
-done:
- if (num_iommu_units)
- kfree(reg_map_array);
}
static void adreno_gpummu_setstate(struct kgsl_device *device,
@@ -453,7 +438,7 @@
/* set page table base */
*cmds++ = cp_type0_packet(MH_MMU_PT_BASE, 1);
- *cmds++ = kgsl_mmu_pt_get_base_addr(
+ *cmds++ = kgsl_mmu_get_pt_base_addr(&device->mmu,
device->mmu.hwpagetable);
sizedwords += 4;
}
@@ -1969,7 +1954,8 @@
adreno_context = (struct adreno_context *)context->devctxt;
- if (kgsl_mmu_pt_equal(adreno_context->pagetable, pt_base)) {
+ if (kgsl_mmu_pt_equal(&device->mmu, adreno_context->pagetable,
+ pt_base)) {
struct kgsl_memdesc *desc;
desc = &adreno_context->gpustate;
@@ -2008,7 +1994,7 @@
size))
return &device->mmu.setstate_memory;
- entry = kgsl_get_mem_entry(pt_base, gpuaddr, size);
+ entry = kgsl_get_mem_entry(device, pt_base, gpuaddr, size);
if (entry)
return &entry->memdesc;
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 5ce34db..548ef3c 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2699,13 +2699,13 @@
/* Set up 16 deep read/write request queues */
if (adreno_dev->gpurev == ADRENO_REV_A330) {
- adreno_regwrite(device, A3XX_VBIF_IN_RD_LIM_CONF0, 0x01010101);
- adreno_regwrite(device, A3XX_VBIF_IN_RD_LIM_CONF1, 0x01010101);
- adreno_regwrite(device, A3XX_VBIF_OUT_RD_LIM_CONF0, 0x01010101);
- adreno_regwrite(device, A3XX_VBIF_OUT_WR_LIM_CONF0, 0x01010101);
+ adreno_regwrite(device, A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818);
+ adreno_regwrite(device, A3XX_VBIF_IN_RD_LIM_CONF1, 0x18181818);
+ adreno_regwrite(device, A3XX_VBIF_OUT_RD_LIM_CONF0, 0x18181818);
+ adreno_regwrite(device, A3XX_VBIF_OUT_WR_LIM_CONF0, 0x18181818);
adreno_regwrite(device, A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303);
- adreno_regwrite(device, A3XX_VBIF_IN_WR_LIM_CONF0, 0x01010101);
- adreno_regwrite(device, A3XX_VBIF_IN_WR_LIM_CONF1, 0x01010101);
+ adreno_regwrite(device, A3XX_VBIF_IN_WR_LIM_CONF0, 0x18181818);
+ adreno_regwrite(device, A3XX_VBIF_IN_WR_LIM_CONF1, 0x18181818);
/* Enable WR-REQ */
adreno_regwrite(device, A3XX_VBIF_GATE_OFF_WRREQ_EN, 0x00003F);
@@ -2721,6 +2721,11 @@
/* Enable 1K sort */
adreno_regwrite(device, A3XX_VBIF_ABIT_SORT, 0x1FFFF);
adreno_regwrite(device, A3XX_VBIF_ABIT_SORT_CONF, 0x000000A4);
+
+ /* Diable VBIF clock gating. This is to enable AXI running
+ * higher frequency than GPU.
+ */
+ adreno_regwrite(device, A3XX_VBIF_CLKON, 1);
} else {
adreno_regwrite(device, A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
adreno_regwrite(device, A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010);
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index bd22233..74493f4 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -226,6 +226,10 @@
adreno_idle(device);
+ if (adreno_is_a20x(adreno_dev) && adreno_dev->drawctxt_active)
+ kgsl_setstate(&device->mmu, adreno_dev->drawctxt_active->id,
+ KGSL_MMUFLAGS_PTUPDATE);
+
kgsl_sharedmem_free(&drawctxt->gpustate);
kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow);
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 2038c10..261e518 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -697,8 +697,6 @@
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- struct kgsl_memdesc **reg_map;
- void *reg_map_array;
int num_iommu_units = 0;
mb();
@@ -783,9 +781,7 @@
ib_list.count = 0;
i = 0;
/* get the register mapped array in case we are using IOMMU */
- num_iommu_units = kgsl_mmu_get_reg_map_desc(&device->mmu,
- ®_map_array);
- reg_map = reg_map_array;
+ num_iommu_units = kgsl_mmu_get_num_iommu_units(&device->mmu);
for (read_idx = 0; read_idx < num_item; ) {
uint32_t this_cmd = rb_copy[read_idx++];
if (adreno_cmd_is_ib(this_cmd)) {
@@ -799,13 +795,14 @@
ib_list.bases[i],
ib_list.sizes[i], 0);
} else if (this_cmd == cp_type0_packet(MH_MMU_PT_BASE, 1) ||
- (num_iommu_units && this_cmd == (reg_map[0]->gpuaddr +
- (KGSL_IOMMU_CONTEXT_USER << KGSL_IOMMU_CTX_SHIFT) +
- KGSL_IOMMU_TTBR0))) {
-
+ (num_iommu_units && this_cmd ==
+ kgsl_mmu_get_reg_gpuaddr(&device->mmu, 0,
+ KGSL_IOMMU_CONTEXT_USER,
+ KGSL_IOMMU_CTX_TTBR0))) {
KGSL_LOG_DUMP(device, "Current pagetable: %x\t"
"pagetable base: %x\n",
- kgsl_mmu_get_ptname_from_ptbase(cur_pt_base),
+ kgsl_mmu_get_ptname_from_ptbase(&device->mmu,
+ cur_pt_base),
cur_pt_base);
/* Set cur_pt_base to the new pagetable base */
@@ -813,12 +810,11 @@
KGSL_LOG_DUMP(device, "New pagetable: %x\t"
"pagetable base: %x\n",
- kgsl_mmu_get_ptname_from_ptbase(cur_pt_base),
+ kgsl_mmu_get_ptname_from_ptbase(&device->mmu,
+ cur_pt_base),
cur_pt_base);
}
}
- if (num_iommu_units)
- kfree(reg_map_array);
/* Restore cur_pt_base back to the pt_base of
the process in whose context the GPU hung */
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index e7a1c13..1066b49 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -193,13 +193,14 @@
EXPORT_SYMBOL(kgsl_cancel_events);
/* kgsl_get_mem_entry - get the mem_entry structure for the specified object
+ * @device - Pointer to the device structure
* @ptbase - the pagetable base of the object
* @gpuaddr - the GPU address of the object
* @size - Size of the region to search
*/
-struct kgsl_mem_entry *kgsl_get_mem_entry(unsigned int ptbase,
- unsigned int gpuaddr, unsigned int size)
+struct kgsl_mem_entry *kgsl_get_mem_entry(struct kgsl_device *device,
+ unsigned int ptbase, unsigned int gpuaddr, unsigned int size)
{
struct kgsl_process_private *priv;
struct kgsl_mem_entry *entry;
@@ -207,7 +208,7 @@
mutex_lock(&kgsl_driver.process_mutex);
list_for_each_entry(priv, &kgsl_driver.process_list, list) {
- if (!kgsl_mmu_pt_equal(priv->pagetable, ptbase))
+ if (!kgsl_mmu_pt_equal(&device->mmu, priv->pagetable, ptbase))
continue;
spin_lock(&priv->mem_lock);
entry = kgsl_sharedmem_find_region(priv, gpuaddr, size);
@@ -1769,8 +1770,10 @@
return -ENODEV;
handle = ion_import_dma_buf(kgsl_ion_client, fd);
- if (IS_ERR_OR_NULL(handle))
+ if (IS_ERR(handle))
return PTR_ERR(handle);
+ else if (!handle)
+ return -EINVAL;
entry->memtype = KGSL_MEM_ENTRY_ION;
entry->priv_data = handle;
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index ac04c56..416eda9 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -175,8 +175,8 @@
void kgsl_mem_entry_destroy(struct kref *kref);
int kgsl_postmortem_dump(struct kgsl_device *device, int manual);
-struct kgsl_mem_entry *kgsl_get_mem_entry(unsigned int ptbase,
- unsigned int gpuaddr, unsigned int size);
+struct kgsl_mem_entry *kgsl_get_mem_entry(struct kgsl_device *device,
+ unsigned int ptbase, unsigned int gpuaddr, unsigned int size);
struct kgsl_mem_entry *kgsl_sharedmem_find_region(
struct kgsl_process_private *private, unsigned int gpuaddr,
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index 8cf00ea..326e79d 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -355,8 +355,9 @@
return NULL;
}
-int kgsl_gpummu_pt_equal(struct kgsl_pagetable *pt,
- unsigned int pt_base)
+int kgsl_gpummu_pt_equal(struct kgsl_mmu *mmu,
+ struct kgsl_pagetable *pt,
+ unsigned int pt_base)
{
struct kgsl_gpummu_pt *gpummu_pt = pt ? pt->priv : NULL;
return gpummu_pt && pt_base && (gpummu_pt->base.gpuaddr == pt_base);
@@ -409,10 +410,10 @@
KGSL_MEM_CRIT(mmu->device,
"mmu page fault: page=0x%lx pt=%d op=%s axi=%d\n",
reg & ~(PAGE_SIZE - 1),
- kgsl_mmu_get_ptname_from_ptbase(ptbase),
+ kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase),
reg & 0x02 ? "WRITE" : "READ", (reg >> 4) & 0xF);
trace_kgsl_mmu_pagefault(mmu->device, reg & ~(PAGE_SIZE - 1),
- kgsl_mmu_get_ptname_from_ptbase(ptbase),
+ kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase),
reg & 0x02 ? "WRITE" : "READ");
}
@@ -714,12 +715,18 @@
}
static unsigned int
-kgsl_gpummu_pt_get_base_addr(struct kgsl_pagetable *pt)
+kgsl_gpummu_get_pt_base_addr(struct kgsl_mmu *mmu,
+ struct kgsl_pagetable *pt)
{
struct kgsl_gpummu_pt *gpummu_pt = pt->priv;
return gpummu_pt->base.gpuaddr;
}
+static int kgsl_gpummu_get_num_iommu_units(struct kgsl_mmu *mmu)
+{
+ return 1;
+}
+
struct kgsl_mmu_ops gpummu_ops = {
.mmu_init = kgsl_gpummu_init,
.mmu_close = kgsl_gpummu_close,
@@ -729,10 +736,13 @@
.mmu_device_setstate = kgsl_gpummu_default_setstate,
.mmu_pagefault = kgsl_gpummu_pagefault,
.mmu_get_current_ptbase = kgsl_gpummu_get_current_ptbase,
+ .mmu_pt_equal = kgsl_gpummu_pt_equal,
+ .mmu_get_pt_base_addr = kgsl_gpummu_get_pt_base_addr,
.mmu_enable_clk = NULL,
.mmu_disable_clk_on_ts = NULL,
.mmu_get_pt_lsb = NULL,
- .mmu_get_reg_map_desc = NULL,
+ .mmu_get_reg_gpuaddr = NULL,
+ .mmu_get_num_iommu_units = kgsl_gpummu_get_num_iommu_units,
};
struct kgsl_mmu_pt_ops gpummu_pt_ops = {
@@ -740,6 +750,4 @@
.mmu_unmap = kgsl_gpummu_unmap,
.mmu_create_pagetable = kgsl_gpummu_create_pagetable,
.mmu_destroy_pagetable = kgsl_gpummu_destroy_pagetable,
- .mmu_pt_equal = kgsl_gpummu_pt_equal,
- .mmu_pt_get_base_addr = kgsl_gpummu_pt_get_base_addr,
};
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 1eb671f..7254647 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -28,7 +28,16 @@
#include "adreno.h"
#include "kgsl_trace.h"
-static struct kgsl_iommu_unit *get_iommu_unit(struct device *dev)
+static struct kgsl_iommu_register_list kgsl_iommuv1_reg[KGSL_IOMMU_REG_MAX] = {
+ { 0, 0, 0 }, /* GLOBAL_BASE */
+ { 0x10, 0x0003FFFF, 14 }, /* TTBR0 */
+ { 0x14, 0x0003FFFF, 14 }, /* TTBR1 */
+ { 0x20, 0, 0 }, /* FSR */
+ { 0x800, 0, 0 }, /* TLBIALL */
+};
+
+static int get_iommu_unit(struct device *dev, struct kgsl_mmu **mmu_out,
+ struct kgsl_iommu_unit **iommu_unit_out)
{
int i, j, k;
@@ -49,13 +58,16 @@
struct kgsl_iommu_unit *iommu_unit =
&iommu->iommu_units[j];
for (k = 0; k < iommu_unit->dev_count; k++) {
- if (iommu_unit->dev[k].dev == dev)
- return iommu_unit;
+ if (iommu_unit->dev[k].dev == dev) {
+ *mmu_out = mmu;
+ *iommu_unit_out = iommu_unit;
+ return 0;
+ }
}
}
}
- return NULL;
+ return -EINVAL;
}
static struct kgsl_iommu_device *get_iommu_device(struct kgsl_iommu_unit *unit,
@@ -74,31 +86,41 @@
static int kgsl_iommu_fault_handler(struct iommu_domain *domain,
struct device *dev, unsigned long addr, int flags)
{
- struct kgsl_iommu_unit *iommu_unit = get_iommu_unit(dev);
- struct kgsl_iommu_device *iommu_dev = get_iommu_device(iommu_unit, dev);
+ int ret = 0;
+ struct kgsl_mmu *mmu;
+ struct kgsl_iommu *iommu;
+ struct kgsl_iommu_unit *iommu_unit;
+ struct kgsl_iommu_device *iommu_dev;
unsigned int ptbase, fsr;
+ ret = get_iommu_unit(dev, &mmu, &iommu_unit);
+ if (ret)
+ goto done;
+ iommu_dev = get_iommu_device(iommu_unit, dev);
if (!iommu_dev) {
KGSL_CORE_ERR("Invalid IOMMU device %p\n", dev);
- return -ENOSYS;
+ ret = -ENOSYS;
+ goto done;
}
+ iommu = mmu->priv;
- ptbase = KGSL_IOMMU_GET_IOMMU_REG(iommu_unit->reg_map.hostptr,
+ ptbase = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit,
iommu_dev->ctx_id, TTBR0);
- fsr = KGSL_IOMMU_GET_IOMMU_REG(iommu_unit->reg_map.hostptr,
+ fsr = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit,
iommu_dev->ctx_id, FSR);
KGSL_MEM_CRIT(iommu_dev->kgsldev,
"GPU PAGE FAULT: addr = %lX pid = %d\n",
- addr, kgsl_mmu_get_ptname_from_ptbase(ptbase));
+ addr, kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase));
KGSL_MEM_CRIT(iommu_dev->kgsldev, "context = %d FSR = %X\n",
iommu_dev->ctx_id, fsr);
trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr,
- kgsl_mmu_get_ptname_from_ptbase(ptbase), 0);
+ kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase), 0);
- return 0;
+done:
+ return ret;
}
/*
@@ -121,6 +143,8 @@
continue;
iommu_drvdata = dev_get_drvdata(
iommu_unit->dev[j].dev->parent);
+ if (iommu_drvdata->aclk)
+ clk_disable_unprepare(iommu_drvdata->aclk);
if (iommu_drvdata->clk)
clk_disable_unprepare(iommu_drvdata->clk);
clk_disable_unprepare(iommu_drvdata->pclk);
@@ -247,6 +271,17 @@
goto done;
}
}
+ if (iommu_drvdata->aclk) {
+ ret = clk_prepare_enable(iommu_drvdata->aclk);
+ if (ret) {
+ if (iommu_drvdata->clk)
+ clk_disable_unprepare(
+ iommu_drvdata->clk);
+ clk_disable_unprepare(
+ iommu_drvdata->pclk);
+ goto done;
+ }
+ }
iommu_unit->dev[j].clk_enabled = true;
}
}
@@ -258,6 +293,7 @@
/*
* kgsl_iommu_pt_equal - Check if pagetables are equal
+ * @mmu - Pointer to mmu structure
* @pt - Pointer to pagetable
* @pt_base - Address of a pagetable that the IOMMU register is
* programmed with
@@ -266,17 +302,23 @@
* the pagetable which is contained in the pt structure
* Return - Non-zero if the pagetable addresses are equal else 0
*/
-static int kgsl_iommu_pt_equal(struct kgsl_pagetable *pt,
- unsigned int pt_base)
+static int kgsl_iommu_pt_equal(struct kgsl_mmu *mmu,
+ struct kgsl_pagetable *pt,
+ unsigned int pt_base)
{
+ struct kgsl_iommu *iommu = mmu->priv;
struct kgsl_iommu_pt *iommu_pt = pt ? pt->priv : NULL;
unsigned int domain_ptbase = iommu_pt ?
iommu_get_pt_base_addr(iommu_pt->domain) : 0;
/* Only compare the valid address bits of the pt_base */
- domain_ptbase &= (KGSL_IOMMU_TTBR0_PA_MASK <<
- KGSL_IOMMU_TTBR0_PA_SHIFT);
- pt_base &= (KGSL_IOMMU_TTBR0_PA_MASK <<
- KGSL_IOMMU_TTBR0_PA_SHIFT);
+ domain_ptbase &=
+ (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask <<
+ iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift);
+
+ pt_base &=
+ (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask <<
+ iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift);
+
return domain_ptbase && pt_base &&
(domain_ptbase == pt_base);
}
@@ -313,7 +355,7 @@
return NULL;
}
iommu_pt->domain = iommu_domain_alloc(&platform_bus_type,
- MSM_IOMMU_DOMAIN_PT_CACHEABLE);
+ MSM_IOMMU_DOMAIN_PT_CACHEABLE);
if (!iommu_pt->domain) {
KGSL_CORE_ERR("Failed to create iommu domain\n");
kfree(iommu_pt);
@@ -568,17 +610,22 @@
}
/*
- * kgsl_iommu_pt_get_base_addr - Get the address of the pagetable that the
+ * kgsl_iommu_get_pt_base_addr - Get the address of the pagetable that the
* IOMMU ttbr0 register is programmed with
+ * @mmu - Pointer to mmu
* @pt - kgsl pagetable pointer that contains the IOMMU domain pointer
*
* Return - actual pagetable address that the ttbr0 register is programmed
* with
*/
-static unsigned int kgsl_iommu_pt_get_base_addr(struct kgsl_pagetable *pt)
+static unsigned int kgsl_iommu_get_pt_base_addr(struct kgsl_mmu *mmu,
+ struct kgsl_pagetable *pt)
{
+ struct kgsl_iommu *iommu = mmu->priv;
struct kgsl_iommu_pt *iommu_pt = pt->priv;
- return iommu_get_pt_base_addr(iommu_pt->domain);
+ return iommu_get_pt_base_addr(iommu_pt->domain) &
+ (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask <<
+ iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift);
}
/*
@@ -653,6 +700,9 @@
if (status)
goto done;
+ iommu->iommu_reg_list = kgsl_iommuv1_reg;
+ iommu->ctx_offset = KGSL_IOMMU_CTX_OFFSET_V1;
+
/* A nop is required in an indirect buffer when switching
* pagetables in-stream */
kgsl_sharedmem_writel(&mmu->setstate_memory,
@@ -707,13 +757,14 @@
mmu->defaultpagetable;
/* Map the IOMMU regsiters to only defaultpagetable */
for (i = 0; i < iommu->unit_count; i++) {
- iommu->iommu_units[i].reg_map.priv |= KGSL_MEMFLAGS_GLOBAL;
+ iommu->iommu_units[i].reg_map.priv |=
+ KGSL_MEMFLAGS_GLOBAL;
status = kgsl_mmu_map(pagetable,
&(iommu->iommu_units[i].reg_map),
GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
if (status) {
iommu->iommu_units[i].reg_map.priv &=
- ~KGSL_MEMFLAGS_GLOBAL;
+ ~KGSL_MEMFLAGS_GLOBAL;
goto err;
}
}
@@ -756,9 +807,7 @@
kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000001);
kgsl_regwrite(mmu->device, MH_MMU_MPU_END,
mh->mpu_base +
- iommu->iommu_units
- [iommu->unit_count - 1].reg_map.gpuaddr -
- PAGE_SIZE);
+ iommu->iommu_units[0].reg_map.gpuaddr);
} else {
kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000000);
}
@@ -788,9 +837,9 @@
for (i = 0; i < iommu->unit_count; i++) {
struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i];
for (j = 0; j < iommu_unit->dev_count; j++)
- iommu_unit->dev[j].pt_lsb = KGSL_IOMMMU_PT_LSB(
- KGSL_IOMMU_GET_IOMMU_REG(
- iommu_unit->reg_map.hostptr,
+ iommu_unit->dev[j].pt_lsb = KGSL_IOMMMU_PT_LSB(iommu,
+ KGSL_IOMMU_GET_CTX_REG(iommu,
+ iommu_unit,
iommu_unit->dev[j].ctx_id,
TTBR0));
}
@@ -929,12 +978,13 @@
return 0;
/* Return the current pt base by reading IOMMU pt_base register */
kgsl_iommu_enable_clk(mmu, KGSL_IOMMU_CONTEXT_USER);
- pt_base = readl_relaxed(iommu->iommu_units[0].reg_map.hostptr +
- (KGSL_IOMMU_CONTEXT_USER << KGSL_IOMMU_CTX_SHIFT) +
- KGSL_IOMMU_TTBR0);
+ pt_base = KGSL_IOMMU_GET_CTX_REG(iommu, (&iommu->iommu_units[0]),
+ KGSL_IOMMU_CONTEXT_USER,
+ TTBR0);
kgsl_iommu_disable_clk_on_ts(mmu, 0, false);
- return pt_base & (KGSL_IOMMU_TTBR0_PA_MASK <<
- KGSL_IOMMU_TTBR0_PA_SHIFT);
+ return pt_base &
+ (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask <<
+ iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift);
}
/*
@@ -955,8 +1005,8 @@
struct kgsl_iommu *iommu = mmu->priv;
int temp;
int i;
- unsigned int pt_base = kgsl_iommu_pt_get_base_addr(
- mmu->hwpagetable);
+ unsigned int pt_base = kgsl_iommu_get_pt_base_addr(mmu,
+ mmu->hwpagetable);
unsigned int pt_val;
if (kgsl_iommu_enable_clk(mmu, KGSL_IOMMU_CONTEXT_USER)) {
@@ -964,7 +1014,9 @@
return;
}
/* Mask off the lsb of the pt base address since lsb will not change */
- pt_base &= (KGSL_IOMMU_TTBR0_PA_MASK << KGSL_IOMMU_TTBR0_PA_SHIFT);
+ pt_base &= (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask <<
+ iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift);
+
if (flags & KGSL_MMUFLAGS_PTUPDATE) {
kgsl_idle(mmu->device);
for (i = 0; i < iommu->unit_count; i++) {
@@ -974,23 +1026,20 @@
KGSL_IOMMU_CONTEXT_USER);
pt_val += pt_base;
- KGSL_IOMMU_SET_IOMMU_REG(
- iommu->iommu_units[i].reg_map.hostptr,
+ KGSL_IOMMU_SET_CTX_REG(iommu, (&iommu->iommu_units[i]),
KGSL_IOMMU_CONTEXT_USER, TTBR0, pt_val);
mb();
- temp = KGSL_IOMMU_GET_IOMMU_REG(
- iommu->iommu_units[i].reg_map.hostptr,
+ temp = KGSL_IOMMU_GET_CTX_REG(iommu,
+ (&iommu->iommu_units[i]),
KGSL_IOMMU_CONTEXT_USER, TTBR0);
}
}
/* Flush tlb */
if (flags & KGSL_MMUFLAGS_TLBFLUSH) {
for (i = 0; i < iommu->unit_count; i++) {
- KGSL_IOMMU_SET_IOMMU_REG(
- iommu->iommu_units[i].reg_map.hostptr,
- KGSL_IOMMU_CONTEXT_USER, CTX_TLBIALL,
- 1);
+ KGSL_IOMMU_SET_CTX_REG(iommu, (&iommu->iommu_units[i]),
+ KGSL_IOMMU_CONTEXT_USER, TLBIALL, 1);
mb();
}
}
@@ -999,40 +1048,32 @@
}
/*
- * kgsl_iommu_get_reg_map_desc - Returns an array of pointers that contain
- * the address of memory descriptors which map the IOMMU registers
+ * kgsl_iommu_get_reg_gpuaddr - Returns the gpu address of IOMMU regsiter
* @mmu - Pointer to mmu structure
- * @reg_map_desc - Out parameter in which the address of the array containing
- * pointers to register map descriptors is returned. The caller is supposed
- * to free this array
+ * @iommu_unit - The iommu unit for which base address is requested
+ * @ctx_id - The context ID of the IOMMU ctx
+ * @reg - The register for which address is required
*
* Return - The number of iommu units which is also the number of register
* mapped descriptor arrays which the out parameter will have
*/
-static int kgsl_iommu_get_reg_map_desc(struct kgsl_mmu *mmu,
- void **reg_map_desc)
+static unsigned int kgsl_iommu_get_reg_gpuaddr(struct kgsl_mmu *mmu,
+ int iommu_unit, int ctx_id, int reg)
{
struct kgsl_iommu *iommu = mmu->priv;
- void **reg_desc_ptr;
- int i;
- /*
- * Alocate array of pointers that will hold address of the register map
- * descriptors
- */
- reg_desc_ptr = kmalloc(iommu->unit_count *
- sizeof(struct kgsl_memdesc *), GFP_KERNEL);
- if (!reg_desc_ptr) {
- KGSL_CORE_ERR("Failed to kmalloc(%d)\n",
- iommu->unit_count * sizeof(struct kgsl_memdesc *));
- return -ENOMEM;
- }
+ if (KGSL_IOMMU_GLOBAL_BASE == reg)
+ return iommu->iommu_units[iommu_unit].reg_map.gpuaddr;
+ else
+ return iommu->iommu_units[iommu_unit].reg_map.gpuaddr +
+ iommu->iommu_reg_list[reg].reg_offset +
+ (ctx_id << KGSL_IOMMU_CTX_SHIFT) + iommu->ctx_offset;
+}
- for (i = 0; i < iommu->unit_count; i++)
- reg_desc_ptr[i] = &(iommu->iommu_units[i].reg_map);
-
- *reg_map_desc = reg_desc_ptr;
- return i;
+static int kgsl_iommu_get_num_iommu_units(struct kgsl_mmu *mmu)
+{
+ struct kgsl_iommu *iommu = mmu->priv;
+ return iommu->unit_count;
}
struct kgsl_mmu_ops iommu_ops = {
@@ -1047,7 +1088,10 @@
.mmu_enable_clk = kgsl_iommu_enable_clk,
.mmu_disable_clk_on_ts = kgsl_iommu_disable_clk_on_ts,
.mmu_get_pt_lsb = kgsl_iommu_get_pt_lsb,
- .mmu_get_reg_map_desc = kgsl_iommu_get_reg_map_desc,
+ .mmu_get_reg_gpuaddr = kgsl_iommu_get_reg_gpuaddr,
+ .mmu_get_num_iommu_units = kgsl_iommu_get_num_iommu_units,
+ .mmu_pt_equal = kgsl_iommu_pt_equal,
+ .mmu_get_pt_base_addr = kgsl_iommu_get_pt_base_addr,
};
struct kgsl_mmu_pt_ops iommu_pt_ops = {
@@ -1055,6 +1099,4 @@
.mmu_unmap = kgsl_iommu_unmap,
.mmu_create_pagetable = kgsl_iommu_create_pagetable,
.mmu_destroy_pagetable = kgsl_iommu_destroy_pagetable,
- .mmu_pt_equal = kgsl_iommu_pt_equal,
- .mmu_pt_get_base_addr = kgsl_iommu_pt_get_base_addr,
};
diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h
index f14db93..7dc222e 100644
--- a/drivers/gpu/msm/kgsl_iommu.h
+++ b/drivers/gpu/msm/kgsl_iommu.h
@@ -15,15 +15,23 @@
#include <mach/iommu.h>
-/* IOMMU registers and masks */
-#define KGSL_IOMMU_TTBR0 0x10
-#define KGSL_IOMMU_TTBR1 0x14
-#define KGSL_IOMMU_FSR 0x20
+#define KGSL_IOMMU_CTX_OFFSET_V1 0
+#define KGSL_IOMMU_CTX_SHIFT 12
-#define KGSL_IOMMU_TTBR0_PA_MASK 0x0003FFFF
-#define KGSL_IOMMU_TTBR0_PA_SHIFT 14
-#define KGSL_IOMMU_CTX_TLBIALL 0x800
-#define KGSL_IOMMU_CTX_SHIFT 12
+enum kgsl_iommu_reg_map {
+ KGSL_IOMMU_GLOBAL_BASE = 0,
+ KGSL_IOMMU_CTX_TTBR0,
+ KGSL_IOMMU_CTX_TTBR1,
+ KGSL_IOMMU_CTX_FSR,
+ KGSL_IOMMU_CTX_TLBIALL,
+ KGSL_IOMMU_REG_MAX
+};
+
+struct kgsl_iommu_register_list {
+ unsigned int reg_offset;
+ unsigned int reg_mask;
+ unsigned int reg_shift;
+};
/*
* Max number of iommu units that the gpu core can have
@@ -35,20 +43,25 @@
#define KGSL_IOMMU_MAX_DEVS_PER_UNIT 2
/* Macros to read/write IOMMU registers */
-#define KGSL_IOMMU_SET_IOMMU_REG(base_addr, ctx, REG, val) \
- writel_relaxed(val, base_addr + \
- (ctx << KGSL_IOMMU_CTX_SHIFT) + \
- KGSL_IOMMU_##REG)
+#define KGSL_IOMMU_SET_CTX_REG(iommu, iommu_unit, ctx, REG, val) \
+ writel_relaxed(val, \
+ iommu_unit->reg_map.hostptr + \
+ iommu->iommu_reg_list[KGSL_IOMMU_CTX_##REG].reg_offset +\
+ (ctx << KGSL_IOMMU_CTX_SHIFT) + \
+ iommu->ctx_offset)
-#define KGSL_IOMMU_GET_IOMMU_REG(base_addr, ctx, REG) \
- readl_relaxed(base_addr + \
- (ctx << KGSL_IOMMU_CTX_SHIFT) + \
- KGSL_IOMMU_##REG)
+#define KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit, ctx, REG) \
+ readl_relaxed( \
+ iommu_unit->reg_map.hostptr + \
+ iommu->iommu_reg_list[KGSL_IOMMU_CTX_##REG].reg_offset +\
+ (ctx << KGSL_IOMMU_CTX_SHIFT) + \
+ iommu->ctx_offset)
/* Gets the lsb value of pagetable */
-#define KGSL_IOMMMU_PT_LSB(pt_val) \
- (pt_val & ~(KGSL_IOMMU_TTBR0_PA_MASK << \
- KGSL_IOMMU_TTBR0_PA_SHIFT))
+#define KGSL_IOMMMU_PT_LSB(iommu, pt_val) \
+ (pt_val & \
+ ~(iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask << \
+ iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift))
/* offset at which a nop command is placed in setstate_memory */
#define KGSL_IOMMU_SETSTATE_NOP_OFFSET 1024
@@ -99,6 +112,9 @@
* @clk_event_queued: Indicates whether an event to disable clocks
* is already queued or not
* @device: Pointer to kgsl device
+ * @ctx_offset: The context offset to be added to base address when
+ * accessing IOMMU registers
+ * @iommu_reg_list: List of IOMMU registers { offset, map, shift } array
*/
struct kgsl_iommu {
struct kgsl_iommu_unit iommu_units[KGSL_IOMMU_MAX_UNITS];
@@ -106,6 +122,8 @@
unsigned int iommu_last_cmd_ts;
bool clk_event_queued;
struct kgsl_device *device;
+ unsigned int ctx_offset;
+ struct kgsl_iommu_register_list *iommu_reg_list;
};
/*
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 0426339..3aea81f 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/iommu.h>
+#include <mach/iommu.h>
#include <mach/socinfo.h>
#include "kgsl.h"
@@ -325,14 +326,16 @@
}
int
-kgsl_mmu_get_ptname_from_ptbase(unsigned int pt_base)
+kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, unsigned int pt_base)
{
struct kgsl_pagetable *pt;
int ptid = -1;
+ if (!mmu->mmu_ops || !mmu->mmu_ops->mmu_pt_equal)
+ return KGSL_MMU_GLOBAL_PT;
spin_lock(&kgsl_driver.ptlock);
list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) {
- if (pt->pt_ops->mmu_pt_equal(pt, pt_base)) {
+ if (mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base)) {
ptid = (int) pt->name;
break;
}
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 8221b80..234629b 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -139,8 +139,15 @@
int (*mmu_get_pt_lsb)(struct kgsl_mmu *mmu,
unsigned int unit_id,
enum kgsl_iommu_context_id ctx_id);
- int (*mmu_get_reg_map_desc)(struct kgsl_mmu *mmu,
- void **reg_map_desc);
+ unsigned int (*mmu_get_reg_gpuaddr)(struct kgsl_mmu *mmu,
+ int iommu_unit_num, int ctx_id, int reg);
+ int (*mmu_get_num_iommu_units)(struct kgsl_mmu *mmu);
+ int (*mmu_pt_equal) (struct kgsl_mmu *mmu,
+ struct kgsl_pagetable *pt,
+ unsigned int pt_base);
+ unsigned int (*mmu_get_pt_base_addr)
+ (struct kgsl_mmu *mmu,
+ struct kgsl_pagetable *pt);
};
struct kgsl_mmu_pt_ops {
@@ -153,10 +160,6 @@
unsigned int *tlb_flags);
void *(*mmu_create_pagetable) (void);
void (*mmu_destroy_pagetable) (void *pt);
- int (*mmu_pt_equal) (struct kgsl_pagetable *pt,
- unsigned int pt_base);
- unsigned int (*mmu_pt_get_base_addr)
- (struct kgsl_pagetable *pt);
};
struct kgsl_mmu {
@@ -196,7 +199,8 @@
unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
void kgsl_setstate(struct kgsl_mmu *mmu, unsigned int context_id,
uint32_t flags);
-int kgsl_mmu_get_ptname_from_ptbase(unsigned int pt_base);
+int kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu,
+ unsigned int pt_base);
int kgsl_mmu_pt_get_flags(struct kgsl_pagetable *pt,
enum kgsl_deviceid id);
void kgsl_mmu_ptpool_destroy(void *ptpool);
@@ -242,28 +246,21 @@
mmu->mmu_ops->mmu_stop(mmu);
}
-static inline int kgsl_mmu_pt_equal(struct kgsl_pagetable *pt,
+static inline int kgsl_mmu_pt_equal(struct kgsl_mmu *mmu,
+ struct kgsl_pagetable *pt,
unsigned int pt_base)
{
- if (KGSL_MMU_TYPE_NONE == kgsl_mmu_get_mmutype())
+ if (mmu->mmu_ops && mmu->mmu_ops->mmu_pt_equal)
+ return mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base);
+ else
return 1;
- else
- return pt->pt_ops->mmu_pt_equal(pt, pt_base);
}
-static inline unsigned int kgsl_mmu_pt_get_base_addr(struct kgsl_pagetable *pt)
+static inline unsigned int kgsl_mmu_get_pt_base_addr(struct kgsl_mmu *mmu,
+ struct kgsl_pagetable *pt)
{
- if (KGSL_MMU_TYPE_NONE == kgsl_mmu_get_mmutype())
- return 0;
- else
- return pt->pt_ops->mmu_pt_get_base_addr(pt);
-}
-
-static inline int kgsl_mmu_get_reg_map_desc(struct kgsl_mmu *mmu,
- void **reg_map_desc)
-{
- if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_reg_map_desc)
- return mmu->mmu_ops->mmu_get_reg_map_desc(mmu, reg_map_desc);
+ if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_pt_base_addr)
+ return mmu->mmu_ops->mmu_get_pt_base_addr(mmu, pt);
else
return 0;
}
@@ -304,4 +301,23 @@
MH_INTERRUPT_MASK__AXI_WRITE_ERROR);
}
+static inline unsigned int kgsl_mmu_get_reg_gpuaddr(struct kgsl_mmu *mmu,
+ int iommu_unit_num,
+ int ctx_id, int reg)
+{
+ if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_reg_gpuaddr)
+ return mmu->mmu_ops->mmu_get_reg_gpuaddr(mmu, iommu_unit_num,
+ ctx_id, reg);
+ else
+ return 0;
+}
+
+static inline int kgsl_mmu_get_num_iommu_units(struct kgsl_mmu *mmu)
+{
+ if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_num_iommu_units)
+ return mmu->mmu_ops->mmu_get_num_iommu_units(mmu);
+ else
+ return 0;
+}
+
#endif /* __KGSL_MMU_H */
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 736fb4e..8c45475 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -349,6 +349,25 @@
return (unsigned int) (ptr - buf);
}
+static int kgsl_pwrctrl_gpu_available_frequencies_show(
+ struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct kgsl_device *device = kgsl_device_from_dev(dev);
+ struct kgsl_pwrctrl *pwr;
+ int index, num_chars = 0;
+
+ if (device == NULL)
+ return 0;
+ pwr = &device->pwrctrl;
+ for (index = 0; index < pwr->num_pwrlevels - 1; index++)
+ num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",
+ pwr->pwrlevels[index].gpu_freq);
+ buf[num_chars++] = '\n';
+ return num_chars;
+}
+
DEVICE_ATTR(gpuclk, 0644, kgsl_pwrctrl_gpuclk_show, kgsl_pwrctrl_gpuclk_store);
DEVICE_ATTR(max_gpuclk, 0644, kgsl_pwrctrl_max_gpuclk_show,
kgsl_pwrctrl_max_gpuclk_store);
@@ -359,6 +378,9 @@
NULL);
DEVICE_ATTR(gputop, 0444, kgsl_pwrctrl_gputop_show,
NULL);
+DEVICE_ATTR(gpu_available_frequencies, 0444,
+ kgsl_pwrctrl_gpu_available_frequencies_show,
+ NULL);
static const struct device_attribute *pwrctrl_attr_list[] = {
&dev_attr_gpuclk,
@@ -367,6 +389,7 @@
&dev_attr_idle_timer,
&dev_attr_gpubusy,
&dev_attr_gputop,
+ &dev_attr_gpu_available_frequencies,
NULL
};
@@ -442,16 +465,17 @@
&pwr->power_flags)) {
trace_kgsl_clk(device, state);
/* High latency clock maintenance. */
- if ((pwr->pwrlevels[0].gpu_freq > 0) &&
- (device->state != KGSL_STATE_NAP)) {
+ if (device->state != KGSL_STATE_NAP) {
for (i = KGSL_MAX_CLKS - 1; i > 0; i--)
if (pwr->grp_clks[i])
clk_prepare(pwr->grp_clks[i]);
- clk_set_rate(pwr->grp_clks[0],
- pwr->pwrlevels[pwr->active_pwrlevel].
+
+ if (pwr->pwrlevels[0].gpu_freq > 0)
+ clk_set_rate(pwr->grp_clks[0],
+ pwr->pwrlevels
+ [pwr->active_pwrlevel].
gpu_freq);
}
-
/* as last step, enable grp_clk
this is to let GPU interrupt to come */
for (i = KGSL_MAX_CLKS - 1; i > 0; i--)
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index cb33ec8..c2ce5c7 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -510,6 +510,25 @@
struct page **pages = NULL;
pgprot_t page_prot = pgprot_writecombine(PAGE_KERNEL);
void *ptr;
+ struct sysinfo si;
+
+ /*
+ * Get the current memory information to be used in deciding if we
+ * should go ahead with this allocation
+ */
+
+ si_meminfo(&si);
+
+ /*
+ * Limit the size of the allocation to the amount of free memory minus
+ * 32MB. Why 32MB? Because thats the buffer that page_alloc uses and
+ * it just seems like a reasonable limit that won't make the OOM killer
+ * go all serial on us. Of course, if we are down this low all bets
+ * are off but above all do no harm.
+ */
+
+ if (size >= ((si.freeram << PAGE_SHIFT) - SZ_32M))
+ return -ENOMEM;
/*
* Add guard page to the end of the allocation when the
@@ -681,7 +700,8 @@
{
unsigned int protflags;
- BUG_ON(size == 0);
+ if (size == 0)
+ return -EINVAL;
protflags = GSL_PT_PAGE_RV;
if (!(flags & KGSL_MEMFLAGS_GPUREADONLY))
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 824d806..abaa8ce 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -175,7 +175,8 @@
/* Get the current PT base */
header->ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
/* And the PID for the task leader */
- pid = header->pid = kgsl_mmu_get_ptname_from_ptbase(header->ptbase);
+ pid = header->pid = kgsl_mmu_get_ptname_from_ptbase(&device->mmu,
+ header->ptbase);
task = find_task_by_vpid(pid);
@@ -307,7 +308,7 @@
struct kgsl_snapshot_object *obj;
int offset;
- entry = kgsl_get_mem_entry(ptbase, gpuaddr, size);
+ entry = kgsl_get_mem_entry(device, ptbase, gpuaddr, size);
if (entry == NULL) {
KGSL_DRV_ERR(device, "Unable to find GPU buffer %8.8X\n",
diff --git a/drivers/gpu/msm/z180_postmortem.c b/drivers/gpu/msm/z180_postmortem.c
index a9b0c50..7cf3799 100644
--- a/drivers/gpu/msm/z180_postmortem.c
+++ b/drivers/gpu/msm/z180_postmortem.c
@@ -152,7 +152,8 @@
ib_gpuptr = rb_hostptr[i+1];
- entry = kgsl_get_mem_entry(pt_base, ib_gpuptr, 1);
+ entry = kgsl_get_mem_entry(device, pt_base, ib_gpuptr,
+ 1);
if (entry == NULL) {
KGSL_LOG_DUMP(device,
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index c1617bff..085b632 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -328,12 +328,14 @@
dev->clk_state = state;
if (state != 0) {
clk_enable(dev->clk);
- clk_enable(dev->pclk);
+ if (!dev->pdata->keep_ahb_clk_on)
+ clk_enable(dev->pclk);
} else {
qup_update_state(dev, QUP_RESET_STATE);
clk_disable(dev->clk);
qup_config_core_on_en(dev);
- clk_disable(dev->pclk);
+ if (!dev->pdata->keep_ahb_clk_on)
+ clk_disable(dev->pclk);
}
}
@@ -1325,6 +1327,12 @@
dev->clk_state = 0;
clk_prepare(dev->clk);
clk_prepare(dev->pclk);
+ /* If the same AHB clock is used on Modem side
+ * switch it on here itself and don't switch it
+ * on and off during suspend and resume.
+ */
+ if (dev->pdata->keep_ahb_clk_on)
+ clk_enable(dev->pclk);
setup_timer(&dev->pwr_timer, qup_i2c_pwr_timer, (unsigned long) dev);
pm_runtime_set_active(&pdev->dev);
@@ -1396,9 +1404,11 @@
free_irq(dev->err_irq, dev);
i2c_del_adapter(&dev->adapter);
clk_unprepare(dev->clk);
- clk_unprepare(dev->pclk);
+ if (!dev->pdata->keep_ahb_clk_on) {
+ clk_unprepare(dev->pclk);
+ clk_put(dev->pclk);
+ }
clk_put(dev->clk);
- clk_put(dev->pclk);
qup_i2c_free_gpios(dev);
if (dev->gsbi)
iounmap(dev->gsbi);
@@ -1434,7 +1444,8 @@
if (dev->clk_state != 0)
qup_i2c_pwr_mgmt(dev, 0);
clk_unprepare(dev->clk);
- clk_unprepare(dev->pclk);
+ if (!dev->pdata->keep_ahb_clk_on)
+ clk_unprepare(dev->pclk);
qup_i2c_free_gpios(dev);
return 0;
}
@@ -1445,7 +1456,8 @@
struct qup_i2c_dev *dev = platform_get_drvdata(pdev);
BUG_ON(qup_i2c_request_gpios(dev) != 0);
clk_prepare(dev->clk);
- clk_prepare(dev->pclk);
+ if (!dev->pdata->keep_ahb_clk_on)
+ clk_prepare(dev->pclk);
dev->suspended = 0;
return 0;
}
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index d3da652..04a7598 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -123,6 +123,7 @@
struct delayed_work input_work;
u32 use_poll;
u32 poll_interval;
+ u32 dlpf_index;
};
struct sensor_regulator {
@@ -137,6 +138,39 @@
{NULL, "vlogic", 1800000, 1800000},
};
+struct dlpf_cfg_tb {
+ u8 cfg; /* cfg index */
+ u32 lpf_bw; /* low pass filter bandwidth in Hz */
+ u32 sample_rate; /* analog sample rate in Khz, 1 or 8 */
+};
+
+static struct dlpf_cfg_tb dlpf_table[] = {
+ {6, 5, 1},
+ {5, 10, 1},
+ {4, 20, 1},
+ {3, 42, 1},
+ {2, 98, 1},
+ {1, 188, 1},
+ {0, 256, 8},
+};
+
+static u8 interval_to_dlpf_cfg(u32 interval)
+{
+ u32 sample_rate = 1000 / interval;
+ u32 i;
+
+ /* the filter bandwidth needs to be greater or
+ * equal to half of the sample rate
+ */
+ for (i = 0; i < sizeof(dlpf_table)/sizeof(dlpf_table[0]); i++) {
+ if (dlpf_table[i].lpf_bw * 2 >= sample_rate)
+ return i;
+ }
+
+ /* return the maximum possible */
+ return --i;
+}
+
static int mpu3050_config_regulator(struct i2c_client *client, bool on)
{
int rc = 0, i;
@@ -217,6 +251,9 @@
{
struct mpu3050_sensor *sensor = dev_get_drvdata(dev);
unsigned long interval_ms;
+ unsigned int dlpf_index;
+ u8 divider, reg;
+ int ret;
if (kstrtoul(buf, 10, &interval_ms))
return -EINVAL;
@@ -224,12 +261,27 @@
(interval_ms > MPU3050_MAX_POLL_INTERVAL))
return -EINVAL;
- if (sensor)
- sensor->poll_interval = interval_ms;
+ dlpf_index = interval_to_dlpf_cfg(interval_ms);
+ divider = interval_ms * dlpf_table[dlpf_index].sample_rate - 1;
- /* Output frequency divider. The poll interval */
- i2c_smbus_write_byte_data(sensor->client, MPU3050_SMPLRT_DIV,
- interval_ms - 1);
+ if (sensor->dlpf_index != dlpf_index) {
+ /* Set low pass filter and full scale */
+ reg = dlpf_table[dlpf_index].cfg;
+ reg |= MPU3050_DEFAULT_FS_RANGE << 3;
+ reg |= MPU3050_EXT_SYNC_NONE << 5;
+ ret = i2c_smbus_write_byte_data(sensor->client,
+ MPU3050_DLPF_FS_SYNC, reg);
+ if (ret == 0)
+ sensor->dlpf_index = dlpf_index;
+ }
+
+ if (sensor->poll_interval != interval_ms) {
+ /* Output frequency divider. The poll interval */
+ ret = i2c_smbus_write_byte_data(sensor->client,
+ MPU3050_SMPLRT_DIV, divider);
+ if (ret == 0)
+ sensor->poll_interval = interval_ms;
+ }
return size;
}
@@ -482,8 +534,8 @@
return ret;
/* Set low pass filter and full scale */
- reg = MPU3050_DEFAULT_FS_RANGE;
- reg |= MPU3050_DLPF_CFG_42HZ << 3;
+ reg = MPU3050_DLPF_CFG_42HZ;
+ reg |= MPU3050_DEFAULT_FS_RANGE << 3;
reg |= MPU3050_EXT_SYNC_NONE << 5;
ret = i2c_smbus_write_byte_data(client, MPU3050_DLPF_FS_SYNC, reg);
if (ret < 0)
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index e696973..f10f433 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -2773,7 +2773,7 @@
{ }
};
MODULE_DEVICE_TABLE(i2c, mxt_id);
-#ifdef OF_CONFIG
+#ifdef CONFIG_OF
static struct of_device_id mxt_match_table[] = {
{ .compatible = "atmel,mxt-ts",},
{ },
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 9240605..26e8496 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -307,6 +307,16 @@
This option enables support for LEDs connected to the PCA9633
LED driver chip accessed via the I2C bus.
+config LEDS_QPNP
+ tristate "Support for QPNP LEDs"
+ depends on SPMI && OF_SPMI
+ help
+ This driver supports the leds functionality of Qualcomm PNP PMIC. It
+ includes RGB Leds, WLED and Flash Led.
+
+ To compile this driver as a module, choose M here: the module will
+ be called leds-qpnp.
+
config LEDS_WM831X_STATUS
tristate "LED support for status LEDs on WM831x PMICs"
depends on LEDS_CLASS
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 8edd465..c688898 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -19,6 +19,7 @@
obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o
obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o
obj-$(CONFIG_LEDS_PM8XXX) += leds-pm8xxx.o
+obj-$(CONFIG_LEDS_QPNP) += leds-qpnp.o
obj-$(CONFIG_LEDS_GPIO_REGISTER) += leds-gpio-register.o
obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
new file mode 100644
index 0000000..f42fb5e
--- /dev/null
+++ b/drivers/leds/leds-qpnp.c
@@ -0,0 +1,725 @@
+
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include <linux/err.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/spmi.h>
+
+#define WLED_MOD_EN_REG(base, n) (base + 0x60 + n*0x10)
+#define WLED_IDAC_DLY_REG(base, n) (WLED_MOD_EN_REG(base, n) + 0x01)
+#define WLED_FULL_SCALE_REG(base, n) (WLED_IDAC_DLY_REG(base, n) + 0x01)
+
+/* wled control registers */
+#define WLED_BRIGHTNESS_CNTL_LSB(base, n) (base + 0x40 + 2*n)
+#define WLED_BRIGHTNESS_CNTL_MSB(base, n) (base + 0x41 + 2*n)
+#define WLED_MOD_CTRL_REG(base) (base + 0x46)
+#define WLED_SYNC_REG(base) (base + 0x47)
+#define WLED_FDBCK_CTRL_REG(base) (base + 0x48)
+#define WLED_SWITCHING_FREQ_REG(base) (base + 0x4C)
+#define WLED_OVP_CFG_REG(base) (base + 0x4D)
+#define WLED_BOOST_LIMIT_REG(base) (base + 0x4E)
+#define WLED_CURR_SINK_REG(base) (base + 0x4F)
+#define WLED_HIGH_POLE_CAP_REG(base) (base + 0x58)
+#define WLED_CURR_SINK_MASK 0xE0
+#define WLED_CURR_SINK_SHFT 0x05
+#define WLED_SWITCH_FREQ_MASK 0x02
+#define WLED_OVP_VAL_MASK 0x03
+#define WLED_OVP_VAL_BIT_SHFT 0x00
+#define WLED_BOOST_LIMIT_MASK 0x07
+#define WLED_BOOST_LIMIT_BIT_SHFT 0x00
+#define WLED_BOOST_ON 0x80
+#define WLED_BOOST_OFF 0x00
+#define WLED_EN_MASK 0x80
+#define WLED_NO_MASK 0x00
+#define WLED_CP_SELECT_MAX 0x03
+#define WLED_CP_SELECT_MASK 0x02
+#define WLED_USE_EXT_GEN_MOD_SRC 0x01
+#define WLED_CTL_DLY_STEP 200
+#define WLED_CTL_DLY_MAX 1400
+#define WLED_MAX_CURR 25
+#define WLED_MSB_MASK 0x0F
+#define WLED_MAX_CURR_MASK 0x19
+#define WLED_OP_FDBCK_MASK 0x07
+#define WLED_OP_FDBCK_BIT_SHFT 0x00
+
+#define WLED_MAX_LEVEL 255
+#define WLED_8_BIT_MASK 0xFF
+#define WLED_4_BIT_MASK 0x0F
+#define WLED_8_BIT_SHFT 0x08
+#define WLED_MAX_DUTY_CYCLE 0xFFF
+
+#define WLED_SYNC_VAL 0x07
+#define WLED_SYNC_RESET_VAL 0x00
+
+#define WLED_TRIGGER_DEFAULT "none"
+#define WLED_FLAGS_DEFAULT 0x00
+#define WLED_DEFAULT_STRINGS 0x01
+#define WLED_DEFAULT_OVP_VAL 0x02
+#define WLED_BOOST_LIM_DEFAULT 0x03
+#define WLED_CP_SEL_DEFAULT 0x00
+#define WLED_CTRL_DLY_DEFAULT 0x00
+#define WLED_SWITCH_FREQ_DEFAULT 0x02
+
+/**
+ * enum qpnp_leds - QPNP supported led ids
+ * @QPNP_ID_WLED - White led backlight
+ */
+enum qpnp_leds {
+ QPNP_ID_WLED,
+};
+
+/* current boost limit */
+enum wled_current_boost_limit {
+ WLED_CURR_LIMIT_105mA,
+ WLED_CURR_LIMIT_385mA,
+ WLED_CURR_LIMIT_525mA,
+ WLED_CURR_LIMIT_805mA,
+ WLED_CURR_LIMIT_980mA,
+ WLED_CURR_LIMIT_1260mA,
+ WLED_CURR_LIMIT_1400mA,
+ WLED_CURR_LIMIT_1680mA,
+};
+
+/* over voltage protection threshold */
+enum wled_ovp_threshold {
+ WLED_OVP_35V,
+ WLED_OVP_32V,
+ WLED_OVP_29V,
+ WLED_OVP_37V,
+};
+
+/* switch frquency */
+enum wled_switch_freq {
+ WLED_800kHz = 0,
+ WLED_960kHz,
+ WLED_1600kHz,
+ WLED_3200kHz,
+};
+
+static u8 wled_debug_regs[] = {
+ /* common registers */
+ 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4d, 0x4e, 0x4f,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ /* LED1 */
+ 0x60, 0x61, 0x62, 0x63, 0x66,
+ /* LED1 */
+ 0x70, 0x71, 0x72, 0x73, 0x76,
+ /* LED1 */
+ 0x80, 0x81, 0x82, 0x83, 0x86,
+};
+
+/**
+ * wled_config_data - wled configuration data
+ * @num_strings - number of wled strings supported
+ * @ovp_val - over voltage protection threshold
+ * @boost_curr_lim - boot current limit
+ * @cp_select - high pole capacitance
+ * @ctrl_delay_us - delay in activation of led
+ * @dig_mod_gen_en - digital module generator
+ * @cs_out_en - current sink output enable
+ * @op_fdbck - selection of output as feedback for the boost
+ */
+struct wled_config_data {
+ u8 num_strings;
+ u8 ovp_val;
+ u8 boost_curr_lim;
+ u8 cp_select;
+ u8 ctrl_delay_us;
+ u8 switch_freq;
+ bool dig_mod_gen_en;
+ bool cs_out_en;
+ bool op_fdbck;
+};
+
+/**
+ * struct qpnp_led_data - internal led data structure
+ * @led_classdev - led class device
+ * @id - led index
+ * @base_reg - base register given in device tree
+ * @lock - to protect the transactions
+ * @reg - cached value of led register
+ * @max_current - maximum current supported by LED
+ * @default_on - true: default state max, false, default state 0
+ */
+struct qpnp_led_data {
+ struct led_classdev cdev;
+ struct spmi_device *spmi_dev;
+ int id;
+ u16 base;
+ u8 reg;
+ struct mutex lock;
+ struct wled_config_data *wled_cfg;
+ int max_current;
+ bool default_on;
+};
+
+static int
+qpnp_led_masked_write(struct qpnp_led_data *led, u16 addr, u8 mask, u8 val)
+{
+ int rc;
+ u8 reg;
+
+ rc = spmi_ext_register_readl(led->spmi_dev->ctrl, led->spmi_dev->sid,
+ addr, ®, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "Unable to read from addr=%x, rc(%d)\n", addr, rc);
+ }
+
+ reg &= ~mask;
+ reg |= val;
+
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
+ addr, ®, 1);
+ if (rc)
+ dev_err(&led->spmi_dev->dev,
+ "Unable to write to addr=%x, rc(%d)\n", addr, rc);
+ return rc;
+}
+
+static int qpnp_wled_set(struct qpnp_led_data *led)
+{
+ int rc, duty;
+ u8 level, val, i, num_wled_strings;
+
+ level = led->cdev.brightness;
+
+ if (level > WLED_MAX_LEVEL)
+ level = WLED_MAX_LEVEL;
+ if (level == 0) {
+ val = WLED_BOOST_OFF;
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
+ led->spmi_dev->sid, WLED_MOD_CTRL_REG(led->base),
+ &val, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED write ctrl reg failed(%d)\n", rc);
+ return rc;
+ }
+ } else {
+ val = WLED_BOOST_ON;
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
+ led->spmi_dev->sid, WLED_MOD_CTRL_REG(led->base),
+ &val, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED write ctrl reg failed(%d)\n", rc);
+ return rc;
+ }
+ }
+
+ duty = (WLED_MAX_DUTY_CYCLE * level) / WLED_MAX_LEVEL;
+
+ num_wled_strings = led->wled_cfg->num_strings;
+
+ /* program brightness control registers */
+ for (i = 0; i < num_wled_strings; i++) {
+ rc = qpnp_led_masked_write(led,
+ WLED_BRIGHTNESS_CNTL_MSB(led->base, i), WLED_MSB_MASK,
+ (duty >> WLED_8_BIT_SHFT) & WLED_4_BIT_MASK);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED set brightness MSB failed(%d)\n", rc);
+ return rc;
+ }
+ val = duty & WLED_8_BIT_MASK;
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl,
+ led->spmi_dev->sid,
+ WLED_BRIGHTNESS_CNTL_LSB(led->base, i), &val, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED set brightness LSB failed(%d)\n", rc);
+ return rc;
+ }
+ }
+
+ /* sync */
+ val = WLED_SYNC_VAL;
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
+ WLED_SYNC_REG(led->base), &val, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED set sync reg failed(%d)\n", rc);
+ return rc;
+ }
+
+ val = WLED_SYNC_RESET_VAL;
+ rc = spmi_ext_register_writel(led->spmi_dev->ctrl, led->spmi_dev->sid,
+ WLED_SYNC_REG(led->base), &val, 1);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED reset sync reg failed(%d)\n", rc);
+ return rc;
+ }
+ return 0;
+}
+
+static void qpnp_wled_dump_regs(struct qpnp_led_data *led)
+{
+ int i;
+ u8 val;
+
+ pr_debug("===== WLED register dump start =====\n");
+ for (i = 0; i < ARRAY_SIZE(wled_debug_regs); i++) {
+ spmi_ext_register_readl(led->spmi_dev->ctrl,
+ led->spmi_dev->sid,
+ led->base + wled_debug_regs[i],
+ &val, sizeof(val));
+ pr_debug("0x%x = 0x%x\n", led->base + wled_debug_regs[i], val);
+ }
+ pr_debug("===== WLED register dump end =====\n");
+}
+
+static void qpnp_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ int rc;
+ struct qpnp_led_data *led;
+
+ led = container_of(led_cdev, struct qpnp_led_data, cdev);
+
+ if (value < LED_OFF || value > led->cdev.max_brightness) {
+ dev_err(led->cdev.dev, "Invalid brightness value\n");
+ return;
+ }
+
+ mutex_lock(&led->lock);
+ led->cdev.brightness = value;
+
+ switch (led->id) {
+ case QPNP_ID_WLED:
+ rc = qpnp_wled_set(led);
+ if (rc < 0)
+ dev_err(led->cdev.dev,
+ "WLED set brightness failed (%d)\n", rc);
+ break;
+ default:
+ dev_err(led->cdev.dev, "Invalid LED(%d)\n", led->id);
+ break;
+ }
+ mutex_unlock(&led->lock);
+}
+
+static int __devinit qpnp_led_set_max_brightness(struct qpnp_led_data *led)
+{
+ switch (led->id) {
+ case QPNP_ID_WLED:
+ led->cdev.max_brightness = WLED_MAX_LEVEL;
+ break;
+ default:
+ dev_err(led->cdev.dev, "Invalid LED(%d)\n", led->id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static enum led_brightness qpnp_led_get(struct led_classdev *led_cdev)
+{
+ struct qpnp_led_data *led;
+
+ led = container_of(led_cdev, struct qpnp_led_data, cdev);
+
+ return led->cdev.brightness;
+}
+
+static int __devinit qpnp_wled_init(struct qpnp_led_data *led)
+{
+ int rc, i;
+ u8 num_wled_strings;
+
+ num_wled_strings = led->wled_cfg->num_strings;
+
+ /* verify ranges */
+ if (led->wled_cfg->ovp_val > WLED_OVP_37V) {
+ dev_err(&led->spmi_dev->dev, "Invalid ovp value\n");
+ return -EINVAL;
+ }
+
+ if (led->wled_cfg->boost_curr_lim > WLED_CURR_LIMIT_1680mA) {
+ dev_err(&led->spmi_dev->dev, "Invalid boost current limit\n");
+ return -EINVAL;
+ }
+
+ if (led->wled_cfg->cp_select > WLED_CP_SELECT_MAX) {
+ dev_err(&led->spmi_dev->dev, "Invalid pole capacitance\n");
+ return -EINVAL;
+ }
+
+ if ((led->max_current > WLED_MAX_CURR)) {
+ dev_err(&led->spmi_dev->dev, "Invalid max current\n");
+ return -EINVAL;
+ }
+
+ if ((led->wled_cfg->ctrl_delay_us % WLED_CTL_DLY_STEP) ||
+ (led->wled_cfg->ctrl_delay_us > WLED_CTL_DLY_MAX)) {
+ dev_err(&led->spmi_dev->dev, "Invalid control delay\n");
+ return -EINVAL;
+ }
+
+ /* program over voltage protection threshold */
+ rc = qpnp_led_masked_write(led, WLED_OVP_CFG_REG(led->base),
+ WLED_OVP_VAL_MASK,
+ (led->wled_cfg->ovp_val << WLED_OVP_VAL_BIT_SHFT));
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED OVP reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ /* program current boost limit */
+ rc = qpnp_led_masked_write(led, WLED_BOOST_LIMIT_REG(led->base),
+ WLED_BOOST_LIMIT_MASK, led->wled_cfg->boost_curr_lim);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED boost limit reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ /* program output feedback */
+ rc = qpnp_led_masked_write(led, WLED_FDBCK_CTRL_REG(led->base),
+ WLED_OP_FDBCK_MASK,
+ (led->wled_cfg->op_fdbck << WLED_OP_FDBCK_BIT_SHFT));
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED fdbck ctrl reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ /* program switch frequency */
+ rc = qpnp_led_masked_write(led, WLED_SWITCHING_FREQ_REG(led->base),
+ WLED_SWITCH_FREQ_MASK, led->wled_cfg->switch_freq);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED switch freq reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ /* program current sink */
+ if (led->wled_cfg->cs_out_en) {
+ rc = qpnp_led_masked_write(led, WLED_CURR_SINK_REG(led->base),
+ WLED_CURR_SINK_MASK,
+ (led->wled_cfg->num_strings << WLED_CURR_SINK_SHFT));
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED curr sink reg write failed(%d)\n", rc);
+ return rc;
+ }
+ }
+
+ /* program high pole capacitance */
+ rc = qpnp_led_masked_write(led, WLED_HIGH_POLE_CAP_REG(led->base),
+ WLED_CP_SELECT_MASK, led->wled_cfg->cp_select);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED pole cap reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ /* program modulator, current mod src and cabc */
+ for (i = 0; i < num_wled_strings; i++) {
+ rc = qpnp_led_masked_write(led, WLED_MOD_EN_REG(led->base, i),
+ WLED_NO_MASK, WLED_EN_MASK);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED mod enable reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ if (led->wled_cfg->dig_mod_gen_en) {
+ rc = qpnp_led_masked_write(led,
+ WLED_MOD_EN_REG(led->base, i),
+ WLED_NO_MASK, WLED_USE_EXT_GEN_MOD_SRC);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED dig mod en reg write failed(%d)\n", rc);
+ }
+ }
+
+ rc = qpnp_led_masked_write(led,
+ WLED_FULL_SCALE_REG(led->base, i), WLED_MAX_CURR_MASK,
+ led->max_current);
+ if (rc) {
+ dev_err(&led->spmi_dev->dev,
+ "WLED max current reg write failed(%d)\n", rc);
+ return rc;
+ }
+
+ }
+
+ /* dump wled registers */
+ qpnp_wled_dump_regs(led);
+
+ return 0;
+}
+
+static int __devinit qpnp_led_initialize(struct qpnp_led_data *led)
+{
+ int rc;
+
+ switch (led->id) {
+ case QPNP_ID_WLED:
+ rc = qpnp_wled_init(led);
+ if (rc)
+ dev_err(led->cdev.dev,
+ "WLED initialize failed(%d)\n", rc);
+ break;
+ default:
+ dev_err(led->cdev.dev, "Invalid LED(%d)\n", led->id);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+/*
+ * Handlers for alternative sources of platform_data
+ */
+static int __devinit qpnp_get_config_wled(struct qpnp_led_data *led,
+ struct device_node *node)
+{
+ u32 val;
+ int rc;
+ const char *temp_string;
+
+ led->id = QPNP_ID_WLED;
+
+ led->wled_cfg = devm_kzalloc(&led->spmi_dev->dev,
+ sizeof(struct wled_config_data), GFP_KERNEL);
+ if (!led->wled_cfg) {
+ dev_err(&led->spmi_dev->dev, "Unable to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ led->cdev.default_trigger = WLED_TRIGGER_DEFAULT;
+ rc = of_property_read_string(node, "linux,default-trigger",
+ &temp_string);
+ if (!rc)
+ led->cdev.default_trigger = temp_string;
+ else if (rc != -EINVAL)
+ return rc;
+
+
+ led->cdev.flags = WLED_FLAGS_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,flags", &val);
+ if (!rc)
+ led->cdev.flags = (int) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->default_on = true;
+ rc = of_property_read_string(node, "qcom,default-state",
+ &temp_string);
+ if (!rc) {
+ if (!strncmp(temp_string, "off", sizeof("off")))
+ led->default_on = false;
+ } else if (rc != -EINVAL)
+ return rc;
+
+ led->wled_cfg->num_strings = WLED_DEFAULT_STRINGS;
+ rc = of_property_read_u32(node, "qcom,num-strings", &val);
+ if (!rc)
+ led->wled_cfg->num_strings = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->wled_cfg->ovp_val = WLED_DEFAULT_OVP_VAL;
+ rc = of_property_read_u32(node, "qcom,ovp-val", &val);
+ if (!rc)
+ led->wled_cfg->ovp_val = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->wled_cfg->boost_curr_lim = WLED_BOOST_LIM_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,boost-curr-lim", &val);
+ if (!rc)
+ led->wled_cfg->boost_curr_lim = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->wled_cfg->cp_select = WLED_CP_SEL_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,cp-sel", &val);
+ if (!rc)
+ led->wled_cfg->cp_select = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->wled_cfg->ctrl_delay_us = WLED_CTRL_DLY_DEFAULT;
+ rc = of_property_read_u32(node, "qcom,ctrl-delay-us", &val);
+ if (!rc)
+ led->wled_cfg->ctrl_delay_us = (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)
+ led->wled_cfg->switch_freq = (u8) val;
+ else if (rc != -EINVAL)
+ return rc;
+
+ led->wled_cfg->dig_mod_gen_en =
+ of_property_read_bool(node, "qcom,dig-mod-gen-en");
+
+ 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;
+}
+
+static int __devinit qpnp_leds_probe(struct spmi_device *spmi)
+{
+ struct qpnp_led_data *led;
+ struct resource *led_resource;
+ struct device_node *node;
+ int rc;
+ const char *led_label;
+
+ led = devm_kzalloc(&spmi->dev, (sizeof(struct qpnp_led_data)),
+ GFP_KERNEL);
+ if (!led) {
+ dev_err(&spmi->dev, "Unable to allocate memory\n");
+ return -ENOMEM;
+ }
+
+ led->spmi_dev = spmi;
+
+ led_resource = spmi_get_resource(spmi, NULL, IORESOURCE_MEM, 0);
+ if (!led_resource) {
+ dev_err(&spmi->dev, "Unable to get LED base address\n");
+ return -ENXIO;
+ }
+ led->base = led_resource->start;
+
+ dev_set_drvdata(&spmi->dev, led);
+
+ node = led->spmi_dev->dev.of_node;
+ if (node == NULL)
+ return -ENODEV;
+
+ rc = of_property_read_string(node, "qcom,label", &led_label);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev,
+ "Failure reading label, rc = %d\n", rc);
+ return rc;
+ }
+
+ rc = of_property_read_string(node, "qcom,name", &led->cdev.name);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev,
+ "Failure reading led name, rc = %d\n", rc);
+ return rc;
+ }
+
+ rc = of_property_read_u32(node, "qcom,max-current", &led->max_current);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev,
+ "Failure reading max_current, rc = %d\n", rc);
+ return rc;
+ }
+
+ led->cdev.brightness_set = qpnp_led_set;
+ led->cdev.brightness_get = qpnp_led_get;
+ led->cdev.brightness = LED_OFF;
+
+ if (strncmp(led_label, "wled", sizeof("wled")) == 0) {
+ rc = qpnp_get_config_wled(led, node);
+ if (rc < 0) {
+ dev_err(&led->spmi_dev->dev,
+ "Unable to read wled config data\n");
+ return rc;
+ }
+ } else {
+ dev_err(&led->spmi_dev->dev, "No LED matching label\n");
+ return -EINVAL;
+ }
+
+ mutex_init(&led->lock);
+
+ rc = qpnp_led_initialize(led);
+ if (rc < 0)
+ goto fail_id_check;
+
+ rc = qpnp_led_set_max_brightness(led);
+ if (rc < 0)
+ goto fail_id_check;
+
+
+ rc = led_classdev_register(&spmi->dev, &led->cdev);
+ if (rc) {
+ dev_err(&spmi->dev, "unable to register led %d,rc=%d\n",
+ led->id, rc);
+ goto fail_id_check;
+ }
+
+ /* configure default state */
+ if (led->default_on)
+ led->cdev.brightness = led->cdev.max_brightness;
+
+ qpnp_led_set(&led->cdev, led->cdev.brightness);
+
+ return 0;
+
+fail_id_check:
+ mutex_destroy(&led->lock);
+ led_classdev_unregister(&led->cdev);
+ return rc;
+}
+
+static int __devexit qpnp_leds_remove(struct spmi_device *spmi)
+{
+ struct qpnp_led_data *led = dev_get_drvdata(&spmi->dev);
+
+ mutex_destroy(&led->lock);
+ led_classdev_unregister(&led->cdev);
+
+ return 0;
+}
+static struct of_device_id spmi_match_table[] = {
+ { .compatible = "qcom,leds-qpnp",
+ }
+};
+
+static struct spmi_driver qpnp_leds_driver = {
+ .driver = {
+ .name = "qcom,leds-qpnp",
+ .of_match_table = spmi_match_table,
+ },
+ .probe = qpnp_leds_probe,
+ .remove = __devexit_p(qpnp_leds_remove),
+};
+
+static int __init qpnp_led_init(void)
+{
+ return spmi_driver_register(&qpnp_leds_driver);
+}
+module_init(qpnp_led_init);
+
+static void __exit qpnp_led_exit(void)
+{
+ spmi_driver_unregister(&qpnp_leds_driver);
+}
+module_exit(qpnp_led_exit);
+
+MODULE_DESCRIPTION("QPNP LEDs driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("leds:leds-qpnp");
diff --git a/drivers/media/dvb/mpq/Kconfig b/drivers/media/dvb/mpq/Kconfig
index 868ad8c..766312c 100644
--- a/drivers/media/dvb/mpq/Kconfig
+++ b/drivers/media/dvb/mpq/Kconfig
@@ -8,5 +8,5 @@
Say Y or M if you own such a device and want to use it.
source "drivers/media/dvb/mpq/demux/Kconfig"
-
+source "drivers/media/dvb/mpq/video/Kconfig"
diff --git a/drivers/media/dvb/mpq/Makefile b/drivers/media/dvb/mpq/Makefile
index 7ccf13e..a8d7137 100644
--- a/drivers/media/dvb/mpq/Makefile
+++ b/drivers/media/dvb/mpq/Makefile
@@ -1,5 +1,5 @@
obj-$(CONFIG_DVB_MPQ) += adapter/
obj-$(CONFIG_DVB_MPQ_DEMUX) += demux/
-
+obj-$(CONFIG_DVB_MPQ_VIDEO) += video/
diff --git a/drivers/media/dvb/mpq/video/Kconfig b/drivers/media/dvb/mpq/video/Kconfig
new file mode 100644
index 0000000..1344a67
--- /dev/null
+++ b/drivers/media/dvb/mpq/video/Kconfig
@@ -0,0 +1,16 @@
+config DVB_MPQ_VIDEO
+ tristate "DVB Video Device"
+ depends on DVB_MPQ
+
+ ---help---
+ This is a dvb/video interface with extensions for
+ Qualcomm Chipset Video hardware. For dvb/video
+ specification please check http://linuxtv.org/
+
+ Say Y or M if you own such a device and want to use it.
+
+config DVB_MPQ_NUM_VIDEO_DEVICES
+ int "Number of video devices"
+ depends on DVB_MPQ_VIDEO
+ default 4
+ range 1 255
diff --git a/drivers/media/dvb/mpq/video/Makefile b/drivers/media/dvb/mpq/video/Makefile
new file mode 100644
index 0000000..38c1091
--- /dev/null
+++ b/drivers/media/dvb/mpq/video/Makefile
@@ -0,0 +1,5 @@
+
+ccflags-y += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/dvb/mpq/include/
+
+obj-$(CONFIG_DVB_MPQ_VIDEO) += mpq_dvb_video.o
diff --git a/drivers/media/dvb/mpq/video/mpq_dvb_video.c b/drivers/media/dvb/mpq/video/mpq_dvb_video.c
new file mode 100644
index 0000000..cd0f605
--- /dev/null
+++ b/drivers/media/dvb/mpq/video/mpq_dvb_video.c
@@ -0,0 +1,2407 @@
+/* Copyright (c) 2010-2012, Code Aurora Forum. 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/cdev.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/poll.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/kthread.h>
+#include <linux/uaccess.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
+#include <linux/android_pmem.h>
+#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 "mpq_dvb_video_internal.h"
+
+
+#define DBG(x...) pr_debug(x)
+#define INFO(x...) pr_info(x)
+#define ERR(x...) pr_err(x)
+
+#define MPQ_VID_DEC_NAME "mpq_vidc_dec"
+static unsigned int vidc_mmu_subsystem[] = {
+ MSM_SUBSYSTEM_VIDEO};
+
+static char vid_thread_names[DVB_MPQ_NUM_VIDEO_DEVICES][10] = {
+ "dvb-vid-0",
+ "dvb-vid-1",
+ "dvb-vid-2",
+ "dvb-vid-3",
+};
+
+static int mpq_int_vid_dec_decode_frame(struct video_client_ctx *client_ctx,
+ struct video_data_buffer *input_frame);
+
+static struct mpq_dvb_video_dev *mpq_dvb_video_device;
+
+static int mpq_get_dev_frm_client(struct video_client_ctx *client_ctx,
+ struct mpq_dvb_video_inst **dev_inst)
+{
+ int i;
+
+ mutex_lock(&mpq_dvb_video_device->lock);
+ for (i = 0; i < DVB_MPQ_NUM_VIDEO_DEVICES; i++) {
+ if (mpq_dvb_video_device->dev_inst[i].client_ctx ==
+ client_ctx) {
+ *dev_inst = &mpq_dvb_video_device->dev_inst[i];
+ break;
+ }
+ }
+ mutex_unlock(&mpq_dvb_video_device->lock);
+
+ if (i == DVB_MPQ_NUM_VIDEO_DEVICES)
+ return -ENODEV;
+
+ return 0;
+}
+
+static u32 mpq_int_check_bcast_mq(struct mpq_dmx_src_data *dmx_data)
+{
+ u32 islist_empty = 0;
+ mutex_lock(&dmx_data->msg_queue_lock);
+ islist_empty = list_empty(&dmx_data->msg_queue);
+ mutex_unlock(&dmx_data->msg_queue_lock);
+
+ return !islist_empty;
+}
+
+static void mpq_get_frame_and_write(struct mpq_dvb_video_inst *dev_inst,
+ unsigned int free_buf)
+{
+ struct mpq_dmx_src_data *dmx_data = dev_inst->dmx_src_data;
+ struct mpq_streambuffer *streambuff = dmx_data->stream_buffer;
+ struct mpq_streambuffer_packet_header pkt_hdr;
+ struct mpq_adapter_video_meta_data meta_data;
+ ssize_t indx = -1;
+ ssize_t bytes_read = 0;
+ size_t pktlen = 0;
+ int frame_found = true;
+ unsigned long kernel_vaddr, phy_addr, user_vaddr;
+ int pmem_fd;
+ struct file *file;
+ s32 buffer_index = -1;
+ size_t size = 0;
+
+ do {
+ wait_event_interruptible(streambuff->packet_data.queue,
+ (!dvb_ringbuffer_empty(&streambuff->packet_data) ||
+ streambuff->packet_data.error != 0) ||
+ kthread_should_stop());
+
+ if (kthread_should_stop()) {
+ DBG("STOP signal Received\n");
+ return;
+ }
+
+ DBG("Received Free Buffer : %d\n", free_buf);
+
+ indx = mpq_streambuffer_pkt_next(streambuff, -1, &pktlen);
+
+ if (-1 == indx) {
+ DBG("Invalid Index -1\n");
+ return;
+ }
+
+ bytes_read = mpq_streambuffer_pkt_read(streambuff, indx,
+ &pkt_hdr, (u8 *)&meta_data);
+
+ switch (meta_data.packet_type) {
+ case DMX_FRAMING_INFO_PACKET:
+ switch (meta_data.info.framing.pattern_type) {
+ case DMX_FRM_H264_SPS:
+ case DMX_FRM_MPEG2_SEQUENCE_HEADER:
+ case DMX_FRM_VC1_SEQUENCE_HEADER:
+ DBG("SPS FOUND\n");
+ frame_found = false;
+ break;
+ case DMX_FRM_H264_PPS:
+ case DMX_FRM_MPEG2_GOP_HEADER:
+ case DMX_FRM_VC1_ENTRY_POINT_HEADER:
+ DBG("PPS FOUND\n");
+ frame_found = false;
+ break;
+ case DMX_FRM_H264_IDR_PIC:
+ case DMX_FRM_H264_NON_IDR_PIC:
+ case DMX_FRM_MPEG2_I_PIC:
+ case DMX_FRM_MPEG2_P_PIC:
+ case DMX_FRM_MPEG2_B_PIC:
+ case DMX_FRM_VC1_FRAME_START_CODE:
+ DBG("FRAME FOUND\n");
+ frame_found = true;
+ break;
+ default:
+ break;
+ }
+ user_vaddr = (unsigned long)
+ dmx_data->in_buffer[free_buf].bufferaddr;
+ vidc_lookup_addr_table(dev_inst->client_ctx,
+ BUFFER_TYPE_INPUT, true, &user_vaddr,
+ &kernel_vaddr, &phy_addr, &pmem_fd, &file,
+ &buffer_index);
+ bytes_read = 0;
+ bytes_read = mpq_streambuffer_data_read(streambuff,
+ (u8 *)(kernel_vaddr + size),
+ pkt_hdr.raw_data_len);
+ DBG("Data Read : %d from Packet Size : %d\n",
+ bytes_read, pkt_hdr.raw_data_len);
+ mpq_streambuffer_pkt_dispose(streambuff, indx, 0);
+ size += pkt_hdr.raw_data_len;
+ dmx_data->in_buffer[free_buf].pts =
+ (meta_data.info.framing.pts_dts_info.pts_exist) ?
+ (meta_data.info.framing.pts_dts_info.pts) : 0;
+ if (frame_found) {
+ dmx_data->in_buffer[free_buf].buffer_len =
+ size;
+ dmx_data->in_buffer[free_buf].client_data =
+ (void *)free_buf;
+ DBG("Size of Data Submitted : %d\n", size);
+ mpq_int_vid_dec_decode_frame(
+ dev_inst->client_ctx,
+ &dmx_data->in_buffer[free_buf]);
+ }
+ break;
+ case DMX_EOS_PACKET:
+ break;
+ case DMX_PES_PACKET:
+ case DMX_PADDING_PACKET:
+ break;
+ }
+ } while (!frame_found);
+
+}
+
+static int mpq_bcast_data_handler(void *arg)
+{
+ struct mpq_dvb_video_inst *dev_inst = arg;
+ struct mpq_dmx_src_data *dmx_data = dev_inst->dmx_src_data;
+ struct mpq_bcast_msg *pMesg;
+ struct mpq_bcast_msg_info msg = {0};
+
+ do {
+ wait_event_interruptible(dmx_data->msg_wait,
+ ((dmx_data->stream_buffer != NULL) &&
+ mpq_int_check_bcast_mq(dmx_data)) ||
+ kthread_should_stop());
+
+ if (kthread_should_stop()) {
+ DBG("STOP signal Received\n");
+ break;
+ }
+
+ mutex_lock(&dmx_data->msg_queue_lock);
+ if (!list_empty(&dmx_data->msg_queue)) {
+ pMesg = list_first_entry(&dmx_data->msg_queue,
+ struct mpq_bcast_msg, list);
+ list_del(&pMesg->list);
+ memcpy(&msg, &pMesg->info,
+ sizeof(struct mpq_bcast_msg_info));
+ kfree(pMesg);
+ }
+ mutex_unlock(&dmx_data->msg_queue_lock);
+
+ switch (msg.code) {
+ case MPQ_BCAST_MSG_IBD:
+ DBG("Received IBD Mesg for :%d\n", msg.data);
+ mpq_get_frame_and_write(dev_inst, msg.data);
+ break;
+ default:
+ DBG("Received Mesg : %d\n", msg.code);
+ }
+ } while (1);
+
+ return 0;
+}
+
+static s32 mpq_int_vid_dec_get_empty_client_index(void)
+{
+ u32 i, found = false;
+
+ for (i = 0; i < VIDC_MAX_NUM_CLIENTS; i++) {
+ if (!mpq_dvb_video_device->vdec_clients[i].vcd_handle) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ ERR("%s():ERROR No space for new client\n", __func__);
+ return -ENOMEM;
+ } else {
+ DBG("%s(): available client index = %u\n", __func__, i);
+ return i;
+ }
+}
+
+static u32 mpq_int_vid_dec_get_status(u32 status)
+{
+ u32 vdec_status;
+
+ switch (status) {
+ case VCD_ERR_SEQHDR_PARSE_FAIL:
+ case VCD_ERR_BITSTREAM_ERR:
+ vdec_status = VIDEO_STATUS_BITSTREAM_ERROR;
+ break;
+ case VCD_S_SUCCESS:
+ vdec_status = VIDEO_STATUS_SUCESS;
+ break;
+ case VCD_ERR_FAIL:
+ vdec_status = VIDEO_STATUS_FAILED;
+ break;
+ case VCD_ERR_ALLOC_FAIL:
+ case VCD_ERR_MAX_CLIENT:
+ vdec_status = VIDEO_STATUS_NORESOURCE;
+ break;
+ case VCD_ERR_ILLEGAL_OP:
+ vdec_status = VIDEO_STATUS_INVALID_CMD;
+ break;
+ case VCD_ERR_ILLEGAL_PARM:
+ vdec_status = VIDEO_STATUS_INVALID_PARAM;
+ break;
+ case VCD_ERR_BAD_POINTER:
+ case VCD_ERR_BAD_HANDLE:
+ vdec_status = VIDEO_STATUS_INVALID_HANDLE;
+ break;
+ case VCD_ERR_NOT_SUPPORTED:
+ vdec_status = VIDEO_STATUS_NO_SUPPORT;
+ break;
+ case VCD_ERR_BAD_STATE:
+ vdec_status = VIDEO_STATUS_INVALID_STATE;
+ break;
+ case VCD_ERR_BUSY:
+ vdec_status = VIDEO_STATUS_BUSY;
+ break;
+ default:
+ vdec_status = VIDEO_STATUS_FAILED;
+ break;
+ }
+
+ return vdec_status;
+}
+
+static void mpq_int_vid_dec_notify_client(struct video_client_ctx *client_ctx)
+{
+ if (client_ctx)
+ complete(&client_ctx->event);
+}
+
+static void mpq_int_vid_dec_vcd_open_done(struct video_client_ctx *client_ctx,
+ struct vcd_handle_container *handle_container)
+{
+ if (client_ctx) {
+ if (handle_container)
+ client_ctx->vcd_handle = handle_container->handle;
+ else
+ DBG("%s(): ERROR. handle_container is NULL\n",
+ __func__);
+
+ mpq_int_vid_dec_notify_client(client_ctx);
+ } else
+ DBG("%s(): ERROR. client_ctx is NULL\n", __func__);
+}
+
+static void mpq_int_vid_dec_handle_field_drop(
+ struct video_client_ctx *client_ctx,
+ u32 event, u32 status, int64_t time_stamp)
+{
+ struct vid_dec_msg *vdec_msg;
+
+ if (!client_ctx) {
+ DBG("%s() NULL pointer\n", __func__);
+ return;
+ }
+
+ vdec_msg = kzalloc(sizeof(struct vid_dec_msg), GFP_KERNEL);
+ if (!vdec_msg) {
+ DBG("%s(): cannot allocate vid_dec_msg "\
+ " buffer\n", __func__);
+ return;
+ }
+ vdec_msg->vdec_msg_info.status_code =
+ mpq_int_vid_dec_get_status(status);
+ if (event == VCD_EVT_IND_INFO_FIELD_DROPPED) {
+ vdec_msg->vdec_msg_info.msgcode =
+ VDEC_MSG_EVT_INFO_FIELD_DROPPED;
+ vdec_msg->vdec_msg_info.msgdata.output_frame.time_stamp
+ = time_stamp;
+ DBG("Send FIELD_DROPPED message to client = %p\n",
+ client_ctx);
+ } else {
+ DBG("mpq_int_vid_dec_input_frame_done(): "\
+ "invalid event type: %d\n", event);
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_INVALID;
+ }
+ vdec_msg->vdec_msg_info.msgdatasize =
+ sizeof(struct vdec_output_frameinfo);
+ mutex_lock(&client_ctx->msg_queue_lock);
+ list_add_tail(&vdec_msg->list, &client_ctx->msg_queue);
+ mutex_unlock(&client_ctx->msg_queue_lock);
+ wake_up(&client_ctx->msg_wait);
+}
+
+static void mpq_int_vid_dec_input_frame_done(
+ struct video_client_ctx *client_ctx, u32 event,
+ u32 status, struct vcd_frame_data *vcd_frame_data)
+{
+ struct vid_dec_msg *vdec_msg;
+ struct mpq_bcast_msg *bcast_msg;
+ struct mpq_dvb_video_inst *dev_inst;
+ struct mpq_dmx_src_data *dmx_data;
+ int rc = 0;
+
+ if (!client_ctx || !vcd_frame_data) {
+ DBG("mpq_int_vid_dec_input_frame_done() NULL pointer\n");
+ return;
+ }
+
+ kfree(vcd_frame_data->desc_buf);
+ vcd_frame_data->desc_buf = NULL;
+ vcd_frame_data->desc_size = 0;
+
+ rc = mpq_get_dev_frm_client(client_ctx, &dev_inst);
+ if (rc) {
+ DBG("Failed to obtain device instance\n");
+ return;
+ }
+
+ if (dev_inst->source == VIDEO_SOURCE_MEMORY) {
+ vdec_msg = kzalloc(sizeof(struct vid_dec_msg), GFP_KERNEL);
+ if (!vdec_msg) {
+ DBG("mpq_int_vid_dec_input_frame_done(): "\
+ "cannot allocate vid_dec_msg buffer\n");
+ return;
+ }
+
+ vdec_msg->vdec_msg_info.status_code =
+ mpq_int_vid_dec_get_status(status);
+
+ if (event == VCD_EVT_RESP_INPUT_DONE) {
+ vdec_msg->vdec_msg_info.msgcode =
+ VDEC_MSG_RESP_INPUT_BUFFER_DONE;
+ DBG("Send INPUT_DON message to client = %p\n",
+ client_ctx);
+
+ } else if (event == VCD_EVT_RESP_INPUT_FLUSHED) {
+ vdec_msg->vdec_msg_info.msgcode =
+ VDEC_MSG_RESP_INPUT_FLUSHED;
+ DBG("Send INPUT_FLUSHED message to client = %p\n",
+ client_ctx);
+ } else {
+ DBG("mpq_int_vid_dec_input_frame_done(): "\
+ "invalid event type: %d\n", event);
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_INVALID;
+ }
+
+ vdec_msg->vdec_msg_info.msgdata.input_frame_clientdata =
+ (void *)vcd_frame_data->frm_clnt_data;
+ vdec_msg->vdec_msg_info.msgdatasize = sizeof(void *);
+
+ mutex_lock(&client_ctx->msg_queue_lock);
+ list_add_tail(&vdec_msg->list, &client_ctx->msg_queue);
+ mutex_unlock(&client_ctx->msg_queue_lock);
+ wake_up(&client_ctx->msg_wait);
+ } else {
+ bcast_msg = kzalloc(sizeof(struct mpq_bcast_msg),
+ GFP_KERNEL);
+ if (!bcast_msg) {
+ DBG("mpq_int_vid_dec_input_frame_done(): "\
+ "cannot allocate mpq_bcast_msg buffer\n");
+ return;
+ }
+
+ if (event == VCD_EVT_RESP_INPUT_DONE) {
+ bcast_msg->info.code = MPQ_BCAST_MSG_IBD;
+ bcast_msg->info.data =
+ (unsigned int)vcd_frame_data->frm_clnt_data;
+ }
+
+ dmx_data = dev_inst->dmx_src_data;
+
+ mutex_lock(&dmx_data->msg_queue_lock);
+ list_add_tail(&bcast_msg->list, &dmx_data->msg_queue);
+ mutex_unlock(&dmx_data->msg_queue_lock);
+ wake_up(&dmx_data->msg_wait);
+ }
+}
+
+static void mpq_int_vid_dec_output_frame_done(
+ struct video_client_ctx *client_ctx,
+ u32 event, u32 status,
+ struct vcd_frame_data *vcd_frame_data)
+{
+ struct vid_dec_msg *vdec_msg;
+
+ unsigned long kernel_vaddr = 0, phy_addr = 0, user_vaddr = 0;
+ int pmem_fd;
+ struct file *file;
+ s32 buffer_index = -1;
+ enum vdec_picture pic_type;
+ u32 ion_flag = 0;
+ struct ion_handle *buff_handle = NULL;
+ struct vdec_output_frameinfo *output_frame;
+
+ if (!client_ctx || !vcd_frame_data) {
+ DBG("mpq_int_vid_dec_input_frame_done() NULL pointer\n");
+ return;
+ }
+
+ vdec_msg = kzalloc(sizeof(struct vid_dec_msg), GFP_KERNEL);
+ if (!vdec_msg) {
+ DBG("mpq_int_vid_dec_input_frame_done(): "\
+ "cannot allocate vid_dec_msg buffer\n");
+ return;
+ }
+
+ vdec_msg->vdec_msg_info.status_code =
+ mpq_int_vid_dec_get_status(status);
+
+ if (event == VCD_EVT_RESP_OUTPUT_DONE)
+ vdec_msg->vdec_msg_info.msgcode =
+ VDEC_MSG_RESP_OUTPUT_BUFFER_DONE;
+ else if (event == VCD_EVT_RESP_OUTPUT_FLUSHED)
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_RESP_OUTPUT_FLUSHED;
+ else {
+ DBG("QVD: mpq_int_vid_dec_output_frame_done"\
+ "invalid cmd type : %d\n", event);
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_INVALID;
+ }
+
+ kernel_vaddr = (unsigned long)vcd_frame_data->virtual;
+
+ if (vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT,
+ false, &user_vaddr, &kernel_vaddr,
+ &phy_addr, &pmem_fd, &file,
+ &buffer_index) ||
+ (vcd_frame_data->flags & VCD_FRAME_FLAG_EOS)) {
+ /* Buffer address in user space */
+ vdec_msg->vdec_msg_info.msgdata.output_frame.bufferaddr =
+ (u8 *) user_vaddr;
+ /* Data length */
+ vdec_msg->vdec_msg_info.msgdata.output_frame.len =
+ vcd_frame_data->data_len;
+ vdec_msg->vdec_msg_info.msgdata.output_frame.flags =
+ vcd_frame_data->flags;
+ /* Timestamp pass-through from input frame */
+ vdec_msg->vdec_msg_info.msgdata.output_frame.time_stamp =
+ vcd_frame_data->time_stamp;
+ /* Output frame client data */
+ vdec_msg->vdec_msg_info.msgdata.output_frame.client_data =
+ (void *)vcd_frame_data->frm_clnt_data;
+ /* Associated input frame client data */
+ vdec_msg->vdec_msg_info.msgdata.output_frame.
+ input_frame_clientdata =
+ (void *)vcd_frame_data->ip_frm_tag;
+ /* Decoded picture width and height */
+ vdec_msg->vdec_msg_info.msgdata.output_frame.framesize.
+ bottom =
+ vcd_frame_data->dec_op_prop.disp_frm.bottom;
+ vdec_msg->vdec_msg_info.msgdata.output_frame.framesize.left =
+ vcd_frame_data->dec_op_prop.disp_frm.left;
+ vdec_msg->vdec_msg_info.msgdata.output_frame.framesize.right =
+ vcd_frame_data->dec_op_prop.disp_frm.right;
+ vdec_msg->vdec_msg_info.msgdata.output_frame.framesize.top =
+ vcd_frame_data->dec_op_prop.disp_frm.top;
+ if (vcd_frame_data->interlaced) {
+ vdec_msg->vdec_msg_info.msgdata.
+ output_frame.interlaced_format =
+ VDEC_InterlaceInterleaveFrameTopFieldFirst;
+ } else {
+ vdec_msg->vdec_msg_info.msgdata.
+ output_frame.interlaced_format =
+ VDEC_InterlaceFrameProgressive;
+ }
+ /* Decoded picture type */
+ switch (vcd_frame_data->frame) {
+ case VCD_FRAME_I:
+ pic_type = PICTURE_TYPE_I;
+ break;
+ case VCD_FRAME_P:
+ pic_type = PICTURE_TYPE_P;
+ break;
+ case VCD_FRAME_B:
+ pic_type = PICTURE_TYPE_B;
+ break;
+ case VCD_FRAME_NOTCODED:
+ pic_type = PICTURE_TYPE_SKIP;
+ break;
+ case VCD_FRAME_IDR:
+ pic_type = PICTURE_TYPE_IDR;
+ break;
+ default:
+ pic_type = PICTURE_TYPE_UNKNOWN;
+ }
+ vdec_msg->vdec_msg_info.msgdata.output_frame.pic_type =
+ pic_type;
+ output_frame = &vdec_msg->vdec_msg_info.msgdata.output_frame;
+ output_frame->aspect_ratio_info.aspect_ratio =
+ vcd_frame_data->aspect_ratio_info.aspect_ratio;
+ output_frame->aspect_ratio_info.par_width =
+ vcd_frame_data->aspect_ratio_info.par_width;
+ output_frame->aspect_ratio_info.par_height =
+ vcd_frame_data->aspect_ratio_info.par_height;
+ vdec_msg->vdec_msg_info.msgdatasize =
+ sizeof(struct vdec_output_frameinfo);
+ } else {
+ DBG("mpq_int_vid_dec_output_frame_done UVA"\
+ "can not be found\n");
+ vdec_msg->vdec_msg_info.status_code = VDEC_S_EFATAL;
+ }
+ if (vcd_frame_data->data_len > 0) {
+ ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_OUTPUT,
+ pmem_fd, kernel_vaddr, buffer_index,
+ &buff_handle);
+ if (ion_flag == CACHED && buff_handle) {
+ msm_ion_do_cache_op(
+ client_ctx->user_ion_client,
+ buff_handle,
+ (unsigned long *) kernel_vaddr,
+ (unsigned long)vcd_frame_data->data_len,
+ ION_IOC_INV_CACHES);
+ }
+ }
+ mutex_lock(&client_ctx->msg_queue_lock);
+ list_add_tail(&vdec_msg->list, &client_ctx->msg_queue);
+ mutex_unlock(&client_ctx->msg_queue_lock);
+ wake_up(&client_ctx->msg_wait);
+}
+
+static void mpq_int_vid_dec_lean_event(struct video_client_ctx *client_ctx,
+ u32 event, u32 status)
+{
+ struct vid_dec_msg *vdec_msg;
+
+ if (!client_ctx) {
+ DBG("%s(): !client_ctx pointer\n", __func__);
+ return;
+ }
+
+ vdec_msg = kzalloc(sizeof(struct vid_dec_msg), GFP_KERNEL);
+ if (!vdec_msg) {
+ DBG("%s(): cannot allocate vid_dec_msg buffer\n",
+ __func__);
+ return;
+ }
+
+ vdec_msg->vdec_msg_info.status_code =
+ mpq_int_vid_dec_get_status(status);
+
+ switch (event) {
+ case VCD_EVT_IND_OUTPUT_RECONFIG:
+ DBG("msm_vidc_dec: Sending VDEC_MSG_EVT_CONFIG_CHANGED"\
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_EVT_CONFIG_CHANGED;
+ break;
+ case VCD_EVT_IND_RESOURCES_LOST:
+ DBG("msm_vidc_dec: Sending VDEC_EVT_RESOURCES_LOST"\
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode = VDEC_EVT_RESOURCES_LOST;
+ break;
+ case VCD_EVT_RESP_FLUSH_INPUT_DONE:
+ DBG("msm_vidc_dec: Sending VDEC_MSG_RESP_FLUSH_INPUT_DONE"\
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode =
+ VDEC_MSG_RESP_FLUSH_INPUT_DONE;
+ break;
+ case VCD_EVT_RESP_FLUSH_OUTPUT_DONE:
+ DBG("msm_vidc_dec: Sending VDEC_MSG_RESP_FLUSH_OUTPUT_DONE"\
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode =
+ VDEC_MSG_RESP_FLUSH_OUTPUT_DONE;
+ break;
+ case VCD_EVT_IND_HWERRFATAL:
+ DBG("msm_vidc_dec: Sending VDEC_MSG_EVT_HW_ERROR"\
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_EVT_HW_ERROR;
+ break;
+ case VCD_EVT_RESP_START:
+ DBG("msm_vidc_dec: Sending VDEC_MSG_RESP_START_DONE"\
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_RESP_START_DONE;
+ break;
+ case VCD_EVT_RESP_STOP:
+ DBG("msm_vidc_dec: Sending VDEC_MSG_RESP_STOP_DONE"\
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_RESP_STOP_DONE;
+ break;
+ case VCD_EVT_RESP_PAUSE:
+ DBG("msm_vidc_dec: Sending VDEC_MSG_RESP_PAUSE_DONE"\
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode = VDEC_MSG_RESP_PAUSE_DONE;
+ break;
+ case VCD_EVT_IND_INFO_OUTPUT_RECONFIG:
+ DBG("msm_vidc_dec: Sending VDEC_MSG_EVT_INFO_CONFIG_CHANGED"\
+ " to client");
+ vdec_msg->vdec_msg_info.msgcode =
+ VDEC_MSG_EVT_INFO_CONFIG_CHANGED;
+ break;
+ default:
+ DBG("%s() : unknown event type\n", __func__);
+ break;
+ }
+
+ vdec_msg->vdec_msg_info.msgdatasize = 0;
+ if (client_ctx->stop_sync_cb &&
+ (event == VCD_EVT_RESP_STOP || event == VCD_EVT_IND_HWERRFATAL)) {
+ client_ctx->stop_sync_cb = false;
+ complete(&client_ctx->event);
+ kfree(vdec_msg);
+ return;
+ }
+ mutex_lock(&client_ctx->msg_queue_lock);
+ list_add_tail(&vdec_msg->list, &client_ctx->msg_queue);
+ mutex_unlock(&client_ctx->msg_queue_lock);
+ wake_up(&client_ctx->msg_wait);
+}
+
+static void mpq_int_state_play(struct video_client_ctx *client_ctx,
+ u32 event, u32 status)
+{
+ struct mpq_bcast_msg *bcast_msg;
+ struct mpq_dvb_video_inst *dev_inst;
+ int i;
+ int rc = 0;
+ struct mpq_dmx_src_data *dmx_data = NULL;
+
+ if (!client_ctx->seq_header_set) {
+ rc = mpq_get_dev_frm_client(client_ctx, &dev_inst);
+ if (rc) {
+ DBG("Failed to get dev_instance in %s\n", __func__);
+ return;
+ }
+
+ if (VIDEO_SOURCE_DEMUX == dev_inst->source) {
+ dmx_data = dev_inst->dmx_src_data;
+ for (i = 0; i < DVB_VID_NUM_IN_BUFFERS; i++) {
+ bcast_msg = kzalloc(
+ sizeof(struct mpq_bcast_msg),
+ GFP_KERNEL);
+ if (!bcast_msg) {
+ DBG("cannot allocate mpq_bcast_msg"\
+ "buffer\n");
+ return;
+ }
+
+ bcast_msg->info.code = MPQ_BCAST_MSG_IBD;
+ bcast_msg->info.data = (unsigned int)i;
+
+ mutex_lock(&dmx_data->msg_queue_lock);
+ list_add_tail(&bcast_msg->list,
+ &dmx_data->msg_queue);
+ mutex_unlock(&dmx_data->msg_queue_lock);
+ wake_up(&dmx_data->msg_wait);
+ }
+ }
+ mpq_int_vid_dec_lean_event(client_ctx, event, status);
+ } else
+ mpq_int_vid_dec_notify_client(client_ctx);
+
+}
+
+static void mpq_int_vid_dec_vcd_cb(u32 event, u32 status,
+ void *info, size_t sz, void *handle,
+ void *const client_data)
+{
+ struct video_client_ctx *client_ctx = client_data;
+
+ DBG("Entering %s()\n", __func__);
+
+ if (!client_ctx) {
+ DBG("%s(): client_ctx is NULL\n", __func__);
+ return;
+ }
+
+ client_ctx->event_status = status;
+
+ switch (event) {
+ case VCD_EVT_RESP_OPEN:
+ mpq_int_vid_dec_vcd_open_done(client_ctx,
+ (struct vcd_handle_container *)
+ info);
+ break;
+ case VCD_EVT_RESP_INPUT_DONE:
+ case VCD_EVT_RESP_INPUT_FLUSHED:
+ mpq_int_vid_dec_input_frame_done(client_ctx, event, status,
+ (struct vcd_frame_data *)info);
+ break;
+ case VCD_EVT_IND_INFO_FIELD_DROPPED:
+ if (info)
+ mpq_int_vid_dec_handle_field_drop(client_ctx, event,
+ status, *((int64_t *)info));
+ else
+ DBG("Wrong Payload for Field dropped\n");
+ break;
+ case VCD_EVT_RESP_OUTPUT_DONE:
+ case VCD_EVT_RESP_OUTPUT_FLUSHED:
+ mpq_int_vid_dec_output_frame_done(client_ctx, event, status,
+ (struct vcd_frame_data *)info);
+ break;
+ case VCD_EVT_RESP_PAUSE:
+ case VCD_EVT_RESP_STOP:
+ case VCD_EVT_RESP_FLUSH_INPUT_DONE:
+ case VCD_EVT_RESP_FLUSH_OUTPUT_DONE:
+ case VCD_EVT_IND_OUTPUT_RECONFIG:
+ case VCD_EVT_IND_HWERRFATAL:
+ case VCD_EVT_IND_RESOURCES_LOST:
+ case VCD_EVT_IND_INFO_OUTPUT_RECONFIG:
+ mpq_int_vid_dec_lean_event(client_ctx, event, status);
+ break;
+ case VCD_EVT_RESP_START:
+ mpq_int_state_play(client_ctx, event, status);
+ break;
+ default:
+ DBG("%s() : Error - Invalid event type =%u\n", __func__,
+ event);
+ break;
+ }
+}
+
+static int mpq_int_vid_dec_set_cont_on_reconfig(
+ struct video_client_ctx *client_ctx)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 enable = true;
+ if (!client_ctx)
+ return -EINVAL;
+ vcd_property_hdr.prop_id = VCD_I_CONT_ON_RECONFIG;
+ vcd_property_hdr.sz = sizeof(u32);
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &enable);
+ if (vcd_status)
+ return -EIO;
+ return 0;
+}
+
+static int mpq_int_vid_dec_set_frame_resolution(
+ struct video_client_ctx *client_ctx,
+ struct vdec_picsize *video_resoultion)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_frame_size frame_resolution;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !video_resoultion)
+ return -EINVAL;
+
+ vcd_property_hdr.prop_id = VCD_I_FRAME_SIZE;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_frame_size);
+ frame_resolution.width = video_resoultion->frame_width;
+ frame_resolution.height = video_resoultion->frame_height;
+ frame_resolution.stride = video_resoultion->stride;
+ frame_resolution.scan_lines = video_resoultion->scan_lines;
+
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &frame_resolution);
+
+ if (vcd_status)
+ return -EIO;
+ else
+ return 0;
+}
+
+static int mpq_int_set_full_hd_frame_resolution(
+ struct video_client_ctx *client_ctx)
+{
+ struct vdec_picsize pic_res;
+ int rc;
+
+ pic_res.frame_height = 1080;
+ pic_res.frame_width = 1920;
+ pic_res.scan_lines = 1080;
+ pic_res.stride = 1920;
+
+ rc = mpq_int_vid_dec_set_frame_resolution(client_ctx,
+ &pic_res);
+ if (rc)
+ DBG("Failed in mpq_int_vid_dec_set_frame_resolution : %d\n",\
+ rc);
+
+ rc = mpq_int_vid_dec_set_cont_on_reconfig(client_ctx);
+ if (rc)
+ DBG("Failed in mpq_int_vid_dec_set_cont_on_reconfig : %d\n",\
+ rc);
+
+ return rc;
+
+}
+
+static int mpq_int_vid_dec_get_frame_resolution(
+ struct video_client_ctx *client_ctx,
+ struct video_pic_res *video_resoultion)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_frame_size frame_resolution;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !video_resoultion)
+ return -EINVAL;
+
+ vcd_property_hdr.prop_id = VCD_I_FRAME_SIZE;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_frame_size);
+
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &frame_resolution);
+
+ video_resoultion->width = frame_resolution.width;
+ video_resoultion->height = frame_resolution.height;
+ video_resoultion->scan_lines = frame_resolution.scan_lines;
+ video_resoultion->stride = frame_resolution.stride;
+
+ if (vcd_status)
+ return -EINVAL;
+ else
+ return 0;
+}
+
+static int mpq_int_vid_dec_get_codec(struct video_client_ctx *client_ctx,
+ enum video_codec_t *video_codec)
+{
+ unsigned int result = 0;
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_codec codec;
+
+ if ((client_ctx == NULL) || (video_codec == NULL))
+ return -EINVAL;
+
+ vcd_property_hdr.prop_id = VCD_I_CODEC;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_codec);
+
+ result = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &codec);
+ if (result)
+ return -EINVAL;
+
+ switch (codec.codec) {
+ case VCD_CODEC_MPEG4:
+ *video_codec = VIDEO_CODECTYPE_MPEG4;
+ break;
+ case VCD_CODEC_H264:
+ *video_codec = VIDEO_CODECTYPE_H264;
+ break;
+ case VCD_CODEC_MPEG2:
+ *video_codec = VIDEO_CODECTYPE_MPEG2;
+ break;
+ case VCD_CODEC_VC1:
+ *video_codec = VIDEO_CODECTYPE_VC1;
+ break;
+ default:
+ *video_codec = VIDEO_CODECTYPE_NONE;
+ break;
+ }
+
+ return result;
+}
+
+static int mpq_int_vid_dec_set_codec(struct video_client_ctx *client_ctx,
+ enum video_codec_t video_codec)
+{
+ unsigned int result = 0;
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_codec codec;
+ unsigned int vcd_status = VCD_ERR_FAIL;
+
+ if (client_ctx == NULL)
+ return -EINVAL;
+
+ vcd_property_hdr.prop_id = VCD_I_CODEC;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_codec);
+
+ switch (video_codec) {
+ case VIDEO_CODECTYPE_MPEG4:
+ codec.codec = VCD_CODEC_MPEG4;
+ break;
+ case VIDEO_CODECTYPE_H264:
+ codec.codec = VCD_CODEC_H264;
+ break;
+ case VIDEO_CODECTYPE_MPEG2:
+ codec.codec = VCD_CODEC_MPEG2;
+ break;
+ case VIDEO_CODECTYPE_VC1:
+ codec.codec = VCD_CODEC_VC1;
+ break;
+ default:
+ result = -EINVAL;
+ break;
+ }
+
+ if (!result) {
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &codec);
+ if (vcd_status)
+ result = -EINVAL;
+ }
+
+ result = mpq_int_set_full_hd_frame_resolution(client_ctx);
+
+ return result;
+}
+
+static int mpq_int_vid_dec_set_output_format(
+ struct video_client_ctx *client_ctx,
+ enum video_out_format_t format)
+{
+ unsigned int result = 0;
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_buffer_format vcd_prop_buffer_format;
+ unsigned int vcd_status = VCD_ERR_FAIL;
+
+ if (client_ctx == NULL)
+ return -EINVAL;
+
+ vcd_property_hdr.prop_id = VCD_I_BUFFER_FORMAT;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_format);
+
+ switch (format) {
+ case VIDEO_YUV_FORMAT_NV12:
+ vcd_prop_buffer_format.buffer_format = VCD_BUFFER_FORMAT_NV12;
+ break;
+ case VIDEO_YUV_FORMAT_TILE_4x2:
+ vcd_prop_buffer_format.buffer_format =
+ VCD_BUFFER_FORMAT_TILE_4x2;
+ break;
+ default:
+ result = -EINVAL;
+ break;
+ }
+
+ if (!result)
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr,
+ &vcd_prop_buffer_format);
+
+ if (vcd_status)
+ return -EINVAL;
+
+ return 0;
+
+}
+
+static int mpq_int_vid_dec_get_output_format(
+ struct video_client_ctx *client_ctx,
+ enum video_out_format_t *format)
+{
+ unsigned int result = 0;
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_buffer_format vcd_prop_buffer_format;
+
+ if ((client_ctx == NULL) || (format == NULL))
+ return -EINVAL;
+
+ vcd_property_hdr.prop_id = VCD_I_BUFFER_FORMAT;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_format);
+
+ result = vcd_get_property(client_ctx->vcd_handle, &vcd_property_hdr,
+ &vcd_prop_buffer_format);
+
+ if (result)
+ return -EINVAL;
+
+ switch (vcd_prop_buffer_format.buffer_format) {
+ case VCD_BUFFER_FORMAT_NV12:
+ *format = VIDEO_YUV_FORMAT_NV12;
+ break;
+ case VCD_BUFFER_FORMAT_TILE_4x2:
+ *format = VIDEO_YUV_FORMAT_TILE_4x2;
+ break;
+ default:
+ result = -EINVAL;
+ break;
+ }
+
+ return result;
+}
+
+static int mpq_int_vid_dec_set_h264_mv_buffers(
+ struct video_client_ctx *client_ctx,
+ struct video_h264_mv *mv_data)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_h264_mv_buffer *vcd_h264_mv_buffer = NULL;
+ struct msm_mapped_buffer *mapped_buffer = NULL;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 len = 0, flags = 0;
+ struct file *file;
+ int rc = 0;
+ unsigned long ionflag = 0;
+ unsigned long buffer_size = 0;
+ unsigned long iova = 0;
+
+ if (!client_ctx || !mv_data)
+ return -EINVAL;
+
+ vcd_property_hdr.prop_id = VCD_I_H264_MV_BUFFER;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_h264_mv_buffer);
+ vcd_h264_mv_buffer = &client_ctx->vcd_h264_mv_buffer;
+
+ memset(&client_ctx->vcd_h264_mv_buffer, 0,
+ sizeof(struct vcd_property_h264_mv_buffer));
+ vcd_h264_mv_buffer->size = mv_data->size;
+ vcd_h264_mv_buffer->count = mv_data->count;
+ vcd_h264_mv_buffer->pmem_fd = mv_data->ion_fd;
+ vcd_h264_mv_buffer->offset = mv_data->offset;
+
+ if (!vcd_get_ion_status()) {
+ if (get_pmem_file(vcd_h264_mv_buffer->pmem_fd,
+ (unsigned long *) (&(vcd_h264_mv_buffer->
+ physical_addr)),
+ (unsigned long *) (&vcd_h264_mv_buffer->
+ kernel_virtual_addr),
+ (unsigned long *) (&len), &file)) {
+ ERR("%s(): get_pmem_file failed\n", __func__);
+ return -EIO;
+ }
+ put_pmem_file(file);
+ flags = MSM_SUBSYSTEM_MAP_IOVA;
+ mapped_buffer = msm_subsystem_map_buffer(
+ (unsigned long)vcd_h264_mv_buffer->physical_addr, len,
+ flags, vidc_mmu_subsystem,
+ sizeof(vidc_mmu_subsystem)/
+ sizeof(unsigned int));
+ if (IS_ERR(mapped_buffer)) {
+ ERR("buffer map failed");
+ return PTR_ERR(mapped_buffer);
+ }
+ vcd_h264_mv_buffer->client_data = (void *) mapped_buffer;
+ vcd_h264_mv_buffer->dev_addr = (u8 *)mapped_buffer->iova[0];
+ } else {
+ client_ctx->h264_mv_ion_handle = ion_import_dma_buf(
+ client_ctx->user_ion_client,
+ vcd_h264_mv_buffer->pmem_fd);
+ if (IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
+ DBG("%s(): get_ION_handle failed\n", __func__);
+ goto import_ion_error;
+ }
+ rc = ion_handle_get_flags(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle,
+ &ionflag);
+ if (rc) {
+ DBG("%s():get_ION_flags fail\n",
+ __func__);
+ goto import_ion_error;
+ }
+ vcd_h264_mv_buffer->kernel_virtual_addr =
+ (u8 *) ion_map_kernel(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle,
+ ionflag);
+ if (!vcd_h264_mv_buffer->kernel_virtual_addr) {
+ DBG("%s(): get_ION_kernel virtual addr failed\n",
+ __func__);
+ goto import_ion_error;
+ }
+
+ rc = ion_map_iommu(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle,
+ VIDEO_DOMAIN, VIDEO_MAIN_POOL,
+ SZ_4K, 0, (unsigned long *)&iova,
+ (unsigned long *)&buffer_size,
+ UNCACHED, 0);
+ if (rc) {
+ DBG("%s():get_ION_kernel physical addr fail\n",
+ __func__);
+ goto ion_map_error;
+ }
+ vcd_h264_mv_buffer->physical_addr = (u8 *) iova;
+ vcd_h264_mv_buffer->client_data = NULL;
+ vcd_h264_mv_buffer->dev_addr = (u8 *) iova;
+
+ }
+ DBG("Virt: %p, Phys %p, fd: %d", vcd_h264_mv_buffer->
+ kernel_virtual_addr, vcd_h264_mv_buffer->physical_addr,
+ vcd_h264_mv_buffer->pmem_fd);
+ DBG("Dev addr %p", vcd_h264_mv_buffer->dev_addr);
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, vcd_h264_mv_buffer);
+
+ if (vcd_status)
+ return -EIO;
+ else
+ return 0;
+ion_map_error:
+ if (vcd_h264_mv_buffer->kernel_virtual_addr) {
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle);
+ vcd_h264_mv_buffer->kernel_virtual_addr = NULL;
+ }
+ if (!IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle);
+ client_ctx->h264_mv_ion_handle = NULL;
+ }
+import_ion_error:
+ return -EIO;
+}
+
+static int mpq_int_vid_dec_get_h264_mv_buffer_size(
+ struct video_client_ctx *client_ctx,
+ struct video_mv_buff_size *mv_buff)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_buffer_size h264_mv_buffer_size;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !mv_buff)
+ return -EINVAL;
+
+ vcd_property_hdr.prop_id = VCD_I_GET_H264_MV_SIZE;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_buffer_size);
+
+ h264_mv_buffer_size.width = mv_buff->width;
+ h264_mv_buffer_size.height = mv_buff->height;
+
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &h264_mv_buffer_size);
+
+ mv_buff->width = h264_mv_buffer_size.width;
+ mv_buff->height = h264_mv_buffer_size.height;
+ mv_buff->size = h264_mv_buffer_size.size;
+ mv_buff->alignment = h264_mv_buffer_size.alignment;
+
+ if (vcd_status)
+ return -EIO;
+ else
+ return 0;
+}
+
+static int mpq_int_vid_dec_free_h264_mv_buffers(
+ struct video_client_ctx *client_ctx)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_buffer_size h264_mv_buffer_size;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ 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);
+
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &h264_mv_buffer_size);
+
+ if (!IS_ERR_OR_NULL(client_ctx->h264_mv_ion_handle)) {
+ ion_unmap_kernel(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle);
+ ion_unmap_iommu(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle,
+ VIDEO_DOMAIN,
+ VIDEO_MAIN_POOL);
+ ion_free(client_ctx->user_ion_client,
+ client_ctx->h264_mv_ion_handle);
+ client_ctx->h264_mv_ion_handle = NULL;
+ }
+
+ if (vcd_status)
+ return -EIO;
+ else
+ return 0;
+}
+
+
+static int mpq_int_vid_dec_get_buffer_req(struct video_client_ctx *client_ctx,
+ struct video_buffer_req *vdec_buf_req)
+{
+ u32 vcd_status = VCD_ERR_FAIL;
+ struct vcd_buffer_requirement vcd_buf_req;
+
+ if (!client_ctx || !vdec_buf_req)
+ return -EINVAL;
+
+ vcd_status = vcd_get_buffer_requirements(client_ctx->vcd_handle,
+ VCD_BUFFER_INPUT, &vcd_buf_req);
+
+ if (vcd_status)
+ return -EINVAL;
+
+ vdec_buf_req->input_buf_prop.alignment = vcd_buf_req.align;
+ vdec_buf_req->input_buf_prop.buf_poolid = vcd_buf_req.buf_pool_id;
+ vdec_buf_req->input_buf_prop.buf_size = vcd_buf_req.sz;
+ vdec_buf_req->num_input_buffers = vcd_buf_req.actual_count;
+
+ vcd_status = vcd_get_buffer_requirements(client_ctx->vcd_handle,
+ VCD_BUFFER_OUTPUT, &vcd_buf_req);
+
+ if (vcd_status)
+ return -EINVAL;
+
+ vdec_buf_req->output_buf_prop.alignment = vcd_buf_req.align;
+ vdec_buf_req->output_buf_prop.buf_poolid = vcd_buf_req.buf_pool_id;
+ vdec_buf_req->output_buf_prop.buf_size = vcd_buf_req.sz;
+ vdec_buf_req->num_output_buffers = vcd_buf_req.actual_count;
+
+ return 0;
+}
+
+static int mpq_int_vid_dec_set_buffer(struct mpq_dvb_video_inst *dev_inst,
+ struct video_data_buffer *data_buffer,
+ enum buffer_dir dir_buffer)
+{
+ struct video_client_ctx *client_ctx =
+ (struct video_client_ctx *)dev_inst->client_ctx;
+ enum vcd_buffer_type buffer = VCD_BUFFER_INPUT;
+ u32 vcd_status = VCD_ERR_FAIL;
+ unsigned long kernel_vaddr, buf_adr_offset = 0, length;
+ int buffer_num = 0;
+
+ if (!client_ctx || !data_buffer)
+ return -EINVAL;
+
+ if (dir_buffer == BUFFER_TYPE_OUTPUT) {
+ buffer = VCD_BUFFER_OUTPUT;
+ buf_adr_offset = (unsigned long)data_buffer->offset;
+ }
+ length = data_buffer->buffer_len;
+ /*If buffer cannot be set, ignore */
+ if (!vidc_insert_addr_table(client_ctx, dir_buffer,
+ (unsigned long)data_buffer->bufferaddr,
+ &kernel_vaddr, data_buffer->ion_fd,
+ buf_adr_offset, MAX_VIDEO_NUM_OF_BUFF, length)) {
+ ERR("%s() : user_virt_addr = %p cannot be set.",
+ __func__, data_buffer->bufferaddr);
+ return -EINVAL;
+ }
+
+ vcd_status = vcd_set_buffer(client_ctx->vcd_handle,
+ buffer, (u8 *) kernel_vaddr, data_buffer->buffer_len);
+
+ if (!vcd_status) {
+ mutex_lock(&client_ctx->enrty_queue_lock);
+ if ((VIDEO_SOURCE_DEMUX == dev_inst->source) &&
+ (BUFFER_TYPE_INPUT == dir_buffer)) {
+ buffer_num = client_ctx->num_of_input_buffers - 1;
+ memcpy(&dev_inst->dmx_src_data->in_buffer[buffer_num],
+ data_buffer,
+ sizeof(struct video_data_buffer));
+ }
+ mutex_unlock(&client_ctx->enrty_queue_lock);
+ return 0;
+ } else
+ return -EINVAL;
+}
+
+static int mpq_int_vid_dec_free_buffer(struct video_client_ctx *client_ctx,
+ struct video_data_buffer *data_buffer,
+ enum buffer_dir dir_buffer)
+
+{
+ enum vcd_buffer_type buffer = VCD_BUFFER_INPUT;
+ u32 vcd_status = VCD_ERR_FAIL;
+ unsigned long kernel_vaddr;
+
+ if (!client_ctx || !data_buffer)
+ return -EINVAL;
+
+ if (dir_buffer == BUFFER_TYPE_OUTPUT)
+ buffer = VCD_BUFFER_OUTPUT;
+
+ /*If buffer NOT set, ignore */
+ if (!vidc_delete_addr_table(client_ctx, dir_buffer,
+ (unsigned long)data_buffer->bufferaddr,
+ &kernel_vaddr)) {
+ DBG("%s() : user_virt_addr = %p has not been set.",
+ __func__, data_buffer->bufferaddr);
+ return 0;
+ }
+ vcd_status = vcd_free_buffer(client_ctx->vcd_handle, buffer,
+ (u8 *)kernel_vaddr);
+
+ if (vcd_status)
+ return -EIO;
+ else
+ return 0;
+}
+
+static int mpq_int_vid_dec_pause_resume(struct video_client_ctx *client_ctx,
+ u32 pause)
+{
+ u32 vcd_status;
+
+ if (!client_ctx) {
+ DBG("%s(): Invalid client_ctx\n", __func__);
+ return -EINVAL;
+ }
+
+ if (pause) {
+ DBG("msm_vidc_dec: PAUSE command from client = %p\n",
+ client_ctx);
+ vcd_status = vcd_pause(client_ctx->vcd_handle);
+ } else {
+ DBG("msm_vidc_dec: RESUME command from client = %p\n",
+ client_ctx);
+ vcd_status = vcd_resume(client_ctx->vcd_handle);
+ }
+
+ if (vcd_status)
+ return -EIO;
+ else
+ return 0;
+}
+
+static int mpq_int_vid_dec_start_stop(struct video_client_ctx *client_ctx,
+ u32 start)
+{
+ struct vid_dec_msg *vdec_msg = NULL;
+ u32 vcd_status;
+
+ DBG("Inside %s()", __func__);
+ if (!client_ctx) {
+ DBG("Invalid client_ctx\n");
+ return -EINVAL;
+ }
+
+ if (start) {
+ if (client_ctx->seq_header_set) {
+ DBG("%s(): Seq Hdr set: Send START_DONE to client",
+ __func__);
+ vdec_msg = kzalloc(sizeof(*vdec_msg), GFP_KERNEL);
+ if (!vdec_msg) {
+ DBG("mpq_int_vid_dec_start_stop:"\
+ " cannot allocate buffer\n");
+ return -ENOMEM;
+ }
+ vdec_msg->vdec_msg_info.msgcode =
+ VDEC_MSG_RESP_START_DONE;
+ vdec_msg->vdec_msg_info.status_code = VDEC_S_SUCCESS;
+ vdec_msg->vdec_msg_info.msgdatasize = 0;
+ mutex_lock(&client_ctx->msg_queue_lock);
+ list_add_tail(&vdec_msg->list, &client_ctx->msg_queue);
+ mutex_unlock(&client_ctx->msg_queue_lock);
+
+ wake_up(&client_ctx->msg_wait);
+
+ DBG("Send START_DONE message to client = %p\n",
+ client_ctx);
+
+ } else {
+ DBG("%s(): Calling decode_start()", __func__);
+ vcd_status =
+ vcd_decode_start(client_ctx->vcd_handle, NULL);
+
+ if (vcd_status) {
+ DBG("%s(): vcd_decode_start failed."\
+ " vcd_status = %u\n", __func__,
+ vcd_status);
+ return -EIO;
+ }
+ }
+ } else {
+ DBG("%s(): Calling vcd_stop()", __func__);
+ mutex_lock(&mpq_dvb_video_device->lock);
+ vcd_status = VCD_ERR_FAIL;
+ if (!client_ctx->stop_called) {
+ client_ctx->stop_called = true;
+ vcd_status = vcd_stop(client_ctx->vcd_handle);
+ }
+ if (vcd_status) {
+ DBG("%s(): vcd_stop failed. vcd_status = %u\n",
+ __func__, vcd_status);
+ mutex_unlock(&mpq_dvb_video_device->lock);
+ return -EIO;
+ }
+ DBG("Send STOP_DONE message to client = %p\n", client_ctx);
+ mutex_unlock(&mpq_dvb_video_device->lock);
+ }
+ return 0;
+}
+
+static int mpq_int_vid_dec_decode_frame(struct video_client_ctx *client_ctx,
+ struct video_data_buffer *input_frame)
+{
+ struct vcd_frame_data vcd_input_buffer;
+ unsigned long kernel_vaddr, phy_addr, user_vaddr;
+ int pmem_fd;
+ struct file *file;
+ s32 buffer_index = -1;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 ion_flag = 0;
+ struct ion_handle *buff_handle = NULL;
+
+ if (!client_ctx || !input_frame)
+ return -EINVAL;
+
+ user_vaddr = (unsigned long)input_frame->bufferaddr;
+
+ if (vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_INPUT,
+ true, &user_vaddr, &kernel_vaddr,
+ &phy_addr, &pmem_fd, &file,
+ &buffer_index)) {
+
+ /* kernel_vaddr is found. send the frame to VCD */
+ memset((void *)&vcd_input_buffer, 0,
+ sizeof(struct vcd_frame_data));
+ vcd_input_buffer.virtual =
+ (u8 *) (kernel_vaddr + input_frame->offset);
+ vcd_input_buffer.offset = 0;
+ vcd_input_buffer.frm_clnt_data =
+ (u32) input_frame->client_data;
+ vcd_input_buffer.ip_frm_tag =
+ (u32) input_frame->client_data;
+ vcd_input_buffer.data_len = input_frame->buffer_len;
+ vcd_input_buffer.time_stamp = input_frame->pts;
+ /* Rely on VCD using the same flags as OMX */
+ vcd_input_buffer.flags = 0;
+ vcd_input_buffer.desc_buf = NULL;
+ vcd_input_buffer.desc_size = 0;
+ if (vcd_input_buffer.data_len > 0) {
+ ion_flag = vidc_get_fd_info(client_ctx,
+ BUFFER_TYPE_INPUT,
+ pmem_fd,
+ kernel_vaddr,
+ buffer_index,
+ &buff_handle);
+ if (ion_flag == CACHED && buff_handle) {
+ msm_ion_do_cache_op(
+ client_ctx->user_ion_client,
+ buff_handle,
+ (unsigned long *)kernel_vaddr,
+ (unsigned long) vcd_input_buffer.data_len,
+ ION_IOC_CLEAN_CACHES);
+ }
+ }
+ vcd_status = vcd_decode_frame(client_ctx->vcd_handle,
+ &vcd_input_buffer);
+ if (!vcd_status)
+ return 0;
+ else {
+ DBG("%s(): vcd_decode_frame failed = %u\n", __func__,
+ vcd_status);
+ return -EIO;
+ }
+
+ } else {
+ DBG("%s(): kernel_vaddr not found\n", __func__);
+ return -EIO;
+ }
+}
+
+static int mpq_int_vid_dec_fill_output_buffer(
+ struct video_client_ctx *client_ctx,
+ struct video_data_buffer *fill_buffer)
+{
+ unsigned long kernel_vaddr, phy_addr, user_vaddr;
+ int pmem_fd;
+ struct file *file;
+ s32 buffer_index = -1;
+ u32 vcd_status = VCD_ERR_FAIL;
+ struct ion_handle *buff_handle = NULL;
+
+ struct vcd_frame_data vcd_frame;
+
+ if (!client_ctx || !fill_buffer)
+ return -EINVAL;
+
+ user_vaddr = (unsigned long)fill_buffer->bufferaddr;
+
+ if (vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT,
+ true, &user_vaddr, &kernel_vaddr,
+ &phy_addr, &pmem_fd, &file,
+ &buffer_index)) {
+
+ memset((void *)&vcd_frame, 0,
+ sizeof(struct vcd_frame_data));
+ vcd_frame.virtual = (u8 *) kernel_vaddr;
+ vcd_frame.frm_clnt_data = (u32) fill_buffer->client_data;
+ vcd_frame.alloc_len = fill_buffer->buffer_len;
+ vcd_frame.ion_flag = vidc_get_fd_info(client_ctx,
+ BUFFER_TYPE_OUTPUT,
+ pmem_fd, kernel_vaddr,
+ buffer_index,
+ &buff_handle);
+ vcd_frame.buff_ion_handle = buff_handle;
+ vcd_status = vcd_fill_output_buffer(client_ctx->vcd_handle,
+ &vcd_frame);
+ if (!vcd_status)
+ return 0;
+ else {
+ DBG("%s(): vcd_fill_output_buffer failed = %u\n",
+ __func__, vcd_status);
+ return -EINVAL;
+ }
+ } else {
+ DBG("%s(): kernel_vaddr not found\n", __func__);
+ return -EIO;
+ }
+}
+
+
+static int mpq_int_vid_dec_flush(struct video_client_ctx *client_ctx,
+ enum vdec_bufferflush flush_dir)
+{
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ DBG("msm_vidc_dec: %s() called with dir = %u", __func__,
+ flush_dir);
+ if (!client_ctx) {
+ DBG("Invalid client_ctx\n");
+ return -EINVAL;
+ }
+
+ switch (flush_dir) {
+ case VDEC_FLUSH_TYPE_INPUT:
+ vcd_status = vcd_flush(client_ctx->vcd_handle,
+ VCD_FLUSH_INPUT);
+ break;
+ case VDEC_FLUSH_TYPE_OUTPUT:
+ vcd_status = vcd_flush(client_ctx->vcd_handle,
+ VCD_FLUSH_OUTPUT);
+ break;
+ case VDEC_FLUSH_TYPE_ALL:
+ vcd_status = vcd_flush(client_ctx->vcd_handle, VCD_FLUSH_ALL);
+ break;
+ default:
+ ERR("%s(): Inavlid flush cmd. flush_dir = %u\n", __func__,
+ flush_dir);
+ return -EINVAL;
+ break;
+ }
+
+ if (!vcd_status)
+ return 0;
+ else {
+ DBG("%s(): vcd_flush failed. vcd_status = %u "\
+ " flush_dir = %u\n", __func__, vcd_status, flush_dir);
+ return -EIO;
+ }
+}
+
+static u32 mpq_int_vid_dec_msg_pending(struct video_client_ctx *client_ctx)
+{
+ u32 islist_empty = 0;
+ mutex_lock(&client_ctx->msg_queue_lock);
+ islist_empty = list_empty(&client_ctx->msg_queue);
+ mutex_unlock(&client_ctx->msg_queue_lock);
+
+ if (islist_empty) {
+ DBG("%s(): vid_dec msg queue empty\n", __func__);
+ if (client_ctx->stop_msg) {
+ DBG("%s(): List empty and Stop Msg set\n",
+ __func__);
+ return client_ctx->stop_msg;
+ }
+ } else {
+ DBG("%s(): vid_dec msg queue Not empty\n", __func__);
+ }
+
+ return !islist_empty;
+}
+
+static int mpq_int_vid_dec_get_next_msg(struct video_client_ctx *client_ctx,
+ struct vdec_msginfo *vdec_msg_info)
+{
+ struct vid_dec_msg *vid_dec_msg = NULL;
+
+ if (!client_ctx)
+ return -EINVAL;
+
+ mutex_lock(&client_ctx->msg_queue_lock);
+ if (!list_empty(&client_ctx->msg_queue)) {
+ DBG("%s(): After Wait\n", __func__);
+ vid_dec_msg = list_first_entry(&client_ctx->msg_queue,
+ struct vid_dec_msg, list);
+ list_del(&vid_dec_msg->list);
+ memcpy(vdec_msg_info, &vid_dec_msg->vdec_msg_info,
+ sizeof(struct vdec_msginfo));
+ kfree(vid_dec_msg);
+ }
+ mutex_unlock(&client_ctx->msg_queue_lock);
+ return 0;
+}
+
+static u32 mpq_int_vid_dec_close_client(struct video_client_ctx *client_ctx)
+{
+ struct vid_dec_msg *vdec_msg;
+ u32 vcd_status;
+
+ DBG("msm_vidc_dec: Inside %s()", __func__);
+ if (!client_ctx || (!client_ctx->vcd_handle)) {
+ DBG("Invalid client_ctx\n");
+ return false;
+ }
+
+ mutex_lock(&mpq_dvb_video_device->lock);
+ if (!client_ctx->stop_called) {
+ client_ctx->stop_called = true;
+ client_ctx->stop_sync_cb = true;
+ vcd_status = vcd_stop(client_ctx->vcd_handle);
+ DBG("Stuck at the stop call\n");
+ if (!vcd_status)
+ wait_for_completion(&client_ctx->event);
+ DBG("Came out of wait event\n");
+ }
+ mutex_lock(&client_ctx->msg_queue_lock);
+ while (!list_empty(&client_ctx->msg_queue)) {
+ DBG("%s(): Delete remaining entries\n", __func__);
+ vdec_msg = list_first_entry(&client_ctx->msg_queue,
+ struct vid_dec_msg, list);
+ if (vdec_msg) {
+ list_del(&vdec_msg->list);
+ kfree(vdec_msg);
+ }
+ }
+ mutex_unlock(&client_ctx->msg_queue_lock);
+ vcd_status = vcd_close(client_ctx->vcd_handle);
+
+ if (vcd_status) {
+ mutex_unlock(&mpq_dvb_video_device->lock);
+ return false;
+ }
+ client_ctx->user_ion_client = NULL;
+ mutex_destroy(&client_ctx->msg_queue_lock);
+ mutex_destroy(&client_ctx->enrty_queue_lock);
+ memset((void *)client_ctx, 0, sizeof(struct video_client_ctx));
+ mpq_dvb_video_device->num_clients--;
+ mutex_unlock(&mpq_dvb_video_device->lock);
+ return true;
+}
+
+static int mpq_int_vid_dec_open_client(struct video_client_ctx **vid_clnt_ctx,
+ int flags)
+{
+ int rc = 0;
+ s32 client_index;
+ struct video_client_ctx *client_ctx = NULL;
+ u8 client_count;
+
+ if (!vid_clnt_ctx) {
+ DBG("Invalid input\n");
+ return -EINVAL;
+ }
+ *vid_clnt_ctx = NULL;
+ client_count = vcd_get_num_of_clients();
+ if (client_count == VIDC_MAX_NUM_CLIENTS) {
+ ERR("ERROR : vid_dec_open() max number of clients"\
+ "limit reached\n");
+ return -ENOMEM;
+ }
+
+ DBG(" Virtual Address of ioremap is %p\n",
+ mpq_dvb_video_device->virt_base);
+ if (!mpq_dvb_video_device->num_clients)
+ if (!vidc_load_firmware())
+ return -ENOMEM;
+
+ client_index = mpq_int_vid_dec_get_empty_client_index();
+ if (client_index == -1) {
+ DBG("%s() : No free clients client_index == -1\n", __func__);
+ vidc_release_firmware();
+ return -ENOMEM;
+ }
+ client_ctx = &mpq_dvb_video_device->vdec_clients[client_index];
+ mpq_dvb_video_device->num_clients++;
+ init_completion(&client_ctx->event);
+ mutex_init(&client_ctx->msg_queue_lock);
+ mutex_init(&client_ctx->enrty_queue_lock);
+ INIT_LIST_HEAD(&client_ctx->msg_queue);
+ init_waitqueue_head(&client_ctx->msg_wait);
+ client_ctx->stop_msg = 0;
+ client_ctx->stop_called = false;
+ client_ctx->stop_sync_cb = false;
+ client_ctx->dmx_disable = 0;
+ if (vcd_get_ion_status()) {
+ client_ctx->user_ion_client = vcd_get_ion_client();
+ if (!client_ctx->user_ion_client) {
+ ERR("vcd_open ion client get failed");
+ rc = -ENOMEM;
+ goto client_failure;
+ }
+ }
+ rc = vcd_open(mpq_dvb_video_device->device_handle, true,
+ mpq_int_vid_dec_vcd_cb, client_ctx, flags);
+ if (!rc) {
+ wait_for_completion(&client_ctx->event);
+ if (client_ctx->event_status) {
+ DBG("callback for vcd_open returned error: %u",
+ client_ctx->event_status);
+ rc = -ENODEV;
+ goto client_failure;
+ }
+ } else {
+ DBG("vcd_open returned error: %u", rc);
+ goto client_failure;
+ }
+ client_ctx->seq_header_set = false;
+ *vid_clnt_ctx = client_ctx;
+
+ return 0;
+
+client_failure:
+ vidc_release_firmware();
+ mpq_dvb_video_device->num_clients--;
+ mutex_destroy(&client_ctx->msg_queue_lock);
+ mutex_destroy(&client_ctx->enrty_queue_lock);
+ memset((void *)client_ctx, 0, sizeof(struct video_client_ctx));
+ return rc;
+}
+
+static int mpq_dvb_video_open(struct inode *inode, struct file *file)
+{
+ int rc;
+ struct mpq_dvb_video_inst *dev_inst = NULL;
+ struct dvb_device *device = NULL;
+
+ DBG("Inside %s()", __func__);
+ mutex_lock(&mpq_dvb_video_device->lock);
+
+ /* Open the dvb/video instance */
+ rc = dvb_generic_open(inode, file);
+ if (rc) {
+ DBG("Failed in dvb_generic_open with return value :%d\n",
+ rc);
+ mutex_unlock(&mpq_dvb_video_device->lock);
+ return rc;
+
+ }
+
+ device = (struct dvb_device *)file->private_data;
+ dev_inst = (struct mpq_dvb_video_inst *)device->priv;
+
+ if (dev_inst->client_ctx) {
+ dvb_generic_release(inode, file);
+ mutex_unlock(&mpq_dvb_video_device->lock);
+ return -EEXIST;
+ }
+
+ rc = mpq_int_vid_dec_open_client(&dev_inst->client_ctx, 0);
+ if (rc) {
+ dvb_generic_release(inode, file);
+ mutex_unlock(&mpq_dvb_video_device->lock);
+ return rc;
+ }
+
+ if (!dev_inst->client_ctx) {
+ dvb_generic_release(inode, file);
+ mutex_unlock(&mpq_dvb_video_device->lock);
+ return -ENOMEM;
+ }
+
+ /* Set default source to memory for easier handling */
+ dev_inst->source = VIDEO_SOURCE_MEMORY;
+
+ mutex_unlock(&mpq_dvb_video_device->lock);
+
+ return rc;
+}
+
+static int mpq_dvb_video_term_dmx_src(struct mpq_dvb_video_inst *dev_inst)
+{
+
+ struct mpq_dmx_src_data *dmx_data = dev_inst->dmx_src_data;
+
+ if (NULL == dmx_data)
+ return 0;
+
+ kthread_stop(dmx_data->data_task);
+ mutex_destroy(&dmx_data->msg_queue_lock);
+
+ kfree(dmx_data);
+ dev_inst->dmx_src_data = NULL;
+
+ return 0;
+
+}
+
+static int mpq_dvb_video_release(struct inode *inode, struct file *file)
+{
+ struct dvb_device *device = file->private_data;
+ struct mpq_dvb_video_inst *dev_inst = device->priv;
+
+ vidc_cleanup_addr_table(dev_inst->client_ctx, BUFFER_TYPE_OUTPUT);
+ vidc_cleanup_addr_table(dev_inst->client_ctx, BUFFER_TYPE_INPUT);
+ if (dev_inst->source == VIDEO_SOURCE_DEMUX)
+ mpq_dvb_video_term_dmx_src(dev_inst);
+ mpq_int_vid_dec_close_client(dev_inst->client_ctx);
+ memset((void *)dev_inst, 0, sizeof(struct mpq_dvb_video_inst));
+ vidc_release_firmware();
+ dvb_generic_release(inode, file);
+ return 0;
+}
+
+static void *mpq_int_vid_dec_map_dev_base_addr(void *device_name)
+{
+ return mpq_dvb_video_device->virt_base;
+}
+
+static int mpq_int_vid_dec_vcd_init(void)
+{
+ int rc;
+ struct vcd_init_config vcd_init_config;
+ u32 i;
+
+ /* init_timer(&hw_timer); */
+ DBG("msm_vidc_dec: Inside %s()", __func__);
+ mpq_dvb_video_device->num_clients = 0;
+
+ for (i = 0; i < VIDC_MAX_NUM_CLIENTS; i++) {
+ memset((void *)&mpq_dvb_video_device->vdec_clients[i], 0,
+ sizeof(mpq_dvb_video_device->vdec_clients[i]));
+ }
+
+ mutex_init(&mpq_dvb_video_device->lock);
+ mpq_dvb_video_device->virt_base = vidc_get_ioaddr();
+ DBG("%s() : base address for VIDC core %u\n", __func__, \
+ (int)mpq_dvb_video_device->virt_base);
+
+ if (!mpq_dvb_video_device->virt_base) {
+ DBG("%s() : ioremap failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ vcd_init_config.device_name = "MPQ_VIDC";
+ vcd_init_config.map_dev_base_addr = mpq_int_vid_dec_map_dev_base_addr;
+ vcd_init_config.interrupt_clr = NULL;
+ vcd_init_config.register_isr = NULL;
+ vcd_init_config.deregister_isr = NULL;
+ vcd_init_config.timer_create = vidc_timer_create;
+ vcd_init_config.timer_release = vidc_timer_release;
+ vcd_init_config.timer_start = vidc_timer_start;
+ vcd_init_config.timer_stop = vidc_timer_stop;
+
+ rc = vcd_init(&vcd_init_config,
+ &mpq_dvb_video_device->device_handle);
+
+ if (rc) {
+ DBG("%s() : vcd_init failed\n", __func__);
+ mutex_destroy(&mpq_dvb_video_device->lock);
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static int mpq_int_vdec_get_fps(struct video_client_ctx *client_ctx,
+ unsigned int *fps)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_frame_rate vcd_frame_rate;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (NULL == fps)
+ return -EINVAL;
+
+ vcd_property_hdr.prop_id = VCD_I_FRAME_RATE;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_frame_rate);
+ vcd_frame_rate.fps_numerator = 0;
+ vcd_frame_rate.fps_denominator = 1;
+
+ *fps = 0;
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_frame_rate);
+
+ if (vcd_status)
+ return -EINVAL;
+ else {
+ *fps = (vcd_frame_rate.fps_numerator * 1000)
+ /(vcd_frame_rate.fps_denominator);
+ return 0;
+ }
+}
+
+static int mpq_dvb_video_command_handler(struct mpq_dvb_video_inst *dev_inst,
+ void *parg)
+{
+ struct video_client_ctx *client_ctx = dev_inst->client_ctx;
+ struct video_command *cmd = parg;
+ int rc = 0;
+
+ if (cmd == NULL)
+ return -EINVAL;
+
+ switch (cmd->cmd) {
+ case VIDEO_CMD_SET_CODEC:
+ DBG("cmd : VIDEO_CMD_SET_CODEC\n");
+ rc = mpq_int_vid_dec_set_codec(client_ctx, cmd->codec);
+ break;
+ case VIDEO_CMD_GET_CODEC:
+ DBG("cmd : VIDEO_CMD_GET_CODEC\n");
+ rc = mpq_int_vid_dec_get_codec(client_ctx, &cmd->codec);
+ break;
+ case VIDEO_CMD_SET_OUTPUT_FORMAT:
+ DBG("cmd : VIDEO_CMD_SET_OUTPUT_FORMAT\n");
+ rc = mpq_int_vid_dec_set_output_format(client_ctx,
+ cmd->format);
+ break;
+ case VIDEO_CMD_GET_OUTPUT_FORMAT:
+ DBG("cmd : VIDEO_CMD_GET_OUTPUT_FORMAT\n");
+ rc = mpq_int_vid_dec_get_output_format(client_ctx,
+ &cmd->format);
+ break;
+ case VIDEO_CMD_GET_PIC_RES:
+ DBG("cmd : VIDEO_CMD_GET_PIC_RES\n");
+ rc = mpq_int_vid_dec_get_frame_resolution(client_ctx,
+ &cmd->frame_res);
+ break;
+ case VIDEO_CMD_SET_INPUT_BUFFERS:
+ DBG("cmd : VIDEO_CMD_SET_INPUT_BUFFERS\n");
+ rc = mpq_int_vid_dec_set_buffer(dev_inst, &cmd->buffer,
+ BUFFER_TYPE_INPUT);
+ break;
+ case VIDEO_CMD_SET_OUTPUT_BUFFERS:
+ DBG("cmd : VIDEO_CMD_SET_OUTPUT_BUFFERS\n");
+ rc = mpq_int_vid_dec_set_buffer(dev_inst, &cmd->buffer,
+ BUFFER_TYPE_OUTPUT);
+ break;
+ case VIDEO_CMD_FREE_INPUT_BUFFERS:
+ DBG("cmd : VIDEO_CMD_FREE_INPUT_BUFFERS\n");
+ rc = mpq_int_vid_dec_free_buffer(client_ctx, &cmd->buffer,
+ BUFFER_TYPE_INPUT);
+ break;
+ case VIDEO_CMD_FREE_OUTPUT_BUFFERS:
+ DBG("cmd : VIDEO_CMD_FREE_OUTPUT_BUFFERS\n");
+ rc = mpq_int_vid_dec_free_buffer(client_ctx, &cmd->buffer,
+ BUFFER_TYPE_OUTPUT);
+ break;
+ case VIDEO_CMD_GET_BUFFER_REQ:
+ DBG("cmd : VIDEO_CMD_GET_BUFFER_REQ\n");
+ rc = mpq_int_vid_dec_get_buffer_req(client_ctx, &cmd->buf_req);
+ break;
+ case VIDEO_CMD_READ_RAW_OUTPUT:
+ DBG("cmd : VIDEO_CMD_READ_RAW_OUTPUT\n");
+ rc = mpq_int_vid_dec_fill_output_buffer(client_ctx,
+ &cmd->buffer);
+ break;
+ case VIDEO_CMD_SET_H264_MV_BUFFER:
+ DBG("cmd : VIDEO_CMD_SET_H264_MV_BUFFER\n");
+ rc = mpq_int_vid_dec_set_h264_mv_buffers(client_ctx,
+ &cmd->mv_buffer_prop);
+ break;
+ case VIDEO_CMD_GET_H264_MV_BUFFER:
+ DBG("cmd : VIDEO_CMD_GET_H264_MV_BUFFER\n");
+ rc = mpq_int_vid_dec_get_h264_mv_buffer_size(client_ctx,
+ &cmd->mv_buffer_req);
+ break;
+ case VIDEO_CMD_FREE_H264_MV_BUFFER:
+ DBG("cmd : VIDEO_CMD_FREE_H264_MV_BUFFER\n");
+ rc = mpq_int_vid_dec_free_h264_mv_buffers(client_ctx);
+ break;
+ case VIDEO_CMD_CLEAR_INPUT_BUFFER:
+ DBG("cmd : VIDEO_CMD_CLEAR_INPUT_BUFFER\n");
+ rc = mpq_int_vid_dec_flush(client_ctx, VDEC_FLUSH_TYPE_INPUT);
+ break;
+ case VIDEO_CMD_CLEAR_OUTPUT_BUFFER:
+ DBG("cmd : VIDEO_CMD_CLEAR_OUTPUT_BUFFER\n");
+ rc = mpq_int_vid_dec_flush(client_ctx, VDEC_FLUSH_TYPE_OUTPUT);
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+
+static ssize_t mpq_dvb_video_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int rc = 0;
+ struct dvb_device *device = file->private_data;
+ struct mpq_dvb_video_inst *dev_inst = NULL;
+
+ struct video_data_buffer *input_frame =
+ (struct video_data_buffer *)buf;
+
+ if ((device == NULL) || (input_frame == NULL))
+ return -EINVAL;
+
+ dev_inst = device->priv;
+ if (dev_inst == NULL)
+ return -EINVAL;
+
+ rc = mpq_int_vid_dec_decode_frame(dev_inst->client_ctx, input_frame);
+ if (rc)
+ return -EIO;
+
+ return input_frame->buffer_len;
+}
+
+static int mpq_dvb_video_get_event(struct video_client_ctx *client_ctx,
+ struct video_event *ev)
+{
+ int rc;
+ struct vdec_msginfo vdec_msg_info;
+
+ memset(ev, 0, sizeof(struct video_event));
+
+ rc = mpq_int_vid_dec_get_next_msg(client_ctx, &vdec_msg_info);
+ if (rc)
+ return rc;
+
+ ev->status = vdec_msg_info.status_code;
+ /* Map the Message here */
+ switch (vdec_msg_info.msgcode) {
+ case VDEC_MSG_INVALID:
+ DBG("VDEC_MSG_INVALID\n");
+ break;
+ case VDEC_MSG_RESP_INPUT_BUFFER_DONE:
+ DBG("VIDEO_EVENT_INPUT_BUFFER_DONE\n");
+ ev->type = VIDEO_EVENT_INPUT_BUFFER_DONE;
+ ev->u.buffer.client_data =
+ vdec_msg_info.msgdata.input_frame_clientdata;
+ break;
+ case VDEC_MSG_RESP_OUTPUT_BUFFER_DONE:
+ DBG("VIDEO_EVENT_OUTPUT_BUFFER_DONE\n");
+ ev->type = VIDEO_EVENT_OUTPUT_BUFFER_DONE;
+ ev->u.buffer.bufferaddr =
+ vdec_msg_info.msgdata.output_frame.bufferaddr;
+ ev->u.buffer.buffer_len =
+ vdec_msg_info.msgdata.output_frame.len;
+ ev->u.buffer.ip_buffer_tag = vdec_msg_info.msgdata.\
+ output_frame.input_frame_clientdata;
+ ev->u.buffer.client_data = vdec_msg_info.msgdata.\
+ output_frame.client_data;
+ ev->u.buffer.pts =
+ vdec_msg_info.msgdata.output_frame.time_stamp;
+ ev->u.buffer.offset =
+ vdec_msg_info.msgdata.output_frame.offset;
+ break;
+ case VDEC_MSG_RESP_START_DONE:
+ DBG("VIDEO_EVENT_DECODER_PLAYING\n");
+ ev->type = VIDEO_EVENT_DECODER_PLAYING;
+ break;
+ case VDEC_MSG_RESP_STOP_DONE:
+ DBG("VIDEO_EVENT_DECODER_FREEZED\n");
+ ev->type = VIDEO_EVENT_DECODER_STOPPED;
+ break;
+ case VDEC_MSG_RESP_PAUSE_DONE:
+ DBG("VDEC_MSG_RESP_PAUSE_DONE\n");
+ ev->type = VIDEO_EVENT_DECODER_FREEZED;
+ break;
+ case VDEC_MSG_RESP_RESUME_DONE:
+ DBG("VIDEO_EVENT_DECODER_RESUMED\n");
+ ev->type = VIDEO_EVENT_DECODER_RESUMED;
+ break;
+ case VDEC_MSG_EVT_CONFIG_CHANGED:
+ case VDEC_MSG_EVT_INFO_CONFIG_CHANGED:
+ DBG("VIDEO_EVENT_SEQ_HDR_FOUND\n");
+ ev->type = VIDEO_EVENT_SEQ_HDR_FOUND;
+ break;
+ case VDEC_MSG_RESP_FLUSH_OUTPUT_DONE:
+ DBG("VIDEO_EVENT_OUTPUT_FLUSH_DONE\n");
+ ev->type = VIDEO_EVENT_OUTPUT_FLUSH_DONE;
+ break;
+ case VDEC_MSG_RESP_OUTPUT_FLUSHED:
+ DBG("VIDEO_EVENT_OUTPUT_FLUSHED\n");
+ ev->type = VIDEO_EVENT_OUTPUT_FLUSHED;
+ ev->u.buffer.bufferaddr =
+ vdec_msg_info.msgdata.output_frame.bufferaddr;
+ ev->u.buffer.buffer_len =
+ vdec_msg_info.msgdata.output_frame.len;
+ ev->u.buffer.ip_buffer_tag = vdec_msg_info.msgdata.\
+ output_frame.input_frame_clientdata;
+ ev->u.buffer.client_data = vdec_msg_info.msgdata.\
+ output_frame.client_data;
+ ev->u.buffer.pts =
+ vdec_msg_info.msgdata.output_frame.time_stamp;
+ ev->u.buffer.offset =
+ vdec_msg_info.msgdata.output_frame.offset;
+ break;
+ case VDEC_MSG_RESP_FLUSH_INPUT_DONE:
+ DBG("VIDEO_EVENT_INPUT_FLUSH_DONE\n");
+ ev->type = VIDEO_EVENT_INPUT_FLUSH_DONE;
+ break;
+ case VDEC_MSG_RESP_INPUT_FLUSHED:
+ DBG("VIDEO_EVENT_INPUT_FLUSHED\n");
+ ev->type = VIDEO_EVENT_INPUT_FLUSHED;
+ ev->u.buffer.client_data =
+ vdec_msg_info.msgdata.input_frame_clientdata;
+ break;
+ }
+ return 0;
+}
+
+static int mpq_dvb_video_play(struct mpq_dvb_video_inst *dev_inst)
+{
+ return mpq_int_vid_dec_start_stop(dev_inst->client_ctx, true);
+}
+
+static int mpq_dvb_video_stop(struct video_client_ctx *client_ctx)
+{
+ return mpq_int_vid_dec_start_stop(client_ctx, false);
+}
+
+static void mpq_dvb_video_get_stream_if(
+ enum mpq_adapter_stream_if interface_id,
+ void *arg)
+{
+ struct mpq_dvb_video_inst *dev_inst = arg;
+
+ DBG("In mpq_dvb_video_get_stream_if : %d\n", interface_id);
+
+ mpq_adapter_get_stream_if(interface_id,
+ &dev_inst->dmx_src_data->stream_buffer);
+
+ wake_up(&dev_inst->dmx_src_data->msg_wait);
+}
+
+static int mpq_dvb_video_init_dmx_src(struct mpq_dvb_video_inst *dev_inst,
+ int device_id)
+{
+ int rc;
+
+ dev_inst->dmx_src_data = kzalloc(sizeof(struct mpq_dmx_src_data),
+ GFP_KERNEL);
+ if (dev_inst->dmx_src_data == NULL)
+ return -ENOMEM;
+
+ rc = mpq_adapter_get_stream_if(
+ (enum mpq_adapter_stream_if)device_id,
+ &dev_inst->dmx_src_data->stream_buffer);
+
+ if (rc) {
+ kfree(dev_inst->dmx_src_data);
+ return -ENODEV;
+ } else if (dev_inst->dmx_src_data->stream_buffer == NULL) {
+ DBG("Stream Buffer is NULL. Resigtering Notifier.\n");
+ rc = mpq_adapter_notify_stream_if(
+ (enum mpq_adapter_stream_if)device_id,
+ mpq_dvb_video_get_stream_if,
+ (void *)dev_inst);
+ if (rc) {
+ kfree(dev_inst->dmx_src_data);
+ return -ENODEV;
+ }
+ }
+
+ mutex_init(&dev_inst->dmx_src_data->msg_queue_lock);
+ INIT_LIST_HEAD(&dev_inst->dmx_src_data->msg_queue);
+ init_waitqueue_head(&dev_inst->dmx_src_data->msg_wait);
+
+ dev_inst->dmx_src_data->data_task = kthread_run(
+ mpq_bcast_data_handler, (void *)dev_inst,
+ vid_thread_names[device_id]);
+
+ return 0;
+}
+
+static int mpq_dvb_video_set_source(struct dvb_device *device,
+ video_stream_source_t source)
+{
+ int rc = 0;
+ struct mpq_dvb_video_inst *dev_inst =
+ (struct mpq_dvb_video_inst *)device->priv;
+
+ if (dev_inst->source == source)
+ return rc;
+
+ if ((VIDEO_SOURCE_MEMORY == source) &&
+ (VIDEO_SOURCE_DEMUX == dev_inst->source))
+ mpq_dvb_video_term_dmx_src(dev_inst);
+
+ dev_inst->source = source;
+ if (VIDEO_SOURCE_DEMUX == source)
+ rc = mpq_dvb_video_init_dmx_src(dev_inst, device->id);
+
+ return rc;
+}
+
+static int mpq_dvb_video_ioctl(struct file *file,
+ unsigned int cmd, void *parg)
+{
+ int rc;
+ struct dvb_device *device = (struct dvb_device *)file->private_data;
+ struct video_client_ctx *client_ctx = NULL;
+ struct mpq_dvb_video_inst *dev_inst = NULL;
+
+ if (device == NULL)
+ return -EINVAL;
+
+ dev_inst = (struct mpq_dvb_video_inst *)device->priv;
+ if (dev_inst == NULL)
+ return -EINVAL;
+
+ client_ctx = (struct video_client_ctx *)dev_inst->client_ctx;
+ if (client_ctx == NULL)
+ return -EINVAL;
+
+ switch (cmd) {
+ case VIDEO_PLAY:
+ DBG("ioctl : VIDEO_PLAY\n");
+ rc = mpq_dvb_video_play(dev_inst);
+ break;
+ case VIDEO_STOP:
+ DBG("ioctl : VIDEO_STOP\n");
+ rc = mpq_dvb_video_stop(client_ctx);
+ break;
+ case VIDEO_FREEZE:
+ DBG("ioctl : VIDEO_FREEZE\n");
+ rc = mpq_int_vid_dec_pause_resume(client_ctx, true);
+ break;
+ case VIDEO_CONTINUE:
+ DBG("ioctl : VIDEO_CONTINUE\n");
+ rc = mpq_int_vid_dec_pause_resume(client_ctx, false);
+ break;
+ case VIDEO_CLEAR_BUFFER:
+ DBG("ioctl : VIDEO_CLEAR_BUFFER\n");
+ rc = mpq_int_vid_dec_flush(client_ctx,
+ VDEC_FLUSH_TYPE_ALL);
+ break;
+ case VIDEO_COMMAND:
+ case VIDEO_TRY_COMMAND:
+ DBG("ioctl : VIDEO_COMMAND\n");
+ rc = mpq_dvb_video_command_handler(dev_inst, parg);
+ break;
+ case VIDEO_GET_FRAME_RATE:
+ DBG("ioctl : VIDEO_GET_FRAME_RATE\n");
+ rc = mpq_int_vdec_get_fps(client_ctx,
+ (unsigned int *)parg);
+ break;
+ case VIDEO_GET_EVENT:
+ DBG("ioctl : VIDEO_GET_EVENT\n");
+ rc = mpq_dvb_video_get_event(client_ctx,
+ (struct video_event *)parg);
+ break;
+ case VIDEO_SELECT_SOURCE:
+ DBG("ioctl : VIDEO_SELECT_SOURCE\n");
+ rc = mpq_dvb_video_set_source(device,
+ (video_stream_source_t)parg);
+ break;
+ default:
+ ERR("Invalid IOCTL\n");
+ rc = -EINVAL;
+ }
+
+ return rc;
+
+}
+
+static unsigned int mpq_dvb_video_poll(struct file *file, poll_table *wait)
+{
+ struct dvb_device *device = file->private_data;
+ struct video_client_ctx *client_ctx = NULL;
+ struct mpq_dvb_video_inst *dev_inst = NULL;
+ unsigned int mask = 0;
+
+ DBG("In %s\n", __func__);
+
+ if (device == NULL)
+ return -EINVAL;
+
+ dev_inst = device->priv;
+ if (dev_inst == NULL)
+ return -EINVAL;
+
+ client_ctx = dev_inst->client_ctx;
+ if (client_ctx == NULL)
+ return -EINVAL;
+
+ poll_wait(file, &client_ctx->msg_wait, wait);
+ if (mpq_int_vid_dec_msg_pending(client_ctx))
+ mask |= POLLIN;
+ else
+ mask = 0;
+
+ return mask;
+}
+
+/*
+ * Driver Registration.
+ */
+static const struct file_operations mpq_dvb_video_fops = {
+ .owner = THIS_MODULE,
+ .write = mpq_dvb_video_write,
+ .unlocked_ioctl = dvb_generic_ioctl,
+ .open = mpq_dvb_video_open,
+ .release = mpq_dvb_video_release,
+ .poll = mpq_dvb_video_poll,
+ .llseek = noop_llseek,
+};
+
+static const struct dvb_device mpq_dvb_video_device_ctrl = {
+ .priv = NULL,
+ .users = 4,
+ .readers = 4, /* arbitrary */
+ .writers = 4,
+ .fops = &mpq_dvb_video_fops,
+ .kernel_ioctl = mpq_dvb_video_ioctl,
+};
+
+static int __init mpq_dvb_video_init(void)
+{
+ int rc, i = 0, j;
+
+ mpq_dvb_video_device = kzalloc(sizeof(struct mpq_dvb_video_dev),
+ GFP_KERNEL);
+ if (!mpq_dvb_video_device) {
+ ERR("%s Unable to allocate memory for mpq_dvb_video_dev\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ mpq_dvb_video_device->mpq_adapter = mpq_adapter_get();
+ if (!mpq_dvb_video_device->mpq_adapter) {
+ ERR("%s Unable to get MPQ Adapter\n", __func__);
+ rc = -ENODEV;
+ goto free_region;
+ }
+
+ rc = mpq_int_vid_dec_vcd_init();
+ if (rc)
+ goto free_region;
+
+ for (i = 0; i < DVB_MPQ_NUM_VIDEO_DEVICES; i++) {
+
+ rc = dvb_register_device(mpq_dvb_video_device->mpq_adapter,
+ &mpq_dvb_video_device->dev_inst[i].video_dev,
+ &mpq_dvb_video_device_ctrl,
+ &mpq_dvb_video_device->dev_inst[i],
+ DVB_DEVICE_VIDEO);
+
+ if (rc) {
+ ERR("Failed in %s with at %d return value :%d\n",
+ __func__, i, rc);
+ goto free_region;
+ }
+
+ }
+
+ return 0;
+
+free_region:
+ for (j = 0; j < i; j++)
+ dvb_unregister_device(
+ mpq_dvb_video_device->dev_inst[j].video_dev);
+
+ kfree(mpq_dvb_video_device);
+ return rc;
+}
+
+static void __exit mpq_dvb_video_exit(void)
+{
+ int i;
+
+ for (i = 0; i < DVB_MPQ_NUM_VIDEO_DEVICES; i++)
+ dvb_unregister_device(
+ mpq_dvb_video_device->dev_inst[i].video_dev);
+
+ mutex_destroy(&mpq_dvb_video_device->lock);
+ kfree(mpq_dvb_video_device);
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MPQ DVB Video driver");
+
+module_init(mpq_dvb_video_init);
+module_exit(mpq_dvb_video_exit);
diff --git a/drivers/media/dvb/mpq/video/mpq_dvb_video_internal.h b/drivers/media/dvb/mpq/video/mpq_dvb_video_internal.h
new file mode 100644
index 0000000..df337b9
--- /dev/null
+++ b/drivers/media/dvb/mpq/video/mpq_dvb_video_internal.h
@@ -0,0 +1,93 @@
+/* Copyright (c) 2010,2012, Code Aurora Forum. 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 MPQ_DVB_VIDEO_INTERNAL_H
+#define MPQ_DVB_VIDEO_INTERNAL_H
+
+#include <linux/msm_vidc_dec.h>
+#include <media/msm/vidc_init.h>
+#include <linux/dvb/video.h>
+
+/*
+ * MPQ Specific Includes.
+ */
+#include "mpq_dvb_debug.h"
+#include "mpq_adapter.h"
+#include "mpq_stream_buffer.h"
+
+#define DVB_MPQ_NUM_VIDEO_DEVICES CONFIG_DVB_MPQ_NUM_VIDEO_DEVICES
+
+/*
+ * Input Buffer Requirements for Video Decoder.
+ */
+#define DVB_VID_NUM_IN_BUFFERS (2)
+#define DVB_VID_IN_BUFFER_SIZE (2*1024*1024)
+#define DVB_VID_IN_BUFFER_ALGN (8*1024)
+
+struct vid_dec_msg {
+ struct list_head list;
+ struct vdec_msginfo vdec_msg_info;
+};
+
+enum mpq_bcast_msgcode {
+ MPQ_BCAST_MSG_START,
+ MPQ_BCAST_MSG_IBD,
+ MPQ_BCAST_MSG_FLUSH,
+ MPQ_BCAST_MSG_TERM
+};
+
+struct mpq_bcast_msg_info {
+ enum mpq_bcast_msgcode code;
+ unsigned int data;
+};
+
+struct mpq_bcast_msg {
+ struct list_head list;
+ struct mpq_bcast_msg_info info;
+};
+
+struct mpq_dmx_src_data {
+ struct mpq_streambuffer *stream_buffer;
+ struct video_data_buffer in_buffer[DVB_VID_NUM_IN_BUFFERS];
+ struct list_head msg_queue;
+ wait_queue_head_t msg_wait;
+ struct mutex msg_queue_lock;
+ struct task_struct *data_task;
+};
+
+struct mpq_dvb_video_inst {
+ struct dvb_device *video_dev;
+ video_stream_source_t source;
+ struct mpq_dmx_src_data *dmx_src_data;
+ struct video_client_ctx *client_ctx;
+};
+
+struct mpq_dvb_video_dev {
+
+ resource_size_t phys_base;
+ void __iomem *virt_base;
+ unsigned int irq;
+ struct clk *hclk;
+ struct clk *hclk_div2;
+ struct clk *pclk;
+ unsigned long hclk_rate;
+ struct mutex lock;
+ s32 device_handle;
+ struct dvb_adapter *mpq_adapter;
+ struct mpq_dvb_video_inst dev_inst[DVB_MPQ_NUM_VIDEO_DEVICES];
+ struct video_client_ctx vdec_clients[DVB_MPQ_NUM_VIDEO_DEVICES];
+ u32 num_clients;
+ void(*timer_handler)(void *);
+};
+
+#endif /* MPQ_DVB_VIDEO_INTERNAL_H */
diff --git a/drivers/media/video/msm/actuators/msm_actuator.c b/drivers/media/video/msm/actuators/msm_actuator.c
index 554cddc..b5bdaae 100644
--- a/drivers/media/video/msm/actuators/msm_actuator.c
+++ b/drivers/media/video/msm/actuators/msm_actuator.c
@@ -250,8 +250,6 @@
target_step_pos = dest_step_pos;
target_lens_pos =
a_ctrl->step_position_table[target_step_pos];
- if (curr_lens_pos == target_lens_pos)
- return rc;
rc = a_ctrl->func_tbl->
actuator_write_focus(
a_ctrl,
@@ -272,8 +270,6 @@
target_step_pos = step_boundary;
target_lens_pos =
a_ctrl->step_position_table[target_step_pos];
- if (curr_lens_pos == target_lens_pos)
- return rc;
rc = a_ctrl->func_tbl->
actuator_write_focus(
a_ctrl,
diff --git a/drivers/media/video/msm/cci/msm_cci.c b/drivers/media/video/msm/cci/msm_cci.c
index ad3cc6a..3caa580 100644
--- a/drivers/media/video/msm/cci/msm_cci.c
+++ b/drivers/media/video/msm/cci/msm_cci.c
@@ -24,11 +24,10 @@
#include "msm_cam_cci_hwreg.h"
#define V4L2_IDENT_CCI 50005
-#define CCI_I2C_QUEUE_0_SIZE 2
+#define CCI_I2C_QUEUE_0_SIZE 64
#define CCI_I2C_QUEUE_1_SIZE 16
-#undef CDBG
-#define CDBG pr_debug
+#define CCI_TIMEOUT msecs_to_jiffies(100)
static void msm_cci_set_clk_param(struct cci_device *cci_dev)
{
@@ -127,8 +126,9 @@
msm_camera_io_w(reg_val, cci_dev->base + CCI_QUEUE_START_ADDR);
CDBG("%s line %d wait_for_completion_interruptible\n",
__func__, __LINE__);
- wait_for_completion_interruptible(&cci_dev->
- cci_master_info[master].reset_complete);
+ wait_for_completion_interruptible_timeout(&cci_dev->
+ cci_master_info[master].reset_complete, CCI_TIMEOUT);
+
rc = cci_dev->cci_master_info[master].status;
if (rc < 0)
pr_err("%s failed rc %d\n", __func__, rc);
@@ -234,6 +234,9 @@
read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg;
mutex_lock(&cci_dev->cci_master_info[master].mutex);
CDBG("%s master %d, queue %d\n", __func__, master, queue);
+ CDBG("%s set param sid 0x%x retries %d id_map %d\n", __func__,
+ c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
+ c_ctrl->cci_info->id_map);
val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 |
c_ctrl->cci_info->retries << 16 |
c_ctrl->cci_info->id_map << 18;
@@ -285,9 +288,8 @@
val = 1 << ((master * 2) + queue);
msm_camera_io_w(val, cci_dev->base + CCI_QUEUE_START_ADDR);
-
- wait_for_completion_interruptible(&cci_dev->
- cci_master_info[master].reset_complete);
+ wait_for_completion_interruptible_timeout(&cci_dev->
+ cci_master_info[master].reset_complete, CCI_TIMEOUT);
read_bytes = (read_cfg->num_byte / 4) + 1;
index = 0;
@@ -328,6 +330,9 @@
cci_dev = v4l2_get_subdevdata(sd);
master = c_ctrl->cci_info->cci_i2c_master;
CDBG("%s master %d, queue %d\n", __func__, master, queue);
+ CDBG("%s set param sid 0x%x retries %d id_map %d\n", __func__,
+ c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
+ c_ctrl->cci_info->id_map);
mutex_lock(&cci_dev->cci_master_info[master].mutex);
val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 |
c_ctrl->cci_info->retries << 16 |
@@ -366,7 +371,7 @@
val = msm_camera_io_r(cci_dev->base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR +
master * 0x200 + queue * 0x100);
- CDBG("%s line %d size of queue %d\n", __func__, __LINE__, val);
+ CDBG("%s:%d cur word count %d\n", __func__, __LINE__, val);
CDBG("%s:%d CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR\n", __func__, __LINE__);
msm_camera_io_w(val, cci_dev->base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR +
master * 0x200 + queue * 0x100);
@@ -378,8 +383,9 @@
CDBG("%s line %d wait_for_completion_interruptible\n",
__func__, __LINE__);
- wait_for_completion_interruptible(&cci_dev->
- cci_master_info[master].reset_complete);
+ wait_for_completion_interruptible_timeout(&cci_dev->
+ cci_master_info[master].reset_complete, CCI_TIMEOUT);
+
ERROR:
mutex_unlock(&cci_dev->cci_master_info[master].mutex);
return rc;
@@ -395,7 +401,10 @@
}
static struct msm_cam_clk_info cci_clk_info[] = {
- {"cci_clk_src", 19200000},
+ {"camss_top_ahb_clk", -1},
+ {"cci_src_clk", 19200000},
+ {"cci_ahb_clk", -1},
+ {"cci_clk", -1},
};
static int32_t msm_cci_init(struct v4l2_subdev *sd)
@@ -411,7 +420,7 @@
rc = msm_cam_clk_enable(&cci_dev->pdev->dev, cci_clk_info,
cci_dev->cci_clk, ARRAY_SIZE(cci_clk_info), 1);
if (rc < 0) {
- CDBG("%s: regulator enable failed\n", __func__);
+ CDBG("%s: clk enable failed\n", __func__);
goto clk_enable_failed;
}
@@ -421,8 +430,9 @@
cci_dev->cci_master_info[MASTER_0].reset_pending = TRUE;
msm_camera_io_w(0xFFFFFFFF, cci_dev->base + CCI_RESET_CMD_ADDR);
msm_camera_io_w(0x1, cci_dev->base + CCI_RESET_CMD_ADDR);
- wait_for_completion_interruptible(&cci_dev->cci_master_info[MASTER_0].
- reset_complete);
+ wait_for_completion_interruptible_timeout(
+ &cci_dev->cci_master_info[MASTER_0].reset_complete,
+ CCI_TIMEOUT);
msm_cci_set_clk_param(cci_dev);
msm_camera_io_w(0xFFFFFFFF, cci_dev->base + CCI_IRQ_MASK_0_ADDR);
msm_camera_io_w(0xFFFFFFFF, cci_dev->base + CCI_IRQ_CLEAR_0_ADDR);
@@ -535,6 +545,12 @@
cci_dev->cci_master_info[MASTER_1].reset_pending = TRUE;
msm_camera_io_w(CCI_M1_RESET_RMSK,
cci_dev->base + CCI_RESET_CMD_ADDR);
+ } else {
+ pr_err("%s unhandled irq 0x%x\n", __func__, irq);
+ cci_dev->cci_master_info[MASTER_0].status = 0;
+ complete(&cci_dev->cci_master_info[MASTER_0].reset_complete);
+ cci_dev->cci_master_info[MASTER_1].status = 0;
+ complete(&cci_dev->cci_master_info[MASTER_1].reset_complete);
}
return IRQ_HANDLED;
}
@@ -686,11 +702,6 @@
goto cci_release_mem;
}
- CDBG("%s line %d cci irq start %d end %d\n", __func__,
- __LINE__,
- new_cci_dev->irq->start,
- new_cci_dev->irq->end);
-
new_cci_dev->pdev = pdev;
msm_cci_initialize_cci_params(new_cci_dev);
diff --git a/drivers/media/video/msm/csi/Makefile b/drivers/media/video/msm/csi/Makefile
index 547eb13..5aaaff7 100644
--- a/drivers/media/video/msm/csi/Makefile
+++ b/drivers/media/video/msm/csi/Makefile
@@ -1,5 +1,5 @@
GCC_VERSION := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-ccflags-y += -Idrivers/media/video/msm
+ccflags-y += -Idrivers/media/video/msm -Idrivers/media/video/msm/server
ifeq ($(CONFIG_MSM_CSI20_HEADER),y)
ccflags-y += -Idrivers/media/video/msm/csi/include/csi2.0
else ifeq ($(CONFIG_MSM_CSI30_HEADER),y)
diff --git a/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h b/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h
index c79748c..b66bee0 100644
--- a/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi2.0/msm_csid_hwreg.h
@@ -47,5 +47,6 @@
#define CSID_RST_STB_ALL 0x7FFF
#define CSID_DL_INPUT_SEL_SHIFT 0x2
#define CSID_PHY_SEL_SHIFT 0x17
+#define CSID_VERSION 0x02000011
#endif
diff --git a/drivers/media/video/msm/csi/include/csi2.0/msm_csiphy_hwreg.h b/drivers/media/video/msm/csi/include/csi2.0/msm_csiphy_hwreg.h
index 93d1fc4..2e83101 100644
--- a/drivers/media/video/msm/csi/include/csi2.0/msm_csiphy_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi2.0/msm_csiphy_hwreg.h
@@ -28,6 +28,7 @@
#define MIPI_CSIPHY_LNCK_MISC1_ADDR 0x128
#define MIPI_CSIPHY_GLBL_RESET_ADDR 0x140
#define MIPI_CSIPHY_GLBL_PWR_CFG_ADDR 0x144
+#define MIPI_CSIPHY_GLBL_IRQ_CMD_ADDR 0x164
#define MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR 0x180
#define MIPI_CSIPHY_INTERRUPT_MASK0_ADDR 0x1A0
#define MIPI_CSIPHY_INTERRUPT_MASK_VAL 0x6F
@@ -37,5 +38,6 @@
#define MIPI_CSIPHY_MODE_CONFIG_SHIFT 0x4
#define MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR 0x1E0
#define MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR 0x1E8
+#define CSIPHY_VERSION 0x0
#endif
diff --git a/drivers/media/video/msm/csi/include/csi2.0/msm_ispif_hwreg.h b/drivers/media/video/msm/csi/include/csi2.0/msm_ispif_hwreg.h
index c678ea2..d37d67e 100644
--- a/drivers/media/video/msm/csi/include/csi2.0/msm_ispif_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi2.0/msm_ispif_hwreg.h
@@ -64,16 +64,25 @@
#define MISC_LOGIC_RST_STB 1
#define STROBED_RST_EN 0
+#define ISPIF_RST_CMD_MASK 0xFE0F1FFF
+#define ISPIF_RST_CMD_1_MASK 0xFC0F1FF9
+
#define PIX_INTF_0_OVERFLOW_IRQ 12
#define RAW_INTF_0_OVERFLOW_IRQ 25
#define RAW_INTF_1_OVERFLOW_IRQ 25
+#define RAW_INTF_2_OVERFLOW_IRQ 12
#define RESET_DONE_IRQ 27
-#define ISPIF_IRQ_STATUS_MASK 0xA493249
-#define ISPIF_IRQ_1_STATUS_MASK 0xA493249
-#define ISPIF_IRQ_STATUS_RDI_SOF_MASK 0x492000
-#define ISPIF_IRQ_STATUS_PIX_SOF_MASK 0x249
-#define ISPIF_IRQ_STATUS_SOF_MASK 0x492249
+#define ISPIF_IRQ_STATUS_MASK 0x0A493249
+#define ISPIF_IRQ_STATUS_1_MASK 0x02493249
+#define ISPIF_IRQ_STATUS_2_MASK 0x00001249
+
+#define ISPIF_IRQ_STATUS_PIX_SOF_MASK 0x249
+#define ISPIF_IRQ_STATUS_RDI0_SOF_MASK 0x492000
+#define ISPIF_IRQ_STATUS_RDI1_SOF_MASK 0x492000
+#define ISPIF_IRQ_STATUS_RDI2_SOF_MASK 0x249
+
+#define ISPIF_IRQ_STATUS_SOF_MASK 0x492249
#define ISPIF_IRQ_GLOBAL_CLEAR_CMD 0x1
#endif
diff --git a/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h b/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h
index 27d5a06..ca21238 100644
--- a/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi3.0/msm_csid_hwreg.h
@@ -47,5 +47,6 @@
#define CSID_RST_STB_ALL 0x7FFF
#define CSID_DL_INPUT_SEL_SHIFT 0x4
#define CSID_PHY_SEL_SHIFT 0x17
+#define CSID_VERSION 0x30000000
#endif
diff --git a/drivers/media/video/msm/csi/include/csi3.0/msm_csiphy_hwreg.h b/drivers/media/video/msm/csi/include/csi3.0/msm_csiphy_hwreg.h
index 79791bd..4e640e3 100644
--- a/drivers/media/video/msm/csi/include/csi3.0/msm_csiphy_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi3.0/msm_csiphy_hwreg.h
@@ -27,15 +27,17 @@
#define MIPI_CSIPHY_LNCK_MISC1_ADDR 0x128
#define MIPI_CSIPHY_GLBL_RESET_ADDR 0x140
#define MIPI_CSIPHY_GLBL_PWR_CFG_ADDR 0x144
+#define MIPI_CSIPHY_GLBL_IRQ_CMD_ADDR 0x164
#define MIPI_CSIPHY_HW_VERSION_ADDR 0x188
#define MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR 0x18C
#define MIPI_CSIPHY_INTERRUPT_MASK0_ADDR 0x1AC
#define MIPI_CSIPHY_INTERRUPT_MASK_VAL 0x3F
-#define MIPI_CSIPHY_INTERRUPT_MASK_ADDR 0x1B0
+#define MIPI_CSIPHY_INTERRUPT_MASK_ADDR 0x1AC
#define MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR 0x1CC
-#define MIPI_CSIPHY_INTERRUPT_CLEAR_ADDR 0x1D0
+#define MIPI_CSIPHY_INTERRUPT_CLEAR_ADDR 0x1CC
#define MIPI_CSIPHY_MODE_CONFIG_SHIFT 0x4
#define MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR 0x1EC
#define MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR 0x1F4
+#define CSIPHY_VERSION 0x10
#endif
diff --git a/drivers/media/video/msm/csi/include/csi3.0/msm_ispif_hwreg.h b/drivers/media/video/msm/csi/include/csi3.0/msm_ispif_hwreg.h
index 4b17538..7c09c4f 100644
--- a/drivers/media/video/msm/csi/include/csi3.0/msm_ispif_hwreg.h
+++ b/drivers/media/video/msm/csi/include/csi3.0/msm_ispif_hwreg.h
@@ -78,17 +78,25 @@
#define MISC_LOGIC_RST_STB 1
#define STROBED_RST_EN 0
+#define ISPIF_RST_CMD_MASK 0xFE0F1FFF
+#define ISPIF_RST_CMD_1_MASK 0xFC0F1FF9
+
#define PIX_INTF_0_OVERFLOW_IRQ 12
#define RAW_INTF_0_OVERFLOW_IRQ 25
#define RAW_INTF_1_OVERFLOW_IRQ 25
+#define RAW_INTF_2_OVERFLOW_IRQ 12
#define RESET_DONE_IRQ 27
-#define ISPIF_IRQ_STATUS_MASK 0xA493249
-#define ISPIF_IRQ_1_STATUS_MASK 0xA493249
-#define ISPIF_IRQ_STATUS_RDI_SOF_MASK 0x492000
-#define ISPIF_IRQ_STATUS_PIX_SOF_MASK 0x249
-#define ISPIF_IRQ_STATUS_SOF_MASK 0x492249
-#define ISPIF_IRQ_GLOBAL_CLEAR_CMD 0x1
+#define ISPIF_IRQ_STATUS_MASK 0x0A493249
+#define ISPIF_IRQ_STATUS_1_MASK 0x02493249
+#define ISPIF_IRQ_STATUS_2_MASK 0x00001249
+#define ISPIF_IRQ_STATUS_PIX_SOF_MASK 0x249
+#define ISPIF_IRQ_STATUS_RDI0_SOF_MASK 0x492000
+#define ISPIF_IRQ_STATUS_RDI1_SOF_MASK 0x492000
+#define ISPIF_IRQ_STATUS_RDI2_SOF_MASK 0x249
+
+#define ISPIF_IRQ_STATUS_SOF_MASK 0x492249
+#define ISPIF_IRQ_GLOBAL_CLEAR_CMD 0x1
#endif
diff --git a/drivers/media/video/msm/csi/msm_csic.c b/drivers/media/video/msm/csi/msm_csic.c
index bcb7bb3..c34d9f7 100644
--- a/drivers/media/video/msm/csi/msm_csic.c
+++ b/drivers/media/video/msm/csi/msm_csic.c
@@ -137,18 +137,17 @@
#define MIPI_PWR_CNTL_EN 0x07
#define MIPI_PWR_CNTL_DIS 0x0
-static int msm_csic_config(struct csic_cfg_params *cfg_params)
+static int msm_csic_config(struct v4l2_subdev *sd,
+ struct msm_camera_csi_params *csic_params)
{
int rc = 0;
uint32_t val = 0;
struct csic_device *csic_dev;
- struct msm_camera_csi_params *csic_params;
void __iomem *csicbase;
int i;
- csic_dev = v4l2_get_subdevdata(cfg_params->subdev);
+ csic_dev = v4l2_get_subdevdata(sd);
csicbase = csic_dev->base;
- csic_params = cfg_params->parms;
/* Enable error correction for DATA lane. Applies to all data lanes */
msm_camera_io_w(0x4, csicbase + MIPI_PHY_CONTROL);
@@ -259,7 +258,7 @@
{"csi_pclk", -1},
};
-static int msm_csic_init(struct v4l2_subdev *sd, uint32_t *csic_version)
+static int msm_csic_init(struct v4l2_subdev *sd)
{
int rc = 0;
struct csic_device *csic_dev;
@@ -355,17 +354,40 @@
return 0;
}
+static long msm_csic_cmd(struct v4l2_subdev *sd, void *arg)
+{
+ long rc = 0;
+ struct csic_cfg_data cdata;
+ struct msm_camera_csi_params csic_params;
+ if (copy_from_user(&cdata,
+ (void *)arg,
+ sizeof(struct csic_cfg_data)))
+ return -EFAULT;
+ CDBG("%s cfgtype = %d\n", __func__, cdata.cfgtype);
+ switch (cdata.cfgtype) {
+ case CSIC_INIT:
+ rc = msm_csic_init(sd);
+ break;
+ case CSIC_CFG:
+ if (copy_from_user(&csic_params,
+ (void *)cdata.csic_params,
+ sizeof(struct msm_camera_csi_params)))
+ return -EFAULT;
+ rc = msm_csic_config(sd, &csic_params);
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+ return rc;
+}
+
static long msm_csic_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int cmd, void *arg)
{
- struct csic_cfg_params cfg_params;
switch (cmd) {
case VIDIOC_MSM_CSIC_CFG:
- cfg_params.subdev = sd;
- cfg_params.parms = arg;
- return msm_csic_config((struct csic_cfg_params *)&cfg_params);
- case VIDIOC_MSM_CSIC_INIT:
- return msm_csic_init(sd, (uint32_t *)arg);
+ return msm_csic_cmd(sd, arg);
case VIDIOC_MSM_CSIC_RELEASE:
return msm_csic_release(sd);
default:
diff --git a/drivers/media/video/msm/csi/msm_csic.h b/drivers/media/video/msm/csi/msm_csic.h
index 177e9d1..c8f1f99 100644
--- a/drivers/media/video/msm/csi/msm_csic.h
+++ b/drivers/media/video/msm/csi/msm_csic.h
@@ -33,19 +33,10 @@
struct clk *csic_clk[5];
};
-struct csic_cfg_params {
- struct v4l2_subdev *subdev;
- void *parms;
-};
-
#define VIDIOC_MSM_CSIC_CFG \
- _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct csic_cfg_params)
-
-#define VIDIOC_MSM_CSIC_INIT \
- _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct v4l2_subdev*)
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct csic_cfg_data*)
#define VIDIOC_MSM_CSIC_RELEASE \
- _IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct v4l2_subdev*)
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct v4l2_subdev*)
#endif
-
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index 6ee87b7..7996ed1 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -11,8 +11,6 @@
*/
#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <mach/board.h>
@@ -21,11 +19,17 @@
#include "msm_csid.h"
#include "msm_csid_hwreg.h"
#include "msm.h"
+#include "msm_cam_server.h"
#define V4L2_IDENT_CSID 50002
+#define CSID_VERSION_V2 0x02000011
+#define CSID_VERSION_V3 0x30000000
#define DBG_CSID 0
+#define TRUE 1
+#define FALSE 0
+
static int msm_csid_cid_lut(
struct msm_camera_csid_lut_params *csid_lut_params,
void __iomem *csidbase)
@@ -33,7 +37,17 @@
int rc = 0, i = 0;
uint32_t val = 0;
+ if (!csid_lut_params) {
+ pr_err("%s:%d csid_lut_params NULL\n", __func__, __LINE__);
+ return -EINVAL;
+ }
for (i = 0; i < csid_lut_params->num_cid && i < 16; i++) {
+ CDBG("%s lut params num_cid = %d, cid = %d, dt = %x, df = %d\n",
+ __func__,
+ csid_lut_params->num_cid,
+ csid_lut_params->vc_cfg[i].cid,
+ csid_lut_params->vc_cfg[i].dt,
+ csid_lut_params->vc_cfg[i].decode_format);
if (csid_lut_params->vc_cfg[i].dt < 0x12 ||
csid_lut_params->vc_cfg[i].dt > 0x37) {
CDBG("%s: unsupported data type 0x%x\n",
@@ -68,19 +82,23 @@
struct msm_camera_csid_params *csid_params) {}
#endif
-static int msm_csid_config(struct csid_cfg_params *cfg_params)
+static int msm_csid_config(struct csid_device *csid_dev,
+ struct msm_camera_csid_params *csid_params)
{
int rc = 0;
uint32_t val = 0;
- struct csid_device *csid_dev;
- struct msm_camera_csid_params *csid_params;
void __iomem *csidbase;
- csid_dev = v4l2_get_subdevdata(cfg_params->subdev);
csidbase = csid_dev->base;
- if (csidbase == NULL)
- return -ENOMEM;
- csid_params = cfg_params->parms;
+ if (!csidbase || !csid_params) {
+ pr_err("%s:%d csidbase %p, csid params %p\n", __func__,
+ __LINE__, csidbase, csid_params);
+ return -EINVAL;
+ }
+ CDBG("%s csid_params, lane_cnt = %d, lane_assign = %x\n",
+ __func__,
+ csid_params->lane_cnt,
+ csid_params->lane_assign);
val = csid_params->lane_cnt - 1;
val |= csid_params->lane_assign << CSID_DL_INPUT_SEL_SHIFT;
if (csid_dev->hw_version < 0x30000000) {
@@ -98,7 +116,6 @@
return rc;
msm_csid_set_debug_reg(csidbase, csid_params);
-
return rc;
}
@@ -106,6 +123,10 @@
{
uint32_t irq;
struct csid_device *csid_dev = data;
+ if (!csid_dev) {
+ pr_err("%s:%d csid_dev NULL\n", __func__, __LINE__);
+ return IRQ_HANDLED;
+ }
irq = msm_camera_io_r(csid_dev->base + CSID_IRQ_STATUS_ADDR);
CDBG("%s CSID%d_IRQ_STATUS_ADDR = 0x%x\n",
__func__, csid_dev->pdev->id, irq);
@@ -115,6 +136,16 @@
return IRQ_HANDLED;
}
+int msm_csid_irq_routine(struct v4l2_subdev *sd, u32 status, bool *handled)
+{
+ struct csid_device *csid_dev = v4l2_get_subdevdata(sd);
+ irqreturn_t ret;
+ CDBG("%s E\n", __func__);
+ ret = msm_csid_irq(csid_dev->irq->start, csid_dev);
+ *handled = TRUE;
+ return 0;
+}
+
static void msm_csid_reset(struct csid_device *csid_dev)
{
msm_camera_io_w(CSID_RST_STB_ALL, csid_dev->base + CSID_RST_CMD_ADDR);
@@ -131,53 +162,95 @@
return 0;
}
-static struct msm_cam_clk_info csid_clk_info[] = {
+static struct msm_cam_clk_info csid_8960_clk_info[] = {
{"csi_src_clk", 177780000},
{"csi_clk", -1},
{"csi_phy_clk", -1},
{"csi_pclk", -1},
};
-static struct camera_vreg_t csid_vreg_info[] = {
+static struct msm_cam_clk_info csid_8974_clk_info[] = {
+ {"csi_ahb_clk", -1},
+ {"csi_src_clk", 200000000},
+ {"csi_clk", -1},
+ {"csi_phy_clk", -1},
+ {"csi_pix_clk", -1},
+ {"csi_rdi_clk", -1},
+};
+
+static struct camera_vreg_t csid_8960_vreg_info[] = {
{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
};
-static int msm_csid_init(struct v4l2_subdev *sd, uint32_t *csid_version)
+static struct camera_vreg_t csid_8974_vreg_info[] = {
+ {"mipi_csi_vdd", REG_LDO, 1800000, 1800000, 12000},
+};
+
+static int msm_csid_init(struct csid_device *csid_dev, uint32_t *csid_version)
{
int rc = 0;
- struct csid_device *csid_dev;
- csid_dev = v4l2_get_subdevdata(sd);
- if (csid_dev == NULL) {
- rc = -ENOMEM;
+
+ if (!csid_version) {
+ pr_err("%s:%d csid_version NULL\n", __func__, __LINE__);
+ rc = -EINVAL;
return rc;
}
-
csid_dev->base = ioremap(csid_dev->mem->start,
resource_size(csid_dev->mem));
if (!csid_dev->base) {
+ pr_err("%s csid_dev->base NULL\n", __func__);
rc = -ENOMEM;
return rc;
}
- rc = msm_camera_config_vreg(&csid_dev->pdev->dev, csid_vreg_info,
- ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 1);
- if (rc < 0) {
- pr_err("%s: regulator on failed\n", __func__);
- goto vreg_config_failed;
- }
+ if (CSID_VERSION <= CSID_VERSION_V2) {
+ 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);
+ if (rc < 0) {
+ pr_err("%s: regulator on failed\n", __func__);
+ goto vreg_config_failed;
+ }
- rc = msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
- ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 1);
- if (rc < 0) {
- pr_err("%s: regulator enable failed\n", __func__);
- goto vreg_enable_failed;
- }
+ rc = msm_camera_enable_vreg(&csid_dev->pdev->dev,
+ csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 1);
+ if (rc < 0) {
+ pr_err("%s: regulator enable failed\n", __func__);
+ goto vreg_enable_failed;
+ }
- rc = msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
- csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 1);
- if (rc < 0) {
- pr_err("%s: regulator enable failed\n", __func__);
- goto clk_enable_failed;
+ rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
+ csid_8960_clk_info, csid_dev->csid_clk,
+ ARRAY_SIZE(csid_8960_clk_info), 1);
+ if (rc < 0) {
+ pr_err("%s: regulator enable failed\n", __func__);
+ goto clk_enable_failed;
+ }
+ } else if (CSID_VERSION == CSID_VERSION_V3) {
+ rc = msm_camera_config_vreg(&csid_dev->pdev->dev,
+ csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 1);
+ if (rc < 0) {
+ pr_err("%s: regulator on failed\n", __func__);
+ goto vreg_config_failed;
+ }
+
+ rc = msm_camera_enable_vreg(&csid_dev->pdev->dev,
+ csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 1);
+ if (rc < 0) {
+ pr_err("%s: regulator enable failed\n", __func__);
+ goto vreg_enable_failed;
+ }
+
+ rc = msm_cam_clk_enable(&csid_dev->pdev->dev,
+ csid_8974_clk_info, csid_dev->csid_clk,
+ ARRAY_SIZE(csid_8974_clk_info), 1);
+ if (rc < 0) {
+ pr_err("%s: regulator enable failed\n", __func__);
+ goto clk_enable_failed;
+ }
}
csid_dev->hw_version =
@@ -186,68 +259,155 @@
init_completion(&csid_dev->reset_complete);
- rc = request_irq(csid_dev->irq->start, msm_csid_irq,
- IRQF_TRIGGER_RISING, "csid", csid_dev);
+ enable_irq(csid_dev->irq->start);
msm_csid_reset(csid_dev);
return rc;
clk_enable_failed:
- msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
- ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
+ if (CSID_VERSION <= CSID_VERSION_V2) {
+ msm_camera_enable_vreg(&csid_dev->pdev->dev,
+ csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+ } else if (CSID_VERSION == CSID_VERSION_V3) {
+ msm_camera_enable_vreg(&csid_dev->pdev->dev,
+ csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+ }
vreg_enable_failed:
- msm_camera_config_vreg(&csid_dev->pdev->dev, csid_vreg_info,
- ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
+ if (CSID_VERSION <= CSID_VERSION_V2) {
+ msm_camera_config_vreg(&csid_dev->pdev->dev,
+ csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+ } else if (CSID_VERSION == CSID_VERSION_V3) {
+ msm_camera_config_vreg(&csid_dev->pdev->dev,
+ csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+ }
vreg_config_failed:
iounmap(csid_dev->base);
csid_dev->base = NULL;
return rc;
}
-static int msm_csid_release(struct v4l2_subdev *sd)
+static int msm_csid_release(struct csid_device *csid_dev)
{
uint32_t irq;
- struct csid_device *csid_dev;
- csid_dev = v4l2_get_subdevdata(sd);
irq = msm_camera_io_r(csid_dev->base + CSID_IRQ_STATUS_ADDR);
msm_camera_io_w(irq, csid_dev->base + CSID_IRQ_CLEAR_CMD_ADDR);
msm_camera_io_w(0, csid_dev->base + CSID_IRQ_MASK_ADDR);
- free_irq(csid_dev->irq->start, csid_dev);
+ disable_irq(csid_dev->irq->start);
- msm_cam_clk_enable(&csid_dev->pdev->dev, csid_clk_info,
- csid_dev->csid_clk, ARRAY_SIZE(csid_clk_info), 0);
+ if (csid_dev->hw_version <= CSID_VERSION_V2) {
+ msm_cam_clk_enable(&csid_dev->pdev->dev, csid_8960_clk_info,
+ csid_dev->csid_clk, ARRAY_SIZE(csid_8960_clk_info), 0);
- msm_camera_enable_vreg(&csid_dev->pdev->dev, csid_vreg_info,
- ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
+ msm_camera_enable_vreg(&csid_dev->pdev->dev,
+ csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
- msm_camera_config_vreg(&csid_dev->pdev->dev, csid_vreg_info,
- ARRAY_SIZE(csid_vreg_info), &csid_dev->csi_vdd, 0);
+ msm_camera_config_vreg(&csid_dev->pdev->dev,
+ csid_8960_vreg_info, ARRAY_SIZE(csid_8960_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+ } else if (csid_dev->hw_version == CSID_VERSION_V3) {
+ msm_cam_clk_enable(&csid_dev->pdev->dev, csid_8974_clk_info,
+ csid_dev->csid_clk, ARRAY_SIZE(csid_8974_clk_info), 0);
+
+ msm_camera_enable_vreg(&csid_dev->pdev->dev,
+ csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+
+ msm_camera_config_vreg(&csid_dev->pdev->dev,
+ csid_8974_vreg_info, ARRAY_SIZE(csid_8974_vreg_info),
+ NULL, 0, &csid_dev->csi_vdd, 0);
+ }
iounmap(csid_dev->base);
csid_dev->base = NULL;
return 0;
}
+static long msm_csid_cmd(struct csid_device *csid_dev, void *arg)
+{
+ int rc = 0;
+ struct csid_cfg_data cdata;
+
+ if (!csid_dev) {
+ pr_err("%s:%d csid_dev NULL\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&cdata,
+ (void *)arg,
+ sizeof(struct csid_cfg_data))) {
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+ CDBG("%s cfgtype = %d\n", __func__, cdata.cfgtype);
+ switch (cdata.cfgtype) {
+ case CSID_INIT:
+ rc = msm_csid_init(csid_dev, &cdata.cfg.csid_version);
+ if (copy_to_user((void *)arg,
+ &cdata,
+ sizeof(struct csid_cfg_data))) {
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ }
+ break;
+ case CSID_CFG: {
+ struct msm_camera_csid_params csid_params;
+ struct msm_camera_csid_vc_cfg *vc_cfg = NULL;
+ if (copy_from_user(&csid_params,
+ (void *)cdata.cfg.csid_params,
+ sizeof(struct msm_camera_csid_params))) {
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+ vc_cfg = kzalloc(csid_params.lut_params.num_cid *
+ sizeof(struct msm_camera_csid_vc_cfg),
+ GFP_KERNEL);
+ if (!vc_cfg) {
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ rc = -ENOMEM;
+ break;
+ }
+ if (copy_from_user(vc_cfg,
+ (void *)csid_params.lut_params.vc_cfg,
+ (csid_params.lut_params.num_cid *
+ sizeof(struct msm_camera_csid_vc_cfg)))) {
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ kfree(vc_cfg);
+ rc = -EFAULT;
+ break;
+ }
+ csid_params.lut_params.vc_cfg = vc_cfg;
+ rc = msm_csid_config(csid_dev, &csid_params);
+ kfree(vc_cfg);
+ break;
+ }
+ default:
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ rc = -ENOIOCTLCMD;
+ break;
+ }
+ return rc;
+}
+
static long msm_csid_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int cmd, void *arg)
{
int rc = -ENOIOCTLCMD;
- struct csid_cfg_params cfg_params;
struct csid_device *csid_dev = v4l2_get_subdevdata(sd);
mutex_lock(&csid_dev->mutex);
switch (cmd) {
case VIDIOC_MSM_CSID_CFG:
- cfg_params.subdev = sd;
- cfg_params.parms = arg;
- rc = msm_csid_config((struct csid_cfg_params *)&cfg_params);
- break;
- case VIDIOC_MSM_CSID_INIT:
- rc = msm_csid_init(sd, (uint32_t *)arg);
+ rc = msm_csid_cmd(csid_dev, arg);
break;
case VIDIOC_MSM_CSID_RELEASE:
- rc = msm_csid_release(sd);
+ rc = msm_csid_release(csid_dev);
break;
default:
pr_err("%s: command not found\n", __func__);
@@ -261,6 +421,7 @@
static struct v4l2_subdev_core_ops msm_csid_subdev_core_ops = {
.g_chip_ident = &msm_csid_subdev_g_chip_ident,
.ioctl = &msm_csid_subdev_ioctl,
+ .interrupt_service_routine = msm_csid_irq_routine,
};
static const struct v4l2_subdev_ops msm_csid_subdev_ops = {
@@ -271,9 +432,10 @@
{
struct csid_device *new_csid_dev;
struct msm_cam_subdev_info sd_info;
+ struct intr_table_entry irq_req;
int rc = 0;
- CDBG("%s: device id = %d\n", __func__, pdev->id);
+ 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__);
@@ -293,6 +455,7 @@
of_property_read_u32((&pdev->dev)->of_node,
"cell-index", &pdev->id);
+ CDBG("%s device id %d\n", __func__, pdev->id);
new_csid_dev->mem = platform_get_resource_byname(pdev,
IORESOURCE_MEM, "csid");
if (!new_csid_dev->mem) {
@@ -327,6 +490,44 @@
new_csid_dev->subdev.entity.name = pdev->name;
new_csid_dev->subdev.entity.revision =
new_csid_dev->subdev.devnode->num;
+
+ /* Request for this device irq from the camera server. If the
+ * IRQ Router is present on this target, the interrupt will be
+ * handled by the camera server and the interrupt service
+ * routine called. If the request_irq call returns ENXIO, then
+ * the IRQ Router hardware is not present on this target. We
+ * have to request for the irq ourselves and register the
+ * appropriate interrupt handler. */
+ irq_req.cam_hw_idx = MSM_CAM_HW_CSI0 + pdev->id;
+ irq_req.dev_name = "csid";
+ irq_req.irq_idx = CAMERA_SS_IRQ_2 + pdev->id;
+ irq_req.irq_num = new_csid_dev->irq->start;
+ irq_req.is_composite = 0;
+ irq_req.irq_trigger_type = IRQF_TRIGGER_RISING;
+ irq_req.num_hwcore = 1;
+ irq_req.subdev_list[0] = &new_csid_dev->subdev;
+ irq_req.data = (void *)new_csid_dev;
+ rc = msm_cam_server_request_irq(&irq_req);
+ if (rc == -ENXIO) {
+ /* IRQ Router hardware is not present on this hardware.
+ * Request for the IRQ and register the interrupt handler. */
+ rc = request_irq(new_csid_dev->irq->start, msm_csid_irq,
+ IRQF_TRIGGER_RISING, "csid", new_csid_dev);
+ if (rc < 0) {
+ release_mem_region(new_csid_dev->mem->start,
+ resource_size(new_csid_dev->mem));
+ pr_err("%s: irq request fail\n", __func__);
+ rc = -EBUSY;
+ goto csid_no_resource;
+ }
+ disable_irq(new_csid_dev->irq->start);
+ } else if (rc < 0) {
+ release_mem_region(new_csid_dev->mem->start,
+ resource_size(new_csid_dev->mem));
+ pr_err("%s Error registering irq ", __func__);
+ goto csid_no_resource;
+ }
+
return 0;
csid_no_resource:
diff --git a/drivers/media/video/msm/csi/msm_csid.h b/drivers/media/video/msm/csi/msm_csid.h
index 2eae49c..398acbc 100644
--- a/drivers/media/video/msm/csi/msm_csid.h
+++ b/drivers/media/video/msm/csi/msm_csid.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. 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
@@ -16,6 +16,7 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <media/v4l2-subdev.h>
+#include <media/msm_camera.h>
struct csid_device {
struct platform_device *pdev;
@@ -32,19 +33,10 @@
struct clk *csid_clk[5];
};
-struct csid_cfg_params {
- struct v4l2_subdev *subdev;
- void *parms;
-};
-
#define VIDIOC_MSM_CSID_CFG \
- _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct csid_cfg_params)
-
-#define VIDIOC_MSM_CSID_INIT \
- _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct v4l2_subdev*)
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct csic_cfg_data*)
#define VIDIOC_MSM_CSID_RELEASE \
- _IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct v4l2_subdev*)
-
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct v4l2_subdev*)
#endif
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
index bec7ae3..3113295 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.c
+++ b/drivers/media/video/msm/csi/msm_csiphy.c
@@ -16,7 +16,6 @@
#include <linux/of.h>
#include <linux/module.h>
#include <mach/board.h>
-#include <mach/camera.h>
#include <mach/vreg.h>
#include <media/msm_isp.h>
#include "msm_csiphy.h"
@@ -27,31 +26,35 @@
#define V4L2_IDENT_CSIPHY 50003
#define CSIPHY_VERSION_V3 0x10
-int msm_csiphy_config(struct csiphy_cfg_params *cfg_params)
+int msm_csiphy_lane_config(struct csiphy_device *csiphy_dev,
+ struct msm_camera_csiphy_params *csiphy_params)
{
int rc = 0;
int j = 0;
uint32_t val = 0;
uint8_t lane_cnt = 0;
uint16_t lane_mask = 0;
- struct csiphy_device *csiphy_dev;
- struct msm_camera_csiphy_params *csiphy_params;
void __iomem *csiphybase;
- csiphy_dev = v4l2_get_subdevdata(cfg_params->subdev);
csiphybase = csiphy_dev->base;
- if (csiphybase == NULL)
- return -ENOMEM;
+ if (!csiphybase) {
+ pr_err("%s: csiphybase NULL\n", __func__);
+ return -EINVAL;
+ }
- csiphy_params = cfg_params->parms;
csiphy_dev->lane_mask[csiphy_dev->pdev->id] |= csiphy_params->lane_mask;
lane_mask = csiphy_dev->lane_mask[csiphy_dev->pdev->id];
lane_cnt = csiphy_params->lane_cnt;
if (csiphy_params->lane_cnt < 1 || csiphy_params->lane_cnt > 4) {
- CDBG("%s: unsupported lane cnt %d\n",
+ pr_err("%s: unsupported lane cnt %d\n",
__func__, csiphy_params->lane_cnt);
return rc;
}
+ CDBG("%s csiphy_params, mask = %x, cnt = %d, settle cnt = %x\n",
+ __func__,
+ csiphy_params->lane_mask,
+ csiphy_params->lane_cnt,
+ csiphy_params->settle_cnt);
msm_camera_io_w(0x1, csiphybase + MIPI_CSIPHY_GLBL_T_INIT_CFG0_ADDR);
msm_camera_io_w(0x1, csiphybase + MIPI_CSIPHY_T_WAKEUP_CFG0_ADDR);
@@ -75,6 +78,7 @@
csiphybase + MIPI_CSIPHY_GLBL_RESET_ADDR);
}
+ lane_mask &= 0x1f;
while (lane_mask & 0x1f) {
if (!(lane_mask & 0x1)) {
j++;
@@ -92,7 +96,7 @@
j++;
lane_mask >>= 1;
}
-
+ msleep(20);
return rc;
}
@@ -102,18 +106,23 @@
int i;
struct csiphy_device *csiphy_dev = data;
- for (i = 0; i < 5; i++) {
+ for (i = 0; i < 8; i++) {
irq = msm_camera_io_r(
csiphy_dev->base +
MIPI_CSIPHY_INTERRUPT_STATUS0_ADDR + 0x4*i);
msm_camera_io_w(irq,
csiphy_dev->base +
MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR + 0x4*i);
- CDBG("%s MIPI_CSIPHY%d_INTERRUPT_STATUS%d = 0x%x\n",
+ pr_err("%s MIPI_CSIPHY%d_INTERRUPT_STATUS%d = 0x%x\n",
__func__, csiphy_dev->pdev->id, i, irq);
+ msm_camera_io_w(0x1, csiphy_dev->base +
+ MIPI_CSIPHY_GLBL_IRQ_CMD_ADDR);
+ msm_camera_io_w(0x0, csiphy_dev->base +
+ MIPI_CSIPHY_GLBL_IRQ_CMD_ADDR);
+ msm_camera_io_w(0x0,
+ csiphy_dev->base +
+ MIPI_CSIPHY_INTERRUPT_CLEAR0_ADDR + 0x4*i);
}
- msm_camera_io_w(0x1, csiphy_dev->base + 0x164);
- msm_camera_io_w(0x0, csiphy_dev->base + 0x164);
return IRQ_HANDLED;
}
@@ -133,17 +142,22 @@
return 0;
}
-static struct msm_cam_clk_info csiphy_clk_info[] = {
+static struct msm_cam_clk_info csiphy_8960_clk_info[] = {
{"csiphy_timer_src_clk", 177780000},
{"csiphy_timer_clk", -1},
};
-static int msm_csiphy_init(struct v4l2_subdev *sd)
+static struct msm_cam_clk_info csiphy_8974_clk_info[] = {
+ {"ispif_ahb_clk", -1},
+ {"csiphy_timer_src_clk", 200000000},
+ {"csiphy_timer_clk", -1},
+};
+
+static int msm_csiphy_init(struct csiphy_device *csiphy_dev)
{
int rc = 0;
- struct csiphy_device *csiphy_dev;
- csiphy_dev = v4l2_get_subdevdata(sd);
if (csiphy_dev == NULL) {
+ pr_err("%s: csiphy_dev NULL\n", __func__);
rc = -ENOMEM;
return rc;
}
@@ -157,15 +171,23 @@
csiphy_dev->base = ioremap(csiphy_dev->mem->start,
resource_size(csiphy_dev->mem));
if (!csiphy_dev->base) {
+ pr_err("%s: csiphy_dev->base NULL\n", __func__);
csiphy_dev->ref_count--;
rc = -ENOMEM;
return rc;
}
- rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev, csiphy_clk_info,
- csiphy_dev->csiphy_clk, ARRAY_SIZE(csiphy_clk_info), 1);
+ if (CSIPHY_VERSION != CSIPHY_VERSION_V3)
+ rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+ csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
+ ARRAY_SIZE(csiphy_8960_clk_info), 1);
+ else
+ rc = msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+ csiphy_8974_clk_info, csiphy_dev->csiphy_clk,
+ ARRAY_SIZE(csiphy_8974_clk_info), 1);
if (rc < 0) {
+ pr_err("%s: csiphy clk enable failed\n", __func__);
csiphy_dev->ref_count--;
iounmap(csiphy_dev->base);
csiphy_dev->base = NULL;
@@ -183,13 +205,11 @@
return 0;
}
-static int msm_csiphy_release(struct v4l2_subdev *sd, void *arg)
+static int msm_csiphy_release(struct csiphy_device *csiphy_dev, void *arg)
{
- struct csiphy_device *csiphy_dev;
int i = 0;
struct msm_camera_csi_lane_params *csi_lane_params;
uint16_t csi_lane_mask;
- csiphy_dev = v4l2_get_subdevdata(sd);
csi_lane_params = (struct msm_camera_csi_lane_params *)arg;
csi_lane_mask = csi_lane_params->csi_lane_mask;
@@ -197,6 +217,10 @@
pr_err("%s csiphy dev NULL / ref_count ZERO\n", __func__);
return 0;
}
+ CDBG("%s csiphy_params, lane assign %x mask = %x\n",
+ __func__,
+ csi_lane_params->csi_lane_assign,
+ csi_lane_params->csi_lane_mask);
if (csiphy_dev->hw_version != CSIPHY_VERSION_V3) {
csiphy_dev->lane_mask[csiphy_dev->pdev->id] = 0;
@@ -229,33 +253,69 @@
#if DBG_CSIPHY
disable_irq(csiphy_dev->irq->start);
#endif
- msm_cam_clk_enable(&csiphy_dev->pdev->dev, csiphy_clk_info,
- csiphy_dev->csiphy_clk, ARRAY_SIZE(csiphy_clk_info), 0);
+ if (CSIPHY_VERSION != CSIPHY_VERSION_V3)
+ msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+ csiphy_8960_clk_info, csiphy_dev->csiphy_clk,
+ ARRAY_SIZE(csiphy_8960_clk_info), 0);
+ else
+ msm_cam_clk_enable(&csiphy_dev->pdev->dev,
+ csiphy_8974_clk_info, csiphy_dev->csiphy_clk,
+ ARRAY_SIZE(csiphy_8974_clk_info), 0);
iounmap(csiphy_dev->base);
csiphy_dev->base = NULL;
return 0;
}
+static long msm_csiphy_cmd(struct csiphy_device *csiphy_dev, void *arg)
+{
+ int rc = 0;
+ struct csiphy_cfg_data cdata;
+ struct msm_camera_csiphy_params csiphy_params;
+ if (!csiphy_dev) {
+ pr_err("%s: csiphy_dev NULL\n", __func__);
+ return -EINVAL;
+ }
+ if (copy_from_user(&cdata,
+ (void *)arg,
+ sizeof(struct csiphy_cfg_data))) {
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+ switch (cdata.cfgtype) {
+ case CSIPHY_INIT:
+ rc = msm_csiphy_init(csiphy_dev);
+ break;
+ case CSIPHY_CFG:
+ if (copy_from_user(&csiphy_params,
+ (void *)cdata.csiphy_params,
+ sizeof(struct msm_camera_csiphy_params))) {
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+ rc = msm_csiphy_lane_config(csiphy_dev, &csiphy_params);
+ break;
+ default:
+ pr_err("%s: %d failed\n", __func__, __LINE__);
+ rc = -ENOIOCTLCMD;
+ break;
+ }
+ return rc;
+}
+
static long msm_csiphy_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int cmd, void *arg)
{
int rc = -ENOIOCTLCMD;
- struct csiphy_cfg_params cfg_params;
struct csiphy_device *csiphy_dev = v4l2_get_subdevdata(sd);
mutex_lock(&csiphy_dev->mutex);
switch (cmd) {
case VIDIOC_MSM_CSIPHY_CFG:
- cfg_params.subdev = sd;
- cfg_params.parms = arg;
- rc = msm_csiphy_config(
- (struct csiphy_cfg_params *)&cfg_params);
- break;
- case VIDIOC_MSM_CSIPHY_INIT:
- rc = msm_csiphy_init(sd);
+ rc = msm_csiphy_cmd(csiphy_dev, arg);
break;
case VIDIOC_MSM_CSIPHY_RELEASE:
- rc = msm_csiphy_release(sd, arg);
+ rc = msm_csiphy_release(csiphy_dev, arg);
break;
default:
pr_err("%s: command not found\n", __func__);
@@ -281,7 +341,6 @@
int rc = 0;
struct msm_cam_subdev_info sd_info;
- CDBG("%s: device id = %d\n", __func__, pdev->id);
new_csiphy_dev = kzalloc(sizeof(struct csiphy_device), GFP_KERNEL);
if (!new_csiphy_dev) {
pr_err("%s: no enough memory\n", __func__);
@@ -301,6 +360,7 @@
if (pdev->dev.of_node)
of_property_read_u32((&pdev->dev)->of_node,
"cell-index", &pdev->id);
+ CDBG("%s: device id = %d\n", __func__, pdev->id);
new_csiphy_dev->mem = platform_get_resource_byname(pdev,
IORESOURCE_MEM, "csiphy");
diff --git a/drivers/media/video/msm/csi/msm_csiphy.h b/drivers/media/video/msm/csi/msm_csiphy.h
index 1fab9c1..4b2e68e 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.h
+++ b/drivers/media/video/msm/csi/msm_csiphy.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. 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
@@ -16,6 +16,7 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <media/v4l2-subdev.h>
+#include <media/msm_camera.h>
#define MAX_CSIPHY 3
@@ -29,23 +30,14 @@
struct mutex mutex;
uint32_t hw_version;
- struct clk *csiphy_clk[2];
+ struct clk *csiphy_clk[3];
uint8_t ref_count;
uint16_t lane_mask[MAX_CSIPHY];
};
-struct csiphy_cfg_params {
- struct v4l2_subdev *subdev;
- void *parms;
-};
-
#define VIDIOC_MSM_CSIPHY_CFG \
- _IOWR('V', BASE_VIDIOC_PRIVATE + 7, void *)
-
-#define VIDIOC_MSM_CSIPHY_INIT \
- _IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct v4l2_subdev*)
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct csiphy_cfg_data*)
#define VIDIOC_MSM_CSIPHY_RELEASE \
_IOWR('V', BASE_VIDIOC_PRIVATE + 9, void *)
-
#endif
diff --git a/drivers/media/video/msm/csi/msm_ispif.c b/drivers/media/video/msm/csi/msm_ispif.c
index 092ee90..ab97138 100644
--- a/drivers/media/video/msm/csi/msm_ispif.c
+++ b/drivers/media/video/msm/csi/msm_ispif.c
@@ -29,6 +29,7 @@
static atomic_t ispif_irq_cnt;
static spinlock_t ispif_tasklet_lock;
+static spinlock_t ispif_sof_lock;
static struct list_head ispif_tasklet_q;
static int msm_ispif_intf_reset(struct ispif_device *ispif,
@@ -36,7 +37,6 @@
{
int rc = 0;
uint32_t data = (0x1 << STROBED_RST_EN);
- uint32_t data1 = (0x1 << STROBED_RST_EN);
uint16_t intfnum = 0, mask = intfmask;
while (mask != 0) {
@@ -47,49 +47,29 @@
}
switch (intfnum) {
case PIX0:
- if (vfe_intf == VFE0)
- data |= (0x1 << PIX_0_VFE_RST_STB) |
- (0x1 << PIX_0_CSID_RST_STB);
- else
- data1 |= (0x1 << PIX_0_VFE_RST_STB) |
- (0x1 << PIX_0_CSID_RST_STB);
+ data |= (0x1 << PIX_0_VFE_RST_STB) |
+ (0x1 << PIX_0_CSID_RST_STB);
ispif->pix_sof_count = 0;
break;
case RDI0:
- if (vfe_intf == VFE0)
- data |= (0x1 << RDI_0_VFE_RST_STB) |
- (0x1 << RDI_0_CSID_RST_STB);
- else
- data1 |= (0x1 << RDI_0_VFE_RST_STB) |
- (0x1 << RDI_0_CSID_RST_STB);
+ data |= (0x1 << RDI_0_VFE_RST_STB) |
+ (0x1 << RDI_0_CSID_RST_STB);
break;
case PIX1:
- if (vfe_intf == VFE0)
- data |= (0x1 << PIX_1_VFE_RST_STB) |
- (0x1 << PIX_1_CSID_RST_STB);
- else
- data1 |= (0x1 << PIX_1_VFE_RST_STB) |
- (0x1 << PIX_1_CSID_RST_STB);
+ data |= (0x1 << PIX_1_VFE_RST_STB) |
+ (0x1 << PIX_1_CSID_RST_STB);
break;
case RDI1:
- if (vfe_intf == VFE0)
- data |= (0x1 << RDI_1_VFE_RST_STB) |
- (0x1 << RDI_1_CSID_RST_STB);
- else
- data1 |= (0x1 << RDI_1_VFE_RST_STB) |
- (0x1 << RDI_1_CSID_RST_STB);
+ data |= (0x1 << RDI_1_VFE_RST_STB) |
+ (0x1 << RDI_1_CSID_RST_STB);
break;
case RDI2:
- if (vfe_intf == VFE0)
- data |= (0x1 << RDI_2_VFE_RST_STB) |
- (0x1 << RDI_2_CSID_RST_STB);
- else
- data1 |= (0x1 << RDI_2_VFE_RST_STB) |
- (0x1 << RDI_2_CSID_RST_STB);
+ data |= (0x1 << RDI_2_VFE_RST_STB) |
+ (0x1 << RDI_2_CSID_RST_STB);
break;
default:
@@ -99,43 +79,26 @@
mask >>= 1;
intfnum++;
} /*end while */
- msm_camera_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
- rc = wait_for_completion_interruptible(&ispif->reset_complete);
- if (ispif->csid_version >= CSID_VERSION_V3 && data1 > 0x1) {
- msm_camera_io_w(data1,
- ispif->base + ISPIF_RST_CMD_1_ADDR);
- rc = wait_for_completion_interruptible(&ispif->
- reset_complete);
+ if (data > 0x1) {
+ 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);
+ rc = wait_for_completion_interruptible(&ispif->reset_complete);
}
-
return rc;
}
static int msm_ispif_reset(struct ispif_device *ispif)
{
int rc = 0;
- uint32_t data = (0x1 << STROBED_RST_EN) |
- (0x1 << SW_REG_RST_STB) |
- (0x1 << MISC_LOGIC_RST_STB) |
- (0x1 << PIX_0_VFE_RST_STB) |
- (0x1 << PIX_0_CSID_RST_STB) |
- (0x1 << RDI_0_VFE_RST_STB) |
- (0x1 << RDI_0_CSID_RST_STB) |
- (0x1 << RDI_1_VFE_RST_STB) |
- (0x1 << RDI_1_CSID_RST_STB);
-
- if (ispif->csid_version >= CSID_VERSION_V2)
- data |= (0x1 << PIX_1_VFE_RST_STB) |
- (0x1 << PIX_1_CSID_RST_STB) |
- (0x1 << RDI_2_VFE_RST_STB) |
- (0x1 << RDI_2_CSID_RST_STB);
ispif->pix_sof_count = 0;
- msm_camera_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
+ msm_camera_io_w(ISPIF_RST_CMD_MASK, ispif->base + ISPIF_RST_CMD_ADDR);
+ if (ispif->csid_version == CSID_VERSION_V3)
+ msm_camera_io_w(ISPIF_RST_CMD_1_MASK, ispif->base +
+ ISPIF_RST_CMD_1_ADDR);
rc = wait_for_completion_interruptible(&ispif->reset_complete);
- if (ispif->csid_version >= CSID_VERSION_V3) {
- msm_camera_io_w(data, ispif->base + ISPIF_RST_CMD_1_ADDR);
- rc = wait_for_completion_interruptible(&ispif->reset_complete);
- }
return rc;
}
@@ -154,35 +117,40 @@
int rc = 0;
uint32_t data;
- if (ispif->ispif_clk[intftype] == NULL) {
- pr_err("%s: ispif NULL clk\n", __func__);
- return;
+ if (ispif->csid_version <= CSID_VERSION_V2) {
+ if (ispif->ispif_clk[intftype] == NULL) {
+ pr_err("%s: ispif NULL clk\n", __func__);
+ return;
+ }
+ rc = clk_set_rate(ispif->ispif_clk[intftype], csid);
+ if (rc < 0)
+ pr_err("%s: clk_set_rate failed %d\n", __func__, rc);
}
-
- rc = clk_set_rate(ispif->ispif_clk[intftype], csid);
- if (rc < 0)
- pr_err("%s: clk_set_rate failed %d\n", __func__, rc);
-
data = msm_camera_io_r(ispif->base + ISPIF_INPUT_SEL_ADDR +
(0x200 * vfe_intf));
switch (intftype) {
case PIX0:
+ data &= ~(0x3);
data |= csid;
break;
case RDI0:
+ data &= ~(0x3 << 4);
data |= (csid << 4);
break;
case PIX1:
+ data &= ~(0x3 << 8);
data |= (csid << 8);
break;
case RDI1:
+ data &= ~(0x3 << 12);
data |= (csid << 12);
break;
case RDI2:
+ data &= ~(0x3 << 20);
data |= (csid << 20);
break;
}
@@ -289,6 +257,8 @@
ispif_params = params_list->params;
CDBG("Enable interface\n");
msm_camera_io_w(0x00000000, ispif->base + ISPIF_IRQ_MASK_ADDR);
+ msm_camera_io_w(0x00000000, ispif->base + ISPIF_IRQ_MASK_1_ADDR);
+ msm_camera_io_w(0x00000000, ispif->base + ISPIF_IRQ_MASK_2_ADDR);
for (i = 0; i < params_len; i++) {
intftype = ispif_params[i].intftype;
vfe_intf = ispif_params[i].vfe_intf;
@@ -319,6 +289,14 @@
ISPIF_IRQ_MASK_ADDR);
msm_camera_io_w(ISPIF_IRQ_STATUS_MASK, ispif->base +
ISPIF_IRQ_CLEAR_ADDR);
+ msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base +
+ ISPIF_IRQ_MASK_1_ADDR);
+ msm_camera_io_w(ISPIF_IRQ_STATUS_1_MASK, ispif->base +
+ ISPIF_IRQ_CLEAR_1_ADDR);
+ msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base +
+ ISPIF_IRQ_MASK_2_ADDR);
+ msm_camera_io_w(ISPIF_IRQ_STATUS_2_MASK, ispif->base +
+ ISPIF_IRQ_CLEAR_2_ADDR);
msm_camera_io_w(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
return rc;
@@ -534,13 +512,24 @@
return rc;
}
+static void send_rdi_sof(struct ispif_device *ispif,
+ enum msm_ispif_intftype interface, int count)
+{
+ struct rdi_count_msg sof_msg;
+ sof_msg.rdi_interface = interface;
+ sof_msg.count = count;
+ v4l2_subdev_notify(&ispif->subdev, NOTIFY_AXI_RDI_SOF_COUNT,
+ (void *)&sof_msg);
+}
+
static void ispif_do_tasklet(unsigned long data)
{
unsigned long flags;
struct ispif_isr_queue_cmd *qcmd = NULL;
- CDBG("=== ispif_do_tasklet start ===\n");
+ struct ispif_device *ispif;
+ ispif = (struct ispif_device *)data;
while (atomic_read(&ispif_irq_cnt)) {
spin_lock_irqsave(&ispif_tasklet_lock, flags);
qcmd = list_first_entry(&ispif_tasklet_q,
@@ -555,28 +544,37 @@
list_del(&qcmd->list);
spin_unlock_irqrestore(&ispif_tasklet_lock,
flags);
+
+ spin_lock_irqsave(&ispif_sof_lock, flags);
if (qcmd->ispifInterruptStatus0 &
- ISPIF_IRQ_STATUS_RDI_SOF_MASK) {
- CDBG("ispif rdi irq status\n");
+ ISPIF_IRQ_STATUS_RDI0_SOF_MASK) {
+ CDBG("%s: ispif RDI0 irq status", __func__);
+ ispif->rdi0_sof_count++;
+ send_rdi_sof(ispif, RDI_0, ispif->rdi0_sof_count);
}
if (qcmd->ispifInterruptStatus1 &
- ISPIF_IRQ_STATUS_RDI_SOF_MASK) {
- CDBG("ispif rdi1 irq status\n");
+ ISPIF_IRQ_STATUS_RDI1_SOF_MASK) {
+ CDBG("%s: ispif RDI1 irq status", __func__);
+ ispif->rdi1_sof_count++;
+ send_rdi_sof(ispif, RDI_1, ispif->rdi1_sof_count);
}
+ if (qcmd->ispifInterruptStatus2 &
+ ISPIF_IRQ_STATUS_RDI2_SOF_MASK) {
+ CDBG("%s: ispif RDI2 irq status", __func__);
+ ispif->rdi2_sof_count++;
+ send_rdi_sof(ispif, RDI_2, ispif->rdi2_sof_count);
+ }
+ spin_unlock_irqrestore(&ispif_sof_lock, flags);
kfree(qcmd);
}
- CDBG("=== ispif_do_tasklet end ===\n");
}
-DECLARE_TASKLET(ispif_tasklet, ispif_do_tasklet, 0);
-
static void ispif_process_irq(struct ispif_device *ispif,
struct ispif_irq_status *out)
{
unsigned long flags;
struct ispif_isr_queue_cmd *qcmd;
- CDBG("ispif_process_irq\n");
qcmd = kzalloc(sizeof(struct ispif_isr_queue_cmd),
GFP_ATOMIC);
if (!qcmd) {
@@ -585,12 +583,14 @@
}
qcmd->ispifInterruptStatus0 = out->ispifIrqStatus0;
qcmd->ispifInterruptStatus1 = out->ispifIrqStatus1;
-
- if (qcmd->ispifInterruptStatus0 & ISPIF_IRQ_STATUS_PIX_SOF_MASK) {
- CDBG("%s: ispif PIX sof irq\n", __func__);
- ispif->pix_sof_count++;
- v4l2_subdev_notify(&ispif->subdev, NOTIFY_VFE_SOF_COUNT,
- (void *)&ispif->pix_sof_count);
+ qcmd->ispifInterruptStatus2 = out->ispifIrqStatus2;
+ if (qcmd->ispifInterruptStatus0 &
+ ISPIF_IRQ_STATUS_PIX_SOF_MASK) {
+ CDBG("%s: ispif PIX irq status", __func__);
+ ispif->pix_sof_count++;
+ v4l2_subdev_notify(&ispif->subdev,
+ NOTIFY_VFE_PIX_SOF_COUNT,
+ (void *)&ispif->pix_sof_count);
}
spin_lock_irqsave(&ispif_tasklet_lock, flags);
@@ -598,25 +598,31 @@
atomic_add(1, &ispif_irq_cnt);
spin_unlock_irqrestore(&ispif_tasklet_lock, flags);
- tasklet_schedule(&ispif_tasklet);
+ tasklet_schedule(&ispif->ispif_tasklet);
return;
}
static inline void msm_ispif_read_irq_status(struct ispif_irq_status *out,
void *data)
{
+ uint32_t status0 = 0, status1 = 0, status2 = 0;
struct ispif_device *ispif = (struct ispif_device *)data;
out->ispifIrqStatus0 = msm_camera_io_r(ispif->base +
ISPIF_IRQ_STATUS_ADDR);
out->ispifIrqStatus1 = msm_camera_io_r(ispif->base +
ISPIF_IRQ_STATUS_1_ADDR);
+ out->ispifIrqStatus2 = msm_camera_io_r(ispif->base +
+ ISPIF_IRQ_STATUS_2_ADDR);
msm_camera_io_w(out->ispifIrqStatus0,
ispif->base + ISPIF_IRQ_CLEAR_ADDR);
msm_camera_io_w(out->ispifIrqStatus1,
ispif->base + ISPIF_IRQ_CLEAR_1_ADDR);
+ msm_camera_io_w(out->ispifIrqStatus2,
+ ispif->base + ISPIF_IRQ_CLEAR_2_ADDR);
- CDBG("%s: irq ispif->irq: Irq_status0 = 0x%x\n", __func__,
- out->ispifIrqStatus0);
+ CDBG("%s: irq vfe0 Irq_status0 = 0x%x, 1 = 0x%x, 2 = 0x%x\n",
+ __func__, out->ispifIrqStatus0, out->ispifIrqStatus1,
+ out->ispifIrqStatus2);
if (out->ispifIrqStatus0 & ISPIF_IRQ_STATUS_MASK) {
if (out->ispifIrqStatus0 & (0x1 << RESET_DONE_IRQ))
complete(&ispif->reset_complete);
@@ -624,11 +630,30 @@
pr_err("%s: pix intf 0 overflow.\n", __func__);
if (out->ispifIrqStatus0 & (0x1 << RAW_INTF_0_OVERFLOW_IRQ))
pr_err("%s: rdi intf 0 overflow.\n", __func__);
+ if (out->ispifIrqStatus1 & (0x1 << RAW_INTF_1_OVERFLOW_IRQ))
+ pr_err("%s: rdi intf 1 overflow.\n", __func__);
+ if (out->ispifIrqStatus2 & (0x1 << RAW_INTF_2_OVERFLOW_IRQ))
+ pr_err("%s: rdi intf 2 overflow.\n", __func__);
if ((out->ispifIrqStatus0 & ISPIF_IRQ_STATUS_SOF_MASK) ||
- (out->ispifIrqStatus1 &
- ISPIF_IRQ_STATUS_SOF_MASK)) {
+ (out->ispifIrqStatus1 & ISPIF_IRQ_STATUS_SOF_MASK) ||
+ (out->ispifIrqStatus2 & ISPIF_IRQ_STATUS_RDI2_SOF_MASK))
ispif_process_irq(ispif, out);
- }
+ }
+ if (ispif->csid_version == CSID_VERSION_V3) {
+ status0 = msm_camera_io_r(ispif->base +
+ ISPIF_IRQ_STATUS_ADDR + 0x200);
+ msm_camera_io_w(status0,
+ ispif->base + ISPIF_IRQ_CLEAR_ADDR + 0x200);
+ status1 = msm_camera_io_r(ispif->base +
+ ISPIF_IRQ_STATUS_1_ADDR + 0x200);
+ msm_camera_io_w(status1,
+ ispif->base + ISPIF_IRQ_CLEAR_1_ADDR + 0x200);
+ status2 = msm_camera_io_r(ispif->base +
+ ISPIF_IRQ_STATUS_2_ADDR + 0x200);
+ msm_camera_io_w(status2,
+ ispif->base + ISPIF_IRQ_CLEAR_2_ADDR + 0x200);
+ CDBG("%s: irq vfe1 Irq_status0 = 0x%x, 1 = 0x%x, 2 = 0x%x\n",
+ __func__, status0, status1, status2);
}
msm_camera_io_w(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
@@ -641,7 +666,7 @@
return IRQ_HANDLED;
}
-static struct msm_cam_clk_info ispif_clk_info[] = {
+static struct msm_cam_clk_info ispif_8960_clk_info[] = {
{"csi_pix_clk", 0},
{"csi_rdi_clk", 0},
{"csi_pix1_clk", 0},
@@ -660,15 +685,18 @@
IRQF_TRIGGER_RISING, "ispif", ispif);
init_completion(&ispif->reset_complete);
+ tasklet_init(&ispif->ispif_tasklet,
+ ispif_do_tasklet, (unsigned long)ispif);
+
ispif->csid_version = *csid_version;
- if (ispif->csid_version >= CSID_VERSION_V2) {
- rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
- ispif->ispif_clk, ARRAY_SIZE(ispif_clk_info), 1);
+ if (ispif->csid_version < CSID_VERSION_V2) {
+ rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+ ispif->ispif_clk, 2, 1);
if (rc < 0)
return rc;
- } else {
- rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
- ispif->ispif_clk, 2, 1);
+ } else if (ispif->csid_version == CSID_VERSION_V2) {
+ rc = msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+ ispif->ispif_clk, ARRAY_SIZE(ispif_8960_clk_info), 1);
if (rc < 0)
return rc;
}
@@ -679,15 +707,16 @@
static void msm_ispif_release(struct ispif_device *ispif)
{
CDBG("%s, free_irq\n", __func__);
- free_irq(ispif->irq->start, 0);
- tasklet_kill(&ispif_tasklet);
+ free_irq(ispif->irq->start, ispif);
+ tasklet_kill(&ispif->ispif_tasklet);
- if (ispif->csid_version == CSID_VERSION_V2)
- msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
- ispif->ispif_clk, ARRAY_SIZE(ispif_clk_info), 0);
- else
- msm_cam_clk_enable(&ispif->pdev->dev, ispif_clk_info,
+ if (ispif->csid_version < CSID_VERSION_V2) {
+ msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
ispif->ispif_clk, 2, 0);
+ } else if (ispif->csid_version == CSID_VERSION_V2) {
+ msm_cam_clk_enable(&ispif->pdev->dev, ispif_8960_clk_info,
+ ispif->ispif_clk, ARRAY_SIZE(ispif_8960_clk_info), 0);
+ }
}
static long msm_ispif_cmd(struct v4l2_subdev *sd, void *arg)
diff --git a/drivers/media/video/msm/csi/msm_ispif.h b/drivers/media/video/msm/csi/msm_ispif.h
index f4ad661..a581a37 100644
--- a/drivers/media/video/msm/csi/msm_ispif.h
+++ b/drivers/media/video/msm/csi/msm_ispif.h
@@ -20,6 +20,7 @@
struct ispif_irq_status {
uint32_t ispifIrqStatus0;
uint32_t ispifIrqStatus1;
+ uint32_t ispifIrqStatus2;
};
struct ispif_device {
@@ -35,12 +36,17 @@
uint32_t csid_version;
struct clk *ispif_clk[5];
uint32_t pix_sof_count;
+ uint32_t rdi0_sof_count;
+ uint32_t rdi1_sof_count;
+ uint32_t rdi2_sof_count;
+ struct tasklet_struct ispif_tasklet;
};
struct ispif_isr_queue_cmd {
struct list_head list;
uint32_t ispifInterruptStatus0;
uint32_t ispifInterruptStatus1;
+ uint32_t ispifInterruptStatus2;
};
#define VIDIOC_MSM_ISPIF_CFG \
diff --git a/drivers/media/video/msm/eeprom/imx074_eeprom.c b/drivers/media/video/msm/eeprom/imx074_eeprom.c
index 21cbafa..a99b17e 100644
--- a/drivers/media/video/msm/eeprom/imx074_eeprom.c
+++ b/drivers/media/video/msm/eeprom/imx074_eeprom.c
@@ -47,14 +47,15 @@
.core = &imx074_eeprom_subdev_core_ops,
};
-uint8_t imx074_wbcalib_data[6];
-struct msm_calib_wb imx074_wb_data;
+static uint8_t imx074_wbcalib_data[6];
+static struct msm_calib_wb imx074_wb_data;
static struct msm_camera_eeprom_info_t imx074_calib_supp_info = {
{FALSE, 0, 0, 1},
{TRUE, 6, 0, 1024},
{FALSE, 0, 0, 1},
{FALSE, 0, 0, 1},
+ {FALSE, 0, 0, 1},
};
static struct msm_camera_eeprom_read_t imx074_eeprom_read_tbl[] = {
diff --git a/drivers/media/video/msm/eeprom/imx091_eeprom.c b/drivers/media/video/msm/eeprom/imx091_eeprom.c
index 68a2361..c53eb20 100644
--- a/drivers/media/video/msm/eeprom/imx091_eeprom.c
+++ b/drivers/media/video/msm/eeprom/imx091_eeprom.c
@@ -47,16 +47,17 @@
.core = &imx091_eeprom_subdev_core_ops,
};
-uint8_t imx091_wbcalib_data[6];
-uint8_t imx091_afcalib_data[6];
-struct msm_calib_wb imx091_wb_data;
-struct msm_calib_af imx091_af_data;
+static uint8_t imx091_wbcalib_data[6];
+static uint8_t imx091_afcalib_data[6];
+static struct msm_calib_wb imx091_wb_data;
+static struct msm_calib_af imx091_af_data;
static struct msm_camera_eeprom_info_t imx091_calib_supp_info = {
{TRUE, 6, 1, 1},
{TRUE, 6, 0, 32768},
{FALSE, 0, 0, 1},
{FALSE, 0, 0, 1},
+ {FALSE, 0, 0, 1},
};
static struct msm_camera_eeprom_read_t imx091_eeprom_read_tbl[] = {
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.c b/drivers/media/video/msm/io/msm_camera_i2c.c
index 82bca02..27ebac5 100644
--- a/drivers/media/video/msm/io/msm_camera_i2c.c
+++ b/drivers/media/video/msm/io/msm_camera_i2c.c
@@ -84,6 +84,7 @@
cci_ctrl.cci_info = client->cci_client;
cci_ctrl.cfg.cci_i2c_write_cfg.reg_conf_tbl = ®_conf_tbl;
cci_ctrl.cfg.cci_i2c_write_cfg.data_type = data_type;
+ cci_ctrl.cfg.cci_i2c_write_cfg.addr_type = client->addr_type;
cci_ctrl.cfg.cci_i2c_write_cfg.size = 1;
rc = v4l2_subdev_call(client->cci_client->cci_subdev,
core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
@@ -336,6 +337,39 @@
return rc;
}
+int32_t msm_camera_i2c_write_bayer_table(
+ struct msm_camera_i2c_client *client,
+ struct msm_camera_i2c_reg_setting *write_setting)
+{
+ int i;
+ int32_t rc = -EFAULT;
+ struct msm_camera_i2c_reg_array *reg_setting;
+
+ if (!client || !write_setting)
+ return rc;
+
+ reg_setting = write_setting->reg_setting;
+ client->addr_type = write_setting->addr_type;
+ if ((write_setting->addr_type != MSM_CAMERA_I2C_BYTE_ADDR
+ && write_setting->addr_type != MSM_CAMERA_I2C_WORD_ADDR)
+ || (write_setting->data_type != MSM_CAMERA_I2C_BYTE_DATA
+ && write_setting->data_type != MSM_CAMERA_I2C_WORD_DATA))
+ return rc;
+ for (i = 0; i < write_setting->size; i++) {
+ rc = msm_camera_i2c_write(client, reg_setting->reg_addr,
+ reg_setting->reg_data, write_setting->data_type);
+ if (rc < 0)
+ break;
+ reg_setting++;
+ }
+ if (write_setting->delay > 20)
+ msleep(write_setting->delay);
+ else if (write_setting->delay)
+ usleep_range(write_setting->delay * 1000, (write_setting->delay
+ * 1000) + 1000);
+ return rc;
+}
+
int32_t msm_camera_i2c_write_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)
@@ -348,6 +382,7 @@
cci_ctrl.cci_info = client->cci_client;
cci_ctrl.cfg.cci_i2c_write_cfg.reg_conf_tbl = reg_conf_tbl;
cci_ctrl.cfg.cci_i2c_write_cfg.data_type = data_type;
+ cci_ctrl.cfg.cci_i2c_write_cfg.addr_type = client->addr_type;
cci_ctrl.cfg.cci_i2c_write_cfg.size = size;
rc = v4l2_subdev_call(client->cci_client->cci_subdev,
core, ioctl, VIDIOC_MSM_CCI_CFG, &cci_ctrl);
diff --git a/drivers/media/video/msm/io/msm_camera_i2c.h b/drivers/media/video/msm/io/msm_camera_i2c.h
index 169a0b3..35b3bd4 100644
--- a/drivers/media/video/msm/io/msm_camera_i2c.h
+++ b/drivers/media/video/msm/io/msm_camera_i2c.h
@@ -17,6 +17,7 @@
#include <linux/delay.h>
#include <mach/camera.h>
#include <media/v4l2-subdev.h>
+#include <media/msm_camera.h>
#define CONFIG_MSM_CAMERA_I2C_DBG 0
@@ -92,6 +93,10 @@
struct msm_camera_i2c_reg_tbl *reg_tbl, uint16_t size,
enum msm_camera_i2c_data_type data_type);
+int32_t msm_camera_i2c_write_bayer_table(
+ struct msm_camera_i2c_client *client,
+ struct msm_camera_i2c_reg_setting *write_setting);
+
int32_t msm_camera_i2c_write_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);
diff --git a/drivers/media/video/msm/io/msm_camera_io_util.c b/drivers/media/video/msm/io/msm_camera_io_util.c
index 4049266..613850b 100644
--- a/drivers/media/video/msm/io/msm_camera_io_util.c
+++ b/drivers/media/video/msm/io/msm_camera_io_util.c
@@ -20,6 +20,7 @@
#include <mach/gpiomux.h>
#define BUFF_SIZE_128 128
+static int gpio_ref_count;
void msm_camera_io_w(u32 data, void __iomem *addr)
{
@@ -133,6 +134,12 @@
clk_info[i].clk_name);
goto cam_clk_enable_err;
}
+ if (clk_info[i].delay > 20) {
+ msleep(clk_info[i].delay);
+ } else if (clk_info[i].delay) {
+ usleep_range(clk_info[i].delay * 1000,
+ (clk_info[i].delay * 1000) + 1000);
+ }
}
} else {
for (i = num_clk - 1; i >= 0; i--) {
@@ -163,26 +170,41 @@
}
int msm_camera_config_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
- int num_vreg, struct regulator **reg_ptr, int config)
+ int num_vreg, enum msm_camera_vreg_name_t *vreg_seq,
+ int num_vreg_seq, struct regulator **reg_ptr, int config)
{
- int i = 0;
+ int i = 0, j = 0;
int rc = 0;
struct camera_vreg_t *curr_vreg;
+
+ if (num_vreg_seq > num_vreg) {
+ pr_err("%s:%d vreg sequence invalid\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+ if (!num_vreg_seq)
+ num_vreg_seq = num_vreg;
+
if (config) {
- for (i = 0; i < num_vreg; i++) {
- curr_vreg = &cam_vreg[i];
- reg_ptr[i] = regulator_get(dev,
+ for (i = 0; i < num_vreg_seq; i++) {
+ if (vreg_seq) {
+ j = vreg_seq[i];
+ if (j >= num_vreg)
+ continue;
+ } else
+ j = i;
+ curr_vreg = &cam_vreg[j];
+ reg_ptr[j] = regulator_get(dev,
curr_vreg->reg_name);
- if (IS_ERR(reg_ptr[i])) {
+ if (IS_ERR(reg_ptr[j])) {
pr_err("%s: %s get failed\n",
__func__,
curr_vreg->reg_name);
- reg_ptr[i] = NULL;
+ reg_ptr[j] = NULL;
goto vreg_get_fail;
}
if (curr_vreg->type == REG_LDO) {
rc = regulator_set_voltage(
- reg_ptr[i],
+ reg_ptr[j],
curr_vreg->min_voltage,
curr_vreg->max_voltage);
if (rc < 0) {
@@ -193,7 +215,7 @@
}
if (curr_vreg->op_mode >= 0) {
rc = regulator_set_optimum_mode(
- reg_ptr[i],
+ reg_ptr[j],
curr_vreg->op_mode);
if (rc < 0) {
pr_err(
@@ -206,20 +228,26 @@
}
}
} else {
- for (i = num_vreg-1; i >= 0; i--) {
- curr_vreg = &cam_vreg[i];
- if (reg_ptr[i]) {
+ for (i = num_vreg_seq-1; i >= 0; i--) {
+ if (vreg_seq) {
+ j = vreg_seq[i];
+ if (j >= num_vreg)
+ continue;
+ } else
+ j = i;
+ curr_vreg = &cam_vreg[j];
+ if (reg_ptr[j]) {
if (curr_vreg->type == REG_LDO) {
if (curr_vreg->op_mode >= 0) {
regulator_set_optimum_mode(
- reg_ptr[i], 0);
+ reg_ptr[j], 0);
}
regulator_set_voltage(
- reg_ptr[i], 0, curr_vreg->
+ reg_ptr[j], 0, curr_vreg->
max_voltage);
}
- regulator_put(reg_ptr[i]);
- reg_ptr[i] = NULL;
+ regulator_put(reg_ptr[j]);
+ reg_ptr[j] = NULL;
}
}
}
@@ -227,52 +255,100 @@
vreg_unconfig:
if (curr_vreg->type == REG_LDO)
- regulator_set_optimum_mode(reg_ptr[i], 0);
+ regulator_set_optimum_mode(reg_ptr[j], 0);
vreg_set_opt_mode_fail:
if (curr_vreg->type == REG_LDO)
- regulator_set_voltage(reg_ptr[i], 0,
+ regulator_set_voltage(reg_ptr[j], 0,
curr_vreg->max_voltage);
vreg_set_voltage_fail:
- regulator_put(reg_ptr[i]);
- reg_ptr[i] = NULL;
+ regulator_put(reg_ptr[j]);
+ reg_ptr[j] = NULL;
vreg_get_fail:
for (i--; i >= 0; i--) {
- curr_vreg = &cam_vreg[i];
+ if (vreg_seq) {
+ j = vreg_seq[i];
+ if (j >= num_vreg)
+ continue;
+ } else
+ j = i;
+ curr_vreg = &cam_vreg[j];
goto vreg_unconfig;
}
return -ENODEV;
}
int msm_camera_enable_vreg(struct device *dev, struct camera_vreg_t *cam_vreg,
- int num_vreg, struct regulator **reg_ptr, int enable)
+ int num_vreg, enum msm_camera_vreg_name_t *vreg_seq,
+ int num_vreg_seq, struct regulator **reg_ptr, int enable)
{
- int i = 0, rc = 0;
+ int i = 0, j = 0, rc = 0;
+
+ if (num_vreg_seq > num_vreg) {
+ pr_err("%s:%d vreg sequence invalid\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+ if (!num_vreg_seq)
+ num_vreg_seq = num_vreg;
+
if (enable) {
- for (i = 0; i < num_vreg; i++) {
- if (IS_ERR(reg_ptr[i])) {
+ for (i = 0; i < num_vreg_seq; i++) {
+ if (vreg_seq) {
+ j = vreg_seq[i];
+ if (j >= num_vreg)
+ continue;
+ } else
+ j = i;
+ if (IS_ERR(reg_ptr[j])) {
pr_err("%s: %s null regulator\n",
- __func__, cam_vreg[i].reg_name);
+ __func__, cam_vreg[j].reg_name);
goto disable_vreg;
}
- rc = regulator_enable(reg_ptr[i]);
+ rc = regulator_enable(reg_ptr[j]);
if (rc < 0) {
pr_err("%s: %s enable failed\n",
- __func__, cam_vreg[i].reg_name);
+ __func__, cam_vreg[j].reg_name);
goto disable_vreg;
}
+ if (cam_vreg[j].delay > 20)
+ msleep(cam_vreg[j].delay);
+ else if (cam_vreg[j].delay)
+ usleep_range(cam_vreg[j].delay * 1000,
+ (cam_vreg[j].delay * 1000) + 1000);
}
} else {
- for (i = num_vreg-1; i >= 0; i--)
- regulator_disable(reg_ptr[i]);
+ for (i = num_vreg_seq-1; i >= 0; i--) {
+ if (vreg_seq) {
+ j = vreg_seq[i];
+ if (j >= num_vreg)
+ continue;
+ } else
+ j = i;
+ regulator_disable(reg_ptr[j]);
+ if (cam_vreg[j].delay > 20)
+ msleep(cam_vreg[j].delay);
+ else if (cam_vreg[j].delay)
+ usleep_range(cam_vreg[j].delay * 1000,
+ (cam_vreg[j].delay * 1000) + 1000);
+ }
}
return rc;
disable_vreg:
for (i--; i >= 0; i--) {
- regulator_disable(reg_ptr[i]);
- goto disable_vreg;
+ if (vreg_seq) {
+ j = vreg_seq[i];
+ if (j >= num_vreg)
+ continue;
+ } else
+ j = i;
+ regulator_disable(reg_ptr[j]);
+ if (cam_vreg[j].delay > 20)
+ msleep(cam_vreg[j].delay);
+ else if (cam_vreg[j].delay)
+ usleep_range(cam_vreg[j].delay * 1000,
+ (cam_vreg[j].delay * 1000) + 1000);
}
return rc;
}
@@ -319,7 +395,7 @@
config_gpio_table(gpio_conf);
if (gpio_en) {
- if (!gpio_conf->gpio_no_mux) {
+ if (!gpio_conf->gpio_no_mux && !gpio_ref_count) {
if (gpio_conf->cam_gpiomux_conf_tbl != NULL) {
msm_gpiomux_install(
(struct msm_gpiomux_config *)
@@ -334,6 +410,7 @@
return rc;
}
}
+ gpio_ref_count++;
if (gpio_conf->cam_gpio_req_tbl_size) {
rc = gpio_request_array(gpio_conf->cam_gpio_req_tbl,
gpio_conf->cam_gpio_req_tbl_size);
@@ -346,9 +423,10 @@
}
}
} else {
+ gpio_ref_count--;
gpio_free_array(gpio_conf->cam_gpio_req_tbl,
gpio_conf->cam_gpio_req_tbl_size);
- if (!gpio_conf->gpio_no_mux)
+ if (!gpio_conf->gpio_no_mux && !gpio_ref_count)
gpio_free_array(gpio_conf->cam_gpio_common_tbl,
gpio_conf->cam_gpio_common_tbl_size);
}
@@ -380,3 +458,39 @@
}
return rc;
}
+
+void msm_camera_bus_scale_cfg(uint32_t bus_perf_client,
+ enum msm_bus_perf_setting perf_setting)
+{
+ int rc = 0;
+ if (!bus_perf_client) {
+ pr_err("%s: Bus Client NOT Registered!!!\n", __func__);
+ return;
+ }
+
+ switch (perf_setting) {
+ case S_EXIT:
+ rc = msm_bus_scale_client_update_request(bus_perf_client, 1);
+ msm_bus_scale_unregister_client(bus_perf_client);
+ break;
+ case S_PREVIEW:
+ rc = msm_bus_scale_client_update_request(bus_perf_client, 1);
+ break;
+ case S_VIDEO:
+ rc = msm_bus_scale_client_update_request(bus_perf_client, 2);
+ break;
+ case S_CAPTURE:
+ rc = msm_bus_scale_client_update_request(bus_perf_client, 3);
+ break;
+ case S_ZSL:
+ rc = msm_bus_scale_client_update_request(bus_perf_client, 4);
+ break;
+ case S_LIVESHOT:
+ rc = msm_bus_scale_client_update_request(bus_perf_client, 5);
+ break;
+ case S_DEFAULT:
+ break;
+ default:
+ pr_warning("%s: INVALID CASE\n", __func__);
+ }
+}
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index e5c1091..98b2372 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -92,6 +92,20 @@
return rc;
}
+static int msm_camera_v4l2_private_general(struct file *f, void *pctx,
+ struct msm_camera_v4l2_ioctl_t *ioctl_ptr)
+{
+ int rc = 0;
+ struct msm_cam_v4l2_device *pcam = video_drvdata(f);
+
+ WARN_ON(pctx != f->private_data);
+
+ rc = msm_server_private_general(pcam, ioctl_ptr);
+ if (rc < 0)
+ pr_err("%s: Private command failed rc %d\n", __func__, rc);
+ return rc;
+}
+
static int msm_camera_v4l2_private_g_ctrl(struct file *f, void *pctx,
struct msm_camera_v4l2_ioctl_t *ioctl_ptr)
{
@@ -690,6 +704,16 @@
return OUTPUT_TYPE_R;
case MSM_V4L2_EXT_CAPTURE_MODE_RDI1:
return OUTPUT_TYPE_R1;
+ case MSM_V4L2_EXT_CAPTURE_MODE_AEC:
+ return OUTPUT_TYPE_SAEC;
+ case MSM_V4L2_EXT_CAPTURE_MODE_AF:
+ return OUTPUT_TYPE_SAFC;
+ case MSM_V4L2_EXT_CAPTURE_MODE_AWB:
+ return OUTPUT_TYPE_SAWB;
+ case MSM_V4L2_EXT_CAPTURE_MODE_IHIST:
+ return OUTPUT_TYPE_IHST;
+ case MSM_V4L2_EXT_CAPTURE_MODE_CSTA:
+ return OUTPUT_TYPE_CSTA;
case MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT:
case MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW:
default:
@@ -761,6 +785,7 @@
{
int rc = -EINVAL;
struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
+ struct msm_cam_v4l2_device *pcam = video_drvdata(file);
D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
switch (cmd) {
@@ -770,6 +795,47 @@
case MSM_CAM_V4L2_IOCTL_PRIVATE_G_CTRL:
rc = msm_camera_v4l2_private_g_ctrl(file, fh, ioctl_ptr);
break;
+ case MSM_CAM_V4L2_IOCTL_PRIVATE_GENERAL:
+ rc = msm_camera_v4l2_private_general(file, fh, ioctl_ptr);
+ break;
+ case MSM_CAM_V4L2_IOCTL_GET_EVENT_PAYLOAD: {
+ struct msm_queue_cmd *event_cmd;
+ void *payload;
+ mutex_lock(&pcam->event_lock);
+ event_cmd = msm_dequeue(&pcam->eventData_q, list_eventdata);
+ if (!event_cmd) {
+ pr_err("%s: No event payload\n", __func__);
+ rc = -EINVAL;
+ mutex_unlock(&pcam->event_lock);
+ return rc;
+ }
+ payload = event_cmd->command;
+ if (event_cmd->trans_code != ioctl_ptr->trans_code) {
+ pr_err("%s: Events don't match\n", __func__);
+ kfree(payload);
+ kfree(event_cmd);
+ rc = -EINVAL;
+ mutex_unlock(&pcam->event_lock);
+ break;
+ }
+ if (ioctl_ptr->len > 0) {
+ if (copy_to_user(ioctl_ptr->ioctl_ptr, payload,
+ ioctl_ptr->len)) {
+ pr_err("%s Copy to user failed for cmd %d",
+ __func__, cmd);
+ kfree(payload);
+ kfree(event_cmd);
+ rc = -EINVAL;
+ mutex_unlock(&pcam->event_lock);
+ break;
+ }
+ }
+ kfree(payload);
+ kfree(event_cmd);
+ mutex_unlock(&pcam->event_lock);
+ rc = 0;
+ break;
+ }
default:
pr_err("%s Unsupported ioctl cmd %d ", __func__, cmd);
break;
@@ -873,7 +939,6 @@
server_q_idx = msm_find_free_queue();
if (server_q_idx < 0)
return server_q_idx;
-
rc = msm_server_begin_session(pcam, server_q_idx);
if (rc < 0) {
pr_err("%s error starting server session ", __func__);
@@ -908,6 +973,8 @@
msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
pcam->pvdev);
+ mutex_init(&pcam->event_lock);
+ msm_queue_init(&pcam->eventData_q, "eventData");
}
pcam_inst->vbqueue_initialized = 0;
rc = 0;
@@ -930,6 +997,7 @@
return rc;
msm_send_open_server_failed:
+ msm_drain_eventq(&pcam->eventData_q);
msm_destroy_v4l2_event_queue(&pcam_inst->eventHandle);
if (pmctl->mctl_release)
@@ -1071,8 +1139,13 @@
D("%s index %d nodeid %d count %d\n", __func__, pcam_inst->my_index,
pcam->vnode_id, pcam->use_count);
pcam->dev_inst[pcam_inst->my_index] = NULL;
- if (pcam_inst->my_index == 0)
+ if (pcam_inst->my_index == 0) {
+ mutex_lock(&pcam->event_lock);
+ msm_drain_eventq(&pcam->eventData_q);
+ mutex_unlock(&pcam->event_lock);
+ mutex_destroy(&pcam->event_lock);
msm_destroy_v4l2_event_queue(&pcam_inst->eventHandle);
+ }
CLR_VIDEO_INST_IDX(pcam_inst->inst_handle);
CLR_IMG_MODE(pcam_inst->inst_handle);
@@ -1135,24 +1208,60 @@
unsigned int cmd, unsigned long evt)
{
struct v4l2_event v4l2_ev;
+ struct v4l2_event_and_payload evt_payload;
struct msm_cam_v4l2_device *pcam = NULL;
-
+ int rc = 0;
+ struct msm_queue_cmd *event_qcmd;
+ void *payload;
if (!mctl) {
pr_err("%s: mctl is NULL\n", __func__);
return -EINVAL;
}
- if (copy_from_user(&v4l2_ev, (void __user *)evt,
- sizeof(struct v4l2_event))) {
+ if (copy_from_user(&evt_payload, (void __user *)evt,
+ sizeof(struct v4l2_event_and_payload))) {
ERR_COPY_FROM_USER();
return -EFAULT;
}
+ v4l2_ev = evt_payload.evt;
v4l2_ev.id = 0;
pcam = mctl->pcam_ptr;
ktime_get_ts(&v4l2_ev.timestamp);
+ if (evt_payload.payload_length > 0 && evt_payload.payload != NULL) {
+ mutex_lock(&pcam->event_lock);
+ event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_KERNEL);
+ if (!event_qcmd) {
+ pr_err("%s Insufficient memory. return", __func__);
+ rc = -ENOMEM;
+ goto event_qcmd_alloc_fail;
+ }
+ payload = kzalloc(evt_payload.payload_length, GFP_KERNEL);
+ if (!payload) {
+ pr_err("%s Insufficient memory. return", __func__);
+ rc = -ENOMEM;
+ goto payload_alloc_fail;
+ }
+ if (copy_from_user(payload,
+ (void __user *)evt_payload.payload,
+ evt_payload.payload_length)) {
+ ERR_COPY_FROM_USER();
+ rc = -EFAULT;
+ goto copy_from_user_failed;
+ }
+ event_qcmd->command = payload;
+ event_qcmd->trans_code = evt_payload.transaction_id;
+ msm_enqueue(&pcam->eventData_q, &event_qcmd->list_eventdata);
+ mutex_unlock(&pcam->event_lock);
+ }
v4l2_event_queue(pcam->pvdev, &v4l2_ev);
- return 0;
+ return rc;
+copy_from_user_failed:
+ kfree(payload);
+payload_alloc_fail:
+ kfree(event_qcmd);
+event_qcmd_alloc_fail:
+ return rc;
}
@@ -1169,11 +1278,21 @@
{
int rc = -ENOMEM;
struct video_device *pvdev = NULL;
- struct i2c_client *client = v4l2_get_subdevdata(pcam->sensor_sdev);
+ struct i2c_client *client = NULL;
+ struct platform_device *pdev = NULL;
D("%s\n", __func__);
/* first register the v4l2 device */
- pcam->v4l2_dev.dev = &client->dev;
+ if (pcam->sensor_sdev->flags & V4L2_SUBDEV_FL_IS_I2C) {
+ client = v4l2_get_subdevdata(pcam->sensor_sdev);
+ pcam->v4l2_dev.dev = &client->dev;
+ pcam->media_dev.dev = &client->dev;
+ } else {
+ pdev = v4l2_get_subdevdata(pcam->sensor_sdev);
+ pcam->v4l2_dev.dev = &pdev->dev;
+ pcam->media_dev.dev = &pdev->dev;
+ }
+
rc = v4l2_device_register(pcam->v4l2_dev.dev, &pcam->v4l2_dev);
if (rc < 0)
return -EINVAL;
@@ -1190,7 +1309,6 @@
strlcpy(pcam->media_dev.model, QCAMERA_NAME,
sizeof(pcam->media_dev.model));
- pcam->media_dev.dev = &client->dev;
rc = media_device_register(&pcam->media_dev);
pvdev->v4l2_dev = &pcam->v4l2_dev;
pcam->v4l2_dev.mdev = &pcam->media_dev;
@@ -1249,7 +1367,7 @@
D("%s called\n", __func__);
- if (!actuator_info)
+ if (!actuator_info || !actuator_info->board_info)
goto probe_fail;
adapter = i2c_get_adapter(actuator_info->bus_id);
@@ -1292,7 +1410,7 @@
D("%s called\n", __func__);
- if (!eeprom_info)
+ if (!eeprom_info || !eeprom_info->board_info)
goto probe_fail;
adapter = i2c_get_adapter(eeprom_info->bus_id);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index a2c21bd..3dc0fe7 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -31,6 +31,7 @@
#include <media/videobuf2-msm-mem.h>
#include <media/msm_isp.h>
#include <mach/camera.h>
+#include <mach/iommu.h>
#include <media/msm_isp.h>
#include <linux/ion.h>
#include <linux/iommu.h>
@@ -140,6 +141,11 @@
uint32_t frameCounter;
};
+struct rdi_count_msg {
+ uint32_t rdi_interface;
+ uint32_t count;
+};
+
/* message id for v4l2_subdev_notify*/
enum msm_camera_v4l2_subdev_notify {
NOTIFY_ISP_MSG_EVT, /* arg = enum ISP_MESSAGE_ID */
@@ -148,11 +154,9 @@
NOTIFY_VFE_MSG_COMP_STATS, /* arg = struct msm_stats_buf */
NOTIFY_VFE_BUF_EVT, /* arg = struct msm_vfe_resp */
NOTIFY_VFE_CAMIF_ERROR,
- NOTIFY_VFE_SOF_COUNT, /*arg = int*/
+ NOTIFY_VFE_PIX_SOF_COUNT, /*arg = int*/
+ NOTIFY_AXI_RDI_SOF_COUNT, /*arg = struct rdi_count_msg*/
NOTIFY_PCLK_CHANGE, /* arg = pclk */
- NOTIFY_CSIPHY_CFG, /* arg = msm_camera_csiphy_params */
- NOTIFY_CSID_CFG, /* arg = msm_camera_csid_params */
- NOTIFY_CSIC_CFG, /* arg = msm_camera_csic_params */
NOTIFY_VFE_IRQ,
NOTIFY_AXI_IRQ,
NOTIFY_GESTURE_EVT, /* arg = v4l2_event */
@@ -201,10 +205,36 @@
enum v4l2_colorspace colorspace;
};
+struct msm_cam_return_frame_info {
+ int dirty;
+ int node_type;
+ struct timeval timestamp;
+};
+
+struct msm_cam_timestamp {
+ uint8_t present;
+ struct timeval timestamp;
+};
+
+struct msm_cam_buf_map_info {
+ int fd;
+ uint32_t data_offset;
+ unsigned long paddr;
+ unsigned long len;
+ struct file *file;
+ struct ion_handle *handle;
+};
+
+struct msm_cam_meta_frame {
+ struct msm_pp_frame frame;
+ /* Mapping information per plane */
+ struct msm_cam_buf_map_info map[VIDEO_MAX_PLANES];
+};
+
struct msm_mctl_pp_frame_info {
int user_cmd;
- struct msm_pp_frame src_frame;
- struct msm_pp_frame dest_frame;
+ struct msm_cam_meta_frame src_frame;
+ struct msm_cam_meta_frame dest_frame;
struct msm_mctl_pp_frame_cmd pp_frame_cmd;
struct msm_cam_media_controller *p_mctl;
};
@@ -242,6 +272,10 @@
int (*mctl_vbqueue_init)(struct msm_cam_v4l2_dev_inst *pcam,
struct vb2_queue *q, enum v4l2_buf_type type);
int (*mctl_ufmt_init)(struct msm_cam_media_controller *p_mctl);
+ int (*isp_config)(struct msm_cam_media_controller *pmctl,
+ unsigned int cmd, unsigned long arg);
+ int (*isp_notify)(struct msm_cam_media_controller *pmctl,
+ struct v4l2_subdev *sd, unsigned int notification, void *arg);
/* the following reflect the HW topology information*/
struct v4l2_subdev *sensor_sdev; /* sensor sub device */
@@ -253,10 +287,10 @@
struct v4l2_subdev *gemini_sdev; /* gemini sub device */
struct v4l2_subdev *vpe_sdev; /* vpe sub device */
struct v4l2_subdev *axi_sdev; /* axi sub device */
+ struct v4l2_subdev *vfe_sdev; /* vfe sub device */
struct v4l2_subdev *eeprom_sdev; /* eeprom sub device */
struct v4l2_subdev *cpp_sdev;/*cpp sub device*/
- struct msm_isp_ops *isp_sdev; /* isp sub device : camif/VFE */
struct msm_cam_config_dev *config_device;
/*mctl session control information*/
@@ -282,21 +316,10 @@
uint32_t ping_imem_cbcr;
uint32_t pong_imem_y;
uint32_t pong_imem_cbcr;
-};
-/* abstract camera device represents a VFE and connected sensor */
-struct msm_isp_ops {
- char *config_dev_name;
-
- int (*isp_config)(struct msm_cam_media_controller *pmctl,
- unsigned int cmd, unsigned long arg);
- int (*isp_notify)(struct v4l2_subdev *sd,
- unsigned int notification, void *arg);
- int (*isp_pp_cmd)(struct msm_cam_media_controller *pmctl,
- struct msm_mctl_pp_cmd, void *data);
-
- /* vfe subdevice */
- struct v4l2_subdev *sd;
+ /*IOMMU domain for this session*/
+ int domain_num;
+ struct iommu_domain *domain;
};
struct msm_isp_buf_info {
@@ -309,7 +332,7 @@
uint32_t data_offset;
};
-#define MSM_DEV_INST_MAX 16
+#define MSM_DEV_INST_MAX 24
struct msm_cam_v4l2_dev_inst {
struct v4l2_fh eventHandle;
struct vb2_queue vid_bufq;
@@ -373,6 +396,9 @@
struct v4l2_subdev *act_sdev; /* actuator sub device */
struct v4l2_subdev *eeprom_sdev; /* actuator sub device */
struct msm_camera_sensor_info *sdata;
+
+ struct msm_device_queue eventData_q; /*payload for events sent to app*/
+ struct mutex event_lock;
};
static inline struct msm_cam_v4l2_device *to_pcam(
@@ -396,6 +422,8 @@
struct msm_cam_media_controller *p_mctl;
struct msm_mem_map_info mem_map;
int dev_num;
+ int domain_num;
+ struct iommu_domain *domain;
};
struct msm_cam_subdev_info {
@@ -555,6 +583,10 @@
* dispatch the irq to the corresponding subdev. */
struct v4l2_subdev *subdev_table[MSM_CAM_HW_MAX];
struct msm_cam_server_irqmap_entry hw_irqmap[CAMERA_SS_IRQ_MAX];
+
+ /*IOMMU domain (Page table)*/
+ int domain_num;
+ struct iommu_domain *domain;
};
enum msm_cam_buf_lookup_type {
@@ -571,11 +603,13 @@
/* ISP related functions */
void msm_isp_vfe_dev_init(struct v4l2_subdev *vd);
+int msm_isp_config(struct msm_cam_media_controller *pmctl,
+ unsigned int cmd, unsigned long arg);
+int msm_isp_notify(struct msm_cam_media_controller *pmctl,
+ struct v4l2_subdev *sd, unsigned int notification, void *arg);
/*
int msm_isp_register(struct msm_cam_v4l2_device *pcam);
*/
-int msm_isp_register(struct msm_cam_server_dev *psvr);
-void msm_isp_unregister(struct msm_cam_server_dev *psvr);
int msm_sensor_register(struct v4l2_subdev *);
int msm_isp_init_module(int g_num_config_nodes);
@@ -589,7 +623,8 @@
uint32_t frame_id);
int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
struct msm_cam_buf_handle *buf_handle,
- struct msm_free_buf *frame, int dirty, int node_type);
+ struct msm_free_buf *frame,
+ struct msm_cam_return_frame_info *ret_frame);
int msm_mctl_reserve_free_buf(struct msm_cam_media_controller *pmctl,
struct msm_cam_v4l2_dev_inst *pcam_inst,
struct msm_cam_buf_handle *buf_handle,
@@ -599,9 +634,9 @@
struct msm_free_buf *free_buf);
/*Memory(PMEM) functions*/
int msm_register_pmem(struct hlist_head *ptype, void __user *arg,
- struct ion_client *client);
+ struct ion_client *client, int domain_num);
int msm_pmem_table_del(struct hlist_head *ptype, void __user *arg,
- struct ion_client *client);
+ struct ion_client *client, int domain_num);
int msm_pmem_region_get_phy_addr(struct hlist_head *ptype,
struct msm_mem_map_info *mem_map, int32_t *phyaddr);
uint8_t msm_pmem_region_lookup(struct hlist_head *ptype,
@@ -623,7 +658,7 @@
struct msm_vfe_cfg_cmd *cfgcmd, void *data);
int msm_vpe_subdev_init(struct v4l2_subdev *sd);
int msm_gemini_subdev_init(struct v4l2_subdev *gemini_sd);
-void msm_vpe_subdev_release(void);
+void msm_vpe_subdev_release(struct v4l2_subdev *sd);
void msm_gemini_subdev_release(struct v4l2_subdev *gemini_sd);
int msm_mctl_is_pp_msg_type(struct msm_cam_media_controller *p_mctl,
int msg_type);
@@ -670,6 +705,10 @@
struct msm_cam_buf_handle *buf_handle);
int msm_mctl_buf_return_buf(struct msm_cam_media_controller *pmctl,
int image_mode, struct msm_frame_buffer *buf);
+int msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
+ struct ion_client *client, int domain_num);
+int msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
+ struct ion_client *client, int domain_num);
int msm_mctl_pp_mctl_divert_done(struct msm_cam_media_controller *p_mctl,
void __user *arg);
void msm_release_ion_client(struct kref *ref);
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 3d94afd..83f762c 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -73,7 +73,7 @@
struct msm_camvfe_params vfe_params;
int rc;
- cfgcmd.cmd_type = CMD_VFE_SOF_COUNT_UPDATE;
+ cfgcmd.cmd_type = CMD_VFE_PIX_SOF_COUNT_UPDATE;
cfgcmd.value = NULL;
vfe_params.vfe_cfg = &cfgcmd;
vfe_params.data = arg;
@@ -156,15 +156,14 @@
return image_mode;
}
-static int msm_isp_notify_VFE_BUF_EVT(struct v4l2_subdev *sd, void *arg)
+static int msm_isp_notify_VFE_BUF_EVT(struct msm_cam_media_controller *pmctl,
+ struct v4l2_subdev *sd, void *arg)
{
int rc = -EINVAL;
struct msm_vfe_resp *vdata = (struct msm_vfe_resp *)arg;
struct msm_free_buf free_buf, temp_free_buf;
struct msm_camvfe_params vfe_params;
struct msm_vfe_cfg_cmd cfgcmd;
- struct msm_cam_media_controller *pmctl =
- (struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
struct msm_frame_info *frame_info =
(struct msm_frame_info *)vdata->evt_msg.data;
@@ -172,7 +171,7 @@
struct msm_cam_buf_handle buf_handle;
if (!pcam) {
- pr_debug("%s pcam is null. return\n", __func__);
+ pr_err("%s pcam is null. return\n", __func__);
msm_isp_sync_free(vdata);
return rc;
}
@@ -275,14 +274,12 @@
/*
* This function executes in interrupt context.
*/
-static int msm_isp_notify_vfe(struct v4l2_subdev *sd,
- unsigned int notification, void *arg)
+static int msm_isp_notify_vfe(struct msm_cam_media_controller *pmctl,
+ struct v4l2_subdev *sd, unsigned int notification, void *arg)
{
int rc = 0;
struct v4l2_event v4l2_evt;
struct msm_isp_event_ctrl *isp_event;
- struct msm_cam_media_controller *pmctl =
- (struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
struct msm_free_buf buf;
if (!pmctl) {
@@ -292,9 +289,9 @@
}
if (notification == NOTIFY_VFE_BUF_EVT)
- return msm_isp_notify_VFE_BUF_EVT(sd, arg);
+ return msm_isp_notify_VFE_BUF_EVT(pmctl, sd, arg);
- if (notification == NOTIFY_VFE_SOF_COUNT)
+ if (notification == NOTIFY_VFE_PIX_SOF_COUNT)
return msm_isp_notify_VFE_SOF_COUNT_EVT(sd, arg);
isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl), GFP_ATOMIC);
@@ -493,11 +490,12 @@
return rc;
}
-static int msm_isp_notify(struct v4l2_subdev *sd,
- unsigned int notification, void *arg)
+int msm_isp_notify(struct msm_cam_media_controller *pmctl,
+ struct v4l2_subdev *sd, unsigned int notification, void *arg)
{
- return msm_isp_notify_vfe(sd, notification, arg);
+ return msm_isp_notify_vfe(pmctl, sd, notification, arg);
}
+EXPORT_SYMBOL(msm_isp_notify);
static int msm_config_vfe(struct v4l2_subdev *sd,
struct msm_cam_media_controller *mctl, void __user *arg)
@@ -703,13 +701,13 @@
return rc;
}
/* config function simliar to origanl msm_ioctl_config*/
-static int msm_isp_config(struct msm_cam_media_controller *pmctl,
+int msm_isp_config(struct msm_cam_media_controller *pmctl,
unsigned int cmd, unsigned long arg)
{
int rc = -EINVAL;
void __user *argp = (void __user *)arg;
- struct v4l2_subdev *sd = pmctl->isp_sdev->sd;
+ struct v4l2_subdev *sd = pmctl->vfe_sdev;
D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
switch (cmd) {
@@ -742,47 +740,7 @@
return rc;
}
-
-static struct msm_isp_ops isp_subdev[MSM_MAX_CAMERA_CONFIGS];
-
-/**/
-int msm_isp_init_module(int g_num_config_nodes)
-{
- int i = 0;
-
- for (i = 0; i < g_num_config_nodes; i++) {
- isp_subdev[i].isp_config = msm_isp_config;
- isp_subdev[i].isp_notify = msm_isp_notify;
- }
- return 0;
-}
-EXPORT_SYMBOL(msm_isp_init_module);
-
-/*
-*/
-int msm_isp_register(struct msm_cam_server_dev *psvr)
-{
- int i = 0;
-
- D("%s\n", __func__);
-
- BUG_ON(!psvr);
-
- /* Initialize notify function for v4l2_dev */
- for (i = 0; i < psvr->config_info.num_config_nodes; i++)
- psvr->isp_subdev[i] = &(isp_subdev[i]);
-
- return 0;
-}
-EXPORT_SYMBOL(msm_isp_register);
-
-/**/
-void msm_isp_unregister(struct msm_cam_server_dev *psvr)
-{
- int i = 0;
- for (i = 0; i < psvr->config_info.num_config_nodes; i++)
- psvr->isp_subdev[i] = NULL;
-}
+EXPORT_SYMBOL(msm_isp_config);
int msm_isp_subdev_ioctl(struct v4l2_subdev *isp_subdev,
struct msm_vfe_cfg_cmd *cfgcmd, void *data)
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index d876f12..0711ca5 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -138,7 +138,38 @@
.pxlcode = V4L2_MBUS_FMT_YUYV8_2X8, /* YUV sensor */
.colorspace = V4L2_COLORSPACE_JPEG,
},
-
+ {
+ .name = "SAEC",
+ .depth = 16,
+ .bitsperpxl = 16,
+ .fourcc = V4L2_PIX_FMT_STATS_AE,
+ .pxlcode = V4L2_MBUS_FMT_SBGGR10_1X10, /* YUV sensor */
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ },
+ {
+ .name = "SAWB",
+ .depth = 16,
+ .bitsperpxl = 16,
+ .fourcc = V4L2_PIX_FMT_STATS_AWB,
+ .pxlcode = V4L2_MBUS_FMT_SBGGR10_1X10, /* YUV sensor */
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ },
+ {
+ .name = "SAFC",
+ .depth = 16,
+ .bitsperpxl = 16,
+ .fourcc = V4L2_PIX_FMT_STATS_AF,
+ .pxlcode = V4L2_MBUS_FMT_SBGGR10_1X10, /* YUV sensor */
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ },
+ {
+ .name = "SHST",
+ .depth = 16,
+ .bitsperpxl = 16,
+ .fourcc = V4L2_PIX_FMT_STATS_IHST,
+ .pxlcode = V4L2_MBUS_FMT_SBGGR10_1X10, /* YUV sensor */
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ },
};
static int msm_get_sensor_info(
@@ -422,17 +453,36 @@
rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
VIDIOC_MSM_AXI_CFG, (void __user *)arg);
else
- rc = p_mctl->isp_sdev->isp_config(p_mctl, cmd, arg);
+ rc = p_mctl->isp_config(p_mctl, cmd, arg);
break;
case MSM_CAM_IOCTL_ISPIF_IO_CFG:
rc = v4l2_subdev_call(p_mctl->ispif_sdev,
core, ioctl, VIDIOC_MSM_ISPIF_CFG, argp);
break;
+
+ case MSM_CAM_IOCTL_CSIPHY_IO_CFG:
+ if (p_mctl->csiphy_sdev)
+ rc = v4l2_subdev_call(p_mctl->csiphy_sdev,
+ core, ioctl, VIDIOC_MSM_CSIPHY_CFG, argp);
+ break;
+
+ case MSM_CAM_IOCTL_CSIC_IO_CFG:
+ if (p_mctl->csic_sdev)
+ rc = v4l2_subdev_call(p_mctl->csic_sdev,
+ core, ioctl, VIDIOC_MSM_CSIC_CFG, argp);
+ break;
+
+ case MSM_CAM_IOCTL_CSID_IO_CFG:
+ if (p_mctl->csid_sdev)
+ rc = v4l2_subdev_call(p_mctl->csid_sdev,
+ core, ioctl, VIDIOC_MSM_CSID_CFG, argp);
+ break;
+
default:
/* ISP config*/
D("%s:%d: go to default. Calling msm_isp_config\n",
__func__, __LINE__);
- rc = p_mctl->isp_sdev->isp_config(p_mctl, cmd, arg);
+ rc = p_mctl->isp_config(p_mctl, cmd, arg);
break;
}
D("%s: !!! cmd = %d, rc = %d\n",
@@ -459,7 +509,6 @@
/* open sub devices - once only*/
if (!p_mctl->opencnt) {
struct msm_sensor_csi_info csi_info;
- uint32_t csid_version = 0;
wake_lock(&p_mctl->wake_lock);
csid_core = camdev->csid_core;
@@ -485,39 +534,10 @@
goto act_power_up_failed;
}
- if (p_mctl->csiphy_sdev) {
- rc = v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
- VIDIOC_MSM_CSIPHY_INIT, NULL);
- if (rc < 0) {
- pr_err("%s: csiphy initialization failed %d\n",
- __func__, rc);
- goto csiphy_init_failed;
- }
- }
-
- if (p_mctl->csid_sdev) {
- rc = v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
- VIDIOC_MSM_CSID_INIT, &csid_version);
- if (rc < 0) {
- pr_err("%s: csid initialization failed %d\n",
- __func__, rc);
- goto csid_init_failed;
- }
- csi_info.is_csic = 0;
- }
-
- if (p_mctl->csic_sdev) {
- rc = v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
- VIDIOC_MSM_CSIC_INIT, &csid_version);
- if (rc < 0) {
- pr_err("%s: csic initialization failed %d\n",
- __func__, rc);
- goto csic_init_failed;
- }
+ if (p_mctl->csic_sdev)
csi_info.is_csic = 1;
- }
-
- csi_info.csid_version = csid_version;
+ else
+ csi_info.is_csic = 0;
rc = v4l2_subdev_call(p_mctl->sensor_sdev, core, ioctl,
VIDIOC_MSM_SENSOR_CSID_INFO, &csi_info);
if (rc < 0) {
@@ -540,26 +560,6 @@
return rc;
msm_csi_version:
- if (p_mctl->csic_sdev)
- if (v4l2_subdev_call(p_mctl->csic_sdev, core, ioctl,
- VIDIOC_MSM_CSIC_RELEASE, NULL) < 0)
- pr_err("%s: csic release failed %d\n", __func__, rc);
-csic_init_failed:
- if (p_mctl->csid_sdev)
- if (v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
- VIDIOC_MSM_CSID_RELEASE, NULL) < 0)
- pr_err("%s: csid release failed %d\n", __func__, rc);
-csid_init_failed:
- if (p_mctl->csiphy_sdev)
- if (v4l2_subdev_call(p_mctl->csiphy_sdev, core, ioctl,
- VIDIOC_MSM_CSIPHY_RELEASE,
- sinfo->sensor_platform_info->csi_lane_params) < 0)
- pr_err("%s: csiphy release failed %d\n", __func__, rc);
-csiphy_init_failed:
- if (p_mctl->act_sdev)
- if (v4l2_subdev_call(p_mctl->act_sdev, core,
- s_power, 0) < 0)
- pr_err("%s: act power down failed:%d\n", __func__, rc);
act_power_up_failed:
if (v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 0) < 0)
pr_err("%s: sensor powerdown failed: %d\n", __func__, rc);
@@ -707,6 +707,9 @@
pmctl->mctl_open = msm_mctl_open;
pmctl->mctl_cmd = msm_mctl_cmd;
pmctl->mctl_release = msm_mctl_release;
+ pmctl->isp_config = msm_isp_config;
+ pmctl->isp_notify = msm_isp_notify;
+
/* init mctl buf */
msm_mctl_buf_init(pcam);
memset(&pmctl->pp_info, 0, sizeof(pmctl->pp_info));
@@ -1598,12 +1601,20 @@
{
int rc = -EINVAL;
struct video_device *pvdev = NULL;
- struct i2c_client *client = v4l2_get_subdevdata(pcam->sensor_sdev);
-
+ struct i2c_client *client = NULL;
+ struct platform_device *pdev = NULL;
D("%s\n", __func__);
/* first register the v4l2 device */
- pcam->mctl_node.v4l2_dev.dev = &client->dev;
+ if (pcam->sensor_sdev->flags & V4L2_SUBDEV_FL_IS_I2C) {
+ client = v4l2_get_subdevdata(pcam->sensor_sdev);
+ pcam->mctl_node.v4l2_dev.dev = &client->dev;
+ } else {
+ pdev = v4l2_get_subdevdata(pcam->sensor_sdev);
+ pcam->mctl_node.v4l2_dev.dev = &pdev->dev;
+ }
+
+ /* first register the v4l2 device */
rc = v4l2_device_register(pcam->mctl_node.v4l2_dev.dev,
&pcam->mctl_node.v4l2_dev);
if (rc < 0)
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 9f7f689..953f042 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -130,7 +130,8 @@
rc = videobuf2_pmem_contig_user_get(mem, &offset,
buf_type,
pcam_inst->buf_offset[buf_idx][i].addr_offset,
- pcam_inst->path, pmctl->client);
+ pcam_inst->path, pmctl->client,
+ pmctl->domain_num);
else
rc = videobuf2_pmem_contig_mmap_get(mem, &offset,
buf_type, pcam_inst->path);
@@ -265,7 +266,8 @@
}
for (i = 0; i < vb->num_planes; i++) {
mem = vb2_plane_cookie(vb, i);
- videobuf2_pmem_contig_user_put(mem, pmctl->client);
+ videobuf2_pmem_contig_user_put(mem, pmctl->client,
+ pmctl->domain_num);
}
buf->state = MSM_BUFFER_STATE_UNUSED;
}
@@ -411,7 +413,8 @@
struct msm_cam_media_controller *pmctl,
struct msm_cam_v4l2_dev_inst *pcam_inst,
struct msm_free_buf *fbuf,
- uint32_t *frame_id, int gen_timestamp)
+ uint32_t *frame_id,
+ struct msm_cam_timestamp *cam_ts)
{
struct msm_frame_buffer *buf = NULL;
int del_buf = 1;
@@ -422,11 +425,15 @@
__func__, fbuf->ch_paddr[0]);
return -EINVAL;
}
- if (gen_timestamp) {
+ if (!cam_ts->present) {
if (frame_id)
buf->vidbuf.v4l2_buf.sequence = *frame_id;
msm_mctl_gettimeofday(
&buf->vidbuf.v4l2_buf.timestamp);
+ } else {
+ D("%s Copying timestamp as %ld.%ld", __func__,
+ cam_ts->timestamp.tv_sec, cam_ts->timestamp.tv_usec);
+ buf->vidbuf.v4l2_buf.timestamp = cam_ts->timestamp;
}
vb2_buffer_done(&buf->vidbuf, VB2_BUF_STATE_DONE);
return 0;
@@ -442,6 +449,7 @@
int idx, rc;
int pp_divert_type = 0, pp_type = 0;
uint32_t image_mode;
+ struct msm_cam_timestamp cam_ts;
if (!p_mctl || !buf_handle || !fbuf) {
pr_err("%s Invalid argument. ", __func__);
@@ -507,8 +515,9 @@
__func__);
return -EINVAL;
}
+ memset(&cam_ts, 0, sizeof(cam_ts));
rc = msm_mctl_buf_done_proc(p_mctl, pcam_inst,
- fbuf, &frame_id, 1);
+ fbuf, &frame_id, &cam_ts);
}
return rc;
}
@@ -752,12 +761,14 @@
int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
struct msm_cam_buf_handle *buf_handle,
- struct msm_free_buf *frame, int dirty, int node_type)
+ struct msm_free_buf *frame,
+ struct msm_cam_return_frame_info *ret_frame)
{
struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
int rc = 0, idx;
+ struct msm_cam_timestamp cam_ts;
- if (!pmctl || !buf_handle) {
+ if (!pmctl || !buf_handle || !ret_frame) {
pr_err("%s Invalid argument ", __func__);
return -EINVAL;
}
@@ -773,13 +784,13 @@
}
} else if (buf_handle->buf_lookup_type == BUF_LOOKUP_BY_IMG_MODE) {
idx = msm_mctl_img_mode_to_inst_index(pmctl,
- buf_handle->image_mode, node_type);
+ buf_handle->image_mode, ret_frame->node_type);
if (idx < 0) {
pr_err("%s Invalid instance, buffer not released\n",
__func__);
return idx;
}
- if (node_type)
+ if (ret_frame->node_type)
pcam_inst = pmctl->pcam_ptr->mctl_node.dev_inst[idx];
else
pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
@@ -791,12 +802,15 @@
}
D("%s:inst=0x%p, paddr=0x%x, dirty=%d",
- __func__, pcam_inst, frame->ch_paddr[0], dirty);
- if (dirty)
+ __func__, pcam_inst, frame->ch_paddr[0], ret_frame->dirty);
+ cam_ts.present = 1;
+ cam_ts.timestamp = ret_frame->timestamp;
+ if (ret_frame->dirty)
/* the frame is dirty, not going to disptach to app */
rc = msm_mctl_release_free_buf(pmctl, pcam_inst, frame);
else
- rc = msm_mctl_buf_done_proc(pmctl, pcam_inst, frame, NULL, 0);
+ rc = msm_mctl_buf_done_proc(pmctl, pcam_inst, frame,
+ NULL, &cam_ts);
return rc;
}
@@ -840,3 +854,199 @@
spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
return -EINVAL;
}
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+/* Unmap using ION APIs */
+static void __msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
+ struct ion_client *client, int domain_num)
+{
+ int i = 0;
+ for (i = 0; i < meta_frame->frame.num_planes; i++) {
+ D("%s Plane %d handle %p", __func__, i,
+ meta_frame->map[i].handle);
+ ion_unmap_iommu(client, meta_frame->map[i].handle,
+ domain_num, 0);
+ ion_free(client, meta_frame->map[i].handle);
+ }
+}
+
+/* Map using ION APIs */
+static int __msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
+ struct ion_client *client, int domain_num)
+{
+ unsigned long paddr = 0;
+ unsigned long len = 0;
+ int i = 0, j = 0;
+
+ for (i = 0; i < meta_frame->frame.num_planes; i++) {
+ meta_frame->map[i].handle = ion_import_dma_buf(client,
+ meta_frame->frame.mp[i].fd);
+ if (IS_ERR_OR_NULL(meta_frame->map[i].handle)) {
+ pr_err("%s: ion_import failed for plane = %d fd = %d",
+ __func__, i, meta_frame->frame.mp[i].fd);
+ /* Roll back previous plane mappings, if any */
+ for (j = i-1; j >= 0; j--) {
+ ion_unmap_iommu(client,
+ meta_frame->map[j].handle,
+ domain_num, 0);
+ ion_free(client, meta_frame->map[j].handle);
+ }
+ return -EACCES;
+ }
+ D("%s Mapping fd %d plane %d handle %p", __func__,
+ meta_frame->frame.mp[i].fd, i,
+ meta_frame->map[i].handle);
+ if (ion_map_iommu(client, meta_frame->map[i].handle,
+ domain_num, 0, SZ_4K,
+ 0, &paddr, &len, UNCACHED, 0) < 0) {
+ pr_err("%s: cannot map address plane %d", __func__, i);
+ ion_free(client, meta_frame->map[i].handle);
+ /* Roll back previous plane mappings, if any */
+ for (j = i-1; j >= 0; j--) {
+ if (meta_frame->map[j].handle) {
+ ion_unmap_iommu(client,
+ meta_frame->map[j].handle,
+ domain_num, 0);
+ ion_free(client,
+ meta_frame->map[j].handle);
+ }
+ }
+ return -EFAULT;
+ }
+
+ /* Validate the offsets with the mapped length. */
+ if ((meta_frame->frame.mp[i].addr_offset > len) ||
+ (meta_frame->frame.mp[i].data_offset +
+ meta_frame->frame.mp[i].length > len)) {
+ pr_err("%s: Invalid offsets A %d D %d L %d len %ld",
+ __func__, meta_frame->frame.mp[i].addr_offset,
+ meta_frame->frame.mp[i].data_offset,
+ meta_frame->frame.mp[i].length, len);
+ /* Roll back previous plane mappings, if any */
+ for (j = i; j >= 0; j--) {
+ if (meta_frame->map[j].handle) {
+ ion_unmap_iommu(client,
+ meta_frame->map[j].handle,
+ domain_num, 0);
+ ion_free(client,
+ meta_frame->map[j].handle);
+ }
+ }
+ return -EINVAL;
+ }
+ meta_frame->map[i].data_offset =
+ meta_frame->frame.mp[i].data_offset;
+ /* Add the addr_offset to the paddr here itself. The addr_offset
+ * will be non-zero only if the user has allocated a buffer with
+ * a single fd, but logically partitioned it into
+ * multiple planes or buffers.*/
+ paddr += meta_frame->frame.mp[i].addr_offset;
+ meta_frame->map[i].paddr = paddr;
+ meta_frame->map[i].len = len;
+ D("%s Plane %d fd %d handle %p paddr %x", __func__,
+ i, meta_frame->frame.mp[i].fd,
+ meta_frame->map[i].handle,
+ (uint32_t)meta_frame->map[i].paddr);
+ }
+ D("%s Frame mapped successfully ", __func__);
+ return 0;
+}
+#else
+/* Unmap using PMEM APIs */
+static int __msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
+ struct ion_client *client, int domain_num)
+{
+ int i = 0, rc = 0;
+
+ for (i = 0; i < meta_frame->frame.num_planes; i++) {
+ D("%s Plane %d handle %p", __func__, i,
+ meta_frame->map[i].handle);
+ put_pmem_file(meta_frame->map[i].file);
+ }
+}
+
+/* Map using PMEM APIs */
+static int __msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
+ struct ion_client *client, int domain_num)
+{
+ unsigned long kvstart = 0;
+ unsigned long paddr = 0;
+ struct file *file = NULL;
+ unsigned long len;
+ int i = 0, j = 0;
+
+ for (i = 0; i < meta_frame->frame.num_planes; i++) {
+ rc = get_pmem_file(meta_frame->frame.mp[i].fd,
+ &paddr, &kvstart, &len, &file);
+ if (rc < 0) {
+ pr_err("%s: get_pmem_file fd %d error %d\n",
+ __func__, meta_frame->frame.mp[i].fd, rc);
+ /* Roll back previous plane mappings, if any */
+ for (j = i-1; j >= 0; j--)
+ if (meta_frame->map[j].file)
+ put_pmem_file(meta_frame->map[j].file);
+
+ return -EACCES;
+ }
+ D("%s Got pmem file for fd %d plane %d as %p", __func__,
+ meta_frame->frame.mp[i].fd, i, file);
+ meta_frame->map[i].file = file;
+ /* Validate the offsets with the mapped length. */
+ if ((meta_frame->frame.mp[i].addr_offset > len) ||
+ (meta_frame->frame.mp[i].data_offset +
+ meta_frame->frame.mp[i].length > len)) {
+ pr_err("%s: Invalid offsets A %d D %d L %d len %ld",
+ __func__, meta_frame->frame.mp[i].addr_offset,
+ meta_frame->frame.mp[i].data_offset,
+ meta_frame->frame.mp[i].length, len);
+ /* Roll back previous plane mappings, if any */
+ for (j = i; j >= 0; j--)
+ if (meta_frame->map[j].file)
+ put_pmem_file(meta_frame->map[j].file);
+
+ return -EINVAL;
+ }
+ meta_frame->map[i].data_offset =
+ meta_frame->frame.mp[i].data_offset;
+ /* Add the addr_offset to the paddr here itself. The addr_offset
+ * will be non-zero only if the user has allocated a buffer with
+ * a single fd, but logically partitioned it into
+ * multiple planes or buffers.*/
+ paddr += meta_frame->frame.mp[i].addr_offset;
+ meta_frame->map[i].paddr = paddr;
+ meta_frame->map[i].len = len;
+ D("%s Plane %d fd %d handle %p paddr %x", __func__,
+ i, meta_frame->frame.mp[i].fd,
+ meta_frame->map[i].handle,
+ (uint32_t)meta_frame->map[i].paddr);
+ }
+ D("%s Frame mapped successfully ", __func__);
+ return 0;
+}
+#endif
+
+int msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
+ struct ion_client *client, int domain_num)
+{
+
+ if ((NULL == meta_frame) || (NULL == client)) {
+ pr_err("%s Invalid input ", __func__);
+ return -EINVAL;
+ }
+
+ memset(&meta_frame->map[0], 0,
+ sizeof(struct msm_cam_buf_map_info) * VIDEO_MAX_PLANES);
+
+ return __msm_mctl_map_user_frame(meta_frame, client, domain_num);
+}
+
+int msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
+ struct ion_client *client, int domain_num)
+{
+ if ((NULL == meta_frame) || (NULL == client)) {
+ pr_err("%s Invalid input ", __func__);
+ return -EINVAL;
+ }
+ __msm_mctl_unmap_user_frame(meta_frame, client, domain_num);
+ return 0;
+}
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index dcb7c51..1f5b739 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -364,49 +364,6 @@
return 0;
}
-static int msm_mctl_pp_copy_timestamp_and_frame_id(
- uint32_t src_handle, uint32_t dest_handle)
-{
- struct msm_frame_buffer *src_vb;
- struct msm_frame_buffer *dest_vb;
-
- src_vb = (struct msm_frame_buffer *)src_handle;
- dest_vb = (struct msm_frame_buffer *)dest_handle;
- dest_vb->vidbuf.v4l2_buf.timestamp =
- src_vb->vidbuf.v4l2_buf.timestamp;
- dest_vb->vidbuf.v4l2_buf.sequence =
- src_vb->vidbuf.v4l2_buf.sequence;
- D("%s: timestamp=%ld:%ld,frame_id=0x%x", __func__,
- dest_vb->vidbuf.v4l2_buf.timestamp.tv_sec,
- dest_vb->vidbuf.v4l2_buf.timestamp.tv_usec,
- dest_vb->vidbuf.v4l2_buf.sequence);
- return 0;
-}
-
-static int msm_mctl_pp_path_to_inst_index(struct msm_cam_v4l2_device *pcam,
- int out_type)
-{
- int image_mode;
- switch (out_type) {
- case OUTPUT_TYPE_P:
- image_mode = MSM_V4L2_EXT_CAPTURE_MODE_PREVIEW;
- break;
- case OUTPUT_TYPE_V:
- image_mode = MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
- break;
- case OUTPUT_TYPE_S:
- image_mode = MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
- break;
- default:
- image_mode = -1;
- break;
- }
- if ((image_mode >= 0) && pcam->dev_inst_map[image_mode])
- return pcam->dev_inst_map[image_mode]->my_index;
- else
- return -EINVAL;
-}
-
static int msm_mctl_pp_path_to_img_mode(int path)
{
switch (path) {
@@ -418,6 +375,16 @@
return MSM_V4L2_EXT_CAPTURE_MODE_MAIN;
case OUTPUT_TYPE_T:
return MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
+ case OUTPUT_TYPE_SAEC:
+ return MSM_V4L2_EXT_CAPTURE_MODE_AEC;
+ case OUTPUT_TYPE_SAWB:
+ return MSM_V4L2_EXT_CAPTURE_MODE_AWB;
+ case OUTPUT_TYPE_SAFC:
+ return MSM_V4L2_EXT_CAPTURE_MODE_AF;
+ case OUTPUT_TYPE_IHST:
+ return MSM_V4L2_EXT_CAPTURE_MODE_IHIST;
+ case OUTPUT_TYPE_CSTA:
+ return MSM_V4L2_EXT_CAPTURE_MODE_CSTA;
default:
return -EINVAL;
}
@@ -615,6 +582,7 @@
struct msm_free_buf buf;
unsigned long flags;
struct msm_cam_buf_handle buf_handle;
+ struct msm_cam_return_frame_info ret_frame;
if (copy_from_user(&frame, arg, sizeof(frame))) {
ERR_COPY_FROM_USER();
@@ -657,7 +625,11 @@
buf.ch_paddr[0] = frame.sp.phy_addr + frame.sp.y_off;
}
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
- rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle, &buf, dirty, 0);
+
+ ret_frame.dirty = dirty;
+ ret_frame.node_type = 0;
+ ret_frame.timestamp = frame.timestamp;
+ rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle, &buf, &ret_frame);
return rc;
}
@@ -667,10 +639,10 @@
{
struct msm_pp_frame frame;
int msg_type, image_mode, rc = 0;
- int dirty = 0;
struct msm_free_buf buf;
unsigned long flags;
struct msm_cam_buf_handle buf_handle;
+ struct msm_cam_return_frame_info ret_frame;
D("%s enter\n", __func__);
@@ -698,6 +670,22 @@
msg_type = VFE_MSG_OUTPUT_T;
image_mode = MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
break;
+ case OUTPUT_TYPE_SAEC:
+ msg_type = VFE_MSG_STATS_AEC;
+ image_mode = MSM_V4L2_EXT_CAPTURE_MODE_AEC;
+ break;
+ case OUTPUT_TYPE_SAWB:
+ msg_type = VFE_MSG_STATS_AWB;
+ image_mode = MSM_V4L2_EXT_CAPTURE_MODE_AWB;
+ break;
+ case OUTPUT_TYPE_SAFC:
+ msg_type = VFE_MSG_STATS_AF;
+ image_mode = MSM_V4L2_EXT_CAPTURE_MODE_AF;
+ break;
+ case OUTPUT_TYPE_IHST:
+ msg_type = VFE_MSG_STATS_IHIST;
+ image_mode = MSM_V4L2_EXT_CAPTURE_MODE_IHIST;
+ break;
default:
rc = -EFAULT;
goto err;
@@ -718,9 +706,12 @@
buf.ch_paddr[0] = frame.sp.phy_addr + frame.sp.y_off;
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
+
+ ret_frame.dirty = 0;
+ ret_frame.node_type = frame.node_type;
+ ret_frame.timestamp = frame.timestamp;
D("%s Frame done id: %d\n", __func__, frame.frame_id);
- rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle,
- &buf, dirty, frame.node_type);
+ rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle, &buf, &ret_frame);
return rc;
err:
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
@@ -755,54 +746,3 @@
return rc;
}
-
-int msm_mctl_pp_get_vpe_buf_info(struct msm_mctl_pp_frame_info *zoom)
-{
- struct msm_cam_media_controller *p_mctl;
- struct msm_cam_v4l2_dev_inst *pcam_inst;
- int rc = 0, idx;
-
- if (!zoom || !zoom->p_mctl) {
- pr_err("%s Invalid input, not sending buffer to VPE ",
- __func__);
- return -EINVAL;
- }
- p_mctl = zoom->p_mctl;
- idx = msm_mctl_pp_path_to_inst_index(p_mctl->pcam_ptr,
- zoom->pp_frame_cmd.path);
- if (idx < 0) {
- pr_err("%s Invalid path, returning\n", __func__);
- return idx;
- }
- pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
- if (!pcam_inst) {
- pr_err("%s Invalid instance, returning\n", __func__);
- return -EINVAL;
- }
-
- rc = msm_mctl_pp_get_phy_addr(pcam_inst,
- zoom->pp_frame_cmd.src_buf_handle, &zoom->src_frame);
- if (rc) {
- pr_err("%s Error getting buffer address for src frame\n",
- __func__);
- return rc;
- }
-
- rc = msm_mctl_pp_get_phy_addr(pcam_inst,
- zoom->pp_frame_cmd.dest_buf_handle, &zoom->dest_frame);
- if (rc) {
- pr_err("%s Error getting buffer address for dest frame\n",
- __func__);
- return rc;
- }
-
- rc = msm_mctl_pp_copy_timestamp_and_frame_id(
- zoom->pp_frame_cmd.src_buf_handle,
- zoom->pp_frame_cmd.dest_buf_handle);
- if (rc < 0) {
- pr_err("%s Error copying timestamp info\n",
- __func__);
- return rc;
- }
- return rc;
-}
diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/video/msm/msm_mem.c
index e2e9d1b..5136d9d 100644
--- a/drivers/media/video/msm/msm_mem.c
+++ b/drivers/media/video/msm/msm_mem.c
@@ -116,7 +116,7 @@
}
static int msm_pmem_table_add(struct hlist_head *ptype,
- struct msm_pmem_info *info, struct ion_client *client)
+ struct msm_pmem_info *info, struct ion_client *client, int domain_num)
{
unsigned long paddr;
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -135,7 +135,7 @@
region->handle = ion_import_dma_buf(client, info->fd);
if (IS_ERR_OR_NULL(region->handle))
goto out1;
- if (ion_map_iommu(client, region->handle, CAMERA_DOMAIN, GEN_POOL,
+ if (ion_map_iommu(client, region->handle, domain_num, 0,
SZ_4K, 0, &paddr, &len, UNCACHED, 0) < 0)
goto out2;
#elif CONFIG_ANDROID_PMEM
@@ -180,7 +180,7 @@
return 0;
out3:
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- ion_unmap_iommu(client, region->handle, CAMERA_DOMAIN, GEN_POOL);
+ ion_unmap_iommu(client, region->handle, domain_num, 0);
#endif
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
out2:
@@ -195,7 +195,8 @@
}
static int __msm_register_pmem(struct hlist_head *ptype,
- struct msm_pmem_info *pinfo, struct ion_client *client)
+ struct msm_pmem_info *pinfo, struct ion_client *client,
+ int domain_num)
{
int rc = 0;
@@ -211,7 +212,7 @@
case MSM_PMEM_BAYER_GRID:
case MSM_PMEM_BAYER_FOCUS:
case MSM_PMEM_BAYER_HIST:
- rc = msm_pmem_table_add(ptype, pinfo, client);
+ rc = msm_pmem_table_add(ptype, pinfo, client, domain_num);
break;
default:
@@ -223,7 +224,8 @@
}
static int __msm_pmem_table_del(struct hlist_head *ptype,
- struct msm_pmem_info *pinfo, struct ion_client *client)
+ struct msm_pmem_info *pinfo, struct ion_client *client,
+ int domain_num)
{
int rc = 0;
struct msm_pmem_region *region;
@@ -250,7 +252,7 @@
hlist_del(node);
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
ion_unmap_iommu(client, region->handle,
- CAMERA_DOMAIN, GEN_POOL);
+ domain_num, 0);
ion_free(client, region->handle);
#else
put_pmem_file(region->file);
@@ -394,7 +396,8 @@
}
int msm_register_pmem(struct hlist_head *ptype, void __user *arg,
- struct ion_client *client)
+ struct ion_client *client,
+ int domain_num)
{
struct msm_pmem_info info;
@@ -403,12 +406,12 @@
return -EFAULT;
}
- return __msm_register_pmem(ptype, &info, client);
+ return __msm_register_pmem(ptype, &info, client, domain_num);
}
//EXPORT_SYMBOL(msm_register_pmem);
int msm_pmem_table_del(struct hlist_head *ptype, void __user *arg,
- struct ion_client *client)
+ struct ion_client *client, int domain_num)
{
struct msm_pmem_info info;
@@ -417,6 +420,6 @@
return -EFAULT;
}
- return __msm_pmem_table_del(ptype, &info, client);
+ return __msm_pmem_table_del(ptype, &info, client, domain_num);
}
//EXPORT_SYMBOL(msm_pmem_table_del);
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index 5990ca7..ede0f7a 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -36,8 +36,8 @@
#define D(fmt, args...) do {} while (0)
#endif
-static int vpe_enable(uint32_t);
-static int vpe_disable(void);
+static int vpe_enable(uint32_t, struct msm_cam_media_controller *);
+static int vpe_disable(struct msm_cam_media_controller *);
static int vpe_update_scaler(struct msm_pp_crop *pcrop);
struct vpe_ctrl_type *vpe_ctrl;
static atomic_t vpe_init_done = ATOMIC_INIT(0);
@@ -425,29 +425,37 @@
int rc = 0;
unsigned long flags;
unsigned long srcP0, srcP1, outP0, outP1;
- struct msm_mctl_pp_frame_info *frame = vpe_ctrl->pp_frame_info;
+ struct msm_mctl_pp_frame_info *frame_info = vpe_ctrl->pp_frame_info;
+
+ if (!frame_info) {
+ pr_err("%s Invalid frame", __func__);
+ return -EINVAL;
+ }
spin_lock_irqsave(&vpe_ctrl->lock, flags);
- if (frame->src_frame.num_planes > 1) {
- srcP0 = vpe_ctrl->pp_frame_info->src_frame.mp[0].phy_addr +
- vpe_ctrl->pp_frame_info->src_frame.mp[0].data_offset;
- srcP1 = vpe_ctrl->pp_frame_info->src_frame.mp[1].phy_addr +
- vpe_ctrl->pp_frame_info->src_frame.mp[1].data_offset;
- outP0 = vpe_ctrl->pp_frame_info->dest_frame.mp[0].phy_addr +
- vpe_ctrl->pp_frame_info->dest_frame.mp[0].data_offset;
- outP1 = vpe_ctrl->pp_frame_info->dest_frame.mp[1].phy_addr +
- vpe_ctrl->pp_frame_info->dest_frame.mp[1].data_offset;
+
+ if (frame_info->src_frame.frame.num_planes > 1) {
+ srcP0 = frame_info->src_frame.map[0].paddr +
+ frame_info->src_frame.map[0].data_offset;
+ srcP1 = frame_info->src_frame.map[1].paddr +
+ frame_info->src_frame.map[1].data_offset;
+ outP0 = frame_info->dest_frame.map[0].paddr +
+ frame_info->dest_frame.map[0].data_offset;
+ outP1 = frame_info->dest_frame.map[1].paddr +
+ frame_info->dest_frame.map[1].data_offset;
} else {
- srcP0 = vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
- vpe_ctrl->pp_frame_info->src_frame.sp.y_off;
- srcP1 = vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
- vpe_ctrl->pp_frame_info->src_frame.sp.cbcr_off;
- outP0 = vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
- vpe_ctrl->pp_frame_info->dest_frame.sp.y_off;
- outP1 = vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
- vpe_ctrl->pp_frame_info->dest_frame.sp.cbcr_off;
+ srcP0 = frame_info->src_frame.map[0].paddr;
+ srcP1 = frame_info->src_frame.map[0].paddr +
+ frame_info->src_frame.map[0].data_offset;
+ outP0 = frame_info->dest_frame.map[0].paddr;
+ outP1 = frame_info->dest_frame.map[0].paddr +
+ frame_info->dest_frame.map[0].data_offset;
}
+ D("%s VPE Configured with Src %x, %x Dest %x, %x",
+ __func__, (uint32_t)srcP0, (uint32_t)srcP1,
+ (uint32_t)outP0, (uint32_t)outP1);
+
msm_camera_io_w(srcP0, vpe_ctrl->vpebase + VPE_SRCP0_ADDR_OFFSET);
msm_camera_io_w(srcP1, vpe_ctrl->vpebase + VPE_SRCP1_ADDR_OFFSET);
msm_camera_io_w(outP0, vpe_ctrl->vpebase + VPE_OUTP0_ADDR_OFFSET);
@@ -482,7 +490,6 @@
v4l2_evt.type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_MCTL_PP_EVENT;
v4l2_evt.id = 0;
v4l2_event_queue(vpe_ctrl->subdev.devnode, &v4l2_evt);
-
spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
}
@@ -513,7 +520,7 @@
{"vpe_pclk", -1},
};
-int vpe_enable(uint32_t clk_rate)
+int vpe_enable(uint32_t clk_rate, struct msm_cam_media_controller *mctl)
{
int rc = 0;
unsigned long flags = 0;
@@ -542,8 +549,27 @@
if (rc < 0)
goto vpe_clk_failed;
+#ifdef CONFIG_MSM_IOMMU
+ rc = iommu_attach_device(mctl->domain, vpe_ctrl->iommu_ctx_src);
+ if (rc < 0) {
+ pr_err("%s: Device attach failed\n", __func__);
+ goto src_attach_failed;
+ }
+ rc = iommu_attach_device(mctl->domain, vpe_ctrl->iommu_ctx_dst);
+ if (rc < 0) {
+ pr_err("%s: Device attach failed\n", __func__);
+ goto dst_attach_failed;
+ }
+#endif
return rc;
+#ifdef CONFIG_MSM_IOMMU
+dst_attach_failed:
+ iommu_detach_device(mctl->domain, vpe_ctrl->iommu_ctx_src);
+src_attach_failed:
+#endif
+ msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
+ vpe_ctrl->vpe_clk, ARRAY_SIZE(vpe_clk_info), 0);
vpe_clk_failed:
if (vpe_ctrl->fs_vpe)
regulator_disable(vpe_ctrl->fs_vpe);
@@ -553,7 +579,7 @@
return rc;
}
-int vpe_disable(void)
+int vpe_disable(struct msm_cam_media_controller *mctl)
{
int rc = 0;
unsigned long flags = 0;
@@ -565,7 +591,10 @@
return rc;
}
spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
-
+#ifdef CONFIG_MSM_IOMMU
+ iommu_detach_device(mctl->domain, vpe_ctrl->iommu_ctx_dst);
+ iommu_detach_device(mctl->domain, vpe_ctrl->iommu_ctx_src);
+#endif
disable_irq(vpe_ctrl->vpeirq->start);
tasklet_kill(&vpe_tasklet);
msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
@@ -596,8 +625,8 @@
msm_vpe_cfg_update(
&vpe_ctrl->pp_frame_info->pp_frame_cmd.crop);
D("%s Sending frame idx %d id %d to VPE ", __func__,
- pp_frame_info->src_frame.buf_idx,
- pp_frame_info->src_frame.frame_id);
+ pp_frame_info->src_frame.frame.buf_idx,
+ pp_frame_info->src_frame.frame.frame_id);
rc = msm_send_frame_to_vpe();
return rc;
}
@@ -648,23 +677,25 @@
return rc; /* this rc should have error code. */
}
-void msm_vpe_subdev_release(void)
+void msm_vpe_subdev_release(struct v4l2_subdev *sd)
{
+ struct msm_cam_media_controller *mctl;
+ mctl = v4l2_get_subdev_hostdata(sd);
if (!atomic_read(&vpe_init_done)) {
/* no VPE object created */
pr_err("%s: no VPE object to release", __func__);
return;
}
-
vpe_reset();
- vpe_disable();
+ vpe_disable(mctl);
iounmap(vpe_ctrl->vpebase);
vpe_ctrl->vpebase = NULL;
atomic_set(&vpe_init_done, 0);
}
EXPORT_SYMBOL(msm_vpe_subdev_release);
-static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd)
+static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd,
+ struct msm_cam_media_controller *mctl)
{
int rc = 0;
@@ -787,19 +818,35 @@
zoom->user_cmd = vpe_cmd->cmd_type;
zoom->p_mctl = v4l2_get_subdev_hostdata(&vpe_ctrl->subdev);
- D("%s: src=0x%x, dest=0x%x,cookie=0x%x,action=0x%x,path=0x%x",
- __func__, zoom->pp_frame_cmd.src_buf_handle,
- zoom->pp_frame_cmd.dest_buf_handle,
- zoom->pp_frame_cmd.cookie,
+ D("%s: cookie=0x%x,action=0x%x,path=0x%x",
+ __func__, zoom->pp_frame_cmd.cookie,
zoom->pp_frame_cmd.vpe_output_action,
zoom->pp_frame_cmd.path);
- rc = msm_mctl_pp_get_vpe_buf_info(zoom);
+
+ D("%s Mapping Source frame ", __func__);
+ zoom->src_frame.frame = zoom->pp_frame_cmd.src_frame;
+ rc = msm_mctl_map_user_frame(&zoom->src_frame,
+ zoom->p_mctl->client, mctl->domain_num);
if (rc < 0) {
- pr_err("%s Error getting buffer info from mctl rc = %d",
+ pr_err("%s Error mapping source buffer rc = %d",
__func__, rc);
kfree(zoom);
break;
}
+
+ D("%s Mapping Destination frame ", __func__);
+ zoom->dest_frame.frame = zoom->pp_frame_cmd.dest_frame;
+ rc = msm_mctl_map_user_frame(&zoom->dest_frame,
+ zoom->p_mctl->client, mctl->domain_num);
+ if (rc < 0) {
+ pr_err("%s Error mapping dest buffer rc = %d",
+ __func__, rc);
+ msm_mctl_unmap_user_frame(&zoom->src_frame,
+ zoom->p_mctl->client, mctl->domain_num);
+ kfree(zoom);
+ break;
+ }
+
rc = msm_vpe_do_pp(zoom);
break;
}
@@ -820,13 +867,13 @@
return -EFAULT;
}
turbo_mode = (int)clk_rate.rate;
- rc = turbo_mode ? vpe_enable(VPE_TURBO_MODE_CLOCK_RATE) :
- vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE);
+ rc = turbo_mode ? vpe_enable(VPE_TURBO_MODE_CLOCK_RATE, mctl) :
+ vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE, mctl);
break;
}
case VPE_CMD_DISABLE:
- rc = vpe_disable();
+ rc = vpe_disable(mctl);
break;
default:
@@ -841,7 +888,8 @@
{
struct msm_vpe_cfg_cmd *vpe_cmd;
int rc = 0;
-
+ struct msm_cam_media_controller *mctl;
+ mctl = v4l2_get_subdev_hostdata(sd);
switch (cmd) {
case VIDIOC_MSM_VPE_INIT: {
msm_vpe_subdev_init(sd);
@@ -849,12 +897,12 @@
}
case VIDIOC_MSM_VPE_RELEASE:
- msm_vpe_subdev_release();
+ msm_vpe_subdev_release(sd);
break;
case MSM_CAM_V4L2_IOCTL_CFG_VPE: {
vpe_cmd = (struct msm_vpe_cfg_cmd *)arg;
- rc = msm_vpe_process_vpe_cmd(vpe_cmd);
+ rc = msm_vpe_process_vpe_cmd(vpe_cmd, mctl);
if (rc < 0) {
pr_err("%s Error processing VPE cmd %d ",
__func__, vpe_cmd->cmd_type);
@@ -876,6 +924,14 @@
return -EFAULT;
}
pp_frame_info = event_qcmd->command;
+
+ D("%s Unmapping source and destination buffers ",
+ __func__);
+ msm_mctl_unmap_user_frame(&pp_frame_info->src_frame,
+ pp_frame_info->p_mctl->client, mctl->domain_num);
+ msm_mctl_unmap_user_frame(&pp_frame_info->dest_frame,
+ pp_frame_info->p_mctl->client, mctl->domain_num);
+
pp_event_info.event = MCTL_PP_EVENT_CMD_ACK;
pp_event_info.ack.cmd = pp_frame_info->user_cmd;
pp_event_info.ack.status = 0;
@@ -884,10 +940,9 @@
pp_event_info.ack.cmd, pp_event_info.ack.status,
pp_event_info.ack.cookie);
if (copy_to_user((void __user *)v4l2_ioctl->ioctl_ptr,
- &pp_event_info,
- sizeof(struct msm_mctl_pp_event_info)))
- pr_err("%s EVENTPAYLOAD Copy to user failed ",
- __func__);
+ &pp_event_info, sizeof(struct msm_mctl_pp_event_info)))
+ pr_err("%s PAYLOAD Copy to user failed ", __func__);
+
kfree(pp_frame_info);
kfree(event_qcmd);
break;
@@ -942,12 +997,22 @@
struct v4l2_subdev_fh *fh)
{
struct vpe_ctrl_type *vpe_ctrl = v4l2_get_subdevdata(sd);
+ struct msm_mctl_pp_frame_info *frame_info = vpe_ctrl->pp_frame_info;
+ struct msm_cam_media_controller *mctl;
+ mctl = v4l2_get_subdev_hostdata(sd);
if (atomic_read(&vpe_ctrl->active) == 0) {
pr_err("%s already closed\n", __func__);
return -EINVAL;
}
D("%s E ", __func__);
+ if (frame_info) {
+ D("%s Unmap the pending item from the queue ", __func__);
+ msm_mctl_unmap_user_frame(&frame_info->src_frame,
+ frame_info->p_mctl->client, mctl->domain_num);
+ msm_mctl_unmap_user_frame(&frame_info->dest_frame,
+ frame_info->p_mctl->client, mctl->domain_num);
+ }
/* Drain the payload queue. */
msm_queue_drain(&vpe_ctrl->eventData_q, list_eventdata);
atomic_dec(&vpe_ctrl->active);
@@ -1027,6 +1092,19 @@
disable_irq(vpe_ctrl->vpeirq->start);
+#ifdef CONFIG_MSM_IOMMU
+ /*get device context for IOMMU*/
+ vpe_ctrl->iommu_ctx_src = msm_iommu_get_ctx("vpe_src"); /*re-confirm*/
+ vpe_ctrl->iommu_ctx_dst = msm_iommu_get_ctx("vpe_dst"); /*re-confirm*/
+ if (!vpe_ctrl->iommu_ctx_src || !vpe_ctrl->iommu_ctx_dst) {
+ release_mem_region(vpe_ctrl->vpemem->start,
+ resource_size(vpe_ctrl->vpemem));
+ pr_err("%s: No iommu fw context found\n", __func__);
+ rc = -ENODEV;
+ goto vpe_no_resource;
+ }
+#endif
+
atomic_set(&vpe_ctrl->active, 0);
vpe_ctrl->pdev = pdev;
sd_info.sdev_type = VPE_DEV;
diff --git a/drivers/media/video/msm/msm_vpe.h b/drivers/media/video/msm/msm_vpe.h
index 6516ea1..aad2380 100644
--- a/drivers/media/video/msm/msm_vpe.h
+++ b/drivers/media/video/msm/msm_vpe.h
@@ -121,6 +121,8 @@
struct msm_mctl_pp_frame_info *pp_frame_info;
atomic_t active;
struct msm_device_queue eventData_q; /*V4L2 Event Payload Queue*/
+ struct device *iommu_ctx_src;
+ struct device *iommu_ctx_dst;
};
/*
diff --git a/drivers/media/video/msm/sensors/Makefile b/drivers/media/video/msm/sensors/Makefile
index 5f3f6dd..cd228a1 100644
--- a/drivers/media/video/msm/sensors/Makefile
+++ b/drivers/media/video/msm/sensors/Makefile
@@ -3,12 +3,11 @@
EXTRA_CFLAGS += -Idrivers/media/video/msm/io
EXTRA_CFLAGS += -Idrivers/media/video/msm/eeprom
EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
-obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
+obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor_common.o msm_sensor.o msm_sensor_bayer.o msm_sensor_init.o
obj-$(CONFIG_OV5647) += ov5647_v4l2.o
obj-$(CONFIG_OV8825) += ov8825_v4l2.o
obj-$(CONFIG_IMX074) += imx074_v4l2.o
obj-$(CONFIG_S5K3L1YX) += s5k3l1yx.o
-obj-$(CONFIG_IMX091) += imx091.o
obj-$(CONFIG_OV2720) += ov2720.o
obj-$(CONFIG_MT9M114) += mt9m114_v4l2.o
obj-$(CONFIG_S5K4E1) += s5k4e1_v4l2.o
diff --git a/drivers/media/video/msm/sensors/imx074_v4l2.c b/drivers/media/video/msm/sensors/imx074_v4l2.c
index ddf0754..91d4797 100644
--- a/drivers/media/video/msm/sensors/imx074_v4l2.c
+++ b/drivers/media/video/msm/sensors/imx074_v4l2.c
@@ -168,44 +168,6 @@
},
};
-static struct msm_camera_csi_params imx074_csic_params = {
- .data_format = CSI_10BIT,
- .lane_cnt = 4,
- .lane_assign = 0xe4,
- .dpcm_scheme = 0,
- .settle_cnt = 0x14,
-};
-
-static struct msm_camera_csi_params *imx074_csic_params_array[] = {
- &imx074_csic_params,
- &imx074_csic_params,
-};
-
-static struct msm_camera_csid_vc_cfg imx074_cid_cfg[] = {
- {0, CSI_RAW10, CSI_DECODE_10BIT},
- {1, CSI_EMBED_DATA, CSI_DECODE_8BIT},
- {2, CSI_RESERVED_DATA_0, CSI_DECODE_8BIT},
-};
-
-static struct msm_camera_csi2_params imx074_csi_params = {
- .csid_params = {
- .lane_cnt = 4,
- .lut_params = {
- .num_cid = ARRAY_SIZE(imx074_cid_cfg),
- .vc_cfg = imx074_cid_cfg,
- },
- },
- .csiphy_params = {
- .lane_cnt = 4,
- .settle_cnt = 0x1B,
- },
-};
-
-static struct msm_camera_csi2_params *imx074_csi_params_array[] = {
- &imx074_csi_params,
- &imx074_csi_params,
-};
-
static struct msm_sensor_output_reg_addr_t imx074_reg_addr = {
.x_output = 0x34C,
.y_output = 0x34E,
@@ -224,6 +186,13 @@
.vert_offset = 3,
};
+static enum msm_camera_vreg_name_t imx074_veg_seq[] = {
+ CAM_VDIG,
+ CAM_VIO,
+ CAM_VANA,
+ CAM_VAF,
+};
+
static const struct i2c_device_id imx074_i2c_id[] = {
{SENSOR_NAME, (kernel_ulong_t)&imx074_s_ctrl},
{ }
@@ -302,12 +271,12 @@
.msm_sensor_reg = &imx074_regs,
.sensor_i2c_client = &imx074_sensor_i2c_client,
.sensor_i2c_addr = 0x34,
+ .vreg_seq = imx074_veg_seq,
+ .num_vreg_seq = ARRAY_SIZE(imx074_veg_seq),
.sensor_output_reg_addr = &imx074_reg_addr,
.sensor_id_info = &imx074_id_info,
.sensor_exp_gain_info = &imx074_exp_gain_info,
.cam_mode = MSM_SENSOR_MODE_INVALID,
- .csic_params = &imx074_csic_params_array[0],
- .csi_params = &imx074_csi_params_array[0],
.msm_sensor_mutex = &imx074_mut,
.sensor_i2c_driver = &imx074_i2c_driver,
.sensor_v4l2_subdev_info = imx074_subdev_info,
diff --git a/drivers/media/video/msm/sensors/imx091.c b/drivers/media/video/msm/sensors/imx091.c
deleted file mode 100644
index 7fda037..0000000
--- a/drivers/media/video/msm/sensors/imx091.c
+++ /dev/null
@@ -1,347 +0,0 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-#include "msm_sensor.h"
-#define SENSOR_NAME "imx091"
-#define PLATFORM_DRIVER_NAME "msm_camera_imx091"
-#define imx091_obj imx091_##obj
-
-DEFINE_MUTEX(imx091_mut);
-static struct msm_sensor_ctrl_t imx091_s_ctrl;
-
-static struct msm_camera_i2c_reg_conf imx091_start_settings[] = {
- {0x0100, 0x01},
-};
-
-static struct msm_camera_i2c_reg_conf imx091_stop_settings[] = {
- {0x0100, 0x00},
-};
-
-static struct msm_camera_i2c_reg_conf imx091_groupon_settings[] = {
- {0x0104, 0x01},
-};
-
-static struct msm_camera_i2c_reg_conf imx091_groupoff_settings[] = {
- {0x0104, 0x00},
-};
-
-static struct msm_camera_i2c_reg_conf imx091_prev_settings[] = {
- /* 30fps 1/2 * 1/2 */
- /* PLL setting */
- {0x0305, 0x02}, /* pre_pll_clk_div[7:0] */
- {0x0307, 0x2F}, /* pll_multiplier[7:0] */
- {0x30A4, 0x02},
- {0x303C, 0x4B},
- /* mode setting */
- {0x0340, 0x06}, /* frame_length_lines[15:8] */
- {0x0341, 0x5A}, /* frame_length_lines[7:0] */
- {0x0342, 0x12}, /* line_length_pck[15:8] */
- {0x0343, 0x0C}, /* line_length_pck[7:0] */
- {0x0344, 0x00}, /* x_addr_start[15:8] */
- {0x0345, 0x08}, /* x_addr_start[7:0] */
- {0x0346, 0x00}, /* y_addr_start[15:8] */
- {0x0347, 0x30}, /* y_addr_start[7:0] */
- {0x0348, 0x10}, /* x_addr_end[15:8] */
- {0x0349, 0x77}, /* x_addr_end[7:0] */
- {0x034A, 0x0C}, /* y_addr_end[15:8] */
- {0x034B, 0x5F}, /* y_addr_end[7:0] */
- {0x034C, 0x08}, /* x_output_size[15:8] */
- {0x034D, 0x38}, /* x_output_size[7:0] */
- {0x034E, 0x06}, /* y_output_size[15:8] */
- {0x034F, 0x18}, /* y_output_size[7:0] */
- {0x0381, 0x01}, /* x_even_inc[3:0] */
- {0x0383, 0x03}, /* x_odd_inc[3:0] */
- {0x0385, 0x01}, /* y_even_inc[7:0] */
- {0x0387, 0x03}, /* y_odd_inc[7:0] */
- {0x3040, 0x08},
- {0x3041, 0x97},
- {0x3048, 0x01},
- {0x3064, 0x12},
- {0x309B, 0x28},
- {0x309E, 0x00},
- {0x30D5, 0x09},
- {0x30D6, 0x01},
- {0x30D7, 0x01},
- {0x30D8, 0x64},
- {0x30D9, 0x89},
- {0x30DE, 0x02},
- {0x3102, 0x10},
- {0x3103, 0x44},
- {0x3104, 0x40},
- {0x3105, 0x00},
- {0x3106, 0x0D},
- {0x3107, 0x01},
- {0x310A, 0x0A},
- {0x315C, 0x99},
- {0x315D, 0x98},
- {0x316E, 0x9A},
- {0x316F, 0x99},
- {0x3318, 0x73},
-};
-
-static struct msm_camera_i2c_reg_conf imx091_snap_settings[] = {
- /* full size */
- /* PLL setting */
- {0x0305, 0x02}, /* pre_pll_clk_div[7:0] */
- {0x0307, 0x2B}, /* pll_multiplier[7:0] */
- {0x30A4, 0x02},
- {0x303C, 0x4B},
- /* mode setting */
- {0x0340, 0x0C}, /* frame_length_lines[15:8] */
- {0x0341, 0x8C}, /* frame_length_lines[7:0] */
- {0x0342, 0x12}, /* line_length_pck[15:8] */
- {0x0343, 0x0C}, /* line_length_pck[7:0] */
- {0x0344, 0x00}, /* x_addr_start[15:8] */
- {0x0345, 0x08}, /* x_addr_start[7:0] */
- {0x0346, 0x00}, /* y_addr_start[15:8] */
- {0x0347, 0x30}, /* y_addr_start[7:0] */
- {0x0348, 0x10}, /* x_addr_end[15:8] */
- {0x0349, 0x77}, /* x_addr_end[7:0] */
- {0x034A, 0x0C}, /* y_addr_end[15:8] */
- {0x034B, 0x5F}, /* y_addr_end[7:0] */
- {0x034C, 0x10}, /* x_output_size[15:8] */
- {0x034D, 0x70}, /* x_output_size[7:0] */
- {0x034E, 0x0C}, /* y_output_size[15:8] */
- {0x034F, 0x30}, /* y_output_size[7:0] */
- {0x0381, 0x01}, /* x_even_inc[3:0] */
- {0x0383, 0x01}, /* x_odd_inc[3:0] */
- {0x0385, 0x01}, /* y_even_inc[7:0] */
- {0x0387, 0x01}, /* y_odd_inc[7:0] */
- {0x3040, 0x08},
- {0x3041, 0x97},
- {0x3048, 0x00},
- {0x3064, 0x12},
- {0x309B, 0x20},
- {0x309E, 0x00},
- {0x30D5, 0x00},
- {0x30D6, 0x85},
- {0x30D7, 0x2A},
- {0x30D8, 0x64},
- {0x30D9, 0x89},
- {0x30DE, 0x00},
- {0x3102, 0x10},
- {0x3103, 0x44},
- {0x3104, 0x40},
- {0x3105, 0x00},
- {0x3106, 0x0D},
- {0x3107, 0x01},
- {0x310A, 0x0A},
- {0x315C, 0x99},
- {0x315D, 0x98},
- {0x316E, 0x9A},
- {0x316F, 0x99},
- {0x3318, 0x64},
-};
-
-static struct msm_camera_i2c_reg_conf imx091_recommend_settings[] = {
- /* global setting */
- {0x3087, 0x53},
- {0x309D, 0x94},
- {0x30A1, 0x08},
- {0x30C7, 0x00},
- {0x3115, 0x0E},
- {0x3118, 0x42},
- {0x311D, 0x34},
- {0x3121, 0x0D},
- {0x3212, 0xF2},
- {0x3213, 0x0F},
- {0x3215, 0x0F},
- {0x3217, 0x0B},
- {0x3219, 0x0B},
- {0x321B, 0x0D},
- {0x321D, 0x0D},
- /* black level setting */
- {0x3032, 0x40},
-};
-
-static struct v4l2_subdev_info imx091_subdev_info[] = {
- {
- .code = V4L2_MBUS_FMT_SBGGR10_1X10,
- .colorspace = V4L2_COLORSPACE_JPEG,
- .fmt = 1,
- .order = 0,
- },
- /* more can be supported, to be added later */
-};
-
-static struct msm_camera_i2c_conf_array imx091_init_conf[] = {
- {&imx091_recommend_settings[0],
- ARRAY_SIZE(imx091_recommend_settings), 0, MSM_CAMERA_I2C_BYTE_DATA}
-};
-
-static struct msm_camera_i2c_conf_array imx091_confs[] = {
- {&imx091_snap_settings[0],
- ARRAY_SIZE(imx091_snap_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
- {&imx091_prev_settings[0],
- ARRAY_SIZE(imx091_prev_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
-};
-
-static struct msm_sensor_output_info_t imx091_dimensions[] = {
- {
- /* full size */
- .x_output = 0x1070, /* 4208 */
- .y_output = 0x0C30, /* 3120 */
- .line_length_pclk = 0x120C, /* 4620 */
- .frame_length_lines = 0x0C8C, /* 3212 */
- .vt_pixel_clk = 206400000,
- .op_pixel_clk = 206400000,
- .binning_factor = 1,
- },
- {
- /* 30 fps 1/2 * 1/2 */
- .x_output = 0x0838, /* 2104 */
- .y_output = 0x0618, /* 1560 */
- .line_length_pclk = 0x120C, /* 4620 */
- .frame_length_lines = 0x065A, /* 1626 */
- .vt_pixel_clk = 225600000,
- .op_pixel_clk = 225600000,
- .binning_factor = 1,
- },
-};
-
-static struct msm_camera_csid_vc_cfg imx091_cid_cfg[] = {
- {0, CSI_RAW10, CSI_DECODE_10BIT},
- {1, CSI_EMBED_DATA, CSI_DECODE_8BIT},
- {2, CSI_RESERVED_DATA_0, CSI_DECODE_8BIT},
-};
-
-static struct msm_camera_csi2_params imx091_csi_params = {
- .csid_params = {
- .lane_cnt = 4,
- .lut_params = {
- .num_cid = ARRAY_SIZE(imx091_cid_cfg),
- .vc_cfg = imx091_cid_cfg,
- },
- },
- .csiphy_params = {
- .lane_cnt = 4,
- .settle_cnt = 0x12,
- },
-};
-
-static struct msm_camera_csi2_params *imx091_csi_params_array[] = {
- &imx091_csi_params,
- &imx091_csi_params,
-};
-
-static struct msm_sensor_output_reg_addr_t imx091_reg_addr = {
- .x_output = 0x034C,
- .y_output = 0x034E,
- .line_length_pclk = 0x0342,
- .frame_length_lines = 0x0340,
-};
-
-static struct msm_sensor_id_info_t imx091_id_info = {
- .sensor_id_reg_addr = 0x0000,
- .sensor_id = 0x0091,
-};
-
-static struct msm_sensor_exp_gain_info_t imx091_exp_gain_info = {
- .coarse_int_time_addr = 0x0202,
- .global_gain_addr = 0x0204,
- .vert_offset = 5,
-};
-
-static const struct i2c_device_id imx091_i2c_id[] = {
- {SENSOR_NAME, (kernel_ulong_t)&imx091_s_ctrl},
- { }
-};
-
-static struct i2c_driver imx091_i2c_driver = {
- .id_table = imx091_i2c_id,
- .probe = msm_sensor_i2c_probe,
- .driver = {
- .name = SENSOR_NAME,
- },
-};
-
-static struct msm_camera_i2c_client imx091_sensor_i2c_client = {
- .addr_type = MSM_CAMERA_I2C_WORD_ADDR,
-};
-
-
-static int __init imx091_sensor_init_module(void)
-{
- return i2c_add_driver(&imx091_i2c_driver);
-}
-
-static struct v4l2_subdev_core_ops imx091_subdev_core_ops = {
- .ioctl = msm_sensor_subdev_ioctl,
- .s_power = msm_sensor_power,
-};
-
-static struct v4l2_subdev_video_ops imx091_subdev_video_ops = {
- .enum_mbus_fmt = msm_sensor_v4l2_enum_fmt,
-};
-
-static struct v4l2_subdev_ops imx091_subdev_ops = {
- .core = &imx091_subdev_core_ops,
- .video = &imx091_subdev_video_ops,
-};
-
-static struct msm_sensor_fn_t imx091_func_tbl = {
- .sensor_start_stream = msm_sensor_start_stream,
- .sensor_stop_stream = msm_sensor_stop_stream,
- .sensor_group_hold_on = msm_sensor_group_hold_on,
- .sensor_group_hold_off = msm_sensor_group_hold_off,
- .sensor_set_fps = msm_sensor_set_fps,
- .sensor_write_exp_gain = msm_sensor_write_exp_gain1,
- .sensor_write_snapshot_exp_gain = msm_sensor_write_exp_gain1,
- .sensor_setting = msm_sensor_setting,
- .sensor_set_sensor_mode = msm_sensor_set_sensor_mode,
- .sensor_mode_init = msm_sensor_mode_init,
- .sensor_get_output_info = msm_sensor_get_output_info,
- .sensor_config = msm_sensor_config,
- .sensor_power_up = msm_sensor_power_up,
- .sensor_power_down = msm_sensor_power_down,
- .sensor_adjust_frame_lines = msm_sensor_adjust_frame_lines1,
- .sensor_get_csi_params = msm_sensor_get_csi_params,
-};
-
-static struct msm_sensor_reg_t imx091_regs = {
- .default_data_type = MSM_CAMERA_I2C_BYTE_DATA,
- .start_stream_conf = imx091_start_settings,
- .start_stream_conf_size = ARRAY_SIZE(imx091_start_settings),
- .stop_stream_conf = imx091_stop_settings,
- .stop_stream_conf_size = ARRAY_SIZE(imx091_stop_settings),
- .group_hold_on_conf = imx091_groupon_settings,
- .group_hold_on_conf_size = ARRAY_SIZE(imx091_groupon_settings),
- .group_hold_off_conf = imx091_groupoff_settings,
- .group_hold_off_conf_size = ARRAY_SIZE(imx091_groupoff_settings),
- .init_settings = &imx091_init_conf[0],
- .init_size = ARRAY_SIZE(imx091_init_conf),
- .mode_settings = &imx091_confs[0],
- .output_settings = &imx091_dimensions[0],
- .num_conf = ARRAY_SIZE(imx091_confs),
-};
-
-static struct msm_sensor_ctrl_t imx091_s_ctrl = {
- .msm_sensor_reg = &imx091_regs,
- .sensor_i2c_client = &imx091_sensor_i2c_client,
- .sensor_i2c_addr = 0x34,
- .sensor_output_reg_addr = &imx091_reg_addr,
- .sensor_id_info = &imx091_id_info,
- .sensor_exp_gain_info = &imx091_exp_gain_info,
- .cam_mode = MSM_SENSOR_MODE_INVALID,
- .csi_params = &imx091_csi_params_array[0],
- .msm_sensor_mutex = &imx091_mut,
- .sensor_i2c_driver = &imx091_i2c_driver,
- .sensor_v4l2_subdev_info = imx091_subdev_info,
- .sensor_v4l2_subdev_info_size = ARRAY_SIZE(imx091_subdev_info),
- .sensor_v4l2_subdev_ops = &imx091_subdev_ops,
- .func_tbl = &imx091_func_tbl,
- .clk_rate = MSM_SENSOR_MCLK_24HZ,
-};
-
-module_init(imx091_sensor_init_module);
-MODULE_DESCRIPTION("SONY 12MP Bayer sensor driver");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/sensors/imx091.h b/drivers/media/video/msm/sensors/imx091.h
new file mode 100644
index 0000000..862b43a
--- /dev/null
+++ b/drivers/media/video/msm/sensors/imx091.h
@@ -0,0 +1,100 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#define IMX091_SENSOR_NAME "imx091"
+DEFINE_MSM_MUTEX(imx091_mut);
+
+static struct msm_sensor_ctrl_t imx091_s_ctrl;
+
+static struct v4l2_subdev_info imx091_subdev_info[] = {
+ {
+ .code = V4L2_MBUS_FMT_SBGGR10_1X10,
+ .colorspace = V4L2_COLORSPACE_JPEG,
+ .fmt = 1,
+ .order = 0,
+ },
+ /* more can be supported, to be added later */
+};
+
+static struct msm_sensor_id_info_t imx091_id_info = {
+ .sensor_id_reg_addr = 0x0000,
+ .sensor_id = 0x0091,
+};
+
+static enum msm_camera_vreg_name_t imx091_veg_seq[] = {
+ CAM_VANA,
+ CAM_VAF,
+ CAM_VDIG,
+ CAM_VIO,
+};
+
+static struct msm_camera_power_seq_t imx091_power_seq[] = {
+ {REQUEST_GPIO, 0},
+ {REQUEST_VREG, 0},
+ {ENABLE_VREG, 0},
+ {ENABLE_GPIO, 0},
+ {CONFIG_CLK, 0},
+};
+
+static const struct i2c_device_id imx091_i2c_id[] = {
+ {IMX091_SENSOR_NAME, (kernel_ulong_t)&imx091_s_ctrl},
+ { }
+};
+
+static struct i2c_driver imx091_i2c_driver = {
+ .id_table = imx091_i2c_id,
+ .probe = msm_sensor_bayer_i2c_probe,
+ .driver = {
+ .name = IMX091_SENSOR_NAME,
+ },
+};
+
+static struct msm_camera_i2c_client imx091_sensor_i2c_client = {
+ .addr_type = MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+static struct v4l2_subdev_core_ops imx091_subdev_core_ops = {
+ .ioctl = msm_sensor_bayer_subdev_ioctl,
+ .s_power = msm_sensor_bayer_power,
+};
+
+static struct v4l2_subdev_video_ops imx091_subdev_video_ops = {
+ .enum_mbus_fmt = msm_sensor_bayer_v4l2_enum_fmt,
+};
+
+static struct v4l2_subdev_ops imx091_subdev_ops = {
+ .core = &imx091_subdev_core_ops,
+ .video = &imx091_subdev_video_ops,
+};
+
+static struct msm_sensor_fn_t imx091_func_tbl = {
+ .sensor_config = msm_sensor_bayer_config,
+ .sensor_power_up = msm_sensor_bayer_power_up,
+ .sensor_power_down = msm_sensor_bayer_power_down,
+ .sensor_get_csi_params = msm_sensor_bayer_get_csi_params,
+};
+
+static struct msm_sensor_ctrl_t imx091_s_ctrl = {
+ .sensor_i2c_client = &imx091_sensor_i2c_client,
+ .sensor_i2c_addr = 0x34,
+ .vreg_seq = imx091_veg_seq,
+ .num_vreg_seq = ARRAY_SIZE(imx091_veg_seq),
+ .power_seq = &imx091_power_seq[0],
+ .num_power_seq = ARRAY_SIZE(imx091_power_seq),
+ .sensor_id_info = &imx091_id_info,
+ .msm_sensor_mutex = &imx091_mut,
+ .sensor_v4l2_subdev_info = imx091_subdev_info,
+ .sensor_v4l2_subdev_info_size = ARRAY_SIZE(imx091_subdev_info),
+ .sensor_v4l2_subdev_ops = &imx091_subdev_ops,
+ .func_tbl = &imx091_func_tbl,
+ .clk_rate = MSM_SENSOR_MCLK_24HZ,
+};
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index c6489c2..8fbcc01 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -9,26 +9,20 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
-
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
#include "msm_sensor.h"
+#include "msm_sensor_common.h"
#include "msm.h"
#include "msm_ispif.h"
#include "msm_camera_i2c_mux.h"
/*=============================================================*/
-int32_t msm_sensor_adjust_frame_lines1(struct msm_sensor_ctrl_t *s_ctrl,
- uint16_t res)
+void msm_sensor_adjust_frame_lines1(struct msm_sensor_ctrl_t *s_ctrl)
{
uint16_t cur_line = 0;
uint16_t exp_fl_lines = 0;
if (s_ctrl->sensor_exp_gain_info) {
- if (s_ctrl->prev_gain && s_ctrl->prev_line &&
- s_ctrl->func_tbl->sensor_write_exp_gain)
- s_ctrl->func_tbl->sensor_write_exp_gain(
- s_ctrl,
- s_ctrl->prev_gain,
- s_ctrl->prev_line);
-
msm_camera_i2c_read(s_ctrl->sensor_i2c_client,
s_ctrl->sensor_exp_gain_info->coarse_int_time_addr,
&cur_line,
@@ -36,7 +30,7 @@
exp_fl_lines = cur_line +
s_ctrl->sensor_exp_gain_info->vert_offset;
if (exp_fl_lines > s_ctrl->msm_sensor_reg->
- output_settings[res].frame_length_lines)
+ output_settings[s_ctrl->curr_res].frame_length_lines)
msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
s_ctrl->sensor_output_reg_addr->
frame_length_lines,
@@ -44,26 +38,18 @@
MSM_CAMERA_I2C_WORD_DATA);
CDBG("%s cur_fl_lines %d, exp_fl_lines %d\n", __func__,
s_ctrl->msm_sensor_reg->
- output_settings[res].frame_length_lines,
+ output_settings[s_ctrl->curr_res].frame_length_lines,
exp_fl_lines);
}
- return 0;
+ return;
}
-int32_t msm_sensor_adjust_frame_lines2(struct msm_sensor_ctrl_t *s_ctrl,
- uint16_t res)
+void msm_sensor_adjust_frame_lines2(struct msm_sensor_ctrl_t *s_ctrl)
{
uint16_t cur_line = 0;
uint16_t exp_fl_lines = 0;
uint8_t int_time[3];
if (s_ctrl->sensor_exp_gain_info) {
- if (s_ctrl->prev_gain && s_ctrl->prev_line &&
- s_ctrl->func_tbl->sensor_write_exp_gain)
- s_ctrl->func_tbl->sensor_write_exp_gain(
- s_ctrl,
- s_ctrl->prev_gain,
- s_ctrl->prev_line);
-
msm_camera_i2c_read_seq(s_ctrl->sensor_i2c_client,
s_ctrl->sensor_exp_gain_info->coarse_int_time_addr-1,
&int_time[0], 3);
@@ -73,7 +59,7 @@
exp_fl_lines = cur_line +
s_ctrl->sensor_exp_gain_info->vert_offset;
if (exp_fl_lines > s_ctrl->msm_sensor_reg->
- output_settings[res].frame_length_lines)
+ output_settings[s_ctrl->curr_res].frame_length_lines)
msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
s_ctrl->sensor_output_reg_addr->
frame_length_lines,
@@ -83,10 +69,32 @@
__func__,
cur_line,
s_ctrl->msm_sensor_reg->
- output_settings[res].frame_length_lines,
+ output_settings[s_ctrl->curr_res].frame_length_lines,
exp_fl_lines);
}
- return 0;
+ return;
+}
+
+static void msm_sensor_delay_frames(struct msm_sensor_ctrl_t *s_ctrl)
+{
+ long fps = 0;
+ uint32_t delay = 0;
+
+ if (s_ctrl->curr_res < MSM_SENSOR_INVALID_RES &&
+ s_ctrl->wait_num_frames > 0) {
+ fps = s_ctrl->msm_sensor_reg->
+ output_settings[s_ctrl->curr_res].vt_pixel_clk /
+ s_ctrl->curr_frame_length_lines /
+ s_ctrl->curr_line_length_pclk;
+ delay = (1000 * s_ctrl->wait_num_frames) / fps / Q10;
+ }
+ CDBG("%s fps = %ld, delay = %d, min_delay %d\n", __func__, fps,
+ delay, s_ctrl->min_delay);
+ if (delay > s_ctrl->min_delay)
+ msleep(delay);
+ else if (s_ctrl->min_delay)
+ msleep(s_ctrl->min_delay);
+ return;
}
int32_t msm_sensor_write_init_settings(struct msm_sensor_ctrl_t *s_ctrl)
@@ -113,9 +121,6 @@
if (rc < 0)
return rc;
- if (s_ctrl->func_tbl->sensor_adjust_frame_lines)
- rc = s_ctrl->func_tbl->sensor_adjust_frame_lines(s_ctrl, res);
-
return rc;
}
@@ -145,11 +150,18 @@
void msm_sensor_start_stream(struct msm_sensor_ctrl_t *s_ctrl)
{
+ if (s_ctrl->curr_res >= s_ctrl->msm_sensor_reg->num_conf)
+ return;
+
+ if (s_ctrl->func_tbl->sensor_adjust_frame_lines)
+ s_ctrl->func_tbl->sensor_adjust_frame_lines(s_ctrl);
+
msm_camera_i2c_write_tbl(
s_ctrl->sensor_i2c_client,
s_ctrl->msm_sensor_reg->start_stream_conf,
s_ctrl->msm_sensor_reg->start_stream_conf_size,
s_ctrl->msm_sensor_reg->default_data_type);
+ msm_sensor_delay_frames(s_ctrl);
}
void msm_sensor_stop_stream(struct msm_sensor_ctrl_t *s_ctrl)
@@ -159,6 +171,7 @@
s_ctrl->msm_sensor_reg->stop_stream_conf,
s_ctrl->msm_sensor_reg->stop_stream_conf_size,
s_ctrl->msm_sensor_reg->default_data_type);
+ msm_sensor_delay_frames(s_ctrl);
}
void msm_sensor_group_hold_on(struct msm_sensor_ctrl_t *s_ctrl)
@@ -244,78 +257,38 @@
int update_type, int res)
{
int32_t rc = 0;
- static int csi_config;
- s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
- msleep(30);
if (update_type == MSM_SENSOR_REG_INIT) {
CDBG("Register INIT\n");
- s_ctrl->curr_csi_params = NULL;
msm_sensor_enable_debugfs(s_ctrl);
+ s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
msm_sensor_write_init_settings(s_ctrl);
- csi_config = 0;
} else if (update_type == MSM_SENSOR_UPDATE_PERIODIC) {
CDBG("PERIODIC : %d\n", res);
msm_sensor_write_conf_array(
s_ctrl->sensor_i2c_client,
s_ctrl->msm_sensor_reg->mode_settings, res);
msleep(30);
- if (!csi_config) {
- s_ctrl->curr_csic_params = s_ctrl->csic_params[res];
- CDBG("CSI config in progress\n");
- v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
- NOTIFY_CSIC_CFG,
- s_ctrl->curr_csic_params);
- CDBG("CSI config is done\n");
- mb();
- msleep(30);
- csi_config = 1;
- }
v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
NOTIFY_PCLK_CHANGE,
&s_ctrl->sensordata->pdata->ioclk.vfe_clk_rate);
-
- s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
- msleep(50);
}
return rc;
}
+
int32_t msm_sensor_setting(struct msm_sensor_ctrl_t *s_ctrl,
int update_type, int res)
{
int32_t rc = 0;
- s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
- msleep(30);
+
if (update_type == MSM_SENSOR_REG_INIT) {
- s_ctrl->curr_csi_params = NULL;
- msm_sensor_enable_debugfs(s_ctrl);
+ s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
msm_sensor_write_init_settings(s_ctrl);
} else if (update_type == MSM_SENSOR_UPDATE_PERIODIC) {
msm_sensor_write_res_settings(s_ctrl, res);
- if (s_ctrl->curr_csi_params != s_ctrl->csi_params[res]) {
- s_ctrl->curr_csi_params = s_ctrl->csi_params[res];
- s_ctrl->curr_csi_params->csid_params.lane_assign =
- s_ctrl->sensordata->sensor_platform_info->
- csi_lane_params->csi_lane_assign;
- s_ctrl->curr_csi_params->csiphy_params.lane_mask =
- s_ctrl->sensordata->sensor_platform_info->
- csi_lane_params->csi_lane_mask;
- v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
- NOTIFY_CSID_CFG,
- &s_ctrl->curr_csi_params->csid_params);
- mb();
- v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
- NOTIFY_CSIPHY_CFG,
- &s_ctrl->curr_csi_params->csiphy_params);
- mb();
- msleep(20);
- }
-
v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
NOTIFY_PCLK_CHANGE, &s_ctrl->msm_sensor_reg->
output_settings[res].op_pixel_clk);
- s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
- msleep(30);
}
return rc;
}
@@ -385,21 +358,10 @@
return rc;
}
-int32_t msm_sensor_release(struct msm_sensor_ctrl_t *s_ctrl)
+static int32_t msm_sensor_release(struct msm_sensor_ctrl_t *s_ctrl)
{
- long fps = 0;
- uint32_t delay = 0;
CDBG("%s called\n", __func__);
s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
- if (s_ctrl->curr_res != MSM_SENSOR_INVALID_RES) {
- fps = s_ctrl->msm_sensor_reg->
- output_settings[s_ctrl->curr_res].vt_pixel_clk /
- s_ctrl->curr_frame_length_lines /
- s_ctrl->curr_line_length_pclk;
- delay = 1000 / fps;
- CDBG("%s fps = %ld, delay = %d\n", __func__, fps, delay);
- msleep(delay);
- }
return 0;
}
@@ -418,7 +380,6 @@
case VIDIOC_MSM_SENSOR_CSID_INFO: {
struct msm_sensor_csi_info *csi_info =
(struct msm_sensor_csi_info *)arg;
- s_ctrl->csid_version = csi_info->csid_version;
s_ctrl->is_csic = csi_info->is_csic;
return 0;
}
@@ -430,14 +391,20 @@
int32_t msm_sensor_get_csi_params(struct msm_sensor_ctrl_t *s_ctrl,
struct csi_lane_params_t *sensor_output_info)
{
- sensor_output_info->csi_lane_assign = s_ctrl->sensordata->
- sensor_platform_info->csi_lane_params->csi_lane_assign;
- sensor_output_info->csi_lane_mask = s_ctrl->sensordata->
- sensor_platform_info->csi_lane_params->csi_lane_mask;
+ uint8_t index;
+ struct msm_camera_csi_lane_params *csi_lane_params =
+ s_ctrl->sensordata->sensor_platform_info->csi_lane_params;
+ if (csi_lane_params) {
+ sensor_output_info->csi_lane_assign = csi_lane_params->
+ csi_lane_assign;
+ sensor_output_info->csi_lane_mask = csi_lane_params->
+ csi_lane_mask;
+ }
sensor_output_info->csi_if = s_ctrl->sensordata->csi_if;
- sensor_output_info->csid_core = s_ctrl->sensordata->
- pdata[0].csid_core;
- sensor_output_info->csid_version = s_ctrl->csid_version;
+ for (index = 0; index < sensor_output_info->csi_if; index++)
+ sensor_output_info->csid_core[index] = s_ctrl->sensordata->
+ pdata[index].csid_core;
+
return 0;
}
@@ -450,9 +417,9 @@
sizeof(struct sensor_cfg_data)))
return -EFAULT;
mutex_lock(s_ctrl->msm_sensor_mutex);
- CDBG("msm_sensor_config: cfgtype = %d\n",
- cdata.cfgtype);
- switch (cdata.cfgtype) {
+ CDBG("%s:%d %s cfgtype = %d\n", __func__, __LINE__,
+ s_ctrl->sensordata->sensor_name, cdata.cfgtype);
+ switch (cdata.cfgtype) {
case CFG_SET_FPS:
case CFG_SET_PICT_FPS:
if (s_ctrl->func_tbl->
@@ -478,8 +445,6 @@
s_ctrl,
cdata.cfg.exp_gain.gain,
cdata.cfg.exp_gain.line);
- s_ctrl->prev_gain = cdata.cfg.exp_gain.gain;
- s_ctrl->prev_line = cdata.cfg.exp_gain.line;
break;
case CFG_SET_PICT_EXP_GAIN:
@@ -573,6 +538,22 @@
rc = -EFAULT;
break;
+ case CFG_POWER_UP:
+ pr_err("%s calling power up\n", __func__);
+ if (s_ctrl->func_tbl->sensor_power_up)
+ rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
+ else
+ rc = -EFAULT;
+ break;
+
+ case CFG_POWER_DOWN:
+ if (s_ctrl->func_tbl->sensor_power_down)
+ rc = s_ctrl->func_tbl->sensor_power_down(
+ s_ctrl);
+ else
+ rc = -EFAULT;
+ break;
+
default:
rc = -EFAULT;
break;
@@ -583,10 +564,15 @@
return rc;
}
-static struct msm_cam_clk_info cam_clk_info[] = {
+static struct msm_cam_clk_info cam_8960_clk_info[] = {
{"cam_clk", MSM_SENSOR_MCLK_24HZ},
};
+static struct msm_cam_clk_info cam_8974_clk_info[] = {
+ {"cam_src_clk", 19200000},
+ {"cam_clk", -1},
+};
+
int32_t msm_sensor_enable_i2c_mux(struct msm_camera_i2c_conf *i2c_conf)
{
struct v4l2_subdev *i2c_mux_sd =
@@ -620,8 +606,8 @@
return -ENOMEM;
}
- rc = of_property_read_u32(of_node, "flash_type", &val);
- CDBG("%s flash_type %d, rc %d\n", __func__, val, rc);
+ rc = of_property_read_u32(of_node, "qcom,flash-type", &val);
+ CDBG("%s qcom,flash-type %d, rc %d\n", __func__, val, rc);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
goto ERROR;
@@ -640,8 +626,8 @@
uint32_t count = 0;
uint32_t *val_array = NULL;
- count = of_property_count_strings(of_node, "cam_vreg_name");
- CDBG("%s cam_vreg_name count %d\n", __func__, count);
+ 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;
@@ -655,8 +641,8 @@
pinfo->num_vreg = count;
for (i = 0; i < count; i++) {
- rc = of_property_read_string_index(of_node, "cam_vreg_name", i,
- &pinfo->cam_vreg[i].reg_name);
+ rc = of_property_read_string_index(of_node,
+ "qcom,cam-vreg-name", i, &pinfo->cam_vreg[i].reg_name);
CDBG("%s reg_name[%d] = %s\n", __func__, i,
pinfo->cam_vreg[i].reg_name);
if (rc < 0) {
@@ -672,8 +658,8 @@
goto ERROR1;
}
- rc = of_property_read_u32_array(of_node, "cam_vreg_type", val_array,
- count);
+ rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-type",
+ val_array, count);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
goto ERROR2;
@@ -684,7 +670,7 @@
pinfo->cam_vreg[i].type);
}
- rc = of_property_read_u32_array(of_node, "cam_vreg_min_voltage",
+ rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-min-voltage",
val_array, count);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
@@ -696,7 +682,7 @@
i, pinfo->cam_vreg[i].min_voltage);
}
- rc = of_property_read_u32_array(of_node, "cam_vreg_max_voltage",
+ rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-max-voltage",
val_array, count);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
@@ -708,8 +694,8 @@
i, pinfo->cam_vreg[i].max_voltage);
}
- rc = of_property_read_u32_array(of_node, "cam_vreg_op_mode", val_array,
- count);
+ rc = of_property_read_u32_array(of_node, "qcom,cam-vreg-op-mode",
+ val_array, count);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
goto ERROR2;
@@ -731,19 +717,25 @@
}
static int32_t msm_sensor_init_gpio_common_tbl_data(struct device_node *of_node,
- struct msm_camera_gpio_conf *gconf)
+ 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, "gpio_common_tbl_num", &count))
+ if (!of_get_property(of_node, "qcom,gpio-common-tbl-num", &count))
return 0;
count /= sizeof(uint32_t);
-
- if (!count)
+ if (!count) {
+ pr_err("%s qcom,gpio-common-tbl-num 0\n", __func__);
return 0;
+ } else if (count > gpio_array_size) {
+ pr_err("%s gpio common tbl size exceeds gpio array\n",
+ __func__);
+ return -EFAULT;
+ }
val_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
if (!val_array) {
@@ -760,19 +752,24 @@
}
gconf->cam_gpio_common_tbl_size = count;
- rc = of_property_read_u32_array(of_node, "gpio_common_tbl_num",
+ rc = of_property_read_u32_array(of_node, "qcom,gpio-common-tbl-num",
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_common_tbl[i].gpio = val_array[i];
+ if (val_array[i] >= gpio_array_size) {
+ pr_err("%s gpio common tbl index %d invalid\n",
+ __func__, val_array[i]);
+ return -EINVAL;
+ }
+ gconf->cam_gpio_common_tbl[i].gpio = gpio_array[val_array[i]];
CDBG("%s cam_gpio_common_tbl[%d].gpio = %d\n", __func__, i,
gconf->cam_gpio_common_tbl[i].gpio);
}
- rc = of_property_read_u32_array(of_node, "gpio_common_tbl_flags",
+ rc = of_property_read_u32_array(of_node, "qcom,gpio-common-tbl-flags",
val_array, count);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
@@ -786,7 +783,7 @@
for (i = 0; i < count; i++) {
rc = of_property_read_string_index(of_node,
- "gpio_common_tbl_label", i,
+ "qcom,gpio-common-tbl-label", i,
&gconf->cam_gpio_common_tbl[i].label);
CDBG("%s cam_gpio_common_tbl[%d].label = %s\n", __func__, i,
gconf->cam_gpio_common_tbl[i].label);
@@ -808,19 +805,21 @@
}
static int32_t msm_sensor_init_gpio_req_tbl_data(struct device_node *of_node,
- struct msm_camera_gpio_conf *gconf)
+ 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, "gpio_req_tbl_num", &count))
+ if (!of_get_property(of_node, "qcom,gpio-req-tbl-num", &count))
return 0;
count /= sizeof(uint32_t);
-
- if (!count)
+ 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) {
@@ -837,19 +836,24 @@
}
gconf->cam_gpio_req_tbl_size = count;
- rc = of_property_read_u32_array(of_node, "gpio_req_tbl_num",
+ 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++) {
- gconf->cam_gpio_req_tbl[i].gpio = val_array[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, "gpio_req_tbl_flags",
+ 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__);
@@ -863,7 +867,7 @@
for (i = 0; i < count; i++) {
rc = of_property_read_string_index(of_node,
- "gpio_req_tbl_label", i,
+ "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);
@@ -885,19 +889,21 @@
}
static int32_t msm_sensor_init_gpio_set_tbl_data(struct device_node *of_node,
- struct msm_camera_gpio_conf *gconf)
+ 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, "gpio_set_tbl_num", &count))
+ if (!of_get_property(of_node, "qcom,gpio-set-tbl-num", &count))
return 0;
count /= sizeof(uint32_t);
-
- if (!count)
+ if (!count) {
+ pr_err("%s qcom,gpio-set-tbl-num 0\n", __func__);
return 0;
+ }
val_array = kzalloc(sizeof(uint32_t) * count, GFP_KERNEL);
if (!val_array) {
@@ -914,19 +920,24 @@
}
gconf->cam_gpio_set_tbl_size = count;
- rc = of_property_read_u32_array(of_node, "gpio_set_tbl_num",
+ rc = of_property_read_u32_array(of_node, "qcom,gpio-set-tbl-num",
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_set_tbl[i].gpio = val_array[i];
+ if (val_array[i] >= gpio_array_size) {
+ pr_err("%s gpio set tbl index %d invalid\n",
+ __func__, val_array[i]);
+ return -EINVAL;
+ }
+ gconf->cam_gpio_set_tbl[i].gpio = gpio_array[val_array[i]];
CDBG("%s cam_gpio_set_tbl[%d].gpio = %d\n", __func__, i,
gconf->cam_gpio_set_tbl[i].gpio);
}
- rc = of_property_read_u32_array(of_node, "gpio_set_tbl_flags",
+ rc = of_property_read_u32_array(of_node, "qcom,gpio-set-tbl-flags",
val_array, count);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
@@ -938,7 +949,7 @@
gconf->cam_gpio_set_tbl[i].flags);
}
- rc = of_property_read_u32_array(of_node, "gpio_set_tbl_delay",
+ rc = of_property_read_u32_array(of_node, "qcom,gpio-set-tbl-delay",
val_array, count);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
@@ -962,7 +973,8 @@
}
static int32_t msm_sensor_init_gpio_tlmm_tbl_data(struct device_node *of_node,
- struct msm_camera_gpio_conf *gconf)
+ 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;
@@ -1013,7 +1025,12 @@
goto ERROR4;
}
for (i = 0; i < count; i++) {
- tlmm_cfg[i].gpio = val_array[i];
+ if (val_array[i] >= gpio_array_size) {
+ pr_err("%s gpio set tbl index %d invalid\n",
+ __func__, val_array[i]);
+ return -EINVAL;
+ }
+ tlmm_cfg[i].gpio = gpio_array[val_array[i]];
CDBG("%s tlmm_cfg[%d].gpio = %d\n", __func__, i,
tlmm_cfg[i].gpio);
}
@@ -1089,8 +1106,8 @@
struct msm_camera_sensor_platform_info *pinfo =
sensordata->sensor_platform_info;
- rc = of_property_read_u32(of_node, "csi_if", &count);
- CDBG("%s csi_if %d, rc %d\n", __func__, count, rc);
+ rc = of_property_read_u32(of_node, "qcom,csi-if", &count);
+ CDBG("%s qcom,csi-if %d, rc %d\n", __func__, count, rc);
if (rc < 0 || !count)
return rc;
sensordata->csi_if = count;
@@ -1109,25 +1126,27 @@
goto ERROR1;
}
- rc = of_property_read_u32_array(of_node, "csid_core", val_array, count);
+ rc = of_property_read_u32_array(of_node, "qcom,csid-core", val_array,
+ count);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
goto ERROR2;
}
for (i = 0; i < count; i++) {
sensordata->pdata[i].csid_core = val_array[i];
- CDBG("%s csid_core[%d].csid_core = %d\n", __func__, i,
+ CDBG("%s csi_data[%d].csid_core = %d\n", __func__, i,
sensordata->pdata[i].csid_core);
}
- rc = of_property_read_u32_array(of_node, "is_vpe", val_array, count);
+ rc = of_property_read_u32_array(of_node, "qcom,is-vpe", val_array,
+ count);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
goto ERROR2;
}
for (i = 0; i < count; i++) {
sensordata->pdata[i].is_vpe = val_array[i];
- CDBG("%s csid_core[%d].is_vpe = %d\n", __func__, i,
+ CDBG("%s csi_data[%d].is_vpe = %d\n", __func__, i,
sensordata->pdata[i].is_vpe);
}
@@ -1139,16 +1158,16 @@
goto ERROR2;
}
- rc = of_property_read_u32(of_node, "csi_lane_assign", &val);
- CDBG("%s csi_lane_assign %x, rc %d\n", __func__, val, rc);
+ rc = of_property_read_u32(of_node, "qcom,csi-lane-assign", &val);
+ CDBG("%s qcom,csi-lane-assign %x, rc %d\n", __func__, val, rc);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
goto ERROR3;
}
pinfo->csi_lane_params->csi_lane_assign = val;
- rc = of_property_read_u32(of_node, "csi_lane_mask", &val);
- CDBG("%s csi_lane_mask %x, rc %d\n", __func__, val, rc);
+ rc = of_property_read_u32(of_node, "qcom,csi-lane-mask", &val);
+ CDBG("%s qcom,csi-lane-mask %x, rc %d\n", __func__, val, rc);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
goto ERROR3;
@@ -1172,8 +1191,8 @@
int32_t rc = 0;
uint32_t val = 0;
- rc = of_property_read_u32(of_node, "actuator_cam_name", &val);
- CDBG("%s actuator_cam_name %d, rc %d\n", __func__, val, rc);
+ rc = of_property_read_u32(of_node, "qcom,actuator-cam-name", &val);
+ CDBG("%s qcom,actuator-cam-name %d, rc %d\n", __func__, val, rc);
if (rc < 0)
return 0;
@@ -1187,13 +1206,13 @@
sensordata->actuator_info->cam_name = val;
- rc = of_property_read_u32(of_node, "actuator_vcm_pwd", &val);
- CDBG("%s actuator_vcm_pwd %d, rc %d\n", __func__, val, rc);
+ rc = of_property_read_u32(of_node, "qcom,actuator-vcm-pwd", &val);
+ CDBG("%s qcom,actuator-vcm-pwd %d, rc %d\n", __func__, val, rc);
if (!rc)
sensordata->actuator_info->vcm_pwd = val;
- rc = of_property_read_u32(of_node, "actuator_vcm_enable", &val);
- CDBG("%s actuator_vcm_enable %d, rc %d\n", __func__, val, rc);
+ rc = of_property_read_u32(of_node, "qcom,actuator-vcm-enable", &val);
+ CDBG("%s qcom,actuator-vcm-enable %d, rc %d\n", __func__, val, rc);
if (!rc)
sensordata->actuator_info->vcm_enable = val;
@@ -1205,12 +1224,14 @@
static int32_t msm_sensor_init_sensor_data(struct platform_device *pdev,
struct msm_sensor_ctrl_t *s_ctrl)
{
- int32_t rc = 0;
+ int32_t rc = 0, i = 0;
uint32_t val = 0;
struct device_node *of_node = pdev->dev.of_node;
struct msm_camera_sensor_platform_info *pinfo = NULL;
struct msm_camera_gpio_conf *gconf = NULL;
struct msm_camera_sensor_info *sensordata = NULL;
+ uint16_t *gpio_array = NULL;
+ uint16_t gpio_array_size = 0;
s_ctrl->sensordata = kzalloc(sizeof(struct msm_camera_sensor_info),
GFP_KERNEL);
@@ -1220,25 +1241,26 @@
}
sensordata = s_ctrl->sensordata;
- rc = of_property_read_string(of_node, "sensor_name",
+
+ rc = of_property_read_string(of_node, "qcom,sensor-name",
&sensordata->sensor_name);
- CDBG("%s sensor_name %s, rc %d\n", __func__,
+ CDBG("%s qcom,sensor-name %s, rc %d\n", __func__,
sensordata->sensor_name, rc);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
goto ERROR1;
}
- rc = of_property_read_u32(of_node, "camera_type", &val);
- CDBG("%s camera_type %d, rc %d\n", __func__, val, rc);
+ rc = of_property_read_u32(of_node, "qcom,camera-type", &val);
+ CDBG("%s qcom,camera-type %d, rc %d\n", __func__, val, rc);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
goto ERROR1;
}
sensordata->camera_type = val;
- rc = of_property_read_u32(of_node, "sensor_type", &val);
- CDBG("%s sensor_type %d, rc %d\n", __func__, val, rc);
+ rc = of_property_read_u32(of_node, "qcom,sensor-type", &val);
+ CDBG("%s qcom,sensor-type %d, rc %d\n", __func__, val, rc);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
goto ERROR1;
@@ -1261,8 +1283,10 @@
pinfo = sensordata->sensor_platform_info;
- rc = of_property_read_u32(of_node, "mount_angle", &pinfo->mount_angle);
- CDBG("%s mount_angle %d, rc %d\n", __func__, pinfo->mount_angle, rc);
+ rc = of_property_read_u32(of_node, "qcom,mount-angle",
+ &pinfo->mount_angle);
+ CDBG("%s qcom,mount-angle %d, rc %d\n", __func__, pinfo->mount_angle,
+ rc);
if (rc < 0) {
/* Set default mount angle */
pinfo->mount_angle = 0;
@@ -1289,7 +1313,8 @@
goto ERROR4;
}
gconf = pinfo->gpio_conf;
- rc = of_property_read_u32(of_node, "gpio_no_mux", &gconf->gpio_no_mux);
+ rc = of_property_read_u32(of_node, "qcom,gpio-no-mux",
+ &gconf->gpio_no_mux);
CDBG("%s gconf->gpio_no_mux %d, rc %d\n", __func__,
gconf->gpio_no_mux, rc);
if (rc < 0) {
@@ -1297,36 +1322,57 @@
goto ERROR5;
}
- rc = msm_sensor_init_gpio_common_tbl_data(of_node, gconf);
- if (rc < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto ERROR5;
- }
+ gpio_array_size = of_gpio_count(of_node);
+ CDBG("%s gpio count %d\n", __func__, gpio_array_size);
- rc = msm_sensor_init_gpio_req_tbl_data(of_node, gconf);
- if (rc < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto ERROR6;
- }
+ 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 ERROR5;
+ }
+ 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_sensor_init_gpio_set_tbl_data(of_node, gconf);
- if (rc < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto ERROR7;
- }
+ rc = msm_sensor_init_gpio_common_tbl_data(of_node, gconf,
+ gpio_array, gpio_array_size);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR5;
+ }
- rc = msm_sensor_init_gpio_tlmm_tbl_data(of_node, gconf);
- if (rc < 0) {
- pr_err("%s failed %d\n", __func__, __LINE__);
- goto ERROR8;
- }
+ rc = msm_sensor_init_gpio_req_tbl_data(of_node, gconf,
+ gpio_array, gpio_array_size);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR6;
+ }
+ rc = msm_sensor_init_gpio_set_tbl_data(of_node, gconf,
+ gpio_array, gpio_array_size);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR7;
+ }
+
+ rc = msm_sensor_init_gpio_tlmm_tbl_data(of_node, gconf,
+ gpio_array, gpio_array_size);
+ if (rc < 0) {
+ pr_err("%s failed %d\n", __func__, __LINE__);
+ goto ERROR8;
+ }
+ }
rc = msm_sensor_init_actuator_data(of_node, sensordata);
if (rc < 0) {
pr_err("%s failed %d\n", __func__, __LINE__);
goto ERROR9;
}
+ kfree(gpio_array);
return rc;
ERROR9:
@@ -1355,6 +1401,7 @@
kfree(s_ctrl->sensordata->flash_data);
ERROR1:
kfree(s_ctrl->sensordata);
+ kfree(gpio_array);
return rc;
}
@@ -1386,7 +1433,11 @@
{
int32_t rc = 0;
struct msm_camera_sensor_info *data = s_ctrl->sensordata;
- CDBG("%s: %d\n", __func__, __LINE__);
+ struct device *dev = NULL;
+ if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE)
+ dev = &s_ctrl->pdev->dev;
+ else
+ dev = &s_ctrl->sensor_i2c_client->client->dev;
s_ctrl->reg_ptr = kzalloc(sizeof(struct regulator *)
* data->sensor_platform_info->num_vreg, GFP_KERNEL);
if (!s_ctrl->reg_ptr) {
@@ -1401,19 +1452,23 @@
goto request_gpio_failed;
}
- rc = msm_camera_config_vreg(&s_ctrl->sensor_i2c_client->client->dev,
- s_ctrl->sensordata->sensor_platform_info->cam_vreg,
- s_ctrl->sensordata->sensor_platform_info->num_vreg,
- s_ctrl->reg_ptr, 1);
+ rc = msm_camera_config_vreg(dev,
+ s_ctrl->sensordata->sensor_platform_info->cam_vreg,
+ s_ctrl->sensordata->sensor_platform_info->num_vreg,
+ s_ctrl->vreg_seq,
+ s_ctrl->num_vreg_seq,
+ s_ctrl->reg_ptr, 1);
if (rc < 0) {
pr_err("%s: regulator on failed\n", __func__);
goto config_vreg_failed;
}
- rc = msm_camera_enable_vreg(&s_ctrl->sensor_i2c_client->client->dev,
- s_ctrl->sensordata->sensor_platform_info->cam_vreg,
- s_ctrl->sensordata->sensor_platform_info->num_vreg,
- s_ctrl->reg_ptr, 1);
+ rc = msm_camera_enable_vreg(dev,
+ s_ctrl->sensordata->sensor_platform_info->cam_vreg,
+ s_ctrl->sensordata->sensor_platform_info->num_vreg,
+ s_ctrl->vreg_seq,
+ s_ctrl->num_vreg_seq,
+ s_ctrl->reg_ptr, 1);
if (rc < 0) {
pr_err("%s: enable regulator failed\n", __func__);
goto enable_vreg_failed;
@@ -1425,17 +1480,33 @@
goto config_gpio_failed;
}
- if (s_ctrl->clk_rate != 0)
- cam_clk_info->clk_rate = s_ctrl->clk_rate;
+ if (s_ctrl->sensor_device_type == MSM_SENSOR_I2C_DEVICE) {
+ if (s_ctrl->clk_rate != 0)
+ cam_8960_clk_info->clk_rate = s_ctrl->clk_rate;
- rc = msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->dev,
- cam_clk_info, &s_ctrl->cam_clk, ARRAY_SIZE(cam_clk_info), 1);
- if (rc < 0) {
- pr_err("%s: clk enable failed\n", __func__);
- goto enable_clk_failed;
+ rc = msm_cam_clk_enable(dev, cam_8960_clk_info,
+ s_ctrl->cam_clk, ARRAY_SIZE(cam_8960_clk_info), 1);
+ if (rc < 0) {
+ pr_err("%s: clk enable failed\n", __func__);
+ goto enable_clk_failed;
+ }
+ } else {
+ rc = msm_cam_clk_enable(dev, cam_8974_clk_info,
+ s_ctrl->cam_clk, ARRAY_SIZE(cam_8974_clk_info), 1);
+ if (rc < 0) {
+ pr_err("%s: clk enable failed\n", __func__);
+ goto enable_clk_failed;
+ }
}
- usleep_range(1000, 2000);
+ if (!s_ctrl->power_seq_delay)
+ usleep_range(1000, 2000);
+ else if (s_ctrl->power_seq_delay < 20)
+ usleep_range((s_ctrl->power_seq_delay * 1000),
+ ((s_ctrl->power_seq_delay * 1000) + 1000));
+ else
+ msleep(s_ctrl->power_seq_delay);
+
if (data->sensor_platform_info->ext_power_ctrl != NULL)
data->sensor_platform_info->ext_power_ctrl(1);
@@ -1443,7 +1514,7 @@
data->sensor_platform_info->i2c_conf->use_i2c_mux)
msm_sensor_enable_i2c_mux(data->sensor_platform_info->i2c_conf);
- if (s_ctrl->sensor_i2c_client->cci_client) {
+ if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE) {
rc = msm_sensor_cci_util(s_ctrl->sensor_i2c_client,
MSM_CCI_INIT);
if (rc < 0) {
@@ -1451,6 +1522,7 @@
goto cci_init_failed;
}
}
+ s_ctrl->curr_res = MSM_SENSOR_INVALID_RES;
return rc;
cci_init_failed:
@@ -1461,15 +1533,19 @@
enable_clk_failed:
msm_camera_config_gpio_table(data, 0);
config_gpio_failed:
- msm_camera_enable_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+ msm_camera_enable_vreg(dev,
s_ctrl->sensordata->sensor_platform_info->cam_vreg,
s_ctrl->sensordata->sensor_platform_info->num_vreg,
+ s_ctrl->vreg_seq,
+ s_ctrl->num_vreg_seq,
s_ctrl->reg_ptr, 0);
enable_vreg_failed:
- msm_camera_config_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+ msm_camera_config_vreg(dev,
s_ctrl->sensordata->sensor_platform_info->cam_vreg,
s_ctrl->sensordata->sensor_platform_info->num_vreg,
+ s_ctrl->vreg_seq,
+ s_ctrl->num_vreg_seq,
s_ctrl->reg_ptr, 0);
config_vreg_failed:
msm_camera_request_gpio_table(data, 0);
@@ -1481,8 +1557,12 @@
int32_t msm_sensor_power_down(struct msm_sensor_ctrl_t *s_ctrl)
{
struct msm_camera_sensor_info *data = s_ctrl->sensordata;
- CDBG("%s\n", __func__);
- if (s_ctrl->sensor_i2c_client->cci_client) {
+ struct device *dev = NULL;
+ if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE)
+ dev = &s_ctrl->pdev->dev;
+ else
+ dev = &s_ctrl->sensor_i2c_client->client->dev;
+ if (s_ctrl->sensor_device_type == MSM_SENSOR_PLATFORM_DEVICE) {
msm_sensor_cci_util(s_ctrl->sensor_i2c_client,
MSM_CCI_RELEASE);
}
@@ -1494,19 +1574,28 @@
if (data->sensor_platform_info->ext_power_ctrl != NULL)
data->sensor_platform_info->ext_power_ctrl(0);
- msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->dev,
- cam_clk_info, &s_ctrl->cam_clk, ARRAY_SIZE(cam_clk_info), 0);
+ if (s_ctrl->sensor_device_type == MSM_SENSOR_I2C_DEVICE)
+ msm_cam_clk_enable(dev, cam_8960_clk_info, s_ctrl->cam_clk,
+ ARRAY_SIZE(cam_8960_clk_info), 0);
+ else
+ msm_cam_clk_enable(dev, cam_8974_clk_info, s_ctrl->cam_clk,
+ ARRAY_SIZE(cam_8974_clk_info), 0);
msm_camera_config_gpio_table(data, 0);
- msm_camera_enable_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+ msm_camera_enable_vreg(dev,
s_ctrl->sensordata->sensor_platform_info->cam_vreg,
s_ctrl->sensordata->sensor_platform_info->num_vreg,
+ s_ctrl->vreg_seq,
+ s_ctrl->num_vreg_seq,
s_ctrl->reg_ptr, 0);
- msm_camera_config_vreg(&s_ctrl->sensor_i2c_client->client->dev,
+ msm_camera_config_vreg(dev,
s_ctrl->sensordata->sensor_platform_info->cam_vreg,
s_ctrl->sensordata->sensor_platform_info->num_vreg,
+ s_ctrl->vreg_seq,
+ s_ctrl->num_vreg_seq,
s_ctrl->reg_ptr, 0);
msm_camera_request_gpio_table(data, 0);
kfree(s_ctrl->reg_ptr);
+ s_ctrl->curr_res = MSM_SENSOR_INVALID_RES;
return 0;
}
@@ -1524,7 +1613,7 @@
return rc;
}
- CDBG("%s msm_sensor id: %x, exp id: %x\n", __func__, chipid,
+ CDBG("%s: read id: %x expected id %x:\n", __func__, chipid,
s_ctrl->sensor_id_info->sensor_id);
if (chipid != s_ctrl->sensor_id_info->sensor_id) {
pr_err("msm_sensor_match_id chip id doesnot match\n");
@@ -1533,11 +1622,6 @@
return rc;
}
-struct msm_sensor_ctrl_t *get_sctrl(struct v4l2_subdev *sd)
-{
- return container_of(sd, struct msm_sensor_ctrl_t, sensor_v4l2_subdev);
-}
-
int32_t msm_sensor_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -1552,6 +1636,7 @@
}
s_ctrl = (struct msm_sensor_ctrl_t *)(id->driver_data);
+ s_ctrl->sensor_device_type = MSM_SENSOR_I2C_DEVICE;
if (s_ctrl->sensor_i2c_client != NULL) {
s_ctrl->sensor_i2c_client->client = client;
if (s_ctrl->sensor_i2c_addr != 0)
@@ -1583,6 +1668,10 @@
if (rc < 0)
goto probe_fail;
+ if (!s_ctrl->wait_num_frames)
+ s_ctrl->wait_num_frames = 1 * Q10;
+
+ pr_err("%s %s probe succeeded\n", __func__, client->name);
snprintf(s_ctrl->sensor_v4l2_subdev.name,
sizeof(s_ctrl->sensor_v4l2_subdev.name), "%s", id->name);
v4l2_i2c_subdev_init(&s_ctrl->sensor_v4l2_subdev, client,
@@ -1633,6 +1722,7 @@
return rc;
}
}
+ s_ctrl->sensor_device_type = MSM_SENSOR_PLATFORM_DEVICE;
s_ctrl->sensor_i2c_client->cci_client = kzalloc(sizeof(
struct msm_camera_cci_client), GFP_KERNEL);
if (!s_ctrl->sensor_i2c_client->cci_client) {
@@ -1658,7 +1748,7 @@
s_ctrl->sensor_i2c_client->cci_client->cci_i2c_master = MASTER_0;
s_ctrl->sensor_i2c_client->cci_client->sid =
s_ctrl->sensor_i2c_addr >> 1;
- s_ctrl->sensor_i2c_client->cci_client->retries = 0;
+ s_ctrl->sensor_i2c_client->cci_client->retries = 3;
s_ctrl->sensor_i2c_client->cci_client->id_map = 0;
rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
diff --git a/drivers/media/video/msm/sensors/msm_sensor.h b/drivers/media/video/msm/sensors/msm_sensor.h
index 64d19e6..7dd0602 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.h
+++ b/drivers/media/video/msm/sensors/msm_sensor.h
@@ -24,185 +24,14 @@
#include <linux/uaccess.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <mach/camera.h>
-#include <mach/gpio.h>
#include <media/msm_camera.h>
#include <media/v4l2-subdev.h>
#include "msm_camera_i2c.h"
#include "msm_camera_eeprom.h"
-#define Q8 0x00000100
-#define Q10 0x00000400
-
-#define MSM_SENSOR_MCLK_8HZ 8000000
-#define MSM_SENSOR_MCLK_16HZ 16000000
-#define MSM_SENSOR_MCLK_24HZ 24000000
-
-struct gpio_tlmm_cfg {
- uint32_t gpio;
- uint32_t dir;
- uint32_t pull;
- uint32_t drvstr;
-};
-
-enum msm_sensor_reg_update {
- /* Sensor egisters that need to be updated during initialization */
- MSM_SENSOR_REG_INIT,
- /* Sensor egisters that needs periodic I2C writes */
- MSM_SENSOR_UPDATE_PERIODIC,
- /* All the sensor Registers will be updated */
- MSM_SENSOR_UPDATE_ALL,
- /* Not valid update */
- MSM_SENSOR_UPDATE_INVALID
-};
-
-enum msm_sensor_cam_mode_t {
- MSM_SENSOR_MODE_2D_RIGHT,
- MSM_SENSOR_MODE_2D_LEFT,
- MSM_SENSOR_MODE_3D,
- MSM_SENSOR_MODE_INVALID
-};
-
-struct msm_sensor_output_reg_addr_t {
- uint16_t x_output;
- uint16_t y_output;
- uint16_t line_length_pclk;
- uint16_t frame_length_lines;
-};
-
-struct msm_sensor_id_info_t {
- uint16_t sensor_id_reg_addr;
- uint16_t sensor_id;
-};
-
-struct msm_sensor_exp_gain_info_t {
- uint16_t coarse_int_time_addr;
- uint16_t global_gain_addr;
- uint16_t vert_offset;
-};
-
-struct msm_sensor_reg_t {
- enum msm_camera_i2c_data_type default_data_type;
- struct msm_camera_i2c_reg_conf *start_stream_conf;
- uint8_t start_stream_conf_size;
- struct msm_camera_i2c_reg_conf *stop_stream_conf;
- uint8_t stop_stream_conf_size;
- struct msm_camera_i2c_reg_conf *group_hold_on_conf;
- uint8_t group_hold_on_conf_size;
- struct msm_camera_i2c_reg_conf *group_hold_off_conf;
- uint8_t group_hold_off_conf_size;
- struct msm_camera_i2c_conf_array *init_settings;
- uint8_t init_size;
- struct msm_camera_i2c_conf_array *mode_settings;
- struct msm_camera_i2c_conf_array *no_effect_settings;
- struct msm_sensor_output_info_t *output_settings;
- uint8_t num_conf;
-};
-
-struct v4l2_subdev_info {
- enum v4l2_mbus_pixelcode code;
- enum v4l2_colorspace colorspace;
- uint16_t fmt;
- uint16_t order;
-};
-
-struct msm_sensor_ctrl_t;
-
-struct msm_sensor_v4l2_ctrl_info_t {
- uint32_t ctrl_id;
- int16_t min;
- int16_t max;
- int16_t step;
- struct msm_camera_i2c_enum_conf_array *enum_cfg_settings;
- int (*s_v4l2_ctrl) (struct msm_sensor_ctrl_t *,
- struct msm_sensor_v4l2_ctrl_info_t *, int);
-};
-
-struct msm_sensor_fn_t {
- void (*sensor_start_stream) (struct msm_sensor_ctrl_t *);
- void (*sensor_stop_stream) (struct msm_sensor_ctrl_t *);
- void (*sensor_group_hold_on) (struct msm_sensor_ctrl_t *);
- void (*sensor_group_hold_off) (struct msm_sensor_ctrl_t *);
-
- int32_t (*sensor_set_fps) (struct msm_sensor_ctrl_t *,
- struct fps_cfg *);
- int32_t (*sensor_write_exp_gain) (struct msm_sensor_ctrl_t *,
- uint16_t, uint32_t);
- int32_t (*sensor_write_snapshot_exp_gain) (struct msm_sensor_ctrl_t *,
- uint16_t, uint32_t);
- int32_t (*sensor_setting) (struct msm_sensor_ctrl_t *,
- int update_type, int rt);
- int32_t (*sensor_csi_setting) (struct msm_sensor_ctrl_t *,
- int update_type, int rt);
- int32_t (*sensor_set_sensor_mode)
- (struct msm_sensor_ctrl_t *, int, int);
- int32_t (*sensor_mode_init) (struct msm_sensor_ctrl_t *,
- int, struct sensor_init_cfg *);
- int32_t (*sensor_get_output_info) (struct msm_sensor_ctrl_t *,
- struct sensor_output_info_t *);
- int (*sensor_config) (struct msm_sensor_ctrl_t *, void __user *);
- int (*sensor_power_down)
- (struct msm_sensor_ctrl_t *);
- int (*sensor_power_up) (struct msm_sensor_ctrl_t *);
- int32_t (*sensor_match_id)(struct msm_sensor_ctrl_t *s_ctrl);
- int (*sensor_adjust_frame_lines)
- (struct msm_sensor_ctrl_t *s_ctrl, uint16_t res);
- int32_t (*sensor_get_csi_params)(struct msm_sensor_ctrl_t *,
- struct csi_lane_params_t *);
-};
-
-struct msm_sensor_csi_info {
- uint32_t csid_version;
- uint8_t is_csic;
-};
-
-enum msm_sensor_state {
- MSM_SENSOR_POWER_UP,
- MSM_SENSOR_POWER_DOWN,
-};
-
-struct msm_sensor_ctrl_t {
- struct msm_camera_sensor_info *sensordata;
- struct i2c_client *msm_sensor_client;
- struct i2c_driver *sensor_i2c_driver;
- struct msm_camera_i2c_client *sensor_i2c_client;
- struct platform_device *pdev;
- uint16_t sensor_i2c_addr;
-
- struct msm_sensor_output_reg_addr_t *sensor_output_reg_addr;
- struct msm_sensor_id_info_t *sensor_id_info;
- struct msm_sensor_exp_gain_info_t *sensor_exp_gain_info;
- struct msm_sensor_reg_t *msm_sensor_reg;
- struct msm_sensor_v4l2_ctrl_info_t *msm_sensor_v4l2_ctrl_info;
- uint16_t num_v4l2_ctrl;
- uint32_t csid_version;
- uint8_t is_csic;
-
- uint16_t curr_line_length_pclk;
- uint16_t curr_frame_length_lines;
- uint16_t prev_gain;
- uint16_t prev_line;
-
- uint32_t fps_divider;
- enum msm_sensor_resolution_t curr_res;
- enum msm_sensor_cam_mode_t cam_mode;
-
- struct mutex *msm_sensor_mutex;
- struct msm_camera_csi2_params *curr_csi_params;
- struct msm_camera_csi2_params **csi_params;
- struct msm_camera_csi_params **csic_params;
- struct msm_camera_csi_params *curr_csic_params;
-
- struct v4l2_subdev sensor_v4l2_subdev;
- struct v4l2_subdev_info *sensor_v4l2_subdev_info;
- uint8_t sensor_v4l2_subdev_info_size;
- struct v4l2_subdev_ops *sensor_v4l2_subdev_ops;
- struct msm_sensor_fn_t *func_tbl;
- struct regulator **reg_ptr;
- struct clk *cam_clk;
- long clk_rate;
- enum msm_sensor_state sensor_state;
-};
+#include "msm_sensor_common.h"
void msm_sensor_start_stream(struct msm_sensor_ctrl_t *s_ctrl);
void msm_sensor_stop_stream(struct msm_sensor_ctrl_t *s_ctrl);
@@ -256,11 +85,9 @@
int32_t msm_sensor_write_output_settings(struct msm_sensor_ctrl_t *s_ctrl,
uint16_t res);
-int32_t msm_sensor_adjust_frame_lines1(struct msm_sensor_ctrl_t *s_ctrl,
- uint16_t res);
+void msm_sensor_adjust_frame_lines1(struct msm_sensor_ctrl_t *s_ctrl);
-int32_t msm_sensor_adjust_frame_lines2(struct msm_sensor_ctrl_t *s_ctrl,
- uint16_t res);
+void msm_sensor_adjust_frame_lines2(struct msm_sensor_ctrl_t *s_ctrl);
int32_t msm_sensor_setting(struct msm_sensor_ctrl_t *s_ctrl,
int update_type, int res);
@@ -276,12 +103,11 @@
int32_t msm_sensor_get_csi_params(struct msm_sensor_ctrl_t *s_ctrl,
struct csi_lane_params_t *sensor_output_info);
+struct msm_sensor_ctrl_t *get_sctrl(struct v4l2_subdev *sd);
int32_t msm_sensor_free_sensor_data(struct msm_sensor_ctrl_t *s_ctrl);
-struct msm_sensor_ctrl_t *get_sctrl(struct v4l2_subdev *sd);
-
#define VIDIOC_MSM_SENSOR_CFG \
- _IOWR('V', BASE_VIDIOC_PRIVATE + 10, void __user *)
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 4, void __user *)
#define VIDIOC_MSM_SENSOR_RELEASE \
_IO('V', BASE_VIDIOC_PRIVATE + 11)
diff --git a/drivers/media/video/msm/sensors/msm_sensor_bayer.c b/drivers/media/video/msm/sensors/msm_sensor_bayer.c
new file mode 100644
index 0000000..c867867
--- /dev/null
+++ b/drivers/media/video/msm/sensors/msm_sensor_bayer.c
@@ -0,0 +1,906 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm_sensor_bayer.h"
+#include "msm.h"
+#include "msm_ispif.h"
+#include "msm_camera_i2c_mux.h"
+/*=============================================================*/
+
+long msm_sensor_bayer_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(sd);
+ void __user *argp = (void __user *)arg;
+ switch (cmd) {
+ case VIDIOC_MSM_SENSOR_CFG:
+ return s_ctrl->func_tbl->sensor_config(s_ctrl, argp);
+ case VIDIOC_MSM_SENSOR_RELEASE:
+ return 0;
+ case VIDIOC_MSM_SENSOR_CSID_INFO: {
+ struct msm_sensor_csi_info *csi_info =
+ (struct msm_sensor_csi_info *)arg;
+ s_ctrl->is_csic = csi_info->is_csic;
+ return 0;
+ }
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+int32_t msm_sensor_bayer_get_csi_params(struct msm_sensor_ctrl_t *s_ctrl,
+ struct csi_lane_params_t *sensor_output_info)
+{
+ uint8_t index;
+ struct msm_camera_csi_lane_params *csi_lane_params =
+ s_ctrl->sensordata->sensor_platform_info->csi_lane_params;
+ if (csi_lane_params) {
+ sensor_output_info->csi_lane_assign = csi_lane_params->
+ csi_lane_assign;
+ sensor_output_info->csi_lane_mask = csi_lane_params->
+ csi_lane_mask;
+ }
+ sensor_output_info->csi_if = s_ctrl->sensordata->csi_if;
+ for (index = 0; index < sensor_output_info->csi_if; index++)
+ sensor_output_info->csid_core[index] = s_ctrl->sensordata->
+ pdata[index].csid_core;
+
+ return 0;
+}
+
+int32_t msm_sensor_bayer_config(struct msm_sensor_ctrl_t *s_ctrl,
+ void __user *argp)
+{
+ struct sensor_cfg_data cdata;
+ long rc = 0;
+ if (copy_from_user(&cdata,
+ (void *)argp,
+ sizeof(struct sensor_cfg_data)))
+ return -EFAULT;
+ mutex_lock(s_ctrl->msm_sensor_mutex);
+ CDBG("%s:%d %s cfgtype = %d\n", __func__, __LINE__,
+ s_ctrl->sensordata->sensor_name, cdata.cfgtype);
+ switch (cdata.cfgtype) {
+ case CFG_WRITE_I2C_ARRAY: {
+ struct msm_camera_i2c_reg_setting conf_array;
+ struct msm_camera_i2c_reg_array *regs = NULL;
+
+ if (copy_from_user(&conf_array,
+ (void *)cdata.cfg.setting,
+ sizeof(struct msm_camera_i2c_reg_setting))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+
+ regs = kzalloc(conf_array.size * sizeof(
+ struct msm_camera_i2c_reg_array),
+ GFP_KERNEL);
+ if (!regs) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+
+ if (copy_from_user(regs, (void *)conf_array.reg_setting,
+ conf_array.size * sizeof(
+ struct msm_camera_i2c_reg_array))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ kfree(regs);
+ rc = -EFAULT;
+ break;
+ }
+
+ conf_array.reg_setting = regs;
+ rc = msm_camera_i2c_write_bayer_table(s_ctrl->sensor_i2c_client,
+ &conf_array);
+ kfree(regs);
+ break;
+ }
+ case CFG_READ_I2C_ARRAY: {
+ struct msm_camera_i2c_reg_setting conf_array;
+ struct msm_camera_i2c_reg_array *regs;
+ int index;
+
+ if (copy_from_user(&conf_array,
+ (void *)cdata.cfg.setting,
+ sizeof(struct msm_camera_i2c_reg_setting))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+
+ regs = kzalloc(conf_array.size * sizeof(
+ struct msm_camera_i2c_reg_array),
+ GFP_KERNEL);
+ if (!regs) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ kfree(regs);
+ break;
+ }
+
+ if (copy_from_user(regs, (void *)conf_array.reg_setting,
+ conf_array.size * sizeof(
+ struct msm_camera_i2c_reg_array))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ kfree(regs);
+ rc = -EFAULT;
+ break;
+ }
+
+ s_ctrl->sensor_i2c_client->addr_type = conf_array.addr_type;
+ for (index = 0; index < conf_array.size; index++) {
+ msm_camera_i2c_read(s_ctrl->sensor_i2c_client,
+ regs[index].reg_addr,
+ ®s[index].reg_data,
+ conf_array.data_type
+ );
+ }
+
+ if (copy_to_user(conf_array.reg_setting,
+ regs,
+ conf_array.size * sizeof(
+ struct msm_camera_i2c_reg_array))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ kfree(regs);
+ rc = -EFAULT;
+ break;
+ }
+ s_ctrl->sensor_i2c_client->addr_type = conf_array.addr_type;
+ kfree(regs);
+ break;
+ }
+ case CFG_PCLK_CHANGE: {
+ uint32_t pclk = cdata.cfg.pclk;
+ v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
+ NOTIFY_PCLK_CHANGE, &pclk);
+ break;
+ }
+ case CFG_GPIO_OP: {
+ struct msm_cam_gpio_operation gop;
+ if (copy_from_user(&gop,
+ (void *)cdata.cfg.setting,
+ sizeof(struct msm_cam_gpio_operation))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ }
+ switch (gop.op_type) {
+ case GPIO_GET_VALUE:
+ gop.value = gpio_get_value(gop.address);
+ if (copy_from_user((void *)cdata.cfg.setting,
+ &gop,
+ sizeof(struct msm_cam_gpio_operation))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+ break;
+ case GPIO_SET_VALUE:
+ gpio_set_value(gop.address, gop.value);
+ break;
+ case GPIO_SET_DIRECTION_INPUT:
+ gpio_direction_input(gop.address);
+ break;
+ case GPIO_SET_DIRECTION_OUTPUT:
+ gpio_direction_output(gop.address, gop.value);
+ break;
+ case GPIO_REQUEST:
+ gpio_request(gop.address, gop.tag);
+ break;
+ case GPIO_FREE:
+ gpio_free(gop.address);
+ break;
+ default:
+ break;
+ }
+
+ break;
+ }
+ case CFG_GET_CSI_PARAMS:
+ if (s_ctrl->func_tbl->sensor_get_csi_params == NULL) {
+ rc = -EFAULT;
+ break;
+ }
+ rc = s_ctrl->func_tbl->sensor_get_csi_params(
+ s_ctrl,
+ &cdata.cfg.csi_lane_params);
+
+ if (copy_to_user((void *)argp,
+ &cdata,
+ sizeof(struct sensor_cfg_data)))
+ rc = -EFAULT;
+ break;
+
+ case CFG_POWER_UP:
+ if (s_ctrl->func_tbl->sensor_power_up)
+ rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
+ else
+ rc = -EFAULT;
+ break;
+
+ case CFG_POWER_DOWN:
+ if (s_ctrl->func_tbl->sensor_power_down)
+ rc = s_ctrl->func_tbl->sensor_power_down(
+ s_ctrl);
+ else
+ rc = -EFAULT;
+ break;
+
+ case CFG_CONFIG_VREG_ARRAY: {
+ struct msm_camera_vreg_setting vreg_setting;
+ struct camera_vreg_t *cam_vreg = NULL;
+
+ if (copy_from_user(&vreg_setting,
+ (void *)cdata.cfg.setting,
+ sizeof(struct msm_camera_vreg_setting))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+
+ cam_vreg = kzalloc(vreg_setting.num_vreg * sizeof(
+ struct camera_vreg_t),
+ GFP_KERNEL);
+ if (!cam_vreg) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+
+ if (copy_from_user(cam_vreg, (void *)vreg_setting.cam_vreg,
+ vreg_setting.num_vreg * sizeof(
+ struct camera_vreg_t))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ kfree(cam_vreg);
+ rc = -EFAULT;
+ break;
+ }
+ rc = msm_camera_config_vreg(
+ &s_ctrl->sensor_i2c_client->client->dev,
+ cam_vreg,
+ vreg_setting.num_vreg,
+ NULL,
+ 0,
+ s_ctrl->reg_ptr,
+ vreg_setting.enable);
+ if (rc < 0) {
+ kfree(cam_vreg);
+ pr_err("%s: regulator on failed\n", __func__);
+ break;
+ }
+
+ rc = msm_camera_enable_vreg(
+ &s_ctrl->sensor_i2c_client->client->dev,
+ cam_vreg,
+ vreg_setting.num_vreg,
+ NULL,
+ 0,
+ s_ctrl->reg_ptr,
+ vreg_setting.enable);
+ if (rc < 0) {
+ kfree(cam_vreg);
+ pr_err("%s: enable regulator failed\n", __func__);
+ break;
+ }
+ kfree(cam_vreg);
+ break;
+ }
+ case CFG_CONFIG_CLK_ARRAY: {
+ struct msm_cam_clk_setting clk_setting;
+ struct msm_cam_clk_info *clk_info = NULL;
+
+ if (copy_from_user(&clk_setting,
+ (void *)cdata.cfg.setting,
+ sizeof(struct msm_camera_vreg_setting))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+
+ clk_info = kzalloc(clk_setting.num_clk_info * sizeof(
+ struct msm_cam_clk_info),
+ GFP_KERNEL);
+ if (!clk_info) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ break;
+ }
+
+ if (copy_from_user(clk_info, (void *)clk_setting.clk_info,
+ clk_setting.num_clk_info * sizeof(
+ struct msm_cam_clk_info))) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ kfree(clk_info);
+ rc = -EFAULT;
+ break;
+ }
+ rc = msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->dev,
+ clk_info, s_ctrl->cam_clk,
+ clk_setting.num_clk_info,
+ clk_setting.enable);
+ kfree(clk_info);
+ break;
+ }
+ case CFG_GET_EEPROM_DATA: {
+ if (copy_to_user((void *)cdata.cfg.eeprom_data.eeprom_data,
+ &s_ctrl->eeprom_data, s_ctrl->eeprom_data.length)) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ }
+ cdata.cfg.eeprom_data.index = s_ctrl->eeprom_data.length;
+ break;
+ }
+ default:
+ rc = -EFAULT;
+ break;
+ }
+
+ mutex_unlock(s_ctrl->msm_sensor_mutex);
+
+ return rc;
+}
+
+static struct msm_cam_clk_info cam_clk_info[] = {
+ {"cam_clk", MSM_SENSOR_MCLK_24HZ},
+};
+
+int32_t msm_sensor_bayer_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;
+}
+
+int32_t msm_sensor_bayer_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;
+}
+
+static struct msm_camera_power_seq_t sensor_power_seq[] = {
+ {REQUEST_GPIO, 0},
+ {REQUEST_VREG, 0},
+ {ENABLE_VREG, 0},
+ {ENABLE_GPIO, 0},
+ {CONFIG_CLK, 0},
+ {CONFIG_EXT_POWER_CTRL, 0},
+ {CONFIG_I2C_MUX, 0},
+};
+
+int32_t msm_sensor_bayer_power_up(struct msm_sensor_ctrl_t *s_ctrl)
+{
+ int32_t rc = 0, size = 0, index = 0;
+ struct msm_camera_sensor_info *data = s_ctrl->sensordata;
+ struct msm_camera_power_seq_t *power_seq = NULL;
+ CDBG("%s: %d\n", __func__, __LINE__);
+ if (s_ctrl->power_seq) {
+ power_seq = s_ctrl->power_seq;
+ size = s_ctrl->num_power_seq;
+ } else {
+ power_seq = &sensor_power_seq[0];
+ size = ARRAY_SIZE(sensor_power_seq);
+ }
+
+ s_ctrl->reg_ptr = kzalloc(sizeof(struct regulator *)
+ * data->sensor_platform_info->num_vreg, GFP_KERNEL);
+ if (!s_ctrl->reg_ptr) {
+ pr_err("%s: could not allocate mem for regulators\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ for (index = 0; index < size; index++) {
+ switch (power_seq[index].power_config) {
+ case REQUEST_GPIO:
+ rc = msm_camera_request_gpio_table(data, 1);
+ if (rc < 0) {
+ pr_err("%s: request gpio failed\n", __func__);
+ goto ERROR;
+ }
+ if (power_seq[index].delay)
+ usleep_range(power_seq[index].delay * 1000,
+ (power_seq[index].delay * 1000) + 1000);
+ break;
+ case REQUEST_VREG:
+ rc = msm_camera_config_vreg(
+ &s_ctrl->sensor_i2c_client->client->dev,
+ s_ctrl->sensordata->sensor_platform_info->
+ cam_vreg,
+ s_ctrl->sensordata->sensor_platform_info->
+ num_vreg,
+ s_ctrl->vreg_seq,
+ s_ctrl->num_vreg_seq,
+ s_ctrl->reg_ptr, 1);
+ if (rc < 0) {
+ pr_err("%s: regulator on failed\n", __func__);
+ goto ERROR;
+ }
+ if (power_seq[index].delay)
+ usleep_range(power_seq[index].delay * 1000,
+ (power_seq[index].delay * 1000) + 1000);
+ break;
+ case ENABLE_VREG:
+ rc = msm_camera_enable_vreg(
+ &s_ctrl->sensor_i2c_client->client->dev,
+ s_ctrl->sensordata->sensor_platform_info->
+ cam_vreg,
+ s_ctrl->sensordata->sensor_platform_info->
+ num_vreg,
+ s_ctrl->vreg_seq,
+ s_ctrl->num_vreg_seq,
+ s_ctrl->reg_ptr, 1);
+ if (rc < 0) {
+ pr_err("%s: enable regulator failed\n",
+ __func__);
+ goto ERROR;
+ }
+ if (power_seq[index].delay)
+ usleep_range(power_seq[index].delay * 1000,
+ (power_seq[index].delay * 1000) + 1000);
+ break;
+ case ENABLE_GPIO:
+ rc = msm_camera_config_gpio_table(data, 1);
+ if (rc < 0) {
+ pr_err("%s: config gpio failed\n", __func__);
+ goto ERROR;
+ }
+ if (power_seq[index].delay)
+ usleep_range(power_seq[index].delay * 1000,
+ (power_seq[index].delay * 1000) + 1000);
+ break;
+ case CONFIG_CLK:
+ if (s_ctrl->clk_rate != 0)
+ cam_clk_info->clk_rate = s_ctrl->clk_rate;
+
+ rc = msm_cam_clk_enable(
+ &s_ctrl->sensor_i2c_client->client->dev,
+ cam_clk_info, s_ctrl->cam_clk,
+ ARRAY_SIZE(cam_clk_info), 1);
+ if (rc < 0) {
+ pr_err("%s: clk enable failed\n", __func__);
+ goto ERROR;
+ }
+ if (power_seq[index].delay)
+ usleep_range(power_seq[index].delay * 1000,
+ (power_seq[index].delay * 1000) + 1000);
+ break;
+ case CONFIG_EXT_POWER_CTRL:
+ if (data->sensor_platform_info->ext_power_ctrl != NULL)
+ data->sensor_platform_info->ext_power_ctrl(1);
+ if (power_seq[index].delay)
+ usleep_range(power_seq[index].delay * 1000,
+ (power_seq[index].delay * 1000) + 1000);
+ break;
+ case CONFIG_I2C_MUX:
+ if (data->sensor_platform_info->i2c_conf &&
+ data->sensor_platform_info->i2c_conf->
+ use_i2c_mux)
+ msm_sensor_bayer_enable_i2c_mux(
+ data->sensor_platform_info->i2c_conf);
+ if (power_seq[index].delay)
+ usleep_range(power_seq[index].delay * 1000,
+ (power_seq[index].delay * 1000) + 1000);
+ break;
+ default:
+ pr_err("%s error power config %d\n", __func__,
+ power_seq[index].power_config);
+ rc = -EINVAL;
+ break;
+ }
+ }
+
+ return rc;
+
+ERROR:
+ for (index--; index >= 0; index--) {
+ switch (power_seq[index].power_config) {
+ case CONFIG_I2C_MUX:
+ if (data->sensor_platform_info->i2c_conf &&
+ data->sensor_platform_info->i2c_conf->
+ use_i2c_mux)
+ msm_sensor_bayer_disable_i2c_mux(
+ data->sensor_platform_info->i2c_conf);
+ break;
+ case CONFIG_EXT_POWER_CTRL:
+ if (data->sensor_platform_info->ext_power_ctrl != NULL)
+ data->sensor_platform_info->ext_power_ctrl(0);
+ break;
+ case CONFIG_CLK:
+ msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->
+ dev, cam_clk_info, s_ctrl->cam_clk,
+ ARRAY_SIZE(cam_clk_info), 0);
+ break;
+ case ENABLE_GPIO:
+ msm_camera_config_gpio_table(data, 0);
+ break;
+ case ENABLE_VREG:
+ msm_camera_enable_vreg(&s_ctrl->sensor_i2c_client->
+ client->dev,
+ s_ctrl->sensordata->sensor_platform_info->
+ cam_vreg,
+ s_ctrl->sensordata->sensor_platform_info->
+ num_vreg,
+ s_ctrl->vreg_seq,
+ s_ctrl->num_vreg_seq,
+ s_ctrl->reg_ptr, 0);
+ break;
+ case REQUEST_VREG:
+ msm_camera_config_vreg(&s_ctrl->sensor_i2c_client->
+ client->dev,
+ s_ctrl->sensordata->sensor_platform_info->
+ cam_vreg,
+ s_ctrl->sensordata->sensor_platform_info->
+ num_vreg,
+ s_ctrl->vreg_seq,
+ s_ctrl->num_vreg_seq,
+ s_ctrl->reg_ptr, 0);
+ break;
+ case REQUEST_GPIO:
+ msm_camera_request_gpio_table(data, 0);
+ break;
+ default:
+ pr_err("%s error power config %d\n", __func__,
+ power_seq[index].power_config);
+ break;
+ }
+ }
+ kfree(s_ctrl->reg_ptr);
+ return rc;
+}
+
+int32_t msm_sensor_bayer_power_down(struct msm_sensor_ctrl_t *s_ctrl)
+{
+ int32_t size = 0, index = 0;
+ struct msm_camera_sensor_info *data = s_ctrl->sensordata;
+ struct msm_camera_power_seq_t *power_seq = NULL;
+ CDBG("%s\n", __func__);
+
+ if (s_ctrl->power_seq) {
+ power_seq = s_ctrl->power_seq;
+ size = s_ctrl->num_power_seq;
+ } else {
+ power_seq = &sensor_power_seq[0];
+ size = ARRAY_SIZE(sensor_power_seq);
+ }
+
+ for (index = (size - 1); index >= 0; index--) {
+ switch (power_seq[index].power_config) {
+ case CONFIG_I2C_MUX:
+ if (data->sensor_platform_info->i2c_conf &&
+ data->sensor_platform_info->i2c_conf->
+ use_i2c_mux)
+ msm_sensor_bayer_disable_i2c_mux(
+ data->sensor_platform_info->i2c_conf);
+ break;
+ case CONFIG_EXT_POWER_CTRL:
+ if (data->sensor_platform_info->ext_power_ctrl != NULL)
+ data->sensor_platform_info->ext_power_ctrl(0);
+ break;
+ case CONFIG_CLK:
+ msm_cam_clk_enable(&s_ctrl->sensor_i2c_client->client->
+ dev, cam_clk_info, s_ctrl->cam_clk,
+ ARRAY_SIZE(cam_clk_info), 0);
+ break;
+ case ENABLE_GPIO:
+ msm_camera_config_gpio_table(data, 0);
+ break;
+ case ENABLE_VREG:
+ msm_camera_enable_vreg(&s_ctrl->sensor_i2c_client->
+ client->dev,
+ s_ctrl->sensordata->sensor_platform_info->
+ cam_vreg,
+ s_ctrl->sensordata->sensor_platform_info->
+ num_vreg,
+ s_ctrl->vreg_seq,
+ s_ctrl->num_vreg_seq,
+ s_ctrl->reg_ptr, 0);
+ break;
+ case REQUEST_VREG:
+ msm_camera_config_vreg(&s_ctrl->sensor_i2c_client->
+ client->dev,
+ s_ctrl->sensordata->sensor_platform_info->
+ cam_vreg,
+ s_ctrl->sensordata->sensor_platform_info->
+ num_vreg,
+ s_ctrl->vreg_seq,
+ s_ctrl->num_vreg_seq,
+ s_ctrl->reg_ptr, 0);
+ break;
+ case REQUEST_GPIO:
+ msm_camera_request_gpio_table(data, 0);
+ break;
+ default:
+ pr_err("%s error power config %d\n", __func__,
+ power_seq[index].power_config);
+ break;
+ }
+ }
+ kfree(s_ctrl->reg_ptr);
+ return 0;
+}
+
+int32_t msm_sensor_bayer_match_id(struct msm_sensor_ctrl_t *s_ctrl)
+{
+ int32_t rc = 0;
+ uint16_t chipid = 0;
+ rc = msm_camera_i2c_read(
+ s_ctrl->sensor_i2c_client,
+ s_ctrl->sensor_id_info->sensor_id_reg_addr, &chipid,
+ MSM_CAMERA_I2C_WORD_DATA);
+ if (rc < 0) {
+ pr_err("%s: %s: read id failed\n", __func__,
+ s_ctrl->sensordata->sensor_name);
+ return rc;
+ }
+
+ CDBG("%s: read id: %x expected id %x:\n", __func__, chipid,
+ s_ctrl->sensor_id_info->sensor_id);
+ if (chipid != s_ctrl->sensor_id_info->sensor_id) {
+ pr_err("msm_sensor_match_id chip id doesnot match\n");
+ return -ENODEV;
+ }
+ return rc;
+}
+
+static int32_t msm_sensor_bayer_eeprom_read(struct msm_sensor_ctrl_t *s_ctrl)
+{
+ uint32_t reg_addr = 0;
+ uint8_t *data = s_ctrl->eeprom_data.data;
+ uint32_t num_byte = 0;
+ int rc = 0;
+ uint32_t i2c_addr;
+ struct msm_camera_sensor_info *sensor_info = s_ctrl->sensordata;
+ i2c_addr = sensor_info->eeprom_info->eeprom_i2c_slave_addr;
+ num_byte = s_ctrl->eeprom_data.length = sensor_info->eeprom_info->
+ eeprom_read_length;
+ reg_addr = sensor_info->eeprom_info->eeprom_reg_addr;
+
+ data = kzalloc(num_byte * sizeof(uint8_t), GFP_KERNEL);
+ if (!data) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ rc = -EFAULT;
+ return rc;
+ }
+
+ s_ctrl->sensor_i2c_client->client->addr = i2c_addr;
+ CDBG("eeprom read: i2c addr is %x num byte %d reg addr %x\n",
+ i2c_addr, num_byte, reg_addr);
+ rc = msm_camera_i2c_read_seq(s_ctrl->sensor_i2c_client, reg_addr, data,
+ num_byte);
+ s_ctrl->sensor_i2c_client->client->addr = s_ctrl->sensor_i2c_addr;
+ return rc;
+}
+
+int32_t msm_sensor_bayer_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int rc = 0;
+ struct msm_sensor_ctrl_t *s_ctrl;
+ CDBG("%s %s_i2c_probe called\n", __func__, client->name);
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ pr_err("%s %s i2c_check_functionality failed\n",
+ __func__, client->name);
+ rc = -EFAULT;
+ return rc;
+ }
+
+ s_ctrl = (struct msm_sensor_ctrl_t *)(id->driver_data);
+ if (s_ctrl->sensor_i2c_client != NULL) {
+ s_ctrl->sensor_i2c_client->client = client;
+ if (s_ctrl->sensor_i2c_addr != 0)
+ s_ctrl->sensor_i2c_client->client->addr =
+ s_ctrl->sensor_i2c_addr;
+ } else {
+ pr_err("%s %s sensor_i2c_client NULL\n",
+ __func__, client->name);
+ rc = -EFAULT;
+ return rc;
+ }
+
+ s_ctrl->sensordata = client->dev.platform_data;
+ if (s_ctrl->sensordata == NULL) {
+ pr_err("%s %s NULL sensor data\n", __func__, client->name);
+ return -EFAULT;
+ }
+
+ rc = s_ctrl->func_tbl->sensor_power_up(s_ctrl);
+ if (rc < 0) {
+ pr_err("%s %s power up failed\n", __func__, client->name);
+ return rc;
+ }
+
+ if (s_ctrl->func_tbl->sensor_match_id)
+ rc = s_ctrl->func_tbl->sensor_match_id(s_ctrl);
+ else
+ rc = msm_sensor_bayer_match_id(s_ctrl);
+ if (rc < 0)
+ goto probe_fail;
+
+ if (!s_ctrl->wait_num_frames)
+ s_ctrl->wait_num_frames = 1;
+
+ pr_err("%s %s probe succeeded\n", __func__, client->name);
+ snprintf(s_ctrl->sensor_v4l2_subdev.name,
+ sizeof(s_ctrl->sensor_v4l2_subdev.name), "%s", id->name);
+ v4l2_i2c_subdev_init(&s_ctrl->sensor_v4l2_subdev, client,
+ s_ctrl->sensor_v4l2_subdev_ops);
+ s_ctrl->sensor_v4l2_subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ media_entity_init(&s_ctrl->sensor_v4l2_subdev.entity, 0, NULL, 0);
+ s_ctrl->sensor_v4l2_subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+ s_ctrl->sensor_v4l2_subdev.entity.group_id = SENSOR_DEV;
+ s_ctrl->sensor_v4l2_subdev.entity.name =
+ s_ctrl->sensor_v4l2_subdev.name;
+ msm_sensor_register(&s_ctrl->sensor_v4l2_subdev);
+ s_ctrl->sensor_v4l2_subdev.entity.revision =
+ s_ctrl->sensor_v4l2_subdev.devnode->num;
+ msm_sensor_bayer_eeprom_read(s_ctrl);
+ goto power_down;
+probe_fail:
+ pr_err("%s %s_i2c_probe failed\n", __func__, client->name);
+power_down:
+ if (rc > 0)
+ rc = 0;
+ s_ctrl->func_tbl->sensor_power_down(s_ctrl);
+ return rc;
+}
+
+int32_t msm_sensor_delay_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int rc = 0;
+ struct msm_sensor_ctrl_t *s_ctrl;
+ CDBG("%s %s_delay_i2c_probe called\n", __func__, client->name);
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+ pr_err("%s %s i2c_check_functionality failed\n",
+ __func__, client->name);
+ rc = -EFAULT;
+ return rc;
+ }
+
+ s_ctrl = (struct msm_sensor_ctrl_t *)(id->driver_data);
+ if (s_ctrl->sensor_i2c_client != NULL) {
+ s_ctrl->sensor_i2c_client->client = client;
+ if (s_ctrl->sensor_i2c_addr != 0)
+ s_ctrl->sensor_i2c_client->client->addr =
+ s_ctrl->sensor_i2c_addr;
+ } else {
+ pr_err("%s %s sensor_i2c_client NULL\n",
+ __func__, client->name);
+ rc = -EFAULT;
+ return rc;
+ }
+
+ s_ctrl->sensordata = client->dev.platform_data;
+ if (s_ctrl->sensordata == NULL) {
+ pr_err("%s %s NULL sensor data\n", __func__, client->name);
+ return -EFAULT;
+ }
+
+ if (!s_ctrl->wait_num_frames)
+ s_ctrl->wait_num_frames = 1;
+
+ pr_err("%s %s probe succeeded\n", __func__, client->name);
+ snprintf(s_ctrl->sensor_v4l2_subdev.name,
+ sizeof(s_ctrl->sensor_v4l2_subdev.name), "%s", id->name);
+ v4l2_i2c_subdev_init(&s_ctrl->sensor_v4l2_subdev, client,
+ s_ctrl->sensor_v4l2_subdev_ops);
+ s_ctrl->sensor_v4l2_subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ media_entity_init(&s_ctrl->sensor_v4l2_subdev.entity, 0, NULL, 0);
+ s_ctrl->sensor_v4l2_subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+ s_ctrl->sensor_v4l2_subdev.entity.group_id = SENSOR_DEV;
+ s_ctrl->sensor_v4l2_subdev.entity.name =
+ s_ctrl->sensor_v4l2_subdev.name;
+ msm_sensor_register(&s_ctrl->sensor_v4l2_subdev);
+ s_ctrl->sensor_v4l2_subdev.entity.revision =
+ s_ctrl->sensor_v4l2_subdev.devnode->num;
+ if (rc > 0)
+ rc = 0;
+ return rc;
+}
+
+int32_t msm_sensor_bayer_power(struct v4l2_subdev *sd, int on)
+{
+ int rc = 0;
+ struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(sd);
+ mutex_lock(s_ctrl->msm_sensor_mutex);
+ if (!on)
+ rc = s_ctrl->func_tbl->sensor_power_down(s_ctrl);
+ mutex_unlock(s_ctrl->msm_sensor_mutex);
+ return rc;
+}
+
+int32_t msm_sensor_bayer_v4l2_enum_fmt(struct v4l2_subdev *sd,
+ unsigned int index, enum v4l2_mbus_pixelcode *code)
+{
+ struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(sd);
+
+ if ((unsigned int)index >= s_ctrl->sensor_v4l2_subdev_info_size)
+ return -EINVAL;
+
+ *code = s_ctrl->sensor_v4l2_subdev_info[index].code;
+ return 0;
+}
+
+int32_t msm_sensor_bayer_v4l2_s_ctrl(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl)
+{
+ int rc = -1, i = 0;
+ struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(sd);
+ struct msm_sensor_v4l2_ctrl_info_t *v4l2_ctrl =
+ s_ctrl->msm_sensor_v4l2_ctrl_info;
+
+ CDBG("%s\n", __func__);
+ CDBG("%d\n", ctrl->id);
+ if (v4l2_ctrl == NULL)
+ return rc;
+ for (i = 0; i < s_ctrl->num_v4l2_ctrl; i++) {
+ if (v4l2_ctrl[i].ctrl_id == ctrl->id) {
+ if (v4l2_ctrl[i].s_v4l2_ctrl != NULL) {
+ CDBG("\n calling msm_sensor_s_ctrl_by_enum\n");
+ rc = v4l2_ctrl[i].s_v4l2_ctrl(
+ s_ctrl,
+ &s_ctrl->msm_sensor_v4l2_ctrl_info[i],
+ ctrl->value);
+ }
+ break;
+ }
+ }
+
+ return rc;
+}
+
+int32_t msm_sensor_bayer_v4l2_query_ctrl(
+ struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl)
+{
+ int rc = -1, i = 0;
+ struct msm_sensor_ctrl_t *s_ctrl =
+ (struct msm_sensor_ctrl_t *) sd->dev_priv;
+
+ CDBG("%s\n", __func__);
+ CDBG("%s id: %d\n", __func__, qctrl->id);
+
+ if (s_ctrl->msm_sensor_v4l2_ctrl_info == NULL)
+ return rc;
+
+ for (i = 0; i < s_ctrl->num_v4l2_ctrl; i++) {
+ if (s_ctrl->msm_sensor_v4l2_ctrl_info[i].ctrl_id == qctrl->id) {
+ qctrl->minimum =
+ s_ctrl->msm_sensor_v4l2_ctrl_info[i].min;
+ qctrl->maximum =
+ s_ctrl->msm_sensor_v4l2_ctrl_info[i].max;
+ qctrl->flags = 1;
+ rc = 0;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+int msm_sensor_bayer_s_ctrl_by_enum(struct msm_sensor_ctrl_t *s_ctrl,
+ struct msm_sensor_v4l2_ctrl_info_t *ctrl_info, int value)
+{
+ int rc = 0;
+ CDBG("%s enter\n", __func__);
+ rc = msm_sensor_write_enum_conf_array(
+ s_ctrl->sensor_i2c_client,
+ ctrl_info->enum_cfg_settings, value);
+ return rc;
+}
+
diff --git a/drivers/media/video/msm/sensors/msm_sensor_bayer.h b/drivers/media/video/msm/sensors/msm_sensor_bayer.h
new file mode 100644
index 0000000..d12244b
--- /dev/null
+++ b/drivers/media/video/msm/sensors/msm_sensor_bayer.h
@@ -0,0 +1,76 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. 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_SENSOR_BAYER_H
+#define MSM_SENSOR_BAYER_H
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <mach/camera.h>
+#include <mach/gpio.h>
+#include <media/msm_camera.h>
+#include <media/v4l2-subdev.h>
+#include "msm_camera_i2c.h"
+#include "msm_camera_eeprom.h"
+#include "msm_sensor_common.h"
+
+struct sensor_driver_t {
+ struct platform_driver *platform_pdriver;
+ int32_t (*platform_probe)(struct platform_device *pdev);
+};
+
+int32_t msm_sensor_bayer_config(struct msm_sensor_ctrl_t *s_ctrl,
+ void __user *argp);
+int32_t msm_sensor_bayer_power_up(struct msm_sensor_ctrl_t *s_ctrl);
+int32_t msm_sensor_bayer_power_down(struct msm_sensor_ctrl_t *s_ctrl);
+
+int32_t msm_sensor_bayer_match_id(struct msm_sensor_ctrl_t *s_ctrl);
+int msm_sensor_bayer_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+int32_t msm_sensor_delay_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+int32_t msm_sensor_bayer_power(struct v4l2_subdev *sd, int on);
+
+int32_t msm_sensor_bayer_v4l2_s_ctrl(struct v4l2_subdev *sd,
+ struct v4l2_control *ctrl);
+
+int32_t msm_sensor_bayer_v4l2_query_ctrl(
+ struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl);
+
+int msm_sensor_bayer_s_ctrl_by_enum(struct msm_sensor_ctrl_t *s_ctrl,
+ struct msm_sensor_v4l2_ctrl_info_t *ctrl_info, int value);
+
+int msm_sensor_bayer_v4l2_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+ enum v4l2_mbus_pixelcode *code);
+
+long msm_sensor_bayer_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg);
+
+int32_t msm_sensor_bayer_get_csi_params(struct msm_sensor_ctrl_t *s_ctrl,
+ struct csi_lane_params_t *sensor_output_info);
+
+#define VIDIOC_MSM_SENSOR_CFG \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 4, void __user *)
+
+#define VIDIOC_MSM_SENSOR_RELEASE \
+ _IO('V', BASE_VIDIOC_PRIVATE + 11)
+
+#define VIDIOC_MSM_SENSOR_CSID_INFO\
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 12, struct msm_sensor_csi_info *)
+#endif
diff --git a/drivers/media/video/msm/sensors/msm_sensor_common.c b/drivers/media/video/msm/sensors/msm_sensor_common.c
new file mode 100644
index 0000000..9dac632
--- /dev/null
+++ b/drivers/media/video/msm/sensors/msm_sensor_common.c
@@ -0,0 +1,18 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm_sensor_common.h"
+
+struct msm_sensor_ctrl_t *get_sctrl(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct msm_sensor_ctrl_t, sensor_v4l2_subdev);
+}
diff --git a/drivers/media/video/msm/sensors/msm_sensor_common.h b/drivers/media/video/msm/sensors/msm_sensor_common.h
new file mode 100644
index 0000000..79fe52e
--- /dev/null
+++ b/drivers/media/video/msm/sensors/msm_sensor_common.h
@@ -0,0 +1,226 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. 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_SENSOR_COMMON_H
+#define MSM_SENSOR_COMMON_H
+
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+#include <mach/camera.h>
+#include <media/msm_camera.h>
+#include <media/v4l2-subdev.h>
+#include "msm_camera_i2c.h"
+#include "msm_camera_eeprom.h"
+#define Q8 0x00000100
+#define Q10 0x00000400
+
+#define MSM_SENSOR_MCLK_8HZ 8000000
+#define MSM_SENSOR_MCLK_16HZ 16000000
+#define MSM_SENSOR_MCLK_24HZ 24000000
+
+#define DEFINE_MSM_MUTEX(mutexname) \
+ static struct mutex mutexname = __MUTEX_INITIALIZER(mutexname)
+
+struct gpio_tlmm_cfg {
+ uint32_t gpio;
+ uint32_t dir;
+ uint32_t pull;
+ uint32_t drvstr;
+};
+
+enum msm_sensor_reg_update {
+ /* Sensor egisters that need to be updated during initialization */
+ MSM_SENSOR_REG_INIT,
+ /* Sensor egisters that needs periodic I2C writes */
+ MSM_SENSOR_UPDATE_PERIODIC,
+ /* All the sensor Registers will be updated */
+ MSM_SENSOR_UPDATE_ALL,
+ /* Not valid update */
+ MSM_SENSOR_UPDATE_INVALID
+};
+
+enum msm_sensor_cam_mode_t {
+ MSM_SENSOR_MODE_2D_RIGHT,
+ MSM_SENSOR_MODE_2D_LEFT,
+ MSM_SENSOR_MODE_3D,
+ MSM_SENSOR_MODE_INVALID
+};
+
+enum msm_camera_power_config_t {
+ REQUEST_GPIO,
+ ENABLE_GPIO,
+ REQUEST_VREG,
+ ENABLE_VREG,
+ CONFIG_CLK,
+ CONFIG_EXT_POWER_CTRL,
+ CONFIG_I2C_MUX,
+};
+
+struct msm_camera_power_seq_t {
+ enum msm_camera_power_config_t power_config;
+ uint32_t delay;
+};
+
+struct msm_sensor_id_info_t {
+ uint16_t sensor_id_reg_addr;
+ uint16_t sensor_id;
+};
+
+struct msm_sensor_reg_t {
+ enum msm_camera_i2c_data_type default_data_type;
+ struct msm_camera_i2c_reg_conf *start_stream_conf;
+ uint8_t start_stream_conf_size;
+ struct msm_camera_i2c_reg_conf *stop_stream_conf;
+ uint8_t stop_stream_conf_size;
+ struct msm_camera_i2c_reg_conf *group_hold_on_conf;
+ uint8_t group_hold_on_conf_size;
+ struct msm_camera_i2c_reg_conf *group_hold_off_conf;
+ uint8_t group_hold_off_conf_size;
+ struct msm_camera_i2c_conf_array *init_settings;
+ uint8_t init_size;
+ struct msm_camera_i2c_conf_array *mode_settings;
+ struct msm_camera_i2c_conf_array *no_effect_settings;
+ struct msm_sensor_output_info_t *output_settings;
+ uint8_t num_conf;
+};
+
+enum msm_sensor_device_type_t {
+ MSM_SENSOR_I2C_DEVICE,
+ MSM_SENSOR_PLATFORM_DEVICE,
+};
+
+struct v4l2_subdev_info {
+ enum v4l2_mbus_pixelcode code;
+ enum v4l2_colorspace colorspace;
+ uint16_t fmt;
+ uint16_t order;
+};
+
+struct msm_sensor_ctrl_t;
+
+struct msm_sensor_v4l2_ctrl_info_t {
+ uint32_t ctrl_id;
+ int16_t min;
+ int16_t max;
+ int16_t step;
+ struct msm_camera_i2c_enum_conf_array *enum_cfg_settings;
+ int (*s_v4l2_ctrl) (struct msm_sensor_ctrl_t *,
+ struct msm_sensor_v4l2_ctrl_info_t *, int);
+};
+
+struct msm_sensor_fn_t {
+ void (*sensor_start_stream) (struct msm_sensor_ctrl_t *);
+ void (*sensor_stop_stream) (struct msm_sensor_ctrl_t *);
+ void (*sensor_group_hold_on) (struct msm_sensor_ctrl_t *);
+ void (*sensor_group_hold_off) (struct msm_sensor_ctrl_t *);
+
+ int32_t (*sensor_set_fps) (struct msm_sensor_ctrl_t *,
+ struct fps_cfg *);
+ int32_t (*sensor_write_exp_gain) (struct msm_sensor_ctrl_t *,
+ uint16_t, uint32_t);
+ int32_t (*sensor_write_snapshot_exp_gain) (struct msm_sensor_ctrl_t *,
+ uint16_t, uint32_t);
+ int32_t (*sensor_setting) (struct msm_sensor_ctrl_t *,
+ int update_type, int rt);
+ int32_t (*sensor_csi_setting) (struct msm_sensor_ctrl_t *,
+ int update_type, int rt);
+ int32_t (*sensor_set_sensor_mode)
+ (struct msm_sensor_ctrl_t *, int, int);
+ int32_t (*sensor_mode_init) (struct msm_sensor_ctrl_t *,
+ int, struct sensor_init_cfg *);
+ int32_t (*sensor_get_output_info) (struct msm_sensor_ctrl_t *,
+ struct sensor_output_info_t *);
+ int (*sensor_config) (struct msm_sensor_ctrl_t *, void __user *);
+ int (*sensor_power_down)
+ (struct msm_sensor_ctrl_t *);
+ int (*sensor_power_up) (struct msm_sensor_ctrl_t *);
+ int32_t (*sensor_match_id)(struct msm_sensor_ctrl_t *s_ctrl);
+ void (*sensor_adjust_frame_lines) (struct msm_sensor_ctrl_t *s_ctrl);
+ int32_t (*sensor_get_csi_params)(struct msm_sensor_ctrl_t *,
+ struct csi_lane_params_t *);
+};
+
+struct msm_sensor_csi_info {
+ uint8_t is_csic;
+};
+
+enum msm_sensor_state {
+ MSM_SENSOR_POWER_UP,
+ MSM_SENSOR_POWER_DOWN,
+};
+
+struct msm_sensor_eeprom_data {
+ uint8_t *data;
+ uint32_t length;
+};
+
+struct msm_sensor_ctrl_t {
+ struct msm_camera_sensor_info *sensordata;
+ struct i2c_client *msm_sensor_client;
+ struct i2c_driver *sensor_i2c_driver;
+ struct platform_device *pdev;
+ struct msm_camera_i2c_client *sensor_i2c_client;
+ uint16_t sensor_i2c_addr;
+ enum msm_camera_vreg_name_t *vreg_seq;
+ int num_vreg_seq;
+ struct msm_camera_power_seq_t *power_seq;
+ int num_power_seq;
+ enum msm_sensor_device_type_t sensor_device_type;
+
+ struct msm_sensor_output_reg_addr_t *sensor_output_reg_addr;
+ struct msm_sensor_id_info_t *sensor_id_info;
+ struct msm_sensor_exp_gain_info_t *sensor_exp_gain_info;
+ struct msm_sensor_reg_t *msm_sensor_reg;
+ struct msm_sensor_v4l2_ctrl_info_t *msm_sensor_v4l2_ctrl_info;
+ uint16_t num_v4l2_ctrl;
+ uint8_t is_csic;
+
+ uint16_t curr_line_length_pclk;
+ uint16_t curr_frame_length_lines;
+
+ uint32_t fps_divider;
+ enum msm_sensor_resolution_t curr_res;
+ enum msm_sensor_cam_mode_t cam_mode;
+
+ struct mutex *msm_sensor_mutex;
+
+ struct v4l2_subdev sensor_v4l2_subdev;
+ struct v4l2_subdev_info *sensor_v4l2_subdev_info;
+ uint8_t sensor_v4l2_subdev_info_size;
+ struct v4l2_subdev_ops *sensor_v4l2_subdev_ops;
+ struct msm_sensor_fn_t *func_tbl;
+ struct regulator **reg_ptr;
+ struct clk *cam_clk[2];
+ long clk_rate;
+ enum msm_sensor_state sensor_state;
+ /* Number of frames to delay after start / stop stream in Q10 format.
+ Initialize to -1 for this value to be ignored */
+ int16_t wait_num_frames;
+ /* minimum delay after stop / stop stream in ms */
+ uint16_t min_delay;
+ /* delay (in ms) after power up sequence */
+ uint16_t power_seq_delay;
+ struct msm_sensor_eeprom_data eeprom_data;
+};
+
+struct msm_sensor_ctrl_t *get_sctrl(struct v4l2_subdev *sd);
+
+#endif
diff --git a/drivers/media/video/msm/sensors/msm_sensor_init.c b/drivers/media/video/msm/sensors/msm_sensor_init.c
new file mode 100644
index 0000000..41c00eb
--- /dev/null
+++ b/drivers/media/video/msm/sensors/msm_sensor_init.c
@@ -0,0 +1,35 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "msm_sensor.h"
+#include "msm.h"
+#include "msm_sensor_bayer.h"
+#include "imx091.h"
+
+static struct i2c_driver *sensor_i2c_driver[] = {
+ /* back camera */
+ &imx091_i2c_driver,
+ /* front camera */
+};
+
+static int __init msm_sensor_init_module(void)
+{
+ int index = 0;
+ for (index = 0; index < ARRAY_SIZE(sensor_i2c_driver); index++)
+ i2c_add_driver(sensor_i2c_driver[index]);
+ return 0;
+}
+
+module_init(msm_sensor_init_module);
+MODULE_DESCRIPTION("Sensor driver probe");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/sensors/mt9e013_v4l2.c b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
index 69a5498..a38cb57 100644
--- a/drivers/media/video/msm/sensors/mt9e013_v4l2.c
+++ b/drivers/media/video/msm/sensors/mt9e013_v4l2.c
@@ -325,22 +325,6 @@
},
};
-static struct msm_camera_csi_params mt9e013_csi_params = {
- .data_format = CSI_10BIT,
- .lane_cnt = 2,
- .lane_assign = 0xe4,
- .dpcm_scheme = 0,
- .settle_cnt = 0x18,
-};
-
-static struct msm_camera_csi_params *mt9e013_csi_params_array[] = {
- &mt9e013_csi_params,
- &mt9e013_csi_params,
- &mt9e013_csi_params,
- &mt9e013_csi_params,
- &mt9e013_csi_params,
-};
-
static struct msm_sensor_output_reg_addr_t mt9e013_reg_addr = {
.x_output = 0x34C,
.y_output = 0x34E,
@@ -472,7 +456,6 @@
.sensor_config = msm_sensor_config,
.sensor_power_up = msm_sensor_power_up,
.sensor_power_down = msm_sensor_power_down,
- .sensor_get_csi_params = msm_sensor_get_csi_params,
};
static struct msm_sensor_reg_t mt9e013_regs = {
@@ -497,7 +480,6 @@
.sensor_id_info = &mt9e013_id_info,
.sensor_exp_gain_info = &mt9e013_exp_gain_info,
.cam_mode = MSM_SENSOR_MODE_INVALID,
- .csic_params = &mt9e013_csi_params_array[0],
.msm_sensor_mutex = &mt9e013_mut,
.sensor_i2c_driver = &mt9e013_i2c_driver,
.sensor_v4l2_subdev_info = mt9e013_subdev_info,
diff --git a/drivers/media/video/msm/sensors/mt9m114_v4l2.c b/drivers/media/video/msm/sensors/mt9m114_v4l2.c
index 806bcc2..cba9538 100644
--- a/drivers/media/video/msm/sensors/mt9m114_v4l2.c
+++ b/drivers/media/video/msm/sensors/mt9m114_v4l2.c
@@ -1184,30 +1184,6 @@
},
};
-static struct msm_camera_csid_vc_cfg mt9m114_cid_cfg[] = {
- {0, CSI_YUV422_8, CSI_DECODE_8BIT},
- {1, CSI_EMBED_DATA, CSI_DECODE_8BIT},
-};
-
-static struct msm_camera_csi2_params mt9m114_csi_params = {
- .csid_params = {
- .lane_cnt = 1,
- .lut_params = {
- .num_cid = 2,
- .vc_cfg = mt9m114_cid_cfg,
- },
- },
- .csiphy_params = {
- .lane_cnt = 1,
- .settle_cnt = 0x14,
- },
-};
-
-static struct msm_camera_csi2_params *mt9m114_csi_params_array[] = {
- &mt9m114_csi_params,
- &mt9m114_csi_params,
-};
-
static struct msm_sensor_output_reg_addr_t mt9m114_reg_addr = {
.x_output = 0xC868,
.y_output = 0xC86A,
@@ -1215,6 +1191,12 @@
.frame_length_lines = 0xC86A,
};
+static enum msm_camera_vreg_name_t mt9m114_veg_seq[] = {
+ CAM_VIO,
+ CAM_VDIG,
+ CAM_VANA,
+};
+
static struct msm_sensor_id_info_t mt9m114_id_info = {
.sensor_id_reg_addr = 0x0,
.sensor_id = 0x2481,
@@ -1288,10 +1270,13 @@
.num_v4l2_ctrl = ARRAY_SIZE(mt9m114_v4l2_ctrl_info),
.sensor_i2c_client = &mt9m114_sensor_i2c_client,
.sensor_i2c_addr = 0x90,
+ .vreg_seq = mt9m114_veg_seq,
+ .num_vreg_seq = ARRAY_SIZE(mt9m114_veg_seq),
.sensor_output_reg_addr = &mt9m114_reg_addr,
.sensor_id_info = &mt9m114_id_info,
.cam_mode = MSM_SENSOR_MODE_INVALID,
- .csi_params = &mt9m114_csi_params_array[0],
+ .min_delay = 30,
+ .power_seq_delay = 60,
.msm_sensor_mutex = &mt9m114_mut,
.sensor_i2c_driver = &mt9m114_i2c_driver,
.sensor_v4l2_subdev_info = mt9m114_subdev_info,
diff --git a/drivers/media/video/msm/sensors/ov2720.c b/drivers/media/video/msm/sensors/ov2720.c
index e08cd0a..1423063 100644
--- a/drivers/media/video/msm/sensors/ov2720.c
+++ b/drivers/media/video/msm/sensors/ov2720.c
@@ -658,34 +658,6 @@
},
};
-static struct msm_camera_csid_vc_cfg ov2720_cid_cfg[] = {
- {0, CSI_RAW10, CSI_DECODE_10BIT},
- {1, CSI_EMBED_DATA, CSI_DECODE_8BIT},
-};
-
-static struct msm_camera_csi2_params ov2720_csi_params = {
- .csid_params = {
- .lane_cnt = 2,
- .lut_params = {
- .num_cid = 2,
- .vc_cfg = ov2720_cid_cfg,
- },
- },
- .csiphy_params = {
- .lane_cnt = 2,
- .settle_cnt = 0x1B,
- },
-};
-
-static struct msm_camera_csi2_params *ov2720_csi_params_array[] = {
- &ov2720_csi_params,
- &ov2720_csi_params,
- &ov2720_csi_params,
- &ov2720_csi_params,
- &ov2720_csi_params,
- &ov2720_csi_params,
-};
-
static struct msm_sensor_output_reg_addr_t ov2720_reg_addr = {
.x_output = 0x3808,
.y_output = 0x380a,
@@ -704,6 +676,12 @@
.vert_offset = 6,
};
+static enum msm_camera_vreg_name_t ov2720_veg_seq[] = {
+ CAM_VIO,
+ CAM_VANA,
+ CAM_VDIG,
+};
+
static int32_t ov2720_write_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
uint16_t gain, uint32_t line)
{
@@ -849,11 +827,12 @@
.msm_sensor_reg = &ov2720_regs,
.sensor_i2c_client = &ov2720_sensor_i2c_client,
.sensor_i2c_addr = 0x6C,
+ .vreg_seq = ov2720_veg_seq,
+ .num_vreg_seq = ARRAY_SIZE(ov2720_veg_seq),
.sensor_output_reg_addr = &ov2720_reg_addr,
.sensor_id_info = &ov2720_id_info,
.sensor_exp_gain_info = &ov2720_exp_gain_info,
.cam_mode = MSM_SENSOR_MODE_INVALID,
- .csi_params = &ov2720_csi_params_array[0],
.msm_sensor_mutex = &ov2720_mut,
.sensor_i2c_driver = &ov2720_i2c_driver,
.sensor_v4l2_subdev_info = ov2720_subdev_info,
diff --git a/drivers/media/video/msm/sensors/ov5647_v4l2.c b/drivers/media/video/msm/sensors/ov5647_v4l2.c
index d192563..79aa7aa 100644
--- a/drivers/media/video/msm/sensors/ov5647_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov5647_v4l2.c
@@ -343,14 +343,6 @@
ARRAY_SIZE(ov5647_zsl_settings), 0, MSM_CAMERA_I2C_BYTE_DATA},
};
-static struct msm_camera_csi_params ov5647_csi_params = {
- .data_format = CSI_8BIT,
- .lane_cnt = 2,
- .lane_assign = 0xe4,
- .dpcm_scheme = 0,
- .settle_cnt = 10,
-};
-
static struct v4l2_subdev_info ov5647_subdev_info[] = {
{
.code = V4L2_MBUS_FMT_SBGGR10_1X10,
@@ -417,14 +409,6 @@
.frame_length_lines = 0x380E,
};
-static struct msm_camera_csi_params *ov5647_csi_params_array[] = {
- &ov5647_csi_params, /* Snapshot */
- &ov5647_csi_params, /* Preview */
- &ov5647_csi_params, /* 60fps */
- &ov5647_csi_params, /* 90fps */
- &ov5647_csi_params, /* ZSL */
-};
-
static struct msm_sensor_id_info_t ov5647_id_info = {
.sensor_id_reg_addr = 0x300a,
.sensor_id = 0x5647,
@@ -572,7 +556,8 @@
s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
/* adjust frame rate */
- if (line > (fl_lines - offset))
+ if ((s_ctrl->curr_res < MSM_SENSOR_RES_2) &&
+ (line > (fl_lines - offset)))
fl_lines = line + offset;
msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
@@ -733,13 +718,15 @@
static int32_t vfe_clk = 266667000;
-int32_t ov5647_sensor_setting(struct msm_sensor_ctrl_t *s_ctrl,
- int update_type, int res)
+static void ov5647_stop_stream(struct msm_sensor_ctrl_t *s_ctrl)
{
- int32_t rc = 0;
- static int csi_config;
- s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
- if (csi_config == 0 || res == 0)
+ msm_camera_i2c_write_tbl(
+ s_ctrl->sensor_i2c_client,
+ s_ctrl->msm_sensor_reg->stop_stream_conf,
+ s_ctrl->msm_sensor_reg->stop_stream_conf_size,
+ s_ctrl->msm_sensor_reg->default_data_type);
+
+ if (s_ctrl->curr_res == MSM_SENSOR_RES_FULL)
msleep(66);
else
msleep(266);
@@ -748,37 +735,31 @@
s_ctrl->sensor_i2c_client,
0x4800, 0x25,
MSM_CAMERA_I2C_BYTE_DATA);
+}
+
+int32_t ov5647_sensor_setting(struct msm_sensor_ctrl_t *s_ctrl,
+ int update_type, int res)
+{
+ int32_t rc = 0;
if (update_type == MSM_SENSOR_REG_INIT) {
CDBG("Register INIT\n");
- s_ctrl->curr_csi_params = NULL;
+ s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
msm_camera_i2c_write(
s_ctrl->sensor_i2c_client,
0x103, 0x1,
MSM_CAMERA_I2C_BYTE_DATA);
msm_sensor_enable_debugfs(s_ctrl);
msm_sensor_write_init_settings(s_ctrl);
- csi_config = 0;
} else if (update_type == MSM_SENSOR_UPDATE_PERIODIC) {
CDBG("PERIODIC : %d\n", res);
msm_sensor_write_conf_array(
s_ctrl->sensor_i2c_client,
s_ctrl->msm_sensor_reg->mode_settings, res);
msleep(30);
- if (!csi_config) {
- s_ctrl->curr_csic_params = s_ctrl->csic_params[res];
- CDBG("CSI config in progress\n");
- v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
- NOTIFY_CSIC_CFG,
- s_ctrl->curr_csic_params);
- CDBG("CSI config is done\n");
- mb();
- msleep(30);
- csi_config = 1;
msm_camera_i2c_write(
s_ctrl->sensor_i2c_client,
0x100, 0x1,
MSM_CAMERA_I2C_BYTE_DATA);
- }
msm_camera_i2c_write(
s_ctrl->sensor_i2c_client,
0x4800, 0x4,
@@ -788,14 +769,12 @@
v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
NOTIFY_PCLK_CHANGE,
&vfe_clk);
- s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
- msleep(50);
}
return rc;
}
static struct msm_sensor_fn_t ov5647_func_tbl = {
.sensor_start_stream = msm_sensor_start_stream,
- .sensor_stop_stream = msm_sensor_stop_stream,
+ .sensor_stop_stream = ov5647_stop_stream,
.sensor_group_hold_on = msm_sensor_group_hold_on,
.sensor_group_hold_off = msm_sensor_group_hold_off,
.sensor_set_fps = msm_sensor_set_fps,
@@ -808,7 +787,6 @@
.sensor_config = msm_sensor_config,
.sensor_power_up = ov5647_sensor_power_up,
.sensor_power_down = ov5647_sensor_power_down,
- .sensor_get_csi_params = msm_sensor_get_csi_params,
};
static struct msm_sensor_reg_t ov5647_regs = {
@@ -837,7 +815,6 @@
.sensor_id_info = &ov5647_id_info,
.sensor_exp_gain_info = &ov5647_exp_gain_info,
.cam_mode = MSM_SENSOR_MODE_INVALID,
- .csic_params = &ov5647_csi_params_array[0],
.msm_sensor_mutex = &ov5647_mut,
.sensor_i2c_driver = &ov5647_i2c_driver,
.sensor_v4l2_subdev_info = ov5647_subdev_info,
diff --git a/drivers/media/video/msm/sensors/ov7692_v4l2.c b/drivers/media/video/msm/sensors/ov7692_v4l2.c
index 71d436e..e0d4b53f 100644
--- a/drivers/media/video/msm/sensors/ov7692_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov7692_v4l2.c
@@ -821,18 +821,6 @@
};
-static struct msm_camera_csi_params ov7692_csi_params = {
- .data_format = CSI_8BIT,
- .lane_cnt = 1,
- .lane_assign = 0xe4,
- .dpcm_scheme = 0,
- .settle_cnt = 0x14,
-};
-
-static struct msm_camera_csi_params *ov7692_csi_params_array[] = {
- &ov7692_csi_params,
-};
-
static struct msm_sensor_output_reg_addr_t ov7692_reg_addr = {
.x_output = 0xCC,
.y_output = 0xCE,
@@ -899,7 +887,6 @@
.sensor_config = msm_sensor_config,
.sensor_power_up = msm_sensor_power_up,
.sensor_power_down = msm_sensor_power_down,
- .sensor_get_csi_params = msm_sensor_get_csi_params,
};
static struct msm_sensor_reg_t ov7692_regs = {
@@ -925,7 +912,6 @@
.sensor_output_reg_addr = &ov7692_reg_addr,
.sensor_id_info = &ov7692_id_info,
.cam_mode = MSM_SENSOR_MODE_INVALID,
- .csic_params = &ov7692_csi_params_array[0],
.msm_sensor_mutex = &ov7692_mut,
.sensor_i2c_driver = &ov7692_i2c_driver,
.sensor_v4l2_subdev_info = ov7692_subdev_info,
diff --git a/drivers/media/video/msm/sensors/ov8825_v4l2.c b/drivers/media/video/msm/sensors/ov8825_v4l2.c
index 1ae3dfd..092ee72 100644
--- a/drivers/media/video/msm/sensors/ov8825_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov8825_v4l2.c
@@ -510,19 +510,6 @@
},
};
-static struct msm_camera_csi_params ov8825_csi_params = {
- .data_format = CSI_10BIT,
- .lane_cnt = 2,
- .lane_assign = 0xe4,
- .dpcm_scheme = 0,
- .settle_cnt = 14,
-};
-
-static struct msm_camera_csi_params *ov8825_csi_params_array[] = {
- &ov8825_csi_params,
- &ov8825_csi_params,
-};
-
static struct msm_sensor_output_reg_addr_t ov8825_reg_addr = {
.x_output = 0x3808,
.y_output = 0x380a,
@@ -868,13 +855,10 @@
int update_type, int res)
{
int32_t rc = 0;
- static int csi_config;
- s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
- msleep(30);
if (update_type == MSM_SENSOR_REG_INIT) {
CDBG("Register INIT\n");
- s_ctrl->curr_csi_params = NULL;
+ s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
msm_sensor_enable_debugfs(s_ctrl);
msm_sensor_write_init_settings(s_ctrl);
CDBG("Update OTP\n");
@@ -885,30 +869,15 @@
usleep_range(10000, 11000);
msm_camera_i2c_write(s_ctrl->sensor_i2c_client, 0x100, 0x0,
MSM_CAMERA_I2C_BYTE_DATA);
- csi_config = 0;
} else if (update_type == MSM_SENSOR_UPDATE_PERIODIC) {
CDBG("PERIODIC : %d\n", res);
msm_sensor_write_conf_array(
s_ctrl->sensor_i2c_client,
s_ctrl->msm_sensor_reg->mode_settings, res);
msleep(30);
- if (!csi_config) {
- s_ctrl->curr_csic_params = s_ctrl->csic_params[res];
- CDBG("CSI config in progress\n");
- v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
- NOTIFY_CSIC_CFG,
- s_ctrl->curr_csic_params);
- CDBG("CSI config is done\n");
- mb();
- msleep(30);
- csi_config = 1;
- }
v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
NOTIFY_PCLK_CHANGE,
&s_ctrl->sensordata->pdata->ioclk.vfe_clk_rate);
-
- s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
- msleep(50);
}
return rc;
}
@@ -955,7 +924,6 @@
.sensor_id_info = &ov8825_id_info,
.sensor_exp_gain_info = &ov8825_exp_gain_info,
.cam_mode = MSM_SENSOR_MODE_INVALID,
- .csic_params = &ov8825_csi_params_array[0],
.msm_sensor_mutex = &ov8825_mut,
.sensor_i2c_driver = &ov8825_i2c_driver,
.sensor_v4l2_subdev_info = ov8825_subdev_info,
diff --git a/drivers/media/video/msm/sensors/ov9726_v4l2.c b/drivers/media/video/msm/sensors/ov9726_v4l2.c
index 27a8b38..50c13c6 100644
--- a/drivers/media/video/msm/sensors/ov9726_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov9726_v4l2.c
@@ -155,18 +155,6 @@
},
};
-static struct msm_camera_csi_params ov9726_csi_params = {
- .data_format = CSI_10BIT,
- .lane_cnt = 1,
- .lane_assign = 0xe4,
- .dpcm_scheme = 0,
- .settle_cnt = 7,
-};
-
-static struct msm_camera_csi_params *ov9726_csi_params_array[] = {
- &ov9726_csi_params,
-};
-
static struct msm_sensor_output_reg_addr_t ov9726_reg_addr = {
.x_output = 0x034c,
.y_output = 0x034e,
@@ -236,7 +224,6 @@
.sensor_config = msm_sensor_config,
.sensor_power_up = msm_sensor_power_up,
.sensor_power_down = msm_sensor_power_down,
- .sensor_get_csi_params = msm_sensor_get_csi_params,
};
static struct msm_sensor_reg_t ov9726_regs = {
@@ -265,7 +252,6 @@
.sensor_id_info = &ov9726_id_info,
.sensor_exp_gain_info = &ov9726_exp_gain_info,
.cam_mode = MSM_SENSOR_MODE_INVALID,
- .csic_params = &ov9726_csi_params_array[0],
.msm_sensor_mutex = &ov9726_mut,
.sensor_i2c_driver = &ov9726_i2c_driver,
.sensor_v4l2_subdev_info = ov9726_subdev_info,
diff --git a/drivers/media/video/msm/sensors/s5k3l1yx.c b/drivers/media/video/msm/sensors/s5k3l1yx.c
index 64b004e..fda59db 100644
--- a/drivers/media/video/msm/sensors/s5k3l1yx.c
+++ b/drivers/media/video/msm/sensors/s5k3l1yx.c
@@ -536,53 +536,6 @@
},
};
-static struct msm_camera_csid_vc_cfg s5k3l1yx_cid_cfg[] = {
- {0, CSI_RAW10, CSI_DECODE_10BIT},
- {1, CSI_EMBED_DATA, CSI_DECODE_8BIT},
-};
-
-static struct msm_camera_csi2_params s5k3l1yx_csi_params = {
- .csid_params = {
- .lane_cnt = 4,
- .lut_params = {
- .num_cid = ARRAY_SIZE(s5k3l1yx_cid_cfg),
- .vc_cfg = s5k3l1yx_cid_cfg,
- },
- },
- .csiphy_params = {
- .lane_cnt = 4,
- .settle_cnt = 0x1B,
- },
-};
-
-static struct msm_camera_csid_vc_cfg s5k3l1yx_cid_dpcm_cfg[] = {
- {0, CSI_RAW8, CSI_DECODE_DPCM_10_8_10},
-};
-
-static struct msm_camera_csi2_params s5k3l1yx_csi_dpcm_params = {
- .csid_params = {
- .lane_assign = 0xe4,
- .lane_cnt = 4,
- .lut_params = {
- .num_cid = ARRAY_SIZE(s5k3l1yx_cid_dpcm_cfg),
- .vc_cfg = s5k3l1yx_cid_dpcm_cfg,
- },
- },
- .csiphy_params = {
- .lane_cnt = 4,
- .settle_cnt = 0x1B,
- },
-};
-
-static struct msm_camera_csi2_params *s5k3l1yx_csi_params_array[] = {
- &s5k3l1yx_csi_params,
- &s5k3l1yx_csi_params,
- &s5k3l1yx_csi_params,
- &s5k3l1yx_csi_params,
- &s5k3l1yx_csi_params,
- &s5k3l1yx_csi_dpcm_params,
-};
-
static struct msm_sensor_output_reg_addr_t s5k3l1yx_reg_addr = {
.x_output = 0x34C,
.y_output = 0x34E,
@@ -590,6 +543,13 @@
.frame_length_lines = 0x340,
};
+static enum msm_camera_vreg_name_t s5k3l1yx_veg_seq[] = {
+ CAM_VDIG,
+ CAM_VANA,
+ CAM_VIO,
+ CAM_VAF,
+};
+
static struct msm_sensor_id_info_t s5k3l1yx_id_info = {
.sensor_id_reg_addr = 0x0,
.sensor_id = 0x3121,
@@ -717,11 +677,12 @@
.msm_sensor_reg = &s5k3l1yx_regs,
.sensor_i2c_client = &s5k3l1yx_sensor_i2c_client,
.sensor_i2c_addr = 0x6E,
+ .vreg_seq = s5k3l1yx_veg_seq,
+ .num_vreg_seq = ARRAY_SIZE(s5k3l1yx_veg_seq),
.sensor_output_reg_addr = &s5k3l1yx_reg_addr,
.sensor_id_info = &s5k3l1yx_id_info,
.sensor_exp_gain_info = &s5k3l1yx_exp_gain_info,
.cam_mode = MSM_SENSOR_MODE_INVALID,
- .csi_params = &s5k3l1yx_csi_params_array[0],
.msm_sensor_mutex = &s5k3l1yx_mut,
.sensor_i2c_driver = &s5k3l1yx_i2c_driver,
.sensor_v4l2_subdev_info = s5k3l1yx_subdev_info,
diff --git a/drivers/media/video/msm/sensors/s5k4e1_v4l2.c b/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
index e90390e..8cdadd8 100644
--- a/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
+++ b/drivers/media/video/msm/sensors/s5k4e1_v4l2.c
@@ -211,19 +211,6 @@
},
};
-static struct msm_camera_csi_params s5k4e1_csi_params = {
- .data_format = CSI_10BIT,
- .lane_cnt = 1,
- .lane_assign = 0xe4,
- .dpcm_scheme = 0,
- .settle_cnt = 24,
-};
-
-static struct msm_camera_csi_params *s5k4e1_csi_params_array[] = {
- &s5k4e1_csi_params,
- &s5k4e1_csi_params,
-};
-
static struct msm_sensor_output_reg_addr_t s5k4e1_reg_addr = {
.x_output = 0x034C,
.y_output = 0x034E,
@@ -487,7 +474,6 @@
.sensor_config = msm_sensor_config,
.sensor_power_up = msm_sensor_power_up,
.sensor_power_down = msm_sensor_power_down,
- .sensor_get_csi_params = msm_sensor_get_csi_params,
};
static struct msm_sensor_reg_t s5k4e1_regs = {
@@ -516,7 +502,6 @@
.sensor_id_info = &s5k4e1_id_info,
.sensor_exp_gain_info = &s5k4e1_exp_gain_info,
.cam_mode = MSM_SENSOR_MODE_INVALID,
- .csic_params = &s5k4e1_csi_params_array[0],
.msm_sensor_mutex = &s5k4e1_mut,
.sensor_i2c_driver = &s5k4e1_i2c_driver,
.sensor_v4l2_subdev_info = s5k4e1_subdev_info,
diff --git a/drivers/media/video/msm/sensors/vx6953.c b/drivers/media/video/msm/sensors/vx6953.c
index b43782c..ddc6cee 100644
--- a/drivers/media/video/msm/sensors/vx6953.c
+++ b/drivers/media/video/msm/sensors/vx6953.c
@@ -848,19 +848,6 @@
},
};
-static struct msm_camera_csi_params vx6953_csi_params = {
- .data_format = CSI_8BIT,
- .lane_cnt = 1,
- .lane_assign = 0xe4,
- .dpcm_scheme = 0,
- .settle_cnt = 7,
-};
-
-static struct msm_camera_csi_params *vx6953_csi_params_array[] = {
- &vx6953_csi_params,
- &vx6953_csi_params,
-};
-
static struct msm_sensor_output_reg_addr_t vx6953_reg_addr = {
.x_output = 0x034C,
.y_output = 0x034E,
@@ -1880,13 +1867,6 @@
vx6953_s_ctrl.msm_sensor_reg->
default_data_type);
-
- vx6953_s_ctrl.curr_csic_params =
- vx6953_s_ctrl.csic_params[0];
- v4l2_subdev_notify(&vx6953_s_ctrl.sensor_v4l2_subdev,
- NOTIFY_CSIC_CFG,
- vx6953_s_ctrl.curr_csic_params);
-
msleep(vx6953_stm5m0edof_delay_msecs_stdby);
if (rt == RES_PREVIEW) {
CDBG("%s write mode_tbl for preview\n",
@@ -2042,7 +2022,6 @@
.sensor_id_info = &vx6953_id_info,
.sensor_exp_gain_info = &vx6953_exp_gain_info,
.cam_mode = MSM_SENSOR_MODE_INVALID,
- .csic_params = &vx6953_csi_params_array[0],
.msm_sensor_mutex = &vx6953_mut,
.sensor_i2c_driver = &vx6953_i2c_driver,
.sensor_v4l2_subdev_info = vx6953_subdev_info,
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index 0919799..db83621 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -11,6 +11,7 @@
*
*/
+#include <linux/of.h>
#include "msm_cam_server.h"
#include "msm_csid.h"
#include "msm_csic.h"
@@ -160,6 +161,16 @@
g_server_dev.interface_map_table[i].mctl_handle = 0;
}
+struct iommu_domain *msm_cam_server_get_domain()
+{
+ return g_server_dev.domain;
+}
+
+int msm_cam_server_get_domain_num()
+{
+ return g_server_dev.domain_num;
+}
+
uint32_t msm_cam_server_get_mctl_handle(void)
{
uint32_t i;
@@ -288,7 +299,7 @@
/* send control command to config and wait for results*/
static int msm_server_control(struct msm_cam_server_dev *server_dev,
- struct msm_ctrl_cmd *out)
+ uint32_t id, struct msm_ctrl_cmd *out)
{
int rc = 0;
void *value;
@@ -326,7 +337,7 @@
server_dev->server_queue[out->queue_idx].evt_id =
server_dev->server_evt_id;
v4l2_evt.type = V4L2_EVENT_PRIVATE_START + MSM_CAM_RESP_V4L2;
- v4l2_evt.id = 0;
+ v4l2_evt.id = id;
v4l2_evt.u.data[0] = out->queue_idx;
/* setup event object to transfer the command; */
isp_event->resptype = MSM_CAM_RESP_V4L2;
@@ -409,6 +420,49 @@
return rc;
}
+int msm_server_private_general(struct msm_cam_v4l2_device *pcam,
+ struct msm_camera_v4l2_ioctl_t *ioctl_ptr)
+{
+ struct msm_ctrl_cmd ctrlcmd;
+ void *temp_data;
+ int rc;
+ temp_data = kzalloc(ioctl_ptr->len, GFP_KERNEL);
+ if (!temp_data) {
+ pr_err("%s could not allocate memory\n", __func__);
+ rc = -ENOMEM;
+ goto end;
+ }
+ if (copy_from_user((void *)temp_data,
+ (void __user *)ioctl_ptr->ioctl_ptr,
+ ioctl_ptr->len)) {
+ ERR_COPY_FROM_USER();
+ rc = -EFAULT;
+ goto copy_from_user_failed;
+ }
+
+ mutex_lock(&pcam->vid_lock);
+ ctrlcmd.type = MSM_V4L2_PRIVATE_CMD;
+ ctrlcmd.length = ioctl_ptr->len;
+ ctrlcmd.value = temp_data;
+ ctrlcmd.timeout_ms = 1000;
+ ctrlcmd.status = ioctl_ptr->id;
+ ctrlcmd.vnode_id = pcam->vnode_id;
+ ctrlcmd.queue_idx = pcam->server_queue_idx;
+ ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
+ /* send command to config thread in usersspace, and get return value */
+ rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
+ if (rc < 0)
+ pr_err("%s: send event failed\n", __func__);
+ mutex_unlock(&pcam->vid_lock);
+
+ kfree(temp_data);
+ return rc;
+copy_from_user_failed:
+ kfree(temp_data);
+end:
+return rc;
+}
+
int msm_server_get_crop(struct msm_cam_v4l2_device *pcam,
int idx, struct v4l2_crop *crop)
{
@@ -428,7 +482,7 @@
pcam->server_queue_idx];
/* send command to config thread in userspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
+ rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
D("%s: rc = %d\n", __func__, rc);
return rc;
@@ -452,7 +506,7 @@
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[idx];
/* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
+ rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
return rc;
}
@@ -474,7 +528,7 @@
pcam->server_queue_idx];
/* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
+ rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
return rc;
}
@@ -520,7 +574,7 @@
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
/* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
+ rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
if (rc >= 0) {
pcam->dev_inst[idx]->vid_fmt = *pfmt;
@@ -586,7 +640,7 @@
ctrlcmd.queue_idx = pcam->server_queue_idx;
/* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
+ rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
if (rc >= 0) {
pcam->dev_inst[idx]->vid_fmt = *pfmt;
pcam->dev_inst[idx]->sensor_pxlcode
@@ -617,7 +671,7 @@
/* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
+ rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
return rc;
}
@@ -638,7 +692,7 @@
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
/* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
+ rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
return rc;
}
@@ -696,7 +750,7 @@
ctrlcmd.queue_idx = pcam->server_queue_idx;
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
/* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
+ rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
D("%s: msm_server_control rc=%d\n", __func__, rc);
if (rc == 0) {
if (tmp_cmd.value && tmp_cmd.length > 0 &&
@@ -750,7 +804,7 @@
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
/* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
+ rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
return rc;
}
@@ -780,7 +834,7 @@
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
/* send command to config thread in usersspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
+ rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
ctrl->value = ((struct v4l2_control *)ctrlcmd.value)->value;
@@ -807,7 +861,7 @@
ctrlcmd.config_ident = g_server_dev.config_info.config_dev_id[0];
/* send command to config thread in userspace, and get return value */
- rc = msm_server_control(&g_server_dev, &ctrlcmd);
+ rc = msm_server_control(&g_server_dev, 0, &ctrlcmd);
D("%s: rc = %d\n", __func__, rc);
if (rc >= 0)
@@ -1013,7 +1067,7 @@
{
int rc = 0;
rc = msm_iommu_map_contig_buffer(
- (unsigned long)IMEM_Y_PING_OFFSET, CAMERA_DOMAIN, GEN_POOL,
+ (unsigned long)IMEM_Y_PING_OFFSET, mctl->domain_num, 0,
((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)),
SZ_4K, IOMMU_WRITE | IOMMU_READ,
(unsigned long *)&mctl->ping_imem_y);
@@ -1025,7 +1079,7 @@
mctl->ping_imem_cbcr = 0;
}
msm_iommu_map_contig_buffer(
- (unsigned long)IMEM_Y_PONG_OFFSET, CAMERA_DOMAIN, GEN_POOL,
+ (unsigned long)IMEM_Y_PONG_OFFSET, mctl->domain_num, 0,
((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)),
SZ_4K, IOMMU_WRITE | IOMMU_READ,
(unsigned long *)&mctl->pong_imem_y);
@@ -1042,10 +1096,10 @@
static void unmap_imem_addresses(struct msm_cam_media_controller *mctl)
{
msm_iommu_unmap_contig_buffer(mctl->ping_imem_y,
- CAMERA_DOMAIN, GEN_POOL,
+ mctl->domain_num, 0,
((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)));
msm_iommu_unmap_contig_buffer(mctl->pong_imem_y,
- CAMERA_DOMAIN, GEN_POOL,
+ mctl->domain_num, 0,
((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)));
mctl->ping_imem_y = 0;
mctl->ping_imem_cbcr = 0;
@@ -1428,6 +1482,10 @@
pr_err("%s: invalid mctl controller", __func__);
goto error;
}
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ pmctl->domain = msm_cam_server_get_domain();
+ pmctl->domain_num = msm_cam_server_get_domain_num();
+#endif
rc = map_imem_addresses(pmctl);
if (rc < 0) {
pr_err("%sFailed to map imem addresses %d\n", __func__, rc);
@@ -1539,6 +1597,11 @@
interface = PIX_0;
}
break;
+ case NOTIFY_AXI_RDI_SOF_COUNT: {
+ struct rdi_count_msg *msg = (struct rdi_count_msg *)arg;
+ interface = msg->rdi_interface;
+ }
+ break;
case NOTIFY_VFE_MSG_STATS:
case NOTIFY_VFE_MSG_COMP_STATS:
case NOTIFY_VFE_CAMIF_ERROR:
@@ -1578,16 +1641,14 @@
switch (notification) {
case NOTIFY_ISP_MSG_EVT:
case NOTIFY_VFE_MSG_OUT:
- case NOTIFY_VFE_SOF_COUNT:
+ case NOTIFY_VFE_PIX_SOF_COUNT:
case NOTIFY_VFE_MSG_STATS:
case NOTIFY_VFE_MSG_COMP_STATS:
case NOTIFY_VFE_BUF_EVT:
p_mctl = msm_cam_server_get_mctl(mctl_handle);
- if (p_mctl->isp_sdev &&
- p_mctl->isp_sdev->isp_notify
- && p_mctl->isp_sdev->sd)
- rc = p_mctl->isp_sdev->isp_notify(
- p_mctl->isp_sdev->sd, notification, arg);
+ if (p_mctl->isp_notify && p_mctl->vfe_sdev)
+ rc = p_mctl->isp_notify(p_mctl,
+ p_mctl->vfe_sdev, notification, arg);
break;
case NOTIFY_VFE_IRQ:{
struct msm_vfe_cfg_cmd cfg_cmd;
@@ -1602,30 +1663,21 @@
case NOTIFY_AXI_IRQ:
rc = v4l2_subdev_call(sd, core, ioctl, VIDIOC_MSM_AXI_IRQ, arg);
break;
+ case NOTIFY_AXI_RDI_SOF_COUNT:
+ p_mctl = msm_cam_server_get_mctl(mctl_handle);
+ if (p_mctl->axi_sdev)
+ rc = v4l2_subdev_call(p_mctl->axi_sdev, core, ioctl,
+ VIDIOC_MSM_AXI_RDI_COUNT_UPDATE, arg);
+ break;
case NOTIFY_PCLK_CHANGE:
p_mctl = v4l2_get_subdev_hostdata(sd);
if (p_mctl->axi_sdev)
rc = v4l2_subdev_call(p_mctl->axi_sdev, video,
s_crystal_freq, *(uint32_t *)arg, 0);
else
- rc = v4l2_subdev_call(p_mctl->isp_sdev->sd, video,
+ rc = v4l2_subdev_call(p_mctl->vfe_sdev, video,
s_crystal_freq, *(uint32_t *)arg, 0);
break;
- case NOTIFY_CSIPHY_CFG:
- p_mctl = v4l2_get_subdev_hostdata(sd);
- rc = v4l2_subdev_call(p_mctl->csiphy_sdev,
- core, ioctl, VIDIOC_MSM_CSIPHY_CFG, arg);
- break;
- case NOTIFY_CSID_CFG:
- p_mctl = v4l2_get_subdev_hostdata(sd);
- rc = v4l2_subdev_call(p_mctl->csid_sdev,
- core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
- break;
- case NOTIFY_CSIC_CFG:
- p_mctl = v4l2_get_subdev_hostdata(sd);
- rc = v4l2_subdev_call(p_mctl->csic_sdev,
- core, ioctl, VIDIOC_MSM_CSIC_CFG, arg);
- break;
case NOTIFY_GESTURE_EVT:
rc = v4l2_subdev_call(g_server_dev.gesture_device,
core, ioctl, VIDIOC_MSM_GESTURE_EVT, arg);
@@ -2112,7 +2164,6 @@
}
cam_hw_idx = MSM_CAM_HW_VFE0 + index;
g_server_dev.vfe_device[index] = sd;
- g_server_dev.isp_subdev[index]->sd = sd;
if (g_server_dev.irqr_device) {
g_server_dev.subdev_table[cam_hw_idx] = sd;
err = msm_cam_server_fill_sdev_irqnum(cam_hw_idx,
@@ -2130,7 +2181,7 @@
break;
case AXI_DEV:
- if (index >= MAX_NUM_VPE_DEV) {
+ if (index >= MAX_NUM_AXI_DEV) {
pr_err("%s Invalid AXI idx %d", __func__, index);
err = -EINVAL;
break;
@@ -2179,6 +2230,23 @@
return err;
}
+#ifdef CONFIG_MSM_IOMMU
+static int camera_register_domain(void)
+{
+ struct msm_iova_partition camera_fw_partition = {
+ .start = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ };
+ struct msm_iova_layout camera_fw_layout = {
+ .partitions = &camera_fw_partition,
+ .npartitions = 1,
+ .client_name = "camera_isp",
+ .domain_flags = 0,
+ };
+
+ return msm_register_domain(&camera_fw_layout);
+}
+#endif
static int msm_setup_server_dev(struct platform_device *pdev)
{
@@ -2255,6 +2323,21 @@
g_server_dev.interface_map_table[i].interface = 0x01 << i;
g_server_dev.interface_map_table[i].mctl_handle = 0;
}
+#ifdef CONFIG_MSM_IOMMU
+ g_server_dev.domain_num = camera_register_domain();
+ if (g_server_dev.domain_num < 0) {
+ pr_err("%s: could not register domain\n", __func__);
+ rc = -ENODEV;
+ return rc;
+ }
+ g_server_dev.domain =
+ msm_get_iommu_domain(g_server_dev.domain_num);
+ if (!g_server_dev.domain) {
+ pr_err("%s: cannot find domain\n", __func__);
+ rc = -ENODEV;
+ return rc;
+ }
+#endif
return rc;
}
@@ -2312,6 +2395,11 @@
return rc;
}
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ pmctl->domain = msm_cam_server_get_domain();
+ pmctl->domain_num = msm_cam_server_get_domain_num();
+#endif
+
D("%s: call mctl_open\n", __func__);
rc = pmctl->mctl_open(pmctl, MSM_APPS_ID_V4L2);
@@ -2584,6 +2672,7 @@
pr_err("%s: cannot find mctl\n", __func__);
return -ENODEV;
}
+
INIT_HLIST_HEAD(&config_cam->p_mctl->stats_info.pmem_stats_list);
spin_lock_init(&config_cam->p_mctl->stats_info.pmem_stats_spinlock);
@@ -2595,21 +2684,10 @@
return rc;
}
-static struct msm_isp_ops *find_isp_op(struct v4l2_subdev *sdev)
-{
- int i;
- for (i = 0; i < g_server_dev.config_info.num_config_nodes; i++) {
- if (g_server_dev.isp_subdev[i]->sd == sdev)
- return g_server_dev.isp_subdev[i];
- }
- return NULL;
-}
-
static int msm_set_mctl_subdev(struct msm_cam_media_controller *pmctl,
struct msm_mctl_set_sdev_data *set_data)
{
int rc = 0;
- struct v4l2_subdev *vfe_sdev = NULL;
struct v4l2_subdev *temp_sdev = NULL;
switch (set_data->sdev_type) {
case CSIPHY_DEV:
@@ -2633,11 +2711,9 @@
temp_sdev = pmctl->ispif_sdev;
break;
case VFE_DEV:
- vfe_sdev = msm_cam_find_subdev_node
+ pmctl->vfe_sdev = msm_cam_find_subdev_node
(&g_server_dev.vfe_device[0], set_data->revision);
- temp_sdev = vfe_sdev;
- pmctl->isp_sdev = find_isp_op(vfe_sdev);
- pmctl->isp_sdev->sd = vfe_sdev;
+ temp_sdev = pmctl->vfe_sdev;
break;
case AXI_DEV:
pmctl->axi_sdev = msm_cam_find_subdev_node
@@ -2678,7 +2754,7 @@
pmctl->ispif_sdev = NULL;
break;
case VFE_DEV:
- pmctl->isp_sdev = NULL;
+ pmctl->vfe_sdev = NULL;
break;
case AXI_DEV:
pmctl->axi_sdev = NULL;
@@ -2710,13 +2786,15 @@
case MSM_CAM_IOCTL_REGISTER_PMEM:
return msm_register_pmem(
&config_cam->p_mctl->stats_info.pmem_stats_list,
- (void __user *)arg, config_cam->p_mctl->client);
+ (void __user *)arg, config_cam->p_mctl->client,
+ config_cam->p_mctl->domain_num);
break;
case MSM_CAM_IOCTL_UNREGISTER_PMEM:
return msm_pmem_table_del(
&config_cam->p_mctl->stats_info.pmem_stats_list,
- (void __user *)arg, config_cam->p_mctl->client);
+ (void __user *)arg, config_cam->p_mctl->client,
+ config_cam->p_mctl->domain_num);
break;
case VIDIOC_SUBSCRIBE_EVENT:
@@ -3001,12 +3079,6 @@
put logic here later to know how many configs to create*/
g_server_dev.config_info.num_config_nodes = 2;
- rc = msm_isp_init_module(g_server_dev.config_info.num_config_nodes);
- if (rc < 0) {
- pr_err("Failed to initialize isp\n");
- return rc;
- }
-
if (!msm_class) {
rc = alloc_chrdev_region(&msm_devno, 0,
g_server_dev.config_info.num_config_nodes+1, "msm_camera");
@@ -3042,22 +3114,27 @@
}
}
- msm_isp_register(&g_server_dev);
return rc;
}
static int __exit msm_camera_exit(struct platform_device *pdev)
{
- msm_isp_unregister(&g_server_dev);
return 0;
}
+static const struct of_device_id msm_cam_server_dt_match[] = {
+ {.compatible = "qcom,cam_server"},
+}
+
+MODULE_DEVICE_TABLE(of, msm_cam_server_dt_match);
+
static struct platform_driver msm_cam_server_driver = {
.probe = msm_camera_probe,
.remove = msm_camera_exit,
.driver = {
.name = "msm_cam_server",
.owner = THIS_MODULE,
+ .of_match_table = msm_cam_server_dt_match,
},
};
diff --git a/drivers/media/video/msm/server/msm_cam_server.h b/drivers/media/video/msm/server/msm_cam_server.h
index 229e9c9..d38bb98 100644
--- a/drivers/media/video/msm/server/msm_cam_server.h
+++ b/drivers/media/video/msm/server/msm_cam_server.h
@@ -20,6 +20,8 @@
#include "msm.h"
uint32_t msm_cam_server_get_mctl_handle(void);
+struct iommu_domain *msm_cam_server_get_domain(void);
+int msm_cam_server_get_domain_num(void);
struct msm_cam_media_controller *msm_cam_server_get_mctl(uint32_t handle);
void msm_cam_server_free_mctl(uint32_t handle);
/* Server session control APIs */
@@ -37,6 +39,8 @@
int32_t msm_find_free_queue(void);
int msm_server_proc_ctrl_cmd(struct msm_cam_v4l2_device *pcam,
struct msm_camera_v4l2_ioctl_t *ioctl_ptr, int is_set_cmd);
+int msm_server_private_general(struct msm_cam_v4l2_device *pcam,
+ struct msm_camera_v4l2_ioctl_t *ioctl_ptr);
int msm_server_s_ctrl(struct msm_cam_v4l2_device *pcam,
struct v4l2_control *ctrl);
int msm_server_g_ctrl(struct msm_cam_v4l2_device *pcam,
@@ -65,5 +69,5 @@
int msm_cam_server_update_irqmap(
struct msm_cam_server_irqmap_entry *entry);
int msm_cam_server_config_interface_map(u32 extendedmode,
- uint32_t mctl_handle);
+ uint32_t mctl_handle);
#endif /* _MSM_CAM_SERVER_H */
diff --git a/drivers/media/video/msm/vfe/Makefile b/drivers/media/video/msm/vfe/Makefile
index 91f0e7f..250b55f 100644
--- a/drivers/media/video/msm/vfe/Makefile
+++ b/drivers/media/video/msm/vfe/Makefile
@@ -16,5 +16,5 @@
obj-$(CONFIG_ARCH_MSM_ARM11) += msm_vfe7x.o
obj-$(CONFIG_ARCH_QSD8X50) += msm_vfe8x.o msm_vfe8x_proc.o
obj-$(CONFIG_ARCH_MSM8960) += msm_vfe32.o
-obj-$(CONFIG_ARCH_MSM8974) += msm_vfe40.o msm_vfe40_axi.o
+obj-$(CONFIG_ARCH_MSM8974) += msm_vfe40.o
obj-$(CONFIG_MSM_CAMERA_V4L2) += msm_vfe_stats_buf.o
diff --git a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c b/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c
index 0bd7b94..de32f1b 100644
--- a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c
@@ -367,7 +367,7 @@
rc = vfe31_ctrl->stats_ops.dqbuf(vfe31_ctrl->stats_ops.stats_ctrl,
stats_type, &buf);
if (rc < 0) {
- pr_err("%s: dq stats buf (type = %d) err = %d",
+ CDBG("%s: dq stats buf (type = %d) err = %d",
__func__, stats_type, rc);
return 0L;
}
@@ -401,7 +401,7 @@
stats_buf = &bufq->bufs[i];
rc = vfe31_ctrl->stats_ops.enqueue_buf(
vfe31_ctrl->stats_ops.stats_ctrl,
- &(stats_buf->info), NULL);
+ &(stats_buf->info), NULL, -1);
if (rc < 0) {
pr_err("%s: dq stats buf (type = %d) err = %d",
__func__, stats_type, rc);
@@ -412,7 +412,7 @@
}
static unsigned long vfe31_stats_unregbuf(
- struct msm_stats_reqbuf *req_buf)
+ struct msm_stats_reqbuf *req_buf, int domain_num)
{
int i = 0, rc = 0;
@@ -420,7 +420,7 @@
rc = vfe31_ctrl->stats_ops.buf_unprepare(
vfe31_ctrl->stats_ops.stats_ctrl,
req_buf->stats_type, i,
- vfe31_ctrl->stats_ops.client);
+ vfe31_ctrl->stats_ops.client, domain_num);
if (rc < 0) {
pr_err("%s: unreg stats buf (type = %d) err = %d",
__func__, req_buf->stats_type, rc);
@@ -3296,7 +3296,7 @@
}
static long vfe_stats_bufq_sub_ioctl(struct msm_vfe_cfg_cmd *cmd,
- void *ion_client)
+ void *ion_client, int domain_num)
{
long rc = 0;
switch (cmd->cmd_type) {
@@ -3344,7 +3344,7 @@
}
rc = vfe31_ctrl->stats_ops.enqueue_buf(&vfe31_ctrl->stats_ctrl,
(struct msm_stats_buf_info *)cmd->value,
- vfe31_ctrl->stats_ops.client);
+ vfe31_ctrl->stats_ops.client, domain_num);
break;
case VFE_CMD_STATS_FLUSH_BUFQ: {
struct msm_stats_flush_bufq *flush_req = NULL;
@@ -3376,7 +3376,7 @@
rc = -EINVAL ;
goto end;
}
- rc = vfe31_stats_unregbuf(req_buf);
+ rc = vfe31_stats_unregbuf(req_buf, domain_num);
}
break;
default:
@@ -3630,7 +3630,8 @@
case VFE_CMD_STATS_FLUSH_BUFQ:
case VFE_CMD_STATS_UNREGBUF:
/* for easy porting put in one envelope */
- rc = vfe_stats_bufq_sub_ioctl(cmd, vfe_params->data);
+ rc = vfe_stats_bufq_sub_ioctl(cmd, vfe_params->data,
+ pmctl->domain_num);
return rc;
default:
if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
@@ -4003,10 +4004,25 @@
vfe31_ctrl->vfe_camif_clk,
ARRAY_SIZE(vfe_camif_clk_info), 1);
if (rc < 0)
- goto vfe_clk_enable_failed;
+ goto vfe_camif_clk_enable_failed;
msm_vfe_camif_pad_reg_reset();
}
+#ifdef CONFIG_MSM_IOMMU
+ rc = iommu_attach_device(mctl->domain, vfe31_ctrl->iommu_ctx_imgwr);
+ if (rc < 0) {
+ rc = -ENODEV;
+ pr_err("%s: Device attach failed\n", __func__);
+ goto device_imgwr_attach_failed;
+ }
+ rc = iommu_attach_device(mctl->domain, vfe31_ctrl->iommu_ctx_misc);
+ if (rc < 0) {
+ rc = -ENODEV;
+ pr_err("%s: Device attach failed\n", __func__);
+ goto device_misc_attach_failed;
+ }
+#endif
+
msm_camio_bus_scale_cfg(
mctl->sdata->pdata->cam_bus_scale_table, S_INIT);
msm_camio_bus_scale_cfg(
@@ -4017,6 +4033,19 @@
return rc;
+#ifdef CONFIG_MSM_IOMMU
+device_misc_attach_failed:
+ iommu_detach_device(mctl->domain, vfe31_ctrl->iommu_ctx_imgwr);
+device_imgwr_attach_failed:
+#endif
+ if (!mctl->sdata->csi_if)
+ msm_cam_clk_enable(&vfe31_ctrl->pdev->dev,
+ vfe_camif_clk_info,
+ vfe31_ctrl->vfe_camif_clk,
+ ARRAY_SIZE(vfe_camif_clk_info), 0);
+vfe_camif_clk_enable_failed:
+ msm_cam_clk_enable(&vfe31_ctrl->pdev->dev, vfe_clk_info,
+ vfe31_ctrl->vfe_clk, ARRAY_SIZE(vfe_clk_info), 0);
vfe_clk_enable_failed:
regulator_disable(vfe31_ctrl->fs_vfe);
vfe_fs_failed:
@@ -4025,7 +4054,6 @@
camif_remap_failed:
iounmap(vfe31_ctrl->vfebase);
vfe_remap_failed:
- disable_irq(vfe31_ctrl->vfeirq->start);
mctl_failed:
return rc;
}
@@ -4037,6 +4065,11 @@
disable_irq(vfe31_ctrl->vfeirq->start);
tasklet_kill(&vfe31_tasklet);
+#ifdef CONFIG_MSM_IOMMU
+ iommu_detach_device(pmctl->domain, vfe31_ctrl->iommu_ctx_misc);
+ iommu_detach_device(pmctl->domain, vfe31_ctrl->iommu_ctx_imgwr);
+#endif
+
if (!pmctl->sdata->csi_if)
msm_cam_clk_enable(&vfe31_ctrl->pdev->dev,
vfe_camif_clk_info,
@@ -4140,6 +4173,25 @@
disable_irq(vfe31_ctrl->vfeirq->start);
+#ifdef CONFIG_MSM_IOMMU
+ /*get device context for IOMMU*/
+ vfe31_ctrl->iommu_ctx_imgwr =
+ msm_iommu_get_ctx("vfe_imgwr"); /*re-confirm*/
+ vfe31_ctrl->iommu_ctx_misc =
+ msm_iommu_get_ctx("vfe_misc"); /*re-confirm*/
+ if (!vfe31_ctrl->iommu_ctx_imgwr || !vfe31_ctrl->iommu_ctx_misc) {
+ if (vfe31_ctrl->camifmem) {
+ release_mem_region(vfe31_ctrl->camifmem->start,
+ resource_size(vfe31_ctrl->camifmem));
+ }
+ release_mem_region(vfe31_ctrl->vfemem->start,
+ resource_size(vfe31_ctrl->vfemem));
+ pr_err("%s: No iommu fw context found\n", __func__);
+ rc = -ENODEV;
+ goto vfe31_no_resource;
+ }
+#endif
+
vfe31_ctrl->pdev = pdev;
vfe31_ctrl->fs_vfe = regulator_get(&vfe31_ctrl->pdev->dev, "vdd");
if (IS_ERR(vfe31_ctrl->fs_vfe)) {
diff --git a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h b/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h
index 60db8e5..97ecd6e 100644
--- a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h
+++ b/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h
@@ -928,6 +928,8 @@
uint32_t snapshot_frame_cnt;
struct msm_stats_bufq_ctrl stats_ctrl;
struct msm_stats_ops stats_ops;
+ struct device *iommu_ctx_imgwr;
+ struct device *iommu_ctx_misc;
};
enum VFE31_STATS_NUM {
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.c b/drivers/media/video/msm/vfe/msm_vfe32.c
index c8d22d4..2740808 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.c
+++ b/drivers/media/video/msm/vfe/msm_vfe32.c
@@ -412,36 +412,116 @@
}
}
-static void axi_disable_irq(struct axi_ctrl_t *axi_ctrl)
+static void axi_enable_irq(struct vfe_share_ctrl_t *share_ctrl)
+{
+ uint32_t irq_mask, irq_mask1;
+ uint16_t vfe_operation_mode =
+ share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+ VFE_OUTPUTS_RDI1);
+ irq_mask1 =
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_1);
+
+ irq_mask1 |= VFE_IMASK_WHILE_STOPPING_1;
+
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
+ irq_mask1 |= VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK;
+
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
+ irq_mask1 |= VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK;
+
+ msm_camera_io_w(irq_mask1, share_ctrl->vfebase +
+ VFE_IRQ_MASK_1);
+
+ if (vfe_operation_mode) {
+ irq_mask =
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ irq_mask |= 0x00000021;
+ if (share_ctrl->stats_comp)
+ irq_mask |= VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK;
+ else
+ irq_mask |= 0x000FE000;
+ msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ atomic_set(&share_ctrl->vstate, 1);
+ }
+ atomic_set(&share_ctrl->handle_common_irq, 1);
+}
+
+static void axi_disable_irq(struct vfe_share_ctrl_t *share_ctrl)
{
/* disable all interrupts. */
- msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
- axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
- msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
- axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
- /* clear all pending interrupts*/
- msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
- axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
- msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
- axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
- /* Ensure the write order while writing
- to the command register using the barrier */
- msm_camera_io_w_mb(1,
- axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CMD);
+ uint32_t irq_mask, irq_mask1;
+ uint16_t vfe_operation_mode =
+ share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+ VFE_OUTPUTS_RDI1);
+
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+ irq_mask1 =
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_1);
+ irq_mask1 &= ~(VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK);
+ msm_camera_io_w(irq_mask1, share_ctrl->vfebase +
+ VFE_IRQ_MASK_1);
+ msm_camera_io_w(VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK,
+ share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+ }
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+ irq_mask1 =
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_1);
+ irq_mask1 &= ~(VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK);
+ msm_camera_io_w(irq_mask1, share_ctrl->vfebase +
+ VFE_IRQ_MASK_1);
+ msm_camera_io_w(VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK,
+ share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+ }
+ if (vfe_operation_mode) {
+ atomic_set(&share_ctrl->vstate, 0);
+ irq_mask =
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ irq_mask &= ~(0x00000021);
+ if (share_ctrl->stats_comp)
+ irq_mask &= ~(VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK);
+ else
+ irq_mask &= ~0x000FE000;
+ msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ }
+
+ if (share_ctrl->axi_ref_cnt == 1) {
+ atomic_set(&share_ctrl->handle_common_irq, 0);
+ msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
+ share_ctrl->vfebase + VFE_IRQ_MASK_0);
+ msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
+ share_ctrl->vfebase + VFE_IRQ_MASK_1);
+
+ /* clear all pending interrupts*/
+ msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
+ share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+ msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
+ share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+ /* Ensure the write order while writing
+ *to the command register using the barrier */
+ msm_camera_io_w_mb(1,
+ share_ctrl->vfebase + VFE_IRQ_CMD);
+ }
}
static void vfe32_stop(struct vfe32_ctrl_type *vfe32_ctrl)
{
- atomic_set(&vfe32_ctrl->share_ctrl->vstate, 0);
/* in either continuous or snapshot mode, stop command can be issued
* at any time. stop camif immediately. */
- msm_camera_io_w(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+ msm_camera_io_w(CAMIF_COMMAND_STOP_IMMEDIATELY,
vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
vfe32_ctrl->share_ctrl->operation_mode &=
~(vfe32_ctrl->share_ctrl->current_mode);
+ vfe32_ctrl->share_ctrl->current_mode = 0;
}
static void vfe32_subdev_notify(int id, int path, uint32_t inst_handle,
@@ -560,6 +640,16 @@
}
msm_camera_io_w(bus_cmd, axi_ctrl->share_ctrl->vfebase +
V32_AXI_BUS_CMD_OFF);
+ msm_camera_io_w(*ch_info++,
+ axi_ctrl->share_ctrl->vfebase + VFE_PIXEL_IF_CFG);
+ if (msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+ V32_GET_HW_VERSION_OFF) ==
+ VFE33_HW_NUMBER) {
+ msm_camera_io_w(*ch_info++,
+ axi_ctrl->share_ctrl->vfebase + VFE_RDI0_CFG);
+ msm_camera_io_w(*ch_info++,
+ axi_ctrl->share_ctrl->vfebase + VFE_RDI1_CFG);
+ }
return 0;
}
@@ -585,6 +675,8 @@
axi_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
atomic_set(&axi_ctrl->share_ctrl->vstate, 0);
+ atomic_set(&axi_ctrl->share_ctrl->handle_common_irq, 0);
+ atomic_set(&axi_ctrl->share_ctrl->pix0_update_ack_pending, 0);
atomic_set(&axi_ctrl->share_ctrl->rdi0_update_ack_pending, 0);
atomic_set(&axi_ctrl->share_ctrl->rdi1_update_ack_pending, 0);
atomic_set(&axi_ctrl->share_ctrl->rdi2_update_ack_pending, 0);
@@ -593,40 +685,14 @@
axi_ctrl->share_ctrl->operation_mode = 0;
axi_ctrl->share_ctrl->current_mode = 0;
axi_ctrl->share_ctrl->outpath.output_mode = 0;
+ axi_ctrl->share_ctrl->comp_output_mode = 0;
axi_ctrl->share_ctrl->vfe_capture_count = 0;
/* this is unsigned 32 bit integer. */
axi_ctrl->share_ctrl->vfeFrameId = 0;
-}
-
-static void vfe32_reset_internal_variables(
- struct vfe32_ctrl_type *vfe32_ctrl)
-{
- /* Stats control variables. */
- memset(&(vfe32_ctrl->afbfStatsControl), 0,
- sizeof(struct vfe_stats_control));
-
- memset(&(vfe32_ctrl->awbStatsControl), 0,
- sizeof(struct vfe_stats_control));
-
- memset(&(vfe32_ctrl->aecbgStatsControl), 0,
- sizeof(struct vfe_stats_control));
-
- memset(&(vfe32_ctrl->bhistStatsControl), 0,
- sizeof(struct vfe_stats_control));
-
- memset(&(vfe32_ctrl->ihistStatsControl), 0,
- sizeof(struct vfe_stats_control));
-
- memset(&(vfe32_ctrl->rsStatsControl), 0,
- sizeof(struct vfe_stats_control));
-
- memset(&(vfe32_ctrl->csStatsControl), 0,
- sizeof(struct vfe_stats_control));
-
- vfe32_ctrl->frame_skip_cnt = 31;
- vfe32_ctrl->frame_skip_pattern = 0xffffffff;
- vfe32_ctrl->snapshot_frame_cnt = 0;
+ axi_ctrl->share_ctrl->rdi0FrameId = 0;
+ axi_ctrl->share_ctrl->rdi1FrameId = 0;
+ axi_ctrl->share_ctrl->rdi2FrameId = 0;
}
static void vfe32_program_dmi_cfg(
@@ -685,6 +751,147 @@
vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
}
+static void vfe32_set_default_reg_values(
+ struct vfe32_ctrl_type *vfe32_ctrl)
+{
+ msm_camera_io_w(0x800080,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_0);
+ msm_camera_io_w(0x800080,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_1);
+ /* What value should we program CGC_OVERRIDE to? */
+ msm_camera_io_w(0xFFFFF,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_CGC_OVERRIDE);
+
+ /* default frame drop period and pattern */
+ msm_camera_io_w(0x1f,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_CFG);
+ msm_camera_io_w(0x1f,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_ENC_CBCR_CFG);
+ msm_camera_io_w(0xFFFFFFFF,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_PATTERN);
+ msm_camera_io_w(0xFFFFFFFF,
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_FRAMEDROP_ENC_CBCR_PATTERN);
+ msm_camera_io_w(0x1f,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y);
+ msm_camera_io_w(0x1f,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_VIEW_CBCR);
+ msm_camera_io_w(0xFFFFFFFF,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y_PATTERN);
+ msm_camera_io_w(0xFFFFFFFF,
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_FRAMEDROP_VIEW_CBCR_PATTERN);
+ msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase + VFE_CLAMP_MIN);
+ msm_camera_io_w(0xFFFFFF,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_CLAMP_MAX);
+
+ /* stats UB config */
+ CDBG("%s: Use bayer stats = %d\n", __func__,
+ vfe32_use_bayer_stats(vfe32_ctrl));
+ if (!vfe32_use_bayer_stats(vfe32_ctrl)) {
+ msm_camera_io_w(0x3980007,
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_AEC_BG_UB_CFG);
+ msm_camera_io_w(0x3A00007,
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_AF_BF_UB_CFG);
+ msm_camera_io_w(0x3A8000F,
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_AWB_UB_CFG);
+ msm_camera_io_w(0x3B80007,
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_RS_UB_CFG);
+ msm_camera_io_w(0x3C0001F,
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_CS_UB_CFG);
+ msm_camera_io_w(0x3E0001F,
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_HIST_UB_CFG);
+ } else {
+ msm_camera_io_w(0x350001F,
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_HIST_UB_CFG);
+ msm_camera_io_w(0x370002F,
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_AEC_BG_UB_CFG);
+ msm_camera_io_w(0x3A0002F,
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_AF_BF_UB_CFG);
+ msm_camera_io_w(0x3D00007,
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_RS_UB_CFG);
+ msm_camera_io_w(0x3D8001F,
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_CS_UB_CFG);
+ msm_camera_io_w(0x3F80007,
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_SKIN_BHIST_UB_CFG);
+ }
+ vfe32_reset_dmi_tables(vfe32_ctrl);
+}
+
+static void vfe32_reset_internal_variables(
+ struct vfe32_ctrl_type *vfe32_ctrl)
+{
+ /* Stats control variables. */
+ memset(&(vfe32_ctrl->afbfStatsControl), 0,
+ sizeof(struct vfe_stats_control));
+
+ memset(&(vfe32_ctrl->awbStatsControl), 0,
+ sizeof(struct vfe_stats_control));
+
+ memset(&(vfe32_ctrl->aecbgStatsControl), 0,
+ sizeof(struct vfe_stats_control));
+
+ memset(&(vfe32_ctrl->bhistStatsControl), 0,
+ sizeof(struct vfe_stats_control));
+
+ memset(&(vfe32_ctrl->ihistStatsControl), 0,
+ sizeof(struct vfe_stats_control));
+
+ memset(&(vfe32_ctrl->rsStatsControl), 0,
+ sizeof(struct vfe_stats_control));
+
+ memset(&(vfe32_ctrl->csStatsControl), 0,
+ sizeof(struct vfe_stats_control));
+
+ vfe32_ctrl->frame_skip_cnt = 31;
+ vfe32_ctrl->frame_skip_pattern = 0xffffffff;
+ vfe32_ctrl->snapshot_frame_cnt = 0;
+ vfe32_set_default_reg_values(vfe32_ctrl);
+}
+
+
+static int vfe32_reset(struct vfe32_ctrl_type *vfe32_ctrl)
+{
+ uint32_t irq_mask1, irq_mask;
+ atomic_set(&vfe32_ctrl->share_ctrl->vstate, 0);
+ msm_camera_io_w(VFE_MODULE_RESET_CMD,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_RESET);
+ msm_camera_io_w(0,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_RESET);
+
+ irq_mask =
+ msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ irq_mask &= ~(0x000FE021|VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK);
+
+ msm_camera_io_w(irq_mask, vfe32_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+
+ /* enable reset_ack interrupt. */
+ irq_mask1 = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
+ irq_mask1 |= VFE_IMASK_WHILE_STOPPING_1;
+ msm_camera_io_w(irq_mask1,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
+ msm_camera_io_w_mb(VFE_ONLY_RESET_CMD,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET);
+
+ return wait_for_completion_interruptible(
+ &vfe32_ctrl->share_ctrl->reset_complete);
+}
+
static int axi_reset(struct axi_ctrl_t *axi_ctrl)
{
axi_reset_internal_variables(axi_ctrl);
@@ -729,7 +936,6 @@
{
uint32_t *p = cmd;
- vfe32_ctrl->share_ctrl->operation_mode = *p;
vfe32_ctrl->share_ctrl->stats_comp = *(++p);
vfe32_ctrl->hfr_mode = *(++p);
@@ -738,19 +944,6 @@
msm_camera_io_w(*(++p),
vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
msm_camera_io_w(*(++p),
- vfe32_ctrl->share_ctrl->vfebase + VFE_PIXEL_IF_CFG);
- if (msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
- V32_GET_HW_VERSION_OFF) ==
- VFE33_HW_NUMBER) {
- msm_camera_io_w(*(++p),
- vfe32_ctrl->share_ctrl->vfebase + VFE_RDI0_CFG);
- msm_camera_io_w(*(++p),
- vfe32_ctrl->share_ctrl->vfebase + VFE_RDI1_CFG);
- } else {
- ++p;
- ++p;
- }
- msm_camera_io_w(*(++p),
vfe32_ctrl->share_ctrl->vfebase + VFE_REALIGN_BUF);
msm_camera_io_w(*(++p),
vfe32_ctrl->share_ctrl->vfebase + VFE_CHROMA_UP);
@@ -767,7 +960,7 @@
rc = vfe32_ctrl->stats_ops.dqbuf(
vfe32_ctrl->stats_ops.stats_ctrl, stats_type, &buf);
if (rc < 0) {
- pr_err("%s: dq stats buf (type = %d) err = %d",
+ CDBG("%s: dq stats buf (type = %d) err = %d",
__func__, stats_type, rc);
return 0L;
}
@@ -802,7 +995,7 @@
stats_buf = &bufq->bufs[i];
rc = vfe32_ctrl->stats_ops.enqueue_buf(
vfe32_ctrl->stats_ops.stats_ctrl,
- &(stats_buf->info), NULL);
+ &(stats_buf->info), NULL, -1);
if (rc < 0) {
pr_err("%s: dq stats buf (type = %d) err = %d",
__func__, stats_type, rc);
@@ -815,7 +1008,7 @@
static unsigned long vfe32_stats_unregbuf(
struct vfe32_ctrl_type *vfe32_ctrl,
- struct msm_stats_reqbuf *req_buf)
+ struct msm_stats_reqbuf *req_buf, int domain_num)
{
int i = 0, rc = 0;
@@ -823,7 +1016,7 @@
rc = vfe32_ctrl->stats_ops.buf_unprepare(
vfe32_ctrl->stats_ops.stats_ctrl,
req_buf->stats_type, i,
- vfe32_ctrl->stats_ops.client);
+ vfe32_ctrl->stats_ops.client, domain_num);
if (rc < 0) {
pr_err("%s: unreg stats buf (type = %d) err = %d",
__func__, req_buf->stats_type, rc);
@@ -1063,70 +1256,17 @@
static void vfe32_start_common(struct vfe32_ctrl_type *vfe32_ctrl)
{
- uint32_t irq_mask = 0x00E00021, irq_mask1, reg_update;
uint16_t vfe_operation_mode =
vfe32_ctrl->share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
VFE_OUTPUTS_RDI1);
- vfe32_ctrl->share_ctrl->start_ack_pending = TRUE;
CDBG("VFE opertaion mode = 0x%x, output mode = 0x%x\n",
vfe32_ctrl->share_ctrl->current_mode,
vfe32_ctrl->share_ctrl->outpath.output_mode);
- if (vfe32_ctrl->share_ctrl->stats_comp)
- irq_mask |= VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK;
- else
- irq_mask |= 0x000FE000;
- irq_mask |=
- msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
- msm_camera_io_w(irq_mask,
- vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
- msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1,
- vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
- irq_mask1 =
- msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
- VFE_IRQ_MASK_1);
- reg_update =
- msm_camera_io_r_mb(vfe32_ctrl->share_ctrl->vfebase +
- VFE_REG_UPDATE_CMD);
-
- if (vfe32_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
- irq_mask1 |= VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK;
- msm_camera_io_w(irq_mask1, vfe32_ctrl->share_ctrl->vfebase +
- VFE_IRQ_MASK_1);
- if (!atomic_cmpxchg(
- &vfe32_ctrl->share_ctrl->rdi0_update_ack_pending,
- 0, 1)) {
- msm_camera_io_w_mb(reg_update|0x2,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_REG_UPDATE_CMD);
- }
- }
- if (vfe32_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
- irq_mask1 |= VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK;
- msm_camera_io_w(irq_mask1, vfe32_ctrl->share_ctrl->vfebase +
- VFE_IRQ_MASK_1);
- if (!atomic_cmpxchg(
- &vfe32_ctrl->share_ctrl->rdi1_update_ack_pending,
- 0, 1)) {
- msm_camera_io_w_mb(reg_update|0x4,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_REG_UPDATE_CMD);
- }
- msm_camera_io_w_mb(reg_update|0x4, vfe32_ctrl->share_ctrl->
- vfebase + VFE_REG_UPDATE_CMD);
- }
if (vfe_operation_mode) {
- msm_camera_io_w_mb(reg_update|0x1, vfe32_ctrl->share_ctrl->
- vfebase + VFE_REG_UPDATE_CMD);
msm_camera_io_w_mb(1, vfe32_ctrl->share_ctrl->vfebase +
VFE_CAMIF_COMMAND);
}
- vfe32_ctrl->share_ctrl->operation_mode |=
- vfe32_ctrl->share_ctrl->current_mode;
- /* Ensure the write order while writing
- to the command register using the barrier */
- atomic_set(&vfe32_ctrl->share_ctrl->vstate, 1);
}
static int vfe32_start_recording(
@@ -1176,6 +1316,7 @@
struct msm_cam_media_controller *pmctl,
struct vfe32_ctrl_type *vfe32_ctrl)
{
+ vfe32_ctrl->share_ctrl->start_ack_pending = TRUE;
vfe32_start_common(vfe32_ctrl);
msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase + 0x18C);
@@ -1570,7 +1711,8 @@
case VFE_CMD_RESET:
pr_info("vfe32_proc_general: cmdID = %s\n",
vfe32_general_cmd[cmd->id]);
- vfe32_reset_internal_variables(vfe32_ctrl);
+ vfe32_ctrl->share_ctrl->vfe_reset_flag = true;
+ vfe32_reset(vfe32_ctrl);
break;
case VFE_CMD_START:
pr_info("vfe32_proc_general: cmdID = %s\n",
@@ -3026,221 +3168,479 @@
}
+void axi_stop_pix(struct vfe_share_ctrl_t *share_ctrl)
+{
+ uint32_t operation_mode =
+ share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+ VFE_OUTPUTS_RDI1);
+ uint32_t irq_comp_mask, irq_mask;
+ uint32_t reg_update = 0x1;
+
+ irq_comp_mask =
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_COMP_MASK);
+ irq_mask = msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+
+ switch (share_ctrl->cmd_type) {
+ case AXI_CMD_PREVIEW: {
+ switch (operation_mode) {
+ case VFE_OUTPUTS_PREVIEW:
+ case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
+ if (share_ctrl->comp_output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY) {
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch1]);
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out0.ch0 |
+ 0x1 << share_ctrl->outpath.out0.ch1);
+ share_ctrl->outpath.output_mode |=
+ VFE32_OUTPUT_MODE_PRIMARY;
+ } else if (share_ctrl->comp_output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch1]);
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch2]);
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out0.ch0 |
+ 0x1 << share_ctrl->outpath.out0.ch1 |
+ 0x1 << share_ctrl->outpath.out0.ch2);
+ share_ctrl->outpath.output_mode |=
+ VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
+ }
+ irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+ break;
+ default:
+ if (share_ctrl->comp_output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY) {
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[share_ctrl->
+ outpath.out1.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[share_ctrl->
+ outpath.out1.ch1]);
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out1.ch0 |
+ 0x1 << share_ctrl->outpath.out1.ch1);
+ share_ctrl->outpath.output_mode |=
+ VFE32_OUTPUT_MODE_SECONDARY;
+ } else if (share_ctrl->comp_output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[share_ctrl->
+ outpath.out1.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[share_ctrl->
+ outpath.out1.ch1]);
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[share_ctrl->
+ outpath.out1.ch2]);
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out1.ch0 |
+ 0x1 << share_ctrl->outpath.out1.ch1 |
+ 0x1 << share_ctrl->outpath.out1.ch2);
+ share_ctrl->outpath.output_mode |=
+ VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
+ }
+ irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+ break;
+ }
+ }
+ break;
+ default:
+ if (share_ctrl->comp_output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY) {
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch1]);
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out0.ch0 |
+ 0x1 << share_ctrl->outpath.out0.ch1);
+ irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+ share_ctrl->outpath.output_mode |=
+ VFE32_OUTPUT_MODE_PRIMARY;
+ } else if (share_ctrl->comp_output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch1]);
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch2]);
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out0.ch0 |
+ 0x1 << share_ctrl->outpath.out0.ch1 |
+ 0x1 << share_ctrl->outpath.out0.ch2);
+ irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+ share_ctrl->outpath.output_mode |=
+ VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
+ }
+
+ if (share_ctrl->comp_output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY) {
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[share_ctrl->
+ outpath.out1.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[share_ctrl->outpath.out1.ch1]);
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out1.ch0 |
+ 0x1 << share_ctrl->outpath.out1.ch1);
+ irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+ share_ctrl->outpath.output_mode |=
+ VFE32_OUTPUT_MODE_SECONDARY;
+ } else if (share_ctrl->comp_output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[share_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[share_ctrl->outpath.out1.ch1]);
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[share_ctrl->outpath.out1.ch2]);
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out1.ch0 |
+ 0x1 << share_ctrl->outpath.out1.ch1 |
+ 0x1 << share_ctrl->outpath.out1.ch2);
+ irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+ share_ctrl->outpath.output_mode |=
+ VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
+ }
+ break;
+ }
+
+ msm_camera_io_w_mb(reg_update,
+ share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ msm_camera_io_w(irq_comp_mask,
+ share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+}
+
+void axi_stop_rdi0(struct vfe_share_ctrl_t *share_ctrl)
+{
+ uint32_t reg_update = 0x2;
+ uint32_t irq_mask;
+ irq_mask = msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[share_ctrl->outpath.out2.ch0]);
+ irq_mask &= ~(0x1 << (share_ctrl->outpath.out2.ch0 +
+ VFE_WM_OFFSET));
+ }
+ msm_camera_io_w_mb(reg_update,
+ share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+}
+
+void axi_stop_rdi1(struct vfe_share_ctrl_t *share_ctrl)
+{
+ uint32_t reg_update = 0x4;
+ uint32_t irq_mask;
+ irq_mask = msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+ msm_camera_io_w(1, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[share_ctrl->outpath.out3.ch0]);
+ irq_mask &= ~(0x1 << (share_ctrl->outpath.out3.ch0 +
+ VFE_WM_OFFSET));
+ }
+
+ msm_camera_io_w_mb(reg_update,
+ share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+}
+
+void axi_stop_process(struct vfe_share_ctrl_t *share_ctrl)
+{
+ uint32_t operation_mode =
+ share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+ VFE_OUTPUTS_RDI1);
+
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+ axi_stop_rdi0(share_ctrl);
+ share_ctrl->comp_output_mode &= ~VFE32_OUTPUT_MODE_TERTIARY1;
+ }
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+ axi_stop_rdi1(share_ctrl);
+ share_ctrl->comp_output_mode &= ~VFE32_OUTPUT_MODE_TERTIARY2;
+ }
+ if (operation_mode) {
+ axi_stop_pix(share_ctrl);
+ share_ctrl->comp_output_mode &=
+ ~(share_ctrl->outpath.output_mode);
+ }
+}
+
static void vfe32_process_reg_update_irq(
struct vfe32_ctrl_type *vfe32_ctrl)
{
unsigned long flags;
+ struct vfe_share_ctrl_t *share_ctrl = vfe32_ctrl->share_ctrl;
- if (vfe32_ctrl->share_ctrl->recording_state ==
- VFE_STATE_START_REQUESTED) {
- if (vfe32_ctrl->share_ctrl->operation_mode &
- VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch1]);
- } else if (vfe32_ctrl->share_ctrl->operation_mode &
- VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out1.ch1]);
- }
- vfe32_ctrl->share_ctrl->recording_state = VFE_STATE_STARTED;
- msm_camera_io_w_mb(1,
- vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
- CDBG("start video triggered .\n");
- } else if (vfe32_ctrl->share_ctrl->recording_state ==
- VFE_STATE_STOP_REQUESTED) {
- if (vfe32_ctrl->share_ctrl->operation_mode &
- VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
- msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch1]);
- } else if (vfe32_ctrl->share_ctrl->operation_mode &
- VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
- msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out1.ch1]);
- }
- CDBG("stop video triggered .\n");
- }
-
- spin_lock_irqsave(&vfe32_ctrl->share_ctrl->start_ack_lock, flags);
- if (vfe32_ctrl->share_ctrl->start_ack_pending == TRUE) {
- vfe32_ctrl->share_ctrl->start_ack_pending = FALSE;
- spin_unlock_irqrestore(
- &vfe32_ctrl->share_ctrl->start_ack_lock, flags);
+ if (atomic_cmpxchg(
+ &share_ctrl->pix0_update_ack_pending, 2, 0) == 2) {
+ axi_stop_pix(share_ctrl);
+ msm_camera_io_w_mb(
+ CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+ share_ctrl->vfebase + VFE_CAMIF_COMMAND);
+ axi_disable_irq(share_ctrl);
vfe32_send_isp_msg(&vfe32_ctrl->subdev,
- vfe32_ctrl->share_ctrl->vfeFrameId, MSG_ID_START_ACK);
- } else {
- spin_unlock_irqrestore(
- &vfe32_ctrl->share_ctrl->start_ack_lock, flags);
- if (vfe32_ctrl->share_ctrl->recording_state ==
- VFE_STATE_STOP_REQUESTED) {
- vfe32_ctrl->share_ctrl->recording_state =
- VFE_STATE_STOPPED;
- /* request a reg update and send STOP_REC_ACK
- * when we process the next reg update irq.
- */
+ share_ctrl->vfeFrameId,
+ MSG_ID_PIX0_UPDATE_ACK);
+ share_ctrl->comp_output_mode &=
+ ~(share_ctrl->outpath.output_mode);
+ share_ctrl->current_mode &=
+ (VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI0);
+ } else {
+ if (share_ctrl->recording_state == VFE_STATE_START_REQUESTED) {
+ if (share_ctrl->operation_mode &
+ VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
+ msm_camera_io_w(1,
+ share_ctrl->vfebase + vfe32_AXI_WM_CFG[
+ share_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(1,
+ share_ctrl->vfebase + vfe32_AXI_WM_CFG[
+ share_ctrl->outpath.out0.ch1]);
+ } else if (share_ctrl->operation_mode &
+ VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+ msm_camera_io_w(1,
+ share_ctrl->vfebase + vfe32_AXI_WM_CFG[
+ share_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(1,
+ share_ctrl->vfebase + vfe32_AXI_WM_CFG[
+ share_ctrl->outpath.out1.ch1]);
+ }
+ share_ctrl->recording_state = VFE_STATE_STARTED;
msm_camera_io_w_mb(1,
- vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
- } else if (vfe32_ctrl->share_ctrl->recording_state ==
- VFE_STATE_STOPPED) {
- vfe32_send_isp_msg(&vfe32_ctrl->subdev,
- vfe32_ctrl->share_ctrl->vfeFrameId,
- MSG_ID_STOP_REC_ACK);
- vfe32_ctrl->share_ctrl->recording_state =
- VFE_STATE_IDLE;
+ share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ CDBG("start video triggered .\n");
+ } else if (share_ctrl->recording_state ==
+ VFE_STATE_STOP_REQUESTED) {
+ if (share_ctrl->operation_mode &
+ VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
+ msm_camera_io_w(0,
+ share_ctrl->vfebase + vfe32_AXI_WM_CFG[
+ share_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(0,
+ share_ctrl->vfebase + vfe32_AXI_WM_CFG[
+ share_ctrl->outpath.out0.ch1]);
+ } else if (share_ctrl->operation_mode &
+ VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+ msm_camera_io_w(0,
+ share_ctrl->vfebase + vfe32_AXI_WM_CFG[
+ share_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(0,
+ share_ctrl->vfebase + vfe32_AXI_WM_CFG[
+ share_ctrl->outpath.out1.ch1]);
+ }
+ CDBG("stop video triggered .\n");
}
- spin_lock_irqsave(
- &vfe32_ctrl->share_ctrl->update_ack_lock, flags);
- if (vfe32_ctrl->share_ctrl->update_ack_pending == TRUE) {
- vfe32_ctrl->share_ctrl->update_ack_pending = FALSE;
- spin_unlock_irqrestore(
- &vfe32_ctrl->share_ctrl->update_ack_lock,
- flags);
+
+ if (atomic_cmpxchg(
+ &share_ctrl->pix0_update_ack_pending, 1, 0) == 1) {
+ share_ctrl->comp_output_mode |=
+ (share_ctrl->outpath.output_mode
+ & ~(VFE32_OUTPUT_MODE_TERTIARY1|
+ VFE32_OUTPUT_MODE_TERTIARY2));
vfe32_send_isp_msg(&vfe32_ctrl->subdev,
- vfe32_ctrl->share_ctrl->vfeFrameId,
- MSG_ID_UPDATE_ACK);
+ share_ctrl->vfeFrameId, MSG_ID_PIX0_UPDATE_ACK);
+ share_ctrl->current_mode &=
+ (VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI0);
} else {
- spin_unlock_irqrestore(
- &vfe32_ctrl->share_ctrl->update_ack_lock,
- flags);
+ if (share_ctrl->recording_state ==
+ VFE_STATE_STOP_REQUESTED) {
+ share_ctrl->recording_state = VFE_STATE_STOPPED;
+ /* request a reg update and send STOP_REC_ACK
+ * when we process the next reg update irq.
+ */
+ msm_camera_io_w_mb(1, share_ctrl->vfebase +
+ VFE_REG_UPDATE_CMD);
+ } else if (share_ctrl->recording_state ==
+ VFE_STATE_STOPPED) {
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ share_ctrl->vfeFrameId,
+ MSG_ID_STOP_REC_ACK);
+ share_ctrl->recording_state = VFE_STATE_IDLE;
+ }
+ spin_lock_irqsave(
+ &share_ctrl->update_ack_lock,
+ flags);
+ if (share_ctrl->update_ack_pending == TRUE) {
+ share_ctrl->update_ack_pending = FALSE;
+ spin_unlock_irqrestore(
+ &share_ctrl->update_ack_lock, flags);
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ share_ctrl->vfeFrameId,
+ MSG_ID_UPDATE_ACK);
+ } else {
+ spin_unlock_irqrestore(
+ &share_ctrl->update_ack_lock, flags);
+ }
}
- }
- switch (vfe32_ctrl->share_ctrl->liveshot_state) {
- case VFE_STATE_START_REQUESTED:
- CDBG("%s enabling liveshot output\n", __func__);
- if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch1]);
+ switch (share_ctrl->liveshot_state) {
+ case VFE_STATE_START_REQUESTED:
+ CDBG("%s enabling liveshot output\n", __func__);
+ if (share_ctrl->comp_output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY) {
+ msm_camera_io_w(1, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[
+ share_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(1, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[
+ share_ctrl->outpath.out0.ch1]);
- vfe32_ctrl->share_ctrl->liveshot_state =
- VFE_STATE_STARTED;
+ share_ctrl->liveshot_state =
+ VFE_STATE_STARTED;
+ }
+ break;
+ case VFE_STATE_STARTED:
+ share_ctrl->vfe_capture_count--;
+ if (!share_ctrl->vfe_capture_count &&
+ (share_ctrl->comp_output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY)) {
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[
+ share_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[
+ share_ctrl->outpath.out0.ch1]);
+ }
+ break;
+ case VFE_STATE_STOP_REQUESTED:
+ if (share_ctrl->comp_output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY) {
+ /* Stop requested, stop write masters, and
+ * trigger REG_UPDATE. Send STOP_LS_ACK in
+ * next reg update. */
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[
+ share_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[
+ share_ctrl->outpath.out0.ch1]);
+
+ share_ctrl->liveshot_state = VFE_STATE_STOPPED;
+ msm_camera_io_w_mb(1, share_ctrl->vfebase +
+ VFE_REG_UPDATE_CMD);
+ }
+ break;
+ case VFE_STATE_STOPPED:
+ CDBG("%s Sending STOP_LS ACK\n", __func__);
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ share_ctrl->vfeFrameId, MSG_ID_STOP_LS_ACK);
+ share_ctrl->liveshot_state = VFE_STATE_IDLE;
+ break;
+ default:
+ break;
}
- break;
- case VFE_STATE_STARTED:
- vfe32_ctrl->share_ctrl->vfe_capture_count--;
- if (!vfe32_ctrl->share_ctrl->vfe_capture_count &&
- (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY)) {
- msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch1]);
- }
- break;
- case VFE_STATE_STOP_REQUESTED:
- if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY) {
- /* Stop requested, stop write masters, and
- * trigger REG_UPDATE. Send STOP_LS_ACK in
- * next reg update. */
- msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch1]);
- vfe32_ctrl->share_ctrl->liveshot_state =
- VFE_STATE_STOPPED;
- msm_camera_io_w_mb(1, vfe32_ctrl->share_ctrl->vfebase +
- VFE_REG_UPDATE_CMD);
- }
- break;
- case VFE_STATE_STOPPED:
- CDBG("%s Sending STOP_LS ACK\n", __func__);
- vfe32_send_isp_msg(&vfe32_ctrl->subdev,
- vfe32_ctrl->share_ctrl->vfeFrameId, MSG_ID_STOP_LS_ACK);
- vfe32_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
- break;
- default:
- break;
- }
-
- if ((vfe32_ctrl->share_ctrl->operation_mode &
- VFE_OUTPUTS_THUMB_AND_MAIN) ||
- (vfe32_ctrl->share_ctrl->operation_mode &
- VFE_OUTPUTS_MAIN_AND_THUMB) ||
- (vfe32_ctrl->share_ctrl->operation_mode &
- VFE_OUTPUTS_THUMB_AND_JPEG) ||
- (vfe32_ctrl->share_ctrl->operation_mode &
- VFE_OUTPUTS_JPEG_AND_THUMB)) {
- /* in snapshot mode */
- /* later we need to add check for live snapshot mode. */
- if (vfe32_ctrl->frame_skip_pattern & (0x1 <<
- (vfe32_ctrl->snapshot_frame_cnt %
- vfe32_ctrl->frame_skip_cnt))) {
- vfe32_ctrl->share_ctrl->vfe_capture_count--;
- /* if last frame to be captured: */
- if (vfe32_ctrl->share_ctrl->vfe_capture_count == 0) {
- /* stop the bus output:write master enable = 0*/
- if (vfe32_ctrl->share_ctrl->outpath.output_mode
- & VFE32_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(0,
- vfe32_ctrl->share_ctrl->vfebase+
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(0,
- vfe32_ctrl->share_ctrl->vfebase+
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch1]);
- }
- if (vfe32_ctrl->share_ctrl->outpath.output_mode&
+ if ((share_ctrl->operation_mode & VFE_OUTPUTS_THUMB_AND_MAIN) ||
+ (share_ctrl->operation_mode &
+ VFE_OUTPUTS_MAIN_AND_THUMB) ||
+ (share_ctrl->operation_mode &
+ VFE_OUTPUTS_THUMB_AND_JPEG) ||
+ (share_ctrl->operation_mode &
+ VFE_OUTPUTS_JPEG_AND_THUMB)) {
+ /* in snapshot mode */
+ /* later we need to add check for live snapshot mode. */
+ if (vfe32_ctrl->frame_skip_pattern & (0x1 <<
+ (vfe32_ctrl->snapshot_frame_cnt %
+ vfe32_ctrl->frame_skip_cnt))) {
+ share_ctrl->vfe_capture_count--;
+ /* if last frame to be captured: */
+ if (share_ctrl->vfe_capture_count == 0) {
+ /* stop the bus output: */
+ if (share_ctrl->comp_output_mode
+ & VFE32_OUTPUT_MODE_PRIMARY) {
+ msm_camera_io_w(0,
+ share_ctrl->vfebase+
+ vfe32_AXI_WM_CFG[
+ share_ctrl->
+ outpath.out0.ch0]);
+ msm_camera_io_w(0,
+ share_ctrl->vfebase+
+ vfe32_AXI_WM_CFG[
+ share_ctrl->
+ outpath.out0.ch1]);
+ }
+ if (share_ctrl->comp_output_mode &
VFE32_OUTPUT_MODE_SECONDARY) {
- msm_camera_io_w(0,
- vfe32_ctrl->share_ctrl->vfebase+
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(0,
- vfe32_ctrl->share_ctrl->vfebase+
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out1.ch1]);
- }
- msm_camera_io_w_mb
- (CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_CAMIF_COMMAND);
- vfe32_ctrl->snapshot_frame_cnt = -1;
- vfe32_ctrl->frame_skip_cnt = 31;
- vfe32_ctrl->frame_skip_pattern = 0xffffffff;
- } /*if snapshot count is 0*/
- } /*if frame is not being dropped*/
- vfe32_ctrl->snapshot_frame_cnt++;
- /* then do reg_update. */
- msm_camera_io_w(1,
- vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
- } /* if snapshot mode. */
+ msm_camera_io_w(0,
+ share_ctrl->vfebase+
+ vfe32_AXI_WM_CFG[
+ share_ctrl->
+ outpath.out1.ch0]);
+ msm_camera_io_w(0,
+ share_ctrl->vfebase+
+ vfe32_AXI_WM_CFG[
+ share_ctrl->
+ outpath.out1.ch1]);
+ }
+ msm_camera_io_w_mb
+ (CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+ share_ctrl->vfebase +
+ VFE_CAMIF_COMMAND);
+ vfe32_ctrl->snapshot_frame_cnt = -1;
+ vfe32_ctrl->frame_skip_cnt = 31;
+ vfe32_ctrl->frame_skip_pattern =
+ 0xffffffff;
+ } /*if snapshot count is 0*/
+ } /*if frame is not being dropped*/
+ vfe32_ctrl->snapshot_frame_cnt++;
+ /* then do reg_update. */
+ msm_camera_io_w(1,
+ share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ } /* if snapshot mode. */
+ }
}
static void vfe32_process_rdi0_reg_update_irq(
struct vfe32_ctrl_type *vfe32_ctrl)
{
if (atomic_cmpxchg(
- &vfe32_ctrl->share_ctrl->rdi0_update_ack_pending, 1, 0)) {
+ &vfe32_ctrl->share_ctrl->rdi0_update_ack_pending, 2, 0) == 2) {
+ axi_stop_rdi0(vfe32_ctrl->share_ctrl);
+ axi_disable_irq(vfe32_ctrl->share_ctrl);
vfe32_send_isp_msg(&vfe32_ctrl->subdev,
vfe32_ctrl->share_ctrl->vfeFrameId,
MSG_ID_RDI0_UPDATE_ACK);
+ vfe32_ctrl->share_ctrl->comp_output_mode &=
+ ~VFE32_OUTPUT_MODE_TERTIARY1;
+ vfe32_ctrl->share_ctrl->current_mode &=
+ ~(VFE_OUTPUTS_RDI0);
+ }
+
+ if (atomic_cmpxchg(
+ &vfe32_ctrl->share_ctrl->rdi0_update_ack_pending, 1, 0) == 1) {
+ vfe32_ctrl->share_ctrl->comp_output_mode |=
+ VFE32_OUTPUT_MODE_TERTIARY1;
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ vfe32_ctrl->share_ctrl->vfeFrameId,
+ MSG_ID_RDI0_UPDATE_ACK);
+ vfe32_ctrl->share_ctrl->current_mode &=
+ ~(VFE_OUTPUTS_RDI0);
}
}
@@ -3248,90 +3648,28 @@
struct vfe32_ctrl_type *vfe32_ctrl)
{
if (atomic_cmpxchg(
- &vfe32_ctrl->share_ctrl->rdi1_update_ack_pending, 1, 0)) {
+ &vfe32_ctrl->share_ctrl->rdi1_update_ack_pending, 2, 0) == 2) {
+ axi_stop_rdi1(vfe32_ctrl->share_ctrl);
+ axi_disable_irq(vfe32_ctrl->share_ctrl);
vfe32_send_isp_msg(&vfe32_ctrl->subdev,
vfe32_ctrl->share_ctrl->vfeFrameId,
MSG_ID_RDI1_UPDATE_ACK);
+ vfe32_ctrl->share_ctrl->comp_output_mode &=
+ ~VFE32_OUTPUT_MODE_TERTIARY2;
+ vfe32_ctrl->share_ctrl->current_mode &=
+ ~(VFE_OUTPUTS_RDI1);
}
-}
-static void vfe32_set_default_reg_values(
- struct vfe32_ctrl_type *vfe32_ctrl)
-{
- msm_camera_io_w(0x800080,
- vfe32_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_0);
- msm_camera_io_w(0x800080,
- vfe32_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_1);
- /* What value should we program CGC_OVERRIDE to? */
- msm_camera_io_w(0xFFFFF,
- vfe32_ctrl->share_ctrl->vfebase + VFE_CGC_OVERRIDE);
-
- /* default frame drop period and pattern */
- msm_camera_io_w(0x1f,
- vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_CFG);
- msm_camera_io_w(0x1f,
- vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_ENC_CBCR_CFG);
- msm_camera_io_w(0xFFFFFFFF,
- vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_PATTERN);
- msm_camera_io_w(0xFFFFFFFF,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_FRAMEDROP_ENC_CBCR_PATTERN);
- msm_camera_io_w(0x1f,
- vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y);
- msm_camera_io_w(0x1f,
- vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_VIEW_CBCR);
- msm_camera_io_w(0xFFFFFFFF,
- vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y_PATTERN);
- msm_camera_io_w(0xFFFFFFFF,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_FRAMEDROP_VIEW_CBCR_PATTERN);
- msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase + VFE_CLAMP_MIN);
- msm_camera_io_w(0xFFFFFF,
- vfe32_ctrl->share_ctrl->vfebase + VFE_CLAMP_MAX);
-
- /* stats UB config */
- CDBG("%s: Use bayer stats = %d\n", __func__,
- vfe32_use_bayer_stats(vfe32_ctrl));
- if (!vfe32_use_bayer_stats(vfe32_ctrl)) {
- msm_camera_io_w(0x3980007,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_BUS_STATS_AEC_BG_UB_CFG);
- msm_camera_io_w(0x3A00007,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_BUS_STATS_AF_BF_UB_CFG);
- msm_camera_io_w(0x3A8000F,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_BUS_STATS_AWB_UB_CFG);
- msm_camera_io_w(0x3B80007,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_BUS_STATS_RS_UB_CFG);
- msm_camera_io_w(0x3C0001F,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_BUS_STATS_CS_UB_CFG);
- msm_camera_io_w(0x3E0001F,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_BUS_STATS_HIST_UB_CFG);
- } else {
- msm_camera_io_w(0x350001F,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_BUS_STATS_HIST_UB_CFG);
- msm_camera_io_w(0x370002F,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_BUS_STATS_AEC_BG_UB_CFG);
- msm_camera_io_w(0x3A0002F,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_BUS_STATS_AF_BF_UB_CFG);
- msm_camera_io_w(0x3D00007,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_BUS_STATS_RS_UB_CFG);
- msm_camera_io_w(0x3D8001F,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_BUS_STATS_CS_UB_CFG);
- msm_camera_io_w(0x3F80007,
- vfe32_ctrl->share_ctrl->vfebase +
- VFE_BUS_STATS_SKIN_BHIST_UB_CFG);
+ if (atomic_cmpxchg(
+ &vfe32_ctrl->share_ctrl->rdi1_update_ack_pending, 1, 0) == 1) {
+ vfe32_ctrl->share_ctrl->comp_output_mode |=
+ VFE32_OUTPUT_MODE_TERTIARY2;
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ vfe32_ctrl->share_ctrl->vfeFrameId,
+ MSG_ID_RDI1_UPDATE_ACK);
+ vfe32_ctrl->share_ctrl->current_mode &=
+ ~(VFE_OUTPUTS_RDI1);
}
- vfe32_reset_dmi_tables(vfe32_ctrl);
}
static void vfe32_process_reset_irq(
@@ -3340,23 +3678,33 @@
unsigned long flags;
atomic_set(&vfe32_ctrl->share_ctrl->vstate, 0);
+ atomic_set(&vfe32_ctrl->share_ctrl->handle_common_irq, 0);
spin_lock_irqsave(&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
if (vfe32_ctrl->share_ctrl->stop_ack_pending) {
vfe32_ctrl->share_ctrl->stop_ack_pending = FALSE;
spin_unlock_irqrestore(
&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
- vfe32_send_isp_msg(&vfe32_ctrl->subdev,
- vfe32_ctrl->share_ctrl->vfeFrameId, MSG_ID_STOP_ACK);
+ if (vfe32_ctrl->share_ctrl->sync_abort)
+ complete(&vfe32_ctrl->share_ctrl->reset_complete);
+ else
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ vfe32_ctrl->share_ctrl->vfeFrameId,
+ MSG_ID_STOP_ACK);
} else {
spin_unlock_irqrestore(
&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
/* this is from reset command. */
- vfe32_set_default_reg_values(vfe32_ctrl);
-
- /* reload all write masters. (frame & line)*/
- msm_camera_io_w(0x7FFF,
- vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
+ vfe32_reset_internal_variables(vfe32_ctrl);
+ if (vfe32_ctrl->share_ctrl->vfe_reset_flag) {
+ vfe32_ctrl->share_ctrl->vfe_reset_flag = false;
+ msm_camera_io_w(0x7F80,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
+ } else {
+ /* reload all write masters. (frame & line)*/
+ msm_camera_io_w(0x7FFF,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
+ }
complete(&vfe32_ctrl->share_ctrl->reset_complete);
}
}
@@ -3367,9 +3715,6 @@
if (vfe32_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_RAW) {
if (vfe32_ctrl->share_ctrl->start_ack_pending) {
- vfe32_send_isp_msg(&vfe32_ctrl->subdev,
- vfe32_ctrl->share_ctrl->vfeFrameId,
- MSG_ID_START_ACK);
vfe32_ctrl->share_ctrl->start_ack_pending = FALSE;
}
vfe32_ctrl->share_ctrl->vfe_capture_count--;
@@ -3411,6 +3756,12 @@
struct axi_ctrl_t *axi_ctrl, uint32_t errStatus)
{
uint32_t reg_value;
+ if (errStatus & VFE32_IMASK_VIOLATION) {
+ pr_err("vfe32_irq: violation interrupt\n");
+ reg_value = msm_camera_io_r(
+ axi_ctrl->share_ctrl->vfebase + VFE_VIOLATION_STATUS);
+ pr_err("%s: violationStatus = 0x%x\n", __func__, reg_value);
+ }
if (errStatus & VFE32_IMASK_CAMIF_ERROR) {
pr_err("vfe32_irq: camif errors\n");
@@ -3441,12 +3792,31 @@
if (errStatus & VFE32_IMASK_REALIGN_BUF_CR_OVFL)
pr_err("vfe32_irq: realign bug CR overflow\n");
- if (errStatus & VFE32_IMASK_VIOLATION) {
- pr_err("vfe32_irq: violation interrupt\n");
- reg_value = msm_camera_io_r(
- axi_ctrl->share_ctrl->vfebase + VFE_VIOLATION_STATUS);
- pr_err("%s: violationStatus = 0x%x\n", __func__, reg_value);
- }
+ if (errStatus & VFE32_IMASK_STATS_AE_BG_BUS_OVFL)
+ pr_err("vfe32_irq: ae/bg stats bus overflow\n");
+
+ if (errStatus & VFE32_IMASK_STATS_AF_BF_BUS_OVFL)
+ pr_err("vfe32_irq: af/bf stats bus overflow\n");
+
+ if (errStatus & VFE32_IMASK_STATS_AWB_BUS_OVFL)
+ pr_err("vfe32_irq: awb stats bus overflow\n");
+
+ if (errStatus & VFE32_IMASK_STATS_RS_BUS_OVFL)
+ pr_err("vfe32_irq: rs stats bus overflow\n");
+
+ if (errStatus & VFE32_IMASK_STATS_CS_BUS_OVFL)
+ pr_err("vfe32_irq: cs stats bus overflow\n");
+
+ if (errStatus & VFE32_IMASK_STATS_IHIST_BUS_OVFL)
+ pr_err("vfe32_irq: ihist stats bus overflow\n");
+
+ if (errStatus & VFE32_IMASK_STATS_SKIN_BHIST_BUS_OVFL)
+ pr_err("vfe32_irq: skin/bhist stats bus overflow\n");
+}
+
+static void vfe32_process_common_error_irq(
+ struct axi_ctrl_t *axi_ctrl, uint32_t errStatus)
+{
if (errStatus & VFE32_IMASK_IMG_MAST_0_BUS_OVFL)
pr_err("vfe32_irq: image master 0 bus overflow\n");
@@ -3469,31 +3839,11 @@
if (errStatus & VFE32_IMASK_IMG_MAST_6_BUS_OVFL)
pr_err("vfe32_irq: image master 6 bus overflow\n");
- if (errStatus & VFE32_IMASK_STATS_AE_BG_BUS_OVFL)
- pr_err("vfe32_irq: ae/bg stats bus overflow\n");
-
- if (errStatus & VFE32_IMASK_STATS_AF_BF_BUS_OVFL)
- pr_err("vfe32_irq: af/bf stats bus overflow\n");
-
- if (errStatus & VFE32_IMASK_STATS_AWB_BUS_OVFL)
- pr_err("vfe32_irq: awb stats bus overflow\n");
-
- if (errStatus & VFE32_IMASK_STATS_RS_BUS_OVFL)
- pr_err("vfe32_irq: rs stats bus overflow\n");
-
- if (errStatus & VFE32_IMASK_STATS_CS_BUS_OVFL)
- pr_err("vfe32_irq: cs stats bus overflow\n");
-
- if (errStatus & VFE32_IMASK_STATS_IHIST_BUS_OVFL)
- pr_err("vfe32_irq: ihist stats bus overflow\n");
-
- if (errStatus & VFE32_IMASK_STATS_SKIN_BHIST_BUS_OVFL)
- pr_err("vfe32_irq: skin/bhist stats bus overflow\n");
-
if (errStatus & VFE32_IMASK_AXI_ERROR)
pr_err("vfe32_irq: axi error\n");
}
+
static void vfe_send_outmsg(
struct axi_ctrl_t *axi_ctrl, uint8_t msgid,
uint32_t ch0_paddr, uint32_t ch1_paddr,
@@ -3506,7 +3856,17 @@
msg.buf.ch_paddr[0] = ch0_paddr;
msg.buf.ch_paddr[1] = ch1_paddr;
msg.buf.ch_paddr[2] = ch2_paddr;
- msg.frameCounter = axi_ctrl->share_ctrl->vfeFrameId;
+ switch (msgid) {
+ case MSG_ID_OUTPUT_TERTIARY1:
+ msg.frameCounter = axi_ctrl->share_ctrl->rdi0FrameId;
+ break;
+ case MSG_ID_OUTPUT_TERTIARY2:
+ msg.frameCounter = axi_ctrl->share_ctrl->rdi1FrameId;
+ break;
+ default:
+ msg.frameCounter = axi_ctrl->share_ctrl->vfeFrameId;
+ break;
+ }
v4l2_subdev_notify(&axi_ctrl->subdev,
NOTIFY_VFE_MSG_OUT,
@@ -3532,15 +3892,15 @@
free buffer.
*/
out_bool = (
- (axi_ctrl->share_ctrl->operation_mode ==
+ (axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_THUMB_AND_MAIN ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_MAIN_AND_THUMB ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_THUMB_AND_JPEG ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_JPEG_AND_THUMB ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_RAW ||
axi_ctrl->share_ctrl->liveshot_state ==
VFE_STATE_STARTED ||
@@ -3587,15 +3947,15 @@
axi_ctrl->share_ctrl->outpath.out0.ch2,
free_buf->ch_paddr[2]);
}
- if (axi_ctrl->share_ctrl->operation_mode ==
+ if (axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_THUMB_AND_MAIN ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_MAIN_AND_THUMB ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_THUMB_AND_JPEG ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_JPEG_AND_THUMB ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_RAW ||
axi_ctrl->share_ctrl->liveshot_state ==
VFE_STATE_STOPPED)
@@ -3623,13 +3983,13 @@
free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
VFE_MSG_OUTPUT_SECONDARY, axi_ctrl);
- out_bool = ((axi_ctrl->share_ctrl->operation_mode ==
+ out_bool = ((axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_THUMB_AND_MAIN ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_MAIN_AND_THUMB ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_RAW ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_JPEG_AND_THUMB) &&
(axi_ctrl->share_ctrl->vfe_capture_count <= 1)) ||
free_buf;
@@ -3669,13 +4029,13 @@
axi_ctrl->share_ctrl->outpath.out1.ch2,
free_buf->ch_paddr[2]);
}
- if (axi_ctrl->share_ctrl->operation_mode ==
+ if (axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_THUMB_AND_MAIN ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_MAIN_AND_THUMB ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_RAW ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_JPEG_AND_THUMB)
axi_ctrl->share_ctrl->outpath.out1.capture_cnt--;
@@ -4389,19 +4749,29 @@
NOTIFY_VFE_IRQ,
(void *)VFE_IMASK_WHILE_STOPPING_1);
- if (atomic_read(&axi_ctrl->share_ctrl->handle_axi_irq))
+ if (atomic_read(&axi_ctrl->share_ctrl->handle_common_irq)) {
+ if (qcmd->vfeInterruptStatus1 &
+ VFE32_IMASK_COMMON_ERROR_ONLY_1) {
+ pr_err("irq errorIrq\n");
+ vfe32_process_common_error_irq(
+ axi_ctrl,
+ qcmd->vfeInterruptStatus1 &
+ VFE32_IMASK_COMMON_ERROR_ONLY_1);
+ }
+
v4l2_subdev_notify(&axi_ctrl->subdev,
NOTIFY_AXI_IRQ,
(void *)qcmd->vfeInterruptStatus0);
+ }
if (atomic_read(&axi_ctrl->share_ctrl->vstate)) {
if (qcmd->vfeInterruptStatus1 &
- VFE32_IMASK_ERROR_ONLY_1) {
+ VFE32_IMASK_VFE_ERROR_ONLY_1) {
pr_err("irq errorIrq\n");
vfe32_process_error_irq(
axi_ctrl,
qcmd->vfeInterruptStatus1 &
- VFE32_IMASK_ERROR_ONLY_1);
+ VFE32_IMASK_VFE_ERROR_ONLY_1);
}
/* then process stats irq. */
@@ -4540,7 +4910,7 @@
static long vfe_stats_bufq_sub_ioctl(
struct vfe32_ctrl_type *vfe_ctrl,
- struct msm_vfe_cfg_cmd *cmd, void *ion_client)
+ struct msm_vfe_cfg_cmd *cmd, void *ion_client, int domain_num)
{
long rc = 0;
switch (cmd->cmd_type) {
@@ -4589,7 +4959,7 @@
rc = vfe_ctrl->stats_ops.enqueue_buf(
&vfe_ctrl->stats_ctrl,
(struct msm_stats_buf_info *)cmd->value,
- vfe_ctrl->stats_ops.client);
+ vfe_ctrl->stats_ops.client, domain_num);
break;
case VFE_CMD_STATS_FLUSH_BUFQ:
{
@@ -4623,7 +4993,7 @@
rc = -EINVAL ;
goto end;
}
- rc = vfe32_stats_unregbuf(vfe_ctrl, req_buf);
+ rc = vfe32_stats_unregbuf(vfe_ctrl, req_buf, domain_num);
}
break;
default:
@@ -4678,7 +5048,7 @@
case VFE_CMD_STATS_UNREGBUF:
/* for easy porting put in one envelope */
rc = vfe_stats_bufq_sub_ioctl(vfe32_ctrl,
- cmd, vfe_params->data);
+ cmd, vfe_params->data, pmctl->domain_num);
return rc;
default:
if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
@@ -4693,8 +5063,8 @@
cmd->cmd_type != CMD_STATS_BG_BUF_RELEASE &&
cmd->cmd_type != CMD_STATS_BF_BUF_RELEASE &&
cmd->cmd_type != CMD_STATS_BHIST_BUF_RELEASE &&
- cmd->cmd_type != CMD_VFE_SOF_COUNT_UPDATE &&
- cmd->cmd_type != CMD_VFE_COUNT_SOF_ENABLE) {
+ cmd->cmd_type != CMD_VFE_PIX_SOF_COUNT_UPDATE &&
+ cmd->cmd_type != CMD_VFE_COUNT_PIX_SOF_ENABLE) {
if (copy_from_user(&vfecmd,
(void __user *)(cmd->value),
sizeof(vfecmd))) {
@@ -4774,7 +5144,7 @@
case CMD_GENERAL:
rc = vfe32_proc_general(pmctl, &vfecmd, vfe32_ctrl);
break;
- case CMD_VFE_COUNT_SOF_ENABLE: {
+ case CMD_VFE_COUNT_PIX_SOF_ENABLE: {
int enable = *((int *)cmd->value);
if (enable)
vfe32_ctrl->vfe_sof_count_enable = TRUE;
@@ -4782,7 +5152,7 @@
vfe32_ctrl->vfe_sof_count_enable = false;
}
break;
- case CMD_VFE_SOF_COUNT_UPDATE:
+ case CMD_VFE_PIX_SOF_COUNT_UPDATE:
if (!vfe32_ctrl->vfe_sof_count_enable)
vfe32_ctrl->share_ctrl->vfeFrameId =
*((uint32_t *)vfe_params->data);
@@ -4874,6 +5244,10 @@
rc = -EINVAL;
goto mctl_failed;
}
+ axi_ctrl->share_ctrl->axi_ref_cnt++;
+ if (axi_ctrl->share_ctrl->axi_ref_cnt > 1)
+ return rc;
+
spin_lock_init(&axi_ctrl->tasklet_lock);
INIT_LIST_HEAD(&axi_ctrl->tasklet_q);
spin_lock_init(&axi_ctrl->share_ctrl->sd_notify_lock);
@@ -4899,6 +5273,21 @@
if (rc < 0)
goto clk_enable_failed;
+#ifdef CONFIG_MSM_IOMMU
+ rc = iommu_attach_device(mctl->domain, axi_ctrl->iommu_ctx_imgwr);
+ if (rc < 0) {
+ pr_err("%s: imgwr attach failed rc = %d\n", __func__, rc);
+ rc = -ENODEV;
+ goto device_imgwr_attach_failed;
+ }
+ rc = iommu_attach_device(mctl->domain, axi_ctrl->iommu_ctx_misc);
+ if (rc < 0) {
+ pr_err("%s: misc attach failed rc = %d\n", __func__, rc);
+ rc = -ENODEV;
+ goto device_misc_attach_failed;
+ }
+#endif
+
msm_camio_bus_scale_cfg(
mctl->sdata->pdata->cam_bus_scale_table, S_INIT);
msm_camio_bus_scale_cfg(
@@ -4911,9 +5300,21 @@
else
axi_ctrl->share_ctrl->register_total = VFE33_REGISTER_TOTAL;
+ spin_lock_init(&axi_ctrl->share_ctrl->stop_flag_lock);
+ spin_lock_init(&axi_ctrl->share_ctrl->update_ack_lock);
+ spin_lock_init(&axi_ctrl->share_ctrl->start_ack_lock);
+
enable_irq(axi_ctrl->vfeirq->start);
return rc;
+
+#ifdef CONFIG_MSM_IOMMU
+device_misc_attach_failed:
+ iommu_detach_device(mctl->domain, axi_ctrl->iommu_ctx_imgwr);
+device_imgwr_attach_failed:
+#endif
+ msm_cam_clk_enable(&axi_ctrl->pdev->dev, vfe32_clk_info,
+ axi_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 0);
clk_enable_failed:
if (axi_ctrl->fs_vfe)
regulator_disable(axi_ctrl->fs_vfe);
@@ -4921,7 +5322,6 @@
iounmap(axi_ctrl->share_ctrl->vfebase);
axi_ctrl->share_ctrl->vfebase = NULL;
remap_failed:
- disable_irq(axi_ctrl->vfeirq->start);
mctl_failed:
return rc;
}
@@ -4932,11 +5332,7 @@
struct vfe32_ctrl_type *vfe32_ctrl =
(struct vfe32_ctrl_type *)v4l2_get_subdevdata(sd);
- spin_lock_init(&vfe32_ctrl->share_ctrl->stop_flag_lock);
- spin_lock_init(&vfe32_ctrl->share_ctrl->abort_lock);
spin_lock_init(&vfe32_ctrl->state_lock);
- spin_lock_init(&vfe32_ctrl->share_ctrl->update_ack_lock);
- spin_lock_init(&vfe32_ctrl->share_ctrl->start_ack_lock);
spin_lock_init(&vfe32_ctrl->stats_bufq_lock);
vfe32_ctrl->update_linear = false;
@@ -4946,7 +5342,8 @@
vfe32_ctrl->vfe_sof_count_enable = false;
vfe32_ctrl->hfr_mode = HFR_MODE_OFF;
- memset(&vfe32_ctrl->stats_ctrl, 0, sizeof(struct msm_stats_bufq_ctrl));
+ memset(&vfe32_ctrl->stats_ctrl, 0,
+ sizeof(struct msm_stats_bufq_ctrl));
memset(&vfe32_ctrl->stats_ops, 0, sizeof(struct msm_stats_ops));
return rc;
@@ -4963,8 +5360,15 @@
}
CDBG("%s, free_irq\n", __func__);
+ axi_ctrl->share_ctrl->axi_ref_cnt--;
+ if (axi_ctrl->share_ctrl->axi_ref_cnt > 0)
+ return;
disable_irq(axi_ctrl->vfeirq->start);
tasklet_kill(&axi_ctrl->vfe32_tasklet);
+#ifdef CONFIG_MSM_IOMMU
+ iommu_detach_device(pmctl->domain, axi_ctrl->iommu_ctx_misc);
+ iommu_detach_device(pmctl->domain, axi_ctrl->iommu_ctx_imgwr);
+#endif
msm_cam_clk_enable(&axi_ctrl->pdev->dev, vfe32_clk_info,
axi_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 0);
if (axi_ctrl->fs_vfe)
@@ -4978,20 +5382,26 @@
msm_camio_bus_scale_cfg(
pmctl->sdata->pdata->cam_bus_scale_table, S_EXIT);
+
}
void msm_vfe_subdev_release(struct v4l2_subdev *sd)
{
struct vfe32_ctrl_type *vfe32_ctrl =
(struct vfe32_ctrl_type *)v4l2_get_subdevdata(sd);
- if (!vfe32_ctrl->share_ctrl->vfebase)
- vfe32_ctrl->share_ctrl->vfebase = NULL;
+ CDBG("vfe subdev release %p\n",
+ vfe32_ctrl->share_ctrl->vfebase);
}
void axi_abort(struct axi_ctrl_t *axi_ctrl)
{
uint8_t axi_busy_flag = true;
+ unsigned long flags;
/* axi halt command. */
+
+ spin_lock_irqsave(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
+ axi_ctrl->share_ctrl->stop_ack_pending = TRUE;
+ spin_unlock_irqrestore(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
msm_camera_io_w(AXI_HALT,
axi_ctrl->share_ctrl->vfebase + VFE_AXI_CMD);
wmb();
@@ -5017,6 +5427,9 @@
* to the command register using the barrier */
msm_camera_io_w_mb(VFE_RESET_UPON_STOP_CMD,
axi_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET);
+ if (axi_ctrl->share_ctrl->sync_abort)
+ wait_for_completion_interruptible(
+ &axi_ctrl->share_ctrl->reset_complete);
}
int axi_config_buffers(struct axi_ctrl_t *axi_ctrl,
@@ -5167,8 +5580,12 @@
void axi_start(struct msm_cam_media_controller *pmctl,
struct axi_ctrl_t *axi_ctrl, struct msm_camera_vfe_params_t vfe_params)
{
- uint32_t irq_comp_mask = 0, irq_mask = 0;
+ uint32_t irq_comp_mask = 0, irq_mask = 0, irq_mask1 = 0;
int rc = 0;
+ uint32_t reg_update = 0;
+ uint16_t operation_mode =
+ (axi_ctrl->share_ctrl->current_mode &
+ ~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1));
rc = axi_config_buffers(axi_ctrl, vfe_params);
if (rc < 0)
return;
@@ -5202,59 +5619,55 @@
irq_comp_mask =
msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
VFE_IRQ_COMP_MASK);
+ irq_mask = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_PRIMARY) {
irq_comp_mask |= (
0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1);
+ irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
} else if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
irq_comp_mask |= (
0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1 |
0x1 << axi_ctrl->share_ctrl->outpath.out0.ch2);
+ irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
}
if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_SECONDARY) {
irq_comp_mask |= (
0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch1 + 8));
+ irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
} else if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
irq_comp_mask |= (
0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch1 + 8) |
0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch2 + 8));
+ irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
}
if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_TERTIARY1) {
- irq_mask = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
irq_mask |= (0x1 << (axi_ctrl->share_ctrl->outpath.out2.ch0 +
VFE_WM_OFFSET));
- msm_camera_io_w(irq_mask, axi_ctrl->share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
}
if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_TERTIARY2) {
- irq_mask = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
irq_mask |= (0x1 << (axi_ctrl->share_ctrl->outpath.out3.ch0 +
VFE_WM_OFFSET));
- msm_camera_io_w(irq_mask, axi_ctrl->share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
}
msm_camera_io_w(irq_comp_mask,
axi_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ msm_camera_io_w(irq_mask, axi_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
switch (vfe_params.cmd_type) {
case AXI_CMD_PREVIEW: {
- uint16_t operation_mode =
- (axi_ctrl->share_ctrl->operation_mode &
- ~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1));
-
switch (operation_mode) {
case VFE_OUTPUTS_PREVIEW:
case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
@@ -5356,14 +5769,46 @@
msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
outpath.out3.ch0]);
- atomic_set(&axi_ctrl->share_ctrl->handle_axi_irq, 1);
+
+ irq_mask1 =
+ msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_1);
+
+ if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+ irq_mask1 |= VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK;
+ if (!atomic_cmpxchg(
+ &axi_ctrl->share_ctrl->rdi0_update_ack_pending,
+ 0, 1))
+ reg_update |= 0x2;
+ }
+ if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+ irq_mask1 |= VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK;
+ if (!atomic_cmpxchg(
+ &axi_ctrl->share_ctrl->rdi1_update_ack_pending,
+ 0, 1))
+ reg_update |= 0x4;
+ }
+ msm_camera_io_w(irq_mask1, axi_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_1);
+ if (operation_mode) {
+ if (!atomic_cmpxchg(
+ &axi_ctrl->share_ctrl->pix0_update_ack_pending,
+ 0, 1))
+ reg_update |= 0x1;
+ }
+
+ msm_camera_io_w_mb(reg_update,
+ axi_ctrl->share_ctrl->vfebase +
+ VFE_REG_UPDATE_CMD);
+ axi_ctrl->share_ctrl->operation_mode |=
+ axi_ctrl->share_ctrl->current_mode;
+ axi_enable_irq(axi_ctrl->share_ctrl);
}
void axi_stop(struct msm_cam_media_controller *pmctl,
struct axi_ctrl_t *axi_ctrl, struct msm_camera_vfe_params_t vfe_params)
{
uint32_t reg_update = 0;
- unsigned long flags;
uint32_t operation_mode =
axi_ctrl->share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
VFE_OUTPUTS_RDI1);
@@ -5386,130 +5831,32 @@
return;
}
- if (!axi_ctrl->share_ctrl->skip_abort) {
- atomic_set(&axi_ctrl->share_ctrl->handle_axi_irq, 0);
- axi_disable_irq(axi_ctrl);
+ if (axi_ctrl->share_ctrl->stop_immediately) {
+ axi_disable_irq(axi_ctrl->share_ctrl);
+ axi_stop_process(axi_ctrl->share_ctrl);
+ return;
}
- spin_lock_irqsave(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
- axi_ctrl->share_ctrl->stop_ack_pending = TRUE;
- spin_unlock_irqrestore(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
- switch (vfe_params.cmd_type) {
- case AXI_CMD_PREVIEW: {
- switch (operation_mode) {
- case VFE_OUTPUTS_PREVIEW:
- case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
- if (axi_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
- + vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
- + vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out0.ch1]);
- } else if (axi_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
- + vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
- + vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out0.ch1]);
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
- + vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out0.ch2]);
- }
- break;
- default:
- if (axi_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY) {
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
- + vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
- + vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out1.ch1]);
- } else if (axi_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
- + vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
- + vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out1.ch1]);
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase
- + vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out1.ch2]);
- }
- break;
- }
- }
- break;
- default:
- if (axi_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out0.ch1]);
- } else if (axi_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out0.ch1]);
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out0.ch2]);
- }
-
- if (axi_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY) {
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out1.ch1]);
- } else if (axi_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out1.ch1]);
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[axi_ctrl->
- share_ctrl->outpath.out1.ch2]);
- }
- break;
+ if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+ if (!atomic_cmpxchg(
+ &axi_ctrl->share_ctrl->rdi0_update_ack_pending,
+ 0, 2))
+ reg_update |= 0x2;
}
- if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
- outpath.out2.ch0]);
- if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
- msm_camera_io_w(0, axi_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
- outpath.out3.ch0]);
-
- if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
- reg_update |= 0x2;
- if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
- reg_update |= 0x4;
-
- if (operation_mode)
- reg_update |= 0x1;
+ if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+ if (!atomic_cmpxchg(
+ &axi_ctrl->share_ctrl->rdi1_update_ack_pending,
+ 0, 2))
+ reg_update |= 0x4;
+ }
+ if (operation_mode) {
+ if (!atomic_cmpxchg(
+ &axi_ctrl->share_ctrl->pix0_update_ack_pending,
+ 0, 2))
+ reg_update |= 0x1;
+ }
msm_camera_io_w_mb(reg_update,
axi_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
- if (!axi_ctrl->share_ctrl->skip_abort)
- axi_abort(axi_ctrl);
-
}
static int msm_axi_config(struct v4l2_subdev *sd, void __user *arg)
@@ -5520,7 +5867,6 @@
struct msm_cam_media_controller *pmctl =
(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
int rc = 0, vfe_cmd_type = 0, rdi_mode = 0;
- unsigned long flags;
if (!axi_ctrl->share_ctrl->vfebase) {
pr_err("%s: base address unmapped\n", __func__);
@@ -5716,11 +6062,6 @@
}
axi_ctrl->share_ctrl->current_mode =
vfe_params.operation_mode;
- spin_lock_irqsave(&axi_ctrl->share_ctrl->abort_lock, flags);
- axi_ctrl->share_ctrl->skip_abort =
- vfe_params.skip_abort;
- spin_unlock_irqrestore(&axi_ctrl->share_ctrl->abort_lock,
- flags);
axi_start(pmctl, axi_ctrl, vfe_params);
}
break;
@@ -5733,17 +6074,22 @@
}
axi_ctrl->share_ctrl->current_mode =
vfe_params.operation_mode;
- spin_lock_irqsave(&axi_ctrl->share_ctrl->abort_lock, flags);
- axi_ctrl->share_ctrl->skip_abort =
- vfe_params.skip_abort;
- spin_unlock_irqrestore(&axi_ctrl->share_ctrl->abort_lock,
- flags);
+ axi_ctrl->share_ctrl->stop_immediately =
+ vfe_params.stop_immediately;
axi_stop(pmctl, axi_ctrl, vfe_params);
}
break;
case CMD_AXI_RESET:
axi_reset(axi_ctrl);
break;
+ case CMD_AXI_ABORT:
+ if (copy_from_user(&axi_ctrl->share_ctrl->sync_abort,
+ (void __user *)(vfecmd.value),
+ sizeof(uint8_t))) {
+ return -EFAULT;
+ }
+ axi_abort(axi_ctrl);
+ break;
default:
pr_err("%s Unsupported AXI configuration %x ", __func__,
cfgcmd.cmd_type);
@@ -5756,12 +6102,12 @@
{
struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
uint32_t irqstatus = (uint32_t) arg;
- unsigned long flags;
if (!axi_ctrl->share_ctrl->vfebase) {
pr_err("%s: base address unmapped\n", __func__);
return;
}
+
/* next, check output path related interrupts. */
if (irqstatus &
VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK) {
@@ -5774,12 +6120,12 @@
vfe32_process_output_path_irq_1(axi_ctrl);
}
- if (axi_ctrl->share_ctrl->outpath.output_mode &
+ if (axi_ctrl->share_ctrl->comp_output_mode &
VFE32_OUTPUT_MODE_TERTIARY1)
if (irqstatus & (0x1 << (axi_ctrl->share_ctrl->outpath.out2.ch0
+ VFE_WM_OFFSET)))
vfe32_process_output_path_irq_rdi0(axi_ctrl);
- if (axi_ctrl->share_ctrl->outpath.output_mode &
+ if (axi_ctrl->share_ctrl->comp_output_mode &
VFE32_OUTPUT_MODE_TERTIARY2)
if (irqstatus & (0x1 << (axi_ctrl->share_ctrl->outpath.out3.ch0
+ VFE_WM_OFFSET)))
@@ -5788,15 +6134,15 @@
/* in snapshot mode if done then send
snapshot done message */
if (
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_THUMB_AND_MAIN ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_MAIN_AND_THUMB ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_THUMB_AND_JPEG ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_JPEG_AND_THUMB ||
- axi_ctrl->share_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_RAW) {
if ((axi_ctrl->share_ctrl->outpath.out0.capture_cnt == 0)
&& (axi_ctrl->share_ctrl->outpath.out1.
@@ -5805,17 +6151,10 @@
CAMIF_COMMAND_STOP_IMMEDIATELY,
axi_ctrl->share_ctrl->vfebase +
VFE_CAMIF_COMMAND);
- spin_lock_irqsave(&axi_ctrl->share_ctrl->abort_lock,
- flags);
- if (axi_ctrl->share_ctrl->skip_abort) {
- spin_unlock_irqrestore(&axi_ctrl->share_ctrl->
- abort_lock, flags);
- atomic_set(&axi_ctrl->share_ctrl->
- handle_axi_irq, 0);
- axi_disable_irq(axi_ctrl);
- } else
- spin_unlock_irqrestore(&axi_ctrl->share_ctrl->
- abort_lock, flags);
+ axi_disable_irq(axi_ctrl->share_ctrl);
+ vfe32_send_isp_msg(&axi_ctrl->subdev,
+ axi_ctrl->share_ctrl->vfeFrameId,
+ MSG_ID_PIX0_UPDATE_ACK);
vfe32_send_isp_msg(&axi_ctrl->subdev,
axi_ctrl->share_ctrl->vfeFrameId,
MSG_ID_SNAPSHOT_DONE);
@@ -5893,6 +6232,29 @@
msm_axi_subdev_release(sd);
rc = 0;
break;
+ case VIDIOC_MSM_AXI_RDI_COUNT_UPDATE: {
+ struct rdi_count_msg *msg = (struct rdi_count_msg *)arg;
+ struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+ switch (msg->rdi_interface) {
+ case RDI_0:
+ axi_ctrl->share_ctrl->rdi0FrameId = msg->count;
+ rc = 0;
+ break;
+ case RDI_1:
+ axi_ctrl->share_ctrl->rdi1FrameId = msg->count;
+ rc = 0;
+ break;
+ case RDI_2:
+ axi_ctrl->share_ctrl->rdi2FrameId = msg->count;
+ rc = 0;
+ break;
+ default:
+ pr_err("%s: Incorrect interface sent\n", __func__);
+ rc = -EINVAL;
+ break;
+ }
+ break;
+ }
default:
pr_err("%s: command %d not found\n", __func__,
_IOC_NR(cmd));
@@ -5953,7 +6315,7 @@
share_ctrl->vfe32_ctrl = vfe32_ctrl;
axi_ctrl->share_ctrl = share_ctrl;
vfe32_ctrl->share_ctrl = share_ctrl;
-
+ axi_ctrl->share_ctrl->axi_ref_cnt = 0;
v4l2_subdev_init(&axi_ctrl->subdev, &msm_axi_subdev_ops);
axi_ctrl->subdev.internal_ops = &msm_axi_internal_ops;
axi_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
@@ -6059,6 +6421,21 @@
goto vfe32_no_resource;
}
+#ifdef CONFIG_MSM_IOMMU
+ /*get device context for IOMMU*/
+ axi_ctrl->iommu_ctx_imgwr =
+ msm_iommu_get_ctx("vfe_imgwr"); /*re-confirm*/
+ axi_ctrl->iommu_ctx_misc =
+ msm_iommu_get_ctx("vfe_misc"); /*re-confirm*/
+ if (!axi_ctrl->iommu_ctx_imgwr || !axi_ctrl->iommu_ctx_misc) {
+ release_mem_region(axi_ctrl->vfemem->start,
+ resource_size(axi_ctrl->vfemem));
+ pr_err("%s: No iommu fw context found\n", __func__);
+ rc = -ENODEV;
+ goto vfe32_no_resource;
+ }
+#endif
+
tasklet_init(&axi_ctrl->vfe32_tasklet,
axi32_do_tasklet, (unsigned long)axi_ctrl);
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.h b/drivers/media/video/msm/vfe/msm_vfe32.h
index f4b7edb..985493e 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.h
+++ b/drivers/media/video/msm/vfe/msm_vfe32.h
@@ -62,6 +62,12 @@
* bit 26-32 = 0, domain reset, bit 0-9 = 1 for module reset. */
#define VFE_RESET_UPON_RESET_CMD 0x000003ff
+/* reset the vfe only when reset command*/
+#define VFE_ONLY_RESET_CMD 0x00000002
+
+/*Vfe module reset command*/
+#define VFE_MODULE_RESET_CMD 0x07ffffff
+
/* bit 5 is for axi status idle or busy.
* 1 = halted, 0 = busy */
#define AXI_STATUS_BUSY_MASK 0x00000020
@@ -244,11 +250,11 @@
#define V32_OUT_CLAMP_OFF 0x00000524
#define V32_OUT_CLAMP_LEN 8
-#define V32_OPERATION_CFG_LEN 44
+#define V32_OPERATION_CFG_LEN 32
#define V32_AXI_BUS_CMD_OFF 0x00000038
#define V32_AXI_OUT_OFF 0x0000003C
-#define V32_AXI_OUT_LEN 240
+#define V32_AXI_OUT_LEN 252
#define V32_AXI_CFG_LEN 47
#define V32_AXI_BUS_FMT_OFF 1
#define V32_AXI_BUS_FMT_LEN 4
@@ -787,7 +793,8 @@
#define VFE32_IMASK_ERROR_ONLY_0 0x0
/* when normal case, don't want to block error status. */
/* bit 0-21 are error irq bits */
-#define VFE32_IMASK_ERROR_ONLY_1 0x005FFFFF
+#define VFE32_IMASK_COMMON_ERROR_ONLY_1 0x00407F00
+#define VFE32_IMASK_VFE_ERROR_ONLY_1 0x001F80FF
#define VFE32_IMASK_CAMIF_ERROR (0x00000001<<0)
#define VFE32_IMASK_BHIST_OVWR (0x00000001<<1)
#define VFE32_IMASK_STATS_CS_OVWR (0x00000001<<2)
@@ -941,11 +948,14 @@
uint32_t register_total;
atomic_t vstate;
- atomic_t handle_axi_irq;
+ atomic_t handle_common_irq;
uint32_t vfeFrameId;
+ uint32_t rdi0FrameId;
+ uint32_t rdi1FrameId;
+ uint32_t rdi2FrameId;
uint32_t stats_comp;
+ spinlock_t sd_notify_lock;
spinlock_t stop_flag_lock;
- spinlock_t abort_lock;
int8_t stop_ack_pending;
enum vfe_output_state liveshot_state;
uint32_t vfe_capture_count;
@@ -955,8 +965,13 @@
struct vfe32_output_path outpath;
uint16_t port_info;
- uint32_t skip_abort;
- spinlock_t sd_notify_lock;
+ uint8_t stop_immediately;
+ uint8_t sync_abort;
+ uint16_t cmd_type;
+ uint8_t vfe_reset_flag;
+
+ uint8_t axi_ref_cnt;
+ uint16_t comp_output_mode;
struct completion reset_complete;
@@ -969,9 +984,11 @@
int8_t update_ack_pending;
enum vfe_output_state recording_state;
+ atomic_t pix0_update_ack_pending;
atomic_t rdi0_update_ack_pending;
atomic_t rdi1_update_ack_pending;
atomic_t rdi2_update_ack_pending;
+
};
struct axi_ctrl_t {
@@ -989,6 +1006,8 @@
struct clk *vfe_clk[3];
struct tasklet_struct vfe32_tasklet;
struct vfe_share_ctrl_t *share_ctrl;
+ struct device *iommu_ctx_imgwr;
+ struct device *iommu_ctx_misc;
};
struct vfe32_ctrl_type {
diff --git a/drivers/media/video/msm/vfe/msm_vfe40.c b/drivers/media/video/msm/vfe/msm_vfe40.c
index 5a1d488..1297379 100644
--- a/drivers/media/video/msm/vfe/msm_vfe40.c
+++ b/drivers/media/video/msm/vfe/msm_vfe40.c
@@ -15,226 +15,597 @@
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/io.h>
+#include <linux/of.h>
#include <linux/atomic.h>
#include <linux/regulator/consumer.h>
#include <linux/clk.h>
-#include <linux/of.h>
#include <mach/irqs.h>
#include <mach/camera.h>
#include <media/v4l2-device.h>
#include <media/v4l2-subdev.h>
#include <media/msm_isp.h>
+#include <mach/msm_bus.h>
+#include <mach/msm_bus_board.h>
#include "msm.h"
+#include "msm_cam_server.h"
#include "msm_vfe40.h"
+atomic_t irq_cnt;
+
+#define VFE_WM_CFG_BASE 0x0070
+#define VFE_WM_CFG_LEN 0x0024
+
+#define vfe40_get_ch_ping_addr(base, chn) \
+ (msm_camera_io_r((base) + VFE_WM_CFG_BASE + VFE_WM_CFG_LEN * (chn)))
+#define vfe40_get_ch_pong_addr(base, chn) \
+ (msm_camera_io_r((base) + VFE_WM_CFG_BASE + VFE_WM_CFG_LEN * (chn) + 4))
+#define vfe40_get_ch_addr(ping_pong, base, chn) \
+ ((((ping_pong) & (1 << (chn))) == 0) ? \
+ (vfe40_get_ch_pong_addr((base), chn)) : \
+ (vfe40_get_ch_ping_addr((base), chn)))
+
+#define vfe40_put_ch_ping_addr(base, chn, addr) \
+ (msm_camera_io_w((addr), \
+ (base) + VFE_WM_CFG_BASE + VFE_WM_CFG_LEN * (chn)))
+#define vfe40_put_ch_pong_addr(base, chn, addr) \
+ (msm_camera_io_w((addr), \
+ (base) + VFE_WM_CFG_BASE + VFE_WM_CFG_LEN * (chn) + 4))
+#define vfe40_put_ch_addr(ping_pong, base, chn, addr) \
+ (((ping_pong) & (1 << (chn))) == 0 ? \
+ vfe40_put_ch_pong_addr((base), (chn), (addr)) : \
+ vfe40_put_ch_ping_addr((base), (chn), (addr)))
+
+static uint32_t vfe_clk_rate;
+static void vfe40_send_isp_msg(struct v4l2_subdev *sd,
+ uint32_t vfeFrameId, uint32_t isp_msg_id);
+
+
struct vfe40_isr_queue_cmd {
struct list_head list;
uint32_t vfeInterruptStatus0;
uint32_t vfeInterruptStatus1;
};
-static const char * const vfe40_general_cmd[] = {
- "DUMMY_0", /* 0 */
- "SET_CLK",
- "RESET",
- "START",
- "TEST_GEN_START",
- "OPERATION_CFG", /* 5 */
- "AXI_OUT_CFG",
- "CAMIF_CFG",
- "AXI_INPUT_CFG",
- "BLACK_LEVEL_CFG",
- "ROLL_OFF_CFG", /* 10 */
- "DEMUX_CFG",
- "FOV_CFG",
- "MAIN_SCALER_CFG",
- "WB_CFG",
- "COLOR_COR_CFG", /* 15 */
- "RGB_G_CFG",
- "LA_CFG",
- "CHROMA_EN_CFG",
- "CHROMA_SUP_CFG",
- "MCE_CFG", /* 20 */
- "SK_ENHAN_CFG",
- "ASF_CFG",
- "S2Y_CFG",
- "S2CbCr_CFG",
- "CHROMA_SUBS_CFG", /* 25 */
- "OUT_CLAMP_CFG",
- "FRAME_SKIP_CFG",
- "DUMMY_1",
- "DUMMY_2",
- "DUMMY_3", /* 30 */
- "UPDATE",
- "BL_LVL_UPDATE",
- "DEMUX_UPDATE",
- "FOV_UPDATE",
- "MAIN_SCALER_UPDATE", /* 35 */
- "WB_UPDATE",
- "COLOR_COR_UPDATE",
- "RGB_G_UPDATE",
- "LA_UPDATE",
- "CHROMA_EN_UPDATE", /* 40 */
- "CHROMA_SUP_UPDATE",
- "MCE_UPDATE",
- "SK_ENHAN_UPDATE",
- "S2CbCr_UPDATE",
- "S2Y_UPDATE", /* 45 */
- "ASF_UPDATE",
- "FRAME_SKIP_UPDATE",
- "CAMIF_FRAME_UPDATE",
- "STATS_AF_UPDATE",
- "STATS_AE_UPDATE", /* 50 */
- "STATS_AWB_UPDATE",
- "STATS_RS_UPDATE",
- "STATS_CS_UPDATE",
- "STATS_SKIN_UPDATE",
- "STATS_IHIST_UPDATE", /* 55 */
- "DUMMY_4",
- "EPOCH1_ACK",
- "EPOCH2_ACK",
- "START_RECORDING",
- "STOP_RECORDING", /* 60 */
- "DUMMY_5",
- "DUMMY_6",
- "CAPTURE",
- "DUMMY_7",
- "STOP", /* 65 */
- "GET_HW_VERSION",
- "GET_FRAME_SKIP_COUNTS",
- "OUTPUT1_BUFFER_ENQ",
- "OUTPUT2_BUFFER_ENQ",
- "OUTPUT3_BUFFER_ENQ", /* 70 */
- "JPEG_OUT_BUF_ENQ",
- "RAW_OUT_BUF_ENQ",
- "RAW_IN_BUF_ENQ",
- "STATS_AF_ENQ",
- "STATS_AE_ENQ", /* 75 */
- "STATS_AWB_ENQ",
- "STATS_RS_ENQ",
- "STATS_CS_ENQ",
- "STATS_SKIN_ENQ",
- "STATS_IHIST_ENQ", /* 80 */
- "DUMMY_8",
- "JPEG_ENC_CFG",
- "DUMMY_9",
- "STATS_AF_START",
- "STATS_AF_STOP", /* 85 */
- "STATS_AE_START",
- "STATS_AE_STOP",
- "STATS_AWB_START",
- "STATS_AWB_STOP",
- "STATS_RS_START", /* 90 */
- "STATS_RS_STOP",
- "STATS_CS_START",
- "STATS_CS_STOP",
- "STATS_SKIN_START",
- "STATS_SKIN_STOP", /* 95 */
- "STATS_IHIST_START",
- "STATS_IHIST_STOP",
- "DUMMY_10",
- "SYNC_TIMER_SETTING",
- "ASYNC_TIMER_SETTING", /* 100 */
- "LIVESHOT",
- "LA_SETUP",
- "LINEARIZATION_CFG",
- "DEMOSAICV3",
- "DEMOSAICV3_ABCC_CFG", /* 105 */
- "DEMOSAICV3_DBCC_CFG",
- "DEMOSAICV3_DBPC_CFG",
- "DEMOSAICV3_ABF_CFG",
- "DEMOSAICV3_ABCC_UPDATE",
- "DEMOSAICV3_DBCC_UPDATE", /* 110 */
- "DEMOSAICV3_DBPC_UPDATE",
- "XBAR_CFG",
- "EZTUNE_CFG",
- "V40_ZSL",
- "LINEARIZATION_UPDATE", /*115*/
- "DEMOSAICV3_ABF_UPDATE",
- "CLF_CFG",
- "CLF_LUMA_UPDATE",
- "CLF_CHROMA_UPDATE",
- "PCA_ROLL_OFF_CFG", /*120*/
- "PCA_ROLL_OFF_UPDATE",
- "GET_REG_DUMP",
- "GET_LINEARIZATON_TABLE",
- "GET_MESH_ROLLOFF_TABLE",
- "GET_PCA_ROLLOFF_TABLE", /*125*/
- "GET_RGB_G_TABLE",
- "GET_LA_TABLE",
- "DEMOSAICV3_UPDATE",
- "ACTIVE_REGION_CONFIG",
- "COLOR_PROCESSING_CONFIG", /*130*/
- "STATS_WB_AEC_CONFIG",
- "STATS_WB_AEC_UPDATE",
- "Y_GAMMA_CONFIG",
- "SCALE_OUTPUT1_CONFIG",
- "SCALE_OUTPUT2_CONFIG", /*135*/
- "CAPTURE_RAW",
- "STOP_LIVESHOT",
- "RECONFIG_VFE",
- "STATS_REQBUF_CFG",
- "STATS_ENQUEUEBUF_CFG",/*140*/
- "STATS_FLUSH_BUFQ_CFG",
- "FOV_ENC_CFG",
- "FOV_VIEW_CFG",
- "FOV_ENC_UPDATE",
- "FOV_VIEW_UPDATE",/*145*/
- "SCALER_ENC_CFG",
- "SCALER_VIEW_CFG",
- "SCALER_ENC_UPDATE",
- "SCALER_VIEW_UPDATE",
- "COLORXFORM_ENC_CFG",/*150*/
- "COLORXFORM_VIEW_CFG",
- "COLORXFORM_ENC_UPDATE",
- "COLORXFORM_VIEW_UPDATE",
+static struct vfe40_cmd_type vfe40_cmd[] = {
+ [1] = {VFE_CMD_SET_CLK},
+ [2] = {VFE_CMD_RESET},
+ [3] = {VFE_CMD_START},
+ [4] = {VFE_CMD_TEST_GEN_START},
+ [5] = {VFE_CMD_OPERATION_CFG, V40_OPERATION_CFG_LEN},
+ [6] = {VFE_CMD_AXI_OUT_CFG, V40_AXI_OUT_LEN, V40_AXI_BUS_CMD_OFF, 0xFF},
+ [7] = {VFE_CMD_CAMIF_CFG, V40_CAMIF_LEN, V40_CAMIF_OFF, 0xFF},
+ [8] = {VFE_CMD_AXI_INPUT_CFG},
+ [9] = {VFE_CMD_BLACK_LEVEL_CFG},
+ [10] = {VFE_CMD_MESH_ROLL_OFF_CFG, V40_MESH_ROLL_OFF_CFG_LEN,
+ V40_MESH_ROLL_OFF_CFG_OFF, 0xFF},
+ [11] = {VFE_CMD_DEMUX_CFG, V40_DEMUX_LEN, V40_DEMUX_OFF, 0xFF},
+ [12] = {VFE_CMD_FOV_CFG},
+ [13] = {VFE_CMD_MAIN_SCALER_CFG},
+ [14] = {VFE_CMD_WB_CFG, V40_WB_LEN, V40_WB_OFF, 0xFF},
+ [15] = {VFE_CMD_COLOR_COR_CFG, V40_COLOR_COR_LEN,
+ V40_COLOR_COR_OFF, 0xFF},
+ [16] = {VFE_CMD_RGB_G_CFG, V40_RGB_G_LEN, V40_RGB_G_OFF, 0xFF},
+ [17] = {VFE_CMD_LA_CFG, V40_LA_LEN, V40_LA_OFF, 0xFF },
+ [18] = {VFE_CMD_CHROMA_EN_CFG, V40_CHROMA_EN_LEN, V40_CHROMA_EN_OFF,
+ 0xFF},
+ [19] = {VFE_CMD_CHROMA_SUP_CFG, V40_CHROMA_SUP_LEN,
+ V40_CHROMA_SUP_OFF, 0xFF},
+ [20] = {VFE_CMD_MCE_CFG, V40_MCE_LEN, V40_MCE_OFF, 0xFF},
+ [21] = {VFE_CMD_SK_ENHAN_CFG, V40_SCE_LEN, V40_SCE_OFF, 0xFF},
+ [22] = {VFE_CMD_ASF_CFG, V40_ASF_LEN, V40_ASF_OFF, 0xFF},
+ [23] = {VFE_CMD_S2Y_CFG},
+ [24] = {VFE_CMD_S2CbCr_CFG},
+ [25] = {VFE_CMD_CHROMA_SUBS_CFG},
+ [26] = {VFE_CMD_OUT_CLAMP_CFG, V40_OUT_CLAMP_LEN, V40_OUT_CLAMP_OFF,
+ 0xFF},
+ [27] = {VFE_CMD_FRAME_SKIP_CFG},
+ [31] = {VFE_CMD_UPDATE},
+ [32] = {VFE_CMD_BL_LVL_UPDATE},
+ [33] = {VFE_CMD_DEMUX_UPDATE, V40_DEMUX_LEN, V40_DEMUX_OFF, 0xFF},
+ [34] = {VFE_CMD_FOV_UPDATE},
+ [35] = {VFE_CMD_MAIN_SCALER_UPDATE},
+ [36] = {VFE_CMD_WB_UPDATE, V40_WB_LEN, V40_WB_OFF, 0xFF},
+ [37] = {VFE_CMD_COLOR_COR_UPDATE, V40_COLOR_COR_LEN,
+ V40_COLOR_COR_OFF, 0xFF},
+ [38] = {VFE_CMD_RGB_G_UPDATE, V40_RGB_G_LEN, V40_CHROMA_EN_OFF, 0xFF},
+ [39] = {VFE_CMD_LA_UPDATE, V40_LA_LEN, V40_LA_OFF, 0xFF },
+ [40] = {VFE_CMD_CHROMA_EN_UPDATE, V40_CHROMA_EN_LEN,
+ V40_CHROMA_EN_OFF, 0xFF},
+ [41] = {VFE_CMD_CHROMA_SUP_UPDATE, V40_CHROMA_SUP_LEN,
+ V40_CHROMA_SUP_OFF, 0xFF},
+ [42] = {VFE_CMD_MCE_UPDATE, V40_MCE_LEN, V40_MCE_OFF, 0xFF},
+ [43] = {VFE_CMD_SK_ENHAN_UPDATE, V40_SCE_LEN, V40_SCE_OFF, 0xFF},
+ [44] = {VFE_CMD_S2CbCr_UPDATE},
+ [45] = {VFE_CMD_S2Y_UPDATE},
+ [46] = {VFE_CMD_ASF_UPDATE, V40_ASF_UPDATE_LEN, V40_ASF_OFF, 0xFF},
+ [47] = {VFE_CMD_FRAME_SKIP_UPDATE},
+ [48] = {VFE_CMD_CAMIF_FRAME_UPDATE},
+ [49] = {VFE_CMD_STATS_AF_UPDATE},
+ [50] = {VFE_CMD_STATS_AE_UPDATE},
+ [51] = {VFE_CMD_STATS_AWB_UPDATE, V40_STATS_AWB_LEN,
+ V40_STATS_AWB_OFF},
+ [52] = {VFE_CMD_STATS_RS_UPDATE, V40_STATS_RS_LEN, V40_STATS_RS_OFF},
+ [53] = {VFE_CMD_STATS_CS_UPDATE, V40_STATS_CS_LEN, V40_STATS_CS_OFF},
+ [54] = {VFE_CMD_STATS_SKIN_UPDATE},
+ [55] = {VFE_CMD_STATS_IHIST_UPDATE, V40_STATS_IHIST_LEN,
+ V40_STATS_IHIST_OFF},
+ [57] = {VFE_CMD_EPOCH1_ACK},
+ [58] = {VFE_CMD_EPOCH2_ACK},
+ [59] = {VFE_CMD_START_RECORDING},
+ [60] = {VFE_CMD_STOP_RECORDING},
+ [63] = {VFE_CMD_CAPTURE, V40_CAPTURE_LEN, 0xFF},
+ [65] = {VFE_CMD_STOP},
+ [66] = {VFE_CMD_GET_HW_VERSION, V40_GET_HW_VERSION_LEN,
+ V40_GET_HW_VERSION_OFF},
+ [67] = {VFE_CMD_GET_FRAME_SKIP_COUNTS},
+ [68] = {VFE_CMD_OUTPUT1_BUFFER_ENQ},
+ [69] = {VFE_CMD_OUTPUT2_BUFFER_ENQ},
+ [70] = {VFE_CMD_OUTPUT3_BUFFER_ENQ},
+ [71] = {VFE_CMD_JPEG_OUT_BUF_ENQ},
+ [72] = {VFE_CMD_RAW_OUT_BUF_ENQ},
+ [73] = {VFE_CMD_RAW_IN_BUF_ENQ},
+ [74] = {VFE_CMD_STATS_AF_ENQ},
+ [75] = {VFE_CMD_STATS_AE_ENQ},
+ [76] = {VFE_CMD_STATS_AWB_ENQ},
+ [77] = {VFE_CMD_STATS_RS_ENQ},
+ [78] = {VFE_CMD_STATS_CS_ENQ},
+ [79] = {VFE_CMD_STATS_SKIN_ENQ},
+ [80] = {VFE_CMD_STATS_IHIST_ENQ},
+ [82] = {VFE_CMD_JPEG_ENC_CFG},
+ [84] = {VFE_CMD_STATS_AF_START},
+ [85] = {VFE_CMD_STATS_AF_STOP},
+ [86] = {VFE_CMD_STATS_AE_START},
+ [87] = {VFE_CMD_STATS_AE_STOP},
+ [88] = {VFE_CMD_STATS_AWB_START, V40_STATS_AWB_LEN, V40_STATS_AWB_OFF},
+ [89] = {VFE_CMD_STATS_AWB_STOP},
+ [90] = {VFE_CMD_STATS_RS_START, V40_STATS_RS_LEN, V40_STATS_RS_OFF},
+ [91] = {VFE_CMD_STATS_RS_STOP},
+ [92] = {VFE_CMD_STATS_CS_START, V40_STATS_CS_LEN, V40_STATS_CS_OFF},
+ [93] = {VFE_CMD_STATS_CS_STOP},
+ [94] = {VFE_CMD_STATS_SKIN_START},
+ [95] = {VFE_CMD_STATS_SKIN_STOP},
+ [96] = {VFE_CMD_STATS_IHIST_START,
+ V40_STATS_IHIST_LEN, V40_STATS_IHIST_OFF},
+ [97] = {VFE_CMD_STATS_IHIST_STOP},
+ [99] = {VFE_CMD_SYNC_TIMER_SETTING, V40_SYNC_TIMER_LEN,
+ V40_SYNC_TIMER_OFF},
+ [100] = {VFE_CMD_ASYNC_TIMER_SETTING, V40_ASYNC_TIMER_LEN,
+ V40_ASYNC_TIMER_OFF},
+ [101] = {VFE_CMD_LIVESHOT},
+ [102] = {VFE_CMD_LA_SETUP},
+ [103] = {VFE_CMD_LINEARIZATION_CFG, V40_LINEARIZATION_LEN1,
+ V40_LINEARIZATION_OFF1},
+ [104] = {VFE_CMD_DEMOSAICV3},
+ [105] = {VFE_CMD_DEMOSAICV3_ABCC_CFG},
+ [106] = {VFE_CMD_DEMOSAICV3_DBCC_CFG, V40_DEMOSAICV3_DBCC_LEN,
+ V40_DEMOSAICV3_DBCC_OFF},
+ [107] = {VFE_CMD_DEMOSAICV3_DBPC_CFG},
+ [108] = {VFE_CMD_DEMOSAICV3_ABF_CFG, V40_DEMOSAICV3_ABF_LEN,
+ V40_DEMOSAICV3_ABF_OFF},
+ [109] = {VFE_CMD_DEMOSAICV3_ABCC_UPDATE},
+ [110] = {VFE_CMD_DEMOSAICV3_DBCC_UPDATE, V40_DEMOSAICV3_DBCC_LEN,
+ V40_DEMOSAICV3_DBCC_OFF},
+ [111] = {VFE_CMD_DEMOSAICV3_DBPC_UPDATE},
+ [112] = {VFE_CMD_XBAR_CFG},
+ [113] = {VFE_CMD_MODULE_CFG, V40_MODULE_CFG_LEN, V40_MODULE_CFG_OFF},
+ [114] = {VFE_CMD_ZSL},
+ [115] = {VFE_CMD_LINEARIZATION_UPDATE, V40_LINEARIZATION_LEN1,
+ V40_LINEARIZATION_OFF1},
+ [116] = {VFE_CMD_DEMOSAICV3_ABF_UPDATE, V40_DEMOSAICV3_ABF_LEN,
+ V40_DEMOSAICV3_ABF_OFF},
+ [117] = {VFE_CMD_CLF_CFG, V40_CLF_CFG_LEN, V40_CLF_CFG_OFF},
+ [118] = {VFE_CMD_CLF_LUMA_UPDATE, V40_CLF_LUMA_UPDATE_LEN,
+ V40_CLF_LUMA_UPDATE_OFF},
+ [119] = {VFE_CMD_CLF_CHROMA_UPDATE, V40_CLF_CHROMA_UPDATE_LEN,
+ V40_CLF_CHROMA_UPDATE_OFF},
+ [120] = {VFE_CMD_PCA_ROLL_OFF_CFG},
+ [121] = {VFE_CMD_PCA_ROLL_OFF_UPDATE},
+ [122] = {VFE_CMD_GET_REG_DUMP},
+ [123] = {VFE_CMD_GET_LINEARIZATON_TABLE},
+ [124] = {VFE_CMD_GET_MESH_ROLLOFF_TABLE},
+ [125] = {VFE_CMD_GET_PCA_ROLLOFF_TABLE},
+ [126] = {VFE_CMD_GET_RGB_G_TABLE},
+ [127] = {VFE_CMD_GET_LA_TABLE},
+ [128] = {VFE_CMD_DEMOSAICV3_UPDATE},
+ [129] = {VFE_CMD_ACTIVE_REGION_CFG},
+ [130] = {VFE_CMD_COLOR_PROCESSING_CONFIG},
+ [131] = {VFE_CMD_STATS_WB_AEC_CONFIG},
+ [132] = {VFE_CMD_STATS_WB_AEC_UPDATE},
+ [133] = {VFE_CMD_Y_GAMMA_CONFIG},
+ [134] = {VFE_CMD_SCALE_OUTPUT1_CONFIG},
+ [135] = {VFE_CMD_SCALE_OUTPUT2_CONFIG},
+ [136] = {VFE_CMD_CAPTURE_RAW},
+ [137] = {VFE_CMD_STOP_LIVESHOT},
+ [138] = {VFE_CMD_RECONFIG_VFE},
+ [139] = {VFE_CMD_STATS_REQBUF},
+ [140] = {VFE_CMD_STATS_ENQUEUEBUF},
+ [141] = {VFE_CMD_STATS_FLUSH_BUFQ},
+ [142] = {VFE_CMD_STATS_UNREGBUF},
+ [143] = {VFE_CMD_STATS_BG_START, V40_STATS_BG_LEN, V40_STATS_BG_OFF},
+ [144] = {VFE_CMD_STATS_BG_STOP},
+ [145] = {VFE_CMD_STATS_BF_START, V40_STATS_BF_LEN, V40_STATS_BF_OFF},
+ [146] = {VFE_CMD_STATS_BF_STOP},
+ [147] = {VFE_CMD_STATS_BHIST_START, V40_STATS_BHIST_LEN,
+ V40_STATS_BHIST_OFF},
+ [148] = {VFE_CMD_STATS_BHIST_STOP},
+ [149] = {VFE_CMD_RESET_2},
+ [150] = {VFE_CMD_FOV_ENC_CFG, V40_FOV_ENC_LEN,
+ V40_FOV_ENC_OFF, 0xFF},
+ [151] = {VFE_CMD_FOV_VIEW_CFG, V40_FOV_VIEW_LEN,
+ V40_FOV_VIEW_OFF, 0xFF},
+ [152] = {VFE_CMD_FOV_ENC_UPDATE, V40_FOV_ENC_LEN,
+ V40_FOV_ENC_OFF, 0xFF},
+ [153] = {VFE_CMD_FOV_VIEW_UPDATE, V40_FOV_VIEW_LEN,
+ V40_FOV_VIEW_OFF, 0xFF},
+ [154] = {VFE_CMD_SCALER_ENC_CFG, V40_SCALER_ENC_LEN,
+ V40_SCALER_ENC_OFF, 0xFF},
+ [155] = {VFE_CMD_SCALER_VIEW_CFG, V40_SCALER_VIEW_LEN,
+ V40_SCALER_VIEW_OFF, 0xFF},
+ [156] = {VFE_CMD_SCALER_ENC_UPDATE, V40_SCALER_ENC_LEN,
+ V40_SCALER_ENC_OFF, 0xFF},
+ [157] = {VFE_CMD_SCALER_VIEW_UPDATE, V40_SCALER_VIEW_LEN,
+ V40_SCALER_VIEW_OFF, 0xFF},
+ [158] = {VFE_CMD_COLORXFORM_ENC_CFG, V40_COLORXFORM_ENC_CFG_LEN,
+ V40_COLORXFORM_ENC_CFG_OFF, 0xFF},
+ [159] = {VFE_CMD_COLORXFORM_VIEW_CFG, V40_COLORXFORM_VIEW_CFG_LEN,
+ V40_COLORXFORM_VIEW_CFG_OFF},
+ [160] = {VFE_CMD_COLORXFORM_ENC_UPDATE, V40_COLORXFORM_ENC_CFG_LEN,
+ V40_COLORXFORM_ENC_CFG_OFF, 0xFF},
+ [161] = {VFE_CMD_COLORXFORM_VIEW_UPDATE, V40_COLORXFORM_VIEW_CFG_LEN,
+ V40_COLORXFORM_VIEW_CFG_OFF, 0xFF},
};
-static void vfe40_stop(struct vfe40_ctrl_type *vfe40_ctrl)
+static const uint32_t vfe40_AXI_WM_CFG[] = {
+ 0x0000006C,
+ 0x00000090,
+ 0x000000B4,
+ 0x000000D8,
+ 0x000000FC,
+ 0x00000120,
+ 0x00000144,
+};
+
+static const char * const vfe40_general_cmd[] = {
+ [1] = "SET_CLK",
+ [2] = "RESET",
+ [3] = "START",
+ [4] = "TEST_GEN_START",
+ [5] = "OPERATION_CFG", /* 5 */
+ [6] = "AXI_OUT_CFG",
+ [7] = "CAMIF_CFG",
+ [8] = "AXI_INPUT_CFG",
+ [9] = "BLACK_LEVEL_CFG",
+ [10] = "ROLL_OFF_CFG", /* 10 */
+ [11] = "DEMUX_CFG",
+ [12] = "FOV_CFG",
+ [13] = "MAIN_SCALER_CFG",
+ [14] = "WB_CFG",
+ [15] = "COLOR_COR_CFG", /* 15 */
+ [16] = "RGB_G_CFG",
+ [17] = "LA_CFG",
+ [18] = "CHROMA_EN_CFG",
+ [19] = "CHROMA_SUP_CFG",
+ [20] = "MCE_CFG", /* 20 */
+ [21] = "SK_ENHAN_CFG",
+ [22] = "ASF_CFG",
+ [23] = "S2Y_CFG",
+ [24] = "S2CbCr_CFG",
+ [25] = "CHROMA_SUBS_CFG", /* 25 */
+ [26] = "OUT_CLAMP_CFG",
+ [27] = "FRAME_SKIP_CFG",
+ [31] = "UPDATE",
+ [32] = "BL_LVL_UPDATE",
+ [33] = "DEMUX_UPDATE",
+ [34] = "FOV_UPDATE",
+ [35] = "MAIN_SCALER_UPDATE", /* 35 */
+ [36] = "WB_UPDATE",
+ [37] = "COLOR_COR_UPDATE",
+ [38] = "RGB_G_UPDATE",
+ [39] = "LA_UPDATE",
+ [40] = "CHROMA_EN_UPDATE", /* 40 */
+ [41] = "CHROMA_SUP_UPDATE",
+ [42] = "MCE_UPDATE",
+ [43] = "SK_ENHAN_UPDATE",
+ [44] = "S2CbCr_UPDATE",
+ [45] = "S2Y_UPDATE", /* 45 */
+ [46] = "ASF_UPDATE",
+ [47] = "FRAME_SKIP_UPDATE",
+ [48] = "CAMIF_FRAME_UPDATE",
+ [49] = "STATS_AF_UPDATE",
+ [50] = "STATS_AE_UPDATE", /* 50 */
+ [51] = "STATS_AWB_UPDATE",
+ [52] = "STATS_RS_UPDATE",
+ [53] = "STATS_CS_UPDATE",
+ [54] = "STATS_SKIN_UPDATE",
+ [55] = "STATS_IHIST_UPDATE", /* 55 */
+ [57] = "EPOCH1_ACK",
+ [58] = "EPOCH2_ACK",
+ [59] = "START_RECORDING",
+ [60] = "STOP_RECORDING", /* 60 */
+ [63] = "CAPTURE",
+ [65] = "STOP", /* 65 */
+ [66] = "GET_HW_VERSION",
+ [67] = "GET_FRAME_SKIP_COUNTS",
+ [68] = "OUTPUT1_BUFFER_ENQ",
+ [69] = "OUTPUT2_BUFFER_ENQ",
+ [70] = "OUTPUT3_BUFFER_ENQ", /* 70 */
+ [71] = "JPEG_OUT_BUF_ENQ",
+ [72] = "RAW_OUT_BUF_ENQ",
+ [73] = "RAW_IN_BUF_ENQ",
+ [74] = "STATS_AF_ENQ",
+ [75] = "STATS_AE_ENQ", /* 75 */
+ [76] = "STATS_AWB_ENQ",
+ [77] = "STATS_RS_ENQ",
+ [78] = "STATS_CS_ENQ",
+ [79] = "STATS_SKIN_ENQ",
+ [80] = "STATS_IHIST_ENQ", /* 80 */
+ [82] = "JPEG_ENC_CFG",
+ [84] = "STATS_AF_START",
+ [85] = "STATS_AF_STOP", /* 85 */
+ [86] = "STATS_AE_START",
+ [87] = "STATS_AE_STOP",
+ [88] = "STATS_AWB_START",
+ [89] = "STATS_AWB_STOP",
+ [90] = "STATS_RS_START", /* 90 */
+ [91] = "STATS_RS_STOP",
+ [92] = "STATS_CS_START",
+ [93] = "STATS_CS_STOP",
+ [94] = "STATS_SKIN_START",
+ [95] = "STATS_SKIN_STOP", /* 95 */
+ [96] = "STATS_IHIST_START",
+ [97] = "STATS_IHIST_STOP",
+ [99] = "SYNC_TIMER_SETTING",
+ [100] = "ASYNC_TIMER_SETTING", /* 100 */
+ [101] = "LIVESHOT",
+ [102] = "LA_SETUP",
+ [103] = "LINEARIZATION_CFG",
+ [104] = "DEMOSAICV3",
+ [105] = "DEMOSAICV3_ABCC_CFG", /* 105 */
+ [106] = "DEMOSAICV3_DBCC_CFG",
+ [107] = "DEMOSAICV3_DBPC_CFG",
+ [108] = "DEMOSAICV3_ABF_CFG",
+ [109] = "DEMOSAICV3_ABCC_UPDATE",
+ [110] = "DEMOSAICV3_DBCC_UPDATE", /* 110 */
+ [111] = "DEMOSAICV3_DBPC_UPDATE",
+ [112] = "XBAR_CFG",
+ [113] = "EZTUNE_CFG",
+ [114] = "V40_ZSL",
+ [115] = "LINEARIZATION_UPDATE", /*115*/
+ [116] = "DEMOSAICV3_ABF_UPDATE",
+ [117] = "CLF_CFG",
+ [118] = "CLF_LUMA_UPDATE",
+ [119] = "CLF_CHROMA_UPDATE",
+ [120] = "PCA_ROLL_OFF_CFG", /*120*/
+ [121] = "PCA_ROLL_OFF_UPDATE",
+ [122] = "GET_REG_DUMP",
+ [123] = "GET_LINEARIZATON_TABLE",
+ [124] = "GET_MESH_ROLLOFF_TABLE",
+ [125] = "GET_PCA_ROLLOFF_TABLE", /*125*/
+ [126] = "GET_RGB_G_TABLE",
+ [127] = "GET_LA_TABLE",
+ [128] = "DEMOSAICV3_UPDATE",
+ [139] = "STATS_REQBUF",
+ [140] = "STATS_ENQUEUEBUF", /*140*/
+ [141] = "STATS_FLUSH_BUFQ",
+ [142] = "STATS_UNREGBUF",
+ [143] = "STATS_BG_START",
+ [144] = "STATS_BG_STOP",
+ [145] = "STATS_BF_START", /*145*/
+ [146] = "STATS_BF_STOP",
+ [147] = "STATS_BHIST_START",
+ [148] = "STATS_BHIST_STOP",
+ [149] = "RESET_2",
+};
+
+/*Temporary use fixed bus vectors in VFE */
+static struct msm_bus_vectors vfe_init_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+static struct msm_bus_vectors vfe_preview_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 27648000,
+ .ib = 110592000,
+ },
+};
+
+static struct msm_bus_vectors vfe_video_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 154275840,
+ .ib = 617103360,
+ },
+};
+
+static struct msm_bus_vectors vfe_snapshot_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 274423680,
+ .ib = 1097694720,
+ },
+};
+
+static struct msm_bus_vectors vfe_zsl_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 302071680,
+ .ib = 1208286720,
+ },
+};
+
+static struct msm_bus_paths vfe_bus_client_config[] = {
+ {
+ ARRAY_SIZE(vfe_init_vectors),
+ vfe_init_vectors,
+ },
+ {
+ ARRAY_SIZE(vfe_preview_vectors),
+ vfe_preview_vectors,
+ },
+ {
+ ARRAY_SIZE(vfe_video_vectors),
+ vfe_video_vectors,
+ },
+ {
+ ARRAY_SIZE(vfe_snapshot_vectors),
+ vfe_snapshot_vectors,
+ },
+ {
+ ARRAY_SIZE(vfe_zsl_vectors),
+ vfe_zsl_vectors,
+ },
+};
+
+static struct msm_bus_scale_pdata vfe_bus_client_pdata = {
+ vfe_bus_client_config,
+ ARRAY_SIZE(vfe_bus_client_config),
+ .name = "msm_camera_vfe",
+};
+
+uint8_t vfe40_use_bayer_stats(struct vfe40_ctrl_type *vfe40_ctrl)
{
- unsigned long flags;
+ if (vfe40_ctrl->ver_num.main >= 4) {
+ /* VFE 4 or above uses bayer stats */
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
- atomic_set(&vfe40_ctrl->share_ctrl->vstate, 0);
+static void axi_enable_irq(struct vfe_share_ctrl_t *share_ctrl)
+{
+ uint32_t irq_mask;
+ uint16_t vfe_operation_mode =
+ share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+ VFE_OUTPUTS_RDI1);
+ irq_mask =
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
- /* for reset hw modules, and send msg when reset_irq comes.*/
- spin_lock_irqsave(&vfe40_ctrl->share_ctrl->stop_flag_lock, flags);
- vfe40_ctrl->share_ctrl->stop_ack_pending = TRUE;
- spin_unlock_irqrestore(&vfe40_ctrl->share_ctrl->stop_flag_lock, flags);
+ irq_mask |= VFE_IMASK_WHILE_STOPPING_0;
+
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
+ irq_mask |= VFE_IRQ_STATUS0_RDI0_REG_UPDATE_MASK;
+
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
+ irq_mask |= VFE_IRQ_STATUS0_RDI1_REG_UPDATE_MASK;
+
+ msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+
+ if (vfe_operation_mode) {
+ irq_mask =
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ irq_mask |= 0x00000021;
+ if (share_ctrl->stats_comp)
+ irq_mask |= VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK_0;
+ else
+ irq_mask |= 0x00FF0000;
+ msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ atomic_set(&share_ctrl->vstate, 1);
+ }
+ atomic_set(&share_ctrl->handle_common_irq, 1);
+}
+
+static void axi_disable_irq(struct vfe_share_ctrl_t *share_ctrl)
+{
/* disable all interrupts. */
+
+ uint32_t irq_mask = 0;
+ uint16_t vfe_operation_mode =
+ share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+ VFE_OUTPUTS_RDI1);
+
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+ irq_mask =
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ irq_mask &= ~(VFE_IRQ_STATUS0_RDI0_REG_UPDATE_MASK);
+ msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ msm_camera_io_w(VFE_IRQ_STATUS0_RDI0_REG_UPDATE_MASK,
+ share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+ }
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+ irq_mask =
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ irq_mask &= ~(VFE_IRQ_STATUS0_RDI1_REG_UPDATE_MASK);
+ msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ msm_camera_io_w(VFE_IRQ_STATUS0_RDI1_REG_UPDATE_MASK,
+ share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+ }
+ if (vfe_operation_mode) {
+ atomic_set(&share_ctrl->vstate, 0);
+ irq_mask =
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ irq_mask &= ~(0x00000011);
+ if (share_ctrl->stats_comp)
+ irq_mask &= ~(VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK_0);
+ else
+ irq_mask &= ~0x00FF0000;
+ msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ }
+
+ if (share_ctrl->axi_ref_cnt == 1) {
+ atomic_set(&share_ctrl->handle_common_irq, 0);
msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
+ share_ctrl->vfebase + VFE_IRQ_MASK_0);
msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
+ share_ctrl->vfebase + VFE_IRQ_MASK_1);
/* clear all pending interrupts*/
- msm_camera_io_w(VFE_CLEAR_ALL_IRQ0,
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
- msm_camera_io_w(VFE_CLEAR_ALL_IRQ1,
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+ msm_camera_io_w(0xFFFFFFFF,
+ share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+ msm_camera_io_w(0xFFFFFFFF,
+ share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
/* Ensure the write order while writing
to the command register using the barrier */
msm_camera_io_w_mb(1,
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_CMD);
+ share_ctrl->vfebase + VFE_IRQ_CMD);
+ }
+}
+
+static void vfe40_stop(struct vfe40_ctrl_type *vfe40_ctrl)
+{
/* in either continuous or snapshot mode, stop command can be issued
* at any time. stop camif immediately. */
msm_camera_io_w(CAMIF_COMMAND_STOP_IMMEDIATELY,
vfe40_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
+ vfe40_ctrl->share_ctrl->operation_mode &=
+ ~(vfe40_ctrl->share_ctrl->current_mode);
+ vfe40_ctrl->share_ctrl->current_mode = 0;
}
-void vfe40_subdev_notify(int id, int path, int image_mode,
+static void vfe40_subdev_notify(int id, int path, uint32_t inst_handle,
struct v4l2_subdev *sd, struct vfe_share_ctrl_t *share_ctrl)
{
struct msm_vfe_resp rp;
struct msm_frame_info frame_info;
unsigned long flags = 0;
spin_lock_irqsave(&share_ctrl->sd_notify_lock, flags);
- CDBG("%s: msgId = %d\n", __func__, id);
+ CDBG("vfe40_subdev_notify : msgId = %d\n", id);
memset(&rp, 0, sizeof(struct msm_vfe_resp));
rp.evt_msg.type = MSM_CAMERA_MSG;
- frame_info.image_mode = image_mode;
+ frame_info.inst_handle = inst_handle;
frame_info.path = path;
rp.evt_msg.data = &frame_info;
rp.type = id;
@@ -242,45 +613,249 @@
spin_unlock_irqrestore(&share_ctrl->sd_notify_lock, flags);
}
+static int vfe40_config_axi(
+ struct axi_ctrl_t *axi_ctrl, int mode, uint32_t *ao)
+{
+ uint32_t *ch_info;
+ uint32_t *axi_cfg = ao;
+ int vfe_mode = (mode & ~(OUTPUT_TERT1|OUTPUT_TERT2));
+
+ /* Update the corresponding write masters for each output*/
+ ch_info = axi_cfg + V40_AXI_CFG_LEN;
+ axi_ctrl->share_ctrl->outpath.out0.ch0 = 0x0000FFFF & *ch_info;
+ axi_ctrl->share_ctrl->outpath.out0.ch1 =
+ 0x0000FFFF & (*ch_info++ >> 16);
+ axi_ctrl->share_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info++;
+ axi_ctrl->share_ctrl->outpath.out0.inst_handle = *ch_info++;
+
+ axi_ctrl->share_ctrl->outpath.out1.ch0 = 0x0000FFFF & *ch_info;
+ axi_ctrl->share_ctrl->outpath.out1.ch1 =
+ 0x0000FFFF & (*ch_info++ >> 16);
+ axi_ctrl->share_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info++;
+ axi_ctrl->share_ctrl->outpath.out1.inst_handle = *ch_info++;
+
+ axi_ctrl->share_ctrl->outpath.out2.ch0 = 0x0000FFFF & *ch_info;
+ axi_ctrl->share_ctrl->outpath.out2.ch1 =
+ 0x0000FFFF & (*ch_info++ >> 16);
+ axi_ctrl->share_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info++;
+ axi_ctrl->share_ctrl->outpath.out2.inst_handle = *ch_info++;
+
+ axi_ctrl->share_ctrl->outpath.out3.ch0 = 0x0000FFFF & *ch_info;
+ axi_ctrl->share_ctrl->outpath.out3.ch1 =
+ 0x0000FFFF & (*ch_info++ >> 16);
+ axi_ctrl->share_ctrl->outpath.out3.ch2 = 0x0000FFFF & *ch_info++;
+ axi_ctrl->share_ctrl->outpath.out3.inst_handle = *ch_info++;
+
+ axi_ctrl->share_ctrl->outpath.output_mode = 0;
+
+ if (mode & OUTPUT_TERT1)
+ axi_ctrl->share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_TERTIARY1;
+ if (mode & OUTPUT_TERT2)
+ axi_ctrl->share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_TERTIARY2;
+ if (mode == OUTPUT_TERT1 || mode == OUTPUT_TERT1
+ || mode == (OUTPUT_TERT1|OUTPUT_TERT2))
+ goto bus_cfg;
+
+ switch (vfe_mode) {
+ case OUTPUT_PRIM:
+ axi_ctrl->share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_PRIMARY;
+ break;
+ case OUTPUT_PRIM_ALL_CHNLS:
+ axi_ctrl->share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
+ break;
+ case OUTPUT_PRIM|OUTPUT_SEC:
+ axi_ctrl->share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_PRIMARY;
+ axi_ctrl->share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_SECONDARY;
+ break;
+ case OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS:
+ axi_ctrl->share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_PRIMARY;
+ axi_ctrl->share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
+ break;
+ case OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC:
+ axi_ctrl->share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
+ axi_ctrl->share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_SECONDARY;
+ break;
+ default:
+ pr_err("%s Invalid AXI mode %d ", __func__, mode);
+ return -EINVAL;
+ }
+
+bus_cfg:
+ msm_camera_io_memcpy(axi_ctrl->share_ctrl->vfebase +
+ vfe40_cmd[VFE_CMD_AXI_OUT_CFG].offset, axi_cfg,
+ V40_AXI_BUS_CFG_LEN);
+ msm_camera_io_w(*ch_info++,
+ axi_ctrl->share_ctrl->vfebase + VFE_RDI0_CFG);
+ msm_camera_io_w(*ch_info++,
+ axi_ctrl->share_ctrl->vfebase + VFE_RDI1_CFG);
+ msm_camera_io_w(*ch_info++,
+ axi_ctrl->share_ctrl->vfebase + VFE_RDI2_CFG);
+ return 0;
+}
+
+static void axi_reset_internal_variables(
+ struct axi_ctrl_t *axi_ctrl)
+{
+ unsigned long flags;
+ /* state control variables */
+ axi_ctrl->share_ctrl->start_ack_pending = FALSE;
+ atomic_set(&irq_cnt, 0);
+
+ spin_lock_irqsave(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
+ axi_ctrl->share_ctrl->stop_ack_pending = FALSE;
+ spin_unlock_irqrestore(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
+
+ spin_lock_irqsave(&axi_ctrl->share_ctrl->update_ack_lock, flags);
+ axi_ctrl->share_ctrl->update_ack_pending = FALSE;
+ spin_unlock_irqrestore(&axi_ctrl->share_ctrl->update_ack_lock, flags);
+
+ axi_ctrl->share_ctrl->recording_state = VFE_STATE_IDLE;
+ axi_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
+
+ atomic_set(&axi_ctrl->share_ctrl->vstate, 0);
+ atomic_set(&axi_ctrl->share_ctrl->handle_common_irq, 0);
+ atomic_set(&axi_ctrl->share_ctrl->pix0_update_ack_pending, 0);
+ atomic_set(&axi_ctrl->share_ctrl->rdi0_update_ack_pending, 0);
+ atomic_set(&axi_ctrl->share_ctrl->rdi1_update_ack_pending, 0);
+ atomic_set(&axi_ctrl->share_ctrl->rdi2_update_ack_pending, 0);
+
+ /* 0 for continuous mode, 1 for snapshot mode */
+ axi_ctrl->share_ctrl->operation_mode = 0;
+ axi_ctrl->share_ctrl->current_mode = 0;
+ axi_ctrl->share_ctrl->outpath.output_mode = 0;
+ axi_ctrl->share_ctrl->comp_output_mode = 0;
+ axi_ctrl->share_ctrl->vfe_capture_count = 0;
+
+ /* this is unsigned 32 bit integer. */
+ axi_ctrl->share_ctrl->vfeFrameId = 0;
+ axi_ctrl->share_ctrl->rdi0FrameId = 0;
+ axi_ctrl->share_ctrl->rdi1FrameId = 0;
+ axi_ctrl->share_ctrl->rdi2FrameId = 0;
+}
+
+static void vfe40_program_dmi_cfg(
+ enum VFE40_DMI_RAM_SEL bankSel,
+ struct vfe40_ctrl_type *vfe40_ctrl)
+{
+ /* set bit 8 for auto increment. */
+ uint32_t value = VFE_DMI_CFG_DEFAULT;
+ value += (uint32_t)bankSel;
+ CDBG("%s: banksel = %d\n", __func__, bankSel);
+
+ msm_camera_io_w(value, vfe40_ctrl->share_ctrl->vfebase +
+ VFE_DMI_CFG);
+ /* by default, always starts with offset 0.*/
+ msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
+ VFE_DMI_ADDR);
+}
+
+static void vfe40_reset_dmi_tables(
+ struct vfe40_ctrl_type *vfe40_ctrl)
+{
+ int i = 0;
+
+ /* Reset Histogram LUTs */
+ CDBG("Reset Bayer histogram LUT : 0\n");
+ vfe40_program_dmi_cfg(STATS_BHIST_RAM0, vfe40_ctrl);
+ /* Loop for configuring LUT */
+ for (i = 0; i < 256; i++) {
+ msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
+ VFE_DMI_DATA_HI);
+ msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
+ VFE_DMI_DATA_LO);
+ }
+ vfe40_program_dmi_cfg(NO_MEM_SELECTED, vfe40_ctrl);
+
+ CDBG("Reset Bayer Histogram LUT: 1\n");
+ vfe40_program_dmi_cfg(STATS_BHIST_RAM1, vfe40_ctrl);
+ /* Loop for configuring LUT */
+ for (i = 0; i < 256; i++) {
+ msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
+ VFE_DMI_DATA_HI);
+ msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
+ VFE_DMI_DATA_LO);
+ }
+ vfe40_program_dmi_cfg(NO_MEM_SELECTED, vfe40_ctrl);
+
+ CDBG("Reset IHistogram LUT\n");
+ vfe40_program_dmi_cfg(STATS_IHIST_RAM, vfe40_ctrl);
+ /* Loop for configuring LUT */
+ for (i = 0; i < 256; i++) {
+ msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
+ VFE_DMI_DATA_HI);
+ msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
+ VFE_DMI_DATA_LO);
+ }
+ vfe40_program_dmi_cfg(NO_MEM_SELECTED, vfe40_ctrl);
+}
+
+static void vfe40_set_default_reg_values(
+ struct vfe40_ctrl_type *vfe40_ctrl)
+{
+ msm_camera_io_w(0x800080,
+ vfe40_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_0);
+ msm_camera_io_w(0x800080,
+ vfe40_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_1);
+ msm_camera_io_w(0xFFFFF,
+ vfe40_ctrl->share_ctrl->vfebase + VFE_CGC_OVERRIDE);
+
+ msm_camera_io_w(0,
+ vfe40_ctrl->share_ctrl->vfebase + VFE_CLAMP_ENC_MIN);
+ msm_camera_io_w(0xFFFFFF,
+ vfe40_ctrl->share_ctrl->vfebase + VFE_CLAMP_ENC_MAX);
+ msm_camera_io_w(0,
+ vfe40_ctrl->share_ctrl->vfebase + VFE_CLAMP_VIEW_MIN);
+ msm_camera_io_w(0xFFFFFF,
+ vfe40_ctrl->share_ctrl->vfebase + VFE_CLAMP_VIEW_MAX);
+
+ /* stats UB config */
+ CDBG("%s: Use bayer stats = %d\n", __func__,
+ vfe40_use_bayer_stats(vfe40_ctrl));
+ msm_camera_io_w(0x350001F,
+ vfe40_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_HIST_WR_UB_CFG);
+ msm_camera_io_w(0x370002F,
+ vfe40_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_BG_WR_UB_CFG);
+ msm_camera_io_w(0x3A0002F,
+ vfe40_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_BF_WR_UB_CFG);
+ msm_camera_io_w(0x3D00007,
+ vfe40_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_RS_WR_UB_CFG);
+ msm_camera_io_w(0x3D8001F,
+ vfe40_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_CS_WR_UB_CFG);
+ msm_camera_io_w(0x3F80007,
+ vfe40_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_SKIN_WR_UB_CFG);
+ vfe40_reset_dmi_tables(vfe40_ctrl);
+}
+
static void vfe40_reset_internal_variables(
struct vfe40_ctrl_type *vfe40_ctrl)
{
- unsigned long flags;
- vfe40_ctrl->vfeImaskCompositePacked = 0;
- /* state control variables */
- vfe40_ctrl->start_ack_pending = FALSE;
- atomic_set(&vfe40_ctrl->share_ctrl->irq_cnt, 0);
-
- spin_lock_irqsave(&vfe40_ctrl->share_ctrl->stop_flag_lock, flags);
- vfe40_ctrl->share_ctrl->stop_ack_pending = FALSE;
- spin_unlock_irqrestore(&vfe40_ctrl->share_ctrl->stop_flag_lock, flags);
-
- vfe40_ctrl->reset_ack_pending = FALSE;
-
- spin_lock_irqsave(&vfe40_ctrl->update_ack_lock, flags);
- vfe40_ctrl->update_ack_pending = FALSE;
- spin_unlock_irqrestore(&vfe40_ctrl->update_ack_lock, flags);
-
- vfe40_ctrl->recording_state = VFE_STATE_IDLE;
- vfe40_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
-
- atomic_set(&vfe40_ctrl->share_ctrl->vstate, 0);
-
- /* 0 for continuous mode, 1 for snapshot mode */
- vfe40_ctrl->share_ctrl->operation_mode = 0;
- vfe40_ctrl->share_ctrl->outpath.output_mode = 0;
- vfe40_ctrl->share_ctrl->vfe_capture_count = 0;
-
- /* this is unsigned 32 bit integer. */
- vfe40_ctrl->share_ctrl->vfeFrameId = 0;
/* Stats control variables. */
- memset(&(vfe40_ctrl->afStatsControl), 0,
+ memset(&(vfe40_ctrl->afbfStatsControl), 0,
sizeof(struct vfe_stats_control));
memset(&(vfe40_ctrl->awbStatsControl), 0,
sizeof(struct vfe_stats_control));
- memset(&(vfe40_ctrl->aecStatsControl), 0,
+ memset(&(vfe40_ctrl->aecbgStatsControl), 0,
+ sizeof(struct vfe_stats_control));
+
+ memset(&(vfe40_ctrl->bhistStatsControl), 0,
sizeof(struct vfe_stats_control));
memset(&(vfe40_ctrl->ihistStatsControl), 0,
@@ -295,32 +870,59 @@
vfe40_ctrl->frame_skip_cnt = 31;
vfe40_ctrl->frame_skip_pattern = 0xffffffff;
vfe40_ctrl->snapshot_frame_cnt = 0;
+ vfe40_set_default_reg_values(vfe40_ctrl);
}
-static void vfe40_reset(struct vfe40_ctrl_type *vfe40_ctrl)
+static int vfe40_reset(struct vfe40_ctrl_type *vfe40_ctrl)
{
- vfe40_reset_internal_variables(vfe40_ctrl);
+ uint32_t irq_mask;
+ atomic_set(&vfe40_ctrl->share_ctrl->vstate, 0);
+ msm_camera_io_w(VFE_MODULE_RESET_CMD,
+ vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_RESET);
+ msm_camera_io_w(0,
+ vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_RESET);
+
+ irq_mask =
+ msm_camera_io_r(vfe40_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ irq_mask &= ~(0x00FF0011|VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK_0);
+
+ /* enable reset_ack interrupt. */
+ irq_mask |= VFE_IMASK_WHILE_STOPPING_0;
+ msm_camera_io_w(irq_mask, vfe40_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+
+ msm_camera_io_w_mb(VFE_ONLY_RESET_CMD,
+ vfe40_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET);
+
+ return wait_for_completion_interruptible(
+ &vfe40_ctrl->share_ctrl->reset_complete);
+}
+
+static int axi_reset(struct axi_ctrl_t *axi_ctrl)
+{
+ axi_reset_internal_variables(axi_ctrl);
/* disable all interrupts. vfeImaskLocal is also reset to 0
* to begin with. */
msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
+ axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
+ axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
/* clear all pending interrupts*/
- msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
- msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+ msm_camera_io_w(VFE_CLEAR_ALL_IRQ0,
+ axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+ msm_camera_io_w(VFE_CLEAR_ALL_IRQ1,
+ axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
/* Ensure the write order while writing
to the command register using the barrier */
- msm_camera_io_w_mb(1, vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_CMD);
+ msm_camera_io_w_mb(1, axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CMD);
/* enable reset_ack interrupt. */
- msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1,
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
+ msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_0,
+ axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
/* Write to VFE_GLOBAL_RESET_CMD to reset the vfe hardware. Once reset
* is done, hardware interrupt will be generated. VFE ist processes
@@ -330,24 +932,10 @@
/* Ensure the write order while writing
to the command register using the barrier */
msm_camera_io_w_mb(VFE_RESET_UPON_RESET_CMD,
- vfe40_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET);
+ axi_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET);
- msm_camera_io_w(0xAAAAAAAA,
- vfe40_ctrl->share_ctrl->vfebase + VFE_0_BUS_BDG_QOS_CFG_0);
- msm_camera_io_w(0xAAAAAAAA,
- vfe40_ctrl->share_ctrl->vfebase + VFE_0_BUS_BDG_QOS_CFG_1);
- msm_camera_io_w(0xAAAAAAAA,
- vfe40_ctrl->share_ctrl->vfebase + VFE_0_BUS_BDG_QOS_CFG_2);
- msm_camera_io_w(0xAAAAAAAA,
- vfe40_ctrl->share_ctrl->vfebase + VFE_0_BUS_BDG_QOS_CFG_3);
- msm_camera_io_w(0xAAAAAAAA,
- vfe40_ctrl->share_ctrl->vfebase + VFE_0_BUS_BDG_QOS_CFG_4);
- msm_camera_io_w(0xAAAAAAAA,
- vfe40_ctrl->share_ctrl->vfebase + VFE_0_BUS_BDG_QOS_CFG_5);
- msm_camera_io_w(0xAAAAAAAA,
- vfe40_ctrl->share_ctrl->vfebase + VFE_0_BUS_BDG_QOS_CFG_6);
- msm_camera_io_w(0x0002AAAA,
- vfe40_ctrl->share_ctrl->vfebase + VFE_0_BUS_BDG_QOS_CFG_7);
+ return wait_for_completion_interruptible(
+ &axi_ctrl->share_ctrl->reset_complete);
}
static int vfe40_operation_config(uint32_t *cmd,
@@ -355,7 +943,6 @@
{
uint32_t *p = cmd;
- vfe40_ctrl->share_ctrl->operation_mode = *p;
vfe40_ctrl->share_ctrl->stats_comp = *(++p);
vfe40_ctrl->hfr_mode = *(++p);
@@ -364,19 +951,6 @@
msm_camera_io_w(*(++p),
vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
msm_camera_io_w(*(++p),
- vfe40_ctrl->share_ctrl->vfebase + VFE_RDI0_CFG);
- if (msm_camera_io_r(vfe40_ctrl->share_ctrl->vfebase +
- V40_GET_HW_VERSION_OFF) ==
- VFE40_HW_NUMBER) {
- msm_camera_io_w(*(++p),
- vfe40_ctrl->share_ctrl->vfebase + VFE_RDI1_CFG);
- msm_camera_io_w(*(++p),
- vfe40_ctrl->share_ctrl->vfebase + VFE_RDI2_CFG);
- } else {
- ++p;
- ++p;
- }
- msm_camera_io_w(*(++p),
vfe40_ctrl->share_ctrl->vfebase + VFE_REALIGN_BUF);
msm_camera_io_w(*(++p),
vfe40_ctrl->share_ctrl->vfebase + VFE_CHROMA_UP);
@@ -428,7 +1002,7 @@
stats_buf = &bufq->bufs[i];
rc = vfe40_ctrl->stats_ops.enqueue_buf(
vfe40_ctrl->stats_ops.stats_ctrl,
- &(stats_buf->info), NULL);
+ &(stats_buf->info), NULL, -1);
if (rc < 0) {
pr_err("%s: dq stats buf (type = %d) err = %d",
__func__, stats_type, rc);
@@ -438,6 +1012,26 @@
return 0L;
}
+
+static unsigned long vfe40_stats_unregbuf(
+ struct vfe40_ctrl_type *vfe40_ctrl,
+ struct msm_stats_reqbuf *req_buf, int domain_num)
+{
+ int i = 0, rc = 0;
+
+ for (i = 0; i < req_buf->num_buf; i++) {
+ rc = vfe40_ctrl->stats_ops.buf_unprepare(
+ vfe40_ctrl->stats_ops.stats_ctrl,
+ req_buf->stats_type, i,
+ vfe40_ctrl->stats_ops.client, domain_num);
+ if (rc < 0) {
+ pr_err("%s: unreg stats buf (type = %d) err = %d",
+ __func__, req_buf->stats_type, rc);
+ return rc;
+ }
+ }
+ return 0L;
+}
static int vfe_stats_awb_buf_init(
struct vfe40_ctrl_type *vfe40_ctrl,
struct vfe_cmd_stats_buf *in)
@@ -469,14 +1063,18 @@
return 0;
}
-static int vfe_stats_aec_buf_init(
- struct vfe40_ctrl_type *vfe40_ctrl, struct vfe_cmd_stats_buf *in)
+static uint32_t vfe_stats_aec_bg_buf_init(
+ struct vfe40_ctrl_type *vfe40_ctrl)
{
uint32_t addr;
unsigned long flags;
+ uint32_t stats_type;
+ stats_type =
+ (!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSM_STATS_TYPE_AEC
+ : MSM_STATS_TYPE_BG;
spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
- addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, MSM_STATS_TYPE_AEC);
+ addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, stats_type);
spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
if (!addr) {
pr_err("%s: dq aec ping buf from free buf queue",
@@ -485,9 +1083,9 @@
}
msm_camera_io_w(addr,
vfe40_ctrl->share_ctrl->vfebase +
- VFE_BUS_STATS_AEC_WR_PING_ADDR);
+ VFE_BUS_STATS_BG_WR_PING_ADDR);
spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
- addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, MSM_STATS_TYPE_AEC);
+ addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, stats_type);
spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
if (!addr) {
pr_err("%s: dq aec pong buf from free buf queue",
@@ -496,26 +1094,31 @@
}
msm_camera_io_w(addr,
vfe40_ctrl->share_ctrl->vfebase +
- VFE_BUS_STATS_AEC_WR_PONG_ADDR);
+ VFE_BUS_STATS_BG_WR_PONG_ADDR);
return 0;
}
-static int vfe_stats_af_buf_init(
- struct vfe40_ctrl_type *vfe40_ctrl, struct vfe_cmd_stats_buf *in)
+static int vfe_stats_af_bf_buf_init(
+ struct vfe40_ctrl_type *vfe40_ctrl)
{
uint32_t addr;
unsigned long flags;
int rc = 0;
+ uint32_t stats_type;
+ stats_type =
+ (!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSM_STATS_TYPE_AF
+ : MSM_STATS_TYPE_BF;
+
spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
- rc = vfe40_stats_flush_enqueue(vfe40_ctrl, MSM_STATS_TYPE_AF);
+ rc = vfe40_stats_flush_enqueue(vfe40_ctrl, stats_type);
if (rc < 0) {
pr_err("%s: dq stats buf err = %d",
__func__, rc);
spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
return -EINVAL;
}
- addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, MSM_STATS_TYPE_AF);
+ addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, stats_type);
spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
if (!addr) {
pr_err("%s: dq af ping buf from free buf queue", __func__);
@@ -523,9 +1126,9 @@
}
msm_camera_io_w(addr,
vfe40_ctrl->share_ctrl->vfebase +
- VFE_BUS_STATS_AF_WR_PING_ADDR);
+ VFE_BUS_STATS_BF_WR_PING_ADDR);
spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
- addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, MSM_STATS_TYPE_AF);
+ addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, stats_type);
spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
if (!addr) {
pr_err("%s: dq af pong buf from free buf queue", __func__);
@@ -533,13 +1136,44 @@
}
msm_camera_io_w(addr,
vfe40_ctrl->share_ctrl->vfebase +
- VFE_BUS_STATS_AF_WR_PONG_ADDR);
+ VFE_BUS_STATS_BF_WR_PONG_ADDR);
+ return 0;
+}
+
+static uint32_t vfe_stats_bhist_buf_init(
+ struct vfe40_ctrl_type *vfe40_ctrl)
+{
+ uint32_t addr;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
+ addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, MSM_STATS_TYPE_BHIST);
+ spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
+ if (!addr) {
+ pr_err("%s: dq ihist ping buf from free buf queue",
+ __func__);
+ return -ENOMEM;
+ }
+ msm_camera_io_w(addr,
+ vfe40_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_SKIN_WR_PING_ADDR);
+ spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
+ addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, MSM_STATS_TYPE_BHIST);
+ spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
+ if (!addr) {
+ pr_err("%s: dq ihist pong buf from free buf queue",
+ __func__);
+ return -ENOMEM;
+ }
+ msm_camera_io_w(addr,
+ vfe40_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_SKIN_WR_PONG_ADDR);
return 0;
}
static int vfe_stats_ihist_buf_init(
- struct vfe40_ctrl_type *vfe40_ctrl, struct vfe_cmd_stats_buf *in)
+ struct vfe40_ctrl_type *vfe40_ctrl)
{
uint32_t addr;
unsigned long flags;
@@ -571,7 +1205,7 @@
}
static int vfe_stats_rs_buf_init(
- struct vfe40_ctrl_type *vfe40_ctrl, struct vfe_cmd_stats_buf *in)
+ struct vfe40_ctrl_type *vfe40_ctrl)
{
uint32_t addr;
unsigned long flags;
@@ -600,7 +1234,7 @@
}
static int vfe_stats_cs_buf_init(
- struct vfe40_ctrl_type *vfe40_ctrl, struct vfe_cmd_stats_buf *in)
+ struct vfe40_ctrl_type *vfe40_ctrl)
{
uint32_t addr;
unsigned long flags;
@@ -627,39 +1261,45 @@
return 0;
}
+static void vfe40_cfg_qos_parms(struct vfe40_ctrl_type *vfe40_ctrl)
+{
+ void __iomem *vfebase = vfe40_ctrl->share_ctrl->vfebase;
+ msm_camera_io_w(0xAAAAAAAA, vfebase + VFE_0_BUS_BDG_QOS_CFG_0);
+ msm_camera_io_w(0xAAAAAAAA, vfebase + VFE_0_BUS_BDG_QOS_CFG_1);
+ msm_camera_io_w(0xAAAAAAAA, vfebase + VFE_0_BUS_BDG_QOS_CFG_2);
+ msm_camera_io_w(0xAAAAAAAA, vfebase + VFE_0_BUS_BDG_QOS_CFG_3);
+ msm_camera_io_w(0xAAAAAAAA, vfebase + VFE_0_BUS_BDG_QOS_CFG_4);
+ msm_camera_io_w(0xAAAAAAAA, vfebase + VFE_0_BUS_BDG_QOS_CFG_5);
+ msm_camera_io_w(0xAAAAAAAA, vfebase + VFE_0_BUS_BDG_QOS_CFG_6);
+ msm_camera_io_w(0x0002AAAA, vfebase + VFE_0_BUS_BDG_QOS_CFG_7);
+}
+
static void vfe40_start_common(struct vfe40_ctrl_type *vfe40_ctrl)
{
- uint32_t irq_mask = 0x1E000011;
- vfe40_ctrl->start_ack_pending = TRUE;
+ uint16_t vfe_operation_mode =
+ vfe40_ctrl->share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+ VFE_OUTPUTS_RDI1);
CDBG("VFE opertaion mode = 0x%x, output mode = 0x%x\n",
- vfe40_ctrl->share_ctrl->operation_mode,
+ vfe40_ctrl->share_ctrl->current_mode,
vfe40_ctrl->share_ctrl->outpath.output_mode);
- msm_camera_io_w(irq_mask,
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
- msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1,
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
+ vfe40_cfg_qos_parms(vfe40_ctrl);
- /* Ensure the write order while writing
- to the command register using the barrier */
- msm_camera_io_w_mb(1,
- vfe40_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
- msm_camera_io_w_mb(1,
- vfe40_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
+ msm_camera_io_w_mb(0x1,
+ vfe40_ctrl->share_ctrl->vfebase +
+ VFE_REG_UPDATE_CMD);
- msm_camera_io_dump(vfe40_ctrl->share_ctrl->vfebase,
- vfe40_ctrl->share_ctrl->register_total*4);
-
- atomic_set(&vfe40_ctrl->share_ctrl->vstate, 1);
+ if (vfe_operation_mode) {
+ msm_camera_io_w_mb(1, vfe40_ctrl->share_ctrl->vfebase +
+ VFE_CAMIF_COMMAND);
+ }
}
static int vfe40_start_recording(
struct msm_cam_media_controller *pmctl,
struct vfe40_ctrl_type *vfe40_ctrl)
{
- msm_camio_bus_scale_cfg(
- pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
- vfe40_ctrl->recording_state = VFE_STATE_START_REQUESTED;
+ vfe40_ctrl->share_ctrl->recording_state = VFE_STATE_START_REQUESTED;
msm_camera_io_w_mb(1,
vfe40_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
return 0;
@@ -669,11 +1309,9 @@
struct msm_cam_media_controller *pmctl,
struct vfe40_ctrl_type *vfe40_ctrl)
{
- vfe40_ctrl->recording_state = VFE_STATE_STOP_REQUESTED;
+ vfe40_ctrl->share_ctrl->recording_state = VFE_STATE_STOP_REQUESTED;
msm_camera_io_w_mb(1,
vfe40_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
- msm_camio_bus_scale_cfg(
- pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
return 0;
}
@@ -691,97 +1329,21 @@
share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
}
+static void vfe40_stop_liveshot(
+ struct msm_cam_media_controller *pmctl,
+ struct vfe40_ctrl_type *vfe40_ctrl)
+{
+ vfe40_ctrl->share_ctrl->liveshot_state = VFE_STATE_STOP_REQUESTED;
+ msm_camera_io_w_mb(1,
+ vfe40_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+}
+
static int vfe40_zsl(
struct msm_cam_media_controller *pmctl,
struct vfe40_ctrl_type *vfe40_ctrl)
{
- uint32_t irq_comp_mask = 0;
- /* capture command is valid for both idle and active state. */
- irq_comp_mask =
- msm_camera_io_r(vfe40_ctrl->
- share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-
- CDBG("%s:op mode %d O/P Mode %d\n", __func__,
- vfe40_ctrl->share_ctrl->operation_mode,
- vfe40_ctrl->share_ctrl->outpath.output_mode);
-
- if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_PRIMARY) {
- irq_comp_mask |= (
- (0x1 << (vfe40_ctrl->share_ctrl->outpath.out0.ch0)) |
- (0x1 << (vfe40_ctrl->share_ctrl->outpath.out0.ch1)));
- } else if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
- irq_comp_mask |= (
- (0x1 << (vfe40_ctrl->share_ctrl->outpath.out0.ch0)) |
- (0x1 << (vfe40_ctrl->share_ctrl->outpath.out0.ch1)) |
- (0x1 << (vfe40_ctrl->share_ctrl->outpath.out0.ch2)));
- }
-
- if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_SECONDARY) {
- irq_comp_mask |= ((0x1 << (vfe40_ctrl->
- share_ctrl->outpath.out1.ch0 + 8)) |
- (0x1 << (vfe40_ctrl->
- share_ctrl->outpath.out1.ch1 + 8)));
- } else if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
- irq_comp_mask |= (
- (0x1 << (vfe40_ctrl->
- share_ctrl->outpath.out1.ch0 + 8)) |
- (0x1 << (vfe40_ctrl->
- share_ctrl->outpath.out1.ch1 + 8)) |
- (0x1 << (vfe40_ctrl->
- share_ctrl->outpath.out1.ch2 + 8)));
- }
-
- if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out0.ch1]);
- } else if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out0.ch1]);
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out0.ch2]);
- }
-
- if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_SECONDARY) {
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out1.ch1]);
- } else if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out1.ch1]);
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out1.ch2]);
- }
-
- msm_camera_io_w(irq_comp_mask,
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ vfe40_ctrl->share_ctrl->start_ack_pending = TRUE;
vfe40_start_common(vfe40_ctrl);
- msm_camio_bus_scale_cfg(
- pmctl->sdata->pdata->cam_bus_scale_table, S_ZSL);
msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase + 0x18C);
msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase + 0x188);
@@ -792,28 +1354,8 @@
struct vfe40_ctrl_type *vfe40_ctrl,
uint32_t num_frames_capture)
{
- uint32_t irq_comp_mask = 0;
-
vfe40_ctrl->share_ctrl->outpath.out0.capture_cnt = num_frames_capture;
vfe40_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
-
- irq_comp_mask =
- msm_camera_io_r(
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-
- if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_PRIMARY) {
- irq_comp_mask |=
- (0x1 << (vfe40_ctrl->share_ctrl->outpath.out0.ch0));
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out0.ch0]);
- }
-
- msm_camera_io_w(irq_comp_mask,
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
- msm_camio_bus_scale_cfg(
- pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
vfe40_start_common(vfe40_ctrl);
return 0;
}
@@ -823,75 +1365,24 @@
uint32_t num_frames_capture,
struct vfe40_ctrl_type *vfe40_ctrl)
{
- uint32_t irq_comp_mask = 0;
-
/* capture command is valid for both idle and active state. */
vfe40_ctrl->share_ctrl->outpath.out1.capture_cnt = num_frames_capture;
- if (vfe40_ctrl->share_ctrl->operation_mode ==
+ if (vfe40_ctrl->share_ctrl->current_mode ==
VFE_OUTPUTS_MAIN_AND_THUMB ||
- vfe40_ctrl->share_ctrl->operation_mode ==
+ vfe40_ctrl->share_ctrl->current_mode ==
VFE_OUTPUTS_THUMB_AND_MAIN ||
- vfe40_ctrl->share_ctrl->operation_mode ==
+ vfe40_ctrl->share_ctrl->current_mode ==
VFE_OUTPUTS_JPEG_AND_THUMB ||
- vfe40_ctrl->share_ctrl->operation_mode ==
+ vfe40_ctrl->share_ctrl->current_mode ==
VFE_OUTPUTS_THUMB_AND_JPEG) {
vfe40_ctrl->share_ctrl->outpath.out0.capture_cnt =
num_frames_capture;
}
vfe40_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
- irq_comp_mask = msm_camera_io_r(
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-
- if (vfe40_ctrl->share_ctrl->operation_mode ==
- VFE_OUTPUTS_MAIN_AND_THUMB ||
- vfe40_ctrl->share_ctrl->operation_mode ==
- VFE_OUTPUTS_JPEG_AND_THUMB ||
- vfe40_ctrl->share_ctrl->operation_mode ==
- VFE_OUTPUTS_THUMB_AND_MAIN) {
- if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_PRIMARY) {
- irq_comp_mask |= (0x1 << vfe40_ctrl->
- share_ctrl->outpath.out0.ch0 |
- 0x1 << vfe40_ctrl->
- share_ctrl->outpath.out0.ch1);
- }
- if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_SECONDARY) {
- irq_comp_mask |=
- (0x1 << (vfe40_ctrl->
- share_ctrl->outpath.out1.ch0 + 8) |
- 0x1 << (vfe40_ctrl->
- share_ctrl->outpath.out1.ch1 + 8));
- }
- if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out0.ch1]);
- }
- if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_SECONDARY) {
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out1.ch1]);
- }
- }
vfe40_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
- msm_camera_io_w(irq_comp_mask,
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
- msm_camera_io_r(vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
- msm_camio_bus_scale_cfg(
- pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
-
vfe40_start_common(vfe40_ctrl);
/* for debug */
msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase + 0x18C);
@@ -903,41 +1394,6 @@
struct msm_cam_media_controller *pmctl,
struct vfe40_ctrl_type *vfe40_ctrl)
{
- uint32_t irq_comp_mask = 0;
- irq_comp_mask =
- msm_camera_io_r(vfe40_ctrl->share_ctrl->vfebase +
- VFE_IRQ_COMP_MASK);
-
- if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_PRIMARY) {
- irq_comp_mask |= (
- 0x1 << vfe40_ctrl->share_ctrl->outpath.out0.ch0 |
- 0x1 << vfe40_ctrl->share_ctrl->outpath.out0.ch1);
- } else if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
- irq_comp_mask |= (
- 0x1 << vfe40_ctrl->share_ctrl->outpath.out0.ch0 |
- 0x1 << vfe40_ctrl->share_ctrl->outpath.out0.ch1 |
- 0x1 << vfe40_ctrl->share_ctrl->outpath.out0.ch2);
- }
- if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_SECONDARY) {
- irq_comp_mask |= (
- 0x1 << (vfe40_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
- 0x1 << (vfe40_ctrl->share_ctrl->outpath.out1.ch1 + 8));
- } else if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
- irq_comp_mask |= (
- 0x1 << (vfe40_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
- 0x1 << (vfe40_ctrl->share_ctrl->outpath.out1.ch1 + 8) |
- 0x1 << (vfe40_ctrl->share_ctrl->outpath.out1.ch2 + 8));
- }
- msm_camera_io_w(irq_comp_mask,
- vfe40_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-
- /*
- msm_camio_bus_scale_cfg(
- pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);*/
vfe40_start_common(vfe40_ctrl);
return 0;
}
@@ -980,9 +1436,9 @@
vfe40_ctrl->update_gamma = false;
}
- spin_lock_irqsave(&vfe40_ctrl->update_ack_lock, flags);
- vfe40_ctrl->update_ack_pending = TRUE;
- spin_unlock_irqrestore(&vfe40_ctrl->update_ack_lock, flags);
+ spin_lock_irqsave(&vfe40_ctrl->share_ctrl->update_ack_lock, flags);
+ vfe40_ctrl->share_ctrl->update_ack_pending = TRUE;
+ spin_unlock_irqrestore(&vfe40_ctrl->share_ctrl->update_ack_lock, flags);
/* Ensure the write order while writing
to the command register using the barrier */
msm_camera_io_w_mb(1,
@@ -1044,7 +1500,7 @@
8 + ((vfe40_ctrl->sync_timer_number) * 12));
/* Sync Timer Pixel Duration */
value = *tbl++;
- val = vfe40_ctrl->share_ctrl->vfe_clk_rate / 10000;
+ val = vfe_clk_rate / 10000;
val = 10000000 / val;
val = value * 10000 / val;
CDBG("%s: Pixel Clk Cycles!!! %d\n", __func__, val);
@@ -1061,19 +1517,7 @@
vfe40_ctrl->share_ctrl->vfebase + V40_TIMER_SELECT_OFF);
}
-static void vfe40_program_dmi_cfg(
- enum VFE40_DMI_RAM_SEL bankSel,
- struct vfe40_ctrl_type *vfe40_ctrl)
-{
- /* set bit 8 for auto increment. */
- uint32_t value = VFE_DMI_CFG_DEFAULT;
- value += (uint32_t)bankSel;
- CDBG("%s: banksel = %d\n", __func__, bankSel);
- msm_camera_io_w(value, vfe40_ctrl->share_ctrl->vfebase + VFE_DMI_CFG);
- /* by default, always starts with offset 0.*/
- msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase + VFE_DMI_ADDR);
-}
static void vfe40_write_gamma_cfg(
enum VFE40_DMI_RAM_SEL channel_sel,
const uint32_t *tbl,
@@ -1132,7 +1576,7 @@
vfe40_program_dmi_cfg(NO_MEM_SELECTED, vfe40_ctrl);
}
-struct vfe40_output_ch *vfe40_get_ch(
+static struct vfe40_output_ch *vfe40_get_ch(
int path, struct vfe_share_ctrl_t *share_ctrl)
{
struct vfe40_output_ch *ch = NULL;
@@ -1141,6 +1585,10 @@
ch = &share_ctrl->outpath.out0;
else if (path == VFE_MSG_OUTPUT_SECONDARY)
ch = &share_ctrl->outpath.out1;
+ else if (path == VFE_MSG_OUTPUT_TERTIARY1)
+ ch = &share_ctrl->outpath.out2;
+ else if (path == VFE_MSG_OUTPUT_TERTIARY2)
+ ch = &share_ctrl->outpath.out3;
else
pr_err("%s: Invalid path %d\n", __func__,
path);
@@ -1148,49 +1596,76 @@
BUG_ON(ch == NULL);
return ch;
}
+static struct msm_free_buf *vfe40_check_free_buffer(
+ int id, int path, struct axi_ctrl_t *axi_ctrl)
+{
+ struct vfe40_output_ch *outch = NULL;
+ struct msm_free_buf *b = NULL;
+ uint32_t inst_handle = 0;
-static int vfe40_configure_pingpong_buffers(
- int id, int path, struct vfe40_ctrl_type *vfe40_ctrl)
+ if (path == VFE_MSG_OUTPUT_PRIMARY)
+ inst_handle = axi_ctrl->share_ctrl->outpath.out0.inst_handle;
+ else if (path == VFE_MSG_OUTPUT_SECONDARY)
+ inst_handle = axi_ctrl->share_ctrl->outpath.out1.inst_handle;
+ else if (path == VFE_MSG_OUTPUT_TERTIARY1)
+ inst_handle = axi_ctrl->share_ctrl->outpath.out2.inst_handle;
+ else if (path == VFE_MSG_OUTPUT_TERTIARY2)
+ inst_handle = axi_ctrl->share_ctrl->outpath.out3.inst_handle;
+
+ vfe40_subdev_notify(id, path, inst_handle,
+ &axi_ctrl->subdev, axi_ctrl->share_ctrl);
+ outch = vfe40_get_ch(path, axi_ctrl->share_ctrl);
+ if (outch->free_buf.ch_paddr[0])
+ b = &outch->free_buf;
+ return b;
+}
+static int configure_pingpong_buffers(
+ int id, int path, struct axi_ctrl_t *axi_ctrl)
{
struct vfe40_output_ch *outch = NULL;
int rc = 0;
- uint32_t image_mode = 0;
+ uint32_t inst_handle = 0;
if (path == VFE_MSG_OUTPUT_PRIMARY)
- image_mode = vfe40_ctrl->share_ctrl->outpath.out0.image_mode;
- else
- image_mode = vfe40_ctrl->share_ctrl->outpath.out1.image_mode;
+ inst_handle = axi_ctrl->share_ctrl->outpath.out0.inst_handle;
+ else if (path == VFE_MSG_OUTPUT_SECONDARY)
+ inst_handle = axi_ctrl->share_ctrl->outpath.out1.inst_handle;
+ else if (path == VFE_MSG_OUTPUT_TERTIARY1)
+ inst_handle = axi_ctrl->share_ctrl->outpath.out2.inst_handle;
+ else if (path == VFE_MSG_OUTPUT_TERTIARY2)
+ inst_handle = axi_ctrl->share_ctrl->outpath.out3.inst_handle;
- vfe40_subdev_notify(id, path, image_mode,
- &vfe40_ctrl->subdev, vfe40_ctrl->share_ctrl);
- outch = vfe40_get_ch(path, vfe40_ctrl->share_ctrl);
+ vfe40_subdev_notify(id, path, inst_handle,
+ &axi_ctrl->subdev, axi_ctrl->share_ctrl);
+ outch = vfe40_get_ch(path, axi_ctrl->share_ctrl);
if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
/* Configure Preview Ping Pong */
- CDBG("%s Configure ping/pong address for %d",
+ pr_info("%s Configure ping/pong address for %d",
__func__, path);
vfe40_put_ch_ping_addr(
- vfe40_ctrl->share_ctrl->vfebase, outch->ch0,
+ axi_ctrl->share_ctrl->vfebase, outch->ch0,
outch->ping.ch_paddr[0]);
vfe40_put_ch_pong_addr(
- vfe40_ctrl->share_ctrl->vfebase, outch->ch0,
+ axi_ctrl->share_ctrl->vfebase, outch->ch0,
outch->pong.ch_paddr[0]);
- if (vfe40_ctrl->share_ctrl->operation_mode !=
- VFE_OUTPUTS_RAW) {
+ if ((axi_ctrl->share_ctrl->current_mode !=
+ VFE_OUTPUTS_RAW) && (path != VFE_MSG_OUTPUT_TERTIARY1)
+ && (path != VFE_MSG_OUTPUT_TERTIARY2)) {
vfe40_put_ch_ping_addr(
- vfe40_ctrl->share_ctrl->vfebase, outch->ch1,
+ axi_ctrl->share_ctrl->vfebase, outch->ch1,
outch->ping.ch_paddr[1]);
vfe40_put_ch_pong_addr(
- vfe40_ctrl->share_ctrl->vfebase, outch->ch1,
+ axi_ctrl->share_ctrl->vfebase, outch->ch1,
outch->pong.ch_paddr[1]);
}
if (outch->ping.num_planes > 2)
vfe40_put_ch_ping_addr(
- vfe40_ctrl->share_ctrl->vfebase, outch->ch2,
+ axi_ctrl->share_ctrl->vfebase, outch->ch2,
outch->ping.ch_paddr[2]);
if (outch->pong.num_planes > 2)
vfe40_put_ch_pong_addr(
- vfe40_ctrl->share_ctrl->vfebase, outch->ch2,
+ axi_ctrl->share_ctrl->vfebase, outch->ch2,
outch->pong.ch_paddr[2]);
/* avoid stale info */
@@ -1220,7 +1695,7 @@
vfe40_program_dmi_cfg(NO_MEM_SELECTED, vfe40_ctrl);
}
-void vfe40_send_isp_msg(
+static void vfe40_send_isp_msg(
struct v4l2_subdev *sd,
uint32_t vfeFrameId,
uint32_t isp_msg_id)
@@ -1240,142 +1715,76 @@
struct vfe40_ctrl_type *vfe40_ctrl)
{
int i , rc = 0;
- uint32_t old_val = 0 , new_val = 0;
+ uint32_t old_val = 0 , new_val = 0, module_val = 0;
uint32_t *cmdp = NULL;
uint32_t *cmdp_local = NULL;
uint32_t snapshot_cnt = 0;
uint32_t temp1 = 0, temp2 = 0;
+ struct msm_camera_vfe_params_t vfe_params;
CDBG("vfe40_proc_general: cmdID = %s, length = %d\n",
vfe40_general_cmd[cmd->id], cmd->length);
switch (cmd->id) {
case VFE_CMD_RESET:
- CDBG("vfe40_proc_general: cmdID = %s\n",
+ pr_info("vfe40_proc_general: cmdID = %s\n",
vfe40_general_cmd[cmd->id]);
+ vfe40_ctrl->share_ctrl->vfe_reset_flag = true;
vfe40_reset(vfe40_ctrl);
break;
case VFE_CMD_START:
- CDBG("vfe40_proc_general: cmdID = %s\n",
+ pr_info("vfe40_proc_general: cmdID = %s\n",
vfe40_general_cmd[cmd->id]);
- if ((vfe40_ctrl->share_ctrl->operation_mode ==
- VFE_OUTPUTS_PREVIEW_AND_VIDEO) ||
- (vfe40_ctrl->share_ctrl->operation_mode ==
- VFE_OUTPUTS_PREVIEW))
- /* Configure primary channel */
- rc = vfe40_configure_pingpong_buffers(
- VFE_MSG_START, VFE_MSG_OUTPUT_PRIMARY,
- vfe40_ctrl);
- else
- /* Configure secondary channel */
- rc = vfe40_configure_pingpong_buffers(
- VFE_MSG_START, VFE_MSG_OUTPUT_SECONDARY,
- vfe40_ctrl);
- if (rc < 0) {
- pr_err(
- "%s error configuring pingpong buffers for preview",
- __func__);
- rc = -EINVAL;
- goto proc_general_done;
+ if (copy_from_user(&vfe_params,
+ (void __user *)(cmd->value),
+ sizeof(struct msm_camera_vfe_params_t))) {
+ rc = -EFAULT;
+ goto proc_general_done;
}
+ vfe40_ctrl->share_ctrl->current_mode =
+ vfe_params.operation_mode;
+
rc = vfe40_start(pmctl, vfe40_ctrl);
break;
case VFE_CMD_UPDATE:
vfe40_update(vfe40_ctrl);
break;
case VFE_CMD_CAPTURE_RAW:
- CDBG("%s: cmdID = VFE_CMD_CAPTURE_RAW\n", __func__);
- if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
- sizeof(uint32_t))) {
- rc = -EFAULT;
- goto proc_general_done;
+ pr_info("%s: cmdID = VFE_CMD_CAPTURE_RAW\n", __func__);
+ if (copy_from_user(&vfe_params,
+ (void __user *)(cmd->value),
+ sizeof(struct msm_camera_vfe_params_t))) {
+ rc = -EFAULT;
+ goto proc_general_done;
}
- rc = vfe40_configure_pingpong_buffers(
- VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_PRIMARY,
- vfe40_ctrl);
- if (rc < 0) {
- pr_err(
- "%s error configuring pingpong buffers for snapshot",
- __func__);
- rc = -EINVAL;
- goto proc_general_done;
- }
+
+ snapshot_cnt = vfe_params.capture_count;
+ vfe40_ctrl->share_ctrl->current_mode =
+ vfe_params.operation_mode;
rc = vfe40_capture_raw(pmctl, vfe40_ctrl, snapshot_cnt);
break;
case VFE_CMD_CAPTURE:
- if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
- sizeof(uint32_t))) {
- rc = -EFAULT;
- goto proc_general_done;
+ pr_info("%s: cmdID = VFE_CMD_CAPTURE\n", __func__);
+ if (copy_from_user(&vfe_params,
+ (void __user *)(cmd->value),
+ sizeof(struct msm_camera_vfe_params_t))) {
+ rc = -EFAULT;
+ goto proc_general_done;
}
- if (vfe40_ctrl->share_ctrl->operation_mode ==
- VFE_OUTPUTS_JPEG_AND_THUMB ||
- vfe40_ctrl->share_ctrl->operation_mode ==
- VFE_OUTPUTS_THUMB_AND_JPEG) {
- if (snapshot_cnt != 1) {
- pr_err("only support 1 inline snapshot\n");
- rc = -EINVAL;
- goto proc_general_done;
- }
- /* Configure primary channel for JPEG */
- rc = vfe40_configure_pingpong_buffers(
- VFE_MSG_JPEG_CAPTURE,
- VFE_MSG_OUTPUT_PRIMARY,
- vfe40_ctrl);
- } else {
- /* Configure primary channel */
- rc = vfe40_configure_pingpong_buffers(
- VFE_MSG_CAPTURE,
- VFE_MSG_OUTPUT_PRIMARY,
- vfe40_ctrl);
- }
- if (rc < 0) {
- pr_err(
- "%s error configuring pingpong buffers for primary output",
- __func__);
- rc = -EINVAL;
- goto proc_general_done;
- }
- /* Configure secondary channel */
- rc = vfe40_configure_pingpong_buffers(
- VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_SECONDARY,
- vfe40_ctrl);
- if (rc < 0) {
- pr_err(
- "%s error configuring pingpong buffers for secondary output",
- __func__);
- rc = -EINVAL;
- goto proc_general_done;
- }
+ snapshot_cnt = vfe_params.capture_count;
+ vfe40_ctrl->share_ctrl->current_mode =
+ vfe_params.operation_mode;
+
rc = vfe40_capture(pmctl, snapshot_cnt, vfe40_ctrl);
break;
case VFE_CMD_START_RECORDING:
- CDBG("vfe40_proc_general: cmdID = %s\n",
+ pr_info("vfe40_proc_general: cmdID = %s\n",
vfe40_general_cmd[cmd->id]);
- if (vfe40_ctrl->share_ctrl->operation_mode ==
- VFE_OUTPUTS_PREVIEW_AND_VIDEO)
- rc = vfe40_configure_pingpong_buffers(
- VFE_MSG_START_RECORDING,
- VFE_MSG_OUTPUT_SECONDARY,
- vfe40_ctrl);
- else if (vfe40_ctrl->share_ctrl->operation_mode ==
- VFE_OUTPUTS_VIDEO_AND_PREVIEW)
- rc = vfe40_configure_pingpong_buffers(
- VFE_MSG_START_RECORDING,
- VFE_MSG_OUTPUT_PRIMARY,
- vfe40_ctrl);
- if (rc < 0) {
- pr_err(
- "%s error configuring pingpong buffers for video\n",
- __func__);
- rc = -EINVAL;
- goto proc_general_done;
- }
rc = vfe40_start_recording(pmctl, vfe40_ctrl);
break;
case VFE_CMD_STOP_RECORDING:
- CDBG("vfe40_proc_general: cmdID = %s\n",
+ pr_info("vfe40_proc_general: cmdID = %s\n",
vfe40_general_cmd[cmd->id]);
rc = vfe40_stop_recording(pmctl, vfe40_ctrl);
break;
@@ -1396,7 +1805,12 @@
break;
case VFE_CMD_STATS_AE_START: {
- rc = vfe_stats_aec_buf_init(vfe40_ctrl, NULL);
+ if (vfe40_use_bayer_stats(vfe40_ctrl)) {
+ /* Error */
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ rc = vfe_stats_aec_bg_buf_init(vfe40_ctrl);
if (rc < 0) {
pr_err("%s: cannot config ping/pong address of AEC",
__func__);
@@ -1425,7 +1839,12 @@
}
break;
case VFE_CMD_STATS_AF_START: {
- rc = vfe_stats_af_buf_init(vfe40_ctrl, NULL);
+ if (vfe40_use_bayer_stats(vfe40_ctrl)) {
+ /* Error */
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ rc = vfe_stats_af_bf_buf_init(vfe40_ctrl);
if (rc < 0) {
pr_err("%s: cannot config ping/pong address of AF",
__func__);
@@ -1453,8 +1872,12 @@
cmdp, (vfe40_cmd[cmd->id].length));
}
break;
-
case VFE_CMD_STATS_AWB_START: {
+ if (vfe40_use_bayer_stats(vfe40_ctrl)) {
+ /* Error */
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
rc = vfe_stats_awb_buf_init(vfe40_ctrl, NULL);
if (rc < 0) {
pr_err("%s: cannot config ping/pong address of AWB",
@@ -1485,7 +1908,7 @@
break;
case VFE_CMD_STATS_IHIST_START: {
- rc = vfe_stats_ihist_buf_init(vfe40_ctrl, NULL);
+ rc = vfe_stats_ihist_buf_init(vfe40_ctrl);
if (rc < 0) {
pr_err("%s: cannot config ping/pong address of IHIST",
__func__);
@@ -1516,7 +1939,7 @@
case VFE_CMD_STATS_RS_START: {
- rc = vfe_stats_rs_buf_init(vfe40_ctrl, NULL);
+ rc = vfe_stats_rs_buf_init(vfe40_ctrl);
if (rc < 0) {
pr_err("%s: cannot config ping/pong address of RS",
__func__);
@@ -1541,7 +1964,7 @@
break;
case VFE_CMD_STATS_CS_START: {
- rc = vfe_stats_cs_buf_init(vfe40_ctrl, NULL);
+ rc = vfe_stats_cs_buf_init(vfe40_ctrl);
if (rc < 0) {
pr_err("%s: cannot config ping/pong address of CS",
__func__);
@@ -1565,6 +1988,65 @@
}
break;
+ case VFE_CMD_STATS_BG_START:
+ case VFE_CMD_STATS_BF_START:
+ case VFE_CMD_STATS_BHIST_START: {
+ if (!vfe40_use_bayer_stats(vfe40_ctrl)) {
+ /* Error */
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ old_val = msm_camera_io_r(
+ vfe40_ctrl->share_ctrl->vfebase + VFE_STATS_CFG);
+ module_val = msm_camera_io_r(
+ vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
+ if (VFE_CMD_STATS_BG_START == cmd->id) {
+ module_val |= BG_ENABLE_MASK;
+ rc = vfe_stats_aec_bg_buf_init(vfe40_ctrl);
+ if (rc < 0) {
+ pr_err("%s: cannot config ping/pong address of CS",
+ __func__);
+ goto proc_general_done;
+ }
+ } else if (VFE_CMD_STATS_BF_START == cmd->id) {
+ module_val |= BF_ENABLE_MASK;
+ rc = vfe_stats_af_bf_buf_init(vfe40_ctrl);
+ if (rc < 0) {
+ pr_err("%s: cannot config ping/pong address of CS",
+ __func__);
+ goto proc_general_done;
+ }
+ } else {
+ module_val |= BHIST_ENABLE_MASK;
+ old_val |= STATS_BHIST_ENABLE_MASK;
+ rc = vfe_stats_bhist_buf_init(vfe40_ctrl);
+ if (rc < 0) {
+ pr_err("%s: cannot config ping/pong address of CS",
+ __func__);
+ goto proc_general_done;
+ }
+ }
+ msm_camera_io_w(old_val, vfe40_ctrl->share_ctrl->vfebase +
+ VFE_STATS_CFG);
+ msm_camera_io_w(module_val,
+ vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value),
+ cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ msm_camera_io_memcpy(
+ vfe40_ctrl->share_ctrl->vfebase +
+ vfe40_cmd[cmd->id].offset,
+ cmdp, (vfe40_cmd[cmd->id].length));
+ }
+ break;
case VFE_CMD_MCE_UPDATE:
case VFE_CMD_MCE_CFG:{
cmdp = kmalloc(cmd->length, GFP_ATOMIC);
@@ -1651,6 +2133,38 @@
rc = -EFAULT;
goto proc_general_done;
+ case VFE_CMD_MESH_ROLL_OFF_CFG: {
+ cmdp = kmalloc(cmd->length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+ if (copy_from_user(cmdp,
+ (void __user *)(cmd->value) , cmd->length)) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ cmdp_local = cmdp;
+ msm_camera_io_memcpy(
+ vfe40_ctrl->share_ctrl->vfebase +
+ vfe40_cmd[cmd->id].offset,
+ cmdp_local, V40_MESH_ROLL_OFF_CFG_LEN);
+ cmdp_local += 9;
+ vfe40_program_dmi_cfg(ROLLOFF_RAM0_BANK0, vfe40_ctrl);
+ /* for loop for extrcting table. */
+ for (i = 0; i < (V40_MESH_ROLL_OFF_TABLE_SIZE * 2); i++) {
+ msm_camera_io_w(*cmdp_local,
+ vfe40_ctrl->share_ctrl->vfebase +
+ VFE_DMI_DATA_LO);
+ cmdp_local++;
+ }
+ CDBG("done writing mesh table\n");
+ vfe40_program_dmi_cfg(NO_MEM_SELECTED, vfe40_ctrl);
+ }
+ break;
+ case VFE_CMD_GET_MESH_ROLLOFF_TABLE:
+ break;
+
case VFE_CMD_LA_CFG:
cmdp = kmalloc(cmd->length, GFP_ATOMIC);
if (!cmdp) {
@@ -1759,15 +2273,6 @@
case VFE_CMD_LIVESHOT:
/* Configure primary channel */
- rc = vfe40_configure_pingpong_buffers(VFE_MSG_CAPTURE,
- VFE_MSG_OUTPUT_PRIMARY, vfe40_ctrl);
- if (rc < 0) {
- pr_err(
- "%s error configuring pingpong buffers for primary output\n",
- __func__);
- rc = -EINVAL;
- goto proc_general_done;
- }
vfe40_start_liveshot(pmctl, vfe40_ctrl);
break;
@@ -1787,7 +2292,6 @@
vfe40_ctrl->share_ctrl->vfebase +
V40_LINEARIZATION_OFF1,
cmdp_local, V40_LINEARIZATION_LEN1);
-
cmdp_local = cmdp + 17;
vfe40_write_linear_cfg(BLACK_LUT_RAM_BANK0,
cmdp_local, vfe40_ctrl);
@@ -2139,6 +2643,11 @@
break;
case VFE_CMD_STATS_AWB_STOP: {
+ if (vfe40_use_bayer_stats(vfe40_ctrl)) {
+ /* Error */
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
old_val = msm_camera_io_r(
vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
old_val &= ~AWB_ENABLE_MASK;
@@ -2146,27 +2655,30 @@
vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
}
break;
-
case VFE_CMD_STATS_AE_STOP: {
+ if (vfe40_use_bayer_stats(vfe40_ctrl)) {
+ /* Error */
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
old_val = msm_camera_io_r(
vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
- old_val &= ~BG_ENABLE_MASK;
+ old_val &= BG_ENABLE_MASK;
msm_camera_io_w(old_val,
vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
}
break;
case VFE_CMD_STATS_AF_STOP: {
+ if (vfe40_use_bayer_stats(vfe40_ctrl)) {
+ /* Error */
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
old_val = msm_camera_io_r(
vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
old_val &= ~BF_ENABLE_MASK;
msm_camera_io_w(old_val,
vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
- rc = vfe40_stats_flush_enqueue(vfe40_ctrl, MSM_STATS_TYPE_AF);
- if (rc < 0) {
- pr_err("%s: dq stats buf err = %d",
- __func__, rc);
- return -EINVAL;
- }
}
break;
@@ -2196,9 +2708,47 @@
vfe40_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
}
break;
+
+ case VFE_CMD_STATS_BG_STOP:
+ case VFE_CMD_STATS_BF_STOP:
+ case VFE_CMD_STATS_BHIST_STOP: {
+ if (!vfe40_use_bayer_stats(vfe40_ctrl)) {
+ /* Error */
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+ old_val = msm_camera_io_r(
+ vfe40_ctrl->share_ctrl->vfebase + VFE_STATS_CFG);
+
+ if (VFE_CMD_STATS_BHIST_STOP == cmd->id)
+ old_val &= ~STATS_BHIST_ENABLE_MASK;
+
+ msm_camera_io_w(old_val,
+ vfe40_ctrl->share_ctrl->vfebase + VFE_STATS_CFG);
+ if (VFE_CMD_STATS_BF_STOP == cmd->id) {
+ rc = vfe40_stats_flush_enqueue(vfe40_ctrl,
+ MSM_STATS_TYPE_BF);
+ if (rc < 0) {
+ pr_err("%s: dq stats buf err = %d",
+ __func__, rc);
+ return -EINVAL;
+ }
+ }
+ }
+ break;
+
case VFE_CMD_STOP:
- CDBG("vfe40_proc_general: cmdID = %s\n",
+ pr_info("vfe40_proc_general: cmdID = %s\n",
vfe40_general_cmd[cmd->id]);
+ if (copy_from_user(&vfe_params,
+ (void __user *)(cmd->value),
+ sizeof(struct msm_camera_vfe_params_t))) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+
+ vfe40_ctrl->share_ctrl->current_mode =
+ vfe_params.operation_mode;
vfe40_stop(vfe40_ctrl);
break;
@@ -2242,14 +2792,15 @@
break;
case VFE_CMD_ZSL:
- rc = vfe40_configure_pingpong_buffers(VFE_MSG_START,
- VFE_MSG_OUTPUT_PRIMARY, vfe40_ctrl);
- if (rc < 0)
- goto proc_general_done;
- rc = vfe40_configure_pingpong_buffers(VFE_MSG_START,
- VFE_MSG_OUTPUT_SECONDARY, vfe40_ctrl);
- if (rc < 0)
- goto proc_general_done;
+ if (copy_from_user(&vfe_params,
+ (void __user *)(cmd->value),
+ sizeof(struct msm_camera_vfe_params_t))) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+
+ vfe40_ctrl->share_ctrl->current_mode =
+ vfe_params.operation_mode;
rc = vfe40_zsl(pmctl, vfe40_ctrl);
break;
@@ -2344,6 +2895,10 @@
*cmdp & VFE_FRAME_SKIP_PERIOD_MASK) + 1;
vfe40_ctrl->frame_skip_pattern = (uint32_t)(*(cmdp + 2));
break;
+ case VFE_CMD_STOP_LIVESHOT:
+ CDBG("%s Stopping liveshot ", __func__);
+ vfe40_stop_liveshot(pmctl, vfe40_ctrl);
+ break;
default:
if (cmd->length != vfe40_cmd[cmd->id].length)
return -EINVAL;
@@ -2402,221 +2957,505 @@
}
+void axi_stop_pix(struct vfe_share_ctrl_t *share_ctrl)
+{
+ uint32_t operation_mode =
+ share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+ VFE_OUTPUTS_RDI1);
+ uint32_t irq_comp_mask, irq_mask;
+ uint32_t reg_update = 0x1;
+
+ irq_comp_mask =
+ msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_COMP_MASK);
+ irq_mask = msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+
+ switch (share_ctrl->cmd_type) {
+ case AXI_CMD_PREVIEW: {
+ switch (operation_mode) {
+ case VFE_OUTPUTS_PREVIEW:
+ case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
+ if (share_ctrl->comp_output_mode &
+ VFE40_OUTPUT_MODE_PRIMARY) {
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch1]);
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out0.ch0 |
+ 0x1 << share_ctrl->outpath.out0.ch1);
+ share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_PRIMARY;
+ } else if (share_ctrl->comp_output_mode &
+ VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch1]);
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch2]);
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out0.ch0 |
+ 0x1 << share_ctrl->outpath.out0.ch1 |
+ 0x1 << share_ctrl->outpath.out0.ch2);
+ share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
+ }
+ irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+ break;
+ default:
+ if (share_ctrl->comp_output_mode &
+ VFE40_OUTPUT_MODE_SECONDARY) {
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[share_ctrl->
+ outpath.out1.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[share_ctrl->
+ outpath.out1.ch1]);
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out1.ch0 |
+ 0x1 << share_ctrl->outpath.out1.ch1);
+ share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_SECONDARY;
+ } else if (share_ctrl->comp_output_mode &
+ VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[share_ctrl->
+ outpath.out1.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[share_ctrl->
+ outpath.out1.ch1]);
+ msm_camera_io_w(0, share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[share_ctrl->
+ outpath.out1.ch2]);
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out1.ch0 |
+ 0x1 << share_ctrl->outpath.out1.ch1 |
+ 0x1 << share_ctrl->outpath.out1.ch2);
+ share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
+ }
+ irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+ break;
+ }
+ }
+ break;
+ default:
+ if (share_ctrl->comp_output_mode &
+ VFE40_OUTPUT_MODE_PRIMARY) {
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch1]);
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out0.ch0 |
+ 0x1 << share_ctrl->outpath.out0.ch1);
+ irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+ share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_PRIMARY;
+ } else if (share_ctrl->comp_output_mode &
+ VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch1]);
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[share_ctrl->
+ outpath.out0.ch2]);
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out0.ch0 |
+ 0x1 << share_ctrl->outpath.out0.ch1 |
+ 0x1 << share_ctrl->outpath.out0.ch2);
+ irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+ share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
+ }
+
+ if (share_ctrl->comp_output_mode &
+ VFE40_OUTPUT_MODE_SECONDARY) {
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[share_ctrl->
+ outpath.out1.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[share_ctrl->outpath.out1.ch1]);
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out1.ch0 |
+ 0x1 << share_ctrl->outpath.out1.ch1);
+ irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+ share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_SECONDARY;
+ } else if (share_ctrl->comp_output_mode &
+ VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[share_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[share_ctrl->outpath.out1.ch1]);
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[share_ctrl->outpath.out1.ch2]);
+ irq_comp_mask &= ~(
+ 0x1 << share_ctrl->outpath.out1.ch0 |
+ 0x1 << share_ctrl->outpath.out1.ch1 |
+ 0x1 << share_ctrl->outpath.out1.ch2);
+ irq_mask &= ~VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+ share_ctrl->outpath.output_mode |=
+ VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
+ }
+ break;
+ }
+
+ msm_camera_io_w_mb(reg_update,
+ share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ msm_camera_io_w(irq_comp_mask,
+ share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+}
+
+void axi_stop_rdi0(struct vfe_share_ctrl_t *share_ctrl)
+{
+ uint32_t reg_update = 0x2;
+ uint32_t irq_mask;
+ irq_mask = msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[share_ctrl->outpath.out2.ch0]);
+ irq_mask &= ~(0x1 << (share_ctrl->outpath.out2.ch0 +
+ VFE_WM_OFFSET));
+ }
+ msm_camera_io_w_mb(reg_update,
+ share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+}
+
+void axi_stop_rdi1(struct vfe_share_ctrl_t *share_ctrl)
+{
+ uint32_t reg_update = 0x4;
+ uint32_t irq_mask;
+ irq_mask = msm_camera_io_r(share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+ msm_camera_io_w(1, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[share_ctrl->outpath.out3.ch0]);
+ irq_mask &= ~(0x1 << (share_ctrl->outpath.out3.ch0 +
+ VFE_WM_OFFSET));
+ }
+
+ msm_camera_io_w_mb(reg_update,
+ share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ msm_camera_io_w(irq_mask, share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+}
+
+void axi_stop_process(struct vfe_share_ctrl_t *share_ctrl)
+{
+ uint32_t operation_mode =
+ share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+ VFE_OUTPUTS_RDI1);
+
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+ axi_stop_rdi0(share_ctrl);
+ share_ctrl->comp_output_mode &= ~VFE40_OUTPUT_MODE_TERTIARY1;
+ }
+ if (share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+ axi_stop_rdi1(share_ctrl);
+ share_ctrl->comp_output_mode &= ~VFE40_OUTPUT_MODE_TERTIARY2;
+ }
+ if (operation_mode) {
+ axi_stop_pix(share_ctrl);
+ share_ctrl->comp_output_mode &=
+ ~(share_ctrl->outpath.output_mode);
+ }
+}
+
static void vfe40_process_reg_update_irq(
struct vfe40_ctrl_type *vfe40_ctrl)
{
unsigned long flags;
+ struct vfe_share_ctrl_t *share_ctrl = vfe40_ctrl->share_ctrl;
- if (vfe40_ctrl->recording_state == VFE_STATE_START_REQUESTED) {
- if (vfe40_ctrl->share_ctrl->operation_mode ==
+ if (atomic_cmpxchg(
+ &share_ctrl->pix0_update_ack_pending, 2, 0) == 2) {
+ axi_stop_pix(share_ctrl);
+ msm_camera_io_w_mb(
+ CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+ share_ctrl->vfebase + VFE_CAMIF_COMMAND);
+ axi_disable_irq(share_ctrl);
+ vfe40_send_isp_msg(&vfe40_ctrl->subdev,
+ share_ctrl->vfeFrameId,
+ MSG_ID_PIX0_UPDATE_ACK);
+ share_ctrl->comp_output_mode &=
+ ~(share_ctrl->outpath.output_mode);
+ share_ctrl->current_mode &=
+ (VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI0);
+ } else {
+ if (share_ctrl->recording_state == VFE_STATE_START_REQUESTED) {
+ if (share_ctrl->operation_mode &
VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
+ msm_camera_io_w(1,
+ share_ctrl->vfebase + vfe40_AXI_WM_CFG[
share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
+ msm_camera_io_w(1,
+ share_ctrl->vfebase + vfe40_AXI_WM_CFG[
share_ctrl->outpath.out0.ch1]);
- } else if (vfe40_ctrl->share_ctrl->operation_mode ==
+ } else if (share_ctrl->operation_mode &
VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
+ msm_camera_io_w(1,
+ share_ctrl->vfebase + vfe40_AXI_WM_CFG[
share_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
+ msm_camera_io_w(1,
+ share_ctrl->vfebase + vfe40_AXI_WM_CFG[
share_ctrl->outpath.out1.ch1]);
}
- vfe40_ctrl->recording_state = VFE_STATE_STARTED;
+ share_ctrl->recording_state = VFE_STATE_STARTED;
msm_camera_io_w_mb(1,
- vfe40_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
CDBG("start video triggered .\n");
- } else if (vfe40_ctrl->recording_state ==
+ } else if (share_ctrl->recording_state ==
VFE_STATE_STOP_REQUESTED) {
- if (vfe40_ctrl->share_ctrl->operation_mode ==
+ if (share_ctrl->operation_mode &
VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
- msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
+ msm_camera_io_w(0,
+ share_ctrl->vfebase + vfe40_AXI_WM_CFG[
share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
+ msm_camera_io_w(0,
+ share_ctrl->vfebase + vfe40_AXI_WM_CFG[
share_ctrl->outpath.out0.ch1]);
- } else if (vfe40_ctrl->share_ctrl->operation_mode ==
+ } else if (share_ctrl->operation_mode &
VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
- msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
+ msm_camera_io_w(0,
+ share_ctrl->vfebase + vfe40_AXI_WM_CFG[
share_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
+ msm_camera_io_w(0,
+ share_ctrl->vfebase + vfe40_AXI_WM_CFG[
share_ctrl->outpath.out1.ch1]);
}
CDBG("stop video triggered .\n");
}
- if (vfe40_ctrl->start_ack_pending == TRUE) {
+ if (atomic_cmpxchg(
+ &share_ctrl->pix0_update_ack_pending, 1, 0) == 1) {
+ share_ctrl->comp_output_mode |=
+ (share_ctrl->outpath.output_mode
+ & ~(VFE40_OUTPUT_MODE_TERTIARY1|
+ VFE40_OUTPUT_MODE_TERTIARY2));
vfe40_send_isp_msg(&vfe40_ctrl->subdev,
- vfe40_ctrl->share_ctrl->vfeFrameId, MSG_ID_START_ACK);
- vfe40_ctrl->start_ack_pending = FALSE;
+ share_ctrl->vfeFrameId, MSG_ID_PIX0_UPDATE_ACK);
+ share_ctrl->current_mode &=
+ (VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI0);
} else {
- if (vfe40_ctrl->recording_state ==
- VFE_STATE_STOP_REQUESTED) {
- vfe40_ctrl->recording_state = VFE_STATE_STOPPED;
+ if (share_ctrl->recording_state ==
+ VFE_STATE_STOP_REQUESTED) {
+ share_ctrl->recording_state = VFE_STATE_STOPPED;
/* request a reg update and send STOP_REC_ACK
* when we process the next reg update irq.
*/
- msm_camera_io_w_mb(1,
- vfe40_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
- } else if (vfe40_ctrl->recording_state ==
+ msm_camera_io_w_mb(1, share_ctrl->vfebase +
+ VFE_REG_UPDATE_CMD);
+ } else if (share_ctrl->recording_state ==
VFE_STATE_STOPPED) {
vfe40_send_isp_msg(&vfe40_ctrl->subdev,
- vfe40_ctrl->share_ctrl->vfeFrameId,
+ share_ctrl->vfeFrameId,
MSG_ID_STOP_REC_ACK);
- vfe40_ctrl->recording_state = VFE_STATE_IDLE;
+ share_ctrl->recording_state = VFE_STATE_IDLE;
}
- spin_lock_irqsave(&vfe40_ctrl->update_ack_lock, flags);
- if (vfe40_ctrl->update_ack_pending == TRUE) {
- vfe40_ctrl->update_ack_pending = FALSE;
+ spin_lock_irqsave(&share_ctrl->update_ack_lock, flags);
+ if (share_ctrl->update_ack_pending == TRUE) {
+ share_ctrl->update_ack_pending = FALSE;
spin_unlock_irqrestore(
- &vfe40_ctrl->update_ack_lock, flags);
+ &share_ctrl->update_ack_lock, flags);
vfe40_send_isp_msg(&vfe40_ctrl->subdev,
- vfe40_ctrl->share_ctrl->vfeFrameId,
- MSG_ID_UPDATE_ACK);
+ share_ctrl->vfeFrameId, MSG_ID_UPDATE_ACK);
} else {
spin_unlock_irqrestore(
- &vfe40_ctrl->update_ack_lock, flags);
+ &share_ctrl->update_ack_lock, flags);
}
}
- if (vfe40_ctrl->share_ctrl->liveshot_state ==
- VFE_STATE_START_REQUESTED) {
+ switch (share_ctrl->liveshot_state) {
+ case VFE_STATE_START_REQUESTED:
CDBG("%s enabling liveshot output\n", __func__);
- if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
+ if (share_ctrl->comp_output_mode &
+ VFE40_OUTPUT_MODE_PRIMARY) {
+ msm_camera_io_w(1, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[
share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
+ msm_camera_io_w(1, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[
share_ctrl->outpath.out0.ch1]);
- vfe40_ctrl->share_ctrl->liveshot_state =
+
+ share_ctrl->liveshot_state =
VFE_STATE_STARTED;
}
- }
-
- if (vfe40_ctrl->share_ctrl->liveshot_state == VFE_STATE_STARTED) {
- vfe40_ctrl->share_ctrl->vfe_capture_count--;
- if (!vfe40_ctrl->share_ctrl->vfe_capture_count)
- vfe40_ctrl->share_ctrl->liveshot_state =
- VFE_STATE_STOP_REQUESTED;
- msm_camera_io_w_mb(1, vfe40_ctrl->
- share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
- } else if (vfe40_ctrl->share_ctrl->liveshot_state ==
- VFE_STATE_STOP_REQUESTED) {
- CDBG("%s: disabling liveshot output\n", __func__);
- if (vfe40_ctrl->share_ctrl->outpath.output_mode &
- VFE40_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
+ break;
+ case VFE_STATE_STARTED:
+ share_ctrl->vfe_capture_count--;
+ if (!share_ctrl->vfe_capture_count &&
+ (share_ctrl->comp_output_mode &
+ VFE40_OUTPUT_MODE_PRIMARY)) {
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[
share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase +
- vfe40_AXI_WM_CFG[vfe40_ctrl->
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[
share_ctrl->outpath.out0.ch1]);
- vfe40_ctrl->share_ctrl->liveshot_state =
- VFE_STATE_STOPPED;
- msm_camera_io_w_mb(1, vfe40_ctrl->share_ctrl->vfebase +
+ }
+ break;
+ case VFE_STATE_STOP_REQUESTED:
+ if (share_ctrl->comp_output_mode &
+ VFE40_OUTPUT_MODE_PRIMARY) {
+ /* Stop requested, stop write masters, and
+ * trigger REG_UPDATE. Send STOP_LS_ACK in
+ * next reg update. */
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[
+ share_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(0, share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[
+ share_ctrl->outpath.out0.ch1]);
+
+ share_ctrl->liveshot_state = VFE_STATE_STOPPED;
+ msm_camera_io_w_mb(1, share_ctrl->vfebase +
VFE_REG_UPDATE_CMD);
}
- } else if (vfe40_ctrl->share_ctrl->liveshot_state ==
- VFE_STATE_STOPPED) {
- vfe40_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
+ break;
+ case VFE_STATE_STOPPED:
+ CDBG("%s Sending STOP_LS ACK\n", __func__);
+ vfe40_send_isp_msg(&vfe40_ctrl->subdev,
+ share_ctrl->vfeFrameId, MSG_ID_STOP_LS_ACK);
+ share_ctrl->liveshot_state = VFE_STATE_IDLE;
+ break;
+ default:
+ break;
}
- if ((vfe40_ctrl->share_ctrl->operation_mode ==
- VFE_OUTPUTS_THUMB_AND_MAIN) ||
- (vfe40_ctrl->share_ctrl->operation_mode ==
- VFE_OUTPUTS_MAIN_AND_THUMB) ||
- (vfe40_ctrl->share_ctrl->operation_mode ==
- VFE_OUTPUTS_THUMB_AND_JPEG) ||
- (vfe40_ctrl->share_ctrl->operation_mode ==
- VFE_OUTPUTS_JPEG_AND_THUMB)) {
+ if ((share_ctrl->operation_mode & VFE_OUTPUTS_THUMB_AND_MAIN) ||
+ (share_ctrl->operation_mode &
+ VFE_OUTPUTS_MAIN_AND_THUMB) ||
+ (share_ctrl->operation_mode &
+ VFE_OUTPUTS_THUMB_AND_JPEG) ||
+ (share_ctrl->operation_mode &
+ VFE_OUTPUTS_JPEG_AND_THUMB)) {
/* in snapshot mode */
/* later we need to add check for live snapshot mode. */
if (vfe40_ctrl->frame_skip_pattern & (0x1 <<
(vfe40_ctrl->snapshot_frame_cnt %
vfe40_ctrl->frame_skip_cnt))) {
- vfe40_ctrl->share_ctrl->vfe_capture_count--;
+ share_ctrl->vfe_capture_count--;
/* if last frame to be captured: */
- if (vfe40_ctrl->share_ctrl->vfe_capture_count == 0) {
- /* stop the bus output:write master enable = 0*/
- if (vfe40_ctrl->share_ctrl->outpath.output_mode
+ if (share_ctrl->vfe_capture_count == 0) {
+ /* stop the bus output: */
+ if (share_ctrl->comp_output_mode
& VFE40_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(0,
- vfe40_ctrl->share_ctrl->vfebase+
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(0,
- vfe40_ctrl->share_ctrl->vfebase+
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out0.ch1]);
- }
- if (vfe40_ctrl->share_ctrl->outpath.output_mode&
+ msm_camera_io_w(0,
+ share_ctrl->vfebase+
+ vfe40_AXI_WM_CFG[
+ share_ctrl->
+ outpath.out0.ch0]);
+ msm_camera_io_w(0,
+ share_ctrl->vfebase+
+ vfe40_AXI_WM_CFG[
+ share_ctrl->
+ outpath.out0.ch1]);
+ }
+ if (share_ctrl->comp_output_mode &
VFE40_OUTPUT_MODE_SECONDARY) {
- msm_camera_io_w(0,
- vfe40_ctrl->share_ctrl->vfebase+
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(0,
- vfe40_ctrl->share_ctrl->vfebase+
- vfe40_AXI_WM_CFG[vfe40_ctrl->
- share_ctrl->outpath.out1.ch1]);
+ msm_camera_io_w(0,
+ share_ctrl->vfebase+
+ vfe40_AXI_WM_CFG[
+ share_ctrl->
+ outpath.out1.ch0]);
+ msm_camera_io_w(0,
+ share_ctrl->vfebase+
+ vfe40_AXI_WM_CFG[
+ share_ctrl->
+ outpath.out1.ch1]);
}
msm_camera_io_w_mb
(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
- vfe40_ctrl->share_ctrl->vfebase +
+ share_ctrl->vfebase +
VFE_CAMIF_COMMAND);
vfe40_ctrl->snapshot_frame_cnt = -1;
vfe40_ctrl->frame_skip_cnt = 31;
- vfe40_ctrl->frame_skip_pattern = 0xffffffff;
+ vfe40_ctrl->frame_skip_pattern =
+ 0xffffffff;
} /*if snapshot count is 0*/
} /*if frame is not being dropped*/
vfe40_ctrl->snapshot_frame_cnt++;
/* then do reg_update. */
msm_camera_io_w(1,
- vfe40_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
} /* if snapshot mode. */
}
+}
-static void vfe40_set_default_reg_values(
- struct vfe40_ctrl_type *vfe40_ctrl)
+static void vfe40_process_rdi0_reg_update_irq(
+ struct vfe40_ctrl_type *vfe40_ctrl)
{
- msm_camera_io_w(0x800080,
- vfe40_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_0);
- msm_camera_io_w(0x800080,
- vfe40_ctrl->share_ctrl->vfebase + VFE_DEMUX_GAIN_1);
- /* What value should we program CGC_OVERRIDE to? */
- msm_camera_io_w(0xFFFFF,
- vfe40_ctrl->share_ctrl->vfebase + VFE_CGC_OVERRIDE);
+ if (atomic_cmpxchg(
+ &vfe40_ctrl->share_ctrl->rdi0_update_ack_pending, 2, 0) == 2) {
+ axi_stop_rdi0(vfe40_ctrl->share_ctrl);
+ axi_disable_irq(vfe40_ctrl->share_ctrl);
+ vfe40_send_isp_msg(&vfe40_ctrl->subdev,
+ vfe40_ctrl->share_ctrl->vfeFrameId,
+ MSG_ID_RDI0_UPDATE_ACK);
+ vfe40_ctrl->share_ctrl->comp_output_mode &=
+ ~VFE40_OUTPUT_MODE_TERTIARY1;
+ vfe40_ctrl->share_ctrl->current_mode &=
+ ~(VFE_OUTPUTS_RDI0);
+ }
- /* default frame drop period and pattern */
- msm_camera_io_w(0, vfe40_ctrl->share_ctrl->vfebase + VFE_CLAMP_ENC_MIN);
- msm_camera_io_w(0xFFFFFF,
- vfe40_ctrl->share_ctrl->vfebase + VFE_CLAMP_ENC_MAX);
- msm_camera_io_w(0,
- vfe40_ctrl->share_ctrl->vfebase + VFE_CLAMP_VIEW_MIN);
- msm_camera_io_w(0xFFFFFF,
- vfe40_ctrl->share_ctrl->vfebase + VFE_CLAMP_VIEW_MAX);
+ if (atomic_cmpxchg(
+ &vfe40_ctrl->share_ctrl->rdi0_update_ack_pending, 1, 0) == 1) {
+ vfe40_ctrl->share_ctrl->comp_output_mode |=
+ VFE40_OUTPUT_MODE_TERTIARY1;
+ vfe40_send_isp_msg(&vfe40_ctrl->subdev,
+ vfe40_ctrl->share_ctrl->vfeFrameId,
+ MSG_ID_RDI0_UPDATE_ACK);
+ vfe40_ctrl->share_ctrl->current_mode &=
+ ~(VFE_OUTPUTS_RDI0);
+ }
+}
- /* stats UB config */
- msm_camera_io_w(0x3980007,
- vfe40_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_AEC_UB_CFG);
- msm_camera_io_w(0x3A00007,
- vfe40_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_AF_UB_CFG);
- msm_camera_io_w(0x3A8000F,
- vfe40_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_AWB_UB_CFG);
- msm_camera_io_w(0x3B80007,
- vfe40_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_RS_UB_CFG);
- msm_camera_io_w(0x3C0001F,
- vfe40_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_CS_UB_CFG);
- msm_camera_io_w(0x3E0001F,
- vfe40_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_HIST_UB_CFG);
+static void vfe40_process_rdi1_reg_update_irq(
+ struct vfe40_ctrl_type *vfe40_ctrl)
+{
+ if (atomic_cmpxchg(
+ &vfe40_ctrl->share_ctrl->rdi1_update_ack_pending, 2, 0) == 2) {
+ axi_stop_rdi1(vfe40_ctrl->share_ctrl);
+ axi_disable_irq(vfe40_ctrl->share_ctrl);
+ vfe40_send_isp_msg(&vfe40_ctrl->subdev,
+ vfe40_ctrl->share_ctrl->vfeFrameId,
+ MSG_ID_RDI1_UPDATE_ACK);
+ vfe40_ctrl->share_ctrl->comp_output_mode &=
+ ~VFE40_OUTPUT_MODE_TERTIARY2;
+ vfe40_ctrl->share_ctrl->current_mode &=
+ ~(VFE_OUTPUTS_RDI1);
+ }
+
+ if (atomic_cmpxchg(
+ &vfe40_ctrl->share_ctrl->rdi1_update_ack_pending, 1, 0) == 1) {
+ vfe40_ctrl->share_ctrl->comp_output_mode |=
+ VFE40_OUTPUT_MODE_TERTIARY2;
+ vfe40_send_isp_msg(&vfe40_ctrl->subdev,
+ vfe40_ctrl->share_ctrl->vfeFrameId,
+ MSG_ID_RDI1_UPDATE_ACK);
+ vfe40_ctrl->share_ctrl->current_mode &=
+ ~(VFE_OUTPUTS_RDI1);
+ }
}
static void vfe40_process_reset_irq(
@@ -2625,39 +3464,45 @@
unsigned long flags;
atomic_set(&vfe40_ctrl->share_ctrl->vstate, 0);
+ atomic_set(&vfe40_ctrl->share_ctrl->handle_common_irq, 0);
spin_lock_irqsave(&vfe40_ctrl->share_ctrl->stop_flag_lock, flags);
if (vfe40_ctrl->share_ctrl->stop_ack_pending) {
vfe40_ctrl->share_ctrl->stop_ack_pending = FALSE;
spin_unlock_irqrestore(
&vfe40_ctrl->share_ctrl->stop_flag_lock, flags);
+ if (vfe40_ctrl->share_ctrl->sync_abort)
+ complete(&vfe40_ctrl->share_ctrl->reset_complete);
+ else
vfe40_send_isp_msg(&vfe40_ctrl->subdev,
- vfe40_ctrl->share_ctrl->vfeFrameId, MSG_ID_STOP_ACK);
+ vfe40_ctrl->share_ctrl->vfeFrameId,
+ MSG_ID_STOP_ACK);
} else {
spin_unlock_irqrestore(
&vfe40_ctrl->share_ctrl->stop_flag_lock, flags);
/* this is from reset command. */
- vfe40_set_default_reg_values(vfe40_ctrl);
-
+ vfe40_reset_internal_variables(vfe40_ctrl);
+ if (vfe40_ctrl->share_ctrl->vfe_reset_flag) {
+ vfe40_ctrl->share_ctrl->vfe_reset_flag = false;
+ msm_camera_io_w(0xFF00,
+ vfe40_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
+ } else {
/* reload all write masters. (frame & line)*/
- msm_camera_io_w(0x7FFF,
+ msm_camera_io_w(0xFF7F,
vfe40_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
- vfe40_send_isp_msg(&vfe40_ctrl->subdev,
- vfe40_ctrl->share_ctrl->vfeFrameId, MSG_ID_RESET_ACK);
+ }
+ complete(&vfe40_ctrl->share_ctrl->reset_complete);
}
}
static void vfe40_process_camif_sof_irq(
struct vfe40_ctrl_type *vfe40_ctrl)
{
- if (vfe40_ctrl->share_ctrl->operation_mode ==
+ if (vfe40_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_RAW) {
- if (vfe40_ctrl->start_ack_pending) {
- vfe40_send_isp_msg(&vfe40_ctrl->subdev,
- vfe40_ctrl->share_ctrl->vfeFrameId,
- MSG_ID_START_ACK);
- vfe40_ctrl->start_ack_pending = FALSE;
- }
+ if (vfe40_ctrl->share_ctrl->start_ack_pending)
+ vfe40_ctrl->share_ctrl->start_ack_pending = FALSE;
+
vfe40_ctrl->share_ctrl->vfe_capture_count--;
/* if last frame to be captured: */
if (vfe40_ctrl->share_ctrl->vfe_capture_count == 0) {
@@ -2672,11 +3517,15 @@
VFE_MODE_OF_OPERATION_VIDEO) &&
(vfe40_ctrl->share_ctrl->vfeFrameId %
vfe40_ctrl->hfr_mode != 0)) {
- vfe40_ctrl->share_ctrl->vfeFrameId++;
+ if (vfe40_ctrl->vfe_sof_count_enable)
+ vfe40_ctrl->share_ctrl->vfeFrameId++;
CDBG("Skip the SOF notification when HFR enabled\n");
return;
}
- vfe40_ctrl->share_ctrl->vfeFrameId++;
+
+ if (vfe40_ctrl->vfe_sof_count_enable)
+ vfe40_ctrl->share_ctrl->vfeFrameId++;
+
vfe40_send_isp_msg(&vfe40_ctrl->subdev,
vfe40_ctrl->share_ctrl->vfeFrameId, MSG_ID_SOF_ACK);
CDBG("camif_sof_irq, frameId = %d\n",
@@ -2694,11 +3543,19 @@
struct axi_ctrl_t *axi_ctrl, uint32_t errStatus)
{
uint32_t reg_value;
+ if (errStatus & VFE40_IMASK_VIOLATION) {
+ pr_err("vfe40_irq: violation interrupt\n");
+ reg_value = msm_camera_io_r(
+ axi_ctrl->share_ctrl->vfebase + VFE_VIOLATION_STATUS);
+ pr_err("%s: violationStatus = 0x%x\n", __func__, reg_value);
+ }
if (errStatus & VFE40_IMASK_CAMIF_ERROR) {
pr_err("vfe40_irq: camif errors\n");
reg_value = msm_camera_io_r(
axi_ctrl->share_ctrl->vfebase + VFE_CAMIF_STATUS);
+ v4l2_subdev_notify(&axi_ctrl->subdev,
+ NOTIFY_VFE_CAMIF_ERROR, (void *)NULL);
pr_err("camifStatus = 0x%x\n", reg_value);
vfe40_send_isp_msg(&axi_ctrl->subdev,
axi_ctrl->share_ctrl->vfeFrameId, MSG_ID_CAMIF_ERROR);
@@ -2722,12 +3579,34 @@
if (errStatus & VFE40_IMASK_REALIGN_BUF_CR_OVFL)
pr_err("vfe40_irq: realign bug CR overflow\n");
- if (errStatus & VFE40_IMASK_VIOLATION) {
- pr_err("vfe40_irq: violation interrupt\n");
- reg_value = msm_camera_io_r(
- axi_ctrl->share_ctrl->vfebase + VFE_VIOLATION_STATUS);
- pr_err("%s: violationStatus = 0x%x\n", __func__, reg_value);
- }
+ if (errStatus & VFE40_IMASK_STATS_BE_BUS_OVFL)
+ pr_err("vfe40_irq: be stats bus overflow\n");
+
+ if (errStatus & VFE40_IMASK_STATS_BG_BUS_OVFL)
+ pr_err("vfe40_irq: bg stats bus overflow\n");
+
+ if (errStatus & VFE40_IMASK_STATS_BF_BUS_OVFL)
+ pr_err("vfe40_irq: bf stats bus overflow\n");
+
+ if (errStatus & VFE40_IMASK_STATS_AWB_BUS_OVFL)
+ pr_err("vfe40_irq: awb stats bus overflow\n");
+
+ if (errStatus & VFE40_IMASK_STATS_RS_BUS_OVFL)
+ pr_err("vfe40_irq: rs stats bus overflow\n");
+
+ if (errStatus & VFE40_IMASK_STATS_CS_BUS_OVFL)
+ pr_err("vfe40_irq: cs stats bus overflow\n");
+
+ if (errStatus & VFE40_IMASK_STATS_IHIST_BUS_OVFL)
+ pr_err("vfe40_irq: ihist stats bus overflow\n");
+
+ if (errStatus & VFE40_IMASK_STATS_SKIN_BHIST_BUS_OVFL)
+ pr_err("vfe40_irq: skin/bhist stats bus overflow\n");
+}
+
+static void vfe40_process_common_error_irq(
+ struct axi_ctrl_t *axi_ctrl, uint32_t errStatus)
+{
if (errStatus & VFE40_IMASK_IMG_MAST_0_BUS_OVFL)
pr_err("vfe40_irq: image master 0 bus overflow\n");
@@ -2750,29 +3629,294 @@
if (errStatus & VFE40_IMASK_IMG_MAST_6_BUS_OVFL)
pr_err("vfe40_irq: image master 6 bus overflow\n");
- if (errStatus & VFE40_IMASK_STATS_AE_BG_BUS_OVFL)
- pr_err("vfe40_irq: ae/bg stats bus overflow\n");
+}
- if (errStatus & VFE40_IMASK_STATS_AF_BF_BUS_OVFL)
- pr_err("vfe40_irq: af/bf stats bus overflow\n");
+static void vfe_send_outmsg(
+ struct axi_ctrl_t *axi_ctrl, uint8_t msgid,
+ uint32_t ch0_paddr, uint32_t ch1_paddr,
+ uint32_t ch2_paddr, uint32_t inst_handle)
+{
+ struct isp_msg_output msg;
- if (errStatus & VFE40_IMASK_STATS_AWB_BUS_OVFL)
- pr_err("vfe40_irq: awb stats bus overflow\n");
+ msg.output_id = msgid;
+ msg.buf.inst_handle = inst_handle;
+ msg.buf.ch_paddr[0] = ch0_paddr;
+ msg.buf.ch_paddr[1] = ch1_paddr;
+ msg.buf.ch_paddr[2] = ch2_paddr;
+ switch (msgid) {
+ case MSG_ID_OUTPUT_TERTIARY1:
+ msg.frameCounter = axi_ctrl->share_ctrl->rdi0FrameId;
+ break;
+ case MSG_ID_OUTPUT_TERTIARY2:
+ msg.frameCounter = axi_ctrl->share_ctrl->rdi1FrameId;
+ break;
+ default:
+ msg.frameCounter = axi_ctrl->share_ctrl->vfeFrameId;
+ break;
+ }
- if (errStatus & VFE40_IMASK_STATS_RS_BUS_OVFL)
- pr_err("vfe40_irq: rs stats bus overflow\n");
+ v4l2_subdev_notify(&axi_ctrl->subdev,
+ NOTIFY_VFE_MSG_OUT,
+ &msg);
+ return;
+}
- if (errStatus & VFE40_IMASK_STATS_CS_BUS_OVFL)
- pr_err("vfe40_irq: cs stats bus overflow\n");
+static void vfe40_process_output_path_irq_0(
+ struct axi_ctrl_t *axi_ctrl)
+{
+ uint32_t ping_pong;
+ uint32_t ch0_paddr, ch1_paddr, ch2_paddr;
+ uint8_t out_bool = 0;
+ struct msm_free_buf *free_buf = NULL;
- if (errStatus & VFE40_IMASK_STATS_IHIST_BUS_OVFL)
- pr_err("vfe40_irq: ihist stats bus overflow\n");
+ free_buf = vfe40_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_PRIMARY, axi_ctrl);
- if (errStatus & VFE40_IMASK_STATS_SKIN_BHIST_BUS_OVFL)
- pr_err("vfe40_irq: skin/bhist stats bus overflow\n");
+ /* we render frames in the following conditions:
+ 1. Continuous mode and the free buffer is avaialable.
+ 2. In snapshot shot mode, free buffer is not always available.
+ when pending snapshot count is <=1, then no need to use
+ free buffer.
+ */
+ out_bool = (
+ (axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_THUMB_AND_MAIN ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_MAIN_AND_THUMB ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_THUMB_AND_JPEG ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_JPEG_AND_THUMB ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_RAW ||
+ axi_ctrl->share_ctrl->liveshot_state ==
+ VFE_STATE_STARTED ||
+ axi_ctrl->share_ctrl->liveshot_state ==
+ VFE_STATE_STOP_REQUESTED ||
+ axi_ctrl->share_ctrl->liveshot_state ==
+ VFE_STATE_STOPPED) &&
+ (axi_ctrl->share_ctrl->vfe_capture_count <= 1)) ||
+ free_buf;
- if (errStatus & VFE40_IMASK_AXI_ERROR)
- pr_err("vfe40_irq: axi error\n");
+ if (out_bool) {
+ ping_pong = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+ VFE_BUS_PING_PONG_STATUS);
+
+ /* Channel 0*/
+ ch0_paddr = vfe40_get_ch_addr(
+ ping_pong, axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out0.ch0);
+ /* Channel 1*/
+ ch1_paddr = vfe40_get_ch_addr(
+ ping_pong, axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out0.ch1);
+ /* Channel 2*/
+ ch2_paddr = vfe40_get_ch_addr(
+ ping_pong, axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out0.ch2);
+
+ CDBG("output path 0, ch0 = 0x%x, ch1 = 0x%x, ch2 = 0x%x\n",
+ ch0_paddr, ch1_paddr, ch2_paddr);
+ if (free_buf) {
+ /* Y channel */
+ vfe40_put_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out0.ch0,
+ free_buf->ch_paddr[0]);
+ /* Chroma channel */
+ vfe40_put_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out0.ch1,
+ free_buf->ch_paddr[1]);
+ if (free_buf->num_planes > 2)
+ vfe40_put_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out0.ch2,
+ free_buf->ch_paddr[2]);
+ }
+ if (axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_THUMB_AND_MAIN ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_MAIN_AND_THUMB ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_THUMB_AND_JPEG ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_JPEG_AND_THUMB ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_RAW ||
+ axi_ctrl->share_ctrl->liveshot_state ==
+ VFE_STATE_STOPPED)
+ axi_ctrl->share_ctrl->outpath.out0.capture_cnt--;
+
+ vfe_send_outmsg(axi_ctrl,
+ MSG_ID_OUTPUT_PRIMARY, ch0_paddr,
+ ch1_paddr, ch2_paddr,
+ axi_ctrl->share_ctrl->outpath.out0.inst_handle);
+
+ } else {
+ axi_ctrl->share_ctrl->outpath.out0.frame_drop_cnt++;
+ CDBG("path_irq_0 - no free buffer!\n");
+ }
+}
+
+static void vfe40_process_output_path_irq_1(
+ struct axi_ctrl_t *axi_ctrl)
+{
+ uint32_t ping_pong;
+ uint32_t ch0_paddr, ch1_paddr, ch2_paddr;
+ /* this must be snapshot main image output. */
+ uint8_t out_bool = 0;
+ struct msm_free_buf *free_buf = NULL;
+
+ free_buf = vfe40_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_SECONDARY, axi_ctrl);
+ out_bool = ((axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_THUMB_AND_MAIN ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_MAIN_AND_THUMB ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_RAW ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_JPEG_AND_THUMB) &&
+ (axi_ctrl->share_ctrl->vfe_capture_count <= 1)) ||
+ free_buf;
+
+ if (out_bool) {
+ ping_pong = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+ VFE_BUS_PING_PONG_STATUS);
+
+ /* Y channel */
+ ch0_paddr = vfe40_get_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out1.ch0);
+ /* Chroma channel */
+ ch1_paddr = vfe40_get_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out1.ch1);
+ ch2_paddr = vfe40_get_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out1.ch2);
+
+ CDBG("%s ch0 = 0x%x, ch1 = 0x%x, ch2 = 0x%x\n",
+ __func__, ch0_paddr, ch1_paddr, ch2_paddr);
+ if (free_buf) {
+ /* Y channel */
+ vfe40_put_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out1.ch0,
+ free_buf->ch_paddr[0]);
+ /* Chroma channel */
+ vfe40_put_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out1.ch1,
+ free_buf->ch_paddr[1]);
+ if (free_buf->num_planes > 2)
+ vfe40_put_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out1.ch2,
+ free_buf->ch_paddr[2]);
+ }
+ if (axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_THUMB_AND_MAIN ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_MAIN_AND_THUMB ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_RAW ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_JPEG_AND_THUMB)
+ axi_ctrl->share_ctrl->outpath.out1.capture_cnt--;
+
+ vfe_send_outmsg(axi_ctrl,
+ MSG_ID_OUTPUT_SECONDARY, ch0_paddr,
+ ch1_paddr, ch2_paddr,
+ axi_ctrl->share_ctrl->outpath.out1.inst_handle);
+
+ } else {
+ axi_ctrl->share_ctrl->outpath.out1.frame_drop_cnt++;
+ CDBG("path_irq_1 - no free buffer!\n");
+ }
+}
+
+static void vfe40_process_output_path_irq_rdi0(
+ struct axi_ctrl_t *axi_ctrl)
+{
+ uint32_t ping_pong;
+ uint32_t ch0_paddr = 0;
+ /* this must be rdi image output. */
+ struct msm_free_buf *free_buf = NULL;
+ /*RDI0*/
+ if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI0) {
+ free_buf = vfe40_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_TERTIARY1, axi_ctrl);
+ if (free_buf) {
+ ping_pong = msm_camera_io_r(axi_ctrl->
+ share_ctrl->vfebase +
+ VFE_BUS_PING_PONG_STATUS);
+
+ /* Y only channel */
+ ch0_paddr = vfe40_get_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out2.ch0);
+
+ pr_debug("%s ch0 = 0x%x\n",
+ __func__, ch0_paddr);
+
+ /* Y channel */
+ vfe40_put_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out2.ch0,
+ free_buf->ch_paddr[0]);
+
+ vfe_send_outmsg(axi_ctrl,
+ MSG_ID_OUTPUT_TERTIARY1, ch0_paddr,
+ 0, 0,
+ axi_ctrl->share_ctrl->outpath.out2.inst_handle);
+
+ } else {
+ axi_ctrl->share_ctrl->outpath.out2.frame_drop_cnt++;
+ pr_err("path_irq_2 irq - no free buffer for rdi0!\n");
+ }
+ }
+}
+
+static void vfe40_process_output_path_irq_rdi1(
+ struct axi_ctrl_t *axi_ctrl)
+{
+ uint32_t ping_pong;
+ uint32_t ch0_paddr = 0;
+ /* this must be rdi image output. */
+ struct msm_free_buf *free_buf = NULL;
+ /*RDI1*/
+ if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI1) {
+ free_buf = vfe40_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
+ VFE_MSG_OUTPUT_TERTIARY2, axi_ctrl);
+ if (free_buf) {
+ ping_pong = msm_camera_io_r(axi_ctrl->
+ share_ctrl->vfebase +
+ VFE_BUS_PING_PONG_STATUS);
+
+ /* Y channel */
+ ch0_paddr = vfe40_get_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out3.ch0);
+ pr_debug("%s ch0 = 0x%x\n",
+ __func__, ch0_paddr);
+
+ /* Y channel */
+ vfe40_put_ch_addr(ping_pong,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out3.ch0,
+ free_buf->ch_paddr[0]);
+
+ vfe_send_outmsg(axi_ctrl,
+ MSG_ID_OUTPUT_TERTIARY2, ch0_paddr,
+ 0, 0,
+ axi_ctrl->share_ctrl->outpath.out3.inst_handle);
+ } else {
+ axi_ctrl->share_ctrl->outpath.out3.frame_drop_cnt++;
+ pr_err("path_irq irq - no free buffer for rdi1!\n");
+ }
+ }
}
static uint32_t vfe40_process_stats_irq_common(
@@ -2799,8 +3943,8 @@
return returnAddr;
}
-static void
-vfe_send_stats_msg(struct vfe40_ctrl_type *vfe40_ctrl,
+static void vfe_send_stats_msg(
+ struct vfe40_ctrl_type *vfe40_ctrl,
uint32_t bufAddress, uint32_t statsNum)
{
int rc = 0;
@@ -2809,24 +3953,36 @@
/* @todo This is causing issues, need further investigate */
/* spin_lock_irqsave(&ctrl->state_lock, flags); */
struct isp_msg_stats msgStats;
+ uint32_t stats_type;
msgStats.frameCounter = vfe40_ctrl->share_ctrl->vfeFrameId;
+ if (vfe40_ctrl->simultaneous_sof_stat)
+ msgStats.frameCounter--;
msgStats.buffer = bufAddress;
-
switch (statsNum) {
case statsAeNum:{
- msgStats.id = MSG_ID_STATS_AEC;
+ msgStats.id =
+ (!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSG_ID_STATS_AEC
+ : MSG_ID_STATS_BG;
+ stats_type =
+ (!vfe40_use_bayer_stats(vfe40_ctrl)) ?
+ MSM_STATS_TYPE_AEC : MSM_STATS_TYPE_BG;
rc = vfe40_ctrl->stats_ops.dispatch(
vfe40_ctrl->stats_ops.stats_ctrl,
- MSM_STATS_TYPE_AEC, bufAddress,
+ stats_type, bufAddress,
&msgStats.buf_idx, &vaddr, &msgStats.fd,
vfe40_ctrl->stats_ops.client);
}
break;
case statsAfNum:{
- msgStats.id = MSG_ID_STATS_AF;
+ msgStats.id =
+ (!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSG_ID_STATS_AF
+ : MSG_ID_STATS_BF;
+ stats_type =
+ (!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSM_STATS_TYPE_AF
+ : MSM_STATS_TYPE_BF;
rc = vfe40_ctrl->stats_ops.dispatch(
vfe40_ctrl->stats_ops.stats_ctrl,
- MSM_STATS_TYPE_AF, bufAddress,
+ stats_type, bufAddress,
&msgStats.buf_idx, &vaddr, &msgStats.fd,
vfe40_ctrl->stats_ops.client);
}
@@ -2868,6 +4024,15 @@
vfe40_ctrl->stats_ops.client);
}
break;
+ case statsSkinNum: {
+ msgStats.id = MSG_ID_STATS_BHIST;
+ rc = vfe40_ctrl->stats_ops.dispatch(
+ vfe40_ctrl->stats_ops.stats_ctrl,
+ MSM_STATS_TYPE_BHIST, bufAddress,
+ &msgStats.buf_idx, &vaddr, &msgStats.fd,
+ vfe40_ctrl->stats_ops.client);
+ }
+ break;
default:
goto stats_done;
@@ -2882,7 +4047,7 @@
__func__, msgStats.id, msgStats.buffer);
}
stats_done:
- spin_unlock_irqrestore(&ctrl->state_lock, flags);
+ /* spin_unlock_irqrestore(&ctrl->state_lock, flags); */
return;
}
@@ -2893,11 +4058,14 @@
uint32_t temp;
msgStats.frame_id = vfe40_ctrl->share_ctrl->vfeFrameId;
+ if (vfe40_ctrl->simultaneous_sof_stat)
+ msgStats.frame_id--;
+
msgStats.status_bits = status_bits;
- msgStats.aec.buff = vfe40_ctrl->aecStatsControl.bufToRender;
+ msgStats.aec.buff = vfe40_ctrl->aecbgStatsControl.bufToRender;
msgStats.awb.buff = vfe40_ctrl->awbStatsControl.bufToRender;
- msgStats.af.buff = vfe40_ctrl->afStatsControl.bufToRender;
+ msgStats.af.buff = vfe40_ctrl->afbfStatsControl.bufToRender;
msgStats.ihist.buff = vfe40_ctrl->ihistStatsControl.bufToRender;
msgStats.rs.buff = vfe40_ctrl->rsStatsControl.bufToRender;
@@ -2912,6 +4080,31 @@
&msgStats);
}
+static void vfe40_process_stats_bg_irq(struct vfe40_ctrl_type *vfe40_ctrl)
+{
+ unsigned long flags;
+ uint32_t addr;
+ uint32_t stats_type;
+ stats_type =
+ (!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSM_STATS_TYPE_AEC
+ : MSM_STATS_TYPE_BG;
+ spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
+ addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, stats_type);
+ spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
+ if (addr) {
+ vfe40_ctrl->aecbgStatsControl.bufToRender =
+ vfe40_process_stats_irq_common(vfe40_ctrl, statsAeNum,
+ addr);
+
+ vfe_send_stats_msg(vfe40_ctrl,
+ vfe40_ctrl->aecbgStatsControl.bufToRender, statsAeNum);
+ } else{
+ vfe40_ctrl->aecbgStatsControl.droppedStatsFrameCount++;
+ CDBG("%s: droppedStatsFrameCount = %d", __func__,
+ vfe40_ctrl->aecbgStatsControl.droppedStatsFrameCount);
+ }
+}
+
static void vfe40_process_stats_awb_irq(struct vfe40_ctrl_type *vfe40_ctrl)
{
unsigned long flags;
@@ -2933,6 +4126,53 @@
}
}
+static void vfe40_process_stats_bf_irq(struct vfe40_ctrl_type *vfe40_ctrl)
+{
+ unsigned long flags;
+ uint32_t addr;
+ uint32_t stats_type;
+ stats_type =
+ (!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSM_STATS_TYPE_AF
+ : MSM_STATS_TYPE_BF;
+ spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
+ addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, stats_type);
+ spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
+ if (addr) {
+ vfe40_ctrl->afbfStatsControl.bufToRender =
+ vfe40_process_stats_irq_common(vfe40_ctrl, statsAfNum,
+ addr);
+
+ vfe_send_stats_msg(vfe40_ctrl,
+ vfe40_ctrl->afbfStatsControl.bufToRender, statsAfNum);
+ } else{
+ vfe40_ctrl->afbfStatsControl.droppedStatsFrameCount++;
+ CDBG("%s: droppedStatsFrameCount = %d", __func__,
+ vfe40_ctrl->afbfStatsControl.droppedStatsFrameCount);
+ }
+}
+
+static void vfe40_process_stats_bhist_irq(struct vfe40_ctrl_type *vfe40_ctrl)
+{
+ unsigned long flags;
+ uint32_t addr;
+ spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
+ addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl, MSM_STATS_TYPE_BHIST);
+ spin_unlock_irqrestore(&vfe40_ctrl->stats_bufq_lock, flags);
+ if (addr) {
+ vfe40_ctrl->bhistStatsControl.bufToRender =
+ vfe40_process_stats_irq_common(vfe40_ctrl,
+ statsSkinNum, addr);
+
+ vfe_send_stats_msg(vfe40_ctrl,
+ vfe40_ctrl->bhistStatsControl.bufToRender,
+ statsSkinNum);
+ } else{
+ vfe40_ctrl->bhistStatsControl.droppedStatsFrameCount++;
+ CDBG("%s: droppedStatsFrameCount = %d", __func__,
+ vfe40_ctrl->bhistStatsControl.droppedStatsFrameCount);
+ }
+}
+
static void vfe40_process_stats_ihist_irq(struct vfe40_ctrl_type *vfe40_ctrl)
{
unsigned long flags;
@@ -2988,8 +4228,9 @@
vfe40_process_stats_irq_common(vfe40_ctrl, statsCsNum,
addr);
- vfe_send_stats_msg(vfe40_ctrl,
- vfe40_ctrl->csStatsControl.bufToRender, statsCsNum);
+ vfe_send_stats_msg(vfe40_ctrl,
+ vfe40_ctrl->csStatsControl.bufToRender,
+ statsCsNum);
} else {
vfe40_ctrl->csStatsControl.droppedStatsFrameCount++;
CDBG("%s: droppedStatsFrameCount = %d", __func__,
@@ -3003,9 +4244,30 @@
unsigned long flags;
int32_t process_stats = false;
uint32_t addr;
+ uint32_t stats_type;
CDBG("%s, stats = 0x%x\n", __func__, status_bits);
spin_lock_irqsave(&vfe40_ctrl->stats_bufq_lock, flags);
+ stats_type =
+ (!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSM_STATS_TYPE_AEC
+ : MSM_STATS_TYPE_BG;
+
+ if (status_bits & VFE_IRQ_STATUS0_STATS_BG) {
+ addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl,
+ stats_type);
+ if (addr) {
+ vfe40_ctrl->aecbgStatsControl.bufToRender =
+ vfe40_process_stats_irq_common(
+ vfe40_ctrl, statsAeNum, addr);
+ process_stats = true;
+ } else{
+ vfe40_ctrl->aecbgStatsControl.bufToRender = 0;
+ vfe40_ctrl->aecbgStatsControl.droppedStatsFrameCount++;
+ }
+ } else {
+ vfe40_ctrl->aecbgStatsControl.bufToRender = 0;
+ }
+
if (status_bits & VFE_IRQ_STATUS0_STATS_AWB) {
addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl,
MSM_STATS_TYPE_AWB);
@@ -3023,6 +4285,26 @@
vfe40_ctrl->awbStatsControl.bufToRender = 0;
}
+ stats_type =
+ (!vfe40_use_bayer_stats(vfe40_ctrl)) ? MSM_STATS_TYPE_AF
+ : MSM_STATS_TYPE_BF;
+ if (status_bits & VFE_IRQ_STATUS0_STATS_BF) {
+ addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl,
+ stats_type);
+ if (addr) {
+ vfe40_ctrl->afbfStatsControl.bufToRender =
+ vfe40_process_stats_irq_common(
+ vfe40_ctrl, statsAfNum,
+ addr);
+ process_stats = true;
+ } else {
+ vfe40_ctrl->afbfStatsControl.bufToRender = 0;
+ vfe40_ctrl->afbfStatsControl.droppedStatsFrameCount++;
+ }
+ } else {
+ vfe40_ctrl->afbfStatsControl.bufToRender = 0;
+ }
+
if (status_bits & VFE_IRQ_STATUS0_STATS_IHIST) {
addr = (uint32_t)vfe40_stats_dqbuf(vfe40_ctrl,
MSM_STATS_TYPE_IHIST);
@@ -3084,7 +4366,6 @@
struct vfe40_ctrl_type *vfe40_ctrl, uint32_t irqstatus)
{
uint32_t status_bits = VFE_COM_STATUS & irqstatus;
-
if ((vfe40_ctrl->hfr_mode != HFR_MODE_OFF) &&
(vfe40_ctrl->share_ctrl->vfeFrameId %
vfe40_ctrl->hfr_mode != 0)) {
@@ -3114,14 +4395,34 @@
CDBG("irq regUpdateIrq\n");
vfe40_process_reg_update_irq(vfe40_ctrl);
break;
+ case VFE_IRQ_STATUS0_RDI0_REG_UPDATE:
+ CDBG("irq rdi0 regUpdateIrq\n");
+ vfe40_process_rdi0_reg_update_irq(vfe40_ctrl);
+ break;
+ case VFE_IRQ_STATUS0_RDI1_REG_UPDATE:
+ CDBG("irq rdi1 regUpdateIrq\n");
+ vfe40_process_rdi1_reg_update_irq(vfe40_ctrl);
+ break;
case VFE_IMASK_WHILE_STOPPING_0:
CDBG("irq resetAckIrq\n");
vfe40_process_reset_irq(vfe40_ctrl);
break;
+ case VFE_IRQ_STATUS0_STATS_BG:
+ CDBG("Stats BG irq occured.\n");
+ vfe40_process_stats_bg_irq(vfe40_ctrl);
+ break;
+ case VFE_IRQ_STATUS0_STATS_BF:
+ CDBG("Stats BF irq occured.\n");
+ vfe40_process_stats_bf_irq(vfe40_ctrl);
+ break;
case VFE_IRQ_STATUS0_STATS_AWB:
CDBG("Stats AWB irq occured.\n");
vfe40_process_stats_awb_irq(vfe40_ctrl);
break;
+ case VFE_IRQ_STATUS0_STATS_SKIN_BHIST:
+ CDBG("Stats BHIST irq occured.\n");
+ vfe40_process_stats_bhist_irq(vfe40_ctrl);
+ break;
case VFE_IRQ_STATUS0_STATS_IHIST:
CDBG("Stats IHIST irq occured.\n");
vfe40_process_stats_ihist_irq(vfe40_ctrl);
@@ -3161,15 +4462,17 @@
{
unsigned long flags;
struct axi_ctrl_t *axi_ctrl = (struct axi_ctrl_t *)data;
+ struct vfe40_ctrl_type *vfe40_ctrl = axi_ctrl->share_ctrl->vfe40_ctrl;
struct vfe40_isr_queue_cmd *qcmd = NULL;
+ int stat_interrupt;
CDBG("=== axi40_do_tasklet start ===\n");
- while (atomic_read(&axi_ctrl->share_ctrl->irq_cnt)) {
+ while (atomic_read(&irq_cnt)) {
spin_lock_irqsave(&axi_ctrl->tasklet_lock, flags);
qcmd = list_first_entry(&axi_ctrl->tasklet_q,
struct vfe40_isr_queue_cmd, list);
- atomic_sub(1, &axi_ctrl->share_ctrl->irq_cnt);
+ atomic_sub(1, &irq_cnt);
if (!qcmd) {
spin_unlock_irqrestore(&axi_ctrl->tasklet_lock,
@@ -3181,38 +4484,82 @@
spin_unlock_irqrestore(&axi_ctrl->tasklet_lock,
flags);
+ if (axi_ctrl->share_ctrl->stats_comp) {
+ stat_interrupt = (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK_0);
+ } else {
+ stat_interrupt =
+ (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_BG) |
+ (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_AWB) |
+ (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_BF) |
+ (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_IHIST) |
+ (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_RS) |
+ (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_CS);
+ }
if (qcmd->vfeInterruptStatus0 &
- VFE_IRQ_STATUS0_CAMIF_SOF_MASK)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ VFE_IRQ_STATUS0_CAMIF_SOF_MASK) {
+ if (stat_interrupt)
+ vfe40_ctrl->simultaneous_sof_stat = 1;
+ v4l2_subdev_notify(&vfe40_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_CAMIF_SOF_MASK);
+ }
/* interrupt to be processed, *qcmd has the payload. */
if (qcmd->vfeInterruptStatus0 &
- VFE_IRQ_STATUS0_REG_UPDATE_MASK) {
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ VFE_IRQ_STATUS0_REG_UPDATE_MASK)
+ v4l2_subdev_notify(&vfe40_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_REG_UPDATE_MASK);
- }
+
+ if (qcmd->vfeInterruptStatus1 &
+ VFE_IRQ_STATUS0_RDI0_REG_UPDATE_MASK)
+ v4l2_subdev_notify(&vfe40_ctrl->subdev,
+ NOTIFY_VFE_IRQ,
+ (void *)VFE_IRQ_STATUS0_RDI0_REG_UPDATE);
+
+ if (qcmd->vfeInterruptStatus1 &
+ VFE_IRQ_STATUS0_RDI1_REG_UPDATE_MASK)
+ v4l2_subdev_notify(&vfe40_ctrl->subdev,
+ NOTIFY_VFE_IRQ,
+ (void *)VFE_IRQ_STATUS0_RDI1_REG_UPDATE);
if (qcmd->vfeInterruptStatus0 &
VFE_IMASK_WHILE_STOPPING_0)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe40_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IMASK_WHILE_STOPPING_0);
+ if (atomic_read(&axi_ctrl->share_ctrl->handle_common_irq)) {
+ if (qcmd->vfeInterruptStatus1 &
+ VFE40_IMASK_COMMON_ERROR_ONLY_1) {
+ pr_err("irq errorIrq\n");
+ vfe40_process_common_error_irq(
+ axi_ctrl,
+ qcmd->vfeInterruptStatus1 &
+ VFE40_IMASK_COMMON_ERROR_ONLY_1);
+ }
+
+ v4l2_subdev_notify(&axi_ctrl->subdev,
+ NOTIFY_AXI_IRQ,
+ (void *)qcmd->vfeInterruptStatus0);
+ }
+
if (atomic_read(&axi_ctrl->share_ctrl->vstate)) {
if (qcmd->vfeInterruptStatus1 &
- VFE40_IMASK_ERROR_ONLY_1) {
+ VFE40_IMASK_VFE_ERROR_ONLY_1) {
pr_err("irq errorIrq\n");
vfe40_process_error_irq(
axi_ctrl,
qcmd->vfeInterruptStatus1 &
- VFE40_IMASK_ERROR_ONLY_1);
+ VFE40_IMASK_VFE_ERROR_ONLY_1);
}
- v4l2_subdev_notify(&axi_ctrl->subdev,
- NOTIFY_AXI_IRQ,
- (void *)qcmd->vfeInterruptStatus0);
/* then process stats irq. */
if (axi_ctrl->share_ctrl->stats_comp) {
@@ -3220,54 +4567,74 @@
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK_0) {
CDBG("Stats composite irq occured.\n");
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe40_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)qcmd->vfeInterruptStatus0);
}
} else {
/* process individual stats interrupt. */
if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_BG)
+ v4l2_subdev_notify(&vfe40_ctrl->subdev,
+ NOTIFY_VFE_IRQ,
+ (void *)VFE_IRQ_STATUS0_STATS_BG);
+
+ if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_STATS_AWB)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe40_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_STATS_AWB);
+
+ if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_BF)
+ v4l2_subdev_notify(&vfe40_ctrl->subdev,
+ NOTIFY_VFE_IRQ,
+ (void *)VFE_IRQ_STATUS0_STATS_BF);
+ if (qcmd->vfeInterruptStatus0 &
+ VFE_IRQ_STATUS0_STATS_SKIN_BHIST)
+ v4l2_subdev_notify(&vfe40_ctrl->subdev,
+ NOTIFY_VFE_IRQ,
+ (void *)
+ VFE_IRQ_STATUS0_STATS_SKIN_BHIST);
+
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_STATS_IHIST)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe40_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_STATS_IHIST);
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_STATS_RS)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe40_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_STATS_RS);
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_STATS_CS)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe40_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_STATS_CS);
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS1_SYNC_TIMER0)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe40_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS1_SYNC_TIMER0);
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS1_SYNC_TIMER1)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe40_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS1_SYNC_TIMER1);
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS1_SYNC_TIMER2)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe40_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS1_SYNC_TIMER2);
}
}
+ vfe40_ctrl->simultaneous_sof_stat = 0;
kfree(qcmd);
}
CDBG("=== axi40_do_tasklet end ===\n");
@@ -3312,16 +4679,26 @@
spin_lock_irqsave(&axi_ctrl->tasklet_lock, flags);
list_add_tail(&qcmd->list, &axi_ctrl->tasklet_q);
- atomic_add(1, &axi_ctrl->share_ctrl->irq_cnt);
+ atomic_add(1, &irq_cnt);
spin_unlock_irqrestore(&axi_ctrl->tasklet_lock, flags);
tasklet_schedule(&axi_ctrl->vfe40_tasklet);
return IRQ_HANDLED;
}
+int msm_axi_subdev_isr_routine(struct v4l2_subdev *sd,
+ u32 status, bool *handled)
+{
+ struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+ irqreturn_t ret;
+ CDBG("%s E ", __func__);
+ ret = vfe40_parse_irq(axi_ctrl->vfeirq->start, axi_ctrl);
+ *handled = TRUE;
+ return 0;
+}
static long vfe_stats_bufq_sub_ioctl(
struct vfe40_ctrl_type *vfe_ctrl,
- struct msm_vfe_cfg_cmd *cmd, void *ion_client)
+ struct msm_vfe_cfg_cmd *cmd, void *ion_client, int domain_num)
{
long rc = 0;
switch (cmd->cmd_type) {
@@ -3370,7 +4747,7 @@
rc = vfe_ctrl->stats_ops.enqueue_buf(
&vfe_ctrl->stats_ctrl,
(struct msm_stats_buf_info *)cmd->value,
- vfe_ctrl->stats_ops.client);
+ vfe_ctrl->stats_ops.client, domain_num);
break;
case VFE_CMD_STATS_FLUSH_BUFQ:
{
@@ -3391,6 +4768,22 @@
vfe_ctrl->stats_ops.client);
}
break;
+ case VFE_CMD_STATS_UNREGBUF:
+ {
+ struct msm_stats_reqbuf *req_buf = NULL;
+ req_buf = (struct msm_stats_reqbuf *)cmd->value;
+ if (sizeof(struct msm_stats_reqbuf) != cmd->length) {
+ /* error. the length not match */
+ pr_err("%s: stats reqbuf input size = %d,\n"
+ "struct size = %d, mitch match\n",
+ __func__, cmd->length,
+ sizeof(struct msm_stats_reqbuf));
+ rc = -EINVAL ;
+ goto end;
+ }
+ rc = vfe40_stats_unregbuf(vfe_ctrl, req_buf, domain_num);
+ }
+ break;
default:
rc = -1;
pr_err("%s: cmd_type %d not supported", __func__,
@@ -3409,10 +4802,9 @@
struct vfe40_ctrl_type *vfe40_ctrl =
(struct vfe40_ctrl_type *)v4l2_get_subdevdata(sd);
struct msm_isp_cmd vfecmd;
- struct msm_camvfe_params *vfe_params =
- (struct msm_camvfe_params *)arg;
- struct msm_vfe_cfg_cmd *cmd = vfe_params->vfe_cfg;
- void *data = vfe_params->data;
+ struct msm_camvfe_params *vfe_params;
+ struct msm_vfe_cfg_cmd *cmd;
+ void *data;
long rc = 0;
struct vfe_cmd_stats_buf *scfg = NULL;
@@ -3423,6 +4815,17 @@
return -EFAULT;
}
+ CDBG("%s\n", __func__);
+ if (subdev_cmd == VIDIOC_MSM_VFE_INIT) {
+ CDBG("%s init\n", __func__);
+ return msm_vfe_subdev_init(sd);
+ } else if (subdev_cmd == VIDIOC_MSM_VFE_RELEASE) {
+ msm_vfe_subdev_release(sd);
+ return 0;
+ }
+ vfe_params = (struct msm_camvfe_params *)arg;
+ cmd = vfe_params->vfe_cfg;
+ data = vfe_params->data;
switch (cmd->cmd_type) {
case CMD_VFE_PROCESS_IRQ:
vfe40_process_irq(vfe40_ctrl, (uint32_t) data);
@@ -3430,27 +4833,33 @@
case VFE_CMD_STATS_REQBUF:
case VFE_CMD_STATS_ENQUEUEBUF:
case VFE_CMD_STATS_FLUSH_BUFQ:
+ case VFE_CMD_STATS_UNREGBUF:
/* for easy porting put in one envelope */
rc = vfe_stats_bufq_sub_ioctl(vfe40_ctrl,
- cmd, vfe_params->data);
+ cmd, vfe_params->data, pmctl->domain_num);
return rc;
default:
if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
- cmd->cmd_type != CMD_CONFIG_PONG_ADDR &&
- cmd->cmd_type != CMD_CONFIG_FREE_BUF_ADDR &&
- cmd->cmd_type != CMD_STATS_AEC_BUF_RELEASE &&
- cmd->cmd_type != CMD_STATS_AWB_BUF_RELEASE &&
- cmd->cmd_type != CMD_STATS_IHIST_BUF_RELEASE &&
- cmd->cmd_type != CMD_STATS_RS_BUF_RELEASE &&
- cmd->cmd_type != CMD_STATS_CS_BUF_RELEASE &&
- cmd->cmd_type != CMD_STATS_AF_BUF_RELEASE) {
- if (copy_from_user(&vfecmd,
+ cmd->cmd_type != CMD_CONFIG_PONG_ADDR &&
+ cmd->cmd_type != CMD_CONFIG_FREE_BUF_ADDR &&
+ cmd->cmd_type != CMD_STATS_AEC_BUF_RELEASE &&
+ cmd->cmd_type != CMD_STATS_AWB_BUF_RELEASE &&
+ cmd->cmd_type != CMD_STATS_IHIST_BUF_RELEASE &&
+ cmd->cmd_type != CMD_STATS_RS_BUF_RELEASE &&
+ cmd->cmd_type != CMD_STATS_CS_BUF_RELEASE &&
+ cmd->cmd_type != CMD_STATS_AF_BUF_RELEASE &&
+ cmd->cmd_type != CMD_STATS_BG_BUF_RELEASE &&
+ cmd->cmd_type != CMD_STATS_BF_BUF_RELEASE &&
+ cmd->cmd_type != CMD_STATS_BHIST_BUF_RELEASE &&
+ cmd->cmd_type != CMD_VFE_PIX_SOF_COUNT_UPDATE &&
+ cmd->cmd_type != CMD_VFE_COUNT_PIX_SOF_ENABLE) {
+ if (copy_from_user(&vfecmd,
(void __user *)(cmd->value),
sizeof(vfecmd))) {
- pr_err("%s %d: copy_from_user failed\n",
- __func__, __LINE__);
- return -EFAULT;
- }
+ pr_err("%s %d: copy_from_user failed\n",
+ __func__, __LINE__);
+ return -EFAULT;
+ }
} else {
/* here eith stats release or frame release. */
if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
@@ -3472,6 +4881,25 @@
sack->nextStatsBuf = *(uint32_t *)data;
}
}
+ }
+
+ CDBG("%s: cmdType = %d\n", __func__, cmd->cmd_type);
+
+ if ((cmd->cmd_type == CMD_STATS_AF_ENABLE) ||
+ (cmd->cmd_type == CMD_STATS_AWB_ENABLE) ||
+ (cmd->cmd_type == CMD_STATS_IHIST_ENABLE) ||
+ (cmd->cmd_type == CMD_STATS_RS_ENABLE) ||
+ (cmd->cmd_type == CMD_STATS_CS_ENABLE) ||
+ (cmd->cmd_type == CMD_STATS_AEC_ENABLE) ||
+ (cmd->cmd_type == CMD_STATS_BG_ENABLE) ||
+ (cmd->cmd_type == CMD_STATS_BF_ENABLE) ||
+ (cmd->cmd_type == CMD_STATS_BHIST_ENABLE)) {
+ struct axidata *axid;
+ axid = data;
+ if (!axid) {
+ rc = -EFAULT;
+ goto vfe40_config_done;
+ }
CDBG("%s: cmdType = %d\n", __func__, cmd->cmd_type);
if ((cmd->cmd_type == CMD_STATS_AF_ENABLE) ||
@@ -3485,39 +4913,69 @@
goto vfe40_config_done;
}
switch (cmd->cmd_type) {
- case CMD_GENERAL:
- rc = vfe40_proc_general(pmctl, &vfecmd, vfe40_ctrl);
- break;
- case CMD_CONFIG_PING_ADDR: {
- int path = *((int *)cmd->value);
- struct vfe40_output_ch *outch =
- vfe40_get_ch(path, vfe40_ctrl->share_ctrl);
- outch->ping = *((struct msm_free_buf *)data);
- }
- break;
-
- case CMD_CONFIG_PONG_ADDR: {
- int path = *((int *)cmd->value);
- struct vfe40_output_ch *outch =
- vfe40_get_ch(path, vfe40_ctrl->share_ctrl);
- outch->pong = *((struct msm_free_buf *)data);
- }
- break;
-
- case CMD_CONFIG_FREE_BUF_ADDR: {
- int path = *((int *)cmd->value);
- struct vfe40_output_ch *outch =
- vfe40_get_ch(path, vfe40_ctrl->share_ctrl);
- outch->free_buf = *((struct msm_free_buf *)data);
- }
- break;
- case CMD_SNAP_BUF_RELEASE:
- break;
+ case CMD_STATS_AEC_ENABLE:
+ case CMD_STATS_BG_ENABLE:
+ case CMD_STATS_BF_ENABLE:
+ case CMD_STATS_BHIST_ENABLE:
+ case CMD_STATS_AWB_ENABLE:
+ case CMD_STATS_IHIST_ENABLE:
+ case CMD_STATS_RS_ENABLE:
+ case CMD_STATS_CS_ENABLE:
default:
- pr_err("%s Unsupported AXI configuration %x ", __func__,
- cmd->cmd_type);
- break;
+ pr_err("%s Unsupported cmd type %d",
+ __func__, cmd->cmd_type);
+ break;
}
+ goto vfe40_config_done;
+ }
+ switch (cmd->cmd_type) {
+ case CMD_GENERAL:
+ rc = vfe40_proc_general(pmctl, &vfecmd, vfe40_ctrl);
+ break;
+ case CMD_VFE_COUNT_PIX_SOF_ENABLE: {
+ int enable = *((int *)cmd->value);
+ if (enable)
+ vfe40_ctrl->vfe_sof_count_enable = TRUE;
+ else
+ vfe40_ctrl->vfe_sof_count_enable = false;
+ }
+ break;
+ case CMD_VFE_PIX_SOF_COUNT_UPDATE:
+ if (!vfe40_ctrl->vfe_sof_count_enable)
+ vfe40_ctrl->share_ctrl->vfeFrameId =
+ *((uint32_t *)vfe_params->data);
+ break;
+ case CMD_CONFIG_PING_ADDR: {
+ int path = *((int *)cmd->value);
+ struct vfe40_output_ch *outch =
+ vfe40_get_ch(path, vfe40_ctrl->share_ctrl);
+ outch->ping = *((struct msm_free_buf *)data);
+ }
+ break;
+
+ case CMD_CONFIG_PONG_ADDR: {
+ int path = *((int *)cmd->value);
+ struct vfe40_output_ch *outch =
+ vfe40_get_ch(path, vfe40_ctrl->share_ctrl);
+ outch->pong = *((struct msm_free_buf *)data);
+ }
+ break;
+
+ case CMD_CONFIG_FREE_BUF_ADDR: {
+ int path = *((int *)cmd->value);
+ struct vfe40_output_ch *outch =
+ vfe40_get_ch(path, vfe40_ctrl->share_ctrl);
+ outch->free_buf = *((struct msm_free_buf *)data);
+ }
+ break;
+
+ case CMD_SNAP_BUF_RELEASE:
+ break;
+
+ default:
+ pr_err("%s Unsupported AXI configuration %x ", __func__,
+ cmd->cmd_type);
+ break;
}
vfe40_config_done:
kfree(scfg);
@@ -3526,6 +4984,39 @@
return rc;
}
+static struct msm_cam_clk_info vfe40_clk_info[] = {
+ {"camss_top_ahb_clk", -1},
+ {"vfe_clk_src", 266670000},
+ {"camss_vfe_vfe_clk", -1},
+ {"camss_csi_vfe_clk", -1},
+ {"iface_clk", -1},
+ {"bus_clk", -1},
+ {"alt_bus_clk", -1},
+};
+
+static int msm_axi_subdev_s_crystal_freq(struct v4l2_subdev *sd,
+ u32 freq, u32 flags)
+{
+ int rc = 0;
+ int round_rate;
+ struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+
+ round_rate = clk_round_rate(axi_ctrl->vfe_clk[1], freq);
+ if (rc < 0) {
+ pr_err("%s: clk_round_rate failed %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ vfe_clk_rate = round_rate;
+ rc = clk_set_rate(axi_ctrl->vfe_clk[1], round_rate);
+ if (rc < 0)
+ pr_err("%s: clk_set_rate failed %d\n",
+ __func__, rc);
+
+ return rc;
+}
+
static const struct v4l2_subdev_core_ops msm_vfe_subdev_core_ops = {
.ioctl = msm_vfe_subdev_ioctl,
};
@@ -3534,46 +5025,1088 @@
.core = &msm_vfe_subdev_core_ops,
};
-int msm_vfe_subdev_init(struct v4l2_subdev *sd,
- struct msm_cam_media_controller *mctl)
+static void msm_vfe40_init_vbif_parms(void __iomem *vfe_vbif_base)
+{
+ msm_camera_io_w_mb(0x1,
+ vfe_vbif_base + VFE40_VBIF_CLKON);
+ msm_camera_io_w_mb(0x1,
+ vfe_vbif_base + VFE40_VBIF_ROUND_ROBIN_QOS_ARB);
+ msm_camera_io_w_mb(0xFFFF,
+ vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO_EN);
+ msm_camera_io_w_mb(0xFFFFFFFF,
+ vfe_vbif_base + VFE40_VBIF_OUT_AXI_AOOO);
+
+ msm_camera_io_w_mb(0x10101010,
+ vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF0);
+ msm_camera_io_w_mb(0x10101010,
+ vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF1);
+ msm_camera_io_w_mb(0x10101010,
+ vfe_vbif_base + VFE40_VBIF_IN_RD_LIM_CONF2);
+ msm_camera_io_w_mb(0x10101010,
+ vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF0);
+ msm_camera_io_w_mb(0x10101010,
+ vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF1);
+ msm_camera_io_w_mb(0x10101010,
+ vfe_vbif_base + VFE40_VBIF_IN_WR_LIM_CONF2);
+ msm_camera_io_w_mb(0x00001010,
+ vfe_vbif_base + VFE40_VBIF_OUT_RD_LIM_CONF0);
+ msm_camera_io_w_mb(0x00001010,
+ vfe_vbif_base + VFE40_VBIF_OUT_WR_LIM_CONF0);
+ msm_camera_io_w_mb(0x00000707,
+ vfe_vbif_base + VFE40_VBIF_DDR_OUT_MAX_BURST);
+ msm_camera_io_w_mb(0x00000030,
+ vfe_vbif_base + VFE40_VBIF_ARB_CTL);
+ msm_camera_io_w_mb(0x04210842,
+ vfe_vbif_base + VFE40_VBIF_DDR_ARB_CONF0);
+ msm_camera_io_w_mb(0x04210842,
+ vfe_vbif_base + VFE40_VBIF_DDR_ARB_CONF1);
+}
+
+int msm_axi_subdev_init(struct v4l2_subdev *sd)
+{
+ int rc = 0;
+ struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+ struct msm_cam_media_controller *mctl;
+ mctl = v4l2_get_subdev_hostdata(sd);
+ if (mctl == NULL) {
+ pr_err("%s: mctl is NULL\n", __func__);
+ rc = -EINVAL;
+ goto mctl_failed;
+ }
+ axi_ctrl->share_ctrl->axi_ref_cnt++;
+ if (axi_ctrl->share_ctrl->axi_ref_cnt > 1)
+ return rc;
+
+ spin_lock_init(&axi_ctrl->tasklet_lock);
+ INIT_LIST_HEAD(&axi_ctrl->tasklet_q);
+ spin_lock_init(&axi_ctrl->share_ctrl->sd_notify_lock);
+
+ axi_ctrl->share_ctrl->vfebase = ioremap(axi_ctrl->vfemem->start,
+ resource_size(axi_ctrl->vfemem));
+ if (!axi_ctrl->share_ctrl->vfebase) {
+ rc = -ENOMEM;
+ pr_err("%s: vfe ioremap failed\n", __func__);
+ goto remap_failed;
+ }
+
+ axi_ctrl->share_ctrl->vfe_vbif_base =
+ ioremap(axi_ctrl->vfe_vbif_mem->start,
+ resource_size(axi_ctrl->vfe_vbif_mem));
+ if (!axi_ctrl->share_ctrl->vfe_vbif_base) {
+ rc = -ENOMEM;
+ pr_err("%s: vfe ioremap failed\n", __func__);
+ goto remap_failed;
+ }
+
+ if (axi_ctrl->fs_vfe) {
+ rc = regulator_enable(axi_ctrl->fs_vfe);
+ if (rc) {
+ pr_err("%s: Regulator enable failed\n", __func__);
+ goto fs_failed;
+ }
+ }
+
+ rc = msm_cam_clk_enable(&axi_ctrl->pdev->dev, vfe40_clk_info,
+ axi_ctrl->vfe_clk, ARRAY_SIZE(vfe40_clk_info), 1);
+ if (rc < 0)
+ goto clk_enable_failed;
+
+ axi_ctrl->bus_perf_client =
+ msm_bus_scale_register_client(&vfe_bus_client_pdata);
+ if (!axi_ctrl->bus_perf_client) {
+ pr_err("%s: Registration Failed!\n", __func__);
+ axi_ctrl->bus_perf_client = 0;
+ goto bus_scale_register_failed;
+ }
+
+ msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_PREVIEW);
+
+ rc = iommu_attach_device(mctl->domain, axi_ctrl->iommu_ctx);
+ if (rc < 0) {
+ pr_err("%s: imgwr attach failed rc = %d\n", __func__, rc);
+ rc = -ENODEV;
+ goto device_imgwr_attach_failed;
+ }
+
+ msm_vfe40_init_vbif_parms(axi_ctrl->share_ctrl->vfe_vbif_base);
+
+ axi_ctrl->share_ctrl->register_total = VFE40_REGISTER_TOTAL;
+
+ spin_lock_init(&axi_ctrl->share_ctrl->stop_flag_lock);
+ spin_lock_init(&axi_ctrl->share_ctrl->update_ack_lock);
+ spin_lock_init(&axi_ctrl->share_ctrl->start_ack_lock);
+ init_completion(&axi_ctrl->share_ctrl->reset_complete);
+
+ if (!axi_ctrl->use_irq_router)
+ enable_irq(axi_ctrl->vfeirq->start);
+
+ return rc;
+
+bus_scale_register_failed:
+ msm_cam_clk_enable(&axi_ctrl->pdev->dev, vfe40_clk_info,
+ axi_ctrl->vfe_clk, ARRAY_SIZE(vfe40_clk_info), 0);
+clk_enable_failed:
+ if (axi_ctrl->fs_vfe)
+ regulator_disable(axi_ctrl->fs_vfe);
+fs_failed:
+ iounmap(axi_ctrl->share_ctrl->vfebase);
+ axi_ctrl->share_ctrl->vfebase = NULL;
+remap_failed:
+ iommu_detach_device(mctl->domain, axi_ctrl->iommu_ctx);
+device_imgwr_attach_failed:
+ if (!axi_ctrl->use_irq_router)
+ disable_irq(axi_ctrl->vfeirq->start);
+mctl_failed:
+ return rc;
+}
+
+int msm_vfe_subdev_init(struct v4l2_subdev *sd)
{
int rc = 0;
struct vfe40_ctrl_type *vfe40_ctrl =
(struct vfe40_ctrl_type *)v4l2_get_subdevdata(sd);
- v4l2_set_subdev_hostdata(sd, mctl);
- spin_lock_init(&vfe40_ctrl->share_ctrl->stop_flag_lock);
spin_lock_init(&vfe40_ctrl->state_lock);
- spin_lock_init(&vfe40_ctrl->io_lock);
- spin_lock_init(&vfe40_ctrl->update_ack_lock);
spin_lock_init(&vfe40_ctrl->stats_bufq_lock);
-
vfe40_ctrl->update_linear = false;
vfe40_ctrl->update_rolloff = false;
vfe40_ctrl->update_la = false;
vfe40_ctrl->update_gamma = false;
+ vfe40_ctrl->vfe_sof_count_enable = true;
vfe40_ctrl->hfr_mode = HFR_MODE_OFF;
+ memset(&vfe40_ctrl->stats_ctrl, 0,
+ sizeof(struct msm_stats_bufq_ctrl));
+ memset(&vfe40_ctrl->stats_ops, 0, sizeof(struct msm_stats_ops));
+
return rc;
}
+void msm_axi_subdev_release(struct v4l2_subdev *sd)
+{
+ struct msm_cam_media_controller *pmctl =
+ (struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
+ struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+ if (!axi_ctrl->share_ctrl->vfebase) {
+ pr_err("%s: base address unmapped\n", __func__);
+ return;
+ }
+
+ CDBG("%s, free_irq\n", __func__);
+ axi_ctrl->share_ctrl->axi_ref_cnt--;
+ if (axi_ctrl->share_ctrl->axi_ref_cnt > 0)
+ return;
+ if (!axi_ctrl->use_irq_router)
+ disable_irq(axi_ctrl->vfeirq->start);
+ tasklet_kill(&axi_ctrl->vfe40_tasklet);
+
+ iommu_detach_device(pmctl->domain, axi_ctrl->iommu_ctx);
+
+ msm_cam_clk_enable(&axi_ctrl->pdev->dev, vfe40_clk_info,
+ axi_ctrl->vfe_clk, ARRAY_SIZE(vfe40_clk_info), 0);
+ if (axi_ctrl->fs_vfe)
+ regulator_disable(axi_ctrl->fs_vfe);
+
+ iounmap(axi_ctrl->share_ctrl->vfebase);
+ iounmap(axi_ctrl->share_ctrl->vfe_vbif_base);
+ axi_ctrl->share_ctrl->vfebase = NULL;
+
+ if (atomic_read(&irq_cnt))
+ pr_warning("%s, Warning IRQ Count not ZERO\n", __func__);
+
+ msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_EXIT);
+ axi_ctrl->bus_perf_client = 0;
+
+ msm_vfe_subdev_release(&axi_ctrl->share_ctrl->vfe40_ctrl->subdev);
+}
+
void msm_vfe_subdev_release(struct v4l2_subdev *sd)
{
struct vfe40_ctrl_type *vfe40_ctrl =
(struct vfe40_ctrl_type *)v4l2_get_subdevdata(sd);
- if (!vfe40_ctrl->share_ctrl->vfebase)
- vfe40_ctrl->share_ctrl->vfebase = NULL;
+ CDBG("vfe subdev release %p\n",
+ vfe40_ctrl->share_ctrl->vfebase);
}
+void axi_abort(struct axi_ctrl_t *axi_ctrl)
+{
+ uint8_t axi_busy_flag = true;
+ unsigned long flags;
+ /* axi halt command. */
+
+ spin_lock_irqsave(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
+ axi_ctrl->share_ctrl->stop_ack_pending = TRUE;
+ spin_unlock_irqrestore(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
+ msm_camera_io_w(AXI_HALT,
+ axi_ctrl->share_ctrl->vfebase + VFE_AXI_CMD);
+ wmb();
+ while (axi_busy_flag) {
+ if (msm_camera_io_r(
+ axi_ctrl->share_ctrl->vfebase + VFE_AXI_STATUS) & 0x1)
+ axi_busy_flag = false;
+ }
+ /* Ensure the write order while writing
+ * to the command register using the barrier */
+ msm_camera_io_w_mb(AXI_HALT_CLEAR,
+ axi_ctrl->share_ctrl->vfebase + VFE_AXI_CMD);
+
+ /* after axi halt, then ok to apply global reset.
+ * enable reset_ack and async timer interrupt only while
+ * stopping the pipeline.*/
+ msm_camera_io_w(0x80000000,
+ axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
+ msm_camera_io_w(0xF0000000,
+ axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
+
+ /* Ensure the write order while writing
+ * to the command register using the barrier */
+ msm_camera_io_w_mb(VFE_RESET_UPON_STOP_CMD,
+ axi_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET);
+ if (axi_ctrl->share_ctrl->sync_abort)
+ wait_for_completion_interruptible(
+ &axi_ctrl->share_ctrl->reset_complete);
+}
+
+int axi_config_buffers(struct axi_ctrl_t *axi_ctrl,
+ struct msm_camera_vfe_params_t vfe_params)
+{
+ uint16_t vfe_mode = axi_ctrl->share_ctrl->current_mode
+ & ~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1);
+ int rc = 0;
+ switch (vfe_params.cmd_type) {
+ case AXI_CMD_PREVIEW:
+ if (vfe_mode) {
+ if ((axi_ctrl->share_ctrl->current_mode &
+ VFE_OUTPUTS_PREVIEW_AND_VIDEO) ||
+ (axi_ctrl->share_ctrl->current_mode &
+ VFE_OUTPUTS_PREVIEW))
+ /* Configure primary channel */
+ rc = configure_pingpong_buffers(
+ VFE_MSG_START,
+ VFE_MSG_OUTPUT_PRIMARY,
+ axi_ctrl);
+ else
+ /* Configure secondary channel */
+ rc = configure_pingpong_buffers(
+ VFE_MSG_START,
+ VFE_MSG_OUTPUT_SECONDARY,
+ axi_ctrl);
+ }
+ if (axi_ctrl->share_ctrl->current_mode &
+ VFE_OUTPUTS_RDI0)
+ rc = configure_pingpong_buffers(
+ VFE_MSG_START, VFE_MSG_OUTPUT_TERTIARY1,
+ axi_ctrl);
+ if (axi_ctrl->share_ctrl->current_mode &
+ VFE_OUTPUTS_RDI1)
+ rc = configure_pingpong_buffers(
+ VFE_MSG_START, VFE_MSG_OUTPUT_TERTIARY2,
+ axi_ctrl);
+
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers for preview",
+ __func__);
+ rc = -EINVAL;
+ goto config_done;
+ }
+ break;
+ case AXI_CMD_RAW_CAPTURE:
+ rc = configure_pingpong_buffers(
+ VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_PRIMARY,
+ axi_ctrl);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers for snapshot",
+ __func__);
+ rc = -EINVAL;
+ goto config_done;
+ }
+ break;
+ case AXI_CMD_ZSL:
+ rc = configure_pingpong_buffers(VFE_MSG_START,
+ VFE_MSG_OUTPUT_PRIMARY, axi_ctrl);
+ if (rc < 0)
+ goto config_done;
+ rc = configure_pingpong_buffers(VFE_MSG_START,
+ VFE_MSG_OUTPUT_SECONDARY, axi_ctrl);
+ if (rc < 0)
+ goto config_done;
+ break;
+ case AXI_CMD_RECORD:
+ if (axi_ctrl->share_ctrl->current_mode &
+ VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
+ axi_ctrl->share_ctrl->outpath.out1.inst_handle =
+ vfe_params.inst_handle;
+ rc = configure_pingpong_buffers(
+ VFE_MSG_START_RECORDING,
+ VFE_MSG_OUTPUT_SECONDARY,
+ axi_ctrl);
+ } else if (axi_ctrl->share_ctrl->current_mode &
+ VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
+ axi_ctrl->share_ctrl->outpath.out0.inst_handle =
+ vfe_params.inst_handle;
+ rc = configure_pingpong_buffers(
+ VFE_MSG_START_RECORDING,
+ VFE_MSG_OUTPUT_PRIMARY,
+ axi_ctrl);
+ }
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers for video",
+ __func__);
+ rc = -EINVAL;
+ goto config_done;
+ }
+ break;
+ case AXI_CMD_LIVESHOT:
+ axi_ctrl->share_ctrl->outpath.out0.inst_handle =
+ vfe_params.inst_handle;
+ rc = configure_pingpong_buffers(VFE_MSG_CAPTURE,
+ VFE_MSG_OUTPUT_PRIMARY, axi_ctrl);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers for primary output",
+ __func__);
+ rc = -EINVAL;
+ goto config_done;
+ }
+ break;
+ case AXI_CMD_CAPTURE:
+ if (axi_ctrl->share_ctrl->current_mode ==
+ VFE_OUTPUTS_JPEG_AND_THUMB ||
+ axi_ctrl->share_ctrl->current_mode ==
+ VFE_OUTPUTS_THUMB_AND_JPEG) {
+
+ /* Configure primary channel for JPEG */
+ rc = configure_pingpong_buffers(
+ VFE_MSG_JPEG_CAPTURE,
+ VFE_MSG_OUTPUT_PRIMARY,
+ axi_ctrl);
+ } else {
+ /* Configure primary channel */
+ rc = configure_pingpong_buffers(
+ VFE_MSG_CAPTURE,
+ VFE_MSG_OUTPUT_PRIMARY,
+ axi_ctrl);
+ }
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers for primary output",
+ __func__);
+ rc = -EINVAL;
+ goto config_done;
+ }
+ /* Configure secondary channel */
+ rc = configure_pingpong_buffers(
+ VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_SECONDARY,
+ axi_ctrl);
+ if (rc < 0) {
+ pr_err("%s error configuring pingpong buffers for secondary output",
+ __func__);
+ rc = -EINVAL;
+ goto config_done;
+ }
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+
+ }
+config_done:
+ return rc;
+}
+
+void axi_start(struct msm_cam_media_controller *pmctl,
+ struct axi_ctrl_t *axi_ctrl, struct msm_camera_vfe_params_t vfe_params)
+{
+ uint32_t irq_comp_mask = 0, irq_mask = 0;
+ int rc = 0;
+ uint32_t reg_update = 0;
+ uint16_t operation_mode =
+ (axi_ctrl->share_ctrl->current_mode &
+ ~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1));
+ rc = axi_config_buffers(axi_ctrl, vfe_params);
+ if (rc < 0)
+ return;
+
+ switch (vfe_params.cmd_type) {
+ case AXI_CMD_PREVIEW:
+ msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_PREVIEW);
+ break;
+ case AXI_CMD_CAPTURE:
+ case AXI_CMD_RAW_CAPTURE:
+ msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_CAPTURE);
+ break;
+ case AXI_CMD_RECORD:
+ msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_VIDEO);
+ return;
+ case AXI_CMD_ZSL:
+ msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_ZSL);
+ break;
+ case AXI_CMD_LIVESHOT:
+ msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_LIVESHOT);
+ return;
+ default:
+ return;
+ }
+
+ irq_comp_mask =
+ msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_COMP_MASK);
+ irq_mask = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE40_OUTPUT_MODE_PRIMARY) {
+ irq_comp_mask |= (
+ 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
+ 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1);
+ irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+ } else if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ irq_comp_mask |= (
+ 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
+ 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1 |
+ 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch2);
+ irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK;
+ }
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE40_OUTPUT_MODE_SECONDARY) {
+ irq_comp_mask |= (
+ 0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
+ 0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch1 + 8));
+ irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+ } else if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ irq_comp_mask |= (
+ 0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
+ 0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch1 + 8) |
+ 0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch2 + 8));
+ irq_mask |= VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK;
+ }
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE40_OUTPUT_MODE_TERTIARY1) {
+ irq_mask |= (0x1 << (axi_ctrl->share_ctrl->outpath.out2.ch0 +
+ VFE_WM_OFFSET));
+ }
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE40_OUTPUT_MODE_TERTIARY2) {
+ irq_mask |= (0x1 << (axi_ctrl->share_ctrl->outpath.out3.ch0 +
+ VFE_WM_OFFSET));
+ }
+
+ msm_camera_io_w(irq_comp_mask,
+ axi_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ msm_camera_io_w(irq_mask, axi_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+
+ switch (vfe_params.cmd_type) {
+ case AXI_CMD_PREVIEW: {
+ switch (operation_mode) {
+ case VFE_OUTPUTS_PREVIEW:
+ case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE40_OUTPUT_MODE_PRIMARY) {
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch1]);
+ } else if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch1]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch2]);
+ }
+ break;
+ default:
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE40_OUTPUT_MODE_SECONDARY) {
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch1]);
+ } else if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch1]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch2]);
+ }
+ break;
+ }
+ }
+ break;
+ default:
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE40_OUTPUT_MODE_PRIMARY) {
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch1]);
+ } else if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch1]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch2]);
+ }
+
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE40_OUTPUT_MODE_SECONDARY) {
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch1]);
+ } else if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch1]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch2]);
+ }
+ break;
+ }
+ if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[axi_ctrl->share_ctrl->
+ outpath.out2.ch0]);
+ if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe40_AXI_WM_CFG[axi_ctrl->share_ctrl->
+ outpath.out3.ch0]);
+
+ if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+ irq_mask |= VFE_IRQ_STATUS0_RDI0_REG_UPDATE_MASK;
+ if (!atomic_cmpxchg(
+ &axi_ctrl->share_ctrl->rdi0_update_ack_pending,
+ 0, 1))
+ reg_update |= 0x2;
+ }
+ if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+ irq_mask |= VFE_IRQ_STATUS0_RDI1_REG_UPDATE_MASK;
+ if (!atomic_cmpxchg(
+ &axi_ctrl->share_ctrl->rdi1_update_ack_pending,
+ 0, 1))
+ reg_update |= 0x4;
+ }
+ msm_camera_io_w(irq_mask, axi_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ if (operation_mode) {
+ if (!atomic_cmpxchg(
+ &axi_ctrl->share_ctrl->pix0_update_ack_pending,
+ 0, 1))
+ reg_update |= 0x1;
+ }
+
+ msm_camera_io_w_mb(reg_update,
+ axi_ctrl->share_ctrl->vfebase +
+ VFE_REG_UPDATE_CMD);
+ axi_ctrl->share_ctrl->operation_mode |=
+ axi_ctrl->share_ctrl->current_mode;
+ axi_enable_irq(axi_ctrl->share_ctrl);
+}
+
+void axi_stop(struct msm_cam_media_controller *pmctl,
+ struct axi_ctrl_t *axi_ctrl, struct msm_camera_vfe_params_t vfe_params)
+{
+ uint32_t reg_update = 0;
+ uint32_t operation_mode =
+ axi_ctrl->share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
+ VFE_OUTPUTS_RDI1);
+
+ switch (vfe_params.cmd_type) {
+ case AXI_CMD_PREVIEW:
+ case AXI_CMD_CAPTURE:
+ case AXI_CMD_RAW_CAPTURE:
+ case AXI_CMD_ZSL:
+ break;
+ case AXI_CMD_RECORD:
+ msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_PREVIEW);
+ return;
+ case AXI_CMD_LIVESHOT:
+ msm_camera_bus_scale_cfg(axi_ctrl->bus_perf_client, S_VIDEO);
+ return;
+ default:
+ return;
+ }
+
+ if (axi_ctrl->share_ctrl->stop_immediately) {
+ axi_disable_irq(axi_ctrl->share_ctrl);
+ axi_stop_process(axi_ctrl->share_ctrl);
+ return;
+ }
+
+ if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
+ if (!atomic_cmpxchg(
+ &axi_ctrl->share_ctrl->rdi0_update_ack_pending, 0, 2))
+ reg_update |= 0x2;
+ }
+ if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
+ if (!atomic_cmpxchg(
+ &axi_ctrl->share_ctrl->rdi1_update_ack_pending, 0, 2))
+ reg_update |= 0x4;
+ }
+ if (operation_mode) {
+ if (!atomic_cmpxchg(
+ &axi_ctrl->share_ctrl->pix0_update_ack_pending, 0, 2))
+ reg_update |= 0x1;
+ }
+ msm_camera_io_w_mb(reg_update,
+ axi_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+}
+
+static int msm_axi_config(struct v4l2_subdev *sd, void __user *arg)
+{
+ struct msm_vfe_cfg_cmd cfgcmd;
+ struct msm_isp_cmd vfecmd;
+ struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+ struct msm_cam_media_controller *pmctl =
+ (struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
+ int rc = 0, vfe_cmd_type = 0, rdi_mode = 0;
+
+ if (!axi_ctrl->share_ctrl->vfebase) {
+ pr_err("%s: base address unmapped\n", __func__);
+ return -EFAULT;
+ }
+ memset(&cfgcmd, 0, sizeof(struct msm_vfe_cfg_cmd));
+ if (NULL != arg) {
+ if (copy_from_user(&cfgcmd, arg, sizeof(cfgcmd))) {
+ ERR_COPY_FROM_USER();
+ return -EFAULT;
+ }
+ }
+ memset(&vfecmd, 0, sizeof(struct msm_isp_cmd));
+ if (NULL != cfgcmd.value) {
+ if (copy_from_user(&vfecmd,
+ (void __user *)(cfgcmd.value),
+ sizeof(vfecmd))) {
+ pr_err("%s %d: copy_from_user failed\n", __func__,
+ __LINE__);
+ return -EFAULT;
+ }
+ }
+
+ vfe_cmd_type = (cfgcmd.cmd_type & ~(CMD_AXI_CFG_TERT1|
+ CMD_AXI_CFG_TERT2));
+ switch (cfgcmd.cmd_type) {
+ case CMD_AXI_CFG_TERT1:{
+ uint32_t *axio = NULL;
+ axio = kmalloc(vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio)
+ return -ENOMEM;
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ return -EFAULT;
+ }
+ vfe40_config_axi(axi_ctrl, OUTPUT_TERT1, axio);
+ kfree(axio);
+ return rc;
+ }
+ case CMD_AXI_CFG_TERT2:{
+ uint32_t *axio = NULL;
+ axio = kmalloc(vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio)
+ return -ENOMEM;
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ return -EFAULT;
+ }
+ vfe40_config_axi(axi_ctrl, OUTPUT_TERT2, axio);
+ kfree(axio);
+ return rc;
+ }
+ case CMD_AXI_CFG_TERT1|CMD_AXI_CFG_TERT2:{
+ uint32_t *axio = NULL;
+ axio = kmalloc(vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio)
+ return -ENOMEM;
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ return -EFAULT;
+ }
+ vfe40_config_axi(axi_ctrl, OUTPUT_TERT1|OUTPUT_TERT2, axio);
+ kfree(axio);
+ return rc;
+ }
+ default:
+ if (cfgcmd.cmd_type & CMD_AXI_CFG_TERT1)
+ rdi_mode |= OUTPUT_TERT1;
+ if (cfgcmd.cmd_type & CMD_AXI_CFG_TERT2)
+ rdi_mode |= OUTPUT_TERT2;
+ }
+ switch (vfe_cmd_type) {
+ case CMD_AXI_CFG_PRIM: {
+ uint32_t *axio = NULL;
+ axio = kmalloc(vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio) {
+ rc = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ rc = -EFAULT;
+ break;
+ }
+ vfe40_config_axi(axi_ctrl, rdi_mode|OUTPUT_PRIM, axio);
+ kfree(axio);
+ break;
+ }
+ case CMD_AXI_CFG_PRIM_ALL_CHNLS: {
+ uint32_t *axio = NULL;
+ axio = kmalloc(vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio) {
+ rc = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ rc = -EFAULT;
+ break;
+ }
+ vfe40_config_axi(axi_ctrl, rdi_mode|OUTPUT_PRIM_ALL_CHNLS,
+ axio);
+ kfree(axio);
+ break;
+ }
+ case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC: {
+ uint32_t *axio = NULL;
+ axio = kmalloc(vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio) {
+ rc = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ rc = -EFAULT;
+ break;
+ }
+ vfe40_config_axi(axi_ctrl,
+ rdi_mode|OUTPUT_PRIM|OUTPUT_SEC, axio);
+ kfree(axio);
+ break;
+ }
+ case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC_ALL_CHNLS: {
+ uint32_t *axio = NULL;
+ axio = kmalloc(vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio) {
+ rc = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ rc = -EFAULT;
+ break;
+ }
+ vfe40_config_axi(axi_ctrl,
+ rdi_mode|OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS, axio);
+ kfree(axio);
+ break;
+ }
+ case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC: {
+ uint32_t *axio = NULL;
+ axio = kmalloc(vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio) {
+ rc = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ rc = -EFAULT;
+ break;
+ }
+ vfe40_config_axi(axi_ctrl,
+ rdi_mode|OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC, axio);
+ kfree(axio);
+ break;
+ }
+
+ case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC_ALL_CHNLS:
+ pr_err("%s Invalid/Unsupported AXI configuration %x",
+ __func__, cfgcmd.cmd_type);
+ break;
+ case CMD_AXI_START: {
+ struct msm_camera_vfe_params_t vfe_params;
+ if (copy_from_user(&vfe_params,
+ (void __user *)(vfecmd.value),
+ sizeof(struct msm_camera_vfe_params_t))) {
+ return -EFAULT;
+ }
+ axi_ctrl->share_ctrl->current_mode =
+ vfe_params.operation_mode;
+ axi_start(pmctl, axi_ctrl, vfe_params);
+ }
+ break;
+ case CMD_AXI_STOP: {
+ struct msm_camera_vfe_params_t vfe_params;
+ if (copy_from_user(&vfe_params,
+ (void __user *)(vfecmd.value),
+ sizeof(struct msm_camera_vfe_params_t))) {
+ return -EFAULT;
+ }
+ axi_ctrl->share_ctrl->current_mode =
+ vfe_params.operation_mode;
+ axi_ctrl->share_ctrl->stop_immediately =
+ vfe_params.stop_immediately;
+ axi_stop(pmctl, axi_ctrl, vfe_params);
+ }
+ break;
+ case CMD_AXI_RESET:
+ axi_reset(axi_ctrl);
+ break;
+ case CMD_AXI_ABORT:
+ if (copy_from_user(&axi_ctrl->share_ctrl->sync_abort,
+ (void __user *)(vfecmd.value),
+ sizeof(uint8_t))) {
+ return -EFAULT;
+ }
+ axi_abort(axi_ctrl);
+ break;
+ default:
+ pr_err("%s Unsupported AXI configuration %x ", __func__,
+ cfgcmd.cmd_type);
+ break;
+ }
+ return rc;
+}
+
+static void msm_axi_process_irq(struct v4l2_subdev *sd, void *arg)
+{
+ struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+ uint32_t irqstatus = (uint32_t) arg;
+
+ if (!axi_ctrl->share_ctrl->vfebase) {
+ pr_err("%s: base address unmapped\n", __func__);
+ return;
+ }
+
+ /* next, check output path related interrupts. */
+ if (irqstatus &
+ VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE0_MASK) {
+ CDBG("Image composite done 0 irq occured.\n");
+ vfe40_process_output_path_irq_0(axi_ctrl);
+ }
+ if (irqstatus &
+ VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK) {
+ CDBG("Image composite done 1 irq occured.\n");
+ vfe40_process_output_path_irq_1(axi_ctrl);
+ }
+
+ if (axi_ctrl->share_ctrl->comp_output_mode &
+ VFE40_OUTPUT_MODE_TERTIARY1)
+ if (irqstatus & (0x1 << (axi_ctrl->share_ctrl->outpath.out2.ch0
+ + VFE_WM_OFFSET)))
+ vfe40_process_output_path_irq_rdi0(axi_ctrl);
+ if (axi_ctrl->share_ctrl->comp_output_mode &
+ VFE40_OUTPUT_MODE_TERTIARY2)
+ if (irqstatus & (0x1 << (axi_ctrl->share_ctrl->outpath.out3.ch0
+ + VFE_WM_OFFSET)))
+ vfe40_process_output_path_irq_rdi1(axi_ctrl);
+
+ /* in snapshot mode if done then send
+ snapshot done message */
+ if (
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_THUMB_AND_MAIN ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_MAIN_AND_THUMB ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_THUMB_AND_JPEG ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_JPEG_AND_THUMB ||
+ axi_ctrl->share_ctrl->operation_mode &
+ VFE_OUTPUTS_RAW) {
+ if ((axi_ctrl->share_ctrl->outpath.out0.capture_cnt == 0)
+ && (axi_ctrl->share_ctrl->outpath.out1.
+ capture_cnt == 0)) {
+ msm_camera_io_w_mb(
+ CAMIF_COMMAND_STOP_IMMEDIATELY,
+ axi_ctrl->share_ctrl->vfebase +
+ VFE_CAMIF_COMMAND);
+ axi_disable_irq(axi_ctrl->share_ctrl);
+ vfe40_send_isp_msg(&axi_ctrl->subdev,
+ axi_ctrl->share_ctrl->vfeFrameId,
+ MSG_ID_PIX0_UPDATE_ACK);
+ vfe40_send_isp_msg(&axi_ctrl->subdev,
+ axi_ctrl->share_ctrl->vfeFrameId,
+ MSG_ID_SNAPSHOT_DONE);
+ }
+ }
+}
+
+static int msm_axi_buf_cfg(struct v4l2_subdev *sd, void __user *arg)
+{
+ struct msm_camvfe_params *vfe_params =
+ (struct msm_camvfe_params *)arg;
+ struct msm_vfe_cfg_cmd *cmd = vfe_params->vfe_cfg;
+ struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+ void *data = vfe_params->data;
+ int rc = 0;
+
+ if (!axi_ctrl->share_ctrl->vfebase) {
+ pr_err("%s: base address unmapped\n", __func__);
+ return -EFAULT;
+ }
+
+ switch (cmd->cmd_type) {
+ case CMD_CONFIG_PING_ADDR: {
+ int path = *((int *)cmd->value);
+ struct vfe40_output_ch *outch =
+ vfe40_get_ch(path, axi_ctrl->share_ctrl);
+ outch->ping = *((struct msm_free_buf *)data);
+ }
+ break;
+
+ case CMD_CONFIG_PONG_ADDR: {
+ int path = *((int *)cmd->value);
+ struct vfe40_output_ch *outch =
+ vfe40_get_ch(path, axi_ctrl->share_ctrl);
+ outch->pong = *((struct msm_free_buf *)data);
+ }
+ break;
+
+ case CMD_CONFIG_FREE_BUF_ADDR: {
+ int path = *((int *)cmd->value);
+ struct vfe40_output_ch *outch =
+ vfe40_get_ch(path, axi_ctrl->share_ctrl);
+ outch->free_buf = *((struct msm_free_buf *)data);
+ }
+ break;
+ default:
+ pr_err("%s Unsupported AXI Buf config %x ", __func__,
+ cmd->cmd_type);
+ }
+ return rc;
+};
+
static const struct v4l2_subdev_internal_ops msm_vfe_internal_ops;
+static long msm_axi_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ int rc = -ENOIOCTLCMD;
+ switch (cmd) {
+ case VIDIOC_MSM_AXI_INIT:
+ rc = msm_axi_subdev_init(sd);
+ break;
+ case VIDIOC_MSM_AXI_CFG:
+ rc = msm_axi_config(sd, arg);
+ break;
+ case VIDIOC_MSM_AXI_IRQ:
+ msm_axi_process_irq(sd, arg);
+ rc = 0;
+ break;
+ case VIDIOC_MSM_AXI_BUF_CFG:
+ msm_axi_buf_cfg(sd, arg);
+ rc = 0;
+ break;
+ case VIDIOC_MSM_AXI_RELEASE:
+ msm_axi_subdev_release(sd);
+ rc = 0;
+ break;
+ case VIDIOC_MSM_AXI_RDI_COUNT_UPDATE: {
+ struct rdi_count_msg *msg = (struct rdi_count_msg *)arg;
+ struct axi_ctrl_t *axi_ctrl = v4l2_get_subdevdata(sd);
+ switch (msg->rdi_interface) {
+ case RDI_0:
+ axi_ctrl->share_ctrl->rdi0FrameId = msg->count;
+ rc = 0;
+ break;
+ case RDI_1:
+ axi_ctrl->share_ctrl->rdi1FrameId = msg->count;
+ rc = 0;
+ break;
+ case RDI_2:
+ axi_ctrl->share_ctrl->rdi2FrameId = msg->count;
+ rc = 0;
+ break;
+ default:
+ pr_err("%s: Incorrect interface sent\n", __func__);
+ rc = -EINVAL;
+ break;
+ }
+ break;
+ }
+ default:
+ pr_err("%s: command %d not found\n", __func__,
+ _IOC_NR(cmd));
+ break;
+ }
+ return rc;
+}
+
+static const struct v4l2_subdev_core_ops msm_axi_subdev_core_ops = {
+ .ioctl = msm_axi_subdev_ioctl,
+ .interrupt_service_routine = msm_axi_subdev_isr_routine,
+};
+
+static const struct v4l2_subdev_video_ops msm_axi_subdev_video_ops = {
+ .s_crystal_freq = msm_axi_subdev_s_crystal_freq,
+};
+
+static const struct v4l2_subdev_ops msm_axi_subdev_ops = {
+ .core = &msm_axi_subdev_core_ops,
+ .video = &msm_axi_subdev_video_ops,
+};
+
+static const struct v4l2_subdev_internal_ops msm_axi_internal_ops;
+
static int __devinit vfe40_probe(struct platform_device *pdev)
{
int rc = 0;
struct axi_ctrl_t *axi_ctrl;
struct vfe40_ctrl_type *vfe40_ctrl;
struct vfe_share_ctrl_t *share_ctrl;
+ struct intr_table_entry irq_req;
struct msm_cam_subdev_info sd_info;
CDBG("%s: device id = %d\n", __func__, pdev->id);
@@ -3606,8 +6139,25 @@
share_ctrl->vfe40_ctrl = vfe40_ctrl;
axi_ctrl->share_ctrl = share_ctrl;
vfe40_ctrl->share_ctrl = share_ctrl;
+ axi_ctrl->share_ctrl->axi_ref_cnt = 0;
+ v4l2_subdev_init(&axi_ctrl->subdev, &msm_axi_subdev_ops);
+ axi_ctrl->subdev.internal_ops = &msm_axi_internal_ops;
+ axi_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ snprintf(axi_ctrl->subdev.name,
+ sizeof(axi_ctrl->subdev.name), "axi");
+ v4l2_set_subdevdata(&axi_ctrl->subdev, axi_ctrl);
axi_ctrl->pdev = pdev;
- vfe40_axi_probe(axi_ctrl);
+
+ sd_info.sdev_type = AXI_DEV;
+ sd_info.sd_index = pdev->id;
+ sd_info.irq_num = 0;
+ msm_cam_register_subdev_node(&axi_ctrl->subdev, &sd_info);
+
+ media_entity_init(&axi_ctrl->subdev.entity, 0, NULL, 0);
+ axi_ctrl->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+ axi_ctrl->subdev.entity.group_id = AXI_DEV;
+ axi_ctrl->subdev.entity.name = pdev->name;
+ axi_ctrl->subdev.entity.revision = axi_ctrl->subdev.devnode->num;
v4l2_subdev_init(&vfe40_ctrl->subdev, &msm_vfe_subdev_ops);
vfe40_ctrl->subdev.internal_ops = &msm_vfe_internal_ops;
@@ -3624,6 +6174,15 @@
rc = -ENODEV;
goto vfe40_no_resource;
}
+
+ axi_ctrl->vfe_vbif_mem = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "vfe_vbif");
+ if (!axi_ctrl->vfe_vbif_mem) {
+ pr_err("%s: no mem resource?\n", __func__);
+ rc = -ENODEV;
+ goto vfe40_no_resource;
+ }
+
axi_ctrl->vfeirq = platform_get_resource_byname(pdev,
IORESOURCE_IRQ, "vfe");
if (!axi_ctrl->vfeirq) {
@@ -3640,26 +6199,83 @@
goto vfe40_no_resource;
}
- rc = request_irq(axi_ctrl->vfeirq->start, vfe40_parse_irq,
- IRQF_TRIGGER_RISING, "vfe", axi_ctrl);
- if (rc < 0) {
- release_mem_region(axi_ctrl->vfemem->start,
- resource_size(axi_ctrl->vfemem));
- pr_err("%s: irq request fail\n", __func__);
- rc = -EBUSY;
+ axi_ctrl->fs_vfe = regulator_get(&pdev->dev, "vdd");
+ if (IS_ERR(axi_ctrl->fs_vfe)) {
+ pr_err("%s: Regulator get failed %ld\n", __func__,
+ PTR_ERR(axi_ctrl->fs_vfe));
+ axi_ctrl->fs_vfe = NULL;
+ }
+
+ /* Register subdev node before requesting irq since
+ * irq_num is needed by msm_cam_server */
+ sd_info.sdev_type = VFE_DEV;
+ sd_info.sd_index = pdev->id;
+ sd_info.irq_num = axi_ctrl->vfeirq->start;
+ msm_cam_register_subdev_node(&vfe40_ctrl->subdev, &sd_info);
+
+ media_entity_init(&vfe40_ctrl->subdev.entity, 0, NULL, 0);
+ vfe40_ctrl->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+ vfe40_ctrl->subdev.entity.group_id = VFE_DEV;
+ vfe40_ctrl->subdev.entity.name = pdev->name;
+ vfe40_ctrl->subdev.entity.revision = vfe40_ctrl->subdev.devnode->num;
+
+ /* Request for this device irq from the camera server. If the
+ * IRQ Router is present on this target, the interrupt will be
+ * handled by the camera server and the interrupt service
+ * routine called. If the request_irq call returns ENXIO, then
+ * the IRQ Router hardware is not present on this target. We
+ * have to request for the irq ourselves and register the
+ * appropriate interrupt handler. */
+ axi_ctrl->use_irq_router = true;
+ irq_req.cam_hw_idx = MSM_CAM_HW_VFE0 + pdev->id;
+ irq_req.dev_name = "vfe";
+ irq_req.irq_idx = CAMERA_SS_IRQ_8;
+ irq_req.irq_num = axi_ctrl->vfeirq->start;
+ irq_req.is_composite = 0;
+ irq_req.irq_trigger_type = IRQF_TRIGGER_RISING;
+ irq_req.num_hwcore = 1;
+ irq_req.subdev_list[0] = &axi_ctrl->subdev;
+ irq_req.data = (void *)axi_ctrl;
+ rc = msm_cam_server_request_irq(&irq_req);
+ if (rc == -ENXIO) {
+ /* IRQ Router hardware is not present on this hardware.
+ * Request for the IRQ and register the interrupt handler. */
+ axi_ctrl->use_irq_router = false;
+ rc = request_irq(axi_ctrl->vfeirq->start, vfe40_parse_irq,
+ IRQF_TRIGGER_RISING, "vfe", axi_ctrl);
+ if (rc < 0) {
+ release_mem_region(axi_ctrl->vfemem->start,
+ resource_size(axi_ctrl->vfemem));
+ pr_err("%s: irq request fail\n", __func__);
+ rc = -EBUSY;
+ goto vfe40_no_resource;
+ }
+ disable_irq(axi_ctrl->vfeirq->start);
+ } else if (rc < 0) {
+ pr_err("%s Error registering irq ", __func__);
goto vfe40_no_resource;
}
- disable_irq(axi_ctrl->vfeirq->start);
+ /*get device context for IOMMU*/
+ if (pdev->id == 0)
+ axi_ctrl->iommu_ctx = msm_iommu_get_ctx("vfe0");
+ else if (pdev->id == 1)
+ axi_ctrl->iommu_ctx = msm_iommu_get_ctx("vfe1");
+ if (!axi_ctrl->iommu_ctx) {
+ release_mem_region(axi_ctrl->vfemem->start,
+ resource_size(axi_ctrl->vfemem));
+ pr_err("%s: No iommu fw context found\n", __func__);
+ rc = -ENODEV;
+ goto vfe40_no_resource;
+ }
tasklet_init(&axi_ctrl->vfe40_tasklet,
axi40_do_tasklet, (unsigned long)axi_ctrl);
vfe40_ctrl->pdev = pdev;
- sd_info.sdev_type = VFE_DEV;
- sd_info.sd_index = pdev->id;
- sd_info.irq_num = axi_ctrl->vfeirq->start;
- msm_cam_register_subdev_node(&vfe40_ctrl->subdev, &sd_info);
+ /*disable bayer stats by default*/
+ vfe40_ctrl->ver_num.main = 0;
+
return 0;
vfe40_no_resource:
diff --git a/drivers/media/video/msm/vfe/msm_vfe40.h b/drivers/media/video/msm/vfe/msm_vfe40.h
index c8b0cb8..5b73751 100644
--- a/drivers/media/video/msm/vfe/msm_vfe40.h
+++ b/drivers/media/video/msm/vfe/msm_vfe40.h
@@ -50,7 +50,16 @@
/* reset the pipeline when reset command.
* bit 26-32 = 0, domain reset, bit 0-9 = 1 for module reset. */
-#define VFE_RESET_UPON_RESET_CMD 0x000001ff
+#define VFE_RESET_UPON_RESET_CMD 0x000003ff
+
+/* reset the vfe only when reset command*/
+#define VFE_ONLY_RESET_CMD 0x00000002
+
+/*Vfe module reset command*/
+#define VFE_MODULE_RESET_CMD 0x07ffffff
+
+/* wm bit offset for IRQ MASK and IRQ STATUS register */
+#define VFE_WM_OFFSET 6
/* constants for irq registers */
#define VFE_DISABLE_ALL_IRQS 0
@@ -60,6 +69,9 @@
#define VFE_IRQ_STATUS0_CAMIF_SOF_MASK (0x00000001<<0)
#define VFE_IRQ_STATUS0_REG_UPDATE_MASK (0x00000001<<4)
+#define VFE_IRQ_STATUS0_RDI0_REG_UPDATE_MASK (0x00000001<<5)
+#define VFE_IRQ_STATUS0_RDI1_REG_UPDATE_MASK (0x00000001<<6)
+#define VFE_IRQ_STATUS0_RDI2_REG_UPDATE_MASK (0x00000001<<7)
#define VFE_IRQ_STATUS0_STATS_BE (0x00000001<<16)
#define VFE_IRQ_STATUS0_STATS_BG (0x00000001<<17)
#define VFE_IRQ_STATUS0_STATS_BF (0x00000001<<18)
@@ -84,13 +96,22 @@
#define VFE_IRQ_STATUS1_ASYNC_TIMER2 (0x00000001<<30)
#define VFE_IRQ_STATUS1_ASYNC_TIMER3 (0x00000001<<31)
+/*TODOs the irq status passed from axi to vfe irq handler does not account
+* for 2 irq status registers. So below macro is added to differentiate between
+* same bit set on both irq status registers. This wil be fixed later by passing
+*entire payload to vfe irq handler and parsing there instead of passing just the
+*status bit*/
+
+#define VFE_IRQ_STATUS0_RDI0_REG_UPDATE VFE_IRQ_STATUS0_RDI0_REG_UPDATE_MASK
+#define VFE_IRQ_STATUS0_RDI1_REG_UPDATE VFE_IRQ_STATUS0_RDI1_REG_UPDATE_MASK
+
/* imask for while waiting for stop ack, driver has already
* requested stop, waiting for reset irq, and async timer irq.
- * For irq_status_0, bit 28-32 are for async timer. For
- * irq_status_1, bit 22 for reset irq, bit 23 for axi_halt_ack
+ * For irq_status_1, bit 28-32 are for async timer. For
+ * irq_status_0, bit 31 for reset irq, bit 23 for axi_halt_ack
irq */
#define VFE_IMASK_WHILE_STOPPING_0 0x80000000
-#define VFE_IMASK_WHILE_STOPPING_1 0x00000100
+#define VFE_IMASK_WHILE_STOPPING_1 0xF0000000
/* For ABF bit 4 is set to zero and other's 1 */
#define ABF_MASK 0xFFFFFFF7
@@ -118,9 +139,12 @@
#define CS_ENABLE_MASK (0x00000001<<10)
#define CLF_ENABLE_MASK (0x00000001<<12)
#define IHIST_ENABLE_MASK (0x00000001<<15)
+#define BHIST_ENABLE_MASK (0x00000001<<18)
#define RS_CS_ENABLE_MASK (RS_ENABLE_MASK|CS_ENABLE_MASK)
#define STATS_ENABLE_MASK 0x000487E0 /* bit 18,15,10,9,8,7,6,5*/
+#define STATS_BHIST_ENABLE_MASK (0x00000001<<1)
+
#define VFE_DMI_CFG_DEFAULT 0x00000100
#define HFR_MODE_OFF 1
@@ -173,11 +197,11 @@
#define V40_OUT_CLAMP_OFF 0x00000874
#define V40_OUT_CLAMP_LEN 16
-#define V40_OPERATION_CFG_LEN 44
+#define V40_OPERATION_CFG_LEN 32
-#define V40_AXI_OUT_OFF 0x0000004C
-#define V40_AXI_OUT_LEN 412
-#define V40_AXI_CH_INF_LEN 32
+#define V40_AXI_BUS_CMD_OFF 0x0000004C
+#define V40_AXI_BUS_CFG_LEN 284
+#define V40_AXI_OUT_LEN 344
#define V40_AXI_CFG_LEN 71
#define V40_FOV_ENC_OFF 0x00000854
@@ -213,7 +237,6 @@
#define V40_MESH_ROLL_OFF_CFG_LEN 36
#define V40_MESH_ROLL_OFF_TABLE_SIZE 130
-
#define V40_COLOR_COR_OFF 0x000005D0
#define V40_COLOR_COR_LEN 52
@@ -309,29 +332,6 @@
#define VFE40_LINEARIZATON_TABLE_LENGTH 36
-#define VFE_WM_CFG_BASE 0x0070
-#define VFE_WM_CFG_LEN 0x0024
-
-#define vfe40_get_ch_ping_addr(base, chn) \
- (msm_camera_io_r((base) + VFE_WM_CFG_BASE + VFE_WM_CFG_LEN * (chn)))
-#define vfe40_get_ch_pong_addr(base, chn) \
- (msm_camera_io_r((base) + VFE_WM_CFG_BASE + VFE_WM_CFG_LEN * (chn) + 4))
-#define vfe40_get_ch_addr(ping_pong, base, chn) \
- ((((ping_pong) & (1 << (chn))) == 0) ? \
- (vfe40_get_ch_pong_addr((base), chn)) : \
- (vfe40_get_ch_ping_addr((base), chn)))
-
-#define vfe40_put_ch_ping_addr(base, chn, addr) \
- (msm_camera_io_w((addr), \
- (base) + VFE_WM_CFG_BASE + VFE_WM_CFG_LEN * (chn)))
-#define vfe40_put_ch_pong_addr(base, chn, addr) \
- (msm_camera_io_w((addr), \
- (base) + VFE_WM_CFG_BASE + VFE_WM_CFG_LEN * (chn) + 4))
-#define vfe40_put_ch_addr(ping_pong, base, chn, addr) \
- (((ping_pong) & (1 << (chn))) == 0 ? \
- vfe40_put_ch_pong_addr((base), (chn), (addr)) : \
- vfe40_put_ch_ping_addr((base), (chn), (addr)))
-
struct vfe_cmd_hw_version {
uint32_t minorVersion;
uint32_t majorVersion;
@@ -704,7 +704,7 @@
struct vfe40_output_ch {
struct list_head free_buf_queue;
spinlock_t free_buf_lock;
- uint16_t image_mode;
+ uint32_t inst_handle;
int8_t ch0;
int8_t ch1;
int8_t ch2;
@@ -719,7 +719,8 @@
#define VFE40_IMASK_ERROR_ONLY_0 0x0
/* when normal case, don't want to block error status. */
/* bit 0-21 are error irq bits */
-#define VFE40_IMASK_ERROR_ONLY_1 0x005FFFFF
+#define VFE40_IMASK_COMMON_ERROR_ONLY_1 0x0000FE00
+#define VFE40_IMASK_VFE_ERROR_ONLY_1 0x00FF01FF
#define VFE40_IMASK_CAMIF_ERROR (0x00000001<<0)
#define VFE40_IMASK_BHIST_OVWR (0x00000001<<1)
#define VFE40_IMASK_STATS_CS_OVWR (0x00000001<<2)
@@ -728,21 +729,21 @@
#define VFE40_IMASK_REALIGN_BUF_CB_OVFL (0x00000001<<5)
#define VFE40_IMASK_REALIGN_BUF_CR_OVFL (0x00000001<<6)
#define VFE40_IMASK_VIOLATION (0x00000001<<7)
-#define VFE40_IMASK_IMG_MAST_0_BUS_OVFL (0x00000001<<8)
-#define VFE40_IMASK_IMG_MAST_1_BUS_OVFL (0x00000001<<9)
-#define VFE40_IMASK_IMG_MAST_2_BUS_OVFL (0x00000001<<10)
-#define VFE40_IMASK_IMG_MAST_3_BUS_OVFL (0x00000001<<11)
-#define VFE40_IMASK_IMG_MAST_4_BUS_OVFL (0x00000001<<12)
-#define VFE40_IMASK_IMG_MAST_5_BUS_OVFL (0x00000001<<13)
-#define VFE40_IMASK_IMG_MAST_6_BUS_OVFL (0x00000001<<14)
-#define VFE40_IMASK_STATS_AE_BG_BUS_OVFL (0x00000001<<15)
-#define VFE40_IMASK_STATS_AF_BF_BUS_OVFL (0x00000001<<16)
-#define VFE40_IMASK_STATS_AWB_BUS_OVFL (0x00000001<<17)
-#define VFE40_IMASK_STATS_RS_BUS_OVFL (0x00000001<<18)
-#define VFE40_IMASK_STATS_CS_BUS_OVFL (0x00000001<<19)
-#define VFE40_IMASK_STATS_IHIST_BUS_OVFL (0x00000001<<20)
-#define VFE40_IMASK_STATS_SKIN_BHIST_BUS_OVFL (0x00000001<<21)
-#define VFE40_IMASK_AXI_ERROR (0x00000001<<22)
+#define VFE40_IMASK_IMG_MAST_0_BUS_OVFL (0x00000001<<9)
+#define VFE40_IMASK_IMG_MAST_1_BUS_OVFL (0x00000001<<10)
+#define VFE40_IMASK_IMG_MAST_2_BUS_OVFL (0x00000001<<11)
+#define VFE40_IMASK_IMG_MAST_3_BUS_OVFL (0x00000001<<12)
+#define VFE40_IMASK_IMG_MAST_4_BUS_OVFL (0x00000001<<13)
+#define VFE40_IMASK_IMG_MAST_5_BUS_OVFL (0x00000001<<14)
+#define VFE40_IMASK_IMG_MAST_6_BUS_OVFL (0x00000001<<15)
+#define VFE40_IMASK_STATS_BE_BUS_OVFL (0x00000001<<16)
+#define VFE40_IMASK_STATS_BG_BUS_OVFL (0x00000001<<17)
+#define VFE40_IMASK_STATS_BF_BUS_OVFL (0x00000001<<18)
+#define VFE40_IMASK_STATS_AWB_BUS_OVFL (0x00000001<<19)
+#define VFE40_IMASK_STATS_RS_BUS_OVFL (0x00000001<<10)
+#define VFE40_IMASK_STATS_CS_BUS_OVFL (0x00000001<<21)
+#define VFE40_IMASK_STATS_IHIST_BUS_OVFL (0x00000001<<22)
+#define VFE40_IMASK_STATS_SKIN_BHIST_BUS_OVFL (0x00000001<<23)
#define VFE_COM_STATUS 0x000FE000
@@ -751,7 +752,8 @@
struct vfe40_output_ch out0; /* preview and thumbnail */
struct vfe40_output_ch out1; /* snapshot */
- struct vfe40_output_ch out2; /* video */
+ struct vfe40_output_ch out2; /* rdi0 */
+ struct vfe40_output_ch out3; /* rdi01 */
};
struct vfe40_frame_extra {
@@ -769,9 +771,7 @@
uint32_t frameCounter;
};
-#define VFE_CLEAR_ALL_IRQS 0xffffffff
-
-#define VFE_HW_VERSION 0x00000000
+#define VFE_HW_VERSION 0x00000000
#define VFE_GLOBAL_RESET 0x0000000C
#define VFE_MODULE_RESET 0x00000010
#define VFE_CGC_OVERRIDE 0x00000014
@@ -786,32 +786,67 @@
#define VFE_IRQ_STATUS_1 0x0000003C
#define VFE_IRQ_COMP_MASK 0x00000040
#define VFE_BUS_CMD 0x0000004C
-#define VFE_BUS_PING_PONG_STATUS 0x00000180
-#define VFE_AXI_CMD 0x000001D8
-#define VFE_AXI_STATUS 0x000002C0
-#define VFE_BUS_STATS_PING_PONG_BASE 0x000000F4
+#define VFE_BUS_PING_PONG_STATUS 0x00000268
+#define VFE_AXI_CMD 0x000002C0
+#define VFE_AXI_STATUS 0x000002E4
+#define VFE_BUS_STATS_PING_PONG_BASE 0x00000168
-#define VFE_BUS_STATS_AEC_WR_PING_ADDR 0x000000F4
-#define VFE_BUS_STATS_AEC_WR_PONG_ADDR 0x000000F8
-#define VFE_BUS_STATS_AEC_UB_CFG 0x000000FC
-#define VFE_BUS_STATS_AF_WR_PING_ADDR 0x00000100
-#define VFE_BUS_STATS_AF_WR_PONG_ADDR 0x00000104
-#define VFE_BUS_STATS_AF_UB_CFG 0x00000108
-#define VFE_BUS_STATS_AWB_WR_PING_ADDR 0x0000010C
-#define VFE_BUS_STATS_AWB_WR_PONG_ADDR 0x00000110
-#define VFE_BUS_STATS_AWB_UB_CFG 0x00000114
-#define VFE_BUS_STATS_RS_WR_PING_ADDR 0x00000118
-#define VFE_BUS_STATS_RS_WR_PONG_ADDR 0x0000011C
-#define VFE_BUS_STATS_RS_UB_CFG 0x00000120
-#define VFE_BUS_STATS_CS_WR_PING_ADDR 0x00000124
-#define VFE_BUS_STATS_CS_WR_PONG_ADDR 0x00000128
-#define VFE_BUS_STATS_CS_UB_CFG 0x0000012C
-#define VFE_BUS_STATS_HIST_WR_PING_ADDR 0x00000130
-#define VFE_BUS_STATS_HIST_WR_PONG_ADDR 0x00000134
-#define VFE_BUS_STATS_HIST_UB_CFG 0x00000138
-#define VFE_BUS_STATS_SKIN_WR_PING_ADDR 0x0000013C
-#define VFE_BUS_STATS_SKIN_WR_PONG_ADDR 0x00000140
-#define VFE_BUS_STATS_SKIN_UB_CFG 0x00000144
+#define VFE_BUS_STATS_BE_WR_PING_ADDR 0x00000168
+#define VFE_BUS_STATS_BE_WR_PONG_ADDR 0x0000016C
+#define VFE_BUS_STATS_BE_WR_ADDR_CFG 0x00000170
+#define VFE_BUS_STATS_BE_UB_CFG 0x00000174
+#define VFE_BUS_STATS_BE_WR_FRAMEDROP_PATTERN 0x00000178
+#define VFE_BUS_STATS_BE_WR_IRQ_SUBSAMPLE_PATTERN 0x0000017C
+
+#define VFE_BUS_STATS_BG_WR_PING_ADDR 0x00000180
+#define VFE_BUS_STATS_BG_WR_PONG_ADDR 0x00000184
+#define VFE_BUS_STATS_BG_WR_ADDR_CFG 0x00000188
+#define VFE_BUS_STATS_BG_WR_UB_CFG 0x0000018C
+#define VFE_BUS_STATS_BG_WR_FRAMEDROP_PATTERN 0x00000190
+#define VFE_BUS_STATS_BG_WR_IRQ_SUBSAMPLE_PATTERN 0x00000194
+
+#define VFE_BUS_STATS_BF_WR_PING_ADDR 0x00000198
+#define VFE_BUS_STATS_BF_WR_PONG_ADDR 0x0000019C
+#define VFE_BUS_STATS_BF_WR_ADDR_CFG 0x000001A0
+#define VFE_BUS_STATS_BF_WR_UB_CFG 0x000001A4
+#define VFE_BUS_STATS_BF_WR_FRAMEDROP_PATTERN 0x000001A8
+#define VFE_BUS_STATS_BF_WR_IRQ_SUBSAMPLE_PATTERN 0x000001AC
+
+#define VFE_BUS_STATS_AWB_WR_PING_ADDR 0x000001B0
+#define VFE_BUS_STATS_AWB_WR_PONG_ADDR 0x000001B4
+#define VFE_BUS_STATS_AWB_WR_ADDR_CFG 0x000001B8
+#define VFE_BUS_STATS_AWB_WR_UB_CFG 0x000001BC
+#define VFE_BUS_STATS_AWB_WR_FRAMEDROP_PATTERN 0x000001C0
+#define VFE_BUS_STATS_AWB_WR_IRQ_SUBSAMPLE_PATTERN 0x000001C4
+
+#define VFE_BUS_STATS_RS_WR_PING_ADDR 0x000001C8
+#define VFE_BUS_STATS_RS_WR_PONG_ADDR 0x000001CC
+#define VFE_BUS_STATS_RS_WR_ADDR_CFG 0x000001D0
+#define VFE_BUS_STATS_RS_WR_UB_CFG 0x000001D4
+#define VFE_BUS_STATS_RS_WR_FRAMEDROP_PATTERN 0x000001D8
+#define VFE_BUS_STATS_RS_WR_IRQ_SUBSAMPLE_PATTERN 0x000001DC
+
+#define VFE_BUS_STATS_CS_WR_PING_ADDR 0x000001E0
+#define VFE_BUS_STATS_CS_WR_PONG_ADDR 0x000001E4
+#define VFE_BUS_STATS_CS_WR_ADDR_CFG 0x000001E8
+#define VFE_BUS_STATS_CS_WR_UB_CFG 0x000001EC
+#define VFE_BUS_STATS_CS_WR_FRAMEDROP_PATTERN 0x000001F0
+#define VFE_BUS_STATS_CS_WR_IRQ_SUBSAMPLE_PATTERN 0x000001F4
+
+#define VFE_BUS_STATS_HIST_WR_PING_ADDR 0x000001F8
+#define VFE_BUS_STATS_HIST_WR_PONG_ADDR 0x000001FC
+#define VFE_BUS_STATS_HIST_WR_ADDR_CFG 0x00000200
+#define VFE_BUS_STATS_HIST_WR_UB_CFG 0x00000204
+#define VFE_BUS_STATS_HIST_WR_FRAMEDROP_PATTERN 0x00000208
+#define VFE_BUS_STATS_HIST_WR_IRQ_SUBSAMPLE_PATTERN 0x0000020C
+
+
+#define VFE_BUS_STATS_SKIN_WR_PING_ADDR 0x00000210
+#define VFE_BUS_STATS_SKIN_WR_PONG_ADDR 0x00000214
+#define VFE_BUS_STATS_SKIN_WR_ADDR_CFG 0x00000218
+#define VFE_BUS_STATS_SKIN_WR_UB_CFG 0x0000021C
+#define VFE_BUS_STATS_SKIN_WR_FRAMEDROP_PATTERN 0x00000220
+#define VFE_BUS_STATS_SKIN_WR_IRQ_SUBSAMPLE_PATTERN 0x00000224
#define VFE_0_BUS_BDG_QOS_CFG_0 0x000002C4
#define VFE_0_BUS_BDG_QOS_CFG_1 0x000002C8
@@ -839,13 +874,14 @@
#define VFE_STATS_AWB_SGW_CFG 0x000008CC
#define VFE_DMI_CFG 0x00000910
#define VFE_DMI_ADDR 0x00000914
+#define VFE_DMI_DATA_HI 0x00000918
#define VFE_DMI_DATA_LO 0x0000091C
#define VFE_BUS_IO_FORMAT_CFG 0x00000054
#define VFE_RDI0_CFG 0x000002E8
#define VFE_RDI1_CFG 0x000002EC
#define VFE_RDI2_CFG 0x000002F0
-#define VFE_VIOLATION_STATUS 0x000007B4
+#define VFE_VIOLATION_STATUS 0x00000048
#define VFE40_DMI_DATA_HI 0x00000918
#define VFE40_DMI_DATA_LO 0x0000091C
@@ -860,6 +896,25 @@
#define VFE40_OUTPUT_MODE_PRIMARY_ALL_CHNLS BIT(7)
#define VFE40_OUTPUT_MODE_SECONDARY BIT(8)
#define VFE40_OUTPUT_MODE_SECONDARY_ALL_CHNLS BIT(9)
+#define VFE40_OUTPUT_MODE_TERTIARY1 BIT(10)
+#define VFE40_OUTPUT_MODE_TERTIARY2 BIT(11)
+
+#define VFE40_VBIF_CLKON 0x4
+#define VFE40_VBIF_IN_RD_LIM_CONF0 0xB0
+#define VFE40_VBIF_IN_RD_LIM_CONF1 0xB4
+#define VFE40_VBIF_IN_RD_LIM_CONF2 0xB8
+#define VFE40_VBIF_IN_WR_LIM_CONF0 0xC0
+#define VFE40_VBIF_IN_WR_LIM_CONF1 0xC4
+#define VFE40_VBIF_IN_WR_LIM_CONF2 0xC8
+#define VFE40_VBIF_OUT_RD_LIM_CONF0 0xD0
+#define VFE40_VBIF_OUT_WR_LIM_CONF0 0xD4
+#define VFE40_VBIF_DDR_OUT_MAX_BURST 0xD8
+#define VFE40_VBIF_ARB_CTL 0xF0
+#define VFE40_VBIF_DDR_ARB_CONF0 0xF4
+#define VFE40_VBIF_DDR_ARB_CONF1 0xF8
+#define VFE40_VBIF_ROUND_ROBIN_QOS_ARB 0x124
+#define VFE40_VBIF_OUT_AXI_AOOO_EN 0x178
+#define VFE40_VBIF_OUT_AXI_AOOO 0x17C
struct vfe_stats_control {
uint32_t droppedStatsFrameCount;
@@ -870,26 +925,50 @@
struct vfe_share_ctrl_t {
void __iomem *vfebase;
+ void __iomem *vfe_vbif_base;
uint32_t register_total;
atomic_t vstate;
+ atomic_t handle_common_irq;
uint32_t vfeFrameId;
+ uint32_t rdi0FrameId;
+ uint32_t rdi1FrameId;
+ uint32_t rdi2FrameId;
uint32_t stats_comp;
+ spinlock_t sd_notify_lock;
spinlock_t stop_flag_lock;
int8_t stop_ack_pending;
enum vfe_output_state liveshot_state;
uint32_t vfe_capture_count;
- uint16_t operation_mode; /* streaming or snapshot */
+ uint32_t operation_mode; /* streaming or snapshot */
+ uint32_t current_mode;
struct vfe40_output_path outpath;
- uint32_t ref_count;
- spinlock_t sd_notify_lock;
- uint32_t vfe_clk_rate;
+ uint16_t port_info;
+ uint8_t stop_immediately;
+ uint8_t sync_abort;
+ uint16_t cmd_type;
+ uint8_t vfe_reset_flag;
- atomic_t irq_cnt;
+ uint8_t axi_ref_cnt;
+ uint16_t comp_output_mode;
+
+ struct completion reset_complete;
+
+ spinlock_t update_ack_lock;
+ spinlock_t start_ack_lock;
+
struct axi_ctrl_t *axi_ctrl;
struct vfe40_ctrl_type *vfe40_ctrl;
+ int8_t start_ack_pending;
+ int8_t update_ack_pending;
+ enum vfe_output_state recording_state;
+
+ atomic_t pix0_update_ack_pending;
+ atomic_t rdi0_update_ack_pending;
+ atomic_t rdi1_update_ack_pending;
+ atomic_t rdi2_update_ack_pending;
};
struct axi_ctrl_t {
@@ -902,27 +981,25 @@
void *syncdata;
struct resource *vfemem;
+ struct resource *vfe_vbif_mem;
struct resource *vfeio;
+ struct resource *vfe_vbif_io;
struct regulator *fs_vfe;
- struct clk *vfe_clk[3];
+ struct clk *vfe_clk[7];
struct tasklet_struct vfe40_tasklet;
struct vfe_share_ctrl_t *share_ctrl;
+ struct device *iommu_ctx;
+ uint32_t bus_perf_client;
+ uint32_t use_irq_router;
};
struct vfe40_ctrl_type {
- uint32_t vfeImaskCompositePacked;
-
- spinlock_t update_ack_lock;
spinlock_t state_lock;
- spinlock_t io_lock;
spinlock_t stats_bufq_lock;
uint32_t extlen;
void *extdata;
- int8_t start_ack_pending;
- int8_t reset_ack_pending;
- int8_t update_ack_pending;
- enum vfe_output_state recording_state;
+ int8_t vfe_sof_count_enable;
int8_t update_linear;
int8_t update_rolloff;
int8_t update_la;
@@ -934,18 +1011,14 @@
uint32_t sync_timer_state;
uint32_t sync_timer_number;
- uint32_t output1Pattern;
- uint32_t output1Period;
- uint32_t output2Pattern;
- uint32_t output2Period;
- uint32_t vfeFrameSkipCount;
- uint32_t vfeFrameSkipPeriod;
- struct vfe_stats_control afStatsControl;
+ struct msm_ver_num_info ver_num;
+ struct vfe_stats_control afbfStatsControl;
struct vfe_stats_control awbStatsControl;
- struct vfe_stats_control aecStatsControl;
+ struct vfe_stats_control aecbgStatsControl;
struct vfe_stats_control ihistStatsControl;
struct vfe_stats_control rsStatsControl;
struct vfe_stats_control csStatsControl;
+ struct vfe_stats_control bhistStatsControl;
/* v4l2 subdev */
struct v4l2_subdev subdev;
@@ -956,6 +1029,8 @@
uint32_t snapshot_frame_cnt;
struct msm_stats_bufq_ctrl stats_ctrl;
struct msm_stats_ops stats_ops;
+
+ uint32_t simultaneous_sof_stat;
};
#define statsAeNum 0
@@ -976,227 +1051,4 @@
uint32_t statsBuf[VFE_STATS_BUFFER_COUNT];
};
-void vfe40_subdev_notify(int id, int path, int image_mode,
- struct v4l2_subdev *sd, struct vfe_share_ctrl_t *share_ctrl);
-struct vfe40_output_ch *vfe40_get_ch(
- int path, struct vfe_share_ctrl_t *share_ctrl);
-void vfe40_send_isp_msg(struct v4l2_subdev *sd,
- uint32_t vfeFrameId, uint32_t isp_msg_id);
-void vfe40_axi_probe(struct axi_ctrl_t *axi_ctrl);
-
-static const uint32_t vfe40_AXI_WM_CFG[] = {
- 0x0000006C,
- 0x00000090,
- 0x000000B4,
- 0x000000D8,
- 0x000000FC,
- 0x00000120,
- 0x00000144,
-};
-
-static struct vfe40_cmd_type vfe40_cmd[] = {
-/*0*/
- {VFE_CMD_DUMMY_0},
- {VFE_CMD_SET_CLK},
- {VFE_CMD_RESET},
- {VFE_CMD_START},
- {VFE_CMD_TEST_GEN_START},
-/*5*/
- {VFE_CMD_OPERATION_CFG, V40_OPERATION_CFG_LEN},
- {VFE_CMD_AXI_OUT_CFG, V40_AXI_OUT_LEN, V40_AXI_OUT_OFF, 0xFF},
- {VFE_CMD_CAMIF_CFG, V40_CAMIF_LEN, V40_CAMIF_OFF, 0xFF},
- {VFE_CMD_AXI_INPUT_CFG},
- {VFE_CMD_BLACK_LEVEL_CFG},
-/*10*/
- {VFE_CMD_MESH_ROLL_OFF_CFG},
- {VFE_CMD_DEMUX_CFG, V40_DEMUX_LEN, V40_DEMUX_OFF, 0xFF},
- {VFE_CMD_FOV_CFG},
- {VFE_CMD_MAIN_SCALER_CFG},
- {VFE_CMD_WB_CFG, V40_WB_LEN, V40_WB_OFF, 0xFF},
-/*15*/
- {VFE_CMD_COLOR_COR_CFG, V40_COLOR_COR_LEN, V40_COLOR_COR_OFF, 0xFF},
- {VFE_CMD_RGB_G_CFG, V40_RGB_G_LEN, V40_RGB_G_OFF, 0xFF},
- {VFE_CMD_LA_CFG, V40_LA_LEN, V40_LA_OFF, 0xFF },
- {VFE_CMD_CHROMA_EN_CFG, V40_CHROMA_EN_LEN, V40_CHROMA_EN_OFF, 0xFF},
- {VFE_CMD_CHROMA_SUP_CFG, V40_CHROMA_SUP_LEN, V40_CHROMA_SUP_OFF, 0xFF},
-/*20*/
- {VFE_CMD_MCE_CFG, V40_MCE_LEN, V40_MCE_OFF, 0xFF},
- {VFE_CMD_SK_ENHAN_CFG, V40_SCE_LEN, V40_SCE_OFF, 0xFF},
- {VFE_CMD_ASF_CFG, V40_ASF_LEN, V40_ASF_OFF, 0xFF},
- {VFE_CMD_S2Y_CFG},
- {VFE_CMD_S2CbCr_CFG},
-/*25*/
- {VFE_CMD_CHROMA_SUBS_CFG},
- {VFE_CMD_OUT_CLAMP_CFG, V40_OUT_CLAMP_LEN, V40_OUT_CLAMP_OFF, 0xFF},
- {VFE_CMD_FRAME_SKIP_CFG},
- {VFE_CMD_DUMMY_1},
- {VFE_CMD_DUMMY_2},
-/*30*/
- {VFE_CMD_DUMMY_3},
- {VFE_CMD_UPDATE},
- {VFE_CMD_BL_LVL_UPDATE},
- {VFE_CMD_DEMUX_UPDATE, V40_DEMUX_LEN, V40_DEMUX_OFF, 0xFF},
- {VFE_CMD_FOV_UPDATE},
-/*35*/
- {VFE_CMD_MAIN_SCALER_UPDATE},
- {VFE_CMD_WB_UPDATE, V40_WB_LEN, V40_WB_OFF, 0xFF},
- {VFE_CMD_COLOR_COR_UPDATE, V40_COLOR_COR_LEN, V40_COLOR_COR_OFF, 0xFF},
- {VFE_CMD_RGB_G_UPDATE, V40_RGB_G_LEN, V40_CHROMA_EN_OFF, 0xFF},
- {VFE_CMD_LA_UPDATE, V40_LA_LEN, V40_LA_OFF, 0xFF },
-/*40*/
- {VFE_CMD_CHROMA_EN_UPDATE, V40_CHROMA_EN_LEN, V40_CHROMA_EN_OFF, 0xFF},
- {VFE_CMD_CHROMA_SUP_UPDATE, V40_CHROMA_SUP_LEN,
- V40_CHROMA_SUP_OFF, 0xFF},
- {VFE_CMD_MCE_UPDATE, V40_MCE_LEN, V40_MCE_OFF, 0xFF},
- {VFE_CMD_SK_ENHAN_UPDATE, V40_SCE_LEN, V40_SCE_OFF, 0xFF},
- {VFE_CMD_S2CbCr_UPDATE},
-/*45*/
- {VFE_CMD_S2Y_UPDATE},
- {VFE_CMD_ASF_UPDATE, V40_ASF_UPDATE_LEN, V40_ASF_OFF, 0xFF},
- {VFE_CMD_FRAME_SKIP_UPDATE},
- {VFE_CMD_CAMIF_FRAME_UPDATE},
- {VFE_CMD_STATS_AF_UPDATE},
-/*50*/
- {VFE_CMD_STATS_AE_UPDATE},
- {VFE_CMD_STATS_AWB_UPDATE, V40_STATS_AWB_LEN, V40_STATS_AWB_OFF},
- {VFE_CMD_STATS_RS_UPDATE, V40_STATS_RS_LEN, V40_STATS_RS_OFF},
- {VFE_CMD_STATS_CS_UPDATE, V40_STATS_CS_LEN, V40_STATS_CS_OFF},
- {VFE_CMD_STATS_SKIN_UPDATE},
-/*55*/
- {VFE_CMD_STATS_IHIST_UPDATE, V40_STATS_IHIST_LEN, V40_STATS_IHIST_OFF},
- {VFE_CMD_DUMMY_4},
- {VFE_CMD_EPOCH1_ACK},
- {VFE_CMD_EPOCH2_ACK},
- {VFE_CMD_START_RECORDING},
-/*60*/
- {VFE_CMD_STOP_RECORDING},
- {VFE_CMD_DUMMY_5},
- {VFE_CMD_DUMMY_6},
- {VFE_CMD_CAPTURE, V40_CAPTURE_LEN, 0xFF},
- {VFE_CMD_DUMMY_7},
-/*65*/
- {VFE_CMD_STOP},
- {VFE_CMD_GET_HW_VERSION, V40_GET_HW_VERSION_LEN,
- V40_GET_HW_VERSION_OFF},
- {VFE_CMD_GET_FRAME_SKIP_COUNTS},
- {VFE_CMD_OUTPUT1_BUFFER_ENQ},
- {VFE_CMD_OUTPUT2_BUFFER_ENQ},
-/*70*/
- {VFE_CMD_OUTPUT3_BUFFER_ENQ},
- {VFE_CMD_JPEG_OUT_BUF_ENQ},
- {VFE_CMD_RAW_OUT_BUF_ENQ},
- {VFE_CMD_RAW_IN_BUF_ENQ},
- {VFE_CMD_STATS_AF_ENQ},
-/*75*/
- {VFE_CMD_STATS_AE_ENQ},
- {VFE_CMD_STATS_AWB_ENQ},
- {VFE_CMD_STATS_RS_ENQ},
- {VFE_CMD_STATS_CS_ENQ},
- {VFE_CMD_STATS_SKIN_ENQ},
-/*80*/
- {VFE_CMD_STATS_IHIST_ENQ},
- {VFE_CMD_DUMMY_8},
- {VFE_CMD_JPEG_ENC_CFG},
- {VFE_CMD_DUMMY_9},
- {VFE_CMD_STATS_AF_START},
-/*85*/
- {VFE_CMD_STATS_AF_STOP},
- {VFE_CMD_STATS_AE_START},
- {VFE_CMD_STATS_AE_STOP},
- {VFE_CMD_STATS_AWB_START, V40_STATS_AWB_LEN, V40_STATS_AWB_OFF},
- {VFE_CMD_STATS_AWB_STOP},
-/*90*/
- {VFE_CMD_STATS_RS_START, V40_STATS_RS_LEN, V40_STATS_RS_OFF},
- {VFE_CMD_STATS_RS_STOP},
- {VFE_CMD_STATS_CS_START, V40_STATS_CS_LEN, V40_STATS_CS_OFF},
- {VFE_CMD_STATS_CS_STOP},
- {VFE_CMD_STATS_SKIN_START},
-/*95*/
- {VFE_CMD_STATS_SKIN_STOP},
- {VFE_CMD_STATS_IHIST_START, V40_STATS_IHIST_LEN, V40_STATS_IHIST_OFF},
- {VFE_CMD_STATS_IHIST_STOP},
- {VFE_CMD_DUMMY_10},
- {VFE_CMD_SYNC_TIMER_SETTING, V40_SYNC_TIMER_LEN, V40_SYNC_TIMER_OFF},
-/*100*/
- {VFE_CMD_ASYNC_TIMER_SETTING, V40_ASYNC_TIMER_LEN, V40_ASYNC_TIMER_OFF},
- {VFE_CMD_LIVESHOT},
- {VFE_CMD_LA_SETUP},
- {VFE_CMD_LINEARIZATION_CFG, V40_LINEARIZATION_LEN1,
- V40_LINEARIZATION_OFF1},
- {VFE_CMD_DEMOSAICV3},
-/*105*/
- {VFE_CMD_DEMOSAICV3_ABCC_CFG},
- {VFE_CMD_DEMOSAICV3_DBCC_CFG, V40_DEMOSAICV3_DBCC_LEN,
- V40_DEMOSAICV3_DBCC_OFF},
- {VFE_CMD_DEMOSAICV3_DBPC_CFG},
- {VFE_CMD_DEMOSAICV3_ABF_CFG, V40_DEMOSAICV3_ABF_LEN,
- V40_DEMOSAICV3_ABF_OFF},
- {VFE_CMD_DEMOSAICV3_ABCC_UPDATE},
-/*110*/
- {VFE_CMD_DEMOSAICV3_DBCC_UPDATE, V40_DEMOSAICV3_DBCC_LEN,
- V40_DEMOSAICV3_DBCC_OFF},
- {VFE_CMD_DEMOSAICV3_DBPC_UPDATE},
- {VFE_CMD_XBAR_CFG},
- {VFE_CMD_MODULE_CFG, V40_MODULE_CFG_LEN, V40_MODULE_CFG_OFF},
- {VFE_CMD_ZSL},
-/*115*/
- {VFE_CMD_LINEARIZATION_UPDATE, V40_LINEARIZATION_LEN1,
- V40_LINEARIZATION_OFF1},
- {VFE_CMD_DEMOSAICV3_ABF_UPDATE, V40_DEMOSAICV3_ABF_LEN,
- V40_DEMOSAICV3_ABF_OFF},
- {VFE_CMD_CLF_CFG, V40_CLF_CFG_LEN, V40_CLF_CFG_OFF},
- {VFE_CMD_CLF_LUMA_UPDATE, V40_CLF_LUMA_UPDATE_LEN,
- V40_CLF_LUMA_UPDATE_OFF},
- {VFE_CMD_CLF_CHROMA_UPDATE, V40_CLF_CHROMA_UPDATE_LEN,
- V40_CLF_CHROMA_UPDATE_OFF},
-/*120*/
- {VFE_CMD_PCA_ROLL_OFF_CFG},
- {VFE_CMD_PCA_ROLL_OFF_UPDATE},
- {VFE_CMD_GET_REG_DUMP},
- {VFE_CMD_GET_LINEARIZATON_TABLE},
- {VFE_CMD_GET_MESH_ROLLOFF_TABLE},
-/*125*/
- {VFE_CMD_GET_PCA_ROLLOFF_TABLE},
- {VFE_CMD_GET_RGB_G_TABLE},
- {VFE_CMD_GET_LA_TABLE},
- {VFE_CMD_DEMOSAICV3_UPDATE},
- {VFE_CMD_ACTIVE_REGION_CFG},
-/*130*/
- {VFE_CMD_COLOR_PROCESSING_CONFIG},
- {VFE_CMD_STATS_WB_AEC_CONFIG},
- {VFE_CMD_STATS_WB_AEC_UPDATE},
- {VFE_CMD_Y_GAMMA_CONFIG},
- {VFE_CMD_SCALE_OUTPUT1_CONFIG},
-/*135*/
- {VFE_CMD_SCALE_OUTPUT2_CONFIG},
- {VFE_CMD_CAPTURE_RAW},
- {VFE_CMD_STOP_LIVESHOT},
- {VFE_CMD_RECONFIG_VFE},
- {VFE_CMD_STATS_REQBUF},
-/*140*/
- {VFE_CMD_STATS_ENQUEUEBUF},
- {VFE_CMD_STATS_FLUSH_BUFQ},
- {VFE_CMD_FOV_ENC_CFG, V40_FOV_ENC_LEN, V40_FOV_ENC_OFF, 0xFF},
- {VFE_CMD_FOV_VIEW_CFG, V40_FOV_VIEW_LEN, V40_FOV_VIEW_OFF, 0xFF},
- {VFE_CMD_FOV_ENC_UPDATE, V40_FOV_ENC_LEN, V40_FOV_ENC_OFF, 0xFF},
-/*145*/
- {VFE_CMD_FOV_VIEW_UPDATE, V40_FOV_VIEW_LEN, V40_FOV_VIEW_OFF, 0xFF},
- {VFE_CMD_SCALER_ENC_CFG, V40_SCALER_ENC_LEN, V40_SCALER_ENC_OFF, 0xFF},
- {VFE_CMD_SCALER_VIEW_CFG, V40_SCALER_VIEW_LEN,
- V40_SCALER_VIEW_OFF, 0xFF},
- {VFE_CMD_SCALER_ENC_UPDATE, V40_SCALER_ENC_LEN,
- V40_SCALER_ENC_OFF, 0xFF},
- {VFE_CMD_SCALER_VIEW_UPDATE, V40_SCALER_VIEW_LEN,
- V40_SCALER_VIEW_OFF, 0xFF},
-/*150*/
- {VFE_CMD_COLORXFORM_ENC_CFG, V40_COLORXFORM_ENC_CFG_LEN,
- V40_COLORXFORM_ENC_CFG_OFF, 0xFF},
- {VFE_CMD_COLORXFORM_VIEW_CFG, V40_COLORXFORM_VIEW_CFG_LEN,
- V40_COLORXFORM_VIEW_CFG_OFF},
- {VFE_CMD_COLORXFORM_ENC_UPDATE, V40_COLORXFORM_ENC_CFG_LEN,
- V40_COLORXFORM_ENC_CFG_OFF, 0xFF},
- {VFE_CMD_COLORXFORM_VIEW_UPDATE, V40_COLORXFORM_VIEW_CFG_LEN,
- V40_COLORXFORM_VIEW_CFG_OFF, 0xFF},
-};
-
#endif /* __MSM_VFE40_H__ */
diff --git a/drivers/media/video/msm/vfe/msm_vfe40_axi.c b/drivers/media/video/msm/vfe/msm_vfe40_axi.c
index 35d5207..41d1cdd 100644
--- a/drivers/media/video/msm/vfe/msm_vfe40_axi.c
+++ b/drivers/media/video/msm/vfe/msm_vfe40_axi.c
@@ -193,6 +193,16 @@
msm_camera_io_memcpy(axi_ctrl->share_ctrl->vfebase +
vfe40_cmd[VFE_CMD_AXI_OUT_CFG].offset, axi_cfg,
vfe40_cmd[VFE_CMD_AXI_OUT_CFG].length - V40_AXI_CH_INF_LEN);
+ msm_camera_io_w(*ch_info++,
+ axi_ctrl->share_ctrl->vfebase + VFE_RDI0_CFG);
+ if (msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+ V40_GET_HW_VERSION_OFF) ==
+ VFE40_HW_NUMBER) {
+ msm_camera_io_w(*ch_info++,
+ axi_ctrl->share_ctrl->vfebase + VFE_RDI1_CFG);
+ msm_camera_io_w(*ch_info++,
+ axi_ctrl->share_ctrl->vfebase + VFE_RDI2_CFG);
+ }
return 0;
}
@@ -331,6 +341,8 @@
case CMD_AXI_STOP:
axi_stop(axi_ctrl);
break;
+ case CMD_AXI_RESET:
+ break;
default:
pr_err("%s Unsupported AXI configuration %x ", __func__,
cfgcmd.cmd_type);
diff --git a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
index 460eb07..15c38af 100644
--- a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
@@ -360,7 +360,7 @@
rc = vfe2x_ctrl->stats_ops.dqbuf(vfe2x_ctrl->stats_ops.stats_ctrl,
stats_type, &buf);
if (rc < 0) {
- pr_err("%s: dq stats buf (type = %d) err = %d",
+ CDBG("%s: dq stats buf (type = %d) err = %d",
__func__, stats_type, rc);
return 0;
}
@@ -395,7 +395,7 @@
stats_buf = &bufq->bufs[i];
rc = vfe2x_ctrl->stats_ops.enqueue_buf(
vfe2x_ctrl->stats_ops.stats_ctrl,
- &(stats_buf->info), NULL);
+ &(stats_buf->info), NULL, -1);
if (rc < 0) {
pr_err("%s: dq stats buf (type = %d) err = %d",
__func__, stats_type, rc);
@@ -414,7 +414,7 @@
rc = vfe2x_ctrl->stats_ops.buf_unprepare(
vfe2x_ctrl->stats_ops.stats_ctrl,
req_buf->stats_type, i,
- vfe2x_ctrl->stats_ops.client);
+ vfe2x_ctrl->stats_ops.client, -1);
if (rc < 0) {
pr_err("%s: unreg stats buf (type = %d) err = %d",
__func__, req_buf->stats_type, rc);
@@ -473,7 +473,7 @@
stats_buf->state == MSM_STATS_BUFFER_STATE_PREPARED) {
rc = vfe2x_ctrl->stats_ops.enqueue_buf(
&vfe2x_ctrl->stats_ctrl,
- info, vfe2x_ctrl->stats_ops.client);
+ info, vfe2x_ctrl->stats_ops.client, -1);
if (rc < 0) {
pr_err("%s: enqueue_buf (type = %d), index : %d, err = %d",
__func__, info->type, info->buf_idx, rc);
@@ -555,7 +555,7 @@
rc = vfe2x_ctrl->stats_ops.enqueue_buf(
&vfe2x_ctrl->stats_ctrl,
(struct msm_stats_buf_info *)cmd->value,
- vfe2x_ctrl->stats_ops.client);
+ vfe2x_ctrl->stats_ops.client, -1);
}
break;
case VFE_CMD_STATS_FLUSH_BUFQ: {
@@ -2352,7 +2352,7 @@
return 0;
}
-void msm_vpe_subdev_release(void)
+void msm_vpe_subdev_release(struct v4l2_subdev *sd)
{
return;
}
diff --git a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c
index 5fbcdb1..a813e09 100644
--- a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c
+++ b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c
@@ -182,7 +182,8 @@
#endif
static int msm_stats_buf_prepare(struct msm_stats_bufq_ctrl *stats_ctrl,
- struct msm_stats_buf_info *info, struct ion_client *client)
+ struct msm_stats_buf_info *info, struct ion_client *client,
+ int domain_num)
{
unsigned long paddr;
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -219,7 +220,7 @@
goto out1;
}
if (ion_map_iommu(client, stats_buf->handle,
- CAMERA_DOMAIN, GEN_POOL, SZ_4K,
+ domain_num, 0, SZ_4K,
0, &paddr, &len, UNCACHED, 0) < 0) {
rc = -EINVAL;
pr_err("%s: cannot map address", __func__);
@@ -257,7 +258,7 @@
return 0;
out3:
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- ion_unmap_iommu(client, stats_buf->handle, CAMERA_DOMAIN, GEN_POOL);
+ ion_unmap_iommu(client, stats_buf->handle, domain_num, 0);
#endif
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
out2:
@@ -270,7 +271,7 @@
}
static int msm_stats_buf_unprepare(struct msm_stats_bufq_ctrl *stats_ctrl,
enum msm_stats_enum_type stats_type, int buf_idx,
- struct ion_client *client)
+ struct ion_client *client, int domain_num)
{
int rc = 0;
struct msm_stats_bufq *bufq = NULL;
@@ -292,7 +293,7 @@
}
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
ion_unmap_iommu(client, stats_buf->handle,
- CAMERA_DOMAIN, GEN_POOL);
+ domain_num, 0);
ion_free(client, stats_buf->handle);
#else
put_pmem_file(stats_buf->file);
@@ -362,7 +363,7 @@
}
}
if (!(*pp_stats_buf)) {
- pr_err("%s: no free stats buf, type = %d",
+ D("%s: no free stats buf, type = %d",
__func__, stats_type);
rc = -1;
return rc;
@@ -472,12 +473,13 @@
return rc;
}
static int msm_stats_enqueue_buf(struct msm_stats_bufq_ctrl *stats_ctrl,
- struct msm_stats_buf_info *info, struct ion_client *client)
+ struct msm_stats_buf_info *info, struct ion_client *client,
+ int domain_num)
{
int rc = 0;
D("%s: stats type : %d, idx : %d\n", __func__,
info->type, info->buf_idx);
- rc = msm_stats_buf_prepare(stats_ctrl, info, client);
+ rc = msm_stats_buf_prepare(stats_ctrl, info, client, domain_num);
if (rc < 0) {
pr_err("%s: buf_prepare failed, rc = %d", __func__, rc);
return -EINVAL;
diff --git a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h
index 18fd425..bf3e70e 100644
--- a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h
+++ b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h
@@ -55,8 +55,8 @@
struct msm_stats_bufq_ctrl *stats_ctrl;
struct ion_client *client;
int (*enqueue_buf) (struct msm_stats_bufq_ctrl *stats_ctrl,
- struct msm_stats_buf_info *info,
- struct ion_client *client);
+ struct msm_stats_buf_info *info,
+ struct ion_client *client, int domain_num);
int (*qbuf) (struct msm_stats_bufq_ctrl *stats_ctrl,
enum msm_stats_enum_type stats_type,
int buf_idx);
@@ -69,10 +69,10 @@
int (*buf_unprepare) (struct msm_stats_bufq_ctrl *stats_ctrl,
enum msm_stats_enum_type stats_type,
int buf_idx,
- struct ion_client *client);
+ struct ion_client *client, int domain_num);
int (*buf_prepare) (struct msm_stats_bufq_ctrl *stats_ctrl,
- struct msm_stats_buf_info *info,
- struct ion_client *client);
+ struct msm_stats_buf_info *info,
+ struct ion_client *client, int domain_num);
int (*reqbuf) (struct msm_stats_bufq_ctrl *stats_ctrl,
struct msm_stats_reqbuf *reqbuf,
struct ion_client *client);
diff --git a/drivers/media/video/msm_vidc/msm_smem.c b/drivers/media/video/msm_vidc/msm_smem.c
index 76d8068..b7b12cb 100644
--- a/drivers/media/video/msm_vidc/msm_smem.c
+++ b/drivers/media/video/msm_vidc/msm_smem.c
@@ -26,7 +26,6 @@
unsigned long *buffer_size, unsigned long flags)
{
int rc;
-
if (!iova || !buffer_size || !hndl || !clnt) {
pr_err("Invalid params: %p, %p, %p, %p\n",
clnt, hndl, iova, buffer_size);
@@ -34,11 +33,10 @@
}
if (align < 4096)
align = 4096;
- flags |= UNCACHED;
pr_debug("\n In %s domain: %d, Partition: %d\n",
__func__, domain_num, partition_num);
rc = ion_map_iommu(clnt, hndl, domain_num, partition_num, align,
- 0, iova, buffer_size, flags, 0);
+ 0, iova, buffer_size, UNCACHED, 0);
if (rc)
pr_err("ion_map_iommu failed(%d).domain: %d,partition: %d\n",
rc, domain_num, partition_num);
@@ -73,27 +71,21 @@
pr_err("Failed to get ion flags: %d", rc);
goto fail_map;
}
- mem->kvaddr = ion_map_kernel(client->clnt, hndl, ionflag);
- if (!mem->kvaddr) {
- pr_err("Failed to map shared mem in kernel\n");
- rc = -EIO;
- goto fail_map;
- }
+ mem->kvaddr = NULL;
mem->domain = domain;
mem->partition_num = partition;
rc = get_device_address(client->clnt, hndl, mem->domain,
- mem->partition_num, 4096, &iova, &buffer_size, UNCACHED);
+ mem->partition_num, 4096, &iova, &buffer_size, ionflag);
if (rc) {
pr_err("Failed to get device address: %d\n", rc);
goto fail_device_address;
}
- mem->kvaddr += offset;
mem->mem_type = client->mem_type;
mem->smem_priv = hndl;
- mem->device_addr = iova + offset;
+ mem->device_addr = iova;
mem->size = buffer_size;
- pr_debug("Buffer device address: 0x%lx, size: %d\n",
+ pr_err("NOTE: Buffer device address: 0x%lx, size: %d\n",
mem->device_addr, mem->size);
return rc;
fail_device_address:
@@ -106,22 +98,28 @@
static int alloc_ion_mem(struct smem_client *client, size_t size,
u32 align, u32 flags, int domain, int partition,
- struct msm_smem *mem)
+ struct msm_smem *mem, int map_kernel)
{
struct ion_handle *hndl;
unsigned long iova = 0;
unsigned long buffer_size = 0;
+ unsigned long ionflags = 0;
int rc = 0;
- flags = flags | ION_HEAP(ION_CP_MM_HEAP_ID);
+ if (flags == SMEM_CACHED)
+ ionflags |= ION_SET_CACHE(CACHED);
+ else
+ ionflags |= ION_SET_CACHE(UNCACHED);
+
+ ionflags = ionflags | ION_HEAP(ION_CP_MM_HEAP_ID);
if (align < 4096)
align = 4096;
size = (size + 4095) & (~4095);
pr_debug("\n in %s domain: %d, Partition: %d\n",
__func__, domain, partition);
- hndl = ion_alloc(client->clnt, size, align, flags);
+ hndl = ion_alloc(client->clnt, size, align, ionflags);
if (IS_ERR_OR_NULL(hndl)) {
- pr_err("Failed to allocate shared memory = %p, %d, %d, 0x%x\n",
- client, size, align, flags);
+ pr_err("Failed to allocate shared memory = %p, %d, %d, 0x%lx\n",
+ client, size, align, ionflags);
rc = -ENOMEM;
goto fail_shared_mem_alloc;
}
@@ -129,12 +127,16 @@
mem->smem_priv = hndl;
mem->domain = domain;
mem->partition_num = partition;
- mem->kvaddr = ion_map_kernel(client->clnt, hndl, 0);
- if (!mem->kvaddr) {
- pr_err("Failed to map shared mem in kernel\n");
- rc = -EIO;
- goto fail_map;
- }
+ if (map_kernel) {
+ mem->kvaddr = ion_map_kernel(client->clnt, hndl, 0);
+ if (!mem->kvaddr) {
+ pr_err("Failed to map shared mem in kernel\n");
+ rc = -EIO;
+ goto fail_map;
+ }
+ } else
+ mem->kvaddr = NULL;
+
rc = get_device_address(client->clnt, hndl, mem->domain,
mem->partition_num, align, &iova, &buffer_size, UNCACHED);
if (rc) {
@@ -142,8 +144,8 @@
goto fail_device_address;
}
mem->device_addr = iova;
- pr_debug("device_address = 0x%lx, kvaddr = 0x%p\n",
- mem->device_addr, mem->kvaddr);
+ pr_err("NOTE: device_address = 0x%lx, kvaddr = 0x%p, size = %d\n",
+ mem->device_addr, mem->kvaddr, size);
mem->size = size;
return rc;
fail_device_address:
@@ -156,10 +158,13 @@
static void free_ion_mem(struct smem_client *client, struct msm_smem *mem)
{
- put_device_address(client->clnt,
- mem->smem_priv, mem->domain, mem->partition_num);
- ion_unmap_kernel(client->clnt, mem->smem_priv);
- ion_free(client->clnt, mem->smem_priv);
+ if (mem->device_addr)
+ put_device_address(client->clnt,
+ mem->smem_priv, mem->domain, mem->partition_num);
+ if (mem->kvaddr)
+ ion_unmap_kernel(client->clnt, mem->smem_priv);
+ if (mem->smem_priv)
+ ion_free(client->clnt, mem->smem_priv);
}
static void *ion_new_client(void)
@@ -209,6 +214,36 @@
return mem;
}
+static int ion_mem_clean_invalidate(struct smem_client *clt,
+ struct msm_smem *mem)
+{
+ /*
+ * Note: We're always mapping into iommu as uncached
+ * as a result we don't need to flush/clean anything
+ */
+ return 0;
+}
+
+int msm_smem_clean_invalidate(void *clt, struct msm_smem *mem)
+{
+ struct smem_client *client = clt;
+ int rc;
+ if (!client || !mem) {
+ pr_err("Invalid client/handle passed\n");
+ return -EINVAL;
+ }
+ switch (client->mem_type) {
+ case SMEM_ION:
+ rc = ion_mem_clean_invalidate(client, mem);
+ break;
+ default:
+ pr_err("Mem type not supported\n");
+ rc = -EINVAL;
+ break;
+ }
+ return rc;
+}
+
void *msm_smem_new_client(enum smem_type mtype)
{
struct smem_client *client = NULL;
@@ -234,7 +269,7 @@
};
struct msm_smem *msm_smem_alloc(void *clt, size_t size, u32 align, u32 flags,
- int domain, int partition)
+ int domain, int partition, int map_kernel)
{
struct smem_client *client;
int rc = 0;
@@ -256,7 +291,7 @@
switch (client->mem_type) {
case SMEM_ION:
rc = alloc_ion_mem(client, size, align, flags,
- domain, partition, mem);
+ domain, partition, mem, map_kernel);
break;
default:
pr_err("Mem type not supported\n");
diff --git a/drivers/media/video/msm_vidc/msm_smem.h b/drivers/media/video/msm_vidc/msm_smem.h
index b742c79..37816e1 100644
--- a/drivers/media/video/msm_vidc/msm_smem.h
+++ b/drivers/media/video/msm_vidc/msm_smem.h
@@ -20,6 +20,11 @@
SMEM_ION,
};
+enum smem_cache_prop {
+ SMEM_CACHED,
+ SMEM_UNCACHED,
+};
+
struct msm_smem {
int mem_type;
size_t size;
@@ -32,9 +37,10 @@
void *msm_smem_new_client(enum smem_type mtype);
struct msm_smem *msm_smem_alloc(void *clt, size_t size, u32 align, u32 flags,
- int domain, int partition);
+ int domain, int partition, int map_kernel);
void msm_smem_free(void *clt, struct msm_smem *mem);
void msm_smem_delete_client(void *clt);
struct msm_smem *msm_smem_user_to_kernel(void *clt, int fd, u32 offset, int
domain, int partition);
+int msm_smem_clean_invalidate(void *clt, struct msm_smem *mem);
#endif
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index 12b4c76..4e810dc 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -165,6 +165,7 @@
int buff_off;
int size;
u32 uvaddr;
+ u32 device_addr;
struct msm_smem *handle;
};
@@ -230,6 +231,28 @@
return ret;
}
+struct buffer_info *get_same_fd_buffer(struct list_head *list,
+ int fd)
+{
+ struct buffer_info *temp;
+ struct buffer_info *ret = NULL;
+ if (!list || fd < 0) {
+ pr_err("%s Invalid input\n", __func__);
+ goto err_invalid_input;
+ }
+ if (!list_empty(list)) {
+ list_for_each_entry(temp, list, list) {
+ if (temp && temp->fd == fd) {
+ pr_err("Found same fd buffer\n");
+ ret = temp;
+ break;
+ }
+ }
+ }
+err_invalid_input:
+ return ret;
+}
+
static int msm_v4l2_open(struct file *filp)
{
int rc = 0;
@@ -362,8 +385,9 @@
rc = msm_vidc_release_buf(&v4l2_inst->vidc_inst,
&buffer_info);
list_del(&bi->list);
- msm_smem_free(v4l2_inst->mem_client,
- bi->handle);
+ if (bi->handle)
+ msm_smem_free(v4l2_inst->mem_client,
+ bi->handle);
kfree(bi);
}
}
@@ -374,8 +398,9 @@
int msm_v4l2_prepare_buf(struct file *file, void *fh,
struct v4l2_buffer *b)
{
- struct msm_smem *handle;
+ struct msm_smem *handle = NULL;
struct buffer_info *binfo;
+ struct buffer_info *temp;
struct msm_vidc_inst *vidc_inst;
struct msm_v4l2_vid_inst *v4l2_inst;
int i, rc = 0;
@@ -402,28 +427,43 @@
rc = -ENOMEM;
goto exit;
}
- handle = msm_smem_user_to_kernel(v4l2_inst->mem_client,
+ temp = get_same_fd_buffer(&v4l2_inst->registered_bufs,
+ b->m.planes[i].reserved[0]);
+ if (temp) {
+ binfo->type = b->type;
+ binfo->fd = b->m.planes[i].reserved[0];
+ binfo->buff_off = b->m.planes[i].reserved[1];
+ binfo->size = b->m.planes[i].length;
+ binfo->uvaddr = b->m.planes[i].m.userptr;
+ binfo->device_addr =
+ temp->handle->device_addr + binfo->buff_off;
+ binfo->handle = NULL;
+ } else {
+ handle = msm_smem_user_to_kernel(v4l2_inst->mem_client,
b->m.planes[i].reserved[0],
b->m.planes[i].reserved[1],
vidc_inst->core->resources.io_map[NS_MAP].domain,
0);
- if (!handle) {
- pr_err("Failed to get device buffer address\n");
- kfree(binfo);
- goto exit;
+ if (!handle) {
+ pr_err("Failed to get device buffer address\n");
+ kfree(binfo);
+ goto exit;
+ }
+ binfo->type = b->type;
+ binfo->fd = b->m.planes[i].reserved[0];
+ binfo->buff_off = b->m.planes[i].reserved[1];
+ binfo->size = b->m.planes[i].length;
+ binfo->uvaddr = b->m.planes[i].m.userptr;
+ binfo->device_addr =
+ handle->device_addr + binfo->buff_off;
+ binfo->handle = handle;
+ pr_debug("Registering buffer: %d, %d, %d\n",
+ b->m.planes[i].reserved[0],
+ b->m.planes[i].reserved[1],
+ b->m.planes[i].length);
}
- binfo->type = b->type;
- binfo->fd = b->m.planes[i].reserved[0];
- binfo->buff_off = b->m.planes[i].reserved[1];
- binfo->size = b->m.planes[i].length;
- binfo->uvaddr = b->m.planes[i].m.userptr;
- binfo->handle = handle;
- pr_debug("Registering buffer: %d, %d, %d\n",
- b->m.planes[i].reserved[0],
- b->m.planes[i].reserved[1],
- b->m.planes[i].length);
list_add_tail(&binfo->list, &v4l2_inst->registered_bufs);
- b->m.planes[i].m.userptr = handle->device_addr;
+ b->m.planes[i].m.userptr = binfo->device_addr;
}
rc = msm_vidc_prepare_buf(&v4l2_inst->vidc_inst, b);
exit:
@@ -453,9 +493,17 @@
rc = -EINVAL;
goto err_invalid_buff;
}
- b->m.planes[i].m.userptr = binfo->handle->device_addr;
- pr_debug("Queueing device address = %ld\n",
- binfo->handle->device_addr);
+ b->m.planes[i].m.userptr = binfo->device_addr;
+ pr_debug("Queueing device address = 0x%x\n",
+ binfo->device_addr);
+ if (binfo->handle) {
+ rc = msm_smem_clean_invalidate(v4l2_inst->mem_client,
+ binfo->handle);
+ if (rc) {
+ pr_err("Failed to clean caches: %d\n", rc);
+ goto err_invalid_buff;
+ }
+ }
}
rc = msm_vidc_qbuf(&v4l2_inst->vidc_inst, b);
err_invalid_buff:
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index a838a12..cae486f 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -156,11 +156,23 @@
static u32 get_frame_size_nv12(int plane,
u32 height, u32 width)
{
- int luma_stride = ALIGN(width, 32);
- int luma_slice = ALIGN(height, 32);
- int chroma_stride = ALIGN(roundup(width, 2)/2, 32);
- int chroma_slice = ALIGN(roundup(height, 2)/2, 32);
- return (luma_stride * luma_slice) + (chroma_stride * chroma_slice) * 2;
+ int size;
+ int luma_h, luma_w, luma_stride, luma_scanl, luma_size;
+ int chroma_h, chroma_w, chroma_stride, chroma_scanl, chroma_size;
+
+ luma_w = width;
+ luma_h = height;
+
+ chroma_w = luma_w;
+ chroma_h = luma_h/2;
+ NV12_IL_CALC_Y_STRIDE(luma_stride, luma_w, 32);
+ NV12_IL_CALC_Y_BUFHEIGHT(luma_scanl, luma_h, 32);
+ NV12_IL_CALC_UV_STRIDE(chroma_stride, chroma_w, 32);
+ NV12_IL_CALC_UV_BUFHEIGHT(chroma_scanl, luma_h, 32);
+ NV12_IL_CALC_BUF_SIZE(size, luma_size, luma_stride,
+ luma_scanl, chroma_size, chroma_stride, chroma_scanl, 32);
+ size = ALIGN(size, SZ_4K);
+ return size;
}
static u32 get_frame_size_nv21(int plane,
u32 height, u32 width)
@@ -312,9 +324,9 @@
if (!inst->extradata_handle) {
inst->extradata_handle =
msm_smem_alloc(inst->mem_client,
- 4096 * 1024, 1, 0,
+ 4096 * 1024, 1, SMEM_UNCACHED,
inst->core->resources.io_map[NS_MAP].domain,
- 0);
+ 0, 0);
if (!inst->extradata_handle) {
pr_err("Failed to allocate extradta memory\n");
rc = -ENOMEM;
@@ -469,8 +481,8 @@
return -EINVAL;
}
if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- inst->prop.width = f->fmt.pix_mp.width;
- inst->prop.height = f->fmt.pix_mp.height;
+ struct hal_frame_size frame_sz;
+
fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats,
ARRAY_SIZE(vdec_formats), f->fmt.pix_mp.pixelformat,
CAPTURE_PORT);
@@ -480,6 +492,21 @@
rc = -EINVAL;
goto err_invalid_fmt;
}
+
+ inst->prop.width = f->fmt.pix_mp.width;
+ inst->prop.height = f->fmt.pix_mp.height;
+
+ frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
+ frame_sz.width = inst->prop.width;
+ frame_sz.height = inst->prop.height;
+ pr_debug("width = %d, height = %d\n",
+ frame_sz.width, frame_sz.height);
+ rc = vidc_hal_session_set_property((void *)inst->session,
+ HAL_PARAM_FRAME_SIZE, &frame_sz);
+ if (rc) {
+ pr_err("Failed to set hal property for framesize\n");
+ goto err_invalid_fmt;
+ }
} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats,
ARRAY_SIZE(vdec_formats), f->fmt.pix_mp.pixelformat,
@@ -570,7 +597,6 @@
{
int i, rc = 0;
struct msm_vidc_inst *inst;
- struct hal_frame_size frame_sz;
unsigned long flags;
if (!q || !q->drv_priv) {
pr_err("Invalid input, q = %p\n", q);
@@ -595,27 +621,42 @@
pr_err("Failed to open instance\n");
break;
}
- frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
- frame_sz.width = inst->prop.width;
- frame_sz.height = inst->prop.height;
- pr_debug("width = %d, height = %d\n",
- frame_sz.width, frame_sz.height);
- rc = vidc_hal_session_set_property((void *)inst->session,
- HAL_PARAM_FRAME_SIZE, &frame_sz);
- if (rc) {
- pr_err("Failed to set hal property for framesize\n");
- break;
- }
+
rc = msm_comm_try_get_bufreqs(inst);
if (rc) {
pr_err("Failed to get buffer requirements: %d\n", rc);
break;
}
*num_planes = 1;
+
spin_lock_irqsave(&inst->lock, flags);
- *num_buffers = inst->buff_req.buffer[1].buffer_count_actual;
+ if (*num_buffers && *num_buffers >
+ inst->buff_req.buffer[HAL_BUFFER_OUTPUT].
+ buffer_count_actual) {
+ struct hal_buffer_count_actual new_buf_count;
+ enum hal_property property_id =
+ HAL_PARAM_BUFFER_COUNT_ACTUAL;
+
+ new_buf_count.buffer_type = HAL_BUFFER_OUTPUT;
+ new_buf_count.buffer_count_actual = *num_buffers;
+ rc = vidc_hal_session_set_property(inst->session,
+ property_id, &new_buf_count);
+
+ spin_unlock_irqrestore(&inst->lock, flags);
+ if (!rc && msm_comm_try_get_bufreqs(inst)) {
+ /* We are allowed to reject clients' request for
+ * more buffers and suggest our own bufreq */
+ pr_warn("Unable to increase the number of output buffers to %d\n",
+ *num_buffers);
+ }
+ spin_lock_irqsave(&inst->lock, flags);
+ }
+ *num_buffers = inst->buff_req.buffer[HAL_BUFFER_OUTPUT].
+ buffer_count_actual;
spin_unlock_irqrestore(&inst->lock, flags);
- pr_debug("size = %d, alignment = %d\n",
+
+ pr_debug("count = %d, size = %d, alignment = %d\n",
+ inst->buff_req.buffer[1].buffer_count_actual,
inst->buff_req.buffer[1].buffer_size,
inst->buff_req.buffer[1].buffer_alignment);
for (i = 0; i < *num_planes; i++) {
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index 50303d6..74f1415 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -449,7 +449,23 @@
static u32 get_frame_size_nv12(int plane, u32 height, u32 width)
{
- return ((height + 31) & (~31)) * ((width + 31) & (~31)) * 3/2;
+ int size;
+ int luma_h, luma_w, luma_stride, luma_scanl, luma_size;
+ int chroma_h, chroma_w, chroma_stride, chroma_scanl, chroma_size;
+
+ luma_w = width;
+ luma_h = height;
+
+ chroma_w = luma_w;
+ chroma_h = luma_h/2;
+ NV12_IL_CALC_Y_STRIDE(luma_stride, luma_w, 32);
+ NV12_IL_CALC_Y_BUFHEIGHT(luma_scanl, luma_h, 32);
+ NV12_IL_CALC_UV_STRIDE(chroma_stride, chroma_w, 32);
+ NV12_IL_CALC_UV_BUFHEIGHT(chroma_scanl, luma_h, 32);
+ NV12_IL_CALC_BUF_SIZE(size, luma_size, luma_stride,
+ luma_scanl, chroma_size, chroma_stride, chroma_scanl, 32);
+ size = ALIGN(size, SZ_4K);
+ return size;
}
static u32 get_frame_size_nv21(int plane, u32 height, u32 width)
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 50f98da..b6dce2c 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -14,6 +14,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/iommu.h>
+#include <asm/div64.h>
#include <mach/iommu.h>
#include <mach/iommu_domains.h>
#include <mach/peripheral-loader.h>
@@ -430,6 +431,7 @@
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
unsigned long flags;
+ int i;
if (!response || !response->data) {
pr_err("Failed to get valid response for prop info\n");
return;
@@ -439,6 +441,12 @@
memcpy(&inst->buff_req, response->data,
sizeof(struct buffer_requirements));
spin_unlock_irqrestore(&inst->lock, flags);
+ for (i = 0; i < 8; i++) {
+ pr_err("NOTE: buffer type: %d, count : %d, size: %d\n",
+ inst->buff_req.buffer[i].buffer_type,
+ inst->buff_req.buffer[i].buffer_count_actual,
+ inst->buff_req.buffer[i].buffer_size);
+ }
signal_session_msg_receipt(cmd, inst);
}
@@ -572,9 +580,41 @@
(u32)fill_buf_done->packet_buffer1);
if (vb) {
vb->v4l2_planes[0].bytesused = fill_buf_done->filled_len1;
- pr_debug("Filled length = %d\n", vb->v4l2_planes[0].bytesused);
+
+ if (!(fill_buf_done->flags1 &
+ HAL_BUFFERFLAG_TIMESTAMPINVALID)) {
+ int64_t time_usec = fill_buf_done->timestamp_hi;
+ time_usec = (time_usec << 32) |
+ fill_buf_done->timestamp_lo;
+
+ vb->v4l2_buf.timestamp =
+ ns_to_timeval(time_usec * NSEC_PER_USEC);
+ }
+
if (fill_buf_done->flags1 & HAL_BUFFERFLAG_EOS)
vb->v4l2_buf.flags |= V4L2_BUF_FLAG_EOS;
+
+ switch (fill_buf_done->picture_type) {
+ case HAL_PICTURE_IDR:
+ case HAL_PICTURE_I:
+ vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
+ break;
+ case HAL_PICTURE_P:
+ vb->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
+ break;
+ case HAL_PICTURE_B:
+ vb->v4l2_buf.flags |= V4L2_BUF_FLAG_BFRAME;
+ break;
+ case HAL_FRAME_NOTCODED:
+ case HAL_UNUSED_PICT:
+ /* Do we need to care about these? */
+ case HAL_FRAME_YUV:
+ break;
+ }
+
+ pr_debug("Filled length = %d; flags %x\n",
+ vb->v4l2_planes[0].bytesused,
+ vb->v4l2_buf.flags);
vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
} else {
/*
@@ -1352,11 +1392,14 @@
list_add_tail(&entry->list, &inst->pendingq);
spin_unlock_irqrestore(&inst->lock, flags);
} else {
+ int64_t time_usec = timeval_to_ns(&vb->v4l2_buf.timestamp);
+ do_div(time_usec, NSEC_PER_USEC);
+
memset(&frame_data, 0 , sizeof(struct vidc_frame_data));
frame_data.alloc_len = vb->v4l2_planes[0].length;
frame_data.filled_len = vb->v4l2_planes[0].bytesused;
frame_data.device_addr = vb->v4l2_planes[0].m.userptr;
- frame_data.timestamp = vb->v4l2_buf.timestamp.tv_usec;
+ frame_data.timestamp = time_usec;
frame_data.clnt_data = (u32)vb;
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
frame_data.buffer_type = HAL_BUFFER_INPUT;
@@ -1451,8 +1494,9 @@
for (i = 0; i < scratch_buf->buffer_count_actual;
i++) {
handle = msm_smem_alloc(inst->mem_client,
- scratch_buf->buffer_size, 1, 0,
- inst->core->resources.io_map[NS_MAP].domain, 0);
+ scratch_buf->buffer_size, 1, SMEM_UNCACHED,
+ inst->core->resources.io_map[NS_MAP].domain,
+ 0, 0);
if (!handle) {
pr_err("Failed to allocate scratch memory\n");
rc = -ENOMEM;
@@ -1510,8 +1554,9 @@
if (persist_buf->buffer_size) {
for (i = 0; i < persist_buf->buffer_count_actual; i++) {
handle = msm_smem_alloc(inst->mem_client,
- persist_buf->buffer_size, 1, 0,
- inst->core->resources.io_map[NS_MAP].domain, 0);
+ persist_buf->buffer_size, 1, SMEM_UNCACHED,
+ inst->core->resources.io_map[NS_MAP].domain,
+ 0, 0);
if (!handle) {
pr_err("Failed to allocate persist memory\n");
rc = -ENOMEM;
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index 630f383..d01b1d1 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -47,6 +47,32 @@
#define SESSION_MSG_INDEX(__msg) (__msg - SESSION_MSG_START)
#define MAX_NAME_LENGTH 64
+
+#define NV12_IL_CALC_Y_STRIDE(stride, frame_width, stride_multiple) \
+ { stride = (frame_width + stride_multiple - 1) & \
+ (0xffffffff - (stride_multiple - 1)); }
+
+#define NV12_IL_CALC_Y_BUFHEIGHT(buf_height, frame_height,\
+ min_buf_height_multiple) \
+ { buf_height = (frame_height + min_buf_height_multiple - 1) & \
+ (0xffffffff - (min_buf_height_multiple - 1)); }
+
+#define NV12_IL_CALC_UV_STRIDE(stride, frame_width, stride_multiple) \
+ { stride = ((((frame_width + 1) >> 1) + stride_multiple - 1) & \
+ (0xffffffff - (stride_multiple - 1))) << 1; }
+
+#define NV12_IL_CALC_UV_BUFHEIGHT(buf_height, frame_height,\
+ min_buf_height_multiple) \
+ { buf_height = ((((frame_height + 1) >> 1) + \
+ min_buf_height_multiple - 1) & (0xffffffff - \
+ (min_buf_height_multiple - 1))); }
+
+#define NV12_IL_CALC_BUF_SIZE(buf_size, y_buf_size, y_stride, \
+ y_buf_height, uv_buf_size, uv_stride, uv_buf_height, uv_alignment) \
+ { y_buf_size = (y_stride * y_buf_height); \
+ uv_buf_size = (uv_stride * uv_buf_height) + uv_alignment; \
+ buf_size = y_buf_size + uv_buf_size; }
+
enum vidc_ports {
OUTPUT_PORT,
CAPTURE_PORT,
diff --git a/drivers/media/video/msm_vidc/vidc_hal.c b/drivers/media/video/msm_vidc/vidc_hal.c
index 8008e66..2021ec6 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.c
+++ b/drivers/media/video/msm_vidc/vidc_hal.c
@@ -308,6 +308,7 @@
{
struct vidc_mem_addr *vmem;
struct msm_smem *alloc;
+ int rc = 0;
if (!mem || !clnt || !size) {
HAL_MSG_ERROR("Invalid Params in %s", __func__);
@@ -316,20 +317,29 @@
vmem = (struct vidc_mem_addr *)mem;
HAL_MSG_HIGH("start to alloc: size:%d, Flags: %d", size, flags);
- alloc = msm_smem_alloc(clnt, size, align, flags, domain, 1);
+ alloc = msm_smem_alloc(clnt, size, align, flags, domain, 1, 1);
HAL_MSG_LOW("Alloc done");
if (!alloc) {
HAL_MSG_HIGH("Alloc fail in %s", __func__);
- return -ENOMEM;
- } else {
- HAL_MSG_MEDIUM("vidc_hal_alloc:ptr=%p,size=%d",
- alloc->kvaddr, size);
- vmem->mem_size = alloc->size;
- vmem->mem_data = alloc;
- vmem->align_virtual_addr = (u8 *) alloc->kvaddr;
- vmem->align_device_addr = (u8 *)alloc->device_addr;
+ rc = -ENOMEM;
+ goto fail_smem_alloc;
}
- return 0;
+ rc = msm_smem_clean_invalidate(clnt, alloc);
+ if (rc) {
+ pr_err("NOTE: Failed to clean caches\n");
+ goto fail_clean_cache;
+ }
+ HAL_MSG_MEDIUM("vidc_hal_alloc:ptr=%p,size=%d",
+ alloc->kvaddr, size);
+ vmem->mem_size = alloc->size;
+ vmem->mem_data = alloc;
+ vmem->align_virtual_addr = (u8 *) alloc->kvaddr;
+ vmem->align_device_addr = (u8 *)alloc->device_addr;
+ return rc;
+fail_clean_cache:
+ msm_smem_free(clnt, alloc);
+fail_smem_alloc:
+ return rc;
}
static void vidc_hal_free(struct smem_client *clnt, struct msm_smem *mem)
@@ -476,7 +486,7 @@
{
q_hdr->qhdr_status = 0x1;
q_hdr->qhdr_type = VIDC_IFACEQ_DFLT_QHDR;
- q_hdr->qhdr_q_size = VIDC_IFACEQ_QUEUE_SIZE;
+ q_hdr->qhdr_q_size = VIDC_IFACEQ_QUEUE_SIZE / 4;
q_hdr->qhdr_pkt_size = 0;
q_hdr->qhdr_rx_wm = 0x1;
q_hdr->qhdr_tx_wm = 0x1;
@@ -517,7 +527,7 @@
rc = vidc_hal_alloc((void *) &dev->iface_q_table,
dev->hal_client,
- VIDC_IFACEQ_TABLE_SIZE, 1, 0, domain);
+ VIDC_IFACEQ_TABLE_SIZE, 1, SMEM_UNCACHED, domain);
if (rc) {
HAL_MSG_ERROR("%s:iface_q_table_alloc_fail", __func__);
return -ENOMEM;
@@ -537,7 +547,7 @@
iface_q = &dev->iface_queues[i];
rc = vidc_hal_alloc((void *) &iface_q->q_array,
dev->hal_client, VIDC_IFACEQ_QUEUE_SIZE,
- 1, 0, domain);
+ 1, SMEM_UNCACHED, domain);
if (rc) {
HAL_MSG_ERROR("%s:iface_q_table_alloc[%d]_fail",
__func__, i);
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index e8d9e04..407bf2e 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -1117,6 +1117,12 @@
return -ENOTRECOVERABLE;
}
+ if (!dev->vp_dummy_complete) {
+ pr_err("VCAP Err: %s: VP dummy read not complete",
+ __func__);
+ return -EINVAL;
+ }
+
switch (c_data->op_mode) {
case VC_VCAP_OP:
mutex_lock(&dev->dev_mutex);
@@ -1390,19 +1396,13 @@
}
dev->vc_resource = 0;
mutex_unlock(&dev->dev_mutex);
+ c_data->streaming = 0;
rc = vb2_streamoff(&c_data->vc_vidq,
V4L2_BUF_TYPE_VIDEO_CAPTURE);
- if (rc >= 0) {
- c_data->streaming = 0;
+ if (rc >= 0)
atomic_set(&c_data->dev->vc_enabled, 0);
- }
return rc;
case VP_VCAP_OP:
- if (!dev->vp_dummy_complete) {
- pr_err("VCAP Err: %s: VP dummy read not complete",
- __func__);
- return -EINVAL;
- }
if (c_data != dev->vp_client) {
pr_err("VCAP Err: %s: VP held by other client",
__func__);
@@ -1441,11 +1441,6 @@
atomic_set(&c_data->dev->vp_enabled, 0);
return rc;
case VC_AND_VP_VCAP_OP:
- if (!dev->vp_dummy_complete) {
- pr_err("VCAP Err: %s: VP dummy read not complete",
- __func__);
- return -EINVAL;
- }
if (c_data != dev->vp_client || c_data != dev->vc_client) {
pr_err("VCAP Err: %s: VC/VP held by other client",
__func__);
diff --git a/drivers/media/video/vcap_vc.c b/drivers/media/video/vcap_vc.c
index 62cc306..966fa4b 100644
--- a/drivers/media/video/vcap_vc.c
+++ b/drivers/media/video/vcap_vc.c
@@ -120,6 +120,13 @@
dprintk(1, "%s: irq=0x%08x\n", __func__, irq);
+ c_data = dev->vc_client;
+ if (!c_data->streaming) {
+ writel_iowmb(irq, VCAP_VC_INT_CLEAR);
+ pr_err("VC no longer streaming\n");
+ return IRQ_HANDLED;
+ }
+
v4l2_evt.id = 0;
if (irq & 0x8000200) {
v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
@@ -161,7 +168,6 @@
pr_err("VC: There is no active vc client\n");
return IRQ_HANDLED;
}
- c_data = dev->vc_client;
spin_lock(&dev->vc_client->cap_slock);
if (list_empty(&dev->vc_client->vid_vc_action.active)) {
@@ -316,15 +322,34 @@
void vc_stop_capture(struct vcap_client_data *c_data)
{
struct vcap_dev *dev = c_data->dev;
- int rc;
+ unsigned int reg;
+ int timeout;
- rc = readl_relaxed(VCAP_VC_CTRL);
- writel_iowmb(rc & ~(0x1), VCAP_VC_CTRL);
-
- if (atomic_read(&dev->vc_enabled) == 1)
- disable_irq(dev->vcirq->start);
-
+ writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
+ writel_iowmb(0x0, VCAP_VC_INT_MASK);
flush_workqueue(dev->vcap_wq);
+ if (atomic_read(&dev->vc_enabled) == 1)
+ disable_irq_nosync(dev->vcirq->start);
+
+ writel_iowmb(0x00000000, VCAP_VC_CTRL);
+ writel_iowmb(0x00000001, VCAP_SW_RESET_REQ);
+ timeout = 10000;
+ while (1) {
+ reg = (readl_relaxed(VCAP_SW_RESET_STATUS) & 0x1);
+ if (!reg)
+ break;
+ timeout--;
+ if (timeout == 0) {
+ /* This should not happen */
+ pr_err("VC is not resetting properly\n");
+ writel_iowmb(0x00000000, VCAP_SW_RESET_REQ);
+ break;
+ }
+ }
+
+ reg = readl_relaxed(VCAP_VC_NPL_CTRL);
+ reg = readl_relaxed(VCAP_VC_NPL_CTRL);
+ writel_iowmb(0x00000002, VCAP_VC_NPL_CTRL);
}
int config_vc_format(struct vcap_client_data *c_data)
@@ -336,21 +361,20 @@
dev = c_data->dev;
/* restart VC */
- writel_relaxed(0x00000001, VCAP_SW_RESET_REQ);
+ writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
+ writel_iowmb(0x00000001, VCAP_SW_RESET_REQ);
timeout = 10000;
while (1) {
- rc = (readl_relaxed(VCAP_SW_RESET_STATUS) & 0x1);
- if (!rc)
+ if (!(readl_relaxed(VCAP_SW_RESET_STATUS) & 0x1))
break;
timeout--;
if (timeout == 0) {
pr_err("VC is not resetting properly\n");
+ writel_iowmb(0x00000002, VCAP_VC_NPL_CTRL);
return -EINVAL;
}
}
- writel_relaxed(0x00000000, VCAP_SW_RESET_REQ);
- writel_iowmb(0x00000102, VCAP_VC_NPL_CTRL);
rc = readl_relaxed(VCAP_VC_NPL_CTRL);
rc = readl_relaxed(VCAP_VC_NPL_CTRL);
writel_iowmb(0x00000002, VCAP_VC_NPL_CTRL);
diff --git a/drivers/media/video/vcap_vc.h b/drivers/media/video/vcap_vc.h
index 792fb14..76693bb 100644
--- a/drivers/media/video/vcap_vc.h
+++ b/drivers/media/video/vcap_vc.h
@@ -19,14 +19,8 @@
#define VCAP_HARDWARE_VERSION 0x10000000
-#define VCAP_BASE (dev->vcapbase)
-#define VCAP_OFFSET(off) (VCAP_BASE + off)
-
#define VCAP_HARDWARE_VERSION_REG (VCAP_BASE + 0x0000)
-#define VCAP_SW_RESET_REQ (VCAP_BASE + 0x0024)
-#define VCAP_SW_RESET_STATUS (VCAP_BASE + 0x0028)
-
#define VCAP_VC_CTRL (VCAP_BASE + 0x0800)
#define VCAP_VC_NPL_CTRL (VCAP_BASE + 0x0804)
#define VCAP_VC_POLARITY (VCAP_BASE + 0x081c)
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index 9f2ead4..f8f27d4 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -74,6 +74,12 @@
dev = c_data->dev;
dprintk(2, "Start setup buffers\n");
+ if (dev->vp_shutdown) {
+ dprintk(1, "%s: VP shutting down, no buf setup\n",
+ __func__);
+ return -EPERM;
+ }
+
/* No need to verify vp_client is not NULL caller does so */
vp_act = &dev->vp_client->vid_vp_action;
@@ -262,6 +268,8 @@
writel_relaxed(0x00000000, VCAP_VP_INTERRUPT_ENABLE);
writel_iowmb(irq, VCAP_VP_INT_CLEAR);
atomic_set(&dev->vp_enabled, 0);
+ if (dev->vp_shutdown)
+ wake_up(&dev->vp_dummy_waitq);
return;
}
@@ -320,7 +328,7 @@
}
dprintk(1, "%s: irq=0x%08x\n", __func__, irq);
- if (!(irq & (VP_PIC_DONE || VP_MODE_CHANGE))) {
+ if (!(irq & (VP_PIC_DONE | VP_MODE_CHANGE))) {
writel_relaxed(irq, VCAP_VP_INT_CLEAR);
pr_err("VP IRQ shows some error\n");
return IRQ_HANDLED;
@@ -350,30 +358,60 @@
return IRQ_HANDLED;
}
+int vp_sw_reset(struct vcap_dev *dev)
+{
+ int timeout;
+ writel_iowmb(0x00000010, VCAP_SW_RESET_REQ);
+ timeout = 10000;
+ while (1) {
+ if (!(readl_relaxed(VCAP_SW_RESET_STATUS) & 0x10))
+ break;
+ timeout--;
+ if (timeout == 0) {
+ /* This should not happen */
+ pr_err("VP is not resetting properly\n");
+ writel_iowmb(0x00000000, VCAP_SW_RESET_REQ);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
void vp_stop_capture(struct vcap_client_data *c_data)
{
struct vcap_dev *dev = c_data->dev;
+ int rc;
- writel_iowmb(0x00000000, VCAP_VP_CTRL);
+ dev->vp_shutdown = true;
flush_workqueue(dev->vcap_wq);
- if (atomic_read(&dev->vp_enabled) == 1)
- disable_irq(dev->vpirq->start);
+ if (atomic_read(&dev->vp_enabled) == 1) {
+ rc = wait_event_interruptible_timeout(dev->vp_dummy_waitq,
+ !atomic_read(&dev->vp_enabled),
+ msecs_to_jiffies(50));
+ if (rc == 0 && atomic_read(&dev->vp_enabled) == 1) {
+ /* This should not happen, if it does hw is stuck */
+ pr_err("%s: VP Timeout and VP still running\n",
+ __func__);
+ }
+ }
- writel_iowmb(0x00000001, VCAP_VP_SW_RESET);
- writel_iowmb(0x00000000, VCAP_VP_SW_RESET);
+ vp_sw_reset(dev);
+ dev->vp_shutdown = false;
}
int config_vp_format(struct vcap_client_data *c_data)
{
struct vcap_dev *dev = c_data->dev;
+ int rc;
INIT_WORK(&dev->vp_to_vc_work.work, mov_buf_to_vc);
dev->vp_to_vc_work.cd = c_data;
/* SW restart VP */
- writel_iowmb(0x00000001, VCAP_VP_SW_RESET);
- writel_iowmb(0x00000000, VCAP_VP_SW_RESET);
+ rc = vp_sw_reset(dev);
+ if (rc < 0)
+ return rc;
/* Film Mode related settings */
writel_iowmb(0x00000000, VCAP_VP_FILM_PROJECTION_T0);
@@ -668,20 +706,18 @@
dev->vp_dummy_event = true;
+ enable_irq(dev->vpirq->start);
writel_relaxed(0x01100101, VCAP_VP_INTERRUPT_ENABLE);
writel_iowmb(0x00000000, VCAP_VP_CTRL);
writel_iowmb(0x00010000, VCAP_VP_CTRL);
- enable_irq(dev->vpirq->start);
rc = wait_event_interruptible_timeout(dev->vp_dummy_waitq,
dev->vp_dummy_complete, msecs_to_jiffies(50));
if (!rc && !dev->vp_dummy_complete) {
pr_err("%s: VP dummy event timeout", __func__);
rc = -ETIME;
- writel_iowmb(0x00000000, VCAP_VP_CTRL);
- writel_iowmb(0x00000001, VCAP_VP_SW_RESET);
- writel_iowmb(0x00000000, VCAP_VP_SW_RESET);
+ vp_sw_reset(dev);
dev->vp_dummy_complete = false;
}
@@ -789,7 +825,7 @@
top_field = 1;
#endif
vp_act->vp_state = VP_FRAME2;
- writel_relaxed(0x01100101, VCAP_VP_INTERRUPT_ENABLE);
+ writel_relaxed(0x01100001, VCAP_VP_INTERRUPT_ENABLE);
#ifdef TOP_FIELD_FIX
writel_iowmb(0x00000000 | vp_act->top_field << 0, VCAP_VP_CTRL);
writel_iowmb(0x00010000 | vp_act->top_field << 0, VCAP_VP_CTRL);
@@ -836,7 +872,7 @@
#endif
/* Config VP & Enable Interrupt */
- writel_relaxed(0x01100101, VCAP_VP_INTERRUPT_ENABLE);
+ writel_relaxed(0x01100001, VCAP_VP_INTERRUPT_ENABLE);
#ifdef TOP_FIELD_FIX
writel_iowmb(0x00000000 | vp_act->top_field << 0, VCAP_VP_CTRL);
writel_iowmb(0x00010000 | vp_act->top_field << 0, VCAP_VP_CTRL);
diff --git a/drivers/media/video/vcap_vp.h b/drivers/media/video/vcap_vp.h
index b2b00e9..2ad5848 100644
--- a/drivers/media/video/vcap_vp.h
+++ b/drivers/media/video/vcap_vp.h
@@ -17,9 +17,6 @@
#include <media/vcap_v4l2.h>
-#define VCAP_BASE (dev->vcapbase)
-#define VCAP_OFFSET(off) (VCAP_BASE + off)
-
#define VCAP_VP_INT_STATUS (VCAP_BASE + 0x404)
#define VCAP_VP_INT_CLEAR (VCAP_BASE + 0x40C)
diff --git a/drivers/media/video/videobuf2-msm-mem.c b/drivers/media/video/videobuf2-msm-mem.c
index 740d183..c1a392e2 100644
--- a/drivers/media/video/videobuf2-msm-mem.c
+++ b/drivers/media/video/videobuf2-msm-mem.c
@@ -62,7 +62,7 @@
goto alloc_failed;
}
rc = ion_map_iommu(mem->client, mem->ion_handle,
- CAMERA_DOMAIN, GEN_POOL, SZ_4K, 0,
+ -1, 0, SZ_4K, 0,
(unsigned long *)&phyaddr,
(unsigned long *)&len, UNCACHED, 0);
if (rc < 0) {
@@ -87,7 +87,7 @@
{
int32_t rc = 0;
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- ion_unmap_iommu(mem->client, mem->ion_handle, CAMERA_DOMAIN, GEN_POOL);
+ ion_unmap_iommu(mem->client, mem->ion_handle, -1, 0);
ion_free(mem->client, mem->ion_handle);
ion_client_destroy(mem->client);
#else
@@ -174,7 +174,8 @@
struct videobuf2_msm_offset *offset,
enum videobuf2_buffer_type buffer_type,
uint32_t addr_offset, int path,
- struct ion_client *client)
+ struct ion_client *client,
+ int domain_num)
{
unsigned long len;
int rc = 0;
@@ -190,7 +191,7 @@
pr_err("%s ION import failed\n", __func__);
return PTR_ERR(mem->ion_handle);
}
- rc = ion_map_iommu(client, mem->ion_handle, CAMERA_DOMAIN, GEN_POOL,
+ rc = ion_map_iommu(client, mem->ion_handle, domain_num, 0,
SZ_4K, 0, (unsigned long *)&mem->phyaddr, &len, UNCACHED, 0);
if (rc < 0)
ion_free(client, mem->ion_handle);
@@ -220,12 +221,12 @@
EXPORT_SYMBOL_GPL(videobuf2_pmem_contig_user_get);
void videobuf2_pmem_contig_user_put(struct videobuf2_contig_pmem *mem,
- struct ion_client *client)
+ struct ion_client *client, int domain_num)
{
if (mem->is_userptr) {
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
ion_unmap_iommu(client, mem->ion_handle,
- CAMERA_DOMAIN, GEN_POOL);
+ domain_num, 0);
ion_free(client, mem->ion_handle);
#elif CONFIG_ANDROID_PMEM
put_pmem_file(mem->file);
diff --git a/drivers/mfd/pm8xxx-misc.c b/drivers/mfd/pm8xxx-misc.c
index 0af013e..6bb1441 100644
--- a/drivers/mfd/pm8xxx-misc.c
+++ b/drivers/mfd/pm8xxx-misc.c
@@ -564,6 +564,7 @@
: SLEEP_CTRL_SMPL_EN_PWR_OFF));
break;
case PM8XXX_VERSION_8921:
+ case PM8XXX_VERSION_8917:
rc = pm8xxx_misc_masked_write(chip,
REG_PM8921_SLEEP_CTRL, SLEEP_CTRL_SMPL_EN_MASK,
(enable ? SLEEP_CTRL_SMPL_EN_RESET
@@ -624,6 +625,7 @@
delay);
break;
case PM8XXX_VERSION_8921:
+ case PM8XXX_VERSION_8917:
rc = pm8xxx_misc_masked_write(chip,
REG_PM8921_SLEEP_CTRL, SLEEP_CTRL_SMPL_SEL_MASK,
delay);
@@ -703,6 +705,7 @@
REG_PM8058_COIN_CHG, reg);
break;
case PM8XXX_VERSION_8921:
+ case PM8XXX_VERSION_8917:
rc = pm8xxx_writeb(chip->dev->parent,
REG_PM8921_COIN_CHG, reg);
break;
@@ -747,6 +750,7 @@
case PM8XXX_VERSION_8018:
case PM8XXX_VERSION_8058:
case PM8XXX_VERSION_8921:
+ case PM8XXX_VERSION_8917:
rc = pm8xxx_misc_masked_write(chip,
REG_PM8XXX_PON_CTRL_1, PON_CTRL_1_WD_EN_MASK,
(enable ? PON_CTRL_1_WD_EN_RESET
@@ -793,6 +797,7 @@
case PM8XXX_VERSION_8018:
case PM8XXX_VERSION_8058:
case PM8XXX_VERSION_8921:
+ case PM8XXX_VERSION_8917:
rc = pm8xxx_writeb(chip->dev->parent,
REG_PM8XXX_GP_TEST_1, PM8XXX_STAY_ON_CFG);
break;
@@ -884,6 +889,7 @@
REG_PM8901_PON_CNTL_4, REG_PM8901_PON_CNTL_5);
break;
case PM8XXX_VERSION_8921:
+ case PM8XXX_VERSION_8917:
__pm8xxx_hard_reset_config(chip, config,
REG_PM8921_PON_CNTL_4, REG_PM8921_PON_CNTL_5);
break;
@@ -941,6 +947,7 @@
case PM8XXX_VERSION_8018:
case PM8XXX_VERSION_8058:
case PM8XXX_VERSION_8921:
+ case PM8XXX_VERSION_8917:
rc = pm8xxx_misc_masked_write(chip,
REG_PM8XXX_GPIO_MUX_CTRL, UART_PATH_SEL_MASK,
uart_path_sel << UART_PATH_SEL_SHIFT);
@@ -1091,6 +1098,7 @@
switch (chip->version) {
case PM8XXX_VERSION_8038:
case PM8XXX_VERSION_8921:
+ case PM8XXX_VERSION_8917:
pm8xxx_misc_masked_write(chip,
REG_PM8XXX_XO_CNTRL_2, clk_mask, value);
break;
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 05707fd..35ae29a 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -27,9 +27,9 @@
#include <linux/i2c.h>
#include <sound/soc.h>
-#define WCD9XXX_SLIM_GLA_MAX_RETRIES 5
#define WCD9XXX_REGISTER_START_OFFSET 0x800
#define WCD9XXX_SLIM_RW_MAX_TRIES 3
+#define SLIMBUS_PRESENT_TIMEOUT 100
#define MAX_WCD9XXX_DEVICE 4
#define TABLA_I2C_MODE 0x03
@@ -283,8 +283,6 @@
return ret;
}
- gpio_direction_output(wcd9xxx->reset_gpio, 1);
- msleep(20);
gpio_direction_output(wcd9xxx->reset_gpio, 0);
msleep(20);
gpio_direction_output(wcd9xxx->reset_gpio, 1);
@@ -338,18 +336,26 @@
WCD9XXX_A_CHIP_VERSION) & 0x1F;
pr_info("%s : Codec version %u initialized\n",
__func__, wcd9xxx->version);
+ pr_info("idbyte_0[%08x] idbyte_1[%08x] idbyte_2[%08x] idbyte_3[%08x]\n",
+ wcd9xxx->idbyte_0, wcd9xxx->idbyte_1,
+ wcd9xxx->idbyte_2, wcd9xxx->idbyte_3);
- if (wcd9xxx->idbyte_0 == 0x2) {
+ if (wcd9xxx->idbyte_0 == 0x2 && wcd9xxx->idbyte_1 == 0x0 &&
+ wcd9xxx->idbyte_2 == 0x0 && wcd9xxx->idbyte_3 == 0x1) {
wcd9xxx_dev = tabla_devs;
wcd9xxx_dev_size = ARRAY_SIZE(tabla_devs);
- } else if (wcd9xxx->idbyte_0 == 0x1) {
+ } else if (wcd9xxx->idbyte_0 == 0x1 && wcd9xxx->idbyte_1 == 0x0 &&
+ wcd9xxx->idbyte_2 == 0x0 && wcd9xxx->idbyte_3 == 0x1) {
wcd9xxx_dev = tabla1x_devs;
wcd9xxx_dev_size = ARRAY_SIZE(tabla1x_devs);
} else if (wcd9xxx->idbyte_0 == 0x0 && wcd9xxx->idbyte_1 == 0x0 &&
wcd9xxx->idbyte_2 == 0x2 && wcd9xxx->idbyte_3 == 0x1) {
wcd9xxx_dev = taiko_devs;
wcd9xxx_dev_size = ARRAY_SIZE(taiko_devs);
- } else if (wcd9xxx->idbyte_0 == 0x0) {
+ } else if ((wcd9xxx->idbyte_0 == 0x0 && wcd9xxx->idbyte_1 == 0x0 &&
+ wcd9xxx->idbyte_2 == 0x0 && wcd9xxx->idbyte_3 == 0x1) ||
+ (wcd9xxx->idbyte_0 == 0x1 && wcd9xxx->idbyte_1 == 0x0 &&
+ wcd9xxx->idbyte_2 == 0x1 && wcd9xxx->idbyte_3 == 0x1)) {
wcd9xxx_dev = sitar_devs;
wcd9xxx_dev_size = ARRAY_SIZE(sitar_devs);
}
@@ -1046,12 +1052,31 @@
return NULL;
}
+static int wcd9xxx_slim_get_laddr(struct slim_device *sb,
+ const u8 *e_addr, u8 e_len, u8 *laddr)
+{
+ int ret;
+ const unsigned long timeout = jiffies +
+ msecs_to_jiffies(SLIMBUS_PRESENT_TIMEOUT);
+
+ do {
+ ret = slim_get_logical_addr(sb, e_addr, e_len, laddr);
+ if (!ret)
+ break;
+ /* Give SLIMBUS time to report present and be ready. */
+ usleep_range(1000, 1000);
+ pr_debug_ratelimited("%s: retyring get logical addr\n",
+ __func__);
+ } while time_before(jiffies, timeout);
+
+ return ret;
+}
+
static int wcd9xxx_slim_probe(struct slim_device *slim)
{
struct wcd9xxx *wcd9xxx;
struct wcd9xxx_pdata *pdata;
int ret = 0;
- int sgla_retry_cnt;
if (slim->dev.of_node) {
dev_info(&slim->dev, "Platform data from device tree\n");
@@ -1096,10 +1121,12 @@
goto err_supplies;
}
- ret = slim_get_logical_addr(wcd9xxx->slim, wcd9xxx->slim->e_addr,
- ARRAY_SIZE(wcd9xxx->slim->e_addr), &wcd9xxx->slim->laddr);
+ ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim, wcd9xxx->slim->e_addr,
+ ARRAY_SIZE(wcd9xxx->slim->e_addr),
+ &wcd9xxx->slim->laddr);
if (ret) {
- pr_err("fail to get slimbus logical address %d\n", ret);
+ pr_err("%s: failed to get slimbus %s logical address: %d\n",
+ __func__, wcd9xxx->slim->name, ret);
goto err_reset;
}
wcd9xxx->read_dev = wcd9xxx_slim_read_device;
@@ -1108,11 +1135,8 @@
wcd9xxx->irq_base = pdata->irq_base;
wcd9xxx_pgd_la = wcd9xxx->slim->laddr;
- if (pdata->num_irqs < TABLA_NUM_IRQS) {
- pr_err("%s: Error, not enough interrupt lines allocated\n",
- __func__);
- goto err_reset;
- }
+ if (pdata->num_irqs < TABLA_NUM_IRQS)
+ pr_warn("%s: Not enough interrupt lines allocated\n", __func__);
wcd9xxx->slim_slave = &pdata->slimbus_slave_device;
@@ -1122,28 +1146,14 @@
goto err_reset;
}
- sgla_retry_cnt = 0;
-
- while (1) {
- ret = slim_get_logical_addr(wcd9xxx->slim_slave,
- wcd9xxx->slim_slave->e_addr,
- ARRAY_SIZE(wcd9xxx->slim_slave->e_addr),
- &wcd9xxx->slim_slave->laddr);
- if (ret) {
- if (sgla_retry_cnt++ < WCD9XXX_SLIM_GLA_MAX_RETRIES) {
- /* Give SLIMBUS slave time to report present
- and be ready.
- */
- usleep_range(1000, 1000);
- pr_debug("%s: retry slim_get_logical_addr()\n",
- __func__);
- continue;
- }
- pr_err("fail to get slimbus slave logical address"
- " %d\n", ret);
- goto err_slim_add;
- }
- break;
+ ret = wcd9xxx_slim_get_laddr(wcd9xxx->slim_slave,
+ wcd9xxx->slim_slave->e_addr,
+ ARRAY_SIZE(wcd9xxx->slim_slave->e_addr),
+ &wcd9xxx->slim_slave->laddr);
+ if (ret) {
+ pr_err("%s: failed to get slimbus %s logical address: %d\n",
+ __func__, wcd9xxx->slim->name, ret);
+ goto err_slim_add;
}
wcd9xxx_inf_la = wcd9xxx->slim_slave->laddr;
wcd9xxx_intf = WCD9XXX_INTERFACE_TYPE_SLIMBUS;
diff --git a/drivers/mfd/wcd9xxx-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c
index 71c68ac..b4cf435 100644
--- a/drivers/mfd/wcd9xxx-slimslave.c
+++ b/drivers/mfd/wcd9xxx-slimslave.c
@@ -535,7 +535,6 @@
unsigned int ch_cnt)
{
u16 grph = 0;
- u32 sph[SLIM_MAX_RX_PORTS] = {0};
int i = 0 , idx = 0;
int ret = 0;
struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
@@ -549,10 +548,9 @@
ret = -EINVAL;
goto err;
}
- sph[i] = rx[idx].sph;
grph = rx[idx].grph;
- pr_debug("%s: ch_num[%d] %d, idx %d, sph[%d] %x, grph %x\n",
- __func__, i, ch_num[i], idx, i, sph[i], grph);
+ pr_debug("%s: ch_num[%d] %d, idx %d, grph %x\n",
+ __func__, i, ch_num[i], idx, grph);
}
/* slim_control_ch (REMOVE) */
@@ -561,12 +559,6 @@
pr_err("%s: slim_control_ch failed ret[%d]\n", __func__, ret);
goto err;
}
- /* slim_disconnect_port */
- ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
- if (ret < 0) {
- pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
- __func__, ret);
- }
for (i = 0; i < ch_cnt; i++) {
idx = (ch_num[i] - BASE_CH_NUM - sh_ch.rx_port_start_offset);
rx[idx].grph = 0;
@@ -580,7 +572,6 @@
unsigned int ch_cnt)
{
u16 grph = 0;
- u32 sph[SLIM_MAX_TX_PORTS] = {0};
int ret = 0;
int i = 0 , idx = 0;
struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
@@ -594,15 +585,8 @@
ret = -EINVAL;
goto err;
}
- sph[i] = tx[idx].sph;
grph = tx[idx].grph;
}
- /* slim_disconnect_port */
- ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
- if (ret < 0) {
- pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
- __func__, ret);
- }
/* slim_control_ch (REMOVE) */
ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
if (ret < 0) {
@@ -633,3 +617,48 @@
return ret;
}
EXPORT_SYMBOL_GPL(wcd9xxx_get_slave_port);
+
+int wcd9xxx_disconnect_port(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
+ unsigned int ch_cnt, unsigned int rx_tx)
+{
+ u32 sph[SLIM_MAX_TX_PORTS] = {0};
+ int i = 0 , idx = 0;
+ int ret = 0;
+ struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
+ struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
+
+ pr_debug("%s: ch_cnt[%d], rx_tx flag = %d\n", __func__, ch_cnt, rx_tx);
+ for (i = 0; i < ch_cnt; i++) {
+ /* rx_tx will be 1 for rx, 0 for tx */
+ if (rx_tx) {
+ idx = (ch_num[i] - BASE_CH_NUM -
+ sh_ch.rx_port_start_offset);
+ if (idx < 0) {
+ pr_err("%s: Invalid index found for RX = %d\n",
+ __func__, idx);
+ ret = -EINVAL;
+ goto err;
+ }
+ sph[i] = rx[idx].sph;
+ } else {
+ idx = (ch_num[i] - BASE_CH_NUM);
+ if (idx < 0) {
+ pr_err("%s:Invalid index found for TX = %d\n",
+ __func__, idx);
+ ret = -EINVAL;
+ goto err;
+ }
+ sph[i] = tx[idx].sph;
+ }
+ }
+
+ /* slim_disconnect_port */
+ ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
+ if (ret < 0) {
+ pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
+ __func__, ret);
+ }
+err:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_disconnect_port);
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 590aa58..d82c353 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -409,7 +409,6 @@
if (index == EXT_CSD_BKOPS_START)
return 0;
- mmc_delay(1);
/* Must check status to be sure of no errors */
do {
err = mmc_send_status(card, &status);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index b22e2f0..a86798d 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -725,12 +725,6 @@
mmc_hostname(host->mmc), __func__,
notify->event_id);
- if (msmsdcc_is_dml_busy(host)) {
- /* oops !!! this should never happen. */
- pr_err("%s: %s: Received SPS EOT event"
- " but DML HW is still busy !!!\n",
- mmc_hostname(host->mmc), __func__);
- }
/*
* Got End of transfer event!!! Check if all of the data
* has been transferred?
@@ -1241,25 +1235,12 @@
if (is_dma_mode(host) && !msmsdcc_config_dma(host, data)) {
datactrl |= MCI_DPSM_DMAENABLE;
} else if (is_sps_mode(host)) {
- if (!msmsdcc_is_dml_busy(host)) {
- if (!msmsdcc_sps_start_xfer(host, data)) {
- /* Now kick start DML transfer */
- mb();
- msmsdcc_dml_start_xfer(host, data);
- datactrl |= MCI_DPSM_DMAENABLE;
- host->sps.busy = 1;
- }
- } else {
- /*
- * Can't proceed with new transfer as
- * previous trasnfer is already in progress.
- * There is no point of going into PIO mode
- * as well. Is this a time to do kernel panic?
- */
- pr_err("%s: %s: DML HW is busy!!!"
- " Can't perform new SPS transfers"
- " now\n", mmc_hostname(host->mmc),
- __func__);
+ if (!msmsdcc_sps_start_xfer(host, data)) {
+ /* Now kick start DML transfer */
+ mb();
+ msmsdcc_dml_start_xfer(host, data);
+ datactrl |= MCI_DPSM_DMAENABLE;
+ host->sps.busy = 1;
}
}
}
@@ -1370,9 +1351,11 @@
*/
if (!(data->mrq->cmd->opcode == MMC_BUS_TEST_W
|| data->mrq->cmd->opcode == MMC_BUS_TEST_R)) {
- pr_err("%s: CMD%d: Data timeout\n",
+ pr_err("%s: CMD%d: Data timeout. DAT0 => %d\n",
mmc_hostname(host->mmc),
- data->mrq->cmd->opcode);
+ data->mrq->cmd->opcode,
+ (readl_relaxed(host->base
+ + MCI_TEST_INPUT) & 0x2) ? 1 : 0);
data->error = -ETIMEDOUT;
msmsdcc_dump_sdcc_state(host);
}
@@ -2191,6 +2174,18 @@
return rc;
}
+static inline int msmsdcc_vreg_get_voltage(struct msm_mmc_reg_data *vreg)
+{
+ int rc = 0;
+
+ rc = regulator_get_voltage(vreg->reg);
+ if (rc < 0)
+ pr_err("%s: regulator_get_voltage(%s) failed. rc=%d\n",
+ __func__, vreg->name, rc);
+
+ return rc;
+}
+
static inline int msmsdcc_vreg_set_optimum_mode(struct msm_mmc_reg_data *vreg,
int uA_load)
{
@@ -2435,6 +2430,82 @@
VDD_IO_SET_LEVEL,
};
+/*
+ * This function returns the current VDD IO voltage level.
+ * Returns negative value if it fails to read the voltage level
+ * Returns 0 if regulator was disabled or if VDD_IO (and VDD)
+ * regulator were not defined for host.
+ */
+static int msmsdcc_get_vdd_io_vol(struct msmsdcc_host *host)
+{
+ int rc = 0;
+
+ if (host->plat->vreg_data) {
+ struct msm_mmc_reg_data *io_reg =
+ host->plat->vreg_data->vdd_io_data;
+
+ /*
+ * If vdd_io is not defined, then we can consider that
+ * IO voltage is same as VDD.
+ */
+ if (!io_reg)
+ io_reg = host->plat->vreg_data->vdd_data;
+
+ if (io_reg && io_reg->is_enabled)
+ rc = msmsdcc_vreg_get_voltage(io_reg);
+ }
+
+ return rc;
+}
+
+/*
+ * This function updates the IO pad power switch bit in MCI_CLK register
+ * based on currrent IO pad voltage level.
+ * NOTE: This function assumes that host lock was not taken by caller.
+ */
+static void msmsdcc_update_io_pad_pwr_switch(struct msmsdcc_host *host)
+{
+ int rc = 0;
+ unsigned long flags;
+
+ if (!is_io_pad_pwr_switch(host))
+ return;
+
+ rc = msmsdcc_get_vdd_io_vol(host);
+
+ spin_lock_irqsave(&host->lock, flags);
+ /*
+ * Dual voltage pad is the SDCC's (chipset) functionality and not all
+ * the SDCC instances support the dual voltage pads.
+ * For dual-voltage pad (1.8v/3.3v), SW should set IO_PAD_PWR_SWITCH
+ * bit before using the pads in 1.8V mode.
+ * For regular, not dual-voltage pads (including eMMC 1.2v/1.8v pads),
+ * IO_PAD_PWR_SWITCH bit is a don't care.
+ * But we don't have an option to know (by reading some SDCC register)
+ * that a particular SDCC instance supports dual voltage pads or not,
+ * so we simply set the IO_PAD_PWR_SWITCH bit for low voltage IO
+ * (1.8v/1.2v). For regular (not dual-voltage pads), this bit value
+ * is anyway ignored.
+ */
+ if (rc > 0 && rc < 2700000)
+ host->io_pad_pwr_switch = 1;
+ else
+ host->io_pad_pwr_switch = 0;
+
+ if (atomic_read(&host->clks_on)) {
+ if (host->io_pad_pwr_switch)
+ writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
+ IO_PAD_PWR_SWITCH),
+ host->base + MMCICLOCK);
+ else
+ writel_relaxed((readl_relaxed(host->base + MMCICLOCK) &
+ ~IO_PAD_PWR_SWITCH),
+ host->base + MMCICLOCK);
+ msmsdcc_sync_reg_wr(host);
+ }
+ spin_unlock_irqrestore(&host->lock, flags);
+}
+
static int msmsdcc_set_vdd_io_vol(struct msmsdcc_host *host,
enum vdd_io_level level,
unsigned int voltage_level)
@@ -2736,6 +2807,7 @@
* present or during system suspend).
*/
msmsdcc_set_vdd_io_vol(host, VDD_IO_LOW, 0);
+ msmsdcc_update_io_pad_pwr_switch(host);
msmsdcc_setup_pins(host, false);
break;
case MMC_POWER_UP:
@@ -2744,6 +2816,7 @@
msmsdcc_cfg_mpm_sdiowakeup(host, SDC_DAT1_ENABLE);
msmsdcc_set_vdd_io_vol(host, VDD_IO_HIGH, 0);
+ msmsdcc_update_io_pad_pwr_switch(host);
msmsdcc_setup_pins(host, true);
break;
case MMC_POWER_ON:
@@ -3156,10 +3229,6 @@
/* Select free running MCLK as input clock of cm_dll_sdc4 */
clk |= (2 << 23);
- /* Clear IO_PAD_PWR_SWITCH while powering off the card */
- if (!ios->vdd)
- host->io_pad_pwr_switch = 0;
-
if (host->io_pad_pwr_switch)
clk |= IO_PAD_PWR_SWITCH;
@@ -3291,7 +3360,10 @@
{
struct device *dev = mmc_dev(host->mmc);
- pr_info("%s: RPM: runtime_status=%d, usage_count=%d,"
+ pr_err("%s: PM: sdcc_suspended=%d, pending_resume=%d, sdcc_suspending=%d\n",
+ mmc_hostname(host->mmc), host->sdcc_suspended,
+ host->pending_resume, host->sdcc_suspending);
+ pr_err("%s: RPM: runtime_status=%d, usage_count=%d,"
" is_suspended=%d, disable_depth=%d, runtime_error=%d,"
" request_pending=%d, request=%d\n",
mmc_hostname(host->mmc), dev->power.runtime_status,
@@ -3312,8 +3384,7 @@
if (mmc->card && mmc_card_sdio(mmc->card))
goto out;
- if (host->sdcc_suspended && host->pending_resume &&
- !pm_runtime_suspended(dev)) {
+ if (host->sdcc_suspended && host->pending_resume) {
host->pending_resume = false;
pm_runtime_get_noresume(dev);
rc = msmsdcc_runtime_resume(dev);
@@ -3334,8 +3405,8 @@
skip_get_sync:
if (rc < 0) {
- pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
- __func__, rc);
+ WARN(1, "%s: %s: failed with error %d\n", mmc_hostname(mmc),
+ __func__, rc);
msmsdcc_print_rpm_info(host);
return rc;
}
@@ -3361,15 +3432,9 @@
rc = pm_runtime_put_sync(mmc->parent);
- /*
- * Ignore -EAGAIN as that is not fatal, it means that
- * either runtime usage count is non-zero or the runtime
- * pm itself is disabled or not in proper state to process
- * idle notification.
- */
- if (rc < 0 && (rc != -EAGAIN)) {
- pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
- __func__, rc);
+ if (rc < 0) {
+ WARN(1, "%s: %s: failed with error %d\n", mmc_hostname(mmc),
+ __func__, rc);
msmsdcc_print_rpm_info(host);
return rc;
}
@@ -3448,14 +3513,12 @@
unsigned long flags;
int rc = 0;
- spin_lock_irqsave(&host->lock, flags);
- host->io_pad_pwr_switch = 0;
- spin_unlock_irqrestore(&host->lock, flags);
-
switch (ios->signal_voltage) {
case MMC_SIGNAL_VOLTAGE_330:
/* Set VDD IO to high voltage range (2.7v - 3.6v) */
rc = msmsdcc_set_vdd_io_vol(host, VDD_IO_HIGH, 0);
+ if (!rc)
+ msmsdcc_update_io_pad_pwr_switch(host);
goto out;
case MMC_SIGNAL_VOLTAGE_180:
break;
@@ -3466,6 +3529,8 @@
* DDR 1.2V mode.
*/
rc = msmsdcc_set_vdd_io_vol(host, VDD_IO_SET_LEVEL, 1200000);
+ if (!rc)
+ msmsdcc_update_io_pad_pwr_switch(host);
goto out;
default:
/* invalid selection. don't do anything */
@@ -3504,12 +3569,7 @@
if (rc)
goto out;
- spin_lock_irqsave(&host->lock, flags);
- writel_relaxed((readl_relaxed(host->base + MMCICLOCK) |
- IO_PAD_PWR_SWITCH), host->base + MMCICLOCK);
- msmsdcc_sync_reg_wr(host);
- host->io_pad_pwr_switch = 1;
- spin_unlock_irqrestore(&host->lock, flags);
+ msmsdcc_update_io_pad_pwr_switch(host);
/* Wait 5 ms for the voltage regulater in the card to become stable. */
usleep_range(5000, 5500);
@@ -4789,10 +4849,10 @@
if (!base)
return;
- pr_info("===== %s: Register Dumps @phys_base=0x%x, @virt_base=0x%x"
+ pr_err("===== %s: Register Dumps @phys_base=0x%x, @virt_base=0x%x"
" =====\n", name, phys_base, (u32)base);
for (i = 0; i < no_of_regs; i = i + 4) {
- pr_info("Reg=0x%.2x: 0x%.8x, 0x%.8x, 0x%.8x, 0x%.8x\n", i*4,
+ pr_err("Reg=0x%.2x: 0x%.8x, 0x%.8x, 0x%.8x, 0x%.8x\n", i*4,
(u32)readl_relaxed(base + i*4),
(u32)readl_relaxed(base + ((i+1)*4)),
(u32)readl_relaxed(base + ((i+2)*4)),
@@ -4803,25 +4863,29 @@
static void msmsdcc_dump_sdcc_state(struct msmsdcc_host *host)
{
/* Dump current state of SDCC clocks, power and irq */
- pr_info("%s: SDCC PWR is %s\n", mmc_hostname(host->mmc),
+ pr_err("%s: SDCC PWR is %s\n", mmc_hostname(host->mmc),
(host->pwr ? "ON" : "OFF"));
- pr_info("%s: SDCC clks are %s, MCLK rate=%d\n",
+ pr_err("%s: SDCC clks are %s, MCLK rate=%d\n",
mmc_hostname(host->mmc),
(atomic_read(&host->clks_on) ? "ON" : "OFF"),
(u32)clk_get_rate(host->clk));
- pr_info("%s: SDCC irq is %s\n", mmc_hostname(host->mmc),
+ pr_err("%s: SDCC irq is %s\n", mmc_hostname(host->mmc),
(host->sdcc_irq_disabled ? "disabled" : "enabled"));
/* Now dump SDCC registers. Don't print FIFO registers */
- if (atomic_read(&host->clks_on))
+ if (atomic_read(&host->clks_on)) {
msmsdcc_print_regs("SDCC-CORE", host->base,
host->core_memres->start, 28);
+ pr_err("%s: MCI_TEST_INPUT = 0x%.8x\n",
+ mmc_hostname(host->mmc),
+ readl_relaxed(host->base + MCI_TEST_INPUT));
+ }
if (host->curr.data) {
if (!msmsdcc_is_dma_possible(host, host->curr.data))
- pr_info("%s: PIO mode\n", mmc_hostname(host->mmc));
+ pr_err("%s: PIO mode\n", mmc_hostname(host->mmc));
else if (is_dma_mode(host))
- pr_info("%s: ADM mode: busy=%d, chnl=%d, crci=%d\n",
+ pr_err("%s: ADM mode: busy=%d, chnl=%d, crci=%d\n",
mmc_hostname(host->mmc), host->dma.busy,
host->dma.channel, host->dma.crci);
else if (is_sps_mode(host)) {
@@ -4829,16 +4893,16 @@
msmsdcc_print_regs("SDCC-DML", host->dml_base,
host->dml_memres->start,
16);
- pr_info("%s: SPS mode: busy=%d\n",
+ pr_err("%s: SPS mode: busy=%d\n",
mmc_hostname(host->mmc), host->sps.busy);
}
- pr_info("%s: xfer_size=%d, data_xfered=%d, xfer_remain=%d\n",
+ pr_err("%s: xfer_size=%d, data_xfered=%d, xfer_remain=%d\n",
mmc_hostname(host->mmc), host->curr.xfer_size,
host->curr.data_xfered, host->curr.xfer_remain);
}
- pr_info("%s: got_dataend=%d, prog_enable=%d,"
+ pr_err("%s: got_dataend=%d, prog_enable=%d,"
" wait_for_auto_prog_done=%d, got_auto_prog_done=%d,"
" req_tout_ms=%d\n", mmc_hostname(host->mmc),
host->curr.got_dataend, host->prog_enable,
@@ -5123,7 +5187,9 @@
pdata->status_gpio = of_get_named_gpio_flags(np,
"cd-gpios", 0, &flags);
if (gpio_is_valid(pdata->status_gpio)) {
- pdata->status_irq = gpio_to_irq(pdata->status_gpio);
+ struct platform_device *pdev = container_of(dev,
+ struct platform_device, dev);
+ pdata->status_irq = platform_get_irq_byname(pdev, "status_irq");
pdata->is_status_gpio_active_low = flags & OF_GPIO_ACTIVE_LOW;
}
@@ -6262,6 +6328,7 @@
wake_unlock(&host->sdio_suspend_wlock);
}
+ host->pending_resume = false;
pr_debug("%s: %s: end\n", mmc_hostname(mmc), __func__);
return 0;
}
@@ -6334,7 +6401,13 @@
if (mmc->card && mmc_card_sdio(mmc->card))
rc = msmsdcc_runtime_resume(dev);
- else
+ /*
+ * As runtime PM is enabled before calling the device's platform resume
+ * callback, we use the pm_runtime_suspended API to know if SDCC is
+ * really runtime suspended or not and set the pending_resume flag only
+ * if its not runtime suspended.
+ */
+ else if (!pm_runtime_suspended(dev))
host->pending_resume = true;
if (host->plat->status_irq) {
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 3b1dbc7..236785d 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -428,6 +428,7 @@
#define MSMSDCC_SW_RST (1 << 5)
#define MSMSDCC_SW_RST_CFG (1 << 6)
#define MSMSDCC_WAIT_FOR_TX_RX (1 << 7)
+#define MSMSDCC_IO_PAD_PWR_SWITCH (1 << 8)
#define set_hw_caps(h, val) ((h)->hw_caps |= val)
#define is_sps_mode(h) ((h)->hw_caps & MSMSDCC_SPS_BAM_SUP)
@@ -438,6 +439,7 @@
#define is_sw_hard_reset(h) ((h)->hw_caps & MSMSDCC_SW_RST)
#define is_sw_reset_save_config(h) ((h)->hw_caps & MSMSDCC_SW_RST_CFG)
#define is_wait_for_tx_rx_active(h) ((h)->hw_caps & MSMSDCC_WAIT_FOR_TX_RX)
+#define is_io_pad_pwr_switch(h) ((h)->hw_caps & MSMSDCC_IO_PAD_PWR_SWITCH)
/* Set controller capabilities based on version */
static inline void set_default_hw_caps(struct msmsdcc_host *host)
@@ -457,7 +459,7 @@
if (version) /* SDCC v4 and greater */
host->hw_caps |= MSMSDCC_AUTO_PROG_DONE |
MSMSDCC_SOFT_RESET | MSMSDCC_REG_WR_ACTIVE
- | MSMSDCC_WAIT_FOR_TX_RX;
+ | MSMSDCC_WAIT_FOR_TX_RX | MSMSDCC_IO_PAD_PWR_SWITCH;
if (version >= 0x2D) /* SDCC v4 2.1.0 and greater */
host->hw_caps |= MSMSDCC_SW_RST | MSMSDCC_SW_RST_CFG;
diff --git a/drivers/net/ethernet/msm/msm_rmnet_bam.c b/drivers/net/ethernet/msm/msm_rmnet_bam.c
index fbe8d3c..295c55c 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_bam.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_bam.c
@@ -29,6 +29,7 @@
#include <linux/if_arp.h>
#include <linux/msm_rmnet.h>
#include <linux/platform_device.h>
+#include <net/pkt_sched.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
@@ -638,6 +639,16 @@
dev->name);
break;
+ case RMNET_IOCTL_FLOW_ENABLE:
+ tc_qdisc_flow_control(dev, (u32)ifr->ifr_data, 1);
+ DBG0("[%s] rmnet_ioctl(): enabled flow", dev->name);
+ break;
+
+ case RMNET_IOCTL_FLOW_DISABLE:
+ tc_qdisc_flow_control(dev, (u32)ifr->ifr_data, 0);
+ DBG0("[%s] rmnet_ioctl(): disabled flow", dev->name);
+ break;
+
case RMNET_IOCTL_GET_QOS: /* Get QoS header state */
ifr->ifr_ifru.ifru_data =
(void *)(p->operation_mode & RMNET_MODE_QOS);
diff --git a/drivers/net/usb/rmnet_usb_ctrl.c b/drivers/net/usb/rmnet_usb_ctrl.c
index 186d07d..f6e4b00 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.c
+++ b/drivers/net/usb/rmnet_usb_ctrl.c
@@ -271,7 +271,7 @@
__func__, status);
}
-static int rmnet_usb_ctrl_start_rx(struct rmnet_ctrl_dev *dev)
+int rmnet_usb_ctrl_start_rx(struct rmnet_ctrl_dev *dev)
{
int retval = 0;
@@ -298,18 +298,6 @@
return 0;
}
-int rmnet_usb_ctrl_start(struct rmnet_ctrl_dev *dev)
-{
- int status = 0;
-
- mutex_lock(&dev->dev_lock);
- if (dev->is_opened)
- status = rmnet_usb_ctrl_start_rx(dev);
- mutex_unlock(&dev->dev_lock);
-
- return status;
-}
-
static int rmnet_usb_ctrl_alloc_rx(struct rmnet_ctrl_dev *dev)
{
int retval = -ENOMEM;
diff --git a/drivers/net/usb/rmnet_usb_ctrl.h b/drivers/net/usb/rmnet_usb_ctrl.h
index 3259940..7a84817 100644
--- a/drivers/net/usb/rmnet_usb_ctrl.h
+++ b/drivers/net/usb/rmnet_usb_ctrl.h
@@ -73,7 +73,7 @@
extern struct rmnet_ctrl_dev *ctrl_dev[];
-extern int rmnet_usb_ctrl_start(struct rmnet_ctrl_dev *);
+extern int rmnet_usb_ctrl_start_rx(struct rmnet_ctrl_dev *);
extern int rmnet_usb_ctrl_stop_rx(struct rmnet_ctrl_dev *);
extern int rmnet_usb_ctrl_init(void);
extern void rmnet_usb_ctrl_exit(void);
diff --git a/drivers/net/usb/rmnet_usb_data.c b/drivers/net/usb/rmnet_usb_data.c
index 4f8039e..b8c6140 100644
--- a/drivers/net/usb/rmnet_usb_data.c
+++ b/drivers/net/usb/rmnet_usb_data.c
@@ -151,7 +151,7 @@
retval = usbnet_resume(iface);
if (!retval) {
if (oldstate & PM_EVENT_SUSPEND)
- retval = rmnet_usb_ctrl_start(dev);
+ retval = rmnet_usb_ctrl_start_rx(dev);
}
fail:
return retval;
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index d26c845..1867fe2 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -89,6 +89,8 @@
static struct workqueue_struct *usbnet_wq;
+static DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup);
+
/* use ethtool to change the level for any given device */
static int msg_level = -1;
module_param (msg_level, int, 0);
@@ -664,7 +666,6 @@
// precondition: never called in_interrupt
static void usbnet_terminate_urbs(struct usbnet *dev)
{
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(unlink_wakeup);
DECLARE_WAITQUEUE(wait, current);
int temp;
@@ -1240,7 +1241,7 @@
// waiting for all pending urbs to complete?
if (dev->wait) {
if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) {
- wake_up (dev->wait);
+ wake_up(&unlink_wakeup);
}
// or are we maybe short a few urbs?
diff --git a/drivers/net/wireless/libra/libra_sdioif.c b/drivers/net/wireless/libra/libra_sdioif.c
index aa7970a..1d72a16 100644
--- a/drivers/net/wireless/libra/libra_sdioif.c
+++ b/drivers/net/wireless/libra/libra_sdioif.c
@@ -27,6 +27,12 @@
/* SDIO Card ID / Device ID */
static unsigned short libra_sdio_card_id;
+/* completion variables */
+struct completion gCard_rem_event_var;
+EXPORT_SYMBOL(gCard_rem_event_var);
+struct completion gShutdown_event_var;
+EXPORT_SYMBOL(gShutdown_event_var);
+
static suspend_handler_t *libra_suspend_hldr;
static resume_handler_t *libra_resume_hldr;
static notify_card_removal_t *libra_notify_card_removal_hdlr;
diff --git a/drivers/net/wireless/wcnss/wcnss_riva.c b/drivers/net/wireless/wcnss/wcnss_riva.c
index 23365ff..2d9ad82 100644
--- a/drivers/net/wireless/wcnss/wcnss_riva.c
+++ b/drivers/net/wireless/wcnss/wcnss_riva.c
@@ -64,7 +64,7 @@
{"iris_vddxo", VREG_NULL_CONFIG, 1800000, 0, 1800000, 10000, NULL},
{"iris_vddrfa", VREG_NULL_CONFIG, 1300000, 0, 1300000, 100000, NULL},
{"iris_vddpa", VREG_NULL_CONFIG, 2900000, 0, 3000000, 515000, NULL},
- {"iris_vdddig", VREG_NULL_CONFIG, 1200000, 0, 1200000, 10000, NULL},
+ {"iris_vdddig", VREG_NULL_CONFIG, 1200000, 0, 1225000, 10000, NULL},
};
static struct vregs_info riva_vregs[] = {
diff --git a/drivers/platform/msm/sps/bam.c b/drivers/platform/msm/sps/bam.c
index 31b405a..eb9e8ee 100644
--- a/drivers/platform/msm/sps/bam.c
+++ b/drivers/platform/msm/sps/bam.c
@@ -643,10 +643,10 @@
*/
int bam_init(void *base, u32 ee,
u16 summing_threshold,
- u32 irq_mask, u32 *version, u32 *num_pipes)
+ u32 irq_mask, u32 *version,
+ u32 *num_pipes, u32 p_rst)
{
- /* disable bit#11 because of HW bug */
- u32 cfg_bits = 0xffffffff & ~(1 << 11);
+ u32 cfg_bits;
u32 ver = 0;
SPS_DBG2("sps:%s:bam=0x%x(va).ee=%d.", __func__, (u32) base, ee);
@@ -658,7 +658,7 @@
(u32) base, ver);
return -ENODEV;
} else
- SPS_INFO("sps:REVISION of BAM 0x%x is 0x%x.\n",
+ SPS_DBG2("sps:REVISION of BAM 0x%x is 0x%x.\n",
(u32) base, ver);
if (summing_threshold == 0) {
@@ -667,6 +667,11 @@
"use default 4.\n", (u32) base);
}
+ if (p_rst)
+ cfg_bits = 0xffffffff & ~(3 << 11);
+ else
+ cfg_bits = 0xffffffff & ~(1 << 11);
+
bam_write_reg_field(base, CTRL, BAM_SW_RST, 1);
/* No delay needed */
bam_write_reg_field(base, CTRL, BAM_SW_RST, 0);
@@ -1398,3 +1403,32 @@
SPS_INFO("-------------------- end of FIFO --------------------\n");
}
+
+/* output BAM_TEST_BUS_REG with specified TEST_BUS_SEL */
+void print_bam_test_bus_reg(void *base, u32 tb_sel)
+{
+ u32 i;
+ u32 test_bus_selection[] = {0x1, 0x2, 0x3, 0x4, 0xD, 0x10,
+ 0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
+ u32 size = sizeof(test_bus_selection) / sizeof(u32);
+
+ if ((base == NULL) || (tb_sel == 0))
+ return;
+
+ SPS_INFO("\nsps:Specified TEST_BUS_SEL value: 0x%x\n", tb_sel);
+ bam_write_reg_field(base, TEST_BUS_SEL, BAM_TESTBUS_SEL, tb_sel);
+ SPS_INFO("sps:BAM_TEST_BUS_REG: 0x%x when TEST_BUS_SEL: 0x%x\n\n",
+ bam_read_reg(base, TEST_BUS_REG),
+ bam_read_reg_field(base, TEST_BUS_SEL, BAM_TESTBUS_SEL));
+
+ /* 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),
+ bam_read_reg_field(base, TEST_BUS_SEL,
+ BAM_TESTBUS_SEL));
+ }
+}
diff --git a/drivers/platform/msm/sps/bam.h b/drivers/platform/msm/sps/bam.h
index 3521ffa..c183fcd 100644
--- a/drivers/platform/msm/sps/bam.h
+++ b/drivers/platform/msm/sps/bam.h
@@ -102,13 +102,16 @@
*
* @num_pipes - return number of pipes
*
+ * @p_rst - ignore external block pipe reset
+ *
* @return 0 on success, negative value on error
*
*/
int bam_init(void *base,
u32 ee,
u16 summing_threshold,
- u32 irq_mask, u32 *version, u32 *num_pipes);
+ u32 irq_mask, u32 *version,
+ u32 *num_pipes, u32 p_rst);
/**
* Initialize BAM device security execution environment
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 656d1fb..5bbcc84 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -89,6 +89,9 @@
u8 debug_level_option;
u8 print_limit_option;
u8 reg_dump_option;
+u32 testbus_sel;
+u32 bam_pipe_sel;
+
static char *debugfs_buf;
static u32 debugfs_buf_size;
@@ -101,6 +104,8 @@
struct dentry *dfile_debug_level_option;
struct dentry *dfile_print_limit_option;
struct dentry *dfile_reg_dump_option;
+struct dentry *dfile_testbus_sel;
+struct dentry *dfile_bam_pipe_sel;
struct dentry *dfile_bam_addr;
static struct sps_bam *phy2bam(u32 phys_addr);
@@ -325,30 +330,53 @@
for (i = 0; i < num_pipes; i++)
print_bam_pipe_selected_reg(vir_addr, i);
break;
- case 5: /* output selected registers of some pipes */
+ case 5: /* output selected registers of selected pipes */
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_selected_reg(vir_addr, i);
+ break;
+ case 6: /* output selected registers of typical pipes */
print_bam_pipe_selected_reg(vir_addr, 4);
print_bam_pipe_selected_reg(vir_addr, 5);
break;
- case 6: /* output desc FIFO of all active pipes */
+ case 7: /* output desc FIFO of all pipes */
for (i = 0; i < num_pipes; i++)
print_bam_pipe_desc_fifo(vir_addr, i);
break;
- case 7: /* output desc FIFO of some pipes */
+ case 8: /* output desc FIFO of selected pipes */
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i))
+ print_bam_pipe_desc_fifo(vir_addr, i);
+ break;
+ case 9: /* output desc FIFO of typical pipes */
print_bam_pipe_desc_fifo(vir_addr, 4);
print_bam_pipe_desc_fifo(vir_addr, 5);
break;
- case 8: /* output selected registers and valid desc FIFO of all pipes */
+ case 10: /* output selected registers and desc FIFO of all pipes */
for (i = 0; i < num_pipes; i++) {
print_bam_pipe_selected_reg(vir_addr, i);
print_bam_pipe_desc_fifo(vir_addr, i);
}
break;
- case 9: /* output selected registers and desc FIFO of some pipes */
+ case 11: /* output selected registers and desc FIFO of selected pipes */
+ for (i = 0; i < num_pipes; i++)
+ if (bam_pipe_sel & (1UL << i)) {
+ print_bam_pipe_selected_reg(vir_addr, i);
+ print_bam_pipe_desc_fifo(vir_addr, i);
+ }
+ break;
+ case 12: /* output selected registers and desc FIFO of typical pipes */
print_bam_pipe_selected_reg(vir_addr, 4);
print_bam_pipe_desc_fifo(vir_addr, 4);
print_bam_pipe_selected_reg(vir_addr, 5);
print_bam_pipe_desc_fifo(vir_addr, 5);
break;
+ case 13: /* output BAM_TEST_BUS_REG */
+ if (testbus_sel)
+ print_bam_test_bus_reg(vir_addr, testbus_sel);
+ else
+ pr_info("sps:TEST_BUS_SEL should NOT be zero.");
+ break;
default:
pr_info("sps:no dump option is chosen yet.");
}
@@ -367,6 +395,8 @@
debug_level_option = 0;
print_limit_option = 0;
reg_dump_option = 0;
+ testbus_sel = 0;
+ bam_pipe_sel = 0;
debugfs_buf_size = 0;
debugfs_buf_used = 0;
wraparound = false;
@@ -416,6 +446,20 @@
goto reg_dump_option_err;
}
+ dfile_testbus_sel = debugfs_create_u32("testbus_sel", 0666,
+ dent, &testbus_sel);
+ if (!dfile_testbus_sel || IS_ERR(dfile_testbus_sel)) {
+ pr_err("sps:fail to create debug_fs file for testbus_sel.\n");
+ goto testbus_sel_err;
+ }
+
+ dfile_bam_pipe_sel = debugfs_create_u32("bam_pipe_sel", 0666,
+ dent, &bam_pipe_sel);
+ if (!dfile_bam_pipe_sel || IS_ERR(dfile_bam_pipe_sel)) {
+ pr_err("sps:fail to create debug_fs file for bam_pipe_sel.\n");
+ goto bam_pipe_sel_err;
+ }
+
dfile_bam_addr = debugfs_create_file("bam_addr", 0666,
dent, 0, &sps_bam_addr_ops);
if (!dfile_bam_addr || IS_ERR(dfile_bam_addr)) {
@@ -427,6 +471,10 @@
return;
bam_addr_err:
+ debugfs_remove(dfile_bam_pipe_sel);
+bam_pipe_sel_err:
+ debugfs_remove(dfile_testbus_sel);
+testbus_sel_err:
debugfs_remove(dfile_reg_dump_option);
reg_dump_option_err:
debugfs_remove(dfile_print_limit_option);
@@ -452,6 +500,10 @@
debugfs_remove(dfile_print_limit_option);
if (dfile_reg_dump_option)
debugfs_remove(dfile_reg_dump_option);
+ if (dfile_testbus_sel)
+ debugfs_remove(dfile_testbus_sel);
+ if (dfile_bam_pipe_sel)
+ debugfs_remove(dfile_bam_pipe_sel);
if (dfile_bam_addr)
debugfs_remove(dfile_bam_addr);
if (dent)
@@ -462,7 +514,8 @@
#endif
/* Get the debug info of BAM registers and descriptor FIFOs */
-int sps_get_bam_debug_info(u32 dev, u32 option, u32 para)
+int sps_get_bam_debug_info(u32 dev, u32 option, u32 para,
+ u32 tb_sel, u8 pre_level)
{
int res = 0;
struct sps_bam *bam;
@@ -545,6 +598,12 @@
print_bam_pipe_selected_reg(vir_addr, 5);
print_bam_pipe_desc_fifo(vir_addr, 5);
break;
+ case 13: /* output BAM_TEST_BUS_REG */
+ if (tb_sel)
+ print_bam_test_bus_reg(vir_addr, tb_sel);
+ else
+ pr_info("sps:TEST_BUS_SEL should NOT be zero.");
+ break;
default:
pr_info("sps:no option is chosen yet.");
}
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index 245ccd2..e3be11d 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -254,7 +254,8 @@
dev->props.ee,
(u16) dev->props.summing_threshold,
irq_mask,
- &dev->version, &num_pipes);
+ &dev->version, &num_pipes,
+ dev->props.options & SPS_BAM_NO_EXT_P_RST);
else
/* No, so just verify that it is enabled */
rc = bam_check(dev->base, &dev->version, &num_pipes);
@@ -401,7 +402,7 @@
}
dev->state |= BAM_STATE_ENABLED;
- SPS_DBG2("sps:BAM 0x%x enabled: ver: %d, number of pipes: %d",
+ SPS_INFO("sps:BAM 0x%x enabled: ver:0x%x, number of pipes:%d",
BAM_ID(dev), dev->version, dev->props.num_pipes);
return 0;
}
diff --git a/drivers/platform/msm/sps/spsi.h b/drivers/platform/msm/sps/spsi.h
index 43a50bd..8a5deff 100644
--- a/drivers/platform/msm/sps/spsi.h
+++ b/drivers/platform/msm/sps/spsi.h
@@ -200,6 +200,9 @@
/* output descriptor FIFO of a pipe */
void print_bam_pipe_desc_fifo(void *, u32);
+/* output BAM_TEST_BUS_REG */
+void print_bam_test_bus_reg(void *, u32);
+
/**
* Translate physical to virtual address
*
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index f6b50a0..551c0a7 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <linux/io.h>
#include <linux/stat.h>
#include <linux/module.h>
@@ -54,11 +55,14 @@
static struct usb_bam_connect_info usb_bam_connections[CONNECTIONS_NUM];
static struct usb_bam_pipe_connect ***msm_usb_bam_connections_info;
static struct usb_bam_pipe_connect *bam_connection_arr;
+void __iomem *qscratch_ram1_reg;
+struct clk *mem_clk;
+struct clk *mem_iface_clk;
static int connect_pipe(u8 conn_idx, enum usb_bam_pipe_dir pipe_dir,
u32 *usb_pipe_idx)
{
- int ret;
+ int ret, ram1_value;
struct sps_pipe **pipe = &sps_pipes[conn_idx][pipe_dir];
struct sps_connect *connection =
&sps_connections[conn_idx][pipe_dir];
@@ -77,13 +81,13 @@
ret = sps_get_config(*pipe, connection);
if (ret) {
pr_err("%s: tx get config failed %d\n", __func__, ret);
- goto get_config_failed;
+ goto free_sps_endpoint;
}
ret = sps_phy2h(pipe_connection->src_phy_addr, &(connection->source));
if (ret) {
pr_err("%s: sps_phy2h failed (src BAM) %d\n", __func__, ret);
- goto get_config_failed;
+ goto free_sps_endpoint;
}
connection->src_pipe_index = pipe_connection->src_pipe_index;
@@ -91,7 +95,7 @@
&(connection->destination));
if (ret) {
pr_err("%s: sps_phy2h failed (dst BAM) %d\n", __func__, ret);
- goto get_config_failed;
+ goto free_sps_endpoint;
}
connection->dest_pipe_index = pipe_connection->dst_pipe_index;
@@ -113,7 +117,7 @@
if (ret) {
pr_err("%s: data fifo setup failure %d\n", __func__,
ret);
- goto fifo_setup_error;
+ goto free_sps_endpoint;
}
ret = sps_setup_bam2bam_fifo(
@@ -123,11 +127,33 @@
if (ret) {
pr_err("%s: desc. fifo setup failure %d\n", __func__,
ret);
- goto fifo_setup_error;
+ goto free_sps_endpoint;
}
} else if (pipe_connection->mem_type == USB_PRIVATE_MEM) {
pr_debug("%s: USB BAM using private memory\n", __func__);
- /* BAM is using dedicated USB private memory, map it */
+
+ if (IS_ERR(mem_clk) || IS_ERR(mem_iface_clk)) {
+ pr_err("%s: Failed to enable USB mem_clk\n", __func__);
+ ret = IS_ERR(mem_clk);
+ goto free_sps_endpoint;
+ }
+
+ clk_prepare_enable(mem_clk);
+ clk_prepare_enable(mem_iface_clk);
+
+ /*
+ * Enable USB PRIVATE RAM to be used for BAM FIFOs
+ * HSUSB: Only RAM13 is used for BAM FIFOs
+ * SSUSB: RAM11, 12, 13 are used for BAM FIFOs
+ */
+ if (pdata->usb_active_bam == HSUSB_BAM)
+ ram1_value = 0x4;
+ else
+ ram1_value = 0x7;
+
+ pr_debug("Writing 0x%x to QSCRATCH_RAM1\n", ram1_value);
+ writel_relaxed(ram1_value, qscratch_ram1_reg);
+
data_mem_buf[conn_idx][pipe_dir].phys_base =
pipe_connection->data_fifo_base_offset +
pdata->usb_base_address;
@@ -187,8 +213,7 @@
error:
sps_disconnect(*pipe);
-fifo_setup_error:
-get_config_failed:
+free_sps_endpoint:
sps_free_endpoint(*pipe);
return ret;
}
@@ -215,6 +240,13 @@
connection->data.base, connection->data.phys_base);
dma_free_coherent(&usb_bam_pdev->dev, connection->desc.size,
connection->desc.base, connection->desc.phys_base);
+ } else if (pipe_connection->mem_type == USB_PRIVATE_MEM) {
+ pr_debug("Freeing USB private memory used by BAM PIPE\n");
+ writel_relaxed(0x0, qscratch_ram1_reg);
+ iounmap(connection->data.base);
+ iounmap(connection->desc.base);
+ clk_disable_unprepare(mem_clk);
+ clk_disable_unprepare(mem_iface_clk);
}
connection->options &= ~SPS_O_AUTO_ENABLE;
@@ -507,6 +539,9 @@
return NULL;
}
+ pdata->ignore_core_reset_ack = of_property_read_bool(node,
+ "qcom,ignore-core-reset-ack");
+
for_each_child_of_node(pdev->dev.of_node, node)
pipe_entry++;
@@ -597,7 +632,9 @@
void *usb_virt_addr;
struct msm_usb_bam_platform_data *pdata =
usb_bam_pdev->dev.platform_data;
- struct resource *res;
+ struct usb_bam_pipe_connect *pipe_connection =
+ &msm_usb_bam_connections_info[pdata->usb_active_bam][0][0];
+ struct resource *res, *ram_resource;
int irq;
res = platform_get_resource_byname(usb_bam_pdev, IORESOURCE_MEM,
@@ -614,11 +651,35 @@
return irq;
}
- usb_virt_addr = ioremap(res->start, resource_size(res));
+ usb_virt_addr = devm_ioremap(&usb_bam_pdev->dev, res->start,
+ resource_size(res));
if (!usb_virt_addr) {
pr_err("%s: ioremap failed\n", __func__);
return -ENOMEM;
}
+
+ /* Check if USB3 pipe memory needs to be enabled */
+ if (pipe_connection->mem_type == USB_PRIVATE_MEM) {
+ pr_debug("%s: Enabling USB private memory for: %s\n", __func__,
+ bam_enable_strings[pdata->usb_active_bam]);
+
+ ram_resource = platform_get_resource_byname(usb_bam_pdev,
+ IORESOURCE_MEM, "qscratch_ram1_reg");
+ if (!res) {
+ dev_err(&usb_bam_pdev->dev, "Unable to get qscratch\n");
+ ret = -ENODEV;
+ goto free_bam_regs;
+ }
+
+ qscratch_ram1_reg = devm_ioremap(&usb_bam_pdev->dev,
+ ram_resource->start,
+ resource_size(ram_resource));
+ if (!qscratch_ram1_reg) {
+ pr_err("%s: ioremap failed for qscratch\n", __func__);
+ ret = -ENOMEM;
+ goto free_bam_regs;
+ }
+ }
usb_props.phys_addr = res->start;
usb_props.virt_addr = usb_virt_addr;
usb_props.virt_size = resource_size(res);
@@ -626,14 +687,28 @@
usb_props.summing_threshold = USB_SUMMING_THRESHOLD;
usb_props.event_threshold = 512;
usb_props.num_pipes = pdata->usb_bam_num_pipes;
+ /*
+ * HSUSB and HSIC Cores don't support RESET ACK signal to BAMs
+ * Hence, let BAM to ignore acknowledge from USB while resetting PIPE
+ */
+ if (pdata->ignore_core_reset_ack && pdata->usb_active_bam != SSUSB_BAM)
+ usb_props.options = SPS_BAM_NO_EXT_P_RST;
ret = sps_register_bam_device(&usb_props, &h_usb);
if (ret < 0) {
pr_err("%s: register bam error %d\n", __func__, ret);
- return -EFAULT;
+ ret = -EFAULT;
+ goto free_qscratch_reg;
}
return 0;
+
+free_qscratch_reg:
+ iounmap(qscratch_ram1_reg);
+free_bam_regs:
+ iounmap(usb_virt_addr);
+
+ return ret;
}
static ssize_t
@@ -698,6 +773,14 @@
usb_bam_wake_work);
}
+ mem_clk = devm_clk_get(&pdev->dev, "mem_clk");
+ if (IS_ERR(mem_clk))
+ dev_dbg(&pdev->dev, "failed to get mem_clock\n");
+
+ mem_iface_clk = devm_clk_get(&pdev->dev, "mem_iface_clk");
+ if (IS_ERR(mem_iface_clk))
+ dev_dbg(&pdev->dev, "failed to get mem_iface_clock\n");
+
if (pdev->dev.of_node) {
dev_dbg(&pdev->dev, "device tree enabled\n");
pdata = usb_bam_dt_to_pdata(pdev);
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 5e1b77a..2868d61 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -1999,11 +1999,6 @@
if (soc > 100)
soc = 100;
- if (bms_fake_battery != -EINVAL) {
- pr_debug("Returning Fake SOC = %d%%\n", bms_fake_battery);
- return bms_fake_battery;
- }
-
if (soc < 0) {
pr_err("bad rem_usb_chg = %d rem_chg %d,"
"cc_uah %d, unusb_chg %d\n",
@@ -2111,6 +2106,11 @@
int batt_temp;
int rc;
+ if (bms_fake_battery != -EINVAL) {
+ pr_debug("Returning Fake SOC = %d%%\n", bms_fake_battery);
+ return bms_fake_battery;
+ }
+
rc = pm8xxx_adc_read(the_chip->batt_temp_channel, &result);
if (rc) {
pr_err("error reading adc channel = %d, rc = %d\n",
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 6330883..cfe1efb 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -270,6 +270,7 @@
int rconn_mohm;
enum pm8921_chg_led_src_config led_src_config;
bool host_mode;
+ bool has_dc_supply;
u8 active_path;
int recent_reported_soc;
};
@@ -1195,6 +1196,12 @@
case POWER_SUPPLY_PROP_PRESENT:
case POWER_SUPPLY_PROP_ONLINE:
val->intval = 0;
+
+ if (the_chip->has_dc_supply) {
+ val->intval = 1;
+ return 0;
+ }
+
if (charging_disabled)
return 0;
@@ -1669,8 +1676,10 @@
*/
if (!get_prop_batt_present(the_chip)
&& !is_dc_chg_plugged_in(the_chip)) {
- pr_err("rejected: no other power source connected\n");
- return;
+ if (!the_chip->has_dc_supply) {
+ pr_err("rejected: no other power source connected\n");
+ return;
+ }
}
if (usb_max_current && mA > usb_max_current) {
@@ -3694,24 +3703,9 @@
chip->led_src_config, rc);
}
- /* Workarounds for die 1.1 and 1.0 */
- if (pm8xxx_get_revision(chip->dev->parent) < PM8XXX_REVISION_8921_2p0) {
- pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST2, 0xF1);
- pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xCE);
- pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xD8);
-
- /* software workaround for correct battery_id detection */
- pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_0, 0xFF);
- pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_1, 0xFF);
- pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_2, 0xFF);
- pm8xxx_writeb(chip->dev->parent, PSI_TXRX_SAMPLE_DATA_3, 0xFF);
- pm8xxx_writeb(chip->dev->parent, PSI_CONFIG_STATUS, 0x0D);
- udelay(100);
- pm8xxx_writeb(chip->dev->parent, PSI_CONFIG_STATUS, 0x0C);
- }
-
/* Workarounds for die 3.0 */
- if (pm8xxx_get_revision(chip->dev->parent) == PM8XXX_REVISION_8921_3p0)
+ if (pm8xxx_get_revision(chip->dev->parent) == PM8XXX_REVISION_8921_3p0
+ && pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8921)
pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xAC);
/* Enable isub_fine resolution AICL for PM8917 */
@@ -4049,6 +4043,7 @@
chip->hot_thr = pdata->hot_thr;
chip->rconn_mohm = pdata->rconn_mohm;
chip->led_src_config = pdata->led_src_config;
+ chip->has_dc_supply = pdata->has_dc_supply;
rc = pm8921_chg_hw_init(chip);
if (rc) {
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index 40f3803..7e74eca 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -62,11 +62,11 @@
config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config),
GFP_KERNEL);
if (!config)
- return NULL;
+ return ERR_PTR(-ENOMEM);
config->init_data = of_get_regulator_init_data(dev, dev->of_node);
if (!config->init_data)
- return NULL;
+ return ERR_PTR(-EINVAL);
init_data = config->init_data;
init_data->constraints.apply_uV = 0;
@@ -77,13 +77,26 @@
} else {
dev_err(dev,
"Fixed regulator specified with variable voltages\n");
- return NULL;
+ return ERR_PTR(-EINVAL);
}
if (init_data->constraints.boot_on)
config->enabled_at_boot = true;
config->gpio = of_get_named_gpio(np, "gpio", 0);
+ /*
+ * of_get_named_gpio() currently returns ENODEV rather than
+ * EPROBE_DEFER. This code attempts to be compatible with both
+ * for now; the ENODEV check can be removed once the API is fixed.
+ * of_get_named_gpio() doesn't differentiate between a missing
+ * property (which would be fine here, since the GPIO is optional)
+ * and some other error. Patches have been posted for both issues.
+ * Once they are check in, we should replace this with:
+ * if (config->gpio < 0 && config->gpio != -ENOENT)
+ */
+ if ((config->gpio == -ENODEV) || (config->gpio == -EPROBE_DEFER))
+ return ERR_PTR(-EPROBE_DEFER);
+
delay = of_get_property(np, "startup-delay-us", NULL);
if (delay)
config->startup_delay = be32_to_cpu(*delay);
@@ -168,10 +181,13 @@
struct fixed_voltage_data *drvdata;
int ret;
- if (pdev->dev.of_node)
+ if (pdev->dev.of_node) {
config = of_get_fixed_voltage_config(&pdev->dev);
- else
+ if (IS_ERR(config))
+ return PTR_ERR(config);
+ } else {
config = pdev->dev.platform_data;
+ }
if (!config)
return -ENOMEM;
diff --git a/drivers/regulator/qpnp-regulator.c b/drivers/regulator/qpnp-regulator.c
index 0e836c7..44fdbc1 100644
--- a/drivers/regulator/qpnp-regulator.c
+++ b/drivers/regulator/qpnp-regulator.c
@@ -56,7 +56,7 @@
};
enum qpnp_regulator_type {
- QPNP_REGULATOR_TYPE_HF_BUCK = 0x03,
+ QPNP_REGULATOR_TYPE_BUCK = 0x03,
QPNP_REGULATOR_TYPE_LDO = 0x04,
QPNP_REGULATOR_TYPE_VS = 0x05,
QPNP_REGULATOR_TYPE_BOOST = 0x1B,
@@ -87,6 +87,7 @@
};
enum qpnp_common_regulator_registers {
+ QPNP_COMMON_REG_DIG_MAJOR_REV = 0x01,
QPNP_COMMON_REG_TYPE = 0x04,
QPNP_COMMON_REG_SUBTYPE = 0x05,
QPNP_COMMON_REG_VOLTAGE_RANGE = 0x40,
@@ -106,7 +107,7 @@
};
enum qpnp_boost_registers {
- QPNP_BOOST_REG_CURRENT_LIMIT = 0x40,
+ QPNP_BOOST_REG_CURRENT_LIMIT = 0x4A,
};
/* Used for indexing into ctrl_reg. These are offets from 0x40 */
@@ -117,10 +118,6 @@
QPNP_COMMON_IDX_ENABLE = 6,
};
-enum qpnp_boost_control_register_index {
- QPNP_BOOST_IDX_CURRENT_LIMIT = 0,
-};
-
/* Common regulator control register layout */
#define QPNP_COMMON_ENABLE_MASK 0x80
#define QPNP_COMMON_ENABLE 0x80
@@ -190,6 +187,8 @@
enum qpnp_regulator_type type;
enum qpnp_regulator_subtype subtype;
enum qpnp_regulator_logical_type logical_type;
+ u32 revision_min;
+ u32 revision_max;
struct regulator_ops *ops;
struct qpnp_voltage_set_points *set_points;
int hpm_min_load;
@@ -213,11 +212,13 @@
u8 ctrl_reg[8];
};
-#define QPNP_VREG_MAP(_type, _subtype, _logical_type, _ops_val, \
- _set_points_val, _hpm_min_load) \
+#define QPNP_VREG_MAP(_type, _subtype, _dig_major_min, _dig_major_max, \
+ _logical_type, _ops_val, _set_points_val, _hpm_min_load) \
{ \
.type = QPNP_REGULATOR_TYPE_##_type, \
.subtype = QPNP_REGULATOR_SUBTYPE_##_subtype, \
+ .revision_min = _dig_major_min, \
+ .revision_max = _dig_major_max, \
.logical_type = QPNP_REGULATOR_LOGICAL_TYPE_##_logical_type, \
.ops = &qpnp_##_ops_val##_ops, \
.set_points = &_set_points_val##_set_points, \
@@ -262,6 +263,10 @@
VOLTAGE_RANGE(2, 750000, 775000, 1537500, 12500),
};
+static struct qpnp_voltage_range nldo3_ranges[] = {
+ VOLTAGE_RANGE(0, 375000, 375000, 1537500, 12500),
+};
+
static struct qpnp_voltage_range smps_ranges[] = {
VOLTAGE_RANGE(0, 375000, 375000, 1562500, 12500),
VOLTAGE_RANGE(1, 1550000, 1575000, 3125000, 25000),
@@ -281,6 +286,8 @@
= SET_POINTS(nldo1_ranges);
static struct qpnp_voltage_set_points nldo2_set_points
= SET_POINTS(nldo2_ranges);
+static struct qpnp_voltage_set_points nldo3_set_points
+ = SET_POINTS(nldo3_ranges);
static struct qpnp_voltage_set_points smps_set_points = SET_POINTS(smps_ranges);
static struct qpnp_voltage_set_points ftsmps_set_points
= SET_POINTS(ftsmps_ranges);
@@ -292,6 +299,7 @@
&pldo_set_points,
&nldo1_set_points,
&nldo2_set_points,
+ &nldo3_set_points,
&smps_set_points,
&ftsmps_set_points,
&boost_set_points,
@@ -959,24 +967,30 @@
.enable_time = qpnp_regulator_common_enable_time,
};
+/* Maximum possible digital major revision value */
+#define INF 0xFF
+
static const struct qpnp_regulator_mapping supported_regulators[] = {
- QPNP_VREG_MAP(HF_BUCK, GP_CTL, SMPS, smps, smps, 100000),
- QPNP_VREG_MAP(LDO, N300, LDO, ldo, nldo1, 10000),
- QPNP_VREG_MAP(LDO, N600, LDO, ldo, nldo2, 10000),
- QPNP_VREG_MAP(LDO, N1200, LDO, ldo, nldo2, 10000),
- QPNP_VREG_MAP(LDO, P50, LDO, ldo, pldo, 5000),
- QPNP_VREG_MAP(LDO, P150, LDO, ldo, pldo, 10000),
- QPNP_VREG_MAP(LDO, P300, LDO, ldo, pldo, 10000),
- QPNP_VREG_MAP(LDO, P600, LDO, ldo, pldo, 10000),
- QPNP_VREG_MAP(LDO, P1200, LDO, ldo, pldo, 10000),
- QPNP_VREG_MAP(VS, LV100, VS, vs, none, 0),
- QPNP_VREG_MAP(VS, LV300, VS, vs, none, 0),
- QPNP_VREG_MAP(VS, MV300, VS, vs, none, 0),
- QPNP_VREG_MAP(VS, MV500, VS, vs, none, 0),
- QPNP_VREG_MAP(VS, HDMI, VS, vs, none, 0),
- QPNP_VREG_MAP(VS, OTG, VS, vs, none, 0),
- QPNP_VREG_MAP(BOOST, 5V_BOOST, BOOST, boost, boost, 0),
- QPNP_VREG_MAP(FTS, FTS_CTL, FTSMPS, ftsmps, ftsmps, 100000),
+ /* type subtype dig_min dig_max ltype ops setpoints hpm_min */
+ QPNP_VREG_MAP(BUCK, GP_CTL, 0, INF, SMPS, smps, smps, 100000),
+ QPNP_VREG_MAP(LDO, N300, 0, INF, LDO, ldo, nldo1, 10000),
+ QPNP_VREG_MAP(LDO, N600, 0, 0, LDO, ldo, nldo2, 10000),
+ QPNP_VREG_MAP(LDO, N1200, 0, 0, LDO, ldo, nldo2, 10000),
+ QPNP_VREG_MAP(LDO, N600, 1, INF, LDO, ldo, nldo3, 10000),
+ QPNP_VREG_MAP(LDO, N1200, 1, INF, LDO, ldo, nldo3, 10000),
+ QPNP_VREG_MAP(LDO, P50, 0, INF, LDO, ldo, pldo, 5000),
+ QPNP_VREG_MAP(LDO, P150, 0, INF, LDO, ldo, pldo, 10000),
+ QPNP_VREG_MAP(LDO, P300, 0, INF, LDO, ldo, pldo, 10000),
+ QPNP_VREG_MAP(LDO, P600, 0, INF, LDO, ldo, pldo, 10000),
+ QPNP_VREG_MAP(LDO, P1200, 0, INF, LDO, ldo, pldo, 10000),
+ QPNP_VREG_MAP(VS, LV100, 0, INF, VS, vs, none, 0),
+ QPNP_VREG_MAP(VS, LV300, 0, INF, VS, vs, none, 0),
+ QPNP_VREG_MAP(VS, MV300, 0, INF, VS, vs, none, 0),
+ QPNP_VREG_MAP(VS, MV500, 0, INF, VS, vs, none, 0),
+ QPNP_VREG_MAP(VS, HDMI, 0, INF, VS, vs, none, 0),
+ QPNP_VREG_MAP(VS, OTG, 0, INF, VS, vs, none, 0),
+ QPNP_VREG_MAP(BOOST, 5V_BOOST, 0, INF, BOOST, boost, boost, 0),
+ QPNP_VREG_MAP(FTS, FTS_CTL, 0, INF, FTSMPS, ftsmps, ftsmps, 100000),
};
static int qpnp_regulator_match(struct qpnp_regulator *vreg)
@@ -984,29 +998,39 @@
const struct qpnp_regulator_mapping *mapping;
struct device_node *node = vreg->spmi_dev->dev.of_node;
int rc, i;
- u8 raw_type[2], type, subtype;
- u32 type_reg[2];
+ u32 type_reg[2], dig_major_rev;
+ u8 version[QPNP_COMMON_REG_SUBTYPE - QPNP_COMMON_REG_DIG_MAJOR_REV + 1];
+ u8 type, subtype;
- rc = of_property_read_u32_array(node, "qcom,force-type",
- type_reg, 2);
+ rc = qpnp_vreg_read(vreg, QPNP_COMMON_REG_DIG_MAJOR_REV, version,
+ ARRAY_SIZE(version));
+ if (rc) {
+ vreg_err(vreg, "could not read version registers, rc=%d\n", rc);
+ return rc;
+ }
+ dig_major_rev = version[QPNP_COMMON_REG_DIG_MAJOR_REV
+ - QPNP_COMMON_REG_DIG_MAJOR_REV];
+ type = version[QPNP_COMMON_REG_TYPE
+ - QPNP_COMMON_REG_DIG_MAJOR_REV];
+ subtype = version[QPNP_COMMON_REG_SUBTYPE
+ - QPNP_COMMON_REG_DIG_MAJOR_REV];
+
+ /*
+ * Override type and subtype register values if qcom,force-type is
+ * present in the device tree node.
+ */
+ rc = of_property_read_u32_array(node, "qcom,force-type", type_reg, 2);
if (!rc) {
type = type_reg[0];
subtype = type_reg[1];
- } else {
- rc = qpnp_vreg_read(vreg, QPNP_COMMON_REG_TYPE, raw_type, 2);
- if (rc) {
- vreg_err(vreg,
- "could not read type register, rc=%d\n", rc);
- return rc;
- }
- type = raw_type[0];
- subtype = raw_type[1];
}
rc = -ENODEV;
for (i = 0; i < ARRAY_SIZE(supported_regulators); i++) {
mapping = &supported_regulators[i];
- if (mapping->type == type && mapping->subtype == subtype) {
+ if (mapping->type == type && mapping->subtype == subtype
+ && mapping->revision_min <= dig_major_rev
+ && mapping->revision_max >= dig_major_rev) {
vreg->logical_type = mapping->logical_type;
vreg->set_points = mapping->set_points;
vreg->hpm_min_load = mapping->hpm_min_load;
@@ -1096,10 +1120,14 @@
if (type == QPNP_REGULATOR_LOGICAL_TYPE_BOOST
&& pdata->boost_current_limit
!= QPNP_BOOST_CURRENT_LIMIT_HW_DEFAULT) {
- ctrl_reg[QPNP_BOOST_IDX_CURRENT_LIMIT] &=
- ~QPNP_BOOST_CURRENT_LIMIT_MASK;
- ctrl_reg[QPNP_BOOST_IDX_CURRENT_LIMIT] |=
- pdata->boost_current_limit & QPNP_BOOST_CURRENT_LIMIT_MASK;
+ reg = pdata->boost_current_limit;
+ mask = QPNP_BOOST_CURRENT_LIMIT_MASK;
+ rc = qpnp_vreg_masked_read_write(vreg,
+ QPNP_BOOST_REG_CURRENT_LIMIT, reg, mask);
+ if (rc) {
+ vreg_err(vreg, "spmi write failed, rc=%d\n", rc);
+ return rc;
+ }
}
/* Write back any control register values that were modified. */
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 6eb5d60..f3a0d98 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -25,6 +25,7 @@
#include <linux/of.h>
#include <linux/of_slimbus.h>
#include <mach/sps.h>
+#include <mach/qdsp6v2/apr.h>
/* Per spec.max 40 bytes per received message */
#define SLIM_RX_MSGQ_BUF_LEN 40
@@ -232,6 +233,7 @@
CLK_GEAR = 7,
ROOT_FREQ = 11,
REF_CLK_GEAR = 15,
+ INTR_WAKE = 19,
};
enum msm_ctrl_state {
@@ -279,6 +281,7 @@
struct completion rx_msgq_notify;
struct task_struct *rx_msgq_thread;
struct clk *rclk;
+ struct clk *hclk;
struct mutex tx_lock;
u8 pgdla;
bool use_rx_msgqs;
@@ -1844,10 +1847,20 @@
{
struct msm_slim_ctrl *dev;
int ret;
+ enum apr_subsys_state q6_state;
struct resource *bam_mem, *bam_io;
struct resource *slim_mem, *slim_io;
struct resource *irq, *bam_irq;
bool rxreg_access = false;
+
+ q6_state = apr_get_q6_state();
+ if (q6_state == APR_SUBSYS_DOWN) {
+ dev_dbg(&pdev->dev, "defering %s, adsp_state %d\n", __func__,
+ q6_state);
+ return -EPROBE_DEFER;
+ } else
+ dev_dbg(&pdev->dev, "adsp is ready\n");
+
slim_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"slimbus_physical");
if (!slim_mem) {
@@ -1955,6 +1968,12 @@
dev->irq = irq->start;
dev->bam.irq = bam_irq->start;
+ dev->hclk = clk_get(dev->dev, "iface_clk");
+ if (IS_ERR(dev->hclk))
+ dev->hclk = NULL;
+ else
+ clk_prepare_enable(dev->hclk);
+
ret = msm_slim_sps_init(dev, bam_mem);
if (ret != 0) {
dev_err(dev->dev, "error SPS init\n");
@@ -2024,8 +2043,8 @@
wmb();
/* Framer register initialization */
- writel_relaxed((0xA << REF_CLK_GEAR) | (0xA << CLK_GEAR) |
- (1 << ROOT_FREQ) | (1 << FRM_ACTIVE) | 1,
+ writel_relaxed((1 << INTR_WAKE) | (0xA << REF_CLK_GEAR) |
+ (0xA << CLK_GEAR) | (1 << ROOT_FREQ) | (1 << FRM_ACTIVE) | 1,
dev->base + FRM_CFG);
/*
* Make sure that framer wake-up and enabling writes go through
@@ -2067,6 +2086,10 @@
* function
*/
mb();
+
+ /* Add devices registered with board-info now that controller is up */
+ slim_ctrl_add_boarddevs(&dev->ctrl);
+
if (pdev->dev.of_node)
of_register_slim_devices(&dev->ctrl);
@@ -2084,6 +2107,10 @@
err_request_irq_failed:
msm_slim_sps_exit(dev);
err_sps_init_failed:
+ if (dev->hclk) {
+ clk_disable_unprepare(dev->hclk);
+ clk_put(dev->hclk);
+ }
err_of_init_failed:
iounmap(dev->bam.base);
err_ioremap_bam_failed:
@@ -2120,6 +2147,8 @@
free_irq(dev->irq, dev);
slim_del_controller(&dev->ctrl);
clk_put(dev->rclk);
+ if (dev->hclk)
+ clk_put(dev->hclk);
msm_slim_sps_exit(dev);
kthread_stop(dev->rx_msgq_thread);
iounmap(dev->bam.base);
@@ -2191,8 +2220,14 @@
{
int ret = 0;
if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
+ struct platform_device *pdev = to_platform_device(dev);
+ struct msm_slim_ctrl *cdev = platform_get_drvdata(pdev);
dev_dbg(dev, "system suspend");
ret = msm_slim_runtime_suspend(dev);
+ if (!ret) {
+ if (cdev->hclk)
+ clk_disable_unprepare(cdev->hclk);
+ }
}
if (ret == -EBUSY) {
/*
@@ -2212,8 +2247,12 @@
{
/* If runtime_pm is enabled, this resume shouldn't do anything */
if (!pm_runtime_enabled(dev) || !pm_runtime_suspended(dev)) {
+ struct platform_device *pdev = to_platform_device(dev);
+ struct msm_slim_ctrl *cdev = platform_get_drvdata(pdev);
int ret;
dev_dbg(dev, "system resume");
+ if (cdev->hclk)
+ clk_prepare_enable(cdev->hclk);
ret = msm_slim_runtime_resume(dev);
if (!ret) {
pm_runtime_mark_last_busy(dev);
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index d0b5817..e50addb 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -373,6 +373,24 @@
EXPORT_SYMBOL_GPL(slim_register_board_info);
/*
+ * slim_ctrl_add_boarddevs: Add devices registered by board-info
+ * @ctrl: Controller to which these devices are to be added to.
+ * This API is called by controller when it is up and running.
+ * If devices on a controller were registered before controller,
+ * this will make sure that they get probed when controller is up.
+ */
+void slim_ctrl_add_boarddevs(struct slim_controller *ctrl)
+{
+ struct sbi_boardinfo *bi;
+ mutex_lock(&board_lock);
+ list_add_tail(&ctrl->list, &slim_ctrl_list);
+ list_for_each_entry(bi, &board_list, list)
+ slim_match_ctrl_to_boardinfo(ctrl, &bi->board_info);
+ mutex_unlock(&board_lock);
+}
+EXPORT_SYMBOL_GPL(slim_ctrl_add_boarddevs);
+
+/*
* slim_busnum_to_ctrl: Map bus number to controller
* @busnum: Bus number
* Returns controller representing this bus number
@@ -394,7 +412,6 @@
static int slim_register_controller(struct slim_controller *ctrl)
{
int ret = 0;
- struct sbi_boardinfo *bi;
/* Can't register until after driver model init */
if (WARN_ON(!slimbus_type.p)) {
@@ -462,15 +479,6 @@
ctrl->wq = create_singlethread_workqueue(dev_name(&ctrl->dev));
if (!ctrl->wq)
goto err_workq_failed;
- /*
- * If devices on a controller were registered before controller,
- * this will make sure that they get probed now that controller is up
- */
- mutex_lock(&board_lock);
- list_add_tail(&ctrl->list, &slim_ctrl_list);
- list_for_each_entry(bi, &board_list, list)
- slim_match_ctrl_to_boardinfo(ctrl, &bi->board_info);
- mutex_unlock(&board_lock);
return 0;
diff --git a/drivers/spmi/qpnp-int.c b/drivers/spmi/qpnp-int.c
index b6dfd51..24e35e4 100644
--- a/drivers/spmi/qpnp-int.c
+++ b/drivers/spmi/qpnp-int.c
@@ -253,12 +253,19 @@
return rc;
}
+static int qpnpint_irq_set_wake(struct irq_data *d, unsigned int on)
+{
+ return 0;
+}
+
static struct irq_chip qpnpint_chip = {
.name = "qpnp-int",
.irq_mask = qpnpint_irq_mask,
.irq_mask_ack = qpnpint_irq_mask_ack,
.irq_unmask = qpnpint_irq_unmask,
.irq_set_type = qpnpint_irq_set_type,
+ .irq_set_wake = qpnpint_irq_set_wake,
+ .flags = IRQCHIP_MASK_ON_SUSPEND,
};
static int qpnpint_init_irq_data(struct q_chip_data *chip_d,
diff --git a/drivers/thermal/msm8960_tsens.c b/drivers/thermal/msm8960_tsens.c
index 78a1292..daf0564 100644
--- a/drivers/thermal/msm8960_tsens.c
+++ b/drivers/thermal/msm8960_tsens.c
@@ -159,6 +159,7 @@
enum platform_type hw_type;
int pm_tsens_thr_data;
int pm_tsens_cntl;
+ struct work_struct tsens_work;
struct tsens_tm_device_sensor sensor[0];
};
@@ -610,9 +611,10 @@
NULL, "type");
}
-static irqreturn_t tsens_isr(int irq, void *data)
+static void tsens_scheduler_fn(struct work_struct *work)
{
- struct tsens_tm_device *tm = data;
+ struct tsens_tm_device *tm = container_of(work, struct tsens_tm_device,
+ tsens_work);
unsigned int threshold, threshold_low, i, code, reg, sensor, mask;
unsigned int sensor_addr;
bool upper_th_x, lower_th_x;
@@ -627,6 +629,7 @@
writel_relaxed(reg | TSENS_LOWER_STATUS_CLR |
TSENS_UPPER_STATUS_CLR, TSENS_CNTL_ADDR);
}
+
mask = ~(TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR);
threshold = readl_relaxed(TSENS_THRESHOLD_ADDR);
threshold_low = (threshold & TSENS_THRESHOLD_LOWER_LIMIT_MASK)
@@ -658,9 +661,7 @@
/* Notify user space */
schedule_work(&tm->sensor[i].work);
adc_code = readl_relaxed(sensor_addr);
- pr_info("\nTrip point triggered by "
- "current temperature (%d degrees) "
- "measured by Temperature-Sensor %d\n",
+ pr_debug("Trigger (%d degrees) for sensor %d\n",
tsens_tz_code_to_degC(adc_code, i), i);
}
}
@@ -672,6 +673,12 @@
else
writel_relaxed(reg & mask, TSENS_CNTL_ADDR);
mb();
+}
+
+static irqreturn_t tsens_isr(int irq, void *data)
+{
+ schedule_work(&tmdev->tsens_work);
+
return IRQ_HANDLED;
}
@@ -869,8 +876,7 @@
tmdev->sensor[TSENS_MAIN_SENSOR].calib_data =
tmdev->sensor[TSENS_MAIN_SENSOR].calib_data_backup;
if (!tmdev->sensor[TSENS_MAIN_SENSOR].calib_data) {
- pr_err("%s: No temperature sensor data for calibration"
- " in QFPROM!\n", __func__);
+ pr_err("QFPROM TSENS calibration data not present\n");
return -ENODEV;
}
@@ -901,8 +907,7 @@
tmdev->sensor[i].calib_data =
tmdev->sensor[i].calib_data_backup;
if (!tmdev->sensor[i].calib_data) {
- WARN(1, "%s: No temperature sensor:%d data for"
- " calibration in QFPROM!\n", __func__, i);
+ pr_err("QFPROM TSENS calibration data not present\n");
return -ENODEV;
}
tmdev->sensor[i].offset = (TSENS_CAL_DEGC *
@@ -1026,6 +1031,7 @@
thermal_zone_device_unregister(tmdev->sensor[i].tz_dev);
goto fail;
}
+ INIT_WORK(&tmdev->tsens_work, tsens_scheduler_fn);
pr_debug("%s: OK\n", __func__);
mb();
diff --git a/drivers/tty/Makefile b/drivers/tty/Makefile
index 9ebb54a..71f6a99 100644
--- a/drivers/tty/Makefile
+++ b/drivers/tty/Makefile
@@ -6,7 +6,7 @@
obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
obj-$(CONFIG_N_HDLC) += n_hdlc.o
obj-$(CONFIG_N_GSM) += n_gsm.o
-obj-$(CONFIG_N_SMUX) += n_smux.o
+obj-$(CONFIG_N_SMUX) += n_smux.o smux_debug.o
obj-$(CONFIG_N_SMUX_LOOPBACK) += smux_test.o smux_loopback.o
obj-$(CONFIG_SMUX_CTL) += smux_ctl.o
obj-$(CONFIG_TRACE_ROUTER) += n_tracerouter.o
diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c
index 1385e08..9f27c9c 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -28,6 +28,7 @@
#include <mach/subsystem_notif.h>
#include <mach/subsystem_restart.h>
#include <mach/msm_serial_hs.h>
+#include <mach/msm_ipc_logging.h>
#include "smux_private.h"
#include "smux_loopback.h"
@@ -59,10 +60,12 @@
MSM_SMUX_PKT = 1U << 3,
};
-static int smux_debug_mask;
+static int smux_debug_mask = MSM_SMUX_DEBUG | MSM_SMUX_POWER_INFO;
module_param_named(debug_mask, smux_debug_mask,
int, S_IRUGO | S_IWUSR | S_IWGRP);
+static int disable_ipc_logging;
+
/* Simulated wakeup used for testing */
int smux_byte_loopback;
module_param_named(byte_loopback, smux_byte_loopback,
@@ -71,14 +74,24 @@
module_param_named(simulate_wakeup_delay, smux_simulate_wakeup_delay,
int, S_IRUGO | S_IWUSR | S_IWGRP);
+#define IPC_LOG_STR(x...) do { \
+ if (!disable_ipc_logging && log_ctx) \
+ ipc_log_string(log_ctx, x); \
+} while (0)
+
#define SMUX_DBG(x...) do { \
if (smux_debug_mask & MSM_SMUX_DEBUG) \
- pr_info(x); \
+ IPC_LOG_STR(x); \
+} while (0)
+
+#define SMUX_ERR(x...) do { \
+ pr_err(x); \
+ IPC_LOG_STR(x); \
} while (0)
#define SMUX_PWR(x...) do { \
if (smux_debug_mask & MSM_SMUX_POWER_INFO) \
- pr_info(x); \
+ IPC_LOG_STR(x); \
} while (0)
#define SMUX_PWR_PKT_RX(pkt) do { \
@@ -90,10 +103,10 @@
if (smux_debug_mask & MSM_SMUX_POWER_INFO) { \
if (pkt->hdr.cmd == SMUX_CMD_BYTE && \
pkt->hdr.flags == SMUX_WAKEUP_ACK) \
- pr_info("smux: TX Wakeup ACK\n"); \
+ IPC_LOG_STR("smux: TX Wakeup ACK\n"); \
else if (pkt->hdr.cmd == SMUX_CMD_BYTE && \
pkt->hdr.flags == SMUX_WAKEUP_REQ) \
- pr_info("smux: TX Wakeup REQ\n"); \
+ IPC_LOG_STR("smux: TX Wakeup REQ\n"); \
else \
smux_log_pkt(pkt, 0); \
} \
@@ -170,59 +183,6 @@
SMUX_PWR_OFF_FLUSH,
};
-/**
- * Logical Channel Structure. One instance per channel.
- *
- * Locking Hierarchy
- * Each lock has a postfix that describes the locking level. If multiple locks
- * are required, only increasing lock hierarchy numbers may be locked which
- * ensures avoiding a deadlock.
- *
- * Locking Example
- * If state_lock_lhb1 is currently held and the TX list needs to be
- * manipulated, then tx_lock_lhb2 may be locked since it's locking hierarchy
- * is greater. However, if tx_lock_lhb2 is held, then state_lock_lhb1 may
- * not be acquired since it would result in a deadlock.
- *
- * Note that the Line Discipline locks (*_lha) should always be acquired
- * before the logical channel locks.
- */
-struct smux_lch_t {
- /* channel state */
- spinlock_t state_lock_lhb1;
- uint8_t lcid;
- unsigned local_state;
- unsigned local_mode;
- uint8_t local_tiocm;
- unsigned options;
-
- unsigned remote_state;
- unsigned remote_mode;
- uint8_t remote_tiocm;
-
- int tx_flow_control;
- int rx_flow_control_auto;
- int rx_flow_control_client;
-
- /* client callbacks and private data */
- void *priv;
- void (*notify)(void *priv, int event_type, const void *metadata);
- int (*get_rx_buffer)(void *priv, void **pkt_priv, void **buffer,
- int size);
-
- /* RX Info */
- struct list_head rx_retry_queue;
- unsigned rx_retry_queue_cnt;
- struct delayed_work rx_retry_work;
-
- /* TX Info */
- spinlock_t tx_lock_lhb2;
- struct list_head tx_queue;
- struct list_head tx_ready_list;
- unsigned tx_pending_data_cnt;
- unsigned notify_lwm;
-};
-
union notifier_metadata {
struct smux_meta_disconnected disconnected;
struct smux_meta_read read;
@@ -276,6 +236,7 @@
int is_initialized;
int platform_devs_registered;
int in_reset;
+ int remote_is_alive;
int ld_open_count;
struct tty_struct *tty;
@@ -302,7 +263,7 @@
/* data structures */
-static struct smux_lch_t smux_lch[SMUX_NUM_LOGICAL_CHANNELS];
+struct smux_lch_t smux_lch[SMUX_NUM_LOGICAL_CHANNELS];
static struct smux_ldisc_t smux;
static const char *tty_error_type[] = {
[TTY_NORMAL] = "normal",
@@ -312,7 +273,7 @@
[TTY_FRAME] = "framing",
};
-static const char *smux_cmds[] = {
+static const char * const smux_cmds[] = {
[SMUX_CMD_DATA] = "DATA",
[SMUX_CMD_OPEN_LCH] = "OPEN",
[SMUX_CMD_CLOSE_LCH] = "CLOSE",
@@ -321,6 +282,44 @@
[SMUX_CMD_BYTE] = "Raw Byte",
};
+static const char * const smux_events[] = {
+ [SMUX_CONNECTED] = "CONNECTED" ,
+ [SMUX_DISCONNECTED] = "DISCONNECTED",
+ [SMUX_READ_DONE] = "READ_DONE",
+ [SMUX_READ_FAIL] = "READ_FAIL",
+ [SMUX_WRITE_DONE] = "WRITE_DONE",
+ [SMUX_WRITE_FAIL] = "WRITE_FAIL",
+ [SMUX_TIOCM_UPDATE] = "TIOCM_UPDATE",
+ [SMUX_LOW_WM_HIT] = "LOW_WM_HIT",
+ [SMUX_HIGH_WM_HIT] = "HIGH_WM_HIT",
+ [SMUX_RX_RETRY_HIGH_WM_HIT] = "RX_RETRY_HIGH_WM_HIT",
+ [SMUX_RX_RETRY_LOW_WM_HIT] = "RX_RETRY_LOW_WM_HIT",
+};
+
+static const char * const smux_local_state[] = {
+ [SMUX_LCH_LOCAL_CLOSED] = "CLOSED",
+ [SMUX_LCH_LOCAL_OPENING] = "OPENING",
+ [SMUX_LCH_LOCAL_OPENED] = "OPENED",
+ [SMUX_LCH_LOCAL_CLOSING] = "CLOSING",
+};
+
+static const char * const smux_remote_state[] = {
+ [SMUX_LCH_REMOTE_CLOSED] = "CLOSED",
+ [SMUX_LCH_REMOTE_OPENED] = "OPENED",
+};
+
+static const char * const smux_mode[] = {
+ [SMUX_LCH_MODE_NORMAL] = "N",
+ [SMUX_LCH_MODE_LOCAL_LOOPBACK] = "L",
+ [SMUX_LCH_MODE_REMOTE_LOOPBACK] = "R",
+};
+
+static const char * const smux_undef[] = {
+ [SMUX_UNDEF_LONG] = "UNDEF",
+ [SMUX_UNDEF_SHORT] = "U",
+};
+
+static void *log_ctx;
static void smux_notify_local_fn(struct work_struct *work);
static DECLARE_WORK(smux_notify_local, smux_notify_local_fn);
@@ -346,12 +345,11 @@
static DECLARE_DELAYED_WORK(smux_delayed_inactivity_work,
smux_inactivity_worker);
-static long msm_smux_tiocm_get_atomic(struct smux_lch_t *ch);
static void list_channel(struct smux_lch_t *ch);
static int smux_send_status_cmd(struct smux_lch_t *ch);
static int smux_dispatch_rx_pkt(struct smux_pkt_t *pkt);
static void smux_flush_tty(void);
-static void smux_purge_ch_tx_queue(struct smux_lch_t *ch);
+static void smux_purge_ch_tx_queue(struct smux_lch_t *ch, int is_ssr);
static int schedule_notify(uint8_t lcid, int event,
const union notifier_metadata *metadata);
static int ssr_notifier_cb(struct notifier_block *this,
@@ -363,6 +361,45 @@
static void smux_pdev_release(struct device *dev);
/**
+ * local_lch_state() - Return human readable form of local logical state.
+ * @state: Local logical channel state enum.
+ *
+ */
+const char *local_lch_state(unsigned state)
+{
+ if (state < ARRAY_SIZE(smux_local_state))
+ return smux_local_state[state];
+ else
+ return smux_undef[SMUX_UNDEF_LONG];
+}
+
+/**
+ * remote_lch_state() - Return human readable for of remote logical state.
+ * @state: Remote logical channel state enum.
+ *
+ */
+const char *remote_lch_state(unsigned state)
+{
+ if (state < ARRAY_SIZE(smux_remote_state))
+ return smux_remote_state[state];
+ else
+ return smux_undef[SMUX_UNDEF_LONG];
+}
+
+/**
+ * lch_mode() - Return human readable form of mode.
+ * @mode: Mode of the logical channel.
+ *
+ */
+const char *lch_mode(unsigned mode)
+{
+ if (mode < ARRAY_SIZE(smux_mode))
+ return smux_mode[mode];
+ else
+ return smux_undef[SMUX_UNDEF_SHORT];
+}
+
+/**
* Convert TTY Error Flags to string for logging purposes.
*
* @flag TTY_* flag
@@ -389,14 +426,31 @@
}
/**
+ * Convert SMUX event to string for logging purposes.
+ *
+ * @event SMUX event
+ * @returns String description or NULL if unknown
+ */
+static const char *event_to_str(unsigned cmd)
+{
+ if (cmd < ARRAY_SIZE(smux_events))
+ return smux_events[cmd];
+ return NULL;
+}
+
+/**
* Set the reset state due to an unrecoverable failure.
*/
static void smux_enter_reset(void)
{
- pr_err("%s: unrecoverable failure, waiting for ssr\n", __func__);
+ SMUX_ERR("%s: unrecoverable failure, waiting for ssr\n", __func__);
smux.in_reset = 1;
+ smux.remote_is_alive = 0;
}
+/**
+ * Initialize the lch_structs.
+ */
static int lch_init(void)
{
unsigned int id;
@@ -410,7 +464,7 @@
smux_rx_wq = create_singlethread_workqueue("smux_rx_wq");
if (IS_ERR(smux_notify_wq) || IS_ERR(smux_tx_wq)) {
- SMUX_DBG("%s: create_singlethread_workqueue ENOMEM\n",
+ SMUX_DBG("smux: %s: create_singlethread_workqueue ENOMEM\n",
__func__);
return -ENOMEM;
}
@@ -421,7 +475,7 @@
i |= smux_loopback_init();
if (i) {
- pr_err("%s: out of memory error\n", __func__);
+ SMUX_ERR("%s: out of memory error\n", __func__);
return -ENOMEM;
}
@@ -471,7 +525,7 @@
/* Empty TX ready list */
spin_lock_irqsave(&smux.tx_lock_lha2, flags);
while (!list_empty(&smux.lch_tx_ready_list)) {
- SMUX_DBG("%s: emptying ready list %p\n",
+ SMUX_DBG("smux: %s: emptying ready list %p\n",
__func__, smux.lch_tx_ready_list.next);
ch = list_first_entry(&smux.lch_tx_ready_list,
struct smux_lch_t,
@@ -488,7 +542,7 @@
struct smux_pkt_t,
list);
list_del(&pkt->list);
- SMUX_DBG("%s: emptying power queue pkt=%p\n",
+ SMUX_DBG("smux: %s: emptying power queue pkt=%p\n",
__func__, pkt);
smux_free_pkt(pkt);
}
@@ -497,13 +551,13 @@
/* Close all ports */
for (i = 0 ; i < SMUX_NUM_LOGICAL_CHANNELS; i++) {
ch = &smux_lch[i];
- SMUX_DBG("%s: cleaning up lcid %d\n", __func__, i);
+ SMUX_DBG("smux: %s: cleaning up lcid %d\n", __func__, i);
spin_lock_irqsave(&ch->state_lock_lhb1, flags);
/* Purge TX queue */
spin_lock(&ch->tx_lock_lhb2);
- smux_purge_ch_tx_queue(ch);
+ smux_purge_ch_tx_queue(ch, 1);
spin_unlock(&ch->tx_lock_lhb2);
/* Notify user of disconnect and reset channel state */
@@ -670,7 +724,7 @@
i += snprintf(logbuf + i, SMUX_PKT_LOG_SIZE - i,
"%02x ", (unsigned)data[count]);
- pr_info("%s\n", logbuf);
+ IPC_LOG_STR(logbuf);
}
static void smux_notify_local_fn(struct work_struct *work)
@@ -688,8 +742,9 @@
¬ify_handle,
handle_size);
if (i != handle_size) {
- pr_err("%s: unable to retrieve handle %d expected %d\n",
- __func__, i, handle_size);
+ SMUX_ERR(
+ "%s: unable to retrieve handle %d expected %d\n",
+ __func__, i, handle_size);
spin_unlock_irqrestore(¬ify_lock_lhc1, flags);
break;
}
@@ -735,7 +790,7 @@
/* Consider a free list implementation instead of kmalloc */
pkt = kmalloc(sizeof(struct smux_pkt_t), GFP_ATOMIC);
if (!pkt) {
- pr_err("%s: out of memory\n", __func__);
+ SMUX_ERR("%s: out of memory\n", __func__);
return NULL;
}
smux_init_pkt(pkt);
@@ -779,7 +834,7 @@
pkt->payload = kmalloc(pkt->hdr.payload_len, GFP_ATOMIC);
pkt->free_payload = 1;
if (!pkt->payload) {
- pr_err("%s: unable to malloc %d bytes for payload\n",
+ SMUX_ERR("%s: unable to malloc %d bytes for payload\n",
__func__, pkt->hdr.payload_len);
return -ENOMEM;
}
@@ -797,11 +852,12 @@
unsigned long flags;
int ret = 0;
+ IPC_LOG_STR("smux: %s ch:%d\n", event_to_str(event), lcid);
ch = &smux_lch[lcid];
notify_handle = kzalloc(sizeof(struct smux_notify_handle),
GFP_ATOMIC);
if (!notify_handle) {
- pr_err("%s: out of memory\n", __func__);
+ SMUX_ERR("%s: out of memory\n", __func__);
ret = -ENOMEM;
goto free_out;
}
@@ -813,7 +869,7 @@
meta_copy = kzalloc(sizeof(union notifier_metadata),
GFP_ATOMIC);
if (!meta_copy) {
- pr_err("%s: out of memory\n", __func__);
+ SMUX_ERR("%s: out of memory\n", __func__);
ret = -ENOMEM;
goto free_out;
}
@@ -826,7 +882,7 @@
spin_lock_irqsave(¬ify_lock_lhc1, flags);
i = kfifo_avail(&smux_notify_fifo);
if (i < handle_size) {
- pr_err("%s: fifo full error %d expected %d\n",
+ SMUX_ERR("%s: fifo full error %d expected %d\n",
__func__, i, handle_size);
ret = -ENOMEM;
goto unlock_out;
@@ -834,7 +890,7 @@
i = kfifo_in(&smux_notify_fifo, ¬ify_handle, handle_size);
if (i < 0 || i != handle_size) {
- pr_err("%s: fifo not available error %d (expected %d)\n",
+ SMUX_ERR("%s: fifo not available error %d (expected %d)\n",
__func__, i, handle_size);
ret = -ENOSPC;
goto unlock_out;
@@ -886,7 +942,7 @@
char *data_start = out;
if (smux_serialize_size(pkt) > SMUX_MAX_PKT_SIZE) {
- pr_err("%s: packet size %d too big\n",
+ SMUX_ERR("%s: packet size %d too big\n",
__func__, smux_serialize_size(pkt));
return -E2BIG;
}
@@ -971,7 +1027,7 @@
len -= data_written;
data += data_written;
} else {
- pr_err("%s: TTY write returned error %d\n",
+ SMUX_ERR("%s: TTY write returned error %d\n",
__func__, data_written);
return data_written;
}
@@ -997,12 +1053,12 @@
int ret;
if (!smux.tty) {
- pr_err("%s: TTY not initialized", __func__);
+ SMUX_ERR("%s: TTY not initialized", __func__);
return -ENOTTY;
}
if (pkt->hdr.cmd == SMUX_CMD_BYTE) {
- SMUX_DBG("%s: tty send single byte\n", __func__);
+ SMUX_DBG("smux: %s: tty send single byte\n", __func__);
ret = write_to_tty(&pkt->hdr.flags, 1);
return ret;
}
@@ -1010,7 +1066,7 @@
smux_serialize_hdr(pkt, &data, &len);
ret = write_to_tty(data, len);
if (ret) {
- pr_err("%s: failed %d to write header %d\n",
+ SMUX_ERR("%s: failed %d to write header %d\n",
__func__, ret, len);
return ret;
}
@@ -1018,7 +1074,7 @@
smux_serialize_payload(pkt, &data, &len);
ret = write_to_tty(data, len);
if (ret) {
- pr_err("%s: failed %d to write payload %d\n",
+ SMUX_ERR("%s: failed %d to write payload %d\n",
__func__, ret, len);
return ret;
}
@@ -1028,7 +1084,7 @@
char zero = 0x0;
ret = write_to_tty(&zero, 1);
if (ret) {
- pr_err("%s: failed %d to write padding %d\n",
+ SMUX_ERR("%s: failed %d to write padding %d\n",
__func__, ret, len);
return ret;
}
@@ -1048,7 +1104,7 @@
pkt = smux_alloc_pkt();
if (!pkt) {
- pr_err("%s: alloc failure for byte %x\n", __func__, ch);
+ SMUX_ERR("%s: alloc failure for byte %x\n", __func__, ch);
return;
}
pkt->hdr.cmd = SMUX_CMD_BYTE;
@@ -1091,7 +1147,7 @@
{
unsigned long flags;
- SMUX_DBG("%s: queuing pkt %p\n", __func__, pkt_ptr);
+ SMUX_DBG("smux: %s: queuing pkt %p\n", __func__, pkt_ptr);
spin_lock_irqsave(&ch->tx_lock_lhb2, flags);
list_add_tail(&pkt_ptr->list, &ch->tx_queue);
@@ -1120,7 +1176,7 @@
spin_lock(&ch->state_lock_lhb1);
if (ch->local_state == SMUX_LCH_LOCAL_OPENING) {
- SMUX_DBG("lcid %d local state 0x%x -> 0x%x\n", lcid,
+ SMUX_DBG("smux: lcid %d local state 0x%x -> 0x%x\n", lcid,
ch->local_state,
SMUX_LCH_LOCAL_OPENED);
@@ -1132,10 +1188,10 @@
schedule_notify(lcid, SMUX_CONNECTED, NULL);
ret = 0;
} else if (ch->remote_mode == SMUX_LCH_MODE_REMOTE_LOOPBACK) {
- SMUX_DBG("Remote loopback OPEN ACK received\n");
+ SMUX_DBG("smux: Remote loopback OPEN ACK received\n");
ret = 0;
} else {
- pr_err("%s: lcid %d state 0x%x open ack invalid\n",
+ SMUX_ERR("%s: lcid %d state 0x%x open ack invalid\n",
__func__, lcid, ch->local_state);
ret = -EINVAL;
}
@@ -1145,7 +1201,7 @@
spin_lock(&smux.tx_lock_lha2);
if (!smux.powerdown_enabled) {
smux.powerdown_enabled = 1;
- SMUX_DBG("%s: enabling power-collapse support\n",
+ SMUX_DBG("smux: %s: enabling power-collapse support\n",
__func__);
}
spin_unlock(&smux.tx_lock_lha2);
@@ -1169,7 +1225,7 @@
spin_lock_irqsave(&ch->state_lock_lhb1, flags);
if (ch->local_state == SMUX_LCH_LOCAL_CLOSING) {
- SMUX_DBG("lcid %d local state 0x%x -> 0x%x\n", lcid,
+ SMUX_DBG("smux: lcid %d local state 0x%x -> 0x%x\n", lcid,
SMUX_LCH_LOCAL_CLOSING,
SMUX_LCH_LOCAL_CLOSED);
ch->local_state = SMUX_LCH_LOCAL_CLOSED;
@@ -1178,10 +1234,10 @@
&meta_disconnected);
ret = 0;
} else if (ch->remote_mode == SMUX_LCH_MODE_REMOTE_LOOPBACK) {
- SMUX_DBG("Remote loopback CLOSE ACK received\n");
+ SMUX_DBG("smux: Remote loopback CLOSE ACK received\n");
ret = 0;
} else {
- pr_err("%s: lcid %d state 0x%x close ack invalid\n",
+ SMUX_ERR("%s: lcid %d state 0x%x close ack invalid\n",
__func__, lcid, ch->local_state);
ret = -EINVAL;
}
@@ -1215,7 +1271,7 @@
spin_lock_irqsave(&ch->state_lock_lhb1, flags);
if (ch->remote_state == SMUX_LCH_REMOTE_CLOSED) {
- SMUX_DBG("lcid %d remote state 0x%x -> 0x%x\n", lcid,
+ SMUX_DBG("smux: lcid %d remote state 0x%x -> 0x%x\n", lcid,
SMUX_LCH_REMOTE_CLOSED,
SMUX_LCH_REMOTE_OPENED);
@@ -1259,15 +1315,16 @@
smux_tx_queue(ack_pkt, ch, 0);
tx_ready = 1;
} else {
- pr_err("%s: Remote loopack allocation failure\n",
- __func__);
+ SMUX_ERR(
+ "%s: Remote loopack allocation failure\n",
+ __func__);
}
} else if (ch->local_state == SMUX_LCH_LOCAL_OPENED) {
schedule_notify(lcid, SMUX_CONNECTED, NULL);
}
ret = 0;
} else {
- pr_err("%s: lcid %d remote state 0x%x open invalid\n",
+ SMUX_ERR("%s: lcid %d remote state 0x%x open invalid\n",
__func__, lcid, ch->remote_state);
ret = -EINVAL;
}
@@ -1279,7 +1336,7 @@
spin_lock_irqsave(&smux.tx_lock_lha2, flags);
if (!smux.powerdown_enabled) {
smux.powerdown_enabled = 1;
- SMUX_DBG("%s: enabling power-collapse support\n",
+ SMUX_DBG("smux: %s: enabling power-collapse support\n",
__func__);
}
spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
@@ -1317,7 +1374,7 @@
spin_lock_irqsave(&ch->state_lock_lhb1, flags);
if (ch->remote_state == SMUX_LCH_REMOTE_OPENED) {
- SMUX_DBG("lcid %d remote state 0x%x -> 0x%x\n", lcid,
+ SMUX_DBG("smux: lcid %d remote state 0x%x -> 0x%x\n", lcid,
SMUX_LCH_REMOTE_OPENED,
SMUX_LCH_REMOTE_CLOSED);
@@ -1351,8 +1408,9 @@
smux_tx_queue(ack_pkt, ch, 0);
tx_ready = 1;
} else {
- pr_err("%s: Remote loopack allocation failure\n",
- __func__);
+ SMUX_ERR(
+ "%s: Remote loopack allocation failure\n",
+ __func__);
}
}
@@ -1361,7 +1419,7 @@
&meta_disconnected);
ret = 0;
} else {
- pr_err("%s: lcid %d remote state 0x%x close invalid\n",
+ SMUX_ERR("%s: lcid %d remote state 0x%x close invalid\n",
__func__, lcid, ch->remote_state);
ret = -EINVAL;
}
@@ -1412,7 +1470,7 @@
if (ch->local_state != SMUX_LCH_LOCAL_OPENED
&& !remote_loopback) {
- pr_err("smux: ch %d error data on local state 0x%x",
+ SMUX_ERR("smux: ch %d error data on local state 0x%x",
lcid, ch->local_state);
ret = -EIO;
spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
@@ -1420,7 +1478,7 @@
}
if (ch->remote_state != SMUX_LCH_REMOTE_OPENED) {
- pr_err("smux: ch %d error data on remote state 0x%x",
+ SMUX_ERR("smux: ch %d error data on remote state 0x%x",
lcid, ch->remote_state);
ret = -EIO;
spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
@@ -1441,8 +1499,9 @@
}
if ((ch->rx_retry_queue_cnt + 1) > SMUX_RX_RETRY_MAX_PKTS) {
/* retry queue full */
- pr_err("%s: ch %d RX retry queue full\n",
- __func__, lcid);
+ SMUX_ERR(
+ "%s: ch %d RX retry queue full; rx flow=%d\n",
+ __func__, lcid, ch->rx_flow_control_auto);
schedule_notify(lcid, SMUX_READ_FAIL, NULL);
ret = -ENOMEM;
spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
@@ -1468,7 +1527,7 @@
smux_tx_queue(ack_pkt, ch, 0);
tx_ready = 1;
} else {
- pr_err("%s: Remote loopack allocation failure\n",
+ SMUX_ERR("%s: Remote loopack allocation failure\n",
__func__);
}
} else if (!do_retry) {
@@ -1492,7 +1551,7 @@
/* buffer allocation failed - add to retry queue */
do_retry = 1;
} else if (tmp < 0) {
- pr_err("%s: ch %d Client RX buffer alloc failed %d\n",
+ SMUX_ERR("%s: ch %d Client RX buffer alloc failed %d\n",
__func__, lcid, tmp);
schedule_notify(lcid, SMUX_READ_FAIL, NULL);
ret = -ENOMEM;
@@ -1504,7 +1563,7 @@
retry = kmalloc(sizeof(struct smux_rx_pkt_retry), GFP_KERNEL);
if (!retry) {
- pr_err("%s: retry alloc failure\n", __func__);
+ SMUX_ERR("%s: retry alloc failure\n", __func__);
ret = -ENOMEM;
schedule_notify(lcid, SMUX_READ_FAIL, NULL);
goto out;
@@ -1516,7 +1575,7 @@
retry->pkt = smux_alloc_pkt();
if (!retry->pkt) {
kfree(retry);
- pr_err("%s: pkt alloc failure\n", __func__);
+ SMUX_ERR("%s: pkt alloc failure\n", __func__);
ret = -ENOMEM;
schedule_notify(lcid, SMUX_READ_FAIL, NULL);
goto out;
@@ -1562,7 +1621,7 @@
unsigned long flags;
if (!pkt || smux_assert_lch_id(pkt->hdr.lcid)) {
- pr_err("%s: invalid packet or channel id\n", __func__);
+ SMUX_ERR("%s: invalid packet or channel id\n", __func__);
return -ENXIO;
}
@@ -1571,14 +1630,14 @@
spin_lock_irqsave(&ch->state_lock_lhb1, flags);
if (ch->local_state != SMUX_LCH_LOCAL_OPENED) {
- pr_err("smux: ch %d error data on local state 0x%x",
+ SMUX_ERR("smux: ch %d error data on local state 0x%x",
lcid, ch->local_state);
ret = -EIO;
goto out;
}
if (ch->remote_state != SMUX_LCH_REMOTE_OPENED) {
- pr_err("smux: ch %d error data on remote state 0x%x",
+ SMUX_ERR("smux: ch %d error data on remote state 0x%x",
lcid, ch->remote_state);
ret = -EIO;
goto out;
@@ -1623,11 +1682,11 @@
/* logical channel flow control changed */
if (pkt->hdr.flags & SMUX_CMD_STATUS_FLOW_CNTL) {
/* disabled TX */
- SMUX_DBG("TX Flow control enabled\n");
+ SMUX_DBG("smux: TX Flow control enabled\n");
ch->tx_flow_control = 1;
} else {
/* re-enable channel */
- SMUX_DBG("TX Flow control disabled\n");
+ SMUX_DBG("smux: TX Flow control disabled\n");
ch->tx_flow_control = 0;
tx_ready = 1;
}
@@ -1671,7 +1730,7 @@
/* Power-down complete, turn off UART */
power_down = 1;
else
- pr_err("%s: sleep request ack invalid in state %d\n",
+ SMUX_ERR("%s: sleep request ack invalid in state %d\n",
__func__, smux.power_state);
} else {
/*
@@ -1690,7 +1749,7 @@
if (smux.power_state == SMUX_PWR_ON) {
ack_pkt = smux_alloc_pkt();
if (ack_pkt) {
- SMUX_PWR("%s: Power %d->%d\n", __func__,
+ SMUX_PWR("smux: %s: Power %d->%d\n", __func__,
smux.power_state,
SMUX_PWR_TURNING_OFF_FLUSH);
@@ -1706,7 +1765,7 @@
}
} else if (smux.power_state == SMUX_PWR_TURNING_OFF_FLUSH) {
/* Local power-down request still in TX queue */
- SMUX_PWR("%s: Power-down shortcut - no ack\n",
+ SMUX_PWR("smux: %s: Power-down shortcut - no ack\n",
__func__);
smux.power_ctl_remote_req_received = 1;
} else if (smux.power_state == SMUX_PWR_TURNING_OFF) {
@@ -1714,17 +1773,17 @@
* Local power-down request already sent to remote
* side, so this request gets treated as an ACK.
*/
- SMUX_PWR("%s: Power-down shortcut - no ack\n",
+ SMUX_PWR("smux: %s: Power-down shortcut - no ack\n",
__func__);
power_down = 1;
} else {
- pr_err("%s: sleep request invalid in state %d\n",
+ SMUX_ERR("%s: sleep request invalid in state %d\n",
__func__, smux.power_state);
}
}
if (power_down) {
- SMUX_PWR("%s: Power %d->%d\n", __func__,
+ SMUX_PWR("smux: %s: Power %d->%d\n", __func__,
smux.power_state, SMUX_PWR_OFF_FLUSH);
smux.power_state = SMUX_PWR_OFF_FLUSH;
queue_work(smux_tx_wq, &smux_inactivity_work);
@@ -1749,7 +1808,7 @@
case SMUX_CMD_OPEN_LCH:
SMUX_LOG_PKT_RX(pkt);
if (smux_assert_lch_id(pkt->hdr.lcid)) {
- pr_err("%s: invalid channel id %d\n",
+ SMUX_ERR("%s: invalid channel id %d\n",
__func__, pkt->hdr.lcid);
break;
}
@@ -1759,7 +1818,7 @@
case SMUX_CMD_DATA:
SMUX_LOG_PKT_RX(pkt);
if (smux_assert_lch_id(pkt->hdr.lcid)) {
- pr_err("%s: invalid channel id %d\n",
+ SMUX_ERR("%s: invalid channel id %d\n",
__func__, pkt->hdr.lcid);
break;
}
@@ -1769,7 +1828,7 @@
case SMUX_CMD_CLOSE_LCH:
SMUX_LOG_PKT_RX(pkt);
if (smux_assert_lch_id(pkt->hdr.lcid)) {
- pr_err("%s: invalid channel id %d\n",
+ SMUX_ERR("%s: invalid channel id %d\n",
__func__, pkt->hdr.lcid);
break;
}
@@ -1779,7 +1838,7 @@
case SMUX_CMD_STATUS:
SMUX_LOG_PKT_RX(pkt);
if (smux_assert_lch_id(pkt->hdr.lcid)) {
- pr_err("%s: invalid channel id %d\n",
+ SMUX_ERR("%s: invalid channel id %d\n",
__func__, pkt->hdr.lcid);
break;
}
@@ -1797,7 +1856,7 @@
default:
SMUX_LOG_PKT_RX(pkt);
- pr_err("%s: command %d unknown\n", __func__, pkt->hdr.cmd);
+ SMUX_ERR("%s: command %d unknown\n", __func__, pkt->hdr.cmd);
ret = -EINVAL;
}
return ret;
@@ -1824,7 +1883,7 @@
memcpy(&recv.hdr, data, sizeof(struct smux_hdr_t));
if (recv.hdr.magic != SMUX_MAGIC) {
- pr_err("%s: invalid header magic\n", __func__);
+ SMUX_ERR("%s: invalid header magic\n", __func__);
return -EINVAL;
}
@@ -1845,7 +1904,7 @@
if (smux.power_state == SMUX_PWR_OFF
|| smux.power_state == SMUX_PWR_TURNING_ON) {
/* wakeup system */
- SMUX_PWR("%s: Power %d->%d\n", __func__,
+ SMUX_PWR("smux: %s: Power %d->%d\n", __func__,
smux.power_state, SMUX_PWR_ON);
smux.power_state = SMUX_PWR_ON;
queue_work(smux_tx_wq, &smux_wakeup_work);
@@ -1857,7 +1916,7 @@
smux_send_byte(SMUX_WAKEUP_ACK);
} else {
/* stale wakeup request from previous wakeup */
- SMUX_PWR("%s: stale Wakeup REQ in state %d\n",
+ SMUX_PWR("smux: %s: stale Wakeup REQ in state %d\n",
__func__, smux.power_state);
}
spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
@@ -1873,7 +1932,7 @@
spin_lock_irqsave(&smux.tx_lock_lha2, flags);
if (smux.power_state == SMUX_PWR_TURNING_ON) {
/* received response to wakeup request */
- SMUX_PWR("%s: Power %d->%d\n", __func__,
+ SMUX_PWR("smux: %s: Power %d->%d\n", __func__,
smux.power_state, SMUX_PWR_ON);
smux.power_state = SMUX_PWR_ON;
queue_work(smux_tx_wq, &smux_tx_work);
@@ -1882,7 +1941,7 @@
} else if (smux.power_state != SMUX_PWR_ON) {
/* invalid message */
- SMUX_PWR("%s: stale Wakeup REQ ACK in state %d\n",
+ SMUX_PWR("smux: %s: stale Wakeup REQ ACK in state %d\n",
__func__, smux.power_state);
}
spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
@@ -1905,7 +1964,7 @@
if (smux_byte_loopback)
smux_receive_byte(SMUX_UT_ECHO_ACK_FAIL,
smux_byte_loopback);
- pr_err("%s: TTY error 0x%x - ignoring\n", __func__, flag);
+ SMUX_ERR("%s: TTY error 0x%x - ignoring\n", __func__, flag);
++*used;
return;
}
@@ -1916,11 +1975,21 @@
smux.rx_state = SMUX_RX_MAGIC;
break;
case SMUX_WAKEUP_REQ:
- SMUX_PWR("smux: RX Wakeup REQ\n");
+ SMUX_PWR("smux: smux: RX Wakeup REQ\n");
+ if (unlikely(!smux.remote_is_alive)) {
+ mutex_lock(&smux.mutex_lha0);
+ smux.remote_is_alive = 1;
+ mutex_unlock(&smux.mutex_lha0);
+ }
smux_handle_wakeup_req();
break;
case SMUX_WAKEUP_ACK:
- SMUX_PWR("smux: RX Wakeup ACK\n");
+ SMUX_PWR("smux: smux: RX Wakeup ACK\n");
+ if (unlikely(!smux.remote_is_alive)) {
+ mutex_lock(&smux.mutex_lha0);
+ smux.remote_is_alive = 1;
+ mutex_unlock(&smux.mutex_lha0);
+ }
smux_handle_wakeup_ack();
break;
default:
@@ -1928,8 +1997,8 @@
if (smux_byte_loopback && data[i] == SMUX_UT_ECHO_REQ)
smux_receive_byte(SMUX_UT_ECHO_ACK_OK,
smux_byte_loopback);
- pr_err("%s: parse error 0x%02x - ignoring\n", __func__,
- (unsigned)data[i]);
+ SMUX_ERR("%s: parse error 0x%02x - ignoring\n",
+ __func__, (unsigned)data[i]);
break;
}
}
@@ -1951,7 +2020,7 @@
int i;
if (flag) {
- pr_err("%s: TTY RX error %d\n", __func__, flag);
+ SMUX_ERR("%s: TTY RX error %d\n", __func__, flag);
smux_enter_reset();
smux.rx_state = SMUX_RX_FAILURE;
++*used;
@@ -1967,8 +2036,9 @@
smux.rx_state = SMUX_RX_HDR;
} else {
/* unexpected / trash character */
- pr_err("%s: rx parse error for char %c; *used=%d, len=%d\n",
- __func__, data[i], *used, len);
+ SMUX_ERR(
+ "%s: rx parse error for char %c; *used=%d, len=%d\n",
+ __func__, data[i], *used, len);
smux.rx_state = SMUX_RX_IDLE;
}
}
@@ -1991,7 +2061,7 @@
struct smux_hdr_t *hdr;
if (flag) {
- pr_err("%s: TTY RX error %d\n", __func__, flag);
+ SMUX_ERR("%s: TTY RX error %d\n", __func__, flag);
smux_enter_reset();
smux.rx_state = SMUX_RX_FAILURE;
++*used;
@@ -2025,7 +2095,7 @@
int remaining;
if (flag) {
- pr_err("%s: TTY RX error %d\n", __func__, flag);
+ SMUX_ERR("%s: TTY RX error %d\n", __func__, flag);
smux_enter_reset();
smux.rx_state = SMUX_RX_FAILURE;
++*used;
@@ -2073,6 +2143,24 @@
}
/**
+ * Returns true if the remote side has acknowledged a wakeup
+ * request previously, so we know that the link is alive and active.
+ *
+ * @returns true for is alive, false for not alive
+ */
+bool smux_remote_is_active(void)
+{
+ bool is_active = false;
+
+ mutex_lock(&smux.mutex_lha0);
+ if (smux.remote_is_alive)
+ is_active = true;
+ mutex_unlock(&smux.mutex_lha0);
+
+ return is_active;
+}
+
+/**
* Add channel to transmit-ready list and trigger transmit worker.
*
* @ch Channel to add
@@ -2081,7 +2169,7 @@
{
unsigned long flags;
- SMUX_DBG("%s: listing channel %d\n",
+ SMUX_DBG("smux: %s: listing channel %d\n",
__func__, ch->lcid);
spin_lock_irqsave(&smux.tx_lock_lha2, flags);
@@ -2120,11 +2208,11 @@
meta_write.write.buffer = pkt->payload;
meta_write.write.len = pkt->hdr.payload_len;
if (ret >= 0) {
- SMUX_DBG("%s: PKT write done", __func__);
+ SMUX_DBG("smux: %s: PKT write done", __func__);
schedule_notify(ch->lcid, SMUX_WRITE_DONE,
&meta_write);
} else {
- pr_err("%s: failed to write pkt %d\n",
+ SMUX_ERR("%s: failed to write pkt %d\n",
__func__, ret);
schedule_notify(ch->lcid, SMUX_WRITE_FAIL,
&meta_write);
@@ -2140,7 +2228,7 @@
{
mutex_lock(&smux.mutex_lha0);
if (!smux.tty) {
- pr_err("%s: ldisc not loaded\n", __func__);
+ SMUX_ERR("%s: ldisc not loaded\n", __func__);
mutex_unlock(&smux.mutex_lha0);
return;
}
@@ -2149,7 +2237,7 @@
msecs_to_jiffies(TTY_BUFFER_FULL_WAIT_MS));
if (tty_chars_in_buffer(smux.tty) > 0)
- pr_err("%s: unable to flush UART queue\n", __func__);
+ SMUX_ERR("%s: unable to flush UART queue\n", __func__);
mutex_unlock(&smux.mutex_lha0);
}
@@ -2158,25 +2246,35 @@
* Purge TX queue for logical channel.
*
* @ch Logical channel pointer
+ * @is_ssr 1 = this is a subsystem restart purge
*
* Must be called with the following spinlocks locked:
* state_lock_lhb1
* tx_lock_lhb2
*/
-static void smux_purge_ch_tx_queue(struct smux_lch_t *ch)
+static void smux_purge_ch_tx_queue(struct smux_lch_t *ch, int is_ssr)
{
struct smux_pkt_t *pkt;
int send_disconnect = 0;
+ struct smux_pkt_t *pkt_tmp;
+ int is_state_pkt;
- while (!list_empty(&ch->tx_queue)) {
- pkt = list_first_entry(&ch->tx_queue, struct smux_pkt_t,
- list);
- list_del(&pkt->list);
-
+ list_for_each_entry_safe(pkt, pkt_tmp, &ch->tx_queue, list) {
+ is_state_pkt = 0;
if (pkt->hdr.cmd == SMUX_CMD_OPEN_LCH) {
- /* Open was never sent, just force to closed state */
- ch->local_state = SMUX_LCH_LOCAL_CLOSED;
- send_disconnect = 1;
+ if (pkt->hdr.flags & SMUX_CMD_OPEN_ACK) {
+ /* Open ACK must still be sent */
+ is_state_pkt = 1;
+ } else {
+ /* Open never sent -- force to closed state */
+ ch->local_state = SMUX_LCH_LOCAL_CLOSED;
+ send_disconnect = 1;
+ }
+ } else if (pkt->hdr.cmd == SMUX_CMD_CLOSE_LCH) {
+ if (pkt->hdr.flags & SMUX_CMD_CLOSE_ACK)
+ is_state_pkt = 1;
+ if (!send_disconnect)
+ is_state_pkt = 1;
} else if (pkt->hdr.cmd == SMUX_CMD_DATA) {
/* Notify client of failed write */
union notifier_metadata meta_write;
@@ -2186,7 +2284,11 @@
meta_write.write.len = pkt->hdr.payload_len;
schedule_notify(ch->lcid, SMUX_WRITE_FAIL, &meta_write);
}
- smux_free_pkt(pkt);
+
+ if (!is_state_pkt || is_ssr) {
+ list_del(&pkt->list);
+ smux_free_pkt(pkt);
+ }
}
if (send_disconnect) {
@@ -2208,7 +2310,7 @@
struct uart_state *state;
if (!smux.tty || !smux.tty->driver_data) {
- pr_err("%s: unable to find UART port for tty %p\n",
+ SMUX_ERR("%s: unable to find UART port for tty %p\n",
__func__, smux.tty);
return;
}
@@ -2236,7 +2338,7 @@
struct uart_state *state;
if (!smux.tty || !smux.tty->driver_data) {
- pr_err("%s: unable to find UART port for tty %p\n",
+ SMUX_ERR("%s: unable to find UART port for tty %p\n",
__func__, smux.tty);
mutex_unlock(&smux.mutex_lha0);
return;
@@ -2276,7 +2378,7 @@
/* wakeup complete */
smux.pwr_wakeup_delay_us = 1;
spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
- SMUX_DBG("%s: wakeup complete\n", __func__);
+ SMUX_DBG("smux: %s: wakeup complete\n", __func__);
/*
* Cancel any pending retry. This avoids a race condition with
@@ -2296,17 +2398,18 @@
SMUX_WAKEUP_DELAY_MAX;
spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
- SMUX_PWR("%s: triggering wakeup\n", __func__);
+ SMUX_PWR("smux: %s: triggering wakeup\n", __func__);
smux_send_byte(SMUX_WAKEUP_REQ);
if (wakeup_delay < SMUX_WAKEUP_DELAY_MIN) {
- SMUX_DBG("%s: sleeping for %u us\n", __func__,
+ SMUX_DBG("smux: %s: sleeping for %u us\n", __func__,
wakeup_delay);
usleep_range(wakeup_delay, 2*wakeup_delay);
queue_work(smux_tx_wq, &smux_wakeup_work);
} else {
/* schedule delayed work */
- SMUX_DBG("%s: scheduling delayed wakeup in %u ms\n",
+ SMUX_DBG(
+ "smux: %s: scheduling delayed wakeup in %u ms\n",
__func__, wakeup_delay / 1000);
queue_delayed_work(smux_tx_wq,
&smux_wakeup_delayed_work,
@@ -2316,7 +2419,7 @@
/* wakeup aborted */
smux.pwr_wakeup_delay_us = 1;
spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
- SMUX_PWR("%s: wakeup aborted\n", __func__);
+ SMUX_PWR("smux: %s: wakeup aborted\n", __func__);
cancel_delayed_work(&smux_wakeup_delayed_work);
}
}
@@ -2346,7 +2449,8 @@
/* start power-down sequence */
pkt = smux_alloc_pkt();
if (pkt) {
- SMUX_PWR("%s: Power %d->%d\n", __func__,
+ SMUX_PWR(
+ "smux: %s: Power %d->%d\n", __func__,
smux.power_state,
SMUX_PWR_TURNING_OFF_FLUSH);
smux.power_state =
@@ -2360,7 +2464,7 @@
&smux.power_queue);
queue_work(smux_tx_wq, &smux_tx_work);
} else {
- pr_err("%s: packet alloc failed\n",
+ SMUX_ERR("%s: packet alloc failed\n",
__func__);
}
}
@@ -2371,7 +2475,7 @@
if (smux.power_state == SMUX_PWR_OFF_FLUSH) {
/* ready to power-down the UART */
- SMUX_PWR("%s: Power %d->%d\n", __func__,
+ SMUX_PWR("smux: %s: Power %d->%d\n", __func__,
smux.power_state, SMUX_PWR_OFF);
smux.power_state = SMUX_PWR_OFF;
@@ -2452,16 +2556,16 @@
smux.rx_activity_flag = 1;
spin_unlock_irqrestore(&smux.rx_lock_lha1, flags);
- SMUX_DBG("%s: %p, len=%d, flag=%d\n", __func__, data, len, flag);
+ SMUX_DBG("smux: %s: %p, len=%d, flag=%d\n", __func__, data, len, flag);
used = 0;
do {
if (smux.in_reset) {
- SMUX_DBG("%s: abort RX due to reset\n", __func__);
+ SMUX_DBG("smux: %s: abort RX due to reset\n", __func__);
smux.rx_state = SMUX_RX_IDLE;
break;
}
- SMUX_DBG("%s: state %d; %d of %d\n",
+ SMUX_DBG("smux: %s: state %d; %d of %d\n",
__func__, smux.rx_state, used, len);
initial_rx_state = smux.rx_state;
@@ -2479,7 +2583,7 @@
smux_rx_handle_pkt_payload(data, len, &used, flag);
break;
default:
- SMUX_DBG("%s: invalid state %d\n",
+ SMUX_DBG("smux: %s: invalid state %d\n",
__func__, smux.rx_state);
smux.rx_state = SMUX_RX_IDLE;
break;
@@ -2520,7 +2624,7 @@
}
if (list_empty(&ch->rx_retry_queue)) {
- SMUX_DBG("%s: retry list empty for channel %d\n",
+ SMUX_DBG("smux: %s: retry list empty for channel %d\n",
__func__, ch->lcid);
spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
return;
@@ -2530,7 +2634,7 @@
rx_retry_list);
spin_unlock_irqrestore(&ch->state_lock_lhb1, flags);
- SMUX_DBG("%s: ch %d retrying rx pkt %p\n",
+ SMUX_DBG("smux: %s: ch %d retrying rx pkt %p\n",
__func__, ch->lcid, retry);
metadata.read.pkt_priv = 0;
metadata.read.buffer = 0;
@@ -2559,7 +2663,7 @@
retry->timeout_in_ms <<= 1;
if (retry->timeout_in_ms > SMUX_RX_RETRY_MAX_MS) {
/* timed out */
- pr_err("%s: ch %d RX retry client timeout\n",
+ SMUX_ERR("%s: ch %d RX retry client timeout\n",
__func__, ch->lcid);
spin_lock_irqsave(&ch->state_lock_lhb1, flags);
tx_ready = smux_remove_rx_retry(ch, retry);
@@ -2570,7 +2674,7 @@
}
} else {
/* client error - drop packet */
- pr_err("%s: ch %d RX retry client failed (%d)\n",
+ SMUX_ERR("%s: ch %d RX retry client failed (%d)\n",
__func__, ch->lcid, tmp);
spin_lock_irqsave(&ch->state_lock_lhb1, flags);
tx_ready = smux_remove_rx_retry(ch, retry);
@@ -2635,7 +2739,7 @@
if (!list_empty(&smux.lch_tx_ready_list) ||
!list_empty(&smux.power_queue)) {
/* data to transmit, do wakeup */
- SMUX_PWR("%s: Power %d->%d\n", __func__,
+ SMUX_PWR("smux: %s: Power %d->%d\n", __func__,
smux.power_state,
SMUX_PWR_TURNING_ON);
smux.power_state = SMUX_PWR_TURNING_ON;
@@ -2669,7 +2773,8 @@
* and we already received a remote
* power-down request.
*/
- SMUX_PWR("%s: Power %d->%d\n", __func__,
+ SMUX_PWR(
+ "smux: %s: Power %d->%d\n", __func__,
smux.power_state,
SMUX_PWR_OFF_FLUSH);
smux.power_state = SMUX_PWR_OFF_FLUSH;
@@ -2678,7 +2783,8 @@
&smux_inactivity_work);
} else {
/* sending local power-down request */
- SMUX_PWR("%s: Power %d->%d\n", __func__,
+ SMUX_PWR(
+ "smux: %s: Power %d->%d\n", __func__,
smux.power_state,
SMUX_PWR_TURNING_OFF);
smux.power_state = SMUX_PWR_TURNING_OFF;
@@ -2704,7 +2810,7 @@
/* get the next ready channel */
if (list_empty(&smux.lch_tx_ready_list)) {
/* no ready channels */
- SMUX_DBG("%s: no more ready channels, exiting\n",
+ SMUX_DBG("smux: %s: no more ready channels, exiting\n",
__func__);
spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
break;
@@ -2713,7 +2819,7 @@
if (smux.power_state != SMUX_PWR_ON) {
/* channel not ready to transmit */
- SMUX_DBG("%s: waiting for link up (state %d)\n",
+ SMUX_DBG("smux: %s: waiting for link up (state %d)\n",
__func__,
smux.power_state);
spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
@@ -2824,11 +2930,11 @@
{
smux.in_reset = 1;
- SMUX_DBG("%s: flushing tx wq\n", __func__);
+ SMUX_DBG("smux: %s: flushing tx wq\n", __func__);
flush_workqueue(smux_tx_wq);
- SMUX_DBG("%s: flushing rx wq\n", __func__);
+ SMUX_DBG("smux: %s: flushing rx wq\n", __func__);
flush_workqueue(smux_rx_wq);
- SMUX_DBG("%s: flushing notify wq\n", __func__);
+ SMUX_DBG("smux: %s: flushing notify wq\n", __func__);
flush_workqueue(smux_notify_wq);
}
@@ -2886,13 +2992,13 @@
/* Auto RX Flow Control */
if (set & SMUX_CH_OPTION_AUTO_REMOTE_TX_STOP) {
- SMUX_DBG("%s: auto rx flow control option enabled\n",
+ SMUX_DBG("smux: %s: auto rx flow control option enabled\n",
__func__);
ch->options |= SMUX_CH_OPTION_AUTO_REMOTE_TX_STOP;
}
if (clear & SMUX_CH_OPTION_AUTO_REMOTE_TX_STOP) {
- SMUX_DBG("%s: auto rx flow control option disabled\n",
+ SMUX_DBG("smux: %s: auto rx flow control option disabled\n",
__func__);
ch->options &= ~SMUX_CH_OPTION_AUTO_REMOTE_TX_STOP;
ch->rx_flow_control_auto = 0;
@@ -2947,13 +3053,13 @@
}
if (ch->local_state != SMUX_LCH_LOCAL_CLOSED) {
- pr_err("%s: open lcid %d local state %x invalid\n",
+ SMUX_ERR("%s: open lcid %d local state %x invalid\n",
__func__, lcid, ch->local_state);
ret = -EINVAL;
goto out;
}
- SMUX_DBG("lcid %d local state 0x%x -> 0x%x\n", lcid,
+ SMUX_DBG("smux: lcid %d local state 0x%x -> 0x%x\n", lcid,
ch->local_state,
SMUX_LCH_LOCAL_OPENING);
@@ -3017,16 +3123,17 @@
ch->remote_tiocm = 0x0;
ch->tx_pending_data_cnt = 0;
ch->notify_lwm = 0;
+ ch->tx_flow_control = 0;
/* Purge TX queue */
spin_lock(&ch->tx_lock_lhb2);
- smux_purge_ch_tx_queue(ch);
+ smux_purge_ch_tx_queue(ch, 0);
spin_unlock(&ch->tx_lock_lhb2);
/* Send Close Command */
if (ch->local_state == SMUX_LCH_LOCAL_OPENED ||
ch->local_state == SMUX_LCH_LOCAL_OPENING) {
- SMUX_DBG("lcid %d local state 0x%x -> 0x%x\n", lcid,
+ SMUX_DBG("smux: lcid %d local state 0x%x -> 0x%x\n", lcid,
ch->local_state,
SMUX_LCH_LOCAL_CLOSING);
@@ -3041,7 +3148,7 @@
smux_tx_queue(pkt, ch, 0);
tx_ready = 1;
} else {
- pr_err("%s: pkt allocation failed\n", __func__);
+ SMUX_ERR("%s: pkt allocation failed\n", __func__);
ret = -ENOMEM;
}
@@ -3091,14 +3198,14 @@
if (ch->local_state != SMUX_LCH_LOCAL_OPENED &&
ch->local_state != SMUX_LCH_LOCAL_OPENING) {
- pr_err("%s: hdr.invalid local state %d channel %d\n",
+ SMUX_ERR("%s: hdr.invalid local state %d channel %d\n",
__func__, ch->local_state, lcid);
ret = -EINVAL;
goto out;
}
if (len > SMUX_MAX_PKT_SIZE - sizeof(struct smux_hdr_t)) {
- pr_err("%s: payload %d too large\n",
+ SMUX_ERR("%s: payload %d too large\n",
__func__, len);
ret = -E2BIG;
goto out;
@@ -3120,10 +3227,10 @@
spin_lock(&ch->tx_lock_lhb2);
/* verify high watermark */
- SMUX_DBG("%s: pending %d", __func__, ch->tx_pending_data_cnt);
+ SMUX_DBG("smux: %s: pending %d", __func__, ch->tx_pending_data_cnt);
if (ch->tx_pending_data_cnt >= SMUX_TX_WM_HIGH) {
- pr_err("%s: ch %d high watermark %d exceeded %d\n",
+ SMUX_ERR("%s: ch %d high watermark %d exceeded %d\n",
__func__, lcid, SMUX_TX_WM_HIGH,
ch->tx_pending_data_cnt);
ret = -EAGAIN;
@@ -3133,7 +3240,7 @@
/* queue packet for transmit */
if (++ch->tx_pending_data_cnt == SMUX_TX_WM_HIGH) {
ch->notify_lwm = 1;
- pr_err("%s: high watermark hit\n", __func__);
+ SMUX_ERR("%s: high watermark hit\n", __func__);
schedule_notify(lcid, SMUX_HIGH_WM_HIT, NULL);
}
list_add_tail(&pkt->list, &ch->tx_queue);
@@ -3251,7 +3358,7 @@
*
* @returns TIOCM status
*/
-static long msm_smux_tiocm_get_atomic(struct smux_lch_t *ch)
+long msm_smux_tiocm_get_atomic(struct smux_lch_t *ch)
{
long status = 0x0;
@@ -3369,24 +3476,26 @@
int power_off_uart = 0;
if (code == SUBSYS_BEFORE_SHUTDOWN) {
- SMUX_DBG("%s: ssr - before shutdown\n", __func__);
+ SMUX_DBG("smux: %s: ssr - before shutdown\n", __func__);
mutex_lock(&smux.mutex_lha0);
smux.in_reset = 1;
+ smux.remote_is_alive = 0;
mutex_unlock(&smux.mutex_lha0);
return NOTIFY_DONE;
} else if (code == SUBSYS_AFTER_POWERUP) {
/* re-register platform devices */
- SMUX_DBG("%s: ssr - after power-up\n", __func__);
+ SMUX_DBG("smux: %s: ssr - after power-up\n", __func__);
mutex_lock(&smux.mutex_lha0);
if (smux.ld_open_count > 0
&& !smux.platform_devs_registered) {
for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
- SMUX_DBG("%s: register pdev '%s'\n",
+ SMUX_DBG("smux: %s: register pdev '%s'\n",
__func__, smux_devs[i].name);
smux_devs[i].dev.release = smux_pdev_release;
tmp = platform_device_register(&smux_devs[i]);
if (tmp)
- pr_err("%s: error %d registering device %s\n",
+ SMUX_ERR(
+ "%s: error %d registering device %s\n",
__func__, tmp, smux_devs[i].name);
}
smux.platform_devs_registered = 1;
@@ -3396,7 +3505,7 @@
} else if (code != SUBSYS_AFTER_SHUTDOWN) {
return NOTIFY_DONE;
}
- SMUX_DBG("%s: ssr - after shutdown\n", __func__);
+ SMUX_DBG("smux: %s: ssr - after shutdown\n", __func__);
/* Cleanup channels */
smux_flush_workqueues();
@@ -3409,7 +3518,7 @@
/* Unregister platform devices */
if (smux.platform_devs_registered) {
for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
- SMUX_DBG("%s: unregister pdev '%s'\n",
+ SMUX_DBG("smux: %s: unregister pdev '%s'\n",
__func__, smux_devs[i].name);
platform_device_unregister(&smux_devs[i]);
}
@@ -3419,7 +3528,8 @@
/* Power-down UART */
spin_lock_irqsave(&smux.tx_lock_lha2, flags);
if (smux.power_state != SMUX_PWR_OFF) {
- SMUX_PWR("%s: SSR - turning off UART\n", __func__);
+ SMUX_PWR("smux: %s: SSR - turning off UART\n",
+ __func__);
smux.power_state = SMUX_PWR_OFF;
power_off_uart = 1;
}
@@ -3433,6 +3543,7 @@
smux.rx_activity_flag = 0;
smux.rx_state = SMUX_RX_IDLE;
smux.in_reset = 0;
+ smux.remote_is_alive = 0;
mutex_unlock(&smux.mutex_lha0);
return NOTIFY_DONE;
@@ -3446,7 +3557,8 @@
struct platform_device *pdev;
pdev = container_of(dev, struct platform_device, dev);
- SMUX_DBG("%s: releasing pdev %p '%s'\n", __func__, pdev, pdev->name);
+ SMUX_DBG("smux: %s: releasing pdev %p '%s'\n",
+ __func__, pdev, pdev->name);
memset(&pdev->dev, 0x0, sizeof(pdev->dev));
}
@@ -3461,14 +3573,14 @@
mutex_lock(&smux.mutex_lha0);
if (smux.ld_open_count) {
- pr_err("%s: %p multiple instances not supported\n",
+ SMUX_ERR("%s: %p multiple instances not supported\n",
__func__, tty);
mutex_unlock(&smux.mutex_lha0);
return -EEXIST;
}
if (tty->ops->write == NULL) {
- pr_err("%s: tty->ops->write already NULL\n", __func__);
+ SMUX_ERR("%s: tty->ops->write already NULL\n", __func__);
mutex_unlock(&smux.mutex_lha0);
return -EINVAL;
}
@@ -3484,7 +3596,7 @@
/* power-down the UART if we are idle */
spin_lock_irqsave(&smux.tx_lock_lha2, flags);
if (smux.power_state == SMUX_PWR_OFF) {
- SMUX_PWR("%s: powering off uart\n", __func__);
+ SMUX_PWR("smux: %s: powering off uart\n", __func__);
smux.power_state = SMUX_PWR_OFF_FLUSH;
spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
queue_work(smux_tx_wq, &smux_inactivity_work);
@@ -3494,12 +3606,12 @@
/* register platform devices */
for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
- SMUX_DBG("%s: register pdev '%s'\n",
+ SMUX_DBG("smux: %s: register pdev '%s'\n",
__func__, smux_devs[i].name);
smux_devs[i].dev.release = smux_pdev_release;
tmp = platform_device_register(&smux_devs[i]);
if (tmp)
- pr_err("%s: error %d registering device %s\n",
+ SMUX_ERR("%s: error %d registering device %s\n",
__func__, tmp, smux_devs[i].name);
}
smux.platform_devs_registered = 1;
@@ -3513,12 +3625,12 @@
int power_up_uart = 0;
int i;
- SMUX_DBG("%s: ldisc unload\n", __func__);
+ SMUX_DBG("smux: %s: ldisc unload\n", __func__);
smux_flush_workqueues();
mutex_lock(&smux.mutex_lha0);
if (smux.ld_open_count <= 0) {
- pr_err("%s: invalid ld count %d\n", __func__,
+ SMUX_ERR("%s: invalid ld count %d\n", __func__,
smux.ld_open_count);
mutex_unlock(&smux.mutex_lha0);
return;
@@ -3531,7 +3643,7 @@
/* Unregister platform devices */
if (smux.platform_devs_registered) {
for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
- SMUX_DBG("%s: unregister pdev '%s'\n",
+ SMUX_DBG("smux: %s: unregister pdev '%s'\n",
__func__, smux_devs[i].name);
platform_device_unregister(&smux_devs[i]);
}
@@ -3555,8 +3667,9 @@
/* Disconnect from TTY */
smux.tty = NULL;
+ smux.remote_is_alive = 0;
mutex_unlock(&smux.mutex_lha0);
- SMUX_DBG("%s: ldisc complete\n", __func__);
+ SMUX_DBG("smux: %s: ldisc complete\n", __func__);
}
/**
@@ -3575,16 +3688,12 @@
const char *tty_name = NULL;
char *f;
- if (smux_debug_mask & MSM_SMUX_DEBUG)
- print_hex_dump(KERN_INFO, "smux tty rx: ", DUMP_PREFIX_OFFSET,
- 16, 1, cp, count, true);
-
/* verify error flags */
for (i = 0, f = fp; i < count; ++i, ++f) {
if (*f != TTY_NORMAL) {
if (tty)
tty_name = tty->name;
- pr_err("%s: TTY %s Error %d (%s)\n", __func__,
+ SMUX_ERR("%s: TTY %s Error %d (%s)\n", __func__,
tty_name, *f, tty_flag_to_str(*f));
/* feed all previous valid data to the parser */
@@ -3603,46 +3712,46 @@
static void smuxld_flush_buffer(struct tty_struct *tty)
{
- pr_err("%s: not supported\n", __func__);
+ SMUX_ERR("%s: not supported\n", __func__);
}
static ssize_t smuxld_chars_in_buffer(struct tty_struct *tty)
{
- pr_err("%s: not supported\n", __func__);
+ SMUX_ERR("%s: not supported\n", __func__);
return -ENODEV;
}
static ssize_t smuxld_read(struct tty_struct *tty, struct file *file,
unsigned char __user *buf, size_t nr)
{
- pr_err("%s: not supported\n", __func__);
+ SMUX_ERR("%s: not supported\n", __func__);
return -ENODEV;
}
static ssize_t smuxld_write(struct tty_struct *tty, struct file *file,
const unsigned char *buf, size_t nr)
{
- pr_err("%s: not supported\n", __func__);
+ SMUX_ERR("%s: not supported\n", __func__);
return -ENODEV;
}
static int smuxld_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
- pr_err("%s: not supported\n", __func__);
+ SMUX_ERR("%s: not supported\n", __func__);
return -ENODEV;
}
static unsigned int smuxld_poll(struct tty_struct *tty, struct file *file,
struct poll_table_struct *tbl)
{
- pr_err("%s: not supported\n", __func__);
+ SMUX_ERR("%s: not supported\n", __func__);
return -ENODEV;
}
static void smuxld_write_wakeup(struct tty_struct *tty)
{
- pr_err("%s: not supported\n", __func__);
+ SMUX_ERR("%s: not supported\n", __func__);
}
static struct tty_ldisc_ops smux_ldisc_ops = {
@@ -3680,6 +3789,7 @@
smux.tty = NULL;
smux.ld_open_count = 0;
smux.in_reset = 0;
+ smux.remote_is_alive = 0;
smux.is_initialized = 1;
smux.platform_devs_registered = 0;
smux_byte_loopback = 0;
@@ -3689,7 +3799,7 @@
ret = tty_register_ldisc(N_SMUX, &smux_ldisc_ops);
if (ret != 0) {
- pr_err("%s: error %d registering line discipline\n",
+ SMUX_ERR("%s: error %d registering line discipline\n",
__func__, ret);
return ret;
}
@@ -3698,10 +3808,16 @@
ret = lch_init();
if (ret != 0) {
- pr_err("%s: lch_init failed\n", __func__);
+ SMUX_ERR("%s: lch_init failed\n", __func__);
return ret;
}
+ log_ctx = ipc_log_context_create(1, "smux");
+ if (!log_ctx) {
+ SMUX_ERR("%s: unable to create log context\n", __func__);
+ disable_ipc_logging = 1;
+ }
+
return 0;
}
@@ -3711,7 +3827,7 @@
ret = tty_unregister_ldisc(N_SMUX);
if (ret != 0) {
- pr_err("%s error %d unregistering line discipline\n",
+ SMUX_ERR("%s error %d unregistering line discipline\n",
__func__, ret);
return;
}
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 1904706..9386804 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -2122,7 +2122,6 @@
free_irq(uport->irq, msm_uport);
if (use_low_power_wakeup(msm_uport))
free_irq(msm_uport->wakeup.irq, msm_uport);
- mutex_destroy(&msm_uport->clk_mutex);
}
static void __exit msm_serial_hs_exit(void)
diff --git a/drivers/tty/smux_debug.c b/drivers/tty/smux_debug.c
new file mode 100644
index 0000000..86377d6
--- /dev/null
+++ b/drivers/tty/smux_debug.c
@@ -0,0 +1,170 @@
+/* drivers/tty/smux_debug.c
+ *
+ * Copyright (c) 2012, Code Aurora Forum. 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.
+ *
+ */
+#include <linux/debugfs.h>
+#include <linux/list.h>
+#include <linux/ctype.h>
+#include <linux/jiffies.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/completion.h>
+#include <linux/termios.h>
+#include <linux/smux.h>
+#include "smux_private.h"
+
+#define DEBUG_BUFMAX 4096
+
+
+
+/**
+ * smux_dump_ch() - Dumps the information of a channel to the screen.
+ * @buf: Buffer for status message.
+ * @max: Size of status queue.
+ * @lch_number: Number of the logical channel.
+ * @lch: Pointer to the lch_number'th instance of struct smux_lch_t.
+ *
+ */
+static int smux_dump_ch(char *buf, int max, struct smux_lch_t *lch)
+{
+ int bytes_written;
+ long tiocm_bits;
+ unsigned long flags;
+
+ spin_lock_irqsave(&lch->state_lock_lhb1, flags);
+ spin_lock(&lch->tx_lock_lhb2);
+
+ tiocm_bits = msm_smux_tiocm_get_atomic(lch);
+
+ bytes_written = scnprintf(
+ buf, max,
+ "ch%02d: "
+ "%s(%s) "
+ "%c%c%c%c%c "
+ "%d "
+ "%s(%s) "
+ "%c%c\n",
+ lch->lcid,
+ local_lch_state(lch->local_state), lch_mode(lch->local_mode),
+ (tiocm_bits & TIOCM_DSR) ? 'D' : 'd',
+ (tiocm_bits & TIOCM_CTS) ? 'T' : 't',
+ (tiocm_bits & TIOCM_RI) ? 'I' : 'i',
+ (tiocm_bits & TIOCM_CD) ? 'C' : 'c',
+ lch->tx_flow_control ? 'F' : 'f',
+ lch->tx_pending_data_cnt,
+ remote_lch_state(lch->remote_state), lch_mode(lch->remote_mode),
+ (tiocm_bits & TIOCM_DTR) ? 'R' : 'r',
+ (tiocm_bits & TIOCM_RTS) ? 'S' : 's'
+ );
+
+ spin_unlock(&lch->tx_lock_lhb2);
+ spin_unlock_irqrestore(&lch->state_lock_lhb1, flags);
+
+ return bytes_written;
+}
+
+/**
+ * smux_dump_format_ch() - Informs user of format for channel dump
+ * @buf: Buffer for status message.
+ * @max: Size of status queue.
+ *
+ */
+static int smux_dump_format_ch(char *buf, int max)
+{
+ return scnprintf(
+ buf, max,
+ "ch_id "
+ "local state(mode) tiocm "
+ "tx_queue "
+ "remote state(mode) tiocm\n"
+ "local tiocm: DSR(D) CTS(T) RI(I) DCD(C) FLOW_CONTROL(F)\n"
+ "remote tiocm: DTR(R) RTS(S)\n"
+ "A capital letter indicates set, otherwise, it is not set.\n\n"
+ );
+}
+
+/**
+ * smux_debug_ch() - Log following information about each channel
+ * local open, local mode, remote open, remote mode,
+ * tiocm bits, flow control state and transmit queue size.
+ * Returns the number of bytes written to buf.
+ * @buf Buffer for status message
+ * @max Size of status queue
+ *
+ */
+static int smux_debug_ch(char *buf, int max)
+{
+ int ch_id;
+
+ int bytes_written = smux_dump_format_ch(buf, max);
+
+ for (ch_id = 0; ch_id < SMUX_NUM_LOGICAL_CHANNELS; ch_id++) {
+ bytes_written += smux_dump_ch(buf + bytes_written,
+ max - bytes_written,
+ &smux_lch[ch_id]);
+ }
+
+ return bytes_written;
+
+}
+
+static char debug_buffer[DEBUG_BUFMAX];
+
+static ssize_t debug_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int (*fill)(char *buf, int max) = file->private_data;
+ int bsize;
+
+ if (*ppos != 0)
+ return 0;
+
+ bsize = fill(debug_buffer, DEBUG_BUFMAX);
+ return simple_read_from_buffer(buf, count, ppos, debug_buffer, bsize);
+}
+
+static int debug_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static const struct file_operations debug_ops = {
+ .read = debug_read,
+ .open = debug_open,
+};
+
+
+static void debug_create(const char *name, mode_t mode,
+ struct dentry *dent,
+ int (*fill)(char *buf, int max))
+{
+ debugfs_create_file(name, mode, dent, fill, &debug_ops);
+}
+
+
+static int __init smux_debugfs_init(void)
+{
+ struct dentry *dent;
+
+ dent = debugfs_create_dir("n_smux", 0);
+ if (IS_ERR(dent))
+ return PTR_ERR(dent);
+
+ debug_create("ch", 0444, dent, smux_debug_ch);
+
+
+ return 0;
+}
+
+late_initcall(smux_debugfs_init);
diff --git a/drivers/tty/smux_private.h b/drivers/tty/smux_private.h
index 353c762..195ee0f 100644
--- a/drivers/tty/smux_private.h
+++ b/drivers/tty/smux_private.h
@@ -31,14 +31,70 @@
#define SMUX_UT_ECHO_ACK_FAIL 0xF2
/* Maximum number of packets in retry queue */
-#define SMUX_RX_RETRY_MAX_PKTS 32
-#define SMUX_RX_WM_HIGH 16
-#define SMUX_RX_WM_LOW 4
-#define SMUX_TX_WM_LOW 2
-#define SMUX_TX_WM_HIGH 4
+#define SMUX_RX_RETRY_MAX_PKTS 128
+#define SMUX_RX_WM_HIGH 4
+#define SMUX_RX_WM_LOW 0
+#define SMUX_TX_WM_LOW 2
+#define SMUX_TX_WM_HIGH 4
struct tty_struct;
+/**
+ * Logical Channel Structure. One instance per channel.
+ *
+ * Locking Hierarchy
+ * Each lock has a postfix that describes the locking level. If multiple locks
+ * are required, only increasing lock hierarchy numbers may be locked which
+ * ensures avoiding a deadlock.
+ *
+ * Locking Example
+ * If state_lock_lhb1 is currently held and the TX list needs to be
+ * manipulated, then tx_lock_lhb2 may be locked since it's locking hierarchy
+ * is greater. However, if tx_lock_lhb2 is held, then state_lock_lhb1 may
+ * not be acquired since it would result in a deadlock.
+ *
+ * Note that the Line Discipline locks (*_lha) should always be acquired
+ * before the logical channel locks.
+ */
+struct smux_lch_t {
+ /* channel state */
+ spinlock_t state_lock_lhb1;
+ uint8_t lcid;
+ unsigned local_state;
+ unsigned local_mode;
+ uint8_t local_tiocm;
+ unsigned options;
+
+ unsigned remote_state;
+ unsigned remote_mode;
+ uint8_t remote_tiocm;
+
+ int tx_flow_control;
+ int rx_flow_control_auto;
+ int rx_flow_control_client;
+
+ /* client callbacks and private data */
+ void *priv;
+ void (*notify)(void *priv, int event_type, const void *metadata);
+ int (*get_rx_buffer)(void *priv, void **pkt_priv, void **buffer,
+ int size);
+
+ /* RX Info */
+ struct list_head rx_retry_queue;
+ unsigned rx_retry_queue_cnt;
+ struct delayed_work rx_retry_work;
+
+ /* TX Info */
+ spinlock_t tx_lock_lhb2;
+ struct list_head tx_queue;
+ struct list_head tx_ready_list;
+ unsigned tx_pending_data_cnt;
+ unsigned notify_lwm;
+};
+
+/* Each instance of smux_lch_t */
+extern struct smux_lch_t smux_lch[SMUX_NUM_LOGICAL_CHANNELS];
+
/* Packet header. */
struct smux_hdr_t {
uint16_t magic;
@@ -102,6 +158,16 @@
SMUX_LCH_REMOTE_OPENED,
};
+/* Enum used to report various undefined actions */
+enum {
+ SMUX_UNDEF_LONG,
+ SMUX_UNDEF_SHORT,
+};
+
+long msm_smux_tiocm_get_atomic(struct smux_lch_t *ch);
+const char *local_lch_state(unsigned state);
+const char *remote_lch_state(unsigned state);
+const char *lch_mode(unsigned mode);
int smux_assert_lch_id(uint32_t lcid);
void smux_init_pkt(struct smux_pkt_t *pkt);
@@ -114,6 +180,7 @@
void smux_rx_state_machine(const unsigned char *data, int len, int flag);
void smuxld_receive_buf(struct tty_struct *tty, const unsigned char *cp,
char *fp, int count);
+bool smux_remote_is_active(void);
/* testing parameters */
extern int smux_byte_loopback;
diff --git a/drivers/tty/smux_test.c b/drivers/tty/smux_test.c
index 4c255a4..81ac04b 100644
--- a/drivers/tty/smux_test.c
+++ b/drivers/tty/smux_test.c
@@ -690,6 +690,7 @@
};
int i = 0;
int failed = 0;
+ int retry_count = 0;
int ret;
i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
@@ -701,7 +702,13 @@
i += smux_ut_basic_core(buf + i, max - i, test_data, __func__);
subsystem_restart("external_modem");
- msleep(5000);
+
+ do {
+ msleep(500);
+ ++retry_count;
+ UT_ASSERT_INT(retry_count, <, 20);
+ } while (!smux_remote_is_active() && !failed);
+
i += smux_ut_basic_core(buf + i, max - i, test_data, __func__);
break;
}
@@ -721,6 +728,7 @@
static struct smux_mock_callback cb_data;
static int cb_initialized;
int ret;
+ int retry_count;
int i = 0;
int failed = 0;
@@ -763,6 +771,14 @@
/* close port */
ret = msm_smux_close(SMUX_TEST_LCID);
UT_ASSERT_INT(ret, ==, 0);
+
+ /* wait for remote side to finish booting */
+ retry_count = 0;
+ do {
+ msleep(500);
+ ++retry_count;
+ UT_ASSERT_INT(retry_count, <, 20);
+ } while (!smux_remote_is_active() && !failed);
break;
}
@@ -795,6 +811,7 @@
static int cb_initialized;
int i = 0;
int failed = 0;
+ int retry_count;
int ret;
i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
@@ -841,12 +858,16 @@
subsystem_restart("external_modem");
/* verify SSR completed */
- UT_ASSERT_INT(ret, ==, 0);
- UT_ASSERT_INT(
- (int)wait_for_completion_timeout(
- &cb_data.cb_completion, 5*HZ),
- >, 0);
- UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ retry_count = 0;
+ while (cb_data.event_disconnected_ssr == 0) {
+ (void)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ);
+ INIT_COMPLETION(cb_data.cb_completion);
+ ++retry_count;
+ UT_ASSERT_INT(retry_count, <, 10);
+ }
+ if (failed)
+ break;
UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 1);
mock_cb_data_reset(&cb_data);
@@ -854,6 +875,14 @@
/* close port */
ret = msm_smux_close(SMUX_TEST_LCID);
UT_ASSERT_INT(ret, ==, 0);
+
+ /* wait for remote side to finish booting */
+ retry_count = 0;
+ do {
+ msleep(500);
+ ++retry_count;
+ UT_ASSERT_INT(retry_count, <, 20);
+ } while (!smux_remote_is_active() && !failed);
break;
}
@@ -1924,6 +1953,136 @@
return i;
}
+/**
+ * Verify remote flow control (remote TX stop).
+ *
+ * @buf Buffer for status message
+ * @max Size of buffer
+ *
+ * @returns Number of bytes written to @buf
+ */
+static int smux_ut_remote_tx_stop(char *buf, int max)
+{
+ static struct smux_mock_callback cb_data;
+ static int cb_initialized;
+ int i = 0;
+ int failed = 0;
+ int ret;
+
+ i += scnprintf(buf + i, max - i, "Running %s\n", __func__);
+ pr_err("%s", buf);
+
+ if (!cb_initialized)
+ mock_cb_data_init(&cb_data);
+
+ mock_cb_data_reset(&cb_data);
+ while (!failed) {
+ /* open port for remote loopback */
+ ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
+ SMUX_CH_OPTION_REMOTE_LOOPBACK, 0);
+ UT_ASSERT_INT(ret, ==, 0);
+
+ ret = msm_smux_open(SMUX_TEST_LCID, &cb_data, smux_mock_cb,
+ get_rx_buffer);
+ UT_ASSERT_INT(ret, ==, 0);
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ), >, 0);
+ UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ UT_ASSERT_INT(cb_data.event_connected, ==, 1);
+ mock_cb_data_reset(&cb_data);
+
+ /* send 1 packet and verify response */
+ ret = msm_smux_write(SMUX_TEST_LCID, (void *)1,
+ test_array, sizeof(test_array));
+ UT_ASSERT_INT(ret, ==, 0);
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ UT_ASSERT_INT(cb_data.event_write_done, ==, 1);
+
+ INIT_COMPLETION(cb_data.cb_completion);
+ if (!cb_data.event_read_done) {
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ }
+ UT_ASSERT_INT(cb_data.event_read_done, ==, 1);
+ mock_cb_data_reset(&cb_data);
+
+ /* enable flow control */
+ UT_ASSERT_INT(smux_lch[SMUX_TEST_LCID].tx_flow_control, ==, 0);
+ ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
+ SMUX_CH_OPTION_REMOTE_TX_STOP, 0);
+ UT_ASSERT_INT(ret, ==, 0);
+
+ /* wait for remote echo and clear our tx_flow control */
+ msleep(500);
+ UT_ASSERT_INT(smux_lch[SMUX_TEST_LCID].tx_flow_control, ==, 1);
+ smux_lch[SMUX_TEST_LCID].tx_flow_control = 0;
+
+ /* Send 1 packet and verify no response */
+ ret = msm_smux_write(SMUX_TEST_LCID, (void *)2,
+ test_array, sizeof(test_array));
+ UT_ASSERT_INT(ret, ==, 0);
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ INIT_COMPLETION(cb_data.cb_completion);
+ UT_ASSERT_INT(cb_data.event_write_done, ==, 1);
+ UT_ASSERT_INT(cb_data.event_read_done, ==, 0);
+ UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, 1*HZ),
+ ==, 0);
+ UT_ASSERT_INT(cb_data.event_read_done, ==, 0);
+ mock_cb_data_reset(&cb_data);
+
+ /* disable flow control and verify response is received */
+ UT_ASSERT_INT(cb_data.event_read_done, ==, 0);
+ ret = msm_smux_set_ch_option(SMUX_TEST_LCID,
+ 0, SMUX_CH_OPTION_REMOTE_TX_STOP);
+ UT_ASSERT_INT(ret, ==, 0);
+
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ UT_ASSERT_INT(cb_data.event_read_done, ==, 1);
+ mock_cb_data_reset(&cb_data);
+
+ /* close port */
+ ret = msm_smux_close(SMUX_TEST_LCID);
+ UT_ASSERT_INT(ret, ==, 0);
+ UT_ASSERT_INT(
+ (int)wait_for_completion_timeout(
+ &cb_data.cb_completion, HZ),
+ >, 0);
+ UT_ASSERT_INT(cb_data.cb_count, ==, 1);
+ UT_ASSERT_INT(cb_data.event_disconnected, ==, 1);
+ UT_ASSERT_INT(cb_data.event_disconnected_ssr, ==, 0);
+ break;
+ }
+
+ if (!failed) {
+ i += scnprintf(buf + i, max - i, "\tOK\n");
+ } else {
+ pr_err("%s: Failed\n", __func__);
+ i += scnprintf(buf + i, max - i, "\tFailed\n");
+ i += mock_cb_data_print(&cb_data, buf + i, max - i);
+ msm_smux_set_ch_option(SMUX_TEST_LCID,
+ 0, SMUX_CH_OPTION_REMOTE_TX_STOP);
+ msm_smux_close(SMUX_TEST_LCID);
+ }
+ mock_cb_data_reset(&cb_data);
+ return i;
+}
+
static char debug_buffer[DEBUG_BUFMAX];
static ssize_t debug_read(struct file *file, char __user *buf,
@@ -1961,7 +2120,7 @@
{
struct dentry *dent;
- dent = debugfs_create_dir("n_smux", 0);
+ dent = debugfs_create_dir("n_smux_test", 0);
if (IS_ERR(dent))
return PTR_ERR(dent);
@@ -1995,6 +2154,8 @@
smux_ut_remote_ssr_open);
debug_create("ut_remote_ssr_rx_buff_retry", 0444, dent,
smux_ut_remote_ssr_rx_buff_retry);
+ debug_create("ut_remote_tx_stop", 0444, dent,
+ smux_ut_remote_tx_stop);
return 0;
}
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 54ea85d..f517340 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -559,13 +559,6 @@
goto err1;
}
- ret = dwc3_host_init(dwc);
- if (ret) {
- dev_err(dev, "failed to initialize host\n");
- dwc3_otg_exit(dwc);
- goto err1;
- }
-
ret = dwc3_gadget_init(dwc);
if (ret) {
dev_err(dev, "failed to initialize gadget\n");
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 522e3a4..6917b2d 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -124,7 +124,11 @@
u8 ep_num_mapping[DBM_MAX_EPS];
const struct usb_ep_ops *original_ep_ops[DWC3_ENDPOINTS_NUM];
struct list_head req_complete_list;
+ struct clk *ref_clk;
struct clk *core_clk;
+ struct clk *iface_clk;
+ struct clk *sleep_clk;
+ struct clk *hsphy_sleep_clk;
struct regulator *hsusb_3p3;
struct regulator *hsusb_1p8;
struct regulator *hsusb_vddcx;
@@ -1227,7 +1231,9 @@
return 0;
}
+ clk_disable_unprepare(mdwc->iface_clk);
clk_disable_unprepare(mdwc->core_clk);
+ clk_disable_unprepare(mdwc->ref_clk);
dwc3_hsusb_ldo_enable(0);
dwc3_ssusb_ldo_enable(0);
wake_unlock(&mdwc->wlock);
@@ -1248,7 +1254,9 @@
}
wake_lock(&mdwc->wlock);
+ clk_prepare_enable(mdwc->ref_clk);
clk_prepare_enable(mdwc->core_clk);
+ clk_prepare_enable(mdwc->iface_clk);
dwc3_hsusb_ldo_enable(1);
dwc3_ssusb_ldo_enable(1);
@@ -1378,6 +1386,7 @@
struct platform_device *dwc3;
struct dwc3_msm *msm;
struct resource *res;
+ void __iomem *tcsr;
int ret = 0;
msm = devm_kzalloc(&pdev->dev, sizeof(*msm), GFP_KERNEL);
@@ -1406,6 +1415,38 @@
clk_set_rate(msm->core_clk, 125000000);
clk_prepare_enable(msm->core_clk);
+ msm->iface_clk = devm_clk_get(&pdev->dev, "iface_clk");
+ if (IS_ERR(msm->iface_clk)) {
+ dev_err(&pdev->dev, "failed to get iface_clk\n");
+ ret = PTR_ERR(msm->iface_clk);
+ goto disable_core_clk;
+ }
+ clk_prepare_enable(msm->iface_clk);
+
+ msm->sleep_clk = devm_clk_get(&pdev->dev, "sleep_clk");
+ if (IS_ERR(msm->sleep_clk)) {
+ dev_err(&pdev->dev, "failed to get sleep_clk\n");
+ ret = PTR_ERR(msm->sleep_clk);
+ goto disable_iface_clk;
+ }
+ clk_prepare_enable(msm->sleep_clk);
+
+ msm->hsphy_sleep_clk = devm_clk_get(&pdev->dev, "sleep_a_clk");
+ if (IS_ERR(msm->hsphy_sleep_clk)) {
+ dev_err(&pdev->dev, "failed to get sleep_a_clk\n");
+ ret = PTR_ERR(msm->hsphy_sleep_clk);
+ goto disable_sleep_clk;
+ }
+ clk_prepare_enable(msm->hsphy_sleep_clk);
+
+ msm->ref_clk = devm_clk_get(&pdev->dev, "ref_clk");
+ if (IS_ERR(msm->ref_clk)) {
+ dev_err(&pdev->dev, "failed to get ref_clk\n");
+ ret = PTR_ERR(msm->ref_clk);
+ goto disable_sleep_a_clk;
+ }
+ clk_prepare_enable(msm->ref_clk);
+
/* SS PHY */
msm->ss_vdd_type = VDDCX_CORNER;
msm->ssusb_vddcx = devm_regulator_get(&pdev->dev, "ssusb_vdd_dig");
@@ -1415,7 +1456,7 @@
if (IS_ERR(msm->ssusb_vddcx)) {
dev_err(&pdev->dev, "unable to get ssusb vddcx\n");
ret = PTR_ERR(msm->ssusb_vddcx);
- goto disable_core_clk;
+ goto disable_ref_clk;
}
msm->ss_vdd_type = VDDCX;
dev_dbg(&pdev->dev, "ss_vdd_type: VDDCX\n");
@@ -1424,7 +1465,7 @@
ret = dwc3_ssusb_config_vddcx(1);
if (ret) {
dev_err(&pdev->dev, "ssusb vddcx configuration failed\n");
- goto disable_core_clk;
+ goto disable_ref_clk;
}
ret = regulator_enable(context->ssusb_vddcx);
@@ -1484,6 +1525,25 @@
goto free_hs_ldo_init;
}
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res) {
+ dev_dbg(&pdev->dev, "missing TCSR memory resource\n");
+ } else {
+ tcsr = devm_ioremap_nocache(&pdev->dev, res->start,
+ resource_size(res));
+ if (!tcsr) {
+ dev_dbg(&pdev->dev, "tcsr ioremap failed\n");
+ } else {
+ /* Enable USB3 on the primary USB port. */
+ writel_relaxed(0x1, tcsr);
+ /*
+ * Ensure that TCSR write is completed before
+ * USB registers initialization.
+ */
+ mb();
+ }
+ }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "missing memory base resource\n");
@@ -1514,7 +1574,6 @@
msm->dwc3 = dwc3;
pm_runtime_set_active(msm->dev);
- pm_runtime_enable(msm->dev);
if (of_property_read_u32(node, "qcom,dwc-usb3-msm-dbm-eps",
&msm->dbm_num_eps)) {
@@ -1600,6 +1659,14 @@
regulator_disable(context->ssusb_vddcx);
unconfig_ss_vddcx:
dwc3_ssusb_config_vddcx(0);
+disable_ref_clk:
+ clk_disable_unprepare(msm->ref_clk);
+disable_sleep_a_clk:
+ clk_disable_unprepare(msm->hsphy_sleep_clk);
+disable_sleep_clk:
+ clk_disable_unprepare(msm->sleep_clk);
+disable_iface_clk:
+ clk_disable_unprepare(msm->iface_clk);
disable_core_clk:
clk_disable_unprepare(msm->core_clk);
@@ -1629,6 +1696,10 @@
regulator_disable(msm->ssusb_vddcx);
dwc3_ssusb_config_vddcx(0);
clk_disable_unprepare(msm->core_clk);
+ clk_disable_unprepare(msm->iface_clk);
+ clk_disable_unprepare(msm->sleep_clk);
+ clk_disable_unprepare(msm->hsphy_sleep_clk);
+ clk_disable_unprepare(msm->ref_clk);
return 0;
}
diff --git a/drivers/usb/gadget/f_adb.c b/drivers/usb/gadget/f_adb.c
index b997a3f..9778673 100644
--- a/drivers/usb/gadget/f_adb.c
+++ b/drivers/usb/gadget/f_adb.c
@@ -48,7 +48,6 @@
atomic_t read_excl;
atomic_t write_excl;
atomic_t open_excl;
- struct delayed_work adb_release_w;
struct list_head tx_idle;
@@ -410,11 +409,6 @@
return r;
}
-static void adb_release_work(struct work_struct *w)
-{
- adb_closed_callback();
-}
-
static int adb_open(struct inode *ip, struct file *fp)
{
pr_info("adb_open\n");
@@ -429,8 +423,7 @@
/* clear the error latch */
atomic_set(&_adb_dev->error, 0);
- if (!cancel_delayed_work_sync(&_adb_dev->adb_release_w))
- adb_ready_callback();
+ adb_ready_callback();
return 0;
}
@@ -439,16 +432,7 @@
{
pr_info("adb_release\n");
- /*
- * When USB cable is plugged out, adb reader is unblocked and
- * -EIO is returned to user space. adb daemon reopen the port
- * which would disable and enable USB configuration unnecessarily.
- *
- * Delay notifying the adb close event to android by 1 sec. If
- * ADB daemon opens the port with in 1 sec, USB configuration
- * re-enable does not happen.
- */
- schedule_delayed_work(&_adb_dev->adb_release_w, msecs_to_jiffies(1000));
+ adb_closed_callback();
adb_unlock(&_adb_dev->open_excl);
return 0;
@@ -624,7 +608,6 @@
atomic_set(&dev->read_excl, 0);
atomic_set(&dev->write_excl, 0);
- INIT_DELAYED_WORK(&dev->adb_release_w, adb_release_work);
INIT_LIST_HEAD(&dev->tx_idle);
_adb_dev = dev;
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c
index c16ff97..40b79a2 100644
--- a/drivers/usb/gadget/udc-core.c
+++ b/drivers/usb/gadget/udc-core.c
@@ -348,7 +348,6 @@
driver->unbind(udc->gadget);
goto err1;
}
- usb_gadget_connect(udc->gadget);
} else {
ret = usb_gadget_start(udc->gadget, driver, bind);
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 7309438..8d967cd 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -691,8 +691,7 @@
hw->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma);
/* clear interrupt enables, set irq latency */
- if (ehci->max_log2_irq_thresh)
- log2_irq_thresh = ehci->max_log2_irq_thresh;
+ log2_irq_thresh = ehci->log2_irq_thresh;
if (log2_irq_thresh < 0 || log2_irq_thresh > 6)
log2_irq_thresh = 0;
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index eebda9e..2126ff0 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -27,6 +27,7 @@
#include <linux/err.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include <linux/wakelock.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
@@ -58,13 +59,14 @@
struct clk *phy_clk;
struct clk *cal_clk;
struct regulator *hsic_vddcx;
+ bool async_int;
atomic_t in_lpm;
+ struct wake_lock wlock;
int peripheral_status_irq;
int wakeup_irq;
int wakeup_gpio;
bool wakeup_irq_enabled;
- bool irq_enabled;
- bool async_int;
+ atomic_t pm_usage_cnt;
uint32_t bus_perf_client;
uint32_t wakeup_int_cnt;
enum usb_vdd_type vdd_type;
@@ -354,21 +356,33 @@
static int ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
{
struct usb_hcd *hcd = hsic_to_hcd(mehci);
- unsigned long timeout;
+ int cnt = 0;
/* initiate read operation */
writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
USB_ULPI_VIEWPORT);
/* wait for completion */
- timeout = jiffies + usecs_to_jiffies(ULPI_IO_TIMEOUT_USEC);
- while (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN) {
- if (time_after(jiffies, timeout)) {
- dev_err(mehci->dev, "ulpi_read: timeout %08x\n",
- readl_relaxed(USB_ULPI_VIEWPORT));
- return -ETIMEDOUT;
- }
+ while (cnt < ULPI_IO_TIMEOUT_USEC) {
+ if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
+ break;
udelay(1);
+ cnt++;
+ }
+
+ if (cnt >= ULPI_IO_TIMEOUT_USEC) {
+ dev_err(mehci->dev, "ulpi_read: timeout ULPI_VIEWPORT: %08x\n",
+ readl_relaxed(USB_ULPI_VIEWPORT));
+ dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
+ readl_relaxed(USB_PORTSC),
+ readl_relaxed(USB_USBCMD),
+ readl_relaxed(USB_FRINDEX));
+
+ /*frame counter increments afte 125us*/
+ udelay(130);
+ dev_err(mehci->dev, "ulpi_read: FRINDEX: %08x\n",
+ readl_relaxed(USB_FRINDEX));
+ return -ETIMEDOUT;
}
return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
@@ -393,7 +407,17 @@
}
if (cnt >= ULPI_IO_TIMEOUT_USEC) {
- dev_err(mehci->dev, "ulpi_write: timeout\n");
+ dev_err(mehci->dev, "ulpi_write: timeout ULPI_VIEWPORT: %08x\n",
+ readl_relaxed(USB_ULPI_VIEWPORT));
+ dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
+ readl_relaxed(USB_PORTSC),
+ readl_relaxed(USB_USBCMD),
+ readl_relaxed(USB_FRINDEX));
+
+ /*frame counter increments afte 125us*/
+ udelay(130);
+ dev_err(mehci->dev, "ulpi_write: FRINDEX: %08x\n",
+ readl_relaxed(USB_FRINDEX));
return -ETIMEDOUT;
}
@@ -602,15 +626,13 @@
disable_irq(hcd->irq);
- /* make sure we don't race against the root hub being resumed */
- if (HCD_RH_RUNNING(hcd) || HCD_WAKEUP_PENDING(hcd) ||
+ /* make sure we don't race against a remote wakeup */
+ if (test_bit(HCD_FLAG_WAKEUP_PENDING, &hcd->flags) ||
readl_relaxed(USB_PORTSC) & PORT_RESUME) {
- dev_warn(mehci->dev, "%s: Root hub is not suspended\n",
- __func__);
+ dev_dbg(mehci->dev, "wakeup pending, aborting suspend\n");
enable_irq(hcd->irq);
return -EBUSY;
}
- mehci->irq_enabled = false;
/*
* PHY may take some time or even fail to enter into low power
@@ -668,13 +690,14 @@
}
atomic_set(&mehci->in_lpm, 1);
- mehci->irq_enabled = true;
enable_irq(hcd->irq);
mehci->wakeup_irq_enabled = 1;
enable_irq_wake(mehci->wakeup_irq);
enable_irq(mehci->wakeup_irq);
+ wake_unlock(&mehci->wlock);
+
dev_info(mehci->dev, "HSIC-USB in low power mode\n");
return 0;
@@ -698,6 +721,8 @@
mehci->wakeup_irq_enabled = 0;
}
+ wake_lock(&mehci->wlock);
+
if (mehci->bus_perf_client && debug_bus_voting_enabled) {
mehci->bus_vote = true;
queue_work(ehci_wq, &mehci->bus_vote_w);
@@ -753,14 +778,13 @@
if (mehci->async_int) {
mehci->async_int = false;
pm_runtime_put_noidle(mehci->dev);
- }
-
- if (!mehci->irq_enabled) {
enable_irq(hcd->irq);
- mehci->irq_enabled = true;
}
- pm_relax(mehci->dev);
+ if (atomic_read(&mehci->pm_usage_cnt)) {
+ atomic_set(&mehci->pm_usage_cnt, 0);
+ pm_runtime_put_noidle(mehci->dev);
+ }
dev_info(mehci->dev, "HSIC-USB exited from low power mode\n");
@@ -787,11 +811,9 @@
if (atomic_read(&mehci->in_lpm)) {
disable_irq_nosync(hcd->irq);
- mehci->irq_enabled = false;
dev_dbg(mehci->dev, "phy async intr\n");
mehci->async_int = true;
pm_runtime_get(mehci->dev);
- pm_stay_awake(mehci->dev);
return IRQ_HANDLED;
}
@@ -1008,9 +1030,7 @@
dev_dbg(mehci->dev, "%s: hsic remote wakeup interrupt cnt: %u\n",
__func__, mehci->wakeup_int_cnt);
- mehci->async_int = true;
- pm_runtime_get(mehci->dev);
- pm_stay_awake(mehci->dev);
+ wake_lock(&mehci->wlock);
if (mehci->wakeup_irq_enabled) {
mehci->wakeup_irq_enabled = 0;
@@ -1018,6 +1038,11 @@
disable_irq_nosync(irq);
}
+ if (!atomic_read(&mehci->pm_usage_cnt)) {
+ atomic_set(&mehci->pm_usage_cnt, 1);
+ pm_runtime_get(mehci->dev);
+ }
+
return IRQ_HANDLED;
}
@@ -1265,13 +1290,15 @@
mehci = hcd_to_hsic(hcd);
mehci->dev = &pdev->dev;
+ pdata = mehci->dev->platform_data;
mehci->ehci.susp_sof_bug = 1;
mehci->ehci.reset_sof_bug = 1;
mehci->ehci.resume_sof_bug = 1;
- mehci->ehci.max_log2_irq_thresh = 6;
+ if (pdata)
+ mehci->ehci.log2_irq_thresh = pdata->log2_irq_thresh;
res = platform_get_resource_byname(pdev,
IORESOURCE_IRQ,
@@ -1321,8 +1348,9 @@
goto unconfig_gpio;
}
- mehci->irq_enabled = true;
device_init_wakeup(&pdev->dev, 1);
+ wake_lock_init(&mehci->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
+ wake_lock(&mehci->wlock);
if (mehci->peripheral_status_irq) {
ret = request_threaded_irq(mehci->peripheral_status_irq,
@@ -1354,7 +1382,6 @@
dev_dbg(&pdev->dev, "mode debugfs file is"
"not available\n");
- pdata = mehci->dev->platform_data;
if (pdata && pdata->bus_scale_table) {
mehci->bus_perf_client =
msm_bus_scale_register_client(pdata->bus_scale_table);
@@ -1437,6 +1464,7 @@
msm_hsic_init_vddcx(mehci, 0);
msm_hsic_init_clocks(mehci, 0);
+ wake_lock_destroy(&mehci->wlock);
iounmap(hcd->regs);
usb_put_hcd(hcd);
diff --git a/drivers/usb/host/ehci-msm2.c b/drivers/usb/host/ehci-msm2.c
index c612cb9..34d90fb 100644
--- a/drivers/usb/host/ehci-msm2.c
+++ b/drivers/usb/host/ehci-msm2.c
@@ -59,6 +59,7 @@
uint32_t pmic_gpio_int_cnt;
atomic_t pm_usage_cnt;
struct wake_lock wlock;
+ struct work_struct phy_susp_fail_work;
};
static inline struct msm_hcd *hcd_to_mhcd(struct usb_hcd *hcd)
@@ -539,6 +540,19 @@
return 0;
}
+static void msm_ehci_phy_susp_fail_work(struct work_struct *w)
+{
+ struct msm_hcd *mhcd = container_of(w, struct msm_hcd,
+ phy_susp_fail_work);
+ struct usb_hcd *hcd = mhcd_to_hcd(mhcd);
+
+ msm_ehci_vbus_power(mhcd, 0);
+ usb_remove_hcd(hcd);
+ msm_hsusb_reset(mhcd);
+ usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
+ msm_ehci_vbus_power(mhcd, 1);
+}
+
#define PHY_SUSPEND_TIMEOUT_USEC (500 * 1000)
#define PHY_RESUME_TIMEOUT_USEC (100 * 1000)
@@ -571,8 +585,8 @@
while (!(readl_relaxed(USB_PORTSC) & PORTSC_PHCD)) {
if (time_after(jiffies, timeout)) {
dev_err(mhcd->dev, "Unable to suspend PHY\n");
- msm_hsusb_reset(mhcd);
- break;
+ schedule_work(&mhcd->phy_susp_fail_work);
+ return -ETIMEDOUT;
}
udelay(1);
}
@@ -992,6 +1006,7 @@
device_init_wakeup(&pdev->dev, 1);
wake_lock_init(&mhcd->wlock, WAKE_LOCK_SUSPEND, dev_name(&pdev->dev));
wake_lock(&mhcd->wlock);
+ INIT_WORK(&mhcd->phy_susp_fail_work, msm_ehci_phy_susp_fail_work);
/*
* This pdev->dev is assigned parent of root-hub by USB core,
* hence, runtime framework automatically calls this driver's
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index a0f995c..f8b884a 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -135,7 +135,7 @@
ktime_t last_periodic_enable;
u32 command;
- unsigned max_log2_irq_thresh;
+ unsigned log2_irq_thresh;
/* SILICON QUIRKS */
unsigned no_selective_suspend:1;
diff --git a/drivers/usb/misc/ks_bridge.c b/drivers/usb/misc/ks_bridge.c
index 10cbe59..be8b58b 100644
--- a/drivers/usb/misc/ks_bridge.c
+++ b/drivers/usb/misc/ks_bridge.c
@@ -58,6 +58,7 @@
struct list_head to_mdm_list;
struct list_head to_ks_list;
wait_queue_head_t ks_wait_q;
+ struct miscdevice *fs_dev;
/* usb specific */
struct usb_device *udev;
@@ -531,7 +532,6 @@
struct usb_endpoint_descriptor *ep_desc;
int i;
struct ks_bridge *ksb;
- struct miscdevice *fs_dev;
ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;
@@ -585,8 +585,8 @@
dbg_log_event(ksb, "PID-ATT", id->idProduct, 0);
- fs_dev = (struct miscdevice *)id->driver_info;
- misc_register(fs_dev);
+ ksb->fs_dev = (struct miscdevice *)id->driver_info;
+ misc_register(ksb->fs_dev);
usb_enable_autosuspend(ksb->udev);
@@ -649,6 +649,7 @@
}
spin_unlock_irqrestore(&ksb->lock, flags);
+ misc_deregister(ksb->fs_dev);
usb_put_dev(ksb->udev);
ksb->ifc = NULL;
usb_set_intfdata(ifc, NULL);
@@ -713,7 +714,8 @@
ksb = kzalloc(sizeof(struct ks_bridge), GFP_KERNEL);
if (!ksb) {
pr_err("unable to allocat mem for ks_bridge");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto dev_free;
}
__ksb[i] = ksb;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 0ef8249..f5bad19 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -760,6 +760,14 @@
test_bit(A_BUS_SUSPEND, &motg->inputs) &&
motg->caps & ALLOW_LPM_ON_DEV_SUSPEND;
dcp = motg->chg_type == USB_DCP_CHARGER;
+
+ /* charging detection in progress due to cable plug-in */
+ if (test_bit(B_SESS_VLD, &motg->inputs) && !device_bus_suspend &&
+ !dcp) {
+ enable_irq(motg->irq);
+ return -EBUSY;
+ }
+
/*
* Chipidea 45-nm PHY suspend sequence:
*
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 0976fc6..c6ffaf2 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -1418,7 +1418,7 @@
video_format, video_format_2string(video_format),
supported ? "Supported" : "Not-Supported");
if (supported) {
- if (mhl_is_connected()) {
+ if (mhl_is_enabled()) {
const struct hdmi_disp_mode_timing_type *mhl_timing =
hdmi_mhl_get_supported_mode(video_format);
boolean mhl_supported = mhl_timing != NULL;
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 26e5687..ade9691 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -917,22 +917,34 @@
*/
if (external_common_state->present_hdcp) {
hdcp_deauthenticate();
+ mutex_lock(&hdcp_auth_state_mutex);
+ hdmi_msm_state->reauth = TRUE;
+ mutex_unlock(&hdcp_auth_state_mutex);
mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
}
}
static void hdmi_msm_hdcp_work(struct work_struct *work)
{
-
/* Only re-enable if cable still connected */
mutex_lock(&external_common_state_hpd_mutex);
if (external_common_state->hpd_state &&
!(hdmi_msm_state->full_auth_done)) {
mutex_unlock(&external_common_state_hpd_mutex);
- hdmi_msm_state->reauth = TRUE;
- hdmi_msm_turn_on();
- } else
+ if (hdmi_msm_state->reauth == TRUE) {
+ DEV_DBG("%s: Starting HDCP re-authentication\n",
+ __func__);
+ hdmi_msm_turn_on();
+ } else {
+ DEV_DBG("%s: Starting HDCP authentication\n", __func__);
+ hdmi_msm_hdcp_enable();
+ }
+ } else {
mutex_unlock(&external_common_state_hpd_mutex);
+ DEV_DBG("%s: HDMI not connected or HDCP already active\n",
+ __func__);
+ hdmi_msm_state->reauth = FALSE;
+ }
}
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
@@ -4342,15 +4354,6 @@
DEV_INFO("power: ON (%dx%d %d)\n", mfd->var_xres, mfd->var_yres,
mfd->var_pixclock);
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
- mutex_lock(&hdmi_msm_state_mutex);
- if (hdmi_msm_state->hdcp_activating) {
- hdmi_msm_state->panel_power_on = TRUE;
- DEV_INFO("HDCP: activating, returning\n");
- }
- mutex_unlock(&hdmi_msm_state_mutex);
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
-
changed = hdmi_common_get_video_format_from_drv_data(mfd);
hdmi_msm_audio_info_setup(TRUE, 0, 0, 0, FALSE);
@@ -4360,7 +4363,13 @@
DEV_DBG("%s: Turning HDMI on\n", __func__);
mutex_unlock(&external_common_state_hpd_mutex);
hdmi_msm_turn_on();
- hdmi_msm_hdcp_enable();
+
+ /* Kick off HDCP Authentication */
+ mutex_lock(&hdcp_auth_state_mutex);
+ hdmi_msm_state->reauth = FALSE;
+ hdmi_msm_state->full_auth_done = FALSE;
+ mutex_unlock(&hdcp_auth_state_mutex);
+ mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
} else
mutex_unlock(&external_common_state_hpd_mutex);
@@ -4448,6 +4457,11 @@
return 0;
}
+bool mhl_is_enabled(void)
+{
+ return hdmi_msm_state->is_mhl_enabled;
+}
+
static int __devinit hdmi_msm_probe(struct platform_device *pdev)
{
int rc;
@@ -4620,6 +4634,12 @@
if (switch_dev_register(&external_common_state->sdev) < 0)
DEV_ERR("Hdmi switch registration failed\n");
+ /* Set the default video resolution for MHL-enabled display */
+ if (hdmi_msm_state->is_mhl_enabled) {
+ DEV_DBG("MHL Enabled. Restricting default video resolution\n");
+ external_common_state->video_resolution =
+ HDMI_VFRMT_1920x1080p30_16_9;
+ }
return 0;
error:
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index cc4eae5..13a922f 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -557,6 +557,7 @@
int mdp4_overlay_commit(struct fb_info *info, int mixer);
int mdp4_dsi_video_pipe_commit(void);
int mdp4_dsi_cmd_pipe_commit(void);
+int mdp4_dsi_cmd_update_cnt(int cndx);
int mdp4_lcdc_pipe_commit(void);
int mdp4_dtv_pipe_commit(void);
void mdp4_dsi_rdptr_init(int cndx);
@@ -853,9 +854,6 @@
void mdp4_dsi_video_3d_sbys(struct msm_fb_data_type *mfd,
struct msmfb_overlay_3d *r3d);
-void mdp4_backlight_init(int cndx);
-void mdp4_backlight_put_level(int cndx, int level);
-
int mdp4_mixer_info(int mixer_num, struct mdp_mixer_info *info);
void mdp_dmap_vsync_set(int enable);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 89ae254..a1ec2db 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -150,6 +150,9 @@
ion_unmap_iommu(display_iclient, ihdl, DISPLAY_READ_DOMAIN,
GEN_POOL);
mdp4_stat.iommu_unmap++;
+ pr_debug("%s: map=%d unmap=%d drop=%d\n", __func__,
+ (int)mdp4_stat.iommu_map, (int)mdp4_stat.iommu_unmap,
+ (int)mdp4_stat.iommu_drop);
ion_free(display_iclient, ihdl);
flist->ihdl[i] = NULL;
}
@@ -1608,8 +1611,8 @@
data |= ctrl->mixer_cfg[num];
off = 0x10100;
}
- pr_debug("%s: mixer=%d data=%x flush=%x\n", __func__,
- mixer, data, ctrl->flush[mixer]);
+ pr_debug("%s: mixer=%d data=%x flush=%x pid=%d\n", __func__,
+ mixer, data, ctrl->flush[mixer], current->pid);
}
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
@@ -2734,7 +2737,6 @@
}
if (mfd->panel_info.pdest == DISPLAY_1 &&
perf_req->use_ov0_blt && !perf_cur->use_ov0_blt) {
- mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
if (mfd->panel_info.type == LCDC_PANEL ||
mfd->panel_info.type == LVDS_PANEL)
mdp4_lcdc_overlay_blt_start(mfd);
@@ -2751,7 +2753,6 @@
}
if (mfd->panel_info.pdest == DISPLAY_2 &&
perf_req->use_ov1_blt && !perf_cur->use_ov1_blt) {
- mdp4_allocate_writeback_buf(mfd, MDP4_MIXER1);
mdp4_dtv_overlay_blt_start(mfd);
pr_info("%s mixer1 start blt [%d] from %d to %d.\n",
__func__,
@@ -2791,7 +2792,6 @@
mdp4_dsi_video_blt_stop(mfd);
else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
mdp4_dsi_cmd_blt_stop(mfd);
- mdp4_free_writeback_buf(mfd, MDP4_MIXER0);
pr_info("%s mixer0 stop blt [%d] from %d to %d.\n",
__func__,
flag,
@@ -2802,7 +2802,6 @@
if (mfd->panel_info.pdest == DISPLAY_2 &&
!perf_req->use_ov1_blt && perf_cur->use_ov1_blt) {
mdp4_dtv_overlay_blt_stop(mfd);
- mdp4_free_writeback_buf(mfd, MDP4_MIXER1);
pr_info("%s mixer1 stop blt [%d] from %d to %d.\n",
__func__,
flag,
@@ -3007,7 +3006,8 @@
struct mdp4_overlay_pipe *pipe;
int i, cnt = 0;
- for (i = MDP4_MIXER_STAGE3; i >= MDP4_MIXER_STAGE_BASE; i--) {
+ /* free pipe besides base layer pipe */
+ for (i = MDP4_MIXER_STAGE3; i > MDP4_MIXER_STAGE_BASE; i--) {
pipe = ctrl->stage[mixer][i];
if (pipe == NULL)
continue;
@@ -3222,9 +3222,7 @@
return 0;
}
- if (pipe->mixer_num == MDP4_MIXER2 ||
- ctrl->panel_mode & MDP4_PANEL_MDDI)
- mutex_lock(&mfd->dma->ov_mutex);
+ mutex_lock(&mfd->dma->ov_mutex);
img = &req->data;
get_img(img, info, pipe, 0, &start, &len, &srcp0_file,
@@ -3354,6 +3352,7 @@
mdp4_dtv_pipe_queue(0, pipe);/* cndx = 0 */
}
+ mutex_unlock(&mfd->dma->ov_mutex);
return ret;
mddi:
@@ -3385,8 +3384,10 @@
if (!(pipe->flags & MDP_OV_PLAY_NOWAIT))
mdp4_iommu_unmap(pipe);
mdp4_stat.overlay_play[pipe->mixer_num]++;
- mutex_unlock(&mfd->dma->ov_mutex);
+
end:
+ mutex_unlock(&mfd->dma->ov_mutex);
+
#ifdef CONFIG_ANDROID_PMEM
if (srcp0_file)
put_pmem_file(srcp0_file);
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 36a6b2a..6f78305 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -28,8 +28,8 @@
#include "mdp.h"
#include "msm_fb.h"
-#include "mdp4.h"
#include "mipi_dsi.h"
+#include "mdp4.h"
static int dsi_state;
@@ -40,14 +40,6 @@
#define MAX_CONTROLLER 1
#define VSYNC_EXPIRE_TICK 4
-#define BACKLIGHT_MAX 4
-
-struct backlight {
- int put;
- int get;
- int tot;
- int blist[BACKLIGHT_MAX];
-};
static struct vsycn_ctrl {
struct device *dev;
@@ -75,7 +67,6 @@
struct msm_fb_data_type *mfd;
struct mdp4_overlay_pipe *base_pipe;
struct vsync_update vlist[2];
- struct backlight blight;
int vsync_enabled;
int clk_enabled;
int clk_control;
@@ -108,68 +99,6 @@
spin_unlock_irqrestore(&mdp_spin_lock, flag);
}
-static int mdp4_backlight_get_level(struct vsycn_ctrl *vctrl)
-{
- int level = -1;
-
- mutex_lock(&vctrl->update_lock);
- if (vctrl->blight.tot) {
- level = vctrl->blight.blist[vctrl->blight.get];
- vctrl->blight.get++;
- vctrl->blight.get %= BACKLIGHT_MAX;
- vctrl->blight.tot--;
- pr_debug("%s: tot=%d put=%d get=%d level=%d\n", __func__,
- vctrl->blight.tot, vctrl->blight.put, vctrl->blight.get, level);
- }
- mutex_unlock(&vctrl->update_lock);
- return level;
-}
-
-void mdp4_backlight_put_level(int cndx, int level)
-{
- struct vsycn_ctrl *vctrl;
-
- if (cndx >= MAX_CONTROLLER) {
- pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
- return;
- }
-
- vctrl = &vsync_ctrl_db[cndx];
- mutex_lock(&vctrl->update_lock);
- vctrl->blight.blist[vctrl->blight.put] = level;
- vctrl->blight.put++;
- vctrl->blight.put %= BACKLIGHT_MAX;
- if (vctrl->blight.tot == BACKLIGHT_MAX) {
- /* drop the oldest one */
- vctrl->blight.get++;
- vctrl->blight.get %= BACKLIGHT_MAX;
- } else {
- vctrl->blight.tot++;
- }
- mutex_unlock(&vctrl->update_lock);
- pr_debug("%s: tot=%d put=%d get=%d level=%d\n", __func__,
- vctrl->blight.tot, vctrl->blight.put, vctrl->blight.get, level);
-
- if (mdp4_overlay_dsi_state_get() <= ST_DSI_SUSPEND)
- return;
-}
-
-static int mdp4_backlight_commit_level(struct vsycn_ctrl *vctrl)
-{
- int level;
- int cnt = 0;
-
- if (vctrl->blight.tot) { /* has new backlight */
- if (mipi_dsi_ctrl_lock(0)) {
- level = mdp4_backlight_get_level(vctrl);
- mipi_dsi_cmd_backlight_tx(level);
- cnt++;
- }
- }
-
- return cnt;
-}
-
static void mdp4_dsi_cmd_blt_ov_update(struct mdp4_overlay_pipe *pipe)
{
uint32 off, addr;
@@ -327,6 +256,7 @@
struct vsycn_ctrl *vctrl;
struct vsync_update *vp;
struct mdp4_overlay_pipe *pipe;
+ struct mdp4_overlay_pipe *real_pipe;
unsigned long flags;
int need_dmap_wait = 0;
int need_ov_wait = 0;
@@ -355,9 +285,6 @@
}
mutex_unlock(&vctrl->update_lock);
-
- mdp4_backlight_commit_level(vctrl);
-
/* free previous committed iommu back to pool */
mdp4_overlay_iommu_unmap_freelist(mixer);
@@ -410,7 +337,11 @@
for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
if (pipe->pipe_used) {
cnt++;
- mdp4_overlay_vsync_commit(pipe);
+ real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);
+ if (real_pipe && real_pipe->pipe_used) {
+ /* pipe not unset */
+ mdp4_overlay_vsync_commit(pipe);
+ }
/* free previous iommu to freelist
* which will be freed at next
* pipe_commit
@@ -420,6 +351,9 @@
}
}
+ /* tx dcs command if had any */
+ mipi_dsi_cmdlist_commit(1);
+
mdp4_mixer_stage_commit(mixer);
pipe = vctrl->base_pipe;
@@ -687,9 +621,6 @@
vctrl->inited = 1;
vctrl->update_ndx = 0;
- vctrl->blight.put = 0;
- vctrl->blight.get = 0;
- vctrl->blight.tot = 0;
mutex_init(&vctrl->update_lock);
init_completion(&vctrl->ov_comp);
init_completion(&vctrl->dmap_comp);
@@ -1029,8 +960,8 @@
atomic_set(&vctrl->suspend, 1);
- mipi_dsi_cmd_backlight_tx(150);
-
+ /* sanity check, free pipes besides base layer */
+ mdp4_overlay_unset_mixer(pipe->mixer_num);
mdp4_mixer_stage_down(pipe);
mdp4_overlay_pipe_free(pipe);
vctrl->base_pipe = NULL;
@@ -1102,8 +1033,10 @@
}
mdp4_overlay_mdp_perf_upd(mfd, 1);
-
+ mutex_lock(&mfd->dma->ov_mutex);
mdp4_dsi_cmd_pipe_commit();
+ mutex_unlock(&mfd->dma->ov_mutex);
+
mdp4_dsi_cmd_wait4vsync(0, &xx);
vctrl->expire_tick = VSYNC_EXPIRE_TICK;
vctrl->clk_control = 1;
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index cf9e635..a461c3b 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -137,7 +137,7 @@
__func__, undx, (int)pipe, pipe->pipe_ndx, pipe->pipe_num,
current->pid);
- *pp = *pipe; /* keep it */
+ *pp = *pipe; /* clone it */
vp->update_cnt++;
mutex_unlock(&vctrl->update_lock);
mdp4_stat.overlay_play[pipe->mixer_num]++;
@@ -155,6 +155,7 @@
struct vsycn_ctrl *vctrl;
struct vsync_update *vp;
struct mdp4_overlay_pipe *pipe;
+ struct mdp4_overlay_pipe *real_pipe;
unsigned long flags;
int cnt = 0;
@@ -212,7 +213,11 @@
for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
if (pipe->pipe_used) {
cnt++;
- mdp4_overlay_vsync_commit(pipe);
+ real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);
+ if (real_pipe && real_pipe->pipe_used) {
+ /* pipe not unset */
+ mdp4_overlay_vsync_commit(pipe);
+ }
/* free previous iommu to freelist
* which will be freed at next
* pipe_commit
@@ -658,12 +663,12 @@
dsi_video_enabled = 0;
if (pipe) {
+ /* sanity check, free pipes besides base layer */
+ mdp4_overlay_unset_mixer(pipe->mixer_num);
if (mfd->ref_cnt == 0) {
/* adb stop */
if (pipe->pipe_type == OVERLAY_TYPE_BF)
mdp4_overlay_borderfill_stage_down(pipe);
-
- mdp4_overlay_unset_mixer(pipe->mixer_num);
vctrl->base_pipe = NULL;
} else {
/* system suspending */
@@ -927,6 +932,8 @@
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
+ mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
+
if (mfd->ov0_wb_buf->write_addr == 0) {
pr_info("%s: no blt_base assigned\n", __func__);
return;
@@ -1010,7 +1017,9 @@
mdp4_overlay_mdp_perf_upd(mfd, 1);
+ mutex_lock(&mfd->dma->ov_mutex);
mdp4_dsi_video_pipe_commit();
+ mutex_unlock(&mfd->dma->ov_mutex);
if (pipe->ov_blt_addr)
mdp4_dsi_video_wait4ov(0);
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index 128a3c6..00f44d4 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -155,13 +155,14 @@
pr_debug("%s: vndx=%d pipe_ndx=%d flags=%x pid=%d\n",
__func__, undx, pipe->pipe_ndx, pipe->flags, current->pid);
- *pp = *pipe; /* keep it */
+ *pp = *pipe; /* clone it */
vp->update_cnt++;
mutex_unlock(&vctrl->update_lock);
mdp4_stat.overlay_play[pipe->mixer_num]++;
}
static void mdp4_dtv_blt_ov_update(struct mdp4_overlay_pipe *pipe);
+static void mdp4_dtv_wait4dmae(int cndx);
int mdp4_dtv_pipe_commit(void)
{
@@ -171,6 +172,7 @@
struct vsycn_ctrl *vctrl;
struct vsync_update *vp;
struct mdp4_overlay_pipe *pipe;
+ struct mdp4_overlay_pipe *real_pipe;
unsigned long flags;
int cnt = 0;
@@ -196,7 +198,11 @@
for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
if (pipe->pipe_used) {
cnt++;
- mdp4_overlay_vsync_commit(pipe);
+ real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);
+ if (real_pipe && real_pipe->pipe_used) {
+ /* pipe not unset */
+ mdp4_overlay_vsync_commit(pipe);
+ }
/* free previous iommu to freelist
* which will be freed at next
* pipe_commit
@@ -221,7 +227,7 @@
/* kickoff overlay1 engine */
mdp4_stat.kickoff_ov1++;
outpdw(MDP_BASE + 0x0008, 0);
- } else if (vctrl->dmae_intr_cnt == 0) {
+ } else {
/* schedule second phase update at dmap */
INIT_COMPLETION(vctrl->dmae_comp);
vsync_irq_enable(INTR_DMA_E_DONE, MDP_DMA_E_TERM);
@@ -570,13 +576,14 @@
pipe = vctrl->base_pipe;
if (pipe != NULL) {
mdp4_dtv_stop(mfd);
+ /* sanity check, free pipes besides base layer */
+ mdp4_overlay_unset_mixer(pipe->mixer_num);
if (hdmi_prim_display && mfd->ref_cnt == 0) {
/* adb stop */
if (pipe->pipe_type == OVERLAY_TYPE_BF)
mdp4_overlay_borderfill_stage_down(pipe);
/* pipe == rgb2 */
- mdp4_overlay_unset_mixer(pipe->mixer_num);
vctrl->base_pipe = NULL;
} else {
mdp4_mixer_stage_down(pipe);
@@ -789,8 +796,6 @@
vctrl->vsync_time = ktime_get();
schedule_work(&vctrl->vsync_work);
- pr_debug("%s: cpu=%d\n", __func__, smp_processor_id());
-
spin_lock(&vctrl->spin_lock);
if (vctrl->wait_vsync_cnt) {
complete_all(&vctrl->vsync_comp);
@@ -816,6 +821,7 @@
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
+ pr_debug("%s: cpu=%d\n", __func__, smp_processor_id());
spin_lock(&vctrl->spin_lock);
if (vctrl->blt_change) {
@@ -834,14 +840,8 @@
vctrl->blt_change = 0;
}
- vctrl->dmae_intr_cnt--;
- if (vctrl->dmae_wait_cnt) {
- complete_all(&vctrl->dmae_comp);
- vctrl->dmae_wait_cnt = 0; /* reset */
- } else {
- mdp4_overlay_dma_commit(MDP4_MIXER1);
- }
-
+ complete_all(&vctrl->dmae_comp);
+ mdp4_overlay_dma_commit(MDP4_MIXER1);
vsync_irq_disable(INTR_DMA_E_DONE, MDP_DMA_E_TERM);
spin_unlock(&vctrl->spin_lock);
}
@@ -1005,5 +1005,8 @@
pipe->srcp0_addr = (uint32)mfd->ibuf.buf;
mdp4_dtv_pipe_queue(0, pipe);
}
+
+ mutex_lock(&mfd->dma->ov_mutex);
mdp4_dtv_pipe_commit();
+ mutex_unlock(&mfd->dma->ov_mutex);
}
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index e10d795..08c3815 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -142,7 +142,7 @@
pr_debug("%s: vndx=%d pipe_ndx=%d pid=%d\n", __func__,
undx, pipe->pipe_ndx, current->pid);
- *pp = *pipe; /* keep it */
+ *pp = *pipe; /* clone it */
vp->update_cnt++;
mutex_unlock(&vctrl->update_lock);
mdp4_stat.overlay_play[pipe->mixer_num]++;
@@ -160,6 +160,7 @@
struct vsycn_ctrl *vctrl;
struct vsync_update *vp;
struct mdp4_overlay_pipe *pipe;
+ struct mdp4_overlay_pipe *real_pipe;
unsigned long flags;
int cnt = 0;
@@ -216,7 +217,11 @@
for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
if (pipe->pipe_used) {
cnt++;
- mdp4_overlay_vsync_commit(pipe);
+ real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);
+ if (real_pipe && real_pipe->pipe_used) {
+ /* pipe not unset */
+ mdp4_overlay_vsync_commit(pipe);
+ }
/* free previous iommu to freelist
* which will be freed at next
* pipe_commit
@@ -647,12 +652,12 @@
lcdc_enabled = 0;
if (pipe) {
+ /* sanity check, free pipes besides base layer */
+ mdp4_overlay_unset_mixer(pipe->mixer_num);
if (mfd->ref_cnt == 0) {
/* adb stop */
if (pipe->pipe_type == OVERLAY_TYPE_BF)
mdp4_overlay_borderfill_stage_down(pipe);
-
- mdp4_overlay_unset_mixer(pipe->mixer_num);
vctrl->base_pipe = NULL;
} else {
/* system suspending */
@@ -900,7 +905,9 @@
mdp4_overlay_mdp_perf_upd(mfd, 1);
+ mutex_lock(&mfd->dma->ov_mutex);
mdp4_lcdc_pipe_commit();
+ mutex_unlock(&mfd->dma->ov_mutex);
if (pipe->ov_blt_addr)
mdp4_lcdc_wait4ov(0);
diff --git a/drivers/video/msm/mdss/mdss.h b/drivers/video/msm/mdss/mdss.h
index 6145d67..675df03 100644
--- a/drivers/video/msm/mdss/mdss.h
+++ b/drivers/video/msm/mdss/mdss.h
@@ -18,10 +18,9 @@
#include <linux/types.h>
#include <linux/workqueue.h>
-#define MDSS_REG_WRITE(addr, val) writel_relaxed(val, mdss_reg_base + addr)
-#define MDSS_REG_READ(addr) readl_relaxed(mdss_reg_base + addr)
+#define MDSS_REG_WRITE(addr, val) writel_relaxed(val, mdss_res->mdp_base + addr)
+#define MDSS_REG_READ(addr) readl_relaxed(mdss_res->mdp_base + addr)
-extern unsigned char *mdss_reg_base;
extern spinlock_t dsi_clk_lock;
enum mdss_mdp_clk_type {
@@ -34,7 +33,7 @@
MDSS_MAX_CLK
};
-struct mdss_res_type {
+struct mdss_data_type {
u32 rev;
u32 mdp_rev;
struct clk *mdp_clk[MDSS_MAX_CLK];
@@ -42,6 +41,9 @@
struct workqueue_struct *clk_ctrl_wq;
struct delayed_work clk_ctrl_worker;
+ struct platform_device *pdev;
+ char __iomem *mdp_base;
+ char __iomem *vbif_base;
u32 irq;
u32 irq_mask;
@@ -69,7 +71,7 @@
u32 *pipe_type_map;
u32 *mixer_type_map;
};
-extern struct mdss_res_type *mdss_res;
+extern struct mdss_data_type *mdss_res;
enum mdss_hw_index {
MDSS_HW_MDP,
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index d051828..8c61be9 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -17,14 +17,154 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of_device.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
#include "mdss.h"
#include "mdss_panel.h"
#include "mdss_dsi.h"
-static struct mdss_panel_common_pdata *panel_pdata;
+static struct mdss_dsi_drv_pdata dsi_drv;
static unsigned char *mdss_dsi_base;
+static unsigned char *mmss_cc_base;
+
+static int mdss_dsi_regulator_init(struct platform_device *pdev)
+{
+ int ret;
+ dsi_drv.vdd_vreg = devm_regulator_get(&pdev->dev, "vdd");
+ if (IS_ERR(dsi_drv.vdd_vreg)) {
+ pr_err("could not get 8941_l22, rc = %ld\n",
+ PTR_ERR(dsi_drv.vdd_vreg));
+ return -ENODEV;
+ }
+
+ ret = regulator_set_voltage(dsi_drv.vdd_vreg, 3000000, 3000000);
+ if (ret) {
+ pr_err("vdd_vreg->set_voltage failed, rc=%d\n", ret);
+ return -EINVAL;
+ }
+
+ dsi_drv.vdd_io_vreg = devm_regulator_get(&pdev->dev, "vdd_io");
+ if (IS_ERR(dsi_drv.vdd_io_vreg)) {
+ pr_err("could not get 8941_l12, rc = %ld\n",
+ PTR_ERR(dsi_drv.vdd_io_vreg));
+ return -ENODEV;
+ }
+
+ ret = regulator_set_voltage(dsi_drv.vdd_io_vreg, 1800000, 1800000);
+ if (ret) {
+ pr_err("vdd_io_vreg->set_voltage failed, rc=%d\n", ret);
+ return -EINVAL;
+ }
+
+ dsi_drv.dsi_vreg = devm_regulator_get(&pdev->dev, "vreg");
+ if (IS_ERR(dsi_drv.dsi_vreg)) {
+ pr_err("could not get 8941_l2, rc = %ld\n",
+ PTR_ERR(dsi_drv.dsi_vreg));
+ return -ENODEV;
+ }
+
+ ret = regulator_set_voltage(dsi_drv.dsi_vreg, 1200000, 1200000);
+ if (ret) {
+ pr_err("dsi_vreg->set_voltage failed, rc=%d\n", ret);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mdss_dsi_panel_power_on(int enable)
+{
+ int ret;
+ pr_debug("%s: enable=%d\n", __func__, enable);
+
+ if (enable) {
+ ret = regulator_set_optimum_mode(dsi_drv.vdd_vreg, 100000);
+ if (ret < 0) {
+ pr_err("%s: vdd_vreg set regulator mode failed.\n",
+ __func__);
+ return ret;
+ }
+
+ ret = regulator_set_optimum_mode(dsi_drv.vdd_io_vreg, 100000);
+ if (ret < 0) {
+ pr_err("%s: vdd_io_vreg set regulator mode failed.\n",
+ __func__);
+ return ret;
+ }
+
+ ret = regulator_set_optimum_mode(dsi_drv.dsi_vreg, 100000);
+ if (ret < 0) {
+ pr_err("%s: dsi_vreg set regulator mode failed.\n",
+ __func__);
+ return ret;
+ }
+
+ ret = regulator_enable(dsi_drv.vdd_vreg);
+ if (ret) {
+ pr_err("%s: Failed to enable regulator.\n", __func__);
+ return ret;
+ }
+
+ ret = regulator_enable(dsi_drv.vdd_io_vreg);
+ if (ret) {
+ pr_err("%s: Failed to enable regulator.\n", __func__);
+ return ret;
+ }
+
+ ret = regulator_enable(dsi_drv.dsi_vreg);
+ if (ret) {
+ pr_err("%s: Failed to enable regulator.\n", __func__);
+ return ret;
+ }
+
+ mdss_dsi_panel_reset(1);
+
+ } else {
+
+ mdss_dsi_panel_reset(0);
+
+ ret = regulator_disable(dsi_drv.vdd_vreg);
+ if (ret) {
+ pr_err("%s: Failed to disable regulator.\n", __func__);
+ return ret;
+ }
+
+ ret = regulator_disable(dsi_drv.vdd_io_vreg);
+ if (ret) {
+ pr_err("%s: Failed to disable regulator.\n", __func__);
+ return ret;
+ }
+
+ ret = regulator_disable(dsi_drv.dsi_vreg);
+ if (ret) {
+ pr_err("%s: Failed to disable regulator.\n", __func__);
+ return ret;
+ }
+
+ ret = regulator_set_optimum_mode(dsi_drv.vdd_vreg, 100);
+ if (ret < 0) {
+ pr_err("%s: vdd_vreg set regulator mode failed.\n",
+ __func__);
+ return ret;
+ }
+
+ ret = regulator_set_optimum_mode(dsi_drv.vdd_io_vreg, 100);
+ if (ret < 0) {
+ pr_err("%s: vdd_io_vreg set regulator mode failed.\n",
+ __func__);
+ return ret;
+ }
+ ret = regulator_set_optimum_mode(dsi_drv.dsi_vreg, 100);
+ if (ret < 0) {
+ pr_err("%s: dsi_vreg set regulator mode failed.\n",
+ __func__);
+ return ret;
+ }
+ }
+ return 0;
+}
static int mdss_dsi_off(struct mdss_panel_data *pdata)
{
@@ -38,14 +178,14 @@
mdss_dsi_op_mode_config(DSI_CMD_MODE, pdata);
- ret = panel_pdata->off(pdata);
+ ret = dsi_drv.off(pdata);
if (ret) {
pr_err("%s: Panel OFF failed\n", __func__);
return ret;
}
spin_lock_bh(&dsi_clk_lock);
- mdss_dsi_clk_disable();
+ mdss_dsi_clk_disable(pdata);
/* disable dsi engine */
MIPI_OUTP(mdss_dsi_base + 0x0004, 0);
@@ -54,6 +194,12 @@
mdss_dsi_unprepare_clocks();
+ ret = mdss_dsi_panel_power_on(0);
+ if (ret) {
+ pr_err("%s: Panel power off failed\n", __func__);
+ return ret;
+ }
+
pr_debug("%s-:\n", __func__);
return ret;
@@ -71,15 +217,18 @@
pinfo = &pdata->panel_info;
- cont_splash_clk_ctrl(0);
+ MIPI_OUTP(mdss_dsi_base + 0x118, 1);
+ MIPI_OUTP(mdss_dsi_base + 0x118, 0);
+
+ mdss_dsi_phy_sw_reset(pdata);
+ mdss_dsi_phy_enable(pdata, 1);
+ mdss_dsi_phy_init(pdata);
+
mdss_dsi_prepare_clocks();
spin_lock_bh(&dsi_clk_lock);
- MIPI_OUTP(mdss_dsi_base + 0x118, 1);
- MIPI_OUTP(mdss_dsi_base + 0x118, 0);
-
- mdss_dsi_clk_enable();
+ mdss_dsi_clk_enable(pdata);
spin_unlock_bh(&dsi_clk_lock);
clk_rate = pdata->panel_info.clk_rate;
@@ -148,7 +297,13 @@
wmb();
}
- ret = panel_pdata->on(pdata);
+ ret = mdss_dsi_panel_power_on(1);
+ if (ret) {
+ pr_err("%s: Panel power on failed\n", __func__);
+ return ret;
+ }
+
+ ret = dsi_drv.on(pdata);
if (ret) {
pr_err("%s: unable to initialize the panel\n", __func__);
return ret;
@@ -167,7 +322,7 @@
unsigned char *mdss_dsi_get_clk_base(void)
{
- return mdss_dsi_base;
+ return mmss_cc_base;
}
static int mdss_dsi_resource_initialized;
@@ -196,8 +351,35 @@
}
}
+ mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!mdss_dsi_mres) {
+ pr_err("%s:%d unable to get the MDSS resources",
+ __func__, __LINE__);
+ return -ENOMEM;
+ }
+ if (mdss_dsi_mres) {
+ mmss_cc_base = ioremap(mdss_dsi_mres->start,
+ resource_size(mdss_dsi_mres));
+ if (!mmss_cc_base) {
+ pr_err("%s:%d unable to remap dsi resources",
+ __func__, __LINE__);
+ return -ENOMEM;
+ }
+ }
+
+ rc = mdss_dsi_regulator_init(pdev);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "%s: failed to init regulator, rc=%d\n",
+ __func__, rc);
+ iounmap(mdss_dsi_base);
+ iounmap(mmss_cc_base);
+ return rc;
+ }
+
if (mdss_dsi_clk_init(pdev)) {
iounmap(mdss_dsi_base);
+ iounmap(mmss_cc_base);
return -EPERM;
}
@@ -208,6 +390,7 @@
"%s: failed to add child nodes, rc=%d\n",
__func__, rc);
iounmap(mdss_dsi_base);
+ iounmap(mmss_cc_base);
return rc;
}
@@ -240,21 +423,19 @@
u32 h_period, v_period, dsi_pclk_rate;
struct mdss_panel_data *pdata = NULL;
- panel_pdata = panel_data;
+ h_period = ((panel_data->panel_info.lcdc.h_pulse_width)
+ + (panel_data->panel_info.lcdc.h_back_porch)
+ + (panel_data->panel_info.xres)
+ + (panel_data->panel_info.lcdc.h_front_porch));
- h_period = ((panel_pdata->panel_info.lcdc.h_pulse_width)
- + (panel_pdata->panel_info.lcdc.h_back_porch)
- + (panel_pdata->panel_info.xres)
- + (panel_pdata->panel_info.lcdc.h_front_porch));
+ v_period = ((panel_data->panel_info.lcdc.v_pulse_width)
+ + (panel_data->panel_info.lcdc.v_back_porch)
+ + (panel_data->panel_info.yres)
+ + (panel_data->panel_info.lcdc.v_front_porch));
- v_period = ((panel_pdata->panel_info.lcdc.v_pulse_width)
- + (panel_pdata->panel_info.lcdc.v_back_porch)
- + (panel_pdata->panel_info.yres)
- + (panel_pdata->panel_info.lcdc.v_front_porch));
+ mipi = &panel_data->panel_info.mipi;
- mipi = &panel_pdata->panel_info.mipi;
-
- panel_pdata->panel_info.type =
+ panel_data->panel_info.type =
((mipi->mode == DSI_VIDEO_MODE)
? MIPI_VIDEO_PANEL : MIPI_CMD_PANEL);
@@ -278,23 +459,23 @@
else
bpp = 3; /* Default format set to RGB888 */
- if (panel_pdata->panel_info.type == MIPI_VIDEO_PANEL &&
- !panel_pdata->panel_info.clk_rate) {
- h_period += panel_pdata->panel_info.lcdc.xres_pad;
- v_period += panel_pdata->panel_info.lcdc.yres_pad;
+ if (panel_data->panel_info.type == MIPI_VIDEO_PANEL &&
+ !panel_data->panel_info.clk_rate) {
+ h_period += panel_data->panel_info.lcdc.xres_pad;
+ v_period += panel_data->panel_info.lcdc.yres_pad;
if (lanes > 0) {
- panel_pdata->panel_info.clk_rate =
+ panel_data->panel_info.clk_rate =
((h_period * v_period * (mipi->frame_rate) * bpp * 8)
/ lanes);
} else {
pr_err("%s: forcing mdss_dsi lanes to 1\n", __func__);
- panel_pdata->panel_info.clk_rate =
+ panel_data->panel_info.clk_rate =
(h_period * v_period
* (mipi->frame_rate) * bpp * 8);
}
}
- pll_divider_config.clk_rate = panel_pdata->panel_info.clk_rate;
+ pll_divider_config.clk_rate = panel_data->panel_info.clk_rate;
rc = mdss_dsi_clk_div_config(bpp, lanes, &dsi_pclk_rate);
if (rc) {
@@ -306,6 +487,9 @@
dsi_pclk_rate = 35000000;
mipi->dsi_pclk_rate = dsi_pclk_rate;
+ dsi_drv.on = panel_data->on;
+ dsi_drv.off = panel_data->off;
+
/*
* data chain
*/
@@ -315,10 +499,12 @@
pdata->on = mdss_dsi_on;
pdata->off = mdss_dsi_off;
- memcpy(&(pdata->panel_info), &(panel_pdata->panel_info),
+ memcpy(&(pdata->panel_info), &(panel_data->panel_info),
sizeof(struct mdss_panel_info));
pdata->dsi_base = mdss_dsi_base;
+ pdata->mmss_cc_base = mmss_cc_base;
+ pdata->set_backlight = panel_data->bl_ctrl;
/*
* register in mdp driver
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 57fce1a..6acb8d5 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -19,7 +19,6 @@
#include "mdss_panel.h"
-#define MMSS_MDSS_CC_BASE_PHY 0xFD8C2300 /* mmss clcok control */
#define MMSS_SERDES_BASE_PHY 0x04f01000 /* mmss (De)Serializer CFG */
#define MIPI_OUTP(addr, data) writel_relaxed((data), (addr))
@@ -77,6 +76,12 @@
DSI_CMD_MODE_MDP,
};
+enum dsi_panel_bl_ctrl {
+ BL_PWM,
+ BL_WLED,
+ BL_DCS_CMD,
+};
+
#define DSI_NON_BURST_SYNCH_PULSE 0
#define DSI_NON_BURST_SYNCH_EVENT 1
#define DSI_BURST_MODE 2
@@ -242,8 +247,16 @@
struct mdss_panel_info panel_info;
int (*on) (struct mdss_panel_data *pdata);
int (*off) (struct mdss_panel_data *pdata);
+ void (*bl_ctrl) (u32 bl_level);
};
+struct mdss_dsi_drv_pdata {
+ struct regulator *vdd_vreg;
+ struct regulator *vdd_io_vreg;
+ struct regulator *dsi_vreg;
+ int (*on) (struct mdss_panel_data *pdata);
+ int (*off) (struct mdss_panel_data *pdata);
+};
int dsi_panel_device_register(struct platform_device *pdev,
struct mdss_panel_common_pdata *panel_data);
@@ -273,8 +286,8 @@
void mdss_dsi_cmd_mdp_start(void);
void mdss_dsi_cmd_bta_sw_trigger(struct mdss_panel_data *pdata);
void mdss_dsi_ack_err_status(unsigned char *dsi_base);
-void mdss_dsi_clk_enable(void);
-void mdss_dsi_clk_disable(void);
+void mdss_dsi_clk_enable(struct mdss_panel_data *pdata);
+void mdss_dsi_clk_disable(struct mdss_panel_data *pdata);
void mdss_dsi_controller_cfg(int enable,
struct mdss_panel_data *pdata);
void mdss_dsi_sw_reset(struct mdss_panel_data *pdata);
@@ -288,7 +301,10 @@
void mdss_dsi_clk_deinit(struct device *dev);
void mdss_dsi_prepare_clocks(void);
void mdss_dsi_unprepare_clocks(void);
-void cont_splash_clk_ctrl(int enable);
unsigned char *mdss_dsi_get_base_adr(void);
+void mdss_dsi_panel_reset(int enable);
+void mdss_dsi_phy_enable(struct mdss_panel_data *pdata, int on);
+void mdss_dsi_phy_init(struct mdss_panel_data *pdata);
+void mdss_dsi_phy_sw_reset(struct mdss_panel_data *pdata);
#endif /* MDSS_DSI_H */
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index bfb7fae..e4b1867 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -13,7 +13,12 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/of.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 "mdss_dsi.h"
@@ -28,6 +33,68 @@
static int num_of_off_cmds;
static char *on_cmds, *off_cmds;
+static char bl_ctrl;
+DEFINE_LED_TRIGGER(bl_led_trigger);
+
+static struct mdss_dsi_phy_ctrl phy_params;
+
+static int rst_gpio;
+static int disp_en;
+
+struct qpnp_pin_cfg param = {
+ .mode = QPNP_PIN_MODE_DIG_OUT,
+ .output_type = QPNP_PIN_OUT_BUF_OPEN_DRAIN_NMOS,
+ .invert = QPNP_PIN_INVERT_ENABLE,
+ .pull = QPNP_PIN_MPP_PULL_UP_30KOHM,
+ .vin_sel = QPNP_PIN_VIN3,
+ .out_strength = QPNP_PIN_OUT_STRENGTH_HIGH,
+ .select = QPNP_PIN_SEL_DTEST3,
+ .master_en = QPNP_PIN_MASTER_ENABLE,
+ .aout_ref = QPNP_PIN_AOUT_0V625,
+ .ain_route = QPNP_PIN_AIN_AMUX_CH7,
+ .cs_out = QPNP_PIN_CS_OUT_20MA,
+};
+
+void mdss_dsi_panel_reset(int enable)
+{
+ if (!disp_en)
+ pr_debug("%s:%d, reset line not configured\n",
+ __func__, __LINE__);
+
+ if (!rst_gpio)
+ pr_debug("%s:%d, reset line not configured\n",
+ __func__, __LINE__);
+
+ if (enable) {
+ gpio_set_value(disp_en, 1);
+ gpio_set_value(rst_gpio, 1);
+ usleep(10);
+ gpio_set_value(rst_gpio, 0);
+ usleep(200);
+ gpio_set_value(rst_gpio, 1);
+ } else {
+ gpio_set_value(rst_gpio, 0);
+ gpio_set_value(disp_en, 0);
+ }
+}
+
+static void mdss_dsi_panel_bl_ctrl(u32 bl_level)
+{
+ if (bl_ctrl) {
+ switch (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__);
+}
+
static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
{
struct mipi_panel_info *mipi;
@@ -37,6 +104,8 @@
pr_debug("%s:%d, debug info (mode) : %d\n", __func__, __LINE__,
mipi->mode);
+ mdss_dsi_panel_reset(1);
+
if (mipi->mode == DSI_VIDEO_MODE) {
mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf, dsi_panel_on_cmds,
num_of_on_cmds);
@@ -64,6 +133,8 @@
return -EINVAL;
}
+ mdss_dsi_panel_reset(0);
+
return 0;
}
@@ -75,6 +146,7 @@
int rc, i, len;
int cmd_plen, data_offset;
const char *data;
+ static const char *bl_ctrl_type;
rc = of_property_read_u32_array(np, "qcom,mdss-pan-res", res, 2);
if (rc) {
@@ -85,6 +157,59 @@
panel_data->panel_info.xres = (!rc ? res[0] : 640);
panel_data->panel_info.yres = (!rc ? res[1] : 480);
+ rc = of_property_read_u32_array(np, "qcom,mdss-pan-active-res", res, 2);
+ if (rc == 0) {
+ panel_data->panel_info.lcdc.xres_pad =
+ panel_data->panel_info.xres - res[0];
+ panel_data->panel_info.lcdc.yres_pad =
+ panel_data->panel_info.yres - res[1];
+ }
+
+ disp_en = of_get_named_gpio(np, "qcom,enable-gpio", 0);
+ if (!gpio_is_valid(disp_en)) {
+ pr_err("%s:%d, Disp_en gpio not specified\n",
+ __func__, __LINE__);
+ return -ENODEV;
+ }
+
+ rc = gpio_request(disp_en, "disp_enable");
+ if (rc) {
+ pr_err("request reset gpio failed, rc=%d\n",
+ rc);
+ gpio_free(disp_en);
+ return -ENODEV;
+ }
+ rc = gpio_direction_output(disp_en, 1);
+ if (rc) {
+ pr_err("set_direction for disp_en gpio failed, rc=%d\n",
+ rc);
+ gpio_free(disp_en);
+ return -ENODEV;
+ }
+
+ rst_gpio = of_get_named_gpio(np, "qcom,rst-gpio", 0);
+ if (!gpio_is_valid(rst_gpio)) {
+ pr_err("%s:%d, reset gpio not specified\n",
+ __func__, __LINE__);
+ } else {
+ rc = qpnp_pin_config(rst_gpio, ¶m);
+ if (rc) {
+ pr_err("request reset gpio failed, rc=%d\n",
+ rc);
+ gpio_free(disp_en);
+ return rc;
+ }
+
+ rc = gpio_request(rst_gpio, "disp_rst_n");
+ if (rc) {
+ pr_err("request reset gpio failed, rc=%d\n",
+ rc);
+ gpio_free(rst_gpio);
+ gpio_free(disp_en);
+ return -ENODEV;
+ }
+ }
+
rc = of_property_read_u32(np, "qcom,mdss-pan-bpp", &tmp);
if (rc) {
pr_err("%s:%d, panel bpp not specified\n",
@@ -106,6 +231,14 @@
"qcom,mdss-pan-underflow-clr", &tmp);
panel_data->panel_info.lcdc.underflow_clr = (!rc ? tmp : 0xff);
+ bl_ctrl_type = of_get_property(pdev->dev.of_node,
+ "qcom,mdss-pan-bl-ctrl", NULL);
+ if (!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;
+ }
+
rc = of_property_read_u32_array(np,
"qcom,mdss-pan-bl-levels", res, 2);
panel_data->panel_info.bl_min = (!rc ? res[0] : 0);
@@ -184,6 +317,53 @@
rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-frame-rate", &tmp);
panel_data->panel_info.mipi.frame_rate = (!rc ? tmp : 60);
+ data = of_get_property(np, "qcom,panel-phy-regulatorSettings", &len);
+ if ((!data) || (len != 8)) {
+ pr_err("%s:%d, Unable to read Phy regulator settings",
+ __func__, __LINE__);
+ goto error;
+ }
+ for (i = 0; i < len; i++)
+ phy_params.regulator[i] = data[i];
+
+ data = of_get_property(np, "qcom,panel-phy-timingSettings", &len);
+ if ((!data) || (len != 12)) {
+ pr_err("%s:%d, Unable to read Phy timing settings",
+ __func__, __LINE__);
+ goto error;
+ }
+ for (i = 0; i < len; i++)
+ phy_params.timing[i] = data[i];
+
+ data = of_get_property(np, "qcom,panel-phy-strengthCtrl", &len);
+ if ((!data) || (len != 2)) {
+ pr_err("%s:%d, Unable to read Phy Strength ctrl settings",
+ __func__, __LINE__);
+ goto error;
+ }
+ phy_params.strength[0] = data[0];
+ phy_params.strength[1] = data[1];
+
+ data = of_get_property(np, "qcom,panel-phy-bistCtrl", &len);
+ if ((!data) || (len != 6)) {
+ pr_err("%s:%d, Unable to read Phy Bist Ctrl settings",
+ __func__, __LINE__);
+ goto error;
+ }
+ for (i = 0; i < len; i++)
+ phy_params.bistCtrl[i] = data[i];
+
+ data = of_get_property(np, "qcom,panel-phy-laneConfig", &len);
+ if ((!data) || (len != 45)) {
+ pr_err("%s:%d, Unable to read Phy lane configure settings",
+ __func__, __LINE__);
+ goto error;
+ }
+ for (i = 0; i < len; i++)
+ phy_params.laneCfg[i] = data[i];
+
+ panel_data->panel_info.mipi.dsi_phy_db = &phy_params;
+
data = of_get_property(np, "qcom,panel-on-cmds", &len);
if (!data) {
pr_err("%s:%d, Unable to read ON cmds", __func__, __LINE__);
@@ -288,6 +468,10 @@
kfree(dsi_panel_off_cmds);
kfree(on_cmds);
kfree(off_cmds);
+ if (rst_gpio)
+ gpio_free(rst_gpio);
+ if (disp_en)
+ gpio_free(disp_en);
return -EINVAL;
}
@@ -295,7 +479,7 @@
static int __devinit mdss_dsi_panel_probe(struct platform_device *pdev)
{
int rc = 0;
- struct mdss_panel_common_pdata *vendor_pdata = NULL;
+ static struct mdss_panel_common_pdata vendor_pdata;
static const char *panel_name;
if (pdev->dev.parent == NULL) {
@@ -314,21 +498,15 @@
else
pr_info("%s: Panel Name = %s\n", __func__, panel_name);
- vendor_pdata = devm_kzalloc(&pdev->dev,
- sizeof(*vendor_pdata), GFP_KERNEL);
- if (!vendor_pdata)
- return -ENOMEM;
-
- rc = mdss_panel_parse_dt(pdev, vendor_pdata);
- if (rc) {
- devm_kfree(&pdev->dev, vendor_pdata);
- vendor_pdata = NULL;
+ rc = mdss_panel_parse_dt(pdev, &vendor_pdata);
+ if (rc)
return rc;
- }
- vendor_pdata->on = mdss_dsi_panel_on;
- vendor_pdata->off = mdss_dsi_panel_off;
- rc = dsi_panel_device_register(pdev, vendor_pdata);
+ vendor_pdata.on = mdss_dsi_panel_on;
+ vendor_pdata.off = mdss_dsi_panel_off;
+ vendor_pdata.bl_ctrl = mdss_dsi_panel_bl_ctrl;
+
+ rc = dsi_panel_device_register(pdev, &vendor_pdata);
if (rc)
return rc;
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 7efca07..1f83b2b 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -186,7 +186,7 @@
/*
* alloc framebuffer info + par data
*/
- fbi = framebuffer_alloc(sizeof(struct msm_fb_data_type), &pdev->dev);
+ fbi = framebuffer_alloc(sizeof(struct msm_fb_data_type), NULL);
if (fbi == NULL) {
pr_err("can't allocate framebuffer info data!\n");
return -ENOMEM;
@@ -810,15 +810,6 @@
mfd->op_enable = true;
- /* cursor memory allocation */
- if (mfd->cursor_update) {
- mfd->cursor_buf = dma_alloc_coherent(NULL, MDSS_MDP_CURSOR_SIZE,
- (dma_addr_t *) &mfd->cursor_buf_phys,
- GFP_KERNEL);
- if (!mfd->cursor_buf)
- mfd->cursor_update = 0;
- }
-
if (mfd->lut_update) {
ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
if (ret)
@@ -829,11 +820,6 @@
if (mfd->lut_update)
fb_dealloc_cmap(&fbi->cmap);
- if (mfd->cursor_buf)
- dma_free_coherent(NULL, MDSS_MDP_CURSOR_SIZE,
- mfd->cursor_buf,
- (dma_addr_t) mfd->cursor_buf_phys);
-
mfd->op_enable = false;
return -EPERM;
}
@@ -1104,7 +1090,7 @@
if (ret)
return ret;
- return mfd->cursor_update(info, &cursor);
+ return mfd->cursor_update(mfd, &cursor);
}
static int mdss_fb_set_lut(struct fb_info *info, void __user *p)
@@ -1120,7 +1106,7 @@
if (ret)
return ret;
- mfd->lut_update(info, &cmap);
+ mfd->lut_update(mfd, &cmap);
return 0;
}
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index 3ea0ab3..ab140fe 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -69,11 +69,10 @@
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 fb_info *info,
+ int (*cursor_update) (struct msm_fb_data_type *mfd,
struct fb_cursor *cursor);
- int (*lut_update) (struct fb_info *info,
- struct fb_cmap *cmap);
- int (*do_histogram) (struct fb_info *info,
+ 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;
diff --git a/drivers/video/msm/mdss/mdss_mdp.c b/drivers/video/msm/mdss/mdss_mdp.c
index a10bac3..695ca1c 100644
--- a/drivers/video/msm/mdss/mdss_mdp.c
+++ b/drivers/video/msm/mdss/mdss_mdp.c
@@ -25,6 +25,7 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/of.h>
+#include <linux/of_address.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/memory_alloc.h>
@@ -46,10 +47,7 @@
#include "mdss_fb.h"
#include "mdss_mdp.h"
-unsigned char *mdss_reg_base;
-
-struct mdss_res_type *mdss_res;
-static struct msm_panel_common_pdata *mdp_pdata;
+struct mdss_data_type *mdss_res;
static DEFINE_SPINLOCK(mdp_lock);
static DEFINE_MUTEX(mdp_clk_lock);
@@ -117,9 +115,13 @@
static irqreturn_t mdss_irq_handler(int irq, void *ptr)
{
+ struct mdss_data_type *mdata = ptr;
u32 intr = MDSS_MDP_REG_READ(MDSS_REG_HW_INTR_STATUS);
- mdss_res->irq_buzy = true;
+ if (!mdata)
+ return IRQ_NONE;
+
+ mdata->irq_buzy = true;
if (intr & MDSS_INTR_MDP)
mdss_irq_dispatch(MDSS_HW_MDP, irq, ptr);
@@ -136,7 +138,7 @@
if (intr & MDSS_INTR_HDMI)
mdss_irq_dispatch(MDSS_HW_HDMI, irq, ptr);
- mdss_res->irq_buzy = false;
+ mdata->irq_buzy = false;
return IRQ_HANDLED;
}
@@ -228,9 +230,9 @@
}
EXPORT_SYMBOL(mdss_disable_irq_nosync);
-static int mdss_mdp_bus_scale_register(void)
+static int mdss_mdp_bus_scale_register(struct mdss_data_type *mdata)
{
- if (!mdss_res->bus_hdl) {
+ if (!mdata->bus_hdl) {
struct msm_bus_scale_pdata *bus_pdata = &mdp_bus_scale_table;
int i;
@@ -239,23 +241,23 @@
mdp_bus_usecases[i].vectors = &mdp_bus_vectors[i];
}
- mdss_res->bus_hdl = msm_bus_scale_register_client(bus_pdata);
- if (!mdss_res->bus_hdl) {
+ mdata->bus_hdl = msm_bus_scale_register_client(bus_pdata);
+ if (!mdata->bus_hdl) {
pr_err("not able to get bus scale\n");
return -ENOMEM;
}
- pr_debug("register bus_hdl=%x\n", mdss_res->bus_hdl);
+ pr_debug("register bus_hdl=%x\n", mdata->bus_hdl);
}
return 0;
}
-static void mdss_mdp_bus_scale_unregister(void)
+static void mdss_mdp_bus_scale_unregister(struct mdss_data_type *mdata)
{
- pr_debug("unregister bus_hdl=%x\n", mdss_res->bus_hdl);
+ pr_debug("unregister bus_hdl=%x\n", mdata->bus_hdl);
- if (mdss_res->bus_hdl)
- msm_bus_scale_unregister_client(mdss_res->bus_hdl);
+ if (mdata->bus_hdl)
+ msm_bus_scale_unregister_client(mdata->bus_hdl);
}
int mdss_mdp_bus_scale_set_quota(u32 ab_quota, u32 ib_quota)
@@ -525,7 +527,7 @@
}
}
-static inline int mdss_mdp_irq_clk_register(struct platform_device *pdev,
+static inline int mdss_mdp_irq_clk_register(struct mdss_data_type *mdata,
char *clk_name, int clk_idx)
{
struct clk *tmp;
@@ -534,182 +536,191 @@
return -EINVAL;
}
-
- tmp = clk_get(&pdev->dev, clk_name);
+ tmp = devm_clk_get(&mdata->pdev->dev, clk_name);
if (IS_ERR(tmp)) {
pr_err("unable to get clk: %s\n", clk_name);
return PTR_ERR(tmp);
}
- mdss_res->mdp_clk[clk_idx] = tmp;
+ mdata->mdp_clk[clk_idx] = tmp;
return 0;
}
-static int mdss_mdp_irq_clk_setup(struct platform_device *pdev)
+static int mdss_mdp_irq_clk_setup(struct mdss_data_type *mdata)
{
int ret;
- int i;
- ret = request_irq(mdss_res->irq, mdss_irq_handler, IRQF_DISABLED,
- "MDSS", 0);
+ ret = devm_request_irq(&mdata->pdev->dev, mdata->irq, mdss_irq_handler,
+ IRQF_DISABLED, "MDSS", mdata);
if (ret) {
pr_err("mdp request_irq() failed!\n");
return ret;
}
- disable_irq(mdss_res->irq);
+ disable_irq(mdata->irq);
- mdss_res->fs = regulator_get(&pdev->dev, "vdd");
- if (IS_ERR_OR_NULL(mdss_res->fs)) {
- mdss_res->fs = NULL;
+ mdata->fs = devm_regulator_get(&mdata->pdev->dev, "vdd");
+ if (IS_ERR_OR_NULL(mdata->fs)) {
+ mdata->fs = NULL;
pr_err("unable to get gdsc regulator\n");
- goto error;
+ return -EINVAL;
}
- regulator_enable(mdss_res->fs);
- mdss_res->fs_ena = true;
+ regulator_enable(mdata->fs);
+ mdata->fs_ena = true;
- if (mdss_mdp_irq_clk_register(pdev, "bus_clk", MDSS_CLK_AXI) ||
- mdss_mdp_irq_clk_register(pdev, "iface_clk", MDSS_CLK_AHB) ||
- mdss_mdp_irq_clk_register(pdev, "core_clk_src", MDSS_CLK_MDP_SRC) ||
- mdss_mdp_irq_clk_register(pdev, "core_clk", MDSS_CLK_MDP_CORE) ||
- mdss_mdp_irq_clk_register(pdev, "lut_clk", MDSS_CLK_MDP_LUT) ||
- mdss_mdp_irq_clk_register(pdev, "vsync_clk", MDSS_CLK_MDP_VSYNC))
- goto error;
+ if (mdss_mdp_irq_clk_register(mdata, "bus_clk", MDSS_CLK_AXI) ||
+ mdss_mdp_irq_clk_register(mdata, "iface_clk", MDSS_CLK_AHB) ||
+ mdss_mdp_irq_clk_register(mdata, "core_clk_src",
+ MDSS_CLK_MDP_SRC) ||
+ mdss_mdp_irq_clk_register(mdata, "core_clk",
+ MDSS_CLK_MDP_CORE) ||
+ mdss_mdp_irq_clk_register(mdata, "lut_clk", MDSS_CLK_MDP_LUT) ||
+ mdss_mdp_irq_clk_register(mdata, "vsync_clk", MDSS_CLK_MDP_VSYNC))
+ return -EINVAL;
mdss_mdp_set_clk_rate(MDP_CLK_DEFAULT_RATE);
pr_debug("mdp clk rate=%ld\n", mdss_mdp_get_clk_rate(MDSS_CLK_MDP_SRC));
return 0;
-error:
- for (i = 0; i < MDSS_MAX_CLK; i++) {
- if (mdss_res->mdp_clk[i])
- clk_put(mdss_res->mdp_clk[i]);
- }
- if (mdss_res->fs)
- regulator_put(mdss_res->fs);
- if (mdss_res->irq)
- free_irq(mdss_res->irq, 0);
-
- return -EINVAL;
-
}
-static struct msm_panel_common_pdata *mdss_mdp_populate_pdata(
- struct device *dev)
+static int mdss_hw_init(struct mdss_data_type *mdata)
{
- struct msm_panel_common_pdata *pdata;
-
- pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- dev_err(dev, "could not allocate memory for pdata\n");
- return pdata;
-}
-
-static u32 mdss_mdp_res_init(struct platform_device *pdev)
-{
- u32 rc;
-
- rc = mdss_mdp_irq_clk_setup(pdev);
- if (rc)
- return rc;
-
- mdss_res->clk_ctrl_wq = create_singlethread_workqueue("mdp_clk_wq");
- INIT_DELAYED_WORK(&mdss_res->clk_ctrl_worker,
- mdss_mdp_clk_ctrl_workqueue_handler);
+ char *base = mdata->vbif_base;
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
- mdss_res->rev = MDSS_MDP_REG_READ(MDSS_REG_HW_VERSION);
- mdss_res->mdp_rev = MDSS_MDP_REG_READ(MDSS_MDP_REG_HW_VERSION);
+ /* Setup VBIF QoS settings*/
+ MDSS_MDP_REG_WRITE(0x2E0, 0x000000AA);
+ MDSS_MDP_REG_WRITE(0x2E4, 0x00000055);
+ writel_relaxed(0x00000001, base + 0x004);
+ writel_relaxed(0x00000707, base + 0x0D8);
+ writel_relaxed(0x00000030, base + 0x0F0);
+ writel_relaxed(0x00000001, base + 0x124);
+ writel_relaxed(0x00000FFF, base + 0x178);
+ writel_relaxed(0x0FFF0FFF, base + 0x17C);
+ writel_relaxed(0x22222222, base + 0x160);
+ writel_relaxed(0x00002222, base + 0x164);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
-
- mdss_res->smp_mb_cnt = MDSS_MDP_SMP_MMB_BLOCKS;
- mdss_res->smp_mb_size = MDSS_MDP_SMP_MMB_SIZE;
- mdss_res->pipe_type_map = mdss_mdp_pipe_type_map;
- mdss_res->mixer_type_map = mdss_mdp_mixer_type_map;
-
- pr_info("mdss_revision=%x\n", mdss_res->rev);
- pr_info("mdp_hw_revision=%x\n", mdss_res->mdp_rev);
-
- mdss_res->res_init = true;
- mdss_res->timeout = HZ/20;
- mdss_res->clk_ena = false;
- mdss_res->irq_mask = MDSS_MDP_DEFAULT_INTR_MASK;
- mdss_res->suspend = false;
- mdss_res->prim_ptype = NO_PANEL;
- mdss_res->irq_ena = false;
+ pr_debug("MDP hw init done\n");
return 0;
}
+static u32 mdss_mdp_res_init(struct mdss_data_type *mdata)
+{
+ u32 rc;
+
+ rc = mdss_mdp_irq_clk_setup(mdata);
+ if (rc)
+ return rc;
+
+ mdata->clk_ctrl_wq = create_singlethread_workqueue("mdp_clk_wq");
+ INIT_DELAYED_WORK(&mdata->clk_ctrl_worker,
+ mdss_mdp_clk_ctrl_workqueue_handler);
+
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+ mdata->rev = MDSS_MDP_REG_READ(MDSS_REG_HW_VERSION);
+ mdata->mdp_rev = MDSS_MDP_REG_READ(MDSS_MDP_REG_HW_VERSION);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+ mdata->smp_mb_cnt = MDSS_MDP_SMP_MMB_BLOCKS;
+ mdata->smp_mb_size = MDSS_MDP_SMP_MMB_SIZE;
+ mdata->pipe_type_map = mdss_mdp_pipe_type_map;
+ mdata->mixer_type_map = mdss_mdp_mixer_type_map;
+
+ pr_info("mdss_revision=%x\n", mdata->rev);
+ pr_info("mdp_hw_revision=%x\n", mdata->mdp_rev);
+
+ mdata->res_init = true;
+ mdata->timeout = HZ/20;
+ mdata->clk_ena = false;
+ mdata->irq_mask = MDSS_MDP_DEFAULT_INTR_MASK;
+ mdata->suspend = false;
+ mdata->prim_ptype = NO_PANEL;
+ mdata->irq_ena = false;
+
+ rc = mdss_hw_init(mdata);
+
+ return rc;
+}
+
static int mdss_mdp_probe(struct platform_device *pdev)
{
- struct resource *mdss_mdp_mres;
- struct resource *mdss_mdp_ires;
- resource_size_t size;
+ struct resource *res;
int rc;
+ struct mdss_data_type *mdata;
- if (!mdss_res) {
- mdss_res = devm_kzalloc(&pdev->dev, sizeof(*mdss_res),
- GFP_KERNEL);
- if (mdss_res == NULL)
- return -ENOMEM;
+ if (!pdev->dev.of_node) {
+ pr_err("MDP driver only supports device tree probe\n");
+ return -ENOTSUPP;
}
- if (pdev->dev.of_node) {
- pdev->id = 0;
- mdp_pdata = mdss_mdp_populate_pdata(&pdev->dev);
- mdss_mdp_mres = platform_get_resource(pdev,
- IORESOURCE_MEM, 0);
- mdss_mdp_ires = platform_get_resource(pdev,
- IORESOURCE_IRQ, 0);
- if (!mdss_mdp_mres || !mdss_mdp_ires) {
- pr_err("unable to get the MDSS resources");
- rc = -ENOMEM;
- goto probe_done;
- }
- mdss_reg_base = ioremap(mdss_mdp_mres->start,
- resource_size(mdss_mdp_mres));
-
- pr_info("MDP HW Base phy_Address=0x%x virt=0x%x\n",
- (int) mdss_mdp_mres->start,
- (int) mdss_reg_base);
-
- mdss_res->irq = mdss_mdp_ires->start;
- } else if ((pdev->id == 0) && (pdev->num_resources > 0)) {
- mdp_pdata = pdev->dev.platform_data;
-
- size = resource_size(&pdev->resource[0]);
- mdss_reg_base = ioremap(pdev->resource[0].start, size);
-
- pr_info("MDP HW Base phy_Address=0x%x virt=0x%x\n",
- (int) pdev->resource[0].start,
- (int) mdss_reg_base);
-
- mdss_res->irq = platform_get_irq(pdev, 0);
- if (mdss_res->irq < 0) {
- pr_err("can not get mdp irq\n");
- rc = -ENOMEM;
- goto probe_done;
- }
+ if (mdss_res) {
+ pr_err("MDP already initialized\n");
+ return -EINVAL;
}
- if (unlikely(!mdss_reg_base)) {
+ mdata = devm_kzalloc(&pdev->dev, sizeof(*mdata), GFP_KERNEL);
+ if (mdata == NULL)
+ return -ENOMEM;
+
+ pdev->id = 0;
+ mdata->pdev = pdev;
+ platform_set_drvdata(pdev, mdata);
+ mdss_res = mdata;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mdp_phys");
+ if (!res) {
+ pr_err("unable to get MDP base address\n");
rc = -ENOMEM;
goto probe_done;
}
- rc = mdss_mdp_res_init(pdev);
+ mdata->mdp_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (unlikely(!mdata->mdp_base)) {
+ pr_err("unable to map MDP base\n");
+ rc = -ENOMEM;
+ goto probe_done;
+ }
+ pr_info("MDP HW Base phy_Address=0x%x virt=0x%x\n",
+ (int) res->start,
+ (int) mdata->mdp_base);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vbif_phys");
+ if (!res) {
+ pr_err("unable to get MDSS VBIF base address\n");
+ rc = -ENOMEM;
+ goto probe_done;
+ }
+
+ mdata->vbif_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (unlikely(!mdata->vbif_base)) {
+ pr_err("unable to map MDSS VBIF base\n");
+ rc = -ENOMEM;
+ goto probe_done;
+ }
+ pr_info("MDSS VBIF HW Base phy_Address=0x%x virt=0x%x\n",
+ (int) res->start,
+ (int) mdata->vbif_base);
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ pr_err("unable to get MDSS irq\n");
+ rc = -ENOMEM;
+ goto probe_done;
+ }
+ mdata->irq = res->start;
+
+ rc = mdss_mdp_res_init(mdata);
if (rc) {
pr_err("unable to initialize mdss mdp resources\n");
goto probe_done;
}
- rc = mdss_mdp_bus_scale_register();
+ rc = mdss_mdp_bus_scale_register(mdata);
probe_done:
- if (IS_ERR_VALUE(rc)) {
- if (mdss_res) {
- devm_kfree(&pdev->dev, mdss_res);
- mdss_res = NULL;
- }
- }
+ if (IS_ERR_VALUE(rc))
+ mdss_res = NULL;
return rc;
}
@@ -770,8 +781,12 @@
static int mdss_mdp_resume(struct platform_device *pdev)
{
+ struct mdss_data_type *mdata = platform_get_drvdata(pdev);
int ret = 0;
+ if (!mdata)
+ return -ENODEV;
+
pr_debug("resume display");
mdss_mdp_footswitch_ctrl(true);
@@ -781,6 +796,8 @@
ret = mdss_fb_resume_all();
if (IS_ERR_VALUE(ret))
pr_err("Unable to resume all fb panels (%d)\n", ret);
+
+ mdss_hw_init(mdata);
return ret;
}
#else
@@ -790,11 +807,11 @@
static int mdss_mdp_remove(struct platform_device *pdev)
{
- if (mdss_res->fs != NULL)
- regulator_put(mdss_res->fs);
- iounmap(mdss_reg_base);
+ struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+ if (!mdata)
+ return -ENODEV;
pm_runtime_disable(&pdev->dev);
- mdss_mdp_bus_scale_unregister();
+ mdss_mdp_bus_scale_unregister(mdata);
return 0;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index 776bf8b..a282c3a 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -40,6 +40,11 @@
#define MAX_DOWNSCALE_RATIO 4
#define MAX_UPSCALE_RATIO 20
+#define C3_ALPHA 3 /* alpha */
+#define C2_R_Cr 2 /* R/Cr */
+#define C1_B_Cb 1 /* B/Cb */
+#define C0_G_Y 0 /* G/luma */
+
#ifdef MDSS_MDP_DEBUG_REG
static inline void mdss_mdp_reg_write(u32 addr, u32 val)
{
@@ -102,6 +107,9 @@
MDSS_MDP_MAX_CSC
};
+struct mdss_mdp_ctl;
+typedef void (*mdp_vsync_handler_t)(struct mdss_mdp_ctl *, ktime_t);
+
struct mdss_mdp_ctl {
u32 num;
u32 ref_cnt;
@@ -133,6 +141,7 @@
int (*stop_fnc) (struct mdss_mdp_ctl *ctl);
int (*prepare_fnc) (struct mdss_mdp_ctl *ctl, void *arg);
int (*display_fnc) (struct mdss_mdp_ctl *ctl, void *arg);
+ int (*set_vsync_handler) (struct mdss_mdp_ctl *, mdp_vsync_handler_t);
void *priv_data;
};
@@ -173,23 +182,8 @@
u8 bpp;
u8 alpha_enable; /* source has alpha */
- /*
- * number of bits for source component,
- * 0 = 1 bit, 1 = 2 bits, 2 = 6 bits, 3 = 8 bits
- */
- u8 a_bit; /* component 3, alpha */
- u8 r_bit; /* component 2, R_Cr */
- u8 b_bit; /* component 1, B_Cb */
- u8 g_bit; /* component 0, G_lumz */
-
- /*
- * unpack pattern
- * A = C3, R = C2, B = C1, G = C0
- */
- u8 element3;
- u8 element2;
- u8 element1;
- u8 element0;
+ u8 bits[MAX_PLANES];
+ u8 element[MAX_PLANES];
};
struct mdss_mdp_plane_sizes {
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index d29ecd6..21f4071 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -533,6 +533,11 @@
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_PACK_3D, 0);
}
+ /* request bus bandwidth for panel commands */
+ ctl->clk_rate = MDP_CLK_DEFAULT_RATE;
+ ctl->bus_ib_quota = SZ_1M;
+ mdss_mdp_ctl_perf_commit(MDSS_MDP_PERF_UPDATE_ALL);
+
ret = pdata->on(pdata);
start_fail:
diff --git a/drivers/video/msm/mdss/mdss_mdp_formats.h b/drivers/video/msm/mdss/mdss_mdp_formats.h
index 07eefc1..ee3b8e6 100644
--- a/drivers/video/msm/mdss/mdss_mdp_formats.h
+++ b/drivers/video/msm/mdss/mdss_mdp_formats.h
@@ -18,311 +18,149 @@
#include "mdss_mdp.h"
-#define C3_ALPHA 3 /* alpha */
-#define C2_R_Cr 2 /* R/Cr */
-#define C1_B_Cb 1 /* B/Cb */
-#define C0_G_Y 0 /* G/luma */
+ /*
+ * number of bits for source component,
+ * 0 = 1 bit, 1 = 2 bits, 2 = 6 bits, 3 = 8 bits
+ */
+enum {
+ COLOR_4BIT,
+ COLOR_5BIT,
+ COLOR_6BIT,
+ COLOR_8BIT,
+};
-static struct mdss_mdp_format_params mdss_mdp_format_map[MDP_IMGTYPE_LIMIT] = {
- [MDP_RGB_565] = {
- .format = MDP_RGB_565,
+#define FMT_RGB_565(fmt, e0, e1, e2) \
+ { \
+ .format = (fmt), \
+ .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED, \
+ .unpack_tight = 1, \
+ .unpack_align_msb = 0, \
+ .alpha_enable = 0, \
+ .unpack_count = 3, \
+ .bpp = 2, \
+ .element = { (e0), (e1), (e2) }, \
+ .bits = { \
+ [C2_R_Cr] = COLOR_5BIT, \
+ [C0_G_Y] = COLOR_6BIT, \
+ [C1_B_Cb] = COLOR_5BIT, \
+ }, \
+ }
+
+#define FMT_RGB_888(fmt, e0, e1, e2) \
+ { \
+ .format = (fmt), \
+ .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED, \
+ .unpack_tight = 1, \
+ .unpack_align_msb = 0, \
+ .alpha_enable = 0, \
+ .unpack_count = 3, \
+ .bpp = 3, \
+ .element = { (e0), (e1), (e2) }, \
+ .bits = { \
+ [C2_R_Cr] = COLOR_8BIT, \
+ [C0_G_Y] = COLOR_8BIT, \
+ [C1_B_Cb] = COLOR_8BIT, \
+ }, \
+ }
+
+#define FMT_RGB_8888(fmt, alpha_en, e0, e1, e2, e3) \
+ { \
+ .format = (fmt), \
+ .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED, \
+ .unpack_tight = 1, \
+ .unpack_align_msb = 0, \
+ .alpha_enable = (alpha_en), \
+ .unpack_count = 4, \
+ .bpp = 4, \
+ .element = { (e0), (e1), (e2), (e3) }, \
+ .bits = { \
+ [C3_ALPHA] = COLOR_8BIT, \
+ [C2_R_Cr] = COLOR_8BIT, \
+ [C0_G_Y] = COLOR_8BIT, \
+ [C1_B_Cb] = COLOR_8BIT, \
+ }, \
+ }
+
+#define FMT_YUV_COMMON(fmt) \
+ .format = (fmt), \
+ .is_yuv = 1, \
+ .bits = { \
+ [C2_R_Cr] = COLOR_8BIT, \
+ [C0_G_Y] = COLOR_8BIT, \
+ [C1_B_Cb] = COLOR_8BIT, \
+ }, \
+ .alpha_enable = 0, \
+ .unpack_tight = 1, \
+ .unpack_align_msb = 0
+
+#define FMT_YUV_PSEUDO(fmt, samp, e0, e1) \
+ { \
+ FMT_YUV_COMMON(fmt), \
+ .fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR, \
+ .chroma_sample = samp, \
+ .unpack_count = 2, \
+ .bpp = 2, \
+ .element = { (e0), (e1) }, \
+ }
+
+#define FMT_YUV_PLANR(fmt, samp, e0, e1) \
+ { \
+ FMT_YUV_COMMON(fmt), \
+ .fetch_planes = MDSS_MDP_PLANE_PLANAR, \
+ .chroma_sample = samp, \
+ .element = { (e0), (e1) } \
+ }
+
+static struct mdss_mdp_format_params mdss_mdp_format_map[] = {
+ FMT_RGB_565(MDP_RGB_565, C1_B_Cb, C0_G_Y, C2_R_Cr),
+ FMT_RGB_565(MDP_BGR_565, C2_R_Cr, C0_G_Y, C1_B_Cb),
+ FMT_RGB_888(MDP_RGB_888, C2_R_Cr, C0_G_Y, C1_B_Cb),
+ FMT_RGB_888(MDP_BGR_888, C1_B_Cb, C0_G_Y, C2_R_Cr),
+
+ FMT_RGB_8888(MDP_XRGB_8888, 0, C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb),
+ FMT_RGB_8888(MDP_ARGB_8888, 1, C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb),
+ FMT_RGB_8888(MDP_RGBA_8888, 1, C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA),
+ FMT_RGB_8888(MDP_RGBX_8888, 0, C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA),
+ FMT_RGB_8888(MDP_BGRA_8888, 1, C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA),
+
+ FMT_YUV_PSEUDO(MDP_Y_CRCB_H1V1, MDSS_MDP_CHROMA_RGB, C2_R_Cr, C1_B_Cb),
+ FMT_YUV_PSEUDO(MDP_Y_CBCR_H1V1, MDSS_MDP_CHROMA_RGB, C1_B_Cb, C2_R_Cr),
+ FMT_YUV_PSEUDO(MDP_Y_CRCB_H2V1, MDSS_MDP_CHROMA_H2V1, C2_R_Cr, C1_B_Cb),
+ FMT_YUV_PSEUDO(MDP_Y_CBCR_H2V1, MDSS_MDP_CHROMA_H2V1, C1_B_Cb, C2_R_Cr),
+ FMT_YUV_PSEUDO(MDP_Y_CRCB_H1V2, MDSS_MDP_CHROMA_H1V2, C2_R_Cr, C1_B_Cb),
+ FMT_YUV_PSEUDO(MDP_Y_CBCR_H1V2, MDSS_MDP_CHROMA_H1V2, C1_B_Cb, C2_R_Cr),
+ FMT_YUV_PSEUDO(MDP_Y_CRCB_H2V2, MDSS_MDP_CHROMA_420, C2_R_Cr, C1_B_Cb),
+ FMT_YUV_PSEUDO(MDP_Y_CBCR_H2V2, MDSS_MDP_CHROMA_420, C1_B_Cb, C2_R_Cr),
+ FMT_YUV_PSEUDO(MDP_Y_CBCR_H2V2_VENUS, MDSS_MDP_CHROMA_420,
+ C1_B_Cb, C2_R_Cr),
+
+ FMT_YUV_PLANR(MDP_Y_CR_CB_H2V2, MDSS_MDP_CHROMA_420, C2_R_Cr, C1_B_Cb),
+ FMT_YUV_PLANR(MDP_Y_CB_CR_H2V2, MDSS_MDP_CHROMA_420, C1_B_Cb, C2_R_Cr),
+ FMT_YUV_PLANR(MDP_Y_CR_CB_GH2V2, MDSS_MDP_CHROMA_420, C2_R_Cr, C1_B_Cb),
+
+ {
+ FMT_YUV_COMMON(MDP_YCBCR_H1V1),
.fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
- .a_bit = 0,
- .r_bit = 1, /* R, 5 bits */
- .b_bit = 1, /* B, 5 bits */
- .g_bit = 2, /* G, 6 bits */
- .alpha_enable = 0,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
- .unpack_count = 2,
- .element2 = C2_R_Cr,
- .element1 = C0_G_Y,
- .element0 = C1_B_Cb,
- .bpp = 1, /* 2 bpp */
- },
- [MDP_BGR_565] = {
- .format = MDP_BGR_565,
- .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
- .a_bit = 0,
- .r_bit = 1, /* R, 5 bits */
- .b_bit = 1, /* B, 5 bits */
- .g_bit = 2, /* G, 6 bits */
- .alpha_enable = 0,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
- .unpack_count = 2,
- .element2 = C1_B_Cb,
- .element1 = C0_G_Y,
- .element0 = C2_R_Cr,
- .bpp = 1, /* 2 bpp */
- },
- [MDP_RGB_888] = {
- .format = MDP_RGB_888,
- .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
- .a_bit = 0,
- .r_bit = 3, /* R, 8 bits */
- .b_bit = 3, /* B, 8 bits */
- .g_bit = 3, /* G, 8 bits */
- .alpha_enable = 0,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
- .unpack_count = 2,
- .element2 = C1_B_Cb,
- .element1 = C0_G_Y,
- .element0 = C2_R_Cr,
- .bpp = 2, /* 3 bpp */
- },
- [MDP_XRGB_8888] = {
- .format = MDP_XRGB_8888,
- .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
- .a_bit = 3, /* alpha, 4 bits */
- .r_bit = 3, /* R, 8 bits */
- .b_bit = 3, /* B, 8 bits */
- .g_bit = 3, /* G, 8 bits */
- .alpha_enable = 0,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
+ .chroma_sample = MDSS_MDP_CHROMA_RGB,
.unpack_count = 3,
- .element3 = C1_B_Cb,
- .element2 = C0_G_Y,
- .element1 = C2_R_Cr,
- .element0 = C3_ALPHA,
- .bpp = 3, /* 4 bpp */
+ .bpp = 3,
+ .element = { C2_R_Cr, C1_B_Cb, C0_G_Y },
},
- [MDP_ARGB_8888] = {
- .format = MDP_ARGB_8888,
+ {
+ FMT_YUV_COMMON(MDP_YCRCB_H1V1),
.fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
- .a_bit = 3, /* alpha, 4 bits */
- .r_bit = 3, /* R, 8 bits */
- .b_bit = 3, /* B, 8 bits */
- .g_bit = 3, /* G, 8 bits */
- .alpha_enable = 1,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
+ .chroma_sample = MDSS_MDP_CHROMA_RGB,
.unpack_count = 3,
- .element3 = C1_B_Cb,
- .element2 = C0_G_Y,
- .element1 = C2_R_Cr,
- .element0 = C3_ALPHA,
- .bpp = 3, /* 4 bpp */
+ .bpp = 3,
+ .element = { C1_B_Cb, C2_R_Cr, C0_G_Y },
},
- [MDP_RGBA_8888] = {
- .format = MDP_RGBA_8888,
- .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
- .a_bit = 3, /* alpha, 4 bits */
- .r_bit = 3, /* R, 8 bits */
- .b_bit = 3, /* B, 8 bits */
- .g_bit = 3, /* G, 8 bits */
- .alpha_enable = 1,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
- .unpack_count = 3,
- .element3 = C3_ALPHA,
- .element2 = C1_B_Cb,
- .element1 = C0_G_Y,
- .element0 = C2_R_Cr,
- .bpp = 3, /* 4 bpp */
- },
- [MDP_RGBX_8888] = {
- .format = MDP_RGBX_8888,
- .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
- .a_bit = 3,
- .r_bit = 3, /* R, 8 bits */
- .b_bit = 3, /* B, 8 bits */
- .g_bit = 3, /* G, 8 bits */
- .alpha_enable = 0,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
- .unpack_count = 3,
- .element3 = C3_ALPHA,
- .element2 = C1_B_Cb,
- .element1 = C0_G_Y,
- .element0 = C2_R_Cr,
- .bpp = 3, /* 4 bpp */
- },
- [MDP_BGRA_8888] = {
- .format = MDP_BGRA_8888,
- .fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
- .a_bit = 3, /* alpha, 4 bits */
- .r_bit = 3, /* R, 8 bits */
- .b_bit = 3, /* B, 8 bits */
- .g_bit = 3, /* G, 8 bits */
- .alpha_enable = 1,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
- .unpack_count = 3,
- .element3 = C3_ALPHA,
- .element2 = C2_R_Cr,
- .element1 = C0_G_Y,
- .element0 = C1_B_Cb,
- .bpp = 3, /* 4 bpp */
- },
- [MDP_YCRYCB_H2V1] = {
- .format = MDP_YCRYCB_H2V1,
- .is_yuv = 1,
- .a_bit = 0,
- .r_bit = 3, /* R, 8 bits */
- .b_bit = 3, /* B, 8 bits */
- .g_bit = 3, /* G, 8 bits */
- .alpha_enable = 0,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
- .unpack_count = 1, /* 2 */
- .bpp = 1, /* 2 bpp */
+ {
+ FMT_YUV_COMMON(MDP_YCRYCB_H2V1),
.fetch_planes = MDSS_MDP_PLANE_INTERLEAVED,
.chroma_sample = MDSS_MDP_CHROMA_H2V1,
- .unpack_count = 3,
- .element3 = C0_G_Y,
- .element2 = C2_R_Cr,
- .element1 = C0_G_Y,
- .element0 = C1_B_Cb,
- },
- [MDP_Y_CRCB_H2V1] = {
- .format = MDP_Y_CRCB_H2V1,
- .is_yuv = 1,
- .a_bit = 0,
- .r_bit = 3, /* R, 8 bits */
- .b_bit = 3, /* B, 8 bits */
- .g_bit = 3, /* G, 8 bits */
- .alpha_enable = 0,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
- .unpack_count = 1, /* 2 */
- .bpp = 1, /* 2 bpp */
- .fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR,
- .chroma_sample = MDSS_MDP_CHROMA_H2V1,
- .element1 = C1_B_Cb,
- .element0 = C2_R_Cr,
- },
- [MDP_Y_CBCR_H2V1] = {
- .format = MDP_Y_CBCR_H2V1,
- .is_yuv = 1,
- .a_bit = 0,
- .r_bit = 3, /* R, 8 bits */
- .b_bit = 3, /* B, 8 bits */
- .g_bit = 3, /* G, 8 bits */
- .alpha_enable = 0,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
- .unpack_count = 1, /* 2 */
- .bpp = 1, /* 2 bpp */
- .fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR,
- .chroma_sample = MDSS_MDP_CHROMA_H2V1,
- .element1 = C2_R_Cr,
- .element0 = C1_B_Cb,
- },
- [MDP_Y_CRCB_H1V2] = {
- .format = MDP_Y_CRCB_H1V2,
- .is_yuv = 1,
- .a_bit = 0,
- .r_bit = 3, /* R, 8 bits */
- .b_bit = 3, /* B, 8 bits */
- .g_bit = 3, /* G, 8 bits */
- .alpha_enable = 0,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
- .unpack_count = 1, /* 2 */
- .bpp = 1, /* 2 bpp */
- .fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR,
- .chroma_sample = MDSS_MDP_CHROMA_H1V2,
- .element1 = C1_B_Cb,
- .element0 = C2_R_Cr,
- },
- [MDP_Y_CBCR_H1V2] = {
- .format = MDP_Y_CBCR_H1V2,
- .is_yuv = 1,
- .a_bit = 0,
- .r_bit = 3, /* R, 8 bits */
- .b_bit = 3, /* B, 8 bits */
- .g_bit = 3, /* G, 8 bits */
- .alpha_enable = 0,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
- .unpack_count = 1, /* 2 */
- .bpp = 1, /* 2 bpp */
- .fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR,
- .chroma_sample = MDSS_MDP_CHROMA_H1V2,
- .element1 = C2_R_Cr,
- .element0 = C1_B_Cb,
- },
- [MDP_Y_CRCB_H2V2] = {
- .format = MDP_Y_CRCB_H2V2,
- .is_yuv = 1,
- .a_bit = 0,
- .r_bit = 3, /* R, 8 bits */
- .b_bit = 3, /* B, 8 bits */
- .g_bit = 3, /* G, 8 bits */
- .alpha_enable = 0,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
- .unpack_count = 1, /* 2 */
- .bpp = 1, /* 2 bpp */
- .fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR,
- .chroma_sample = MDSS_MDP_CHROMA_420,
- .element1 = C1_B_Cb,
- .element0 = C2_R_Cr,
- },
- [MDP_Y_CBCR_H2V2] = {
- .format = MDP_Y_CBCR_H2V2,
- .is_yuv = 1,
- .a_bit = 0,
- .r_bit = 3, /* R, 8 bits */
- .b_bit = 3, /* B, 8 bits */
- .g_bit = 3, /* G, 8 bits */
- .alpha_enable = 0,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
- .unpack_count = 1, /* 2 */
- .bpp = 1, /* 2 bpp */
- .fetch_planes = MDSS_MDP_PLANE_PSEUDO_PLANAR,
- .chroma_sample = MDSS_MDP_CHROMA_420,
- .element1 = C2_R_Cr,
- .element0 = C1_B_Cb,
- },
- [MDP_Y_CR_CB_H2V2] = {
- .format = MDP_Y_CR_CB_H2V2,
- .is_yuv = 1,
- .a_bit = 0,
- .r_bit = 3, /* R, 8 bits */
- .b_bit = 3, /* B, 8 bits */
- .g_bit = 3, /* G, 8 bits */
- .alpha_enable = 0,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
- .unpack_count = 1, /* 2 */
- .bpp = 1, /* 2 bpp */
- .fetch_planes = MDSS_MDP_PLANE_PLANAR,
- .chroma_sample = MDSS_MDP_CHROMA_420,
- },
- [MDP_Y_CB_CR_H2V2] = {
- .format = MDP_Y_CB_CR_H2V2,
- .is_yuv = 1,
- .a_bit = 0,
- .r_bit = 3, /* R, 8 bits */
- .b_bit = 3, /* B, 8 bits */
- .g_bit = 3, /* G, 8 bits */
- .alpha_enable = 0,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
- .unpack_count = 1, /* 2 */
- .bpp = 1, /* 2 bpp */
- .fetch_planes = MDSS_MDP_PLANE_PLANAR,
- .chroma_sample = MDSS_MDP_CHROMA_420,
- },
- [MDP_Y_CR_CB_GH2V2] = {
- .format = MDP_Y_CR_CB_GH2V2,
- .is_yuv = 1,
- .a_bit = 0,
- .r_bit = 3, /* R, 8 bits */
- .b_bit = 3, /* B, 8 bits */
- .g_bit = 3, /* G, 8 bits */
- .alpha_enable = 0,
- .unpack_tight = 1,
- .unpack_align_msb = 0,
- .unpack_count = 1, /* 2 */
- .bpp = 1, /* 2 bpp */
- .fetch_planes = MDSS_MDP_PLANE_PLANAR,
- .chroma_sample = MDSS_MDP_CHROMA_420,
+ .unpack_count = 4,
+ .bpp = 2,
+ .element = { C1_B_Cb, C0_G_Y, C2_R_Cr, C0_G_Y },
},
};
#endif
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index bc64d2e..6f92474 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -13,6 +13,8 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
+#include <linux/workqueue.h>
+
#include "mdss_fb.h"
#include "mdss_mdp.h"
@@ -44,6 +46,12 @@
u8 timegen_en;
struct completion pp_comp;
struct completion vsync_comp;
+
+ struct mutex vsync_lock;
+ struct work_struct vsync_work;
+ mdp_vsync_handler_t vsync_handler;
+ void *vsync_ptr;
+ ktime_t vsync_time;
};
struct mdss_mdp_video_ctx mdss_mdp_video_ctx_list[MAX_SESSIONS];
@@ -141,6 +149,47 @@
return 0;
}
+static void send_vsync_work(struct work_struct *work)
+{
+ struct mdss_mdp_video_ctx *ctx;
+
+ ctx = container_of(work, typeof(*ctx), vsync_work);
+ mutex_lock(&ctx->vsync_lock);
+ if (ctx->vsync_handler)
+ ctx->vsync_handler(ctx->vsync_ptr, ctx->vsync_time);
+ mutex_unlock(&ctx->vsync_lock);
+}
+
+static int mdss_mdp_video_set_vsync_handler(struct mdss_mdp_ctl *ctl,
+ mdp_vsync_handler_t vsync_handler)
+{
+ struct mdss_mdp_video_ctx *ctx;
+
+ ctx = (struct mdss_mdp_video_ctx *) ctl->priv_data;
+ if (!ctx) {
+ pr_err("invalid ctx for ctl=%d\n", ctl->num);
+ return -ENODEV;
+ }
+ if (mutex_lock_interruptible(&ctx->vsync_lock))
+ return -EINTR;
+
+ if (!ctx->timegen_en) {
+ ctx->vsync_time = ktime_get();
+ schedule_work(&ctx->vsync_work);
+ }
+
+ if (!ctx->vsync_handler && vsync_handler)
+ mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num);
+ else if (ctx->vsync_handler && !vsync_handler)
+ mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num);
+
+ ctx->vsync_handler = vsync_handler;
+ ctx->vsync_ptr = ctl;
+ mutex_unlock(&ctx->vsync_lock);
+
+ return 0;
+}
+
static int mdss_mdp_video_stop(struct mdss_mdp_ctl *ctl)
{
struct mdss_mdp_video_ctx *ctx;
@@ -161,6 +210,11 @@
ctx->timegen_en = false;
}
+ mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, 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));
return 0;
@@ -190,10 +244,13 @@
pr_err("invalid ctx\n");
return;
}
+ ctx->vsync_time = ktime_get();
pr_debug("intr ctl=%d\n", ctx->ctl_num);
complete(&ctx->vsync_comp);
+ if (ctx->vsync_handler)
+ schedule_work(&ctx->vsync_work);
}
static int mdss_mdp_video_prepare(struct mdss_mdp_ctl *ctl, void *arg)
@@ -207,15 +264,10 @@
}
if (ctx->timegen_en) {
- u32 intr_type = MDSS_MDP_IRQ_PING_PONG_COMP;
-
pr_debug("waiting for ping pong %d done\n", ctx->pp_num);
- mdss_mdp_set_intr_callback(intr_type, ctx->pp_num,
- mdss_mdp_video_pp_intr_done, ctx);
- mdss_mdp_irq_enable(intr_type, ctx->pp_num);
-
+ mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num);
wait_for_completion_interruptible(&ctx->pp_comp);
- mdss_mdp_irq_disable(intr_type, ctx->pp_num);
+ mdss_mdp_irq_disable(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num);
}
return 0;
@@ -224,7 +276,6 @@
static int mdss_mdp_video_display(struct mdss_mdp_ctl *ctl, void *arg)
{
struct mdss_mdp_video_ctx *ctx;
- u32 intr_type = MDSS_MDP_IRQ_INTF_VSYNC;
pr_debug("kickoff ctl=%d\n", ctl->num);
@@ -233,9 +284,12 @@
pr_err("invalid ctx\n");
return -ENODEV;
}
- mdss_mdp_set_intr_callback(intr_type, ctl->intf_num,
- mdss_mdp_video_vsync_intr_done, ctx);
- mdss_mdp_irq_enable(intr_type, ctl->intf_num);
+ INIT_COMPLETION(ctx->vsync_comp);
+
+ if (mutex_lock_interruptible(&ctx->vsync_lock))
+ return -EINTR;
+ if (!ctx->vsync_handler)
+ mdss_mdp_irq_enable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num);
if (!ctx->timegen_en) {
int off = MDSS_MDP_REG_INTF_OFFSET(ctl->intf_num);
@@ -249,7 +303,9 @@
}
wait_for_completion_interruptible(&ctx->vsync_comp);
- mdss_mdp_irq_disable(intr_type, ctl->intf_num);
+ if (!ctx->vsync_handler)
+ mdss_mdp_irq_disable(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num);
+ mutex_unlock(&ctx->vsync_lock);
return 0;
}
@@ -293,6 +349,13 @@
init_completion(&ctx->pp_comp);
init_completion(&ctx->vsync_comp);
+ INIT_WORK(&ctx->vsync_work, send_vsync_work);
+ mutex_init(&ctx->vsync_lock);
+ mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_INTF_VSYNC, ctl->intf_num,
+ mdss_mdp_video_vsync_intr_done, ctx);
+ mdss_mdp_set_intr_callback(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num,
+ mdss_mdp_video_pp_intr_done, ctx);
+
itp.width = pinfo->xres + pinfo->lcdc.xres_pad;
itp.height = pinfo->yres + pinfo->lcdc.yres_pad;
itp.border_clr = pinfo->lcdc.border_clr;
@@ -316,6 +379,7 @@
ctl->stop_fnc = mdss_mdp_video_stop;
ctl->prepare_fnc = mdss_mdp_video_prepare;
ctl->display_fnc = mdss_mdp_video_display;
+ ctl->set_vsync_handler = mdss_mdp_video_set_vsync_handler;
return 0;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
index af422b7..8b4434e 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_writeback.c
@@ -145,20 +145,24 @@
dst_format = (chroma_samp << 23) |
(fmt->fetch_planes << 19) |
- (fmt->unpack_align_msb << 18) |
- (fmt->unpack_tight << 17) |
- (fmt->unpack_count << 12) |
- (fmt->bpp << 9) |
- (fmt->alpha_enable << 8) |
- (fmt->a_bit << 6) |
- (fmt->r_bit << 4) |
- (fmt->b_bit << 2) |
- (fmt->g_bit << 0);
+ (fmt->bits[C3_ALPHA] << 6) |
+ (fmt->bits[C2_R_Cr] << 4) |
+ (fmt->bits[C1_B_Cb] << 2) |
+ (fmt->bits[C0_G_Y] << 0);
- pattern = (fmt->element3 << 24) |
- (fmt->element2 << 15) |
- (fmt->element1 << 8) |
- (fmt->element0 << 0);
+ if (fmt->alpha_enable)
+ dst_format |= BIT(8); /* DSTC3_EN */
+
+ if (fmt->fetch_planes != MDSS_MDP_PLANE_PLANAR) {
+ pattern = (fmt->element[3] << 24) | (fmt->element[2] << 15) |
+ (fmt->element[1] << 8) | (fmt->element[0] << 0);
+ dst_format |= (fmt->unpack_align_msb << 18) |
+ (fmt->unpack_tight << 17) |
+ ((fmt->unpack_count - 1) << 12) |
+ ((fmt->bpp - 1) << 9);
+ } else {
+ pattern = 0;
+ }
ystride0 = (ctx->dst_planes.ystride[0]) |
(ctx->dst_planes.ystride[1] << 16);
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 3c7afed..1cb474d 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -13,6 +13,7 @@
#define pr_fmt(fmt) "%s: " fmt, __func__
+#include <linux/dma-mapping.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/major.h>
@@ -48,7 +49,6 @@
struct mdss_mdp_format_params *fmt)
{
u32 xres, yres;
- u32 dst_w, dst_h;
xres = mfd->fbi->var.xres;
yres = mfd->fbi->var.yres;
@@ -61,32 +61,45 @@
if (req->src.width > MAX_IMG_WIDTH ||
req->src.height > MAX_IMG_HEIGHT ||
req->src_rect.w == 0 || req->src_rect.h == 0 ||
- req->dst_rect.w < MIN_DST_W || req->dst_rect.h < MIN_DST_H ||
- req->dst_rect.w > MAX_DST_W || req->dst_rect.h > MAX_DST_H ||
CHECK_BOUNDS(req->src_rect.x, req->src_rect.w, req->src.width) ||
- CHECK_BOUNDS(req->src_rect.y, req->src_rect.h, req->src.height) ||
- CHECK_BOUNDS(req->dst_rect.x, req->dst_rect.w, xres) ||
- CHECK_BOUNDS(req->dst_rect.y, req->dst_rect.h, yres)) {
- pr_err("invalid image img_w=%d img_h=%d\n",
- req->src.width, req->src.height);
-
- pr_err("\tsrc_rect=%d,%d,%d,%d dst_rect=%d,%d,%d,%d\n",
+ CHECK_BOUNDS(req->src_rect.y, req->src_rect.h, req->src.height)) {
+ pr_err("invalid source image img wh=%dx%d rect=%d,%d,%d,%d\n",
+ req->src.width, req->src.height,
req->src_rect.x, req->src_rect.y,
- req->src_rect.w, req->src_rect.h,
- req->dst_rect.x, req->dst_rect.y,
+ req->src_rect.w, req->src_rect.h);
+ return -EOVERFLOW;
+ }
+
+ if (req->dst_rect.w < MIN_DST_W || req->dst_rect.h < MIN_DST_H ||
+ req->dst_rect.w > MAX_DST_W || req->dst_rect.h > MAX_DST_H) {
+ pr_err("invalid destination resolution (%dx%d)",
req->dst_rect.w, req->dst_rect.h);
- return -EINVAL;
+ return -EOVERFLOW;
}
- if (req->flags & MDP_ROT_90) {
- dst_h = req->dst_rect.w;
- dst_w = req->dst_rect.h;
+ if (req->flags & MDSS_MDP_ROT_ONLY) {
+ /* dst res should match src res in rotation only mode*/
+ req->dst_rect.w = req->src_rect.w;
+ req->dst_rect.h = req->src_rect.h;
} else {
- dst_w = req->dst_rect.w;
- dst_h = req->dst_rect.h;
- }
+ u32 dst_w, dst_h;
- if (!(req->flags & MDSS_MDP_ROT_ONLY)) {
+ if ((CHECK_BOUNDS(req->dst_rect.x, req->dst_rect.w, xres) ||
+ CHECK_BOUNDS(req->dst_rect.y, req->dst_rect.h, yres))) {
+ pr_err("invalid destination rect=%d,%d,%d,%d\n",
+ req->dst_rect.x, req->dst_rect.y,
+ req->dst_rect.w, req->dst_rect.h);
+ return -EOVERFLOW;
+ }
+
+ if (req->flags & MDP_ROT_90) {
+ dst_h = req->dst_rect.w;
+ dst_w = req->dst_rect.h;
+ } else {
+ dst_w = req->dst_rect.w;
+ dst_h = req->dst_rect.h;
+ }
+
if ((req->src_rect.w * MAX_UPSCALE_RATIO) < dst_w) {
pr_err("too much upscaling Width %d->%d\n",
req->src_rect.w, req->dst_rect.w);
@@ -110,6 +123,22 @@
req->src_rect.h, req->dst_rect.h);
return -EINVAL;
}
+
+ if ((fmt->chroma_sample == MDSS_MDP_CHROMA_420 ||
+ fmt->chroma_sample == MDSS_MDP_CHROMA_H2V1) &&
+ ((req->src_rect.w * (MAX_UPSCALE_RATIO / 2)) < dst_w)) {
+ pr_err("too much YUV upscaling Width %d->%d\n",
+ req->src_rect.w, req->dst_rect.w);
+ return -EINVAL;
+ }
+
+ if ((fmt->chroma_sample == MDSS_MDP_CHROMA_420 ||
+ fmt->chroma_sample == MDSS_MDP_CHROMA_H1V2) &&
+ (req->src_rect.h * (MAX_UPSCALE_RATIO / 2)) < dst_h) {
+ pr_err("too much YUV upscaling Height %d->%d\n",
+ req->src_rect.h, req->dst_rect.h);
+ return -EINVAL;
+ }
}
if (fmt->is_yuv) {
@@ -122,22 +151,6 @@
pr_err("invalid odd dst resolution\n");
return -EINVAL;
}
-
- if (((req->src_rect.w * (MAX_UPSCALE_RATIO / 2)) < dst_w) &&
- (fmt->chroma_sample == MDSS_MDP_CHROMA_420 ||
- fmt->chroma_sample == MDSS_MDP_CHROMA_H2V1)) {
- pr_err("too much YUV upscaling Width %d->%d\n",
- req->src_rect.w, req->dst_rect.w);
- return -EINVAL;
- }
-
- if (((req->src_rect.h * (MAX_UPSCALE_RATIO / 2)) < dst_h) &&
- (fmt->chroma_sample == MDSS_MDP_CHROMA_420 ||
- fmt->chroma_sample == MDSS_MDP_CHROMA_H1V2)) {
- pr_err("too much YUV upscaling Height %d->%d\n",
- req->src_rect.h, req->dst_rect.h);
- return -EINVAL;
- }
}
return 0;
@@ -602,15 +615,67 @@
mfd->kickoff_fnc(mfd->ctl);
}
-static int mdss_mdp_hw_cursor_update(struct fb_info *info,
+static void mdss_mdp_overlay_handle_vsync(struct mdss_mdp_ctl *ctl, ktime_t t)
+{
+ struct device *dev;
+ char buf[64];
+ char *envp[2];
+
+ if (!ctl || !ctl->mfd || !ctl->mfd->fbi) {
+ pr_warn("Invalid handle for vsync\n");
+ return;
+ }
+
+ dev = ctl->mfd->fbi->dev;
+
+ snprintf(buf, sizeof(buf), "VSYNC=%llu", ktime_to_ns(t));
+ envp[0] = buf;
+ envp[1] = NULL;
+ kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
+
+ pr_debug("sent vsync on ctl=%d ts=%llu\n", ctl->num, ktime_to_ns(t));
+}
+
+static int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en)
+{
+ struct mdss_mdp_ctl *ctl = mfd->ctl;
+ int rc;
+
+ if (!ctl)
+ return -ENODEV;
+ if (!ctl->set_vsync_handler)
+ return -ENOTSUPP;
+
+ pr_debug("vsync en=%d\n", en);
+
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+ if (en)
+ rc = ctl->set_vsync_handler(ctl, mdss_mdp_overlay_handle_vsync);
+ else
+ rc = ctl->set_vsync_handler(ctl, NULL);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF, false);
+
+ return rc;
+}
+
+static int mdss_mdp_hw_cursor_update(struct msm_fb_data_type *mfd,
struct fb_cursor *cursor)
{
- struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
struct mdss_mdp_mixer *mixer;
struct fb_image *img = &cursor->image;
- int calpha_en, transp_en, blendcfg, alpha;
+ u32 blendcfg;
int off, ret = 0;
+ if (!mfd->cursor_buf) {
+ mfd->cursor_buf = dma_alloc_coherent(NULL, MDSS_MDP_CURSOR_SIZE,
+ (dma_addr_t *) &mfd->cursor_buf_phys,
+ GFP_KERNEL);
+ if (!mfd->cursor_buf) {
+ pr_err("can't allocate cursor buffer\n");
+ return -ENOMEM;
+ }
+ }
+
mixer = mdss_mdp_mixer_get(mfd->ctl, MDSS_MDP_MIXER_MUX_DEFAULT);
off = MDSS_MDP_REG_LM_OFFSET(mixer->num);
@@ -630,6 +695,7 @@
(img->dy << 16) | img->dx);
if (cursor->set & FB_CUR_SETIMAGE) {
+ int calpha_en, transp_en, alpha, size;
ret = copy_from_user(mfd->cursor_buf, img->data,
img->width * img->height * 4);
if (ret)
@@ -647,8 +713,9 @@
else
calpha_en = 0x2; /* argb */
- MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_SIZE,
- (img->height << 16) | img->width);
+ size = (img->height << 16) | img->width;
+ MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_IMG_SIZE, size);
+ MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_SIZE, size);
MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_STRIDE,
img->width * 4);
MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_BASE_ADDR,
@@ -684,10 +751,13 @@
}
if (!cursor->enable != !(blendcfg & 0x1)) {
- if (cursor->enable)
+ if (cursor->enable) {
+ pr_debug("enable hw cursor on mixer=%d\n", mixer->num);
blendcfg |= 0x1;
- else
+ } else {
+ pr_debug("disable hw cursor on mixer=%d\n", mixer->num);
blendcfg &= ~0x1;
+ }
MDSS_MDP_REG_WRITE(off + MDSS_MDP_REG_LM_CURSOR_BLEND_CONFIG,
blendcfg);
@@ -795,6 +865,16 @@
}
break;
+ case MSMFB_VSYNC_CTRL:
+ case MSMFB_OVERLAY_VSYNC_CTRL:
+ if (!copy_from_user(&val, argp, sizeof(val))) {
+ ret = mdss_mdp_overlay_vsync_ctrl(mfd, val);
+ } else {
+ pr_err("MSMFB_OVERLAY_VSYNC_CTRL failed (%d)\n", ret);
+ ret = -EFAULT;
+ }
+ break;
+
default:
if (mfd->panel_info.type == WRITEBACK_PANEL)
ret = mdss_mdp_wb_ioctl_handler(mfd, cmd, argp);
@@ -809,7 +889,6 @@
mfd->on_fnc = mdss_mdp_ctl_on;
mfd->off_fnc = mdss_mdp_ctl_off;
mfd->hw_refresh = true;
- mfd->lut_update = NULL;
mfd->do_histogram = NULL;
mfd->overlay_play_enable = true;
mfd->cursor_update = mdss_mdp_hw_cursor_update;
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 9a8260f..c94068a 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -363,6 +363,12 @@
}
chroma_sample = pipe->src_fmt->chroma_sample;
+ if (pipe->flags & MDP_SOURCE_ROTATED_90) {
+ if (chroma_sample == MDSS_MDP_CHROMA_H1V2)
+ chroma_sample = MDSS_MDP_CHROMA_H2V1;
+ else if (chroma_sample == MDSS_MDP_CHROMA_H2V1)
+ chroma_sample = MDSS_MDP_CHROMA_H1V2;
+ }
if ((pipe->src.h != pipe->dst.h) ||
(chroma_sample == MDSS_MDP_CHROMA_420) ||
@@ -391,7 +397,7 @@
else
scale_config |= /* G/Y, A */
(MDSS_MDP_SCALE_FILTER_PCMN << 10) |
- (MDSS_MDP_SCALE_FILTER_NEAREST << 18);
+ (MDSS_MDP_SCALE_FILTER_PCMN << 18);
if (pipe->src.h <= chr_dst_h)
scale_config |= /* CrCb */
@@ -449,7 +455,7 @@
else
scale_config |= /* G/Y, A */
(MDSS_MDP_SCALE_FILTER_PCMN << 8) |
- (MDSS_MDP_SCALE_FILTER_NEAREST << 16);
+ (MDSS_MDP_SCALE_FILTER_PCMN << 16);
if (pipe->src.w <= chr_dst_w)
scale_config |= /* CrCb */
@@ -523,7 +529,7 @@
static int mdss_mdp_format_setup(struct mdss_mdp_pipe *pipe)
{
struct mdss_mdp_format_params *fmt;
- u32 rot90, opmode, chroma_samp;
+ u32 opmode, chroma_samp, unpack, src_format;
fmt = pipe->src_fmt;
@@ -536,8 +542,6 @@
pr_debug("pnum=%d format=%d opmode=%x\n", pipe->num, fmt->format,
opmode);
- rot90 = !!(pipe->flags & MDP_ROT_90);
-
chroma_samp = fmt->chroma_sample;
if (pipe->flags & MDP_SOURCE_ROTATED_90) {
if (chroma_samp == MDSS_MDP_CHROMA_H2V1)
@@ -546,26 +550,34 @@
chroma_samp = MDSS_MDP_CHROMA_H2V1;
}
- mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_FORMAT,
- (chroma_samp << 23) |
- (fmt->fetch_planes << 19) |
- (fmt->unpack_align_msb << 18) |
- (fmt->unpack_tight << 17) |
- (fmt->unpack_count << 12) |
- (rot90 << 11) |
- (fmt->bpp << 9) |
- (fmt->alpha_enable << 8) |
- (fmt->a_bit << 6) |
- (fmt->r_bit << 4) |
- (fmt->b_bit << 2) |
- (fmt->g_bit << 0));
+ src_format = (chroma_samp << 23) |
+ (fmt->fetch_planes << 19) |
+ (fmt->bits[C3_ALPHA] << 6) |
+ (fmt->bits[C2_R_Cr] << 4) |
+ (fmt->bits[C1_B_Cb] << 2) |
+ (fmt->bits[C0_G_Y] << 0);
- mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN,
- (fmt->element3 << 24) |
- (fmt->element2 << 16) |
- (fmt->element1 << 8) |
- (fmt->element0 << 0));
+ if (pipe->flags & MDP_ROT_90)
+ src_format |= BIT(11); /* ROT90 */
+ if (fmt->alpha_enable &&
+ fmt->fetch_planes != MDSS_MDP_PLANE_INTERLEAVED)
+ src_format |= BIT(8); /* SRCC3_EN */
+
+ if (fmt->fetch_planes != MDSS_MDP_PLANE_PLANAR) {
+ unpack = (fmt->element[3] << 24) | (fmt->element[2] << 16) |
+ (fmt->element[1] << 8) | (fmt->element[0] << 0);
+
+ src_format |= ((fmt->unpack_count - 1) << 12) |
+ (fmt->unpack_tight << 17) |
+ (fmt->unpack_align_msb << 18) |
+ ((fmt->bpp - 1) << 9);
+ } else {
+ unpack = 0;
+ }
+
+ mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_FORMAT, src_format);
+ mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_UNPACK_PATTERN, unpack);
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC_OP_MODE, opmode);
return 0;
@@ -595,17 +607,23 @@
static int mdss_mdp_src_addr_setup(struct mdss_mdp_pipe *pipe,
struct mdss_mdp_data *data)
{
- int ret;
+ int is_rot = pipe->mixer->rotator_mode;
+ int ret = 0;
pr_debug("pnum=%d\n", pipe->num);
- if (pipe->type != MDSS_MDP_PIPE_TYPE_DMA)
+ if (!is_rot)
data->bwc_enabled = pipe->bwc_mode;
ret = mdss_mdp_data_check(data, &pipe->src_planes);
if (ret)
return ret;
+ /* planar format expects YCbCr, swap chroma planes if YCrCb */
+ if (!is_rot && (pipe->src_fmt->fetch_planes == MDSS_MDP_PLANE_PLANAR) &&
+ (pipe->src_fmt->element[0] == C2_R_Cr))
+ swap(data->p[1].addr, data->p[2].addr);
+
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC0_ADDR, data->p[0].addr);
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC1_ADDR, data->p[1].addr);
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC2_ADDR, data->p[2].addr);
diff --git a/drivers/video/msm/mdss/mdss_mdp_util.c b/drivers/video/msm/mdss/mdss_mdp_util.c
index f6b4fce..53cd378 100644
--- a/drivers/video/msm/mdss/mdss_mdp_util.c
+++ b/drivers/video/msm/mdss/mdss_mdp_util.c
@@ -102,8 +102,6 @@
spin_lock(&mdss_mdp_intr_lock);
fnc = mdp_intr_cb[index].func;
arg = mdp_intr_cb[index].arg;
- if (fnc != NULL)
- mdp_intr_cb[index].func = NULL;
spin_unlock(&mdss_mdp_intr_lock);
if (fnc)
fnc(arg);
@@ -164,14 +162,16 @@
struct mdss_mdp_format_params *mdss_mdp_get_format_params(u32 format)
{
- struct mdss_mdp_format_params *fmt = NULL;
if (format < MDP_IMGTYPE_LIMIT) {
- fmt = &mdss_mdp_format_map[format];
- if (fmt->format != format)
- fmt = NULL;
+ struct mdss_mdp_format_params *fmt = NULL;
+ int i;
+ for (i = 0; i < ARRAY_SIZE(mdss_mdp_format_map); i++) {
+ fmt = &mdss_mdp_format_map[i];
+ if (format == fmt->format)
+ return fmt;
+ }
}
-
- return fmt;
+ return NULL;
}
int mdss_mdp_get_plane_sizes(u32 format, u32 w, u32 h,
@@ -193,30 +193,35 @@
memset(ps, 0, sizeof(struct mdss_mdp_plane_sizes));
if (fmt->fetch_planes == MDSS_MDP_PLANE_INTERLEAVED) {
- u32 bpp = fmt->bpp + 1;
+ u32 bpp = fmt->bpp;
ps->num_planes = 1;
ps->plane_size[0] = w * h * bpp;
ps->ystride[0] = w * bpp;
} else {
u8 hmap[] = { 1, 2, 1, 2 };
u8 vmap[] = { 1, 1, 2, 2 };
- u8 horiz, vert;
+ u8 horiz, vert, stride_align;
horiz = hmap[fmt->chroma_sample];
vert = vmap[fmt->chroma_sample];
- if (format == MDP_Y_CR_CB_GH2V2) {
- ps->plane_size[0] = ALIGN(w, 16) * h;
- ps->plane_size[1] = ALIGN(w / horiz, 16) * (h / vert);
- ps->ystride[0] = ALIGN(w, 16);
- ps->ystride[1] = ALIGN(w / horiz, 16);
- } else {
- ps->plane_size[0] = w * h;
- ps->plane_size[1] = (w / horiz) * (h / vert);
- ps->ystride[0] = w;
- ps->ystride[1] = (w / horiz);
+ switch (format) {
+ case MDP_Y_CR_CB_GH2V2:
+ stride_align = 16;
+ break;
+ case MDP_Y_CBCR_H2V2_VENUS:
+ stride_align = 32;
+ break;
+ default:
+ stride_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] * h;
+ 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;
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index 3ec3a5d..5d23548 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -83,6 +83,18 @@
u32 yres_pad;
};
+
+/* DSI PHY configuration */
+struct mdss_dsi_phy_ctrl {
+ uint32_t regulator[8];
+ uint32_t timing[12];
+ uint32_t ctrl[4];
+ uint32_t strength[2];
+ char bistCtrl[6];
+ uint32_t pll[21];
+ char laneCfg[45];
+};
+
struct mipi_panel_info {
char mode; /* video/cmd */
char interleave_mode;
@@ -103,7 +115,7 @@
char t_clk_post; /* 0xc0, DSI_CLKOUT_TIMING_CTRL */
char t_clk_pre; /* 0xc0, DSI_CLKOUT_TIMING_CTRL */
char vc; /* virtual channel */
- struct mipi_dsi_phy_ctrl *dsi_phy_db;
+ struct mdss_dsi_phy_ctrl *dsi_phy_db;
/* video mode */
char pulse_mode_hsa_he;
char hfp_power_stop;
@@ -168,6 +180,7 @@
struct mdss_panel_info panel_info;
void (*set_backlight) (u32 bl_level);
unsigned char *dsi_base;
+ unsigned char *mmss_cc_base;
/* function entry chain */
int (*on) (struct mdss_panel_data *pdata);
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
index c766ec7..9d9a366 100644
--- a/drivers/video/msm/mdss/msm_mdss_io_8974.c
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -12,6 +12,7 @@
*/
#include <linux/clk.h>
#include <linux/interrupt.h>
+#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
@@ -26,8 +27,9 @@
static struct dsi_clk_desc dsi_pclk;
-static struct clk *dsi_byte_div_clk;
+static struct clk *dsi_byte_clk;
static struct clk *dsi_esc_clk;
+static struct clk *dsi_pixel_clk;
int mdss_dsi_clk_on;
@@ -35,16 +37,23 @@
{
struct device *dev = &pdev->dev;
- dsi_byte_div_clk = clk_get(dev, "byte_clk");
- if (IS_ERR(dsi_byte_div_clk)) {
- pr_err("can't find dsi_byte_div_clk\n");
- dsi_byte_div_clk = NULL;
+ dsi_byte_clk = clk_get(dev, "byte_clk");
+ if (IS_ERR(dsi_byte_clk)) {
+ pr_err("can't find dsi_byte_clk\n");
+ dsi_byte_clk = NULL;
+ goto mdss_dsi_clk_err;
+ }
+
+ dsi_pixel_clk = clk_get(dev, "pixel_clk");
+ if (IS_ERR(dsi_pixel_clk)) {
+ pr_err("can't find dsi_pixel_clk\n");
+ dsi_pixel_clk = NULL;
goto mdss_dsi_clk_err;
}
dsi_esc_clk = clk_get(dev, "core_clk");
if (IS_ERR(dsi_esc_clk)) {
- printk(KERN_ERR "can't find dsi_esc_clk\n");
+ pr_err("can't find dsi_esc_clk\n");
dsi_esc_clk = NULL;
goto mdss_dsi_clk_err;
}
@@ -58,10 +67,12 @@
void mdss_dsi_clk_deinit(struct device *dev)
{
- if (dsi_byte_div_clk)
- clk_put(dsi_byte_div_clk);
+ if (dsi_byte_clk)
+ clk_put(dsi_byte_clk);
if (dsi_esc_clk)
clk_put(dsi_esc_clk);
+ if (dsi_pixel_clk)
+ clk_put(dsi_pixel_clk);
}
#define PREF_DIV_RATIO 27
@@ -143,57 +154,145 @@
return 0;
}
-void cont_splash_clk_ctrl(int enable)
-{
- static int cont_splash_clks_enabled;
- if (enable && !cont_splash_clks_enabled) {
- clk_prepare_enable(dsi_byte_div_clk);
- clk_prepare_enable(dsi_esc_clk);
- cont_splash_clks_enabled = 1;
- } else if (!enable && cont_splash_clks_enabled) {
- clk_disable_unprepare(dsi_byte_div_clk);
- clk_disable_unprepare(dsi_esc_clk);
- cont_splash_clks_enabled = 0;
- }
-}
-
void mdss_dsi_prepare_clocks(void)
{
- clk_prepare(dsi_byte_div_clk);
+ clk_prepare(dsi_byte_clk);
clk_prepare(dsi_esc_clk);
+ clk_prepare(dsi_pixel_clk);
}
void mdss_dsi_unprepare_clocks(void)
{
clk_unprepare(dsi_esc_clk);
- clk_unprepare(dsi_byte_div_clk);
+ clk_unprepare(dsi_pixel_clk);
+ clk_unprepare(dsi_byte_clk);
}
-void mdss_dsi_clk_enable(void)
+void mdss_dsi_clk_enable(struct mdss_panel_data *pdata)
{
if (mdss_dsi_clk_on) {
pr_info("%s: mdss_dsi_clks already ON\n", __func__);
return;
}
- if (clk_set_rate(dsi_byte_div_clk, 1) < 0) /* divided by 1 */
- pr_err("%s: dsi_byte_div_clk - clk_set_rate failed\n",
- __func__);
- if (clk_set_rate(dsi_esc_clk, 2) < 0) /* divided by 2 */
+ if (clk_set_rate(dsi_esc_clk, 19200000) < 0)
pr_err("%s: dsi_esc_clk - clk_set_rate failed\n",
__func__);
- clk_enable(dsi_byte_div_clk);
+
+ if (clk_set_rate(dsi_byte_clk, 53000000) < 0)
+ pr_err("%s: dsi_byte_clk - clk_set_rate failed\n",
+ __func__);
+
+ if (clk_set_rate(dsi_pixel_clk, 70000000) < 0)
+ pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n",
+ __func__);
+
clk_enable(dsi_esc_clk);
+ clk_enable(dsi_byte_clk);
+ clk_enable(dsi_pixel_clk);
+
mdss_dsi_clk_on = 1;
}
-void mdss_dsi_clk_disable(void)
+void mdss_dsi_clk_disable(struct mdss_panel_data *pdata)
{
if (mdss_dsi_clk_on == 0) {
pr_info("%s: mdss_dsi_clks already OFF\n", __func__);
return;
}
+
+ clk_disable(dsi_pixel_clk);
+ clk_disable(dsi_byte_clk);
clk_disable(dsi_esc_clk);
- clk_disable(dsi_byte_div_clk);
+
mdss_dsi_clk_on = 0;
}
+
+void mdss_dsi_phy_sw_reset(struct mdss_panel_data *pdata)
+{
+ /* start phy sw reset */
+ MIPI_OUTP((pdata->dsi_base) + 0x12c, 0x0001);
+ wmb();
+ usleep(1);
+ /* end phy sw reset */
+ MIPI_OUTP((pdata->dsi_base) + 0x12c, 0x0000);
+ wmb();
+ usleep(1);
+}
+
+void mdss_dsi_phy_enable(struct mdss_panel_data *pdata, int on)
+{
+ if (on) {
+ MIPI_OUTP((pdata->dsi_base) + 0x0220, 0x006);
+ usleep(10);
+ MIPI_OUTP((pdata->dsi_base) + 0x0268, 0x001);
+ usleep(10);
+ MIPI_OUTP((pdata->dsi_base) + 0x0268, 0x000);
+ usleep(10);
+ MIPI_OUTP((pdata->dsi_base) + 0x0220, 0x007);
+ wmb();
+
+ /* MMSS_DSI_0_PHY_DSIPHY_CTRL_0 */
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x07e);
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x06e);
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x06c);
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x064);
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x065);
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x075);
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x077);
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x07f);
+ wmb();
+
+ } else {
+ MIPI_OUTP((pdata->dsi_base) + 0x0220, 0x006);
+ usleep(10);
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x000);
+ wmb();
+ }
+}
+
+void mdss_dsi_phy_init(struct mdss_panel_data *pdata)
+{
+ struct mdss_dsi_phy_ctrl *pd;
+ int i, off, ln, offset;
+
+ pd = (pdata->panel_info.mipi).dsi_phy_db;
+
+ off = 0x0580; /* phy regulator ctrl settings */
+ for (i = 0; i < 8; i++) {
+ MIPI_OUTP((pdata->dsi_base) + off, pd->regulator[i]);
+ wmb();
+ off += 4;
+ }
+
+ off = 0x0440; /* phy timing ctrl 0 - 11 */
+ for (i = 0; i < 12; i++) {
+ MIPI_OUTP((pdata->dsi_base) + off, pd->timing[i]);
+ wmb();
+ off += 4;
+ }
+
+ /* Strength ctrl 0 - 1 */
+ MIPI_OUTP((pdata->dsi_base) + 0x0484, pd->strength[0]);
+ MIPI_OUTP((pdata->dsi_base) + 0x0488, pd->strength[1]);
+ wmb();
+
+ off = 0x04b4; /* phy BIST ctrl 0 - 5 */
+ for (i = 0; i < 6; i++) {
+ MIPI_OUTP((pdata->dsi_base) + off, pd->bistCtrl[i]);
+ wmb();
+ off += 4;
+ }
+
+ /* 4 lanes + clk lane configuration */
+ /* lane config n * (0 - 4) & DataPath setup */
+ for (ln = 0; ln < 5; ln++) {
+ off = 0x0300 + (ln * 0x40);
+ for (i = 0; i < 9; i++) {
+ offset = i + (ln * 9);
+ MIPI_OUTP((pdata->dsi_base) + off, pd->laneCfg[offset]);
+ wmb();
+ off += 4;
+ }
+ }
+}
diff --git a/drivers/video/msm/mhl/mhl_8334.c b/drivers/video/msm/mhl/mhl_8334.c
index 646dd29..4347dc7 100644
--- a/drivers/video/msm/mhl/mhl_8334.c
+++ b/drivers/video/msm/mhl/mhl_8334.c
@@ -224,12 +224,6 @@
return 0;
}
-bool mhl_is_connected(void)
-{
- return true;
-}
-
-
/* USB_HANDSHAKING FUNCTIONS */
int mhl_device_discovery(const char *name, int *result)
@@ -547,6 +541,11 @@
pr_debug("MHL: mhl_msm_state->mhl_data->irq=[%d]\n",
mhl_msm_state->mhl_data->irq);
+ if (!mhl_msm_state->mhl_data->mhl_enabled) {
+ pr_info("MHL Display not enabled\n");
+ return -ENODEV;
+ }
+
/* Init GPIO stuff here */
ret = mhl_sii_gpio_setup(1);
if (ret == -1) {
diff --git a/drivers/video/msm/mhl_api.h b/drivers/video/msm/mhl_api.h
index a4364ea..7fdbaa9 100644
--- a/drivers/video/msm/mhl_api.h
+++ b/drivers/video/msm/mhl_api.h
@@ -15,9 +15,9 @@
#define __MHL_API_H__
#ifdef CONFIG_FB_MSM_HDMI_MHL_8334
-bool mhl_is_connected(void);
+bool mhl_is_enabled(void);
#else
-static bool mhl_is_connected(void)
+static bool mhl_is_enabled(void)
{
return false;
}
diff --git a/drivers/video/msm/mipi_dsi.h b/drivers/video/msm/mipi_dsi.h
index ebbf362..2f691cf 100644
--- a/drivers/video/msm/mipi_dsi.h
+++ b/drivers/video/msm/mipi_dsi.h
@@ -117,6 +117,9 @@
#define DSI_INTR_CMD_DMA_DONE_MASK BIT(1)
#define DSI_INTR_CMD_DMA_DONE BIT(0)
+#define DSI_MDP_TERM BIT(8)
+#define DSI_CMD_TERM BIT(0)
+
#define DSI_CMD_TRIGGER_NONE 0x0 /* mdp trigger */
#define DSI_CMD_TRIGGER_TE 0x02
#define DSI_CMD_TRIGGER_SW 0x04
@@ -185,8 +188,8 @@
#define DSI_HDR_DATA1(data) ((data) & 0x0ff)
#define DSI_HDR_WC(wc) ((wc) & 0x0ffff)
-#define DSI_BUF_SIZE 1024
-#define MIPI_DSI_MRPS 0x04 /* Maximum Return Packet Size */
+#define DSI_BUF_SIZE 64
+#define MIPI_DSI_MRPS 0x04 /* Maximum Return Packet Size */
#define MIPI_DSI_LEN 8 /* 4 x 4 - 6 - 2, bytes dcs header+crc-align */
@@ -247,7 +250,6 @@
char *payload;
};
-
typedef void (*kickoff_act)(void *);
struct dsi_kickoff_action {
@@ -257,6 +259,30 @@
};
+#define CMD_REQ_MAX 4
+
+typedef void (*fxn)(u32 data);
+
+#define CMD_REQ_RX 0x0001
+#define CMD_REQ_COMMIT 0x0002
+#define CMD_REQ_NO_MAX_PKT_SIZE 0x0008
+
+struct dcs_cmd_req {
+ struct dsi_cmd_desc *cmds;
+ int cmds_cnt;
+ u32 flags;
+ int rlen; /* rx length */
+ fxn cb;
+};
+
+struct dcs_cmd_list {
+ int put;
+ int get;
+ int tot;
+ struct dcs_cmd_req list[CMD_REQ_MAX];
+};
+
+
char *mipi_dsi_buf_reserve_hdr(struct dsi_buf *dp, int hlen);
char *mipi_dsi_buf_init(struct dsi_buf *dp);
void mipi_dsi_init(void);
@@ -284,7 +310,7 @@
void mipi_dsi_set_tear_on(struct msm_fb_data_type *mfd);
void mipi_dsi_set_tear_off(struct msm_fb_data_type *mfd);
void mipi_dsi_set_backlight(struct msm_fb_data_type *mfd, int level);
-void mipi_dsi_cmd_backlight_tx(int level);
+void mipi_dsi_cmd_backlight_tx(struct dsi_buf *dp);
void mipi_dsi_clk_enable(void);
void mipi_dsi_clk_disable(void);
void mipi_dsi_pre_kickoff_action(void);
@@ -315,6 +341,10 @@
void mipi_dsi_turn_off_clks(void);
void mipi_dsi_clk_cfg(int on);
+int mipi_dsi_cmdlist_put(struct dcs_cmd_req *cmdreq);
+struct dcs_cmd_req *mipi_dsi_cmdlist_get(void);
+void mipi_dsi_cmdlist_commit(int from_mdp);
+
#ifdef CONFIG_FB_MSM_MDP303
void update_lane_config(struct msm_panel_info *pinfo);
#endif
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
index 39e2d6d..39a071b 100644
--- a/drivers/video/msm/mipi_dsi_host.c
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -42,12 +42,13 @@
static struct completion dsi_dma_comp;
static struct completion dsi_mdp_comp;
static struct dsi_buf dsi_tx_buf;
-static int dsi_irq_enabled;
+static struct dsi_buf dsi_rx_buf;
static spinlock_t dsi_irq_lock;
static spinlock_t dsi_mdp_lock;
spinlock_t dsi_clk_lock;
static int dsi_ctrl_lock;
static int dsi_mdp_busy;
+static struct mutex cmd_mutex;
static struct list_head pre_kickoff_list;
static struct list_head post_kickoff_list;
@@ -59,6 +60,8 @@
STAT_DSI_MDP
};
+struct dcs_cmd_list cmdlist;
+
#ifdef CONFIG_FB_MSM_MDP40
void mipi_dsi_mdp_stat_inc(int which)
{
@@ -90,42 +93,52 @@
init_completion(&dsi_dma_comp);
init_completion(&dsi_mdp_comp);
mipi_dsi_buf_alloc(&dsi_tx_buf, DSI_BUF_SIZE);
+ mipi_dsi_buf_alloc(&dsi_rx_buf, DSI_BUF_SIZE);
spin_lock_init(&dsi_irq_lock);
spin_lock_init(&dsi_mdp_lock);
spin_lock_init(&dsi_clk_lock);
+ mutex_init(&cmd_mutex);
INIT_LIST_HEAD(&pre_kickoff_list);
INIT_LIST_HEAD(&post_kickoff_list);
}
-void mipi_dsi_enable_irq(void)
+
+static u32 dsi_irq_mask;
+
+void mipi_dsi_enable_irq(u32 term)
{
unsigned long flags;
spin_lock_irqsave(&dsi_irq_lock, flags);
- if (dsi_irq_enabled) {
- pr_debug("%s: IRQ aleady enabled\n", __func__);
+ if (dsi_irq_mask & term) {
spin_unlock_irqrestore(&dsi_irq_lock, flags);
return;
}
- dsi_irq_enabled = 1;
- enable_irq(dsi_irq);
+ if (dsi_irq_mask == 0) {
+ enable_irq(dsi_irq);
+ pr_debug("%s: IRQ Enable, mask=%x term=%x\n",
+ __func__, (int)dsi_irq_mask, (int)term);
+ }
+ dsi_irq_mask |= term;
spin_unlock_irqrestore(&dsi_irq_lock, flags);
}
-void mipi_dsi_disable_irq(void)
+void mipi_dsi_disable_irq(u32 term)
{
unsigned long flags;
spin_lock_irqsave(&dsi_irq_lock, flags);
- if (dsi_irq_enabled == 0) {
- pr_debug("%s: IRQ already disabled\n", __func__);
+ if (!(dsi_irq_mask & term)) {
spin_unlock_irqrestore(&dsi_irq_lock, flags);
return;
}
-
- dsi_irq_enabled = 0;
- disable_irq(dsi_irq);
+ dsi_irq_mask &= ~term;
+ if (dsi_irq_mask == 0) {
+ disable_irq(dsi_irq);
+ pr_debug("%s: IRQ Disable, mask=%x term=%x\n",
+ __func__, (int)dsi_irq_mask, (int)term);
+ }
spin_unlock_irqrestore(&dsi_irq_lock, flags);
}
@@ -133,17 +146,19 @@
* mipi_dsi_disale_irq_nosync() should be called
* from interrupt context
*/
- void mipi_dsi_disable_irq_nosync(void)
+void mipi_dsi_disable_irq_nosync(u32 term)
{
spin_lock(&dsi_irq_lock);
- if (dsi_irq_enabled == 0) {
- pr_debug("%s: IRQ cannot be disabled\n", __func__);
+ if (!(dsi_irq_mask & term)) {
spin_unlock(&dsi_irq_lock);
return;
}
-
- dsi_irq_enabled = 0;
- disable_irq_nosync(dsi_irq);
+ dsi_irq_mask &= ~term;
+ if (dsi_irq_mask == 0) {
+ disable_irq_nosync(dsi_irq);
+ pr_debug("%s: IRQ Disable, mask=%x term=%x\n",
+ __func__, (int)dsi_irq_mask, (int)term);
+ }
spin_unlock(&dsi_irq_lock);
}
@@ -1007,27 +1022,6 @@
wmb();
}
-int mipi_dsi_ctrl_lock(int mdp)
-{
- unsigned long flag;
- int lock = 0;
-
- spin_lock_irqsave(&dsi_mdp_lock, flag);
- if (dsi_ctrl_lock == FALSE) {
- dsi_ctrl_lock = TRUE;
- lock = 1;
- if (lock && mdp) /* mdp pixel */
- mipi_dsi_enable_irq();
- }
- spin_unlock_irqrestore(&dsi_mdp_lock, flag);
- return lock;
-}
-
-int mipi_dsi_ctrl_lock_query()
-{
- return dsi_ctrl_lock;
-}
-
void mipi_dsi_mdp_busy_wait(struct msm_fb_data_type *mfd)
{
unsigned long flag;
@@ -1060,7 +1054,7 @@
mipi_dsi_mdp_stat_inc(STAT_DSI_START);
spin_lock_irqsave(&dsi_mdp_lock, flag);
- mipi_dsi_enable_irq();
+ mipi_dsi_enable_irq(DSI_MDP_TERM);
dsi_mdp_busy = TRUE;
spin_unlock_irqrestore(&dsi_mdp_lock, flag);
}
@@ -1134,51 +1128,6 @@
return 4;
}
-static char led_pwm1[2] = {0x51, 0x0}; /* DTYPE_DCS_WRITE1 */
-
-static struct dsi_cmd_desc backlight_cmd = {
- DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(led_pwm1), led_pwm1};
-
-/*
- * mipi_dsi_cmd_backlight_tx:
- * thread context only
- */
-void mipi_dsi_cmd_backlight_tx(int level)
-{
- struct dsi_buf *tp;
- struct dsi_cmd_desc *cmd;
- unsigned long flag;
-
- spin_lock_irqsave(&dsi_mdp_lock, flag);
- dsi_mdp_busy = TRUE;
- led_pwm1[1] = (unsigned char)(level);
- tp = &dsi_tx_buf;
- cmd = &backlight_cmd;
- mipi_dsi_buf_init(&dsi_tx_buf);
-
- if (tp->dmap) {
- dma_unmap_single(&dsi_dev, tp->dmap, tp->len, DMA_TO_DEVICE);
- tp->dmap = 0;
- }
-
- mipi_dsi_enable_irq();
- mipi_dsi_cmd_dma_add(tp, cmd);
-
- tp->len += 3;
- tp->len &= ~0x03; /* multipled by 4 */
-
- tp->dmap = dma_map_single(&dsi_dev, tp->data, tp->len, DMA_TO_DEVICE);
- if (dma_mapping_error(&dsi_dev, tp->dmap))
- pr_err("%s: dmap mapp failed\n", __func__);
-
- MIPI_OUTP(MIPI_DSI_BASE + 0x044, tp->dmap);
- MIPI_OUTP(MIPI_DSI_BASE + 0x048, tp->len);
- wmb();
- MIPI_OUTP(MIPI_DSI_BASE + 0x08c, 0x01); /* trigger */
- wmb();
- spin_unlock_irqrestore(&dsi_mdp_lock, flag);
-}
-
/*
* mipi_dsi_cmds_tx:
* thread context only
@@ -1209,7 +1158,7 @@
cm = cmds;
mipi_dsi_buf_init(tp);
for (i = 0; i < cnt; i++) {
- mipi_dsi_enable_irq();
+ mipi_dsi_enable_irq(DSI_CMD_TERM);
mipi_dsi_buf_init(tp);
mipi_dsi_cmd_dma_add(tp, cm);
mipi_dsi_cmd_dma_tx(tp);
@@ -1300,20 +1249,20 @@
/* packet size need to be set at every read */
pkt_size = len;
max_pktsize[0] = pkt_size;
- mipi_dsi_enable_irq();
+ mipi_dsi_enable_irq(DSI_CMD_TERM);
mipi_dsi_buf_init(tp);
mipi_dsi_cmd_dma_add(tp, pkt_size_cmd);
mipi_dsi_cmd_dma_tx(tp);
}
- mipi_dsi_enable_irq();
+ mipi_dsi_enable_irq(DSI_CMD_TERM);
mipi_dsi_buf_init(tp);
mipi_dsi_cmd_dma_add(tp, cmds);
/* transmit read comamnd to client */
mipi_dsi_cmd_dma_tx(tp);
- mipi_dsi_disable_irq();
+ mipi_dsi_disable_irq(DSI_CMD_TERM);
/*
* once cmd_dma_done interrupt received,
* return data from client is ready and stored
@@ -1372,6 +1321,126 @@
return rp->len;
}
+int mipi_dsi_cmds_rx_new(struct dsi_buf *tp, struct dsi_buf *rp,
+ struct dcs_cmd_req *req, int rlen)
+{
+ struct dsi_cmd_desc *cmds;
+ int cnt, len, diff, pkt_size;
+ char cmd;
+ unsigned long flag;
+
+ if (req->flags & CMD_REQ_NO_MAX_PKT_SIZE) {
+ /* Only support rlen = 4*n */
+ rlen += 3;
+ rlen &= ~0x03;
+ }
+
+ cmds = req->cmds;
+
+ len = rlen;
+ diff = 0;
+
+ if (len <= 2)
+ cnt = 4; /* short read */
+ else {
+ if (len > MIPI_DSI_LEN)
+ len = MIPI_DSI_LEN; /* 8 bytes at most */
+
+ len = (len + 3) & ~0x03; /* len 4 bytes align */
+ diff = len - rlen;
+ /*
+ * add extra 2 bytes to len to have overall
+ * packet size is multipe by 4. This also make
+ * sure 4 bytes dcs headerlocates within a
+ * 32 bits register after shift in.
+ * after all, len should be either 6 or 10.
+ */
+ len += 2;
+ cnt = len + 6; /* 4 bytes header + 2 bytes crc */
+ }
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ dsi_mdp_busy = TRUE;
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+ if (!(req->flags & CMD_REQ_NO_MAX_PKT_SIZE)) {
+
+
+ /* packet size need to be set at every read */
+ pkt_size = len;
+ max_pktsize[0] = pkt_size;
+ mipi_dsi_enable_irq(DSI_CMD_TERM);
+ mipi_dsi_buf_init(tp);
+ mipi_dsi_cmd_dma_add(tp, pkt_size_cmd);
+ mipi_dsi_cmd_dma_tx(tp);
+ }
+
+ mipi_dsi_enable_irq(DSI_CMD_TERM);
+ mipi_dsi_buf_init(tp);
+ mipi_dsi_cmd_dma_add(tp, cmds);
+
+ /* transmit read comamnd to client */
+ mipi_dsi_cmd_dma_tx(tp);
+
+ mipi_dsi_disable_irq(DSI_CMD_TERM);
+ /*
+ * once cmd_dma_done interrupt received,
+ * return data from client is ready and stored
+ * at RDBK_DATA register already
+ */
+ mipi_dsi_buf_init(rp);
+ if (req->flags & CMD_REQ_NO_MAX_PKT_SIZE) {
+ /*
+ * expect rlen = n * 4
+ * short alignement for start addr
+ */
+ rp->data += 2;
+ }
+
+ mipi_dsi_cmd_dma_rx(rp, cnt);
+
+ spin_lock_irqsave(&dsi_mdp_lock, flag);
+ dsi_mdp_busy = FALSE;
+ complete(&dsi_mdp_comp);
+ spin_unlock_irqrestore(&dsi_mdp_lock, flag);
+
+ if (req->flags & CMD_REQ_NO_MAX_PKT_SIZE) {
+ /*
+ * remove extra 2 bytes from previous
+ * rx transaction at shift register
+ * which was inserted during copy
+ * shift registers to rx buffer
+ * rx payload start from long alignment addr
+ */
+ rp->data += 2;
+ }
+
+ cmd = rp->data[0];
+ switch (cmd) {
+ case DTYPE_ACK_ERR_RESP:
+ pr_debug("%s: rx ACK_ERR_PACLAGE\n", __func__);
+ break;
+ case DTYPE_GEN_READ1_RESP:
+ case DTYPE_DCS_READ1_RESP:
+ mipi_dsi_short_read1_resp(rp);
+ break;
+ case DTYPE_GEN_READ2_RESP:
+ case DTYPE_DCS_READ2_RESP:
+ mipi_dsi_short_read2_resp(rp);
+ break;
+ case DTYPE_GEN_LREAD_RESP:
+ case DTYPE_DCS_LREAD_RESP:
+ mipi_dsi_long_read_resp(rp);
+ rp->len -= 2; /* extra 2 bytes added */
+ rp->len -= diff; /* align bytes */
+ break;
+ default:
+ break;
+ }
+
+ return rp->len;
+}
+
int mipi_dsi_cmd_dma_tx(struct dsi_buf *tp)
{
@@ -1390,6 +1459,11 @@
pr_debug("\n");
#endif
+ if (tp->len == 0) {
+ pr_err("%s: Error, len=0\n", __func__);
+ return 0;
+ }
+
spin_lock_irqsave(&dsi_mdp_lock, flags);
tp->len += 3;
tp->len &= ~0x03; /* multipled by 4 */
@@ -1441,6 +1515,134 @@
return rlen;
}
+void mipi_dsi_cmd_mdp_busy(void)
+{
+ u32 status;
+ unsigned long flags;
+ int need_wait;
+
+ spin_lock_irqsave(&dsi_mdp_lock, flags);
+ status = MIPI_INP(MIPI_DSI_BASE + 0x0004);/* DSI_STATUS */
+ if (status & 0x04) { /* MDP BUSY */
+ INIT_COMPLETION(dsi_mdp_comp);
+ need_wait = 1;
+ pr_debug("%s: status=%x need_wait\n", __func__, (int)status);
+ mipi_dsi_enable_irq(DSI_MDP_TERM);
+ }
+ spin_unlock_irqrestore(&dsi_mdp_lock, flags);
+
+ if (need_wait)
+ wait_for_completion(&dsi_mdp_comp);
+}
+
+/*
+ * mipi_dsi_cmd_get: cmd_mutex acquired by caller
+ */
+struct dcs_cmd_req *mipi_dsi_cmdlist_get(void)
+{
+ struct dcs_cmd_req *req = NULL;
+
+ if (cmdlist.get != cmdlist.put) {
+ req = &cmdlist.list[cmdlist.get];
+ cmdlist.get++;
+ cmdlist.get %= CMD_REQ_MAX;
+ cmdlist.tot--;
+ pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
+ cmdlist.tot, cmdlist.put, cmdlist.get);
+ }
+ return req;
+}
+void mipi_dsi_cmdlist_tx(struct dcs_cmd_req *req)
+{
+ struct dsi_buf *tp;
+ int ret;
+
+ mipi_dsi_buf_init(&dsi_tx_buf);
+ tp = &dsi_tx_buf;
+ ret = mipi_dsi_cmds_tx(tp, req->cmds, req->cmds_cnt);
+
+ if (req->cb)
+ req->cb(ret);
+
+}
+
+void mipi_dsi_cmdlist_rx(struct dcs_cmd_req *req)
+{
+ int len;
+ u32 *dp;
+ struct dsi_buf *tp;
+ struct dsi_buf *rp;
+
+ mipi_dsi_buf_init(&dsi_tx_buf);
+ mipi_dsi_buf_init(&dsi_rx_buf);
+
+ tp = &dsi_tx_buf;
+ rp = &dsi_rx_buf;
+
+ len = mipi_dsi_cmds_rx_new(tp, rp, req, req->rlen);
+ dp = (u32 *)rp->data;
+
+ if (req->cb)
+ req->cb(*dp);
+}
+
+void mipi_dsi_cmdlist_commit(int from_mdp)
+{
+ struct dcs_cmd_req *req;
+
+ mutex_lock(&cmd_mutex);
+ req = mipi_dsi_cmdlist_get();
+ if (req == NULL) {
+ mutex_unlock(&cmd_mutex);
+ return;
+ }
+
+ pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);
+
+ if (!from_mdp) { /* from put */
+ /* make sure dsi_cmd_mdp is idle */
+ mipi_dsi_cmd_mdp_busy();
+ }
+
+ if (req->flags && CMD_REQ_RX)
+ mipi_dsi_cmdlist_rx(req);
+ else
+ mipi_dsi_cmdlist_tx(req);
+
+ mutex_unlock(&cmd_mutex);
+}
+
+int mipi_dsi_cmdlist_put(struct dcs_cmd_req *cmdreq)
+{
+ struct dcs_cmd_req *req;
+ int ret = 0;
+
+ mutex_lock(&cmd_mutex);
+ req = &cmdlist.list[cmdlist.put];
+ *req = *cmdreq;
+ cmdlist.put++;
+ cmdlist.put %= CMD_REQ_MAX;
+ cmdlist.tot++;
+ if (cmdlist.put == cmdlist.get) {
+ /* drop the oldest one */
+ pr_debug("%s: DROP, tot=%d put=%d get=%d\n", __func__,
+ cmdlist.tot, cmdlist.put, cmdlist.get);
+ cmdlist.get++;
+ cmdlist.get %= CMD_REQ_MAX;
+ cmdlist.tot--;
+ }
+ mutex_unlock(&cmd_mutex);
+
+ ret++;
+ pr_debug("%s: tot=%d put=%d get=%d\n", __func__,
+ cmdlist.tot, cmdlist.put, cmdlist.get);
+
+ if (req->flags & CMD_REQ_COMMIT)
+ mipi_dsi_cmdlist_commit(0);
+
+ return ret;
+}
+
void mipi_dsi_irq_set(uint32 mask, uint32 irq)
{
uint32 data;
@@ -1529,6 +1731,8 @@
isr = MIPI_INP(MIPI_DSI_BASE + 0x010c);/* DSI_INTR_CTRL */
MIPI_OUTP(MIPI_DSI_BASE + 0x010c, isr);
+ pr_debug("%s: isr=%x\n", __func__, (int)isr);
+
#ifdef CONFIG_FB_MSM_MDP40
mdp4_stat.intr_dsi++;
#endif
@@ -1548,7 +1752,7 @@
spin_lock(&dsi_mdp_lock);
complete(&dsi_dma_comp);
dsi_ctrl_lock = FALSE;
- mipi_dsi_disable_irq_nosync();
+ mipi_dsi_disable_irq_nosync(DSI_CMD_TERM);
spin_unlock(&dsi_mdp_lock);
}
@@ -1556,7 +1760,7 @@
mipi_dsi_mdp_stat_inc(STAT_DSI_MDP);
spin_lock(&dsi_mdp_lock);
dsi_ctrl_lock = FALSE;
- mipi_dsi_disable_irq_nosync();
+ mipi_dsi_disable_irq_nosync(DSI_MDP_TERM);
dsi_mdp_busy = FALSE;
complete(&dsi_mdp_comp);
spin_unlock(&dsi_mdp_lock);
diff --git a/drivers/video/msm/mipi_novatek.c b/drivers/video/msm/mipi_novatek.c
index 7dd41d2..b893cc7 100644
--- a/drivers/video/msm/mipi_novatek.c
+++ b/drivers/video/msm/mipi_novatek.c
@@ -393,18 +393,16 @@
mipi = &mfd->panel_info.mipi;
- if (mipi_dsi_ctrl_lock(0)) {
- if (mipi->mode == DSI_VIDEO_MODE) {
- mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_video_on_cmds,
+ if (mipi->mode == DSI_VIDEO_MODE) {
+ mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_video_on_cmds,
ARRAY_SIZE(novatek_video_on_cmds));
- } else {
- mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_cmd_on_cmds,
+ } else {
+ mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_cmd_on_cmds,
ARRAY_SIZE(novatek_cmd_on_cmds));
- /* clean up ack_err_status */
- mipi_dsi_cmd_bta_sw_trigger();
- mipi_novatek_manufacture_id(mfd);
- }
+ /* clean up ack_err_status */
+ mipi_dsi_cmd_bta_sw_trigger();
+ mipi_novatek_manufacture_id(mfd);
}
return 0;
@@ -421,35 +419,38 @@
if (mfd->key != MFD_KEY)
return -EINVAL;
- if (mipi_dsi_ctrl_lock(0)) {
- mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_display_off_cmds,
+ mipi_dsi_cmds_tx(&novatek_tx_buf, novatek_display_off_cmds,
ARRAY_SIZE(novatek_display_off_cmds));
- }
return 0;
}
DEFINE_LED_TRIGGER(bkl_led_trigger);
-#ifdef CONFIG_FB_MSM_MDP303
-void mdp4_backlight_put_level(int cndx, int level)
-{
- /* do nothing */
-}
-#endif
+static char led_pwm1[2] = {0x51, 0x0}; /* DTYPE_DCS_WRITE1 */
+static struct dsi_cmd_desc backlight_cmd = {
+ DTYPE_DCS_LWRITE, 1, 0, 0, 1, sizeof(led_pwm1), led_pwm1};
+
+struct dcs_cmd_req cmdreq;
static void mipi_novatek_set_backlight(struct msm_fb_data_type *mfd)
{
- struct mipi_panel_info *mipi;
if ((mipi_novatek_pdata->enable_wled_bl_ctrl)
&& (wled_trigger_initialized)) {
led_trigger_event(bkl_led_trigger, mfd->bl_level);
return;
}
- mipi = &mfd->panel_info.mipi;
- mdp4_backlight_put_level(0, mfd->bl_level);
+ led_pwm1[1] = (unsigned char)mfd->bl_level;
+
+ cmdreq.cmds = &backlight_cmd;
+ cmdreq.cmds_cnt = 1;
+ cmdreq.flags = 0;
+ cmdreq.rlen = 0;
+ cmdreq.cb = NULL;
+
+ mipi_dsi_cmdlist_put(&cmdreq);
}
static int mipi_dsi_3d_barrier_sysfs_register(struct device *dev);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
index 0c6aa86..84f148f 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
@@ -171,6 +171,7 @@
u32 sz_desc;
u32 sz_cpb;
u32 sz_context;
+ u32 sz_extnuserdata;
};
struct ddl_dec_buffers{
struct ddl_buf_addr desc;
@@ -186,6 +187,7 @@
struct ddl_buf_addr h264_vert_nb_mv;
struct ddl_buf_addr h264_nb_ip;
struct ddl_buf_addr context;
+ struct ddl_buf_addr extnuserdata;
};
struct ddl_enc_buffer_size{
u32 sz_cur_y;
@@ -228,7 +230,17 @@
[DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH];
u32 num_output_frames;
u32 out_frm_next_frmindex;
- u32 first_output_frame_tag;
+};
+struct ddl_mp2_datadumpenabletype {
+ u32 userdatadump_enable;
+ u32 pictempscalable_extdump_enable;
+ u32 picspat_extdump_enable;
+ u32 picdisp_extdump_enable;
+ u32 copyright_extdump_enable;
+ u32 quantmatrix_extdump_enable;
+ u32 seqscalable_extdump_enable;
+ u32 seqdisp_extdump_enable;
+ u32 seq_extdump_enable;
};
struct ddl_encoder_data{
struct ddl_codec_data_hdr hdr;
@@ -323,6 +335,9 @@
u32 dmx_disable;
int avg_dec_time;
int dec_time_sum;
+ struct ddl_mp2_datadumpenabletype mp2_datadump_enable;
+ u32 mp2_datadump_status;
+ u32 extn_user_data_enable;
};
union ddl_codec_data{
struct ddl_codec_data_hdr hdr;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
index 949e5c0..95be1b6 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -533,6 +533,7 @@
ddl_pmem_free(&dec_bufs->stx_parser);
ddl_pmem_free(&dec_bufs->desc);
ddl_pmem_free(&dec_bufs->context);
+ ddl_pmem_free(&dec_bufs->extnuserdata);
memset(dec_bufs, 0, sizeof(struct ddl_dec_buffers));
}
@@ -601,6 +602,7 @@
u32 sz_sub_anchor_mv = 0, sz_overlap_xform = 0, sz_bit_plane3 = 0;
u32 sz_bit_plane2 = 0, sz_bit_plane1 = 0, sz_stx_parser = 0;
u32 sz_desc, sz_cpb, sz_context, sz_vert_nb_mv = 0, sz_nb_ip = 0;
+ u32 sz_extnuserdata = 0;
if (codec == VCD_CODEC_H264) {
sz_mv = ddl_get_yuv_buf_size(width,
@@ -630,7 +632,8 @@
sz_bit_plane3 = DDL_KILO_BYTE(2);
sz_bit_plane2 = DDL_KILO_BYTE(2);
sz_bit_plane1 = DDL_KILO_BYTE(2);
- }
+ } else if (codec == VCD_CODEC_MPEG2)
+ sz_extnuserdata = DDL_KILO_BYTE(2);
}
sz_desc = DDL_KILO_BYTE(128);
sz_cpb = VCD_DEC_CPB_SIZE;
@@ -657,6 +660,7 @@
buf_size->sz_desc = sz_desc;
buf_size->sz_cpb = sz_cpb;
buf_size->sz_context = sz_context;
+ buf_size->sz_extnuserdata = sz_extnuserdata;
}
}
@@ -774,6 +778,16 @@
}
}
}
+ if (buf_size.sz_extnuserdata > 0) {
+ dec_bufs->extnuserdata.mem_type = DDL_FW_MEM;
+ ptr = ddl_pmem_alloc(&dec_bufs->extnuserdata,
+ buf_size.sz_extnuserdata, DDL_KILO_BYTE(2));
+ if (!ptr)
+ goto fail_free_exit;
+ else
+ memset(dec_bufs->extnuserdata.align_virtual_addr,
+ 0, buf_size.sz_extnuserdata);
+ }
return status;
fail_free_exit:
status = VCD_ERR_ALLOC_FAIL;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index 8ec444f..c3d20cf 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -256,6 +256,10 @@
DDL_MSG_LOW("HEADER_DONE");
vidc_1080p_get_decode_seq_start_result(&seq_hdr_info);
parse_hdr_size_data(ddl, &seq_hdr_info);
+ decoder->mp2_datadump_status = 0;
+ vidc_sm_get_mp2datadump_status(&ddl->shared_mem
+ [ddl->command_channel],
+ &decoder->mp2_datadump_status);
if (res_trk_get_disable_fullhd() &&
(seq_hdr_info.img_size_x * seq_hdr_info.img_size_y >
1280 * 720)) {
@@ -1205,6 +1209,10 @@
vidc_sm_get_metadata_status(&ddl->shared_mem
[ddl->command_channel],
&decoder->meta_data_exists);
+ decoder->mp2_datadump_status = 0;
+ vidc_sm_get_mp2datadump_status(&ddl->shared_mem
+ [ddl->command_channel],
+ &decoder->mp2_datadump_status);
if (decoder->output_order == VCD_DEC_ORDER_DISPLAY) {
vidc_sm_get_frame_tags(&ddl->shared_mem
[ddl->command_channel],
@@ -1793,27 +1801,11 @@
vidc_sm_get_frame_tags(&ddl->shared_mem
[ddl->command_channel],
&output_frame->ip_frm_tag, &bottom_frame_tag);
-
- if (start_bfr_idx == 0) {
- encoder->batch_frame.first_output_frame_tag =
- output_frame->ip_frm_tag;
- DDL_MSG_LOW("%s: first_output_frame_tag[0x%x]",
- __func__, output_frame->ip_frm_tag);
- if (!output_frame->ip_frm_tag) {
- DDL_MSG_ERROR("%s: first_output_frame_tag "\
- "is zero", __func__);
- }
+ if (!output_frame->ip_frm_tag) {
+ DDL_MSG_ERROR("%s: zero frame tag rcvd, index = %d",
+ __func__, index);
+ output_frame->ip_frm_tag = (u32)ddl->client_data;
}
- if (output_frame->ip_frm_tag !=
- encoder->batch_frame.first_output_frame_tag) {
- DDL_MSG_ERROR("%s: output_frame->ip_frm_tag[0x%x] is "\
- "not equal to the first_output_frame_tag[0x%x]\n",
- __func__, output_frame->ip_frm_tag,
- encoder->batch_frame.first_output_frame_tag);
- output_frame->ip_frm_tag =
- encoder->batch_frame.first_output_frame_tag;
- }
-
ddl_get_encoded_frame(output_frame,
encoder->codec.codec,
encoder->enc_frame_info.enc_frame);
@@ -1896,27 +1888,11 @@
vidc_sm_get_frame_tags(&ddl->shared_mem
[ddl->command_channel],
&output_frame->ip_frm_tag, &bottom_frame_tag);
-
- if (start_bfr_idx == 0) {
- encoder->batch_frame.first_output_frame_tag =
- output_frame->ip_frm_tag;
- DDL_MSG_LOW("%s: first_output_frame_tag[0x%x]",
- __func__, output_frame->ip_frm_tag);
- if (!output_frame->ip_frm_tag) {
- DDL_MSG_ERROR("%s: first_output_frame_tag "\
- "is zero", __func__);
- }
+ if (!output_frame->ip_frm_tag) {
+ DDL_MSG_ERROR("%s: zero frame tag rcvd, index = %d",
+ __func__, index);
+ output_frame->ip_frm_tag = (u32)ddl->client_data;
}
- if (output_frame->ip_frm_tag !=
- encoder->batch_frame.first_output_frame_tag) {
- DDL_MSG_ERROR("%s: output_frame->ip_frm_tag[0x%x] is "\
- "not equal to the first_output_frame_tag[0x%x]\n",
- __func__, output_frame->ip_frm_tag,
- encoder->batch_frame.first_output_frame_tag);
- output_frame->ip_frm_tag =
- encoder->batch_frame.first_output_frame_tag;
- }
-
ddl_get_encoded_frame(output_frame,
encoder->codec.codec,
encoder->enc_frame_info.enc_frame);
@@ -1987,8 +1963,9 @@
&output_frame->ip_frm_tag,
&bottom_frame_tag);
if (!output_frame->ip_frm_tag) {
- DDL_MSG_ERROR("%s: output frame tag is zero",
- __func__);
+ DDL_MSG_ERROR("%s: zero frame tag rcvd, index = %d",
+ __func__, index);
+ output_frame->ip_frm_tag = (u32)ddl->client_data;
}
ddl_get_encoded_frame(
output_frame,
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
index fade821..f70c47c 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
@@ -52,6 +52,12 @@
case VCD_METADATA_QCOMFILLER:
skip_words = 21;
break;
+ case VCD_METADATA_USER_DATA:
+ skip_words = 27;
+ break;
+ case VCD_METADATA_EXT_DATA:
+ skip_words = 30;
+ break;
}
} else {
buffer = (u32 *) ddl->codec_data.encoder.meta_data_input.
@@ -123,6 +129,18 @@
hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] =
VCD_METADATA_PASSTHROUGH;
+ hdr_entry = ddl_metadata_hdr_entry(ddl,
+ VCD_METADATA_USER_DATA);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] =
+ VCD_METADATA_USER_DATA;
+ hdr_entry = ddl_metadata_hdr_entry(ddl,
+ VCD_METADATA_EXT_DATA);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] =
+ VCD_METADATA_EXT_DATA;
} else {
hdr_entry = ddl_metadata_hdr_entry(ddl, VCD_METADATA_ENC_SLICE);
hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
@@ -146,6 +164,9 @@
else if (codec == VCD_CODEC_VC1 ||
codec == VCD_CODEC_VC1_RCV)
flag |= VCD_METADATA_VC1;
+ else if (codec == VCD_CODEC_MPEG2)
+ flag |= (VCD_METADATA_USER_DATA |
+ VCD_METADATA_EXT_DATA);
} else
flag |= VCD_METADATA_ENC_SLICE;
return flag;
@@ -165,7 +186,6 @@
{
u32 flag = decoder->meta_data_enable_flag;
u32 suffix = 0, size = 0;
-
if (!flag) {
decoder->suffix = 0;
return;
@@ -210,6 +230,18 @@
DDL_METADATA_ALIGNSIZE(size);
suffix += (size);
}
+ if (flag & VCD_METADATA_USER_DATA) {
+ size = DDL_METADATA_HDR_SIZE;
+ size += DDL_METADATA_USER_PAYLOAD_SIZE;
+ DDL_METADATA_ALIGNSIZE(size);
+ suffix += (size);
+ }
+ if (flag & VCD_METADATA_EXT_DATA) {
+ size = DDL_METADATA_HDR_SIZE;
+ size += DDL_METADATA_EXT_PAYLOAD_SIZE;
+ DDL_METADATA_ALIGNSIZE(size);
+ suffix += (size);
+ }
size = DDL_METADATA_EXTRADATANONE_SIZE;
DDL_METADATA_ALIGNSIZE(size);
suffix += (size);
@@ -278,6 +310,10 @@
if (flag)
flag |= DDL_METADATA_MANDATORY;
if (*meta_data_enable_flag != flag) {
+ if (VCD_CODEC_MPEG2 == codec)
+ ddl_set_mp2_dump_default(
+ &ddl->codec_data.decoder,
+ flag);
*meta_data_enable_flag = flag;
if (ddl->decoding)
ddl_set_default_decoder_buffer_req(
@@ -357,6 +393,7 @@
u32 qp_enable = false, concealed_mb_enable = false;
u32 vc1_param_enable = false, sei_nal_enable = false;
u32 vui_enable = false, enc_slice_size_enable = false;
+ u32 mp2_data_dump_enable = false;
if (ddl->decoding)
flag = ddl->codec_data.decoder.meta_data_enable_flag;
@@ -380,10 +417,22 @@
}
DDL_MSG_LOW("metadata enable flag : %d", sei_nal_enable);
+ if (flag & VCD_METADATA_EXT_DATA || flag & VCD_METADATA_USER_DATA) {
+ mp2_data_dump_enable = true;
+ ddl->codec_data.decoder.extn_user_data_enable =
+ mp2_data_dump_enable;
+ vidc_sm_set_mp2datadump_enable(&ddl->shared_mem
+ [ddl->command_channel],
+ &ddl->codec_data.decoder.mp2_datadump_enable);
+ } else {
+ mp2_data_dump_enable = false;
+ ddl->codec_data.decoder.extn_user_data_enable =
+ mp2_data_dump_enable;
+ }
vidc_sm_set_metadata_enable(&ddl->shared_mem
[ddl->command_channel], extradata_enable, qp_enable,
concealed_mb_enable, vc1_param_enable, sei_nal_enable,
- vui_enable, enc_slice_size_enable);
+ vui_enable, enc_slice_size_enable, mp2_data_dump_enable);
}
u32 ddl_vidc_encode_set_metadata_output_buf(struct ddl_client_context *ddl)
@@ -487,6 +536,11 @@
output_frame->flags &= ~(VCD_FRAME_FLAG_EXTRADATA);
return;
}
+ if (!decoder->mp2_datadump_status && decoder->codec.codec ==
+ VCD_CODEC_MPEG2 && !decoder->extn_user_data_enable) {
+ output_frame->flags &= ~(VCD_FRAME_FLAG_EXTRADATA);
+ return;
+ }
DDL_MSG_LOW("processing metadata for decoder");
DDL_MSG_LOW("data_len/metadata_offset : %d/%d",
output_frame->data_len, decoder->meta_data_offset);
@@ -507,3 +561,27 @@
*qfiller = (u32)(qfiller_size - DDL_METADATA_HDR_SIZE);
}
}
+
+void ddl_set_mp2_dump_default(struct ddl_decoder_data *decoder, u32 flag)
+{
+
+ if (flag & VCD_METADATA_EXT_DATA) {
+ decoder->mp2_datadump_enable.pictempscalable_extdump_enable =
+ true;
+ decoder->mp2_datadump_enable.picspat_extdump_enable = true;
+ decoder->mp2_datadump_enable.picdisp_extdump_enable = true;
+ decoder->mp2_datadump_enable.copyright_extdump_enable = true;
+ decoder->mp2_datadump_enable.quantmatrix_extdump_enable =
+ true;
+ decoder->mp2_datadump_enable.seqscalable_extdump_enable =
+ true;
+ decoder->mp2_datadump_enable.seqdisp_extdump_enable = true;
+ decoder->mp2_datadump_enable.seq_extdump_enable = true;
+ }
+ if (flag & VCD_METADATA_USER_DATA)
+ decoder->mp2_datadump_enable.userdatadump_enable =
+ DDL_METADATA_USER_DUMP_FULL_MODE;
+ else
+ decoder->mp2_datadump_enable.userdatadump_enable =
+ DDL_METADATA_USER_DUMP_DISABLE_MODE;
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h
index c63b6a9..e03a9b7 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h
@@ -14,7 +14,7 @@
#ifndef _VCD_DDL_METADATA_H_
#define _VCD_DDL_METADATA_H_
-#define DDL_MAX_DEC_METADATATYPE 8
+#define DDL_MAX_DEC_METADATATYPE 10
#define DDL_MAX_ENC_METADATATYPE 3
#define DDL_METADATA_EXTRAPAD_SIZE 256
#define DDL_METADATA_HDR_SIZE 20
@@ -27,6 +27,8 @@
#define DDL_METADATA_SEI_MAX 5
#define DDL_METADATA_VUI_PAYLOAD_SIZE 256
#define DDL_METADATA_PASSTHROUGH_PAYLOAD_SIZE 68
+#define DDL_METADATA_EXT_PAYLOAD_SIZE (640)
+#define DDL_METADATA_USER_PAYLOAD_SIZE (2048)
#define DDL_METADATA_CLIENT_INPUTBUFSIZE 256
#define DDL_METADATA_TOTAL_INPUTBUFSIZE \
(DDL_METADATA_CLIENT_INPUTBUFSIZE * VCD_MAX_NO_CLIENT)
@@ -46,6 +48,10 @@
#define DDL_METADATA_HDR_PORT_INDEX 1
#define DDL_METADATA_HDR_TYPE_INDEX 2
+#define DDL_METADATA_USER_DUMP_DISABLE_MODE 0
+#define DDL_METADATA_USER_DUMP_OFFSET_MODE 1
+#define DDL_METADATA_USER_DUMP_FULL_MODE 2
+
void ddl_set_default_meta_data_hdr(struct ddl_client_context *ddl);
u32 ddl_get_metadata_params(struct ddl_client_context *ddl,
struct vcd_property_hdr *property_hdr, void *property_value);
@@ -62,5 +68,6 @@
void ddl_vidc_decode_set_metadata_output(struct ddl_decoder_data *decoder);
void ddl_process_encoder_metadata(struct ddl_client_context *ddl);
void ddl_process_decoder_metadata(struct ddl_client_context *ddl);
+void ddl_set_mp2_dump_default(struct ddl_decoder_data *decoder, u32 flag);
#endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
index d83cde8..416b497 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
@@ -187,6 +187,8 @@
#define VIDC_SM_METADATA_ENABLE_ADDR 0x0038
+#define VIDC_SM_METADATA_ENABLE_MP2_DATADUMP_BMSK 0x00000200
+#define VIDC_SM_METADATA_ENABLE_MP2_DATADUMP_SHFT 9
#define VIDC_SM_METADATA_ENABLE_EXTRADATA_BMSK 0x40
#define VIDC_SM_METADATA_ENABLE_EXTRADATA_SHFT 6
#define VIDC_SM_METADATA_ENABLE_ENC_SLICE_SIZE_BMSK 0x20
@@ -251,6 +253,51 @@
#define VIDC_SM_TIMEOUT_VALUE_BMSK 0xffffffff
#define VIDC_SM_TIMEOUT_VALUE_SHFT 0
+#define VIDC_SM_MP2_DATA_DUMP_CONTROL_ADDR 0x0194
+#define VIDC_SM_MP2_USERDATA_DUMP_ENABLE_BMSK 0x00000300
+#define VIDC_SM_MP2_USERDATA_DUMP_ENABLE_SHFT 8
+#define VIDC_SM_MP2_PICT_TEMP_DUMP_ENABLE_BMSK 0x00000080
+#define VIDC_SM_MP2_PICT_TEMP_DUMP_ENABLE_SHFT 7
+#define VIDC_SM_MP2_PICT_SPAT_EXT_DUMP_ENABLE_BMSK 0x00000040
+#define VIDC_SM_MP2_PICT_SPAT_EXT_DUMP_ENABLE_SHFT 6
+#define VIDC_SM_MP2_PICT_DISP_EXT_DUMP_ENABLE_BMSK 0x00000020
+#define VIDC_SM_MP2_PICT_DISP_EXT_DUMP_ENABLE_SHFT 5
+#define VIDC_SM_MP2_COPYRIGHT_EXT_DUMP_ENABLE_BMSK 0x00000010
+#define VIDC_SM_MP2_COPYRIGHT_EXT_DUMP_ENABLE_SHFT 4
+#define VIDC_SM_MP2_QMATRIX_EXT_DUMP_ENABLE_BMSK 0x00000008
+#define VIDC_SM_MP2_QMATRIX_EXT_DUMP_ENABLE_SHFT 3
+#define VIDC_SM_MP2_SCAL_EXT_DUMP_ENABLE_BMSK 0x00000004
+#define VIDC_SM_MP2_SCAL_EXT_DUMP_ENABLE_SHFT 2
+#define VIDC_SM_MP2_SEQ_DISP_EXT_DUMP_ENABLE_BMSK 0x00000002
+#define VIDC_SM_MP2_SEQ_DISP_EXT_DUMP_ENABLE_SHFT 1
+#define VIDC_SM_MP2_SEQ_EXT_DUMP_ENABLE_BMSK 0x00000001
+#define VIDC_SM_MP2_SEQ_EXT_DUMP_ENABLE_SHFT 0
+
+#define VIDC_SM_MP2_DATA_DUMP_STATUS_ADDR 0x0198
+#define VIDC_SM_MP2_USERDATA_DUMP_STATUS_BMSK 0x00000300
+#define VIDC_SM_MP2_USERDATA_DUMP_STATUS_SHFT 8
+#define VIDC_SM_MP2_PICT_TEMP_DUMP_STATUS_BMSK 0x00000080
+#define VIDC_SM_MP2_PICT_TEMP_DUMP_STATUS_SHFT 7
+#define VIDC_SM_MP2_PICT_SPAT_EXT_DUMP_STATUS_BMSK 0x00000040
+#define VIDC_SM_MP2_PICT_SPAT_EXT_DUMP_STATUS_SHFT 6
+#define VIDC_SM_MP2_PICT_DISP_EXT_DUMP_STATUS_BMSK 0x00000020
+#define VIDC_SM_MP2_PICT_DISP_EXT_DUMP_STATUS_SHFT 5
+#define VIDC_SM_MP2_COPYRIGHT_EXT_DUMP_STATUS_BMSK 0x00000010
+#define VIDC_SM_MP2_COPYRIGHT_EXT_DUMP_STATUS_SHFT 4
+#define VIDC_SM_MP2_QMATRIX_EXT_DUMP_STATUS_BMSK 0x00000008
+#define VIDC_SM_MP2_QMATRIX_EXT_DUMP_STATUS_SHFT 3
+#define VIDC_SM_MP2_SCAL_EXT_DUMP_STATUS_BMSK 0x00000004
+#define VIDC_SM_MP2_SCAL_EXT_DUMP_STATUS_SHFT 2
+#define VIDC_SM_MP2_SEQ_DISP_EXT_DUMP_STATUS_BMSK 0x00000002
+#define VIDC_SM_MP2_SEQ_DISP_EXT_DUMP_STATUS_SHFT 1
+#define VIDC_SM_MP2_SEQ_EXT_DUMP_STATUS_BMSK 0x00000001
+#define VIDC_SM_MP2_SEQ_EXT_DUMP_STATUS_SHFT 0
+
+#define VIDC_SM_MP2_DATA_DUMP_BUFFER_ADDR 0x01a4
+#define VIDC_SM_MP2_DATA_DUMP_BUFFER_SIZE_ADDR 0x01a8
+
+
+
#define VIDC_SM_ENC_EXT_CTRL_CLOSED_GOP_ENABLE_BMSK 0x40
#define VIDC_SM_ENC_EXT_CTRL_CLOSED_GOP_ENABLE_SHFT 6
@@ -579,11 +626,14 @@
void vidc_sm_set_metadata_enable(struct ddl_buf_addr *shared_mem,
u32 extradata_enable, u32 qp_enable, u32 concealed_mb_enable,
u32 vc1Param_enable, u32 sei_nal_enable, u32 vui_enable,
- u32 enc_slice_size_enable)
+ u32 enc_slice_size_enable, u32 mp2_data_dump_enable)
{
u32 metadata_enable;
- metadata_enable = VIDC_SETFIELD((extradata_enable) ? 1 : 0,
+ metadata_enable = VIDC_SETFIELD((mp2_data_dump_enable) ? 1 : 0,
+ VIDC_SM_METADATA_ENABLE_MP2_DATADUMP_SHFT,
+ VIDC_SM_METADATA_ENABLE_MP2_DATADUMP_BMSK) |
+ VIDC_SETFIELD((extradata_enable) ? 1 : 0,
VIDC_SM_METADATA_ENABLE_EXTRADATA_SHFT,
VIDC_SM_METADATA_ENABLE_EXTRADATA_BMSK) |
VIDC_SETFIELD((enc_slice_size_enable) ? 1 : 0,
@@ -1015,3 +1065,71 @@
timeout);
}
+void vidc_sm_set_mp2datadump_enable(struct ddl_buf_addr *shared_mem,
+ struct ddl_mp2_datadumpenabletype *ddl_mp2_datadump_enable)
+{
+ u32 mp2_datadump_enable = 0;
+
+ mp2_datadump_enable = VIDC_SETFIELD(
+ ddl_mp2_datadump_enable->userdatadump_enable,
+ VIDC_SM_MP2_USERDATA_DUMP_ENABLE_SHFT,
+ VIDC_SM_MP2_USERDATA_DUMP_ENABLE_BMSK) |
+ VIDC_SETFIELD(ddl_mp2_datadump_enable->
+ pictempscalable_extdump_enable ? 1 : 0,
+ VIDC_SM_MP2_PICT_TEMP_DUMP_ENABLE_SHFT,
+ VIDC_SM_MP2_PICT_TEMP_DUMP_ENABLE_BMSK) |
+ VIDC_SETFIELD(ddl_mp2_datadump_enable->
+ picspat_extdump_enable ? 1 : 0,
+ VIDC_SM_MP2_PICT_SPAT_EXT_DUMP_ENABLE_SHFT,
+ VIDC_SM_MP2_PICT_SPAT_EXT_DUMP_ENABLE_BMSK) |
+ VIDC_SETFIELD(ddl_mp2_datadump_enable->
+ picdisp_extdump_enable ? 1 : 0,
+ VIDC_SM_MP2_PICT_DISP_EXT_DUMP_ENABLE_SHFT,
+ VIDC_SM_MP2_PICT_DISP_EXT_DUMP_ENABLE_BMSK) |
+ VIDC_SETFIELD(ddl_mp2_datadump_enable->
+ copyright_extdump_enable ? 1 : 0,
+ VIDC_SM_MP2_COPYRIGHT_EXT_DUMP_ENABLE_SHFT,
+ VIDC_SM_MP2_COPYRIGHT_EXT_DUMP_ENABLE_BMSK) |
+ VIDC_SETFIELD(ddl_mp2_datadump_enable->
+ quantmatrix_extdump_enable ? 1 : 0,
+ VIDC_SM_MP2_QMATRIX_EXT_DUMP_ENABLE_SHFT,
+ VIDC_SM_MP2_QMATRIX_EXT_DUMP_ENABLE_BMSK) |
+ VIDC_SETFIELD(ddl_mp2_datadump_enable->
+ seqscalable_extdump_enable ? 1 : 0,
+ VIDC_SM_MP2_SCAL_EXT_DUMP_ENABLE_SHFT,
+ VIDC_SM_MP2_SCAL_EXT_DUMP_ENABLE_BMSK) |
+ VIDC_SETFIELD(ddl_mp2_datadump_enable->
+ seqdisp_extdump_enable ? 1 : 0,
+ VIDC_SM_MP2_SEQ_DISP_EXT_DUMP_ENABLE_SHFT,
+ VIDC_SM_MP2_SEQ_DISP_EXT_DUMP_ENABLE_BMSK) |
+ VIDC_SETFIELD(ddl_mp2_datadump_enable->
+ seq_extdump_enable ? 1 : 0,
+ VIDC_SM_MP2_SEQ_EXT_DUMP_ENABLE_SHFT,
+ VIDC_SM_MP2_SEQ_EXT_DUMP_ENABLE_BMSK);
+ DDL_MEM_WRITE_32(shared_mem, VIDC_SM_MP2_DATA_DUMP_CONTROL_ADDR,
+ mp2_datadump_enable);
+
+}
+
+void vidc_sm_get_mp2datadump_status(struct ddl_buf_addr
+ *shared_mem, u32 *ext_userdata_present)
+{
+ u32 status;
+
+ status = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_MP2_DATA_DUMP_STATUS_ADDR);
+ *ext_userdata_present = (u32) VIDC_GETFIELD(status,
+ VIDC_SM_MP2_USERDATA_DUMP_STATUS_BMSK,
+ VIDC_SM_MP2_USERDATA_DUMP_STATUS_SHFT);
+}
+
+void vidc_sm_set_mp2datadumpbuffer(struct ddl_buf_addr *shared_mem,
+ u32 mp2datadumpaddr, u32 mp2datadumpsize)
+{
+ DDL_MEM_WRITE_32(shared_mem,
+ VIDC_SM_MP2_DATA_DUMP_BUFFER_ADDR,
+ mp2datadumpaddr);
+ DDL_MEM_WRITE_32(shared_mem,
+ VIDC_SM_MP2_DATA_DUMP_BUFFER_SIZE_ADDR,
+ mp2datadumpsize);
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
index 1a46c36..9cb1933 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
@@ -139,7 +139,7 @@
void vidc_sm_set_metadata_enable(struct ddl_buf_addr *shared_mem,
u32 extradata_enable, u32 qp_enable, u32 concealed_mb_enable,
u32 vc1Param_enable, u32 sei_nal_enable, u32 vui_enable,
- u32 enc_slice_size_enable);
+ u32 enc_slice_size_enable, u32 mp2_data_dump_enable);
void vidc_sm_get_metadata_status(struct ddl_buf_addr *shared_mem,
u32 *pb_metadata_present);
void vidc_sm_get_metadata_display_index(struct ddl_buf_addr *shared_mem,
@@ -193,4 +193,11 @@
u32 *output_buffer_size);
void vidc_sm_set_video_core_timeout_value(struct ddl_buf_addr *shared_mem,
u32 timeout);
+void vidc_sm_get_mp2datadump_status(struct ddl_buf_addr
+ *shared_mem, u32 *ext_userdata_present);
+void vidc_sm_set_mp2datadump_enable(struct ddl_buf_addr *shared_mem,
+ struct ddl_mp2_datadumpenabletype *ddl_mp2_datadump_enable);
+void vidc_sm_set_mp2datadumpbuffer(struct ddl_buf_addr *shared_mem,
+ u32 mp2datadumpaddr, u32 mp2datadumpsize);
+
#endif
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 260cd72..90114f7 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
@@ -112,10 +112,10 @@
&iova,
&buffer_size,
UNCACHED, 0);
- if (ret) {
+ if (ret || !iova) {
DDL_MSG_ERROR(
- "%s():DDL ION ion map iommu failed\n",
- __func__);
+ "%s():DDL ION ion map iommu failed, ret = %d iova = 0x%lx\n",
+ __func__, ret, iova);
goto unmap_ion_alloc;
}
addr->alloced_phys_addr = (phys_addr_t) iova;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
index d1f6e07..4072b02 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
@@ -867,7 +867,6 @@
DDL_MEMSET(encoder->batch_frame.slice_batch_in.align_virtual_addr, 0,
sizeof(struct vidc_1080p_enc_slice_batch_in_param));
encoder->batch_frame.out_frm_next_frmindex = 0;
- encoder->batch_frame.first_output_frame_tag = 0;
bitstream_size = encoder->batch_frame.output_frame[0].vcd_frm.alloc_len;
encoder->output_buf_req.sz = bitstream_size;
y_addr = DDL_OFFSET(ddl_context->dram_base_b.align_physical_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 291de5f..972160a 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
@@ -85,9 +85,10 @@
&iova,
&buffer_size,
UNCACHED, 0);
- if (ret) {
- DDL_MSG_ERROR("%s():DDL ION client iommu map failed\n",
- __func__);
+ if (ret || !iova) {
+ DDL_MSG_ERROR(
+ "%s():DDL ION client iommu map failed, ret = %d iova = 0x%lx\n",
+ __func__, ret, iova);
goto ion_unmap_bail_out;
}
addr->mapped_buffer = NULL;
diff --git a/drivers/video/msm/vidc/common/dec/vdec.c b/drivers/video/msm/vidc/common/dec/vdec.c
index 927f19b..f68265a 100644
--- a/drivers/video/msm/vidc/common/dec/vdec.c
+++ b/drivers/video/msm/vidc/common/dec/vdec.c
@@ -936,9 +936,10 @@
SZ_4K, 0, (unsigned long *)&iova,
(unsigned long *)&buffer_size,
UNCACHED, 0);
- if (rc) {
- ERR("%s():get_ION_kernel physical addr fail\n",
- __func__);
+ if (rc || !iova) {
+ ERR(
+ "%s():get_ION_kernel physical addr fail, rc = %d iova = 0x%lx\n",
+ __func__, rc, iova);
goto ion_map_error;
}
vcd_h264_mv_buffer->physical_addr = (u8 *) iova;
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
index 50cccbb..5ee0a3d 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -1868,9 +1868,10 @@
(unsigned long *)&iova,
(unsigned long *)&buffer_size,
UNCACHED, 0);
- if (rc) {
- ERR("%s():ION map iommu addr fail\n",
- __func__);
+ if (rc || !iova) {
+ ERR(
+ "%s():ION map iommu addr fail, rc = %d, iova = 0x%lx\n",
+ __func__, rc, iova);
goto map_ion_error;
}
control->physical_addr = (u8 *) iova;
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index c884cf5..221c154 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -680,9 +680,10 @@
(unsigned long *) &buffer_size,
UNCACHED,
ION_IOMMU_UNMAP_DELAYED);
- if (ret) {
- ERR("%s():ION iommu map fail\n",
- __func__);
+ if (ret || !iova) {
+ ERR(
+ "%s():ION iommu map fail, ret = %d, iova = 0x%lx\n",
+ __func__, ret, iova);
goto ion_map_error;
}
phys_addr = iova;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index 28ea453..b97a58e 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -121,8 +121,10 @@
(unsigned long *)&iova,
(unsigned long *)&buffer_size,
UNCACHED, 0);
- if (ret) {
- pr_err("%s() ION iommu map failed", __func__);
+ if (ret || !iova) {
+ pr_err(
+ "%s() ION iommu map failed, ret = %d, iova = 0x%lx",
+ __func__, ret, iova);
goto ion_map_bailout;
}
map_buffer->phy_addr = iova;
diff --git a/include/linux/dvb/video.h b/include/linux/dvb/video.h
index 1d750c0..81475c2 100644
--- a/include/linux/dvb/video.h
+++ b/include/linux/dvb/video.h
@@ -57,6 +57,19 @@
VIDEO_CENTER_CUT_OUT /* use center cut out format */
} video_displayformat_t;
+enum video_codec_t {
+ VIDEO_CODECTYPE_NONE,
+ VIDEO_CODECTYPE_MPEG2,
+ VIDEO_CODECTYPE_MPEG4,
+ VIDEO_CODECTYPE_H264,
+ VIDEO_CODECTYPE_VC1
+};
+
+enum video_out_format_t {
+ VIDEO_YUV_FORMAT_NV12,
+ VIDEO_YUV_FORMAT_TILE_4x2
+};
+
typedef struct {
int w;
int h;
@@ -84,12 +97,29 @@
#define VIDEO_CMD_FREEZE (2)
#define VIDEO_CMD_CONTINUE (3)
+#define VIDEO_CMD_SET_CODEC (4)
+#define VIDEO_CMD_GET_CODEC (5)
+#define VIDEO_CMD_SET_OUTPUT_FORMAT (6)
+#define VIDEO_CMD_GET_OUTPUT_FORMAT (7)
+#define VIDEO_CMD_GET_BUFFER_REQ (8)
+#define VIDEO_CMD_SET_INPUT_BUFFERS (9)
+#define VIDEO_CMD_SET_OUTPUT_BUFFERS (10)
+#define VIDEO_CMD_READ_RAW_OUTPUT (11)
+#define VIDEO_CMD_GET_PIC_RES (12)
+#define VIDEO_CMD_FREE_INPUT_BUFFERS (13)
+#define VIDEO_CMD_FREE_OUTPUT_BUFFERS (14)
+#define VIDEO_CMD_GET_H264_MV_BUFFER (15)
+#define VIDEO_CMD_SET_H264_MV_BUFFER (16)
+#define VIDEO_CMD_FREE_H264_MV_BUFFER (17)
+#define VIDEO_CMD_CLEAR_INPUT_BUFFER (18)
+#define VIDEO_CMD_CLEAR_OUTPUT_BUFFER (19)
+
/* Flags for VIDEO_CMD_FREEZE */
-#define VIDEO_CMD_FREEZE_TO_BLACK (1 << 0)
+#define VIDEO_CMD_FREEZE_TO_BLACK (1 << 0)
/* Flags for VIDEO_CMD_STOP */
-#define VIDEO_CMD_STOP_TO_BLACK (1 << 0)
-#define VIDEO_CMD_STOP_IMMEDIATELY (1 << 1)
+#define VIDEO_CMD_STOP_TO_BLACK (1 << 0)
+#define VIDEO_CMD_STOP_IMMEDIATELY (1 << 1)
/* Play input formats: */
/* The decoder has no special format requirements */
@@ -97,6 +127,56 @@
/* The decoder requires full GOPs */
#define VIDEO_PLAY_FMT_GOP (1)
+/* Picture Resolution for Video Data */
+struct video_pic_res {
+ unsigned int width;
+ unsigned int height;
+ unsigned int stride;
+ unsigned int scan_lines;
+};
+
+/* Video Buffer Properties */
+struct video_buffer_prop {
+ unsigned int alignment;
+ unsigned int buf_poolid;
+ size_t buf_size;
+};
+
+/* Buffer Requirements from Video Decoder */
+struct video_buffer_req {
+ unsigned int num_input_buffers; /* Number of Input Buffers */
+ unsigned int num_output_buffers; /* Number of Output Buffers */
+ struct video_buffer_prop input_buf_prop; /* Input Buffer Properties */
+ struct video_buffer_prop output_buf_prop; /* Output Buffer Prop */
+};
+
+/* Video Data Buffer Structure for Input and Output */
+struct video_data_buffer {
+ void __user *bufferaddr; /* Pointer to Buffer */
+ size_t buffer_len; /* Length of Buffer */
+ int ion_fd; /* file Descriptor */
+ size_t offset;
+ size_t mmaped_size;
+ void *client_data;
+ void *ip_buffer_tag;
+ __u64 pts;
+};
+
+struct video_h264_mv {
+ size_t size;
+ int count;
+ int ion_fd;
+ int offset;
+};
+
+struct video_mv_buff_size {
+ int width;
+ int height;
+ int size;
+ int alignment;
+};
+
+
/* The structure must be zeroed before use by the application
This ensures it can be extended safely in the future. */
struct video_command {
@@ -112,11 +192,23 @@
1 specifies forward single stepping,
-1 specifies backward single stepping,
>1: playback at speed/1000 of the normal speed,
- <-1: reverse playback at (-speed/1000) of the normal speed. */
+ <-1: reverse playback at (-speed/1000) of
+ the normal speed. */
__s32 speed;
__u32 format;
} play;
+ union {
+ enum video_codec_t codec; /* Video Codec Type */
+ enum video_out_format_t format; /* YUV Format */
+ struct video_pic_res frame_res; /* Frame Resolution */
+ /* Buffer Requirements for Video Decoder */
+ struct video_buffer_req buf_req;
+ struct video_data_buffer buffer; /* Buffer Details */
+ struct video_mv_buff_size mv_buffer_req;
+ struct video_h264_mv mv_buffer_prop;
+ };
+
struct {
__u32 data[16];
} raw;
@@ -126,22 +218,47 @@
/* FIELD_UNKNOWN can be used if the hardware does not know whether
the Vsync is for an odd, even or progressive (i.e. non-interlaced)
field. */
-#define VIDEO_VSYNC_FIELD_UNKNOWN (0)
-#define VIDEO_VSYNC_FIELD_ODD (1)
+#define VIDEO_VSYNC_FIELD_UNKNOWN (0)
+#define VIDEO_VSYNC_FIELD_ODD (1)
#define VIDEO_VSYNC_FIELD_EVEN (2)
#define VIDEO_VSYNC_FIELD_PROGRESSIVE (3)
struct video_event {
__s32 type;
-#define VIDEO_EVENT_SIZE_CHANGED 1
-#define VIDEO_EVENT_FRAME_RATE_CHANGED 2
-#define VIDEO_EVENT_DECODER_STOPPED 3
-#define VIDEO_EVENT_VSYNC 4
+#define VIDEO_EVENT_SIZE_CHANGED (1)
+#define VIDEO_EVENT_FRAME_RATE_CHANGED (2)
+#define VIDEO_EVENT_DECODER_STOPPED (3)
+#define VIDEO_EVENT_VSYNC (4)
+#define VIDEO_EVENT_DECODER_PLAYING (5)
+#define VIDEO_EVENT_DECODER_FREEZED (6)
+#define VIDEO_EVENT_DECODER_RESUMED (7)
+#define VIDEO_EVENT_INPUT_BUFFER_DONE (8)
+#define VIDEO_EVENT_SEQ_HDR_FOUND (9)
+#define VIDEO_EVENT_OUTPUT_BUFFER_DONE (10)
+#define VIDEO_EVENT_OUTPUT_FLUSH_DONE (11)
+#define VIDEO_EVENT_INPUT_FLUSH_DONE (12)
+#define VIDEO_EVENT_INPUT_FLUSHED (13)
+#define VIDEO_EVENT_OUTPUT_FLUSHED (14)
+
+
+ unsigned int status;
+#define VIDEO_STATUS_SUCESS 0
+#define VIDEO_STATUS_BITSTREAM_ERROR 1
+#define VIDEO_STATUS_FAILED 2
+#define VIDEO_STATUS_NORESOURCE 3
+#define VIDEO_STATUS_INVALID_CMD 4
+#define VIDEO_STATUS_INVALID_PARAM 5
+#define VIDEO_STATUS_INVALID_STATE 6
+#define VIDEO_STATUS_BUSY 7
+#define VIDEO_STATUS_INVALID_HANDLE 8
+#define VIDEO_STATUS_NO_SUPPORT 9
__kernel_time_t timestamp;
+
union {
video_size_t size;
unsigned int frame_rate; /* in frames per 1000sec */
- unsigned char vsync_field; /* unknown/odd/even/progressive */
+ unsigned char vsync_field; /* unknown/odd/even/progressive */
+ struct video_data_buffer buffer; /* Output Buffer Details */
} u;
};
@@ -149,8 +266,8 @@
struct video_status {
int video_blank; /* blank video on freeze? */
video_play_state_t play_state; /* current state of playback */
- video_stream_source_t stream_source; /* current source (demux/memory) */
- video_format_t video_format; /* current aspect ratio of stream*/
+ video_stream_source_t stream_source;/* current source (demux/memory) */
+ video_format_t video_format; /* current aspect ratio of stream*/
video_displayformat_t display_format;/* selected cropping mode */
};
@@ -160,7 +277,6 @@
__s32 size;
};
-
typedef
struct video_highlight {
int active; /* 1=show highlight, 0=hide highlight */
@@ -268,9 +384,9 @@
#define VIDEO_GET_PTS _IOR('o', 57, __u64)
/* Read the number of displayed frames since the decoder was started */
-#define VIDEO_GET_FRAME_COUNT _IOR('o', 58, __u64)
+#define VIDEO_GET_FRAME_COUNT _IOR('o', 58, __u64)
-#define VIDEO_COMMAND _IOWR('o', 59, struct video_command)
-#define VIDEO_TRY_COMMAND _IOWR('o', 60, struct video_command)
+#define VIDEO_COMMAND _IOWR('o', 59, struct video_command)
+#define VIDEO_TRY_COMMAND _IOWR('o', 60, struct video_command)
#endif /*_DVBVIDEO_H_*/
diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h
index 7169870..f28053c 100644
--- a/include/linux/iopoll.h
+++ b/include/linux/iopoll.h
@@ -49,6 +49,28 @@
})
/**
+ * readl_poll_timeout_noirq - Periodically poll an address until a condition is met or a timeout occurs
+ * @addr: Address to poll
+ * @val: Variable to read the value into
+ * @cond: Break condition (usually involving @val)
+ * @max_reads: Maximum number of reads before giving up
+ * @time_between_us: Time to udelay() between successive reads
+ *
+ * Returns 0 on success and -ETIMEDOUT upon a timeout.
+ */
+#define readl_poll_timeout_noirq(addr, val, cond, max_reads, time_between_us) \
+({ \
+ int count; \
+ for (count = (max_reads); count > 0; count--) { \
+ (val) = readl(addr); \
+ if (cond) \
+ break; \
+ udelay(time_between_us); \
+ } \
+ (cond) ? 0 : -ETIMEDOUT; \
+})
+
+/**
* readl_poll - Periodically poll an address until a condition is met
* @addr: Address to poll
* @val: Variable to read the value into
diff --git a/include/linux/mfd/pm8xxx/pm8921-charger.h b/include/linux/mfd/pm8xxx/pm8921-charger.h
index 6bd4cb2..7b389c5 100644
--- a/include/linux/mfd/pm8xxx/pm8921-charger.h
+++ b/include/linux/mfd/pm8xxx/pm8921-charger.h
@@ -93,6 +93,7 @@
* however, this should only be enabled for devices which
* control the DC OVP FETs otherwise this option should
* remain disabled
+ * @has_dc_supply: report DC online if this bit is set in board file
* @trkl_voltage: the trkl voltage in (mV) below which hw controlled
* trkl charging happens with linear charger
* @weak_voltage: the weak voltage (mV) below which hw controlled
@@ -142,6 +143,7 @@
int64_t batt_id_max;
bool keep_btm_on_suspend;
bool dc_unplug_check;
+ bool has_dc_supply;
int trkl_voltage;
int weak_voltage;
int trkl_current;
diff --git a/include/linux/mfd/wcd9xxx/wcd9xxx-slimslave.h b/include/linux/mfd/wcd9xxx/wcd9xxx-slimslave.h
index 9619527..0d5d058 100644
--- a/include/linux/mfd/wcd9xxx/wcd9xxx-slimslave.h
+++ b/include/linux/mfd/wcd9xxx/wcd9xxx-slimslave.h
@@ -116,4 +116,6 @@
unsigned int *rx_ch,
unsigned int *tx_ch);
int wcd9xxx_get_slave_port(unsigned int ch_num);
+int wcd9xxx_disconnect_port(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
+ unsigned int tot_ch, unsigned int rx_tx);
#endif /* __WCD9310_SLIMSLAVE_H_ */
diff --git a/include/linux/msm_audio.h b/include/linux/msm_audio.h
index f2a39e4..4eb8a65 100644
--- a/include/linux/msm_audio.h
+++ b/include/linux/msm_audio.h
@@ -222,6 +222,28 @@
#define SND_SET_DEVICE _IOW(SND_IOCTL_MAGIC, 2, struct msm_device_config *)
+enum cad_device_path_type {
+ CAD_DEVICE_PATH_RX, /*For Decoding session*/
+ CAD_DEVICE_PATH_TX, /* For Encoding session*/
+ CAD_DEVICE_PATH_RX_TX, /* For Voice call */
+ CAD_DEVICE_PATH_LB, /* For loopback (FM Analog)*/
+ CAD_DEVICE_PATH_MAX
+};
+
+struct cad_devices_type {
+ uint32_t rx_device;
+ uint32_t tx_device;
+ enum cad_device_path_type pathtype;
+};
+
+struct msm_cad_device_config {
+ struct cad_devices_type device;
+ uint32_t ear_mute;
+ uint32_t mic_mute;
+};
+
+#define CAD_SET_DEVICE _IOW(SND_IOCTL_MAGIC, 2, struct msm_cad_device_config *)
+
#define SND_METHOD_VOICE 0
struct msm_snd_volume_config {
@@ -232,6 +254,14 @@
#define SND_SET_VOLUME _IOW(SND_IOCTL_MAGIC, 3, struct msm_snd_volume_config *)
+struct msm_cad_volume_config {
+ struct cad_devices_type device;
+ uint32_t method;
+ uint32_t volume;
+};
+
+#define CAD_SET_VOLUME _IOW(SND_IOCTL_MAGIC, 3, struct msm_cad_volume_config *)
+
/* Returns the number of SND endpoints supported. */
#define SND_GET_NUM_ENDPOINTS _IOR(SND_IOCTL_MAGIC, 4, unsigned *)
@@ -254,6 +284,24 @@
#define SND_AVC_CTL _IOW(SND_IOCTL_MAGIC, 6, unsigned *)
#define SND_AGC_CTL _IOW(SND_IOCTL_MAGIC, 7, unsigned *)
+/*return the number of CAD endpoints supported. */
+
+#define CAD_GET_NUM_ENDPOINTS _IOR(SND_IOCTL_MAGIC, 4, unsigned *)
+
+struct msm_cad_endpoint {
+ int id; /* input and output */
+ char name[64]; /* output only */
+};
+
+/* Takes an index between 0 and one less than the number returned by
+ * SND_GET_NUM_ENDPOINTS, and returns the CAD index and name of a
+ * CAD endpoint. On input, the .id field contains the number of the
+ * endpoint, and on exit it contains the SND index, while .name contains
+ * the description of the endpoint.
+ */
+
+#define CAD_GET_ENDPOINT _IOWR(SND_IOCTL_MAGIC, 5, struct msm_cad_endpoint *)
+
struct msm_audio_pcm_config {
uint32_t pcm_feedback; /* 0 - disable > 0 - enable */
uint32_t buffer_count; /* Number of buffers to allocate */
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 2519a6e..e7cbb79 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -105,6 +105,8 @@
MDP_YCRCB_H1V1, /* YCrCb interleave */
MDP_YCBCR_H1V1, /* YCbCr interleave */
MDP_BGR_565, /* BGR 565 planer */
+ MDP_BGR_888, /* BGR 888 */
+ MDP_Y_CBCR_H2V2_VENUS,
MDP_IMGTYPE_LIMIT,
MDP_RGB_BORDERFILL, /* border fill pipe */
MDP_FB_FORMAT = MDP_IMGTYPE2_START, /* framebuffer format */
diff --git a/include/linux/msm_rmnet.h b/include/linux/msm_rmnet.h
index 9f52464..063a8f1 100644
--- a/include/linux/msm_rmnet.h
+++ b/include/linux/msm_rmnet.h
@@ -40,6 +40,8 @@
RMNET_IOCTL_GET_OPMODE = 0x000089F7, /* Get operation mode */
RMNET_IOCTL_OPEN = 0x000089F8, /* Open transport port */
RMNET_IOCTL_CLOSE = 0x000089F9, /* Close transport port */
+ RMNET_IOCTL_FLOW_ENABLE = 0x000089FA, /* Flow enable */
+ RMNET_IOCTL_FLOW_DISABLE = 0x000089FB, /* Flow disable */
RMNET_IOCTL_MAX
};
diff --git a/include/linux/msm_vidc_dec.h b/include/linux/msm_vidc_dec.h
index 3d8907a..3c99562 100644
--- a/include/linux/msm_vidc_dec.h
+++ b/include/linux/msm_vidc_dec.h
@@ -76,6 +76,9 @@
#define VDEC_EXTRADATA_VUI 0x020
#define VDEC_EXTRADATA_VC1 0x040
+#define VDEC_EXTRADATA_EXT_DATA 0x0800
+#define VDEC_EXTRADATA_USER_DATA 0x1000
+
#define VDEC_CMDBASE 0x800
#define VDEC_CMD_SET_INTF_VERSION (VDEC_CMDBASE)
diff --git a/include/linux/slimbus/slimbus.h b/include/linux/slimbus/slimbus.h
index a088b9c..d365b15 100644
--- a/include/linux/slimbus/slimbus.h
+++ b/include/linux/slimbus/slimbus.h
@@ -1011,6 +1011,15 @@
extern struct slim_controller *slim_busnum_to_ctrl(u32 busnum);
/*
+ * slim_ctrl_add_boarddevs: Add devices registered by board-info
+ * @ctrl: Controller to which these devices are to be added to.
+ * This API is called by controller when it is up and running.
+ * If devices on a controller were registered before controller,
+ * this will make sure that they get probed when controller is up
+ */
+extern void slim_ctrl_add_boarddevs(struct slim_controller *ctrl);
+
+/*
* slim_register_board_info: Board-initialization routine.
* @info: List of all devices on all controllers present on the board.
* @n: number of entries.
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index aaabca9..59ba64b 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -378,6 +378,7 @@
unsigned strobe;
unsigned data;
struct msm_bus_scale_pdata *bus_scale_table;
+ unsigned log2_irq_thresh;
};
struct msm_usb_host_platform_data {
@@ -437,6 +438,7 @@
* @usb_bam_num_pipes: max number of pipes to use.
* @active_conn_num: number of active pipe connections.
* @usb_base_address: BAM physical address.
+ * @ignore_core_reset_ack: BAM can ignore ACK from USB core during PIPE RESET
*/
struct msm_usb_bam_platform_data {
struct usb_bam_pipe_connect *connections;
@@ -444,6 +446,7 @@
int usb_bam_num_pipes;
u32 total_bam_num;
u32 usb_base_address;
+ bool ignore_core_reset_ack;
};
enum usb_bam {
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index 516f764..a040d49 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -29,6 +29,7 @@
#define USBCMD_RESET 2
#define USB_USBINTR (MSM_USB_BASE + 0x0148)
+#define USB_FRINDEX (MSM_USB_BASE + 0x014C)
#define PORTSC_PHCD (1 << 23) /* phy suspend mode */
#define PORTSC_PTS_MASK (3 << 30)
diff --git a/include/media/msm/vcd_property.h b/include/media/msm/vcd_property.h
index acd0fa3..484d08f 100644
--- a/include/media/msm/vcd_property.h
+++ b/include/media/msm/vcd_property.h
@@ -113,6 +113,9 @@
#define VCD_METADATA_PASSTHROUGH 0x080
#define VCD_METADATA_ENC_SLICE 0x100
+#define VCD_METADATA_EXT_DATA 0x0800
+#define VCD_METADATA_USER_DATA 0x1000
+
struct vcd_property_meta_data_enable {
u32 meta_data_enable_flag;
};
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index b27debc..f95230e 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -16,6 +16,7 @@
#ifdef MSM_CAMERA_BIONIC
#include <sys/types.h>
#endif
+#include <linux/videodev2.h>
#include <linux/types.h>
#include <linux/ioctl.h>
#ifdef __KERNEL__
@@ -151,7 +152,7 @@
_IOW(MSM_CAM_IOCTL_MAGIC, 39, struct msm_camera_st_frame *)
#define MSM_CAM_IOCTL_V4L2_EVT_NOTIFY \
- _IOR(MSM_CAM_IOCTL_MAGIC, 40, struct v4l2_event *)
+ _IOW(MSM_CAM_IOCTL_MAGIC, 40, struct v4l2_event_and_payload)
#define MSM_CAM_IOCTL_SET_MEM_MAP_INFO \
_IOR(MSM_CAM_IOCTL_MAGIC, 41, struct msm_mem_map_info *)
@@ -216,6 +217,24 @@
#define MSM_CAM_IOCTL_STATS_UNREG_BUF \
_IOR(MSM_CAM_IOCTL_MAGIC, 61, struct msm_stats_flush_bufq *)
+#define MSM_CAM_IOCTL_CSIC_IO_CFG \
+ _IOWR(MSM_CAM_IOCTL_MAGIC, 62, struct csic_cfg_data *)
+
+#define MSM_CAM_IOCTL_CSID_IO_CFG \
+ _IOWR(MSM_CAM_IOCTL_MAGIC, 63, struct csid_cfg_data *)
+
+#define MSM_CAM_IOCTL_CSIPHY_IO_CFG \
+ _IOR(MSM_CAM_IOCTL_MAGIC, 64, struct csiphy_cfg_data *)
+
+#define MSM_CAM_IOCTL_OEM \
+ _IOW(MSM_CAM_IOCTL_MAGIC, 65, struct sensor_cfg_data *)
+
+struct v4l2_event_and_payload {
+ struct v4l2_event evt;
+ uint32_t payload_length;
+ uint32_t transaction_id;
+ void *payload;
+};
struct msm_stats_reqbuf {
int num_buf; /* how many buffers requested */
@@ -350,6 +369,27 @@
uint32_t inst_handle;
};
+struct msm_pp_crop {
+ uint32_t src_x;
+ uint32_t src_y;
+ uint32_t src_w;
+ uint32_t src_h;
+ uint32_t dst_x;
+ uint32_t dst_y;
+ uint32_t dst_w;
+ uint32_t dst_h;
+ uint8_t update_flag;
+};
+
+struct msm_mctl_pp_frame_cmd {
+ uint32_t cookie;
+ uint8_t vpe_output_action;
+ struct msm_pp_frame src_frame;
+ struct msm_pp_frame dest_frame;
+ struct msm_pp_crop crop;
+ int path;
+};
+
struct msm_cam_evt_divert_frame {
unsigned short image_mode;
unsigned short op_mode;
@@ -486,8 +526,8 @@
#define CMD_STATS_BG_BUF_RELEASE 56
#define CMD_STATS_BF_BUF_RELEASE 57
#define CMD_STATS_BHIST_BUF_RELEASE 58
-#define CMD_VFE_SOF_COUNT_UPDATE 59
-#define CMD_VFE_COUNT_SOF_ENABLE 60
+#define CMD_VFE_PIX_SOF_COUNT_UPDATE 59
+#define CMD_VFE_COUNT_PIX_SOF_ENABLE 60
#define CMD_AXI_CFG_PRIM BIT(8)
#define CMD_AXI_CFG_PRIM_ALL_CHNLS BIT(9)
@@ -499,6 +539,8 @@
#define CMD_AXI_START 0xE1
#define CMD_AXI_STOP 0xE2
#define CMD_AXI_RESET 0xE3
+#define CMD_AXI_ABORT 0xE4
+
#define AXI_CMD_PREVIEW BIT(0)
@@ -583,6 +625,7 @@
MSM_STATS_TYPE_BF, /* Bayer Focus */
MSM_STATS_TYPE_BHIST, /* Bayer Hist */
MSM_STATS_TYPE_AE_AW, /* legacy stats for vfe 2.x*/
+ MSM_STATS_TYPE_COMP, /* Composite stats */
MSM_STATS_TYPE_MAX /* MAX */
};
@@ -662,8 +705,11 @@
#define OUTPUT_TYPE_ST_D BIT(7)
#define OUTPUT_TYPE_R BIT(8)
#define OUTPUT_TYPE_R1 BIT(9)
-
-
+#define OUTPUT_TYPE_SAEC BIT(10)
+#define OUTPUT_TYPE_SAFC BIT(11)
+#define OUTPUT_TYPE_SAWB BIT(12)
+#define OUTPUT_TYPE_IHST BIT(13)
+#define OUTPUT_TYPE_CSTA BIT(14)
struct fd_roi_info {
void *info;
@@ -778,27 +824,39 @@
/* extendedmode for the thumb nail image in VIDIOC_S_PARM */
#define MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+4)
-#define MSM_V4L2_EXT_CAPTURE_MODE_RAW \
+/* ISP_PIX_OUTPUT1: no pp, directly send output1 buf to user */
+#define MSM_V4L2_EXT_CAPTURE_MODE_ISP_PIX_OUTPUT1 \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+5)
-#define MSM_V4L2_EXT_CAPTURE_MODE_RDI \
+/* ISP_PIX_OUTPUT2: no pp, directly send output2 buf to user */
+#define MSM_V4L2_EXT_CAPTURE_MODE_ISP_PIX_OUTPUT2 \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+6)
-#define MSM_V4L2_EXT_CAPTURE_MODE_RDI1 \
+/* raw image type */
+#define MSM_V4L2_EXT_CAPTURE_MODE_RAW \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+7)
-#define MSM_V4L2_EXT_CAPTURE_MODE_RDI2 \
+/* RDI dump */
+#define MSM_V4L2_EXT_CAPTURE_MODE_RDI \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+8)
-#define MSM_V4L2_EXT_CAPTURE_MODE_AEC \
+/* RDI dump 1 */
+#define MSM_V4L2_EXT_CAPTURE_MODE_RDI1 \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+9)
-#define MSM_V4L2_EXT_CAPTURE_MODE_AWB \
+/* RDI dump 2 */
+#define MSM_V4L2_EXT_CAPTURE_MODE_RDI2 \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+10)
-#define MSM_V4L2_EXT_CAPTURE_MODE_AF \
+#define MSM_V4L2_EXT_CAPTURE_MODE_AEC \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+11)
-#define MSM_V4L2_EXT_CAPTURE_MODE_IHIST \
+#define MSM_V4L2_EXT_CAPTURE_MODE_AWB \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+12)
-#define MSM_V4L2_EXT_CAPTURE_MODE_CS \
+#define MSM_V4L2_EXT_CAPTURE_MODE_AF \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+13)
-#define MSM_V4L2_EXT_CAPTURE_MODE_RS \
+#define MSM_V4L2_EXT_CAPTURE_MODE_IHIST \
(MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+14)
-#define MSM_V4L2_EXT_CAPTURE_MODE_MAX (MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+15)
+#define MSM_V4L2_EXT_CAPTURE_MODE_CS \
+ (MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+15)
+#define MSM_V4L2_EXT_CAPTURE_MODE_RS \
+ (MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+16)
+#define MSM_V4L2_EXT_CAPTURE_MODE_CSTA \
+ (MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+17)
+#define MSM_V4L2_EXT_CAPTURE_MODE_MAX (MSM_V4L2_EXT_CAPTURE_MODE_DEFAULT+18)
#define MSM_V4L2_PID_MOTION_ISO V4L2_CID_PRIVATE_BASE
#define MSM_V4L2_PID_EFFECT (V4L2_CID_PRIVATE_BASE+1)
@@ -851,7 +909,8 @@
#define MSM_V4L2_CLOSE 11
#define MSM_V4L2_SET_CTRL_CMD 12
#define MSM_V4L2_EVT_SUB_MASK 13
-#define MSM_V4L2_MAX 14
+#define MSM_V4L2_PRIVATE_CMD 14
+#define MSM_V4L2_MAX 15
#define V4L2_CAMERA_EXIT 43
struct crop_info {
@@ -918,7 +977,15 @@
#define CFG_START_STREAM 44
#define CFG_STOP_STREAM 45
#define CFG_GET_CSI_PARAMS 46
-#define CFG_MAX 47
+#define CFG_POWER_UP 47
+#define CFG_POWER_DOWN 48
+#define CFG_WRITE_I2C_ARRAY 49
+#define CFG_READ_I2C_ARRAY 50
+#define CFG_PCLK_CHANGE 51
+#define CFG_CONFIG_VREG_ARRAY 52
+#define CFG_CONFIG_CLK_ARRAY 53
+#define CFG_GPIO_OP 54
+#define CFG_MAX 55
#define MOVE_NEAR 0
@@ -1233,6 +1300,33 @@
uint16_t num_info;
};
+struct msm_sensor_exp_gain_info_t {
+ uint16_t coarse_int_time_addr;
+ uint16_t global_gain_addr;
+ uint16_t vert_offset;
+};
+
+struct msm_sensor_output_reg_addr_t {
+ uint16_t x_output;
+ uint16_t y_output;
+ uint16_t line_length_pclk;
+ uint16_t frame_length_lines;
+};
+
+struct sensor_driver_params_type {
+ struct msm_camera_i2c_reg_setting *init_settings;
+ uint16_t init_settings_size;
+ struct msm_camera_i2c_reg_setting *mode_settings;
+ uint16_t mode_settings_size;
+ struct msm_sensor_output_reg_addr_t *sensor_output_reg_addr;
+ struct msm_camera_i2c_reg_setting *start_settings;
+ struct msm_camera_i2c_reg_setting *stop_settings;
+ struct msm_camera_i2c_reg_setting *groupon_settings;
+ struct msm_camera_i2c_reg_setting *groupoff_settings;
+ struct msm_sensor_exp_gain_info_t *sensor_exp_gain_info;
+ struct msm_sensor_output_info_t *output_info;
+};
+
struct mirror_flip {
int32_t x_mirror;
int32_t y_flip;
@@ -1255,11 +1349,81 @@
};
struct csi_lane_params_t {
- uint8_t csi_lane_assign;
+ uint16_t csi_lane_assign;
uint8_t csi_lane_mask;
uint8_t csi_if;
- uint8_t csid_core;
- uint32_t csid_version;
+ uint8_t csid_core[2];
+};
+
+struct msm_camera_csid_lut_params {
+ uint8_t num_cid;
+ struct msm_camera_csid_vc_cfg *vc_cfg;
+};
+
+struct msm_camera_csid_params {
+ uint8_t lane_cnt;
+ uint16_t lane_assign;
+ uint8_t phy_sel;
+ struct msm_camera_csid_lut_params lut_params;
+};
+
+struct msm_camera_csiphy_params {
+ uint8_t lane_cnt;
+ uint8_t settle_cnt;
+ uint16_t lane_mask;
+ uint8_t combo_mode;
+};
+
+struct msm_camera_csi2_params {
+ struct msm_camera_csid_params csid_params;
+ struct msm_camera_csiphy_params csiphy_params;
+};
+
+enum msm_camera_csi_data_format {
+ CSI_8BIT,
+ CSI_10BIT,
+ CSI_12BIT,
+};
+
+struct msm_camera_csi_params {
+ enum msm_camera_csi_data_format data_format;
+ uint8_t lane_cnt;
+ uint8_t lane_assign;
+ uint8_t settle_cnt;
+ uint8_t dpcm_scheme;
+};
+
+enum csic_cfg_type_t {
+ CSIC_INIT,
+ CSIC_CFG,
+};
+
+struct csic_cfg_data {
+ enum csic_cfg_type_t cfgtype;
+ struct msm_camera_csi_params *csic_params;
+};
+
+enum csid_cfg_type_t {
+ CSID_INIT,
+ CSID_CFG,
+};
+
+struct csid_cfg_data {
+ enum csid_cfg_type_t cfgtype;
+ union {
+ uint32_t csid_version;
+ struct msm_camera_csid_params *csid_params;
+ } cfg;
+};
+
+enum csiphy_cfg_type_t {
+ CSIPHY_INIT,
+ CSIPHY_CFG,
+};
+
+struct csiphy_cfg_data {
+ enum csiphy_cfg_type_t cfgtype;
+ struct msm_camera_csiphy_params *csiphy_params;
};
#define CSI_EMBED_DATA 0x12
@@ -1359,6 +1523,81 @@
} cfg;
};
+enum msm_camera_i2c_reg_addr_type {
+ MSM_CAMERA_I2C_BYTE_ADDR = 1,
+ MSM_CAMERA_I2C_WORD_ADDR,
+};
+
+struct msm_camera_i2c_reg_array {
+ uint16_t reg_addr;
+ uint16_t reg_data;
+};
+
+enum msm_camera_i2c_data_type {
+ MSM_CAMERA_I2C_BYTE_DATA = 1,
+ MSM_CAMERA_I2C_WORD_DATA,
+ MSM_CAMERA_I2C_SET_BYTE_MASK,
+ MSM_CAMERA_I2C_UNSET_BYTE_MASK,
+ MSM_CAMERA_I2C_SET_WORD_MASK,
+ MSM_CAMERA_I2C_UNSET_WORD_MASK,
+ MSM_CAMERA_I2C_SET_BYTE_WRITE_MASK_DATA,
+};
+
+struct msm_camera_i2c_reg_setting {
+ struct msm_camera_i2c_reg_array *reg_setting;
+ uint16_t size;
+ enum msm_camera_i2c_reg_addr_type addr_type;
+ enum msm_camera_i2c_data_type data_type;
+ uint16_t delay;
+};
+
+enum oem_setting_type {
+ I2C_READ = 1,
+ I2C_WRITE,
+ GPIO_OP,
+ EEPROM_READ,
+ VREG_SET,
+ CLK_SET,
+};
+
+struct sensor_oem_setting {
+ enum oem_setting_type type;
+ void *data;
+};
+
+enum camera_vreg_type {
+ REG_LDO,
+ REG_VS,
+ REG_GPIO,
+};
+
+struct camera_vreg_t {
+ const char *reg_name;
+ enum camera_vreg_type type;
+ int min_voltage;
+ int max_voltage;
+ int op_mode;
+ uint32_t delay;
+};
+
+struct msm_camera_vreg_setting {
+ struct camera_vreg_t *cam_vreg;
+ uint16_t num_vreg;
+ uint8_t enable;
+};
+
+struct msm_cam_clk_info {
+ const char *clk_name;
+ long clk_rate;
+ uint32_t delay;
+};
+
+struct msm_cam_clk_setting {
+ struct msm_cam_clk_info *clk_info;
+ uint16_t num_clk_info;
+ uint8_t enable;
+};
+
struct sensor_cfg_data {
int cfgtype;
int mode;
@@ -1395,12 +1634,30 @@
int ae_mode;
uint8_t wb_val;
int8_t exp_compensation;
+ uint32_t pclk;
struct cord aec_cord;
int is_autoflash;
struct mirror_flip mirror_flip;
+ void *setting;
} cfg;
};
+enum gpio_operation_type {
+ GPIO_REQUEST,
+ GPIO_FREE,
+ GPIO_SET_DIRECTION_OUTPUT,
+ GPIO_SET_DIRECTION_INPUT,
+ GPIO_GET_VALUE,
+ GPIO_SET_VALUE,
+};
+
+struct msm_cam_gpio_operation {
+ enum gpio_operation_type op_type;
+ unsigned address;
+ int value;
+ const char *tag;
+};
+
struct damping_params_t {
uint32_t damping_step;
uint32_t damping_delay;
@@ -1557,11 +1814,17 @@
struct pixel_t video_coord[128];
};
+struct msm_calib_raw {
+ uint8_t *data;
+ uint32_t size;
+};
+
struct msm_camera_eeprom_info_t {
struct msm_eeprom_support af;
struct msm_eeprom_support wb;
struct msm_eeprom_support lsc;
struct msm_eeprom_support dpc;
+ struct msm_eeprom_support raw;
};
struct msm_eeprom_cfg_data {
@@ -1734,6 +1997,9 @@
#define MSM_CAM_V4L2_IOCTL_PRIVATE_G_CTRL \
_IOWR('V', BASE_VIDIOC_PRIVATE + 9, struct msm_camera_v4l2_ioctl_t)
+#define MSM_CAM_V4L2_IOCTL_PRIVATE_GENERAL \
+ _IOW('V', BASE_VIDIOC_PRIVATE + 10, struct msm_camera_v4l2_ioctl_t)
+
#define VIDIOC_MSM_VPE_INIT \
_IO('V', BASE_VIDIOC_PRIVATE + 15)
@@ -1758,22 +2024,27 @@
#define VIDIOC_MSM_AXI_BUF_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE + 22, void *)
+#define VIDIOC_MSM_AXI_RDI_COUNT_UPDATE \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 23, struct rdi_count_msg)
+
#define VIDIOC_MSM_VFE_INIT \
- _IO('V', BASE_VIDIOC_PRIVATE + 22)
+ _IO('V', BASE_VIDIOC_PRIVATE + 24)
#define VIDIOC_MSM_VFE_RELEASE \
- _IO('V', BASE_VIDIOC_PRIVATE + 23)
+ _IO('V', BASE_VIDIOC_PRIVATE + 25)
struct msm_camera_v4l2_ioctl_t {
uint32_t id;
- void __user *ioctl_ptr;
uint32_t len;
+ uint32_t trans_code;
+ void __user *ioctl_ptr;
};
struct msm_camera_vfe_params_t {
uint32_t operation_mode;
uint32_t capture_count;
uint32_t skip_abort;
+ uint8_t stop_immediately;
uint16_t port_info;
uint32_t inst_handle;
uint16_t cmd_type;
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 9fa5932..faaa522 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -68,6 +68,9 @@
#define MSG_ID_RDI0_UPDATE_ACK 49
#define MSG_ID_RDI1_UPDATE_ACK 50
#define MSG_ID_RDI2_UPDATE_ACK 51
+#define MSG_ID_PIX0_UPDATE_ACK 52
+#define MSG_ID_PREV_STOP_ACK 53
+
/* ISP command IDs */
#define VFE_CMD_DUMMY_0 0
@@ -324,30 +327,10 @@
struct msm_vpe_clock_rate {
uint32_t rate;
};
-struct msm_pp_crop {
- uint32_t src_x;
- uint32_t src_y;
- uint32_t src_w;
- uint32_t src_h;
- uint32_t dst_x;
- uint32_t dst_y;
- uint32_t dst_w;
- uint32_t dst_h;
- uint8_t update_flag;
-};
+
#define MSM_MCTL_PP_VPE_FRAME_ACK (1<<0)
#define MSM_MCTL_PP_VPE_FRAME_TO_APP (1<<1)
-struct msm_mctl_pp_frame_cmd {
- uint32_t cookie;
- uint8_t vpe_output_action;
- uint32_t src_buf_handle;
- uint32_t dest_buf_handle;
- struct msm_pp_crop crop;
- int path;
- /* TBD: 3D related */
-};
-
#define VFE_OUTPUTS_MAIN_AND_PREVIEW BIT(0)
#define VFE_OUTPUTS_MAIN_AND_VIDEO BIT(1)
#define VFE_OUTPUTS_MAIN_AND_THUMB BIT(2)
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index cf99435..d56e534 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -38,6 +38,12 @@
writel_relaxed(val, addr); \
} while (0)
+#define VCAP_BASE (dev->vcapbase)
+#define VCAP_OFFSET(off) (VCAP_BASE + off)
+
+#define VCAP_SW_RESET_REQ (VCAP_BASE + 0x024)
+#define VCAP_SW_RESET_STATUS (VCAP_BASE + 0x028)
+
struct vcap_client_data;
enum rdy_buf {
@@ -167,6 +173,7 @@
bool vp_resource;
bool vp_dummy_event;
bool vp_dummy_complete;
+ bool vp_shutdown;
wait_queue_head_t vp_dummy_waitq;
struct workqueue_struct *vcap_wq;
diff --git a/include/media/videobuf2-msm-mem.h b/include/media/videobuf2-msm-mem.h
index 84e2bea..5285997 100644
--- a/include/media/videobuf2-msm-mem.h
+++ b/include/media/videobuf2-msm-mem.h
@@ -72,9 +72,10 @@
struct videobuf2_msm_offset *offset,
enum videobuf2_buffer_type,
uint32_t addr_offset, int path,
- struct ion_client *client);
+ struct ion_client *client,
+ int domain_num);
void videobuf2_pmem_contig_user_put(struct videobuf2_contig_pmem *mem,
- struct ion_client *client);
+ struct ion_client *client, int domain_num);
unsigned long videobuf2_to_pmem_contig(struct vb2_buffer *buf,
unsigned int plane_no);
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 3526e29..80f36e0 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -967,6 +967,26 @@
#define HCI_OP_LE_CREATE_CONN_CANCEL 0x200e
+#define HCI_OP_LE_READ_WHITE_LIST_SIZE 0x200F
+struct hci_rp_le_read_white_list_size {
+ __u8 status;
+ __u8 size;
+} __packed;
+
+#define HCI_OP_LE_CLEAR_WHITE_LIST 0x2010
+
+#define HCI_OP_LE_ADD_DEV_WHITE_LIST 0x2011
+struct hci_cp_le_add_dev_white_list {
+ __u8 addr_type;
+ bdaddr_t addr;
+} __packed;
+
+#define HCI_OP_LE_REMOVE_DEV_WHITE_LIST 0x2012
+struct hci_cp_le_remove_dev_white_list {
+ __u8 addr_type;
+ bdaddr_t addr;
+} __packed;
+
#define HCI_OP_LE_CONN_UPDATE 0x2013
struct hci_cp_le_conn_update {
__le16 handle;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 22428c1..e8c0bf3 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -191,6 +191,7 @@
unsigned int acl_pkts;
unsigned int sco_pkts;
unsigned int le_pkts;
+ unsigned int le_white_list_size;
unsigned int data_block_len;
@@ -602,6 +603,9 @@
bdaddr_t *dst, __u8 sec_level,
__u8 auth_type,
struct bt_le_params *le_params);
+void hci_le_add_dev_white_list(struct hci_dev *hdev, bdaddr_t *dst);
+void hci_le_remove_dev_white_list(struct hci_dev *hdev, bdaddr_t *dst);
+void hci_le_cancel_create_connect(struct hci_dev *hdev, bdaddr_t *dst);
int hci_conn_check_link_mode(struct hci_conn *conn);
int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
int hci_conn_change_link_key(struct hci_conn *conn);
@@ -1035,7 +1039,7 @@
int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 le);
int mgmt_le_conn_params(u16 index, bdaddr_t *bdaddr, u16 interval,
u16 latency, u16 timeout);
-int mgmt_disconnected(u16 index, bdaddr_t *bdaddr);
+int mgmt_disconnected(u16 index, bdaddr_t *bdaddr, u8 reason);
int mgmt_disconnect_failed(u16 index);
int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status);
int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 3048339..602fe59 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -60,6 +60,7 @@
__u8 hci_ver;
__u16 hci_rev;
__u8 name[MGMT_MAX_NAME_LENGTH];
+ __u8 le_white_list_size;
} __packed;
struct mgmt_mode {
@@ -246,6 +247,26 @@
bdaddr_t bdaddr;
} __packed;
+#define MGMT_OP_LE_READ_WHITE_LIST_SIZE 0xE000
+
+#define MGMT_OP_LE_CLEAR_WHITE_LIST 0xE001
+
+#define MGMT_OP_LE_ADD_DEV_WHITE_LIST 0xE002
+struct mgmt_cp_le_add_dev_white_list {
+ __u8 addr_type;
+ bdaddr_t bdaddr;
+} __packed;
+
+#define MGMT_OP_LE_REMOVE_DEV_WHITE_LIST 0xE003
+struct mgmt_cp_le_remove_dev_white_list {
+ __u8 addr_type;
+ bdaddr_t bdaddr;
+} __packed;
+
+#define MGMT_OP_LE_CREATE_CONN_WHITE_LIST 0xE004
+
+#define MGMT_OP_LE_CANCEL_CREATE_CONN_WHITE_LIST 0xE005
+
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
@@ -290,6 +311,7 @@
#define MGMT_EV_DISCONNECTED 0x000C
struct mgmt_ev_disconnected {
bdaddr_t bdaddr;
+ __u8 reason;
} __packed;
#define MGMT_EV_CONNECT_FAILED 0x000D
diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h
index fffdc60..95ec28b 100644
--- a/include/net/pkt_sched.h
+++ b/include/net/pkt_sched.h
@@ -103,7 +103,8 @@
struct tcf_result *res);
extern int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp,
struct tcf_result *res);
-
+extern void tc_qdisc_flow_control(struct net_device *dev, u32 tcm_handle,
+ int flow_enable);
/* Calculate maximal size of packet seen by hard_start_xmit
routine of this device.
*/
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index b7ddb08..90872c9 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -978,6 +978,16 @@
u32 sample_rate;
};
+struct asm_amrwbplus_cfg {
+ u32 size_bytes;
+ u32 version;
+ u32 num_channels;
+ u32 amr_band_mode;
+ u32 amr_dtx_mode;
+ u32 amr_frame_fmt;
+ u32 amr_lsf_idx;
+};
+
struct asm_flac_cfg {
u16 stream_info_present;
u16 min_blk_size;
@@ -1373,7 +1383,7 @@
u32 uid;
} __attribute__((packed));
-#define ASM_DATA_CMD_READ_COMPRESSED 0x00010DBC
+#define ASM_DATA_CMD_READ_COMPRESSED 0x00010DBF
struct asm_stream_cmd_read_compressed {
struct apr_hdr hdr;
u32 buf_add;
@@ -1398,6 +1408,7 @@
struct asm_flac_cfg flac_cfg;
struct asm_vorbis_cfg vorbis_cfg;
struct asm_multi_channel_pcm_fmt_blk multi_ch_pcm_cfg;
+ struct asm_amrwbplus_cfg amrwbplus_cfg;
} __attribute__((packed)) write_cfg;
} __attribute__((packed));
@@ -1444,7 +1455,7 @@
u32 id;
} __attribute__((packed));
-#define ASM_DATA_EVENT_READ_COMPRESSED_DONE 0x00010DBD
+#define ASM_DATA_EVENT_READ_COMPRESSED_DONE 0x00010DC0
struct asm_data_event_read_compressed_done {
u32 status;
u32 buffer_add;
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index 01f2fac..323a228 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -288,6 +288,9 @@
int q6asm_media_format_block_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg);
+int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
+ struct asm_amrwbplus_cfg *cfg);
+
int q6asm_media_format_block_multi_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg);
diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index 9271f5d..5fa311a 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -48,6 +48,48 @@
TP_ARGS(frequency, cpu_id)
);
+TRACE_EVENT(cpu_frequency_switch_start,
+
+ TP_PROTO(unsigned int start_freq, unsigned int end_freq,
+ unsigned int cpu_id),
+
+ TP_ARGS(start_freq, end_freq, cpu_id),
+
+ TP_STRUCT__entry(
+ __field( u32, start_freq )
+ __field( u32, end_freq )
+ __field( u32, cpu_id )
+ ),
+
+ TP_fast_assign(
+ __entry->start_freq = start_freq;
+ __entry->end_freq = end_freq;
+ __entry->cpu_id = cpu_id;
+ ),
+
+ TP_printk("start=%lu end=%lu cpu_id=%lu",
+ (unsigned long)__entry->start_freq,
+ (unsigned long)__entry->end_freq,
+ (unsigned long)__entry->cpu_id)
+);
+
+TRACE_EVENT(cpu_frequency_switch_end,
+
+ TP_PROTO(unsigned int cpu_id),
+
+ TP_ARGS(cpu_id),
+
+ TP_STRUCT__entry(
+ __field( u32, cpu_id )
+ ),
+
+ TP_fast_assign(
+ __entry->cpu_id = cpu_id;
+ ),
+
+ TP_printk("cpu_id=%lu", (unsigned long)__entry->cpu_id)
+);
+
TRACE_EVENT(machine_suspend,
TP_PROTO(unsigned int state),
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 431dba8..006d5c9 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -2002,7 +2002,7 @@
static int __ftrace_function_set_filter(int filter, char *buf, int len,
struct function_filter_data *data)
{
- int i, re_cnt, ret;
+ int i, re_cnt, ret = 0;
int *reset;
char **re;
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 08bf42d..f57fab7 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -50,7 +50,7 @@
bdaddr_t *dst, __u8 sec_level, __u8 auth_type,
struct bt_le_params *le_params)
{
- struct hci_conn *le;
+ struct hci_conn *le, *le_wlist_conn;
struct hci_cp_le_create_conn cp;
struct adv_entry *entry;
struct link_key *key;
@@ -59,8 +59,21 @@
le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
if (le) {
- hci_conn_hold(le);
- return le;
+ le_wlist_conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
+ BDADDR_ANY);
+ if (!le_wlist_conn) {
+ hci_conn_hold(le);
+ return le;
+ } else {
+ BT_DBG("remove wlist conn");
+ le->out = 1;
+ le->link_mode |= HCI_LM_MASTER;
+ le->sec_level = BT_SECURITY_LOW;
+ le->type = LE_LINK;
+ hci_proto_connect_cfm(le, 0);
+ hci_conn_del(le_wlist_conn);
+ return le;
+ }
}
key = hci_find_link_key_type(hdev, dst, KEY_TYPE_LTK);
@@ -107,8 +120,13 @@
cp.conn_latency = cpu_to_le16(BT_LE_LATENCY_DEF);
le->conn_timeout = 5;
}
- bacpy(&cp.peer_addr, &le->dst);
- cp.peer_addr_type = le->dst_type;
+ if (!bacmp(&le->dst, BDADDR_ANY)) {
+ cp.filter_policy = 0x01;
+ le->conn_timeout = 0;
+ } else {
+ bacpy(&cp.peer_addr, &le->dst);
+ cp.peer_addr_type = le->dst_type;
+ }
hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
@@ -121,6 +139,73 @@
hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL);
}
+void hci_le_cancel_create_connect(struct hci_dev *hdev, bdaddr_t *dst)
+{
+ struct hci_conn *le;
+
+ BT_DBG("%p", hdev);
+
+ le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
+ if (le) {
+ BT_DBG("send hci connect cancel");
+ hci_le_connect_cancel(le);
+ hci_conn_del(le);
+ }
+}
+EXPORT_SYMBOL(hci_le_cancel_create_connect);
+
+void hci_le_add_dev_white_list(struct hci_dev *hdev, bdaddr_t *dst)
+{
+ struct hci_cp_le_add_dev_white_list cp;
+ struct adv_entry *entry;
+ struct link_key *key;
+
+ BT_DBG("%p", hdev);
+
+ memset(&cp, 0, sizeof(cp));
+ bacpy(&cp.addr, dst);
+
+ key = hci_find_link_key_type(hdev, dst, KEY_TYPE_LTK);
+ if (!key) {
+ entry = hci_find_adv_entry(hdev, dst);
+ if (entry)
+ cp.addr_type = entry->bdaddr_type;
+ else
+ cp.addr_type = 0x00;
+ } else {
+ cp.addr_type = key->addr_type;
+ }
+
+ hci_send_cmd(hdev, HCI_OP_LE_ADD_DEV_WHITE_LIST, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_add_dev_white_list);
+
+void hci_le_remove_dev_white_list(struct hci_dev *hdev, bdaddr_t *dst)
+{
+ struct hci_cp_le_remove_dev_white_list cp;
+ struct adv_entry *entry;
+ struct link_key *key;
+
+ BT_DBG("%p", hdev);
+
+ memset(&cp, 0, sizeof(cp));
+ bacpy(&cp.addr, dst);
+
+ key = hci_find_link_key_type(hdev, dst, KEY_TYPE_LTK);
+ if (!key) {
+ entry = hci_find_adv_entry(hdev, dst);
+ if (entry)
+ cp.addr_type = entry->bdaddr_type;
+ else
+ cp.addr_type = 0x00;
+ } else {
+ cp.addr_type = key->addr_type;
+ }
+
+ hci_send_cmd(hdev, HCI_OP_LE_REMOVE_DEV_WHITE_LIST, sizeof(cp), &cp);
+}
+EXPORT_SYMBOL(hci_le_remove_dev_white_list);
+
void hci_acl_connect(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index bf854c3..0cd3c3f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -305,6 +305,12 @@
/* Read LE buffer size */
hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
+
+ /* Read LE clear white list */
+ hci_send_cmd(hdev, HCI_OP_LE_CLEAR_WHITE_LIST, 0, NULL);
+
+ /* Read LE white list size */
+ hci_send_cmd(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL);
}
static void hci_scan_req(struct hci_dev *hdev, unsigned long opt)
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 6e8500b..e5f43ec 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -426,6 +426,16 @@
hci_req_complete(hdev, HCI_OP_HOST_BUFFER_SIZE, status);
}
+static void hci_cc_le_clear_white_list(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ __u8 status = *((__u8 *) skb->data);
+
+ BT_DBG("%s status 0x%x", hdev->name, status);
+
+ hci_req_complete(hdev, HCI_OP_LE_CLEAR_WHITE_LIST, status);
+}
+
static void hci_cc_read_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_rp_read_ssp_mode *rp = (void *) skb->data;
@@ -913,6 +923,23 @@
hci_req_complete(hdev, HCI_OP_LE_READ_BUFFER_SIZE, rp->status);
}
+static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
+ struct sk_buff *skb)
+{
+ struct hci_rp_le_read_white_list_size *rp = (void *) skb->data;
+
+ BT_DBG("%s status 0x%x", hdev->name, rp->status);
+
+ if (rp->status)
+ return;
+
+ hdev->le_white_list_size = rp->size;
+
+ BT_DBG("%s le white list %d", hdev->name, hdev->le_white_list_size);
+
+ hci_req_complete(hdev, HCI_OP_LE_READ_WHITE_LIST_SIZE, rp->status);
+}
+
static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_rp_user_confirm_reply *rp = (void *) skb->data;
@@ -1767,7 +1794,7 @@
struct hci_ev_disconn_complete *ev = (void *) skb->data;
struct hci_conn *conn;
- BT_DBG("%s status %d", hdev->name, ev->status);
+ BT_DBG("%s status %d reason %d", hdev->name, ev->status, ev->reason);
if (ev->status) {
hci_dev_lock(hdev);
@@ -1785,7 +1812,7 @@
conn->state = BT_CLOSED;
if (conn->type == ACL_LINK || conn->type == LE_LINK)
- mgmt_disconnected(hdev->id, &conn->dst);
+ mgmt_disconnected(hdev->id, &conn->dst, ev->reason);
if (conn->type == LE_LINK)
del_timer(&conn->smp_timer);
@@ -2253,6 +2280,14 @@
hci_cc_le_read_buffer_size(hdev, skb);
break;
+ case HCI_OP_LE_READ_WHITE_LIST_SIZE:
+ hci_cc_le_read_white_list_size(hdev, skb);
+ break;
+
+ case HCI_OP_LE_CLEAR_WHITE_LIST:
+ hci_cc_le_clear_white_list(hdev, skb);
+ break;
+
case HCI_OP_READ_RSSI:
hci_cc_read_rssi(hdev, skb);
break;
@@ -3172,11 +3207,23 @@
{
struct hci_ev_le_conn_complete *ev = (void *) skb->data;
struct hci_conn *conn;
+ u8 white_list;
BT_DBG("%s status %d", hdev->name, ev->status);
hci_dev_lock(hdev);
+ /* Ignore event for LE cancel create conn whitelist */
+ if (ev->status && !bacmp(&ev->bdaddr, BDADDR_ANY))
+ goto unlock;
+
+ if (hci_conn_hash_lookup_ba(hdev, LE_LINK, BDADDR_ANY))
+ white_list = 1;
+ else
+ white_list = 0;
+
+ BT_DBG("w_list %d", white_list);
+
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr);
if (!conn) {
conn = hci_le_conn_add(hdev, &ev->bdaddr, ev->bdaddr_type);
@@ -3208,7 +3255,8 @@
hci_conn_hold_device(conn);
hci_conn_add_sysfs(conn);
- hci_proto_connect_cfm(conn, ev->status);
+ if (!white_list)
+ hci_proto_connect_cfm(conn, ev->status);
unlock:
hci_dev_unlock(hdev);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 72234c1..d7deaaf 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -229,6 +229,8 @@
memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
+ rp.le_white_list_size = hdev->le_white_list_size;
+
hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
@@ -1450,6 +1452,185 @@
return err;
}
+static int le_add_dev_white_list(struct sock *sk, u16 index,
+ unsigned char *data, u16 len)
+{
+ struct hci_dev *hdev;
+ struct mgmt_cp_le_add_dev_white_list *cp;
+ int err = 0;
+
+ BT_DBG("");
+
+ cp = (void *) data;
+
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_LE_ADD_DEV_WHITE_LIST,
+ EINVAL);
+
+ hdev = hci_dev_get(index);
+ if (!hdev)
+ return cmd_status(sk, index, MGMT_OP_LE_ADD_DEV_WHITE_LIST,
+ ENODEV);
+
+ hci_dev_lock_bh(hdev);
+
+ if (!test_bit(HCI_UP, &hdev->flags)) {
+ err = cmd_status(sk, index, MGMT_OP_LE_ADD_DEV_WHITE_LIST,
+ ENETDOWN);
+ goto failed;
+ }
+
+ hci_le_add_dev_white_list(hdev, &cp->bdaddr);
+
+failed:
+ hci_dev_unlock_bh(hdev);
+ hci_dev_put(hdev);
+
+ return err;
+}
+
+static int le_remove_dev_white_list(struct sock *sk, u16 index,
+ unsigned char *data, u16 len)
+{
+ struct hci_dev *hdev;
+ struct mgmt_cp_le_remove_dev_white_list *cp;
+ int err = 0;
+
+ BT_DBG("");
+
+ cp = (void *) data;
+
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_LE_REMOVE_DEV_WHITE_LIST,
+ EINVAL);
+
+ hdev = hci_dev_get(index);
+ if (!hdev)
+ return cmd_status(sk, index, MGMT_OP_LE_REMOVE_DEV_WHITE_LIST,
+ ENODEV);
+
+ hci_dev_lock_bh(hdev);
+
+ if (!test_bit(HCI_UP, &hdev->flags)) {
+ err = cmd_status(sk, index, MGMT_OP_LE_REMOVE_DEV_WHITE_LIST,
+ ENETDOWN);
+ goto failed;
+ }
+
+ hci_le_remove_dev_white_list(hdev, &cp->bdaddr);
+
+failed:
+ hci_dev_unlock_bh(hdev);
+ hci_dev_put(hdev);
+
+ return err;
+}
+
+static int le_create_conn_white_list(struct sock *sk, u16 index)
+{
+ struct hci_dev *hdev;
+ struct hci_conn *conn;
+ u8 sec_level, auth_type;
+ struct pending_cmd *cmd;
+ bdaddr_t bdaddr;
+ int err = 0;
+
+ BT_DBG("");
+
+ hdev = hci_dev_get(index);
+ if (!hdev)
+ return cmd_status(sk, index, MGMT_OP_LE_CREATE_CONN_WHITE_LIST,
+ ENODEV);
+
+ hci_dev_lock_bh(hdev);
+
+ if (!test_bit(HCI_UP, &hdev->flags)) {
+ err = cmd_status(sk, index, MGMT_OP_LE_CREATE_CONN_WHITE_LIST,
+ ENETDOWN);
+ goto failed;
+ }
+
+ cmd = mgmt_pending_add(sk, MGMT_OP_LE_CREATE_CONN_WHITE_LIST, index,
+ NULL, 0);
+ if (!cmd) {
+ err = -ENOMEM;
+ goto failed;
+ }
+
+ sec_level = BT_SECURITY_MEDIUM;
+ auth_type = HCI_AT_GENERAL_BONDING;
+ memset(&bdaddr, 0, sizeof(bdaddr));
+ conn = hci_le_connect(hdev, 0, BDADDR_ANY, sec_level, auth_type, NULL);
+ if (IS_ERR(conn)) {
+ err = PTR_ERR(conn);
+ mgmt_pending_remove(cmd);
+ }
+
+failed:
+ hci_dev_unlock_bh(hdev);
+ hci_dev_put(hdev);
+
+ return err;
+}
+
+static int le_cancel_create_conn_white_list(struct sock *sk, u16 index)
+{
+ struct hci_dev *hdev;
+ int err = 0;
+
+ BT_DBG("");
+
+ hdev = hci_dev_get(index);
+ if (!hdev)
+ return cmd_status(sk, index,
+ MGMT_OP_LE_CANCEL_CREATE_CONN_WHITE_LIST, ENODEV);
+
+ hci_dev_lock_bh(hdev);
+
+ if (!test_bit(HCI_UP, &hdev->flags)) {
+ err = cmd_status(sk, index,
+ MGMT_OP_LE_CANCEL_CREATE_CONN_WHITE_LIST, ENETDOWN);
+ goto failed;
+ }
+
+ hci_le_cancel_create_connect(hdev, BDADDR_ANY);
+
+failed:
+ hci_dev_unlock_bh(hdev);
+ hci_dev_put(hdev);
+
+ return err;
+}
+
+static int le_clear_white_list(struct sock *sk, u16 index)
+{
+ struct hci_dev *hdev;
+ int err;
+
+ BT_DBG("");
+
+ hdev = hci_dev_get(index);
+ if (!hdev)
+ return cmd_status(sk, index,
+ MGMT_OP_LE_CLEAR_WHITE_LIST, ENODEV);
+
+ hci_dev_lock_bh(hdev);
+
+ if (!test_bit(HCI_UP, &hdev->flags)) {
+ err = cmd_status(sk, index,
+ MGMT_OP_LE_CLEAR_WHITE_LIST, ENETDOWN);
+ goto failed;
+ }
+
+ err = hci_send_cmd(hdev, HCI_OP_LE_CLEAR_WHITE_LIST, 0, NULL);
+
+failed:
+ hci_dev_unlock_bh(hdev);
+ hci_dev_put(hdev);
+
+ return err;
+}
+
static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
u16 len)
{
@@ -2466,7 +2647,23 @@
case MGMT_OP_ENCRYPT_LINK:
err = encrypt_link(sk, index, buf + sizeof(*hdr), len);
break;
-
+ case MGMT_OP_LE_ADD_DEV_WHITE_LIST:
+ err = le_add_dev_white_list(sk, index, buf + sizeof(*hdr),
+ len);
+ break;
+ case MGMT_OP_LE_REMOVE_DEV_WHITE_LIST:
+ err = le_remove_dev_white_list(sk, index, buf + sizeof(*hdr),
+ len);
+ break;
+ case MGMT_OP_LE_CLEAR_WHITE_LIST:
+ err = le_clear_white_list(sk, index);
+ break;
+ case MGMT_OP_LE_CREATE_CONN_WHITE_LIST:
+ err = le_create_conn_white_list(sk, index);
+ break;
+ case MGMT_OP_LE_CANCEL_CREATE_CONN_WHITE_LIST:
+ err = le_cancel_create_conn_white_list(sk, index);
+ break;
default:
BT_DBG("Unknown op %u", opcode);
err = cmd_status(sk, index, opcode, 0x01);
@@ -2626,10 +2823,25 @@
int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 le)
{
struct mgmt_ev_connected ev;
+ struct pending_cmd *cmd;
+ struct hci_dev *hdev;
+
+ BT_DBG("hci%u", index);
+
+ hdev = hci_dev_get(index);
+
+ if (!hdev)
+ return -ENODEV;
bacpy(&ev.bdaddr, bdaddr);
ev.le = le;
+ cmd = mgmt_pending_find(MGMT_OP_LE_CREATE_CONN_WHITE_LIST, index);
+ if (cmd) {
+ BT_ERR("mgmt_connected remove mgmt pending white_list");
+ mgmt_pending_remove(cmd);
+ }
+
return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL);
}
@@ -2663,21 +2875,22 @@
mgmt_pending_remove(cmd);
}
-int mgmt_disconnected(u16 index, bdaddr_t *bdaddr)
+int mgmt_disconnected(u16 index, bdaddr_t *bdaddr, u8 reason)
{
struct mgmt_ev_disconnected ev;
struct sock *sk = NULL;
int err;
- mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk);
-
bacpy(&ev.bdaddr, bdaddr);
+ ev.reason = reason;
err = mgmt_event(MGMT_EV_DISCONNECTED, index, &ev, sizeof(ev), sk);
if (sk)
sock_put(sk);
+ mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk);
+
return err;
}
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 3d8981f..60e2fa9 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1030,6 +1030,35 @@
}
/*
+ * enable/disable flow on qdisc.
+ */
+void
+tc_qdisc_flow_control(struct net_device *dev, u32 tcm_handle, int enable_flow)
+{
+ struct Qdisc *q;
+ struct __qdisc_change_req {
+ struct nlattr attr;
+ struct tc_prio_qopt data;
+ } req = {
+ .attr = {sizeof(struct __qdisc_change_req), TCA_OPTIONS},
+ .data = {3, {1, 2, 2, 2, 1, 2, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}, 1}
+ };
+
+ /* override flow bit */
+ req.data.enable_flow = enable_flow;
+
+ /* look up using tcm handle */
+ q = qdisc_lookup(dev, tcm_handle);
+
+ /* call registered change function */
+ if (q) {
+ if (q->ops->change(q, &(req.attr)) != 0)
+ pr_err("tc_qdisc_flow_control: qdisc change failed");
+ }
+}
+EXPORT_SYMBOL(tc_qdisc_flow_control);
+
+/*
* Create/change qdisc.
*/
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 776e193..4c655c2 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1726,7 +1726,7 @@
$subjectline = $line;
$sublinenr = "#$linenr & ";
# Check for Subject line less than line limit
- if (length($1) > SHORTTEXT_LIMIT) {
+ if (length($1) > SHORTTEXT_LIMIT && !($1 =~ m/Revert\ \"/)) {
WARN("LONG_SUMMARY_LINE",
"summary line over " .
SHORTTEXT_LIMIT .
@@ -1738,7 +1738,7 @@
# headers so we are now in the shorttext.
$shorttext = IN_SHORTTEXT_BLANKLINE;
$shorttext_exspc = 4;
- if (length($1) > SHORTTEXT_LIMIT) {
+ if (length($1) > SHORTTEXT_LIMIT && !($1 =~ m/Revert\ \"/)) {
WARN("LONG_SUMMARY_LINE",
"summary line over " .
SHORTTEXT_LIMIT .
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 32565bc..67572c3 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -2414,7 +2414,7 @@
snd_soc_write(codec, SITAR_A_BIAS_CENTRAL_BG_CTL, 0x50);
if (SITAR_IS_1P0(sitar_core->version))
snd_soc_update_bits(codec, SITAR_A_LDO_H_MODE_1,
- 0xFF, 0x65);
+ 0xF3, 0x61);
usleep_range(1000, 1000);
} else {
pr_err("%s: Error, Invalid bandgap settings\n", __func__);
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 4758829..9881640 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -4472,8 +4472,8 @@
pr_err("%s: Slim close tx/rx wait timeout\n",
__func__);
ret = -EINVAL;
- }
- ret = 0;
+ } else
+ ret = 0;
break;
}
return ret;
@@ -4486,7 +4486,7 @@
struct snd_soc_codec *codec = w->codec;
struct tabla_priv *tabla_p = snd_soc_codec_get_drvdata(codec);
u32 j = 0;
- u32 ret = 0;
+ int ret = 0;
codec->control_data = dev_get_drvdata(codec->dev->parent);
tabla = codec->control_data;
@@ -4543,13 +4543,22 @@
ret = wcd9xxx_close_slim_sch_rx(tabla,
tabla_p->dai[j].ch_num,
tabla_p->dai[j].ch_tot);
- tabla_p->dai[j].rate = 0;
- memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
- tabla_p->dai[j].ch_tot));
- tabla_p->dai[j].ch_tot = 0;
ret = tabla_codec_enable_chmask(tabla_p,
SND_SOC_DAPM_POST_PMD,
j);
+ if (ret < 0) {
+ ret = wcd9xxx_disconnect_port(tabla,
+ tabla_p->dai[j].ch_num,
+ tabla_p->dai[j].ch_tot,
+ 1);
+ pr_info("%s: Disconnect RX port ret = %d\n",
+ __func__, ret);
+ }
+ tabla_p->dai[j].rate = 0;
+ memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
+ tabla_p->dai[j].ch_tot));
+ tabla_p->dai[j].ch_tot = 0;
+
if ((tabla != NULL) &&
(tabla->dev != NULL) &&
(tabla->dev->parent != NULL)) {
@@ -4569,7 +4578,7 @@
struct tabla_priv *tabla_p = snd_soc_codec_get_drvdata(codec);
/* index to the DAI ID, for now hardcoding */
u32 j = 0;
- u32 ret = 0;
+ int ret = 0;
codec->control_data = dev_get_drvdata(codec->dev->parent);
tabla = codec->control_data;
@@ -4626,13 +4635,21 @@
ret = wcd9xxx_close_slim_sch_tx(tabla,
tabla_p->dai[j].ch_num,
tabla_p->dai[j].ch_tot);
+ ret = tabla_codec_enable_chmask(tabla_p,
+ SND_SOC_DAPM_POST_PMD,
+ j);
+ if (ret < 0) {
+ ret = wcd9xxx_disconnect_port(tabla,
+ tabla_p->dai[j].ch_num,
+ tabla_p->dai[j].ch_tot, 0);
+ pr_info("%s: Disconnect TX port, ret = %d\n",
+ __func__, ret);
+ }
+
tabla_p->dai[j].rate = 0;
memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
tabla_p->dai[j].ch_tot));
tabla_p->dai[j].ch_tot = 0;
- ret = tabla_codec_enable_chmask(tabla_p,
- SND_SOC_DAPM_POST_PMD,
- j);
if ((tabla != NULL) &&
(tabla->dev != NULL) &&
(tabla->dev->parent != NULL)) {
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index 2959fe0..4b86f2b 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -1280,6 +1280,28 @@
return 0;
}
+static int msm_slim_4_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ pr_debug("%s()\n", __func__);
+
+ rate->min = rate->max = 48000;
+ if (rec_mode == INCALL_REC_STEREO)
+ channels->min = channels->max = 2;
+ else
+ channels->min = channels->max = 1;
+
+ pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
+ channels->min, channels->max);
+ return 0;
+}
+
static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -1944,7 +1966,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
- .be_hw_params_fixup = msm_be_hw_params_fixup,
+ .be_hw_params_fixup = msm_slim_4_tx_be_hw_params_fixup,
.ops = &msm_slimbus_4_be_ops,
},
{
@@ -2010,6 +2032,9 @@
return -ENODEV;
}
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
+ bottom_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(16);
+
mbhc_cfg.calibration = def_tabla_mbhc_cal();
if (!mbhc_cfg.calibration) {
pr_err("Calibration data allocation failed\n");
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index f5bbf56..be0395b 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -133,7 +133,7 @@
static int msm_ext_top_spk_pamp;
static int msm_slim_0_rx_ch = 1;
static int msm_slim_0_tx_ch = 1;
-static int msm_hdmi_rx_ch = 2;
+static int msm_hdmi_rx_ch = 8;
static struct clk *codec_clk;
static int clk_users;
@@ -515,14 +515,15 @@
static const char *spk_function[] = {"Off", "On"};
static const char *slim0_rx_ch_text[] = {"One", "Two"};
static const char *slim0_tx_ch_text[] = {"One", "Two", "Three", "Four"};
-static const char *hdmi_rx_ch_text[] = {"Two", "Three", "Four", "Five", "Six"};
+static const char * const hdmi_rx_ch_text[] = {"Two", "Three", "Four",
+ "Five", "Six", "Seven", "Eight"};
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),
- SOC_ENUM_SINGLE_EXT(5, hdmi_rx_ch_text),
+ SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text),
};
@@ -627,7 +628,7 @@
#undef S
#define S(X, Y) ((TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla_cal)->X) = (Y))
S(v_no_mic, 30);
- S(v_hs_max, 1550);
+ S(v_hs_max, 2400);
#undef S
#define S(X, Y) ((TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal)->X) = (Y))
S(c[0], 62);
@@ -645,24 +646,24 @@
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] = 38;
- btn_low[2] = 39;
- btn_high[2] = 64;
- btn_low[3] = 65;
- btn_high[3] = 91;
- btn_low[4] = 92;
- btn_high[4] = 115;
- btn_low[5] = 116;
- btn_high[5] = 141;
- btn_low[6] = 142;
- btn_high[6] = 163;
- btn_low[7] = 164;
- btn_high[7] = 250;
+ btn_high[0] = 20;
+ btn_low[1] = 21;
+ btn_high[1] = 62;
+ btn_low[2] = 62;
+ btn_high[2] = 104;
+ btn_low[3] = 105;
+ btn_high[3] = 143;
+ btn_low[4] = 144;
+ btn_high[4] = 181;
+ btn_low[5] = 182;
+ btn_high[5] = 218;
+ btn_low[6] = 219;
+ btn_high[6] = 254;
+ btn_low[7] = 255;
+ btn_high[7] = 330;
n_ready = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_READY);
- n_ready[0] = 48;
- n_ready[1] = 38;
+ n_ready[0] = 80;
+ n_ready[1] = 68;
n_cic = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_CIC);
n_cic[0] = 60;
n_cic[1] = 47;
@@ -1486,6 +1487,9 @@
return -ENODEV;
}
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917)
+ bottom_spk_pamp_gpio = PM8921_GPIO_PM_TO_SYS(16);
+
mbhc_cfg.calibration = def_tabla_mbhc_cal();
if (!mbhc_cfg.calibration) {
pr_err("Calibration data allocation failed\n");
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 1dbd698..dd576c4 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -26,6 +26,7 @@
#include <sound/initval.h>
#include <sound/control.h>
#include <sound/q6asm.h>
+#include <sound/pcm_params.h>
#include <asm/dma.h>
#include <linux/dma-mapping.h>
#include <linux/android_pmem.h>
@@ -82,12 +83,12 @@
.rate_min = 8000,
.rate_max = 48000,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 8,
.buffer_bytes_max = 1200 * 1024 * 2,
- .period_bytes_min = 4800,
+ .period_bytes_min = 2400,
.period_bytes_max = 1200 * 1024,
.periods_min = 2,
- .periods_max = 512,
+ .periods_max = 1024,
.fifo_size = 0,
};
@@ -134,8 +135,6 @@
break;
} else
atomic_set(&prtd->pending_buffer, 0);
- if (runtime->status->hw_ptr >= runtime->control->appl_ptr)
- break;
buf = prtd->audio_client->port[IN].buf;
pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n",
__func__, prtd->pcm_count, prtd->out_head);
@@ -292,6 +291,7 @@
struct asm_aac_cfg aac_cfg;
struct asm_wma_cfg wma_cfg;
struct asm_wmapro_cfg wma_pro_cfg;
+ struct asm_amrwbplus_cfg amrwb_cfg;
int ret;
pr_debug("compressed stream prepare\n");
@@ -389,6 +389,27 @@
return ret;
}
break;
+ case SND_AUDIOCODEC_AMRWB:
+ pr_debug("SND_AUDIOCODEC_AMRWB\n");
+ ret = q6asm_media_format_block(prtd->audio_client,
+ compr->codec);
+ if (ret < 0) {
+ pr_err("%s: CMD Format block failed\n", __func__);
+ return ret;
+ }
+ break;
+ case SND_AUDIOCODEC_AMRWBPLUS:
+ pr_debug("SND_AUDIOCODEC_AMRWBPLUS\n");
+ memset(&amrwb_cfg, 0x0, sizeof(struct asm_amrwbplus_cfg));
+ amrwb_cfg.size_bytes = sizeof(struct asm_amrwbplus_cfg);
+ pr_debug("calling q6asm_media_format_block_amrwbplus");
+ ret = q6asm_media_format_block_amrwbplus(prtd->audio_client,
+ &amrwb_cfg);
+ if (ret < 0) {
+ pr_err("%s: CMD Format block failed\n", __func__);
+ return ret;
+ }
+ break;
default:
return -EINVAL;
}
@@ -506,7 +527,7 @@
{
pr_debug("%s\n", __func__);
/* MP3 Block */
- compr->info.compr_cap.num_codecs = 1;
+ compr->info.compr_cap.num_codecs = 10;
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;
@@ -519,6 +540,8 @@
compr->info.compr_cap.codecs[5] = SND_AUDIOCODEC_DTS;
compr->info.compr_cap.codecs[6] = SND_AUDIOCODEC_DTS_LBR;
compr->info.compr_cap.codecs[7] = SND_AUDIOCODEC_DTS_PASS_THROUGH;
+ compr->info.compr_cap.codecs[8] = SND_AUDIOCODEC_AMRWB;
+ compr->info.compr_cap.codecs[9] = SND_AUDIOCODEC_AMRWBPLUS;
/* Add new codecs here */
}
@@ -548,7 +571,6 @@
}
prtd = &compr->prtd;
prtd->substream = substream;
- prtd->audio_client->perf_mode = false;
prtd->audio_client = q6asm_audio_client_alloc(
(app_cb)compr_event_handler, compr);
if (!prtd->audio_client) {
@@ -556,7 +578,7 @@
kfree(prtd);
return -ENOMEM;
}
-
+ prtd->audio_client->perf_mode = false;
pr_info("%s: session ID %d\n", __func__, prtd->audio_client->session);
prtd->session_id = prtd->audio_client->session;
@@ -791,7 +813,17 @@
pr_err("%s: Set IO mode failed\n", __func__);
return -ENOMEM;
}
-
+ /* Modifying kernel hardware params based on userspace config */
+ if (params_periods(params) > 0 &&
+ (params_periods(params) != runtime->hw.periods_max)) {
+ runtime->hw.periods_max = params_periods(params);
+ }
+ if (params_period_bytes(params) > 0 &&
+ (params_period_bytes(params) != runtime->hw.period_bytes_min)) {
+ runtime->hw.period_bytes_min = params_period_bytes(params);
+ }
+ runtime->hw.buffer_bytes_max =
+ runtime->hw.period_bytes_min * runtime->hw.periods_max;
ret = q6asm_audio_client_buf_alloc_contiguous(dir,
prtd->audio_client,
runtime->hw.period_bytes_min,
@@ -907,10 +939,17 @@
pr_debug("SND_AUDIOCODEC_DTS\n");
compr->codec = FORMAT_DTS_LBR;
break;
- default:
- pr_debug("FORMAT_LINEAR_PCM\n");
- compr->codec = FORMAT_LINEAR_PCM;
+ case SND_AUDIOCODEC_AMRWB:
+ pr_debug("msm_compr_ioctl SND_AUDIOCODEC_AMRWB\n");
+ compr->codec = FORMAT_AMRWB;
break;
+ case SND_AUDIOCODEC_AMRWBPLUS:
+ pr_debug("msm_compr_ioctl SND_AUDIOCODEC_AMRWBPLUS\n");
+ compr->codec = FORMAT_AMR_WB_PLUS;
+ break;
+ default:
+ pr_err("msm_compr_ioctl failed..unknown codec\n");
+ return -EFAULT;
}
return 0;
case SNDRV_PCM_IOCTL1_RESET:
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 011ff29..011912e 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -82,7 +82,7 @@
SNDRV_PCM_RATE_KNOT),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 6,
+ .channels_max = 8,
.rate_min = 8000,
.rate_max = 48000,
},
@@ -173,7 +173,7 @@
SNDRV_PCM_RATE_KNOT),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 6,
+ .channels_max = 8,
.rate_min = 8000,
.rate_max = 48000,
},
diff --git a/sound/soc/msm/msm-dai-q6-hdmi.c b/sound/soc/msm/msm-dai-q6-hdmi.c
index c082ed7..2b3dd5f 100644
--- a/sound/soc/msm/msm-dai-q6-hdmi.c
+++ b/sound/soc/msm/msm-dai-q6-hdmi.c
@@ -111,6 +111,13 @@
dai_data->port_config.hdmi_multi_ch.channel_allocation =
channel_allocation;
break;
+ case 8:
+ channel_allocation = 0x1F;
+ hdmi_msm_audio_info_setup(1, MSM_HDMI_AUDIO_CHANNEL_8,
+ channel_allocation, level_shift, down_mix);
+ dai_data->port_config.hdmi_multi_ch.channel_allocation =
+ channel_allocation;
+ break;
default:
dev_err(dai->dev, "invalid Channels = %u\n",
dai_data->channels);
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 89b709f..ee1ab79 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -465,6 +465,9 @@
dai_data->channels = params_channels(params);
switch (dai_data->channels) {
case 2:
+ case 4:
+ case 6:
+ case 8:
dai_data->port_config.mi2s.channel = MSM_AFE_STEREO;
break;
case 1:
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
index 2d23b48..10b8f7a 100644
--- a/sound/soc/msm/msm-multi-ch-pcm-q6.c
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -83,7 +83,7 @@
.rate_min = 8000,
.rate_max = 48000,
.channels_min = 1,
- .channels_max = 6,
+ .channels_max = 8,
.buffer_bytes_max = PLAYBACK_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE,
.period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
.period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
@@ -330,7 +330,6 @@
return -ENOMEM;
}
prtd->substream = substream;
- prtd->audio_client->perf_mode = false;
prtd->audio_client = q6asm_audio_client_alloc(
(app_cb)event_handler, prtd);
if (!prtd->audio_client) {
@@ -338,6 +337,7 @@
kfree(prtd);
return -ENOMEM;
}
+ prtd->audio_client->perf_mode = false;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
runtime->hw = msm_pcm_hardware_playback;
ret = q6asm_open_write(prtd->audio_client,
diff --git a/sound/soc/msm/msm-pcm-lpa.c b/sound/soc/msm/msm-pcm-lpa.c
index 116ce3e..ff0fb3b 100644
--- a/sound/soc/msm/msm-pcm-lpa.c
+++ b/sound/soc/msm/msm-pcm-lpa.c
@@ -282,7 +282,6 @@
}
runtime->hw = msm_pcm_hardware;
prtd->substream = substream;
- prtd->audio_client->perf_mode = false;
prtd->audio_client = q6asm_audio_client_alloc(
(app_cb)event_handler, prtd);
if (!prtd->audio_client) {
@@ -290,6 +289,7 @@
kfree(prtd);
return -ENOMEM;
}
+ prtd->audio_client->perf_mode = false;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM);
if (ret < 0) {
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 374357d..5f0a20e 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -1302,6 +1302,9 @@
SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_INT_BT_SCO_RX,
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_INT_BT_SCO_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = {
@@ -1317,6 +1320,9 @@
SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_INT_FM_RX,
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_INT_FM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = {
@@ -1332,6 +1338,9 @@
SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_AFE_PCM_RX,
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_AFE_PCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new auxpcm_rx_mixer_controls[] = {
@@ -1347,6 +1356,9 @@
SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_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_AUXPCM_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new sec_auxpcm_rx_mixer_controls[] = {
@@ -1407,6 +1419,18 @@
SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_MI2S_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 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_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
@@ -2322,6 +2346,7 @@
{"MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
{"MI2S_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"MI2S_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
{"MI2S_RX", NULL, "MI2S_RX Audio Mixer"},
{"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
@@ -2336,24 +2361,30 @@
{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
{"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
{"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX Audio Mixer"},
{"INTERNAL_FM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"INTERNAL_FM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"INTERNAL_FM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
{"INTERNAL_FM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"INTERNAL_FM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
{"INT_FM_RX", NULL, "INTERNAL_FM_RX Audio Mixer"},
{"AFE_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"AFE_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"AFE_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
{"AFE_PCM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"AFE_PCM_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
{"PCM_RX", NULL, "AFE_PCM_RX Audio Mixer"},
{"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
+ {"MultiMedia5 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
{"MultiMedia1 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
+ {"MultiMedia5 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"MultiMedia1 Mixer", "AFE_PCM_TX", "PCM_TX"},
+ {"MultiMedia5 Mixer", "AFE_PCM_TX", "PCM_TX"},
{"MM_UL1", NULL, "MultiMedia1 Mixer"},
{"MultiMedia2 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"MM_UL2", NULL, "MultiMedia2 Mixer"},
@@ -2364,6 +2395,7 @@
{"AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"AUX_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
{"AUX_PCM_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"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"},
diff --git a/sound/soc/msm/msm-pcm.h b/sound/soc/msm/msm-pcm.h
index 6e1325b..867116a 100644
--- a/sound/soc/msm/msm-pcm.h
+++ b/sound/soc/msm/msm-pcm.h
@@ -27,7 +27,7 @@
#include <mach/qdsp5/qdsp5audrecmsg.h>
#include <mach/qdsp5/qdsp5audpreproccmdi.h>
#include <mach/qdsp5/qdsp5audpreprocmsg.h>
-
+#include <mach/qdsp5/qdsp5audpp.h>
#include <../arch/arm/mach-msm/qdsp5/adsp.h>
#include <../arch/arm/mach-msm/qdsp5/audmgr.h>
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index a577b6a..c8d4b02 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -38,6 +38,7 @@
#define SPK_AMP_POS 0x1
#define SPK_AMP_NEG 0x2
#define SPKR_BOOST_GPIO 15
+#define LEFT_SPKR_AMPL_GPIO 15
#define DEFAULT_PMIC_SPK_GAIN 0x0D
#define SITAR_EXT_CLK_RATE 12288000
@@ -121,6 +122,24 @@
return 1;
}
+static int msm8930_cfg_spkr_gpio(int gpio,
+ int enable, const char *gpio_label)
+{
+ int ret = 0;
+
+ pr_debug("%s: Configure %s GPIO %u",
+ __func__, gpio_label, gpio);
+ ret = gpio_request(gpio, gpio_label);
+ if (ret)
+ return ret;
+
+ pr_debug("%s: Enable %s gpio %u\n",
+ __func__, gpio_label, gpio);
+ gpio_direction_output(gpio, enable);
+
+ return ret;
+}
+
static void msm8960_ext_spk_power_amp_on(u32 spk)
{
int ret = 0;
@@ -139,24 +158,30 @@
if ((msm8930_ext_spk_pamp & SPK_AMP_POS) &&
(msm8930_ext_spk_pamp & SPK_AMP_NEG)) {
- if (machine_is_msm8930_mtp()
- || machine_is_msm8930_fluid()) {
- pr_debug("%s: Configure Speaker Boost GPIO %u",
- __func__, SPKR_BOOST_GPIO);
- ret = gpio_request(SPKR_BOOST_GPIO,
- "SPKR_BOOST_EN");
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
+ ret = msm8930_cfg_spkr_gpio(
+ LEFT_SPKR_AMPL_GPIO,
+ 1, "LEFT_SPKR_AMPL");
if (ret) {
- pr_err("%s: Failed to configure speaker boost "
- "gpio %u\n", __func__, SPKR_BOOST_GPIO);
+ pr_err("%s: Failed to config ampl gpio %u\n",
+ __func__, LEFT_SPKR_AMPL_GPIO);
return;
}
+ } else {
- pr_debug("%s: Enable Speaker boost gpio %u\n",
- __func__, SPKR_BOOST_GPIO);
- gpio_direction_output(SPKR_BOOST_GPIO, 1);
+ if (machine_is_msm8930_mtp()
+ || machine_is_msm8930_fluid()) {
+ ret = msm8930_cfg_spkr_gpio(
+ SPKR_BOOST_GPIO, 1, "SPKR_BOOST");
+ if (ret) {
+ pr_err("%s: Failure: spkr boost gpio %u\n",
+ __func__, SPKR_BOOST_GPIO);
+ return;
+ }
+ }
+ pm8xxx_spk_enable(MSM8930_SPK_ON);
}
- pm8xxx_spk_enable(MSM8930_SPK_ON);
pr_debug("%s: slepping 4 ms after turning on external "
" Left Speaker Ampl\n", __func__);
usleep_range(4000, 4000);
@@ -175,6 +200,13 @@
if (spk & (SPK_AMP_POS | SPK_AMP_NEG)) {
if (!msm8930_ext_spk_pamp)
return;
+
+ if (socinfo_get_pmic_model() == PMIC_MODEL_PM8917) {
+ gpio_free(LEFT_SPKR_AMPL_GPIO);
+ msm8930_ext_spk_pamp = 0;
+ return;
+ }
+
if (machine_is_msm8930_mtp()
|| machine_is_msm8930_fluid()) {
pr_debug("%s: Free speaker boost gpio %u\n",
@@ -463,7 +495,8 @@
{
int ret = 0;
msm8930_pmic_spk_gain = ucontrol->value.integer.value[0];
- ret = pm8xxx_spk_gain(msm8930_pmic_spk_gain);
+ if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917)
+ ret = pm8xxx_spk_gain(msm8930_pmic_spk_gain);
pr_debug("%s: msm8930_pmic_spk_gain = %d"
" ucontrol->value.integer.value[0] = %d\n", __func__,
msm8930_pmic_spk_gain,
@@ -660,8 +693,10 @@
mbhc_cfg.gpio_irq = gpio_to_irq(mbhc_cfg.gpio);
sitar_hs_detect(codec, &mbhc_cfg);
- /* Initialize default PMIC speaker gain */
- pm8xxx_spk_gain(DEFAULT_PMIC_SPK_GAIN);
+ if (socinfo_get_pmic_model() != PMIC_MODEL_PM8917) {
+ /* Initialize default PMIC speaker gain */
+ pm8xxx_spk_gain(DEFAULT_PMIC_SPK_GAIN);
+ }
return 0;
}
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 040bbe0..e98fe64 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -715,20 +715,20 @@
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] = 20;
- btn_low[1] = 21;
- btn_high[1] = 62;
- btn_low[2] = 63;
- btn_high[2] = 104;
- btn_low[3] = 105;
- btn_high[3] = 143;
- btn_low[4] = 144;
- btn_high[4] = 181;
- btn_low[5] = 182;
- btn_high[5] = 218;
- btn_low[6] = 219;
- btn_high[6] = 254;
- btn_low[7] = 255;
+ 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;
n_ready = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_READY);
n_ready[0] = 80;
@@ -1754,11 +1754,18 @@
return ret;
}
- if (msm8960_configure_headset_mic_gpios()) {
- pr_err("%s Fail to configure headset mic gpios\n", __func__);
+ if (cpu_is_msm8960()) {
+ if (msm8960_configure_headset_mic_gpios()) {
+ pr_err("%s Fail to configure headset mic gpios\n",
+ __func__);
+ msm8960_headset_gpios_configured = 0;
+ } else
+ msm8960_headset_gpios_configured = 1;
+ } else {
msm8960_headset_gpios_configured = 0;
- } else
- msm8960_headset_gpios_configured = 1;
+ pr_debug("%s headset GPIO 23 and 35 not configured msm960ab",
+ __func__);
+ }
mutex_init(&cdc_mclk_mutex);
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index f50b915..545a5b9 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -823,6 +823,22 @@
.be_id = MSM_FRONTEND_DAI_VOIP,
},
{
+ .name = "Circuit-Switch Voice",
+ .stream_name = "CS-Voice",
+ .cpu_dai_name = "CS-VOICE",
+ .platform_name = "msm-pcm-voice",
+ .dynamic = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_CS_VOICE,
+ },
+ {
.name = "MSM8974 LPA",
.stream_name = "LPA",
.cpu_dai_name = "MultiMedia3",
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index 6724c545..c6970f1 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -250,6 +250,18 @@
}
this_adm.apr = NULL;
}
+ pr_debug("Resetting calibration blocks");
+ for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
+ /* Device calibration */
+ mem_addr_audproc[i].cal_size = 0;
+ mem_addr_audproc[i].cal_kvaddr = 0;
+ mem_addr_audproc[i].cal_paddr = 0;
+
+ /* Volume calibration */
+ mem_addr_audvol[i].cal_size = 0;
+ mem_addr_audvol[i].cal_kvaddr = 0;
+ mem_addr_audvol[i].cal_paddr = 0;
+ }
return 0;
}
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index 76940ee..1aac158 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -1526,6 +1526,14 @@
case FORMAT_DTS_LBR:
open.format = DTS_LBR;
break;
+ case FORMAT_AMRWB:
+ open.format = AMRWB_FS;
+ pr_debug("q6asm_open_write FORMAT_AMRWB");
+ break;
+ case FORMAT_AMR_WB_PLUS:
+ open.format = AMR_WB_PLUS;
+ pr_debug("q6asm_open_write FORMAT_AMR_WB_PLUS");
+ break;
default:
pr_err("%s: Invalid format[%d]\n", __func__, format);
goto fail_cmd;
@@ -2372,7 +2380,56 @@
return -EINVAL;
}
+int q6asm_media_format_block_amrwbplus(struct audio_client *ac,
+ struct asm_amrwbplus_cfg *cfg)
+{
+ struct asm_stream_media_format_update fmt;
+ int rc = 0;
+ pr_debug("q6asm_media_format_block_amrwbplus");
+ pr_debug("%s:session[%d]band-mode[%d]frame-fmt[%d]ch[%d]\n",
+ __func__,
+ ac->session,
+ cfg->amr_band_mode,
+ cfg->amr_frame_fmt,
+ cfg->num_channels);
+
+ q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
+
+ fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
+
+ fmt.format = AMR_WB_PLUS;
+ fmt.cfg_size = cfg->size_bytes;
+
+ fmt.write_cfg.amrwbplus_cfg.size_bytes = cfg->size_bytes;
+ fmt.write_cfg.amrwbplus_cfg.version = cfg->version;
+ fmt.write_cfg.amrwbplus_cfg.num_channels = cfg->num_channels;
+ fmt.write_cfg.amrwbplus_cfg.amr_band_mode = cfg->amr_band_mode;
+ fmt.write_cfg.amrwbplus_cfg.amr_dtx_mode = cfg->amr_dtx_mode;
+ fmt.write_cfg.amrwbplus_cfg.amr_frame_fmt = cfg->amr_frame_fmt;
+ fmt.write_cfg.amrwbplus_cfg.amr_lsf_idx = cfg->amr_lsf_idx;
+
+ pr_debug("%s: num_channels=%x amr_band_mode=%d amr_frame_fmt=%d\n",
+ __func__,
+ cfg->num_channels,
+ cfg->amr_band_mode,
+ cfg->amr_frame_fmt);
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
+ if (rc < 0) {
+ pr_err("%s:Comamnd media format update failed..\n", __func__);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return -EINVAL;
+}
int q6asm_media_format_block_multi_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg)
{
@@ -2444,6 +2501,9 @@
case FORMAT_AMRWB:
fmt.format = AMRWB_FS;
break;
+ case FORMAT_AMR_WB_PLUS:
+ fmt.format = AMR_WB_PLUS;
+ break;
case FORMAT_AMRNB:
fmt.format = AMRNB_FS;
break;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
index 206e881..f1e0f3a 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-voice-v2.c
@@ -466,6 +466,9 @@
static __devinit int msm_pcm_probe(struct platform_device *pdev)
{
+ if (pdev->dev.of_node)
+ dev_set_name(&pdev->dev, "%s", "msm-pcm-voice");
+
pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
return snd_soc_register_platform(&pdev->dev,
&msm_soc_platform);
@@ -477,10 +480,17 @@
return 0;
}
+static const struct of_device_id msm_voice_dt_match[] = {
+ {.compatible = "qcom,msm-pcm-voice"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, msm_voice_dt_match);
+
static struct platform_driver msm_pcm_driver = {
.driver = {
.name = "msm-pcm-voice",
.owner = THIS_MODULE,
+ .of_match_table = msm_voice_dt_match,
},
.probe = msm_pcm_probe,
.remove = __devexit_p(msm_pcm_remove),
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index a3af263..392b9b0 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -136,7 +136,7 @@
kfree(temp);
return -EFAULT;
}
- if (!strict_strtol(temp, 10, &out_enable_flag)) {
+ if (!kstrtol(temp, 10, &out_enable_flag)) {
kfree(temp);
return count;
}
@@ -177,7 +177,7 @@
kfree(temp);
return -EFAULT;
}
- if (!strict_strtol(temp, 10, &in_enable_flag)) {
+ if (!kstrtol(temp, 10, &in_enable_flag)) {
kfree(temp);
return count;
}
@@ -347,7 +347,7 @@
int rc = 0;
pr_debug("%s: Session id %d\n", __func__, ac->session);
mutex_lock(&ac->cmd_lock);
- if (ac->io_mode == SYNC_IO_MODE) {
+ if (ac->io_mode & SYNC_IO_MODE) {
port = &ac->port[dir];
if (!port->buf) {
mutex_unlock(&ac->cmd_lock);
@@ -454,7 +454,7 @@
if (!ac || !ac->session)
return;
pr_debug("%s: Session id %d\n", __func__, ac->session);
- if (ac->io_mode == SYNC_IO_MODE) {
+ if (ac->io_mode & SYNC_IO_MODE) {
for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
port = &ac->port[loopcnt];
if (!port->buf)
@@ -603,7 +603,7 @@
if (ac->session <= 0 || ac->session > 8)
goto fail;
- if (ac->io_mode == SYNC_IO_MODE) {
+ if (ac->io_mode & SYNC_IO_MODE) {
if (ac->port[dir].buf) {
pr_debug("%s: buffer already allocated\n", __func__);
return 0;
@@ -973,7 +973,7 @@
pr_debug("%s: Rxed opcode[0x%x] status[0x%x] token[%d]",
__func__, payload[0], payload[1],
data->token);
- if (ac->io_mode == SYNC_IO_MODE) {
+ if (ac->io_mode & SYNC_IO_MODE) {
if (port->buf == NULL) {
pr_err("%s: Unexpected Write Done\n",
__func__);
@@ -1025,7 +1025,7 @@
payload[READDONE_IDX_SEQ_ID],
payload[READDONE_IDX_NUMFRAMES]);
- if (ac->io_mode == SYNC_IO_MODE) {
+ if (ac->io_mode & SYNC_IO_MODE) {
if (port->buf == NULL) {
pr_err("%s: Unexpected Write Done\n", __func__);
return -EINVAL;
@@ -1092,7 +1092,7 @@
if (!ac || ((dir != IN) && (dir != OUT)))
return NULL;
- if (ac->io_mode == SYNC_IO_MODE) {
+ if (ac->io_mode & SYNC_IO_MODE) {
port = &ac->port[dir];
mutex_lock(&port->lock);
@@ -1186,7 +1186,7 @@
if (!ac || (dir != OUT))
return ret;
- if (ac->io_mode == SYNC_IO_MODE) {
+ if (ac->io_mode & SYNC_IO_MODE) {
port = &ac->port[dir];
mutex_lock(&port->lock);
@@ -2825,7 +2825,7 @@
pr_err("APR handle NULL\n");
return -EINVAL;
}
- if (ac->io_mode == SYNC_IO_MODE) {
+ if (ac->io_mode & SYNC_IO_MODE) {
port = &ac->port[OUT];
q6asm_add_hdr(ac, &read.hdr, sizeof(read), FALSE);
@@ -2888,7 +2888,7 @@
pr_err("APR handle NULL\n");
return -EINVAL;
}
- if (ac->io_mode == SYNC_IO_MODE) {
+ if (ac->io_mode & SYNC_IO_MODE) {
port = &ac->port[OUT];
q6asm_add_hdr_async(ac, &read.hdr, sizeof(read), FALSE);
@@ -2969,12 +2969,10 @@
write.timestamp_lsw = param->lsw_ts;
liomode = (ASYNC_IO_MODE | NT_MODE);
- if (ac->io_mode == liomode) {
- pr_info("%s: subtracting 32 for header\n", __func__);
+ if (ac->io_mode == liomode)
lbuf_addr_lsw = (write.buf_addr_lsw - 32);
- } else{
+ else
lbuf_addr_lsw = write.buf_addr_lsw;
- }
pr_debug("%s: token[0x%x], buf_addr_lsw[0x%x], buf_size[0x%x], ts_msw[0x%x], ts_lsw[0x%x], lbuf_addr_lsw: 0x[%x]\n",
__func__,
@@ -3034,12 +3032,10 @@
read.buf_size = param->len;
read.seq_id = param->uid;
liomode = (NT_MODE | ASYNC_IO_MODE);
- if (ac->io_mode == liomode) {
- pr_info("%s: subtracting 32 for header\n", __func__);
+ if (ac->io_mode == liomode)
lbuf_addr_lsw = (read.buf_addr_lsw - 32);
- } else{
+ else
lbuf_addr_lsw = read.buf_addr_lsw;
- }
list_for_each_safe(ptr, next, &ac->port[IN].mem_map_handle) {
buf_node = list_entry(ptr, struct asm_buffer_node, list);
@@ -3075,7 +3071,7 @@
return -EINVAL;
}
pr_debug("%s: session[%d] len=%d", __func__, ac->session, len);
- if (ac->io_mode == SYNC_IO_MODE) {
+ if (ac->io_mode & SYNC_IO_MODE) {
port = &ac->port[IN];
q6asm_add_hdr(ac, &write.hdr, sizeof(write),
@@ -3143,7 +3139,7 @@
return -EINVAL;
}
pr_debug("%s: session[%d] len=%d", __func__, ac->session, len);
- if (ac->io_mode == SYNC_IO_MODE) {
+ if (ac->io_mode & SYNC_IO_MODE) {
port = &ac->port[IN];
q6asm_add_hdr_async(ac, &write.hdr, sizeof(write),
@@ -3352,7 +3348,7 @@
int loopcnt = 0;
struct audio_port_data *port = NULL;
- if (ac->io_mode == SYNC_IO_MODE) {
+ if (ac->io_mode & SYNC_IO_MODE) {
mutex_lock(&ac->cmd_lock);
for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
port = &ac->port[loopcnt];
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 4e11dfe..f84b456 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -50,19 +50,6 @@
static int voice_send_set_device_cmd(struct voice_data *v);
static int voice_send_disable_vocproc_cmd(struct voice_data *v);
static int voice_send_vol_index_cmd(struct voice_data *v);
-static int voice_send_cvp_map_memory_cmd(struct voice_data *v);
-static int voice_send_cvp_unmap_memory_cmd(struct voice_data *v);
-static int voice_send_cvs_map_memory_cmd(struct voice_data *v);
-static int voice_send_cvs_unmap_memory_cmd(struct voice_data *v);
-static int voice_send_cvs_register_cal_cmd(struct voice_data *v);
-static int voice_send_cvs_deregister_cal_cmd(struct voice_data *v);
-static int voice_send_cvp_register_cal_cmd(struct voice_data *v);
-static int voice_send_cvp_deregister_cal_cmd(struct voice_data *v);
-static int voice_send_cvp_register_vol_cal_table_cmd(struct voice_data *v);
-static int voice_send_cvp_deregister_vol_cal_table_cmd(struct voice_data *v);
-static int voice_send_set_widevoice_enable_cmd(struct voice_data *v);
-static int voice_send_set_pp_enable_cmd(struct voice_data *v,
- uint32_t module_id, int enable);
static int voice_cvs_stop_playback(struct voice_data *v);
static int voice_cvs_start_playback(struct voice_data *v);
static int voice_cvs_start_record(struct voice_data *v, uint32_t rec_mode);
@@ -223,7 +210,6 @@
goto err;
}
- rtac_set_voice_handle(RTAC_CVS, common.apr_q6_cvs);
}
if (common.apr_q6_cvp == NULL) {
@@ -238,7 +224,6 @@
goto err;
}
- rtac_set_voice_handle(RTAC_CVP, common.apr_q6_cvp);
}
mutex_unlock(&common.common_lock);
@@ -249,7 +234,6 @@
if (common.apr_q6_cvs != NULL) {
apr_deregister(common.apr_q6_cvs);
common.apr_q6_cvs = NULL;
- rtac_set_voice_handle(RTAC_CVS, NULL);
}
if (common.apr_q6_mvm != NULL) {
apr_deregister(common.apr_q6_mvm);
@@ -278,7 +262,8 @@
return -EINVAL;
}
pr_debug("%s: VoLTE command to MVM\n", __func__);
- if (is_volte_session(v->session_id)) {
+ if (is_volte_session(v->session_id) ||
+ is_voice_session(v->session_id)) {
mvm_handle = voice_get_mvm_handle(v);
mvm_voice_ctl_cmd.hdr.hdr_field = APR_HDR_FIELD(
APR_MSG_TYPE_SEQ_CMD,
@@ -1211,765 +1196,6 @@
return -EINVAL;
}
-static int voice_send_cvs_register_cal_cmd(struct voice_data *v)
-{
- struct cvs_register_cal_data_cmd cvs_reg_cal_cmd;
- struct acdb_cal_block cal_block;
- int ret = 0;
- void *apr_cvs;
- u16 cvs_handle;
- uint32_t cal_paddr;
-
- /* get the cvs cal data */
- get_all_vocstrm_cal(&cal_block);
- if (cal_block.cal_size == 0)
- goto fail;
-
- if (v == NULL) {
- pr_err("%s: v is NULL\n", __func__);
- return -EINVAL;
- }
- apr_cvs = common.apr_q6_cvs;
-
- if (!apr_cvs) {
- pr_err("%s: apr_cvs is NULL.\n", __func__);
- return -EINVAL;
- }
-
- if (is_voip_session(v->session_id)) {
- if (common.cvs_cal.buf) {
- cal_paddr = common.cvs_cal.phy;
-
- memcpy(common.cvs_cal.buf,
- (void *) cal_block.cal_kvaddr,
- cal_block.cal_size);
- } else {
- return -EINVAL;
- }
- } else {
- cal_paddr = cal_block.cal_paddr;
- }
-
- cvs_handle = voice_get_cvs_handle(v);
-
- /* fill in the header */
- cvs_reg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- cvs_reg_cal_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(cvs_reg_cal_cmd) - APR_HDR_SIZE);
- cvs_reg_cal_cmd.hdr.src_port = v->session_id;
- cvs_reg_cal_cmd.hdr.dest_port = cvs_handle;
- cvs_reg_cal_cmd.hdr.token = 0;
- cvs_reg_cal_cmd.hdr.opcode = VSS_ISTREAM_CMD_REGISTER_CALIBRATION_DATA;
-
- cvs_reg_cal_cmd.cvs_cal_data.phys_addr = cal_paddr;
- cvs_reg_cal_cmd.cvs_cal_data.mem_size = cal_block.cal_size;
-
- v->cvs_state = CMD_STATUS_FAIL;
- ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_reg_cal_cmd);
- if (ret < 0) {
- pr_err("Fail: sending cvs cal,\n");
- goto fail;
- }
- ret = wait_event_timeout(v->cvs_wait,
- (v->cvs_state == CMD_STATUS_SUCCESS),
- msecs_to_jiffies(TIMEOUT_MS));
- if (!ret) {
- pr_err("%s: wait_event timeout\n", __func__);
- goto fail;
- }
- return 0;
-fail:
- return -EINVAL;
-
-}
-
-static int voice_send_cvs_deregister_cal_cmd(struct voice_data *v)
-{
- struct cvs_deregister_cal_data_cmd cvs_dereg_cal_cmd;
- struct acdb_cal_block cal_block;
- int ret = 0;
- void *apr_cvs;
- u16 cvs_handle;
-
- get_all_vocstrm_cal(&cal_block);
- if (cal_block.cal_size == 0)
- return 0;
-
- if (v == NULL) {
- pr_err("%s: v is NULL\n", __func__);
- return -EINVAL;
- }
- apr_cvs = common.apr_q6_cvs;
-
- if (!apr_cvs) {
- pr_err("%s: apr_cvs is NULL.\n", __func__);
- return -EINVAL;
- }
- cvs_handle = voice_get_cvs_handle(v);
-
- /* fill in the header */
- cvs_dereg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- cvs_dereg_cal_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(cvs_dereg_cal_cmd) - APR_HDR_SIZE);
- cvs_dereg_cal_cmd.hdr.src_port = v->session_id;
- cvs_dereg_cal_cmd.hdr.dest_port = cvs_handle;
- cvs_dereg_cal_cmd.hdr.token = 0;
- cvs_dereg_cal_cmd.hdr.opcode =
- VSS_ISTREAM_CMD_DEREGISTER_CALIBRATION_DATA;
-
- v->cvs_state = CMD_STATUS_FAIL;
- ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_dereg_cal_cmd);
- if (ret < 0) {
- pr_err("Fail: sending cvs cal,\n");
- goto fail;
- }
- ret = wait_event_timeout(v->cvs_wait,
- (v->cvs_state == CMD_STATUS_SUCCESS),
- msecs_to_jiffies(TIMEOUT_MS));
- if (!ret) {
- pr_err("%s: wait_event timeout\n", __func__);
- goto fail;
- }
- return 0;
-fail:
- return -EINVAL;
-
-}
-
-static int voice_send_cvp_map_memory_cmd(struct voice_data *v)
-{
- struct vss_map_memory_cmd cvp_map_mem_cmd;
- struct acdb_cal_block cal_block;
- int ret = 0;
- void *apr_cvp;
- u16 cvp_handle;
- uint32_t cal_paddr;
-
- /* get all cvp cal data */
- get_all_cvp_cal(&cal_block);
- if (cal_block.cal_size == 0)
- goto fail;
-
- if (v == NULL) {
- pr_err("%s: v is NULL\n", __func__);
- return -EINVAL;
- }
- apr_cvp = common.apr_q6_cvp;
-
- if (!apr_cvp) {
- pr_err("%s: apr_cvp is NULL.\n", __func__);
- return -EINVAL;
- }
-
- if (is_voip_session(v->session_id)) {
- if (common.cvp_cal.buf)
- cal_paddr = common.cvp_cal.phy;
- else
- return -EINVAL;
- } else {
- cal_paddr = cal_block.cal_paddr;
- }
- cvp_handle = voice_get_cvp_handle(v);
-
- /* fill in the header */
- cvp_map_mem_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- cvp_map_mem_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(cvp_map_mem_cmd) - APR_HDR_SIZE);
- cvp_map_mem_cmd.hdr.src_port = v->session_id;
- cvp_map_mem_cmd.hdr.dest_port = cvp_handle;
- cvp_map_mem_cmd.hdr.token = 0;
- cvp_map_mem_cmd.hdr.opcode = VSS_ICOMMON_CMD_MAP_MEMORY;
-
- pr_debug("%s, phy_addr:0x%x, mem_size:%d\n", __func__,
- cal_paddr, cal_block.cal_size);
- cvp_map_mem_cmd.vss_map_mem.phys_addr = cal_paddr;
- cvp_map_mem_cmd.vss_map_mem.mem_size = cal_block.cal_size;
- cvp_map_mem_cmd.vss_map_mem.mem_pool_id =
- VSS_ICOMMON_MAP_MEMORY_SHMEM8_4K_POOL;
-
- v->cvp_state = CMD_STATUS_FAIL;
- ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_map_mem_cmd);
- if (ret < 0) {
- pr_err("Fail: sending cvp cal,\n");
- goto fail;
- }
- ret = wait_event_timeout(v->cvp_wait,
- (v->cvp_state == CMD_STATUS_SUCCESS),
- msecs_to_jiffies(TIMEOUT_MS));
- if (!ret) {
- pr_err("%s: wait_event timeout\n", __func__);
- goto fail;
- }
- return 0;
-fail:
- return -EINVAL;
-
-}
-
-static int voice_send_cvp_unmap_memory_cmd(struct voice_data *v)
-{
- struct vss_unmap_memory_cmd cvp_unmap_mem_cmd;
- struct acdb_cal_block cal_block;
- int ret = 0;
- void *apr_cvp;
- u16 cvp_handle;
- uint32_t cal_paddr;
-
- get_all_cvp_cal(&cal_block);
- if (cal_block.cal_size == 0)
- return 0;
-
- if (v == NULL) {
- pr_err("%s: v is NULL\n", __func__);
- return -EINVAL;
- }
- apr_cvp = common.apr_q6_cvp;
-
- if (!apr_cvp) {
- pr_err("%s: apr_cvp is NULL.\n", __func__);
- return -EINVAL;
- }
-
- if (is_voip_session(v->session_id))
- cal_paddr = common.cvp_cal.phy;
- else
- cal_paddr = cal_block.cal_paddr;
-
- cvp_handle = voice_get_cvp_handle(v);
-
- /* fill in the header */
- cvp_unmap_mem_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- cvp_unmap_mem_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(cvp_unmap_mem_cmd) - APR_HDR_SIZE);
- cvp_unmap_mem_cmd.hdr.src_port = v->session_id;
- cvp_unmap_mem_cmd.hdr.dest_port = cvp_handle;
- cvp_unmap_mem_cmd.hdr.token = 0;
- cvp_unmap_mem_cmd.hdr.opcode = VSS_ICOMMON_CMD_UNMAP_MEMORY;
-
- cvp_unmap_mem_cmd.vss_unmap_mem.phys_addr = cal_paddr;
-
- v->cvp_state = CMD_STATUS_FAIL;
- ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_unmap_mem_cmd);
- if (ret < 0) {
- pr_err("Fail: sending cvp cal,\n");
- goto fail;
- }
- ret = wait_event_timeout(v->cvp_wait,
- (v->cvp_state == CMD_STATUS_SUCCESS),
- msecs_to_jiffies(TIMEOUT_MS));
- if (!ret) {
- pr_err("%s: wait_event timeout\n", __func__);
- goto fail;
- }
- return 0;
-fail:
- return -EINVAL;
-
-}
-
-static int voice_send_cvs_map_memory_cmd(struct voice_data *v)
-{
- struct vss_map_memory_cmd cvs_map_mem_cmd;
- struct acdb_cal_block cal_block;
- int ret = 0;
- void *apr_cvs;
- u16 cvs_handle;
- uint32_t cal_paddr;
-
- /* get all cvs cal data */
- get_all_vocstrm_cal(&cal_block);
- if (cal_block.cal_size == 0)
- goto fail;
-
- if (v == NULL) {
- pr_err("%s: v is NULL\n", __func__);
- return -EINVAL;
- }
- apr_cvs = common.apr_q6_cvs;
-
- if (!apr_cvs) {
- pr_err("%s: apr_cvs is NULL.\n", __func__);
- return -EINVAL;
- }
-
- if (is_voip_session(v->session_id)) {
- if (common.cvs_cal.buf)
- cal_paddr = common.cvs_cal.phy;
- else
- return -EINVAL;
- } else {
- cal_paddr = cal_block.cal_paddr;
- }
-
- cvs_handle = voice_get_cvs_handle(v);
-
- /* fill in the header */
- cvs_map_mem_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- cvs_map_mem_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(cvs_map_mem_cmd) - APR_HDR_SIZE);
- cvs_map_mem_cmd.hdr.src_port = v->session_id;
- cvs_map_mem_cmd.hdr.dest_port = cvs_handle;
- cvs_map_mem_cmd.hdr.token = 0;
- cvs_map_mem_cmd.hdr.opcode = VSS_ICOMMON_CMD_MAP_MEMORY;
-
- pr_debug("%s, phys_addr: 0x%x, mem_size: %d\n", __func__,
- cal_paddr, cal_block.cal_size);
- cvs_map_mem_cmd.vss_map_mem.phys_addr = cal_paddr;
- cvs_map_mem_cmd.vss_map_mem.mem_size = cal_block.cal_size;
- cvs_map_mem_cmd.vss_map_mem.mem_pool_id =
- VSS_ICOMMON_MAP_MEMORY_SHMEM8_4K_POOL;
-
- v->cvs_state = CMD_STATUS_FAIL;
- ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_map_mem_cmd);
- if (ret < 0) {
- pr_err("Fail: sending cvs cal,\n");
- goto fail;
- }
- ret = wait_event_timeout(v->cvs_wait,
- (v->cvs_state == CMD_STATUS_SUCCESS),
- msecs_to_jiffies(TIMEOUT_MS));
- if (!ret) {
- pr_err("%s: wait_event timeout\n", __func__);
- goto fail;
- }
- return 0;
-fail:
- return -EINVAL;
-
-}
-
-static int voice_send_cvs_unmap_memory_cmd(struct voice_data *v)
-{
- struct vss_unmap_memory_cmd cvs_unmap_mem_cmd;
- struct acdb_cal_block cal_block;
- int ret = 0;
- void *apr_cvs;
- u16 cvs_handle;
- uint32_t cal_paddr;
-
- get_all_vocstrm_cal(&cal_block);
- if (cal_block.cal_size == 0)
- return 0;
-
- if (v == NULL) {
- pr_err("%s: v is NULL\n", __func__);
- return -EINVAL;
- }
- apr_cvs = common.apr_q6_cvs;
-
- if (!apr_cvs) {
- pr_err("%s: apr_cvs is NULL.\n", __func__);
- return -EINVAL;
- }
-
- if (is_voip_session(v->session_id))
- cal_paddr = common.cvs_cal.phy;
- else
- cal_paddr = cal_block.cal_paddr;
-
- cvs_handle = voice_get_cvs_handle(v);
-
- /* fill in the header */
- cvs_unmap_mem_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- cvs_unmap_mem_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(cvs_unmap_mem_cmd) - APR_HDR_SIZE);
- cvs_unmap_mem_cmd.hdr.src_port = v->session_id;
- cvs_unmap_mem_cmd.hdr.dest_port = cvs_handle;
- cvs_unmap_mem_cmd.hdr.token = 0;
- cvs_unmap_mem_cmd.hdr.opcode = VSS_ICOMMON_CMD_UNMAP_MEMORY;
-
- cvs_unmap_mem_cmd.vss_unmap_mem.phys_addr = cal_paddr;
-
- v->cvs_state = CMD_STATUS_FAIL;
- ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_unmap_mem_cmd);
- if (ret < 0) {
- pr_err("Fail: sending cvs cal,\n");
- goto fail;
- }
- ret = wait_event_timeout(v->cvs_wait,
- (v->cvs_state == CMD_STATUS_SUCCESS),
- msecs_to_jiffies(TIMEOUT_MS));
- if (!ret) {
- pr_err("%s: wait_event timeout\n", __func__);
- goto fail;
- }
- return 0;
-fail:
- return -EINVAL;
-
-}
-
-static int voice_send_cvp_register_cal_cmd(struct voice_data *v)
-{
- struct cvp_register_cal_data_cmd cvp_reg_cal_cmd;
- struct acdb_cal_block cal_block;
- int ret = 0;
- void *apr_cvp;
- u16 cvp_handle;
- uint32_t cal_paddr;
-
- /* get the cvp cal data */
- get_all_vocproc_cal(&cal_block);
- if (cal_block.cal_size == 0)
- goto fail;
-
- if (v == NULL) {
- pr_err("%s: v is NULL\n", __func__);
- return -EINVAL;
- }
- apr_cvp = common.apr_q6_cvp;
-
- if (!apr_cvp) {
- pr_err("%s: apr_cvp is NULL.\n", __func__);
- return -EINVAL;
- }
-
- if (is_voip_session(v->session_id)) {
- if (common.cvp_cal.buf) {
- cal_paddr = common.cvp_cal.phy;
-
- memcpy(common.cvp_cal.buf,
- (void *)cal_block.cal_kvaddr,
- cal_block.cal_size);
- } else {
- return -EINVAL;
- }
- } else {
- cal_paddr = cal_block.cal_paddr;
- }
-
- cvp_handle = voice_get_cvp_handle(v);
-
- /* fill in the header */
- cvp_reg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- cvp_reg_cal_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(cvp_reg_cal_cmd) - APR_HDR_SIZE);
- cvp_reg_cal_cmd.hdr.src_port = v->session_id;
- cvp_reg_cal_cmd.hdr.dest_port = cvp_handle;
- cvp_reg_cal_cmd.hdr.token = 0;
- cvp_reg_cal_cmd.hdr.opcode = VSS_IVOCPROC_CMD_REGISTER_CALIBRATION_DATA;
-
- cvp_reg_cal_cmd.cvp_cal_data.phys_addr = cal_paddr;
- cvp_reg_cal_cmd.cvp_cal_data.mem_size = cal_block.cal_size;
-
- v->cvp_state = CMD_STATUS_FAIL;
- ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_reg_cal_cmd);
- if (ret < 0) {
- pr_err("Fail: sending cvp cal,\n");
- goto fail;
- }
- ret = wait_event_timeout(v->cvp_wait,
- (v->cvp_state == CMD_STATUS_SUCCESS),
- msecs_to_jiffies(TIMEOUT_MS));
- if (!ret) {
- pr_err("%s: wait_event timeout\n", __func__);
- goto fail;
- }
- return 0;
-fail:
- return -EINVAL;
-
-}
-
-static int voice_send_cvp_deregister_cal_cmd(struct voice_data *v)
-{
- struct cvp_deregister_cal_data_cmd cvp_dereg_cal_cmd;
- struct acdb_cal_block cal_block;
- int ret = 0;
- void *apr_cvp;
- u16 cvp_handle;
-
- get_all_vocproc_cal(&cal_block);
- if (cal_block.cal_size == 0)
- return 0;
-
- if (v == NULL) {
- pr_err("%s: v is NULL\n", __func__);
- return -EINVAL;
- }
- apr_cvp = common.apr_q6_cvp;
-
- if (!apr_cvp) {
- pr_err("%s: apr_cvp is NULL.\n", __func__);
- return -EINVAL;
- }
- cvp_handle = voice_get_cvp_handle(v);
-
- /* fill in the header */
- cvp_dereg_cal_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- cvp_dereg_cal_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(cvp_dereg_cal_cmd) - APR_HDR_SIZE);
- cvp_dereg_cal_cmd.hdr.src_port = v->session_id;
- cvp_dereg_cal_cmd.hdr.dest_port = cvp_handle;
- cvp_dereg_cal_cmd.hdr.token = 0;
- cvp_dereg_cal_cmd.hdr.opcode =
- VSS_IVOCPROC_CMD_DEREGISTER_CALIBRATION_DATA;
-
- v->cvp_state = CMD_STATUS_FAIL;
- ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_dereg_cal_cmd);
- if (ret < 0) {
- pr_err("Fail: sending cvp cal,\n");
- goto fail;
- }
- ret = wait_event_timeout(v->cvp_wait,
- (v->cvp_state == CMD_STATUS_SUCCESS),
- msecs_to_jiffies(TIMEOUT_MS));
- if (!ret) {
- pr_err("%s: wait_event timeout\n", __func__);
- goto fail;
- }
- return 0;
-fail:
- return -EINVAL;
-
-}
-
-static int voice_send_cvp_register_vol_cal_table_cmd(struct voice_data *v)
-{
- struct cvp_register_vol_cal_table_cmd cvp_reg_cal_tbl_cmd;
- struct acdb_cal_block vol_block;
- struct acdb_cal_block voc_block;
- int ret = 0;
- void *apr_cvp;
- u16 cvp_handle;
- uint32_t cal_paddr;
-
- /* get the cvp vol cal data */
- get_all_vocvol_cal(&vol_block);
- get_all_vocproc_cal(&voc_block);
-
- if (vol_block.cal_size == 0)
- goto fail;
-
- if (v == NULL) {
- pr_err("%s: v is NULL\n", __func__);
- return -EINVAL;
- }
- apr_cvp = common.apr_q6_cvp;
-
- if (!apr_cvp) {
- pr_err("%s: apr_cvp is NULL.\n", __func__);
- return -EINVAL;
- }
-
- if (is_voip_session(v->session_id)) {
- if (common.cvp_cal.buf) {
- cal_paddr = common.cvp_cal.phy + voc_block.cal_size;
-
- memcpy(common.cvp_cal.buf + voc_block.cal_size,
- (void *) vol_block.cal_kvaddr,
- vol_block.cal_size);
- } else {
- return -EINVAL;
- }
- } else {
- cal_paddr = vol_block.cal_paddr;
- }
-
- cvp_handle = voice_get_cvp_handle(v);
-
- /* fill in the header */
- cvp_reg_cal_tbl_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- cvp_reg_cal_tbl_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(cvp_reg_cal_tbl_cmd) - APR_HDR_SIZE);
- cvp_reg_cal_tbl_cmd.hdr.src_port = v->session_id;
- cvp_reg_cal_tbl_cmd.hdr.dest_port = cvp_handle;
- cvp_reg_cal_tbl_cmd.hdr.token = 0;
- cvp_reg_cal_tbl_cmd.hdr.opcode =
- VSS_IVOCPROC_CMD_REGISTER_VOLUME_CAL_TABLE;
-
- cvp_reg_cal_tbl_cmd.cvp_vol_cal_tbl.phys_addr = cal_paddr;
- cvp_reg_cal_tbl_cmd.cvp_vol_cal_tbl.mem_size = vol_block.cal_size;
-
- v->cvp_state = CMD_STATUS_FAIL;
- ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_reg_cal_tbl_cmd);
- if (ret < 0) {
- pr_err("Fail: sending cvp cal table,\n");
- goto fail;
- }
- ret = wait_event_timeout(v->cvp_wait,
- (v->cvp_state == CMD_STATUS_SUCCESS),
- msecs_to_jiffies(TIMEOUT_MS));
- if (!ret) {
- pr_err("%s: wait_event timeout\n", __func__);
- goto fail;
- }
- return 0;
-fail:
- return -EINVAL;
-
-}
-
-static int voice_send_cvp_deregister_vol_cal_table_cmd(struct voice_data *v)
-{
- struct cvp_deregister_vol_cal_table_cmd cvp_dereg_cal_tbl_cmd;
- struct acdb_cal_block cal_block;
- int ret = 0;
- void *apr_cvp;
- u16 cvp_handle;
-
- get_all_vocvol_cal(&cal_block);
- if (cal_block.cal_size == 0)
- return 0;
-
- if (v == NULL) {
- pr_err("%s: v is NULL\n", __func__);
- return -EINVAL;
- }
- apr_cvp = common.apr_q6_cvp;
-
- if (!apr_cvp) {
- pr_err("%s: apr_cvp is NULL.\n", __func__);
- return -EINVAL;
- }
- cvp_handle = voice_get_cvp_handle(v);
-
- /* fill in the header */
- cvp_dereg_cal_tbl_cmd.hdr.hdr_field = APR_HDR_FIELD(
- APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE),
- APR_PKT_VER);
- cvp_dereg_cal_tbl_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(cvp_dereg_cal_tbl_cmd) - APR_HDR_SIZE);
- cvp_dereg_cal_tbl_cmd.hdr.src_port = v->session_id;
- cvp_dereg_cal_tbl_cmd.hdr.dest_port = cvp_handle;
- cvp_dereg_cal_tbl_cmd.hdr.token = 0;
- cvp_dereg_cal_tbl_cmd.hdr.opcode =
- VSS_IVOCPROC_CMD_DEREGISTER_VOLUME_CAL_TABLE;
-
- v->cvp_state = CMD_STATUS_FAIL;
- ret = apr_send_pkt(apr_cvp, (uint32_t *) &cvp_dereg_cal_tbl_cmd);
- if (ret < 0) {
- pr_err("Fail: sending cvp cal table,\n");
- goto fail;
- }
- ret = wait_event_timeout(v->cvp_wait,
- (v->cvp_state == CMD_STATUS_SUCCESS),
- msecs_to_jiffies(TIMEOUT_MS));
- if (!ret) {
- pr_err("%s: wait_event timeout\n", __func__);
- goto fail;
- }
- return 0;
-fail:
- return -EINVAL;
-
-}
-
-static int voice_send_set_widevoice_enable_cmd(struct voice_data *v)
-{
- struct mvm_set_widevoice_enable_cmd mvm_set_wv_cmd;
- int ret = 0;
- void *apr_mvm;
- u16 mvm_handle;
-
- if (v == NULL) {
- pr_err("%s: v is NULL\n", __func__);
- return -EINVAL;
- }
- apr_mvm = common.apr_q6_mvm;
-
- if (!apr_mvm) {
- pr_err("%s: apr_mvm is NULL.\n", __func__);
- return -EINVAL;
- }
- mvm_handle = voice_get_mvm_handle(v);
-
- /* fill in the header */
- mvm_set_wv_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- mvm_set_wv_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(mvm_set_wv_cmd) - APR_HDR_SIZE);
- mvm_set_wv_cmd.hdr.src_port = v->session_id;
- mvm_set_wv_cmd.hdr.dest_port = mvm_handle;
- mvm_set_wv_cmd.hdr.token = 0;
- mvm_set_wv_cmd.hdr.opcode = VSS_IWIDEVOICE_CMD_SET_WIDEVOICE;
-
- mvm_set_wv_cmd.vss_set_wv.enable = v->wv_enable;
-
- v->mvm_state = CMD_STATUS_FAIL;
- ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_set_wv_cmd);
- if (ret < 0) {
- pr_err("Fail: sending mvm set widevoice enable,\n");
- goto fail;
- }
- ret = wait_event_timeout(v->mvm_wait,
- (v->mvm_state == CMD_STATUS_SUCCESS),
- msecs_to_jiffies(TIMEOUT_MS));
- if (!ret) {
- pr_err("%s: wait_event timeout\n", __func__);
- goto fail;
- }
- return 0;
-fail:
- return -EINVAL;
-}
-
-static int voice_send_set_pp_enable_cmd(struct voice_data *v,
- uint32_t module_id, int enable)
-{
- struct cvs_set_pp_enable_cmd cvs_set_pp_cmd;
- int ret = 0;
- void *apr_cvs;
- u16 cvs_handle;
-
- if (v == NULL) {
- pr_err("%s: v is NULL\n", __func__);
- return -EINVAL;
- }
- apr_cvs = common.apr_q6_cvs;
-
- if (!apr_cvs) {
- pr_err("%s: apr_cvs is NULL.\n", __func__);
- return -EINVAL;
- }
- cvs_handle = voice_get_cvs_handle(v);
-
- /* fill in the header */
- cvs_set_pp_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- cvs_set_pp_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(cvs_set_pp_cmd) - APR_HDR_SIZE);
- cvs_set_pp_cmd.hdr.src_port = v->session_id;
- cvs_set_pp_cmd.hdr.dest_port = cvs_handle;
- cvs_set_pp_cmd.hdr.token = 0;
- cvs_set_pp_cmd.hdr.opcode = VSS_ICOMMON_CMD_SET_UI_PROPERTY;
-
- cvs_set_pp_cmd.vss_set_pp.module_id = module_id;
- cvs_set_pp_cmd.vss_set_pp.param_id = VOICE_PARAM_MOD_ENABLE;
- cvs_set_pp_cmd.vss_set_pp.param_size = MOD_ENABLE_PARAM_LEN;
- cvs_set_pp_cmd.vss_set_pp.reserved = 0;
- cvs_set_pp_cmd.vss_set_pp.enable = enable;
- cvs_set_pp_cmd.vss_set_pp.reserved_field = 0;
- pr_debug("voice_send_set_pp_enable_cmd, module_id=%d, enable=%d\n",
- module_id, enable);
-
- v->cvs_state = CMD_STATUS_FAIL;
- ret = apr_send_pkt(apr_cvs, (uint32_t *) &cvs_set_pp_cmd);
- if (ret < 0) {
- pr_err("Fail: sending cvs set slowtalk enable,\n");
- goto fail;
- }
- ret = wait_event_timeout(v->cvs_wait,
- (v->cvs_state == CMD_STATUS_SUCCESS),
- msecs_to_jiffies(TIMEOUT_MS));
- if (!ret) {
- pr_err("%s: wait_event timeout\n", __func__);
- goto fail;
- }
- return 0;
-fail:
- return -EINVAL;
-}
static int voice_setup_vocproc(struct voice_data *v)
{
@@ -2040,17 +1266,6 @@
goto fail;
}
- /* send cvs cal */
- ret = voice_send_cvs_map_memory_cmd(v);
- if (!ret)
- voice_send_cvs_register_cal_cmd(v);
-
- /* send cvp and vol cal */
- ret = voice_send_cvp_map_memory_cmd(v);
- if (!ret) {
- voice_send_cvp_register_cal_cmd(v);
- voice_send_cvp_register_vol_cal_table_cmd(v);
- }
/* enable vocproc */
ret = voice_send_enable_vocproc_cmd(v);
@@ -2065,16 +1280,6 @@
/* send tty mode if tty device is used */
voice_send_tty_mode_cmd(v);
- /* enable widevoice if wv_enable is set */
- if (v->wv_enable)
- voice_send_set_widevoice_enable_cmd(v);
-
- /* enable slowtalk if st_enable is set */
- if (v->st_enable)
- voice_send_set_pp_enable_cmd(v, MODULE_ID_VOICE_MODULE_ST,
- v->st_enable);
- voice_send_set_pp_enable_cmd(v, MODULE_ID_VOICE_MODULE_FENS,
- v->fens_enable);
if (is_voip_session(v->session_id))
voice_send_netid_timing_cmd(v);
@@ -2087,10 +1292,6 @@
if (v->rec_info.rec_enable)
voice_cvs_start_record(v, v->rec_info.rec_mode);
- rtac_add_voice(voice_get_cvs_handle(v),
- voice_get_cvp_handle(v),
- v->dev_rx.port_id, v->dev_tx.port_id,
- v->session_id);
return 0;
@@ -2359,14 +1560,6 @@
goto fail;
}
- /* deregister cvp and vol cal */
- voice_send_cvp_deregister_vol_cal_table_cmd(v);
- voice_send_cvp_deregister_cal_cmd(v);
- voice_send_cvp_unmap_memory_cmd(v);
-
- /* deregister cvs cal */
- voice_send_cvs_deregister_cal_cmd(v);
- voice_send_cvs_unmap_memory_cmd(v);
/* destrop cvp session */
cvp_destroy_session_cmd.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -2395,7 +1588,6 @@
goto fail;
}
- rtac_remove_voice(voice_get_cvs_handle(v));
cvp_handle = 0;
voice_set_cvp_handle(v, cvp_handle);
@@ -2975,12 +2167,6 @@
mutex_lock(&v->lock);
if (v->voc_state == VOC_RUN) {
- if (v->dev_tx.port_id != RT_PROXY_PORT_001_TX &&
- v->dev_rx.port_id != RT_PROXY_PORT_001_RX)
- afe_sidetone(v->dev_tx.port_id, v->dev_rx.port_id,
- 0, 0);
-
- rtac_remove_voice(voice_get_cvs_handle(v));
/* send cmd to dsp to disable vocproc */
ret = voice_send_disable_vocproc_cmd(v);
if (ret < 0) {
@@ -2988,10 +2174,6 @@
goto fail;
}
- /* deregister cvp and vol cal */
- voice_send_cvp_deregister_vol_cal_table_cmd(v);
- voice_send_cvp_deregister_cal_cmd(v);
- voice_send_cvp_unmap_memory_cmd(v);
v->voc_state = VOC_CHANGE;
}
@@ -3004,7 +2186,6 @@
int voc_enable_cvp(uint16_t session_id)
{
struct voice_data *v = voice_get_session(session_id);
- struct sidetone_cal sidetone_cal_data;
int ret = 0;
if (v == NULL) {
@@ -3021,53 +2202,9 @@
pr_err("%s: set device failed\n", __func__);
goto fail;
}
- /* send cvp and vol cal */
- ret = voice_send_cvp_map_memory_cmd(v);
- if (!ret) {
- voice_send_cvp_register_cal_cmd(v);
- voice_send_cvp_register_vol_cal_table_cmd(v);
- }
- ret = voice_send_enable_vocproc_cmd(v);
- if (ret < 0) {
- pr_err("%s: enable vocproc failed\n", __func__);
- goto fail;
-
- }
/* send tty mode if tty device is used */
voice_send_tty_mode_cmd(v);
- /* enable widevoice if wv_enable is set */
- if (v->wv_enable)
- voice_send_set_widevoice_enable_cmd(v);
-
- /* enable slowtalk */
- if (v->st_enable)
- voice_send_set_pp_enable_cmd(v,
- MODULE_ID_VOICE_MODULE_ST,
- v->st_enable);
- /* enable FENS */
- if (v->fens_enable)
- voice_send_set_pp_enable_cmd(v,
- MODULE_ID_VOICE_MODULE_FENS,
- v->fens_enable);
-
- get_sidetone_cal(&sidetone_cal_data);
- if (v->dev_tx.port_id != RT_PROXY_PORT_001_TX &&
- v->dev_rx.port_id != RT_PROXY_PORT_001_RX) {
- ret = afe_sidetone(v->dev_tx.port_id,
- v->dev_rx.port_id,
- sidetone_cal_data.enable,
- sidetone_cal_data.gain);
-
- if (ret < 0)
- pr_err("%s: AFE command sidetone failed\n",
- __func__);
- }
-
- rtac_add_voice(voice_get_cvs_handle(v),
- voice_get_cvp_handle(v),
- v->dev_rx.port_id, v->dev_tx.port_id,
- v->session_id);
v->voc_state = VOC_RUN;
}
@@ -3201,8 +2338,6 @@
mvm_handle = voice_get_mvm_handle(v);
- if (mvm_handle != 0)
- voice_send_set_widevoice_enable_cmd(v);
mutex_unlock(&v->lock);
@@ -3246,16 +2381,6 @@
else if (module_id == MODULE_ID_VOICE_MODULE_FENS)
v->fens_enable = enable;
- if (v->voc_state == VOC_RUN) {
- if (module_id == MODULE_ID_VOICE_MODULE_ST)
- ret = voice_send_set_pp_enable_cmd(v,
- MODULE_ID_VOICE_MODULE_ST,
- enable);
- else if (module_id == MODULE_ID_VOICE_MODULE_FENS)
- ret = voice_send_set_pp_enable_cmd(v,
- MODULE_ID_VOICE_MODULE_FENS,
- enable);
- }
mutex_unlock(&v->lock);
return ret;
@@ -3391,10 +2516,6 @@
mutex_lock(&v->lock);
if (v->voc_state == VOC_RUN) {
- if (v->dev_tx.port_id != RT_PROXY_PORT_001_TX &&
- v->dev_rx.port_id != RT_PROXY_PORT_001_RX)
- afe_sidetone(v->dev_tx.port_id, v->dev_rx.port_id,
- 0, 0);
ret = voice_destroy_vocproc(v);
if (ret < 0)
pr_err("%s: destroy voice failed\n", __func__);
@@ -3409,7 +2530,6 @@
int voc_start_voice_call(uint16_t session_id)
{
struct voice_data *v = voice_get_session(session_id);
- struct sidetone_cal sidetone_cal_data;
int ret = 0;
if (v == NULL) {
@@ -3447,16 +2567,6 @@
pr_err("start voice failed\n");
goto fail;
}
- get_sidetone_cal(&sidetone_cal_data);
- if (v->dev_tx.port_id != RT_PROXY_PORT_001_TX &&
- v->dev_rx.port_id != RT_PROXY_PORT_001_RX) {
- ret = afe_sidetone(v->dev_tx.port_id,
- v->dev_rx.port_id,
- sidetone_cal_data.enable,
- sidetone_cal_data.gain);
- if (ret < 0)
- pr_err("AFE command sidetone failed\n");
- }
v->voc_state = VOC_RUN;
}
@@ -3649,8 +2759,6 @@
wake_up(&v->cvs_wait);
break;
case VOICE_CMD_SET_PARAM:
- rtac_make_voice_callback(RTAC_CVS, ptr,
- data->payload_size);
break;
default:
pr_debug("%s: cmd = 0x%x\n", __func__, ptr[0]);
@@ -3712,9 +2820,6 @@
pr_debug("%s: dl_cb is NULL\n", __func__);
} else if (data->opcode == VSS_ISTREAM_EVT_SEND_DEC_BUFFER) {
pr_debug("Send dec buf resp\n");
- } else if (data->opcode == VOICE_EVT_GET_PARAM_ACK) {
- rtac_make_voice_callback(RTAC_CVS, data->payload,
- data->payload_size);
} else
pr_debug("Unknown opcode 0x%x\n", data->opcode);
@@ -3792,8 +2897,6 @@
wake_up(&v->cvp_wait);
break;
case VOICE_CMD_SET_PARAM:
- rtac_make_voice_callback(RTAC_CVP, ptr,
- data->payload_size);
break;
default:
pr_debug("%s: not match cmd = 0x%x\n",
@@ -3801,9 +2904,6 @@
break;
}
}
- } else if (data->opcode == VOICE_EVT_GET_PARAM_ACK) {
- rtac_make_voice_callback(RTAC_CVP, data->payload,
- data->payload_size);
}
return 0;
}
@@ -3812,73 +2912,9 @@
static int __init voice_init(void)
{
int rc = 0, i = 0;
- int len;
memset(&common, 0, sizeof(struct common_data));
- /* Allocate memory for VoIP calibration */
- common.client = msm_ion_client_create(UINT_MAX, "voip_client");
- if (IS_ERR_OR_NULL((void *)common.client)) {
- pr_err("%s: ION create client for Voip failed\n", __func__);
- goto cont;
- }
- common.cvp_cal.handle = ion_alloc(common.client, CVP_CAL_SIZE, SZ_4K,
- ION_HEAP(ION_AUDIO_HEAP_ID));
- if (IS_ERR_OR_NULL((void *) common.cvp_cal.handle)) {
- pr_err("%s: ION memory allocation for CVP failed\n",
- __func__);
- ion_client_destroy(common.client);
- goto cont;
- }
-
- rc = ion_phys(common.client, common.cvp_cal.handle,
- (ion_phys_addr_t *)&common.cvp_cal.phy, (size_t *)&len);
- if (rc) {
- pr_err("%s: ION Get Physical for cvp failed, rc = %d\n",
- __func__, rc);
- ion_free(common.client, common.cvp_cal.handle);
- ion_client_destroy(common.client);
- goto cont;
- }
-
- common.cvp_cal.buf = ion_map_kernel(common.client,
- common.cvp_cal.handle, 0);
- if (IS_ERR_OR_NULL((void *) common.cvp_cal.buf)) {
- pr_err("%s: ION memory mapping for cvp failed\n", __func__);
- common.cvp_cal.buf = NULL;
- ion_free(common.client, common.cvp_cal.handle);
- ion_client_destroy(common.client);
- goto cont;
- }
- memset((void *)common.cvp_cal.buf, 0, CVP_CAL_SIZE);
-
- common.cvs_cal.handle = ion_alloc(common.client, CVS_CAL_SIZE, SZ_4K,
- ION_HEAP(ION_AUDIO_HEAP_ID));
- if (IS_ERR_OR_NULL((void *) common.cvs_cal.handle)) {
- pr_err("%s: ION memory allocation for CVS failed\n",
- __func__);
- goto cont;
- }
-
- rc = ion_phys(common.client, common.cvs_cal.handle,
- (ion_phys_addr_t *)&common.cvs_cal.phy, (size_t *)&len);
- if (rc) {
- pr_err("%s: ION Get Physical for cvs failed, rc = %d\n",
- __func__, rc);
- ion_free(common.client, common.cvs_cal.handle);
- goto cont;
- }
-
- common.cvs_cal.buf = ion_map_kernel(common.client,
- common.cvs_cal.handle, 0);
- if (IS_ERR_OR_NULL((void *) common.cvs_cal.buf)) {
- pr_err("%s: ION memory mapping for cvs failed\n", __func__);
- common.cvs_cal.buf = NULL;
- ion_free(common.client, common.cvs_cal.handle);
- goto cont;
- }
- memset((void *)common.cvs_cal.buf, 0, CVS_CAL_SIZE);
-cont:
/* set default value */
common.default_mute_val = 1; /* default is mute */
common.default_vol_val = 0;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 1bedb15..d313349 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -119,6 +119,8 @@
#define VSS_IMVM_CMD_CREATE_FULL_CONTROL_SESSION 0x000110FE
/* Create a new full control MVM session. */
+#define VSS_IVOCPROC_CMD_CREATE_FULL_CONTROL_SESSION_V2 0x000112BF
+
#define APRV2_IBASIC_CMD_DESTROY_SESSION 0x0001003C
/**< No payload. Wait for APRV2_IBASIC_RSP_RESULT response. */
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 4522d15..79016b5 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3231,6 +3231,7 @@
card->instantiated = 0;
mutex_init(&card->mutex);
mutex_init(&card->dpcm_mutex);
+ mutex_init(&card->dapm_power_mutex);
mutex_lock(&client_mutex);
list_add(&card->list, &card_list);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 729142f..5ac643416 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1290,7 +1290,7 @@
/* Do we need to apply any queued changes? */
if (sort[w->id] != cur_sort || w->reg != cur_reg ||
w->dapm != cur_dapm || w->subseq != cur_subseq) {
- if (!list_empty(&pending))
+ if (cur_dapm && !list_empty(&pending))
dapm_seq_run_coalesced(cur_dapm, &pending);
if (cur_dapm && cur_dapm->seq_notifier) {
@@ -1350,7 +1350,7 @@
"Failed to apply widget power: %d\n", ret);
}
- if (!list_empty(&pending))
+ if (cur_dapm && !list_empty(&pending))
dapm_seq_run_coalesced(cur_dapm, &pending);
if (cur_dapm && cur_dapm->seq_notifier) {
@@ -1567,6 +1567,8 @@
trace_snd_soc_dapm_start(card);
+ mutex_lock(&card->dapm_power_mutex);
+
list_for_each_entry(d, &card->dapm_list, list) {
if (d->n_widgets || d->codec == NULL) {
if (d->idle_bias_off)
@@ -1682,6 +1684,8 @@
"DAPM sequencing finished, waiting %dms\n", card->pop_time);
pop_wait(card->pop_time);
+ mutex_unlock(&card->dapm_power_mutex);
+
trace_snd_soc_dapm_done(card);
return 0;
@@ -3092,9 +3096,9 @@
if (stream == NULL)
return 0;
- //mutex_lock(&codec->mutex);
+ mutex_lock(&codec->mutex);
soc_dapm_stream_event(&codec->dapm, stream, event);
- //mutex_unlock(&codec->mutex);
+ mutex_unlock(&codec->mutex);
return 0;
}