Merge "msm: dma: use ADM security domain 1 on 8064" into msm-3.0
diff --git a/arch/arm/configs/fsm9xxx-perf_defconfig b/arch/arm/configs/fsm9xxx-perf_defconfig
index 60d8a32..b6bc4f1 100644
--- a/arch/arm/configs/fsm9xxx-perf_defconfig
+++ b/arch/arm/configs/fsm9xxx-perf_defconfig
@@ -139,7 +139,6 @@
# CONFIG_USB_SUPPORT is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
-# CONFIG_LEDS_MSM_PMIC is not set
CONFIG_SWITCH=y
CONFIG_SWITCH_GPIO=y
CONFIG_RTC_CLASS=y
diff --git a/arch/arm/configs/fsm9xxx_defconfig b/arch/arm/configs/fsm9xxx_defconfig
index 6913409..dd9797a 100644
--- a/arch/arm/configs/fsm9xxx_defconfig
+++ b/arch/arm/configs/fsm9xxx_defconfig
@@ -137,7 +137,6 @@
# CONFIG_USB_SUPPORT is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
-# CONFIG_LEDS_MSM_PMIC is not set
CONFIG_SWITCH=y
CONFIG_SWITCH_GPIO=y
CONFIG_RTC_CLASS=y
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 4322baf..162fc04 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -157,8 +157,9 @@
CONFIG_BT_HCIUART_IBS=y
CONFIG_BT_MSM_SLEEP=y
CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_WEXT is not set
CONFIG_RFKILL=y
-CONFIG_RFKILL_PM=y
CONFIG_MTD=y
CONFIG_MTD_TESTS=m
CONFIG_MTD_CMDLINE_PARTS=y
@@ -184,8 +185,6 @@
CONFIG_SMSC911X=y
# CONFIG_NETDEV_10000 is not set
CONFIG_LIBRA_SDIOIF=m
-CONFIG_CFG80211=y
-CONFIG_CFG80211_WEXT=n
# CONFIG_INPUT_MOUSEDEV is not set
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=m
@@ -194,7 +193,6 @@
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C=y
-CONFIG_SYNA_MULTI_TOUCH=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index be8ade5..d19fa3d 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -155,8 +155,9 @@
CONFIG_BT_HCIUART_IBS=y
CONFIG_BT_MSM_SLEEP=y
CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_WEXT is not set
CONFIG_RFKILL=y
-CONFIG_RFKILL_PM=y
CONFIG_MTD=y
CONFIG_MTD_TESTS=m
CONFIG_MTD_CMDLINE_PARTS=y
@@ -182,8 +183,6 @@
CONFIG_SMSC911X=y
# CONFIG_NETDEV_10000 is not set
CONFIG_LIBRA_SDIOIF=m
-CONFIG_CFG80211=y
-CONFIG_CFG80211_WEXT=n
# CONFIG_INPUT_MOUSEDEV is not set
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_EVBUG=m
@@ -192,7 +191,6 @@
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH=y
CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C=y
-CONFIG_SYNA_MULTI_TOUCH=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
diff --git a/arch/arm/configs/msm7630-perf_defconfig b/arch/arm/configs/msm7630-perf_defconfig
index 202d117..56710d7 100644
--- a/arch/arm/configs/msm7630-perf_defconfig
+++ b/arch/arm/configs/msm7630-perf_defconfig
@@ -71,7 +71,6 @@
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
-CONFIG_INET_DIAG=y
CONFIG_IPV6=y
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -173,9 +172,10 @@
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_IBS=y
CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_WEXT is not set
# CONFIG_WIRELESS_EXT_SYSFS is not set
CONFIG_RFKILL=y
-CONFIG_RFKILL_PM=y
CONFIG_MTD=y
CONFIG_MTD_TESTS=m
CONFIG_MTD_CMDLINE_PARTS=y
@@ -208,8 +208,6 @@
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
CONFIG_LIBRA_SDIOIF=m
-CONFIG_CFG80211=y
-CONFIG_CFG80211_WEXT=n
CONFIG_SLIP=y
CONFIG_SLIP_COMPRESSED=y
CONFIG_SLIP_MODE_SLIP6=y
@@ -326,7 +324,6 @@
CONFIG_MMC_MSM_SDC2_8_BIT_SUPPORT=y
CONFIG_MMC_MSM_SDC3_SUPPORT=y
CONFIG_MMC_MSM_SDC4_SUPPORT=y
-# CONFIG_LEDS_MSM_PMIC is not set
CONFIG_LEDS_PMIC8058=y
CONFIG_SWITCH=y
CONFIG_SWITCH_GPIO=y
diff --git a/arch/arm/configs/msm7630_defconfig b/arch/arm/configs/msm7630_defconfig
index bc944d0..115ce98 100644
--- a/arch/arm/configs/msm7630_defconfig
+++ b/arch/arm/configs/msm7630_defconfig
@@ -70,7 +70,6 @@
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
-CONFIG_INET_DIAG=y
CONFIG_IPV6=y
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -172,9 +171,10 @@
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_IBS=y
CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_WEXT is not set
# CONFIG_WIRELESS_EXT_SYSFS is not set
CONFIG_RFKILL=y
-CONFIG_RFKILL_PM=y
CONFIG_MTD=y
CONFIG_MTD_TESTS=m
CONFIG_MTD_CMDLINE_PARTS=y
@@ -207,8 +207,6 @@
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
CONFIG_LIBRA_SDIOIF=m
-CONFIG_CFG80211=y
-CONFIG_CFG80211_WEXT=n
CONFIG_SLIP=y
CONFIG_SLIP_COMPRESSED=y
CONFIG_SLIP_MODE_SLIP6=y
diff --git a/arch/arm/configs/msm8660-perf_defconfig b/arch/arm/configs/msm8660-perf_defconfig
index d377460..51c64d3 100644
--- a/arch/arm/configs/msm8660-perf_defconfig
+++ b/arch/arm/configs/msm8660-perf_defconfig
@@ -104,7 +104,6 @@
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
-CONFIG_INET_DIAG=y
CONFIG_IPV6=y
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -212,9 +211,10 @@
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_IBS=y
CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_WEXT is not set
# CONFIG_WIRELESS_EXT_SYSFS is not set
CONFIG_RFKILL=y
-CONFIG_RFKILL_PM=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_MISC_DEVICES=y
@@ -249,8 +249,6 @@
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
CONFIG_LIBRA_SDIOIF=m
-CONFIG_CFG80211=y
-CONFIG_CFG80211_WEXT=n
CONFIG_PPP=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_DEFLATE=y
@@ -379,7 +377,6 @@
CONFIG_MMC_MSM_SDC4_SUPPORT=y
CONFIG_MMC_MSM_SDC5_SUPPORT=y
CONFIG_LEDS_GPIO=y
-# CONFIG_LEDS_MSM_PMIC is not set
CONFIG_LEDS_PMIC8058=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
diff --git a/arch/arm/configs/msm8660_defconfig b/arch/arm/configs/msm8660_defconfig
index 2569f82..e8708f3 100644
--- a/arch/arm/configs/msm8660_defconfig
+++ b/arch/arm/configs/msm8660_defconfig
@@ -95,7 +95,6 @@
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_LRO is not set
-CONFIG_INET_DIAG=y
CONFIG_IPV6=y
CONFIG_IPV6_PRIVACY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -203,9 +202,10 @@
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_IBS=y
CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=y
+# CONFIG_CFG80211_WEXT is not set
# CONFIG_WIRELESS_EXT_SYSFS is not set
CONFIG_RFKILL=y
-CONFIG_RFKILL_PM=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_MISC_DEVICES=y
@@ -242,8 +242,6 @@
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
CONFIG_LIBRA_SDIOIF=m
-CONFIG_CFG80211=y
-CONFIG_CFG80211_WEXT=n
CONFIG_PPP=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_DEFLATE=y
@@ -366,7 +364,6 @@
CONFIG_MMC_MSM_SDC4_SUPPORT=y
CONFIG_MMC_MSM_SDC5_SUPPORT=y
CONFIG_LEDS_GPIO=y
-# CONFIG_LEDS_MSM_PMIC is not set
CONFIG_LEDS_PMIC8058=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index 26d54f9..4275140 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -41,6 +41,7 @@
# CONFIG_MSM_PROC_COMM is not set
CONFIG_MSM_SMD=y
CONFIG_MSM_SMD_PKG4=y
+CONFIG_MSM_BAM_DMUX=y
CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
@@ -62,16 +63,35 @@
CONFIG_VFP=y
CONFIG_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+CONFIG_IPV6=y
+# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET6_XFRM_MODE_BEET is not set
+# CONFIG_IPV6_SIT is not set
+# CONFIG_ANDROID_PARANOID_NETWORK is not set
+CONFIG_CFG80211=y
CONFIG_MTD=y
CONFIG_MTD_TESTS=m
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
-CONFIG_PM=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_MISC_DEVICES=y
# CONFIG_ANDROID_PMEM is not set
+CONFIG_NETDEVICES=y
+CONFIG_HOSTAP=m
+# CONFIG_MSM_RMNET is not set
+CONFIG_MSM_RMNET_BAM=y
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
@@ -99,16 +119,10 @@
CONFIG_SPI_SPIDEV=m
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
-CONFIG_HWMON=y
CONFIG_SENSORS_PM8XXX_ADC=y
CONFIG_THERMAL=y
CONFIG_THERMAL_TSENS8960=y
CONFIG_MFD_PM8018_CORE=y
-CONFIG_MFD_PM8XXX_PWM=y
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_PM8XXX=y
-# CONFIG_LEDS_MSM_PMIC is not set
CONFIG_REGULATOR=y
CONFIG_REGULATOR_GPIO=y
# CONFIG_HID_SUPPORT is not set
@@ -116,56 +130,21 @@
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_CI13XXX_MSM=y
CONFIG_USB_G_ANDROID=y
-CONFIG_SWITCH=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-CONFIG_IPV6=y
-# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET6_XFRM_MODE_BEET is not set
-# CONFIG_IPV6_SIT is not set
-# CONFIG_ANDROID_PARANOID_NETWORK is not set
-# CONFIG_WIRELESS is not set
CONFIG_MMC=y
-# CONFIG_MMC_DEBUG is not set
CONFIG_MMC_PERF_PROFILING=y
CONFIG_MMC_UNSAFE_RESUME=y
-# CONFIG_MMC_CLKGATE is not set
CONFIG_MMC_EMBEDDED_SDIO=y
CONFIG_MMC_PARANOID_SD_INIT=y
-
-#
-# MMC/SD/SDIO Card Drivers
-#
-CONFIG_MMC_BLOCK=y
CONFIG_MMC_BLOCK_MINORS=32
# CONFIG_MMC_BLOCK_BOUNCE is not set
-# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set
-# CONFIG_SDIO_UART is not set
-# CONFIG_MMC_TEST is not set
-
-#
-# MMC/SD/SDIO Host Controller Drivers
-#
-# CONFIG_MMC_SDHCI is not set
CONFIG_MMC_MSM=y
CONFIG_MMC_MSM_SDIO_SUPPORT=y
CONFIG_MMC_MSM_CARD_HW_DETECTION=y
-CONFIG_MMC_MSM_SDC1_SUPPORT=y
-# CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT is not set
-CONFIG_MMC_MSM_SDC2_SUPPORT=y
-# CONFIG_MMC_MSM_SDC2_8_BIT_SUPPORT is not set
-# CONFIG_MMC_MSM_SDC3_SUPPORT is not set
-# CONFIG_MMC_MSM_SDC4_SUPPORT is not set
-# CONFIG_MMC_MSM_SDC5_SUPPORT is not set
CONFIG_MMC_MSM_SPS_SUPPORT=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_PM8XXX=y
+CONFIG_SWITCH=y
CONFIG_RTC_CLASS=y
# CONFIG_RTC_INTF_ALARM is not set
# CONFIG_RTC_DRV_MSM is not set
@@ -206,29 +185,8 @@
CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_TWOFISH=y
CONFIG_CRYPTO_DEFLATE=y
-CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_DEV_QCRYPTO=m
CONFIG_CRYPTO_DEV_QCE=m
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
CONFIG_LIBCRC32C=y
-
-CONFIG_WIRELESS=y
-CONFIG_WEXT_CORE=y
-CONFIG_WEXT_PROC=y
-CONFIG_CFG80211=y
-CONFIG_CFG80211_WEXT=y
-CONFIG_WIRELESS_EXT_SYSFS=y
-CONFIG_LIB80211=m
-CONFIG_NETDEVICES=y
-CONFIG_WLAN=y
-# CONFIG_MSM_RMNET is not set
-CONFIG_MSM_BAM_DMUX=y
-CONFIG_MSM_RMNET_BAM=y
-CONFIG_HOSTAP=m
-CONFIG_WIRELESS_EXT=y
-CONFIG_WEXT_SPY=y
-CONFIG_WEXT_PRIV=y
-CONFIG_LIB80211_CRYPT_WEP=m
-CONFIG_LIB80211_CRYPT_CCMP=m
-CONFIG_LIB80211_CRYPT_TKIP=m
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index a17c476..f3ae47e 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -176,6 +176,8 @@
select MIGRATION
select ARCH_MEMORY_PROBE
select ARCH_MEMORY_REMOVE
+ select DONT_RESERVE_FROM_MOVABLE_ZONE
+ select MSM_ULTRASOUND
config ARCH_APQ8064
bool "APQ8064"
@@ -1768,6 +1770,12 @@
Enable HW audio support in QDSP6.
QDSP6 can support HW encoder & decoder and audio processing
+config MSM_ULTRASOUND
+ bool "MSM ultrasound support"
+ depends on MSM_AUDIO_QDSP6
+ help
+ Enable support for qdsp6/ultrasound.
+
config MSM_RPC_VIBRATOR
bool "RPC based MSM Vibrator Support"
depends on MSM_ONCRPCROUTER
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index eef1a43..b63f1a7 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -653,6 +653,7 @@
&msm_device_sps,
&msm9615_device_tsens,
&msm_device_nand,
+ &msm_device_bam_dmux,
&msm_rpm_device,
#ifdef CONFIG_HW_RANDOM_MSM
&msm_device_rng,
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index 5df1700..9fa13e5 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -2550,7 +2550,7 @@
}
/* Sample clock for 'tcxo4_ticks' reference clock ticks. */
-static u32 run_measurement(unsigned tcxo4_ticks)
+static unsigned long run_measurement(unsigned tcxo4_ticks)
{
/* TCXO4_CNT_EN and RINGOSC_CNT_EN register values. */
u32 reg_val_enable = readl_relaxed(MISC_CLK_CTL_BASE_REG) | 0x3;
@@ -2573,7 +2573,7 @@
/* Perform a hardware rate measurement for a given clock.
FOR DEBUG USE ONLY: Measurements take ~15 ms! */
-static unsigned measure_clk_get_rate(struct clk *clk)
+static unsigned long measure_clk_get_rate(struct clk *clk)
{
unsigned long flags;
u32 regval, prph_web_reg_old;
@@ -2626,7 +2626,7 @@
return -EINVAL;
}
-static unsigned measure_clk_get_rate(struct clk *clk)
+static unsigned long measure_clk_get_rate(struct clk *clk)
{
return 0;
}
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 8d90d57..6521537 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -2934,7 +2934,7 @@
struct pix_rdi_clk {
bool enabled;
- unsigned cur_rate;
+ unsigned long cur_rate;
void __iomem *const s_reg;
u32 s_mask;
@@ -2951,7 +2951,7 @@
return container_of(clk, struct pix_rdi_clk, c);
}
-static int pix_rdi_clk_set_rate(struct clk *c, unsigned rate)
+static int pix_rdi_clk_set_rate(struct clk *c, unsigned long rate)
{
int ret, i;
u32 reg;
@@ -3011,7 +3011,7 @@
return 0;
}
-static unsigned pix_rdi_clk_get_rate(struct clk *c)
+static unsigned long pix_rdi_clk_get_rate(struct clk *c)
{
return to_pix_rdi_clk(c)->cur_rate;
}
@@ -3982,7 +3982,7 @@
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
-static unsigned hdmi_pll_clk_get_rate(struct clk *clk)
+static unsigned long hdmi_pll_clk_get_rate(struct clk *clk)
{
return hdmi_pll_get_rate();
}
@@ -4970,7 +4970,7 @@
/* Perform a hardware rate measurement for a given clock.
FOR DEBUG USE ONLY: Measurements take ~15 ms! */
-static unsigned measure_clk_get_rate(struct clk *c)
+static unsigned long measure_clk_get_rate(struct clk *c)
{
unsigned long flags;
u32 pdm_reg_backup, ringosc_reg_backup;
@@ -5023,7 +5023,7 @@
return -EINVAL;
}
-static unsigned measure_clk_get_rate(struct clk *clk)
+static unsigned long measure_clk_get_rate(struct clk *clk)
{
return 0;
}
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index c5d3d1d..6707757 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3466,7 +3466,7 @@
/* Perform a hardware rate measurement for a given clock.
FOR DEBUG USE ONLY: Measurements take ~15 ms! */
-static unsigned measure_clk_get_rate(struct clk *c)
+static unsigned long measure_clk_get_rate(struct clk *c)
{
unsigned long flags;
u32 pdm_reg_backup, ringosc_reg_backup;
@@ -3520,7 +3520,7 @@
return -EINVAL;
}
-static unsigned measure_clk_get_rate(struct clk *clk)
+static unsigned long measure_clk_get_rate(struct clk *clk)
{
return 0;
}
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index d2a1df1..8ff9725 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -1406,7 +1406,7 @@
}
/* Sample clock for 'ticks' reference clock ticks. */
-static u32 run_measurement(unsigned ticks)
+static unsigned long run_measurement(unsigned ticks)
{
/* Stop counters and set the XO4 counter start value. */
writel_relaxed(ticks, RINGOSC_TCXO_CTL_REG);
@@ -1430,7 +1430,7 @@
/* Perform a hardware rate measurement for a given clock.
FOR DEBUG USE ONLY: Measurements take ~15 ms! */
-static unsigned measure_clk_get_rate(struct clk *c)
+static unsigned long measure_clk_get_rate(struct clk *c)
{
unsigned long flags;
u32 pdm_reg_backup, ringosc_reg_backup;
@@ -1483,7 +1483,7 @@
return -EINVAL;
}
-static unsigned measure_clk_get_rate(struct clk *clk)
+static unsigned long measure_clk_get_rate(struct clk *clk)
{
return 0;
}
diff --git a/arch/arm/mach-msm/clock-dummy.c b/arch/arm/mach-msm/clock-dummy.c
index 1798a3c..feef984 100644
--- a/arch/arm/mach-msm/clock-dummy.c
+++ b/arch/arm/mach-msm/clock-dummy.c
@@ -17,17 +17,17 @@
return 0;
}
-static int dummy_clk_set_rate(struct clk *clk, unsigned rate)
+static int dummy_clk_set_rate(struct clk *clk, unsigned long rate)
{
return 0;
}
-static int dummy_clk_set_min_rate(struct clk *clk, unsigned rate)
+static int dummy_clk_set_min_rate(struct clk *clk, unsigned long rate)
{
return 0;
}
-static int dummy_clk_set_max_rate(struct clk *clk, unsigned rate)
+static int dummy_clk_set_max_rate(struct clk *clk, unsigned long rate)
{
return 0;
}
@@ -37,12 +37,12 @@
return 0;
}
-static unsigned dummy_clk_get_rate(struct clk *clk)
+static unsigned long dummy_clk_get_rate(struct clk *clk)
{
return 0;
}
-static long dummy_clk_round_rate(struct clk *clk, unsigned rate)
+static long dummy_clk_round_rate(struct clk *clk, unsigned long rate)
{
return rate;
}
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 7489ea7..c1cfb55 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -508,7 +508,7 @@
}
/* Set a clock to an exact rate. */
-int rcg_clk_set_rate(struct clk *c, unsigned rate)
+int rcg_clk_set_rate(struct clk *c, unsigned long rate)
{
struct rcg_clk *clk = to_rcg_clk(c);
struct clk_freq_tbl *nf;
@@ -524,7 +524,7 @@
}
/* Set a clock to a rate greater than some minimum. */
-int rcg_clk_set_min_rate(struct clk *c, unsigned rate)
+int rcg_clk_set_min_rate(struct clk *c, unsigned long rate)
{
struct rcg_clk *clk = to_rcg_clk(c);
struct clk_freq_tbl *nf;
@@ -540,7 +540,7 @@
}
/* Get the currently-set rate of a clock in Hz. */
-unsigned rcg_clk_get_rate(struct clk *c)
+unsigned long rcg_clk_get_rate(struct clk *c)
{
struct rcg_clk *clk = to_rcg_clk(c);
unsigned long flags;
@@ -567,7 +567,7 @@
}
/* Return a supported rate that's at least the specified rate. */
-long rcg_clk_round_rate(struct clk *c, unsigned rate)
+long rcg_clk_round_rate(struct clk *c, unsigned long rate)
{
struct rcg_clk *clk = to_rcg_clk(c);
struct clk_freq_tbl *f;
@@ -673,7 +673,7 @@
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
-static unsigned pll_vote_clk_get_rate(struct clk *clk)
+static unsigned long pll_vote_clk_get_rate(struct clk *clk)
{
struct pll_vote_clk *pll = to_pll_vote_clk(clk);
return pll->rate;
@@ -753,7 +753,7 @@
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
-static unsigned pll_clk_get_rate(struct clk *clk)
+static unsigned long pll_clk_get_rate(struct clk *clk)
{
struct pll_clk *pll = to_pll_clk(clk);
return pll->rate;
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 9887bb1..16a9955 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -143,12 +143,12 @@
int rcg_clk_enable(struct clk *clk);
void rcg_clk_disable(struct clk *clk);
-int rcg_clk_set_rate(struct clk *clk, unsigned rate);
-int rcg_clk_set_min_rate(struct clk *clk, unsigned rate);
-unsigned rcg_clk_get_rate(struct clk *clk);
+int rcg_clk_set_rate(struct clk *clk, unsigned long rate);
+int rcg_clk_set_min_rate(struct clk *clk, unsigned long rate);
+unsigned long rcg_clk_get_rate(struct clk *clk);
int rcg_clk_list_rate(struct clk *clk, unsigned n);
int rcg_clk_is_enabled(struct clk *clk);
-long rcg_clk_round_rate(struct clk *clk, unsigned rate);
+long rcg_clk_round_rate(struct clk *clk, unsigned long rate);
struct clk *rcg_clk_get_parent(struct clk *c);
int rcg_clk_handoff(struct clk *c);
@@ -167,7 +167,7 @@
return container_of(clk, struct fixed_clk, c);
}
-static inline unsigned fixed_clk_get_rate(struct clk *clk)
+static inline unsigned long fixed_clk_get_rate(struct clk *clk)
{
struct fixed_clk *f = to_fixed_clk(clk);
return f->rate;
diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c
index f7f3666..79fe662 100644
--- a/arch/arm/mach-msm/clock-pcom.c
+++ b/arch/arm/mach-msm/clock-pcom.c
@@ -74,28 +74,29 @@
return pc_clk_reset(id, action);
}
-static int pc_clk_set_rate(struct clk *clk, unsigned rate)
+static int pc_clk_set_rate(struct clk *clk, unsigned long rate)
{
/* The rate _might_ be rounded off to the nearest KHz value by the
* remote function. So a return value of 0 doesn't necessarily mean
* that the exact rate was set successfully.
*/
+ unsigned r = rate;
int id = to_pcom_clk(clk)->id;
- int rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate);
+ int rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &r);
if (rc < 0)
return rc;
else
return (int)id < 0 ? -EINVAL : 0;
}
-static int pc_clk_set_min_rate(struct clk *clk, unsigned rate)
+static int pc_clk_set_min_rate(struct clk *clk, unsigned long rate)
{
int rc;
int id = to_pcom_clk(clk)->id;
bool ignore_error = (cpu_is_msm7x27() && id == P_EBI1_CLK &&
rate >= INT_MAX);
-
- rc = msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &rate);
+ unsigned r = rate;
+ rc = msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &r);
if (rc < 0)
return rc;
else if (ignore_error)
@@ -104,10 +105,11 @@
return (int)id < 0 ? -EINVAL : 0;
}
-static int pc_clk_set_max_rate(struct clk *clk, unsigned rate)
+static int pc_clk_set_max_rate(struct clk *clk, unsigned long rate)
{
int id = to_pcom_clk(clk)->id;
- int rc = msm_proc_comm(PCOM_CLKCTL_RPC_MAX_RATE, &id, &rate);
+ unsigned r = rate;
+ int rc = msm_proc_comm(PCOM_CLKCTL_RPC_MAX_RATE, &id, &r);
if (rc < 0)
return rc;
else
@@ -124,17 +126,18 @@
return (int)id < 0 ? -EINVAL : 0;
}
-static int pc_clk_set_ext_config(struct clk *clk, unsigned config)
+static int pc_clk_set_ext_config(struct clk *clk, unsigned long config)
{
int id = to_pcom_clk(clk)->id;
- int rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_EXT_CONFIG, &id, &config);
+ unsigned c = config;
+ int rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_EXT_CONFIG, &id, &c);
if (rc < 0)
return rc;
else
return (int)id < 0 ? -EINVAL : 0;
}
-static unsigned pc_clk_get_rate(struct clk *clk)
+static unsigned long pc_clk_get_rate(struct clk *clk)
{
int id = to_pcom_clk(clk)->id;
if (msm_proc_comm(PCOM_CLKCTL_RPC_RATE, &id, NULL))
@@ -152,7 +155,7 @@
return id;
}
-static long pc_clk_round_rate(struct clk *clk, unsigned rate)
+static long pc_clk_round_rate(struct clk *clk, unsigned long rate)
{
/* Not really supported; pc_clk_set_rate() does rounding on it's own. */
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 2ccebb4..75cba59 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -26,8 +26,8 @@
struct msm_rpm_iv_pair iv;
int rc = 0;
struct rpm_clk *r = to_rpm_clk(clk);
- unsigned this_khz, this_sleep_khz;
- unsigned peer_khz = 0, peer_sleep_khz = 0;
+ unsigned long this_khz, this_sleep_khz;
+ unsigned long peer_khz = 0, peer_sleep_khz = 0;
struct rpm_clk *peer = r->peer;
spin_lock_irqsave(&rpm_clock_lock, flags);
@@ -78,7 +78,7 @@
if (r->last_set_khz) {
struct msm_rpm_iv_pair iv;
struct rpm_clk *peer = r->peer;
- unsigned peer_khz = 0, peer_sleep_khz = 0;
+ unsigned long peer_khz = 0, peer_sleep_khz = 0;
int rc;
iv.id = r->rpm_clk_id;
@@ -104,11 +104,11 @@
return;
}
-static int rpm_clk_set_min_rate(struct clk *clk, unsigned rate)
+static int rpm_clk_set_min_rate(struct clk *clk, unsigned long rate)
{
unsigned long flags;
struct rpm_clk *r = to_rpm_clk(clk);
- unsigned this_khz, this_sleep_khz;
+ unsigned long this_khz, this_sleep_khz;
int rc = 0;
this_khz = DIV_ROUND_UP(rate, 1000);
@@ -129,7 +129,7 @@
if (r->enabled) {
struct msm_rpm_iv_pair iv;
struct rpm_clk *peer = r->peer;
- unsigned peer_khz = 0, peer_sleep_khz = 0;
+ unsigned long peer_khz = 0, peer_sleep_khz = 0;
iv.id = r->rpm_clk_id;
@@ -158,7 +158,7 @@
return rc;
}
-static unsigned rpm_clk_get_rate(struct clk *clk)
+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 };
@@ -175,7 +175,7 @@
return !!(rpm_clk_get_rate(clk));
}
-static long rpm_clk_round_rate(struct clk *clk, unsigned rate)
+static long rpm_clk_round_rate(struct clk *clk, unsigned long rate)
{
/* Not supported. */
return rate;
diff --git a/arch/arm/mach-msm/clock-voter.c b/arch/arm/mach-msm/clock-voter.c
index e754752..56beca1 100644
--- a/arch/arm/mach-msm/clock-voter.c
+++ b/arch/arm/mach-msm/clock-voter.c
@@ -21,10 +21,10 @@
static DEFINE_SPINLOCK(voter_clk_lock);
/* Aggregate the rate of clocks that are currently on. */
-static unsigned voter_clk_aggregate_rate(const struct clk *parent)
+static unsigned long voter_clk_aggregate_rate(const struct clk *parent)
{
struct clk *clk;
- unsigned rate = 0;
+ unsigned long rate = 0;
list_for_each_entry(clk, &parent->children, siblings) {
struct clk_voter *v = to_clk_voter(clk);
@@ -34,13 +34,13 @@
return rate;
}
-static int voter_clk_set_rate(struct clk *clk, unsigned rate)
+static int voter_clk_set_rate(struct clk *clk, unsigned long rate)
{
int ret = 0;
unsigned long flags;
struct clk *clkp;
struct clk_voter *clkh, *v = to_clk_voter(clk);
- unsigned cur_rate, new_rate, other_rate = 0;
+ unsigned long cur_rate, new_rate, other_rate = 0;
spin_lock_irqsave(&voter_clk_lock, flags);
@@ -77,7 +77,7 @@
{
int ret = 0;
unsigned long flags;
- unsigned cur_rate;
+ unsigned long cur_rate;
struct clk *parent;
struct clk_voter *v = to_clk_voter(clk);
@@ -103,10 +103,9 @@
static void voter_clk_disable(struct clk *clk)
{
- unsigned long flags;
+ unsigned long flags, cur_rate, new_rate;
struct clk *parent;
struct clk_voter *v = to_clk_voter(clk);
- unsigned cur_rate, new_rate;
spin_lock_irqsave(&voter_clk_lock, flags);
parent = v->parent;
@@ -125,10 +124,9 @@
spin_unlock_irqrestore(&voter_clk_lock, flags);
}
-static unsigned voter_clk_get_rate(struct clk *clk)
+static unsigned long voter_clk_get_rate(struct clk *clk)
{
- unsigned rate;
- unsigned long flags;
+ unsigned long rate, flags;
struct clk_voter *v = to_clk_voter(clk);
spin_lock_irqsave(&voter_clk_lock, flags);
@@ -144,7 +142,7 @@
return v->enabled;
}
-static long voter_clk_round_rate(struct clk *clk, unsigned rate)
+static long voter_clk_round_rate(struct clk *clk, unsigned long rate)
{
struct clk_voter *v = to_clk_voter(clk);
return clk_round_rate(v->parent, rate);
diff --git a/arch/arm/mach-msm/clock-voter.h b/arch/arm/mach-msm/clock-voter.h
index 64baf3b..10353d4 100644
--- a/arch/arm/mach-msm/clock-voter.h
+++ b/arch/arm/mach-msm/clock-voter.h
@@ -19,7 +19,7 @@
struct clk_voter {
bool enabled;
- unsigned rate;
+ unsigned long rate;
struct clk *parent;
struct clk c;
};
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 4f3ad95..eff85f0 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -133,7 +133,7 @@
int clk_enable(struct clk *clk)
{
int ret = 0;
- unsigned long flags, rate;
+ unsigned long flags;
struct clk *parent;
if (!clk)
@@ -142,7 +142,6 @@
spin_lock_irqsave(&clk->lock, flags);
if (clk->count == 0) {
parent = clk_get_parent(clk);
- rate = clk_get_rate(clk);
ret = clk_enable(parent);
if (ret)
@@ -151,7 +150,7 @@
if (ret)
goto err_enable_depends;
- ret = vote_rate_vdd(clk, rate);
+ ret = vote_rate_vdd(clk, clk->rate);
if (ret)
goto err_vote_vdd;
if (clk->ops->enable)
@@ -175,7 +174,7 @@
return 0;
err_enable_clock:
- unvote_rate_vdd(clk, rate);
+ unvote_rate_vdd(clk, clk->rate);
err_vote_vdd:
clk_disable(clk->depends);
err_enable_depends:
@@ -198,11 +197,10 @@
goto out;
if (clk->count == 1) {
struct clk *parent = clk_get_parent(clk);
- unsigned long rate = clk_get_rate(clk);
if (clk->ops->disable)
clk->ops->disable(clk);
- unvote_rate_vdd(clk, rate);
+ unvote_rate_vdd(clk, clk->rate);
clk_disable(clk->depends);
clk_disable(parent);
}
@@ -231,7 +229,7 @@
EXPORT_SYMBOL(clk_get_rate);
static int _clk_set_rate(struct clk *clk, unsigned long rate,
- int (*set_fn)(struct clk *, unsigned))
+ int (*set_fn)(struct clk *, unsigned long))
{
unsigned long start_rate, flags;
int rc;
@@ -241,7 +239,7 @@
spin_lock_irqsave(&clk->lock, flags);
if (clk->count) {
- start_rate = clk_get_rate(clk);
+ start_rate = clk->rate;
/* Enforce vdd requirements for target frequency. */
rc = vote_rate_vdd(clk, rate);
if (rc)
@@ -254,6 +252,10 @@
} else {
rc = set_fn(clk, rate);
}
+
+ if (!rc)
+ clk->rate = rate;
+
spin_unlock_irqrestore(&clk->lock, flags);
return rc;
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index ed5c9c6..81f12c6 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -47,7 +47,7 @@
const char *class_name;
int (*set_vdd)(struct clk_vdd_class *v_class, int level);
int level_votes[MAX_VDD_LEVELS];
- unsigned cur_level;
+ unsigned long cur_level;
spinlock_t lock;
};
@@ -65,14 +65,14 @@
void (*auto_off)(struct clk *clk);
int (*handoff)(struct clk *clk);
int (*reset)(struct clk *clk, enum clk_reset_action action);
- int (*set_rate)(struct clk *clk, unsigned rate);
- int (*set_min_rate)(struct clk *clk, unsigned rate);
- int (*set_max_rate)(struct clk *clk, unsigned rate);
+ int (*set_rate)(struct clk *clk, unsigned long rate);
+ int (*set_min_rate)(struct clk *clk, unsigned long rate);
+ int (*set_max_rate)(struct clk *clk, unsigned long rate);
int (*set_flags)(struct clk *clk, unsigned flags);
- unsigned (*get_rate)(struct clk *clk);
+ unsigned long (*get_rate)(struct clk *clk);
int (*list_rate)(struct clk *clk, unsigned n);
int (*is_enabled)(struct clk *clk);
- long (*round_rate)(struct clk *clk, unsigned rate);
+ long (*round_rate)(struct clk *clk, unsigned long rate);
int (*set_parent)(struct clk *clk, struct clk *parent);
struct clk *(*get_parent)(struct clk *clk);
bool (*is_local)(struct clk *clk);
@@ -93,6 +93,7 @@
struct clk *depends;
struct clk_vdd_class *vdd_class;
unsigned long fmax[MAX_VDD_LEVELS];
+ unsigned long rate;
struct list_head children;
struct list_head siblings;
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 2d2f104..b737b116 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1969,18 +1969,22 @@
{
.gpu_freq = 400000000,
.bus_freq = 4,
+ .io_fraction = 0,
},
{
.gpu_freq = 300000000,
.bus_freq = 3,
+ .io_fraction = 33,
},
{
.gpu_freq = 200000000,
.bus_freq = 2,
+ .io_fraction = 100,
},
{
.gpu_freq = 128000000,
.bus_freq = 1,
+ .io_fraction = 100,
},
{
.gpu_freq = 27000000,
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 3cf7d48..60fa257 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -332,6 +332,11 @@
.id = -1,
};
+struct platform_device msm_device_bam_dmux = {
+ .name = "BAM_RMNT",
+ .id = -1,
+};
+
#ifdef CONFIG_HW_RANDOM_MSM
/* PRNG device */
#define MSM_PRNG_PHYS 0x1A500000
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index def2558..4458adf 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -657,18 +657,22 @@
{
.gpu_freq = 266667000,
.bus_freq = 4,
+ .io_fraction = 0,
},
{
.gpu_freq = 228571000,
.bus_freq = 3,
+ .io_fraction = 33,
},
{
.gpu_freq = 200000000,
.bus_freq = 2,
+ .io_fraction = 100,
},
{
.gpu_freq = 177778000,
- .bus_freq = 1
+ .bus_freq = 1,
+ .io_fraction = 100,
},
{
.gpu_freq = 27000000,
diff --git a/arch/arm/mach-msm/include/mach/audio_dma_msm8k.h b/arch/arm/mach-msm/include/mach/audio_dma_msm8k.h
index 5c9bfb5..1970d0b 100644
--- a/arch/arm/mach-msm/include/mach/audio_dma_msm8k.h
+++ b/arch/arm/mach-msm/include/mach/audio_dma_msm8k.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-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
@@ -202,6 +202,11 @@
#define LPAIF_DMA_SET_BUFF_CNT(x) DMA_CTRL_ADDR(x, 0x20)
#define LPAIF_DMA_SET_PER_CNT(x) DMA_CTRL_ADDR(x, 0x24)
+#define LPAIF_DMA_PER_CNT_PER_CNT_MASK 0x000FFFFF
+#define LPAIF_DMA_PER_CNT_PER_CNT_SHIFT 0
+#define LPAIF_DMA_PER_CNT_FIFO_WORDCNT_MASK 0x00F00000
+#define LPAIF_DMA_PER_CNT_FIFO_WORDCNT_SHIFT 20
+
/* channel assignments */
#define DMA_CH_0 0
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
index 97dad67..3965a75 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
@@ -14,5 +14,6 @@
#define __MSM_HDMI_AUDIO_H
int hdmi_audio_enable(bool on , u32 fifo_water_mark);
+int hdmi_audio_packet_enable(bool on);
#endif /* __MSM_HDMI_AUDIO_H*/
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h b/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h
index 8309953..62d7a33 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/apr.h
@@ -76,7 +76,8 @@
#define APR_SVC_ADSP_MVM 0x09
#define APR_SVC_ADSP_CVS 0x0A
#define APR_SVC_ADSP_CVP 0x0B
-#define APR_SVC_MAX 0x0C
+#define APR_SVC_USM 0x0C
+#define APR_SVC_MAX 0x0D
/* Modem Service IDs */
#define APR_SVC_MVS 0x3
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/apr_us.h b/arch/arm/mach-msm/include/mach/qdsp6v2/apr_us.h
new file mode 100644
index 0000000..444d7ad
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/apr_us.h
@@ -0,0 +1,156 @@
+/* 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 __APR_US_H__
+#define __APR_US_H__
+
+#include <mach/qdsp6v2/apr.h>
+
+/* ======================================================================= */
+/* Session Level commands */
+#define USM_SESSION_CMD_MEMORY_MAP 0x00012304
+struct usm_stream_cmd_memory_map {
+ struct apr_hdr hdr;
+ u32 buf_add;
+ u32 buf_size;
+ u16 mempool_id;
+ u16 reserved;
+} __packed;
+
+#define USM_SESSION_CMD_MEMORY_UNMAP 0x00012305
+struct usm_stream_cmd_memory_unmap {
+ struct apr_hdr hdr;
+ u32 buf_add;
+} __packed;
+
+#define USM_SESSION_CMD_RUN 0x00012306
+struct usm_stream_cmd_run {
+ struct apr_hdr hdr;
+ u32 flags;
+ u32 msw_ts;
+ u32 lsw_ts;
+} __packed;
+
+/* Stream level commands */
+#define USM_STREAM_CMD_OPEN_READ 0x00012309
+struct usm_stream_cmd_open_read {
+ struct apr_hdr hdr;
+ u32 uMode;
+ u32 src_endpoint;
+ u32 pre_proc_top;
+ u32 format;
+} __packed;
+
+#define USM_STREAM_CMD_OPEN_WRITE 0x00011271
+struct usm_stream_cmd_open_write {
+ struct apr_hdr hdr;
+ u32 format;
+} __packed;
+
+
+#define USM_STREAM_CMD_CLOSE 0x0001230A
+
+/* Encoder configuration definitions */
+#define USM_STREAM_CMD_SET_ENC_PARAM 0x0001230B
+/* Decoder configuration definitions */
+#define USM_DATA_CMD_MEDIA_FORMAT_UPDATE 0x00011272
+
+/* Encoder/decoder configuration block */
+#define USM_PARAM_ID_ENCDEC_ENC_CFG_BLK 0x0001230D
+
+/* Parameter structures used in USM_STREAM_CMD_SET_ENCDEC_PARAM command */
+/* common declarations */
+struct usm_cfg_common {
+ u16 ch_cfg;
+ u16 bits_per_sample;
+ u32 sample_rate;
+ u32 dev_id;
+ u32 data_map;
+} __packed;
+
+/* Max number of static located transparent data (bytes) */
+#define USM_MAX_CFG_DATA_SIZE 20
+struct usm_encode_cfg_blk {
+ u32 frames_per_buf;
+ u32 format_id;
+ /* <cfg_size> = sizeof(usm_cfg_common)+|tarnsp_data| */
+ u32 cfg_size;
+ struct usm_cfg_common cfg_common;
+ /* Transparent configuration data for specific encoder */
+ u8 transp_data[USM_MAX_CFG_DATA_SIZE];
+} __packed;
+
+struct usm_stream_cmd_encdec_cfg_blk {
+ struct apr_hdr hdr;
+ u32 param_id;
+ u32 param_size;
+ struct usm_encode_cfg_blk enc_blk;
+} __packed;
+
+struct us_encdec_cfg {
+ u32 format_id;
+ struct usm_cfg_common cfg_common;
+ u16 params_size;
+ u8 *params;
+} __packed;
+
+struct usm_stream_media_format_update {
+ struct apr_hdr hdr;
+ u32 format_id;
+ /* <cfg_size> = sizeof(usm_cfg_common)+|tarnsp_data| */
+ u32 cfg_size;
+ struct usm_cfg_common cfg_common;
+ /* Transparent configuration data for specific encoder */
+ u8 transp_data[USM_MAX_CFG_DATA_SIZE];
+} __packed;
+
+
+#define USM_DATA_CMD_READ 0x0001230E
+struct usm_stream_cmd_read {
+ struct apr_hdr hdr;
+ u32 buf_add;
+ u32 buf_size;
+ u32 uid;
+ u32 counter;
+} __packed;
+
+#define USM_DATA_EVENT_READ_DONE 0x0001230F
+struct usm_data_event_read_done {
+ u32 status;
+ u32 buffer_add;
+ u32 enc_frame_size;
+ u32 offset;
+ u32 msw_ts;
+ u32 lsw_ts;
+ u32 flags;
+ u32 num_frames;
+ u32 id;
+} __packed;
+
+#define USM_DATA_CMD_WRITE 0x00011273
+struct usm_stream_cmd_write {
+ struct apr_hdr hdr;
+ u32 buf_add;
+ u32 buf_size;
+ u32 uid;
+ u32 msw_ts;
+ u32 lsw_ts;
+ u32 flags;
+} __packed;
+
+#define USM_DATA_EVENT_WRITE_DONE 0x00011274
+struct usm_data_event_write_done {
+ u32 buf_add;
+ u32 status;
+} __packed;
+
+#endif /* __APR_US_H__ */
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h b/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
new file mode 100644
index 0000000..346dc0d
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/usf.h
@@ -0,0 +1,185 @@
+/* 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 __USF_H__
+#define __USF_H__
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define USF_IOCTL_MAGIC 'U'
+
+#define US_SET_TX_INFO _IOW(USF_IOCTL_MAGIC, 0, \
+ struct us_tx_info_type)
+#define US_START_TX _IO(USF_IOCTL_MAGIC, 1)
+#define US_GET_TX_UPDATE _IOWR(USF_IOCTL_MAGIC, 2, \
+ struct us_tx_update_info_type)
+#define US_SET_RX_INFO _IOW(USF_IOCTL_MAGIC, 3, \
+ struct us_rx_info_type)
+#define US_SET_RX_UPDATE _IOWR(USF_IOCTL_MAGIC, 4, \
+ struct us_rx_update_info_type)
+#define US_START_RX _IO(USF_IOCTL_MAGIC, 5)
+
+#define US_STOP_TX _IO(USF_IOCTL_MAGIC, 6)
+#define US_STOP_RX _IO(USF_IOCTL_MAGIC, 7)
+
+
+/* Encoder (TX), decoder (RX) supported US data formats */
+#define USF_POINT_EPOS_FORMAT 0
+#define USF_RAW_FORMAT 1
+
+/* Types of events, produced by the calculators */
+#define USF_TSC_EVENT 1
+#define USF_MOUSE_EVENT 2
+#define USF_KEYBOARD_EVENT 4
+#define USF_ALL_EVENTS (USF_TSC_EVENT | USF_MOUSE_EVENT | USF_KEYBOARD_EVENT)
+
+/* Max size of the client name */
+#define USF_MAX_CLIENT_NAME_SIZE 20
+/* Info structure common for TX and RX */
+struct us_xx_info_type {
+/* Input: general info */
+/* Name of the client - event calculator */
+ const char *client_name;
+/* Selected device identification, accepted in the kernel's CAD */
+ uint32_t dev_id;
+/* 0 - point_epos type; (e.g. 1 - gr_mmrd) */
+ uint32_t stream_format;
+/* Required sample rate in Hz */
+ uint32_t sample_rate;
+/* Size of a buffer (bytes) for US data transfer between the module and USF */
+ uint32_t buf_size;
+/* Number of the buffers for the US data transfer */
+ uint16_t buf_num;
+/* Number of the microphones (TX) or speakers(RX) */
+ uint16_t port_cnt;
+/* Microphones(TX) or speakers(RX) indexes in their enumeration */
+ uint8_t port_id[4];
+/* Bits per sample 16 or 32 */
+ uint16_t bits_per_sample;
+/* Input: Transparent info for encoder in the LPASS */
+/* Parameters data size in bytes */
+ uint16_t params_data_size;
+/* Pointer to the parameters */
+ uint8_t *params_data;
+};
+
+struct us_input_info_type {
+ /* Touch screen dimensions: min & max;for input module */
+ int tsc_x_dim[2];
+ int tsc_y_dim[2];
+ /* Touch screen fuzz; for input module */
+ int tsc_x_fuzz;
+ int tsc_y_fuzz;
+ /* Touch screen pressure limits: min & max; for input module */
+ int tsc_pressure[2];
+ /* Bitmap of types of events (USF_X_EVENT), produced by calculator */
+ uint16_t event_types;
+};
+
+struct us_tx_info_type {
+ /* Common info */
+ struct us_xx_info_type us_xx_info;
+ /* Info specific for TX*/
+ struct us_input_info_type input_info;
+};
+
+struct us_rx_info_type {
+ /* Common info */
+ struct us_xx_info_type us_xx_info;
+ /* Info specific for RX*/
+};
+
+
+#define USF_PIX_COORDINATE 0 /* unit is pixel */
+#define USF_CMM_COORDINATE 1 /* unit is 0.01 mm */
+struct point_event_type {
+/* Pen coordinates (x, y) in units, defined by <coordinates_type> */
+ int coordinates[2];
+/* {x;y} in degrees [-90; 90] */
+ uint32_t inclinations[2];
+/* [0-1023] (10bits); 0 - pen up */
+ uint32_t pressure;
+/* 0 - mapped in the display pixel. 1 - raw in 0.01 mm (only for log); */
+ uint8_t coordinates_type;
+};
+
+/* Mouse buttons, supported by USF */
+#define USF_BUTTON_LEFT_MASK 1
+#define USF_BUTTON_MIDDLE_MASK 2
+#define USF_BUTTON_RIGHT_MASK 4
+struct mouse_event_type {
+/* The mouse relative movement (dX, dY, dZ) */
+ int rels[3];
+/* Bitmap of mouse buttons states: 1 - down, 0 - up; */
+ uint16_t buttons_states;
+};
+
+struct key_event_type {
+/* Calculated MS key- see input.h. */
+ uint32_t key;
+/* Keyboard's key state: 1 - down, 0 - up; */
+ uint8_t key_state;
+};
+
+struct usf_event_type {
+/* Event sequence number */
+ uint32_t seq_num;
+/* Event generation system time */
+ uint32_t timestamp;
+/* Destination input event type (e.g. touch screen, mouse, key) */
+ uint16_t event_type;
+ union {
+ struct point_event_type point_event;
+ struct mouse_event_type mouse_event;
+ struct key_event_type key_event;
+ } event_data;
+};
+
+struct us_tx_update_info_type {
+/* Input general: */
+/* Number of calculated events */
+ uint16_t event_counter;
+/* Calculated events or NULL */
+ struct usf_event_type *event;
+/* Pointer (read index) to the end of available region */
+/* in the shared US data memory */
+ uint32_t free_region;
+/* Input transparent data: */
+/* Parameters size */
+ uint16_t params_data_size;
+/* Pointer to the parameters */
+ uint8_t *params_data;
+/* Output parameters: */
+/* Pointer (write index) to the end of ready US data region */
+/* in the shared memory */
+ uint32_t ready_region;
+};
+
+struct us_rx_update_info_type {
+/* Input general: */
+/* Pointer (write index) to the end of ready US data region */
+/* in the shared memory */
+ uint32_t ready_region;
+/* Input transparent data: */
+/* Parameters size */
+ uint16_t params_data_size;
+/* pPointer to the parameters */
+ uint8_t *params_data;
+/* Output parameters: */
+/* Pointer (read index) to the end of available region */
+/* in the shared US data memory */
+ uint32_t free_region;
+};
+
+#endif /* __USF_H__ */
diff --git a/arch/arm/mach-msm/qdsp6v2/Makefile b/arch/arm/mach-msm/qdsp6v2/Makefile
index 5e88927..7759c74 100644
--- a/arch/arm/mach-msm/qdsp6v2/Makefile
+++ b/arch/arm/mach-msm/qdsp6v2/Makefile
@@ -16,3 +16,4 @@
obj-y += audio_acdb.o
obj-y += aac_in.o qcelp_in.o evrc_in.o amrnb_in.o audio_utils.o
obj-y += audio_wma.o audio_wmapro.o audio_aac.o audio_multi_aac.o audio_utils_aio.o
+obj-$(CONFIG_MSM_ULTRASOUND) += ultrasound/
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index c4eb205..78f6519 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -191,6 +191,7 @@
if (svc == APR_SVC_AFE || svc == APR_SVC_ASM ||
svc == APR_SVC_VSM || svc == APR_SVC_VPM ||
svc == APR_SVC_ADM || svc == APR_SVC_ADSP_CORE ||
+ svc == APR_SVC_USM ||
svc == APR_SVC_TEST_CLIENT || svc == APR_SVC_ADSP_MVM ||
svc == APR_SVC_ADSP_CVS || svc == APR_SVC_ADSP_CVP)
clnt = APR_CLIENT_AUDIO;
@@ -355,6 +356,10 @@
client_id = APR_CLIENT_VOICE;
svc_idx = 6;
svc_id = APR_SVC_SRD;
+ } else if (!strncmp(svc_name, "USM", 3)) {
+ client_id = APR_CLIENT_AUDIO;
+ svc_idx = 8;
+ svc_id = APR_SVC_USM;
} else {
pr_err("APR: Wrong svc name\n");
goto done;
diff --git a/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c b/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
index 11d5d05..16258eb 100644
--- a/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
+++ b/arch/arm/mach-msm/qdsp6v2/lpa_if_hdmi.c
@@ -74,8 +74,6 @@
pending = (intrsrc
& (UNDER_CH(dma_ch) | PER_CH(dma_ch) | ERR_CH(dma_ch)));
- pr_debug("pending = 0x%08x\n", pending);
-
if (pending & UNDER_CH(dma_ch))
pr_err("under run\n");
if (pending & ERR_CH(dma_ch))
@@ -104,10 +102,9 @@
dai_start_hdmi(lpa_if->dma_ch);
- mb();
-
hdmi_audio_enable(1, HDMI_AUDIO_FIFO_WATER_MARK);
- mb();
+
+ hdmi_audio_packet_enable(1);
return 0;
}
@@ -121,7 +118,7 @@
dma_params.period_size = lpa_if->dma_period_sz;
dma_params.channels = 2;
- lpa_if->dma_ch = 0;
+ lpa_if->dma_ch = 4;
dai_set_params(lpa_if->dma_ch, &dma_params);
register_dma_irq_handler(lpa_if->dma_ch, lpa_if_irq, (void *)lpa_if);
@@ -232,6 +229,7 @@
lpa_if_ptr->dma_buf = 0;
core_req_bus_bandwith(AUDIO_IF_BUS_ID, 100000, 0);
+ mb();
return 0;
}
@@ -244,9 +242,6 @@
const char __user *start = buf;
int xfer, rc;
- pr_debug("count %u cpu_buf %d dma_buf %d\n",
- (unsigned int)count, lpa_if->cpu_buf, lpa_if->dma_buf);
-
mutex_lock(&lpa_if->lock);
if (dma_buf_index < 2) {
@@ -259,6 +254,7 @@
goto end;
}
+ mb();
pr_debug("prefill: count %u audio_buf[%u].size %u\n",
count, dma_buf_index, ab->size);
@@ -315,15 +311,20 @@
static int lpa_if_release(struct inode *inode, struct file *file)
{
struct lpa_if *lpa_if = file->private_data;
- hdmi_audio_enable(0, HDMI_AUDIO_FIFO_WATER_MARK);
- smp_mb();
+ hdmi_audio_packet_enable(0);
+
+ wait_for_dma_cnt_stop(lpa_if->dma_ch);
+
+ hdmi_audio_enable(0, HDMI_AUDIO_FIFO_WATER_MARK);
if (lpa_if->config) {
unregister_dma_irq_handler(lpa_if->dma_ch);
dai_stop_hdmi(lpa_if->dma_ch);
lpa_if->config = 0;
}
+ core_req_bus_bandwith(AUDIO_IF_BUS_ID, 0, 0);
+
return 0;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/snddev_hdmi.c b/arch/arm/mach-msm/qdsp6v2/snddev_hdmi.c
index 4eeb654..9b8346d 100644
--- a/arch/arm/mach-msm/qdsp6v2/snddev_hdmi.c
+++ b/arch/arm/mach-msm/qdsp6v2/snddev_hdmi.c
@@ -102,7 +102,7 @@
snddev_hdmi_active = 0;
if (snddev_hdmi_data->on_apps) {
- pr_debug("%s open done\n", dev_info->name);
+ pr_debug("%s Closed\n", dev_info->name);
mutex_unlock(&snddev_hdmi_lock);
return 0;
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/Makefile b/arch/arm/mach-msm/qdsp6v2/ultrasound/Makefile
new file mode 100644
index 0000000..540119b
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/Makefile
@@ -0,0 +1,2 @@
+obj-y += q6usm.o usf.o
+EXTRA_CFLAGS += -I$(src)/..
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c
new file mode 100644
index 0000000..d48df06
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.c
@@ -0,0 +1,1162 @@
+/* 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.
+ *
+ */
+#include <linux/fs.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/msm_audio.h>
+#include <sound/apr_audio.h>
+#include "q6usm.h"
+
+/* The driver version*/
+#define DRV_VERSION "1.0"
+
+#define SESSION_MAX 0x02 /* aDSP:USM limit */
+
+#define READDONE_IDX_STATUS 0
+#define READDONE_IDX_BUFFER 1
+#define READDONE_IDX_SIZE 2
+#define READDONE_IDX_OFFSET 3
+#define READDONE_IDX_MSW_TS 4
+#define READDONE_IDX_LSW_TS 5
+#define READDONE_IDX_FLAGS 6
+#define READDONE_IDX_NUMFRAMES 7
+#define READDONE_IDX_ID 8
+
+#define WRITEDONE_IDX_STATUS 0
+
+/* Standard timeout in the asynchronous ops */
+#define Q6USM_TIMEOUT_JIFFIES (3*HZ) /* 3 sec */
+
+/* cyclic buffer with 1 gap support */
+#define USM_MIN_BUF_CNT 3
+
+static DEFINE_MUTEX(session_lock);
+
+static struct us_client *session[SESSION_MAX];
+static int32_t q6usm_mmapcallback(struct apr_client_data *data, void *priv);
+static int32_t q6usm_callback(struct apr_client_data *data, void *priv);
+static void q6usm_add_hdr(struct us_client *usc, struct apr_hdr *hdr,
+ uint32_t pkt_size, bool cmd_flg);
+
+struct usm_mmap {
+ atomic_t ref_cnt;
+ atomic_t cmd_state;
+ wait_queue_head_t cmd_wait;
+ void *apr;
+};
+
+static struct usm_mmap this_mmap;
+
+static int q6usm_session_alloc(struct us_client *usc)
+{
+ int ind = 0;
+
+ mutex_lock(&session_lock);
+ for (ind = 0; ind < SESSION_MAX; ++ind) {
+ if (!session[ind]) {
+ session[ind] = usc;
+ mutex_unlock(&session_lock);
+ ++ind; /* session id: 0 reserved */
+ pr_debug("%s: session[%d] was allocated\n",
+ __func__, ind);
+ return ind;
+ }
+ }
+ mutex_unlock(&session_lock);
+ return -ENOMEM;
+}
+
+static void q6usm_session_free(struct us_client *usc)
+{
+ /* Session index was incremented during allocation */
+ uint16_t ind = (uint16_t)usc->session - 1;
+
+ pr_debug("%s: to free session[%d]\n", __func__, ind);
+ if (ind < SESSION_MAX) {
+ mutex_lock(&session_lock);
+ session[ind] = 0;
+ mutex_unlock(&session_lock);
+ }
+}
+
+int q6usm_us_client_buf_free(unsigned int dir,
+ struct us_client *usc)
+{
+ struct us_port_data *port;
+ int rc = 0;
+ uint32_t size = 0;
+
+ if ((usc == NULL) ||
+ ((dir != IN) && (dir != OUT)))
+ return -EINVAL;
+
+ mutex_lock(&usc->cmd_lock);
+ port = &usc->port[dir];
+ if (port == NULL) {
+ mutex_unlock(&usc->cmd_lock);
+ return -EINVAL;
+ }
+
+ if (port->data == NULL) {
+ mutex_unlock(&usc->cmd_lock);
+ return 0;
+ }
+
+ rc = q6usm_memory_unmap(usc, port->phys, dir);
+ if (rc)
+ pr_err("%s: CMD Memory_unmap* failed\n", __func__);
+
+ pr_debug("%s: data[%p]phys[%p][%p]\n", __func__,
+ (void *)port->data, (void *)port->phys, (void *)&port->phys);
+ size = port->buf_size * port->buf_cnt;
+ dma_free_coherent(NULL, size, port->data, port->phys);
+ port->data = NULL;
+ port->phys = 0;
+ port->buf_size = 0;
+ port->buf_cnt = 0;
+
+ mutex_unlock(&usc->cmd_lock);
+ return 0;
+}
+
+void q6usm_us_client_free(struct us_client *usc)
+{
+ int loopcnt = 0;
+ struct us_port_data *port;
+
+ if ((usc == NULL) ||
+ !(usc->session))
+ return;
+
+ for (loopcnt = 0; loopcnt <= OUT; ++loopcnt) {
+ port = &usc->port[loopcnt];
+ if (port->data == NULL)
+ continue;
+ pr_debug("%s: loopcnt = %d\n", __func__, loopcnt);
+ q6usm_us_client_buf_free(loopcnt, usc);
+ }
+ q6usm_session_free(usc);
+ apr_deregister(usc->apr);
+
+ pr_debug("%s: APR De-Register\n", __func__);
+
+ if (atomic_read(&this_mmap.ref_cnt) <= 0) {
+ pr_err("%s: APR Common Port Already Closed\n", __func__);
+ goto done;
+ }
+
+ atomic_dec(&this_mmap.ref_cnt);
+ if (atomic_read(&this_mmap.ref_cnt) == 0) {
+ apr_deregister(this_mmap.apr);
+ pr_debug("%s: APR De-Register common port\n", __func__);
+ }
+done:
+ kfree(usc);
+ pr_debug("%s:\n", __func__);
+ return;
+}
+
+struct us_client *q6usm_us_client_alloc(
+ void (*cb)(uint32_t, uint32_t, uint32_t *, void *),
+ void *priv)
+{
+ struct us_client *usc;
+ int n;
+ int lcnt = 0;
+
+ usc = kzalloc(sizeof(struct us_client), GFP_KERNEL);
+ if (usc == NULL)
+ return NULL;
+ n = q6usm_session_alloc(usc);
+ if (n <= 0)
+ goto fail_session;
+ usc->session = n;
+ usc->cb = cb;
+ usc->priv = priv;
+ usc->apr = apr_register("ADSP", "USM", \
+ (apr_fn)q6usm_callback,\
+ ((usc->session) << 8 | 0x0001),\
+ usc);
+
+ if (usc->apr == NULL) {
+ pr_err("%s: Registration with APR failed\n", __func__);
+ goto fail;
+ }
+ pr_info("%s: Registering the common port with APR\n", __func__);
+ if (atomic_read(&this_mmap.ref_cnt) == 0) {
+ this_mmap.apr = apr_register("ADSP", "USM",
+ (apr_fn)q6usm_mmapcallback,
+ 0x0FFFFFFFF, &this_mmap);
+ if (this_mmap.apr == NULL) {
+ pr_err("%s: USM port registration failed\n",
+ __func__);
+ goto fail;
+ }
+ }
+
+ atomic_inc(&this_mmap.ref_cnt);
+ init_waitqueue_head(&usc->cmd_wait);
+ mutex_init(&usc->cmd_lock);
+ for (lcnt = 0; lcnt <= OUT; ++lcnt) {
+ mutex_init(&usc->port[lcnt].lock);
+ spin_lock_init(&usc->port[lcnt].dsp_lock);
+ }
+ atomic_set(&usc->cmd_state, 0);
+
+ return usc;
+fail:
+ q6usm_us_client_free(usc);
+ return NULL;
+fail_session:
+ kfree(usc);
+ return NULL;
+}
+
+int q6usm_us_client_buf_alloc(unsigned int dir,
+ struct us_client *usc,
+ unsigned int bufsz,
+ unsigned int bufcnt)
+{
+ int rc = 0;
+ struct us_port_data *port = NULL;
+ unsigned int size = bufsz*bufcnt;
+
+ if ((usc == NULL) ||
+ ((dir != IN) && (dir != OUT)) || (size == 0) ||
+ (usc->session <= 0 || usc->session > SESSION_MAX) ||
+ (bufcnt < USM_MIN_BUF_CNT)) {
+ pr_err("%s: wrong parameters: size=%d; bufcnt=%d\n",
+ __func__, size, bufcnt);
+ return -EINVAL;
+ }
+
+ mutex_lock(&usc->cmd_lock);
+
+ port = &usc->port[dir];
+
+ port->data = dma_alloc_coherent(NULL, size, &(port->phys), GFP_KERNEL);
+ if (port->data == NULL) {
+ pr_err("%s: US region allocation failed\n", __func__);
+ mutex_unlock(&usc->cmd_lock);
+ return -ENOMEM;
+ }
+
+ port->buf_cnt = bufcnt;
+ port->buf_size = bufsz;
+ pr_debug("%s: data[%p]; phys[%p]; [%p]\n", __func__,
+ (void *)port->data,
+ (void *)port->phys,
+ (void *)&port->phys);
+
+ rc = q6usm_memory_map(usc, port->phys, dir, size, 1);
+ if (rc < 0) {
+ pr_err("%s: CMD Memory_map failed\n", __func__);
+ mutex_unlock(&usc->cmd_lock);
+ q6usm_us_client_buf_free(dir, usc);
+ } else {
+ mutex_unlock(&usc->cmd_lock);
+ rc = 0;
+ }
+
+ return rc;
+}
+
+static int32_t q6usm_mmapcallback(struct apr_client_data *data, void *priv)
+{
+ uint32_t token;
+ uint32_t *payload = data->payload;
+
+ pr_debug("%s: ptr0[0x%x]; ptr1[0x%x]; opcode[0x%x];"
+ "token[0x%x]; payload_s[%d]; src[%d]; dest[%d];\n",
+ __func__, payload[0], payload[1], data->opcode, data->token,
+ data->payload_size, data->src_port, data->dest_port);
+
+ if (data->opcode == APR_BASIC_RSP_RESULT) {
+ /* status field check */
+ if (payload[1]) {
+ pr_err("%s: wrong response[%d] on cmd [%d]\n",
+ __func__, payload[1], payload[0]);
+ } else {
+ token = data->token;
+ switch (payload[0]) {
+ case USM_SESSION_CMD_MEMORY_MAP:
+ case USM_SESSION_CMD_MEMORY_UNMAP:
+ pr_debug("%s: cmd[0x%x]; result[0x%x]\n",
+ __func__, payload[0], payload[1]);
+ if (atomic_read(&this_mmap.cmd_state)) {
+ atomic_set(&this_mmap.cmd_state, 0);
+ wake_up(&this_mmap.cmd_wait);
+ }
+ break;
+ default:
+ pr_debug("%s: wrong command[0x%x]\n",
+ __func__, payload[0]);
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+
+static int32_t q6usm_callback(struct apr_client_data *data, void *priv)
+{
+ struct us_client *usc = (struct us_client *)priv;
+ unsigned long dsp_flags;
+ uint32_t *payload = data->payload;
+ uint32_t token = data->token;
+
+ if (usc == NULL) {
+ pr_err("%s: client info is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ if (data->opcode == APR_BASIC_RSP_RESULT) {
+ /* status field check */
+ if (payload[1]) {
+ pr_err("%s: wrong response[%d] on cmd [%d]\n",
+ __func__, payload[1], payload[0]);
+ if (usc->cb)
+ usc->cb(data->opcode, token,
+ (uint32_t *)data->payload, usc->priv);
+ } else {
+ switch (payload[0]) {
+ case USM_SESSION_CMD_RUN:
+ case USM_STREAM_CMD_CLOSE:
+ if (token != usc->session) {
+ pr_err("%s: wrong token[%d]",
+ __func__, token);
+ break;
+ }
+ case USM_STREAM_CMD_OPEN_READ:
+ case USM_STREAM_CMD_OPEN_WRITE:
+ case USM_STREAM_CMD_SET_ENC_PARAM:
+ case USM_DATA_CMD_MEDIA_FORMAT_UPDATE:
+ if (atomic_read(&usc->cmd_state)) {
+ atomic_set(&usc->cmd_state, 0);
+ wake_up(&usc->cmd_wait);
+ }
+ if (usc->cb)
+ usc->cb(data->opcode, token,
+ (uint32_t *)data->payload,
+ usc->priv);
+ break;
+ default:
+ pr_debug("%s: command[0x%x] wrong response\n",
+ __func__, payload[0]);
+ break;
+ }
+ }
+ return 0;
+ }
+
+ switch (data->opcode) {
+ case USM_DATA_EVENT_READ_DONE: {
+ struct us_port_data *port = &usc->port[OUT];
+
+ pr_debug("%s: R-D: stat=%d; buff=%x; size=%d; off=%d\n",
+ __func__,
+ payload[READDONE_IDX_STATUS],
+ payload[READDONE_IDX_BUFFER],
+ payload[READDONE_IDX_SIZE],
+ payload[READDONE_IDX_OFFSET]);
+ pr_debug("msw_ts=%d; lsw_ts=%d; flags=%d; id=%d; num=%d\n",
+ payload[READDONE_IDX_MSW_TS],
+ payload[READDONE_IDX_LSW_TS],
+ payload[READDONE_IDX_FLAGS],
+ payload[READDONE_IDX_ID],
+ payload[READDONE_IDX_NUMFRAMES]);
+
+ spin_lock_irqsave(&port->dsp_lock, dsp_flags);
+ if (payload[READDONE_IDX_STATUS]) {
+ pr_err("%s: wrong READDONE[%d]; token[%d]\n",
+ __func__,
+ payload[READDONE_IDX_STATUS],
+ token);
+ token = USM_WRONG_TOKEN;
+ spin_unlock_irqrestore(&port->dsp_lock,
+ dsp_flags);
+ break;
+ }
+
+ if (port->expected_token != token) {
+ u32 cpu_buf = port->cpu_buf;
+ pr_err("%s: expected[%d] != token[%d]\n",
+ __func__, port->expected_token, token);
+ pr_info("%s: dsp_buf=%d; cpu_buf=%d;\n",
+ __func__, port->dsp_buf, cpu_buf);
+
+ token = USM_WRONG_TOKEN;
+ /* To prevent data handle continiue */
+ port->expected_token = USM_WRONG_TOKEN;
+ spin_unlock_irqrestore(&port->dsp_lock,
+ dsp_flags);
+ break;
+ } /* port->expected_token != data->token */
+
+ port->expected_token = token + 1;
+ if (port->expected_token == port->buf_cnt)
+ port->expected_token = 0;
+
+ /* gap support */
+ if (port->expected_token != port->cpu_buf) {
+ port->dsp_buf = port->expected_token;
+ token = port->dsp_buf; /* for callback */
+ } else
+ port->dsp_buf = token;
+
+ spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
+ break;
+ } /* case USM_DATA_EVENT_READ_DONE */
+
+ case USM_DATA_EVENT_WRITE_DONE: {
+ struct us_port_data *port = &usc->port[IN];
+
+ pr_debug("%s W-D: code[0x%x]; status[0x%x]; token[%d]",
+ __func__,
+ payload[0], payload[1], token);
+
+ if (payload[WRITEDONE_IDX_STATUS]) {
+ pr_err("%s: wrong WRITEDONE_IDX_STATUS[%d]\n",
+ __func__,
+ payload[WRITEDONE_IDX_STATUS]);
+ break;
+ }
+
+ spin_lock_irqsave(&port->dsp_lock, dsp_flags);
+ port->dsp_buf = token + 1;
+ if (port->dsp_buf == port->buf_cnt)
+ port->dsp_buf = 0;
+ spin_unlock_irqrestore(&port->dsp_lock, dsp_flags);
+
+ pr_info("%s: WRITE_DONE: token=%d; dsp_buf=%d; cpu_buf=%d\n",
+ __func__,
+ token, port->dsp_buf, port->cpu_buf);
+
+ break;
+ } /* case USM_DATA_EVENT_WRITE_DONE */
+
+ default:
+ pr_debug("%s: not supported code [0x%x]",
+ __func__, data->opcode);
+ return 0;
+
+ } /* switch */
+
+ if (usc->cb)
+ usc->cb(data->opcode, token,
+ data->payload, usc->priv);
+
+ return 0;
+}
+
+uint32_t q6usm_get_ready_data(int dir, struct us_client *usc)
+{
+ uint32_t ret = 0xffffffff;
+
+ if ((usc != NULL) && ((dir == IN) || (dir == OUT)))
+ ret = usc->port[dir].dsp_buf;
+ return ret;
+}
+
+uint32_t q6usm_get_virtual_address(int dir,
+ struct us_client *usc,
+ struct vm_area_struct *vms)
+{
+ uint32_t ret = 0xffffffff;
+
+ if (vms && (usc != NULL) && ((dir == IN) || (dir == OUT))) {
+ struct us_port_data *port = &usc->port[dir];
+ ret = dma_mmap_coherent(NULL, vms,
+ port->data, port->phys,
+ port->buf_size * port->buf_cnt);
+ }
+ return ret;
+}
+
+static void q6usm_add_hdr(struct us_client *usc, struct apr_hdr *hdr,
+ uint32_t pkt_size, bool cmd_flg)
+{
+ pr_debug("%s: pkt size=%d; cmd_flg=%d\n",
+ __func__, pkt_size, cmd_flg);
+ pr_debug("**************\n");
+ mutex_lock(&usc->cmd_lock);
+ hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
+ APR_HDR_LEN(sizeof(struct apr_hdr)),\
+ APR_PKT_VER);
+ hdr->src_svc = ((struct apr_svc *)usc->apr)->id;
+ hdr->src_domain = APR_DOMAIN_APPS;
+ hdr->dest_svc = APR_SVC_USM;
+ hdr->dest_domain = APR_DOMAIN_ADSP;
+ hdr->src_port = (usc->session << 8) | 0x0001;
+ hdr->dest_port = (usc->session << 8) | 0x0001;
+ if (cmd_flg) {
+ hdr->token = usc->session;
+ atomic_set(&usc->cmd_state, 1);
+ }
+ hdr->pkt_size = APR_PKT_SIZE(APR_HDR_SIZE, pkt_size);
+ mutex_unlock(&usc->cmd_lock);
+ return;
+}
+
+static void q6usm_add_mmaphdr(struct us_client *usc, struct apr_hdr *hdr,
+ uint32_t pkt_size, bool cmd_flg)
+{
+ pr_debug("%s: pkt size=%d cmd_flg=%d\n",
+ __func__, pkt_size, cmd_flg);
+ pr_debug("**************\n");
+ hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, \
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ hdr->src_port = 0;
+ hdr->dest_port = 0;
+ if (cmd_flg) {
+ hdr->token = 0;
+ atomic_set(&this_mmap.cmd_state, 1);
+ }
+ hdr->pkt_size = pkt_size;
+ return;
+}
+
+static uint32_t q6usm_ext2int_format(uint32_t ext_format)
+{
+ uint32_t int_format = INVALID_FORMAT;
+ switch (ext_format) {
+ case FORMAT_USPS_EPOS:
+ int_format = US_POINT_EPOS_FORMAT;
+ break;
+ case FORMAT_USRAW:
+ int_format = US_RAW_FORMAT;
+ break;
+ default:
+ pr_err("%s: Invalid format[%d]\n", __func__, ext_format);
+ break;
+ }
+
+ return int_format;
+}
+
+int q6usm_open_read(struct us_client *usc,
+ uint32_t format)
+{
+ uint32_t int_format = INVALID_FORMAT;
+ int rc = 0x00;
+ struct usm_stream_cmd_open_read open;
+
+ pr_debug("%s: session[%d]", __func__, usc->session);
+
+ if ((usc == NULL) || (usc->apr == NULL)) {
+ pr_err("%s: client or its apr is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ q6usm_add_hdr(usc, &open.hdr, sizeof(open), true);
+ open.hdr.opcode = USM_STREAM_CMD_OPEN_READ;
+ open.src_endpoint = 0; /* AFE */
+ open.pre_proc_top = 0; /* No preprocessing required */
+
+ int_format = q6usm_ext2int_format(format);
+ if (int_format == INVALID_FORMAT)
+ return -EINVAL;
+
+ open.uMode = STREAM_PRIORITY_NORMAL;
+ open.format = int_format;
+
+ rc = apr_send_pkt(usc->apr, (uint32_t *) &open);
+ if (rc < 0) {
+ pr_err("%s: open failed op[0x%x]rc[%d]\n",
+ __func__, open.hdr.opcode, rc);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(usc->cmd_wait,
+ (atomic_read(&usc->cmd_state) == 0),
+ Q6USM_TIMEOUT_JIFFIES);
+ if (!rc) {
+ rc = -ETIME;
+ pr_err("%s: timeout, waited for OPEN_READ rc[%d]\n",
+ __func__, rc);
+ goto fail_cmd;
+ } else
+ rc = 0;
+fail_cmd:
+ return rc;
+}
+
+
+int q6usm_enc_cfg_blk(struct us_client *usc, struct us_encdec_cfg* us_cfg)
+{
+ uint32_t int_format = INVALID_FORMAT;
+ struct usm_stream_cmd_encdec_cfg_blk enc_cfg_obj;
+ struct usm_stream_cmd_encdec_cfg_blk *enc_cfg = &enc_cfg_obj;
+ int rc = 0;
+ uint32_t total_cfg_size =
+ sizeof(struct usm_stream_cmd_encdec_cfg_blk);
+ uint32_t round_params_size = 0;
+ uint8_t is_allocated = 0;
+
+
+ if ((usc == NULL) || (us_cfg == NULL)) {
+ pr_err("%s: wrong input", __func__);
+ return -EINVAL;
+ }
+
+ int_format = q6usm_ext2int_format(us_cfg->format_id);
+ if (int_format == INVALID_FORMAT) {
+ pr_err("%s: wrong input format[%d]",
+ __func__, us_cfg->format_id);
+ return -EINVAL;
+ }
+
+ /* Transparent configuration data is after enc_cfg */
+ /* Integer number of u32s is requred */
+ round_params_size = ((us_cfg->params_size + 3)/4) * 4;
+ if (round_params_size > USM_MAX_CFG_DATA_SIZE) {
+ /* Dynamic allocated encdec_cfg_blk is required */
+ /* static part use */
+ round_params_size -= USM_MAX_CFG_DATA_SIZE;
+ total_cfg_size += round_params_size;
+ enc_cfg = kzalloc(total_cfg_size, GFP_KERNEL);
+ if (enc_cfg == NULL) {
+ pr_err("%s: enc_cfg[%d] allocation failed\n",
+ __func__, total_cfg_size);
+ return -ENOMEM;
+ }
+ is_allocated = 1;
+ } else
+ round_params_size = 0;
+
+ q6usm_add_hdr(usc, &enc_cfg->hdr, total_cfg_size - APR_HDR_SIZE, true);
+
+ enc_cfg->hdr.opcode = USM_STREAM_CMD_SET_ENC_PARAM;
+ enc_cfg->param_id = USM_PARAM_ID_ENCDEC_ENC_CFG_BLK;
+ enc_cfg->param_size = sizeof(struct usm_encode_cfg_blk)+
+ round_params_size;
+ enc_cfg->enc_blk.frames_per_buf = 1;
+ enc_cfg->enc_blk.format_id = int_format;
+ enc_cfg->enc_blk.cfg_size = sizeof(struct usm_cfg_common)+
+ USM_MAX_CFG_DATA_SIZE +
+ round_params_size;
+ memcpy(&(enc_cfg->enc_blk.cfg_common), &(us_cfg->cfg_common),
+ sizeof(struct usm_cfg_common));
+
+ /* Transparent data copy */
+ memcpy(enc_cfg->enc_blk.transp_data, us_cfg->params,
+ us_cfg->params_size);
+ pr_info("%s: cfg_size[%d], params_size[%d]\n",
+ __func__,
+ enc_cfg->enc_blk.cfg_size,
+ us_cfg->params_size);
+ pr_info("%s: params[%d,%d,%d,%d, %d,%d,%d,%d]\n",
+ __func__,
+ enc_cfg->enc_blk.transp_data[0],
+ enc_cfg->enc_blk.transp_data[1],
+ enc_cfg->enc_blk.transp_data[2],
+ enc_cfg->enc_blk.transp_data[3],
+ enc_cfg->enc_blk.transp_data[4],
+ enc_cfg->enc_blk.transp_data[5],
+ enc_cfg->enc_blk.transp_data[6],
+ enc_cfg->enc_blk.transp_data[7]
+ );
+ pr_info("%s: srate:%d, ch=%d, bps= %d; dmap:0x%x; dev_id=0x%x\n",
+ __func__, enc_cfg->enc_blk.cfg_common.sample_rate,
+ enc_cfg->enc_blk.cfg_common.ch_cfg,
+ enc_cfg->enc_blk.cfg_common.bits_per_sample,
+ enc_cfg->enc_blk.cfg_common.data_map,
+ enc_cfg->enc_blk.cfg_common.dev_id);
+
+ rc = apr_send_pkt(usc->apr, (uint32_t *) enc_cfg);
+ if (rc < 0) {
+ pr_err("%s:Comamnd open failed\n", __func__);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(usc->cmd_wait,
+ (atomic_read(&usc->cmd_state) == 0),
+ Q6USM_TIMEOUT_JIFFIES);
+ if (!rc) {
+ rc = -ETIME;
+ pr_err("%s: timeout opcode[0x%x]\n",
+ __func__, enc_cfg->hdr.opcode);
+ } else
+ rc = 0;
+
+fail_cmd:
+ if (is_allocated == 1)
+ kfree(enc_cfg);
+
+ return rc;
+}
+
+int q6usm_dec_cfg_blk(struct us_client *usc, struct us_encdec_cfg *us_cfg)
+{
+
+ uint32_t int_format = INVALID_FORMAT;
+ struct usm_stream_media_format_update dec_cfg_obj;
+ struct usm_stream_media_format_update *dec_cfg = &dec_cfg_obj;
+
+ int rc = 0;
+ uint32_t total_cfg_size = sizeof(struct usm_stream_media_format_update);
+ uint32_t round_params_size = 0;
+ uint8_t is_allocated = 0;
+
+
+ if ((usc == NULL) || (us_cfg == NULL)) {
+ pr_err("%s: wrong input", __func__);
+ return -EINVAL;
+ }
+
+ int_format = q6usm_ext2int_format(us_cfg->format_id);
+ if (int_format == INVALID_FORMAT) {
+ pr_err("%s: wrong input format[%d]",
+ __func__, us_cfg->format_id);
+ return -EINVAL;
+ }
+
+ /* Transparent configuration data is after enc_cfg */
+ /* Integer number of u32s is requred */
+ round_params_size = ((us_cfg->params_size + 3)/4) * 4;
+ if (round_params_size > USM_MAX_CFG_DATA_SIZE) {
+ /* Dynamic allocated encdec_cfg_blk is required */
+ /* static part use */
+ round_params_size -= USM_MAX_CFG_DATA_SIZE;
+ total_cfg_size += round_params_size;
+ dec_cfg = kzalloc(total_cfg_size, GFP_KERNEL);
+ if (dec_cfg == NULL) {
+ pr_err("%s:dec_cfg[%d] allocation failed\n",
+ __func__, total_cfg_size);
+ return -ENOMEM;
+ }
+ is_allocated = 1;
+ } else { /* static transp_data is enough */
+ round_params_size = 0;
+ }
+
+ q6usm_add_hdr(usc, &dec_cfg->hdr, total_cfg_size - APR_HDR_SIZE, true);
+
+ dec_cfg->hdr.opcode = USM_DATA_CMD_MEDIA_FORMAT_UPDATE;
+ dec_cfg->format_id = int_format;
+ dec_cfg->cfg_size = sizeof(struct usm_cfg_common) +
+ USM_MAX_CFG_DATA_SIZE +
+ round_params_size;
+ memcpy(&(dec_cfg->cfg_common), &(us_cfg->cfg_common),
+ sizeof(struct usm_cfg_common));
+ /* Transparent data copy */
+ memcpy(dec_cfg->transp_data, us_cfg->params, us_cfg->params_size);
+ pr_info("%s: cfg_size[%d], params_size[%d]; parambytes[%d,%d,%d,%d]\n",
+ __func__,
+ dec_cfg->cfg_size,
+ us_cfg->params_size,
+ dec_cfg->transp_data[0],
+ dec_cfg->transp_data[1],
+ dec_cfg->transp_data[2],
+ dec_cfg->transp_data[3]
+ );
+
+ rc = apr_send_pkt(usc->apr, (uint32_t *) dec_cfg);
+ if (rc < 0) {
+ pr_err("%s:Comamnd open failed\n", __func__);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(usc->cmd_wait,
+ (atomic_read(&usc->cmd_state) == 0),
+ Q6USM_TIMEOUT_JIFFIES);
+ if (!rc) {
+ rc = -ETIME;
+ pr_err("%s: timeout opcode[0x%x]\n",
+ __func__, dec_cfg->hdr.opcode);
+ } else
+ rc = 0;
+
+fail_cmd:
+ if (is_allocated == 1)
+ kfree(dec_cfg);
+
+ return rc;
+}
+
+int q6usm_open_write(struct us_client *usc,
+ uint32_t format)
+{
+ int rc = 0;
+ uint32_t int_format = INVALID_FORMAT;
+ struct usm_stream_cmd_open_write open;
+
+ pr_debug("%s: session[%d]", __func__, usc->session);
+
+ if ((usc == NULL) || (usc->apr == NULL)) {
+ pr_err("%s: APR handle NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ q6usm_add_hdr(usc, &open.hdr, sizeof(open), true);
+ open.hdr.opcode = USM_STREAM_CMD_OPEN_WRITE;
+
+ int_format = q6usm_ext2int_format(format);
+ if (int_format == INVALID_FORMAT) {
+ pr_err("%s: wrong format[%d]", __func__, format);
+ return -EINVAL;
+ }
+
+ open.format = int_format;
+
+ rc = apr_send_pkt(usc->apr, (uint32_t *) &open);
+ if (rc < 0) {
+ pr_err("%s:open failed op[0x%x]rc[%d]\n", \
+ __func__, open.hdr.opcode, rc);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(usc->cmd_wait,
+ (atomic_read(&usc->cmd_state) == 0),
+ Q6USM_TIMEOUT_JIFFIES);
+ if (!rc) {
+ rc = -ETIME;
+ pr_err("%s:timeout. waited for OPEN_WRITR rc[%d]\n",
+ __func__, rc);
+ goto fail_cmd;
+ } else
+ rc = 0;
+
+fail_cmd:
+ return rc;
+}
+
+int q6usm_run(struct us_client *usc, uint32_t flags,
+ uint32_t msw_ts, uint32_t lsw_ts)
+{
+ struct usm_stream_cmd_run run;
+ int rc = 0;
+
+ if ((usc == NULL) || (usc->apr == NULL)) {
+ pr_err("%s: APR handle NULL\n", __func__);
+ return -EINVAL;
+ }
+ q6usm_add_hdr(usc, &run.hdr, sizeof(run), true);
+
+ run.hdr.opcode = USM_SESSION_CMD_RUN;
+ run.flags = flags;
+ run.msw_ts = msw_ts;
+ run.lsw_ts = lsw_ts;
+
+ rc = apr_send_pkt(usc->apr, (uint32_t *) &run);
+ if (rc < 0) {
+ pr_err("%s: Commmand run failed[%d]\n", __func__, rc);
+ goto fail_cmd;
+ }
+
+ rc = wait_event_timeout(usc->cmd_wait,
+ (atomic_read(&usc->cmd_state) == 0),
+ Q6USM_TIMEOUT_JIFFIES);
+ if (!rc) {
+ rc = -ETIME;
+ pr_err("%s: timeout. waited for run success rc[%d]\n",
+ __func__, rc);
+ } else
+ rc = 0;
+
+fail_cmd:
+ return rc;
+}
+
+
+int q6usm_memory_map(struct us_client *usc, uint32_t buf_add, int dir,
+ uint32_t bufsz, uint32_t bufcnt)
+{
+ struct usm_stream_cmd_memory_map mem_map;
+ int rc = 0;
+
+ if ((usc == NULL) || (usc->apr == NULL) || (this_mmap.apr == NULL)) {
+ pr_err("%s: APR handle NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ q6usm_add_mmaphdr(usc, &mem_map.hdr,
+ sizeof(struct usm_stream_cmd_memory_map), true);
+ mem_map.hdr.opcode = USM_SESSION_CMD_MEMORY_MAP;
+
+ mem_map.buf_add = buf_add;
+ mem_map.buf_size = bufsz * bufcnt;
+ mem_map.mempool_id = 0;
+
+ pr_debug("%s: buf add[%x] buf_add_parameter[%x]\n",
+ __func__, mem_map.buf_add, buf_add);
+
+ rc = apr_send_pkt(this_mmap.apr, (uint32_t *) &mem_map);
+ if (rc < 0) {
+ pr_err("%s: mem_map op[0x%x]rc[%d]\n",
+ __func__, mem_map.hdr.opcode, rc);
+ goto fail_cmd;
+ }
+
+ rc = wait_event_timeout(this_mmap.cmd_wait,
+ (atomic_read(&this_mmap.cmd_state) == 0),
+ Q6USM_TIMEOUT_JIFFIES);
+ if (!rc) {
+ rc = -ETIME;
+ pr_err("%s: timeout. waited for memory_map\n", __func__);
+ } else
+ rc = 0;
+fail_cmd:
+ return rc;
+}
+
+int q6usm_memory_unmap(struct us_client *usc, uint32_t buf_add, int dir)
+{
+ struct usm_stream_cmd_memory_unmap mem_unmap;
+ int rc = 0;
+
+ if ((usc == NULL) || (usc->apr == NULL) || (this_mmap.apr == NULL)) {
+ pr_err("%s: APR handle NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ q6usm_add_mmaphdr(usc, &mem_unmap.hdr,
+ sizeof(struct usm_stream_cmd_memory_unmap), true);
+ mem_unmap.hdr.opcode = USM_SESSION_CMD_MEMORY_UNMAP;
+ mem_unmap.buf_add = buf_add;
+
+ rc = apr_send_pkt(this_mmap.apr, (uint32_t *) &mem_unmap);
+ if (rc < 0) {
+ pr_err("%s:mem_unmap op[0x%x]rc[%d]\n",
+ __func__, mem_unmap.hdr.opcode, rc);
+ goto fail_cmd;
+ }
+
+ rc = wait_event_timeout(this_mmap.cmd_wait,
+ (atomic_read(&this_mmap.cmd_state) == 0),
+ Q6USM_TIMEOUT_JIFFIES);
+ if (!rc) {
+ rc = -ETIME;
+ pr_err("%s: timeout. waited for memory_map\n", __func__);
+ } else
+ rc = 0;
+fail_cmd:
+ return rc;
+}
+
+int q6usm_read(struct us_client *usc, uint32_t read_ind)
+{
+ struct usm_stream_cmd_read read;
+ struct us_port_data *port = NULL;
+ int rc = 0;
+ u32 read_counter = 0;
+ u32 loop_ind = 0;
+
+ if ((usc == NULL) || (usc->apr == NULL)) {
+ pr_err("%s: APR handle NULL\n", __func__);
+ return -EINVAL;
+ }
+ port = &usc->port[OUT];
+
+ if (read_ind > port->buf_cnt) {
+ pr_err("%s: wrong read_ind[%d]\n",
+ __func__, read_ind);
+ return -EINVAL;
+ }
+ if (read_ind == port->cpu_buf) {
+ pr_err("%s: no free region\n", __func__);
+ return 0;
+ }
+
+ if (read_ind > port->cpu_buf) { /* 1 range */
+ read_counter = read_ind - port->cpu_buf;
+ } else { /* 2 ranges */
+ read_counter = (port->buf_cnt - port->cpu_buf) + read_ind;
+ }
+
+ q6usm_add_hdr(usc, &read.hdr, (sizeof(read) - APR_HDR_SIZE), false);
+
+ read.hdr.opcode = USM_DATA_CMD_READ;
+ read.buf_size = port->buf_size;
+
+ for (loop_ind = 0; loop_ind < read_counter; ++loop_ind) {
+ u32 temp_cpu_buf = port->cpu_buf;
+
+ read.buf_add = (uint32_t)(port->phys) +
+ port->buf_size * (port->cpu_buf);
+ read.uid = port->cpu_buf;
+ read.hdr.token = port->cpu_buf;
+ read.counter = 1;
+
+ ++(port->cpu_buf);
+ if (port->cpu_buf == port->buf_cnt)
+ port->cpu_buf = 0;
+
+ rc = apr_send_pkt(usc->apr, (uint32_t *) &read);
+
+ if (rc < 0) {
+ port->cpu_buf = temp_cpu_buf;
+
+ pr_err("%s:read op[0x%x]rc[%d]\n",
+ __func__, read.hdr.opcode, rc);
+ break;
+ } else
+ rc = 0;
+ } /* bufs loop */
+
+ return rc;
+}
+
+int q6usm_write(struct us_client *usc, uint32_t write_ind)
+{
+ int rc = 0;
+ struct usm_stream_cmd_write cmd_write;
+ struct us_port_data *port = NULL;
+ u32 current_dsp_buf = 0;
+
+ if ((usc == NULL) || (usc->apr == NULL)) {
+ pr_err("%s: APR handle NULL\n", __func__);
+ return -EINVAL;
+ }
+ port = &usc->port[IN];
+
+ current_dsp_buf = port->dsp_buf;
+ /* free region, caused by new dsp_buf report from DSP, */
+ /* can be only extended */
+ if (port->cpu_buf >= current_dsp_buf) {
+ /* 2 -part free region, including empty buffer */
+ if ((write_ind <= port->cpu_buf) &&
+ (write_ind > current_dsp_buf)) {
+ pr_err("%s: wrong w_ind[%d]; d_buf=%d; c_buf=%d\n",
+ __func__, write_ind,
+ current_dsp_buf, port->cpu_buf);
+ return -EINVAL;
+ }
+ } else {
+ /* 1 -part free region */
+ if ((write_ind <= port->cpu_buf) ||
+ (write_ind > current_dsp_buf)) {
+ pr_err("%s: wrong w_ind[%d]; d_buf=%d; c_buf=%d\n",
+ __func__, write_ind,
+ current_dsp_buf, port->cpu_buf);
+ return -EINVAL;
+ }
+ }
+
+ q6usm_add_hdr(usc, &cmd_write.hdr,
+ (sizeof(cmd_write) - APR_HDR_SIZE), false);
+
+ cmd_write.hdr.opcode = USM_DATA_CMD_WRITE;
+ cmd_write.buf_size = port->buf_size;
+
+ while (port->cpu_buf != write_ind) {
+ u32 temp_cpu_buf = port->cpu_buf;
+
+ cmd_write.buf_add = (uint32_t)(port->phys) +
+ port->buf_size * (port->cpu_buf);
+ cmd_write.uid = port->cpu_buf;
+ cmd_write.hdr.token = port->cpu_buf;
+
+ pr_debug("%s:buf addr[0x%x] size[%d] token[%d] uid[%d]\n",
+ __func__, cmd_write.buf_add, cmd_write.buf_size,
+ cmd_write.hdr.token, cmd_write.uid);
+ pr_debug("%s: data=0x%p\n", __func__, port->data);
+
+ ++(port->cpu_buf);
+ if (port->cpu_buf == port->buf_cnt)
+ port->cpu_buf = 0;
+
+ rc = apr_send_pkt(usc->apr, (uint32_t *) &cmd_write);
+
+ if (rc < 0) {
+ port->cpu_buf = temp_cpu_buf;
+ pr_err("%s:write op[0x%x];rc[%d];cpu_buf[%d]\n",
+ __func__, cmd_write.hdr.opcode,
+ rc, port->cpu_buf);
+ break;
+ }
+
+ rc = 0;
+ }
+
+ pr_debug("%s:exit: rc=%d; write_ind=%d; cpu_buf=%d; dsp_buf=%d\n",
+ __func__, rc, write_ind, port->cpu_buf, port->dsp_buf);
+
+ return rc;
+}
+
+bool q6usm_is_write_buf_full(struct us_client *usc, uint32_t* free_region)
+{
+ struct us_port_data *port = NULL;
+ u32 cpu_buf = 0;
+
+ if ((usc == NULL) || !free_region) {
+ pr_err("%s: input data wrong\n", __func__);
+ return false;
+ }
+ port = &usc->port[IN];
+ cpu_buf = port->cpu_buf + 1;
+ if (cpu_buf == port->buf_cnt)
+ cpu_buf = 0;
+
+ *free_region = port->dsp_buf;
+
+ return cpu_buf == *free_region;
+}
+
+int q6usm_cmd(struct us_client *usc, int cmd)
+{
+ struct apr_hdr hdr;
+ int rc = 0;
+ atomic_t *state;
+
+ if ((usc == NULL) || (usc->apr == NULL)) {
+ pr_err("%s: APR handle NULL\n", __func__);
+ return -EINVAL;
+ }
+ q6usm_add_hdr(usc, &hdr, (sizeof(hdr) - APR_HDR_SIZE), true);
+ switch (cmd) {
+ case CMD_CLOSE:
+ hdr.opcode = USM_STREAM_CMD_CLOSE;
+ state = &usc->cmd_state;
+ break;
+
+ default:
+ pr_err("%s:Invalid format[%d]\n", __func__, cmd);
+ goto fail_cmd;
+ }
+
+ pr_debug("%s:session[%d]opcode[0x%x] ", __func__,
+ usc->session, hdr.opcode);
+ rc = apr_send_pkt(usc->apr, (uint32_t *) &hdr);
+ if (rc < 0) {
+ pr_err("%s: Command 0x%x failed\n", __func__, hdr.opcode);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(usc->cmd_wait, (atomic_read(state) == 0),
+ Q6USM_TIMEOUT_JIFFIES);
+ if (!rc) {
+ rc = -ETIME;
+ pr_err("%s:timeout. waited for response opcode[0x%x]\n",
+ __func__, hdr.opcode);
+ } else
+ rc = 0;
+fail_cmd:
+ return rc;
+}
+
+static int __init q6usm_init(void)
+{
+ pr_debug("%s\n", __func__);
+ init_waitqueue_head(&this_mmap.cmd_wait);
+ memset(session, 0, sizeof(session));
+ return 0;
+}
+
+device_initcall(q6usm_init);
+
+MODULE_DESCRIPTION("Interface with QDSP6:USM");
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.h b/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.h
new file mode 100644
index 0000000..fe12ee1
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/q6usm.h
@@ -0,0 +1,109 @@
+/* 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 __Q6_USM_H__
+#define __Q6_USM_H__
+
+#include <mach/qdsp6v2/apr_us.h>
+
+#define FORMAT_USPS_EPOS 0x00000000
+#define FORMAT_USRAW 0x00000001
+#define INVALID_FORMAT 0xffffffff
+
+#define IN 0x000
+#define OUT 0x001
+
+#define USM_WRONG_TOKEN 0xffffffff
+#define USM_UNDEF_TOKEN 0xfffffffe
+
+#define CMD_CLOSE 0x0004
+
+/* bit 0:1 represents priority of stream */
+#define STREAM_PRIORITY_NORMAL 0x0000
+#define STREAM_PRIORITY_LOW 0x0001
+#define STREAM_PRIORITY_HIGH 0x0002
+
+/* bit 4 represents META enable of encoded data buffer */
+#define BUFFER_META_ENABLE 0x0010
+
+struct us_region {
+ dma_addr_t phys;
+ /* If == NULL, the region isn't allocated */
+ void *data;
+ /* number of buffers in the region */
+ uint32_t buf_cnt;
+ /* size of buffer */
+ uint32_t buf_size;
+};
+
+struct us_port_data {
+ dma_addr_t phys;
+ /* cyclic region of buffers with 1 gap */
+ void *data;
+ /* number of buffers in the region */
+ uint32_t buf_cnt;
+ /* size of buffer */
+ uint32_t buf_size;
+ /* TX: write index */
+ uint32_t dsp_buf;
+ /* TX: read index */
+ uint32_t cpu_buf;
+ /* expected token from dsp */
+ uint32_t expected_token;
+ /* read or write locks */
+ struct mutex lock;
+ spinlock_t dsp_lock;
+};
+
+struct us_client {
+ int session;
+ /* idx:1 out port, 0: in port*/
+ struct us_port_data port[2];
+
+ struct apr_svc *apr;
+ struct mutex cmd_lock;
+
+ atomic_t cmd_state;
+ atomic_t eos_state;
+ wait_queue_head_t cmd_wait;
+
+ void (*cb)(uint32_t, uint32_t, uint32_t *, void *);
+ void *priv;
+};
+
+int q6usm_run(struct us_client *usc, uint32_t flags,
+ uint32_t msw_ts, uint32_t lsw_ts);
+int q6usm_cmd(struct us_client *usc, int cmd);
+int q6usm_us_client_buf_alloc(unsigned int dir, struct us_client *usc,
+ unsigned int bufsz, unsigned int bufcnt);
+int q6usm_enc_cfg_blk(struct us_client *usc, struct us_encdec_cfg *us_cfg);
+int q6usm_dec_cfg_blk(struct us_client *usc, struct us_encdec_cfg *us_cfg);
+int q6usm_read(struct us_client *usc, uint32_t read_ind);
+struct us_client *q6usm_us_client_alloc(
+ void (*cb)(uint32_t, uint32_t, uint32_t *, void *),
+ void *priv);
+int q6usm_open_read(struct us_client *usc, uint32_t format);
+void q6usm_us_client_free(struct us_client *usc);
+int q6usm_memory_map(struct us_client *usc, uint32_t buf_add,
+ int dir, uint32_t bufsz, uint32_t bufcnt);
+int q6usm_memory_unmap(struct us_client *usc, uint32_t buf_add,
+ int dir);
+
+uint32_t q6usm_get_ready_data(int dir, struct us_client *usc);
+uint32_t q6usm_get_virtual_address(int dir, struct us_client *usc,
+ struct vm_area_struct *vms);
+
+int q6usm_open_write(struct us_client *usc, uint32_t format);
+int q6usm_write(struct us_client *usc, uint32_t write_ind);
+bool q6usm_is_write_buf_full(struct us_client *usc, uint32_t* free_region);
+
+#endif /* __Q6_USM_H__ */
diff --git a/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
new file mode 100644
index 0000000..bfe0006
--- /dev/null
+++ b/arch/arm/mach-msm/qdsp6v2/ultrasound/usf.c
@@ -0,0 +1,1006 @@
+/* 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.
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/wait.h>
+#include <linux/input.h>
+#include <linux/uaccess.h>
+#include <linux/time.h>
+#include <asm/mach-types.h>
+#include <sound/apr_audio.h>
+#include <mach/qdsp6v2/usf.h>
+#include "q6usm.h"
+
+/* The driver version*/
+#define DRV_VERSION "1.0"
+
+/* Standard timeout in the asynchronous ops */
+#define USF_TIMEOUT_JIFFIES (3*HZ) /* 3 sec */
+
+/* Undefined USF device */
+#define USF_UNDEF_DEV_ID 0xffff
+
+/* RX memory mapping flag */
+#define USF_VM_WRITE 2
+
+/* The driver states */
+enum usf_state_type {
+ USF_IDLE_STATE,
+ USF_OPENED_STATE,
+ USF_CONFIGURED_STATE,
+ USF_WORK_STATE,
+ USF_ERROR_STATE
+};
+
+struct usf_xx_type {
+ /* Name of the client - event calculator */
+ char client_name[USF_MAX_CLIENT_NAME_SIZE];
+ /* The driver state in TX or RX direction */
+ enum usf_state_type usf_state;
+ /* wait for q6 events mechanism */
+ wait_queue_head_t wait;
+ /* IF with q6usm info */
+ struct us_client *usc;
+ /* Q6:USM' Encoder/decoder configuration */
+ struct us_encdec_cfg encdec_cfg;
+ /* Shared buffer (with Q6:USM) size */
+ uint32_t buffer_size;
+ /* Number of the shared buffers (with Q6:USM) */
+ uint32_t buffer_count;
+ /* Shared memory (Cyclic buffer with 1 gap) control */
+ uint32_t new_region;
+ uint32_t prev_region;
+ /* Q6:USM's events handler */
+ void (*cb)(uint32_t, uint32_t, uint32_t *, void *);
+ /* User's update info isn't acceptable */
+ u8 user_upd_info_na;
+};
+
+struct usf_type {
+ /* TX device component configuration & control */
+ struct usf_xx_type usf_tx;
+ /* RX device component configuration & control */
+ struct usf_xx_type usf_rx;
+ /* Index into the opened device container */
+ /* To prevent mutual usage of the same device */
+ uint16_t dev_ind;
+ /* Event types, supported by device */
+ uint16_t event_types;
+ /* The device is "input" module registered client */
+ struct input_dev *input_if;
+};
+
+/* The MAX number of the supported devices */
+#define MAX_DEVS_NUMBER 1
+
+/* The opened devices container */
+static int s_opened_devs[MAX_DEVS_NUMBER];
+
+static void usf_rx_cb(uint32_t opcode, uint32_t token,
+ uint32_t *payload, void *priv)
+{
+ struct usf_xx_type *usf_xx = (struct usf_xx_type *) priv;
+
+ if (usf_xx == NULL) {
+ pr_err("%s: the private data is NULL\n", __func__);
+ return;
+ }
+
+ switch (opcode) {
+ case USM_DATA_EVENT_WRITE_DONE:
+ wake_up(&usf_xx->wait);
+ break;
+ default:
+ break;
+ }
+}
+
+static void usf_tx_cb(uint32_t opcode, uint32_t token,
+ uint32_t *payload, void *priv)
+{
+ struct usf_xx_type *usf_xx = (struct usf_xx_type *) priv;
+
+ if (usf_xx == NULL) {
+ pr_err("%s: the private data is NULL\n", __func__);
+ return;
+ }
+
+ switch (opcode) {
+ case USM_DATA_EVENT_READ_DONE:
+ if (token == USM_WRONG_TOKEN)
+ usf_xx->usf_state = USF_ERROR_STATE;
+ usf_xx->new_region = token;
+ wake_up(&usf_xx->wait);
+ break;
+
+ case APR_BASIC_RSP_RESULT:
+ if (payload[1]) {
+ usf_xx->usf_state = USF_ERROR_STATE;
+ usf_xx->new_region = USM_WRONG_TOKEN;
+ wake_up(&usf_xx->wait);
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void release_xx(struct usf_xx_type *usf_xx)
+{
+ if (usf_xx != NULL) {
+ if (usf_xx->usc) {
+ q6usm_us_client_free(usf_xx->usc);
+ usf_xx->usc = NULL;
+ }
+
+ if (usf_xx->encdec_cfg.params != NULL) {
+ kfree(usf_xx->encdec_cfg.params);
+ usf_xx->encdec_cfg.params = NULL;
+ }
+ }
+}
+
+static void usf_disable(struct usf_xx_type *usf_xx)
+{
+ if (usf_xx != NULL) {
+ if ((usf_xx->usf_state != USF_IDLE_STATE) &&
+ (usf_xx->usf_state != USF_OPENED_STATE)) {
+ (void)q6usm_cmd(usf_xx->usc, CMD_CLOSE);
+ usf_xx->usf_state = USF_OPENED_STATE;
+ wake_up(&usf_xx->wait);
+ }
+ release_xx(usf_xx);
+ }
+}
+
+static int config_xx(struct usf_xx_type *usf_xx, struct us_xx_info_type *config)
+{
+ int rc = 0;
+ uint16_t data_map_size = 0;
+
+ if ((usf_xx == NULL) ||
+ (config == NULL))
+ return -EINVAL;
+
+ data_map_size = sizeof(usf_xx->encdec_cfg.cfg_common.data_map);
+
+ if (config->client_name != NULL) {
+ if (strncpy_from_user(usf_xx->client_name,
+ config->client_name,
+ sizeof(usf_xx->client_name) - 1) < 0) {
+ pr_err("%s: get client name failed\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ pr_info("%s: name=%s; buf_size:%d; dev_id:0x%x; sample_rate:%d\n",
+ __func__, usf_xx->client_name, config->buf_size,
+ config->dev_id, config->sample_rate);
+
+ pr_info("%s: buf_num:%d; format:%d; port_cnt:%d; data_size=%d\n",
+ __func__, config->buf_num, config->stream_format,
+ config->port_cnt, config->params_data_size);
+
+ pr_debug("%s: p_id[0]=%d, p_id[1]=%d, p_id[2]=%d, p_id[3]=%d\n",
+ __func__,
+ config->port_id[0],
+ config->port_id[1],
+ config->port_id[2],
+ config->port_id[3]);
+
+ if (data_map_size < config->port_cnt) {
+ pr_err("%s: number of supported ports:%d < requested:%d\n",
+ __func__,
+ data_map_size,
+ config->port_cnt);
+ return -EINVAL;
+ }
+
+ /* q6usm allocation & configuration */
+ usf_xx->buffer_size = config->buf_size;
+ usf_xx->buffer_count = config->buf_num;
+ usf_xx->encdec_cfg.cfg_common.bits_per_sample =
+ config->bits_per_sample;
+ usf_xx->encdec_cfg.cfg_common.sample_rate = config->sample_rate;
+ /* AFE port e.g. AFE_PORT_ID_SLIMBUS_MULTI_CHAN_1_RX */
+ usf_xx->encdec_cfg.cfg_common.dev_id = config->dev_id;
+
+ usf_xx->encdec_cfg.cfg_common.ch_cfg = config->port_cnt;
+ memcpy((void *)&usf_xx->encdec_cfg.cfg_common.data_map,
+ (void *)config->port_id,
+ config->port_cnt);
+ if (rc) {
+ pr_err("%s: ports offsets copy failure\n", __func__);
+ return -EINVAL;
+ }
+
+ usf_xx->encdec_cfg.format_id = config->stream_format;
+ usf_xx->encdec_cfg.params_size = config->params_data_size;
+ usf_xx->user_upd_info_na = 1; /* it's used in US_GET_TX_UPDATE */
+
+ if (config->params_data_size > 0) { /* transparent data copy */
+ usf_xx->encdec_cfg.params = kzalloc(config->params_data_size,
+ GFP_KERNEL);
+ if (usf_xx->encdec_cfg.params == NULL) {
+ pr_err("%s: params memory alloc[%d] failure\n",
+ __func__,
+ config->params_data_size);
+ return -ENOMEM;
+ }
+ rc = copy_from_user(usf_xx->encdec_cfg.params,
+ config->params_data,
+ config->params_data_size);
+ if (rc) {
+ pr_err("%s: transparent data copy failure\n",
+ __func__);
+ kfree(usf_xx->encdec_cfg.params);
+ usf_xx->encdec_cfg.params = NULL;
+ return -EINVAL;
+ }
+ pr_debug("%s: params_size[%d]; params[%d,%d,%d,%d, %d]\n",
+ __func__,
+ config->params_data_size,
+ usf_xx->encdec_cfg.params[0],
+ usf_xx->encdec_cfg.params[1],
+ usf_xx->encdec_cfg.params[2],
+ usf_xx->encdec_cfg.params[3],
+ usf_xx->encdec_cfg.params[4]
+ );
+ }
+
+ usf_xx->usc = q6usm_us_client_alloc(usf_xx->cb, (void *)usf_xx);
+ if (!usf_xx->usc) {
+ pr_err("%s: Could not allocate q6usm client\n", __func__);
+ rc = -EFAULT;
+ }
+
+ return rc;
+}
+
+static int register_input_device(struct usf_type *usf_info,
+ struct us_input_info_type *input_info)
+{
+ int rc = 0;
+ struct input_dev *input_dev = NULL;
+
+ if ((usf_info == NULL) ||
+ (input_info == NULL) ||
+ !(input_info->event_types & USF_ALL_EVENTS)) {
+ pr_err("%s: wrong input parameter(s)\n", __func__);
+ return -EINVAL;
+ }
+
+ if (usf_info->input_if != NULL) {
+ pr_err("%s: input_if is already allocated\n", __func__);
+ return -EFAULT;
+ }
+
+ input_dev = input_allocate_device();
+ if (input_dev == NULL) {
+ pr_err("%s: input_allocate_device() failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ /* Common part configuration */
+ input_dev->name = (const char *)(usf_info->usf_tx.client_name);
+ input_dev->phys = NULL;
+ input_dev->id.bustype = BUS_HOST;
+ input_dev->id.vendor = 0x0001;
+ input_dev->id.product = 0x0001;
+ input_dev->id.version = 0x0001;
+
+ if (input_info->event_types & USF_TSC_EVENT) {
+ /* TSC part configuration */
+ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+ input_set_abs_params(input_dev, ABS_X,
+ input_info->tsc_x_dim[0],
+ input_info->tsc_x_dim[1],
+ input_info->tsc_x_fuzz, 0);
+ input_set_abs_params(input_dev, ABS_Y,
+ input_info->tsc_y_dim[0],
+ input_info->tsc_y_dim[1],
+ input_info->tsc_y_fuzz, 0);
+
+ input_set_abs_params(input_dev, ABS_PRESSURE,
+ input_info->tsc_pressure[0],
+ input_info->tsc_pressure[1], 0, 0);
+
+ }
+
+ if (input_info->event_types & USF_MOUSE_EVENT) {
+ /* Mouse part configuration */
+ input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
+
+ input_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
+ BIT_MASK(BTN_RIGHT) |
+ BIT_MASK(BTN_MIDDLE);
+ input_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
+ }
+
+ if (input_info->event_types & USF_KEYBOARD_EVENT) {
+ /* Keyboard part configuration */
+ input_dev->evbit[0] |= BIT_MASK(EV_KEY);
+
+ /* All keys are permitted */
+ memset(input_dev->keybit, 0xff, sizeof(input_dev->keybit));
+ }
+
+ rc = input_register_device(input_dev);
+ if (rc) {
+ pr_err("%s: input_register_device() failed; rc=%d\n",
+ __func__, rc);
+ input_free_device(input_dev);
+ } else {
+ usf_info->input_if = input_dev;
+ usf_info->event_types = input_info->event_types;
+ pr_info("%s: input device[%s] was registered\n",
+ __func__, input_dev->name);
+ }
+
+ return rc;
+
+}
+
+static void notify_tsc_event(struct input_dev *input_if,
+ int x, int y, int pressure)
+{
+ if (pressure) {
+ input_report_abs(input_if, ABS_X, x);
+ input_report_abs(input_if, ABS_Y, y);
+ input_report_abs(input_if, ABS_PRESSURE, pressure);
+ input_report_key(input_if, BTN_TOUCH, !!pressure);
+ } else {
+ input_report_abs(input_if, ABS_PRESSURE, 0);
+ input_report_key(input_if, BTN_TOUCH, 0);
+ }
+
+ input_sync(input_if);
+
+ pr_debug("%s: TSC event: x[%d], y[%d], pressure[%d]\n",
+ __func__, x, y, pressure);
+}
+
+static void notify_mouse_event(struct input_dev *input_if,
+ struct mouse_event_type *me)
+{
+ if (me == NULL) {
+ pr_err("%s: mouse event is NULL\n", __func__);
+ return;
+ }
+
+ input_report_rel(input_if, REL_X, me->rels[0]);
+ input_report_rel(input_if, REL_Y, me->rels[1]);
+
+ input_report_key(input_if, BTN_LEFT,
+ me->buttons_states & USF_BUTTON_LEFT_MASK);
+ input_report_key(input_if, BTN_MIDDLE,
+ me->buttons_states & USF_BUTTON_MIDDLE_MASK);
+ input_report_key(input_if, BTN_RIGHT,
+ me->buttons_states & USF_BUTTON_RIGHT_MASK);
+
+ input_sync(input_if);
+
+ pr_debug("%s: mouse event: dx[%d], dy[%d], buttons_states[%d]\n",
+ __func__, me->rels[0], me->rels[1], me->buttons_states);
+}
+
+static void notify_key_event(struct input_dev *input_if,
+ struct key_event_type *ke)
+{
+ if (ke == NULL) {
+ pr_err("%s: key event is NULL\n", __func__);
+ return;
+ }
+
+ input_report_key(input_if, ke->key, ke->key_state);
+ input_sync(input_if);
+ pr_debug("%s: key event: key[%d], state[%d]\n",
+ __func__,
+ ke->key,
+ ke->key_state);
+
+}
+
+static void handle_input_event(struct usf_type *usf_info,
+ uint16_t event_counter,
+ struct usf_event_type *event)
+{
+ struct input_dev *input_if = NULL;
+ uint16_t ind = 0;
+
+ if ((usf_info == NULL) || (usf_info->input_if == NULL) ||
+ (event == NULL) || (!event_counter)) {
+ return;
+ }
+
+ input_if = usf_info->input_if;
+
+ for (ind = 0; ind < event_counter; ++ind) {
+ event += ind;
+ if (event->event_type & usf_info->event_types) {
+ /* the event is supported */
+ if (event->event_type & USF_TSC_EVENT) {
+ struct point_event_type *pe =
+ &(event->event_data.point_event);
+ if (pe->coordinates_type ==
+ USF_PIX_COORDINATE) {
+ notify_tsc_event(input_if,
+ pe->coordinates[0],
+ pe->coordinates[1],
+ pe->pressure);
+ } else
+ pr_debug("%s: wrong coord type:%d\n",
+ __func__,
+ pe->coordinates_type);
+
+ continue;
+ }
+
+ if (event->event_type & USF_MOUSE_EVENT) {
+ notify_mouse_event(input_if,
+ &(event->event_data.mouse_event));
+ continue;
+ }
+
+ if (event->event_type & USF_KEYBOARD_EVENT) {
+ notify_key_event(input_if,
+ &(event->event_data.key_event));
+ continue;
+ }
+ } /* the event is supported */
+ }
+}
+
+static int usf_start_tx(struct usf_xx_type *usf_xx)
+{
+ int rc = q6usm_run(usf_xx->usc, 0, 0, 0);
+
+ pr_debug("%s: tx: q6usm_run; rc=%d\n", __func__, rc);
+ if (!rc) {
+ /* supply all buffers */
+ rc = q6usm_read(usf_xx->usc,
+ usf_xx->buffer_count);
+ pr_debug("%s: q6usm_read[%d]\n",
+ __func__, rc);
+
+ if (rc)
+ pr_err("%s: buf read failed",
+ __func__);
+ else
+ usf_xx->usf_state =
+ USF_WORK_STATE;
+ }
+
+ return rc;
+} /* usf_start_tx */
+
+static int usf_start_rx(struct usf_xx_type *usf_xx)
+{
+ int rc = q6usm_run(usf_xx->usc, 0, 0, 0);
+
+ pr_debug("%s: rx: q6usm_run; rc=%d\n",
+ __func__, rc);
+ if (!rc)
+ usf_xx->usf_state = USF_WORK_STATE;
+
+ return rc;
+} /* usf_start_rx */
+
+static int usf_set_tx_info(struct usf_type *usf, unsigned long arg)
+{
+ struct us_tx_info_type config_tx;
+ const char *name = NULL;
+ struct usf_xx_type *usf_xx = &usf->usf_tx;
+ int rc = copy_from_user(&config_tx,
+ (void *) arg,
+ sizeof(config_tx));
+
+ if (rc) {
+ pr_err("%s: copy error[%d]\n",
+ __func__, rc);
+ return -EINVAL;
+ }
+
+ name = config_tx.us_xx_info.client_name;
+
+ usf_xx->new_region = USM_UNDEF_TOKEN;
+ usf_xx->prev_region = USM_UNDEF_TOKEN;
+ usf_xx->cb = usf_tx_cb;
+
+ init_waitqueue_head(&usf_xx->wait);
+
+ if (name != NULL) {
+ int res = strncpy_from_user(
+ usf_xx->client_name,
+ name,
+ sizeof(usf_xx->client_name)-1);
+ if (res < 0) {
+ pr_err("%s: get client name failed\n",
+ __func__);
+ return -EINVAL;
+ }
+ }
+
+ rc = config_xx(usf_xx, &config_tx.us_xx_info);
+ if (rc)
+ return rc;
+
+ rc = q6usm_open_read(usf_xx->usc,
+ usf_xx->encdec_cfg.format_id);
+ if (rc)
+ return rc;
+
+ rc = q6usm_us_client_buf_alloc(OUT, usf_xx->usc,
+ usf_xx->buffer_size,
+ usf_xx->buffer_count);
+ if (rc)
+ return rc;
+
+ rc = q6usm_enc_cfg_blk(usf_xx->usc,
+ &usf_xx->encdec_cfg);
+ if (!rc) {
+ rc = register_input_device(usf,
+ &config_tx.input_info);
+ if (!rc)
+ usf_xx->usf_state = USF_CONFIGURED_STATE;
+ }
+
+ return rc;
+} /* usf_set_tx_info */
+
+static int usf_set_rx_info(struct usf_type *usf, unsigned long arg)
+{
+ struct us_rx_info_type config_rx;
+ struct usf_xx_type *usf_xx = &usf->usf_rx;
+ int rc = copy_from_user(&config_rx,
+ (void *) arg,
+ sizeof(config_rx));
+
+ if (rc) {
+ pr_err("%s: copy_from_user() failed[%d]\n",
+ __func__, rc);
+ return -EINVAL;
+ }
+
+ usf_xx->new_region = USM_UNDEF_TOKEN;
+ usf_xx->prev_region = USM_UNDEF_TOKEN;
+
+ usf_xx->cb = usf_rx_cb;
+
+ rc = config_xx(usf_xx, &config_rx.us_xx_info);
+ if (rc)
+ return rc;
+
+ rc = q6usm_open_write(usf_xx->usc,
+ usf_xx->encdec_cfg.format_id);
+ if (rc)
+ return rc;
+
+ if (usf_xx->buffer_size && usf_xx->buffer_count) {
+ rc = q6usm_us_client_buf_alloc(
+ IN,
+ usf_xx->usc,
+ usf_xx->buffer_size,
+ usf_xx->buffer_count);
+ if (rc)
+ return rc;
+ }
+
+ rc = q6usm_dec_cfg_blk(usf_xx->usc,
+ &usf_xx->encdec_cfg);
+ if (!rc) {
+ init_waitqueue_head(&usf_xx->wait);
+ usf_xx->usf_state = USF_CONFIGURED_STATE;
+ }
+
+ return rc;
+} /* usf_set_rx_info */
+
+
+static int usf_get_tx_update(struct usf_type *usf, unsigned long arg)
+{
+ struct us_tx_update_info_type upd_tx_info;
+ unsigned long prev_jiffies = 0;
+ struct usf_xx_type *usf_xx = &usf->usf_tx;
+ int rc = copy_from_user(&upd_tx_info, (void *) arg,
+ sizeof(upd_tx_info));
+
+ if (rc) {
+ pr_err("%s: get_update: copy_from_user() failed[%d]\n",
+ __func__, rc);
+ return -EINVAL;
+ }
+
+ if (!usf_xx->user_upd_info_na) {
+ handle_input_event(usf,
+ upd_tx_info.event_counter,
+ upd_tx_info.event);
+
+ /* Release available regions */
+ rc = q6usm_read(usf_xx->usc,
+ upd_tx_info.free_region);
+ if (rc)
+ return rc;
+ } else
+ usf_xx->user_upd_info_na = 0;
+
+ /* Get data ready regions */
+ prev_jiffies = jiffies;
+ rc = wait_event_timeout(usf_xx->wait,
+ (usf_xx->prev_region !=
+ usf_xx->new_region) ||
+ (usf_xx->usf_state !=
+ USF_WORK_STATE),
+ USF_TIMEOUT_JIFFIES);
+
+ if (!rc) {
+ pr_debug("%s: timeout. prev_j=%lu; j=%lu\n",
+ __func__, prev_jiffies, jiffies);
+ pr_debug("%s: timeout. prev=%d; new=%d\n",
+ __func__, usf_xx->prev_region,
+ usf_xx->new_region);
+ pr_debug("%s: timeout. free_region=%d;\n",
+ __func__, upd_tx_info.free_region);
+ if (usf_xx->prev_region ==
+ usf_xx->new_region) {
+ pr_err("%s:read data: timeout\n",
+ __func__);
+ return -ETIME;
+ }
+ }
+
+ if (usf_xx->usf_state != USF_WORK_STATE) {
+ pr_err("%s: TX device is in not work state[%d]\n",
+ __func__, usf_xx->usf_state);
+ return -EINTR;
+ }
+
+ upd_tx_info.ready_region = usf_xx->new_region;
+ rc = copy_to_user((void __user *)arg, &upd_tx_info,
+ sizeof(upd_tx_info));
+ if (upd_tx_info.ready_region == USM_WRONG_TOKEN) {
+ pr_err("%s: TX path corrupted; prev=%d\n",
+ __func__, usf_xx->prev_region);
+ rc = -EIO;
+ }
+ usf_xx->prev_region = upd_tx_info.ready_region;
+
+ return rc;
+} /* usf_get_tx_update */
+
+static int usf_set_rx_update(struct usf_xx_type *usf_xx, unsigned long arg)
+{
+ struct us_rx_update_info_type upd_rx_info;
+ int rc = copy_from_user(&upd_rx_info, (void *) arg,
+ sizeof(upd_rx_info));
+
+ if (rc) {
+ pr_err("%s: get_update: copy_from_user() failed[%d]\n",
+ __func__, rc);
+ return -EINVAL;
+ }
+
+ /* Send available data regions */
+ if (upd_rx_info.ready_region !=
+ usf_xx->buffer_count) {
+ rc = q6usm_write(
+ usf_xx->usc,
+ upd_rx_info.ready_region);
+ if (rc)
+ return rc;
+ }
+
+ /* Get free regions */
+ rc = wait_event_timeout(
+ usf_xx->wait,
+ !q6usm_is_write_buf_full(
+ usf_xx->usc,
+ &upd_rx_info.free_region) ||
+ (usf_xx->usf_state == USF_IDLE_STATE),
+ USF_TIMEOUT_JIFFIES);
+
+ if (!rc) {
+ rc = -ETIME;
+ pr_err("%s:timeout. wait for write buf not full\n",
+ __func__);
+ } else {
+ if (usf_xx->usf_state !=
+ USF_WORK_STATE) {
+ pr_err("%s: RX: state[%d]\n",
+ __func__,
+ usf_xx->usf_state);
+ rc = -EINTR;
+ } else
+ rc = copy_to_user(
+ (void __user *)arg,
+ &upd_rx_info,
+ sizeof(upd_rx_info));
+ }
+
+ return rc;
+} /* usf_set_rx_update */
+
+static int usf_stop_tx(struct usf_type *usf)
+{
+ struct usf_xx_type *usf_xx = &usf->usf_tx;
+
+ if (usf->input_if != NULL) {
+ input_unregister_device(usf->input_if);
+ usf->input_if = NULL;
+ pr_info("%s input_unregister_device",
+ __func__);
+ }
+ usf_disable(usf_xx);
+
+ return 0;
+} /* usf_stop_tx */
+
+static long usf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int rc = 0;
+ struct usf_type *usf = file->private_data;
+ struct usf_xx_type *usf_xx = NULL;
+
+ switch (cmd) {
+ case US_START_TX: {
+ usf_xx = &usf->usf_tx;
+ if (usf_xx->usf_state == USF_CONFIGURED_STATE)
+ rc = usf_start_tx(usf_xx);
+ else {
+ pr_err("%s: start_tx: wrong state[%d]\n",
+ __func__,
+ usf_xx->usf_state);
+ return -EBADFD;
+ }
+ break;
+ }
+
+ case US_START_RX: {
+ usf_xx = &usf->usf_rx;
+ if (usf_xx->usf_state == USF_CONFIGURED_STATE)
+ rc = usf_start_rx(usf_xx);
+ else {
+ pr_err("%s: start_rx: wrong state[%d]\n",
+ __func__,
+ usf_xx->usf_state);
+ return -EBADFD;
+ }
+ break;
+ }
+
+ case US_SET_TX_INFO: {
+ usf_xx = &usf->usf_tx;
+ if (usf_xx->usf_state == USF_OPENED_STATE)
+ rc = usf_set_tx_info(usf, arg);
+ else {
+ pr_err("%s: set_tx_info: wrong state[%d]\n",
+ __func__,
+ usf_xx->usf_state);
+ return -EBADFD;
+ }
+
+ break;
+ } /* US_SET_TX_INFO */
+
+ case US_SET_RX_INFO: {
+ usf_xx = &usf->usf_rx;
+ if (usf_xx->usf_state == USF_OPENED_STATE)
+ rc = usf_set_rx_info(usf, arg);
+ else {
+ pr_err("%s: set_rx_info: wrong state[%d]\n",
+ __func__,
+ usf_xx->usf_state);
+ return -EBADFD;
+ }
+
+ break;
+ } /* US_SET_RX_INFO */
+
+ case US_GET_TX_UPDATE: {
+ struct usf_xx_type *usf_xx = &usf->usf_tx;
+ if (usf_xx->usf_state == USF_WORK_STATE)
+ rc = usf_get_tx_update(usf, arg);
+ else {
+ pr_err("%s: get_tx_update: wrong state[%d]\n", __func__,
+ usf_xx->usf_state);
+ rc = -EBADFD;
+ }
+ break;
+ } /* US_GET_TX_UPDATE */
+
+ case US_SET_RX_UPDATE: {
+ struct usf_xx_type *usf_xx = &usf->usf_rx;
+ if (usf_xx->usf_state == USF_WORK_STATE)
+ rc = usf_set_rx_update(usf_xx, arg);
+ else {
+ pr_err("%s: set_rx_update: wrong state[%d]\n",
+ __func__,
+ usf_xx->usf_state);
+ rc = -EBADFD;
+ }
+ break;
+ } /* US_SET_RX_UPDATE */
+
+ case US_STOP_TX: {
+ usf_xx = &usf->usf_tx;
+ if (usf_xx->usf_state == USF_WORK_STATE)
+ rc = usf_stop_tx(usf);
+ else {
+ pr_err("%s: stop_tx: wrong state[%d]\n",
+ __func__,
+ usf_xx->usf_state);
+ return -EBADFD;
+ }
+ break;
+ } /* US_STOP_TX */
+
+ case US_STOP_RX: {
+ usf_xx = &usf->usf_rx;
+ if (usf_xx->usf_state == USF_WORK_STATE)
+ usf_disable(usf_xx);
+ else {
+ pr_err("%s: stop_rx: wrong state[%d]\n",
+ __func__,
+ usf_xx->usf_state);
+ return -EBADFD;
+ }
+ break;
+ } /* US_STOP_RX */
+
+ default:
+ rc = -EINVAL;
+ break;
+ }
+
+ if (rc &&
+ ((cmd == US_SET_TX_INFO) ||
+ (cmd == US_SET_RX_INFO)))
+ release_xx(usf_xx);
+
+ return rc;
+} /* usf_ioctl */
+
+static int usf_mmap(struct file *file, struct vm_area_struct *vms)
+{
+ struct usf_type *usf = file->private_data;
+ int dir = OUT;
+ struct usf_xx_type *usf_xx = &usf->usf_tx;
+
+ if (vms->vm_flags & USF_VM_WRITE) { /* RX buf mapping */
+ dir = IN;
+ usf_xx = &usf->usf_rx;
+ }
+
+ return q6usm_get_virtual_address(dir, usf_xx->usc, vms);
+}
+
+static uint16_t add_opened_dev(int minor)
+{
+ uint16_t ind = 0;
+
+ for (ind = 0; ind < MAX_DEVS_NUMBER; ++ind) {
+ if (minor == s_opened_devs[ind]) {
+ pr_err("%s: device %d is already opened\n",
+ __func__, minor);
+ return USF_UNDEF_DEV_ID;
+ }
+
+ if (s_opened_devs[ind] == 0) {
+ s_opened_devs[ind] = minor;
+ pr_info("%s: device %d is added; ind=%d\n",
+ __func__, minor, ind);
+ return ind;
+ }
+ }
+
+ pr_err("%s: there is no place for device %d\n",
+ __func__, minor);
+ return USF_UNDEF_DEV_ID;
+}
+
+static int usf_open(struct inode *inode, struct file *file)
+{
+ struct usf_type *usf = NULL;
+ uint16_t dev_ind = 0;
+ int minor = MINOR(inode->i_rdev);
+
+ dev_ind = add_opened_dev(minor);
+ if (dev_ind == USF_UNDEF_DEV_ID)
+ return -EBUSY;
+
+ usf = kzalloc(sizeof(struct usf_type), GFP_KERNEL);
+ if (usf == NULL) {
+ pr_err("%s:usf allocation failed\n", __func__);
+ return -ENOMEM;
+ }
+
+ file->private_data = usf;
+ usf->dev_ind = dev_ind;
+
+ usf->usf_tx.usf_state = USF_OPENED_STATE;
+ usf->usf_rx.usf_state = USF_OPENED_STATE;
+
+ pr_info("%s:usf in open\n", __func__);
+ return 0;
+}
+
+
+static int usf_release(struct inode *inode, struct file *file)
+{
+ struct usf_type *usf = file->private_data;
+
+ pr_info("%s: release entry\n", __func__);
+
+ if (usf->input_if != NULL) {
+ input_unregister_device(usf->input_if);
+ usf->input_if = NULL;
+ pr_info("%s input_unregister_device\n", __func__);
+ }
+
+ usf_disable(&usf->usf_tx);
+ usf_disable(&usf->usf_rx);
+
+ s_opened_devs[usf->dev_ind] = 0;
+
+ kfree(usf);
+ pr_info("%s: release exit\n", __func__);
+ return 0;
+}
+
+static const struct file_operations usf_fops = {
+ .owner = THIS_MODULE,
+ .open = usf_open,
+ .release = usf_release,
+ .unlocked_ioctl = usf_ioctl,
+ .mmap = usf_mmap,
+};
+
+struct miscdevice usf_misc[MAX_DEVS_NUMBER] = {
+ {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "usf1",
+ .fops = &usf_fops,
+ },
+};
+
+static int __init usf_init(void)
+{
+ int rc = 0;
+ uint16_t ind = 0;
+
+ pr_info("%s: USF SW version %s.\n", __func__, DRV_VERSION);
+ pr_info("%s: Max %d devs registration\n", __func__, MAX_DEVS_NUMBER);
+
+ for (ind = 0; ind < MAX_DEVS_NUMBER; ++ind) {
+ rc = misc_register(&usf_misc[ind]);
+ if (rc) {
+ pr_err("%s: misc_register() failed ind=%d; rc = %d\n",
+ __func__, ind, rc);
+ break;
+ }
+ }
+
+ return rc;
+}
+
+device_initcall(usf_init);
+
+MODULE_DESCRIPTION("Ultrasound framework driver");
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index bb31b6a..696a7bd 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -29,6 +29,7 @@
#include <linux/file.h>
#include <linux/major.h>
#include <linux/regulator/consumer.h>
+#include <linux/ion.h>
#define DRIVER_NAME "msm_rotator"
@@ -123,6 +124,7 @@
struct mutex imem_lock;
int imem_owner;
wait_queue_head_t wq;
+ struct ion_client *client;
};
#define COMPONENT_5BITS 1
@@ -709,57 +711,82 @@
return 0;
}
-static int get_img(int memory_id, unsigned long *start, unsigned long *len,
- struct file **pp_file)
+static int get_img(struct msmfb_data *fbd, unsigned long *start,
+ unsigned long *len, struct file **p_file, struct ion_handle **p_ihdl)
{
int ret = 0;
#ifdef CONFIG_FB
- struct file *file;
+ struct file *file = NULL;
int put_needed, fb_num;
#endif
#ifdef CONFIG_ANDROID_PMEM
unsigned long vstart;
#endif
-#ifdef CONFIG_ANDROID_PMEM
- if (!get_pmem_file(memory_id, start, &vstart, len, pp_file))
- return 0;
-#endif
#ifdef CONFIG_FB
- file = fget_light(memory_id, &put_needed);
- if (file == NULL)
- return -1;
+ if (fbd->flags & MDP_MEMORY_ID_TYPE_FB) {
+ file = fget_light(fbd->memory_id, &put_needed);
+ if (file == NULL)
+ return -EINVAL;
- if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
- fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
- if (get_fb_phys_info(start, len, fb_num))
+ if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+ fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
+ if (get_fb_phys_info(start, len, fb_num))
+ ret = -1;
+ else
+ *p_file = file;
+ } else
ret = -1;
- else
- *pp_file = file;
- } else
- ret = -1;
- if (ret)
- fput_light(file, put_needed);
+ if (ret)
+ fput_light(file, put_needed);
+ return ret;
+ }
#endif
- return ret;
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ *p_ihdl = ion_import_fd(msm_rotator_dev->client,
+ fbd->memory_id);
+ if (IS_ERR_OR_NULL(*p_ihdl))
+ return PTR_ERR(*p_ihdl);
+ if (!ion_phys(msm_rotator_dev->client, *p_ihdl, start,
+ (size_t *) len))
+ return 0;
+ else
+ return -ENOMEM;
+#endif
+#ifdef CONFIG_ANDROID_PMEM
+ if (!get_pmem_file(fbd->memory_id, start, &vstart, len, p_file))
+ return 0;
+ else
+ return -ENOMEM;
+#endif
+
}
+static void put_img(struct file *p_file, struct ion_handle *p_ihdl)
+{
+#ifdef CONFIG_ANDROID_PMEM
+ if (p_file != NULL)
+ put_pmem_file(p_file);
+#endif
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ if (!IS_ERR_OR_NULL(p_ihdl))
+ ion_free(msm_rotator_dev->client, p_ihdl);
+#endif
+}
static int msm_rotator_do_rotate(unsigned long arg)
{
- int rc = 0;
- unsigned int status;
+ unsigned int status, format;
struct msm_rotator_data_info info;
unsigned int in_paddr, out_paddr;
unsigned long src_len, dst_len;
- struct file *src_file = 0;
- struct file *dst_file = 0;
- int use_imem = 0;
- int s;
- struct file *src_chroma_file = 0;
- struct file *dst_chroma_file = 0;
+ int use_imem = 0, rc = 0, s;
+ struct file *srcp0_file = NULL, *dstp0_file = NULL;
+ struct file *srcp1_file = NULL, *dstp1_file = NULL;
+ struct ion_handle *srcp0_ihdl = NULL, *dstp0_ihdl = NULL;
+ struct ion_handle *srcp1_ihdl = NULL, *dstp1_ihdl = NULL;
unsigned int in_chroma_paddr = 0, out_chroma_paddr = 0;
unsigned int in_chroma2_paddr = 0;
- uint32_t format;
struct msm_rotator_img_info *img_info;
struct msm_rotator_mem_planes src_planes, dst_planes;
@@ -808,16 +835,16 @@
goto do_rotate_unlock_mutex;
}
- rc = get_img(info.src.memory_id, (unsigned long *)&in_paddr,
- (unsigned long *)&src_len, &src_file);
+ rc = get_img(&info.src, (unsigned long *)&in_paddr,
+ (unsigned long *)&src_len, &srcp0_file, &srcp0_ihdl);
if (rc) {
pr_err("%s: in get_img() failed id=0x%08x\n",
DRIVER_NAME, info.src.memory_id);
goto do_rotate_unlock_mutex;
}
- rc = get_img(info.dst.memory_id, (unsigned long *)&out_paddr,
- (unsigned long *)&dst_len, &dst_file);
+ rc = get_img(&info.dst, (unsigned long *)&out_paddr,
+ (unsigned long *)&dst_len, &dstp0_file, &dstp0_ihdl);
if (rc) {
pr_err("%s: out get_img() failed id=0x%08x\n",
DRIVER_NAME, info.dst.memory_id);
@@ -845,18 +872,20 @@
goto do_rotate_unlock_mutex;
}
- rc = get_img(info.src_chroma.memory_id,
+ rc = get_img(&info.src_chroma,
(unsigned long *)&in_chroma_paddr,
- (unsigned long *)&src_len, &src_chroma_file);
+ (unsigned long *)&src_len, &srcp1_file,
+ &srcp1_ihdl);
if (rc) {
pr_err("%s: in chroma get_img() failed id=0x%08x\n",
DRIVER_NAME, info.src_chroma.memory_id);
goto do_rotate_unlock_mutex;
}
- rc = get_img(info.dst_chroma.memory_id,
+ rc = get_img(&info.dst_chroma,
(unsigned long *)&out_chroma_paddr,
- (unsigned long *)&dst_len, &dst_chroma_file);
+ (unsigned long *)&dst_len, &dstp1_file,
+ &dstp1_ihdl);
if (rc) {
pr_err("%s: out chroma get_img() failed id=0x%08x\n",
DRIVER_NAME, info.dst_chroma.memory_id);
@@ -1019,14 +1048,10 @@
#endif
schedule_delayed_work(&msm_rotator_dev->rot_clk_work, HZ);
do_rotate_unlock_mutex:
- if (dst_chroma_file)
- put_pmem_file(dst_chroma_file);
- if (src_chroma_file)
- put_pmem_file(src_chroma_file);
- if (dst_file)
- put_pmem_file(dst_file);
- if (src_file)
- put_pmem_file(src_file);
+ put_img(dstp1_file, dstp1_ihdl);
+ put_img(srcp1_file, srcp1_ihdl);
+ put_img(dstp0_file, dstp0_ihdl);
+ put_img(srcp0_file, srcp0_ihdl);
mutex_unlock(&msm_rotator_dev->rotator_lock);
dev_dbg(msm_rotator_dev->device, "%s() returning rc = %d\n",
__func__, rc);
@@ -1361,7 +1386,9 @@
msm_rotator_rot_clk_work_f);
mutex_init(&msm_rotator_dev->rotator_lock);
-
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ msm_rotator_dev->client = msm_ion_client_create(-1, pdev->name);
+#endif
platform_set_drvdata(pdev, msm_rotator_dev);
@@ -1387,9 +1414,9 @@
if (msm_rotator_dev->imem_clk)
clk_disable(msm_rotator_dev->imem_clk);
#endif
- if (ver != pdata->hardware_version_number) {
+ if (ver != pdata->hardware_version_number)
pr_info("%s: invalid HW version\n", DRIVER_NAME);
- }
+
msm_rotator_dev->irq = platform_get_irq(pdev, 0);
if (msm_rotator_dev->irq < 0) {
printk(KERN_ALERT "%s: could not get IORESOURCE_IRQ\n",
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index b13190d..0693f46 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1080,6 +1080,7 @@
{
long status = 0;
uint io = 1;
+ static uint io_cnt;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
@@ -1097,12 +1098,9 @@
goto done;
}
if (!kgsl_check_timestamp(device, timestamp)) {
- if (pwr->active_pwrlevel) {
- int low_pwrlevel = pwr->num_pwrlevels -
- KGSL_PWRLEVEL_LOW_OFFSET;
- if (pwr->active_pwrlevel == low_pwrlevel)
- io = 0;
- }
+ io_cnt = (io_cnt + 1) % 100;
+ if (io_cnt < pwr->pwrlevels[pwr->active_pwrlevel].io_fraction)
+ io = 0;
mutex_unlock(&device->mutex);
/* We need to make sure that the process is placed in wait-q
* before its condition is called */
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 2aff1ff..64397e0 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -479,6 +479,8 @@
gpu_freq) : 0;
pwr->pwrlevels[i].bus_freq =
pdata_pwr->pwrlevel[i].bus_freq;
+ pwr->pwrlevels[i].io_fraction =
+ pdata_pwr->pwrlevel[i].io_fraction;
}
/* Do not set_rate for targets in sync with AXI */
if (pwr->pwrlevels[0].gpu_freq > 0)
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 17dab76..6258a9b 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -21,7 +21,6 @@
#define KGSL_PWRLEVEL_TURBO 0
#define KGSL_PWRLEVEL_NOMINAL 1
-#define KGSL_PWRLEVEL_LOW_OFFSET 2
#define KGSL_MAX_CLKS 5
diff --git a/drivers/hwmon/msm_adc.c b/drivers/hwmon/msm_adc.c
index 42bcd07..b8d581e 100644
--- a/drivers/hwmon/msm_adc.c
+++ b/drivers/hwmon/msm_adc.c
@@ -98,6 +98,8 @@
/* Needed to support file_op interfaces */
static struct msm_adc_drv *msm_adc_drv;
+static bool conv_first_request;
+
static ssize_t msm_adc_show_curr(struct device *dev,
struct device_attribute *devattr, char *buf);
@@ -726,6 +728,16 @@
struct msm_adc_platform_data *pdata =
msm_adc_drv->pdev->dev.platform_data;
struct msm_adc_channels *channel = &pdata->channel[hwmon_chan];
+ int ret = 0;
+
+ if (conv_first_request) {
+ ret = pm8058_xoadc_calib_device(channel->adc_dev_instance);
+ if (ret) {
+ pr_err("pmic8058 xoadc calibration failed, retry\n");
+ return ret;
+ }
+ conv_first_request = false;
+ }
channel->adc_access_fn->adc_slot_request(channel->adc_dev_instance,
&slot);
@@ -813,6 +825,16 @@
msm_adc_drv->pdev->dev.platform_data;
struct msm_adc_channels *channel = &pdata->channel[client->adc_chan];
struct adc_conv_slot *slot;
+ int ret;
+
+ if (conv_first_request) {
+ ret = pm8058_xoadc_calib_device(channel->adc_dev_instance);
+ if (ret) {
+ pr_err("pmic8058 xoadc calibration failed, retry\n");
+ return ret;
+ }
+ conv_first_request = false;
+ }
channel->adc_access_fn->adc_slot_request(channel->adc_dev_instance,
&slot);
@@ -871,46 +893,6 @@
return rc;
}
-int32_t adc_calib_request(void *h, struct completion *calib_complete_evt)
-{
- struct msm_client_data *client = (struct msm_client_data *)h;
- struct msm_adc_platform_data *pdata =
- msm_adc_drv->pdev->dev.platform_data;
- struct msm_adc_channels *channel = &pdata->channel[client->adc_chan];
- struct adc_conv_slot *slot;
- int rc, calib_status;
-
- channel->adc_access_fn->adc_slot_request(channel->adc_dev_instance,
- &slot);
- if (slot) {
- slot->conv.result.chan = client->adc_chan;
- slot->blocking = 0;
- slot->compk = calib_complete_evt;
- slot->adc_request = START_OF_CALIBRATION;
- slot->chan_path = channel->chan_path_type;
- slot->chan_adc_config = channel->adc_config_type;
- slot->chan_adc_calib = channel->adc_calib_type;
- rc = channel->adc_access_fn->adc_calibrate(
- channel->adc_dev_instance, slot, &calib_status);
-
- if (calib_status == CALIB_NOT_REQUIRED) {
- channel->adc_access_fn->adc_restore_slot(
- channel->adc_dev_instance, slot);
- /* client will always wait in case when
- calibration is not required */
- complete(calib_complete_evt);
- } else {
- atomic_inc(&msm_adc_drv->total_outst);
- mutex_lock(&client->lock);
- client->num_outstanding++;
- mutex_unlock(&client->lock);
- }
-
- return rc;
- }
- return -EBUSY;
-}
-
static void msm_rpc_adc_conv_cb(void *context, u32 param,
void *evt_buf, u32 len)
{
@@ -1458,6 +1440,7 @@
else
msm_rpc_adc_init(pdev);
}
+ conv_first_request = true;
pr_info("msm_adc successfully registered\n");
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index a256e51..2d42e17 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -1661,7 +1661,7 @@
memcpy(data, &skb->data[PEEK_DATA_OFSET], len);
iris_q_evt_data(radio, data, len, IRIS_BUF_PEEK);
radio_hci_req_complete(hdev, status);
-
+ kfree(data);
}
@@ -1872,9 +1872,13 @@
int len;
struct iris_device *radio = video_get_drvdata(video_get_dev());
+ struct hci_fm_station_rsp *rsp;
len = sizeof(struct hci_fm_station_rsp);
- memcpy(&radio->fm_st_rsp.station_rsp, skb_pull(skb, len), len);
+ rsp = (struct hci_fm_station_rsp *)skb_pull(skb, len);
+ if (rsp == NULL)
+ return;
+ memcpy(&radio->fm_st_rsp.station_rsp, rsp, len);
iris_q_event(radio, IRIS_EVT_TUNE_SUCC);
@@ -1927,7 +1931,8 @@
len = ev->num_stations_found * PARAMS_PER_STATION + STN_FREQ_OFFSET;
for (cnt = STN_FREQ_OFFSET, stn_num = 0;
- (cnt < len) && (stn_num < ev->num_stations_found);
+ (cnt < len) && (stn_num < ev->num_stations_found)
+ && (stn_num < ARRAY_SIZE(ev->rel_freq));
cnt += PARAMS_PER_STATION, stn_num++) {
abs_freq = *((int *)&skb->data[cnt]);
rel_freq = abs_freq - radio->recv_conf.band_low_limit;
@@ -2069,8 +2074,16 @@
void radio_hci_event_packet(struct radio_hci_dev *hdev, struct sk_buff *skb)
{
- struct radio_hci_event_hdr *hdr = (void *) skb->data;
- __u8 event = hdr->evt;
+ struct radio_hci_event_hdr *hdr;
+ u8 event;
+
+ if (skb == NULL) {
+ FMDERR("Socket buffer is NULL");
+ return;
+ }
+
+ hdr = (void *) skb->data;
+ event = hdr->evt;
skb_pull(skb, RADIO_HCI_EVENT_HDR_SIZE);
diff --git a/drivers/net/msm_rmnet_bam.c b/drivers/net/msm_rmnet_bam.c
index aeb85dc..e617aa5 100644
--- a/drivers/net/msm_rmnet_bam.c
+++ b/drivers/net/msm_rmnet_bam.c
@@ -737,8 +737,11 @@
bam_rmnet_drivers[n].driver.name = tempname;
bam_rmnet_drivers[n].driver.owner = THIS_MODULE;
ret = platform_driver_register(&bam_rmnet_drivers[n]);
- if (!ret)
+ if (ret) {
+ pr_err("%s: registration failed n=%d rc=%d\n",
+ __func__, n, ret);
return ret;
+ }
}
return 0;
}
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index b96c288..dde6194 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -105,6 +105,39 @@
FSM_STATE_FLCB = 22,
};
+struct fsm_state_to_batt_status {
+ enum chg_fsm_state fsm_state;
+ int batt_state;
+};
+
+static struct fsm_state_to_batt_status map[] = {
+ {FSM_STATE_OFF_0, POWER_SUPPLY_STATUS_UNKNOWN},
+ {FSM_STATE_BATFETDET_START_12, POWER_SUPPLY_STATUS_UNKNOWN},
+ {FSM_STATE_BATFETDET_END_16, POWER_SUPPLY_STATUS_UNKNOWN},
+ /*
+ * for CHG_HIGHI_1 report NOT_CHARGING if battery missing,
+ * too hot/cold, charger too hot
+ */
+ {FSM_STATE_ON_CHG_HIGHI_1, POWER_SUPPLY_STATUS_FULL},
+ {FSM_STATE_ATC_2A, POWER_SUPPLY_STATUS_CHARGING},
+ {FSM_STATE_ATC_2B, POWER_SUPPLY_STATUS_CHARGING},
+ {FSM_STATE_ON_BAT_3, POWER_SUPPLY_STATUS_DISCHARGING},
+ {FSM_STATE_ATC_FAIL_4, POWER_SUPPLY_STATUS_DISCHARGING},
+ {FSM_STATE_DELAY_5, POWER_SUPPLY_STATUS_UNKNOWN },
+ {FSM_STATE_ON_CHG_AND_BAT_6, POWER_SUPPLY_STATUS_CHARGING},
+ {FSM_STATE_FAST_CHG_7, POWER_SUPPLY_STATUS_CHARGING},
+ {FSM_STATE_TRKL_CHG_8, POWER_SUPPLY_STATUS_CHARGING},
+ {FSM_STATE_CHG_FAIL_9, POWER_SUPPLY_STATUS_DISCHARGING},
+ {FSM_STATE_EOC_10, POWER_SUPPLY_STATUS_FULL},
+ {FSM_STATE_ON_CHG_VREGOK_11, POWER_SUPPLY_STATUS_NOT_CHARGING},
+ {FSM_STATE_ATC_PAUSE_13, POWER_SUPPLY_STATUS_NOT_CHARGING},
+ {FSM_STATE_FAST_CHG_PAUSE_14, POWER_SUPPLY_STATUS_NOT_CHARGING},
+ {FSM_STATE_TRKL_CHG_PAUSE_15, POWER_SUPPLY_STATUS_NOT_CHARGING},
+ {FSM_STATE_START_BOOT, POWER_SUPPLY_STATUS_NOT_CHARGING},
+ {FSM_STATE_FLCB_VREGOK, POWER_SUPPLY_STATUS_NOT_CHARGING},
+ {FSM_STATE_FLCB, POWER_SUPPLY_STATUS_NOT_CHARGING},
+};
+
enum chg_regulation_loop {
VDD_LOOP = BIT(3),
BAT_CURRENT_LOOP = BIT(2),
@@ -968,36 +1001,22 @@
static int get_prop_batt_status(struct pm8921_chg_chip *chip)
{
- int temp = 0;
+ int batt_state = POWER_SUPPLY_STATUS_DISCHARGING;
+ int fsm_state = pm_chg_get_fsm_state(chip);
+ int i;
- if (!get_prop_batt_present(chip))
- return POWER_SUPPLY_STATUS_UNKNOWN;
+ for (i = 0; i < ARRAY_SIZE(map); i++)
+ if (map[i].fsm_state == fsm_state)
+ batt_state = map[i].batt_state;
- if (chip->ext) {
- if (chip->ext_charge_done)
- return POWER_SUPPLY_STATUS_FULL;
+ if (fsm_state == FSM_STATE_ON_CHG_HIGHI_1) {
+ if (!pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ)
+ || !pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ)
+ || !pm_chg_get_rt_status(chip, CHGHOT_IRQ))
- if (chip->ext_charging)
- return POWER_SUPPLY_STATUS_CHARGING;
+ batt_state = POWER_SUPPLY_STATUS_NOT_CHARGING;
}
-
- /* TODO reading the FSM state is more reliable */
- temp = pm_chg_get_rt_status(chip, TRKLCHG_IRQ);
-
- temp |= pm_chg_get_rt_status(chip, FASTCHG_IRQ);
- if (temp)
- return POWER_SUPPLY_STATUS_CHARGING;
- /*
- * The battery is not charging
- * check the FET - if on battery is discharging
- * - if off battery is isolated(full) and the system
- * is being driven from a charger
- */
- temp = pm_chg_get_rt_status(chip, BATFET_IRQ);
- if (temp)
- return POWER_SUPPLY_STATUS_DISCHARGING;
-
- return POWER_SUPPLY_STATUS_FULL;
+ return batt_state;
}
static int get_prop_batt_temp(struct pm8921_chg_chip *chip)
diff --git a/drivers/thermal/pmic8058-tm.c b/drivers/thermal/pmic8058-tm.c
index cc98f37..2589494 100644
--- a/drivers/thermal/pmic8058-tm.c
+++ b/drivers/thermal/pmic8058-tm.c
@@ -351,7 +351,6 @@
static int __devinit pmic8058_tm_probe(struct platform_device *pdev)
{
- DECLARE_COMPLETION_ONSTACK(wait);
struct pm8058_tm_device *tmdev;
struct pm8058_chip *pm_chip;
unsigned int irq;
@@ -382,10 +381,6 @@
return rc;
}
- /* calibrate the die temperature sensor */
- if (adc_calib_request(tmdev->adc_handle, &wait) == CALIB_STARTED)
- wait_for_completion(&wait);
-
tmdev->pm_chip = pm_chip;
tmdev->tz_dev = thermal_zone_device_register("pm8058_tz",
PM8058_TRIP_NUM, tmdev,
diff --git a/drivers/usb/gadget/u_bam.c b/drivers/usb/gadget/u_bam.c
index 73407bd..1de8fc1 100644
--- a/drivers/usb/gadget/u_bam.c
+++ b/drivers/usb/gadget/u_bam.c
@@ -33,37 +33,37 @@
static const char *bam_ch_names[] = { "bam_dmux_ch_8" };
-#define TX_PKT_DROP_THRESHOLD 1000
-#define RX_PKT_FLOW_CTRL_EN_THRESHOLD 1000
-#define RX_PKT_FLOW_CTRL_DISABLE 500
-#define RX_PKT_FLOW_CTRL_SUPPORT 1
+#define BAM_MUX_TX_PKT_DROP_THRESHOLD 1000
+#define BAM_MUX_RX_PKT_FCTRL_EN_TSHOLD 200
+#define BAM_MUX_RX_PKT_FCTRL_DIS_TSHOLD 125
+#define BAM_MUX_RX_PKT_FLOW_CTRL_SUPPORT 1
#define BAM_MUX_HDR 8
-#define RX_Q_SIZE 16
-#define TX_Q_SIZE 200
-#define RX_REQ_SIZE (2048 - BAM_MUX_HDR)
+#define BAM_MUX_RX_Q_SIZE 16
+#define BAM_MUX_TX_Q_SIZE 200
+#define BAM_MUX_RX_REQ_SIZE (2048 - BAM_MUX_HDR)
-unsigned int tx_pkt_drop_thld = TX_PKT_DROP_THRESHOLD;
-module_param(tx_pkt_drop_thld, uint, S_IRUGO | S_IWUSR);
+unsigned int bam_mux_tx_pkt_drop_thld = BAM_MUX_TX_PKT_DROP_THRESHOLD;
+module_param(bam_mux_tx_pkt_drop_thld, uint, S_IRUGO | S_IWUSR);
-unsigned int rx_fctrl_en_thld = RX_PKT_FLOW_CTRL_EN_THRESHOLD;
-module_param(rx_fctrl_en_thld, uint, S_IRUGO | S_IWUSR);
+unsigned int bam_mux_rx_fctrl_en_thld = BAM_MUX_RX_PKT_FCTRL_EN_TSHOLD;
+module_param(bam_mux_rx_fctrl_en_thld, uint, S_IRUGO | S_IWUSR);
-unsigned int rx_fctrl_support = RX_PKT_FLOW_CTRL_SUPPORT;
-module_param(rx_fctrl_support, uint, S_IRUGO | S_IWUSR);
+unsigned int bam_mux_rx_fctrl_support = BAM_MUX_RX_PKT_FLOW_CTRL_SUPPORT;
+module_param(bam_mux_rx_fctrl_support, uint, S_IRUGO | S_IWUSR);
-unsigned int rx_fctrl_dis_thld = RX_PKT_FLOW_CTRL_DISABLE;
-module_param(rx_fctrl_dis_thld, uint, S_IRUGO | S_IWUSR);
+unsigned int bam_mux_rx_fctrl_dis_thld = BAM_MUX_RX_PKT_FCTRL_DIS_TSHOLD;
+module_param(bam_mux_rx_fctrl_dis_thld, uint, S_IRUGO | S_IWUSR);
-unsigned int tx_q_size = TX_Q_SIZE;
-module_param(tx_q_size, uint, S_IRUGO | S_IWUSR);
+unsigned int bam_mux_tx_q_size = BAM_MUX_TX_Q_SIZE;
+module_param(bam_mux_tx_q_size, uint, S_IRUGO | S_IWUSR);
-unsigned int rx_q_size = RX_Q_SIZE;
-module_param(rx_q_size, uint, S_IRUGO | S_IWUSR);
+unsigned int bam_mux_rx_q_size = BAM_MUX_RX_Q_SIZE;
+module_param(bam_mux_rx_q_size, uint, S_IRUGO | S_IWUSR);
-unsigned int rx_req_size = RX_REQ_SIZE;
-module_param(rx_req_size, uint, S_IRUGO | S_IWUSR);
+unsigned int bam_mux_rx_req_size = BAM_MUX_RX_REQ_SIZE;
+module_param(bam_mux_rx_req_size, uint, S_IRUGO | S_IWUSR);
#define BAM_CH_OPENED BIT(0)
#define BAM_CH_READY BIT(1)
@@ -211,7 +211,7 @@
return;
}
- if (d->tx_skb_q.qlen > tx_pkt_drop_thld) {
+ if (d->tx_skb_q.qlen > bam_mux_tx_pkt_drop_thld) {
d->tohost_drp_cnt++;
if (printk_ratelimit())
pr_err("%s: tx pkt dropped: tx_drop_cnt:%u\n",
@@ -246,8 +246,8 @@
port, d, d->to_modem,
d->pending_with_bam, port->port_num);
- if (rx_fctrl_support &&
- d->pending_with_bam >= rx_fctrl_dis_thld) {
+ if (bam_mux_rx_fctrl_support &&
+ d->pending_with_bam >= bam_mux_rx_fctrl_dis_thld) {
spin_unlock_irqrestore(&port->port_lock, flags);
return;
@@ -274,7 +274,13 @@
return;
}
- while ((skb = __skb_dequeue(&d->rx_skb_q))) {
+ while (!bam_mux_rx_fctrl_support ||
+ (d->pending_with_bam < bam_mux_rx_fctrl_en_thld)) {
+ skb = __skb_dequeue(&d->rx_skb_q);
+ if (!skb) {
+ spin_unlock_irqrestore(&port->port_lock, flags);
+ return;
+ }
d->pending_with_bam++;
d->to_modem++;
@@ -370,8 +376,8 @@
/* TODO: Handle flow control gracefully by having
* having call back mechanism from bam driver
*/
- if (rx_fctrl_support &&
- d->pending_with_bam >= rx_fctrl_en_thld) {
+ if (bam_mux_rx_fctrl_support &&
+ d->pending_with_bam >= bam_mux_rx_fctrl_en_thld) {
list_add_tail(&req->list, &d->rx_idle);
spin_unlock(&port->port_lock);
@@ -379,7 +385,7 @@
}
spin_unlock(&port->port_lock);
- skb = alloc_skb(rx_req_size + BAM_MUX_HDR, GFP_ATOMIC);
+ skb = alloc_skb(bam_mux_rx_req_size + BAM_MUX_HDR, GFP_ATOMIC);
if (!skb) {
spin_lock(&port->port_lock);
list_add_tail(&req->list, &d->rx_idle);
@@ -389,7 +395,7 @@
skb_reserve(skb, BAM_MUX_HDR);
req->buf = skb->data;
- req->length = rx_req_size;
+ req->length = bam_mux_rx_req_size;
req->context = skb;
status = usb_ep_queue(ep, req, GFP_ATOMIC);
@@ -427,14 +433,14 @@
while (port->port_usb && !list_empty(&d->rx_idle)) {
req = list_first_entry(&d->rx_idle, struct usb_request, list);
- skb = alloc_skb(rx_req_size + BAM_MUX_HDR, GFP_ATOMIC);
+ skb = alloc_skb(bam_mux_rx_req_size + BAM_MUX_HDR, GFP_ATOMIC);
if (!skb)
break;
skb_reserve(skb, BAM_MUX_HDR);
list_del(&req->list);
req->buf = skb->data;
- req->length = rx_req_size;
+ req->length = bam_mux_rx_req_size;
req->context = skb;
spin_unlock_irqrestore(&port->port_lock, flags);
@@ -473,7 +479,7 @@
d = &port->data_ch;
ep = port->port_usb->out;
- ret = gbam_alloc_requests(ep, &d->rx_idle, rx_q_size,
+ ret = gbam_alloc_requests(ep, &d->rx_idle, bam_mux_rx_q_size,
gbam_epout_complete, GFP_ATOMIC);
if (ret) {
pr_err("%s: rx req allocation failed\n", __func__);
@@ -481,7 +487,7 @@
}
ep = port->port_usb->in;
- ret = gbam_alloc_requests(ep, &d->tx_idle, tx_q_size,
+ ret = gbam_alloc_requests(ep, &d->tx_idle, bam_mux_tx_q_size,
gbam_epin_complete, GFP_ATOMIC);
if (ret) {
pr_err("%s: tx req allocation failed\n", __func__);
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 9805b6c..4b34969 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -3088,10 +3088,36 @@
HDMI_OUTP(HDMI_AUDIO_CFG, hdmi_audio_config);
+ mb();
+ pr_info("%s :HDMI_AUDIO_CFG 0x%08x\n", __func__,
+ HDMI_INP(HDMI_AUDIO_CFG));
+
return 0;
}
EXPORT_SYMBOL(hdmi_audio_enable);
+#define HDMI_AUDIO_PKT_CTRL 0x0020
+#define HDMI_AUDIO_SAMPLE_SEND_ENABLE 1
+
+int hdmi_audio_packet_enable(bool on)
+{
+ u32 hdmi_audio_pkt_ctrl;
+ hdmi_audio_pkt_ctrl = HDMI_INP(HDMI_AUDIO_PKT_CTRL);
+
+ if (on)
+ hdmi_audio_pkt_ctrl |= HDMI_AUDIO_SAMPLE_SEND_ENABLE;
+ else
+ hdmi_audio_pkt_ctrl &= ~(HDMI_AUDIO_SAMPLE_SEND_ENABLE);
+
+ HDMI_OUTP(HDMI_AUDIO_PKT_CTRL, hdmi_audio_pkt_ctrl);
+
+ mb();
+ pr_info("%s : HDMI_AUDIO_PKT_CTRL 0x%08x\n", __func__,
+ HDMI_INP(HDMI_AUDIO_PKT_CTRL));
+ return 0;
+}
+EXPORT_SYMBOL(hdmi_audio_packet_enable);
+
static void hdmi_msm_audio_info_setup(boolean enabled, int num_of_channels,
int level_shift, boolean down_mix)
{
@@ -3294,7 +3320,8 @@
external_common_state->video_resolution,
MSM_HDMI_SAMPLE_RATE_48KHZ, channels);
hdmi_msm_audio_info_setup(TRUE, channels, 0, FALSE);
- hdmi_msm_audio_ctrl_setup(TRUE, 1);
+
+ hdmi_msm_audio_ctrl_setup(FALSE, 1);
/* Turn on Audio FIFO and SAM DROP ISR */
HDMI_OUTP(0x02CC, HDMI_INP(0x02CC) | BIT(1) | BIT(3));
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 5d8c547..d757b5d 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -428,9 +428,7 @@
struct mdp4_overlay_pipe *pipe);
int mdp4_overlay_play_wait(struct fb_info *info,
struct msmfb_overlay_data *req);
-int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
- struct file **pp_src_file, struct file **pp_src_plane1_file,
- struct file **pp_src_plane2_file);
+int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req);
struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(int ptype, int mixer,
int req_share);
void mdp4_overlay_pipe_free(struct mdp4_overlay_pipe *pipe);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 6d63229..dbed160 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -1821,39 +1821,57 @@
}
static int get_img(struct msmfb_data *img, struct fb_info *info,
- unsigned long *start, unsigned long *len, struct file **pp_file)
+ unsigned long *start, unsigned long *len, struct file **srcp_file,
+ struct ion_handle **srcp_ihdl)
{
- int put_needed, ret = 0, fb_num;
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+#endif
struct file *file;
+ int put_needed, ret = 0, fb_num;
#ifdef CONFIG_ANDROID_PMEM
unsigned long vstart;
#endif
-
if (img->flags & MDP_BLIT_SRC_GEM) {
- *pp_file = NULL;
+ *srcp_file = NULL;
return kgsl_gem_obj_addr(img->memory_id, (int) img->priv,
start, len);
}
-#ifdef CONFIG_ANDROID_PMEM
- if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
- return 0;
-#endif
- file = fget_light(img->memory_id, &put_needed);
- if (file == NULL)
- return -1;
+ if (img->flags & MDP_MEMORY_ID_TYPE_FB) {
+ file = fget_light(img->memory_id, &put_needed);
+ if (file == NULL)
+ return -EINVAL;
- if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
- fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
- if (get_fb_phys_info(start, len, fb_num))
+ if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+ fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
+ if (get_fb_phys_info(start, len, fb_num))
+ ret = -1;
+ else
+ *srcp_file = file;
+ } else
ret = -1;
- else
- *pp_file = file;
- } else
- ret = -1;
- if (ret)
- fput_light(file, put_needed);
- return ret;
+ if (ret)
+ fput_light(file, put_needed);
+ return ret;
+ }
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ *srcp_ihdl = ion_import_fd(mfd->client, img->memory_id);
+ if (IS_ERR_OR_NULL(*srcp_ihdl))
+ return PTR_ERR(*srcp_ihdl);
+ if (!ion_phys(mfd->client, *srcp_ihdl, start, (size_t *) len))
+ return 0;
+ else
+ return -EINVAL;
+#endif
+#ifdef CONFIG_ANDROID_PMEM
+ if (!get_pmem_file(img->memory_id, start, &vstart,
+ len, srcp_file))
+ return 0;
+ else
+ return -EINVAL;
+#endif
}
#ifdef CONFIG_FB_MSM_MIPI_DSI
@@ -2306,9 +2324,7 @@
return 0;
}
-int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req,
- struct file **pp_src_file, struct file **pp_src_plane1_file,
- struct file **pp_src_plane2_file)
+int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
struct msmfb_data *img;
@@ -2316,9 +2332,12 @@
struct mdp4_pipe_desc *pd;
ulong start, addr;
ulong len = 0;
- struct file *p_src_file = 0;
- struct file *p_src_plane1_file = 0, *p_src_plane2_file = 0;
+ struct file *srcp0_file = NULL;
+ struct file *srcp1_file = NULL, *srcp2_file = NULL;
+ struct ion_handle *srcp0_ihdl = NULL;
+ struct ion_handle *srcp1_ihdl = NULL, *srcp2_ihdl = NULL;
uint32_t overlay_version = 0;
+ int ret = 0;
if (mfd == NULL)
return -ENODEV;
@@ -2346,13 +2365,13 @@
pd->player = pipe; /* keep */
img = &req->data;
- get_img(img, info, &start, &len, &p_src_file);
+ get_img(img, info, &start, &len, &srcp0_file, &srcp0_ihdl);
if (len == 0) {
mutex_unlock(&mfd->dma->ov_mutex);
pr_err("%s: pmem Error\n", __func__);
- return -1;
+ ret = -1;
+ goto end;
}
- *pp_src_file = p_src_file;
addr = start + img->offset;
pipe->srcp0_addr = addr;
@@ -2364,14 +2383,15 @@
if (pipe->fetch_plane == OVERLAY_PLANE_PSEUDO_PLANAR) {
if (overlay_version > 0) {
img = &req->plane1_data;
- get_img(img, info, &start, &len, &p_src_plane1_file);
+ get_img(img, info, &start, &len, &srcp1_file,
+ &srcp1_ihdl);
if (len == 0) {
mutex_unlock(&mfd->dma->ov_mutex);
pr_err("%s: Error to get plane1\n", __func__);
- return -EINVAL;
+ ret = -EINVAL;
+ goto end;
}
pipe->srcp1_addr = start + img->offset;
- *pp_src_plane1_file = p_src_plane1_file;
} else if (pipe->frame_format ==
MDP4_FRAME_FORMAT_VIDEO_SUPERTILE) {
struct tile_desc tile;
@@ -2395,24 +2415,26 @@
} else if (pipe->fetch_plane == OVERLAY_PLANE_PLANAR) {
if (overlay_version > 0) {
img = &req->plane1_data;
- get_img(img, info, &start, &len, &p_src_plane1_file);
+ get_img(img, info, &start, &len, &srcp1_file,
+ &srcp1_ihdl);
if (len == 0) {
mutex_unlock(&mfd->dma->ov_mutex);
pr_err("%s: Error to get plane1\n", __func__);
- return -EINVAL;
+ ret = -EINVAL;
+ goto end;
}
pipe->srcp1_addr = start + img->offset;
- *pp_src_plane1_file = p_src_plane1_file;
img = &req->plane2_data;
- get_img(img, info, &start, &len, &p_src_plane2_file);
+ get_img(img, info, &start, &len, &srcp2_file,
+ &srcp2_ihdl);
if (len == 0) {
mutex_unlock(&mfd->dma->ov_mutex);
pr_err("%s: Error to get plane2\n", __func__);
- return -EINVAL;
+ ret = -EINVAL;
+ goto end;
}
pipe->srcp2_addr = start + img->offset;
- *pp_src_plane2_file = p_src_plane2_file;
} else {
if (pipe->src_format == MDP_Y_CR_CB_GH2V2) {
addr += (ALIGN(pipe->src_width, 16) *
@@ -2495,7 +2517,7 @@
if (pipe->flags & MDP_OV_PLAY_NOWAIT) {
mdp4_stat.overlay_play[pipe->mixer_num]++;
mutex_unlock(&mfd->dma->ov_mutex);
- return 0;
+ goto end;
}
#ifdef CONFIG_FB_MSM_MIPI_DSI
if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
@@ -2512,8 +2534,23 @@
}
mdp4_stat.overlay_play[pipe->mixer_num]++;
-
mutex_unlock(&mfd->dma->ov_mutex);
-
- return 0;
+end:
+#ifdef CONFIG_ANDROID_PMEM
+ if (srcp0_file)
+ put_pmem_file(srcp0_file);
+ if (srcp1_file)
+ put_pmem_file(srcp1_file);
+ if (srcp2_file)
+ put_pmem_file(srcp2_file);
+#endif
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ if (!IS_ERR_OR_NULL(srcp0_ihdl))
+ ion_free(mfd->client, srcp0_ihdl);
+ if (!IS_ERR_OR_NULL(srcp1_ihdl))
+ ion_free(mfd->client, srcp1_ihdl);
+ if (!IS_ERR_OR_NULL(srcp2_ihdl))
+ ion_free(mfd->client, srcp2_ihdl);
+#endif
+ return ret;
}
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 5cf79c1..4e47093 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -555,11 +555,11 @@
void mdp4_overlay0_done_dsi_video(struct mdp_dma_data *dma)
{
spin_lock(&mdp_spin_lock);
+ dma->busy = FALSE;
if (dsi_pipe->blt_addr == 0) {
spin_unlock(&mdp_spin_lock);
return;
}
- dma->busy = FALSE;
mdp4_dsi_video_blt_dmap_update(dsi_pipe);
dsi_pipe->dmap_cnt++;
mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 0eda69a..75264ef 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -451,11 +451,11 @@
void mdp4_overlay0_done_lcdc(struct mdp_dma_data *dma)
{
spin_lock(&mdp_spin_lock);
+ dma->busy = FALSE;
if (lcdc_pipe->blt_addr == 0) {
spin_unlock(&mdp_spin_lock);
return;
}
- dma->busy = FALSE;
mdp4_lcdc_blt_dmap_update(lcdc_pipe);
lcdc_pipe->dmap_cnt++;
mdp_disable_irq_nosync(MDP_OVERLAY0_TERM);
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 7595838..10e4156 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -2526,8 +2526,6 @@
int ret;
struct msmfb_overlay_data req;
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
- struct file *p_src_file = 0;
- struct file *p_src_plane1_file = 0, *p_src_plane2_file = 0;
if (mfd->overlay_play_enable == 0) /* nothing to do */
return 0;
@@ -2549,17 +2547,7 @@
add_timer(&mfd->msmfb_no_update_notify_timer);
mutex_unlock(&msm_fb_notify_update_sem);
- ret = mdp4_overlay_play(info, &req, &p_src_file, &p_src_plane1_file,
- &p_src_plane2_file);
-
-#ifdef CONFIG_ANDROID_PMEM
- if (p_src_file)
- put_pmem_file(p_src_file);
- if (p_src_plane1_file)
- put_pmem_file(p_src_plane1_file);
- if (p_src_plane2_file)
- put_pmem_file(p_src_plane2_file);
-#endif
+ ret = mdp4_overlay_play(info, &req);
return ret;
}
@@ -3304,7 +3292,9 @@
mfd->fb_page = fb_num;
mfd->index = fbi_list_index;
mfd->mdp_fb_page_protection = MDP_FB_PAGE_PROTECTION_WRITECOMBINE;
-
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ mfd->client = msm_ion_client_create(-1, pdev->name);
+#endif
/* link to the latest pdev */
mfd->pdev = this_dev;
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index a650e73..bc25062 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -37,6 +37,7 @@
#include <linux/fb.h>
#include <linux/list.h>
#include <linux/types.h>
+#include <linux/ion.h>
#include <linux/msm_mdp.h>
#ifdef CONFIG_HAS_EARLYSUSPEND
@@ -172,6 +173,7 @@
struct list_head writeback_free_queue;
struct list_head writeback_register_queue;
wait_queue_head_t wait_q;
+ struct ion_client *client;
};
struct dentry *msm_fb_get_debugfs_root(void);
diff --git a/include/linux/msm_adc.h b/include/linux/msm_adc.h
index 9818cf0..5d5fb1b 100644
--- a/include/linux/msm_adc.h
+++ b/include/linux/msm_adc.h
@@ -343,7 +343,6 @@
int32_t adc_channel_close(void *h);
int32_t adc_channel_request_conv(void *h, struct completion *conv_complete_evt);
int32_t adc_channel_read_result(void *h, struct adc_chan_result *chan_result);
-int32_t adc_calib_request(void *h, struct completion *calib_complete_evt);
#else
int32_t adc_channel_open(uint32_t channel, void **h)
{
@@ -365,11 +364,6 @@
pr_err("%s.not supported.\n", __func__);
return -ENODEV;
}
-int32_t adc_calib_request(void *h, struct completion *calib_complete_evt)
-{
- pr_err("%s.not supported.\n", __func__);
- return -ENODEV;
-}
#endif /* CONFIG_SENSORS_MSM_ADC */
#endif
#endif /* __MSM_ADC_H */
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 84e8564..9db6bc6 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -111,6 +111,7 @@
struct kgsl_pwrlevel {
unsigned int gpu_freq;
unsigned int bus_freq;
+ unsigned int io_fraction;
};
struct kgsl_version {
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index d909c8b..5011229 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -131,6 +131,7 @@
#define MDP_DEINTERLACE_ODD 0x00400000
#define MDP_OV_PLAY_NOWAIT 0x00200000
#define MDP_SOURCE_ROTATED_90 0x00100000
+#define MDP_MEMORY_ID_TYPE_FB 0x00001000
#define MDP_TRANSP_NOP 0xffffffff
#define MDP_ALPHA_NOP 0xff
diff --git a/include/linux/pmic8058-xoadc.h b/include/linux/pmic8058-xoadc.h
index 8a5820f..f72ad66 100644
--- a/include/linux/pmic8058-xoadc.h
+++ b/include/linux/pmic8058-xoadc.h
@@ -65,20 +65,57 @@
u32 xoadc_wakeup;
};
-int32_t pm8058_xoadc_read_adc_code(uint32_t , int32_t *data);
+#ifdef CONFIG_PMIC8058_XOADC
+int32_t pm8058_xoadc_read_adc_code(uint32_t adc_instance, int32_t *data);
-int32_t pm8058_xoadc_select_chan_and_start_conv(uint32_t,
- struct adc_conv_slot *);
+int32_t pm8058_xoadc_select_chan_and_start_conv(uint32_t adc_instance,
+ struct adc_conv_slot *slot);
-void pm8058_xoadc_slot_request(uint32_t, struct adc_conv_slot **slot);
+void pm8058_xoadc_slot_request(uint32_t adc_instance,
+ struct adc_conv_slot **slot);
-void pm8058_xoadc_restore_slot(uint32_t, struct adc_conv_slot *slot);
+void pm8058_xoadc_restore_slot(uint32_t adc_instance,
+ struct adc_conv_slot *slot);
-struct adc_properties *pm8058_xoadc_get_properties(uint32_t);
+struct adc_properties *pm8058_xoadc_get_properties(uint32_t dev_instance);
-int32_t pm8058_xoadc_calibrate(uint32_t, struct adc_conv_slot *, int *);
+int32_t pm8058_xoadc_calibrate(uint32_t dev_instance,
+ struct adc_conv_slot *slot, int * calib_status);
int32_t pm8058_xoadc_registered(void);
int32_t pm8058_xoadc_calib_device(uint32_t adc_instance);
+
+#else
+
+static inline int32_t pm8058_xoadc_read_adc_code(uint32_t adc_instance,
+ int32_t *data)
+{ return -ENXIO; }
+
+static inline int32_t pm8058_xoadc_select_chan_and_start_conv(
+ uint32_t adc_instance, struct adc_conv_slot *slot)
+{ return -ENXIO; }
+
+static inline void pm8058_xoadc_slot_request(uint32_t adc_instance,
+ struct adc_conv_slot **slot)
+{ return; }
+
+static inline void pm8058_xoadc_restore_slot(uint32_t adc_instance,
+ struct adc_conv_slot *slot)
+{ return; }
+
+static inline struct adc_properties *pm8058_xoadc_get_properties(
+ uint32_t dev_instance)
+{ return NULL; }
+
+static inline int32_t pm8058_xoadc_calibrate(uint32_t dev_instance,
+ struct adc_conv_slot *slot, int *calib_status)
+{ return -ENXIO; }
+
+static inline int32_t pm8058_xoadc_registered(void)
+{ return -ENXIO; }
+
+static inline int32_t pm8058_xoadc_calib_device(uint32_t adc_instance)
+{ return -ENXIO; }
+#endif
#endif
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index aff1ce8..9126bbb 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -870,6 +870,8 @@
#define G711_MLAW_FS 0x00010BF8
#define G711_PCM_FS 0x00010BF9
#define MPEG4_MULTI_AAC 0x00010D86
+#define US_POINT_EPOS_FORMAT 0x00012310
+#define US_RAW_FORMAT 0x0001127C
#define ASM_ENCDEC_SBCRATE 0x00010C13
#define ASM_ENCDEC_IMMDIATE_DECODE 0x00010C14
diff --git a/include/sound/dai.h b/include/sound/dai.h
index 27ff980..4d3fb96 100644
--- a/include/sound/dai.h
+++ b/include/sound/dai.h
@@ -43,6 +43,7 @@
void unregister_dma_irq_handler(int dma_ch);
void dai_set_master_mode(uint32_t dma_ch, int mode);
int dai_start_hdmi(uint32_t dma_ch);
+int wait_for_dma_cnt_stop(uint32_t dma_ch);
void dai_stop_hdmi(uint32_t dma_ch);
#endif
diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c
index e9f49b5..892e3ec 100644
--- a/kernel/power/wakelock.c
+++ b/kernel/power/wakelock.c
@@ -52,8 +52,6 @@
struct wake_lock main_wake_lock;
suspend_state_t requested_suspend_state = PM_SUSPEND_MEM;
static struct wake_lock unknown_wakeup;
-/* flag to warn/bug if wakelocks are taken after suspend_noirq */
-static int msm_suspend_check_done;
#ifdef CONFIG_WAKELOCK_STAT
static struct wake_lock deleted_wake_locks;
@@ -385,21 +383,11 @@
#endif
if (debug_mask & DEBUG_SUSPEND)
pr_info("power_suspend_late return %d\n", ret);
-
- if (ret == 0)
- msm_suspend_check_done = 1;
return ret;
}
-static int power_resume_early(struct device *dev)
-{
- msm_suspend_check_done = 0;
- return 0;
-}
-
static struct dev_pm_ops power_driver_pm_ops = {
.suspend_noirq = power_suspend_late,
- .resume_noirq = power_resume_early,
};
static struct platform_driver power_driver = {
@@ -542,24 +530,12 @@
void wake_lock(struct wake_lock *lock)
{
- /*
- * if wake lock is being called too late in the suspend sequence,
- * call bug so we get to analyze the callstack
- */
- BUG_ON(msm_suspend_check_done);
-
wake_lock_internal(lock, 0, 0);
}
EXPORT_SYMBOL(wake_lock);
void wake_lock_timeout(struct wake_lock *lock, long timeout)
{
- /*
- * if wake lock is being called too late in the suspend sequence,
- * call bug so we get to analyze the callstack
- */
- BUG_ON(msm_suspend_check_done);
-
wake_lock_internal(lock, timeout, 1);
}
EXPORT_SYMBOL(wake_lock_timeout);
diff --git a/sound/soc/msm/lpass-dma.c b/sound/soc/msm/lpass-dma.c
index 84b6f1f..66c1836 100644
--- a/sound/soc/msm/lpass-dma.c
+++ b/sound/soc/msm/lpass-dma.c
@@ -93,6 +93,7 @@
spin_lock_irqsave(&dai_lock, flag);
intrsrc = readl(dai_info.base + LPAIF_IRQ_STAT(0));
writel(intrsrc, dai_info.base + LPAIF_IRQ_CLEAR(0));
+ mb();
while (intrsrc) {
dma_ch = dai_find_dma_channel(intrsrc);
@@ -149,6 +150,7 @@
dai_info.base + LPAIF_DMA_BUFF_LEN(dma_ch));
writel(((dai[dma_ch]->period_len >> 2) - 1),
dai_info.base + LPAIF_DMA_PER_LEN(dma_ch));
+ mb();
}
static void dai_enable_codec(uint32_t dma_ch, int codec)
@@ -237,6 +239,7 @@
dai[dma_ch]->channels = params->channels;
dai[dma_ch]->buffer_len = params->buffer_size;
dai[dma_ch]->period_len = params->period_size;
+ mb();
dai_config_dma(dma_ch);
return dma_ch;
}
@@ -278,6 +281,7 @@
val = readl(dai_info.base + LPAIF_IRQ_EN(0));
val = val | (7 << (dma_ch * 3));
writel(val, dai_info.base + LPAIF_IRQ_EN(0));
+ mb();
val = (HDMI_BURST_INCR4 | HDMI_WPSCNT | HDMI_AUDIO_INTF |
@@ -287,10 +291,58 @@
}
spin_unlock_irqrestore(&dai_lock, flag);
+ mb();
dai_print_state(dma_ch);
return 0;
}
+int wait_for_dma_cnt_stop(uint32_t dma_ch)
+{
+ uint32_t dma_per_cnt_reg_val, dma_per_cnt, prev_dma_per_cnt;
+ uint32_t i;
+
+ pr_info("%s dma_ch %u\n", __func__, dma_ch);
+
+ dma_per_cnt_reg_val = readl_relaxed(dai_info.base +
+ LPAIF_DMA_PER_CNT(dma_ch));
+
+ dma_per_cnt =
+ ((LPAIF_DMA_PER_CNT_PER_CNT_MASK & dma_per_cnt_reg_val) >>
+ LPAIF_DMA_PER_CNT_PER_CNT_SHIFT) -
+ ((LPAIF_DMA_PER_CNT_FIFO_WORDCNT_MASK & dma_per_cnt_reg_val) >>
+ LPAIF_DMA_PER_CNT_FIFO_WORDCNT_SHIFT);
+
+ prev_dma_per_cnt = dma_per_cnt;
+
+ i = 1;
+ pr_info("%s: i = %u dma_per_cnt_reg_val 0x%08x , dma_per_cnt %u\n",
+ __func__, i, dma_per_cnt_reg_val, dma_per_cnt);
+
+ while (i <= 50) {
+ msleep(50);
+
+ dma_per_cnt_reg_val = readl_relaxed(dai_info.base +
+ LPAIF_DMA_PER_CNT(dma_ch));
+
+ dma_per_cnt =
+ ((LPAIF_DMA_PER_CNT_PER_CNT_MASK & dma_per_cnt_reg_val) >>
+ LPAIF_DMA_PER_CNT_PER_CNT_SHIFT) -
+ ((LPAIF_DMA_PER_CNT_FIFO_WORDCNT_MASK & dma_per_cnt_reg_val) >>
+ LPAIF_DMA_PER_CNT_FIFO_WORDCNT_SHIFT);
+
+ i++;
+
+ pr_info("%s: i = %u dma_per_cnt_reg_val 0x%08x , dma_per_cnt %u\n",
+ __func__, i, dma_per_cnt_reg_val, dma_per_cnt);
+
+ if (prev_dma_per_cnt == dma_per_cnt)
+ break;
+
+ prev_dma_per_cnt = dma_per_cnt;
+ }
+ return 0;
+}
+
void dai_stop_hdmi(uint32_t dma_ch)
{
unsigned long flag = 0x0;
@@ -307,14 +359,18 @@
intrVal = 0x0;
writel(intrVal, dai_info.base + LPAIF_DMA_CTL(dma_ch));
+ mb();
+
intrVal = readl(dai_info.base + LPAIF_IRQ_EN(0));
int_mask = ((int_mask) << (dma_ch * 3));
int_mask = ~int_mask;
- intrVal = intrVal && int_mask;
+ intrVal = intrVal & int_mask;
writel(intrVal, dai_info.base + LPAIF_IRQ_EN(0));
+ mb();
+
spin_unlock_irqrestore(&dai_lock, flag);
}