Merge "ASoC: msm9615: Add the amix control to configure AUX PCM rate" into msm-3.4
diff --git a/Documentation/devicetree/bindings/arm/msm/spm-v2.txt b/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
index a33d833..d8784db 100644
--- a/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
+++ b/Documentation/devicetree/bindings/arm/msm/spm-v2.txt
@@ -40,6 +40,7 @@
- qcom,saw2-spm-cmd-ret: The Retention command sequence
- qcom,saw2-spm-cmd-spc: The Standalone PC command sequence
- qcom,saw2-spm-cmd-pc: The Power Collapse command sequence
+- qcom,saw2-spm-cmd-gdhs: L2 GDHS command sequence
Example:
qcom,spm@f9089000 {
@@ -56,11 +57,11 @@
qcom,saw2-avs-dly= <0>;
qcom,saw2-spm-dly= <0x20000400>;
qcom,saw2-spm-ctl = <0x1>;
- qcom,spm-cmd-wfi = [03 0b 0f];
- qcom,spm-cmd-spc = [00 20 50 80 60 70 10 92
+ qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 92
a0 b0 03 68 70 3b 92 a0 b0
82 2b 50 10 30 02 22 30 0f];
- qcom,spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
+ qcom,saw2-spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
a0 b0 82 10 30 02 22 30 0f];
};
diff --git a/Documentation/devicetree/bindings/qseecom/qseecom.txt b/Documentation/devicetree/bindings/qseecom/qseecom.txt
new file mode 100644
index 0000000..8b17ba9
--- /dev/null
+++ b/Documentation/devicetree/bindings/qseecom/qseecom.txt
@@ -0,0 +1,10 @@
+* QSEECOM (Qualcomm Secure Execution Environment Communicator)
+
+Required properties:
+- compatible : Should be "qcom,qseecom"
+
+Example:
+
+ qcom,qseecom@fe806000 {
+ compatible = "qcom,qseecom";
+ };
diff --git a/Documentation/tzcom.txt b/Documentation/tzcom.txt
deleted file mode 100644
index 7472dee..0000000
--- a/Documentation/tzcom.txt
+++ /dev/null
@@ -1,181 +0,0 @@
-Introduction
-============
-
-The tzcom (TrustZone Communicator) device driver provides IOCTLs for userspace
-to communicate with TrustZone Operating Environment (TZBSP) using Secure
-Channel Manager (SCM) interface. It also provides a way for TZBSP to utilize
-services in HLOS.
-
-Hardware description
-====================
-
-The hardware interaction is specified in Secure Channel Manager for TZBSP design
-document. This driver exercises the SCM interface (scm_call).
-
-Software description
-====================
-
-This driver is a character device driver and following operations are registered:
-- tzcom_open()
-- tzcom_release()
-- tzcom_ioctl()
-
-
-This driver provides following IOCTL methods:
- TZCOM_IOCTL_REGISTER_SERVICE_REQ - to register HLOS service
- TZCOM_IOCTL_UNREGISTER_SERVICE_REQ - to unregister HLOS service
- TZCOM_IOCTL_SEND_CMD_REQ - send a command to a service
- TZCOM_IOCTL_READ_NEXT_CMD_REQ - wait for a cmd from TZBSP to use HLOS service
- TZCOM_IOCTL_CONTINUE_CMD_REQ - continue the last incomplete cmd on TZBSP
-
-TZCOM_IOCTL_REGISTER_SERVICE_REQ sequence diagram:
-
- +--------------+ +---------------+
- | USERSPACE | | TZCOM |
- +------+-------+ +-------+-------+
- | REGISTER_SERVICE |
- |----------------->| ___
- | |,-' ``.
- | + verify &`.
- | | add |
- | | service |
- | | to a list|
- | registered |<-.._,,,,/
- |<-----------------|
- | |
-
-TZCOM_IOCTL_READ_NEXT_CMD_REQ, TZCOM_IOCTL_SEND_CMD_REQ and
-TZCOM_IOCTL_CONTINUE_CMD_REQ sequence:
-
- +--------------+ +---------------+ +-------------+ +----------------+
- | USERSPACE | | TZCOM | | SCM | | TZBSP |
- +---+--+-------+ +-------+-------+ +------+------+ +-------+--------+
- | | READ_NEXT_CMD | | |
- +--|----------------->| | |
- | | |.--------. | |
- | | || BLOCKED| | |
- | | |`--------' | |
- | | | | |
- | | | | |
- | | SEND_CMD | | |
- | +----------------->| | |
- | | | scm_call | |
- | | +---------------->| SEND_CMD |
- | | | +---------------->|
- | | | | cmd incomplete |
- | | | scm_call returns|<----------------+
- | | |<----------------+ |
- | | | | |
- | | |,-'''-. | |
- | | + READ `. | |
- | | | NEXT | | |
- | | | CMD / | |
- | | READ_NEXT_CMD ret|<.____,' | |
- |<-|------------------+ | |
- ,---. | | | | |
- / \ | | | | |
-/perform\| | | | |
- received) | | | |
-\command/| | | | |
- \ / | | | | |
- `---' | | | | |
- | | | | |
- | | CONTINUE_CMD | | |
- +--|----------------->| | |
- | | returns | _,... | |
- | | immediately |' `. | |
- | | | fill in`. | |
- | | | incomplete | |
- | | | cmd ; | |
- | |<-...---' | |
- | | scm_call | |
- | +---------------->| SEND_CMD |
- | | +---------------->|
- | | | cmd complete |
- | | scm_call returns|<----------------+
- |SEND_CMD return |<----------------+ |
- |<-----------------+ | |
- | | | |
-
-
-
-There are three shared buffers between TZCOM driver and TZBSP.
-1) For command and response buffers for SEND_CMD requests
-2) For commands originated from TZBSP and their corresponding responses
-3) For debug service
-
-When calling IOCTL_SEND_CMD_REQ from userspace, command request and response
-buffers are initialized and provided in the IOCTL arguments. Where request and
-response buffers will be passed as an arguments to the smc_call method.
-
-The requests are synchronous. The driver will put the process to sleep,
-waiting for the completion of the requests using wait_for_completion().
-
-This driver uses kmalloc for shared buffer pools which get initialized at driver
-initialization. There are three buffers each 20 KB. If any of the buffers fail
-to initialize then driver will fail to load. Assumption is the allocated
-memory for buffers is contiguous.
-
-
-Design
-======
-
-The goal of this driver is to provide a communication API for the userspace
-application to execute services in TrustZone as well as TrustZone operating
-environment to access services in HLOS.
-
-Currently TZ->HLOS communication happens from a blocking call to READ_NEXT_CMD
-that is initiated from the userspace and on receiving a command request from TZ
-service, command is placed on a queue to unblock READ_NEXT_CMD call. This could
-have been solved by using a callback, but the practice of invoking callbacks in
-userspace from kernel is discouraged.
-
-Power Management
-================
-
-n/a
-
-SMP/multi-core
-==============
-
-TZCOM allows multiple services being registered from HLOS and multiple processes
-or threads can call IOCTL_READ_NEXT_MSG. These services will block until new
-data arrives on the shared buffer (buffer #2 as mentioned in Software
-Description). This is achieved using wait queues.
-
-Security
-========
-
-Please refer to Security Channel Manager design document.
-
-Performance
-===========
-
-Every scm_call is a context switch between non-trusted and trusted operating
-environment. There are no performance related matrix for scm_call available as
-of now.
-
-Interface
-=========
-
-This driver will have a /dev/tzcom node and following IOCTL calls can be made.
-
-Userspace API (ioctl calls):
- TZCOM_IOCTL_REGISTER_SERVICE_REQ - to register HLOS service
- TZCOM_IOCTL_UNREGISTER_SERVICE_REQ - to unregister HLOS service
- TZCOM_IOCTL_SEND_CMD_REQ - send a command to a service
- TZCOM_IOCTL_READ_NEXT_CMD_REQ - wait for a cmd from TZBSP to use HLOS service
- TZCOM_IOCTL_CONTINUE_CMD_REQ - continue the last incomplete cmd on TZBSP
-
-
-Dependencies
-============
-
-This driver interacts with Trustzone operating environment, thus depends on
-the TZBSP supported architecture.
-
-
-To do
-=====
-
-TBD
diff --git a/arch/arm/boot/dts/msm-pm8841.dtsi b/arch/arm/boot/dts/msm-pm8841.dtsi
index 523c9b0..b157e95 100644
--- a/arch/arm/boot/dts/msm-pm8841.dtsi
+++ b/arch/arm/boot/dts/msm-pm8841.dtsi
@@ -153,13 +153,13 @@
status = "disabled";
qcom,ctl@2600 {
- reg = <0x2300 0x100>;
+ reg = <0x2600 0x100>;
};
qcom,ps@2700 {
- reg = <0x2400 0x100>;
+ reg = <0x2700 0x100>;
};
qcom,freq@2800 {
- reg = <0x2500 0x100>;
+ reg = <0x2800 0x100>;
};
};
diff --git a/arch/arm/boot/dts/msm9625.dts b/arch/arm/boot/dts/msm9625.dts
index d5aed00..b7b8be2 100644
--- a/arch/arm/boot/dts/msm9625.dts
+++ b/arch/arm/boot/dts/msm9625.dts
@@ -33,9 +33,11 @@
reg = <0xfd510000 0x4000>;
};
- timer {
+ timer: msm-qtimer@f9021000 {
compatible = "qcom,msm-qtimer", "arm,armv7-timer";
+ reg = <0xF9021000 0x1000>;
interrupts = <0 7 0>;
+ irq-is-not-percpu;
clock-frequency = <5000000>;
};
diff --git a/arch/arm/boot/dts/msmcopper.dtsi b/arch/arm/boot/dts/msmcopper.dtsi
index eb781b7..a37f4ff 100644
--- a/arch/arm/boot/dts/msmcopper.dtsi
+++ b/arch/arm/boot/dts/msmcopper.dtsi
@@ -276,6 +276,11 @@
compatible = "qcom,dwc-usb3-msm";
reg = <0xF9200000 0xCCFF>;
interrupts = <0 131 0>;
+ SSUSB_VDDCX-supply = <&pm8841_s2>;
+ SSUSB_1p8-supply = <&pm8941_l6>;
+ HSUSB_VDDCX-supply = <&pm8841_s2>;
+ HSUSB_1p8-supply = <&pm8941_l6>;
+ HSUSB_3p3-supply = <&pm8941_l24>;
qcom,dwc-usb3-msm-dbm-eps = <4>;
};
@@ -336,4 +341,8 @@
compatible = "qcom,msm-rng";
reg = <0xf9bff000 0x200>;
};
+
+ qcom,qseecom@fe806000 {
+ compatible = "qcom,qseecom";
+ };
};
diff --git a/arch/arm/boot/dts/msmcopper_pm.dtsi b/arch/arm/boot/dts/msmcopper_pm.dtsi
index 0da3200..79cb95c 100644
--- a/arch/arm/boot/dts/msmcopper_pm.dtsi
+++ b/arch/arm/boot/dts/msmcopper_pm.dtsi
@@ -27,11 +27,11 @@
qcom,saw2-avs-dly= <0>;
qcom,saw2-spm-dly= <0x20000400>;
qcom,saw2-spm-ctl = <0x1>;
- qcom,spm-cmd-wfi = [03 0b 0f];
- qcom,spm-cmd-spc = [00 20 50 80 60 70 10 92
+ qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 92
a0 b0 03 68 70 3b 92 a0 b0
82 2b 50 10 30 02 22 30 0f];
- qcom,spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
+ qcom,saw2-spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
a0 b0 82 10 30 02 22 30 0f];
};
@@ -49,11 +49,11 @@
qcom,saw2-avs-dly= <0>;
qcom,saw2-spm-dly= <0x20000400>;
qcom,saw2-spm-ctl = <0x1>;
- qcom,spm-cmd-wfi = [03 0b 0f];
- qcom,spm-cmd-spc = [00 20 50 80 60 70 10 92
+ qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 92
a0 b0 03 68 70 3b 92 a0 b0
82 2b 50 10 30 02 22 30 0f];
- qcom,spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
+ qcom,saw2-spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
a0 b0 82 10 30 02 22 30 0f];
};
@@ -71,11 +71,11 @@
qcom,saw2-avs-dly= <0>;
qcom,saw2-spm-dly= <0x20000400>;
qcom,saw2-spm-ctl = <0x1>;
- qcom,spm-cmd-wfi = [03 0b 0f];
- qcom,spm-cmd-spc = [00 20 50 80 60 70 10 92
+ qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 92
a0 b0 03 68 70 3b 92 a0 b0
82 2b 50 10 30 02 22 30 0f];
- qcom,spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
+ qcom,saw2-spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
a0 b0 82 10 30 02 22 30 0f];
};
@@ -93,11 +93,11 @@
qcom,saw2-avs-dly= <0>;
qcom,saw2-spm-dly= <0x20000400>;
qcom,saw2-spm-ctl = <0x1>;
- qcom,spm-cmd-wfi = [03 0b 0f];
- qcom,spm-cmd-spc = [00 20 50 80 60 70 10 92
+ qcom,saw2-spm-cmd-wfi = [03 0b 0f];
+ qcom,saw2-spm-cmd-spc = [00 20 50 80 60 70 10 92
a0 b0 03 68 70 3b 92 a0 b0
82 2b 50 10 30 02 22 30 0f];
- qcom,spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
+ qcom,saw2-spm-cmd-pc = [00 20 10 92 a0 b0 07 3b 92
a0 b0 82 10 30 02 22 30 0f];
};
@@ -123,12 +123,12 @@
qcom,vctl-timeout-us = <50>;
qcom,vctl-port = <0x0>; /* TODO: */
qcom,phase-port = <0x1>; /* TODO: */
- qcom,spm-cmd-ret = [0b 00 20 03 22 00 0f];
- qcom,spm-cmd-spc = [00 20 32 60 70 80 42 03
- 78 80 44 22 50 3b 60 02 32
- 50 0f];
- qcom,spm-cmd-pc = [00 10 32 60 70 80 b0 11 42
- 07 01 b0 78 80 12 44 a0 50
+ qcom,saw2-spm-cmd-ret = [0b 00 20 03 22 00 0f];
+ qcom,saw2-spm-cmd-gdhs = [00 20 32 60 70 80 0b 42 07
+ 78 80 44 22 50 3b 60 02 32
+ 50 0f];
+ qcom,saw2-spm-cmd-pc = [00 10 32 60 70 80 b0 11 0b
+ 42 07 01 b0 78 80 12 44 a0 50
3b 60 02 32 a0 50 0f];
};
diff --git a/arch/arm/configs/fsm9xxx-perf_defconfig b/arch/arm/configs/fsm9xxx-perf_defconfig
index 18f6d7f..4ba55de 100644
--- a/arch/arm/configs/fsm9xxx-perf_defconfig
+++ b/arch/arm/configs/fsm9xxx-perf_defconfig
@@ -32,6 +32,8 @@
CONFIG_MSM_SMD_PKG3=y
# CONFIG_MSM_SMD_DEBUG is not set
CONFIG_MSM_ONCRPCROUTER=y
+CONFIG_MSM_IPC_ROUTER=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
# CONFIG_MSM_ONCRPCROUTER_DEBUG is not set
# CONFIG_MSM_HW3D is not set
# CONFIG_QSD_AUDIO is not set
@@ -86,6 +88,7 @@
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
+CONFIG_MTD_UBI=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=8
CONFIG_BLK_DEV_RAM_SIZE=16384
@@ -159,6 +162,7 @@
CONFIG_TMPFS=y
CONFIG_YAFFS_FS=y
CONFIG_YAFFS_DISABLE_TAGS_ECC=y
+CONFIG_UBIFS_FS=m
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_NLS_CODEPAGE_437=y
diff --git a/arch/arm/configs/fsm9xxx_defconfig b/arch/arm/configs/fsm9xxx_defconfig
index 4707556..ad1b6a6 100644
--- a/arch/arm/configs/fsm9xxx_defconfig
+++ b/arch/arm/configs/fsm9xxx_defconfig
@@ -32,6 +32,8 @@
CONFIG_MSM_SMD=y
CONFIG_MSM_SMD_PKG3=y
CONFIG_MSM_ONCRPCROUTER=y
+CONFIG_MSM_IPC_ROUTER=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
# CONFIG_MSM_HW3D is not set
# CONFIG_QSD_AUDIO is not set
# CONFIG_SURF_FFA_GPIO_KEYPAD is not set
@@ -85,6 +87,7 @@
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
+CONFIG_MTD_UBI=m
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_COUNT=8
CONFIG_BLK_DEV_RAM_SIZE=16384
@@ -158,6 +161,7 @@
CONFIG_TMPFS=y
CONFIG_YAFFS_FS=y
CONFIG_YAFFS_DISABLE_TAGS_ECC=y
+CONFIG_UBIFS_FS=m
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_NLS_CODEPAGE_437=y
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 473a7d5..49fae4a 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -69,10 +69,11 @@
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-# CONFIG_SUSPEND is not set
+CONFIG_PM_RUNTIME=y
CONFIG_NET=y
CONFIG_UNIX=y
CONFIG_INET=y
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 447427a..a163829 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -192,6 +192,7 @@
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
CONFIG_NETDEVICES=y
+CONFIG_TUN=y
CONFIG_SMC91X=y
CONFIG_SMSC911X=y
CONFIG_LIBRA_SDIOIF=m
@@ -227,6 +228,7 @@
CONFIG_BATTERY_MSM=y
CONFIG_SENSORS_MSM_ADC=y
CONFIG_MARIMBA_CORE=y
+CONFIG_REGULATOR_MSM_GPIO=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_DEV=y
@@ -237,13 +239,13 @@
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA_V4L2=y
CONFIG_OV5647=y
-CONFIG_OV8825=y
CONFIG_AD5046_ACT=y
CONFIG_WEBCAM_OV9726=y
CONFIG_MT9E013=y
CONFIG_S5K4E1=y
CONFIG_DW9712_ACT=y
CONFIG_MSM_CAMERA_FLASH_SC628A=y
+CONFIG_OV8825=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_ACTUATOR=y
CONFIG_OV7692=y
@@ -339,6 +341,5 @@
CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
-CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 639eb10..d8e2e3c 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -192,6 +192,7 @@
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
CONFIG_NETDEVICES=y
+CONFIG_TUN=y
CONFIG_SMC91X=y
CONFIG_SMSC911X=y
CONFIG_LIBRA_SDIOIF=m
@@ -228,6 +229,7 @@
CONFIG_BATTERY_MSM=y
CONFIG_SENSORS_MSM_ADC=y
CONFIG_MARIMBA_CORE=y
+CONFIG_REGULATOR_MSM_GPIO=y
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_VIDEO_DEV=y
@@ -238,13 +240,13 @@
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA_V4L2=y
CONFIG_OV5647=y
-CONFIG_OV8825=y
CONFIG_AD5046_ACT=y
CONFIG_WEBCAM_OV9726=y
CONFIG_MT9E013=y
CONFIG_S5K4E1=y
CONFIG_DW9712_ACT=y
CONFIG_MSM_CAMERA_FLASH_SC628A=y
+CONFIG_OV8825=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_ACTUATOR=y
CONFIG_OV7692=y
@@ -347,6 +349,5 @@
CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
-CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRC_CCITT=y
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
index c39b403..136dc46 100644
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -207,6 +207,7 @@
CONFIG_DM_CRYPT=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_TUN=y
CONFIG_MSM_RMNET_SDIO=y
CONFIG_SMC91X=y
CONFIG_SMSC911X=y
@@ -370,7 +371,6 @@
CONFIG_DEBUG_INFO=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
-CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_DEV_QCRYPTO=m
CONFIG_CRYPTO_DEV_QCE=m
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index 8dda15f..bead86e 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -208,6 +208,7 @@
CONFIG_DM_CRYPT=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_TUN=y
CONFIG_MSM_RMNET_SDIO=y
CONFIG_SMC91X=y
CONFIG_SMSC911X=y
@@ -378,7 +379,6 @@
CONFIG_DEBUG_PAGEALLOC=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
-CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_DEV_QCRYPTO=m
CONFIG_CRYPTO_DEV_QCE=m
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index d5b4007..fe30dc8 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -248,6 +248,7 @@
CONFIG_DM_UEVENT=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_TUN=y
CONFIG_MSM_RMNET_SDIO=y
CONFIG_SMC91X=y
CONFIG_SMC911X=y
@@ -415,7 +416,6 @@
CONFIG_ANDROID_TIMED_GPIO=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
CONFIG_MSM_SSBI=y
-CONFIG_MSM_IOMMU=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
@@ -443,7 +443,6 @@
CONFIG_ENABLE_DEFAULT_TRACERS=y
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
-CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_DEV_QCRYPTO=m
CONFIG_CRYPTO_DEV_QCE=m
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 5e2c1a8..45339ee 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -249,6 +249,7 @@
CONFIG_DM_UEVENT=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_TUN=y
CONFIG_MSM_RMNET_SDIO=y
CONFIG_SMC91X=y
CONFIG_SMC911X=y
@@ -417,7 +418,6 @@
CONFIG_ANDROID_TIMED_GPIO=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
CONFIG_MSM_SSBI=y
-CONFIG_MSM_IOMMU=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
@@ -455,7 +455,6 @@
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_LL=y
-CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_DEV_QCRYPTO=m
CONFIG_CRYPTO_DEV_QCE=m
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 74d31b3..47d6ea8 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -66,7 +66,6 @@
CONFIG_MSM_SMD_PKG4=y
CONFIG_MSM_PCIE=y
CONFIG_MSM_BAM_DMUX=y
-CONFIG_MSM_RMNET_SMUX=y
CONFIG_MSM_DSPS=y
CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
@@ -256,9 +255,11 @@
CONFIG_DM_CRYPT=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_TUN=y
CONFIG_KS8851=m
# CONFIG_MSM_RMNET is not set
CONFIG_MSM_RMNET_BAM=y
+CONFIG_MSM_RMNET_SMUX=y
CONFIG_SMC91X=y
CONFIG_SMC911X=y
CONFIG_SMSC911X=y
@@ -308,7 +309,6 @@
CONFIG_SMB349_CHARGER=y
CONFIG_PM8921_CHARGER=y
CONFIG_PM8921_BMS=y
-CONFIG_PM8921_BCL=y
CONFIG_SENSORS_PM8XXX_ADC=y
CONFIG_SENSORS_EPM_ADC=y
CONFIG_THERMAL=y
@@ -475,7 +475,6 @@
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
CONFIG_PID_IN_CONTEXTIDR=y
-CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_DEV_QCRYPTO=m
CONFIG_CRYPTO_DEV_QCE=m
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 07a3f91..a0636f9 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -261,6 +261,7 @@
CONFIG_DM_CRYPT=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
+CONFIG_TUN=y
CONFIG_KS8851=m
# CONFIG_MSM_RMNET is not set
CONFIG_MSM_RMNET_BAM=y
@@ -492,7 +493,6 @@
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_USER=y
CONFIG_PID_IN_CONTEXTIDR=y
-CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_DEV_QCRYPTO=m
CONFIG_CRYPTO_DEV_QCE=m
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 89fb888..1e45f66 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -1,7 +1,7 @@
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
CONFIG_EXPERIMENTAL=y
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
-CONFIG_SPARSE_IRQ=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_CGROUPS=y
@@ -28,6 +28,7 @@
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_PARTITION_ADVANCED=y
CONFIG_ARCH_MSM=y
CONFIG_ARCH_MSM9625=y
# CONFIG_MSM_STACKED_MEMORY is not set
@@ -51,7 +52,6 @@
# CONFIG_SUSPEND is not set
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
-CONFIG_MISC_DEVICES=y
# CONFIG_ANDROID_PMEM is not set
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_KEYBOARD is not set
@@ -67,20 +67,17 @@
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
# CONFIG_HWMON is not set
-# CONFIG_MFD_SUPPORT is not set
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
# CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_PARTITION_ADVANCED=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_TIMER_STATS=y
# CONFIG_DEBUG_PREEMPT is not set
diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h
index 2098288..99ee2de 100644
--- a/arch/arm/include/asm/arch_timer.h
+++ b/arch/arm/include/asm/arch_timer.h
@@ -4,7 +4,7 @@
#include <linux/ioport.h>
struct arch_timer {
- struct resource res[2];
+ struct resource res[3];
};
#ifdef CONFIG_ARM_ARCH_TIMER
diff --git a/arch/arm/include/asm/mach/mmc.h b/arch/arm/include/asm/mach/mmc.h
index 0bdb0f1..a6ec7b2 100644
--- a/arch/arm/include/asm/mach/mmc.h
+++ b/arch/arm/include/asm/mach/mmc.h
@@ -146,7 +146,6 @@
unsigned int msmsdcc_fmid;
unsigned int msmsdcc_fmax;
bool nonremovable;
- bool pclk_src_dfab;
unsigned int mpm_sdiowakeup_int;
unsigned int wpswitch_gpio;
unsigned char wpswitch_polarity;
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index 81a9a71..87bb7d3 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -19,6 +19,7 @@
#include <linux/clockchips.h>
#include <linux/interrupt.h>
#include <linux/of_irq.h>
+#include <linux/of_address.h>
#include <linux/io.h>
#include <linux/irq.h>
@@ -32,8 +33,43 @@
static unsigned long arch_timer_rate;
static int arch_timer_ppi;
static int arch_timer_ppi2;
+static int is_irq_percpu;
static struct clock_event_device __percpu **arch_timer_evt;
+static void __iomem *timer_base;
+
+static u32 timer_reg_read_cp15(int reg);
+static void timer_reg_write_cp15(int reg, u32 val);
+static inline cycle_t counter_get_cntpct_cp15(void);
+static inline cycle_t counter_get_cntvct_cp15(void);
+
+static u32 timer_reg_read_mem(int reg);
+static void timer_reg_write_mem(int reg, u32 val);
+static inline cycle_t counter_get_cntpct_mem(void);
+static inline cycle_t counter_get_cntvct_mem(void);
+
+struct arch_timer_operations {
+ void (*reg_write)(int, u32);
+ u32 (*reg_read)(int);
+ cycle_t (*get_cntpct)(void);
+ cycle_t (*get_cntvct)(void);
+};
+
+static struct arch_timer_operations arch_timer_ops_cp15 = {
+ .reg_read = &timer_reg_read_cp15,
+ .reg_write = &timer_reg_write_cp15,
+ .get_cntpct = &counter_get_cntpct_cp15,
+ .get_cntvct = &counter_get_cntvct_cp15,
+};
+
+static struct arch_timer_operations arch_timer_ops_mem = {
+ .reg_read = &timer_reg_read_mem,
+ .reg_write = &timer_reg_write_mem,
+ .get_cntpct = &counter_get_cntpct_mem,
+ .get_cntvct = &counter_get_cntvct_mem,
+};
+
+static struct arch_timer_operations *arch_specific_timer = &arch_timer_ops_cp15;
/*
* Architected system timer support.
@@ -47,7 +83,29 @@
#define ARCH_TIMER_REG_FREQ 1
#define ARCH_TIMER_REG_TVAL 2
-static void arch_timer_reg_write(int reg, u32 val)
+/* Iomapped Register Offsets */
+#define QTIMER_CNTP_LOW_REG 0x000
+#define QTIMER_CNTP_HIGH_REG 0x004
+#define QTIMER_CNTV_LOW_REG 0x008
+#define QTIMER_CNTV_HIGH_REG 0x00C
+#define QTIMER_CTRL_REG 0x02C
+#define QTIMER_FREQ_REG 0x010
+#define QTIMER_CNTP_TVAL_REG 0x028
+#define QTIMER_CNTV_TVAL_REG 0x038
+
+static void timer_reg_write_mem(int reg, u32 val)
+{
+ switch (reg) {
+ case ARCH_TIMER_REG_CTRL:
+ __raw_writel(val, timer_base + QTIMER_CTRL_REG);
+ break;
+ case ARCH_TIMER_REG_TVAL:
+ __raw_writel(val, timer_base + QTIMER_CNTP_TVAL_REG);
+ break;
+ }
+}
+
+static void timer_reg_write_cp15(int reg, u32 val)
{
switch (reg) {
case ARCH_TIMER_REG_CTRL:
@@ -61,7 +119,28 @@
isb();
}
-static u32 arch_timer_reg_read(int reg)
+static u32 timer_reg_read_mem(int reg)
+{
+ u32 val;
+
+ switch (reg) {
+ case ARCH_TIMER_REG_CTRL:
+ val = __raw_readl(timer_base + QTIMER_CTRL_REG);
+ break;
+ case ARCH_TIMER_REG_FREQ:
+ val = __raw_readl(timer_base + QTIMER_FREQ_REG);
+ break;
+ case ARCH_TIMER_REG_TVAL:
+ val = __raw_readl(timer_base + QTIMER_CNTP_TVAL_REG);
+ break;
+ default:
+ BUG();
+ }
+
+ return val;
+}
+
+static u32 timer_reg_read_cp15(int reg)
{
u32 val;
@@ -87,10 +166,11 @@
struct clock_event_device *evt;
unsigned long ctrl;
- ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+ ctrl = arch_specific_timer->reg_read(ARCH_TIMER_REG_CTRL);
if (ctrl & ARCH_TIMER_CTRL_IT_STAT) {
ctrl |= ARCH_TIMER_CTRL_IT_MASK;
- arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+ arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL,
+ ctrl);
evt = *__this_cpu_ptr(arch_timer_evt);
evt->event_handler(evt);
return IRQ_HANDLED;
@@ -103,9 +183,9 @@
{
unsigned long ctrl;
- ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+ ctrl = arch_specific_timer->reg_read(ARCH_TIMER_REG_CTRL);
ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
- arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+ arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL, ctrl);
}
static void arch_timer_set_mode(enum clock_event_mode mode,
@@ -126,12 +206,12 @@
{
unsigned long ctrl;
- ctrl = arch_timer_reg_read(ARCH_TIMER_REG_CTRL);
+ ctrl = arch_specific_timer->reg_read(ARCH_TIMER_REG_CTRL);
ctrl |= ARCH_TIMER_CTRL_ENABLE;
ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
- arch_timer_reg_write(ARCH_TIMER_REG_CTRL, ctrl);
- arch_timer_reg_write(ARCH_TIMER_REG_TVAL, evt);
+ arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL, ctrl);
+ arch_specific_timer->reg_write(ARCH_TIMER_REG_TVAL, evt);
return 0;
}
@@ -168,19 +248,16 @@
static int local_timer_is_architected(void)
{
return (cpu_architecture() >= CPU_ARCH_ARMv7) &&
- ((read_cpuid_ext(CPUID_EXT_PFR1) >> 16) & 0xf) == 1;
+ ((read_cpuid_ext(CPUID_EXT_PFR1) >> 16) & 0xf) == 1;
}
static int arch_timer_available(void)
{
unsigned long freq;
- if (!local_timer_is_architected())
- return -ENXIO;
-
if (arch_timer_rate == 0) {
- arch_timer_reg_write(ARCH_TIMER_REG_CTRL, 0);
- freq = arch_timer_reg_read(ARCH_TIMER_REG_FREQ);
+ arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL, 0);
+ freq = arch_specific_timer->reg_read(ARCH_TIMER_REG_FREQ);
/* Check the timer frequency. */
if (freq == 0) {
@@ -196,33 +273,57 @@
return 0;
}
-static inline cycle_t arch_counter_get_cntpct(void)
+static inline cycle_t counter_get_cntpct_mem(void)
{
- u32 cvall, cvalh;
+ u32 cvall, cvalh, thigh;
- asm volatile("mrrc p15, 0, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
+ do {
+ cvalh = __raw_readl(timer_base + QTIMER_CNTP_HIGH_REG);
+ cvall = __raw_readl(timer_base + QTIMER_CNTP_LOW_REG);
+ thigh = __raw_readl(timer_base + QTIMER_CNTP_HIGH_REG);
+ } while (cvalh != thigh);
return ((cycle_t) cvalh << 32) | cvall;
}
-static inline cycle_t arch_counter_get_cntvct(void)
+static inline cycle_t counter_get_cntpct_cp15(void)
+{
+ u32 cvall, cvalh;
+
+ asm volatile("mrrc p15, 0, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
+ return ((cycle_t) cvalh << 32) | cvall;
+}
+
+static inline cycle_t counter_get_cntvct_mem(void)
+{
+ u32 cvall, cvalh, thigh;
+
+ do {
+ cvalh = __raw_readl(timer_base + QTIMER_CNTV_HIGH_REG);
+ cvall = __raw_readl(timer_base + QTIMER_CNTV_LOW_REG);
+ thigh = __raw_readl(timer_base + QTIMER_CNTV_HIGH_REG);
+ } while (cvalh != thigh);
+
+ return ((cycle_t) cvalh << 32) | cvall;
+}
+
+static inline cycle_t counter_get_cntvct_cp15(void)
{
u32 cvall, cvalh;
asm volatile("mrrc p15, 1, %0, %1, c14" : "=r" (cvall), "=r" (cvalh));
-
return ((cycle_t) cvalh << 32) | cvall;
}
static cycle_t arch_counter_read(struct clocksource *cs)
{
- return arch_counter_get_cntpct();
+ return arch_specific_timer->get_cntpct();
}
#ifdef ARCH_HAS_READ_CURRENT_TIMER
int read_current_timer(unsigned long *timer_val)
{
- *timer_val = (unsigned long)arch_counter_get_cntpct();
+ *timer_val = (unsigned long)arch_specific_timer->get_cntpct();
return 0;
}
#endif
@@ -239,7 +340,7 @@
{
cycle_t cntvct;
- cntvct = arch_counter_get_cntvct();
+ cntvct = arch_specific_timer->get_cntvct();
/*
* The sched_clock infrastructure only knows about counters
@@ -273,6 +374,11 @@
{
int err;
+ if (timer_base)
+ arch_specific_timer = &arch_timer_ops_mem;
+ else if (!local_timer_is_architected())
+ return -ENXIO;
+
err = arch_timer_available();
if (err)
return err;
@@ -289,8 +395,12 @@
set_delay_fn(read_current_timer_delay_loop);
#endif
- err = request_percpu_irq(arch_timer_ppi, arch_timer_handler,
+ if (is_irq_percpu)
+ err = request_percpu_irq(arch_timer_ppi, arch_timer_handler,
"arch_timer", arch_timer_evt);
+ else
+ err = request_irq(arch_timer_ppi, arch_timer_handler, 0,
+ "arch_timer", arch_timer_evt);
if (err) {
pr_err("arch_timer: can't register interrupt %d (%d)\n",
arch_timer_ppi, err);
@@ -298,8 +408,13 @@
}
if (arch_timer_ppi2) {
- err = request_percpu_irq(arch_timer_ppi2, arch_timer_handler,
- "arch_timer", arch_timer_evt);
+ if (is_irq_percpu)
+ err = request_percpu_irq(arch_timer_ppi2,
+ arch_timer_handler, "arch_timer",
+ arch_timer_evt);
+ else
+ err = request_irq(arch_timer_ppi2, arch_timer_handler,
+ 0, "arch_timer", arch_timer_evt);
if (err) {
pr_err("arch_timer: can't register interrupt %d (%d)\n",
arch_timer_ppi2, err);
@@ -336,6 +451,16 @@
if (at->res[1].start > 0 && (at->res[1].flags & IORESOURCE_IRQ))
arch_timer_ppi2 = at->res[1].start;
+ if (at->res[2].start > 0 && at->res[2].end > 0 &&
+ (at->res[2].flags & IORESOURCE_MEM))
+ timer_base = ioremap(at->res[2].start,
+ resource_size(&at->res[2]));
+
+ if (!timer_base) {
+ pr_err("arch_timer: cant map timer base\n");
+ return -ENOMEM;
+ }
+
return arch_timer_common_register();
}
@@ -366,6 +491,20 @@
pr_err("arch_timer: interrupt not specified in timer node\n");
return -ENODEV;
}
+
+ if (of_get_address(np, 0, NULL, NULL)) {
+ timer_base = of_iomap(np, 0);
+ if (!timer_base) {
+ pr_err("arch_timer: cant map timer base\n");
+ return -ENOMEM;
+ }
+ }
+
+ if (of_get_property(np, "irq-is-not-percpu", NULL))
+ is_irq_percpu = 0;
+ else
+ is_irq_percpu = 1;
+
arch_timer_ppi = ret;
ret = irq_of_parse_and_map(np, 1);
if (ret > 0)
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 08b65db..3554b56 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -2257,6 +2257,16 @@
separately. This will guarantee that the last acesses for each cpu
will be logged but there will be fewer entries per cpu
+config MSM_EBI_ERP
+ bool "External Bus Interface (EBI) error reporting"
+ help
+ Say 'Y' here to enable reporting of external bus interface errors to
+ the kernel log. Information such as the offending address and
+ transaction type will be logged. This may be useful for debugging
+ seemingly broken memory accesses.
+
+ For production builds, you should probably say 'N' here.
+
config MSM_CACHE_ERP
bool "Cache / CPU error reporting"
depends on ARCH_MSM_KRAIT
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index f316f36..eb9dc0a 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -288,7 +288,7 @@
obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
obj-$(CONFIG_ARCH_MSMCOPPER) += board-copper.o board-dt.o board-copper-regulator.o board-copper-gpiomux.o
obj-$(CONFIG_ARCH_MSMCOPPER) += acpuclock-krait.o acpuclock-copper.o
-obj-$(CONFIG_ARCH_MSMCOPPER) += clock-local2.o clock-pll.o clock-copper.o
+obj-$(CONFIG_ARCH_MSMCOPPER) += clock-local2.o clock-pll.o clock-copper.o clock-rpm.o clock-voter.o
obj-$(CONFIG_ARCH_MSMCOPPER) += gdsc.o
obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
@@ -331,6 +331,7 @@
obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60-vcm.o
endif
obj-$(CONFIG_MSM_OCMEM) += ocmem.o ocmem_allocator.o ocmem_notifier.o
+obj-$(CONFIG_MSM_OCMEM) += ocmem_sched.o ocmem_api.o
obj-$(CONFIG_ARCH_MSM7X27) += gpiomux-7x27.o gpiomux-v1.o gpiomux.o
obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-7x30.o gpiomux-v1.o gpiomux.o
@@ -364,6 +365,7 @@
obj-$(CONFIG_ARCH_MSM8960) += mdm2.o mdm_common.o
obj-$(CONFIG_MSM_RTB) += msm_rtb.o
obj-$(CONFIG_MSM_CACHE_ERP) += cache_erp.o
+obj-$(CONFIG_MSM_EBI_ERP) += ebi_erp.o
obj-$(CONFIG_MSM_CACHE_DUMP) += msm_cache_dump.o
obj-$(CONFIG_MSM_HSIC_SYSMON) += hsic_sysmon.o
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index 71ad49a..101a26d 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -58,11 +58,15 @@
};
#define LVDS_CHIMEI_PANEL_NAME "lvds_chimei_wxga"
+#define LVDS_FRC_PANEL_NAME "lvds_frc_fhd"
#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 TVOUT_PANEL_NAME "tvout_msm"
+#define LVDS_PIXEL_MAP_PATTERN_1 1
+#define LVDS_PIXEL_MAP_PATTERN_2 2
+
#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
static unsigned char hdmi_is_primary = 1;
#else
@@ -98,12 +102,18 @@
strnlen(MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
PANEL_NAME_MAX_LEN)))
return 0;
- } else if (machine_is_apq8064_cdp() ||
- machine_is_mpq8064_dtv()) {
+ } else if (machine_is_apq8064_cdp()) {
if (!strncmp(name, LVDS_CHIMEI_PANEL_NAME,
strnlen(LVDS_CHIMEI_PANEL_NAME,
PANEL_NAME_MAX_LEN)))
return 0;
+ } else if (machine_is_mpq8064_dtv()) {
+ if (!strncmp(name, LVDS_FRC_PANEL_NAME,
+ strnlen(LVDS_FRC_PANEL_NAME,
+ PANEL_NAME_MAX_LEN))) {
+ set_mdp_clocks_for_wuxga();
+ return 0;
+ }
}
if (!strncmp(name, HDMI_PANEL_NAME,
@@ -283,12 +293,16 @@
static int hdmi_enable_5v(int on);
static int hdmi_core_power(int on, int show);
static int hdmi_cec_power(int on);
+static int hdmi_gpio_config(int on);
+static int hdmi_panel_power(int on);
static struct msm_hdmi_platform_data hdmi_msm_data = {
.irq = HDMI_IRQ,
.enable_5v = hdmi_enable_5v,
.core_power = hdmi_core_power,
.cec_power = hdmi_cec_power,
+ .panel_power = hdmi_panel_power,
+ .gpio_config = hdmi_gpio_config,
};
static struct platform_device hdmi_msm_device = {
@@ -599,7 +613,9 @@
u32 ver = socinfo_get_version();
if ((SOCINFO_VERSION_MAJOR(ver) == 1) &&
(SOCINFO_VERSION_MINOR(ver) == 0))
- return 1;
+ return LVDS_PIXEL_MAP_PATTERN_1;
+ } else if (machine_is_mpq8064_dtv()) {
+ return LVDS_PIXEL_MAP_PATTERN_2;
}
return 0;
}
@@ -624,6 +640,23 @@
}
};
+#define FRC_GPIO_UPDATE (SX150X_EXP4_GPIO_BASE + 8)
+#define FRC_GPIO_RESET (SX150X_EXP4_GPIO_BASE + 9)
+#define FRC_GPIO_PWR (SX150X_EXP4_GPIO_BASE + 10)
+
+static int lvds_frc_gpio[] = {FRC_GPIO_UPDATE, FRC_GPIO_RESET, FRC_GPIO_PWR};
+static struct lvds_panel_platform_data lvds_frc_pdata = {
+ .gpio = lvds_frc_gpio,
+};
+
+static struct platform_device lvds_frc_panel_device = {
+ .name = "lvds_frc_fhd",
+ .id = 0,
+ .dev = {
+ .platform_data = &lvds_frc_pdata,
+ }
+};
+
static int dsi2lvds_gpio[2] = {
LPM_CHANNEL,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
@@ -687,8 +720,22 @@
static struct lcdc_platform_data dtv_pdata = {
.bus_scale_table = &dtv_bus_scale_pdata,
+ .lcdc_power_save = hdmi_panel_power,
};
+static int hdmi_panel_power(int on)
+{
+ int rc;
+
+ pr_debug("%s: HDMI Core: %s\n", __func__, (on ? "ON" : "OFF"));
+ rc = hdmi_core_power(on, 1);
+ if (rc)
+ rc = hdmi_cec_power(on);
+
+ pr_debug("%s: HDMI Core: %s Success\n", __func__, (on ? "ON" : "OFF"));
+ return rc;
+}
+
static int hdmi_enable_5v(int on)
{
/* TBD: PM8921 regulator instead of 8901 */
@@ -736,7 +783,6 @@
static struct regulator *reg_8921_lvs7, *reg_8921_s4, *reg_ext_3p3v;
static int prev_on;
int rc;
- int pmic_gpio14 = PM8921_GPIO_PM_TO_SYS(14);
if (on == prev_on)
return 0;
@@ -793,20 +839,61 @@
rc = regulator_enable(reg_ext_3p3v);
if (rc) {
pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
- return -ENODEV;
+ return rc;
}
rc = regulator_enable(reg_8921_lvs7);
if (rc) {
pr_err("'%s' regulator enable failed, rc=%d\n",
"hdmi_vdda", rc);
- return rc;
+ goto error1;
}
rc = regulator_enable(reg_8921_s4);
if (rc) {
pr_err("'%s' regulator enable failed, rc=%d\n",
"hdmi_lvl_tsl", rc);
- return rc;
+ goto error2;
}
+ pr_debug("%s(on): success\n", __func__);
+ } else {
+ rc = regulator_disable(reg_ext_3p3v);
+ if (rc) {
+ pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_disable(reg_8921_lvs7);
+ if (rc) {
+ pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_disable(reg_8921_s4);
+ if (rc) {
+ pr_err("disable reg_8921_s4 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ pr_debug("%s(off): success\n", __func__);
+ }
+
+ prev_on = on;
+
+ return 0;
+
+error2:
+ regulator_disable(reg_8921_lvs7);
+error1:
+ regulator_disable(reg_ext_3p3v);
+ return rc;
+}
+
+static int hdmi_gpio_config(int on)
+{
+ int rc = 0;
+ static int prev_on;
+ int pmic_gpio14 = PM8921_GPIO_PM_TO_SYS(14);
+
+ if (on == prev_on)
+ return 0;
+
+ if (on) {
rc = gpio_request(HDMI_DDC_CLK_GPIO, "HDMI_DDC_CLK");
if (rc) {
pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
@@ -844,27 +931,10 @@
gpio_set_value_cansleep(pmic_gpio14, 1);
gpio_free(pmic_gpio14);
}
-
- rc = regulator_disable(reg_ext_3p3v);
- if (rc) {
- pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
- return -ENODEV;
- }
- rc = regulator_disable(reg_8921_lvs7);
- if (rc) {
- pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
- return -ENODEV;
- }
- rc = regulator_disable(reg_8921_s4);
- if (rc) {
- pr_err("disable reg_8921_s4 failed, rc=%d\n", rc);
- return -ENODEV;
- }
pr_debug("%s(off): success\n", __func__);
}
prev_on = on;
-
return 0;
error4:
@@ -874,8 +944,6 @@
error2:
gpio_free(HDMI_DDC_CLK_GPIO);
error1:
- regulator_disable(reg_8921_lvs7);
- regulator_disable(reg_8921_s4);
return rc;
}
@@ -921,6 +989,8 @@
platform_device_register(&mipi_dsi2lvds_bridge_device);
if (machine_is_apq8064_mtp())
platform_device_register(&mipi_dsi_toshiba_panel_device);
+ if (machine_is_mpq8064_dtv())
+ platform_device_register(&lvds_frc_panel_device);
msm_fb_register_device("mdp", &mdp_pdata);
msm_fb_register_device("lvds", &lvds_pdata);
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 2009584..bef5cdc 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -236,11 +236,16 @@
14, 10, 6, 4, 1
};
+/*
+ * Note: There is a bug in LPG module that results in incorrect
+ * behavior of pattern when LUT index 0 is used. So effectively
+ * there are 63 usable LUT entries.
+ */
static struct pm8xxx_pwm_duty_cycles pm8921_led0_pwm_duty_cycles = {
.duty_pcts = (int *)&pm8921_led0_pwm_duty_pcts,
.num_duty_pcts = ARRAY_SIZE(pm8921_led0_pwm_duty_pcts),
.duty_ms = PM8XXX_LED_PWM_DUTY_MS,
- .start_idx = 0,
+ .start_idx = 1,
};
static struct pm8xxx_led_config pm8921_led_configs[] = {
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index 5f74468..fe4beab 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -247,7 +247,6 @@
#endif
.sup_clk_table = sdc1_sup_clk_rates,
.sup_clk_cnt = ARRAY_SIZE(sdc1_sup_clk_rates),
- .pclk_src_dfab = 1,
.nonremovable = 1,
.pin_data = &mmc_slot_pin_data[SDCC1],
.vreg_data = &mmc_slot_vreg_data[SDCC1],
@@ -270,7 +269,6 @@
.mmc_bus_width = MMC_CAP_4_BIT_DATA,
.sup_clk_table = sdc2_sup_clk_rates,
.sup_clk_cnt = ARRAY_SIZE(sdc2_sup_clk_rates),
- .pclk_src_dfab = 1,
.pin_data = &mmc_slot_pin_data[SDCC2],
.sdiowakeup_irq = MSM_GPIO_TO_INT(61),
.msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
@@ -290,7 +288,6 @@
.mmc_bus_width = MMC_CAP_4_BIT_DATA,
.sup_clk_table = sdc3_sup_clk_rates,
.sup_clk_cnt = ARRAY_SIZE(sdc3_sup_clk_rates),
- .pclk_src_dfab = 1,
.pin_data = &mmc_slot_pin_data[SDCC3],
.vreg_data = &mmc_slot_vreg_data[SDCC3],
.wpswitch_gpio = PM8921_GPIO_PM_TO_SYS(17),
@@ -322,7 +319,6 @@
.mmc_bus_width = MMC_CAP_4_BIT_DATA,
.sup_clk_table = sdc4_sup_clk_rates,
.sup_clk_cnt = ARRAY_SIZE(sdc4_sup_clk_rates),
- .pclk_src_dfab = 1,
.pin_data = &mmc_slot_pin_data[SDCC4],
.sdiowakeup_irq = MSM_GPIO_TO_INT(65),
.msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index e18e40d..8a837d6 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -516,12 +516,16 @@
static int hdmi_enable_5v(int on);
static int hdmi_core_power(int on, int show);
static int hdmi_cec_power(int on);
+static int hdmi_gpio_config(int on);
+static int hdmi_panel_power(int on);
static struct msm_hdmi_platform_data hdmi_msm_data = {
.irq = HDMI_IRQ,
.enable_5v = hdmi_enable_5v,
.core_power = hdmi_core_power,
.cec_power = hdmi_cec_power,
+ .panel_power = hdmi_panel_power,
+ .gpio_config = hdmi_gpio_config,
};
static struct platform_device hdmi_msm_device = {
@@ -594,7 +598,21 @@
static struct lcdc_platform_data dtv_pdata = {
.bus_scale_table = &dtv_bus_scale_pdata,
+ .lcdc_power_save = hdmi_panel_power,
};
+
+static int hdmi_panel_power(int on)
+{
+ int rc;
+
+ pr_debug("%s: HDMI Core: %s\n", __func__, (on ? "ON" : "OFF"));
+ rc = hdmi_core_power(on, 1);
+ if (rc)
+ rc = hdmi_cec_power(on);
+
+ pr_debug("%s: HDMI Core: %s Success\n", __func__, (on ? "ON" : "OFF"));
+ return rc;
+}
#endif
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
@@ -674,30 +692,8 @@
"hdmi_avdd", rc);
return rc;
}
- rc = gpio_request(100, "HDMI_DDC_CLK");
- if (rc) {
- pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
- "HDMI_DDC_CLK", 100, rc);
- goto error1;
- }
- rc = gpio_request(101, "HDMI_DDC_DATA");
- if (rc) {
- pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
- "HDMI_DDC_DATA", 101, rc);
- goto error2;
- }
- rc = gpio_request(102, "HDMI_HPD");
- if (rc) {
- pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
- "HDMI_HPD", 102, rc);
- goto error3;
- }
pr_debug("%s(on): success\n", __func__);
} else {
- gpio_free(100);
- gpio_free(101);
- gpio_free(102);
-
rc = regulator_disable(reg_8038_l23);
if (rc) {
pr_err("disable reg_8038_l23 failed, rc=%d\n", rc);
@@ -714,13 +710,50 @@
prev_on = on;
return 0;
+}
-error3:
- gpio_free(101);
+static int hdmi_gpio_config(int on)
+{
+ int rc = 0;
+ static int prev_on;
+
+ if (on == prev_on)
+ return 0;
+
+ if (on) {
+ rc = gpio_request(100, "HDMI_DDC_CLK");
+ if (rc) {
+ pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+ "HDMI_DDC_CLK", 100, rc);
+ return rc;
+ }
+ rc = gpio_request(101, "HDMI_DDC_DATA");
+ if (rc) {
+ pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+ "HDMI_DDC_DATA", 101, rc);
+ goto error1;
+ }
+ rc = gpio_request(102, "HDMI_HPD");
+ if (rc) {
+ pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+ "HDMI_HPD", 102, rc);
+ goto error2;
+ }
+ pr_debug("%s(on): success\n", __func__);
+ } else {
+ gpio_free(100);
+ gpio_free(101);
+ gpio_free(102);
+ pr_debug("%s(off): success\n", __func__);
+ }
+
+ prev_on = on;
+ return 0;
+
error2:
- gpio_free(100);
+ gpio_free(101);
error1:
- regulator_disable(reg_8038_l23);
+ gpio_free(100);
return rc;
}
diff --git a/arch/arm/mach-msm/board-8930-gpu.c b/arch/arm/mach-msm/board-8930-gpu.c
index e23b76c..3c3843a 100644
--- a/arch/arm/mach-msm/board-8930-gpu.c
+++ b/arch/arm/mach-msm/board-8930-gpu.c
@@ -115,7 +115,7 @@
static struct kgsl_device_platform_data kgsl_3d0_pdata = {
.pwrlevel = {
{
- .gpu_freq = 400000000,
+ .gpu_freq = 450000000,
.bus_freq = 3,
.io_fraction = 0,
},
diff --git a/arch/arm/mach-msm/board-8930-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
index cf7a829..188cf39 100644
--- a/arch/arm/mach-msm/board-8930-pmic.c
+++ b/arch/arm/mach-msm/board-8930-pmic.c
@@ -274,11 +274,16 @@
14, 10, 6, 4, 1
};
+/*
+ * Note: There is a bug in LPG module that results in incorrect
+ * behavior of pattern when LUT index 0 is used. So effectively
+ * there are 63 usable LUT entries.
+ */
static struct pm8xxx_pwm_duty_cycles pm8038_led0_pwm_duty_cycles = {
.duty_pcts = (int *)&pm8038_led0_pwm_duty_pcts,
.num_duty_pcts = ARRAY_SIZE(pm8038_led0_pwm_duty_pcts),
.duty_ms = PM8XXX_LED_PWM_DUTY_MS,
- .start_idx = 0,
+ .start_idx = 1,
};
static struct pm8xxx_led_config pm8038_led_configs[] = {
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index cb8903c..5bee8a2 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -485,7 +485,7 @@
RPM_LDO(L15, 0, 1, 0, 1800000, 2950000, 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, 1200000, 1200000, "8038_s2", 10000, 10000),
+ 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),
diff --git a/arch/arm/mach-msm/board-8930-storage.c b/arch/arm/mach-msm/board-8930-storage.c
index bb35c95..65da578 100644
--- a/arch/arm/mach-msm/board-8930-storage.c
+++ b/arch/arm/mach-msm/board-8930-storage.c
@@ -239,7 +239,6 @@
#endif
.sup_clk_table = sdc1_sup_clk_rates,
.sup_clk_cnt = ARRAY_SIZE(sdc1_sup_clk_rates),
- .pclk_src_dfab = 1,
.nonremovable = 1,
.vreg_data = &mmc_slot_vreg_data[SDCC1],
.pin_data = &mmc_slot_pin_data[SDCC1],
@@ -254,7 +253,6 @@
.mmc_bus_width = MMC_CAP_4_BIT_DATA,
.sup_clk_table = sdc3_sup_clk_rates,
.sup_clk_cnt = ARRAY_SIZE(sdc3_sup_clk_rates),
- .pclk_src_dfab = 1,
#ifdef CONFIG_MMC_MSM_SDC3_WP_SUPPORT
/*TODO: Insert right replacement for PM8038 */
#ifndef MSM8930_PHASE_2
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 712b520..8df37f7 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -786,13 +786,13 @@
{
.name = "VDDD_CDC_D",
.min_uV = 1200000,
- .max_uV = 1200000,
+ .max_uV = 1250000,
.optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
},
{
.name = "CDC_VDDA_A_1P2V",
.min_uV = 1200000,
- .max_uV = 1200000,
+ .max_uV = 1250000,
.optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
},
},
@@ -850,13 +850,13 @@
{
.name = "VDDD_CDC_D",
.min_uV = 1200000,
- .max_uV = 1200000,
+ .max_uV = 1250000,
.optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
},
{
.name = "CDC_VDDA_A_1P2V",
.min_uV = 1200000,
- .max_uV = 1200000,
+ .max_uV = 1250000,
.optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
},
},
@@ -1202,6 +1202,7 @@
[23] = MSM_GPIO_TO_INT(85),
[24] = MSM_GPIO_TO_INT(83),
[25] = USB1_HS_IRQ,
+ [26] = MSM_GPIO_TO_INT(6),
[27] = HDMI_IRQ,
[29] = MSM_GPIO_TO_INT(10),
[30] = MSM_GPIO_TO_INT(102),
@@ -1215,15 +1216,15 @@
[38] = MSM_GPIO_TO_INT(50),
[39] = MSM_GPIO_TO_INT(42),
[41] = MSM_GPIO_TO_INT(62),
- [42] = MSM_GPIO_TO_INT(76),
- [43] = MSM_GPIO_TO_INT(75),
+ [42] = MSM_GPIO_TO_INT(8),
+ [43] = MSM_GPIO_TO_INT(33),
[44] = MSM_GPIO_TO_INT(70),
[45] = MSM_GPIO_TO_INT(69),
[46] = MSM_GPIO_TO_INT(67),
[47] = MSM_GPIO_TO_INT(65),
- [48] = MSM_GPIO_TO_INT(58),
- [49] = MSM_GPIO_TO_INT(54),
- [50] = MSM_GPIO_TO_INT(52),
+ [48] = MSM_GPIO_TO_INT(55),
+ [49] = MSM_GPIO_TO_INT(74),
+ [50] = MSM_GPIO_TO_INT(98),
[51] = MSM_GPIO_TO_INT(49),
[52] = MSM_GPIO_TO_INT(40),
[53] = MSM_GPIO_TO_INT(37),
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index a9b2a59..c1017a9 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -717,12 +717,16 @@
static int hdmi_enable_5v(int on);
static int hdmi_core_power(int on, int show);
static int hdmi_cec_power(int on);
+static int hdmi_gpio_config(int on);
+static int hdmi_panel_power(int on);
static struct msm_hdmi_platform_data hdmi_msm_data = {
.irq = HDMI_IRQ,
.enable_5v = hdmi_enable_5v,
.core_power = hdmi_core_power,
.cec_power = hdmi_cec_power,
+ .panel_power = hdmi_panel_power,
+ .gpio_config = hdmi_gpio_config,
};
static struct platform_device hdmi_msm_device = {
@@ -784,7 +788,21 @@
static struct lcdc_platform_data dtv_pdata = {
.bus_scale_table = &dtv_bus_scale_pdata,
+ .lcdc_power_save = hdmi_panel_power,
};
+
+static int hdmi_panel_power(int on)
+{
+ int rc;
+
+ pr_debug("%s: HDMI Core: %s\n", __func__, (on ? "ON" : "OFF"));
+ rc = hdmi_core_power(on, 1);
+ if (rc)
+ rc = hdmi_cec_power(on);
+
+ pr_debug("%s: HDMI Core: %s Success\n", __func__, (on ? "ON" : "OFF"));
+ return rc;
+}
#endif
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
@@ -885,30 +903,8 @@
"hdmi_vcc", rc);
return rc;
}
- rc = gpio_request(100, "HDMI_DDC_CLK");
- if (rc) {
- pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
- "HDMI_DDC_CLK", 100, rc);
- goto error1;
- }
- rc = gpio_request(101, "HDMI_DDC_DATA");
- if (rc) {
- pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
- "HDMI_DDC_DATA", 101, rc);
- goto error2;
- }
- rc = gpio_request(102, "HDMI_HPD");
- if (rc) {
- pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
- "HDMI_HPD", 102, rc);
- goto error3;
- }
pr_debug("%s(on): success\n", __func__);
} else {
- gpio_free(100);
- gpio_free(101);
- gpio_free(102);
-
rc = regulator_disable(reg_8921_l23);
if (rc) {
pr_err("disable reg_8921_l23 failed, rc=%d\n", rc);
@@ -930,14 +926,50 @@
prev_on = on;
return 0;
+}
-error3:
- gpio_free(101);
+static int hdmi_gpio_config(int on)
+{
+ int rc = 0;
+ static int prev_on;
+
+ if (on == prev_on)
+ return 0;
+
+ if (on) {
+ rc = gpio_request(100, "HDMI_DDC_CLK");
+ if (rc) {
+ pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+ "HDMI_DDC_CLK", 100, rc);
+ return rc;
+ }
+ rc = gpio_request(101, "HDMI_DDC_DATA");
+ if (rc) {
+ pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+ "HDMI_DDC_DATA", 101, rc);
+ goto error1;
+ }
+ rc = gpio_request(102, "HDMI_HPD");
+ if (rc) {
+ pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
+ "HDMI_HPD", 102, rc);
+ goto error2;
+ }
+ pr_debug("%s(on): success\n", __func__);
+ } else {
+ gpio_free(100);
+ gpio_free(101);
+ gpio_free(102);
+ pr_debug("%s(off): success\n", __func__);
+ }
+
+ prev_on = on;
+ return 0;
+
error2:
- gpio_free(100);
+ gpio_free(101);
error1:
- regulator_disable(reg_8921_l23);
- regulator_disable(reg_8921_s4);
+ gpio_free(100);
return rc;
}
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index ea1ab58..977dbb2 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -529,11 +529,16 @@
14, 10, 6, 4, 1
};
+/*
+ * Note: There is a bug in LPG module that results in incorrect
+ * behavior of pattern when LUT index 0 is used. So effectively
+ * there are 63 usable LUT entries.
+ */
static struct pm8xxx_pwm_duty_cycles pm8921_led0_pwm_duty_cycles = {
.duty_pcts = (int *)&pm8921_led0_pwm_duty_pcts,
.num_duty_pcts = ARRAY_SIZE(pm8921_led0_pwm_duty_pcts),
.duty_ms = PM8XXX_LED_PWM_DUTY_MS,
- .start_idx = 0,
+ .start_idx = 1,
};
static struct pm8xxx_led_config pm8921_led_configs[] = {
diff --git a/arch/arm/mach-msm/board-8960-storage.c b/arch/arm/mach-msm/board-8960-storage.c
index 85785fc..e674e91 100644
--- a/arch/arm/mach-msm/board-8960-storage.c
+++ b/arch/arm/mach-msm/board-8960-storage.c
@@ -290,7 +290,6 @@
#endif
.sup_clk_table = sdc1_sup_clk_rates,
.sup_clk_cnt = ARRAY_SIZE(sdc1_sup_clk_rates),
- .pclk_src_dfab = 1,
.nonremovable = 1,
.vreg_data = &mmc_slot_vreg_data[SDCC1],
.pin_data = &mmc_slot_pin_data[SDCC1],
@@ -309,7 +308,6 @@
.mmc_bus_width = MMC_CAP_4_BIT_DATA,
.sup_clk_table = sdc2_sup_clk_rates,
.sup_clk_cnt = ARRAY_SIZE(sdc2_sup_clk_rates),
- .pclk_src_dfab = 1,
.vreg_data = &mmc_slot_vreg_data[SDCC2],
.pin_data = &mmc_slot_pin_data[SDCC2],
.sdiowakeup_irq = MSM_GPIO_TO_INT(90),
@@ -323,7 +321,6 @@
.mmc_bus_width = MMC_CAP_4_BIT_DATA,
.sup_clk_table = sdc3_sup_clk_rates,
.sup_clk_cnt = ARRAY_SIZE(sdc3_sup_clk_rates),
- .pclk_src_dfab = 1,
#ifdef CONFIG_MMC_MSM_SDC3_WP_SUPPORT
.wpswitch_gpio = PM8921_GPIO_PM_TO_SYS(16),
#endif
@@ -354,7 +351,6 @@
.mmc_bus_width = MMC_CAP_4_BIT_DATA,
.sup_clk_table = sdc4_sup_clk_rates,
.sup_clk_cnt = ARRAY_SIZE(sdc4_sup_clk_rates),
- .pclk_src_dfab = 1,
.vreg_data = &mmc_slot_vreg_data[SDCC4],
.pin_data = &mmc_slot_pin_data[SDCC4],
.sdiowakeup_irq = MSM_GPIO_TO_INT(85),
diff --git a/arch/arm/mach-msm/board-9615-storage.c b/arch/arm/mach-msm/board-9615-storage.c
index 51e2432..2025bd0 100644
--- a/arch/arm/mach-msm/board-9615-storage.c
+++ b/arch/arm/mach-msm/board-9615-storage.c
@@ -176,7 +176,6 @@
.mmc_bus_width = MMC_CAP_4_BIT_DATA,
.sup_clk_table = sdc1_sup_clk_rates,
.sup_clk_cnt = ARRAY_SIZE(sdc1_sup_clk_rates),
- .pclk_src_dfab = true,
.vreg_data = &mmc_slot_vreg_data[SDCC1],
.pin_data = &mmc_slot_pin_data[SDCC1],
#ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION
@@ -205,7 +204,6 @@
.mmc_bus_width = MMC_CAP_4_BIT_DATA,
.sup_clk_table = sdc2_sup_clk_rates,
.sup_clk_cnt = ARRAY_SIZE(sdc2_sup_clk_rates),
- .pclk_src_dfab = 1,
.pin_data = &mmc_slot_pin_data[SDCC2],
.sdiowakeup_irq = MSM_GPIO_TO_INT(GPIO_SDC2_DAT1_WAKEUP),
.msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index 2afefa6..614cfe2 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -421,33 +421,6 @@
platform_device_register(&copper_device_tz_log);
}
-/*
- * Used to satisfy dependencies for devices that need to be
- * run early or in a particular order. Most likely your device doesn't fall
- * into this category, and thus the driver should not be added here. The
- * EPROBE_DEFER can satisfy most dependency problems.
- */
-void __init msm_copper_add_drivers(void)
-{
- msm_smd_init();
- msm_rpm_driver_init();
- rpm_regulator_smd_driver_init();
- msm_spm_device_init();
- regulator_stub_init();
-}
-
-static struct of_device_id irq_match[] __initdata = {
- { .compatible = "qcom,msm-qgic2", .data = gic_of_init, },
- { .compatible = "qcom,msm-gpio", .data = msm_gpio_of_init, },
- { .compatible = "qcom,spmi-pmic-arb", .data = qpnpint_of_init, },
- {}
-};
-
-void __init msm_copper_init_irq(void)
-{
- of_irq_init(irq_match);
-}
-
static struct clk_lookup msm_clocks_dummy[] = {
CLK_DUMMY("xo", XO_CLK, NULL, OFF),
CLK_DUMMY("xo", XO_CLK, "pil_pronto", OFF),
@@ -476,6 +449,37 @@
.size = ARRAY_SIZE(msm_clocks_dummy),
};
+/*
+ * Used to satisfy dependencies for devices that need to be
+ * run early or in a particular order. Most likely your device doesn't fall
+ * into this category, and thus the driver should not be added here. The
+ * EPROBE_DEFER can satisfy most dependency problems.
+ */
+void __init msm_copper_add_drivers(void)
+{
+ msm_smd_init();
+ msm_rpm_driver_init();
+ rpm_regulator_smd_driver_init();
+ msm_spm_device_init();
+ regulator_stub_init();
+ if (machine_is_copper_rumi())
+ msm_clock_init(&msm_dummy_clock_init_data);
+ else
+ msm_clock_init(&msmcopper_clock_init_data);
+}
+
+static struct of_device_id irq_match[] __initdata = {
+ { .compatible = "qcom,msm-qgic2", .data = gic_of_init, },
+ { .compatible = "qcom,msm-gpio", .data = msm_gpio_of_init, },
+ { .compatible = "qcom,spmi-pmic-arb", .data = qpnpint_of_init, },
+ {}
+};
+
+void __init msm_copper_init_irq(void)
+{
+ of_irq_init(irq_match);
+}
+
static struct of_dev_auxdata msm_copper_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF991F000, \
"msm_serial_hsl.0", NULL),
@@ -503,6 +507,8 @@
"pil_pronto", NULL),
OF_DEV_AUXDATA("qcom,msm-rng", 0xF9BFF000, \
"msm_rng", NULL),
+ OF_DEV_AUXDATA("qcom,qseecom", 0xFE806000, \
+ "qseecom", NULL),
{}
};
@@ -510,11 +516,6 @@
{
msm_copper_init_gpiomux();
- if (machine_is_copper_rumi())
- msm_clock_init(&msm_dummy_clock_init_data);
- else
- msm_clock_init(&msmcopper_clock_init_data);
-
*adata = msm_copper_auxdata_lookup;
regulator_has_full_constraints();
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index bd38f30..3da68ad 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -497,12 +497,10 @@
} else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7()) {
if (!strncmp(name, "lcdc_truly_hvga_ips3p2335_pt", 28))
ret = 0;
- } else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
+ } else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb() ||
+ machine_is_msm8625_evt()) {
if (!strncmp(name, "mipi_cmd_nt35510_wvga", 21))
ret = 0;
- } else if (machine_is_msm8625_evt()) {
- if (!strncmp(name, "mipi_video_nt35510_wvga", 23))
- ret = 0;
}
#if !defined(CONFIG_FB_MSM_LCDC_AUTO_DETECT) && \
@@ -579,90 +577,98 @@
};
#endif
-static int evb_backlight_control(int level)
+static int evb_backlight_control(int level, int mode)
{
int i = 0;
- int remainder;
+ int remainder, ret = 0;
+
/* device address byte = 0x72 */
- gpio_set_value(96, 0);
- udelay(67);
- gpio_set_value(96, 1);
- udelay(33);
- gpio_set_value(96, 0);
- udelay(33);
- gpio_set_value(96, 1);
- udelay(67);
- gpio_set_value(96, 0);
- udelay(33);
- gpio_set_value(96, 1);
- udelay(67);
- gpio_set_value(96, 0);
- udelay(33);
- gpio_set_value(96, 1);
- udelay(67);
- gpio_set_value(96, 0);
- udelay(67);
- gpio_set_value(96, 1);
- udelay(33);
- gpio_set_value(96, 0);
- udelay(67);
- gpio_set_value(96, 1);
- udelay(33);
- gpio_set_value(96, 0);
- udelay(33);
- gpio_set_value(96, 1);
- udelay(67);
- gpio_set_value(96, 0);
- udelay(67);
- gpio_set_value(96, 1);
- udelay(33);
+ if (!mode) {
+ gpio_set_value(96, 0);
+ udelay(67);
+ gpio_set_value(96, 1);
+ udelay(33);
+ gpio_set_value(96, 0);
+ udelay(33);
+ gpio_set_value(96, 1);
+ udelay(67);
+ gpio_set_value(96, 0);
+ udelay(33);
+ gpio_set_value(96, 1);
+ udelay(67);
+ gpio_set_value(96, 0);
+ udelay(33);
+ gpio_set_value(96, 1);
+ udelay(67);
+ gpio_set_value(96, 0);
+ udelay(67);
+ gpio_set_value(96, 1);
+ udelay(33);
+ gpio_set_value(96, 0);
+ udelay(67);
+ gpio_set_value(96, 1);
+ udelay(33);
+ gpio_set_value(96, 0);
+ udelay(33);
+ gpio_set_value(96, 1);
+ udelay(67);
+ gpio_set_value(96, 0);
+ udelay(67);
+ gpio_set_value(96, 1);
+ udelay(33);
- /* t-EOS and t-start */
- gpio_set_value(96, 0);
- ndelay(4200);
- gpio_set_value(96, 1);
- ndelay(9000);
+ /* t-EOS and t-start */
+ gpio_set_value(96, 0);
+ ndelay(4200);
+ gpio_set_value(96, 1);
+ ndelay(9000);
- /* data byte */
- /* RFA = 0 */
- gpio_set_value(96, 0);
- udelay(67);
- gpio_set_value(96, 1);
- udelay(33);
+ /* data byte */
+ /* RFA = 0 */
+ gpio_set_value(96, 0);
+ udelay(67);
+ gpio_set_value(96, 1);
+ udelay(33);
- /* Address bits */
- gpio_set_value(96, 0);
- udelay(67);
- gpio_set_value(96, 1);
- udelay(33);
- gpio_set_value(96, 0);
- udelay(67);
- gpio_set_value(96, 1);
- udelay(33);
+ /* Address bits */
+ gpio_set_value(96, 0);
+ udelay(67);
+ gpio_set_value(96, 1);
+ udelay(33);
+ gpio_set_value(96, 0);
+ udelay(67);
+ gpio_set_value(96, 1);
+ udelay(33);
- /* Data bits */
- for (i = 0; i < 5; i++) {
- remainder = (level) & (16);
- if (remainder) {
- gpio_set_value(96, 0);
- udelay(33);
- gpio_set_value(96, 1);
- udelay(67);
- } else {
- gpio_set_value(96, 0);
- udelay(67);
- gpio_set_value(96, 1);
- udelay(33);
+ /* Data bits */
+ for (i = 0; i < 5; i++) {
+ remainder = (level) & (16);
+ if (remainder) {
+ gpio_set_value(96, 0);
+ udelay(33);
+ gpio_set_value(96, 1);
+ udelay(67);
+ } else {
+ gpio_set_value(96, 0);
+ udelay(67);
+ gpio_set_value(96, 1);
+ udelay(33);
+ }
+ level = level << 1;
}
- level = level << 1;
+
+ /* t-EOS */
+ gpio_set_value(96, 0);
+ ndelay(12000);
+ gpio_set_value(96, 1);
+ } else {
+ ret = pmapp_disp_backlight_set_brightness(level);
+ if (ret)
+ pr_err("%s: can't set lcd backlight!\n", __func__);
}
- /* t-EOS */
- gpio_set_value(96, 0);
- ndelay(12000);
- gpio_set_value(96, 1);
- return 0;
+ return ret;
}
static int mipi_NT35510_rotate_panel(void)
@@ -687,7 +693,7 @@
};
static struct msm_panel_common_pdata mipi_NT35510_pdata = {
- .pmic_backlight = evb_backlight_control,
+ .backlight = evb_backlight_control,
.rotate_panel = mipi_NT35510_rotate_panel,
};
@@ -700,7 +706,7 @@
};
static struct msm_panel_common_pdata mipi_NT35516_pdata = {
- .pmic_backlight = evb_backlight_control,
+ .backlight = evb_backlight_control,
};
static struct platform_device mipi_dsi_NT35516_panel_device = {
@@ -1140,54 +1146,30 @@
static int mipi_dsi_panel_qrd3_power(int on)
{
int rc = 0;
+ static struct regulator *gpio_reg_2p85v, *gpio_reg_1p8v;
if (!qrd3_dsi_gpio_initialized) {
+ pmapp_disp_backlight_init();
rc = gpio_request(GPIO_QRD3_LCD_BACKLIGHT_EN,
"qrd3_gpio_bkl_en");
if (rc < 0)
return rc;
- rc = gpio_request(GPIO_QRD3_LCD_EXT_2V85_EN,
- "qrd3_gpio_ext_2v85_en");
- if (rc < 0)
- return rc;
-
- rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_EXT_2V85_EN, 0,
- GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
- GPIO_CFG_ENABLE);
- if (rc < 0) {
- pr_err("failed QRD3 GPIO_QRD3_LCD_EXT_2V85_EN tlmm config\n");
- return rc;
+ gpio_reg_2p85v = regulator_get(&msm8625_mipi_dsi_device.dev,
+ "lcd_vdd");
+ if (IS_ERR(gpio_reg_2p85v)) {
+ pr_err("%s:ext_2p85v regulator get failed", __func__);
+ return -EINVAL;
}
- rc = gpio_direction_output(GPIO_QRD3_LCD_EXT_2V85_EN, 1);
- if (rc < 0) {
- pr_err("failed to enable external 2V85\n");
- gpio_free(GPIO_QRD3_LCD_EXT_2V85_EN);
- return rc;
+ gpio_reg_1p8v = regulator_get(&msm8625_mipi_dsi_device.dev,
+ "lcd_vddi");
+ if (IS_ERR(gpio_reg_1p8v)) {
+ pr_err("%s:ext_1p8v regulator get failed", __func__);
+ return -EINVAL;
}
- rc = gpio_request(GPIO_QRD3_LCD_EXT_1V8_EN,
- "qrd3_gpio_ext_1v8_en");
- if (rc < 0)
- return rc;
-
- rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_EXT_1V8_EN, 0,
- GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
- GPIO_CFG_ENABLE);
- if (rc < 0) {
- pr_err("failed QRD3 GPIO_QRD3_LCD_EXT_1V8_EN tlmm config\n");
- return rc;
- }
-
- rc = gpio_direction_output(GPIO_QRD3_LCD_EXT_1V8_EN, 1);
- if (rc < 0) {
- pr_err("failed to enable external 1v8\n");
- gpio_free(GPIO_QRD3_LCD_EXT_1V8_EN);
- return rc;
- }
-
- qrd3_dsi_gpio_initialized = 1;
+ qrd3_dsi_gpio_initialized = 1;
}
if (on) {
@@ -1204,7 +1186,7 @@
gpio_free(GPIO_QRD3_LCD_BACKLIGHT_EN);
return rc;
}
-
+ /*Toggle Backlight GPIO*/
gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
udelay(190);
gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 0);
@@ -1212,18 +1194,17 @@
gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
/* 1 wire mode starts from this low to high transition */
udelay(50);
- } else {
- gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0,
- GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
- GPIO_CFG_DISABLE);
- }
- gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_2V85_EN, !!on);
- gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_1V8_EN, !!on);
+ /*Enable EXT_2.85 and 1.8 regulators*/
+ rc = regulator_enable(gpio_reg_2p85v);
+ if (rc < 0)
+ pr_err("%s: reg enable failed\n", __func__);
+ rc = regulator_enable(gpio_reg_1p8v);
+ if (rc < 0)
+ pr_err("%s: reg enable failed\n", __func__);
- if (on) {
+ /*Configure LCD Bridge reset*/
rc = gpio_tlmm_config(qrd3_mipi_dsi_gpio[0], GPIO_CFG_ENABLE);
-
if (rc < 0) {
pr_err("Failed to enable LCD Bridge reset enable\n");
return rc;
@@ -1237,18 +1218,32 @@
return rc;
}
+ /*Toggle Bridge Reset GPIO*/
msleep(20);
gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 0);
msleep(20);
gpio_set_value_cansleep(GPIO_QRD3_LCD_BRDG_RESET_N, 1);
msleep(20);
+
} else {
+ gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0,
+ GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
+ GPIO_CFG_DISABLE);
+
gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BRDG_RESET_N, 0,
GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
GPIO_CFG_DISABLE);
+
+ rc = regulator_disable(gpio_reg_2p85v);
+ if (rc < 0)
+ pr_err("%s: reg disable failed\n", __func__);
+ rc = regulator_disable(gpio_reg_1p8v);
+ if (rc < 0)
+ pr_err("%s: reg disable failed\n", __func__);
+
}
- return rc;
+ return rc;
}
static int mipi_dsi_panel_power(int on)
diff --git a/arch/arm/mach-msm/board-msm7627a-wlan.c b/arch/arm/mach-msm/board-msm7627a-wlan.c
index 07b7ab0..0949c5f 100644
--- a/arch/arm/mach-msm/board-msm7627a-wlan.c
+++ b/arch/arm/mach-msm/board-msm7627a-wlan.c
@@ -327,13 +327,16 @@
}
gpio_set_value(gpio_wlan_sys_rest_en, 0);
} else {
- gpio_request(gpio_wlan_sys_rest_en, "WLAN_DEEP_SLEEP_N");
- rc = setup_wlan_gpio(on);
- if (rc) {
- pr_err("%s: wlan_set_gpio = %d\n", __func__, rc);
- goto set_gpio_fail;
+ rc = gpio_request(gpio_wlan_sys_rest_en, "WLAN_DEEP_SLEEP_N");
+ if (!rc) {
+ rc = setup_wlan_gpio(on);
+ if (rc) {
+ pr_err("%s: setup_wlan_gpio = %d\n",
+ __func__, rc);
+ goto set_gpio_fail;
+ }
+ gpio_free(gpio_wlan_sys_rest_en);
}
- gpio_free(gpio_wlan_sys_rest_en);
}
/* GPIO_WLAN_3V3_EN is only required for the QRD7627a */
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 1c32b5e..1521a6c 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -650,7 +650,12 @@
u32 low_voltage = msm_psy_batt_data.voltage_min_design;
u32 high_voltage = msm_psy_batt_data.voltage_max_design;
- return (current_voltage - low_voltage) * 100
+ if (current_voltage <= low_voltage)
+ return 0;
+ else if (current_voltage >= high_voltage)
+ return 100;
+ else
+ return (current_voltage - low_voltage) * 100
/ (high_voltage - low_voltage);
}
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 73a900c..102f6ac 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -3083,13 +3083,17 @@
static int hdmi_enable_5v(int on);
static int hdmi_core_power(int on, int show);
+static int hdmi_gpio_config(int on);
static int hdmi_cec_power(int on);
+static int hdmi_panel_power(int on);
static struct msm_hdmi_platform_data hdmi_msm_data = {
.irq = HDMI_IRQ,
.enable_5v = hdmi_enable_5v,
.core_power = hdmi_core_power,
.cec_power = hdmi_cec_power,
+ .panel_power = hdmi_panel_power,
+ .gpio_config = hdmi_gpio_config,
};
static struct platform_device hdmi_msm_device = {
@@ -8389,7 +8393,6 @@
.msmsdcc_fmid = 24000000,
.msmsdcc_fmax = 48000000,
.nonremovable = 1,
- .pclk_src_dfab = 1,
.msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
};
#endif
@@ -8404,7 +8407,6 @@
.msmsdcc_fmid = 24000000,
.msmsdcc_fmax = 48000000,
.nonremovable = 0,
- .pclk_src_dfab = 1,
.register_status_notify = sdc2_register_status_notify,
#ifdef CONFIG_MSM_SDIO_AL
.is_sdio_al_client = 1,
@@ -8429,7 +8431,6 @@
.msmsdcc_fmid = 24000000,
.msmsdcc_fmax = 48000000,
.nonremovable = 0,
- .pclk_src_dfab = 1,
.mpm_sdiowakeup_int = MSM_MPM_PIN_SDC3_DAT1,
.msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
};
@@ -8444,7 +8445,6 @@
.msmsdcc_fmid = 24000000,
.msmsdcc_fmax = 48000000,
.nonremovable = 0,
- .pclk_src_dfab = 1,
.mpm_sdiowakeup_int = MSM_MPM_PIN_SDC4_DAT1,
.msm_bus_voting_data = &sps_to_ddr_bus_voting_data,
};
@@ -8460,7 +8460,6 @@
.msmsdcc_fmid = 24000000,
.msmsdcc_fmax = 48000000,
.nonremovable = 0,
- .pclk_src_dfab = 1,
.register_status_notify = sdc5_register_status_notify,
#ifdef CONFIG_MSM_SDIO_AL
.is_sdio_al_client = 1,
@@ -9011,6 +9010,29 @@
"8058_l16", rc);
return rc;
}
+ pr_debug("%s(on): success\n", __func__);
+ } else {
+ rc = regulator_disable(reg_8058_l16);
+ if (rc)
+ pr_warning("'%s' regulator disable failed, rc=%d\n",
+ "8058_l16", rc);
+ pr_debug("%s(off): success\n", __func__);
+ }
+
+ prev_on = on;
+
+ return 0;
+}
+
+static int hdmi_gpio_config(int on)
+{
+ int rc = 0;
+ static int prev_on;
+
+ if (on == prev_on)
+ return 0;
+
+ if (on) {
rc = gpio_request(170, "HDMI_DDC_CLK");
if (rc) {
pr_err("'%s'(%d) gpio_request failed, rc=%d\n",
@@ -9029,20 +9051,15 @@
"HDMI_HPD", 172, rc);
goto error3;
}
- pr_info("%s(on): success\n", __func__);
+ pr_debug("%s(on): success\n", __func__);
} else {
gpio_free(170);
gpio_free(171);
gpio_free(172);
- rc = regulator_disable(reg_8058_l16);
- if (rc)
- pr_warning("'%s' regulator disable failed, rc=%d\n",
- "8058_l16", rc);
- pr_info("%s(off): success\n", __func__);
+ pr_debug("%s(off): success\n", __func__);
}
prev_on = on;
-
return 0;
error3:
@@ -9050,7 +9067,6 @@
error2:
gpio_free(170);
error1:
- regulator_disable(reg_8058_l16);
return rc;
}
@@ -9099,6 +9115,18 @@
return rc;
}
+static int hdmi_panel_power(int on)
+{
+ int rc;
+
+ pr_debug("%s: HDMI Core: %s\n", __func__, (on ? "ON" : "OFF"));
+ rc = hdmi_core_power(on, 1);
+ if (rc)
+ rc = hdmi_cec_power(on);
+
+ pr_debug("%s: HDMI Core: %s Success\n", __func__, (on ? "ON" : "OFF"));
+ return rc;
+}
#undef _GET_REGULATOR
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL */
@@ -9521,6 +9549,7 @@
static struct lcdc_platform_data dtv_pdata = {
.bus_scale_table = &dtv_bus_scale_pdata,
+ .lcdc_power_save = hdmi_panel_power,
};
static struct msm_bus_paths dtv_hdmi_prim_bus_scale_usecases[] = {
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 761a3c9..d8d8934 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -596,7 +596,12 @@
u32 low_voltage = msm_psy_batt_data.voltage_min_design;
u32 high_voltage = msm_psy_batt_data.voltage_max_design;
- return (current_voltage - low_voltage) * 100
+ if (current_voltage <= low_voltage)
+ return 0;
+ else if (current_voltage >= high_voltage)
+ return 100;
+ else
+ return (current_voltage - low_voltage) * 100
/ (high_voltage - low_voltage);
}
@@ -652,14 +657,16 @@
#define GPIO_VREG_ID_EXT_1P8V 1
static struct regulator_consumer_supply vreg_consumers_EXT_2P85V[] = {
- REGULATOR_SUPPLY("cam0_avdd", "0-006c"),
- REGULATOR_SUPPLY("cam1_avdd", "0-0078"),
+ REGULATOR_SUPPLY("cam_ov5647_avdd", "0-006c"),
+ REGULATOR_SUPPLY("cam_ov7692_avdd", "0-0078"),
+ REGULATOR_SUPPLY("cam_ov8825_avdd", "0-000d"),
REGULATOR_SUPPLY("lcd_vdd", "mipi_dsi.1"),
};
static struct regulator_consumer_supply vreg_consumers_EXT_1P8V[] = {
- REGULATOR_SUPPLY("cam0_vdd", "0-006c"),
- REGULATOR_SUPPLY("cam1_vdd", "0-0078"),
+ REGULATOR_SUPPLY("cam_ov5647_vdd", "0-006c"),
+ REGULATOR_SUPPLY("cam_ov7692_vdd", "0-0078"),
+ REGULATOR_SUPPLY("cam_ov8825_vdd", "0-000d"),
REGULATOR_SUPPLY("lcd_vddi", "mipi_dsi.1"),
};
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index c4ada1e..5867eef 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -934,6 +934,7 @@
.c = {
.dbg_name = "gfx2d0_p_clk",
.ops = &clk_ops_branch,
+ .flags = CLKFLAG_SKIP_HANDOFF,
CLK_INIT(gfx2d0_p_clk.c),
},
};
@@ -952,6 +953,7 @@
.c = {
.dbg_name = "gfx2d1_p_clk",
.ops = &clk_ops_branch,
+ .flags = CLKFLAG_SKIP_HANDOFF,
CLK_INIT(gfx2d1_p_clk.c),
},
};
@@ -3346,6 +3348,7 @@
.c = {
.dbg_name = "gfx2d0_clk",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_SKIP_HANDOFF,
VDD_DIG_FMAX_MAP3(LOW, 100000000, NOMINAL, 200000000,
HIGH, 228571000),
CLK_INIT(gfx2d0_clk.c),
@@ -3390,6 +3393,7 @@
.c = {
.dbg_name = "gfx2d1_clk",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_SKIP_HANDOFF,
VDD_DIG_FMAX_MAP3(LOW, 100000000, NOMINAL, 200000000,
HIGH, 228571000),
CLK_INIT(gfx2d1_clk.c),
@@ -4598,7 +4602,6 @@
static DEFINE_CLK_VOTER(dfab_bam_dmux_clk, &dfab_clk.c, 0);
static DEFINE_CLK_VOTER(dfab_scm_clk, &dfab_clk.c, 0);
static DEFINE_CLK_VOTER(dfab_qseecom_clk, &dfab_clk.c, 0);
-static DEFINE_CLK_VOTER(dfab_tzcom_clk, &dfab_clk.c, 0);
static DEFINE_CLK_VOTER(dfab_msmbus_clk, &dfab_clk.c, 0);
static DEFINE_CLK_VOTER(dfab_msmbus_a_clk, &dfab_a_clk.c, 0);
@@ -5305,7 +5308,6 @@
CLK_LOOKUP("bus_clk", dfab_bam_dmux_clk.c, "BAM_RMNT"),
CLK_LOOKUP("bus_clk", dfab_scm_clk.c, "scm"),
CLK_LOOKUP("bus_clk", dfab_qseecom_clk.c, "qseecom"),
- CLK_LOOKUP("bus_clk", dfab_tzcom_clk.c, "tzcom"),
CLK_LOOKUP("alt_core_clk", usb_hsic_xcvr_fs_clk.c, "msm_hsic_host"),
CLK_LOOKUP("phy_clk", usb_hsic_hsic_clk.c, "msm_hsic_host"),
@@ -5650,7 +5652,6 @@
CLK_LOOKUP("bus_clk", dfab_bam_dmux_clk.c, "BAM_RMNT"),
CLK_LOOKUP("bus_clk", dfab_scm_clk.c, "scm"),
CLK_LOOKUP("bus_clk", dfab_qseecom_clk.c, "qseecom"),
- CLK_LOOKUP("bus_clk", dfab_tzcom_clk.c, "tzcom"),
CLK_LOOKUP("mem_clk", ebi1_adm_clk.c, "msm_dmov"),
CLK_LOOKUP("mem_clk", ebi1_acpu_a_clk.c, ""),
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 975587d..74d71a2 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -700,6 +700,7 @@
.c = {
.dbg_name = "gfx2d0_p_clk",
.ops = &clk_ops_branch,
+ .flags = CLKFLAG_SKIP_HANDOFF,
CLK_INIT(gfx2d0_p_clk.c),
},
};
@@ -716,6 +717,7 @@
.c = {
.dbg_name = "gfx2d1_p_clk",
.ops = &clk_ops_branch,
+ .flags = CLKFLAG_SKIP_HANDOFF,
CLK_INIT(gfx2d1_p_clk.c),
},
};
@@ -2178,6 +2180,7 @@
.c = {
.dbg_name = "gfx2d0_clk",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_SKIP_HANDOFF,
VDD_DIG_FMAX_MAP3(LOW, 100000000, NOMINAL, 200000000,
HIGH, 228571000),
CLK_INIT(gfx2d0_clk.c),
@@ -2222,6 +2225,7 @@
.c = {
.dbg_name = "gfx2d1_clk",
.ops = &clk_ops_rcg,
+ .flags = CLKFLAG_SKIP_HANDOFF,
VDD_DIG_FMAX_MAP3(LOW, 100000000, NOMINAL, 200000000,
HIGH, 228571000),
CLK_INIT(gfx2d1_clk.c),
diff --git a/arch/arm/mach-msm/clock-copper.c b/arch/arm/mach-msm/clock-copper.c
index 778301b..6ddf1a0 100644
--- a/arch/arm/mach-msm/clock-copper.c
+++ b/arch/arm/mach-msm/clock-copper.c
@@ -23,6 +23,8 @@
#include "clock-local2.h"
#include "clock-pll.h"
+#include "clock-rpm.h"
+#include "clock-voter.h"
enum {
GCC_BASE,
@@ -713,6 +715,37 @@
},
};
+#define RPM_BUS_CLK_TYPE 0x316b6c63
+#define RPM_MEM_CLK_TYPE 0x326b6c63
+
+#define PNOC_ID 0x0
+#define SNOC_ID 0x1
+#define CNOC_ID 0x2
+
+#define BIMC_ID 0x0
+#define OCMEM_ID 0x1
+
+DEFINE_CLK_RPM_SMD(pnoc_clk, pnoc_a_clk, RPM_BUS_CLK_TYPE, PNOC_ID, NULL);
+DEFINE_CLK_RPM_SMD(snoc_clk, snoc_a_clk, RPM_BUS_CLK_TYPE, SNOC_ID, NULL);
+DEFINE_CLK_RPM_SMD(cnoc_clk, cnoc_a_clk, RPM_BUS_CLK_TYPE, CNOC_ID, NULL);
+
+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);
+
+static DEFINE_CLK_VOTER(pnoc_msmbus_clk, &pnoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(snoc_msmbus_clk, &snoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(cnoc_msmbus_clk, &cnoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(pnoc_msmbus_a_clk, &pnoc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(snoc_msmbus_a_clk, &snoc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(cnoc_msmbus_a_clk, &cnoc_a_clk.c, LONG_MAX);
+
+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_msmbus_clk, &ocmemgx_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ocmemgx_msmbus_a_clk, &ocmemgx_a_clk.c, LONG_MAX);
+
static struct clk_freq_tbl ftbl_gcc_usb30_master_clk[] = {
F(125000000, gpll0, 1, 5, 24),
F_END
@@ -2199,28 +2232,6 @@
},
};
-static struct clk_freq_tbl ftbl_mmss_ahb_clk[] = {
- F_MM(19200000, cxo, 1, 0, 0),
- F_MM(40000000, gpll0, 15, 0, 0),
- F_MM(80000000, mmpll0, 10, 0, 0),
- F_END,
-};
-
-/* TODO: This may go away (may be controlled by the RPM). */
-static struct rcg_clk ahb_clk_src = {
- .cmd_rcgr_reg = 0x5000,
- .set_rate = set_rate_hid,
- .freq_tbl = ftbl_mmss_ahb_clk,
- .current_freq = &rcg_dummy_freq,
- .base = &virt_bases[MMSS_BASE],
- .c = {
- .dbg_name = "ahb_clk_src",
- .ops = &clk_ops_rcg,
- VDD_DIG_FMAX_MAP2(LOW, 40000000, NOMINAL, 80000000),
- CLK_INIT(ahb_clk_src.c),
- },
-};
-
static struct clk_freq_tbl ftbl_mmss_axi_clk[] = {
F_MM( 19200000, cxo, 1, 0, 0),
F_MM(150000000, gpll0, 4, 0, 0),
@@ -2244,6 +2255,29 @@
},
};
+static struct clk_freq_tbl ftbl_ocmemnoc_clk[] = {
+ F_MM( 19200000, cxo, 1, 0, 0),
+ F_MM(150000000, gpll0, 4, 0, 0),
+ F_MM(333330000, mmpll1, 3, 0, 0),
+ F_MM(400000000, mmpll0, 2, 0, 0),
+ F_END
+};
+
+struct rcg_clk ocmemnoc_clk_src = {
+ .cmd_rcgr_reg = OCMEMNOC_CMD_RCGR,
+ .set_rate = set_rate_hid,
+ .freq_tbl = ftbl_ocmemnoc_clk,
+ .current_freq = &rcg_dummy_freq,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "ocmemnoc_clk_src",
+ .ops = &clk_ops_rcg,
+ VDD_DIG_FMAX_MAP3(LOW, 150000000, NOMINAL, 333330000,
+ HIGH, 400000000),
+ CLK_INIT(ocmemnoc_clk_src.c),
+ },
+};
+
static struct clk_freq_tbl ftbl_camss_csi0_3_clk[] = {
F_MM(100000000, gpll0, 6, 0, 0),
F_MM(200000000, mmpll0, 4, 0, 0),
@@ -2869,7 +2903,6 @@
static struct branch_clk camss_cci_cci_ahb_clk = {
.cbcr_reg = CAMSS_CCI_CCI_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2893,7 +2926,6 @@
static struct branch_clk camss_csi0_ahb_clk = {
.cbcr_reg = CAMSS_CSI0_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -2953,7 +2985,6 @@
static struct branch_clk camss_csi1_ahb_clk = {
.cbcr_reg = CAMSS_CSI1_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3013,7 +3044,6 @@
static struct branch_clk camss_csi2_ahb_clk = {
.cbcr_reg = CAMSS_CSI2_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3073,7 +3103,6 @@
static struct branch_clk camss_csi3_ahb_clk = {
.cbcr_reg = CAMSS_CSI3_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3181,7 +3210,6 @@
static struct branch_clk camss_ispif_ahb_clk = {
.cbcr_reg = CAMSS_ISPIF_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3229,7 +3257,6 @@
static struct branch_clk camss_jpeg_jpeg_ahb_clk = {
.cbcr_reg = CAMSS_JPEG_JPEG_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3253,6 +3280,7 @@
static struct branch_clk camss_jpeg_jpeg_ocmemnoc_clk = {
.cbcr_reg = CAMSS_JPEG_JPEG_OCMEMNOC_CBCR,
+ .parent = &ocmemnoc_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3312,7 +3340,6 @@
static struct branch_clk camss_micro_ahb_clk = {
.cbcr_reg = CAMSS_MICRO_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3360,7 +3387,6 @@
static struct branch_clk camss_top_ahb_clk = {
.cbcr_reg = CAMSS_TOP_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3372,7 +3398,6 @@
static struct branch_clk camss_vfe_cpp_ahb_clk = {
.cbcr_reg = CAMSS_VFE_CPP_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3420,7 +3445,6 @@
static struct branch_clk camss_vfe_vfe_ahb_clk = {
.cbcr_reg = CAMSS_VFE_VFE_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3444,6 +3468,7 @@
static struct branch_clk camss_vfe_vfe_ocmemnoc_clk = {
.cbcr_reg = CAMSS_VFE_VFE_OCMEMNOC_CBCR,
+ .parent = &ocmemnoc_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3455,7 +3480,6 @@
static struct branch_clk mdss_ahb_clk = {
.cbcr_reg = MDSS_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3575,7 +3599,6 @@
static struct branch_clk mdss_hdmi_ahb_clk = {
.cbcr_reg = MDSS_HDMI_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3659,7 +3682,6 @@
static struct branch_clk mmss_misc_ahb_clk = {
.cbcr_reg = MMSS_MISC_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3671,7 +3693,6 @@
static struct branch_clk mmss_mmssnoc_ahb_clk = {
.cbcr_reg = MMSS_MMSSNOC_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3683,7 +3704,6 @@
static struct branch_clk mmss_mmssnoc_bto_ahb_clk = {
.cbcr_reg = MMSS_MMSSNOC_BTO_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3717,9 +3737,21 @@
},
};
+struct branch_clk ocmemnoc_clk = {
+ .cbcr_reg = OCMEMNOC_CBCR,
+ .parent = &ocmemnoc_clk_src.c,
+ .has_sibling = 0,
+ .bcr_reg = 0x50b0,
+ .base = &virt_bases[MMSS_BASE],
+ .c = {
+ .dbg_name = "ocmemnoc_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(ocmemnoc_clk.c),
+ },
+};
+
static struct branch_clk venus0_ahb_clk = {
.cbcr_reg = VENUS0_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3743,6 +3775,7 @@
static struct branch_clk venus0_ocmemnoc_clk = {
.cbcr_reg = VENUS0_OCMEMNOC_CBCR,
+ .parent = &ocmemnoc_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -3777,7 +3810,6 @@
static struct branch_clk oxilicx_ahb_clk = {
.cbcr_reg = OXILICX_AHB_CBCR,
- .parent = &ahb_clk_src.c,
.has_sibling = 1,
.base = &virt_bases[MMSS_BASE],
.c = {
@@ -4310,6 +4342,7 @@
{&gcc_usb_hsic_system_clk.c, GCC_BASE, 0x0061},
{&mmss_mmssnoc_ahb_clk.c, MMSS_BASE, 0x0001},
{&mmss_mmssnoc_axi_clk.c, MMSS_BASE, 0x0004},
+ {&ocmemnoc_clk.c, MMSS_BASE, 0x0007},
{&camss_cci_cci_ahb_clk.c, MMSS_BASE, 0x002e},
{&camss_cci_cci_clk.c, MMSS_BASE, 0x002d},
{&camss_csi0_ahb_clk.c, MMSS_BASE, 0x0042},
@@ -4663,7 +4696,6 @@
/* Multimedia clocks */
CLK_LOOKUP("bus_clk_src", axi_clk_src.c, ""),
- CLK_LOOKUP("bus_clk_src", ahb_clk_src.c, ""),
CLK_LOOKUP("bus_clk", mmss_mmssnoc_ahb_clk.c, ""),
CLK_LOOKUP("bus_clk", mmss_mmssnoc_axi_clk.c, ""),
CLK_LOOKUP("core_clk", mdss_edpaux_clk.c, ""),
@@ -4787,6 +4819,34 @@
CLK_DUMMY("dfab_clk", DFAB_CLK, "msm_sps", OFF),
CLK_DUMMY("mem_clk", NULL, "msm_sps", OFF),
CLK_DUMMY("bus_clk", NULL, "scm", OFF),
+ CLK_DUMMY("bus_clk", NULL, "qseecom", OFF),
+
+ CLK_LOOKUP("bus_clk", snoc_clk.c, ""),
+ CLK_LOOKUP("bus_clk", pnoc_clk.c, ""),
+ CLK_LOOKUP("bus_clk", cnoc_clk.c, ""),
+ CLK_LOOKUP("mem_clk", bimc_clk.c, ""),
+ CLK_LOOKUP("mem_clk", ocmemgx_clk.c, ""),
+ CLK_LOOKUP("bus_clk", snoc_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", pnoc_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", cnoc_a_clk.c, ""),
+ CLK_LOOKUP("mem_clk", bimc_a_clk.c, ""),
+ CLK_LOOKUP("mem_clk", ocmemgx_a_clk.c, ""),
+
+ CLK_LOOKUP("bus_clk", cnoc_msmbus_clk.c, "msm_config_noc"),
+ CLK_LOOKUP("bus_a_clk", cnoc_msmbus_a_clk.c, "msm_config_noc"),
+ CLK_LOOKUP("bus_clk", snoc_msmbus_clk.c, "msm_sys_noc"),
+ CLK_LOOKUP("bus_a_clk", snoc_msmbus_a_clk.c, "msm_sys_noc"),
+ CLK_LOOKUP("bus_clk", pnoc_msmbus_clk.c, "msm_periph_noc"),
+ CLK_LOOKUP("bus_a_clk", pnoc_msmbus_a_clk.c, "msm_periph_noc"),
+ CLK_LOOKUP("mem_clk", bimc_msmbus_clk.c, "msm_bimc"),
+ CLK_LOOKUP("mem_a_clk", bimc_msmbus_a_clk.c, "msm_bimc"),
+ CLK_LOOKUP("mem_clk", bimc_acpu_a_clk.c, ""),
+ CLK_LOOKUP("ocmem_clk", ocmemgx_msmbus_clk.c, "msm_bus"),
+ CLK_LOOKUP("ocmem_a_clk", ocmemgx_msmbus_a_clk.c, "msm_bus"),
+ CLK_LOOKUP("bus_clk", ocmemnoc_clk.c, "msm_ocmem_noc"),
+ CLK_LOOKUP("bus_a_clk", ocmemnoc_clk.c, "msm_ocmem_noc"),
+ CLK_LOOKUP("bus_clk", axi_clk_src.c, "msm_mmss_noc"),
+ CLK_LOOKUP("bus_a_clk", axi_clk_src.c, "msm_mmss_noc"),
};
static struct pll_config_regs gpll0_regs __initdata = {
@@ -4981,7 +5041,6 @@
static void __init msmcopper_clock_post_init(void)
{
- clk_set_rate(&ahb_clk_src.c, 80000000);
clk_set_rate(&axi_clk_src.c, 333330000);
/* Set rates for single-rate clocks. */
diff --git a/arch/arm/mach-msm/clock-dss-8960.c b/arch/arm/mach-msm/clock-dss-8960.c
index 8331899..7f3646f 100644
--- a/arch/arm/mach-msm/clock-dss-8960.c
+++ b/arch/arm/mach-msm/clock-dss-8960.c
@@ -97,6 +97,7 @@
{
unsigned int val;
u32 ahb_en_reg, ahb_enabled;
+ unsigned int timeout_count;
ahb_en_reg = readl_relaxed(AHB_EN_REG);
ahb_enabled = ahb_en_reg & BIT(4);
@@ -110,6 +111,12 @@
writel_relaxed(0x8D, HDMI_PHY_PLL_LOCKDET_CFG2);
writel_relaxed(0x10, HDMI_PHY_PLL_LOCKDET_CFG0);
writel_relaxed(0x1A, HDMI_PHY_PLL_LOCKDET_CFG1);
+ /* Wait for a short time before de-asserting
+ * to allow the hardware to complete its job.
+ * This much of delay should be fine for hardware
+ * to assert and de-assert.
+ */
+ udelay(10);
/* De-assert PLL S/W reset */
writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
@@ -118,6 +125,11 @@
/* Assert PHY S/W reset */
writel_relaxed(val, HDMI_PHY_REG_12);
val &= ~BIT(5);
+ /* Wait for a short time before de-asserting
+ to allow the hardware to complete its job.
+ This much of delay should be fine for hardware
+ to assert and de-assert. */
+ udelay(10);
/* De-assert PHY S/W reset */
writel_relaxed(val, HDMI_PHY_REG_12);
writel_relaxed(0x3f, HDMI_PHY_REG_2);
@@ -135,8 +147,32 @@
writel_relaxed(val, HDMI_PHY_PLL_PWRDN_B);
writel_relaxed(0x80, HDMI_PHY_REG_2);
- while (!(readl_relaxed(HDMI_PHY_PLL_STATUS0) & BIT(0)))
- cpu_relax();
+ timeout_count = 1000;
+ while (!(readl_relaxed(HDMI_PHY_PLL_STATUS0) & BIT(0)) &&
+ timeout_count) {
+ if (--timeout_count == 0) {
+ /*
+ * PLL has still not locked.
+ * Do a software reset and try again
+ * Assert PLL S/W reset first
+ */
+ writel_relaxed(0x8D, HDMI_PHY_PLL_LOCKDET_CFG2);
+
+ /* Wait for a short time before de-asserting
+ * to allow the hardware to complete its job.
+ * This much of delay should be fine for hardware
+ * to assert and de-assert.
+ */
+ udelay(10);
+ writel_relaxed(0x0D, HDMI_PHY_PLL_LOCKDET_CFG2);
+ timeout_count = 1000;
+
+ pr_err("%s: PLL not locked after %d iterations\n",
+ __func__, timeout_count);
+ pr_err("%s: Asserting PLL S/W reset & trying again\n",
+ __func__);
+ }
+ }
if (!ahb_enabled)
writel_relaxed(ahb_en_reg & ~BIT(4), AHB_EN_REG);
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 02e103d..b5ae4ab 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -610,10 +610,8 @@
ns_val = readl_relaxed(clk->ns_reg) & ns_mask;
for (freq = clk->freq_tbl; freq->freq_hz != FREQ_END; freq++) {
if ((freq->ns_val & ns_mask) == ns_val &&
- (!freq->md_val || freq->md_val == md_val)) {
- pr_info("%s rate=%d\n", clk->c.dbg_name, freq->freq_hz);
+ (!freq->md_val || freq->md_val == md_val))
break;
- }
}
if (freq->freq_hz == FREQ_END)
return HANDOFF_UNKNOWN_RATE;
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index c84cfb8..467d5d1 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -282,7 +282,6 @@
if (freq->d_val != d_regval)
continue;
}
- pr_info("%s rate=%lu\n", rcg->c.dbg_name, freq->freq_hz);
break;
}
@@ -448,7 +447,6 @@
cbcr_regval = readl_relaxed(CBCR_REG(branch));
if ((cbcr_regval & CBCR_BRANCH_OFF_BIT))
return HANDOFF_DISABLED_CLK;
- pr_info("%s enabled.\n", branch->c.dbg_name);
if (branch->parent) {
if (branch->parent->ops->handoff)
@@ -459,17 +457,12 @@
}
static int __branch_clk_reset(void __iomem *bcr_reg,
- enum clk_reset_action action, const char *name)
+ enum clk_reset_action action)
{
int ret = 0;
unsigned long flags;
u32 reg_val;
- if (!bcr_reg) {
- WARN("clk_reset called on an unsupported clock (%s)\n", name);
- return -EPERM;
- }
-
spin_lock_irqsave(&local_clock_reg_lock, flags);
reg_val = readl_relaxed(bcr_reg);
switch (action) {
@@ -494,7 +487,13 @@
static int branch_clk_reset(struct clk *c, enum clk_reset_action action)
{
struct branch_clk *branch = to_branch_clk(c);
- return __branch_clk_reset(BCR_REG(branch), action, c->dbg_name);
+
+ if (!branch->bcr_reg) {
+ WARN("clk_reset called on an unsupported clock (%s)\n",
+ c->dbg_name);
+ return -EPERM;
+ }
+ return __branch_clk_reset(BCR_REG(branch), action);
}
/*
@@ -503,7 +502,13 @@
static int local_vote_clk_reset(struct clk *c, enum clk_reset_action action)
{
struct local_vote_clk *vclk = to_local_vote_clk(c);
- return __branch_clk_reset(BCR_REG(vclk), action, c->dbg_name);
+
+ if (!vclk->bcr_reg) {
+ WARN("clk_reset called on an unsupported clock (%s)\n",
+ c->dbg_name);
+ return -EPERM;
+ }
+ return __branch_clk_reset(BCR_REG(vclk), action);
}
static int local_vote_clk_enable(struct clk *c)
@@ -546,7 +551,6 @@
vote_regval = readl_relaxed(VOTE_REG(vclk));
if (!(vote_regval & vclk->en_mask))
return HANDOFF_DISABLED_CLK;
- pr_info("%s enabled.\n", vclk->c.dbg_name);
return HANDOFF_ENABLED_CLK;
}
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 4539828..e0707fc 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -18,13 +18,89 @@
#include "clock.h"
#include "clock-rpm.h"
+#define __clk_rpmrs_set_rate(r, value, ctx, noirq) \
+ ((r)->rpmrs_data->set_rate_fn((r), (value), (ctx), (noirq)))
+
+#define clk_rpmrs_set_rate_sleep(r, value) \
+ __clk_rpmrs_set_rate((r), (value), (r)->rpmrs_data->ctx_sleep_id, 0)
+
+#define clk_rpmrs_set_rate_sleep_noirq(r, value) \
+ __clk_rpmrs_set_rate((r), (value), (r)->rpmrs_data->ctx_sleep_id, 1)
+
+#define clk_rpmrs_set_rate_active(r, value) \
+ __clk_rpmrs_set_rate((r), (value), (r)->rpmrs_data->ctx_active_id, 0)
+
+#define clk_rpmrs_set_rate_active_noirq(r, value) \
+ __clk_rpmrs_set_rate((r), (value), (r)->rpmrs_data->ctx_active_id, 1)
+
+static int clk_rpmrs_set_rate(struct rpm_clk *r, uint32_t value,
+ uint32_t context, int noirq)
+{
+ struct msm_rpm_iv_pair iv = {
+ .id = r->rpm_clk_id,
+ .value = value,
+ };
+ if (noirq)
+ return msm_rpmrs_set_noirq(context, &iv, 1);
+ else
+ return msm_rpmrs_set(context, &iv, 1);
+}
+
+static int clk_rpmrs_get_rate(struct rpm_clk *r)
+{
+ int rc;
+ struct msm_rpm_iv_pair iv = { .id = r->rpm_status_id, };
+ rc = msm_rpm_get_status(&iv, 1);
+ return (rc < 0) ? rc : iv.value * 1000;
+}
+
+#define RPM_SMD_KEY_CLOCK_SET_RATE 0x007A484B
+
+static int clk_rpmrs_set_rate_smd(struct rpm_clk *r, uint32_t value,
+ uint32_t context, int noirq)
+{
+ struct msm_rpm_kvp kvp = {
+ .key = RPM_SMD_KEY_CLOCK_SET_RATE,
+ .data = (void *)&value,
+ .length = sizeof(value),
+ };
+
+ if (noirq)
+ return msm_rpm_send_message_noirq(context,
+ r->rpm_res_type, r->rpm_clk_id, &kvp, 1);
+ else
+ return msm_rpm_send_message(context, r->rpm_res_type,
+ r->rpm_clk_id, &kvp, 1);
+}
+
+struct clk_rpmrs_data {
+ int (*set_rate_fn)(struct rpm_clk *r, uint32_t value,
+ uint32_t context, int noirq);
+ int (*get_rate_fn)(struct rpm_clk *r);
+ int ctx_active_id;
+ int ctx_sleep_id;
+};
+
+struct clk_rpmrs_data clk_rpmrs_data = {
+ .set_rate_fn = clk_rpmrs_set_rate,
+ .get_rate_fn = clk_rpmrs_get_rate,
+ .ctx_active_id = MSM_RPM_CTX_SET_0,
+ .ctx_sleep_id = MSM_RPM_CTX_SET_SLEEP,
+};
+
+struct clk_rpmrs_data clk_rpmrs_data_smd = {
+ .set_rate_fn = clk_rpmrs_set_rate_smd,
+ .ctx_active_id = MSM_RPM_CTX_ACTIVE_SET,
+ .ctx_sleep_id = MSM_RPM_CTX_SLEEP_SET,
+};
+
static DEFINE_SPINLOCK(rpm_clock_lock);
static int rpm_clk_enable(struct clk *clk)
{
unsigned long flags;
struct rpm_clk *r = to_rpm_clk(clk);
- struct msm_rpm_iv_pair iv = { .id = r->rpm_clk_id };
+ uint32_t value;
int rc = 0;
unsigned long this_khz, this_sleep_khz;
unsigned long peer_khz = 0, peer_sleep_khz = 0;
@@ -45,21 +121,23 @@
peer_sleep_khz = peer->last_set_sleep_khz;
}
- iv.value = max(this_khz, peer_khz);
+ value = max(this_khz, peer_khz);
if (r->branch)
- iv.value = !!iv.value;
+ value = !!value;
- rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &iv, 1);
+ rc = clk_rpmrs_set_rate_active_noirq(r, value);
if (rc)
goto out;
- iv.value = max(this_sleep_khz, peer_sleep_khz);
+ value = max(this_sleep_khz, peer_sleep_khz);
if (r->branch)
- iv.value = !!iv.value;
- rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_SLEEP, &iv, 1);
+ value = !!value;
+
+ rc = clk_rpmrs_set_rate_sleep_noirq(r, value);
if (rc) {
- iv.value = peer_khz;
- msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &iv, 1);
+ /* Undo the active set vote and restore it to peer_khz */
+ value = peer_khz;
+ rc = clk_rpmrs_set_rate_active_noirq(r, value);
}
out:
@@ -79,7 +157,7 @@
spin_lock_irqsave(&rpm_clock_lock, flags);
if (r->last_set_khz) {
- struct msm_rpm_iv_pair iv = { .id = r->rpm_clk_id };
+ uint32_t value;
struct rpm_clk *peer = r->peer;
unsigned long peer_khz = 0, peer_sleep_khz = 0;
int rc;
@@ -90,13 +168,13 @@
peer_sleep_khz = peer->last_set_sleep_khz;
}
- iv.value = r->branch ? !!peer_khz : peer_khz;
- rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &iv, 1);
+ value = r->branch ? !!peer_khz : peer_khz;
+ rc = clk_rpmrs_set_rate_active_noirq(r, value);
if (rc)
goto out;
- iv.value = r->branch ? !!peer_sleep_khz : peer_sleep_khz;
- rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_SLEEP, &iv, 1);
+ value = r->branch ? !!peer_sleep_khz : peer_sleep_khz;
+ rc = clk_rpmrs_set_rate_sleep_noirq(r, value);
}
r->enabled = false;
out:
@@ -124,25 +202,23 @@
this_sleep_khz = this_khz;
if (r->enabled) {
- struct msm_rpm_iv_pair iv;
+ uint32_t value;
struct rpm_clk *peer = r->peer;
unsigned long peer_khz = 0, peer_sleep_khz = 0;
- iv.id = r->rpm_clk_id;
-
/* Take peer clock's rate into account only if it's enabled. */
if (peer->enabled) {
peer_khz = peer->last_set_khz;
peer_sleep_khz = peer->last_set_sleep_khz;
}
- iv.value = max(this_khz, peer_khz);
- rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_0, &iv, 1);
+ value = max(this_khz, peer_khz);
+ rc = clk_rpmrs_set_rate_active_noirq(r, value);
if (rc)
goto out;
- iv.value = max(this_sleep_khz, peer_sleep_khz);
- rc = msm_rpmrs_set_noirq(MSM_RPM_CTX_SET_SLEEP, &iv, 1);
+ value = max(this_sleep_khz, peer_sleep_khz);
+ rc = clk_rpmrs_set_rate_sleep_noirq(r, value);
}
if (!rc) {
r->last_set_khz = this_khz;
@@ -158,13 +234,10 @@
static unsigned long rpm_clk_get_rate(struct clk *clk)
{
struct rpm_clk *r = to_rpm_clk(clk);
- struct msm_rpm_iv_pair iv = { r->rpm_status_id };
- int rc;
-
- rc = msm_rpm_get_status(&iv, 1);
- if (rc < 0)
- return rc;
- return iv.value * 1000;
+ if (r->rpmrs_data->get_rate_fn)
+ return r->rpmrs_data->get_rate_fn(r);
+ else
+ return 0;
}
static int rpm_clk_is_enabled(struct clk *clk)
@@ -183,6 +256,29 @@
return false;
}
+static enum handoff rpm_clk_handoff(struct clk *clk)
+{
+ struct rpm_clk *r = to_rpm_clk(clk);
+ struct msm_rpm_iv_pair iv = { r->rpm_status_id };
+ int rc;
+
+ /*
+ * Querying an RPM clock's status will return 0 unless the clock's
+ * rate has previously been set through the RPM. When handing off,
+ * assume these clocks are enabled (unless the RPM call fails) so
+ * child clocks of these RPM clocks can still be handed off.
+ */
+ rc = msm_rpm_get_status(&iv, 1);
+ if (rc < 0)
+ return HANDOFF_DISABLED_CLK;
+
+ r->last_set_khz = iv.value;
+ r->last_set_sleep_khz = iv.value;
+ clk->rate = iv.value * 1000;
+
+ return HANDOFF_ENABLED_CLK;
+}
+
struct clk_ops clk_ops_rpm = {
.enable = rpm_clk_enable,
.disable = rpm_clk_disable,
@@ -191,10 +287,12 @@
.is_enabled = rpm_clk_is_enabled,
.round_rate = rpm_clk_round_rate,
.is_local = rpm_clk_is_local,
+ .handoff = rpm_clk_handoff,
};
struct clk_ops clk_ops_rpm_branch = {
.enable = rpm_clk_enable,
.disable = rpm_clk_disable,
.is_local = rpm_clk_is_local,
+ .handoff = rpm_clk_handoff,
};
diff --git a/arch/arm/mach-msm/clock-rpm.h b/arch/arm/mach-msm/clock-rpm.h
index b0d5693..b2358bc 100644
--- a/arch/arm/mach-msm/clock-rpm.h
+++ b/arch/arm/mach-msm/clock-rpm.h
@@ -15,12 +15,15 @@
#define __ARCH_ARM_MACH_MSM_CLOCK_RPM_H
#include <mach/rpm.h>
+#include <mach/rpm-smd.h>
struct clk_ops;
+struct clk_rpmrs_data;
extern struct clk_ops clk_ops_rpm;
extern struct clk_ops clk_ops_rpm_branch;
struct rpm_clk {
+ const int rpm_res_type;
const int rpm_clk_id;
const int rpm_status_id;
const bool active_only;
@@ -29,6 +32,7 @@
unsigned last_set_sleep_khz;
bool enabled;
bool branch; /* true: RPM only accepts 1 for ON and 0 for OFF */
+ struct clk_rpmrs_data *rpmrs_data;
struct rpm_clk *peer;
struct clk c;
@@ -39,12 +43,17 @@
return container_of(clk, struct rpm_clk, c);
}
-#define DEFINE_CLK_RPM(name, active, r_id, dep) \
+extern struct clk_rpmrs_data clk_rpmrs_data;
+extern struct clk_rpmrs_data clk_rpmrs_data_smd;
+
+#define __DEFINE_CLK_RPM(name, active, type, r_id, stat_id, dep, rpmrsdata) \
static struct rpm_clk active; \
static struct rpm_clk name = { \
- .rpm_clk_id = MSM_RPM_ID_##r_id##_CLK, \
- .rpm_status_id = MSM_RPM_STATUS_ID_##r_id##_CLK, \
+ .rpm_res_type = (type), \
+ .rpm_clk_id = (r_id), \
+ .rpm_status_id = (stat_id), \
.peer = &active, \
+ .rpmrs_data = (rpmrsdata),\
.c = { \
.ops = &clk_ops_rpm, \
.flags = CLKFLAG_SKIP_AUTO_OFF, \
@@ -54,10 +63,12 @@
}, \
}; \
static struct rpm_clk active = { \
- .rpm_clk_id = MSM_RPM_ID_##r_id##_CLK, \
- .rpm_status_id = MSM_RPM_STATUS_ID_##r_id##_CLK, \
+ .rpm_res_type = (type), \
+ .rpm_clk_id = (r_id), \
+ .rpm_status_id = (stat_id), \
.peer = &name, \
.active_only = true, \
+ .rpmrs_data = (rpmrsdata),\
.c = { \
.ops = &clk_ops_rpm, \
.flags = CLKFLAG_SKIP_AUTO_OFF, \
@@ -67,15 +78,18 @@
}, \
};
-#define DEFINE_CLK_RPM_BRANCH(name, active, r_id, r) \
+#define __DEFINE_CLK_RPM_BRANCH(name, active, type, r_id, stat_id, r, \
+ rpmrsdata) \
static struct rpm_clk active; \
static struct rpm_clk name = { \
- .rpm_clk_id = MSM_RPM_ID_##r_id##_CLK, \
- .rpm_status_id = MSM_RPM_STATUS_ID_##r_id##_CLK, \
+ .rpm_res_type = (type), \
+ .rpm_clk_id = (r_id), \
+ .rpm_status_id = (stat_id), \
.peer = &active, \
.last_set_khz = ((r) / 1000), \
.last_set_sleep_khz = ((r) / 1000), \
.branch = true, \
+ .rpmrs_data = (rpmrsdata),\
.c = { \
.ops = &clk_ops_rpm_branch, \
.flags = CLKFLAG_SKIP_AUTO_OFF, \
@@ -86,12 +100,14 @@
}, \
}; \
static struct rpm_clk active = { \
- .rpm_clk_id = MSM_RPM_ID_##r_id##_CLK, \
- .rpm_status_id = MSM_RPM_STATUS_ID_##r_id##_CLK, \
+ .rpm_res_type = (type), \
+ .rpm_clk_id = (r_id), \
+ .rpm_status_id = (stat_id), \
.peer = &name, \
.last_set_khz = ((r) / 1000), \
.active_only = true, \
.branch = true, \
+ .rpmrs_data = (rpmrsdata),\
.c = { \
.ops = &clk_ops_rpm_branch, \
.flags = CLKFLAG_SKIP_AUTO_OFF, \
@@ -102,4 +118,19 @@
}, \
};
+#define DEFINE_CLK_RPM(name, active, r_id, dep) \
+ __DEFINE_CLK_RPM(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
+ MSM_RPM_STATUS_ID_##r_id##_CLK, dep, &clk_rpmrs_data)
+
+#define DEFINE_CLK_RPM_BRANCH(name, active, r_id, r) \
+ __DEFINE_CLK_RPM_BRANCH(name, active, 0, MSM_RPM_ID_##r_id##_CLK, \
+ MSM_RPM_STATUS_ID_##r_id##_CLK, r, &clk_rpmrs_data)
+
+#define DEFINE_CLK_RPM_SMD(name, active, type, r_id, dep) \
+ __DEFINE_CLK_RPM(name, active, type, r_id, 0, dep, &clk_rpmrs_data_smd)
+
+#define DEFINE_CLK_RPM_SMD_BRANCH(name, active, type, r_id, dep) \
+ __DEFINE_CLK_RPM_BRANCH(name, active, type, r_id, 0, dep, \
+ &clk_rpmrs_data_smd)
+
#endif
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 8a1c6eb..8bf98fa 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -21,10 +21,17 @@
#include <linux/module.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
+#include <linux/list.h>
#include <trace/events/power.h>
#include "clock.h"
+struct handoff_clk {
+ struct list_head list;
+ struct clk *clk;
+};
+static LIST_HEAD(handoff_list);
+
/* Find the voltage level required for a given rate. */
static int find_vdd_level(struct clk *clk, unsigned long rate)
{
@@ -203,18 +210,8 @@
ret = clk->ops->enable(clk);
if (ret)
goto err_enable_clock;
- } else if (clk->flags & CLKFLAG_HANDOFF_RATE) {
- /*
- * The clock was already enabled by handoff code so there is no
- * need to enable it again here. Clearing the handoff flag will
- * prevent the lateinit handoff code from disabling the clock if
- * a client driver still has it enabled.
- */
- clk->flags &= ~CLKFLAG_HANDOFF_RATE;
- goto out;
}
clk->count++;
-out:
spin_unlock_irqrestore(&clk->lock, flags);
return 0;
@@ -422,6 +419,58 @@
static struct clock_init_data __initdata *clk_init_data;
+static enum handoff __init __handoff_clk(struct clk *clk)
+{
+ enum handoff ret;
+ struct handoff_clk *h;
+ unsigned long rate;
+ int err = 0;
+
+ /*
+ * Tree roots don't have parents, but need to be handed off. So,
+ * terminate recursion by returning "enabled". Also return "enabled"
+ * for clocks with non-zero enable counts since they must have already
+ * been handed off.
+ */
+ if (clk == NULL || clk->count)
+ return HANDOFF_ENABLED_CLK;
+
+ /* Clocks without handoff functions are assumed to be disabled. */
+ if (!clk->ops->handoff || (clk->flags & CLKFLAG_SKIP_HANDOFF))
+ return HANDOFF_DISABLED_CLK;
+
+ /*
+ * Handoff functions for children must be called before their parents'
+ * so that the correct parent is returned by the clk_get_parent() below.
+ */
+ ret = clk->ops->handoff(clk);
+ if (ret == HANDOFF_ENABLED_CLK) {
+ ret = __handoff_clk(clk_get_parent(clk));
+ if (ret == HANDOFF_ENABLED_CLK) {
+ h = kmalloc(sizeof(*h), GFP_KERNEL);
+ if (!h) {
+ err = -ENOMEM;
+ goto out;
+ }
+ err = clk_prepare_enable(clk);
+ if (err)
+ goto out;
+ rate = clk_get_rate(clk);
+ if (rate)
+ pr_debug("%s rate=%lu\n", clk->dbg_name, rate);
+ h->clk = clk;
+ list_add_tail(&h->list, &handoff_list);
+ }
+ }
+out:
+ if (err) {
+ pr_err("%s handoff failed (%d)\n", clk->dbg_name, err);
+ kfree(h);
+ ret = HANDOFF_DISABLED_CLK;
+ }
+ return ret;
+}
+
void __init msm_clock_init(struct clock_init_data *data)
{
unsigned n;
@@ -448,14 +497,8 @@
* Detect and preserve initial clock state until clock_late_init() or
* a driver explicitly changes it, whichever is first.
*/
- for (n = 0; n < num_clocks; n++) {
- clk = clock_tbl[n].clk;
- if (clk->ops->handoff && !(clk->flags & CLKFLAG_HANDOFF_RATE) &&
- (clk->ops->handoff(clk) == HANDOFF_ENABLED_CLK)) {
- clk->flags |= CLKFLAG_HANDOFF_RATE;
- clk_prepare_enable(clk);
- }
- }
+ for (n = 0; n < num_clocks; n++)
+ __handoff_clk(clock_tbl[n].clk);
clkdev_add_table(clock_tbl, num_clocks);
@@ -471,13 +514,13 @@
static int __init clock_late_init(void)
{
unsigned n, count = 0;
+ struct handoff_clk *h, *h_temp;
unsigned long flags;
int ret = 0;
clock_debug_init(clk_init_data);
for (n = 0; n < clk_init_data->size; n++) {
struct clk *clk = clk_init_data->table[n].clk;
- bool handoff = false;
clock_debug_add(clk);
spin_lock_irqsave(&clk->lock, flags);
@@ -487,19 +530,16 @@
clk->ops->auto_off(clk);
}
}
- if (clk->flags & CLKFLAG_HANDOFF_RATE) {
- clk->flags &= ~CLKFLAG_HANDOFF_RATE;
- handoff = true;
- }
spin_unlock_irqrestore(&clk->lock, flags);
- /*
- * Calling this outside the lock is safe since
- * it doesn't need to be atomic with the flag change.
- */
- if (handoff)
- clk_disable_unprepare(clk);
}
pr_info("clock_late_init() disabled %d unused clocks\n", count);
+
+ list_for_each_entry_safe(h, h_temp, &handoff_list, list) {
+ clk_disable_unprepare(h->clk);
+ list_del(&h->list);
+ kfree(h);
+ }
+
if (clk_init_data->late_init)
ret = clk_init_data->late_init();
return ret;
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 1be05ad..03d5790 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -29,10 +29,10 @@
#define CLKFLAG_NOINVERT 0x00000002
#define CLKFLAG_NONEST 0x00000004
#define CLKFLAG_NORESET 0x00000008
-#define CLKFLAG_HANDOFF_RATE 0x00000010
#define CLKFLAG_HWCG 0x00000020
#define CLKFLAG_RETAIN 0x00000040
#define CLKFLAG_NORETAIN 0x00000080
+#define CLKFLAG_SKIP_HANDOFF 0x00000100
#define CLKFLAG_SKIP_AUTO_OFF 0x00000200
#define CLKFLAG_MIN 0x00000400
#define CLKFLAG_MAX 0x00000800
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index b9617f3..09e30c1 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -2316,13 +2316,21 @@
},
};
-
static struct msm_bus_vectors vcap_480_vectors[] = {
{
.src = MSM_BUS_MASTER_VIDEO_CAP,
.dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = 1280 * 720 * 3 * 60,
- .ib = 1280 * 720 * 3 * 60 * 1.5,
+ .ab = 480 * 720 * 3 * 60,
+ .ib = 480 * 720 * 3 * 60 * 1.5,
+ },
+};
+
+static struct msm_bus_vectors vcap_576_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_VIDEO_CAP,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 576 * 720 * 3 * 60,
+ .ib = 576 * 720 * 3 * 60 * 1.5,
},
};
@@ -2354,6 +2362,10 @@
vcap_480_vectors,
},
{
+ ARRAY_SIZE(vcap_576_vectors),
+ vcap_576_vectors,
+ },
+ {
ARRAY_SIZE(vcap_720_vectors),
vcap_720_vectors,
},
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 4654606..adc9169 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1445,7 +1445,7 @@
},
};
-static struct platform_device msm8625_mipi_dsi_device = {
+struct platform_device msm8625_mipi_dsi_device = {
.name = "mipi_dsi",
.id = 1,
.num_resources = ARRAY_SIZE(msm8625_mipi_dsi_resources),
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index f1d7aa0..2b2fcc7 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -300,6 +300,7 @@
extern struct platform_device msm_kgsl_2d1;
extern struct platform_device msm_mipi_dsi1_device;
+extern struct platform_device msm8625_mipi_dsi_device;
extern struct platform_device msm_lvds_device;
extern struct platform_device msm_ebi2_lcdc_device;
diff --git a/arch/arm/mach-msm/ebi_erp.c b/arch/arm/mach-msm/ebi_erp.c
new file mode 100644
index 0000000..cd9119d
--- /dev/null
+++ b/arch/arm/mach-msm/ebi_erp.c
@@ -0,0 +1,194 @@
+/* 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/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/cpu.h>
+
+#define MODULE_NAME "msm_ebi_erp"
+
+#define EBI_ERR_ADDR 0x100
+#define SLV_ERR_APACKET_0 0x108
+#define SLV_ERR_APACKET_1 0x10C
+#define SLV_ERR_CNTL 0x114
+
+#define CNTL_ERR_OCCURRED BIT(4)
+#define CNTL_CLEAR_ERR BIT(8)
+#define CNTL_IRQ_EN BIT(12)
+
+#define AMID_MASK 0xFFFF
+#define ERR_AWRITE BIT(0)
+#define ERR_AOOOWR BIT(1)
+#define ERR_AOOORD BIT(2)
+#define ERR_APTORNS BIT(3)
+#define ERR_ALOCK_SHIFT 6
+#define ERR_ALOCK_MASK 0x3
+#define ERR_ATYPE_SHIFT 8
+#define ERR_ATYPE_MASK 0xF
+#define ERR_ABURST BIT(12)
+#define ERR_ASIZE_SHIFT 13
+#define ERR_ASIZE_MASK 0x7
+#define ERR_ATID_SHIFT 16
+#define ERR_ATID_MASK 0xFF
+#define ERR_ALEN_SHIFT 24
+#define ERR_ALEN_MASK 0xF
+
+#define ERR_CODE_DECODE_ERROR BIT(0)
+#define ERR_CODE_MPU_ERROR BIT(1)
+
+struct msm_ebi_erp_data {
+ void __iomem *base;
+ struct device *dev;
+};
+
+static const char *err_lock_types[4] = {
+ "normal",
+ "exclusive",
+ "locked",
+ "barrier",
+};
+
+static const char *err_sizes[8] = {
+ "byte",
+ "half word",
+ "word",
+ "double word",
+ "reserved_4",
+ "reserved_5",
+ "reserved_6",
+ "reserved_7",
+};
+
+static irqreturn_t msm_ebi_irq(int irq, void *dev_id)
+{
+ struct msm_ebi_erp_data *drvdata = dev_id;
+ void __iomem *base = drvdata->base;
+ unsigned int err_addr, err_apacket0, err_apacket1, err_cntl;
+
+ err_addr = readl_relaxed(base + EBI_ERR_ADDR);
+ err_apacket0 = readl_relaxed(base + SLV_ERR_APACKET_0);
+ err_apacket1 = readl_relaxed(base + SLV_ERR_APACKET_1);
+ err_cntl = readl_relaxed(base + SLV_ERR_CNTL);
+
+ if (!(err_cntl & CNTL_ERR_OCCURRED))
+ return IRQ_NONE;
+
+ pr_alert("EBI error detected!\n");
+ pr_alert("\tDevice = %s\n", dev_name(drvdata->dev));
+ pr_alert("\tERR_ADDR = 0x%08x\n", err_addr);
+ pr_alert("\tAPACKET0 = 0x%08x\n", err_apacket0);
+ pr_alert("\tAPACKET1 = 0x%08x\n", err_apacket1);
+ pr_alert("\tERR_CNTL = 0x%08x\n", err_cntl);
+
+ pr_alert("\tAMID = 0x%08x\n", err_apacket0 & AMID_MASK);
+ pr_alert("\tType = %s, %s, %s\n",
+ err_apacket1 & ERR_AWRITE ? "write" : "read",
+ err_sizes[(err_apacket1 >> ERR_ASIZE_SHIFT) & ERR_ASIZE_MASK],
+ err_apacket1 & ERR_APTORNS ? "non-secure" : "secure");
+
+ pr_alert("\tALOCK = %s\n",
+ err_lock_types[(err_apacket1 >> ERR_ALOCK_SHIFT) & ERR_ALOCK_MASK]);
+
+ pr_alert("\tABURST = %s\n", err_apacket1 & ERR_ABURST ?
+ "increment" : "wrap");
+
+ pr_alert("\tCODE = %s %s\n", err_cntl & ERR_CODE_DECODE_ERROR ?
+ "decode error" : "",
+ err_cntl & ERR_CODE_MPU_ERROR ?
+ "mpu error" : "");
+ err_cntl |= CNTL_CLEAR_ERR;
+ writel_relaxed(err_cntl, base + SLV_ERR_CNTL);
+ mb(); /* Ensure interrupt is cleared before returning */
+ return IRQ_HANDLED;
+}
+
+static int __devinit msm_ebi_erp_probe(struct platform_device *pdev)
+{
+ struct resource *r;
+ struct msm_ebi_erp_data *drvdata;
+ int ret, irq;
+ unsigned int err_cntl;
+
+ drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
+ drvdata->dev = &pdev->dev;
+ platform_set_drvdata(pdev, drvdata);
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r)
+ return -EINVAL;
+
+ drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r));
+ if (!drvdata->base)
+ return -ENOMEM;
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ ret = devm_request_irq(&pdev->dev, irq, msm_ebi_irq, IRQF_TRIGGER_HIGH,
+ dev_name(&pdev->dev), drvdata);
+ if (ret)
+ return ret;
+
+ /* Enable the interrupt */
+ err_cntl = readl_relaxed(drvdata->base + SLV_ERR_CNTL);
+ err_cntl |= CNTL_IRQ_EN;
+ writel_relaxed(err_cntl, drvdata->base + SLV_ERR_CNTL);
+ mb(); /* Ensure interrupt is enabled before returning */
+ return 0;
+}
+
+static int msm_ebi_erp_remove(struct platform_device *pdev)
+{
+ struct msm_ebi_erp_data *drvdata = platform_get_drvdata(pdev);
+ unsigned int err_cntl;
+
+ /* Disable the interrupt */
+ err_cntl = readl_relaxed(drvdata->base + SLV_ERR_CNTL);
+ err_cntl &= ~CNTL_IRQ_EN;
+ writel_relaxed(err_cntl, drvdata->base + SLV_ERR_CNTL);
+ mb(); /* Ensure interrupt is disabled before returning */
+ return 0;
+}
+
+static struct platform_driver msm_ebi_erp_driver = {
+ .probe = msm_ebi_erp_probe,
+ .remove = __devexit_p(msm_ebi_erp_remove),
+ .driver = {
+ .name = MODULE_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_ebi_erp_init(void)
+{
+ return platform_driver_register(&msm_ebi_erp_driver);
+}
+
+static void __exit msm_ebi_erp_exit(void)
+{
+ platform_driver_unregister(&msm_ebi_erp_driver);
+}
+
+
+module_init(msm_ebi_erp_init);
+module_exit(msm_ebi_erp_exit);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("MSM cache error reporting driver");
diff --git a/arch/arm/mach-msm/headsmp.S b/arch/arm/mach-msm/headsmp.S
index 50d2060..e5ad312 100644
--- a/arch/arm/mach-msm/headsmp.S
+++ b/arch/arm/mach-msm/headsmp.S
@@ -27,10 +27,6 @@
sub r4, r4, r5 @ determine virtual/phys offsets
add r6, r6, r4 @ apply
pen:
- wfe
- dsb @ ensure subsequent access is
- @ after event
-
ldr r7, [r6] @ pen_rel has cpu to remove from reset
cmp r7, r0 @ are we lucky?
bne pen
diff --git a/arch/arm/mach-msm/hsic_sysmon.c b/arch/arm/mach-msm/hsic_sysmon.c
index 2dedbac..07a9dbb 100644
--- a/arch/arm/mach-msm/hsic_sysmon.c
+++ b/arch/arm/mach-msm/hsic_sysmon.c
@@ -139,14 +139,13 @@
}
if (!hs->ifc) {
- dev_err(&hs->udev->dev, "can't %s, device disconnected\n",
- opstr);
+ pr_err("can't %s, device disconnected", opstr);
return -ENODEV;
}
ret = usb_autopm_get_interface(hs->ifc);
if (ret < 0) {
- dev_err(&hs->udev->dev, "can't %s, autopm_get failed:%d\n",
+ dev_err(&hs->ifc->dev, "can't %s, autopm_get failed:%d\n",
opstr, ret);
return ret;
}
@@ -159,7 +158,7 @@
atomic_dec(&hs->dbg_pending[op]);
if (ret)
- dev_err(&hs->udev->dev,
+ dev_err(&hs->ifc->dev,
"can't %s, usb_bulk_msg failed, err:%d\n", opstr, ret);
else
atomic_add(*actual_len, &hs->dbg_bytecnt[op]);
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index bae5cbc..243b488 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -389,6 +389,7 @@
int (*backlight_level)(int level, int max, int min);
int (*pmic_backlight)(int level);
int (*rotate_panel)(void);
+ int (*backlight) (int level, int mode);
int (*panel_num)(void);
void (*panel_config_gpio)(int);
int (*vga_switch)(int select_vga);
@@ -485,6 +486,8 @@
int (*enable_5v)(int on);
int (*core_power)(int on, int show);
int (*cec_power)(int on);
+ int (*panel_power)(int on);
+ int (*gpio_config)(int on);
int (*init_irq)(void);
bool (*check_hdcp_hw_support)(void);
};
diff --git a/arch/arm/mach-msm/include/mach/ocmem.h b/arch/arm/mach-msm/include/mach/ocmem.h
index bf7c338..b0475ed 100644
--- a/arch/arm/mach-msm/include/mach/ocmem.h
+++ b/arch/arm/mach-msm/include/mach/ocmem.h
@@ -41,7 +41,7 @@
};
struct ocmem_map_list {
- int num_chunks;
+ unsigned num_chunks;
struct ocmem_chunk chunks[OCMEM_MAX_CHUNKS];
};
@@ -84,9 +84,14 @@
int ocmem_notifier_unregister(void *notif_hndl, struct notifier_block *nb);
+/* Obtain the maximum quota for the client */
+unsigned long get_max_quota(int client_id);
+
/* Allocation APIs */
struct ocmem_buf *ocmem_allocate(int client_id, unsigned long size);
+struct ocmem_buf *ocmem_allocate_nowait(int client_id, unsigned long size);
+
struct ocmem_buf *ocmem_allocate_nb(int client_id, unsigned long size);
struct ocmem_buf *ocmem_allocate_range(int client_id, unsigned long min,
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index dd3a318..dd976ea 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -24,6 +24,9 @@
#define OCMEM_PHYS_BASE 0xFEC00000
#define OCMEM_PHYS_SIZE 0x180000
+#define TO_OCMEM 0x1
+#define TO_DDR 0x2
+
struct ocmem_zone;
struct ocmem_zone_ops {
@@ -45,6 +48,19 @@
struct ocmem_zone_ops *z_ops;
};
+enum op_code {
+ SCHED_NOP = 0x0,
+ SCHED_ALLOCATE,
+ SCHED_FREE,
+ SCHED_GROW,
+ SCHED_SHRINK,
+ SCHED_MAP,
+ SCHED_UNMAP,
+ SCHED_EVICT,
+ SCHED_RESTORE,
+ SCHED_DUMP,
+};
+
struct ocmem_req {
struct rw_semaphore rw_sem;
/* Chain in sched queue */
@@ -60,6 +76,8 @@
/* reverse pointers */
struct ocmem_zone *zone;
struct ocmem_buf *buffer;
+ struct ocmem_map_list *mlist;
+ enum op_code op;
unsigned long state;
/* Request assignments */
unsigned long req_start;
@@ -73,7 +91,41 @@
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;
+}
+
struct ocmem_zone *get_zone(unsigned);
+unsigned long offset_to_phys(unsigned long);
+unsigned long phys_to_offset(unsigned long);
unsigned long allocate_head(struct ocmem_zone *, unsigned long);
int free_head(struct ocmem_zone *, unsigned long, unsigned long);
unsigned long allocate_tail(struct ocmem_zone *, unsigned long);
@@ -82,4 +134,12 @@
int ocmem_notifier_init(void);
int check_notifier(int);
int dispatch_notification(int, enum ocmem_notif_type, struct ocmem_buf *);
+
+int ocmem_sched_init(void);
+int process_allocate(int, struct ocmem_handle *, unsigned long, unsigned long,
+ unsigned long, bool, bool);
+int process_free(int, struct ocmem_handle *);
+int process_xfer(int, struct ocmem_handle *, struct ocmem_map_list *,
+ int direction);
+unsigned long process_quota(int);
#endif
diff --git a/arch/arm/mach-msm/include/mach/rpm-smd.h b/arch/arm/mach-msm/include/mach/rpm-smd.h
index ff58fed..0239e36 100644
--- a/arch/arm/mach-msm/include/mach/rpm-smd.h
+++ b/arch/arm/mach-msm/include/mach/rpm-smd.h
@@ -236,6 +236,20 @@
return 0;
}
+
+static inline int msm_rpm_send_message(enum msm_rpm_set set, uint32_t rsc_type,
+ uint32_t rsc_id, struct msm_rpm_kvp *kvp, int nelems)
+{
+ return 0;
+}
+
+static inline int msm_rpm_send_message_noirq(enum msm_rpm_set set,
+ uint32_t rsc_type, uint32_t rsc_id, struct msm_rpm_kvp *kvp,
+ int nelems)
+{
+ return 0;
+}
+
static inline int msm_rpm_wait_for_ack(uint32_t msg_id)
{
return 0;
diff --git a/arch/arm/mach-msm/include/mach/rpm.h b/arch/arm/mach-msm/include/mach/rpm.h
index 98621be..de4c9d9 100644
--- a/arch/arm/mach-msm/include/mach/rpm.h
+++ b/arch/arm/mach-msm/include/mach/rpm.h
@@ -899,6 +899,8 @@
extern struct msm_rpm_platform_data msm8930_rpm_data;
extern struct msm_rpm_platform_data apq8064_rpm_data;
+#if defined(CONFIG_MSM_RPM)
+
int msm_rpm_local_request_is_outstanding(void);
int msm_rpm_get_status(struct msm_rpm_iv_pair *status, int count);
int msm_rpm_set(int ctx, struct msm_rpm_iv_pair *req, int count);
@@ -938,4 +940,70 @@
int msm_rpm_unregister_notification(struct msm_rpm_notification *n);
int msm_rpm_init(struct msm_rpm_platform_data *data);
+#else
+
+static inline int msm_rpm_local_request_is_outstanding(void)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_get_status(struct msm_rpm_iv_pair *status, int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_set(int ctx, struct msm_rpm_iv_pair *req, int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_set_noirq(int ctx, struct msm_rpm_iv_pair *req,
+ int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_set_nosleep(
+ int ctx, struct msm_rpm_iv_pair *req, int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_clear(int ctx, struct msm_rpm_iv_pair *req,
+ int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_clear_noirq(int ctx, struct msm_rpm_iv_pair *req,
+ int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_clear_nosleep(
+ int ctx, struct msm_rpm_iv_pair *req, int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_register_notification(struct msm_rpm_notification *n,
+ struct msm_rpm_iv_pair *req, int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_unregister_notification(
+ struct msm_rpm_notification *n)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpm_init(struct msm_rpm_platform_data *data)
+{
+ return -ENODEV;
+}
+
+#endif /* CONFIG_RPM */
+
#endif /* __ARCH_ARM_MACH_MSM_RPM_H */
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 86e06a4..e35d99b 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -34,7 +34,7 @@
.virtual = (unsigned long) MSM_##name##_BASE, \
.pfn = __phys_to_pfn(chip##_##name##_PHYS), \
.length = chip##_##name##_SIZE, \
- .type = MT_DEVICE_NONSHARED, \
+ .type = MT_DEVICE, \
}
#define MSM_DEVICE(name) MSM_CHIP_DEVICE(name, MSM)
diff --git a/arch/arm/mach-msm/ipc_router.c b/arch/arm/mach-msm/ipc_router.c
index 6fa435a..c15e8b1 100644
--- a/arch/arm/mach-msm/ipc_router.c
+++ b/arch/arm/mach-msm/ipc_router.c
@@ -2023,7 +2023,7 @@
}
int msm_ipc_router_lookup_server_name(struct msm_ipc_port_name *srv_name,
- struct msm_ipc_port_addr *srv_addr,
+ struct msm_ipc_server_info *srv_info,
int num_entries_in_array,
uint32_t lookup_mask)
{
@@ -2036,8 +2036,8 @@
return -EINVAL;
}
- if (num_entries_in_array && !srv_addr) {
- pr_err("%s: srv_addr NULL\n", __func__);
+ if (num_entries_in_array && !srv_info) {
+ pr_err("%s: srv_info NULL\n", __func__);
return -EINVAL;
}
@@ -2054,10 +2054,14 @@
list_for_each_entry(server_port,
&server->server_port_list, list) {
if (i < num_entries_in_array) {
- srv_addr[i].node_id =
+ srv_info[i].node_id =
server_port->server_addr.node_id;
- srv_addr[i].port_id =
+ srv_info[i].port_id =
server_port->server_addr.port_id;
+ srv_info[i].service =
+ server->name.service;
+ srv_info[i].instance =
+ server->name.instance;
}
i++;
}
diff --git a/arch/arm/mach-msm/ipc_router.h b/arch/arm/mach-msm/ipc_router.h
index a90be23..07bc5e0 100644
--- a/arch/arm/mach-msm/ipc_router.h
+++ b/arch/arm/mach-msm/ipc_router.h
@@ -185,7 +185,7 @@
int msm_ipc_router_get_curr_pkt_size(struct msm_ipc_port *port_ptr);
int msm_ipc_router_bind_control_port(struct msm_ipc_port *port_ptr);
int msm_ipc_router_lookup_server_name(struct msm_ipc_port_name *srv_name,
- struct msm_ipc_port_addr *port_addr,
+ struct msm_ipc_server_info *srv_info,
int num_entries_in_array,
uint32_t lookup_mask);
int msm_ipc_router_close_port(struct msm_ipc_port *port_ptr);
diff --git a/arch/arm/mach-msm/ipc_socket.c b/arch/arm/mach-msm/ipc_socket.c
index d82ffe5..d3917f1 100644
--- a/arch/arm/mach-msm/ipc_socket.c
+++ b/arch/arm/mach-msm/ipc_socket.c
@@ -367,8 +367,8 @@
struct sock *sk = sock->sk;
struct msm_ipc_port *port_ptr;
struct server_lookup_args server_arg;
- struct msm_ipc_port_addr *port_addr = NULL;
- unsigned int n, port_addr_sz = 0;
+ struct msm_ipc_server_info *srv_info = NULL;
+ unsigned int n, srv_info_sz = 0;
int ret;
if (!sk)
@@ -409,33 +409,33 @@
break;
}
if (server_arg.num_entries_in_array) {
- port_addr_sz = server_arg.num_entries_in_array *
- sizeof(*port_addr);
- port_addr = kmalloc(port_addr_sz, GFP_KERNEL);
- if (!port_addr) {
+ srv_info_sz = server_arg.num_entries_in_array *
+ sizeof(*srv_info);
+ srv_info = kmalloc(srv_info_sz, GFP_KERNEL);
+ if (!srv_info) {
ret = -ENOMEM;
break;
}
}
ret = msm_ipc_router_lookup_server_name(&server_arg.port_name,
- port_addr, server_arg.num_entries_in_array,
+ srv_info, server_arg.num_entries_in_array,
server_arg.lookup_mask);
if (ret < 0) {
pr_err("%s: Server not found\n", __func__);
ret = -ENODEV;
- kfree(port_addr);
+ kfree(srv_info);
break;
}
server_arg.num_entries_found = ret;
ret = copy_to_user((void *)arg, &server_arg,
sizeof(server_arg));
- if (port_addr_sz) {
+ if (srv_info_sz) {
ret = copy_to_user((void *)(arg + sizeof(server_arg)),
- port_addr, port_addr_sz);
+ srv_info, srv_info_sz);
if (ret)
ret = -EFAULT;
- kfree(port_addr);
+ kfree(srv_info);
}
break;
diff --git a/arch/arm/mach-msm/modem_notifier.c b/arch/arm/mach-msm/modem_notifier.c
index d92098b..2f4f6af 100644
--- a/arch/arm/mach-msm/modem_notifier.c
+++ b/arch/arm/mach-msm/modem_notifier.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-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
@@ -193,8 +193,15 @@
}
#endif
-static int __init init_modem_notifier_list(void)
+int __init msm_init_modem_notifier_list(void)
{
+ static bool registered;
+
+ if (registered)
+ return 0;
+
+ registered = true;
+
srcu_init_notifier_head(&modem_notifier_list);
modem_notifier_debugfs_init();
#if defined(DEBUG)
@@ -210,4 +217,4 @@
return 0;
}
-module_init(init_modem_notifier_list);
+module_init(msm_init_modem_notifier_list);
diff --git a/arch/arm/mach-msm/modem_notifier.h b/arch/arm/mach-msm/modem_notifier.h
index 1bd2d6d..e39c163 100644
--- a/arch/arm/mach-msm/modem_notifier.h
+++ b/arch/arm/mach-msm/modem_notifier.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-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
@@ -30,5 +30,6 @@
extern void modem_queue_start_reset_notify(void);
extern void modem_queue_end_reset_notify(void);
extern void modem_queue_smsm_init_notify(void);
+extern int __init msm_init_modem_notifier_list(void);
#endif /* _MODEM_NOTIFIER_H */
diff --git a/arch/arm/mach-msm/ocmem.c b/arch/arm/mach-msm/ocmem.c
index ddfc906..ae1d6f2 100644
--- a/arch/arm/mach-msm/ocmem.c
+++ b/arch/arm/mach-msm/ocmem.c
@@ -97,6 +97,25 @@
return -EINVAL;
}
+inline unsigned long phys_to_offset(unsigned long addr)
+{
+ if (!ocmem_pdata)
+ return 0;
+ if (addr < ocmem_pdata->base ||
+ addr > (ocmem_pdata->base + ocmem_pdata->size))
+ return 0;
+ return addr - ocmem_pdata->base;
+}
+
+inline unsigned long offset_to_phys(unsigned long offset)
+{
+ if (!ocmem_pdata)
+ return 0;
+ if (offset > ocmem_pdata->size)
+ return 0;
+ return offset + ocmem_pdata->base;
+}
+
static struct ocmem_plat_data *parse_static_config(struct platform_device *pdev)
{
struct ocmem_plat_data *pdata = NULL;
@@ -276,6 +295,8 @@
if (ocmem_notifier_init())
return -EBUSY;
+ if (ocmem_sched_init())
+ return -EBUSY;
dev_info(dev, "initialized successfully\n");
return 0;
}
diff --git a/arch/arm/mach-msm/ocmem_api.c b/arch/arm/mach-msm/ocmem_api.c
new file mode 100644
index 0000000..bed13de
--- /dev/null
+++ b/arch/arm/mach-msm/ocmem_api.c
@@ -0,0 +1,327 @@
+/* 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/slab.h>
+#include <mach/ocmem_priv.h>
+
+static inline int check_id(int id)
+{
+ return (id < OCMEM_CLIENT_MAX && id >= OCMEM_GRAPHICS);
+}
+
+static struct ocmem_handle *generate_handle(void)
+{
+ struct ocmem_handle *handle = NULL;
+
+ handle = kzalloc(sizeof(struct ocmem_handle), GFP_KERNEL);
+ if (!handle) {
+ pr_err("ocmem: Unable to generate buffer handle\n");
+ return NULL;
+ }
+ mutex_init(&handle->handle_mutex);
+ return handle;
+}
+
+static int free_handle(struct ocmem_handle *handle)
+{
+ if (!handle)
+ return -EINVAL;
+
+ mutex_destroy(&handle->handle_mutex);
+ kfree(handle);
+ handle = NULL;
+ return 0;
+}
+
+static int __ocmem_free(int id, struct ocmem_buf *buf)
+{
+ int ret = 0;
+ struct ocmem_handle *handle = buffer_to_handle(buf);
+
+ if (!handle)
+ return -EINVAL;
+
+ mutex_lock(&handle->handle_mutex);
+ ret = process_free(id, handle);
+ mutex_unlock(&handle->handle_mutex);
+
+ if (ret)
+ return -EINVAL;
+
+ free_handle(handle);
+ return 0;
+}
+
+static struct ocmem_buf *__ocmem_allocate_range(int id, unsigned long min,
+ unsigned long max, unsigned long step, bool block, bool wait)
+{
+ struct ocmem_handle *handle = NULL;
+ int ret = 0;
+
+ handle = generate_handle();
+ if (!handle) {
+ pr_err("ocmem: Unable to generate handle\n");
+ return NULL;
+ }
+
+ mutex_lock(&handle->handle_mutex);
+ ret = process_allocate(id, handle, min, max, step, block, wait);
+ mutex_unlock(&handle->handle_mutex);
+ if (ret) {
+ pr_err("ocmem allocation failed\n");
+ free_handle(handle);
+ return NULL;
+ } else
+ return handle_to_buffer(handle);
+}
+
+struct ocmem_buf *ocmem_allocate(int client_id, unsigned long size)
+{
+ bool can_block = false;
+ bool can_wait = true;
+
+ if (!check_id(client_id)) {
+ pr_err("ocmem: Invalid client id: %d\n", client_id);
+ return NULL;
+ }
+
+ if (size < OCMEM_MIN_ALLOC) {
+ pr_err("ocmem: requested size %lx must be at least %x\n",
+ size, OCMEM_MIN_ALLOC);
+ return NULL;
+ }
+
+ if (!IS_ALIGNED(size, OCMEM_MIN_ALIGN)) {
+ pr_err("ocmem: Invalid alignment, size must be %x aligned\n",
+ OCMEM_MIN_ALIGN);
+ return NULL;
+ }
+
+ return __ocmem_allocate_range(client_id, size, size,
+ size, can_block, can_wait);
+}
+
+struct ocmem_buf *ocmem_allocate_nowait(int client_id, unsigned long size)
+{
+ bool can_block = false;
+ bool can_wait = false;
+
+ if (!check_id(client_id)) {
+ pr_err("ocmem: Invalid client id: %d\n", client_id);
+ return NULL;
+ }
+
+ if (size < OCMEM_MIN_ALLOC) {
+ pr_err("ocmem: requested size %lx must be at least %x\n",
+ size, OCMEM_MIN_ALLOC);
+ return NULL;
+ }
+
+ if (!IS_ALIGNED(size, OCMEM_MIN_ALIGN)) {
+ pr_err("ocmem: Invalid alignment, size must be %x aligned\n",
+ OCMEM_MIN_ALIGN);
+ return NULL;
+ }
+ return __ocmem_allocate_range(client_id, size, size,
+ size, can_block, can_wait);
+}
+
+struct ocmem_buf *ocmem_allocate_range(int client_id, unsigned long min,
+ unsigned long goal, unsigned long step)
+{
+ bool can_block = true;
+ bool can_wait = false;
+
+ if (!check_id(client_id)) {
+ pr_err("ocmem: Invalid client id: %d\n", client_id);
+ return NULL;
+ }
+
+ /* Asynchronous API requires notifier registration */
+ if (!check_notifier(client_id)) {
+ pr_err("ocmem: No notifier registered for client %d\n",
+ client_id);
+ return NULL;
+ }
+
+ if (min < OCMEM_MIN_ALLOC) {
+ pr_err("ocmem: requested min size %lx must be at least %x\n",
+ min, OCMEM_MIN_ALLOC);
+ return NULL;
+ }
+
+ if (!IS_ALIGNED(min | goal | step, OCMEM_MIN_ALIGN)) {
+ pr_err("ocmem: Invalid alignment, args must be %x aligned\n",
+ OCMEM_MIN_ALIGN);
+ return NULL;
+ }
+
+ return __ocmem_allocate_range(client_id, min, goal,
+ step, can_block, can_wait);
+}
+
+struct ocmem_buf *ocmem_allocate_nb(int client_id, unsigned long size)
+{
+ bool can_block = true;
+ bool can_wait = false;
+
+ if (!check_id(client_id)) {
+ pr_err("ocmem: Invalid client id: %d\n", client_id);
+ return NULL;
+ }
+
+ /* Asynchronous API requires notifier registration */
+ if (!check_notifier(client_id)) {
+ pr_err("ocmem: No notifier registered for client %d\n",
+ client_id);
+ return NULL;
+ }
+
+ if (size < OCMEM_MIN_ALLOC) {
+ pr_err("ocmem: requested size %lx must be at least %x\n",
+ size, OCMEM_MIN_ALLOC);
+ return NULL;
+ }
+
+ if (!IS_ALIGNED(size, OCMEM_MIN_ALIGN)) {
+ pr_err("ocmem: Invalid alignment, args must be %x aligned\n",
+ OCMEM_MIN_ALIGN);
+ return NULL;
+ }
+
+ return __ocmem_allocate_range(client_id, 0, size, size,
+ can_block, can_wait);
+
+}
+
+int ocmem_free(int client_id, struct ocmem_buf *buffer)
+{
+ if (!check_id(client_id)) {
+ pr_err("ocmem: Invalid client id: %d\n", client_id);
+ return -EINVAL;
+ }
+
+ if (!buffer) {
+ pr_err("ocmem: Invalid buffer\n");
+ return -EINVAL;
+ }
+
+ return __ocmem_free(client_id, buffer);
+}
+
+int pre_validate_chunk_list(struct ocmem_map_list *list)
+{
+ int i = 0;
+ struct ocmem_chunk *chunks;
+
+ if (!list)
+ return -EINVAL;
+
+ if (list->num_chunks > OCMEM_MAX_CHUNKS || list->num_chunks == 0)
+ return -EINVAL;
+
+ chunks = list->chunks;
+
+ if (!chunks)
+ return -EINVAL;
+
+ for (i = 0; i < list->num_chunks; i++) {
+ if (!chunks[i].ddr_paddr ||
+ chunks[i].size < MIN_CHUNK_SIZE)
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int ocmem_map(int client_id, struct ocmem_buf *buffer,
+ struct ocmem_map_list *list)
+{
+ int ret = 0;
+ struct ocmem_handle *handle = NULL;
+
+ if (!check_id(client_id)) {
+ pr_err("ocmem: Invalid client id: %d\n", client_id);
+ return -EINVAL;
+ }
+
+ /* Asynchronous API requires notifier registration */
+ if (!check_notifier(client_id)) {
+ pr_err("ocmem: No notifier registered for client %d\n",
+ client_id);
+ return -EINVAL;
+ }
+
+ if (!buffer) {
+ pr_err("ocmem: Invalid buffer\n");
+ return -EINVAL;
+ }
+
+ if (!pre_validate_chunk_list(list))
+ return -EINVAL;
+
+ handle = buffer_to_handle(buffer);
+
+ if (!handle)
+ return -EINVAL;
+
+ mutex_lock(&handle->handle_mutex);
+ ret = process_xfer(client_id, handle, list, TO_OCMEM);
+ mutex_unlock(&handle->handle_mutex);
+ return ret;
+}
+
+int ocmem_unmap(int client_id, struct ocmem_buf *buffer,
+ struct ocmem_map_list *list)
+{
+
+ int ret = 0;
+ struct ocmem_handle *handle = NULL;
+
+ if (!check_id(client_id)) {
+ pr_err("ocmem: Invalid client id: %d\n", client_id);
+ return -EINVAL;
+ }
+
+ /* Asynchronous API requires notifier registration */
+ if (!check_notifier(client_id)) {
+ pr_err("ocmem: No notifier registered for client %d\n",
+ client_id);
+ return -EINVAL;
+ }
+
+ if (!buffer) {
+ pr_err("ocmem: Invalid buffer\n");
+ return -EINVAL;
+ }
+
+ if (!pre_validate_chunk_list(list))
+ return -EINVAL;
+
+ handle = buffer_to_handle(buffer);
+
+ if (!handle)
+ return -EINVAL;
+
+ mutex_lock(&handle->handle_mutex);
+ ret = process_xfer(client_id, handle, list, TO_DDR);
+ mutex_unlock(&handle->handle_mutex);
+ return ret;
+}
+
+unsigned long get_max_quota(int client_id)
+{
+ if (!check_id(client_id)) {
+ pr_err("ocmem: Invalid client id: %d\n", client_id);
+ return 0x0;
+ }
+ return process_quota(client_id);
+}
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
new file mode 100644
index 0000000..10a267c
--- /dev/null
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -0,0 +1,1255 @@
+/* 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/slab.h>
+#include <linux/mm.h>
+#include <linux/rbtree.h>
+#include <linux/idr.h>
+#include <linux/genalloc.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <mach/ocmem_priv.h>
+
+enum request_states {
+ R_FREE = 0x0, /* request is not allocated */
+ R_PENDING, /* request has a pending operation */
+ R_ALLOCATED, /* request has been allocated */
+ R_MUST_GROW, /* request must grow as a part of pending operation */
+ R_MUST_SHRINK, /* request must shrink as a part of pending operation */
+ R_MUST_MAP, /* request must be mapped before being used */
+ R_MUST_UNMAP, /* request must be unmapped when not being used */
+ R_MAPPED, /* request is mapped and actively used by client */
+ R_UNMAPPED, /* request is not mapped, so it's not in active use */
+ R_EVICTED, /* request is evicted and must be restored */
+};
+
+#define SET_STATE(x, val) (set_bit((val), &(x)->state))
+#define CLEAR_STATE(x, val) (clear_bit((val), &(x)->state))
+#define TEST_STATE(x, val) (test_bit((val), &(x)->state))
+
+enum op_res {
+ OP_COMPLETE = 0x0,
+ OP_RESCHED,
+ OP_PARTIAL,
+ OP_FAIL = ~0x0,
+};
+
+/* Represents various client priorities */
+/* Note: More than one client can share a priority level */
+enum client_prio {
+ MIN_PRIO = 0x0,
+ NO_PRIO = MIN_PRIO,
+ PRIO_SENSORS = 0x1,
+ PRIO_BLAST = 0x1,
+ PRIO_LP_AUDIO = 0x1,
+ PRIO_HP_AUDIO = 0x2,
+ PRIO_VOICE = 0x3,
+ PRIO_GFX_GROWTH = 0x4,
+ PRIO_VIDEO = 0x5,
+ PRIO_GFX = 0x6,
+ PRIO_OCMEM = 0x7,
+ MAX_OCMEM_PRIO = PRIO_OCMEM + 1,
+};
+
+static struct list_head sched_queue[MAX_OCMEM_PRIO];
+static struct mutex sched_queue_mutex;
+
+/* The duration in msecs before a pending operation is scheduled
+ * This allows an idle window between use case boundaries where various
+ * hardware state changes can occur. The value will be tweaked on actual
+ * hardware.
+*/
+#define SCHED_DELAY 10
+
+/* OCMEM Operational modes */
+enum ocmem_client_modes {
+ OCMEM_PERFORMANCE = 1,
+ OCMEM_PASSIVE,
+ OCMEM_LOW_POWER,
+ OCMEM_MODE_MAX = OCMEM_LOW_POWER
+};
+
+/* OCMEM Addressing modes */
+enum ocmem_interconnects {
+ OCMEM_BLOCKED = 0,
+ OCMEM_PORT = 1,
+ OCMEM_OCMEMNOC = 2,
+ OCMEM_SYSNOC = 3,
+};
+
+/**
+ * Primary OCMEM Arbitration Table
+ **/
+struct ocmem_table {
+ int client_id;
+ int priority;
+ int mode;
+ int hw_interconnect;
+} ocmem_client_table[OCMEM_CLIENT_MAX] = {
+ {OCMEM_GRAPHICS, PRIO_GFX, OCMEM_PERFORMANCE, OCMEM_PORT},
+ {OCMEM_VIDEO, PRIO_VIDEO, OCMEM_PERFORMANCE, OCMEM_OCMEMNOC},
+ {OCMEM_CAMERA, NO_PRIO, OCMEM_PERFORMANCE, OCMEM_OCMEMNOC},
+ {OCMEM_HP_AUDIO, PRIO_HP_AUDIO, OCMEM_PASSIVE, OCMEM_BLOCKED},
+ {OCMEM_VOICE, PRIO_VOICE, OCMEM_PASSIVE, OCMEM_BLOCKED},
+ {OCMEM_LP_AUDIO, PRIO_LP_AUDIO, OCMEM_LOW_POWER, OCMEM_SYSNOC},
+ {OCMEM_SENSORS, PRIO_SENSORS, OCMEM_LOW_POWER, OCMEM_SYSNOC},
+ {OCMEM_BLAST, PRIO_BLAST, OCMEM_LOW_POWER, OCMEM_SYSNOC},
+};
+
+static struct rb_root sched_tree;
+static struct mutex sched_mutex;
+
+/* A region represents a continuous interval in OCMEM address space */
+struct ocmem_region {
+ /* Chain in Interval Tree */
+ struct rb_node region_rb;
+ /* Hash map of requests */
+ struct idr region_idr;
+ unsigned long r_start;
+ unsigned long r_end;
+ unsigned long r_sz;
+ /* Highest priority of all requests served by this region */
+ int max_prio;
+};
+
+/* Is OCMEM tightly coupled to the client ?*/
+static inline int is_tcm(int id)
+{
+ if (ocmem_client_table[id].hw_interconnect == OCMEM_PORT ||
+ ocmem_client_table[id].hw_interconnect == OCMEM_OCMEMNOC)
+ return 1;
+ else
+ return 0;
+}
+
+static inline int is_blocked(int id)
+{
+ return ocmem_client_table[id].hw_interconnect == OCMEM_BLOCKED ? 1 : 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)
+{
+ int hw_interconnect = ocmem_client_table[id].hw_interconnect;
+ unsigned long ret_addr = 0x0;
+
+ switch (hw_interconnect) {
+ case OCMEM_PORT:
+ ret_addr = phys_to_offset(addr);
+ break;
+ case OCMEM_OCMEMNOC:
+ case OCMEM_SYSNOC:
+ ret_addr = addr;
+ break;
+ case OCMEM_BLOCKED:
+ ret_addr = 0x0;
+ break;
+ }
+ return ret_addr;
+}
+
+/* Returns the address as viewed by the core */
+static unsigned long core_address(int id, unsigned long addr)
+{
+ int hw_interconnect = ocmem_client_table[id].hw_interconnect;
+ unsigned long ret_addr = 0x0;
+
+ switch (hw_interconnect) {
+ case OCMEM_PORT:
+ ret_addr = offset_to_phys(addr);
+ break;
+ case OCMEM_OCMEMNOC:
+ case OCMEM_SYSNOC:
+ ret_addr = addr;
+ break;
+ case OCMEM_BLOCKED:
+ ret_addr = 0x0;
+ break;
+ }
+ return ret_addr;
+}
+
+static int insert_region(struct ocmem_region *region)
+{
+
+ struct rb_root *root = &sched_tree;
+ struct rb_node **p = &root->rb_node;
+ struct rb_node *parent = NULL;
+ struct ocmem_region *tmp = NULL;
+ unsigned long addr = region->r_start;
+
+ while (*p) {
+ parent = *p;
+ tmp = rb_entry(parent, struct ocmem_region, region_rb);
+
+ if (tmp->r_end > addr) {
+ if (tmp->r_start <= addr)
+ break;
+ p = &(*p)->rb_left;
+ } else if (tmp->r_end <= addr)
+ p = &(*p)->rb_right;
+ }
+ rb_link_node(®ion->region_rb, parent, p);
+ rb_insert_color(®ion->region_rb, root);
+ return 0;
+}
+
+static int remove_region(struct ocmem_region *region)
+{
+ struct rb_root *root = &sched_tree;
+ rb_erase(®ion->region_rb, root);
+ return 0;
+}
+
+static struct ocmem_req *ocmem_create_req(void)
+{
+ struct ocmem_req *p = NULL;
+
+ p = kzalloc(sizeof(struct ocmem_req), GFP_KERNEL);
+ if (!p)
+ return NULL;
+
+ INIT_LIST_HEAD(&p->zone_list);
+ INIT_LIST_HEAD(&p->sched_list);
+ init_rwsem(&p->rw_sem);
+ SET_STATE(p, R_FREE);
+ return p;
+}
+
+static int ocmem_destroy_req(struct ocmem_req *req)
+{
+ kfree(req);
+ return 0;
+}
+
+static struct ocmem_region *create_region(void)
+{
+ struct ocmem_region *p = NULL;
+
+ p = kzalloc(sizeof(struct ocmem_region), GFP_KERNEL);
+ if (!p)
+ return NULL;
+ idr_init(&p->region_idr);
+ p->r_start = p->r_end = p->r_sz = 0x0;
+ p->max_prio = NO_PRIO;
+ return p;
+}
+
+static int destroy_region(struct ocmem_region *region)
+{
+ kfree(region);
+ return 0;
+}
+
+static int attach_req(struct ocmem_region *region, struct ocmem_req *req)
+{
+ int ret, id;
+
+ while (1) {
+ if (idr_pre_get(®ion->region_idr, GFP_KERNEL) == 0)
+ return -ENOMEM;
+
+ ret = idr_get_new_above(®ion->region_idr, req, 1, &id);
+
+ if (ret != -EAGAIN)
+ break;
+ }
+
+ if (!ret) {
+ req->req_id = id;
+ pr_debug("ocmem: request %p(id:%d) attached to region %p\n",
+ req, id, region);
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int detach_req(struct ocmem_region *region, struct ocmem_req *req)
+{
+ idr_remove(®ion->region_idr, req->req_id);
+ return 0;
+}
+
+static int populate_region(struct ocmem_region *region, struct ocmem_req *req)
+{
+ region->r_start = req->req_start;
+ region->r_end = req->req_end;
+ region->r_sz = req->req_end - req->req_start + 1;
+ return 0;
+}
+
+static int region_req_count(int id, void *ptr, void *data)
+{
+ int *count = data;
+ *count = *count + 1;
+ return 0;
+}
+
+static int req_count(struct ocmem_region *region)
+{
+ int count = 0;
+ idr_for_each(®ion->region_idr, region_req_count, &count);
+ return count;
+}
+
+static int compute_max_prio(int id, void *ptr, void *data)
+{
+ int *max = data;
+ struct ocmem_req *req = ptr;
+
+ if (req->prio > *max)
+ *max = req->prio;
+ return 0;
+}
+
+static int update_region_prio(struct ocmem_region *region)
+{
+ int max_prio;
+ if (req_count(region) != 0) {
+ idr_for_each(®ion->region_idr, compute_max_prio, &max_prio);
+ region->max_prio = max_prio;
+ } else {
+ region->max_prio = NO_PRIO;
+ }
+ pr_debug("ocmem: Updating prio of region %p as %d\n",
+ region, max_prio);
+
+ return 0;
+}
+
+static struct ocmem_region *find_region(unsigned long addr)
+{
+ struct ocmem_region *region = NULL;
+ struct rb_node *rb_node = NULL;
+
+ rb_node = sched_tree.rb_node;
+
+ while (rb_node) {
+ struct ocmem_region *tmp_region = NULL;
+ tmp_region = rb_entry(rb_node, struct ocmem_region, region_rb);
+
+ if (tmp_region->r_end > addr) {
+ region = tmp_region;
+ if (tmp_region->r_start <= addr)
+ break;
+ rb_node = rb_node->rb_left;
+ } else {
+ rb_node = rb_node->rb_right;
+ }
+ }
+ return region;
+}
+
+static struct ocmem_region *find_region_intersection(unsigned long start,
+ unsigned long end)
+{
+
+ struct ocmem_region *region = NULL;
+ region = find_region(start);
+ if (region && end <= region->r_start)
+ region = NULL;
+ return region;
+}
+
+static struct ocmem_region *find_region_match(unsigned long start,
+ unsigned long end)
+{
+
+ struct ocmem_region *region = NULL;
+ region = find_region(start);
+ if (region && start == region->r_start && end == region->r_end)
+ return region;
+ return NULL;
+}
+
+static struct ocmem_req *find_req_match(int owner, struct ocmem_region *region)
+{
+ struct ocmem_req *req = NULL;
+
+ if (!region)
+ return NULL;
+
+ req = idr_find(®ion->region_idr, owner);
+
+ return req;
+}
+
+/* Must be called with req->sem held */
+static inline int is_mapped(struct ocmem_req *req)
+{
+ return TEST_STATE(req, R_MAPPED);
+}
+
+/* Must be called with sched_mutex held */
+static int __sched_unmap(struct ocmem_req *req)
+{
+ struct ocmem_req *matched_req = NULL;
+ struct ocmem_region *matched_region = NULL;
+
+ matched_region = find_region_match(req->req_start, req->req_end);
+ matched_req = find_req_match(req->req_id, matched_region);
+
+ if (!matched_region || !matched_req) {
+ pr_err("Could not find backing region for req");
+ goto invalid_op_error;
+ }
+
+ if (matched_req != req) {
+ pr_err("Request does not match backing req");
+ goto invalid_op_error;
+ }
+
+ if (!is_mapped(req)) {
+ pr_err("Request is not currently mapped");
+ goto invalid_op_error;
+ }
+
+ /* Update the request state */
+ CLEAR_STATE(req, R_MAPPED);
+ SET_STATE(req, R_MUST_MAP);
+
+ return OP_COMPLETE;
+
+invalid_op_error:
+ return OP_FAIL;
+}
+
+/* Must be called with sched_mutex held */
+static int __sched_map(struct ocmem_req *req)
+{
+ struct ocmem_req *matched_req = NULL;
+ struct ocmem_region *matched_region = NULL;
+
+ matched_region = find_region_match(req->req_start, req->req_end);
+ matched_req = find_req_match(req->req_id, matched_region);
+
+ if (!matched_region || !matched_req) {
+ pr_err("Could not find backing region for req");
+ goto invalid_op_error;
+ }
+
+ if (matched_req != req) {
+ pr_err("Request does not match backing req");
+ goto invalid_op_error;
+ }
+
+ /* Update the request state */
+ CLEAR_STATE(req, R_MUST_MAP);
+ SET_STATE(req, R_MAPPED);
+
+ return OP_COMPLETE;
+
+invalid_op_error:
+ return OP_FAIL;
+}
+
+static int do_map(struct ocmem_req *req)
+{
+ int rc = 0;
+
+ mutex_lock(&sched_mutex);
+ rc = __sched_map(req);
+ mutex_unlock(&sched_mutex);
+
+ if (rc == OP_FAIL)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int do_unmap(struct ocmem_req *req)
+{
+ int rc = 0;
+
+ mutex_lock(&sched_mutex);
+ rc = __sched_unmap(req);
+ mutex_unlock(&sched_mutex);
+
+ if (rc == OP_FAIL)
+ return -EINVAL;
+
+ return 0;
+}
+
+/* process map is a wrapper where power control will be added later */
+static int process_map(struct ocmem_req *req, unsigned long start,
+ unsigned long end)
+{
+ return do_map(req);
+}
+
+/* process unmap is a wrapper where power control will be added later */
+static int process_unmap(struct ocmem_req *req, unsigned long start,
+ unsigned long end)
+{
+ return do_unmap(req);
+}
+
+static int __sched_grow(struct ocmem_req *req, bool can_block)
+{
+ unsigned long min = req->req_min;
+ unsigned long max = req->req_max;
+ unsigned long step = req->req_step;
+ int owner = req->owner;
+ unsigned long curr_sz = 0;
+ unsigned long growth_sz = 0;
+ unsigned long curr_start = 0;
+ enum client_prio prio = req->prio;
+ unsigned long alloc_addr = 0x0;
+ bool retry;
+ struct ocmem_region *spanned_r = NULL;
+ struct ocmem_region *overlap_r = NULL;
+
+ struct ocmem_req *matched_req = NULL;
+ struct ocmem_region *matched_region = NULL;
+
+ struct ocmem_zone *zone = get_zone(owner);
+ struct ocmem_region *region = NULL;
+
+ matched_region = find_region_match(req->req_start, req->req_end);
+ matched_req = find_req_match(req->req_id, matched_region);
+
+ if (!matched_region || !matched_req) {
+ pr_err("Could not find backing region for req");
+ goto invalid_op_error;
+ }
+
+ if (matched_req != req) {
+ pr_err("Request does not match backing req");
+ goto invalid_op_error;
+ }
+
+ curr_sz = matched_req->req_sz;
+ curr_start = matched_req->req_start;
+ growth_sz = matched_req->req_max - matched_req->req_sz;
+
+ pr_debug("Attempting to grow req %p from %lx to %lx\n",
+ req, matched_req->req_sz, matched_req->req_max);
+
+ retry = false;
+
+ pr_debug("ocmem: GROW: growth size %lx\n", growth_sz);
+
+retry_next_step:
+
+ spanned_r = NULL;
+ overlap_r = NULL;
+
+ spanned_r = find_region(zone->z_head);
+ overlap_r = find_region_intersection(zone->z_head,
+ zone->z_head + growth_sz);
+
+ if (overlap_r == NULL) {
+ /* no conflicting regions, schedule this region */
+ zone->z_ops->free(zone, curr_start, curr_sz);
+ alloc_addr = zone->z_ops->allocate(zone, curr_sz + growth_sz);
+
+ if (alloc_addr < 0) {
+ pr_err("ocmem: zone allocation operation failed\n");
+ goto internal_error;
+ }
+
+ curr_sz += growth_sz;
+ /* Detach the region from the interval tree */
+ /* This is to guarantee that any change in size
+ * causes the tree to be rebalanced if required */
+
+ detach_req(matched_region, req);
+ if (req_count(matched_region) == 0) {
+ remove_region(matched_region);
+ region = matched_region;
+ } else {
+ region = create_region();
+ if (!region) {
+ pr_err("ocmem: Unable to create region\n");
+ goto region_error;
+ }
+ }
+
+ /* update the request */
+ req->req_start = alloc_addr;
+ /* increment the size to reflect new length */
+ req->req_sz = curr_sz;
+ req->req_end = alloc_addr + req->req_sz - 1;
+
+ /* update request state */
+ CLEAR_STATE(req, R_MUST_GROW);
+ SET_STATE(req, R_ALLOCATED);
+ SET_STATE(req, R_MUST_MAP);
+ req->op = SCHED_MAP;
+
+ /* update the region with new req */
+ attach_req(region, req);
+ populate_region(region, req);
+ update_region_prio(region);
+
+ /* update the tree with new region */
+ if (insert_region(region)) {
+ pr_err("ocmem: Failed to insert the region\n");
+ goto region_error;
+ }
+
+ if (retry) {
+ SET_STATE(req, R_MUST_GROW);
+ SET_STATE(req, R_PENDING);
+ req->op = SCHED_GROW;
+ return OP_PARTIAL;
+ }
+ } else if (spanned_r != NULL && overlap_r != NULL) {
+ /* resolve conflicting regions based on priority */
+ if (overlap_r->max_prio < prio) {
+ /* Growth cannot be triggered unless a previous
+ * client of lower priority was evicted */
+ pr_err("ocmem: Invalid growth scheduled\n");
+ /* This is serious enough to fail */
+ BUG();
+ return OP_FAIL;
+ } else if (overlap_r->max_prio > prio) {
+ if (min == max) {
+ /* Cannot grow at this time, try later */
+ SET_STATE(req, R_PENDING);
+ SET_STATE(req, R_MUST_GROW);
+ return OP_RESCHED;
+ } else {
+ /* Try to grow in steps */
+ growth_sz -= step;
+ /* We are OOM at this point so need to retry */
+ if (growth_sz <= curr_sz) {
+ SET_STATE(req, R_PENDING);
+ SET_STATE(req, R_MUST_GROW);
+ return OP_RESCHED;
+ }
+ retry = true;
+ pr_debug("ocmem: Attempting with reduced size %lx\n",
+ growth_sz);
+ goto retry_next_step;
+ }
+ } else {
+ pr_err("ocmem: grow: New Region %p Existing %p\n",
+ matched_region, overlap_r);
+ pr_err("ocmem: Undetermined behavior\n");
+ /* This is serious enough to fail */
+ BUG();
+ }
+ } else if (spanned_r == NULL && overlap_r != NULL) {
+ goto err_not_supported;
+ }
+
+ return OP_COMPLETE;
+
+err_not_supported:
+ pr_err("ocmem: Scheduled unsupported operation\n");
+ return OP_FAIL;
+region_error:
+ zone->z_ops->free(zone, alloc_addr, curr_sz);
+ detach_req(region, req);
+ update_region_prio(region);
+ /* req is going to be destroyed by the caller anyways */
+internal_error:
+ destroy_region(region);
+invalid_op_error:
+ return OP_FAIL;
+}
+
+/* Must be called with sched_mutex held */
+static int __sched_free(struct ocmem_req *req)
+{
+ int owner = req->owner;
+ int ret = 0;
+
+ struct ocmem_req *matched_req = NULL;
+ struct ocmem_region *matched_region = NULL;
+
+ struct ocmem_zone *zone = get_zone(owner);
+
+ BUG_ON(!zone);
+
+ matched_region = find_region_match(req->req_start, req->req_end);
+ matched_req = find_req_match(req->req_id, matched_region);
+
+ if (!matched_region || !matched_req)
+ goto invalid_op_error;
+ if (matched_req != req)
+ goto invalid_op_error;
+
+ ret = zone->z_ops->free(zone,
+ matched_req->req_start, matched_req->req_sz);
+
+ if (ret < 0)
+ goto err_op_fail;
+
+ detach_req(matched_region, matched_req);
+ update_region_prio(matched_region);
+ if (req_count(matched_region) == 0) {
+ remove_region(matched_region);
+ destroy_region(matched_region);
+ }
+
+ /* Update the request */
+ req->req_start = 0x0;
+ req->req_sz = 0x0;
+ req->req_end = 0x0;
+ SET_STATE(req, R_FREE);
+ return OP_COMPLETE;
+invalid_op_error:
+ pr_err("ocmem: free: Failed to find matching region\n");
+err_op_fail:
+ pr_err("ocmem: free: Failed\n");
+ return OP_FAIL;
+}
+
+/* Must be called with sched_mutex held */
+static int __sched_allocate(struct ocmem_req *req, bool can_block,
+ bool can_wait)
+{
+ unsigned long min = req->req_min;
+ unsigned long max = req->req_max;
+ unsigned long step = req->req_step;
+ int owner = req->owner;
+ unsigned long sz = max;
+ enum client_prio prio = req->prio;
+ unsigned long alloc_addr = 0x0;
+ bool retry;
+
+ struct ocmem_region *spanned_r = NULL;
+ struct ocmem_region *overlap_r = NULL;
+
+ struct ocmem_zone *zone = get_zone(owner);
+ struct ocmem_region *region = NULL;
+
+ BUG_ON(!zone);
+
+ if (min > (zone->z_end - zone->z_start)) {
+ pr_err("ocmem: requested minimum size exceeds quota\n");
+ goto invalid_op_error;
+ }
+
+ if (max > (zone->z_end - zone->z_start)) {
+ pr_err("ocmem: requested maximum size exceeds quota\n");
+ goto invalid_op_error;
+ }
+
+ if (min > zone->z_free) {
+ pr_err("ocmem: out of memory for zone %d\n", owner);
+ goto invalid_op_error;
+ }
+
+ region = create_region();
+
+ if (!region) {
+ pr_err("ocmem: Unable to create region\n");
+ goto invalid_op_error;
+ }
+
+ retry = false;
+
+ pr_debug("ocmem: ALLOCATE: request size %lx\n", sz);
+
+retry_next_step:
+
+ spanned_r = NULL;
+ overlap_r = NULL;
+
+ spanned_r = find_region(zone->z_head);
+ overlap_r = find_region_intersection(zone->z_head, zone->z_head + sz);
+
+ if (overlap_r == NULL) {
+ /* no conflicting regions, schedule this region */
+ alloc_addr = zone->z_ops->allocate(zone, sz);
+
+ if (alloc_addr < 0) {
+ pr_err("Zone Allocation operation failed\n");
+ goto internal_error;
+ }
+
+ /* update the request */
+ req->req_start = alloc_addr;
+ req->req_end = alloc_addr + sz - 1;
+ req->req_sz = sz;
+ req->zone = zone;
+
+ /* update request state */
+ CLEAR_STATE(req, R_FREE);
+ SET_STATE(req, R_ALLOCATED);
+ SET_STATE(req, R_MUST_MAP);
+ req->op = SCHED_NOP;
+
+ /* attach the request to the region */
+ attach_req(region, req);
+ populate_region(region, req);
+ update_region_prio(region);
+
+ /* update the tree with new region */
+ if (insert_region(region)) {
+ pr_err("ocmem: Failed to insert the region\n");
+ zone->z_ops->free(zone, alloc_addr, sz);
+ detach_req(region, req);
+ update_region_prio(region);
+ /* req will be destroyed by the caller */
+ goto internal_error;
+ }
+
+ if (retry) {
+ SET_STATE(req, R_MUST_GROW);
+ SET_STATE(req, R_PENDING);
+ req->op = SCHED_GROW;
+ return OP_PARTIAL;
+ }
+ } else if (spanned_r != NULL && overlap_r != NULL) {
+ /* resolve conflicting regions based on priority */
+ if (overlap_r->max_prio < prio) {
+ if (min == max) {
+ pr_err("ocmem: Requires eviction support\n");
+ goto err_not_supported;
+ } else {
+ /* Try to allocate atleast >= 'min' immediately */
+ sz -= step;
+ if (sz < min)
+ goto err_out_of_mem;
+ retry = true;
+ pr_debug("ocmem: Attempting with reduced size %lx\n",
+ sz);
+ goto retry_next_step;
+ }
+ } else if (overlap_r->max_prio > prio) {
+ if (can_block == true) {
+ SET_STATE(req, R_PENDING);
+ SET_STATE(req, R_MUST_GROW);
+ return OP_RESCHED;
+ } else {
+ if (min == max) {
+ pr_err("Cannot allocate %lx synchronously\n",
+ sz);
+ goto err_out_of_mem;
+ } else {
+ sz -= step;
+ if (sz < min)
+ goto err_out_of_mem;
+ retry = true;
+ pr_debug("ocmem: Attempting reduced size %lx\n",
+ sz);
+ goto retry_next_step;
+ }
+ }
+ } else {
+ pr_err("ocmem: Undetermined behavior\n");
+ pr_err("ocmem: New Region %p Existing %p\n", region,
+ overlap_r);
+ /* This is serious enough to fail */
+ BUG();
+ }
+ } else if (spanned_r == NULL && overlap_r != NULL)
+ goto err_not_supported;
+
+ return OP_COMPLETE;
+
+err_not_supported:
+ pr_err("ocmem: Scheduled unsupported operation\n");
+ return OP_FAIL;
+
+err_out_of_mem:
+ pr_err("ocmem: Out of memory during allocation\n");
+internal_error:
+ destroy_region(region);
+invalid_op_error:
+ return OP_FAIL;
+}
+
+static int sched_enqueue(struct ocmem_req *priv)
+{
+ struct ocmem_req *next = NULL;
+ mutex_lock(&sched_queue_mutex);
+ list_add_tail(&priv->sched_list, &sched_queue[priv->owner]);
+ pr_debug("enqueued req %p\n", priv);
+ list_for_each_entry(next, &sched_queue[priv->owner], sched_list) {
+ pr_debug("pending requests for client %p\n", next);
+ }
+ mutex_unlock(&sched_queue_mutex);
+ return 0;
+}
+
+static struct ocmem_req *ocmem_fetch_req(void)
+{
+ int i;
+ struct ocmem_req *req = NULL;
+ struct ocmem_req *next = NULL;
+
+ mutex_lock(&sched_queue_mutex);
+ for (i = MIN_PRIO; i < MAX_OCMEM_PRIO; i++) {
+ if (list_empty(&sched_queue[i]))
+ continue;
+ list_for_each_entry_safe(req, next, &sched_queue[i], sched_list)
+ {
+ if (req) {
+ pr_debug("ocmem: Fetched pending request %p\n",
+ req);
+ list_del(&req->sched_list);
+ break;
+ }
+ }
+ }
+ mutex_unlock(&sched_queue_mutex);
+ return req;
+}
+
+int process_xfer(int id, struct ocmem_handle *handle,
+ struct ocmem_map_list *list, int direction)
+{
+
+ return 0;
+}
+
+unsigned long process_quota(int id)
+{
+ struct ocmem_zone *zone = NULL;
+
+ if (is_blocked(id))
+ return 0;
+
+ zone = get_zone(id);
+
+ if (zone && zone->z_pool)
+ return zone->z_end - zone->z_start;
+ else
+ return 0;
+}
+
+static int do_grow(struct ocmem_req *req)
+{
+ struct ocmem_buf *buffer = NULL;
+ bool can_block = true;
+ int rc = 0;
+
+ down_write(&req->rw_sem);
+ buffer = req->buffer;
+
+ /* Take the scheduler mutex */
+ mutex_lock(&sched_mutex);
+ rc = __sched_grow(req, can_block);
+ mutex_unlock(&sched_mutex);
+
+ if (rc == OP_FAIL)
+ goto err_op_fail;
+
+ if (rc == OP_RESCHED) {
+ pr_debug("ocmem: Enqueue this allocation");
+ sched_enqueue(req);
+ }
+
+ else if (rc == OP_COMPLETE || rc == OP_PARTIAL) {
+ buffer->addr = device_address(req->owner, req->req_start);
+ buffer->len = req->req_sz;
+ }
+
+ up_write(&req->rw_sem);
+ return 0;
+err_op_fail:
+ up_write(&req->rw_sem);
+ return -EINVAL;
+}
+
+static int process_grow(struct ocmem_req *req)
+{
+ int rc = 0;
+
+ /* Attempt to grow the region */
+ rc = do_grow(req);
+
+ if (rc < 0)
+ return -EINVAL;
+
+ /* Map the newly grown region */
+ if (is_tcm(req->owner)) {
+ rc = process_map(req, req->req_start, req->req_end);
+ if (rc < 0)
+ return -EINVAL;
+ }
+
+ /* Notify the client about the buffer growth */
+ rc = dispatch_notification(req->owner, OCMEM_ALLOC_GROW, req->buffer);
+ if (rc < 0) {
+ pr_err("No notifier callback to cater for req %p event: %d\n",
+ req, OCMEM_ALLOC_GROW);
+ BUG();
+ }
+ return 0;
+}
+
+static void ocmem_sched_wk_func(struct work_struct *work);
+DECLARE_DELAYED_WORK(ocmem_sched_thread, ocmem_sched_wk_func);
+
+static int ocmem_schedule_pending(void)
+{
+ schedule_delayed_work(&ocmem_sched_thread,
+ msecs_to_jiffies(SCHED_DELAY));
+ return 0;
+}
+
+static int do_free(struct ocmem_req *req)
+{
+ int rc = 0;
+ struct ocmem_buf *buffer = req->buffer;
+
+ down_write(&req->rw_sem);
+
+ if (is_mapped(req)) {
+ pr_err("ocmem: Buffer needs to be unmapped before free\n");
+ goto err_free_fail;
+ }
+
+ /* Grab the sched mutex */
+ mutex_lock(&sched_mutex);
+ rc = __sched_free(req);
+ mutex_unlock(&sched_mutex);
+
+ switch (rc) {
+
+ case OP_COMPLETE:
+ buffer->addr = 0x0;
+ buffer->len = 0x0;
+ break;
+ case OP_FAIL:
+ default:
+ goto err_free_fail;
+ break;
+ }
+
+ up_write(&req->rw_sem);
+ return 0;
+err_free_fail:
+ up_write(&req->rw_sem);
+ pr_err("ocmem: freeing req %p failed\n", req);
+ return -EINVAL;
+}
+
+int process_free(int id, struct ocmem_handle *handle)
+{
+ struct ocmem_req *req = NULL;
+ struct ocmem_buf *buffer = NULL;
+ int rc = 0;
+
+ if (is_blocked(id)) {
+ pr_err("Client %d cannot request free\n", id);
+ return -EINVAL;
+ }
+
+ req = handle_to_req(handle);
+ buffer = handle_to_buffer(handle);
+
+ if (!req)
+ return -EINVAL;
+
+ if (req->req_start != core_address(id, buffer->addr)) {
+ pr_err("Invalid buffer handle passed for free\n");
+ return -EINVAL;
+ }
+
+ if (is_tcm(req->owner)) {
+ rc = process_unmap(req, req->req_start, req->req_end);
+ if (rc < 0)
+ return -EINVAL;
+ }
+
+ rc = do_free(req);
+
+ if (rc < 0)
+ return -EINVAL;
+
+ ocmem_destroy_req(req);
+ handle->req = NULL;
+
+ ocmem_schedule_pending();
+ return 0;
+}
+
+static int do_allocate(struct ocmem_req *req, bool can_block, bool can_wait)
+{
+ int rc = 0;
+ struct ocmem_buf *buffer = req->buffer;
+
+ down_write(&req->rw_sem);
+
+ /* Take the scheduler mutex */
+ mutex_lock(&sched_mutex);
+ rc = __sched_allocate(req, can_block, can_wait);
+ mutex_unlock(&sched_mutex);
+
+ if (rc == OP_FAIL)
+ goto err_allocate_fail;
+
+ if (rc == OP_RESCHED) {
+ buffer->addr = 0x0;
+ buffer->len = 0x0;
+ pr_debug("ocmem: Enqueuing req %p\n", req);
+ sched_enqueue(req);
+ } else if (rc == OP_PARTIAL) {
+ buffer->addr = device_address(req->owner, req->req_start);
+ buffer->len = req->req_sz;
+ pr_debug("ocmem: Enqueuing req %p\n", req);
+ sched_enqueue(req);
+ } else if (rc == OP_COMPLETE) {
+ buffer->addr = device_address(req->owner, req->req_start);
+ buffer->len = req->req_sz;
+ }
+
+ up_write(&req->rw_sem);
+ return 0;
+err_allocate_fail:
+ up_write(&req->rw_sem);
+ return -EINVAL;
+}
+
+
+int process_allocate(int id, struct ocmem_handle *handle,
+ unsigned long min, unsigned long max,
+ unsigned long step, bool can_block, bool can_wait)
+{
+
+ struct ocmem_req *req = NULL;
+ struct ocmem_buf *buffer = NULL;
+ int rc = 0;
+
+ /* sanity checks */
+ if (is_blocked(id)) {
+ pr_err("Client %d cannot request allocation\n", id);
+ return -EINVAL;
+ }
+
+ if (handle->req != NULL) {
+ pr_err("Invalid handle passed in\n");
+ return -EINVAL;
+ }
+
+ buffer = handle_to_buffer(handle);
+ BUG_ON(buffer == NULL);
+
+ /* prepare a request structure to represent this transaction */
+ req = ocmem_create_req();
+ if (!req)
+ return -ENOMEM;
+
+ req->owner = id;
+ req->req_min = min;
+ req->req_max = max;
+ req->req_step = step;
+ req->prio = ocmem_client_table[id].priority;
+ req->op = SCHED_ALLOCATE;
+ req->buffer = buffer;
+
+ rc = do_allocate(req, can_block, can_wait);
+
+ if (rc < 0)
+ goto do_allocate_error;
+
+ handle->req = req;
+
+ if (is_tcm(id)) {
+ rc = process_map(req, req->req_start, req->req_end);
+ if (rc < 0)
+ goto map_error;
+ }
+
+ return 0;
+
+map_error:
+ handle->req = NULL;
+ do_free(req);
+do_allocate_error:
+ ocmem_destroy_req(req);
+ return -EINVAL;
+}
+
+int process_delayed_allocate(struct ocmem_req *req)
+{
+
+ struct ocmem_handle *handle = NULL;
+ int rc = 0;
+ int id = req->owner;
+
+ handle = req_to_handle(req);
+ BUG_ON(handle == NULL);
+
+ rc = do_allocate(req, true, false);
+
+ if (rc < 0)
+ goto do_allocate_error;
+
+ if (is_tcm(id)) {
+ rc = process_map(req, req->req_start, req->req_end);
+ if (rc < 0)
+ goto map_error;
+ }
+
+ /* Notify the client about the buffer growth */
+ rc = dispatch_notification(id, OCMEM_ALLOC_GROW, req->buffer);
+ if (rc < 0) {
+ pr_err("No notifier callback to cater for req %p event: %d\n",
+ req, OCMEM_ALLOC_GROW);
+ BUG();
+ }
+ return 0;
+
+map_error:
+ handle->req = NULL;
+ do_free(req);
+do_allocate_error:
+ ocmem_destroy_req(req);
+ return -EINVAL;
+}
+
+static void ocmem_sched_wk_func(struct work_struct *work)
+{
+
+ struct ocmem_buf *buffer = NULL;
+ struct ocmem_handle *handle = NULL;
+ struct ocmem_req *req = ocmem_fetch_req();
+
+ if (!req) {
+ pr_debug("No Pending Requests found\n");
+ return;
+ }
+
+ pr_debug("ocmem: sched_wk pending req %p\n", req);
+ handle = req_to_handle(req);
+ buffer = handle_to_buffer(handle);
+ BUG_ON(req->op == SCHED_NOP);
+
+ switch (req->op) {
+ case SCHED_GROW:
+ process_grow(req);
+ break;
+ case SCHED_ALLOCATE:
+ process_delayed_allocate(req);
+ break;
+ default:
+ pr_err("ocmem: Unknown operation encountered\n");
+ break;
+ }
+ return;
+}
+
+int ocmem_sched_init(void)
+{
+ int i = 0;
+ sched_tree = RB_ROOT;
+ mutex_init(&sched_mutex);
+ mutex_init(&sched_queue_mutex);
+ for (i = MIN_PRIO; i < MAX_OCMEM_PRIO; i++)
+ INIT_LIST_HEAD(&sched_queue[i]);
+
+ return 0;
+}
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index b40c0c7..49e63aa 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -202,8 +202,6 @@
pen_release = cpu_logical_map(cpu);
__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
- __asm__("sev");
- mb();
/*
* Send the secondary CPU a soft interrupt, thereby causing
diff --git a/arch/arm/mach-msm/rpm-regulator-smd.c b/arch/arm/mach-msm/rpm-regulator-smd.c
index b892d05..152b6e5 100644
--- a/arch/arm/mach-msm/rpm-regulator-smd.c
+++ b/arch/arm/mach-msm/rpm-regulator-smd.c
@@ -762,10 +762,11 @@
struct rpm_vreg *rpm_vreg;
regulator = regulator_get(dev, supply);
- if (regulator == NULL) {
- pr_err("could not find regulator for: dev=%s, id=%s\n",
- (dev ? dev_name(dev) : ""), (supply ? supply : ""));
- return ERR_PTR(-ENODEV);
+ if (IS_ERR(regulator)) {
+ pr_err("could not find regulator for: dev=%s, supply=%s, rc=%ld\n",
+ (dev ? dev_name(dev) : ""), (supply ? supply : ""),
+ PTR_ERR(regulator));
+ return ERR_CAST(regulator);
}
framework_reg = regulator_get_drvdata(regulator);
@@ -818,7 +819,7 @@
static int rpm_regulator_check_input(struct rpm_regulator *regulator)
{
- if (regulator == NULL || regulator->rpm_vreg == NULL) {
+ if (IS_ERR_OR_NULL(regulator) || regulator->rpm_vreg == NULL) {
pr_err("invalid rpm_regulator pointer\n");
return -EINVAL;
}
@@ -1142,7 +1143,7 @@
reg->set_active = !!(val & RPM_SET_CONFIG_ACTIVE);
reg->set_sleep = !!(val & RPM_SET_CONFIG_SLEEP);
- init_data = of_get_regulator_init_data(dev);
+ init_data = of_get_regulator_init_data(dev, node);
if (init_data == NULL) {
dev_err(dev, "%s: unable to allocate memory\n", __func__);
rc = -ENOMEM;
diff --git a/arch/arm/mach-msm/rpm_resources.h b/arch/arm/mach-msm/rpm_resources.h
index d594405..46d6d94 100644
--- a/arch/arm/mach-msm/rpm_resources.h
+++ b/arch/arm/mach-msm/rpm_resources.h
@@ -102,6 +102,8 @@
unsigned int rpmrs_target_id[MSM_RPMRS_ID_LAST];
};
+#if defined(CONFIG_MSM_RPM)
+
int msm_rpmrs_set(int ctx, struct msm_rpm_iv_pair *req, int count);
int msm_rpmrs_set_noirq(int ctx, struct msm_rpm_iv_pair *req, int count);
int msm_rpmrs_set_bits_noirq(int ctx, struct msm_rpm_iv_pair *req, int count,
@@ -139,4 +141,74 @@
void msm_rpmrs_show_resources(void);
int msm_rpmrs_levels_init(struct msm_rpmrs_platform_data *data);
+#else
+
+static inline int msm_rpmrs_set(int ctx, struct msm_rpm_iv_pair *req,
+ int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpmrs_set_noirq(int ctx, struct msm_rpm_iv_pair *req,
+ int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpmrs_set_bits_noirq(int ctx, struct msm_rpm_iv_pair *req,
+ int count, int *mask)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpmrs_set_nosleep(
+ int ctx, struct msm_rpm_iv_pair *req, int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpmrs_clear(int ctx, struct msm_rpm_iv_pair *req,
+ int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpmrs_clear_noirq(int ctx, struct msm_rpm_iv_pair *req,
+ int count)
+{
+ return -ENODEV;
+}
+
+static inline int msm_rpmrs_clear_nosleep(
+ int ctx, struct msm_rpm_iv_pair *req, int count)
+{
+ return -ENODEV;
+}
+
+static inline struct msm_rpmrs_limits *msm_rpmrs_lowest_limits(
+ bool from_idle, enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
+ uint32_t sleep_us)
+{
+ return NULL;
+}
+
+static inline int msm_rpmrs_enter_sleep(uint32_t sclk_count,
+ struct msm_rpmrs_limits *limits, bool from_idle, bool notify_rpm)
+{
+ return -ENODEV;
+}
+
+static inline void msm_rpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
+ bool from_idle, bool notify_rpm, bool collapsed)
+{
+ return;
+}
+
+static inline int msm_rpmrs_levels_init(struct msm_rpmrs_platform_data *data)
+{
+ return -ENODEV;
+}
+
+#endif /* CONFIG_MSM_RPM */
+
#endif /* __ARCH_ARM_MACH_MSM_RPM_RESOURCES_H */
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index 2980811..6e81be6 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -282,14 +282,22 @@
uint32_t notify_rpm;
};
- struct mode_of mode_of_data[] = {
- {"qcom,spm-cmd-wfi", MSM_SPM_MODE_CLOCK_GATING, 0},
- {"qcom,spm-cmd-ret", MSM_SPM_MODE_POWER_RETENTION, 0},
- {"qcom,spm-cmd-spc", MSM_SPM_MODE_POWER_COLLAPSE, 0},
- {"qcom,spm-cmd-pc", MSM_SPM_MODE_POWER_COLLAPSE, 1},
+ struct mode_of of_cpu_modes[] = {
+ {"qcom,saw2-spm-cmd-wfi", MSM_SPM_MODE_CLOCK_GATING, 0},
+ {"qcom,saw2-spm-cmd-ret", MSM_SPM_MODE_POWER_RETENTION, 0},
+ {"qcom,saw2-spm-cmd-spc", MSM_SPM_MODE_POWER_COLLAPSE, 0},
+ {"qcom,saw2-spm-cmd-pc", MSM_SPM_MODE_POWER_COLLAPSE, 1},
};
- BUG_ON(ARRAY_SIZE(mode_of_data) > MSM_SPM_MODE_NR);
+ struct mode_of of_l2_modes[] = {
+ {"qcom,saw2-spm-cmd-ret", MSM_SPM_L2_MODE_RETENTION, 1},
+ {"qcom,saw2-spm-cmd-gdhs", MSM_SPM_L2_MODE_GDHS, 1},
+ {"qcom,saw2-spm-cmd-pc", MSM_SPM_L2_MODE_POWER_COLLAPSE, 1},
+ };
+
+ struct mode_of *mode_of_data;
+ int num_modes;
+
memset(&spm_data, 0, sizeof(struct msm_spm_platform_data));
memset(&modes, 0,
(MSM_SPM_MODE_NR - 2) * sizeof(struct msm_spm_seq_entry));
@@ -339,7 +347,22 @@
spm_data.reg_init_values[spm_of_data[i].id] = val;
}
- for (i = 0; i < ARRAY_SIZE(mode_of_data); i++) {
+ /*
+ * Device with id 0..NR_CPUS are SPM for apps cores
+ * Device with id 0xFFFF is for L2 SPM.
+ */
+ if (cpu >= 0 && cpu < num_possible_cpus()) {
+ mode_of_data = of_cpu_modes;
+ num_modes = ARRAY_SIZE(of_cpu_modes);
+ dev = &per_cpu(msm_cpu_spm_device, cpu);
+
+ } else {
+ mode_of_data = of_l2_modes;
+ num_modes = ARRAY_SIZE(of_l2_modes);
+ dev = &msm_spm_l2_device;
+ }
+
+ for (i = 0; i < num_modes; i++) {
key = mode_of_data[i].key;
modes[mode_count].cmd =
(uint8_t *)of_get_property(node, key, &len);
@@ -353,16 +376,8 @@
spm_data.modes = modes;
spm_data.num_modes = mode_count;
- /*
- * Device with id 0..NR_CPUS are SPM for apps cores
- * Device with id 0xFFFF is for L2 SPM.
- */
- if (cpu >= 0 && cpu < num_possible_cpus())
- dev = &per_cpu(msm_cpu_spm_device, cpu);
- else
- dev = &msm_spm_l2_device;
-
ret = msm_spm_dev_init(dev, &spm_data);
+
if (ret < 0)
pr_warn("%s():failed core-id:%u ret:%d\n", __func__, cpu, ret);
diff --git a/drivers/base/genlock.c b/drivers/base/genlock.c
index 5e1d7af..aed71c0 100644
--- a/drivers/base/genlock.c
+++ b/drivers/base/genlock.c
@@ -34,7 +34,15 @@
#define GENLOCK_LOG_ERR(fmt, args...) \
pr_err("genlock: %s: " fmt, __func__, ##args)
+/* The genlock magic stored in the kernel private data is used to protect
+ * against the possibility of user space passing a valid fd to a
+ * non-genlock file for genlock_attach_lock()
+ */
+#define GENLOCK_MAGIC_OK 0xD2EAD10C
+#define GENLOCK_MAGIC_BAD 0xD2EADBAD
+
struct genlock {
+ unsigned int magic; /* Magic for attach verification */
struct list_head active; /* List of handles holding lock */
spinlock_t lock; /* Spinlock to protect the lock internals */
wait_queue_head_t queue; /* Holding pen for processes pending lock */
@@ -56,7 +64,7 @@
* released while another process tries to attach it
*/
-static DEFINE_SPINLOCK(genlock_file_lock);
+static DEFINE_SPINLOCK(genlock_ref_lock);
static void genlock_destroy(struct kref *kref)
{
@@ -68,10 +76,9 @@
* still active after the lock gets released
*/
- spin_lock(&genlock_file_lock);
if (lock->file)
lock->file->private_data = NULL;
- spin_unlock(&genlock_file_lock);
+ lock->magic = GENLOCK_MAGIC_BAD;
kfree(lock);
}
@@ -130,6 +137,7 @@
init_waitqueue_head(&lock->queue);
spin_lock_init(&lock->lock);
+ lock->magic = GENLOCK_MAGIC_OK;
lock->state = _UNLOCKED;
/*
@@ -203,21 +211,30 @@
* released and then attached
*/
- spin_lock(&genlock_file_lock);
+ spin_lock(&genlock_ref_lock);
lock = file->private_data;
- spin_unlock(&genlock_file_lock);
fput(file);
if (lock == NULL) {
GENLOCK_LOG_ERR("File descriptor is invalid\n");
- return ERR_PTR(-EINVAL);
+ goto fail_invalid;
+ }
+
+ if (lock->magic != GENLOCK_MAGIC_OK) {
+ GENLOCK_LOG_ERR("Magic is invalid - 0x%X\n", lock->magic);
+ goto fail_invalid;
}
handle->lock = lock;
kref_get(&lock->refcount);
+ spin_unlock(&genlock_ref_lock);
return lock;
+
+fail_invalid:
+ spin_unlock(&genlock_ref_lock);
+ return ERR_PTR(-EINVAL);
}
EXPORT_SYMBOL(genlock_attach_lock);
@@ -595,7 +612,9 @@
}
spin_unlock_irqrestore(&handle->lock->lock, flags);
+ spin_lock(&genlock_ref_lock);
kref_put(&handle->lock->refcount, genlock_destroy);
+ spin_unlock(&genlock_ref_lock);
handle->lock = NULL;
handle->active = 0;
}
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index d54d3dc..fedcf03 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -16,6 +16,7 @@
#include <linux/diagchar.h>
#include <linux/sched.h>
#include <linux/err.h>
+#include <linux/ratelimit.h>
#include <linux/workqueue.h>
#include <linux/pm_runtime.h>
#include <linux/platform_device.h>
@@ -55,7 +56,7 @@
err = diag_bridge_read((char *)driver->buf_in_hsic,
IN_BUF_SIZE);
if (err) {
- pr_err("DIAG: Error initiating HSIC read, err: %d\n",
+ pr_err_ratelimited("DIAG: Error initiating HSIC read, err: %d\n",
err);
/*
* If the error is recoverable, then clear
@@ -63,7 +64,7 @@
* read on the next frame. Otherwise, don't
* resubmit a read on the next frame.
*/
- if ((-ESHUTDOWN) != err)
+ if ((-ENODEV) != err)
driver->in_busy_hsic_read = 0;
}
}
@@ -373,14 +374,15 @@
err = diag_bridge_write(driver->usb_buf_mdm_out,
driver->read_len_mdm);
if (err) {
- pr_err("DIAG: mdm data on hsic write err: %d\n", err);
+ pr_err_ratelimited("DIAG: mdm data on hsic write err: %d\n",
+ err);
/*
* If the error is recoverable, then clear
* the write flag, so we will resubmit a
* write on the next frame. Otherwise, don't
* resubmit a write on the next frame.
*/
- if ((-ESHUTDOWN) != err)
+ if ((-ENODEV) != err)
driver->in_busy_hsic_write = 0;
}
}
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 5997405..5798c94 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -837,15 +837,16 @@
struct cpu_dbs_info_s *this_dbs_info;
unsigned int cpu = smp_processor_id();
+ get_online_cpus();
+
if (lock_policy_rwsem_write(cpu) < 0)
- return;
+ goto bail_acq_sema_failed;
this_dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
policy = this_dbs_info->cur_policy;
if (!policy) {
/* CPU not using ondemand governor */
- unlock_policy_rwsem_write(cpu);
- return;
+ goto bail_incorrect_governor;
}
if (policy->cur < policy->max) {
@@ -856,7 +857,13 @@
this_dbs_info->prev_cpu_idle = get_cpu_idle_time(cpu,
&this_dbs_info->prev_cpu_wall);
}
+
+bail_incorrect_governor:
unlock_policy_rwsem_write(cpu);
+
+bail_acq_sema_failed:
+ put_online_cpus();
+ return;
}
static void dbs_input_event(struct input_handle *handle, unsigned int type,
diff --git a/drivers/gpio/qpnp-gpio.c b/drivers/gpio/qpnp-gpio.c
index d9a23e1..97859e5 100644
--- a/drivers/gpio/qpnp-gpio.c
+++ b/drivers/gpio/qpnp-gpio.c
@@ -22,6 +22,8 @@
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
+#include <linux/export.h>
+#include <linux/module.h>
#include <linux/qpnp/gpio.h>
#include <linux/export.h>
@@ -504,27 +506,26 @@
}
static int qpnp_gpio_of_gpio_xlate(struct gpio_chip *gpio_chip,
- struct device_node *np,
- const void *gpio_spec, u32 *flags)
+ const struct of_phandle_args *gpio_spec,
+ u32 *flags)
{
struct qpnp_gpio_chip *q_chip = dev_get_drvdata(gpio_chip->dev);
struct qpnp_gpio_spec *q_spec;
- const __be32 *gpio = gpio_spec;
- u32 n = be32_to_cpup(gpio);
if (WARN_ON(gpio_chip->of_gpio_n_cells < 2)) {
pr_err("of_gpio_n_cells < 2\n");
return -EINVAL;
}
- q_spec = qpnp_pmic_gpio_get_spec(q_chip, n);
+ q_spec = qpnp_pmic_gpio_get_spec(q_chip, gpio_spec->args[0]);
if (!q_spec) {
- pr_err("no such PMIC gpio %u in device topology\n", n);
+ pr_err("no such PMIC gpio %u in device topology\n",
+ gpio_spec->args[0]);
return -EINVAL;
}
if (flags)
- *flags = be32_to_cpu(gpio[1]);
+ *flags = gpio_spec->args[1];
return q_spec->gpio_chip_idx;
}
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 6041cd8..615c7ad 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -156,7 +156,7 @@
"a225_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
1536, 768, 3, SZ_512K },
/* A3XX doesn't use the pix_shader_start */
- { ADRENO_REV_A305, 3, 0, 5, 0,
+ { ADRENO_REV_A305, 3, 0, 5, ANY_ID,
"a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev,
512, 0, 2, SZ_256K },
/* A3XX doesn't use the pix_shader_start */
@@ -500,8 +500,9 @@
* thing and set the chip_id based on the SoC
*/
+ unsigned int version = socinfo_get_version();
+
if (cpu_is_apq8064()) {
- unsigned int version = socinfo_get_version();
/* A320 */
majorid = 2;
@@ -518,10 +519,21 @@
else
patchid = 0;
} else if (cpu_is_msm8930()) {
+
/* A305 */
majorid = 0;
minorid = 5;
- patchid = 0;
+
+ /*
+ * V1.2 has some GPU work arounds that we need to communicate
+ * up to user space via the patchid
+ */
+
+ if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
+ (SOCINFO_VERSION_MINOR(version) == 2))
+ patchid = 2;
+ else
+ patchid = 0;
}
return (0x03 << 24) | (majorid << 16) | (minorid << 8) | patchid;
@@ -1342,7 +1354,7 @@
* get an interrupt */
cmds[0] = cp_type3_packet(CP_NOP, 1);
cmds[1] = 0;
- adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
+ adreno_ringbuffer_issuecmds_intr(device, context,
&cmds[0], 2);
}
}
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 4ce56a4..df5f0f9 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -27,8 +27,8 @@
/* Flags to control command packet settings */
#define KGSL_CMD_FLAGS_NONE 0x00000000
#define KGSL_CMD_FLAGS_PMODE 0x00000001
-#define KGSL_CMD_FLAGS_NO_TS_CMP 0x00000002
-#define KGSL_CMD_FLAGS_NOT_KERNEL_CMD 0x00000004
+#define KGSL_CMD_FLAGS_NOT_KERNEL_CMD 0x00000002
+#define KGSL_CMD_FLAGS_DUMMY_INTR_CMD 0x00000004
/* Command identifiers */
#define KGSL_CONTEXT_TO_MEM_IDENTIFIER 0x2EADBEEF
@@ -46,6 +46,8 @@
#define ADRENO_ISTORE_START 0x5000 /* Istore offset */
+#define ADRENO_NUM_CTX_SWITCH_ALLOWED_BEFORE_DRAW 50
+
enum adreno_gpurev {
ADRENO_REV_UNKNOWN = 0,
ADRENO_REV_A200 = 200,
@@ -90,11 +92,14 @@
unsigned int reg_rbbm_status;
unsigned int reg_cp_pfp_ucode_data;
unsigned int reg_cp_pfp_ucode_addr;
+ /* keeps track of when we need to execute the draw workaround code */
+ int ctx_switches_since_last_draw;
/* GPU specific function hooks */
int (*ctxt_create)(struct adreno_device *, struct adreno_context *);
void (*ctxt_save)(struct adreno_device *, struct adreno_context *);
void (*ctxt_restore)(struct adreno_device *, struct adreno_context *);
+ void (*ctxt_draw_workaround)(struct adreno_device *);
irqreturn_t (*irq_handler)(struct adreno_device *);
void (*irq_control)(struct adreno_device *, int);
void * (*snapshot)(struct adreno_device *, void *, int *, int);
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 7ccfd3f..c3c266e 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1450,11 +1450,49 @@
return ret;
}
+static void a2xx_drawctxt_draw_workaround(struct adreno_device *adreno_dev)
+{
+ struct kgsl_device *device = &adreno_dev->dev;
+ unsigned int cmd[11];
+ unsigned int *cmds = &cmd[0];
+
+ adreno_dev->gpudev->ctx_switches_since_last_draw++;
+ /* If there have been > than ADRENO_NUM_CTX_SWITCH_ALLOWED_BEFORE_DRAW
+ * calls to context switches w/o gmem being saved then we need to
+ * execute this workaround */
+ if (adreno_dev->gpudev->ctx_switches_since_last_draw >
+ ADRENO_NUM_CTX_SWITCH_ALLOWED_BEFORE_DRAW)
+ adreno_dev->gpudev->ctx_switches_since_last_draw = 0;
+ else
+ return;
+ /*
+ * Issue an empty draw call to avoid possible hangs due to
+ * repeated idles without intervening draw calls.
+ * On adreno 225 the PC block has a cache that is only
+ * flushed on draw calls and repeated idles can make it
+ * overflow. The gmem save path contains draw calls so
+ * this workaround isn't needed there.
+ */
+ *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+ *cmds++ = (0x4 << 16) | (REG_PA_SU_SC_MODE_CNTL - 0x2000);
+ *cmds++ = 0;
+ *cmds++ = cp_type3_packet(CP_DRAW_INDX, 5);
+ *cmds++ = 0;
+ *cmds++ = 1<<14;
+ *cmds++ = 0;
+ *cmds++ = device->mmu.setstate_memory.gpuaddr;
+ *cmds++ = 0;
+ *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
+ *cmds++ = 0x00000000;
+
+ adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
+ &cmd[0], 11);
+}
+
static void a2xx_drawctxt_save(struct adreno_device *adreno_dev,
struct adreno_context *context)
{
struct kgsl_device *device = &adreno_dev->dev;
- unsigned int cmd[22];
if (context == NULL)
return;
@@ -1499,33 +1537,11 @@
adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE,
context->chicken_restore, 3);
}
+ adreno_dev->gpudev->ctx_switches_since_last_draw = 0;
context->flags |= CTXT_FLAGS_GMEM_RESTORE;
- } else if (adreno_is_a225(adreno_dev)) {
- unsigned int *cmds = &cmd[0];
- /*
- * Issue an empty draw call to avoid possible hangs due to
- * repeated idles without intervening draw calls.
- * On adreno 225 the PC block has a cache that is only
- * flushed on draw calls and repeated idles can make it
- * overflow. The gmem save path contains draw calls so
- * this workaround isn't needed there.
- */
- *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
- *cmds++ = (0x4 << 16) | (REG_PA_SU_SC_MODE_CNTL - 0x2000);
- *cmds++ = 0;
- *cmds++ = cp_type3_packet(CP_DRAW_INDX, 5);
- *cmds++ = 0;
- *cmds++ = 1<<14;
- *cmds++ = 0;
- *cmds++ = device->mmu.setstate_memory.gpuaddr;
- *cmds++ = 0;
- *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
- *cmds++ = 0x00000000;
-
- adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
- &cmd[0], 11);
- }
+ } else if (adreno_is_a225(adreno_dev))
+ a2xx_drawctxt_draw_workaround(adreno_dev);
}
static void a2xx_drawctxt_restore(struct adreno_device *adreno_dev,
@@ -1983,6 +1999,7 @@
.ctxt_create = a2xx_drawctxt_create,
.ctxt_save = a2xx_drawctxt_save,
.ctxt_restore = a2xx_drawctxt_restore,
+ .ctxt_draw_workaround = a2xx_drawctxt_draw_workaround,
.irq_handler = a2xx_irq_handler,
.irq_control = a2xx_irq_control,
.snapshot = a2xx_snapshot,
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 1902f50..e258072 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2409,30 +2409,29 @@
static void a3xx_cp_callback(struct adreno_device *adreno_dev, int irq)
{
- struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
+ struct kgsl_device *device = &adreno_dev->dev;
if (irq == A3XX_INT_CP_RB_INT) {
unsigned int context_id;
- kgsl_sharedmem_readl(&adreno_dev->dev.memstore,
- &context_id,
+ kgsl_sharedmem_readl(&device->memstore, &context_id,
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
current_context));
if (context_id < KGSL_MEMSTORE_MAX) {
- kgsl_sharedmem_writel(&rb->device->memstore,
+ kgsl_sharedmem_writel(&device->memstore,
KGSL_MEMSTORE_OFFSET(context_id,
ts_cmp_enable), 0);
wmb();
}
- KGSL_CMD_WARN(rb->device, "ringbuffer rb interrupt\n");
+ KGSL_CMD_WARN(device, "ringbuffer rb interrupt\n");
}
- wake_up_interruptible_all(&rb->device->wait_queue);
+ wake_up_interruptible_all(&device->wait_queue);
/* Schedule work to free mem and issue ibs */
- queue_work(rb->device->work_queue, &rb->device->ts_expired_ws);
+ queue_work(device->work_queue, &device->ts_expired_ws);
- atomic_notifier_call_chain(&rb->device->ts_notifier_list,
- rb->device->id, NULL);
+ atomic_notifier_call_chain(&device->ts_notifier_list,
+ device->id, NULL);
}
#define A3XX_IRQ_CALLBACK(_c) { .func = _c }
@@ -2621,6 +2620,7 @@
.ctxt_create = a3xx_drawctxt_create,
.ctxt_save = a3xx_drawctxt_save,
.ctxt_restore = a3xx_drawctxt_restore,
+ .ctxt_draw_workaround = NULL,
.rb_init = a3xx_rb_init,
.irq_control = a3xx_irq_control,
.irq_handler = a3xx_irq_handler,
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index 0d15fb9..76122ae 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -147,6 +147,7 @@
{
struct adreno_context *drawctxt;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
int ret;
drawctxt = kzalloc(sizeof(struct adreno_context), GFP_KERNEL);
@@ -157,6 +158,7 @@
drawctxt->pagetable = pagetable;
drawctxt->bin_base_offset = 0;
drawctxt->id = context->id;
+ rb->timestamp[context->id] = 0;
if (flags & KGSL_CONTEXT_PREAMBLE)
drawctxt->flags |= CTXT_FLAGS_PREAMBLE;
@@ -174,6 +176,12 @@
kgsl_sharedmem_writel(&device->memstore,
KGSL_MEMSTORE_OFFSET(drawctxt->id, ref_wait_ts),
KGSL_INIT_REFTIMESTAMP);
+ kgsl_sharedmem_writel(&device->memstore,
+ KGSL_MEMSTORE_OFFSET(drawctxt->id, ts_cmp_enable), 0);
+ kgsl_sharedmem_writel(&device->memstore,
+ KGSL_MEMSTORE_OFFSET(drawctxt->id, soptimestamp), 0);
+ kgsl_sharedmem_writel(&device->memstore,
+ KGSL_MEMSTORE_OFFSET(drawctxt->id, eoptimestamp), 0);
context->devctxt = drawctxt;
return 0;
@@ -270,8 +278,13 @@
}
/* already current? */
- if (adreno_dev->drawctxt_active == drawctxt)
+ if (adreno_dev->drawctxt_active == drawctxt) {
+ if (adreno_dev->gpudev->ctxt_draw_workaround &&
+ adreno_is_a225(adreno_dev))
+ adreno_dev->gpudev->ctxt_draw_workaround(
+ adreno_dev);
return;
+ }
KGSL_CTXT_INFO(device, "from %p to %p flags %d\n",
adreno_dev->drawctxt_active, drawctxt, flags);
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 3d46221..8bc933a 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -453,7 +453,7 @@
* error checking if needed
*/
total_sizedwords += flags & KGSL_CMD_FLAGS_PMODE ? 4 : 0;
- total_sizedwords += !(flags & KGSL_CMD_FLAGS_NO_TS_CMP) ? 7 : 0;
+ total_sizedwords += context ? 7 : 0;
total_sizedwords += !(flags & KGSL_CMD_FLAGS_NOT_KERNEL_CMD) ? 2 : 0;
if (adreno_is_a3xx(adreno_dev))
@@ -498,9 +498,10 @@
/* always increment the global timestamp. once. */
rb->timestamp[KGSL_MEMSTORE_GLOBAL]++;
- if (context) {
+
+ if (context && !(flags & KGSL_CMD_FLAGS_DUMMY_INTR_CMD)) {
if (context_id == KGSL_MEMSTORE_GLOBAL)
- rb->timestamp[context_id] =
+ rb->timestamp[context->id] =
rb->timestamp[KGSL_MEMSTORE_GLOBAL];
else
rb->timestamp[context_id]++;
@@ -530,7 +531,7 @@
GSL_RB_WRITE(ringcmds, rcmd_gpu,
cp_type3_packet(CP_MEM_WRITE, 2));
GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
- KGSL_MEMSTORE_OFFSET(context->id, soptimestamp)));
+ KGSL_MEMSTORE_OFFSET(context_id, soptimestamp)));
GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
/* end-of-pipeline timestamp */
@@ -538,14 +539,14 @@
cp_type3_packet(CP_EVENT_WRITE, 3));
GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
- KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp)));
+ KGSL_MEMSTORE_OFFSET(context_id, eoptimestamp)));
GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp);
GSL_RB_WRITE(ringcmds, rcmd_gpu,
cp_type3_packet(CP_MEM_WRITE, 2));
GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
- KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
- eoptimestamp)));
+ KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
+ eoptimestamp)));
GSL_RB_WRITE(ringcmds, rcmd_gpu,
rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
} else {
@@ -553,13 +554,11 @@
cp_type3_packet(CP_EVENT_WRITE, 3));
GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS);
GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr +
- KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL,
- eoptimestamp)));
- GSL_RB_WRITE(ringcmds, rcmd_gpu,
- rb->timestamp[KGSL_MEMSTORE_GLOBAL]);
+ KGSL_MEMSTORE_OFFSET(context_id, eoptimestamp)));
+ GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->timestamp[context_id]);
}
- if (!(flags & KGSL_CMD_FLAGS_NO_TS_CMP)) {
+ if (context) {
/* Conditional execution based on memory values */
GSL_RB_WRITE(ringcmds, rcmd_gpu,
cp_type3_packet(CP_COND_EXEC, 4));
@@ -592,6 +591,30 @@
}
void
+adreno_ringbuffer_issuecmds_intr(struct kgsl_device *device,
+ struct kgsl_context *k_ctxt,
+ unsigned int *cmds,
+ int sizedwords)
+{
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
+ struct adreno_context *a_ctxt = NULL;
+
+ if (!k_ctxt)
+ return;
+
+ a_ctxt = k_ctxt->devctxt;
+
+ if (k_ctxt->id == KGSL_CONTEXT_INVALID ||
+ a_ctxt == NULL ||
+ device->state & KGSL_STATE_HUNG)
+ return;
+
+ adreno_ringbuffer_addcmds(rb, a_ctxt, KGSL_CMD_FLAGS_DUMMY_INTR_CMD,
+ cmds, sizedwords);
+}
+
+void
adreno_ringbuffer_issuecmds(struct kgsl_device *device,
unsigned int flags,
unsigned int *cmds,
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index ae2e4c7..6ad85ad 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -108,6 +108,11 @@
unsigned int *cmdaddr,
int sizedwords);
+void adreno_ringbuffer_issuecmds_intr(struct kgsl_device *device,
+ struct kgsl_context *k_ctxt,
+ unsigned int *cmdaddr,
+ int sizedwords);
+
void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb);
void kgsl_cp_intrcallback(struct kgsl_device *device);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index e789733..81de64f 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2523,7 +2523,7 @@
}
status = kgsl_allocate_contiguous(&device->memstore,
- sizeof(struct kgsl_devmemstore));
+ KGSL_MEMSTORE_SIZE);
if (status != 0) {
KGSL_DRV_ERR(device, "kgsl_allocate_contiguous failed %d\n",
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index febb265..b3f2d1e 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -82,7 +82,8 @@
return -ENOSYS;
}
- ptbase = iommu_get_pt_base_addr(domain);
+ ptbase = KGSL_IOMMU_GET_IOMMU_REG(iommu_unit->reg_map.hostptr,
+ iommu_dev->ctx_id, TTBR0);
fsr = KGSL_IOMMU_GET_IOMMU_REG(iommu_unit->reg_map.hostptr,
iommu_dev->ctx_id, FSR);
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 60231f6..3eff40f 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -143,7 +143,7 @@
),
TP_printk(
- "d_name=%s context_id=%u curr_ts=%u timestamp=0x%x timeout=%u",
+ "d_name=%s context_id=%u curr_ts=0x%x timestamp=0x%x timeout=%u",
__get_str(device_name),
__entry->context_id,
__entry->curr_ts,
@@ -175,7 +175,7 @@
),
TP_printk(
- "d_name=%s curr_ts=%u result=%d",
+ "d_name=%s curr_ts=0x%x result=%d",
__get_str(device_name),
__entry->curr_ts,
__entry->result
@@ -386,7 +386,7 @@
TP_printk(
"d_name=%s gpuaddr=0x%08x size=%d type=%d ctx=%u"
- " curr_ts=0x%08x free_ts=0x%08x",
+ " curr_ts=0x%x free_ts=0x%x",
__get_str(device_name),
__entry->gpuaddr,
__entry->size,
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 7fe5498..09ff05d 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -266,6 +266,9 @@
#define MXT_X_INVERT (1 << 1)
#define MXT_Y_INVERT (1 << 2)
+/* Touch suppression */
+#define MXT_TCHSUP_ACTIVE (1 << 0)
+
/* Touchscreen absolute values */
#define MXT_MAX_AREA 0xff
@@ -343,6 +346,8 @@
u8 t9_min_reportid;
u8 t15_max_reportid;
u8 t15_min_reportid;
+ u8 t42_max_reportid;
+ u8 t42_min_reportid;
u8 cfg_version[MXT_CFG_VERSION_LEN];
int cfg_version_idx;
int t38_start_addr;
@@ -887,6 +892,25 @@
data->keyarray_old = data->keyarray_new;
}
+static void mxt_release_all(struct mxt_data *data)
+{
+ int id;
+
+ for (id = 0; id < MXT_MAX_FINGER; id++)
+ if (data->finger[id].status)
+ data->finger[id].status = MXT_RELEASE;
+
+ mxt_input_report(data, 0);
+}
+
+static void mxt_handle_touch_supression(struct mxt_data *data, u8 status)
+{
+ dev_dbg(&data->client->dev, "touch suppression\n");
+ /* release all touches */
+ if (status & MXT_TCHSUP_ACTIVE)
+ mxt_release_all(data);
+}
+
static irqreturn_t mxt_interrupt(int irq, void *dev_id)
{
struct mxt_data *data = dev_id;
@@ -921,6 +945,9 @@
else if (reportid >= data->t15_min_reportid &&
reportid <= data->t15_max_reportid)
mxt_handle_key_array(data, &message);
+ else if (reportid >= data->t42_min_reportid &&
+ reportid <= data->t42_max_reportid)
+ mxt_handle_touch_supression(data, message.message[0]);
else
mxt_dump_message(dev, &message);
} while (reportid != 0xff);
@@ -1283,6 +1310,7 @@
struct mxt_object *t7_object;
struct mxt_object *t9_object;
struct mxt_object *t15_object;
+ struct mxt_object *t42_object;
int error;
/* Store T7 and T9 locally, used in suspend/resume operations */
@@ -1322,6 +1350,16 @@
}
}
+ /* Store T42 min and max report ids */
+ t42_object = mxt_get_object(data, MXT_PROCI_TOUCHSUPPRESSION_T42);
+ if (!t42_object)
+ dev_dbg(&client->dev, "T42 object is not available\n");
+ else {
+ data->t42_max_reportid = t42_object->max_reportid;
+ data->t42_min_reportid = t42_object->max_reportid -
+ t42_object->num_report_ids + 1;
+ }
+
return 0;
}
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 67da5ea..9ed6cca 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -7,7 +7,6 @@
obj-$(CONFIG_MSM_CAMERA) += io/
ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
- EXTRA_CFLAGS += -Idrivers/media/video/msm/io
EXTRA_CFLAGS += -Idrivers/media/video/msm/eeprom
EXTRA_CFLAGS += -Idrivers/media/video/msm/sensors
EXTRA_CFLAGS += -Idrivers/media/video/msm/actuators
diff --git a/drivers/media/video/msm/flash.c b/drivers/media/video/msm/flash.c
index 7c4021d..54c59f8 100644
--- a/drivers/media/video/msm/flash.c
+++ b/drivers/media/video/msm/flash.c
@@ -17,15 +17,16 @@
#include <linux/pwm.h>
#include <linux/pmic8058-pwm.h>
#include <linux/hrtimer.h>
-#include <linux/i2c.h>
#include <linux/export.h>
#include <mach/pmic.h>
#include <mach/camera.h>
#include <mach/gpio.h>
+#include "msm_camera_i2c.h"
struct i2c_client *sx150x_client;
struct timer_list timer_flash;
static struct msm_camera_sensor_info *sensor_data;
+static struct msm_camera_i2c_client i2c_client;
enum msm_cam_flash_stat{
MSM_CAM_FLASH_OFF,
MSM_CAM_FLASH_ON,
@@ -33,47 +34,6 @@
static struct i2c_client *sc628a_client;
-static int32_t flash_i2c_txdata(struct i2c_client *client,
- unsigned char *txdata, int length)
-{
- struct i2c_msg msg[] = {
- {
- .addr = client->addr >> 1,
- .flags = 0,
- .len = length,
- .buf = txdata,
- },
- };
- if (i2c_transfer(client->adapter, msg, 1) < 0) {
- CDBG("flash_i2c_txdata faild 0x%x\n", client->addr >> 1);
- return -EIO;
- }
-
- return 0;
-}
-
-static int32_t flash_i2c_write_b(struct i2c_client *client,
- uint8_t baddr, uint8_t bdata)
-{
- int32_t rc = -EFAULT;
- unsigned char buf[2];
- if (!client)
- return -ENOTSUPP;
-
- memset(buf, 0, sizeof(buf));
- buf[0] = baddr;
- buf[1] = bdata;
-
- rc = flash_i2c_txdata(client, buf, 2);
- if (rc < 0) {
- CDBG("i2c_write_b failed, addr = 0x%x, val = 0x%x!\n",
- baddr, bdata);
- }
- usleep_range(4000, 5000);
-
- return rc;
-}
-
static const struct i2c_device_id sc628a_i2c_id[] = {
{"sc628a", 0},
{ }
@@ -128,8 +88,10 @@
}
tps61310_client = client;
-
- rc = flash_i2c_write_b(tps61310_client, 0x01, 0x00);
+ i2c_client.client = tps61310_client;
+ i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+ rc = msm_camera_i2c_write(&i2c_client, 0x01, 0x00,
+ MSM_CAMERA_I2C_BYTE_DATA);
if (rc < 0) {
tps61310_client = NULL;
goto probe_failure;
@@ -431,10 +393,18 @@
break;
case MSM_CAMERA_LED_OFF:
- if (sc628a_client)
- rc = flash_i2c_write_b(sc628a_client, 0x02, 0x00);
- if (tps61310_client)
- rc = flash_i2c_write_b(tps61310_client, 0x01, 0x00);
+ if (sc628a_client) {
+ i2c_client.client = sc628a_client;
+ i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+ rc = msm_camera_i2c_write(&i2c_client, 0x02, 0x00,
+ MSM_CAMERA_I2C_BYTE_DATA);
+ }
+ if (tps61310_client) {
+ i2c_client.client = tps61310_client;
+ i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+ rc = msm_camera_i2c_write(&i2c_client, 0x01, 0x00,
+ MSM_CAMERA_I2C_BYTE_DATA);
+ }
gpio_set_value_cansleep(external->led_en, 0);
gpio_set_value_cansleep(external->led_flash_en, 0);
break;
@@ -443,20 +413,36 @@
gpio_set_value_cansleep(external->led_en, 1);
gpio_set_value_cansleep(external->led_flash_en, 1);
usleep_range(2000, 3000);
- if (sc628a_client)
- rc = flash_i2c_write_b(sc628a_client, 0x02, 0x06);
- if (tps61310_client)
- rc = flash_i2c_write_b(tps61310_client, 0x01, 0x86);
+ if (sc628a_client) {
+ i2c_client.client = sc628a_client;
+ i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+ rc = msm_camera_i2c_write(&i2c_client, 0x02, 0x06,
+ MSM_CAMERA_I2C_BYTE_DATA);
+ }
+ if (tps61310_client) {
+ i2c_client.client = tps61310_client;
+ i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+ rc = msm_camera_i2c_write(&i2c_client, 0x01, 0x86,
+ MSM_CAMERA_I2C_BYTE_DATA);
+ }
break;
case MSM_CAMERA_LED_HIGH:
gpio_set_value_cansleep(external->led_en, 1);
gpio_set_value_cansleep(external->led_flash_en, 1);
usleep_range(2000, 3000);
- if (sc628a_client)
- rc = flash_i2c_write_b(sc628a_client, 0x02, 0x49);
- if (tps61310_client)
- rc = flash_i2c_write_b(tps61310_client, 0x01, 0x8B);
+ if (sc628a_client) {
+ i2c_client.client = sc628a_client;
+ i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+ rc = msm_camera_i2c_write(&i2c_client, 0x02, 0x49,
+ MSM_CAMERA_I2C_BYTE_DATA);
+ }
+ if (tps61310_client) {
+ i2c_client.client = tps61310_client;
+ i2c_client.addr_type = MSM_CAMERA_I2C_BYTE_ADDR;
+ rc = msm_camera_i2c_write(&i2c_client, 0x01, 0x8B,
+ MSM_CAMERA_I2C_BYTE_DATA);
+ }
break;
default:
diff --git a/drivers/media/video/msm/io/Makefile b/drivers/media/video/msm/io/Makefile
index 64df7fb..611eecd 100644
--- a/drivers/media/video/msm/io/Makefile
+++ b/drivers/media/video/msm/io/Makefile
@@ -1,9 +1,9 @@
GCC_VERSION := $(shell $(CONFIG_SHELL) $(PWD)/scripts/gcc-version.sh $(CROSS_COMPILE)gcc)
-obj-$(CONFIG_MSM_CAMERA) += msm_camera_io_util.o
EXTRA_CFLAGS += -Idrivers/media/video/msm
+obj-$(CONFIG_MSM_CAMERA) += msm_camera_io_util.o msm_camera_i2c.o
ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
- obj-$(CONFIG_MSM_CAMERA) += msm_camera_i2c.o msm_camera_i2c_mux.o
+ obj-$(CONFIG_MSM_CAMERA) += msm_camera_i2c_mux.o
obj-$(CONFIG_ARCH_MSM7X27A) += msm_io_7x27a_v4l2.o
obj-$(CONFIG_ARCH_MSM8X60) += msm_io_vfe31_v4l2.o
obj-$(CONFIG_ARCH_MSM7X30) += msm_io_vfe31_v4l2.o
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 09511b1..c3c09d4 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -108,6 +108,25 @@
return rc;
}
+static int msm_camera_v4l2_private_s_ctrl(struct file *f, void *pctx,
+ struct msm_camera_v4l2_ioctl_t *ioctl_ptr)
+{
+ int rc = -EINVAL;
+ struct msm_cam_v4l2_device *pcam = video_drvdata(f);
+ struct msm_cam_v4l2_dev_inst *pcam_inst;
+ pcam_inst = container_of(f->private_data,
+ struct msm_cam_v4l2_dev_inst, eventHandle);
+ WARN_ON(pctx != f->private_data);
+ mutex_lock(&pcam->vid_lock);
+ switch (ioctl_ptr->id) {
+ case MSM_V4L2_PID_CTRL_CMD:
+ rc = msm_server_proc_ctrl_cmd(pcam, ioctl_ptr, 1);
+ break;
+ }
+ mutex_unlock(&pcam->vid_lock);
+ return rc;
+}
+
static int msm_camera_v4l2_s_ctrl(struct file *f, void *pctx,
struct v4l2_control *ctrl)
{
@@ -127,17 +146,6 @@
__func__, pcam_inst, pcam_inst->my_index);
pcam_inst->is_mem_map_inst = 1;
break;
- case MSM_V4L2_PID_MMAP_ENTRY:
- if (copy_from_user(&pcam_inst->mem_map,
- (void *)ctrl->value,
- sizeof(struct msm_mem_map_info))) {
- rc = -EFAULT;
- } else
- D("%s:mmap entry:cookie=0x%x,mem_type=%d,len=%d\n",
- __func__, pcam_inst->mem_map.cookie,
- pcam_inst->mem_map.mem_type,
- pcam_inst->mem_map.length);
- break;
default:
if (ctrl->id == MSM_V4L2_PID_CAM_MODE)
pcam->op_mode = ctrl->value;
@@ -685,6 +693,22 @@
return rc;
}
+static long msm_camera_v4l2_private_ioctl(struct file *file, void *fh,
+ bool valid_prio, int cmd,
+ void *arg)
+{
+ int rc = -EINVAL;
+ struct msm_camera_v4l2_ioctl_t *ioctl_ptr = arg;
+ D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
+
+ switch (cmd) {
+ case MSM_CAM_V4L2_IOCTL_PRIVATE_S_CTRL:
+ rc = msm_camera_v4l2_private_s_ctrl(file, fh, ioctl_ptr);
+ break;
+ }
+ return rc;
+}
+
/* v4l2_ioctl_ops */
static const struct v4l2_ioctl_ops g_msm_ioctl_ops = {
.vidioc_querycap = msm_camera_v4l2_querycap,
@@ -724,6 +748,7 @@
/* event subscribe/unsubscribe */
.vidioc_subscribe_event = msm_camera_v4l2_subscribe_event,
.vidioc_unsubscribe_event = msm_camera_v4l2_unsubscribe_event,
+ .vidioc_default = msm_camera_v4l2_private_ioctl,
};
/* v4l2_file_operations */
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index caa2d32..42330b4 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -39,11 +39,16 @@
#define MSM_V4L2_DIMENSION_SIZE 96
#define MAX_DEV_NAME_LEN 50
-#define ERR_USER_COPY(to) pr_debug("%s(%d): copy %s user\n", \
+#define ERR_USER_COPY(to) pr_err("%s(%d): copy %s user\n", \
__func__, __LINE__, ((to) ? "to" : "from"))
#define ERR_COPY_FROM_USER() ERR_USER_COPY(0)
#define ERR_COPY_TO_USER() ERR_USER_COPY(1)
+#define COPY_FROM_USER(error, dest, src, size) \
+ (error = (copy_from_user(dest, src, size) ? -EFAULT : 0))
+#define COPY_TO_USER(error, dest, src, size) \
+ (error = (copy_to_user(dest, src, size) ? -EFAULT : 0))
+
#define MSM_CSIPHY_DRV_NAME "msm_csiphy"
#define MSM_CSID_DRV_NAME "msm_csid"
#define MSM_CSIC_DRV_NAME "msm_csic"
@@ -102,6 +107,7 @@
qcmd = list_first_entry(&__q->list, \
struct msm_queue_cmd, member); \
list_del_init(&qcmd->member); \
+ kfree(qcmd->command); \
free_qcmd(qcmd); \
}; \
spin_unlock_irqrestore(&__q->lock, flags); \
@@ -147,7 +153,6 @@
NOTIFY_VFE_MSG_COMP_STATS, /* arg = struct msm_stats_buf */
NOTIFY_VFE_BUF_EVT, /* arg = struct msm_vfe_resp */
NOTIFY_ISPIF_STREAM, /* arg = enable parameter for s_stream */
- NOTIFY_VPE_MSG_EVT,
NOTIFY_PCLK_CHANGE, /* arg = pclk */
NOTIFY_CSIPHY_CFG, /* arg = msm_camera_csiphy_params */
NOTIFY_CSID_CFG, /* arg = msm_camera_csid_params */
@@ -206,6 +211,7 @@
struct msm_pp_frame src_frame;
struct msm_pp_frame dest_frame;
struct msm_mctl_pp_frame_cmd pp_frame_cmd;
+ struct msm_cam_media_controller *p_mctl;
};
struct msm_mctl_pp_ctrl {
@@ -587,6 +593,10 @@
int msm_cam_server_close_mctl_session(struct msm_cam_v4l2_device *pcam);
long msm_v4l2_evt_notify(struct msm_cam_media_controller *mctl,
unsigned int cmd, unsigned long evt);
+int msm_mctl_pp_get_vpe_buf_info(struct msm_mctl_pp_frame_info *zoom);
+void msm_queue_init(struct msm_device_queue *queue, const char *name);
+void msm_enqueue(struct msm_device_queue *queue, struct list_head *entry);
+void msm_drain_eventq(struct msm_device_queue *queue);
#endif /* __KERNEL__ */
#endif /* _MSM_H */
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 848beda..fab0095 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -661,6 +661,8 @@
case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC:
case CMD_AXI_CFG_PRIM|CMD_AXI_CFG_SEC_ALL_CHNLS:
case CMD_AXI_CFG_PRIM_ALL_CHNLS|CMD_AXI_CFG_SEC:
+ case CMD_AXI_START:
+ case CMD_AXI_STOP:
/* Dont need to pass buffer information.
* subdev will get the buffer from media
* controller free queue.
@@ -742,13 +744,6 @@
D("%s: cmd %d\n", __func__, _IOC_NR(cmd));
switch (cmd) {
- case MSM_CAM_IOCTL_PICT_PP_DONE:
- /* Release the preview of snapshot frame
- * that was grabbed.
- */
- /*rc = msm_pp_release(pmsm->sync, arg);*/
- break;
-
case MSM_CAM_IOCTL_CONFIG_VFE:
/* Coming from config thread for update */
rc = msm_config_vfe(sd, pmctl, argp);
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index e6523cd..ed6c493 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -767,8 +767,10 @@
VIDIOC_MSM_CSIPHY_RELEASE, NULL);
}
- if (p_mctl->act_sdev)
+ if (p_mctl->act_sdev) {
v4l2_subdev_call(p_mctl->act_sdev, core, s_power, 0);
+ p_mctl->act_sdev = NULL;
+ }
v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 0);
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 1088a54..eade6f1 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -454,7 +454,7 @@
image_mode, fbuf,
&frame_id, 1);
D("%s mctl node buf done %d\n", __func__, 0);
- return -EINVAL;
+ return rc;
} else {
pr_err("%s Invalid instance, dropping buffer\n",
__func__);
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index f4c04bb..844a3ff 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -36,18 +36,6 @@
#define D(fmt, args...) do {} while (0)
#endif
-
-static int msm_mctl_pp_vpe_ioctl(struct v4l2_subdev *vpe_sd,
- struct msm_mctl_pp_cmd *cmd, void *data)
-{
- int rc = 0;
- struct msm_mctl_pp_params parm;
- parm.cmd = cmd;
- parm.data = data;
- rc = v4l2_subdev_call(vpe_sd, core, ioctl, VIDIOC_MSM_VPE_CFG, &parm);
- return rc;
-}
-
static int msm_mctl_pp_buf_divert(
struct msm_cam_media_controller *pmctl,
struct msm_cam_v4l2_dev_inst *pcam_inst,
@@ -384,244 +372,6 @@
return -EINVAL;
}
-int msm_mctl_pp_proc_vpe_cmd(
- struct msm_cam_media_controller *p_mctl,
- struct msm_mctl_pp_cmd *pp_cmd)
-{
- int rc = 0, idx;
- void __user *argp = (void __user *)pp_cmd->value;
- struct msm_cam_v4l2_dev_inst *pcam_inst;
-
- switch (pp_cmd->id) {
- case VPE_CMD_INIT:
- case VPE_CMD_DEINIT:
- rc = msm_mctl_pp_vpe_ioctl(
- p_mctl->vpe_sdev, pp_cmd, NULL);
- break;
- case VPE_CMD_DISABLE:
- case VPE_CMD_RESET:
- rc = msm_mctl_pp_vpe_ioctl(
- p_mctl->vpe_sdev, pp_cmd, NULL);
- break;
- case VPE_CMD_ENABLE: {
- struct msm_vpe_clock_rate clk_rate;
- if (sizeof(struct msm_vpe_clock_rate) !=
- pp_cmd->length) {
- pr_err("%s: vpe cmd size mismatch "
- "(id=%d, length = %d, expect size = %d",
- __func__, pp_cmd->id, pp_cmd->length,
- sizeof(struct msm_vpe_clock_rate));
- rc = -EINVAL;
- break;
- }
- if (copy_from_user(&clk_rate, pp_cmd->value,
- sizeof(struct msm_vpe_clock_rate))) {
- pr_err("%s:clk_rate copy failed", __func__);
- return -EFAULT;
- }
- pp_cmd->value = (void *)&clk_rate;
- rc = msm_mctl_pp_vpe_ioctl(
- p_mctl->vpe_sdev, pp_cmd, NULL);
- pp_cmd->value = argp;
- break;
- }
- case VPE_CMD_FLUSH: {
- struct msm_vpe_flush_frame_buffer flush_buf;
- if (sizeof(struct msm_vpe_flush_frame_buffer) !=
- pp_cmd->length) {
- D("%s: size mismatch(id=%d, len = %d, expected = %d",
- __func__, pp_cmd->id, pp_cmd->length,
- sizeof(struct msm_vpe_flush_frame_buffer));
- rc = -EINVAL;
- break;
- }
- if (copy_from_user(
- &flush_buf, pp_cmd->value, sizeof(flush_buf)))
- return -EFAULT;
- pp_cmd->value = (void *)&flush_buf;
- rc = msm_mctl_pp_vpe_ioctl(
- p_mctl->vpe_sdev, pp_cmd, NULL);
- if (rc == 0) {
- if (copy_to_user((void *)argp,
- &flush_buf,
- sizeof(flush_buf))) {
- ERR_COPY_TO_USER();
- rc = -EFAULT;
- }
- pp_cmd->value = argp;
- }
- }
- break;
- case VPE_CMD_OPERATION_MODE_CFG: {
- struct msm_vpe_op_mode_cfg op_mode_cfg;
- if (sizeof(struct msm_vpe_op_mode_cfg) !=
- pp_cmd->length) {
- D("%s: size mismatch(id=%d, len = %d, expected = %d",
- __func__, pp_cmd->id, pp_cmd->length,
- sizeof(struct msm_vpe_op_mode_cfg));
- rc = -EINVAL;
- break;
- }
- if (copy_from_user(&op_mode_cfg,
- pp_cmd->value,
- sizeof(op_mode_cfg)))
- return -EFAULT;
- pp_cmd->value = (void *)&op_mode_cfg;
- rc = msm_mctl_pp_vpe_ioctl(
- p_mctl->vpe_sdev, pp_cmd, NULL);
- break;
- }
- case VPE_CMD_INPUT_PLANE_CFG: {
- struct msm_vpe_input_plane_cfg input_cfg;
- if (sizeof(struct msm_vpe_input_plane_cfg) !=
- pp_cmd->length) {
- D("%s: mismatch(id=%d, len = %d, expected = %d",
- __func__, pp_cmd->id, pp_cmd->length,
- sizeof(struct msm_vpe_input_plane_cfg));
- rc = -EINVAL;
- break;
- }
- if (copy_from_user(
- &input_cfg, pp_cmd->value, sizeof(input_cfg)))
- return -EFAULT;
- pp_cmd->value = (void *)&input_cfg;
- rc = msm_mctl_pp_vpe_ioctl(
- p_mctl->vpe_sdev, pp_cmd, NULL);
- break;
- }
- case VPE_CMD_OUTPUT_PLANE_CFG: {
- struct msm_vpe_output_plane_cfg output_cfg;
- if (sizeof(struct msm_vpe_output_plane_cfg) !=
- pp_cmd->length) {
- D("%s: size mismatch(id=%d, len = %d, expected = %d",
- __func__, pp_cmd->id, pp_cmd->length,
- sizeof(struct msm_vpe_output_plane_cfg));
- rc = -EINVAL;
- break;
- }
- if (copy_from_user(&output_cfg, pp_cmd->value,
- sizeof(output_cfg))) {
- D("%s: cannot copy pp_cmd->value, size=%d",
- __func__, pp_cmd->length);
- return -EFAULT;
- }
- pp_cmd->value = (void *)&output_cfg;
- rc = msm_mctl_pp_vpe_ioctl(
- p_mctl->vpe_sdev, pp_cmd, NULL);
- break;
- }
- case VPE_CMD_INPUT_PLANE_UPDATE: {
- struct msm_vpe_input_plane_update_cfg input_update_cfg;
- if (sizeof(struct msm_vpe_input_plane_update_cfg) !=
- pp_cmd->length) {
- D("%s: size mismatch(id=%d, len = %d, expected = %d",
- __func__, pp_cmd->id, pp_cmd->length,
- sizeof(struct msm_vpe_input_plane_update_cfg));
- rc = -EINVAL;
- break;
- }
- if (copy_from_user(&input_update_cfg, pp_cmd->value,
- sizeof(input_update_cfg)))
- return -EFAULT;
- pp_cmd->value = (void *)&input_update_cfg;
- rc = msm_mctl_pp_vpe_ioctl(
- p_mctl->vpe_sdev, pp_cmd, NULL);
- break;
- }
- case VPE_CMD_SCALE_CFG_TYPE: {
- struct msm_vpe_scaler_cfg scaler_cfg;
- if (sizeof(struct msm_vpe_scaler_cfg) !=
- pp_cmd->length) {
- D("%s: size mismatch(id=%d, len = %d, expected = %d",
- __func__, pp_cmd->id, pp_cmd->length,
- sizeof(struct msm_vpe_scaler_cfg));
- rc = -EINVAL;
- break;
- }
- if (copy_from_user(&scaler_cfg, pp_cmd->value,
- sizeof(scaler_cfg)))
- return -EFAULT;
- pp_cmd->value = (void *)&scaler_cfg;
- rc = msm_mctl_pp_vpe_ioctl(
- p_mctl->vpe_sdev, pp_cmd, NULL);
- break;
- }
- case VPE_CMD_ZOOM: {
- struct msm_mctl_pp_frame_info *zoom;
- zoom = kmalloc(sizeof(struct msm_mctl_pp_frame_info),
- GFP_ATOMIC);
- if (!zoom) {
- rc = -ENOMEM;
- break;
- }
- if (sizeof(zoom->pp_frame_cmd) != pp_cmd->length) {
- D("%s: size mismatch(id=%d, len = %d, expected = %d",
- __func__, pp_cmd->id, pp_cmd->length,
- sizeof(zoom->pp_frame_cmd));
- rc = -EINVAL;
- kfree(zoom);
- break;
- }
- if (copy_from_user(&zoom->pp_frame_cmd, pp_cmd->value,
- sizeof(zoom->pp_frame_cmd))) {
- kfree(zoom);
- return -EFAULT;
- }
- 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,
- zoom->pp_frame_cmd.vpe_output_action,
- zoom->pp_frame_cmd.path);
- 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__);
- kfree(zoom);
- return idx;
- }
- pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
- if (!pcam_inst) {
- pr_err("%s Invalid instance, returning\n", __func__);
- kfree(zoom);
- return -EINVAL;
- }
- zoom->user_cmd = pp_cmd->id;
- rc = msm_mctl_pp_get_phy_addr(pcam_inst,
- zoom->pp_frame_cmd.src_buf_handle, &zoom->src_frame);
- if (rc) {
- kfree(zoom);
- break;
- }
- rc = msm_mctl_pp_get_phy_addr(pcam_inst,
- zoom->pp_frame_cmd.dest_buf_handle, &zoom->dest_frame);
- if (rc) {
- kfree(zoom);
- break;
- }
- 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) {
- kfree(zoom);
- break;
- }
- rc = msm_mctl_pp_vpe_ioctl(
- p_mctl->vpe_sdev, pp_cmd, (void *)zoom);
- if (rc) {
- kfree(zoom);
- break;
- }
- break;
- }
- default:
- rc = -1;
- break;
- }
- return rc;
-}
-
static int msm_mctl_pp_path_to_img_mode(int path)
{
switch (path) {
@@ -717,9 +467,6 @@
return -EFAULT;
switch (pp_cmd.type) {
- case MSM_PP_CMD_TYPE_VPE:
- rc = msm_mctl_pp_proc_vpe_cmd(p_mctl, &pp_cmd.cmd);
- break;
case MSM_PP_CMD_TYPE_MCTL:
rc = msm_mctl_pp_proc_cmd(p_mctl, &pp_cmd.cmd);
break;
@@ -739,71 +486,6 @@
return rc;
}
-int msm_mctl_pp_notify(struct msm_cam_media_controller *p_mctl,
- struct msm_mctl_pp_frame_info *pp_frame_info)
-{
- struct msm_mctl_pp_frame_cmd *pp_frame_cmd;
- pp_frame_cmd = &pp_frame_info->pp_frame_cmd;
-
- D("%s: msm_cam_evt_divert_frame=%d",
- __func__, sizeof(struct msm_mctl_pp_event_info));
- if ((MSM_MCTL_PP_VPE_FRAME_TO_APP &
- pp_frame_cmd->vpe_output_action)) {
- struct msm_free_buf done_frame;
- int img_mode =
- msm_mctl_pp_path_to_img_mode(
- pp_frame_cmd->path);
- if (img_mode < 0) {
- pr_err("%s Invalid image mode\n", __func__);
- return img_mode;
- }
- done_frame.ch_paddr[0] =
- pp_frame_info->dest_frame.sp.phy_addr;
- done_frame.vb =
- pp_frame_info->dest_frame.handle;
- msm_mctl_buf_done_pp(
- p_mctl, img_mode, &done_frame, 0, 0);
- D("%s: vpe done to app, vb=0x%x, path=%d, phy=0x%x",
- __func__, done_frame.vb,
- pp_frame_cmd->path, done_frame.ch_paddr[0]);
- }
- if ((MSM_MCTL_PP_VPE_FRAME_ACK &
- pp_frame_cmd->vpe_output_action)) {
- struct v4l2_event v4l2_evt;
- struct msm_mctl_pp_event_info *pp_event_info;
- struct msm_isp_event_ctrl *isp_event;
- isp_event = kzalloc(sizeof(struct msm_isp_event_ctrl),
- GFP_ATOMIC);
- if (!isp_event) {
- pr_err("%s Insufficient memory.", __func__);
- return -ENOMEM;
- }
- memset(&v4l2_evt, 0, sizeof(v4l2_evt));
- *((uint32_t *)v4l2_evt.u.data) = (uint32_t)isp_event;
-
- /* Get hold of pp event info struct inside event ctrl.*/
- pp_event_info = &(isp_event->isp_data.pp_event_info);
-
- 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;
- pp_event_info->ack.cookie = pp_frame_cmd->cookie;
- v4l2_evt.id = 0;
- v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
- MSM_CAM_RESP_MCTL_PP_EVENT;
-
- v4l2_event_queue(
- p_mctl->config_device->
- config_stat_event_queue.pvdev,
- &v4l2_evt);
- D("%s: ack to daemon, cookie=0x%x, event = 0x%x",
- __func__, pp_frame_info->pp_frame_cmd.cookie,
- v4l2_evt.type);
- }
- kfree(pp_frame_info); /* free mem */
- return 0;
-}
-
int msm_mctl_pp_reserve_free_frame(
struct msm_cam_media_controller *p_mctl,
void __user *arg)
@@ -1027,3 +709,54 @@
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_vfe31_v4l2.c b/drivers/media/video/msm/msm_vfe31_v4l2.c
index a010817..7a2670c 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.c
@@ -367,7 +367,7 @@
static void vfe31_stop(void)
{
-
+ uint8_t axiBusyFlag = true;
unsigned long flags;
atomic_set(&vfe31_ctrl->vstate, 0);
@@ -397,52 +397,6 @@
* at any time. stop camif immediately. */
msm_camera_io_w_mb(CAMIF_COMMAND_STOP_IMMEDIATELY,
vfe31_ctrl->vfebase + VFE_CAMIF_COMMAND);
-}
-
-void axi_start(void)
-{
- switch (vfe31_ctrl->operation_mode) {
- case VFE_OUTPUTS_PREVIEW:
- case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
- if (vfe31_ctrl->outpath.output_mode &
- VFE31_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
- } else if (vfe31_ctrl->outpath.output_mode &
- VFE31_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
- msm_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
- msm_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch2]);
- }
- break;
- default:
- if (vfe31_ctrl->outpath.output_mode &
- VFE31_OUTPUT_MODE_SECONDARY) {
- msm_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
- } else if (vfe31_ctrl->outpath.output_mode &
- VFE31_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
- msm_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
- msm_camera_io_w(1, vfe31_ctrl->vfebase +
- vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch2]);
- }
- break;
- }
-}
-
-void axi_stop(void)
-{
- uint8_t axiBusyFlag = true;
/* axi halt command. */
msm_camera_io_w(AXI_HALT,
vfe31_ctrl->vfebase + VFE_AXI_CMD);
@@ -999,6 +953,43 @@
}
msm_camera_io_w(irq_comp_mask, vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ switch (vfe31_ctrl->operation_mode) {
+ case VFE_OUTPUTS_PREVIEW:
+ case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
+ if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_PRIMARY) {
+ msm_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+ } else if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ msm_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+ msm_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch2]);
+ }
+ break;
+ default:
+ if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_SECONDARY) {
+ msm_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
+ } else if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ msm_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch1]);
+ msm_camera_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out1.ch2]);
+ }
+ break;
+ }
msm_camio_bus_scale_cfg(
pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
vfe31_start_common();
@@ -3582,11 +3573,11 @@
break;
case CMD_AXI_START:
- axi_start();
+ /* No need to decouple AXI/VFE for VFE3.1*/
break;
case CMD_AXI_STOP:
- axi_stop();
+ /* No need to decouple AXI/VFE for VFE3.1*/
break;
default:
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 98c1ca0..3611656 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -30,25 +30,24 @@
atomic_t irq_cnt;
#define VFE32_AXI_OFFSET 0x0050
-#define vfe32_get_ch_ping_addr(chn) \
- (msm_camera_io_r(vfe32_ctrl->vfebase + 0x0050 + 0x18 * (chn)))
-#define vfe32_get_ch_pong_addr(chn) \
- (msm_camera_io_r(vfe32_ctrl->vfebase + 0x0050 + 0x18 * (chn) + 4))
-#define vfe32_get_ch_addr(ping_pong, chn) \
- (((ping_pong) & (1 << (chn))) == 0 ? \
- vfe32_get_ch_pong_addr(chn) : vfe32_get_ch_ping_addr(chn))
+#define vfe32_get_ch_ping_addr(base, chn) \
+ (msm_camera_io_r((base) + 0x0050 + 0x18 * (chn)))
+#define vfe32_get_ch_pong_addr(base, chn) \
+ (msm_camera_io_r((base) + 0x0050 + 0x18 * (chn) + 4))
+#define vfe32_get_ch_addr(ping_pong, base, chn) \
+ ((((ping_pong) & (1 << (chn))) == 0) ? \
+ (vfe32_get_ch_pong_addr((base), chn)) : \
+ (vfe32_get_ch_ping_addr((base), chn)))
-#define vfe32_put_ch_ping_addr(chn, addr) \
- (msm_camera_io_w((addr), vfe32_ctrl->vfebase + 0x0050 + 0x18 * (chn)))
-#define vfe32_put_ch_pong_addr(chn, addr) \
- (msm_camera_io_w((addr), \
- vfe32_ctrl->vfebase + 0x0050 + 0x18 * (chn) + 4))
-#define vfe32_put_ch_addr(ping_pong, chn, addr) \
+#define vfe32_put_ch_ping_addr(base, chn, addr) \
+ (msm_camera_io_w((addr), (base) + 0x0050 + 0x18 * (chn)))
+#define vfe32_put_ch_pong_addr(base, chn, addr) \
+ (msm_camera_io_w((addr), (base) + 0x0050 + 0x18 * (chn) + 4))
+#define vfe32_put_ch_addr(ping_pong, base, chn, addr) \
(((ping_pong) & (1 << (chn))) == 0 ? \
- vfe32_put_ch_pong_addr((chn), (addr)) : \
- vfe32_put_ch_ping_addr((chn), (addr)))
+ vfe32_put_ch_pong_addr((base), (chn), (addr)) : \
+ vfe32_put_ch_ping_addr((base), (chn), (addr)))
-static struct vfe32_ctrl_type *vfe32_ctrl;
static uint32_t vfe_clk_rate;
struct vfe32_isr_queue_cmd {
@@ -357,112 +356,117 @@
"DEMOSAICV3_UPDATE",
};
-static void vfe32_stop(void)
+static void vfe32_stop(struct vfe32_ctrl_type *vfe32_ctrl)
{
unsigned long flags;
- atomic_set(&vfe32_ctrl->vstate, 0);
+ atomic_set(&vfe32_ctrl->share_ctrl->vstate, 0);
/* for reset hw modules, and send msg when reset_irq comes.*/
- spin_lock_irqsave(&vfe32_ctrl->stop_flag_lock, flags);
- vfe32_ctrl->stop_ack_pending = TRUE;
- spin_unlock_irqrestore(&vfe32_ctrl->stop_flag_lock, flags);
+ spin_lock_irqsave(&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
+ vfe32_ctrl->share_ctrl->stop_ack_pending = TRUE;
+ spin_unlock_irqrestore(&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
/* disable all interrupts. */
msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
- vfe32_ctrl->vfebase + VFE_IRQ_MASK_0);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
- vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
/* clear all pending interrupts*/
msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
- vfe32_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
- vfe32_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+ vfe32_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,
- vfe32_ctrl->vfebase + VFE_IRQ_CMD);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_CMD);
/* 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,
- vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
-
+ vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
}
-static void vfe32_subdev_notify(int id, int path)
+static void vfe32_subdev_notify(int id, int path,
+ struct v4l2_subdev *sd, struct vfe_share_ctrl_t *share_ctrl)
{
struct msm_vfe_resp rp;
unsigned long flags = 0;
- spin_lock_irqsave(&vfe32_ctrl->sd_notify_lock, flags);
+ spin_lock_irqsave(&share_ctrl->sd_notify_lock, flags);
CDBG("vfe32_subdev_notify : msgId = %d\n", id);
memset(&rp, 0, sizeof(struct msm_vfe_resp));
rp.evt_msg.type = MSM_CAMERA_MSG;
rp.evt_msg.msg_id = path;
rp.type = id;
- v4l2_subdev_notify(&vfe32_ctrl->subdev, NOTIFY_VFE_BUF_EVT, &rp);
- spin_unlock_irqrestore(&vfe32_ctrl->sd_notify_lock, flags);
+ v4l2_subdev_notify(sd, NOTIFY_VFE_BUF_EVT, &rp);
+ spin_unlock_irqrestore(&share_ctrl->sd_notify_lock, flags);
}
-static int vfe32_config_axi(int mode, uint32_t *ao)
+static int vfe32_config_axi(
+ struct axi_ctrl_t *axi_ctrl, int mode, uint32_t *ao)
{
uint32_t *ch_info;
uint32_t *axi_cfg = ao+V32_AXI_BUS_FMT_OFF;
/* Update the corresponding write masters for each output*/
ch_info = axi_cfg + V32_AXI_CFG_LEN;
- vfe32_ctrl->outpath.out0.ch0 = 0x0000FFFF & *ch_info;
- vfe32_ctrl->outpath.out0.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
- vfe32_ctrl->outpath.out0.ch2 = 0x0000FFFF & *ch_info++;
- vfe32_ctrl->outpath.out1.ch0 = 0x0000FFFF & *ch_info;
- vfe32_ctrl->outpath.out1.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
- vfe32_ctrl->outpath.out1.ch2 = 0x0000FFFF & *ch_info++;
- vfe32_ctrl->outpath.out2.ch0 = 0x0000FFFF & *ch_info;
- vfe32_ctrl->outpath.out2.ch1 = 0x0000FFFF & (*ch_info++ >> 16);
- vfe32_ctrl->outpath.out2.ch2 = 0x0000FFFF & *ch_info++;
+ 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.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.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++;
switch (mode) {
case OUTPUT_PRIM:
- vfe32_ctrl->outpath.output_mode =
+ axi_ctrl->share_ctrl->outpath.output_mode =
VFE32_OUTPUT_MODE_PRIMARY;
break;
case OUTPUT_PRIM_ALL_CHNLS:
- vfe32_ctrl->outpath.output_mode =
+ axi_ctrl->share_ctrl->outpath.output_mode =
VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
break;
case OUTPUT_PRIM|OUTPUT_SEC:
- vfe32_ctrl->outpath.output_mode =
+ axi_ctrl->share_ctrl->outpath.output_mode =
VFE32_OUTPUT_MODE_PRIMARY;
- vfe32_ctrl->outpath.output_mode |=
+ axi_ctrl->share_ctrl->outpath.output_mode |=
VFE32_OUTPUT_MODE_SECONDARY;
break;
case OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS:
- vfe32_ctrl->outpath.output_mode =
+ axi_ctrl->share_ctrl->outpath.output_mode =
VFE32_OUTPUT_MODE_PRIMARY;
- vfe32_ctrl->outpath.output_mode |=
+ axi_ctrl->share_ctrl->outpath.output_mode |=
VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS;
break;
case OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC:
- vfe32_ctrl->outpath.output_mode =
+ axi_ctrl->share_ctrl->outpath.output_mode =
VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS;
- vfe32_ctrl->outpath.output_mode |=
+ axi_ctrl->share_ctrl->outpath.output_mode |=
VFE32_OUTPUT_MODE_SECONDARY;
break;
default:
pr_err("%s Invalid AXI mode %d ", __func__, mode);
return -EINVAL;
}
- msm_camera_io_w(*ao, vfe32_ctrl->vfebase +
+ msm_camera_io_w(*ao, axi_ctrl->share_ctrl->vfebase +
VFE_BUS_IO_FORMAT_CFG);
- msm_camera_io_memcpy(vfe32_ctrl->vfebase +
+ msm_camera_io_memcpy(axi_ctrl->share_ctrl->vfebase +
vfe32_cmd[VFE_CMD_AXI_OUT_CFG].offset, axi_cfg,
vfe32_cmd[VFE_CMD_AXI_OUT_CFG].length - V32_AXI_CH_INF_LEN
- V32_AXI_BUS_FMT_LEN);
return 0;
}
-static void vfe32_reset_internal_variables(void)
+static void vfe32_reset_internal_variables(
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
unsigned long flags;
vfe32_ctrl->vfeImaskCompositePacked = 0;
@@ -470,9 +474,9 @@
vfe32_ctrl->start_ack_pending = FALSE;
atomic_set(&irq_cnt, 0);
- spin_lock_irqsave(&vfe32_ctrl->stop_flag_lock, flags);
- vfe32_ctrl->stop_ack_pending = FALSE;
- spin_unlock_irqrestore(&vfe32_ctrl->stop_flag_lock, flags);
+ spin_lock_irqsave(&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
+ vfe32_ctrl->share_ctrl->stop_ack_pending = FALSE;
+ spin_unlock_irqrestore(&vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
vfe32_ctrl->reset_ack_pending = FALSE;
@@ -481,17 +485,17 @@
spin_unlock_irqrestore(&vfe32_ctrl->update_ack_lock, flags);
vfe32_ctrl->recording_state = VFE_STATE_IDLE;
- vfe32_ctrl->liveshot_state = VFE_STATE_IDLE;
+ vfe32_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
- atomic_set(&vfe32_ctrl->vstate, 0);
+ atomic_set(&vfe32_ctrl->share_ctrl->vstate, 0);
/* 0 for continuous mode, 1 for snapshot mode */
- vfe32_ctrl->operation_mode = 0;
- vfe32_ctrl->outpath.output_mode = 0;
- vfe32_ctrl->vfe_capture_count = 0;
+ vfe32_ctrl->share_ctrl->operation_mode = 0;
+ vfe32_ctrl->share_ctrl->outpath.output_mode = 0;
+ vfe32_ctrl->share_ctrl->vfe_capture_count = 0;
/* this is unsigned 32 bit integer. */
- vfe32_ctrl->vfeFrameId = 0;
+ vfe32_ctrl->share_ctrl->vfeFrameId = 0;
/* Stats control variables. */
memset(&(vfe32_ctrl->afStatsControl), 0,
sizeof(struct vfe_stats_control));
@@ -516,30 +520,30 @@
vfe32_ctrl->snapshot_frame_cnt = 0;
}
-static void vfe32_reset(void)
+static void vfe32_reset(struct vfe32_ctrl_type *vfe32_ctrl)
{
- vfe32_reset_internal_variables();
+ vfe32_reset_internal_variables(vfe32_ctrl);
/* disable all interrupts. vfeImaskLocal is also reset to 0
* to begin with. */
msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
- vfe32_ctrl->vfebase + VFE_IRQ_MASK_0);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
- vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
/* clear all pending interrupts*/
msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
- vfe32_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
- vfe32_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+ vfe32_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, vfe32_ctrl->vfebase + VFE_IRQ_CMD);
+ msm_camera_io_w_mb(1, vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_CMD);
/* enable reset_ack interrupt. */
msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1,
- vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_1);
/* Write to VFE_GLOBAL_RESET_CMD to reset the vfe hardware. Once reset
* is done, hardware interrupt will be generated. VFE ist processes
@@ -549,409 +553,516 @@
/* Ensure the write order while writing
to the command register using the barrier */
msm_camera_io_w_mb(VFE_RESET_UPON_RESET_CMD,
- vfe32_ctrl->vfebase + VFE_GLOBAL_RESET);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET);
}
-static int vfe32_operation_config(uint32_t *cmd)
+static int vfe32_operation_config(uint32_t *cmd,
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
uint32_t *p = cmd;
- vfe32_ctrl->operation_mode = *p;
- vfe32_ctrl->stats_comp = *(++p);
+ vfe32_ctrl->share_ctrl->operation_mode = *p;
+ vfe32_ctrl->share_ctrl->stats_comp = *(++p);
vfe32_ctrl->hfr_mode = *(++p);
- msm_camera_io_w(*(++p), vfe32_ctrl->vfebase + VFE_CFG);
- msm_camera_io_w(*(++p), vfe32_ctrl->vfebase + VFE_MODULE_CFG);
- msm_camera_io_w(*(++p), vfe32_ctrl->vfebase + VFE_PIXEL_IF_CFG);
- if (msm_camera_io_r(vfe32_ctrl->vfebase + V32_GET_HW_VERSION_OFF) ==
+ msm_camera_io_w(*(++p),
+ vfe32_ctrl->share_ctrl->vfebase + VFE_CFG);
+ 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->vfebase + VFE_RDI0_CFG);
- msm_camera_io_w(*(++p), vfe32_ctrl->vfebase + VFE_RDI1_CFG);
+ 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->vfebase + VFE_REALIGN_BUF);
- msm_camera_io_w(*(++p), vfe32_ctrl->vfebase + VFE_CHROMA_UP);
- msm_camera_io_w(*(++p), vfe32_ctrl->vfebase + VFE_STATS_CFG);
+ 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);
+ msm_camera_io_w(*(++p),
+ vfe32_ctrl->share_ctrl->vfebase + VFE_STATS_CFG);
return 0;
}
-static uint32_t vfe_stats_awb_buf_init(struct vfe_cmd_stats_buf *in)
+static uint32_t vfe_stats_awb_buf_init(
+ struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_buf *in)
{
uint32_t *ptr = in->statsBuf;
uint32_t addr;
addr = ptr[0];
msm_camera_io_w(addr,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PING_ADDR);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_AWB_WR_PING_ADDR);
addr = ptr[1];
msm_camera_io_w(addr,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_AWB_WR_PONG_ADDR);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_AWB_WR_PONG_ADDR);
vfe32_ctrl->awbStatsControl.nextFrameAddrBuf = in->statsBuf[2];
return 0;
}
-static uint32_t vfe_stats_aec_buf_init(struct vfe_cmd_stats_buf *in)
+static uint32_t vfe_stats_aec_buf_init(
+ struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_buf *in)
{
uint32_t *ptr = in->statsBuf;
uint32_t addr;
addr = ptr[0];
msm_camera_io_w(addr,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_AEC_WR_PING_ADDR);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_AEC_WR_PING_ADDR);
addr = ptr[1];
msm_camera_io_w(addr,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_AEC_WR_PONG_ADDR);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_AEC_WR_PONG_ADDR);
vfe32_ctrl->aecStatsControl.nextFrameAddrBuf = in->statsBuf[2];
return 0;
}
-static uint32_t vfe_stats_af_buf_init(struct vfe_cmd_stats_buf *in)
+static uint32_t vfe_stats_af_buf_init(
+ struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_buf *in)
{
uint32_t *ptr = in->statsBuf;
uint32_t addr;
addr = ptr[0];
msm_camera_io_w(addr,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_AF_WR_PING_ADDR);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_AF_WR_PING_ADDR);
addr = ptr[1];
msm_camera_io_w(addr,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_AF_WR_PONG_ADDR);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_AF_WR_PONG_ADDR);
vfe32_ctrl->afStatsControl.nextFrameAddrBuf = in->statsBuf[2];
return 0;
}
-static uint32_t vfe_stats_ihist_buf_init(struct vfe_cmd_stats_buf *in)
+static uint32_t vfe_stats_ihist_buf_init(
+ struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_buf *in)
{
uint32_t *ptr = in->statsBuf;
uint32_t addr;
addr = ptr[0];
msm_camera_io_w(addr,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_HIST_WR_PING_ADDR);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_HIST_WR_PING_ADDR);
addr = ptr[1];
msm_camera_io_w(addr,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_HIST_WR_PONG_ADDR);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_HIST_WR_PONG_ADDR);
vfe32_ctrl->ihistStatsControl.nextFrameAddrBuf = in->statsBuf[2];
return 0;
}
-static uint32_t vfe_stats_rs_buf_init(struct vfe_cmd_stats_buf *in)
+static uint32_t vfe_stats_rs_buf_init(
+ struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_buf *in)
{
uint32_t *ptr = in->statsBuf;
uint32_t addr;
addr = ptr[0];
msm_camera_io_w(addr,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_RS_WR_PING_ADDR);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_RS_WR_PING_ADDR);
addr = ptr[1];
msm_camera_io_w(addr,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_RS_WR_PONG_ADDR);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_RS_WR_PONG_ADDR);
vfe32_ctrl->rsStatsControl.nextFrameAddrBuf = in->statsBuf[2];
return 0;
}
-static uint32_t vfe_stats_cs_buf_init(struct vfe_cmd_stats_buf *in)
+static uint32_t vfe_stats_cs_buf_init(
+ struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_buf *in)
{
uint32_t *ptr = in->statsBuf;
uint32_t addr;
addr = ptr[0];
msm_camera_io_w(addr,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_CS_WR_PING_ADDR);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_CS_WR_PING_ADDR);
addr = ptr[1];
msm_camera_io_w(addr,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_CS_WR_PONG_ADDR);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_BUS_STATS_CS_WR_PONG_ADDR);
vfe32_ctrl->csStatsControl.nextFrameAddrBuf = in->statsBuf[2];
return 0;
}
-static void vfe32_start_common(void)
+static void vfe32_start_common(struct vfe32_ctrl_type *vfe32_ctrl)
{
uint32_t irq_mask = 0x00E00021;
vfe32_ctrl->start_ack_pending = TRUE;
CDBG("VFE opertaion mode = 0x%x, output mode = 0x%x\n",
- vfe32_ctrl->operation_mode, vfe32_ctrl->outpath.output_mode);
- if (vfe32_ctrl->stats_comp)
+ vfe32_ctrl->share_ctrl->operation_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;
- msm_camera_io_w(irq_mask, vfe32_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->vfebase + VFE_IRQ_MASK_1);
+ vfe32_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(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
- msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
+ msm_camera_io_w_mb(1,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ msm_camera_io_w_mb(1,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
-
- atomic_set(&vfe32_ctrl->vstate, 1);
+ atomic_set(&vfe32_ctrl->share_ctrl->vstate, 1);
}
-static int vfe32_start_recording(struct msm_cam_media_controller *pmctl)
+static int vfe32_start_recording(
+ struct msm_cam_media_controller *pmctl,
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
msm_camio_bus_scale_cfg(
pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
vfe32_ctrl->recording_state = VFE_STATE_START_REQUESTED;
- msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ msm_camera_io_w_mb(1,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
return 0;
}
-static int vfe32_stop_recording(struct msm_cam_media_controller *pmctl)
+static int vfe32_stop_recording(
+ struct msm_cam_media_controller *pmctl,
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
vfe32_ctrl->recording_state = VFE_STATE_STOP_REQUESTED;
- msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ msm_camera_io_w_mb(1,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
msm_camio_bus_scale_cfg(
pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
return 0;
}
-static void vfe32_start_liveshot(struct msm_cam_media_controller *pmctl)
+static void vfe32_start_liveshot(
+ struct msm_cam_media_controller *pmctl,
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
/* Hardcode 1 live snapshot for now. */
- vfe32_ctrl->outpath.out0.capture_cnt = 1;
- vfe32_ctrl->vfe_capture_count = vfe32_ctrl->outpath.out0.capture_cnt;
+ vfe32_ctrl->share_ctrl->outpath.out0.capture_cnt = 1;
+ vfe32_ctrl->share_ctrl->vfe_capture_count =
+ vfe32_ctrl->share_ctrl->outpath.out0.capture_cnt;
- vfe32_ctrl->liveshot_state = VFE_STATE_START_REQUESTED;
- msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ vfe32_ctrl->share_ctrl->liveshot_state = VFE_STATE_START_REQUESTED;
+ msm_camera_io_w_mb(1, vfe32_ctrl->
+ share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
}
-static int vfe32_zsl(struct msm_cam_media_controller *pmctl)
+static int vfe32_zsl(
+ struct msm_cam_media_controller *pmctl,
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
uint32_t irq_comp_mask = 0;
/* capture command is valid for both idle and active state. */
irq_comp_mask =
- msm_camera_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ msm_camera_io_r(vfe32_ctrl->
+ share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
CDBG("%s:op mode %d O/P Mode %d\n", __func__,
- vfe32_ctrl->operation_mode, vfe32_ctrl->outpath.output_mode);
+ vfe32_ctrl->share_ctrl->operation_mode,
+ vfe32_ctrl->share_ctrl->outpath.output_mode);
- if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_PRIMARY) {
- irq_comp_mask |= ((0x1 << (vfe32_ctrl->outpath.out0.ch0)) |
- (0x1 << (vfe32_ctrl->outpath.out0.ch1)));
- } else if (vfe32_ctrl->outpath.output_mode &
+ if (vfe32_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY) {
+ irq_comp_mask |= (
+ (0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch0)) |
+ (0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch1)));
+ } else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
- irq_comp_mask |= ((0x1 << (vfe32_ctrl->outpath.out0.ch0)) |
- (0x1 << (vfe32_ctrl->outpath.out0.ch1)) |
- (0x1 << (vfe32_ctrl->outpath.out0.ch2)));
+ irq_comp_mask |= (
+ (0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch0)) |
+ (0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch1)) |
+ (0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch2)));
}
- if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_SECONDARY) {
- irq_comp_mask |= ((0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8)) |
- (0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8)));
- } else if (vfe32_ctrl->outpath.output_mode &
+ if (vfe32_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY) {
+ irq_comp_mask |= ((0x1 << (vfe32_ctrl->
+ share_ctrl->outpath.out1.ch0 + 8)) |
+ (0x1 << (vfe32_ctrl->
+ share_ctrl->outpath.out1.ch1 + 8)));
+ } else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
- irq_comp_mask |= ((0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8)) |
- (0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8)) |
- (0x1 << (vfe32_ctrl->outpath.out1.ch2 + 8)));
+ irq_comp_mask |= (
+ (0x1 << (vfe32_ctrl->
+ share_ctrl->outpath.out1.ch0 + 8)) |
+ (0x1 << (vfe32_ctrl->
+ share_ctrl->outpath.out1.ch1 + 8)) |
+ (0x1 << (vfe32_ctrl->
+ share_ctrl->outpath.out1.ch2 + 8)));
}
- if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
- } else if (vfe32_ctrl->outpath.output_mode &
+ 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]);
+ } else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch2]);
+ 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]);
+ msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->
+ share_ctrl->outpath.out0.ch2]);
}
- if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_SECONDARY) {
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
- } else if (vfe32_ctrl->outpath.output_mode &
+ if (vfe32_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY) {
+ 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]);
+ } else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch2]);
+ 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]);
+ msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->
+ share_ctrl->outpath.out1.ch2]);
}
- msm_camera_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
- vfe32_start_common();
+ msm_camera_io_w(irq_comp_mask,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ vfe32_start_common(vfe32_ctrl);
msm_camio_bus_scale_cfg(
pmctl->sdata->pdata->cam_bus_scale_table, S_ZSL);
- msm_camera_io_w(1, vfe32_ctrl->vfebase + 0x18C);
- msm_camera_io_w(1, vfe32_ctrl->vfebase + 0x188);
+ msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase + 0x18C);
+ msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase + 0x188);
return 0;
}
static int vfe32_capture_raw(
struct msm_cam_media_controller *pmctl,
+ struct vfe32_ctrl_type *vfe32_ctrl,
uint32_t num_frames_capture)
{
uint32_t irq_comp_mask = 0;
- vfe32_ctrl->outpath.out0.capture_cnt = num_frames_capture;
- vfe32_ctrl->vfe_capture_count = num_frames_capture;
+ vfe32_ctrl->share_ctrl->outpath.out0.capture_cnt = num_frames_capture;
+ vfe32_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
irq_comp_mask =
- msm_camera_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
- if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_PRIMARY) {
- irq_comp_mask |= (0x1 << (vfe32_ctrl->outpath.out0.ch0));
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
+ if (vfe32_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY) {
+ irq_comp_mask |=
+ (0x1 << (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.ch0]);
}
- msm_camera_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ msm_camera_io_w(irq_comp_mask,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
msm_camio_bus_scale_cfg(
pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
- vfe32_start_common();
+ vfe32_start_common(vfe32_ctrl);
return 0;
}
static int vfe32_capture(
struct msm_cam_media_controller *pmctl,
- uint32_t num_frames_capture)
+ uint32_t num_frames_capture,
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
uint32_t irq_comp_mask = 0;
/* capture command is valid for both idle and active state. */
- vfe32_ctrl->outpath.out1.capture_cnt = num_frames_capture;
- if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
- vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN ||
- vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
- vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) {
- vfe32_ctrl->outpath.out0.capture_cnt =
+ vfe32_ctrl->share_ctrl->outpath.out1.capture_cnt = num_frames_capture;
+ if (vfe32_ctrl->share_ctrl->operation_mode ==
+ VFE_OUTPUTS_MAIN_AND_THUMB ||
+ vfe32_ctrl->share_ctrl->operation_mode ==
+ VFE_OUTPUTS_THUMB_AND_MAIN ||
+ vfe32_ctrl->share_ctrl->operation_mode ==
+ VFE_OUTPUTS_JPEG_AND_THUMB ||
+ vfe32_ctrl->share_ctrl->operation_mode ==
+ VFE_OUTPUTS_THUMB_AND_JPEG) {
+ vfe32_ctrl->share_ctrl->outpath.out0.capture_cnt =
num_frames_capture;
}
- vfe32_ctrl->vfe_capture_count = num_frames_capture;
+ vfe32_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
irq_comp_mask = msm_camera_io_r(
- vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
- if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
- vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
- vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) {
- if (vfe32_ctrl->outpath.output_mode &
+ if (vfe32_ctrl->share_ctrl->operation_mode ==
+ VFE_OUTPUTS_MAIN_AND_THUMB ||
+ vfe32_ctrl->share_ctrl->operation_mode ==
+ VFE_OUTPUTS_JPEG_AND_THUMB ||
+ vfe32_ctrl->share_ctrl->operation_mode ==
+ VFE_OUTPUTS_THUMB_AND_MAIN) {
+ if (vfe32_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_PRIMARY) {
- irq_comp_mask |= (0x1 << vfe32_ctrl->outpath.out0.ch0 |
- 0x1 << vfe32_ctrl->outpath.out0.ch1);
+ irq_comp_mask |= (0x1 << vfe32_ctrl->
+ share_ctrl->outpath.out0.ch0 |
+ 0x1 << vfe32_ctrl->
+ share_ctrl->outpath.out0.ch1);
}
- if (vfe32_ctrl->outpath.output_mode &
+ if (vfe32_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_SECONDARY) {
irq_comp_mask |=
- (0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8) |
- 0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8));
+ (0x1 << (vfe32_ctrl->
+ share_ctrl->outpath.out1.ch0 + 8) |
+ 0x1 << (vfe32_ctrl->
+ share_ctrl->outpath.out1.ch1 + 8));
}
- if (vfe32_ctrl->outpath.output_mode &
+ if (vfe32_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
+ 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]);
}
- if (vfe32_ctrl->outpath.output_mode &
+ if (vfe32_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_SECONDARY) {
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
+ 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->vfe_capture_count = num_frames_capture;
+ vfe32_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
- msm_camera_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
- msm_camera_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ msm_camera_io_w(irq_comp_mask,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
msm_camio_bus_scale_cfg(
pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
- vfe32_start_common();
+ vfe32_start_common(vfe32_ctrl);
/* for debug */
- msm_camera_io_w(1, vfe32_ctrl->vfebase + 0x18C);
- msm_camera_io_w(1, vfe32_ctrl->vfebase + 0x188);
+ msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase + 0x18C);
+ msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase + 0x188);
return 0;
}
-static int vfe32_start(struct msm_cam_media_controller *pmctl)
+static int vfe32_start(
+ struct msm_cam_media_controller *pmctl,
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
uint32_t irq_comp_mask = 0;
irq_comp_mask =
- msm_camera_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_COMP_MASK);
- if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_PRIMARY) {
- irq_comp_mask |= (0x1 << vfe32_ctrl->outpath.out0.ch0 |
- 0x1 << vfe32_ctrl->outpath.out0.ch1);
- } else if (vfe32_ctrl->outpath.output_mode &
+ if (vfe32_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY) {
+ irq_comp_mask |= (
+ 0x1 << vfe32_ctrl->share_ctrl->outpath.out0.ch0 |
+ 0x1 << vfe32_ctrl->share_ctrl->outpath.out0.ch1);
+ } else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
- irq_comp_mask |= (0x1 << vfe32_ctrl->outpath.out0.ch0 |
- 0x1 << vfe32_ctrl->outpath.out0.ch1 |
- 0x1 << vfe32_ctrl->outpath.out0.ch2);
+ irq_comp_mask |= (
+ 0x1 << vfe32_ctrl->share_ctrl->outpath.out0.ch0 |
+ 0x1 << vfe32_ctrl->share_ctrl->outpath.out0.ch1 |
+ 0x1 << vfe32_ctrl->share_ctrl->outpath.out0.ch2);
}
- if (vfe32_ctrl->outpath.output_mode & VFE32_OUTPUT_MODE_SECONDARY) {
- irq_comp_mask |= (0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8) |
- 0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8));
- } else if (vfe32_ctrl->outpath.output_mode &
+ if (vfe32_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY) {
+ irq_comp_mask |= (
+ 0x1 << (vfe32_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
+ 0x1 << (vfe32_ctrl->share_ctrl->outpath.out1.ch1 + 8));
+ } else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
- irq_comp_mask |= (0x1 << (vfe32_ctrl->outpath.out1.ch0 + 8) |
- 0x1 << (vfe32_ctrl->outpath.out1.ch1 + 8) |
- 0x1 << (vfe32_ctrl->outpath.out1.ch2 + 8));
+ irq_comp_mask |= (
+ 0x1 << (vfe32_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
+ 0x1 << (vfe32_ctrl->share_ctrl->outpath.out1.ch1 + 8) |
+ 0x1 << (vfe32_ctrl->share_ctrl->outpath.out1.ch2 + 8));
}
- msm_camera_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+ msm_camera_io_w(irq_comp_mask,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
msm_camio_bus_scale_cfg(
pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
- vfe32_start_common();
+ vfe32_start_common(vfe32_ctrl);
return 0;
}
-static void vfe32_update(void)
+static void vfe32_update(struct vfe32_ctrl_type *vfe32_ctrl)
{
unsigned long flags;
uint32_t value = 0;
if (vfe32_ctrl->update_linear) {
if (!msm_camera_io_r(
- vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF1))
+ vfe32_ctrl->share_ctrl->vfebase +
+ V32_LINEARIZATION_OFF1))
msm_camera_io_w(1,
- vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF1);
+ vfe32_ctrl->share_ctrl->vfebase +
+ V32_LINEARIZATION_OFF1);
else
msm_camera_io_w(0,
- vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF1);
+ vfe32_ctrl->share_ctrl->vfebase +
+ V32_LINEARIZATION_OFF1);
vfe32_ctrl->update_linear = false;
}
if (vfe32_ctrl->update_rolloff) {
- value = msm_camera_io_r(vfe32_ctrl->vfebase +
+ value = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
V33_PCA_ROLL_OFF_CFG_OFF1);
value ^= V33_PCA_ROLL_OFF_LUT_BANK_SEL_MASK;
- msm_camera_io_w(value, vfe32_ctrl->vfebase +
+ msm_camera_io_w(value, vfe32_ctrl->share_ctrl->vfebase +
V33_PCA_ROLL_OFF_CFG_OFF1);
vfe32_ctrl->update_rolloff = false;
}
if (vfe32_ctrl->update_la) {
- if (!msm_camera_io_r(vfe32_ctrl->vfebase + V32_LA_OFF))
+ if (!msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + V32_LA_OFF))
msm_camera_io_w(1,
- vfe32_ctrl->vfebase + V32_LA_OFF);
+ vfe32_ctrl->share_ctrl->vfebase + V32_LA_OFF);
else
msm_camera_io_w(0,
- vfe32_ctrl->vfebase + V32_LA_OFF);
+ vfe32_ctrl->share_ctrl->vfebase + V32_LA_OFF);
vfe32_ctrl->update_la = false;
}
if (vfe32_ctrl->update_gamma) {
- value = msm_camera_io_r(vfe32_ctrl->vfebase + V32_RGB_G_OFF);
+ value = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + V32_RGB_G_OFF);
value ^= V32_GAMMA_LUT_BANK_SEL_MASK;
- msm_camera_io_w(value, vfe32_ctrl->vfebase + V32_RGB_G_OFF);
+ msm_camera_io_w(value,
+ vfe32_ctrl->share_ctrl->vfebase + V32_RGB_G_OFF);
vfe32_ctrl->update_gamma = false;
}
@@ -960,11 +1071,12 @@
spin_unlock_irqrestore(&vfe32_ctrl->update_ack_lock, flags);
/* Ensure the write order while writing
to the command register using the barrier */
- msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ msm_camera_io_w_mb(1,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
return;
}
-static void vfe32_sync_timer_stop(void)
+static void vfe32_sync_timer_stop(struct vfe32_ctrl_type *vfe32_ctrl)
{
uint32_t value = 0;
vfe32_ctrl->sync_timer_state = 0;
@@ -976,10 +1088,13 @@
value = 0x40000;
/* Timer Stop */
- msm_camera_io_w(value, vfe32_ctrl->vfebase + V32_SYNC_TIMER_OFF);
+ msm_camera_io_w(value,
+ vfe32_ctrl->share_ctrl->vfebase + V32_SYNC_TIMER_OFF);
}
-static void vfe32_sync_timer_start(const uint32_t *tbl)
+static void vfe32_sync_timer_start(
+ const uint32_t *tbl,
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
/* set bit 8 for auto increment. */
uint32_t value = 1;
@@ -1001,14 +1116,17 @@
}
/* Timer Start */
- msm_camera_io_w(value, vfe32_ctrl->vfebase + V32_SYNC_TIMER_OFF);
+ msm_camera_io_w(value,
+ vfe32_ctrl->share_ctrl->vfebase + V32_SYNC_TIMER_OFF);
/* Sync Timer Line Start */
value = *tbl++;
- msm_camera_io_w(value, vfe32_ctrl->vfebase + V32_SYNC_TIMER_OFF +
+ msm_camera_io_w(value,
+ vfe32_ctrl->share_ctrl->vfebase + V32_SYNC_TIMER_OFF +
4 + ((vfe32_ctrl->sync_timer_number) * 12));
/* Sync Timer Pixel Start */
value = *tbl++;
- msm_camera_io_w(value, vfe32_ctrl->vfebase + V32_SYNC_TIMER_OFF +
+ msm_camera_io_w(value,
+ vfe32_ctrl->share_ctrl->vfebase + V32_SYNC_TIMER_OFF +
8 + ((vfe32_ctrl->sync_timer_number) * 12));
/* Sync Timer Pixel Duration */
value = *tbl++;
@@ -1016,87 +1134,99 @@
val = 10000000 / val;
val = value * 10000 / val;
CDBG("%s: Pixel Clk Cycles!!! %d\n", __func__, val);
- msm_camera_io_w(val, vfe32_ctrl->vfebase + V32_SYNC_TIMER_OFF +
+ msm_camera_io_w(val,
+ vfe32_ctrl->share_ctrl->vfebase + V32_SYNC_TIMER_OFF +
12 + ((vfe32_ctrl->sync_timer_number) * 12));
/* Timer0 Active High/LOW */
value = *tbl++;
msm_camera_io_w(value,
- vfe32_ctrl->vfebase + V32_SYNC_TIMER_POLARITY_OFF);
+ vfe32_ctrl->share_ctrl->vfebase + V32_SYNC_TIMER_POLARITY_OFF);
/* Selects sync timer 0 output to drive onto timer1 port */
value = 0;
- msm_camera_io_w(value, vfe32_ctrl->vfebase + V32_TIMER_SELECT_OFF);
+ msm_camera_io_w(value,
+ vfe32_ctrl->share_ctrl->vfebase + V32_TIMER_SELECT_OFF);
}
-static void vfe32_program_dmi_cfg(enum VFE32_DMI_RAM_SEL bankSel)
+static void vfe32_program_dmi_cfg(
+ enum VFE32_DMI_RAM_SEL bankSel,
+ struct vfe32_ctrl_type *vfe32_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, vfe32_ctrl->vfebase + VFE_DMI_CFG);
+ msm_camera_io_w(value, vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_CFG);
/* by default, always starts with offset 0.*/
- msm_camera_io_w(0, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+ msm_camera_io_w(0, vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_ADDR);
}
-static void vfe32_write_gamma_cfg(enum VFE32_DMI_RAM_SEL channel_sel,
- const uint32_t *tbl)
+static void vfe32_write_gamma_cfg(
+ enum VFE32_DMI_RAM_SEL channel_sel,
+ const uint32_t *tbl,
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
int i;
uint32_t value, value1, value2;
- vfe32_program_dmi_cfg(channel_sel);
+ vfe32_program_dmi_cfg(channel_sel, vfe32_ctrl);
for (i = 0 ; i < (VFE32_GAMMA_NUM_ENTRIES/2) ; i++) {
value = *tbl++;
value1 = value & 0x0000FFFF;
value2 = (value & 0xFFFF0000)>>16;
msm_camera_io_w((value1),
- vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_DATA_LO);
msm_camera_io_w((value2),
- vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_DATA_LO);
}
- vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+ vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
}
-static void vfe32_read_gamma_cfg(enum VFE32_DMI_RAM_SEL channel_sel,
- uint32_t *tbl)
+static void vfe32_read_gamma_cfg(
+ enum VFE32_DMI_RAM_SEL channel_sel,
+ uint32_t *tbl,
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
int i;
- vfe32_program_dmi_cfg(channel_sel);
+ vfe32_program_dmi_cfg(channel_sel, vfe32_ctrl);
CDBG("%s: Gamma table channel: %d\n", __func__, channel_sel);
for (i = 0 ; i < VFE32_GAMMA_NUM_ENTRIES ; i++) {
- *tbl = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+ *tbl = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_DATA_LO);
CDBG("%s: %08x\n", __func__, *tbl);
tbl++;
}
- vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+ vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
}
-static void vfe32_write_la_cfg(enum VFE32_DMI_RAM_SEL channel_sel,
- const uint32_t *tbl)
+static void vfe32_write_la_cfg(
+ enum VFE32_DMI_RAM_SEL channel_sel,
+ const uint32_t *tbl,
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
uint32_t i;
uint32_t value, value1, value2;
- vfe32_program_dmi_cfg(channel_sel);
+ vfe32_program_dmi_cfg(channel_sel, vfe32_ctrl);
for (i = 0 ; i < (VFE32_LA_TABLE_LENGTH/2) ; i++) {
value = *tbl++;
value1 = value & 0x0000FFFF;
value2 = (value & 0xFFFF0000)>>16;
msm_camera_io_w((value1),
- vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_DATA_LO);
msm_camera_io_w((value2),
- vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_DATA_LO);
}
- vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+ vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
}
-static struct vfe32_output_ch *vfe32_get_ch(int path)
+static struct vfe32_output_ch *vfe32_get_ch(
+ int path, struct vfe_share_ctrl_t *share_ctrl)
{
struct vfe32_output_ch *ch = NULL;
if (path == VFE_MSG_OUTPUT_PRIMARY)
- ch = &vfe32_ctrl->outpath.out0;
+ ch = &share_ctrl->outpath.out0;
else if (path == VFE_MSG_OUTPUT_SECONDARY)
- ch = &vfe32_ctrl->outpath.out1;
+ ch = &share_ctrl->outpath.out1;
else
pr_err("%s: Invalid path %d\n", __func__,
path);
@@ -1104,44 +1234,54 @@
BUG_ON(ch == NULL);
return ch;
}
-static struct msm_free_buf *vfe32_check_free_buffer(int id, int path)
+static struct msm_free_buf *vfe32_check_free_buffer(
+ int id, int path, struct axi_ctrl_t *axi_ctrl)
{
struct vfe32_output_ch *outch = NULL;
struct msm_free_buf *b = NULL;
- vfe32_subdev_notify(id, path);
- outch = vfe32_get_ch(path);
+ vfe32_subdev_notify(id, path,
+ &axi_ctrl->subdev, axi_ctrl->share_ctrl);
+ outch = vfe32_get_ch(path, axi_ctrl->share_ctrl);
if (outch->free_buf.ch_paddr[0])
b = &outch->free_buf;
return b;
}
-static int vfe32_configure_pingpong_buffers(int id, int path)
+static int vfe32_configure_pingpong_buffers(
+ int id, int path, struct vfe32_ctrl_type *vfe32_ctrl)
{
struct vfe32_output_ch *outch = NULL;
int rc = 0;
- vfe32_subdev_notify(id, path);
- outch = vfe32_get_ch(path);
+ vfe32_subdev_notify(id, path,
+ &vfe32_ctrl->subdev, vfe32_ctrl->share_ctrl);
+ outch = vfe32_get_ch(path, vfe32_ctrl->share_ctrl);
if (outch->ping.ch_paddr[0] && outch->pong.ch_paddr[0]) {
/* Configure Preview Ping Pong */
pr_info("%s Configure ping/pong address for %d",
__func__, path);
- vfe32_put_ch_ping_addr(outch->ch0,
+ vfe32_put_ch_ping_addr(
+ vfe32_ctrl->share_ctrl->vfebase, outch->ch0,
outch->ping.ch_paddr[0]);
- vfe32_put_ch_pong_addr(outch->ch0,
+ vfe32_put_ch_pong_addr(
+ vfe32_ctrl->share_ctrl->vfebase, outch->ch0,
outch->pong.ch_paddr[0]);
- if (vfe32_ctrl->operation_mode !=
+ if (vfe32_ctrl->share_ctrl->operation_mode !=
VFE_OUTPUTS_RAW) {
- vfe32_put_ch_ping_addr(outch->ch1,
+ vfe32_put_ch_ping_addr(
+ vfe32_ctrl->share_ctrl->vfebase, outch->ch1,
outch->ping.ch_paddr[1]);
- vfe32_put_ch_pong_addr(outch->ch1,
+ vfe32_put_ch_pong_addr(
+ vfe32_ctrl->share_ctrl->vfebase, outch->ch1,
outch->pong.ch_paddr[1]);
}
if (outch->ping.num_planes > 2)
- vfe32_put_ch_ping_addr(outch->ch2,
+ vfe32_put_ch_ping_addr(
+ vfe32_ctrl->share_ctrl->vfebase, outch->ch2,
outch->ping.ch_paddr[2]);
if (outch->pong.num_planes > 2)
- vfe32_put_ch_pong_addr(outch->ch2,
+ vfe32_put_ch_pong_addr(
+ vfe32_ctrl->share_ctrl->vfebase, outch->ch2,
outch->pong.ch_paddr[2]);
/* avoid stale info */
@@ -1154,37 +1294,41 @@
return rc;
}
-static void vfe32_write_linear_cfg(enum VFE32_DMI_RAM_SEL channel_sel,
- const uint32_t *tbl)
+static void vfe32_write_linear_cfg(
+ enum VFE32_DMI_RAM_SEL channel_sel,
+ const uint32_t *tbl, struct vfe32_ctrl_type *vfe32_ctrl)
{
uint32_t i;
- vfe32_program_dmi_cfg(channel_sel);
+ vfe32_program_dmi_cfg(channel_sel, vfe32_ctrl);
/* for loop for configuring LUT. */
for (i = 0 ; i < VFE32_LINEARIZATON_TABLE_LENGTH ; i++) {
- msm_camera_io_w(*tbl, vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+ msm_camera_io_w(*tbl,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_DATA_LO);
tbl++;
}
CDBG("done writing to linearization table\n");
- vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+ vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
}
static void vfe32_send_isp_msg(
- struct vfe32_ctrl_type *vctrl,
+ struct v4l2_subdev *sd,
+ uint32_t vfeFrameId,
uint32_t isp_msg_id)
{
struct isp_msg_event isp_msg_evt;
isp_msg_evt.msg_id = isp_msg_id;
- isp_msg_evt.sof_count = vfe32_ctrl->vfeFrameId;
- v4l2_subdev_notify(&vctrl->subdev,
+ isp_msg_evt.sof_count = vfeFrameId;
+ v4l2_subdev_notify(sd,
NOTIFY_ISP_MSG_EVT,
(void *)&isp_msg_evt);
}
static int vfe32_proc_general(
struct msm_cam_media_controller *pmctl,
- struct msm_isp_cmd *cmd)
+ struct msm_isp_cmd *cmd,
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
int i , rc = 0;
uint32_t old_val = 0 , new_val = 0;
@@ -1199,32 +1343,34 @@
case VFE_CMD_RESET:
pr_info("vfe32_proc_general: cmdID = %s\n",
vfe32_general_cmd[cmd->id]);
- vfe32_reset();
+ vfe32_reset(vfe32_ctrl);
break;
case VFE_CMD_START:
pr_info("vfe32_proc_general: cmdID = %s\n",
vfe32_general_cmd[cmd->id]);
- if ((vfe32_ctrl->operation_mode ==
+ if ((vfe32_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_PREVIEW_AND_VIDEO) ||
- (vfe32_ctrl->operation_mode ==
+ (vfe32_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_PREVIEW))
/* Configure primary channel */
rc = vfe32_configure_pingpong_buffers(
- VFE_MSG_V32_START, VFE_MSG_OUTPUT_PRIMARY);
+ VFE_MSG_V32_START, VFE_MSG_OUTPUT_PRIMARY,
+ vfe32_ctrl);
else
/* Configure secondary channel */
rc = vfe32_configure_pingpong_buffers(
- VFE_MSG_V32_START, VFE_MSG_OUTPUT_SECONDARY);
+ VFE_MSG_V32_START, VFE_MSG_OUTPUT_SECONDARY,
+ vfe32_ctrl);
if (rc < 0) {
pr_err("%s error configuring pingpong buffers"
" for preview", __func__);
rc = -EINVAL;
goto proc_general_done;
}
- rc = vfe32_start(pmctl);
+ rc = vfe32_start(pmctl, vfe32_ctrl);
break;
case VFE_CMD_UPDATE:
- vfe32_update();
+ vfe32_update(vfe32_ctrl);
break;
case VFE_CMD_CAPTURE_RAW:
pr_info("%s: cmdID = VFE_CMD_CAPTURE_RAW\n", __func__);
@@ -1233,15 +1379,16 @@
rc = -EFAULT;
goto proc_general_done;
}
- rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE,
- VFE_MSG_OUTPUT_PRIMARY);
+ rc = vfe32_configure_pingpong_buffers(
+ VFE_MSG_V32_CAPTURE, VFE_MSG_OUTPUT_PRIMARY,
+ vfe32_ctrl);
if (rc < 0) {
pr_err("%s error configuring pingpong buffers"
" for snapshot", __func__);
rc = -EINVAL;
goto proc_general_done;
}
- rc = vfe32_capture_raw(pmctl, snapshot_cnt);
+ rc = vfe32_capture_raw(pmctl, vfe32_ctrl, snapshot_cnt);
break;
case VFE_CMD_CAPTURE:
if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
@@ -1250,8 +1397,10 @@
goto proc_general_done;
}
- if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
- vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) {
+ if (vfe32_ctrl->share_ctrl->operation_mode ==
+ VFE_OUTPUTS_JPEG_AND_THUMB ||
+ vfe32_ctrl->share_ctrl->operation_mode ==
+ VFE_OUTPUTS_THUMB_AND_JPEG) {
if (snapshot_cnt != 1) {
pr_err("only support 1 inline snapshot\n");
rc = -EINVAL;
@@ -1260,12 +1409,14 @@
/* Configure primary channel for JPEG */
rc = vfe32_configure_pingpong_buffers(
VFE_MSG_V32_JPEG_CAPTURE,
- VFE_MSG_OUTPUT_PRIMARY);
+ VFE_MSG_OUTPUT_PRIMARY,
+ vfe32_ctrl);
} else {
/* Configure primary channel */
rc = vfe32_configure_pingpong_buffers(
VFE_MSG_V32_CAPTURE,
- VFE_MSG_OUTPUT_PRIMARY);
+ VFE_MSG_OUTPUT_PRIMARY,
+ vfe32_ctrl);
}
if (rc < 0) {
pr_err("%s error configuring pingpong buffers"
@@ -1274,41 +1425,44 @@
goto proc_general_done;
}
/* Configure secondary channel */
- rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE,
- VFE_MSG_OUTPUT_SECONDARY);
+ rc = vfe32_configure_pingpong_buffers(
+ VFE_MSG_V32_CAPTURE, VFE_MSG_OUTPUT_SECONDARY,
+ vfe32_ctrl);
if (rc < 0) {
pr_err("%s error configuring pingpong buffers"
" for secondary output", __func__);
rc = -EINVAL;
goto proc_general_done;
}
- rc = vfe32_capture(pmctl, snapshot_cnt);
+ rc = vfe32_capture(pmctl, snapshot_cnt, vfe32_ctrl);
break;
case VFE_CMD_START_RECORDING:
pr_info("vfe32_proc_general: cmdID = %s\n",
vfe32_general_cmd[cmd->id]);
- if (vfe32_ctrl->operation_mode ==
+ if (vfe32_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_PREVIEW_AND_VIDEO)
rc = vfe32_configure_pingpong_buffers(
VFE_MSG_V32_START_RECORDING,
- VFE_MSG_OUTPUT_SECONDARY);
- else if (vfe32_ctrl->operation_mode ==
+ VFE_MSG_OUTPUT_SECONDARY,
+ vfe32_ctrl);
+ else if (vfe32_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_VIDEO_AND_PREVIEW)
rc = vfe32_configure_pingpong_buffers(
VFE_MSG_V32_START_RECORDING,
- VFE_MSG_OUTPUT_PRIMARY);
+ VFE_MSG_OUTPUT_PRIMARY,
+ vfe32_ctrl);
if (rc < 0) {
pr_err("%s error configuring pingpong buffers"
" for video", __func__);
rc = -EINVAL;
goto proc_general_done;
}
- rc = vfe32_start_recording(pmctl);
+ rc = vfe32_start_recording(pmctl, vfe32_ctrl);
break;
case VFE_CMD_STOP_RECORDING:
pr_info("vfe32_proc_general: cmdID = %s\n",
vfe32_general_cmd[cmd->id]);
- rc = vfe32_stop_recording(pmctl);
+ rc = vfe32_stop_recording(pmctl, vfe32_ctrl);
break;
case VFE_CMD_OPERATION_CFG: {
if (cmd->length != V32_OPERATION_CFG_LEN) {
@@ -1322,7 +1476,7 @@
rc = -EFAULT;
goto proc_general_done;
}
- rc = vfe32_operation_config(cmdp);
+ rc = vfe32_operation_config(cmdp, vfe32_ctrl);
}
break;
@@ -1338,12 +1492,14 @@
rc = -EFAULT;
goto proc_general_done;
}
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
old_val |= AE_BG_ENABLE_MASK;
msm_camera_io_w(old_val,
- vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_cmd[cmd->id].offset,
cmdp, (vfe32_cmd[cmd->id].length));
}
break;
@@ -1359,12 +1515,14 @@
rc = -EFAULT;
goto proc_general_done;
}
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
+ VFE_MODULE_CFG);
old_val |= AF_BF_ENABLE_MASK;
msm_camera_io_w(old_val,
- vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_cmd[cmd->id].offset,
cmdp, (vfe32_cmd[cmd->id].length));
}
break;
@@ -1380,12 +1538,14 @@
rc = -EFAULT;
goto proc_general_done;
}
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
old_val |= AWB_ENABLE_MASK;
msm_camera_io_w(old_val,
- vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_cmd[cmd->id].offset,
cmdp, (vfe32_cmd[cmd->id].length));
}
break;
@@ -1402,12 +1562,14 @@
rc = -EFAULT;
goto proc_general_done;
}
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
old_val |= IHIST_ENABLE_MASK;
msm_camera_io_w(old_val,
- vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_cmd[cmd->id].offset,
cmdp, (vfe32_cmd[cmd->id].length));
}
break;
@@ -1426,7 +1588,8 @@
goto proc_general_done;
}
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_cmd[cmd->id].offset,
cmdp, (vfe32_cmd[cmd->id].length));
}
break;
@@ -1444,7 +1607,8 @@
goto proc_general_done;
}
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_cmd[cmd->id].offset,
cmdp, (vfe32_cmd[cmd->id].length));
}
break;
@@ -1454,7 +1618,7 @@
cmdp = kmalloc(cmd->length, GFP_ATOMIC);
/* Incrementing with 4 so as to point to the 2nd Register as
the 2nd register has the mce_enable bit */
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase +
+ old_val = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
V32_CHROMA_SUP_OFF + 4);
if (!cmdp) {
rc = -ENOMEM;
@@ -1471,21 +1635,22 @@
old_val &= MCE_EN_MASK;
new_val = new_val | old_val;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + V32_CHROMA_SUP_OFF + 4,
- &new_val, 4);
+ vfe32_ctrl->share_ctrl->vfebase +
+ V32_CHROMA_SUP_OFF + 4, &new_val, 4);
cmdp_local += 1;
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase +
+ old_val = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
V32_CHROMA_SUP_OFF + 8);
new_val = *cmdp_local;
old_val &= MCE_Q_K_MASK;
new_val = new_val | old_val;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + V32_CHROMA_SUP_OFF + 8,
- &new_val, 4);
+ vfe32_ctrl->share_ctrl->vfebase +
+ V32_CHROMA_SUP_OFF + 8, &new_val, 4);
cmdp_local += 1;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_cmd[cmd->id].offset,
cmdp_local, (vfe32_cmd[cmd->id].length));
}
break;
@@ -1503,31 +1668,31 @@
goto proc_general_done;
}
cmdp_local = cmdp;
- msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_CHROMA_SUP_OFF,
- cmdp_local, 4);
+ msm_camera_io_memcpy(vfe32_ctrl->share_ctrl->vfebase +
+ V32_CHROMA_SUP_OFF, cmdp_local, 4);
cmdp_local += 1;
new_val = *cmdp_local;
/* Incrementing with 4 so as to point to the 2nd Register as
* the 2nd register has the mce_enable bit
*/
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase +
+ old_val = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
V32_CHROMA_SUP_OFF + 4);
old_val &= ~MCE_EN_MASK;
new_val = new_val | old_val;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + V32_CHROMA_SUP_OFF + 4,
- &new_val, 4);
+ vfe32_ctrl->share_ctrl->vfebase +
+ V32_CHROMA_SUP_OFF + 4, &new_val, 4);
cmdp_local += 1;
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase +
+ old_val = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
V32_CHROMA_SUP_OFF + 8);
new_val = *cmdp_local;
old_val &= ~MCE_Q_K_MASK;
new_val = new_val | old_val;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + V32_CHROMA_SUP_OFF + 8,
- &new_val, 4);
+ vfe32_ctrl->share_ctrl->vfebase +
+ V32_CHROMA_SUP_OFF + 8, &new_val, 4);
}
break;
case VFE_CMD_BLACK_LEVEL_CFG:
@@ -1547,27 +1712,28 @@
}
cmdp_local = cmdp;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_cmd[cmd->id].offset,
cmdp_local, 16);
cmdp_local += 4;
- vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0);
+ vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0, vfe32_ctrl);
/* for loop for extrcting init table. */
for (i = 0; i < (V32_MESH_ROLL_OFF_INIT_TABLE_SIZE * 2); i++) {
msm_camera_io_w(*cmdp_local ,
- vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_DATA_LO);
cmdp_local++;
}
CDBG("done writing init table\n");
/* by default, always starts with offset 0. */
msm_camera_io_w(V32_MESH_ROLL_OFF_DELTA_TABLE_OFFSET,
- vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_ADDR);
/* for loop for extracting delta table. */
for (i = 0; i < (V32_MESH_ROLL_OFF_DELTA_TABLE_SIZE * 2); i++) {
msm_camera_io_w(*cmdp_local,
- vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_DATA_LO);
cmdp_local++;
}
- vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+ vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
}
break;
@@ -1584,27 +1750,29 @@
goto proc_general_done;
}
cmdp_local = cmdp;
- vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0);
+ vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0, vfe32_ctrl);
CDBG("%s: Mesh Rolloff init Table\n", __func__);
for (i = 0; i < (V32_MESH_ROLL_OFF_INIT_TABLE_SIZE * 2); i++) {
*cmdp_local =
msm_camera_io_r(
- vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_DMI_DATA_LO);
CDBG("%s: %08x\n", __func__, *cmdp_local);
cmdp_local++;
}
msm_camera_io_w(V32_MESH_ROLL_OFF_DELTA_TABLE_OFFSET,
- vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_ADDR);
CDBG("%s: Mesh Rolloff Delta Table\n", __func__);
for (i = 0; i < (V32_MESH_ROLL_OFF_DELTA_TABLE_SIZE * 2); i++) {
*cmdp_local =
msm_camera_io_r(
- vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_DMI_DATA_LO);
CDBG("%s: %08x\n", __func__, *cmdp_local);
cmdp_local++;
}
CDBG("done reading delta table\n");
- vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+ vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
if (copy_to_user((void __user *)(cmd->value), cmdp,
temp1)) {
rc = -EFAULT;
@@ -1626,11 +1794,13 @@
}
cmdp_local = cmdp;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_cmd[cmd->id].offset,
cmdp_local, (vfe32_cmd[cmd->id].length));
cmdp_local += 1;
- vfe32_write_la_cfg(LUMA_ADAPT_LUT_RAM_BANK0, cmdp_local);
+ vfe32_write_la_cfg(LUMA_ADAPT_LUT_RAM_BANK0,
+ cmdp_local, vfe32_ctrl);
break;
case VFE_CMD_LA_UPDATE: {
@@ -1648,13 +1818,14 @@
}
cmdp_local = cmdp + 1;
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase + V32_LA_OFF);
+ old_val = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + V32_LA_OFF);
if (old_val != 0x0)
vfe32_write_la_cfg(LUMA_ADAPT_LUT_RAM_BANK0,
- cmdp_local);
+ cmdp_local, vfe32_ctrl);
else
vfe32_write_la_cfg(LUMA_ADAPT_LUT_RAM_BANK1,
- cmdp_local);
+ cmdp_local, vfe32_ctrl);
}
vfe32_ctrl->update_la = true;
break;
@@ -1671,19 +1842,24 @@
goto proc_general_done;
}
cmdp_local = cmdp;
- if (msm_camera_io_r(vfe32_ctrl->vfebase + V32_LA_OFF))
- vfe32_program_dmi_cfg(LUMA_ADAPT_LUT_RAM_BANK1);
+ if (msm_camera_io_r(vfe32_ctrl->
+ share_ctrl->vfebase + V32_LA_OFF))
+ vfe32_program_dmi_cfg(LUMA_ADAPT_LUT_RAM_BANK1,
+ vfe32_ctrl);
else
- vfe32_program_dmi_cfg(LUMA_ADAPT_LUT_RAM_BANK0);
+ vfe32_program_dmi_cfg(LUMA_ADAPT_LUT_RAM_BANK0,
+ vfe32_ctrl);
for (i = 0 ; i < (VFE32_LA_TABLE_LENGTH / 2) ; i++) {
*cmdp_local =
msm_camera_io_r(
- vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
- *cmdp_local |= (msm_camera_io_r(vfe32_ctrl->vfebase +
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_DMI_DATA_LO);
+ *cmdp_local |= (msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase +
VFE_DMI_DATA_LO)) << 16;
cmdp_local++;
}
- vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+ vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
if (copy_to_user((void __user *)(cmd->value), cmdp,
temp1)) {
rc = -EFAULT;
@@ -1703,22 +1879,23 @@
rc = -EFAULT;
goto proc_general_done;
}
- msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_SCE_OFF,
- cmdp, V32_SCE_LEN);
+ msm_camera_io_memcpy(
+ vfe32_ctrl->share_ctrl->vfebase + V32_SCE_OFF,
+ cmdp, V32_SCE_LEN);
}
break;
case VFE_CMD_LIVESHOT:
/* Configure primary channel */
rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_CAPTURE,
- VFE_MSG_OUTPUT_PRIMARY);
+ VFE_MSG_OUTPUT_PRIMARY, vfe32_ctrl);
if (rc < 0) {
pr_err("%s error configuring pingpong buffers"
" for primary output", __func__);
rc = -EINVAL;
goto proc_general_done;
}
- vfe32_start_liveshot(pmctl);
+ vfe32_start_liveshot(pmctl, vfe32_ctrl);
break;
case VFE_CMD_LINEARIZATION_CFG:
@@ -1734,15 +1911,18 @@
}
cmdp_local = cmdp;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF1,
+ vfe32_ctrl->share_ctrl->vfebase +
+ V32_LINEARIZATION_OFF1,
cmdp_local, V32_LINEARIZATION_LEN1);
cmdp_local += 4;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF2,
+ vfe32_ctrl->share_ctrl->vfebase +
+ V32_LINEARIZATION_OFF2,
cmdp_local, V32_LINEARIZATION_LEN2);
cmdp_local = cmdp + 17;
- vfe32_write_linear_cfg(BLACK_LUT_RAM_BANK0, cmdp_local);
+ vfe32_write_linear_cfg(BLACK_LUT_RAM_BANK0,
+ cmdp_local, vfe32_ctrl);
break;
case VFE_CMD_LINEARIZATION_UPDATE:
@@ -1759,21 +1939,26 @@
cmdp_local = cmdp;
cmdp_local++;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF1 + 4,
+ vfe32_ctrl->share_ctrl->vfebase +
+ V32_LINEARIZATION_OFF1 + 4,
cmdp_local, (V32_LINEARIZATION_LEN1 - 4));
cmdp_local += 3;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF2,
+ vfe32_ctrl->share_ctrl->vfebase +
+ V32_LINEARIZATION_OFF2,
cmdp_local, V32_LINEARIZATION_LEN2);
cmdp_local = cmdp + 17;
/*extracting the bank select*/
old_val = msm_camera_io_r(
- vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF1);
+ vfe32_ctrl->share_ctrl->vfebase +
+ V32_LINEARIZATION_OFF1);
if (old_val != 0x0)
- vfe32_write_linear_cfg(BLACK_LUT_RAM_BANK0, cmdp_local);
+ vfe32_write_linear_cfg(BLACK_LUT_RAM_BANK0,
+ cmdp_local, vfe32_ctrl);
else
- vfe32_write_linear_cfg(BLACK_LUT_RAM_BANK1, cmdp_local);
+ vfe32_write_linear_cfg(BLACK_LUT_RAM_BANK1,
+ cmdp_local, vfe32_ctrl);
vfe32_ctrl->update_linear = true;
break;
@@ -1790,18 +1975,20 @@
}
cmdp_local = cmdp;
if (msm_camera_io_r(
- vfe32_ctrl->vfebase + V32_LINEARIZATION_OFF1))
- vfe32_program_dmi_cfg(BLACK_LUT_RAM_BANK1);
+ vfe32_ctrl->share_ctrl->vfebase +
+ V32_LINEARIZATION_OFF1))
+ vfe32_program_dmi_cfg(BLACK_LUT_RAM_BANK1, vfe32_ctrl);
else
- vfe32_program_dmi_cfg(BLACK_LUT_RAM_BANK0);
+ vfe32_program_dmi_cfg(BLACK_LUT_RAM_BANK0, vfe32_ctrl);
CDBG("%s: Linearization Table\n", __func__);
for (i = 0 ; i < VFE32_LINEARIZATON_TABLE_LENGTH ; i++) {
*cmdp_local = msm_camera_io_r(
- vfe32_ctrl->vfebase + VFE_DMI_DATA_LO);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE_DMI_DATA_LO);
CDBG("%s: %08x\n", __func__, *cmdp_local);
cmdp_local++;
}
- vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+ vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
if (copy_to_user((void __user *)(cmd->value), cmdp,
temp1)) {
rc = -EFAULT;
@@ -1829,15 +2016,17 @@
new_val = *cmdp_local;
old_val = msm_camera_io_r(
- vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
+ vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
old_val &= DEMOSAIC_MASK;
new_val = new_val | old_val;
*cmdp_local = new_val;
- msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF,
+ msm_camera_io_memcpy(
+ vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF,
cmdp_local, V32_DEMOSAICV3_0_LEN);
cmdp_local += 1;
- msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_DEMOSAICV3_1_OFF,
+ msm_camera_io_memcpy(
+ vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_1_OFF,
cmdp_local, V32_DEMOSAICV3_1_LEN);
break;
@@ -1862,22 +2051,25 @@
new_val = *cmdp_local;
old_val = msm_camera_io_r(
- vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
+ vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
old_val &= DEMOSAIC_MASK;
new_val = new_val | old_val;
*cmdp_local = new_val;
- msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF,
+ msm_camera_io_memcpy(
+ vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF,
cmdp_local, V32_DEMOSAICV3_0_LEN);
/* As the address space is not contiguous increment by 2
* before copying to next address space */
cmdp_local += 1;
- msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_DEMOSAICV3_1_OFF,
+ msm_camera_io_memcpy(
+ vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_1_OFF,
cmdp_local, 2 * V32_DEMOSAICV3_0_LEN);
/* As the address space is not contiguous increment by 2
* before copying to next address space */
cmdp_local += 2;
- msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_DEMOSAICV3_2_OFF,
+ msm_camera_io_memcpy(
+ vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_2_OFF,
cmdp_local, 2 * V32_DEMOSAICV3_0_LEN);
break;
@@ -1902,17 +2094,19 @@
new_val = *cmdp_local;
old_val = msm_camera_io_r(
- vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
+ vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
old_val &= ABF_MASK;
new_val = new_val | old_val;
*cmdp_local = new_val;
- msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF,
- cmdp_local, 4);
+ msm_camera_io_memcpy(
+ vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF,
+ cmdp_local, 4);
cmdp_local += 1;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_cmd[cmd->id].offset,
cmdp_local, (vfe32_cmd[cmd->id].length));
}
break;
@@ -1934,16 +2128,18 @@
new_val = *cmdp_local;
old_val = msm_camera_io_r(
- vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
+ vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
old_val &= DBCC_MASK;
new_val = new_val | old_val;
*cmdp_local = new_val;
- msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF,
- cmdp_local, 4);
+ msm_camera_io_memcpy(
+ vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF,
+ cmdp_local, 4);
cmdp_local += 1;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_cmd[cmd->id].offset,
cmdp_local, (vfe32_cmd[cmd->id].length));
break;
@@ -1964,28 +2160,28 @@
new_val = *cmdp_local;
old_val = msm_camera_io_r(
- vfe32_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
+ vfe32_ctrl->share_ctrl->vfebase + V32_DEMOSAICV3_0_OFF);
old_val &= DBPC_MASK;
new_val = new_val | old_val;
*cmdp_local = new_val;
- msm_camera_io_memcpy(vfe32_ctrl->vfebase +
+ msm_camera_io_memcpy(vfe32_ctrl->share_ctrl->vfebase +
V32_DEMOSAICV3_0_OFF,
cmdp_local, V32_DEMOSAICV3_LEN);
cmdp_local += 1;
- msm_camera_io_memcpy(vfe32_ctrl->vfebase +
+ msm_camera_io_memcpy(vfe32_ctrl->share_ctrl->vfebase +
V32_DEMOSAICV3_DBPC_CFG_OFF,
cmdp_local, V32_DEMOSAICV3_DBPC_LEN);
cmdp_local += 1;
- msm_camera_io_memcpy(vfe32_ctrl->vfebase +
+ msm_camera_io_memcpy(vfe32_ctrl->share_ctrl->vfebase +
V32_DEMOSAICV3_DBPC_CFG_OFF0,
cmdp_local, V32_DEMOSAICV3_DBPC_LEN);
cmdp_local += 1;
- msm_camera_io_memcpy(vfe32_ctrl->vfebase +
+ msm_camera_io_memcpy(vfe32_ctrl->share_ctrl->vfebase +
V32_DEMOSAICV3_DBPC_CFG_OFF1,
cmdp_local, V32_DEMOSAICV3_DBPC_LEN);
cmdp_local += 1;
- msm_camera_io_memcpy(vfe32_ctrl->vfebase +
+ msm_camera_io_memcpy(vfe32_ctrl->share_ctrl->vfebase +
V32_DEMOSAICV3_DBPC_CFG_OFF2,
cmdp_local, V32_DEMOSAICV3_DBPC_LEN);
break;
@@ -2002,13 +2198,14 @@
rc = -EFAULT;
goto proc_general_done;
}
- msm_camera_io_memcpy(vfe32_ctrl->vfebase + V32_RGB_G_OFF,
+ msm_camera_io_memcpy(
+ vfe32_ctrl->share_ctrl->vfebase + V32_RGB_G_OFF,
cmdp, 4);
cmdp += 1;
- vfe32_write_gamma_cfg(RGBLUT_RAM_CH0_BANK0, cmdp);
- vfe32_write_gamma_cfg(RGBLUT_RAM_CH1_BANK0, cmdp);
- vfe32_write_gamma_cfg(RGBLUT_RAM_CH2_BANK0, cmdp);
+ vfe32_write_gamma_cfg(RGBLUT_RAM_CH0_BANK0, cmdp, vfe32_ctrl);
+ vfe32_write_gamma_cfg(RGBLUT_RAM_CH1_BANK0, cmdp, vfe32_ctrl);
+ vfe32_write_gamma_cfg(RGBLUT_RAM_CH2_BANK0, cmdp, vfe32_ctrl);
}
cmdp -= 1;
break;
@@ -2025,16 +2222,23 @@
goto proc_general_done;
}
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase + V32_RGB_G_OFF);
+ old_val = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + V32_RGB_G_OFF);
cmdp += 1;
if (old_val != 0x0) {
- vfe32_write_gamma_cfg(RGBLUT_RAM_CH0_BANK0, cmdp);
- vfe32_write_gamma_cfg(RGBLUT_RAM_CH1_BANK0, cmdp);
- vfe32_write_gamma_cfg(RGBLUT_RAM_CH2_BANK0, cmdp);
+ vfe32_write_gamma_cfg(
+ RGBLUT_RAM_CH0_BANK0, cmdp, vfe32_ctrl);
+ vfe32_write_gamma_cfg(
+ RGBLUT_RAM_CH1_BANK0, cmdp, vfe32_ctrl);
+ vfe32_write_gamma_cfg(
+ RGBLUT_RAM_CH2_BANK0, cmdp, vfe32_ctrl);
} else {
- vfe32_write_gamma_cfg(RGBLUT_RAM_CH0_BANK1, cmdp);
- vfe32_write_gamma_cfg(RGBLUT_RAM_CH1_BANK1, cmdp);
- vfe32_write_gamma_cfg(RGBLUT_RAM_CH2_BANK1, cmdp);
+ vfe32_write_gamma_cfg(
+ RGBLUT_RAM_CH0_BANK1, cmdp, vfe32_ctrl);
+ vfe32_write_gamma_cfg(
+ RGBLUT_RAM_CH1_BANK1, cmdp, vfe32_ctrl);
+ vfe32_write_gamma_cfg(
+ RGBLUT_RAM_CH2_BANK1, cmdp, vfe32_ctrl);
}
}
vfe32_ctrl->update_gamma = TRUE;
@@ -2054,12 +2258,14 @@
}
cmdp_local = cmdp;
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase + V32_RGB_G_OFF);
+ old_val = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + V32_RGB_G_OFF);
temp2 = old_val ? RGBLUT_RAM_CH0_BANK1 :
RGBLUT_RAM_CH0_BANK0;
for (i = 0; i < 3; i++) {
vfe32_read_gamma_cfg(temp2,
- cmdp_local + (VFE32_GAMMA_NUM_ENTRIES * i));
+ cmdp_local + (VFE32_GAMMA_NUM_ENTRIES * i),
+ vfe32_ctrl);
temp2 += 2;
}
if (copy_to_user((void __user *)(cmd->value), cmdp,
@@ -2070,54 +2276,60 @@
break;
case VFE_CMD_STATS_AWB_STOP: {
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
old_val &= ~AWB_ENABLE_MASK;
msm_camera_io_w(old_val,
- vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
}
break;
case VFE_CMD_STATS_AE_STOP: {
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
old_val &= ~AE_BG_ENABLE_MASK;
msm_camera_io_w(old_val,
- vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
}
break;
case VFE_CMD_STATS_AF_STOP: {
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
old_val &= ~AF_BF_ENABLE_MASK;
msm_camera_io_w(old_val,
- vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
}
break;
case VFE_CMD_STATS_IHIST_STOP: {
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
old_val &= ~IHIST_ENABLE_MASK;
msm_camera_io_w(old_val,
- vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
}
break;
case VFE_CMD_STATS_RS_STOP: {
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
old_val &= ~RS_ENABLE_MASK;
msm_camera_io_w(old_val,
- vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
}
break;
case VFE_CMD_STATS_CS_STOP: {
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
old_val &= ~CS_ENABLE_MASK;
msm_camera_io_w(old_val,
- vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
}
break;
case VFE_CMD_STOP:
pr_info("vfe32_proc_general: cmdID = %s\n",
vfe32_general_cmd[cmd->id]);
- vfe32_stop();
+ vfe32_stop(vfe32_ctrl);
break;
case VFE_CMD_SYNC_TIMER_SETTING:
@@ -2131,7 +2343,7 @@
rc = -EFAULT;
goto proc_general_done;
}
- vfe32_sync_timer_start(cmdp);
+ vfe32_sync_timer_start(cmdp, vfe32_ctrl);
break;
case VFE_CMD_MODULE_CFG: {
@@ -2147,27 +2359,29 @@
goto proc_general_done;
}
*cmdp &= ~STATS_ENABLE_MASK;
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_MODULE_CFG);
+ old_val = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + VFE_MODULE_CFG);
old_val &= STATS_ENABLE_MASK;
*cmdp |= old_val;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_cmd[cmd->id].offset,
cmdp, (vfe32_cmd[cmd->id].length));
}
break;
case VFE_CMD_ZSL:
rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_START,
- VFE_MSG_OUTPUT_PRIMARY);
+ VFE_MSG_OUTPUT_PRIMARY, vfe32_ctrl);
if (rc < 0)
goto proc_general_done;
rc = vfe32_configure_pingpong_buffers(VFE_MSG_V32_START,
- VFE_MSG_OUTPUT_SECONDARY);
+ VFE_MSG_OUTPUT_SECONDARY, vfe32_ctrl);
if (rc < 0)
goto proc_general_done;
- rc = vfe32_zsl(pmctl);
+ rc = vfe32_zsl(pmctl, vfe32_ctrl);
break;
case VFE_CMD_ASF_CFG:
@@ -2183,11 +2397,13 @@
goto proc_general_done;
}
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_cmd[cmd->id].offset,
cmdp, (vfe32_cmd[cmd->id].length));
cmdp_local = cmdp + V32_ASF_LEN/4;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + V32_ASF_SPECIAL_EFX_CFG_OFF,
+ vfe32_ctrl->share_ctrl->vfebase +
+ V32_ASF_SPECIAL_EFX_CFG_OFF,
cmdp_local, V32_ASF_SPECIAL_EFX_CFG_LEN);
break;
@@ -2209,37 +2425,44 @@
cmdp_local++;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + V33_PCA_ROLL_OFF_CFG_OFF1,
+ vfe32_ctrl->share_ctrl->vfebase +
+ V33_PCA_ROLL_OFF_CFG_OFF1,
cmdp_local, V33_PCA_ROLL_OFF_CFG_LEN1);
cmdp_local += 4;
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + V33_PCA_ROLL_OFF_CFG_OFF2,
+ vfe32_ctrl->share_ctrl->vfebase +
+ V33_PCA_ROLL_OFF_CFG_OFF2,
cmdp_local, V33_PCA_ROLL_OFF_CFG_LEN2);
cmdp_local += 3;
CDBG("%s: start writing RollOff Ram0 table\n", __func__);
- vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0);
- msm_camera_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+ vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0, vfe32_ctrl);
+ msm_camera_io_w(temp1,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_ADDR);
for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
msm_camera_io_w(*(cmdp_local + 1),
- vfe32_ctrl->vfebase + VFE33_DMI_DATA_HI);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE33_DMI_DATA_HI);
msm_camera_io_w(*cmdp_local,
- vfe32_ctrl->vfebase + VFE33_DMI_DATA_LO);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE33_DMI_DATA_LO);
cmdp_local += 2;
}
CDBG("%s: end writing RollOff Ram0 table\n", __func__);
CDBG("%s: start writing RollOff Ram1 table\n", __func__);
- vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0);
- msm_camera_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+ vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0, vfe32_ctrl);
+ msm_camera_io_w(temp1,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_ADDR);
for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
msm_camera_io_w(*cmdp_local,
- vfe32_ctrl->vfebase + VFE33_DMI_DATA_LO);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE33_DMI_DATA_LO);
cmdp_local += 2;
}
CDBG("%s: end writing RollOff Ram1 table\n", __func__);
- vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+ vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
break;
case VFE_CMD_PCA_ROLL_OFF_UPDATE:
@@ -2259,41 +2482,46 @@
temp1 = *cmdp_local;
cmdp_local += 8;
- temp2 = msm_camera_io_r(vfe32_ctrl->vfebase +
+ temp2 = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
V33_PCA_ROLL_OFF_CFG_OFF1)
& V33_PCA_ROLL_OFF_LUT_BANK_SEL_MASK;
CDBG("%s: start writing RollOff Ram0 table\n", __func__);
if (temp2)
- vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0);
+ vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0, vfe32_ctrl);
else
- vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK1);
+ vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK1, vfe32_ctrl);
- msm_camera_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+ msm_camera_io_w(temp1,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_ADDR);
for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
msm_camera_io_w(*(cmdp_local + 1),
- vfe32_ctrl->vfebase + VFE33_DMI_DATA_HI);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE33_DMI_DATA_HI);
msm_camera_io_w(*cmdp_local,
- vfe32_ctrl->vfebase + VFE33_DMI_DATA_LO);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE33_DMI_DATA_LO);
cmdp_local += 2;
}
CDBG("%s: end writing RollOff Ram0 table\n", __func__);
CDBG("%s: start writing RollOff Ram1 table\n", __func__);
if (temp2)
- vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0);
+ vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0, vfe32_ctrl);
else
- vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK1);
+ vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK1, vfe32_ctrl);
- msm_camera_io_w(temp1, vfe32_ctrl->vfebase + VFE_DMI_ADDR);
+ msm_camera_io_w(temp1,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_DMI_ADDR);
for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE ; i++) {
msm_camera_io_w(*cmdp_local,
- vfe32_ctrl->vfebase + VFE33_DMI_DATA_LO);
+ vfe32_ctrl->share_ctrl->vfebase +
+ VFE33_DMI_DATA_LO);
cmdp_local += 2;
}
CDBG("%s: end writing RollOff Ram1 table\n", __func__);
- vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+ vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
vfe32_ctrl->update_rolloff = true;
break;
case VFE_CMD_GET_PCA_ROLLOFF_TABLE:
@@ -2308,33 +2536,37 @@
goto proc_general_done;
}
cmdp_local = cmdp;
- old_val = msm_camera_io_r(vfe32_ctrl->vfebase +
+ old_val = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
V33_PCA_ROLL_OFF_CFG_OFF1) &
V33_PCA_ROLL_OFF_LUT_BANK_SEL_MASK;
if (old_val)
- vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK1);
+ vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK1, vfe32_ctrl);
else
- vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0);
+ vfe32_program_dmi_cfg(ROLLOFF_RAM0_BANK0, vfe32_ctrl);
CDBG("%s: PCA Rolloff Ram0\n", __func__);
for (i = 0 ; i < V33_PCA_ROLL_OFF_TABLE_SIZE * 2; i++) {
temp2 = (i == (V33_PCA_ROLL_OFF_TABLE_SIZE));
if (old_val && temp2)
- vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK1);
+ vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK1,
+ vfe32_ctrl);
else if (!old_val && temp2)
- vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0);
+ vfe32_program_dmi_cfg(ROLLOFF_RAM1_BANK0,
+ vfe32_ctrl);
- *cmdp_local = msm_camera_io_r(vfe32_ctrl->vfebase +
+ *cmdp_local = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase +
VFE33_DMI_DATA_LO);
*(cmdp_local + 1) =
- msm_camera_io_r(vfe32_ctrl->vfebase +
+ msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase +
VFE33_DMI_DATA_HI);
CDBG("%s: %08x%08x\n", __func__,
*(cmdp_local + 1), *cmdp_local);
cmdp_local += 2;
}
- vfe32_program_dmi_cfg(NO_MEM_SELECTED);
+ vfe32_program_dmi_cfg(NO_MEM_SELECTED, vfe32_ctrl);
if (copy_to_user((void __user *)(cmd->value), cmdp,
temp1)) {
rc = -EFAULT;
@@ -2352,7 +2584,7 @@
goto proc_general_done;
}
*cmdp = msm_camera_io_r(
- vfe32_ctrl->vfebase+V32_GET_HW_VERSION_OFF);
+ vfe32_ctrl->share_ctrl->vfebase+V32_GET_HW_VERSION_OFF);
if (copy_to_user((void __user *)(cmd->value), cmdp,
V32_GET_HW_VERSION_LEN)) {
rc = -EFAULT;
@@ -2360,7 +2592,8 @@
}
break;
case VFE_CMD_GET_REG_DUMP:
- temp1 = sizeof(uint32_t) * vfe32_ctrl->register_total;
+ temp1 = sizeof(uint32_t) *
+ vfe32_ctrl->share_ctrl->register_total;
if (cmd->length != temp1) {
rc = -EINVAL;
goto proc_general_done;
@@ -2370,11 +2603,12 @@
rc = -ENOMEM;
goto proc_general_done;
}
- msm_camera_io_dump(
- vfe32_ctrl->vfebase, vfe32_ctrl->register_total*4);
+ msm_camera_io_dump(vfe32_ctrl->share_ctrl->vfebase,
+ vfe32_ctrl->share_ctrl->register_total*4);
CDBG("%s: %p %p %d\n", __func__, (void *)cmdp,
- vfe32_ctrl->vfebase, temp1);
- memcpy_fromio((void *)cmdp, vfe32_ctrl->vfebase, temp1);
+ vfe32_ctrl->share_ctrl->vfebase, temp1);
+ memcpy_fromio((void *)cmdp,
+ vfe32_ctrl->share_ctrl->vfebase, temp1);
if (copy_to_user((void __user *)(cmd->value), cmdp, temp1)) {
rc = -EFAULT;
goto proc_general_done;
@@ -2399,7 +2633,8 @@
}
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_cmd[cmd->id].offset,
cmdp, (vfe32_cmd[cmd->id].length));
vfe32_ctrl->frame_skip_cnt = ((uint32_t)
*cmdp & VFE_FRAME_SKIP_PERIOD_MASK) + 1;
@@ -2423,7 +2658,8 @@
goto proc_general_done;
}
msm_camera_io_memcpy(
- vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ vfe32_ctrl->share_ctrl->vfebase +
+ vfe32_cmd[cmd->id].offset,
cmdp, (vfe32_cmd[cmd->id].length));
break;
@@ -2435,10 +2671,11 @@
return rc;
}
-static void vfe32_stats_af_ack(struct vfe_cmd_stats_ack *pAck)
+static void vfe32_stats_af_ack(
+ struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_ack *pAck)
{
unsigned long flags;
- spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ spinlock_t *lock = (vfe32_ctrl->share_ctrl->stats_comp ?
&vfe32_ctrl->comp_stats_ack_lock :
&vfe32_ctrl->af_ack_lock);
spin_lock_irqsave(lock, flags);
@@ -2447,10 +2684,11 @@
spin_unlock_irqrestore(lock, flags);
}
-static void vfe32_stats_awb_ack(struct vfe_cmd_stats_ack *pAck)
+static void vfe32_stats_awb_ack(
+ struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_ack *pAck)
{
unsigned long flags;
- spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ spinlock_t *lock = (vfe32_ctrl->share_ctrl->stats_comp ?
&vfe32_ctrl->comp_stats_ack_lock :
&vfe32_ctrl->awb_ack_lock);
spin_lock_irqsave(lock, flags);
@@ -2459,10 +2697,11 @@
spin_unlock_irqrestore(lock, flags);
}
-static void vfe32_stats_aec_ack(struct vfe_cmd_stats_ack *pAck)
+static void vfe32_stats_aec_ack(
+ struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_ack *pAck)
{
unsigned long flags;
- spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ spinlock_t *lock = (vfe32_ctrl->share_ctrl->stats_comp ?
&vfe32_ctrl->comp_stats_ack_lock :
&vfe32_ctrl->aec_ack_lock);
spin_lock_irqsave(lock, flags);
@@ -2471,10 +2710,11 @@
spin_unlock_irqrestore(lock, flags);
}
-static void vfe32_stats_ihist_ack(struct vfe_cmd_stats_ack *pAck)
+static void vfe32_stats_ihist_ack(
+ struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_ack *pAck)
{
unsigned long flags;
- spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ spinlock_t *lock = (vfe32_ctrl->share_ctrl->stats_comp ?
&vfe32_ctrl->comp_stats_ack_lock :
&vfe32_ctrl->ihist_ack_lock);
spin_lock_irqsave(lock, flags);
@@ -2482,10 +2722,11 @@
vfe32_ctrl->ihistStatsControl.ackPending = FALSE;
spin_unlock_irqrestore(lock, flags);
}
-static void vfe32_stats_rs_ack(struct vfe_cmd_stats_ack *pAck)
+static void vfe32_stats_rs_ack(
+ struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_ack *pAck)
{
unsigned long flags;
- spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ spinlock_t *lock = (vfe32_ctrl->share_ctrl->stats_comp ?
&vfe32_ctrl->comp_stats_ack_lock :
&vfe32_ctrl->rs_ack_lock);
spin_lock_irqsave(lock, flags);
@@ -2493,10 +2734,11 @@
vfe32_ctrl->rsStatsControl.ackPending = FALSE;
spin_unlock_irqrestore(lock, flags);
}
-static void vfe32_stats_cs_ack(struct vfe_cmd_stats_ack *pAck)
+static void vfe32_stats_cs_ack(
+ struct vfe32_ctrl_type *vfe32_ctrl, struct vfe_cmd_stats_ack *pAck)
{
unsigned long flags;
- spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ spinlock_t *lock = (vfe32_ctrl->share_ctrl->stats_comp ?
&vfe32_ctrl->comp_stats_ack_lock :
&vfe32_ctrl->cs_ack_lock);
spin_lock_irqsave(lock, flags);
@@ -2505,73 +2747,85 @@
spin_unlock_irqrestore(lock, flags);
}
-static inline void vfe32_read_irq_status(struct vfe32_irq_status *out)
+static inline void vfe32_read_irq_status(
+ struct axi_ctrl_t *axi_ctrl, struct vfe32_irq_status *out)
{
uint32_t *temp;
memset(out, 0, sizeof(struct vfe32_irq_status));
- temp = (uint32_t *)(vfe32_ctrl->vfebase + VFE_IRQ_STATUS_0);
+ temp = (uint32_t *)(axi_ctrl->share_ctrl->vfebase + VFE_IRQ_STATUS_0);
out->vfeIrqStatus0 = msm_camera_io_r(temp);
- temp = (uint32_t *)(vfe32_ctrl->vfebase + VFE_IRQ_STATUS_1);
+ temp = (uint32_t *)(axi_ctrl->share_ctrl->vfebase + VFE_IRQ_STATUS_1);
out->vfeIrqStatus1 = msm_camera_io_r(temp);
- temp = (uint32_t *)(vfe32_ctrl->vfebase + VFE_CAMIF_STATUS);
+ temp = (uint32_t *)(axi_ctrl->share_ctrl->vfebase + VFE_CAMIF_STATUS);
out->camifStatus = msm_camera_io_r(temp);
CDBG("camifStatus = 0x%x\n", out->camifStatus);
/* clear the pending interrupt of the same kind.*/
msm_camera_io_w(out->vfeIrqStatus0,
- vfe32_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+ axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
msm_camera_io_w(out->vfeIrqStatus1,
- vfe32_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+ 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, vfe32_ctrl->vfebase + VFE_IRQ_CMD);
+ msm_camera_io_w_mb(1, axi_ctrl->share_ctrl->vfebase + VFE_IRQ_CMD);
}
-static void vfe32_process_reg_update_irq(void)
+static void vfe32_process_reg_update_irq(
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
unsigned long flags;
if (vfe32_ctrl->recording_state == VFE_STATE_START_REQUESTED) {
- if (vfe32_ctrl->operation_mode ==
+ if (vfe32_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
- } else if (vfe32_ctrl->operation_mode ==
+ 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->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
+ 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->recording_state = VFE_STATE_STARTED;
- msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ msm_camera_io_w_mb(1,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
CDBG("start video triggered .\n");
} else if (vfe32_ctrl->recording_state ==
VFE_STATE_STOP_REQUESTED) {
- if (vfe32_ctrl->operation_mode ==
+ if (vfe32_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
- msm_camera_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
- } else if (vfe32_ctrl->operation_mode ==
+ 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->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
+ 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");
}
if (vfe32_ctrl->start_ack_pending == TRUE) {
- vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_START_ACK);
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ vfe32_ctrl->share_ctrl->vfeFrameId, MSG_ID_START_ACK);
vfe32_ctrl->start_ack_pending = FALSE;
} else {
if (vfe32_ctrl->recording_state ==
@@ -2581,10 +2835,12 @@
* when we process the next reg update irq.
*/
msm_camera_io_w_mb(1,
- vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
} else if (vfe32_ctrl->recording_state ==
VFE_STATE_STOPPED) {
- vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_STOP_REC_ACK);
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ vfe32_ctrl->share_ctrl->vfeFrameId,
+ MSG_ID_STOP_REC_ACK);
vfe32_ctrl->recording_state = VFE_STATE_IDLE;
}
spin_lock_irqsave(&vfe32_ctrl->update_ack_lock, flags);
@@ -2592,80 +2848,102 @@
vfe32_ctrl->update_ack_pending = FALSE;
spin_unlock_irqrestore(
&vfe32_ctrl->update_ack_lock, flags);
- vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_UPDATE_ACK);
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ vfe32_ctrl->share_ctrl->vfeFrameId,
+ MSG_ID_UPDATE_ACK);
} else {
spin_unlock_irqrestore(
&vfe32_ctrl->update_ack_lock, flags);
}
}
- if (vfe32_ctrl->liveshot_state == VFE_STATE_START_REQUESTED) {
+ if (vfe32_ctrl->share_ctrl->liveshot_state ==
+ VFE_STATE_START_REQUESTED) {
pr_info("%s enabling liveshot output\n", __func__);
- if (vfe32_ctrl->outpath.output_mode &
+ if (vfe32_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
- vfe32_ctrl->liveshot_state = VFE_STATE_STARTED;
+ 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]);
+ vfe32_ctrl->share_ctrl->liveshot_state =
+ VFE_STATE_STARTED;
}
}
- if (vfe32_ctrl->liveshot_state == VFE_STATE_STARTED) {
- vfe32_ctrl->vfe_capture_count--;
- if (!vfe32_ctrl->vfe_capture_count)
- vfe32_ctrl->liveshot_state = VFE_STATE_STOP_REQUESTED;
- msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
- } else if (vfe32_ctrl->liveshot_state == VFE_STATE_STOP_REQUESTED) {
+ if (vfe32_ctrl->share_ctrl->liveshot_state == VFE_STATE_STARTED) {
+ vfe32_ctrl->share_ctrl->vfe_capture_count--;
+ if (!vfe32_ctrl->share_ctrl->vfe_capture_count)
+ vfe32_ctrl->share_ctrl->liveshot_state =
+ VFE_STATE_STOP_REQUESTED;
+ msm_camera_io_w_mb(1, vfe32_ctrl->
+ share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ } else if (vfe32_ctrl->share_ctrl->liveshot_state ==
+ VFE_STATE_STOP_REQUESTED) {
CDBG("%s: disabling liveshot output\n", __func__);
- if (vfe32_ctrl->outpath.output_mode &
+ if (vfe32_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
- vfe32_ctrl->liveshot_state = VFE_STATE_STOPPED;
- msm_camera_io_w_mb(1, vfe32_ctrl->vfebase +
+ 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);
}
- } else if (vfe32_ctrl->liveshot_state == VFE_STATE_STOPPED) {
- vfe32_ctrl->liveshot_state = VFE_STATE_IDLE;
+ } else if (vfe32_ctrl->share_ctrl->liveshot_state ==
+ VFE_STATE_STOPPED) {
+ vfe32_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
}
- if ((vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN) ||
- (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB) ||
- (vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG) ||
- (vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB)) {
+ 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->vfe_capture_count--;
+ vfe32_ctrl->share_ctrl->vfe_capture_count--;
/* if last frame to be captured: */
- if (vfe32_ctrl->vfe_capture_count == 0) {
+ if (vfe32_ctrl->share_ctrl->vfe_capture_count == 0) {
/* stop the bus output:write master enable = 0*/
- if (vfe32_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(0, vfe32_ctrl->vfebase +
+ 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->
- outpath.out0.ch0]);
- msm_camera_io_w(0, vfe32_ctrl->vfebase +
+ share_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(0,
+ vfe32_ctrl->share_ctrl->vfebase+
vfe32_AXI_WM_CFG[vfe32_ctrl->
- outpath.out0.ch1]);
+ share_ctrl->outpath.out0.ch1]);
}
- if (vfe32_ctrl->outpath.output_mode &
+ if (vfe32_ctrl->share_ctrl->outpath.output_mode&
VFE32_OUTPUT_MODE_SECONDARY) {
- msm_camera_io_w(0, vfe32_ctrl->vfebase +
+ msm_camera_io_w(0,
+ vfe32_ctrl->share_ctrl->vfebase+
vfe32_AXI_WM_CFG[vfe32_ctrl->
- outpath.out1.ch0]);
- msm_camera_io_w(0, vfe32_ctrl->vfebase +
+ share_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(0,
+ vfe32_ctrl->share_ctrl->vfebase+
vfe32_AXI_WM_CFG[vfe32_ctrl->
- outpath.out1.ch1]);
+ share_ctrl->outpath.out1.ch1]);
}
msm_camera_io_w_mb
(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
- vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
+ 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;
@@ -2673,116 +2951,143 @@
} /*if frame is not being dropped*/
vfe32_ctrl->snapshot_frame_cnt++;
/* then do reg_update. */
- msm_camera_io_w(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ msm_camera_io_w(1,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_REG_UPDATE_CMD);
} /* if snapshot mode. */
}
-static void vfe32_set_default_reg_values(void)
+static void vfe32_set_default_reg_values(
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
- msm_camera_io_w(0x800080, vfe32_ctrl->vfebase + VFE_DEMUX_GAIN_0);
- msm_camera_io_w(0x800080, vfe32_ctrl->vfebase + VFE_DEMUX_GAIN_1);
+ 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->vfebase + VFE_CGC_OVERRIDE);
+ 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->vfebase + VFE_FRAMEDROP_ENC_Y_CFG);
- msm_camera_io_w(0x1f, vfe32_ctrl->vfebase + VFE_FRAMEDROP_ENC_CBCR_CFG);
+ 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->vfebase + VFE_FRAMEDROP_ENC_Y_PATTERN);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_ENC_Y_PATTERN);
msm_camera_io_w(0xFFFFFFFF,
- vfe32_ctrl->vfebase + VFE_FRAMEDROP_ENC_CBCR_PATTERN);
- msm_camera_io_w(0x1f, vfe32_ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y);
- msm_camera_io_w(0x1f, vfe32_ctrl->vfebase + VFE_FRAMEDROP_VIEW_CBCR);
+ 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->vfebase + VFE_FRAMEDROP_VIEW_Y_PATTERN);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_FRAMEDROP_VIEW_Y_PATTERN);
msm_camera_io_w(0xFFFFFFFF,
- vfe32_ctrl->vfebase + VFE_FRAMEDROP_VIEW_CBCR_PATTERN);
- msm_camera_io_w(0, vfe32_ctrl->vfebase + VFE_CLAMP_MIN);
- msm_camera_io_w(0xFFFFFF, vfe32_ctrl->vfebase + VFE_CLAMP_MAX);
+ 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 */
msm_camera_io_w(0x3980007,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_AEC_UB_CFG);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_AEC_UB_CFG);
msm_camera_io_w(0x3A00007,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_AF_UB_CFG);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_AF_UB_CFG);
msm_camera_io_w(0x3A8000F,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_AWB_UB_CFG);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_AWB_UB_CFG);
msm_camera_io_w(0x3B80007,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_RS_UB_CFG);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_RS_UB_CFG);
msm_camera_io_w(0x3C0001F,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_CS_UB_CFG);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_CS_UB_CFG);
msm_camera_io_w(0x3E0001F,
- vfe32_ctrl->vfebase + VFE_BUS_STATS_HIST_UB_CFG);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_STATS_HIST_UB_CFG);
}
-static void vfe32_process_reset_irq(void)
+static void vfe32_process_reset_irq(
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
unsigned long flags;
- atomic_set(&vfe32_ctrl->vstate, 0);
+ atomic_set(&vfe32_ctrl->share_ctrl->vstate, 0);
- spin_lock_irqsave(&vfe32_ctrl->stop_flag_lock, flags);
- if (vfe32_ctrl->stop_ack_pending) {
- vfe32_ctrl->stop_ack_pending = FALSE;
- spin_unlock_irqrestore(&vfe32_ctrl->stop_flag_lock, flags);
- vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_STOP_ACK);
+ 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);
} else {
- spin_unlock_irqrestore(&vfe32_ctrl->stop_flag_lock, flags);
+ spin_unlock_irqrestore(
+ &vfe32_ctrl->share_ctrl->stop_flag_lock, flags);
/* this is from reset command. */
- vfe32_set_default_reg_values();
+ vfe32_set_default_reg_values(vfe32_ctrl);
/* reload all write masters. (frame & line)*/
- msm_camera_io_w(0x7FFF, vfe32_ctrl->vfebase + VFE_BUS_CMD);
- vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_RESET_ACK);
+ msm_camera_io_w(0x7FFF,
+ vfe32_ctrl->share_ctrl->vfebase + VFE_BUS_CMD);
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ vfe32_ctrl->share_ctrl->vfeFrameId, MSG_ID_RESET_ACK);
}
}
-static void vfe32_process_camif_sof_irq(void)
+static void vfe32_process_camif_sof_irq(
+ struct vfe32_ctrl_type *vfe32_ctrl)
{
- if (vfe32_ctrl->operation_mode ==
+ if (vfe32_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_RAW) {
if (vfe32_ctrl->start_ack_pending) {
- vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_START_ACK);
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ vfe32_ctrl->share_ctrl->vfeFrameId,
+ MSG_ID_START_ACK);
vfe32_ctrl->start_ack_pending = FALSE;
}
- vfe32_ctrl->vfe_capture_count--;
+ vfe32_ctrl->share_ctrl->vfe_capture_count--;
/* if last frame to be captured: */
- if (vfe32_ctrl->vfe_capture_count == 0) {
+ if (vfe32_ctrl->share_ctrl->vfe_capture_count == 0) {
/* Ensure the write order while writing
to the command register using the barrier */
msm_camera_io_w_mb(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
- vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
+ vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
}
} /* if raw snapshot mode. */
if ((vfe32_ctrl->hfr_mode != HFR_MODE_OFF) &&
- (vfe32_ctrl->operation_mode == VFE_MODE_OF_OPERATION_VIDEO) &&
- (vfe32_ctrl->vfeFrameId % vfe32_ctrl->hfr_mode != 0)) {
- vfe32_ctrl->vfeFrameId++;
+ (vfe32_ctrl->share_ctrl->operation_mode ==
+ VFE_MODE_OF_OPERATION_VIDEO) &&
+ (vfe32_ctrl->share_ctrl->vfeFrameId %
+ vfe32_ctrl->hfr_mode != 0)) {
+ vfe32_ctrl->share_ctrl->vfeFrameId++;
CDBG("Skip the SOF notification when HFR enabled\n");
return;
}
- vfe32_ctrl->vfeFrameId++;
- vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_SOF_ACK);
- CDBG("camif_sof_irq, frameId = %d\n", vfe32_ctrl->vfeFrameId);
+ vfe32_ctrl->share_ctrl->vfeFrameId++;
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ vfe32_ctrl->share_ctrl->vfeFrameId, MSG_ID_SOF_ACK);
+ CDBG("camif_sof_irq, frameId = %d\n",
+ vfe32_ctrl->share_ctrl->vfeFrameId);
if (vfe32_ctrl->sync_timer_state) {
if (vfe32_ctrl->sync_timer_repeat_count == 0)
- vfe32_sync_timer_stop();
+ vfe32_sync_timer_stop(vfe32_ctrl);
else
vfe32_ctrl->sync_timer_repeat_count--;
}
}
-static void vfe32_process_error_irq(uint32_t errStatus)
+static void vfe32_process_error_irq(
+ struct axi_ctrl_t *axi_ctrl, uint32_t errStatus)
{
uint32_t reg_value;
if (errStatus & VFE32_IMASK_CAMIF_ERROR) {
pr_err("vfe32_irq: camif errors\n");
reg_value = msm_camera_io_r(
- vfe32_ctrl->vfebase + VFE_CAMIF_STATUS);
+ axi_ctrl->share_ctrl->vfebase + VFE_CAMIF_STATUS);
pr_err("camifStatus = 0x%x\n", reg_value);
- vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_CAMIF_ERROR);
+ vfe32_send_isp_msg(&axi_ctrl->subdev,
+ axi_ctrl->share_ctrl->vfeFrameId, MSG_ID_CAMIF_ERROR);
}
if (errStatus & VFE32_IMASK_BHIST_OVWR)
@@ -2806,7 +3111,7 @@
if (errStatus & VFE32_IMASK_VIOLATION) {
pr_err("vfe32_irq: violation interrupt\n");
reg_value = msm_camera_io_r(
- vfe32_ctrl->vfebase + VFE_VIOLATION_STATUS);
+ axi_ctrl->share_ctrl->vfebase + VFE_VIOLATION_STATUS);
pr_err("%s: violationStatus = 0x%x\n", __func__, reg_value);
}
@@ -2856,7 +3161,8 @@
pr_err("vfe32_irq: axi error\n");
}
-static void vfe_send_outmsg(struct v4l2_subdev *sd, uint8_t msgid,
+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)
{
struct isp_msg_output msg;
@@ -2865,15 +3171,16 @@
msg.buf.ch_paddr[0] = ch0_paddr;
msg.buf.ch_paddr[1] = ch1_paddr;
msg.buf.ch_paddr[2] = ch2_paddr;
- msg.frameCounter = vfe32_ctrl->vfeFrameId;
+ msg.frameCounter = axi_ctrl->share_ctrl->vfeFrameId;
- v4l2_subdev_notify(&vfe32_ctrl->subdev,
+ v4l2_subdev_notify(&axi_ctrl->subdev,
NOTIFY_VFE_MSG_OUT,
&msg);
return;
}
-static void vfe32_process_output_path_irq_0(void)
+static void vfe32_process_output_path_irq_0(
+ struct axi_ctrl_t *axi_ctrl)
{
uint32_t ping_pong;
uint32_t ch0_paddr, ch1_paddr, ch2_paddr;
@@ -2881,7 +3188,7 @@
struct msm_free_buf *free_buf = NULL;
free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
- VFE_MSG_OUTPUT_PRIMARY);
+ VFE_MSG_OUTPUT_PRIMARY, axi_ctrl);
/* we render frames in the following conditions:
1. Continuous mode and the free buffer is avaialable.
@@ -2889,73 +3196,91 @@
when pending snapshot count is <=1, then no need to use
free buffer.
*/
- out_bool = ((vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_MAIN ||
- vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
- vfe32_ctrl->operation_mode == VFE_OUTPUTS_THUMB_AND_JPEG ||
- vfe32_ctrl->operation_mode == VFE_OUTPUTS_JPEG_AND_THUMB ||
- vfe32_ctrl->operation_mode == VFE_OUTPUTS_RAW ||
- vfe32_ctrl->liveshot_state == VFE_STATE_STARTED ||
- vfe32_ctrl->liveshot_state == VFE_STATE_STOP_REQUESTED ||
- vfe32_ctrl->liveshot_state == VFE_STATE_STOPPED) &&
- (vfe32_ctrl->vfe_capture_count <= 1)) || free_buf;
+ 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 (out_bool) {
- ping_pong = msm_camera_io_r(vfe32_ctrl->vfebase +
+ ping_pong = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
VFE_BUS_PING_PONG_STATUS);
/* Channel 0*/
- ch0_paddr = vfe32_get_ch_addr(ping_pong,
- vfe32_ctrl->outpath.out0.ch0);
+ ch0_paddr = vfe32_get_ch_addr(
+ ping_pong, axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out0.ch0);
/* Channel 1*/
- ch1_paddr = vfe32_get_ch_addr(ping_pong,
- vfe32_ctrl->outpath.out0.ch1);
+ ch1_paddr = vfe32_get_ch_addr(
+ ping_pong, axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out0.ch1);
/* Channel 2*/
- ch2_paddr = vfe32_get_ch_addr(ping_pong,
- vfe32_ctrl->outpath.out0.ch2);
+ ch2_paddr = vfe32_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 */
vfe32_put_ch_addr(ping_pong,
- vfe32_ctrl->outpath.out0.ch0,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out0.ch0,
free_buf->ch_paddr[0]);
/* Chroma channel */
vfe32_put_ch_addr(ping_pong,
- vfe32_ctrl->outpath.out0.ch1,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out0.ch1,
free_buf->ch_paddr[1]);
if (free_buf->num_planes > 2)
vfe32_put_ch_addr(ping_pong,
- vfe32_ctrl->outpath.out0.ch2,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out0.ch2,
free_buf->ch_paddr[2]);
}
- if (vfe32_ctrl->operation_mode ==
+ if (axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_THUMB_AND_MAIN ||
- vfe32_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_MAIN_AND_THUMB ||
- vfe32_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_THUMB_AND_JPEG ||
- vfe32_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_JPEG_AND_THUMB ||
- vfe32_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_RAW ||
- vfe32_ctrl->liveshot_state == VFE_STATE_STOPPED)
- vfe32_ctrl->outpath.out0.capture_cnt--;
+ axi_ctrl->share_ctrl->liveshot_state ==
+ VFE_STATE_STOPPED)
+ axi_ctrl->share_ctrl->outpath.out0.capture_cnt--;
- vfe_send_outmsg(&vfe32_ctrl->subdev,
+ vfe_send_outmsg(axi_ctrl,
MSG_ID_OUTPUT_PRIMARY, ch0_paddr,
ch1_paddr, ch2_paddr);
- if (vfe32_ctrl->liveshot_state == VFE_STATE_STOPPED)
- vfe32_ctrl->liveshot_state = VFE_STATE_IDLE;
+ if (axi_ctrl->share_ctrl->liveshot_state == VFE_STATE_STOPPED)
+ axi_ctrl->share_ctrl->liveshot_state = VFE_STATE_IDLE;
} else {
- vfe32_ctrl->outpath.out0.frame_drop_cnt++;
+ axi_ctrl->share_ctrl->outpath.out0.frame_drop_cnt++;
CDBG("path_irq_0 - no free buffer!\n");
}
}
-static void vfe32_process_output_path_irq_1(void)
+static void vfe32_process_output_path_irq_1(
+ struct axi_ctrl_t *axi_ctrl)
{
uint32_t ping_pong;
uint32_t ch0_paddr, ch1_paddr, ch2_paddr;
@@ -2964,81 +3289,89 @@
struct msm_free_buf *free_buf = NULL;
free_buf = vfe32_check_free_buffer(VFE_MSG_OUTPUT_IRQ,
- VFE_MSG_OUTPUT_SECONDARY);
- out_bool = ((vfe32_ctrl->operation_mode ==
+ VFE_MSG_OUTPUT_SECONDARY, axi_ctrl);
+ out_bool = ((axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_THUMB_AND_MAIN ||
- vfe32_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_MAIN_AND_THUMB ||
- vfe32_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_RAW ||
- vfe32_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_JPEG_AND_THUMB) &&
- (vfe32_ctrl->vfe_capture_count <= 1)) || free_buf;
+ (axi_ctrl->share_ctrl->vfe_capture_count <= 1)) ||
+ free_buf;
if (out_bool) {
- ping_pong = msm_camera_io_r(vfe32_ctrl->vfebase +
+ ping_pong = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
VFE_BUS_PING_PONG_STATUS);
/* Y channel */
ch0_paddr = vfe32_get_ch_addr(ping_pong,
- vfe32_ctrl->outpath.out1.ch0);
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out1.ch0);
/* Chroma channel */
ch1_paddr = vfe32_get_ch_addr(ping_pong,
- vfe32_ctrl->outpath.out1.ch1);
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out1.ch1);
ch2_paddr = vfe32_get_ch_addr(ping_pong,
- vfe32_ctrl->outpath.out1.ch2);
+ 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 */
vfe32_put_ch_addr(ping_pong,
- vfe32_ctrl->outpath.out1.ch0,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out1.ch0,
free_buf->ch_paddr[0]);
/* Chroma channel */
vfe32_put_ch_addr(ping_pong,
- vfe32_ctrl->outpath.out1.ch1,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out1.ch1,
free_buf->ch_paddr[1]);
if (free_buf->num_planes > 2)
vfe32_put_ch_addr(ping_pong,
- vfe32_ctrl->outpath.out1.ch2,
+ axi_ctrl->share_ctrl->vfebase,
+ axi_ctrl->share_ctrl->outpath.out1.ch2,
free_buf->ch_paddr[2]);
}
- if (vfe32_ctrl->operation_mode ==
+ if (axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_THUMB_AND_MAIN ||
- vfe32_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_MAIN_AND_THUMB ||
- vfe32_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_RAW ||
- vfe32_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_JPEG_AND_THUMB)
- vfe32_ctrl->outpath.out1.capture_cnt--;
+ axi_ctrl->share_ctrl->outpath.out1.capture_cnt--;
- vfe_send_outmsg(&vfe32_ctrl->subdev,
+ vfe_send_outmsg(axi_ctrl,
MSG_ID_OUTPUT_SECONDARY, ch0_paddr,
ch1_paddr, ch2_paddr);
} else {
- vfe32_ctrl->outpath.out1.frame_drop_cnt++;
+ axi_ctrl->share_ctrl->outpath.out1.frame_drop_cnt++;
CDBG("path_irq_1 - no free buffer!\n");
}
}
-static uint32_t vfe32_process_stats_irq_common(uint32_t statsNum,
- uint32_t newAddr) {
-
+static uint32_t vfe32_process_stats_irq_common(
+ struct vfe32_ctrl_type *vfe32_ctrl,
+ uint32_t statsNum, uint32_t newAddr)
+{
uint32_t pingpongStatus;
uint32_t returnAddr;
uint32_t pingpongAddr;
/* must be 0=ping, 1=pong */
pingpongStatus =
- ((msm_camera_io_r(vfe32_ctrl->vfebase +
+ ((msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
VFE_BUS_PING_PONG_STATUS))
& ((uint32_t)(1<<(statsNum + 7)))) >> (statsNum + 7);
/* stats bits starts at 7 */
CDBG("statsNum %d, pingpongStatus %d\n", statsNum, pingpongStatus);
pingpongAddr =
- ((uint32_t)(vfe32_ctrl->vfebase +
+ ((uint32_t)(vfe32_ctrl->share_ctrl->vfebase +
VFE_BUS_STATS_PING_PONG_BASE)) +
(3*statsNum)*4 + (1-pingpongStatus)*4;
returnAddr = msm_camera_io_r((uint32_t *)pingpongAddr);
@@ -3047,14 +3380,15 @@
}
static void
-vfe_send_stats_msg(uint32_t bufAddress, uint32_t statsNum)
+vfe_send_stats_msg(struct vfe32_ctrl_type *vfe32_ctrl,
+ uint32_t bufAddress, uint32_t statsNum)
{
unsigned long flags;
/* fill message with right content. */
/* @todo This is causing issues, need further investigate */
/* spin_lock_irqsave(&ctrl->state_lock, flags); */
struct isp_msg_stats msgStats;
- msgStats.frameCounter = vfe32_ctrl->vfeFrameId;
+ msgStats.frameCounter = vfe32_ctrl->share_ctrl->vfeFrameId;
msgStats.buffer = bufAddress;
switch (statsNum) {
@@ -3114,12 +3448,13 @@
return;
}
-static void vfe_send_comp_stats_msg(uint32_t status_bits)
+static void vfe_send_comp_stats_msg(
+ struct vfe32_ctrl_type *vfe32_ctrl, uint32_t status_bits)
{
struct msm_stats_buf msgStats;
uint32_t temp;
- msgStats.frame_id = vfe32_ctrl->vfeFrameId;
+ msgStats.frame_id = vfe32_ctrl->share_ctrl->vfeFrameId;
msgStats.status_bits = status_bits;
msgStats.aec.buff = vfe32_ctrl->aecStatsControl.bufToRender;
@@ -3130,7 +3465,8 @@
msgStats.rs.buff = vfe32_ctrl->rsStatsControl.bufToRender;
msgStats.cs.buff = vfe32_ctrl->csStatsControl.bufToRender;
- temp = msm_camera_io_r(vfe32_ctrl->vfebase + VFE_STATS_AWB_SGW_CFG);
+ temp = msm_camera_io_r(
+ vfe32_ctrl->share_ctrl->vfebase + VFE_STATS_AWB_SGW_CFG);
msgStats.awb_ymin = (0xFF00 & temp) >> 8;
v4l2_subdev_notify(&vfe32_ctrl->subdev,
@@ -3138,18 +3474,18 @@
&msgStats);
}
-static void vfe32_process_stats_ae_irq(void)
+static void vfe32_process_stats_ae_irq(struct vfe32_ctrl_type *vfe32_ctrl)
{
unsigned long flags;
spin_lock_irqsave(&vfe32_ctrl->aec_ack_lock, flags);
if (!(vfe32_ctrl->aecStatsControl.ackPending)) {
spin_unlock_irqrestore(&vfe32_ctrl->aec_ack_lock, flags);
vfe32_ctrl->aecStatsControl.bufToRender =
- vfe32_process_stats_irq_common(statsAeNum,
+ vfe32_process_stats_irq_common(vfe32_ctrl, statsAeNum,
vfe32_ctrl->aecStatsControl.nextFrameAddrBuf);
- vfe_send_stats_msg(vfe32_ctrl->aecStatsControl.bufToRender,
- statsAeNum);
+ vfe_send_stats_msg(vfe32_ctrl,
+ vfe32_ctrl->aecStatsControl.bufToRender, statsAeNum);
} else{
spin_unlock_irqrestore(&vfe32_ctrl->aec_ack_lock, flags);
vfe32_ctrl->aecStatsControl.droppedStatsFrameCount++;
@@ -3158,18 +3494,18 @@
}
}
-static void vfe32_process_stats_awb_irq(void)
+static void vfe32_process_stats_awb_irq(struct vfe32_ctrl_type *vfe32_ctrl)
{
unsigned long flags;
spin_lock_irqsave(&vfe32_ctrl->awb_ack_lock, flags);
if (!(vfe32_ctrl->awbStatsControl.ackPending)) {
spin_unlock_irqrestore(&vfe32_ctrl->awb_ack_lock, flags);
vfe32_ctrl->awbStatsControl.bufToRender =
- vfe32_process_stats_irq_common(statsAwbNum,
+ vfe32_process_stats_irq_common(vfe32_ctrl, statsAwbNum,
vfe32_ctrl->awbStatsControl.nextFrameAddrBuf);
- vfe_send_stats_msg(vfe32_ctrl->awbStatsControl.bufToRender,
- statsAwbNum);
+ vfe_send_stats_msg(vfe32_ctrl,
+ vfe32_ctrl->awbStatsControl.bufToRender, statsAwbNum);
} else{
spin_unlock_irqrestore(&vfe32_ctrl->awb_ack_lock, flags);
vfe32_ctrl->awbStatsControl.droppedStatsFrameCount++;
@@ -3178,18 +3514,18 @@
}
}
-static void vfe32_process_stats_af_irq(void)
+static void vfe32_process_stats_af_irq(struct vfe32_ctrl_type *vfe32_ctrl)
{
unsigned long flags;
spin_lock_irqsave(&vfe32_ctrl->af_ack_lock, flags);
if (!(vfe32_ctrl->afStatsControl.ackPending)) {
spin_unlock_irqrestore(&vfe32_ctrl->af_ack_lock, flags);
vfe32_ctrl->afStatsControl.bufToRender =
- vfe32_process_stats_irq_common(statsAfNum,
+ vfe32_process_stats_irq_common(vfe32_ctrl, statsAfNum,
vfe32_ctrl->afStatsControl.nextFrameAddrBuf);
- vfe_send_stats_msg(vfe32_ctrl->afStatsControl.bufToRender,
- statsAfNum);
+ vfe_send_stats_msg(vfe32_ctrl,
+ vfe32_ctrl->afStatsControl.bufToRender, statsAfNum);
} else{
spin_unlock_irqrestore(&vfe32_ctrl->af_ack_lock, flags);
vfe32_ctrl->afStatsControl.droppedStatsFrameCount++;
@@ -3198,15 +3534,17 @@
}
}
-static void vfe32_process_stats_ihist_irq(void)
+static void vfe32_process_stats_ihist_irq(struct vfe32_ctrl_type *vfe32_ctrl)
{
if (!(vfe32_ctrl->ihistStatsControl.ackPending)) {
vfe32_ctrl->ihistStatsControl.bufToRender =
- vfe32_process_stats_irq_common(statsIhistNum,
+ vfe32_process_stats_irq_common(
+ vfe32_ctrl, statsIhistNum,
vfe32_ctrl->ihistStatsControl.nextFrameAddrBuf);
- vfe_send_stats_msg(vfe32_ctrl->ihistStatsControl.bufToRender,
- statsIhistNum);
+ vfe_send_stats_msg(vfe32_ctrl,
+ vfe32_ctrl->ihistStatsControl.bufToRender,
+ statsIhistNum);
} else {
vfe32_ctrl->ihistStatsControl.droppedStatsFrameCount++;
CDBG("%s: droppedStatsFrameCount = %d", __func__,
@@ -3214,15 +3552,15 @@
}
}
-static void vfe32_process_stats_rs_irq(void)
+static void vfe32_process_stats_rs_irq(struct vfe32_ctrl_type *vfe32_ctrl)
{
if (!(vfe32_ctrl->rsStatsControl.ackPending)) {
vfe32_ctrl->rsStatsControl.bufToRender =
- vfe32_process_stats_irq_common(statsRsNum,
+ vfe32_process_stats_irq_common(vfe32_ctrl, statsRsNum,
vfe32_ctrl->rsStatsControl.nextFrameAddrBuf);
- vfe_send_stats_msg(vfe32_ctrl->rsStatsControl.bufToRender,
- statsRsNum);
+ vfe_send_stats_msg(vfe32_ctrl,
+ vfe32_ctrl->rsStatsControl.bufToRender, statsRsNum);
} else {
vfe32_ctrl->rsStatsControl.droppedStatsFrameCount++;
CDBG("%s: droppedStatsFrameCount = %d", __func__,
@@ -3230,15 +3568,15 @@
}
}
-static void vfe32_process_stats_cs_irq(void)
+static void vfe32_process_stats_cs_irq(struct vfe32_ctrl_type *vfe32_ctrl)
{
if (!(vfe32_ctrl->csStatsControl.ackPending)) {
vfe32_ctrl->csStatsControl.bufToRender =
- vfe32_process_stats_irq_common(statsCsNum,
+ vfe32_process_stats_irq_common(vfe32_ctrl, statsCsNum,
vfe32_ctrl->csStatsControl.nextFrameAddrBuf);
- vfe_send_stats_msg(vfe32_ctrl->csStatsControl.bufToRender,
- statsCsNum);
+ vfe_send_stats_msg(vfe32_ctrl,
+ vfe32_ctrl->csStatsControl.bufToRender, statsCsNum);
} else {
vfe32_ctrl->csStatsControl.droppedStatsFrameCount++;
CDBG("%s: droppedStatsFrameCount = %d", __func__,
@@ -3246,7 +3584,8 @@
}
}
-static void vfe32_process_stats(uint32_t status_bits)
+static void vfe32_process_stats(struct vfe32_ctrl_type *vfe32_ctrl,
+ uint32_t status_bits)
{
unsigned long flags;
int32_t process_stats = false;
@@ -3257,7 +3596,8 @@
if (!vfe32_ctrl->aecStatsControl.ackPending) {
vfe32_ctrl->aecStatsControl.ackPending = TRUE;
vfe32_ctrl->aecStatsControl.bufToRender =
- vfe32_process_stats_irq_common(statsAeNum,
+ vfe32_process_stats_irq_common(
+ vfe32_ctrl, statsAeNum,
vfe32_ctrl->aecStatsControl.nextFrameAddrBuf);
process_stats = true;
} else{
@@ -3272,7 +3612,8 @@
if (!vfe32_ctrl->awbStatsControl.ackPending) {
vfe32_ctrl->awbStatsControl.ackPending = TRUE;
vfe32_ctrl->awbStatsControl.bufToRender =
- vfe32_process_stats_irq_common(statsAwbNum,
+ vfe32_process_stats_irq_common(
+ vfe32_ctrl, statsAwbNum,
vfe32_ctrl->awbStatsControl.nextFrameAddrBuf);
process_stats = true;
} else{
@@ -3288,7 +3629,8 @@
if (!vfe32_ctrl->afStatsControl.ackPending) {
vfe32_ctrl->afStatsControl.ackPending = TRUE;
vfe32_ctrl->afStatsControl.bufToRender =
- vfe32_process_stats_irq_common(statsAfNum,
+ vfe32_process_stats_irq_common(
+ vfe32_ctrl, statsAfNum,
vfe32_ctrl->afStatsControl.nextFrameAddrBuf);
process_stats = true;
} else {
@@ -3303,7 +3645,8 @@
if (!vfe32_ctrl->ihistStatsControl.ackPending) {
vfe32_ctrl->ihistStatsControl.ackPending = TRUE;
vfe32_ctrl->ihistStatsControl.bufToRender =
- vfe32_process_stats_irq_common(statsIhistNum,
+ vfe32_process_stats_irq_common(
+ vfe32_ctrl, statsIhistNum,
vfe32_ctrl->ihistStatsControl.nextFrameAddrBuf);
process_stats = true;
} else {
@@ -3318,7 +3661,8 @@
if (!vfe32_ctrl->rsStatsControl.ackPending) {
vfe32_ctrl->rsStatsControl.ackPending = TRUE;
vfe32_ctrl->rsStatsControl.bufToRender =
- vfe32_process_stats_irq_common(statsRsNum,
+ vfe32_process_stats_irq_common(
+ vfe32_ctrl, statsRsNum,
vfe32_ctrl->rsStatsControl.nextFrameAddrBuf);
process_stats = true;
} else {
@@ -3329,12 +3673,12 @@
vfe32_ctrl->rsStatsControl.bufToRender = 0;
}
-
if (status_bits & VFE_IRQ_STATUS0_STATS_CS) {
if (!vfe32_ctrl->csStatsControl.ackPending) {
vfe32_ctrl->csStatsControl.ackPending = TRUE;
vfe32_ctrl->csStatsControl.bufToRender =
- vfe32_process_stats_irq_common(statsCsNum,
+ vfe32_process_stats_irq_common(
+ vfe32_ctrl, statsCsNum,
vfe32_ctrl->csStatsControl.nextFrameAddrBuf);
process_stats = true;
} else {
@@ -3347,83 +3691,89 @@
spin_unlock_irqrestore(&vfe32_ctrl->comp_stats_ack_lock, flags);
if (process_stats)
- vfe_send_comp_stats_msg(status_bits);
+ vfe_send_comp_stats_msg(vfe32_ctrl, status_bits);
return;
}
-static void vfe32_process_stats_irq(uint32_t irqstatus)
+static void vfe32_process_stats_irq(
+ struct vfe32_ctrl_type *vfe32_ctrl, uint32_t irqstatus)
{
uint32_t status_bits = VFE_COM_STATUS & irqstatus;
if ((vfe32_ctrl->hfr_mode != HFR_MODE_OFF) &&
- (vfe32_ctrl->vfeFrameId % vfe32_ctrl->hfr_mode != 0)) {
+ (vfe32_ctrl->share_ctrl->vfeFrameId %
+ vfe32_ctrl->hfr_mode != 0)) {
CDBG("Skip the stats when HFR enabled\n");
return;
}
- vfe32_process_stats(status_bits);
+ vfe32_process_stats(vfe32_ctrl, status_bits);
return;
}
-static void vfe32_process_irq(uint32_t irqstatus)
+static void vfe32_process_irq(
+ struct vfe32_ctrl_type *vfe32_ctrl, uint32_t irqstatus)
{
if (irqstatus &
VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK) {
- vfe32_process_stats_irq(irqstatus);
+ vfe32_process_stats_irq(vfe32_ctrl, irqstatus);
return;
}
switch (irqstatus) {
case VFE_IRQ_STATUS0_CAMIF_SOF_MASK:
CDBG("irq camifSofIrq\n");
- vfe32_process_camif_sof_irq();
+ vfe32_process_camif_sof_irq(vfe32_ctrl);
break;
case VFE_IRQ_STATUS0_REG_UPDATE_MASK:
CDBG("irq regUpdateIrq\n");
- vfe32_process_reg_update_irq();
+ vfe32_process_reg_update_irq(vfe32_ctrl);
break;
case VFE_IMASK_WHILE_STOPPING_1:
CDBG("irq resetAckIrq\n");
- vfe32_process_reset_irq();
+ vfe32_process_reset_irq(vfe32_ctrl);
break;
case VFE_IRQ_STATUS0_STATS_AEC:
CDBG("Stats AEC irq occured.\n");
- vfe32_process_stats_ae_irq();
+ vfe32_process_stats_ae_irq(vfe32_ctrl);
break;
case VFE_IRQ_STATUS0_STATS_AWB:
CDBG("Stats AWB irq occured.\n");
- vfe32_process_stats_awb_irq();
+ vfe32_process_stats_awb_irq(vfe32_ctrl);
break;
case VFE_IRQ_STATUS0_STATS_AF:
CDBG("Stats AF irq occured.\n");
- vfe32_process_stats_af_irq();
+ vfe32_process_stats_af_irq(vfe32_ctrl);
break;
case VFE_IRQ_STATUS0_STATS_IHIST:
CDBG("Stats IHIST irq occured.\n");
- vfe32_process_stats_ihist_irq();
+ vfe32_process_stats_ihist_irq(vfe32_ctrl);
break;
case VFE_IRQ_STATUS0_STATS_RS:
CDBG("Stats RS irq occured.\n");
- vfe32_process_stats_rs_irq();
+ vfe32_process_stats_rs_irq(vfe32_ctrl);
break;
case VFE_IRQ_STATUS0_STATS_CS:
CDBG("Stats CS irq occured.\n");
- vfe32_process_stats_cs_irq();
+ vfe32_process_stats_cs_irq(vfe32_ctrl);
break;
case VFE_IRQ_STATUS0_SYNC_TIMER0:
CDBG("SYNC_TIMER 0 irq occured.\n");
- vfe32_send_isp_msg(vfe32_ctrl,
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ vfe32_ctrl->share_ctrl->vfeFrameId,
MSG_ID_SYNC_TIMER0_DONE);
break;
case VFE_IRQ_STATUS0_SYNC_TIMER1:
CDBG("SYNC_TIMER 1 irq occured.\n");
- vfe32_send_isp_msg(vfe32_ctrl,
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ vfe32_ctrl->share_ctrl->vfeFrameId,
MSG_ID_SYNC_TIMER1_DONE);
break;
case VFE_IRQ_STATUS0_SYNC_TIMER2:
CDBG("SYNC_TIMER 2 irq occured.\n");
- vfe32_send_isp_msg(vfe32_ctrl,
+ vfe32_send_isp_msg(&vfe32_ctrl->subdev,
+ vfe32_ctrl->share_ctrl->vfeFrameId,
MSG_ID_SYNC_TIMER2_DONE);
break;
default:
@@ -3474,11 +3824,12 @@
NOTIFY_VFE_IRQ,
(void *)VFE_IMASK_WHILE_STOPPING_1);
- if (atomic_read(&vfe32_ctrl->vstate)) {
+ if (atomic_read(&axi_ctrl->share_ctrl->vstate)) {
if (qcmd->vfeInterruptStatus1 &
VFE32_IMASK_ERROR_ONLY_1) {
pr_err("irq errorIrq\n");
vfe32_process_error_irq(
+ axi_ctrl,
qcmd->vfeInterruptStatus1 &
VFE32_IMASK_ERROR_ONLY_1);
}
@@ -3487,7 +3838,7 @@
(void *)qcmd->vfeInterruptStatus0);
/* then process stats irq. */
- if (vfe32_ctrl->stats_comp) {
+ if (axi_ctrl->share_ctrl->stats_comp) {
/* process stats comb interrupt. */
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK) {
@@ -3567,7 +3918,7 @@
CDBG("vfe_parse_irq\n");
- vfe32_read_irq_status(&irq);
+ vfe32_read_irq_status(axi_ctrl, &irq);
if ((irq.vfeIrqStatus0 == 0) && (irq.vfeIrqStatus1 == 0)) {
CDBG("vfe_parse_irq: vfeIrqStatus0 & 1 are both 0!\n");
@@ -3581,12 +3932,12 @@
return IRQ_HANDLED;
}
- spin_lock_irqsave(&vfe32_ctrl->stop_flag_lock, flags);
- if (vfe32_ctrl->stop_ack_pending) {
+ spin_lock_irqsave(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
+ if (axi_ctrl->share_ctrl->stop_ack_pending) {
irq.vfeIrqStatus0 &= VFE_IMASK_WHILE_STOPPING_0;
irq.vfeIrqStatus1 &= VFE_IMASK_WHILE_STOPPING_1;
}
- spin_unlock_irqrestore(&vfe32_ctrl->stop_flag_lock, flags);
+ spin_unlock_irqrestore(&axi_ctrl->share_ctrl->stop_flag_lock, flags);
CDBG("vfe_parse_irq: Irq_status0 = 0x%x, Irq_status1 = 0x%x.\n",
irq.vfeIrqStatus0, irq.vfeIrqStatus1);
@@ -3608,6 +3959,8 @@
{
struct msm_cam_media_controller *pmctl =
(struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
+ struct vfe32_ctrl_type *vfe32_ctrl =
+ (struct vfe32_ctrl_type *)v4l2_get_subdevdata(sd);
struct msm_isp_cmd vfecmd;
struct msm_camvfe_params *vfe_params =
(struct msm_camvfe_params *)arg;
@@ -3619,8 +3972,14 @@
struct vfe_cmd_stats_buf *scfg = NULL;
struct msm_pmem_region *regptr = NULL;
struct vfe_cmd_stats_ack *sack = NULL;
+
+ if (!vfe32_ctrl->share_ctrl->vfebase) {
+ pr_err("%s: base address unmapped\n", __func__);
+ return -EFAULT;
+ }
+
if (cmd->cmd_type == CMD_VFE_PROCESS_IRQ) {
- vfe32_process_irq((uint32_t) data);
+ vfe32_process_irq(vfe32_ctrl, (uint32_t) data);
return rc;
} else if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
cmd->cmd_type != CMD_CONFIG_PONG_ADDR &&
@@ -3688,22 +4047,22 @@
/* individual */
switch (cmd->cmd_type) {
case CMD_STATS_AEC_ENABLE:
- rc = vfe_stats_aec_buf_init(scfg);
+ rc = vfe_stats_aec_buf_init(vfe32_ctrl, scfg);
break;
case CMD_STATS_AF_ENABLE:
- rc = vfe_stats_af_buf_init(scfg);
+ rc = vfe_stats_af_buf_init(vfe32_ctrl, scfg);
break;
case CMD_STATS_AWB_ENABLE:
- rc = vfe_stats_awb_buf_init(scfg);
+ rc = vfe_stats_awb_buf_init(vfe32_ctrl, scfg);
break;
case CMD_STATS_IHIST_ENABLE:
- rc = vfe_stats_ihist_buf_init(scfg);
+ rc = vfe_stats_ihist_buf_init(vfe32_ctrl, scfg);
break;
case CMD_STATS_RS_ENABLE:
- rc = vfe_stats_rs_buf_init(scfg);
+ rc = vfe_stats_rs_buf_init(vfe32_ctrl, scfg);
break;
case CMD_STATS_CS_ENABLE:
- rc = vfe_stats_cs_buf_init(scfg);
+ rc = vfe_stats_cs_buf_init(vfe32_ctrl, scfg);
break;
default:
pr_err("%s Unsupported cmd type %d",
@@ -3714,50 +4073,51 @@
}
switch (cmd->cmd_type) {
case CMD_GENERAL:
- rc = vfe32_proc_general(pmctl, &vfecmd);
+ rc = vfe32_proc_general(pmctl, &vfecmd, vfe32_ctrl);
break;
-
case CMD_CONFIG_PING_ADDR: {
int path = *((int *)cmd->value);
- struct vfe32_output_ch *outch = vfe32_get_ch(path);
+ struct vfe32_output_ch *outch =
+ vfe32_get_ch(path, vfe32_ctrl->share_ctrl);
outch->ping = *((struct msm_free_buf *)data);
}
break;
case CMD_CONFIG_PONG_ADDR: {
int path = *((int *)cmd->value);
- struct vfe32_output_ch *outch = vfe32_get_ch(path);
+ struct vfe32_output_ch *outch =
+ vfe32_get_ch(path, vfe32_ctrl->share_ctrl);
outch->pong = *((struct msm_free_buf *)data);
}
break;
case CMD_CONFIG_FREE_BUF_ADDR: {
int path = *((int *)cmd->value);
- struct vfe32_output_ch *outch = vfe32_get_ch(path);
+ struct vfe32_output_ch *outch =
+ vfe32_get_ch(path, vfe32_ctrl->share_ctrl);
outch->free_buf = *((struct msm_free_buf *)data);
}
break;
-
case CMD_SNAP_BUF_RELEASE:
break;
case CMD_STATS_AEC_BUF_RELEASE:
- vfe32_stats_aec_ack(sack);
+ vfe32_stats_aec_ack(vfe32_ctrl, sack);
break;
case CMD_STATS_AF_BUF_RELEASE:
- vfe32_stats_af_ack(sack);
+ vfe32_stats_af_ack(vfe32_ctrl, sack);
break;
case CMD_STATS_AWB_BUF_RELEASE:
- vfe32_stats_awb_ack(sack);
+ vfe32_stats_awb_ack(vfe32_ctrl, sack);
break;
case CMD_STATS_IHIST_BUF_RELEASE:
- vfe32_stats_ihist_ack(sack);
+ vfe32_stats_ihist_ack(vfe32_ctrl, sack);
break;
case CMD_STATS_RS_BUF_RELEASE:
- vfe32_stats_rs_ack(sack);
+ vfe32_stats_rs_ack(vfe32_ctrl, sack);
break;
case CMD_STATS_CS_BUF_RELEASE:
- vfe32_stats_cs_ack(sack);
+ vfe32_stats_cs_ack(vfe32_ctrl, sack);
break;
default:
pr_err("%s Unsupported AXI configuration %x ", __func__,
@@ -3816,17 +4176,16 @@
v4l2_set_subdev_hostdata(sd, mctl);
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->vfebase = ioremap(axi_ctrl->vfemem->start,
+ axi_ctrl->share_ctrl->vfebase = ioremap(axi_ctrl->vfemem->start,
resource_size(axi_ctrl->vfemem));
- if (!axi_ctrl->vfebase) {
+ if (!axi_ctrl->share_ctrl->vfebase) {
rc = -ENOMEM;
pr_err("%s: vfe ioremap failed\n", __func__);
goto remap_failed;
}
- vfe32_ctrl->vfebase = axi_ctrl->vfebase;
-
if (axi_ctrl->fs_vfe == NULL) {
axi_ctrl->fs_vfe =
regulator_get(&axi_ctrl->pdev->dev, "fs_vfe");
@@ -3854,11 +4213,12 @@
msm_camio_bus_scale_cfg(
mctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
- if (msm_camera_io_r(vfe32_ctrl->vfebase + V32_GET_HW_VERSION_OFF) ==
+ if (msm_camera_io_r(
+ axi_ctrl->share_ctrl->vfebase + V32_GET_HW_VERSION_OFF) ==
VFE32_HW_NUMBER)
- vfe32_ctrl->register_total = VFE32_REGISTER_TOTAL;
+ axi_ctrl->share_ctrl->register_total = VFE32_REGISTER_TOTAL;
else
- vfe32_ctrl->register_total = VFE33_REGISTER_TOTAL;
+ axi_ctrl->share_ctrl->register_total = VFE33_REGISTER_TOTAL;
enable_irq(axi_ctrl->vfeirq->start);
@@ -3868,8 +4228,8 @@
regulator_put(axi_ctrl->fs_vfe);
axi_ctrl->fs_vfe = NULL;
fs_failed:
- iounmap(axi_ctrl->vfebase);
- axi_ctrl->vfebase = NULL;
+ iounmap(axi_ctrl->share_ctrl->vfebase);
+ axi_ctrl->share_ctrl->vfebase = NULL;
remap_failed:
disable_irq(axi_ctrl->vfeirq->start);
return rc;
@@ -3879,9 +4239,11 @@
struct msm_cam_media_controller *mctl)
{
int rc = 0;
+ struct vfe32_ctrl_type *vfe32_ctrl =
+ (struct vfe32_ctrl_type *)v4l2_get_subdevdata(sd);
v4l2_set_subdev_hostdata(sd, mctl);
- spin_lock_init(&vfe32_ctrl->stop_flag_lock);
+ spin_lock_init(&vfe32_ctrl->share_ctrl->stop_flag_lock);
spin_lock_init(&vfe32_ctrl->state_lock);
spin_lock_init(&vfe32_ctrl->io_lock);
spin_lock_init(&vfe32_ctrl->update_ack_lock);
@@ -3893,7 +4255,6 @@
spin_lock_init(&vfe32_ctrl->rs_ack_lock);
spin_lock_init(&vfe32_ctrl->cs_ack_lock);
spin_lock_init(&vfe32_ctrl->comp_stats_ack_lock);
- spin_lock_init(&vfe32_ctrl->sd_notify_lock);
vfe32_ctrl->update_linear = false;
vfe32_ctrl->update_rolloff = false;
@@ -3909,6 +4270,11 @@
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__);
disable_irq(axi_ctrl->vfeirq->start);
tasklet_kill(&axi_ctrl->vfe32_tasklet);
@@ -3919,8 +4285,8 @@
regulator_put(axi_ctrl->fs_vfe);
axi_ctrl->fs_vfe = NULL;
}
- iounmap(axi_ctrl->vfebase);
- axi_ctrl->vfebase = NULL;
+ iounmap(axi_ctrl->share_ctrl->vfebase);
+ axi_ctrl->share_ctrl->vfebase = NULL;
if (atomic_read(&irq_cnt))
pr_warning("%s, Warning IRQ Count not ZERO\n", __func__);
@@ -3931,78 +4297,92 @@
void msm_vfe_subdev_release(struct v4l2_subdev *sd)
{
- vfe32_ctrl->vfebase = 0;
+ 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;
}
-void axi_start(void)
+void axi_start(struct axi_ctrl_t *axi_ctrl)
{
- switch (vfe32_ctrl->operation_mode) {
+ switch (axi_ctrl->share_ctrl->operation_mode) {
case VFE_OUTPUTS_PREVIEW:
case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
- if (vfe32_ctrl->outpath.output_mode &
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
- } else if (vfe32_ctrl->outpath.output_mode &
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(1, 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(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch2]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch1]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch2]);
}
break;
default:
- if (vfe32_ctrl->outpath.output_mode &
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_SECONDARY) {
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
- } else if (vfe32_ctrl->outpath.output_mode &
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(1, 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(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
- msm_camera_io_w(1, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch2]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch1]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch2]);
}
break;
}
}
-void axi_stop(void)
+void axi_stop(struct axi_ctrl_t *axi_ctrl)
{
uint8_t axiBusyFlag = true;
- /* axi halt command. */
+ /* axi halt command. */
msm_camera_io_w(AXI_HALT,
- vfe32_ctrl->vfebase + VFE_AXI_CMD);
+ axi_ctrl->share_ctrl->vfebase + VFE_AXI_CMD);
wmb();
while (axiBusyFlag) {
- if (msm_camera_io_r(vfe32_ctrl->vfebase + VFE_AXI_STATUS) & 0x1)
+ if (msm_camera_io_r(
+ axi_ctrl->share_ctrl->vfebase + VFE_AXI_STATUS) & 0x1)
axiBusyFlag = false;
}
/* Ensure the write order while writing
to the command register using the barrier */
msm_camera_io_w_mb(AXI_HALT_CLEAR,
- vfe32_ctrl->vfebase + VFE_AXI_CMD);
+ 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(0xf0000000,
- vfe32_ctrl->vfebase + VFE_IRQ_MASK_0);
+ axi_ctrl->share_ctrl->vfebase + VFE_IRQ_MASK_0);
msm_camera_io_w(VFE_IMASK_WHILE_STOPPING_1,
- vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
+ 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,
- vfe32_ctrl->vfebase + VFE_GLOBAL_RESET);
+ axi_ctrl->share_ctrl->vfebase + VFE_GLOBAL_RESET);
}
static int msm_axi_config(struct v4l2_subdev *sd, void __user *arg)
@@ -4010,7 +4390,12 @@
struct msm_vfe_cfg_cmd cfgcmd;
struct msm_isp_cmd vfecmd;
int rc = 0;
+ 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 -EFAULT;
+ }
if (NULL != arg) {
if (copy_from_user(&cfgcmd, arg, sizeof(cfgcmd))) {
ERR_COPY_FROM_USER();
@@ -4043,7 +4428,7 @@
rc = -EFAULT;
break;
}
- vfe32_config_axi(OUTPUT_PRIM, axio);
+ vfe32_config_axi(axi_ctrl, OUTPUT_PRIM, axio);
kfree(axio);
}
break;
@@ -4062,7 +4447,7 @@
rc = -EFAULT;
break;
}
- vfe32_config_axi(OUTPUT_PRIM_ALL_CHNLS, axio);
+ vfe32_config_axi(axi_ctrl, OUTPUT_PRIM_ALL_CHNLS, axio);
kfree(axio);
}
break;
@@ -4081,7 +4466,7 @@
rc = -EFAULT;
break;
}
- vfe32_config_axi(OUTPUT_PRIM|OUTPUT_SEC, axio);
+ vfe32_config_axi(axi_ctrl, OUTPUT_PRIM|OUTPUT_SEC, axio);
kfree(axio);
}
break;
@@ -4100,7 +4485,8 @@
rc = -EFAULT;
break;
}
- vfe32_config_axi(OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS, axio);
+ vfe32_config_axi(axi_ctrl,
+ OUTPUT_PRIM|OUTPUT_SEC_ALL_CHNLS, axio);
kfree(axio);
}
break;
@@ -4119,7 +4505,8 @@
rc = -EFAULT;
break;
}
- vfe32_config_axi(OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC, axio);
+ vfe32_config_axi(axi_ctrl,
+ OUTPUT_PRIM_ALL_CHNLS|OUTPUT_SEC, axio);
kfree(axio);
}
break;
@@ -4128,10 +4515,10 @@
__func__, cfgcmd.cmd_type);
break;
case CMD_AXI_START:
- axi_start();
+ axi_start(axi_ctrl);
break;
case CMD_AXI_STOP:
- axi_stop();
+ axi_stop(axi_ctrl);
break;
default:
pr_err("%s Unsupported AXI configuration %x ", __func__,
@@ -4143,43 +4530,95 @@
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");
- vfe32_process_output_path_irq_0();
+ vfe32_process_output_path_irq_0(axi_ctrl);
}
if (irqstatus &
VFE_IRQ_STATUS0_IMAGE_COMPOSIT_DONE1_MASK) {
CDBG("Image composite done 1 irq occured.\n");
- vfe32_process_output_path_irq_1();
+ vfe32_process_output_path_irq_1(axi_ctrl);
}
/* in snapshot mode if done then send
snapshot done message */
- if (vfe32_ctrl->operation_mode ==
+ if (axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_THUMB_AND_MAIN ||
- vfe32_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_MAIN_AND_THUMB ||
- vfe32_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_THUMB_AND_JPEG ||
- vfe32_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_JPEG_AND_THUMB ||
- vfe32_ctrl->operation_mode ==
+ axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_RAW) {
- if ((vfe32_ctrl->outpath.out0.capture_cnt == 0)
- && (vfe32_ctrl->outpath.out1.
+ 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,
- vfe32_ctrl->vfebase +
+ axi_ctrl->share_ctrl->vfebase +
VFE_CAMIF_COMMAND);
- vfe32_send_isp_msg(vfe32_ctrl,
+ vfe32_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 vfe32_output_ch *outch =
+ vfe32_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 vfe32_output_ch *outch =
+ vfe32_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 vfe32_output_ch *outch =
+ vfe32_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,
@@ -4198,6 +4637,10 @@
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;
@@ -4227,14 +4670,36 @@
{
int rc = 0;
struct axi_ctrl_t *axi_ctrl;
+ struct vfe32_ctrl_type *vfe32_ctrl;
+ struct vfe_share_ctrl_t *share_ctrl;
CDBG("%s: device id = %d\n", __func__, pdev->id);
- vfe32_ctrl = kzalloc(sizeof(struct vfe32_ctrl_type), GFP_KERNEL);
- if (!vfe32_ctrl) {
+
+ share_ctrl = kzalloc(sizeof(struct vfe_share_ctrl_t), GFP_KERNEL);
+ if (!share_ctrl) {
pr_err("%s: no enough memory\n", __func__);
return -ENOMEM;
}
axi_ctrl = kzalloc(sizeof(struct axi_ctrl_t), GFP_KERNEL);
+ if (!axi_ctrl) {
+ pr_err("%s: no enough memory\n", __func__);
+ kfree(share_ctrl);
+ return -ENOMEM;
+ }
+
+ vfe32_ctrl = kzalloc(sizeof(struct vfe32_ctrl_type), GFP_KERNEL);
+ if (!vfe32_ctrl) {
+ pr_err("%s: no enough memory\n", __func__);
+ kfree(share_ctrl);
+ kfree(axi_ctrl);
+ return -ENOMEM;
+ }
+
+ share_ctrl->axi_ctrl = axi_ctrl;
+ share_ctrl->vfe32_ctrl = vfe32_ctrl;
+ axi_ctrl->share_ctrl = share_ctrl;
+ vfe32_ctrl->share_ctrl = share_ctrl;
+
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;
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index d1faded..086600a 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -900,6 +900,30 @@
uint32_t droppedStatsFrameCount;
uint32_t bufToRender;
};
+struct axi_ctrl_t;
+struct vfe32_ctrl_type;
+
+struct vfe_share_ctrl_t {
+ void __iomem *vfebase;
+ uint32_t register_total;
+
+ atomic_t vstate;
+ uint32_t vfeFrameId;
+ uint32_t stats_comp;
+ 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 */
+ struct vfe32_output_path outpath;
+
+ uint32_t ref_count;
+ spinlock_t sd_notify_lock;
+
+ struct axi_ctrl_t *axi_ctrl;
+ struct vfe32_ctrl_type *vfe32_ctrl;
+};
struct axi_ctrl_t {
struct v4l2_subdev subdev;
@@ -908,7 +932,6 @@
spinlock_t tasklet_lock;
struct list_head tasklet_q;
- void __iomem *vfebase;
void *syncdata;
struct resource *vfemem;
@@ -916,15 +939,12 @@
struct regulator *fs_vfe;
struct clk *vfe_clk[3];
struct tasklet_struct vfe32_tasklet;
+ struct vfe_share_ctrl_t *share_ctrl;
};
struct vfe32_ctrl_type {
- uint16_t operation_mode; /* streaming or snapshot */
- struct vfe32_output_path outpath;
-
uint32_t vfeImaskCompositePacked;
- spinlock_t stop_flag_lock;
spinlock_t update_ack_lock;
spinlock_t state_lock;
spinlock_t io_lock;
@@ -941,7 +961,6 @@
void *extdata;
int8_t start_ack_pending;
- int8_t stop_ack_pending;
int8_t reset_ack_pending;
int8_t update_ack_pending;
enum vfe_output_state recording_state;
@@ -949,19 +968,13 @@
int8_t update_rolloff;
int8_t update_la;
int8_t update_gamma;
- enum vfe_output_state liveshot_state;
- void __iomem *vfebase;
- uint32_t register_total;
+ struct vfe_share_ctrl_t *share_ctrl;
- uint32_t stats_comp;
- atomic_t vstate;
- uint32_t vfe_capture_count;
uint32_t sync_timer_repeat_count;
uint32_t sync_timer_state;
uint32_t sync_timer_number;
- uint32_t vfeFrameId;
uint32_t output1Pattern;
uint32_t output1Period;
uint32_t output2Pattern;
@@ -978,7 +991,6 @@
/* v4l2 subdev */
struct v4l2_subdev subdev;
struct platform_device *pdev;
- spinlock_t sd_notify_lock;
uint32_t hfr_mode;
uint32_t frame_skip_cnt;
uint32_t frame_skip_pattern;
@@ -1015,4 +1027,7 @@
#define VIDIOC_MSM_AXI_IRQ \
_IOWR('V', BASE_VIDIOC_PRIVATE + 21, void *)
+#define VIDIOC_MSM_AXI_BUF_CFG \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 22, void *)
+
#endif /* __MSM_VFE32_H__ */
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index f9ce74b..54e9582 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -30,14 +30,19 @@
#include "msm.h"
#include "msm_vpe.h"
+#ifdef CONFIG_MSM_CAMERA_DEBUG
+#define D(fmt, args...) pr_debug("msm_vpe: " fmt, ##args)
+#else
+#define D(fmt, args...) do {} while (0)
+#endif
+
static int vpe_enable(uint32_t);
static int vpe_disable(void);
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);
-static int msm_vpe_do_pp(struct msm_mctl_pp_cmd *cmd,
- struct msm_mctl_pp_frame_info *pp_frame_info);
+static int msm_vpe_do_pp(struct msm_mctl_pp_frame_info *pp_frame_info);
static long long vpe_do_div(long long num, long long den)
{
@@ -57,8 +62,7 @@
msm_camera_io_dump(vpe_ctrl->vpebase + 0x50400, 0x10);
/* this triggers the operation. */
- msm_camera_io_w(1, vpe_ctrl->vpebase + VPE_DL0_START_OFFSET);
- wmb();
+ msm_camera_io_w_mb(1, vpe_ctrl->vpebase + VPE_DL0_START_OFFSET);
return 0;
}
@@ -72,7 +76,7 @@
static void vpe_config_axi_default(void)
{
msm_camera_io_w(0x25, vpe_ctrl->vpebase + VPE_AXI_ARB_2_OFFSET);
- CDBG("%s: yaddr %ld cbcraddr %ld", __func__,
+ D("%s: yaddr %ld cbcraddr %ld", __func__,
vpe_ctrl->out_y_addr, vpe_ctrl->out_cbcr_addr);
if (!vpe_ctrl->out_y_addr || !vpe_ctrl->out_cbcr_addr)
return;
@@ -81,7 +85,6 @@
/* for video CbCr address */
msm_camera_io_w(vpe_ctrl->out_cbcr_addr,
vpe_ctrl->vpebase + VPE_OUTP1_ADDR_OFFSET);
-
}
static int vpe_reset(void)
@@ -92,7 +95,7 @@
spin_lock_irqsave(&vpe_ctrl->lock, flags);
if (vpe_ctrl->state == VPE_STATE_IDLE) {
- CDBG("%s: VPE already disabled.", __func__);
+ D("%s: VPE already disabled.", __func__);
spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
return rc;
}
@@ -101,7 +104,7 @@
vpe_reset_state_variables();
vpe_version = msm_camera_io_r(
vpe_ctrl->vpebase + VPE_HW_VERSION_OFFSET);
- CDBG("vpe_version = 0x%x\n", vpe_version);
+ D("vpe_version = 0x%x\n", vpe_version);
/* disable all interrupts.*/
msm_camera_io_w(0, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET);
/* clear all pending interrupts*/
@@ -139,13 +142,13 @@
rot_flag = msm_camera_io_r(vpe_ctrl->vpebase +
VPE_OP_MODE_OFFSET) & 0xE00;
if (pinfo != NULL) {
- CDBG("%s: Crop info in2_w = %d, in2_h = %d "
+ D("%s: Crop info in2_w = %d, in2_h = %d "
"out2_w = %d out2_h = %d\n",
__func__, pcrop->src_w, pcrop->src_h,
pcrop->dst_w, pcrop->dst_h);
rc = vpe_update_scaler(pcrop);
}
- CDBG("return rc = %d rot_flag = %d\n", rc, rot_flag);
+ D("return rc = %d rot_flag = %d\n", rc, rot_flag);
rc |= rot_flag;
return rc;
@@ -200,7 +203,7 @@
vpe_ctrl->out_w = w;
vpe_ctrl->out_h = h;
}
- CDBG("%s: out_w=%d, out_h=%d", __func__, vpe_ctrl->out_w,
+ D("%s: out_w=%d, out_h=%d", __func__, vpe_ctrl->out_w,
vpe_ctrl->out_h);
return 0;
}
@@ -239,7 +242,7 @@
out_ROI_width = pcrop->dst_w;
out_ROI_height = pcrop->dst_h;
- CDBG("src w = 0x%x, h=0x%x, dst w = 0x%x, h =0x%x.\n",
+ D("src w = 0x%x, h=0x%x, dst w = 0x%x, h =0x%x.\n",
src_ROI_width, src_ROI_height, out_ROI_width,
out_ROI_height);
src_roi = (src_ROI_height << 16) + src_ROI_width;
@@ -249,12 +252,12 @@
src_x = pcrop->src_x;
src_y = pcrop->src_y;
- CDBG("src_x = %d, src_y=%d.\n", src_x, src_y);
+ D("src_x = %d, src_y=%d.\n", src_x, src_y);
src_xy = src_y*(1<<16) + src_x;
msm_camera_io_w(src_xy, vpe_ctrl->vpebase +
VPE_SRC_XY_OFFSET);
- CDBG("src_xy = %d, src_roi=%d.\n", src_xy, src_roi);
+ D("src_xy = %d, src_roi=%d.\n", src_xy, src_roi);
/* decide whether to use FIR or M/N for scaling */
if ((out_ROI_width == 1 && src_ROI_width < 4) ||
@@ -387,9 +390,9 @@
} else if (scale_unit_sel_y == 1) /* M over N scalar */
phase_init_y = 0;
- CDBG("phase step x = %d, step y = %d.\n",
+ D("phase step x = %d, step y = %d.\n",
phase_step_x, phase_step_y);
- CDBG("phase init x = %d, init y = %d.\n",
+ D("phase init x = %d, init y = %d.\n",
phase_init_x, phase_init_y);
msm_camera_io_w(phase_step_x, vpe_ctrl->vpebase +
@@ -416,24 +419,40 @@
spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
return busy;
}
+
static int msm_send_frame_to_vpe(void)
{
int rc = 0;
unsigned long flags;
+ unsigned long srcP0, srcP1, outP0, outP1;
+ struct msm_mctl_pp_frame_info *frame = vpe_ctrl->pp_frame_info;
spin_lock_irqsave(&vpe_ctrl->lock, flags);
- msm_camera_io_w((vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
- vpe_ctrl->pp_frame_info->src_frame.sp.y_off),
- vpe_ctrl->vpebase + VPE_SRCP0_ADDR_OFFSET);
- msm_camera_io_w((vpe_ctrl->pp_frame_info->src_frame.sp.phy_addr +
- vpe_ctrl->pp_frame_info->src_frame.sp.cbcr_off),
- vpe_ctrl->vpebase + VPE_SRCP1_ADDR_OFFSET);
- msm_camera_io_w((vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
- vpe_ctrl->pp_frame_info->dest_frame.sp.y_off),
- vpe_ctrl->vpebase + VPE_OUTP0_ADDR_OFFSET);
- msm_camera_io_w((vpe_ctrl->pp_frame_info->dest_frame.sp.phy_addr +
- vpe_ctrl->pp_frame_info->dest_frame.sp.cbcr_off),
- vpe_ctrl->vpebase + VPE_OUTP1_ADDR_OFFSET);
+ 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;
+ } 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;
+ }
+
+ 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);
+ msm_camera_io_w(outP1, vpe_ctrl->vpebase + VPE_OUTP1_ADDR_OFFSET);
+
vpe_ctrl->state = VPE_STATE_ACTIVE;
spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
vpe_start();
@@ -443,27 +462,33 @@
static void vpe_send_outmsg(void)
{
unsigned long flags;
- struct msm_vpe_resp rp;
- memset(&rp, 0, sizeof(rp));
+ struct v4l2_event v4l2_evt;
+ struct msm_queue_cmd *event_qcmd;
spin_lock_irqsave(&vpe_ctrl->lock, flags);
if (vpe_ctrl->state == VPE_STATE_IDLE) {
pr_err("%s VPE is in IDLE state. Ignore the ack msg", __func__);
spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
return;
}
- rp.type = vpe_ctrl->pp_frame_info->pp_frame_cmd.path;
- rp.extdata = (void *)vpe_ctrl->pp_frame_info;
- rp.extlen = sizeof(*vpe_ctrl->pp_frame_info);
- vpe_ctrl->state = VPE_STATE_INIT; /* put it back to idle. */
+ event_qcmd = kzalloc(sizeof(struct msm_queue_cmd), GFP_ATOMIC);
+ atomic_set(&event_qcmd->on_heap, 1);
+ event_qcmd->command = (void *)vpe_ctrl->pp_frame_info;
vpe_ctrl->pp_frame_info = NULL;
+ vpe_ctrl->state = VPE_STATE_INIT; /* put it back to idle. */
+
+ /* Enqueue the event payload. */
+ msm_enqueue(&vpe_ctrl->eventData_q, &event_qcmd->list_eventdata);
+ /* Now queue the event. */
+ 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);
- v4l2_subdev_notify(&vpe_ctrl->subdev,
- NOTIFY_VPE_MSG_EVT, (void *)&rp);
}
static void vpe_do_tasklet(unsigned long data)
{
- CDBG("%s: irq_status = 0x%x",
+ D("%s: irq_status = 0x%x",
__func__, vpe_ctrl->irq_status);
if (vpe_ctrl->irq_status & 0x1)
vpe_send_outmsg();
@@ -478,7 +503,7 @@
msm_camera_io_w_mb(vpe_ctrl->irq_status, vpe_ctrl->vpebase +
VPE_INTR_CLEAR_OFFSET);
msm_camera_io_w(0, vpe_ctrl->vpebase + VPE_INTR_ENABLE_OFFSET);
- CDBG("%s: vpe_parse_irq =0x%x.\n", __func__, vpe_ctrl->irq_status);
+ D("%s: vpe_parse_irq =0x%x.\n", __func__, vpe_ctrl->irq_status);
tasklet_schedule(&vpe_tasklet);
return IRQ_HANDLED;
}
@@ -492,7 +517,7 @@
{
int rc = 0;
unsigned long flags = 0;
- CDBG("%s", __func__);
+ D("%s", __func__);
/* don't change the order of clock and irq.*/
spin_lock_irqsave(&vpe_ctrl->lock, flags);
if (vpe_ctrl->state != VPE_STATE_IDLE) {
@@ -536,10 +561,10 @@
{
int rc = 0;
unsigned long flags = 0;
- CDBG("%s", __func__);
+ D("%s", __func__);
spin_lock_irqsave(&vpe_ctrl->lock, flags);
if (vpe_ctrl->state == VPE_STATE_IDLE) {
- CDBG("%s: VPE already disabled", __func__);
+ D("%s: VPE already disabled", __func__);
spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
return rc;
}
@@ -559,8 +584,7 @@
return rc;
}
-static int msm_vpe_do_pp(struct msm_mctl_pp_cmd *cmd,
- struct msm_mctl_pp_frame_info *pp_frame_info)
+static int msm_vpe_do_pp(struct msm_mctl_pp_frame_info *pp_frame_info)
{
int rc = 0;
unsigned long flags;
@@ -577,7 +601,7 @@
vpe_ctrl->pp_frame_info = pp_frame_info;
msm_vpe_cfg_update(
&vpe_ctrl->pp_frame_info->pp_frame_cmd.crop);
- CDBG("%s Sending frame idx %d id %d to VPE ", __func__,
+ 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);
rc = msm_send_frame_to_vpe();
@@ -590,7 +614,7 @@
struct msm_cam_media_controller *mctl)
{
int rc = 0;
- CDBG("%s:begin", __func__);
+ D("%s:begin", __func__);
if (atomic_read(&vpe_init_done)) {
pr_err("%s: VPE has been initialized", __func__);
return -EBUSY;
@@ -604,7 +628,7 @@
}
v4l2_set_subdev_hostdata(sd, mctl);
spin_lock_init(&vpe_ctrl->lock);
- CDBG("%s:end", __func__);
+ D("%s:end", __func__);
return rc;
}
EXPORT_SYMBOL(msm_vpe_subdev_init);
@@ -646,84 +670,310 @@
}
EXPORT_SYMBOL(msm_vpe_subdev_release);
-static long msm_vpe_subdev_ioctl(struct v4l2_subdev *sd,
- unsigned int subdev_cmd, void *arg)
+static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd)
{
- struct msm_mctl_pp_params *vpe_params;
- struct msm_mctl_pp_cmd *cmd;
int rc = 0;
- if (subdev_cmd == VIDIOC_MSM_VPE_INIT) {
+ switch (vpe_cmd->cmd_type) {
+ case VPE_CMD_RESET:
+ rc = vpe_reset();
+ break;
+
+ case VPE_CMD_OPERATION_MODE_CFG: {
+ struct msm_vpe_op_mode_cfg op_mode_cfg;
+ if (sizeof(struct msm_vpe_op_mode_cfg) != vpe_cmd->length) {
+ pr_err("%s: size mismatch cmd=%d, len=%d, expected=%d",
+ __func__, vpe_cmd->cmd_type, vpe_cmd->length,
+ sizeof(struct msm_vpe_op_mode_cfg));
+ rc = -EINVAL;
+ break;
+ }
+ COPY_FROM_USER(rc, &op_mode_cfg, (void __user *)vpe_cmd->value,
+ sizeof(op_mode_cfg));
+ if (rc) {
+ ERR_COPY_FROM_USER();
+ break;
+ }
+
+ vpe_cmd->value = (void *)&op_mode_cfg;
+ rc = vpe_operation_config(vpe_cmd->value);
+ break;
+ }
+
+ case VPE_CMD_INPUT_PLANE_CFG: {
+ struct msm_vpe_input_plane_cfg input_cfg;
+ if (sizeof(struct msm_vpe_input_plane_cfg) != vpe_cmd->length) {
+ pr_err("%s: mismatch cmd = %d, len = %d, expected = %d",
+ __func__, vpe_cmd->cmd_type, vpe_cmd->length,
+ sizeof(struct msm_vpe_input_plane_cfg));
+ rc = -EINVAL;
+ break;
+ }
+ COPY_FROM_USER(rc, &input_cfg, (void __user *)vpe_cmd->value,
+ sizeof(input_cfg));
+ if (rc) {
+ ERR_COPY_FROM_USER();
+ break;
+ }
+
+ vpe_cmd->value = (void *)&input_cfg;
+ vpe_input_plane_config(vpe_cmd->value);
+ break;
+ }
+
+ case VPE_CMD_OUTPUT_PLANE_CFG: {
+ struct msm_vpe_output_plane_cfg output_cfg;
+ if (sizeof(struct msm_vpe_output_plane_cfg) !=
+ vpe_cmd->length) {
+ pr_err("%s: size mismatch cmd=%d, len=%d, expected=%d",
+ __func__, vpe_cmd->cmd_type, vpe_cmd->length,
+ sizeof(struct msm_vpe_output_plane_cfg));
+ rc = -EINVAL;
+ break;
+ }
+ COPY_FROM_USER(rc, &output_cfg, (void __user *)vpe_cmd->value,
+ sizeof(output_cfg));
+ if (rc) {
+ ERR_COPY_FROM_USER();
+ break;
+ }
+
+ vpe_cmd->value = (void *)&output_cfg;
+ vpe_output_plane_config(vpe_cmd->value);
+ break;
+ }
+
+ case VPE_CMD_SCALE_CFG_TYPE:{
+ struct msm_vpe_scaler_cfg scaler_cfg;
+ if (sizeof(struct msm_vpe_scaler_cfg) != vpe_cmd->length) {
+ pr_err("%s: size mismatch cmd=%d, len=%d, expected=%d",
+ __func__, vpe_cmd->cmd_type, vpe_cmd->length,
+ sizeof(struct msm_vpe_scaler_cfg));
+ rc = -EINVAL;
+ break;
+ }
+ COPY_FROM_USER(rc, &scaler_cfg, (void __user *)vpe_cmd->value,
+ sizeof(scaler_cfg));
+ if (rc) {
+ ERR_COPY_FROM_USER();
+ break;
+ }
+
+ vpe_cmd->value = (void *)&scaler_cfg;
+ vpe_update_scale_coef(vpe_cmd->value);
+ break;
+ }
+
+ case VPE_CMD_ZOOM: {
+ struct msm_mctl_pp_frame_info *zoom;
+ zoom = kmalloc(sizeof(struct msm_mctl_pp_frame_info),
+ GFP_ATOMIC);
+ if (!zoom) {
+ pr_err("%s Not enough memory ", __func__);
+ rc = -ENOMEM;
+ break;
+ }
+
+ if (sizeof(zoom->pp_frame_cmd) != vpe_cmd->length) {
+ pr_err("%s: size mismatch id=%d, len=%d, expected=%d",
+ __func__, vpe_cmd->cmd_type, vpe_cmd->length,
+ sizeof(zoom->pp_frame_cmd));
+ rc = -EINVAL;
+ kfree(zoom);
+ break;
+ }
+ COPY_FROM_USER(rc, &zoom->pp_frame_cmd,
+ (void __user *)vpe_cmd->value,
+ sizeof(zoom->pp_frame_cmd));
+ if (rc) {
+ ERR_COPY_FROM_USER();
+ kfree(zoom);
+ break;
+ }
+
+ 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,
+ zoom->pp_frame_cmd.vpe_output_action,
+ zoom->pp_frame_cmd.path);
+ rc = msm_mctl_pp_get_vpe_buf_info(zoom);
+ if (rc < 0) {
+ pr_err("%s Error getting buffer info from mctl rc = %d",
+ __func__, rc);
+ kfree(zoom);
+ break;
+ }
+ rc = msm_vpe_do_pp(zoom);
+ break;
+ }
+
+ case VPE_CMD_ENABLE: {
+ struct msm_vpe_clock_rate clk_rate;
+ int turbo_mode;
+ if (sizeof(struct msm_vpe_clock_rate) != vpe_cmd->length) {
+ pr_err("%s: size mismatch cmd=%d, len=%d, expected=%d",
+ __func__, vpe_cmd->cmd_type, vpe_cmd->length,
+ sizeof(struct msm_vpe_clock_rate));
+ rc = -EINVAL;
+ break;
+ }
+ if (copy_from_user(&clk_rate, (void __user *)vpe_cmd->value,
+ sizeof(struct msm_vpe_clock_rate))) {
+ pr_err("%s:clk_rate copy failed", __func__);
+ 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);
+ break;
+ }
+
+ case VPE_CMD_DISABLE:
+ rc = vpe_disable();
+ break;
+
+ default:
+ break;
+ }
+
+ return rc;
+}
+
+static long msm_vpe_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ struct msm_vpe_cfg_cmd *vpe_cmd;
+ int rc = 0;
+
+ switch (cmd) {
+ case VIDIOC_MSM_VPE_INIT: {
struct msm_cam_media_controller *mctl =
(struct msm_cam_media_controller *)arg;
msm_vpe_subdev_init(sd, mctl);
- } else if (subdev_cmd == VIDIOC_MSM_VPE_RELEASE) {
+ break;
+ }
+
+ case VIDIOC_MSM_VPE_RELEASE:
msm_vpe_subdev_release();
- } else if (subdev_cmd == VIDIOC_MSM_VPE_CFG) {
- vpe_params = (struct msm_mctl_pp_params *)arg;
- cmd = vpe_params->cmd;
- switch (cmd->id) {
- case VPE_CMD_INIT:
- case VPE_CMD_DEINIT:
- break;
- case VPE_CMD_RESET:
- rc = vpe_reset();
- break;
- case VPE_CMD_OPERATION_MODE_CFG:
- rc = vpe_operation_config(cmd->value);
- break;
- case VPE_CMD_INPUT_PLANE_CFG:
- vpe_input_plane_config(cmd->value);
- break;
- case VPE_CMD_OUTPUT_PLANE_CFG:
- vpe_output_plane_config(cmd->value);
- break;
- case VPE_CMD_SCALE_CFG_TYPE:
- vpe_update_scale_coef(cmd->value);
- break;
- case VPE_CMD_ZOOM: {
- rc = msm_vpe_do_pp(cmd,
- (struct msm_mctl_pp_frame_info *)vpe_params->data);
+ break;
+
+ case MSM_CAM_V4L2_IOCTL_CFG_VPE: {
+ vpe_cmd = (struct msm_vpe_cfg_cmd *)arg;
+ rc = msm_vpe_process_vpe_cmd(vpe_cmd);
+ if (rc < 0) {
+ pr_err("%s Error processing VPE cmd %d ",
+ __func__, vpe_cmd->cmd_type);
break;
}
- case VPE_CMD_ENABLE: {
- struct msm_vpe_clock_rate *clk_rate = cmd->value;
- int turbo_mode = (int)clk_rate->rate;
- rc = turbo_mode ?
- vpe_enable(VPE_TURBO_MODE_CLOCK_RATE) :
- vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE);
- break;
+ break;
}
- case VPE_CMD_DISABLE:
- rc = vpe_disable();
- break;
- case VPE_CMD_INPUT_PLANE_UPDATE:
- case VPE_CMD_FLUSH:
- default:
- break;
+
+ case MSM_CAM_V4L2_IOCTL_GET_EVENT_PAYLOAD: {
+ struct msm_device_queue *queue = &vpe_ctrl->eventData_q;
+ struct msm_queue_cmd *event_qcmd;
+ struct msm_mctl_pp_event_info pp_event_info;
+ struct msm_mctl_pp_frame_info *pp_frame_info;
+ struct msm_camera_v4l2_ioctl_t *v4l2_ioctl = arg;
+
+ event_qcmd = msm_dequeue(queue, list_eventdata);
+ if (!event_qcmd) {
+ pr_err("%s No events in the queue", __func__);
+ return -EFAULT;
}
- CDBG("%s: end, id = %d, rc = %d", __func__, cmd->id, rc);
+ pp_frame_info = event_qcmd->command;
+ 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;
+ pp_event_info.ack.cookie = pp_frame_info->pp_frame_cmd.cookie;
+ D("%s Sending payload %d %d %d", __func__,
+ 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__);
+ kfree(pp_frame_info);
+ kfree(event_qcmd);
+ break;
+ }
+
+ default:
+ break;
}
return rc;
}
+int msm_vpe_subdev_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub)
+{
+ D("%s E\n", __func__);
+ return v4l2_event_subscribe(fh, sub, VPE_SUBDEV_MAX_EVENTS);
+}
+
+int msm_vpe_subdev_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub)
+{
+ D("%s E\n", __func__);
+ return v4l2_event_unsubscribe(fh, sub);
+}
+
static const struct v4l2_subdev_core_ops msm_vpe_subdev_core_ops = {
.ioctl = msm_vpe_subdev_ioctl,
+ .subscribe_event = msm_vpe_subdev_subscribe_event,
+ .unsubscribe_event = msm_vpe_subdev_unsubscribe_event,
};
static const struct v4l2_subdev_ops msm_vpe_subdev_ops = {
.core = &msm_vpe_subdev_core_ops,
};
-static const struct v4l2_subdev_internal_ops msm_vpe_internal_ops;
+static int msm_vpe_subdev_open(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh)
+{
+ struct vpe_ctrl_type *vpe_ctrl = v4l2_get_subdevdata(sd);
+ /* Only one client of VPE allowed. */
+ if (atomic_read(&vpe_ctrl->active) != 0) {
+ pr_err("%s already opened\n", __func__);
+ return -EINVAL;
+ }
-static int __devinit vpe_probe(struct platform_device *pdev)
+ D("%s E ", __func__);
+ atomic_inc(&vpe_ctrl->active);
+ return 0;
+}
+
+static int msm_vpe_subdev_close(struct v4l2_subdev *sd,
+ struct v4l2_subdev_fh *fh)
+{
+ struct vpe_ctrl_type *vpe_ctrl = v4l2_get_subdevdata(sd);
+ if (atomic_read(&vpe_ctrl->active) == 0) {
+ pr_err("%s already closed\n", __func__);
+ return -EINVAL;
+ }
+
+ D("%s E ", __func__);
+ /* Drain the payload queue. */
+ msm_queue_drain(&vpe_ctrl->eventData_q, list_eventdata);
+ atomic_dec(&vpe_ctrl->active);
+ return 0;
+}
+
+static const struct v4l2_subdev_internal_ops msm_vpe_internal_ops = {
+ .open = msm_vpe_subdev_open,
+ .close = msm_vpe_subdev_close,
+};
+
+static int __devinit msm_vpe_probe(struct platform_device *pdev)
{
int rc = 0;
- CDBG("%s: device id = %d\n", __func__, pdev->id);
+ D("%s: device id = %d\n", __func__, pdev->id);
vpe_ctrl = kzalloc(sizeof(struct vpe_ctrl_type), GFP_KERNEL);
if (!vpe_ctrl) {
- pr_err("%s: no enough memory\n", __func__);
+ pr_err("%s: not enough memory\n", __func__);
return -ENOMEM;
}
@@ -734,6 +984,13 @@
snprintf(vpe_ctrl->subdev.name, sizeof(vpe_ctrl->subdev.name), "vpe");
platform_set_drvdata(pdev, &vpe_ctrl->subdev);
+ media_entity_init(&vpe_ctrl->subdev.entity, 0, NULL, 0);
+ vpe_ctrl->subdev.entity.type = MEDIA_ENT_T_DEVNODE_V4L;
+ vpe_ctrl->subdev.entity.group_id = VPE_DEV;
+ vpe_ctrl->subdev.entity.name = vpe_ctrl->subdev.name;
+
+ vpe_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_EVENTS;
+
vpe_ctrl->vpemem = platform_get_resource_byname(pdev,
IORESOURCE_MEM, "vpe");
if (!vpe_ctrl->vpemem) {
@@ -769,17 +1026,22 @@
disable_irq(vpe_ctrl->vpeirq->start);
+ atomic_set(&vpe_ctrl->active, 0);
vpe_ctrl->pdev = pdev;
msm_cam_register_subdev_node(&vpe_ctrl->subdev, VPE_DEV, pdev->id);
+ vpe_ctrl->subdev.entity.revision = vpe_ctrl->subdev.devnode->num;
+ msm_queue_init(&vpe_ctrl->eventData_q, "ackevents");
+
return 0;
vpe_no_resource:
+ pr_err("%s: VPE Probe failed.\n", __func__);
kfree(vpe_ctrl);
return 0;
}
-struct platform_driver vpe_driver = {
- .probe = vpe_probe,
+struct platform_driver msm_vpe_driver = {
+ .probe = msm_vpe_probe,
.driver = {
.name = MSM_VPE_DRV_NAME,
.owner = THIS_MODULE,
@@ -788,9 +1050,15 @@
static int __init msm_vpe_init_module(void)
{
- return platform_driver_register(&vpe_driver);
+ return platform_driver_register(&msm_vpe_driver);
+}
+
+static void __exit msm_vpe_exit_module(void)
+{
+ platform_driver_unregister(&msm_vpe_driver);
}
module_init(msm_vpe_init_module);
+module_exit(msm_vpe_exit_module);
MODULE_DESCRIPTION("VPE driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/video/msm/msm_vpe.h b/drivers/media/video/msm/msm_vpe.h
index 0d14626..5cf0309 100644
--- a/drivers/media/video/msm/msm_vpe.h
+++ b/drivers/media/video/msm/msm_vpe.h
@@ -79,8 +79,8 @@
#define VPE_DEFAULT_SCALE_CONFIG 0x3c
#define VPE_NORMAL_MODE_CLOCK_RATE 150000000
-#define VPE_TURBO_MODE_CLOCK_RATE 200000000
-
+#define VPE_TURBO_MODE_CLOCK_RATE 200000000
+#define VPE_SUBDEV_MAX_EVENTS 30
/**************************************************/
/*********** End of command id ********************/
@@ -119,6 +119,8 @@
struct regulator *fs_vpe;
struct clk *vpe_clk[2];
struct msm_mctl_pp_frame_info *pp_frame_info;
+ atomic_t active;
+ struct msm_device_queue eventData_q; /*V4L2 Event Payload Queue*/
};
/*
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index 8d004f6..cb59737 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -34,7 +34,7 @@
static void msm_cam_server_subdev_notify(struct v4l2_subdev *sd,
unsigned int notification, void *arg);
-static void msm_queue_init(struct msm_device_queue *queue, const char *name)
+void msm_queue_init(struct msm_device_queue *queue, const char *name)
{
D("%s\n", __func__);
spin_lock_init(&queue->lock);
@@ -45,7 +45,7 @@
init_waitqueue_head(&queue->wait);
}
-static void msm_enqueue(struct msm_device_queue *queue,
+void msm_enqueue(struct msm_device_queue *queue,
struct list_head *entry)
{
unsigned long flags;
@@ -62,7 +62,7 @@
spin_unlock_irqrestore(&queue->lock, flags);
}
-static void msm_drain_eventq(struct msm_device_queue *queue)
+void msm_drain_eventq(struct msm_device_queue *queue)
{
unsigned long flags;
struct msm_queue_cmd *qcmd;
@@ -560,55 +560,52 @@
}
int msm_server_proc_ctrl_cmd(struct msm_cam_v4l2_device *pcam,
- struct v4l2_control *ctrl, int is_set_cmd)
+ struct msm_camera_v4l2_ioctl_t *ioctl_ptr, int is_set_cmd)
{
int rc = 0;
- struct msm_ctrl_cmd ctrlcmd, *tmp_cmd;
+ struct msm_ctrl_cmd ctrlcmd, tmp_cmd, *cmd_ptr;
uint8_t *ctrl_data = NULL;
- void __user *uptr_cmd;
- void __user *uptr_value;
uint32_t cmd_len = sizeof(struct msm_ctrl_cmd);
uint32_t value_len;
- tmp_cmd = (struct msm_ctrl_cmd *)ctrl->value;
- uptr_cmd = (void __user *)ctrl->value;
- uptr_value = (void __user *)tmp_cmd->value;
- value_len = tmp_cmd->length;
-
- D("%s: cmd type = %d, up1=0x%x, ulen1=%d, up2=0x%x, ulen2=%d\n",
- __func__, tmp_cmd->type, (uint32_t)uptr_cmd, cmd_len,
- (uint32_t)uptr_value, tmp_cmd->length);
-
- ctrl_data = kzalloc(value_len+cmd_len, GFP_KERNEL);
- if (ctrl_data == 0) {
- pr_err("%s could not allocate memory\n", __func__);
- rc = -ENOMEM;
- goto end;
- }
- tmp_cmd = (struct msm_ctrl_cmd *)ctrl_data;
- if (copy_from_user((void *)ctrl_data, uptr_cmd,
- cmd_len)) {
+ if (copy_from_user(&tmp_cmd,
+ (void __user *)ioctl_ptr->ioctl_ptr, cmd_len)) {
pr_err("%s: copy_from_user failed.\n", __func__);
rc = -EINVAL;
goto end;
}
- tmp_cmd->value = (void *)(ctrl_data+cmd_len);
- if (uptr_value && tmp_cmd->length > 0) {
- if (copy_from_user((void *)tmp_cmd->value, uptr_value,
- value_len)) {
- pr_err("%s: copy_from_user failed, size=%d\n",
- __func__, value_len);
+ value_len = tmp_cmd.length;
+ ctrl_data = kzalloc(value_len+cmd_len, GFP_KERNEL);
+ if (!ctrl_data) {
+ pr_err("%s could not allocate memory\n", __func__);
+ rc = -ENOMEM;
+ goto end;
+ }
+
+ cmd_ptr = (struct msm_ctrl_cmd *) ctrl_data;
+ *cmd_ptr = tmp_cmd;
+ if (tmp_cmd.value && tmp_cmd.length > 0) {
+ cmd_ptr->value = (void *)(ctrl_data+cmd_len);
+ if (copy_from_user((void *)cmd_ptr->value,
+ (void __user *)tmp_cmd.value,
+ value_len)) {
+ pr_err("%s: copy_from_user failed.\n", __func__);
rc = -EINVAL;
goto end;
}
- } else
- tmp_cmd->value = NULL;
+ } else {
+ cmd_ptr->value = NULL;
+ }
+
+ D("%s: cmd type = %d, up1=0x%x, ulen1=%d, up2=0x%x, ulen2=%d\n",
+ __func__, tmp_cmd.type, (uint32_t)ioctl_ptr->ioctl_ptr, cmd_len,
+ (uint32_t)tmp_cmd.value, tmp_cmd.length);
ctrlcmd.type = MSM_V4L2_SET_CTRL_CMD;
ctrlcmd.length = cmd_len + value_len;
ctrlcmd.value = (void *)ctrl_data;
- if (tmp_cmd->timeout_ms > 0)
- ctrlcmd.timeout_ms = tmp_cmd->timeout_ms;
+ if (tmp_cmd.timeout_ms > 0)
+ ctrlcmd.timeout_ms = tmp_cmd.timeout_ms;
else
ctrlcmd.timeout_ms = 1000;
ctrlcmd.vnode_id = pcam->vnode_id;
@@ -618,17 +615,17 @@
rc = msm_server_control(&g_server_dev, &ctrlcmd);
D("%s: msm_server_control rc=%d\n", __func__, rc);
if (rc == 0) {
- if (uptr_value && tmp_cmd->length > 0 &&
- copy_to_user((void __user *)uptr_value,
- (void *)(ctrl_data+cmd_len), tmp_cmd->length)) {
+ if (tmp_cmd.value && tmp_cmd.length > 0 &&
+ copy_to_user((void __user *)tmp_cmd.value,
+ (void *)(ctrl_data+cmd_len), tmp_cmd.length)) {
pr_err("%s: copy_to_user failed, size=%d\n",
- __func__, tmp_cmd->length);
+ __func__, tmp_cmd.length);
rc = -EINVAL;
goto end;
}
- tmp_cmd->value = uptr_value;
- if (copy_to_user((void __user *)uptr_cmd,
- (void *)tmp_cmd, cmd_len)) {
+
+ if (copy_to_user((void __user *)ioctl_ptr->ioctl_ptr,
+ (void *)&tmp_cmd, cmd_len)) {
pr_err("%s: copy_to_user failed in cpy, size=%d\n",
__func__, cmd_len);
rc = -EINVAL;
@@ -637,8 +634,8 @@
}
end:
D("%s: END, type = %d, vaddr = 0x%x, vlen = %d, status = %d, rc = %d\n",
- __func__, tmp_cmd->type, (uint32_t)tmp_cmd->value,
- tmp_cmd->length, tmp_cmd->status, rc);
+ __func__, tmp_cmd.type, (uint32_t)tmp_cmd.value,
+ tmp_cmd.length, tmp_cmd.status, rc);
kfree(ctrl_data);
return rc;
}
@@ -655,8 +652,6 @@
pr_err("%s Invalid control\n", __func__);
return -EINVAL;
}
- if (ctrl->id == MSM_V4L2_PID_CTRL_CMD)
- return msm_server_proc_ctrl_cmd(pcam, ctrl, 1);
memset(ctrl_data, 0, sizeof(ctrl_data));
@@ -687,8 +682,6 @@
pr_err("%s Invalid control\n", __func__);
return -EINVAL;
}
- if (ctrl->id == MSM_V4L2_PID_CTRL_CMD)
- return msm_server_proc_ctrl_cmd(pcam, ctrl, 0);
memset(ctrl_data, 0, sizeof(ctrl_data));
@@ -1421,16 +1414,6 @@
g_server_dev.vfe_device[0], notification, arg);
}
break;
- case NOTIFY_VPE_MSG_EVT: {
- struct msm_cam_media_controller *pmctl =
- (struct msm_cam_media_controller *)
- v4l2_get_subdev_hostdata(sd);
- struct msm_vpe_resp *vdata = (struct msm_vpe_resp *)arg;
- msm_mctl_pp_notify(pmctl,
- (struct msm_mctl_pp_frame_info *)
- vdata->extdata);
- break;
- }
case NOTIFY_VFE_IRQ:{
struct msm_vfe_cfg_cmd cfg_cmd;
struct msm_camvfe_params vfe_params;
diff --git a/drivers/media/video/msm/server/msm_cam_server.h b/drivers/media/video/msm/server/msm_cam_server.h
index 2fe4c2b..677feaa 100644
--- a/drivers/media/video/msm/server/msm_cam_server.h
+++ b/drivers/media/video/msm/server/msm_cam_server.h
@@ -36,7 +36,7 @@
int msm_server_get_usecount(void);
int32_t msm_find_free_queue(void);
int msm_server_proc_ctrl_cmd(struct msm_cam_v4l2_device *pcam,
- struct v4l2_control *ctrl, int is_set_cmd);
+ struct msm_camera_v4l2_ioctl_t *ioctl_ptr, int is_set_cmd);
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,
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 9719307..db0dbc2 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -32,6 +32,7 @@
#include <media/v4l2-ctrls.h>
#include <media/v4l2-fh.h>
#include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
#include <linux/regulator/consumer.h>
#include <mach/clk.h>
#include <linux/clk.h>
@@ -58,6 +59,228 @@
printk(KERN_DEBUG "VCAP: " fmt, ## arg); \
} while (0)
+int vcap_reg_powerup(struct vcap_dev *dev)
+{
+ dev->fs_vcap = regulator_get(NULL, "fs_vcap");
+ if (IS_ERR(dev->fs_vcap)) {
+ pr_err("%s: Regulator FS_VCAP get failed %ld\n", __func__,
+ PTR_ERR(dev->fs_vcap));
+ dev->fs_vcap = NULL;
+ return -EINVAL;
+ } else if (regulator_enable(dev->fs_vcap)) {
+ pr_err("%s: Regulator FS_VCAP enable failed\n", __func__);
+ regulator_put(dev->fs_vcap);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+void vcap_reg_powerdown(struct vcap_dev *dev)
+{
+ if (dev->fs_vcap == NULL)
+ return;
+ regulator_disable(dev->fs_vcap);
+ regulator_put(dev->fs_vcap);
+ dev->fs_vcap = NULL;
+ return;
+}
+
+int config_gpios(int on, struct vcap_platform_data *pdata)
+{
+ int i, ret;
+ int num_gpios = pdata->num_gpios;
+ unsigned *gpios = pdata->gpios;
+
+ dprintk(4, "GPIO config start\n");
+ if (on) {
+ for (i = 0; i < num_gpios; i++) {
+ ret = gpio_request(gpios[i], "vcap:vc");
+ if (ret) {
+ pr_err("VCAP: failed at GPIO %d to request\n",
+ gpios[i]);
+ goto gpio_failed;
+ }
+ ret = gpio_direction_input(gpios[i]);
+ if (ret) {
+ pr_err("VCAP: failed at GPIO %d to set to input\n",
+ gpios[i]);
+ i++;
+ goto gpio_failed;
+ }
+ }
+ } else {
+ for (i = 0; i < num_gpios; i++)
+ gpio_free(gpios[i]);
+ }
+ dprintk(4, "GPIO config exit\n");
+ return 0;
+gpio_failed:
+ for (i--; i >= 0; i--)
+ gpio_free(gpios[i]);
+ return -EINVAL;
+}
+
+int vcap_clk_powerup(struct vcap_dev *dev, struct device *ddev,
+ unsigned long rate)
+{
+ int ret = 0;
+
+ dev->vcap_clk = clk_get(ddev, "core_clk");
+ if (IS_ERR(dev->vcap_clk)) {
+ dev->vcap_clk = NULL;
+ pr_err("%s: Could not clk_get core_clk\n", __func__);
+ clk_put(dev->vcap_clk);
+ dev->vcap_clk = NULL;
+ return -EINVAL;
+ }
+
+ clk_prepare(dev->vcap_clk);
+ ret = clk_enable(dev->vcap_clk);
+ if (ret) {
+ pr_err("%s: Failed core clk_enable %d\n", __func__, ret);
+ goto fail_vcap_clk_unprep;
+ }
+
+ rate = clk_round_rate(dev->vcap_clk, rate);
+ if (rate < 0) {
+ pr_err("%s: Failed core rnd_rate\n", __func__);
+ goto fail_vcap_clk;
+ }
+ ret = clk_set_rate(dev->vcap_clk, rate);
+ if (ret < 0) {
+ pr_err("%s: Failed core set_rate %d\n", __func__, ret);
+ goto fail_vcap_clk;
+ }
+
+ dev->vcap_npl_clk = clk_get(ddev, "vcap_npl_clk");
+ if (IS_ERR(dev->vcap_npl_clk)) {
+ dev->vcap_npl_clk = NULL;
+ pr_err("%s: Could not clk_get npl\n", __func__);
+ clk_put(dev->vcap_npl_clk);
+ dev->vcap_npl_clk = NULL;
+ goto fail_vcap_clk;
+ }
+
+ clk_prepare(dev->vcap_npl_clk);
+ ret = clk_enable(dev->vcap_npl_clk);
+ if (ret) {
+ pr_err("%s:Failed npl clk_enable %d\n", __func__, ret);
+ goto fail_vcap_npl_clk_unprep;
+ }
+
+ dev->vcap_p_clk = clk_get(ddev, "iface_clk");
+ if (IS_ERR(dev->vcap_p_clk)) {
+ dev->vcap_p_clk = NULL;
+ pr_err("%s: Could not clk_get pix(AHB)\n", __func__);
+ clk_put(dev->vcap_p_clk);
+ dev->vcap_p_clk = NULL;
+ goto fail_vcap_npl_clk;
+ }
+
+ clk_prepare(dev->vcap_p_clk);
+ ret = clk_enable(dev->vcap_p_clk);
+ if (ret) {
+ pr_err("%s: Failed pix(AHB) clk_enable %d\n", __func__, ret);
+ goto fail_vcap_p_clk_unprep;
+ }
+ return 0;
+
+fail_vcap_p_clk_unprep:
+ clk_unprepare(dev->vcap_p_clk);
+ clk_put(dev->vcap_p_clk);
+ dev->vcap_p_clk = NULL;
+
+fail_vcap_npl_clk:
+ clk_disable(dev->vcap_npl_clk);
+fail_vcap_npl_clk_unprep:
+ clk_unprepare(dev->vcap_npl_clk);
+ clk_put(dev->vcap_npl_clk);
+ dev->vcap_npl_clk = NULL;
+
+fail_vcap_clk:
+ clk_disable(dev->vcap_clk);
+fail_vcap_clk_unprep:
+ clk_unprepare(dev->vcap_clk);
+ clk_put(dev->vcap_clk);
+ dev->vcap_clk = NULL;
+ return -EINVAL;
+}
+
+void vcap_clk_powerdown(struct vcap_dev *dev)
+{
+ if (dev->vcap_p_clk != NULL) {
+ clk_disable(dev->vcap_p_clk);
+ clk_unprepare(dev->vcap_p_clk);
+ clk_put(dev->vcap_p_clk);
+ dev->vcap_p_clk = NULL;
+ }
+
+ if (dev->vcap_npl_clk != NULL) {
+ clk_disable(dev->vcap_npl_clk);
+ clk_unprepare(dev->vcap_npl_clk);
+ clk_put(dev->vcap_npl_clk);
+ dev->vcap_npl_clk = NULL;
+ }
+
+ if (dev->vcap_clk != NULL) {
+ clk_disable(dev->vcap_clk);
+ clk_unprepare(dev->vcap_clk);
+ clk_put(dev->vcap_clk);
+ dev->vcap_clk = NULL;
+ }
+}
+
+int vcap_get_bus_client_handle(struct vcap_dev *dev)
+{
+ struct msm_bus_scale_pdata *vcap_axi_client_pdata =
+ dev->vcap_pdata->bus_client_pdata;
+ dev->bus_client_handle =
+ msm_bus_scale_register_client(vcap_axi_client_pdata);
+
+ return 0;
+}
+
+int vcap_enable(struct vcap_dev *dev, struct device *ddev,
+ unsigned long rate)
+{
+ int rc;
+
+ rc = vcap_reg_powerup(dev);
+ if (rc < 0)
+ goto reg_failed;
+ rc = vcap_clk_powerup(dev, ddev, rate);
+ if (rc < 0)
+ goto clk_failed;
+ rc = vcap_get_bus_client_handle(dev);
+ if (rc < 0)
+ goto bus_r_failed;
+ rc = config_gpios(1, dev->vcap_pdata);
+ if (rc < 0)
+ goto gpio_failed;
+ return 0;
+
+gpio_failed:
+ msm_bus_scale_unregister_client(dev->bus_client_handle);
+ dev->bus_client_handle = 0;
+bus_r_failed:
+ vcap_clk_powerdown(dev);
+clk_failed:
+ vcap_reg_powerdown(dev);
+reg_failed:
+ return rc;
+}
+
+int vcap_disable(struct vcap_dev *dev)
+{
+ config_gpios(0, dev->vcap_pdata);
+
+ msm_bus_scale_unregister_client(dev->bus_client_handle);
+ dev->bus_client_handle = 0;
+ vcap_clk_powerdown(dev);
+ vcap_reg_powerdown(dev);
+ return 0;
+}
+
enum vcap_op_mode determine_mode(struct vcap_client_data *cd)
{
if (cd->set_cap == 1 && cd->set_vp_o == 0 &&
@@ -502,7 +725,7 @@
int size;
struct vcap_priv_fmt *priv_fmt;
struct v4l2_format_vc_ext *vc_format;
- struct vcap_client_data *c_data = file->private_data;
+ struct vcap_client_data *c_data = to_client_data(file->private_data);
priv_fmt = (struct vcap_priv_fmt *) f->fmt.raw_data;
@@ -511,8 +734,6 @@
vc_format = (struct v4l2_format_vc_ext *) &priv_fmt->u.timing;
c_data->vc_format = *vc_format;
- config_vc_format(c_data);
-
size = (c_data->vc_format.hactive_end -
c_data->vc_format.hactive_start);
@@ -525,11 +746,9 @@
size *= (c_data->vc_format.vactive_end -
c_data->vc_format.vactive_start);
priv_fmt->u.timing.sizeimage = size;
- vcap_ctrl->vc_client = c_data;
c_data->set_cap = true;
break;
case VP_IN_TYPE:
- vcap_ctrl->vp_client = c_data;
c_data->vp_in_fmt.width = priv_fmt->u.pix.width;
c_data->vp_in_fmt.height = priv_fmt->u.pix.height;
c_data->vp_in_fmt.pixfmt = priv_fmt->u.pix.pixelformat;
@@ -546,7 +765,6 @@
c_data->set_decode = true;
break;
case VP_OUT_TYPE:
- vcap_ctrl->vp_client = c_data;
c_data->vp_out_fmt.width = priv_fmt->u.pix.width;
c_data->vp_out_fmt.height = priv_fmt->u.pix.height;
c_data->vp_out_fmt.pixfmt = priv_fmt->u.pix.pixelformat;
@@ -572,7 +790,7 @@
static int vidioc_reqbufs(struct file *file, void *priv,
struct v4l2_requestbuffers *rb)
{
- struct vcap_client_data *c_data = file->private_data;
+ struct vcap_client_data *c_data = to_client_data(file->private_data);
int rc;
dprintk(3, "In Req Buf %08x\n", (unsigned int)rb->type);
@@ -631,7 +849,7 @@
static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
{
- struct vcap_client_data *c_data = file->private_data;
+ struct vcap_client_data *c_data = to_client_data(file->private_data);
switch (p->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
@@ -645,7 +863,7 @@
static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
{
- struct vcap_client_data *c_data = file->private_data;
+ struct vcap_client_data *c_data = to_client_data(file->private_data);
struct vb2_buffer *vb;
struct vb2_queue *q;
int rc;
@@ -706,7 +924,7 @@
static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
{
- struct vcap_client_data *c_data = file->private_data;
+ struct vcap_client_data *c_data = to_client_data(file->private_data);
int rc;
dprintk(3, "In DQ Buf %08x\n", (unsigned int)p->type);
@@ -764,10 +982,33 @@
return 0;
}
+int request_bus_bw(struct vcap_dev *dev, unsigned long rate)
+{
+ struct msm_bus_paths *bus_vectors;
+ int idx, length;
+ bus_vectors = dev->vcap_pdata->bus_client_pdata->usecase;
+ length = dev->vcap_pdata->bus_client_pdata->num_usecases;
+ idx = 0;
+ do {
+ if (rate <= bus_vectors[idx].vectors[0].ab)
+ break;
+ idx++;
+ } while (idx < length);
+ if (idx == length) {
+ pr_err("VCAP: Defaulting to highest BW request\n");
+ idx--;
+ }
+ msm_bus_scale_client_update_request(dev->bus_client_handle, idx);
+ return 0;
+}
+
static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
{
- struct vcap_client_data *c_data = file->private_data;
+ struct vcap_client_data *c_data = to_client_data(file->private_data);
+ struct vcap_dev *dev = c_data->dev;
+ unsigned long flags;
int rc;
+ unsigned long rate;
dprintk(3, "In Stream ON\n");
if (determine_mode(c_data) != c_data->op_mode) {
@@ -777,25 +1018,97 @@
switch (c_data->op_mode) {
case VC_VCAP_OP:
+ spin_lock_irqsave(&dev->dev_slock, flags);
+ if (dev->vc_resource) {
+ pr_err("VCAP Err: %s: VC resource taken", __func__);
+ spin_unlock_irqrestore(&dev->dev_slock, flags);
+ return -EBUSY;
+ }
+ dev->vc_resource = 1;
+ spin_unlock_irqrestore(&dev->dev_slock, flags);
+
c_data->dev->vc_client = c_data;
+
+ if (!c_data->vc_format.clk_freq) {
+ rc = -EINVAL;
+ goto free_res;
+ }
+
+ rate = c_data->vc_format.clk_freq;
+ rate = clk_round_rate(dev->vcap_clk, rate);
+ if (rate <= 0) {
+ pr_err("%s: Failed core rnd_rate\n", __func__);
+ rc = -EINVAL;
+ goto free_res;
+ }
+ rc = clk_set_rate(dev->vcap_clk, rate);
+ if (rc < 0)
+ goto free_res;
+
+ rate = (c_data->vc_format.hactive_end -
+ c_data->vc_format.hactive_start);
+
+ if (c_data->vc_format.color_space)
+ rate *= 3;
+ else
+ rate *= 2;
+
+ rate *= (c_data->vc_format.vactive_end -
+ c_data->vc_format.vactive_start);
+ rate *= c_data->vc_format.frame_rate;
+ if (rate == 0)
+ goto free_res;
+
+ rc = request_bus_bw(dev, rate);
+ if (rc < 0)
+ goto free_res;
+
config_vc_format(c_data);
- return vb2_streamon(&c_data->vc_vidq, i);
+ rc = vb2_streamon(&c_data->vc_vidq, i);
+ if (rc < 0)
+ goto free_res;
+ break;
case VP_VCAP_OP:
+ spin_lock_irqsave(&dev->dev_slock, flags);
+ if (dev->vp_resource) {
+ pr_err("VCAP Err: %s: VP resource taken", __func__);
+ spin_unlock_irqrestore(&dev->dev_slock, flags);
+ return -EBUSY;
+ }
+ dev->vp_resource = 1;
+ spin_unlock_irqrestore(&dev->dev_slock, flags);
+ c_data->dev->vp_client = c_data;
+
+ rate = 160000000;
+ rate = clk_round_rate(dev->vcap_clk, rate);
+ if (rate <= 0) {
+ pr_err("%s: Failed core rnd_rate\n", __func__);
+ rc = -EINVAL;
+ goto free_res;
+ }
+ rc = clk_set_rate(dev->vcap_clk, rate);
+ if (rc < 0)
+ goto free_res;
+
+ rate = c_data->vp_out_fmt.width *
+ c_data->vp_out_fmt.height * 240;
+ rc = request_bus_bw(dev, rate);
+ if (rc < 0)
+ goto free_res;
+
rc = streamon_validate_q(&c_data->vp_in_vidq);
if (rc < 0)
- return rc;
+ goto free_res;
rc = streamon_validate_q(&c_data->vp_out_vidq);
if (rc < 0)
- return rc;
-
- c_data->dev->vp_client = c_data;
+ goto free_res;
rc = config_vp_format(c_data);
if (rc < 0)
- return rc;
+ goto free_res;
rc = init_motion_buf(c_data);
if (rc < 0)
- return rc;
+ goto free_res;
if (c_data->vid_vp_action.nr_enabled) {
rc = init_nr_buf(c_data);
if (rc < 0)
@@ -803,6 +1116,7 @@
}
c_data->vid_vp_action.vp_state = VP_FRAME1;
+ c_data->streaming = 1;
rc = vb2_streamon(&c_data->vp_in_vidq,
V4L2_BUF_TYPE_INTERLACED_IN_DECODER);
@@ -813,39 +1127,85 @@
V4L2_BUF_TYPE_VIDEO_OUTPUT);
if (rc < 0)
goto s_on_deinit_nr_buf;
- return rc;
+ break;
case VC_AND_VP_VCAP_OP:
+ spin_lock_irqsave(&dev->dev_slock, flags);
+ if (dev->vc_resource || dev->vp_resource) {
+ pr_err("VCAP Err: %s: VC/VP resource taken",
+ __func__);
+ spin_unlock_irqrestore(&dev->dev_slock, flags);
+ return -EBUSY;
+ }
+ dev->vc_resource = 1;
+ dev->vp_resource = 1;
+ spin_unlock_irqrestore(&dev->dev_slock, flags);
+ c_data->dev->vc_client = c_data;
+ c_data->dev->vp_client = c_data;
+
+ if (!c_data->vc_format.clk_freq) {
+ rc = -EINVAL;
+ goto free_res;
+ }
+
+ rate = c_data->vc_format.clk_freq;
+ rate = clk_round_rate(dev->vcap_clk, rate);
+ if (rate <= 0) {
+ pr_err("%s: Failed core rnd_rate\n", __func__);
+ rc = -EINVAL;
+ goto free_res;
+ }
+ rc = clk_set_rate(dev->vcap_clk, rate);
+ if (rc < 0)
+ goto free_res;
+
+ rate = (c_data->vc_format.hactive_end -
+ c_data->vc_format.hactive_start);
+
+ if (c_data->vc_format.color_space)
+ rate *= 3;
+ else
+ rate *= 2;
+
+ rate *= (c_data->vc_format.vactive_end -
+ c_data->vc_format.vactive_start);
+ rate *= c_data->vc_format.frame_rate;
+ rate *= 2;
+ if (rate == 0)
+ goto free_res;
+
+ rc = request_bus_bw(dev, rate);
+ if (rc < 0)
+ goto free_res;
+
rc = streamon_validate_q(&c_data->vc_vidq);
if (rc < 0)
return rc;
rc = streamon_validate_q(&c_data->vp_in_vidq);
if (rc < 0)
- return rc;
+ goto free_res;
rc = streamon_validate_q(&c_data->vp_out_vidq);
if (rc < 0)
- return rc;
-
- c_data->dev->vc_client = c_data;
- c_data->dev->vp_client = c_data;
- c_data->dev->vc_to_vp_work.cd = c_data;
+ goto free_res;
rc = config_vc_format(c_data);
if (rc < 0)
- return rc;
+ goto free_res;
rc = config_vp_format(c_data);
if (rc < 0)
- return rc;
+ goto free_res;
rc = init_motion_buf(c_data);
if (rc < 0)
- return rc;
+ goto free_res;
+
if (c_data->vid_vp_action.nr_enabled) {
rc = init_nr_buf(c_data);
if (rc < 0)
goto s_on_deinit_m_buf;
}
- c_data->streaming = 1;
+ c_data->dev->vc_to_vp_work.cd = c_data;
c_data->vid_vp_action.vp_state = VP_FRAME1;
+ c_data->streaming = 1;
/* These stream on calls should not fail */
rc = vb2_streamon(&c_data->vc_vidq,
@@ -862,7 +1222,7 @@
V4L2_BUF_TYPE_VIDEO_OUTPUT);
if (rc < 0)
goto s_on_deinit_nr_buf;
- return rc;
+ break;
default:
pr_err("VCAP Error: %s: Operation Mode type", __func__);
return -ENOTRECOVERABLE;
@@ -874,6 +1234,21 @@
deinit_nr_buf(c_data);
s_on_deinit_m_buf:
deinit_motion_buf(c_data);
+free_res:
+ spin_lock_irqsave(&dev->dev_slock, flags);
+ if (c_data->op_mode == VC_VCAP_OP) {
+ dev->vc_resource = 0;
+ c_data->dev->vc_client = NULL;
+ } else if (c_data->op_mode == VP_VCAP_OP) {
+ dev->vp_resource = 0;
+ c_data->dev->vp_client = NULL;
+ } else if (c_data->op_mode == VC_AND_VP_VCAP_OP) {
+ c_data->dev->vc_client = NULL;
+ c_data->dev->vp_client = NULL;
+ dev->vc_resource = 0;
+ dev->vp_resource = 0;
+ }
+ spin_unlock_irqrestore(&dev->dev_slock, flags);
return rc;
}
@@ -893,22 +1268,51 @@
static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
{
- struct vcap_client_data *c_data = file->private_data;
+ struct vcap_client_data *c_data = to_client_data(file->private_data);
+ struct vcap_dev *dev = c_data->dev;
+ unsigned long flags;
int rc;
switch (c_data->op_mode) {
case VC_VCAP_OP:
+ if (c_data != dev->vc_client) {
+ pr_err("VCAP Err: %s: VC held by other client",
+ __func__);
+ return -EBUSY;
+ }
+ spin_lock_irqsave(&dev->dev_slock, flags);
+ if (!dev->vc_resource) {
+ pr_err("VCAP Err: %s: VC res not acquired", __func__);
+ spin_unlock_irqrestore(&dev->dev_slock, flags);
+ return -EBUSY;
+ }
+ dev->vc_resource = 0;
+ spin_unlock_irqrestore(&dev->dev_slock, flags);
rc = vb2_streamoff(&c_data->vc_vidq, i);
if (rc >= 0)
atomic_set(&c_data->dev->vc_enabled, 0);
return rc;
case VP_VCAP_OP:
+ if (c_data != dev->vp_client) {
+ pr_err("VCAP Err: %s: VP held by other client",
+ __func__);
+ return -EBUSY;
+ }
+ spin_lock_irqsave(&dev->dev_slock, flags);
+ if (!dev->vp_resource) {
+ pr_err("VCAP Err: %s: VP res not acquired", __func__);
+ spin_unlock_irqrestore(&dev->dev_slock, flags);
+ return -EBUSY;
+ }
+ dev->vp_resource = 0;
+ spin_unlock_irqrestore(&dev->dev_slock, flags);
rc = streamoff_validate_q(&c_data->vp_in_vidq);
if (rc < 0)
return rc;
rc = streamoff_validate_q(&c_data->vp_out_vidq);
if (rc < 0)
return rc;
+ c_data->streaming = 0;
/* These stream on calls should not fail */
rc = vb2_streamoff(&c_data->vp_in_vidq,
@@ -927,6 +1331,21 @@
atomic_set(&c_data->dev->vp_enabled, 0);
return rc;
case VC_AND_VP_VCAP_OP:
+ if (c_data != dev->vp_client || c_data != dev->vc_client) {
+ pr_err("VCAP Err: %s: VC/VP held by other client",
+ __func__);
+ return -EBUSY;
+ }
+ spin_lock_irqsave(&dev->dev_slock, flags);
+ if (!(dev->vc_resource || dev->vp_resource)) {
+ pr_err("VCAP Err: %s: VC or VP res not acquired",
+ __func__);
+ spin_unlock_irqrestore(&dev->dev_slock, flags);
+ return -EBUSY;
+ }
+ dev->vc_resource = 0;
+ dev->vp_resource = 0;
+ spin_unlock_irqrestore(&dev->dev_slock, flags);
rc = streamoff_validate_q(&c_data->vc_vidq);
if (rc < 0)
return rc;
@@ -967,6 +1386,36 @@
return 0;
}
+static int vidioc_subscribe_event(struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub)
+{
+ int rc;
+ if (sub->type == V4L2_EVENT_ALL) {
+ sub->type = V4L2_EVENT_PRIVATE_START +
+ VCAP_GENERIC_NOTIFY_EVENT;
+ sub->id = 0;
+ do {
+ rc = v4l2_event_subscribe(fh, sub, 16);
+ if (rc < 0) {
+ sub->type = V4L2_EVENT_ALL;
+ v4l2_event_unsubscribe(fh, sub);
+ return rc;
+ }
+ sub->type++;
+ } while (sub->type !=
+ V4L2_EVENT_PRIVATE_START + VCAP_MAX_NOTIFY_EVENT);
+ } else {
+ rc = v4l2_event_subscribe(fh, sub, 16);
+ }
+ return rc;
+}
+
+static int vidioc_unsubscribe_event(struct v4l2_fh *fh,
+ struct v4l2_event_subscription *sub)
+{
+ return v4l2_event_unsubscribe(fh, sub);
+}
+
/* VCAP fops */
static void *vcap_ops_get_userptr(void *alloc_ctx, unsigned long vaddr,
unsigned long size, int write)
@@ -995,6 +1444,7 @@
struct vcap_dev *dev = video_drvdata(file);
struct vcap_client_data *c_data;
struct vb2_queue *q;
+ unsigned long flags;
int ret;
c_data = kzalloc(sizeof(*c_data), GFP_KERNEL);
if (!dev)
@@ -1047,10 +1497,29 @@
INIT_LIST_HEAD(&c_data->vid_vc_action.active);
INIT_LIST_HEAD(&c_data->vid_vp_action.in_active);
INIT_LIST_HEAD(&c_data->vid_vp_action.out_active);
- file->private_data = c_data;
+ v4l2_fh_init(&c_data->vfh, dev->vfd);
+ v4l2_fh_add(&c_data->vfh);
+
+ spin_lock_irqsave(&dev->dev_slock, flags);
+ atomic_inc(&dev->open_clients);
+ ret = atomic_read(&dev->open_clients);
+ spin_unlock_irqrestore(&dev->dev_slock, flags);
+ if (ret == 1) {
+ ret = vcap_enable(dev, dev->ddev, 54860000);
+ if (ret < 0) {
+ pr_err("Err: %s: Power on vcap failed", __func__);
+ goto vcap_power_failed;
+ }
+ }
+
+ file->private_data = &c_data->vfh;
return 0;
+vcap_power_failed:
+ v4l2_fh_del(&c_data->vfh);
+ v4l2_fh_exit(&c_data->vfh);
+ vb2_queue_release(&c_data->vp_out_vidq);
vp_out_q_failed:
vb2_queue_release(&c_data->vp_in_vidq);
vp_in_q_failed:
@@ -1062,12 +1531,29 @@
static int vcap_close(struct file *file)
{
- struct vcap_client_data *c_data = file->private_data;
+ struct vcap_dev *dev = video_drvdata(file);
+ struct vcap_client_data *c_data = to_client_data(file->private_data);
+ unsigned long flags;
+ int ret;
+
+ if (c_data == NULL)
+ return 0;
+
+ spin_lock_irqsave(&dev->dev_slock, flags);
+ atomic_dec(&dev->open_clients);
+ ret = atomic_read(&dev->open_clients);
+ spin_unlock_irqrestore(&dev->dev_slock, flags);
+ if (ret == 0)
+ vcap_disable(dev);
+ v4l2_fh_del(&c_data->vfh);
+ v4l2_fh_exit(&c_data->vfh);
vb2_queue_release(&c_data->vp_out_vidq);
vb2_queue_release(&c_data->vp_in_vidq);
vb2_queue_release(&c_data->vc_vidq);
- c_data->dev->vc_client = NULL;
- c_data->dev->vp_client = NULL;
+ if (c_data->dev->vc_client == c_data)
+ c_data->dev->vc_client = NULL;
+ if (c_data->dev->vp_client == c_data)
+ c_data->dev->vp_client = NULL;
kfree(c_data);
return 0;
}
@@ -1103,29 +1589,35 @@
static unsigned int vcap_poll(struct file *file,
struct poll_table_struct *wait)
{
- struct vcap_client_data *c_data = file->private_data;
+ struct vcap_client_data *c_data = to_client_data(file->private_data);
struct vb2_queue *q;
unsigned int mask = 0;
+ dprintk(1, "Enter slect/poll\n");
+
switch (c_data->op_mode) {
case VC_VCAP_OP:
q = &c_data->vc_vidq;
- return vb2_poll(q, file, wait);
+ mask = vb2_poll(q, file, wait);
+ break;
case VP_VCAP_OP:
q = &c_data->vp_in_vidq;
mask = poll_work(q, file, wait, 0);
q = &c_data->vp_out_vidq;
mask |= poll_work(q, file, wait, 1);
- return mask;
+ break;
case VC_AND_VP_VCAP_OP:
q = &c_data->vp_out_vidq;
mask = poll_work(q, file, wait, 0);
- return mask;
+ break;
default:
pr_err("VCAP Error: %s: Unknown operation mode", __func__);
return POLLERR;
}
- return 0;
+ if (v4l2_event_pending(&c_data->vfh))
+ mask |= POLLPRI;
+ poll_wait(file, &(c_data->vfh.wait), wait);
+ return mask;
}
/* V4L2 and video device structures */
@@ -1153,6 +1645,9 @@
.vidioc_dqbuf = vidioc_dqbuf,
.vidioc_streamon = vidioc_streamon,
.vidioc_streamoff = vidioc_streamoff,
+
+ .vidioc_subscribe_event = vidioc_subscribe_event,
+ .vidioc_unsubscribe_event = vidioc_unsubscribe_event,
};
static struct video_device vcap_template = {
@@ -1162,220 +1657,6 @@
.release = video_device_release,
};
-int vcap_reg_powerup(struct vcap_dev *dev)
-{
- dev->fs_vcap = regulator_get(NULL, "fs_vcap");
- if (IS_ERR(dev->fs_vcap)) {
- pr_err("%s: Regulator FS_VCAP get failed %ld\n", __func__,
- PTR_ERR(dev->fs_vcap));
- dev->fs_vcap = NULL;
- return -EINVAL;
- } else if (regulator_enable(dev->fs_vcap)) {
- pr_err("%s: Regulator FS_VCAP enable failed\n", __func__);
- regulator_put(dev->fs_vcap);
- return -EINVAL;
- }
- return 0;
-}
-
-void vcap_reg_powerdown(struct vcap_dev *dev)
-{
- if (dev->fs_vcap == NULL)
- return;
- regulator_disable(dev->fs_vcap);
- regulator_put(dev->fs_vcap);
- dev->fs_vcap = NULL;
- return;
-}
-
-int config_gpios(int on, struct vcap_platform_data *pdata)
-{
- int i, ret;
- int num_gpios = pdata->num_gpios;
- unsigned *gpios = pdata->gpios;
-
- if (on) {
- for (i = 0; i < num_gpios; i++) {
- ret = gpio_request(gpios[i], "vcap:vc");
- if (ret) {
- pr_err("VCAP: failed at GPIO %d to request\n",
- gpios[i]);
- goto gpio_failed;
- }
- ret = gpio_direction_input(gpios[i]);
- if (ret) {
- pr_err("VCAP: failed at GPIO %d to set to input\n",
- gpios[i]);
- i++;
- goto gpio_failed;
- }
- }
- } else {
- for (i = 0; i < num_gpios; i++)
- gpio_free(gpios[i]);
- }
- dprintk(2, "GPIO config done\n");
- return 0;
-gpio_failed:
- for (i--; i >= 0; i--)
- gpio_free(gpios[i]);
- return -EINVAL;
-}
-
-int vcap_clk_powerup(struct vcap_dev *dev, struct device *ddev)
-{
- int ret = 0;
-
- dev->vcap_clk = clk_get(ddev, "core_clk");
- if (IS_ERR(dev->vcap_clk)) {
- dev->vcap_clk = NULL;
- pr_err("%s: Could not clk_get core_clk\n", __func__);
- clk_put(dev->vcap_clk);
- dev->vcap_clk = NULL;
- return -EINVAL;
- }
-
- clk_prepare(dev->vcap_clk);
- ret = clk_enable(dev->vcap_clk);
- if (ret) {
- pr_err("%s: Failed core clk_enable %d\n", __func__, ret);
- goto fail_vcap_clk_unprep;
- }
-
- clk_set_rate(dev->vcap_clk, 160000000);
- if (ret) {
- pr_err("%s: Failed core set_rate %d\n", __func__, ret);
- goto fail_vcap_clk;
- }
-
- dev->vcap_npl_clk = clk_get(ddev, "vcap_npl_clk");
- if (IS_ERR(dev->vcap_npl_clk)) {
- dev->vcap_npl_clk = NULL;
- pr_err("%s: Could not clk_get npl\n", __func__);
- clk_put(dev->vcap_npl_clk);
- dev->vcap_npl_clk = NULL;
- goto fail_vcap_clk;
- }
-
- clk_prepare(dev->vcap_npl_clk);
- ret = clk_enable(dev->vcap_npl_clk);
- if (ret) {
- pr_err("%s:Failed npl clk_enable %d\n", __func__, ret);
- goto fail_vcap_npl_clk_unprep;
- }
-
- dev->vcap_p_clk = clk_get(ddev, "iface_clk");
- if (IS_ERR(dev->vcap_p_clk)) {
- dev->vcap_p_clk = NULL;
- pr_err("%s: Could not clk_get pix(AHB)\n", __func__);
- clk_put(dev->vcap_p_clk);
- dev->vcap_p_clk = NULL;
- goto fail_vcap_npl_clk;
- }
-
- clk_prepare(dev->vcap_p_clk);
- ret = clk_enable(dev->vcap_p_clk);
- if (ret) {
- pr_err("%s: Failed pix(AHB) clk_enable %d\n", __func__, ret);
- goto fail_vcap_p_clk_unprep;
- }
- return 0;
-
-fail_vcap_p_clk_unprep:
- clk_unprepare(dev->vcap_p_clk);
- clk_put(dev->vcap_p_clk);
- dev->vcap_p_clk = NULL;
-
-fail_vcap_npl_clk:
- clk_disable(dev->vcap_npl_clk);
-fail_vcap_npl_clk_unprep:
- clk_unprepare(dev->vcap_npl_clk);
- clk_put(dev->vcap_npl_clk);
- dev->vcap_npl_clk = NULL;
-
-fail_vcap_clk:
- clk_disable(dev->vcap_clk);
-fail_vcap_clk_unprep:
- clk_unprepare(dev->vcap_clk);
- clk_put(dev->vcap_clk);
- dev->vcap_clk = NULL;
- return -EINVAL;
-}
-
-void vcap_clk_powerdown(struct vcap_dev *dev)
-{
- if (dev->vcap_p_clk != NULL) {
- clk_disable(dev->vcap_p_clk);
- clk_unprepare(dev->vcap_p_clk);
- clk_put(dev->vcap_p_clk);
- dev->vcap_p_clk = NULL;
- }
-
- if (dev->vcap_npl_clk != NULL) {
- clk_disable(dev->vcap_npl_clk);
- clk_unprepare(dev->vcap_npl_clk);
- clk_put(dev->vcap_npl_clk);
- dev->vcap_npl_clk = NULL;
- }
-
- if (dev->vcap_clk != NULL) {
- clk_disable(dev->vcap_clk);
- clk_unprepare(dev->vcap_clk);
- clk_put(dev->vcap_clk);
- dev->vcap_clk = NULL;
- }
-}
-
-int vcap_get_bus_client_handle(struct vcap_dev *dev)
-{
- struct msm_bus_scale_pdata *vcap_axi_client_pdata =
- dev->vcap_pdata->bus_client_pdata;
- dev->bus_client_handle =
- msm_bus_scale_register_client(vcap_axi_client_pdata);
-
- return 0;
-}
-
-int vcap_enable(struct vcap_dev *dev, struct device *ddev)
-{
- int rc;
-
- rc = vcap_reg_powerup(dev);
- if (rc < 0)
- goto reg_failed;
- rc = vcap_clk_powerup(dev, ddev);
- if (rc < 0)
- goto clk_failed;
- rc = vcap_get_bus_client_handle(dev);
- if (rc < 0)
- goto bus_r_failed;
- config_gpios(1, dev->vcap_pdata);
- if (rc < 0)
- goto gpio_failed;
- return 0;
-
-gpio_failed:
- msm_bus_scale_unregister_client(dev->bus_client_handle);
- dev->bus_client_handle = 0;
-bus_r_failed:
- vcap_clk_powerdown(dev);
-clk_failed:
- vcap_reg_powerdown(dev);
-reg_failed:
- return rc;
-}
-
-int vcap_disable(struct vcap_dev *dev)
-{
- config_gpios(0, dev->vcap_pdata);
-
- msm_bus_scale_unregister_client(dev->bus_client_handle);
- dev->bus_client_handle = 0;
- vcap_clk_powerdown(dev);
- vcap_reg_powerdown(dev);
- return 0;
-}
-
static irqreturn_t vcap_vp_handler(int irq_num, void *data)
{
return vp_handler(vcap_ctrl);
@@ -1465,10 +1746,10 @@
if (ret)
goto free_resource;
- ret = vcap_enable(dev, &pdev->dev);
+ ret = vcap_enable(dev, &pdev->dev, 54860000);
if (ret)
goto unreg_dev;
- msm_bus_scale_client_update_request(dev->bus_client_handle, 3);
+ msm_bus_scale_client_update_request(dev->bus_client_handle, 0);
ret = detect_vc(dev);
@@ -1504,6 +1785,10 @@
atomic_set(&dev->vc_enabled, 0);
atomic_set(&dev->vp_enabled, 0);
+ atomic_set(&dev->open_clients, 0);
+ dev->ddev = &pdev->dev;
+ spin_lock_init(&dev->dev_slock);
+ vcap_disable(dev);
dprintk(1, "Exit probe succesfully");
return 0;
diff --git a/drivers/media/video/vcap_vc.c b/drivers/media/video/vcap_vc.c
index 2c4a243..ad0718e 100644
--- a/drivers/media/video/vcap_vc.c
+++ b/drivers/media/video/vcap_vc.c
@@ -22,6 +22,7 @@
#include <mach/clk.h>
#include <linux/clk.h>
+#include <media/v4l2-event.h>
#include <media/vcap_v4l2.h>
#include <media/vcap_fmt.h>
#include "vcap_vc.h"
@@ -113,14 +114,40 @@
struct vcap_buffer *buf;
struct vb2_buffer *vb = NULL;
struct vcap_client_data *c_data;
-
+ struct v4l2_event v4l2_evt;
irq = readl_relaxed(VCAP_VC_INT_STATUS);
dprintk(1, "%s: irq=0x%08x\n", __func__, irq);
- vc_buf_status = irq & VC_BUFFER_WRITTEN;
+ v4l2_evt.id = 0;
+ if (irq & 0x8000200) {
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VC_PIX_ERR_EVENT;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
+ }
+ if (irq & 0x40000200) {
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VC_LINE_ERR_EVENT;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
+ }
+ if (irq & 0x20000200) {
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VC_VSYNC_ERR_EVENT;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
+ }
+ if (irq & 0x00000800) {
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VC_NPL_OFLOW_ERR_EVENT;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
+ }
+ if (irq & 0x00000400) {
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VC_LBUF_OFLOW_ERR_EVENT;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
+ }
+ vc_buf_status = irq & VC_BUFFER_WRITTEN;
dprintk(1, "Done buf status = %d\n", vc_buf_status);
if (vc_buf_status == VC_NO_BUF) {
@@ -139,8 +166,11 @@
spin_lock(&dev->vc_client->cap_slock);
if (list_empty(&dev->vc_client->vid_vc_action.active)) {
/* Just leave we have no new queued buffers */
- writel_relaxed(irq, VCAP_VC_INT_CLEAR);
spin_unlock(&dev->vc_client->cap_slock);
+ writel_relaxed(irq, VCAP_VC_INT_CLEAR);
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VC_BUF_OVERWRITE_EVENT;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
dprintk(1, "We have no more avilable buffers\n");
return IRQ_HANDLED;
}
@@ -166,6 +196,9 @@
spin_lock(&dev->vc_client->cap_slock);
if (list_empty(&dev->vc_client->vid_vc_action.active)) {
spin_unlock(&dev->vc_client->cap_slock);
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VC_BUF_OVERWRITE_EVENT;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
writel_relaxed(irq, VCAP_VC_INT_CLEAR);
return IRQ_HANDLED;
}
@@ -187,8 +220,11 @@
spin_lock(&dev->vc_client->cap_slock);
vb = &dev->vc_client->vid_vc_action.buf2->vb;
if (list_empty(&dev->vc_client->vid_vc_action.active)) {
- writel_relaxed(irq, VCAP_VC_INT_CLEAR);
spin_unlock(&dev->vc_client->cap_slock);
+ writel_relaxed(irq, VCAP_VC_INT_CLEAR);
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VC_BUF_OVERWRITE_EVENT;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
return IRQ_HANDLED;
}
buf = list_entry(dev->vc_client->vid_vc_action.active.next,
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index f8dfdc1..1b503ba 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -20,6 +20,7 @@
#include <mach/clk.h>
#include <linux/clk.h>
+#include <media/v4l2-event.h>
#include <media/vcap_v4l2.h>
#include <media/vcap_fmt.h>
#include "vcap_vp.h"
@@ -254,13 +255,35 @@
{
struct vcap_client_data *c_data;
struct vp_action *vp_act;
+ struct v4l2_event v4l2_evt;
uint32_t irq;
int rc;
irq = readl_relaxed(VCAP_VP_INT_STATUS);
+ if (irq & 0x02000000) {
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VP_REG_R_ERR_EVENT;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
+ }
+ if (irq & 0x01000000) {
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VC_LINE_ERR_EVENT;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
+ }
+ if (irq & 0x00020000) {
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VP_IN_HEIGHT_ERR_EVENT;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
+ }
+ if (irq & 0x00010000) {
+ v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
+ VCAP_VP_IN_WIDTH_ERR_EVENT;
+ v4l2_event_queue(dev->vfd, &v4l2_evt);
+ }
+
dprintk(1, "%s: irq=0x%08x\n", __func__, irq);
- if (!irq & VP_PIC_DONE) {
+ if (!(irq & VP_PIC_DONE)) {
writel_relaxed(irq, VCAP_VP_INT_CLEAR);
pr_err("VP IRQ shows some error\n");
return IRQ_HANDLED;
@@ -530,7 +553,7 @@
chroma_fmt << 11 | 0x2 << 4, VCAP_VP_IN_CONFIG);
chroma_fmt = 0;
- if (c_data->vp_in_fmt.pixfmt == V4L2_PIX_FMT_NV16)
+ if (c_data->vp_out_fmt.pixfmt == V4L2_PIX_FMT_NV16)
chroma_fmt = 1;
writel_relaxed((c_data->vp_in_fmt.width / 16) << 20 |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index f4e7fda..8c392fc 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1043,6 +1043,18 @@
read/write capability to registers which are part of the
WCD9310 core and gives the ability to use the WCD9310 codec.
+config WCD9320_CODEC
+ tristate "WCD9320 Codec"
+ select SLIMBUS
+ select MFD_CORE
+ help
+ Enables the WCD9xxx codec core driver. The core driver provides
+ read/write capability to registers which are part of the
+ WCD9320 core and gives the ability to use the WCD9320 codec.
+ The WCD9320 codec support either I2C/I2S or Slimbus for
+ control and data exchnage with master processor.
+
+
config MFD_RC5T583
bool "Ricoh RC5T583 Power Management system device"
depends on I2C=y && GENERIC_HARDIRQS
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index 099e45f..07552c8 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -80,6 +80,8 @@
obj-$(CONFIG_WCD9310_CODEC) += wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o
obj-$(CONFIG_WCD9304_CODEC) += wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o
+obj-$(CONFIG_WCD9320_CODEC) += wcd9xxx-core.o wcd9xxx-irq.o wcd9xxx-slimslave.o
+
ifeq ($(CONFIG_SA1100_ASSABET),y)
obj-$(CONFIG_MCP_UCB1200) += ucb1x00-assabet.o
diff --git a/drivers/mfd/wcd9xxx-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c
index 705a57b..889c416 100644
--- a/drivers/mfd/wcd9xxx-slimslave.c
+++ b/drivers/mfd/wcd9xxx-slimslave.c
@@ -472,6 +472,12 @@
grph = rx[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) {
@@ -510,6 +516,12 @@
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) {
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 1c2f018..3c28447 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -628,14 +628,6 @@
PMIC8058. Driver interface to program registers of the ADC over
AMUX channels, devices on programmable MPP's and xotherm.
-config TZCOM
- tristate "Trustzone Communicator driver"
- default n
- help
- Provides a communication interface between userspace and
- TrustZone Operating Environment (TZBSP) using Secure Channel
- Manager (SCM) interface.
-
config QSEECOM
tristate "Qualcomm Secure Execution Communicator driver"
help
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index b628976..be3d0a0 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -69,6 +69,5 @@
obj-$(CONFIG_MSM_MEMORY_LOW_POWER_MODE_SUSPEND_DEEP_POWER_DOWN) \
+= msm_migrate_pages.o
obj-$(CONFIG_PMIC8058_XOADC) += pmic8058-xoadc.o
-obj-$(CONFIG_TZCOM) += tzcom.o
obj-$(CONFIG_QSEECOM) += qseecom.o
obj-$(CONFIG_QFP_FUSE) += qfp_fuse.o
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 4c92ee5..d5afe8d 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1717,19 +1717,22 @@
}
/* register client for bus scaling */
- qseecom_platform_support = (struct msm_bus_scale_pdata *)
- pdev->dev.platform_data;
- qsee_perf_client = msm_bus_scale_register_client(
- qseecom_platform_support);
- if (!qsee_perf_client) {
- pr_err("Unable to register bus client\n");
- } else {
- qseecom_bus_clk = clk_get(class_dev, "bus_clk");
- if (IS_ERR(qseecom_bus_clk)) {
- qseecom_bus_clk = NULL;
- } else if (qseecom_bus_clk != NULL) {
- pr_debug("Enabled DFAB clock");
- clk_set_rate(qseecom_bus_clk, 64000000);
+ if (!pdev->dev.of_node) {
+ qseecom_platform_support = (struct msm_bus_scale_pdata *)
+ pdev->dev.platform_data;
+ qsee_perf_client = msm_bus_scale_register_client(
+ qseecom_platform_support);
+
+ if (!qsee_perf_client) {
+ pr_err("Unable to register bus client\n");
+ } else {
+ qseecom_bus_clk = clk_get(class_dev, "bus_clk");
+ if (IS_ERR(qseecom_bus_clk)) {
+ qseecom_bus_clk = NULL;
+ } else if (qseecom_bus_clk != NULL) {
+ pr_debug("Enabled DFAB clock");
+ clk_set_rate(qseecom_bus_clk, 64000000);
+ }
}
}
return 0;
@@ -1750,12 +1753,20 @@
return 0;
};
+static struct of_device_id qseecom_match[] = {
+ {
+ .compatible = "qcom,qseecom",
+ },
+ {}
+};
+
static struct platform_driver qseecom_plat_driver = {
.probe = qseecom_probe,
.remove = qseecom_remove,
.driver = {
.name = "qseecom",
.owner = THIS_MODULE,
+ .of_match_table = qseecom_match,
},
};
diff --git a/drivers/misc/tzcom.c b/drivers/misc/tzcom.c
deleted file mode 100644
index 3b943c8..0000000
--- a/drivers/misc/tzcom.c
+++ /dev/null
@@ -1,1248 +0,0 @@
-/* Qualcomm TrustZone communicator driver
- *
- * 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.
- */
-
-#define KMSG_COMPONENT "TZCOM"
-#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include <linux/debugfs.h>
-#include <linux/cdev.h>
-#include <linux/uaccess.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/android_pmem.h>
-#include <linux/io.h>
-#include <linux/ion.h>
-#include <linux/tzcom.h>
-#include <linux/clk.h>
-#include <mach/scm.h>
-#include <mach/peripheral-loader.h>
-#include <mach/msm_bus.h>
-#include <mach/msm_bus_board.h>
-#include <mach/socinfo.h>
-#include "tzcomi.h"
-
-#define TZCOM_DEV "tzcom"
-
-#define TZSCHEDULER_CMD_ID 1 /* CMD id of the trustzone scheduler */
-
-#undef PDEBUG
-#define PDEBUG(fmt, args...) pr_debug("%s(%i, %s): " fmt "\n", \
- __func__, current->pid, current->comm, ## args)
-
-#undef PERR
-#define PERR(fmt, args...) pr_err("%s(%i, %s): " fmt "\n", \
- __func__, current->pid, current->comm, ## args)
-
-#undef PWARN
-#define PWARN(fmt, args...) pr_warning("%s(%i, %s): " fmt "\n", \
- __func__, current->pid, current->comm, ## args)
-
-
-static uint32_t tzcom_perf_client;
-static struct class *driver_class;
-static dev_t tzcom_device_no;
-static struct cdev tzcom_cdev;
-struct ion_client *ion_clnt;
-static u8 *sb_in_virt;
-static s32 sb_in_phys;
-static size_t sb_in_length = 20 * SZ_1K;
-static u8 *sb_out_virt;
-static s32 sb_out_phys;
-static size_t sb_out_length = 20 * SZ_1K;
-
-static void *pil;
-
-static atomic_t svc_instance_ctr = ATOMIC_INIT(0);
-static DEFINE_MUTEX(sb_in_lock);
-static DEFINE_MUTEX(sb_out_lock);
-static DEFINE_MUTEX(send_cmd_lock);
-static DEFINE_MUTEX(tzcom_bw_mutex);
-static int tzcom_bw_count;
-static struct clk *tzcom_bus_clk;
-struct tzcom_callback_list {
- struct list_head list;
- struct tzcom_callback callback;
-};
-
-struct tzcom_registered_svc_list {
- struct list_head list;
- struct tzcom_register_svc_op_req svc;
- wait_queue_head_t next_cmd_wq;
- int next_cmd_flag;
-};
-
-struct tzcom_data_t {
- struct list_head callback_list_head;
- struct mutex callback_list_lock;
- struct list_head registered_svc_list_head;
- spinlock_t registered_svc_list_lock;
- wait_queue_head_t cont_cmd_wq;
- int cont_cmd_flag;
- u32 handled_cmd_svc_instance_id;
- int abort;
- wait_queue_head_t abort_wq;
- atomic_t ioctl_count;
-};
-
-static int tzcom_enable_bus_scaling(void)
-{
- int ret = 0;
- if (!tzcom_perf_client)
- return -EINVAL;
-
- if (IS_ERR_OR_NULL(tzcom_bus_clk))
- return -EINVAL;
-
- mutex_lock(&tzcom_bw_mutex);
- if (!tzcom_bw_count) {
- ret = msm_bus_scale_client_update_request(
- tzcom_perf_client, 1);
- if (ret) {
- pr_err("Bandwidth request failed (%d)\n", ret);
- } else {
- ret = clk_enable(tzcom_bus_clk);
- if (ret)
- pr_err("Clock enable failed\n");
- }
- }
- if (ret)
- msm_bus_scale_client_update_request(tzcom_perf_client, 0);
- else
- tzcom_bw_count++;
- mutex_unlock(&tzcom_bw_mutex);
- return ret;
-}
-
-static void tzcom_disable_bus_scaling(void)
-{
- if (!tzcom_perf_client)
- return ;
-
- if (IS_ERR_OR_NULL(tzcom_bus_clk))
- return ;
-
- mutex_lock(&tzcom_bw_mutex);
- if (tzcom_bw_count > 0)
- if (tzcom_bw_count-- == 1) {
- msm_bus_scale_client_update_request(tzcom_perf_client,
- 0);
- clk_disable(tzcom_bus_clk);
- }
- mutex_unlock(&tzcom_bw_mutex);
-}
-
-static int tzcom_scm_call(const void *cmd_buf, size_t cmd_len,
- void *resp_buf, size_t resp_len)
-{
- return scm_call(SCM_SVC_TZSCHEDULER, TZSCHEDULER_CMD_ID,
- cmd_buf, cmd_len, resp_buf, resp_len);
-}
-
-static s32 tzcom_virt_to_phys(u8 *virt)
-{
- if (virt >= sb_in_virt &&
- virt < (sb_in_virt + sb_in_length)) {
- return sb_in_phys + (virt - sb_in_virt);
- } else if (virt >= sb_out_virt &&
- virt < (sb_out_virt + sb_out_length)) {
- return sb_out_phys + (virt - sb_out_virt);
- } else {
- return virt_to_phys(virt);
- }
-}
-
-static u8 *tzcom_phys_to_virt(s32 phys)
-{
- if (phys >= sb_in_phys &&
- phys < (sb_in_phys + sb_in_length)) {
- return sb_in_virt + (phys - sb_in_phys);
- } else if (phys >= sb_out_phys &&
- phys < (sb_out_phys + sb_out_length)) {
- return sb_out_virt + (phys - sb_out_phys);
- } else {
- return phys_to_virt(phys);
- }
-}
-
-static int __tzcom_is_svc_unique(struct tzcom_data_t *data,
- struct tzcom_register_svc_op_req svc)
-{
- struct tzcom_registered_svc_list *ptr;
- int unique = 1;
- unsigned long flags;
-
- spin_lock_irqsave(&data->registered_svc_list_lock, flags);
- list_for_each_entry(ptr, &data->registered_svc_list_head, list) {
- if (ptr->svc.svc_id == svc.svc_id) {
- PERR("Service id: %u is already registered",
- ptr->svc.svc_id);
- unique = 0;
- break;
- } else if (svc.cmd_id_low >= ptr->svc.cmd_id_low &&
- svc.cmd_id_low <= ptr->svc.cmd_id_high) {
- PERR("Cmd id low falls in the range of another"
- "registered service");
- unique = 0;
- break;
- } else if (svc.cmd_id_high >= ptr->svc.cmd_id_low &&
- svc.cmd_id_high <= ptr->svc.cmd_id_high) {
- PERR("Cmd id high falls in the range of another"
- "registered service");
- unique = 0;
- break;
- }
- }
- spin_unlock_irqrestore(&data->registered_svc_list_lock, flags);
- return unique;
-}
-
-static int tzcom_register_service(struct tzcom_data_t *data, void __user *argp)
-{
- int ret;
- unsigned long flags;
- struct tzcom_register_svc_op_req rcvd_svc;
- struct tzcom_registered_svc_list *new_entry;
-
- ret = copy_from_user(&rcvd_svc, argp, sizeof(rcvd_svc));
-
- if (ret) {
- PERR("copy_from_user failed");
- return ret;
- }
-
- PDEBUG("svc_id: %u, cmd_id_low: %u, cmd_id_high: %u",
- rcvd_svc.svc_id, rcvd_svc.cmd_id_low,
- rcvd_svc.cmd_id_high);
- if (!__tzcom_is_svc_unique(data, rcvd_svc)) {
- PERR("Provided service is not unique");
- return -EINVAL;
- }
-
- rcvd_svc.instance_id = atomic_inc_return(&svc_instance_ctr);
-
- ret = copy_to_user(argp, &rcvd_svc, sizeof(rcvd_svc));
- if (ret) {
- PERR("copy_to_user failed");
- return ret;
- }
-
- new_entry = kmalloc(sizeof(*new_entry), GFP_KERNEL);
- if (!new_entry) {
- PERR("kmalloc failed");
- return -ENOMEM;
- }
- memcpy(&new_entry->svc, &rcvd_svc, sizeof(rcvd_svc));
- new_entry->next_cmd_flag = 0;
- init_waitqueue_head(&new_entry->next_cmd_wq);
-
- spin_lock_irqsave(&data->registered_svc_list_lock, flags);
- list_add_tail(&new_entry->list, &data->registered_svc_list_head);
- spin_unlock_irqrestore(&data->registered_svc_list_lock, flags);
-
-
- return ret;
-}
-
-static int tzcom_unregister_service(struct tzcom_data_t *data,
- void __user *argp)
-{
- int ret = 0;
- unsigned long flags;
- struct tzcom_unregister_svc_op_req req;
- struct tzcom_registered_svc_list *ptr, *next;
- ret = copy_from_user(&req, argp, sizeof(req));
- if (ret) {
- PERR("copy_from_user failed");
- return ret;
- }
-
- spin_lock_irqsave(&data->registered_svc_list_lock, flags);
- list_for_each_entry_safe(ptr, next, &data->registered_svc_list_head,
- list) {
- if (req.svc_id == ptr->svc.svc_id &&
- req.instance_id == ptr->svc.instance_id) {
- wake_up_all(&ptr->next_cmd_wq);
- list_del(&ptr->list);
- kfree(ptr);
- spin_unlock_irqrestore(&data->registered_svc_list_lock,
- flags);
- return 0;
- }
- }
- spin_unlock_irqrestore(&data->registered_svc_list_lock, flags);
-
- return -EINVAL;
-}
-
-static int __tzcom_is_cont_cmd(struct tzcom_data_t *data)
-{
- int ret;
- ret = (data->cont_cmd_flag != 0);
- return ret || data->abort;
-}
-
-/**
- * +---------+ +-----+ +-----------------+
- * | TZCOM | | SCM | | TZCOM_SCHEDULER |
- * +----+----+ +--+--+ +--------+--------+
- * | | |
- * | scm_call | |
- * |------------------------------------->| |
- * | cmd_buf = struct tzcom_command { | |
- * | cmd_type, |------------------>|
- * +------+------------- sb_in_cmd_addr, | |
- * | | sb_in_cmd_len | |
- * | | } | |
- * | | resp_buf = struct tzcom_response { | |
- * | cmd_status, | |
- * | +---------- sb_in_rsp_addr, | |
- * | | sb_in_rsp_len |<------------------|
- * | | }
- * | | struct tzcom_callback {---------+
- * | | uint32_t cmd_id; |
- * | | uint32_t sb_out_cb_data_len;|
- * | +---------------+ uint32_t sb_out_cb_data_off;|
- * | | } |
- * | _________________________|_______________________________ |
- * | +-----------------------+| +----------------------+ |
- * +--->+ copy from req.cmd_buf |+>| copy to req.resp_buf | |
- * +-----------------------+ +----------------------+ |
- * _________________________________________________________ |
- * INPUT SHARED BUFFER |
- * +------------------------------------------------------------------------+
- * | _________________________________________________________
- * | +---------------------------------------------+
- * +->| cmd_id | data_len | data_off | data... |
- * +---------------------------------------------+
- * |<------------>|copy to next_cmd.req_buf
- * _________________________________________________________
- * OUTPUT SHARED BUFFER
- */
-static int __tzcom_send_cmd(struct tzcom_data_t *data,
- struct tzcom_send_cmd_op_req *req)
-{
- int ret = 0;
- unsigned long flags;
- u32 reqd_len_sb_in = 0;
- u32 reqd_len_sb_out = 0;
- struct tzcom_command cmd;
- struct tzcom_response resp;
- struct tzcom_callback *next_callback;
- void *cb_data = NULL;
- struct tzcom_callback_list *new_entry;
- struct tzcom_callback *cb;
- size_t new_entry_len = 0;
- struct tzcom_registered_svc_list *ptr_svc;
-
- if (req->cmd_buf == NULL || req->resp_buf == NULL) {
- PERR("cmd buffer or response buffer is null");
- return -EINVAL;
- }
-
- if (req->cmd_len <= 0 || req->resp_len <= 0 ||
- req->cmd_len > sb_in_length || req->resp_len > sb_in_length) {
- PERR("cmd buffer length or "
- "response buffer length not valid");
- return -EINVAL;
- }
- PDEBUG("received cmd_req.req: 0x%p",
- req->cmd_buf);
- PDEBUG("received cmd_req.rsp size: %u, ptr: 0x%p",
- req->resp_len,
- req->resp_buf);
-
- reqd_len_sb_in = req->cmd_len + req->resp_len;
- if (reqd_len_sb_in > sb_in_length) {
- PDEBUG("Not enough memory to fit cmd_buf and "
- "resp_buf. Required: %u, Available: %u",
- reqd_len_sb_in, sb_in_length);
- return -ENOMEM;
- }
-
- /* Copy req->cmd_buf to SB in and set
- * req->resp_buf to SB in + cmd_len
- */
- mutex_lock(&sb_in_lock);
- PDEBUG("Before memcpy on sb_in");
- memcpy(sb_in_virt, req->cmd_buf, req->cmd_len);
- PDEBUG("After memcpy on sb_in");
-
- /* cmd_type will always be a new here */
- cmd.cmd_type = TZ_SCHED_CMD_NEW;
- cmd.sb_in_cmd_addr = (u8 *) tzcom_virt_to_phys(sb_in_virt);
- cmd.sb_in_cmd_len = req->cmd_len;
-
- resp.cmd_status = TZ_SCHED_STATUS_INCOMPLETE;
- resp.sb_in_rsp_addr = (u8 *) tzcom_virt_to_phys(sb_in_virt +
- req->cmd_len);
- resp.sb_in_rsp_len = req->resp_len;
-
- PDEBUG("before call tzcom_scm_call, cmd_id = : %u", req->cmd_id);
- PDEBUG("before call tzcom_scm_call, sizeof(cmd) = : %u", sizeof(cmd));
-
- ret = tzcom_scm_call((const void *) &cmd, sizeof(cmd),
- &resp, sizeof(resp));
- mutex_unlock(&sb_in_lock);
-
- if (ret) {
- PERR("tzcom_scm_call failed with err: %d", ret);
- return ret;
- }
-
- while (resp.cmd_status != TZ_SCHED_STATUS_COMPLETE) {
- /*
- * If cmd is incomplete, get the callback cmd out from SB out
- * and put it on the list
- */
- PDEBUG("cmd_status is incomplete.");
- next_callback = (struct tzcom_callback *)sb_out_virt;
-
- mutex_lock(&sb_out_lock);
- reqd_len_sb_out = sizeof(*next_callback)
- + next_callback->sb_out_cb_data_len;
- if (reqd_len_sb_out > sb_out_length ||
- reqd_len_sb_out < sizeof(*next_callback) ||
- next_callback->sb_out_cb_data_len > sb_out_length) {
- PERR("Incorrect callback data length"
- " Required: %u, Available: %u, Min: %u",
- reqd_len_sb_out, sb_out_length,
- sizeof(*next_callback));
- mutex_unlock(&sb_out_lock);
- return -ENOMEM;
- }
-
- /* Assumption is cb_data_off is sizeof(tzcom_callback) */
- new_entry_len = sizeof(*new_entry)
- + next_callback->sb_out_cb_data_len;
- new_entry = kmalloc(new_entry_len, GFP_KERNEL);
- if (!new_entry) {
- PERR("kmalloc failed");
- mutex_unlock(&sb_out_lock);
- return -ENOMEM;
- }
-
- cb = &new_entry->callback;
- cb->cmd_id = next_callback->cmd_id;
- cb->sb_out_cb_data_len = next_callback->sb_out_cb_data_len;
- cb->sb_out_cb_data_off = sizeof(*cb);
-
- cb_data = (u8 *)next_callback
- + next_callback->sb_out_cb_data_off;
- memcpy((u8 *)cb + cb->sb_out_cb_data_off, cb_data,
- next_callback->sb_out_cb_data_len);
- mutex_unlock(&sb_out_lock);
-
- mutex_lock(&data->callback_list_lock);
- list_add_tail(&new_entry->list, &data->callback_list_head);
- mutex_unlock(&data->callback_list_lock);
-
- /*
- * We don't know which service can handle the command. so we
- * wake up all blocking services and let them figure out if
- * they can handle the given command.
- */
- spin_lock_irqsave(&data->registered_svc_list_lock, flags);
- list_for_each_entry(ptr_svc,
- &data->registered_svc_list_head, list) {
- ptr_svc->next_cmd_flag = 1;
- wake_up_interruptible(&ptr_svc->next_cmd_wq);
- }
- spin_unlock_irqrestore(&data->registered_svc_list_lock,
- flags);
-
- PDEBUG("waking up next_cmd_wq and "
- "waiting for cont_cmd_wq");
- if (wait_event_interruptible(data->cont_cmd_wq,
- __tzcom_is_cont_cmd(data))) {
- PWARN("Interrupted: exiting send_cmd loop");
- return -ERESTARTSYS;
- }
-
- if (data->abort) {
- PERR("Aborting driver");
- return -ENODEV;
- }
- data->cont_cmd_flag = 0;
- cmd.cmd_type = TZ_SCHED_CMD_PENDING;
- mutex_lock(&sb_in_lock);
- ret = tzcom_scm_call((const void *) &cmd, sizeof(cmd), &resp,
- sizeof(resp));
- mutex_unlock(&sb_in_lock);
- if (ret) {
- PERR("tzcom_scm_call failed with err: %d", ret);
- return ret;
- }
- }
-
- mutex_lock(&sb_in_lock);
- resp.sb_in_rsp_addr = sb_in_virt + cmd.sb_in_cmd_len;
- resp.sb_in_rsp_len = req->resp_len;
- memcpy(req->resp_buf, resp.sb_in_rsp_addr, resp.sb_in_rsp_len);
- /* Zero out memory for security purpose */
- memset(sb_in_virt, 0, reqd_len_sb_in);
- mutex_unlock(&sb_in_lock);
-
- return ret;
-}
-
-
-static int tzcom_send_cmd(struct tzcom_data_t *data, void __user *argp)
-{
- int ret = 0;
- struct tzcom_send_cmd_op_req req;
-
- ret = copy_from_user(&req, argp, sizeof(req));
- if (ret) {
- PERR("copy_from_user failed");
- return ret;
- }
- ret = __tzcom_send_cmd(data, &req);
- if (ret)
- return ret;
-
- PDEBUG("sending cmd_req->rsp "
- "size: %u, ptr: 0x%p", req.resp_len,
- req.resp_buf);
- ret = copy_to_user(argp, &req, sizeof(req));
- if (ret) {
- PDEBUG("copy_to_user failed");
- return ret;
- }
- return ret;
-}
-
-static int __tzcom_send_cmd_req_clean_up(
- struct tzcom_send_cmd_fd_op_req *req)
-{
- char *field;
- uint32_t *update;
- int ret = 0;
- int i = 0;
-
- for (i = 0; i < MAX_ION_FD; i++) {
- if (req->ifd_data[i].fd != 0) {
- field = (char *)req->cmd_buf +
- req->ifd_data[i].cmd_buf_offset;
- update = (uint32_t *) field;
- *update = 0;
- }
- }
- return ret;
-}
-
-static int __tzcom_update_with_phy_addr(
- struct tzcom_send_cmd_fd_op_req *req)
-{
- struct ion_handle *ihandle;
- char *field;
- uint32_t *update;
- ion_phys_addr_t pa;
- int ret = 0;
- int i = 0;
- uint32_t length;
-
- for (i = 0; i < MAX_ION_FD; i++) {
- if (req->ifd_data[i].fd != 0) {
- /* Get the handle of the shared fd */
- ihandle = ion_import_fd(ion_clnt, req->ifd_data[i].fd);
- if (ihandle == NULL) {
- PERR("Ion client can't retrieve the handle\n");
- return -ENOMEM;
- }
- field = (char *) req->cmd_buf +
- req->ifd_data[i].cmd_buf_offset;
- update = (uint32_t *) field;
-
- /* Populate the cmd data structure with the phys_addr */
- ret = ion_phys(ion_clnt, ihandle, &pa, &length);
- if (ret)
- return -ENOMEM;
-
- *update = (uint32_t)pa;
- ion_free(ion_clnt, ihandle);
- }
- }
- return ret;
-}
-
-static int tzcom_send_cmd_with_fd(struct tzcom_data_t *data,
- void __user *argp)
-{
- int ret = 0;
- struct tzcom_send_cmd_fd_op_req req;
- struct tzcom_send_cmd_op_req send_cmd_req;
-
- ret = copy_from_user(&req, argp, sizeof(req));
- if (ret) {
- PERR("copy_from_user failed");
- return ret;
- }
-
- send_cmd_req.cmd_id = req.cmd_id;
- send_cmd_req.cmd_buf = req.cmd_buf;
- send_cmd_req.cmd_len = req.cmd_len;
- send_cmd_req.resp_buf = req.resp_buf;
- send_cmd_req.resp_len = req.resp_len;
-
- ret = __tzcom_update_with_phy_addr(&req);
- if (ret)
- return ret;
- ret = __tzcom_send_cmd(data, &send_cmd_req);
- __tzcom_send_cmd_req_clean_up(&req);
-
- if (ret)
- return ret;
-
- PDEBUG("sending cmd_req->rsp "
- "size: %u, ptr: 0x%p", req.resp_len,
- req.resp_buf);
- ret = copy_to_user(argp, &req, sizeof(req));
- if (ret) {
- PDEBUG("copy_to_user failed");
- return ret;
- }
- return ret;
-}
-
-static struct tzcom_registered_svc_list *__tzcom_find_svc(
- struct tzcom_data_t *data,
- uint32_t instance_id)
-{
- struct tzcom_registered_svc_list *entry;
- unsigned long flags;
-
- spin_lock_irqsave(&data->registered_svc_list_lock, flags);
- list_for_each_entry(entry,
- &data->registered_svc_list_head, list) {
- if (entry->svc.instance_id == instance_id)
- break;
- }
- spin_unlock_irqrestore(&data->registered_svc_list_lock, flags);
-
- return entry;
-}
-
-static int __tzcom_copy_cmd(struct tzcom_data_t *data,
- struct tzcom_next_cmd_op_req *req,
- struct tzcom_registered_svc_list *ptr_svc)
-{
- int found = 0;
- int ret = -EAGAIN;
- struct tzcom_callback_list *entry, *next;
- struct tzcom_callback *cb;
-
- PDEBUG("In here");
- mutex_lock(&data->callback_list_lock);
- PDEBUG("Before looping through cmd and svc lists.");
- list_for_each_entry_safe(entry, next, &data->callback_list_head, list) {
- cb = &entry->callback;
- if (req->svc_id == ptr_svc->svc.svc_id &&
- req->instance_id == ptr_svc->svc.instance_id &&
- cb->cmd_id >= ptr_svc->svc.cmd_id_low &&
- cb->cmd_id <= ptr_svc->svc.cmd_id_high) {
- PDEBUG("Found matching entry");
- found = 1;
- if (cb->sb_out_cb_data_len <= req->req_len) {
- PDEBUG("copying cmd buffer %p to req "
- "buffer %p, length: %u",
- (u8 *)cb + cb->sb_out_cb_data_off,
- req->req_buf, cb->sb_out_cb_data_len);
- req->cmd_id = cb->cmd_id;
- ret = copy_to_user(req->req_buf,
- (u8 *)cb + cb->sb_out_cb_data_off,
- cb->sb_out_cb_data_len);
- if (ret) {
- PERR("copy_to_user failed");
- break;
- }
- list_del(&entry->list);
- kfree(entry);
- ret = 0;
- } else {
- PERR("callback data buffer is "
- "larger than provided buffer."
- "Required: %u, Provided: %u",
- cb->sb_out_cb_data_len,
- req->req_len);
- ret = -ENOMEM;
- }
- break;
- }
- }
- PDEBUG("After looping through cmd and svc lists.");
- mutex_unlock(&data->callback_list_lock);
- return ret;
-}
-
-static int __tzcom_is_next_cmd(struct tzcom_data_t *data,
- struct tzcom_registered_svc_list *svc)
-{
- int ret;
- ret = (svc->next_cmd_flag != 0);
- return ret || data->abort;
-}
-
-static int tzcom_read_next_cmd(struct tzcom_data_t *data, void __user *argp)
-{
- int ret = 0;
- struct tzcom_next_cmd_op_req req;
- struct tzcom_registered_svc_list *this_svc;
-
- ret = copy_from_user(&req, argp, sizeof(req));
- if (ret) {
- PERR("copy_from_user failed");
- return ret;
- }
-
- if (req.instance_id > atomic_read(&svc_instance_ctr)) {
- PERR("Invalid instance_id for the request");
- return -EINVAL;
- }
-
- if (!req.req_buf || req.req_len == 0) {
- PERR("Invalid request buffer or buffer length");
- return -EINVAL;
- }
-
- PDEBUG("Before next_cmd loop");
- this_svc = __tzcom_find_svc(data, req.instance_id);
-
- while (1) {
- PDEBUG("Before wait_event next_cmd.");
- if (wait_event_interruptible(this_svc->next_cmd_wq,
- __tzcom_is_next_cmd(data, this_svc))) {
- PWARN("Interrupted: exiting wait_next_cmd loop");
- /* woken up for different reason */
- return -ERESTARTSYS;
- }
-
- if (data->abort) {
- PERR("Aborting driver");
- return -ENODEV;
- }
- PDEBUG("After wait_event next_cmd.");
- this_svc->next_cmd_flag = 0;
-
- ret = __tzcom_copy_cmd(data, &req, this_svc);
- if (ret == 0) {
- PDEBUG("Successfully found svc for cmd");
- data->handled_cmd_svc_instance_id = req.instance_id;
- break;
- } else if (ret == -ENOMEM) {
- PERR("Not enough memory");
- return ret;
- }
- }
- ret = copy_to_user(argp, &req, sizeof(req));
- if (ret) {
- PERR("copy_to_user failed");
- return ret;
- }
- PDEBUG("copy_to_user is done.");
- return ret;
-}
-
-static int tzcom_cont_cmd(struct tzcom_data_t *data, void __user *argp)
-{
- int ret = 0;
- struct tzcom_cont_cmd_op_req req;
- ret = copy_from_user(&req, argp, sizeof(req));
- if (ret) {
- PERR("copy_from_user failed");
- return ret;
- }
-
- /*
- * Only the svc instance that handled the cmd (in read_next_cmd method)
- * can call continue cmd
- */
- if (data->handled_cmd_svc_instance_id != req.instance_id) {
- PWARN("Only the service instance that handled the last "
- "callback can continue cmd. "
- "Expected: %u, Received: %u",
- data->handled_cmd_svc_instance_id,
- req.instance_id);
- return -EINVAL;
- }
-
- if (req.resp_buf) {
- mutex_lock(&sb_out_lock);
- memcpy(sb_out_virt, req.resp_buf, req.resp_len);
- mutex_unlock(&sb_out_lock);
- }
-
- data->cont_cmd_flag = 1;
- wake_up_interruptible(&data->cont_cmd_wq);
- return ret;
-}
-
-static int tzcom_abort(struct tzcom_data_t *data)
-{
- int ret = 0;
- unsigned long flags;
- struct tzcom_registered_svc_list *lsvc, *nsvc;
- if (data->abort) {
- PERR("Already aborting");
- return -EINVAL;
- }
-
- data->abort = 1;
-
- PDEBUG("Waking up cont_cmd_wq");
- wake_up_all(&data->cont_cmd_wq);
-
- spin_lock_irqsave(&data->registered_svc_list_lock, flags);
- PDEBUG("Before waking up service wait queues");
- list_for_each_entry_safe(lsvc, nsvc,
- &data->registered_svc_list_head, list) {
- wake_up_all(&lsvc->next_cmd_wq);
- }
- spin_unlock_irqrestore(&data->registered_svc_list_lock, flags);
-
- PDEBUG("ioctl_count before loop: %d", atomic_read(&data->ioctl_count));
- while (atomic_read(&data->ioctl_count) > 0) {
- if (wait_event_interruptible(data->abort_wq,
- atomic_read(&data->ioctl_count) <= 0)) {
- PERR("Interrupted from abort");
- ret = -ERESTARTSYS;
- break;
- }
- }
- return ret;
-}
-
-static long tzcom_ioctl(struct file *file, unsigned cmd,
- unsigned long arg)
-{
- int ret = 0;
- struct tzcom_data_t *tzcom_data = file->private_data;
- void __user *argp = (void __user *) arg;
- PDEBUG("enter tzcom_ioctl()");
- if (tzcom_data->abort) {
- PERR("Aborting tzcom driver");
- return -ENODEV;
- }
-
- switch (cmd) {
- case TZCOM_IOCTL_REGISTER_SERVICE_REQ: {
- PDEBUG("ioctl register_service_req()");
- atomic_inc(&tzcom_data->ioctl_count);
- ret = tzcom_register_service(tzcom_data, argp);
- atomic_dec(&tzcom_data->ioctl_count);
- wake_up_interruptible(&tzcom_data->abort_wq);
- if (ret)
- PERR("failed tzcom_register_service: %d", ret);
- break;
- }
- case TZCOM_IOCTL_UNREGISTER_SERVICE_REQ: {
- PDEBUG("ioctl unregister_service_req()");
- atomic_inc(&tzcom_data->ioctl_count);
- ret = tzcom_unregister_service(tzcom_data, argp);
- atomic_dec(&tzcom_data->ioctl_count);
- wake_up_interruptible(&tzcom_data->abort_wq);
- if (ret)
- PERR("failed tzcom_unregister_service: %d", ret);
- break;
- }
- case TZCOM_IOCTL_SEND_CMD_REQ: {
- PDEBUG("ioctl send_cmd_req()");
- /* Only one client allowed here at a time */
- mutex_lock(&send_cmd_lock);
- atomic_inc(&tzcom_data->ioctl_count);
- ret = tzcom_send_cmd(tzcom_data, argp);
- atomic_dec(&tzcom_data->ioctl_count);
- wake_up_interruptible(&tzcom_data->abort_wq);
- mutex_unlock(&send_cmd_lock);
- if (ret)
- PERR("failed tzcom_send_cmd: %d", ret);
- break;
- }
- case TZCOM_IOCTL_SEND_CMD_FD_REQ: {
- PDEBUG("ioctl send_cmd_req()");
- /* Only one client allowed here at a time */
- mutex_lock(&send_cmd_lock);
- atomic_inc(&tzcom_data->ioctl_count);
- ret = tzcom_send_cmd_with_fd(tzcom_data, argp);
- atomic_dec(&tzcom_data->ioctl_count);
- wake_up_interruptible(&tzcom_data->abort_wq);
- mutex_unlock(&send_cmd_lock);
- if (ret)
- PERR("failed tzcom_send_cmd: %d", ret);
- break;
- }
- case TZCOM_IOCTL_READ_NEXT_CMD_REQ: {
- PDEBUG("ioctl read_next_cmd_req()");
- atomic_inc(&tzcom_data->ioctl_count);
- ret = tzcom_read_next_cmd(tzcom_data, argp);
- atomic_dec(&tzcom_data->ioctl_count);
- wake_up_interruptible(&tzcom_data->abort_wq);
- if (ret)
- PERR("failed tzcom_read_next: %d", ret);
- break;
- }
- case TZCOM_IOCTL_CONTINUE_CMD_REQ: {
- PDEBUG("ioctl continue_cmd_req()");
- atomic_inc(&tzcom_data->ioctl_count);
- ret = tzcom_cont_cmd(tzcom_data, argp);
- atomic_dec(&tzcom_data->ioctl_count);
- wake_up_interruptible(&tzcom_data->abort_wq);
- if (ret)
- PERR("failed tzcom_cont_cmd: %d", ret);
- break;
- }
- case TZCOM_IOCTL_ABORT_REQ: {
- PDEBUG("ioctl abort_req()");
- ret = tzcom_abort(tzcom_data);
- if (ret)
- PERR("failed tzcom_abort: %d", ret);
- break;
- }
- default:
- return -EINVAL;
- }
- return ret;
-}
-
-static int tzcom_open(struct inode *inode, struct file *file)
-{
- int ret;
- long pil_error;
- struct tz_pr_init_sb_req_s sb_out_init_req;
- struct tz_pr_init_sb_rsp_s sb_out_init_rsp;
- void *rsp_addr_virt;
- struct tzcom_command cmd;
- struct tzcom_response resp;
- struct tzcom_data_t *tzcom_data;
-
- PDEBUG("In here");
-
- ret = tzcom_enable_bus_scaling();
-
- if (pil == NULL) {
- pil = pil_get("tzapps");
- if (IS_ERR(pil)) {
- PERR("Playready PIL image load failed");
- pil_error = PTR_ERR(pil);
- pil = NULL;
- return pil_error;
- }
- PDEBUG("tzapps image loaded successfully");
- }
-
- sb_out_init_req.pr_cmd = TZ_SCHED_CMD_ID_INIT_SB_OUT;
- sb_out_init_req.sb_len = sb_out_length;
- sb_out_init_req.sb_ptr = tzcom_virt_to_phys(sb_out_virt);
- PDEBUG("sb_out_init_req { pr_cmd: %d, sb_len: %u, "
- "sb_ptr (phys): 0x%x }",
- sb_out_init_req.pr_cmd,
- sb_out_init_req.sb_len,
- sb_out_init_req.sb_ptr);
-
- mutex_lock(&sb_in_lock);
- PDEBUG("Before memcpy on sb_in");
- memcpy(sb_in_virt, &sb_out_init_req, sizeof(sb_out_init_req));
- PDEBUG("After memcpy on sb_in");
-
- /* It will always be a new cmd from this method */
- cmd.cmd_type = TZ_SCHED_CMD_NEW;
- cmd.sb_in_cmd_addr = (u8 *) tzcom_virt_to_phys(sb_in_virt);
- cmd.sb_in_cmd_len = sizeof(sb_out_init_req);
- PDEBUG("tzcom_command { cmd_type: %u, sb_in_cmd_addr: %p, "
- "sb_in_cmd_len: %u }",
- cmd.cmd_type, cmd.sb_in_cmd_addr, cmd.sb_in_cmd_len);
-
- resp.cmd_status = TZ_SCHED_STATUS_INCOMPLETE;
-
- PDEBUG("Before scm_call for sb_init");
- ret = tzcom_scm_call(&cmd, sizeof(cmd), &resp, sizeof(resp));
- if (ret) {
- PERR("tzcom_scm_call failed with err: %d", ret);
- return ret;
- }
- PDEBUG("After scm_call for sb_init");
-
- PDEBUG("tzcom_response after scm cmd_status: %u", resp.cmd_status);
- if (resp.cmd_status == TZ_SCHED_STATUS_COMPLETE) {
- resp.sb_in_rsp_addr = (u8 *)cmd.sb_in_cmd_addr +
- cmd.sb_in_cmd_len;
- resp.sb_in_rsp_len = sizeof(sb_out_init_rsp);
- PDEBUG("tzcom_response sb_in_rsp_addr: %p, sb_in_rsp_len: %u",
- resp.sb_in_rsp_addr, resp.sb_in_rsp_len);
- rsp_addr_virt = tzcom_phys_to_virt((unsigned long)
- resp.sb_in_rsp_addr);
- PDEBUG("Received response phys: %p, virt: %p",
- resp.sb_in_rsp_addr, rsp_addr_virt);
- memcpy(&sb_out_init_rsp, rsp_addr_virt, resp.sb_in_rsp_len);
- } else {
- PERR("Error with SB initialization");
- mutex_unlock(&sb_in_lock);
- return -EPERM;
- }
- mutex_unlock(&sb_in_lock);
-
- PDEBUG("sb_out_init_rsp { pr_cmd: %d, ret: %d }",
- sb_out_init_rsp.pr_cmd, sb_out_init_rsp.ret);
-
- if (sb_out_init_rsp.ret) {
- PERR("sb_out_init_req failed: %d", sb_out_init_rsp.ret);
- return -EPERM;
- }
-
- tzcom_data = kmalloc(sizeof(*tzcom_data), GFP_KERNEL);
- if (!tzcom_data) {
- PERR("kmalloc failed");
- return -ENOMEM;
- }
- file->private_data = tzcom_data;
-
- INIT_LIST_HEAD(&tzcom_data->callback_list_head);
- mutex_init(&tzcom_data->callback_list_lock);
-
- INIT_LIST_HEAD(&tzcom_data->registered_svc_list_head);
- spin_lock_init(&tzcom_data->registered_svc_list_lock);
-
- init_waitqueue_head(&tzcom_data->cont_cmd_wq);
- tzcom_data->cont_cmd_flag = 0;
- tzcom_data->handled_cmd_svc_instance_id = 0;
- tzcom_data->abort = 0;
- init_waitqueue_head(&tzcom_data->abort_wq);
- atomic_set(&tzcom_data->ioctl_count, 0);
- return 0;
-}
-
-static int tzcom_release(struct inode *inode, struct file *file)
-{
- struct tzcom_data_t *tzcom_data = file->private_data;
- struct tzcom_callback_list *lcb, *ncb;
- struct tzcom_registered_svc_list *lsvc, *nsvc;
- unsigned long flags;
- PDEBUG("In here");
-
- if (!tzcom_data->abort) {
- PDEBUG("Calling abort");
- tzcom_abort(tzcom_data);
- }
-
- PDEBUG("Before removing callback list");
- mutex_lock(&tzcom_data->callback_list_lock);
- list_for_each_entry_safe(lcb, ncb,
- &tzcom_data->callback_list_head, list) {
- list_del(&lcb->list);
- kfree(lcb);
- }
- mutex_unlock(&tzcom_data->callback_list_lock);
- PDEBUG("After removing callback list");
-
- PDEBUG("Before removing svc list");
- spin_lock_irqsave(&tzcom_data->registered_svc_list_lock, flags);
- list_for_each_entry_safe(lsvc, nsvc,
- &tzcom_data->registered_svc_list_head, list) {
- list_del(&lsvc->list);
- kfree(lsvc);
- }
- spin_unlock_irqrestore(&tzcom_data->registered_svc_list_lock, flags);
- PDEBUG("After removing svc list");
- if (pil != NULL) {
- pil_put(pil);
- pil = NULL;
- }
- PDEBUG("Freeing tzcom data");
- kfree(tzcom_data);
- tzcom_disable_bus_scaling();
- return 0;
-}
-
-static struct msm_bus_paths tzcom_bw_table[] = {
- {
- .vectors = (struct msm_bus_vectors[]){
- {
- .src = MSM_BUS_MASTER_SPS,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- },
- },
- .num_paths = 1,
- },
- {
- .vectors = (struct msm_bus_vectors[]){
- {
- .src = MSM_BUS_MASTER_SPS,
- .dst = MSM_BUS_SLAVE_EBI_CH0,
- .ib = (492 * 8) * 1000000UL,
- .ab = (492 * 8) * 100000UL,
- },
- },
- .num_paths = 1,
- },
-
-};
-
-static struct msm_bus_scale_pdata tzcom_bus_pdata = {
- .usecase = tzcom_bw_table,
- .num_usecases = ARRAY_SIZE(tzcom_bw_table),
- .name = "tzcom",
-};
-static const struct file_operations tzcom_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = tzcom_ioctl,
- .open = tzcom_open,
- .release = tzcom_release
-};
-
-static int __init tzcom_init(void)
-{
- int rc;
- struct device *class_dev;
-
- PDEBUG("Hello tzcom");
-
- rc = alloc_chrdev_region(&tzcom_device_no, 0, 1, TZCOM_DEV);
- if (rc < 0) {
- PERR("alloc_chrdev_region failed %d", rc);
- return rc;
- }
-
- driver_class = class_create(THIS_MODULE, TZCOM_DEV);
- if (IS_ERR(driver_class)) {
- rc = -ENOMEM;
- PERR("class_create failed %d", rc);
- goto unregister_chrdev_region;
- }
-
- class_dev = device_create(driver_class, NULL, tzcom_device_no, NULL,
- TZCOM_DEV);
- if (!class_dev) {
- PERR("class_device_create failed %d", rc);
- rc = -ENOMEM;
- goto class_destroy;
- }
-
- cdev_init(&tzcom_cdev, &tzcom_fops);
- tzcom_cdev.owner = THIS_MODULE;
-
- rc = cdev_add(&tzcom_cdev, MKDEV(MAJOR(tzcom_device_no), 0), 1);
- if (rc < 0) {
- PERR("cdev_add failed %d", rc);
- goto class_device_destroy;
- }
-
- sb_in_phys = pmem_kalloc(sb_in_length, PMEM_MEMTYPE_EBI1 |
- PMEM_ALIGNMENT_4K);
- if (IS_ERR((void *)sb_in_phys)) {
- PERR("could not allocte in kernel pmem buffers for sb_in");
- sb_in_phys = 0;
- rc = -ENOMEM;
- goto class_device_destroy;
- }
- PDEBUG("physical_addr for sb_in: 0x%x", sb_in_phys);
-
- sb_in_virt = (u8 *) ioremap((unsigned long)sb_in_phys,
- sb_in_length);
- if (!sb_in_virt) {
- PERR("Shared buffer IN allocation failed.");
- rc = -ENOMEM;
- goto class_device_destroy;
- }
- PDEBUG("sb_in virt address: %p, phys address: 0x%x",
- sb_in_virt, tzcom_virt_to_phys(sb_in_virt));
-
- sb_out_phys = pmem_kalloc(sb_out_length, PMEM_MEMTYPE_EBI1 |
- PMEM_ALIGNMENT_4K);
- if (IS_ERR((void *)sb_out_phys)) {
- PERR("could not allocte in kernel pmem buffers for sb_out");
- sb_out_phys = 0;
- rc = -ENOMEM;
- goto class_device_destroy;
- }
- PDEBUG("physical_addr for sb_out: 0x%x", sb_out_phys);
-
- sb_out_virt = (u8 *) ioremap((unsigned long)sb_out_phys,
- sb_out_length);
- if (!sb_out_virt) {
- PERR("Shared buffer OUT allocation failed.");
- rc = -ENOMEM;
- goto class_device_destroy;
- }
- PDEBUG("sb_out virt address: %p, phys address: 0x%x",
- sb_out_virt, tzcom_virt_to_phys(sb_out_virt));
- ion_clnt = msm_ion_client_create(0x03, "tzcom");
- /* Initialized in tzcom_open */
- pil = NULL;
-
- tzcom_perf_client = msm_bus_scale_register_client(
- &tzcom_bus_pdata);
- if (!tzcom_perf_client)
- pr_err("Unable to register bus client");
-
- tzcom_bus_clk = clk_get(class_dev, "bus_clk");
- if (IS_ERR(tzcom_bus_clk)) {
- tzcom_bus_clk = NULL;
- } else if (tzcom_bus_clk != NULL) {
- pr_debug("Enabled DFAB clock\n");
- clk_set_rate(tzcom_bus_clk, 64000000);
- }
- return 0;
-
-class_device_destroy:
- if (sb_in_virt)
- iounmap(sb_in_virt);
- if (sb_in_phys)
- pmem_kfree(sb_in_phys);
- if (sb_out_virt)
- iounmap(sb_out_virt);
- if (sb_out_phys)
- pmem_kfree(sb_out_phys);
- device_destroy(driver_class, tzcom_device_no);
-class_destroy:
- class_destroy(driver_class);
-unregister_chrdev_region:
- unregister_chrdev_region(tzcom_device_no, 1);
- return rc;
-}
-
-static void __exit tzcom_exit(void)
-{
- PDEBUG("Goodbye tzcom");
- if (sb_in_virt)
- iounmap(sb_in_virt);
- if (sb_in_phys)
- pmem_kfree(sb_in_phys);
- if (sb_out_virt)
- iounmap(sb_out_virt);
- if (sb_out_phys)
- pmem_kfree(sb_out_phys);
- if (pil != NULL) {
- pil_put(pil);
- pil = NULL;
- }
- clk_put(tzcom_bus_clk);
- device_destroy(driver_class, tzcom_device_no);
- class_destroy(driver_class);
- unregister_chrdev_region(tzcom_device_no, 1);
- ion_client_destroy(ion_clnt);
-}
-
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Sachin Shah <sachins@codeaurora.org>");
-MODULE_DESCRIPTION("Qualcomm TrustZone Communicator");
-MODULE_VERSION("1.00");
-
-module_init(tzcom_init);
-module_exit(tzcom_exit);
diff --git a/drivers/misc/tzcomi.h b/drivers/misc/tzcomi.h
deleted file mode 100644
index 33634cf..0000000
--- a/drivers/misc/tzcomi.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Qualcomm TrustZone communicator driver
- *
- * Copyright (c) 2011, 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 __TZCOMI_H_
-#define __TZCOMI_H_
-
-#include <linux/types.h>
-
-enum tz_sched_cmd_id {
- TZ_SCHED_CMD_ID_INVALID = 0,
- TZ_SCHED_CMD_ID_INIT_SB_OUT, /**< Initialize the shared buffer */
- TZ_SCHED_CMD_ID_INIT_SB_LOG, /**< Initialize the logging shared buf */
- TZ_SCHED_CMD_ID_UNKNOWN = 0x7FFFFFFE,
- TZ_SCHED_CMD_ID_MAX = 0x7FFFFFFF
-};
-
-enum tz_sched_cmd_type {
- TZ_SCHED_CMD_INVALID = 0,
- TZ_SCHED_CMD_NEW, /** New TZ Scheduler Command */
- TZ_SCHED_CMD_PENDING, /** Pending cmd...sched will restore stack */
- TZ_SCHED_CMD_COMPLETE, /** TZ sched command is complete */
- TZ_SCHED_CMD_MAX = 0x7FFFFFFF
-};
-
-enum tz_sched_cmd_status {
- TZ_SCHED_STATUS_INCOMPLETE = 0,
- TZ_SCHED_STATUS_COMPLETE,
- TZ_SCHED_STATUS_MAX = 0x7FFFFFFF
-};
-
-/** Command structure for initializing shared buffers (SB_OUT
- and SB_LOG)
-*/
-__packed struct tz_pr_init_sb_req_s {
- /** First 4 bytes should always be command id
- * from enum tz_sched_cmd_id */
- uint32_t pr_cmd;
- /** Pointer to the physical location of sb_out buffer */
- uint32_t sb_ptr;
- /** length of shared buffer */
- uint32_t sb_len;
-};
-
-
-__packed struct tz_pr_init_sb_rsp_s {
- /** First 4 bytes should always be command id
- * from enum tz_sched_cmd_id */
- uint32_t pr_cmd;
- /** Return code, 0 for success, Approp error code otherwise */
- int32_t ret;
-};
-
-
-/**
- * struct tzcom_command - tzcom command buffer
- * @cmd_type: value from enum tz_sched_cmd_type
- * @sb_in_cmd_addr: points to physical location of command
- * buffer
- * @sb_in_cmd_len: length of command buffer
- */
-__packed struct tzcom_command {
- uint32_t cmd_type;
- uint8_t *sb_in_cmd_addr;
- uint32_t sb_in_cmd_len;
-};
-
-/**
- * struct tzcom_response - tzcom response buffer
- * @cmd_status: value from enum tz_sched_cmd_status
- * @sb_in_rsp_addr: points to physical location of response
- * buffer
- * @sb_in_rsp_len: length of command response
- */
-__packed struct tzcom_response {
- uint32_t cmd_status;
- uint8_t *sb_in_rsp_addr;
- uint32_t sb_in_rsp_len;
-};
-
-/**
- * struct tzcom_callback - tzcom callback buffer
- * @cmd_id: command to run in registered service
- * @sb_out_rsp_addr: points to physical location of response
- * buffer
- * @sb_in_cmd_len: length of command response
- *
- * A callback buffer would be laid out in sb_out as follows:
- *
- * --------------------- <--- struct tzcom_callback
- * | callback header |
- * --------------------- <--- tzcom_callback.sb_out_cb_data_off
- * | callback data |
- * ---------------------
- */
-__packed struct tzcom_callback {
- uint32_t cmd_id;
- uint32_t sb_out_cb_data_len;
- uint32_t sb_out_cb_data_off;
-};
-
-#endif /* __TZCOMI_H_ */
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 5e0d669..1331aa4 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -606,7 +606,6 @@
struct mmc_request mrq = {NULL};
struct mmc_command cmd = {0};
struct mmc_data data = {0};
- unsigned int timeout_us;
struct scatterlist sg;
@@ -626,23 +625,12 @@
cmd.arg = 0;
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
- data.timeout_ns = card->csd.tacc_ns * 100;
- data.timeout_clks = card->csd.tacc_clks * 100;
-
- timeout_us = data.timeout_ns / 1000;
- timeout_us += data.timeout_clks * 1000 /
- (card->host->ios.clock / 1000);
-
- if (timeout_us > 100000) {
- data.timeout_ns = 100000000;
- data.timeout_clks = 0;
- }
-
data.blksz = 4;
data.blocks = 1;
data.flags = MMC_DATA_READ;
data.sg = &sg;
data.sg_len = 1;
+ mmc_set_data_timeout(&data, card);
mrq.cmd = &cmd;
mrq.data = &data;
@@ -1394,6 +1382,7 @@
if (mq->num_of_potential_packed_wr_reqs >
mq->num_wr_reqs_to_start_packing)
mq->wr_packing_enabled = true;
+ mq->num_of_potential_packed_wr_reqs = 0;
return;
}
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index e7838f5..eba80c5 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1173,6 +1173,9 @@
clks = (unsigned long long)data->timeout_ns * host->clk_rate;
do_div(clks, 1000000000UL);
timeout = data->timeout_clks + (unsigned int)clks*2 ;
+ WARN(!timeout,
+ "%s: data timeout is zero. timeout_ns=0x%x, timeout_clks=0x%x\n",
+ mmc_hostname(host->mmc), data->timeout_ns, data->timeout_clks);
if (host->is_dma_mode && (datactrl & MCI_DPSM_DMAENABLE)) {
/* Use ADM (Application Data Mover) HW for Data transfer */
@@ -2338,8 +2341,8 @@
static inline void msmsdcc_setup_clocks(struct msmsdcc_host *host, bool enable)
{
if (enable) {
- if (!IS_ERR_OR_NULL(host->dfab_pclk))
- clk_prepare_enable(host->dfab_pclk);
+ if (!IS_ERR_OR_NULL(host->bus_clk))
+ clk_prepare_enable(host->bus_clk);
if (!IS_ERR(host->pclk))
clk_prepare_enable(host->pclk);
clk_prepare_enable(host->clk);
@@ -2351,8 +2354,8 @@
clk_disable_unprepare(host->clk);
if (!IS_ERR(host->pclk))
clk_disable_unprepare(host->pclk);
- if (!IS_ERR_OR_NULL(host->dfab_pclk))
- clk_disable_unprepare(host->dfab_pclk);
+ if (!IS_ERR_OR_NULL(host->bus_clk))
+ clk_disable_unprepare(host->bus_clk);
}
}
@@ -2874,13 +2877,14 @@
DBG(host, "ios->clock = %u\n", ios->clock);
spin_lock_irqsave(&host->lock, flags);
if (!host->sdcc_irq_disabled) {
- spin_unlock_irqrestore(&host->lock, flags);
- disable_irq(host->core_irqres->start);
- spin_lock_irqsave(&host->lock, flags);
+ disable_irq_nosync(host->core_irqres->start);
host->sdcc_irq_disabled = 1;
}
spin_unlock_irqrestore(&host->lock, flags);
+ /* Make sure sdcc core irq is synchronized */
+ synchronize_irq(host->core_irqres->start);
+
pwr = msmsdcc_setup_pwr(host, ios);
spin_lock_irqsave(&host->lock, flags);
@@ -4825,21 +4829,17 @@
}
/*
- * Setup SDCC clock if derived from Dayatona
- * fabric core clock.
+ * Setup SDCC bus voter clock.
*/
- if (plat->pclk_src_dfab) {
- host->dfab_pclk = clk_get(&pdev->dev, "bus_clk");
- if (!IS_ERR(host->dfab_pclk)) {
- /* Set the clock rate to 64MHz for max. performance */
- ret = clk_set_rate(host->dfab_pclk, 64000000);
- if (ret)
- goto dfab_pclk_put;
- ret = clk_prepare_enable(host->dfab_pclk);
- if (ret)
- goto dfab_pclk_put;
- } else
- goto dma_free;
+ host->bus_clk = clk_get(&pdev->dev, "bus_clk");
+ if (!IS_ERR_OR_NULL(host->bus_clk)) {
+ /* Vote for max. clk rate for max. performance */
+ ret = clk_set_rate(host->bus_clk, INT_MAX);
+ if (ret)
+ goto bus_clk_put;
+ ret = clk_prepare_enable(host->bus_clk);
+ if (ret)
+ goto bus_clk_put;
}
/*
@@ -5226,12 +5226,11 @@
pclk_put:
if (!IS_ERR(host->pclk))
clk_put(host->pclk);
- if (!IS_ERR_OR_NULL(host->dfab_pclk))
- clk_disable_unprepare(host->dfab_pclk);
- dfab_pclk_put:
- if (!IS_ERR_OR_NULL(host->dfab_pclk))
- clk_put(host->dfab_pclk);
- dma_free:
+ if (!IS_ERR_OR_NULL(host->bus_clk))
+ clk_disable_unprepare(host->bus_clk);
+ bus_clk_put:
+ if (!IS_ERR_OR_NULL(host->bus_clk))
+ clk_put(host->bus_clk);
if (host->is_dma_mode) {
if (host->dmares)
dma_free_coherent(NULL,
@@ -5288,8 +5287,8 @@
clk_put(host->clk);
if (!IS_ERR(host->pclk))
clk_put(host->pclk);
- if (!IS_ERR_OR_NULL(host->dfab_pclk))
- clk_put(host->dfab_pclk);
+ if (!IS_ERR_OR_NULL(host->bus_clk))
+ clk_put(host->bus_clk);
if (host->cpu_dma_latency)
pm_qos_remove_request(&host->pm_qos_req_dma);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 1fe5129..2222337 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -350,7 +350,7 @@
struct mmc_host *mmc;
struct clk *clk; /* main MMC bus clock */
struct clk *pclk; /* SDCC peripheral bus clock */
- struct clk *dfab_pclk; /* Daytona Fabric SDCC clock */
+ struct clk *bus_clk; /* SDCC bus voter clock */
unsigned int clks_on; /* set if clocks are enabled */
unsigned int eject; /* eject state */
diff --git a/drivers/mtd/devices/msm_nand.c b/drivers/mtd/devices/msm_nand.c
index bd36aea..c43abca 100644
--- a/drivers/mtd/devices/msm_nand.c
+++ b/drivers/mtd/devices/msm_nand.c
@@ -1990,20 +1990,74 @@
{
int ret;
struct mtd_oob_ops ops;
+ int (*read_oob)(struct mtd_info *, loff_t, struct mtd_oob_ops *);
- /* printk("msm_nand_read %llx %x\n", from, len); */
+ if (!dual_nand_ctlr_present)
+ read_oob = msm_nand_read_oob;
+ else
+ read_oob = msm_nand_read_oob_dualnandc;
ops.mode = MTD_OPS_PLACE_OOB;
- ops.len = len;
ops.retlen = 0;
ops.ooblen = 0;
- ops.datbuf = buf;
ops.oobbuf = NULL;
- if (!dual_nand_ctlr_present)
- ret = msm_nand_read_oob(mtd, from, &ops);
- else
- ret = msm_nand_read_oob_dualnandc(mtd, from, &ops);
- *retlen = ops.retlen;
+ ret = 0;
+ *retlen = 0;
+
+ if ((from & (mtd->writesize - 1)) == 0 && len == mtd->writesize) {
+ /* reading a page on page boundary */
+ ops.len = len;
+ ops.datbuf = buf;
+ ret = read_oob(mtd, from, &ops);
+ *retlen = ops.retlen;
+ } else if (len > 0) {
+ /* reading any size on any offset. partial page is supported */
+ u8 *bounce_buf;
+ loff_t aligned_from;
+ loff_t offset;
+ size_t actual_len;
+
+ bounce_buf = kmalloc(mtd->writesize, GFP_KERNEL);
+ if (!bounce_buf) {
+ pr_err("%s: could not allocate memory\n", __func__);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ops.len = mtd->writesize;
+ offset = from & (mtd->writesize - 1);
+ aligned_from = from - offset;
+
+ for (;;) {
+ int no_copy;
+
+ actual_len = mtd->writesize - offset;
+ if (actual_len > len)
+ actual_len = len;
+
+ no_copy = (offset == 0 && actual_len == mtd->writesize);
+ ops.datbuf = (no_copy) ? buf : bounce_buf;
+ ret = read_oob(mtd, aligned_from, &ops);
+ if (ret < 0)
+ break;
+
+ if (!no_copy)
+ memcpy(buf, bounce_buf + offset, actual_len);
+
+ len -= actual_len;
+ *retlen += actual_len;
+ if (len == 0)
+ break;
+
+ buf += actual_len;
+ offset = 0;
+ aligned_from += mtd->writesize;
+ }
+
+ kfree(bounce_buf);
+ }
+
+out:
return ret;
}
@@ -2963,18 +3017,54 @@
{
int ret;
struct mtd_oob_ops ops;
+ int (*write_oob)(struct mtd_info *, loff_t, struct mtd_oob_ops *);
+
+ if (!dual_nand_ctlr_present)
+ write_oob = msm_nand_write_oob;
+ else
+ write_oob = msm_nand_write_oob_dualnandc;
ops.mode = MTD_OPS_PLACE_OOB;
- ops.len = len;
ops.retlen = 0;
ops.ooblen = 0;
- ops.datbuf = (uint8_t *)buf;
ops.oobbuf = NULL;
- if (!dual_nand_ctlr_present)
- ret = msm_nand_write_oob(mtd, to, &ops);
- else
- ret = msm_nand_write_oob_dualnandc(mtd, to, &ops);
- *retlen = ops.retlen;
+ ret = 0;
+ *retlen = 0;
+
+ if (!virt_addr_valid(buf) &&
+ ((to | len) & (mtd->writesize - 1)) == 0 &&
+ ((unsigned long) buf & ~PAGE_MASK) + len > PAGE_SIZE) {
+ /*
+ * Handle writing of large size write buffer in vmalloc
+ * address space that does not fit in an MMU page.
+ * The destination address must be on page boundary,
+ * and the size must be multiple of NAND page size.
+ * Writing partial page is not supported.
+ */
+ ops.len = mtd->writesize;
+
+ for (;;) {
+ ops.datbuf = (uint8_t *) buf;
+
+ ret = write_oob(mtd, to, &ops);
+ if (ret < 0)
+ break;
+
+ len -= mtd->writesize;
+ *retlen += mtd->writesize;
+ if (len == 0)
+ break;
+
+ buf += mtd->writesize;
+ to += mtd->writesize;
+ }
+ } else {
+ ops.len = len;
+ ops.datbuf = (uint8_t *) buf;
+ ret = write_oob(mtd, to, &ops);
+ *retlen = ops.retlen;
+ }
+
return ret;
}
@@ -6747,6 +6837,7 @@
mtd->writesize = supported_flash.pagesize * i;
mtd->oobsize = supported_flash.oobsize * i;
mtd->erasesize = supported_flash.blksize * i;
+ mtd->writebufsize = mtd->writesize;
if (!interleave_enable)
mtd_writesize = mtd->writesize;
diff --git a/drivers/net/usb/rmnet_usb_data.c b/drivers/net/usb/rmnet_usb_data.c
index 2183ee6..ee9737a 100644
--- a/drivers/net/usb/rmnet_usb_data.c
+++ b/drivers/net/usb/rmnet_usb_data.c
@@ -99,7 +99,7 @@
dev = (struct rmnet_ctrl_dev *)unet->data[1];
if (!dev) {
- dev_err(&unet->udev->dev, "%s: ctrl device not found\n",
+ dev_err(&iface->dev, "%s: ctrl device not found\n",
__func__);
retval = -ENODEV;
goto fail;
@@ -118,7 +118,7 @@
}
/* TBD : do we need to set/clear usbnet->udev->reset_resume*/
} else
- dev_dbg(&unet->udev->dev,
+ dev_dbg(&iface->dev,
"%s: device is busy can not suspend\n", __func__);
fail:
@@ -141,8 +141,7 @@
dev = (struct rmnet_ctrl_dev *)unet->data[1];
if (!dev) {
- dev_err(&unet->udev->dev, "%s: ctrl device not found\n",
- __func__);
+ dev_err(&iface->dev, "%s: ctrl device not found\n", __func__);
retval = -ENODEV;
goto fail;
}
@@ -164,17 +163,15 @@
struct usb_host_endpoint *bulk_in = NULL;
struct usb_host_endpoint *bulk_out = NULL;
struct usb_host_endpoint *int_in = NULL;
- struct usb_device *udev;
int status = 0;
int i;
int numends;
- udev = interface_to_usbdev(iface);
numends = iface->cur_altsetting->desc.bNumEndpoints;
for (i = 0; i < numends; i++) {
endpoint = iface->cur_altsetting->endpoint + i;
if (!endpoint) {
- dev_err(&udev->dev, "%s: invalid endpoint %u\n",
+ dev_err(&iface->dev, "%s: invalid endpoint %u\n",
__func__, i);
status = -EINVAL;
goto out;
@@ -188,7 +185,7 @@
}
if (!bulk_in || !bulk_out || !int_in) {
- dev_err(&udev->dev, "%s: invalid endpoints\n", __func__);
+ dev_err(&iface->dev, "%s: invalid endpoints\n", __func__);
status = -EINVAL;
goto out;
}
@@ -394,7 +391,7 @@
break;
default:
- dev_err(&unet->udev->dev, "[%s] error: "
+ dev_err(&unet->intf->dev, "[%s] error: "
"rmnet_ioct called for unsupported cmd[%d]",
dev->name, cmd);
return -EINVAL;
@@ -507,16 +504,14 @@
const struct usb_device_id *prod)
{
struct usbnet *unet;
- struct usb_device *udev;
struct driver_info *info;
unsigned int iface_num;
static int first_rmnet_iface_num = -EINVAL;
int status = 0;
- udev = interface_to_usbdev(iface);
iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
if (iface->num_altsetting != 1) {
- dev_err(&udev->dev, "%s invalid num_altsetting %u\n",
+ dev_err(&iface->dev, "%s invalid num_altsetting %u\n",
__func__, iface->num_altsetting);
status = -EINVAL;
goto out;
@@ -528,7 +523,7 @@
status = usbnet_probe(iface, prod);
if (status < 0) {
- dev_err(&udev->dev, "usbnet_probe failed %d\n", status);
+ dev_err(&iface->dev, "usbnet_probe failed %d\n", status);
goto out;
}
unet = usb_get_intfdata(iface);
@@ -558,10 +553,10 @@
status = rmnet_usb_data_debugfs_init(unet);
if (status)
- dev_dbg(&udev->dev, "mode debugfs file is not available\n");
+ dev_dbg(&iface->dev, "mode debugfs file is not available\n");
/* allow modem to wake up suspended system */
- device_set_wakeup_enable(&udev->dev, 1);
+ device_set_wakeup_enable(&unet->udev->dev, 1);
out:
return status;
}
@@ -569,23 +564,20 @@
static void rmnet_usb_disconnect(struct usb_interface *intf)
{
struct usbnet *unet;
- struct usb_device *udev;
struct rmnet_ctrl_dev *dev;
- udev = interface_to_usbdev(intf);
- device_set_wakeup_enable(&udev->dev, 0);
-
unet = usb_get_intfdata(intf);
if (!unet) {
- dev_err(&udev->dev, "%s:data device not found\n", __func__);
+ dev_err(&intf->dev, "%s:data device not found\n", __func__);
return;
}
+ device_set_wakeup_enable(&unet->udev->dev, 0);
rmnet_usb_data_debugfs_cleanup(unet);
dev = (struct rmnet_ctrl_dev *)unet->data[1];
if (!dev) {
- dev_err(&udev->dev, "%s:ctrl device not found\n", __func__);
+ dev_err(&intf->dev, "%s:ctrl device not found\n", __func__);
return;
}
unet->data[0] = 0;
diff --git a/drivers/regulator/msm-gpio-regulator.c b/drivers/regulator/msm-gpio-regulator.c
index 5c99f4c..15e5b53 100644
--- a/drivers/regulator/msm-gpio-regulator.c
+++ b/drivers/regulator/msm-gpio-regulator.c
@@ -42,11 +42,13 @@
/* Request GPIO now if it hasn't been requested before. */
if (!vreg->gpio_requested) {
rc = gpio_request(vreg->gpio, vreg->gpio_label);
- if (rc < 0)
+ if (rc < 0) {
pr_err("failed to request gpio %u (%s), rc=%d\n",
vreg->gpio, vreg->gpio_label, rc);
- else
+ return rc;
+ } else {
vreg->gpio_requested = true;
+ }
rc = gpio_sysfs_set_active_low(vreg->gpio, vreg->active_low);
if (rc < 0)
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 4e6091e..81ce143 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -26,6 +26,9 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/msm_hsusb.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/rpm-regulator.h>
#include "core.h"
#include "gadget.h"
@@ -95,6 +98,49 @@
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 regulator *hsusb_3p3;
+ struct regulator *hsusb_1p8;
+ struct regulator *hsusb_vddcx;
+ struct regulator *ssusb_1p8;
+ struct regulator *ssusb_vddcx;
+ enum usb_vdd_type ss_vdd_type;
+ enum usb_vdd_type hs_vdd_type;
+};
+
+#define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */
+#define USB_HSPHY_3P3_VOL_MAX 3300000 /* uV */
+#define USB_HSPHY_3P3_HPM_LOAD 16000 /* uA */
+
+#define USB_HSPHY_1P8_VOL_MIN 1800000 /* uV */
+#define USB_HSPHY_1P8_VOL_MAX 1800000 /* uV */
+#define USB_HSPHY_1P8_HPM_LOAD 19000 /* uA */
+
+#define USB_SSPHY_1P8_VOL_MIN 1800000 /* uV */
+#define USB_SSPHY_1P8_VOL_MAX 1800000 /* uV */
+#define USB_SSPHY_1P8_HPM_LOAD 23000 /* uA */
+
+#define USB_PHY_VDD_DIG_VOL_NONE 0 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MIN 1045000 /* uV */
+#define USB_PHY_VDD_DIG_VOL_MAX 1320000 /* uV */
+
+enum usb_vdd_value {
+ VDD_NONE = 0,
+ VDD_MIN,
+ VDD_MAX,
+ VDD_VAL_MAX,
+};
+
+static const int vdd_val[VDD_TYPE_MAX][VDD_VAL_MAX] = {
+ { /* VDD_CX CORNER Voting */
+ [VDD_NONE] = RPM_VREG_CORNER_NONE,
+ [VDD_MIN] = RPM_VREG_CORNER_NOMINAL,
+ [VDD_MAX] = RPM_VREG_CORNER_HIGH,
+ },
+ { /* VDD_CX Voltage Voting */
+ [VDD_NONE] = USB_PHY_VDD_DIG_VOL_NONE,
+ [VDD_MIN] = USB_PHY_VDD_DIG_VOL_MIN,
+ [VDD_MAX] = USB_PHY_VDD_DIG_VOL_MAX,
+ },
};
static struct dwc3_msm *context;
@@ -750,6 +796,213 @@
}
EXPORT_SYMBOL(msm_ep_unconfig);
+/* HSPHY */
+static int dwc3_hsusb_config_vddcx(int high)
+{
+ int min_vol, ret;
+ struct dwc3_msm *dwc = context;
+ enum usb_vdd_type vdd_type = context->hs_vdd_type;
+ int max_vol = vdd_val[vdd_type][VDD_MAX];
+
+ min_vol = vdd_val[vdd_type][high ? VDD_MIN : VDD_NONE];
+ ret = regulator_set_voltage(dwc->hsusb_vddcx, min_vol, max_vol);
+ if (ret) {
+ dev_err(dwc->dev, "unable to set voltage for HSUSB_VDDCX\n");
+ return ret;
+ }
+
+ dev_dbg(dwc->dev, "%s: min_vol:%d max_vol:%d\n", __func__,
+ min_vol, max_vol);
+
+ return ret;
+}
+
+static int dwc3_hsusb_ldo_init(int init)
+{
+ int rc = 0;
+ struct dwc3_msm *dwc = context;
+
+ if (!init) {
+ regulator_set_voltage(dwc->hsusb_1p8, 0, USB_HSPHY_1P8_VOL_MAX);
+ regulator_set_voltage(dwc->hsusb_3p3, 0, USB_HSPHY_3P3_VOL_MAX);
+ return 0;
+ }
+
+ dwc->hsusb_3p3 = devm_regulator_get(dwc->dev, "HSUSB_3p3");
+ if (IS_ERR(dwc->hsusb_3p3)) {
+ dev_err(dwc->dev, "unable to get hsusb 3p3\n");
+ return PTR_ERR(dwc->hsusb_3p3);
+ }
+
+ rc = regulator_set_voltage(dwc->hsusb_3p3,
+ USB_HSPHY_3P3_VOL_MIN, USB_HSPHY_3P3_VOL_MAX);
+ if (rc) {
+ dev_err(dwc->dev, "unable to set voltage for hsusb 3p3\n");
+ return rc;
+ }
+ dwc->hsusb_1p8 = devm_regulator_get(dwc->dev, "HSUSB_1p8");
+ if (IS_ERR(dwc->hsusb_1p8)) {
+ dev_err(dwc->dev, "unable to get hsusb 1p8\n");
+ rc = PTR_ERR(dwc->hsusb_1p8);
+ goto devote_3p3;
+ }
+ rc = regulator_set_voltage(dwc->hsusb_1p8,
+ USB_HSPHY_1P8_VOL_MIN, USB_HSPHY_1P8_VOL_MAX);
+ if (rc) {
+ dev_err(dwc->dev, "unable to set voltage for hsusb 1p8\n");
+ goto devote_3p3;
+ }
+
+ return 0;
+
+devote_3p3:
+ regulator_set_voltage(dwc->hsusb_3p3, 0, USB_HSPHY_3P3_VOL_MAX);
+
+ return rc;
+}
+
+static int dwc3_hsusb_ldo_enable(int on)
+{
+ int rc = 0;
+ struct dwc3_msm *dwc = context;
+
+ dev_dbg(dwc->dev, "reg (%s)\n", on ? "HPM" : "LPM");
+
+ if (!on)
+ goto disable_regulators;
+
+
+ rc = regulator_set_optimum_mode(dwc->hsusb_1p8, USB_HSPHY_1P8_HPM_LOAD);
+ if (rc < 0) {
+ dev_err(dwc->dev, "Unable to set HPM of regulator HSUSB_1p8\n");
+ return rc;
+ }
+
+ rc = regulator_enable(dwc->hsusb_1p8);
+ if (rc) {
+ dev_err(dwc->dev, "Unable to enable HSUSB_1p8\n");
+ goto put_1p8_lpm;
+ }
+
+ rc = regulator_set_optimum_mode(dwc->hsusb_3p3, USB_HSPHY_3P3_HPM_LOAD);
+ if (rc < 0) {
+ dev_err(dwc->dev, "Unable to set HPM of regulator HSUSB_3p3\n");
+ goto disable_1p8;
+ }
+
+ rc = regulator_enable(dwc->hsusb_3p3);
+ if (rc) {
+ dev_err(dwc->dev, "Unable to enable HSUSB_3p3\n");
+ goto put_3p3_lpm;
+ }
+
+ return 0;
+
+disable_regulators:
+ rc = regulator_disable(dwc->hsusb_3p3);
+ if (rc)
+ dev_err(dwc->dev, "Unable to disable HSUSB_3p3\n");
+
+put_3p3_lpm:
+ rc = regulator_set_optimum_mode(dwc->hsusb_3p3, 0);
+ if (rc < 0)
+ dev_err(dwc->dev, "Unable to set LPM of regulator HSUSB_3p3\n");
+
+disable_1p8:
+ rc = regulator_disable(dwc->hsusb_1p8);
+ if (rc)
+ dev_err(dwc->dev, "Unable to disable HSUSB_1p8\n");
+
+put_1p8_lpm:
+ rc = regulator_set_optimum_mode(dwc->hsusb_1p8, 0);
+ if (rc < 0)
+ dev_err(dwc->dev, "Unable to set LPM of regulator HSUSB_1p8\n");
+
+ return rc < 0 ? rc : 0;
+}
+
+/* SSPHY */
+static int dwc3_ssusb_config_vddcx(int high)
+{
+ int min_vol, ret;
+ struct dwc3_msm *dwc = context;
+ enum usb_vdd_type vdd_type = context->ss_vdd_type;
+ int max_vol = vdd_val[vdd_type][VDD_MAX];
+
+ min_vol = vdd_val[vdd_type][high ? VDD_MIN : VDD_NONE];
+ ret = regulator_set_voltage(dwc->ssusb_vddcx, min_vol, max_vol);
+ if (ret) {
+ dev_err(dwc->dev, "unable to set voltage for SSUSB_VDDCX\n");
+ return ret;
+ }
+
+ dev_dbg(dwc->dev, "%s: min_vol:%d max_vol:%d\n", __func__,
+ min_vol, max_vol);
+ return ret;
+}
+
+/* 3.3v supply not needed for SS PHY */
+static int dwc3_ssusb_ldo_init(int init)
+{
+ int rc = 0;
+ struct dwc3_msm *dwc = context;
+
+ if (!init) {
+ regulator_set_voltage(dwc->ssusb_1p8, 0, USB_SSPHY_1P8_VOL_MAX);
+ return 0;
+ }
+
+ dwc->ssusb_1p8 = devm_regulator_get(dwc->dev, "SSUSB_1p8");
+ if (IS_ERR(dwc->ssusb_1p8)) {
+ dev_err(dwc->dev, "unable to get ssusb 1p8\n");
+ return PTR_ERR(dwc->ssusb_1p8);
+ }
+ rc = regulator_set_voltage(dwc->ssusb_1p8,
+ USB_SSPHY_1P8_VOL_MIN, USB_SSPHY_1P8_VOL_MAX);
+ if (rc)
+ dev_err(dwc->dev, "unable to set voltage for ssusb 1p8\n");
+
+ return rc;
+}
+
+static int dwc3_ssusb_ldo_enable(int on)
+{
+ int rc = 0;
+ struct dwc3_msm *dwc = context;
+
+ dev_dbg(context->dev, "reg (%s)\n", on ? "HPM" : "LPM");
+
+ if (!on)
+ goto disable_regulators;
+
+
+ rc = regulator_set_optimum_mode(dwc->ssusb_1p8, USB_SSPHY_1P8_HPM_LOAD);
+ if (rc < 0) {
+ dev_err(dwc->dev, "Unable to set HPM of SSUSB_1p8\n");
+ return rc;
+ }
+
+ rc = regulator_enable(dwc->ssusb_1p8);
+ if (rc) {
+ dev_err(dwc->dev, "Unable to enable SSUSB_1p8\n");
+ goto put_1p8_lpm;
+ }
+
+ return 0;
+
+disable_regulators:
+ rc = regulator_disable(dwc->ssusb_1p8);
+ if (rc)
+ dev_err(dwc->dev, "Unable to disable SSUSB_1p8\n");
+
+put_1p8_lpm:
+ rc = regulator_set_optimum_mode(dwc->ssusb_1p8, 0);
+ if (rc < 0)
+ dev_err(dwc->dev, "Unable to set LPM of SSUSB_1p8\n");
+
+ return rc < 0 ? rc : 0;
+}
+
static int __devinit dwc3_msm_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
@@ -766,26 +1019,107 @@
platform_set_drvdata(pdev, msm);
context = msm;
+ msm->dev = &pdev->dev;
INIT_LIST_HEAD(&msm->req_complete_list);
+ /* SS PHY */
+ msm->ss_vdd_type = VDDCX_CORNER;
+ msm->ssusb_vddcx = devm_regulator_get(&pdev->dev, "ssusb_vdd_dig");
+ if (IS_ERR(msm->ssusb_vddcx)) {
+ msm->ssusb_vddcx = devm_regulator_get(&pdev->dev,
+ "SSUSB_VDDCX");
+ if (IS_ERR(msm->ssusb_vddcx)) {
+ dev_err(&pdev->dev, "unable to get ssusb vddcx\n");
+ return PTR_ERR(msm->ssusb_vddcx);
+ }
+ msm->ss_vdd_type = VDDCX;
+ dev_dbg(&pdev->dev, "ss_vdd_type: VDDCX\n");
+ }
+
+ ret = dwc3_ssusb_config_vddcx(1);
+ if (ret) {
+ dev_err(&pdev->dev, "ssusb vddcx configuration failed\n");
+ return ret;
+ }
+
+ ret = regulator_enable(context->ssusb_vddcx);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to enable the ssusb vddcx\n");
+ goto unconfig_ss_vddcx;
+ }
+
+ ret = dwc3_ssusb_ldo_init(1);
+ if (ret) {
+ dev_err(&pdev->dev, "ssusb vreg configuration failed\n");
+ goto disable_ss_vddcx;
+ }
+
+ ret = dwc3_ssusb_ldo_enable(1);
+ if (ret) {
+ dev_err(&pdev->dev, "ssusb vreg enable failed\n");
+ goto free_ss_ldo_init;
+ }
+
+ /* HS PHY */
+ msm->hs_vdd_type = VDDCX_CORNER;
+ msm->hsusb_vddcx = devm_regulator_get(&pdev->dev, "hsusb_vdd_dig");
+ if (IS_ERR(msm->hsusb_vddcx)) {
+ msm->hsusb_vddcx = devm_regulator_get(&pdev->dev,
+ "HSUSB_VDDCX");
+ if (IS_ERR(msm->hsusb_vddcx)) {
+ dev_err(&pdev->dev, "unable to get hsusb vddcx\n");
+ ret = PTR_ERR(msm->ssusb_vddcx);
+ goto disable_ss_ldo;
+ }
+ msm->hs_vdd_type = VDDCX;
+ dev_dbg(&pdev->dev, "hs_vdd_type: VDDCX\n");
+ }
+
+ ret = dwc3_hsusb_config_vddcx(1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vddcx configuration failed\n");
+ goto disable_ss_ldo;
+ }
+
+ ret = regulator_enable(context->hsusb_vddcx);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to enable the hsusb vddcx\n");
+ goto unconfig_hs_vddcx;
+ }
+
+ ret = dwc3_hsusb_ldo_init(1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vreg configuration failed\n");
+ goto disable_hs_vddcx;
+ }
+
+ ret = dwc3_hsusb_ldo_enable(1);
+ if (ret) {
+ dev_err(&pdev->dev, "hsusb vreg enable failed\n");
+ goto free_hs_ldo_init;
+ }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "missing memory base resource\n");
- return -ENODEV;
+ ret = -ENODEV;
+ goto disable_hs_ldo;
}
msm->base = devm_ioremap_nocache(&pdev->dev, res->start,
resource_size(res));
if (!msm->base) {
dev_err(&pdev->dev, "ioremap failed\n");
- return -ENODEV;
+ ret = -ENODEV;
+ goto disable_hs_ldo;
}
dwc3 = platform_device_alloc("dwc3-msm", -1);
if (!dwc3) {
dev_err(&pdev->dev, "couldn't allocate dwc3 device\n");
- return -ENOMEM;
+ ret = -ENODEV;
+ goto disable_hs_ldo;
}
dma_set_coherent_mask(&dwc3->dev, pdev->dev.coherent_dma_mask);
@@ -794,7 +1128,6 @@
dwc3->dev.dma_mask = pdev->dev.dma_mask;
dwc3->dev.dma_parms = pdev->dev.dma_parms;
msm->resource_size = resource_size(res);
- msm->dev = &pdev->dev;
msm->dwc3 = dwc3;
if (of_property_read_u32(node, "qcom,dwc-usb3-msm-dbm-eps",
@@ -810,20 +1143,20 @@
"max: %d, dbm_num_eps: %d\n",
DBM_MAX_EPS, msm->dbm_num_eps);
ret = -ENODEV;
- goto err1;
+ goto put_pdev;
}
ret = platform_device_add_resources(dwc3, pdev->resource,
pdev->num_resources);
if (ret) {
dev_err(&pdev->dev, "couldn't add resources to dwc3 device\n");
- goto err1;
+ goto put_pdev;
}
ret = platform_device_add(dwc3);
if (ret) {
dev_err(&pdev->dev, "failed to register dwc3 device\n");
- goto err1;
+ goto put_pdev;
}
/* Reset the DBM */
@@ -831,8 +1164,24 @@
return 0;
-err1:
+put_pdev:
platform_device_put(dwc3);
+disable_hs_ldo:
+ dwc3_hsusb_ldo_enable(0);
+free_hs_ldo_init:
+ dwc3_hsusb_ldo_init(0);
+disable_hs_vddcx:
+ regulator_disable(context->hsusb_vddcx);
+unconfig_hs_vddcx:
+ dwc3_hsusb_config_vddcx(0);
+disable_ss_ldo:
+ dwc3_ssusb_ldo_enable(0);
+free_ss_ldo_init:
+ dwc3_ssusb_ldo_init(0);
+disable_ss_vddcx:
+ regulator_disable(context->ssusb_vddcx);
+unconfig_ss_vddcx:
+ dwc3_ssusb_config_vddcx(0);
return ret;
}
@@ -843,6 +1192,15 @@
platform_device_unregister(msm->dwc3);
+ dwc3_hsusb_ldo_enable(0);
+ dwc3_hsusb_ldo_init(0);
+ regulator_disable(msm->hsusb_vddcx);
+ dwc3_hsusb_config_vddcx(0);
+ dwc3_ssusb_ldo_enable(0);
+ dwc3_ssusb_ldo_init(0);
+ regulator_disable(msm->ssusb_vddcx);
+ dwc3_ssusb_config_vddcx(0);
+
return 0;
}
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index eefe95f..90a3b1e 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -1546,7 +1546,8 @@
{ \
if (size >= sizeof(buffer)) \
return -EINVAL; \
- return strlcpy(buffer, buf, sizeof(buffer)); \
+ strlcpy(buffer, strim((char *) buf), sizeof(buffer)); \
+ return size; \
} \
static DEVICE_ATTR(field, S_IRUGO | S_IWUSR, field ## _show, field ## _store);
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index fb86874..8cdc2e9 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -1720,6 +1720,7 @@
if (!mReq->req.no_interrupt)
mReq->ptr->token |= MSM_ETD_IOC;
}
+ mReq->req.dma = 0;
}
mReq->ptr->page[0] = mReq->req.dma;
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index 96e5a90..37b4e53 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -11,6 +11,9 @@
* GNU General Public License for more details.
*/
+/* add additional information to our printk's */
+#define pr_fmt(fmt) "%s: " fmt "\n", __func__
+
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
@@ -18,6 +21,7 @@
#include <linux/module.h>
#include <linux/kref.h>
#include <linux/platform_device.h>
+#include <linux/ratelimit.h>
#include <linux/uaccess.h>
#include <linux/usb.h>
#include <linux/debugfs.h>
@@ -50,26 +54,37 @@
struct diag_bridge *dev = __dev;
if (!dev) {
- err("dev is null");
+ pr_err("dev is null");
return -ENODEV;
}
dev->ops = ops;
dev->err = 0;
+ kref_get(&dev->kref);
+
return 0;
}
EXPORT_SYMBOL(diag_bridge_open);
+static void diag_bridge_delete(struct kref *kref)
+{
+ struct diag_bridge *dev = container_of(kref, struct diag_bridge, kref);
+
+ usb_put_dev(dev->udev);
+ __dev = 0;
+ kfree(dev);
+}
+
void diag_bridge_close(void)
{
struct diag_bridge *dev = __dev;
- dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+ dev_dbg(&dev->ifc->dev, "%s:\n", __func__);
usb_kill_anchored_urbs(&dev->submitted);
-
dev->ops = 0;
+ kref_put(&dev->kref, diag_bridge_delete);
}
EXPORT_SYMBOL(diag_bridge_close);
@@ -78,13 +93,14 @@
struct diag_bridge *dev = urb->context;
struct diag_bridge_ops *cbs = dev->ops;
- dev_dbg(&dev->udev->dev, "%s: status:%d actual:%d\n", __func__,
+ dev_dbg(&dev->ifc->dev, "%s: status:%d actual:%d\n", __func__,
urb->status, urb->actual_length);
if (urb->status == -EPROTO) {
- dev_err(&dev->udev->dev, "%s: proto error\n", __func__);
- /* save error so that subsequent read/write returns ESHUTDOWN */
+ dev_err(&dev->ifc->dev, "%s: proto error\n", __func__);
+ /* save error so that subsequent read/write returns ENODEV */
dev->err = urb->status;
+ kref_put(&dev->kref, diag_bridge_delete);
return;
}
@@ -96,6 +112,7 @@
dev->bytes_to_host += urb->actual_length;
dev->pending_reads--;
+ kref_put(&dev->kref, diag_bridge_delete);
}
int diag_bridge_read(char *data, int size)
@@ -105,33 +122,40 @@
struct diag_bridge *dev = __dev;
int ret;
- dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+ pr_debug("reading %d bytes", size);
- if (!size) {
- dev_err(&dev->udev->dev, "invalid size:%d\n", size);
- return -EINVAL;
+ if (!dev || !dev->ifc) {
+ pr_err("device is disconnected");
+ return -ENODEV;
}
- if (!dev->ifc) {
- dev_err(&dev->udev->dev, "device is disconnected\n");
+ if (!dev->ops) {
+ pr_err("bridge is not open");
return -ENODEV;
}
+ if (!size) {
+ dev_err(&dev->ifc->dev, "invalid size:%d\n", size);
+ return -EINVAL;
+ }
+
/* if there was a previous unrecoverable error, just quit */
if (dev->err)
- return -ESHUTDOWN;
+ return -ENODEV;
+
+ kref_get(&dev->kref);
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
- dev_err(&dev->udev->dev, "unable to allocate urb\n");
- return -ENOMEM;
+ dev_err(&dev->ifc->dev, "unable to allocate urb\n");
+ ret = -ENOMEM;
+ goto error;
}
ret = usb_autopm_get_interface(dev->ifc);
- if (ret < 0) {
- dev_err(&dev->udev->dev, "autopm_get failed:%d\n", ret);
- usb_free_urb(urb);
- return ret;
+ if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
+ pr_err_ratelimited("read: autopm_get failed:%d", ret);
+ goto free_error;
}
pipe = usb_rcvbulkpipe(dev->udev, dev->in_epAddr);
@@ -142,18 +166,18 @@
ret = usb_submit_urb(urb, GFP_KERNEL);
if (ret) {
- dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret);
+ pr_err_ratelimited("submitting urb failed err:%d", ret);
dev->pending_reads--;
usb_unanchor_urb(urb);
- usb_free_urb(urb);
- usb_autopm_put_interface(dev->ifc);
- return ret;
}
-
usb_autopm_put_interface(dev->ifc);
- usb_free_urb(urb);
- return 0;
+free_error:
+ usb_free_urb(urb);
+error:
+ if (ret) /* otherwise this is done in the completion handler */
+ kref_put(&dev->kref, diag_bridge_delete);
+ return ret;
}
EXPORT_SYMBOL(diag_bridge_read);
@@ -162,14 +186,15 @@
struct diag_bridge *dev = urb->context;
struct diag_bridge_ops *cbs = dev->ops;
- dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+ dev_dbg(&dev->ifc->dev, "%s:\n", __func__);
usb_autopm_put_interface_async(dev->ifc);
if (urb->status == -EPROTO) {
- dev_err(&dev->udev->dev, "%s: proto error\n", __func__);
- /* save error so that subsequent read/write returns ESHUTDOWN */
+ dev_err(&dev->ifc->dev, "%s: proto error\n", __func__);
+ /* save error so that subsequent read/write returns ENODEV */
dev->err = urb->status;
+ kref_put(&dev->kref, diag_bridge_delete);
return;
}
@@ -181,6 +206,7 @@
dev->bytes_to_mdm += urb->actual_length;
dev->pending_writes--;
+ kref_put(&dev->kref, diag_bridge_delete);
}
int diag_bridge_write(char *data, int size)
@@ -190,33 +216,40 @@
struct diag_bridge *dev = __dev;
int ret;
- dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+ pr_debug("writing %d bytes", size);
- if (!size) {
- dev_err(&dev->udev->dev, "invalid size:%d\n", size);
- return -EINVAL;
+ if (!dev || !dev->ifc) {
+ pr_err("device is disconnected");
+ return -ENODEV;
}
- if (!dev->ifc) {
- dev_err(&dev->udev->dev, "device is disconnected\n");
+ if (!dev->ops) {
+ pr_err("bridge is not open");
return -ENODEV;
}
+ if (!size) {
+ dev_err(&dev->ifc->dev, "invalid size:%d\n", size);
+ return -EINVAL;
+ }
+
/* if there was a previous unrecoverable error, just quit */
if (dev->err)
- return -ESHUTDOWN;
+ return -ENODEV;
+
+ kref_get(&dev->kref);
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
- err("unable to allocate urb");
- return -ENOMEM;
+ dev_err(&dev->ifc->dev, "unable to allocate urb\n");
+ ret = -ENOMEM;
+ goto error;
}
ret = usb_autopm_get_interface(dev->ifc);
- if (ret < 0) {
- dev_err(&dev->udev->dev, "autopm_get failed:%d\n", ret);
- usb_free_urb(urb);
- return ret;
+ if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
+ pr_err_ratelimited("write: autopm_get failed:%d", ret);
+ goto free_error;
}
pipe = usb_sndbulkpipe(dev->udev, dev->out_epAddr);
@@ -227,30 +260,22 @@
ret = usb_submit_urb(urb, GFP_KERNEL);
if (ret) {
- dev_err(&dev->udev->dev, "submitting urb failed err:%d\n", ret);
+ pr_err_ratelimited("submitting urb failed err:%d", ret);
dev->pending_writes--;
usb_unanchor_urb(urb);
- usb_free_urb(urb);
usb_autopm_put_interface(dev->ifc);
- return ret;
+ goto free_error;
}
+free_error:
usb_free_urb(urb);
-
- return 0;
+error:
+ if (ret) /* otherwise this is done in the completion handler */
+ kref_put(&dev->kref, diag_bridge_delete);
+ return ret;
}
EXPORT_SYMBOL(diag_bridge_write);
-static void diag_bridge_delete(struct kref *kref)
-{
- struct diag_bridge *dev =
- container_of(kref, struct diag_bridge, kref);
-
- usb_put_dev(dev->udev);
- __dev = 0;
- kfree(dev);
-}
-
#if defined(CONFIG_DEBUG_FS)
#define DEBUG_BUF_SIZE 512
static ssize_t diag_read_stats(struct file *file, char __user *ubuf,
@@ -260,6 +285,9 @@
char *buf;
int ret;
+ if (!dev)
+ return -ENODEV;
+
buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
if (!buf)
return -ENOMEM;
@@ -286,8 +314,10 @@
{
struct diag_bridge *dev = __dev;
- dev->bytes_to_host = dev->bytes_to_mdm = 0;
- dev->pending_reads = dev->pending_writes = 0;
+ if (dev) {
+ dev->bytes_to_host = dev->bytes_to_mdm = 0;
+ dev->pending_reads = dev->pending_writes = 0;
+ }
return count;
}
@@ -334,7 +364,7 @@
int ret = -ENOMEM;
__u8 ifc_num;
- dbg("%s: id:%lu", __func__, id->driver_info);
+ pr_debug("id:%lu", id->driver_info);
ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;
@@ -344,12 +374,12 @@
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
- pr_err("%s: unable to allocate dev\n", __func__);
+ pr_err("unable to allocate dev");
return -ENOMEM;
}
dev->pdev = platform_device_alloc("diag_bridge", -1);
if (!dev->pdev) {
- pr_err("%s: unable to allocate platform device\n", __func__);
+ pr_err("unable to allocate platform device");
kfree(dev);
return -ENOMEM;
}
@@ -372,7 +402,7 @@
}
if (!(dev->in_epAddr && dev->out_epAddr)) {
- err("could not find bulk in and bulk out endpoints");
+ pr_err("could not find bulk in and bulk out endpoints");
ret = -ENODEV;
goto error;
}
@@ -381,7 +411,7 @@
diag_bridge_debugfs_init();
platform_device_add(dev->pdev);
- dev_dbg(&dev->udev->dev, "%s: complete\n", __func__);
+ dev_dbg(&dev->ifc->dev, "%s: complete\n", __func__);
return 0;
@@ -396,9 +426,10 @@
{
struct diag_bridge *dev = usb_get_intfdata(ifc);
- dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+ dev_dbg(&dev->ifc->dev, "%s:\n", __func__);
platform_device_del(dev->pdev);
+ dev->ifc = NULL;
diag_bridge_debugfs_cleanup();
kref_put(&dev->kref, diag_bridge_delete);
usb_set_intfdata(ifc, NULL);
@@ -413,7 +444,7 @@
if (cbs && cbs->suspend) {
ret = cbs->suspend(cbs->ctxt);
if (ret) {
- dev_dbg(&dev->udev->dev,
+ dev_dbg(&dev->ifc->dev,
"%s: diag veto'd suspend\n", __func__);
return ret;
}
@@ -467,7 +498,7 @@
ret = usb_register(&diag_bridge_driver);
if (ret) {
- err("%s: unable to register diag driver", __func__);
+ pr_err("unable to register diag driver");
return ret;
}
diff --git a/drivers/usb/misc/mdm_ctrl_bridge.c b/drivers/usb/misc/mdm_ctrl_bridge.c
index 49591cd..044af3a 100644
--- a/drivers/usb/misc/mdm_ctrl_bridge.c
+++ b/drivers/usb/misc/mdm_ctrl_bridge.c
@@ -128,12 +128,10 @@
static void resp_avail_cb(struct urb *urb)
{
struct ctrl_bridge *dev = urb->context;
- struct usb_device *udev;
int status = 0;
int resubmit_urb = 1;
struct bridge *brdg = dev->brdg;
- udev = interface_to_usbdev(dev->intf);
switch (urb->status) {
case 0:
/*success*/
@@ -154,7 +152,7 @@
/*resubmit*/
case -EOVERFLOW:
default:
- dev_dbg(&udev->dev, "%s: non zero urb status = %d\n",
+ dev_dbg(&dev->intf->dev, "%s: non zero urb status = %d\n",
__func__, urb->status);
}
@@ -163,7 +161,7 @@
usb_anchor_urb(dev->inturb, &dev->tx_submitted);
status = usb_submit_urb(dev->inturb, GFP_ATOMIC);
if (status) {
- dev_err(&udev->dev,
+ dev_err(&dev->intf->dev,
"%s: Error re-submitting Int URB %d\n",
__func__, status);
usb_unanchor_urb(dev->inturb);
@@ -175,14 +173,11 @@
{
int status;
struct usb_cdc_notification *ctrl;
- struct usb_device *udev;
struct ctrl_bridge *dev = urb->context;
struct bridge *brdg = dev->brdg;
unsigned int ctrl_bits;
unsigned char *data;
- udev = interface_to_usbdev(dev->intf);
-
switch (urb->status) {
case 0:
/*success*/
@@ -194,7 +189,8 @@
/* unplug */
return;
case -EPIPE:
- dev_err(&udev->dev, "%s: stall on int endpoint\n", __func__);
+ dev_err(&dev->intf->dev,
+ "%s: stall on int endpoint\n", __func__);
/* TBD : halt to be cleared in work */
case -EOVERFLOW:
default:
@@ -209,8 +205,8 @@
switch (ctrl->bNotificationType) {
case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
dev->resp_avail++;
- usb_fill_control_urb(dev->readurb, udev,
- usb_rcvctrlpipe(udev, 0),
+ usb_fill_control_urb(dev->readurb, dev->udev,
+ usb_rcvctrlpipe(dev->udev, 0),
(unsigned char *)dev->in_ctlreq,
dev->readbuf,
DEFAULT_READ_URB_LENGTH,
@@ -219,7 +215,7 @@
usb_anchor_urb(dev->readurb, &dev->tx_submitted);
status = usb_submit_urb(dev->readurb, GFP_ATOMIC);
if (status) {
- dev_err(&udev->dev,
+ dev_err(&dev->intf->dev,
"%s: Error submitting Read URB %d\n",
__func__, status);
usb_unanchor_urb(dev->readurb);
@@ -227,19 +223,19 @@
}
return;
case USB_CDC_NOTIFY_NETWORK_CONNECTION:
- dev_dbg(&udev->dev, "%s network\n", ctrl->wValue ?
+ dev_dbg(&dev->intf->dev, "%s network\n", ctrl->wValue ?
"connected to" : "disconnected from");
break;
case USB_CDC_NOTIFY_SERIAL_STATE:
dev->notify_ser_state++;
ctrl_bits = get_unaligned_le16(data);
- dev_dbg(&udev->dev, "serial state: %d\n", ctrl_bits);
+ dev_dbg(&dev->intf->dev, "serial state: %d\n", ctrl_bits);
dev->cbits_tohost = ctrl_bits;
if (brdg && brdg->ops.send_cbits)
brdg->ops.send_cbits(brdg->ctx, ctrl_bits);
break;
default:
- dev_err(&udev->dev, "%s: unknown notification %d received:"
+ dev_err(&dev->intf->dev, "%s: unknown notification %d received:"
"index %d len %d data0 %d data1 %d",
__func__, ctrl->bNotificationType, ctrl->wIndex,
ctrl->wLength, data[0], data[1]);
@@ -249,7 +245,7 @@
usb_anchor_urb(urb, &dev->tx_submitted);
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status) {
- dev_err(&udev->dev, "%s: Error re-submitting Int URB %d\n",
+ dev_err(&dev->intf->dev, "%s: Error re-submitting Int URB %d\n",
__func__, status);
usb_unanchor_urb(urb);
}
@@ -260,7 +256,7 @@
int retval = 0;
if (!dev->inturb) {
- dev_err(&dev->udev->dev, "%s: inturb is NULL\n", __func__);
+ dev_err(&dev->intf->dev, "%s: inturb is NULL\n", __func__);
return -ENODEV;
}
@@ -268,7 +264,7 @@
usb_anchor_urb(dev->inturb, &dev->tx_submitted);
retval = usb_submit_urb(dev->inturb, GFP_KERNEL);
if (retval < 0) {
- dev_err(&dev->udev->dev,
+ dev_err(&dev->intf->dev,
"%s error submitting int urb %d\n",
__func__, retval);
usb_unanchor_urb(dev->inturb);
@@ -321,7 +317,7 @@
if (!dev || !dev->brdg)
return;
- dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+ dev_dbg(&dev->intf->dev, "%s:\n", __func__);
ctrl_bridge_set_cbits(dev->brdg->ch_id, 0);
usb_unlink_anchored_urbs(&dev->tx_submitted);
@@ -350,7 +346,6 @@
int result;
struct urb *writeurb;
struct usb_ctrlrequest *out_ctlreq;
- struct usb_device *udev;
struct ctrl_bridge *dev;
if (id >= MAX_BRIDGE_DEVICES) {
@@ -365,14 +360,12 @@
goto free_data;
}
- udev = interface_to_usbdev(dev->intf);
-
- dev_dbg(&udev->dev, "%s:[id]:%u: write (%d bytes)\n",
+ dev_dbg(&dev->intf->dev, "%s:[id]:%u: write (%d bytes)\n",
__func__, id, size);
writeurb = usb_alloc_urb(0, GFP_ATOMIC);
if (!writeurb) {
- dev_err(&udev->dev, "%s: error allocating read urb\n",
+ dev_err(&dev->intf->dev, "%s: error allocating read urb\n",
__func__);
result = -ENOMEM;
goto free_data;
@@ -380,7 +373,7 @@
out_ctlreq = kmalloc(sizeof(*out_ctlreq), GFP_ATOMIC);
if (!out_ctlreq) {
- dev_err(&udev->dev,
+ dev_err(&dev->intf->dev,
"%s: error allocating setup packet buffer\n",
__func__);
result = -ENOMEM;
@@ -403,15 +396,15 @@
dev->intf->cur_altsetting->desc.bInterfaceNumber;
out_ctlreq->wLength = cpu_to_le16(size);
- usb_fill_control_urb(writeurb, udev,
- usb_sndctrlpipe(udev, 0),
+ usb_fill_control_urb(writeurb, dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
(unsigned char *)out_ctlreq,
(void *)data, size,
ctrl_write_callback, dev);
result = usb_autopm_get_interface_async(dev->intf);
if (result < 0) {
- dev_err(&udev->dev, "%s: unable to resume interface: %d\n",
+ dev_err(&dev->intf->dev, "%s: unable to resume interface: %d\n",
__func__, result);
/*
@@ -430,7 +423,7 @@
usb_anchor_urb(writeurb, &dev->tx_submitted);
result = usb_submit_urb(writeurb, GFP_ATOMIC);
if (result < 0) {
- dev_err(&udev->dev, "%s: submit URB error %d\n",
+ dev_err(&dev->intf->dev, "%s: submit URB error %d\n",
__func__, result);
usb_autopm_put_interface_async(dev->intf);
goto unanchor_urb;
@@ -614,14 +607,14 @@
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) {
- dev_err(&udev->dev, "%s: unable to allocate dev\n",
+ dev_err(&ifc->dev, "%s: unable to allocate dev\n",
__func__);
return -ENOMEM;
}
dev->pdev = platform_device_alloc(ctrl_bridge_names[id], id);
if (!dev->pdev) {
- dev_err(&dev->udev->dev,
- "%s: unable to allocate platform device\n", __func__);
+ dev_err(&ifc->dev, "%s: unable to allocate platform device\n",
+ __func__);
retval = -ENOMEM;
goto nomem;
}
@@ -639,7 +632,7 @@
dev->inturb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->inturb) {
- dev_err(&udev->dev, "%s: error allocating int urb\n", __func__);
+ dev_err(&ifc->dev, "%s: error allocating int urb\n", __func__);
retval = -ENOMEM;
goto pdev_del;
}
@@ -648,7 +641,7 @@
dev->intbuf = kmalloc(wMaxPacketSize, GFP_KERNEL);
if (!dev->intbuf) {
- dev_err(&udev->dev, "%s: error allocating int buffer\n",
+ dev_err(&ifc->dev, "%s: error allocating int buffer\n",
__func__);
retval = -ENOMEM;
goto free_inturb;
@@ -663,7 +656,7 @@
dev->readurb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->readurb) {
- dev_err(&udev->dev, "%s: error allocating read urb\n",
+ dev_err(&ifc->dev, "%s: error allocating read urb\n",
__func__);
retval = -ENOMEM;
goto free_intbuf;
@@ -671,7 +664,7 @@
dev->readbuf = kmalloc(DEFAULT_READ_URB_LENGTH, GFP_KERNEL);
if (!dev->readbuf) {
- dev_err(&udev->dev, "%s: error allocating read buffer\n",
+ dev_err(&ifc->dev, "%s: error allocating read buffer\n",
__func__);
retval = -ENOMEM;
goto free_rurb;
@@ -679,8 +672,7 @@
dev->in_ctlreq = kmalloc(sizeof(*dev->in_ctlreq), GFP_KERNEL);
if (!dev->in_ctlreq) {
- dev_err(&udev->dev,
- "%s:error allocating setup packet buffer\n",
+ dev_err(&ifc->dev, "%s:error allocating setup packet buffer\n",
__func__);
retval = -ENOMEM;
goto free_rbuf;
@@ -722,7 +714,7 @@
{
struct ctrl_bridge *dev = __dev[id];
- dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+ dev_dbg(&dev->intf->dev, "%s:\n", __func__);
platform_device_del(dev->pdev);
diff --git a/drivers/usb/misc/mdm_data_bridge.c b/drivers/usb/misc/mdm_data_bridge.c
index 6ee3204..26be973 100644
--- a/drivers/usb/misc/mdm_data_bridge.c
+++ b/drivers/usb/misc/mdm_data_bridge.c
@@ -208,7 +208,7 @@
/*do not resubmit*/
case -EPIPE:
set_bit(RX_HALT, &dev->flags);
- dev_err(&dev->udev->dev, "%s: epout halted\n", __func__);
+ dev_err(&dev->intf->dev, "%s: epout halted\n", __func__);
schedule_work(&dev->kevent);
/* FALLTHROUGH */
case -ESHUTDOWN:
@@ -309,7 +309,7 @@
return -ENODEV;
}
- dev_dbg(&dev->udev->dev, "%s: dev:%p\n", __func__, dev);
+ dev_dbg(&dev->intf->dev, "%s: dev:%p\n", __func__, dev);
dev->brdg = brdg;
dev->err = 0;
@@ -341,7 +341,7 @@
if (!dev || !dev->brdg)
return;
- dev_dbg(&dev->udev->dev, "%s:\n", __func__);
+ dev_dbg(&dev->intf->dev, "%s:\n", __func__);
usb_unlink_anchored_urbs(&dev->tx_active);
usb_unlink_anchored_urbs(&dev->rx_active);
@@ -370,7 +370,7 @@
status = usb_autopm_get_interface(dev->intf);
if (status < 0) {
- dev_err(&dev->udev->dev,
+ dev_err(&dev->intf->dev,
"can't acquire interface, status %d\n", status);
return;
}
@@ -378,7 +378,7 @@
status = usb_clear_halt(dev->udev, dev->bulk_out);
usb_autopm_put_interface(dev->intf);
if (status < 0 && status != -EPIPE && status != -ESHUTDOWN)
- dev_err(&dev->udev->dev,
+ dev_err(&dev->intf->dev,
"can't clear tx halt, status %d\n", status);
else
clear_bit(TX_HALT, &dev->flags);
@@ -389,7 +389,7 @@
status = usb_autopm_get_interface(dev->intf);
if (status < 0) {
- dev_err(&dev->udev->dev,
+ dev_err(&dev->intf->dev,
"can't acquire interface, status %d\n", status);
return;
}
@@ -397,7 +397,7 @@
status = usb_clear_halt(dev->udev, dev->bulk_in);
usb_autopm_put_interface(dev->intf);
if (status < 0 && status != -EPIPE && status != -ESHUTDOWN)
- dev_err(&dev->udev->dev,
+ dev_err(&dev->intf->dev,
"can't clear rx halt, status %d\n", status);
else {
clear_bit(RX_HALT, &dev->flags);
@@ -426,7 +426,7 @@
break;
case -EPIPE:
set_bit(TX_HALT, &dev->flags);
- dev_err(&dev->udev->dev, "%s: epout halted\n", __func__);
+ dev_err(&dev->intf->dev, "%s: epout halted\n", __func__);
schedule_work(&dev->kevent);
/* FALLTHROUGH */
case -ESHUTDOWN:
@@ -474,17 +474,17 @@
if (!brdg)
return -ENODEV;
- dev_dbg(&dev->udev->dev, "%s: write (%d bytes)\n", __func__, skb->len);
+ dev_dbg(&dev->intf->dev, "%s: write (%d bytes)\n", __func__, skb->len);
result = usb_autopm_get_interface(dev->intf);
if (result < 0) {
- dev_err(&dev->udev->dev, "%s: resume failure\n", __func__);
+ dev_err(&dev->intf->dev, "%s: resume failure\n", __func__);
goto pm_error;
}
txurb = usb_alloc_urb(0, GFP_KERNEL);
if (!txurb) {
- dev_err(&dev->udev->dev, "%s: error allocating read urb\n",
+ dev_err(&dev->intf->dev, "%s: error allocating read urb\n",
__func__);
result = -ENOMEM;
goto error;
@@ -512,13 +512,13 @@
if (result < 0) {
usb_unanchor_urb(txurb);
atomic_dec(&dev->pending_txurbs);
- dev_err(&dev->udev->dev, "%s: submit URB error %d\n",
+ dev_err(&dev->intf->dev, "%s: submit URB error %d\n",
__func__, result);
goto free_urb;
}
dev->to_modem++;
- dev_dbg(&dev->udev->dev, "%s: pending_txurbs: %u\n", __func__, pending);
+ dev_dbg(&dev->intf->dev, "%s: pending_txurbs: %u\n", __func__, pending);
/* flow control: last urb submitted but return -EBUSY */
if (fctrl_support && pending > fctrl_en_thld) {
@@ -928,7 +928,7 @@
for (i = 0; i < numends; i++) {
endpoint = iface->cur_altsetting->endpoint + i;
if (!endpoint) {
- dev_err(&udev->dev, "%s: invalid endpoint %u\n",
+ dev_err(&iface->dev, "%s: invalid endpoint %u\n",
__func__, i);
status = -EINVAL;
goto out;
@@ -943,20 +943,20 @@
}
if (!bulk_in || !bulk_out || !int_in) {
- dev_err(&udev->dev, "%s: invalid endpoints\n", __func__);
+ dev_err(&iface->dev, "%s: invalid endpoints\n", __func__);
status = -EINVAL;
goto out;
}
status = data_bridge_probe(iface, bulk_in, bulk_out, ch_id);
if (status < 0) {
- dev_err(&udev->dev, "data_bridge_probe failed %d\n", status);
+ dev_err(&iface->dev, "data_bridge_probe failed %d\n", status);
goto out;
}
status = ctrl_bridge_probe(iface, int_in, ch_id);
if (status < 0) {
- dev_err(&udev->dev, "ctrl_bridge_probe failed %d\n", status);
+ dev_err(&iface->dev, "ctrl_bridge_probe failed %d\n", status);
goto free_data_bridge;
}
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index b8d1df8..7777154 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -297,6 +297,11 @@
select FB_MSM_LVDS
default n
+config FB_MSM_LVDS_FRC_FHD
+ bool
+ select FB_MSM_LVDS
+ default n
+
config FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT
bool
select FB_MSM_MIPI_DSI_TOSHIBA
@@ -490,6 +495,15 @@
---help---
Support for LVDS Chimei WXGA(1366x768) panel
+config FB_MSM_LVDS_FRC_FHD_PANEL
+ bool "LVDS FRC FHD Panel"
+ select FB_MSM_LVDS_FRC_FHD
+ ---help---
+ Support for LVDS Frc FHD(1920x1080) panel
+ FRC(Frame Rate Converter) uses LVDS as input
+ interface. It is treated as a HDMI panel with
+ 1920x1080 resolution.
+
config FB_MSM_TRY_MDDI_CATCH_LCDC_PRISM
depends on FB_MSM_LCDC_HW
bool "MDDI Panel Auto Detect + LCDC Prism WVGA"
@@ -568,6 +582,7 @@
config FB_MSM_LVDS_MIPI_PANEL_DETECT
bool "LVDS + MIPI Panel Auto Detect"
select FB_MSM_LVDS_CHIMEI_WXGA
+ select FB_MSM_LVDS_FRC_FHD
select FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT
select FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT
select FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index b2ecb08..e4a0948 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -165,6 +165,7 @@
obj-$(CONFIG_FB_MSM_HDMI_ADV7520_PANEL) += adv7520.o
obj-$(CONFIG_FB_MSM_LCDC_ST15_WXGA) += lcdc_st15.o
obj-$(CONFIG_FB_MSM_LVDS_CHIMEI_WXGA) += lvds_chimei_wxga.o
+obj-$(CONFIG_FB_MSM_LVDS_FRC_FHD) += lvds_frc_fhd.o
obj-$(CONFIG_FB_MSM_HDMI_MSM_PANEL) += hdmi_msm.o
obj-$(CONFIG_FB_MSM_EXT_INTERFACE_COMMON) += external_common.o
obj-$(CONFIG_FB_MSM_LCDC_TRULY_HVGA_IPS3P2335) += lcdc_truly_ips3p2335.o
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index a372016..aa19bdd 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -809,7 +809,6 @@
if (!external_common_state->
disp_mode_list.num_of_elements)
hdmi_msm_read_edid();
- hdmi_msm_turn_on();
}
} else {
hdmi_msm_state->hpd_cable_chg_detected = FALSE;
@@ -824,16 +823,14 @@
DEV_INFO("Hdmi state switch to %d: %s\n",
external_common_state->sdev.state, __func__);
if (hpd_state) {
+ /* Build EDID table */
hdmi_msm_read_edid();
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
hdmi_msm_state->reauth = FALSE ;
#endif
- /* Build EDID table */
- hdmi_msm_turn_on();
DEV_INFO("HDMI HPD: sense CONNECTED: send ONLINE\n");
kobject_uevent(external_common_state->uevent_kobj,
KOBJ_ONLINE);
- hdmi_msm_hdcp_enable();
#ifndef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
/* Send Audio for HDMI Compliance Cases*/
envp[0] = "HDCP_STATE=PASS";
@@ -1312,7 +1309,8 @@
/* HDMI_CTRL */
HDMI_OUTP(0x0000, reg_val);
- DEV_DBG("HDMI Core: %s\n", power_on ? "Enable" : "Disable");
+ DEV_DBG("HDMI Core: %s, HDMI_CTRL=0x%08x\n",
+ power_on ? "Enable" : "Disable", reg_val);
}
static void msm_hdmi_init_ddc(void)
@@ -4105,7 +4103,6 @@
static void hdmi_msm_turn_on(void)
{
- uint32 hpd_ctrl;
uint32 audio_pkt_ctrl, audio_cfg;
/*
* Number of wait iterations for QDSP to disable Audio Engine
@@ -4128,6 +4125,7 @@
msleep(20);
}
+ hdmi_msm_set_mode(FALSE);
mutex_lock(&hdcp_auth_state_mutex);
hdmi_msm_reset_core();
mutex_unlock(&hdcp_auth_state_mutex);
@@ -4147,14 +4145,7 @@
#endif
hdmi_msm_spd_infoframe_packetsetup();
- /* set timeout to 4.1ms (max) for hardware debounce */
- hpd_ctrl = (HDMI_INP(0x0258) & ~0xFFF) | 0xFFF;
-
- /* Toggle HPD circuit to trigger HPD sense */
- HDMI_OUTP(0x0258, ~(1 << 28) & hpd_ctrl);
- HDMI_OUTP(0x0258, (1 << 28) | hpd_ctrl);
-
- /* Setup HPD IRQ */
+ /* Set IRQ for HPD */
HDMI_OUTP(0x0254, 4 | (external_common_state->hpd_state ? 0 : 2));
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
@@ -4231,22 +4222,24 @@
static void hdmi_msm_hpd_off(void)
{
+ int rc = 0;
+
if (!hdmi_msm_state->hpd_initialized) {
DEV_DBG("%s: HPD is already OFF, returning\n", __func__);
return;
}
- DEV_DBG("%s: (timer, clk, 5V, core, IRQ off)\n", __func__);
+ DEV_DBG("%s: (timer, 5V, IRQ off)\n", __func__);
del_timer(&hdmi_msm_state->hpd_state_timer);
disable_irq(hdmi_msm_state->irq);
hdmi_msm_set_mode(FALSE);
- hdmi_msm_state->hpd_initialized = FALSE;
- hdmi_msm_powerdown_phy();
- hdmi_msm_state->pd->cec_power(0);
hdmi_msm_state->pd->enable_5v(0);
- hdmi_msm_state->pd->core_power(0, 1);
hdmi_msm_clk(0);
+ rc = hdmi_msm_state->pd->gpio_config(0);
+ if (rc != 0)
+ DEV_INFO("%s: Failed to disable GPIOs. Error=%d\n",
+ __func__, rc);
hdmi_msm_state->hpd_initialized = FALSE;
}
@@ -4262,40 +4255,56 @@
{
static int phy_reset_done;
uint32 hpd_ctrl;
+ int rc = 0;
if (hdmi_msm_state->hpd_initialized) {
- DEV_DBG("%s: HPD is already ON, returning\n", __func__);
- return 0;
+ DEV_DBG("%s: HPD is already ON\n", __func__);
+ } else {
+ rc = hdmi_msm_state->pd->gpio_config(1);
+ if (rc) {
+ DEV_ERR("%s: Failed to enable GPIOs. Error=%d\n",
+ __func__, rc);
+ goto error1;
+ }
+
+ rc = hdmi_msm_clk(1);
+ if (rc) {
+ DEV_ERR("%s: Failed to enable clocks. Error=%d\n",
+ __func__, rc);
+ goto error2;
+ }
+
+ rc = hdmi_msm_state->pd->enable_5v(1);
+ if (rc) {
+ DEV_ERR("%s: Failed to enable 5V regulator. Error=%d\n",
+ __func__, rc);
+ goto error3;
+ }
+ hdmi_msm_dump_regs("HDMI-INIT: ");
+
+ hdmi_msm_set_mode(FALSE);
+ if (!phy_reset_done) {
+ hdmi_phy_reset();
+ phy_reset_done = 1;
+ }
+ hdmi_msm_set_mode(TRUE);
+
+ /* HDMI_USEC_REFTIMER[0x0208] */
+ HDMI_OUTP(0x0208, 0x0001001B);
+
+ /* set timeout to 4.1ms (max) for hardware debounce */
+ hpd_ctrl = HDMI_INP(0x0258) | 0x1FFF;
+
+ /* Toggle HPD circuit to trigger HPD sense */
+ HDMI_OUTP(0x0258, ~(1 << 28) & hpd_ctrl);
+ HDMI_OUTP(0x0258, (1 << 28) | hpd_ctrl);
+
+ hdmi_msm_state->hpd_initialized = TRUE;
+
+ /* Check HPD State */
+ enable_irq(hdmi_msm_state->irq);
}
- hdmi_msm_clk(1);
- hdmi_msm_state->pd->core_power(1, 1);
- hdmi_msm_state->pd->enable_5v(1);
- hdmi_msm_state->pd->cec_power(1);
- hdmi_msm_dump_regs("HDMI-INIT: ");
- hdmi_msm_set_mode(FALSE);
-
- if (!phy_reset_done) {
- hdmi_phy_reset();
- phy_reset_done = 1;
- }
-
- /* HDMI_USEC_REFTIMER[0x0208] */
- HDMI_OUTP(0x0208, 0x0001001B);
-
- /* Check HPD State */
- enable_irq(hdmi_msm_state->irq);
-
- /* set timeout to 4.1ms (max) for hardware debounce */
- hpd_ctrl = (HDMI_INP(0x0258) & ~0xFFF) | 0xFFF;
-
- /* Toggle HPD circuit to trigger HPD sense */
- HDMI_OUTP(0x0258, ~(1 << 28) & hpd_ctrl);
- HDMI_OUTP(0x0258, (1 << 28) | hpd_ctrl);
-
- DEV_DBG("%s: (clk, 5V, core, IRQ on) <trigger:%s>\n", __func__,
- trigger_handler ? "true" : "false");
-
if (trigger_handler) {
/* Set HPD state machine: ensure at least 2 readouts */
mutex_lock(&hdmi_msm_state_mutex);
@@ -4310,24 +4319,33 @@
jiffies + HZ/2);
}
- hdmi_msm_state->hpd_initialized = TRUE;
-
- hdmi_msm_set_mode(TRUE);
-
+ DEV_DBG("%s: (IRQ, 5V on) <trigger:%s>\n", __func__,
+ trigger_handler ? "true" : "false");
return 0;
+
+error3:
+ hdmi_msm_clk(0);
+error2:
+ hdmi_msm_state->pd->gpio_config(0);
+error1:
+ return rc;
}
static int hdmi_msm_power_ctrl(boolean enable)
{
- if (!external_common_state->hpd_feature_on)
+ int rc = 0;
+ if (!hdmi_prim_display && !external_common_state->hpd_feature_on)
return 0;
- if (enable)
- hdmi_msm_hpd_on(true);
- else
+ if (enable) {
+ DEV_DBG("%s: Turning HPD ciruitry on\n", __func__);
+ rc = hdmi_msm_hpd_on(true);
+ } else {
+ DEV_DBG("%s: Turning HPD ciruitry off\n", __func__);
hdmi_msm_hpd_off();
+ }
- return 0;
+ return rc;
}
static int hdmi_msm_power_on(struct platform_device *pdev)
@@ -4351,22 +4369,15 @@
#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
changed = hdmi_common_get_video_format_from_drv_data(mfd);
- if (!external_common_state->hpd_feature_on || mfd->ref_cnt) {
- int rc = hdmi_msm_hpd_on(true);
- DEV_INFO("HPD: panel power without 'hpd' feature on\n");
- if (rc) {
- DEV_WARN("HPD: activation failed: rc=%d\n", rc);
- return rc;
- }
- }
hdmi_msm_audio_info_setup(TRUE, 0, 0, 0, FALSE);
mutex_lock(&external_common_state_hpd_mutex);
hdmi_msm_state->panel_power_on = TRUE;
- if ((external_common_state->hpd_state && !hdmi_msm_is_power_on())
- || changed) {
+ if (external_common_state->hpd_state && hdmi_msm_is_power_on()) {
+ DEV_DBG("%s: Turning HDMI on\n", __func__);
mutex_unlock(&external_common_state_hpd_mutex);
hdmi_msm_turn_on();
+ hdmi_msm_hdcp_enable();
} else
mutex_unlock(&external_common_state_hpd_mutex);
@@ -4386,8 +4397,6 @@
*/
static int hdmi_msm_power_off(struct platform_device *pdev)
{
- struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
-
if (!hdmi_msm_state->hdmi_app_clk)
return -ENODEV;
@@ -4407,15 +4416,7 @@
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
hdcp_deauthenticate();
#endif
- hdmi_msm_hpd_off();
hdmi_msm_powerdown_phy();
- hdmi_msm_dump_regs("HDMI-OFF: ");
- hdmi_msm_hpd_on(true);
-
- mutex_lock(&external_common_state_hpd_mutex);
- if (!external_common_state->hpd_feature_on || mfd->ref_cnt)
- hdmi_msm_hpd_off();
- mutex_unlock(&external_common_state_hpd_mutex);
hdmi_msm_state->panel_power_on = FALSE;
return 0;
@@ -4561,11 +4562,10 @@
} else
DEV_ERR("Init FAILED: failed to add fb device\n");
- DEV_INFO("HDMI HPD: ON\n");
-
rc = hdmi_msm_hpd_on(true);
if (rc)
goto error;
+ DEV_INFO("HDMI HPD: ON\n");
if (hdmi_msm_has_hdcp()) {
/* Don't Set Encryption in case of non HDCP builds */
diff --git a/drivers/video/msm/lvds.c b/drivers/video/msm/lvds.c
index 6323423..f5d8201 100644
--- a/drivers/video/msm/lvds.c
+++ b/drivers/video/msm/lvds.c
@@ -33,6 +33,9 @@
#include "msm_fb.h"
#include "mdp4.h"
+
+#define LVDS_PIXEL_MAP_PATTERN_2 2
+
static int lvds_probe(struct platform_device *pdev);
static int lvds_remove(struct platform_device *pdev);
@@ -65,14 +68,39 @@
usleep(1000);
/* LVDS PHY PLL configuration */
- MDP_OUTP(MDP_BASE + 0xc3004, 0x62);
- MDP_OUTP(MDP_BASE + 0xc3008, 0x30);
- MDP_OUTP(MDP_BASE + 0xc300c, 0xc4);
- MDP_OUTP(MDP_BASE + 0xc3014, 0x10);
- MDP_OUTP(MDP_BASE + 0xc3018, 0x05);
- MDP_OUTP(MDP_BASE + 0xc301c, 0x62);
- MDP_OUTP(MDP_BASE + 0xc3020, 0x41);
- MDP_OUTP(MDP_BASE + 0xc3024, 0x0d);
+ if (mfd->panel_info.clk_rate == 74250000) {
+ MDP_OUTP(MDP_BASE + 0xc3000, 0x08);
+ MDP_OUTP(MDP_BASE + 0xc3004, 0x4c);
+ MDP_OUTP(MDP_BASE + 0xc3008, 0x30);
+ MDP_OUTP(MDP_BASE + 0xc300c, 0xc3);
+ MDP_OUTP(MDP_BASE + 0xc3014, 0x10);
+ MDP_OUTP(MDP_BASE + 0xc3018, 0x04);
+ MDP_OUTP(MDP_BASE + 0xc301c, 0x62);
+ MDP_OUTP(MDP_BASE + 0xc3020, 0x41);
+ MDP_OUTP(MDP_BASE + 0xc3024, 0x0d);
+ MDP_OUTP(MDP_BASE + 0xc3028, 0x07);
+ MDP_OUTP(MDP_BASE + 0xc302c, 0x00);
+ MDP_OUTP(MDP_BASE + 0xc3030, 0x1c);
+ MDP_OUTP(MDP_BASE + 0xc3034, 0x01);
+ MDP_OUTP(MDP_BASE + 0xc3038, 0x00);
+ MDP_OUTP(MDP_BASE + 0xc3040, 0xC0);
+ MDP_OUTP(MDP_BASE + 0xc3044, 0x00);
+ MDP_OUTP(MDP_BASE + 0xc3048, 0x30);
+ MDP_OUTP(MDP_BASE + 0xc304c, 0x00);
+
+ MDP_OUTP(MDP_BASE + 0xc3000, 0x11);
+ MDP_OUTP(MDP_BASE + 0xc3064, 0x05);
+ MDP_OUTP(MDP_BASE + 0xc3050, 0x20);
+ } else {
+ MDP_OUTP(MDP_BASE + 0xc3004, 0x62);
+ MDP_OUTP(MDP_BASE + 0xc3008, 0x30);
+ MDP_OUTP(MDP_BASE + 0xc300c, 0xc4);
+ MDP_OUTP(MDP_BASE + 0xc3014, 0x10);
+ MDP_OUTP(MDP_BASE + 0xc3018, 0x05);
+ MDP_OUTP(MDP_BASE + 0xc301c, 0x62);
+ MDP_OUTP(MDP_BASE + 0xc3020, 0x41);
+ MDP_OUTP(MDP_BASE + 0xc3024, 0x0d);
+ }
MDP_OUTP(MDP_BASE + 0xc3000, 0x01);
/* Wait until LVDS PLL is locked and ready */
@@ -99,22 +127,42 @@
if (lvds_pdata &&
lvds_pdata->lvds_pixel_remap &&
lvds_pdata->lvds_pixel_remap()) {
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
- MDP_OUTP(MDP_BASE + 0xc2014, 0x05080001);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
- MDP_OUTP(MDP_BASE + 0xc2018, 0x00020304);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
- MDP_OUTP(MDP_BASE + 0xc201c, 0x1011090a);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
- MDP_OUTP(MDP_BASE + 0xc2020, 0x000b0c0d);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
- MDP_OUTP(MDP_BASE + 0xc2024, 0x191a1213);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
- MDP_OUTP(MDP_BASE + 0xc2028, 0x00141518);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_3_TO_0 */
- MDP_OUTP(MDP_BASE + 0xc202c, 0x171b0607);
- /* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_6_TO_4 */
- MDP_OUTP(MDP_BASE + 0xc2030, 0x000e0f16);
+ if (lvds_pdata->lvds_pixel_remap() ==
+ LVDS_PIXEL_MAP_PATTERN_2) {
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
+ MDP_OUTP(MDP_BASE + 0xc2014, 0x070A1B1B);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
+ MDP_OUTP(MDP_BASE + 0xc2018, 0x00040506);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
+ MDP_OUTP(MDP_BASE + 0xc201c, 0x12131B1B);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
+ MDP_OUTP(MDP_BASE + 0xc2020, 0x000B0C0D);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
+ MDP_OUTP(MDP_BASE + 0xc2024, 0x191A1B1B);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
+ MDP_OUTP(MDP_BASE + 0xc2028, 0x00141518);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_3_TO_0 */
+ MDP_OUTP(MDP_BASE + 0xc202c, 0x171B1B1B);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_6_TO_4 */
+ MDP_OUTP(MDP_BASE + 0xc2030, 0x000e0f16);
+ } else {
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
+ MDP_OUTP(MDP_BASE + 0xc2014, 0x05080001);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_6_TO_4 */
+ MDP_OUTP(MDP_BASE + 0xc2018, 0x00020304);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_3_TO_0 */
+ MDP_OUTP(MDP_BASE + 0xc201c, 0x1011090a);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D1_6_TO_4 */
+ MDP_OUTP(MDP_BASE + 0xc2020, 0x000b0c0d);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_3_TO_0 */
+ MDP_OUTP(MDP_BASE + 0xc2024, 0x191a1213);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D2_6_TO_4 */
+ MDP_OUTP(MDP_BASE + 0xc2028, 0x00141518);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_3_TO_0 */
+ MDP_OUTP(MDP_BASE + 0xc202c, 0x171b0607);
+ /* MDP_LCDC_LVDS_MUX_CTL_FOR_D3_6_TO_4 */
+ MDP_OUTP(MDP_BASE + 0xc2030, 0x000e0f16);
+ }
} else {
/* MDP_LCDC_LVDS_MUX_CTL_FOR_D0_3_TO_0 */
MDP_OUTP(MDP_BASE + 0xc2014, 0x03040508);
@@ -135,7 +183,7 @@
}
if (mfd->panel_info.lvds.channel_mode ==
LVDS_DUAL_CHANNEL_MODE) {
- lvds_intf = 0x0001ff80;
+ lvds_intf = 0x0003ff80;
lvds_phy_cfg0 = BIT(6) | BIT(7);
if (mfd->panel_info.lvds.channel_swap)
lvds_intf |= BIT(4);
@@ -159,7 +207,7 @@
if (mfd->panel_info.lvds.channel_mode ==
LVDS_DUAL_CHANNEL_MODE) {
- lvds_intf = 0x00017788;
+ lvds_intf = 0x00037788;
lvds_phy_cfg0 = BIT(6) | BIT(7);
if (mfd->panel_info.lvds.channel_swap)
lvds_intf |= BIT(4);
diff --git a/drivers/video/msm/lvds_frc_fhd.c b/drivers/video/msm/lvds_frc_fhd.c
new file mode 100644
index 0000000..7739588
--- /dev/null
+++ b/drivers/video/msm/lvds_frc_fhd.c
@@ -0,0 +1,201 @@
+/* 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 <mach/gpio.h>
+#include "msm_fb.h"
+
+static struct lvds_panel_platform_data *frc_pdata;
+static struct platform_device *frc_fbpdev;
+static int gpio_update; /* 268 */
+static int gpio_reset; /* 269 */
+static int gpio_pwr; /* 270 */
+
+static int lvds_frc_panel_on(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = gpio_request(gpio_pwr, "frc_pwr");
+ if (ret) {
+ pr_err("%s: gpio_pwr=%d, gpio_request failed\n",
+ __func__, gpio_pwr);
+ goto panel_on_exit;
+ }
+ ret = gpio_request(gpio_update, "frc_update");
+ if (ret) {
+ pr_err("%s: gpio_update=%d, gpio_request failed\n",
+ __func__, gpio_update);
+ goto panel_on_exit1;
+ }
+ ret = gpio_request(gpio_reset, "frc_reset");
+ if (ret) {
+ pr_err("%s: gpio_reset=%d, gpio_request failed\n",
+ __func__, gpio_reset);
+ goto panel_on_exit2;
+ }
+
+ gpio_direction_output(gpio_reset, 1);
+ gpio_direction_output(gpio_pwr, 0);
+ gpio_direction_output(gpio_update, 0);
+ usleep(1000);
+ gpio_direction_output(gpio_reset, 0);
+ usleep(1000);
+ gpio_direction_output(gpio_pwr, 1);
+ usleep(1000);
+ gpio_direction_output(gpio_update, 1);
+ usleep(1000);
+ gpio_direction_output(gpio_reset, 1);
+ usleep(1000);
+ gpio_free(gpio_reset);
+panel_on_exit2:
+ gpio_free(gpio_update);
+panel_on_exit1:
+ gpio_free(gpio_pwr);
+panel_on_exit:
+ return ret;
+}
+
+static int lvds_frc_panel_off(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = gpio_request(gpio_pwr, "frc_pwr");
+ if (ret) {
+ pr_err("%s: gpio_pwr=%d, gpio_request failed\n",
+ __func__, gpio_pwr);
+ goto panel_off_exit;
+ }
+ ret = gpio_request(gpio_update, "frc_update");
+ if (ret) {
+ pr_err("%s: gpio_update=%d, gpio_request failed\n",
+ __func__, gpio_update);
+ goto panel_off_exit1;
+ }
+ ret = gpio_request(gpio_reset, "frc_reset");
+ if (ret) {
+ pr_err("%s: gpio_reset=%d, gpio_request failed\n",
+ __func__, gpio_reset);
+ goto panel_off_exit2;
+ }
+ gpio_direction_output(gpio_reset, 0);
+ usleep(1000);
+ gpio_direction_output(gpio_update, 0);
+ usleep(1000);
+ gpio_direction_output(gpio_pwr, 0);
+ usleep(1000);
+ gpio_free(gpio_reset);
+panel_off_exit2:
+ gpio_free(gpio_update);
+panel_off_exit1:
+ gpio_free(gpio_pwr);
+panel_off_exit:
+ return ret;
+}
+
+static int __devinit lvds_frc_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+
+ if (pdev->id == 0) {
+ frc_pdata = pdev->dev.platform_data;
+ if (frc_pdata != NULL) {
+ gpio_update = frc_pdata->gpio[0];
+ gpio_reset = frc_pdata->gpio[1];
+ gpio_pwr = frc_pdata->gpio[2];
+ pr_info("%s: power=%d update=%d reset=%d\n",
+ __func__, gpio_pwr, gpio_update, gpio_reset);
+ }
+ return 0;
+ }
+
+ frc_fbpdev = msm_fb_add_device(pdev);
+ if (!frc_fbpdev) {
+ dev_err(&pdev->dev, "failed to add msm_fb device\n");
+ rc = -ENODEV;
+ goto probe_exit;
+ }
+
+probe_exit:
+ return rc;
+}
+
+static struct platform_driver this_driver = {
+ .probe = lvds_frc_probe,
+ .driver = {
+ .name = "lvds_frc_fhd",
+ },
+};
+
+static struct msm_fb_panel_data lvds_frc_panel_data = {
+ .on = lvds_frc_panel_on,
+ .off = lvds_frc_panel_off,
+};
+
+static struct platform_device this_device = {
+ .name = "lvds_frc_fhd",
+ .id = 1,
+ .dev = {
+ .platform_data = &lvds_frc_panel_data,
+ }
+};
+
+static int __init lvds_frc_fhd_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+ if (msm_fb_detect_client("lvds_frc_fhd"))
+ return 0;
+
+ ret = platform_driver_register(&this_driver);
+ if (ret)
+ return ret;
+
+ pinfo = &lvds_frc_panel_data.panel_info;
+ pinfo->xres = 1920;
+ pinfo->yres = 1080;
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+ pinfo->type = LVDS_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 24;
+ pinfo->fb_num = 2;
+ pinfo->clk_rate = 74250000;
+ pinfo->bl_max = 255;
+ pinfo->bl_min = 1;
+
+ /*
+ * use hdmi 1080p60 setting, for dual channel mode,
+ * horizontal length is half.
+ */
+ pinfo->lcdc.h_back_porch = 148/2;
+ pinfo->lcdc.h_front_porch = 88/2;
+ pinfo->lcdc.h_pulse_width = 44/2;
+ pinfo->lcdc.v_back_porch = 36;
+ pinfo->lcdc.v_front_porch = 4;
+ pinfo->lcdc.v_pulse_width = 5;
+ pinfo->lcdc.underflow_clr = 0xff;
+ pinfo->lcdc.hsync_skew = 0;
+ pinfo->lvds.channel_mode = LVDS_DUAL_CHANNEL_MODE;
+ pinfo->lcdc.is_sync_active_high = TRUE;
+
+ /* Set border color, padding only for reducing active display region */
+ pinfo->lcdc.border_clr = 0x0;
+ pinfo->lcdc.xres_pad = 0;
+ pinfo->lcdc.yres_pad = 0;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+
+ return ret;
+}
+
+module_init(lvds_frc_fhd_init);
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index ca5d2c6..e76d8b2 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -1068,21 +1068,31 @@
goto error;
}
- switch (mgmt->block) {
- case MDP_BLOCK_DMA_P:
- case MDP_BLOCK_DMA_S:
- ret = _mdp_histogram_read_dma_data(mgmt);
- break;
- case MDP_BLOCK_VG_1:
- case MDP_BLOCK_VG_2:
- ret = _mdp_histogram_read_vg_data(mgmt);
- break;
- default:
- pr_err("%s, invalid MDP block = %d\n", __func__, mgmt->block);
+ if (mgmt->hist == NULL) {
+ if ((mgmt->mdp_is_hist_init == TRUE) &&
+ ((!completion_done(&mgmt->mdp_hist_comp)) &&
+ waitqueue_active(&mgmt->mdp_hist_comp.wait)))
+ pr_err("mgmt->hist invalid NULL\n");
ret = -EINVAL;
- goto error;
}
+ if (!ret) {
+ switch (mgmt->block) {
+ case MDP_BLOCK_DMA_P:
+ case MDP_BLOCK_DMA_S:
+ ret = _mdp_histogram_read_dma_data(mgmt);
+ break;
+ case MDP_BLOCK_VG_1:
+ case MDP_BLOCK_VG_2:
+ ret = _mdp_histogram_read_vg_data(mgmt);
+ break;
+ default:
+ pr_err("%s, invalid MDP block = %d\n", __func__,
+ mgmt->block);
+ ret = -EINVAL;
+ goto error;
+ }
+ }
/*
* if read was triggered by an underrun or failed copying,
* don't wake up readers
@@ -1573,16 +1583,7 @@
__mdp_histogram_kickoff(mgmt);
if (isr & INTR_HIST_DONE) {
- if ((waitqueue_active(&mgmt->mdp_hist_comp.wait))
- && (mgmt->hist != NULL)) {
- if (!queue_work(mdp_hist_wq,
- &mgmt->mdp_histogram_worker)) {
- pr_err("%s %d- can't queue hist_read\n",
- __func__, mgmt->block);
- }
- } else {
- __mdp_histogram_reset(mgmt);
- }
+ queue_work(mdp_hist_wq, &mgmt->mdp_histogram_worker);
}
}
diff --git a/drivers/video/msm/mdp4_dtv.c b/drivers/video/msm/mdp4_dtv.c
index f0353bd..bd0ce2f 100644
--- a/drivers/video/msm/mdp4_dtv.c
+++ b/drivers/video/msm/mdp4_dtv.c
@@ -137,6 +137,12 @@
clk_prepare_enable(ebi1_clk);
}
#endif
+
+ if (dtv_pdata && dtv_pdata->lcdc_power_save)
+ dtv_pdata->lcdc_power_save(1);
+ if (dtv_pdata && dtv_pdata->lcdc_gpio_config)
+ ret = dtv_pdata->lcdc_gpio_config(1);
+
mfd = platform_get_drvdata(pdev);
ret = clk_set_rate(tv_src_clk, mfd->fbi->var.pixclock);
@@ -158,11 +164,6 @@
if (mdp_tv_clk)
clk_prepare_enable(mdp_tv_clk);
- if (dtv_pdata && dtv_pdata->lcdc_power_save)
- dtv_pdata->lcdc_power_save(1);
- if (dtv_pdata && dtv_pdata->lcdc_gpio_config)
- ret = dtv_pdata->lcdc_gpio_config(1);
-
ret = panel_next_on(pdev);
return ret;
}
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 18d2107..8410592 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -181,7 +181,12 @@
lcdc_bpp = mfd->panel_info.bpp;
hsync_period =
- hsync_pulse_width + h_back_porch + lcdc_width + h_front_porch;
+ hsync_pulse_width + h_back_porch + h_front_porch;
+ if ((mfd->panel_info.type == LVDS_PANEL) &&
+ (mfd->panel_info.lvds.channel_mode == LVDS_DUAL_CHANNEL_MODE))
+ hsync_period += lcdc_width / 2;
+ else
+ hsync_period += lcdc_width;
hsync_ctrl = (hsync_period << 16) | hsync_pulse_width;
hsync_start_x = hsync_pulse_width + h_back_porch;
hsync_end_x = hsync_period - h_front_porch - 1;
@@ -216,8 +221,13 @@
#ifdef CONFIG_FB_MSM_MDP40
- hsync_polarity = 1;
- vsync_polarity = 1;
+ if (mfd->panel_info.lcdc.is_sync_active_high) {
+ hsync_polarity = 0;
+ vsync_polarity = 0;
+ } else {
+ hsync_polarity = 1;
+ vsync_polarity = 1;
+ }
lcdc_underflow_clr |= 0x80000000; /* enable recovery */
#else
hsync_polarity = 0;
diff --git a/drivers/video/msm/mipi_NT35510.c b/drivers/video/msm/mipi_NT35510.c
index 964df4e..e605aed 100644
--- a/drivers/video/msm/mipi_NT35510.c
+++ b/drivers/video/msm/mipi_NT35510.c
@@ -19,6 +19,8 @@
static struct dsi_buf nt35510_tx_buf;
static struct dsi_buf nt35510_rx_buf;
+static int mipi_nt35510_bl_ctrl;
+
#define NT35510_SLEEP_OFF_DELAY 150
#define NT35510_DISPLAY_ON_DELAY 150
@@ -174,6 +176,9 @@
static char cmd19[3] = {
0xB1, 0xEC, 0x00,
};
+static char cmd19_rotate[3] = {
+ 0xB1, 0xEC, 0x06,
+};
static char cmd20[4] = {
0xBC, 0x05, 0x05, 0x05,
};
@@ -246,6 +251,11 @@
{DTYPE_DCS_WRITE, 1, 0, 0, 10, sizeof(write_ram), write_ram},
};
+static struct dsi_cmd_desc nt35510_cmd_display_on_cmds_rotate[] = {
+ {DTYPE_DCS_LWRITE, 1, 0, 0, 50,
+ sizeof(cmd19_rotate), cmd19_rotate},
+};
+
static char video0[6] = {
0xF0, 0x55, 0xAA, 0x52,
0x08, 0x01,
@@ -489,6 +499,12 @@
mipi_dsi_cmds_tx(mfd, &nt35510_tx_buf,
nt35510_cmd_display_on_cmds,
ARRAY_SIZE(nt35510_cmd_display_on_cmds));
+
+ if (rotate) {
+ mipi_dsi_cmds_tx(mfd, &nt35510_tx_buf,
+ nt35510_cmd_display_on_cmds_rotate,
+ ARRAY_SIZE(nt35510_cmd_display_on_cmds_rotate));
+ }
}
return 0;
@@ -514,8 +530,63 @@
return 0;
}
+static ssize_t mipi_nt35510_wta_bl_ctrl(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ ssize_t ret = strnlen(buf, PAGE_SIZE);
+ int err;
+
+ err = kstrtoint(buf, 0, &mipi_nt35510_bl_ctrl);
+ if (err)
+ return ret;
+
+ pr_info("%s: bl ctrl set to %d\n", __func__, mipi_nt35510_bl_ctrl);
+
+ return ret;
+}
+
+static DEVICE_ATTR(bl_ctrl, S_IWUSR, NULL, mipi_nt35510_wta_bl_ctrl);
+
+static struct attribute *mipi_nt35510_fs_attrs[] = {
+ &dev_attr_bl_ctrl.attr,
+ NULL,
+};
+
+static struct attribute_group mipi_nt35510_fs_attr_group = {
+ .attrs = mipi_nt35510_fs_attrs,
+};
+
+static int mipi_nt35510_create_sysfs(struct platform_device *pdev)
+{
+ int rc;
+ struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+
+ if (!mfd) {
+ pr_err("%s: mfd not found\n", __func__);
+ return -ENODEV;
+ }
+ if (!mfd->fbi) {
+ pr_err("%s: mfd->fbi not found\n", __func__);
+ return -ENODEV;
+ }
+ if (!mfd->fbi->dev) {
+ pr_err("%s: mfd->fbi->dev not found\n", __func__);
+ return -ENODEV;
+ }
+ rc = sysfs_create_group(&mfd->fbi->dev->kobj,
+ &mipi_nt35510_fs_attr_group);
+ if (rc) {
+ pr_err("%s: sysfs group creation failed, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ return 0;
+}
+
static int __devinit mipi_nt35510_lcd_probe(struct platform_device *pdev)
{
+ struct platform_device *pthisdev = NULL;
pr_debug("%s\n", __func__);
if (pdev->id == 0) {
@@ -525,7 +596,8 @@
return 0;
}
- msm_fb_add_device(pdev);
+ pthisdev = msm_fb_add_device(pdev);
+ mipi_nt35510_create_sysfs(pthisdev);
return 0;
}
@@ -537,6 +609,8 @@
},
};
+static int old_bl_level;
+
static void mipi_nt35510_set_backlight(struct msm_fb_data_type *mfd)
{
int bl_level;
@@ -544,11 +618,33 @@
bl_level = mfd->bl_level;
if (mipi_nt35510_pdata->bl_lock) {
- spin_lock_irqsave(&mipi_nt35510_pdata->bl_spinlock, flags);
- mipi_nt35510_pdata->pmic_backlight(bl_level);
- spin_unlock_irqrestore(&mipi_nt35510_pdata->bl_spinlock, flags);
- } else
- mipi_nt35510_pdata->pmic_backlight(bl_level);
+ if (!mipi_nt35510_bl_ctrl) {
+ /* Level received is of range 1 to bl_max,
+ We need to convert the levels to 1
+ to 31 */
+ bl_level = (2 * bl_level * 31 + mfd->panel_info.bl_max)
+ /(2 * mfd->panel_info.bl_max);
+ if (bl_level == old_bl_level)
+ return;
+
+ if (bl_level == 0)
+ mipi_nt35510_pdata->backlight(0, 1);
+
+ if (old_bl_level == 0)
+ mipi_nt35510_pdata->backlight(50, 1);
+
+ spin_lock_irqsave(&mipi_nt35510_pdata->bl_spinlock,
+ flags);
+ mipi_nt35510_pdata->backlight(bl_level, 0);
+ spin_unlock_irqrestore(&mipi_nt35510_pdata->bl_spinlock,
+ flags);
+ old_bl_level = bl_level;
+ } else {
+ mipi_nt35510_pdata->backlight(bl_level, 1);
+ }
+ } else {
+ mipi_nt35510_pdata->backlight(bl_level, mipi_nt35510_bl_ctrl);
+ }
}
static struct msm_fb_panel_data nt35510_panel_data = {
diff --git a/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c b/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
index f052e93..1524ce6 100644
--- a/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
+++ b/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
@@ -56,7 +56,7 @@
pinfo.lcdc.border_clr = 0; /* blk */
pinfo.lcdc.underflow_clr = 0xff; /* blue */
pinfo.lcdc.hsync_skew = 0;
- pinfo.bl_max = 31;
+ pinfo.bl_max = 255;
pinfo.bl_min = 1;
pinfo.fb_num = 2;
diff --git a/drivers/video/msm/mipi_NT35510_video_wvga_pt.c b/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
index 4e97d99..8a364ba 100644
--- a/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
+++ b/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
@@ -59,7 +59,7 @@
delayed from VSYNC active edge */
pinfo.lcdc.hsync_skew = 0;
pinfo.clk_rate = 499000000;
- pinfo.bl_max = 31;
+ pinfo.bl_max = 255;
pinfo.bl_min = 1;
pinfo.fb_num = 2;
diff --git a/drivers/video/msm/mipi_renesas_cmd_fwvga_pt.c b/drivers/video/msm/mipi_renesas_cmd_fwvga_pt.c
index 7f5ac70..2ebfad4 100644
--- a/drivers/video/msm/mipi_renesas_cmd_fwvga_pt.c
+++ b/drivers/video/msm/mipi_renesas_cmd_fwvga_pt.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
@@ -93,7 +93,7 @@
pinfo.lcdc.border_clr = 0; /* blk */
pinfo.lcdc.underflow_clr = 0xff; /* blue */
pinfo.lcdc.hsync_skew = 0;
- pinfo.bl_max = 100;
+ pinfo.bl_max = 255;
pinfo.bl_min = 1;
pinfo.fb_num = 2;
diff --git a/drivers/video/msm/mipi_renesas_video_fwvga_pt.c b/drivers/video/msm/mipi_renesas_video_fwvga_pt.c
index e826773..144d9ff 100644
--- a/drivers/video/msm/mipi_renesas_video_fwvga_pt.c
+++ b/drivers/video/msm/mipi_renesas_video_fwvga_pt.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
@@ -105,7 +105,7 @@
pinfo.lcdc.border_clr = 0; /* blk */
pinfo.lcdc.underflow_clr = 0xff; /* blue */
pinfo.lcdc.hsync_skew = 0;
- pinfo.bl_max = 100;
+ pinfo.bl_max = 255;
pinfo.bl_min = 1;
pinfo.fb_num = 2;
diff --git a/drivers/video/msm/mipi_truly_tft540960_1_e.c b/drivers/video/msm/mipi_truly_tft540960_1_e.c
index e465d46..98b24b1 100644
--- a/drivers/video/msm/mipi_truly_tft540960_1_e.c
+++ b/drivers/video/msm/mipi_truly_tft540960_1_e.c
@@ -19,6 +19,8 @@
static struct dsi_buf truly_tx_buf;
static struct dsi_buf truly_rx_buf;
+static int mipi_truly_bl_ctrl;
+
#define TRULY_CMD_DELAY 0
#define MIPI_SETTING_DELAY 10
#define TRULY_SLEEP_OFF_DELAY 150
@@ -720,8 +722,64 @@
return 0;
}
+static ssize_t mipi_truly_wta_bl_ctrl(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ ssize_t ret = strnlen(buf, PAGE_SIZE);
+ int err;
+
+ err = kstrtoint(buf, 0, &mipi_truly_bl_ctrl);
+ if (err)
+ return ret;
+
+ pr_info("%s: bl ctrl set to %d\n", __func__, mipi_truly_bl_ctrl);
+
+ return ret;
+}
+
+static DEVICE_ATTR(bl_ctrl, S_IWUSR, NULL, mipi_truly_wta_bl_ctrl);
+
+static struct attribute *mipi_truly_fs_attrs[] = {
+ &dev_attr_bl_ctrl.attr,
+ NULL,
+};
+
+static struct attribute_group mipi_truly_fs_attr_group = {
+ .attrs = mipi_truly_fs_attrs,
+};
+
+static int mipi_truly_create_sysfs(struct platform_device *pdev)
+{
+ int rc;
+ struct msm_fb_data_type *mfd = platform_get_drvdata(pdev);
+
+ if (!mfd) {
+ pr_err("%s: mfd not found\n", __func__);
+ return -ENODEV;
+ }
+ if (!mfd->fbi) {
+ pr_err("%s: mfd->fbi not found\n", __func__);
+ return -ENODEV;
+ }
+ if (!mfd->fbi->dev) {
+ pr_err("%s: mfd->fbi->dev not found\n", __func__);
+ return -ENODEV;
+ }
+ rc = sysfs_create_group(&mfd->fbi->dev->kobj,
+ &mipi_truly_fs_attr_group);
+ if (rc) {
+ pr_err("%s: sysfs group creation failed, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ return 0;
+}
+
+
static int __devinit mipi_truly_lcd_probe(struct platform_device *pdev)
{
+ struct platform_device *pthisdev = NULL;
int rc = 0;
if (pdev->id == 0) {
@@ -731,7 +789,8 @@
return rc;
}
- msm_fb_add_device(pdev);
+ pthisdev = msm_fb_add_device(pdev);
+ mipi_truly_create_sysfs(pthisdev);
return rc;
}
@@ -743,6 +802,8 @@
},
};
+static int old_bl_level;
+
static void mipi_truly_set_backlight(struct msm_fb_data_type *mfd)
{
int bl_level;
@@ -750,11 +811,33 @@
bl_level = mfd->bl_level;
if (mipi_truly_pdata->bl_lock) {
- spin_lock_irqsave(&mipi_truly_pdata->bl_spinlock, flags);
- mipi_truly_pdata->pmic_backlight(bl_level);
- spin_unlock_irqrestore(&mipi_truly_pdata->bl_spinlock, flags);
- } else
- mipi_truly_pdata->pmic_backlight(bl_level);
+ if (!mipi_truly_bl_ctrl) {
+ /* Level received is of range 1 to bl_max,
+ We need to convert the levels to 1
+ to 31 */
+ bl_level = (2 * bl_level * 31 + mfd->panel_info.bl_max)
+ /(2 * mfd->panel_info.bl_max);
+ if (bl_level == old_bl_level)
+ return;
+
+ if (bl_level == 0)
+ mipi_truly_pdata->backlight(0, 1);
+
+ if (old_bl_level == 0)
+ mipi_truly_pdata->backlight(50, 1);
+
+ spin_lock_irqsave(&mipi_truly_pdata->bl_spinlock,
+ flags);
+ mipi_truly_pdata->backlight(bl_level, 0);
+ spin_unlock_irqrestore(&mipi_truly_pdata->bl_spinlock,
+ flags);
+ old_bl_level = bl_level;
+ } else {
+ mipi_truly_pdata->backlight(bl_level, 1);
+ }
+ } else {
+ mipi_truly_pdata->backlight(bl_level, mipi_truly_bl_ctrl);
+ }
}
static struct msm_fb_panel_data truly_panel_data = {
diff --git a/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c b/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c
index de98177..3423241 100644
--- a/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c
+++ b/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c
@@ -56,7 +56,7 @@
pinfo.lcdc.border_clr = 0; /* blk */
pinfo.lcdc.underflow_clr = 0xff; /* blue */
pinfo.lcdc.hsync_skew = 0;
- pinfo.bl_max = 31;
+ pinfo.bl_max = 255;
pinfo.bl_min = 1;
pinfo.fb_num = 2;
diff --git a/drivers/video/msm/mipi_truly_tft540960_1_e_video_qhd_pt.c b/drivers/video/msm/mipi_truly_tft540960_1_e_video_qhd_pt.c
index ea2ff47..3c0c0b7 100644
--- a/drivers/video/msm/mipi_truly_tft540960_1_e_video_qhd_pt.c
+++ b/drivers/video/msm/mipi_truly_tft540960_1_e_video_qhd_pt.c
@@ -59,7 +59,7 @@
pinfo.lcdc.hsync_skew = 0;
pinfo.clk_rate = 699000000;
pinfo.lcd.refx100 = 6000; /* FB driver calc FPS based on this value */
- pinfo.bl_max = 31;
+ pinfo.bl_max = 255;
pinfo.bl_min = 1;
pinfo.fb_num = 2;
diff --git a/drivers/video/msm/msm_dss_io_8960.c b/drivers/video/msm/msm_dss_io_8960.c
index 70c8afc..682a45a 100644
--- a/drivers/video/msm/msm_dss_io_8960.c
+++ b/drivers/video/msm/msm_dss_io_8960.c
@@ -747,7 +747,6 @@
void hdmi_msm_reset_core(void)
{
- hdmi_msm_set_mode(FALSE);
hdmi_msm_clk(0);
udelay(5);
hdmi_msm_clk(1);
diff --git a/drivers/video/msm/msm_dss_io_8x60.c b/drivers/video/msm/msm_dss_io_8x60.c
index a1897e3..bb6f710 100644
--- a/drivers/video/msm/msm_dss_io_8x60.c
+++ b/drivers/video/msm/msm_dss_io_8x60.c
@@ -548,7 +548,6 @@
void hdmi_msm_reset_core(void)
{
- hdmi_msm_set_mode(FALSE);
hdmi_msm_clk(0);
udelay(5);
hdmi_msm_clk(1);
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 3ed305b..81a6e50 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -575,9 +575,6 @@
mfd->op_enable);
if (ret)
MSM_FB_INFO("msm_fb_resume: can't turn on display!\n");
- } else {
- if (pdata->power_ctrl)
- pdata->power_ctrl(TRUE);
}
return ret;
@@ -633,29 +630,49 @@
static int msm_fb_ext_suspend(struct device *dev)
{
struct msm_fb_data_type *mfd = dev_get_drvdata(dev);
+ struct msm_fb_panel_data *pdata = NULL;
int ret = 0;
if ((!mfd) || (mfd->key != MFD_KEY))
return 0;
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
if (mfd->panel_info.type == HDMI_PANEL ||
- mfd->panel_info.type == DTV_PANEL)
+ mfd->panel_info.type == DTV_PANEL) {
ret = msm_fb_suspend_sub(mfd);
+ /* Turn off the HPD circuitry */
+ if (pdata->power_ctrl) {
+ MSM_FB_INFO("%s: Turning off HPD circuitry\n",
+ __func__);
+ pdata->power_ctrl(FALSE);
+ }
+ }
+
return ret;
}
static int msm_fb_ext_resume(struct device *dev)
{
struct msm_fb_data_type *mfd = dev_get_drvdata(dev);
+ struct msm_fb_panel_data *pdata = NULL;
int ret = 0;
if ((!mfd) || (mfd->key != MFD_KEY))
return 0;
+ pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
if (mfd->panel_info.type == HDMI_PANEL ||
- mfd->panel_info.type == DTV_PANEL)
+ mfd->panel_info.type == DTV_PANEL) {
+ /* Turn on the HPD circuitry */
+ if (pdata->power_ctrl) {
+ pdata->power_ctrl(TRUE);
+ MSM_FB_INFO("%s: Turning on HPD circuitry\n",
+ __func__);
+ }
+
ret = msm_fb_resume_sub(mfd);
+ }
return ret;
}
@@ -813,9 +830,6 @@
mfd->panel_power_on = curr_pwr_state;
mfd->op_enable = TRUE;
- } else {
- if (pdata->power_ctrl)
- pdata->power_ctrl(FALSE);
}
break;
}
@@ -1316,7 +1330,7 @@
GEN_POOL,
fbi->fix.smem_len,
SZ_4K,
- 1,
+ 0,
&(mfd->display_iova));
msm_iommu_map_contig_buffer(fbi->fix.smem_start,
@@ -1324,7 +1338,7 @@
GEN_POOL,
fbi->fix.smem_len,
SZ_4K,
- 1,
+ 0,
&(mfd->rotator_iova));
if (!bf_supported || mfd->index == 0)
diff --git a/drivers/video/msm/msm_fb_panel.h b/drivers/video/msm/msm_fb_panel.h
index 8ccc21c..a2c3db1 100644
--- a/drivers/video/msm/msm_fb_panel.h
+++ b/drivers/video/msm/msm_fb_panel.h
@@ -82,6 +82,7 @@
uint32 xres_pad;
/* Pad height */
uint32 yres_pad;
+ boolean is_sync_active_high;
};
struct mddi_panel_info {
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index ec9f187..4358a92 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -977,7 +977,7 @@
struct ubifs_budget_req ino_req = { .dirtied_ino = 1,
.dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) };
struct timespec time;
- unsigned int saved_nlink;
+ unsigned int saved_nlink = 0;
/*
* Budget request settings: deletion direntry, new direntry, removing
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 1e1e09f..28c0917 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -436,7 +436,6 @@
header-y += msm_audio_sbc.h
header-y += msm_ipc.h
header-y += msm_charm.h
-header-y += tzcom.h
header-y += qseecom.h
header-y += qcedev.h
header-y += idle_stats_device.h
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 612b133..2657ec3 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -90,6 +90,32 @@
};
+enum {
+ TAIKO_IRQ_SLIMBUS = 0,
+ TAIKO_IRQ_MBHC_REMOVAL,
+ TAIKO_IRQ_MBHC_SHORT_TERM,
+ TAIKO_IRQ_MBHC_PRESS,
+ TAIKO_IRQ_MBHC_RELEASE,
+ TAIKO_IRQ_MBHC_POTENTIAL,
+ TAIKO_IRQ_MBHC_INSERTION,
+ TAIKO_IRQ_BG_PRECHARGE,
+ TAIKO_IRQ_PA1_STARTUP,
+ TAIKO_IRQ_PA2_STARTUP,
+ TAIKO_IRQ_PA3_STARTUP,
+ TAIKO_IRQ_PA4_STARTUP,
+ TAIKO_IRQ_PA5_STARTUP,
+ TAIKO_IRQ_MICBIAS1_PRECHARGE,
+ TAIKO_IRQ_MICBIAS2_PRECHARGE,
+ TAIKO_IRQ_MICBIAS3_PRECHARGE,
+ TAIKO_IRQ_HPH_PA_OCPL_FAULT,
+ TAIKO_IRQ_HPH_PA_OCPR_FAULT,
+ TAIKO_IRQ_EAR_PA_OCPL_FAULT,
+ TAIKO_IRQ_HPH_L_PA_STARTUP,
+ TAIKO_IRQ_HPH_R_PA_STARTUP,
+ TAIKO_IRQ_EAR_PA_STARTUP,
+ TAIKO_NUM_IRQS,
+};
+
enum wcd9xxx_pm_state {
WCD9XXX_PM_SLEEPABLE,
WCD9XXX_PM_AWAKE,
diff --git a/include/linux/mfd/wcd9xxx/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h
index db76294..ba71293 100644
--- a/include/linux/mfd/wcd9xxx/pdata.h
+++ b/include/linux/mfd/wcd9xxx/pdata.h
@@ -34,6 +34,16 @@
#define TABLA_CFILT2_SEL 0x1
#define TABLA_CFILT3_SEL 0x2
+#define TAIKO_CFILT1_SEL 0x0
+#define TAIKO_CFILT2_SEL 0x1
+#define TAIKO_CFILT3_SEL 0x2
+
+#define TAIKO_LDOH_1P95_V 0x0
+#define TAIKO_LDOH_2P35_V 0x1
+#define TAIKO_LDOH_2P75_V 0x2
+#define TAIKO_LDOH_2P85_V 0x3
+
+
#define MAX_AMIC_CHANNEL 7
#define TABLA_OCP_300_MA 0x0
diff --git a/include/linux/mfd/wcd9xxx/wcd9320_registers.h b/include/linux/mfd/wcd9xxx/wcd9320_registers.h
new file mode 100644
index 0000000..5725e6e
--- /dev/null
+++ b/include/linux/mfd/wcd9xxx/wcd9320_registers.h
@@ -0,0 +1,1354 @@
+/* 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 WCD9320_REGISTERS_H
+#define WCD9320_REGISTERS_H
+
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+
+#define TAIKO_A_CHIP_CTL WCD9XXX_A_CHIP_CTL
+#define TAIKO_A_CHIP_CTL__POR WCD9XXX_A_CHIP_CTL__POR
+#define TAIKO_A_CHIP_STATUS WCD9XXX_A_CHIP_STATUS
+#define TAIKO_A_CHIP_STATUS__POR WCD9XXX_A_CHIP_STATUS__POR
+#define TAIKO_A_CHIP_ID_BYTE_0 WCD9XXX_A_CHIP_ID_BYTE_0
+#define TAIKO_A_CHIP_ID_BYTE_0__POR WCD9XXX_A_CHIP_ID_BYTE_0__POR
+#define TAIKO_A_CHIP_ID_BYTE_1 WCD9XXX_A_CHIP_ID_BYTE_1
+#define TAIKO_A_CHIP_ID_BYTE_1__POR WCD9XXX_A_CHIP_ID_BYTE_1__POR
+#define TAIKO_A_CHIP_ID_BYTE_2 WCD9XXX_A_CHIP_ID_BYTE_2
+#define TAIKO_A_CHIP_ID_BYTE_2__POR WCD9XXX_A_CHIP_ID_BYTE_2__POR
+#define TAIKO_A_CHIP_ID_BYTE_3 WCD9XXX_A_CHIP_ID_BYTE_3
+#define TAIKO_A_CHIP_ID_BYTE_3__POR WCD9XXX_A_CHIP_ID_BYTE_3__POR
+#define TAIKO_A_CHIP_VERSION WCD9XXX_A_CHIP_VERSION
+#define TAIKO_A_CHIP_VERSION__POR WCD9XXX_A_CHIP_VERSION__POR
+#define TAIKO_A_SB_VERSION WCD9XXX_A_SB_VERSION
+#define TAIKO_A_SB_VERSION__POR WCD9XXX_A_SB_VERSION__POR
+#define TAIKO_A_SLAVE_ID_1 WCD9XXX_A_SLAVE_ID_1
+#define TAIKO_A_SLAVE_ID_1__POR WCD9XXX_A_SLAVE_ID_1__POR
+#define TAIKO_A_SLAVE_ID_2 WCD9XXX_A_SLAVE_ID_2
+#define TAIKO_A_SLAVE_ID_2__POR WCD9XXX_A_SLAVE_ID_2__POR
+#define TAIKO_A_SLAVE_ID_3 WCD9XXX_A_SLAVE_ID_3
+#define TAIKO_A_SLAVE_ID_3__POR WCD9XXX_A_SLAVE_ID_3__POR
+#define TAIKO_A_PIN_CTL_OE0 (0x010)
+#define TAIKO_A_PIN_CTL_OE0__POR (0x00)
+#define TAIKO_A_PIN_CTL_OE1 (0x011)
+#define TAIKO_A_PIN_CTL_OE1__POR (0x00)
+#define TAIKO_A_PIN_CTL_DATA0 (0x012)
+#define TAIKO_A_PIN_CTL_DATA0__POR (0x00)
+#define TAIKO_A_PIN_CTL_DATA1 (0x013)
+#define TAIKO_A_PIN_CTL_DATA1__POR (0x00)
+#define TAIKO_A_HDRIVE_GENERIC (0x018)
+#define TAIKO_A_HDRIVE_GENERIC__POR (0x00)
+#define TAIKO_A_HDRIVE_OVERRIDE (0x019)
+#define TAIKO_A_HDRIVE_OVERRIDE__POR (0x08)
+#define TAIKO_A_ANA_CSR_WAIT_STATE (0x020)
+#define TAIKO_A_ANA_CSR_WAIT_STATE__POR (0x44)
+#define TAIKO_A_PROCESS_MONITOR_CTL0 (0x040)
+#define TAIKO_A_PROCESS_MONITOR_CTL0__POR (0x80)
+#define TAIKO_A_PROCESS_MONITOR_CTL1 (0x041)
+#define TAIKO_A_PROCESS_MONITOR_CTL1__POR (0x00)
+#define TAIKO_A_PROCESS_MONITOR_CTL2 (0x042)
+#define TAIKO_A_PROCESS_MONITOR_CTL2__POR (0x00)
+#define TAIKO_A_PROCESS_MONITOR_CTL3 (0x043)
+#define TAIKO_A_PROCESS_MONITOR_CTL3__POR (0x01)
+#define TAIKO_A_QFUSE_CTL (0x048)
+#define TAIKO_A_QFUSE_CTL__POR (0x00)
+#define TAIKO_A_QFUSE_STATUS (0x049)
+#define TAIKO_A_QFUSE_STATUS__POR (0x00)
+#define TAIKO_A_QFUSE_DATA_OUT0 (0x04A)
+#define TAIKO_A_QFUSE_DATA_OUT0__POR (0x00)
+#define TAIKO_A_QFUSE_DATA_OUT1 (0x04B)
+#define TAIKO_A_QFUSE_DATA_OUT1__POR (0x00)
+#define TAIKO_A_QFUSE_DATA_OUT2 (0x04C)
+#define TAIKO_A_QFUSE_DATA_OUT2__POR (0x00)
+#define TAIKO_A_QFUSE_DATA_OUT3 (0x04D)
+#define TAIKO_A_QFUSE_DATA_OUT3__POR (0x00)
+#define TAIKO_A_QFUSE_DATA_OUT4 (0x04E)
+#define TAIKO_A_QFUSE_DATA_OUT4__POR (0x00)
+#define TAIKO_A_QFUSE_DATA_OUT5 (0x04F)
+#define TAIKO_A_QFUSE_DATA_OUT5__POR (0x00)
+#define TAIKO_A_QFUSE_DATA_OUT6 (0x050)
+#define TAIKO_A_QFUSE_DATA_OUT6__POR (0x00)
+#define TAIKO_A_QFUSE_DATA_OUT7 (0x051)
+#define TAIKO_A_QFUSE_DATA_OUT7__POR (0x00)
+#define TAIKO_A_CDC_CTL WCD9XXX_A_CDC_CTL
+#define TAIKO_A_CDC_CTL__POR WCD9XXX_A_CDC_CTL__POR
+#define TAIKO_A_LEAKAGE_CTL WCD9XXX_A_LEAKAGE_CTL
+#define TAIKO_A_LEAKAGE_CTL__POR WCD9XXX_A_LEAKAGE_CTL__POR
+#define TAIKO_A_INTR_MODE (0x090)
+#define TAIKO_A_INTR_MODE__POR (0x00)
+#define TAIKO_A_INTR_MASK0 (0x094)
+#define TAIKO_A_INTR_MASK0__POR (0xFF)
+#define TAIKO_A_INTR_MASK1 (0x095)
+#define TAIKO_A_INTR_MASK1__POR (0xFF)
+#define TAIKO_A_INTR_MASK2 (0x096)
+#define TAIKO_A_INTR_MASK2__POR (0x3F)
+#define TAIKO_A_INTR_MASK3 (0x097)
+#define TAIKO_A_INTR_MASK3__POR (0x3F)
+#define TAIKO_A_INTR_STATUS0 (0x098)
+#define TAIKO_A_INTR_STATUS0__POR (0x00)
+#define TAIKO_A_INTR_STATUS1 (0x099)
+#define TAIKO_A_INTR_STATUS1__POR (0x00)
+#define TAIKO_A_INTR_STATUS2 (0x09A)
+#define TAIKO_A_INTR_STATUS2__POR (0x00)
+#define TAIKO_A_INTR_STATUS3 (0x09B)
+#define TAIKO_A_INTR_STATUS3__POR (0x00)
+#define TAIKO_A_INTR_CLEAR0 (0x09C)
+#define TAIKO_A_INTR_CLEAR0__POR (0x00)
+#define TAIKO_A_INTR_CLEAR1 (0x09D)
+#define TAIKO_A_INTR_CLEAR1__POR (0x00)
+#define TAIKO_A_INTR_CLEAR2 (0x09E)
+#define TAIKO_A_INTR_CLEAR2__POR (0x00)
+#define TAIKO_A_INTR_CLEAR3 (0x09F)
+#define TAIKO_A_INTR_CLEAR3__POR (0x00)
+#define TAIKO_A_INTR_LEVEL0 (0x0A0)
+#define TAIKO_A_INTR_LEVEL0__POR (0x01)
+#define TAIKO_A_INTR_LEVEL1 (0x0A1)
+#define TAIKO_A_INTR_LEVEL1__POR (0x00)
+#define TAIKO_A_INTR_LEVEL2 (0x0A2)
+#define TAIKO_A_INTR_LEVEL2__POR (0x00)
+#define TAIKO_A_INTR_LEVEL3 (0x0A3)
+#define TAIKO_A_INTR_LEVEL3__POR (0x00)
+#define TAIKO_A_INTR_TEST0 (0x0A4)
+#define TAIKO_A_INTR_TEST0__POR (0x00)
+#define TAIKO_A_INTR_TEST1 (0x0A5)
+#define TAIKO_A_INTR_TEST1__POR (0x00)
+#define TAIKO_A_INTR_TEST2 (0x0A6)
+#define TAIKO_A_INTR_TEST2__POR (0x00)
+#define TAIKO_A_INTR_TEST3 (0x0A7)
+#define TAIKO_A_INTR_TEST3__POR (0x00)
+#define TAIKO_A_INTR_SET0 (0x0A8)
+#define TAIKO_A_INTR_SET0__POR (0x00)
+#define TAIKO_A_INTR_SET1 (0x0A9)
+#define TAIKO_A_INTR_SET1__POR (0x00)
+#define TAIKO_A_INTR_SET2 (0x0AA)
+#define TAIKO_A_INTR_SET2__POR (0x00)
+#define TAIKO_A_INTR_SET3 (0x0AB)
+#define TAIKO_A_INTR_SET3__POR (0x00)
+#define TAIKO_A_INTR_DESTN0 (0x0AC)
+#define TAIKO_A_INTR_DESTN0__POR (0x00)
+#define TAIKO_A_INTR_DESTN1 (0x0AD)
+#define TAIKO_A_INTR_DESTN1__POR (0x00)
+#define TAIKO_A_INTR_DESTN2 (0x0AE)
+#define TAIKO_A_INTR_DESTN2__POR (0x00)
+#define TAIKO_A_INTR_DESTN3 (0x0AF)
+#define TAIKO_A_INTR_DESTN3__POR (0x00)
+#define TAIKO_A_CDC_TX_I2S_SCK_MODE (0x0C0)
+#define TAIKO_A_CDC_TX_I2S_SCK_MODE__POR (0x00)
+#define TAIKO_A_CDC_TX_I2S_WS_MODE (0x0C1)
+#define TAIKO_A_CDC_TX_I2S_WS_MODE__POR (0x00)
+#define TAIKO_A_CDC_DMIC_DATA0_MODE (0x0C4)
+#define TAIKO_A_CDC_DMIC_DATA0_MODE__POR (0x00)
+#define TAIKO_A_CDC_DMIC_CLK0_MODE (0x0C5)
+#define TAIKO_A_CDC_DMIC_CLK0_MODE__POR (0x00)
+#define TAIKO_A_CDC_DMIC_DATA1_MODE (0x0C6)
+#define TAIKO_A_CDC_DMIC_DATA1_MODE__POR (0x00)
+#define TAIKO_A_CDC_DMIC_CLK1_MODE (0x0C7)
+#define TAIKO_A_CDC_DMIC_CLK1_MODE__POR (0x00)
+#define TAIKO_A_CDC_RX_I2S_SCK_MODE (0x0C8)
+#define TAIKO_A_CDC_RX_I2S_SCK_MODE__POR (0x00)
+#define TAIKO_A_CDC_RX_I2S_WS_MODE (0x0C9)
+#define TAIKO_A_CDC_RX_I2S_WS_MODE__POR (0x00)
+#define TAIKO_A_CDC_DMIC_DATA2_MODE (0x0CA)
+#define TAIKO_A_CDC_DMIC_DATA2_MODE__POR (0x00)
+#define TAIKO_A_CDC_DMIC_CLK2_MODE (0x0CB)
+#define TAIKO_A_CDC_DMIC_CLK2_MODE__POR (0x00)
+#define TAIKO_A_CDC_INTR1_MODE (0x0CC)
+#define TAIKO_A_CDC_INTR1_MODE__POR (0x00)
+#define TAIKO_A_CDC_SB_NRZ_SEL_MODE (0x0CD)
+#define TAIKO_A_CDC_SB_NRZ_SEL_MODE__POR (0x00)
+#define TAIKO_A_CDC_INTR2_MODE (0x0CE)
+#define TAIKO_A_CDC_INTR2_MODE__POR (0x00)
+#define TAIKO_A_CDC_RF_PA_ON_MODE (0x0CF)
+#define TAIKO_A_CDC_RF_PA_ON_MODE__POR (0x00)
+#define TAIKO_A_BIAS_REF_CTL (0x100)
+#define TAIKO_A_BIAS_REF_CTL__POR (0x1C)
+#define TAIKO_A_BIAS_CENTRAL_BG_CTL (0x101)
+#define TAIKO_A_BIAS_CENTRAL_BG_CTL__POR (0x50)
+#define TAIKO_A_BIAS_PRECHRG_CTL (0x102)
+#define TAIKO_A_BIAS_PRECHRG_CTL__POR (0x07)
+#define TAIKO_A_BIAS_CURR_CTL_1 (0x103)
+#define TAIKO_A_BIAS_CURR_CTL_1__POR (0x52)
+#define TAIKO_A_BIAS_CURR_CTL_2 (0x104)
+#define TAIKO_A_BIAS_CURR_CTL_2__POR (0x00)
+#define TAIKO_A_BIAS_OSC_BG_CTL (0x105)
+#define TAIKO_A_BIAS_OSC_BG_CTL__POR (0x16)
+#define TAIKO_A_CLK_BUFF_EN1 (0x108)
+#define TAIKO_A_CLK_BUFF_EN1__POR (0x04)
+#define TAIKO_A_CLK_BUFF_EN2 (0x109)
+#define TAIKO_A_CLK_BUFF_EN2__POR (0x02)
+#define TAIKO_A_LDO_H_MODE_1 (0x110)
+#define TAIKO_A_LDO_H_MODE_1__POR (0x65)
+#define TAIKO_A_LDO_H_MODE_2 (0x111)
+#define TAIKO_A_LDO_H_MODE_2__POR (0xA8)
+#define TAIKO_A_LDO_H_LOOP_CTL (0x112)
+#define TAIKO_A_LDO_H_LOOP_CTL__POR (0x6B)
+#define TAIKO_A_LDO_H_COMP_1 (0x113)
+#define TAIKO_A_LDO_H_COMP_1__POR (0x84)
+#define TAIKO_A_LDO_H_COMP_2 (0x114)
+#define TAIKO_A_LDO_H_COMP_2__POR (0xE0)
+#define TAIKO_A_LDO_H_BIAS_1 (0x115)
+#define TAIKO_A_LDO_H_BIAS_1__POR (0x6D)
+#define TAIKO_A_LDO_H_BIAS_2 (0x116)
+#define TAIKO_A_LDO_H_BIAS_2__POR (0xA5)
+#define TAIKO_A_LDO_H_BIAS_3 (0x117)
+#define TAIKO_A_LDO_H_BIAS_3__POR (0x60)
+#define TAIKO_A_VBAT_CLK (0x118)
+#define TAIKO_A_VBAT_CLK__POR (0x03)
+#define TAIKO_A_VBAT_LOOP (0x119)
+#define TAIKO_A_VBAT_LOOP__POR (0x02)
+#define TAIKO_A_VBAT_REF (0x11A)
+#define TAIKO_A_VBAT_REF__POR (0x20)
+#define TAIKO_A_VBAT_ADC_TEST (0x11B)
+#define TAIKO_A_VBAT_ADC_TEST__POR (0x00)
+#define TAIKO_A_VBAT_FE (0x11C)
+#define TAIKO_A_VBAT_FE__POR (0x48)
+#define TAIKO_A_VBAT_BIAS_1 (0x11D)
+#define TAIKO_A_VBAT_BIAS_1__POR (0x03)
+#define TAIKO_A_VBAT_BIAS_2 (0x11E)
+#define TAIKO_A_VBAT_BIAS_2__POR (0x00)
+#define TAIKO_A_VBAT_ADC_DATA_MSB (0x11F)
+#define TAIKO_A_VBAT_ADC_DATA_MSB__POR (0x00)
+#define TAIKO_A_VBAT_ADC_DATA_LSB (0x120)
+#define TAIKO_A_VBAT_ADC_DATA_LSB__POR (0x00)
+#define TAIKO_A_MICB_CFILT_1_CTL (0x128)
+#define TAIKO_A_MICB_CFILT_1_CTL__POR (0x40)
+#define TAIKO_A_MICB_CFILT_1_VAL (0x129)
+#define TAIKO_A_MICB_CFILT_1_VAL__POR (0x80)
+#define TAIKO_A_MICB_CFILT_1_PRECHRG (0x12A)
+#define TAIKO_A_MICB_CFILT_1_PRECHRG__POR (0x38)
+#define TAIKO_A_MICB_1_CTL (0x12B)
+#define TAIKO_A_MICB_1_CTL__POR (0x16)
+#define TAIKO_A_MICB_1_INT_RBIAS (0x12C)
+#define TAIKO_A_MICB_1_INT_RBIAS__POR (0x24)
+#define TAIKO_A_MICB_1_MBHC (0x12D)
+#define TAIKO_A_MICB_1_MBHC__POR (0x01)
+#define TAIKO_A_MICB_CFILT_2_CTL (0x12E)
+#define TAIKO_A_MICB_CFILT_2_CTL__POR (0x40)
+#define TAIKO_A_MICB_CFILT_2_VAL (0x12F)
+#define TAIKO_A_MICB_CFILT_2_VAL__POR (0x80)
+#define TAIKO_A_MICB_CFILT_2_PRECHRG (0x130)
+#define TAIKO_A_MICB_CFILT_2_PRECHRG__POR (0x38)
+#define TAIKO_A_MICB_2_CTL (0x131)
+#define TAIKO_A_MICB_2_CTL__POR (0x16)
+#define TAIKO_A_MICB_2_INT_RBIAS (0x132)
+#define TAIKO_A_MICB_2_INT_RBIAS__POR (0x24)
+#define TAIKO_A_MICB_2_MBHC (0x133)
+#define TAIKO_A_MICB_2_MBHC__POR (0x02)
+#define TAIKO_A_MICB_CFILT_3_CTL (0x134)
+#define TAIKO_A_MICB_CFILT_3_CTL__POR (0x40)
+#define TAIKO_A_MICB_CFILT_3_VAL (0x135)
+#define TAIKO_A_MICB_CFILT_3_VAL__POR (0x80)
+#define TAIKO_A_MICB_CFILT_3_PRECHRG (0x136)
+#define TAIKO_A_MICB_CFILT_3_PRECHRG__POR (0x38)
+#define TAIKO_A_MICB_3_CTL (0x137)
+#define TAIKO_A_MICB_3_CTL__POR (0x16)
+#define TAIKO_A_MICB_3_INT_RBIAS (0x138)
+#define TAIKO_A_MICB_3_INT_RBIAS__POR (0x24)
+#define TAIKO_A_MICB_3_MBHC (0x139)
+#define TAIKO_A_MICB_3_MBHC__POR (0x00)
+#define TAIKO_A_MICB_4_CTL (0x13D)
+#define TAIKO_A_MICB_4_CTL__POR (0x16)
+#define TAIKO_A_MICB_4_INT_RBIAS (0x13E)
+#define TAIKO_A_MICB_4_INT_RBIAS__POR (0x24)
+#define TAIKO_A_MICB_4_MBHC (0x13F)
+#define TAIKO_A_MICB_4_MBHC__POR (0x01)
+#define TAIKO_A_MBHC_INSERT_DETECT (0x14A)
+#define TAIKO_A_MBHC_INSERT_DETECT__POR (0x00)
+#define TAIKO_A_MBHC_INSERT_DET_STATUS (0x14B)
+#define TAIKO_A_MBHC_INSERT_DET_STATUS__POR (0x00)
+#define TAIKO_A_TX_COM_BIAS (0x14C)
+#define TAIKO_A_TX_COM_BIAS__POR (0xF0)
+#define TAIKO_A_MBHC_SCALING_MUX_1 (0x14E)
+#define TAIKO_A_MBHC_SCALING_MUX_1__POR (0x00)
+#define TAIKO_A_MBHC_SCALING_MUX_2 (0x14F)
+#define TAIKO_A_MBHC_SCALING_MUX_2__POR (0x80)
+#define TAIKO_A_MAD_ANA_CTRL (0x150)
+#define TAIKO_A_MAD_ANA_CTRL__POR (0xF1)
+#define TAIKO_A_TX_SUP_SWITCH_CTRL_1 (0x151)
+#define TAIKO_A_TX_SUP_SWITCH_CTRL_1__POR (0x00)
+#define TAIKO_A_TX_SUP_SWITCH_CTRL_2 (0x152)
+#define TAIKO_A_TX_SUP_SWITCH_CTRL_2__POR (0x80)
+#define TAIKO_A_TX_1_2_EN (0x153)
+#define TAIKO_A_TX_1_2_EN__POR (0x00)
+#define TAIKO_A_TX_1_2_TEST_EN (0x154)
+#define TAIKO_A_TX_1_2_TEST_EN__POR (0xCC)
+#define TAIKO_A_TX_1_2_ADC_CH1 (0x155)
+#define TAIKO_A_TX_1_2_ADC_CH1__POR (0x44)
+#define TAIKO_A_TX_1_2_ADC_CH2 (0x156)
+#define TAIKO_A_TX_1_2_ADC_CH2__POR (0x44)
+#define TAIKO_A_TX_1_2_ATEST_REFCTRL (0x157)
+#define TAIKO_A_TX_1_2_ATEST_REFCTRL__POR (0x00)
+#define TAIKO_A_TX_1_2_TEST_CTL (0x158)
+#define TAIKO_A_TX_1_2_TEST_CTL__POR (0x38)
+#define TAIKO_A_TX_1_2_TEST_BLOCK_EN (0x159)
+#define TAIKO_A_TX_1_2_TEST_BLOCK_EN__POR (0xFC)
+#define TAIKO_A_TX_1_2_TXFE_CLKDIV (0x15A)
+#define TAIKO_A_TX_1_2_TXFE_CLKDIV__POR (0x55)
+#define TAIKO_A_TX_1_2_SAR_ERR_CH1 (0x15B)
+#define TAIKO_A_TX_1_2_SAR_ERR_CH1__POR (0x00)
+#define TAIKO_A_TX_1_2_SAR_ERR_CH2 (0x15C)
+#define TAIKO_A_TX_1_2_SAR_ERR_CH2__POR (0x00)
+#define TAIKO_A_TX_3_4_EN (0x15D)
+#define TAIKO_A_TX_3_4_EN__POR (0x00)
+#define TAIKO_A_TX_3_4_TEST_EN (0x15E)
+#define TAIKO_A_TX_3_4_TEST_EN__POR (0xCC)
+#define TAIKO_A_TX_3_4_ADC_CH3 (0x15F)
+#define TAIKO_A_TX_3_4_ADC_CH3__POR (0x44)
+#define TAIKO_A_TX_3_4_ADC_CH4 (0x160)
+#define TAIKO_A_TX_3_4_ADC_CH4__POR (0x44)
+#define TAIKO_A_TX_3_4_ATEST_REFCTRL (0x161)
+#define TAIKO_A_TX_3_4_ATEST_REFCTRL__POR (0x00)
+#define TAIKO_A_TX_3_4_TEST_CTL (0x162)
+#define TAIKO_A_TX_3_4_TEST_CTL__POR (0x38)
+#define TAIKO_A_TX_3_4_TEST_BLOCK_EN (0x163)
+#define TAIKO_A_TX_3_4_TEST_BLOCK_EN__POR (0xFC)
+#define TAIKO_A_TX_3_4_TXFE_CKDIV (0x164)
+#define TAIKO_A_TX_3_4_TXFE_CKDIV__POR (0x55)
+#define TAIKO_A_TX_3_4_SAR_ERR_CH3 (0x165)
+#define TAIKO_A_TX_3_4_SAR_ERR_CH3__POR (0x00)
+#define TAIKO_A_TX_3_4_SAR_ERR_CH4 (0x166)
+#define TAIKO_A_TX_3_4_SAR_ERR_CH4__POR (0x00)
+#define TAIKO_A_TX_5_6_EN (0x167)
+#define TAIKO_A_TX_5_6_EN__POR (0x11)
+#define TAIKO_A_TX_5_6_TEST_EN (0x168)
+#define TAIKO_A_TX_5_6_TEST_EN__POR (0xCC)
+#define TAIKO_A_TX_5_6_ADC_CH5 (0x169)
+#define TAIKO_A_TX_5_6_ADC_CH5__POR (0x44)
+#define TAIKO_A_TX_5_6_ADC_CH6 (0x16A)
+#define TAIKO_A_TX_5_6_ADC_CH6__POR (0x44)
+#define TAIKO_A_TX_5_6_ATEST_REFCTRL (0x16B)
+#define TAIKO_A_TX_5_6_ATEST_REFCTRL__POR (0x00)
+#define TAIKO_A_TX_5_6_TEST_CTL (0x16C)
+#define TAIKO_A_TX_5_6_TEST_CTL__POR (0x38)
+#define TAIKO_A_TX_5_6_TEST_BLOCK_EN (0x16D)
+#define TAIKO_A_TX_5_6_TEST_BLOCK_EN__POR (0xFC)
+#define TAIKO_A_TX_5_6_TXFE_CKDIV (0x16E)
+#define TAIKO_A_TX_5_6_TXFE_CKDIV__POR (0x55)
+#define TAIKO_A_TX_5_6_SAR_ERR_CH5 (0x16F)
+#define TAIKO_A_TX_5_6_SAR_ERR_CH5__POR (0x00)
+#define TAIKO_A_TX_5_6_SAR_ERR_CH6 (0x170)
+#define TAIKO_A_TX_5_6_SAR_ERR_CH6__POR (0x00)
+#define TAIKO_A_TX_7_MBHC_EN (0x171)
+#define TAIKO_A_TX_7_MBHC_EN__POR (0x0C)
+#define TAIKO_A_TX_7_MBHC_ATEST_REFCTRL (0x172)
+#define TAIKO_A_TX_7_MBHC_ATEST_REFCTRL__POR (0x00)
+#define TAIKO_A_TX_7_MBHC_ADC (0x173)
+#define TAIKO_A_TX_7_MBHC_ADC__POR (0x44)
+#define TAIKO_A_TX_7_MBHC_TEST_CTL (0x174)
+#define TAIKO_A_TX_7_MBHC_TEST_CTL__POR (0x38)
+#define TAIKO_A_TX_7_MBHC_SAR_ERR (0x175)
+#define TAIKO_A_TX_7_MBHC_SAR_ERR__POR (0x00)
+#define TAIKO_A_TX_7_TXFE_CLKDIV (0x176)
+#define TAIKO_A_TX_7_TXFE_CLKDIV__POR (0x0B)
+#define TAIKO_A_BUCK_MODE_1 (0x181)
+#define TAIKO_A_BUCK_MODE_1__POR (0x21)
+#define TAIKO_A_BUCK_MODE_2 (0x182)
+#define TAIKO_A_BUCK_MODE_2__POR (0xFF)
+#define TAIKO_A_BUCK_MODE_3 (0x183)
+#define TAIKO_A_BUCK_MODE_3__POR (0xCC)
+#define TAIKO_A_BUCK_MODE_4 (0x184)
+#define TAIKO_A_BUCK_MODE_4__POR (0x3A)
+#define TAIKO_A_BUCK_MODE_5 (0x185)
+#define TAIKO_A_BUCK_MODE_5__POR (0x00)
+#define TAIKO_A_BUCK_CTRL_VCL_1 (0x186)
+#define TAIKO_A_BUCK_CTRL_VCL_1__POR (0x48)
+#define TAIKO_A_BUCK_CTRL_VCL_2 (0x187)
+#define TAIKO_A_BUCK_CTRL_VCL_2__POR (0xA3)
+#define TAIKO_A_BUCK_CTRL_VCL_3 (0x188)
+#define TAIKO_A_BUCK_CTRL_VCL_3__POR (0x82)
+#define TAIKO_A_BUCK_CTRL_CCL_1 (0x189)
+#define TAIKO_A_BUCK_CTRL_CCL_1__POR (0xAB)
+#define TAIKO_A_BUCK_CTRL_CCL_2 (0x18A)
+#define TAIKO_A_BUCK_CTRL_CCL_2__POR (0xDC)
+#define TAIKO_A_BUCK_CTRL_CCL_3 (0x18B)
+#define TAIKO_A_BUCK_CTRL_CCL_3__POR (0x6A)
+#define TAIKO_A_BUCK_CTRL_CCL_4 (0x18C)
+#define TAIKO_A_BUCK_CTRL_CCL_4__POR (0x58)
+#define TAIKO_A_BUCK_CTRL_PWM_DRVR_1 (0x18D)
+#define TAIKO_A_BUCK_CTRL_PWM_DRVR_1__POR (0x50)
+#define TAIKO_A_BUCK_CTRL_PWM_DRVR_2 (0x18E)
+#define TAIKO_A_BUCK_CTRL_PWM_DRVR_2__POR (0x64)
+#define TAIKO_A_BUCK_CTRL_PWM_DRVR_3 (0x18F)
+#define TAIKO_A_BUCK_CTRL_PWM_DRVR_3__POR (0x77)
+#define TAIKO_A_BUCK_TMUX_A_D (0x190)
+#define TAIKO_A_BUCK_TMUX_A_D__POR (0x00)
+#define TAIKO_A_NCP_BUCKREF (0x191)
+#define TAIKO_A_NCP_BUCKREF__POR (0x00)
+#define TAIKO_A_NCP_EN (0x192)
+#define TAIKO_A_NCP_EN__POR (0xFE)
+#define TAIKO_A_NCP_CLK (0x193)
+#define TAIKO_A_NCP_CLK__POR (0x94)
+#define TAIKO_A_NCP_STATIC (0x194)
+#define TAIKO_A_NCP_STATIC__POR (0x28)
+#define TAIKO_A_NCP_VTH_LOW (0x195)
+#define TAIKO_A_NCP_VTH_LOW__POR (0x88)
+#define TAIKO_A_NCP_VTH_HIGH (0x196)
+#define TAIKO_A_NCP_VTH_HIGH__POR (0xA0)
+#define TAIKO_A_NCP_ATEST (0x197)
+#define TAIKO_A_NCP_ATEST__POR (0x00)
+#define TAIKO_A_NCP_DTEST (0x198)
+#define TAIKO_A_NCP_DTEST__POR (0x00)
+#define TAIKO_A_NCP_DLY1 (0x199)
+#define TAIKO_A_NCP_DLY1__POR (0x06)
+#define TAIKO_A_NCP_DLY2 (0x19A)
+#define TAIKO_A_NCP_DLY2__POR (0x06)
+#define TAIKO_A_RX_AUX_SW_CTL (0x19B)
+#define TAIKO_A_RX_AUX_SW_CTL__POR (0x00)
+#define TAIKO_A_RX_PA_AUX_IN_CONN (0x19C)
+#define TAIKO_A_RX_PA_AUX_IN_CONN__POR (0x00)
+#define TAIKO_A_RX_COM_TIMER_DIV (0x19E)
+#define TAIKO_A_RX_COM_TIMER_DIV__POR (0xE8)
+#define TAIKO_A_RX_COM_OCP_CTL (0x19F)
+#define TAIKO_A_RX_COM_OCP_CTL__POR (0x1F)
+#define TAIKO_A_RX_COM_OCP_COUNT (0x1A0)
+#define TAIKO_A_RX_COM_OCP_COUNT__POR (0x77)
+#define TAIKO_A_RX_COM_DAC_CTL (0x1A1)
+#define TAIKO_A_RX_COM_DAC_CTL__POR (0x00)
+#define TAIKO_A_RX_COM_BIAS (0x1A2)
+#define TAIKO_A_RX_COM_BIAS__POR (0x00)
+#define TAIKO_A_RX_HPH_AUTO_CHOP (0x1A4)
+#define TAIKO_A_RX_HPH_AUTO_CHOP__POR (0x38)
+#define TAIKO_A_RX_HPH_CHOP_CTL (0x1A5)
+#define TAIKO_A_RX_HPH_CHOP_CTL__POR (0xB4)
+#define TAIKO_A_RX_HPH_BIAS_PA (0x1A6)
+#define TAIKO_A_RX_HPH_BIAS_PA__POR (0xAA)
+#define TAIKO_A_RX_HPH_BIAS_LDO (0x1A7)
+#define TAIKO_A_RX_HPH_BIAS_LDO__POR (0x87)
+#define TAIKO_A_RX_HPH_BIAS_CNP (0x1A8)
+#define TAIKO_A_RX_HPH_BIAS_CNP__POR (0x8A)
+#define TAIKO_A_RX_HPH_BIAS_WG_OCP (0x1A9)
+#define TAIKO_A_RX_HPH_BIAS_WG_OCP__POR (0x2A)
+#define TAIKO_A_RX_HPH_OCP_CTL (0x1AA)
+#define TAIKO_A_RX_HPH_OCP_CTL__POR (0x68)
+#define TAIKO_A_RX_HPH_CNP_EN (0x1AB)
+#define TAIKO_A_RX_HPH_CNP_EN__POR (0x80)
+#define TAIKO_A_RX_HPH_CNP_WG_CTL (0x1AC)
+#define TAIKO_A_RX_HPH_CNP_WG_CTL__POR (0xDE)
+#define TAIKO_A_RX_HPH_CNP_WG_TIME (0x1AD)
+#define TAIKO_A_RX_HPH_CNP_WG_TIME__POR (0x2A)
+#define TAIKO_A_RX_HPH_L_GAIN (0x1AE)
+#define TAIKO_A_RX_HPH_L_GAIN__POR (0x00)
+#define TAIKO_A_RX_HPH_L_TEST (0x1AF)
+#define TAIKO_A_RX_HPH_L_TEST__POR (0x00)
+#define TAIKO_A_RX_HPH_L_PA_CTL (0x1B0)
+#define TAIKO_A_RX_HPH_L_PA_CTL__POR (0x40)
+#define TAIKO_A_RX_HPH_L_DAC_CTL (0x1B1)
+#define TAIKO_A_RX_HPH_L_DAC_CTL__POR (0x00)
+#define TAIKO_A_RX_HPH_L_ATEST (0x1B2)
+#define TAIKO_A_RX_HPH_L_ATEST__POR (0x00)
+#define TAIKO_A_RX_HPH_L_STATUS (0x1B3)
+#define TAIKO_A_RX_HPH_L_STATUS__POR (0x00)
+#define TAIKO_A_RX_HPH_R_GAIN (0x1B4)
+#define TAIKO_A_RX_HPH_R_GAIN__POR (0x00)
+#define TAIKO_A_RX_HPH_R_TEST (0x1B5)
+#define TAIKO_A_RX_HPH_R_TEST__POR (0x00)
+#define TAIKO_A_RX_HPH_R_PA_CTL (0x1B6)
+#define TAIKO_A_RX_HPH_R_PA_CTL__POR (0x40)
+#define TAIKO_A_RX_HPH_R_DAC_CTL (0x1B7)
+#define TAIKO_A_RX_HPH_R_DAC_CTL__POR (0x00)
+#define TAIKO_A_RX_HPH_R_ATEST (0x1B8)
+#define TAIKO_A_RX_HPH_R_ATEST__POR (0x00)
+#define TAIKO_A_RX_HPH_R_STATUS (0x1B9)
+#define TAIKO_A_RX_HPH_R_STATUS__POR (0x00)
+#define TAIKO_A_RX_EAR_BIAS_PA (0x1BA)
+#define TAIKO_A_RX_EAR_BIAS_PA__POR (0xA6)
+#define TAIKO_A_RX_EAR_BIAS_CMBUFF (0x1BB)
+#define TAIKO_A_RX_EAR_BIAS_CMBUFF__POR (0xA0)
+#define TAIKO_A_RX_EAR_EN (0x1BC)
+#define TAIKO_A_RX_EAR_EN__POR (0x00)
+#define TAIKO_A_RX_EAR_GAIN (0x1BD)
+#define TAIKO_A_RX_EAR_GAIN__POR (0x02)
+#define TAIKO_A_RX_EAR_CMBUFF (0x1BE)
+#define TAIKO_A_RX_EAR_CMBUFF__POR (0x04)
+#define TAIKO_A_RX_EAR_ICTL (0x1BF)
+#define TAIKO_A_RX_EAR_ICTL__POR (0x40)
+#define TAIKO_A_RX_EAR_CCOMP (0x1C0)
+#define TAIKO_A_RX_EAR_CCOMP__POR (0x08)
+#define TAIKO_A_RX_EAR_VCM (0x1C1)
+#define TAIKO_A_RX_EAR_VCM__POR (0x03)
+#define TAIKO_A_RX_EAR_CNP (0x1C2)
+#define TAIKO_A_RX_EAR_CNP__POR (0xF2)
+#define TAIKO_A_RX_EAR_DAC_CTL_ATEST (0x1C3)
+#define TAIKO_A_RX_EAR_DAC_CTL_ATEST__POR (0x00)
+#define TAIKO_A_RX_EAR_STATUS (0x1C5)
+#define TAIKO_A_RX_EAR_STATUS__POR (0x04)
+#define TAIKO_A_RX_LINE_BIAS_PA (0x1C6)
+#define TAIKO_A_RX_LINE_BIAS_PA__POR (0xA8)
+#define TAIKO_A_RX_BUCK_BIAS1 (0x1C7)
+#define TAIKO_A_RX_BUCK_BIAS1__POR (0x42)
+#define TAIKO_A_RX_BUCK_BIAS2 (0x1C8)
+#define TAIKO_A_RX_BUCK_BIAS2__POR (0x84)
+#define TAIKO_A_RX_LINE_COM (0x1C9)
+#define TAIKO_A_RX_LINE_COM__POR (0x80)
+#define TAIKO_A_RX_LINE_CNP_EN (0x1CA)
+#define TAIKO_A_RX_LINE_CNP_EN__POR (0x00)
+#define TAIKO_A_RX_LINE_CNP_WG_CTL (0x1CB)
+#define TAIKO_A_RX_LINE_CNP_WG_CTL__POR (0x00)
+#define TAIKO_A_RX_LINE_CNP_WG_TIME (0x1CC)
+#define TAIKO_A_RX_LINE_CNP_WG_TIME__POR (0x04)
+#define TAIKO_A_RX_LINE_1_GAIN (0x1CD)
+#define TAIKO_A_RX_LINE_1_GAIN__POR (0x00)
+#define TAIKO_A_RX_LINE_1_TEST (0x1CE)
+#define TAIKO_A_RX_LINE_1_TEST__POR (0x00)
+#define TAIKO_A_RX_LINE_1_DAC_CTL (0x1CF)
+#define TAIKO_A_RX_LINE_1_DAC_CTL__POR (0x00)
+#define TAIKO_A_RX_LINE_1_STATUS (0x1D0)
+#define TAIKO_A_RX_LINE_1_STATUS__POR (0x00)
+#define TAIKO_A_RX_LINE_2_GAIN (0x1D1)
+#define TAIKO_A_RX_LINE_2_GAIN__POR (0x00)
+#define TAIKO_A_RX_LINE_2_TEST (0x1D2)
+#define TAIKO_A_RX_LINE_2_TEST__POR (0x00)
+#define TAIKO_A_RX_LINE_2_DAC_CTL (0x1D3)
+#define TAIKO_A_RX_LINE_2_DAC_CTL__POR (0x00)
+#define TAIKO_A_RX_LINE_2_STATUS (0x1D4)
+#define TAIKO_A_RX_LINE_2_STATUS__POR (0x00)
+#define TAIKO_A_RX_LINE_3_GAIN (0x1D5)
+#define TAIKO_A_RX_LINE_3_GAIN__POR (0x00)
+#define TAIKO_A_RX_LINE_3_TEST (0x1D6)
+#define TAIKO_A_RX_LINE_3_TEST__POR (0x00)
+#define TAIKO_A_RX_LINE_3_DAC_CTL (0x1D7)
+#define TAIKO_A_RX_LINE_3_DAC_CTL__POR (0x00)
+#define TAIKO_A_RX_LINE_3_STATUS (0x1D8)
+#define TAIKO_A_RX_LINE_3_STATUS__POR (0x00)
+#define TAIKO_A_RX_LINE_4_GAIN (0x1D9)
+#define TAIKO_A_RX_LINE_4_GAIN__POR (0x00)
+#define TAIKO_A_RX_LINE_4_TEST (0x1DA)
+#define TAIKO_A_RX_LINE_4_TEST__POR (0x00)
+#define TAIKO_A_RX_LINE_4_DAC_CTL (0x1DB)
+#define TAIKO_A_RX_LINE_4_DAC_CTL__POR (0x00)
+#define TAIKO_A_RX_LINE_4_STATUS (0x1DC)
+#define TAIKO_A_RX_LINE_4_STATUS__POR (0x00)
+#define TAIKO_A_RX_LINE_CNP_DBG (0x1DD)
+#define TAIKO_A_RX_LINE_CNP_DBG__POR (0x00)
+#define TAIKO_A_SPKR_DRV_EN (0x1DF)
+#define TAIKO_A_SPKR_DRV_EN__POR (0x6F)
+#define TAIKO_A_SPKR_DRV_GAIN (0x1E0)
+#define TAIKO_A_SPKR_DRV_GAIN__POR (0x00)
+#define TAIKO_A_SPKR_DRV_DAC_CTL (0x1E1)
+#define TAIKO_A_SPKR_DRV_DAC_CTL__POR (0x04)
+#define TAIKO_A_SPKR_DRV_OCP_CTL (0x1E2)
+#define TAIKO_A_SPKR_DRV_OCP_CTL__POR (0x98)
+#define TAIKO_A_SPKR_DRV_CLIP_DET (0x1E3)
+#define TAIKO_A_SPKR_DRV_CLIP_DET__POR (0x48)
+#define TAIKO_A_SPKR_DRV_IEC (0x1E4)
+#define TAIKO_A_SPKR_DRV_IEC__POR (0x20)
+#define TAIKO_A_SPKR_DRV_DBG_DAC (0x1E5)
+#define TAIKO_A_SPKR_DRV_DBG_DAC__POR (0x05)
+#define TAIKO_A_SPKR_DRV_DBG_PA (0x1E6)
+#define TAIKO_A_SPKR_DRV_DBG_PA__POR (0x18)
+#define TAIKO_A_SPKR_DRV_DBG_PWRSTG (0x1E7)
+#define TAIKO_A_SPKR_DRV_DBG_PWRSTG__POR (0x00)
+#define TAIKO_A_SPKR_DRV_BIAS_LDO (0x1E8)
+#define TAIKO_A_SPKR_DRV_BIAS_LDO__POR (0x45)
+#define TAIKO_A_SPKR_DRV_BIAS_INT (0x1E9)
+#define TAIKO_A_SPKR_DRV_BIAS_INT__POR (0xA5)
+#define TAIKO_A_SPKR_DRV_BIAS_PA (0x1EA)
+#define TAIKO_A_SPKR_DRV_BIAS_PA__POR (0x55)
+#define TAIKO_A_SPKR_DRV_STATUS_OCP (0x1EB)
+#define TAIKO_A_SPKR_DRV_STATUS_OCP__POR (0x00)
+#define TAIKO_A_SPKR_DRV_STATUS_PA (0x1EC)
+#define TAIKO_A_SPKR_DRV_STATUS_PA__POR (0x00)
+#define TAIKO_A_SPKR_PROT_EN (0x1ED)
+#define TAIKO_A_SPKR_PROT_EN__POR (0x00)
+#define TAIKO_A_SPKR_PROT_ADC_EN (0x1EE)
+#define TAIKO_A_SPKR_PROT_ADC_EN__POR (0x44)
+#define TAIKO_A_SPKR_PROT_ISENSE_BIAS (0x1EF)
+#define TAIKO_A_SPKR_PROT_ISENSE_BIAS__POR (0x44)
+#define TAIKO_A_SPKR_PROT_VSENSE_BIAS (0x1F0)
+#define TAIKO_A_SPKR_PROT_VSENSE_BIAS__POR (0x44)
+#define TAIKO_A_SPKR_PROT_ADC_ATEST_REFCTRL (0x1F1)
+#define TAIKO_A_SPKR_PROT_ADC_ATEST_REFCTRL__POR (0x00)
+#define TAIKO_A_SPKR_PROT_ADC_TEST_CTL (0x1F2)
+#define TAIKO_A_SPKR_PROT_ADC_TEST_CTL__POR (0x38)
+#define TAIKO_A_SPKR_PROT_TEST_BLOCK_EN (0x1F3)
+#define TAIKO_A_SPKR_PROT_TEST_BLOCK_EN__POR (0xFC)
+#define TAIKO_A_SPKR_PROT_ATEST (0x1F4)
+#define TAIKO_A_SPKR_PROT_ATEST__POR (0x00)
+#define TAIKO_A_SPKR_PROT_V_SAR_ERR (0x1F5)
+#define TAIKO_A_SPKR_PROT_V_SAR_ERR__POR (0x00)
+#define TAIKO_A_SPKR_PROT_I_SAR_ERR (0x1F6)
+#define TAIKO_A_SPKR_PROT_I_SAR_ERR__POR (0x00)
+#define TAIKO_A_SPKR_PROT_LDO_CTRL (0x1F7)
+#define TAIKO_A_SPKR_PROT_LDO_CTRL__POR (0x00)
+#define TAIKO_A_SPKR_PROT_ISENSE_CTRL (0x1F8)
+#define TAIKO_A_SPKR_PROT_ISENSE_CTRL__POR (0x00)
+#define TAIKO_A_SPKR_PROT_VSENSE_CTRL (0x1F9)
+#define TAIKO_A_SPKR_PROT_VSENSE_CTRL__POR (0x00)
+#define TAIKO_A_RC_OSC_FREQ (0x1FA)
+#define TAIKO_A_RC_OSC_FREQ__POR (0x46)
+#define TAIKO_A_RC_OSC_TEST (0x1FB)
+#define TAIKO_A_RC_OSC_TEST__POR (0x0A)
+#define TAIKO_A_RC_OSC_STATUS (0x1FC)
+#define TAIKO_A_RC_OSC_STATUS__POR (0x18)
+#define TAIKO_A_RC_OSC_TUNER (0x1FD)
+#define TAIKO_A_RC_OSC_TUNER__POR (0x00)
+#define TAIKO_A_MBHC_HPH (0x1FE)
+#define TAIKO_A_MBHC_HPH__POR (0x44)
+#define TAIKO_A_CDC_ANC1_B1_CTL (0x200)
+#define TAIKO_A_CDC_ANC1_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC2_B1_CTL (0x280)
+#define TAIKO_A_CDC_ANC2_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC1_SHIFT (0x201)
+#define TAIKO_A_CDC_ANC1_SHIFT__POR (0x00)
+#define TAIKO_A_CDC_ANC2_SHIFT (0x281)
+#define TAIKO_A_CDC_ANC2_SHIFT__POR (0x00)
+#define TAIKO_A_CDC_ANC1_IIR_B1_CTL (0x202)
+#define TAIKO_A_CDC_ANC1_IIR_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC2_IIR_B1_CTL (0x282)
+#define TAIKO_A_CDC_ANC2_IIR_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC1_IIR_B2_CTL (0x203)
+#define TAIKO_A_CDC_ANC1_IIR_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC2_IIR_B2_CTL (0x283)
+#define TAIKO_A_CDC_ANC2_IIR_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC1_IIR_B3_CTL (0x204)
+#define TAIKO_A_CDC_ANC1_IIR_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC2_IIR_B3_CTL (0x284)
+#define TAIKO_A_CDC_ANC2_IIR_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC1_LPF_B1_CTL (0x206)
+#define TAIKO_A_CDC_ANC1_LPF_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC2_LPF_B1_CTL (0x286)
+#define TAIKO_A_CDC_ANC2_LPF_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC1_LPF_B2_CTL (0x207)
+#define TAIKO_A_CDC_ANC1_LPF_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC2_LPF_B2_CTL (0x287)
+#define TAIKO_A_CDC_ANC2_LPF_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC1_SPARE (0x209)
+#define TAIKO_A_CDC_ANC1_SPARE__POR (0x00)
+#define TAIKO_A_CDC_ANC2_SPARE (0x289)
+#define TAIKO_A_CDC_ANC2_SPARE__POR (0x00)
+#define TAIKO_A_CDC_ANC1_SMLPF_CTL (0x20A)
+#define TAIKO_A_CDC_ANC1_SMLPF_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC2_SMLPF_CTL (0x28A)
+#define TAIKO_A_CDC_ANC2_SMLPF_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC1_DCFLT_CTL (0x20B)
+#define TAIKO_A_CDC_ANC1_DCFLT_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC2_DCFLT_CTL (0x28B)
+#define TAIKO_A_CDC_ANC2_DCFLT_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC1_GAIN_CTL (0x20C)
+#define TAIKO_A_CDC_ANC1_GAIN_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC2_GAIN_CTL (0x28C)
+#define TAIKO_A_CDC_ANC2_GAIN_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC1_B2_CTL (0x20D)
+#define TAIKO_A_CDC_ANC1_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_ANC2_B2_CTL (0x28D)
+#define TAIKO_A_CDC_ANC2_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX1_VOL_CTL_TIMER (0x220)
+#define TAIKO_A_CDC_TX1_VOL_CTL_TIMER__POR (0x00)
+#define TAIKO_A_CDC_TX2_VOL_CTL_TIMER (0x228)
+#define TAIKO_A_CDC_TX2_VOL_CTL_TIMER__POR (0x00)
+#define TAIKO_A_CDC_TX3_VOL_CTL_TIMER (0x230)
+#define TAIKO_A_CDC_TX3_VOL_CTL_TIMER__POR (0x00)
+#define TAIKO_A_CDC_TX4_VOL_CTL_TIMER (0x238)
+#define TAIKO_A_CDC_TX4_VOL_CTL_TIMER__POR (0x00)
+#define TAIKO_A_CDC_TX5_VOL_CTL_TIMER (0x240)
+#define TAIKO_A_CDC_TX5_VOL_CTL_TIMER__POR (0x00)
+#define TAIKO_A_CDC_TX6_VOL_CTL_TIMER (0x248)
+#define TAIKO_A_CDC_TX6_VOL_CTL_TIMER__POR (0x00)
+#define TAIKO_A_CDC_TX7_VOL_CTL_TIMER (0x250)
+#define TAIKO_A_CDC_TX7_VOL_CTL_TIMER__POR (0x00)
+#define TAIKO_A_CDC_TX8_VOL_CTL_TIMER (0x258)
+#define TAIKO_A_CDC_TX8_VOL_CTL_TIMER__POR (0x00)
+#define TAIKO_A_CDC_TX9_VOL_CTL_TIMER (0x260)
+#define TAIKO_A_CDC_TX9_VOL_CTL_TIMER__POR (0x00)
+#define TAIKO_A_CDC_TX10_VOL_CTL_TIMER (0x268)
+#define TAIKO_A_CDC_TX10_VOL_CTL_TIMER__POR (0x00)
+#define TAIKO_A_CDC_TX1_VOL_CTL_GAIN (0x221)
+#define TAIKO_A_CDC_TX1_VOL_CTL_GAIN__POR (0x00)
+#define TAIKO_A_CDC_TX2_VOL_CTL_GAIN (0x229)
+#define TAIKO_A_CDC_TX2_VOL_CTL_GAIN__POR (0x00)
+#define TAIKO_A_CDC_TX3_VOL_CTL_GAIN (0x231)
+#define TAIKO_A_CDC_TX3_VOL_CTL_GAIN__POR (0x00)
+#define TAIKO_A_CDC_TX4_VOL_CTL_GAIN (0x239)
+#define TAIKO_A_CDC_TX4_VOL_CTL_GAIN__POR (0x00)
+#define TAIKO_A_CDC_TX5_VOL_CTL_GAIN (0x241)
+#define TAIKO_A_CDC_TX5_VOL_CTL_GAIN__POR (0x00)
+#define TAIKO_A_CDC_TX6_VOL_CTL_GAIN (0x249)
+#define TAIKO_A_CDC_TX6_VOL_CTL_GAIN__POR (0x00)
+#define TAIKO_A_CDC_TX7_VOL_CTL_GAIN (0x251)
+#define TAIKO_A_CDC_TX7_VOL_CTL_GAIN__POR (0x00)
+#define TAIKO_A_CDC_TX8_VOL_CTL_GAIN (0x259)
+#define TAIKO_A_CDC_TX8_VOL_CTL_GAIN__POR (0x00)
+#define TAIKO_A_CDC_TX9_VOL_CTL_GAIN (0x261)
+#define TAIKO_A_CDC_TX9_VOL_CTL_GAIN__POR (0x00)
+#define TAIKO_A_CDC_TX10_VOL_CTL_GAIN (0x269)
+#define TAIKO_A_CDC_TX10_VOL_CTL_GAIN__POR (0x00)
+#define TAIKO_A_CDC_TX1_VOL_CTL_CFG (0x222)
+#define TAIKO_A_CDC_TX1_VOL_CTL_CFG__POR (0x00)
+#define TAIKO_A_CDC_TX2_VOL_CTL_CFG (0x22A)
+#define TAIKO_A_CDC_TX2_VOL_CTL_CFG__POR (0x00)
+#define TAIKO_A_CDC_TX3_VOL_CTL_CFG (0x232)
+#define TAIKO_A_CDC_TX3_VOL_CTL_CFG__POR (0x00)
+#define TAIKO_A_CDC_TX4_VOL_CTL_CFG (0x23A)
+#define TAIKO_A_CDC_TX4_VOL_CTL_CFG__POR (0x00)
+#define TAIKO_A_CDC_TX5_VOL_CTL_CFG (0x242)
+#define TAIKO_A_CDC_TX5_VOL_CTL_CFG__POR (0x00)
+#define TAIKO_A_CDC_TX6_VOL_CTL_CFG (0x24A)
+#define TAIKO_A_CDC_TX6_VOL_CTL_CFG__POR (0x00)
+#define TAIKO_A_CDC_TX7_VOL_CTL_CFG (0x252)
+#define TAIKO_A_CDC_TX7_VOL_CTL_CFG__POR (0x00)
+#define TAIKO_A_CDC_TX8_VOL_CTL_CFG (0x25A)
+#define TAIKO_A_CDC_TX8_VOL_CTL_CFG__POR (0x00)
+#define TAIKO_A_CDC_TX9_VOL_CTL_CFG (0x262)
+#define TAIKO_A_CDC_TX9_VOL_CTL_CFG__POR (0x00)
+#define TAIKO_A_CDC_TX10_VOL_CTL_CFG (0x26A)
+#define TAIKO_A_CDC_TX10_VOL_CTL_CFG__POR (0x00)
+#define TAIKO_A_CDC_TX1_MUX_CTL (0x223)
+#define TAIKO_A_CDC_TX1_MUX_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX2_MUX_CTL (0x22B)
+#define TAIKO_A_CDC_TX2_MUX_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX3_MUX_CTL (0x233)
+#define TAIKO_A_CDC_TX3_MUX_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX4_MUX_CTL (0x23B)
+#define TAIKO_A_CDC_TX4_MUX_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX5_MUX_CTL (0x243)
+#define TAIKO_A_CDC_TX5_MUX_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX6_MUX_CTL (0x24B)
+#define TAIKO_A_CDC_TX6_MUX_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX7_MUX_CTL (0x253)
+#define TAIKO_A_CDC_TX7_MUX_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX8_MUX_CTL (0x25B)
+#define TAIKO_A_CDC_TX8_MUX_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX9_MUX_CTL (0x263)
+#define TAIKO_A_CDC_TX9_MUX_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX10_MUX_CTL (0x26B)
+#define TAIKO_A_CDC_TX10_MUX_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX1_CLK_FS_CTL (0x224)
+#define TAIKO_A_CDC_TX1_CLK_FS_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX2_CLK_FS_CTL (0x22C)
+#define TAIKO_A_CDC_TX2_CLK_FS_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX3_CLK_FS_CTL (0x234)
+#define TAIKO_A_CDC_TX3_CLK_FS_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX4_CLK_FS_CTL (0x23C)
+#define TAIKO_A_CDC_TX4_CLK_FS_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX5_CLK_FS_CTL (0x244)
+#define TAIKO_A_CDC_TX5_CLK_FS_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX6_CLK_FS_CTL (0x24C)
+#define TAIKO_A_CDC_TX6_CLK_FS_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX7_CLK_FS_CTL (0x254)
+#define TAIKO_A_CDC_TX7_CLK_FS_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX8_CLK_FS_CTL (0x25C)
+#define TAIKO_A_CDC_TX8_CLK_FS_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX9_CLK_FS_CTL (0x264)
+#define TAIKO_A_CDC_TX9_CLK_FS_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX10_CLK_FS_CTL (0x26C)
+#define TAIKO_A_CDC_TX10_CLK_FS_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX1_DMIC_CTL (0x225)
+#define TAIKO_A_CDC_TX1_DMIC_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX2_DMIC_CTL (0x22D)
+#define TAIKO_A_CDC_TX2_DMIC_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX3_DMIC_CTL (0x235)
+#define TAIKO_A_CDC_TX3_DMIC_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX4_DMIC_CTL (0x23D)
+#define TAIKO_A_CDC_TX4_DMIC_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX5_DMIC_CTL (0x245)
+#define TAIKO_A_CDC_TX5_DMIC_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX6_DMIC_CTL (0x24D)
+#define TAIKO_A_CDC_TX6_DMIC_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX7_DMIC_CTL (0x255)
+#define TAIKO_A_CDC_TX7_DMIC_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX8_DMIC_CTL (0x25D)
+#define TAIKO_A_CDC_TX8_DMIC_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX9_DMIC_CTL (0x265)
+#define TAIKO_A_CDC_TX9_DMIC_CTL__POR (0x00)
+#define TAIKO_A_CDC_TX10_DMIC_CTL (0x26D)
+#define TAIKO_A_CDC_TX10_DMIC_CTL__POR (0x00)
+#define TAIKO_A_CDC_DEBUG_B1_CTL (0x278)
+#define TAIKO_A_CDC_DEBUG_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_DEBUG_B2_CTL (0x279)
+#define TAIKO_A_CDC_DEBUG_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_DEBUG_B3_CTL (0x27A)
+#define TAIKO_A_CDC_DEBUG_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_DEBUG_B4_CTL (0x27B)
+#define TAIKO_A_CDC_DEBUG_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_DEBUG_B5_CTL (0x27C)
+#define TAIKO_A_CDC_DEBUG_B5_CTL__POR (0x00)
+#define TAIKO_A_CDC_DEBUG_B6_CTL (0x27D)
+#define TAIKO_A_CDC_DEBUG_B6_CTL__POR (0x00)
+#define TAIKO_A_CDC_DEBUG_B7_CTL (0x27E)
+#define TAIKO_A_CDC_DEBUG_B7_CTL__POR (0x00)
+#define TAIKO_A_CDC_SRC1_PDA_CFG (0x2A0)
+#define TAIKO_A_CDC_SRC1_PDA_CFG__POR (0x00)
+#define TAIKO_A_CDC_SRC2_PDA_CFG (0x2A8)
+#define TAIKO_A_CDC_SRC2_PDA_CFG__POR (0x00)
+#define TAIKO_A_CDC_SRC1_FS_CTL (0x2A1)
+#define TAIKO_A_CDC_SRC1_FS_CTL__POR (0x00)
+#define TAIKO_A_CDC_SRC2_FS_CTL (0x2A9)
+#define TAIKO_A_CDC_SRC2_FS_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX1_B1_CTL (0x2B0)
+#define TAIKO_A_CDC_RX1_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX2_B1_CTL (0x2B8)
+#define TAIKO_A_CDC_RX2_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX3_B1_CTL (0x2C0)
+#define TAIKO_A_CDC_RX3_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX4_B1_CTL (0x2C8)
+#define TAIKO_A_CDC_RX4_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX5_B1_CTL (0x2D0)
+#define TAIKO_A_CDC_RX5_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX6_B1_CTL (0x2D8)
+#define TAIKO_A_CDC_RX6_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX7_B1_CTL (0x2E0)
+#define TAIKO_A_CDC_RX7_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX1_B2_CTL (0x2B1)
+#define TAIKO_A_CDC_RX1_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX2_B2_CTL (0x2B9)
+#define TAIKO_A_CDC_RX2_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX3_B2_CTL (0x2C1)
+#define TAIKO_A_CDC_RX3_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX4_B2_CTL (0x2C9)
+#define TAIKO_A_CDC_RX4_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX5_B2_CTL (0x2D1)
+#define TAIKO_A_CDC_RX5_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX6_B2_CTL (0x2D9)
+#define TAIKO_A_CDC_RX6_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX7_B2_CTL (0x2E1)
+#define TAIKO_A_CDC_RX7_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX1_B3_CTL (0x2B2)
+#define TAIKO_A_CDC_RX1_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX2_B3_CTL (0x2BA)
+#define TAIKO_A_CDC_RX2_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX3_B3_CTL (0x2C2)
+#define TAIKO_A_CDC_RX3_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX4_B3_CTL (0x2CA)
+#define TAIKO_A_CDC_RX4_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX5_B3_CTL (0x2D2)
+#define TAIKO_A_CDC_RX5_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX6_B3_CTL (0x2DA)
+#define TAIKO_A_CDC_RX6_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX7_B3_CTL (0x2E2)
+#define TAIKO_A_CDC_RX7_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX1_B4_CTL (0x2B3)
+#define TAIKO_A_CDC_RX1_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX2_B4_CTL (0x2BB)
+#define TAIKO_A_CDC_RX2_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX3_B4_CTL (0x2C3)
+#define TAIKO_A_CDC_RX3_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX4_B4_CTL (0x2CB)
+#define TAIKO_A_CDC_RX4_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX5_B4_CTL (0x2D3)
+#define TAIKO_A_CDC_RX5_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX6_B4_CTL (0x2DB)
+#define TAIKO_A_CDC_RX6_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX7_B4_CTL (0x2E3)
+#define TAIKO_A_CDC_RX7_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX1_B5_CTL (0x2B4)
+#define TAIKO_A_CDC_RX1_B5_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX2_B5_CTL (0x2BC)
+#define TAIKO_A_CDC_RX2_B5_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX3_B5_CTL (0x2C4)
+#define TAIKO_A_CDC_RX3_B5_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX4_B5_CTL (0x2CC)
+#define TAIKO_A_CDC_RX4_B5_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX5_B5_CTL (0x2D4)
+#define TAIKO_A_CDC_RX5_B5_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX6_B5_CTL (0x2DC)
+#define TAIKO_A_CDC_RX6_B5_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX7_B5_CTL (0x2E4)
+#define TAIKO_A_CDC_RX7_B5_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX1_B6_CTL (0x2B5)
+#define TAIKO_A_CDC_RX1_B6_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX2_B6_CTL (0x2BD)
+#define TAIKO_A_CDC_RX2_B6_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX3_B6_CTL (0x2C5)
+#define TAIKO_A_CDC_RX3_B6_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX4_B6_CTL (0x2CD)
+#define TAIKO_A_CDC_RX4_B6_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX5_B6_CTL (0x2D5)
+#define TAIKO_A_CDC_RX5_B6_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX6_B6_CTL (0x2DD)
+#define TAIKO_A_CDC_RX6_B6_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX7_B6_CTL (0x2E5)
+#define TAIKO_A_CDC_RX7_B6_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX1_VOL_CTL_B1_CTL (0x2B6)
+#define TAIKO_A_CDC_RX1_VOL_CTL_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX2_VOL_CTL_B1_CTL (0x2BE)
+#define TAIKO_A_CDC_RX2_VOL_CTL_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX3_VOL_CTL_B1_CTL (0x2C6)
+#define TAIKO_A_CDC_RX3_VOL_CTL_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX4_VOL_CTL_B1_CTL (0x2CE)
+#define TAIKO_A_CDC_RX4_VOL_CTL_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX5_VOL_CTL_B1_CTL (0x2D6)
+#define TAIKO_A_CDC_RX5_VOL_CTL_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX6_VOL_CTL_B1_CTL (0x2DE)
+#define TAIKO_A_CDC_RX6_VOL_CTL_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX7_VOL_CTL_B1_CTL (0x2E6)
+#define TAIKO_A_CDC_RX7_VOL_CTL_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL (0x2B7)
+#define TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL (0x2BF)
+#define TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL (0x2C7)
+#define TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL (0x2CF)
+#define TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL (0x2D7)
+#define TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL (0x2DF)
+#define TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL (0x2E7)
+#define TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_VBAT_CFG (0x2E8)
+#define TAIKO_A_CDC_VBAT_CFG__POR (0x1A)
+#define TAIKO_A_CDC_VBAT_ADC_CAL1 (0x2E9)
+#define TAIKO_A_CDC_VBAT_ADC_CAL1__POR (0x00)
+#define TAIKO_A_CDC_VBAT_ADC_CAL2 (0x2EA)
+#define TAIKO_A_CDC_VBAT_ADC_CAL2__POR (0x00)
+#define TAIKO_A_CDC_VBAT_ADC_CAL3 (0x2EB)
+#define TAIKO_A_CDC_VBAT_ADC_CAL3__POR (0x04)
+#define TAIKO_A_CDC_VBAT_PK_EST1 (0x2EC)
+#define TAIKO_A_CDC_VBAT_PK_EST1__POR (0xE0)
+#define TAIKO_A_CDC_VBAT_PK_EST2 (0x2ED)
+#define TAIKO_A_CDC_VBAT_PK_EST2__POR (0x01)
+#define TAIKO_A_CDC_VBAT_PK_EST3 (0x2EE)
+#define TAIKO_A_CDC_VBAT_PK_EST3__POR (0x40)
+#define TAIKO_A_CDC_VBAT_RF_PROC1 (0x2EF)
+#define TAIKO_A_CDC_VBAT_RF_PROC1__POR (0x2A)
+#define TAIKO_A_CDC_VBAT_RF_PROC2 (0x2F0)
+#define TAIKO_A_CDC_VBAT_RF_PROC2__POR (0x86)
+#define TAIKO_A_CDC_VBAT_TAC1 (0x2F1)
+#define TAIKO_A_CDC_VBAT_TAC1__POR (0x70)
+#define TAIKO_A_CDC_VBAT_TAC2 (0x2F2)
+#define TAIKO_A_CDC_VBAT_TAC2__POR (0x18)
+#define TAIKO_A_CDC_VBAT_TAC3 (0x2F3)
+#define TAIKO_A_CDC_VBAT_TAC3__POR (0x18)
+#define TAIKO_A_CDC_VBAT_TAC4 (0x2F4)
+#define TAIKO_A_CDC_VBAT_TAC4__POR (0x03)
+#define TAIKO_A_CDC_VBAT_GAIN_UPD1 (0x2F5)
+#define TAIKO_A_CDC_VBAT_GAIN_UPD1__POR (0x01)
+#define TAIKO_A_CDC_VBAT_GAIN_UPD2 (0x2F6)
+#define TAIKO_A_CDC_VBAT_GAIN_UPD2__POR (0x00)
+#define TAIKO_A_CDC_VBAT_GAIN_UPD3 (0x2F7)
+#define TAIKO_A_CDC_VBAT_GAIN_UPD3__POR (0x64)
+#define TAIKO_A_CDC_VBAT_GAIN_UPD4 (0x2F8)
+#define TAIKO_A_CDC_VBAT_GAIN_UPD4__POR (0x01)
+#define TAIKO_A_CDC_VBAT_DEBUG1 (0x2F9)
+#define TAIKO_A_CDC_VBAT_DEBUG1__POR (0x00)
+#define TAIKO_A_CDC_CLK_ANC_RESET_CTL (0x300)
+#define TAIKO_A_CDC_CLK_ANC_RESET_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_RX_RESET_CTL (0x301)
+#define TAIKO_A_CDC_CLK_RX_RESET_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_TX_RESET_B1_CTL (0x302)
+#define TAIKO_A_CDC_CLK_TX_RESET_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_TX_RESET_B2_CTL (0x303)
+#define TAIKO_A_CDC_CLK_TX_RESET_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_DMIC_B1_CTL (0x304)
+#define TAIKO_A_CDC_CLK_DMIC_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_DMIC_B2_CTL (0x305)
+#define TAIKO_A_CDC_CLK_DMIC_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_RX_I2S_CTL (0x306)
+#define TAIKO_A_CDC_CLK_RX_I2S_CTL__POR (0x03)
+#define TAIKO_A_CDC_CLK_TX_I2S_CTL (0x307)
+#define TAIKO_A_CDC_CLK_TX_I2S_CTL__POR (0x03)
+#define TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL (0x308)
+#define TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL (0x309)
+#define TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL (0x30A)
+#define TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL (0x30B)
+#define TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_OTHR_CTL (0x30C)
+#define TAIKO_A_CDC_CLK_OTHR_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL (0x30D)
+#define TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL (0x30E)
+#define TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_RX_B1_CTL (0x30F)
+#define TAIKO_A_CDC_CLK_RX_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_RX_B2_CTL (0x310)
+#define TAIKO_A_CDC_CLK_RX_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_MCLK_CTL (0x311)
+#define TAIKO_A_CDC_CLK_MCLK_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_PDM_CTL (0x312)
+#define TAIKO_A_CDC_CLK_PDM_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_SD_CTL (0x313)
+#define TAIKO_A_CDC_CLK_SD_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLK_POWER_CTL (0x314)
+#define TAIKO_A_CDC_CLK_POWER_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLSH_B1_CTL (0x320)
+#define TAIKO_A_CDC_CLSH_B1_CTL__POR (0xE4)
+#define TAIKO_A_CDC_CLSH_B2_CTL (0x321)
+#define TAIKO_A_CDC_CLSH_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLSH_B3_CTL (0x322)
+#define TAIKO_A_CDC_CLSH_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_CLSH_BUCK_NCP_VARS (0x323)
+#define TAIKO_A_CDC_CLSH_BUCK_NCP_VARS__POR (0x00)
+#define TAIKO_A_CDC_CLSH_IDLE_HPH_THSD (0x324)
+#define TAIKO_A_CDC_CLSH_IDLE_HPH_THSD__POR (0x12)
+#define TAIKO_A_CDC_CLSH_IDLE_EAR_THSD (0x325)
+#define TAIKO_A_CDC_CLSH_IDLE_EAR_THSD__POR (0x0C)
+#define TAIKO_A_CDC_CLSH_FCLKONLY_HPH_THSD (0x326)
+#define TAIKO_A_CDC_CLSH_FCLKONLY_HPH_THSD__POR (0x18)
+#define TAIKO_A_CDC_CLSH_FCLKONLY_EAR_THSD (0x327)
+#define TAIKO_A_CDC_CLSH_FCLKONLY_EAR_THSD__POR (0x23)
+#define TAIKO_A_CDC_CLSH_K_ADDR (0x328)
+#define TAIKO_A_CDC_CLSH_K_ADDR__POR (0x00)
+#define TAIKO_A_CDC_CLSH_K_DATA (0x329)
+#define TAIKO_A_CDC_CLSH_K_DATA__POR (0xA4)
+#define TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_L (0x32A)
+#define TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_L__POR (0xD7)
+#define TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_U (0x32B)
+#define TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_U__POR (0x05)
+#define TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_L (0x32C)
+#define TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_L__POR (0x60)
+#define TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_U (0x32D)
+#define TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_U__POR (0x09)
+#define TAIKO_A_CDC_CLSH_V_PA_HD_EAR (0x32E)
+#define TAIKO_A_CDC_CLSH_V_PA_HD_EAR__POR (0x00)
+#define TAIKO_A_CDC_CLSH_V_PA_HD_HPH (0x32F)
+#define TAIKO_A_CDC_CLSH_V_PA_HD_HPH__POR (0x00)
+#define TAIKO_A_CDC_CLSH_V_PA_MIN_EAR (0x330)
+#define TAIKO_A_CDC_CLSH_V_PA_MIN_EAR__POR (0x00)
+#define TAIKO_A_CDC_CLSH_V_PA_MIN_HPH (0x331)
+#define TAIKO_A_CDC_CLSH_V_PA_MIN_HPH__POR (0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_B1_CTL (0x340)
+#define TAIKO_A_CDC_IIR1_GAIN_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_B1_CTL (0x350)
+#define TAIKO_A_CDC_IIR2_GAIN_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_B2_CTL (0x341)
+#define TAIKO_A_CDC_IIR1_GAIN_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_B2_CTL (0x351)
+#define TAIKO_A_CDC_IIR2_GAIN_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_B3_CTL (0x342)
+#define TAIKO_A_CDC_IIR1_GAIN_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_B3_CTL (0x352)
+#define TAIKO_A_CDC_IIR2_GAIN_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_B4_CTL (0x343)
+#define TAIKO_A_CDC_IIR1_GAIN_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_B4_CTL (0x353)
+#define TAIKO_A_CDC_IIR2_GAIN_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_B5_CTL (0x344)
+#define TAIKO_A_CDC_IIR1_GAIN_B5_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_B5_CTL (0x354)
+#define TAIKO_A_CDC_IIR2_GAIN_B5_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_B6_CTL (0x345)
+#define TAIKO_A_CDC_IIR1_GAIN_B6_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_B6_CTL (0x355)
+#define TAIKO_A_CDC_IIR2_GAIN_B6_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_B7_CTL (0x346)
+#define TAIKO_A_CDC_IIR1_GAIN_B7_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_B7_CTL (0x356)
+#define TAIKO_A_CDC_IIR2_GAIN_B7_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_B8_CTL (0x347)
+#define TAIKO_A_CDC_IIR1_GAIN_B8_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_B8_CTL (0x357)
+#define TAIKO_A_CDC_IIR2_GAIN_B8_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR1_CTL (0x348)
+#define TAIKO_A_CDC_IIR1_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR2_CTL (0x358)
+#define TAIKO_A_CDC_IIR2_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR1_GAIN_TIMER_CTL (0x349)
+#define TAIKO_A_CDC_IIR1_GAIN_TIMER_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR2_GAIN_TIMER_CTL (0x359)
+#define TAIKO_A_CDC_IIR2_GAIN_TIMER_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR1_COEF_B1_CTL (0x34A)
+#define TAIKO_A_CDC_IIR1_COEF_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR2_COEF_B1_CTL (0x35A)
+#define TAIKO_A_CDC_IIR2_COEF_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR1_COEF_B2_CTL (0x34B)
+#define TAIKO_A_CDC_IIR1_COEF_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_IIR2_COEF_B2_CTL (0x35B)
+#define TAIKO_A_CDC_IIR2_COEF_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_TOP_GAIN_UPDATE (0x360)
+#define TAIKO_A_CDC_TOP_GAIN_UPDATE__POR (0x00)
+#define TAIKO_A_CDC_COMP0_B1_CTL (0x368)
+#define TAIKO_A_CDC_COMP0_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP1_B1_CTL (0x370)
+#define TAIKO_A_CDC_COMP1_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP2_B1_CTL (0x378)
+#define TAIKO_A_CDC_COMP2_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP0_B2_CTL (0x369)
+#define TAIKO_A_CDC_COMP0_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP1_B2_CTL (0x371)
+#define TAIKO_A_CDC_COMP1_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP2_B2_CTL (0x379)
+#define TAIKO_A_CDC_COMP2_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP0_B3_CTL (0x36A)
+#define TAIKO_A_CDC_COMP0_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP1_B3_CTL (0x372)
+#define TAIKO_A_CDC_COMP1_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP2_B3_CTL (0x37A)
+#define TAIKO_A_CDC_COMP2_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP0_B4_CTL (0x36B)
+#define TAIKO_A_CDC_COMP0_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP1_B4_CTL (0x373)
+#define TAIKO_A_CDC_COMP1_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP2_B4_CTL (0x37B)
+#define TAIKO_A_CDC_COMP2_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP0_B5_CTL (0x36C)
+#define TAIKO_A_CDC_COMP0_B5_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP1_B5_CTL (0x374)
+#define TAIKO_A_CDC_COMP1_B5_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP2_B5_CTL (0x37C)
+#define TAIKO_A_CDC_COMP2_B5_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP0_B6_CTL (0x36D)
+#define TAIKO_A_CDC_COMP0_B6_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP1_B6_CTL (0x375)
+#define TAIKO_A_CDC_COMP1_B6_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP2_B6_CTL (0x37D)
+#define TAIKO_A_CDC_COMP2_B6_CTL__POR (0x00)
+#define TAIKO_A_CDC_COMP0_SHUT_DOWN_STATUS (0x36E)
+#define TAIKO_A_CDC_COMP0_SHUT_DOWN_STATUS__POR (0x00)
+#define TAIKO_A_CDC_COMP1_SHUT_DOWN_STATUS (0x376)
+#define TAIKO_A_CDC_COMP1_SHUT_DOWN_STATUS__POR (0x00)
+#define TAIKO_A_CDC_COMP2_SHUT_DOWN_STATUS (0x37E)
+#define TAIKO_A_CDC_COMP2_SHUT_DOWN_STATUS__POR (0x00)
+#define TAIKO_A_CDC_COMP0_FS_CFG (0x36F)
+#define TAIKO_A_CDC_COMP0_FS_CFG__POR (0x00)
+#define TAIKO_A_CDC_COMP1_FS_CFG (0x377)
+#define TAIKO_A_CDC_COMP1_FS_CFG__POR (0x00)
+#define TAIKO_A_CDC_COMP2_FS_CFG (0x37F)
+#define TAIKO_A_CDC_COMP2_FS_CFG__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX1_B1_CTL (0x380)
+#define TAIKO_A_CDC_CONN_RX1_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX1_B2_CTL (0x381)
+#define TAIKO_A_CDC_CONN_RX1_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX1_B3_CTL (0x382)
+#define TAIKO_A_CDC_CONN_RX1_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX2_B1_CTL (0x383)
+#define TAIKO_A_CDC_CONN_RX2_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX2_B2_CTL (0x384)
+#define TAIKO_A_CDC_CONN_RX2_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX2_B3_CTL (0x385)
+#define TAIKO_A_CDC_CONN_RX2_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX3_B1_CTL (0x386)
+#define TAIKO_A_CDC_CONN_RX3_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX3_B2_CTL (0x387)
+#define TAIKO_A_CDC_CONN_RX3_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX4_B1_CTL (0x388)
+#define TAIKO_A_CDC_CONN_RX4_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX4_B2_CTL (0x389)
+#define TAIKO_A_CDC_CONN_RX4_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX5_B1_CTL (0x38A)
+#define TAIKO_A_CDC_CONN_RX5_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX5_B2_CTL (0x38B)
+#define TAIKO_A_CDC_CONN_RX5_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX6_B1_CTL (0x38C)
+#define TAIKO_A_CDC_CONN_RX6_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX6_B2_CTL (0x38D)
+#define TAIKO_A_CDC_CONN_RX6_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX7_B1_CTL (0x38E)
+#define TAIKO_A_CDC_CONN_RX7_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX7_B2_CTL (0x38F)
+#define TAIKO_A_CDC_CONN_RX7_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX7_B3_CTL (0x390)
+#define TAIKO_A_CDC_CONN_RX7_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_ANC_B1_CTL (0x391)
+#define TAIKO_A_CDC_CONN_ANC_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_ANC_B2_CTL (0x392)
+#define TAIKO_A_CDC_CONN_ANC_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_TX_B1_CTL (0x393)
+#define TAIKO_A_CDC_CONN_TX_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_TX_B2_CTL (0x394)
+#define TAIKO_A_CDC_CONN_TX_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_TX_B3_CTL (0x395)
+#define TAIKO_A_CDC_CONN_TX_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_TX_B4_CTL (0x396)
+#define TAIKO_A_CDC_CONN_TX_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_EQ1_B1_CTL (0x397)
+#define TAIKO_A_CDC_CONN_EQ1_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_EQ1_B2_CTL (0x398)
+#define TAIKO_A_CDC_CONN_EQ1_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_EQ1_B3_CTL (0x399)
+#define TAIKO_A_CDC_CONN_EQ1_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_EQ1_B4_CTL (0x39A)
+#define TAIKO_A_CDC_CONN_EQ1_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_EQ2_B1_CTL (0x39B)
+#define TAIKO_A_CDC_CONN_EQ2_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_EQ2_B2_CTL (0x39C)
+#define TAIKO_A_CDC_CONN_EQ2_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_EQ2_B3_CTL (0x39D)
+#define TAIKO_A_CDC_CONN_EQ2_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_EQ2_B4_CTL (0x39E)
+#define TAIKO_A_CDC_CONN_EQ2_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_SRC1_B1_CTL (0x39F)
+#define TAIKO_A_CDC_CONN_SRC1_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_SRC1_B2_CTL (0x3A0)
+#define TAIKO_A_CDC_CONN_SRC1_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_SRC2_B1_CTL (0x3A1)
+#define TAIKO_A_CDC_CONN_SRC2_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_SRC2_B2_CTL (0x3A2)
+#define TAIKO_A_CDC_CONN_SRC2_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B1_CTL (0x3A3)
+#define TAIKO_A_CDC_CONN_TX_SB_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B2_CTL (0x3A4)
+#define TAIKO_A_CDC_CONN_TX_SB_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B3_CTL (0x3A5)
+#define TAIKO_A_CDC_CONN_TX_SB_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B4_CTL (0x3A6)
+#define TAIKO_A_CDC_CONN_TX_SB_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B5_CTL (0x3A7)
+#define TAIKO_A_CDC_CONN_TX_SB_B5_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B6_CTL (0x3A8)
+#define TAIKO_A_CDC_CONN_TX_SB_B6_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B7_CTL (0x3A9)
+#define TAIKO_A_CDC_CONN_TX_SB_B7_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B8_CTL (0x3AA)
+#define TAIKO_A_CDC_CONN_TX_SB_B8_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B9_CTL (0x3AB)
+#define TAIKO_A_CDC_CONN_TX_SB_B9_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B10_CTL (0x3AC)
+#define TAIKO_A_CDC_CONN_TX_SB_B10_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_TX_SB_B11_CTL (0x3AD)
+#define TAIKO_A_CDC_CONN_TX_SB_B11_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX_SB_B1_CTL (0x3AE)
+#define TAIKO_A_CDC_CONN_RX_SB_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_RX_SB_B2_CTL (0x3AF)
+#define TAIKO_A_CDC_CONN_RX_SB_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_CLSH_CTL (0x3B0)
+#define TAIKO_A_CDC_CONN_CLSH_CTL__POR (0x00)
+#define TAIKO_A_CDC_CONN_MISC (0x3B1)
+#define TAIKO_A_CDC_CONN_MISC__POR (0x01)
+#define TAIKO_A_CDC_CONN_MAD (0x3B2)
+#define TAIKO_A_CDC_CONN_MAD__POR (0x01)
+#define TAIKO_A_CDC_MBHC_EN_CTL (0x3C0)
+#define TAIKO_A_CDC_MBHC_EN_CTL__POR (0x00)
+#define TAIKO_A_CDC_MBHC_FIR_B1_CFG (0x3C1)
+#define TAIKO_A_CDC_MBHC_FIR_B1_CFG__POR (0x00)
+#define TAIKO_A_CDC_MBHC_FIR_B2_CFG (0x3C2)
+#define TAIKO_A_CDC_MBHC_FIR_B2_CFG__POR (0x06)
+#define TAIKO_A_CDC_MBHC_TIMER_B1_CTL (0x3C3)
+#define TAIKO_A_CDC_MBHC_TIMER_B1_CTL__POR (0x03)
+#define TAIKO_A_CDC_MBHC_TIMER_B2_CTL (0x3C4)
+#define TAIKO_A_CDC_MBHC_TIMER_B2_CTL__POR (0x09)
+#define TAIKO_A_CDC_MBHC_TIMER_B3_CTL (0x3C5)
+#define TAIKO_A_CDC_MBHC_TIMER_B3_CTL__POR (0x1E)
+#define TAIKO_A_CDC_MBHC_TIMER_B4_CTL (0x3C6)
+#define TAIKO_A_CDC_MBHC_TIMER_B4_CTL__POR (0x45)
+#define TAIKO_A_CDC_MBHC_TIMER_B5_CTL (0x3C7)
+#define TAIKO_A_CDC_MBHC_TIMER_B5_CTL__POR (0x04)
+#define TAIKO_A_CDC_MBHC_TIMER_B6_CTL (0x3C8)
+#define TAIKO_A_CDC_MBHC_TIMER_B6_CTL__POR (0x78)
+#define TAIKO_A_CDC_MBHC_B1_STATUS (0x3C9)
+#define TAIKO_A_CDC_MBHC_B1_STATUS__POR (0x00)
+#define TAIKO_A_CDC_MBHC_B2_STATUS (0x3CA)
+#define TAIKO_A_CDC_MBHC_B2_STATUS__POR (0x00)
+#define TAIKO_A_CDC_MBHC_B3_STATUS (0x3CB)
+#define TAIKO_A_CDC_MBHC_B3_STATUS__POR (0x00)
+#define TAIKO_A_CDC_MBHC_B4_STATUS (0x3CC)
+#define TAIKO_A_CDC_MBHC_B4_STATUS__POR (0x00)
+#define TAIKO_A_CDC_MBHC_B5_STATUS (0x3CD)
+#define TAIKO_A_CDC_MBHC_B5_STATUS__POR (0x00)
+#define TAIKO_A_CDC_MBHC_B1_CTL (0x3CE)
+#define TAIKO_A_CDC_MBHC_B1_CTL__POR (0xC0)
+#define TAIKO_A_CDC_MBHC_B2_CTL (0x3CF)
+#define TAIKO_A_CDC_MBHC_B2_CTL__POR (0x5D)
+#define TAIKO_A_CDC_MBHC_VOLT_B1_CTL (0x3D0)
+#define TAIKO_A_CDC_MBHC_VOLT_B1_CTL__POR (0x00)
+#define TAIKO_A_CDC_MBHC_VOLT_B2_CTL (0x3D1)
+#define TAIKO_A_CDC_MBHC_VOLT_B2_CTL__POR (0x00)
+#define TAIKO_A_CDC_MBHC_VOLT_B3_CTL (0x3D2)
+#define TAIKO_A_CDC_MBHC_VOLT_B3_CTL__POR (0x00)
+#define TAIKO_A_CDC_MBHC_VOLT_B4_CTL (0x3D3)
+#define TAIKO_A_CDC_MBHC_VOLT_B4_CTL__POR (0x00)
+#define TAIKO_A_CDC_MBHC_VOLT_B5_CTL (0x3D4)
+#define TAIKO_A_CDC_MBHC_VOLT_B5_CTL__POR (0x00)
+#define TAIKO_A_CDC_MBHC_VOLT_B6_CTL (0x3D5)
+#define TAIKO_A_CDC_MBHC_VOLT_B6_CTL__POR (0x00)
+#define TAIKO_A_CDC_MBHC_VOLT_B7_CTL (0x3D6)
+#define TAIKO_A_CDC_MBHC_VOLT_B7_CTL__POR (0xFF)
+#define TAIKO_A_CDC_MBHC_VOLT_B8_CTL (0x3D7)
+#define TAIKO_A_CDC_MBHC_VOLT_B8_CTL__POR (0x07)
+#define TAIKO_A_CDC_MBHC_VOLT_B9_CTL (0x3D8)
+#define TAIKO_A_CDC_MBHC_VOLT_B9_CTL__POR (0xFF)
+#define TAIKO_A_CDC_MBHC_VOLT_B10_CTL (0x3D9)
+#define TAIKO_A_CDC_MBHC_VOLT_B10_CTL__POR (0x7F)
+#define TAIKO_A_CDC_MBHC_VOLT_B11_CTL (0x3DA)
+#define TAIKO_A_CDC_MBHC_VOLT_B11_CTL__POR (0x00)
+#define TAIKO_A_CDC_MBHC_VOLT_B12_CTL (0x3DB)
+#define TAIKO_A_CDC_MBHC_VOLT_B12_CTL__POR (0x80)
+#define TAIKO_A_CDC_MBHC_CLK_CTL (0x3DC)
+#define TAIKO_A_CDC_MBHC_CLK_CTL__POR (0x00)
+#define TAIKO_A_CDC_MBHC_INT_CTL (0x3DD)
+#define TAIKO_A_CDC_MBHC_INT_CTL__POR (0x00)
+#define TAIKO_A_CDC_MBHC_DEBUG_CTL (0x3DE)
+#define TAIKO_A_CDC_MBHC_DEBUG_CTL__POR (0x00)
+#define TAIKO_A_CDC_MBHC_SPARE (0x3DF)
+#define TAIKO_A_CDC_MBHC_SPARE__POR (0x00)
+#define TAIKO_A_CDC_MAD_MAIN_CTL_1 (0x3E0)
+#define TAIKO_A_CDC_MAD_MAIN_CTL_1__POR (0x00)
+#define TAIKO_A_CDC_MAD_MAIN_CTL_2 (0x3E1)
+#define TAIKO_A_CDC_MAD_MAIN_CTL_2__POR (0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_1 (0x3E2)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_1__POR (0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_2 (0x3E3)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_2__POR (0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_3 (0x3E4)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_3__POR (0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_4 (0x3E5)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_4__POR (0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_5 (0x3E6)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_5__POR (0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_6 (0x3E7)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_6__POR (0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_7 (0x3E8)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_7__POR (0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_8 (0x3E9)
+#define TAIKO_A_CDC_MAD_AUDIO_CTL_8__POR (0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_PTR (0x3EA)
+#define TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_PTR__POR (0x00)
+#define TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_VAL (0x3EB)
+#define TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_VAL__POR (0x40)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_1 (0x3EC)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_1__POR (0x00)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_2 (0x3ED)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_2__POR (0x00)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_3 (0x3EE)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_3__POR (0x00)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_4 (0x3EF)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_4__POR (0x00)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_5 (0x3F0)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_5__POR (0x00)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_6 (0x3F1)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_6__POR (0x00)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_7 (0x3F2)
+#define TAIKO_A_CDC_MAD_ULTR_CTL_7__POR (0x00)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_1 (0x3F3)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_1__POR (0x00)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_2 (0x3F4)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_2__POR (0x00)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_3 (0x3F5)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_3__POR (0x00)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_4 (0x3F6)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_4__POR (0x00)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_5 (0x3F7)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_5__POR (0x00)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_6 (0x3F8)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_6__POR (0x00)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_7 (0x3F9)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_7__POR (0x00)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_8 (0x3FA)
+#define TAIKO_A_CDC_MAD_BEACON_CTL_8__POR (0x00)
+#define TAIKO_A_CDC_MAD_BEACON_IIR_CTL_PTR (0x3FB)
+#define TAIKO_A_CDC_MAD_BEACON_IIR_CTL_PTR__POR (0x00)
+#define TAIKO_A_CDC_MAD_BEACON_IIR_CTL_VAL (0x3FC)
+#define TAIKO_A_CDC_MAD_BEACON_IIR_CTL_VAL__POR (0x00)
+
+
+/* SLIMBUS Slave Registers */
+#define TAIKO_SLIM_PGD_PORT_INT_EN0 (0x30)
+#define TAIKO_SLIM_PGD_PORT_INT_STATUS0 (0x34)
+#define TAIKO_SLIM_PGD_PORT_INT_CLR0 (0x38)
+#define TAIKO_SLIM_PGD_PORT_INT_SOURCE0 (0x60)
+
+/* Macros for Packing Register Writes into a U32 */
+#define TAIKO_PACKED_REG_SIZE sizeof(u32)
+
+#define TAIKO_CODEC_PACK_ENTRY(reg, mask, val) ((val & 0xff)|\
+ ((mask & 0xff) << 8)|((reg & 0xffff) << 16))
+
+#define TAIKO_CODEC_UNPACK_ENTRY(packed, reg, mask, val) \
+ do { \
+ ((reg) = ((packed >> 16) & (0xffff))); \
+ ((mask) = ((packed >> 8) & (0xff))); \
+ ((val) = ((packed) & (0xff))); \
+ } while (0);
+
+#endif
diff --git a/include/linux/msm_ipc.h b/include/linux/msm_ipc.h
index 82f76a6..44fa8eb 100644
--- a/include/linux/msm_ipc.h
+++ b/include/linux/msm_ipc.h
@@ -62,12 +62,19 @@
#define IPC_ROUTER_IOCTL_BIND_CONTROL_PORT \
_IOR(IPC_ROUTER_IOCTL_MAGIC, 4, unsigned int)
+struct msm_ipc_server_info {
+ uint32_t node_id;
+ uint32_t port_id;
+ uint32_t service;
+ uint32_t instance;
+};
+
struct server_lookup_args {
struct msm_ipc_port_name port_name;
int num_entries_in_array;
int num_entries_found;
uint32_t lookup_mask;
- struct msm_ipc_port_addr port_addr[0];
+ struct msm_ipc_server_info srv_info[0];
};
#endif
diff --git a/include/linux/tzcom.h b/include/linux/tzcom.h
deleted file mode 100644
index 448ab2a..0000000
--- a/include/linux/tzcom.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Qualcomm TrustZone communicator API */
-
-#ifndef __TZCOM_H_
-#define __TZCOM_H_
-
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-#define MAX_ION_FD 4
-/**
- * struct tzcom_register_svc_op_req - for register service ioctl request
- * @svc_id - service id (shared between userspace and TZ)
- * @cmd_id_low - low number in cmd_id range (shared between userspace and TZ)
- * @cmd_id_high - high number in cmd_id range (shared between userspace and TZ)
- * @instance_id - unique id for the given service generated by tzcom driver
- */
-struct tzcom_register_svc_op_req {
- uint32_t svc_id; /* in */
- uint32_t cmd_id_low; /* in */
- uint32_t cmd_id_high; /* in */
- uint32_t instance_id; /* out */
-};
-
-/**
- * struct tzcom_unregister_svc_op_req - for unregister service ioctl request
- * @svc_id - service id to unregister (provided in register_service request)
- * @instance_id - instance id generated in register service request
- */
-struct tzcom_unregister_svc_op_req {
- uint32_t svc_id; /* in */
- uint32_t instance_id; /* in */
-};
-
-/**
- * struct tzcom_next_cmd_op_req - for read next command ioctl request
- * @svc_id - has to be a registered svc_id (see @tzcom_register_svc_op_req)
- * @instance_id - unique id for the given service (see @tzcom_register_svc_op_req)
- * @cmd_id - command to execute on the given service, received from TZ
- * @req_len - request buffer length, received from TZ
- * @req - request buffer, received from TZ
- */
-struct tzcom_next_cmd_op_req {
- uint32_t svc_id; /* in */
- uint32_t instance_id; /* in */
- uint32_t cmd_id; /* out */
- unsigned int req_len; /* in/out */
- void *req_buf; /* in/out */
-};
-
-/**
- * struct tzcom_send_cmd_op_req - for send command ioctl request
- * @cmd_id - command to execute on TZBSP side
- * @ifd_data_fd - ion handle to some memory allocated in user space
- * @cmd_buf_offset - command buffer offset
- * @cmd_len - command buffer length
- * @cmd_buf - command buffer
- * @resp_len - response buffer length
- * @resp_buf - response buffer
- */
-struct tzcom_send_cmd_op_req {
- uint32_t cmd_id; /* in */
- unsigned int cmd_len; /* in */
- void *cmd_buf; /* in */
- unsigned int resp_len; /* in/out */
- void *resp_buf; /* in/out */
-};
-
-/**
- * struct tzcom_ion_fd_info - ion fd handle data information
- * @fd - ion handle to some memory allocated in user space
- * @cmd_buf_offset - command buffer offset
- */
-struct tzcom_ion_fd_info {
- int32_t fd;
- uint32_t cmd_buf_offset;
-};
-
-/**
- * struct tzcom_send_cmd_op_req - for send command ioctl request
- * @cmd_id - command to execute on TZBSP side
- * @ifd_data_fd - ion handle to some memory allocated in user space
- * @cmd_buf_offset - command buffer offset
- * @cmd_len - command buffer length
- * @cmd_buf - command buffer
- * @resp_len - response buffer length
- * @resp_buf - response buffer
- */
-struct tzcom_send_cmd_fd_op_req {
- uint32_t cmd_id; /* in */
- struct tzcom_ion_fd_info ifd_data[MAX_ION_FD];
- unsigned int cmd_len; /* in */
- void *cmd_buf; /* in */
- unsigned int resp_len; /* in/out */
- void *resp_buf; /* in/out */
-};
-/**
- * struct tzcom_cont_cmd_op_req - for continue command ioctl request. used
- * as a trigger from HLOS service to notify TZCOM that it's done with its
- * operation and provide the response for TZCOM can continue the incomplete
- * command execution
- * @cmd_id - Command to continue filled in by tzcom as tzcom knows about the
- * last incomplete command.
- * @instance_id - Instance id of the svc
- * @resp_len - Length of the response
- * @resp_buf - Response buffer where the response of the cmd should go.
- */
-struct tzcom_cont_cmd_op_req {
- uint32_t cmd_id; /* out */
- uint32_t instance_id; /* in */
- unsigned int resp_len; /* in */
- void *resp_buf; /* in */
-};
-
-#define TZCOM_IOC_MAGIC 0x97
-
-/* For HLOS service */
-#define TZCOM_IOCTL_REGISTER_SERVICE_REQ \
- _IOWR(TZCOM_IOC_MAGIC, 1, struct tzcom_register_svc_op_req)
-/* For HLOS service */
-#define TZCOM_IOCTL_UNREGISTER_SERVICE_REQ \
- _IOWR(TZCOM_IOC_MAGIC, 2, struct tzcom_unregister_svc_op_req)
-/* For TZ service */
-#define TZCOM_IOCTL_SEND_CMD_REQ \
- _IOWR(TZCOM_IOC_MAGIC, 3, struct tzcom_send_cmd_op_req)
-/* For HLOS service */
-#define TZCOM_IOCTL_READ_NEXT_CMD_REQ \
- _IOWR(TZCOM_IOC_MAGIC, 4, struct tzcom_next_cmd_op_req)
-/* For TZ service */
-#define TZCOM_IOCTL_CONTINUE_CMD_REQ \
- _IOWR(TZCOM_IOC_MAGIC, 5, struct tzcom_cont_cmd_op_req)
-
-#define TZCOM_IOCTL_ABORT_REQ _IO(TZCOM_IOC_MAGIC, 6)
-/* For TZ service */
-#define TZCOM_IOCTL_SEND_CMD_FD_REQ \
- _IOWR(TZCOM_IOC_MAGIC, 7, struct tzcom_send_cmd_fd_op_req)
-#endif /* __TZCOM_H_ */
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 6d72470..bcd0afb 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -605,6 +605,7 @@
struct ion_allocation_data ion_alloc;
struct ion_fd_data fd_data;
+ int ion_dev_fd;
};
enum msm_st_frame_packing {
@@ -1450,25 +1451,33 @@
#define QCAMERA_VNODE_GROUP_ID 2
#define MSM_CAM_V4L2_IOCTL_GET_CAMERA_INFO \
- _IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct msm_camera_v4l2_ioctl_t *)
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct msm_camera_v4l2_ioctl_t)
#define MSM_CAM_V4L2_IOCTL_GET_CONFIG_INFO \
- _IOWR('V', BASE_VIDIOC_PRIVATE + 2, struct msm_camera_v4l2_ioctl_t *)
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 2, struct msm_camera_v4l2_ioctl_t)
#define MSM_CAM_V4L2_IOCTL_GET_MCTL_INFO \
- _IOWR('V', BASE_VIDIOC_PRIVATE + 3, struct msm_camera_v4l2_ioctl_t *)
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 3, struct msm_camera_v4l2_ioctl_t)
#define MSM_CAM_V4L2_IOCTL_CTRL_CMD_DONE \
- _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct msm_camera_v4l2_ioctl_t *)
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 4, struct msm_camera_v4l2_ioctl_t)
#define MSM_CAM_V4L2_IOCTL_GET_EVENT_PAYLOAD \
- _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct msm_camera_v4l2_ioctl_t *)
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 5, struct msm_camera_v4l2_ioctl_t)
#define MSM_CAM_IOCTL_SEND_EVENT \
_IOWR('V', BASE_VIDIOC_PRIVATE + 6, struct v4l2_event)
+#define MSM_CAM_V4L2_IOCTL_CFG_VPE \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 7, struct msm_vpe_cfg_cmd)
+
+#define MSM_CAM_V4L2_IOCTL_PRIVATE_S_CTRL \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 8, struct msm_camera_v4l2_ioctl_t)
+
struct msm_camera_v4l2_ioctl_t {
+ uint32_t id;
void __user *ioctl_ptr;
+ uint32_t len;
};
#endif /* __LINUX_MSM_CAMERA_H */
diff --git a/include/media/vcap_fmt.h b/include/media/vcap_fmt.h
index 51b45ac..92240bf1 100644
--- a/include/media/vcap_fmt.h
+++ b/include/media/vcap_fmt.h
@@ -15,7 +15,19 @@
#define VCAP_FMT_H
#define V4L2_BUF_TYPE_INTERLACED_IN_DECODER (V4L2_BUF_TYPE_PRIVATE)
-#define V4L2_BUF_TYPE_VP_OUT (V4L2_BUF_TYPE_PRIVATE + 1)
+
+#define VCAP_GENERIC_NOTIFY_EVENT 0
+#define VCAP_VC_PIX_ERR_EVENT 1
+#define VCAP_VC_LINE_ERR_EVENT 2
+#define VCAP_VC_VSYNC_ERR_EVENT 3
+#define VCAP_VC_NPL_OFLOW_ERR_EVENT 4
+#define VCAP_VC_LBUF_OFLOW_ERR_EVENT 5
+#define VCAP_VC_BUF_OVERWRITE_EVENT 6
+#define VCAP_VP_REG_R_ERR_EVENT 7
+#define VCAP_VP_REG_W_ERR_EVENT 8
+#define VCAP_VP_IN_HEIGHT_ERR_EVENT 9
+#define VCAP_VP_IN_WIDTH_ERR_EVENT 10
+#define VCAP_MAX_NOTIFY_EVENT 11
enum hal_vcap_mode {
HAL_VCAP_MODE_PRO = 0,
@@ -39,7 +51,8 @@
enum hal_vcap_polar d_polar;
enum hal_vcap_color color_space;
- float clk_freq;
+ uint32_t clk_freq;
+ uint32_t frame_rate;
uint32_t vtotal;
uint32_t htotal;
uint32_t hactive_start;
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index 374e681..045c107 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -29,6 +29,8 @@
#include <media/vcap_fmt.h>
#include <mach/board.h>
+#define to_client_data(val) container_of(val, struct vcap_client_data, vfh)
+
#define writel_iowmb(val, addr) \
do { \
__iowmb(); \
@@ -146,6 +148,7 @@
struct clk *vcap_clk;
struct clk *vcap_p_clk;
struct clk *vcap_npl_clk;
+ struct device *ddev;
/*struct platform_device *pdev;*/
uint32_t bus_client_handle;
@@ -156,8 +159,10 @@
atomic_t vc_enabled;
atomic_t vp_enabled;
- atomic_t vc_resource;
- atomic_t vp_resource;
+ spinlock_t dev_slock;
+ atomic_t open_clients;
+ bool vc_resource;
+ bool vp_resource;
struct workqueue_struct *vcap_wq;
struct vp_work_t vp_work;
@@ -204,6 +209,8 @@
spinlock_t cap_slock;
bool streaming;
+
+ struct v4l2_fh vfh;
};
struct vcap_hacked_vals {
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 7719b82..980b846 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -59,10 +59,11 @@
#include <net/bluetooth/amp.h>
bool disable_ertm;
+bool enable_hs;
bool enable_reconfig;
static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
-static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP | L2CAP_FC_A2MP, };
+static u8 l2cap_fc_mask = L2CAP_FC_L2CAP;
struct workqueue_struct *_l2cap_wq;
@@ -754,6 +755,7 @@
if (l2cap_pi(sk)->amp_pref ==
BT_AMP_POLICY_PREFER_AMP &&
+ enable_hs &&
conn->fc_mask & L2CAP_FC_A2MP)
amp_create_physical(conn, sk);
else
@@ -862,6 +864,7 @@
if (l2cap_pi(sk)->amp_pref ==
BT_AMP_POLICY_PREFER_AMP &&
+ enable_hs &&
conn->fc_mask & L2CAP_FC_A2MP)
amp_create_physical(conn, sk);
else
@@ -2723,7 +2726,7 @@
if (!l2cap_pi(sk)->conn)
return;
- if (!(l2cap_pi(sk)->conn->fc_mask & L2CAP_FC_A2MP))
+ if (!(l2cap_pi(sk)->conn->fc_mask & L2CAP_FC_A2MP) || !enable_hs)
return;
if (l2cap_pi(sk)->amp_id == 0) {
@@ -4654,10 +4657,14 @@
L2CAP_INFO_RSP, sizeof(buf), buf);
} else if (type == L2CAP_IT_FIXED_CHAN) {
u8 buf[12];
+ u8 fc_mask = l2cap_fc_mask;
struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
- memcpy(buf + 4, l2cap_fixed_chan, 8);
+ if (enable_hs)
+ fc_mask |= L2CAP_FC_A2MP;
+ memset(rsp->data, 0, 8);
+ rsp->data[0] = fc_mask;
l2cap_send_cmd(conn, cmd->ident,
L2CAP_INFO_RSP, sizeof(buf), buf);
} else {
@@ -7367,7 +7374,7 @@
l2cap_data_channel(sk, skb);
bh_unlock_sock(sk);
- } else if (cid == L2CAP_CID_A2MP) {
+ } else if ((cid == L2CAP_CID_A2MP) && enable_hs) {
BT_DBG("A2MP");
amp_conn_ind(conn->hcon, skb);
} else {
@@ -7522,8 +7529,9 @@
if (!status) {
l2cap_pi(sk)->conf_state |=
L2CAP_CONF_CONNECT_PEND;
- if (l2cap_pi(sk)->amp_pref ==
- BT_AMP_POLICY_PREFER_AMP) {
+ if ((l2cap_pi(sk)->amp_pref ==
+ BT_AMP_POLICY_PREFER_AMP) &&
+ enable_hs) {
amp_create_physical(l2cap_pi(sk)->conn,
sk);
} else
@@ -7825,5 +7833,8 @@
module_param(disable_ertm, bool, 0644);
MODULE_PARM_DESC(disable_ertm, "Disable enhanced retransmission mode");
+module_param(enable_hs, bool, 0644);
+MODULE_PARM_DESC(enable_hs, "Enable A2MP protocol");
+
module_param(enable_reconfig, bool, 0644);
MODULE_PARM_DESC(enable_reconfig, "Enable reconfig after initiating AMP move");
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 77a6dd9..deb67f5 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1634,7 +1634,8 @@
$exec_file =~ /^Kconfig$/) &&
$rawline =~ /^new (file )?mode\s([0-9]+)$/ &&
(oct($2) & 0111)) {
- ERROR("Source file has +x permissions: " .
+ ERROR("EXECUTE_PERMISSIONS",
+ "Source file has +x permissions: " .
"$exec_file\n");
}
$here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
@@ -1647,7 +1648,8 @@
if ($shorttext == IN_SHORTTEXT_BLANKLINE && $line=~/\S/) {
# the subject line was just processed,
# a blank line must be next
- WARN("non-blank line after summary line\n" . $herecurr);
+ WARN("NONBLANK_AFTER_SUMMARY",
+ "non-blank line after summary line\n" . $herecurr);
$shorttext = IN_SHORTTEXT;
# this non-blank line may or may not be commit text -
# a warning has been generated so assume it is commit
@@ -1658,7 +1660,8 @@
if ($shorttext == IN_SHORTTEXT) {
if ($line=~/^---/ || $line=~/^diff.*/) {
if ($commit_text_present == 0) {
- WARN("please add commit text explaining " .
+ WARN("NO_COMMIT_TEXT",
+ "please add commit text explaining " .
"*why* the change is needed\n" .
$herecurr);
}
@@ -1668,7 +1671,8 @@
&& $line !~ /^:([0-7]{6}\s){2}
([[:xdigit:]]+\.*
\s){2}\w+\s\w+/xms) {
- WARN("commit text line over " .
+ WARN("LONG_COMMIT_TEXT",
+ "commit text line over " .
SHORTTEXT_LIMIT .
" characters\n" . $herecurr);
} elsif ($line=~/^\s*change-id:/i ||
@@ -1678,7 +1682,8 @@
# this is a tag, there must be commit
# text by now
if ($commit_text_present == 0) {
- WARN("please add commit text explaining " .
+ WARN("NO_COMMIT_TEXT",
+ "please add commit text explaining " .
"*why* the change is needed\n" .
$herecurr);
# prevent duplicate warnings
@@ -1699,7 +1704,8 @@
$shorttext = IN_SHORTTEXT;
# Check for Subject line followed by a blank line.
if (length($line) != 0) {
- WARN("non-blank line after " .
+ WARN("NONBLANK_AFTER_SUMMARY",
+ "non-blank line after " .
"summary line\n" .
$sublinenr . $here .
"\n" . $subjectline .
@@ -1721,7 +1727,8 @@
$sublinenr = "#$linenr & ";
# Check for Subject line less than line limit
if (length($1) > SHORTTEXT_LIMIT) {
- WARN("summary line over " .
+ WARN("LONG_SUMMARY_LINE",
+ "summary line over " .
SHORTTEXT_LIMIT .
" characters\n" . $herecurr);
}
@@ -1732,7 +1739,8 @@
$shorttext = IN_SHORTTEXT_BLANKLINE;
$shorttext_exspc = 4;
if (length($1) > SHORTTEXT_LIMIT) {
- WARN("summary line over " .
+ WARN("LONG_SUMMARY_LINE",
+ "summary line over " .
SHORTTEXT_LIMIT .
" characters\n" . $herecurr);
}
@@ -1797,13 +1805,14 @@
}
}
if ($line =~ /^\s*signed-off-by:.*(quicinc|qualcomm)\.com/i) {
- WARN("invalid Signed-off-by identity\n" . $line );
+ WARN("BAD_SIGN_OFF",
+ "invalid Signed-off-by identity\n" . $line );
}
}
#check the patch for invalid author credentials
if ($line =~ /^From:.*(quicinc|qualcomm)\.com/) {
- WARN("invalid author identity\n" . $line );
+ WARN("BAD_AUTHOR", "invalid author identity\n" . $line );
}
# Check for wrappage within a valid hunk of the file
@@ -3291,19 +3300,20 @@
# sys_open/read/write/close are not allowed in the kernel
if ($line =~ /\b(sys_(?:open|read|write|close))\b/) {
- ERROR("$1 is inappropriate in kernel code.\n" .
+ ERROR("FILE_OPS", "$1 is inappropriate in kernel code.\n" .
$herecurr);
}
# filp_open is a backdoor for sys_open
if ($line =~ /\b(filp_open)\b/) {
- ERROR("$1 is inappropriate in kernel code.\n" .
+ ERROR("FILE_OPS", "$1 is inappropriate in kernel code.\n" .
$herecurr);
}
# read[bwl] & write[bwl] use too many barriers, use the _relaxed variants
if ($line =~ /\b((?:read|write)[bwl])\b/) {
- ERROR("Use of $1 is deprecated: use $1_relaxed\n\t" .
+ ERROR("NON_RELAXED_IO",
+ "Use of $1 is deprecated: use $1_relaxed\n\t" .
"with appropriate memory barriers instead.\n" .
$herecurr);
}
@@ -3313,7 +3323,8 @@
my ($all, $pref, $suf) = ($1, $2, $3);
$pref =~ s/in/read/;
$pref =~ s/out/write/;
- ERROR("Use of $all is deprecated: use " .
+ ERROR("NON_RELAXED_IO",
+ "Use of $all is deprecated: use " .
"__raw_$pref$suf\n\t" .
"with appropriate memory barriers instead.\n" .
$herecurr);
@@ -3321,7 +3332,8 @@
# dsb is too ARMish, and should usually be mb.
if ($line =~ /\bdsb\b/) {
- WARN("Use of dsb is discouranged: prefer mb.\n" .
+ WARN("ARM_BARRIER",
+ "Use of dsb is discouranged: prefer mb.\n" .
$herecurr);
}
@@ -3329,12 +3341,13 @@
if ($realfile =~ /\/mach-msm\/board-[0-9]+/ &&
$realfile !~ /camera/ && $realfile !~ /gpiomux/ &&
$line =~ /\s*struct msm_gpiomux_config\s*/ ) {
- WARN("Non gpiomux board file cannot have a gpiomux config declarations. Please declare gpiomux configs in board-*-gpiomux.c file.\n" . $herecurr);
+ WARN("GPIOMUX_IN_BOARD",
+ "Non gpiomux board file cannot have a gpiomux config declarations. Please declare gpiomux configs in board-*-gpiomux.c file.\n" . $herecurr);
}
# MSM - check if vreg_xxx function are used
if ($line =~ /\b(vreg_(get|put|set_level|enable|disable))\b/) {
- WARN("Use of $1 API is deprecated: " .
+ WARN("DEPRECATED_VREG_APIS", "Use of $1 API is deprecated: " .
"use regulator APIs\n" . $herecurr);
}
@@ -3354,7 +3367,8 @@
);
foreach my $k (keys %str_fns) {
if ($line =~ /\b$k\b/) {
- ERROR("Use of $k is deprecated: " .
+ ERROR("UNBOUNDED_STRING_FNS",
+ "Use of $k is deprecated: " .
"use $str_fns{$k} instead.\n" .
$herecurr);
}
@@ -3362,13 +3376,15 @@
# warn about #if 0
if ($line =~ /^.\s*\#\s*if\s+0\b/) {
- WARN("if this code is redundant consider removing it\n"
+ WARN("IF_0",
+ "if this code is redundant consider removing it\n"
. $herecurr);
}
# warn about #if 1
if ($line =~ /^.\s*\#\s*if\s+1\b/) {
- WARN("if this code is required consider removing"
+ WARN("IF_1",
+ "if this code is required consider removing"
. " #if 1\n" . $herecurr);
}
@@ -3408,7 +3424,8 @@
# check the patch for use of mdelay
if ($line =~ /\bmdelay\s*\(/) {
- WARN("use of mdelay() found: msleep() is the preferred API.\n" . $line );
+ WARN("MDELAY",
+ "use of mdelay() found: msleep() is the preferred API.\n" . $line );
}
# warn about #ifdefs in C files
@@ -3598,7 +3615,8 @@
# check for return codes on error paths
if ($line =~ /\breturn\s+-\d+/) {
- ERROR("illegal return value, please use an error code\n" . $herecurr);
+ ERROR("NO_ERROR_CODE",
+ "illegal return value, please use an error code\n" . $herecurr);
}
# check for gcc specific __FUNCTION__
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 80204f5..b211ac4 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -292,6 +292,9 @@
config SND_SOC_CS8427
tristate
+config SND_SOC_WCD9320
+ tristate
+
config SND_SOC_WL1273
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 965d6a1..5aabfee 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -51,6 +51,7 @@
snd-soc-wcd9304-objs := wcd9304.o wcd9304-tables.o
snd-soc-wcd9310-objs := wcd9310.o wcd9310-tables.o
snd-soc-cs8427-objs := cs8427.o
+snd-soc-wcd9320-objs := wcd9320.o wcd9320-tables.o
snd-soc-wl1273-objs := wl1273.o
snd-soc-wm1250-ev1-objs := wm1250-ev1.o
snd-soc-wm2000-objs := wm2000.o
@@ -158,6 +159,7 @@
obj-$(CONFIG_SND_SOC_WCD9304) += snd-soc-wcd9304.o
obj-$(CONFIG_SND_SOC_WCD9310) += snd-soc-wcd9310.o
obj-$(CONFIG_SND_SOC_CS8427) += snd-soc-cs8427.o
+obj-$(CONFIG_SND_SOC_WCD9320) += snd-soc-wcd9320.o
obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o
obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 4b4dae1..9dcfc1c 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -5265,16 +5265,37 @@
wcd9xxx_unlock_sleep(core);
}
+static u16 tabla_get_cfilt_reg(struct snd_soc_codec *codec, u8 cfilt)
+{
+ u16 reg;
+
+ switch (cfilt) {
+ case TABLA_CFILT1_SEL:
+ reg = TABLA_A_MICB_CFILT_1_CTL;
+ break;
+ case TABLA_CFILT2_SEL:
+ reg = TABLA_A_MICB_CFILT_2_CTL;
+ break;
+ case TABLA_CFILT3_SEL:
+ reg = TABLA_A_MICB_CFILT_3_CTL;
+ break;
+ default:
+ BUG();
+ }
+ return reg;
+}
+
void tabla_mbhc_cal(struct snd_soc_codec *codec)
{
struct tabla_priv *tabla;
struct tabla_mbhc_btn_detect_cfg *btn_det;
- u8 cfilt_mode, bg_mode;
+ u8 cfilt_mode, micbias2_cfilt_mode, bg_mode;
u8 ncic, nmeas, navg;
u32 mclk_rate;
u32 dce_wait, sta_wait;
u8 *n_cic;
void *calibration;
+ u16 bias2_ctl;
tabla = snd_soc_codec_get_drvdata(codec);
calibration = tabla->mbhc_cfg.calibration;
@@ -5303,7 +5324,16 @@
* Need to restore defaults once calculation is done.
*/
cfilt_mode = snd_soc_read(codec, tabla->mbhc_bias_regs.cfilt_ctl);
- snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x40, 0x00);
+ micbias2_cfilt_mode =
+ snd_soc_read(codec, tabla_get_cfilt_reg(codec,
+ tabla->pdata->micbias.bias2_cfilt_sel));
+ snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x40,
+ TABLA_CFILT_FAST_MODE);
+ snd_soc_update_bits(codec,
+ tabla_get_cfilt_reg(codec,
+ tabla->pdata->micbias.bias2_cfilt_sel),
+ 0x40, TABLA_CFILT_FAST_MODE);
+
bg_mode = snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x02,
0x02);
@@ -5317,6 +5347,12 @@
snd_soc_write(codec, TABLA_A_TX_7_MBHC_TEST_CTL, 0x78);
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x04, 0x04);
+ /* MICBIAS2 routing for calibration */
+ bias2_ctl = snd_soc_read(codec, TABLA_A_MICB_2_CTL);
+ snd_soc_update_bits(codec, TABLA_A_MICB_1_MBHC, 0x03, TABLA_MICBIAS2);
+ snd_soc_write(codec, TABLA_A_MICB_2_CTL,
+ snd_soc_read(codec, tabla->mbhc_bias_regs.ctl_reg));
+
/* DCE measurement for 0 volts */
snd_soc_write(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x0A);
snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x04);
@@ -5354,7 +5390,15 @@
tabla->mbhc_data.sta_mb = tabla_codec_read_sta_result(codec);
/* Restore default settings. */
+ snd_soc_write(codec, TABLA_A_MICB_2_CTL, bias2_ctl);
+ snd_soc_update_bits(codec, TABLA_A_MICB_1_MBHC, 0x03,
+ tabla->mbhc_cfg.micbias);
+
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
+ snd_soc_update_bits(codec,
+ tabla_get_cfilt_reg(codec,
+ tabla->pdata->micbias.bias2_cfilt_sel), 0x40,
+ micbias2_cfilt_mode);
snd_soc_update_bits(codec, tabla->mbhc_bias_regs.cfilt_ctl, 0x40,
cfilt_mode);
snd_soc_update_bits(codec, TABLA_A_BIAS_CENTRAL_BG_CTL, 0x02, bg_mode);
@@ -5538,6 +5582,10 @@
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_B1_CTL, 0x02, 0x02);
snd_soc_update_bits(codec, TABLA_A_MBHC_SCALING_MUX_2, 0xF0, 0xF0);
+
+ /* override mbhc's micbias */
+ snd_soc_update_bits(codec, TABLA_A_MICB_1_MBHC, 0x03,
+ tabla->mbhc_cfg.micbias);
}
static bool tabla_mbhc_fw_validate(const struct firmware *fw)
diff --git a/sound/soc/codecs/wcd9320-tables.c b/sound/soc/codecs/wcd9320-tables.c
new file mode 100644
index 0000000..68a4670
--- /dev/null
+++ b/sound/soc/codecs/wcd9320-tables.c
@@ -0,0 +1,1359 @@
+/* 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/mfd/wcd9xxx/wcd9320_registers.h>
+#include "wcd9320.h"
+
+const u8 taiko_reg_readable[TAIKO_CACHE_SIZE] = {
+ [TAIKO_A_CHIP_CTL] = 1,
+ [TAIKO_A_CHIP_STATUS] = 1,
+ [TAIKO_A_CHIP_ID_BYTE_0] = 1,
+ [TAIKO_A_CHIP_ID_BYTE_1] = 1,
+ [TAIKO_A_CHIP_ID_BYTE_2] = 1,
+ [TAIKO_A_CHIP_ID_BYTE_3] = 1,
+ [TAIKO_A_CHIP_VERSION] = 1,
+ [TAIKO_A_SLAVE_ID_1] = 1,
+ [TAIKO_A_SLAVE_ID_2] = 1,
+ [TAIKO_A_SLAVE_ID_3] = 1,
+ [TAIKO_A_PIN_CTL_OE0] = 1,
+ [TAIKO_A_PIN_CTL_OE1] = 1,
+ [TAIKO_A_PIN_CTL_DATA0] = 1,
+ [TAIKO_A_PIN_CTL_DATA1] = 1,
+ [TAIKO_A_HDRIVE_GENERIC] = 1,
+ [TAIKO_A_HDRIVE_OVERRIDE] = 1,
+ [TAIKO_A_ANA_CSR_WAIT_STATE] = 1,
+ [TAIKO_A_PROCESS_MONITOR_CTL0] = 1,
+ [TAIKO_A_PROCESS_MONITOR_CTL1] = 1,
+ [TAIKO_A_PROCESS_MONITOR_CTL2] = 1,
+ [TAIKO_A_PROCESS_MONITOR_CTL3] = 1,
+ [TAIKO_A_QFUSE_CTL] = 1,
+ [TAIKO_A_QFUSE_STATUS] = 1,
+ [TAIKO_A_QFUSE_DATA_OUT0] = 1,
+ [TAIKO_A_QFUSE_DATA_OUT1] = 1,
+ [TAIKO_A_QFUSE_DATA_OUT2] = 1,
+ [TAIKO_A_QFUSE_DATA_OUT3] = 1,
+ [TAIKO_A_QFUSE_DATA_OUT4] = 1,
+ [TAIKO_A_QFUSE_DATA_OUT5] = 1,
+ [TAIKO_A_QFUSE_DATA_OUT6] = 1,
+ [TAIKO_A_QFUSE_DATA_OUT7] = 1,
+ [TAIKO_A_CDC_CTL] = 1,
+ [TAIKO_A_LEAKAGE_CTL] = 1,
+ [TAIKO_A_INTR_MODE] = 1,
+ [TAIKO_A_INTR_MASK0] = 1,
+ [TAIKO_A_INTR_MASK1] = 1,
+ [TAIKO_A_INTR_MASK2] = 1,
+ [TAIKO_A_INTR_MASK3] = 1,
+ [TAIKO_A_INTR_STATUS0] = 1,
+ [TAIKO_A_INTR_STATUS1] = 1,
+ [TAIKO_A_INTR_STATUS2] = 1,
+ [TAIKO_A_INTR_STATUS3] = 1,
+ [TAIKO_A_INTR_CLEAR0] = 0,
+ [TAIKO_A_INTR_CLEAR1] = 0,
+ [TAIKO_A_INTR_CLEAR2] = 0,
+ [TAIKO_A_INTR_CLEAR3] = 0,
+ [TAIKO_A_INTR_LEVEL0] = 1,
+ [TAIKO_A_INTR_LEVEL1] = 1,
+ [TAIKO_A_INTR_LEVEL2] = 1,
+ [TAIKO_A_INTR_LEVEL3] = 1,
+ [TAIKO_A_INTR_TEST0] = 1,
+ [TAIKO_A_INTR_TEST1] = 1,
+ [TAIKO_A_INTR_TEST2] = 1,
+ [TAIKO_A_INTR_TEST3] = 1,
+ [TAIKO_A_INTR_SET0] = 1,
+ [TAIKO_A_INTR_SET1] = 1,
+ [TAIKO_A_INTR_SET2] = 1,
+ [TAIKO_A_INTR_SET3] = 1,
+ [TAIKO_A_INTR_DESTN0] = 1,
+ [TAIKO_A_INTR_DESTN1] = 1,
+ [TAIKO_A_INTR_DESTN2] = 1,
+ [TAIKO_A_INTR_DESTN3] = 1,
+ [TAIKO_A_CDC_TX_I2S_SCK_MODE] = 1,
+ [TAIKO_A_CDC_TX_I2S_WS_MODE] = 1,
+ [TAIKO_A_CDC_DMIC_DATA0_MODE] = 1,
+ [TAIKO_A_CDC_DMIC_CLK0_MODE] = 1,
+ [TAIKO_A_CDC_DMIC_DATA1_MODE] = 1,
+ [TAIKO_A_CDC_DMIC_CLK1_MODE] = 1,
+ [TAIKO_A_CDC_RX_I2S_SCK_MODE] = 1,
+ [TAIKO_A_CDC_RX_I2S_WS_MODE] = 1,
+ [TAIKO_A_CDC_DMIC_DATA2_MODE] = 1,
+ [TAIKO_A_CDC_DMIC_CLK2_MODE] = 1,
+ [TAIKO_A_CDC_INTR1_MODE] = 1,
+ [TAIKO_A_CDC_SB_NRZ_SEL_MODE] = 1,
+ [TAIKO_A_CDC_INTR2_MODE] = 1,
+ [TAIKO_A_CDC_RF_PA_ON_MODE] = 1,
+ [TAIKO_A_BIAS_REF_CTL] = 1,
+ [TAIKO_A_BIAS_CENTRAL_BG_CTL] = 1,
+ [TAIKO_A_BIAS_PRECHRG_CTL] = 1,
+ [TAIKO_A_BIAS_CURR_CTL_1] = 1,
+ [TAIKO_A_BIAS_CURR_CTL_2] = 1,
+ [TAIKO_A_BIAS_OSC_BG_CTL] = 1,
+ [TAIKO_A_CLK_BUFF_EN1] = 1,
+ [TAIKO_A_CLK_BUFF_EN2] = 1,
+ [TAIKO_A_LDO_H_MODE_1] = 1,
+ [TAIKO_A_LDO_H_MODE_2] = 1,
+ [TAIKO_A_LDO_H_LOOP_CTL] = 1,
+ [TAIKO_A_LDO_H_COMP_1] = 1,
+ [TAIKO_A_LDO_H_COMP_2] = 1,
+ [TAIKO_A_LDO_H_BIAS_1] = 1,
+ [TAIKO_A_LDO_H_BIAS_2] = 1,
+ [TAIKO_A_LDO_H_BIAS_3] = 1,
+ [TAIKO_A_VBAT_CLK] = 1,
+ [TAIKO_A_VBAT_LOOP] = 1,
+ [TAIKO_A_VBAT_REF] = 1,
+ [TAIKO_A_VBAT_ADC_TEST] = 1,
+ [TAIKO_A_VBAT_FE] = 1,
+ [TAIKO_A_VBAT_BIAS_1] = 1,
+ [TAIKO_A_VBAT_BIAS_2] = 1,
+ [TAIKO_A_VBAT_ADC_DATA_MSB] = 1,
+ [TAIKO_A_VBAT_ADC_DATA_LSB] = 1,
+ [TAIKO_A_MICB_CFILT_1_CTL] = 1,
+ [TAIKO_A_MICB_CFILT_1_VAL] = 1,
+ [TAIKO_A_MICB_CFILT_1_PRECHRG] = 1,
+ [TAIKO_A_MICB_1_CTL] = 1,
+ [TAIKO_A_MICB_1_INT_RBIAS] = 1,
+ [TAIKO_A_MICB_1_MBHC] = 1,
+ [TAIKO_A_MICB_CFILT_2_CTL] = 1,
+ [TAIKO_A_MICB_CFILT_2_VAL] = 1,
+ [TAIKO_A_MICB_CFILT_2_PRECHRG] = 1,
+ [TAIKO_A_MICB_2_CTL] = 1,
+ [TAIKO_A_MICB_2_INT_RBIAS] = 1,
+ [TAIKO_A_MICB_2_MBHC] = 1,
+ [TAIKO_A_MICB_CFILT_3_CTL] = 1,
+ [TAIKO_A_MICB_CFILT_3_VAL] = 1,
+ [TAIKO_A_MICB_CFILT_3_PRECHRG] = 1,
+ [TAIKO_A_MICB_3_CTL] = 1,
+ [TAIKO_A_MICB_3_INT_RBIAS] = 1,
+ [TAIKO_A_MICB_3_MBHC] = 1,
+ [TAIKO_A_MICB_4_CTL] = 1,
+ [TAIKO_A_MICB_4_INT_RBIAS] = 1,
+ [TAIKO_A_MICB_4_MBHC] = 1,
+ [TAIKO_A_MBHC_INSERT_DETECT] = 1,
+ [TAIKO_A_MBHC_INSERT_DET_STATUS] = 1,
+ [TAIKO_A_TX_COM_BIAS] = 1,
+ [TAIKO_A_MBHC_SCALING_MUX_1] = 1,
+ [TAIKO_A_MBHC_SCALING_MUX_2] = 1,
+ [TAIKO_A_MAD_ANA_CTRL] = 1,
+ [TAIKO_A_TX_SUP_SWITCH_CTRL_1] = 1,
+ [TAIKO_A_TX_SUP_SWITCH_CTRL_2] = 1,
+ [TAIKO_A_TX_1_2_EN] = 1,
+ [TAIKO_A_TX_1_2_TEST_EN] = 1,
+ [TAIKO_A_TX_1_2_ADC_CH1] = 1,
+ [TAIKO_A_TX_1_2_ADC_CH2] = 1,
+ [TAIKO_A_TX_1_2_ATEST_REFCTRL] = 1,
+ [TAIKO_A_TX_1_2_TEST_CTL] = 1,
+ [TAIKO_A_TX_1_2_TEST_BLOCK_EN] = 1,
+ [TAIKO_A_TX_1_2_TXFE_CLKDIV] = 1,
+ [TAIKO_A_TX_1_2_SAR_ERR_CH1] = 1,
+ [TAIKO_A_TX_1_2_SAR_ERR_CH2] = 1,
+ [TAIKO_A_TX_3_4_EN] = 1,
+ [TAIKO_A_TX_3_4_TEST_EN] = 1,
+ [TAIKO_A_TX_3_4_ADC_CH3] = 1,
+ [TAIKO_A_TX_3_4_ADC_CH4] = 1,
+ [TAIKO_A_TX_3_4_ATEST_REFCTRL] = 1,
+ [TAIKO_A_TX_3_4_TEST_CTL] = 1,
+ [TAIKO_A_TX_3_4_TEST_BLOCK_EN] = 1,
+ [TAIKO_A_TX_3_4_TXFE_CKDIV] = 1,
+ [TAIKO_A_TX_3_4_SAR_ERR_CH3] = 1,
+ [TAIKO_A_TX_3_4_SAR_ERR_CH4] = 1,
+ [TAIKO_A_TX_5_6_EN] = 1,
+ [TAIKO_A_TX_5_6_TEST_EN] = 1,
+ [TAIKO_A_TX_5_6_ADC_CH5] = 1,
+ [TAIKO_A_TX_5_6_ADC_CH6] = 1,
+ [TAIKO_A_TX_5_6_ATEST_REFCTRL] = 1,
+ [TAIKO_A_TX_5_6_TEST_CTL] = 1,
+ [TAIKO_A_TX_5_6_TEST_BLOCK_EN] = 1,
+ [TAIKO_A_TX_5_6_TXFE_CKDIV] = 1,
+ [TAIKO_A_TX_5_6_SAR_ERR_CH5] = 1,
+ [TAIKO_A_TX_5_6_SAR_ERR_CH6] = 1,
+ [TAIKO_A_TX_7_MBHC_EN] = 1,
+ [TAIKO_A_TX_7_MBHC_ATEST_REFCTRL] = 1,
+ [TAIKO_A_TX_7_MBHC_ADC] = 1,
+ [TAIKO_A_TX_7_MBHC_TEST_CTL] = 1,
+ [TAIKO_A_TX_7_MBHC_SAR_ERR] = 1,
+ [TAIKO_A_TX_7_TXFE_CLKDIV] = 1,
+ [TAIKO_A_BUCK_MODE_1] = 1,
+ [TAIKO_A_BUCK_MODE_2] = 1,
+ [TAIKO_A_BUCK_MODE_3] = 1,
+ [TAIKO_A_BUCK_MODE_4] = 1,
+ [TAIKO_A_BUCK_MODE_5] = 1,
+ [TAIKO_A_BUCK_CTRL_VCL_1] = 1,
+ [TAIKO_A_BUCK_CTRL_VCL_2] = 1,
+ [TAIKO_A_BUCK_CTRL_VCL_3] = 1,
+ [TAIKO_A_BUCK_CTRL_CCL_1] = 1,
+ [TAIKO_A_BUCK_CTRL_CCL_2] = 1,
+ [TAIKO_A_BUCK_CTRL_CCL_3] = 1,
+ [TAIKO_A_BUCK_CTRL_CCL_4] = 1,
+ [TAIKO_A_BUCK_CTRL_PWM_DRVR_1] = 1,
+ [TAIKO_A_BUCK_CTRL_PWM_DRVR_2] = 1,
+ [TAIKO_A_BUCK_CTRL_PWM_DRVR_3] = 1,
+ [TAIKO_A_BUCK_TMUX_A_D] = 1,
+ [TAIKO_A_NCP_BUCKREF] = 1,
+ [TAIKO_A_NCP_EN] = 1,
+ [TAIKO_A_NCP_CLK] = 1,
+ [TAIKO_A_NCP_STATIC] = 1,
+ [TAIKO_A_NCP_VTH_LOW] = 1,
+ [TAIKO_A_NCP_VTH_HIGH] = 1,
+ [TAIKO_A_NCP_ATEST] = 1,
+ [TAIKO_A_NCP_DTEST] = 1,
+ [TAIKO_A_NCP_DLY1] = 1,
+ [TAIKO_A_NCP_DLY2] = 1,
+ [TAIKO_A_RX_AUX_SW_CTL] = 1,
+ [TAIKO_A_RX_PA_AUX_IN_CONN] = 1,
+ [TAIKO_A_RX_COM_TIMER_DIV] = 1,
+ [TAIKO_A_RX_COM_OCP_CTL] = 1,
+ [TAIKO_A_RX_COM_OCP_COUNT] = 1,
+ [TAIKO_A_RX_COM_DAC_CTL] = 1,
+ [TAIKO_A_RX_COM_BIAS] = 1,
+ [TAIKO_A_RX_HPH_AUTO_CHOP] = 1,
+ [TAIKO_A_RX_HPH_CHOP_CTL] = 1,
+ [TAIKO_A_RX_HPH_BIAS_PA] = 1,
+ [TAIKO_A_RX_HPH_BIAS_LDO] = 1,
+ [TAIKO_A_RX_HPH_BIAS_CNP] = 1,
+ [TAIKO_A_RX_HPH_BIAS_WG_OCP] = 1,
+ [TAIKO_A_RX_HPH_OCP_CTL] = 1,
+ [TAIKO_A_RX_HPH_CNP_EN] = 1,
+ [TAIKO_A_RX_HPH_CNP_WG_CTL] = 1,
+ [TAIKO_A_RX_HPH_CNP_WG_TIME] = 1,
+ [TAIKO_A_RX_HPH_L_GAIN] = 1,
+ [TAIKO_A_RX_HPH_L_TEST] = 1,
+ [TAIKO_A_RX_HPH_L_PA_CTL] = 1,
+ [TAIKO_A_RX_HPH_L_DAC_CTL] = 1,
+ [TAIKO_A_RX_HPH_L_ATEST] = 1,
+ [TAIKO_A_RX_HPH_L_STATUS] = 1,
+ [TAIKO_A_RX_HPH_R_GAIN] = 1,
+ [TAIKO_A_RX_HPH_R_TEST] = 1,
+ [TAIKO_A_RX_HPH_R_PA_CTL] = 1,
+ [TAIKO_A_RX_HPH_R_DAC_CTL] = 1,
+ [TAIKO_A_RX_HPH_R_ATEST] = 1,
+ [TAIKO_A_RX_HPH_R_STATUS] = 1,
+ [TAIKO_A_RX_EAR_BIAS_PA] = 1,
+ [TAIKO_A_RX_EAR_BIAS_CMBUFF] = 1,
+ [TAIKO_A_RX_EAR_EN] = 1,
+ [TAIKO_A_RX_EAR_GAIN] = 1,
+ [TAIKO_A_RX_EAR_CMBUFF] = 1,
+ [TAIKO_A_RX_EAR_ICTL] = 1,
+ [TAIKO_A_RX_EAR_CCOMP] = 1,
+ [TAIKO_A_RX_EAR_VCM] = 1,
+ [TAIKO_A_RX_EAR_CNP] = 1,
+ [TAIKO_A_RX_EAR_DAC_CTL_ATEST] = 1,
+ [TAIKO_A_RX_EAR_STATUS] = 1,
+ [TAIKO_A_RX_LINE_BIAS_PA] = 1,
+ [TAIKO_A_RX_BUCK_BIAS1] = 1,
+ [TAIKO_A_RX_BUCK_BIAS2] = 1,
+ [TAIKO_A_RX_LINE_COM] = 1,
+ [TAIKO_A_RX_LINE_CNP_EN] = 1,
+ [TAIKO_A_RX_LINE_CNP_WG_CTL] = 1,
+ [TAIKO_A_RX_LINE_CNP_WG_TIME] = 1,
+ [TAIKO_A_RX_LINE_1_GAIN] = 1,
+ [TAIKO_A_RX_LINE_1_TEST] = 1,
+ [TAIKO_A_RX_LINE_1_DAC_CTL] = 1,
+ [TAIKO_A_RX_LINE_1_STATUS] = 1,
+ [TAIKO_A_RX_LINE_2_GAIN] = 1,
+ [TAIKO_A_RX_LINE_2_TEST] = 1,
+ [TAIKO_A_RX_LINE_2_DAC_CTL] = 1,
+ [TAIKO_A_RX_LINE_2_STATUS] = 1,
+ [TAIKO_A_RX_LINE_3_GAIN] = 1,
+ [TAIKO_A_RX_LINE_3_TEST] = 1,
+ [TAIKO_A_RX_LINE_3_DAC_CTL] = 1,
+ [TAIKO_A_RX_LINE_3_STATUS] = 1,
+ [TAIKO_A_RX_LINE_4_GAIN] = 1,
+ [TAIKO_A_RX_LINE_4_TEST] = 1,
+ [TAIKO_A_RX_LINE_4_DAC_CTL] = 1,
+ [TAIKO_A_RX_LINE_4_STATUS] = 1,
+ [TAIKO_A_RX_LINE_CNP_DBG] = 1,
+ [TAIKO_A_SPKR_DRV_EN] = 1,
+ [TAIKO_A_SPKR_DRV_GAIN] = 1,
+ [TAIKO_A_SPKR_DRV_DAC_CTL] = 1,
+ [TAIKO_A_SPKR_DRV_OCP_CTL] = 1,
+ [TAIKO_A_SPKR_DRV_CLIP_DET] = 1,
+ [TAIKO_A_SPKR_DRV_IEC] = 1,
+ [TAIKO_A_SPKR_DRV_DBG_DAC] = 1,
+ [TAIKO_A_SPKR_DRV_DBG_PA] = 1,
+ [TAIKO_A_SPKR_DRV_DBG_PWRSTG] = 1,
+ [TAIKO_A_SPKR_DRV_BIAS_LDO] = 1,
+ [TAIKO_A_SPKR_DRV_BIAS_INT] = 1,
+ [TAIKO_A_SPKR_DRV_BIAS_PA] = 1,
+ [TAIKO_A_SPKR_DRV_STATUS_OCP] = 1,
+ [TAIKO_A_SPKR_DRV_STATUS_PA] = 1,
+ [TAIKO_A_SPKR_PROT_EN] = 1,
+ [TAIKO_A_SPKR_PROT_ADC_EN] = 1,
+ [TAIKO_A_SPKR_PROT_ISENSE_BIAS] = 1,
+ [TAIKO_A_SPKR_PROT_VSENSE_BIAS] = 1,
+ [TAIKO_A_SPKR_PROT_ADC_ATEST_REFCTRL] = 1,
+ [TAIKO_A_SPKR_PROT_ADC_TEST_CTL] = 1,
+ [TAIKO_A_SPKR_PROT_TEST_BLOCK_EN] = 1,
+ [TAIKO_A_SPKR_PROT_ATEST] = 1,
+ [TAIKO_A_SPKR_PROT_V_SAR_ERR] = 1,
+ [TAIKO_A_SPKR_PROT_I_SAR_ERR] = 1,
+ [TAIKO_A_SPKR_PROT_LDO_CTRL] = 1,
+ [TAIKO_A_SPKR_PROT_ISENSE_CTRL] = 1,
+ [TAIKO_A_SPKR_PROT_VSENSE_CTRL] = 1,
+ [TAIKO_A_RC_OSC_FREQ] = 1,
+ [TAIKO_A_RC_OSC_TEST] = 1,
+ [TAIKO_A_RC_OSC_STATUS] = 1,
+ [TAIKO_A_RC_OSC_TUNER] = 1,
+ [TAIKO_A_MBHC_HPH] = 1,
+ [TAIKO_A_CDC_ANC1_B1_CTL] = 1,
+ [TAIKO_A_CDC_ANC2_B1_CTL] = 1,
+ [TAIKO_A_CDC_ANC1_SHIFT] = 1,
+ [TAIKO_A_CDC_ANC2_SHIFT] = 1,
+ [TAIKO_A_CDC_ANC1_IIR_B1_CTL] = 1,
+ [TAIKO_A_CDC_ANC2_IIR_B1_CTL] = 1,
+ [TAIKO_A_CDC_ANC1_IIR_B2_CTL] = 1,
+ [TAIKO_A_CDC_ANC2_IIR_B2_CTL] = 1,
+ [TAIKO_A_CDC_ANC1_IIR_B3_CTL] = 1,
+ [TAIKO_A_CDC_ANC2_IIR_B3_CTL] = 1,
+ [TAIKO_A_CDC_ANC1_LPF_B1_CTL] = 1,
+ [TAIKO_A_CDC_ANC2_LPF_B1_CTL] = 1,
+ [TAIKO_A_CDC_ANC1_LPF_B2_CTL] = 1,
+ [TAIKO_A_CDC_ANC2_LPF_B2_CTL] = 1,
+ [TAIKO_A_CDC_ANC1_SPARE] = 1,
+ [TAIKO_A_CDC_ANC2_SPARE] = 1,
+ [TAIKO_A_CDC_ANC1_SMLPF_CTL] = 1,
+ [TAIKO_A_CDC_ANC2_SMLPF_CTL] = 1,
+ [TAIKO_A_CDC_ANC1_DCFLT_CTL] = 1,
+ [TAIKO_A_CDC_ANC2_DCFLT_CTL] = 1,
+ [TAIKO_A_CDC_ANC1_GAIN_CTL] = 1,
+ [TAIKO_A_CDC_ANC2_GAIN_CTL] = 1,
+ [TAIKO_A_CDC_ANC1_B2_CTL] = 1,
+ [TAIKO_A_CDC_ANC2_B2_CTL] = 1,
+ [TAIKO_A_CDC_TX1_VOL_CTL_TIMER] = 1,
+ [TAIKO_A_CDC_TX2_VOL_CTL_TIMER] = 1,
+ [TAIKO_A_CDC_TX3_VOL_CTL_TIMER] = 1,
+ [TAIKO_A_CDC_TX4_VOL_CTL_TIMER] = 1,
+ [TAIKO_A_CDC_TX5_VOL_CTL_TIMER] = 1,
+ [TAIKO_A_CDC_TX6_VOL_CTL_TIMER] = 1,
+ [TAIKO_A_CDC_TX7_VOL_CTL_TIMER] = 1,
+ [TAIKO_A_CDC_TX8_VOL_CTL_TIMER] = 1,
+ [TAIKO_A_CDC_TX9_VOL_CTL_TIMER] = 1,
+ [TAIKO_A_CDC_TX10_VOL_CTL_TIMER] = 1,
+ [TAIKO_A_CDC_TX1_VOL_CTL_GAIN] = 1,
+ [TAIKO_A_CDC_TX2_VOL_CTL_GAIN] = 1,
+ [TAIKO_A_CDC_TX3_VOL_CTL_GAIN] = 1,
+ [TAIKO_A_CDC_TX4_VOL_CTL_GAIN] = 1,
+ [TAIKO_A_CDC_TX5_VOL_CTL_GAIN] = 1,
+ [TAIKO_A_CDC_TX6_VOL_CTL_GAIN] = 1,
+ [TAIKO_A_CDC_TX7_VOL_CTL_GAIN] = 1,
+ [TAIKO_A_CDC_TX8_VOL_CTL_GAIN] = 1,
+ [TAIKO_A_CDC_TX9_VOL_CTL_GAIN] = 1,
+ [TAIKO_A_CDC_TX10_VOL_CTL_GAIN] = 1,
+ [TAIKO_A_CDC_TX1_VOL_CTL_CFG] = 1,
+ [TAIKO_A_CDC_TX2_VOL_CTL_CFG] = 1,
+ [TAIKO_A_CDC_TX3_VOL_CTL_CFG] = 1,
+ [TAIKO_A_CDC_TX4_VOL_CTL_CFG] = 1,
+ [TAIKO_A_CDC_TX5_VOL_CTL_CFG] = 1,
+ [TAIKO_A_CDC_TX6_VOL_CTL_CFG] = 1,
+ [TAIKO_A_CDC_TX7_VOL_CTL_CFG] = 1,
+ [TAIKO_A_CDC_TX8_VOL_CTL_CFG] = 1,
+ [TAIKO_A_CDC_TX9_VOL_CTL_CFG] = 1,
+ [TAIKO_A_CDC_TX10_VOL_CTL_CFG] = 1,
+ [TAIKO_A_CDC_TX1_MUX_CTL] = 1,
+ [TAIKO_A_CDC_TX2_MUX_CTL] = 1,
+ [TAIKO_A_CDC_TX3_MUX_CTL] = 1,
+ [TAIKO_A_CDC_TX4_MUX_CTL] = 1,
+ [TAIKO_A_CDC_TX5_MUX_CTL] = 1,
+ [TAIKO_A_CDC_TX6_MUX_CTL] = 1,
+ [TAIKO_A_CDC_TX7_MUX_CTL] = 1,
+ [TAIKO_A_CDC_TX8_MUX_CTL] = 1,
+ [TAIKO_A_CDC_TX9_MUX_CTL] = 1,
+ [TAIKO_A_CDC_TX10_MUX_CTL] = 1,
+ [TAIKO_A_CDC_TX1_CLK_FS_CTL] = 1,
+ [TAIKO_A_CDC_TX2_CLK_FS_CTL] = 1,
+ [TAIKO_A_CDC_TX3_CLK_FS_CTL] = 1,
+ [TAIKO_A_CDC_TX4_CLK_FS_CTL] = 1,
+ [TAIKO_A_CDC_TX5_CLK_FS_CTL] = 1,
+ [TAIKO_A_CDC_TX6_CLK_FS_CTL] = 1,
+ [TAIKO_A_CDC_TX7_CLK_FS_CTL] = 1,
+ [TAIKO_A_CDC_TX8_CLK_FS_CTL] = 1,
+ [TAIKO_A_CDC_TX9_CLK_FS_CTL] = 1,
+ [TAIKO_A_CDC_TX10_CLK_FS_CTL] = 1,
+ [TAIKO_A_CDC_TX1_DMIC_CTL] = 1,
+ [TAIKO_A_CDC_TX2_DMIC_CTL] = 1,
+ [TAIKO_A_CDC_TX3_DMIC_CTL] = 1,
+ [TAIKO_A_CDC_TX4_DMIC_CTL] = 1,
+ [TAIKO_A_CDC_TX5_DMIC_CTL] = 1,
+ [TAIKO_A_CDC_TX6_DMIC_CTL] = 1,
+ [TAIKO_A_CDC_TX7_DMIC_CTL] = 1,
+ [TAIKO_A_CDC_TX8_DMIC_CTL] = 1,
+ [TAIKO_A_CDC_TX9_DMIC_CTL] = 1,
+ [TAIKO_A_CDC_TX10_DMIC_CTL] = 1,
+ [TAIKO_A_CDC_DEBUG_B1_CTL] = 1,
+ [TAIKO_A_CDC_DEBUG_B2_CTL] = 1,
+ [TAIKO_A_CDC_DEBUG_B3_CTL] = 1,
+ [TAIKO_A_CDC_DEBUG_B4_CTL] = 1,
+ [TAIKO_A_CDC_DEBUG_B5_CTL] = 1,
+ [TAIKO_A_CDC_DEBUG_B6_CTL] = 1,
+ [TAIKO_A_CDC_DEBUG_B7_CTL] = 1,
+ [TAIKO_A_CDC_SRC1_PDA_CFG] = 1,
+ [TAIKO_A_CDC_SRC2_PDA_CFG] = 1,
+ [TAIKO_A_CDC_SRC1_FS_CTL] = 1,
+ [TAIKO_A_CDC_SRC2_FS_CTL] = 1,
+ [TAIKO_A_CDC_RX1_B1_CTL] = 1,
+ [TAIKO_A_CDC_RX2_B1_CTL] = 1,
+ [TAIKO_A_CDC_RX3_B1_CTL] = 1,
+ [TAIKO_A_CDC_RX4_B1_CTL] = 1,
+ [TAIKO_A_CDC_RX5_B1_CTL] = 1,
+ [TAIKO_A_CDC_RX6_B1_CTL] = 1,
+ [TAIKO_A_CDC_RX7_B1_CTL] = 1,
+ [TAIKO_A_CDC_RX1_B2_CTL] = 1,
+ [TAIKO_A_CDC_RX2_B2_CTL] = 1,
+ [TAIKO_A_CDC_RX3_B2_CTL] = 1,
+ [TAIKO_A_CDC_RX4_B2_CTL] = 1,
+ [TAIKO_A_CDC_RX5_B2_CTL] = 1,
+ [TAIKO_A_CDC_RX6_B2_CTL] = 1,
+ [TAIKO_A_CDC_RX7_B2_CTL] = 1,
+ [TAIKO_A_CDC_RX1_B3_CTL] = 1,
+ [TAIKO_A_CDC_RX2_B3_CTL] = 1,
+ [TAIKO_A_CDC_RX3_B3_CTL] = 1,
+ [TAIKO_A_CDC_RX4_B3_CTL] = 1,
+ [TAIKO_A_CDC_RX5_B3_CTL] = 1,
+ [TAIKO_A_CDC_RX6_B3_CTL] = 1,
+ [TAIKO_A_CDC_RX7_B3_CTL] = 1,
+ [TAIKO_A_CDC_RX1_B4_CTL] = 1,
+ [TAIKO_A_CDC_RX2_B4_CTL] = 1,
+ [TAIKO_A_CDC_RX3_B4_CTL] = 1,
+ [TAIKO_A_CDC_RX4_B4_CTL] = 1,
+ [TAIKO_A_CDC_RX5_B4_CTL] = 1,
+ [TAIKO_A_CDC_RX6_B4_CTL] = 1,
+ [TAIKO_A_CDC_RX7_B4_CTL] = 1,
+ [TAIKO_A_CDC_RX1_B5_CTL] = 1,
+ [TAIKO_A_CDC_RX2_B5_CTL] = 1,
+ [TAIKO_A_CDC_RX3_B5_CTL] = 1,
+ [TAIKO_A_CDC_RX4_B5_CTL] = 1,
+ [TAIKO_A_CDC_RX5_B5_CTL] = 1,
+ [TAIKO_A_CDC_RX6_B5_CTL] = 1,
+ [TAIKO_A_CDC_RX7_B5_CTL] = 1,
+ [TAIKO_A_CDC_RX1_B6_CTL] = 1,
+ [TAIKO_A_CDC_RX2_B6_CTL] = 1,
+ [TAIKO_A_CDC_RX3_B6_CTL] = 1,
+ [TAIKO_A_CDC_RX4_B6_CTL] = 1,
+ [TAIKO_A_CDC_RX5_B6_CTL] = 1,
+ [TAIKO_A_CDC_RX6_B6_CTL] = 1,
+ [TAIKO_A_CDC_RX7_B6_CTL] = 1,
+ [TAIKO_A_CDC_RX1_VOL_CTL_B1_CTL] = 1,
+ [TAIKO_A_CDC_RX2_VOL_CTL_B1_CTL] = 1,
+ [TAIKO_A_CDC_RX3_VOL_CTL_B1_CTL] = 1,
+ [TAIKO_A_CDC_RX4_VOL_CTL_B1_CTL] = 1,
+ [TAIKO_A_CDC_RX5_VOL_CTL_B1_CTL] = 1,
+ [TAIKO_A_CDC_RX6_VOL_CTL_B1_CTL] = 1,
+ [TAIKO_A_CDC_RX7_VOL_CTL_B1_CTL] = 1,
+ [TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL] = 1,
+ [TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL] = 1,
+ [TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL] = 1,
+ [TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL] = 1,
+ [TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL] = 1,
+ [TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL] = 1,
+ [TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL] = 1,
+ [TAIKO_A_CDC_VBAT_CFG] = 1,
+ [TAIKO_A_CDC_VBAT_ADC_CAL1] = 1,
+ [TAIKO_A_CDC_VBAT_ADC_CAL2] = 1,
+ [TAIKO_A_CDC_VBAT_ADC_CAL3] = 1,
+ [TAIKO_A_CDC_VBAT_PK_EST1] = 1,
+ [TAIKO_A_CDC_VBAT_PK_EST2] = 1,
+ [TAIKO_A_CDC_VBAT_PK_EST3] = 1,
+ [TAIKO_A_CDC_VBAT_RF_PROC1] = 1,
+ [TAIKO_A_CDC_VBAT_RF_PROC2] = 1,
+ [TAIKO_A_CDC_VBAT_TAC1] = 1,
+ [TAIKO_A_CDC_VBAT_TAC2] = 1,
+ [TAIKO_A_CDC_VBAT_TAC3] = 1,
+ [TAIKO_A_CDC_VBAT_TAC4] = 1,
+ [TAIKO_A_CDC_VBAT_GAIN_UPD1] = 1,
+ [TAIKO_A_CDC_VBAT_GAIN_UPD2] = 1,
+ [TAIKO_A_CDC_VBAT_GAIN_UPD3] = 1,
+ [TAIKO_A_CDC_VBAT_GAIN_UPD4] = 1,
+ [TAIKO_A_CDC_VBAT_DEBUG1] = 1,
+ [TAIKO_A_CDC_CLK_ANC_RESET_CTL] = 1,
+ [TAIKO_A_CDC_CLK_RX_RESET_CTL] = 1,
+ [TAIKO_A_CDC_CLK_TX_RESET_B1_CTL] = 1,
+ [TAIKO_A_CDC_CLK_TX_RESET_B2_CTL] = 1,
+ [TAIKO_A_CDC_CLK_DMIC_B1_CTL] = 1,
+ [TAIKO_A_CDC_CLK_DMIC_B2_CTL] = 1,
+ [TAIKO_A_CDC_CLK_RX_I2S_CTL] = 1,
+ [TAIKO_A_CDC_CLK_TX_I2S_CTL] = 1,
+ [TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL] = 1,
+ [TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL] = 1,
+ [TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL] = 1,
+ [TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL] = 1,
+ [TAIKO_A_CDC_CLK_OTHR_CTL] = 1,
+ [TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL] = 1,
+ [TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL] = 1,
+ [TAIKO_A_CDC_CLK_RX_B1_CTL] = 1,
+ [TAIKO_A_CDC_CLK_RX_B2_CTL] = 1,
+ [TAIKO_A_CDC_CLK_MCLK_CTL] = 1,
+ [TAIKO_A_CDC_CLK_PDM_CTL] = 1,
+ [TAIKO_A_CDC_CLK_SD_CTL] = 1,
+ [TAIKO_A_CDC_CLK_POWER_CTL] = 1,
+ [TAIKO_A_CDC_CLSH_B1_CTL] = 1,
+ [TAIKO_A_CDC_CLSH_B2_CTL] = 1,
+ [TAIKO_A_CDC_CLSH_B3_CTL] = 1,
+ [TAIKO_A_CDC_CLSH_BUCK_NCP_VARS] = 1,
+ [TAIKO_A_CDC_CLSH_IDLE_HPH_THSD] = 1,
+ [TAIKO_A_CDC_CLSH_IDLE_EAR_THSD] = 1,
+ [TAIKO_A_CDC_CLSH_FCLKONLY_HPH_THSD] = 1,
+ [TAIKO_A_CDC_CLSH_FCLKONLY_EAR_THSD] = 1,
+ [TAIKO_A_CDC_CLSH_K_ADDR] = 1,
+ [TAIKO_A_CDC_CLSH_K_DATA] = 1,
+ [TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_L] = 1,
+ [TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_U] = 1,
+ [TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_L] = 1,
+ [TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_U] = 1,
+ [TAIKO_A_CDC_CLSH_V_PA_HD_EAR] = 1,
+ [TAIKO_A_CDC_CLSH_V_PA_HD_HPH] = 1,
+ [TAIKO_A_CDC_CLSH_V_PA_MIN_EAR] = 1,
+ [TAIKO_A_CDC_CLSH_V_PA_MIN_HPH] = 1,
+ [TAIKO_A_CDC_IIR1_GAIN_B1_CTL] = 1,
+ [TAIKO_A_CDC_IIR2_GAIN_B1_CTL] = 1,
+ [TAIKO_A_CDC_IIR1_GAIN_B2_CTL] = 1,
+ [TAIKO_A_CDC_IIR2_GAIN_B2_CTL] = 1,
+ [TAIKO_A_CDC_IIR1_GAIN_B3_CTL] = 1,
+ [TAIKO_A_CDC_IIR2_GAIN_B3_CTL] = 1,
+ [TAIKO_A_CDC_IIR1_GAIN_B4_CTL] = 1,
+ [TAIKO_A_CDC_IIR2_GAIN_B4_CTL] = 1,
+ [TAIKO_A_CDC_IIR1_GAIN_B5_CTL] = 1,
+ [TAIKO_A_CDC_IIR2_GAIN_B5_CTL] = 1,
+ [TAIKO_A_CDC_IIR1_GAIN_B6_CTL] = 1,
+ [TAIKO_A_CDC_IIR2_GAIN_B6_CTL] = 1,
+ [TAIKO_A_CDC_IIR1_GAIN_B7_CTL] = 1,
+ [TAIKO_A_CDC_IIR2_GAIN_B7_CTL] = 1,
+ [TAIKO_A_CDC_IIR1_GAIN_B8_CTL] = 1,
+ [TAIKO_A_CDC_IIR2_GAIN_B8_CTL] = 1,
+ [TAIKO_A_CDC_IIR1_CTL] = 1,
+ [TAIKO_A_CDC_IIR2_CTL] = 1,
+ [TAIKO_A_CDC_IIR1_GAIN_TIMER_CTL] = 1,
+ [TAIKO_A_CDC_IIR2_GAIN_TIMER_CTL] = 1,
+ [TAIKO_A_CDC_IIR1_COEF_B1_CTL] = 1,
+ [TAIKO_A_CDC_IIR2_COEF_B1_CTL] = 1,
+ [TAIKO_A_CDC_IIR1_COEF_B2_CTL] = 1,
+ [TAIKO_A_CDC_IIR2_COEF_B2_CTL] = 1,
+ [TAIKO_A_CDC_TOP_GAIN_UPDATE] = 1,
+ [TAIKO_A_CDC_COMP0_B1_CTL] = 1,
+ [TAIKO_A_CDC_COMP1_B1_CTL] = 1,
+ [TAIKO_A_CDC_COMP2_B1_CTL] = 1,
+ [TAIKO_A_CDC_COMP0_B2_CTL] = 1,
+ [TAIKO_A_CDC_COMP1_B2_CTL] = 1,
+ [TAIKO_A_CDC_COMP2_B2_CTL] = 1,
+ [TAIKO_A_CDC_COMP0_B3_CTL] = 1,
+ [TAIKO_A_CDC_COMP1_B3_CTL] = 1,
+ [TAIKO_A_CDC_COMP2_B3_CTL] = 1,
+ [TAIKO_A_CDC_COMP0_B4_CTL] = 1,
+ [TAIKO_A_CDC_COMP1_B4_CTL] = 1,
+ [TAIKO_A_CDC_COMP2_B4_CTL] = 1,
+ [TAIKO_A_CDC_COMP0_B5_CTL] = 1,
+ [TAIKO_A_CDC_COMP1_B5_CTL] = 1,
+ [TAIKO_A_CDC_COMP2_B5_CTL] = 1,
+ [TAIKO_A_CDC_COMP0_B6_CTL] = 1,
+ [TAIKO_A_CDC_COMP1_B6_CTL] = 1,
+ [TAIKO_A_CDC_COMP2_B6_CTL] = 1,
+ [TAIKO_A_CDC_COMP0_SHUT_DOWN_STATUS] = 1,
+ [TAIKO_A_CDC_COMP1_SHUT_DOWN_STATUS] = 1,
+ [TAIKO_A_CDC_COMP2_SHUT_DOWN_STATUS] = 1,
+ [TAIKO_A_CDC_COMP0_FS_CFG] = 1,
+ [TAIKO_A_CDC_COMP1_FS_CFG] = 1,
+ [TAIKO_A_CDC_COMP2_FS_CFG] = 1,
+ [TAIKO_A_CDC_CONN_RX1_B1_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX1_B2_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX1_B3_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX2_B1_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX2_B2_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX2_B3_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX3_B1_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX3_B2_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX4_B1_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX4_B2_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX5_B1_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX5_B2_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX6_B1_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX6_B2_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX7_B1_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX7_B2_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX7_B3_CTL] = 1,
+ [TAIKO_A_CDC_CONN_ANC_B1_CTL] = 1,
+ [TAIKO_A_CDC_CONN_ANC_B2_CTL] = 1,
+ [TAIKO_A_CDC_CONN_TX_B1_CTL] = 1,
+ [TAIKO_A_CDC_CONN_TX_B2_CTL] = 1,
+ [TAIKO_A_CDC_CONN_TX_B3_CTL] = 1,
+ [TAIKO_A_CDC_CONN_TX_B4_CTL] = 1,
+ [TAIKO_A_CDC_CONN_EQ1_B1_CTL] = 1,
+ [TAIKO_A_CDC_CONN_EQ1_B2_CTL] = 1,
+ [TAIKO_A_CDC_CONN_EQ1_B3_CTL] = 1,
+ [TAIKO_A_CDC_CONN_EQ1_B4_CTL] = 1,
+ [TAIKO_A_CDC_CONN_EQ2_B1_CTL] = 1,
+ [TAIKO_A_CDC_CONN_EQ2_B2_CTL] = 1,
+ [TAIKO_A_CDC_CONN_EQ2_B3_CTL] = 1,
+ [TAIKO_A_CDC_CONN_EQ2_B4_CTL] = 1,
+ [TAIKO_A_CDC_CONN_SRC1_B1_CTL] = 1,
+ [TAIKO_A_CDC_CONN_SRC1_B2_CTL] = 1,
+ [TAIKO_A_CDC_CONN_SRC2_B1_CTL] = 1,
+ [TAIKO_A_CDC_CONN_SRC2_B2_CTL] = 1,
+ [TAIKO_A_CDC_CONN_TX_SB_B1_CTL] = 1,
+ [TAIKO_A_CDC_CONN_TX_SB_B2_CTL] = 1,
+ [TAIKO_A_CDC_CONN_TX_SB_B3_CTL] = 1,
+ [TAIKO_A_CDC_CONN_TX_SB_B4_CTL] = 1,
+ [TAIKO_A_CDC_CONN_TX_SB_B5_CTL] = 1,
+ [TAIKO_A_CDC_CONN_TX_SB_B6_CTL] = 1,
+ [TAIKO_A_CDC_CONN_TX_SB_B7_CTL] = 1,
+ [TAIKO_A_CDC_CONN_TX_SB_B8_CTL] = 1,
+ [TAIKO_A_CDC_CONN_TX_SB_B9_CTL] = 1,
+ [TAIKO_A_CDC_CONN_TX_SB_B10_CTL] = 1,
+ [TAIKO_A_CDC_CONN_TX_SB_B11_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX_SB_B1_CTL] = 1,
+ [TAIKO_A_CDC_CONN_RX_SB_B2_CTL] = 1,
+ [TAIKO_A_CDC_CONN_CLSH_CTL] = 1,
+ [TAIKO_A_CDC_CONN_MISC] = 1,
+ [TAIKO_A_CDC_CONN_MAD] = 1,
+ [TAIKO_A_CDC_MBHC_EN_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_FIR_B1_CFG] = 1,
+ [TAIKO_A_CDC_MBHC_FIR_B2_CFG] = 1,
+ [TAIKO_A_CDC_MBHC_TIMER_B1_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_TIMER_B2_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_TIMER_B3_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_TIMER_B4_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_TIMER_B5_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_TIMER_B6_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_B1_STATUS] = 1,
+ [TAIKO_A_CDC_MBHC_B2_STATUS] = 1,
+ [TAIKO_A_CDC_MBHC_B3_STATUS] = 1,
+ [TAIKO_A_CDC_MBHC_B4_STATUS] = 1,
+ [TAIKO_A_CDC_MBHC_B5_STATUS] = 1,
+ [TAIKO_A_CDC_MBHC_B1_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_B2_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_VOLT_B1_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_VOLT_B2_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_VOLT_B3_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_VOLT_B4_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_VOLT_B5_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_VOLT_B6_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_VOLT_B7_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_VOLT_B8_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_VOLT_B9_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_VOLT_B10_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_VOLT_B11_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_VOLT_B12_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_CLK_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_INT_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_DEBUG_CTL] = 1,
+ [TAIKO_A_CDC_MBHC_SPARE] = 1,
+ [TAIKO_A_CDC_MAD_MAIN_CTL_1] = 1,
+ [TAIKO_A_CDC_MAD_MAIN_CTL_2] = 1,
+ [TAIKO_A_CDC_MAD_AUDIO_CTL_1] = 1,
+ [TAIKO_A_CDC_MAD_AUDIO_CTL_2] = 1,
+ [TAIKO_A_CDC_MAD_AUDIO_CTL_3] = 1,
+ [TAIKO_A_CDC_MAD_AUDIO_CTL_4] = 1,
+ [TAIKO_A_CDC_MAD_AUDIO_CTL_5] = 1,
+ [TAIKO_A_CDC_MAD_AUDIO_CTL_6] = 1,
+ [TAIKO_A_CDC_MAD_AUDIO_CTL_7] = 1,
+ [TAIKO_A_CDC_MAD_AUDIO_CTL_8] = 1,
+ [TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_PTR] = 1,
+ [TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_VAL] = 1,
+ [TAIKO_A_CDC_MAD_ULTR_CTL_1] = 1,
+ [TAIKO_A_CDC_MAD_ULTR_CTL_2] = 1,
+ [TAIKO_A_CDC_MAD_ULTR_CTL_3] = 1,
+ [TAIKO_A_CDC_MAD_ULTR_CTL_4] = 1,
+ [TAIKO_A_CDC_MAD_ULTR_CTL_5] = 1,
+ [TAIKO_A_CDC_MAD_ULTR_CTL_6] = 1,
+ [TAIKO_A_CDC_MAD_ULTR_CTL_7] = 1,
+ [TAIKO_A_CDC_MAD_BEACON_CTL_1] = 1,
+ [TAIKO_A_CDC_MAD_BEACON_CTL_2] = 1,
+ [TAIKO_A_CDC_MAD_BEACON_CTL_3] = 1,
+ [TAIKO_A_CDC_MAD_BEACON_CTL_4] = 1,
+ [TAIKO_A_CDC_MAD_BEACON_CTL_5] = 1,
+ [TAIKO_A_CDC_MAD_BEACON_CTL_6] = 1,
+ [TAIKO_A_CDC_MAD_BEACON_CTL_7] = 1,
+ [TAIKO_A_CDC_MAD_BEACON_CTL_8] = 1,
+ [TAIKO_A_CDC_MAD_BEACON_IIR_CTL_PTR] = 1,
+ [TAIKO_A_CDC_MAD_BEACON_IIR_CTL_VAL] = 1,
+};
+
+const u8 taiko_reg_defaults[TAIKO_CACHE_SIZE] = {
+ [TAIKO_A_CHIP_CTL] = TAIKO_A_CHIP_CTL__POR,
+ [TAIKO_A_CHIP_STATUS] = TAIKO_A_CHIP_STATUS__POR,
+ [TAIKO_A_CHIP_ID_BYTE_0] = TAIKO_A_CHIP_ID_BYTE_0__POR,
+ [TAIKO_A_CHIP_ID_BYTE_1] = TAIKO_A_CHIP_ID_BYTE_1__POR,
+ [TAIKO_A_CHIP_ID_BYTE_2] = TAIKO_A_CHIP_ID_BYTE_2__POR,
+ [TAIKO_A_CHIP_ID_BYTE_3] = TAIKO_A_CHIP_ID_BYTE_3__POR,
+ [TAIKO_A_CHIP_VERSION] = TAIKO_A_CHIP_VERSION__POR,
+ [TAIKO_A_SLAVE_ID_1] = TAIKO_A_SLAVE_ID_1__POR,
+ [TAIKO_A_SLAVE_ID_2] = TAIKO_A_SLAVE_ID_2__POR,
+ [TAIKO_A_SLAVE_ID_3] = TAIKO_A_SLAVE_ID_3__POR,
+ [TAIKO_A_PIN_CTL_OE0] = TAIKO_A_PIN_CTL_OE0__POR,
+ [TAIKO_A_PIN_CTL_OE1] = TAIKO_A_PIN_CTL_OE1__POR,
+ [TAIKO_A_PIN_CTL_DATA0] = TAIKO_A_PIN_CTL_DATA0__POR,
+ [TAIKO_A_PIN_CTL_DATA1] = TAIKO_A_PIN_CTL_DATA1__POR,
+ [TAIKO_A_HDRIVE_GENERIC] = TAIKO_A_HDRIVE_GENERIC__POR,
+ [TAIKO_A_HDRIVE_OVERRIDE] = TAIKO_A_HDRIVE_OVERRIDE__POR,
+ [TAIKO_A_ANA_CSR_WAIT_STATE] = TAIKO_A_ANA_CSR_WAIT_STATE__POR,
+ [TAIKO_A_PROCESS_MONITOR_CTL0] = TAIKO_A_PROCESS_MONITOR_CTL0__POR,
+ [TAIKO_A_PROCESS_MONITOR_CTL1] = TAIKO_A_PROCESS_MONITOR_CTL1__POR,
+ [TAIKO_A_PROCESS_MONITOR_CTL2] = TAIKO_A_PROCESS_MONITOR_CTL2__POR,
+ [TAIKO_A_PROCESS_MONITOR_CTL3] = TAIKO_A_PROCESS_MONITOR_CTL3__POR,
+ [TAIKO_A_QFUSE_CTL] = TAIKO_A_QFUSE_CTL__POR,
+ [TAIKO_A_QFUSE_STATUS] = TAIKO_A_QFUSE_STATUS__POR,
+ [TAIKO_A_QFUSE_DATA_OUT0] = TAIKO_A_QFUSE_DATA_OUT0__POR,
+ [TAIKO_A_QFUSE_DATA_OUT1] = TAIKO_A_QFUSE_DATA_OUT1__POR,
+ [TAIKO_A_QFUSE_DATA_OUT2] = TAIKO_A_QFUSE_DATA_OUT2__POR,
+ [TAIKO_A_QFUSE_DATA_OUT3] = TAIKO_A_QFUSE_DATA_OUT3__POR,
+ [TAIKO_A_QFUSE_DATA_OUT4] = TAIKO_A_QFUSE_DATA_OUT4__POR,
+ [TAIKO_A_QFUSE_DATA_OUT5] = TAIKO_A_QFUSE_DATA_OUT5__POR,
+ [TAIKO_A_QFUSE_DATA_OUT6] = TAIKO_A_QFUSE_DATA_OUT6__POR,
+ [TAIKO_A_QFUSE_DATA_OUT7] = TAIKO_A_QFUSE_DATA_OUT7__POR,
+ [TAIKO_A_CDC_CTL] = TAIKO_A_CDC_CTL__POR,
+ [TAIKO_A_LEAKAGE_CTL] = TAIKO_A_LEAKAGE_CTL__POR,
+ [TAIKO_A_INTR_MODE] = TAIKO_A_INTR_MODE__POR,
+ [TAIKO_A_INTR_MASK0] = TAIKO_A_INTR_MASK0__POR,
+ [TAIKO_A_INTR_MASK1] = TAIKO_A_INTR_MASK1__POR,
+ [TAIKO_A_INTR_MASK2] = TAIKO_A_INTR_MASK2__POR,
+ [TAIKO_A_INTR_MASK3] = TAIKO_A_INTR_MASK3__POR,
+ [TAIKO_A_INTR_STATUS0] = TAIKO_A_INTR_STATUS0__POR,
+ [TAIKO_A_INTR_STATUS1] = TAIKO_A_INTR_STATUS1__POR,
+ [TAIKO_A_INTR_STATUS2] = TAIKO_A_INTR_STATUS2__POR,
+ [TAIKO_A_INTR_STATUS3] = TAIKO_A_INTR_STATUS3__POR,
+ [TAIKO_A_INTR_CLEAR0] = TAIKO_A_INTR_CLEAR0__POR,
+ [TAIKO_A_INTR_CLEAR1] = TAIKO_A_INTR_CLEAR1__POR,
+ [TAIKO_A_INTR_CLEAR2] = TAIKO_A_INTR_CLEAR2__POR,
+ [TAIKO_A_INTR_CLEAR3] = TAIKO_A_INTR_CLEAR3__POR,
+ [TAIKO_A_INTR_LEVEL0] = TAIKO_A_INTR_LEVEL0__POR,
+ [TAIKO_A_INTR_LEVEL1] = TAIKO_A_INTR_LEVEL1__POR,
+ [TAIKO_A_INTR_LEVEL2] = TAIKO_A_INTR_LEVEL2__POR,
+ [TAIKO_A_INTR_LEVEL3] = TAIKO_A_INTR_LEVEL3__POR,
+ [TAIKO_A_INTR_TEST0] = TAIKO_A_INTR_TEST0__POR,
+ [TAIKO_A_INTR_TEST1] = TAIKO_A_INTR_TEST1__POR,
+ [TAIKO_A_INTR_TEST2] = TAIKO_A_INTR_TEST2__POR,
+ [TAIKO_A_INTR_TEST3] = TAIKO_A_INTR_TEST3__POR,
+ [TAIKO_A_INTR_SET0] = TAIKO_A_INTR_SET0__POR,
+ [TAIKO_A_INTR_SET1] = TAIKO_A_INTR_SET1__POR,
+ [TAIKO_A_INTR_SET2] = TAIKO_A_INTR_SET2__POR,
+ [TAIKO_A_INTR_SET3] = TAIKO_A_INTR_SET3__POR,
+ [TAIKO_A_INTR_DESTN0] = TAIKO_A_INTR_DESTN0__POR,
+ [TAIKO_A_INTR_DESTN1] = TAIKO_A_INTR_DESTN1__POR,
+ [TAIKO_A_INTR_DESTN2] = TAIKO_A_INTR_DESTN2__POR,
+ [TAIKO_A_INTR_DESTN3] = TAIKO_A_INTR_DESTN3__POR,
+ [TAIKO_A_CDC_TX_I2S_SCK_MODE] = TAIKO_A_CDC_TX_I2S_SCK_MODE__POR,
+ [TAIKO_A_CDC_TX_I2S_WS_MODE] = TAIKO_A_CDC_TX_I2S_WS_MODE__POR,
+ [TAIKO_A_CDC_DMIC_DATA0_MODE] = TAIKO_A_CDC_DMIC_DATA0_MODE__POR,
+ [TAIKO_A_CDC_DMIC_CLK0_MODE] = TAIKO_A_CDC_DMIC_CLK0_MODE__POR,
+ [TAIKO_A_CDC_DMIC_DATA1_MODE] = TAIKO_A_CDC_DMIC_DATA1_MODE__POR,
+ [TAIKO_A_CDC_DMIC_CLK1_MODE] = TAIKO_A_CDC_DMIC_CLK1_MODE__POR,
+ [TAIKO_A_CDC_RX_I2S_SCK_MODE] = TAIKO_A_CDC_RX_I2S_SCK_MODE__POR,
+ [TAIKO_A_CDC_RX_I2S_WS_MODE] = TAIKO_A_CDC_RX_I2S_WS_MODE__POR,
+ [TAIKO_A_CDC_DMIC_DATA2_MODE] = TAIKO_A_CDC_DMIC_DATA2_MODE__POR,
+ [TAIKO_A_CDC_DMIC_CLK2_MODE] = TAIKO_A_CDC_DMIC_CLK2_MODE__POR,
+ [TAIKO_A_CDC_INTR1_MODE] = TAIKO_A_CDC_INTR1_MODE__POR,
+ [TAIKO_A_CDC_SB_NRZ_SEL_MODE] = TAIKO_A_CDC_SB_NRZ_SEL_MODE__POR,
+ [TAIKO_A_CDC_INTR2_MODE] = TAIKO_A_CDC_INTR2_MODE__POR,
+ [TAIKO_A_CDC_RF_PA_ON_MODE] = TAIKO_A_CDC_RF_PA_ON_MODE__POR,
+ [TAIKO_A_BIAS_REF_CTL] = TAIKO_A_BIAS_REF_CTL__POR,
+ [TAIKO_A_BIAS_CENTRAL_BG_CTL] = TAIKO_A_BIAS_CENTRAL_BG_CTL__POR,
+ [TAIKO_A_BIAS_PRECHRG_CTL] = TAIKO_A_BIAS_PRECHRG_CTL__POR,
+ [TAIKO_A_BIAS_CURR_CTL_1] = TAIKO_A_BIAS_CURR_CTL_1__POR,
+ [TAIKO_A_BIAS_CURR_CTL_2] = TAIKO_A_BIAS_CURR_CTL_2__POR,
+ [TAIKO_A_BIAS_OSC_BG_CTL] = TAIKO_A_BIAS_OSC_BG_CTL__POR,
+ [TAIKO_A_CLK_BUFF_EN1] = TAIKO_A_CLK_BUFF_EN1__POR,
+ [TAIKO_A_CLK_BUFF_EN2] = TAIKO_A_CLK_BUFF_EN2__POR,
+ [TAIKO_A_LDO_H_MODE_1] = TAIKO_A_LDO_H_MODE_1__POR,
+ [TAIKO_A_LDO_H_MODE_2] = TAIKO_A_LDO_H_MODE_2__POR,
+ [TAIKO_A_LDO_H_LOOP_CTL] = TAIKO_A_LDO_H_LOOP_CTL__POR,
+ [TAIKO_A_LDO_H_COMP_1] = TAIKO_A_LDO_H_COMP_1__POR,
+ [TAIKO_A_LDO_H_COMP_2] = TAIKO_A_LDO_H_COMP_2__POR,
+ [TAIKO_A_LDO_H_BIAS_1] = TAIKO_A_LDO_H_BIAS_1__POR,
+ [TAIKO_A_LDO_H_BIAS_2] = TAIKO_A_LDO_H_BIAS_2__POR,
+ [TAIKO_A_LDO_H_BIAS_3] = TAIKO_A_LDO_H_BIAS_3__POR,
+ [TAIKO_A_VBAT_CLK] = TAIKO_A_VBAT_CLK__POR,
+ [TAIKO_A_VBAT_LOOP] = TAIKO_A_VBAT_LOOP__POR,
+ [TAIKO_A_VBAT_REF] = TAIKO_A_VBAT_REF__POR,
+ [TAIKO_A_VBAT_ADC_TEST] = TAIKO_A_VBAT_ADC_TEST__POR,
+ [TAIKO_A_VBAT_FE] = TAIKO_A_VBAT_FE__POR,
+ [TAIKO_A_VBAT_BIAS_1] = TAIKO_A_VBAT_BIAS_1__POR,
+ [TAIKO_A_VBAT_BIAS_2] = TAIKO_A_VBAT_BIAS_2__POR,
+ [TAIKO_A_VBAT_ADC_DATA_MSB] = TAIKO_A_VBAT_ADC_DATA_MSB__POR,
+ [TAIKO_A_VBAT_ADC_DATA_LSB] = TAIKO_A_VBAT_ADC_DATA_LSB__POR,
+ [TAIKO_A_MICB_CFILT_1_CTL] = TAIKO_A_MICB_CFILT_1_CTL__POR,
+ [TAIKO_A_MICB_CFILT_1_VAL] = TAIKO_A_MICB_CFILT_1_VAL__POR,
+ [TAIKO_A_MICB_CFILT_1_PRECHRG] = TAIKO_A_MICB_CFILT_1_PRECHRG__POR,
+ [TAIKO_A_MICB_1_CTL] = TAIKO_A_MICB_1_CTL__POR,
+ [TAIKO_A_MICB_1_INT_RBIAS] = TAIKO_A_MICB_1_INT_RBIAS__POR,
+ [TAIKO_A_MICB_1_MBHC] = TAIKO_A_MICB_1_MBHC__POR,
+ [TAIKO_A_MICB_CFILT_2_CTL] = TAIKO_A_MICB_CFILT_2_CTL__POR,
+ [TAIKO_A_MICB_CFILT_2_VAL] = TAIKO_A_MICB_CFILT_2_VAL__POR,
+ [TAIKO_A_MICB_CFILT_2_PRECHRG] = TAIKO_A_MICB_CFILT_2_PRECHRG__POR,
+ [TAIKO_A_MICB_2_CTL] = TAIKO_A_MICB_2_CTL__POR,
+ [TAIKO_A_MICB_2_INT_RBIAS] = TAIKO_A_MICB_2_INT_RBIAS__POR,
+ [TAIKO_A_MICB_2_MBHC] = TAIKO_A_MICB_2_MBHC__POR,
+ [TAIKO_A_MICB_CFILT_3_CTL] = TAIKO_A_MICB_CFILT_3_CTL__POR,
+ [TAIKO_A_MICB_CFILT_3_VAL] = TAIKO_A_MICB_CFILT_3_VAL__POR,
+ [TAIKO_A_MICB_CFILT_3_PRECHRG] = TAIKO_A_MICB_CFILT_3_PRECHRG__POR,
+ [TAIKO_A_MICB_3_CTL] = TAIKO_A_MICB_3_CTL__POR,
+ [TAIKO_A_MICB_3_INT_RBIAS] = TAIKO_A_MICB_3_INT_RBIAS__POR,
+ [TAIKO_A_MICB_3_MBHC] = TAIKO_A_MICB_3_MBHC__POR,
+ [TAIKO_A_MICB_4_CTL] = TAIKO_A_MICB_4_CTL__POR,
+ [TAIKO_A_MICB_4_INT_RBIAS] = TAIKO_A_MICB_4_INT_RBIAS__POR,
+ [TAIKO_A_MICB_4_MBHC] = TAIKO_A_MICB_4_MBHC__POR,
+ [TAIKO_A_MBHC_INSERT_DETECT] = TAIKO_A_MBHC_INSERT_DETECT__POR,
+ [TAIKO_A_MBHC_INSERT_DET_STATUS] = TAIKO_A_MBHC_INSERT_DET_STATUS__POR,
+ [TAIKO_A_TX_COM_BIAS] = TAIKO_A_TX_COM_BIAS__POR,
+ [TAIKO_A_MBHC_SCALING_MUX_1] = TAIKO_A_MBHC_SCALING_MUX_1__POR,
+ [TAIKO_A_MBHC_SCALING_MUX_2] = TAIKO_A_MBHC_SCALING_MUX_2__POR,
+ [TAIKO_A_MAD_ANA_CTRL] = TAIKO_A_MAD_ANA_CTRL__POR,
+ [TAIKO_A_TX_SUP_SWITCH_CTRL_1] = TAIKO_A_TX_SUP_SWITCH_CTRL_1__POR,
+ [TAIKO_A_TX_SUP_SWITCH_CTRL_2] = TAIKO_A_TX_SUP_SWITCH_CTRL_2__POR,
+ [TAIKO_A_TX_1_2_EN] = TAIKO_A_TX_1_2_EN__POR,
+ [TAIKO_A_TX_1_2_TEST_EN] = TAIKO_A_TX_1_2_TEST_EN__POR,
+ [TAIKO_A_TX_1_2_ADC_CH1] = TAIKO_A_TX_1_2_ADC_CH1__POR,
+ [TAIKO_A_TX_1_2_ADC_CH2] = TAIKO_A_TX_1_2_ADC_CH2__POR,
+ [TAIKO_A_TX_1_2_ATEST_REFCTRL] = TAIKO_A_TX_1_2_ATEST_REFCTRL__POR,
+ [TAIKO_A_TX_1_2_TEST_CTL] = TAIKO_A_TX_1_2_TEST_CTL__POR,
+ [TAIKO_A_TX_1_2_TEST_BLOCK_EN] = TAIKO_A_TX_1_2_TEST_BLOCK_EN__POR,
+ [TAIKO_A_TX_1_2_TXFE_CLKDIV] = TAIKO_A_TX_1_2_TXFE_CLKDIV__POR,
+ [TAIKO_A_TX_1_2_SAR_ERR_CH1] = TAIKO_A_TX_1_2_SAR_ERR_CH1__POR,
+ [TAIKO_A_TX_1_2_SAR_ERR_CH2] = TAIKO_A_TX_1_2_SAR_ERR_CH2__POR,
+ [TAIKO_A_TX_3_4_EN] = TAIKO_A_TX_3_4_EN__POR,
+ [TAIKO_A_TX_3_4_TEST_EN] = TAIKO_A_TX_3_4_TEST_EN__POR,
+ [TAIKO_A_TX_3_4_ADC_CH3] = TAIKO_A_TX_3_4_ADC_CH3__POR,
+ [TAIKO_A_TX_3_4_ADC_CH4] = TAIKO_A_TX_3_4_ADC_CH4__POR,
+ [TAIKO_A_TX_3_4_ATEST_REFCTRL] = TAIKO_A_TX_3_4_ATEST_REFCTRL__POR,
+ [TAIKO_A_TX_3_4_TEST_CTL] = TAIKO_A_TX_3_4_TEST_CTL__POR,
+ [TAIKO_A_TX_3_4_TEST_BLOCK_EN] = TAIKO_A_TX_3_4_TEST_BLOCK_EN__POR,
+ [TAIKO_A_TX_3_4_TXFE_CKDIV] = TAIKO_A_TX_3_4_TXFE_CKDIV__POR,
+ [TAIKO_A_TX_3_4_SAR_ERR_CH3] = TAIKO_A_TX_3_4_SAR_ERR_CH3__POR,
+ [TAIKO_A_TX_3_4_SAR_ERR_CH4] = TAIKO_A_TX_3_4_SAR_ERR_CH4__POR,
+ [TAIKO_A_TX_5_6_EN] = TAIKO_A_TX_5_6_EN__POR,
+ [TAIKO_A_TX_5_6_TEST_EN] = TAIKO_A_TX_5_6_TEST_EN__POR,
+ [TAIKO_A_TX_5_6_ADC_CH5] = TAIKO_A_TX_5_6_ADC_CH5__POR,
+ [TAIKO_A_TX_5_6_ADC_CH6] = TAIKO_A_TX_5_6_ADC_CH6__POR,
+ [TAIKO_A_TX_5_6_ATEST_REFCTRL] = TAIKO_A_TX_5_6_ATEST_REFCTRL__POR,
+ [TAIKO_A_TX_5_6_TEST_CTL] = TAIKO_A_TX_5_6_TEST_CTL__POR,
+ [TAIKO_A_TX_5_6_TEST_BLOCK_EN] = TAIKO_A_TX_5_6_TEST_BLOCK_EN__POR,
+ [TAIKO_A_TX_5_6_TXFE_CKDIV] = TAIKO_A_TX_5_6_TXFE_CKDIV__POR,
+ [TAIKO_A_TX_5_6_SAR_ERR_CH5] = TAIKO_A_TX_5_6_SAR_ERR_CH5__POR,
+ [TAIKO_A_TX_5_6_SAR_ERR_CH6] = TAIKO_A_TX_5_6_SAR_ERR_CH6__POR,
+ [TAIKO_A_TX_7_MBHC_EN] = TAIKO_A_TX_7_MBHC_EN__POR,
+ [TAIKO_A_TX_7_MBHC_ATEST_REFCTRL] =
+ TAIKO_A_TX_7_MBHC_ATEST_REFCTRL__POR,
+ [TAIKO_A_TX_7_MBHC_ADC] = TAIKO_A_TX_7_MBHC_ADC__POR,
+ [TAIKO_A_TX_7_MBHC_TEST_CTL] = TAIKO_A_TX_7_MBHC_TEST_CTL__POR,
+ [TAIKO_A_TX_7_MBHC_SAR_ERR] = TAIKO_A_TX_7_MBHC_SAR_ERR__POR,
+ [TAIKO_A_TX_7_TXFE_CLKDIV] = TAIKO_A_TX_7_TXFE_CLKDIV__POR,
+ [TAIKO_A_BUCK_MODE_1] = TAIKO_A_BUCK_MODE_1__POR,
+ [TAIKO_A_BUCK_MODE_2] = TAIKO_A_BUCK_MODE_2__POR,
+ [TAIKO_A_BUCK_MODE_3] = TAIKO_A_BUCK_MODE_3__POR,
+ [TAIKO_A_BUCK_MODE_4] = TAIKO_A_BUCK_MODE_4__POR,
+ [TAIKO_A_BUCK_MODE_5] = TAIKO_A_BUCK_MODE_5__POR,
+ [TAIKO_A_BUCK_CTRL_VCL_1] = TAIKO_A_BUCK_CTRL_VCL_1__POR,
+ [TAIKO_A_BUCK_CTRL_VCL_2] = TAIKO_A_BUCK_CTRL_VCL_2__POR,
+ [TAIKO_A_BUCK_CTRL_VCL_3] = TAIKO_A_BUCK_CTRL_VCL_3__POR,
+ [TAIKO_A_BUCK_CTRL_CCL_1] = TAIKO_A_BUCK_CTRL_CCL_1__POR,
+ [TAIKO_A_BUCK_CTRL_CCL_2] = TAIKO_A_BUCK_CTRL_CCL_2__POR,
+ [TAIKO_A_BUCK_CTRL_CCL_3] = TAIKO_A_BUCK_CTRL_CCL_3__POR,
+ [TAIKO_A_BUCK_CTRL_CCL_4] = TAIKO_A_BUCK_CTRL_CCL_4__POR,
+ [TAIKO_A_BUCK_CTRL_PWM_DRVR_1] = TAIKO_A_BUCK_CTRL_PWM_DRVR_1__POR,
+ [TAIKO_A_BUCK_CTRL_PWM_DRVR_2] = TAIKO_A_BUCK_CTRL_PWM_DRVR_2__POR,
+ [TAIKO_A_BUCK_CTRL_PWM_DRVR_3] = TAIKO_A_BUCK_CTRL_PWM_DRVR_3__POR,
+ [TAIKO_A_BUCK_TMUX_A_D] = TAIKO_A_BUCK_TMUX_A_D__POR,
+ [TAIKO_A_NCP_BUCKREF] = TAIKO_A_NCP_BUCKREF__POR,
+ [TAIKO_A_NCP_EN] = TAIKO_A_NCP_EN__POR,
+ [TAIKO_A_NCP_CLK] = TAIKO_A_NCP_CLK__POR,
+ [TAIKO_A_NCP_STATIC] = TAIKO_A_NCP_STATIC__POR,
+ [TAIKO_A_NCP_VTH_LOW] = TAIKO_A_NCP_VTH_LOW__POR,
+ [TAIKO_A_NCP_VTH_HIGH] = TAIKO_A_NCP_VTH_HIGH__POR,
+ [TAIKO_A_NCP_ATEST] = TAIKO_A_NCP_ATEST__POR,
+ [TAIKO_A_NCP_DTEST] = TAIKO_A_NCP_DTEST__POR,
+ [TAIKO_A_NCP_DLY1] = TAIKO_A_NCP_DLY1__POR,
+ [TAIKO_A_NCP_DLY2] = TAIKO_A_NCP_DLY2__POR,
+ [TAIKO_A_RX_AUX_SW_CTL] = TAIKO_A_RX_AUX_SW_CTL__POR,
+ [TAIKO_A_RX_PA_AUX_IN_CONN] = TAIKO_A_RX_PA_AUX_IN_CONN__POR,
+ [TAIKO_A_RX_COM_TIMER_DIV] = TAIKO_A_RX_COM_TIMER_DIV__POR,
+ [TAIKO_A_RX_COM_OCP_CTL] = TAIKO_A_RX_COM_OCP_CTL__POR,
+ [TAIKO_A_RX_COM_OCP_COUNT] = TAIKO_A_RX_COM_OCP_COUNT__POR,
+ [TAIKO_A_RX_COM_DAC_CTL] = TAIKO_A_RX_COM_DAC_CTL__POR,
+ [TAIKO_A_RX_COM_BIAS] = TAIKO_A_RX_COM_BIAS__POR,
+ [TAIKO_A_RX_HPH_AUTO_CHOP] = TAIKO_A_RX_HPH_AUTO_CHOP__POR,
+ [TAIKO_A_RX_HPH_CHOP_CTL] = TAIKO_A_RX_HPH_CHOP_CTL__POR,
+ [TAIKO_A_RX_HPH_BIAS_PA] = TAIKO_A_RX_HPH_BIAS_PA__POR,
+ [TAIKO_A_RX_HPH_BIAS_LDO] = TAIKO_A_RX_HPH_BIAS_LDO__POR,
+ [TAIKO_A_RX_HPH_BIAS_CNP] = TAIKO_A_RX_HPH_BIAS_CNP__POR,
+ [TAIKO_A_RX_HPH_BIAS_WG_OCP] = TAIKO_A_RX_HPH_BIAS_WG_OCP__POR,
+ [TAIKO_A_RX_HPH_OCP_CTL] = TAIKO_A_RX_HPH_OCP_CTL__POR,
+ [TAIKO_A_RX_HPH_CNP_EN] = TAIKO_A_RX_HPH_CNP_EN__POR,
+ [TAIKO_A_RX_HPH_CNP_WG_CTL] = TAIKO_A_RX_HPH_CNP_WG_CTL__POR,
+ [TAIKO_A_RX_HPH_CNP_WG_TIME] = TAIKO_A_RX_HPH_CNP_WG_TIME__POR,
+ [TAIKO_A_RX_HPH_L_GAIN] = TAIKO_A_RX_HPH_L_GAIN__POR,
+ [TAIKO_A_RX_HPH_L_TEST] = TAIKO_A_RX_HPH_L_TEST__POR,
+ [TAIKO_A_RX_HPH_L_PA_CTL] = TAIKO_A_RX_HPH_L_PA_CTL__POR,
+ [TAIKO_A_RX_HPH_L_DAC_CTL] = TAIKO_A_RX_HPH_L_DAC_CTL__POR,
+ [TAIKO_A_RX_HPH_L_ATEST] = TAIKO_A_RX_HPH_L_ATEST__POR,
+ [TAIKO_A_RX_HPH_L_STATUS] = TAIKO_A_RX_HPH_L_STATUS__POR,
+ [TAIKO_A_RX_HPH_R_GAIN] = TAIKO_A_RX_HPH_R_GAIN__POR,
+ [TAIKO_A_RX_HPH_R_TEST] = TAIKO_A_RX_HPH_R_TEST__POR,
+ [TAIKO_A_RX_HPH_R_PA_CTL] = TAIKO_A_RX_HPH_R_PA_CTL__POR,
+ [TAIKO_A_RX_HPH_R_DAC_CTL] = TAIKO_A_RX_HPH_R_DAC_CTL__POR,
+ [TAIKO_A_RX_HPH_R_ATEST] = TAIKO_A_RX_HPH_R_ATEST__POR,
+ [TAIKO_A_RX_HPH_R_STATUS] = TAIKO_A_RX_HPH_R_STATUS__POR,
+ [TAIKO_A_RX_EAR_BIAS_PA] = TAIKO_A_RX_EAR_BIAS_PA__POR,
+ [TAIKO_A_RX_EAR_BIAS_CMBUFF] = TAIKO_A_RX_EAR_BIAS_CMBUFF__POR,
+ [TAIKO_A_RX_EAR_EN] = TAIKO_A_RX_EAR_EN__POR,
+ [TAIKO_A_RX_EAR_GAIN] = TAIKO_A_RX_EAR_GAIN__POR,
+ [TAIKO_A_RX_EAR_CMBUFF] = TAIKO_A_RX_EAR_CMBUFF__POR,
+ [TAIKO_A_RX_EAR_ICTL] = TAIKO_A_RX_EAR_ICTL__POR,
+ [TAIKO_A_RX_EAR_CCOMP] = TAIKO_A_RX_EAR_CCOMP__POR,
+ [TAIKO_A_RX_EAR_VCM] = TAIKO_A_RX_EAR_VCM__POR,
+ [TAIKO_A_RX_EAR_CNP] = TAIKO_A_RX_EAR_CNP__POR,
+ [TAIKO_A_RX_EAR_DAC_CTL_ATEST] = TAIKO_A_RX_EAR_DAC_CTL_ATEST__POR,
+ [TAIKO_A_RX_EAR_STATUS] = TAIKO_A_RX_EAR_STATUS__POR,
+ [TAIKO_A_RX_LINE_BIAS_PA] = TAIKO_A_RX_LINE_BIAS_PA__POR,
+ [TAIKO_A_RX_BUCK_BIAS1] = TAIKO_A_RX_BUCK_BIAS1__POR,
+ [TAIKO_A_RX_BUCK_BIAS2] = TAIKO_A_RX_BUCK_BIAS2__POR,
+ [TAIKO_A_RX_LINE_COM] = TAIKO_A_RX_LINE_COM__POR,
+ [TAIKO_A_RX_LINE_CNP_EN] = TAIKO_A_RX_LINE_CNP_EN__POR,
+ [TAIKO_A_RX_LINE_CNP_WG_CTL] = TAIKO_A_RX_LINE_CNP_WG_CTL__POR,
+ [TAIKO_A_RX_LINE_CNP_WG_TIME] = TAIKO_A_RX_LINE_CNP_WG_TIME__POR,
+ [TAIKO_A_RX_LINE_1_GAIN] = TAIKO_A_RX_LINE_1_GAIN__POR,
+ [TAIKO_A_RX_LINE_1_TEST] = TAIKO_A_RX_LINE_1_TEST__POR,
+ [TAIKO_A_RX_LINE_1_DAC_CTL] = TAIKO_A_RX_LINE_1_DAC_CTL__POR,
+ [TAIKO_A_RX_LINE_1_STATUS] = TAIKO_A_RX_LINE_1_STATUS__POR,
+ [TAIKO_A_RX_LINE_2_GAIN] = TAIKO_A_RX_LINE_2_GAIN__POR,
+ [TAIKO_A_RX_LINE_2_TEST] = TAIKO_A_RX_LINE_2_TEST__POR,
+ [TAIKO_A_RX_LINE_2_DAC_CTL] = TAIKO_A_RX_LINE_2_DAC_CTL__POR,
+ [TAIKO_A_RX_LINE_2_STATUS] = TAIKO_A_RX_LINE_2_STATUS__POR,
+ [TAIKO_A_RX_LINE_3_GAIN] = TAIKO_A_RX_LINE_3_GAIN__POR,
+ [TAIKO_A_RX_LINE_3_TEST] = TAIKO_A_RX_LINE_3_TEST__POR,
+ [TAIKO_A_RX_LINE_3_DAC_CTL] = TAIKO_A_RX_LINE_3_DAC_CTL__POR,
+ [TAIKO_A_RX_LINE_3_STATUS] = TAIKO_A_RX_LINE_3_STATUS__POR,
+ [TAIKO_A_RX_LINE_4_GAIN] = TAIKO_A_RX_LINE_4_GAIN__POR,
+ [TAIKO_A_RX_LINE_4_TEST] = TAIKO_A_RX_LINE_4_TEST__POR,
+ [TAIKO_A_RX_LINE_4_DAC_CTL] = TAIKO_A_RX_LINE_4_DAC_CTL__POR,
+ [TAIKO_A_RX_LINE_4_STATUS] = TAIKO_A_RX_LINE_4_STATUS__POR,
+ [TAIKO_A_RX_LINE_CNP_DBG] = TAIKO_A_RX_LINE_CNP_DBG__POR,
+ [TAIKO_A_SPKR_DRV_EN] = TAIKO_A_SPKR_DRV_EN__POR,
+ [TAIKO_A_SPKR_DRV_GAIN] = TAIKO_A_SPKR_DRV_GAIN__POR,
+ [TAIKO_A_SPKR_DRV_DAC_CTL] = TAIKO_A_SPKR_DRV_DAC_CTL__POR,
+ [TAIKO_A_SPKR_DRV_OCP_CTL] = TAIKO_A_SPKR_DRV_OCP_CTL__POR,
+ [TAIKO_A_SPKR_DRV_CLIP_DET] = TAIKO_A_SPKR_DRV_CLIP_DET__POR,
+ [TAIKO_A_SPKR_DRV_IEC] = TAIKO_A_SPKR_DRV_IEC__POR,
+ [TAIKO_A_SPKR_DRV_DBG_DAC] = TAIKO_A_SPKR_DRV_DBG_DAC__POR,
+ [TAIKO_A_SPKR_DRV_DBG_PA] = TAIKO_A_SPKR_DRV_DBG_PA__POR,
+ [TAIKO_A_SPKR_DRV_DBG_PWRSTG] = TAIKO_A_SPKR_DRV_DBG_PWRSTG__POR,
+ [TAIKO_A_SPKR_DRV_BIAS_LDO] = TAIKO_A_SPKR_DRV_BIAS_LDO__POR,
+ [TAIKO_A_SPKR_DRV_BIAS_INT] = TAIKO_A_SPKR_DRV_BIAS_INT__POR,
+ [TAIKO_A_SPKR_DRV_BIAS_PA] = TAIKO_A_SPKR_DRV_BIAS_PA__POR,
+ [TAIKO_A_SPKR_DRV_STATUS_OCP] = TAIKO_A_SPKR_DRV_STATUS_OCP__POR,
+ [TAIKO_A_SPKR_DRV_STATUS_PA] = TAIKO_A_SPKR_DRV_STATUS_PA__POR,
+ [TAIKO_A_SPKR_PROT_EN] = TAIKO_A_SPKR_PROT_EN__POR,
+ [TAIKO_A_SPKR_PROT_ADC_EN] = TAIKO_A_SPKR_PROT_ADC_EN__POR,
+ [TAIKO_A_SPKR_PROT_ISENSE_BIAS] = TAIKO_A_SPKR_PROT_ISENSE_BIAS__POR,
+ [TAIKO_A_SPKR_PROT_VSENSE_BIAS] = TAIKO_A_SPKR_PROT_VSENSE_BIAS__POR,
+ [TAIKO_A_SPKR_PROT_ADC_ATEST_REFCTRL] =
+ TAIKO_A_SPKR_PROT_ADC_ATEST_REFCTRL__POR,
+ [TAIKO_A_SPKR_PROT_ADC_TEST_CTL] = TAIKO_A_SPKR_PROT_ADC_TEST_CTL__POR,
+ [TAIKO_A_SPKR_PROT_TEST_BLOCK_EN] =
+ TAIKO_A_SPKR_PROT_TEST_BLOCK_EN__POR,
+ [TAIKO_A_SPKR_PROT_ATEST] = TAIKO_A_SPKR_PROT_ATEST__POR,
+ [TAIKO_A_SPKR_PROT_V_SAR_ERR] = TAIKO_A_SPKR_PROT_V_SAR_ERR__POR,
+ [TAIKO_A_SPKR_PROT_I_SAR_ERR] = TAIKO_A_SPKR_PROT_I_SAR_ERR__POR,
+ [TAIKO_A_SPKR_PROT_LDO_CTRL] = TAIKO_A_SPKR_PROT_LDO_CTRL__POR,
+ [TAIKO_A_SPKR_PROT_ISENSE_CTRL] = TAIKO_A_SPKR_PROT_ISENSE_CTRL__POR,
+ [TAIKO_A_SPKR_PROT_VSENSE_CTRL] = TAIKO_A_SPKR_PROT_VSENSE_CTRL__POR,
+ [TAIKO_A_RC_OSC_FREQ] = TAIKO_A_RC_OSC_FREQ__POR,
+ [TAIKO_A_RC_OSC_TEST] = TAIKO_A_RC_OSC_TEST__POR,
+ [TAIKO_A_RC_OSC_STATUS] = TAIKO_A_RC_OSC_STATUS__POR,
+ [TAIKO_A_RC_OSC_TUNER] = TAIKO_A_RC_OSC_TUNER__POR,
+ [TAIKO_A_MBHC_HPH] = TAIKO_A_MBHC_HPH__POR,
+ [TAIKO_A_CDC_ANC1_B1_CTL] = TAIKO_A_CDC_ANC1_B1_CTL__POR,
+ [TAIKO_A_CDC_ANC2_B1_CTL] = TAIKO_A_CDC_ANC2_B1_CTL__POR,
+ [TAIKO_A_CDC_ANC1_SHIFT] = TAIKO_A_CDC_ANC1_SHIFT__POR,
+ [TAIKO_A_CDC_ANC2_SHIFT] = TAIKO_A_CDC_ANC2_SHIFT__POR,
+ [TAIKO_A_CDC_ANC1_IIR_B1_CTL] = TAIKO_A_CDC_ANC1_IIR_B1_CTL__POR,
+ [TAIKO_A_CDC_ANC2_IIR_B1_CTL] = TAIKO_A_CDC_ANC2_IIR_B1_CTL__POR,
+ [TAIKO_A_CDC_ANC1_IIR_B2_CTL] = TAIKO_A_CDC_ANC1_IIR_B2_CTL__POR,
+ [TAIKO_A_CDC_ANC2_IIR_B2_CTL] = TAIKO_A_CDC_ANC2_IIR_B2_CTL__POR,
+ [TAIKO_A_CDC_ANC1_IIR_B3_CTL] = TAIKO_A_CDC_ANC1_IIR_B3_CTL__POR,
+ [TAIKO_A_CDC_ANC2_IIR_B3_CTL] = TAIKO_A_CDC_ANC2_IIR_B3_CTL__POR,
+ [TAIKO_A_CDC_ANC1_LPF_B1_CTL] = TAIKO_A_CDC_ANC1_LPF_B1_CTL__POR,
+ [TAIKO_A_CDC_ANC2_LPF_B1_CTL] = TAIKO_A_CDC_ANC2_LPF_B1_CTL__POR,
+ [TAIKO_A_CDC_ANC1_LPF_B2_CTL] = TAIKO_A_CDC_ANC1_LPF_B2_CTL__POR,
+ [TAIKO_A_CDC_ANC2_LPF_B2_CTL] = TAIKO_A_CDC_ANC2_LPF_B2_CTL__POR,
+ [TAIKO_A_CDC_ANC1_SPARE] = TAIKO_A_CDC_ANC1_SPARE__POR,
+ [TAIKO_A_CDC_ANC2_SPARE] = TAIKO_A_CDC_ANC2_SPARE__POR,
+ [TAIKO_A_CDC_ANC1_SMLPF_CTL] = TAIKO_A_CDC_ANC1_SMLPF_CTL__POR,
+ [TAIKO_A_CDC_ANC2_SMLPF_CTL] = TAIKO_A_CDC_ANC2_SMLPF_CTL__POR,
+ [TAIKO_A_CDC_ANC1_DCFLT_CTL] = TAIKO_A_CDC_ANC1_DCFLT_CTL__POR,
+ [TAIKO_A_CDC_ANC2_DCFLT_CTL] = TAIKO_A_CDC_ANC2_DCFLT_CTL__POR,
+ [TAIKO_A_CDC_ANC1_GAIN_CTL] = TAIKO_A_CDC_ANC1_GAIN_CTL__POR,
+ [TAIKO_A_CDC_ANC2_GAIN_CTL] = TAIKO_A_CDC_ANC2_GAIN_CTL__POR,
+ [TAIKO_A_CDC_ANC1_B2_CTL] = TAIKO_A_CDC_ANC1_B2_CTL__POR,
+ [TAIKO_A_CDC_ANC2_B2_CTL] = TAIKO_A_CDC_ANC2_B2_CTL__POR,
+ [TAIKO_A_CDC_TX1_VOL_CTL_TIMER] = TAIKO_A_CDC_TX1_VOL_CTL_TIMER__POR,
+ [TAIKO_A_CDC_TX2_VOL_CTL_TIMER] = TAIKO_A_CDC_TX2_VOL_CTL_TIMER__POR,
+ [TAIKO_A_CDC_TX3_VOL_CTL_TIMER] = TAIKO_A_CDC_TX3_VOL_CTL_TIMER__POR,
+ [TAIKO_A_CDC_TX4_VOL_CTL_TIMER] = TAIKO_A_CDC_TX4_VOL_CTL_TIMER__POR,
+ [TAIKO_A_CDC_TX5_VOL_CTL_TIMER] = TAIKO_A_CDC_TX5_VOL_CTL_TIMER__POR,
+ [TAIKO_A_CDC_TX6_VOL_CTL_TIMER] = TAIKO_A_CDC_TX6_VOL_CTL_TIMER__POR,
+ [TAIKO_A_CDC_TX7_VOL_CTL_TIMER] = TAIKO_A_CDC_TX7_VOL_CTL_TIMER__POR,
+ [TAIKO_A_CDC_TX8_VOL_CTL_TIMER] = TAIKO_A_CDC_TX8_VOL_CTL_TIMER__POR,
+ [TAIKO_A_CDC_TX9_VOL_CTL_TIMER] = TAIKO_A_CDC_TX9_VOL_CTL_TIMER__POR,
+ [TAIKO_A_CDC_TX10_VOL_CTL_TIMER] = TAIKO_A_CDC_TX10_VOL_CTL_TIMER__POR,
+ [TAIKO_A_CDC_TX1_VOL_CTL_GAIN] = TAIKO_A_CDC_TX1_VOL_CTL_GAIN__POR,
+ [TAIKO_A_CDC_TX2_VOL_CTL_GAIN] = TAIKO_A_CDC_TX2_VOL_CTL_GAIN__POR,
+ [TAIKO_A_CDC_TX3_VOL_CTL_GAIN] = TAIKO_A_CDC_TX3_VOL_CTL_GAIN__POR,
+ [TAIKO_A_CDC_TX4_VOL_CTL_GAIN] = TAIKO_A_CDC_TX4_VOL_CTL_GAIN__POR,
+ [TAIKO_A_CDC_TX5_VOL_CTL_GAIN] = TAIKO_A_CDC_TX5_VOL_CTL_GAIN__POR,
+ [TAIKO_A_CDC_TX6_VOL_CTL_GAIN] = TAIKO_A_CDC_TX6_VOL_CTL_GAIN__POR,
+ [TAIKO_A_CDC_TX7_VOL_CTL_GAIN] = TAIKO_A_CDC_TX7_VOL_CTL_GAIN__POR,
+ [TAIKO_A_CDC_TX8_VOL_CTL_GAIN] = TAIKO_A_CDC_TX8_VOL_CTL_GAIN__POR,
+ [TAIKO_A_CDC_TX9_VOL_CTL_GAIN] = TAIKO_A_CDC_TX9_VOL_CTL_GAIN__POR,
+ [TAIKO_A_CDC_TX10_VOL_CTL_GAIN] = TAIKO_A_CDC_TX10_VOL_CTL_GAIN__POR,
+ [TAIKO_A_CDC_TX1_VOL_CTL_CFG] = TAIKO_A_CDC_TX1_VOL_CTL_CFG__POR,
+ [TAIKO_A_CDC_TX2_VOL_CTL_CFG] = TAIKO_A_CDC_TX2_VOL_CTL_CFG__POR,
+ [TAIKO_A_CDC_TX3_VOL_CTL_CFG] = TAIKO_A_CDC_TX3_VOL_CTL_CFG__POR,
+ [TAIKO_A_CDC_TX4_VOL_CTL_CFG] = TAIKO_A_CDC_TX4_VOL_CTL_CFG__POR,
+ [TAIKO_A_CDC_TX5_VOL_CTL_CFG] = TAIKO_A_CDC_TX5_VOL_CTL_CFG__POR,
+ [TAIKO_A_CDC_TX6_VOL_CTL_CFG] = TAIKO_A_CDC_TX6_VOL_CTL_CFG__POR,
+ [TAIKO_A_CDC_TX7_VOL_CTL_CFG] = TAIKO_A_CDC_TX7_VOL_CTL_CFG__POR,
+ [TAIKO_A_CDC_TX8_VOL_CTL_CFG] = TAIKO_A_CDC_TX8_VOL_CTL_CFG__POR,
+ [TAIKO_A_CDC_TX9_VOL_CTL_CFG] = TAIKO_A_CDC_TX9_VOL_CTL_CFG__POR,
+ [TAIKO_A_CDC_TX10_VOL_CTL_CFG] = TAIKO_A_CDC_TX10_VOL_CTL_CFG__POR,
+ [TAIKO_A_CDC_TX1_MUX_CTL] = TAIKO_A_CDC_TX1_MUX_CTL__POR,
+ [TAIKO_A_CDC_TX2_MUX_CTL] = TAIKO_A_CDC_TX2_MUX_CTL__POR,
+ [TAIKO_A_CDC_TX3_MUX_CTL] = TAIKO_A_CDC_TX3_MUX_CTL__POR,
+ [TAIKO_A_CDC_TX4_MUX_CTL] = TAIKO_A_CDC_TX4_MUX_CTL__POR,
+ [TAIKO_A_CDC_TX5_MUX_CTL] = TAIKO_A_CDC_TX5_MUX_CTL__POR,
+ [TAIKO_A_CDC_TX6_MUX_CTL] = TAIKO_A_CDC_TX6_MUX_CTL__POR,
+ [TAIKO_A_CDC_TX7_MUX_CTL] = TAIKO_A_CDC_TX7_MUX_CTL__POR,
+ [TAIKO_A_CDC_TX8_MUX_CTL] = TAIKO_A_CDC_TX8_MUX_CTL__POR,
+ [TAIKO_A_CDC_TX9_MUX_CTL] = TAIKO_A_CDC_TX9_MUX_CTL__POR,
+ [TAIKO_A_CDC_TX10_MUX_CTL] = TAIKO_A_CDC_TX10_MUX_CTL__POR,
+ [TAIKO_A_CDC_TX1_CLK_FS_CTL] = TAIKO_A_CDC_TX1_CLK_FS_CTL__POR,
+ [TAIKO_A_CDC_TX2_CLK_FS_CTL] = TAIKO_A_CDC_TX2_CLK_FS_CTL__POR,
+ [TAIKO_A_CDC_TX3_CLK_FS_CTL] = TAIKO_A_CDC_TX3_CLK_FS_CTL__POR,
+ [TAIKO_A_CDC_TX4_CLK_FS_CTL] = TAIKO_A_CDC_TX4_CLK_FS_CTL__POR,
+ [TAIKO_A_CDC_TX5_CLK_FS_CTL] = TAIKO_A_CDC_TX5_CLK_FS_CTL__POR,
+ [TAIKO_A_CDC_TX6_CLK_FS_CTL] = TAIKO_A_CDC_TX6_CLK_FS_CTL__POR,
+ [TAIKO_A_CDC_TX7_CLK_FS_CTL] = TAIKO_A_CDC_TX7_CLK_FS_CTL__POR,
+ [TAIKO_A_CDC_TX8_CLK_FS_CTL] = TAIKO_A_CDC_TX8_CLK_FS_CTL__POR,
+ [TAIKO_A_CDC_TX9_CLK_FS_CTL] = TAIKO_A_CDC_TX9_CLK_FS_CTL__POR,
+ [TAIKO_A_CDC_TX10_CLK_FS_CTL] = TAIKO_A_CDC_TX10_CLK_FS_CTL__POR,
+ [TAIKO_A_CDC_TX1_DMIC_CTL] = TAIKO_A_CDC_TX1_DMIC_CTL__POR,
+ [TAIKO_A_CDC_TX2_DMIC_CTL] = TAIKO_A_CDC_TX2_DMIC_CTL__POR,
+ [TAIKO_A_CDC_TX3_DMIC_CTL] = TAIKO_A_CDC_TX3_DMIC_CTL__POR,
+ [TAIKO_A_CDC_TX4_DMIC_CTL] = TAIKO_A_CDC_TX4_DMIC_CTL__POR,
+ [TAIKO_A_CDC_TX5_DMIC_CTL] = TAIKO_A_CDC_TX5_DMIC_CTL__POR,
+ [TAIKO_A_CDC_TX6_DMIC_CTL] = TAIKO_A_CDC_TX6_DMIC_CTL__POR,
+ [TAIKO_A_CDC_TX7_DMIC_CTL] = TAIKO_A_CDC_TX7_DMIC_CTL__POR,
+ [TAIKO_A_CDC_TX8_DMIC_CTL] = TAIKO_A_CDC_TX8_DMIC_CTL__POR,
+ [TAIKO_A_CDC_TX9_DMIC_CTL] = TAIKO_A_CDC_TX9_DMIC_CTL__POR,
+ [TAIKO_A_CDC_TX10_DMIC_CTL] = TAIKO_A_CDC_TX10_DMIC_CTL__POR,
+ [TAIKO_A_CDC_DEBUG_B1_CTL] = TAIKO_A_CDC_DEBUG_B1_CTL__POR,
+ [TAIKO_A_CDC_DEBUG_B2_CTL] = TAIKO_A_CDC_DEBUG_B2_CTL__POR,
+ [TAIKO_A_CDC_DEBUG_B3_CTL] = TAIKO_A_CDC_DEBUG_B3_CTL__POR,
+ [TAIKO_A_CDC_DEBUG_B4_CTL] = TAIKO_A_CDC_DEBUG_B4_CTL__POR,
+ [TAIKO_A_CDC_DEBUG_B5_CTL] = TAIKO_A_CDC_DEBUG_B5_CTL__POR,
+ [TAIKO_A_CDC_DEBUG_B6_CTL] = TAIKO_A_CDC_DEBUG_B6_CTL__POR,
+ [TAIKO_A_CDC_DEBUG_B7_CTL] = TAIKO_A_CDC_DEBUG_B7_CTL__POR,
+ [TAIKO_A_CDC_SRC1_PDA_CFG] = TAIKO_A_CDC_SRC1_PDA_CFG__POR,
+ [TAIKO_A_CDC_SRC2_PDA_CFG] = TAIKO_A_CDC_SRC2_PDA_CFG__POR,
+ [TAIKO_A_CDC_SRC1_FS_CTL] = TAIKO_A_CDC_SRC1_FS_CTL__POR,
+ [TAIKO_A_CDC_SRC2_FS_CTL] = TAIKO_A_CDC_SRC2_FS_CTL__POR,
+ [TAIKO_A_CDC_RX1_B1_CTL] = TAIKO_A_CDC_RX1_B1_CTL__POR,
+ [TAIKO_A_CDC_RX2_B1_CTL] = TAIKO_A_CDC_RX2_B1_CTL__POR,
+ [TAIKO_A_CDC_RX3_B1_CTL] = TAIKO_A_CDC_RX3_B1_CTL__POR,
+ [TAIKO_A_CDC_RX4_B1_CTL] = TAIKO_A_CDC_RX4_B1_CTL__POR,
+ [TAIKO_A_CDC_RX5_B1_CTL] = TAIKO_A_CDC_RX5_B1_CTL__POR,
+ [TAIKO_A_CDC_RX6_B1_CTL] = TAIKO_A_CDC_RX6_B1_CTL__POR,
+ [TAIKO_A_CDC_RX7_B1_CTL] = TAIKO_A_CDC_RX7_B1_CTL__POR,
+ [TAIKO_A_CDC_RX1_B2_CTL] = TAIKO_A_CDC_RX1_B2_CTL__POR,
+ [TAIKO_A_CDC_RX2_B2_CTL] = TAIKO_A_CDC_RX2_B2_CTL__POR,
+ [TAIKO_A_CDC_RX3_B2_CTL] = TAIKO_A_CDC_RX3_B2_CTL__POR,
+ [TAIKO_A_CDC_RX4_B2_CTL] = TAIKO_A_CDC_RX4_B2_CTL__POR,
+ [TAIKO_A_CDC_RX5_B2_CTL] = TAIKO_A_CDC_RX5_B2_CTL__POR,
+ [TAIKO_A_CDC_RX6_B2_CTL] = TAIKO_A_CDC_RX6_B2_CTL__POR,
+ [TAIKO_A_CDC_RX7_B2_CTL] = TAIKO_A_CDC_RX7_B2_CTL__POR,
+ [TAIKO_A_CDC_RX1_B3_CTL] = TAIKO_A_CDC_RX1_B3_CTL__POR,
+ [TAIKO_A_CDC_RX2_B3_CTL] = TAIKO_A_CDC_RX2_B3_CTL__POR,
+ [TAIKO_A_CDC_RX3_B3_CTL] = TAIKO_A_CDC_RX3_B3_CTL__POR,
+ [TAIKO_A_CDC_RX4_B3_CTL] = TAIKO_A_CDC_RX4_B3_CTL__POR,
+ [TAIKO_A_CDC_RX5_B3_CTL] = TAIKO_A_CDC_RX5_B3_CTL__POR,
+ [TAIKO_A_CDC_RX6_B3_CTL] = TAIKO_A_CDC_RX6_B3_CTL__POR,
+ [TAIKO_A_CDC_RX7_B3_CTL] = TAIKO_A_CDC_RX7_B3_CTL__POR,
+ [TAIKO_A_CDC_RX1_B4_CTL] = TAIKO_A_CDC_RX1_B4_CTL__POR,
+ [TAIKO_A_CDC_RX2_B4_CTL] = TAIKO_A_CDC_RX2_B4_CTL__POR,
+ [TAIKO_A_CDC_RX3_B4_CTL] = TAIKO_A_CDC_RX3_B4_CTL__POR,
+ [TAIKO_A_CDC_RX4_B4_CTL] = TAIKO_A_CDC_RX4_B4_CTL__POR,
+ [TAIKO_A_CDC_RX5_B4_CTL] = TAIKO_A_CDC_RX5_B4_CTL__POR,
+ [TAIKO_A_CDC_RX6_B4_CTL] = TAIKO_A_CDC_RX6_B4_CTL__POR,
+ [TAIKO_A_CDC_RX7_B4_CTL] = TAIKO_A_CDC_RX7_B4_CTL__POR,
+ [TAIKO_A_CDC_RX1_B5_CTL] = TAIKO_A_CDC_RX1_B5_CTL__POR,
+ [TAIKO_A_CDC_RX2_B5_CTL] = TAIKO_A_CDC_RX2_B5_CTL__POR,
+ [TAIKO_A_CDC_RX3_B5_CTL] = TAIKO_A_CDC_RX3_B5_CTL__POR,
+ [TAIKO_A_CDC_RX4_B5_CTL] = TAIKO_A_CDC_RX4_B5_CTL__POR,
+ [TAIKO_A_CDC_RX5_B5_CTL] = TAIKO_A_CDC_RX5_B5_CTL__POR,
+ [TAIKO_A_CDC_RX6_B5_CTL] = TAIKO_A_CDC_RX6_B5_CTL__POR,
+ [TAIKO_A_CDC_RX7_B5_CTL] = TAIKO_A_CDC_RX7_B5_CTL__POR,
+ [TAIKO_A_CDC_RX1_B6_CTL] = TAIKO_A_CDC_RX1_B6_CTL__POR,
+ [TAIKO_A_CDC_RX2_B6_CTL] = TAIKO_A_CDC_RX2_B6_CTL__POR,
+ [TAIKO_A_CDC_RX3_B6_CTL] = TAIKO_A_CDC_RX3_B6_CTL__POR,
+ [TAIKO_A_CDC_RX4_B6_CTL] = TAIKO_A_CDC_RX4_B6_CTL__POR,
+ [TAIKO_A_CDC_RX5_B6_CTL] = TAIKO_A_CDC_RX5_B6_CTL__POR,
+ [TAIKO_A_CDC_RX6_B6_CTL] = TAIKO_A_CDC_RX6_B6_CTL__POR,
+ [TAIKO_A_CDC_RX7_B6_CTL] = TAIKO_A_CDC_RX7_B6_CTL__POR,
+ [TAIKO_A_CDC_RX1_VOL_CTL_B1_CTL] = TAIKO_A_CDC_RX1_VOL_CTL_B1_CTL__POR,
+ [TAIKO_A_CDC_RX2_VOL_CTL_B1_CTL] = TAIKO_A_CDC_RX2_VOL_CTL_B1_CTL__POR,
+ [TAIKO_A_CDC_RX3_VOL_CTL_B1_CTL] = TAIKO_A_CDC_RX3_VOL_CTL_B1_CTL__POR,
+ [TAIKO_A_CDC_RX4_VOL_CTL_B1_CTL] = TAIKO_A_CDC_RX4_VOL_CTL_B1_CTL__POR,
+ [TAIKO_A_CDC_RX5_VOL_CTL_B1_CTL] = TAIKO_A_CDC_RX5_VOL_CTL_B1_CTL__POR,
+ [TAIKO_A_CDC_RX6_VOL_CTL_B1_CTL] = TAIKO_A_CDC_RX6_VOL_CTL_B1_CTL__POR,
+ [TAIKO_A_CDC_RX7_VOL_CTL_B1_CTL] = TAIKO_A_CDC_RX7_VOL_CTL_B1_CTL__POR,
+ [TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL] = TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL__POR,
+ [TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL] = TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL__POR,
+ [TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL] = TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL__POR,
+ [TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL] = TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL__POR,
+ [TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL] = TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL__POR,
+ [TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL] = TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL__POR,
+ [TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL] = TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL__POR,
+ [TAIKO_A_CDC_VBAT_CFG] = TAIKO_A_CDC_VBAT_CFG__POR,
+ [TAIKO_A_CDC_VBAT_ADC_CAL1] = TAIKO_A_CDC_VBAT_ADC_CAL1__POR,
+ [TAIKO_A_CDC_VBAT_ADC_CAL2] = TAIKO_A_CDC_VBAT_ADC_CAL2__POR,
+ [TAIKO_A_CDC_VBAT_ADC_CAL3] = TAIKO_A_CDC_VBAT_ADC_CAL3__POR,
+ [TAIKO_A_CDC_VBAT_PK_EST1] = TAIKO_A_CDC_VBAT_PK_EST1__POR,
+ [TAIKO_A_CDC_VBAT_PK_EST2] = TAIKO_A_CDC_VBAT_PK_EST2__POR,
+ [TAIKO_A_CDC_VBAT_PK_EST3] = TAIKO_A_CDC_VBAT_PK_EST3__POR,
+ [TAIKO_A_CDC_VBAT_RF_PROC1] = TAIKO_A_CDC_VBAT_RF_PROC1__POR,
+ [TAIKO_A_CDC_VBAT_RF_PROC2] = TAIKO_A_CDC_VBAT_RF_PROC2__POR,
+ [TAIKO_A_CDC_VBAT_TAC1] = TAIKO_A_CDC_VBAT_TAC1__POR,
+ [TAIKO_A_CDC_VBAT_TAC2] = TAIKO_A_CDC_VBAT_TAC2__POR,
+ [TAIKO_A_CDC_VBAT_TAC3] = TAIKO_A_CDC_VBAT_TAC3__POR,
+ [TAIKO_A_CDC_VBAT_TAC4] = TAIKO_A_CDC_VBAT_TAC4__POR,
+ [TAIKO_A_CDC_VBAT_GAIN_UPD1] = TAIKO_A_CDC_VBAT_GAIN_UPD1__POR,
+ [TAIKO_A_CDC_VBAT_GAIN_UPD2] = TAIKO_A_CDC_VBAT_GAIN_UPD2__POR,
+ [TAIKO_A_CDC_VBAT_GAIN_UPD3] = TAIKO_A_CDC_VBAT_GAIN_UPD3__POR,
+ [TAIKO_A_CDC_VBAT_GAIN_UPD4] = TAIKO_A_CDC_VBAT_GAIN_UPD4__POR,
+ [TAIKO_A_CDC_VBAT_DEBUG1] = TAIKO_A_CDC_VBAT_DEBUG1__POR,
+ [TAIKO_A_CDC_CLK_ANC_RESET_CTL] = TAIKO_A_CDC_CLK_ANC_RESET_CTL__POR,
+ [TAIKO_A_CDC_CLK_RX_RESET_CTL] = TAIKO_A_CDC_CLK_RX_RESET_CTL__POR,
+ [TAIKO_A_CDC_CLK_TX_RESET_B1_CTL] =
+ TAIKO_A_CDC_CLK_TX_RESET_B1_CTL__POR,
+ [TAIKO_A_CDC_CLK_TX_RESET_B2_CTL] =
+ TAIKO_A_CDC_CLK_TX_RESET_B2_CTL__POR,
+ [TAIKO_A_CDC_CLK_DMIC_B1_CTL] = TAIKO_A_CDC_CLK_DMIC_B1_CTL__POR,
+ [TAIKO_A_CDC_CLK_DMIC_B2_CTL] = TAIKO_A_CDC_CLK_DMIC_B2_CTL__POR,
+ [TAIKO_A_CDC_CLK_RX_I2S_CTL] = TAIKO_A_CDC_CLK_RX_I2S_CTL__POR,
+ [TAIKO_A_CDC_CLK_TX_I2S_CTL] = TAIKO_A_CDC_CLK_TX_I2S_CTL__POR,
+ [TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL] =
+ TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL__POR,
+ [TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL] =
+ TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL__POR,
+ [TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL] =
+ TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL__POR,
+ [TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL] =
+ TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL__POR,
+ [TAIKO_A_CDC_CLK_OTHR_CTL] = TAIKO_A_CDC_CLK_OTHR_CTL__POR,
+ [TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL] =
+ TAIKO_A_CDC_CLK_RDAC_CLK_EN_CTL__POR,
+ [TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL] = TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL__POR,
+ [TAIKO_A_CDC_CLK_RX_B1_CTL] = TAIKO_A_CDC_CLK_RX_B1_CTL__POR,
+ [TAIKO_A_CDC_CLK_RX_B2_CTL] = TAIKO_A_CDC_CLK_RX_B2_CTL__POR,
+ [TAIKO_A_CDC_CLK_MCLK_CTL] = TAIKO_A_CDC_CLK_MCLK_CTL__POR,
+ [TAIKO_A_CDC_CLK_PDM_CTL] = TAIKO_A_CDC_CLK_PDM_CTL__POR,
+ [TAIKO_A_CDC_CLK_SD_CTL] = TAIKO_A_CDC_CLK_SD_CTL__POR,
+ [TAIKO_A_CDC_CLK_POWER_CTL] = TAIKO_A_CDC_CLK_POWER_CTL__POR,
+ [TAIKO_A_CDC_CLSH_B1_CTL] = TAIKO_A_CDC_CLSH_B1_CTL__POR,
+ [TAIKO_A_CDC_CLSH_B2_CTL] = TAIKO_A_CDC_CLSH_B2_CTL__POR,
+ [TAIKO_A_CDC_CLSH_B3_CTL] = TAIKO_A_CDC_CLSH_B3_CTL__POR,
+ [TAIKO_A_CDC_CLSH_BUCK_NCP_VARS] = TAIKO_A_CDC_CLSH_BUCK_NCP_VARS__POR,
+ [TAIKO_A_CDC_CLSH_IDLE_HPH_THSD] = TAIKO_A_CDC_CLSH_IDLE_HPH_THSD__POR,
+ [TAIKO_A_CDC_CLSH_IDLE_EAR_THSD] = TAIKO_A_CDC_CLSH_IDLE_EAR_THSD__POR,
+ [TAIKO_A_CDC_CLSH_FCLKONLY_HPH_THSD] =
+ TAIKO_A_CDC_CLSH_FCLKONLY_HPH_THSD__POR,
+ [TAIKO_A_CDC_CLSH_FCLKONLY_EAR_THSD] =
+ TAIKO_A_CDC_CLSH_FCLKONLY_EAR_THSD__POR,
+ [TAIKO_A_CDC_CLSH_K_ADDR] = TAIKO_A_CDC_CLSH_K_ADDR__POR,
+ [TAIKO_A_CDC_CLSH_K_DATA] = TAIKO_A_CDC_CLSH_K_DATA__POR,
+ [TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_L] =
+ TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_L__POR,
+ [TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_U] =
+ TAIKO_A_CDC_CLSH_I_PA_FACT_HPH_U__POR,
+ [TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_L] =
+ TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_L__POR,
+ [TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_U] =
+ TAIKO_A_CDC_CLSH_I_PA_FACT_EAR_U__POR,
+ [TAIKO_A_CDC_CLSH_V_PA_HD_EAR] = TAIKO_A_CDC_CLSH_V_PA_HD_EAR__POR,
+ [TAIKO_A_CDC_CLSH_V_PA_HD_HPH] = TAIKO_A_CDC_CLSH_V_PA_HD_HPH__POR,
+ [TAIKO_A_CDC_CLSH_V_PA_MIN_EAR] = TAIKO_A_CDC_CLSH_V_PA_MIN_EAR__POR,
+ [TAIKO_A_CDC_CLSH_V_PA_MIN_HPH] = TAIKO_A_CDC_CLSH_V_PA_MIN_HPH__POR,
+ [TAIKO_A_CDC_IIR1_GAIN_B1_CTL] = TAIKO_A_CDC_IIR1_GAIN_B1_CTL__POR,
+ [TAIKO_A_CDC_IIR2_GAIN_B1_CTL] = TAIKO_A_CDC_IIR2_GAIN_B1_CTL__POR,
+ [TAIKO_A_CDC_IIR1_GAIN_B2_CTL] = TAIKO_A_CDC_IIR1_GAIN_B2_CTL__POR,
+ [TAIKO_A_CDC_IIR2_GAIN_B2_CTL] = TAIKO_A_CDC_IIR2_GAIN_B2_CTL__POR,
+ [TAIKO_A_CDC_IIR1_GAIN_B3_CTL] = TAIKO_A_CDC_IIR1_GAIN_B3_CTL__POR,
+ [TAIKO_A_CDC_IIR2_GAIN_B3_CTL] = TAIKO_A_CDC_IIR2_GAIN_B3_CTL__POR,
+ [TAIKO_A_CDC_IIR1_GAIN_B4_CTL] = TAIKO_A_CDC_IIR1_GAIN_B4_CTL__POR,
+ [TAIKO_A_CDC_IIR2_GAIN_B4_CTL] = TAIKO_A_CDC_IIR2_GAIN_B4_CTL__POR,
+ [TAIKO_A_CDC_IIR1_GAIN_B5_CTL] = TAIKO_A_CDC_IIR1_GAIN_B5_CTL__POR,
+ [TAIKO_A_CDC_IIR2_GAIN_B5_CTL] = TAIKO_A_CDC_IIR2_GAIN_B5_CTL__POR,
+ [TAIKO_A_CDC_IIR1_GAIN_B6_CTL] = TAIKO_A_CDC_IIR1_GAIN_B6_CTL__POR,
+ [TAIKO_A_CDC_IIR2_GAIN_B6_CTL] = TAIKO_A_CDC_IIR2_GAIN_B6_CTL__POR,
+ [TAIKO_A_CDC_IIR1_GAIN_B7_CTL] = TAIKO_A_CDC_IIR1_GAIN_B7_CTL__POR,
+ [TAIKO_A_CDC_IIR2_GAIN_B7_CTL] = TAIKO_A_CDC_IIR2_GAIN_B7_CTL__POR,
+ [TAIKO_A_CDC_IIR1_GAIN_B8_CTL] = TAIKO_A_CDC_IIR1_GAIN_B8_CTL__POR,
+ [TAIKO_A_CDC_IIR2_GAIN_B8_CTL] = TAIKO_A_CDC_IIR2_GAIN_B8_CTL__POR,
+ [TAIKO_A_CDC_IIR1_CTL] = TAIKO_A_CDC_IIR1_CTL__POR,
+ [TAIKO_A_CDC_IIR2_CTL] = TAIKO_A_CDC_IIR2_CTL__POR,
+ [TAIKO_A_CDC_IIR1_GAIN_TIMER_CTL] =
+ TAIKO_A_CDC_IIR1_GAIN_TIMER_CTL__POR,
+ [TAIKO_A_CDC_IIR2_GAIN_TIMER_CTL] =
+ TAIKO_A_CDC_IIR2_GAIN_TIMER_CTL__POR,
+ [TAIKO_A_CDC_IIR1_COEF_B1_CTL] = TAIKO_A_CDC_IIR1_COEF_B1_CTL__POR,
+ [TAIKO_A_CDC_IIR2_COEF_B1_CTL] = TAIKO_A_CDC_IIR2_COEF_B1_CTL__POR,
+ [TAIKO_A_CDC_IIR1_COEF_B2_CTL] = TAIKO_A_CDC_IIR1_COEF_B2_CTL__POR,
+ [TAIKO_A_CDC_IIR2_COEF_B2_CTL] = TAIKO_A_CDC_IIR2_COEF_B2_CTL__POR,
+ [TAIKO_A_CDC_TOP_GAIN_UPDATE] = TAIKO_A_CDC_TOP_GAIN_UPDATE__POR,
+ [TAIKO_A_CDC_COMP0_B1_CTL] = TAIKO_A_CDC_COMP0_B1_CTL__POR,
+ [TAIKO_A_CDC_COMP1_B1_CTL] = TAIKO_A_CDC_COMP1_B1_CTL__POR,
+ [TAIKO_A_CDC_COMP2_B1_CTL] = TAIKO_A_CDC_COMP2_B1_CTL__POR,
+ [TAIKO_A_CDC_COMP0_B2_CTL] = TAIKO_A_CDC_COMP0_B2_CTL__POR,
+ [TAIKO_A_CDC_COMP1_B2_CTL] = TAIKO_A_CDC_COMP1_B2_CTL__POR,
+ [TAIKO_A_CDC_COMP2_B2_CTL] = TAIKO_A_CDC_COMP2_B2_CTL__POR,
+ [TAIKO_A_CDC_COMP0_B3_CTL] = TAIKO_A_CDC_COMP0_B3_CTL__POR,
+ [TAIKO_A_CDC_COMP1_B3_CTL] = TAIKO_A_CDC_COMP1_B3_CTL__POR,
+ [TAIKO_A_CDC_COMP2_B3_CTL] = TAIKO_A_CDC_COMP2_B3_CTL__POR,
+ [TAIKO_A_CDC_COMP0_B4_CTL] = TAIKO_A_CDC_COMP0_B4_CTL__POR,
+ [TAIKO_A_CDC_COMP1_B4_CTL] = TAIKO_A_CDC_COMP1_B4_CTL__POR,
+ [TAIKO_A_CDC_COMP2_B4_CTL] = TAIKO_A_CDC_COMP2_B4_CTL__POR,
+ [TAIKO_A_CDC_COMP0_B5_CTL] = TAIKO_A_CDC_COMP0_B5_CTL__POR,
+ [TAIKO_A_CDC_COMP1_B5_CTL] = TAIKO_A_CDC_COMP1_B5_CTL__POR,
+ [TAIKO_A_CDC_COMP2_B5_CTL] = TAIKO_A_CDC_COMP2_B5_CTL__POR,
+ [TAIKO_A_CDC_COMP0_B6_CTL] = TAIKO_A_CDC_COMP0_B6_CTL__POR,
+ [TAIKO_A_CDC_COMP1_B6_CTL] = TAIKO_A_CDC_COMP1_B6_CTL__POR,
+ [TAIKO_A_CDC_COMP2_B6_CTL] = TAIKO_A_CDC_COMP2_B6_CTL__POR,
+ [TAIKO_A_CDC_COMP0_SHUT_DOWN_STATUS] =
+ TAIKO_A_CDC_COMP0_SHUT_DOWN_STATUS__POR,
+ [TAIKO_A_CDC_COMP1_SHUT_DOWN_STATUS] =
+ TAIKO_A_CDC_COMP1_SHUT_DOWN_STATUS__POR,
+ [TAIKO_A_CDC_COMP2_SHUT_DOWN_STATUS] =
+ TAIKO_A_CDC_COMP2_SHUT_DOWN_STATUS__POR,
+ [TAIKO_A_CDC_COMP0_FS_CFG] = TAIKO_A_CDC_COMP0_FS_CFG__POR,
+ [TAIKO_A_CDC_COMP1_FS_CFG] = TAIKO_A_CDC_COMP1_FS_CFG__POR,
+ [TAIKO_A_CDC_COMP2_FS_CFG] = TAIKO_A_CDC_COMP2_FS_CFG__POR,
+ [TAIKO_A_CDC_CONN_RX1_B1_CTL] = TAIKO_A_CDC_CONN_RX1_B1_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX1_B2_CTL] = TAIKO_A_CDC_CONN_RX1_B2_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX1_B3_CTL] = TAIKO_A_CDC_CONN_RX1_B3_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX2_B1_CTL] = TAIKO_A_CDC_CONN_RX2_B1_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX2_B2_CTL] = TAIKO_A_CDC_CONN_RX2_B2_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX2_B3_CTL] = TAIKO_A_CDC_CONN_RX2_B3_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX3_B1_CTL] = TAIKO_A_CDC_CONN_RX3_B1_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX3_B2_CTL] = TAIKO_A_CDC_CONN_RX3_B2_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX4_B1_CTL] = TAIKO_A_CDC_CONN_RX4_B1_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX4_B2_CTL] = TAIKO_A_CDC_CONN_RX4_B2_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX5_B1_CTL] = TAIKO_A_CDC_CONN_RX5_B1_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX5_B2_CTL] = TAIKO_A_CDC_CONN_RX5_B2_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX6_B1_CTL] = TAIKO_A_CDC_CONN_RX6_B1_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX6_B2_CTL] = TAIKO_A_CDC_CONN_RX6_B2_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX7_B1_CTL] = TAIKO_A_CDC_CONN_RX7_B1_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX7_B2_CTL] = TAIKO_A_CDC_CONN_RX7_B2_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX7_B3_CTL] = TAIKO_A_CDC_CONN_RX7_B3_CTL__POR,
+ [TAIKO_A_CDC_CONN_ANC_B1_CTL] = TAIKO_A_CDC_CONN_ANC_B1_CTL__POR,
+ [TAIKO_A_CDC_CONN_ANC_B2_CTL] = TAIKO_A_CDC_CONN_ANC_B2_CTL__POR,
+ [TAIKO_A_CDC_CONN_TX_B1_CTL] = TAIKO_A_CDC_CONN_TX_B1_CTL__POR,
+ [TAIKO_A_CDC_CONN_TX_B2_CTL] = TAIKO_A_CDC_CONN_TX_B2_CTL__POR,
+ [TAIKO_A_CDC_CONN_TX_B3_CTL] = TAIKO_A_CDC_CONN_TX_B3_CTL__POR,
+ [TAIKO_A_CDC_CONN_TX_B4_CTL] = TAIKO_A_CDC_CONN_TX_B4_CTL__POR,
+ [TAIKO_A_CDC_CONN_EQ1_B1_CTL] = TAIKO_A_CDC_CONN_EQ1_B1_CTL__POR,
+ [TAIKO_A_CDC_CONN_EQ1_B2_CTL] = TAIKO_A_CDC_CONN_EQ1_B2_CTL__POR,
+ [TAIKO_A_CDC_CONN_EQ1_B3_CTL] = TAIKO_A_CDC_CONN_EQ1_B3_CTL__POR,
+ [TAIKO_A_CDC_CONN_EQ1_B4_CTL] = TAIKO_A_CDC_CONN_EQ1_B4_CTL__POR,
+ [TAIKO_A_CDC_CONN_EQ2_B1_CTL] = TAIKO_A_CDC_CONN_EQ2_B1_CTL__POR,
+ [TAIKO_A_CDC_CONN_EQ2_B2_CTL] = TAIKO_A_CDC_CONN_EQ2_B2_CTL__POR,
+ [TAIKO_A_CDC_CONN_EQ2_B3_CTL] = TAIKO_A_CDC_CONN_EQ2_B3_CTL__POR,
+ [TAIKO_A_CDC_CONN_EQ2_B4_CTL] = TAIKO_A_CDC_CONN_EQ2_B4_CTL__POR,
+ [TAIKO_A_CDC_CONN_SRC1_B1_CTL] = TAIKO_A_CDC_CONN_SRC1_B1_CTL__POR,
+ [TAIKO_A_CDC_CONN_SRC1_B2_CTL] = TAIKO_A_CDC_CONN_SRC1_B2_CTL__POR,
+ [TAIKO_A_CDC_CONN_SRC2_B1_CTL] = TAIKO_A_CDC_CONN_SRC2_B1_CTL__POR,
+ [TAIKO_A_CDC_CONN_SRC2_B2_CTL] = TAIKO_A_CDC_CONN_SRC2_B2_CTL__POR,
+ [TAIKO_A_CDC_CONN_TX_SB_B1_CTL] = TAIKO_A_CDC_CONN_TX_SB_B1_CTL__POR,
+ [TAIKO_A_CDC_CONN_TX_SB_B2_CTL] = TAIKO_A_CDC_CONN_TX_SB_B2_CTL__POR,
+ [TAIKO_A_CDC_CONN_TX_SB_B3_CTL] = TAIKO_A_CDC_CONN_TX_SB_B3_CTL__POR,
+ [TAIKO_A_CDC_CONN_TX_SB_B4_CTL] = TAIKO_A_CDC_CONN_TX_SB_B4_CTL__POR,
+ [TAIKO_A_CDC_CONN_TX_SB_B5_CTL] = TAIKO_A_CDC_CONN_TX_SB_B5_CTL__POR,
+ [TAIKO_A_CDC_CONN_TX_SB_B6_CTL] = TAIKO_A_CDC_CONN_TX_SB_B6_CTL__POR,
+ [TAIKO_A_CDC_CONN_TX_SB_B7_CTL] = TAIKO_A_CDC_CONN_TX_SB_B7_CTL__POR,
+ [TAIKO_A_CDC_CONN_TX_SB_B8_CTL] = TAIKO_A_CDC_CONN_TX_SB_B8_CTL__POR,
+ [TAIKO_A_CDC_CONN_TX_SB_B9_CTL] = TAIKO_A_CDC_CONN_TX_SB_B9_CTL__POR,
+ [TAIKO_A_CDC_CONN_TX_SB_B10_CTL] = TAIKO_A_CDC_CONN_TX_SB_B10_CTL__POR,
+ [TAIKO_A_CDC_CONN_TX_SB_B11_CTL] = TAIKO_A_CDC_CONN_TX_SB_B11_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX_SB_B1_CTL] = TAIKO_A_CDC_CONN_RX_SB_B1_CTL__POR,
+ [TAIKO_A_CDC_CONN_RX_SB_B2_CTL] = TAIKO_A_CDC_CONN_RX_SB_B2_CTL__POR,
+ [TAIKO_A_CDC_CONN_CLSH_CTL] = TAIKO_A_CDC_CONN_CLSH_CTL__POR,
+ [TAIKO_A_CDC_CONN_MISC] = TAIKO_A_CDC_CONN_MISC__POR,
+ [TAIKO_A_CDC_CONN_MAD] = TAIKO_A_CDC_CONN_MAD__POR,
+ [TAIKO_A_CDC_MBHC_EN_CTL] = TAIKO_A_CDC_MBHC_EN_CTL__POR,
+ [TAIKO_A_CDC_MBHC_FIR_B1_CFG] = TAIKO_A_CDC_MBHC_FIR_B1_CFG__POR,
+ [TAIKO_A_CDC_MBHC_FIR_B2_CFG] = TAIKO_A_CDC_MBHC_FIR_B2_CFG__POR,
+ [TAIKO_A_CDC_MBHC_TIMER_B1_CTL] = TAIKO_A_CDC_MBHC_TIMER_B1_CTL__POR,
+ [TAIKO_A_CDC_MBHC_TIMER_B2_CTL] = TAIKO_A_CDC_MBHC_TIMER_B2_CTL__POR,
+ [TAIKO_A_CDC_MBHC_TIMER_B3_CTL] = TAIKO_A_CDC_MBHC_TIMER_B3_CTL__POR,
+ [TAIKO_A_CDC_MBHC_TIMER_B4_CTL] = TAIKO_A_CDC_MBHC_TIMER_B4_CTL__POR,
+ [TAIKO_A_CDC_MBHC_TIMER_B5_CTL] = TAIKO_A_CDC_MBHC_TIMER_B5_CTL__POR,
+ [TAIKO_A_CDC_MBHC_TIMER_B6_CTL] = TAIKO_A_CDC_MBHC_TIMER_B6_CTL__POR,
+ [TAIKO_A_CDC_MBHC_B1_STATUS] = TAIKO_A_CDC_MBHC_B1_STATUS__POR,
+ [TAIKO_A_CDC_MBHC_B2_STATUS] = TAIKO_A_CDC_MBHC_B2_STATUS__POR,
+ [TAIKO_A_CDC_MBHC_B3_STATUS] = TAIKO_A_CDC_MBHC_B3_STATUS__POR,
+ [TAIKO_A_CDC_MBHC_B4_STATUS] = TAIKO_A_CDC_MBHC_B4_STATUS__POR,
+ [TAIKO_A_CDC_MBHC_B5_STATUS] = TAIKO_A_CDC_MBHC_B5_STATUS__POR,
+ [TAIKO_A_CDC_MBHC_B1_CTL] = TAIKO_A_CDC_MBHC_B1_CTL__POR,
+ [TAIKO_A_CDC_MBHC_B2_CTL] = TAIKO_A_CDC_MBHC_B2_CTL__POR,
+ [TAIKO_A_CDC_MBHC_VOLT_B1_CTL] = TAIKO_A_CDC_MBHC_VOLT_B1_CTL__POR,
+ [TAIKO_A_CDC_MBHC_VOLT_B2_CTL] = TAIKO_A_CDC_MBHC_VOLT_B2_CTL__POR,
+ [TAIKO_A_CDC_MBHC_VOLT_B3_CTL] = TAIKO_A_CDC_MBHC_VOLT_B3_CTL__POR,
+ [TAIKO_A_CDC_MBHC_VOLT_B4_CTL] = TAIKO_A_CDC_MBHC_VOLT_B4_CTL__POR,
+ [TAIKO_A_CDC_MBHC_VOLT_B5_CTL] = TAIKO_A_CDC_MBHC_VOLT_B5_CTL__POR,
+ [TAIKO_A_CDC_MBHC_VOLT_B6_CTL] = TAIKO_A_CDC_MBHC_VOLT_B6_CTL__POR,
+ [TAIKO_A_CDC_MBHC_VOLT_B7_CTL] = TAIKO_A_CDC_MBHC_VOLT_B7_CTL__POR,
+ [TAIKO_A_CDC_MBHC_VOLT_B8_CTL] = TAIKO_A_CDC_MBHC_VOLT_B8_CTL__POR,
+ [TAIKO_A_CDC_MBHC_VOLT_B9_CTL] = TAIKO_A_CDC_MBHC_VOLT_B9_CTL__POR,
+ [TAIKO_A_CDC_MBHC_VOLT_B10_CTL] = TAIKO_A_CDC_MBHC_VOLT_B10_CTL__POR,
+ [TAIKO_A_CDC_MBHC_VOLT_B11_CTL] = TAIKO_A_CDC_MBHC_VOLT_B11_CTL__POR,
+ [TAIKO_A_CDC_MBHC_VOLT_B12_CTL] = TAIKO_A_CDC_MBHC_VOLT_B12_CTL__POR,
+ [TAIKO_A_CDC_MBHC_CLK_CTL] = TAIKO_A_CDC_MBHC_CLK_CTL__POR,
+ [TAIKO_A_CDC_MBHC_INT_CTL] = TAIKO_A_CDC_MBHC_INT_CTL__POR,
+ [TAIKO_A_CDC_MBHC_DEBUG_CTL] = TAIKO_A_CDC_MBHC_DEBUG_CTL__POR,
+ [TAIKO_A_CDC_MBHC_SPARE] = TAIKO_A_CDC_MBHC_SPARE__POR,
+ [TAIKO_A_CDC_MAD_MAIN_CTL_1] = TAIKO_A_CDC_MAD_MAIN_CTL_1__POR,
+ [TAIKO_A_CDC_MAD_MAIN_CTL_2] = TAIKO_A_CDC_MAD_MAIN_CTL_2__POR,
+ [TAIKO_A_CDC_MAD_AUDIO_CTL_1] = TAIKO_A_CDC_MAD_AUDIO_CTL_1__POR,
+ [TAIKO_A_CDC_MAD_AUDIO_CTL_2] = TAIKO_A_CDC_MAD_AUDIO_CTL_2__POR,
+ [TAIKO_A_CDC_MAD_AUDIO_CTL_3] = TAIKO_A_CDC_MAD_AUDIO_CTL_3__POR,
+ [TAIKO_A_CDC_MAD_AUDIO_CTL_4] = TAIKO_A_CDC_MAD_AUDIO_CTL_4__POR,
+ [TAIKO_A_CDC_MAD_AUDIO_CTL_5] = TAIKO_A_CDC_MAD_AUDIO_CTL_5__POR,
+ [TAIKO_A_CDC_MAD_AUDIO_CTL_6] = TAIKO_A_CDC_MAD_AUDIO_CTL_6__POR,
+ [TAIKO_A_CDC_MAD_AUDIO_CTL_7] = TAIKO_A_CDC_MAD_AUDIO_CTL_7__POR,
+ [TAIKO_A_CDC_MAD_AUDIO_CTL_8] = TAIKO_A_CDC_MAD_AUDIO_CTL_8__POR,
+ [TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_PTR] =
+ TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_PTR__POR,
+ [TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_VAL] =
+ TAIKO_A_CDC_MAD_AUDIO_IIR_CTL_VAL__POR,
+ [TAIKO_A_CDC_MAD_ULTR_CTL_1] = TAIKO_A_CDC_MAD_ULTR_CTL_1__POR,
+ [TAIKO_A_CDC_MAD_ULTR_CTL_2] = TAIKO_A_CDC_MAD_ULTR_CTL_2__POR,
+ [TAIKO_A_CDC_MAD_ULTR_CTL_3] = TAIKO_A_CDC_MAD_ULTR_CTL_3__POR,
+ [TAIKO_A_CDC_MAD_ULTR_CTL_4] = TAIKO_A_CDC_MAD_ULTR_CTL_4__POR,
+ [TAIKO_A_CDC_MAD_ULTR_CTL_5] = TAIKO_A_CDC_MAD_ULTR_CTL_5__POR,
+ [TAIKO_A_CDC_MAD_ULTR_CTL_6] = TAIKO_A_CDC_MAD_ULTR_CTL_6__POR,
+ [TAIKO_A_CDC_MAD_ULTR_CTL_7] = TAIKO_A_CDC_MAD_ULTR_CTL_7__POR,
+ [TAIKO_A_CDC_MAD_BEACON_CTL_1] = TAIKO_A_CDC_MAD_BEACON_CTL_1__POR,
+ [TAIKO_A_CDC_MAD_BEACON_CTL_2] = TAIKO_A_CDC_MAD_BEACON_CTL_2__POR,
+ [TAIKO_A_CDC_MAD_BEACON_CTL_3] = TAIKO_A_CDC_MAD_BEACON_CTL_3__POR,
+ [TAIKO_A_CDC_MAD_BEACON_CTL_4] = TAIKO_A_CDC_MAD_BEACON_CTL_4__POR,
+ [TAIKO_A_CDC_MAD_BEACON_CTL_5] = TAIKO_A_CDC_MAD_BEACON_CTL_5__POR,
+ [TAIKO_A_CDC_MAD_BEACON_CTL_6] = TAIKO_A_CDC_MAD_BEACON_CTL_6__POR,
+ [TAIKO_A_CDC_MAD_BEACON_CTL_7] = TAIKO_A_CDC_MAD_BEACON_CTL_7__POR,
+ [TAIKO_A_CDC_MAD_BEACON_CTL_8] = TAIKO_A_CDC_MAD_BEACON_CTL_8__POR,
+ [TAIKO_A_CDC_MAD_BEACON_IIR_CTL_PTR] =
+ TAIKO_A_CDC_MAD_BEACON_IIR_CTL_PTR__POR,
+ [TAIKO_A_CDC_MAD_BEACON_IIR_CTL_VAL] =
+ TAIKO_A_CDC_MAD_BEACON_IIR_CTL_VAL__POR,
+};
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
new file mode 100644
index 0000000..67a5d8a
--- /dev/null
+++ b/sound/soc/codecs/wcd9320.c
@@ -0,0 +1,7471 @@
+/* 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/init.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/device.h>
+#include <linux/printk.h>
+#include <linux/ratelimit.h>
+#include <linux/debugfs.h>
+#include <linux/mfd/wcd9xxx/core.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
+#include <linux/mfd/wcd9xxx/wcd9320_registers.h>
+#include <linux/mfd/wcd9xxx/pdata.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include "wcd9320.h"
+
+#define WCD9320_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
+ SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
+
+
+#define NUM_DECIMATORS 10
+#define NUM_INTERPOLATORS 7
+#define BITS_PER_REG 8
+#define TAIKO_CFILT_FAST_MODE 0x00
+#define TAIKO_CFILT_SLOW_MODE 0x40
+#define MBHC_FW_READ_ATTEMPTS 15
+#define MBHC_FW_READ_TIMEOUT 2000000
+
+enum {
+ MBHC_USE_HPHL_TRIGGER = 1,
+ MBHC_USE_MB_TRIGGER = 2
+};
+
+#define MBHC_NUM_DCE_PLUG_DETECT 3
+#define NUM_ATTEMPTS_INSERT_DETECT 25
+#define NUM_ATTEMPTS_TO_REPORT 5
+
+#define TAIKO_JACK_MASK (SND_JACK_HEADSET | SND_JACK_OC_HPHL | \
+ SND_JACK_OC_HPHR | SND_JACK_UNSUPPORTED)
+
+#define TAIKO_I2S_MASTER_MODE_MASK 0x08
+
+#define TAIKO_OCP_ATTEMPT 1
+
+#define AIF1_PB 1
+#define AIF1_CAP 2
+#define AIF2_PB 3
+#define AIF2_CAP 4
+#define AIF3_CAP 5
+#define AIF3_PB 6
+
+#define NUM_CODEC_DAIS 6
+#define TAIKO_COMP_DIGITAL_GAIN_OFFSET 3
+
+struct taiko_codec_dai_data {
+ u32 rate;
+ u32 *ch_num;
+ u32 ch_act;
+ u32 ch_tot;
+};
+
+#define TAIKO_MCLK_RATE_12288KHZ 12288000
+#define TAIKO_MCLK_RATE_9600KHZ 9600000
+
+#define TAIKO_FAKE_INS_THRESHOLD_MS 2500
+#define TAIKO_FAKE_REMOVAL_MIN_PERIOD_MS 50
+
+#define TAIKO_MBHC_BUTTON_MIN 0x8000
+
+#define TAIKO_MBHC_FAKE_INSERT_LOW 10
+#define TAIKO_MBHC_FAKE_INSERT_HIGH 80
+#define TAIKO_MBHC_FAKE_INS_HIGH_NO_GPIO 150
+
+#define TAIKO_MBHC_STATUS_REL_DETECTION 0x0C
+
+#define TAIKO_MBHC_GPIO_REL_DEBOUNCE_TIME_MS 200
+
+#define TAIKO_MBHC_FAKE_INS_DELTA_MV 200
+#define TAIKO_MBHC_FAKE_INS_DELTA_SCALED_MV 300
+
+#define TAIKO_HS_DETECT_PLUG_TIME_MS (5 * 1000)
+#define TAIKO_HS_DETECT_PLUG_INERVAL_MS 100
+
+#define TAIKO_GPIO_IRQ_DEBOUNCE_TIME_US 5000
+
+#define TAIKO_MBHC_GND_MIC_SWAP_THRESHOLD 2
+
+#define TAIKO_ACQUIRE_LOCK(x) do { mutex_lock(&x); } while (0)
+#define TAIKO_RELEASE_LOCK(x) do { mutex_unlock(&x); } while (0)
+
+static const DECLARE_TLV_DB_SCALE(digital_gain, 0, 1, 0);
+static const DECLARE_TLV_DB_SCALE(line_gain, 0, 7, 1);
+static const DECLARE_TLV_DB_SCALE(analog_gain, 0, 25, 1);
+static struct snd_soc_dai_driver taiko_dai[];
+static const DECLARE_TLV_DB_SCALE(aux_pga_gain, 0, 2, 0);
+
+enum taiko_bandgap_type {
+ TAIKO_BANDGAP_OFF = 0,
+ TAIKO_BANDGAP_AUDIO_MODE,
+ TAIKO_BANDGAP_MBHC_MODE,
+};
+
+struct mbhc_micbias_regs {
+ u16 cfilt_val;
+ u16 cfilt_ctl;
+ u16 mbhc_reg;
+ u16 int_rbias;
+ u16 ctl_reg;
+ u8 cfilt_sel;
+};
+
+/* Codec supports 2 IIR filters */
+enum {
+ IIR1 = 0,
+ IIR2,
+ IIR_MAX,
+};
+/* Codec supports 5 bands */
+enum {
+ BAND1 = 0,
+ BAND2,
+ BAND3,
+ BAND4,
+ BAND5,
+ BAND_MAX,
+};
+
+enum {
+ COMPANDER_1 = 0,
+ COMPANDER_2,
+ COMPANDER_MAX,
+};
+
+enum {
+ COMPANDER_FS_8KHZ = 0,
+ COMPANDER_FS_16KHZ,
+ COMPANDER_FS_32KHZ,
+ COMPANDER_FS_48KHZ,
+ COMPANDER_FS_96KHZ,
+ COMPANDER_FS_192KHZ,
+ COMPANDER_FS_MAX,
+};
+
+/* Flags to track of PA and DAC state.
+ * PA and DAC should be tracked separately as AUXPGA loopback requires
+ * only PA to be turned on without DAC being on. */
+enum taiko_priv_ack_flags {
+ TAIKO_HPHL_PA_OFF_ACK = 0,
+ TAIKO_HPHR_PA_OFF_ACK,
+ TAIKO_HPHL_DAC_OFF_ACK,
+ TAIKO_HPHR_DAC_OFF_ACK
+};
+
+
+struct comp_sample_dependent_params {
+ u32 peak_det_timeout;
+ u32 rms_meter_div_fact;
+ u32 rms_meter_resamp_fact;
+};
+
+/* Data used by MBHC */
+struct mbhc_internal_cal_data {
+ u16 dce_z;
+ u16 dce_mb;
+ u16 sta_z;
+ u16 sta_mb;
+ u32 t_sta_dce;
+ u32 t_dce;
+ u32 t_sta;
+ u32 micb_mv;
+ u16 v_ins_hu;
+ u16 v_ins_h;
+ u16 v_b1_hu;
+ u16 v_b1_h;
+ u16 v_b1_huc;
+ u16 v_brh;
+ u16 v_brl;
+ u16 v_no_mic;
+ u8 npoll;
+ u8 nbounce_wait;
+ s16 adj_v_hs_max;
+ u16 adj_v_ins_hu;
+ u16 adj_v_ins_h;
+ s16 v_inval_ins_low;
+ s16 v_inval_ins_high;
+};
+
+struct taiko_reg_address {
+ u16 micb_4_ctl;
+ u16 micb_4_int_rbias;
+ u16 micb_4_mbhc;
+};
+
+enum taiko_mbhc_plug_type {
+ PLUG_TYPE_INVALID = -1,
+ PLUG_TYPE_NONE,
+ PLUG_TYPE_HEADSET,
+ PLUG_TYPE_HEADPHONE,
+ PLUG_TYPE_HIGH_HPH,
+ PLUG_TYPE_GND_MIC_SWAP,
+};
+
+enum taiko_mbhc_state {
+ MBHC_STATE_NONE = -1,
+ MBHC_STATE_POTENTIAL,
+ MBHC_STATE_POTENTIAL_RECOVERY,
+ MBHC_STATE_RELEASE,
+};
+
+struct hpf_work {
+ struct taiko_priv *taiko;
+ u32 decimator;
+ u8 tx_hpf_cut_of_freq;
+ struct delayed_work dwork;
+};
+
+static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
+
+struct taiko_priv {
+ struct snd_soc_codec *codec;
+ struct taiko_reg_address reg_addr;
+ u32 adc_count;
+ u32 cfilt1_cnt;
+ u32 cfilt2_cnt;
+ u32 cfilt3_cnt;
+ u32 rx_bias_count;
+ s32 dmic_1_2_clk_cnt;
+ s32 dmic_3_4_clk_cnt;
+ s32 dmic_5_6_clk_cnt;
+
+ enum taiko_bandgap_type bandgap_type;
+ bool mclk_enabled;
+ bool clock_active;
+ bool config_mode_active;
+ bool mbhc_polling_active;
+ unsigned long mbhc_fake_ins_start;
+ int buttons_pressed;
+ enum taiko_mbhc_state mbhc_state;
+ struct taiko_mbhc_config mbhc_cfg;
+ struct mbhc_internal_cal_data mbhc_data;
+
+ struct wcd9xxx_pdata *pdata;
+ u32 anc_slot;
+
+ bool no_mic_headset_override;
+ /* Delayed work to report long button press */
+ struct delayed_work mbhc_btn_dwork;
+
+ struct mbhc_micbias_regs mbhc_bias_regs;
+ bool mbhc_micbias_switched;
+
+ /* track PA/DAC state */
+ unsigned long hph_pa_dac_state;
+
+ /*track taiko interface type*/
+ u8 intf_type;
+
+ u32 hph_status; /* track headhpone status */
+ /* define separate work for left and right headphone OCP to avoid
+ * additional checking on which OCP event to report so no locking
+ * to ensure synchronization is required
+ */
+ struct work_struct hphlocp_work; /* reporting left hph ocp off */
+ struct work_struct hphrocp_work; /* reporting right hph ocp off */
+
+ u8 hphlocp_cnt; /* headphone left ocp retry */
+ u8 hphrocp_cnt; /* headphone right ocp retry */
+
+ /* Work to perform MBHC Firmware Read */
+ struct delayed_work mbhc_firmware_dwork;
+ const struct firmware *mbhc_fw;
+
+ /* num of slim ports required */
+ struct taiko_codec_dai_data dai[NUM_CODEC_DAIS];
+
+ /*compander*/
+ int comp_enabled[COMPANDER_MAX];
+ u32 comp_fs[COMPANDER_MAX];
+
+ /* Maintain the status of AUX PGA */
+ int aux_pga_cnt;
+ u8 aux_l_gain;
+ u8 aux_r_gain;
+
+ struct delayed_work mbhc_insert_dwork;
+ unsigned long mbhc_last_resume; /* in jiffies */
+
+ u8 current_plug;
+ struct work_struct hs_correct_plug_work;
+ bool hs_detect_work_stop;
+ bool hs_polling_irq_prepared;
+ bool lpi_enabled; /* low power insertion detection */
+ bool in_gpio_handler;
+ /* Currently, only used for mbhc purpose, to protect
+ * concurrent execution of mbhc threaded irq handlers and
+ * kill race between DAPM and MBHC.But can serve as a
+ * general lock to protect codec resource
+ */
+ struct mutex codec_resource_lock;
+
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debugfs_poke;
+ struct dentry *debugfs_mbhc;
+#endif
+};
+
+
+static const u32 comp_shift[] = {
+ 0,
+ 2,
+};
+
+static const int comp_rx_path[] = {
+ COMPANDER_1,
+ COMPANDER_1,
+ COMPANDER_2,
+ COMPANDER_2,
+ COMPANDER_2,
+ COMPANDER_2,
+ COMPANDER_MAX,
+};
+
+static const struct comp_sample_dependent_params comp_samp_params[] = {
+ {
+ .peak_det_timeout = 0x2,
+ .rms_meter_div_fact = 0x8 << 4,
+ .rms_meter_resamp_fact = 0x21,
+ },
+ {
+ .peak_det_timeout = 0x3,
+ .rms_meter_div_fact = 0x9 << 4,
+ .rms_meter_resamp_fact = 0x28,
+ },
+
+ {
+ .peak_det_timeout = 0x5,
+ .rms_meter_div_fact = 0xB << 4,
+ .rms_meter_resamp_fact = 0x28,
+ },
+
+ {
+ .peak_det_timeout = 0x5,
+ .rms_meter_div_fact = 0xB << 4,
+ .rms_meter_resamp_fact = 0x28,
+ },
+};
+
+static unsigned short rx_digital_gain_reg[] = {
+ TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL,
+ TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL,
+ TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL,
+ TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL,
+ TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL,
+ TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL,
+ TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL,
+};
+
+
+static unsigned short tx_digital_gain_reg[] = {
+ TAIKO_A_CDC_TX1_VOL_CTL_GAIN,
+ TAIKO_A_CDC_TX2_VOL_CTL_GAIN,
+ TAIKO_A_CDC_TX3_VOL_CTL_GAIN,
+ TAIKO_A_CDC_TX4_VOL_CTL_GAIN,
+ TAIKO_A_CDC_TX5_VOL_CTL_GAIN,
+ TAIKO_A_CDC_TX6_VOL_CTL_GAIN,
+ TAIKO_A_CDC_TX7_VOL_CTL_GAIN,
+ TAIKO_A_CDC_TX8_VOL_CTL_GAIN,
+ TAIKO_A_CDC_TX9_VOL_CTL_GAIN,
+ TAIKO_A_CDC_TX10_VOL_CTL_GAIN,
+};
+
+static int taiko_codec_enable_charge_pump(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ pr_debug("%s %d\n", __func__, event);
+
+ /* FIX . need to use CLASS-H controller */
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_CTL, 0x01,
+ 0x01);
+ usleep_range(200, 200);
+ snd_soc_update_bits(codec, TAIKO_A_NCP_STATIC, 0x10, 0x00);
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_RESET_B1_CTL,
+ 0x01, 0x01);
+ usleep_range(20, 20);
+ snd_soc_update_bits(codec, TAIKO_A_NCP_STATIC, 0x08, 0x08);
+ snd_soc_update_bits(codec, TAIKO_A_NCP_STATIC, 0x10, 0x10);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_CTL, 0x01,
+ 0x00);
+ snd_soc_update_bits(codec, TAIKO_A_NCP_STATIC, 0x08, 0x00);
+ break;
+ }
+ return 0;
+}
+
+static int taiko_get_anc_slot(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ ucontrol->value.integer.value[0] = taiko->anc_slot;
+ return 0;
+}
+
+static int taiko_put_anc_slot(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ taiko->anc_slot = ucontrol->value.integer.value[0];
+ return 0;
+}
+
+static int taiko_pa_gain_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 ear_pa_gain;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ ear_pa_gain = snd_soc_read(codec, TAIKO_A_RX_EAR_GAIN);
+
+ ear_pa_gain = ear_pa_gain >> 5;
+
+ if (ear_pa_gain == 0x00) {
+ ucontrol->value.integer.value[0] = 0;
+ } else if (ear_pa_gain == 0x04) {
+ ucontrol->value.integer.value[0] = 1;
+ } else {
+ pr_err("%s: ERROR: Unsupported Ear Gain = 0x%x\n",
+ __func__, ear_pa_gain);
+ return -EINVAL;
+ }
+
+ pr_debug("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
+
+ return 0;
+}
+
+static int taiko_pa_gain_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u8 ear_pa_gain;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ pr_debug("%s: ucontrol->value.integer.value[0] = %ld\n", __func__,
+ ucontrol->value.integer.value[0]);
+
+ switch (ucontrol->value.integer.value[0]) {
+ case 0:
+ ear_pa_gain = 0x00;
+ break;
+ case 1:
+ ear_pa_gain = 0x80;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, TAIKO_A_RX_EAR_GAIN, 0xE0, ear_pa_gain);
+ return 0;
+}
+
+static int taiko_get_iir_enable_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ ucontrol->value.integer.value[0] =
+ snd_soc_read(codec, (TAIKO_A_CDC_IIR1_CTL + 16 * iir_idx)) &
+ (1 << band_idx);
+
+ pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
+ iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[0]);
+ return 0;
+}
+
+static int taiko_put_iir_enable_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+ int value = ucontrol->value.integer.value[0];
+
+ /* Mask first 5 bits, 6-8 are reserved */
+ snd_soc_update_bits(codec, (TAIKO_A_CDC_IIR1_CTL + 16 * iir_idx),
+ (1 << band_idx), (value << band_idx));
+
+ pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
+ iir_idx, band_idx, value);
+ return 0;
+}
+static uint32_t get_iir_band_coeff(struct snd_soc_codec *codec,
+ int iir_idx, int band_idx,
+ int coeff_idx)
+{
+ /* Address does not automatically update if reading */
+ snd_soc_write(codec,
+ (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
+ (band_idx * BAND_MAX + coeff_idx) & 0x1F);
+
+ /* Mask bits top 2 bits since they are reserved */
+ return ((snd_soc_read(codec,
+ (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx)) << 24)) &
+ 0x3FFFFFFF;
+}
+
+static int taiko_get_iir_band_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ ucontrol->value.integer.value[0] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 0);
+ ucontrol->value.integer.value[1] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 1);
+ ucontrol->value.integer.value[2] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 2);
+ ucontrol->value.integer.value[3] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 3);
+ ucontrol->value.integer.value[4] =
+ get_iir_band_coeff(codec, iir_idx, band_idx, 4);
+
+ pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
+ "%s: IIR #%d band #%d b1 = 0x%x\n"
+ "%s: IIR #%d band #%d b2 = 0x%x\n"
+ "%s: IIR #%d band #%d a1 = 0x%x\n"
+ "%s: IIR #%d band #%d a2 = 0x%x\n",
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[0],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[1],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[2],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[3],
+ __func__, iir_idx, band_idx,
+ (uint32_t)ucontrol->value.integer.value[4]);
+ return 0;
+}
+
+static void set_iir_band_coeff(struct snd_soc_codec *codec,
+ int iir_idx, int band_idx,
+ int coeff_idx, uint32_t value)
+{
+ /* Mask top 3 bits, 6-8 are reserved */
+ /* Update address manually each time */
+ snd_soc_write(codec,
+ (TAIKO_A_CDC_IIR1_COEF_B1_CTL + 16 * iir_idx),
+ (band_idx * BAND_MAX + coeff_idx) & 0x1F);
+
+ /* Mask top 2 bits, 7-8 are reserved */
+ snd_soc_write(codec,
+ (TAIKO_A_CDC_IIR1_COEF_B2_CTL + 16 * iir_idx),
+ (value >> 24) & 0x3F);
+
+}
+
+static int taiko_put_iir_band_audio_mixer(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int iir_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->reg;
+ int band_idx = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->shift;
+
+ set_iir_band_coeff(codec, iir_idx, band_idx, 0,
+ ucontrol->value.integer.value[0]);
+ set_iir_band_coeff(codec, iir_idx, band_idx, 1,
+ ucontrol->value.integer.value[1]);
+ set_iir_band_coeff(codec, iir_idx, band_idx, 2,
+ ucontrol->value.integer.value[2]);
+ set_iir_band_coeff(codec, iir_idx, band_idx, 3,
+ ucontrol->value.integer.value[3]);
+ set_iir_band_coeff(codec, iir_idx, band_idx, 4,
+ ucontrol->value.integer.value[4]);
+
+ pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
+ "%s: IIR #%d band #%d b1 = 0x%x\n"
+ "%s: IIR #%d band #%d b2 = 0x%x\n"
+ "%s: IIR #%d band #%d a1 = 0x%x\n"
+ "%s: IIR #%d band #%d a2 = 0x%x\n",
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 0),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 1),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 2),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 3),
+ __func__, iir_idx, band_idx,
+ get_iir_band_coeff(codec, iir_idx, band_idx, 4));
+ return 0;
+}
+
+static int taiko_compander_gain_offset(
+ struct snd_soc_codec *codec, u32 enable,
+ unsigned int reg, int mask, int event)
+{
+ int pa_mode = snd_soc_read(codec, reg) & mask;
+ int gain_offset = 0;
+ /* if PMU && enable is 1-> offset is 3
+ * if PMU && enable is 0-> offset is 0
+ * if PMD && pa_mode is PA -> offset is 0: PMU compander is off
+ * if PMD && pa_mode is comp -> offset is -3: PMU compander is on.
+ */
+
+ if (SND_SOC_DAPM_EVENT_ON(event) && (enable != 0))
+ gain_offset = TAIKO_COMP_DIGITAL_GAIN_OFFSET;
+ if (SND_SOC_DAPM_EVENT_OFF(event) && (pa_mode == 0))
+ gain_offset = -TAIKO_COMP_DIGITAL_GAIN_OFFSET;
+ return gain_offset;
+}
+
+
+static int taiko_config_gain_compander(
+ struct snd_soc_codec *codec,
+ u32 compander, u32 enable, int event)
+{
+ int value = 0;
+ int mask = 1 << 4;
+ int gain = 0;
+ int gain_offset;
+ if (compander >= COMPANDER_MAX) {
+ pr_err("%s: Error, invalid compander channel\n", __func__);
+ return -EINVAL;
+ }
+
+ if ((enable == 0) || SND_SOC_DAPM_EVENT_OFF(event))
+ value = 1 << 4;
+
+ if (compander == COMPANDER_1) {
+ gain_offset = taiko_compander_gain_offset(codec, enable,
+ TAIKO_A_RX_HPH_L_GAIN, mask, event);
+ snd_soc_update_bits(codec, TAIKO_A_RX_HPH_L_GAIN, mask, value);
+ gain = snd_soc_read(codec, TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL,
+ 0xFF, gain - gain_offset);
+ gain_offset = taiko_compander_gain_offset(codec, enable,
+ TAIKO_A_RX_HPH_R_GAIN, mask, event);
+ snd_soc_update_bits(codec, TAIKO_A_RX_HPH_R_GAIN, mask, value);
+ gain = snd_soc_read(codec, TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL,
+ 0xFF, gain - gain_offset);
+ } else if (compander == COMPANDER_2) {
+ gain_offset = taiko_compander_gain_offset(codec, enable,
+ TAIKO_A_RX_LINE_1_GAIN, mask, event);
+ snd_soc_update_bits(codec, TAIKO_A_RX_LINE_1_GAIN, mask, value);
+ gain = snd_soc_read(codec, TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL,
+ 0xFF, gain - gain_offset);
+ gain_offset = taiko_compander_gain_offset(codec, enable,
+ TAIKO_A_RX_LINE_3_GAIN, mask, event);
+ snd_soc_update_bits(codec, TAIKO_A_RX_LINE_3_GAIN, mask, value);
+ gain = snd_soc_read(codec, TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL,
+ 0xFF, gain - gain_offset);
+ gain_offset = taiko_compander_gain_offset(codec, enable,
+ TAIKO_A_RX_LINE_2_GAIN, mask, event);
+ snd_soc_update_bits(codec, TAIKO_A_RX_LINE_2_GAIN, mask, value);
+ gain = snd_soc_read(codec, TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL,
+ 0xFF, gain - gain_offset);
+ gain_offset = taiko_compander_gain_offset(codec, enable,
+ TAIKO_A_RX_LINE_4_GAIN, mask, event);
+ snd_soc_update_bits(codec, TAIKO_A_RX_LINE_4_GAIN, mask, value);
+ gain = snd_soc_read(codec, TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL,
+ 0xFF, gain - gain_offset);
+ }
+ return 0;
+}
+static int taiko_get_compander(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int comp = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->max;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = taiko->comp_enabled[comp];
+
+ return 0;
+}
+
+static int taiko_set_compander(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ int comp = ((struct soc_multi_mixer_control *)
+ kcontrol->private_value)->max;
+ int value = ucontrol->value.integer.value[0];
+
+ if (value == taiko->comp_enabled[comp]) {
+ pr_debug("%s: compander #%d enable %d no change\n",
+ __func__, comp, value);
+ return 0;
+ }
+ taiko->comp_enabled[comp] = value;
+ return 0;
+}
+
+
+static int taiko_config_compander(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ u32 rate = taiko->comp_fs[w->shift];
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (taiko->comp_enabled[w->shift] != 0) {
+ /* Enable both L/R compander clocks */
+ snd_soc_update_bits(codec,
+ TAIKO_A_CDC_CLK_RX_B2_CTL,
+ 0x03 << comp_shift[w->shift],
+ 0x03 << comp_shift[w->shift]);
+ /* Clar the HALT for the compander*/
+ snd_soc_update_bits(codec,
+ TAIKO_A_CDC_COMP1_B1_CTL +
+ w->shift * 8, 1 << 2, 0);
+ /* Toggle compander reset bits*/
+ snd_soc_update_bits(codec,
+ TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL,
+ 0x03 << comp_shift[w->shift],
+ 0x03 << comp_shift[w->shift]);
+ snd_soc_update_bits(codec,
+ TAIKO_A_CDC_CLK_OTHR_RESET_B2_CTL,
+ 0x03 << comp_shift[w->shift], 0);
+ taiko_config_gain_compander(codec, w->shift, 1, event);
+ /* Update the RMS meter resampling*/
+ snd_soc_update_bits(codec,
+ TAIKO_A_CDC_COMP1_B3_CTL +
+ w->shift * 8, 0xFF, 0x01);
+ /* Wait for 1ms*/
+ usleep_range(1000, 1000);
+ }
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ /* Set sample rate dependent paramater*/
+ if (taiko->comp_enabled[w->shift] != 0) {
+ snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_FS_CFG +
+ w->shift * 8, 0x03, rate);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_B2_CTL +
+ w->shift * 8, 0x0F,
+ comp_samp_params[rate].peak_det_timeout);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_B2_CTL +
+ w->shift * 8, 0xF0,
+ comp_samp_params[rate].rms_meter_div_fact);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_B3_CTL +
+ w->shift * 8, 0xFF,
+ comp_samp_params[rate].rms_meter_resamp_fact);
+ /* Compander enable -> 0x370/0x378*/
+ snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_B1_CTL +
+ w->shift * 8, 0x03, 0x03);
+ }
+ break;
+ case SND_SOC_DAPM_PRE_PMD:
+ /* Halt the compander*/
+ snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_B1_CTL +
+ w->shift * 8, 1 << 2, 1 << 2);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /* Restore the gain */
+ taiko_config_gain_compander(codec, w->shift,
+ taiko->comp_enabled[w->shift], event);
+ /* Disable the compander*/
+ snd_soc_update_bits(codec, TAIKO_A_CDC_COMP1_B1_CTL +
+ w->shift * 8, 0x03, 0x00);
+ /* Turn off the clock for compander in pair*/
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_B2_CTL,
+ 0x03 << comp_shift[w->shift], 0);
+ break;
+ }
+ return 0;
+}
+
+static const char * const taiko_ear_pa_gain_text[] = {"POS_6_DB", "POS_2_DB"};
+static const struct soc_enum taiko_ear_pa_gain_enum[] = {
+ SOC_ENUM_SINGLE_EXT(2, taiko_ear_pa_gain_text),
+};
+
+/*cut of frequency for high pass filter*/
+static const char * const cf_text[] = {
+ "MIN_3DB_4Hz", "MIN_3DB_75Hz", "MIN_3DB_150Hz"
+};
+
+static const struct soc_enum cf_dec1_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_TX1_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec2_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_TX2_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec3_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_TX3_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec4_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_TX4_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec5_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_TX5_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec6_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_TX6_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec7_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_TX7_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec8_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_TX8_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec9_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_TX9_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_dec10_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_TX10_MUX_CTL, 4, 3, cf_text);
+
+static const struct soc_enum cf_rxmix1_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_RX1_B4_CTL, 1, 3, cf_text);
+
+static const struct soc_enum cf_rxmix2_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_RX2_B4_CTL, 1, 3, cf_text);
+
+static const struct soc_enum cf_rxmix3_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_RX3_B4_CTL, 1, 3, cf_text);
+
+static const struct soc_enum cf_rxmix4_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_RX4_B4_CTL, 1, 3, cf_text);
+
+static const struct soc_enum cf_rxmix5_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_RX5_B4_CTL, 1, 3, cf_text)
+;
+static const struct soc_enum cf_rxmix6_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_RX6_B4_CTL, 1, 3, cf_text);
+
+static const struct soc_enum cf_rxmix7_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_RX7_B4_CTL, 1, 3, cf_text);
+
+static const struct snd_kcontrol_new taiko_snd_controls[] = {
+
+ SOC_ENUM_EXT("EAR PA Gain", taiko_ear_pa_gain_enum[0],
+ taiko_pa_gain_get, taiko_pa_gain_put),
+
+ SOC_SINGLE_TLV("LINEOUT1 Volume", TAIKO_A_RX_LINE_1_GAIN, 0, 12, 1,
+ line_gain),
+ SOC_SINGLE_TLV("LINEOUT2 Volume", TAIKO_A_RX_LINE_2_GAIN, 0, 12, 1,
+ line_gain),
+ SOC_SINGLE_TLV("LINEOUT3 Volume", TAIKO_A_RX_LINE_3_GAIN, 0, 12, 1,
+ line_gain),
+ SOC_SINGLE_TLV("LINEOUT4 Volume", TAIKO_A_RX_LINE_4_GAIN, 0, 12, 1,
+ line_gain),
+
+ SOC_SINGLE_TLV("HPHL Volume", TAIKO_A_RX_HPH_L_GAIN, 0, 12, 1,
+ line_gain),
+ SOC_SINGLE_TLV("HPHR Volume", TAIKO_A_RX_HPH_R_GAIN, 0, 12, 1,
+ line_gain),
+
+ SOC_SINGLE_S8_TLV("RX1 Digital Volume", TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX2 Digital Volume", TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX3 Digital Volume", TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX4 Digital Volume", TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX5 Digital Volume", TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX6 Digital Volume", TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL,
+ -84, 40, digital_gain),
+ SOC_SINGLE_S8_TLV("RX7 Digital Volume", TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL,
+ -84, 40, digital_gain),
+
+ SOC_SINGLE_S8_TLV("DEC1 Volume", TAIKO_A_CDC_TX1_VOL_CTL_GAIN, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("DEC2 Volume", TAIKO_A_CDC_TX2_VOL_CTL_GAIN, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("DEC3 Volume", TAIKO_A_CDC_TX3_VOL_CTL_GAIN, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("DEC4 Volume", TAIKO_A_CDC_TX4_VOL_CTL_GAIN, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("DEC5 Volume", TAIKO_A_CDC_TX5_VOL_CTL_GAIN, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("DEC6 Volume", TAIKO_A_CDC_TX6_VOL_CTL_GAIN, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("DEC7 Volume", TAIKO_A_CDC_TX7_VOL_CTL_GAIN, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("DEC8 Volume", TAIKO_A_CDC_TX8_VOL_CTL_GAIN, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("DEC9 Volume", TAIKO_A_CDC_TX9_VOL_CTL_GAIN, -84, 40,
+ digital_gain),
+ SOC_SINGLE_S8_TLV("DEC10 Volume", TAIKO_A_CDC_TX10_VOL_CTL_GAIN, -84,
+ 40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP1 Volume", TAIKO_A_CDC_IIR1_GAIN_B1_CTL, -84,
+ 40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP2 Volume", TAIKO_A_CDC_IIR1_GAIN_B2_CTL, -84,
+ 40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP3 Volume", TAIKO_A_CDC_IIR1_GAIN_B3_CTL, -84,
+ 40, digital_gain),
+ SOC_SINGLE_S8_TLV("IIR1 INP4 Volume", TAIKO_A_CDC_IIR1_GAIN_B4_CTL, -84,
+ 40, digital_gain),
+ SOC_SINGLE_TLV("ADC1 Volume", TAIKO_A_TX_1_2_EN, 5, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC2 Volume", TAIKO_A_TX_1_2_EN, 1, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC3 Volume", TAIKO_A_TX_3_4_EN, 5, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC4 Volume", TAIKO_A_TX_3_4_EN, 1, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC5 Volume", TAIKO_A_TX_5_6_EN, 5, 3, 0, analog_gain),
+ SOC_SINGLE_TLV("ADC6 Volume", TAIKO_A_TX_5_6_EN, 1, 3, 0, analog_gain),
+
+
+ SOC_SINGLE("MICBIAS1 CAPLESS Switch", TAIKO_A_MICB_1_CTL, 4, 1, 1),
+ SOC_SINGLE("MICBIAS2 CAPLESS Switch", TAIKO_A_MICB_2_CTL, 4, 1, 1),
+ SOC_SINGLE("MICBIAS3 CAPLESS Switch", TAIKO_A_MICB_3_CTL, 4, 1, 1),
+ SOC_SINGLE("MICBIAS4 CAPLESS Switch", TAIKO_A_MICB_4_CTL, 4, 1, 1),
+
+ SOC_SINGLE_EXT("ANC Slot", SND_SOC_NOPM, 0, 0, 100, taiko_get_anc_slot,
+ taiko_put_anc_slot),
+ SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
+ SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
+ SOC_ENUM("TX3 HPF cut off", cf_dec3_enum),
+ SOC_ENUM("TX4 HPF cut off", cf_dec4_enum),
+ SOC_ENUM("TX5 HPF cut off", cf_dec5_enum),
+ SOC_ENUM("TX6 HPF cut off", cf_dec6_enum),
+ SOC_ENUM("TX7 HPF cut off", cf_dec7_enum),
+ SOC_ENUM("TX8 HPF cut off", cf_dec8_enum),
+ SOC_ENUM("TX9 HPF cut off", cf_dec9_enum),
+ SOC_ENUM("TX10 HPF cut off", cf_dec10_enum),
+
+ SOC_SINGLE("TX1 HPF Switch", TAIKO_A_CDC_TX1_MUX_CTL, 3, 1, 0),
+ SOC_SINGLE("TX2 HPF Switch", TAIKO_A_CDC_TX2_MUX_CTL, 3, 1, 0),
+ SOC_SINGLE("TX3 HPF Switch", TAIKO_A_CDC_TX3_MUX_CTL, 3, 1, 0),
+ SOC_SINGLE("TX4 HPF Switch", TAIKO_A_CDC_TX4_MUX_CTL, 3, 1, 0),
+ SOC_SINGLE("TX5 HPF Switch", TAIKO_A_CDC_TX5_MUX_CTL, 3, 1, 0),
+ SOC_SINGLE("TX6 HPF Switch", TAIKO_A_CDC_TX6_MUX_CTL, 3, 1, 0),
+ SOC_SINGLE("TX7 HPF Switch", TAIKO_A_CDC_TX7_MUX_CTL, 3, 1, 0),
+ SOC_SINGLE("TX8 HPF Switch", TAIKO_A_CDC_TX8_MUX_CTL, 3, 1, 0),
+ SOC_SINGLE("TX9 HPF Switch", TAIKO_A_CDC_TX9_MUX_CTL, 3, 1, 0),
+ SOC_SINGLE("TX10 HPF Switch", TAIKO_A_CDC_TX10_MUX_CTL, 3, 1, 0),
+
+ SOC_SINGLE("RX1 HPF Switch", TAIKO_A_CDC_RX1_B5_CTL, 2, 1, 0),
+ SOC_SINGLE("RX2 HPF Switch", TAIKO_A_CDC_RX2_B5_CTL, 2, 1, 0),
+ SOC_SINGLE("RX3 HPF Switch", TAIKO_A_CDC_RX3_B5_CTL, 2, 1, 0),
+ SOC_SINGLE("RX4 HPF Switch", TAIKO_A_CDC_RX4_B5_CTL, 2, 1, 0),
+ SOC_SINGLE("RX5 HPF Switch", TAIKO_A_CDC_RX5_B5_CTL, 2, 1, 0),
+ SOC_SINGLE("RX6 HPF Switch", TAIKO_A_CDC_RX6_B5_CTL, 2, 1, 0),
+ SOC_SINGLE("RX7 HPF Switch", TAIKO_A_CDC_RX7_B5_CTL, 2, 1, 0),
+
+ SOC_ENUM("RX1 HPF cut off", cf_rxmix1_enum),
+ SOC_ENUM("RX2 HPF cut off", cf_rxmix2_enum),
+ SOC_ENUM("RX3 HPF cut off", cf_rxmix3_enum),
+ SOC_ENUM("RX4 HPF cut off", cf_rxmix4_enum),
+ SOC_ENUM("RX5 HPF cut off", cf_rxmix5_enum),
+ SOC_ENUM("RX6 HPF cut off", cf_rxmix6_enum),
+ SOC_ENUM("RX7 HPF cut off", cf_rxmix7_enum),
+
+ SOC_SINGLE_EXT("IIR1 Enable Band1", IIR1, BAND1, 1, 0,
+ taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band2", IIR1, BAND2, 1, 0,
+ taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band3", IIR1, BAND3, 1, 0,
+ taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band4", IIR1, BAND4, 1, 0,
+ taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR1 Enable Band5", IIR1, BAND5, 1, 0,
+ taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band1", IIR2, BAND1, 1, 0,
+ taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band2", IIR2, BAND2, 1, 0,
+ taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band3", IIR2, BAND3, 1, 0,
+ taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band4", IIR2, BAND4, 1, 0,
+ taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+ SOC_SINGLE_EXT("IIR2 Enable Band5", IIR2, BAND5, 1, 0,
+ taiko_get_iir_enable_audio_mixer, taiko_put_iir_enable_audio_mixer),
+
+ SOC_SINGLE_MULTI_EXT("IIR1 Band1", IIR1, BAND1, 255, 0, 5,
+ taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band2", IIR1, BAND2, 255, 0, 5,
+ taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band3", IIR1, BAND3, 255, 0, 5,
+ taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band4", IIR1, BAND4, 255, 0, 5,
+ taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR1 Band5", IIR1, BAND5, 255, 0, 5,
+ taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band1", IIR2, BAND1, 255, 0, 5,
+ taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band2", IIR2, BAND2, 255, 0, 5,
+ taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band3", IIR2, BAND3, 255, 0, 5,
+ taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band4", IIR2, BAND4, 255, 0, 5,
+ taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+ SOC_SINGLE_MULTI_EXT("IIR2 Band5", IIR2, BAND5, 255, 0, 5,
+ taiko_get_iir_band_audio_mixer, taiko_put_iir_band_audio_mixer),
+
+ SOC_SINGLE_EXT("COMP1 Switch", SND_SOC_NOPM, 1, COMPANDER_1, 0,
+ taiko_get_compander, taiko_set_compander),
+ SOC_SINGLE_EXT("COMP2 Switch", SND_SOC_NOPM, 0, COMPANDER_2, 0,
+ taiko_get_compander, taiko_set_compander),
+
+};
+
+static const char * const rx_mix1_text[] = {
+ "ZERO", "SRC1", "SRC2", "IIR1", "IIR2", "RX1", "RX2", "RX3", "RX4",
+ "RX5", "RX6", "RX7"
+};
+
+static const char * const rx_mix2_text[] = {
+ "ZERO", "SRC1", "SRC2", "IIR1", "IIR2"
+};
+
+static const char * const rx_dsm_text[] = {
+ "CIC_OUT", "DSM_INV"
+};
+
+static const char * const sb_tx1_mux_text[] = {
+ "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+ "DEC1"
+};
+
+static const char * const sb_tx2_mux_text[] = {
+ "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+ "DEC2"
+};
+
+static const char * const sb_tx3_mux_text[] = {
+ "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+ "DEC3"
+};
+
+static const char * const sb_tx4_mux_text[] = {
+ "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+ "DEC4"
+};
+
+static const char * const sb_tx5_mux_text[] = {
+ "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+ "DEC5"
+};
+
+static const char * const sb_tx6_mux_text[] = {
+ "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+ "DEC6"
+};
+
+static const char * const sb_tx7_to_tx10_mux_text[] = {
+ "ZERO", "RMIX1", "RMIX2", "RMIX3", "RMIX4", "RMIX5", "RMIX6", "RMIX7",
+ "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
+ "DEC9", "DEC10"
+};
+
+static const char * const dec1_mux_text[] = {
+ "ZERO", "DMIC1", "ADC6",
+};
+
+static const char * const dec2_mux_text[] = {
+ "ZERO", "DMIC2", "ADC5",
+};
+
+static const char * const dec3_mux_text[] = {
+ "ZERO", "DMIC3", "ADC4",
+};
+
+static const char * const dec4_mux_text[] = {
+ "ZERO", "DMIC4", "ADC3",
+};
+
+static const char * const dec5_mux_text[] = {
+ "ZERO", "DMIC5", "ADC2",
+};
+
+static const char * const dec6_mux_text[] = {
+ "ZERO", "DMIC6", "ADC1",
+};
+
+static const char * const dec7_mux_text[] = {
+ "ZERO", "DMIC1", "DMIC6", "ADC1", "ADC6", "ANC1_FB", "ANC2_FB",
+};
+
+static const char * const dec8_mux_text[] = {
+ "ZERO", "DMIC2", "DMIC5", "ADC2", "ADC5",
+};
+
+static const char * const dec9_mux_text[] = {
+ "ZERO", "DMIC4", "DMIC5", "ADC2", "ADC3", "ADCMB", "ANC1_FB", "ANC2_FB",
+};
+
+static const char * const dec10_mux_text[] = {
+ "ZERO", "DMIC3", "DMIC6", "ADC1", "ADC4", "ADCMB", "ANC1_FB", "ANC2_FB",
+};
+
+static const char * const anc_mux_text[] = {
+ "ZERO", "ADC1", "ADC2", "ADC3", "ADC4", "ADC5", "ADC6", "ADC_MB",
+ "RSVD_1", "DMIC1", "DMIC2", "DMIC3", "DMIC4", "DMIC5", "DMIC6"
+};
+
+static const char * const anc1_fb_mux_text[] = {
+ "ZERO", "EAR_HPH_L", "EAR_LINE_1",
+};
+
+static const char * const iir1_inp1_text[] = {
+ "ZERO", "DEC1", "DEC2", "DEC3", "DEC4", "DEC5", "DEC6", "DEC7", "DEC8",
+ "DEC9", "DEC10", "RX1", "RX2", "RX3", "RX4", "RX5", "RX6", "RX7"
+};
+
+static const struct soc_enum rx_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx_mix1_inp3_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B2_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx2_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx2_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx3_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX3_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx3_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX3_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx4_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX4_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx4_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX4_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx5_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX5_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx5_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX5_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx6_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX6_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx6_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX6_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx7_mix1_inp1_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B1_CTL, 0, 12, rx_mix1_text);
+
+static const struct soc_enum rx7_mix1_inp2_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B1_CTL, 4, 12, rx_mix1_text);
+
+static const struct soc_enum rx1_mix2_inp1_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B3_CTL, 0, 5, rx_mix2_text);
+
+static const struct soc_enum rx1_mix2_inp2_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX1_B3_CTL, 3, 5, rx_mix2_text);
+
+static const struct soc_enum rx2_mix2_inp1_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B3_CTL, 0, 5, rx_mix2_text);
+
+static const struct soc_enum rx2_mix2_inp2_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX2_B3_CTL, 3, 5, rx_mix2_text);
+
+static const struct soc_enum rx7_mix2_inp1_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B3_CTL, 0, 5, rx_mix2_text);
+
+static const struct soc_enum rx7_mix2_inp2_chain_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_RX7_B3_CTL, 3, 5, rx_mix2_text);
+
+static const struct soc_enum rx4_dsm_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_RX4_B6_CTL, 4, 2, rx_dsm_text);
+
+static const struct soc_enum rx6_dsm_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_RX6_B6_CTL, 4, 2, rx_dsm_text);
+
+static const struct soc_enum sb_tx1_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B1_CTL, 0, 9, sb_tx1_mux_text);
+
+static const struct soc_enum sb_tx2_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B2_CTL, 0, 9, sb_tx2_mux_text);
+
+static const struct soc_enum sb_tx3_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B3_CTL, 0, 9, sb_tx3_mux_text);
+
+static const struct soc_enum sb_tx4_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B4_CTL, 0, 9, sb_tx4_mux_text);
+
+static const struct soc_enum sb_tx5_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B5_CTL, 0, 9, sb_tx5_mux_text);
+
+static const struct soc_enum sb_tx6_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B6_CTL, 0, 9, sb_tx6_mux_text);
+
+static const struct soc_enum sb_tx7_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B7_CTL, 0, 18,
+ sb_tx7_to_tx10_mux_text);
+
+static const struct soc_enum sb_tx8_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B8_CTL, 0, 18,
+ sb_tx7_to_tx10_mux_text);
+
+static const struct soc_enum sb_tx9_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0, 18,
+ sb_tx7_to_tx10_mux_text);
+
+static const struct soc_enum sb_tx10_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0, 18,
+ sb_tx7_to_tx10_mux_text);
+
+static const struct soc_enum dec1_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 0, 3, dec1_mux_text);
+
+static const struct soc_enum dec2_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 2, 3, dec2_mux_text);
+
+static const struct soc_enum dec3_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 4, 3, dec3_mux_text);
+
+static const struct soc_enum dec4_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B1_CTL, 6, 3, dec4_mux_text);
+
+static const struct soc_enum dec5_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B2_CTL, 0, 3, dec5_mux_text);
+
+static const struct soc_enum dec6_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B2_CTL, 2, 3, dec6_mux_text);
+
+static const struct soc_enum dec7_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B2_CTL, 4, 7, dec7_mux_text);
+
+static const struct soc_enum dec8_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B3_CTL, 0, 7, dec8_mux_text);
+
+static const struct soc_enum dec9_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B3_CTL, 3, 8, dec9_mux_text);
+
+static const struct soc_enum dec10_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_TX_B4_CTL, 0, 8, dec10_mux_text);
+
+static const struct soc_enum anc1_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B1_CTL, 0, 16, anc_mux_text);
+
+static const struct soc_enum anc2_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B1_CTL, 4, 16, anc_mux_text);
+
+static const struct soc_enum anc1_fb_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_ANC_B2_CTL, 0, 3, anc1_fb_mux_text);
+
+static const struct soc_enum iir1_inp1_mux_enum =
+ SOC_ENUM_SINGLE(TAIKO_A_CDC_CONN_EQ1_B1_CTL, 0, 18, iir1_inp1_text);
+
+static const struct snd_kcontrol_new rx_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX1 MIX1 INP2 Mux", rx_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx_mix1_inp3_mux =
+ SOC_DAPM_ENUM("RX1 MIX1 INP3 Mux", rx_mix1_inp3_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX2 MIX1 INP1 Mux", rx2_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX2 MIX1 INP2 Mux", rx2_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx3_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX3 MIX1 INP1 Mux", rx3_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx3_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX3 MIX1 INP2 Mux", rx3_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx4_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX4 MIX1 INP1 Mux", rx4_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx4_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX4 MIX1 INP2 Mux", rx4_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx5_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX5 MIX1 INP1 Mux", rx5_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx5_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX5 MIX1 INP2 Mux", rx5_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx6_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX6 MIX1 INP1 Mux", rx6_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx6_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX6 MIX1 INP2 Mux", rx6_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx7_mix1_inp1_mux =
+ SOC_DAPM_ENUM("RX7 MIX1 INP1 Mux", rx7_mix1_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx7_mix1_inp2_mux =
+ SOC_DAPM_ENUM("RX7 MIX1 INP2 Mux", rx7_mix1_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx1_mix2_inp1_mux =
+ SOC_DAPM_ENUM("RX1 MIX2 INP1 Mux", rx1_mix2_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx1_mix2_inp2_mux =
+ SOC_DAPM_ENUM("RX1 MIX2 INP2 Mux", rx1_mix2_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix2_inp1_mux =
+ SOC_DAPM_ENUM("RX2 MIX2 INP1 Mux", rx2_mix2_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx2_mix2_inp2_mux =
+ SOC_DAPM_ENUM("RX2 MIX2 INP2 Mux", rx2_mix2_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx7_mix2_inp1_mux =
+ SOC_DAPM_ENUM("RX7 MIX2 INP1 Mux", rx7_mix2_inp1_chain_enum);
+
+static const struct snd_kcontrol_new rx7_mix2_inp2_mux =
+ SOC_DAPM_ENUM("RX7 MIX2 INP2 Mux", rx7_mix2_inp2_chain_enum);
+
+static const struct snd_kcontrol_new rx4_dsm_mux =
+ SOC_DAPM_ENUM("RX4 DSM MUX Mux", rx4_dsm_enum);
+
+static const struct snd_kcontrol_new rx6_dsm_mux =
+ SOC_DAPM_ENUM("RX6 DSM MUX Mux", rx6_dsm_enum);
+
+static const struct snd_kcontrol_new sb_tx1_mux =
+ SOC_DAPM_ENUM("SLIM TX1 MUX Mux", sb_tx1_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx2_mux =
+ SOC_DAPM_ENUM("SLIM TX2 MUX Mux", sb_tx2_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx3_mux =
+ SOC_DAPM_ENUM("SLIM TX3 MUX Mux", sb_tx3_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx4_mux =
+ SOC_DAPM_ENUM("SLIM TX4 MUX Mux", sb_tx4_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx5_mux =
+ SOC_DAPM_ENUM("SLIM TX5 MUX Mux", sb_tx5_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx6_mux =
+ SOC_DAPM_ENUM("SLIM TX6 MUX Mux", sb_tx6_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx7_mux =
+ SOC_DAPM_ENUM("SLIM TX7 MUX Mux", sb_tx7_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx8_mux =
+ SOC_DAPM_ENUM("SLIM TX8 MUX Mux", sb_tx8_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx9_mux =
+ SOC_DAPM_ENUM("SLIM TX9 MUX Mux", sb_tx9_mux_enum);
+
+static const struct snd_kcontrol_new sb_tx10_mux =
+ SOC_DAPM_ENUM("SLIM TX10 MUX Mux", sb_tx10_mux_enum);
+
+
+static int wcd9320_put_dec_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *w = wlist->widgets[0];
+ struct snd_soc_codec *codec = w->codec;
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ unsigned int dec_mux, decimator;
+ char *dec_name = NULL;
+ char *widget_name = NULL;
+ char *temp;
+ u16 tx_mux_ctl_reg;
+ u8 adc_dmic_sel = 0x0;
+ int ret = 0;
+
+ if (ucontrol->value.enumerated.item[0] > e->max - 1)
+ return -EINVAL;
+
+ dec_mux = ucontrol->value.enumerated.item[0];
+
+ widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+ if (!widget_name)
+ return -ENOMEM;
+ temp = widget_name;
+
+ dec_name = strsep(&widget_name, " ");
+ widget_name = temp;
+ if (!dec_name) {
+ pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = kstrtouint(strpbrk(dec_name, "123456789"), 10, &decimator);
+ if (ret < 0) {
+ pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ dev_dbg(w->dapm->dev, "%s(): widget = %s decimator = %u dec_mux = %u\n"
+ , __func__, w->name, decimator, dec_mux);
+
+
+ switch (decimator) {
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ if (dec_mux == 1)
+ adc_dmic_sel = 0x1;
+ else
+ adc_dmic_sel = 0x0;
+ break;
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ if ((dec_mux == 1) || (dec_mux == 2))
+ adc_dmic_sel = 0x1;
+ else
+ adc_dmic_sel = 0x0;
+ break;
+ default:
+ pr_err("%s: Invalid Decimator = %u\n", __func__, decimator);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ tx_mux_ctl_reg = TAIKO_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
+
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x1, adc_dmic_sel);
+
+ ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
+
+out:
+ kfree(widget_name);
+ return ret;
+}
+
+#define WCD9320_DEC_ENUM(xname, xenum) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = snd_soc_info_enum_double, \
+ .get = snd_soc_dapm_get_enum_double, \
+ .put = wcd9320_put_dec_enum, \
+ .private_value = (unsigned long)&xenum }
+
+static const struct snd_kcontrol_new dec1_mux =
+ WCD9320_DEC_ENUM("DEC1 MUX Mux", dec1_mux_enum);
+
+static const struct snd_kcontrol_new dec2_mux =
+ WCD9320_DEC_ENUM("DEC2 MUX Mux", dec2_mux_enum);
+
+static const struct snd_kcontrol_new dec3_mux =
+ WCD9320_DEC_ENUM("DEC3 MUX Mux", dec3_mux_enum);
+
+static const struct snd_kcontrol_new dec4_mux =
+ WCD9320_DEC_ENUM("DEC4 MUX Mux", dec4_mux_enum);
+
+static const struct snd_kcontrol_new dec5_mux =
+ WCD9320_DEC_ENUM("DEC5 MUX Mux", dec5_mux_enum);
+
+static const struct snd_kcontrol_new dec6_mux =
+ WCD9320_DEC_ENUM("DEC6 MUX Mux", dec6_mux_enum);
+
+static const struct snd_kcontrol_new dec7_mux =
+ WCD9320_DEC_ENUM("DEC7 MUX Mux", dec7_mux_enum);
+
+static const struct snd_kcontrol_new dec8_mux =
+ WCD9320_DEC_ENUM("DEC8 MUX Mux", dec8_mux_enum);
+
+static const struct snd_kcontrol_new dec9_mux =
+ WCD9320_DEC_ENUM("DEC9 MUX Mux", dec9_mux_enum);
+
+static const struct snd_kcontrol_new dec10_mux =
+ WCD9320_DEC_ENUM("DEC10 MUX Mux", dec10_mux_enum);
+
+static const struct snd_kcontrol_new iir1_inp1_mux =
+ SOC_DAPM_ENUM("IIR1 INP1 Mux", iir1_inp1_mux_enum);
+
+static const struct snd_kcontrol_new anc1_mux =
+ SOC_DAPM_ENUM("ANC1 MUX Mux", anc1_mux_enum);
+
+static const struct snd_kcontrol_new anc2_mux =
+ SOC_DAPM_ENUM("ANC2 MUX Mux", anc2_mux_enum);
+
+static const struct snd_kcontrol_new anc1_fb_mux =
+ SOC_DAPM_ENUM("ANC1 FB MUX Mux", anc1_fb_mux_enum);
+
+static const struct snd_kcontrol_new dac1_switch[] = {
+ SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_EAR_EN, 5, 1, 0)
+};
+static const struct snd_kcontrol_new hphl_switch[] = {
+ SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_HPH_L_DAC_CTL, 6, 1, 0)
+};
+
+static const struct snd_kcontrol_new hphl_pa_mix[] = {
+ SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
+ 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new hphr_pa_mix[] = {
+ SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
+ 6, 1, 0),
+};
+
+static const struct snd_kcontrol_new ear_pa_mix[] = {
+ SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
+ 5, 1, 0),
+};
+static const struct snd_kcontrol_new lineout1_pa_mix[] = {
+ SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
+ 4, 1, 0),
+};
+
+static const struct snd_kcontrol_new lineout2_pa_mix[] = {
+ SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
+ 3, 1, 0),
+};
+
+static const struct snd_kcontrol_new lineout3_pa_mix[] = {
+ SOC_DAPM_SINGLE("AUX_PGA_L Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
+ 2, 1, 0),
+};
+
+static const struct snd_kcontrol_new lineout4_pa_mix[] = {
+ SOC_DAPM_SINGLE("AUX_PGA_R Switch", TAIKO_A_RX_PA_AUX_IN_CONN,
+ 1, 1, 0),
+};
+
+static const struct snd_kcontrol_new lineout3_ground_switch =
+ SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_LINE_3_DAC_CTL, 6, 1, 0);
+
+static const struct snd_kcontrol_new lineout4_ground_switch =
+ SOC_DAPM_SINGLE("Switch", TAIKO_A_RX_LINE_4_DAC_CTL, 6, 1, 0);
+
+static void taiko_codec_enable_adc_block(struct snd_soc_codec *codec,
+ int enable)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s %d\n", __func__, enable);
+
+ if (enable) {
+ taiko->adc_count++;
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_CTL, 0x2, 0x2);
+ } else {
+ taiko->adc_count--;
+ if (!taiko->adc_count)
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_OTHR_CTL,
+ 0x2, 0x0);
+ }
+}
+
+static int taiko_codec_enable_adc(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ u16 adc_reg;
+ u8 init_bit_shift;
+
+ pr_debug("%s %d\n", __func__, event);
+
+ if (w->reg == TAIKO_A_TX_1_2_EN)
+ adc_reg = TAIKO_A_TX_1_2_TEST_CTL;
+ else if (w->reg == TAIKO_A_TX_3_4_EN)
+ adc_reg = TAIKO_A_TX_3_4_TEST_CTL;
+ else if (w->reg == TAIKO_A_TX_5_6_EN)
+ adc_reg = TAIKO_A_TX_5_6_TEST_CTL;
+ else {
+ pr_err("%s: Error, invalid adc register\n", __func__);
+ return -EINVAL;
+ }
+
+ if (w->shift == 3)
+ init_bit_shift = 6;
+ else if (w->shift == 7)
+ init_bit_shift = 7;
+ else {
+ pr_err("%s: Error, invalid init bit postion adc register\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ taiko_codec_enable_adc_block(codec, 1);
+ snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift,
+ 1 << init_bit_shift);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+
+ snd_soc_update_bits(codec, adc_reg, 1 << init_bit_shift, 0x00);
+
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ taiko_codec_enable_adc_block(codec, 0);
+ break;
+ }
+ return 0;
+}
+
+static void taiko_codec_enable_audio_mode_bandgap(struct snd_soc_codec *codec)
+{
+ snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x80,
+ 0x80);
+ snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x04,
+ 0x04);
+ snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x01,
+ 0x01);
+ usleep_range(1000, 1000);
+ snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x80,
+ 0x00);
+}
+
+static void taiko_codec_enable_bandgap(struct snd_soc_codec *codec,
+ enum taiko_bandgap_type choice)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ /* TODO lock resources accessed by audio streams and threaded
+ * interrupt handlers
+ */
+
+ pr_debug("%s, choice is %d, current is %d\n", __func__, choice,
+ taiko->bandgap_type);
+
+ if (taiko->bandgap_type == choice)
+ return;
+
+ if ((taiko->bandgap_type == TAIKO_BANDGAP_OFF) &&
+ (choice == TAIKO_BANDGAP_AUDIO_MODE)) {
+ taiko_codec_enable_audio_mode_bandgap(codec);
+ } else if (choice == TAIKO_BANDGAP_MBHC_MODE) {
+ /* bandgap mode becomes fast,
+ * mclk should be off or clk buff source souldn't be VBG
+ * Let's turn off mclk always */
+ WARN_ON(snd_soc_read(codec, TAIKO_A_CLK_BUFF_EN2) & (1 << 2));
+ snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x2,
+ 0x2);
+ snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x80,
+ 0x80);
+ snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x4,
+ 0x4);
+ snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x01,
+ 0x01);
+ usleep_range(1000, 1000);
+ snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x80,
+ 0x00);
+ } else if ((taiko->bandgap_type == TAIKO_BANDGAP_MBHC_MODE) &&
+ (choice == TAIKO_BANDGAP_AUDIO_MODE)) {
+ snd_soc_write(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x00);
+ usleep_range(100, 100);
+ taiko_codec_enable_audio_mode_bandgap(codec);
+ } else if (choice == TAIKO_BANDGAP_OFF) {
+ snd_soc_write(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x00);
+ } else {
+ pr_err("%s: Error, Invalid bandgap settings\n", __func__);
+ }
+ taiko->bandgap_type = choice;
+}
+
+static void taiko_codec_disable_clock_block(struct snd_soc_codec *codec)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ pr_debug("%s\n", __func__);
+ snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN2, 0x04, 0x00);
+ usleep_range(50, 50);
+ snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN2, 0x02, 0x02);
+ snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1, 0x05, 0x00);
+ usleep_range(50, 50);
+ taiko->clock_active = false;
+}
+
+static int taiko_codec_mclk_index(const struct taiko_priv *taiko)
+{
+ if (taiko->mbhc_cfg.mclk_rate == TAIKO_MCLK_RATE_12288KHZ)
+ return 0;
+ else if (taiko->mbhc_cfg.mclk_rate == TAIKO_MCLK_RATE_9600KHZ)
+ return 1;
+ else {
+ BUG_ON(1);
+ return -EINVAL;
+ }
+}
+
+static void taiko_enable_rx_bias(struct snd_soc_codec *codec, u32 enable)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ if (enable) {
+ taiko->rx_bias_count++;
+ if (taiko->rx_bias_count == 1)
+ snd_soc_update_bits(codec, TAIKO_A_RX_COM_BIAS,
+ 0x80, 0x80);
+ } else {
+ taiko->rx_bias_count--;
+ if (!taiko->rx_bias_count)
+ snd_soc_update_bits(codec, TAIKO_A_RX_COM_BIAS,
+ 0x80, 0x00);
+ }
+}
+
+static int taiko_codec_enable_config_mode(struct snd_soc_codec *codec,
+ int enable)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s: enable = %d\n", __func__, enable);
+ if (enable) {
+
+ snd_soc_update_bits(codec, TAIKO_A_RC_OSC_FREQ, 0x10, 0);
+ /* bandgap mode to fast */
+ snd_soc_write(codec, TAIKO_A_BIAS_OSC_BG_CTL, 0x17);
+ usleep_range(5, 5);
+ snd_soc_update_bits(codec, TAIKO_A_RC_OSC_FREQ, 0x80,
+ 0x80);
+ snd_soc_update_bits(codec, TAIKO_A_RC_OSC_TEST, 0x80,
+ 0x80);
+ usleep_range(10, 10);
+ snd_soc_update_bits(codec, TAIKO_A_RC_OSC_TEST, 0x80, 0);
+ usleep_range(10000, 10000);
+ snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1, 0x08, 0x08);
+
+ } else {
+ snd_soc_update_bits(codec, TAIKO_A_BIAS_OSC_BG_CTL, 0x1,
+ 0);
+ snd_soc_update_bits(codec, TAIKO_A_RC_OSC_FREQ, 0x80, 0);
+ /* clk source to ext clk and clk buff ref to VBG */
+ snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1, 0x0C, 0x04);
+ }
+ taiko->config_mode_active = enable ? true : false;
+
+ return 0;
+}
+
+static int taiko_codec_enable_clock_block(struct snd_soc_codec *codec,
+ int config_mode)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s: config_mode = %d\n", __func__, config_mode);
+
+ /* transit to RCO requires mclk off */
+ WARN_ON(snd_soc_read(codec, TAIKO_A_CLK_BUFF_EN2) & (1 << 2));
+ if (config_mode) {
+ /* enable RCO and switch to it */
+ taiko_codec_enable_config_mode(codec, 1);
+ snd_soc_write(codec, TAIKO_A_CLK_BUFF_EN2, 0x02);
+ usleep_range(1000, 1000);
+ } else {
+ /* switch to MCLK */
+ snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1, 0x08, 0x00);
+
+ if (taiko->mbhc_polling_active) {
+ snd_soc_write(codec, TAIKO_A_CLK_BUFF_EN2, 0x02);
+ taiko_codec_enable_config_mode(codec, 0);
+ }
+ }
+
+ snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1, 0x01, 0x01);
+ snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN2, 0x02, 0x00);
+ /* on MCLK */
+ snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN2, 0x04, 0x04);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_MCLK_CTL, 0x01, 0x01);
+ usleep_range(50, 50);
+ taiko->clock_active = true;
+ return 0;
+}
+
+static int taiko_codec_enable_aux_pga(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s: %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ taiko_codec_enable_bandgap(codec, TAIKO_BANDGAP_AUDIO_MODE);
+ taiko_enable_rx_bias(codec, 1);
+
+ if (taiko->aux_pga_cnt++ == 1
+ && !taiko->mclk_enabled) {
+ taiko_codec_enable_clock_block(codec, 1);
+ pr_debug("AUX PGA enabled RC osc\n");
+ }
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ taiko_enable_rx_bias(codec, 0);
+
+ if (taiko->aux_pga_cnt-- == 0) {
+ if (taiko->mbhc_polling_active)
+ taiko_codec_enable_bandgap(codec,
+ TAIKO_BANDGAP_MBHC_MODE);
+ else
+ taiko_codec_enable_bandgap(codec,
+ TAIKO_BANDGAP_OFF);
+
+ if (!taiko->mclk_enabled &&
+ !taiko->mbhc_polling_active) {
+ taiko_codec_enable_clock_block(codec, 0);
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+static int taiko_codec_enable_lineout(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ u16 lineout_gain_reg;
+
+ pr_debug("%s %d %s\n", __func__, event, w->name);
+
+ switch (w->shift) {
+ case 0:
+ lineout_gain_reg = TAIKO_A_RX_LINE_1_GAIN;
+ break;
+ case 1:
+ lineout_gain_reg = TAIKO_A_RX_LINE_2_GAIN;
+ break;
+ case 2:
+ lineout_gain_reg = TAIKO_A_RX_LINE_3_GAIN;
+ break;
+ case 3:
+ lineout_gain_reg = TAIKO_A_RX_LINE_4_GAIN;
+ break;
+ default:
+ pr_err("%s: Error, incorrect lineout register value\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x40);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ pr_debug("%s: sleeping 16 ms after %s PA turn on\n",
+ __func__, w->name);
+ usleep_range(16000, 16000);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, lineout_gain_reg, 0x40, 0x00);
+ break;
+ }
+ return 0;
+}
+
+
+static int taiko_codec_enable_dmic(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ u8 dmic_clk_en;
+ u16 dmic_clk_reg;
+ s32 *dmic_clk_cnt;
+ unsigned int dmic;
+ int ret;
+
+ ret = kstrtouint(strpbrk(w->name, "123456"), 10, &dmic);
+ if (ret < 0) {
+ pr_err("%s: Invalid DMIC line on the codec\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (dmic) {
+ case 1:
+ case 2:
+ dmic_clk_en = 0x01;
+ dmic_clk_cnt = &(taiko->dmic_1_2_clk_cnt);
+ dmic_clk_reg = TAIKO_A_CDC_CLK_DMIC_B1_CTL;
+ pr_debug("%s() event %d DMIC%d dmic_1_2_clk_cnt %d\n",
+ __func__, event, dmic, *dmic_clk_cnt);
+
+ break;
+
+ case 3:
+ case 4:
+ dmic_clk_en = 0x10;
+ dmic_clk_cnt = &(taiko->dmic_3_4_clk_cnt);
+ dmic_clk_reg = TAIKO_A_CDC_CLK_DMIC_B1_CTL;
+
+ pr_debug("%s() event %d DMIC%d dmic_3_4_clk_cnt %d\n",
+ __func__, event, dmic, *dmic_clk_cnt);
+ break;
+
+ case 5:
+ case 6:
+ dmic_clk_en = 0x01;
+ dmic_clk_cnt = &(taiko->dmic_5_6_clk_cnt);
+ dmic_clk_reg = TAIKO_A_CDC_CLK_DMIC_B2_CTL;
+
+ pr_debug("%s() event %d DMIC%d dmic_5_6_clk_cnt %d\n",
+ __func__, event, dmic, *dmic_clk_cnt);
+
+ break;
+
+ default:
+ pr_err("%s: Invalid DMIC Selection\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+
+ (*dmic_clk_cnt)++;
+ if (*dmic_clk_cnt == 1)
+ snd_soc_update_bits(codec, dmic_clk_reg,
+ dmic_clk_en, dmic_clk_en);
+
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+
+ (*dmic_clk_cnt)--;
+ if (*dmic_clk_cnt == 0)
+ snd_soc_update_bits(codec, dmic_clk_reg,
+ dmic_clk_en, 0);
+ break;
+ }
+ return 0;
+}
+
+static int taiko_codec_enable_anc(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ const char *filename;
+ const struct firmware *fw;
+ int i;
+ int ret;
+ int num_anc_slots;
+ struct anc_header *anc_head;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ u32 anc_writes_size = 0;
+ int anc_size_remaining;
+ u32 *anc_ptr;
+ u16 reg;
+ u8 mask, val, old_val;
+
+ pr_debug("%s %d\n", __func__, event);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+
+ filename = "wcd9320/wcd9320_anc.bin";
+
+ ret = request_firmware(&fw, filename, codec->dev);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to acquire ANC data: %d\n",
+ ret);
+ return -ENODEV;
+ }
+
+ if (fw->size < sizeof(struct anc_header)) {
+ dev_err(codec->dev, "Not enough data\n");
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+
+ /* First number is the number of register writes */
+ anc_head = (struct anc_header *)(fw->data);
+ anc_ptr = (u32 *)((u32)fw->data + sizeof(struct anc_header));
+ anc_size_remaining = fw->size - sizeof(struct anc_header);
+ num_anc_slots = anc_head->num_anc_slots;
+
+ if (taiko->anc_slot >= num_anc_slots) {
+ dev_err(codec->dev, "Invalid ANC slot selected\n");
+ release_firmware(fw);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < num_anc_slots; i++) {
+
+ if (anc_size_remaining < TAIKO_PACKED_REG_SIZE) {
+ dev_err(codec->dev, "Invalid register format\n");
+ release_firmware(fw);
+ return -EINVAL;
+ }
+ anc_writes_size = (u32)(*anc_ptr);
+ anc_size_remaining -= sizeof(u32);
+ anc_ptr += 1;
+
+ if (anc_writes_size * TAIKO_PACKED_REG_SIZE
+ > anc_size_remaining) {
+ dev_err(codec->dev, "Invalid register format\n");
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+
+ if (taiko->anc_slot == i)
+ break;
+
+ anc_size_remaining -= (anc_writes_size *
+ TAIKO_PACKED_REG_SIZE);
+ anc_ptr += anc_writes_size;
+ }
+ if (i == num_anc_slots) {
+ dev_err(codec->dev, "Selected ANC slot not present\n");
+ release_firmware(fw);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < anc_writes_size; i++) {
+ TAIKO_CODEC_UNPACK_ENTRY(anc_ptr[i], reg,
+ mask, val);
+ old_val = snd_soc_read(codec, reg);
+ snd_soc_write(codec, reg, (old_val & ~mask) |
+ (val & mask));
+ }
+ release_firmware(fw);
+
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_RESET_CTL, 0xFF);
+ snd_soc_write(codec, TAIKO_A_CDC_CLK_ANC_CLK_EN_CTL, 0);
+ break;
+ }
+ return 0;
+}
+
+/* called under codec_resource_lock acquisition */
+static void taiko_codec_start_hs_polling(struct snd_soc_codec *codec)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ int mbhc_state = taiko->mbhc_state;
+
+ pr_debug("%s: enter\n", __func__);
+ if (!taiko->mbhc_polling_active) {
+ pr_debug("Polling is not active, do not start polling\n");
+ return;
+ }
+ snd_soc_write(codec, TAIKO_A_MBHC_SCALING_MUX_1, 0x84);
+
+ if (!taiko->no_mic_headset_override) {
+ if (mbhc_state == MBHC_STATE_POTENTIAL) {
+ pr_debug("%s recovering MBHC state macine\n", __func__);
+ taiko->mbhc_state = MBHC_STATE_POTENTIAL_RECOVERY;
+ /* set to max button press threshold */
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B2_CTL,
+ 0x7F);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B1_CTL,
+ 0xFF);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B4_CTL,
+ 0x7F);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B3_CTL,
+ 0xFF);
+ /* set to max */
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B6_CTL,
+ 0x7F);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B5_CTL,
+ 0xFF);
+ }
+ }
+
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x1);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x1);
+ pr_debug("%s: leave\n", __func__);
+}
+
+/* called under codec_resource_lock acquisition */
+static void taiko_codec_pause_hs_polling(struct snd_soc_codec *codec)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s: enter\n", __func__);
+ if (!taiko->mbhc_polling_active) {
+ pr_debug("polling not active, nothing to pause\n");
+ return;
+ }
+
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+ pr_debug("%s: leave\n", __func__);
+}
+
+static void taiko_codec_switch_cfilt_mode(struct snd_soc_codec *codec, int mode)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ u8 reg_mode_val, cur_mode_val;
+ bool mbhc_was_polling = false;
+
+ if (mode)
+ reg_mode_val = TAIKO_CFILT_FAST_MODE;
+ else
+ reg_mode_val = TAIKO_CFILT_SLOW_MODE;
+
+ cur_mode_val = snd_soc_read(codec,
+ taiko->mbhc_bias_regs.cfilt_ctl) & 0x40;
+
+ if (cur_mode_val != reg_mode_val) {
+ TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+ if (taiko->mbhc_polling_active) {
+ taiko_codec_pause_hs_polling(codec);
+ mbhc_was_polling = true;
+ }
+ snd_soc_update_bits(codec,
+ taiko->mbhc_bias_regs.cfilt_ctl, 0x40, reg_mode_val);
+ if (mbhc_was_polling)
+ taiko_codec_start_hs_polling(codec);
+ TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+ pr_debug("%s: CFILT mode change (%x to %x)\n", __func__,
+ cur_mode_val, reg_mode_val);
+ } else {
+ pr_debug("%s: CFILT Value is already %x\n",
+ __func__, cur_mode_val);
+ }
+}
+
+static void taiko_codec_update_cfilt_usage(struct snd_soc_codec *codec,
+ u8 cfilt_sel, int inc)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ u32 *cfilt_cnt_ptr = NULL;
+ u16 micb_cfilt_reg;
+
+ switch (cfilt_sel) {
+ case TAIKO_CFILT1_SEL:
+ cfilt_cnt_ptr = &taiko->cfilt1_cnt;
+ micb_cfilt_reg = TAIKO_A_MICB_CFILT_1_CTL;
+ break;
+ case TAIKO_CFILT2_SEL:
+ cfilt_cnt_ptr = &taiko->cfilt2_cnt;
+ micb_cfilt_reg = TAIKO_A_MICB_CFILT_2_CTL;
+ break;
+ case TAIKO_CFILT3_SEL:
+ cfilt_cnt_ptr = &taiko->cfilt3_cnt;
+ micb_cfilt_reg = TAIKO_A_MICB_CFILT_3_CTL;
+ break;
+ default:
+ return; /* should not happen */
+ }
+
+ if (inc) {
+ if (!(*cfilt_cnt_ptr)++) {
+ /* Switch CFILT to slow mode if MBHC CFILT being used */
+ if (cfilt_sel == taiko->mbhc_bias_regs.cfilt_sel)
+ taiko_codec_switch_cfilt_mode(codec, 0);
+
+ snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0x80);
+ }
+ } else {
+ /* check if count not zero, decrement
+ * then check if zero, go ahead disable cfilter
+ */
+ if ((*cfilt_cnt_ptr) && !--(*cfilt_cnt_ptr)) {
+ snd_soc_update_bits(codec, micb_cfilt_reg, 0x80, 0);
+
+ /* Switch CFILT to fast mode if MBHC CFILT being used */
+ if (cfilt_sel == taiko->mbhc_bias_regs.cfilt_sel)
+ taiko_codec_switch_cfilt_mode(codec, 1);
+ }
+ }
+}
+
+static int taiko_find_k_value(unsigned int ldoh_v, unsigned int cfilt_mv)
+{
+ int rc = -EINVAL;
+ unsigned min_mv, max_mv;
+
+ switch (ldoh_v) {
+ case TAIKO_LDOH_1P95_V:
+ min_mv = 160;
+ max_mv = 1800;
+ break;
+ case TAIKO_LDOH_2P35_V:
+ min_mv = 200;
+ max_mv = 2200;
+ break;
+ case TAIKO_LDOH_2P75_V:
+ min_mv = 240;
+ max_mv = 2600;
+ break;
+ case TAIKO_LDOH_2P85_V:
+ min_mv = 250;
+ max_mv = 2700;
+ break;
+ default:
+ goto done;
+ }
+
+ if (cfilt_mv < min_mv || cfilt_mv > max_mv)
+ goto done;
+
+ for (rc = 4; rc <= 44; rc++) {
+ min_mv = max_mv * (rc) / 44;
+ if (min_mv >= cfilt_mv) {
+ rc -= 4;
+ break;
+ }
+ }
+done:
+ return rc;
+}
+
+static bool taiko_is_hph_pa_on(struct snd_soc_codec *codec)
+{
+ u8 hph_reg_val = 0;
+ hph_reg_val = snd_soc_read(codec, TAIKO_A_RX_HPH_CNP_EN);
+
+ return (hph_reg_val & 0x30) ? true : false;
+}
+
+static bool taiko_is_hph_dac_on(struct snd_soc_codec *codec, int left)
+{
+ u8 hph_reg_val = 0;
+ if (left)
+ hph_reg_val = snd_soc_read(codec,
+ TAIKO_A_RX_HPH_L_DAC_CTL);
+ else
+ hph_reg_val = snd_soc_read(codec,
+ TAIKO_A_RX_HPH_R_DAC_CTL);
+
+ return (hph_reg_val & 0xC0) ? true : false;
+}
+
+static void taiko_turn_onoff_override(struct snd_soc_codec *codec, bool on)
+{
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x04, on << 2);
+}
+
+/* called under codec_resource_lock acquisition */
+static void taiko_codec_drive_v_to_micbias(struct snd_soc_codec *codec,
+ int usec)
+{
+ int cfilt_k_val;
+ bool set = true;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ if (taiko->mbhc_data.micb_mv != VDDIO_MICBIAS_MV &&
+ taiko->mbhc_micbias_switched) {
+ pr_debug("%s: set mic V to micbias V\n", __func__);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
+ taiko_turn_onoff_override(codec, true);
+ while (1) {
+ cfilt_k_val = taiko_find_k_value(
+ taiko->pdata->micbias.ldoh_v,
+ set ? taiko->mbhc_data.micb_mv :
+ VDDIO_MICBIAS_MV);
+ snd_soc_update_bits(codec,
+ taiko->mbhc_bias_regs.cfilt_val,
+ 0xFC, (cfilt_k_val << 2));
+ if (!set)
+ break;
+ usleep_range(usec, usec);
+ set = false;
+ }
+ taiko_turn_onoff_override(codec, false);
+ }
+}
+
+/* called under codec_resource_lock acquisition */
+static void __taiko_codec_switch_micbias(struct snd_soc_codec *codec,
+ int vddio_switch, bool restartpolling,
+ bool checkpolling)
+{
+ int cfilt_k_val;
+ bool override;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ if (vddio_switch && !taiko->mbhc_micbias_switched &&
+ (!checkpolling || taiko->mbhc_polling_active)) {
+ if (restartpolling)
+ taiko_codec_pause_hs_polling(codec);
+ override = snd_soc_read(codec, TAIKO_A_CDC_MBHC_B1_CTL) & 0x04;
+ if (!override)
+ taiko_turn_onoff_override(codec, true);
+ /* Adjust threshold if Mic Bias voltage changes */
+ if (taiko->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) {
+ cfilt_k_val = taiko_find_k_value(
+ taiko->pdata->micbias.ldoh_v,
+ VDDIO_MICBIAS_MV);
+ usleep_range(10000, 10000);
+ snd_soc_update_bits(codec,
+ taiko->mbhc_bias_regs.cfilt_val,
+ 0xFC, (cfilt_k_val << 2));
+ usleep_range(10000, 10000);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B1_CTL,
+ taiko->mbhc_data.adj_v_ins_hu & 0xFF);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B2_CTL,
+ (taiko->mbhc_data.adj_v_ins_hu >> 8) &
+ 0xFF);
+ pr_debug("%s: Programmed MBHC thresholds to VDDIO\n",
+ __func__);
+ }
+
+ /* enable MIC BIAS Switch to VDDIO */
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg,
+ 0x80, 0x80);
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg,
+ 0x10, 0x00);
+ if (!override)
+ taiko_turn_onoff_override(codec, false);
+ if (restartpolling)
+ taiko_codec_start_hs_polling(codec);
+
+ taiko->mbhc_micbias_switched = true;
+ pr_debug("%s: VDDIO switch enabled\n", __func__);
+ } else if (!vddio_switch && taiko->mbhc_micbias_switched) {
+ if ((!checkpolling || taiko->mbhc_polling_active) &&
+ restartpolling)
+ taiko_codec_pause_hs_polling(codec);
+ /* Reprogram thresholds */
+ if (taiko->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) {
+ cfilt_k_val = taiko_find_k_value(
+ taiko->pdata->micbias.ldoh_v,
+ taiko->mbhc_data.micb_mv);
+ snd_soc_update_bits(codec,
+ taiko->mbhc_bias_regs.cfilt_val,
+ 0xFC, (cfilt_k_val << 2));
+ usleep_range(10000, 10000);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B1_CTL,
+ taiko->mbhc_data.v_ins_hu & 0xFF);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B2_CTL,
+ (taiko->mbhc_data.v_ins_hu >> 8) & 0xFF);
+ pr_debug("%s: Programmed MBHC thresholds to MICBIAS\n",
+ __func__);
+ }
+
+ /* Disable MIC BIAS Switch to VDDIO */
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg,
+ 0x80, 0x00);
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg,
+ 0x10, 0x00);
+
+ if ((!checkpolling || taiko->mbhc_polling_active) &&
+ restartpolling)
+ taiko_codec_start_hs_polling(codec);
+
+ taiko->mbhc_micbias_switched = false;
+ pr_debug("%s: VDDIO switch disabled\n", __func__);
+ }
+}
+
+static void taiko_codec_switch_micbias(struct snd_soc_codec *codec,
+ int vddio_switch)
+{
+ return __taiko_codec_switch_micbias(codec, vddio_switch, true, true);
+}
+
+static int taiko_codec_enable_micbias(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ u16 micb_int_reg;
+ int micb_line;
+ u8 cfilt_sel_val = 0;
+ char *internal1_text = "Internal1";
+ char *internal2_text = "Internal2";
+ char *internal3_text = "Internal3";
+
+ pr_debug("%s %d\n", __func__, event);
+ switch (w->reg) {
+ case TAIKO_A_MICB_1_CTL:
+ micb_int_reg = TAIKO_A_MICB_1_INT_RBIAS;
+ cfilt_sel_val = taiko->pdata->micbias.bias1_cfilt_sel;
+ micb_line = TAIKO_MICBIAS1;
+ break;
+ case TAIKO_A_MICB_2_CTL:
+ micb_int_reg = TAIKO_A_MICB_2_INT_RBIAS;
+ cfilt_sel_val = taiko->pdata->micbias.bias2_cfilt_sel;
+ micb_line = TAIKO_MICBIAS2;
+ break;
+ case TAIKO_A_MICB_3_CTL:
+ micb_int_reg = TAIKO_A_MICB_3_INT_RBIAS;
+ cfilt_sel_val = taiko->pdata->micbias.bias3_cfilt_sel;
+ micb_line = TAIKO_MICBIAS3;
+ break;
+ case TAIKO_A_MICB_4_CTL:
+ micb_int_reg = taiko->reg_addr.micb_4_int_rbias;
+ cfilt_sel_val = taiko->pdata->micbias.bias4_cfilt_sel;
+ micb_line = TAIKO_MICBIAS4;
+ break;
+ default:
+ pr_err("%s: Error, invalid micbias register\n", __func__);
+ return -EINVAL;
+ }
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Decide whether to switch the micbias for MBHC */
+ if (w->reg == taiko->mbhc_bias_regs.ctl_reg) {
+ TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+ taiko_codec_switch_micbias(codec, 0);
+ TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+ }
+
+ snd_soc_update_bits(codec, w->reg, 0x0E, 0x0A);
+ taiko_codec_update_cfilt_usage(codec, cfilt_sel_val, 1);
+
+ if (strnstr(w->name, internal1_text, 30))
+ snd_soc_update_bits(codec, micb_int_reg, 0xE0, 0xE0);
+ else if (strnstr(w->name, internal2_text, 30))
+ snd_soc_update_bits(codec, micb_int_reg, 0x1C, 0x1C);
+ else if (strnstr(w->name, internal3_text, 30))
+ snd_soc_update_bits(codec, micb_int_reg, 0x3, 0x3);
+
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+
+ usleep_range(20000, 20000);
+
+ if (taiko->mbhc_polling_active &&
+ taiko->mbhc_cfg.micbias == micb_line) {
+ TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+ taiko_codec_pause_hs_polling(codec);
+ taiko_codec_start_hs_polling(codec);
+ TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+ }
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ if ((w->reg == taiko->mbhc_bias_regs.ctl_reg) &&
+ taiko_is_hph_pa_on(codec)) {
+ TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+ taiko_codec_switch_micbias(codec, 1);
+ TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+ }
+
+ if (strnstr(w->name, internal1_text, 30))
+ snd_soc_update_bits(codec, micb_int_reg, 0x80, 0x00);
+ else if (strnstr(w->name, internal2_text, 30))
+ snd_soc_update_bits(codec, micb_int_reg, 0x10, 0x00);
+ else if (strnstr(w->name, internal3_text, 30))
+ snd_soc_update_bits(codec, micb_int_reg, 0x2, 0x0);
+
+ taiko_codec_update_cfilt_usage(codec, cfilt_sel_val, 0);
+ break;
+ }
+
+ return 0;
+}
+
+
+static void tx_hpf_corner_freq_callback(struct work_struct *work)
+{
+ struct delayed_work *hpf_delayed_work;
+ struct hpf_work *hpf_work;
+ struct taiko_priv *taiko;
+ struct snd_soc_codec *codec;
+ u16 tx_mux_ctl_reg;
+ u8 hpf_cut_of_freq;
+
+ hpf_delayed_work = to_delayed_work(work);
+ hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+ taiko = hpf_work->taiko;
+ codec = hpf_work->taiko->codec;
+ hpf_cut_of_freq = hpf_work->tx_hpf_cut_of_freq;
+
+ tx_mux_ctl_reg = TAIKO_A_CDC_TX1_MUX_CTL +
+ (hpf_work->decimator - 1) * 8;
+
+ pr_debug("%s(): decimator %u hpf_cut_of_freq 0x%x\n", __func__,
+ hpf_work->decimator, (unsigned int)hpf_cut_of_freq);
+
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30, hpf_cut_of_freq << 4);
+}
+
+#define TX_MUX_CTL_CUT_OFF_FREQ_MASK 0x30
+#define CF_MIN_3DB_4HZ 0x0
+#define CF_MIN_3DB_75HZ 0x1
+#define CF_MIN_3DB_150HZ 0x2
+
+static int taiko_codec_enable_dec(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ unsigned int decimator;
+ char *dec_name = NULL;
+ char *widget_name = NULL;
+ char *temp;
+ int ret = 0;
+ u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
+ u8 dec_hpf_cut_of_freq;
+ int offset;
+
+
+ pr_debug("%s %d\n", __func__, event);
+
+ widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+ if (!widget_name)
+ return -ENOMEM;
+ temp = widget_name;
+
+ dec_name = strsep(&widget_name, " ");
+ widget_name = temp;
+ if (!dec_name) {
+ pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = kstrtouint(strpbrk(dec_name, "123456789"), 10, &decimator);
+ if (ret < 0) {
+ pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pr_debug("%s(): widget = %s dec_name = %s decimator = %u\n", __func__,
+ w->name, dec_name, decimator);
+
+ if (w->reg == TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL) {
+ dec_reset_reg = TAIKO_A_CDC_CLK_TX_RESET_B1_CTL;
+ offset = 0;
+ } else if (w->reg == TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL) {
+ dec_reset_reg = TAIKO_A_CDC_CLK_TX_RESET_B2_CTL;
+ offset = 8;
+ } else {
+ pr_err("%s: Error, incorrect dec\n", __func__);
+ return -EINVAL;
+ }
+
+ tx_vol_ctl_reg = TAIKO_A_CDC_TX1_VOL_CTL_CFG + 8 * (decimator - 1);
+ tx_mux_ctl_reg = TAIKO_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+
+ /* Enableable TX digital mute */
+ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
+
+ snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
+ 1 << w->shift);
+ snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
+
+ dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg);
+
+ dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq & 0x30) >> 4;
+
+ tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq =
+ dec_hpf_cut_of_freq;
+
+ if ((dec_hpf_cut_of_freq != CF_MIN_3DB_150HZ)) {
+
+ /* set cut of freq to CF_MIN_3DB_150HZ (0x1); */
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
+ CF_MIN_3DB_150HZ << 4);
+ }
+
+ /* enable HPF */
+ snd_soc_update_bits(codec, tx_mux_ctl_reg , 0x08, 0x00);
+
+ break;
+
+ case SND_SOC_DAPM_POST_PMU:
+
+ /* Disable TX digital mute */
+ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00);
+
+ if (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
+ CF_MIN_3DB_150HZ) {
+
+ schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
+ msecs_to_jiffies(300));
+ }
+ /* apply the digital gain after the decimator is enabled*/
+ if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
+ snd_soc_write(codec,
+ tx_digital_gain_reg[w->shift + offset],
+ snd_soc_read(codec,
+ tx_digital_gain_reg[w->shift + offset])
+ );
+
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+
+ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
+ cancel_delayed_work_sync(&tx_hpf_work[decimator - 1].dwork);
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08);
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
+ (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq) << 4);
+
+ break;
+ }
+out:
+ kfree(widget_name);
+ return ret;
+}
+
+static int taiko_codec_reset_interpolator(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ pr_debug("%s %d %s\n", __func__, event, w->name);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_RESET_CTL,
+ 1 << w->shift, 1 << w->shift);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_RESET_CTL,
+ 1 << w->shift, 0x0);
+ break;
+ case SND_SOC_DAPM_POST_PMU:
+ /* apply the digital gain after the interpolator is enabled*/
+ if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
+ snd_soc_write(codec,
+ rx_digital_gain_reg[w->shift],
+ snd_soc_read(codec,
+ rx_digital_gain_reg[w->shift])
+ );
+ break;
+ }
+ return 0;
+}
+
+static int taiko_codec_enable_ldo_h(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ case SND_SOC_DAPM_POST_PMD:
+ usleep_range(1000, 1000);
+ break;
+ }
+ return 0;
+}
+
+static int taiko_codec_enable_rx_bias(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ pr_debug("%s %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ taiko_enable_rx_bias(codec, 1);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ taiko_enable_rx_bias(codec, 0);
+ break;
+ }
+ return 0;
+}
+static int taiko_hphr_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ pr_debug("%s %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
+ break;
+ }
+ return 0;
+}
+
+static void taiko_snd_soc_jack_report(struct taiko_priv *taiko,
+ struct snd_soc_jack *jack, int status,
+ int mask)
+{
+ /* XXX: wake_lock_timeout()? */
+ snd_soc_jack_report_no_dapm(jack, status, mask);
+}
+
+static void hphocp_off_report(struct taiko_priv *taiko,
+ u32 jack_status, int irq)
+{
+ struct snd_soc_codec *codec;
+ if (!taiko) {
+ pr_err("%s: Bad taiko private data\n", __func__);
+ return;
+ }
+
+ pr_debug("%s: clear ocp status %x\n", __func__, jack_status);
+ codec = taiko->codec;
+ if (taiko->hph_status & jack_status) {
+ taiko->hph_status &= ~jack_status;
+ if (taiko->mbhc_cfg.headset_jack)
+ taiko_snd_soc_jack_report(taiko,
+ taiko->mbhc_cfg.headset_jack,
+ taiko->hph_status,
+ TAIKO_JACK_MASK);
+ snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL, 0x10, 0x00);
+ snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL, 0x10, 0x10);
+ /* reset retry counter as PA is turned off signifying
+ * start of new OCP detection session
+ */
+ if (TAIKO_IRQ_HPH_PA_OCPL_FAULT)
+ taiko->hphlocp_cnt = 0;
+ else
+ taiko->hphrocp_cnt = 0;
+ wcd9xxx_enable_irq(codec->control_data, irq);
+ }
+}
+
+static void hphlocp_off_report(struct work_struct *work)
+{
+ struct taiko_priv *taiko = container_of(work, struct taiko_priv,
+ hphlocp_work);
+ hphocp_off_report(taiko, SND_JACK_OC_HPHL, TAIKO_IRQ_HPH_PA_OCPL_FAULT);
+}
+
+static void hphrocp_off_report(struct work_struct *work)
+{
+ struct taiko_priv *taiko = container_of(work, struct taiko_priv,
+ hphrocp_work);
+ hphocp_off_report(taiko, SND_JACK_OC_HPHR, TAIKO_IRQ_HPH_PA_OCPR_FAULT);
+}
+
+static int taiko_hph_pa_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ u8 mbhc_micb_ctl_val;
+ pr_debug("%s: event = %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ mbhc_micb_ctl_val = snd_soc_read(codec,
+ taiko->mbhc_bias_regs.ctl_reg);
+
+ if (!(mbhc_micb_ctl_val & 0x80)) {
+ TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+ taiko_codec_switch_micbias(codec, 1);
+ TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+ }
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ /* schedule work is required because at the time HPH PA DAPM
+ * event callback is called by DAPM framework, CODEC dapm mutex
+ * would have been locked while snd_soc_jack_report also
+ * attempts to acquire same lock.
+ */
+ if (w->shift == 5) {
+ clear_bit(TAIKO_HPHL_PA_OFF_ACK,
+ &taiko->hph_pa_dac_state);
+ clear_bit(TAIKO_HPHL_DAC_OFF_ACK,
+ &taiko->hph_pa_dac_state);
+ if (taiko->hph_status & SND_JACK_OC_HPHL)
+ schedule_work(&taiko->hphlocp_work);
+ } else if (w->shift == 4) {
+ clear_bit(TAIKO_HPHR_PA_OFF_ACK,
+ &taiko->hph_pa_dac_state);
+ clear_bit(TAIKO_HPHR_DAC_OFF_ACK,
+ &taiko->hph_pa_dac_state);
+ if (taiko->hph_status & SND_JACK_OC_HPHR)
+ schedule_work(&taiko->hphrocp_work);
+ }
+
+ TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+ taiko_codec_switch_micbias(codec, 0);
+ TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+
+ pr_debug("%s: sleep 10 ms after %s PA disable.\n", __func__,
+ w->name);
+ usleep_range(10000, 10000);
+ break;
+ }
+ return 0;
+}
+
+static void taiko_get_mbhc_micbias_regs(struct snd_soc_codec *codec,
+ struct mbhc_micbias_regs *micbias_regs)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ unsigned int cfilt;
+
+ switch (taiko->mbhc_cfg.micbias) {
+ case TAIKO_MICBIAS1:
+ cfilt = taiko->pdata->micbias.bias1_cfilt_sel;
+ micbias_regs->mbhc_reg = TAIKO_A_MICB_1_MBHC;
+ micbias_regs->int_rbias = TAIKO_A_MICB_1_INT_RBIAS;
+ micbias_regs->ctl_reg = TAIKO_A_MICB_1_CTL;
+ break;
+ case TAIKO_MICBIAS2:
+ cfilt = taiko->pdata->micbias.bias2_cfilt_sel;
+ micbias_regs->mbhc_reg = TAIKO_A_MICB_2_MBHC;
+ micbias_regs->int_rbias = TAIKO_A_MICB_2_INT_RBIAS;
+ micbias_regs->ctl_reg = TAIKO_A_MICB_2_CTL;
+ break;
+ case TAIKO_MICBIAS3:
+ cfilt = taiko->pdata->micbias.bias3_cfilt_sel;
+ micbias_regs->mbhc_reg = TAIKO_A_MICB_3_MBHC;
+ micbias_regs->int_rbias = TAIKO_A_MICB_3_INT_RBIAS;
+ micbias_regs->ctl_reg = TAIKO_A_MICB_3_CTL;
+ break;
+ case TAIKO_MICBIAS4:
+ cfilt = taiko->pdata->micbias.bias4_cfilt_sel;
+ micbias_regs->mbhc_reg = taiko->reg_addr.micb_4_mbhc;
+ micbias_regs->int_rbias = taiko->reg_addr.micb_4_int_rbias;
+ micbias_regs->ctl_reg = taiko->reg_addr.micb_4_ctl;
+ break;
+ default:
+ /* Should never reach here */
+ pr_err("%s: Invalid MIC BIAS for MBHC\n", __func__);
+ return;
+ }
+
+ micbias_regs->cfilt_sel = cfilt;
+
+ switch (cfilt) {
+ case TAIKO_CFILT1_SEL:
+ micbias_regs->cfilt_val = TAIKO_A_MICB_CFILT_1_VAL;
+ micbias_regs->cfilt_ctl = TAIKO_A_MICB_CFILT_1_CTL;
+ taiko->mbhc_data.micb_mv = taiko->pdata->micbias.cfilt1_mv;
+ break;
+ case TAIKO_CFILT2_SEL:
+ micbias_regs->cfilt_val = TAIKO_A_MICB_CFILT_2_VAL;
+ micbias_regs->cfilt_ctl = TAIKO_A_MICB_CFILT_2_CTL;
+ taiko->mbhc_data.micb_mv = taiko->pdata->micbias.cfilt2_mv;
+ break;
+ case TAIKO_CFILT3_SEL:
+ micbias_regs->cfilt_val = TAIKO_A_MICB_CFILT_3_VAL;
+ micbias_regs->cfilt_ctl = TAIKO_A_MICB_CFILT_3_CTL;
+ taiko->mbhc_data.micb_mv = taiko->pdata->micbias.cfilt3_mv;
+ break;
+ }
+}
+static const struct snd_soc_dapm_widget taiko_dapm_i2s_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("RX_I2S_CLK", TAIKO_A_CDC_CLK_RX_I2S_CTL,
+ 4, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("TX_I2S_CLK", TAIKO_A_CDC_CLK_TX_I2S_CTL, 4,
+ 0, NULL, 0),
+};
+
+static int taiko_lineout_dac_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ pr_debug("%s %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
+ break;
+ }
+ return 0;
+}
+
+static const struct snd_soc_dapm_route audio_i2s_map[] = {
+ {"RX_I2S_CLK", NULL, "CDC_CONN"},
+ {"SLIM RX1", NULL, "RX_I2S_CLK"},
+ {"SLIM RX2", NULL, "RX_I2S_CLK"},
+ {"SLIM RX3", NULL, "RX_I2S_CLK"},
+ {"SLIM RX4", NULL, "RX_I2S_CLK"},
+
+ {"SLIM TX7", NULL, "TX_I2S_CLK"},
+ {"SLIM TX8", NULL, "TX_I2S_CLK"},
+ {"SLIM TX9", NULL, "TX_I2S_CLK"},
+ {"SLIM TX10", NULL, "TX_I2S_CLK"},
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* SLIMBUS Connections */
+
+ {"SLIM TX1", NULL, "SLIM TX1 MUX"},
+ {"SLIM TX1 MUX", "DEC1", "DEC1 MUX"},
+
+ {"SLIM TX2", NULL, "SLIM TX2 MUX"},
+ {"SLIM TX2 MUX", "DEC2", "DEC2 MUX"},
+
+ {"SLIM TX3", NULL, "SLIM TX3 MUX"},
+ {"SLIM TX3 MUX", "DEC3", "DEC3 MUX"},
+ {"SLIM TX3 MUX", "RMIX1", "RX1 MIX1"},
+ {"SLIM TX3 MUX", "RMIX2", "RX2 MIX1"},
+ {"SLIM TX3 MUX", "RMIX3", "RX3 MIX1"},
+ {"SLIM TX3 MUX", "RMIX4", "RX4 MIX1"},
+ {"SLIM TX3 MUX", "RMIX5", "RX5 MIX1"},
+ {"SLIM TX3 MUX", "RMIX6", "RX6 MIX1"},
+ {"SLIM TX3 MUX", "RMIX7", "RX7 MIX1"},
+
+ {"SLIM TX4", NULL, "SLIM TX4 MUX"},
+ {"SLIM TX4 MUX", "DEC4", "DEC4 MUX"},
+
+ {"SLIM TX5", NULL, "SLIM TX5 MUX"},
+ {"SLIM TX5 MUX", "DEC5", "DEC5 MUX"},
+ {"SLIM TX5 MUX", "RMIX1", "RX1 MIX1"},
+ {"SLIM TX5 MUX", "RMIX2", "RX2 MIX1"},
+ {"SLIM TX5 MUX", "RMIX3", "RX3 MIX1"},
+ {"SLIM TX5 MUX", "RMIX4", "RX4 MIX1"},
+ {"SLIM TX5 MUX", "RMIX5", "RX5 MIX1"},
+ {"SLIM TX5 MUX", "RMIX6", "RX6 MIX1"},
+ {"SLIM TX5 MUX", "RMIX7", "RX7 MIX1"},
+
+ {"SLIM TX6", NULL, "SLIM TX6 MUX"},
+ {"SLIM TX6 MUX", "DEC6", "DEC6 MUX"},
+
+ {"SLIM TX7", NULL, "SLIM TX7 MUX"},
+ {"SLIM TX7 MUX", "DEC1", "DEC1 MUX"},
+ {"SLIM TX7 MUX", "DEC2", "DEC2 MUX"},
+ {"SLIM TX7 MUX", "DEC3", "DEC3 MUX"},
+ {"SLIM TX7 MUX", "DEC4", "DEC4 MUX"},
+ {"SLIM TX7 MUX", "DEC5", "DEC5 MUX"},
+ {"SLIM TX7 MUX", "DEC6", "DEC6 MUX"},
+ {"SLIM TX7 MUX", "DEC7", "DEC7 MUX"},
+ {"SLIM TX7 MUX", "DEC8", "DEC8 MUX"},
+ {"SLIM TX7 MUX", "DEC9", "DEC9 MUX"},
+ {"SLIM TX7 MUX", "DEC10", "DEC10 MUX"},
+ {"SLIM TX7 MUX", "RMIX1", "RX1 MIX1"},
+ {"SLIM TX7 MUX", "RMIX2", "RX2 MIX1"},
+ {"SLIM TX7 MUX", "RMIX3", "RX3 MIX1"},
+ {"SLIM TX7 MUX", "RMIX4", "RX4 MIX1"},
+ {"SLIM TX7 MUX", "RMIX5", "RX5 MIX1"},
+ {"SLIM TX7 MUX", "RMIX6", "RX6 MIX1"},
+ {"SLIM TX7 MUX", "RMIX7", "RX7 MIX1"},
+
+ {"SLIM TX8", NULL, "SLIM TX8 MUX"},
+ {"SLIM TX8 MUX", "DEC1", "DEC1 MUX"},
+ {"SLIM TX8 MUX", "DEC2", "DEC2 MUX"},
+ {"SLIM TX8 MUX", "DEC3", "DEC3 MUX"},
+ {"SLIM TX8 MUX", "DEC4", "DEC4 MUX"},
+ {"SLIM TX8 MUX", "DEC5", "DEC5 MUX"},
+ {"SLIM TX8 MUX", "DEC6", "DEC6 MUX"},
+ {"SLIM TX8 MUX", "DEC7", "DEC7 MUX"},
+ {"SLIM TX8 MUX", "DEC8", "DEC8 MUX"},
+ {"SLIM TX8 MUX", "DEC9", "DEC9 MUX"},
+ {"SLIM TX8 MUX", "DEC10", "DEC10 MUX"},
+
+ {"SLIM TX9", NULL, "SLIM TX9 MUX"},
+ {"SLIM TX9 MUX", "DEC1", "DEC1 MUX"},
+ {"SLIM TX9 MUX", "DEC2", "DEC2 MUX"},
+ {"SLIM TX9 MUX", "DEC3", "DEC3 MUX"},
+ {"SLIM TX9 MUX", "DEC4", "DEC4 MUX"},
+ {"SLIM TX9 MUX", "DEC5", "DEC5 MUX"},
+ {"SLIM TX9 MUX", "DEC6", "DEC6 MUX"},
+ {"SLIM TX9 MUX", "DEC7", "DEC7 MUX"},
+ {"SLIM TX9 MUX", "DEC8", "DEC8 MUX"},
+ {"SLIM TX9 MUX", "DEC9", "DEC9 MUX"},
+ {"SLIM TX9 MUX", "DEC10", "DEC10 MUX"},
+
+ {"SLIM TX10", NULL, "SLIM TX10 MUX"},
+ {"SLIM TX10 MUX", "DEC1", "DEC1 MUX"},
+ {"SLIM TX10 MUX", "DEC2", "DEC2 MUX"},
+ {"SLIM TX10 MUX", "DEC3", "DEC3 MUX"},
+ {"SLIM TX10 MUX", "DEC4", "DEC4 MUX"},
+ {"SLIM TX10 MUX", "DEC5", "DEC5 MUX"},
+ {"SLIM TX10 MUX", "DEC6", "DEC6 MUX"},
+ {"SLIM TX10 MUX", "DEC7", "DEC7 MUX"},
+ {"SLIM TX10 MUX", "DEC8", "DEC8 MUX"},
+ {"SLIM TX10 MUX", "DEC9", "DEC9 MUX"},
+ {"SLIM TX10 MUX", "DEC10", "DEC10 MUX"},
+
+ /* Earpiece (RX MIX1) */
+ {"EAR", NULL, "EAR PA"},
+ {"EAR PA", NULL, "EAR_PA_MIXER"},
+ {"EAR_PA_MIXER", NULL, "DAC1"},
+ {"DAC1", NULL, "CP"},
+
+ {"ANC1 FB MUX", "EAR_HPH_L", "RX1 MIX2"},
+ {"ANC1 FB MUX", "EAR_LINE_1", "RX2 MIX2"},
+ {"ANC", NULL, "ANC1 FB MUX"},
+
+ /* Headset (RX MIX1 and RX MIX2) */
+ {"HEADPHONE", NULL, "HPHL"},
+ {"HEADPHONE", NULL, "HPHR"},
+
+ {"HPHL", NULL, "HPHL_PA_MIXER"},
+ {"HPHL_PA_MIXER", NULL, "HPHL DAC"},
+
+ {"HPHR", NULL, "HPHR_PA_MIXER"},
+ {"HPHR_PA_MIXER", NULL, "HPHR DAC"},
+
+ {"HPHL DAC", NULL, "CP"},
+ {"HPHR DAC", NULL, "CP"},
+
+ {"ANC", NULL, "ANC1 MUX"},
+ {"ANC", NULL, "ANC2 MUX"},
+ {"ANC1 MUX", "ADC1", "ADC1"},
+ {"ANC1 MUX", "ADC2", "ADC2"},
+ {"ANC1 MUX", "ADC3", "ADC3"},
+ {"ANC1 MUX", "ADC4", "ADC4"},
+ {"ANC2 MUX", "ADC1", "ADC1"},
+ {"ANC2 MUX", "ADC2", "ADC2"},
+ {"ANC2 MUX", "ADC3", "ADC3"},
+ {"ANC2 MUX", "ADC4", "ADC4"},
+
+ {"ANC", NULL, "CDC_CONN"},
+
+ {"DAC1", "Switch", "RX1 CHAIN"},
+ {"HPHL DAC", "Switch", "RX1 CHAIN"},
+ {"HPHR DAC", NULL, "RX2 CHAIN"},
+
+ {"LINEOUT1", NULL, "LINEOUT1 PA"},
+ {"LINEOUT2", NULL, "LINEOUT2 PA"},
+ {"LINEOUT3", NULL, "LINEOUT3 PA"},
+ {"LINEOUT4", NULL, "LINEOUT4 PA"},
+
+ {"LINEOUT1 PA", NULL, "LINEOUT1_PA_MIXER"},
+ {"LINEOUT1_PA_MIXER", NULL, "LINEOUT1 DAC"},
+ {"LINEOUT2 PA", NULL, "LINEOUT2_PA_MIXER"},
+ {"LINEOUT2_PA_MIXER", NULL, "LINEOUT2 DAC"},
+ {"LINEOUT3 PA", NULL, "LINEOUT3_PA_MIXER"},
+ {"LINEOUT3_PA_MIXER", NULL, "LINEOUT3 DAC"},
+ {"LINEOUT4 PA", NULL, "LINEOUT4_PA_MIXER"},
+ {"LINEOUT4_PA_MIXER", NULL, "LINEOUT4 DAC"},
+
+ {"LINEOUT1 DAC", NULL, "RX3 MIX1"},
+
+ {"RX4 DSM MUX", "DSM_INV", "RX3 MIX1"},
+ {"RX4 DSM MUX", "CIC_OUT", "RX4 MIX1"},
+ {"LINEOUT3 DAC", NULL, "RX4 DSM MUX"},
+
+ {"LINEOUT2 DAC", NULL, "RX5 MIX1"},
+
+ {"RX6 DSM MUX", "DSM_INV", "RX5 MIX1"},
+ {"RX6 DSM MUX", "CIC_OUT", "RX6 MIX1"},
+ {"LINEOUT4 DAC", NULL, "RX6 DSM MUX"},
+
+ {"RX1 CHAIN", NULL, "RX1 MIX2"},
+ {"RX2 CHAIN", NULL, "RX2 MIX2"},
+ {"RX1 CHAIN", NULL, "ANC"},
+ {"RX2 CHAIN", NULL, "ANC"},
+
+ {"CP", NULL, "RX_BIAS"},
+ {"LINEOUT1 DAC", NULL, "RX_BIAS"},
+ {"LINEOUT2 DAC", NULL, "RX_BIAS"},
+ {"LINEOUT3 DAC", NULL, "RX_BIAS"},
+ {"LINEOUT4 DAC", NULL, "RX_BIAS"},
+
+ {"RX1 MIX1", NULL, "COMP1_CLK"},
+ {"RX2 MIX1", NULL, "COMP1_CLK"},
+ {"RX3 MIX1", NULL, "COMP2_CLK"},
+ {"RX5 MIX1", NULL, "COMP2_CLK"},
+
+
+ {"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
+ {"RX1 MIX1", NULL, "RX1 MIX1 INP2"},
+ {"RX1 MIX1", NULL, "RX1 MIX1 INP3"},
+ {"RX2 MIX1", NULL, "RX2 MIX1 INP1"},
+ {"RX2 MIX1", NULL, "RX2 MIX1 INP2"},
+ {"RX3 MIX1", NULL, "RX3 MIX1 INP1"},
+ {"RX3 MIX1", NULL, "RX3 MIX1 INP2"},
+ {"RX4 MIX1", NULL, "RX4 MIX1 INP1"},
+ {"RX4 MIX1", NULL, "RX4 MIX1 INP2"},
+ {"RX5 MIX1", NULL, "RX5 MIX1 INP1"},
+ {"RX5 MIX1", NULL, "RX5 MIX1 INP2"},
+ {"RX6 MIX1", NULL, "RX6 MIX1 INP1"},
+ {"RX6 MIX1", NULL, "RX6 MIX1 INP2"},
+ {"RX7 MIX1", NULL, "RX7 MIX1 INP1"},
+ {"RX7 MIX1", NULL, "RX7 MIX1 INP2"},
+ {"RX1 MIX2", NULL, "RX1 MIX1"},
+ {"RX1 MIX2", NULL, "RX1 MIX2 INP1"},
+ {"RX1 MIX2", NULL, "RX1 MIX2 INP2"},
+ {"RX2 MIX2", NULL, "RX2 MIX1"},
+ {"RX2 MIX2", NULL, "RX2 MIX2 INP1"},
+ {"RX2 MIX2", NULL, "RX2 MIX2 INP2"},
+ {"RX7 MIX2", NULL, "RX7 MIX1"},
+ {"RX7 MIX2", NULL, "RX7 MIX2 INP1"},
+ {"RX7 MIX2", NULL, "RX7 MIX2 INP2"},
+
+ {"RX1 MIX1 INP1", "RX1", "SLIM RX1"},
+ {"RX1 MIX1 INP1", "RX2", "SLIM RX2"},
+ {"RX1 MIX1 INP1", "RX3", "SLIM RX3"},
+ {"RX1 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX1 MIX1 INP1", "RX5", "SLIM RX5"},
+ {"RX1 MIX1 INP1", "RX6", "SLIM RX6"},
+ {"RX1 MIX1 INP1", "RX7", "SLIM RX7"},
+ {"RX1 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX1 MIX1 INP2", "RX1", "SLIM RX1"},
+ {"RX1 MIX1 INP2", "RX2", "SLIM RX2"},
+ {"RX1 MIX1 INP2", "RX3", "SLIM RX3"},
+ {"RX1 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX1 MIX1 INP2", "RX5", "SLIM RX5"},
+ {"RX1 MIX1 INP2", "RX6", "SLIM RX6"},
+ {"RX1 MIX1 INP2", "RX7", "SLIM RX7"},
+ {"RX1 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX1 MIX1 INP3", "RX1", "SLIM RX1"},
+ {"RX1 MIX1 INP3", "RX2", "SLIM RX2"},
+ {"RX1 MIX1 INP3", "RX3", "SLIM RX3"},
+ {"RX1 MIX1 INP3", "RX4", "SLIM RX4"},
+ {"RX1 MIX1 INP3", "RX5", "SLIM RX5"},
+ {"RX1 MIX1 INP3", "RX6", "SLIM RX6"},
+ {"RX1 MIX1 INP3", "RX7", "SLIM RX7"},
+ {"RX2 MIX1 INP1", "RX1", "SLIM RX1"},
+ {"RX2 MIX1 INP1", "RX2", "SLIM RX2"},
+ {"RX2 MIX1 INP1", "RX3", "SLIM RX3"},
+ {"RX2 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX2 MIX1 INP1", "RX5", "SLIM RX5"},
+ {"RX2 MIX1 INP1", "RX6", "SLIM RX6"},
+ {"RX2 MIX1 INP1", "RX7", "SLIM RX7"},
+ {"RX2 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX2 MIX1 INP2", "RX1", "SLIM RX1"},
+ {"RX2 MIX1 INP2", "RX2", "SLIM RX2"},
+ {"RX2 MIX1 INP2", "RX3", "SLIM RX3"},
+ {"RX2 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX2 MIX1 INP2", "RX5", "SLIM RX5"},
+ {"RX2 MIX1 INP2", "RX6", "SLIM RX6"},
+ {"RX2 MIX1 INP2", "RX7", "SLIM RX7"},
+ {"RX2 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX3 MIX1 INP1", "RX1", "SLIM RX1"},
+ {"RX3 MIX1 INP1", "RX2", "SLIM RX2"},
+ {"RX3 MIX1 INP1", "RX3", "SLIM RX3"},
+ {"RX3 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX3 MIX1 INP1", "RX5", "SLIM RX5"},
+ {"RX3 MIX1 INP1", "RX6", "SLIM RX6"},
+ {"RX3 MIX1 INP1", "RX7", "SLIM RX7"},
+ {"RX3 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX3 MIX1 INP2", "RX1", "SLIM RX1"},
+ {"RX3 MIX1 INP2", "RX2", "SLIM RX2"},
+ {"RX3 MIX1 INP2", "RX3", "SLIM RX3"},
+ {"RX3 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX3 MIX1 INP2", "RX5", "SLIM RX5"},
+ {"RX3 MIX1 INP2", "RX6", "SLIM RX6"},
+ {"RX3 MIX1 INP2", "RX7", "SLIM RX7"},
+ {"RX3 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX4 MIX1 INP1", "RX1", "SLIM RX1"},
+ {"RX4 MIX1 INP1", "RX2", "SLIM RX2"},
+ {"RX4 MIX1 INP1", "RX3", "SLIM RX3"},
+ {"RX4 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX4 MIX1 INP1", "RX5", "SLIM RX5"},
+ {"RX4 MIX1 INP1", "RX6", "SLIM RX6"},
+ {"RX4 MIX1 INP1", "RX7", "SLIM RX7"},
+ {"RX4 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX4 MIX1 INP2", "RX1", "SLIM RX1"},
+ {"RX4 MIX1 INP2", "RX2", "SLIM RX2"},
+ {"RX4 MIX1 INP2", "RX3", "SLIM RX3"},
+ {"RX4 MIX1 INP2", "RX5", "SLIM RX5"},
+ {"RX4 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX4 MIX1 INP2", "RX6", "SLIM RX6"},
+ {"RX4 MIX1 INP2", "RX7", "SLIM RX7"},
+ {"RX4 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX5 MIX1 INP1", "RX1", "SLIM RX1"},
+ {"RX5 MIX1 INP1", "RX2", "SLIM RX2"},
+ {"RX5 MIX1 INP1", "RX3", "SLIM RX3"},
+ {"RX5 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX5 MIX1 INP1", "RX5", "SLIM RX5"},
+ {"RX5 MIX1 INP1", "RX6", "SLIM RX6"},
+ {"RX5 MIX1 INP1", "RX7", "SLIM RX7"},
+ {"RX5 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX5 MIX1 INP2", "RX1", "SLIM RX1"},
+ {"RX5 MIX1 INP2", "RX2", "SLIM RX2"},
+ {"RX5 MIX1 INP2", "RX3", "SLIM RX3"},
+ {"RX5 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX5 MIX1 INP2", "RX5", "SLIM RX5"},
+ {"RX5 MIX1 INP2", "RX6", "SLIM RX6"},
+ {"RX5 MIX1 INP2", "RX7", "SLIM RX7"},
+ {"RX5 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX6 MIX1 INP1", "RX1", "SLIM RX1"},
+ {"RX6 MIX1 INP1", "RX2", "SLIM RX2"},
+ {"RX6 MIX1 INP1", "RX3", "SLIM RX3"},
+ {"RX6 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX6 MIX1 INP1", "RX5", "SLIM RX5"},
+ {"RX6 MIX1 INP1", "RX6", "SLIM RX6"},
+ {"RX6 MIX1 INP1", "RX7", "SLIM RX7"},
+ {"RX6 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX6 MIX1 INP2", "RX1", "SLIM RX1"},
+ {"RX6 MIX1 INP2", "RX2", "SLIM RX2"},
+ {"RX6 MIX1 INP2", "RX3", "SLIM RX3"},
+ {"RX6 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX6 MIX1 INP2", "RX5", "SLIM RX5"},
+ {"RX6 MIX1 INP2", "RX6", "SLIM RX6"},
+ {"RX6 MIX1 INP2", "RX7", "SLIM RX7"},
+ {"RX6 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX7 MIX1 INP1", "RX1", "SLIM RX1"},
+ {"RX7 MIX1 INP1", "RX2", "SLIM RX2"},
+ {"RX7 MIX1 INP1", "RX3", "SLIM RX3"},
+ {"RX7 MIX1 INP1", "RX4", "SLIM RX4"},
+ {"RX7 MIX1 INP1", "RX5", "SLIM RX5"},
+ {"RX7 MIX1 INP1", "RX6", "SLIM RX6"},
+ {"RX7 MIX1 INP1", "RX7", "SLIM RX7"},
+ {"RX7 MIX1 INP1", "IIR1", "IIR1"},
+ {"RX7 MIX1 INP2", "RX1", "SLIM RX1"},
+ {"RX7 MIX1 INP2", "RX2", "SLIM RX2"},
+ {"RX7 MIX1 INP2", "RX3", "SLIM RX3"},
+ {"RX7 MIX1 INP2", "RX4", "SLIM RX4"},
+ {"RX7 MIX1 INP2", "RX5", "SLIM RX5"},
+ {"RX7 MIX1 INP2", "RX6", "SLIM RX6"},
+ {"RX7 MIX1 INP2", "RX7", "SLIM RX7"},
+ {"RX7 MIX1 INP2", "IIR1", "IIR1"},
+ {"RX1 MIX2 INP1", "IIR1", "IIR1"},
+ {"RX1 MIX2 INP2", "IIR1", "IIR1"},
+ {"RX2 MIX2 INP1", "IIR1", "IIR1"},
+ {"RX2 MIX2 INP2", "IIR1", "IIR1"},
+ {"RX7 MIX2 INP1", "IIR1", "IIR1"},
+ {"RX7 MIX2 INP2", "IIR1", "IIR1"},
+
+ /* Decimator Inputs */
+ {"DEC1 MUX", "DMIC1", "DMIC1"},
+ {"DEC1 MUX", "ADC6", "ADC6"},
+ {"DEC1 MUX", NULL, "CDC_CONN"},
+ {"DEC2 MUX", "DMIC2", "DMIC2"},
+ {"DEC2 MUX", "ADC5", "ADC5"},
+ {"DEC2 MUX", NULL, "CDC_CONN"},
+ {"DEC3 MUX", "DMIC3", "DMIC3"},
+ {"DEC3 MUX", "ADC4", "ADC4"},
+ {"DEC3 MUX", NULL, "CDC_CONN"},
+ {"DEC4 MUX", "DMIC4", "DMIC4"},
+ {"DEC4 MUX", "ADC3", "ADC3"},
+ {"DEC4 MUX", NULL, "CDC_CONN"},
+ {"DEC5 MUX", "DMIC5", "DMIC5"},
+ {"DEC5 MUX", "ADC2", "ADC2"},
+ {"DEC5 MUX", NULL, "CDC_CONN"},
+ {"DEC6 MUX", "DMIC6", "DMIC6"},
+ {"DEC6 MUX", "ADC1", "ADC1"},
+ {"DEC6 MUX", NULL, "CDC_CONN"},
+ {"DEC7 MUX", "DMIC1", "DMIC1"},
+ {"DEC7 MUX", "DMIC6", "DMIC6"},
+ {"DEC7 MUX", "ADC1", "ADC1"},
+ {"DEC7 MUX", "ADC6", "ADC6"},
+ {"DEC7 MUX", NULL, "CDC_CONN"},
+ {"DEC8 MUX", "DMIC2", "DMIC2"},
+ {"DEC8 MUX", "DMIC5", "DMIC5"},
+ {"DEC8 MUX", "ADC2", "ADC2"},
+ {"DEC8 MUX", "ADC5", "ADC5"},
+ {"DEC8 MUX", NULL, "CDC_CONN"},
+ {"DEC9 MUX", "DMIC4", "DMIC4"},
+ {"DEC9 MUX", "DMIC5", "DMIC5"},
+ {"DEC9 MUX", "ADC2", "ADC2"},
+ {"DEC9 MUX", "ADC3", "ADC3"},
+ {"DEC9 MUX", NULL, "CDC_CONN"},
+ {"DEC10 MUX", "DMIC3", "DMIC3"},
+ {"DEC10 MUX", "DMIC6", "DMIC6"},
+ {"DEC10 MUX", "ADC1", "ADC1"},
+ {"DEC10 MUX", "ADC4", "ADC4"},
+ {"DEC10 MUX", NULL, "CDC_CONN"},
+
+ /* ADC Connections */
+ {"ADC1", NULL, "AMIC1"},
+ {"ADC2", NULL, "AMIC2"},
+ {"ADC3", NULL, "AMIC3"},
+ {"ADC4", NULL, "AMIC4"},
+ {"ADC5", NULL, "AMIC5"},
+ {"ADC6", NULL, "AMIC6"},
+
+ /* AUX PGA Connections */
+ {"HPHL_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+ {"HPHL_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+ {"HPHL_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+ {"HPHL_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+ {"HPHR_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+ {"HPHR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+ {"HPHR_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+ {"HPHR_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+ {"LINEOUT1_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+ {"LINEOUT1_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+ {"LINEOUT1_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+ {"LINEOUT1_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+ {"LINEOUT2_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+ {"LINEOUT2_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+ {"LINEOUT2_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+ {"LINEOUT2_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+ {"LINEOUT3_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+ {"LINEOUT3_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+ {"LINEOUT3_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+ {"LINEOUT3_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+ {"LINEOUT4_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+ {"LINEOUT4_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+ {"LINEOUT4_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+ {"LINEOUT4_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+ {"EAR_PA_MIXER", "AUX_PGA_L Switch", "AUX_PGA_Left"},
+ {"EAR_PA_MIXER", "AUX_PGA_R Switch", "AUX_PGA_Right"},
+ {"EAR_PA_MIXER", "AUX_PGA_L_INV Switch", "AUX_PGA_Left"},
+ {"EAR_PA_MIXER", "AUX_PGA_R_INV Switch", "AUX_PGA_Right"},
+ {"AUX_PGA_Left", NULL, "AMIC5"},
+ {"AUX_PGA_Right", NULL, "AMIC6"},
+
+
+ {"IIR1", NULL, "IIR1 INP1 MUX"},
+ {"IIR1 INP1 MUX", "DEC1", "DEC1 MUX"},
+ {"IIR1 INP1 MUX", "DEC2", "DEC2 MUX"},
+ {"IIR1 INP1 MUX", "DEC3", "DEC3 MUX"},
+ {"IIR1 INP1 MUX", "DEC4", "DEC4 MUX"},
+ {"IIR1 INP1 MUX", "DEC5", "DEC5 MUX"},
+ {"IIR1 INP1 MUX", "DEC6", "DEC6 MUX"},
+ {"IIR1 INP1 MUX", "DEC7", "DEC7 MUX"},
+ {"IIR1 INP1 MUX", "DEC8", "DEC8 MUX"},
+ {"IIR1 INP1 MUX", "DEC9", "DEC9 MUX"},
+ {"IIR1 INP1 MUX", "DEC10", "DEC10 MUX"},
+
+ {"MIC BIAS1 Internal1", NULL, "LDO_H"},
+ {"MIC BIAS1 Internal2", NULL, "LDO_H"},
+ {"MIC BIAS1 External", NULL, "LDO_H"},
+ {"MIC BIAS2 Internal1", NULL, "LDO_H"},
+ {"MIC BIAS2 Internal2", NULL, "LDO_H"},
+ {"MIC BIAS2 Internal3", NULL, "LDO_H"},
+ {"MIC BIAS2 External", NULL, "LDO_H"},
+ {"MIC BIAS3 Internal1", NULL, "LDO_H"},
+ {"MIC BIAS3 Internal2", NULL, "LDO_H"},
+ {"MIC BIAS3 External", NULL, "LDO_H"},
+ {"MIC BIAS4 External", NULL, "LDO_H"},
+};
+
+static int taiko_readable(struct snd_soc_codec *ssc, unsigned int reg)
+{
+ return taiko_reg_readable[reg];
+}
+
+static bool taiko_is_digital_gain_register(unsigned int reg)
+{
+ bool rtn = false;
+ switch (reg) {
+ case TAIKO_A_CDC_RX1_VOL_CTL_B2_CTL:
+ case TAIKO_A_CDC_RX2_VOL_CTL_B2_CTL:
+ case TAIKO_A_CDC_RX3_VOL_CTL_B2_CTL:
+ case TAIKO_A_CDC_RX4_VOL_CTL_B2_CTL:
+ case TAIKO_A_CDC_RX5_VOL_CTL_B2_CTL:
+ case TAIKO_A_CDC_RX6_VOL_CTL_B2_CTL:
+ case TAIKO_A_CDC_RX7_VOL_CTL_B2_CTL:
+ case TAIKO_A_CDC_TX1_VOL_CTL_GAIN:
+ case TAIKO_A_CDC_TX2_VOL_CTL_GAIN:
+ case TAIKO_A_CDC_TX3_VOL_CTL_GAIN:
+ case TAIKO_A_CDC_TX4_VOL_CTL_GAIN:
+ case TAIKO_A_CDC_TX5_VOL_CTL_GAIN:
+ case TAIKO_A_CDC_TX6_VOL_CTL_GAIN:
+ case TAIKO_A_CDC_TX7_VOL_CTL_GAIN:
+ case TAIKO_A_CDC_TX8_VOL_CTL_GAIN:
+ case TAIKO_A_CDC_TX9_VOL_CTL_GAIN:
+ case TAIKO_A_CDC_TX10_VOL_CTL_GAIN:
+ rtn = true;
+ break;
+ default:
+ break;
+ }
+ return rtn;
+}
+
+static int taiko_volatile(struct snd_soc_codec *ssc, unsigned int reg)
+{
+ /* Registers lower than 0x100 are top level registers which can be
+ * written by the Taiko core driver.
+ */
+
+ if ((reg >= TAIKO_A_CDC_MBHC_EN_CTL) || (reg < 0x100))
+ return 1;
+
+ /* IIR Coeff registers are not cacheable */
+ if ((reg >= TAIKO_A_CDC_IIR1_COEF_B1_CTL) &&
+ (reg <= TAIKO_A_CDC_IIR2_COEF_B2_CTL))
+ return 1;
+
+ /* Digital gain register is not cacheable so we have to write
+ * the setting even it is the same
+ */
+ if (taiko_is_digital_gain_register(reg))
+ return 1;
+
+ /* HPH status registers */
+ if (reg == TAIKO_A_RX_HPH_L_STATUS || reg == TAIKO_A_RX_HPH_R_STATUS)
+ return 1;
+
+ return 0;
+}
+
+#define TAIKO_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
+static int taiko_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
+{
+ int ret;
+ BUG_ON(reg > TAIKO_MAX_REGISTER);
+
+ if (!taiko_volatile(codec, reg)) {
+ ret = snd_soc_cache_write(codec, reg, value);
+ if (ret != 0)
+ dev_err(codec->dev, "Cache write to %x failed: %d\n",
+ reg, ret);
+ }
+
+ return wcd9xxx_reg_write(codec->control_data, reg, value);
+}
+static unsigned int taiko_read(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ unsigned int val;
+ int ret;
+
+ BUG_ON(reg > TAIKO_MAX_REGISTER);
+
+ if (!taiko_volatile(codec, reg) && taiko_readable(codec, reg) &&
+ reg < codec->driver->reg_cache_size) {
+ ret = snd_soc_cache_read(codec, reg, &val);
+ if (ret >= 0) {
+ return val;
+ } else
+ dev_err(codec->dev, "Cache read from %x failed: %d\n",
+ reg, ret);
+ }
+
+ val = wcd9xxx_reg_read(codec->control_data, reg);
+ return val;
+}
+
+static s16 taiko_get_current_v_ins(struct taiko_priv *taiko, bool hu)
+{
+ s16 v_ins;
+ if ((taiko->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) &&
+ taiko->mbhc_micbias_switched)
+ v_ins = hu ? (s16)taiko->mbhc_data.adj_v_ins_hu :
+ (s16)taiko->mbhc_data.adj_v_ins_h;
+ else
+ v_ins = hu ? (s16)taiko->mbhc_data.v_ins_hu :
+ (s16)taiko->mbhc_data.v_ins_h;
+ return v_ins;
+}
+
+static s16 taiko_get_current_v_hs_max(struct taiko_priv *taiko)
+{
+ s16 v_hs_max;
+ struct taiko_mbhc_plug_type_cfg *plug_type;
+
+ plug_type = TAIKO_MBHC_CAL_PLUG_TYPE_PTR(taiko->mbhc_cfg.calibration);
+ if ((taiko->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) &&
+ taiko->mbhc_micbias_switched)
+ v_hs_max = taiko->mbhc_data.adj_v_hs_max;
+ else
+ v_hs_max = plug_type->v_hs_max;
+ return v_hs_max;
+}
+
+static void taiko_codec_calibrate_hs_polling(struct snd_soc_codec *codec)
+{
+ u8 *n_ready, *n_cic;
+ struct taiko_mbhc_btn_detect_cfg *btn_det;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ const s16 v_ins_hu = taiko_get_current_v_ins(taiko, true);
+
+ btn_det = TAIKO_MBHC_CAL_BTN_DET_PTR(taiko->mbhc_cfg.calibration);
+
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B1_CTL,
+ v_ins_hu & 0xFF);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B2_CTL,
+ (v_ins_hu >> 8) & 0xFF);
+
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B3_CTL,
+ taiko->mbhc_data.v_b1_hu & 0xFF);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B4_CTL,
+ (taiko->mbhc_data.v_b1_hu >> 8) & 0xFF);
+
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B5_CTL,
+ taiko->mbhc_data.v_b1_h & 0xFF);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B6_CTL,
+ (taiko->mbhc_data.v_b1_h >> 8) & 0xFF);
+
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B9_CTL,
+ taiko->mbhc_data.v_brh & 0xFF);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B10_CTL,
+ (taiko->mbhc_data.v_brh >> 8) & 0xFF);
+
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B11_CTL,
+ taiko->mbhc_data.v_brl & 0xFF);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_VOLT_B12_CTL,
+ (taiko->mbhc_data.v_brl >> 8) & 0xFF);
+
+ n_ready = taiko_mbhc_cal_btn_det_mp(btn_det, TAIKO_BTN_DET_N_READY);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_TIMER_B1_CTL,
+ n_ready[taiko_codec_mclk_index(taiko)]);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_TIMER_B2_CTL,
+ taiko->mbhc_data.npoll);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_TIMER_B3_CTL,
+ taiko->mbhc_data.nbounce_wait);
+ n_cic = taiko_mbhc_cal_btn_det_mp(btn_det, TAIKO_BTN_DET_N_CIC);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_TIMER_B6_CTL,
+ n_cic[taiko_codec_mclk_index(taiko)]);
+}
+
+static int taiko_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct wcd9xxx *taiko_core = dev_get_drvdata(dai->codec->dev->parent);
+ pr_debug("%s(): substream = %s stream = %d\n" , __func__,
+ substream->name, substream->stream);
+ if ((taiko_core != NULL) &&
+ (taiko_core->dev != NULL) &&
+ (taiko_core->dev->parent != NULL))
+ pm_runtime_get_sync(taiko_core->dev->parent);
+
+ return 0;
+}
+
+static void taiko_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct wcd9xxx *taiko_core = dev_get_drvdata(dai->codec->dev->parent);
+ pr_debug("%s(): substream = %s stream = %d\n" , __func__,
+ substream->name, substream->stream);
+ if ((taiko_core != NULL) &&
+ (taiko_core->dev != NULL) &&
+ (taiko_core->dev->parent != NULL)) {
+ pm_runtime_mark_last_busy(taiko_core->dev->parent);
+ pm_runtime_put(taiko_core->dev->parent);
+ }
+}
+
+int taiko_mclk_enable(struct snd_soc_codec *codec, int mclk_enable, bool dapm)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s: mclk_enable = %u, dapm = %d\n", __func__, mclk_enable,
+ dapm);
+ if (dapm)
+ TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+ if (mclk_enable) {
+ taiko->mclk_enabled = true;
+
+ if (taiko->mbhc_polling_active) {
+ taiko_codec_pause_hs_polling(codec);
+ taiko_codec_disable_clock_block(codec);
+ taiko_codec_enable_bandgap(codec,
+ TAIKO_BANDGAP_AUDIO_MODE);
+ taiko_codec_enable_clock_block(codec, 0);
+ taiko_codec_calibrate_hs_polling(codec);
+ taiko_codec_start_hs_polling(codec);
+ } else {
+ taiko_codec_disable_clock_block(codec);
+ taiko_codec_enable_bandgap(codec,
+ TAIKO_BANDGAP_AUDIO_MODE);
+ taiko_codec_enable_clock_block(codec, 0);
+ }
+ } else {
+
+ if (!taiko->mclk_enabled) {
+ if (dapm)
+ TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+ pr_err("Error, MCLK already diabled\n");
+ return -EINVAL;
+ }
+ taiko->mclk_enabled = false;
+
+ if (taiko->mbhc_polling_active) {
+ taiko_codec_pause_hs_polling(codec);
+ taiko_codec_disable_clock_block(codec);
+ taiko_codec_enable_bandgap(codec,
+ TAIKO_BANDGAP_MBHC_MODE);
+ taiko_enable_rx_bias(codec, 1);
+ taiko_codec_enable_clock_block(codec, 1);
+ taiko_codec_calibrate_hs_polling(codec);
+ taiko_codec_start_hs_polling(codec);
+ snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1,
+ 0x05, 0x01);
+ } else {
+ taiko_codec_disable_clock_block(codec);
+ taiko_codec_enable_bandgap(codec,
+ TAIKO_BANDGAP_OFF);
+ }
+ }
+ if (dapm)
+ TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+ return 0;
+}
+
+static int taiko_set_dai_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ pr_debug("%s\n", __func__);
+ return 0;
+}
+
+static int taiko_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ u8 val = 0;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
+
+ pr_debug("%s\n", __func__);
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ /* CPU is master */
+ if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+ if (dai->id == AIF1_CAP)
+ snd_soc_update_bits(dai->codec,
+ TAIKO_A_CDC_CLK_TX_I2S_CTL,
+ TAIKO_I2S_MASTER_MODE_MASK, 0);
+ else if (dai->id == AIF1_PB)
+ snd_soc_update_bits(dai->codec,
+ TAIKO_A_CDC_CLK_RX_I2S_CTL,
+ TAIKO_I2S_MASTER_MODE_MASK, 0);
+ }
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ /* CPU is slave */
+ if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+ val = TAIKO_I2S_MASTER_MODE_MASK;
+ if (dai->id == AIF1_CAP)
+ snd_soc_update_bits(dai->codec,
+ TAIKO_A_CDC_CLK_TX_I2S_CTL, val, val);
+ else if (dai->id == AIF1_PB)
+ snd_soc_update_bits(dai->codec,
+ TAIKO_A_CDC_CLK_RX_I2S_CTL, val, val);
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int taiko_set_channel_map(struct snd_soc_dai *dai,
+ unsigned int tx_num, unsigned int *tx_slot,
+ unsigned int rx_num, unsigned int *rx_slot)
+
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
+ u32 i = 0;
+ if (!tx_slot && !rx_slot) {
+ pr_err("%s: Invalid\n", __func__);
+ return -EINVAL;
+ }
+ pr_debug("%s(): dai_name = %s DAI-ID %x tx_ch %d rx_ch %d\n",
+ __func__, dai->name, dai->id, tx_num, rx_num);
+
+ if (dai->id == AIF1_PB || dai->id == AIF2_PB || dai->id == AIF3_PB) {
+ for (i = 0; i < rx_num; i++) {
+ taiko->dai[dai->id - 1].ch_num[i] = rx_slot[i];
+ taiko->dai[dai->id - 1].ch_act = 0;
+ taiko->dai[dai->id - 1].ch_tot = rx_num;
+ }
+ } else if (dai->id == AIF1_CAP || dai->id == AIF2_CAP ||
+ dai->id == AIF3_CAP) {
+ for (i = 0; i < tx_num; i++) {
+ taiko->dai[dai->id - 1].ch_num[i] = tx_slot[i];
+ taiko->dai[dai->id - 1].ch_act = 0;
+ taiko->dai[dai->id - 1].ch_tot = tx_num;
+ }
+ }
+ return 0;
+}
+
+static int taiko_get_channel_map(struct snd_soc_dai *dai,
+ unsigned int *tx_num, unsigned int *tx_slot,
+ unsigned int *rx_num, unsigned int *rx_slot)
+
+{
+ struct wcd9xxx *taiko = dev_get_drvdata(dai->codec->control_data);
+
+ u32 cnt = 0;
+ u32 tx_ch[SLIM_MAX_TX_PORTS];
+ u32 rx_ch[SLIM_MAX_RX_PORTS];
+
+ if (!rx_slot && !tx_slot) {
+ pr_err("%s: Invalid\n", __func__);
+ return -EINVAL;
+ }
+
+ /* for virtual port, codec driver needs to do
+ * housekeeping, for now should be ok
+ */
+ wcd9xxx_get_channel(taiko, rx_ch, tx_ch);
+ if (dai->id == AIF1_PB) {
+ *rx_num = taiko_dai[dai->id - 1].playback.channels_max;
+ while (cnt < *rx_num) {
+ rx_slot[cnt] = rx_ch[cnt];
+ cnt++;
+ }
+ } else if (dai->id == AIF1_CAP) {
+ *tx_num = taiko_dai[dai->id - 1].capture.channels_max;
+ while (cnt < *tx_num) {
+ tx_slot[cnt] = tx_ch[6 + cnt];
+ cnt++;
+ }
+ } else if (dai->id == AIF2_PB) {
+ *rx_num = taiko_dai[dai->id - 1].playback.channels_max;
+ while (cnt < *rx_num) {
+ rx_slot[cnt] = rx_ch[5 + cnt];
+ cnt++;
+ }
+ } else if (dai->id == AIF2_CAP) {
+ *tx_num = taiko_dai[dai->id - 1].capture.channels_max;
+ tx_slot[0] = tx_ch[cnt];
+ tx_slot[1] = tx_ch[1 + cnt];
+ tx_slot[2] = tx_ch[5 + cnt];
+ tx_slot[3] = tx_ch[3 + cnt];
+
+ } else if (dai->id == AIF3_PB) {
+ *rx_num = taiko_dai[dai->id - 1].playback.channels_max;
+ rx_slot[0] = rx_ch[3];
+ rx_slot[1] = rx_ch[4];
+
+ } else if (dai->id == AIF3_CAP) {
+ *tx_num = taiko_dai[dai->id - 1].capture.channels_max;
+ tx_slot[cnt] = tx_ch[2 + cnt];
+ tx_slot[cnt + 1] = tx_ch[4 + cnt];
+ }
+ pr_debug("%s(): dai_name = %s DAI-ID %x tx_ch %d rx_ch %d\n",
+ __func__, dai->name, dai->id, *tx_num, *rx_num);
+
+
+ return 0;
+}
+
+static int taiko_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(dai->codec);
+ u8 path, shift;
+ u16 tx_fs_reg, rx_fs_reg;
+ u8 tx_fs_rate, rx_fs_rate, rx_state, tx_state;
+ u32 compander_fs;
+
+ pr_debug("%s: dai_name = %s DAI-ID %x rate %d num_ch %d\n", __func__,
+ dai->name, dai->id, params_rate(params),
+ params_channels(params));
+
+ switch (params_rate(params)) {
+ case 8000:
+ tx_fs_rate = 0x00;
+ rx_fs_rate = 0x00;
+ compander_fs = COMPANDER_FS_8KHZ;
+ break;
+ case 16000:
+ tx_fs_rate = 0x01;
+ rx_fs_rate = 0x20;
+ compander_fs = COMPANDER_FS_16KHZ;
+ break;
+ case 32000:
+ tx_fs_rate = 0x02;
+ rx_fs_rate = 0x40;
+ compander_fs = COMPANDER_FS_32KHZ;
+ break;
+ case 48000:
+ tx_fs_rate = 0x03;
+ rx_fs_rate = 0x60;
+ compander_fs = COMPANDER_FS_48KHZ;
+ break;
+ case 96000:
+ tx_fs_rate = 0x04;
+ rx_fs_rate = 0x80;
+ compander_fs = COMPANDER_FS_96KHZ;
+ break;
+ case 192000:
+ tx_fs_rate = 0x05;
+ rx_fs_rate = 0xA0;
+ compander_fs = COMPANDER_FS_192KHZ;
+ break;
+ default:
+ pr_err("%s: Invalid sampling rate %d\n", __func__,
+ params_rate(params));
+ return -EINVAL;
+ }
+
+
+ /**
+ * If current dai is a tx dai, set sample rate to
+ * all the txfe paths that are currently not active
+ */
+ if ((dai->id == AIF1_CAP) || (dai->id == AIF2_CAP) ||
+ (dai->id == AIF3_CAP)) {
+
+ tx_state = snd_soc_read(codec,
+ TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL);
+
+ for (path = 1, shift = 0;
+ path <= NUM_DECIMATORS; path++, shift++) {
+
+ if (path == BITS_PER_REG + 1) {
+ shift = 0;
+ tx_state = snd_soc_read(codec,
+ TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL);
+ }
+
+ if (!(tx_state & (1 << shift))) {
+ tx_fs_reg = TAIKO_A_CDC_TX1_CLK_FS_CTL
+ + (BITS_PER_REG*(path-1));
+ snd_soc_update_bits(codec, tx_fs_reg,
+ 0x07, tx_fs_rate);
+ }
+ }
+ if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ snd_soc_update_bits(codec,
+ TAIKO_A_CDC_CLK_TX_I2S_CTL,
+ 0x20, 0x20);
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ snd_soc_update_bits(codec,
+ TAIKO_A_CDC_CLK_TX_I2S_CTL,
+ 0x20, 0x00);
+ break;
+ default:
+ pr_err("invalid format\n");
+ break;
+ }
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_TX_I2S_CTL,
+ 0x07, tx_fs_rate);
+ } else {
+ taiko->dai[dai->id - 1].rate = params_rate(params);
+ }
+ }
+ /**
+ * TODO: Need to handle case where same RX chain takes 2 or more inputs
+ * with varying sample rates
+ */
+
+ /**
+ * If current dai is a rx dai, set sample rate to
+ * all the rx paths that are currently not active
+ */
+ if (dai->id == AIF1_PB || dai->id == AIF2_PB || dai->id == AIF3_PB) {
+
+ rx_state = snd_soc_read(codec,
+ TAIKO_A_CDC_CLK_RX_B1_CTL);
+
+ for (path = 1, shift = 0;
+ path <= NUM_INTERPOLATORS; path++, shift++) {
+
+ if (!(rx_state & (1 << shift))) {
+ rx_fs_reg = TAIKO_A_CDC_RX1_B5_CTL
+ + (BITS_PER_REG*(path-1));
+ snd_soc_update_bits(codec, rx_fs_reg,
+ 0xE0, rx_fs_rate);
+ if (comp_rx_path[shift] < COMPANDER_MAX)
+ taiko->comp_fs[comp_rx_path[shift]]
+ = compander_fs;
+ }
+ }
+ if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ snd_soc_update_bits(codec,
+ TAIKO_A_CDC_CLK_RX_I2S_CTL,
+ 0x20, 0x20);
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ snd_soc_update_bits(codec,
+ TAIKO_A_CDC_CLK_RX_I2S_CTL,
+ 0x20, 0x00);
+ break;
+ default:
+ pr_err("invalid format\n");
+ break;
+ }
+ snd_soc_update_bits(codec, TAIKO_A_CDC_CLK_RX_I2S_CTL,
+ 0x03, (rx_fs_rate >> 0x05));
+ } else {
+ taiko->dai[dai->id - 1].rate = params_rate(params);
+ }
+ }
+
+ return 0;
+}
+
+static struct snd_soc_dai_ops taiko_dai_ops = {
+ .startup = taiko_startup,
+ .shutdown = taiko_shutdown,
+ .hw_params = taiko_hw_params,
+ .set_sysclk = taiko_set_dai_sysclk,
+ .set_fmt = taiko_set_dai_fmt,
+ .set_channel_map = taiko_set_channel_map,
+ .get_channel_map = taiko_get_channel_map,
+};
+
+static struct snd_soc_dai_driver taiko_dai[] = {
+ {
+ .name = "taiko_rx1",
+ .id = AIF1_PB,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .rates = WCD9320_RATES,
+ .formats = TAIKO_FORMATS,
+ .rate_max = 192000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &taiko_dai_ops,
+ },
+ {
+ .name = "taiko_tx1",
+ .id = AIF1_CAP,
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .rates = WCD9320_RATES,
+ .formats = TAIKO_FORMATS,
+ .rate_max = 192000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 4,
+ },
+ .ops = &taiko_dai_ops,
+ },
+ {
+ .name = "taiko_rx2",
+ .id = AIF2_PB,
+ .playback = {
+ .stream_name = "AIF2 Playback",
+ .rates = WCD9320_RATES,
+ .formats = TAIKO_FORMATS,
+ .rate_min = 8000,
+ .rate_max = 192000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &taiko_dai_ops,
+ },
+ {
+ .name = "taiko_tx2",
+ .id = AIF2_CAP,
+ .capture = {
+ .stream_name = "AIF2 Capture",
+ .rates = WCD9320_RATES,
+ .formats = TAIKO_FORMATS,
+ .rate_max = 192000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 4,
+ },
+ .ops = &taiko_dai_ops,
+ },
+ {
+ .name = "taiko_tx3",
+ .id = AIF3_CAP,
+ .capture = {
+ .stream_name = "AIF3 Capture",
+ .rates = WCD9320_RATES,
+ .formats = TAIKO_FORMATS,
+ .rate_max = 48000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &taiko_dai_ops,
+ },
+ {
+ .name = "taiko_rx3",
+ .id = AIF3_PB,
+ .playback = {
+ .stream_name = "AIF3 Playback",
+ .rates = WCD9320_RATES,
+ .formats = TAIKO_FORMATS,
+ .rate_min = 8000,
+ .rate_max = 192000,
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &taiko_dai_ops,
+ },
+};
+
+static struct snd_soc_dai_driver taiko_i2s_dai[] = {
+ {
+ .name = "taiko_i2s_rx1",
+ .id = 1,
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .rates = WCD9320_RATES,
+ .formats = TAIKO_FORMATS,
+ .rate_max = 192000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 4,
+ },
+ .ops = &taiko_dai_ops,
+ },
+ {
+ .name = "taiko_i2s_tx1",
+ .id = 2,
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .rates = WCD9320_RATES,
+ .formats = TAIKO_FORMATS,
+ .rate_max = 192000,
+ .rate_min = 8000,
+ .channels_min = 1,
+ .channels_max = 4,
+ },
+ .ops = &taiko_dai_ops,
+ },
+};
+
+static int taiko_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct wcd9xxx *taiko;
+ struct snd_soc_codec *codec = w->codec;
+ struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
+ u32 j = 0;
+ u32 ret = 0;
+ codec->control_data = dev_get_drvdata(codec->dev->parent);
+ taiko = codec->control_data;
+ /* Execute the callback only if interface type is slimbus */
+ if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+ return 0;
+
+ pr_debug("%s: %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ for (j = 0; j < ARRAY_SIZE(taiko_dai); j++) {
+ if ((taiko_dai[j].id == AIF1_CAP) ||
+ (taiko_dai[j].id == AIF2_CAP) ||
+ (taiko_dai[j].id == AIF3_CAP))
+ continue;
+ if (!strncmp(w->sname,
+ taiko_dai[j].playback.stream_name, 13)) {
+ ++taiko_p->dai[j].ch_act;
+ break;
+ }
+ }
+ if (taiko_p->dai[j].ch_act == taiko_p->dai[j].ch_tot)
+ ret = wcd9xxx_cfg_slim_sch_rx(taiko,
+ taiko_p->dai[j].ch_num,
+ taiko_p->dai[j].ch_tot,
+ taiko_p->dai[j].rate);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ for (j = 0; j < ARRAY_SIZE(taiko_dai); j++) {
+ if ((taiko_dai[j].id == AIF1_CAP) ||
+ (taiko_dai[j].id == AIF2_CAP) ||
+ (taiko_dai[j].id == AIF3_CAP))
+ continue;
+ if (!strncmp(w->sname,
+ taiko_dai[j].playback.stream_name, 13)) {
+ --taiko_p->dai[j].ch_act;
+ break;
+ }
+ }
+ if (!taiko_p->dai[j].ch_act) {
+ ret = wcd9xxx_close_slim_sch_rx(taiko,
+ taiko_p->dai[j].ch_num,
+ taiko_p->dai[j].ch_tot);
+ usleep_range(15000, 15000);
+ taiko_p->dai[j].rate = 0;
+ memset(taiko_p->dai[j].ch_num, 0, (sizeof(u32)*
+ taiko_p->dai[j].ch_tot));
+ taiko_p->dai[j].ch_tot = 0;
+ }
+ }
+ return ret;
+}
+
+static int taiko_codec_enable_slimtx(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct wcd9xxx *taiko;
+ struct snd_soc_codec *codec = w->codec;
+ struct taiko_priv *taiko_p = snd_soc_codec_get_drvdata(codec);
+ /* index to the DAI ID, for now hardcoding */
+ u32 j = 0;
+ u32 ret = 0;
+
+ codec->control_data = dev_get_drvdata(codec->dev->parent);
+ taiko = codec->control_data;
+
+ /* Execute the callback only if interface type is slimbus */
+ if (taiko_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+ return 0;
+
+ pr_debug("%s(): %s %d\n", __func__, w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ for (j = 0; j < ARRAY_SIZE(taiko_dai); j++) {
+ if (taiko_dai[j].id == AIF1_PB ||
+ taiko_dai[j].id == AIF2_PB ||
+ taiko_dai[j].id == AIF3_PB)
+ continue;
+ if (!strncmp(w->sname,
+ taiko_dai[j].capture.stream_name, 13)) {
+ ++taiko_p->dai[j].ch_act;
+ break;
+ }
+ }
+ if (taiko_p->dai[j].ch_act == taiko_p->dai[j].ch_tot)
+ ret = wcd9xxx_cfg_slim_sch_tx(taiko,
+ taiko_p->dai[j].ch_num,
+ taiko_p->dai[j].ch_tot,
+ taiko_p->dai[j].rate);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ for (j = 0; j < ARRAY_SIZE(taiko_dai); j++) {
+ if (taiko_dai[j].id == AIF1_PB ||
+ taiko_dai[j].id == AIF2_PB ||
+ taiko_dai[j].id == AIF3_PB)
+ continue;
+ if (!strncmp(w->sname,
+ taiko_dai[j].capture.stream_name, 13)) {
+ --taiko_p->dai[j].ch_act;
+ break;
+ }
+ }
+ if (!taiko_p->dai[j].ch_act) {
+ ret = wcd9xxx_close_slim_sch_tx(taiko,
+ taiko_p->dai[j].ch_num,
+ taiko_p->dai[j].ch_tot);
+ taiko_p->dai[j].rate = 0;
+ memset(taiko_p->dai[j].ch_num, 0, (sizeof(u32)*
+ taiko_p->dai[j].ch_tot));
+ taiko_p->dai[j].ch_tot = 0;
+ }
+ }
+ return ret;
+}
+
+/* Todo: Have seperate dapm widgets for I2S and Slimbus.
+ * Might Need to have callbacks registered only for slimbus
+ */
+static const struct snd_soc_dapm_widget taiko_dapm_widgets[] = {
+ /*RX stuff */
+ SND_SOC_DAPM_OUTPUT("EAR"),
+
+ SND_SOC_DAPM_PGA("EAR PA", TAIKO_A_RX_EAR_EN, 4, 0, NULL, 0),
+
+ SND_SOC_DAPM_MIXER("DAC1", TAIKO_A_RX_EAR_EN, 6, 0, dac1_switch,
+ ARRAY_SIZE(dac1_switch)),
+
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX1", "AIF1 Playback", 0, SND_SOC_NOPM, 0,
+ 0, taiko_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX2", "AIF1 Playback", 0, SND_SOC_NOPM, 0,
+ 0, taiko_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX3", "AIF1 Playback", 0, SND_SOC_NOPM, 0,
+ 0, taiko_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX4", "AIF3 Playback", 0, SND_SOC_NOPM, 0,
+ 0, taiko_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX5", "AIF3 Playback", 0, SND_SOC_NOPM, 0,
+ 0, taiko_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX6", "AIF2 Playback", 0, SND_SOC_NOPM, 0,
+ 0, taiko_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_AIF_IN_E("SLIM RX7", "AIF2 Playback", 0, SND_SOC_NOPM, 0,
+ 0, taiko_codec_enable_slimrx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* Headphone */
+ SND_SOC_DAPM_OUTPUT("HEADPHONE"),
+ SND_SOC_DAPM_PGA_E("HPHL", TAIKO_A_RX_HPH_CNP_EN, 5, 0, NULL, 0,
+ taiko_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MIXER("HPHL DAC", TAIKO_A_RX_HPH_L_DAC_CTL, 7, 0,
+ hphl_switch, ARRAY_SIZE(hphl_switch)),
+
+ SND_SOC_DAPM_PGA_E("HPHR", TAIKO_A_RX_HPH_CNP_EN, 4, 0, NULL, 0,
+ taiko_hph_pa_event, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_DAC_E("HPHR DAC", NULL, TAIKO_A_RX_HPH_R_DAC_CTL, 7, 0,
+ taiko_hphr_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* Speaker */
+ SND_SOC_DAPM_OUTPUT("LINEOUT1"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT2"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT3"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT4"),
+
+ SND_SOC_DAPM_PGA_E("LINEOUT1 PA", TAIKO_A_RX_LINE_CNP_EN, 0, 0, NULL,
+ 0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("LINEOUT2 PA", TAIKO_A_RX_LINE_CNP_EN, 1, 0, NULL,
+ 0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("LINEOUT3 PA", TAIKO_A_RX_LINE_CNP_EN, 2, 0, NULL,
+ 0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("LINEOUT4 PA", TAIKO_A_RX_LINE_CNP_EN, 3, 0, NULL,
+ 0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TAIKO_A_RX_LINE_1_DAC_CTL, 7, 0
+ , taiko_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_DAC_E("LINEOUT2 DAC", NULL, TAIKO_A_RX_LINE_2_DAC_CTL, 7, 0
+ , taiko_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_DAC_E("LINEOUT3 DAC", NULL, TAIKO_A_RX_LINE_3_DAC_CTL, 7, 0
+ , taiko_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SWITCH("LINEOUT3 DAC GROUND", SND_SOC_NOPM, 0, 0,
+ &lineout3_ground_switch),
+ SND_SOC_DAPM_DAC_E("LINEOUT4 DAC", NULL, TAIKO_A_RX_LINE_4_DAC_CTL, 7, 0
+ , taiko_lineout_dac_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SWITCH("LINEOUT4 DAC GROUND", SND_SOC_NOPM, 0, 0,
+ &lineout4_ground_switch),
+
+ SND_SOC_DAPM_MIXER_E("RX1 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 0, 0, NULL,
+ 0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_MIXER_E("RX2 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 1, 0, NULL,
+ 0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_MIXER_E("RX7 MIX2", TAIKO_A_CDC_CLK_RX_B1_CTL, 2, 0, NULL,
+ 0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_MIXER_E("RX4 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 3, 0, NULL,
+ 0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_MIXER_E("RX5 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 4, 0, NULL,
+ 0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_MIXER_E("RX6 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 5, 0, NULL,
+ 0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
+ SND_SOC_DAPM_MIXER_E("RX7 MIX1", TAIKO_A_CDC_CLK_RX_B1_CTL, 6, 0, NULL,
+ 0, taiko_codec_reset_interpolator, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX3 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX_E("RX4 DSM MUX", TAIKO_A_CDC_CLK_RX_B1_CTL, 3, 0,
+ &rx4_dsm_mux, taiko_codec_reset_interpolator,
+ SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MUX_E("RX6 DSM MUX", TAIKO_A_CDC_CLK_RX_B1_CTL, 5, 0,
+ &rx6_dsm_mux, taiko_codec_reset_interpolator,
+ SND_SOC_DAPM_PRE_PMU),
+
+ SND_SOC_DAPM_MIXER("RX1 CHAIN", TAIKO_A_CDC_RX1_B6_CTL, 5, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("RX2 CHAIN", TAIKO_A_CDC_RX2_B6_CTL, 5, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX1 MIX1 INP3", SND_SOC_NOPM, 0, 0,
+ &rx_mix1_inp3_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx2_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX3 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx3_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX4 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx4_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX4 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx4_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX5 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx5_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX5 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx5_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX6 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx6_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX6 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx6_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX7 MIX1 INP1", SND_SOC_NOPM, 0, 0,
+ &rx7_mix1_inp1_mux),
+ SND_SOC_DAPM_MUX("RX7 MIX1 INP2", SND_SOC_NOPM, 0, 0,
+ &rx7_mix1_inp2_mux),
+ SND_SOC_DAPM_MUX("RX1 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+ &rx1_mix2_inp1_mux),
+ SND_SOC_DAPM_MUX("RX1 MIX2 INP2", SND_SOC_NOPM, 0, 0,
+ &rx1_mix2_inp2_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+ &rx2_mix2_inp1_mux),
+ SND_SOC_DAPM_MUX("RX2 MIX2 INP2", SND_SOC_NOPM, 0, 0,
+ &rx2_mix2_inp2_mux),
+ SND_SOC_DAPM_MUX("RX7 MIX2 INP1", SND_SOC_NOPM, 0, 0,
+ &rx7_mix2_inp1_mux),
+ SND_SOC_DAPM_MUX("RX7 MIX2 INP2", SND_SOC_NOPM, 0, 0,
+ &rx7_mix2_inp2_mux),
+
+ SND_SOC_DAPM_SUPPLY("CP", TAIKO_A_NCP_EN, 0, 0,
+ taiko_codec_enable_charge_pump, SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD),
+
+ SND_SOC_DAPM_SUPPLY("RX_BIAS", SND_SOC_NOPM, 0, 0,
+ taiko_codec_enable_rx_bias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ /* TX */
+
+ SND_SOC_DAPM_SUPPLY("CDC_CONN", TAIKO_A_CDC_CLK_OTHR_CTL, 2, 0, NULL,
+ 0),
+
+ SND_SOC_DAPM_SUPPLY("LDO_H", TAIKO_A_LDO_H_MODE_1, 7, 0,
+ taiko_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_SUPPLY("COMP1_CLK", SND_SOC_NOPM, 0, 0,
+ taiko_config_compander, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("COMP2_CLK", SND_SOC_NOPM, 1, 0,
+ taiko_config_compander, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_POST_PMD),
+
+
+ SND_SOC_DAPM_INPUT("AMIC1"),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 External", TAIKO_A_MICB_1_CTL, 7, 0,
+ taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal1", TAIKO_A_MICB_1_CTL, 7, 0,
+ taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS1 Internal2", TAIKO_A_MICB_1_CTL, 7, 0,
+ taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("ADC1", NULL, TAIKO_A_TX_1_2_EN, 7, 0,
+ taiko_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_INPUT("AMIC3"),
+ SND_SOC_DAPM_ADC_E("ADC3", NULL, TAIKO_A_TX_3_4_EN, 7, 0,
+ taiko_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_INPUT("AMIC4"),
+ SND_SOC_DAPM_ADC_E("ADC4", NULL, TAIKO_A_TX_3_4_EN, 3, 0,
+ taiko_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_INPUT("AMIC5"),
+ SND_SOC_DAPM_ADC_E("ADC5", NULL, TAIKO_A_TX_5_6_EN, 7, 0,
+ taiko_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_INPUT("AMIC6"),
+ SND_SOC_DAPM_ADC_E("ADC6", NULL, TAIKO_A_TX_5_6_EN, 3, 0,
+ taiko_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
+
+ SND_SOC_DAPM_MUX_E("DEC1 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
+ &dec1_mux, taiko_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC2 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
+ &dec2_mux, taiko_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC3 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
+ &dec3_mux, taiko_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC4 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
+ &dec4_mux, taiko_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC5 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 4, 0,
+ &dec5_mux, taiko_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC6 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 5, 0,
+ &dec6_mux, taiko_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC7 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 6, 0,
+ &dec7_mux, taiko_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC8 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B1_CTL, 7, 0,
+ &dec8_mux, taiko_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC9 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0, 0,
+ &dec9_mux, taiko_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX_E("DEC10 MUX", TAIKO_A_CDC_CLK_TX_CLK_EN_B2_CTL, 1, 0,
+ &dec10_mux, taiko_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
+ SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
+
+ SND_SOC_DAPM_MIXER_E("ANC", SND_SOC_NOPM, 0, 0, NULL, 0,
+ taiko_codec_enable_anc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("ANC1 FB MUX", SND_SOC_NOPM, 0, 0, &anc1_fb_mux),
+
+ SND_SOC_DAPM_INPUT("AMIC2"),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 External", TAIKO_A_MICB_2_CTL, 7, 0,
+ taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal1", TAIKO_A_MICB_2_CTL, 7, 0,
+ taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal2", TAIKO_A_MICB_2_CTL, 7, 0,
+ taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS2 Internal3", TAIKO_A_MICB_2_CTL, 7, 0,
+ taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 External", TAIKO_A_MICB_3_CTL, 7, 0,
+ taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal1", TAIKO_A_MICB_3_CTL, 7, 0,
+ taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS3 Internal2", TAIKO_A_MICB_3_CTL, 7, 0,
+ taiko_codec_enable_micbias, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_MICBIAS_E("MIC BIAS4 External", TAIKO_A_MICB_4_CTL, 7,
+ 0, taiko_codec_enable_micbias,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("ADC2", NULL, TAIKO_A_TX_1_2_EN, 3, 0,
+ taiko_codec_enable_adc, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SLIM TX1 MUX", SND_SOC_NOPM, 0, 0, &sb_tx1_mux),
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX1", "AIF2 Capture", 0, SND_SOC_NOPM, 0,
+ 0, taiko_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SLIM TX2 MUX", SND_SOC_NOPM, 0, 0, &sb_tx2_mux),
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX2", "AIF2 Capture", 0, SND_SOC_NOPM, 0,
+ 0, taiko_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SLIM TX3 MUX", SND_SOC_NOPM, 0, 0, &sb_tx3_mux),
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX3", "AIF3 Capture", 0, SND_SOC_NOPM, 0,
+ 0, taiko_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SLIM TX4 MUX", SND_SOC_NOPM, 0, 0, &sb_tx4_mux),
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX4", "AIF2 Capture", 0, SND_SOC_NOPM, 0,
+ 0, taiko_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SLIM TX5 MUX", SND_SOC_NOPM, 0, 0, &sb_tx5_mux),
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX5", "AIF3 Capture", 0, SND_SOC_NOPM, 0,
+ 0, taiko_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SLIM TX6 MUX", SND_SOC_NOPM, 0, 0, &sb_tx6_mux),
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX6", "AIF2 Capture", 0, SND_SOC_NOPM, 0,
+ 0, taiko_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SLIM TX7 MUX", SND_SOC_NOPM, 0, 0, &sb_tx7_mux),
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX7", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+ 0, taiko_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SLIM TX8 MUX", SND_SOC_NOPM, 0, 0, &sb_tx8_mux),
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX8", "AIF1 Capture", 0, SND_SOC_NOPM, 0,
+ 0, taiko_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SLIM TX9 MUX", SND_SOC_NOPM, 0, 0, &sb_tx9_mux),
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX9", "AIF1 Capture", NULL, SND_SOC_NOPM,
+ 0, 0, taiko_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MUX("SLIM TX10 MUX", SND_SOC_NOPM, 0, 0, &sb_tx10_mux),
+ SND_SOC_DAPM_AIF_OUT_E("SLIM TX10", "AIF1 Capture", NULL, SND_SOC_NOPM,
+ 0, 0, taiko_codec_enable_slimtx,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* Digital Mic Inputs */
+ SND_SOC_DAPM_ADC_E("DMIC1", NULL, SND_SOC_NOPM, 0, 0,
+ taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("DMIC2", NULL, SND_SOC_NOPM, 0, 0,
+ taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("DMIC3", NULL, SND_SOC_NOPM, 0, 0,
+ taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("DMIC4", NULL, SND_SOC_NOPM, 0, 0,
+ taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("DMIC5", NULL, SND_SOC_NOPM, 0, 0,
+ taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_ADC_E("DMIC6", NULL, SND_SOC_NOPM, 0, 0,
+ taiko_codec_enable_dmic, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ /* Sidetone */
+ SND_SOC_DAPM_MUX("IIR1 INP1 MUX", SND_SOC_NOPM, 0, 0, &iir1_inp1_mux),
+ SND_SOC_DAPM_PGA("IIR1", TAIKO_A_CDC_CLK_SD_CTL, 0, 0, NULL, 0),
+
+ /* AUX PGA */
+ SND_SOC_DAPM_ADC_E("AUX_PGA_Left", NULL, TAIKO_A_RX_AUX_SW_CTL, 7, 0,
+ taiko_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_ADC_E("AUX_PGA_Right", NULL, TAIKO_A_RX_AUX_SW_CTL, 6, 0,
+ taiko_codec_enable_aux_pga, SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_POST_PMD),
+
+ /* Lineout, ear and HPH PA Mixers */
+
+ SND_SOC_DAPM_MIXER("EAR_PA_MIXER", SND_SOC_NOPM, 0, 0,
+ ear_pa_mix, ARRAY_SIZE(ear_pa_mix)),
+
+ SND_SOC_DAPM_MIXER("HPHL_PA_MIXER", SND_SOC_NOPM, 0, 0,
+ hphl_pa_mix, ARRAY_SIZE(hphl_pa_mix)),
+
+ SND_SOC_DAPM_MIXER("HPHR_PA_MIXER", SND_SOC_NOPM, 0, 0,
+ hphr_pa_mix, ARRAY_SIZE(hphr_pa_mix)),
+
+ SND_SOC_DAPM_MIXER("LINEOUT1_PA_MIXER", SND_SOC_NOPM, 0, 0,
+ lineout1_pa_mix, ARRAY_SIZE(lineout1_pa_mix)),
+
+ SND_SOC_DAPM_MIXER("LINEOUT2_PA_MIXER", SND_SOC_NOPM, 0, 0,
+ lineout2_pa_mix, ARRAY_SIZE(lineout2_pa_mix)),
+
+ SND_SOC_DAPM_MIXER("LINEOUT3_PA_MIXER", SND_SOC_NOPM, 0, 0,
+ lineout3_pa_mix, ARRAY_SIZE(lineout3_pa_mix)),
+
+ SND_SOC_DAPM_MIXER("LINEOUT4_PA_MIXER", SND_SOC_NOPM, 0, 0,
+ lineout4_pa_mix, ARRAY_SIZE(lineout4_pa_mix)),
+
+};
+
+static short taiko_codec_read_sta_result(struct snd_soc_codec *codec)
+{
+ u8 bias_msb, bias_lsb;
+ short bias_value;
+
+ bias_msb = snd_soc_read(codec, TAIKO_A_CDC_MBHC_B3_STATUS);
+ bias_lsb = snd_soc_read(codec, TAIKO_A_CDC_MBHC_B2_STATUS);
+ bias_value = (bias_msb << 8) | bias_lsb;
+ return bias_value;
+}
+
+static short taiko_codec_read_dce_result(struct snd_soc_codec *codec)
+{
+ u8 bias_msb, bias_lsb;
+ short bias_value;
+
+ bias_msb = snd_soc_read(codec, TAIKO_A_CDC_MBHC_B5_STATUS);
+ bias_lsb = snd_soc_read(codec, TAIKO_A_CDC_MBHC_B4_STATUS);
+ bias_value = (bias_msb << 8) | bias_lsb;
+ return bias_value;
+}
+
+static void taiko_turn_onoff_rel_detection(struct snd_soc_codec *codec, bool on)
+{
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x02, on << 1);
+}
+
+static short __taiko_codec_sta_dce(struct snd_soc_codec *codec, int dce,
+ bool override_bypass, bool noreldetection)
+{
+ short bias_value;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ wcd9xxx_disable_irq(codec->control_data, TAIKO_IRQ_MBHC_POTENTIAL);
+ if (noreldetection)
+ taiko_turn_onoff_rel_detection(codec, false);
+
+ /* Turn on the override */
+ if (!override_bypass)
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x4, 0x4);
+ if (dce) {
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x4);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
+ usleep_range(taiko->mbhc_data.t_sta_dce,
+ taiko->mbhc_data.t_sta_dce);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x4);
+ usleep_range(taiko->mbhc_data.t_dce,
+ taiko->mbhc_data.t_dce);
+ bias_value = taiko_codec_read_dce_result(codec);
+ } else {
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x2);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
+ usleep_range(taiko->mbhc_data.t_sta_dce,
+ taiko->mbhc_data.t_sta_dce);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x2);
+ usleep_range(taiko->mbhc_data.t_sta,
+ taiko->mbhc_data.t_sta);
+ bias_value = taiko_codec_read_sta_result(codec);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x0);
+ }
+ /* Turn off the override after measuring mic voltage */
+ if (!override_bypass)
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
+
+ if (noreldetection)
+ taiko_turn_onoff_rel_detection(codec, true);
+ wcd9xxx_enable_irq(codec->control_data, TAIKO_IRQ_MBHC_POTENTIAL);
+
+ return bias_value;
+}
+
+static short taiko_codec_sta_dce(struct snd_soc_codec *codec, int dce,
+ bool norel)
+{
+ return __taiko_codec_sta_dce(codec, dce, false, norel);
+}
+
+/* called only from interrupt which is under codec_resource_lock acquisition */
+static short taiko_codec_setup_hs_polling(struct snd_soc_codec *codec)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ short bias_value;
+ u8 cfilt_mode;
+
+ pr_debug("%s: enter, mclk_enabled %d\n", __func__, taiko->mclk_enabled);
+ if (!taiko->mbhc_cfg.calibration) {
+ pr_err("Error, no taiko calibration\n");
+ return -ENODEV;
+ }
+
+ if (!taiko->mclk_enabled) {
+ taiko_codec_disable_clock_block(codec);
+ taiko_codec_enable_bandgap(codec, TAIKO_BANDGAP_MBHC_MODE);
+ taiko_enable_rx_bias(codec, 1);
+ taiko_codec_enable_clock_block(codec, 1);
+ }
+
+ snd_soc_update_bits(codec, TAIKO_A_CLK_BUFF_EN1, 0x05, 0x01);
+
+ /* Make sure CFILT is in fast mode, save current mode */
+ cfilt_mode = snd_soc_read(codec, taiko->mbhc_bias_regs.cfilt_ctl);
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.cfilt_ctl, 0x70, 0x00);
+
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.ctl_reg, 0x1F, 0x16);
+
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
+ snd_soc_write(codec, TAIKO_A_MBHC_SCALING_MUX_1, 0x84);
+
+ snd_soc_update_bits(codec, TAIKO_A_TX_7_MBHC_EN, 0x80, 0x80);
+ snd_soc_update_bits(codec, TAIKO_A_TX_7_MBHC_EN, 0x1F, 0x1C);
+ snd_soc_update_bits(codec, TAIKO_A_TX_7_MBHC_TEST_CTL, 0x40, 0x40);
+
+ snd_soc_update_bits(codec, TAIKO_A_TX_7_MBHC_EN, 0x80, 0x00);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x00);
+
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x2, 0x2);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
+
+ taiko_codec_calibrate_hs_polling(codec);
+
+ /* don't flip override */
+ bias_value = __taiko_codec_sta_dce(codec, 1, true, true);
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.cfilt_ctl, 0x40,
+ cfilt_mode);
+ snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x13, 0x00);
+
+ return bias_value;
+}
+
+static int taiko_cancel_btn_work(struct taiko_priv *taiko)
+{
+ int r = 0;
+ struct wcd9xxx *core = dev_get_drvdata(taiko->codec->dev->parent);
+
+ if (cancel_delayed_work_sync(&taiko->mbhc_btn_dwork)) {
+ /* if scheduled mbhc_btn_dwork is canceled from here,
+ * we have to unlock from here instead btn_work */
+ wcd9xxx_unlock_sleep(core);
+ r = 1;
+ }
+ return r;
+}
+
+/* called under codec_resource_lock acquisition */
+void taiko_set_and_turnoff_hph_padac(struct snd_soc_codec *codec)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ u8 wg_time;
+
+ wg_time = snd_soc_read(codec, TAIKO_A_RX_HPH_CNP_WG_TIME) ;
+ wg_time += 1;
+
+ /* If headphone PA is on, check if userspace receives
+ * removal event to sync-up PA's state */
+ if (taiko_is_hph_pa_on(codec)) {
+ pr_debug("%s PA is on, setting PA_OFF_ACK\n", __func__);
+ set_bit(TAIKO_HPHL_PA_OFF_ACK, &taiko->hph_pa_dac_state);
+ set_bit(TAIKO_HPHR_PA_OFF_ACK, &taiko->hph_pa_dac_state);
+ } else {
+ pr_debug("%s PA is off\n", __func__);
+ }
+
+ if (taiko_is_hph_dac_on(codec, 1))
+ set_bit(TAIKO_HPHL_DAC_OFF_ACK, &taiko->hph_pa_dac_state);
+ if (taiko_is_hph_dac_on(codec, 0))
+ set_bit(TAIKO_HPHR_DAC_OFF_ACK, &taiko->hph_pa_dac_state);
+
+ snd_soc_update_bits(codec, TAIKO_A_RX_HPH_CNP_EN, 0x30, 0x00);
+ snd_soc_update_bits(codec, TAIKO_A_RX_HPH_L_DAC_CTL,
+ 0xC0, 0x00);
+ snd_soc_update_bits(codec, TAIKO_A_RX_HPH_R_DAC_CTL,
+ 0xC0, 0x00);
+ usleep_range(wg_time * 1000, wg_time * 1000);
+}
+
+static void taiko_clr_and_turnon_hph_padac(struct taiko_priv *taiko)
+{
+ bool pa_turned_on = false;
+ struct snd_soc_codec *codec = taiko->codec;
+ u8 wg_time;
+
+ wg_time = snd_soc_read(codec, TAIKO_A_RX_HPH_CNP_WG_TIME) ;
+ wg_time += 1;
+
+ if (test_and_clear_bit(TAIKO_HPHR_DAC_OFF_ACK,
+ &taiko->hph_pa_dac_state)) {
+ pr_debug("%s: HPHR clear flag and enable DAC\n", __func__);
+ snd_soc_update_bits(taiko->codec, TAIKO_A_RX_HPH_R_DAC_CTL,
+ 0xC0, 0xC0);
+ }
+ if (test_and_clear_bit(TAIKO_HPHL_DAC_OFF_ACK,
+ &taiko->hph_pa_dac_state)) {
+ pr_debug("%s: HPHL clear flag and enable DAC\n", __func__);
+ snd_soc_update_bits(taiko->codec, TAIKO_A_RX_HPH_L_DAC_CTL,
+ 0xC0, 0xC0);
+ }
+
+ if (test_and_clear_bit(TAIKO_HPHR_PA_OFF_ACK,
+ &taiko->hph_pa_dac_state)) {
+ pr_debug("%s: HPHR clear flag and enable PA\n", __func__);
+ snd_soc_update_bits(taiko->codec, TAIKO_A_RX_HPH_CNP_EN, 0x10,
+ 1 << 4);
+ pa_turned_on = true;
+ }
+ if (test_and_clear_bit(TAIKO_HPHL_PA_OFF_ACK,
+ &taiko->hph_pa_dac_state)) {
+ pr_debug("%s: HPHL clear flag and enable PA\n", __func__);
+ snd_soc_update_bits(taiko->codec, TAIKO_A_RX_HPH_CNP_EN, 0x20,
+ 1 << 5);
+ pa_turned_on = true;
+ }
+
+ if (pa_turned_on) {
+ pr_debug("%s: PA was turned off by MBHC and not by DAPM\n",
+ __func__);
+ usleep_range(wg_time * 1000, wg_time * 1000);
+ }
+}
+
+/* called under codec_resource_lock acquisition */
+static void taiko_codec_report_plug(struct snd_soc_codec *codec, int insertion,
+ enum snd_jack_types jack_type)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ if (!insertion) {
+ /* Report removal */
+ taiko->hph_status &= ~jack_type;
+ if (taiko->mbhc_cfg.headset_jack) {
+ /* cancel possibly scheduled btn work and
+ * report release if we reported button press */
+ if (taiko_cancel_btn_work(taiko)) {
+ pr_debug("%s: button press is canceled\n",
+ __func__);
+ } else if (taiko->buttons_pressed) {
+ pr_debug("%s: release of button press%d\n",
+ __func__, jack_type);
+ taiko_snd_soc_jack_report(taiko,
+ taiko->mbhc_cfg.button_jack, 0,
+ taiko->buttons_pressed);
+ taiko->buttons_pressed &=
+ ~TAIKO_JACK_BUTTON_MASK;
+ }
+ pr_debug("%s: Reporting removal %d(%x)\n", __func__,
+ jack_type, taiko->hph_status);
+ taiko_snd_soc_jack_report(taiko,
+ taiko->mbhc_cfg.headset_jack,
+ taiko->hph_status,
+ TAIKO_JACK_MASK);
+ }
+ taiko_set_and_turnoff_hph_padac(codec);
+ hphocp_off_report(taiko, SND_JACK_OC_HPHR,
+ TAIKO_IRQ_HPH_PA_OCPR_FAULT);
+ hphocp_off_report(taiko, SND_JACK_OC_HPHL,
+ TAIKO_IRQ_HPH_PA_OCPL_FAULT);
+ taiko->current_plug = PLUG_TYPE_NONE;
+ taiko->mbhc_polling_active = false;
+ } else {
+ /* Report insertion */
+ taiko->hph_status |= jack_type;
+
+ if (jack_type == SND_JACK_HEADPHONE)
+ taiko->current_plug = PLUG_TYPE_HEADPHONE;
+ else if (jack_type == SND_JACK_UNSUPPORTED)
+ taiko->current_plug = PLUG_TYPE_GND_MIC_SWAP;
+ else if (jack_type == SND_JACK_HEADSET) {
+ taiko->mbhc_polling_active = true;
+ taiko->current_plug = PLUG_TYPE_HEADSET;
+ }
+ if (taiko->mbhc_cfg.headset_jack) {
+ pr_debug("%s: Reporting insertion %d(%x)\n", __func__,
+ jack_type, taiko->hph_status);
+ taiko_snd_soc_jack_report(taiko,
+ taiko->mbhc_cfg.headset_jack,
+ taiko->hph_status,
+ TAIKO_JACK_MASK);
+ }
+ taiko_clr_and_turnon_hph_padac(taiko);
+ }
+}
+
+static int taiko_codec_enable_hs_detect(struct snd_soc_codec *codec,
+ int insertion, int trigger,
+ bool padac_off)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ int central_bias_enabled = 0;
+ const struct taiko_mbhc_general_cfg *generic =
+ TAIKO_MBHC_CAL_GENERAL_PTR(taiko->mbhc_cfg.calibration);
+ const struct taiko_mbhc_plug_detect_cfg *plug_det =
+ TAIKO_MBHC_CAL_PLUG_DET_PTR(taiko->mbhc_cfg.calibration);
+
+ if (!taiko->mbhc_cfg.calibration) {
+ pr_err("Error, no taiko calibration\n");
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_INT_CTL, 0x1, 0);
+
+ /* Make sure mic bias and Mic line schmitt trigger
+ * are turned OFF
+ */
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.ctl_reg, 0x01, 0x01);
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg, 0x90, 0x00);
+
+ if (insertion) {
+ taiko_codec_switch_micbias(codec, 0);
+
+ /* DAPM can manipulate PA/DAC bits concurrently */
+ if (padac_off == true)
+ taiko_set_and_turnoff_hph_padac(codec);
+
+ if (trigger & MBHC_USE_HPHL_TRIGGER) {
+ /* Enable HPH Schmitt Trigger */
+ snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x11,
+ 0x11);
+ snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x0C,
+ plug_det->hph_current << 2);
+ snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x02,
+ 0x02);
+ }
+ if (trigger & MBHC_USE_MB_TRIGGER) {
+ /* enable the mic line schmitt trigger */
+ snd_soc_update_bits(codec,
+ taiko->mbhc_bias_regs.mbhc_reg,
+ 0x60, plug_det->mic_current << 5);
+ snd_soc_update_bits(codec,
+ taiko->mbhc_bias_regs.mbhc_reg,
+ 0x80, 0x80);
+ usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid);
+ snd_soc_update_bits(codec,
+ taiko->mbhc_bias_regs.ctl_reg, 0x01,
+ 0x00);
+ snd_soc_update_bits(codec,
+ taiko->mbhc_bias_regs.mbhc_reg,
+ 0x10, 0x10);
+ }
+
+ /* setup for insetion detection */
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_INT_CTL, 0x2, 0);
+ } else {
+ pr_debug("setup for removal detection\n");
+ /* Make sure the HPH schmitt trigger is OFF */
+ snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x12, 0x00);
+
+ /* enable the mic line schmitt trigger */
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.ctl_reg,
+ 0x01, 0x00);
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg, 0x60,
+ plug_det->mic_current << 5);
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg,
+ 0x80, 0x80);
+ usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid);
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg,
+ 0x10, 0x10);
+
+ /* Setup for low power removal detection */
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_INT_CTL, 0x2, 0x2);
+ }
+
+ if (snd_soc_read(codec, TAIKO_A_CDC_MBHC_B1_CTL) & 0x4) {
+ /* called called by interrupt */
+ if (!(taiko->clock_active)) {
+ taiko_codec_enable_config_mode(codec, 1);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL,
+ 0x06, 0);
+ usleep_range(generic->t_shutdown_plug_rem,
+ generic->t_shutdown_plug_rem);
+ taiko_codec_enable_config_mode(codec, 0);
+ } else
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL,
+ 0x06, 0);
+ }
+
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.int_rbias, 0x80, 0);
+
+ /* If central bandgap disabled */
+ if (!(snd_soc_read(codec, TAIKO_A_PIN_CTL_OE1) & 1)) {
+ snd_soc_update_bits(codec, TAIKO_A_PIN_CTL_OE1, 0x3, 0x3);
+ usleep_range(generic->t_bg_fast_settle,
+ generic->t_bg_fast_settle);
+ central_bias_enabled = 1;
+ }
+
+ /* If LDO_H disabled */
+ if (snd_soc_read(codec, TAIKO_A_PIN_CTL_OE0) & 0x80) {
+ snd_soc_update_bits(codec, TAIKO_A_PIN_CTL_OE0, 0x10, 0);
+ snd_soc_update_bits(codec, TAIKO_A_PIN_CTL_OE0, 0x80, 0x80);
+ usleep_range(generic->t_ldoh, generic->t_ldoh);
+ snd_soc_update_bits(codec, TAIKO_A_PIN_CTL_OE0, 0x80, 0);
+
+ if (central_bias_enabled)
+ snd_soc_update_bits(codec, TAIKO_A_PIN_CTL_OE1, 0x1, 0);
+ }
+
+ snd_soc_update_bits(codec, taiko->reg_addr.micb_4_mbhc, 0x3,
+ taiko->mbhc_cfg.micbias);
+
+ wcd9xxx_enable_irq(codec->control_data, TAIKO_IRQ_MBHC_INSERTION);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
+ return 0;
+}
+
+static u16 taiko_codec_v_sta_dce(struct snd_soc_codec *codec, bool dce,
+ s16 vin_mv)
+{
+ struct taiko_priv *taiko;
+ s16 diff, zero;
+ u32 mb_mv, in;
+ u16 value;
+
+ taiko = snd_soc_codec_get_drvdata(codec);
+ mb_mv = taiko->mbhc_data.micb_mv;
+
+ if (mb_mv == 0) {
+ pr_err("%s: Mic Bias voltage is set to zero\n", __func__);
+ return -EINVAL;
+ }
+
+ if (dce) {
+ diff = (taiko->mbhc_data.dce_mb) - (taiko->mbhc_data.dce_z);
+ zero = (taiko->mbhc_data.dce_z);
+ } else {
+ diff = (taiko->mbhc_data.sta_mb) - (taiko->mbhc_data.sta_z);
+ zero = (taiko->mbhc_data.sta_z);
+ }
+ in = (u32) diff * vin_mv;
+
+ value = (u16) (in / mb_mv) + zero;
+ return value;
+}
+
+static s32 taiko_codec_sta_dce_v(struct snd_soc_codec *codec, s8 dce,
+ u16 bias_value)
+{
+ struct taiko_priv *taiko;
+ s16 value, z, mb;
+ s32 mv;
+
+ taiko = snd_soc_codec_get_drvdata(codec);
+ value = bias_value;
+ if (dce) {
+ z = (taiko->mbhc_data.dce_z);
+ mb = (taiko->mbhc_data.dce_mb);
+ mv = (value - z) * (s32)taiko->mbhc_data.micb_mv / (mb - z);
+ } else {
+ z = (taiko->mbhc_data.sta_z);
+ mb = (taiko->mbhc_data.sta_mb);
+ mv = (value - z) * (s32)taiko->mbhc_data.micb_mv / (mb - z);
+ }
+
+ return mv;
+}
+
+static void btn_lpress_fn(struct work_struct *work)
+{
+ struct delayed_work *delayed_work;
+ struct taiko_priv *taiko;
+ short bias_value;
+ int dce_mv, sta_mv;
+ struct wcd9xxx *core;
+
+ pr_debug("%s:\n", __func__);
+
+ delayed_work = to_delayed_work(work);
+ taiko = container_of(delayed_work, struct taiko_priv, mbhc_btn_dwork);
+ core = dev_get_drvdata(taiko->codec->dev->parent);
+
+ if (taiko) {
+ if (taiko->mbhc_cfg.button_jack) {
+ bias_value = taiko_codec_read_sta_result(taiko->codec);
+ sta_mv = taiko_codec_sta_dce_v(taiko->codec, 0,
+ bias_value);
+ bias_value = taiko_codec_read_dce_result(taiko->codec);
+ dce_mv = taiko_codec_sta_dce_v(taiko->codec, 1,
+ bias_value);
+ pr_debug("%s: Reporting long button press event\n",
+ __func__);
+ pr_debug("%s: STA: %d, DCE: %d\n", __func__, sta_mv,
+ dce_mv);
+ taiko_snd_soc_jack_report(taiko,
+ taiko->mbhc_cfg.button_jack,
+ taiko->buttons_pressed,
+ taiko->buttons_pressed);
+ }
+ } else {
+ pr_err("%s: Bad taiko private data\n", __func__);
+ }
+
+ pr_debug("%s: leave\n", __func__);
+ wcd9xxx_unlock_sleep(core);
+}
+
+void taiko_mbhc_cal(struct snd_soc_codec *codec)
+{
+ struct taiko_priv *taiko;
+ struct taiko_mbhc_btn_detect_cfg *btn_det;
+ u8 cfilt_mode, bg_mode;
+ u8 ncic, nmeas, navg;
+ u32 mclk_rate;
+ u32 dce_wait, sta_wait;
+ u8 *n_cic;
+ void *calibration;
+
+ taiko = snd_soc_codec_get_drvdata(codec);
+ calibration = taiko->mbhc_cfg.calibration;
+
+ wcd9xxx_disable_irq(codec->control_data, TAIKO_IRQ_MBHC_POTENTIAL);
+ taiko_turn_onoff_rel_detection(codec, false);
+
+ /* First compute the DCE / STA wait times
+ * depending on tunable parameters.
+ * The value is computed in microseconds
+ */
+ btn_det = TAIKO_MBHC_CAL_BTN_DET_PTR(calibration);
+ n_cic = taiko_mbhc_cal_btn_det_mp(btn_det, TAIKO_BTN_DET_N_CIC);
+ ncic = n_cic[taiko_codec_mclk_index(taiko)];
+ nmeas = TAIKO_MBHC_CAL_BTN_DET_PTR(calibration)->n_meas;
+ navg = TAIKO_MBHC_CAL_GENERAL_PTR(calibration)->mbhc_navg;
+ mclk_rate = taiko->mbhc_cfg.mclk_rate;
+ dce_wait = (1000 * 512 * ncic * (nmeas + 1)) / (mclk_rate / 1000);
+ sta_wait = (1000 * 128 * (navg + 1)) / (mclk_rate / 1000);
+
+ taiko->mbhc_data.t_dce = dce_wait;
+ taiko->mbhc_data.t_sta = sta_wait;
+
+ /* LDOH and CFILT are already configured during pdata handling.
+ * Only need to make sure CFILT and bandgap are in Fast mode.
+ * Need to restore defaults once calculation is done.
+ */
+ cfilt_mode = snd_soc_read(codec, taiko->mbhc_bias_regs.cfilt_ctl);
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.cfilt_ctl, 0x40, 0x00);
+ bg_mode = snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x02,
+ 0x02);
+
+ /* Micbias, CFILT, LDOH, MBHC MUX mode settings
+ * to perform ADC calibration
+ */
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.ctl_reg, 0x60,
+ taiko->mbhc_cfg.micbias << 5);
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
+ snd_soc_update_bits(codec, TAIKO_A_LDO_H_MODE_1, 0x60, 0x60);
+ snd_soc_write(codec, TAIKO_A_TX_7_MBHC_TEST_CTL, 0x78);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x04, 0x04);
+
+ /* DCE measurement for 0 volts */
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x0A);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x04);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x02);
+ snd_soc_write(codec, TAIKO_A_MBHC_SCALING_MUX_1, 0x81);
+ usleep_range(100, 100);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x04);
+ usleep_range(taiko->mbhc_data.t_dce, taiko->mbhc_data.t_dce);
+ taiko->mbhc_data.dce_z = taiko_codec_read_dce_result(codec);
+
+ /* DCE measurment for MB voltage */
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x0A);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x02);
+ snd_soc_write(codec, TAIKO_A_MBHC_SCALING_MUX_1, 0x82);
+ usleep_range(100, 100);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x04);
+ usleep_range(taiko->mbhc_data.t_dce, taiko->mbhc_data.t_dce);
+ taiko->mbhc_data.dce_mb = taiko_codec_read_dce_result(codec);
+
+ /* Sta measuremnt for 0 volts */
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x0A);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x02);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x02);
+ snd_soc_write(codec, TAIKO_A_MBHC_SCALING_MUX_1, 0x81);
+ usleep_range(100, 100);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x02);
+ usleep_range(taiko->mbhc_data.t_sta, taiko->mbhc_data.t_sta);
+ taiko->mbhc_data.sta_z = taiko_codec_read_sta_result(codec);
+
+ /* STA Measurement for MB Voltage */
+ snd_soc_write(codec, TAIKO_A_MBHC_SCALING_MUX_1, 0x82);
+ usleep_range(100, 100);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_EN_CTL, 0x02);
+ usleep_range(taiko->mbhc_data.t_sta, taiko->mbhc_data.t_sta);
+ taiko->mbhc_data.sta_mb = taiko_codec_read_sta_result(codec);
+
+ /* Restore default settings. */
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.cfilt_ctl, 0x40,
+ cfilt_mode);
+ snd_soc_update_bits(codec, TAIKO_A_BIAS_CENTRAL_BG_CTL, 0x02, bg_mode);
+
+ snd_soc_write(codec, TAIKO_A_MBHC_SCALING_MUX_1, 0x84);
+ usleep_range(100, 100);
+
+ wcd9xxx_enable_irq(codec->control_data, TAIKO_IRQ_MBHC_POTENTIAL);
+ taiko_turn_onoff_rel_detection(codec, true);
+}
+
+void *taiko_mbhc_cal_btn_det_mp(const struct taiko_mbhc_btn_detect_cfg *btn_det,
+ const enum taiko_mbhc_btn_det_mem mem)
+{
+ void *ret = &btn_det->_v_btn_low;
+
+ switch (mem) {
+ case TAIKO_BTN_DET_GAIN:
+ ret += sizeof(btn_det->_n_cic);
+ case TAIKO_BTN_DET_N_CIC:
+ ret += sizeof(btn_det->_n_ready);
+ case TAIKO_BTN_DET_N_READY:
+ ret += sizeof(btn_det->_v_btn_high[0]) * btn_det->num_btn;
+ case TAIKO_BTN_DET_V_BTN_HIGH:
+ ret += sizeof(btn_det->_v_btn_low[0]) * btn_det->num_btn;
+ case TAIKO_BTN_DET_V_BTN_LOW:
+ /* do nothing */
+ break;
+ default:
+ ret = NULL;
+ }
+
+ return ret;
+}
+
+static s16 taiko_scale_v_micb_vddio(struct taiko_priv *taiko, int v,
+ bool tovddio)
+{
+ int r;
+ int vddio_k, mb_k;
+ vddio_k = taiko_find_k_value(taiko->pdata->micbias.ldoh_v,
+ VDDIO_MICBIAS_MV);
+ mb_k = taiko_find_k_value(taiko->pdata->micbias.ldoh_v,
+ taiko->mbhc_data.micb_mv);
+ if (tovddio)
+ r = v * vddio_k / mb_k;
+ else
+ r = v * mb_k / vddio_k;
+ return r;
+}
+
+static void taiko_mbhc_calc_thres(struct snd_soc_codec *codec)
+{
+ struct taiko_priv *taiko;
+ s16 btn_mv = 0, btn_delta_mv;
+ struct taiko_mbhc_btn_detect_cfg *btn_det;
+ struct taiko_mbhc_plug_type_cfg *plug_type;
+ u16 *btn_high;
+ u8 *n_ready;
+ int i;
+
+ taiko = snd_soc_codec_get_drvdata(codec);
+ btn_det = TAIKO_MBHC_CAL_BTN_DET_PTR(taiko->mbhc_cfg.calibration);
+ plug_type = TAIKO_MBHC_CAL_PLUG_TYPE_PTR(taiko->mbhc_cfg.calibration);
+
+ n_ready = taiko_mbhc_cal_btn_det_mp(btn_det, TAIKO_BTN_DET_N_READY);
+ if (taiko->mbhc_cfg.mclk_rate == TAIKO_MCLK_RATE_12288KHZ) {
+ taiko->mbhc_data.npoll = 4;
+ taiko->mbhc_data.nbounce_wait = 30;
+ } else if (taiko->mbhc_cfg.mclk_rate == TAIKO_MCLK_RATE_9600KHZ) {
+ taiko->mbhc_data.npoll = 7;
+ taiko->mbhc_data.nbounce_wait = 23;
+ }
+
+ taiko->mbhc_data.t_sta_dce = ((1000 * 256) /
+ (taiko->mbhc_cfg.mclk_rate / 1000) *
+ n_ready[taiko_codec_mclk_index(taiko)]) +
+ 10;
+ taiko->mbhc_data.v_ins_hu =
+ taiko_codec_v_sta_dce(codec, STA, plug_type->v_hs_max);
+ taiko->mbhc_data.v_ins_h =
+ taiko_codec_v_sta_dce(codec, DCE, plug_type->v_hs_max);
+
+ taiko->mbhc_data.v_inval_ins_low = TAIKO_MBHC_FAKE_INSERT_LOW;
+ if (taiko->mbhc_cfg.gpio)
+ taiko->mbhc_data.v_inval_ins_high =
+ TAIKO_MBHC_FAKE_INSERT_HIGH;
+ else
+ taiko->mbhc_data.v_inval_ins_high =
+ TAIKO_MBHC_FAKE_INS_HIGH_NO_GPIO;
+
+ if (taiko->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) {
+ taiko->mbhc_data.adj_v_hs_max =
+ taiko_scale_v_micb_vddio(taiko, plug_type->v_hs_max, true);
+ taiko->mbhc_data.adj_v_ins_hu =
+ taiko_codec_v_sta_dce(codec, STA,
+ taiko->mbhc_data.adj_v_hs_max);
+ taiko->mbhc_data.adj_v_ins_h =
+ taiko_codec_v_sta_dce(codec, DCE,
+ taiko->mbhc_data.adj_v_hs_max);
+ taiko->mbhc_data.v_inval_ins_low =
+ taiko_scale_v_micb_vddio(taiko,
+ taiko->mbhc_data.v_inval_ins_low,
+ false);
+ taiko->mbhc_data.v_inval_ins_high =
+ taiko_scale_v_micb_vddio(taiko,
+ taiko->mbhc_data.v_inval_ins_high,
+ false);
+ }
+
+ btn_high = taiko_mbhc_cal_btn_det_mp(btn_det, TAIKO_BTN_DET_V_BTN_HIGH);
+ for (i = 0; i < btn_det->num_btn; i++)
+ btn_mv = btn_high[i] > btn_mv ? btn_high[i] : btn_mv;
+
+ taiko->mbhc_data.v_b1_h = taiko_codec_v_sta_dce(codec, DCE, btn_mv);
+ btn_delta_mv = btn_mv + btn_det->v_btn_press_delta_sta;
+ taiko->mbhc_data.v_b1_hu =
+ taiko_codec_v_sta_dce(codec, STA, btn_delta_mv);
+
+ btn_delta_mv = btn_mv + btn_det->v_btn_press_delta_cic;
+
+ taiko->mbhc_data.v_b1_huc =
+ taiko_codec_v_sta_dce(codec, DCE, btn_delta_mv);
+
+ taiko->mbhc_data.v_brh = taiko->mbhc_data.v_b1_h;
+ taiko->mbhc_data.v_brl = TAIKO_MBHC_BUTTON_MIN;
+
+ taiko->mbhc_data.v_no_mic =
+ taiko_codec_v_sta_dce(codec, STA, plug_type->v_no_mic);
+}
+
+void taiko_mbhc_init(struct snd_soc_codec *codec)
+{
+ struct taiko_priv *taiko;
+ struct taiko_mbhc_general_cfg *generic;
+ struct taiko_mbhc_btn_detect_cfg *btn_det;
+ int n;
+ u8 *n_cic, *gain;
+
+ taiko = snd_soc_codec_get_drvdata(codec);
+ generic = TAIKO_MBHC_CAL_GENERAL_PTR(taiko->mbhc_cfg.calibration);
+ btn_det = TAIKO_MBHC_CAL_BTN_DET_PTR(taiko->mbhc_cfg.calibration);
+
+ for (n = 0; n < 8; n++) {
+ snd_soc_update_bits(codec,
+ TAIKO_A_CDC_MBHC_FIR_B1_CFG,
+ 0x07, n);
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_FIR_B2_CFG,
+ btn_det->c[n]);
+ }
+
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B2_CTL, 0x07,
+ btn_det->nc);
+
+ n_cic = taiko_mbhc_cal_btn_det_mp(btn_det, TAIKO_BTN_DET_N_CIC);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_TIMER_B6_CTL, 0xFF,
+ n_cic[taiko_codec_mclk_index(taiko)]);
+
+ gain = taiko_mbhc_cal_btn_det_mp(btn_det, TAIKO_BTN_DET_GAIN);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B2_CTL, 0x78,
+ gain[taiko_codec_mclk_index(taiko)] << 3);
+
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_TIMER_B4_CTL, 0x70,
+ generic->mbhc_nsa << 4);
+
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_TIMER_B4_CTL, 0x0F,
+ btn_det->n_meas);
+
+ snd_soc_write(codec, TAIKO_A_CDC_MBHC_TIMER_B5_CTL, generic->mbhc_navg);
+
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x80, 0x80);
+
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x78,
+ btn_det->mbhc_nsc << 3);
+
+ snd_soc_update_bits(codec, taiko->reg_addr.micb_4_mbhc, 0x03,
+ TAIKO_MICBIAS2);
+
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x02, 0x02);
+
+ snd_soc_update_bits(codec, TAIKO_A_MBHC_SCALING_MUX_2, 0xF0, 0xF0);
+}
+
+static bool taiko_mbhc_fw_validate(const struct firmware *fw)
+{
+ u32 cfg_offset;
+ struct taiko_mbhc_imped_detect_cfg *imped_cfg;
+ struct taiko_mbhc_btn_detect_cfg *btn_cfg;
+
+ if (fw->size < TAIKO_MBHC_CAL_MIN_SIZE)
+ return false;
+
+ /* previous check guarantees that there is enough fw data up
+ * to num_btn
+ */
+ btn_cfg = TAIKO_MBHC_CAL_BTN_DET_PTR(fw->data);
+ cfg_offset = (u32) ((void *) btn_cfg - (void *) fw->data);
+ if (fw->size < (cfg_offset + TAIKO_MBHC_CAL_BTN_SZ(btn_cfg)))
+ return false;
+
+ /* previous check guarantees that there is enough fw data up
+ * to start of impedance detection configuration
+ */
+ imped_cfg = TAIKO_MBHC_CAL_IMPED_DET_PTR(fw->data);
+ cfg_offset = (u32) ((void *) imped_cfg - (void *) fw->data);
+
+ if (fw->size < (cfg_offset + TAIKO_MBHC_CAL_IMPED_MIN_SZ))
+ return false;
+
+ if (fw->size < (cfg_offset + TAIKO_MBHC_CAL_IMPED_SZ(imped_cfg)))
+ return false;
+
+ return true;
+}
+
+/* called under codec_resource_lock acquisition */
+static int taiko_determine_button(const struct taiko_priv *priv,
+ const s32 micmv)
+{
+ s16 *v_btn_low, *v_btn_high;
+ struct taiko_mbhc_btn_detect_cfg *btn_det;
+ int i, btn = -1;
+
+ btn_det = TAIKO_MBHC_CAL_BTN_DET_PTR(priv->mbhc_cfg.calibration);
+ v_btn_low = taiko_mbhc_cal_btn_det_mp(btn_det, TAIKO_BTN_DET_V_BTN_LOW);
+ v_btn_high = taiko_mbhc_cal_btn_det_mp(btn_det,
+ TAIKO_BTN_DET_V_BTN_HIGH);
+
+ for (i = 0; i < btn_det->num_btn; i++) {
+ if ((v_btn_low[i] <= micmv) && (v_btn_high[i] >= micmv)) {
+ btn = i;
+ break;
+ }
+ }
+
+ if (btn == -1)
+ pr_debug("%s: couldn't find button number for mic mv %d\n",
+ __func__, micmv);
+
+ return btn;
+}
+
+static int taiko_get_button_mask(const int btn)
+{
+ int mask = 0;
+ switch (btn) {
+ case 0:
+ mask = SND_JACK_BTN_0;
+ break;
+ case 1:
+ mask = SND_JACK_BTN_1;
+ break;
+ case 2:
+ mask = SND_JACK_BTN_2;
+ break;
+ case 3:
+ mask = SND_JACK_BTN_3;
+ break;
+ case 4:
+ mask = SND_JACK_BTN_4;
+ break;
+ case 5:
+ mask = SND_JACK_BTN_5;
+ break;
+ case 6:
+ mask = SND_JACK_BTN_6;
+ break;
+ case 7:
+ mask = SND_JACK_BTN_7;
+ break;
+ }
+ return mask;
+}
+
+static irqreturn_t taiko_dce_handler(int irq, void *data)
+{
+ int i, mask;
+ short dce, sta;
+ s32 mv, mv_s, stamv_s;
+ bool vddio;
+ int btn = -1, meas = 0;
+ struct taiko_priv *priv = data;
+ const struct taiko_mbhc_btn_detect_cfg *d =
+ TAIKO_MBHC_CAL_BTN_DET_PTR(priv->mbhc_cfg.calibration);
+ short btnmeas[d->n_btn_meas + 1];
+ struct snd_soc_codec *codec = priv->codec;
+ struct wcd9xxx *core = dev_get_drvdata(priv->codec->dev->parent);
+ int n_btn_meas = d->n_btn_meas;
+ u8 mbhc_status = snd_soc_read(codec, TAIKO_A_CDC_MBHC_B1_STATUS) & 0x3E;
+
+ pr_debug("%s: enter\n", __func__);
+
+ TAIKO_ACQUIRE_LOCK(priv->codec_resource_lock);
+ if (priv->mbhc_state == MBHC_STATE_POTENTIAL_RECOVERY) {
+ pr_debug("%s: mbhc is being recovered, skip button press\n",
+ __func__);
+ goto done;
+ }
+
+ priv->mbhc_state = MBHC_STATE_POTENTIAL;
+
+ if (!priv->mbhc_polling_active) {
+ pr_warn("%s: mbhc polling is not active, skip button press\n",
+ __func__);
+ goto done;
+ }
+
+ dce = taiko_codec_read_dce_result(codec);
+ mv = taiko_codec_sta_dce_v(codec, 1, dce);
+
+ /* If GPIO interrupt already kicked in, ignore button press */
+ if (priv->in_gpio_handler) {
+ pr_debug("%s: GPIO State Changed, ignore button press\n",
+ __func__);
+ btn = -1;
+ goto done;
+ }
+
+ vddio = (priv->mbhc_data.micb_mv != VDDIO_MICBIAS_MV &&
+ priv->mbhc_micbias_switched);
+ mv_s = vddio ? taiko_scale_v_micb_vddio(priv, mv, false) : mv;
+
+ if (mbhc_status != TAIKO_MBHC_STATUS_REL_DETECTION) {
+ if (priv->mbhc_last_resume &&
+ !time_after(jiffies, priv->mbhc_last_resume + HZ)) {
+ pr_debug("%s: Button is already released shortly after resume\n",
+ __func__);
+ n_btn_meas = 0;
+ } else {
+ pr_debug("%s: Button is already released without resume",
+ __func__);
+ sta = taiko_codec_read_sta_result(codec);
+ stamv_s = taiko_codec_sta_dce_v(codec, 0, sta);
+ if (vddio)
+ stamv_s = taiko_scale_v_micb_vddio(priv,
+ stamv_s,
+ false);
+ btn = taiko_determine_button(priv, mv_s);
+ if (btn != taiko_determine_button(priv, stamv_s))
+ btn = -1;
+ goto done;
+ }
+ }
+
+ /* determine pressed button */
+ btnmeas[meas++] = taiko_determine_button(priv, mv_s);
+ pr_debug("%s: meas %d - DCE %d,%d,%d button %d\n", __func__,
+ meas - 1, dce, mv, mv_s, btnmeas[meas - 1]);
+ if (n_btn_meas == 0)
+ btn = btnmeas[0];
+ for (; ((d->n_btn_meas) && (meas < (d->n_btn_meas + 1))); meas++) {
+ dce = taiko_codec_sta_dce(codec, 1, false);
+ mv = taiko_codec_sta_dce_v(codec, 1, dce);
+ mv_s = vddio ? taiko_scale_v_micb_vddio(priv, mv, false) : mv;
+
+ btnmeas[meas] = taiko_determine_button(priv, mv_s);
+ pr_debug("%s: meas %d - DCE %d,%d,%d button %d\n",
+ __func__, meas, dce, mv, mv_s, btnmeas[meas]);
+ /* if large enough measurements are collected,
+ * start to check if last all n_btn_con measurements were
+ * in same button low/high range */
+ if (meas + 1 >= d->n_btn_con) {
+ for (i = 0; i < d->n_btn_con; i++)
+ if ((btnmeas[meas] < 0) ||
+ (btnmeas[meas] != btnmeas[meas - i]))
+ break;
+ if (i == d->n_btn_con) {
+ /* button pressed */
+ btn = btnmeas[meas];
+ break;
+ } else if ((n_btn_meas - meas) < (d->n_btn_con - 1)) {
+ /* if left measurements are less than n_btn_con,
+ * it's impossible to find button number */
+ break;
+ }
+ }
+ }
+
+ if (btn >= 0) {
+ if (priv->in_gpio_handler) {
+ pr_debug(
+ "%s: GPIO already triggered, ignore button press\n",
+ __func__);
+ goto done;
+ }
+ mask = taiko_get_button_mask(btn);
+ priv->buttons_pressed |= mask;
+ wcd9xxx_lock_sleep(core);
+ if (schedule_delayed_work(&priv->mbhc_btn_dwork,
+ msecs_to_jiffies(400)) == 0) {
+ WARN(1, "Button pressed twice without release event\n");
+ wcd9xxx_unlock_sleep(core);
+ }
+ } else {
+ pr_debug("%s: bogus button press, too short press?\n",
+ __func__);
+ }
+
+ done:
+ pr_debug("%s: leave\n", __func__);
+ TAIKO_RELEASE_LOCK(priv->codec_resource_lock);
+ return IRQ_HANDLED;
+}
+
+static int taiko_is_fake_press(struct taiko_priv *priv)
+{
+ int i;
+ int r = 0;
+ struct snd_soc_codec *codec = priv->codec;
+ const int dces = MBHC_NUM_DCE_PLUG_DETECT;
+ s16 mb_v, v_ins_hu, v_ins_h;
+
+ v_ins_hu = taiko_get_current_v_ins(priv, true);
+ v_ins_h = taiko_get_current_v_ins(priv, false);
+
+ for (i = 0; i < dces; i++) {
+ usleep_range(10000, 10000);
+ if (i == 0) {
+ mb_v = taiko_codec_sta_dce(codec, 0, true);
+ pr_debug("%s: STA[0]: %d,%d\n", __func__, mb_v,
+ taiko_codec_sta_dce_v(codec, 0, mb_v));
+ if (mb_v < (s16)priv->mbhc_data.v_b1_hu ||
+ mb_v > v_ins_hu) {
+ r = 1;
+ break;
+ }
+ } else {
+ mb_v = taiko_codec_sta_dce(codec, 1, true);
+ pr_debug("%s: DCE[%d]: %d,%d\n", __func__, i, mb_v,
+ taiko_codec_sta_dce_v(codec, 1, mb_v));
+ if (mb_v < (s16)priv->mbhc_data.v_b1_h ||
+ mb_v > v_ins_h) {
+ r = 1;
+ break;
+ }
+ }
+ }
+
+ return r;
+}
+
+static irqreturn_t taiko_release_handler(int irq, void *data)
+{
+ int ret;
+ struct taiko_priv *priv = data;
+ struct snd_soc_codec *codec = priv->codec;
+
+ pr_debug("%s: enter\n", __func__);
+
+ TAIKO_ACQUIRE_LOCK(priv->codec_resource_lock);
+ priv->mbhc_state = MBHC_STATE_RELEASE;
+
+ taiko_codec_drive_v_to_micbias(codec, 10000);
+
+ if (priv->buttons_pressed & TAIKO_JACK_BUTTON_MASK) {
+ ret = taiko_cancel_btn_work(priv);
+ if (ret == 0) {
+ pr_debug("%s: Reporting long button release event\n",
+ __func__);
+ if (priv->mbhc_cfg.button_jack)
+ taiko_snd_soc_jack_report(priv,
+ priv->mbhc_cfg.button_jack, 0,
+ priv->buttons_pressed);
+ } else {
+ if (taiko_is_fake_press(priv)) {
+ pr_debug("%s: Fake button press interrupt\n",
+ __func__);
+ } else if (priv->mbhc_cfg.button_jack) {
+ if (priv->in_gpio_handler) {
+ pr_debug("%s: GPIO kicked in, ignore\n",
+ __func__);
+ } else {
+ pr_debug(
+ "%s: Reporting short button press and release\n",
+ __func__);
+ taiko_snd_soc_jack_report(priv,
+ priv->mbhc_cfg.button_jack,
+ priv->buttons_pressed,
+ priv->buttons_pressed);
+ taiko_snd_soc_jack_report(priv,
+ priv->mbhc_cfg.button_jack, 0,
+ priv->buttons_pressed);
+ }
+ }
+ }
+
+ priv->buttons_pressed &= ~TAIKO_JACK_BUTTON_MASK;
+ }
+
+ taiko_codec_calibrate_hs_polling(codec);
+
+ if (priv->mbhc_cfg.gpio)
+ msleep(TAIKO_MBHC_GPIO_REL_DEBOUNCE_TIME_MS);
+
+ taiko_codec_start_hs_polling(codec);
+
+ pr_debug("%s: leave\n", __func__);
+ TAIKO_RELEASE_LOCK(priv->codec_resource_lock);
+ return IRQ_HANDLED;
+}
+
+static void taiko_codec_shutdown_hs_removal_detect(struct snd_soc_codec *codec)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ const struct taiko_mbhc_general_cfg *generic =
+ TAIKO_MBHC_CAL_GENERAL_PTR(taiko->mbhc_cfg.calibration);
+
+ if (!taiko->mclk_enabled && !taiko->mbhc_polling_active)
+ taiko_codec_enable_config_mode(codec, 1);
+
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x6, 0x0);
+
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg, 0x80, 0x00);
+
+ usleep_range(generic->t_shutdown_plug_rem,
+ generic->t_shutdown_plug_rem);
+
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL, 0xA, 0x8);
+ if (!taiko->mclk_enabled && !taiko->mbhc_polling_active)
+ taiko_codec_enable_config_mode(codec, 0);
+
+ snd_soc_write(codec, TAIKO_A_MBHC_SCALING_MUX_1, 0x00);
+}
+
+static void taiko_codec_cleanup_hs_polling(struct snd_soc_codec *codec)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ taiko_codec_shutdown_hs_removal_detect(codec);
+
+ if (!taiko->mclk_enabled) {
+ taiko_codec_disable_clock_block(codec);
+ taiko_codec_enable_bandgap(codec, TAIKO_BANDGAP_OFF);
+ }
+
+ taiko->mbhc_polling_active = false;
+ taiko->mbhc_state = MBHC_STATE_NONE;
+}
+
+static irqreturn_t taiko_hphl_ocp_irq(int irq, void *data)
+{
+ struct taiko_priv *taiko = data;
+ struct snd_soc_codec *codec;
+
+ pr_info("%s: received HPHL OCP irq\n", __func__);
+
+ if (taiko) {
+ codec = taiko->codec;
+ if (taiko->hphlocp_cnt++ < TAIKO_OCP_ATTEMPT) {
+ pr_info("%s: retry\n", __func__);
+ snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL, 0x10,
+ 0x00);
+ snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL, 0x10,
+ 0x10);
+ } else {
+ wcd9xxx_disable_irq(codec->control_data,
+ TAIKO_IRQ_HPH_PA_OCPL_FAULT);
+ taiko->hphlocp_cnt = 0;
+ taiko->hph_status |= SND_JACK_OC_HPHL;
+ if (taiko->mbhc_cfg.headset_jack)
+ taiko_snd_soc_jack_report(taiko,
+ taiko->mbhc_cfg.headset_jack,
+ taiko->hph_status,
+ TAIKO_JACK_MASK);
+ }
+ } else {
+ pr_err("%s: Bad taiko private data\n", __func__);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t taiko_hphr_ocp_irq(int irq, void *data)
+{
+ struct taiko_priv *taiko = data;
+ struct snd_soc_codec *codec;
+
+ pr_info("%s: received HPHR OCP irq\n", __func__);
+
+ if (taiko) {
+ codec = taiko->codec;
+ if (taiko->hphrocp_cnt++ < TAIKO_OCP_ATTEMPT) {
+ pr_info("%s: retry\n", __func__);
+ snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL, 0x10,
+ 0x00);
+ snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL, 0x10,
+ 0x10);
+ } else {
+ wcd9xxx_disable_irq(codec->control_data,
+ TAIKO_IRQ_HPH_PA_OCPR_FAULT);
+ taiko->hphrocp_cnt = 0;
+ taiko->hph_status |= SND_JACK_OC_HPHR;
+ if (taiko->mbhc_cfg.headset_jack)
+ taiko_snd_soc_jack_report(taiko,
+ taiko->mbhc_cfg.headset_jack,
+ taiko->hph_status,
+ TAIKO_JACK_MASK);
+ }
+ } else {
+ pr_err("%s: Bad taiko private data\n", __func__);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static bool taiko_is_inval_ins_range(struct snd_soc_codec *codec,
+ s32 mic_volt, bool highhph, bool *highv)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ bool invalid = false;
+ s16 v_hs_max;
+
+ /* Perform this check only when the high voltage headphone
+ * needs to be considered as invalid
+ */
+ v_hs_max = taiko_get_current_v_hs_max(taiko);
+ *highv = mic_volt > v_hs_max;
+ if (!highhph && *highv)
+ invalid = true;
+ else if (mic_volt < taiko->mbhc_data.v_inval_ins_high &&
+ (mic_volt > taiko->mbhc_data.v_inval_ins_low))
+ invalid = true;
+
+ return invalid;
+}
+
+static bool taiko_is_inval_ins_delta(struct snd_soc_codec *codec,
+ int mic_volt, int mic_volt_prev,
+ int threshold)
+{
+ return abs(mic_volt - mic_volt_prev) > threshold;
+}
+
+/* called under codec_resource_lock acquisition */
+void taiko_find_plug_and_report(struct snd_soc_codec *codec,
+ enum taiko_mbhc_plug_type plug_type)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ if (plug_type == PLUG_TYPE_HEADPHONE &&
+ taiko->current_plug == PLUG_TYPE_NONE) {
+ /* Nothing was reported previously
+ * report a headphone or unsupported
+ */
+ taiko_codec_report_plug(codec, 1, SND_JACK_HEADPHONE);
+ taiko_codec_cleanup_hs_polling(codec);
+ } else if (plug_type == PLUG_TYPE_GND_MIC_SWAP) {
+ if (taiko->current_plug == PLUG_TYPE_HEADSET)
+ taiko_codec_report_plug(codec, 0, SND_JACK_HEADSET);
+ else if (taiko->current_plug == PLUG_TYPE_HEADPHONE)
+ taiko_codec_report_plug(codec, 0, SND_JACK_HEADPHONE);
+
+ taiko_codec_report_plug(codec, 1, SND_JACK_UNSUPPORTED);
+ taiko_codec_cleanup_hs_polling(codec);
+ } else if (plug_type == PLUG_TYPE_HEADSET) {
+ /* If Headphone was reported previously, this will
+ * only report the mic line
+ */
+ taiko_codec_report_plug(codec, 1, SND_JACK_HEADSET);
+ msleep(100);
+ taiko_codec_start_hs_polling(codec);
+ } else if (plug_type == PLUG_TYPE_HIGH_HPH) {
+ if (taiko->current_plug == PLUG_TYPE_NONE)
+ taiko_codec_report_plug(codec, 1, SND_JACK_HEADPHONE);
+ taiko_codec_cleanup_hs_polling(codec);
+ pr_debug("setup mic trigger for further detection\n");
+ taiko->lpi_enabled = true;
+ taiko_codec_enable_hs_detect(codec, 1,
+ MBHC_USE_MB_TRIGGER |
+ MBHC_USE_HPHL_TRIGGER,
+ false);
+ } else {
+ WARN(1, "Unexpected current plug_type %d, plug_type %d\n",
+ taiko->current_plug, plug_type);
+ }
+}
+
+/* should be called under interrupt context that hold suspend */
+static void taiko_schedule_hs_detect_plug(struct taiko_priv *taiko)
+{
+ pr_debug("%s: scheduling taiko_hs_correct_gpio_plug\n", __func__);
+ taiko->hs_detect_work_stop = false;
+ wcd9xxx_lock_sleep(taiko->codec->control_data);
+ schedule_work(&taiko->hs_correct_plug_work);
+}
+
+/* called under codec_resource_lock acquisition */
+static void taiko_cancel_hs_detect_plug(struct taiko_priv *taiko)
+{
+ pr_debug("%s: canceling hs_correct_plug_work\n", __func__);
+ taiko->hs_detect_work_stop = true;
+ wmb();
+ TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+ if (cancel_work_sync(&taiko->hs_correct_plug_work)) {
+ pr_debug("%s: hs_correct_plug_work is canceled\n", __func__);
+ wcd9xxx_unlock_sleep(taiko->codec->control_data);
+ }
+ TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+}
+
+static bool taiko_hs_gpio_level_remove(struct taiko_priv *taiko)
+{
+ return (gpio_get_value_cansleep(taiko->mbhc_cfg.gpio) !=
+ taiko->mbhc_cfg.gpio_level_insert);
+}
+
+/* called under codec_resource_lock acquisition */
+static void taiko_codec_hphr_gnd_switch(struct snd_soc_codec *codec, bool on)
+{
+ snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x01, on);
+ if (on)
+ usleep_range(5000, 5000);
+}
+
+/* called under codec_resource_lock acquisition and mbhc override = 1 */
+static enum taiko_mbhc_plug_type
+taiko_codec_get_plug_type(struct snd_soc_codec *codec, bool highhph)
+{
+ int i;
+ bool gndswitch, vddioswitch;
+ int scaled;
+ struct taiko_mbhc_plug_type_cfg *plug_type_ptr;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ const bool vddio = (taiko->mbhc_data.micb_mv != VDDIO_MICBIAS_MV);
+ int num_det = (MBHC_NUM_DCE_PLUG_DETECT + vddio);
+ enum taiko_mbhc_plug_type plug_type[num_det];
+ s16 mb_v[num_det];
+ s32 mic_mv[num_det];
+ bool inval;
+ bool highdelta;
+ bool ahighv = false, highv;
+
+ /* make sure override is on */
+ WARN_ON(!(snd_soc_read(codec, TAIKO_A_CDC_MBHC_B1_CTL) & 0x04));
+
+ /* GND and MIC swap detection requires at least 2 rounds of DCE */
+ BUG_ON(num_det < 2);
+
+ plug_type_ptr =
+ TAIKO_MBHC_CAL_PLUG_TYPE_PTR(taiko->mbhc_cfg.calibration);
+
+ plug_type[0] = PLUG_TYPE_INVALID;
+
+ /* performs DCEs for N times
+ * 1st: check if voltage is in invalid range
+ * 2nd - N-2nd: check voltage range and delta
+ * N-1st: check voltage range, delta with HPHR GND switch
+ * Nth: check voltage range with VDDIO switch if micbias V != vddio V*/
+ for (i = 0; i < num_det; i++) {
+ gndswitch = (i == (num_det - 1 - vddio));
+ vddioswitch = (vddio && ((i == num_det - 1) ||
+ (i == num_det - 2)));
+ if (i == 0) {
+ mb_v[i] = taiko_codec_setup_hs_polling(codec);
+ mic_mv[i] = taiko_codec_sta_dce_v(codec, 1 , mb_v[i]);
+ inval = taiko_is_inval_ins_range(codec, mic_mv[i],
+ highhph, &highv);
+ ahighv |= highv;
+ scaled = mic_mv[i];
+ } else {
+ if (vddioswitch)
+ __taiko_codec_switch_micbias(taiko->codec, 1,
+ false, false);
+ if (gndswitch)
+ taiko_codec_hphr_gnd_switch(codec, true);
+ mb_v[i] = __taiko_codec_sta_dce(codec, 1, true, true);
+ mic_mv[i] = taiko_codec_sta_dce_v(codec, 1 , mb_v[i]);
+ if (vddioswitch)
+ scaled = taiko_scale_v_micb_vddio(taiko,
+ mic_mv[i],
+ false);
+ else
+ scaled = mic_mv[i];
+ /* !gndswitch & vddioswitch means the previous DCE
+ * was done with gndswitch, don't compare with DCE
+ * with gndswitch */
+ highdelta = taiko_is_inval_ins_delta(codec, scaled,
+ mic_mv[i - !gndswitch - vddioswitch],
+ TAIKO_MBHC_FAKE_INS_DELTA_SCALED_MV);
+ inval = (taiko_is_inval_ins_range(codec, mic_mv[i],
+ highhph, &highv) ||
+ highdelta);
+ ahighv |= highv;
+ if (gndswitch)
+ taiko_codec_hphr_gnd_switch(codec, false);
+ if (vddioswitch)
+ __taiko_codec_switch_micbias(taiko->codec, 0,
+ false, false);
+ /* claim UNSUPPORTED plug insertion when
+ * good headset is detected but HPHR GND switch makes
+ * delta difference */
+ if (i == (num_det - 2) && highdelta && !ahighv)
+ plug_type[0] = PLUG_TYPE_GND_MIC_SWAP;
+ else if (i == (num_det - 1) && inval)
+ plug_type[0] = PLUG_TYPE_INVALID;
+ }
+ pr_debug("%s: DCE #%d, %04x, V %d, scaled V %d, GND %d, VDDIO %d, inval %d\n",
+ __func__, i + 1, mb_v[i] & 0xffff, mic_mv[i], scaled,
+ gndswitch, vddioswitch, inval);
+ /* don't need to run further DCEs */
+ if (ahighv && inval)
+ break;
+ mic_mv[i] = scaled;
+ }
+
+ for (i = 0; (plug_type[0] != PLUG_TYPE_GND_MIC_SWAP && !inval) &&
+ i < num_det; i++) {
+ /*
+ * If we are here, means none of the all
+ * measurements are fake, continue plug type detection.
+ * If all three measurements do not produce same
+ * plug type, restart insertion detection
+ */
+ if (mic_mv[i] < plug_type_ptr->v_no_mic) {
+ plug_type[i] = PLUG_TYPE_HEADPHONE;
+ pr_debug("%s: Detect attempt %d, detected Headphone\n",
+ __func__, i);
+ } else if (highhph && (mic_mv[i] > plug_type_ptr->v_hs_max)) {
+ plug_type[i] = PLUG_TYPE_HIGH_HPH;
+ pr_debug(
+ "%s: Detect attempt %d, detected High Headphone\n",
+ __func__, i);
+ } else {
+ plug_type[i] = PLUG_TYPE_HEADSET;
+ pr_debug("%s: Detect attempt %d, detected Headset\n",
+ __func__, i);
+ }
+
+ if (i > 0 && (plug_type[i - 1] != plug_type[i])) {
+ pr_err("%s: Detect attempt %d and %d are not same",
+ __func__, i - 1, i);
+ plug_type[0] = PLUG_TYPE_INVALID;
+ inval = true;
+ break;
+ }
+ }
+
+ pr_debug("%s: Detected plug type %d\n", __func__, plug_type[0]);
+ return plug_type[0];
+}
+
+static void taiko_hs_correct_gpio_plug(struct work_struct *work)
+{
+ struct taiko_priv *taiko;
+ struct snd_soc_codec *codec;
+ int retry = 0, pt_gnd_mic_swap_cnt = 0;
+ bool correction = false;
+ enum taiko_mbhc_plug_type plug_type;
+ unsigned long timeout;
+
+ taiko = container_of(work, struct taiko_priv, hs_correct_plug_work);
+ codec = taiko->codec;
+
+ pr_debug("%s: enter\n", __func__);
+ taiko->mbhc_cfg.mclk_cb_fn(codec, 1, false);
+
+ /* Keep override on during entire plug type correction work.
+ *
+ * This is okay under the assumption that any GPIO irqs which use
+ * MBHC block cancel and sync this work so override is off again
+ * prior to GPIO interrupt handler's MBHC block usage.
+ * Also while this correction work is running, we can guarantee
+ * DAPM doesn't use any MBHC block as this work only runs with
+ * headphone detection.
+ */
+ taiko_turn_onoff_override(codec, true);
+
+ timeout = jiffies + msecs_to_jiffies(TAIKO_HS_DETECT_PLUG_TIME_MS);
+ while (!time_after(jiffies, timeout)) {
+ ++retry;
+ rmb();
+ if (taiko->hs_detect_work_stop) {
+ pr_debug("%s: stop requested\n", __func__);
+ break;
+ }
+
+ msleep(TAIKO_HS_DETECT_PLUG_INERVAL_MS);
+ if (taiko_hs_gpio_level_remove(taiko)) {
+ pr_debug("%s: GPIO value is low\n", __func__);
+ break;
+ }
+
+ /* can race with removal interrupt */
+ TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+ plug_type = taiko_codec_get_plug_type(codec, true);
+ TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+
+ if (plug_type == PLUG_TYPE_INVALID) {
+ pr_debug("Invalid plug in attempt # %d\n", retry);
+ if (retry == NUM_ATTEMPTS_TO_REPORT &&
+ taiko->current_plug == PLUG_TYPE_NONE) {
+ taiko_codec_report_plug(codec, 1,
+ SND_JACK_HEADPHONE);
+ }
+ } else if (plug_type == PLUG_TYPE_HEADPHONE) {
+ pr_debug("Good headphone detected, continue polling mic\n");
+ if (taiko->current_plug == PLUG_TYPE_NONE)
+ taiko_codec_report_plug(codec, 1,
+ SND_JACK_HEADPHONE);
+ } else {
+ if (plug_type == PLUG_TYPE_GND_MIC_SWAP) {
+ pt_gnd_mic_swap_cnt++;
+ if (pt_gnd_mic_swap_cnt <
+ TAIKO_MBHC_GND_MIC_SWAP_THRESHOLD)
+ continue;
+ else if (pt_gnd_mic_swap_cnt >
+ TAIKO_MBHC_GND_MIC_SWAP_THRESHOLD) {
+ /* This is due to GND/MIC switch didn't
+ * work, Report unsupported plug */
+ } else if (taiko->mbhc_cfg.swap_gnd_mic) {
+ /* if switch is toggled, check again,
+ * otherwise report unsupported plug */
+ if (taiko->mbhc_cfg.swap_gnd_mic(codec))
+ continue;
+ }
+ } else
+ pt_gnd_mic_swap_cnt = 0;
+
+ TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+ /* Turn off override */
+ taiko_turn_onoff_override(codec, false);
+ /* The valid plug also includes PLUG_TYPE_GND_MIC_SWAP
+ */
+ taiko_find_plug_and_report(codec, plug_type);
+ TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+ pr_debug("Attempt %d found correct plug %d\n", retry,
+ plug_type);
+ correction = true;
+ break;
+ }
+ }
+
+ /* Turn off override */
+ if (!correction)
+ taiko_turn_onoff_override(codec, false);
+
+ taiko->mbhc_cfg.mclk_cb_fn(codec, 0, false);
+ pr_debug("%s: leave\n", __func__);
+ /* unlock sleep */
+ wcd9xxx_unlock_sleep(taiko->codec->control_data);
+}
+
+/* called under codec_resource_lock acquisition */
+static void taiko_codec_decide_gpio_plug(struct snd_soc_codec *codec)
+{
+ enum taiko_mbhc_plug_type plug_type;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s: enter\n", __func__);
+
+ taiko_turn_onoff_override(codec, true);
+ plug_type = taiko_codec_get_plug_type(codec, true);
+ taiko_turn_onoff_override(codec, false);
+
+ if (taiko_hs_gpio_level_remove(taiko)) {
+ pr_debug("%s: GPIO value is low when determining plug\n",
+ __func__);
+ return;
+ }
+
+ if (plug_type == PLUG_TYPE_INVALID ||
+ plug_type == PLUG_TYPE_GND_MIC_SWAP) {
+ taiko_schedule_hs_detect_plug(taiko);
+ } else if (plug_type == PLUG_TYPE_HEADPHONE) {
+ taiko_codec_report_plug(codec, 1, SND_JACK_HEADPHONE);
+
+ taiko_schedule_hs_detect_plug(taiko);
+ } else {
+ pr_debug("%s: Valid plug found, determine plug type %d\n",
+ __func__, plug_type);
+ taiko_find_plug_and_report(codec, plug_type);
+ }
+}
+
+/* called under codec_resource_lock acquisition */
+static void taiko_codec_detect_plug_type(struct snd_soc_codec *codec)
+{
+ enum taiko_mbhc_plug_type plug_type;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ const struct taiko_mbhc_plug_detect_cfg *plug_det =
+ TAIKO_MBHC_CAL_PLUG_DET_PTR(taiko->mbhc_cfg.calibration);
+
+ /* Turn on the override,
+ * taiko_codec_setup_hs_polling requires override on */
+ taiko_turn_onoff_override(codec, true);
+
+ if (plug_det->t_ins_complete > 20)
+ msleep(plug_det->t_ins_complete);
+ else
+ usleep_range(plug_det->t_ins_complete * 1000,
+ plug_det->t_ins_complete * 1000);
+
+ if (taiko->mbhc_cfg.gpio) {
+ /* Turn off the override */
+ taiko_turn_onoff_override(codec, false);
+ if (taiko_hs_gpio_level_remove(taiko))
+ pr_debug(
+ "%s: GPIO value is low when determining plug\n",
+ __func__);
+ else
+ taiko_codec_decide_gpio_plug(codec);
+ return;
+ }
+
+ plug_type = taiko_codec_get_plug_type(codec, false);
+ taiko_turn_onoff_override(codec, false);
+
+ if (plug_type == PLUG_TYPE_INVALID) {
+ pr_debug("%s: Invalid plug type detected\n", __func__);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_B1_CTL, 0x02, 0x02);
+ taiko_codec_cleanup_hs_polling(codec);
+ taiko_codec_enable_hs_detect(codec, 1,
+ MBHC_USE_MB_TRIGGER |
+ MBHC_USE_HPHL_TRIGGER, false);
+ } else if (plug_type == PLUG_TYPE_GND_MIC_SWAP) {
+ pr_debug("%s: GND-MIC swapped plug type detected\n", __func__);
+ taiko_codec_report_plug(codec, 1, SND_JACK_UNSUPPORTED);
+ taiko_codec_cleanup_hs_polling(codec);
+ taiko_codec_enable_hs_detect(codec, 0, 0, false);
+ } else if (plug_type == PLUG_TYPE_HEADPHONE) {
+ pr_debug("%s: Headphone Detected\n", __func__);
+ taiko_codec_report_plug(codec, 1, SND_JACK_HEADPHONE);
+ taiko_codec_cleanup_hs_polling(codec);
+ taiko_codec_enable_hs_detect(codec, 0, 0, false);
+ } else if (plug_type == PLUG_TYPE_HEADSET) {
+ pr_debug("%s: Headset detected\n", __func__);
+ taiko_codec_report_plug(codec, 1, SND_JACK_HEADSET);
+
+ /* avoid false button press detect */
+ msleep(50);
+ taiko_codec_start_hs_polling(codec);
+ }
+}
+
+/* called only from interrupt which is under codec_resource_lock acquisition */
+static void taiko_hs_insert_irq_gpio(struct taiko_priv *priv, bool is_removal)
+{
+ struct snd_soc_codec *codec = priv->codec;
+
+ if (!is_removal) {
+ pr_debug("%s: MIC trigger insertion interrupt\n", __func__);
+
+ rmb();
+ if (priv->lpi_enabled)
+ msleep(100);
+
+ rmb();
+ if (!priv->lpi_enabled) {
+ pr_debug("%s: lpi is disabled\n", __func__);
+ } else if (gpio_get_value_cansleep(priv->mbhc_cfg.gpio) ==
+ priv->mbhc_cfg.gpio_level_insert) {
+ pr_debug(
+ "%s: Valid insertion, detect plug type\n", __func__);
+ taiko_codec_decide_gpio_plug(codec);
+ } else {
+ pr_debug(
+ "%s: Invalid insertion stop plug detection\n",
+ __func__);
+ }
+ } else {
+ pr_err("%s: GPIO used, invalid MBHC Removal\n", __func__);
+ }
+}
+
+/* called only from interrupt which is under codec_resource_lock acquisition */
+static void taiko_hs_insert_irq_nogpio(struct taiko_priv *priv, bool is_removal,
+ bool is_mb_trigger)
+{
+ int ret;
+ struct snd_soc_codec *codec = priv->codec;
+ struct wcd9xxx *core = dev_get_drvdata(priv->codec->dev->parent);
+
+ if (is_removal) {
+ /* cancel possiblely running hs detect work */
+ taiko_cancel_hs_detect_plug(priv);
+
+ /*
+ * If headphone is removed while playback is in progress,
+ * it is possible that micbias will be switched to VDDIO.
+ */
+ taiko_codec_switch_micbias(codec, 0);
+ if (priv->current_plug == PLUG_TYPE_HEADPHONE)
+ taiko_codec_report_plug(codec, 0, SND_JACK_HEADPHONE);
+ else if (priv->current_plug == PLUG_TYPE_GND_MIC_SWAP)
+ taiko_codec_report_plug(codec, 0, SND_JACK_UNSUPPORTED);
+ else
+ WARN(1, "%s: Unexpected current plug type %d\n",
+ __func__, priv->current_plug);
+ taiko_codec_shutdown_hs_removal_detect(codec);
+ taiko_codec_enable_hs_detect(codec, 1,
+ MBHC_USE_MB_TRIGGER |
+ MBHC_USE_HPHL_TRIGGER,
+ true);
+ } else if (is_mb_trigger && !is_removal) {
+ pr_debug("%s: Waiting for Headphone left trigger\n",
+ __func__);
+ wcd9xxx_lock_sleep(core);
+ if (schedule_delayed_work(&priv->mbhc_insert_dwork,
+ usecs_to_jiffies(1000000)) == 0) {
+ pr_err("%s: mbhc_insert_dwork is already scheduled\n",
+ __func__);
+ wcd9xxx_unlock_sleep(core);
+ }
+ taiko_codec_enable_hs_detect(codec, 1, MBHC_USE_HPHL_TRIGGER,
+ false);
+ } else {
+ ret = cancel_delayed_work(&priv->mbhc_insert_dwork);
+ if (ret != 0) {
+ pr_debug(
+ "%s: Complete plug insertion, Detecting plug type\n",
+ __func__);
+ taiko_codec_detect_plug_type(codec);
+ wcd9xxx_unlock_sleep(core);
+ } else {
+ wcd9xxx_enable_irq(codec->control_data,
+ TAIKO_IRQ_MBHC_INSERTION);
+ pr_err("%s: Error detecting plug insertion\n",
+ __func__);
+ }
+ }
+}
+
+static irqreturn_t taiko_hs_insert_irq(int irq, void *data)
+{
+ bool is_mb_trigger, is_removal;
+ struct taiko_priv *priv = data;
+ struct snd_soc_codec *codec = priv->codec;
+
+ pr_debug("%s: enter\n", __func__);
+ TAIKO_ACQUIRE_LOCK(priv->codec_resource_lock);
+ wcd9xxx_disable_irq(codec->control_data, TAIKO_IRQ_MBHC_INSERTION);
+
+ is_mb_trigger = !!(snd_soc_read(codec, priv->mbhc_bias_regs.mbhc_reg) &
+ 0x10);
+ is_removal = !!(snd_soc_read(codec, TAIKO_A_CDC_MBHC_INT_CTL) & 0x02);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_INT_CTL, 0x03, 0x00);
+
+ /* Turn off both HPH and MIC line schmitt triggers */
+ snd_soc_update_bits(codec, priv->mbhc_bias_regs.mbhc_reg, 0x90, 0x00);
+ snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x13, 0x00);
+ snd_soc_update_bits(codec, priv->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
+
+ if (priv->mbhc_cfg.gpio)
+ taiko_hs_insert_irq_gpio(priv, is_removal);
+ else
+ taiko_hs_insert_irq_nogpio(priv, is_removal, is_mb_trigger);
+
+ TAIKO_RELEASE_LOCK(priv->codec_resource_lock);
+ return IRQ_HANDLED;
+}
+
+static bool is_valid_mic_voltage(struct snd_soc_codec *codec, s32 mic_mv)
+{
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ const struct taiko_mbhc_plug_type_cfg *plug_type =
+ TAIKO_MBHC_CAL_PLUG_TYPE_PTR(taiko->mbhc_cfg.calibration);
+ const s16 v_hs_max = taiko_get_current_v_hs_max(taiko);
+
+ return (!(mic_mv > 10 && mic_mv < 80) && (mic_mv > plug_type->v_no_mic)
+ && (mic_mv < v_hs_max)) ? true : false;
+}
+
+/* called under codec_resource_lock acquisition
+ * returns true if mic voltage range is back to normal insertion
+ * returns false either if timedout or removed */
+static bool taiko_hs_remove_settle(struct snd_soc_codec *codec)
+{
+ int i;
+ bool timedout, settled = false;
+ s32 mic_mv[MBHC_NUM_DCE_PLUG_DETECT];
+ short mb_v[MBHC_NUM_DCE_PLUG_DETECT];
+ unsigned long retry = 0, timeout;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ const s16 v_hs_max = taiko_get_current_v_hs_max(taiko);
+
+ timeout = jiffies + msecs_to_jiffies(TAIKO_HS_DETECT_PLUG_TIME_MS);
+ while (!(timedout = time_after(jiffies, timeout))) {
+ retry++;
+ if (taiko->mbhc_cfg.gpio && taiko_hs_gpio_level_remove(taiko)) {
+ pr_debug("%s: GPIO indicates removal\n", __func__);
+ break;
+ }
+
+ if (taiko->mbhc_cfg.gpio) {
+ if (retry > 1)
+ msleep(250);
+ else
+ msleep(50);
+ }
+
+ if (taiko->mbhc_cfg.gpio && taiko_hs_gpio_level_remove(taiko)) {
+ pr_debug("%s: GPIO indicates removal\n", __func__);
+ break;
+ }
+
+ for (i = 0; i < MBHC_NUM_DCE_PLUG_DETECT; i++) {
+ mb_v[i] = taiko_codec_sta_dce(codec, 1, true);
+ mic_mv[i] = taiko_codec_sta_dce_v(codec, 1 , mb_v[i]);
+ pr_debug("%s : DCE run %lu, mic_mv = %d(%x)\n",
+ __func__, retry, mic_mv[i], mb_v[i]);
+ }
+
+ if (taiko->mbhc_cfg.gpio && taiko_hs_gpio_level_remove(taiko)) {
+ pr_debug("%s: GPIO indicates removal\n", __func__);
+ break;
+ }
+
+ if (taiko->current_plug == PLUG_TYPE_NONE) {
+ pr_debug("%s : headset/headphone is removed\n",
+ __func__);
+ break;
+ }
+
+ for (i = 0; i < MBHC_NUM_DCE_PLUG_DETECT; i++)
+ if (!is_valid_mic_voltage(codec, mic_mv[i]))
+ break;
+
+ if (i == MBHC_NUM_DCE_PLUG_DETECT) {
+ pr_debug("%s: MIC voltage settled\n", __func__);
+ settled = true;
+ msleep(200);
+ break;
+ }
+
+ /* only for non-GPIO remove irq */
+ if (!taiko->mbhc_cfg.gpio) {
+ for (i = 0; i < MBHC_NUM_DCE_PLUG_DETECT; i++)
+ if (mic_mv[i] < v_hs_max)
+ break;
+ if (i == MBHC_NUM_DCE_PLUG_DETECT) {
+ pr_debug("%s: Headset is removed\n", __func__);
+ break;
+ }
+ }
+ }
+
+ if (timedout)
+ pr_debug("%s: Microphone did not settle in %d seconds\n",
+ __func__, TAIKO_HS_DETECT_PLUG_TIME_MS);
+ return settled;
+}
+
+/* called only from interrupt which is under codec_resource_lock acquisition */
+static void taiko_hs_remove_irq_gpio(struct taiko_priv *priv)
+{
+ struct snd_soc_codec *codec = priv->codec;
+
+ if (taiko_hs_remove_settle(codec))
+ taiko_codec_start_hs_polling(codec);
+ pr_debug("%s: remove settle done\n", __func__);
+}
+
+/* called only from interrupt which is under codec_resource_lock acquisition */
+static void taiko_hs_remove_irq_nogpio(struct taiko_priv *priv)
+{
+ short bias_value;
+ bool removed = true;
+ struct snd_soc_codec *codec = priv->codec;
+ const struct taiko_mbhc_general_cfg *generic =
+ TAIKO_MBHC_CAL_GENERAL_PTR(priv->mbhc_cfg.calibration);
+ int min_us = TAIKO_FAKE_REMOVAL_MIN_PERIOD_MS * 1000;
+
+ if (priv->current_plug != PLUG_TYPE_HEADSET) {
+ pr_debug("%s(): Headset is not inserted, ignore removal\n",
+ __func__);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL,
+ 0x08, 0x08);
+ return;
+ }
+
+ usleep_range(generic->t_shutdown_plug_rem,
+ generic->t_shutdown_plug_rem);
+
+ do {
+ bias_value = taiko_codec_sta_dce(codec, 1, true);
+ pr_debug("%s: DCE %d,%d, %d us left\n", __func__, bias_value,
+ taiko_codec_sta_dce_v(codec, 1, bias_value), min_us);
+ if (bias_value < taiko_get_current_v_ins(priv, false)) {
+ pr_debug("%s: checking false removal\n", __func__);
+ msleep(500);
+ removed = !taiko_hs_remove_settle(codec);
+ pr_debug("%s: headset %sactually removed\n", __func__,
+ removed ? "" : "not ");
+ break;
+ }
+ min_us -= priv->mbhc_data.t_dce;
+ } while (min_us > 0);
+
+ if (removed) {
+ /* cancel possiblely running hs detect work */
+ taiko_cancel_hs_detect_plug(priv);
+ /*
+ * If this removal is not false, first check the micbias
+ * switch status and switch it to LDOH if it is already
+ * switched to VDDIO.
+ */
+ taiko_codec_switch_micbias(codec, 0);
+
+ taiko_codec_report_plug(codec, 0, SND_JACK_HEADSET);
+ taiko_codec_cleanup_hs_polling(codec);
+ taiko_codec_enable_hs_detect(codec, 1,
+ MBHC_USE_MB_TRIGGER |
+ MBHC_USE_HPHL_TRIGGER,
+ true);
+ } else {
+ taiko_codec_start_hs_polling(codec);
+ }
+}
+
+static irqreturn_t taiko_hs_remove_irq(int irq, void *data)
+{
+ struct taiko_priv *priv = data;
+ bool vddio;
+ pr_debug("%s: enter, removal interrupt\n", __func__);
+
+ TAIKO_ACQUIRE_LOCK(priv->codec_resource_lock);
+ vddio = (priv->mbhc_data.micb_mv != VDDIO_MICBIAS_MV &&
+ priv->mbhc_micbias_switched);
+ if (vddio)
+ __taiko_codec_switch_micbias(priv->codec, 0, false, true);
+
+ if (priv->mbhc_cfg.gpio)
+ taiko_hs_remove_irq_gpio(priv);
+ else
+ taiko_hs_remove_irq_nogpio(priv);
+
+ /* if driver turned off vddio switch and headset is not removed,
+ * turn on the vddio switch back, if headset is removed then vddio
+ * switch is off by time now and shouldn't be turn on again from here */
+ if (vddio && priv->current_plug == PLUG_TYPE_HEADSET)
+ __taiko_codec_switch_micbias(priv->codec, 1, true, true);
+ TAIKO_RELEASE_LOCK(priv->codec_resource_lock);
+
+ return IRQ_HANDLED;
+}
+
+static void taiko_mbhc_insert_work(struct work_struct *work)
+{
+ struct delayed_work *dwork;
+ struct taiko_priv *taiko;
+ struct snd_soc_codec *codec;
+ struct wcd9xxx *taiko_core;
+
+ dwork = to_delayed_work(work);
+ taiko = container_of(dwork, struct taiko_priv, mbhc_insert_dwork);
+ codec = taiko->codec;
+ taiko_core = dev_get_drvdata(codec->dev->parent);
+
+ pr_debug("%s:\n", __func__);
+
+ /* Turn off both HPH and MIC line schmitt triggers */
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.mbhc_reg, 0x90, 0x00);
+ snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x13, 0x00);
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
+ wcd9xxx_disable_irq_sync(codec->control_data, TAIKO_IRQ_MBHC_INSERTION);
+ taiko_codec_detect_plug_type(codec);
+ wcd9xxx_unlock_sleep(taiko_core);
+}
+
+static void taiko_hs_gpio_handler(struct snd_soc_codec *codec)
+{
+ bool insert;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ bool is_removed = false;
+
+ pr_debug("%s: enter\n", __func__);
+
+ taiko->in_gpio_handler = true;
+ /* Wait here for debounce time */
+ usleep_range(TAIKO_GPIO_IRQ_DEBOUNCE_TIME_US,
+ TAIKO_GPIO_IRQ_DEBOUNCE_TIME_US);
+
+ TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+
+ /* cancel pending button press */
+ if (taiko_cancel_btn_work(taiko))
+ pr_debug("%s: button press is canceled\n", __func__);
+
+ insert = (gpio_get_value_cansleep(taiko->mbhc_cfg.gpio) ==
+ taiko->mbhc_cfg.gpio_level_insert);
+ if ((taiko->current_plug == PLUG_TYPE_NONE) && insert) {
+ taiko->lpi_enabled = false;
+ wmb();
+
+ /* cancel detect plug */
+ taiko_cancel_hs_detect_plug(taiko);
+
+ /* Disable Mic Bias pull down and HPH Switch to GND */
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.ctl_reg, 0x01,
+ 0x00);
+ snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x01, 0x00);
+ taiko_codec_detect_plug_type(codec);
+ } else if ((taiko->current_plug != PLUG_TYPE_NONE) && !insert) {
+ taiko->lpi_enabled = false;
+ wmb();
+
+ /* cancel detect plug */
+ taiko_cancel_hs_detect_plug(taiko);
+
+ if (taiko->current_plug == PLUG_TYPE_HEADPHONE) {
+ taiko_codec_report_plug(codec, 0, SND_JACK_HEADPHONE);
+ is_removed = true;
+ } else if (taiko->current_plug == PLUG_TYPE_GND_MIC_SWAP) {
+ taiko_codec_report_plug(codec, 0, SND_JACK_UNSUPPORTED);
+ is_removed = true;
+ } else if (taiko->current_plug == PLUG_TYPE_HEADSET) {
+ taiko_codec_pause_hs_polling(codec);
+ taiko_codec_cleanup_hs_polling(codec);
+ taiko_codec_report_plug(codec, 0, SND_JACK_HEADSET);
+ is_removed = true;
+ }
+
+ if (is_removed) {
+ /* Enable Mic Bias pull down and HPH Switch to GND */
+ snd_soc_update_bits(codec,
+ taiko->mbhc_bias_regs.ctl_reg, 0x01,
+ 0x01);
+ snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x01,
+ 0x01);
+ /* Make sure mic trigger is turned off */
+ snd_soc_update_bits(codec,
+ taiko->mbhc_bias_regs.ctl_reg,
+ 0x01, 0x01);
+ snd_soc_update_bits(codec,
+ taiko->mbhc_bias_regs.mbhc_reg,
+ 0x90, 0x00);
+ /* Reset MBHC State Machine */
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL,
+ 0x08, 0x08);
+ snd_soc_update_bits(codec, TAIKO_A_CDC_MBHC_CLK_CTL,
+ 0x08, 0x00);
+ /* Turn off override */
+ taiko_turn_onoff_override(codec, false);
+ }
+ }
+
+ taiko->in_gpio_handler = false;
+ TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+ pr_debug("%s: leave\n", __func__);
+}
+
+static irqreturn_t taiko_mechanical_plug_detect_irq(int irq, void *data)
+{
+ int r = IRQ_HANDLED;
+ struct snd_soc_codec *codec = data;
+
+ if (unlikely(wcd9xxx_lock_sleep(codec->control_data) == false)) {
+ pr_warn("%s: failed to hold suspend\n", __func__);
+ r = IRQ_NONE;
+ } else {
+ taiko_hs_gpio_handler(codec);
+ wcd9xxx_unlock_sleep(codec->control_data);
+ }
+
+ return r;
+}
+
+static int taiko_mbhc_init_and_calibrate(struct taiko_priv *taiko)
+{
+ int ret = 0;
+ struct snd_soc_codec *codec = taiko->codec;
+
+ taiko->mbhc_cfg.mclk_cb_fn(codec, 1, false);
+ taiko_mbhc_init(codec);
+ taiko_mbhc_cal(codec);
+ taiko_mbhc_calc_thres(codec);
+ taiko->mbhc_cfg.mclk_cb_fn(codec, 0, false);
+ taiko_codec_calibrate_hs_polling(codec);
+ if (!taiko->mbhc_cfg.gpio) {
+ ret = taiko_codec_enable_hs_detect(codec, 1,
+ MBHC_USE_MB_TRIGGER |
+ MBHC_USE_HPHL_TRIGGER,
+ false);
+
+ if (IS_ERR_VALUE(ret))
+ pr_err("%s: Failed to setup MBHC detection\n",
+ __func__);
+ } else {
+ /* Enable Mic Bias pull down and HPH Switch to GND */
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.ctl_reg,
+ 0x01, 0x01);
+ snd_soc_update_bits(codec, TAIKO_A_MBHC_HPH, 0x01, 0x01);
+ INIT_WORK(&taiko->hs_correct_plug_work,
+ taiko_hs_correct_gpio_plug);
+ }
+
+ if (!IS_ERR_VALUE(ret)) {
+ snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL, 0x10, 0x10);
+ wcd9xxx_enable_irq(codec->control_data,
+ TAIKO_IRQ_HPH_PA_OCPL_FAULT);
+ wcd9xxx_enable_irq(codec->control_data,
+ TAIKO_IRQ_HPH_PA_OCPR_FAULT);
+
+ if (taiko->mbhc_cfg.gpio) {
+ ret = request_threaded_irq(taiko->mbhc_cfg.gpio_irq,
+ NULL,
+ taiko_mechanical_plug_detect_irq,
+ (IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING),
+ "taiko-gpio", codec);
+ if (!IS_ERR_VALUE(ret)) {
+ ret = enable_irq_wake(taiko->mbhc_cfg.gpio_irq);
+ /* Bootup time detection */
+ taiko_hs_gpio_handler(codec);
+ }
+ }
+ }
+
+ return ret;
+}
+
+static void mbhc_fw_read(struct work_struct *work)
+{
+ struct delayed_work *dwork;
+ struct taiko_priv *taiko;
+ struct snd_soc_codec *codec;
+ const struct firmware *fw;
+ int ret = -1, retry = 0;
+
+ dwork = to_delayed_work(work);
+ taiko = container_of(dwork, struct taiko_priv, mbhc_firmware_dwork);
+ codec = taiko->codec;
+
+ while (retry < MBHC_FW_READ_ATTEMPTS) {
+ retry++;
+ pr_info("%s:Attempt %d to request MBHC firmware\n",
+ __func__, retry);
+ ret = request_firmware(&fw, "wcd9320/wcd9320_mbhc.bin",
+ codec->dev);
+
+ if (ret != 0) {
+ usleep_range(MBHC_FW_READ_TIMEOUT,
+ MBHC_FW_READ_TIMEOUT);
+ } else {
+ pr_info("%s: MBHC Firmware read succesful\n", __func__);
+ break;
+ }
+ }
+
+ if (ret != 0) {
+ pr_err("%s: Cannot load MBHC firmware use default cal\n",
+ __func__);
+ } else if (taiko_mbhc_fw_validate(fw) == false) {
+ pr_err("%s: Invalid MBHC cal data size use default cal\n",
+ __func__);
+ release_firmware(fw);
+ } else {
+ taiko->mbhc_cfg.calibration = (void *)fw->data;
+ taiko->mbhc_fw = fw;
+ }
+
+ (void) taiko_mbhc_init_and_calibrate(taiko);
+}
+
+int taiko_hs_detect(struct snd_soc_codec *codec,
+ const struct taiko_mbhc_config *cfg)
+{
+ struct taiko_priv *taiko;
+ int rc = 0;
+
+ if (!codec || !cfg->calibration) {
+ pr_err("Error: no codec or calibration\n");
+ return -EINVAL;
+ }
+
+ if (cfg->mclk_rate != TAIKO_MCLK_RATE_12288KHZ) {
+ if (cfg->mclk_rate == TAIKO_MCLK_RATE_9600KHZ)
+ pr_err("Error: clock rate %dHz is not yet supported\n",
+ cfg->mclk_rate);
+ else
+ pr_err("Error: unsupported clock rate %d\n",
+ cfg->mclk_rate);
+ return -EINVAL;
+ }
+
+ taiko = snd_soc_codec_get_drvdata(codec);
+ taiko->mbhc_cfg = *cfg;
+ taiko->in_gpio_handler = false;
+ taiko->current_plug = PLUG_TYPE_NONE;
+ taiko->lpi_enabled = false;
+ taiko_get_mbhc_micbias_regs(codec, &taiko->mbhc_bias_regs);
+
+ /* Put CFILT in fast mode by default */
+ snd_soc_update_bits(codec, taiko->mbhc_bias_regs.cfilt_ctl,
+ 0x40, TAIKO_CFILT_FAST_MODE);
+ INIT_DELAYED_WORK(&taiko->mbhc_firmware_dwork, mbhc_fw_read);
+ INIT_DELAYED_WORK(&taiko->mbhc_btn_dwork, btn_lpress_fn);
+ INIT_WORK(&taiko->hphlocp_work, hphlocp_off_report);
+ INIT_WORK(&taiko->hphrocp_work, hphrocp_off_report);
+ INIT_DELAYED_WORK(&taiko->mbhc_insert_dwork, taiko_mbhc_insert_work);
+
+ if (!taiko->mbhc_cfg.read_fw_bin)
+ rc = taiko_mbhc_init_and_calibrate(taiko);
+ else
+ schedule_delayed_work(&taiko->mbhc_firmware_dwork,
+ usecs_to_jiffies(MBHC_FW_READ_TIMEOUT));
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(taiko_hs_detect);
+
+static unsigned long slimbus_value;
+
+static irqreturn_t taiko_slimbus_irq(int irq, void *data)
+{
+ struct taiko_priv *priv = data;
+ struct snd_soc_codec *codec = priv->codec;
+ int i, j;
+ u8 val;
+
+ for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++) {
+ slimbus_value = wcd9xxx_interface_reg_read(codec->control_data,
+ TAIKO_SLIM_PGD_PORT_INT_STATUS0 + i);
+ for_each_set_bit(j, &slimbus_value, BITS_PER_BYTE) {
+ val = wcd9xxx_interface_reg_read(codec->control_data,
+ TAIKO_SLIM_PGD_PORT_INT_SOURCE0 + i*8 + j);
+ if (val & 0x1)
+ pr_err_ratelimited(
+ "overflow error on port %x, value %x\n",
+ i*8 + j, val);
+ if (val & 0x2)
+ pr_err_ratelimited(
+ "underflow error on port %x, value %x\n",
+ i*8 + j, val);
+ }
+ wcd9xxx_interface_reg_write(codec->control_data,
+ TAIKO_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int taiko_handle_pdata(struct taiko_priv *taiko)
+{
+ struct snd_soc_codec *codec = taiko->codec;
+ struct wcd9xxx_pdata *pdata = taiko->pdata;
+ int k1, k2, k3, rc = 0;
+ u8 leg_mode = pdata->amic_settings.legacy_mode;
+ u8 txfe_bypass = pdata->amic_settings.txfe_enable;
+ u8 txfe_buff = pdata->amic_settings.txfe_buff;
+ u8 flag = pdata->amic_settings.use_pdata;
+ u8 i = 0, j = 0;
+ u8 val_txfe = 0, value = 0;
+
+ if (!pdata) {
+ rc = -ENODEV;
+ goto done;
+ }
+
+ /* Make sure settings are correct */
+ if ((pdata->micbias.ldoh_v > TAIKO_LDOH_2P85_V) ||
+ (pdata->micbias.bias1_cfilt_sel > TAIKO_CFILT3_SEL) ||
+ (pdata->micbias.bias2_cfilt_sel > TAIKO_CFILT3_SEL) ||
+ (pdata->micbias.bias3_cfilt_sel > TAIKO_CFILT3_SEL) ||
+ (pdata->micbias.bias4_cfilt_sel > TAIKO_CFILT3_SEL)) {
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* figure out k value */
+ k1 = taiko_find_k_value(pdata->micbias.ldoh_v,
+ pdata->micbias.cfilt1_mv);
+ k2 = taiko_find_k_value(pdata->micbias.ldoh_v,
+ pdata->micbias.cfilt2_mv);
+ k3 = taiko_find_k_value(pdata->micbias.ldoh_v,
+ pdata->micbias.cfilt3_mv);
+
+ if (IS_ERR_VALUE(k1) || IS_ERR_VALUE(k2) || IS_ERR_VALUE(k3)) {
+ rc = -EINVAL;
+ goto done;
+ }
+
+ /* Set voltage level and always use LDO */
+ snd_soc_update_bits(codec, TAIKO_A_LDO_H_MODE_1, 0x0C,
+ (pdata->micbias.ldoh_v << 2));
+
+ snd_soc_update_bits(codec, TAIKO_A_MICB_CFILT_1_VAL, 0xFC,
+ (k1 << 2));
+ snd_soc_update_bits(codec, TAIKO_A_MICB_CFILT_2_VAL, 0xFC,
+ (k2 << 2));
+ snd_soc_update_bits(codec, TAIKO_A_MICB_CFILT_3_VAL, 0xFC,
+ (k3 << 2));
+
+ snd_soc_update_bits(codec, TAIKO_A_MICB_1_CTL, 0x60,
+ (pdata->micbias.bias1_cfilt_sel << 5));
+ snd_soc_update_bits(codec, TAIKO_A_MICB_2_CTL, 0x60,
+ (pdata->micbias.bias2_cfilt_sel << 5));
+ snd_soc_update_bits(codec, TAIKO_A_MICB_3_CTL, 0x60,
+ (pdata->micbias.bias3_cfilt_sel << 5));
+ snd_soc_update_bits(codec, taiko->reg_addr.micb_4_ctl, 0x60,
+ (pdata->micbias.bias4_cfilt_sel << 5));
+
+ for (i = 0; i < 6; j++, i += 2) {
+ if (flag & (0x01 << i)) {
+ value = (leg_mode & (0x01 << i)) ? 0x10 : 0x00;
+ val_txfe = (txfe_bypass & (0x01 << i)) ? 0x20 : 0x00;
+ val_txfe = val_txfe |
+ ((txfe_buff & (0x01 << i)) ? 0x10 : 0x00);
+ snd_soc_update_bits(codec, TAIKO_A_TX_1_2_EN + j * 10,
+ 0x10, value);
+ snd_soc_update_bits(codec,
+ TAIKO_A_TX_1_2_TEST_EN + j * 10,
+ 0x30, val_txfe);
+ }
+ if (flag & (0x01 << (i + 1))) {
+ value = (leg_mode & (0x01 << (i + 1))) ? 0x01 : 0x00;
+ val_txfe = (txfe_bypass &
+ (0x01 << (i + 1))) ? 0x02 : 0x00;
+ val_txfe |= (txfe_buff &
+ (0x01 << (i + 1))) ? 0x01 : 0x00;
+ snd_soc_update_bits(codec, TAIKO_A_TX_1_2_EN + j * 10,
+ 0x01, value);
+ snd_soc_update_bits(codec,
+ TAIKO_A_TX_1_2_TEST_EN + j * 10,
+ 0x03, val_txfe);
+ }
+ }
+ if (flag & 0x40) {
+ value = (leg_mode & 0x40) ? 0x10 : 0x00;
+ value = value | ((txfe_bypass & 0x40) ? 0x02 : 0x00);
+ value = value | ((txfe_buff & 0x40) ? 0x01 : 0x00);
+ snd_soc_update_bits(codec, TAIKO_A_TX_7_MBHC_EN,
+ 0x13, value);
+ }
+
+ if (pdata->ocp.use_pdata) {
+ /* not defined in CODEC specification */
+ if (pdata->ocp.hph_ocp_limit == 1 ||
+ pdata->ocp.hph_ocp_limit == 5) {
+ rc = -EINVAL;
+ goto done;
+ }
+ snd_soc_update_bits(codec, TAIKO_A_RX_COM_OCP_CTL,
+ 0x0F, pdata->ocp.num_attempts);
+ snd_soc_write(codec, TAIKO_A_RX_COM_OCP_COUNT,
+ ((pdata->ocp.run_time << 4) | pdata->ocp.wait_time));
+ snd_soc_update_bits(codec, TAIKO_A_RX_HPH_OCP_CTL,
+ 0xE0, (pdata->ocp.hph_ocp_limit << 5));
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+ if (!strncmp(pdata->regulator[i].name, "CDC_VDDA_RX", 11)) {
+ if (pdata->regulator[i].min_uV == 1800000 &&
+ pdata->regulator[i].max_uV == 1800000) {
+ snd_soc_write(codec, TAIKO_A_BIAS_REF_CTL,
+ 0x1C);
+ } else if (pdata->regulator[i].min_uV == 2200000 &&
+ pdata->regulator[i].max_uV == 2200000) {
+ snd_soc_write(codec, TAIKO_A_BIAS_REF_CTL,
+ 0x1E);
+ } else {
+ pr_err("%s: unsupported CDC_VDDA_RX voltage\n"
+ "min %d, max %d\n", __func__,
+ pdata->regulator[i].min_uV,
+ pdata->regulator[i].max_uV);
+ rc = -EINVAL;
+ }
+ break;
+ }
+ }
+done:
+ return rc;
+}
+
+static const struct taiko_reg_mask_val taiko_1_0_reg_defaults[] = {
+
+ /* Taiko 1.1 MICBIAS changes */
+ TAIKO_REG_VAL(TAIKO_A_MICB_1_INT_RBIAS, 0x24),
+ TAIKO_REG_VAL(TAIKO_A_MICB_2_INT_RBIAS, 0x24),
+ TAIKO_REG_VAL(TAIKO_A_MICB_3_INT_RBIAS, 0x24),
+
+ /* Taiko 1.1 HPH changes */
+ TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_PA, 0x57),
+ TAIKO_REG_VAL(TAIKO_A_RX_HPH_BIAS_LDO, 0x56),
+
+ /* Taiko 1.1 EAR PA changes */
+ TAIKO_REG_VAL(TAIKO_A_RX_EAR_BIAS_PA, 0xA6),
+ TAIKO_REG_VAL(TAIKO_A_RX_EAR_GAIN, 0x02),
+ TAIKO_REG_VAL(TAIKO_A_RX_EAR_VCM, 0x03),
+
+
+ /* Taiko 1.1 RX Changes */
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B5_CTL, 0x78),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B5_CTL, 0x78),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B5_CTL, 0x78),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX4_B5_CTL, 0x78),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B5_CTL, 0x78),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B5_CTL, 0x78),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B5_CTL, 0x78),
+
+ /* Taiko 1.1 RX1 and RX2 Changes */
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX1_B6_CTL, 0xA0),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX2_B6_CTL, 0xA0),
+
+ /* Taiko 1.1 RX3 to RX7 Changes */
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX3_B6_CTL, 0x80),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX4_B6_CTL, 0x80),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX5_B6_CTL, 0x80),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX6_B6_CTL, 0x80),
+ TAIKO_REG_VAL(TAIKO_A_CDC_RX7_B6_CTL, 0x80),
+
+};
+
+static void taiko_update_reg_defaults(struct snd_soc_codec *codec)
+{
+ u32 i;
+
+ for (i = 0; i < ARRAY_SIZE(taiko_1_0_reg_defaults); i++)
+ snd_soc_write(codec, taiko_1_0_reg_defaults[i].reg,
+ taiko_1_0_reg_defaults[i].val);
+}
+
+static const struct taiko_reg_mask_val taiko_codec_reg_init_val[] = {
+ /* Initialize current threshold to 350MA
+ * number of wait and run cycles to 4096
+ */
+ {TAIKO_A_RX_HPH_OCP_CTL, 0xE0, 0x60},
+ {TAIKO_A_RX_COM_OCP_COUNT, 0xFF, 0xFF},
+
+ {TAIKO_A_QFUSE_CTL, 0xFF, 0x03},
+
+ /* Initialize gain registers to use register gain */
+ {TAIKO_A_RX_HPH_L_GAIN, 0x10, 0x10},
+ {TAIKO_A_RX_HPH_R_GAIN, 0x10, 0x10},
+ {TAIKO_A_RX_LINE_1_GAIN, 0x10, 0x10},
+ {TAIKO_A_RX_LINE_2_GAIN, 0x10, 0x10},
+ {TAIKO_A_RX_LINE_3_GAIN, 0x10, 0x10},
+ {TAIKO_A_RX_LINE_4_GAIN, 0x10, 0x10},
+
+ /* Initialize mic biases to differential mode */
+ {TAIKO_A_MICB_1_INT_RBIAS, 0x24, 0x24},
+ {TAIKO_A_MICB_2_INT_RBIAS, 0x24, 0x24},
+ {TAIKO_A_MICB_3_INT_RBIAS, 0x24, 0x24},
+
+
+ /* Use 16 bit sample size for TX1 to TX6 */
+ {TAIKO_A_CDC_CONN_TX_SB_B1_CTL, 0x30, 0x20},
+ {TAIKO_A_CDC_CONN_TX_SB_B2_CTL, 0x30, 0x20},
+ {TAIKO_A_CDC_CONN_TX_SB_B3_CTL, 0x30, 0x20},
+ {TAIKO_A_CDC_CONN_TX_SB_B4_CTL, 0x30, 0x20},
+ {TAIKO_A_CDC_CONN_TX_SB_B5_CTL, 0x30, 0x20},
+ {TAIKO_A_CDC_CONN_TX_SB_B6_CTL, 0x30, 0x20},
+
+ /* Use 16 bit sample size for TX7 to TX10 */
+ {TAIKO_A_CDC_CONN_TX_SB_B7_CTL, 0x60, 0x40},
+ {TAIKO_A_CDC_CONN_TX_SB_B8_CTL, 0x60, 0x40},
+ {TAIKO_A_CDC_CONN_TX_SB_B9_CTL, 0x60, 0x40},
+ {TAIKO_A_CDC_CONN_TX_SB_B10_CTL, 0x60, 0x40},
+
+ /* Use 16 bit sample size for RX */
+ {TAIKO_A_CDC_CONN_RX_SB_B1_CTL, 0xFF, 0xAA},
+ {TAIKO_A_CDC_CONN_RX_SB_B2_CTL, 0xFF, 0xAA},
+
+ /*enable HPF filter for TX paths */
+ {TAIKO_A_CDC_TX1_MUX_CTL, 0x8, 0x0},
+ {TAIKO_A_CDC_TX2_MUX_CTL, 0x8, 0x0},
+ {TAIKO_A_CDC_TX3_MUX_CTL, 0x8, 0x0},
+ {TAIKO_A_CDC_TX4_MUX_CTL, 0x8, 0x0},
+ {TAIKO_A_CDC_TX5_MUX_CTL, 0x8, 0x0},
+ {TAIKO_A_CDC_TX6_MUX_CTL, 0x8, 0x0},
+ {TAIKO_A_CDC_TX7_MUX_CTL, 0x8, 0x0},
+ {TAIKO_A_CDC_TX8_MUX_CTL, 0x8, 0x0},
+ {TAIKO_A_CDC_TX9_MUX_CTL, 0x8, 0x0},
+ {TAIKO_A_CDC_TX10_MUX_CTL, 0x8, 0x0},
+
+ /* config Decimator for DMIC CLK_MODE_1(4.8Mhz@9.6Mhz mclk) */
+ {TAIKO_A_CDC_TX1_DMIC_CTL, 0x7, 0x0},
+ {TAIKO_A_CDC_TX2_DMIC_CTL, 0x7, 0x0},
+ {TAIKO_A_CDC_TX3_DMIC_CTL, 0x7, 0x0},
+ {TAIKO_A_CDC_TX4_DMIC_CTL, 0x7, 0x0},
+ {TAIKO_A_CDC_TX5_DMIC_CTL, 0x7, 0x0},
+ {TAIKO_A_CDC_TX6_DMIC_CTL, 0x7, 0x0},
+ {TAIKO_A_CDC_TX7_DMIC_CTL, 0x7, 0x0},
+ {TAIKO_A_CDC_TX8_DMIC_CTL, 0x7, 0x0},
+ {TAIKO_A_CDC_TX9_DMIC_CTL, 0x7, 0x0},
+ {TAIKO_A_CDC_TX10_DMIC_CTL, 0x7, 0x0},
+
+ /* config DMIC clk to CLK_MODE_1 (4.8Mhz@9.6Mhz mclk) */
+ {TAIKO_A_CDC_CLK_DMIC_B1_CTL, 0xEE, 0x0},
+ {TAIKO_A_CDC_CLK_DMIC_B2_CTL, 0xEE, 0x0},
+};
+
+static void taiko_codec_init_reg(struct snd_soc_codec *codec)
+{
+ u32 i;
+
+ for (i = 0; i < ARRAY_SIZE(taiko_codec_reg_init_val); i++)
+ snd_soc_update_bits(codec, taiko_codec_reg_init_val[i].reg,
+ taiko_codec_reg_init_val[i].mask,
+ taiko_codec_reg_init_val[i].val);
+}
+
+static void taiko_update_reg_address(struct taiko_priv *priv)
+{
+ struct taiko_reg_address *reg_addr = &priv->reg_addr;
+ reg_addr->micb_4_mbhc = TAIKO_A_MICB_4_MBHC;
+ reg_addr->micb_4_int_rbias = TAIKO_A_MICB_4_INT_RBIAS;
+ reg_addr->micb_4_ctl = TAIKO_A_MICB_4_CTL;
+
+}
+
+#ifdef CONFIG_DEBUG_FS
+static int codec_debug_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t codec_debug_write(struct file *filp,
+ const char __user *ubuf, size_t cnt, loff_t *ppos)
+{
+ char lbuf[32];
+ char *buf;
+ int rc;
+ struct taiko_priv *taiko = filp->private_data;
+
+ if (cnt > sizeof(lbuf) - 1)
+ return -EINVAL;
+
+ rc = copy_from_user(lbuf, ubuf, cnt);
+ if (rc)
+ return -EFAULT;
+
+ lbuf[cnt] = '\0';
+ buf = (char *)lbuf;
+ taiko->no_mic_headset_override = (*strsep(&buf, " ") == '0') ?
+ false : true;
+ return rc;
+}
+
+static ssize_t codec_mbhc_debug_read(struct file *file, char __user *buf,
+ size_t count, loff_t *pos)
+{
+ const int size = 768;
+ char buffer[size];
+ int n = 0;
+ struct taiko_priv *taiko = file->private_data;
+ struct snd_soc_codec *codec = taiko->codec;
+ const struct mbhc_internal_cal_data *p = &taiko->mbhc_data;
+ const s16 v_ins_hu_cur = taiko_get_current_v_ins(taiko, true);
+ const s16 v_ins_h_cur = taiko_get_current_v_ins(taiko, false);
+
+ n = scnprintf(buffer, size - n, "dce_z = %x(%dmv)\n", p->dce_z,
+ taiko_codec_sta_dce_v(codec, 1, p->dce_z));
+ n += scnprintf(buffer + n, size - n, "dce_mb = %x(%dmv)\n",
+ p->dce_mb, taiko_codec_sta_dce_v(codec, 1, p->dce_mb));
+ n += scnprintf(buffer + n, size - n, "sta_z = %x(%dmv)\n",
+ p->sta_z, taiko_codec_sta_dce_v(codec, 0, p->sta_z));
+ n += scnprintf(buffer + n, size - n, "sta_mb = %x(%dmv)\n",
+ p->sta_mb, taiko_codec_sta_dce_v(codec, 0, p->sta_mb));
+ n += scnprintf(buffer + n, size - n, "t_dce = %x\n", p->t_dce);
+ n += scnprintf(buffer + n, size - n, "t_sta = %x\n", p->t_sta);
+ n += scnprintf(buffer + n, size - n, "micb_mv = %dmv\n",
+ p->micb_mv);
+ n += scnprintf(buffer + n, size - n, "v_ins_hu = %x(%dmv)%s\n",
+ p->v_ins_hu,
+ taiko_codec_sta_dce_v(codec, 0, p->v_ins_hu),
+ p->v_ins_hu == v_ins_hu_cur ? "*" : "");
+ n += scnprintf(buffer + n, size - n, "v_ins_h = %x(%dmv)%s\n",
+ p->v_ins_h, taiko_codec_sta_dce_v(codec, 1, p->v_ins_h),
+ p->v_ins_h == v_ins_h_cur ? "*" : "");
+ n += scnprintf(buffer + n, size - n, "adj_v_ins_hu = %x(%dmv)%s\n",
+ p->adj_v_ins_hu,
+ taiko_codec_sta_dce_v(codec, 0, p->adj_v_ins_hu),
+ p->adj_v_ins_hu == v_ins_hu_cur ? "*" : "");
+ n += scnprintf(buffer + n, size - n, "adj_v_ins_h = %x(%dmv)%s\n",
+ p->adj_v_ins_h,
+ taiko_codec_sta_dce_v(codec, 1, p->adj_v_ins_h),
+ p->adj_v_ins_h == v_ins_h_cur ? "*" : "");
+ n += scnprintf(buffer + n, size - n, "v_b1_hu = %x(%dmv)\n",
+ p->v_b1_hu, taiko_codec_sta_dce_v(codec, 0, p->v_b1_hu));
+ n += scnprintf(buffer + n, size - n, "v_b1_h = %x(%dmv)\n",
+ p->v_b1_h, taiko_codec_sta_dce_v(codec, 1, p->v_b1_h));
+ n += scnprintf(buffer + n, size - n, "v_b1_huc = %x(%dmv)\n",
+ p->v_b1_huc,
+ taiko_codec_sta_dce_v(codec, 1, p->v_b1_huc));
+ n += scnprintf(buffer + n, size - n, "v_brh = %x(%dmv)\n",
+ p->v_brh, taiko_codec_sta_dce_v(codec, 1, p->v_brh));
+ n += scnprintf(buffer + n, size - n, "v_brl = %x(%dmv)\n", p->v_brl,
+ taiko_codec_sta_dce_v(codec, 0, p->v_brl));
+ n += scnprintf(buffer + n, size - n, "v_no_mic = %x(%dmv)\n",
+ p->v_no_mic,
+ taiko_codec_sta_dce_v(codec, 0, p->v_no_mic));
+ n += scnprintf(buffer + n, size - n, "npoll = %d\n", p->npoll);
+ n += scnprintf(buffer + n, size - n, "nbounce_wait = %d\n",
+ p->nbounce_wait);
+ n += scnprintf(buffer + n, size - n, "v_inval_ins_low = %d\n",
+ p->v_inval_ins_low);
+ n += scnprintf(buffer + n, size - n, "v_inval_ins_high = %d\n",
+ p->v_inval_ins_high);
+ if (taiko->mbhc_cfg.gpio)
+ n += scnprintf(buffer + n, size - n, "GPIO insert = %d\n",
+ taiko_hs_gpio_level_remove(taiko));
+ buffer[n] = 0;
+
+ return simple_read_from_buffer(buf, count, pos, buffer, n);
+}
+
+static const struct file_operations codec_debug_ops = {
+ .open = codec_debug_open,
+ .write = codec_debug_write,
+};
+
+static const struct file_operations codec_mbhc_debug_ops = {
+ .open = codec_debug_open,
+ .read = codec_mbhc_debug_read,
+};
+#endif
+
+static int taiko_codec_probe(struct snd_soc_codec *codec)
+{
+ struct wcd9xxx *control;
+ struct taiko_priv *taiko;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+ int ret = 0;
+ int i;
+ int ch_cnt;
+
+ codec->control_data = dev_get_drvdata(codec->dev->parent);
+ control = codec->control_data;
+
+ taiko = kzalloc(sizeof(struct taiko_priv), GFP_KERNEL);
+ if (!taiko) {
+ dev_err(codec->dev, "Failed to allocate private data\n");
+ return -ENOMEM;
+ }
+ for (i = 0 ; i < NUM_DECIMATORS; i++) {
+ tx_hpf_work[i].taiko = taiko;
+ tx_hpf_work[i].decimator = i + 1;
+ INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
+ tx_hpf_corner_freq_callback);
+ }
+
+ /* Make sure mbhc micbias register addresses are zeroed out */
+ memset(&taiko->mbhc_bias_regs, 0,
+ sizeof(struct mbhc_micbias_regs));
+ taiko->mbhc_micbias_switched = false;
+
+ /* Make sure mbhc intenal calibration data is zeroed out */
+ memset(&taiko->mbhc_data, 0,
+ sizeof(struct mbhc_internal_cal_data));
+ taiko->mbhc_data.t_sta_dce = DEFAULT_DCE_STA_WAIT;
+ taiko->mbhc_data.t_dce = DEFAULT_DCE_WAIT;
+ taiko->mbhc_data.t_sta = DEFAULT_STA_WAIT;
+ snd_soc_codec_set_drvdata(codec, taiko);
+
+ taiko->mclk_enabled = false;
+ taiko->bandgap_type = TAIKO_BANDGAP_OFF;
+ taiko->clock_active = false;
+ taiko->config_mode_active = false;
+ taiko->mbhc_polling_active = false;
+ taiko->mbhc_fake_ins_start = 0;
+ taiko->no_mic_headset_override = false;
+ taiko->hs_polling_irq_prepared = false;
+ mutex_init(&taiko->codec_resource_lock);
+ taiko->codec = codec;
+ taiko->mbhc_state = MBHC_STATE_NONE;
+ taiko->mbhc_last_resume = 0;
+ for (i = 0; i < COMPANDER_MAX; i++) {
+ taiko->comp_enabled[i] = 0;
+ taiko->comp_fs[i] = COMPANDER_FS_48KHZ;
+ }
+ taiko->pdata = dev_get_platdata(codec->dev->parent);
+ taiko->intf_type = wcd9xxx_get_intf_type();
+ taiko->aux_pga_cnt = 0;
+ taiko->aux_l_gain = 0x1F;
+ taiko->aux_r_gain = 0x1F;
+ taiko_update_reg_address(taiko);
+ taiko_update_reg_defaults(codec);
+ taiko_codec_init_reg(codec);
+ ret = taiko_handle_pdata(taiko);
+ if (IS_ERR_VALUE(ret)) {
+ pr_err("%s: bad pdata\n", __func__);
+ goto err_pdata;
+ }
+
+ if (taiko->intf_type == WCD9XXX_INTERFACE_TYPE_I2C) {
+ snd_soc_dapm_new_controls(dapm, taiko_dapm_i2s_widgets,
+ ARRAY_SIZE(taiko_dapm_i2s_widgets));
+ snd_soc_dapm_add_routes(dapm, audio_i2s_map,
+ ARRAY_SIZE(audio_i2s_map));
+ }
+
+ snd_soc_dapm_sync(dapm);
+
+ ret = wcd9xxx_request_irq(codec->control_data, TAIKO_IRQ_MBHC_INSERTION,
+ taiko_hs_insert_irq, "Headset insert detect", taiko);
+ if (ret) {
+ pr_err("%s: Failed to request irq %d\n", __func__,
+ TAIKO_IRQ_MBHC_INSERTION);
+ goto err_insert_irq;
+ }
+ wcd9xxx_disable_irq(codec->control_data, TAIKO_IRQ_MBHC_INSERTION);
+
+ ret = wcd9xxx_request_irq(codec->control_data, TAIKO_IRQ_MBHC_REMOVAL,
+ taiko_hs_remove_irq, "Headset remove detect", taiko);
+ if (ret) {
+ pr_err("%s: Failed to request irq %d\n", __func__,
+ TAIKO_IRQ_MBHC_REMOVAL);
+ goto err_remove_irq;
+ }
+
+ ret = wcd9xxx_request_irq(codec->control_data, TAIKO_IRQ_MBHC_POTENTIAL,
+ taiko_dce_handler, "DC Estimation detect", taiko);
+ if (ret) {
+ pr_err("%s: Failed to request irq %d\n", __func__,
+ TAIKO_IRQ_MBHC_POTENTIAL);
+ goto err_potential_irq;
+ }
+
+ ret = wcd9xxx_request_irq(codec->control_data, TAIKO_IRQ_MBHC_RELEASE,
+ taiko_release_handler, "Button Release detect", taiko);
+ if (ret) {
+ pr_err("%s: Failed to request irq %d\n", __func__,
+ TAIKO_IRQ_MBHC_RELEASE);
+ goto err_release_irq;
+ }
+
+ ret = wcd9xxx_request_irq(codec->control_data, TAIKO_IRQ_SLIMBUS,
+ taiko_slimbus_irq, "SLIMBUS Slave", taiko);
+ if (ret) {
+ pr_err("%s: Failed to request irq %d\n", __func__,
+ TAIKO_IRQ_SLIMBUS);
+ goto err_slimbus_irq;
+ }
+
+ for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++)
+ wcd9xxx_interface_reg_write(codec->control_data,
+ TAIKO_SLIM_PGD_PORT_INT_EN0 + i, 0xFF);
+
+ ret = wcd9xxx_request_irq(codec->control_data,
+ TAIKO_IRQ_HPH_PA_OCPL_FAULT, taiko_hphl_ocp_irq,
+ "HPH_L OCP detect", taiko);
+ if (ret) {
+ pr_err("%s: Failed to request irq %d\n", __func__,
+ TAIKO_IRQ_HPH_PA_OCPL_FAULT);
+ goto err_hphl_ocp_irq;
+ }
+ wcd9xxx_disable_irq(codec->control_data, TAIKO_IRQ_HPH_PA_OCPL_FAULT);
+
+ ret = wcd9xxx_request_irq(codec->control_data,
+ TAIKO_IRQ_HPH_PA_OCPR_FAULT, taiko_hphr_ocp_irq,
+ "HPH_R OCP detect", taiko);
+ if (ret) {
+ pr_err("%s: Failed to request irq %d\n", __func__,
+ TAIKO_IRQ_HPH_PA_OCPR_FAULT);
+ goto err_hphr_ocp_irq;
+ }
+ wcd9xxx_disable_irq(codec->control_data, TAIKO_IRQ_HPH_PA_OCPR_FAULT);
+ for (i = 0; i < ARRAY_SIZE(taiko_dai); i++) {
+ switch (taiko_dai[i].id) {
+ case AIF1_PB:
+ ch_cnt = taiko_dai[i].playback.channels_max;
+ break;
+ case AIF1_CAP:
+ ch_cnt = taiko_dai[i].capture.channels_max;
+ break;
+ case AIF2_PB:
+ ch_cnt = taiko_dai[i].playback.channels_max;
+ break;
+ case AIF2_CAP:
+ ch_cnt = taiko_dai[i].capture.channels_max;
+ break;
+ case AIF3_PB:
+ ch_cnt = taiko_dai[i].playback.channels_max;
+ break;
+ case AIF3_CAP:
+ ch_cnt = taiko_dai[i].capture.channels_max;
+ break;
+ default:
+ continue;
+ }
+ taiko->dai[i].ch_num = kzalloc((sizeof(unsigned int)*
+ ch_cnt), GFP_KERNEL);
+ }
+
+#ifdef CONFIG_DEBUG_FS
+ if (ret == 0) {
+ taiko->debugfs_poke =
+ debugfs_create_file("TRRS", S_IFREG | S_IRUGO, NULL, taiko,
+ &codec_debug_ops);
+ taiko->debugfs_mbhc =
+ debugfs_create_file("taiko_mbhc", S_IFREG | S_IRUGO,
+ NULL, taiko, &codec_mbhc_debug_ops);
+ }
+#endif
+ codec->ignore_pmdown_time = 1;
+ return ret;
+
+err_hphr_ocp_irq:
+ wcd9xxx_free_irq(codec->control_data,
+ TAIKO_IRQ_HPH_PA_OCPL_FAULT, taiko);
+err_hphl_ocp_irq:
+ wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_SLIMBUS, taiko);
+err_slimbus_irq:
+ wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_MBHC_RELEASE, taiko);
+err_release_irq:
+ wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_MBHC_POTENTIAL, taiko);
+err_potential_irq:
+ wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_MBHC_REMOVAL, taiko);
+err_remove_irq:
+ wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_MBHC_INSERTION, taiko);
+err_insert_irq:
+err_pdata:
+ mutex_destroy(&taiko->codec_resource_lock);
+ kfree(taiko);
+ return ret;
+}
+static int taiko_codec_remove(struct snd_soc_codec *codec)
+{
+ int i;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_SLIMBUS, taiko);
+ wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_MBHC_RELEASE, taiko);
+ wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_MBHC_POTENTIAL, taiko);
+ wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_MBHC_REMOVAL, taiko);
+ wcd9xxx_free_irq(codec->control_data, TAIKO_IRQ_MBHC_INSERTION, taiko);
+ TAIKO_ACQUIRE_LOCK(taiko->codec_resource_lock);
+ taiko_codec_disable_clock_block(codec);
+ TAIKO_RELEASE_LOCK(taiko->codec_resource_lock);
+ taiko_codec_enable_bandgap(codec, TAIKO_BANDGAP_OFF);
+ if (taiko->mbhc_fw)
+ release_firmware(taiko->mbhc_fw);
+ for (i = 0; i < ARRAY_SIZE(taiko_dai); i++)
+ kfree(taiko->dai[i].ch_num);
+ mutex_destroy(&taiko->codec_resource_lock);
+#ifdef CONFIG_DEBUG_FS
+ debugfs_remove(taiko->debugfs_poke);
+ debugfs_remove(taiko->debugfs_mbhc);
+#endif
+ kfree(taiko);
+ return 0;
+}
+static struct snd_soc_codec_driver soc_codec_dev_taiko = {
+ .probe = taiko_codec_probe,
+ .remove = taiko_codec_remove,
+
+ .read = taiko_read,
+ .write = taiko_write,
+
+ .readable_register = taiko_readable,
+ .volatile_register = taiko_volatile,
+
+ .reg_cache_size = TAIKO_CACHE_SIZE,
+ .reg_cache_default = taiko_reg_defaults,
+ .reg_word_size = 1,
+
+ .controls = taiko_snd_controls,
+ .num_controls = ARRAY_SIZE(taiko_snd_controls),
+ .dapm_widgets = taiko_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(taiko_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
+#ifdef CONFIG_PM
+static int taiko_suspend(struct device *dev)
+{
+ dev_dbg(dev, "%s: system suspend\n", __func__);
+ return 0;
+}
+
+static int taiko_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct taiko_priv *taiko = platform_get_drvdata(pdev);
+ dev_dbg(dev, "%s: system resume\n", __func__);
+ taiko->mbhc_last_resume = jiffies;
+ return 0;
+}
+
+static const struct dev_pm_ops taiko_pm_ops = {
+ .suspend = taiko_suspend,
+ .resume = taiko_resume,
+};
+#endif
+
+static int __devinit taiko_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+ ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_taiko,
+ taiko_dai, ARRAY_SIZE(taiko_dai));
+ else if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_I2C)
+ ret = snd_soc_register_codec(&pdev->dev, &soc_codec_dev_taiko,
+ taiko_i2s_dai, ARRAY_SIZE(taiko_i2s_dai));
+ return ret;
+}
+static int __devexit taiko_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_codec(&pdev->dev);
+ return 0;
+}
+static struct platform_driver taiko_codec_driver = {
+ .probe = taiko_probe,
+ .remove = taiko_remove,
+ .driver = {
+ .name = "taiko_codec",
+ .owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &taiko_pm_ops,
+#endif
+ },
+};
+
+static int __init taiko_codec_init(void)
+{
+ return platform_driver_register(&taiko_codec_driver);
+}
+
+static void __exit taiko_codec_exit(void)
+{
+ platform_driver_unregister(&taiko_codec_driver);
+}
+
+module_init(taiko_codec_init);
+module_exit(taiko_codec_exit);
+
+MODULE_DESCRIPTION("Taiko codec driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/wcd9320.h b/sound/soc/codecs/wcd9320.h
new file mode 100644
index 0000000..739ab17
--- /dev/null
+++ b/sound/soc/codecs/wcd9320.h
@@ -0,0 +1,252 @@
+/* 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 WCD9320_H
+#define WCD9320_H
+
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
+
+#define TAIKO_NUM_REGISTERS 0x400
+#define TAIKO_MAX_REGISTER (TAIKO_NUM_REGISTERS-1)
+#define TAIKO_CACHE_SIZE TAIKO_NUM_REGISTERS
+
+#define TAIKO_REG_VAL(reg, val) {reg, 0, val}
+
+#define DEFAULT_DCE_STA_WAIT 55
+#define DEFAULT_DCE_WAIT 60000
+#define DEFAULT_STA_WAIT 5000
+#define VDDIO_MICBIAS_MV 1800
+
+#define STA 0
+#define DCE 1
+
+#define TAIKO_JACK_BUTTON_MASK (SND_JACK_BTN_0 | SND_JACK_BTN_1 | \
+ SND_JACK_BTN_2 | SND_JACK_BTN_3 | \
+ SND_JACK_BTN_4 | SND_JACK_BTN_5 | \
+ SND_JACK_BTN_6 | SND_JACK_BTN_7)
+
+extern const u8 taiko_reg_readable[TAIKO_CACHE_SIZE];
+extern const u8 taiko_reg_defaults[TAIKO_CACHE_SIZE];
+
+enum taiko_micbias_num {
+ TAIKO_MICBIAS1 = 0,
+ TAIKO_MICBIAS2,
+ TAIKO_MICBIAS3,
+ TAIKO_MICBIAS4,
+};
+
+enum taiko_pid_current {
+ TAIKO_PID_MIC_2P5_UA,
+ TAIKO_PID_MIC_5_UA,
+ TAIKO_PID_MIC_10_UA,
+ TAIKO_PID_MIC_20_UA,
+};
+
+struct taiko_reg_mask_val {
+ u16 reg;
+ u8 mask;
+ u8 val;
+};
+
+enum taiko_mbhc_clk_freq {
+ TAIKO_MCLK_12P2MHZ = 0,
+ TAIKO_MCLK_9P6MHZ,
+ TAIKO_NUM_CLK_FREQS,
+};
+
+enum taiko_mbhc_analog_pwr_cfg {
+ TAIKO_ANALOG_PWR_COLLAPSED = 0,
+ TAIKO_ANALOG_PWR_ON,
+ TAIKO_NUM_ANALOG_PWR_CONFIGS,
+};
+
+enum taiko_mbhc_btn_det_mem {
+ TAIKO_BTN_DET_V_BTN_LOW,
+ TAIKO_BTN_DET_V_BTN_HIGH,
+ TAIKO_BTN_DET_N_READY,
+ TAIKO_BTN_DET_N_CIC,
+ TAIKO_BTN_DET_GAIN
+};
+
+struct taiko_mbhc_general_cfg {
+ u8 t_ldoh;
+ u8 t_bg_fast_settle;
+ u8 t_shutdown_plug_rem;
+ u8 mbhc_nsa;
+ u8 mbhc_navg;
+ u8 v_micbias_l;
+ u8 v_micbias;
+ u8 mbhc_reserved;
+ u16 settle_wait;
+ u16 t_micbias_rampup;
+ u16 t_micbias_rampdown;
+ u16 t_supply_bringup;
+} __packed;
+
+struct taiko_mbhc_plug_detect_cfg {
+ u32 mic_current;
+ u32 hph_current;
+ u16 t_mic_pid;
+ u16 t_ins_complete;
+ u16 t_ins_retry;
+ u16 v_removal_delta;
+ u8 micbias_slow_ramp;
+ u8 reserved0;
+ u8 reserved1;
+ u8 reserved2;
+} __packed;
+
+struct taiko_mbhc_plug_type_cfg {
+ u8 av_detect;
+ u8 mono_detect;
+ u8 num_ins_tries;
+ u8 reserved0;
+ s16 v_no_mic;
+ s16 v_av_min;
+ s16 v_av_max;
+ s16 v_hs_min;
+ s16 v_hs_max;
+ u16 reserved1;
+} __packed;
+
+
+struct taiko_mbhc_btn_detect_cfg {
+ s8 c[8];
+ u8 nc;
+ u8 n_meas;
+ u8 mbhc_nsc;
+ u8 n_btn_meas;
+ u8 n_btn_con;
+ u8 num_btn;
+ u8 reserved0;
+ u8 reserved1;
+ u16 t_poll;
+ u16 t_bounce_wait;
+ u16 t_rel_timeout;
+ s16 v_btn_press_delta_sta;
+ s16 v_btn_press_delta_cic;
+ u16 t_btn0_timeout;
+ s16 _v_btn_low[0]; /* v_btn_low[num_btn] */
+ s16 _v_btn_high[0]; /* v_btn_high[num_btn] */
+ u8 _n_ready[TAIKO_NUM_CLK_FREQS];
+ u8 _n_cic[TAIKO_NUM_CLK_FREQS];
+ u8 _gain[TAIKO_NUM_CLK_FREQS];
+} __packed;
+
+struct taiko_mbhc_imped_detect_cfg {
+ u8 _hs_imped_detect;
+ u8 _n_rload;
+ u8 _hph_keep_on;
+ u8 _repeat_rload_calc;
+ u16 _t_dac_ramp_time;
+ u16 _rhph_high;
+ u16 _rhph_low;
+ u16 _rload[0]; /* rload[n_rload] */
+ u16 _alpha[0]; /* alpha[n_rload] */
+ u16 _beta[3];
+} __packed;
+
+struct taiko_mbhc_config {
+ struct snd_soc_jack *headset_jack;
+ struct snd_soc_jack *button_jack;
+ bool read_fw_bin;
+ /* void* calibration contains:
+ * struct taiko_mbhc_general_cfg generic;
+ * struct taiko_mbhc_plug_detect_cfg plug_det;
+ * struct taiko_mbhc_plug_type_cfg plug_type;
+ * struct taiko_mbhc_btn_detect_cfg btn_det;
+ * struct taiko_mbhc_imped_detect_cfg imped_det;
+ * Note: various size depends on btn_det->num_btn
+ */
+ void *calibration;
+ enum taiko_micbias_num micbias;
+ int (*mclk_cb_fn) (struct snd_soc_codec*, int, bool);
+ unsigned int mclk_rate;
+ unsigned int gpio;
+ unsigned int gpio_irq;
+ int gpio_level_insert;
+ /* swap_gnd_mic returns true if extern GND/MIC swap switch toggled */
+ bool (*swap_gnd_mic) (struct snd_soc_codec *);
+};
+
+extern int taiko_hs_detect(struct snd_soc_codec *codec,
+ const struct taiko_mbhc_config *cfg);
+
+struct anc_header {
+ u32 reserved[3];
+ u32 num_anc_slots;
+};
+
+extern int taiko_mclk_enable(struct snd_soc_codec *codec, int mclk_enable,
+ bool dapm);
+
+extern void *taiko_mbhc_cal_btn_det_mp(const struct taiko_mbhc_btn_detect_cfg
+ *btn_det,
+ const enum taiko_mbhc_btn_det_mem mem);
+
+#define TAIKO_MBHC_CAL_SIZE(buttons, rload) ( \
+ sizeof(enum taiko_micbias_num) + \
+ sizeof(struct taiko_mbhc_general_cfg) + \
+ sizeof(struct taiko_mbhc_plug_detect_cfg) + \
+ ((sizeof(s16) + sizeof(s16)) * buttons) + \
+ sizeof(struct taiko_mbhc_plug_type_cfg) + \
+ sizeof(struct taiko_mbhc_btn_detect_cfg) + \
+ sizeof(struct taiko_mbhc_imped_detect_cfg) + \
+ ((sizeof(u16) + sizeof(u16)) * rload) \
+ )
+
+#define TAIKO_MBHC_CAL_GENERAL_PTR(cali) ( \
+ (struct taiko_mbhc_general_cfg *) cali)
+#define TAIKO_MBHC_CAL_PLUG_DET_PTR(cali) ( \
+ (struct taiko_mbhc_plug_detect_cfg *) \
+ &(TAIKO_MBHC_CAL_GENERAL_PTR(cali)[1]))
+#define TAIKO_MBHC_CAL_PLUG_TYPE_PTR(cali) ( \
+ (struct taiko_mbhc_plug_type_cfg *) \
+ &(TAIKO_MBHC_CAL_PLUG_DET_PTR(cali)[1]))
+#define TAIKO_MBHC_CAL_BTN_DET_PTR(cali) ( \
+ (struct taiko_mbhc_btn_detect_cfg *) \
+ &(TAIKO_MBHC_CAL_PLUG_TYPE_PTR(cali)[1]))
+#define TAIKO_MBHC_CAL_IMPED_DET_PTR(cali) ( \
+ (struct taiko_mbhc_imped_detect_cfg *) \
+ (((void *)&TAIKO_MBHC_CAL_BTN_DET_PTR(cali)[1]) + \
+ (TAIKO_MBHC_CAL_BTN_DET_PTR(cali)->num_btn * \
+ (sizeof(TAIKO_MBHC_CAL_BTN_DET_PTR(cali)->_v_btn_low[0]) + \
+ sizeof(TAIKO_MBHC_CAL_BTN_DET_PTR(cali)->_v_btn_high[0])))) \
+ )
+
+/* minimum size of calibration data assuming there is only one button and
+ * one rload.
+ */
+#define TAIKO_MBHC_CAL_MIN_SIZE ( \
+ sizeof(struct taiko_mbhc_general_cfg) + \
+ sizeof(struct taiko_mbhc_plug_detect_cfg) + \
+ sizeof(struct taiko_mbhc_plug_type_cfg) + \
+ sizeof(struct taiko_mbhc_btn_detect_cfg) + \
+ sizeof(struct taiko_mbhc_imped_detect_cfg) + \
+ (sizeof(u16) * 2))
+
+#define TAIKO_MBHC_CAL_BTN_SZ(cfg_ptr) ( \
+ sizeof(struct taiko_mbhc_btn_detect_cfg) + \
+ (cfg_ptr->num_btn * (sizeof(cfg_ptr->_v_btn_low[0]) + \
+ sizeof(cfg_ptr->_v_btn_high[0]))))
+
+#define TAIKO_MBHC_CAL_IMPED_MIN_SZ ( \
+ sizeof(struct taiko_mbhc_imped_detect_cfg) + \
+ sizeof(u16) * 2)
+
+#define TAIKO_MBHC_CAL_IMPED_SZ(cfg_ptr) ( \
+ sizeof(struct taiko_mbhc_imped_detect_cfg) + \
+ (cfg_ptr->_n_rload * (sizeof(cfg_ptr->_rload[0]) + \
+ sizeof(cfg_ptr->_alpha[0]))))
+
+#endif
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index 8c45f8a..a7fd38b 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -126,6 +126,8 @@
.gpio_level_insert = 1,
};
+static struct mutex cdc_mclk_mutex;
+
static void msm_enable_ext_spk_amp_gpio(u32 spk_amp_gpio)
{
int ret = 0;
@@ -373,35 +375,42 @@
static int msm_enable_codec_ext_clk(struct snd_soc_codec *codec, int enable,
bool dapm)
{
+ int r = 0;
pr_debug("%s: enable = %d\n", __func__, enable);
+
+ mutex_lock(&cdc_mclk_mutex);
if (enable) {
clk_users++;
pr_debug("%s: clk_users = %d\n", __func__, clk_users);
- if (clk_users != 1)
- return 0;
-
- if (codec_clk) {
- clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
- clk_prepare_enable(codec_clk);
- tabla_mclk_enable(codec, 1, dapm);
- } else {
- pr_err("%s: Error setting Tabla MCLK\n", __func__);
- clk_users--;
- return -EINVAL;
+ if (clk_users == 1) {
+ if (codec_clk) {
+ clk_set_rate(codec_clk, TABLA_EXT_CLK_RATE);
+ clk_prepare_enable(codec_clk);
+ tabla_mclk_enable(codec, 1, dapm);
+ } else {
+ pr_err("%s: Error setting Tabla MCLK\n",
+ __func__);
+ clk_users--;
+ r = -EINVAL;
+ }
}
} else {
- pr_debug("%s: clk_users = %d\n", __func__, clk_users);
- if (clk_users == 0)
- return 0;
- clk_users--;
- if (!clk_users) {
- pr_debug("%s: disabling MCLK. clk_users = %d\n",
+ if (clk_users > 0) {
+ clk_users--;
+ pr_debug("%s: clk_users = %d\n", __func__, clk_users);
+ if (clk_users == 0) {
+ pr_debug("%s: disabling MCLK. clk_users = %d\n",
__func__, clk_users);
- tabla_mclk_enable(codec, 0, dapm);
- clk_disable_unprepare(codec_clk);
+ tabla_mclk_enable(codec, 0, dapm);
+ clk_disable_unprepare(codec_clk);
+ }
+ } else {
+ pr_err("%s: Error releasing Tabla MCLK\n", __func__);
+ r = -EINVAL;
}
}
- return 0;
+ mutex_unlock(&cdc_mclk_mutex);
+ return r;
}
static int msm_mclk_event(struct snd_soc_dapm_widget *w,
@@ -2008,6 +2017,7 @@
} else
msm_headset_gpios_configured = 1;
+ mutex_init(&cdc_mclk_mutex);
return ret;
}
@@ -2024,6 +2034,7 @@
if (mbhc_cfg.gpio)
gpio_free(mbhc_cfg.gpio);
kfree(mbhc_cfg.calibration);
+ mutex_destroy(&cdc_mclk_mutex);
}
module_exit(msm_audio_exit);
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index 0995300..4ecd8df 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -1062,7 +1062,8 @@
.cpu_dai_name = "MultiMedia1",
.platform_name = "msm-pcm-dsp",
.dynamic = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.ignore_suspend = 1,
@@ -1075,7 +1076,8 @@
.cpu_dai_name = "MultiMedia2",
.platform_name = "msm-multi-ch-pcm-dsp",
.dynamic = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.ignore_suspend = 1,
@@ -1088,7 +1090,8 @@
.cpu_dai_name = "CS-VOICE",
.platform_name = "msm-pcm-voice",
.dynamic = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ignore_suspend = 1,
.ignore_pmdown_time = 1, /* this dainlink has playback support */
@@ -1102,7 +1105,8 @@
.cpu_dai_name = "VoIP",
.platform_name = "msm-voip-dsp",
.dynamic = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.ignore_suspend = 1,
@@ -1110,12 +1114,13 @@
.be_id = MSM_FRONTEND_DAI_VOIP,
},
{
- .name = "MSM8960 LPA",
- .stream_name = "LPA",
+ .name = "MSM8960 Media3",
+ .stream_name = "MultiMedia3",
.cpu_dai_name = "MultiMedia3",
- .platform_name = "msm-pcm-lpa",
+ .platform_name = "msm-pcm-dsp",
.dynamic = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.ignore_suspend = 1,
@@ -1129,7 +1134,8 @@
.cpu_dai_name = "SLIMBUS0_HOSTLESS",
.platform_name = "msm-pcm-hostless",
.dynamic = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ignore_suspend = 1,
.ignore_pmdown_time = 1, /* this dainlink has playback support */
@@ -1142,7 +1148,8 @@
.cpu_dai_name = "INT_FM_HOSTLESS",
.platform_name = "msm-pcm-hostless",
.dynamic = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ignore_suspend = 1,
.ignore_pmdown_time = 1, /* this dainlink has playback support */
@@ -1173,12 +1180,13 @@
.codec_name = "snd-soc-dummy",
},
{
- .name = "MSM8960 Compr",
- .stream_name = "COMPR",
+ .name = "MSM8960 Compr1",
+ .stream_name = "COMPR1",
.cpu_dai_name = "MultiMedia4",
.platform_name = "msm-compr-dsp",
.dynamic = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.ignore_suspend = 1,
@@ -1191,7 +1199,8 @@
.cpu_dai_name = "VOICE_STUB",
.platform_name = "msm-pcm-hostless",
.dynamic = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ignore_suspend = 1,
.ignore_pmdown_time = 1, /* this dainlink has playback support */
@@ -1205,7 +1214,8 @@
.cpu_dai_name = "HDMI_HOSTLESS",
.platform_name = "msm-pcm-hostless",
.dynamic = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ignore_suspend = 1,
.ignore_pmdown_time = 1, /* this dainlink has playback support */
@@ -1219,7 +1229,8 @@
.cpu_dai_name = "MI2S_TX_HOSTLESS",
.platform_name = "msm-pcm-hostless",
.dynamic = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ignore_suspend = 1,
.codec_dai_name = "snd-soc-dummy-dai",
@@ -1232,13 +1243,70 @@
.cpu_dai_name = "SEC_I2S_RX_HOSTLESS",
.platform_name = "msm-pcm-hostless",
.dynamic = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE, SND_SOC_DPCM_TRIGGER_BESPOKE},
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ignore_suspend = 1,
.ignore_pmdown_time = 1, /* this dainlink has playback support */
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
},
+ {
+ .name = "MSM8960 Media5",
+ .stream_name = "MultiMedia5",
+ .cpu_dai_name = "MultiMedia5",
+ .platform_name = "msm-multi-ch-pcm-dsp",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE,
+ SND_SOC_DPCM_TRIGGER_BESPOKE},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1, /* this dailink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5
+ },
+ {
+ .name = "MSM8960 Media6",
+ .stream_name = "MultiMedia6",
+ .cpu_dai_name = "MultiMedia6",
+ .platform_name = "msm-multi-ch-pcm-dsp",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE,
+ SND_SOC_DPCM_TRIGGER_BESPOKE},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1, /* this dailink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA6
+ },
+ {
+ .name = "MSM8960 Compr2",
+ .stream_name = "COMPR2",
+ .cpu_dai_name = "MultiMedia7",
+ .platform_name = "msm-compr-dsp",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE,
+ SND_SOC_DPCM_TRIGGER_BESPOKE},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1, /* this dailink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA7,
+ },
+ {
+ .name = "MSM8960 Compr3",
+ .stream_name = "COMPR3",
+ .cpu_dai_name = "MultiMedia8",
+ .platform_name = "msm-compr-dsp",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_BESPOKE,
+ SND_SOC_DPCM_TRIGGER_BESPOKE},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1, /* this dailink has playback support */
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
+ },
/* Backend DAI Links */
{
.name = LPASS_BE_SLIMBUS_0_RX,
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index c8d3a71c..6e190b2 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -55,7 +55,7 @@
SNDRV_PCM_RATE_KNOT),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 6,
.rate_min = 8000,
.rate_max = 48000,
},
@@ -157,7 +157,7 @@
SNDRV_PCM_RATE_KNOT),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 6,
.rate_min = 8000,
.rate_max = 48000,
},
@@ -172,13 +172,69 @@
SNDRV_PCM_RATE_KNOT),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 6,
.rate_min = 8000,
.rate_max = 48000,
},
.ops = &msm_fe_Multimedia_dai_ops,
.name = "MultiMedia4",
},
+ {
+ .playback = {
+ .stream_name = "MultiMedia5 Playback",
+ .rates = (SNDRV_PCM_RATE_8000_48000 |
+ SNDRV_PCM_RATE_KNOT),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 6,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_fe_Multimedia_dai_ops,
+ .name = "MultiMedia5",
+ },
+ {
+ .playback = {
+ .stream_name = "MultiMedia6 Playback",
+ .rates = (SNDRV_PCM_RATE_8000_48000 |
+ SNDRV_PCM_RATE_KNOT),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 6,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_fe_Multimedia_dai_ops,
+ .name = "MultiMedia6",
+ },
+ {
+ .playback = {
+ .stream_name = "MultiMedia7 Playback",
+ .rates = (SNDRV_PCM_RATE_8000_48000 |
+ SNDRV_PCM_RATE_KNOT),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 6,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_fe_Multimedia_dai_ops,
+ .name = "MultiMedia7",
+ },
+ {
+ .playback = {
+ .stream_name = "MultiMedia8 Playback",
+ .rates = (SNDRV_PCM_RATE_8000_48000 |
+ SNDRV_PCM_RATE_KNOT),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 6,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_fe_Multimedia_dai_ops,
+ .name = "MultiMedia8",
+ },
/* FE DAIs created for hostless operation purpose */
{
.playback = {
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 357a53b..4e1ce52 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -191,6 +191,15 @@
{INVALID_SESSION, INVALID_SESSION},
/* MULTIMEDIA4 */
{INVALID_SESSION, INVALID_SESSION},
+ /* MULTIMEDIA5 */
+ {INVALID_SESSION, INVALID_SESSION},
+ /* MULTIMEDIA6 */
+ {INVALID_SESSION, INVALID_SESSION},
+ /* MULTIMEDIA7*/
+ {INVALID_SESSION, INVALID_SESSION},
+ /* MULTIMEDIA8 */
+ {INVALID_SESSION, INVALID_SESSION},
+
};
static uint8_t is_be_dai_extproc(int be_dai)
@@ -1030,6 +1039,18 @@
SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_PRI_I2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_PRI_I2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_PRI_I2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_PRI_I2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_PRI_I2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new sec_i2s_rx_mixer_controls[] = {
@@ -1045,6 +1066,18 @@
SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SEC_I2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SEC_I2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SEC_I2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SEC_I2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SEC_I2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
@@ -1060,6 +1093,18 @@
SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SLIMBUS_0_RX,
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new mi2s_rx_mixer_controls[] = {
@@ -1075,6 +1120,18 @@
SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_MI2S_RX,
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_MI2S_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
@@ -1090,6 +1147,18 @@
SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_HDMI_RX,
MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer,
msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
+ SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer,
+ msm_routing_put_audio_mixer),
};
/* incall music delivery mixer */
static const struct snd_kcontrol_new incall_music_delivery_mixer_controls[] = {
@@ -1339,6 +1408,9 @@
SOC_SINGLE_EXT("VoLTE", MSM_BACKEND_DAI_HDMI_RX,
MSM_FRONTEND_DAI_VOLTE, 1, 0, msm_routing_get_voice_mixer,
msm_routing_put_voice_mixer),
+ SOC_SINGLE_EXT("Voice Stub", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
};
static const struct snd_kcontrol_new stub_rx_mixer_controls[] = {
@@ -1795,6 +1867,10 @@
SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
@@ -2001,24 +2077,40 @@
{"PRI_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"PRI_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
{"PRI_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"PRI_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+ {"PRI_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+ {"PRI_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+ {"PRI_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
{"PRI_I2S_RX", NULL, "PRI_RX Audio Mixer"},
{"SEC_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"SEC_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"SEC_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
{"SEC_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"SEC_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+ {"SEC_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+ {"SEC_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+ {"SEC_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
{"SEC_I2S_RX", NULL, "SEC_RX Audio Mixer"},
{"SLIMBUS_0_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
{"SLIMBUS_0_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
{"SLIMBUS_0_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
{"SLIMBUS_0_RX Audio Mixer", "MultiMedia4", "MM_DL4"},
+ {"SLIMBUS_0_RX Audio Mixer", "MultiMedia5", "MM_DL5"},
+ {"SLIMBUS_0_RX Audio Mixer", "MultiMedia6", "MM_DL6"},
+ {"SLIMBUS_0_RX Audio Mixer", "MultiMedia7", "MM_DL7"},
+ {"SLIMBUS_0_RX Audio Mixer", "MultiMedia8", "MM_DL8"},
{"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Audio Mixer"},
{"HDMI Mixer", "MultiMedia1", "MM_DL1"},
{"HDMI Mixer", "MultiMedia2", "MM_DL2"},
{"HDMI Mixer", "MultiMedia3", "MM_DL3"},
{"HDMI Mixer", "MultiMedia4", "MM_DL4"},
+ {"HDMI Mixer", "MultiMedia5", "MM_DL5"},
+ {"HDMI Mixer", "MultiMedia6", "MM_DL6"},
+ {"HDMI Mixer", "MultiMedia7", "MM_DL7"},
+ {"HDMI Mixer", "MultiMedia8", "MM_DL8"},
{"HDMI", NULL, "HDMI Mixer"},
/* incall */
@@ -2224,6 +2316,8 @@
{"BE_OUT", NULL, "PCM_RX"},
{"PCM_TX", NULL, "BE_IN"},
{"BE_OUT", NULL, "SLIMBUS_3_RX"},
+ {"BE_OUT", NULL, "STUB_RX"},
+ {"STUB_TX", NULL, "BE_IN"},
};
static int msm_pcm_routing_hw_params(struct snd_pcm_substream *substream,
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index 3065861..d1230ad 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -56,6 +56,10 @@
MSM_FRONTEND_DAI_MULTIMEDIA2,
MSM_FRONTEND_DAI_MULTIMEDIA3,
MSM_FRONTEND_DAI_MULTIMEDIA4,
+ MSM_FRONTEND_DAI_MULTIMEDIA5,
+ MSM_FRONTEND_DAI_MULTIMEDIA6,
+ MSM_FRONTEND_DAI_MULTIMEDIA7,
+ MSM_FRONTEND_DAI_MULTIMEDIA8,
MSM_FRONTEND_DAI_CS_VOICE,
MSM_FRONTEND_DAI_VOIP,
MSM_FRONTEND_DAI_AFE_RX,
@@ -65,8 +69,8 @@
MSM_FRONTEND_DAI_MAX,
};
-#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA4 + 1)
-#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA4
+#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA8 + 1)
+#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA8
enum {
MSM_BACKEND_DAI_PRI_I2S_RX = 0,