Merge "msm: camera: Fixed memory leak and added NULL check" into msm-3.0
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index c6e314e..64cba23 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -97,6 +97,9 @@
CONFIG_DIAG_CHAR=y
CONFIG_HW_RANDOM=y
CONFIG_DCC_TTY=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_QUP=y
CONFIG_SPI=y
CONFIG_SPI_QUP=y
CONFIG_SPI_SPIDEV=m
@@ -104,9 +107,8 @@
CONFIG_SPMI_MSM_PMIC_ARB=y
CONFIG_MSM_QPNP=y
CONFIG_MSM_QPNP_INT=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_QUP=y
+CONFIG_SLIMBUS=y
+CONFIG_SLIMBUS_MSM_CTRL=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
CONFIG_POWER_SUPPLY=y
@@ -146,8 +148,6 @@
CONFIG_SPS=y
CONFIG_SPS_SUPPORT_BAMDMA=y
CONFIG_SPS_SUPPORT_NDP_BAM=y
-CONFIG_SLIMBUS=y
-CONFIG_SLIMBUS_MSM_CTRL=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 6a5497d..5b55f99 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -1,4 +1,3 @@
-CONFIG_CFG80211=m
CONFIG_EXPERIMENTAL=y
CONFIG_LOCALVERSION="$(KERNEL_LOCAL_VERSION)-perf"
# CONFIG_SWAP is not set
@@ -170,6 +169,7 @@
CONFIG_BT_HCIUART_IBS=y
CONFIG_BT_MSM_SLEEP=y
CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=m
# CONFIG_CFG80211_WEXT is not set
CONFIG_RFKILL=y
CONFIG_GENLOCK=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 11c4224..7f9c54d 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -1,4 +1,3 @@
-CONFIG_CFG80211=m
CONFIG_EXPERIMENTAL=y
CONFIG_LOCALVERSION="$(KERNEL_LOCAL_VERSION)"
# CONFIG_SWAP is not set
@@ -170,6 +169,7 @@
CONFIG_BT_HCIUART_IBS=y
CONFIG_BT_MSM_SLEEP=y
CONFIG_MSM_BT_POWER=y
+CONFIG_CFG80211=m
# CONFIG_CFG80211_WEXT is not set
CONFIG_RFKILL=y
CONFIG_GENLOCK=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 2bc922a..1bd3c56 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -9,7 +9,6 @@
CONFIG_CGROUP_CPUACCT=y
CONFIG_RESOURCE_COUNTERS=y
CONFIG_CGROUP_SCHED=y
-CONFIG_FAIR_GROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
@@ -87,9 +86,9 @@
CONFIG_MSM_DLOAD_MODE=y
CONFIG_MSM_QDSS=y
CONFIG_MSM_SLEEP_STATS=y
-CONFIG_MSM_DCVS=y
CONFIG_MSM_CACHE_ERP=y
CONFIG_MSM_L2_ERP_2BIT_PANIC=y
+CONFIG_MSM_DCVS=y
CONFIG_STRICT_MEMORY_RWX=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
@@ -291,7 +290,6 @@
CONFIG_SPI=y
CONFIG_SPI_QUP=y
CONFIG_SPI_SPIDEV=m
-CONFIG_SPI_MASTER=y
CONFIG_SLIMBUS_MSM_CTRL=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
@@ -303,7 +301,6 @@
CONFIG_PM8921_CHARGER=y
CONFIG_PM8921_BMS=y
CONFIG_SENSORS_PM8XXX_ADC=y
-CONFIG_HWMON=y
CONFIG_SENSORS_EPM_ADC=y
CONFIG_THERMAL=y
CONFIG_THERMAL_TSENS8960=y
@@ -332,9 +329,9 @@
CONFIG_OV2720=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_ACTUATOR=y
-CONFIG_IMX091=y
CONFIG_MSM_GEMINI=y
CONFIG_S5K3L1YX=y
+CONFIG_IMX091=y
CONFIG_RADIO_IRIS=y
CONFIG_RADIO_IRIS_TRANSPORT=m
CONFIG_ION=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 706bc88..69806d0 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -8,7 +8,6 @@
CONFIG_CGROUP_CPUACCT=y
CONFIG_RESOURCE_COUNTERS=y
CONFIG_CGROUP_SCHED=y
-CONFIG_FAIR_GROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_NAMESPACES=y
# CONFIG_UTS_NS is not set
@@ -87,13 +86,13 @@
CONFIG_MSM_QDSS=y
CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE=y
CONFIG_MSM_SLEEP_STATS=y
-CONFIG_MSM_DCVS=y
CONFIG_MSM_RTB=y
CONFIG_MSM_RTB_SEPARATE_CPUS=y
CONFIG_MSM_CACHE_ERP=y
CONFIG_MSM_L1_ERR_PANIC=y
CONFIG_MSM_L2_ERP_1BIT_PANIC=y
CONFIG_MSM_L2_ERP_2BIT_PANIC=y
+CONFIG_MSM_DCVS=y
CONFIG_MSM_CACHE_DUMP=y
CONFIG_MSM_CACHE_DUMP_ON_PANIC=y
CONFIG_STRICT_MEMORY_RWX=y
@@ -297,7 +296,6 @@
CONFIG_SPI=y
CONFIG_SPI_QUP=y
CONFIG_SPI_SPIDEV=m
-CONFIG_SPI_MASTER=y
CONFIG_SLIMBUS_MSM_CTRL=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
@@ -309,7 +307,6 @@
CONFIG_PM8921_CHARGER=y
CONFIG_PM8921_BMS=y
CONFIG_SENSORS_PM8XXX_ADC=y
-CONFIG_HWMON=y
CONFIG_SENSORS_EPM_ADC=y
CONFIG_THERMAL=y
CONFIG_THERMAL_TSENS8960=y
@@ -338,9 +335,9 @@
CONFIG_OV2720=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_ACTUATOR=y
-CONFIG_IMX091=y
CONFIG_MSM_GEMINI=y
CONFIG_S5K3L1YX=y
+CONFIG_IMX091=y
CONFIG_RADIO_IRIS=y
CONFIG_RADIO_IRIS_TRANSPORT=m
CONFIG_ION=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index ebb78d4..70cba0f 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -43,7 +43,6 @@
# CONFIG_MSM_RESET_MODEM is not set
CONFIG_MSM_IPC_ROUTER=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
-CONFIG_MSM_PIL_QDSP6V4=y
CONFIG_MSM_SUBSYSTEM_RESTART=y
# CONFIG_MSM_SYSMON_COMM is not set
CONFIG_MSM_MODEM_8960=y
@@ -192,7 +191,6 @@
CONFIG_SPI=y
CONFIG_SPI_QUP=y
CONFIG_SPI_SPIDEV=m
-CONFIG_SLIMBUS=y
CONFIG_SLIMBUS_MSM_CTRL=y
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
diff --git a/arch/arm/lib/div64.S b/arch/arm/lib/div64.S
index faa7748..e55c484 100644
--- a/arch/arm/lib/div64.S
+++ b/arch/arm/lib/div64.S
@@ -13,6 +13,7 @@
*/
#include <linux/linkage.h>
+#include <asm/unwind.h>
#ifdef __ARMEB__
#define xh r0
@@ -44,6 +45,7 @@
*/
ENTRY(__do_div64)
+UNWIND(.fnstart)
@ Test for easy paths first.
subs ip, r4, #1
@@ -189,7 +191,12 @@
moveq yh, xh
moveq xh, #0
moveq pc, lr
+UNWIND(.fnend)
+UNWIND(.fnstart)
+UNWIND(.pad #4)
+UNWIND(.save {lr})
+Ldiv0_64:
@ Division by 0:
str lr, [sp, #-8]!
bl __div0
@@ -200,4 +207,5 @@
mov xh, #0
ldr pc, [sp], #8
+UNWIND(.fnend)
ENDPROC(__do_div64)
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index d142713..2609aca 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -222,7 +222,6 @@
obj-$(CONFIG_ARCH_MSM7X27A) += clock-pcom-lookup.o devices-msm7x27a.o
board-7627a-all-objs += board-msm7627a-storage.o board-msm7627a-bt.o board-msm7627a-camera.o
board-7627a-all-objs += board-msm7627a-display.o board-msm7627a-wlan.o board-msm7627a-io.o
-board-7627a-all-objs += board-msm7627a-audio.o
obj-$(CONFIG_MACH_MSM7X27A_RUMI3) += board-msm7x27a.o board-7627a-all.o
obj-$(CONFIG_MACH_MSM7X27A_SURF) += board-msm7x27a.o board-7627a-all.o
obj-$(CONFIG_MACH_MSM7X27A_FFA) += board-msm7x27a.o board-7627a-all.o
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index 0ff931a..7b84a68 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -181,12 +181,12 @@
.io_fraction = 0,
},
{
- .gpu_freq = 320000000,
+ .gpu_freq = 325000000,
.bus_freq = 2,
.io_fraction = 33,
},
{
- .gpu_freq = 192000000,
+ .gpu_freq = 200000000,
.bus_freq = 1,
.io_fraction = 100,
},
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index d06b5bd..3f4266f 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -588,6 +588,12 @@
.name = "usb",
};
+static int phy_init_seq[] = {
+ 0x38, 0x81, /* update DC voltage level */
+ 0x24, 0x82, /* set pre-emphasis and rise/fall time */
+ -1
+};
+
static struct msm_otg_platform_data msm_otg_pdata = {
.mode = USB_OTG,
.otg_control = OTG_PMIC_CONTROL,
@@ -595,6 +601,7 @@
.pmic_id_irq = PM8921_USB_ID_IN_IRQ(PM8921_IRQ_BASE),
.power_budget = 750,
.bus_scale_table = &usb_bus_scale_pdata,
+ .phy_init_seq = phy_init_seq,
};
static struct msm_usb_host_platform_data msm_ehci_host_pdata3 = {
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
index 5b632bd..bfb8be3 100644
--- a/arch/arm/mach-msm/board-8960-gpiomux.c
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -55,7 +55,7 @@
.pull = GPIOMUX_PULL_NONE,
};
-static struct gpiomux_setting gsbi5 = {
+static struct gpiomux_setting gsbi_uart = {
.func = GPIOMUX_FUNC_1,
.drv = GPIOMUX_DRV_8MA,
.pull = GPIOMUX_PULL_NONE,
@@ -327,30 +327,6 @@
},
},
{
- .gpio = 22, /* GSBI5 UART2 */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi5,
- },
- },
- {
- .gpio = 23, /* GSBI5 UART2 */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi5,
- },
- },
- {
- .gpio = 24, /* GSBI5 UART2 */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi5,
- },
- },
- {
- .gpio = 25, /* GSBI5 UART2 */
- .settings = {
- [GPIOMUX_SUSPENDED] = &gsbi5,
- },
- },
- {
.gpio = 44, /* GSBI12 I2C QUP SDA */
.settings = {
[GPIOMUX_SUSPENDED] = &gsbi12,
@@ -376,6 +352,60 @@
},
};
+static struct msm_gpiomux_config msm8960_gsbi5_uart_configs[] __initdata = {
+ {
+ .gpio = 22, /* GSBI5 UART2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi_uart,
+ },
+ },
+ {
+ .gpio = 23, /* GSBI5 UART2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi_uart,
+ },
+ },
+ {
+ .gpio = 24, /* GSBI5 UART2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi_uart,
+ },
+ },
+ {
+ .gpio = 25, /* GSBI5 UART2 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi_uart,
+ },
+ },
+};
+
+static struct msm_gpiomux_config msm8960_gsbi8_uart_configs[] __initdata = {
+ {
+ .gpio = 34, /* GSBI8 UART3 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi_uart,
+ },
+ },
+ {
+ .gpio = 35, /* GSBI8 UART3 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi_uart,
+ },
+ },
+ {
+ .gpio = 36, /* GSBI8 UART3 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi_uart,
+ },
+ },
+ {
+ .gpio = 37, /* GSBI8 UART3 */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi_uart,
+ },
+ },
+};
+
static struct msm_gpiomux_config msm8960_slimbus_config[] __initdata = {
{
.gpio = 60, /* slimbus data */
@@ -686,5 +716,12 @@
msm_gpiomux_install(msm8960_mdp_vsync_configs,
ARRAY_SIZE(msm8960_mdp_vsync_configs));
+ if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
+ msm_gpiomux_install(msm8960_gsbi8_uart_configs,
+ ARRAY_SIZE(msm8960_gsbi8_uart_configs));
+ else
+ msm_gpiomux_install(msm8960_gsbi5_uart_configs,
+ ARRAY_SIZE(msm8960_gsbi5_uart_configs));
+
return 0;
}
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 257b27f..f462c7a 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2192,7 +2192,6 @@
static struct platform_device *common_devices[] __initdata = {
&msm8960_device_dmov,
&msm_device_smd,
- &msm8960_device_uart_gsbi5,
&msm_device_uart_dm6,
&msm_device_saw_core0,
&msm_device_saw_core1,
@@ -2275,6 +2274,7 @@
};
static struct platform_device *sim_devices[] __initdata = {
+ &msm8960_device_uart_gsbi5,
&msm8960_device_otg,
&msm8960_device_gadget_peripheral,
&msm_device_hsusb_host,
@@ -2320,6 +2320,7 @@
};
static struct platform_device *rumi3_devices[] __initdata = {
+ &msm8960_device_uart_gsbi5,
&msm_kgsl_3d0,
&msm_kgsl_2d0,
&msm_kgsl_2d1,
@@ -2900,6 +2901,12 @@
platform_device_register(&msm8960_device_ext_3p3v_vreg);
if (machine_is_msm8960_cdp())
platform_device_register(&msm8960_device_ext_l2_vreg);
+
+ if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
+ platform_device_register(&msm8960_device_uart_gsbi8);
+ else
+ platform_device_register(&msm8960_device_uart_gsbi5);
+
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
msm8960_pm8921_gpio_mpp_init();
platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
diff --git a/arch/arm/mach-msm/board-dt.c b/arch/arm/mach-msm/board-dt.c
index 52f3de6..674df09 100644
--- a/arch/arm/mach-msm/board-dt.c
+++ b/arch/arm/mach-msm/board-dt.c
@@ -61,7 +61,7 @@
}
}
-static const char *msm_dt_match[] __initdata = {
+static const char *msm_dt_match[] __initconst = {
"qcom,msmcopper",
NULL
};
diff --git a/arch/arm/mach-msm/board-msm7627a-audio.c b/arch/arm/mach-msm/board-msm7627a-audio.c
deleted file mode 100644
index c393226..0000000
--- a/arch/arm/mach-msm/board-msm7627a-audio.c
+++ /dev/null
@@ -1,429 +0,0 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <asm/mach-types.h>
-#include <linux/platform_device.h>
-#include <linux/android_pmem.h>
-#include <linux/gfp.h>
-#include <mach/msm_memtypes.h>
-#include <mach/board.h>
-#include <mach/msm_rpcrouter.h>
-#include <mach/socinfo.h>
-
-#include "devices.h"
-#include "board-msm7627a.h"
-#include "devices-msm7x2xa.h"
-
-static struct android_pmem_platform_data android_pmem_adsp_pdata = {
- .name = "pmem_adsp",
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
- .cached = 1,
- .memory_type = MEMTYPE_EBI1,
- .request_region = request_fmem_c_region,
- .release_region = release_fmem_c_region,
- .reusable = 1,
-};
-
-static struct platform_device android_pmem_adsp_device = {
- .name = "android_pmem",
- .id = 1,
- .dev = { .platform_data = &android_pmem_adsp_pdata },
-};
-
-#define SND(desc, num) { .name = #desc, .id = num }
-static struct snd_endpoint snd_endpoints_list[] = {
- SND(HANDSET, 0),
- SND(MONO_HEADSET, 2),
- SND(HEADSET, 3),
- SND(SPEAKER, 6),
- SND(TTY_HEADSET, 8),
- SND(TTY_VCO, 9),
- SND(TTY_HCO, 10),
- SND(BT, 12),
- SND(IN_S_SADC_OUT_HANDSET, 16),
- SND(IN_S_SADC_OUT_SPEAKER_PHONE, 25),
- SND(FM_DIGITAL_STEREO_HEADSET, 26),
- SND(FM_DIGITAL_SPEAKER_PHONE, 27),
- SND(FM_DIGITAL_BT_A2DP_HEADSET, 28),
- SND(STEREO_HEADSET_AND_SPEAKER, 31),
- SND(CURRENT, 0x7FFFFFFE),
- SND(FM_ANALOG_STEREO_HEADSET, 35),
- SND(FM_ANALOG_STEREO_HEADSET_CODEC, 36),
-};
-#undef SND
-
-static struct msm_snd_endpoints msm_device_snd_endpoints = {
- .endpoints = snd_endpoints_list,
- .num = sizeof(snd_endpoints_list) / sizeof(struct snd_endpoint)
-};
-
-static struct platform_device msm_device_snd = {
- .name = "msm_snd",
- .id = -1,
- .dev = {
- .platform_data = &msm_device_snd_endpoints
- },
-};
-
-#define DEC0_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
- (1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
- (1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
- (1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
- (1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
- (1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
-#define DEC1_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
- (1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
- (1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
- (1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
- (1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
- (1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
-#define DEC2_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
- (1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
- (1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
- (1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
- (1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
- (1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
-#define DEC3_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
- (1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
- (1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
- (1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
- (1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
- (1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
-#define DEC4_FORMAT (1<<MSM_ADSP_CODEC_MIDI)
-
-static unsigned int dec_concurrency_table[] = {
- /* Audio LP */
- (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DMA)), 0,
- 0, 0, 0,
-
- /* Concurrency 1 */
- (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC3_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC4_FORMAT),
-
- /* Concurrency 2 */
- (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC3_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC4_FORMAT),
-
- /* Concurrency 3 */
- (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC4_FORMAT),
-
- /* Concurrency 4 */
- (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC4_FORMAT),
-
- /* Concurrency 5 */
- (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC4_FORMAT),
-
- /* Concurrency 6 */
- (DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
- 0, 0, 0,
-
- /* Concurrency 7 */
- (DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
- (DEC4_FORMAT),
-};
-
-#define DEC_INFO(name, queueid, decid, nr_codec) { .module_name = name, \
- .module_queueid = queueid, .module_decid = decid, \
- .nr_codec_support = nr_codec}
-
-static struct msm_adspdec_info dec_info_list[] = {
- DEC_INFO("AUDPLAY0TASK", 13, 0, 11), /* AudPlay0BitStreamCtrlQueue */
- DEC_INFO("AUDPLAY1TASK", 14, 1, 11), /* AudPlay1BitStreamCtrlQueue */
- DEC_INFO("AUDPLAY2TASK", 15, 2, 11), /* AudPlay2BitStreamCtrlQueue */
- DEC_INFO("AUDPLAY3TASK", 16, 3, 11), /* AudPlay3BitStreamCtrlQueue */
- DEC_INFO("AUDPLAY4TASK", 17, 4, 1), /* AudPlay4BitStreamCtrlQueue */
-};
-
-static struct msm_adspdec_database msm_device_adspdec_database = {
- .num_dec = ARRAY_SIZE(dec_info_list),
- .num_concurrency_support = (ARRAY_SIZE(dec_concurrency_table) / \
- ARRAY_SIZE(dec_info_list)),
- .dec_concurrency_table = dec_concurrency_table,
- .dec_info_list = dec_info_list,
-};
-
-static struct platform_device msm_device_adspdec = {
- .name = "msm_adspdec",
- .id = -1,
- .dev = {
- .platform_data = &msm_device_adspdec_database
- },
-};
-
-static struct android_pmem_platform_data android_pmem_audio_pdata = {
- .name = "pmem_audio",
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
- .cached = 0,
- .memory_type = MEMTYPE_EBI1,
-};
-
-static struct platform_device android_pmem_audio_device = {
- .name = "android_pmem",
- .id = 2,
- .dev = { .platform_data = &android_pmem_audio_pdata },
-};
-
-static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE;
-static int __init pmem_kernel_ebi1_size_setup(char *p)
-{
- pmem_kernel_ebi1_size = memparse(p, NULL);
- return 0;
-}
-early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup);
-
-static unsigned pmem_audio_size = MSM_PMEM_AUDIO_SIZE;
-static int __init pmem_audio_size_setup(char *p)
-{
- pmem_audio_size = memparse(p, NULL);
- return 0;
-}
-early_param("pmem_audio_size", pmem_audio_size_setup);
-
-static struct memtype_reserve msm7627a_reserve_table[] __initdata = {
- [MEMTYPE_SMI] = {
- },
- [MEMTYPE_EBI0] = {
- .flags = MEMTYPE_FLAGS_1M_ALIGN,
- },
- [MEMTYPE_EBI1] = {
- .flags = MEMTYPE_FLAGS_1M_ALIGN,
- },
-};
-
-static struct android_pmem_platform_data android_pmem_pdata = {
- .name = "pmem",
- .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
- .cached = 1,
- .memory_type = MEMTYPE_EBI1,
-};
-static struct platform_device android_pmem_device = {
- .name = "android_pmem",
- .id = 0,
- .dev = { .platform_data = &android_pmem_pdata },
-};
-
-static struct android_pmem_platform_data *pmem_pdata_array[] __initdata = {
- &android_pmem_adsp_pdata,
- &android_pmem_audio_pdata,
- &android_pmem_pdata,
-};
-
-static unsigned pmem_mdp_size;
-static unsigned pmem_adsp_size;
-
-static int __init pmem_mdp_size_setup(char *p)
-{
- pmem_mdp_size = memparse(p, NULL);
- return 0;
-}
-early_param("pmem_mdp_size", pmem_mdp_size_setup);
-
-static int __init pmem_adsp_size_setup(char *p)
-{
- pmem_adsp_size = memparse(p, NULL);
- return 0;
-}
-early_param("pmem_adsp_size", pmem_adsp_size_setup);
-
-static void __init msm7627a_size_pmem_devices(void)
-{
- unsigned int i;
- unsigned int reusable_count = 0;
-
- if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
- pmem_mdp_size = MSM7x25A_MSM_PMEM_MDP_SIZE;
- pmem_adsp_size = MSM7x25A_MSM_PMEM_ADSP_SIZE;
- } else {
- pmem_mdp_size = MSM_PMEM_MDP_SIZE;
- pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
- }
-
- android_pmem_adsp_pdata.size = pmem_adsp_size;
- android_pmem_pdata.size = pmem_mdp_size;
- android_pmem_audio_pdata.size = pmem_audio_size;
-
- fmem_pdata.size = 0;
-
- /* Find pmem devices that should use FMEM (reusable) memory.
- */
- for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
- struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
-
- if (!reusable_count && pdata->reusable)
- fmem_pdata.size += pdata->size;
-
- reusable_count += (pdata->reusable) ? 1 : 0;
-
- if (pdata->reusable && reusable_count > 1) {
- pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
- __func__, pdata->name);
- pdata->reusable = 0;
- }
- }
-}
-
-static void __init qrd7627a_size_pmem_devices(void)
-{
- unsigned int i;
- unsigned int reusable_count = 0;
-
- pmem_mdp_size = QRD_PMEM_MDP_SIZE;
- pmem_adsp_size = QRD_PMEM_ADSP_SIZE;
-
- android_pmem_adsp_pdata.size = pmem_adsp_size;
- android_pmem_pdata.size = pmem_mdp_size;
- android_pmem_audio_pdata.size = pmem_audio_size;
-
- fmem_pdata.size = 0;
-
- /* Find pmem devices that should use FMEM (reusable) memory.
- */
- for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
- struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
-
- if (!reusable_count && pdata->reusable)
- fmem_pdata.size += pdata->size;
-
- reusable_count += (pdata->reusable) ? 1 : 0;
-
- if (pdata->reusable && reusable_count > 1) {
- pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
- __func__, pdata->name);
- pdata->reusable = 0;
- }
- }
-}
-
-static void __init reserve_memory_for(struct android_pmem_platform_data *p)
-{
- msm7627a_reserve_table[p->memory_type].size += p->size;
-}
-
-static void __init msm7627a_reserve_pmem_memory(void)
-{
- unsigned int i;
- for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
- if (!pmem_pdata_array[i]->reusable)
- reserve_memory_for(pmem_pdata_array[i]);
- }
-
- msm7627a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
-}
-
-static void __init qrd7627a_reserve_pmem_memory(void)
-{
- reserve_memory_for(&android_pmem_adsp_pdata);
- reserve_memory_for(&android_pmem_pdata);
- reserve_memory_for(&android_pmem_audio_pdata);
- msm7627a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
-}
-
-static void __init msm7627a_calculate_reserve_sizes(void)
-{
- msm7627a_size_pmem_devices();
- msm7627a_reserve_pmem_memory();
-}
-
-static void __init qrd7627a_calculate_reserve_sizes(void)
-{
- qrd7627a_size_pmem_devices();
- qrd7627a_reserve_pmem_memory();
-}
-
-static int msm7627a_paddr_to_memtype(unsigned int paddr)
-{
- return MEMTYPE_EBI1;
-}
-
-static struct reserve_info msm7627a_reserve_info __initdata = {
- .memtype_reserve_table = msm7627a_reserve_table,
- .calculate_reserve_sizes = msm7627a_calculate_reserve_sizes,
- .paddr_to_memtype = msm7627a_paddr_to_memtype,
-};
-
-static struct reserve_info qrd7627a_reserve_info __initdata = {
- .memtype_reserve_table = msm7627a_reserve_table,
- .calculate_reserve_sizes = qrd7627a_calculate_reserve_sizes,
- .paddr_to_memtype = msm7627a_paddr_to_memtype,
-};
-
-void __init msm7627a_reserve(void)
-{
- reserve_info = &msm7627a_reserve_info;
- msm_reserve();
- fmem_pdata.phys = reserve_memory_for_fmem(fmem_pdata.size);
-}
-
-void __init qrd7627a_reserve(void)
-{
- reserve_info = &qrd7627a_reserve_info;
- msm_reserve();
- fmem_pdata.phys = reserve_memory_for_fmem(fmem_pdata.size);
-}
-
-static struct platform_device *audio_devices[] __initdata = {
- &android_pmem_device,
- &android_pmem_adsp_device,
- &android_pmem_audio_device,
- &msm_device_adspdec,
- &msm_device_snd,
-};
-
-void __init msm_adsp_add_pdev(void)
-{
- int rc = 0;
- struct rpc_board_dev *rpc_adsp_pdev;
-
- rpc_adsp_pdev = kzalloc(sizeof(struct rpc_board_dev), GFP_KERNEL);
- if (rpc_adsp_pdev == NULL) {
- pr_err("%s: Memory Allocation failure\n", __func__);
- return;
- }
- rpc_adsp_pdev->prog = ADSP_RPC_PROG;
-
- if (cpu_is_msm8625())
- rpc_adsp_pdev->pdev = msm8625_device_adsp;
- else
- rpc_adsp_pdev->pdev = msm_adsp_device;
- rc = msm_rpc_add_board_dev(rpc_adsp_pdev, 1);
- if (rc < 0) {
- pr_err("%s: return val: %d\n", __func__, rc);
- kfree(rpc_adsp_pdev);
- }
-
- platform_add_devices(audio_devices,
- ARRAY_SIZE(audio_devices));
-
-}
diff --git a/arch/arm/mach-msm/board-msm7627a-camera.c b/arch/arm/mach-msm/board-msm7627a-camera.c
index 2269073..94b8710 100644
--- a/arch/arm/mach-msm/board-msm7627a-camera.c
+++ b/arch/arm/mach-msm/board-msm7627a-camera.c
@@ -206,9 +206,9 @@
};
static struct msm_camera_sensor_flash_src msm_flash_src_ov5647 = {
- .flash_sr_type = MSM_CAMERA_FLASH_SRC_LED,
- ._fsrc.led_src.led_name = "flashlight",
- ._fsrc.led_src.led_name_len = 10,
+ .flash_sr_type = MSM_CAMERA_FLASH_SRC_LED1,
+ ._fsrc.ext_driver_src.led_en = 13,
+ ._fsrc.ext_driver_src.led_flash_en = 32,
};
static struct msm_camera_sensor_flash_data flash_ov5647 = {
diff --git a/arch/arm/mach-msm/board-msm7627a-display.c b/arch/arm/mach-msm/board-msm7627a-display.c
index 33a46cc..e96284a 100644
--- a/arch/arm/mach-msm/board-msm7627a-display.c
+++ b/arch/arm/mach-msm/board-msm7627a-display.c
@@ -573,6 +573,93 @@
};
#endif
+static int evb_backlight_control(int level)
+{
+
+ int i = 0;
+ int remainder;
+ /* device address byte = 0x72 */
+ gpio_set_value_cansleep(96, 0);
+ udelay(67);
+ gpio_set_value_cansleep(96, 1);
+ udelay(33);
+ gpio_set_value_cansleep(96, 0);
+ udelay(33);
+ gpio_set_value_cansleep(96, 1);
+ udelay(67);
+ gpio_set_value_cansleep(96, 0);
+ udelay(33);
+ gpio_set_value_cansleep(96, 1);
+ udelay(67);
+ gpio_set_value_cansleep(96, 0);
+ udelay(33);
+ gpio_set_value_cansleep(96, 1);
+ udelay(67);
+ gpio_set_value_cansleep(96, 0);
+ udelay(67);
+ gpio_set_value_cansleep(96, 1);
+ udelay(33);
+ gpio_set_value_cansleep(96, 0);
+ udelay(67);
+ gpio_set_value_cansleep(96, 1);
+ udelay(33);
+ gpio_set_value_cansleep(96, 0);
+ udelay(33);
+ gpio_set_value_cansleep(96, 1);
+ udelay(67);
+ gpio_set_value_cansleep(96, 0);
+ udelay(67);
+ gpio_set_value_cansleep(96, 1);
+ udelay(33);
+
+ /* t-EOS and t-start */
+ gpio_set_value_cansleep(96, 0);
+ ndelay(4200);
+ gpio_set_value_cansleep(96, 1);
+ ndelay(9000);
+
+ /* data byte */
+ /* RFA = 0 */
+ gpio_set_value_cansleep(96, 0);
+ udelay(67);
+ gpio_set_value_cansleep(96, 1);
+ udelay(33);
+
+ /* Address bits */
+ gpio_set_value_cansleep(96, 0);
+ udelay(67);
+ gpio_set_value_cansleep(96, 1);
+ udelay(33);
+ gpio_set_value_cansleep(96, 0);
+ udelay(67);
+ gpio_set_value_cansleep(96, 1);
+ udelay(33);
+
+ /* Data bits */
+ for (i = 0; i < 5; i++) {
+ remainder = (level) & (16);
+ if (remainder) {
+ gpio_set_value_cansleep(96, 0);
+ udelay(33);
+ gpio_set_value_cansleep(96, 1);
+ udelay(67);
+ } else {
+ gpio_set_value_cansleep(96, 0);
+ udelay(67);
+ gpio_set_value_cansleep(96, 1);
+ udelay(33);
+ }
+ level = level << 1;
+ }
+
+ /* t-EOS */
+ gpio_set_value_cansleep(96, 0);
+ ndelay(12000);
+ gpio_set_value_cansleep(96, 1);
+ return 0;
+}
+
+
static struct msm_panel_common_pdata mipi_truly_pdata = {
.pmic_backlight = mipi_truly_set_bl,
};
@@ -586,7 +673,7 @@
};
static struct msm_panel_common_pdata mipi_NT35510_pdata = {
- .pmic_backlight = NULL,/*mipi_NT35510_set_bl,*/
+ .pmic_backlight = evb_backlight_control,
};
static struct platform_device mipi_dsi_NT35510_panel_device = {
@@ -1028,7 +1115,7 @@
return rc;
rc = gpio_tlmm_config(GPIO_CFG(GPIO_QRD3_LCD_BACKLIGHT_EN, 0,
- GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
+ GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA),
GPIO_CFG_ENABLE);
if (rc < 0) {
pr_err("failed QRD3 GPIO_BACKLIGHT_EN tlmm config\n");
@@ -1084,7 +1171,17 @@
qrd3_dsi_gpio_initialized = 1;
}
- gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, !!on);
+ if (on) {
+ gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
+ udelay(190);
+ gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 0);
+ udelay(286);
+ gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, 1);
+ /* 1 wire mode starts from this low to high transition */
+ udelay(50);
+ } else
+ gpio_set_value_cansleep(GPIO_QRD3_LCD_BACKLIGHT_EN, !!on);
+
gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_2V85_EN, !!on);
gpio_set_value_cansleep(GPIO_QRD3_LCD_EXT_1V8_EN, !!on);
@@ -1167,10 +1264,11 @@
if (machine_is_msm7627a_qrd1())
platform_add_devices(qrd_fb_devices,
ARRAY_SIZE(qrd_fb_devices));
- else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
+ else if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
+ mipi_NT35510_pdata.bl_lock = 1;
platform_add_devices(evb_fb_devices,
ARRAY_SIZE(evb_fb_devices));
- else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7()) {
+ } else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7()) {
sku3_lcdc_lcd_camera_power_init();
platform_add_devices(qrd3_fb_devices,
ARRAY_SIZE(qrd3_fb_devices));
diff --git a/arch/arm/mach-msm/board-msm7627a.h b/arch/arm/mach-msm/board-msm7627a.h
index e3c9469..68e333f 100644
--- a/arch/arm/mach-msm/board-msm7627a.h
+++ b/arch/arm/mach-msm/board-msm7627a.h
@@ -14,25 +14,11 @@
#define __ARCH_ARM_MACH_MSM_BOARD_7627A__
#include "pm.h"
-#include <linux/fmem.h>
-
void __init msm7627a_init_mmc(void);
void __init msm_msm7627a_allocate_memory_regions(void);
void __init msm_fb_add_devices(void);
-#define PMEM_KERNEL_EBI1_SIZE 0x3A000
-#define MSM_PMEM_AUDIO_SIZE 0x1F4000
-
-#define MSM_PMEM_MDP_SIZE 0x2300000
-#define MSM_PMEM_ADSP_SIZE 0x1100000
-
-#define MSM7x25A_MSM_PMEM_MDP_SIZE 0x1500000
-#define MSM7x25A_MSM_PMEM_ADSP_SIZE 0xB91000
-
-#define QRD_PMEM_MDP_SIZE 0x1DD1000
-#define QRD_PMEM_ADSP_SIZE 0x1100000
-
enum {
GPIO_EXPANDER_IRQ_BASE = NR_MSM_IRQS + NR_GPIO_IRQS,
GPIO_EXPANDER_GPIO_BASE = NR_MSM_GPIOS,
@@ -116,14 +102,9 @@
void __init msm7627a_bt_power_init(void);
#endif
-extern struct fmem_platform_data fmem_pdata;
-
void __init msm7627a_camera_init(void);
u32 msm7627a_power_collapse_latency(enum msm_pm_sleep_mode);
void __init msm7627a_add_io_devices(void);
void __init qrd7627a_add_io_devices(void);
-void __init msm_adsp_add_pdev(void);
-void __init msm7627a_reserve(void);
-void __init qrd7627a_reserve(void);
#endif
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index b203c29..09f44a7 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -59,6 +59,9 @@
#include "pm-boot.h"
#include "board-msm7627a.h"
+#define PMEM_KERNEL_EBI1_SIZE 0x3A000
+#define MSM_PMEM_AUDIO_SIZE 0x5B000
+
#if defined(CONFIG_GPIO_SX150X)
enum {
SX150X_CORE,
@@ -152,6 +155,15 @@
.msm_i2c_config_gpio = gsbi_qup_i2c_gpio_config,
};
+#ifdef CONFIG_ARCH_MSM7X27A
+#define MSM_PMEM_MDP_SIZE 0x2300000
+#define MSM7x25A_MSM_PMEM_MDP_SIZE 0x1500000
+
+#define MSM_PMEM_ADSP_SIZE 0x1100000
+#define MSM7x25A_MSM_PMEM_ADSP_SIZE 0xB91000
+
+#endif
+
static struct android_usb_platform_data android_usb_pdata = {
.update_pid_and_serial_num = usb_diag_update_pid_and_serial_num,
};
@@ -438,6 +450,207 @@
.v_addr = MSM_CFG_CTL_BASE,
};
+static struct android_pmem_platform_data android_pmem_adsp_pdata = {
+ .name = "pmem_adsp",
+ .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+ .cached = 1,
+ .memory_type = MEMTYPE_EBI1,
+ .request_region = request_fmem_c_region,
+ .release_region = release_fmem_c_region,
+ .reusable = 1,
+};
+
+static struct platform_device android_pmem_adsp_device = {
+ .name = "android_pmem",
+ .id = 1,
+ .dev = { .platform_data = &android_pmem_adsp_pdata },
+};
+
+static unsigned pmem_mdp_size = MSM_PMEM_MDP_SIZE;
+static int __init pmem_mdp_size_setup(char *p)
+{
+ pmem_mdp_size = memparse(p, NULL);
+ return 0;
+}
+
+early_param("pmem_mdp_size", pmem_mdp_size_setup);
+
+static unsigned pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
+static int __init pmem_adsp_size_setup(char *p)
+{
+ pmem_adsp_size = memparse(p, NULL);
+ return 0;
+}
+
+early_param("pmem_adsp_size", pmem_adsp_size_setup);
+
+#define SND(desc, num) { .name = #desc, .id = num }
+static struct snd_endpoint snd_endpoints_list[] = {
+ SND(HANDSET, 0),
+ SND(MONO_HEADSET, 2),
+ SND(HEADSET, 3),
+ SND(SPEAKER, 6),
+ SND(TTY_HEADSET, 8),
+ SND(TTY_VCO, 9),
+ SND(TTY_HCO, 10),
+ SND(BT, 12),
+ SND(IN_S_SADC_OUT_HANDSET, 16),
+ SND(IN_S_SADC_OUT_SPEAKER_PHONE, 25),
+ SND(FM_DIGITAL_STEREO_HEADSET, 26),
+ SND(FM_DIGITAL_SPEAKER_PHONE, 27),
+ SND(FM_DIGITAL_BT_A2DP_HEADSET, 28),
+ SND(STEREO_HEADSET_AND_SPEAKER, 31),
+ SND(CURRENT, 0x7FFFFFFE),
+ SND(FM_ANALOG_STEREO_HEADSET, 35),
+ SND(FM_ANALOG_STEREO_HEADSET_CODEC, 36),
+};
+#undef SND
+
+static struct msm_snd_endpoints msm_device_snd_endpoints = {
+ .endpoints = snd_endpoints_list,
+ .num = sizeof(snd_endpoints_list) / sizeof(struct snd_endpoint)
+};
+
+static struct platform_device msm_device_snd = {
+ .name = "msm_snd",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_device_snd_endpoints
+ },
+};
+
+#define DEC0_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
+ (1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
+ (1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
+ (1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
+ (1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
+ (1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
+#define DEC1_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
+ (1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
+ (1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
+ (1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
+ (1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
+ (1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
+#define DEC2_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
+ (1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
+ (1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
+ (1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
+ (1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
+ (1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
+#define DEC3_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
+ (1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
+ (1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
+ (1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
+ (1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
+ (1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
+#define DEC4_FORMAT (1<<MSM_ADSP_CODEC_MIDI)
+
+static unsigned int dec_concurrency_table[] = {
+ /* Audio LP */
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DMA)), 0,
+ 0, 0, 0,
+
+ /* Concurrency 1 */
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC3_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC4_FORMAT),
+
+ /* Concurrency 2 */
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC3_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC4_FORMAT),
+
+ /* Concurrency 3 */
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC4_FORMAT),
+
+ /* Concurrency 4 */
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC4_FORMAT),
+
+ /* Concurrency 5 */
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC4_FORMAT),
+
+ /* Concurrency 6 */
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ 0, 0, 0,
+
+ /* Concurrency 7 */
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC4_FORMAT),
+};
+
+#define DEC_INFO(name, queueid, decid, nr_codec) { .module_name = name, \
+ .module_queueid = queueid, .module_decid = decid, \
+ .nr_codec_support = nr_codec}
+
+static struct msm_adspdec_info dec_info_list[] = {
+ DEC_INFO("AUDPLAY0TASK", 13, 0, 11), /* AudPlay0BitStreamCtrlQueue */
+ DEC_INFO("AUDPLAY1TASK", 14, 1, 11), /* AudPlay1BitStreamCtrlQueue */
+ DEC_INFO("AUDPLAY2TASK", 15, 2, 11), /* AudPlay2BitStreamCtrlQueue */
+ DEC_INFO("AUDPLAY3TASK", 16, 3, 11), /* AudPlay3BitStreamCtrlQueue */
+ DEC_INFO("AUDPLAY4TASK", 17, 4, 1), /* AudPlay4BitStreamCtrlQueue */
+};
+
+static struct msm_adspdec_database msm_device_adspdec_database = {
+ .num_dec = ARRAY_SIZE(dec_info_list),
+ .num_concurrency_support = (ARRAY_SIZE(dec_concurrency_table) / \
+ ARRAY_SIZE(dec_info_list)),
+ .dec_concurrency_table = dec_concurrency_table,
+ .dec_info_list = dec_info_list,
+};
+
+static struct platform_device msm_device_adspdec = {
+ .name = "msm_adspdec",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_device_adspdec_database
+ },
+};
+
+static struct android_pmem_platform_data android_pmem_audio_pdata = {
+ .name = "pmem_audio",
+ .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+ .cached = 0,
+ .memory_type = MEMTYPE_EBI1,
+};
+
+static struct platform_device android_pmem_audio_device = {
+ .name = "android_pmem",
+ .id = 2,
+ .dev = { .platform_data = &android_pmem_audio_pdata },
+};
+
+static struct android_pmem_platform_data android_pmem_pdata = {
+ .name = "pmem",
+ .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+ .cached = 1,
+ .memory_type = MEMTYPE_EBI1,
+};
+static struct platform_device android_pmem_device = {
+ .name = "android_pmem",
+ .id = 0,
+ .dev = { .platform_data = &android_pmem_pdata },
+};
+
static u32 msm_calculate_batt_capacity(u32 current_voltage);
static struct msm_psy_batt_pdata msm_psy_batt_data = {
@@ -590,8 +803,13 @@
static struct platform_device *common_devices[] __initdata = {
&android_usb_device,
+ &android_pmem_device,
+ &android_pmem_adsp_device,
+ &android_pmem_audio_device,
&fmem_device,
&msm_device_nand,
+ &msm_device_snd,
+ &msm_device_adspdec,
&asoc_msm_pcm,
&asoc_msm_dai0,
&asoc_msm_dai1,
@@ -611,9 +829,126 @@
&msm8625_kgsl_3d0,
};
+static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE;
+static int __init pmem_kernel_ebi1_size_setup(char *p)
+{
+ pmem_kernel_ebi1_size = memparse(p, NULL);
+ return 0;
+}
+early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup);
+
+static unsigned pmem_audio_size = MSM_PMEM_AUDIO_SIZE;
+static int __init pmem_audio_size_setup(char *p)
+{
+ pmem_audio_size = memparse(p, NULL);
+ return 0;
+}
+early_param("pmem_audio_size", pmem_audio_size_setup);
+
+static struct memtype_reserve msm7x27a_reserve_table[] __initdata = {
+ [MEMTYPE_SMI] = {
+ },
+ [MEMTYPE_EBI0] = {
+ .flags = MEMTYPE_FLAGS_1M_ALIGN,
+ },
+ [MEMTYPE_EBI1] = {
+ .flags = MEMTYPE_FLAGS_1M_ALIGN,
+ },
+};
+
+#ifdef CONFIG_ANDROID_PMEM
+static struct android_pmem_platform_data *pmem_pdata_array[] __initdata = {
+ &android_pmem_adsp_pdata,
+ &android_pmem_audio_pdata,
+ &android_pmem_pdata,
+};
+#endif
+
+static void __init size_pmem_devices(void)
+{
+#ifdef CONFIG_ANDROID_PMEM
+ unsigned int i;
+ unsigned int reusable_count = 0;
+
+ if (machine_is_msm7625a_surf() || machine_is_msm7625a_ffa()) {
+ pmem_mdp_size = MSM7x25A_MSM_PMEM_MDP_SIZE;
+ pmem_adsp_size = MSM7x25A_MSM_PMEM_ADSP_SIZE;
+ } else {
+ pmem_mdp_size = MSM_PMEM_MDP_SIZE;
+ pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
+ }
+
+ android_pmem_adsp_pdata.size = pmem_adsp_size;
+ android_pmem_pdata.size = pmem_mdp_size;
+ android_pmem_audio_pdata.size = pmem_audio_size;
+
+ fmem_pdata.size = 0;
+
+ /* Find pmem devices that should use FMEM (reusable) memory.
+ */
+ for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
+ struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
+
+ if (!reusable_count && pdata->reusable)
+ fmem_pdata.size += pdata->size;
+
+ reusable_count += (pdata->reusable) ? 1 : 0;
+
+ if (pdata->reusable && reusable_count > 1) {
+ pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
+ __func__, pdata->name);
+ pdata->reusable = 0;
+ }
+ }
+#endif
+
+}
+
+static void __init reserve_memory_for(struct android_pmem_platform_data *p)
+{
+ msm7x27a_reserve_table[p->memory_type].size += p->size;
+}
+
+static void __init reserve_pmem_memory(void)
+{
+#ifdef CONFIG_ANDROID_PMEM
+ unsigned int i;
+ for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
+ if (!pmem_pdata_array[i]->reusable)
+ reserve_memory_for(pmem_pdata_array[i]);
+ }
+
+ msm7x27a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
+#endif
+}
+
+static void __init msm7x27a_calculate_reserve_sizes(void)
+{
+ size_pmem_devices();
+ reserve_pmem_memory();
+}
+
+static int msm7x27a_paddr_to_memtype(unsigned int paddr)
+{
+ return MEMTYPE_EBI1;
+}
+
+static struct reserve_info msm7x27a_reserve_info __initdata = {
+ .memtype_reserve_table = msm7x27a_reserve_table,
+ .calculate_reserve_sizes = msm7x27a_calculate_reserve_sizes,
+ .paddr_to_memtype = msm7x27a_paddr_to_memtype,
+};
+
+static void __init msm7x27a_reserve(void)
+{
+ reserve_info = &msm7x27a_reserve_info;
+ msm_reserve();
+ fmem_pdata.phys = reserve_memory_for_fmem(fmem_pdata.size);
+}
+
static void __init msm8625_reserve(void)
{
- msm7627a_reserve();
+ msm7x27a_reserve();
memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
memblock_remove(MSM8625_WARM_BOOT_PHYS, SZ_32);
}
@@ -674,6 +1009,29 @@
}
};
+static void msm_adsp_add_pdev(void)
+{
+ int rc = 0;
+ struct rpc_board_dev *rpc_adsp_pdev;
+
+ rpc_adsp_pdev = kzalloc(sizeof(struct rpc_board_dev), GFP_KERNEL);
+ if (rpc_adsp_pdev == NULL) {
+ pr_err("%s: Memory Allocation failure\n", __func__);
+ return;
+ }
+ rpc_adsp_pdev->prog = ADSP_RPC_PROG;
+
+ if (cpu_is_msm8625())
+ rpc_adsp_pdev->pdev = msm8625_device_adsp;
+ else
+ rpc_adsp_pdev->pdev = msm_adsp_device;
+ rc = msm_rpc_add_board_dev(rpc_adsp_pdev, 1);
+ if (rc < 0) {
+ pr_err("%s: return val: %d\n", __func__, rc);
+ kfree(rpc_adsp_pdev);
+ }
+}
+
static void __init msm7627a_rumi3_init(void)
{
msm7x27a_init_ebi2();
@@ -821,7 +1179,7 @@
MACHINE_START(MSM7X27A_RUMI3, "QCT MSM7x27a RUMI3")
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm_common_io_init,
- .reserve = msm7627a_reserve,
+ .reserve = msm7x27a_reserve,
.init_irq = msm_init_irq,
.init_machine = msm7627a_rumi3_init,
.timer = &msm_timer,
@@ -831,7 +1189,7 @@
MACHINE_START(MSM7X27A_SURF, "QCT MSM7x27a SURF")
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm_common_io_init,
- .reserve = msm7627a_reserve,
+ .reserve = msm7x27a_reserve,
.init_irq = msm_init_irq,
.init_machine = msm7x2x_init,
.timer = &msm_timer,
@@ -841,7 +1199,7 @@
MACHINE_START(MSM7X27A_FFA, "QCT MSM7x27a FFA")
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm_common_io_init,
- .reserve = msm7627a_reserve,
+ .reserve = msm7x27a_reserve,
.init_irq = msm_init_irq,
.init_machine = msm7x2x_init,
.timer = &msm_timer,
@@ -851,7 +1209,7 @@
MACHINE_START(MSM7625A_SURF, "QCT MSM7625a SURF")
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm_common_io_init,
- .reserve = msm7627a_reserve,
+ .reserve = msm7x27a_reserve,
.init_irq = msm_init_irq,
.init_machine = msm7x2x_init,
.timer = &msm_timer,
@@ -861,7 +1219,7 @@
MACHINE_START(MSM7625A_FFA, "QCT MSM7625a FFA")
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm_common_io_init,
- .reserve = msm7627a_reserve,
+ .reserve = msm7x27a_reserve,
.init_irq = msm_init_irq,
.init_machine = msm7x2x_init,
.timer = &msm_timer,
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 947c639..88b442c 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -2666,7 +2666,7 @@
MSM_FB_DSUB_PMEM_ADDER, 4096)
#define MSM_PMEM_SF_SIZE 0x4000000 /* 64 Mbytes */
-#define MSM_HDMI_PRIM_PMEM_SF_SIZE 0x4000000 /* 64 Mbytes */
+#define MSM_HDMI_PRIM_PMEM_SF_SIZE 0x8000000 /* 128 Mbytes */
#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
unsigned char hdmi_is_primary = 1;
@@ -2882,7 +2882,7 @@
.id = 2,
.dev = { .platform_data = &android_pmem_adsp_pdata },
};
-#endif
+
static struct android_pmem_platform_data android_pmem_audio_pdata = {
.name = "pmem_audio",
.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
@@ -2895,7 +2895,7 @@
.id = 4,
.dev = { .platform_data = &android_pmem_audio_pdata },
};
-
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
#define PMEM_BUS_WIDTH(_bw) \
{ \
.vectors = &(struct msm_bus_vectors){ \
@@ -2954,8 +2954,8 @@
.id = 7,
.dev = { .platform_data = &android_pmem_smipool_pdata },
};
-#endif
-#endif
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
#define GPIO_DONGLE_PWR_EN 258
static void setup_display_power(void);
@@ -4264,9 +4264,9 @@
&android_pmem_device,
&android_pmem_adsp_device,
&android_pmem_smipool_device,
-#endif
&android_pmem_audio_device,
-#endif
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
#ifdef CONFIG_MSM_ROTATOR
&msm_rotator_device,
#endif
@@ -5195,9 +5195,9 @@
&android_pmem_device,
&android_pmem_adsp_device,
&android_pmem_smipool_device,
-#endif
&android_pmem_audio_device,
-#endif
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
#ifdef CONFIG_MSM_ROTATOR
&msm_rotator_device,
#endif
@@ -5491,15 +5491,19 @@
if (hdmi_is_primary)
pmem_sf_size = MSM_HDMI_PRIM_PMEM_SF_SIZE;
android_pmem_pdata.size = pmem_sf_size;
-#endif
android_pmem_audio_pdata.size = MSM_PMEM_AUDIO_SIZE;
-#endif
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
}
+#ifdef CONFIG_ANDROID_PMEM
+#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
static void __init reserve_memory_for(struct android_pmem_platform_data *p)
{
msm8x60_reserve_table[p->memory_type].size += p->size;
}
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
+#endif /*CONFIG_ANDROID_PMEM*/
static void __init reserve_pmem_memory(void)
{
@@ -5508,10 +5512,10 @@
reserve_memory_for(&android_pmem_adsp_pdata);
reserve_memory_for(&android_pmem_smipool_pdata);
reserve_memory_for(&android_pmem_pdata);
-#endif
reserve_memory_for(&android_pmem_audio_pdata);
+#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
msm8x60_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
-#endif
+#endif /*CONFIG_ANDROID_PMEM*/
}
static void __init reserve_mdp_memory(void);
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index f3b2178..60457cc 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -24,6 +24,9 @@
#include <linux/bootmem.h>
#include <linux/mfd/marimba.h>
#include <linux/power_supply.h>
+#include <linux/input/rmi_platformdata.h>
+#include <linux/input/rmi_i2c.h>
+#include <linux/i2c/atmel_mxt_ts.h>
#include <linux/regulator/consumer.h>
#include <linux/memblock.h>
#include <linux/input/ft5x06_ts.h>
@@ -55,6 +58,20 @@
#include "board-msm7x27a-regulator.h"
#include "board-msm7627a.h"
+#define PMEM_KERNEL_EBI1_SIZE 0x3A000
+#define MSM_PMEM_AUDIO_SIZE 0x5B000
+#define BAHAMA_SLAVE_ID_FM_REG 0x02
+#define FM_GPIO 83
+#define BT_PCM_BCLK_MODE 0x88
+#define BT_PCM_DIN_MODE 0x89
+#define BT_PCM_DOUT_MODE 0x8A
+#define BT_PCM_SYNC_MODE 0x8B
+#define FM_I2S_SD_MODE 0x8E
+#define FM_I2S_WS_MODE 0x8F
+#define FM_I2S_SCK_MODE 0x90
+#define I2C_PIN_CTL 0x15
+#define I2C_NORMAL 0x40
+
static struct platform_device msm_wlan_ar6000_pm_device = {
.name = "wlan_ar6000_pm_dev",
.id = -1,
@@ -108,6 +125,11 @@
.msm_i2c_config_gpio = gsbi_qup_i2c_gpio_config,
};
+#ifdef CONFIG_ARCH_MSM7X27A
+#define MSM_PMEM_MDP_SIZE 0x1DD1000
+#define MSM_PMEM_ADSP_SIZE 0x1100000
+#endif
+
static struct android_usb_platform_data android_usb_pdata = {
.update_pid_and_serial_num = usb_diag_update_pid_and_serial_num,
};
@@ -354,6 +376,203 @@
.v_addr = MSM_CFG_CTL_BASE,
};
+static struct android_pmem_platform_data android_pmem_adsp_pdata = {
+ .name = "pmem_adsp",
+ .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+ .cached = 1,
+ .memory_type = MEMTYPE_EBI1,
+};
+
+static struct platform_device android_pmem_adsp_device = {
+ .name = "android_pmem",
+ .id = 1,
+ .dev = { .platform_data = &android_pmem_adsp_pdata },
+};
+
+static unsigned pmem_mdp_size = MSM_PMEM_MDP_SIZE;
+static int __init pmem_mdp_size_setup(char *p)
+{
+ pmem_mdp_size = memparse(p, NULL);
+ return 0;
+}
+
+early_param("pmem_mdp_size", pmem_mdp_size_setup);
+
+static unsigned pmem_adsp_size = MSM_PMEM_ADSP_SIZE;
+static int __init pmem_adsp_size_setup(char *p)
+{
+ pmem_adsp_size = memparse(p, NULL);
+ return 0;
+}
+
+early_param("pmem_adsp_size", pmem_adsp_size_setup);
+
+#define SND(desc, num) { .name = #desc, .id = num }
+static struct snd_endpoint snd_endpoints_list[] = {
+ SND(HANDSET, 0),
+ SND(MONO_HEADSET, 2),
+ SND(HEADSET, 3),
+ SND(SPEAKER, 6),
+ SND(TTY_HEADSET, 8),
+ SND(TTY_VCO, 9),
+ SND(TTY_HCO, 10),
+ SND(BT, 12),
+ SND(IN_S_SADC_OUT_HANDSET, 16),
+ SND(IN_S_SADC_OUT_SPEAKER_PHONE, 25),
+ SND(FM_DIGITAL_STEREO_HEADSET, 26),
+ SND(FM_DIGITAL_SPEAKER_PHONE, 27),
+ SND(FM_DIGITAL_BT_A2DP_HEADSET, 28),
+ SND(STEREO_HEADSET_AND_SPEAKER, 31),
+ SND(CURRENT, 0x7FFFFFFE),
+ SND(FM_ANALOG_STEREO_HEADSET, 35),
+ SND(FM_ANALOG_STEREO_HEADSET_CODEC, 36),
+};
+#undef SND
+
+static struct msm_snd_endpoints msm_device_snd_endpoints = {
+ .endpoints = snd_endpoints_list,
+ .num = sizeof(snd_endpoints_list) / sizeof(struct snd_endpoint)
+};
+
+static struct platform_device msm_device_snd = {
+ .name = "msm_snd",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_device_snd_endpoints
+ },
+};
+
+#define DEC0_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
+ (1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
+ (1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
+ (1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
+ (1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
+ (1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
+#define DEC1_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
+ (1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
+ (1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
+ (1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
+ (1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
+ (1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
+#define DEC2_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
+ (1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
+ (1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
+ (1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
+ (1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
+ (1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
+#define DEC3_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
+ (1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
+ (1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
+ (1<<MSM_ADSP_CODEC_AMRNB)|(1<<MSM_ADSP_CODEC_WAV)| \
+ (1<<MSM_ADSP_CODEC_ADPCM)|(1<<MSM_ADSP_CODEC_YADPCM)| \
+ (1<<MSM_ADSP_CODEC_EVRC)|(1<<MSM_ADSP_CODEC_QCELP))
+#define DEC4_FORMAT (1<<MSM_ADSP_CODEC_MIDI)
+
+static unsigned int dec_concurrency_table[] = {
+ /* Audio LP */
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DMA)), 0,
+ 0, 0, 0,
+
+ /* Concurrency 1 */
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC3_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC4_FORMAT),
+
+ /* Concurrency 2 */
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC3_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC4_FORMAT),
+
+ /* Concurrency 3 */
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC2_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC4_FORMAT),
+
+ /* Concurrency 4 */
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC4_FORMAT),
+
+ /* Concurrency 5 */
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_TUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC4_FORMAT),
+
+ /* Concurrency 6 */
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ 0, 0, 0, 0,
+
+ /* Concurrency 7 */
+ (DEC0_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC1_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC2_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC3_FORMAT|(1<<MSM_ADSP_MODE_NONTUNNEL)|(1<<MSM_ADSP_OP_DM)),
+ (DEC4_FORMAT),
+};
+
+#define DEC_INFO(name, queueid, decid, nr_codec) { .module_name = name, \
+ .module_queueid = queueid, .module_decid = decid, \
+ .nr_codec_support = nr_codec}
+
+static struct msm_adspdec_info dec_info_list[] = {
+ DEC_INFO("AUDPLAY0TASK", 13, 0, 11), /* AudPlay0BitStreamCtrlQueue */
+ DEC_INFO("AUDPLAY1TASK", 14, 1, 11), /* AudPlay1BitStreamCtrlQueue */
+ DEC_INFO("AUDPLAY2TASK", 15, 2, 11), /* AudPlay2BitStreamCtrlQueue */
+ DEC_INFO("AUDPLAY3TASK", 16, 3, 11), /* AudPlay3BitStreamCtrlQueue */
+ DEC_INFO("AUDPLAY4TASK", 17, 4, 1), /* AudPlay4BitStreamCtrlQueue */
+};
+
+static struct msm_adspdec_database msm_device_adspdec_database = {
+ .num_dec = ARRAY_SIZE(dec_info_list),
+ .num_concurrency_support = (ARRAY_SIZE(dec_concurrency_table) / \
+ ARRAY_SIZE(dec_info_list)),
+ .dec_concurrency_table = dec_concurrency_table,
+ .dec_info_list = dec_info_list,
+};
+
+static struct platform_device msm_device_adspdec = {
+ .name = "msm_adspdec",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_device_adspdec_database
+ },
+};
+
+static struct android_pmem_platform_data android_pmem_audio_pdata = {
+ .name = "pmem_audio",
+ .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+ .cached = 0,
+ .memory_type = MEMTYPE_EBI1,
+};
+
+static struct platform_device android_pmem_audio_device = {
+ .name = "android_pmem",
+ .id = 2,
+ .dev = { .platform_data = &android_pmem_audio_pdata },
+};
+
+static struct android_pmem_platform_data android_pmem_pdata = {
+ .name = "pmem",
+ .allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
+ .cached = 1,
+ .memory_type = MEMTYPE_EBI1,
+};
+static struct platform_device android_pmem_device = {
+ .name = "android_pmem",
+ .id = 0,
+ .dev = { .platform_data = &android_pmem_pdata },
+};
+
static u32 msm_calculate_batt_capacity(u32 current_voltage);
static struct msm_psy_batt_pdata msm_psy_batt_data = {
@@ -381,7 +600,12 @@
static struct platform_device *common_devices[] __initdata = {
&android_usb_device,
+ &android_pmem_device,
+ &android_pmem_adsp_device,
+ &android_pmem_audio_device,
&msm_batt_device,
+ &msm_device_adspdec,
+ &msm_device_snd,
&asoc_msm_pcm,
&asoc_msm_dai0,
&asoc_msm_dai1,
@@ -415,6 +639,110 @@
&msm8625_kgsl_3d0,
};
+static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE;
+static int __init pmem_kernel_ebi1_size_setup(char *p)
+{
+ pmem_kernel_ebi1_size = memparse(p, NULL);
+ return 0;
+}
+early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup);
+
+static unsigned pmem_audio_size = MSM_PMEM_AUDIO_SIZE;
+static int __init pmem_audio_size_setup(char *p)
+{
+ pmem_audio_size = memparse(p, NULL);
+ return 0;
+}
+early_param("pmem_audio_size", pmem_audio_size_setup);
+
+static struct memtype_reserve msm7627a_reserve_table[] __initdata = {
+ [MEMTYPE_SMI] = {
+ },
+ [MEMTYPE_EBI0] = {
+ .flags = MEMTYPE_FLAGS_1M_ALIGN,
+ },
+ [MEMTYPE_EBI1] = {
+ .flags = MEMTYPE_FLAGS_1M_ALIGN,
+ },
+};
+
+static void __init size_pmem_devices(void)
+{
+#ifdef CONFIG_ANDROID_PMEM
+ android_pmem_adsp_pdata.size = pmem_adsp_size;
+ android_pmem_pdata.size = pmem_mdp_size;
+ android_pmem_audio_pdata.size = pmem_audio_size;
+#endif
+}
+
+static void __init reserve_memory_for(struct android_pmem_platform_data *p)
+{
+ msm7627a_reserve_table[p->memory_type].size += p->size;
+}
+
+static void __init reserve_pmem_memory(void)
+{
+#ifdef CONFIG_ANDROID_PMEM
+ reserve_memory_for(&android_pmem_adsp_pdata);
+ reserve_memory_for(&android_pmem_pdata);
+ reserve_memory_for(&android_pmem_audio_pdata);
+ msm7627a_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
+#endif
+}
+
+static void __init msm7627a_calculate_reserve_sizes(void)
+{
+ size_pmem_devices();
+ reserve_pmem_memory();
+}
+
+static int msm7627a_paddr_to_memtype(unsigned int paddr)
+{
+ return MEMTYPE_EBI1;
+}
+
+static struct reserve_info msm7627a_reserve_info __initdata = {
+ .memtype_reserve_table = msm7627a_reserve_table,
+ .calculate_reserve_sizes = msm7627a_calculate_reserve_sizes,
+ .paddr_to_memtype = msm7627a_paddr_to_memtype,
+};
+
+static void __init msm7627a_reserve(void)
+{
+ reserve_info = &msm7627a_reserve_info;
+ msm_reserve();
+ memblock_remove(MSM8625_WARM_BOOT_PHYS, SZ_32);
+}
+
+static void __init msm8625_reserve(void)
+{
+ memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
+ msm7627a_reserve();
+}
+
+static void msmqrd_adsp_add_pdev(void)
+{
+ int rc = 0;
+ struct rpc_board_dev *rpc_adsp_pdev;
+
+ rpc_adsp_pdev = kzalloc(sizeof(struct rpc_board_dev), GFP_KERNEL);
+ if (rpc_adsp_pdev == NULL) {
+ pr_err("%s: Memory Allocation failure\n", __func__);
+ return;
+ }
+ rpc_adsp_pdev->prog = ADSP_RPC_PROG;
+
+ if (cpu_is_msm8625())
+ rpc_adsp_pdev->pdev = msm8625_device_adsp;
+ else
+ rpc_adsp_pdev->pdev = msm_adsp_device;
+ rc = msm_rpc_add_board_dev(rpc_adsp_pdev, 1);
+ if (rc < 0) {
+ pr_err("%s: return val: %d\n", __func__, rc);
+ kfree(rpc_adsp_pdev);
+ }
+}
+
static void __init msm7627a_device_i2c_init(void)
{
msm_gsbi0_qup_i2c_device.dev.platform_data = &msm_gsbi0_qup_i2c_pdata;
@@ -520,19 +848,11 @@
}
}
-static void __init qrd8625_reserve(void)
-{
- memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
- qrd7627a_reserve();
- memblock_remove(MSM8625_WARM_BOOT_PHYS, SZ_32);
- msm_pm_8625_boot_pdata.p_addr = memblock_alloc(SZ_8, SZ_64K);
-}
-
static void __init msm_qrd_init(void)
{
msm7x2x_misc_init();
msm7627a_init_regulators();
- msm_adsp_add_pdev();
+ msmqrd_adsp_add_pdev();
if (cpu_is_msm8625())
msm8625_device_i2c_init();
@@ -577,7 +897,7 @@
MACHINE_START(MSM7627A_QRD1, "QRD MSM7627a QRD1")
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm_common_io_init,
- .reserve = qrd7627a_reserve,
+ .reserve = msm7627a_reserve,
.init_irq = msm_init_irq,
.init_machine = msm_qrd_init,
.timer = &msm_timer,
@@ -587,7 +907,7 @@
MACHINE_START(MSM7627A_QRD3, "QRD MSM7627a QRD3")
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm_common_io_init,
- .reserve = qrd7627a_reserve,
+ .reserve = msm7627a_reserve,
.init_irq = msm_init_irq,
.init_machine = msm_qrd_init,
.timer = &msm_timer,
@@ -597,7 +917,7 @@
MACHINE_START(MSM7627A_EVB, "QRD MSM7627a EVB")
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm_common_io_init,
- .reserve = qrd7627a_reserve,
+ .reserve = msm7627a_reserve,
.init_irq = msm_init_irq,
.init_machine = msm_qrd_init,
.timer = &msm_timer,
@@ -607,7 +927,7 @@
MACHINE_START(MSM8625_EVB, "QRD MSM8625 EVB")
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm8625_map_io,
- .reserve = qrd8625_reserve,
+ .reserve = msm8625_reserve,
.init_irq = msm8625_init_irq,
.init_machine = msm_qrd_init,
.timer = &msm_timer,
@@ -617,7 +937,7 @@
MACHINE_START(MSM8625_QRD7, "QRD MSM8625 QRD7")
.boot_params = PHYS_OFFSET + 0x100,
.map_io = msm8625_map_io,
- .reserve = qrd8625_reserve,
+ .reserve = msm8625_reserve,
.init_irq = msm8625_init_irq,
.init_machine = msm_qrd_init,
.timer = &msm_timer,
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 7828d64..794c342 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -4493,6 +4493,8 @@
static DEFINE_CLK_VOTER(dfab_scm_clk, &dfab_clk.c);
static DEFINE_CLK_VOTER(dfab_qseecom_clk, &dfab_clk.c);
static DEFINE_CLK_VOTER(dfab_tzcom_clk, &dfab_clk.c);
+static DEFINE_CLK_VOTER(dfab_msmbus_clk, &dfab_clk.c);
+static DEFINE_CLK_VOTER(dfab_msmbus_a_clk, &dfab_a_clk.c);
static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c);
static DEFINE_CLK_VOTER(ebi1_adm_clk, &ebi1_clk.c);
@@ -4927,10 +4929,10 @@
CLK_LOOKUP("bus_a_clk", mmfab_a_clk.c, "msm_mm_fab"),
CLK_LOOKUP("mem_clk", ebi1_msmbus_clk.c, "msm_bus"),
CLK_LOOKUP("mem_a_clk", ebi1_a_clk.c, "msm_bus"),
+ CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
+ CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("ebi1_clk", ebi1_clk.c, ""),
- CLK_LOOKUP("dfab_clk", dfab_clk.c, ""),
- CLK_LOOKUP("dfab_a_clk", dfab_a_clk.c, ""),
CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, ""),
CLK_LOOKUP("mmfpb_a_clk", mmfpb_a_clk.c, "clock-8960"),
CLK_LOOKUP("cfpb_a_clk", cfpb_a_clk.c, "clock-8960"),
@@ -5211,10 +5213,10 @@
CLK_LOOKUP("bus_a_clk", mmfab_a_clk.c, "msm_mm_fab"),
CLK_LOOKUP("mem_clk", ebi1_msmbus_clk.c, "msm_bus"),
CLK_LOOKUP("mem_a_clk", ebi1_a_clk.c, "msm_bus"),
+ CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
+ CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("ebi1_clk", ebi1_clk.c, NULL),
- CLK_LOOKUP("dfab_clk", dfab_clk.c, NULL),
- CLK_LOOKUP("dfab_a_clk", dfab_a_clk.c, NULL),
CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, NULL),
CLK_LOOKUP("mmfpb_a_clk", mmfpb_a_clk.c, "clock-8960"),
CLK_LOOKUP("cfpb_a_clk", cfpb_a_clk.c, "clock-8960"),
@@ -5229,7 +5231,7 @@
CLK_LOOKUP("core_clk", gsbi5_uart_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("core_clk", gsbi6_uart_clk.c, "msm_serial_hs.0"),
CLK_LOOKUP("core_clk", gsbi7_uart_clk.c, ""),
- CLK_LOOKUP("core_clk", gsbi8_uart_clk.c, ""),
+ CLK_LOOKUP("core_clk", gsbi8_uart_clk.c, "msm_serial_hsl.1"),
CLK_LOOKUP("core_clk", gsbi9_uart_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi10_uart_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi11_uart_clk.c, ""),
@@ -5282,7 +5284,7 @@
CLK_LOOKUP("iface_clk", gsbi5_p_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("iface_clk", gsbi6_p_clk.c, "msm_serial_hs.0"),
CLK_LOOKUP("iface_clk", gsbi7_p_clk.c, ""),
- CLK_LOOKUP("iface_clk", gsbi8_p_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gsbi8_p_clk.c, "msm_serial_hsl.1"),
CLK_LOOKUP("iface_clk", gsbi9_p_clk.c, ""),
CLK_LOOKUP("iface_clk", gsbi10_p_clk.c, "qup_i2c.10"),
CLK_LOOKUP("iface_clk", gsbi11_p_clk.c, ""),
@@ -5502,10 +5504,10 @@
CLK_LOOKUP("bus_a_clk", mmfab_a_clk.c, "msm_mm_fab"),
CLK_LOOKUP("mem_clk", ebi1_msmbus_clk.c, "msm_bus"),
CLK_LOOKUP("mem_a_clk", ebi1_a_clk.c, "msm_bus"),
+ CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
+ CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("ebi1_clk", ebi1_clk.c, NULL),
- CLK_LOOKUP("dfab_clk", dfab_clk.c, NULL),
- CLK_LOOKUP("dfab_a_clk", dfab_a_clk.c, NULL),
CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, NULL),
CLK_LOOKUP("mmfpb_a_clk", mmfpb_a_clk.c, "clock-8960"),
CLK_LOOKUP("cfpb_a_clk", cfpb_a_clk.c, "clock-8960"),
@@ -5897,18 +5899,6 @@
writel_relaxed(0, SW_RESET_CORE_REG);
writel_relaxed(0, SW_RESET_CORE2_REG);
- /* Reset 3D core once more, with its clock enabled. This can
- * eventually be done as part of the GDFS footswitch driver. */
- clk_set_rate(&gfx3d_clk.c, 27000000);
- clk_prepare_enable(&gfx3d_clk.c);
- writel_relaxed(BIT(12), SW_RESET_CORE_REG);
- mb();
- udelay(5);
- writel_relaxed(0, SW_RESET_CORE_REG);
- /* Make sure reset is de-asserted before clock is disabled. */
- mb();
- clk_disable_unprepare(&gfx3d_clk.c);
-
/* Enable TSSC and PDM PXO sources. */
writel_relaxed(BIT(11), TSSC_CLK_CTL_REG);
writel_relaxed(BIT(15), PDM_CLK_NS_REG);
@@ -6052,6 +6042,14 @@
/* Keep PXO on whenever APPS cpu is active */
clk_prepare_enable(&pxo_a_clk.c);
+ /* Reset 3D core while clocked to ensure it resets completely. */
+ clk_set_rate(&gfx3d_clk.c, 27000000);
+ clk_prepare_enable(&gfx3d_clk.c);
+ clk_reset(&gfx3d_clk.c, CLK_RESET_ASSERT);
+ udelay(5);
+ clk_reset(&gfx3d_clk.c, CLK_RESET_DEASSERT);
+ clk_disable_unprepare(&gfx3d_clk.c);
+
/* Initialize rates for clocks that only support one. */
clk_set_rate(&pdm_clk.c, 27000000);
clk_set_rate(&prng_clk.c, 64000000);
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index ad8c936..c724414 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3813,18 +3813,6 @@
/* Deassert all MM core resets. */
writel_relaxed(0, SW_RESET_CORE_REG);
- /* Reset 3D core once more, with its clock enabled. This can
- * eventually be done as part of the GDFS footswitch driver. */
- clk_set_rate(&gfx3d_clk.c, 27000000);
- clk_prepare_enable(&gfx3d_clk.c);
- writel_relaxed(BIT(12), SW_RESET_CORE_REG);
- mb();
- udelay(5);
- writel_relaxed(0, SW_RESET_CORE_REG);
- /* Make sure reset is de-asserted before clock is disabled. */
- mb();
- clk_disable_unprepare(&gfx3d_clk.c);
-
/* Enable TSSC and PDM PXO sources. */
writel_relaxed(BIT(11), TSSC_CLK_CTL_REG);
writel_relaxed(BIT(15), PDM_CLK_NS_REG);
@@ -3838,6 +3826,14 @@
/* Keep PXO on whenever APPS cpu is active */
clk_prepare_enable(&pxo_a_clk.c);
+ /* Reset 3D core while clocked to ensure it resets completely. */
+ clk_set_rate(&gfx3d_clk.c, 27000000);
+ clk_prepare_enable(&gfx3d_clk.c);
+ clk_reset(&gfx3d_clk.c, CLK_RESET_ASSERT);
+ udelay(5);
+ clk_reset(&gfx3d_clk.c, CLK_RESET_DEASSERT);
+ clk_disable_unprepare(&gfx3d_clk.c);
+
/* Initialize rates for clocks that only support one. */
clk_set_rate(&pdm_clk.c, 27000000);
clk_set_rate(&prng_clk.c, 64000000);
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index a2ebe50..89e3036 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -1356,6 +1356,8 @@
static DEFINE_CLK_VOTER(dfab_sdc2_clk, &dfab_clk.c);
static DEFINE_CLK_VOTER(dfab_sps_clk, &dfab_clk.c);
static DEFINE_CLK_VOTER(dfab_bam_dmux_clk, &dfab_clk.c);
+static DEFINE_CLK_VOTER(dfab_msmbus_clk, &dfab_clk.c);
+static DEFINE_CLK_VOTER(dfab_msmbus_a_clk, &dfab_a_clk.c);
static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c);
static DEFINE_CLK_VOTER(ebi1_adm_clk, &ebi1_clk.c);
@@ -1611,14 +1613,14 @@
CLK_LOOKUP("bus_a_clk", sfab_a_clk.c, "msm_sys_fab"),
CLK_LOOKUP("mem_clk", ebi1_msmbus_clk.c, "msm_bus"),
CLK_LOOKUP("mem_a_clk", ebi1_a_clk.c, "msm_bus"),
+ CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
+ CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("bus_clk", sfpb_clk.c, NULL),
CLK_LOOKUP("bus_a_clk", sfpb_a_clk.c, NULL),
CLK_LOOKUP("bus_clk", cfpb_clk.c, NULL),
CLK_LOOKUP("bus_a_clk", cfpb_a_clk.c, NULL),
CLK_LOOKUP("ebi1_clk", ebi1_clk.c, NULL),
- CLK_LOOKUP("dfab_clk", dfab_clk.c, NULL),
- CLK_LOOKUP("dfab_a_clk", dfab_a_clk.c, NULL),
CLK_LOOKUP("core_clk", gp0_clk.c, ""),
CLK_LOOKUP("core_clk", gp1_clk.c, ""),
diff --git a/arch/arm/mach-msm/clock-voter.c b/arch/arm/mach-msm/clock-voter.c
index 9ad653d..8ff4878 100644
--- a/arch/arm/mach-msm/clock-voter.c
+++ b/arch/arm/mach-msm/clock-voter.c
@@ -29,7 +29,7 @@
list_for_each_entry(clk, &parent->children, siblings) {
struct clk_voter *v = to_clk_voter(clk);
if (v->enabled)
- rate = max(v->rate, rate);
+ rate = max(clk->rate, rate);
}
return rate;
}
@@ -54,10 +54,10 @@
list_for_each_entry(clkp, &parent->children, siblings) {
clkh = to_clk_voter(clkp);
if (clkh->enabled && clkh != v)
- other_rate = max(clkh->rate, other_rate);
+ other_rate = max(clkp->rate, other_rate);
}
- cur_rate = max(other_rate, v->rate);
+ cur_rate = max(other_rate, clk->rate);
new_rate = max(other_rate, rate);
if (new_rate != cur_rate) {
@@ -66,7 +66,7 @@
goto unlock;
}
}
- v->rate = rate;
+ clk->rate = rate;
unlock:
spin_unlock_irqrestore(&voter_clk_lock, flags);
@@ -89,8 +89,8 @@
* than the current rate.
*/
cur_rate = voter_clk_aggregate_rate(parent);
- if (v->rate > cur_rate) {
- ret = clk_set_rate(parent, v->rate);
+ if (clk->rate > cur_rate) {
+ ret = clk_set_rate(parent, clk->rate);
if (ret)
goto out;
}
@@ -116,7 +116,7 @@
*/
v->enabled = false;
new_rate = voter_clk_aggregate_rate(parent);
- cur_rate = max(new_rate, v->rate);
+ cur_rate = max(new_rate, clk->rate);
if (new_rate < cur_rate)
clk_set_rate(parent, new_rate);
@@ -124,18 +124,6 @@
spin_unlock_irqrestore(&voter_clk_lock, flags);
}
-static unsigned long voter_clk_get_rate(struct clk *clk)
-{
- unsigned long rate, flags;
- struct clk_voter *v = to_clk_voter(clk);
-
- spin_lock_irqsave(&voter_clk_lock, flags);
- rate = v->rate;
- spin_unlock_irqrestore(&voter_clk_lock, flags);
-
- return rate;
-}
-
static int voter_clk_is_enabled(struct clk *clk)
{
struct clk_voter *v = to_clk_voter(clk);
@@ -163,7 +151,6 @@
.enable = voter_clk_enable,
.disable = voter_clk_disable,
.set_rate = voter_clk_set_rate,
- .get_rate = voter_clk_get_rate,
.is_enabled = voter_clk_is_enabled,
.round_rate = voter_clk_round_rate,
.get_parent = voter_clk_get_parent,
diff --git a/arch/arm/mach-msm/clock-voter.h b/arch/arm/mach-msm/clock-voter.h
index 10353d4..de17894 100644
--- a/arch/arm/mach-msm/clock-voter.h
+++ b/arch/arm/mach-msm/clock-voter.h
@@ -19,7 +19,6 @@
struct clk_voter {
bool enabled;
- unsigned long rate;
struct clk *parent;
struct clk c;
};
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 029fc6f3..3255248 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -36,6 +36,7 @@
#include <sound/apr_audio.h>
#include <mach/msm_tsif.h>
#include <mach/qdss.h>
+#include <mach/msm_serial_hs_lite.h>
#include "clock.h"
#include "devices.h"
#include "devices-msm8x60.h"
@@ -72,6 +73,7 @@
#define MSM_UART2DM_PHYS (MSM_GSBI2_PHYS + 0x40000)
#define MSM_UART5DM_PHYS (MSM_GSBI5_PHYS + 0x40000)
#define MSM_UART6DM_PHYS (MSM_GSBI6_PHYS + 0x40000)
+#define MSM_UART8DM_PHYS (MSM_GSBI8_PHYS + 0x40000)
/* GSBI QUP devices */
#define MSM_GSBI1_QUP_PHYS (MSM_GSBI1_PHYS + 0x80000)
@@ -308,6 +310,39 @@
.num_resources = ARRAY_SIZE(resources_uart_gsbi5),
.resource = resources_uart_gsbi5,
};
+
+static struct msm_serial_hslite_platform_data uart_gsbi8_pdata = {
+ .line = 0,
+};
+
+static struct resource resources_uart_gsbi8[] = {
+ {
+ .start = GSBI8_UARTDM_IRQ,
+ .end = GSBI8_UARTDM_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = MSM_UART8DM_PHYS,
+ .end = MSM_UART8DM_PHYS + PAGE_SIZE - 1,
+ .name = "uartdm_resource",
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MSM_GSBI8_PHYS,
+ .end = MSM_GSBI8_PHYS + PAGE_SIZE - 1,
+ .name = "gsbi_resource",
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device msm8960_device_uart_gsbi8 = {
+ .name = "msm_serial_hsl",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(resources_uart_gsbi8),
+ .resource = resources_uart_gsbi8,
+ .dev.platform_data = &uart_gsbi8_pdata,
+};
+
/* MSM Video core device */
#ifdef CONFIG_MSM_BUS_SCALING
static struct msm_bus_vectors vidc_init_vectors[] = {
diff --git a/arch/arm/mach-msm/devices-msm7x27.c b/arch/arm/mach-msm/devices-msm7x27.c
index 77314e7..5ec339e 100644
--- a/arch/arm/mach-msm/devices-msm7x27.c
+++ b/arch/arm/mach-msm/devices-msm7x27.c
@@ -855,6 +855,7 @@
.num_levels = 1,
.set_grp_async = NULL,
.idle_timeout = HZ,
+ .strtstp_sleepwake = true,
.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM,
};
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 4575166..70f1c2c 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -809,6 +809,7 @@
.num_levels = 3,
.set_grp_async = set_grp_xbar_async,
.idle_timeout = HZ,
+ .strtstp_sleepwake = true,
.nap_allowed = false,
.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM,
};
@@ -836,8 +837,10 @@
void __init msm8x25_kgsl_3d0_init(void)
{
- if (cpu_is_msm8625())
+ if (cpu_is_msm8625()) {
kgsl_3d0_pdata.idle_timeout = HZ/5;
+ kgsl_3d0_pdata.strtstp_sleepwake = false;
+ }
}
static void __init msm_register_device(struct platform_device *pdev, void *data)
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 5758dc4..078e931 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -55,6 +55,7 @@
extern struct platform_device msm8960_device_uart_gsbi2;
extern struct platform_device msm8960_device_uart_gsbi5;
+extern struct platform_device msm8960_device_uart_gsbi8;
extern struct platform_device msm8960_device_ssbi_pmic;
extern struct platform_device msm8960_device_qup_i2c_gsbi3;
extern struct platform_device msm8960_device_qup_i2c_gsbi4;
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 5b3f297..f01b0f7 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -99,6 +99,7 @@
#define MSM_CAMERA_FLASH_SRC_CURRENT_DRIVER (0x00000001<<2)
#define MSM_CAMERA_FLASH_SRC_EXT (0x00000001<<3)
#define MSM_CAMERA_FLASH_SRC_LED (0x00000001<<3)
+#define MSM_CAMERA_FLASH_SRC_LED1 (0x00000001<<4)
struct msm_camera_sensor_flash_pmic {
uint8_t num_of_src;
@@ -357,6 +358,7 @@
struct msm_panel_common_pdata {
uintptr_t hw_revision_addr;
int gpio;
+ bool bl_lock;
int (*backlight_level)(int level, int max, int min);
int (*pmic_backlight)(int level);
int (*panel_num)(void);
diff --git a/arch/arm/mach-msm/include/mach/msm_rtb.h b/arch/arm/mach-msm/include/mach/msm_rtb.h
index 5eea63f..74ddfbd 100644
--- a/arch/arm/mach-msm/include/mach/msm_rtb.h
+++ b/arch/arm/mach-msm/include/mach/msm_rtb.h
@@ -15,7 +15,7 @@
/*
* These numbers are used from the kernel command line and sysfs
- * to control filtering. Remove items from here with extreme caution
+ * to control filtering. Remove items from here with extreme caution.
*/
enum logk_event_type {
LOGK_NONE = 0,
@@ -24,9 +24,11 @@
LOGK_LOGBUF = 3,
LOGK_HOTPLUG = 4,
LOGK_CTXID = 5,
- LOGK_OTHER = 31,
+ LOGK_TIMESTAMP = 6,
};
+#define LOGTYPE_NOPC 0x80
+
struct msm_rtb_platform_data {
unsigned int size;
};
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 99bf212..aee562e 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -44,6 +44,8 @@
#define machine_is_copper_sim() 0
#endif
+#define PLATFORM_SUBTYPE_SGLTE 6
+
enum msm_cpu {
MSM_CPU_UNKNOWN = 0,
MSM_CPU_7X01,
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index 9b72f7c..7eaf526 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -1205,4 +1205,17 @@
int sps_setup_bam2bam_fifo(struct sps_mem_buffer *mem_buffer,
u32 addr, u32 size, int use_offset);
+/**
+ * Get the number of unused descriptors in the descriptor FIFO
+ * of a pipe
+ *
+ * @h - client context for SPS connection end point
+ *
+ * @desc_num - number of unused descriptors
+ *
+ * @return 0 on success, negative value on error
+ *
+ */
+int sps_get_unused_desc_num(struct sps_pipe *h, u32 *desc_num);
+
#endif /* _SPS_H_ */
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8064.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8064.c
index d05eaea..5a3d722 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8064.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8064.c
@@ -360,6 +360,8 @@
.tier = tier2,
.num_tiers = ARRAY_SIZE(tier2),
.buswidth = 8,
+ .slaveclk[DUAL_CTX] = "dfab_clk",
+ .slaveclk[ACTIVE_CTX] = "dfab_a_clk",
},
{
.id = MSM_BUS_SLAVE_SYSTEM_IMEM,
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c
index 36fe156..0f37c6d 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c
@@ -316,6 +316,8 @@
.tier = tier2,
.num_tiers = ARRAY_SIZE(tier2),
.buswidth = 8,
+ .slaveclk[DUAL_CTX] = "dfab_clk",
+ .slaveclk[ACTIVE_CTX] = "dfab_a_clk",
},
{
.id = MSM_BUS_SLAVE_SYSTEM_IMEM,
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
index 0d265c7..7ede23d 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
@@ -356,6 +356,8 @@
.tier = tier2,
.num_tiers = ARRAY_SIZE(tier2),
.buswidth = 8,
+ .slaveclk[DUAL_CTX] = "dfab_clk",
+ .slaveclk[ACTIVE_CTX] = "dfab_a_clk",
},
{
.id = MSM_BUS_SLAVE_SYSTEM_IMEM,
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_9615.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_9615.c
index 5b52cb9..34cb2db 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_9615.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_9615.c
@@ -184,6 +184,8 @@
.tier = tier2,
.num_tiers = ARRAY_SIZE(tier2),
.buswidth = 8,
+ .slaveclk[DUAL_CTX] = "dfab_clk",
+ .slaveclk[ACTIVE_CTX] = "dfab_a_clk",
},
{
.id = MSM_BUS_SLAVE_EBI_CH0,
diff --git a/arch/arm/mach-msm/msm_rtb.c b/arch/arm/mach-msm/msm_rtb.c
index 3f56d1a..403c13d 100644
--- a/arch/arm/mach-msm/msm_rtb.c
+++ b/arch/arm/mach-msm/msm_rtb.c
@@ -20,6 +20,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/atomic.h>
#include <asm/io.h>
#include <asm-generic/sizes.h>
#include <mach/memory.h>
@@ -76,7 +77,7 @@
int msm_rtb_event_should_log(enum logk_event_type log_type)
{
return msm_rtb.initialized && msm_rtb.enabled &&
- ((1 << log_type) & msm_rtb.filter);
+ ((1 << (log_type & ~LOGTYPE_NOPC)) & msm_rtb.filter);
}
EXPORT_SYMBOL(msm_rtb_event_should_log);
@@ -109,10 +110,39 @@
start->data = data;
}
+static void uncached_logk_pc_idx(enum logk_event_type log_type, void *caller,
+ void *data, int idx)
+{
+ struct msm_rtb_layout *start;
+
+ start = &msm_rtb.rtb[idx & (msm_rtb.nentries - 1)];
+
+ msm_rtb_emit_sentinel(start);
+ msm_rtb_write_type(log_type, start);
+ msm_rtb_write_caller(caller, start);
+ msm_rtb_write_idx(idx, start);
+ msm_rtb_write_data(data, start);
+ mb();
+
+ return;
+}
+
+static void uncached_logk_timestamp(int idx)
+{
+ unsigned long long timestamp;
+ void *timestamp_upper, *timestamp_lower;
+ timestamp = sched_clock();
+ timestamp_lower = (void *)lower_32_bits(timestamp);
+ timestamp_upper = (void *)upper_32_bits(timestamp);
+
+ uncached_logk_pc_idx(LOGK_TIMESTAMP|LOGTYPE_NOPC, timestamp_lower,
+ timestamp_upper, idx);
+}
+
#if defined(CONFIG_MSM_RTB_SEPARATE_CPUS)
static int msm_rtb_get_idx(void)
{
- int cpu, i;
+ int cpu, i, offset;
atomic_t *index;
/*
@@ -126,16 +156,34 @@
i = atomic_add_return(msm_rtb.step_size, index);
i -= msm_rtb.step_size;
+ /* Check if index has wrapped around */
+ offset = (i & (msm_rtb.nentries - 1)) -
+ ((i - msm_rtb.step_size) & (msm_rtb.nentries - 1));
+ if (offset < 0) {
+ uncached_logk_timestamp(i);
+ i = atomic_add_return(msm_rtb.step_size, index);
+ i -= msm_rtb.step_size;
+ }
+
return i;
}
#else
static int msm_rtb_get_idx(void)
{
- int i;
+ int i, offset;
i = atomic_inc_return(&msm_rtb_idx);
i--;
+ /* Check if index has wrapped around */
+ offset = (i & (msm_rtb.nentries - 1)) -
+ ((i - 1) & (msm_rtb.nentries - 1));
+ if (offset < 0) {
+ uncached_logk_timestamp(i);
+ i = atomic_inc_return(&msm_rtb_idx);
+ i--;
+ }
+
return i;
}
#endif
@@ -144,21 +192,13 @@
void *data)
{
int i;
- struct msm_rtb_layout *start;
if (!msm_rtb_event_should_log(log_type))
return 0;
i = msm_rtb_get_idx();
- start = &msm_rtb.rtb[i & (msm_rtb.nentries - 1)];
-
- msm_rtb_emit_sentinel(start);
- msm_rtb_write_type(log_type, start);
- msm_rtb_write_caller(caller, start);
- msm_rtb_write_idx(i, start);
- msm_rtb_write_data(data, start);
- mb();
+ uncached_logk_pc_idx(log_type, caller, data, i);
return 1;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index b5f071f..2403c02 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -371,14 +371,11 @@
mutex_lock(&q6.lock);
if (q6.state == APR_Q6_NOIMG) {
q6.pil = pil_get("q6");
- if (!q6.pil) {
- pr_err("APR: Unable to load q6 image\n");
+ if (IS_ERR(q6.pil)) {
+ rc = PTR_ERR(q6.pil);
+ pr_err("APR: Unable to load q6 image, error:%d\n", rc);
mutex_unlock(&q6.lock);
- /* Return failure if not intended for simulator */
- if (!machine_is_apq8064_sim()) {
- pr_debug("APR: Not apq8064 sim\n");
- return svc;
- }
+ return svc;
}
q6.state = APR_Q6_LOADED;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c b/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
index 75af881..ee32b80 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_multi_aac.c
@@ -69,7 +69,7 @@
/* Configure PCM output block */
rc = q6asm_enc_cfg_blk_pcm(audio->ac,
0, /*native sampling rate*/
- (audio->pcm_cfg.channel_count <= 2) ? 0 : 2);
+ 0 /*native channel count*/);
if (rc < 0) {
pr_err("pcm output block config failed\n");
break;
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 3cf0550..d00dd1a 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -39,6 +39,7 @@
#include <mach/system.h>
#include <mach/subsystem_notif.h>
#include <mach/socinfo.h>
+#include <asm/cacheflush.h>
#include "smd_private.h"
#include "proc_comm.h"
@@ -2473,10 +2474,12 @@
modem_queue_start_reset_notify();
} else if (modm & SMSM_RESET) {
- if (!disable_smsm_reset_handshake)
- apps |= SMSM_RESET;
-
pr_err("\nSMSM: Modem SMSM state changed to SMSM_RESET.");
+ if (!disable_smsm_reset_handshake) {
+ apps |= SMSM_RESET;
+ flush_cache_all();
+ outer_flush_all();
+ }
modem_queue_start_reset_notify();
} else if (modm & SMSM_INIT) {
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 9ef4028..5f835a2 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -88,24 +88,65 @@
static int msm_smd_pkt_debug_mask;
module_param_named(debug_mask, msm_smd_pkt_debug_mask,
int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+enum {
+ SMD_PKT_STATUS = 1U << 0,
+ SMD_PKT_READ = 1U << 1,
+ SMD_PKT_WRITE = 1U << 2,
+ SMD_PKT_READ_DUMP_BUFFER = 1U << 3,
+ SMD_PKT_WRITE_DUMP_BUFFER = 1U << 4,
+ SMD_PKT_POLL = 1U << 5,
+};
+
#define DEBUG
#ifdef DEBUG
-#define D_DUMP_BUFFER(prestr, cnt, buf) \
+#define D_STATUS(x...) \
do { \
- if (msm_smd_pkt_debug_mask) \
- print_hex_dump(KERN_DEBUG, prestr, \
- DUMP_PREFIX_NONE, 16, 1, \
- buf, cnt, 1); \
+ if (msm_smd_pkt_debug_mask & SMD_PKT_STATUS) \
+ pr_info("Status: "x); \
+} while (0)
+
+#define D_READ(x...) \
+do { \
+ if (msm_smd_pkt_debug_mask & SMD_PKT_READ) \
+ pr_info("Read: "x); \
+} while (0)
+
+#define D_WRITE(x...) \
+do { \
+ if (msm_smd_pkt_debug_mask & SMD_PKT_WRITE) \
+ pr_info("Write: "x); \
+} while (0)
+
+#define D_READ_DUMP_BUFFER(prestr, cnt, buf) \
+do { \
+ if (msm_smd_pkt_debug_mask & SMD_PKT_READ_DUMP_BUFFER) \
+ print_hex_dump(KERN_INFO, prestr, \
+ DUMP_PREFIX_NONE, 16, 1, \
+ buf, cnt, 1); \
+} while (0)
+
+#define D_WRITE_DUMP_BUFFER(prestr, cnt, buf) \
+do { \
+ if (msm_smd_pkt_debug_mask & SMD_PKT_WRITE_DUMP_BUFFER) \
+ print_hex_dump(KERN_INFO, prestr, \
+ DUMP_PREFIX_NONE, 16, 1, \
+ buf, cnt, 1); \
+} while (0)
+
+#define D_POLL(x...) \
+do { \
+ if (msm_smd_pkt_debug_mask & SMD_PKT_POLL) \
+ pr_info("Poll: "x); \
} while (0)
#else
-#define D_DUMP_BUFFER(prestr, cnt, buf) do {} while (0)
-#endif
-
-#ifdef DEBUG
-#define D(x...) if (msm_smd_pkt_debug_mask) printk(x)
-#else
-#define D(x...) do {} while (0)
+#define D_STATUS(x...) do {} while (0)
+#define D_READ(x...) do {} while (0)
+#define D_WRITE(x...) do {} while (0)
+#define D_READ_DUMP_BUFFER(prestr, cnt, buf) do {} while (0)
+#define D_WRITE_DUMP_BUFFER(prestr, cnt, buf) do {} while (0)
+#define D_POLL(x...) do {} while (0)
#endif
static ssize_t open_timeout_store(struct device *d,
@@ -171,6 +212,7 @@
wake_up(&smd_pkt_devp->ch_read_wait_queue);
wake_up(&smd_pkt_devp->ch_write_wait_queue);
wake_up_interruptible(&smd_pkt_devp->ch_opened_wait_queue);
+ D_STATUS("%s smd_pkt_dev id:%d\n", __func__, smd_pkt_devp->i);
}
static void loopback_probe_worker(struct work_struct *work)
@@ -195,9 +237,12 @@
smd_pkt_devp = container_of(work, struct smd_pkt_dev,
packet_arrival_work);
mutex_lock(&smd_pkt_devp->ch_lock);
- if (smd_pkt_devp->ch)
+ if (smd_pkt_devp->ch) {
+ D_READ("%s locking smd_pkt_dev id:%d wakelock\n",
+ __func__, smd_pkt_devp->i);
wake_lock_timeout(&smd_pkt_devp->pa_wake_lock,
WAKELOCK_TIMEOUT);
+ }
mutex_unlock(&smd_pkt_devp->ch_lock);
}
@@ -213,15 +258,20 @@
switch (cmd) {
case TIOCMGET:
+ D_STATUS("%s TIOCMGET command on smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
ret = smd_tiocmget(smd_pkt_devp->ch);
break;
case TIOCMSET:
+ D_STATUS("%s TIOCSET command on smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
ret = smd_tiocmset(smd_pkt_devp->ch, arg, ~arg);
break;
case SMD_PKT_IOCTL_BLOCKING_WRITE:
ret = get_user(smd_pkt_devp->blocking_write, (int *)arg);
break;
default:
+ pr_err("%s: Unrecognized ioctl command %d\n", __func__, cmd);
ret = -1;
}
@@ -240,18 +290,27 @@
struct smd_channel *chl;
unsigned long flags;
- D(KERN_ERR "%s: read %i bytes\n",
- __func__, count);
-
smd_pkt_devp = file->private_data;
- if (!smd_pkt_devp || !smd_pkt_devp->ch)
+ if (!smd_pkt_devp) {
+ pr_err("%s on NULL smd_pkt_dev\n", __func__);
return -EINVAL;
+ }
+
+ if (!smd_pkt_devp->ch) {
+ pr_err("%s on a closed smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
+ return -EINVAL;
+ }
if (smd_pkt_devp->do_reset_notification) {
/* notify client that a reset occurred */
+ pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
return notify_reset(smd_pkt_devp);
}
+ D_READ("Begin %s on smd_pkt_dev id:%d buffer_size %d\n",
+ __func__, smd_pkt_devp->i, count);
chl = smd_pkt_devp->ch;
wait_for_packet:
@@ -260,20 +319,19 @@
smd_read_avail(chl)) ||
smd_pkt_devp->has_reset);
- if (smd_pkt_devp->has_reset)
+ if (smd_pkt_devp->has_reset) {
+ pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
return notify_reset(smd_pkt_devp);
+ }
if (r < 0) {
/* qualify error message */
if (r != -ERESTARTSYS) {
/* we get this anytime a signal comes in */
- printk(KERN_ERR "ERROR:%s:%i:%s: "
- "wait_event_interruptible ret %i\n",
- __FILE__,
- __LINE__,
- __func__,
- r
- );
+ pr_err("%s: wait_event_interruptible on smd_pkt_dev"
+ " id:%d ret %i\n",
+ __func__, smd_pkt_devp->i, r);
}
return r;
}
@@ -284,13 +342,16 @@
pkt_size = smd_cur_packet_size(smd_pkt_devp->ch);
if (!pkt_size) {
- D(KERN_ERR "%s: Nothing to read\n", __func__);
+ pr_err("%s: No data on smd_pkt_dev id:%d, False wakeup\n",
+ __func__, smd_pkt_devp->i);
mutex_unlock(&smd_pkt_devp->rx_lock);
goto wait_for_packet;
}
if (pkt_size > count) {
- pr_err("packet size %i > buffer size %i,", pkt_size, count);
+ pr_err("%s: failure on smd_pkt_dev id: %d - packet size %d"
+ " > buffer size %d,", __func__, smd_pkt_devp->i,
+ pkt_size, count);
mutex_unlock(&smd_pkt_devp->rx_lock);
return -ETOOSMALL;
}
@@ -302,8 +363,12 @@
(pkt_size - bytes_read));
if (r < 0) {
mutex_unlock(&smd_pkt_devp->rx_lock);
- if (smd_pkt_devp->has_reset)
+ if (smd_pkt_devp->has_reset) {
+ pr_err("%s notifying reset for smd_pkt_dev"
+ " id:%d\n", __func__, smd_pkt_devp->i);
return notify_reset(smd_pkt_devp);
+ }
+ pr_err("%s Error while reading %d\n", __func__, r);
return r;
}
bytes_read += r;
@@ -313,10 +378,12 @@
smd_pkt_devp->has_reset);
if (smd_pkt_devp->has_reset) {
mutex_unlock(&smd_pkt_devp->rx_lock);
+ pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
return notify_reset(smd_pkt_devp);
}
} while (pkt_size != bytes_read);
- D_DUMP_BUFFER("read: ", bytes_read, buf);
+ D_READ_DUMP_BUFFER("Read: ", (bytes_read > 16 ? 16 : bytes_read), buf);
mutex_unlock(&smd_pkt_devp->rx_lock);
mutex_lock(&smd_pkt_devp->ch_lock);
@@ -325,12 +392,14 @@
!smd_cur_packet_size(smd_pkt_devp->ch)) {
wake_unlock(&smd_pkt_devp->pa_wake_lock);
smd_pkt_devp->poll_mode = 0;
+ D_READ("%s unlocked smd_pkt_dev id:%d wakelock\n",
+ __func__, smd_pkt_devp->i);
}
spin_unlock_irqrestore(&smd_pkt_devp->pa_spinlock, flags);
mutex_unlock(&smd_pkt_devp->ch_lock);
- D(KERN_ERR "%s: just read %i bytes\n",
- __func__, bytes_read);
+ D_READ("Finished %s on smd_pkt_dev id:%d %d bytes\n",
+ __func__, smd_pkt_devp->i, bytes_read);
/* check and wakeup read threads waiting on this device */
check_and_wakeup_reader(smd_pkt_devp);
@@ -347,24 +416,33 @@
struct smd_pkt_dev *smd_pkt_devp;
DEFINE_WAIT(write_wait);
- D(KERN_ERR "%s: writting %i bytes\n",
- __func__, count);
-
smd_pkt_devp = file->private_data;
- if (!smd_pkt_devp || !smd_pkt_devp->ch)
+ if (!smd_pkt_devp) {
+ pr_err("%s on NULL smd_pkt_dev\n", __func__);
return -EINVAL;
+ }
+
+ if (!smd_pkt_devp->ch) {
+ pr_err("%s on a closed smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
+ return -EINVAL;
+ }
if (smd_pkt_devp->do_reset_notification) {
+ pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
/* notify client that a reset occurred */
return notify_reset(smd_pkt_devp);
}
+ D_WRITE("Begin %s on smd_pkt_dev id:%d data_size %d\n",
+ __func__, smd_pkt_devp->i, count);
mutex_lock(&smd_pkt_devp->tx_lock);
if (!smd_pkt_devp->blocking_write) {
if (smd_write_avail(smd_pkt_devp->ch) < count) {
- D(KERN_ERR "%s: Not enough space to write\n",
- __func__);
+ pr_err("%s: Not enough space in smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
mutex_unlock(&smd_pkt_devp->tx_lock);
return -ENOMEM;
}
@@ -373,7 +451,8 @@
r = smd_write_start(smd_pkt_devp->ch, count);
if (r < 0) {
mutex_unlock(&smd_pkt_devp->tx_lock);
- pr_err("%s: Error %d @ smd_write_start\n", __func__, r);
+ pr_err("%s: Error:%d in smd_pkt_dev id:%d @ smd_write_start\n",
+ __func__, r, smd_pkt_devp->i);
return r;
}
@@ -391,6 +470,8 @@
if (smd_pkt_devp->has_reset) {
mutex_unlock(&smd_pkt_devp->tx_lock);
+ pr_err("%s notifying reset for smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
return notify_reset(smd_pkt_devp);
} else {
r = smd_write_segment(smd_pkt_devp->ch,
@@ -398,17 +479,22 @@
(count - bytes_written), 1);
if (r < 0) {
mutex_unlock(&smd_pkt_devp->tx_lock);
- if (smd_pkt_devp->has_reset)
+ if (smd_pkt_devp->has_reset) {
+ pr_err("%s notifying reset for"
+ " smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
return notify_reset(smd_pkt_devp);
+ }
}
bytes_written += r;
}
} while (bytes_written != count);
smd_write_end(smd_pkt_devp->ch);
mutex_unlock(&smd_pkt_devp->tx_lock);
-
- D(KERN_ERR "%s: just wrote %i bytes\n",
- __func__, count);
+ D_WRITE_DUMP_BUFFER("Write: ",
+ (bytes_written > 16 ? 16 : bytes_written), buf);
+ D_WRITE("Finished %s on smd_pkt_dev id:%d %d bytes\n",
+ __func__, smd_pkt_devp->i, count);
return count;
}
@@ -419,13 +505,18 @@
unsigned int mask = 0;
smd_pkt_devp = file->private_data;
- if (!smd_pkt_devp)
+ if (!smd_pkt_devp) {
+ pr_err("%s on a NULL device\n", __func__);
return POLLERR;
+ }
smd_pkt_devp->poll_mode = 1;
poll_wait(file, &smd_pkt_devp->ch_read_wait_queue, wait);
- if (smd_read_avail(smd_pkt_devp->ch))
+ if (smd_read_avail(smd_pkt_devp->ch)) {
mask |= POLLIN | POLLRDNORM;
+ D_POLL("%s sets POLLIN for smd_pkt_dev id: %d\n",
+ __func__, smd_pkt_devp->i);
+ }
return mask;
}
@@ -435,18 +526,27 @@
int sz;
unsigned long flags;
- if (!smd_pkt_devp || !smd_pkt_devp->ch)
+ if (!smd_pkt_devp) {
+ pr_err("%s on a NULL device\n", __func__);
return;
+ }
+
+ if (!smd_pkt_devp->ch) {
+ pr_err("%s on a closed smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
+ return;
+ }
sz = smd_cur_packet_size(smd_pkt_devp->ch);
if (sz == 0) {
- D(KERN_ERR "%s: packet size is 0\n", __func__);
+ D_READ("%s: No packet in smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
return;
}
if (!smd_read_avail(smd_pkt_devp->ch)) {
- D(KERN_ERR "%s: packet size is %i - "
- "but the data isn't here\n",
- __func__, sz);
+ D_READ("%s: packet size is %d in smd_pkt_dev id:%d -"
+ " but the data isn't here\n",
+ __func__, sz, smd_pkt_devp->i);
return;
}
@@ -456,20 +556,28 @@
wake_lock(&smd_pkt_devp->pa_wake_lock);
spin_unlock_irqrestore(&smd_pkt_devp->pa_spinlock, flags);
schedule_work(&smd_pkt_devp->packet_arrival_work);
- D(KERN_ERR "%s: after wake_up\n", __func__);
+ D_READ("%s: wake_up smd_pkt_dev id:%d\n", __func__, smd_pkt_devp->i);
}
static void check_and_wakeup_writer(struct smd_pkt_dev *smd_pkt_devp)
{
int sz;
- if (!smd_pkt_devp || !smd_pkt_devp->ch)
+ if (!smd_pkt_devp) {
+ pr_err("%s on a NULL device\n", __func__);
return;
+ }
+
+ if (!smd_pkt_devp->ch) {
+ pr_err("%s on a closed smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
+ return;
+ }
sz = smd_write_avail(smd_pkt_devp->ch);
if (sz) {
- D(KERN_ERR "%s: %d bytes Write Space available\n",
- __func__, sz);
+ D_WRITE("%s: %d bytes write space in smd_pkt_dev id:%d\n",
+ __func__, sz, smd_pkt_devp->i);
smd_disable_read_intr(smd_pkt_devp->ch);
wake_up(&smd_pkt_devp->ch_write_wait_queue);
}
@@ -479,31 +587,32 @@
{
struct smd_pkt_dev *smd_pkt_devp = priv;
- if (smd_pkt_devp->ch == 0)
+ if (smd_pkt_devp->ch == 0) {
+ pr_err("%s on a closed smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
return;
+ }
switch (event) {
case SMD_EVENT_DATA: {
- D(KERN_ERR "%s: data\n", __func__);
+ D_STATUS("%s: DATA event in smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
check_and_wakeup_reader(smd_pkt_devp);
if (smd_pkt_devp->blocking_write)
check_and_wakeup_writer(smd_pkt_devp);
- D(KERN_ERR "%s: data after check_and_wakeup\n", __func__);
break;
}
case SMD_EVENT_OPEN:
- D(KERN_ERR "%s: smd opened\n",
- __func__);
-
+ D_STATUS("%s: OPEN event in smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
smd_pkt_devp->has_reset = 0;
smd_pkt_devp->is_open = 1;
wake_up_interruptible(&smd_pkt_devp->ch_opened_wait_queue);
break;
case SMD_EVENT_CLOSE:
+ D_STATUS("%s: CLOSE event in smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
smd_pkt_devp->is_open = 0;
- printk(KERN_ERR "%s: smd closed\n",
- __func__);
-
/* put port into reset state */
clean_and_signal(smd_pkt_devp);
if (smd_pkt_devp->i == LOOPBACK_INX)
@@ -591,6 +700,8 @@
for (i = 0; i < NUM_SMD_PKT_PORTS; i++) {
if (!strncmp(pdev->name, smd_ch_name[i], SMD_MAX_CH_NAME_LEN)) {
complete_all(&smd_pkt_devp[i]->ch_allocated);
+ D_STATUS("%s allocated SMD ch for smd_pkt_dev id:%d\n",
+ __func__, i);
break;
}
}
@@ -614,8 +725,11 @@
smd_pkt_devp = container_of(inode->i_cdev, struct smd_pkt_dev, cdev);
- if (!smd_pkt_devp)
+ if (!smd_pkt_devp) {
+ pr_err("%s on a NULL device\n", __func__);
return -EINVAL;
+ }
+ D_STATUS("Begin %s on smd_pkt_dev id:%d\n", __func__, smd_pkt_devp->i);
wake_lock_init(&smd_pkt_devp->pa_wake_lock, WAKE_LOCK_SUSPEND,
smd_pkt_dev_name[smd_pkt_devp->i]);
@@ -643,6 +757,9 @@
smd_pkt_devp->pil = pil_get(peripheral);
if (IS_ERR(smd_pkt_devp->pil)) {
r = PTR_ERR(smd_pkt_devp->pil);
+ pr_err("%s failed on smd_pkt_dev id:%d -"
+ " pil_get failed for %s\n", __func__,
+ smd_pkt_devp->i, peripheral);
goto release_pd;
}
@@ -672,8 +789,9 @@
if (r == 0)
r = -ETIMEDOUT;
if (r < 0) {
- pr_err("%s: wait failed for smd port:"
- " %d\n", __func__, r);
+ pr_err("%s: wait on smd_pkt_dev id:%d"
+ " allocation failed rc:%d\n",
+ __func__, smd_pkt_devp->i, r);
goto release_pil;
}
}
@@ -697,16 +815,19 @@
r = -ETIMEDOUT;
if (r < 0) {
- pr_err("%s: wait failed for smd open: %d\n",
- __func__, r);
+ pr_err("%s: wait on smd_pkt_dev id:%d OPEN event failed"
+ " rc:%d\n", __func__, smd_pkt_devp->i, r);
} else if (!smd_pkt_devp->is_open) {
- pr_err("%s: Invalid open notification\n", __func__);
+ pr_err("%s: Invalid OPEN event on smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
r = -ENODEV;
} else {
smd_disable_read_intr(smd_pkt_devp->ch);
smd_pkt_devp->ch_size =
smd_write_avail(smd_pkt_devp->ch);
r = 0;
+ D_STATUS("Finished %s on smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
}
}
release_pil:
@@ -730,8 +851,12 @@
int r = 0;
struct smd_pkt_dev *smd_pkt_devp = file->private_data;
- if (!smd_pkt_devp)
+ if (!smd_pkt_devp) {
+ pr_err("%s on a NULL device\n", __func__);
return -EINVAL;
+ }
+ D_STATUS("Begin %s on smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
clean_and_signal(smd_pkt_devp);
@@ -750,6 +875,8 @@
smd_pkt_devp->has_reset = 0;
smd_pkt_devp->do_reset_notification = 0;
wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
+ D_STATUS("Finished %s on smd_pkt_dev id:%d\n",
+ __func__, smd_pkt_devp->i);
return r;
}
@@ -774,22 +901,14 @@
NUM_SMD_PKT_PORTS,
DEVICE_NAME);
if (IS_ERR_VALUE(r)) {
- printk(KERN_ERR "ERROR:%s:%i:%s: "
- "alloc_chrdev_region() ret %i.\n",
- __FILE__,
- __LINE__,
- __func__,
- r);
+ pr_err("%s: alloc_chrdev_region() failed ret:%i\n",
+ __func__, r);
goto error0;
}
smd_pkt_classp = class_create(THIS_MODULE, DEVICE_NAME);
if (IS_ERR(smd_pkt_classp)) {
- printk(KERN_ERR "ERROR:%s:%i:%s: "
- "class_create() ENOMEM\n",
- __FILE__,
- __LINE__,
- __func__);
+ pr_err("%s: class_create() failed ENOMEM\n", __func__);
r = -ENOMEM;
goto error1;
}
@@ -798,10 +917,8 @@
smd_pkt_devp[i] = kzalloc(sizeof(struct smd_pkt_dev),
GFP_KERNEL);
if (IS_ERR(smd_pkt_devp[i])) {
- printk(KERN_ERR "ERROR:%s:%i:%s kmalloc() ENOMEM\n",
- __FILE__,
- __LINE__,
- __func__);
+ pr_err("%s: kzalloc() failed for smd_pkt_dev id:%d\n",
+ __func__, i);
r = -ENOMEM;
goto error2;
}
@@ -827,11 +944,8 @@
1);
if (IS_ERR_VALUE(r)) {
- printk(KERN_ERR "%s:%i:%s: cdev_add() ret %i\n",
- __FILE__,
- __LINE__,
- __func__,
- r);
+ pr_err("%s: cdev_add() failed for smd_pkt_dev id:%d"
+ " ret:%i\n", __func__, i, r);
kfree(smd_pkt_devp[i]);
goto error2;
}
@@ -844,11 +958,8 @@
smd_pkt_dev_name[i]);
if (IS_ERR(smd_pkt_devp[i]->devicep)) {
- printk(KERN_ERR "%s:%i:%s: "
- "device_create() ENOMEM\n",
- __FILE__,
- __LINE__,
- __func__);
+ pr_err("%s: device_create() failed for smd_pkt_dev"
+ " id:%d\n", __func__, i);
r = -ENOMEM;
cdev_del(&smd_pkt_devp[i]->cdev);
kfree(smd_pkt_devp[i]);
@@ -856,13 +967,13 @@
}
if (device_create_file(smd_pkt_devp[i]->devicep,
&dev_attr_open_timeout))
- pr_err("%s: unable to create device attr on #%d\n",
- __func__, i);
+ pr_err("%s: unable to create device attr for"
+ " smd_pkt_dev id:%d\n", __func__, i);
}
INIT_DELAYED_WORK(&loopback_work, loopback_probe_worker);
- D(KERN_INFO "SMD Packet Port Driver Initialized.\n");
+ D_STATUS("SMD Packet Port Driver Initialized.\n");
return 0;
error2:
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 59643c5..8b2566a 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -566,7 +566,7 @@
of_property_read_u32_array(np, "arm,filter-ranges",
filter, ARRAY_SIZE(filter));
- if (filter[0] && filter[1]) {
+ if (filter[1]) {
writel_relaxed(ALIGN(filter[0] + filter[1], SZ_1M),
l2x0_base + L2X0_ADDR_FILTER_END);
writel_relaxed((filter[0] & ~(SZ_1M - 1)) | L2X0_ADDR_FILTER_EN,
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index a77d825..65ddfec 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -510,6 +510,18 @@
}
+void diag_toggle_event_mask(int toggle)
+{
+ uint8_t *ptr = driver->event_masks;
+
+ mutex_lock(&driver->diagchar_mutex);
+ if (toggle)
+ memset(ptr, 0xFF, EVENT_MASK_SIZE);
+ else
+ memset(ptr, 0, EVENT_MASK_SIZE);
+ mutex_unlock(&driver->diagchar_mutex);
+}
+
static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
{
uint8_t *ptr = driver->event_masks;
@@ -813,9 +825,8 @@
*(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
*(uint16_t *)(driver->apps_rsp_buf + 4) =
EVENT_LAST_ID + 1;
- for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
- *(unsigned char *)(driver->apps_rsp_buf + 6 + i)
- = 0x0;
+ memcpy(driver->apps_rsp_buf+6, driver->event_masks,
+ EVENT_LAST_ID/8+1);
/* cannot do this on work queue, as each event update
needs a num_bytes variable. Each queue_work call will
overwrite the previous input, as its the same struct */
@@ -832,6 +843,8 @@
#endif
} else if (*buf == 0x60) {
diag_event_config = *(buf+1);
+ diag_toggle_event_mask(*(buf+1));
+ diag_update_userspace_clients(EVENT_MASKS_TYPE);
#if defined(CONFIG_DIAG_OVER_USB)
if (chk_apps_only()) {
driver->apps_rsp_buf[0] = 0x60;
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index d7a104c..fb672e4 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -113,6 +113,7 @@
.pfp_fw = NULL,
.pm4_fw = NULL,
.wait_timeout = 10000, /* in milliseconds */
+ .ib_check_level = 0,
};
@@ -975,7 +976,7 @@
return status;
}
-const struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device,
+struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device,
unsigned int pt_base,
unsigned int gpuaddr,
unsigned int size)
@@ -1034,7 +1035,7 @@
uint8_t *adreno_convertaddr(struct kgsl_device *device, unsigned int pt_base,
unsigned int gpuaddr, unsigned int size)
{
- const struct kgsl_memdesc *memdesc;
+ struct kgsl_memdesc *memdesc;
memdesc = adreno_find_region(device, pt_base, gpuaddr, size);
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 07ccb85..4885312 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -77,6 +77,7 @@
unsigned int istore_size;
unsigned int pix_shader_start;
unsigned int instruction_size;
+ unsigned int ib_check_level;
};
struct adreno_gpudev {
@@ -119,7 +120,7 @@
void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords,
unsigned int value);
-const struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device,
+struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device,
unsigned int pt_base,
unsigned int gpuaddr,
unsigned int size);
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index 3461316..9e022b9 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -113,6 +113,8 @@
&kgsl_cff_dump_enable_fops);
debugfs_create_u32("wait_timeout", 0644, device->d_debugfs,
&adreno_dev->wait_timeout);
+ debugfs_create_u32("ib_check", 0644, device->d_debugfs,
+ &adreno_dev->ib_check_level);
/* Create post mortem control files */
diff --git a/drivers/gpu/msm/adreno_pm4types.h b/drivers/gpu/msm/adreno_pm4types.h
index 6e85ec6..fb44b25 100644
--- a/drivers/gpu/msm/adreno_pm4types.h
+++ b/drivers/gpu/msm/adreno_pm4types.h
@@ -29,11 +29,6 @@
/* skip N 32-bit words to get to the next packet */
#define CP_NOP 0x10
-/* indirect buffer dispatch. prefetch parser uses this packet type to determine
-* whether to pre-fetch the IB
-*/
-#define CP_INDIRECT_BUFFER 0x3f
-
/* indirect buffer dispatch. same as IB, but init is pipelined */
#define CP_INDIRECT_BUFFER_PFD 0x37
@@ -120,6 +115,9 @@
/* load constants from a location in memory */
#define CP_LOAD_CONSTANT_CONTEXT 0x2e
+/* (A2x) sets binning configuration registers */
+#define CP_SET_BIN_DATA 0x2f
+
/* selective invalidation of state pointers */
#define CP_INVALIDATE_STATE 0x3b
@@ -213,7 +211,7 @@
/* packet headers */
#define CP_HDR_ME_INIT cp_type3_packet(CP_ME_INIT, 18)
#define CP_HDR_INDIRECT_BUFFER_PFD cp_type3_packet(CP_INDIRECT_BUFFER_PFD, 2)
-#define CP_HDR_INDIRECT_BUFFER cp_type3_packet(CP_INDIRECT_BUFFER, 2)
+#define CP_HDR_INDIRECT_BUFFER_PFE cp_type3_packet(CP_INDIRECT_BUFFER_PFE, 2)
/* dword base address of the GFX decode space */
#define SUBBLOCK_OFFSET(reg) ((unsigned int)((reg) - (0x2000)))
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 5b197b4..d97659c 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -54,7 +54,7 @@
{CP_IM_LOAD, "IN__LOAD"},
{CP_IM_LOAD_IMMEDIATE, "IM_LOADI"},
{CP_IM_STORE, "IM_STORE"},
- {CP_INDIRECT_BUFFER, "IND_BUF_"},
+ {CP_INDIRECT_BUFFER_PFE, "IND_BUF_"},
{CP_INDIRECT_BUFFER_PFD, "IND_BUFP"},
{CP_INTERRUPT, "PM4_INTR"},
{CP_INVALIDATE_STATE, "INV_STAT"},
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 9542dfc..b9c0a28 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -22,6 +22,7 @@
#include "adreno.h"
#include "adreno_pm4types.h"
#include "adreno_ringbuffer.h"
+#include "adreno_debugfs.h"
#include "a2xx_reg.h"
#include "a3xx_reg.h"
@@ -545,6 +546,198 @@
adreno_ringbuffer_addcmds(rb, flags, cmds, sizedwords);
}
+static bool _parse_ibs(struct kgsl_device_private *dev_priv, uint gpuaddr,
+ int sizedwords);
+
+static bool
+_handle_type3(struct kgsl_device_private *dev_priv, uint *hostaddr)
+{
+ unsigned int opcode = cp_type3_opcode(*hostaddr);
+ switch (opcode) {
+ case CP_INDIRECT_BUFFER_PFD:
+ case CP_INDIRECT_BUFFER_PFE:
+ case CP_COND_INDIRECT_BUFFER_PFE:
+ case CP_COND_INDIRECT_BUFFER_PFD:
+ return _parse_ibs(dev_priv, hostaddr[1], hostaddr[2]);
+ case CP_NOP:
+ case CP_WAIT_FOR_IDLE:
+ case CP_WAIT_REG_MEM:
+ case CP_WAIT_REG_EQ:
+ case CP_WAT_REG_GTE:
+ case CP_WAIT_UNTIL_READ:
+ case CP_WAIT_IB_PFD_COMPLETE:
+ case CP_REG_RMW:
+ case CP_REG_TO_MEM:
+ case CP_MEM_WRITE:
+ case CP_MEM_WRITE_CNTR:
+ case CP_COND_EXEC:
+ case CP_COND_WRITE:
+ case CP_EVENT_WRITE:
+ case CP_EVENT_WRITE_SHD:
+ case CP_EVENT_WRITE_CFL:
+ case CP_EVENT_WRITE_ZPD:
+ case CP_DRAW_INDX:
+ case CP_DRAW_INDX_2:
+ case CP_DRAW_INDX_BIN:
+ case CP_DRAW_INDX_2_BIN:
+ case CP_VIZ_QUERY:
+ case CP_SET_STATE:
+ case CP_SET_CONSTANT:
+ case CP_IM_LOAD:
+ case CP_IM_LOAD_IMMEDIATE:
+ case CP_LOAD_CONSTANT_CONTEXT:
+ case CP_INVALIDATE_STATE:
+ case CP_SET_SHADER_BASES:
+ case CP_SET_BIN_MASK:
+ case CP_SET_BIN_SELECT:
+ case CP_SET_BIN_BASE_OFFSET:
+ case CP_SET_BIN_DATA:
+ case CP_CONTEXT_UPDATE:
+ case CP_INTERRUPT:
+ case CP_IM_STORE:
+ case CP_LOAD_STATE:
+ break;
+ /* these shouldn't come from userspace */
+ case CP_ME_INIT:
+ case CP_SET_PROTECTED_MODE:
+ default:
+ KGSL_CMD_ERR(dev_priv->device, "bad CP opcode %0x\n", opcode);
+ return false;
+ break;
+ }
+
+ return true;
+}
+
+static bool
+_handle_type0(struct kgsl_device_private *dev_priv, uint *hostaddr)
+{
+ unsigned int reg = type0_pkt_offset(*hostaddr);
+ unsigned int cnt = type0_pkt_size(*hostaddr);
+ if (reg < 0x0192 || (reg + cnt) >= 0x8000) {
+ KGSL_CMD_ERR(dev_priv->device, "bad type0 reg: 0x%0x cnt: %d\n",
+ reg, cnt);
+ return false;
+ }
+ return true;
+}
+
+/*
+ * Traverse IBs and dump them to test vector. Detect swap by inspecting
+ * register writes, keeping note of the current state, and dump
+ * framebuffer config to test vector
+ */
+static bool _parse_ibs(struct kgsl_device_private *dev_priv,
+ uint gpuaddr, int sizedwords)
+{
+ static uint level; /* recursion level */
+ bool ret = false;
+ uint *hostaddr, *hoststart;
+ int dwords_left = sizedwords; /* dwords left in the current command
+ buffer */
+ struct kgsl_mem_entry *entry;
+
+ spin_lock(&dev_priv->process_priv->mem_lock);
+ entry = kgsl_sharedmem_find_region(dev_priv->process_priv,
+ gpuaddr, sizedwords * sizeof(uint));
+ spin_unlock(&dev_priv->process_priv->mem_lock);
+ if (entry == NULL) {
+ KGSL_CMD_ERR(dev_priv->device,
+ "no mapping for gpuaddr: 0x%08x\n", gpuaddr);
+ return false;
+ }
+
+ hostaddr = (uint *)kgsl_gpuaddr_to_vaddr(&entry->memdesc, gpuaddr);
+ if (hostaddr == NULL) {
+ KGSL_CMD_ERR(dev_priv->device,
+ "no mapping for gpuaddr: 0x%08x\n", gpuaddr);
+ return false;
+ }
+
+ hoststart = hostaddr;
+
+ level++;
+
+ KGSL_CMD_INFO(dev_priv->device, "ib: gpuaddr:0x%08x, wc:%d, hptr:%p\n",
+ gpuaddr, sizedwords, hostaddr);
+
+ mb();
+ while (dwords_left > 0) {
+ bool cur_ret = true;
+ int count = 0; /* dword count including packet header */
+
+ switch (*hostaddr >> 30) {
+ case 0x0: /* type-0 */
+ count = (*hostaddr >> 16)+2;
+ cur_ret = _handle_type0(dev_priv, hostaddr);
+ break;
+ case 0x1: /* type-1 */
+ count = 2;
+ break;
+ case 0x3: /* type-3 */
+ count = ((*hostaddr >> 16) & 0x3fff) + 2;
+ cur_ret = _handle_type3(dev_priv, hostaddr);
+ break;
+ default:
+ KGSL_CMD_ERR(dev_priv->device, "unexpected type: "
+ "type:%d, word:0x%08x @ 0x%p, gpu:0x%08x\n",
+ *hostaddr >> 30, *hostaddr, hostaddr,
+ gpuaddr+4*(sizedwords-dwords_left));
+ cur_ret = false;
+ count = dwords_left;
+ break;
+ }
+
+ if (!cur_ret) {
+ KGSL_CMD_ERR(dev_priv->device,
+ "bad sub-type: #:%d/%d, v:0x%08x"
+ " @ 0x%p[gb:0x%08x], level:%d\n",
+ sizedwords-dwords_left, sizedwords, *hostaddr,
+ hostaddr, gpuaddr+4*(sizedwords-dwords_left),
+ level);
+
+ if (ADRENO_DEVICE(dev_priv->device)->ib_check_level
+ >= 2)
+ print_hex_dump(KERN_ERR,
+ level == 1 ? "IB1:" : "IB2:",
+ DUMP_PREFIX_OFFSET, 32, 4, hoststart,
+ sizedwords*4, 0);
+ goto done;
+ }
+
+ /* jump to next packet */
+ dwords_left -= count;
+ hostaddr += count;
+ if (dwords_left < 0) {
+ KGSL_CMD_ERR(dev_priv->device,
+ "bad count: c:%d, #:%d/%d, "
+ "v:0x%08x @ 0x%p[gb:0x%08x], level:%d\n",
+ count, sizedwords-(dwords_left+count),
+ sizedwords, *(hostaddr-count), hostaddr-count,
+ gpuaddr+4*(sizedwords-(dwords_left+count)),
+ level);
+ if (ADRENO_DEVICE(dev_priv->device)->ib_check_level
+ >= 2)
+ print_hex_dump(KERN_ERR,
+ level == 1 ? "IB1:" : "IB2:",
+ DUMP_PREFIX_OFFSET, 32, 4, hoststart,
+ sizedwords*4, 0);
+ goto done;
+ }
+ }
+
+ ret = true;
+done:
+ if (!ret)
+ KGSL_DRV_ERR(dev_priv->device,
+ "parsing failed: gpuaddr:0x%08x, "
+ "host:0x%p, wc:%d\n", gpuaddr, hoststart, sizedwords);
+
+ level--;
+
+ return ret;
+}
+
int
adreno_ringbuffer_issueibcmds(struct kgsl_device_private *dev_priv,
struct kgsl_context *context,
@@ -603,9 +796,12 @@
*cmds++ = ibdesc[0].sizedwords;
}
for (i = start_index; i < numibs; i++) {
- (void)kgsl_cffdump_parse_ibs(dev_priv, NULL,
- ibdesc[i].gpuaddr, ibdesc[i].sizedwords, false);
-
+ if (unlikely(adreno_dev->ib_check_level >= 1 &&
+ !_parse_ibs(dev_priv, ibdesc[i].gpuaddr,
+ ibdesc[i].sizedwords))) {
+ kfree(link);
+ return -EINVAL;
+ }
*cmds++ = CP_HDR_INDIRECT_BUFFER_PFD;
*cmds++ = ibdesc[i].gpuaddr;
*cmds++ = ibdesc[i].sizedwords;
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index 0361387..d0110b9 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -13,10 +13,6 @@
#ifndef __ADRENO_RINGBUFFER_H
#define __ADRENO_RINGBUFFER_H
-#define GSL_RB_USE_MEM_RPTR
-#define GSL_RB_USE_MEM_TIMESTAMP
-#define GSL_DEVICE_SHADOW_MEMSTORE_TO_USER
-
/*
* Adreno ringbuffer sizes in bytes - these are converted to
* the appropriate log2 values in the code
@@ -71,37 +67,16 @@
gpuaddr += sizeof(uint); \
} while (0)
-/* timestamp */
-#ifdef GSL_DEVICE_SHADOW_MEMSTORE_TO_USER
-#define GSL_RB_USE_MEM_TIMESTAMP
-#endif /* GSL_DEVICE_SHADOW_MEMSTORE_TO_USER */
-
-#ifdef GSL_RB_USE_MEM_TIMESTAMP
/* enable timestamp (...scratch0) memory shadowing */
#define GSL_RB_MEMPTRS_SCRATCH_MASK 0x1
#define GSL_RB_INIT_TIMESTAMP(rb)
-#else
-#define GSL_RB_MEMPTRS_SCRATCH_MASK 0x0
-#define GSL_RB_INIT_TIMESTAMP(rb) \
- adreno_regwrite((rb)->device->id, REG_CP_TIMESTAMP, 0)
-
-#endif /* GSL_RB_USE_MEMTIMESTAMP */
-
/* mem rptr */
-#ifdef GSL_RB_USE_MEM_RPTR
#define GSL_RB_CNTL_NO_UPDATE 0x0 /* enable */
#define GSL_RB_GET_READPTR(rb, data) \
do { \
*(data) = rb->memptrs->rptr; \
} while (0)
-#else
-#define GSL_RB_CNTL_NO_UPDATE 0x1 /* disable */
-#define GSL_RB_GET_READPTR(rb, data) \
- do { \
- adreno_regread((rb)->device->id, REG_CP_RB_RPTR, (data)); \
- } while (0)
-#endif /* GSL_RB_USE_MEMRPTR */
#define GSL_RB_CNTL_POLL_EN 0x0 /* disable */
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 6c1199e..45bcf69 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -938,40 +938,6 @@
return result;
}
-static bool check_ibdesc(struct kgsl_device_private *dev_priv,
- struct kgsl_ibdesc *ibdesc, unsigned int numibs,
- bool parse)
-{
- bool result = true;
- unsigned int i;
- for (i = 0; i < numibs; i++) {
- struct kgsl_mem_entry *entry;
- spin_lock(&dev_priv->process_priv->mem_lock);
- entry = kgsl_sharedmem_find_region(dev_priv->process_priv,
- ibdesc[i].gpuaddr, ibdesc[i].sizedwords * sizeof(uint));
- spin_unlock(&dev_priv->process_priv->mem_lock);
- if (entry == NULL) {
- KGSL_DRV_ERR(dev_priv->device,
- "invalid cmd buffer gpuaddr %08x " \
- "sizedwords %d\n", ibdesc[i].gpuaddr,
- ibdesc[i].sizedwords);
- result = false;
- break;
- }
-
- if (parse && !kgsl_cffdump_parse_ibs(dev_priv, &entry->memdesc,
- ibdesc[i].gpuaddr, ibdesc[i].sizedwords, true)) {
- KGSL_DRV_ERR(dev_priv->device,
- "invalid cmd buffer gpuaddr %08x " \
- "sizedwords %d numibs %d/%d\n",
- ibdesc[i].gpuaddr,
- ibdesc[i].sizedwords, i+1, numibs);
- result = false;
- break;
- }
- }
- return result;
-}
static long kgsl_ioctl_rb_issueibcmds(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
@@ -1037,12 +1003,6 @@
param->numibs = 1;
}
- if (!check_ibdesc(dev_priv, ibdesc, param->numibs, true)) {
- KGSL_DRV_ERR(dev_priv->device, "bad ibdesc");
- result = -EINVAL;
- goto free_ibdesc;
- }
-
result = dev_priv->device->ftbl->issueibcmds(dev_priv,
context,
ibdesc,
@@ -1052,18 +1012,6 @@
trace_kgsl_issueibcmds(dev_priv->device, param, result);
- if (result != 0)
- goto free_ibdesc;
-
- /* this is a check to try to detect if a command buffer was freed
- * during issueibcmds().
- */
- if (!check_ibdesc(dev_priv, ibdesc, param->numibs, false)) {
- KGSL_DRV_ERR(dev_priv->device, "bad ibdesc AFTER issue");
- result = -EINVAL;
- goto free_ibdesc;
- }
-
free_ibdesc:
kfree(ibdesc);
done:
@@ -1286,9 +1234,9 @@
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
- result = remap_vmalloc_range(vma, (void *) entry->memdesc.hostptr, 0);
+ result = kgsl_sharedmem_map_vma(vma, &entry->memdesc);
if (result) {
- KGSL_CORE_ERR("remap_vmalloc_range failed: %d\n", result);
+ KGSL_CORE_ERR("kgsl_sharedmem_map_vma failed: %d\n", result);
goto error_free_vmalloc;
}
@@ -1428,7 +1376,8 @@
int sglen = PAGE_ALIGN(size) / PAGE_SIZE;
unsigned long paddr = (unsigned long) addr;
- memdesc->sg = vmalloc(sglen * sizeof(struct scatterlist));
+ memdesc->sg = kgsl_sg_alloc(sglen);
+
if (memdesc->sg == NULL)
return -ENOMEM;
@@ -1468,7 +1417,7 @@
err:
spin_unlock(¤t->mm->page_table_lock);
- vfree(memdesc->sg);
+ kgsl_sg_free(memdesc->sg, sglen);
memdesc->sg = NULL;
return -EINVAL;
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 3dafbb9..87bba25 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -21,6 +21,7 @@
#include <linux/mutex.h>
#include <linux/cdev.h>
#include <linux/regulator/consumer.h>
+#include <linux/mm.h>
#define KGSL_NAME "kgsl"
@@ -98,7 +99,15 @@
extern struct kgsl_driver kgsl_driver;
struct kgsl_pagetable;
-struct kgsl_memdesc_ops;
+struct kgsl_memdesc;
+
+struct kgsl_memdesc_ops {
+ int (*vmflags)(struct kgsl_memdesc *);
+ int (*vmfault)(struct kgsl_memdesc *, struct vm_area_struct *,
+ struct vm_fault *);
+ void (*free)(struct kgsl_memdesc *memdesc);
+ int (*map_kernel_mem)(struct kgsl_memdesc *);
+};
/* shared memory allocation */
struct kgsl_memdesc {
@@ -185,13 +194,15 @@
}
return 0;
}
-static inline uint8_t *kgsl_gpuaddr_to_vaddr(const struct kgsl_memdesc *memdesc,
+static inline uint8_t *kgsl_gpuaddr_to_vaddr(struct kgsl_memdesc *memdesc,
unsigned int gpuaddr)
{
- if (memdesc->hostptr == NULL || memdesc->gpuaddr == 0 ||
- (gpuaddr < memdesc->gpuaddr ||
- gpuaddr >= memdesc->gpuaddr + memdesc->size))
- return NULL;
+ if (memdesc->gpuaddr == 0 ||
+ gpuaddr < memdesc->gpuaddr ||
+ gpuaddr >= (memdesc->gpuaddr + memdesc->size) ||
+ (NULL == memdesc->hostptr && memdesc->ops->map_kernel_mem &&
+ memdesc->ops->map_kernel_mem(memdesc)))
+ return NULL;
return memdesc->hostptr + (gpuaddr - memdesc->gpuaddr);
}
diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c
index a972f69..4e354d0 100644
--- a/drivers/gpu/msm/kgsl_cffdump.c
+++ b/drivers/gpu/msm/kgsl_cffdump.c
@@ -497,190 +497,6 @@
}
EXPORT_SYMBOL(kgsl_cffdump_waitirq);
-#define ADDRESS_STACK_SIZE 256
-#define GET_PM4_TYPE3_OPCODE(x) ((*(x) >> 8) & 0xFF)
-static unsigned int kgsl_cffdump_addr_count;
-
-static bool kgsl_cffdump_handle_type3(struct kgsl_device_private *dev_priv,
- uint *hostaddr, bool check_only)
-{
- static uint addr_stack[ADDRESS_STACK_SIZE];
- static uint size_stack[ADDRESS_STACK_SIZE];
-
- switch (GET_PM4_TYPE3_OPCODE(hostaddr)) {
- case CP_INDIRECT_BUFFER_PFD:
- case CP_INDIRECT_BUFFER:
- {
- /* traverse indirect buffers */
- int i;
- uint ibaddr = hostaddr[1];
- uint ibsize = hostaddr[2];
-
- /* is this address already in encountered? */
- for (i = 0;
- i < kgsl_cffdump_addr_count && addr_stack[i] != ibaddr;
- ++i)
- ;
-
- if (kgsl_cffdump_addr_count == i) {
- addr_stack[kgsl_cffdump_addr_count] = ibaddr;
- size_stack[kgsl_cffdump_addr_count++] = ibsize;
-
- if (kgsl_cffdump_addr_count >= ADDRESS_STACK_SIZE) {
- KGSL_CORE_ERR("stack overflow\n");
- return false;
- }
-
- return kgsl_cffdump_parse_ibs(dev_priv, NULL,
- ibaddr, ibsize, check_only);
- } else if (size_stack[i] != ibsize) {
- KGSL_CORE_ERR("gpuaddr: 0x%08x, "
- "wc: %u, with size wc: %u already on the "
- "stack\n", ibaddr, ibsize, size_stack[i]);
- return false;
- }
- }
- break;
- }
-
- return true;
-}
-
-/*
- * Traverse IBs and dump them to test vector. Detect swap by inspecting
- * register writes, keeping note of the current state, and dump
- * framebuffer config to test vector
- */
-bool kgsl_cffdump_parse_ibs(struct kgsl_device_private *dev_priv,
- const struct kgsl_memdesc *memdesc, uint gpuaddr, int sizedwords,
- bool check_only)
-{
- static uint level; /* recursion level */
- bool ret = true;
- uint *hostaddr, *hoststart;
- int dwords_left = sizedwords; /* dwords left in the current command
- buffer */
-
- if (level == 0)
- kgsl_cffdump_addr_count = 0;
-
- if (memdesc == NULL) {
- struct kgsl_mem_entry *entry;
- spin_lock(&dev_priv->process_priv->mem_lock);
- entry = kgsl_sharedmem_find_region(dev_priv->process_priv,
- gpuaddr, sizedwords * sizeof(uint));
- spin_unlock(&dev_priv->process_priv->mem_lock);
- if (entry == NULL) {
- KGSL_CORE_ERR("did not find mapping "
- "for gpuaddr: 0x%08x\n", gpuaddr);
- return true;
- }
- memdesc = &entry->memdesc;
- }
- hostaddr = (uint *)kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr);
- if (hostaddr == NULL) {
- KGSL_CORE_ERR("no kernel mapping for "
- "gpuaddr: 0x%08x\n", gpuaddr);
- return true;
- }
-
- hoststart = hostaddr;
-
- level++;
-
- mb();
- kgsl_cache_range_op((struct kgsl_memdesc *)memdesc,
- KGSL_CACHE_OP_INV);
-#ifdef DEBUG
- pr_info("kgsl: cffdump: ib: gpuaddr:0x%08x, wc:%d, hptr:%p\n",
- gpuaddr, sizedwords, hostaddr);
-#endif
-
- while (dwords_left > 0) {
- int count = 0; /* dword count including packet header */
- bool cur_ret = true;
-
- switch (*hostaddr >> 30) {
- case 0x0: /* type-0 */
- count = (*hostaddr >> 16)+2;
- break;
- case 0x1: /* type-1 */
- count = 2;
- break;
- case 0x3: /* type-3 */
- count = ((*hostaddr >> 16) & 0x3fff) + 2;
- cur_ret = kgsl_cffdump_handle_type3(dev_priv,
- hostaddr, check_only);
- break;
- default:
- pr_warn("kgsl: cffdump: parse-ib: unexpected type: "
- "type:%d, word:0x%08x @ 0x%p, gpu:0x%08x\n",
- *hostaddr >> 30, *hostaddr, hostaddr,
- gpuaddr+4*(sizedwords-dwords_left));
- cur_ret = false;
- count = dwords_left;
- break;
- }
-
-#ifdef DEBUG
- if (!cur_ret) {
- pr_info("kgsl: cffdump: bad sub-type: #:%d/%d, v:0x%08x"
- " @ 0x%p[gb:0x%08x], level:%d\n",
- sizedwords-dwords_left, sizedwords, *hostaddr,
- hostaddr, gpuaddr+4*(sizedwords-dwords_left),
- level);
-
- print_hex_dump(KERN_ERR, level == 1 ? "IB1:" : "IB2:",
- DUMP_PREFIX_OFFSET, 32, 4, hoststart,
- sizedwords*4, 0);
- }
-#endif
- ret = ret && cur_ret;
-
- /* jump to next packet */
- dwords_left -= count;
- hostaddr += count;
- cur_ret = dwords_left >= 0;
-
-#ifdef DEBUG
- if (!cur_ret) {
- pr_info("kgsl: cffdump: bad count: c:%d, #:%d/%d, "
- "v:0x%08x @ 0x%p[gb:0x%08x], level:%d\n",
- count, sizedwords-(dwords_left+count),
- sizedwords, *(hostaddr-count), hostaddr-count,
- gpuaddr+4*(sizedwords-(dwords_left+count)),
- level);
-
- print_hex_dump(KERN_ERR, level == 1 ? "IB1:" : "IB2:",
- DUMP_PREFIX_OFFSET, 32, 4, hoststart,
- sizedwords*4, 0);
- }
-#endif
-
- ret = ret && cur_ret;
- }
-
- if (!ret)
- pr_info("kgsl: cffdump: parsing failed: gpuaddr:0x%08x, "
- "host:0x%p, wc:%d\n", gpuaddr, hoststart, sizedwords);
-
- if (!check_only) {
-#ifdef DEBUG
- uint offset = gpuaddr - memdesc->gpuaddr;
- pr_info("kgsl: cffdump: ib-dump: hostptr:%p, gpuaddr:%08x, "
- "physaddr:%08x, offset:%d, size:%d", hoststart,
- gpuaddr, memdesc->physaddr + offset, offset,
- sizedwords*4);
-#endif
- kgsl_cffdump_syncmem(dev_priv, memdesc, gpuaddr, sizedwords*4,
- false);
- }
-
- level--;
-
- return ret;
-}
-
static int subbuf_start_handler(struct rchan_buf *buf,
void *subbuf, void *prev_subbuf, uint prev_padding)
{
diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c
index 03f8c42..d43b29b 100644
--- a/drivers/gpu/msm/kgsl_drm.c
+++ b/drivers/gpu/msm/kgsl_drm.c
@@ -903,17 +903,18 @@
struct drm_gem_object *obj = vma->vm_private_data;
struct drm_device *dev = obj->dev;
struct drm_kgsl_gem_object *priv;
- unsigned long offset, pg;
+ unsigned long offset;
struct page *page;
+ int i;
mutex_lock(&dev->struct_mutex);
priv = obj->driver_private;
offset = (unsigned long) vmf->virtual_address - vma->vm_start;
- pg = (unsigned long) priv->memdesc.hostptr + offset;
+ i = offset >> PAGE_SHIFT;
+ page = sg_page(&(priv->memdesc.sg[i]));
- page = vmalloc_to_page((void *) pg);
if (!page) {
mutex_unlock(&dev->struct_mutex);
return VM_FAULT_SIGBUS;
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index 942aa12..bbb5d46 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -357,8 +357,8 @@
int kgsl_gpummu_pt_equal(struct kgsl_pagetable *pt,
unsigned int pt_base)
{
- struct kgsl_gpummu_pt *gpummu_pt = pt->priv;
- return pt && pt_base && (gpummu_pt->base.gpuaddr == pt_base);
+ struct kgsl_gpummu_pt *gpummu_pt = pt ? pt->priv : NULL;
+ return gpummu_pt && pt_base && (gpummu_pt->base.gpuaddr == pt_base);
}
void kgsl_gpummu_destroy_pagetable(void *mmu_specific_pt)
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 194067b..ea11068 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -46,8 +46,8 @@
static int kgsl_iommu_pt_equal(struct kgsl_pagetable *pt,
unsigned int pt_base)
{
- struct iommu_domain *domain = pt->priv;
- return pt && pt_base && ((unsigned int)domain == pt_base);
+ struct iommu_domain *domain = pt ? pt->priv : NULL;
+ return domain && pt_base && ((unsigned int)domain == pt_base);
}
static void kgsl_iommu_destroy_pagetable(void *mmu_specific_pt)
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 6f575ec..d960eaf 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -509,6 +509,7 @@
pwr->nap_allowed = pdata->nap_allowed;
pwr->idle_needed = pdata->idle_needed;
pwr->interval_timeout = pdata->idle_timeout;
+ pwr->strtstp_sleepwake = pdata->strtstp_sleepwake;
pwr->ebi1_clk = clk_get(&pdev->dev, "bus_clk");
if (IS_ERR(pwr->ebi1_clk))
pwr->ebi1_clk = NULL;
@@ -629,7 +630,8 @@
KGSL_PWR_INFO(device, "idle timer expired device %d\n", device->id);
if (device->requested_state != KGSL_STATE_SUSPEND) {
- if (device->pwrctrl.restore_slumber)
+ if (device->pwrctrl.restore_slumber ||
+ device->pwrctrl.strtstp_sleepwake)
kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
else
kgsl_pwrctrl_request_state(device, KGSL_STATE_SLEEP);
@@ -770,7 +772,9 @@
case KGSL_STATE_NAP:
case KGSL_STATE_SLEEP:
del_timer_sync(&device->idle_timer);
- kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_NOMINAL);
+ if (!device->pwrctrl.strtstp_sleepwake)
+ kgsl_pwrctrl_pwrlevel_change(device,
+ KGSL_PWRLEVEL_NOMINAL);
device->pwrctrl.restore_slumber = true;
device->ftbl->suspend_context(device);
device->ftbl->stop(device);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 2222cdf..7dd429f 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -48,6 +48,7 @@
int thermal_pwrlevel;
unsigned int num_pwrlevels;
unsigned int interval_timeout;
+ bool strtstp_sleepwake;
struct regulator *gpu_reg;
uint32_t pcl;
unsigned int nap_allowed;
diff --git a/drivers/gpu/msm/kgsl_pwrscale_idlestats.c b/drivers/gpu/msm/kgsl_pwrscale_idlestats.c
index 2976b0b..71af893 100644
--- a/drivers/gpu/msm/kgsl_pwrscale_idlestats.c
+++ b/drivers/gpu/msm/kgsl_pwrscale_idlestats.c
@@ -153,6 +153,14 @@
MSM_IDLE_STATS_EVENT_IDLE_TIMER_EXPIRED);
}
+static void idlestats_wake(struct kgsl_device *device,
+ struct kgsl_pwrscale *pwrscale)
+{
+ /* Use highest perf level on wake-up from
+ sleep for better performance */
+ kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_TURBO);
+}
+
static int idlestats_init(struct kgsl_device *device,
struct kgsl_pwrscale *pwrscale)
{
@@ -218,5 +226,6 @@
.idle = idlestats_idle,
.busy = idlestats_busy,
.sleep = idlestats_sleep,
+ .wake = idlestats_wake,
.close = idlestats_close
};
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index 5634a19..1f142f8 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -299,13 +299,14 @@
struct vm_area_struct *vma,
struct vm_fault *vmf)
{
- unsigned long offset, pg;
+ unsigned long offset;
struct page *page;
+ int i;
offset = (unsigned long) vmf->virtual_address - vma->vm_start;
- pg = (unsigned long) memdesc->hostptr + offset;
- page = vmalloc_to_page((void *) pg);
+ i = offset >> PAGE_SHIFT;
+ page = sg_page(&memdesc->sg[i]);
if (page == NULL)
return VM_FAULT_SIGBUS;
@@ -322,8 +323,14 @@
static void kgsl_vmalloc_free(struct kgsl_memdesc *memdesc)
{
+ int i = 0;
+ struct scatterlist *sg;
kgsl_driver.stats.vmalloc -= memdesc->size;
- vfree(memdesc->hostptr);
+ if (memdesc->hostptr)
+ vunmap(memdesc->hostptr);
+ if (memdesc->sg)
+ for_each_sg(memdesc->sg, sg, memdesc->sglen, i)
+ __free_page(sg_page(sg));
}
static int kgsl_contiguous_vmflags(struct kgsl_memdesc *memdesc)
@@ -331,6 +338,39 @@
return VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTEXPAND;
}
+/*
+ * kgsl_vmalloc_map_kernel - Map the memory in memdesc to kernel address space
+ *
+ * @memdesc - The memory descriptor which contains information about the memory
+ *
+ * Return: 0 on success else error code
+ */
+static int kgsl_vmalloc_map_kernel(struct kgsl_memdesc *memdesc)
+{
+ if (!memdesc->hostptr) {
+ pgprot_t page_prot = pgprot_writecombine(PAGE_KERNEL);
+ struct page **pages = NULL;
+ struct scatterlist *sg;
+ int i;
+ /* create a list of pages to call vmap */
+ pages = vmalloc(memdesc->sglen * sizeof(struct page *));
+ if (!pages) {
+ KGSL_CORE_ERR("vmalloc(%d) failed\n",
+ memdesc->sglen * sizeof(struct page *));
+ return -ENOMEM;
+ }
+ for_each_sg(memdesc->sg, sg, memdesc->sglen, i)
+ pages[i] = sg_page(sg);
+ memdesc->hostptr = vmap(pages, memdesc->sglen,
+ VM_IOREMAP, page_prot);
+ vfree(pages);
+ }
+ if (!memdesc->hostptr)
+ return -ENOMEM;
+
+ return 0;
+}
+
static int kgsl_contiguous_vmfault(struct kgsl_memdesc *memdesc,
struct vm_area_struct *vma,
struct vm_fault *vmf)
@@ -374,6 +414,7 @@
.free = kgsl_vmalloc_free,
.vmflags = kgsl_vmalloc_vmflags,
.vmfault = kgsl_vmalloc_vmfault,
+ .map_kernel_mem = kgsl_vmalloc_map_kernel,
};
EXPORT_SYMBOL(kgsl_vmalloc_ops);
@@ -411,7 +452,7 @@
static int
_kgsl_sharedmem_vmalloc(struct kgsl_memdesc *memdesc,
struct kgsl_pagetable *pagetable,
- void *ptr, size_t size, unsigned int protflags)
+ size_t size, unsigned int protflags)
{
int order, ret = 0;
int sglen = PAGE_ALIGN(size) / PAGE_SIZE;
@@ -421,9 +462,9 @@
memdesc->pagetable = pagetable;
memdesc->priv = KGSL_MEMFLAGS_CACHED;
memdesc->ops = &kgsl_vmalloc_ops;
- memdesc->hostptr = (void *) ptr;
- memdesc->sg = vmalloc(sglen * sizeof(struct scatterlist));
+ memdesc->sg = kgsl_sg_alloc(sglen);
+
if (memdesc->sg == NULL) {
ret = -ENOMEM;
goto done;
@@ -434,17 +475,18 @@
memdesc->sglen = sglen;
sg_init_table(memdesc->sg, sglen);
- for (i = 0; i < memdesc->sglen; i++, ptr += PAGE_SIZE) {
- struct page *page = vmalloc_to_page(ptr);
+ for (i = 0; i < memdesc->sglen; i++) {
+ struct page *page = alloc_page(GFP_KERNEL | __GFP_ZERO |
+ __GFP_HIGHMEM);
if (!page) {
- ret = -EINVAL;
+ ret = -ENOMEM;
+ memdesc->sglen = i;
goto done;
}
+ flush_dcache_page(page);
sg_set_page(&memdesc->sg[i], page, PAGE_SIZE, 0);
}
- kgsl_cache_range_op(memdesc, KGSL_CACHE_OP_FLUSH);
-
ret = kgsl_mmu_map(pagetable, memdesc, protflags);
if (ret)
@@ -469,20 +511,18 @@
kgsl_sharedmem_vmalloc(struct kgsl_memdesc *memdesc,
struct kgsl_pagetable *pagetable, size_t size)
{
- void *ptr;
-
+ int ret = 0;
BUG_ON(size == 0);
size = ALIGN(size, PAGE_SIZE * 2);
- ptr = vmalloc(size);
- if (ptr == NULL) {
- KGSL_CORE_ERR("vmalloc(%d) failed\n", size);
- return -ENOMEM;
- }
-
- return _kgsl_sharedmem_vmalloc(memdesc, pagetable, ptr, size,
+ ret = _kgsl_sharedmem_vmalloc(memdesc, pagetable, size,
GSL_PT_PAGE_RV | GSL_PT_PAGE_WV);
+ if (!ret)
+ ret = kgsl_vmalloc_map_kernel(memdesc);
+ if (ret)
+ kgsl_sharedmem_free(memdesc);
+ return ret;
}
EXPORT_SYMBOL(kgsl_sharedmem_vmalloc);
@@ -491,25 +531,15 @@
struct kgsl_pagetable *pagetable,
size_t size, int flags)
{
- void *ptr;
unsigned int protflags;
BUG_ON(size == 0);
- ptr = vmalloc_user(size);
-
- if (ptr == NULL) {
- KGSL_CORE_ERR("vmalloc_user(%d) failed: allocated=%d\n",
- size, kgsl_driver.stats.vmalloc);
- return -ENOMEM;
- }
-
- kmemleak_not_leak(ptr);
protflags = GSL_PT_PAGE_RV;
if (!(flags & KGSL_MEMFLAGS_GPUREADONLY))
protflags |= GSL_PT_PAGE_WV;
- return _kgsl_sharedmem_vmalloc(memdesc, pagetable, ptr, size,
+ return _kgsl_sharedmem_vmalloc(memdesc, pagetable, size,
protflags);
}
EXPORT_SYMBOL(kgsl_sharedmem_vmalloc_user);
@@ -560,7 +590,7 @@
if (memdesc->ops && memdesc->ops->free)
memdesc->ops->free(memdesc);
- vfree(memdesc->sg);
+ kgsl_sg_free(memdesc->sg, memdesc->sglen);
memset(memdesc, 0, sizeof(*memdesc));
}
@@ -692,3 +722,33 @@
return 0;
}
EXPORT_SYMBOL(kgsl_sharedmem_set);
+
+/*
+ * kgsl_sharedmem_map_vma - Map a user vma to physical memory
+ *
+ * @vma - The user vma to map
+ * @memdesc - The memory descriptor which contains information about the
+ * physical memory
+ *
+ * Return: 0 on success else error code
+ */
+int
+kgsl_sharedmem_map_vma(struct vm_area_struct *vma,
+ const struct kgsl_memdesc *memdesc)
+{
+ unsigned long addr = vma->vm_start;
+ unsigned long size = vma->vm_end - vma->vm_start;
+ int ret, i = 0;
+
+ if (!memdesc->sg || (size != memdesc->size) ||
+ (memdesc->sglen != (size / PAGE_SIZE)))
+ return -EINVAL;
+
+ for (; addr < vma->vm_end; addr += PAGE_SIZE, i++) {
+ ret = vm_insert_page(vma, addr, sg_page(&memdesc->sg[i]));
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(kgsl_sharedmem_map_vma);
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index a1e4c91..def29b3 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -32,13 +32,6 @@
/** Set if the memdesc is mapped into all pagetables */
#define KGSL_MEMFLAGS_GLOBAL 0x00000002
-struct kgsl_memdesc_ops {
- int (*vmflags)(struct kgsl_memdesc *);
- int (*vmfault)(struct kgsl_memdesc *, struct vm_area_struct *,
- struct vm_fault *);
- void (*free)(struct kgsl_memdesc *memdesc);
-};
-
extern struct kgsl_memdesc_ops kgsl_vmalloc_ops;
int kgsl_sharedmem_vmalloc(struct kgsl_memdesc *memdesc,
@@ -92,13 +85,38 @@
return pa;
}
+int
+kgsl_sharedmem_map_vma(struct vm_area_struct *vma,
+ const struct kgsl_memdesc *memdesc);
+
+/*
+ * For relatively small sglists, it is preferable to use kzalloc
+ * rather than going down the vmalloc rat hole. If the size of
+ * the sglist is < PAGE_SIZE use kzalloc otherwise fallback to
+ * vmalloc
+ */
+
+static inline void *kgsl_sg_alloc(unsigned int sglen)
+{
+ if ((sglen * sizeof(struct scatterlist)) < PAGE_SIZE)
+ return kzalloc(sglen * sizeof(struct scatterlist), GFP_KERNEL);
+ else
+ return vmalloc(sglen * sizeof(struct scatterlist));
+}
+
+static inline void kgsl_sg_free(void *ptr, unsigned int sglen)
+{
+ if ((sglen * sizeof(struct scatterlist)) < PAGE_SIZE)
+ kfree(ptr);
+ else
+ vfree(ptr);
+}
+
static inline int
memdesc_sg_phys(struct kgsl_memdesc *memdesc,
unsigned int physaddr, unsigned int size)
{
- memdesc->sg = vmalloc(sizeof(struct scatterlist) * 1);
- if (memdesc->sg == NULL)
- return -ENOMEM;
+ memdesc->sg = kgsl_sg_alloc(1);
kmemleak_not_leak(memdesc->sg);
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 6c43a75..41f4435 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -409,7 +409,7 @@
unsigned int index = 0;
unsigned int nextindex;
unsigned int nextcnt = Z180_STREAM_END_CMD | 5;
- struct kgsl_memdesc tmp = {0};
+ struct kgsl_mem_entry *entry = NULL;
unsigned int cmd;
struct kgsl_device *device = dev_priv->device;
struct kgsl_pagetable *pagetable = dev_priv->process_priv->pagetable;
@@ -427,8 +427,30 @@
}
cmd = ibdesc[0].gpuaddr;
sizedwords = ibdesc[0].sizedwords;
-
- tmp.hostptr = (void *)*timestamp;
+ /*
+ * Get a kernel mapping to the IB for monkey patching.
+ * See the end of this function.
+ */
+ entry = kgsl_sharedmem_find_region(dev_priv->process_priv, cmd,
+ sizedwords);
+ if (entry == NULL) {
+ KGSL_DRV_ERR(device, "Bad ibdesc: gpuaddr 0x%x size %d\n",
+ cmd, sizedwords);
+ result = -EINVAL;
+ goto error;
+ }
+ /*
+ * This will only map memory if it exists, otherwise it will reuse the
+ * mapping. And the 2d userspace reuses IBs so we likely won't create
+ * too many mappings.
+ */
+ if (kgsl_gpuaddr_to_vaddr(&entry->memdesc, cmd) == NULL) {
+ KGSL_DRV_ERR(device,
+ "Cannot make kernel mapping for gpuaddr 0x%x\n",
+ cmd);
+ result = -EINVAL;
+ goto error;
+ }
KGSL_CMD_INFO(device, "ctxt %d ibaddr 0x%08x sizedwords %d\n",
context->id, cmd, sizedwords);
@@ -470,12 +492,13 @@
nextaddr = z180_dev->ringbuffer.cmdbufdesc.gpuaddr
+ rb_offset(nextindex);
- tmp.hostptr = (void *)(tmp.hostptr +
- (sizedwords * sizeof(unsigned int)));
- tmp.size = 12;
-
- kgsl_sharedmem_writel(&tmp, 4, nextaddr);
- kgsl_sharedmem_writel(&tmp, 8, nextcnt);
+ /* monkey patch the IB so that it jumps back to the ringbuffer */
+ kgsl_sharedmem_writel(&entry->memdesc,
+ ((sizedwords + 1) * sizeof(unsigned int)),
+ nextaddr);
+ kgsl_sharedmem_writel(&entry->memdesc,
+ ((sizedwords + 2) * sizeof(unsigned int)),
+ nextcnt);
/* sync memory before activating the hardware for the new command*/
mb();
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index ab732b2..a276e84 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -99,6 +99,7 @@
struct hci_fm_ssbi_peek ssbi_peek_reg;
struct hci_fm_sig_threshold_rsp sig_th;
struct hci_fm_ch_det_threshold ch_det_threshold;
+ struct hci_fm_data_rd_rsp default_data;
};
static struct video_device *priv_videodev;
@@ -1769,23 +1770,15 @@
struct iris_device *radio = video_get_drvdata(video_get_dev());
__u8 status = *((__u8 *) skb->data);
__u8 len;
- char *data;
if (status)
return;
len = skb->data[1];
- data = kmalloc(len+2, GFP_ATOMIC);
- if (!data) {
- FMDERR("Memory allocation failed");
- return;
- }
- data[0] = status;
- data[1] = len;
- memcpy(&data[2], &skb->data[DEFAULT_DATA_OFFSET], len);
- iris_q_evt_data(radio, data, len+2, IRIS_BUF_RD_DEFAULT);
+ memset(&radio->default_data, 0 , sizeof(struct hci_fm_data_rd_rsp));
+ memcpy(&radio->default_data, &skb->data[0], len+2);
+ iris_q_evt_data(radio, &skb->data[0], len+2, IRIS_BUF_RD_DEFAULT);
radio_hci_req_complete(hdev, status);
- kfree(data);
}
static void hci_cc_ssbi_peek_rsp(struct radio_hci_dev *hdev,
@@ -2773,6 +2766,8 @@
unsigned long arg = 0;
struct hci_fm_tx_ps tx_ps = {0};
struct hci_fm_tx_rt tx_rt = {0};
+ struct hci_fm_def_data_rd_req rd_txgain;
+ struct hci_fm_def_data_wr_req wr_txgain;
switch (ctrl->id) {
case V4L2_CID_PRIVATE_IRIS_TX_TONE:
@@ -3055,6 +3050,32 @@
radio->ps_repeatcount = ctrl->value;
break;
case V4L2_CID_TUNE_POWER_LEVEL:
+ if (ctrl->value > FM_TX_PWR_LVL_MAX)
+ ctrl->value = FM_TX_PWR_LVL_MAX;
+ if (ctrl->value < FM_TX_PWR_LVL_0)
+ ctrl->value = FM_TX_PWR_LVL_0;
+ rd_txgain.mode = FM_TX_PHY_CFG_MODE;
+ rd_txgain.length = FM_TX_PHY_CFG_LEN;
+ rd_txgain.param_len = 0x00;
+ rd_txgain.param = 0x00;
+
+ retval = hci_def_data_read(&rd_txgain, radio->fm_hdev);
+ if (retval < 0) {
+ FMDERR("Default data read failed for PHY_CFG %d\n",
+ retval);
+ break;
+ }
+ memset(&wr_txgain, 0, sizeof(wr_txgain));
+ wr_txgain.mode = FM_TX_PHY_CFG_MODE;
+ wr_txgain.length = FM_TX_PHY_CFG_LEN;
+ memcpy(&wr_txgain.data, &radio->default_data.data,
+ radio->default_data.ret_data_len);
+ wr_txgain.data[FM_TX_PWR_GAIN_OFFSET] =
+ (ctrl->value) * FM_TX_PWR_LVL_STEP_SIZE;
+ retval = hci_def_data_write(&wr_txgain, radio->fm_hdev);
+ if (retval < 0)
+ FMDERR("Default write failed for PHY_TXGAIN %d\n",
+ retval);
break;
case V4L2_CID_PRIVATE_IRIS_SOFT_MUTE:
radio->mute_mode.soft_mute = ctrl->value;
diff --git a/drivers/media/radio/radio-tavarua.c b/drivers/media/radio/radio-tavarua.c
index a2ec006..212e5d5 100644
--- a/drivers/media/radio/radio-tavarua.c
+++ b/drivers/media/radio/radio-tavarua.c
@@ -3631,13 +3631,8 @@
struct v4l2_hw_freq_seek *seek)
{
struct tavarua_device *radio = video_get_drvdata(video_devdata(file));
- int dir;
- if (seek->seek_upward)
- dir = SRCH_DIR_UP;
- else
- dir = SRCH_DIR_DOWN;
FMDBG("starting search\n");
- return tavarua_search(radio, CTRL_ON, dir);
+ return tavarua_search(radio, CTRL_ON, seek->seek_upward);
}
/*
diff --git a/drivers/media/video/msm/flash.c b/drivers/media/video/msm/flash.c
index 6985f3c..a86e5c4 100644
--- a/drivers/media/video/msm/flash.c
+++ b/drivers/media/video/msm/flash.c
@@ -212,6 +212,66 @@
#endif /* CONFIG_LEDS_PMIC8058 */
return rc;
}
+
+int msm_camera_flash_led(
+ struct msm_camera_sensor_flash_external *external,
+ unsigned led_state)
+{
+ int rc = 0;
+
+ CDBG("msm_camera_flash_led: %d\n", led_state);
+ switch (led_state) {
+ case MSM_CAMERA_LED_INIT:
+ rc = gpio_request(external->led_en, "sgm3141");
+ CDBG("MSM_CAMERA_LED_INIT: gpio_req: %d %d\n",
+ external->led_en, rc);
+ if (!rc)
+ gpio_direction_output(external->led_en, 0);
+ else
+ return 0;
+
+ rc = gpio_request(external->led_flash_en, "sgm3141");
+ CDBG("MSM_CAMERA_LED_INIT: gpio_req: %d %d\n",
+ external->led_flash_en, rc);
+ if (!rc)
+ gpio_direction_output(external->led_flash_en, 0);
+
+ break;
+
+ case MSM_CAMERA_LED_RELEASE:
+ CDBG("MSM_CAMERA_LED_RELEASE\n");
+ gpio_set_value_cansleep(external->led_en, 0);
+ gpio_free(external->led_en);
+ gpio_set_value_cansleep(external->led_flash_en, 0);
+ gpio_free(external->led_flash_en);
+ break;
+
+ case MSM_CAMERA_LED_OFF:
+ CDBG("MSM_CAMERA_LED_OFF\n");
+ gpio_set_value_cansleep(external->led_en, 0);
+ gpio_set_value_cansleep(external->led_flash_en, 0);
+ break;
+
+ case MSM_CAMERA_LED_LOW:
+ CDBG("MSM_CAMERA_LED_LOW\n");
+ gpio_set_value_cansleep(external->led_en, 1);
+ gpio_set_value_cansleep(external->led_flash_en, 1);
+ break;
+
+ case MSM_CAMERA_LED_HIGH:
+ CDBG("MSM_CAMERA_LED_HIGH\n");
+ gpio_set_value_cansleep(external->led_en, 1);
+ gpio_set_value_cansleep(external->led_flash_en, 1);
+ break;
+
+ default:
+ rc = -EFAULT;
+ break;
+ }
+
+ return rc;
+}
+
int msm_camera_flash_external(
struct msm_camera_sensor_flash_external *external,
unsigned led_state)
@@ -439,6 +499,12 @@
led_state);
break;
+ case MSM_CAMERA_FLASH_SRC_LED1:
+ rc = msm_camera_flash_led(
+ &fdata->flash_src->_fsrc.ext_driver_src,
+ led_state);
+ break;
+
default:
rc = -ENODEV;
break;
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
index af27a56..e2236191 100644
--- a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -743,13 +743,13 @@
if (mode == OUTPUT_SEC) {
/* Thumbnail */
if (vfe2x_ctrl->zsl_mode) {
- ao->output2buffer1_y_phy = ad->ping.ch_paddr[0];
- ao->output2buffer1_cbcr_phy = ad->ping.ch_paddr[1];
- ao->output2buffer2_y_phy = ad->pong.ch_paddr[0];
- ao->output2buffer2_cbcr_phy = ad->pong.ch_paddr[1];
- ao->output2buffer3_y_phy = ad->free_buf.ch_paddr[0];
- ao->output2buffer3_cbcr_phy = ad->free_buf.ch_paddr[1];
- bptr = &ao->output2buffer4_y_phy;
+ ao->output1buffer1_y_phy = ad->ping.ch_paddr[0];
+ ao->output1buffer1_cbcr_phy = ad->ping.ch_paddr[1];
+ ao->output1buffer2_y_phy = ad->pong.ch_paddr[0];
+ ao->output1buffer2_cbcr_phy = ad->pong.ch_paddr[1];
+ ao->output1buffer3_y_phy = ad->free_buf.ch_paddr[0];
+ ao->output1buffer3_cbcr_phy = ad->free_buf.ch_paddr[1];
+ bptr = &ao->output1buffer4_y_phy;
for (cnt = 0; cnt < 5; cnt++) {
*bptr = ad->pong.ch_paddr[0];
bptr++;
diff --git a/drivers/media/video/msm/sensors/Makefile b/drivers/media/video/msm/sensors/Makefile
index ac133d2..3052832 100644
--- a/drivers/media/video/msm/sensors/Makefile
+++ b/drivers/media/video/msm/sensors/Makefile
@@ -3,6 +3,7 @@
EXTRA_CFLAGS += -Idrivers/media/video/msm/io
EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
obj-$(CONFIG_MSM_CAMERA_SENSOR) += msm_sensor.o
+obj-$(CONFIG_OV5647) += ov5647_v4l2.o
obj-$(CONFIG_IMX074) += imx074_v4l2.o
obj-$(CONFIG_S5K3L1YX) += s5k3l1yx.o
obj-$(CONFIG_IMX091) += imx091.o
@@ -12,4 +13,3 @@
obj-$(CONFIG_MT9E013) += mt9e013_v4l2.o
obj-$(CONFIG_WEBCAM_OV9726) += ov9726_v4l2.o
obj-$(CONFIG_WEBCAM_OV7692_QRD) += ov7692_qrd_v4l2.o
-obj-$(CONFIG_OV5647) += ov5647_v4l2.o
diff --git a/drivers/media/video/msm/sensors/ov5647_v4l2.c b/drivers/media/video/msm/sensors/ov5647_v4l2.c
index 9a85836..ba0592e 100644
--- a/drivers/media/video/msm/sensors/ov5647_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov5647_v4l2.c
@@ -273,16 +273,16 @@
.y_output = 0x7A0, /*1952*/
.line_length_pclk = 0xA8C,
.frame_length_lines = 0x7B0,
- .vt_pixel_clk = 159408000,
+ .vt_pixel_clk = 79704000,
.op_pixel_clk = 159408000,
.binning_factor = 0x0,
},
{ /* For PREVIEW */
- .x_output = 0x500, /*2608*/ /*for 5Mp*/
- .y_output = 0x3C0, /*1952*/
- .line_length_pclk = 0x768 * 2,
+ .x_output = 0x500, /*1280*/
+ .y_output = 0x3C0, /*960*/
+ .line_length_pclk = 0x768,
.frame_length_lines = 0x3D8,
- .vt_pixel_clk = 159408000,
+ .vt_pixel_clk = 55969920,
.op_pixel_clk = 159408000,
.binning_factor = 0x0,
},
diff --git a/drivers/media/video/msm/wfd/Makefile b/drivers/media/video/msm/wfd/Makefile
index 2b39e66..5decaca 100644
--- a/drivers/media/video/msm/wfd/Makefile
+++ b/drivers/media/video/msm/wfd/Makefile
@@ -2,3 +2,4 @@
obj-y += enc-subdev.o
obj-y += vsg-subdev.o
obj-y += wfd-ioctl.o
+obj-y += wfd-util.o
diff --git a/drivers/media/video/msm/wfd/vsg-subdev.c b/drivers/media/video/msm/wfd/vsg-subdev.c
index 6ceadad..ac8e4e7 100644
--- a/drivers/media/video/msm/wfd/vsg-subdev.c
+++ b/drivers/media/video/msm/wfd/vsg-subdev.c
@@ -244,7 +244,7 @@
goto threshold_err_bad_param;
} else if (!context) {
WFD_MSG_ERR("Context not proper in %s", __func__);
- goto threshold_err_bad_param;
+ goto threshold_err_no_context;
}
INIT_WORK(&task->work, vsg_timer_helper_func);
@@ -255,6 +255,8 @@
hrtimer_forward_now(&context->threshold_timer, ns_to_ktime(
context->max_frame_interval));
return HRTIMER_RESTART;
+threshold_err_no_context:
+ return HRTIMER_NORESTART;
}
int vsg_init(struct v4l2_subdev *sd, u32 val)
@@ -399,13 +401,13 @@
&context->last_buffer->mdp_buf_info,
&temp->mdp_buf_info);
+ list_del(&temp->node);
+
if (!is_last_buffer &&
!(temp->flags & VSG_NEVER_RELEASE)) {
vsg_release_input_buffer(context, temp);
kfree(temp);
}
-
- list_del(&temp->node);
}
}
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
index 7692f43..2c2c551 100644
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -86,6 +86,7 @@
u32 input_buf_size;
u32 out_buf_size;
struct list_head input_mem_list;
+ struct wfd_stats stats;
};
struct wfd_vid_buffer {
@@ -313,6 +314,9 @@
WFD_MSG_ERR("Unable to queue the"
" buffer to mdp\n");
break;
+ } else {
+ wfd_stats_update(&inst->stats,
+ WFD_STAT_EVENT_MDP_QUEUE);
}
}
rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
@@ -514,6 +518,9 @@
WFD_MSG_ERR("Either streamoff called or"
" MDP REPORTED ERROR\n");
break;
+ } else {
+ wfd_stats_update(&inst->stats,
+ WFD_STAT_EVENT_MDP_DEQUEUE);
}
mregion = obuf_mdp.cookie;
@@ -534,8 +541,11 @@
core, ioctl, VSG_Q_BUFFER, (void *)&ibuf_vsg);
if (rc) {
- WFD_MSG_ERR("Failed to encode frame\n");
+ WFD_MSG_ERR("Failed to queue frame to vsg\n");
break;
+ } else {
+ wfd_stats_update(&inst->stats,
+ WFD_STAT_EVENT_VSG_QUEUE);
}
}
WFD_MSG_DBG("Exiting the thread\n");
@@ -833,9 +843,13 @@
WFD_MSG_ERR("Failed to register buffer\n");
return rc;
}
+
rc = vb2_qbuf(&inst->vid_bufq, b);
if (rc)
WFD_MSG_ERR("Failed to queue buffer\n");
+ else
+ wfd_stats_update(&inst->stats, WFD_STAT_EVENT_CLIENT_QUEUE);
+
return rc;
}
@@ -894,8 +908,17 @@
struct v4l2_buffer *b)
{
struct wfd_inst *inst = filp->private_data;
+ int rc;
+
WFD_MSG_INFO("Waiting to dequeue buffer\n");
- return vb2_dqbuf(&inst->vid_bufq, b, 0);
+ rc = vb2_dqbuf(&inst->vid_bufq, b, 0);
+
+ if (rc)
+ WFD_MSG_ERR("Failed to dequeue buffer\n");
+ else
+ wfd_stats_update(&inst->stats, WFD_STAT_EVENT_CLIENT_DEQUEUE);
+
+ return rc;
}
static int wfdioc_g_ctrl(struct file *filp, void *fh,
struct v4l2_control *a)
@@ -1129,11 +1152,15 @@
ioctl, VSG_RETURN_IP_BUFFER, (void *)&buf);
if (rc)
WFD_MSG_ERR("Failed to return buffer to vsg\n");
+ else
+ wfd_stats_update(&inst->stats, WFD_STAT_EVENT_ENC_DEQUEUE);
+
}
static int vsg_release_input_frame(void *cookie, struct vsg_buf_info *buf)
{
struct file *filp = cookie;
+ struct wfd_inst *inst = filp->private_data;
struct wfd_device *wfd_dev =
(struct wfd_device *)video_drvdata(filp);
int rc = 0;
@@ -1142,6 +1169,10 @@
ioctl, MDP_Q_BUFFER, buf);
if (rc)
WFD_MSG_ERR("Failed to Q buffer to mdp\n");
+ else {
+ wfd_stats_update(&inst->stats, WFD_STAT_EVENT_MDP_QUEUE);
+ wfd_stats_update(&inst->stats, WFD_STAT_EVENT_VSG_DEQUEUE);
+ }
return rc;
}
@@ -1149,9 +1180,11 @@
static int vsg_encode_frame(void *cookie, struct vsg_buf_info *buf)
{
struct file *filp = cookie;
+ struct wfd_inst *inst = filp->private_data;
struct wfd_device *wfd_dev =
(struct wfd_device *)video_drvdata(filp);
struct venc_buf_info venc_buf;
+ int rc = 0;
if (!buf)
return -EINVAL;
@@ -1162,8 +1195,16 @@
};
wfd_flush_ion_buffer(wfd_dev->ion_client, venc_buf.mregion);
- return v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
+
+ rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
ENCODE_FRAME, &venc_buf);
+
+ if (rc)
+ WFD_MSG_ERR("Encode failed\n");
+ else
+ wfd_stats_update(&inst->stats, WFD_STAT_EVENT_ENC_QUEUE);
+
+ return rc;
}
void *wfd_vb2_mem_ops_get_userptr(void *alloc_ctx, unsigned long vaddr,
@@ -1220,6 +1261,9 @@
spin_lock_init(&inst->inst_lock);
INIT_LIST_HEAD(&inst->input_mem_list);
INIT_LIST_HEAD(&inst->minfo_list);
+
+ wfd_stats_init(&inst->stats, MINOR(filp->f_dentry->d_inode->i_rdev));
+
rc = v4l2_subdev_call(&wfd_dev->mdp_sdev, core, ioctl, MDP_OPEN,
(void *)&inst->mdp_inst);
if (rc) {
@@ -1298,6 +1342,8 @@
kfree(inst);
}
+
+ wfd_stats_deinit(&inst->stats);
WFD_MSG_DBG("wfd_close: X\n");
return 0;
}
@@ -1371,6 +1417,7 @@
goto err_venc_init;
}
+ WFD_MSG_DBG("__wfd_probe: X\n");
return rc;
err_venc_init:
@@ -1403,6 +1450,14 @@
pdev->dev.platform_data = (void *) wfd_dev;
ion_client = msm_ion_client_create(-1, "wfd");
+
+ rc = wfd_stats_setup();
+ if (rc) {
+ WFD_MSG_ERR("No debugfs support: %d\n", rc);
+ /* Don't treat this as a fatal err */
+ rc = 0;
+ }
+
if (!ion_client) {
WFD_MSG_ERR("Failed to create ion client\n");
rc = -ENODEV;
@@ -1461,6 +1516,7 @@
return -ENODEV;
}
+ wfd_stats_teardown();
for (c = 0; c < WFD_NUM_DEVICES; ++c) {
v4l2_device_unregister_subdev(&wfd_dev[c].vsg_sdev);
v4l2_device_unregister_subdev(&wfd_dev[c].enc_sdev);
diff --git a/drivers/media/video/msm/wfd/wfd-util.c b/drivers/media/video/msm/wfd/wfd-util.c
new file mode 100644
index 0000000..233668b0
--- /dev/null
+++ b/drivers/media/video/msm/wfd/wfd-util.c
@@ -0,0 +1,217 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/hrtimer.h>
+#include <linux/limits.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include "wfd-util.h"
+
+static struct dentry *wfd_debugfs_root;
+
+int wfd_stats_setup()
+{
+ wfd_debugfs_root = debugfs_create_dir("wfd", NULL);
+
+ if (wfd_debugfs_root == ERR_PTR(-ENODEV))
+ return -ENODEV;
+ else if (!wfd_debugfs_root)
+ return -ENOMEM;
+ else
+ return 0;
+}
+
+void wfd_stats_teardown()
+{
+ if (wfd_debugfs_root)
+ debugfs_remove_recursive(wfd_debugfs_root);
+}
+
+int wfd_stats_init(struct wfd_stats *stats, int device)
+{
+ char device_str[NAME_MAX] = "";
+ int rc = 0;
+
+ if (!stats) {
+ rc = -EINVAL;
+ goto wfd_stats_init_fail;
+ } else if (!wfd_debugfs_root) {
+ WFD_MSG_ERR("wfd debugfs root does not exist\n");
+ rc = -ENOENT;
+ goto wfd_stats_init_fail;
+ }
+
+ memset(stats, 0, sizeof(*stats));
+ INIT_LIST_HEAD(&stats->enc_queue);
+
+ snprintf(device_str, sizeof(device_str), "%d", device);
+ stats->d_parent = debugfs_create_dir(device_str, wfd_debugfs_root);
+ if (IS_ERR(stats->d_parent)) {
+ rc = PTR_ERR(stats->d_parent);
+ stats->d_parent = NULL;
+ goto wfd_stats_init_fail;
+ }
+
+ stats->d_v4l2_buf_count = debugfs_create_u32("v4l2_buf_count", S_IRUGO,
+ stats->d_parent, &stats->v4l2_buf_count);
+ if (IS_ERR(stats->d_v4l2_buf_count)) {
+ rc = PTR_ERR(stats->d_v4l2_buf_count);
+ stats->d_v4l2_buf_count = NULL;
+ goto wfd_stats_init_fail;
+ }
+
+ stats->d_mdp_buf_count = debugfs_create_u32("mdp_buf_count", S_IRUGO,
+ stats->d_parent, &stats->mdp_buf_count);
+ if (IS_ERR(stats->d_mdp_buf_count)) {
+ rc = PTR_ERR(stats->d_mdp_buf_count);
+ stats->d_mdp_buf_count = NULL;
+ goto wfd_stats_init_fail;
+ }
+
+ stats->d_vsg_buf_count = debugfs_create_u32("vsg_buf_count", S_IRUGO,
+ stats->d_parent, &stats->vsg_buf_count);
+ if (IS_ERR(stats->d_vsg_buf_count)) {
+ rc = PTR_ERR(stats->d_vsg_buf_count);
+ stats->d_vsg_buf_count = NULL;
+ goto wfd_stats_init_fail;
+ }
+
+ stats->d_enc_buf_count = debugfs_create_u32("enc_buf_count", S_IRUGO,
+ stats->d_parent, &stats->enc_buf_count);
+ if (IS_ERR(stats->d_enc_buf_count)) {
+ rc = PTR_ERR(stats->d_enc_buf_count);
+ stats->d_enc_buf_count = NULL;
+ goto wfd_stats_init_fail;
+ }
+
+ stats->d_frames_encoded = debugfs_create_u32("frames_encoded", S_IRUGO,
+ stats->d_parent, &stats->frames_encoded);
+ if (IS_ERR(stats->d_frames_encoded)) {
+ rc = PTR_ERR(stats->d_frames_encoded);
+ stats->d_frames_encoded = NULL;
+ goto wfd_stats_init_fail;
+ }
+
+ stats->d_mdp_updates = debugfs_create_u32("mdp_updates", S_IRUGO,
+ stats->d_parent, &stats->mdp_updates);
+ if (IS_ERR(stats->d_mdp_updates)) {
+ rc = PTR_ERR(stats->d_mdp_updates);
+ stats->d_mdp_updates = NULL;
+ goto wfd_stats_init_fail;
+ }
+
+ stats->d_enc_avg_latency = debugfs_create_u32("enc_avg_latency",
+ S_IRUGO, stats->d_parent, &stats->enc_avg_latency);
+ if (IS_ERR(stats->d_enc_avg_latency)) {
+ rc = PTR_ERR(stats->d_enc_avg_latency);
+ stats->d_enc_avg_latency = NULL;
+ goto wfd_stats_init_fail;
+ }
+
+ return rc;
+wfd_stats_init_fail:
+ return rc;
+}
+
+int wfd_stats_update(struct wfd_stats *stats, enum wfd_stats_event event)
+{
+ int rc = 0;
+ switch (event) {
+ case WFD_STAT_EVENT_CLIENT_QUEUE:
+ stats->v4l2_buf_count++;
+ break;
+ case WFD_STAT_EVENT_CLIENT_DEQUEUE: {
+ struct wfd_stats_encode_sample *sample = NULL;
+
+ stats->v4l2_buf_count--;
+
+ if (!list_empty(&stats->enc_queue))
+ sample = list_first_entry(&stats->enc_queue,
+ struct wfd_stats_encode_sample,
+ list);
+ if (sample) {
+ ktime_t kdiff = ktime_sub(ktime_get(),
+ sample->encode_start_ts);
+ uint32_t diff = ktime_to_ms(kdiff);
+
+ stats->enc_cumulative_latency += diff;
+ stats->enc_latency_samples++;
+ stats->enc_avg_latency = stats->enc_cumulative_latency /
+ stats->enc_latency_samples;
+
+ list_del(&sample->list);
+ kfree(sample);
+ sample = NULL;
+ }
+ break;
+ }
+ case WFD_STAT_EVENT_MDP_QUEUE:
+ stats->mdp_buf_count++;
+ stats->mdp_updates++;
+ break;
+ case WFD_STAT_EVENT_MDP_DEQUEUE:
+ stats->mdp_buf_count--;
+ break;
+ case WFD_STAT_EVENT_ENC_QUEUE: {
+ struct wfd_stats_encode_sample *sample = NULL;
+
+ stats->enc_buf_count++;
+ stats->frames_encoded++;
+
+ sample = kzalloc(sizeof(*sample), GFP_KERNEL);
+ if (sample) {
+ INIT_LIST_HEAD(&sample->list);
+ sample->encode_start_ts = ktime_get();
+ list_add_tail(&sample->list, &stats->enc_queue);
+ } else {
+ WFD_MSG_WARN("Unable to measure latency\n");
+ }
+ break;
+ }
+ case WFD_STAT_EVENT_ENC_DEQUEUE:
+ stats->enc_buf_count--;
+ break;
+ case WFD_STAT_EVENT_VSG_QUEUE:
+ stats->vsg_buf_count++;
+ break;
+ case WFD_STAT_EVENT_VSG_DEQUEUE:
+ stats->vsg_buf_count--;
+ break;
+ default:
+ rc = -ENOTSUPP;
+ }
+
+ return rc;
+}
+
+int wfd_stats_deinit(struct wfd_stats *stats)
+{
+ WFD_MSG_ERR("Latencies: avg enc. latency %d",
+ stats->enc_avg_latency);
+ /* Delete all debugfs files in one shot :) */
+ if (stats->d_parent)
+ debugfs_remove_recursive(stats->d_parent);
+
+ stats->d_parent =
+ stats->d_v4l2_buf_count =
+ stats->d_mdp_buf_count =
+ stats->d_vsg_buf_count =
+ stats->d_enc_buf_count =
+ stats->d_frames_encoded =
+ stats->d_mdp_updates =
+ stats->d_enc_avg_latency = NULL;
+
+ return 0;
+}
diff --git a/drivers/media/video/msm/wfd/wfd-util.h b/drivers/media/video/msm/wfd/wfd-util.h
index 06dbffa..b6bb245 100644
--- a/drivers/media/video/msm/wfd/wfd-util.h
+++ b/drivers/media/video/msm/wfd/wfd-util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -11,6 +11,10 @@
*
*/
+#include <linux/debugfs.h>
+#include <linux/list.h>
+#include <linux/ktime.h>
+
#ifndef _WFD_UTIL_H_
#define _WFD_UTIL_H_
@@ -27,4 +31,59 @@
#define WFD_MSG_ERR(fmt...) pr_err(KERN_ERR WFD_TAG fmt)
#define WFD_MSG_CRIT(fmt...) pr_crit(KERN_CRIT WFD_TAG fmt)
#define WFD_MSG_DBG(fmt...) pr_debug(WFD_TAG fmt)
+
+
+struct wfd_stats_encode_sample {
+ ktime_t encode_start_ts;
+ struct list_head list;
+};
+
+struct wfd_stats {
+ /* Output Buffers */
+ uint32_t v4l2_buf_count;
+
+ /* Input Buffers */
+ uint32_t mdp_buf_count;
+ uint32_t vsg_buf_count;
+ uint32_t enc_buf_count;
+
+ /* Other */
+ uint32_t frames_encoded;
+ uint32_t mdp_updates;
+
+ uint32_t enc_avg_latency;
+ uint32_t enc_cumulative_latency;
+ uint32_t enc_latency_samples;
+ struct list_head enc_queue;
+
+ /* Debugfs entries */
+ struct dentry *d_parent;
+ struct dentry *d_v4l2_buf_count;
+ struct dentry *d_mdp_buf_count;
+ struct dentry *d_vsg_buf_count;
+ struct dentry *d_enc_buf_count;
+ struct dentry *d_frames_encoded;
+ struct dentry *d_mdp_updates;
+ struct dentry *d_enc_avg_latency;
+};
+
+enum wfd_stats_event {
+ WFD_STAT_EVENT_CLIENT_QUEUE,
+ WFD_STAT_EVENT_CLIENT_DEQUEUE,
+
+ WFD_STAT_EVENT_MDP_QUEUE,
+ WFD_STAT_EVENT_MDP_DEQUEUE,
+
+ WFD_STAT_EVENT_VSG_QUEUE,
+ WFD_STAT_EVENT_VSG_DEQUEUE,
+
+ WFD_STAT_EVENT_ENC_QUEUE,
+ WFD_STAT_EVENT_ENC_DEQUEUE,
+};
+
+int wfd_stats_setup(void);
+int wfd_stats_init(struct wfd_stats *, int device);
+int wfd_stats_update(struct wfd_stats *, enum wfd_stats_event);
+int wfd_stats_deinit(struct wfd_stats *);
+void wfd_stats_teardown(void);
#endif
diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c
index 217f18d..0fe8f2a 100644
--- a/drivers/platform/msm/sps/sps.c
+++ b/drivers/platform/msm/sps/sps.c
@@ -1352,6 +1352,32 @@
EXPORT_SYMBOL(sps_free_mem);
/**
+ * Get the number of unused descriptors in the descriptor FIFO
+ * of a pipe
+ *
+ */
+int sps_get_unused_desc_num(struct sps_pipe *h, u32 *desc_num)
+{
+ struct sps_pipe *pipe = h;
+ struct sps_bam *bam;
+ int result;
+
+ SPS_DBG("sps:%s.", __func__);
+
+ bam = sps_bam_lock(pipe);
+ if (bam == NULL)
+ return SPS_ERROR;
+
+ result = sps_bam_pipe_get_unused_desc_num(bam, pipe->pipe_index,
+ desc_num);
+
+ sps_bam_unlock(bam);
+
+ return result;
+}
+EXPORT_SYMBOL(sps_get_unused_desc_num);
+
+/**
* Register a BAM device
*
*/
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index da1de86..6c8b1f9 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -1960,3 +1960,29 @@
return result;
}
+/**
+ * Get the number of unused descriptors in the descriptor FIFO
+ * of a pipe
+ */
+int sps_bam_pipe_get_unused_desc_num(struct sps_bam *dev, u32 pipe_index,
+ u32 *desc_num)
+{
+ u32 sw_offset, peer_offset, fifo_size;
+ u32 desc_size = sizeof(struct sps_iovec);
+ struct sps_pipe *pipe = dev->pipes[pipe_index];
+
+ if (pipe == NULL)
+ return SPS_ERROR;
+
+ fifo_size = pipe->desc_size;
+
+ sw_offset = bam_pipe_get_desc_read_offset(dev->base, pipe_index);
+ peer_offset = bam_pipe_get_desc_write_offset(dev->base, pipe_index);
+
+ if (sw_offset <= peer_offset)
+ *desc_num = (peer_offset - sw_offset) / desc_size;
+ else
+ *desc_num = (peer_offset + fifo_size - sw_offset) / desc_size;
+
+ return 0;
+}
diff --git a/drivers/platform/msm/sps/sps_bam.h b/drivers/platform/msm/sps/sps_bam.h
index 70e7898..6004b75 100644
--- a/drivers/platform/msm/sps/sps_bam.h
+++ b/drivers/platform/msm/sps/sps_bam.h
@@ -545,4 +545,20 @@
int sps_bam_pipe_timer_ctrl(struct sps_bam *dev, u32 pipe_index,
struct sps_timer_ctrl *timer_ctrl,
struct sps_timer_result *timer_result);
+
+
+/**
+ * Get the number of unused descriptors in the descriptor FIFO
+ * of a pipe
+ *
+ * @dev - pointer to BAM device descriptor
+ *
+ * @pipe_index - pipe index
+ *
+ * @desc_num - number of unused descriptors
+ *
+ */
+int sps_bam_pipe_get_unused_desc_num(struct sps_bam *dev, u32 pipe_index,
+ u32 *desc_num);
+
#endif /* _SPSBAM_H_ */
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 80f50de..0e121d1 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -440,7 +440,6 @@
int ret;
struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
- wake_lock(&msm_uport->dma_wake_lock);
/* Set up the MREG/NREG/DREG/MNDREG */
ret = clk_set_rate(msm_uport->clk, uport->uartclk);
if (ret) {
@@ -456,6 +455,7 @@
if (msm_uport->pclk) {
ret = clk_enable(msm_uport->pclk);
if (ret) {
+ clk_disable(msm_uport->clk);
dev_err(uport->dev,
"Error could not turn on UART pclk\n");
return ret;
@@ -1578,10 +1578,14 @@
tx->dma_base = dma_map_single(uport->dev, tx_buf->buf, UART_XMIT_SIZE,
DMA_TO_DEVICE);
+ wake_lock(&msm_uport->dma_wake_lock);
/* turn on uart clk */
ret = msm_hs_init_clk(uport);
- if (unlikely(ret))
+ if (unlikely(ret)) {
+ pr_err("Turning ON uartclk error\n");
+ wake_unlock(&msm_uport->dma_wake_lock);
return ret;
+ }
/* Set auto RFR Level */
data = msm_hs_read(uport, UARTDM_MR1_ADDR);
@@ -1646,20 +1650,26 @@
if (use_low_power_wakeup(msm_uport)) {
ret = irq_set_irq_wake(msm_uport->wakeup.irq, 1);
- if (unlikely(ret))
- return ret;
+ if (unlikely(ret)) {
+ pr_err("%s():Err setting wakeup irq\n", __func__);
+ goto deinit_uart_clk;
+ }
}
ret = request_irq(uport->irq, msm_hs_isr, IRQF_TRIGGER_HIGH,
"msm_hs_uart", msm_uport);
- if (unlikely(ret))
- return ret;
+ if (unlikely(ret)) {
+ pr_err("%s():Error getting uart irq\n", __func__);
+ goto free_wake_irq;
+ }
if (use_low_power_wakeup(msm_uport)) {
ret = request_irq(msm_uport->wakeup.irq, msm_hs_wakeup_isr,
IRQF_TRIGGER_FALLING,
"msm_hs_wakeup", msm_uport);
- if (unlikely(ret))
- return ret;
+ if (unlikely(ret)) {
+ pr_err("%s():Err getting uart wakeup_irq\n", __func__);
+ goto free_uart_irq;
+ }
disable_irq(msm_uport->wakeup.irq);
}
@@ -1673,8 +1683,19 @@
dev_err(uport->dev, "set active error:%d\n", ret);
pm_runtime_enable(uport->dev);
-
return 0;
+
+free_uart_irq:
+ free_irq(uport->irq, msm_uport);
+free_wake_irq:
+ irq_set_irq_wake(msm_uport->wakeup.irq, 0);
+deinit_uart_clk:
+ clk_disable(msm_uport->clk);
+ if (msm_uport->pclk)
+ clk_disable(msm_uport->pclk);
+ wake_unlock(&msm_uport->dma_wake_lock);
+
+ return ret;
}
/* Initialize tx and rx data structures */
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 3e5c6f1..3fb9c83 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -70,6 +70,8 @@
#include "f_rndis.c"
#include "rndis.c"
#include "u_ether.c"
+#include "u_bam_data.c"
+#include "f_mbim.c"
MODULE_AUTHOR("Mike Lockwood");
MODULE_DESCRIPTION("Android Composite USB Driver");
@@ -386,6 +388,35 @@
.attributes = rmnet_function_attributes,
};
+
+/* MBIM - used with BAM */
+#define MAX_MBIM_INSTANCES 1
+
+static int mbim_function_init(struct android_usb_function *f,
+ struct usb_composite_dev *cdev)
+{
+ return mbim_init(MAX_MBIM_INSTANCES);
+}
+
+static void mbim_function_cleanup(struct android_usb_function *f)
+{
+ fmbim_cleanup();
+}
+
+static int mbim_function_bind_config(struct android_usb_function *f,
+ struct usb_configuration *c)
+{
+ return mbim_bind_config(c, 0);
+}
+
+static struct android_usb_function mbim_function = {
+ .name = "usb_mbim",
+ .cleanup = mbim_function_cleanup,
+ .bind_config = mbim_function_bind_config,
+ .init = mbim_function_init,
+};
+
+
/* DIAG */
static char diag_clients[32]; /*enabled DIAG clients- "diag[,diag_mdm]" */
static ssize_t clients_store(
@@ -1004,6 +1035,7 @@
static struct android_usb_function *supported_functions[] = {
+ &mbim_function,
&rmnet_smd_function,
&rmnet_sdio_function,
&rmnet_smd_sdio_function,
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index 9cbfad8..8e0bef0 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2710,6 +2710,12 @@
return 0;
}
+static int is_sps_req(struct ci13xxx_req *mReq)
+{
+ return (CI13XX_REQ_VENDOR_ID(mReq->req.udc_priv) == MSM_VENDOR_ID &&
+ mReq->req.udc_priv & MSM_SPS_MODE);
+}
+
/**
* ep_set_halt: sets the endpoint halt feature
*
@@ -2731,7 +2737,9 @@
#ifndef STALL_IN
/* g_file_storage MS compliant but g_zero fails chapter 9 compliance */
if (value && mEp->type == USB_ENDPOINT_XFER_BULK && mEp->dir == TX &&
- !list_empty(&mEp->qh.queue)) {
+ !list_empty(&mEp->qh.queue) &&
+ !is_sps_req(list_entry(mEp->qh.queue.next, struct ci13xxx_req,
+ queue))){
spin_unlock_irqrestore(mEp->lock, flags);
return -EAGAIN;
}
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
new file mode 100644
index 0000000..8288496
--- /dev/null
+++ b/drivers/usb/gadget/f_mbim.c
@@ -0,0 +1,1772 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+
+#include <linux/usb/cdc.h>
+
+#include <linux/usb/composite.h>
+#include <linux/usb/android_composite.h>
+#include <linux/platform_device.h>
+
+#include <linux/spinlock.h>
+
+/*
+ * This function is a "Mobile Broadband Interface Model" (MBIM) link.
+ * MBIM is intended to be used with high-speed network attachments.
+ *
+ * Note that MBIM requires the use of "alternate settings" for its data
+ * interface. This means that the set_alt() method has real work to do,
+ * and also means that a get_alt() method is required.
+ */
+
+#define MBIM_BULK_BUFFER_SIZE 4096
+
+#define MBIM_IOCTL_MAGIC 'o'
+#define MBIM_GET_NTB_SIZE _IOR(MBIM_IOCTL_MAGIC, 2, u32)
+#define MBIM_GET_DATAGRAM_COUNT _IOR(MBIM_IOCTL_MAGIC, 3, u16)
+
+#define NR_MBIM_PORTS 1
+
+struct ctrl_pkt {
+ void *buf;
+ int len;
+ struct list_head list;
+};
+
+struct mbim_ep_descs {
+ struct usb_endpoint_descriptor *in;
+ struct usb_endpoint_descriptor *out;
+ struct usb_endpoint_descriptor *notify;
+};
+
+struct mbim_notify_port {
+ struct usb_ep *notify;
+ struct usb_request *notify_req;
+ u8 notify_state;
+ atomic_t notify_count;
+};
+
+enum mbim_notify_state {
+ NCM_NOTIFY_NONE,
+ NCM_NOTIFY_CONNECT,
+ NCM_NOTIFY_SPEED,
+};
+
+struct f_mbim {
+ struct usb_function function;
+ struct usb_composite_dev *cdev;
+
+ atomic_t online;
+ bool is_open;
+
+ atomic_t open_excl;
+ atomic_t ioctl_excl;
+ atomic_t read_excl;
+ atomic_t write_excl;
+
+ wait_queue_head_t read_wq;
+ wait_queue_head_t write_wq;
+
+ u8 port_num;
+ struct data_port bam_port;
+ struct mbim_notify_port not_port;
+
+ struct mbim_ep_descs fs;
+ struct mbim_ep_descs hs;
+
+ u8 ctrl_id, data_id;
+
+ struct ndp_parser_opts *parser_opts;
+
+ spinlock_t lock;
+
+ struct list_head cpkt_req_q;
+ struct list_head cpkt_resp_q;
+
+ u32 ntb_input_size;
+ u16 ntb_max_datagrams;
+
+ pid_t user_pid;
+
+ atomic_t error;
+};
+
+struct mbim_ntb_input_size {
+ u32 ntb_input_size;
+ u16 ntb_max_datagrams;
+ u16 reserved;
+};
+
+/* temporary variable used between mbim_open() and mbim_gadget_bind() */
+static struct f_mbim *_mbim_dev;
+
+static unsigned int nr_mbim_ports;
+
+static struct mbim_ports {
+ struct f_mbim *port;
+ unsigned port_num;
+} mbim_ports[NR_MBIM_PORTS];
+
+static inline struct f_mbim *func_to_mbim(struct usb_function *f)
+{
+ return container_of(f, struct f_mbim, function);
+}
+
+/* peak (theoretical) bulk transfer rate in bits-per-second */
+static inline unsigned mbim_bitrate(struct usb_gadget *g)
+{
+ if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+ return 13 * 512 * 8 * 1000 * 8;
+ else
+ return 19 * 64 * 1 * 1000 * 8;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define NTB_DEFAULT_IN_SIZE (0x4000)
+#define NTB_OUT_SIZE (0x1000)
+#define NDP_IN_DIVISOR (0x4)
+
+#define FORMATS_SUPPORTED USB_CDC_NCM_NTB16_SUPPORTED
+
+static struct usb_cdc_ncm_ntb_parameters ntb_parameters = {
+ .wLength = sizeof ntb_parameters,
+ .bmNtbFormatsSupported = cpu_to_le16(FORMATS_SUPPORTED),
+ .dwNtbInMaxSize = cpu_to_le32(NTB_DEFAULT_IN_SIZE),
+ .wNdpInDivisor = cpu_to_le16(NDP_IN_DIVISOR),
+ .wNdpInPayloadRemainder = cpu_to_le16(0),
+ .wNdpInAlignment = cpu_to_le16(4),
+
+ .dwNtbOutMaxSize = cpu_to_le32(NTB_OUT_SIZE),
+ .wNdpOutDivisor = cpu_to_le16(4),
+ .wNdpOutPayloadRemainder = cpu_to_le16(0),
+ .wNdpOutAlignment = cpu_to_le16(4),
+ .wNtbOutMaxDatagrams = cpu_to_le16(4),
+};
+
+/*
+ * Use wMaxPacketSize big enough to fit CDC_NOTIFY_SPEED_CHANGE in one
+ * packet, to simplify cancellation; and a big transfer interval, to
+ * waste less bandwidth.
+ */
+
+#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
+#define NCM_STATUS_BYTECOUNT 16 /* 8 byte header + data */
+
+static struct usb_interface_assoc_descriptor mbim_iad_desc = {
+ .bLength = sizeof mbim_iad_desc,
+ .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
+
+ /* .bFirstInterface = DYNAMIC, */
+ .bInterfaceCount = 2, /* control + data */
+ .bFunctionClass = 2,
+ .bFunctionSubClass = 0x0e,
+ .bFunctionProtocol = 0,
+ /* .iFunction = DYNAMIC */
+};
+
+/* interface descriptor: */
+static struct usb_interface_descriptor mbim_control_intf = {
+ .bLength = sizeof mbim_control_intf,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ /* .bInterfaceNumber = DYNAMIC */
+ .bNumEndpoints = 1,
+ .bInterfaceClass = 0x02,
+ .bInterfaceSubClass = 0x0e,
+ .bInterfaceProtocol = 0,
+ /* .iInterface = DYNAMIC */
+};
+
+static struct usb_cdc_header_desc mbim_header_desc = {
+ .bLength = sizeof mbim_header_desc,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_HEADER_TYPE,
+
+ .bcdCDC = cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_union_desc mbim_union_desc = {
+ .bLength = sizeof(mbim_union_desc),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_UNION_TYPE,
+ /* .bMasterInterface0 = DYNAMIC */
+ /* .bSlaveInterface0 = DYNAMIC */
+};
+
+static struct usb_cdc_mbb_desc mbb_desc = {
+ .bLength = sizeof mbb_desc,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_MBB_TYPE,
+
+ .bcdMbbVersion = cpu_to_le16(0x0100),
+
+ .wMaxControlMessage = cpu_to_le16(0x1000),
+ .bNumberFilters = 0x10,
+ .bMaxFilterSize = 0x80,
+ .wMaxSegmentSize = cpu_to_le16(0x1000),
+ .bmNetworkCapabilities = 0x20,
+};
+
+/* the default data interface has no endpoints ... */
+static struct usb_interface_descriptor mbim_data_nop_intf = {
+ .bLength = sizeof mbim_data_nop_intf,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ /* .bInterfaceNumber = DYNAMIC */
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = 0x0a,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0x02,
+ /* .iInterface = DYNAMIC */
+};
+
+/* ... but the "real" data interface has two bulk endpoints */
+static struct usb_interface_descriptor mbim_data_intf = {
+ .bLength = sizeof mbim_data_intf,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ /* .bInterfaceNumber = DYNAMIC */
+ .bAlternateSetting = 1,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = 0x0a,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0x02,
+ /* .iInterface = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor fs_mbim_notify_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 4*cpu_to_le16(NCM_STATUS_BYTECOUNT),
+ .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC,
+};
+
+static struct usb_endpoint_descriptor fs_mbim_in_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor fs_mbim_out_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *mbim_fs_function[] = {
+ (struct usb_descriptor_header *) &mbim_iad_desc,
+ /* MBIM control descriptors */
+ (struct usb_descriptor_header *) &mbim_control_intf,
+ (struct usb_descriptor_header *) &mbim_header_desc,
+ (struct usb_descriptor_header *) &mbb_desc,
+ (struct usb_descriptor_header *) &fs_mbim_notify_desc,
+ /* data interface, altsettings 0 and 1 */
+ (struct usb_descriptor_header *) &mbim_data_nop_intf,
+ (struct usb_descriptor_header *) &mbim_data_intf,
+ (struct usb_descriptor_header *) &fs_mbim_in_desc,
+ (struct usb_descriptor_header *) &fs_mbim_out_desc,
+ NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor hs_mbim_notify_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = 4*cpu_to_le16(NCM_STATUS_BYTECOUNT),
+ .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
+};
+static struct usb_endpoint_descriptor hs_mbim_in_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_mbim_out_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *mbim_hs_function[] = {
+ (struct usb_descriptor_header *) &mbim_iad_desc,
+ /* MBIM control descriptors */
+ (struct usb_descriptor_header *) &mbim_control_intf,
+ (struct usb_descriptor_header *) &mbim_header_desc,
+ (struct usb_descriptor_header *) &mbb_desc,
+ (struct usb_descriptor_header *) &hs_mbim_notify_desc,
+ /* data interface, altsettings 0 and 1 */
+ (struct usb_descriptor_header *) &mbim_data_nop_intf,
+ (struct usb_descriptor_header *) &mbim_data_intf,
+ (struct usb_descriptor_header *) &hs_mbim_in_desc,
+ (struct usb_descriptor_header *) &hs_mbim_out_desc,
+ NULL,
+};
+
+/* string descriptors: */
+
+#define STRING_CTRL_IDX 0
+#define STRING_DATA_IDX 1
+
+static struct usb_string mbim_string_defs[] = {
+ [STRING_CTRL_IDX].s = "MBIM Control",
+ [STRING_DATA_IDX].s = "MBIM Data",
+ { } /* end of list */
+};
+
+static struct usb_gadget_strings mbim_string_table = {
+ .language = 0x0409, /* en-us */
+ .strings = mbim_string_defs,
+};
+
+static struct usb_gadget_strings *mbim_strings[] = {
+ &mbim_string_table,
+ NULL,
+};
+
+/*
+ * Here are options for the Datagram Pointer table (NDP) parser.
+ * There are 2 different formats: NDP16 and NDP32 in the spec (ch. 3),
+ * in NDP16 offsets and sizes fields are 1 16bit word wide,
+ * in NDP32 -- 2 16bit words wide. Also signatures are different.
+ * To make the parser code the same, put the differences in the structure,
+ * and switch pointers to the structures when the format is changed.
+ */
+
+struct ndp_parser_opts {
+ u32 nth_sign;
+ u32 ndp_sign;
+ unsigned nth_size;
+ unsigned ndp_size;
+ unsigned ndplen_align;
+ /* sizes in u16 units */
+ unsigned dgram_item_len; /* index or length */
+ unsigned block_length;
+ unsigned fp_index;
+ unsigned reserved1;
+ unsigned reserved2;
+ unsigned next_fp_index;
+};
+
+#define INIT_NDP16_OPTS { \
+ .nth_sign = USB_CDC_NCM_NTH16_SIGN, \
+ .ndp_sign = USB_CDC_NCM_NDP16_NOCRC_SIGN, \
+ .nth_size = sizeof(struct usb_cdc_ncm_nth16), \
+ .ndp_size = sizeof(struct usb_cdc_ncm_ndp16), \
+ .ndplen_align = 4, \
+ .dgram_item_len = 1, \
+ .block_length = 1, \
+ .fp_index = 1, \
+ .reserved1 = 0, \
+ .reserved2 = 0, \
+ .next_fp_index = 1, \
+}
+
+#define INIT_NDP32_OPTS { \
+ .nth_sign = USB_CDC_NCM_NTH32_SIGN, \
+ .ndp_sign = USB_CDC_NCM_NDP32_NOCRC_SIGN, \
+ .nth_size = sizeof(struct usb_cdc_ncm_nth32), \
+ .ndp_size = sizeof(struct usb_cdc_ncm_ndp32), \
+ .ndplen_align = 8, \
+ .dgram_item_len = 2, \
+ .block_length = 2, \
+ .fp_index = 2, \
+ .reserved1 = 1, \
+ .reserved2 = 2, \
+ .next_fp_index = 2, \
+}
+
+static struct ndp_parser_opts ndp16_opts = INIT_NDP16_OPTS;
+static struct ndp_parser_opts ndp32_opts = INIT_NDP32_OPTS;
+
+static inline int mbim_lock(atomic_t *excl)
+{
+ if (atomic_inc_return(excl) == 1) {
+ return 0;
+ } else {
+ atomic_dec(excl);
+ return -EBUSY;
+ }
+}
+
+static inline void mbim_unlock(atomic_t *excl)
+{
+ atomic_dec(excl);
+}
+
+static struct ctrl_pkt *mbim_alloc_ctrl_pkt(unsigned len, gfp_t flags)
+{
+ struct ctrl_pkt *pkt;
+
+ pkt = kzalloc(sizeof(struct ctrl_pkt), flags);
+ if (!pkt)
+ return ERR_PTR(-ENOMEM);
+
+ pkt->buf = kmalloc(len, flags);
+ if (!pkt->buf) {
+ kfree(pkt);
+ return ERR_PTR(-ENOMEM);
+ }
+ pkt->len = len;
+
+ return pkt;
+}
+
+static void mbim_free_ctrl_pkt(struct ctrl_pkt *pkt)
+{
+ if (pkt) {
+ kfree(pkt->buf);
+ kfree(pkt);
+ }
+}
+
+static struct usb_request *mbim_alloc_req(struct usb_ep *ep, int buffer_size)
+{
+ struct usb_request *req = usb_ep_alloc_request(ep, GFP_KERNEL);
+ if (!req)
+ return NULL;
+
+ req->buf = kmalloc(buffer_size, GFP_KERNEL);
+ if (!req->buf) {
+ usb_ep_free_request(ep, req);
+ return NULL;
+ }
+ req->length = buffer_size;
+ return req;
+}
+
+void fmbim_free_req(struct usb_ep *ep, struct usb_request *req)
+{
+ if (req) {
+ kfree(req->buf);
+ usb_ep_free_request(ep, req);
+ }
+}
+
+static void fmbim_ctrl_response_available(struct f_mbim *dev)
+{
+ struct usb_request *req = dev->not_port.notify_req;
+ struct usb_cdc_notification *event = NULL;
+ unsigned long flags;
+ int ret;
+
+ int notif_c = 0;
+
+ pr_info("dev:%p portno#%d\n", dev, dev->port_num);
+
+ spin_lock_irqsave(&dev->lock, flags);
+
+ if (!atomic_read(&dev->online)) {
+ pr_info("dev:%p is not online\n", dev);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ return;
+ }
+
+ if (!req) {
+ pr_info("dev:%p req is NULL\n", dev);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ return;
+ }
+
+ if (!req->buf) {
+ pr_info("dev:%p req->buf is NULL\n", dev);
+ spin_unlock_irqrestore(&dev->lock, flags);
+ return;
+ }
+
+ notif_c = atomic_inc_return(&dev->not_port.notify_count);
+ pr_info("atomic_inc_return[notif_c] = %d", notif_c);
+
+ event = req->buf;
+ event->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
+ | USB_RECIP_INTERFACE;
+ event->bNotificationType = USB_CDC_NOTIFY_RESPONSE_AVAILABLE;
+ event->wValue = cpu_to_le16(0);
+ event->wIndex = cpu_to_le16(dev->ctrl_id);
+ event->wLength = cpu_to_le16(0);
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ pr_info("Call usb_ep_queue");
+
+ ret = usb_ep_queue(dev->not_port.notify,
+ dev->not_port.notify_req, GFP_ATOMIC);
+ if (ret) {
+ atomic_dec(&dev->not_port.notify_count);
+ pr_err("ep enqueue error %d\n", ret);
+ }
+
+ pr_info("Succcessfull Exit");
+}
+
+static int
+fmbim_send_cpkt_response(struct f_mbim *gr, struct ctrl_pkt *cpkt)
+{
+ struct f_mbim *dev = gr;
+ unsigned long flags;
+
+ if (!gr || !cpkt) {
+ pr_err("Invalid cpkt, dev:%p cpkt:%p\n",
+ gr, cpkt);
+ return -ENODEV;
+ }
+
+ pr_info("dev:%p port_num#%d\n", dev, dev->port_num);
+
+ if (!atomic_read(&dev->online)) {
+ pr_info("dev:%p is not connected\n", dev);
+ mbim_free_ctrl_pkt(cpkt);
+ return 0;
+ }
+
+ spin_lock_irqsave(&dev->lock, flags);
+ list_add(&cpkt->list, &dev->cpkt_resp_q);
+ spin_unlock_irqrestore(&dev->lock, flags);
+
+ fmbim_ctrl_response_available(dev);
+
+ return 0;
+}
+
+/* ---------------------------- BAM INTERFACE ----------------------------- */
+
+static int mbim_bam_setup(int no_ports)
+{
+ int ret;
+
+ pr_info("no_ports:%d\n", no_ports);
+
+ ret = bam_data_setup(no_ports);
+ if (ret) {
+ pr_err("bam_data_setup failed err: %d\n", ret);
+ return ret;
+ }
+
+ pr_info("Initialized %d ports\n", no_ports);
+ return 0;
+}
+
+static int mbim_bam_connect(struct f_mbim *dev)
+{
+ int ret;
+
+ pr_info("dev:%p portno:%d\n", dev, dev->port_num);
+
+ ret = bam_data_connect(&dev->bam_port, dev->port_num, dev->port_num);
+ if (ret) {
+ pr_err("bam_data_setup failed: err:%d\n",
+ ret);
+ return ret;
+ } else {
+ pr_info("mbim bam connected\n");
+ }
+
+ return 0;
+}
+
+static int mbim_bam_disconnect(struct f_mbim *dev)
+{
+ pr_info("dev:%p port:%d. Do nothing.\n",
+ dev, dev->port_num);
+
+ /* bam_data_disconnect(&dev->bam_port, dev->port_num); */
+
+ return 0;
+}
+
+/* -------------------------------------------------------------------------*/
+
+static inline void mbim_reset_values(struct f_mbim *mbim)
+{
+ mbim->parser_opts = &ndp16_opts;
+
+ mbim->ntb_input_size = NTB_DEFAULT_IN_SIZE;
+
+ atomic_set(&mbim->not_port.notify_count, 0);
+ atomic_set(&mbim->online, 0);
+}
+
+/*
+ * Context: mbim->lock held
+ */
+static void mbim_do_notify(struct f_mbim *mbim)
+{
+ struct usb_request *req = mbim->not_port.notify_req;
+ struct usb_cdc_notification *event;
+ struct usb_composite_dev *cdev = mbim->cdev;
+ __le32 *data;
+ int status;
+
+ pr_info("notify_state: %d", mbim->not_port.notify_state);
+
+ if (!req)
+ return;
+
+ event = req->buf;
+
+ switch (mbim->not_port.notify_state) {
+
+ case NCM_NOTIFY_NONE:
+ return;
+
+ case NCM_NOTIFY_CONNECT:
+ event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
+ if (mbim->is_open)
+ event->wValue = cpu_to_le16(1);
+ else
+ event->wValue = cpu_to_le16(0);
+ event->wLength = 0;
+ req->length = sizeof *event;
+
+ pr_info("notify connect %s\n",
+ mbim->is_open ? "true" : "false");
+ mbim->not_port.notify_state = NCM_NOTIFY_NONE;
+ break;
+
+ case NCM_NOTIFY_SPEED:
+ event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
+ event->wValue = cpu_to_le16(0);
+ event->wLength = cpu_to_le16(8);
+ req->length = NCM_STATUS_BYTECOUNT;
+
+ /* SPEED_CHANGE data is up/down speeds in bits/sec */
+ data = req->buf + sizeof *event;
+ data[0] = cpu_to_le32(mbim_bitrate(cdev->gadget));
+ data[1] = data[0];
+
+ pr_info("notify speed %d\n",
+ mbim_bitrate(cdev->gadget));
+ mbim->not_port.notify_state = NCM_NOTIFY_CONNECT;
+ break;
+ }
+ event->bmRequestType = 0xA1;
+ event->wIndex = cpu_to_le16(mbim->ctrl_id);
+
+ mbim->not_port.notify_req = NULL;
+ /*
+ * In double buffering if there is a space in FIFO,
+ * completion callback can be called right after the call,
+ * so unlocking
+ */
+ spin_unlock(&mbim->lock);
+ status = usb_ep_queue(mbim->not_port.notify, req, GFP_ATOMIC);
+ spin_lock(&mbim->lock);
+ if (status < 0) {
+ mbim->not_port.notify_req = req;
+ atomic_dec(&mbim->not_port.notify_count);
+ pr_err("usb_ep_queue failed, err: %d", status);
+ }
+}
+
+/*
+ * Context: mbim->lock held
+ */
+static void mbim_notify(struct f_mbim *mbim)
+{
+ /*
+ * If mbim_notify() is called before the second (CONNECT)
+ * notification is sent, then it will reset to send the SPEED
+ * notificaion again (and again, and again), but it's not a problem
+ */
+ pr_info("dev:%p\n", mbim);
+
+ mbim->not_port.notify_state = NCM_NOTIFY_SPEED;
+ mbim_do_notify(mbim);
+}
+
+static void mbim_notify_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_mbim *mbim = req->context;
+ struct usb_cdc_notification *event = req->buf;
+
+ int notif_c = 0;
+
+ pr_info("dev:%p\n", mbim);
+
+ spin_lock(&mbim->lock);
+ switch (req->status) {
+ case 0:
+ pr_info("Notification %02x sent\n",
+ event->bNotificationType);
+
+ notif_c = atomic_dec_return(&mbim->not_port.notify_count);
+
+ if (notif_c != 0) {
+ pr_info("Continue to mbim_do_notify()");
+ break;
+ } else {
+ pr_info("notify_count decreased to 0. Do not notify");
+ spin_unlock(&mbim->lock);
+ return;
+ }
+
+ break;
+
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ /* connection gone */
+ mbim->not_port.notify_state = NCM_NOTIFY_NONE;
+ atomic_set(&mbim->not_port.notify_count, 0);
+ pr_info("ESHUTDOWN/ECONNRESET, connection gone");
+ break;
+ default:
+ pr_err("Unknown event %02x --> %d\n",
+ event->bNotificationType, req->status);
+ break;
+ }
+
+ mbim->not_port.notify_req = req;
+ mbim_do_notify(mbim);
+
+ spin_unlock(&mbim->lock);
+
+ pr_info("dev:%p Exit\n", mbim);
+}
+
+static void mbim_ep0out_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ /* now for SET_NTB_INPUT_SIZE only */
+ unsigned in_size = 0;
+ struct usb_function *f = req->context;
+ struct f_mbim *mbim = func_to_mbim(f);
+ struct mbim_ntb_input_size *ntb = NULL;
+
+ pr_info("dev:%p\n", mbim);
+
+ req->context = NULL;
+ if (req->status || req->actual != req->length) {
+ pr_err("Bad control-OUT transfer\n");
+ goto invalid;
+ }
+
+ if (req->length == 4) {
+ in_size = get_unaligned_le32(req->buf);
+ if (in_size < USB_CDC_NCM_NTB_MIN_IN_SIZE ||
+ in_size > le32_to_cpu(ntb_parameters.dwNtbInMaxSize)) {
+ pr_err("Illegal INPUT SIZE (%d) from host\n", in_size);
+ goto invalid;
+ }
+ } else if (req->length == 8) {
+ ntb = (struct mbim_ntb_input_size *)req->buf;
+ in_size = get_unaligned_le32(&(ntb->ntb_input_size));
+ if (in_size < USB_CDC_NCM_NTB_MIN_IN_SIZE ||
+ in_size > le32_to_cpu(ntb_parameters.dwNtbInMaxSize)) {
+ pr_err("Illegal INPUT SIZE (%d) from host\n", in_size);
+ goto invalid;
+ }
+ mbim->ntb_max_datagrams =
+ get_unaligned_le16(&(ntb->ntb_max_datagrams));
+ } else {
+ pr_err("Illegal NTB length %d\n", in_size);
+ goto invalid;
+ }
+
+ pr_info("Set NTB INPUT SIZE %d\n", in_size);
+
+ mbim->ntb_input_size = in_size;
+ return;
+
+invalid:
+ usb_ep_set_halt(ep);
+
+ pr_err("dev:%p Failed\n", mbim);
+
+ return;
+}
+
+static void
+fmbim_cmd_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_mbim *dev = req->context;
+ struct ctrl_pkt *cpkt = NULL;
+ int len = req->actual;
+
+ if (!dev) {
+ pr_err("mbim dev is null\n");
+ return;
+ }
+
+ if (req->status < 0) {
+ pr_err("mbim command error %d\n", req->status);
+ return;
+ }
+
+ pr_info("dev:%p port#%d\n", dev, dev->port_num);
+
+ spin_lock(&dev->lock);
+ if (!dev->is_open) {
+ pr_err("mbim file handler %p is not open", dev);
+ spin_unlock(&dev->lock);
+ return;
+ }
+
+ cpkt = mbim_alloc_ctrl_pkt(len, GFP_ATOMIC);
+ if (!cpkt) {
+ pr_err("Unable to allocate ctrl pkt\n");
+ spin_unlock(&dev->lock);
+ return;
+ }
+
+ pr_info("Add to cpkt_req_q packet with len = %d\n", len);
+ memcpy(cpkt->buf, req->buf, len);
+ list_add_tail(&cpkt->list, &dev->cpkt_req_q);
+ spin_unlock(&dev->lock);
+
+ /* wakeup read thread */
+ pr_info("Wake up read queue");
+ wake_up(&dev->read_wq);
+
+ return;
+}
+
+static int
+mbim_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+ struct f_mbim *mbim = func_to_mbim(f);
+ struct usb_composite_dev *cdev = mbim->cdev;
+ struct usb_request *req = cdev->req;
+ struct ctrl_pkt *cpkt = NULL;
+ int value = -EOPNOTSUPP;
+ u16 w_index = le16_to_cpu(ctrl->wIndex);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+
+ /*
+ * composite driver infrastructure handles everything except
+ * CDC class messages; interface activation uses set_alt().
+ */
+
+ if (!atomic_read(&mbim->online)) {
+ pr_info("usb cable is not connected\n");
+ return -ENOTCONN;
+ }
+
+ switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
+ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_RESET_FUNCTION:
+
+ pr_info("USB_CDC_RESET_FUNCTION");
+ value = 0;
+ if (!_mbim_dev->user_pid) {
+ pr_err("QBI pid is not set");
+ break;
+ }
+
+ if (!_mbim_dev->is_open) {
+ pr_err("QBI is not up yet");
+ break;
+ }
+
+ send_sig_info(SIGUSR1, SEND_SIG_NOINFO,
+ find_task_by_vpid(_mbim_dev->user_pid));
+
+ pr_info("Sent signal to QBI pid %d",
+ _mbim_dev->user_pid);
+ break;
+
+ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_SEND_ENCAPSULATED_COMMAND:
+
+ pr_info("USB_CDC_SEND_ENCAPSULATED_COMMAND");
+
+ if (w_length > req->length) {
+ pr_err("w_length > req->length: %d > %d",
+ w_length, req->length);
+ }
+ value = w_length;
+ req->complete = fmbim_cmd_complete;
+ req->context = mbim;
+ break;
+
+ case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_GET_ENCAPSULATED_RESPONSE:
+
+ pr_info("USB_CDC_GET_ENCAPSULATED_RESPONSE");
+
+ if (w_value) {
+ pr_err("w_length > 0: %d", w_length);
+ break;
+ }
+
+ pr_info("req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+
+ spin_lock(&mbim->lock);
+ if (list_empty(&mbim->cpkt_resp_q)) {
+ pr_err("ctrl resp queue empty\n");
+ spin_unlock(&mbim->lock);
+ break;
+ }
+
+ cpkt = list_first_entry(&mbim->cpkt_resp_q,
+ struct ctrl_pkt, list);
+ list_del(&cpkt->list);
+ spin_unlock(&mbim->lock);
+
+ value = min_t(unsigned, w_length, cpkt->len);
+ memcpy(req->buf, cpkt->buf, value);
+ mbim_free_ctrl_pkt(cpkt);
+
+ pr_info("copied encapsulated_response %d bytes",
+ value);
+
+ break;
+
+ case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_GET_NTB_PARAMETERS:
+
+ pr_info("USB_CDC_GET_NTB_PARAMETERS");
+
+ if (w_length == 0 || w_value != 0 || w_index != mbim->ctrl_id)
+ break;
+
+ value = w_length > sizeof ntb_parameters ?
+ sizeof ntb_parameters : w_length;
+ memcpy(req->buf, &ntb_parameters, value);
+ break;
+
+ case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_GET_NTB_INPUT_SIZE:
+
+ pr_info("USB_CDC_GET_NTB_INPUT_SIZE");
+
+ if (w_length < 4 || w_value != 0 || w_index != mbim->ctrl_id)
+ break;
+
+ put_unaligned_le32(mbim->ntb_input_size, req->buf);
+ value = 4;
+ pr_info("Reply to host INPUT SIZE %d\n",
+ mbim->ntb_input_size);
+ break;
+
+ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_SET_NTB_INPUT_SIZE:
+
+ pr_info("USB_CDC_SET_NTB_INPUT_SIZE");
+
+ if (w_length != 4 && w_length != 8) {
+ pr_err("wrong NTB length %d", w_length);
+ break;
+ }
+
+ if (w_value != 0 || w_index != mbim->ctrl_id)
+ break;
+
+ req->complete = mbim_ep0out_complete;
+ req->length = w_length;
+ req->context = f;
+
+ value = req->length;
+ break;
+
+ case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_GET_NTB_FORMAT:
+ {
+ uint16_t format;
+
+ pr_info("USB_CDC_GET_NTB_FORMAT");
+
+ if (w_length < 2 || w_value != 0 || w_index != mbim->ctrl_id)
+ break;
+
+ format = (mbim->parser_opts == &ndp16_opts) ? 0x0000 : 0x0001;
+ put_unaligned_le16(format, req->buf);
+ value = 2;
+ pr_info("NTB FORMAT: sending %d\n", format);
+ break;
+ }
+
+ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_SET_NTB_FORMAT:
+ {
+ pr_info("USB_CDC_SET_NTB_FORMAT");
+
+ if (w_length != 0 || w_index != mbim->ctrl_id)
+ break;
+ switch (w_value) {
+ case 0x0000:
+ mbim->parser_opts = &ndp16_opts;
+ pr_info("NCM16 selected\n");
+ break;
+ case 0x0001:
+ mbim->parser_opts = &ndp32_opts;
+ pr_info("NCM32 selected\n");
+ break;
+ default:
+ break;
+ }
+ value = 0;
+ break;
+ }
+
+ /* optional in mbim descriptor: */
+ /* case USB_CDC_GET_MAX_DATAGRAM_SIZE: */
+ /* case USB_CDC_SET_MAX_DATAGRAM_SIZE: */
+
+ default:
+ pr_err("invalid control req: %02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ }
+
+ /* respond with data transfer or status phase? */
+ if (value >= 0) {
+ pr_info("control request: %02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ req->zero = 0;
+ req->length = value;
+ value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+ if (value < 0) {
+ pr_err("queueing req failed: %02x.%02x, err %d\n",
+ ctrl->bRequestType,
+ ctrl->bRequest, value);
+ }
+ } else {
+ pr_err("ctrl req err %d: %02x.%02x v%04x i%04x l%d\n",
+ value, ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ }
+
+ /* device either stalls (value < 0) or reports success */
+ return value;
+}
+
+static int mbim_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+ struct f_mbim *mbim = func_to_mbim(f);
+ struct usb_composite_dev *cdev = mbim->cdev;
+ int ret = 0;
+
+ /* Control interface has only altsetting 0 */
+ if (intf == mbim->ctrl_id) {
+
+ pr_info("CONTROL_INTERFACE");
+
+ if (alt != 0)
+ goto fail;
+
+ if (mbim->not_port.notify->driver_data) {
+ pr_info("reset mbim control %d\n", intf);
+ usb_ep_disable(mbim->not_port.notify);
+ }
+
+ ret = config_ep_by_speed(cdev->gadget, f,
+ mbim->not_port.notify);
+ if (ret) {
+ mbim->not_port.notify->desc = NULL;
+ pr_err("Failed configuring notify ep %s: err %d\n",
+ mbim->not_port.notify->name, ret);
+ return ret;
+ }
+
+ ret = usb_ep_enable(mbim->not_port.notify);
+ if (ret) {
+ pr_err("usb ep#%s enable failed, err#%d\n",
+ mbim->not_port.notify->name, ret);
+ return ret;
+ }
+ mbim->not_port.notify->driver_data = mbim;
+
+ /* Data interface has two altsettings, 0 and 1 */
+ } else if (intf == mbim->data_id) {
+
+ pr_info("DATA_INTERFACE");
+
+ if (alt > 1)
+ goto fail;
+
+ if (mbim->bam_port.in->driver_data) {
+ pr_info("reset mbim\n");
+ mbim_reset_values(mbim);
+ mbim_bam_disconnect(mbim);
+ }
+
+ /*
+ * CDC Network only sends data in non-default altsettings.
+ * Changing altsettings resets filters, statistics, etc.
+ */
+ if (alt == 1) {
+ pr_info("Alt set 1, initialize ports");
+
+ if (!mbim->bam_port.in->desc) {
+
+ pr_info("Choose endpoints");
+
+ ret = config_ep_by_speed(cdev->gadget, f,
+ mbim->bam_port.in);
+ if (ret) {
+ mbim->bam_port.in->desc = NULL;
+ pr_err("IN ep %s failed: %d\n",
+ mbim->bam_port.in->name, ret);
+ return ret;
+ }
+
+ pr_info("Set mbim port in_desc = 0x%p",
+ mbim->bam_port.in->desc);
+
+ ret = config_ep_by_speed(cdev->gadget, f,
+ mbim->bam_port.out);
+ if (ret) {
+ mbim->bam_port.out->desc = NULL;
+ pr_err("OUT ep %s failed: %d\n",
+ mbim->bam_port.out->name, ret);
+ return ret;
+ }
+
+ pr_info("Set mbim port out_desc = 0x%p",
+ mbim->bam_port.out->desc);
+ } else {
+ pr_info("PORTS already SET");
+ }
+
+ pr_info("Activate mbim\n");
+ mbim_bam_connect(mbim);
+ }
+
+ spin_lock(&mbim->lock);
+ mbim_notify(mbim);
+ spin_unlock(&mbim->lock);
+ } else {
+ goto fail;
+ }
+
+ atomic_set(&mbim->online, 1);
+
+ pr_info("SET DEVICE ONLINE");
+
+ /* wakeup file threads */
+ wake_up(&mbim->read_wq);
+ wake_up(&mbim->write_wq);
+
+ return 0;
+
+fail:
+ pr_err("ERROR: Illegal Interface");
+ return -EINVAL;
+}
+
+/*
+ * Because the data interface supports multiple altsettings,
+ * this MBIM function *MUST* implement a get_alt() method.
+ */
+static int mbim_get_alt(struct usb_function *f, unsigned intf)
+{
+ struct f_mbim *mbim = func_to_mbim(f);
+
+ if (intf == mbim->ctrl_id)
+ return 0;
+ return mbim->bam_port.in->driver_data ? 1 : 0;
+}
+
+static void mbim_disable(struct usb_function *f)
+{
+ struct f_mbim *mbim = func_to_mbim(f);
+
+ pr_info("SET DEVICE OFFLINE");
+ atomic_set(&mbim->online, 0);
+
+ if (_mbim_dev && _mbim_dev->user_pid && _mbim_dev->is_open) {
+ send_sig_info(SIGUSR1, SEND_SIG_NOINFO,
+ find_task_by_vpid(_mbim_dev->user_pid));
+ pr_info("Sending reset signal to QBI pid %d",
+ _mbim_dev->user_pid);
+ }
+
+ mbim_bam_disconnect(mbim);
+
+ if (mbim->not_port.notify->driver_data) {
+ usb_ep_disable(mbim->not_port.notify);
+ mbim->not_port.notify->driver_data = NULL;
+ }
+
+ pr_info("mbim deactivated\n");
+}
+
+/*---------------------- function driver setup/binding ---------------------*/
+
+static int
+mbim_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = c->cdev;
+ struct f_mbim *mbim = func_to_mbim(f);
+ int status;
+ struct usb_ep *ep;
+
+ pr_info("Enter");
+
+ mbim->cdev = cdev;
+
+ /* allocate instance-specific interface IDs */
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ mbim->ctrl_id = status;
+ mbim_iad_desc.bFirstInterface = status;
+
+ mbim_control_intf.bInterfaceNumber = status;
+ mbim_union_desc.bMasterInterface0 = status;
+
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ mbim->data_id = status;
+
+ mbim_data_nop_intf.bInterfaceNumber = status;
+ mbim_data_intf.bInterfaceNumber = status;
+ mbim_union_desc.bSlaveInterface0 = status;
+
+ status = -ENODEV;
+
+ /* allocate instance-specific endpoints */
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_mbim_in_desc);
+ if (!ep) {
+ pr_err("usb epin autoconfig failed\n");
+ goto fail;
+ }
+ pr_info("usb epin autoconfig succeeded\n");
+ ep->driver_data = cdev; /* claim */
+ mbim->bam_port.in = ep;
+
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_mbim_out_desc);
+ if (!ep) {
+ pr_err("usb epout autoconfig failed\n");
+ goto fail;
+ }
+ pr_info("usb epout autoconfig succeeded\n");
+ ep->driver_data = cdev; /* claim */
+ mbim->bam_port.out = ep;
+
+ ep = usb_ep_autoconfig(cdev->gadget, &fs_mbim_notify_desc);
+ if (!ep) {
+ pr_err("usb notify ep autoconfig failed\n");
+ goto fail;
+ }
+ pr_info("usb notify ep autoconfig succeeded\n");
+ mbim->not_port.notify = ep;
+ ep->driver_data = cdev; /* claim */
+
+ status = -ENOMEM;
+
+ /* allocate notification request and buffer */
+ mbim->not_port.notify_req = mbim_alloc_req(ep, NCM_STATUS_BYTECOUNT);
+ if (!mbim->not_port.notify_req) {
+ pr_info("failed to allocate notify request\n");
+ goto fail;
+ }
+ pr_info("allocated notify ep request & request buffer\n");
+
+ mbim->not_port.notify_req->context = mbim;
+ mbim->not_port.notify_req->complete = mbim_notify_complete;
+
+ /* copy descriptors, and track endpoint copies */
+ f->descriptors = usb_copy_descriptors(mbim_fs_function);
+ if (!f->descriptors)
+ goto fail;
+
+ /*
+ * support all relevant hardware speeds... we expect that when
+ * hardware is dual speed, all bulk-capable endpoints work at
+ * both speeds
+ */
+ if (gadget_is_dualspeed(c->cdev->gadget)) {
+ hs_mbim_in_desc.bEndpointAddress =
+ fs_mbim_in_desc.bEndpointAddress;
+ hs_mbim_out_desc.bEndpointAddress =
+ fs_mbim_out_desc.bEndpointAddress;
+ hs_mbim_notify_desc.bEndpointAddress =
+ fs_mbim_notify_desc.bEndpointAddress;
+
+ /* copy descriptors, and track endpoint copies */
+ f->hs_descriptors = usb_copy_descriptors(mbim_hs_function);
+ if (!f->hs_descriptors)
+ goto fail;
+ }
+
+ pr_info("mbim(%d): %s speed IN/%s OUT/%s NOTIFY/%s\n",
+ mbim->port_num,
+ gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+ mbim->bam_port.in->name, mbim->bam_port.out->name,
+ mbim->not_port.notify->name);
+
+ return 0;
+
+fail:
+ pr_err("%s failed to bind, err %d\n", f->name, status);
+
+ if (f->descriptors)
+ usb_free_descriptors(f->descriptors);
+
+ if (mbim->not_port.notify_req) {
+ kfree(mbim->not_port.notify_req->buf);
+ usb_ep_free_request(mbim->not_port.notify,
+ mbim->not_port.notify_req);
+ }
+
+ /* we might as well release our claims on endpoints */
+ if (mbim->not_port.notify)
+ mbim->not_port.notify->driver_data = NULL;
+ if (mbim->bam_port.out)
+ mbim->bam_port.out->driver_data = NULL;
+ if (mbim->bam_port.in)
+ mbim->bam_port.in->driver_data = NULL;
+
+ return status;
+}
+
+static void mbim_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct f_mbim *mbim = func_to_mbim(f);
+
+ if (gadget_is_dualspeed(c->cdev->gadget))
+ usb_free_descriptors(f->hs_descriptors);
+ usb_free_descriptors(f->descriptors);
+
+ kfree(mbim->not_port.notify_req->buf);
+ usb_ep_free_request(mbim->not_port.notify, mbim->not_port.notify_req);
+}
+
+/**
+ * mbim_bind_config - add MBIM link to a configuration
+ * @c: the configuration to support the network link
+ * Context: single threaded during gadget setup
+ * Returns zero on success, else negative errno.
+ */
+int mbim_bind_config(struct usb_configuration *c, unsigned portno)
+{
+ struct f_mbim *mbim = NULL;
+ int status = 0;
+
+ pr_info("port number %u", portno);
+
+ if (portno >= nr_mbim_ports) {
+ pr_err("Can not add port %u. Max ports = %d",
+ portno, nr_mbim_ports);
+ return -ENODEV;
+ }
+
+ status = mbim_bam_setup(nr_mbim_ports);
+ if (status) {
+ pr_err("bam setup failed");
+ return status;
+ }
+
+ /* maybe allocate device-global string IDs */
+ if (mbim_string_defs[0].id == 0) {
+
+ /* control interface label */
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ mbim_string_defs[STRING_CTRL_IDX].id = status;
+ mbim_control_intf.iInterface = status;
+
+ /* data interface label */
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ mbim_string_defs[STRING_DATA_IDX].id = status;
+ mbim_data_nop_intf.iInterface = status;
+ mbim_data_intf.iInterface = status;
+ }
+
+ /* allocate and initialize one new instance */
+ mbim = mbim_ports[0].port;
+ if (!mbim) {
+ pr_info("mbim struct not allocated");
+ return -ENOMEM;
+ }
+
+ mbim->cdev = c->cdev;
+
+ spin_lock_init(&mbim->lock);
+
+ mbim_reset_values(mbim);
+
+ mbim->function.name = "usb_mbim";
+ mbim->function.strings = mbim_strings;
+ mbim->function.bind = mbim_bind;
+ mbim->function.unbind = mbim_unbind;
+ mbim->function.set_alt = mbim_set_alt;
+ mbim->function.get_alt = mbim_get_alt;
+ mbim->function.setup = mbim_setup;
+ mbim->function.disable = mbim_disable;
+
+ INIT_LIST_HEAD(&mbim->cpkt_req_q);
+ INIT_LIST_HEAD(&mbim->cpkt_resp_q);
+
+ status = usb_add_function(c, &mbim->function);
+
+ pr_info("Exit status %d", status);
+
+ return status;
+}
+
+/* ------------ MBIM DRIVER File Operations API for USER SPACE ------------ */
+
+static ssize_t
+mbim_read(struct file *fp, char __user *buf, size_t count, loff_t *pos)
+{
+ struct f_mbim *dev = fp->private_data;
+ struct ctrl_pkt *cpkt = NULL;
+ int ret = 0;
+
+ pr_debug("Enter(%d)\n", count);
+
+ if (!dev) {
+ pr_err("Received NULL mbim pointer\n");
+ return -ENODEV;
+ }
+
+ if (count > MBIM_BULK_BUFFER_SIZE) {
+ pr_err("Buffer size is too big %d, should be at most %d\n",
+ count, MBIM_BULK_BUFFER_SIZE);
+ return -EINVAL;
+ }
+
+ if (mbim_lock(&dev->read_excl)) {
+ pr_err("Previous reading is not finished yet\n");
+ return -EBUSY;
+ }
+
+ /* block until mbim online */
+ while (!(atomic_read(&dev->online) || atomic_read(&dev->error))) {
+ pr_err("USB cable not connected. Wait.\n");
+ ret = wait_event_interruptible(dev->read_wq,
+ (atomic_read(&dev->online) ||
+ atomic_read(&dev->error)));
+ if (ret < 0) {
+ mbim_unlock(&dev->read_excl);
+ return 0;
+ }
+ }
+
+ if (atomic_read(&dev->error)) {
+ mbim_unlock(&dev->read_excl);
+ return -EIO;
+ }
+
+ while (list_empty(&dev->cpkt_req_q)) {
+ pr_err("Requests list is empty. Wait.\n");
+ ret = wait_event_interruptible(dev->read_wq,
+ !list_empty(&dev->cpkt_req_q));
+ if (ret < 0) {
+ pr_err("Waiting failed\n");
+ mbim_unlock(&dev->read_excl);
+ return 0;
+ }
+ pr_debug("Received request packet\n");
+ }
+
+ cpkt = list_first_entry(&dev->cpkt_req_q, struct ctrl_pkt,
+ list);
+ if (cpkt->len > count) {
+ mbim_unlock(&dev->read_excl);
+ pr_err("cpkt size too big:%d > buf size:%d\n",
+ cpkt->len, count);
+ return -ENOMEM;
+ }
+
+ pr_debug("cpkt size:%d\n", cpkt->len);
+
+ list_del(&cpkt->list);
+ mbim_unlock(&dev->read_excl);
+
+ ret = copy_to_user(buf, cpkt->buf, cpkt->len);
+ if (ret) {
+ pr_err("copy_to_user failed: err %d\n", ret);
+ ret = 0;
+ } else {
+ pr_debug("copied %d bytes to user\n", cpkt->len);
+ ret = cpkt->len;
+ }
+
+ mbim_free_ctrl_pkt(cpkt);
+
+ return ret;
+}
+
+static ssize_t
+mbim_write(struct file *fp, const char __user *buf, size_t count, loff_t *pos)
+{
+ struct f_mbim *dev = fp->private_data;
+ struct ctrl_pkt *cpkt = NULL;
+ int ret = 0;
+
+ pr_debug("Enter(%d)", count);
+
+ if (!dev) {
+ pr_err("Received NULL mbim pointer\n");
+ return -ENODEV;
+ }
+
+ if (!count) {
+ pr_err("zero length ctrl pkt\n");
+ return -ENODEV;
+ }
+
+ if (count > MAX_CTRL_PKT_SIZE) {
+ pr_err("given pkt size too big:%d > max_pkt_size:%d\n",
+ count, MAX_CTRL_PKT_SIZE);
+ return -ENOMEM;
+ }
+
+ if (mbim_lock(&dev->write_excl)) {
+ pr_err("Previous writing not finished yet\n");
+ return -EBUSY;
+ }
+
+ if (!atomic_read(&dev->online)) {
+ pr_err("USB cable not connected\n");
+ mbim_unlock(&dev->write_excl);
+ return -EPIPE;
+ }
+
+ cpkt = mbim_alloc_ctrl_pkt(count, GFP_KERNEL);
+ if (!cpkt) {
+ pr_err("failed to allocate ctrl pkt\n");
+ mbim_unlock(&dev->write_excl);
+ return -ENOMEM;
+ }
+
+ ret = copy_from_user(cpkt->buf, buf, count);
+ if (ret) {
+ pr_err("copy_from_user failed err:%d\n", ret);
+ mbim_free_ctrl_pkt(cpkt);
+ mbim_unlock(&dev->write_excl);
+ return 0;
+ }
+
+ fmbim_send_cpkt_response(dev, cpkt);
+
+ mbim_unlock(&dev->write_excl);
+
+ pr_debug("Exit(%d)", count);
+
+ return count;
+}
+
+static int mbim_open(struct inode *ip, struct file *fp)
+{
+ pr_info("Open mbim driver\n");
+
+ while (!_mbim_dev) {
+ pr_err("mbim_dev not created yet\n");
+ return -ENODEV;
+ }
+
+ if (mbim_lock(&_mbim_dev->open_excl)) {
+ pr_err("Already opened\n");
+ return -EBUSY;
+ }
+
+ pr_info("Lock mbim_dev->open_excl for open\n");
+
+ if (!atomic_read(&_mbim_dev->online))
+ pr_err("USB cable not connected\n");
+
+ pr_info("Set QBI pid %d\n", pid_nr(task_pid(current)));
+ _mbim_dev->user_pid = pid_nr(task_pid(current));
+
+ fp->private_data = _mbim_dev;
+
+ atomic_set(&_mbim_dev->error, 0);
+
+ spin_lock(&_mbim_dev->lock);
+ _mbim_dev->is_open = true;
+ mbim_notify(_mbim_dev);
+ spin_unlock(&_mbim_dev->lock);
+
+ pr_info("Exit, mbim file opened\n");
+
+ return 0;
+}
+
+static int mbim_release(struct inode *ip, struct file *fp)
+{
+ struct f_mbim *mbim = fp->private_data;
+
+ pr_info("Close mbim file");
+
+ spin_lock(&mbim->lock);
+ mbim->is_open = false;
+ mbim_notify(mbim);
+ spin_unlock(&mbim->lock);
+
+ mbim->user_pid = 0;
+
+ mbim_unlock(&_mbim_dev->open_excl);
+
+ return 0;
+}
+
+static long mbim_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
+{
+ struct f_mbim *mbim = fp->private_data;
+ int ret = 0;
+
+ pr_info("Received command %d", cmd);
+
+ if (mbim_lock(&mbim->ioctl_excl))
+ return -EBUSY;
+
+ switch (cmd) {
+ case MBIM_GET_NTB_SIZE:
+ ret = copy_to_user((void __user *)arg,
+ &mbim->ntb_input_size, sizeof(mbim->ntb_input_size));
+ if (ret) {
+ pr_err("copying to user space failed");
+ ret = -EFAULT;
+ }
+ pr_info("Sent NTB size %d", mbim->ntb_input_size);
+ break;
+ case MBIM_GET_DATAGRAM_COUNT:
+ ret = copy_to_user((void __user *)arg,
+ &mbim->ntb_max_datagrams,
+ sizeof(mbim->ntb_max_datagrams));
+ if (ret) {
+ pr_err("copying to user space failed");
+ ret = -EFAULT;
+ }
+ pr_info("Sent NTB datagrams count %d",
+ mbim->ntb_max_datagrams);
+ break;
+ default:
+ pr_err("wrong parameter");
+ ret = -EINVAL;
+ }
+
+ mbim_unlock(&mbim->ioctl_excl);
+
+ return ret;
+}
+
+/* file operations for MBIM device /dev/android_mbim */
+static const struct file_operations mbim_fops = {
+ .owner = THIS_MODULE,
+ .open = mbim_open,
+ .release = mbim_release,
+ .read = mbim_read,
+ .write = mbim_write,
+ .unlocked_ioctl = mbim_ioctl,
+};
+
+static struct miscdevice mbim_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "android_mbim",
+ .fops = &mbim_fops,
+};
+
+static int mbim_init(int instances)
+{
+ int i;
+ struct f_mbim *dev = NULL;
+ int ret;
+
+ pr_info("initialize %d instances\n", instances);
+
+ if (instances > NR_MBIM_PORTS) {
+ pr_err("Max-%d instances supported\n", NR_MBIM_PORTS);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < instances; i++) {
+ dev = kzalloc(sizeof(struct f_mbim), GFP_KERNEL);
+ if (!dev) {
+ pr_err("Failed to allocate mbim dev\n");
+ ret = -ENOMEM;
+ goto fail_probe;
+ }
+
+ dev->port_num = i;
+ spin_lock_init(&dev->lock);
+ INIT_LIST_HEAD(&dev->cpkt_req_q);
+ INIT_LIST_HEAD(&dev->cpkt_resp_q);
+
+ mbim_ports[i].port = dev;
+ mbim_ports[i].port_num = i;
+
+ init_waitqueue_head(&dev->read_wq);
+ init_waitqueue_head(&dev->write_wq);
+
+ atomic_set(&dev->open_excl, 0);
+ atomic_set(&dev->ioctl_excl, 0);
+ atomic_set(&dev->read_excl, 0);
+ atomic_set(&dev->write_excl, 0);
+
+ nr_mbim_ports++;
+
+ }
+
+ _mbim_dev = dev;
+ ret = misc_register(&mbim_device);
+ if (ret) {
+ pr_err("mbim driver failed to register");
+ goto fail_probe;
+ }
+
+ pr_info("Initialized %d ports\n", nr_mbim_ports);
+
+ return ret;
+
+fail_probe:
+ pr_err("Failed");
+ for (i = 0; i < nr_mbim_ports; i++) {
+ kfree(mbim_ports[i].port);
+ mbim_ports[i].port = NULL;
+ }
+
+ return ret;
+}
+
+static void fmbim_cleanup(void)
+{
+ int i = 0;
+
+ pr_info("Enter");
+
+ for (i = 0; i < nr_mbim_ports; i++) {
+ kfree(mbim_ports[i].port);
+ mbim_ports[i].port = NULL;
+ }
+ nr_mbim_ports = 0;
+
+ misc_deregister(&mbim_device);
+
+ _mbim_dev = NULL;
+}
+
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index cc26c85..b086428 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -488,20 +488,16 @@
}
dev->notify->driver_data = dev;
- if (dev->port.in->driver_data) {
- pr_debug("%s: reset port:%d\n", __func__, dev->port_num);
- gport_rmnet_disconnect(dev);
+ if (!dev->port.in->driver_data) {
+ if (config_ep_by_speed(cdev->gadget, f, dev->port.in) ||
+ config_ep_by_speed(cdev->gadget, f, dev->port.out)) {
+ dev->port.in->desc = NULL;
+ dev->port.out->desc = NULL;
+ return -EINVAL;
+ }
+ ret = gport_rmnet_connect(dev);
}
- if (config_ep_by_speed(cdev->gadget, f, dev->port.in) ||
- config_ep_by_speed(cdev->gadget, f, dev->port.out)) {
- dev->port.in->desc = NULL;
- dev->port.out->desc = NULL;
- return -EINVAL;
- }
-
- ret = gport_rmnet_connect(dev);
-
atomic_set(&dev->online, 1);
return ret;
diff --git a/drivers/usb/gadget/u_bam_data.c b/drivers/usb/gadget/u_bam_data.c
new file mode 100644
index 0000000..73b4e75
--- /dev/null
+++ b/drivers/usb/gadget/u_bam_data.c
@@ -0,0 +1,328 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifdef pr_fmt
+#undef pr_fmt
+#endif
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/bitops.h>
+#include <linux/usb/gadget.h>
+
+#include <mach/bam_dmux.h>
+#include <mach/usb_gadget_xport.h>
+#include <mach/usb_bam.h>
+
+#define BAM2BAM_DATA_N_PORTS 1
+
+static struct workqueue_struct *bam_data_wq;
+static int n_bam2bam_data_ports;
+
+#define SPS_PARAMS_SPS_MODE BIT(5)
+#define SPS_PARAMS_TBE BIT(6)
+#define MSM_VENDOR_ID BIT(16)
+
+struct data_port {
+ struct usb_function func;
+ struct usb_ep *in;
+ struct usb_ep *out;
+};
+
+struct bam_data_ch_info {
+ unsigned long flags;
+ unsigned id;
+
+ struct bam_data_port *port;
+ struct work_struct write_tobam_w;
+
+ struct usb_request *rx_req;
+ struct usb_request *tx_req;
+
+ u8 src_pipe_idx;
+ u8 dst_pipe_idx;
+ u8 connection_idx;
+};
+
+struct bam_data_port {
+ unsigned port_num;
+ struct data_port *port_usb;
+ struct bam_data_ch_info data_ch;
+
+ struct work_struct connect_w;
+ struct work_struct disconnect_w;
+};
+
+struct bam_data_port *bam2bam_data_ports[BAM2BAM_DATA_N_PORTS];
+
+/*------------data_path----------------------------*/
+
+static void bam_data_endless_rx_complete(struct usb_ep *ep,
+ struct usb_request *req)
+{
+ int status = req->status;
+
+ pr_info("status: %d\n", status);
+}
+
+static void bam_data_endless_tx_complete(struct usb_ep *ep,
+ struct usb_request *req)
+{
+ int status = req->status;
+
+ pr_info("status: %d\n", status);
+}
+
+static void bam_data_start_endless_rx(struct bam_data_port *port)
+{
+ struct bam_data_ch_info *d = &port->data_ch;
+ int status;
+
+ status = usb_ep_queue(port->port_usb->out, d->rx_req, GFP_ATOMIC);
+ if (status)
+ pr_err("error enqueuing transfer, %d\n", status);
+}
+
+static void bam_data_start_endless_tx(struct bam_data_port *port)
+{
+ struct bam_data_ch_info *d = &port->data_ch;
+ int status;
+
+ status = usb_ep_queue(port->port_usb->in, d->tx_req, GFP_ATOMIC);
+ if (status)
+ pr_err("error enqueuing transfer, %d\n", status);
+}
+
+static void bam2bam_data_disconnect_work(struct work_struct *w)
+{
+ struct bam_data_port *port =
+ container_of(w, struct bam_data_port, disconnect_w);
+
+ pr_info("Enter");
+
+ /* disable endpoints */
+ if (!port->port_usb || !port->port_usb->out || !port->port_usb->in) {
+ pr_err("port_usb->out/in == NULL. Exit");
+ return;
+ }
+ usb_ep_disable(port->port_usb->out);
+ usb_ep_disable(port->port_usb->in);
+
+ port->port_usb->in->driver_data = NULL;
+ port->port_usb->out->driver_data = NULL;
+
+ port->port_usb = 0;
+
+ pr_info("Exit");
+}
+
+static void bam2bam_data_connect_work(struct work_struct *w)
+{
+ struct bam_data_port *port = container_of(w, struct bam_data_port,
+ connect_w);
+ struct bam_data_ch_info *d = &port->data_ch;
+ u32 sps_params;
+ int ret;
+
+ pr_info("Enter");
+
+ ret = usb_bam_connect(d->connection_idx, &d->src_pipe_idx,
+ &d->dst_pipe_idx);
+ d->src_pipe_idx = 11;
+ d->dst_pipe_idx = 10;
+
+ if (ret) {
+ pr_err("usb_bam_connect failed: err:%d\n", ret);
+ return;
+ }
+
+ if (!port->port_usb) {
+ pr_err("port_usb is NULL");
+ return;
+ }
+
+ if (!port->port_usb->out) {
+ pr_err("port_usb->out (bulk out ep) is NULL");
+ return;
+ }
+
+ d->rx_req = usb_ep_alloc_request(port->port_usb->out, GFP_KERNEL);
+ if (!d->rx_req)
+ return;
+
+ d->rx_req->context = port;
+ d->rx_req->complete = bam_data_endless_rx_complete;
+ d->rx_req->length = 0;
+ sps_params = (SPS_PARAMS_SPS_MODE | d->src_pipe_idx |
+ MSM_VENDOR_ID) & ~SPS_PARAMS_TBE;
+ d->rx_req->udc_priv = sps_params;
+ d->tx_req = usb_ep_alloc_request(port->port_usb->in, GFP_KERNEL);
+ if (!d->tx_req)
+ return;
+
+ d->tx_req->context = port;
+ d->tx_req->complete = bam_data_endless_tx_complete;
+ d->tx_req->length = 0;
+ sps_params = (SPS_PARAMS_SPS_MODE | d->dst_pipe_idx |
+ MSM_VENDOR_ID) & ~SPS_PARAMS_TBE;
+ d->tx_req->udc_priv = sps_params;
+
+ /* queue in & out requests */
+ bam_data_start_endless_rx(port);
+ bam_data_start_endless_tx(port);
+
+ pr_info("Done\n");
+}
+
+static void bam2bam_data_port_free(int portno)
+{
+ kfree(bam2bam_data_ports[portno]);
+ bam2bam_data_ports[portno] = NULL;
+}
+
+static int bam2bam_data_port_alloc(int portno)
+{
+ struct bam_data_port *port = NULL;
+ struct bam_data_ch_info *d = NULL;
+
+ port = kzalloc(sizeof(struct bam_data_port), GFP_KERNEL);
+ if (!port)
+ return -ENOMEM;
+
+ port->port_num = portno;
+
+ INIT_WORK(&port->connect_w, bam2bam_data_connect_work);
+ INIT_WORK(&port->disconnect_w, bam2bam_data_disconnect_work);
+
+ /* data ch */
+ d = &port->data_ch;
+ d->port = port;
+ bam2bam_data_ports[portno] = port;
+
+ pr_info("port:%p portno:%d\n", port, portno);
+
+ return 0;
+}
+
+void bam_data_disconnect(struct data_port *gr, u8 port_num)
+{
+ struct bam_data_port *port;
+ struct bam_data_ch_info *d;
+
+ pr_info("dev:%p port#%d\n", gr, port_num);
+
+ if (port_num >= n_bam2bam_data_ports) {
+ pr_err("invalid bam2bam portno#%d\n", port_num);
+ return;
+ }
+
+ if (!gr) {
+ pr_err("mbim data port is null\n");
+ return;
+ }
+
+ port = bam2bam_data_ports[port_num];
+
+ d = &port->data_ch;
+ port->port_usb = gr;
+
+ queue_work(bam_data_wq, &port->disconnect_w);
+}
+
+int bam_data_connect(struct data_port *gr, u8 port_num,
+ u8 connection_idx)
+{
+ struct bam_data_port *port;
+ struct bam_data_ch_info *d;
+ int ret;
+
+ pr_info("dev:%p port#%d\n", gr, port_num);
+
+ if (port_num >= n_bam2bam_data_ports) {
+ pr_err("invalid portno#%d\n", port_num);
+ return -ENODEV;
+ }
+
+ if (!gr) {
+ pr_err("mbim data port is null\n");
+ return -ENODEV;
+ }
+
+ port = bam2bam_data_ports[port_num];
+
+ d = &port->data_ch;
+
+ ret = usb_ep_enable(gr->in);
+ if (ret) {
+ pr_err("usb_ep_enable failed eptype:IN ep:%p", gr->in);
+ return ret;
+ }
+ gr->in->driver_data = port;
+
+ ret = usb_ep_enable(gr->out);
+ if (ret) {
+ pr_err("usb_ep_enable failed eptype:OUT ep:%p", gr->out);
+ gr->in->driver_data = 0;
+ return ret;
+ }
+ gr->out->driver_data = port;
+
+ port->port_usb = gr;
+
+ d->connection_idx = connection_idx;
+
+ queue_work(bam_data_wq, &port->connect_w);
+
+ return 0;
+}
+
+int bam_data_setup(unsigned int no_bam2bam_port)
+{
+ int i;
+ int ret;
+
+ pr_info("requested %d BAM2BAM ports", no_bam2bam_port);
+
+ if (!no_bam2bam_port || no_bam2bam_port > BAM2BAM_DATA_N_PORTS) {
+ pr_err("Invalid num of ports count:%d\n", no_bam2bam_port);
+ return -EINVAL;
+ }
+
+ bam_data_wq = alloc_workqueue("k_bam_data",
+ WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+ if (!bam_data_wq) {
+ pr_err("Failed to create workqueue\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < no_bam2bam_port; i++) {
+ n_bam2bam_data_ports++;
+ ret = bam2bam_data_port_alloc(i);
+ if (ret) {
+ n_bam2bam_data_ports--;
+ pr_err("Failed to alloc port:%d\n", i);
+ goto free_bam_ports;
+ }
+ }
+
+ return 0;
+
+free_bam_ports:
+ for (i = 0; i < n_bam2bam_data_ports; i++)
+ bam2bam_data_port_free(i);
+ destroy_workqueue(bam_data_wq);
+
+ return ret;
+}
+
diff --git a/drivers/video/msm/mipi_NT35510.c b/drivers/video/msm/mipi_NT35510.c
index 930b4e9..c6f531e 100644
--- a/drivers/video/msm/mipi_NT35510.c
+++ b/drivers/video/msm/mipi_NT35510.c
@@ -18,6 +18,7 @@
static struct msm_panel_common_pdata *mipi_nt35510_pdata;
static struct dsi_buf nt35510_tx_buf;
static struct dsi_buf nt35510_rx_buf;
+spinlock_t bl_spinlock;
#define NT35510_SLEEP_OFF_DELAY 150
#define NT35510_DISPLAY_ON_DELAY 150
@@ -506,6 +507,8 @@
if (pdev->id == 0) {
mipi_nt35510_pdata = pdev->dev.platform_data;
+ if (mipi_nt35510_pdata->bl_lock)
+ spin_lock_init(&bl_spinlock);
return 0;
}
@@ -523,8 +526,16 @@
static void mipi_nt35510_set_backlight(struct msm_fb_data_type *mfd)
{
- /* Add backlight changes later*/
- return;
+ int bl_level;
+ unsigned long flags;
+ bl_level = mfd->bl_level;
+
+ if (mipi_nt35510_pdata->bl_lock) {
+ spin_lock_irqsave(&bl_spinlock, flags);
+ mipi_nt35510_pdata->pmic_backlight(bl_level);
+ spin_unlock_irqrestore(&bl_spinlock, flags);
+ } else
+ mipi_nt35510_pdata->pmic_backlight(bl_level);
}
static struct msm_fb_panel_data nt35510_panel_data = {
@@ -564,7 +575,6 @@
return -ENOMEM;
nt35510_panel_data.panel_info = *pinfo;
-
ret = platform_device_add_data(pdev, &nt35510_panel_data,
sizeof(nt35510_panel_data));
if (ret) {
diff --git a/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c b/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
index 2c4ee3e..f052e93 100644
--- a/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
+++ b/drivers/video/msm/mipi_NT35510_cmd_wvga_pt.c
@@ -56,7 +56,7 @@
pinfo.lcdc.border_clr = 0; /* blk */
pinfo.lcdc.underflow_clr = 0xff; /* blue */
pinfo.lcdc.hsync_skew = 0;
- pinfo.bl_max = 100;
+ pinfo.bl_max = 31;
pinfo.bl_min = 1;
pinfo.fb_num = 2;
diff --git a/drivers/video/msm/mipi_NT35510_video_wvga_pt.c b/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
index 82e03b2..4e97d99 100644
--- a/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
+++ b/drivers/video/msm/mipi_NT35510_video_wvga_pt.c
@@ -59,7 +59,7 @@
delayed from VSYNC active edge */
pinfo.lcdc.hsync_skew = 0;
pinfo.clk_rate = 499000000;
- pinfo.bl_max = 100; /*16; CHECK THIS!!!*/
+ pinfo.bl_max = 31;
pinfo.bl_min = 1;
pinfo.fb_num = 2;
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 672468e..8739122 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -164,6 +164,7 @@
int num_levels;
int (*set_grp_async)(void);
unsigned int idle_timeout;
+ bool strtstp_sleepwake;
unsigned int nap_allowed;
unsigned int clk_map;
unsigned int idle_needed;
diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h
index 81a9279..2b39f69 100644
--- a/include/linux/usb/cdc.h
+++ b/include/linux/usb/cdc.h
@@ -53,6 +53,7 @@
#define USB_CDC_DMM_TYPE 0x14
#define USB_CDC_OBEX_TYPE 0x15
#define USB_CDC_NCM_TYPE 0x1a
+#define USB_CDC_MBB_TYPE 0x1b /* mbb_desc */
/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */
struct usb_cdc_header_desc {
@@ -187,6 +188,21 @@
__le16 bcdNcmVersion;
__u8 bmNetworkCapabilities;
} __attribute__ ((packed));
+
+/* "MBIM Functional Descriptor" */
+struct usb_cdc_mbb_desc {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+
+ __le16 bcdMbbVersion;
+ __le16 wMaxControlMessage;
+ __u8 bNumberFilters;
+ __u8 bMaxFilterSize;
+ __le16 wMaxSegmentSize;
+ __u8 bmNetworkCapabilities;
+} __packed;
+
/*-------------------------------------------------------------------------*/
/*
@@ -201,6 +217,7 @@
#define USB_CDC_SEND_ENCAPSULATED_COMMAND 0x00
#define USB_CDC_GET_ENCAPSULATED_RESPONSE 0x01
+#define USB_CDC_RESET_FUNCTION 0x05
#define USB_CDC_REQ_SET_LINE_CODING 0x20
#define USB_CDC_REQ_GET_LINE_CODING 0x21
#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22
diff --git a/include/media/radio-iris.h b/include/media/radio-iris.h
index de2b356..dfad18d 100644
--- a/include/media/radio-iris.h
+++ b/include/media/radio-iris.h
@@ -44,7 +44,14 @@
/* default data access */
#define DEFAULT_DATA_OFFSET 2
#define DEFAULT_DATA_SIZE 249
-
+/* Power levels are 0-7, but SOC will expect values from 0-255
+ * So the each level step size will be 255/7 = 36 */
+#define FM_TX_PWR_LVL_STEP_SIZE 36
+#define FM_TX_PWR_LVL_0 0 /* Lowest power lvl that can be set for Tx */
+#define FM_TX_PWR_LVL_MAX 7 /* Max power lvl for Tx */
+#define FM_TX_PHY_CFG_MODE 0x3c
+#define FM_TX_PHY_CFG_LEN 0x10
+#define FM_TX_PWR_GAIN_OFFSET 14
/* HCI timeouts */
#define RADIO_HCI_TIMEOUT (10000) /* 10 seconds */
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index d5645ff..d49e215 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -209,6 +209,15 @@
MBHC_STATE_RELEASE,
};
+struct hpf_work {
+ struct tabla_priv *tabla;
+ u32 decimator;
+ u8 tx_hpf_cut_of_freq;
+ struct delayed_work dwork;
+};
+
+static struct hpf_work tx_hpf_work[NUM_DECIMATORS];
+
struct tabla_priv {
struct snd_soc_codec *codec;
struct tabla_reg_address reg_addr;
@@ -2279,6 +2288,9 @@
break;
case SND_SOC_DAPM_POST_PMU:
+
+ usleep_range(20000, 20000);
+
if (tabla->mbhc_polling_active &&
tabla->mbhc_cfg.micbias == micb_line) {
TABLA_ACQUIRE_LOCK(tabla->codec_resource_lock);
@@ -2310,14 +2322,73 @@
return 0;
}
+
+static void tx_hpf_corner_freq_callback(struct work_struct *work)
+{
+ struct delayed_work *hpf_delayed_work;
+ struct hpf_work *hpf_work;
+ struct tabla_priv *tabla;
+ struct snd_soc_codec *codec;
+ u16 tx_mux_ctl_reg;
+ u8 hpf_cut_of_freq;
+
+ hpf_delayed_work = to_delayed_work(work);
+ hpf_work = container_of(hpf_delayed_work, struct hpf_work, dwork);
+ tabla = hpf_work->tabla;
+ codec = hpf_work->tabla->codec;
+ hpf_cut_of_freq = hpf_work->tx_hpf_cut_of_freq;
+
+ tx_mux_ctl_reg = TABLA_A_CDC_TX1_MUX_CTL +
+ (hpf_work->decimator - 1) * 8;
+
+ pr_debug("%s(): decimator %u hpf_cut_of_freq 0x%x\n", __func__,
+ hpf_work->decimator, (unsigned int)hpf_cut_of_freq);
+
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30, hpf_cut_of_freq << 4);
+}
+
+#define TX_MUX_CTL_CUT_OFF_FREQ_MASK 0x30
+#define CF_MIN_3DB_4HZ 0x0
+#define CF_MIN_3DB_75HZ 0x1
+#define CF_MIN_3DB_150HZ 0x2
+
static int tabla_codec_enable_dec(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
- u16 dec_reset_reg;
+ unsigned int decimator;
+ char *dec_name = NULL;
+ char *widget_name = NULL;
+ char *temp;
+ int ret = 0;
+ u16 dec_reset_reg, tx_vol_ctl_reg, tx_mux_ctl_reg;
+ u8 dec_hpf_cut_of_freq;
pr_debug("%s %d\n", __func__, event);
+ widget_name = kstrndup(w->name, 15, GFP_KERNEL);
+ if (!widget_name)
+ return -ENOMEM;
+ temp = widget_name;
+
+ dec_name = strsep(&widget_name, " ");
+ widget_name = temp;
+ if (!dec_name) {
+ pr_err("%s: Invalid decimator = %s\n", __func__, w->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = kstrtouint(strpbrk(dec_name, "123456789"), 10, &decimator);
+ if (ret < 0) {
+ pr_err("%s: Invalid decimator = %s\n", __func__, dec_name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pr_debug("%s(): widget = %s dec_name = %s decimator = %u\n", __func__,
+ w->name, dec_name, decimator);
+
if (w->reg == TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL)
dec_reset_reg = TABLA_A_CDC_CLK_TX_RESET_B1_CTL;
else if (w->reg == TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL)
@@ -2327,14 +2398,68 @@
return -EINVAL;
}
+ tx_vol_ctl_reg = TABLA_A_CDC_TX1_VOL_CTL_CFG + 8 * (decimator -1);
+ tx_mux_ctl_reg = TABLA_A_CDC_TX1_MUX_CTL + 8 * (decimator - 1);
+
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+
+ // Enableable TX digital mute */
+ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
+
snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift,
1 << w->shift);
snd_soc_update_bits(codec, dec_reset_reg, 1 << w->shift, 0x0);
+
+ dec_hpf_cut_of_freq = snd_soc_read(codec, tx_mux_ctl_reg);
+
+ dec_hpf_cut_of_freq = (dec_hpf_cut_of_freq & 0x30) >> 4;
+
+ tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq =
+ dec_hpf_cut_of_freq;
+
+ if ((dec_hpf_cut_of_freq != CF_MIN_3DB_150HZ)) {
+
+ /* set cut of freq to CF_MIN_3DB_150HZ (0x1); */
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
+ CF_MIN_3DB_150HZ << 4);
+ }
+
+ /* enable HPF */
+ snd_soc_update_bits(codec, tx_mux_ctl_reg , 0x08, 0x00);
+
+ break;
+
+ case SND_SOC_DAPM_POST_PMU:
+
+ /* Disable TX digital mute */
+ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x00);
+
+ if (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq !=
+ CF_MIN_3DB_150HZ) {
+
+ schedule_delayed_work(&tx_hpf_work[decimator - 1].dwork,
+ msecs_to_jiffies(300));
+ }
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+
+ snd_soc_update_bits(codec, tx_vol_ctl_reg, 0x01, 0x01);
+ cancel_delayed_work_sync(&tx_hpf_work[decimator - 1].dwork);
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x08, 0x08);
+ snd_soc_update_bits(codec, tx_mux_ctl_reg, 0x30,
+ (tx_hpf_work[decimator - 1].tx_hpf_cut_of_freq) << 4);
+
break;
}
- return 0;
+out:
+ kfree(widget_name);
+ return ret;
}
static int tabla_codec_reset_interpolator(struct snd_soc_dapm_widget *w,
@@ -3858,34 +3983,54 @@
tabla_codec_enable_adc, SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_MUX_E("DEC1 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 0, 0,
- &dec1_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+ &dec1_mux, tabla_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("DEC2 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 1, 0,
- &dec2_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+ &dec2_mux, tabla_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("DEC3 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 2, 0,
- &dec3_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+ &dec3_mux, tabla_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("DEC4 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 3, 0,
- &dec4_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+ &dec4_mux, tabla_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("DEC5 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 4, 0,
- &dec5_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+ &dec5_mux, tabla_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("DEC6 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 5, 0,
- &dec6_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+ &dec6_mux, tabla_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("DEC7 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 6, 0,
- &dec7_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+ &dec7_mux, tabla_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("DEC8 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B1_CTL, 7, 0,
- &dec8_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+ &dec8_mux, tabla_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("DEC9 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL, 0, 0,
- &dec9_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+ &dec9_mux, tabla_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX_E("DEC10 MUX", TABLA_A_CDC_CLK_TX_CLK_EN_B2_CTL, 1, 0,
- &dec10_mux, tabla_codec_enable_dec, SND_SOC_DAPM_PRE_PMU),
+ &dec10_mux, tabla_codec_enable_dec,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
+ SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_MUX("ANC1 MUX", SND_SOC_NOPM, 0, 0, &anc1_mux),
SND_SOC_DAPM_MUX("ANC2 MUX", SND_SOC_NOPM, 0, 0, &anc2_mux),
@@ -6470,6 +6615,12 @@
dev_err(codec->dev, "Failed to allocate private data\n");
return -ENOMEM;
}
+ for (i = 0 ; i < NUM_DECIMATORS; i++) {
+ tx_hpf_work[i].tabla = tabla;
+ tx_hpf_work[i].decimator = i + 1;
+ INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
+ tx_hpf_corner_freq_callback);
+ }
/* Make sure mbhc micbias register addresses are zeroed out */
memset(&tabla->mbhc_bias_regs, 0,
diff --git a/sound/soc/msm/msm7201.c b/sound/soc/msm/msm7201.c
index 6408cef..f814a21 100644
--- a/sound/soc/msm/msm7201.c
+++ b/sound/soc/msm/msm7201.c
@@ -197,6 +197,12 @@
} req;
snd_rpc_ids.device = (int)ucontrol->value.integer.value[0];
+
+ if (ucontrol->value.integer.value[1] > 1)
+ ucontrol->value.integer.value[1] = 1;
+ if (ucontrol->value.integer.value[2] > 1)
+ ucontrol->value.integer.value[2] = 1;
+
req.hdr.type = 0;
req.hdr.rpc_vers = 2;
@@ -221,6 +227,8 @@
printk(KERN_INFO "snd device connected\n");
snd_mute_ear_mute = ucontrol->value.integer.value[1];
snd_mute_mic_mute = ucontrol->value.integer.value[2];
+ printk(KERN_ERR "%s: snd_mute_ear_mute =%d, snd_mute_mic_mute = %d\n",
+ __func__, snd_mute_ear_mute, snd_mute_mic_mute);
}
return rc;
@@ -251,7 +259,7 @@
static struct snd_kcontrol_new snd_msm_controls[] = {
MSM_EXT_TLV("PCM Playback Volume", 0, snd_msm_volume_info, \
snd_msm_volume_get, snd_msm_volume_put, 0, db_scale_linear),
- MSM_EXT("device", 1, snd_msm_device_info, snd_msm_device_get, \
+ MSM_EXT("device", 0, snd_msm_device_info, snd_msm_device_get, \
snd_msm_device_put, 0),
};
@@ -331,6 +339,8 @@
}
ret = msm_snd_rpc_connect();
+ snd_mute_ear_mute = 0;
+ snd_mute_mic_mute = 0;
return ret;
}
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 3063f3e..265df9e 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -60,6 +60,7 @@
[snd_soc_dapm_pre] = 0,
[snd_soc_dapm_supply] = 1,
[snd_soc_dapm_micbias] = 2,
+ [snd_soc_dapm_adc] = 3,
[snd_soc_dapm_mic] = 4,
[snd_soc_dapm_mux] = 5,
[snd_soc_dapm_virt_mux] = 5,
@@ -70,7 +71,6 @@
[snd_soc_dapm_pga] = 8,
[snd_soc_dapm_aif_in] = 8,
[snd_soc_dapm_aif_out] = 8,
- [snd_soc_dapm_adc] = 9,
[snd_soc_dapm_out_drv] = 10,
[snd_soc_dapm_hp] = 10,
[snd_soc_dapm_spk] = 10,