Merge "Bluetooth: LE sockets not ready until encrypted" into msm-3.0
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 76ff09c..3c87f8d 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -54,6 +54,7 @@
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
CONFIG_CP_ACCESS=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 3ddb0c9..cc33b8f 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -54,6 +54,7 @@
CONFIG_HIGH_RES_TIMERS=y
CONFIG_PREEMPT=y
CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
CONFIG_CP_ACCESS=y
CONFIG_ZBOOT_ROM_TEXT=0x0
CONFIG_ZBOOT_ROM_BSS=0x0
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index eca2ffa..22cf652 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -74,6 +74,7 @@
CONFIG_MSM_TZ_LOG=y
CONFIG_MSM_RPM_LOG=y
CONFIG_MSM_RPM_STATS_LOG=y
+CONFIG_MSM_IOMMU=y
CONFIG_MSM_BUS_SCALING=y
CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y
CONFIG_MSM_WATCHDOG=y
@@ -266,9 +267,7 @@
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_PMIC8XXX_PWRKEY=y
# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_HS=y
-# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
CONFIG_DIAG_CHAR=y
@@ -329,9 +328,10 @@
CONFIG_FB_MSM_MDP40=y
CONFIG_FB_MSM_OVERLAY=y
CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y
-CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
+CONFIG_FB_MSM_OVERLAY1_WRITEBACK=y
CONFIG_FB_MSM_MIPI_PANEL_DETECT=y
CONFIG_FB_MSM_HDMI_MSM_PANEL=y
+CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_SOUND=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 18e9085..c38c161 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -74,6 +74,7 @@
CONFIG_MSM_TZ_LOG=y
CONFIG_MSM_RPM_LOG=y
CONFIG_MSM_RPM_STATS_LOG=y
+CONFIG_MSM_IOMMU=y
CONFIG_MSM_BUS_SCALING=y
CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y
CONFIG_MSM_WATCHDOG=y
@@ -267,9 +268,7 @@
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_PMIC8XXX_PWRKEY=y
# CONFIG_LEGACY_PTYS is not set
-CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_HS=y
-# CONFIG_SERIAL_MSM_CLOCK_CONTROL is not set
CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
CONFIG_DIAG_CHAR=y
@@ -330,6 +329,7 @@
CONFIG_FB_MSM_MDP40=y
CONFIG_FB_MSM_OVERLAY=y
CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y
+CONFIG_FB_MSM_OVERLAY1_WRITEBACK=y
CONFIG_FB_MSM_WRITEBACK_MSM_PANEL=y
CONFIG_FB_MSM_MIPI_PANEL_DETECT=y
CONFIG_FB_MSM_HDMI_MSM_PANEL=y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 19a316e..2394c47 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -172,6 +172,7 @@
obj-$(CONFIG_ARCH_MSM8960) += rpm-regulator-8960.o
obj-$(CONFIG_ARCH_MSM9615) += rpm-regulator-9615.o
obj-$(CONFIG_ARCH_MSM8930) += rpm-regulator-8930.o
+obj-$(CONFIG_ARCH_APQ8064) += rpm-regulator-8960.o
endif
ifdef CONFIG_MSM_SUBSYSTEM_RESTART
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 02b2c33..470e836 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -463,25 +463,25 @@
static struct acpu_level acpu_freq_tbl_8960_kraitv2_slow[] = {
{ 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 950000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 950000 },
- { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 975000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 975000 },
- { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 1000000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 1000000 },
- { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 1025000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 1025000 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 1075000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1075000 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1100000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1100000 },
- { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(16), 1125000 },
- { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1125000 },
- { 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1175000 },
+ { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 975000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 975000 },
+ { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 1000000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 1000000 },
+ { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 1025000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 1025000 },
+ { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 1075000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 1075000 },
+ { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1100000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1100000 },
+ { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1125000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1125000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1175000 },
{ 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1175000 },
- { 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1200000 },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1200000 },
{ 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1200000 },
- { 1, { 1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1225000 },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1225000 },
{ 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1225000 },
- { 1, { 1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1237500 },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1237500 },
{ 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(16), 1237500 },
{ 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(16), 1250000 },
{ 0, { 0 } }
@@ -490,25 +490,25 @@
static struct acpu_level acpu_freq_tbl_8960_kraitv2_nom[] = {
{ 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 900000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 900000 },
- { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 925000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 925000 },
- { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 950000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 950000 },
- { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 975000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 975000 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 1025000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 1025000 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1050000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1050000 },
- { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(16), 1075000 },
- { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1075000 },
- { 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1125000 },
+ { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 925000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 925000 },
+ { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 950000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 950000 },
+ { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 975000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 975000 },
+ { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 1025000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 1025000 },
+ { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1050000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1050000 },
+ { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1075000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1075000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1125000 },
{ 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1125000 },
- { 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1150000 },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1150000 },
{ 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1150000 },
- { 1, { 1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1175000 },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1175000 },
{ 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1175000 },
- { 1, { 1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1187500 },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1187500 },
{ 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(16), 1187500 },
{ 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(16), 1200000 },
{ 0, { 0 } }
@@ -517,25 +517,25 @@
static struct acpu_level acpu_freq_tbl_8960_kraitv2_fast[] = {
{ 0, { STBY_KHZ, QSB, 0, 0, 0x00 }, L2(0), 850000 },
{ 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(1), 850000 },
- { 1, { 432000, HFPLL, 2, 0, 0x20 }, L2(6), 875000 },
- { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(6), 875000 },
- { 1, { 540000, HFPLL, 2, 0, 0x28 }, L2(6), 900000 },
- { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(6), 900000 },
- { 1, { 648000, HFPLL, 1, 0, 0x18 }, L2(6), 925000 },
- { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(6), 925000 },
- { 1, { 756000, HFPLL, 1, 0, 0x1C }, L2(11), 975000 },
- { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(11), 975000 },
- { 1, { 864000, HFPLL, 1, 0, 0x20 }, L2(11), 1000000 },
- { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(11), 1000000 },
- { 1, { 972000, HFPLL, 1, 0, 0x24 }, L2(16), 1025000 },
- { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(16), 1025000 },
- { 1, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1075000 },
+ { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(7), 875000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(7), 875000 },
+ { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(7), 900000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(7), 900000 },
+ { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(7), 925000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(7), 925000 },
+ { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(7), 975000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(7), 975000 },
+ { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(7), 1000000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(7), 1000000 },
+ { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(7), 1025000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(7), 1025000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(16), 1075000 },
{ 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(16), 1075000 },
- { 1, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1100000 },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(16), 1100000 },
{ 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(16), 1100000 },
- { 1, { 1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1125000 },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(16), 1125000 },
{ 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(16), 1125000 },
- { 1, { 1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1137500 },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(16), 1137500 },
{ 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(16), 1137500 },
{ 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(16), 1150000 },
{ 0, { 0 } }
@@ -1298,10 +1298,10 @@
case CPU_DYING:
case CPU_DYING_FROZEN:
/*
- * On Krait v1, the primary and secondary muxes must be set
- * to QSB before L2 power collapse and restored after.
+ * On Krait v1 and 8064v1, the primary and secondary muxes must
+ * be set to QSB before L2 power collapse and restored after.
*/
- if (cpu_is_krait_v1()) {
+ if (cpu_is_krait_v1() || cpu_is_apq8064()) {
prev_sec_src[cpu] = get_sec_clk_src(&scalable[cpu]);
prev_pri_src[cpu] = get_pri_clk_src(&scalable[cpu]);
set_sec_clk_src(&scalable[cpu], SEC_SRC_SEL_QSB);
@@ -1324,7 +1324,7 @@
break;
case CPU_STARTING:
case CPU_STARTING_FROZEN:
- if (cpu_is_krait_v1()) {
+ if (cpu_is_krait_v1() || cpu_is_apq8064()) {
set_sec_clk_src(&scalable[cpu], prev_sec_src[cpu]);
set_pri_clk_src(&scalable[cpu], prev_pri_src[cpu]);
}
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index 73758d0..5ead88c 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -28,10 +28,10 @@
#ifdef CONFIG_FB_MSM_TRIPLE_BUFFER
/* prim = 1366 x 768 x 3(bpp) x 3(pages) */
-#define MSM_FB_PRIM_BUF_SIZE roundup(1366 * 768 * 3 * 3, 0x10000)
+#define MSM_FB_PRIM_BUF_SIZE roundup(1376 * 768 * 4 * 3, 0x10000)
#else
/* prim = 1366 x 768 x 3(bpp) x 2(pages) */
-#define MSM_FB_PRIM_BUF_SIZE roundup(1366 * 768 * 3 * 2, 0x10000)
+#define MSM_FB_PRIM_BUF_SIZE roundup(1376 * 768 * 4 * 2, 0x10000)
#endif
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
@@ -58,22 +58,52 @@
#define MSM_FB_OVERLAY1_WRITEBACK_SIZE (0)
#endif /* CONFIG_FB_MSM_OVERLAY1_WRITEBACK */
+
static struct resource msm_fb_resources[] = {
{
.flags = IORESOURCE_DMA,
}
};
-#define SIMULATOR_PANAL_NAME "mipi_video_simulator"
-#define SIMULATOR_PANAL_NAME_LEN 20
+#define PANEL_NAME_MAX_LEN 30
#define LVDS_CHIMEI_PANEL_NAME "lvds_chimei_wxga"
-#define LVDS_CHIMEI_PANEL_NAME_LEN 16
+#define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME "mipi_video_toshiba_wsvga"
+#define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
+#define HDMI_PANEL_NAME "hdmi_msm"
+#define TVOUT_PANEL_NAME "tvout_msm"
static int msm_fb_detect_panel(const char *name)
{
- if (!strncmp(name, LVDS_CHIMEI_PANEL_NAME,
- LVDS_CHIMEI_PANEL_NAME_LEN))
+ if (machine_is_apq8064_liquid()) {
+ if (!strncmp(name, LVDS_CHIMEI_PANEL_NAME,
+ strnlen(LVDS_CHIMEI_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+
+#if !defined(CONFIG_FB_MSM_LVDS_MIPI_PANEL_DETECT) && \
+ !defined(CONFIG_FB_MSM_MIPI_PANEL_DETECT)
+ if (!strncmp(name, MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
+ strnlen(MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+#endif
+ } else if (machine_is_apq8064_mtp()) {
+ if (!strncmp(name, MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
+ strnlen(MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+ } else if (machine_is_apq8064_cdp()) {
+ if (!strncmp(name, LVDS_CHIMEI_PANEL_NAME,
+ strnlen(LVDS_CHIMEI_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
+ return 0;
+ }
+
+ if (!strncmp(name, HDMI_PANEL_NAME,
+ strnlen(HDMI_PANEL_NAME,
+ PANEL_NAME_MAX_LEN)))
return 0;
+
return -ENODEV;
}
@@ -105,15 +135,15 @@
#define MDP_VSYNC_GPIO 0
static int mdp_core_clk_rate_table[] = {
- 266667000,
- 266667000,
- 266667000,
- 266667000,
+ 200000000,
+ 200000000,
+ 200000000,
+ 200000000,
};
static struct msm_panel_common_pdata mdp_pdata = {
.gpio = MDP_VSYNC_GPIO,
- .mdp_core_clk_rate = 266667000,
+ .mdp_core_clk_rate = 200000000,
.mdp_core_clk_table = mdp_core_clk_rate_table,
.num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
.mdp_rev = MDP_REV_44,
@@ -136,9 +166,337 @@
#endif
}
+static bool dsi_power_on;
+static int mipi_dsi_panel_power(int on)
+{
+ static struct regulator *reg_lvs7, *reg_l2, *reg_l11, *reg_ext_3p3v;
+ static int gpio36, gpio25, gpio26, mpp3;
+ int rc;
+
+ pr_debug("%s: on=%d\n", __func__, on);
+
+ if (!dsi_power_on) {
+ reg_lvs7 = regulator_get(&msm_mipi_dsi1_device.dev,
+ "dsi1_vddio");
+ if (IS_ERR_OR_NULL(reg_lvs7)) {
+ pr_err("could not get 8921_lvs7, rc = %ld\n",
+ PTR_ERR(reg_lvs7));
+ return -ENODEV;
+ }
+
+ reg_l2 = regulator_get(&msm_mipi_dsi1_device.dev,
+ "dsi1_pll_vdda");
+ if (IS_ERR_OR_NULL(reg_l2)) {
+ pr_err("could not get 8921_l2, rc = %ld\n",
+ PTR_ERR(reg_l2));
+ return -ENODEV;
+ }
+
+ rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
+ if (rc) {
+ pr_err("set_voltage l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ reg_l11 = regulator_get(&msm_mipi_dsi1_device.dev,
+ "dsi1_avdd");
+ if (IS_ERR(reg_l11)) {
+ pr_err("could not get 8921_l11, rc = %ld\n",
+ PTR_ERR(reg_l11));
+ return -ENODEV;
+ }
+ rc = regulator_set_voltage(reg_l11, 3000000, 3000000);
+ if (rc) {
+ pr_err("set_voltage l11 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+
+ if (machine_is_apq8064_liquid()) {
+ reg_ext_3p3v = regulator_get(&msm_mipi_dsi1_device.dev,
+ "dsi1_vccs_3p3v");
+ if (IS_ERR_OR_NULL(reg_ext_3p3v)) {
+ pr_err("could not get reg_ext_3p3v, rc = %ld\n",
+ PTR_ERR(reg_ext_3p3v));
+ reg_ext_3p3v = NULL;
+ return -ENODEV;
+ }
+ mpp3 = PM8921_MPP_PM_TO_SYS(3);
+ rc = gpio_request(mpp3, "backlight_en");
+ if (rc) {
+ pr_err("request mpp3 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ }
+
+ gpio25 = PM8921_GPIO_PM_TO_SYS(25);
+ rc = gpio_request(gpio25, "disp_rst_n");
+ if (rc) {
+ pr_err("request gpio 25 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ gpio26 = PM8921_GPIO_PM_TO_SYS(26);
+ rc = gpio_request(gpio26, "pwm_backlight_ctrl");
+ if (rc) {
+ pr_err("request gpio 26 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ gpio36 = PM8921_GPIO_PM_TO_SYS(36); /* lcd1_pwr_en_n */
+ rc = gpio_request(gpio36, "lcd1_pwr_en_n");
+ if (rc) {
+ pr_err("request gpio 36 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ dsi_power_on = true;
+ }
+
+ if (on) {
+ rc = regulator_enable(reg_lvs7);
+ if (rc) {
+ pr_err("enable lvs7 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = regulator_set_optimum_mode(reg_l11, 110000);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l11 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_enable(reg_l11);
+ if (rc) {
+ pr_err("enable l11 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = regulator_set_optimum_mode(reg_l2, 100000);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_enable(reg_l2);
+ if (rc) {
+ pr_err("enable l2 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ if (machine_is_apq8064_liquid()) {
+ rc = regulator_enable(reg_ext_3p3v);
+ if (rc) {
+ pr_err("enable reg_ext_3p3v failed, rc=%d\n",
+ rc);
+ return -ENODEV;
+ }
+ gpio_set_value_cansleep(mpp3, 1);
+ }
+
+ gpio_set_value_cansleep(gpio36, 0);
+ gpio_set_value_cansleep(gpio25, 1);
+ } else {
+ gpio_set_value_cansleep(gpio25, 0);
+ gpio_set_value_cansleep(gpio36, 1);
+
+ if (machine_is_apq8064_liquid()) {
+ gpio_set_value_cansleep(mpp3, 0);
+
+ rc = regulator_disable(reg_ext_3p3v);
+ if (rc) {
+ pr_err("disable reg_ext_3p3v failed, rc=%d\n",
+ rc);
+ return -ENODEV;
+ }
+ }
+
+ rc = regulator_disable(reg_lvs7);
+ if (rc) {
+ pr_err("disable reg_lvs7 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_disable(reg_l2);
+ if (rc) {
+ pr_err("disable reg_l2 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+static struct mipi_dsi_platform_data mipi_dsi_pdata = {
+ .dsi_power_save = mipi_dsi_panel_power,
+};
+
+static bool lvds_power_on;
+static int lvds_panel_power(int on)
+{
+ static struct regulator *reg_lvs7, *reg_l2, *reg_ext_3p3v;
+ static int gpio36, gpio26, mpp3;
+ int rc;
+
+ pr_debug("%s: on=%d\n", __func__, on);
+
+ if (!lvds_power_on) {
+ reg_lvs7 = regulator_get(&msm_lvds_device.dev,
+ "lvds_vdda");
+ if (IS_ERR_OR_NULL(reg_lvs7)) {
+ pr_err("could not get 8921_lvs7, rc = %ld\n",
+ PTR_ERR(reg_lvs7));
+ return -ENODEV;
+ }
+
+ reg_l2 = regulator_get(&msm_lvds_device.dev,
+ "lvds_pll_vdda");
+ if (IS_ERR_OR_NULL(reg_l2)) {
+ pr_err("could not get 8921_l2, rc = %ld\n",
+ PTR_ERR(reg_l2));
+ return -ENODEV;
+ }
+
+ rc = regulator_set_voltage(reg_l2, 1200000, 1200000);
+ if (rc) {
+ pr_err("set_voltage l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+
+ reg_ext_3p3v = regulator_get(&msm_lvds_device.dev,
+ "lvds_vccs_3p3v");
+ if (IS_ERR_OR_NULL(reg_ext_3p3v)) {
+ pr_err("could not get reg_ext_3p3v, rc = %ld\n",
+ PTR_ERR(reg_ext_3p3v));
+ return -ENODEV;
+ }
+
+ gpio26 = PM8921_GPIO_PM_TO_SYS(26);
+ rc = gpio_request(gpio26, "pwm_backlight_ctrl");
+ if (rc) {
+ pr_err("request gpio 26 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ gpio36 = PM8921_GPIO_PM_TO_SYS(36); /* lcd1_pwr_en_n */
+ rc = gpio_request(gpio36, "lcd1_pwr_en_n");
+ if (rc) {
+ pr_err("request gpio 36 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ mpp3 = PM8921_MPP_PM_TO_SYS(3);
+ rc = gpio_request(mpp3, "backlight_en");
+ if (rc) {
+ pr_err("request mpp3 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ lvds_power_on = true;
+ }
+
+ if (on) {
+ rc = regulator_enable(reg_lvs7);
+ if (rc) {
+ pr_err("enable lvs7 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = regulator_set_optimum_mode(reg_l2, 100000);
+ if (rc < 0) {
+ pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+ rc = regulator_enable(reg_l2);
+ if (rc) {
+ pr_err("enable l2 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ rc = regulator_enable(reg_ext_3p3v);
+ if (rc) {
+ pr_err("enable reg_ext_3p3v failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+
+ gpio_set_value_cansleep(gpio36, 0);
+ gpio_set_value_cansleep(mpp3, 1);
+ } else {
+ gpio_set_value_cansleep(mpp3, 0);
+ gpio_set_value_cansleep(gpio36, 1);
+
+ rc = regulator_disable(reg_lvs7);
+ if (rc) {
+ pr_err("disable reg_lvs7 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_disable(reg_l2);
+ if (rc) {
+ pr_err("disable reg_l2 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = regulator_disable(reg_ext_3p3v);
+ if (rc) {
+ pr_err("disable reg_ext_3p3v failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+}
+
+static struct lcdc_platform_data lvds_pdata = {
+ .lcdc_power_save = lvds_panel_power,
+};
+
+#define LPM_CHANNEL 2
+static int lvds_chimei_gpio[] = {LPM_CHANNEL};
+
+static struct lvds_panel_platform_data lvds_chimei_pdata = {
+ .gpio = lvds_chimei_gpio,
+};
+
+static struct platform_device lvds_chimei_panel_device = {
+ .name = "lvds_chimei_wxga",
+ .id = 0,
+ .dev = {
+ .platform_data = &lvds_chimei_pdata,
+ }
+};
+
+static int dsi2lvds_gpio[2] = {
+ LPM_CHANNEL,/* Backlight PWM-ID=0 for PMIC-GPIO#24 */
+ 0x1F08 /* DSI2LVDS Bridge GPIO Output, mask=0x1f, out=0x08 */
+};
+static struct msm_panel_common_pdata mipi_dsi2lvds_pdata = {
+ .gpio_num = dsi2lvds_gpio,
+};
+
+static struct platform_device mipi_dsi2lvds_bridge_device = {
+ .name = "mipi_tc358764",
+ .id = 0,
+ .dev.platform_data = &mipi_dsi2lvds_pdata,
+};
+
+static int toshiba_gpio[] = {LPM_CHANNEL};
+static struct mipi_dsi_panel_platform_data toshiba_pdata = {
+ .gpio = toshiba_gpio,
+};
+
+static struct platform_device mipi_dsi_toshiba_panel_device = {
+ .name = "mipi_toshiba",
+ .id = 0,
+ .dev = {
+ .platform_data = &toshiba_pdata,
+ }
+};
+
void __init apq8064_init_fb(void)
{
platform_device_register(&msm_fb_device);
+ platform_device_register(&lvds_chimei_panel_device);
+
+ if (machine_is_apq8064_liquid())
+ platform_device_register(&mipi_dsi2lvds_bridge_device);
+ if (machine_is_apq8064_mtp())
+ platform_device_register(&mipi_dsi_toshiba_panel_device);
+
msm_fb_register_device("mdp", &mdp_pdata);
- msm_fb_register_device("lvds", NULL);
+ msm_fb_register_device("lvds", &lvds_pdata);
+ msm_fb_register_device("mipi_dsi", &mipi_dsi_pdata);
}
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index e769566..62b7f17 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -116,6 +116,18 @@
.pull = GPIOMUX_PULL_NONE,
};
+static struct gpiomux_setting gsbi3_suspended_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_KEEPER,
+};
+
+static struct gpiomux_setting gsbi3_active_cfg = {
+ .func = GPIOMUX_FUNC_1,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
#ifdef CONFIG_USB_EHCI_MSM_HSIC
static struct gpiomux_setting hsic_act_cfg = {
.func = GPIOMUX_FUNC_1,
@@ -130,6 +142,66 @@
.dir = GPIOMUX_OUT_LOW,
};
+static struct gpiomux_setting cyts_resout_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting cyts_resout_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting cyts_sleep_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting cyts_sleep_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting cyts_int_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting cyts_int_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct msm_gpiomux_config cyts_gpio_configs[] __initdata = {
+ { /* TS INTERRUPT */
+ .gpio = 6,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cyts_int_act_cfg,
+ [GPIOMUX_SUSPENDED] = &cyts_int_sus_cfg,
+ },
+ },
+ { /* TS SLEEP */
+ .gpio = 33,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cyts_sleep_act_cfg,
+ [GPIOMUX_SUSPENDED] = &cyts_sleep_sus_cfg,
+ },
+ },
+ { /* TS RESOUT */
+ .gpio = 7,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &cyts_resout_act_cfg,
+ [GPIOMUX_SUSPENDED] = &cyts_resout_sus_cfg,
+ },
+ },
+};
+
static struct msm_gpiomux_config apq8064_hsic_configs[] = {
{
.gpio = 88, /*HSIC_STROBE */
@@ -148,8 +220,46 @@
};
#endif
+static struct gpiomux_setting mxt_reset_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting mxt_reset_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_6MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting mxt_int_sus_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_2MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting mxt_int_act_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
static struct msm_gpiomux_config apq8064_gsbi_configs[] __initdata = {
{
+ .gpio = 8, /* GSBI3 I2C QUP SDA */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &gsbi3_active_cfg,
+ },
+ },
+ {
+ .gpio = 9, /* GSBI3 I2C QUP SCL */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gsbi3_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &gsbi3_active_cfg,
+ },
+ },
+ {
.gpio = 18, /* GSBI1 UART TX */
.settings = {
[GPIOMUX_SUSPENDED] = &gsbi1_uart_config,
@@ -352,6 +462,23 @@
}
};
+static struct msm_gpiomux_config apq8064_mxt_configs[] __initdata = {
+ { /* TS INTERRUPT */
+ .gpio = 6,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &mxt_int_act_cfg,
+ [GPIOMUX_SUSPENDED] = &mxt_int_sus_cfg,
+ },
+ },
+ { /* TS RESET */
+ .gpio = 33,
+ .settings = {
+ [GPIOMUX_ACTIVE] = &mxt_reset_act_cfg,
+ [GPIOMUX_SUSPENDED] = &mxt_reset_sus_cfg,
+ },
+ },
+};
+
void __init apq8064_init_gpiomux(void)
{
int rc;
@@ -386,8 +513,16 @@
msm_gpiomux_install(mdm_configs,
ARRAY_SIZE(mdm_configs));
+ if (machine_is_apq8064_mtp())
+ msm_gpiomux_install(cyts_gpio_configs,
+ ARRAY_SIZE(cyts_gpio_configs));
+
#ifdef CONFIG_USB_EHCI_MSM_HSIC
msm_gpiomux_install(apq8064_hsic_configs,
ARRAY_SIZE(apq8064_hsic_configs));
#endif
+
+ if (machine_is_apq8064_cdp() || machine_is_apq8064_liquid())
+ msm_gpiomux_install(apq8064_mxt_configs,
+ ARRAY_SIZE(apq8064_mxt_configs));
}
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index a8c5d48..0357c40 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -125,14 +125,14 @@
static struct kgsl_device_platform_data kgsl_3d0_pdata = {
.pwrlevel = {
{
- .gpu_freq = 400000000,
- .bus_freq = 4,
- .io_fraction = 0,
+ .gpu_freq = 192000000,
+ .bus_freq = 2,
+ .io_fraction = 100,
},
{
- .gpu_freq = 320000000,
- .bus_freq = 3,
- .io_fraction = 33,
+ .gpu_freq = 192000000,
+ .bus_freq = 2,
+ .io_fraction = 100,
},
{
.gpu_freq = 1920000000,
@@ -140,8 +140,9 @@
.io_fraction = 100,
},
{
- .gpu_freq = 27000000,
- .bus_freq = 0,
+ .gpu_freq = 192000000,
+ .bus_freq = 2,
+ .io_fraction = 100,
},
},
.init_level = 0,
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 5204e48..02dfc5e 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -86,6 +86,13 @@
PM_GPIO_STRENGTH_##_strength, \
PM_GPIO_FUNC_NORMAL, 0, 0)
+#define PM8921_GPIO_OUTPUT_BUFCONF(_gpio, _val, _strength, _bufconf) \
+ PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_OUT,\
+ PM_GPIO_OUT_BUF_##_bufconf, _val, \
+ PM_GPIO_PULL_NO, PM_GPIO_VIN_S4, \
+ PM_GPIO_STRENGTH_##_strength, \
+ PM_GPIO_FUNC_NORMAL, 0, 0)
+
#define PM8921_GPIO_INPUT(_gpio, _pull) \
PM8921_GPIO_INIT(_gpio, PM_GPIO_DIR_IN, PM_GPIO_OUT_BUF_CMOS, 0, \
_pull, PM_GPIO_VIN_S4, \
@@ -106,12 +113,18 @@
/* Initial PM8921 GPIO configurations */
static struct pm8xxx_gpio_init pm8921_gpios[] __initdata = {
+ PM8921_GPIO_OUTPUT(23, 0, HIGH), /* touchscreen power FET */
+ PM8921_GPIO_OUTPUT_BUFCONF(25, 0, LOW, CMOS), /* DISP_RESET_N */
+ PM8921_GPIO_OUTPUT_FUNC(26, 0, PM_GPIO_FUNC_2), /* Bl: Off, PWM mode */
+ PM8921_GPIO_OUTPUT_BUFCONF(36, 1, LOW, OPEN_DRAIN),
};
/* Initial PM8XXX MPP configurations */
static struct pm8xxx_mpp_init pm8xxx_mpps[] __initdata = {
+ PM8921_MPP_INIT(3, D_OUTPUT, PM8921_MPP_DIG_LEVEL_VPH, DOUT_CTRL_LOW),
/* External 5V regulator enable; shared by HDMI and USB_OTG switches. */
- PM8921_MPP_INIT(7, D_INPUT, PM8921_MPP_DIG_LEVEL_VPH, DIN_TO_INT),
+ PM8921_MPP_INIT(7, D_OUTPUT, PM8921_MPP_DIG_LEVEL_VPH, DOUT_CTRL_LOW),
+ PM8921_MPP_INIT(8, D_OUTPUT, PM8921_MPP_DIG_LEVEL_S4, DOUT_CTRL_LOW),
};
void __init apq8064_pm8xxx_gpio_mpp_init(void)
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index f3eebce..4e29feb 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -29,6 +29,8 @@
REGULATOR_SUPPLY("8921_l2", NULL),
REGULATOR_SUPPLY("mipi_csi_vdd", "4-001a"),
REGULATOR_SUPPLY("mipi_csi_vdd", "4-006c"),
+ REGULATOR_SUPPLY("lvds_pll_vdda", "lvds.0"),
+ REGULATOR_SUPPLY("dsi1_pll_vdda", "mipi_dsi.1"),
};
VREG_CONSUMERS(L3) = {
REGULATOR_SUPPLY("8921_l3", NULL),
@@ -62,6 +64,7 @@
};
VREG_CONSUMERS(L9) = {
REGULATOR_SUPPLY("8921_l9", NULL),
+ REGULATOR_SUPPLY("vdd", "3-0024"),
};
VREG_CONSUMERS(L10) = {
REGULATOR_SUPPLY("8921_l10", NULL),
@@ -69,6 +72,7 @@
};
VREG_CONSUMERS(L11) = {
REGULATOR_SUPPLY("8921_l11", NULL),
+ REGULATOR_SUPPLY("dsi1_avdd", "mipi_dsi.1"),
};
VREG_CONSUMERS(L12) = {
REGULATOR_SUPPLY("cam_vdig", "4-001a"),
@@ -97,6 +101,9 @@
};
VREG_CONSUMERS(L23) = {
REGULATOR_SUPPLY("8921_l23", NULL),
+ REGULATOR_SUPPLY("pll_vdd", "pil_qdsp6v4.1"),
+ REGULATOR_SUPPLY("pll_vdd", "pil_qdsp6v4.2"),
+
};
VREG_CONSUMERS(L24) = {
REGULATOR_SUPPLY("8921_l24", NULL),
@@ -106,6 +113,8 @@
REGULATOR_SUPPLY("8921_l25", NULL),
REGULATOR_SUPPLY("VDDD_CDC_D", "tabla-slim"),
REGULATOR_SUPPLY("CDC_VDDA_A_1P2V", "tabla-slim"),
+ REGULATOR_SUPPLY("VDDD_CDC_D", "tabla2x-slim"),
+ REGULATOR_SUPPLY("CDC_VDDA_A_1P2V", "tabla2x-slim"),
};
VREG_CONSUMERS(L26) = {
REGULATOR_SUPPLY("8921_l26", NULL),
@@ -113,9 +122,11 @@
};
VREG_CONSUMERS(L27) = {
REGULATOR_SUPPLY("8921_l27", NULL),
+ REGULATOR_SUPPLY("core_vdd", "pil_qdsp6v4.2"),
};
VREG_CONSUMERS(L28) = {
REGULATOR_SUPPLY("8921_l28", NULL),
+ REGULATOR_SUPPLY("core_vdd", "pil_qdsp6v4.1"),
};
VREG_CONSUMERS(S1) = {
REGULATOR_SUPPLY("8921_s1", NULL),
@@ -139,7 +150,13 @@
REGULATOR_SUPPLY("CDC_VDD_CP", "tabla-slim"),
REGULATOR_SUPPLY("CDC_VDDA_TX", "tabla-slim"),
REGULATOR_SUPPLY("CDC_VDDA_RX", "tabla-slim"),
+ REGULATOR_SUPPLY("VDDIO_CDC", "tabla2x-slim"),
+ REGULATOR_SUPPLY("CDC_VDD_CP", "tabla2x-slim"),
+ REGULATOR_SUPPLY("CDC_VDDA_TX", "tabla2x-slim"),
+ REGULATOR_SUPPLY("CDC_VDDA_RX", "tabla2x-slim"),
REGULATOR_SUPPLY("riva_vddpx", "wcnss_wlan.0"),
+ REGULATOR_SUPPLY("vcc_i2c", "3-005b"),
+ REGULATOR_SUPPLY("vcc_i2c", "3-0024"),
};
VREG_CONSUMERS(S5) = {
REGULATOR_SUPPLY("8921_s5", NULL),
@@ -177,6 +194,8 @@
VREG_CONSUMERS(LVS7) = {
REGULATOR_SUPPLY("8921_lvs7", NULL),
REGULATOR_SUPPLY("pll_vdd", "pil_riva"),
+ REGULATOR_SUPPLY("lvds_vdda", "lvds.0"),
+ REGULATOR_SUPPLY("dsi1_vddio", "mipi_dsi.1"),
};
VREG_CONSUMERS(USB_OTG) = {
REGULATOR_SUPPLY("8921_usb_otg", NULL),
@@ -199,10 +218,19 @@
VREG_CONSUMERS(EXT_5V) = {
REGULATOR_SUPPLY("ext_5v", NULL),
};
+VREG_CONSUMERS(EXT_MPP8) = {
+ REGULATOR_SUPPLY("ext_mpp8", NULL),
+};
VREG_CONSUMERS(EXT_3P3V) = {
REGULATOR_SUPPLY("ext_3p3v", NULL),
REGULATOR_SUPPLY("vdd_io", "spi0.2"),
REGULATOR_SUPPLY("mhl_ext_3p3v", "msm_otg"),
+ REGULATOR_SUPPLY("lvds_vccs_3p3v", "lvds.0"),
+ REGULATOR_SUPPLY("dsi1_vccs_3p3v", "mipi_dsi.1"),
+};
+VREG_CONSUMERS(EXT_TS_SW) = {
+ REGULATOR_SUPPLY("ext_ts_sw", NULL),
+ REGULATOR_SUPPLY("vdd_ana", "3-005b"),
};
#define PM8XXX_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
@@ -328,6 +356,97 @@
.consumer_supplies = vreg_consumers_##_id, \
}
+#define RPM_INIT(_id, _min_uV, _max_uV, _modes, _ops, _apply_uV, _default_uV, \
+ _peak_uA, _avg_uA, _pull_down, _pin_ctrl, _freq, _pin_fn, \
+ _force_mode, _power_mode, _state, _sleep_selectable, \
+ _always_on, _supply_regulator, _system_uA) \
+ { \
+ .init_data = { \
+ .constraints = { \
+ .valid_modes_mask = _modes, \
+ .valid_ops_mask = _ops, \
+ .min_uV = _min_uV, \
+ .max_uV = _max_uV, \
+ .input_uV = _min_uV, \
+ .apply_uV = _apply_uV, \
+ .always_on = _always_on, \
+ }, \
+ .num_consumer_supplies = \
+ ARRAY_SIZE(vreg_consumers_##_id), \
+ .consumer_supplies = vreg_consumers_##_id, \
+ .supply_regulator = _supply_regulator, \
+ }, \
+ .id = RPM_VREG_ID_PM8921_##_id, \
+ .default_uV = _default_uV, \
+ .peak_uA = _peak_uA, \
+ .avg_uA = _avg_uA, \
+ .pull_down_enable = _pull_down, \
+ .pin_ctrl = _pin_ctrl, \
+ .freq = RPM_VREG_FREQ_##_freq, \
+ .pin_fn = _pin_fn, \
+ .force_mode = _force_mode, \
+ .power_mode = _power_mode, \
+ .state = _state, \
+ .sleep_selectable = _sleep_selectable, \
+ .system_uA = _system_uA, \
+ }
+
+#define RPM_LDO(_id, _always_on, _pd, _sleep_selectable, _min_uV, _max_uV, \
+ _supply_regulator, _system_uA, _init_peak_uA) \
+ RPM_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_NORMAL \
+ | REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE \
+ | REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE \
+ | REGULATOR_CHANGE_DRMS, 0, _max_uV, _init_peak_uA, 0, _pd, \
+ RPM_VREG_PIN_CTRL_NONE, NONE, RPM_VREG_PIN_FN_8960_NONE, \
+ RPM_VREG_FORCE_MODE_8960_NONE, RPM_VREG_POWER_MODE_8960_PWM, \
+ RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
+ _supply_regulator, _system_uA)
+
+#define RPM_SMPS(_id, _always_on, _pd, _sleep_selectable, _min_uV, _max_uV, \
+ _supply_regulator, _system_uA, _freq) \
+ RPM_INIT(_id, _min_uV, _max_uV, REGULATOR_MODE_NORMAL \
+ | REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE \
+ | REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE \
+ | REGULATOR_CHANGE_DRMS, 0, _max_uV, _system_uA, 0, _pd, \
+ RPM_VREG_PIN_CTRL_NONE, _freq, RPM_VREG_PIN_FN_8960_NONE, \
+ RPM_VREG_FORCE_MODE_8960_NONE, RPM_VREG_POWER_MODE_8960_PWM, \
+ RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
+ _supply_regulator, _system_uA)
+
+#define RPM_VS(_id, _always_on, _pd, _sleep_selectable, _supply_regulator) \
+ RPM_INIT(_id, 0, 0, 0, REGULATOR_CHANGE_STATUS, 0, 0, 1000, 1000, _pd, \
+ RPM_VREG_PIN_CTRL_NONE, NONE, RPM_VREG_PIN_FN_8960_NONE, \
+ RPM_VREG_FORCE_MODE_8960_NONE, RPM_VREG_POWER_MODE_8960_PWM, \
+ RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
+ _supply_regulator, 0)
+
+#define RPM_NCP(_id, _always_on, _sleep_selectable, _min_uV, _max_uV, \
+ _supply_regulator, _freq) \
+ RPM_INIT(_id, _min_uV, _max_uV, 0, REGULATOR_CHANGE_VOLTAGE \
+ | REGULATOR_CHANGE_STATUS, 0, _max_uV, 1000, 1000, 0, \
+ RPM_VREG_PIN_CTRL_NONE, _freq, RPM_VREG_PIN_FN_8960_NONE, \
+ RPM_VREG_FORCE_MODE_8960_NONE, RPM_VREG_POWER_MODE_8960_PWM, \
+ RPM_VREG_STATE_OFF, _sleep_selectable, _always_on, \
+ _supply_regulator, 0)
+
+/* Pin control initialization */
+#define RPM_PC_INIT(_id, _always_on, _pin_fn, _pin_ctrl, _supply_regulator) \
+ { \
+ .init_data = { \
+ .constraints = { \
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS, \
+ .always_on = _always_on, \
+ }, \
+ .num_consumer_supplies = \
+ ARRAY_SIZE(vreg_consumers_##_id##_PC), \
+ .consumer_supplies = vreg_consumers_##_id##_PC, \
+ .supply_regulator = _supply_regulator, \
+ }, \
+ .id = RPM_VREG_ID_PM8921_##_id##_PC, \
+ .pin_fn = RPM_VREG_PIN_FN_8960_##_pin_fn, \
+ .pin_ctrl = _pin_ctrl, \
+ }
+
/* GPIO regulator constraints */
struct gpio_regulator_platform_data
apq8064_gpio_regulator_pdata[] __devinitdata = {
@@ -335,6 +454,10 @@
GPIO_VREG(EXT_5V, "ext_5v", "ext_5v_en", PM8921_MPP_PM_TO_SYS(7), NULL),
GPIO_VREG(EXT_3P3V, "ext_3p3v", "ext_3p3v_en",
APQ8064_EXT_3P3V_REG_EN_GPIO, NULL),
+ GPIO_VREG(EXT_TS_SW, "ext_ts_sw", "ext_ts_sw_en",
+ PM8921_GPIO_PM_TO_SYS(23), "ext_3p3v"),
+ GPIO_VREG(EXT_MPP8, "ext_mpp8", "ext_mpp8_en",
+ PM8921_MPP_PM_TO_SYS(8), NULL),
};
/* SAW regulator constraints */
@@ -354,69 +477,71 @@
struct pm8xxx_regulator_platform_data
msm8064_pm8921_regulator_pdata[] __devinitdata = {
/*
- * ID name always_on pd min_uV max_uV en_t supply
+ * ID name always_on pd min_uV max_uV en_t supply
* system_uA reg_ID
*/
- PM8XXX_SMPS(S1, "8921_s1", 1, 1, 1225000, 1225000, 500, NULL, 100000,
- 1),
- PM8XXX_SMPS(S2, "8921_s2", 0, 1, 1300000, 1300000, 500, NULL, 0, 2),
- PM8XXX_SMPS(S3, "8921_s3", 1, 1, 1150000, 1150000, 500, NULL, 100000,
- 3),
- PM8XXX_SMPS(S4, "8921_s4", 1, 1, 1800000, 1800000, 500, NULL, 100000,
- 4),
- PM8XXX_SMPS(S7, "8921_s7", 0, 1, 1300000, 1300000, 500, NULL, 100000,
- 5),
-
- PM8XXX_LDO(L1, "8921_l1", 1, 1, 1100000, 1100000, 200, "8921_s4", 0,
- 6),
- PM8XXX_LDO(L2, "8921_l2", 0, 1, 1200000, 1200000, 200, "8921_s4", 0,
- 7),
- PM8XXX_LDO(L3, "8921_l3", 0, 1, 3075000, 3075000, 200, NULL, 0, 8),
- PM8XXX_LDO(L4, "8921_l4", 1, 1, 1800000, 1800000, 200, NULL, 10000,
- 9),
- PM8XXX_LDO(L5, "8921_l5", 0, 1, 2950000, 2950000, 200, NULL, 0, 10),
- PM8XXX_LDO(L6, "8921_l6", 0, 1, 2950000, 2950000, 200, NULL, 0, 11),
- PM8XXX_LDO(L7, "8921_l7", 0, 1, 1850000, 2950000, 200, NULL, 0, 12),
- PM8XXX_LDO(L8, "8921_l8", 0, 1, 2800000, 2800000, 200, NULL, 0, 13),
- PM8XXX_LDO(L9, "8921_l9", 0, 1, 2850000, 2850000, 200, NULL, 0, 14),
- PM8XXX_LDO(L10, "8921_l10", 0, 1, 2900000, 2900000, 200, NULL, 0, 15),
- PM8XXX_LDO(L11, "8921_l11", 0, 1, 3000000, 3000000, 200, NULL, 0, 16),
- PM8XXX_LDO(L12, "8921_l12", 0, 1, 1200000, 1200000, 200, "8921_s4", 0,
- 17),
- PM8XXX_LDO(L14, "8921_l14", 0, 1, 1800000, 1800000, 200, NULL, 0, 18),
- PM8XXX_LDO(L15, "8921_l15", 0, 1, 1800000, 2950000, 200, NULL, 0, 19),
- PM8XXX_LDO(L16, "8921_l16", 0, 1, 2800000, 2800000, 200, NULL, 0, 20),
- PM8XXX_LDO(L17, "8921_l17", 0, 1, 2000000, 2000000, 200, NULL, 0, 21),
- PM8XXX_LDO(L18, "8921_l18", 0, 1, 1300000, 1800000, 200, "8921_s4", 0,
- 22),
- PM8XXX_LDO(L22, "8921_l22", 0, 1, 2600000, 2600000, 200, NULL, 0, 23),
- PM8XXX_LDO(L23, "8921_l23", 0, 1, 1800000, 1800000, 200, NULL, 0, 24),
- PM8XXX_NLDO1200(L24, "8921_l24", 1, 1, 1150000, 1150000, 200, "8921_s1",
- 10000, 25),
- PM8XXX_NLDO1200(L25, "8921_l25", 1, 1, 1225000, 1225000, 200, "8921_s1",
- 10000, 26),
PM8XXX_NLDO1200(L26, "8921_l26", 0, 1, 1050000, 1050000, 200, "8921_s7",
- 0, 27),
- PM8XXX_NLDO1200(L27, "8921_l27", 0, 1, 1100000, 1100000, 200, "8921_s7",
- 0, 28),
- PM8XXX_NLDO1200(L28, "8921_l28", 0, 1, 1050000, 1050000, 200, "8921_s7",
- 0, 29),
+ 0, 1),
- /* ID name always_on pd en_t supply reg_ID */
- PM8XXX_VS(LVS1, "8921_lvs1", 0, 1, 0, "8921_s4", 30),
- PM8XXX_VS300(LVS2, "8921_lvs2", 0, 1, 0, "8921_s1", 31),
- PM8XXX_VS(LVS3, "8921_lvs3", 0, 1, 0, "8921_s4", 32),
- PM8XXX_VS(LVS4, "8921_lvs4", 0, 1, 0, "8921_s4", 33),
- PM8XXX_VS(LVS5, "8921_lvs5", 0, 1, 0, "8921_s4", 34),
- PM8XXX_VS(LVS6, "8921_lvs6", 0, 1, 0, "8921_s4", 35),
- PM8XXX_VS(LVS7, "8921_lvs7", 1, 1, 0, "8921_s4", 36),
+ /* ID name always_on pd en_t supply reg_ID */
+ PM8XXX_VS300(USB_OTG, "8921_usb_otg", 0, 0, 0, "ext_5v", 2),
+ PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1, 0, "ext_5v", 3),
+};
- PM8XXX_VS300(USB_OTG, "8921_usb_otg", 0, 0, 0, "ext_5v", 37),
- PM8XXX_VS300(HDMI_MVS, "8921_hdmi_mvs", 0, 1, 0, "ext_5v", 38),
+static struct rpm_regulator_init_data
+apq8064_rpm_regulator_init_data[] __devinitdata = {
+ /* ID a_on pd ss min_uV max_uV supply sys_uA freq */
+ RPM_SMPS(S1, 1, 1, 0, 1225000, 1225000, NULL, 100000, 3p20),
+ RPM_SMPS(S2, 0, 1, 0, 1300000, 1300000, NULL, 0, 1p60),
+ RPM_SMPS(S3, 0, 1, 1, 500000, 1150000, NULL, 100000, 4p80),
+ RPM_SMPS(S4, 1, 1, 0, 1800000, 1800000, NULL, 100000, 1p60),
+ RPM_SMPS(S7, 0, 1, 0, 1300000, 1300000, NULL, 100000, 3p20),
- /* ID name always_on min_uV max_uV en_t supply reg_ID */
- PM8XXX_NCP(NCP, "8921_ncp", 0, 1800000, 1800000, 200, "8921_l6", 39),
+ /* ID a_on pd ss min_uV max_uV supply sys_uA init_ip */
+ RPM_LDO(L1, 1, 1, 0, 1100000, 1100000, "8921_s4", 0, 10000),
+ RPM_LDO(L2, 0, 1, 0, 1200000, 1200000, "8921_s4", 0, 0),
+ RPM_LDO(L3, 0, 1, 0, 3075000, 3075000, NULL, 0, 0),
+ RPM_LDO(L4, 1, 1, 0, 1800000, 1800000, NULL, 10000, 10000),
+ RPM_LDO(L5, 0, 1, 0, 2950000, 2950000, NULL, 0, 0),
+ RPM_LDO(L6, 0, 1, 0, 2950000, 2950000, NULL, 0, 0),
+ RPM_LDO(L7, 0, 1, 0, 1850000, 2950000, NULL, 0, 0),
+ RPM_LDO(L8, 0, 1, 0, 2800000, 2800000, NULL, 0, 0),
+ RPM_LDO(L9, 0, 1, 0, 2850000, 2850000, NULL, 0, 0),
+ RPM_LDO(L10, 0, 1, 0, 2900000, 2900000, NULL, 0, 0),
+ RPM_LDO(L11, 0, 1, 0, 3000000, 3000000, NULL, 0, 0),
+ RPM_LDO(L12, 0, 1, 0, 1200000, 1200000, "8921_s4", 0, 0),
+ RPM_LDO(L14, 0, 1, 0, 1800000, 1800000, NULL, 0, 0),
+ RPM_LDO(L15, 0, 1, 0, 1800000, 2950000, NULL, 0, 0),
+ RPM_LDO(L16, 0, 1, 0, 2800000, 2800000, NULL, 0, 0),
+ RPM_LDO(L17, 0, 1, 0, 2000000, 2000000, NULL, 0, 0),
+ RPM_LDO(L18, 0, 1, 0, 1300000, 1800000, "8921_s4", 0, 0),
+ RPM_LDO(L22, 0, 1, 0, 2600000, 2600000, NULL, 0, 0),
+ RPM_LDO(L23, 0, 1, 0, 1800000, 1800000, NULL, 0, 0),
+ RPM_LDO(L24, 0, 1, 1, 750000, 1150000, "8921_s1", 10000, 10000),
+ RPM_LDO(L25, 1, 1, 0, 1225000, 1225000, "8921_s1", 10000, 10000),
+ RPM_LDO(L27, 0, 1, 0, 1100000, 1100000, "8921_s7", 0, 0),
+ RPM_LDO(L28, 0, 1, 0, 1050000, 1050000, "8921_s7", 0, 0),
+
+ /* ID a_on pd ss supply */
+ RPM_VS(LVS1, 0, 1, 0, "8921_s4"),
+ RPM_VS(LVS2, 0, 1, 0, "8921_s1"),
+ RPM_VS(LVS3, 0, 1, 0, "8921_s4"),
+ RPM_VS(LVS4, 0, 1, 0, "8921_s4"),
+ RPM_VS(LVS5, 0, 1, 0, "8921_s4"),
+ RPM_VS(LVS6, 0, 1, 0, "8921_s4"),
+ RPM_VS(LVS7, 1, 1, 1, "8921_s4"),
+
+ /* ID a_on ss min_uV max_uV supply freq */
+ RPM_NCP(NCP, 0, 0, 1800000, 1800000, "8921_l6", 1p60),
};
int msm8064_pm8921_regulator_pdata_len __devinitdata =
ARRAY_SIZE(msm8064_pm8921_regulator_pdata);
+
+struct rpm_regulator_platform_data apq8064_rpm_regulator_pdata __devinitdata = {
+ .init_data = apq8064_rpm_regulator_init_data,
+ .num_regulators = ARRAY_SIZE(apq8064_rpm_regulator_init_data),
+ .version = RPM_VREG_VERSION_8960,
+ .vreg_id_vdd_mem = RPM_VREG_ID_PM8921_L24,
+ .vreg_id_vdd_dig = RPM_VREG_ID_PM8921_S3,
+};
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 92e8f1b..af2e18c 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -24,6 +24,8 @@
#include <linux/platform_data/qcom_crypto_device.h>
#include <linux/ion.h>
#include <linux/memory.h>
+#include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/cyttsp.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <asm/hardware/gic.h>
@@ -525,6 +527,207 @@
},
};
+/* configuration data for mxt1386e using V2.1 firmware */
+static const u8 mxt1386e_config_data_v2_1[] = {
+ /* T6 Object */
+ 0, 0, 0, 0, 0, 0,
+ /* T38 Object */
+ 14, 0, 0, 24, 1, 12, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ /* T7 Object */
+ 100, 16, 50,
+ /* T8 Object */
+ 25, 0, 20, 20, 0, 0, 20, 50, 0, 0,
+ /* T9 Object */
+ 131, 0, 0, 26, 42, 0, 32, 80, 2, 5,
+ 0, 5, 5, 0, 10, 30, 10, 10, 255, 2,
+ 85, 5, 10, 10, 10, 10, 135, 55, 70, 40,
+ 10, 5, 0, 0, 0,
+ /* T18 Object */
+ 0, 0,
+ /* T24 Object */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* T25 Object */
+ 3, 0, 60, 115, 156, 99,
+ /* T27 Object */
+ 0, 0, 0, 0, 0, 0, 0,
+ /* T40 Object */
+ 0, 0, 0, 0, 0,
+ /* T42 Object */
+ 2, 0, 255, 0, 255, 0, 0, 0, 0, 0,
+ /* T43 Object */
+ 0, 0, 0, 0, 0, 0, 0, 64, 0, 8,
+ 16,
+ /* T46 Object */
+ 64, 0, 20, 20, 0, 0, 0, 0, 0,
+ /* T47 Object */
+ 0, 0, 0, 0, 0, 0, 3, 64, 66, 0,
+ /* T48 Object */
+ 31, 64, 64, 0, 0, 0, 0, 0, 0, 0,
+ 48, 40, 0, 10, 10, 0, 0, 100, 10, 80,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 52, 0, 12, 0, 17, 0, 1, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0,
+ /* T56 Object */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 2, 99, 33, 0, 149, 24, 193, 255, 255, 255,
+ 255,
+};
+
+#define MXT_TS_GPIO_IRQ 6
+#define MXT_TS_PWR_EN_GPIO PM8921_GPIO_PM_TO_SYS(23)
+#define MXT_TS_RESET_GPIO 33
+
+static struct mxt_config_info mxt_config_array[] = {
+ {
+ .config = mxt1386e_config_data_v2_1,
+ .config_length = ARRAY_SIZE(mxt1386e_config_data_v2_1),
+ .family_id = 0xA0,
+ .variant_id = 0x7,
+ .version = 0x21,
+ .build = 0xAA,
+ },
+};
+
+static struct mxt_platform_data mxt_platform_data = {
+ .config_array = mxt_config_array,
+ .config_array_size = ARRAY_SIZE(mxt_config_array),
+ .x_size = 1365,
+ .y_size = 767,
+ .irqflags = IRQF_TRIGGER_FALLING,
+ .i2c_pull_up = true,
+ .reset_gpio = MXT_TS_RESET_GPIO,
+ .irq_gpio = MXT_TS_GPIO_IRQ,
+};
+
+static struct i2c_board_info mxt_device_info[] __initdata = {
+ {
+ I2C_BOARD_INFO("atmel_mxt_ts", 0x5b),
+ .platform_data = &mxt_platform_data,
+ .irq = MSM_GPIO_TO_INT(MXT_TS_GPIO_IRQ),
+ },
+};
+#define CYTTSP_TS_GPIO_IRQ 6
+#define CYTTSP_TS_GPIO_RESOUT 7
+#define CYTTSP_TS_GPIO_SLEEP 33
+
+static ssize_t tma340_vkeys_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, 200,
+ __stringify(EV_KEY) ":" __stringify(KEY_BACK) ":73:1120:97:97"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_MENU) ":230:1120:97:97"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_HOME) ":389:1120:97:97"
+ ":" __stringify(EV_KEY) ":" __stringify(KEY_SEARCH) ":544:1120:97:97"
+ "\n");
+}
+
+static struct kobj_attribute tma340_vkeys_attr = {
+ .attr = {
+ .mode = S_IRUGO,
+ },
+ .show = &tma340_vkeys_show,
+};
+
+static struct attribute *tma340_properties_attrs[] = {
+ &tma340_vkeys_attr.attr,
+ NULL
+};
+
+static struct attribute_group tma340_properties_attr_group = {
+ .attrs = tma340_properties_attrs,
+};
+
+static int cyttsp_platform_init(struct i2c_client *client)
+{
+ int rc = 0;
+ static struct kobject *tma340_properties_kobj;
+
+ tma340_vkeys_attr.attr.name = "virtualkeys.cyttsp-i2c";
+ tma340_properties_kobj = kobject_create_and_add("board_properties",
+ NULL);
+ if (tma340_properties_kobj)
+ rc = sysfs_create_group(tma340_properties_kobj,
+ &tma340_properties_attr_group);
+ if (!tma340_properties_kobj || rc)
+ pr_err("%s: failed to create board_properties\n",
+ __func__);
+
+ return 0;
+}
+
+static struct cyttsp_regulator cyttsp_regulator_data[] = {
+ {
+ .name = "vdd",
+ .min_uV = CY_TMA300_VTG_MIN_UV,
+ .max_uV = CY_TMA300_VTG_MAX_UV,
+ .hpm_load_uA = CY_TMA300_CURR_24HZ_UA,
+ .lpm_load_uA = CY_TMA300_CURR_24HZ_UA,
+ },
+ {
+ .name = "vcc_i2c",
+ .min_uV = CY_I2C_VTG_MIN_UV,
+ .max_uV = CY_I2C_VTG_MAX_UV,
+ .hpm_load_uA = CY_I2C_CURR_UA,
+ .lpm_load_uA = CY_I2C_CURR_UA,
+ },
+};
+
+static struct cyttsp_platform_data cyttsp_pdata = {
+ .panel_maxx = 634,
+ .panel_maxy = 1166,
+ .disp_maxx = 599,
+ .disp_maxy = 1023,
+ .disp_minx = 0,
+ .disp_miny = 0,
+ .flags = 0x01,
+ .gen = CY_GEN3,
+ .use_st = CY_USE_ST,
+ .use_mt = CY_USE_MT,
+ .use_hndshk = CY_SEND_HNDSHK,
+ .use_trk_id = CY_USE_TRACKING_ID,
+ .use_sleep = CY_USE_DEEP_SLEEP_SEL,
+ .use_gestures = CY_USE_GESTURES,
+ .fw_fname = "cyttsp_8064_mtp.hex",
+ /* change act_intrvl to customize the Active power state
+ * scanning/processing refresh interval for Operating mode
+ */
+ .act_intrvl = CY_ACT_INTRVL_DFLT,
+ /* change tch_tmout to customize the touch timeout for the
+ * Active power state for Operating mode
+ */
+ .tch_tmout = CY_TCH_TMOUT_DFLT,
+ /* change lp_intrvl to customize the Low Power power state
+ * scanning/processing refresh interval for Operating mode
+ */
+ .lp_intrvl = CY_LP_INTRVL_DFLT,
+ .sleep_gpio = CYTTSP_TS_GPIO_SLEEP,
+ .resout_gpio = CYTTSP_TS_GPIO_RESOUT,
+ .irq_gpio = CYTTSP_TS_GPIO_IRQ,
+ .regulator_info = cyttsp_regulator_data,
+ .num_regulators = ARRAY_SIZE(cyttsp_regulator_data),
+ .init = cyttsp_platform_init,
+ .correct_fw_ver = 17,
+};
+
+static struct i2c_board_info cyttsp_info[] __initdata = {
+ {
+ I2C_BOARD_INFO(CY_I2C_NAME, 0x24),
+ .platform_data = &cyttsp_pdata,
+ .irq = MSM_GPIO_TO_INT(CYTTSP_TS_GPIO_IRQ),
+ },
+};
+
#if defined(CONFIG_CRYPTO_DEV_QCRYPTO) || \
defined(CONFIG_CRYPTO_DEV_QCRYPTO_MODULE) || \
defined(CONFIG_CRYPTO_DEV_QCEDEV) || \
@@ -1085,6 +1288,15 @@
},
};
+static struct platform_device apq8064_device_ext_mpp8_vreg __devinitdata = {
+ .name = GPIO_REGULATOR_DEV_NAME,
+ .id = PM8921_MPP_PM_TO_SYS(8),
+ .dev = {
+ .platform_data
+ = &apq8064_gpio_regulator_pdata[GPIO_VREG_ID_EXT_MPP8],
+ },
+};
+
static struct platform_device apq8064_device_ext_3p3v_vreg __devinitdata = {
.name = GPIO_REGULATOR_DEV_NAME,
.id = APQ8064_EXT_3P3V_REG_EN_GPIO,
@@ -1094,13 +1306,32 @@
},
};
+static struct platform_device apq8064_device_ext_ts_sw_vreg __devinitdata = {
+ .name = GPIO_REGULATOR_DEV_NAME,
+ .id = PM8921_GPIO_PM_TO_SYS(23),
+ .dev = {
+ .platform_data
+ = &apq8064_gpio_regulator_pdata[GPIO_VREG_ID_EXT_TS_SW],
+ },
+};
+
+static struct platform_device apq8064_device_rpm_regulator __devinitdata = {
+ .name = "rpm-regulator",
+ .id = -1,
+ .dev = {
+ .platform_data = &apq8064_rpm_regulator_pdata,
+ },
+};
+
static struct platform_device *common_devices[] __initdata = {
&apq8064_device_dmov,
+ &apq8064_device_qup_i2c_gsbi3,
&apq8064_device_qup_i2c_gsbi4,
&apq8064_device_qup_spi_gsbi5,
- &apq8064_slim_ctrl,
&apq8064_device_ext_5v_vreg,
+ &apq8064_device_ext_mpp8_vreg,
&apq8064_device_ext_3p3v_vreg,
+ &apq8064_device_ext_ts_sw_vreg,
&apq8064_device_ssbi_pmic1,
&apq8064_device_ssbi_pmic2,
&msm_device_smd_apq8064,
@@ -1221,6 +1452,11 @@
/* add more slimbus slaves as needed */
};
+static struct msm_i2c_platform_data apq8064_i2c_qup_gsbi3_pdata = {
+ .clk_freq = 100000,
+ .src_clk_rate = 24000000,
+};
+
static struct msm_i2c_platform_data apq8064_i2c_qup_gsbi4_pdata = {
.clk_freq = 100000,
.src_clk_rate = 24000000,
@@ -1228,6 +1464,8 @@
static void __init apq8064_i2c_init(void)
{
+ apq8064_device_qup_i2c_gsbi3.dev.platform_data =
+ &apq8064_i2c_qup_gsbi3_pdata;
apq8064_device_qup_i2c_gsbi4.dev.platform_data =
&apq8064_i2c_qup_gsbi4_pdata;
}
@@ -1261,15 +1499,74 @@
msm_clock_init(&apq8064_clock_init_data);
}
+#define I2C_SURF 1
+#define I2C_FFA (1 << 1)
+#define I2C_RUMI (1 << 2)
+#define I2C_SIM (1 << 3)
+#define I2C_LIQUID (1 << 4)
+
+struct i2c_registry {
+ u8 machs;
+ int bus;
+ struct i2c_board_info *info;
+ int len;
+};
+
+static struct i2c_registry apq8064_i2c_devices[] __initdata = {
+ {
+ I2C_SURF | I2C_LIQUID,
+ APQ_8064_GSBI3_QUP_I2C_BUS_ID,
+ mxt_device_info,
+ ARRAY_SIZE(mxt_device_info),
+ },
+ {
+ I2C_FFA,
+ APQ_8064_GSBI3_QUP_I2C_BUS_ID,
+ cyttsp_info,
+ ARRAY_SIZE(cyttsp_info),
+ },
+};
+
+static void __init register_i2c_devices(void)
+{
+ u8 mach_mask = 0;
+ int i;
+
+ /* Build the matching 'supported_machs' bitmask */
+ if (machine_is_apq8064_cdp())
+ mach_mask = I2C_SURF;
+ else if (machine_is_apq8064_mtp())
+ mach_mask = I2C_FFA;
+ else if (machine_is_apq8064_liquid())
+ mach_mask = I2C_LIQUID;
+ else if (machine_is_apq8064_rumi3())
+ mach_mask = I2C_RUMI;
+ else if (machine_is_apq8064_sim())
+ mach_mask = I2C_SIM;
+ else
+ pr_err("unmatched machine ID in register_i2c_devices\n");
+
+ /* Run the array and install devices as appropriate */
+ for (i = 0; i < ARRAY_SIZE(apq8064_i2c_devices); ++i) {
+ if (apq8064_i2c_devices[i].machs & mach_mask)
+ i2c_register_board_info(apq8064_i2c_devices[i].bus,
+ apq8064_i2c_devices[i].info,
+ apq8064_i2c_devices[i].len);
+ }
+}
+
static void __init apq8064_common_init(void)
{
if (socinfo_init() < 0)
pr_err("socinfo_init() failed!\n");
BUG_ON(msm_rpm_init(&apq8064_rpm_data));
BUG_ON(msm_rpmrs_levels_init(&msm_rpmrs_data));
+ regulator_suppress_info_printing();
+ platform_device_register(&apq8064_device_rpm_regulator);
apq8064_clock_init();
apq8064_init_gpiomux();
apq8064_i2c_init();
+ register_i2c_devices();
apq8064_device_qup_spi_gsbi5.dev.platform_data =
&apq8064_qup_spi_gsbi5_pdata;
@@ -1282,6 +1579,12 @@
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
apq8064_pm8xxx_gpio_mpp_init();
apq8064_init_mmc();
+
+ if (machine_is_apq8064_mtp()) {
+ mdm_8064_device.dev.platform_data = &mdm_platform_data;
+ platform_device_register(&mdm_8064_device);
+ }
+ platform_device_register(&apq8064_slim_ctrl);
slim_register_board_info(apq8064_slim_devices,
ARRAY_SIZE(apq8064_slim_devices));
msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
@@ -1292,11 +1595,6 @@
msm_cpuidle_set_states(msm_cstates, ARRAY_SIZE(msm_cstates),
msm_pm_data);
BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
-
- if (machine_is_apq8064_mtp()) {
- mdm_8064_device.dev.platform_data = &mdm_platform_data;
- platform_device_register(&mdm_8064_device);
- }
}
static void __init apq8064_allocate_memory_regions(void)
@@ -1330,7 +1628,10 @@
ethernet_init();
platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+ apq8064_init_fb();
apq8064_init_gpu();
+ platform_add_devices(msm_footswitch_devices,
+ msm_num_footswitch_devices);
}
MACHINE_START(APQ8064_SIM, "QCT APQ8064 SIMULATOR")
@@ -1359,6 +1660,7 @@
.handle_irq = gic_handle_irq,
.timer = &msm_timer,
.init_machine = apq8064_cdp_init,
+ .init_early = apq8064_allocate_memory_regions,
MACHINE_END
MACHINE_START(APQ8064_MTP, "QCT APQ8064 MTP")
@@ -1368,6 +1670,7 @@
.handle_irq = gic_handle_irq,
.timer = &msm_timer,
.init_machine = apq8064_cdp_init,
+ .init_early = apq8064_allocate_memory_regions,
MACHINE_END
MACHINE_START(APQ8064_LIQUID, "QCT APQ8064 LIQUID")
@@ -1377,5 +1680,6 @@
.handle_irq = gic_handle_irq,
.timer = &msm_timer,
.init_machine = apq8064_cdp_init,
+ .init_early = apq8064_allocate_memory_regions,
MACHINE_END
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index e1451f5..d401f4c 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -18,6 +18,7 @@
#include <linux/mfd/pm8xxx/pm8821.h>
#include <mach/msm_memtypes.h>
#include <mach/irqs.h>
+#include <mach/rpm-regulator.h>
/* Macros assume PMIC GPIOs and MPPs start at 1 */
#define PM8921_GPIO_BASE NR_GPIO_IRQS
@@ -37,12 +38,17 @@
#define GPIO_VREG_ID_EXT_5V 0
#define GPIO_VREG_ID_EXT_3P3V 1
+#define GPIO_VREG_ID_EXT_TS_SW 2
+#define GPIO_VREG_ID_EXT_MPP8 3
#define APQ8064_EXT_3P3V_REG_EN_GPIO 77
extern struct gpio_regulator_platform_data
apq8064_gpio_regulator_pdata[] __devinitdata;
+extern struct rpm_regulator_platform_data
+ apq8064_rpm_regulator_pdata __devinitdata;
+
extern struct regulator_init_data msm8064_saw_regulator_pdata_8921_s5;
extern struct regulator_init_data msm8064_saw_regulator_pdata_8921_s6;
extern struct regulator_init_data msm8064_saw_regulator_pdata_8821_s0;
@@ -58,6 +64,7 @@
extern struct msm_camera_board_info apq8064_camera_board_info;
void apq8064_init_cam(void);
+#define APQ_8064_GSBI3_QUP_I2C_BUS_ID 3
#define APQ_8064_GSBI4_QUP_I2C_BUS_ID 4
void apq8064_init_fb(void);
diff --git a/arch/arm/mach-msm/board-8930-camera.c b/arch/arm/mach-msm/board-8930-camera.c
index 8212e15..e0bc723 100644
--- a/arch/arm/mach-msm/board-8930-camera.c
+++ b/arch/arm/mach-msm/board-8930-camera.c
@@ -499,8 +499,8 @@
{"mipi_csi_vdd", REG_LDO, 1200000, 1200000, 20000},
{"cam_vdig", REG_LDO, 1200000, 1200000, 105000},
{"cam_vana", REG_LDO, 2800000, 2850000, 85600},
- {"cam_vio", REG_VS, 0, 0, 0},
- {"cam_vaf", REG_LDO, 2800000, 2800000, 300000},
+ {"cam_vio", REG_LDO, 1800000, 1800000, 16000},
+ {"cam_vaf", REG_LDO, 2800000, 2850000, 300000},
};
static struct msm_camera_sensor_flash_data flash_s5k3l1yx = {
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index d871e04..9175c75 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -417,7 +417,7 @@
#else
static int mdp_core_clk_rate_table[] = {
85330000,
- 85330000,
+ 128000000,
160000000,
200000000,
};
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 618d757..90cc3c5 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -40,6 +40,7 @@
#include <linux/ks8851.h>
#include <linux/i2c/isa1200.h>
#include <linux/gpio_keys.h>
+#include <linux/memory.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
@@ -429,12 +430,9 @@
if (high - low <= bank_size)
return;
- msm8930_reserve_info.low_unstable_address = low + bank_size;
- /* To avoid overflow of u32 compute max_unstable_size
- * by first subtracting low from mb->start)
- * */
- msm8930_reserve_info.max_unstable_size = (mb->start - low) +
- mb->size - bank_size;
+ msm8930_reserve_info.low_unstable_address = mb->start -
+ MIN_MEMORY_BLOCK_SIZE + mb->size;
+ msm8930_reserve_info.max_unstable_size = MIN_MEMORY_BLOCK_SIZE;
msm8930_reserve_info.bank_size = bank_size;
pr_info("low unstable address %lx max size %lx bank size %lx\n",
diff --git a/arch/arm/mach-msm/board-8960-camera.c b/arch/arm/mach-msm/board-8960-camera.c
index 6c292a4..23c4928 100644
--- a/arch/arm/mach-msm/board-8960-camera.c
+++ b/arch/arm/mach-msm/board-8960-camera.c
@@ -219,6 +219,18 @@
.ab = 0,
.ib = 0,
},
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 0,
+ .ib = 0,
+ },
};
static struct msm_bus_vectors cam_preview_vectors[] = {
@@ -240,6 +252,18 @@
.ab = 0,
.ib = 0,
},
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 0,
+ .ib = 0,
+ },
};
static struct msm_bus_vectors cam_video_vectors[] = {
@@ -261,6 +285,18 @@
.ab = 0,
.ib = 0,
},
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 0,
+ .ib = 0,
+ },
};
static struct msm_bus_vectors cam_snapshot_vectors[] = {
@@ -282,6 +318,18 @@
.ab = 540000000,
.ib = 1350000000,
},
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 43200000,
+ .ib = 69120000,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 43200000,
+ .ib = 69120000,
+ },
};
static struct msm_bus_vectors cam_zsl_vectors[] = {
@@ -303,6 +351,18 @@
.ab = 540000000,
.ib = 1350000000,
},
+ {
+ .src = MSM_BUS_MASTER_JPEG_ENC,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 43200000,
+ .ib = 69120000,
+ },
+ {
+ .src = MSM_BUS_MASTER_VFE,
+ .dst = MSM_BUS_SLAVE_MM_IMEM,
+ .ab = 43200000,
+ .ib = 69120000,
+ },
};
static struct msm_bus_paths cam_bus_client_config[] = {
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index fb78ce7..aa8477e 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -81,6 +81,8 @@
}
};
+static void set_mdp_clocks_for_liquid_wuxga(void);
+
static int msm_fb_detect_panel(const char *name)
{
if (machine_is_msm8960_liquid()) {
@@ -88,8 +90,10 @@
if (SOCINFO_VERSION_MAJOR(ver) == 3) {
if (!strncmp(name, MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME,
strnlen(MIPI_VIDEO_CHIMEI_WUXGA_PANEL_NAME,
- PANEL_NAME_MAX_LEN)))
+ PANEL_NAME_MAX_LEN))) {
+ set_mdp_clocks_for_liquid_wuxga();
return 0;
+ }
} else {
if (!strncmp(name, MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
strnlen(MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME,
@@ -617,7 +621,7 @@
#else
static int mdp_core_clk_rate_table[] = {
85330000,
- 85330000,
+ 128000000,
160000000,
200000000,
};
@@ -643,6 +647,24 @@
#endif
};
+/**
+ * Set MDP clocks to high frequency to avoid DSI underflow
+ * when using high resolution 1200x1920 WUXGA panel.
+ */
+static void set_mdp_clocks_for_liquid_wuxga(void)
+{
+ int i;
+
+ mdp_ui_vectors[0].ab = 2000000000;
+ mdp_ui_vectors[0].ib = 2000000000;
+
+ mdp_pdata.mdp_core_clk_rate = 200000000;
+
+ for (i = 0; i < ARRAY_SIZE(mdp_core_clk_rate_table); i++)
+ mdp_core_clk_rate_table[i] = 200000000;
+
+}
+
void __init msm8960_mdp_writeback(struct memtype_reserve* reserve_table)
{
mdp_pdata.ov0_wb_size = MSM_FB_OVERLAY0_WRITEBACK_SIZE;
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index 0375b84..744709c 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -95,6 +95,8 @@
PM8XXX_GPIO_INPUT(16, PM_GPIO_PULL_UP_30), /* SD_CARD_WP */
/* External regulator shared by display and touchscreen on LiQUID */
PM8XXX_GPIO_OUTPUT(17, 0), /* DISP 3.3 V Boost */
+ PM8XXX_GPIO_OUTPUT(18, 1), /* TABLA SPKR_LEFT_EN */
+ PM8XXX_GPIO_OUTPUT(19, 1), /* TABLA SPKR_RIGHT_EN */
PM8XXX_GPIO_OUTPUT_VIN(21, 1, PM_GPIO_VIN_VPH), /* Backlight Enable */
PM8XXX_GPIO_DISABLE(22), /* Disable NFC */
PM8XXX_GPIO_OUTPUT_FUNC(24, 0, PM_GPIO_FUNC_2), /* Bl: Off, PWM mode */
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 786ec01..76a27ff 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1022,12 +1022,54 @@
0x23, 0x83,/* set source impedance sdjusment */
-1};
+#ifdef CONFIG_MSM_BUS_SCALING
+/* Bandwidth requests (zero) if no vote placed */
+static struct msm_bus_vectors usb_init_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+/* Bus bandwidth requests in Bytes/sec */
+static struct msm_bus_vectors usb_max_vectors[] = {
+ {
+ .src = MSM_BUS_MASTER_SPS,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 60000000, /* At least 480Mbps on bus. */
+ .ib = 960000000, /* MAX bursts rate */
+ },
+};
+
+static struct msm_bus_paths usb_bus_scale_usecases[] = {
+ {
+ ARRAY_SIZE(usb_init_vectors),
+ usb_init_vectors,
+ },
+ {
+ ARRAY_SIZE(usb_max_vectors),
+ usb_max_vectors,
+ },
+};
+
+static struct msm_bus_scale_pdata usb_bus_scale_pdata = {
+ usb_bus_scale_usecases,
+ ARRAY_SIZE(usb_bus_scale_usecases),
+ .name = "usb",
+};
+#endif
+
static struct msm_otg_platform_data msm_otg_pdata = {
.mode = USB_OTG,
.otg_control = OTG_PMIC_CONTROL,
.phy_type = SNPS_28NM_INTEGRATED_PHY,
.pmic_id_irq = PM8921_USB_ID_IN_IRQ(PM8921_IRQ_BASE),
.power_budget = 750,
+#ifdef CONFIG_MSM_BUS_SCALING
+ .bus_scale_table = &usb_bus_scale_pdata,
+#endif
};
#endif
@@ -1916,6 +1958,7 @@
&msm_bus_sys_fpb,
&msm_bus_cpss_fpb,
&msm_pcm,
+ &msm_multi_ch_pcm,
&msm_pcm_routing,
&msm_cpudai0,
&msm_cpudai1,
@@ -1967,6 +2010,7 @@
&msm_device_hsusb_host,
&android_usb_device,
&msm_pcm,
+ &msm_multi_ch_pcm,
&msm_pcm_routing,
&msm_cpudai0,
&msm_cpudai1,
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 29f5fac..74ba1b3 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -2697,7 +2697,7 @@
#define USER_SMI_SIZE (MSM_SMI_SIZE - KERNEL_SMI_SIZE)
#define MSM_PMEM_SMIPOOL_SIZE USER_SMI_SIZE
-#define MSM_ION_SF_SIZE 0x1800000 /* 24MB */
+#define MSM_ION_SF_SIZE 0x4000000 /* 64MB */
#define MSM_ION_CAMERA_SIZE MSM_PMEM_ADSP_SIZE
#define MSM_ION_MM_FW_SIZE 0x200000 /* (2MB) */
#define MSM_ION_MM_SIZE 0x3600000 /* (54MB) */
@@ -9572,7 +9572,7 @@
#ifdef CONFIG_FB_MSM_MIPI_DSI
int mdp_core_clk_rate_table[] = {
85330000,
- 85330000,
+ 128000000,
160000000,
200000000,
};
@@ -9586,7 +9586,7 @@
#else
int mdp_core_clk_rate_table[] = {
59080000,
- 85330000,
+ 128000000,
128000000,
200000000,
};
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 8ecfea2..2bd0dcd 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -44,6 +44,7 @@
#define ADM0_PBUS_CLK_CTL_REG REG(0x2208)
#define CE1_HCLK_CTL_REG REG(0x2720)
#define CE1_CORE_CLK_CTL_REG REG(0x2724)
+#define PRNG_CLK_NS_REG REG(0x2E80)
#define CE3_HCLK_CTL_REG REG(0x36C4)
#define CE3_CORE_CLK_CTL_REG REG(0x36CC)
#define CE3_CLK_SRC_NS_REG REG(0x36C0)
@@ -4878,14 +4879,14 @@
CLK_LOOKUP("core_clk", gsbi7_uart_clk.c, "msm_serial_hsl.0"),
CLK_LOOKUP("core_clk", gsbi1_qup_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi2_qup_clk.c, ""),
- CLK_LOOKUP("core_clk", gsbi3_qup_clk.c, ""),
+ CLK_LOOKUP("core_clk", gsbi3_qup_clk.c, "qup_i2c.3"),
CLK_LOOKUP("core_clk", gsbi4_qup_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi5_qup_clk.c, "spi_qsd.0"),
CLK_LOOKUP("core_clk", gsbi6_qup_clk.c, ""),
CLK_LOOKUP("core_clk", gsbi7_qup_clk.c, ""),
CLK_LOOKUP("core_clk", pdm_clk.c, ""),
CLK_LOOKUP("mem_clk", pmem_clk.c, "msm_sps"),
- CLK_DUMMY("core_clk", PRNG_CLK, "msm_rng.0", OFF),
+ CLK_LOOKUP("core_clk", prng_clk.c, "msm_rng.0"),
CLK_LOOKUP("core_clk", sdc1_clk.c, "msm_sdcc.1"),
CLK_LOOKUP("core_clk", sdc2_clk.c, "msm_sdcc.2"),
CLK_LOOKUP("core_clk", sdc3_clk.c, "msm_sdcc.3"),
@@ -4911,7 +4912,7 @@
CLK_LOOKUP("dma_bam_pclk", dma_bam_p_clk.c, NULL),
CLK_LOOKUP("iface_clk", gsbi1_p_clk.c, "msm_serial_hsl.1"),
CLK_LOOKUP("iface_clk", gsbi2_p_clk.c, ""),
- CLK_LOOKUP("iface_clk", gsbi3_p_clk.c, ""),
+ CLK_LOOKUP("iface_clk", gsbi3_p_clk.c, "qup_i2c.3"),
CLK_LOOKUP("iface_clk", gsbi4_p_clk.c, ""),
CLK_LOOKUP("iface_clk", gsbi5_p_clk.c, "spi_qsd.0"),
CLK_LOOKUP("iface_clk", gsbi6_p_clk.c, ""),
@@ -4959,10 +4960,10 @@
CLK_LOOKUP("csiphy_timer_clk", csi0phy_timer_clk.c, ""),
CLK_LOOKUP("csiphy_timer_clk", csi1phy_timer_clk.c, ""),
CLK_LOOKUP("csiphy_timer_clk", csi2phy_timer_clk.c, ""),
- CLK_LOOKUP("dsi_byte_div_clk", dsi1_byte_clk.c, ""),
- CLK_LOOKUP("dsi_byte_div_clk", dsi2_byte_clk.c, ""),
- CLK_LOOKUP("dsi_esc_clk", dsi1_esc_clk.c, ""),
- CLK_LOOKUP("dsi_esc_clk", dsi2_esc_clk.c, ""),
+ CLK_LOOKUP("dsi_byte_div_clk", dsi1_byte_clk.c, NULL),
+ CLK_LOOKUP("dsi_byte_div_clk", dsi2_byte_clk.c, NULL),
+ CLK_LOOKUP("dsi_esc_clk", dsi1_esc_clk.c, NULL),
+ CLK_LOOKUP("dsi_esc_clk", dsi2_esc_clk.c, NULL),
CLK_DUMMY("rgb_tv_clk", RGB_TV_CLK, "", OFF),
CLK_DUMMY("npl_tv_clk", NPL_TV_CLK, "", OFF),
CLK_LOOKUP("core_clk", gfx3d_clk.c, "kgsl-3d0.0"),
@@ -4979,18 +4980,18 @@
CLK_LOOKUP("ijpeg_clk", ijpeg_clk.c, ""),
CLK_LOOKUP("core_clk", ijpeg_clk.c, "footswitch-8x60.3"),
CLK_LOOKUP("core_clk", jpegd_clk.c, ""),
- CLK_LOOKUP("mdp_clk", mdp_clk.c, ""),
+ CLK_LOOKUP("mdp_clk", mdp_clk.c, NULL),
CLK_LOOKUP("core_clk", mdp_clk.c, "footswitch-8x60.4"),
- CLK_LOOKUP("mdp_vsync_clk", mdp_vsync_clk.c, ""),
+ CLK_LOOKUP("mdp_vsync_clk", mdp_vsync_clk.c, NULL),
CLK_LOOKUP("vsync_clk", mdp_vsync_clk.c, "footswitch-8x60.4"),
- CLK_LOOKUP("lut_mdp", lut_mdp_clk.c, ""),
+ CLK_LOOKUP("lut_mdp", lut_mdp_clk.c, NULL),
CLK_LOOKUP("lut_clk", lut_mdp_clk.c, "footswitch-8x60.4"),
CLK_LOOKUP("core_clk", rot_clk.c, "msm_rotator.0"),
CLK_LOOKUP("core_clk", rot_clk.c, "footswitch-8x60.6"),
- CLK_DUMMY("tv_src_clk", TV_SRC_CLK, "", OFF),
+ CLK_DUMMY("tv_src_clk", TV_SRC_CLK, NULL, OFF),
CLK_LOOKUP("core_clk", vcodec_clk.c, "msm_vidc.0"),
CLK_LOOKUP("core_clk", vcodec_clk.c, "footswitch-8x60.7"),
- CLK_DUMMY("mdp_tv_clk", MDP_TV_CLK, "", OFF),
+ CLK_DUMMY("mdp_tv_clk", MDP_TV_CLK, NULL, OFF),
CLK_DUMMY("tv_clk", MDP_TV_CLK, "footswitch-8x60.4", OFF),
CLK_DUMMY("hdmi_clk", HDMI_TV_CLK, "", OFF),
CLK_LOOKUP("core_clk", hdmi_app_clk.c, ""),
@@ -5006,12 +5007,12 @@
CLK_LOOKUP("bus_a_clk", vcodec_axi_a_clk.c, "footswitch-8x60.7"),
CLK_LOOKUP("bus_b_clk", vcodec_axi_b_clk.c, "footswitch-8x60.7"),
CLK_LOOKUP("bus_clk", vpe_axi_clk.c, "footswitch-8x60.9"),
- CLK_LOOKUP("amp_pclk", amp_p_clk.c, ""),
+ CLK_LOOKUP("amp_pclk", amp_p_clk.c, NULL),
CLK_LOOKUP("csi_pclk", csi_p_clk.c, ""),
- CLK_LOOKUP("dsi_m_pclk", dsi1_m_p_clk.c, ""),
- CLK_LOOKUP("dsi_s_pclk", dsi1_s_p_clk.c, ""),
- CLK_LOOKUP("dsi_m_pclk", dsi2_m_p_clk.c, ""),
- CLK_LOOKUP("dsi_s_pclk", dsi2_s_p_clk.c, ""),
+ CLK_LOOKUP("dsi_m_pclk", dsi1_m_p_clk.c, NULL),
+ CLK_LOOKUP("dsi_s_pclk", dsi1_s_p_clk.c, NULL),
+ CLK_LOOKUP("dsi_m_pclk", dsi2_m_p_clk.c, NULL),
+ CLK_LOOKUP("dsi_s_pclk", dsi2_s_p_clk.c, NULL),
CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, "kgsl-3d0.0"),
CLK_LOOKUP("iface_clk", gfx3d_p_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("master_iface_clk", hdmi_m_p_clk.c, ""),
@@ -5020,7 +5021,7 @@
CLK_LOOKUP("iface_clk", ijpeg_p_clk.c, "footswitch-8x60.3"),
CLK_LOOKUP("iface_clk", jpegd_p_clk.c, ""),
CLK_LOOKUP("mem_iface_clk", imem_p_clk.c, "kgsl-3d0.0"),
- CLK_LOOKUP("mdp_pclk", mdp_p_clk.c, ""),
+ CLK_LOOKUP("mdp_pclk", mdp_p_clk.c, NULL),
CLK_LOOKUP("iface_clk", mdp_p_clk.c, "footswitch-8x60.4"),
CLK_LOOKUP("iface_clk", smmu_p_clk.c, "msm_iommu"),
CLK_LOOKUP("iface_clk", rot_p_clk.c, "msm_rotator.0"),
@@ -5249,7 +5250,7 @@
CLK_LOOKUP("core_clk", gfx3d_clk.c, "kgsl-3d0.0"),
CLK_LOOKUP("core_clk", gfx3d_clk.c, "footswitch-8x60.2"),
CLK_LOOKUP("bus_clk", ijpeg_axi_clk.c, "footswitch-8x60.3"),
- CLK_LOOKUP("mem_clk", imem_axi_clk.c, ""),
+ CLK_LOOKUP("imem_clk", imem_axi_clk.c, NULL),
CLK_LOOKUP("ijpeg_clk", ijpeg_clk.c, NULL),
CLK_LOOKUP("core_clk", ijpeg_clk.c, "footswitch-8x60.3"),
CLK_LOOKUP("core_clk", jpegd_clk.c, ""),
@@ -5540,8 +5541,8 @@
rmwreg(0, SATA_PHY_REF_CLK_CTL_REG, 0x1);
/*
- * TODO: Programming below PLLs is temporary and needs to be removed
- * after bootloaders program them.
+ * TODO: Programming below PLLs and prng_clk is temporary and
+ * needs to be removed after bootloaders program them.
*/
if (cpu_is_apq8064()) {
u32 is_pll_enabled;
@@ -5588,6 +5589,10 @@
/* Enable PLL4 source on the LPASS Primary PLL Mux */
writel_relaxed(0x1, LCC_PRI_PLL_CLK_CTL_REG);
+
+ /* Program prng_clk to 64MHz if it isn't configured */
+ if (!readl_relaxed(PRNG_CLK_NS_REG))
+ writel_relaxed(0x2B, PRNG_CLK_NS_REG);
}
}
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 8ea344b..d312f24 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -106,7 +106,6 @@
const uint32_t ns_val;
const uint32_t ctl_val;
uint32_t mnd_en_mask;
- const unsigned sys_vdd;
void *const extra_freq_data;
};
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index cb63395..912d1b0 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -69,6 +69,7 @@
.pet_time = 10000,
.bark_time = 11000,
.has_secure = true,
+ .needs_expired_enable = true,
};
struct platform_device msm8064_device_watchdog = {
@@ -160,6 +161,46 @@
.resource = resources_uart_gsbi3,
};
+static struct resource resources_qup_i2c_gsbi3[] = {
+ {
+ .name = "gsbi_qup_i2c_addr",
+ .start = MSM_GSBI3_PHYS,
+ .end = MSM_GSBI3_PHYS + 4 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "qup_phys_addr",
+ .start = MSM_GSBI3_QUP_PHYS,
+ .end = MSM_GSBI3_QUP_PHYS + MSM_QUP_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "qup_err_intr",
+ .start = GSBI3_QUP_IRQ,
+ .end = GSBI3_QUP_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .name = "i2c_clk",
+ .start = 9,
+ .end = 9,
+ .flags = IORESOURCE_IO,
+ },
+ {
+ .name = "i2c_sda",
+ .start = 8,
+ .end = 8,
+ .flags = IORESOURCE_IO,
+ },
+};
+
+struct platform_device apq8064_device_qup_i2c_gsbi3 = {
+ .name = "qup_i2c",
+ .id = 3,
+ .num_resources = ARRAY_SIZE(resources_qup_i2c_gsbi3),
+ .resource = resources_qup_i2c_gsbi3,
+};
+
static struct resource resources_qup_i2c_gsbi4[] = {
{
.name = "gsbi_qup_i2c_addr",
@@ -381,6 +422,7 @@
#define LPASS_SLIMBUS_PHYS 0x28080000
#define LPASS_SLIMBUS_BAM_PHYS 0x28084000
+#define LPASS_SLIMBUS_SLEW (MSM8960_TLMM_PHYS + 0x207C)
/* Board info for the slimbus slave device */
static struct resource slimbus_res[] = {
{
@@ -396,6 +438,12 @@
.name = "slimbus_bam_physical",
},
{
+ .start = LPASS_SLIMBUS_SLEW,
+ .end = LPASS_SLIMBUS_SLEW + 4 - 1,
+ .flags = IORESOURCE_MEM,
+ .name = "slimbus_slew_reg",
+ },
+ {
.start = SLIMBUS0_CORE_EE1_IRQ,
.end = SLIMBUS0_CORE_EE1_IRQ,
.flags = IORESOURCE_IRQ,
@@ -884,7 +932,7 @@
CLK_DUMMY("core_clk", GSBI1_UART_CLK, NULL, OFF),
CLK_DUMMY("core_clk", GSBI2_UART_CLK, NULL, OFF),
CLK_DUMMY("core_clk", GSBI3_UART_CLK,
- "msm_serial_hsl.0", OFF),
+ NULL, OFF),
CLK_DUMMY("core_clk", GSBI4_UART_CLK, NULL, OFF),
CLK_DUMMY("core_clk", GSBI5_UART_CLK, NULL, OFF),
CLK_DUMMY("core_clk", GSBI6_UART_CLK, NULL, OFF),
@@ -896,7 +944,7 @@
CLK_DUMMY("core_clk", GSBI12_UART_CLK, NULL, OFF),
CLK_DUMMY("core_clk", GSBI1_QUP_CLK, NULL, OFF),
CLK_DUMMY("core_clk", GSBI2_QUP_CLK, NULL, OFF),
- CLK_DUMMY("core_clk", GSBI3_QUP_CLK, NULL, OFF),
+ CLK_DUMMY("core_clk", GSBI3_QUP_CLK, "qup_i2c.3", OFF),
CLK_DUMMY("core_clk", GSBI4_QUP_CLK, "qup_i2c.4", OFF),
CLK_DUMMY("core_clk", GSBI5_QUP_CLK, "spi_qsd.0", OFF),
CLK_DUMMY("core_clk", GSBI6_QUP_CLK, NULL, OFF),
@@ -928,7 +976,7 @@
CLK_DUMMY("ref_clk", SATA_PHY_REF_CLK, NULL, OFF),
CLK_DUMMY("iface_clk", GSBI1_P_CLK, NULL, OFF),
CLK_DUMMY("iface_clk", GSBI2_P_CLK, NULL, OFF),
- CLK_DUMMY("iface_clk", GSBI3_P_CLK, "msm_serial_hsl.0", OFF),
+ CLK_DUMMY("iface_clk", GSBI3_P_CLK, "qup_i2c.3", OFF),
CLK_DUMMY("iface_clk", GSBI4_P_CLK, "qup_i2c.4", OFF),
CLK_DUMMY("iface_clk", GSBI5_P_CLK, "spi_qsd.0", OFF),
CLK_DUMMY("iface_clk", GSBI6_P_CLK, NULL, OFF),
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 872d9d4..4525bab 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1389,6 +1389,11 @@
.id = -1,
};
+struct platform_device msm_multi_ch_pcm = {
+ .name = "msm-multi-ch-pcm-dsp",
+ .id = -1,
+};
+
struct platform_device msm_pcm_routing = {
.name = "msm-pcm-routing",
.id = -1,
@@ -1405,7 +1410,7 @@
};
struct platform_device msm_cpudai_hdmi_rx = {
- .name = "msm-dai-q6",
+ .name = "msm-dai-q6-hdmi",
.id = 8,
};
@@ -1658,7 +1663,7 @@
};
#endif
-static struct platform_device msm_lvds_device = {
+struct platform_device msm_lvds_device = {
.name = "lvds",
.id = 0,
};
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index e3c875b..c4f57ab 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -70,6 +70,7 @@
extern struct platform_device apq8064_device_uart_gsbi1;
extern struct platform_device apq8064_device_uart_gsbi3;
extern struct platform_device apq8064_device_uart_gsbi7;
+extern struct platform_device apq8064_device_qup_i2c_gsbi3;
extern struct platform_device apq8064_device_qup_i2c_gsbi4;
extern struct platform_device apq8064_device_qup_spi_gsbi5;
extern struct platform_device apq8064_slim_ctrl;
@@ -163,6 +164,7 @@
extern struct platform_device msm_device_vidc_720p;
extern struct platform_device msm_pcm;
+extern struct platform_device msm_multi_ch_pcm;
extern struct platform_device msm_pcm_routing;
extern struct platform_device msm_cpudai0;
extern struct platform_device msm_cpudai1;
@@ -235,6 +237,7 @@
extern struct platform_device msm_kgsl_2d1;
extern struct platform_device msm_mipi_dsi1_device;
+extern struct platform_device msm_lvds_device;
extern struct clk_lookup msm_clocks_fsm9xxx[];
extern unsigned msm_num_clocks_fsm9xxx;
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index 296c111..5c10463 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.c
@@ -623,7 +623,7 @@
init_data = pdev->dev.platform_data;
if (pdev->id == FS_MDP) {
- if (cpu_is_msm8960() || cpu_is_msm8930())
+ if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_apq8064())
fs->clk_data = mdp_8960_clks;
else if (cpu_is_msm8x60())
fs->clk_data = mdp_8660_clks;
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 6eceea7..ba9fc70 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -399,6 +399,10 @@
char dlane_swap;
};
+struct lvds_panel_platform_data {
+ int *gpio;
+};
+
struct msm_fb_platform_data {
int (*detect_client)(const char *name);
int mddi_prescan;
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 06d214f..530d2c1 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -577,6 +577,7 @@
CAMIO_CSI0_PHY_CLK,
CAMIO_CSI1_PHY_CLK,
CAMIO_CSIPHY_TIMER_SRC_CLK,
+ CAMIO_IMEM_CLK,
CAMIO_MAX_CLK
};
diff --git a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
index 562a305..57e794f 100644
--- a/arch/arm/mach-msm/include/mach/msm_hdmi_audio.h
+++ b/arch/arm/mach-msm/include/mach/msm_hdmi_audio.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
@@ -13,6 +13,15 @@
#ifndef __MSM_HDMI_AUDIO_H
#define __MSM_HDMI_AUDIO_H
+/* Supported HDMI Audio channels */
+#define MSM_HDMI_AUDIO_CHANNEL_2 0
+#define MSM_HDMI_AUDIO_CHANNEL_4 1
+#define MSM_HDMI_AUDIO_CHANNEL_6 2
+#define MSM_HDMI_AUDIO_CHANNEL_8 3
+
+#define TRUE 1
+#define FALSE 0
+
enum hdmi_supported_sample_rates {
HDMI_SAMPLE_RATE_32KHZ,
HDMI_SAMPLE_RATE_44_1KHZ,
@@ -27,5 +36,7 @@
int hdmi_audio_packet_enable(bool on);
void hdmi_msm_audio_sample_rate_reset(int rate);
int hdmi_msm_audio_get_sample_rate(void);
+int hdmi_msm_audio_info_setup(bool enabled, u32 num_of_channels,
+ u32 channel_allocation, u32 level_shift, bool down_mix);
#endif /* __MSM_HDMI_AUDIO_H*/
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator.h b/arch/arm/mach-msm/include/mach/rpm-regulator.h
index 0d113ac..f8f4c87 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator.h
@@ -163,6 +163,10 @@
*
* Consumers can vote to disable a regulator with this function by passing
* min_uV = 0 and max_uV = 0.
+ *
+ * Voltage switch type regulators may be controlled via rpm_vreg_set_voltage
+ * as well. For this type of regulator, max_uV > 0 is treated as an enable
+ * request and max_uV == 0 is treated as a disable request.
*/
int rpm_vreg_set_voltage(int vreg_id, enum rpm_vreg_voter voter, int min_uV,
int max_uV, int sleep_also);
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index 600a2e9..c856455 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -43,123 +43,10 @@
char *name;
int domain;
} msm_iommu_ctx_names[] = {
- /* Camera */
- {
- .name = "vpe_src",
- .domain = GLOBAL_DOMAIN,
- },
- /* Camera */
- {
- .name = "vpe_dst",
- .domain = GLOBAL_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_imgwr",
- .domain = GLOBAL_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_misc",
- .domain = GLOBAL_DOMAIN,
- },
- /* Camera */
- {
- .name = "ijpeg_src",
- .domain = GLOBAL_DOMAIN,
- },
- /* Camera */
- {
- .name = "ijpeg_dst",
- .domain = GLOBAL_DOMAIN,
- },
- /* Camera */
- {
- .name = "jpegd_src",
- .domain = GLOBAL_DOMAIN,
- },
- /* Camera */
- {
- .name = "jpegd_dst",
- .domain = GLOBAL_DOMAIN,
- },
- /* Display */
- {
- .name = "mdp_vg1",
- .domain = GLOBAL_DOMAIN,
- },
- /* Display */
- {
- .name = "mdp_vg2",
- .domain = GLOBAL_DOMAIN,
- },
- /* Display */
- {
- .name = "mdp_rgb1",
- .domain = GLOBAL_DOMAIN,
- },
- /* Display */
- {
- .name = "mdp_rgb2",
- .domain = GLOBAL_DOMAIN,
- },
- /* Rotator */
- {
- .name = "rot_src",
- .domain = GLOBAL_DOMAIN,
- },
- /* Rotator */
- {
- .name = "rot_dst",
- .domain = GLOBAL_DOMAIN,
- },
- /* Video */
- {
- .name = "vcodec_a_mm1",
- .domain = GLOBAL_DOMAIN,
- },
- /* Video */
- {
- .name = "vcodec_b_mm2",
- .domain = GLOBAL_DOMAIN,
- },
- /* Video */
- {
- .name = "vcodec_a_stream",
- .domain = GLOBAL_DOMAIN,
- },
-};
-
-static struct mem_pool global_pools[] = {
- [VIDEO_FIRMWARE_POOL] =
- /* Low addresses, intended for video firmware */
- {
- .paddr = SZ_128K,
- .size = SZ_16M - SZ_128K,
- },
- [LOW_256MB_POOL] =
- /*
- * Video can only access first 256MB of memory
- * dedicated pool for such allocations
- */
- {
- .paddr = SZ_16M,
- .size = SZ_256M - SZ_16M,
- },
- [HIGH_POOL] =
- /* Remaining address space up to 2G */
- {
- .paddr = SZ_256M,
- .size = SZ_2G - SZ_256M,
- }
};
static struct msm_iommu_domain msm_iommu_domains[] = {
- [GLOBAL_DOMAIN] = {
- .iova_pools = global_pools,
- .npools = ARRAY_SIZE(global_pools),
- }
};
int msm_iommu_map_extra(struct iommu_domain *domain,
@@ -281,10 +168,8 @@
int msm_use_iommu()
{
- /*
- * For now, just detect if the iommu is attached.
- */
- return iommu_found();
+ /* Kill use of the iommu by these clients for now. */
+ return 0;
}
static int __init msm_subsystem_iommu_init(void)
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 46695c4..3b064ff 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -315,7 +315,12 @@
return 0;
mb = &meminfo.bank[meminfo.nr_banks - 1];
- fmem_phys = mb->start + (mb->size - fmem_size);
+ /*
+ * Placing fmem at the top of memory causes multimedia issues.
+ * Instead, place it 1 page below the top of memory to prevent
+ * the issues from occurring.
+ */
+ fmem_phys = mb->start + (mb->size - fmem_size) - PAGE_SIZE;
ret = memblock_remove(fmem_phys, fmem_size);
BUG_ON(ret);
diff --git a/arch/arm/mach-msm/msm_watchdog.c b/arch/arm/mach-msm/msm_watchdog.c
index 4303f83..5bff832 100644
--- a/arch/arm/mach-msm/msm_watchdog.c
+++ b/arch/arm/mach-msm/msm_watchdog.c
@@ -363,6 +363,9 @@
if (cpu_is_msm9615())
__raw_writel(0xF, MSM_TCSR_BASE + TCSR_WDT_CFG);
+ if (pdata->needs_expired_enable)
+ __raw_writel(0x1, MSM_CLK_CTL_BASE + 0x3820);
+
configure_bark_dump();
delay_time = msecs_to_jiffies(pdata->pet_time);
diff --git a/arch/arm/mach-msm/msm_watchdog.h b/arch/arm/mach-msm/msm_watchdog.h
index 201c2b1..33e9e0c 100644
--- a/arch/arm/mach-msm/msm_watchdog.h
+++ b/arch/arm/mach-msm/msm_watchdog.h
@@ -19,6 +19,7 @@
/* bark timeout in ms */
unsigned int bark_time;
bool has_secure;
+ bool needs_expired_enable;
};
#ifdef CONFIG_MSM_WATCHDOG
diff --git a/arch/arm/mach-msm/peripheral-loader.c b/arch/arm/mach-msm/peripheral-loader.c
index 0886975..1004e01 100644
--- a/arch/arm/mach-msm/peripheral-loader.c
+++ b/arch/arm/mach-msm/peripheral-loader.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -288,14 +288,10 @@
mutex_lock(&pil->lock);
WARN(!pil->count, "%s: Reference count mismatch\n", __func__);
- /* TODO: Peripheral shutdown support */
- if (pil->count == 1)
- goto unlock;
if (pil->count)
pil->count--;
if (pil->count == 0)
pil->desc->ops->shutdown(pil->desc);
-unlock:
mutex_unlock(&pil->lock);
pil_d = find_peripheral(pil->desc->depends_on);
diff --git a/arch/arm/mach-msm/pil-gss.c b/arch/arm/mach-msm/pil-gss.c
index f3e83d9..6ec9b5d 100644
--- a/arch/arm/mach-msm/pil-gss.c
+++ b/arch/arm/mach-msm/pil-gss.c
@@ -257,6 +257,49 @@
.shutdown = pil_gss_shutdown,
};
+static int pil_gss_init_image_trusted(struct pil_desc *pil,
+ const u8 *metadata, size_t size)
+{
+ return pas_init_image(PAS_GSS, metadata, size);
+}
+
+static int pil_gss_reset_trusted(struct pil_desc *pil)
+{
+ struct gss_data *drv = dev_get_drvdata(pil->dev);
+ int err;
+
+ err = make_gss_proxy_votes(pil->dev);
+ if (err)
+ return err;
+
+ err = pas_auth_and_reset(PAS_GSS);
+ if (err)
+ remove_gss_proxy_votes_now(drv);
+
+ return err;
+}
+
+static int pil_gss_shutdown_trusted(struct pil_desc *pil)
+{
+ struct gss_data *drv = dev_get_drvdata(pil->dev);
+ int ret;
+
+ ret = pas_shutdown(PAS_GSS);
+ if (ret)
+ return ret;
+
+ remove_gss_proxy_votes_now(drv);
+
+ return ret;
+}
+
+static struct pil_reset_ops pil_gss_ops_trusted = {
+ .init_image = pil_gss_init_image_trusted,
+ .verify_blob = nop_verify_blob,
+ .auth_and_reset = pil_gss_reset_trusted,
+ .shutdown = pil_gss_shutdown_trusted,
+};
+
static void configure_gss_pll(struct gss_data *drv)
{
u32 regval, is_pll_enabled;
@@ -354,8 +397,13 @@
desc->name = "gss";
desc->dev = &pdev->dev;
- desc->ops = &pil_gss_ops;
- dev_info(&pdev->dev, "using non-secure boot\n");
+ if (pas_supported(PAS_GSS) > 0) {
+ desc->ops = &pil_gss_ops_trusted;
+ dev_info(&pdev->dev, "using secure boot\n");
+ } else {
+ desc->ops = &pil_gss_ops;
+ dev_info(&pdev->dev, "using non-secure boot\n");
+ }
INIT_DELAYED_WORK(&drv->work, remove_gss_proxy_votes);
diff --git a/arch/arm/mach-msm/rpm-regulator.c b/arch/arm/mach-msm/rpm-regulator.c
index 946d31b..ed366ae 100644
--- a/arch/arm/mach-msm/rpm-regulator.c
+++ b/arch/arm/mach-msm/rpm-regulator.c
@@ -268,8 +268,10 @@
if (vreg->part->uV.mask)
uV = GET_PART(vreg, uV);
- else
+ else if (vreg->part->mV.mask)
uV = MILLI_TO_MICRO(GET_PART(vreg, mV));
+ else if (vreg->part->enable_state.mask)
+ uV = GET_PART(vreg, enable_state);
return uV;
}
@@ -278,8 +280,10 @@
{
if (vreg->part->uV.mask)
SET_PART(vreg, uV, uV);
- else
+ else if (vreg->part->mV.mask)
SET_PART(vreg, mV, MICRO_TO_MILLI(uV));
+ else if (vreg->part->enable_state.mask)
+ SET_PART(vreg, enable_state, uV);
}
static int vreg_send_request(struct vreg *vreg, enum rpm_vreg_voter voter,
@@ -380,9 +384,14 @@
if (vreg->part->uV.mask) {
s_val[vreg->part->uV.word] = 0 << vreg->part->uV.shift;
s_mask[vreg->part->uV.word] = vreg->part->uV.mask;
- } else {
+ } else if (vreg->part->mV.mask) {
s_val[vreg->part->mV.word] = 0 << vreg->part->mV.shift;
s_mask[vreg->part->mV.word] = vreg->part->mV.mask;
+ } else if (vreg->part->enable_state.mask) {
+ s_val[vreg->part->enable_state.word]
+ = 0 << vreg->part->enable_state.shift;
+ s_mask[vreg->part->enable_state.word]
+ = vreg->part->enable_state.mask;
}
rc = vreg_send_request(vreg, voter, MSM_RPM_CTX_SET_SLEEP,
@@ -421,6 +430,10 @@
*
* Consumers can vote to disable a regulator with this function by passing
* min_uV = 0 and max_uV = 0.
+ *
+ * Voltage switch type regulators may be controlled via rpm_vreg_set_voltage
+ * as well. For this type of regulator, max_uV > 0 is treated as an enable
+ * request and max_uV == 0 is treated as a disable request.
*/
int rpm_vreg_set_voltage(int vreg_id, enum rpm_vreg_voter voter, int min_uV,
int max_uV, int sleep_also)
@@ -431,14 +444,6 @@
int uV = min_uV;
int lim_min_uV, lim_max_uV, i, rc;
- /*
- * HACK: make this function a no-op for 8064 so that it can be called by
- * consumers on 8064 before RPM capabilities are present. (needed for
- * acpuclock driver)
- */
- if (cpu_is_apq8064())
- return 0;
-
if (!config) {
pr_err("rpm-regulator driver has not probed yet.\n");
return -ENODEV;
@@ -450,7 +455,6 @@
}
vreg = &config->vregs[vreg_id];
- range = &vreg->set_points->range[0];
if (!vreg->pdata.sleep_selectable) {
vreg_err(vreg, "regulator is not marked sleep selectable\n");
@@ -458,7 +462,8 @@
}
/* Allow min_uV == max_uV == 0 to represent a disable request. */
- if (min_uV != 0 || max_uV != 0) {
+ if ((min_uV != 0 || max_uV != 0)
+ && (vreg->part->uV.mask || vreg->part->mV.mask)) {
/*
* Check if request voltage is outside of allowed range. The
* regulator core has already checked that constraint range
@@ -477,6 +482,7 @@
return -EINVAL;
}
+ range = &vreg->set_points->range[0];
/* Find the range which uV is inside of. */
for (i = vreg->set_points->count - 1; i > 0; i--) {
if (uV > vreg->set_points->range[i - 1].max_uV) {
@@ -504,10 +510,20 @@
if (vreg->part->uV.mask) {
val[vreg->part->uV.word] = uV << vreg->part->uV.shift;
mask[vreg->part->uV.word] = vreg->part->uV.mask;
- } else {
+ } else if (vreg->part->mV.mask) {
val[vreg->part->mV.word]
= MICRO_TO_MILLI(uV) << vreg->part->mV.shift;
mask[vreg->part->mV.word] = vreg->part->mV.mask;
+ } else if (vreg->part->enable_state.mask) {
+ /*
+ * Translate max_uV > 0 into an enable request for regulator
+ * types which to not support voltage setting, e.g. voltage
+ * switches.
+ */
+ val[vreg->part->enable_state.word]
+ = (max_uV > 0 ? 1 : 0) << vreg->part->enable_state.shift;
+ mask[vreg->part->enable_state.word]
+ = vreg->part->enable_state.mask;
}
rc = vreg_set_noirq(vreg, voter, sleep_also, mask[0], val[0], mask[1],
@@ -532,13 +548,6 @@
struct vreg *vreg;
int rc;
- /*
- * HACK: make this function a no-op for 8064 so that it can be called by
- * consumers on 8064 before RPM capabilities are present.
- */
- if (cpu_is_apq8064())
- return 0;
-
if (!config) {
pr_err("rpm-regulator driver has not probed yet.\n");
return -ENODEV;
diff --git a/arch/arm/mach-msm/scm-pas.h b/arch/arm/mach-msm/scm-pas.h
index 67a0992..3651ee1 100644
--- a/arch/arm/mach-msm/scm-pas.h
+++ b/arch/arm/mach-msm/scm-pas.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -20,6 +20,8 @@
PAS_MODEM_SW,
PAS_MODEM_FW,
PAS_RIVA,
+ PAS_SECAPP,
+ PAS_GSS,
};
extern int pas_init_image(enum pas_id id, const u8 *metadata, size_t size);
diff --git a/arch/arm/mach-msm/smd_pkt.c b/arch/arm/mach-msm/smd_pkt.c
index 8023129..63c5fef 100644
--- a/arch/arm/mach-msm/smd_pkt.c
+++ b/arch/arm/mach-msm/smd_pkt.c
@@ -31,6 +31,7 @@
#include <linux/msm_smd_pkt.h>
#include <linux/poll.h>
#include <asm/ioctls.h>
+#include <linux/wakelock.h>
#include <mach/msm_smd.h>
#include <mach/peripheral-loader.h>
@@ -45,6 +46,7 @@
#define LOOPBACK_INX (NUM_SMD_PKT_PORTS - 1)
#define DEVICE_NAME "smdpkt"
+#define WAKELOCK_TIMEOUT (2*HZ)
struct smd_pkt_dev {
struct cdev cdev;
@@ -70,7 +72,8 @@
int has_reset;
int do_reset_notification;
struct completion ch_allocated;
-
+ struct wake_lock pa_wake_lock; /* Packet Arrival Wake lock*/
+ struct work_struct packet_arrival_work;
} *smd_pkt_devp[NUM_SMD_PKT_PORTS];
struct class *smd_pkt_classp;
@@ -183,6 +186,19 @@
}
+static void packet_arrival_worker(struct work_struct *work)
+{
+ struct smd_pkt_dev *smd_pkt_devp;
+
+ 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)
+ wake_lock_timeout(&smd_pkt_devp->pa_wake_lock,
+ WAKELOCK_TIMEOUT);
+ mutex_unlock(&smd_pkt_devp->ch_lock);
+}
+
static long smd_pkt_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
@@ -421,6 +437,7 @@
/* here we have a packet of size sz ready */
wake_up(&smd_pkt_devp->ch_read_wait_queue);
+ schedule_work(&smd_pkt_devp->packet_arrival_work);
D(KERN_ERR "%s: after wake_up\n", __func__);
}
@@ -579,6 +596,10 @@
if (!smd_pkt_devp)
return -EINVAL;
+ wake_lock_init(&smd_pkt_devp->pa_wake_lock, WAKE_LOCK_SUSPEND,
+ smd_pkt_dev_name[smd_pkt_devp->i]);
+ INIT_WORK(&smd_pkt_devp->packet_arrival_work, packet_arrival_worker);
+
file->private_data = smd_pkt_devp;
mutex_lock(&smd_pkt_devp->ch_lock);
@@ -665,6 +686,9 @@
out:
mutex_unlock(&smd_pkt_devp->ch_lock);
+ if (r < 0)
+ wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
+
return r;
}
@@ -690,6 +714,7 @@
smd_pkt_devp->has_reset = 0;
smd_pkt_devp->do_reset_notification = 0;
+ wake_lock_destroy(&smd_pkt_devp->pa_wake_lock);
return r;
}
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index e566234..4128e3a 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -215,13 +215,13 @@
return __raw_readl(addr);
t1 = __raw_readl(addr);
- t2 = __raw_readl(addr);
+ t2 = __raw_readl_no_log(addr);
if ((t2-t1) <= 1)
return t2;
while (1) {
- t1 = __raw_readl(addr);
- t2 = __raw_readl(addr);
- t3 = __raw_readl(addr);
+ t1 = __raw_readl_no_log(addr);
+ t2 = __raw_readl_no_log(addr);
+ t3 = __raw_readl_no_log(addr);
cpu_relax();
if ((t3-t2) <= 1)
return t3;
@@ -304,7 +304,7 @@
/* read the counter four extra times to make sure write posts
before reading the time */
for (i = 0; i < 4; i++)
- __raw_readl(clock->regbase + TIMER_COUNT_VAL);
+ __raw_readl_no_log(clock->regbase + TIMER_COUNT_VAL);
}
now = msm_read_timer_count(clock, LOCAL_TIMER);
clock_state->last_set = now;
@@ -415,11 +415,12 @@
tmp /= (loop_zero_count-1);
while (loop_zero_count--) {
- t1 = __raw_readl(MSM_RPM_MPM_BASE + MPM_SCLK_COUNT_VAL);
+ t1 = __raw_readl_no_log(MSM_RPM_MPM_BASE + MPM_SCLK_COUNT_VAL);
do {
udelay(1);
t2 = t1;
- t1 = __raw_readl(MSM_RPM_MPM_BASE + MPM_SCLK_COUNT_VAL);
+ t1 = __raw_readl_no_log(
+ MSM_RPM_MPM_BASE + MPM_SCLK_COUNT_VAL);
} while ((t2 != t1) && --loop_count);
if (!loop_count) {
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index b4ca325..7d2e44f 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1136,3 +1136,4 @@
apq8064_cdp MACH_APQ8064_CDP APQ8064_CDP 3948
apq8064_mtp MACH_APQ8064_MTP APQ8064_MTP 3949
apq8064_liquid MACH_APQ8064_LIQUID APQ8064_LIQUID 3951
+msm7627a_qrd3 MACH_MSM7627A_QRD3 MSM7627A_QRD3 4005
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 7ceae89..07322cd 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -124,7 +124,8 @@
*/
int chk_apps_master(void)
{
- if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615())
+ if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm9615() ||
+ cpu_is_apq8064() || cpu_is_msm8627())
return 1;
else
return 0;
diff --git a/drivers/gpu/ion/ion_cp_heap.c b/drivers/gpu/ion/ion_cp_heap.c
index fc1cfb6..a6b0cf6 100644
--- a/drivers/gpu/ion/ion_cp_heap.c
+++ b/drivers/gpu/ion/ion_cp_heap.c
@@ -27,9 +27,11 @@
#include <linux/memory_alloc.h>
#include <linux/seq_file.h>
#include <linux/fmem.h>
+#include <linux/iommu.h>
#include <mach/msm_memtypes.h>
#include <mach/scm.h>
-#include "ion_priv.h"
+#include <mach/iommu_domains.h>
+ #include "ion_priv.h"
#include <asm/mach/map.h>
@@ -566,6 +568,103 @@
return ret_value;
}
+static int ion_cp_heap_map_iommu(struct ion_buffer *buffer,
+ struct ion_iommu_map *data,
+ unsigned int domain_num,
+ unsigned int partition_num,
+ unsigned long align,
+ unsigned long iova_length,
+ unsigned long flags)
+{
+ unsigned long temp_phys, temp_iova;
+ struct iommu_domain *domain;
+ int i, ret = 0;
+ unsigned long extra;
+
+ data->mapped_size = iova_length;
+
+ if (!msm_use_iommu()) {
+ data->iova_addr = buffer->priv_phys;
+ return 0;
+ }
+
+ extra = iova_length - buffer->size;
+
+ data->iova_addr = msm_allocate_iova_address(domain_num, partition_num,
+ data->mapped_size, align);
+
+ if (!data->iova_addr) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ ret = -ENOMEM;
+ goto out1;
+ }
+
+ temp_iova = data->iova_addr;
+ temp_phys = buffer->priv_phys;
+ for (i = buffer->size; i > 0; i -= SZ_4K, temp_iova += SZ_4K,
+ temp_phys += SZ_4K) {
+ ret = iommu_map(domain, temp_iova, temp_phys,
+ get_order(SZ_4K),
+ ION_IS_CACHED(flags) ? 1 : 0);
+
+ if (ret) {
+ pr_err("%s: could not map %lx to %lx in domain %p\n",
+ __func__, temp_iova, temp_phys, domain);
+ goto out2;
+ }
+ }
+
+ if (extra && (msm_iommu_map_extra(domain, temp_iova, extra, flags) < 0))
+ goto out2;
+
+ return 0;
+
+out2:
+ for ( ; i < buffer->size; i += SZ_4K, temp_iova -= SZ_4K)
+ iommu_unmap(domain, temp_iova, get_order(SZ_4K));
+out1:
+ msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+ data->mapped_size);
+out:
+ return ret;
+}
+
+static void ion_cp_heap_unmap_iommu(struct ion_iommu_map *data)
+{
+ int i;
+ unsigned long temp_iova;
+ unsigned int domain_num;
+ unsigned int partition_num;
+ struct iommu_domain *domain;
+
+ if (!msm_use_iommu())
+ return;
+
+ domain_num = iommu_map_domain(data);
+ partition_num = iommu_map_partition(data);
+
+ domain = msm_get_iommu_domain(domain_num);
+
+ if (!domain) {
+ WARN(1, "Could not get domain %d. Corruption?\n", domain_num);
+ return;
+ }
+
+ temp_iova = data->iova_addr;
+ for (i = data->mapped_size; i > 0; i -= SZ_4K, temp_iova += SZ_4K)
+ iommu_unmap(domain, temp_iova, get_order(SZ_4K));
+
+ msm_free_iova_address(data->iova_addr, domain_num, partition_num,
+ data->mapped_size);
+
+ return;
+}
static struct ion_heap_ops cp_heap_ops = {
.allocate = ion_cp_heap_allocate,
@@ -581,6 +680,8 @@
.print_debug = ion_cp_print_debug,
.secure_heap = ion_cp_secure_heap,
.unsecure_heap = ion_cp_unsecure_heap,
+ .map_iommu = ion_cp_heap_map_iommu,
+ .unmap_iommu = ion_cp_heap_unmap_iommu,
};
struct ion_heap *ion_cp_heap_create(struct ion_platform_heap *heap_data)
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 805e2b6..9cbebbe 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -131,31 +131,35 @@
struct adreno_gpudev *gpudev;
unsigned int istore_size;
unsigned int pix_shader_start;
+ unsigned int instruction_size; /* Size of an instruction in dwords */
} adreno_gpulist[] = {
{ ADRENO_REV_A200, 0, 2, ANY_ID, ANY_ID,
"yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev,
- 512, 384},
+ 512, 384, 3},
{ ADRENO_REV_A205, 0, 1, 0, ANY_ID,
"yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev,
- 512, 384},
+ 512, 384, 3},
{ ADRENO_REV_A220, 2, 1, ANY_ID, ANY_ID,
"leia_pm4_470.fw", "leia_pfp_470.fw", &adreno_a2xx_gpudev,
- 512, 384},
+ 512, 384, 3},
/*
* patchlevel 5 (8960v2) needs special pm4 firmware to work around
* a hardware problem.
*/
{ ADRENO_REV_A225, 2, 2, 0, 5,
"a225p5_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
- 1536, 768 },
+ 1536, 768, 3 },
{ ADRENO_REV_A225, 2, 2, 0, 6,
"a225_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
- 1536, 768 },
+ 1536, 768, 3 },
{ ADRENO_REV_A225, 2, 2, ANY_ID, ANY_ID,
"a225_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev,
- 1536, 768 },
+ 1536, 768, 3 },
+ /* A3XX doesn't use the pix_shader_start */
{ ADRENO_REV_A320, 3, 1, ANY_ID, ANY_ID,
- "a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev },
+ "a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev,
+ 512, 0, 2 },
+
};
static irqreturn_t adreno_isr(int irq, void *data)
@@ -248,6 +252,16 @@
unsigned int mh_mmu_invalidate = 0x00000003; /*invalidate all and tc */
/*
+ * A3XX doesn't support the fast path (the registers don't even exist)
+ * so just bail out early
+ */
+
+ if (adreno_is_a3xx(adreno_dev)) {
+ kgsl_mmu_device_setstate(device, flags);
+ return;
+ }
+
+ /*
* If possible, then set the state via the command stream to avoid
* a CPU idle. Otherwise, use the default setstate which uses register
* writes For CFF dump we must idle and use the registers so that it is
@@ -442,6 +456,7 @@
adreno_dev->pm4_fwfile = adreno_gpulist[i].pm4fw;
adreno_dev->istore_size = adreno_gpulist[i].istore_size;
adreno_dev->pix_shader_start = adreno_gpulist[i].pix_shader_start;
+ adreno_dev->instruction_size = adreno_gpulist[i].instruction_size;
}
static int __devinit
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 9c2d704..9498b80 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -39,12 +39,7 @@
#define ADRENO_DEFAULT_PWRSCALE_POLICY NULL
#endif
-/*
- * constants for the size of shader instructions
- */
-#define ADRENO_ISTORE_BYTES 12
-#define ADRENO_ISTORE_WORDS 3
-#define ADRENO_ISTORE_START 0x5000
+#define ADRENO_ISTORE_START 0x5000 /* Istore offset */
enum adreno_gpurev {
ADRENO_REV_UNKNOWN = 0,
@@ -75,6 +70,7 @@
unsigned int wait_timeout;
unsigned int istore_size;
unsigned int pix_shader_start;
+ unsigned int instruction_size;
};
struct adreno_gpudev {
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index e31b76b..f2b1278 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -164,7 +164,8 @@
static inline int _shader_shadow_size(struct adreno_device *adreno_dev)
{
- return adreno_dev->istore_size*ADRENO_ISTORE_BYTES;
+ return adreno_dev->istore_size *
+ (adreno_dev->instruction_size * sizeof(unsigned int));
}
static inline int _context_size(struct adreno_device *adreno_dev)
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 1bad811..f68bc41 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -34,7 +34,7 @@
0x01ea, 0x01ea, 0x01ee, 0x01f1, 0x01f5, 0x01f5, 0x01fc, 0x01ff,
0x0440, 0x0440, 0x0443, 0x0443, 0x0445, 0x0445, 0x044d, 0x044f,
0x0452, 0x0452, 0x0454, 0x046f, 0x047c, 0x047c, 0x047f, 0x047f,
- 0x0579, 0x057f, 0x0600, 0x0602, 0x0605, 0x0607, 0x060a, 0x060e,
+ 0x0578, 0x057f, 0x0600, 0x0602, 0x0605, 0x0607, 0x060a, 0x060e,
0x0612, 0x0614, 0x0c01, 0x0c02, 0x0c06, 0x0c1d, 0x0c3d, 0x0c3f,
0x0c48, 0x0c4b, 0x0c80, 0x0c80, 0x0c88, 0x0c8b, 0x0ca0, 0x0cb7,
0x0cc0, 0x0cc1, 0x0cc6, 0x0cc7, 0x0ce4, 0x0ce5, 0x0e00, 0x0e05,
@@ -127,13 +127,8 @@
#define HLSQ_MEMOBJ_OFFSET 0x400
#define HLSQ_MIPMAP_OFFSET 0x800
-#ifdef GSL_USE_A3XX_HLSQ_SHADOW_RAM
/* Use shadow RAM */
#define HLSQ_SHADOW_BASE (0x10000+SSIZE*2)
-#else
-/* Use working RAM */
-#define HLSQ_SHADOW_BASE 0x10000
-#endif
#define REG_TO_MEM_LOOP_COUNT_SHIFT 15
@@ -258,7 +253,7 @@
struct adreno_context *drawctxt)
{
unsigned int *cmd = tmp_ctx.cmd;
- unsigned int *start = cmd;
+ unsigned int *start;
unsigned int i;
drawctxt->constant_save_commands[0].hostptr = cmd;
@@ -266,6 +261,8 @@
virt2gpu(cmd, &drawctxt->gpustate);
cmd++;
+ start = cmd;
+
*cmd++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1);
*cmd++ = 0;
@@ -1313,7 +1310,8 @@
_SET(SP_FSCTRLREG1_FSINITIALOUTSTANDING, 2) |
_SET(SP_FSCTRLREG1_HALFPRECVAROFFSET, 63);
/* SP_FS_OBJ_OFFSET_REG */
- *cmds++ = _SET(SP_OBJOFFSETREG_CONSTOBJECTSTARTOFFSET, 128);
+ *cmds++ = _SET(SP_OBJOFFSETREG_CONSTOBJECTSTARTOFFSET, 128) |
+ _SET(SP_OBJOFFSETREG_SHADEROBJOFFSETINIC, 1);
/* SP_FS_OBJ_START_REG */
*cmds++ = 0x00000000;
@@ -1329,7 +1327,7 @@
/* SP_FS_OUT_REG */
*cmds++ = _SET(SP_FSOUTREG_PAD0, SP_PIXEL_BASED);
- *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
+ *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 5);
*cmds++ = CP_REG(A3XX_SP_FS_MRT_REG_0);
/* SP_FS_MRT_REG0 */
*cmds++ = _SET(SP_FSMRTREG_REGID, 4);
@@ -1426,7 +1424,7 @@
_SET(VPC_VPCVARPSREPLMODE_COMPONENT16, 1) |
_SET(VPC_VPCVARPSREPLMODE_COMPONENT17, 2);
- *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 11);
+ *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_SP_SP_CTRL_REG);
/* SP_SP_CTRL_REG */
*cmds++ = _SET(SP_SPCTRLREG_SLEEPMODE, 1);
@@ -1652,7 +1650,9 @@
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_GRAS_SC_CONTROL);
/* GRAS_SC_CONTROL */
- *cmds++ = _SET(GRAS_SC_CONTROL_RASTER_MODE, 1);
+ /*cmds++ = _SET(GRAS_SC_CONTROL_RASTER_MODE, 1);
+ *cmds++ = _SET(GRAS_SC_CONTROL_RASTER_MODE, 1) |*/
+ *cmds++ = 0x04001000;
*cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2);
*cmds++ = CP_REG(A3XX_GRAS_SU_MODE_CONTROL);
@@ -2130,24 +2130,17 @@
static int a3xx_create_gmem_shadow(struct adreno_device *adreno_dev,
struct adreno_context *drawctxt)
{
+ int result;
+
calc_gmemsize(&drawctxt->context_gmem_shadow,
adreno_dev->gmemspace.sizebytes);
tmp_ctx.gmem_base = adreno_dev->gmemspace.gpu_base;
- if (drawctxt->flags & CTXT_FLAGS_GMEM_SHADOW) {
- int result =
- kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
- drawctxt->pagetable,
- drawctxt->context_gmem_shadow.size);
+ result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow,
+ drawctxt->pagetable, drawctxt->context_gmem_shadow.size);
- if (result)
- return result;
- } else {
- memset(&drawctxt->context_gmem_shadow.gmemshadow, 0,
- sizeof(drawctxt->context_gmem_shadow.gmemshadow));
-
- return 0;
- }
+ if (result)
+ return result;
build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow,
&tmp_ctx.cmd);
@@ -2163,6 +2156,8 @@
kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow,
KGSL_CACHE_OP_FLUSH);
+ drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW;
+
return 0;
}
@@ -2431,10 +2426,7 @@
#define A3XX_INT_MASK \
((1 << A3XX_INT_RBBM_AHB_ERROR) | \
(1 << A3XX_INT_RBBM_REG_TIMEOUT) | \
- (1 << A3XX_INT_RBBM_ME_MS_TIMEOUT) | \
- (1 << A3XX_INT_RBBM_PFP_MS_TIMEOUT) | \
(1 << A3XX_INT_RBBM_ATB_BUS_OVERFLOW) | \
- (1 << A3XX_INT_VFD_ERROR) | \
(1 << A3XX_INT_CP_T0_PACKET_IN_IB) | \
(1 << A3XX_INT_CP_OPCODE_ERROR) | \
(1 << A3XX_INT_CP_RESERVED_BIT_ERROR) | \
@@ -2444,7 +2436,6 @@
(1 << A3XX_INT_CP_RB_INT) | \
(1 << A3XX_INT_CP_REG_PROTECT_FAULT) | \
(1 << A3XX_INT_CP_AHB_ERROR_HALT) | \
- (1 << A3XX_INT_MISC_HANG_DETECT) | \
(1 << A3XX_INT_UCHE_OOB_ACCESS))
static struct {
@@ -2474,7 +2465,7 @@
A3XX_IRQ_CALLBACK(a3xx_err_callback), /* 21 - CP_AHB_ERROR_FAULT */
A3XX_IRQ_CALLBACK(NULL), /* 22 - Unused */
A3XX_IRQ_CALLBACK(NULL), /* 23 - Unused */
- A3XX_IRQ_CALLBACK(a3xx_err_callback), /* 24 - MISC_HANG_DETECT */
+ A3XX_IRQ_CALLBACK(NULL), /* 24 - MISC_HANG_DETECT */
A3XX_IRQ_CALLBACK(a3xx_err_callback), /* 25 - UCHE_OOB_ACCESS */
/* 26 to 31 - Unused */
};
@@ -2547,6 +2538,9 @@
{
struct kgsl_device *device = &adreno_dev->dev;
+ /* GMEM size on A320 is 512K */
+ adreno_dev->gmemspace.sizebytes = SZ_512K;
+
/* Reset the core */
adreno_regwrite(device, A3XX_RBBM_SW_RESET_CMD,
0x00000001);
@@ -2570,10 +2564,17 @@
adreno_regwrite(device, A3XX_RBBM_AHB_CTL0, 0x00000001);
/* Enable AHB error reporting */
- adreno_regwrite(device, A3XX_RBBM_AHB_CTL1, 0xA6FFFFFF);
+ adreno_regwrite(device, A3XX_RBBM_AHB_CTL1, 0x86FFFFFF);
/* Turn on the power counters */
adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, 0x00003000);
+
+ /* Turn on hang detection - this spews a lot of useful information
+ * into the RBBM registers on a hang */
+
+ adreno_regwrite(device, A3XX_RBBM_INTERFACE_HANG_INT_CTL,
+ (1 << 16) | 0xFFF);
+
}
/* Defined in adreno_a3xx_snapshot.c */
diff --git a/drivers/gpu/msm/adreno_a3xx_snapshot.c b/drivers/gpu/msm/adreno_a3xx_snapshot.c
index aade50c..c8c7c44 100644
--- a/drivers/gpu/msm/adreno_a3xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a3xx_snapshot.c
@@ -80,7 +80,7 @@
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct kgsl_snapshot_debug *header = snapshot;
unsigned int *data = snapshot + sizeof(*header);
- int i, size = adreno_dev->pm4_fw_size >> 2;
+ int i, size = adreno_dev->pm4_fw_size - 1;
if (remain < DEBUG_SECTION_SZ(size)) {
SNAPSHOT_ERR_NOMEM(device, "CP PM4 RAM DEBUG");
@@ -98,7 +98,7 @@
*/
adreno_regwrite(device, REG_CP_ME_RAM_RADDR, 0x0);
- for (i = 0; i < adreno_dev->pm4_fw_size >> 2; i++)
+ for (i = 0; i < size; i++)
adreno_regread(device, REG_CP_ME_RAM_DATA, &data[i]);
return DEBUG_SECTION_SZ(size);
@@ -110,7 +110,7 @@
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct kgsl_snapshot_debug *header = snapshot;
unsigned int *data = snapshot + sizeof(*header);
- int i, size = adreno_dev->pfp_fw_size >> 2;
+ int i, size = adreno_dev->pfp_fw_size - 1;
if (remain < DEBUG_SECTION_SZ(size)) {
SNAPSHOT_ERR_NOMEM(device, "CP PFP RAM DEBUG");
@@ -127,7 +127,7 @@
* maintain always changing hardcoded constants
*/
kgsl_regwrite(device, A3XX_CP_PFP_UCODE_ADDR, 0x0);
- for (i = 0; i < adreno_dev->pfp_fw_size >> 2; i++)
+ for (i = 0; i < size; i++)
adreno_regread(device, A3XX_CP_PFP_UCODE_DATA, &data[i]);
return DEBUG_SECTION_SZ(size);
@@ -175,7 +175,7 @@
return 0;
}
- val = (id << 0x06) | (1 << 0x10);
+ val = (id << 8) | (1 << 16);
header->id = id;
header->count = DEBUGFS_BLOCK_SIZE;
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index c1b9e4c..b53ca8f 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -143,7 +143,8 @@
return 0;
adreno_dev = ADRENO_DEVICE(device);
- count = adreno_dev->istore_size * ADRENO_ISTORE_WORDS;
+ count = adreno_dev->istore_size * adreno_dev->instruction_size;
+
remaining = count;
for (i = 0; i < count; i += rowc) {
unsigned int vals[rowc];
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index 9bf85cf..aeb89b3 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -86,7 +86,7 @@
gmem_restore_quad[7] = uint2float(shadow->width);
memcpy(shadow->quad_vertices.hostptr, gmem_copy_quad, QUAD_LEN << 2);
- memcpy(shadow->quad_vertices_restore.hostptr, gmem_copy_quad,
+ memcpy(shadow->quad_vertices_restore.hostptr, gmem_restore_quad,
QUAD_RESTORE_LEN << 2);
memcpy(shadow->quad_texcoords.hostptr, gmem_copy_texcoord,
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index fb88a72..cc3f3e7 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -86,7 +86,7 @@
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
int count, i;
- count = adreno_dev->istore_size * ADRENO_ISTORE_WORDS;
+ count = adreno_dev->istore_size * adreno_dev->instruction_size;
if (remain < (count * 4) + sizeof(*header)) {
KGSL_DRV_ERR(device,
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 36248ef..671479e 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -17,6 +17,7 @@
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/iommu.h>
+#include <mach/socinfo.h>
#include "kgsl.h"
#include "kgsl_mmu.h"
@@ -534,9 +535,16 @@
int ret;
if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) {
- memdesc->gpuaddr = memdesc->physaddr;
- return 0;
+ if (memdesc->sglen == 1) {
+ memdesc->gpuaddr = sg_phys(memdesc->sg);
+ return 0;
+ } else {
+ KGSL_CORE_ERR("Memory is not contigious "
+ "(sglen = %d)\n", memdesc->sglen);
+ return -EINVAL;
+ }
}
+
memdesc->gpuaddr = gen_pool_alloc_aligned(pagetable->pool,
memdesc->size, KGSL_MMU_ALIGN_SHIFT);
@@ -712,7 +720,14 @@
void kgsl_mmu_set_mmutype(char *mmutype)
{
- kgsl_mmu_type = iommu_found() ? KGSL_MMU_TYPE_IOMMU : KGSL_MMU_TYPE_GPU;
+ /* Set the default MMU - GPU on <=8960 and nothing on >= 8064 */
+ kgsl_mmu_type =
+ cpu_is_apq8064() ? KGSL_MMU_TYPE_NONE : KGSL_MMU_TYPE_GPU;
+
+ /* Use the IOMMU if it is found */
+ if (iommu_found())
+ kgsl_mmu_type = KGSL_MMU_TYPE_IOMMU;
+
if (mmutype && !strncmp(mmutype, "gpummu", 6))
kgsl_mmu_type = KGSL_MMU_TYPE_GPU;
if (iommu_found() && mmutype && !strncmp(mmutype, "iommu", 5))
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 9f2e3bd..c8b4707 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -33,7 +33,6 @@
#include <linux/slab.h>
#include <linux/pm_runtime.h>
#include <linux/gpio.h>
-#include <mach/socinfo.h>
MODULE_LICENSE("GPL v2");
MODULE_VERSION("0.2");
@@ -307,20 +306,12 @@
/*
* Before calling qup_config_core_on_en(), please make
* sure that QuPE core is in RESET state.
- *
- * Configuration of CORE_ON_EN - BIT13 in QUP_CONFIG register
- * is only required for targets like 7x27a, where it needs
- * be turned on for disabling the QuPE pclks.
*/
static void
qup_config_core_on_en(struct qup_i2c_dev *dev)
{
uint32_t status;
- if (!(cpu_is_msm7x27a() || cpu_is_msm7x27aa() ||
- cpu_is_msm7x25a() || cpu_is_msm7x25aa()))
- return;
-
status = readl_relaxed(dev->base + QUP_CONFIG);
status |= BIT(13);
writel_relaxed(status, dev->base + QUP_CONFIG);
diff --git a/drivers/media/video/msm/csi/msm_ispif.c b/drivers/media/video/msm/csi/msm_ispif.c
index af61bd2..86d62c9 100644
--- a/drivers/media/video/msm/csi/msm_ispif.c
+++ b/drivers/media/video/msm/csi/msm_ispif.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -73,43 +73,54 @@
static struct ispif_device *ispif;
+atomic_t ispif_irq_cnt;
+spinlock_t ispif_tasklet_lock;
+struct list_head ispif_tasklet_q;
static uint32_t global_intf_cmd_mask = 0xFFFFFFFF;
-static int msm_ispif_intf_reset(uint8_t intftype)
+
+static int msm_ispif_intf_reset(uint8_t intfmask)
{
int rc = 0;
- uint32_t data;
+ uint32_t data = 0x1;
+ uint8_t intfnum = 0, mask = intfmask;
+ while (mask != 0) {
+ if (!(intfmask & (0x1 << intfnum))) {
+ mask >>= 1;
+ intfnum++;
+ continue;
+ }
+ switch (intfnum) {
+ case PIX0:
+ data = (0x1 << STROBED_RST_EN) +
+ (0x1 << PIX_VFE_RST_STB) +
+ (0x1 << PIX_CSID_RST_STB);
+ break;
- switch (intftype) {
- case PIX0:
- data = (0x1 << STROBED_RST_EN) +
- (0x1 << PIX_VFE_RST_STB) +
- (0x1 << PIX_CSID_RST_STB);
+ case RDI0:
+ data = (0x1 << STROBED_RST_EN) +
+ (0x1 << RDI_VFE_RST_STB) +
+ (0x1 << RDI_CSID_RST_STB);
+ break;
+
+ case RDI1:
+ data = (0x1 << STROBED_RST_EN) +
+ (0x1 << RDI_1_VFE_RST_STB) +
+ (0x1 << RDI_1_CSID_RST_STB);
+ break;
+
+ default:
+ rc = -EINVAL;
+ break;
+ }
+ mask >>= 1;
+ intfnum++;
+ } /*end while */
+ if (rc >= 0) {
msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
- break;
-
- case RDI0:
- data = (0x1 << STROBED_RST_EN) +
- (0x1 << RDI_VFE_RST_STB) +
- (0x1 << RDI_CSID_RST_STB);
- msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
- break;
-
- case RDI1:
- data = (0x1 << STROBED_RST_EN) +
- (0x1 << RDI_1_VFE_RST_STB) +
- (0x1 << RDI_1_CSID_RST_STB);
- msm_io_w(data, ispif->base + ISPIF_RST_CMD_ADDR);
- break;
-
- default:
- rc = -EINVAL;
- break;
+ rc = wait_for_completion_interruptible(&ispif->reset_complete);
}
- if (rc >= 0)
- rc = wait_for_completion_interruptible(
- &ispif->reset_complete);
return rc;
}
@@ -244,97 +255,109 @@
}
static void
-msm_ispif_intf_cmd(uint8_t intftype, uint8_t intf_cmd_mask)
+msm_ispif_intf_cmd(uint8_t intfmask, uint8_t intf_cmd_mask)
{
uint8_t vc = 0, val = 0;
- uint32_t cid_mask = msm_ispif_get_cid_mask(intftype);
-
- while (cid_mask != 0) {
- if ((cid_mask & 0xf) != 0x0) {
- val = (intf_cmd_mask>>(vc*2)) & 0x3;
- global_intf_cmd_mask &= ~((0x3 & ~val)
- <<((vc*2)+(intftype*8)));
- CDBG("intf cmd 0x%x\n", global_intf_cmd_mask);
- msm_io_w(global_intf_cmd_mask,
- ispif->base + ISPIF_INTF_CMD_ADDR);
+ uint8_t mask = intfmask, intfnum = 0;
+ uint32_t cid_mask = 0;
+ while (mask != 0) {
+ if (!(intfmask & (0x1 << intfnum))) {
+ mask >>= 1;
+ intfnum++;
+ continue;
}
- vc++;
- cid_mask >>= 4;
+
+ cid_mask = msm_ispif_get_cid_mask(intfnum);
+ vc = 0;
+
+ while (cid_mask != 0) {
+ if ((cid_mask & 0xf) != 0x0) {
+ val = (intf_cmd_mask>>(vc*2)) & 0x3;
+ global_intf_cmd_mask |=
+ (0x3 << ((vc * 2) + (intfnum * 8)));
+ global_intf_cmd_mask &= ~((0x3 & ~val)
+ << ((vc * 2) +
+ (intfnum * 8)));
+ }
+ vc++;
+ cid_mask >>= 4;
+ }
+ mask >>= 1;
+ intfnum++;
}
+ msm_io_w(global_intf_cmd_mask, ispif->base + ISPIF_INTF_CMD_ADDR);
}
-static int msm_ispif_abort_intf_transfer(uint8_t intf)
+static int msm_ispif_abort_intf_transfer(uint8_t intfmask)
{
int rc = 0;
uint8_t intf_cmd_mask = 0xAA;
-
- CDBG("abort stream request\n");
+ uint8_t intfnum = 0, mask = intfmask;
mutex_lock(&ispif->mutex);
- msm_ispif_intf_cmd(intf, intf_cmd_mask);
- rc = msm_ispif_intf_reset(intf);
- global_intf_cmd_mask |= 0xFF<<(intf * 8);
+ msm_ispif_intf_cmd(intfmask, intf_cmd_mask);
+ while (mask != 0) {
+ if (intfmask & (0x1 << intfnum))
+ global_intf_cmd_mask |= (0xFF << (intfnum * 8));
+ mask >>= 1;
+ intfnum++;
+ }
mutex_unlock(&ispif->mutex);
return rc;
}
-static int msm_ispif_start_intf_transfer(uint8_t intf)
+static int msm_ispif_start_intf_transfer(uint8_t intfmask)
{
- uint32_t data;
uint8_t intf_cmd_mask = 0x55;
int rc = 0;
-
- CDBG("start stream request\n");
mutex_lock(&ispif->mutex);
- switch (intf) {
- case PIX0:
- data = msm_io_r(ispif->base + ISPIF_PIX_STATUS_ADDR);
- if ((data & 0xf) != 0xf) {
- CDBG("interface is busy\n");
- mutex_unlock(&ispif->mutex);
- return -EBUSY;
- }
- break;
-
- case RDI0:
- data = msm_io_r(ispif->base + ISPIF_RDI_STATUS_ADDR);
- ispif->start_ack_pending = 1;
- break;
-
- case RDI1:
- data = msm_io_r(ispif->base + ISPIF_RDI_1_STATUS_ADDR);
- ispif->start_ack_pending = 1;
- break;
- }
- msm_ispif_intf_cmd(intf, intf_cmd_mask);
+ rc = msm_ispif_intf_reset(intfmask);
+ msm_ispif_intf_cmd(intfmask, intf_cmd_mask);
mutex_unlock(&ispif->mutex);
return rc;
}
-static int msm_ispif_stop_intf_transfer(uint8_t intf)
+static int msm_ispif_stop_intf_transfer(uint8_t intfmask)
{
int rc = 0;
uint8_t intf_cmd_mask = 0x00;
- CDBG("stop stream request\n");
+ uint8_t intfnum = 0, mask = intfmask;
mutex_lock(&ispif->mutex);
- msm_ispif_intf_cmd(intf, intf_cmd_mask);
- switch (intf) {
- case PIX0:
- while ((msm_io_r(ispif->base + ISPIF_PIX_STATUS_ADDR)
- & 0xf) != 0xf) {
- CDBG("Wait for Idle\n");
- }
- break;
+ msm_ispif_intf_cmd(intfmask, intf_cmd_mask);
+ while (mask != 0) {
+ if (intfmask & (0x1 << intfnum)) {
+ switch (intfnum) {
+ case PIX0:
+ while ((msm_io_r(ispif->base +
+ ISPIF_PIX_STATUS_ADDR)
+ & 0xf) != 0xf) {
+ CDBG("Wait for pix0 Idle\n");
+ }
+ break;
- case RDI0:
- while ((msm_io_r(ispif->base + ISPIF_RDI_STATUS_ADDR)
- & 0xf) != 0xf) {
- CDBG("Wait for Idle\n");
+ case RDI0:
+ while ((msm_io_r(ispif->base +
+ ISPIF_RDI_STATUS_ADDR)
+ & 0xf) != 0xf) {
+ CDBG("Wait for rdi0 Idle\n");
+ }
+ break;
+
+ case RDI1:
+ while ((msm_io_r(ispif->base +
+ ISPIF_RDI_1_STATUS_ADDR)
+ & 0xf) != 0xf) {
+ CDBG("Wait for rdi1 Idle\n");
+ }
+ break;
+
+ default:
+ break;
+ }
+ global_intf_cmd_mask |= (0xFF << (intfnum * 8));
}
- break;
- default:
- break;
+ mask >>= 1;
+ intfnum++;
}
- global_intf_cmd_mask |= 0xFF<<(intf * 8);
mutex_unlock(&ispif->mutex);
return rc;
}
@@ -364,10 +387,77 @@
return rc;
}
+static void ispif_do_tasklet(unsigned long data)
+{
+ unsigned long flags;
+
+ struct ispif_isr_queue_cmd *qcmd = NULL;
+ CDBG("=== ispif_do_tasklet start ===\n");
+
+ while (atomic_read(&ispif_irq_cnt)) {
+ spin_lock_irqsave(&ispif_tasklet_lock, flags);
+ qcmd = list_first_entry(&ispif_tasklet_q,
+ struct ispif_isr_queue_cmd, list);
+ atomic_sub(1, &ispif_irq_cnt);
+
+ if (!qcmd) {
+ spin_unlock_irqrestore(&ispif_tasklet_lock,
+ flags);
+ return;
+ }
+ list_del(&qcmd->list);
+ spin_unlock_irqrestore(&ispif_tasklet_lock,
+ flags);
+ if (qcmd->ispifInterruptStatus0 &
+ ISPIF_IRQ_STATUS_RDI_SOF_MASK) {
+ CDBG("ispif rdi irq status\n");
+ }
+ if (qcmd->ispifInterruptStatus1 &
+ ISPIF_IRQ_STATUS_RDI_SOF_MASK) {
+ CDBG("ispif rdi1 irq status\n");
+ }
+ kfree(qcmd);
+ }
+ CDBG("=== ispif_do_tasklet end ===\n");
+}
+
+DECLARE_TASKLET(ispif_tasklet, ispif_do_tasklet, 0);
+
+static void ispif_process_irq(struct ispif_irq_status *out)
+{
+ unsigned long flags;
+ struct ispif_isr_queue_cmd *qcmd;
+
+ CDBG("ispif_process_irq\n");
+ qcmd = kzalloc(sizeof(struct ispif_isr_queue_cmd),
+ GFP_ATOMIC);
+ if (!qcmd) {
+ pr_err("ispif_process_irq: qcmd malloc failed!\n");
+ return;
+ }
+ qcmd->ispifInterruptStatus0 = out->ispifIrqStatus0;
+ qcmd->ispifInterruptStatus1 = out->ispifIrqStatus1;
+
+ spin_lock_irqsave(&ispif_tasklet_lock, flags);
+ list_add_tail(&qcmd->list, &ispif_tasklet_q);
+
+ atomic_add(1, &ispif_irq_cnt);
+ spin_unlock_irqrestore(&ispif_tasklet_lock, flags);
+ tasklet_schedule(&ispif_tasklet);
+ return;
+}
+
static inline void msm_ispif_read_irq_status(struct ispif_irq_status *out)
{
out->ispifIrqStatus0 = msm_io_r(ispif->base +
- ISPIF_IRQ_STATUS_ADDR);
+ ISPIF_IRQ_STATUS_ADDR);
+ out->ispifIrqStatus1 = msm_io_r(ispif->base +
+ ISPIF_IRQ_STATUS_1_ADDR);
+ msm_io_w(out->ispifIrqStatus0,
+ ispif->base + ISPIF_IRQ_CLEAR_ADDR);
+ msm_io_w(out->ispifIrqStatus1,
+ ispif->base + ISPIF_IRQ_CLEAR_1_ADDR);
+
CDBG("ispif->irq: Irq_status0 = 0x%x\n",
out->ispifIrqStatus0);
if (out->ispifIrqStatus0 & ISPIF_IRQ_STATUS_MASK) {
@@ -377,23 +467,14 @@
pr_err("%s: pix intf 0 overflow.\n", __func__);
if (out->ispifIrqStatus0 & (0x1 << RAW_INTF_0_OVERFLOW_IRQ))
pr_err("%s: rdi intf 0 overflow.\n", __func__);
- if (out->ispifIrqStatus0 & ISPIF_IRQ_STATUS_RDI_SOF_MASK) {
- if (ispif->start_ack_pending) {
- v4l2_subdev_notify(&ispif->subdev,
- NOTIFY_ISP_MSG_EVT,
- (void *)MSG_ID_START_ACK);
- ispif->start_ack_pending = 0;
- /* stop stream at frame boundary */
- msm_ispif_stop_intf_transfer(RDI0);
- }
- v4l2_subdev_notify(&ispif->subdev, NOTIFY_ISP_MSG_EVT,
- (void *)MSG_ID_SOF_ACK);
+ if ((out->ispifIrqStatus0 & ISPIF_IRQ_STATUS_RDI_SOF_MASK) ||
+ (out->ispifIrqStatus1 &
+ ISPIF_IRQ_STATUS_RDI_SOF_MASK)) {
+ ispif_process_irq(out);
}
}
- msm_io_w(out->ispifIrqStatus0,
- ispif->base + ISPIF_IRQ_CLEAR_ADDR);
msm_io_w(ISPIF_IRQ_GLOBAL_CLEAR_CMD, ispif->base +
- ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
+ ISPIF_IRQ_GLOBAL_CLEAR_CMD_ADDR);
}
static irqreturn_t msm_io_ispif_irq(int irq_num, void *data)
@@ -414,6 +495,8 @@
static int msm_ispif_init(const uint32_t *csid_version)
{
int rc = 0;
+ spin_lock_init(&ispif_tasklet_lock);
+ INIT_LIST_HEAD(&ispif_tasklet_q);
rc = request_irq(ispif->irq->start, msm_io_ispif_irq,
IRQF_TRIGGER_RISING, "ispif", 0);
@@ -451,6 +534,7 @@
CDBG("%s, free_irq\n", __func__);
free_irq(ispif->irq->start, 0);
+ tasklet_kill(&ispif_tasklet);
}
void msm_ispif_vfe_get_cid(uint8_t intftype, char *cids, int *num)
diff --git a/drivers/media/video/msm/csi/msm_ispif.h b/drivers/media/video/msm/csi/msm_ispif.h
index deadc28..8f1dd12 100644
--- a/drivers/media/video/msm/csi/msm_ispif.h
+++ b/drivers/media/video/msm/csi/msm_ispif.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
@@ -36,6 +36,12 @@
struct clk *ispif_clk[5];
};
+struct ispif_isr_queue_cmd {
+ struct list_head list;
+ uint32_t ispifInterruptStatus0;
+ uint32_t ispifInterruptStatus1;
+};
+
#define VIDIOC_MSM_ISPIF_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct msm_ispif_params)
@@ -51,6 +57,12 @@
#define ISPIF_OFF_IMMEDIATELY (0x01 << 2)
#define ISPIF_S_STREAM_SHIFT 4
+
+#define PIX_0 (0x01 << 0)
+#define RDI_0 (0x01 << 1)
+#define PIX_1 (0x01 << 2)
+#define RDI_1 (0x01 << 3)
+
void msm_ispif_vfe_get_cid(uint8_t intftype, char *cids, int *num);
#endif
diff --git a/drivers/media/video/msm/io/msm_io_util.c b/drivers/media/video/msm/io/msm_io_util.c
index 0ae247e..207f8be 100644
--- a/drivers/media/video/msm/io/msm_io_util.c
+++ b/drivers/media/video/msm/io/msm_io_util.c
@@ -40,29 +40,42 @@
goto cam_clk_set_err;
}
}
+ rc = clk_prepare(clk_ptr[i]);
+ if (rc < 0) {
+ pr_err("%s prepare failed\n",
+ clk_info[i].clk_name);
+ goto cam_clk_prepare_err;
+ }
+
rc = clk_enable(clk_ptr[i]);
if (rc < 0) {
pr_err("%s enable failed\n",
clk_info[i].clk_name);
- goto cam_clk_set_err;
+ goto cam_clk_enable_err;
}
}
} else {
for (i = num_clk - 1; i >= 0; i--) {
- if (clk_ptr[i] != NULL)
+ if (clk_ptr[i] != NULL) {
clk_disable(clk_ptr[i]);
+ clk_unprepare(clk_ptr[i]);
clk_put(clk_ptr[i]);
+ }
}
}
return rc;
+cam_clk_enable_err:
+ clk_unprepare(clk_ptr[i]);
+cam_clk_prepare_err:
cam_clk_set_err:
clk_put(clk_ptr[i]);
cam_clk_get_err:
for (i--; i >= 0; i--) {
if (clk_ptr[i] != NULL) {
clk_disable(clk_ptr[i]);
+ clk_unprepare(clk_ptr[i]);
clk_put(clk_ptr[i]);
}
}
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 22322b8..7680559 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -116,6 +116,7 @@
NOTIFY_ISP_MSG_EVT, /* arg = enum ISP_MESSAGE_ID */
NOTIFY_VFE_MSG_OUT, /* arg = struct isp_msg_output */
NOTIFY_VFE_MSG_STATS, /* arg = struct isp_msg_stats */
+ NOTIFY_VFE_MSG_COMP_STATS, /* arg = struct msm_stats_buf */
NOTIFY_VFE_BUF_EVT, /* arg = struct msm_vfe_resp */
NOTIFY_ISPIF_STREAM, /* arg = enable parameter for s_stream */
NOTIFY_VPE_MSG_EVT,
@@ -426,7 +427,7 @@
int msg_type, struct msm_free_buf *buf,
uint32_t frame_id);
int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
- int msg_type, struct msm_free_buf *frame, int dirty);
+ int msg_type, struct msm_free_buf *frame, int dirty, int node_type);
int msm_mctl_reserve_free_buf(struct msm_cam_media_controller *pmctl,
struct msm_cam_v4l2_dev_inst *pcam_inst,
int path, struct msm_free_buf *free_buf);
@@ -473,7 +474,7 @@
int msm_mctl_pp_notify(struct msm_cam_media_controller *pmctl,
struct msm_mctl_pp_frame_info *pp_frame_info);
int msm_mctl_img_mode_to_inst_index(struct msm_cam_media_controller *pmctl,
- int out_type);
+ int out_type, int node_type);
struct msm_frame_buffer *msm_mctl_buf_find(
struct msm_cam_media_controller *pmctl,
struct msm_cam_v4l2_dev_inst *pcam_inst, int del_buf,
diff --git a/drivers/media/video/msm/msm_io_8960.c b/drivers/media/video/msm/msm_io_8960.c
index 79294a3..d111452 100644
--- a/drivers/media/video/msm/msm_io_8960.c
+++ b/drivers/media/video/msm/msm_io_8960.c
@@ -29,6 +29,7 @@
static struct clk *camio_jpeg_clk;
static struct clk *camio_jpeg_pclk;
+static struct clk *camio_imem_clk;
static struct regulator *fs_ijpeg;
static struct platform_device *camio_dev;
@@ -129,6 +130,11 @@
clk = clk_get(NULL, "ijpeg_pclk");
break;
+ case CAMIO_IMEM_CLK:
+ camio_imem_clk =
+ clk = clk_get(NULL, "imem_clk");
+ break;
+
default:
break;
}
@@ -158,6 +164,10 @@
clk = camio_jpeg_pclk;
break;
+ case CAMIO_IMEM_CLK:
+ clk = camio_imem_clk;
+ break;
+
default:
break;
}
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 6b3aef7..bb50d77 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -142,7 +142,7 @@
{
int rc = -EINVAL, image_mode;
struct msm_vfe_resp *vdata = (struct msm_vfe_resp *)arg;
- struct msm_free_buf free_buf;
+ struct msm_free_buf free_buf, temp_free_buf;
struct msm_camvfe_params vfe_params;
struct msm_vfe_cfg_cmd cfgcmd;
struct msm_sync *sync =
@@ -190,7 +190,12 @@
vfe_params.vfe_cfg = &cfgcmd;
vfe_params.data = (void *)&free_buf;
rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
- /* Write the same buffer into PONG */
+ temp_free_buf = free_buf;
+ if (msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+ image_mode, &free_buf)) {
+ /* Write the same buffer into PONG */
+ free_buf = temp_free_buf;
+ }
cfgcmd.cmd_type = CMD_CONFIG_PONG_ADDR;
cfgcmd.value = &vfe_id;
vfe_params.vfe_cfg = &cfgcmd;
@@ -307,6 +312,36 @@
}
}
break;
+ case NOTIFY_VFE_MSG_COMP_STATS: {
+ struct msm_stats_buf *stats = (struct msm_stats_buf *)arg;
+ struct msm_stats_buf *stats_buf = NULL;
+
+ isp_event->isp_data.isp_msg.msg_id = MSG_ID_STATS_COMPOSITE;
+ stats->aec.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->aec.buff, &(stats->aec.fd));
+ stats->awb.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->awb.buff, &(stats->awb.fd));
+ stats->af.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->af.buff, &(stats->af.fd));
+ stats->ihist.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->ihist.buff, &(stats->ihist.fd));
+ stats->rs.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->rs.buff, &(stats->rs.fd));
+ stats->cs.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->cs.buff, &(stats->cs.fd));
+
+ stats_buf = kmalloc(sizeof(struct msm_stats_buf), GFP_ATOMIC);
+ if (!stats_buf) {
+ pr_err("%s: out of memory.\n", __func__);
+ rc = -ENOMEM;
+ } else {
+ *stats_buf = *stats;
+ isp_event->isp_data.isp_msg.len =
+ sizeof(struct msm_stats_buf);
+ isp_event->isp_data.isp_msg.data = stats_buf;
+ }
+ }
+ break;
case NOTIFY_VFE_MSG_STATS: {
struct msm_stats_buf stats;
struct isp_msg_stats *isp_stats = (struct isp_msg_stats *)arg;
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 2c4fbe4..13d1daf 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -241,6 +241,7 @@
case NOTIFY_ISP_MSG_EVT:
case NOTIFY_VFE_MSG_OUT:
case NOTIFY_VFE_MSG_STATS:
+ case NOTIFY_VFE_MSG_COMP_STATS:
case NOTIFY_VFE_BUF_EVT:
case NOTIFY_VFE_BUF_FREE_EVT:
if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 1ab76fe..8148f1f 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -325,9 +325,13 @@
}
int msm_mctl_img_mode_to_inst_index(struct msm_cam_media_controller *pmctl,
- int image_mode)
+ int image_mode, int node_type)
{
- if ((image_mode >= 0) &&
+ if ((image_mode >= 0) && node_type &&
+ pmctl->sync.pcam_sync->mctl_node.dev_inst_map[image_mode])
+ return pmctl->sync.pcam_sync->
+ mctl_node.dev_inst_map[image_mode]->my_index;
+ else if ((image_mode >= 0) &&
pmctl->sync.pcam_sync->dev_inst_map[image_mode])
return pmctl->sync.pcam_sync->
dev_inst_map[image_mode]->my_index;
@@ -424,13 +428,13 @@
msm_mctl_check_pp(p_mctl, image_mode, &pp_divert_type, &pp_type);
D("%s: pp_type=%d, pp_divert_type = %d, frame_id = 0x%x",
- __func__, pp_type, pp_divert_type, frame_id);
+ __func__, pp_type, pp_divert_type, frame_id);
if (pp_type || pp_divert_type)
rc = msm_mctl_do_pp_divert(p_mctl,
image_mode, fbuf, frame_id, pp_type);
else {
idx = msm_mctl_img_mode_to_inst_index(
- p_mctl, image_mode);
+ p_mctl, image_mode, 0);
if (idx < 0) {
pr_err("%s Invalid instance, dropping buffer\n",
__func__);
@@ -450,6 +454,22 @@
return 0;
}
+static int is_buffer_queued(struct msm_cam_v4l2_device *pcam, int image_mode)
+{
+ int idx;
+ int ret = 0;
+ struct msm_frame_buffer *buf = NULL;
+ struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
+ idx = pcam->mctl_node.dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ list_for_each_entry(buf, &pcam_inst->free_vq, list) {
+ if (buf->state != MSM_BUFFER_STATE_QUEUED)
+ continue;
+ ret = 1;
+ }
+ return ret;
+}
+
struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst(
struct msm_cam_media_controller *pmctl,
int image_mode)
@@ -462,22 +482,39 @@
/* Valid image mode. Search the mctl node first.
* If mctl node doesnt have the instance, then
* search in the user's video node */
- if (pcam->mctl_node.dev_inst_map[image_mode]) {
- idx =
- pcam->mctl_node.dev_inst_map[image_mode]->my_index;
- pcam_inst = pcam->mctl_node.dev_inst[idx];
- D("%s Found instance %p in mctl node device\n",
+ if (pmctl->vfe_output_mode == VFE_OUTPUTS_MAIN_AND_THUMB
+ || pmctl->vfe_output_mode == VFE_OUTPUTS_THUMB_AND_MAIN) {
+ if (pcam->mctl_node.dev_inst_map[image_mode]
+ && is_buffer_queued(pcam, image_mode)) {
+ idx =
+ pcam->mctl_node.dev_inst_map[image_mode]
+ ->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ D("%s Found instance %p in mctl node device\n",
+ __func__, pcam_inst);
+ } else if (pcam->dev_inst_map[image_mode]) {
+ idx = pcam->dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->dev_inst[idx];
+ D("%s Found instance %p in video device",
__func__, pcam_inst);
- } else if (pcam->dev_inst_map[image_mode]) {
- idx = pcam->dev_inst_map[image_mode]->my_index;
- pcam_inst = pcam->dev_inst[idx];
- D("%s Found instance %p in video device",
+ }
+ } else {
+ if (pcam->mctl_node.dev_inst_map[image_mode]) {
+ idx = pcam->mctl_node.dev_inst_map[image_mode]
+ ->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ D("%s Found instance %p in mctl node device\n",
__func__, pcam_inst);
+ } else if (pcam->dev_inst_map[image_mode]) {
+ idx = pcam->dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->dev_inst[idx];
+ D("%s Found instance %p in video device",
+ __func__, pcam_inst);
+ }
}
} else
pr_err("%s Invalid image mode %d. Return NULL\n",
__func__, image_mode);
-
return pcam_inst;
}
@@ -597,19 +634,21 @@
return rc;
}
-int msm_mctl_buf_done_pp(
- struct msm_cam_media_controller *pmctl,
- int image_mode, struct msm_free_buf *frame, int dirty)
+int msm_mctl_buf_done_pp(struct msm_cam_media_controller *pmctl,
+ int image_mode, struct msm_free_buf *frame, int dirty, int node_type)
{
struct msm_cam_v4l2_dev_inst *pcam_inst;
int rc = 0, idx;
- idx = msm_mctl_img_mode_to_inst_index(pmctl, image_mode);
+ idx = msm_mctl_img_mode_to_inst_index(pmctl, image_mode, node_type);
if (idx < 0) {
pr_err("%s Invalid instance, buffer not released\n", __func__);
return idx;
}
- pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+ if (node_type)
+ pcam_inst = pmctl->sync.pcam_sync->mctl_node.dev_inst[idx];
+ else
+ pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
if (!pcam_inst) {
pr_err("%s Invalid instance, cannot send buf to user",
__func__);
@@ -638,7 +677,7 @@
int rc = -EINVAL, idx;
idx = msm_mctl_img_mode_to_inst_index(pmctl,
- image_mode);
+ image_mode, 0);
if (idx < 0) {
pr_err("%s Invalid instance, cant get buffer\n", __func__);
return NULL;
@@ -677,7 +716,7 @@
struct msm_frame_buffer *buf = NULL;
idx = msm_mctl_img_mode_to_inst_index(pmctl,
- image_mode);
+ image_mode, 0);
if (idx < 0) {
pr_err("%s Invalid instance, cant put buffer\n", __func__);
return idx;
@@ -712,7 +751,7 @@
int idx;
idx = msm_mctl_img_mode_to_inst_index(pmctl,
- image_mode);
+ image_mode, 0);
if (idx < 0) {
pr_err("%s Invalid instance, cant delete buffer\n", __func__);
return idx;
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index 1593e7e..82c5bf7 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -95,20 +95,95 @@
*pp_type = OUTPUT_TYPE_V;
break;
case MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL:
+ pp_key = PP_THUMB;
+ if (p_mctl->pp_info.pp_key & pp_key)
+ *pp_divert_type = OUTPUT_TYPE_T;
if (p_mctl->pp_info.pp_ctrl.pp_msg_type == OUTPUT_TYPE_T)
*pp_type = OUTPUT_TYPE_T;
break;
default:
break;
}
- if (p_mctl->pp_info.div_frame[image_mode].ch_paddr[0])
- *pp_divert_type = 0;
+ if (p_mctl->vfe_output_mode != VFE_OUTPUTS_MAIN_AND_THUMB &&
+ p_mctl->vfe_output_mode != VFE_OUTPUTS_THUMB_AND_MAIN) {
+ if (p_mctl->pp_info.div_frame[image_mode].ch_paddr[0])
+ *pp_divert_type = 0;
+ }
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
D("%s: pp_type=%d, pp_divert_type = %d",
__func__, *pp_type, *pp_divert_type);
return rc;
}
+static int is_buf_in_queue(struct msm_cam_v4l2_device *pcam,
+ struct msm_free_buf *fbuf, int image_mode)
+{
+ struct msm_frame_buffer *buf = NULL, *tmp;
+ struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
+ unsigned long flags = 0;
+ struct videobuf2_contig_pmem *mem;
+ uint32_t buf_idx, offset = 0;
+ uint32_t buf_phyaddr = 0;
+ int idx;
+ idx = pcam->mctl_node.dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
+ list_for_each_entry_safe(buf, tmp,
+ &pcam_inst->free_vq, list) {
+ buf_idx = buf->vidbuf.v4l2_buf.index;
+ mem = vb2_plane_cookie(&buf->vidbuf, 0);
+ if (mem->buffer_type == VIDEOBUF2_MULTIPLE_PLANES)
+ offset = mem->offset.data_offset +
+ pcam_inst->buf_offset[buf_idx][0].data_offset;
+ else
+ offset = mem->offset.sp_off.y_off;
+ buf_phyaddr = (unsigned long)
+ videobuf2_to_pmem_contig(&buf->vidbuf, 0) +
+ offset;
+ D("%s vb_idx=%d,vb_paddr=0x%x ch0=0x%x\n",
+ __func__, buf->vidbuf.v4l2_buf.index,
+ buf_phyaddr, fbuf->ch_paddr[0]);
+ if (fbuf->ch_paddr[0] == buf_phyaddr) {
+ spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+ return 1;
+ }
+ }
+ spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
+ return 0;
+}
+static struct msm_cam_v4l2_dev_inst *msm_mctl_get_pcam_inst_for_divert(
+ struct msm_cam_media_controller *pmctl,
+ int image_mode, struct msm_free_buf *fbuf, int *node_type)
+{
+ struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
+ struct msm_cam_v4l2_device *pcam = pmctl->sync.pcam_sync;
+ int idx;
+
+ if (image_mode >= 0) {
+ /* Valid image mode. Search the mctl node first.
+ * If mctl node doesnt have the instance, then
+ * search in the user's video node */
+ if (pcam->mctl_node.dev_inst_map[image_mode]
+ && is_buf_in_queue(pcam, fbuf, image_mode)) {
+ idx =
+ pcam->mctl_node.dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->mctl_node.dev_inst[idx];
+ *node_type = MCTL_NODE;
+ D("%s Found instance %p in mctl node device\n",
+ __func__, pcam_inst);
+ } else if (pcam->dev_inst_map[image_mode]) {
+ idx = pcam->dev_inst_map[image_mode]->my_index;
+ pcam_inst = pcam->dev_inst[idx];
+ *node_type = VIDEO_NODE;
+ D("%s Found instance %p in video device",
+ __func__, pcam_inst);
+ } else
+ pr_err("%s Invalid image mode %d. Return NULL\n",
+ __func__, image_mode);
+ }
+ return pcam_inst;
+}
+
int msm_mctl_do_pp_divert(
struct msm_cam_media_controller *p_mctl,
int image_mode, struct msm_free_buf *fbuf,
@@ -120,8 +195,10 @@
struct msm_cam_evt_divert_frame div;
struct msm_frame_buffer *vb = NULL;
struct videobuf2_contig_pmem *mem;
+ int node;
- pcam_inst = msm_mctl_get_pcam_inst(p_mctl, image_mode);
+ pcam_inst = msm_mctl_get_pcam_inst_for_divert
+ (p_mctl, image_mode, fbuf, &node);
if (!pcam_inst) {
pr_err("%s Invalid instance. Cannot divert frame.\n",
__func__);
@@ -155,6 +232,7 @@
* this buffer.*/
mem = vb2_plane_cookie(&vb->vidbuf, 0);
div.frame.path = mem->path;
+ div.frame.node_type = node;
if (mem->buffer_type == VIDEOBUF2_SINGLE_PLANE) {
/* This buffer contains only 1 plane. Use the
* single planar structure to store the info.*/
@@ -670,7 +748,7 @@
done_frame.vb =
pp_frame_info->dest_frame.handle;
msm_mctl_buf_done_pp(
- p_mctl, img_mode, &done_frame, 0);
+ p_mctl, img_mode, &done_frame, 0, 0);
D("%s: vpe done to app, vb=0x%x, path=%d, phy=0x%x",
__func__, done_frame.vb,
pp_frame_cmd->path, done_frame.ch_paddr[0]);
@@ -848,7 +926,7 @@
}
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
/* here buf.addr is phy_addr */
- rc = msm_mctl_buf_done_pp(p_mctl, image_mode, &buf, dirty);
+ rc = msm_mctl_buf_done_pp(p_mctl, image_mode, &buf, dirty, 0);
return rc;
}
@@ -882,6 +960,9 @@
image_mode = MSM_V4L2_EXT_CAPTURE_MODE_VIDEO;
break;
case OUTPUT_TYPE_T:
+ msg_type = VFE_MSG_OUTPUT_T;
+ image_mode = MSM_V4L2_EXT_CAPTURE_MODE_THUMBNAIL;
+ break;
default:
rc = -EFAULT;
goto err;
@@ -895,7 +976,8 @@
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
D("%s Frame done id: %d\n", __func__, frame.frame_id);
- rc = msm_mctl_buf_done_pp(p_mctl, image_mode, &buf, dirty);
+ rc = msm_mctl_buf_done_pp(p_mctl, image_mode,
+ &buf, dirty, frame.node_type);
return rc;
err:
spin_unlock_irqrestore(&p_mctl->pp_info.lock, flags);
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 4b86bd8..99d9911 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -547,6 +547,10 @@
memset(&(vfe32_ctrl->csStatsControl), 0,
sizeof(struct vfe_stats_control));
+
+ vfe32_ctrl->frame_skip_cnt = 31;
+ vfe32_ctrl->frame_skip_pattern = 0xffffffff;
+ vfe32_ctrl->snapshot_frame_cnt = 0;
}
static void vfe32_reset(void)
@@ -589,6 +593,7 @@
vfe32_ctrl->operation_mode = *p;
vfe32_ctrl->stats_comp = *(++p);
+ vfe32_ctrl->hfr_mode = *(++p);
msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_CFG);
msm_io_w(*(++p), vfe32_ctrl->vfebase + VFE_MODULE_CFG);
@@ -684,10 +689,16 @@
static void vfe32_start_common(void)
{
+ uint32_t irq_mask = 0x00E00021;
vfe32_ctrl->start_ack_pending = TRUE;
CDBG("VFE opertaion mode = 0x%x, output mode = 0x%x\n",
vfe32_ctrl->operation_mode, vfe32_ctrl->outpath.output_mode);
- msm_io_w(0x00EFE021, vfe32_ctrl->vfebase + VFE_IRQ_MASK_0);
+ if (vfe32_ctrl->stats_comp)
+ irq_mask |= VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK;
+ else
+ irq_mask |= 0x000FE000;
+
+ msm_io_w(irq_mask, vfe32_ctrl->vfebase + VFE_IRQ_MASK_0);
msm_io_w(VFE_IMASK_WHILE_STOPPING_1,
vfe32_ctrl->vfebase + VFE_IRQ_MASK_1);
@@ -2363,6 +2374,23 @@
goto proc_general_done;
}
break;
+ case VFE_CMD_FRAME_SKIP_CFG:
+ if (cmd->length != vfe32_cmd[cmd->id].length)
+ return -EINVAL;
+
+ cmdp = kmalloc(vfe32_cmd[cmd->id].length, GFP_ATOMIC);
+ if (!cmdp) {
+ rc = -ENOMEM;
+ goto proc_general_done;
+ }
+
+ CHECKED_COPY_FROM_USER(cmdp);
+ msm_io_memcpy(vfe32_ctrl->vfebase + vfe32_cmd[cmd->id].offset,
+ cmdp, (vfe32_cmd[cmd->id].length));
+ vfe32_ctrl->frame_skip_cnt = ((uint32_t)
+ *cmdp & VFE_FRAME_SKIP_PERIOD_MASK) + 1;
+ vfe32_ctrl->frame_skip_pattern = (uint32_t)(*(cmdp + 2));
+ break;
default:
if (cmd->length != vfe32_cmd[cmd->id].length)
return -EINVAL;
@@ -2389,47 +2417,73 @@
static void vfe32_stats_af_ack(struct vfe_cmd_stats_ack *pAck)
{
unsigned long flags;
- spin_lock_irqsave(&vfe32_ctrl->af_ack_lock, flags);
+ spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ &vfe32_ctrl->comp_stats_ack_lock :
+ &vfe32_ctrl->af_ack_lock);
+ spin_lock_irqsave(lock, flags);
vfe32_ctrl->afStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
vfe32_ctrl->afStatsControl.ackPending = FALSE;
- spin_unlock_irqrestore(&vfe32_ctrl->af_ack_lock, flags);
+ spin_unlock_irqrestore(lock, flags);
}
static void vfe32_stats_awb_ack(struct vfe_cmd_stats_ack *pAck)
{
unsigned long flags;
- spin_lock_irqsave(&vfe32_ctrl->awb_ack_lock, flags);
+ spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ &vfe32_ctrl->comp_stats_ack_lock :
+ &vfe32_ctrl->awb_ack_lock);
+ spin_lock_irqsave(lock, flags);
vfe32_ctrl->awbStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
vfe32_ctrl->awbStatsControl.ackPending = FALSE;
- spin_unlock_irqrestore(&vfe32_ctrl->awb_ack_lock, flags);
+ spin_unlock_irqrestore(lock, flags);
}
static void vfe32_stats_aec_ack(struct vfe_cmd_stats_ack *pAck)
{
unsigned long flags;
- spin_lock_irqsave(&vfe32_ctrl->aec_ack_lock, flags);
+ spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ &vfe32_ctrl->comp_stats_ack_lock :
+ &vfe32_ctrl->aec_ack_lock);
+ spin_lock_irqsave(lock, flags);
vfe32_ctrl->aecStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
vfe32_ctrl->aecStatsControl.ackPending = FALSE;
- spin_unlock_irqrestore(&vfe32_ctrl->aec_ack_lock, flags);
+ spin_unlock_irqrestore(lock, flags);
}
static void vfe32_stats_ihist_ack(struct vfe_cmd_stats_ack *pAck)
{
+ unsigned long flags;
+ spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ &vfe32_ctrl->comp_stats_ack_lock :
+ &vfe32_ctrl->ihist_ack_lock);
+ spin_lock_irqsave(lock, flags);
vfe32_ctrl->ihistStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
vfe32_ctrl->ihistStatsControl.ackPending = FALSE;
+ spin_unlock_irqrestore(lock, flags);
}
static void vfe32_stats_rs_ack(struct vfe_cmd_stats_ack *pAck)
{
+ unsigned long flags;
+ spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ &vfe32_ctrl->comp_stats_ack_lock :
+ &vfe32_ctrl->rs_ack_lock);
+ spin_lock_irqsave(lock, flags);
vfe32_ctrl->rsStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
vfe32_ctrl->rsStatsControl.ackPending = FALSE;
+ spin_unlock_irqrestore(lock, flags);
}
static void vfe32_stats_cs_ack(struct vfe_cmd_stats_ack *pAck)
{
+ unsigned long flags;
+ spinlock_t *lock = (vfe32_ctrl->stats_comp ?
+ &vfe32_ctrl->comp_stats_ack_lock :
+ &vfe32_ctrl->cs_ack_lock);
+ spin_lock_irqsave(lock, flags);
vfe32_ctrl->csStatsControl.nextFrameAddrBuf = pAck->nextStatsBuf;
vfe32_ctrl->csStatsControl.ackPending = FALSE;
+ spin_unlock_irqrestore(lock, flags);
}
-
static inline void vfe32_read_irq_status(struct vfe32_irq_status *out)
{
uint32_t *temp;
@@ -2559,30 +2613,43 @@
(vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB)) {
/* in snapshot mode */
/* later we need to add check for live snapshot mode. */
- vfe32_ctrl->vfe_capture_count--;
- /* if last frame to be captured: */
- if (vfe32_ctrl->vfe_capture_count == 0) {
- if (vfe32_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY) {
- msm_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch0]);
- msm_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out0.ch1]);
- }
- if (vfe32_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY) {
- msm_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch0]);
- msm_io_w(0, vfe32_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->outpath.out1.ch1]);
- }
- msm_io_w_mb(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
+ if (vfe32_ctrl->frame_skip_pattern & (0x1 <<
+ (vfe32_ctrl->snapshot_frame_cnt %
+ vfe32_ctrl->frame_skip_cnt))) {
+ vfe32_ctrl->vfe_capture_count--;
+ /* if last frame to be captured: */
+ if (vfe32_ctrl->vfe_capture_count == 0) {
+ /* stop the bus output:write master enable = 0*/
+ if (vfe32_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY) {
+ msm_io_w(0, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->
+ outpath.out0.ch0]);
+ msm_io_w(0, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->
+ outpath.out0.ch1]);
+ }
+ if (vfe32_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY) {
+ msm_io_w(0, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->
+ outpath.out1.ch0]);
+ msm_io_w(0, vfe32_ctrl->vfebase +
+ vfe32_AXI_WM_CFG[vfe32_ctrl->
+ outpath.out1.ch1]);
+ }
+ msm_io_w_mb
+ (CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
-
- /* then do reg_update. */
- msm_io_w(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
- }
- } /* in snapshot mode. */
+ vfe32_ctrl->snapshot_frame_cnt = -1;
+ vfe32_ctrl->frame_skip_cnt = 31;
+ vfe32_ctrl->frame_skip_pattern = 0xffffffff;
+ } /*if snapshot count is 0*/
+ } /*if frame is not being dropped*/
+ vfe32_ctrl->snapshot_frame_cnt++;
+ /* then do reg_update. */
+ msm_io_w(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
+ } /* if snapshot mode. */
}
static void vfe32_set_default_reg_values(void)
@@ -2654,6 +2721,13 @@
msm_io_w_mb(CAMIF_COMMAND_STOP_AT_FRAME_BOUNDARY,
vfe32_ctrl->vfebase + VFE_CAMIF_COMMAND);
}
+ } /* if raw snapshot mode. */
+ if ((vfe32_ctrl->hfr_mode != HFR_MODE_OFF) &&
+ (vfe32_ctrl->operation_mode == VFE_MODE_OF_OPERATION_VIDEO) &&
+ (vfe32_ctrl->vfeFrameId % vfe32_ctrl->hfr_mode != 0)) {
+ vfe32_ctrl->vfeFrameId++;
+ CDBG("Skip the SOF notification when HFR enabled\n");
+ return;
}
vfe32_ctrl->vfeFrameId++;
vfe32_send_isp_msg(vfe32_ctrl, MSG_ID_SOF_ACK);
@@ -2907,11 +2981,6 @@
}
}
-static void vfe32_process_stats_comb_irq(uint32_t *irqstatus)
-{
- return;
-}
-
static uint32_t vfe32_process_stats_irq_common(uint32_t statsNum,
uint32_t newAddr) {
@@ -2971,17 +3040,23 @@
case statsIhistNum: {
msgStats.id = MSG_ID_STATS_IHIST;
+ spin_lock_irqsave(&vfe32_ctrl->ihist_ack_lock, flags);
vfe32_ctrl->ihistStatsControl.ackPending = TRUE;
+ spin_unlock_irqrestore(&vfe32_ctrl->ihist_ack_lock, flags);
}
break;
case statsRsNum: {
msgStats.id = MSG_ID_STATS_RS;
+ spin_lock_irqsave(&vfe32_ctrl->rs_ack_lock, flags);
vfe32_ctrl->rsStatsControl.ackPending = TRUE;
+ spin_unlock_irqrestore(&vfe32_ctrl->rs_ack_lock, flags);
}
break;
case statsCsNum: {
msgStats.id = MSG_ID_STATS_CS;
+ spin_lock_irqsave(&vfe32_ctrl->cs_ack_lock, flags);
vfe32_ctrl->csStatsControl.ackPending = TRUE;
+ spin_unlock_irqrestore(&vfe32_ctrl->cs_ack_lock, flags);
}
break;
@@ -2997,6 +3072,30 @@
return;
}
+static void vfe_send_comp_stats_msg(uint32_t status_bits)
+{
+ struct msm_stats_buf msgStats;
+ uint32_t temp;
+
+ msgStats.frame_id = vfe32_ctrl->vfeFrameId;
+ msgStats.status_bits = status_bits;
+
+ msgStats.aec.buff = vfe32_ctrl->aecStatsControl.bufToRender;
+ msgStats.awb.buff = vfe32_ctrl->awbStatsControl.bufToRender;
+ msgStats.af.buff = vfe32_ctrl->afStatsControl.bufToRender;
+
+ msgStats.ihist.buff = vfe32_ctrl->ihistStatsControl.bufToRender;
+ msgStats.rs.buff = vfe32_ctrl->rsStatsControl.bufToRender;
+ msgStats.cs.buff = vfe32_ctrl->csStatsControl.bufToRender;
+
+ temp = msm_io_r(vfe32_ctrl->vfebase + VFE_STATS_AWB_SGW_CFG);
+ msgStats.awb_ymin = (0xFF00 & temp) >> 8;
+
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
+ NOTIFY_VFE_MSG_COMP_STATS,
+ &msgStats);
+}
+
static void vfe32_process_stats_ae_irq(void)
{
unsigned long flags;
@@ -3105,6 +3204,126 @@
}
}
+static void vfe32_process_stats(uint32_t status_bits)
+{
+ unsigned long flags;
+ int32_t process_stats = false;
+ CDBG("%s, stats = 0x%x\n", __func__, status_bits);
+
+ spin_lock_irqsave(&vfe32_ctrl->comp_stats_ack_lock, flags);
+ if (status_bits & VFE_IRQ_STATUS0_STATS_AEC) {
+ if (!vfe32_ctrl->aecStatsControl.ackPending) {
+ vfe32_ctrl->aecStatsControl.ackPending = TRUE;
+ vfe32_ctrl->aecStatsControl.bufToRender =
+ vfe32_process_stats_irq_common(statsAeNum,
+ vfe32_ctrl->aecStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else{
+ vfe32_ctrl->aecStatsControl.bufToRender = 0;
+ vfe32_ctrl->aecStatsControl.droppedStatsFrameCount++;
+ }
+ } else {
+ vfe32_ctrl->aecStatsControl.bufToRender = 0;
+ }
+
+ if (status_bits & VFE_IRQ_STATUS0_STATS_AWB) {
+ if (!vfe32_ctrl->awbStatsControl.ackPending) {
+ vfe32_ctrl->awbStatsControl.ackPending = TRUE;
+ vfe32_ctrl->awbStatsControl.bufToRender =
+ vfe32_process_stats_irq_common(statsAwbNum,
+ vfe32_ctrl->awbStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else{
+ vfe32_ctrl->awbStatsControl.droppedStatsFrameCount++;
+ vfe32_ctrl->awbStatsControl.bufToRender = 0;
+ }
+ } else {
+ vfe32_ctrl->awbStatsControl.bufToRender = 0;
+ }
+
+
+ if (status_bits & VFE_IRQ_STATUS0_STATS_AF) {
+ if (!vfe32_ctrl->afStatsControl.ackPending) {
+ vfe32_ctrl->afStatsControl.ackPending = TRUE;
+ vfe32_ctrl->afStatsControl.bufToRender =
+ vfe32_process_stats_irq_common(statsAfNum,
+ vfe32_ctrl->afStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else {
+ vfe32_ctrl->afStatsControl.bufToRender = 0;
+ vfe32_ctrl->afStatsControl.droppedStatsFrameCount++;
+ }
+ } else {
+ vfe32_ctrl->afStatsControl.bufToRender = 0;
+ }
+
+ if (status_bits & VFE_IRQ_STATUS0_STATS_IHIST) {
+ if (!vfe32_ctrl->ihistStatsControl.ackPending) {
+ vfe32_ctrl->ihistStatsControl.ackPending = TRUE;
+ vfe32_ctrl->ihistStatsControl.bufToRender =
+ vfe32_process_stats_irq_common(statsIhistNum,
+ vfe32_ctrl->ihistStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else {
+ vfe32_ctrl->ihistStatsControl.droppedStatsFrameCount++;
+ vfe32_ctrl->ihistStatsControl.bufToRender = 0;
+ }
+ } else {
+ vfe32_ctrl->ihistStatsControl.bufToRender = 0;
+ }
+
+ if (status_bits & VFE_IRQ_STATUS0_STATS_RS) {
+ if (!vfe32_ctrl->rsStatsControl.ackPending) {
+ vfe32_ctrl->rsStatsControl.ackPending = TRUE;
+ vfe32_ctrl->rsStatsControl.bufToRender =
+ vfe32_process_stats_irq_common(statsRsNum,
+ vfe32_ctrl->rsStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else {
+ vfe32_ctrl->rsStatsControl.droppedStatsFrameCount++;
+ vfe32_ctrl->rsStatsControl.bufToRender = 0;
+ }
+ } else {
+ vfe32_ctrl->rsStatsControl.bufToRender = 0;
+ }
+
+
+ if (status_bits & VFE_IRQ_STATUS0_STATS_CS) {
+ if (!vfe32_ctrl->csStatsControl.ackPending) {
+ vfe32_ctrl->csStatsControl.ackPending = TRUE;
+ vfe32_ctrl->csStatsControl.bufToRender =
+ vfe32_process_stats_irq_common(statsCsNum,
+ vfe32_ctrl->csStatsControl.nextFrameAddrBuf);
+ process_stats = true;
+ } else {
+ vfe32_ctrl->csStatsControl.droppedStatsFrameCount++;
+ vfe32_ctrl->csStatsControl.bufToRender = 0;
+ }
+ } else {
+ vfe32_ctrl->csStatsControl.bufToRender = 0;
+ }
+
+ spin_unlock_irqrestore(&vfe32_ctrl->comp_stats_ack_lock, flags);
+ if (process_stats)
+ vfe_send_comp_stats_msg(status_bits);
+
+ return;
+}
+
+static void vfe32_process_stats_irq(uint32_t *irqstatus)
+{
+ uint32_t status_bits = VFE_COM_STATUS & *irqstatus;
+
+ if ((vfe32_ctrl->hfr_mode != HFR_MODE_OFF) &&
+ (vfe32_ctrl->vfeFrameId % vfe32_ctrl->hfr_mode != 0)) {
+ CDBG("Skip the stats when HFR enabled\n");
+ return;
+ }
+
+ vfe32_process_stats(status_bits);
+ return;
+}
+
static void vfe32_do_tasklet(unsigned long data)
{
unsigned long flags;
@@ -3191,7 +3410,7 @@
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK) {
CDBG("Stats composite irq occured.\n");
- vfe32_process_stats_comb_irq(
+ vfe32_process_stats_irq(
&qcmd->vfeInterruptStatus0);
}
} else {
@@ -3618,6 +3837,10 @@
spin_lock_init(&vfe32_ctrl->aec_ack_lock);
spin_lock_init(&vfe32_ctrl->awb_ack_lock);
spin_lock_init(&vfe32_ctrl->af_ack_lock);
+ spin_lock_init(&vfe32_ctrl->ihist_ack_lock);
+ spin_lock_init(&vfe32_ctrl->rs_ack_lock);
+ spin_lock_init(&vfe32_ctrl->cs_ack_lock);
+ spin_lock_init(&vfe32_ctrl->comp_stats_ack_lock);
spin_lock_init(&vfe32_ctrl->sd_notify_lock);
INIT_LIST_HEAD(&vfe32_ctrl->tasklet_q);
@@ -3625,6 +3848,7 @@
vfe32_ctrl->update_rolloff = false;
vfe32_ctrl->update_la = false;
vfe32_ctrl->update_gamma = false;
+ vfe32_ctrl->hfr_mode = HFR_MODE_OFF;
enable_irq(vfe32_ctrl->vfeirq->start);
diff --git a/drivers/media/video/msm/msm_vfe32.h b/drivers/media/video/msm/msm_vfe32.h
index 1adfffd..62c3639 100644
--- a/drivers/media/video/msm/msm_vfe32.h
+++ b/drivers/media/video/msm/msm_vfe32.h
@@ -168,6 +168,9 @@
#define VFE_AF_PINGPONG_STATUS_BIT 0x100
#define VFE_AWB_PINGPONG_STATUS_BIT 0x200
+#define HFR_MODE_OFF 1
+#define VFE_FRAME_SKIP_PERIOD_MASK 0x0000001F /*bits 0 -4*/
+
enum VFE32_DMI_RAM_SEL {
NO_MEM_SELECTED = 0,
BLACK_LUT_RAM_BANK0 = 0x1,
@@ -220,7 +223,7 @@
#define V32_OUT_CLAMP_OFF 0x00000524
#define V32_OUT_CLAMP_LEN 8
-#define V32_OPERATION_CFG_LEN 32
+#define V32_OPERATION_CFG_LEN 36
#define V32_AXI_OUT_OFF 0x00000038
#define V32_AXI_OUT_LEN 216
@@ -778,6 +781,8 @@
#define VFE32_IMASK_STATS_SKIN_BHIST_BUS_OVFL (0x00000001<<21)
#define VFE32_IMASK_AXI_ERROR (0x00000001<<22)
+#define VFE_COM_STATUS 0x000FE000
+
struct vfe32_output_path {
uint16_t output_mode; /* bitmask */
@@ -864,6 +869,7 @@
#define VFE_CLAMP_MIN 0x00000528
#define VFE_REALIGN_BUF 0x0000052C
#define VFE_STATS_CFG 0x00000530
+#define VFE_STATS_AWB_SGW_CFG 0x00000554
#define VFE_DMI_CFG 0x00000598
#define VFE_DMI_ADDR 0x0000059C
#define VFE_DMI_DATA_LO 0x000005A4
@@ -906,6 +912,10 @@
spinlock_t aec_ack_lock;
spinlock_t awb_ack_lock;
spinlock_t af_ack_lock;
+ spinlock_t ihist_ack_lock;
+ spinlock_t rs_ack_lock;
+ spinlock_t cs_ack_lock;
+ spinlock_t comp_stats_ack_lock;
uint32_t extlen;
void *extdata;
@@ -958,6 +968,10 @@
struct platform_device *pdev;
struct clk *vfe_clk[3];
spinlock_t sd_notify_lock;
+ uint32_t hfr_mode;
+ uint32_t frame_skip_cnt;
+ uint32_t frame_skip_pattern;
+ uint32_t snapshot_frame_cnt;
};
#define statsAeNum 0
diff --git a/drivers/media/video/msm/sensors/msm_sensor.c b/drivers/media/video/msm/sensors/msm_sensor.c
index 1b57350..d0b4f1f 100644
--- a/drivers/media/video/msm/sensors/msm_sensor.c
+++ b/drivers/media/video/msm/sensors/msm_sensor.c
@@ -215,7 +215,7 @@
v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
NOTIFY_ISPIF_STREAM, (void *)ISPIF_STREAM(
- PIX0, ISPIF_OFF_IMMEDIATELY));
+ PIX_0, ISPIF_OFF_IMMEDIATELY));
s_ctrl->func_tbl->sensor_stop_stream(s_ctrl);
msleep(30);
if (update_type == MSM_SENSOR_REG_INIT) {
@@ -244,7 +244,7 @@
output_settings[res].op_pixel_clk);
v4l2_subdev_notify(&s_ctrl->sensor_v4l2_subdev,
NOTIFY_ISPIF_STREAM, (void *)ISPIF_STREAM(
- PIX0, ISPIF_ON_FRAME_BOUNDARY));
+ PIX_0, ISPIF_ON_FRAME_BOUNDARY));
s_ctrl->func_tbl->sensor_start_stream(s_ctrl);
msleep(30);
}
diff --git a/drivers/mfd/wcd9310-core.c b/drivers/mfd/wcd9310-core.c
index 84eadef..588f950 100644
--- a/drivers/mfd/wcd9310-core.c
+++ b/drivers/mfd/wcd9310-core.c
@@ -370,6 +370,13 @@
mutex_init(&tabla->io_lock);
mutex_init(&tabla->xfer_lock);
+
+ mutex_init(&tabla->pm_lock);
+ tabla->wlock_holders = 0;
+ tabla->pm_state = TABLA_PM_SLEEPABLE;
+ init_waitqueue_head(&tabla->pm_wq);
+ wake_lock_init(&tabla->wlock, WAKE_LOCK_IDLE, "wcd9310-irq");
+
dev_set_drvdata(tabla->dev, tabla);
tabla_bring_up(tabla);
@@ -397,19 +404,22 @@
tabla_irq_exit(tabla);
err:
tabla_bring_down(tabla);
+ wake_lock_destroy(&tabla->wlock);
+ mutex_destroy(&tabla->pm_lock);
mutex_destroy(&tabla->io_lock);
mutex_destroy(&tabla->xfer_lock);
return ret;
}
+
static void tabla_device_exit(struct tabla *tabla)
{
tabla_irq_exit(tabla);
tabla_bring_down(tabla);
tabla_free_reset(tabla);
+ mutex_destroy(&tabla->pm_lock);
+ wake_lock_destroy(&tabla->wlock);
mutex_destroy(&tabla->io_lock);
mutex_destroy(&tabla->xfer_lock);
- slim_remove_device(tabla->slim_slave);
- kfree(tabla);
}
@@ -707,13 +717,13 @@
}
int tabla_i2c_read(struct tabla *tabla, unsigned short reg,
- int bytes, void *dest, bool interface_reg)
+ int bytes, void *dest, bool interface_reg)
{
return tabla_i2c_read_device(reg, bytes, dest);
}
int tabla_i2c_write(struct tabla *tabla, unsigned short reg,
- int bytes, void *src, bool interface_reg)
+ int bytes, void *src, bool interface_reg)
{
return tabla_i2c_write_device(reg, src, bytes);
}
@@ -799,7 +809,13 @@
static int __devexit tabla_i2c_remove(struct i2c_client *client)
{
+ struct tabla *tabla;
+
pr_debug("exit\n");
+ tabla = dev_get_drvdata(&client->dev);
+ tabla_device_exit(tabla);
+ tabla_disable_supplies(tabla);
+ kfree(tabla);
return 0;
}
@@ -935,6 +951,7 @@
err:
return ret;
}
+
static int tabla_slim_remove(struct slim_device *pdev)
{
struct tabla *tabla;
@@ -948,14 +965,103 @@
tabla = slim_get_devicedata(pdev);
tabla_device_exit(tabla);
tabla_disable_supplies(tabla);
+ slim_remove_device(tabla->slim_slave);
kfree(tabla);
return 0;
}
+
+static int tabla_resume(struct tabla *tabla)
+{
+ int ret = 0;
+
+ pr_debug("%s: enter\n", __func__);
+ mutex_lock(&tabla->pm_lock);
+ if (tabla->pm_state == TABLA_PM_ASLEEP) {
+ pr_debug("%s: resuming system, state %d, wlock %d\n", __func__,
+ tabla->pm_state, tabla->wlock_holders);
+ tabla->pm_state = TABLA_PM_SLEEPABLE;
+ } else {
+ pr_warn("%s: system is already awake, state %d wlock %d\n",
+ __func__, tabla->pm_state, tabla->wlock_holders);
+ }
+ mutex_unlock(&tabla->pm_lock);
+ wake_up_all(&tabla->pm_wq);
+
+ return ret;
+}
+
+static int tabla_slim_resume(struct slim_device *sldev)
+{
+ struct tabla *tabla = slim_get_devicedata(sldev);
+ return tabla_resume(tabla);
+}
+
+static int tabla_i2c_resume(struct i2c_client *i2cdev)
+{
+ struct tabla *tabla = dev_get_drvdata(&i2cdev->dev);
+ return tabla_resume(tabla);
+}
+
+static int tabla_suspend(struct tabla *tabla, pm_message_t pmesg)
+{
+ int ret = 0;
+
+ pr_debug("%s: enter\n", __func__);
+ /* wake_lock() can be called after this suspend chain call started.
+ * thus suspend can be called while wlock is being held */
+ mutex_lock(&tabla->pm_lock);
+ if (tabla->pm_state == TABLA_PM_SLEEPABLE) {
+ pr_debug("%s: suspending system, state %d, wlock %d\n",
+ __func__, tabla->pm_state, tabla->wlock_holders);
+ tabla->pm_state = TABLA_PM_ASLEEP;
+ } else if (tabla->pm_state == TABLA_PM_AWAKE) {
+ /* unlock to wait for pm_state == TABLA_PM_SLEEPABLE
+ * then set to TABLA_PM_ASLEEP */
+ pr_debug("%s: waiting to suspend system, state %d, wlock %d\n",
+ __func__, tabla->pm_state, tabla->wlock_holders);
+ mutex_unlock(&tabla->pm_lock);
+ if (!(wait_event_timeout(tabla->pm_wq,
+ tabla_pm_cmpxchg(tabla,
+ TABLA_PM_SLEEPABLE,
+ TABLA_PM_ASLEEP) ==
+ TABLA_PM_SLEEPABLE,
+ HZ))) {
+ pr_debug("%s: suspend failed state %d, wlock %d\n",
+ __func__, tabla->pm_state,
+ tabla->wlock_holders);
+ ret = -EBUSY;
+ } else {
+ pr_debug("%s: done, state %d, wlock %d\n", __func__,
+ tabla->pm_state, tabla->wlock_holders);
+ }
+ mutex_lock(&tabla->pm_lock);
+ } else if (tabla->pm_state == TABLA_PM_ASLEEP) {
+ pr_warn("%s: system is already suspended, state %d, wlock %dn",
+ __func__, tabla->pm_state, tabla->wlock_holders);
+ }
+ mutex_unlock(&tabla->pm_lock);
+
+ return ret;
+}
+
+static int tabla_slim_suspend(struct slim_device *sldev, pm_message_t pmesg)
+{
+ struct tabla *tabla = slim_get_devicedata(sldev);
+ return tabla_suspend(tabla, pmesg);
+}
+
+static int tabla_i2c_suspend(struct i2c_client *i2cdev, pm_message_t pmesg)
+{
+ struct tabla *tabla = dev_get_drvdata(&i2cdev->dev);
+ return tabla_suspend(tabla, pmesg);
+}
+
static const struct slim_device_id slimtest_id[] = {
{"tabla-slim", 0},
{}
};
+
static struct slim_driver tabla_slim_driver = {
.driver = {
.name = "tabla-slim",
@@ -964,6 +1070,8 @@
.probe = tabla_slim_probe,
.remove = tabla_slim_remove,
.id_table = slimtest_id,
+ .resume = tabla_slim_resume,
+ .suspend = tabla_slim_suspend,
};
static const struct slim_device_id slimtest2x_id[] = {
@@ -979,6 +1087,8 @@
.probe = tabla_slim_probe,
.remove = tabla_slim_remove,
.id_table = slimtest2x_id,
+ .resume = tabla_slim_resume,
+ .suspend = tabla_slim_suspend,
};
#define TABLA_I2C_TOP_LEVEL 0
@@ -996,13 +1106,15 @@
MODULE_DEVICE_TABLE(i2c, tabla_id_table);
static struct i2c_driver tabla_i2c_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "tabla-i2c-core",
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "tabla-i2c-core",
},
- .id_table = tabla_id_table,
- .probe = tabla_i2c_probe,
- .remove = __devexit_p(tabla_i2c_remove),
+ .id_table = tabla_id_table,
+ .probe = tabla_i2c_probe,
+ .remove = __devexit_p(tabla_i2c_remove),
+ .resume = tabla_i2c_resume,
+ .suspend = tabla_i2c_suspend,
};
static int __init tabla_init(void)
diff --git a/drivers/mfd/wcd9310-irq.c b/drivers/mfd/wcd9310-irq.c
index fef1323..c6a9c23 100644
--- a/drivers/mfd/wcd9310-irq.c
+++ b/drivers/mfd/wcd9310-irq.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -12,6 +12,7 @@
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/sched.h>
#include <linux/irq.h>
#include <linux/mfd/core.h>
#include <linux/mfd/wcd9310/core.h>
@@ -83,6 +84,60 @@
.irq_enable = tabla_irq_enable,
};
+enum tabla_pm_state tabla_pm_cmpxchg(struct tabla *tabla, enum tabla_pm_state o,
+ enum tabla_pm_state n)
+{
+ enum tabla_pm_state old;
+ mutex_lock(&tabla->pm_lock);
+ old = tabla->pm_state;
+ if (old == o)
+ tabla->pm_state = n;
+ mutex_unlock(&tabla->pm_lock);
+ return old;
+}
+EXPORT_SYMBOL_GPL(tabla_pm_cmpxchg);
+
+void tabla_lock_sleep(struct tabla *tabla)
+{
+ enum tabla_pm_state os;
+
+ /* tabla_{lock/unlock}_sleep will be called by tabla_irq_thread
+ * and its subroutines only motly.
+ * but btn0_lpress_fn is not tabla_irq_thread's subroutine and
+ * it can race with tabla_irq_thread.
+ * so need to embrace wlock_holders with mutex.
+ */
+ mutex_lock(&tabla->pm_lock);
+ if (tabla->wlock_holders++ == 0)
+ wake_lock(&tabla->wlock);
+ mutex_unlock(&tabla->pm_lock);
+ while (!wait_event_timeout(tabla->pm_wq,
+ ((os = tabla_pm_cmpxchg(tabla, TABLA_PM_SLEEPABLE,
+ TABLA_PM_AWAKE)) ==
+ TABLA_PM_SLEEPABLE ||
+ (os == TABLA_PM_AWAKE)),
+ 5 * HZ)) {
+ pr_err("%s: system didn't resume within 5000ms, state %d, "
+ "wlock %d\n", __func__, tabla->pm_state,
+ tabla->wlock_holders);
+ WARN_ON_ONCE(1);
+ }
+ wake_up_all(&tabla->pm_wq);
+}
+EXPORT_SYMBOL_GPL(tabla_lock_sleep);
+
+void tabla_unlock_sleep(struct tabla *tabla)
+{
+ mutex_lock(&tabla->pm_lock);
+ if (--tabla->wlock_holders == 0) {
+ tabla->pm_state = TABLA_PM_SLEEPABLE;
+ wake_unlock(&tabla->wlock);
+ }
+ mutex_unlock(&tabla->pm_lock);
+ wake_up_all(&tabla->pm_wq);
+}
+EXPORT_SYMBOL_GPL(tabla_unlock_sleep);
+
static irqreturn_t tabla_irq_thread(int irq, void *data)
{
int ret;
@@ -90,11 +145,13 @@
u8 status[TABLA_NUM_IRQ_REGS];
unsigned int i;
+ tabla_lock_sleep(tabla);
ret = tabla_bulk_read(tabla, TABLA_A_INTR_STATUS0,
TABLA_NUM_IRQ_REGS, status);
if (ret < 0) {
dev_err(tabla->dev, "Failed to read interrupt status: %d\n",
ret);
+ tabla_unlock_sleep(tabla);
return IRQ_NONE;
}
/* Apply masking */
@@ -127,6 +184,7 @@
break;
}
}
+ tabla_unlock_sleep(tabla);
return IRQ_HANDLED;
}
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 5c62769..b83e871 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -283,6 +283,14 @@
---help---
A driver for Qualcomm WLAN SDIO Libra chipset.
+config ATH6K_LEGACY
+ tristate "QCA AR6003 wlan SDIO driver"
+ depends on MMC_MSM && WLAN
+ select WIRELESS_EXT
+ select WEXT_PRIV
+ ---help---
+ This module adds support for wireless adapters based on QCA AR6003 chipset running over SDIO.
+
config WCNSS_CORE
tristate "Qualcomm WCNSS CORE driver"
depends on ARCH_MSM8960
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 2e80692..93de829 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -1893,7 +1893,7 @@
INIT_DELAYED_WORK(&chip->calib_ccadc_work, calibrate_ccadc_work);
/* begin calibration only on chips > 2.0 */
if (chip->revision >= PM8XXX_REVISION_8921_2p0)
- calibrate_ccadc_work(&(chip->calib_ccadc_work.work));
+ schedule_delayed_work(&chip->calib_ccadc_work, 0);
/* initial hkadc calibration */
schedule_work(&chip->calib_hkadc_work);
diff --git a/drivers/power/pm8xxx-ccadc.c b/drivers/power/pm8xxx-ccadc.c
index 17cf53a..c95fd93 100644
--- a/drivers/power/pm8xxx-ccadc.c
+++ b/drivers/power/pm8xxx-ccadc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -209,7 +209,7 @@
return rc;
}
if ((reg & (START_CONV_BIT | EOC_CONV_BIT)) != EOC_CONV_BIT)
- msleep(60);
+ msleep(20);
else
break;
}
diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c
index 0fed092..02d1c39 100644
--- a/drivers/slimbus/slim-msm-ctrl.c
+++ b/drivers/slimbus/slim-msm-ctrl.c
@@ -1862,11 +1862,6 @@
}
- dev->rclk = clk_get(dev->dev, "audio_slimbus_clk");
- if (!dev->rclk) {
- dev_err(dev->dev, "slimbus clock not found");
- goto err_clk_get_failed;
- }
dev->framer.rootfreq = SLIM_ROOT_FREQ >> 3;
dev->framer.superfreq =
dev->framer.rootfreq / SLIM_CL_PER_SUPERFRAME_DIV8;
@@ -1882,6 +1877,20 @@
}
msm_slim_prg_slew(pdev, dev);
+
+ /* Register with framework before enabling frame, clock */
+ ret = slim_add_numbered_controller(&dev->ctrl);
+ if (ret) {
+ dev_err(dev->dev, "error adding controller\n");
+ goto err_ctrl_failed;
+ }
+
+
+ dev->rclk = clk_get(dev->dev, "audio_slimbus_clk");
+ if (!dev->rclk) {
+ dev_err(dev->dev, "slimbus clock not found");
+ goto err_clk_get_failed;
+ }
clk_set_rate(dev->rclk, SLIM_ROOT_FREQ);
clk_enable(dev->rclk);
@@ -1910,13 +1919,6 @@
*/
wmb();
- /* Register with framework before enabling frame, clock */
- ret = slim_add_numbered_controller(&dev->ctrl);
- if (ret) {
- dev_err(dev->dev, "error adding controller\n");
- goto err_ctrl_failed;
- }
-
/* Framer register initialization */
writel_relaxed((0xA << REF_CLK_GEAR) | (0xA << CLK_GEAR) |
(1 << ROOT_FREQ) | (1 << FRM_ACTIVE) | 1,
@@ -1969,11 +1971,9 @@
err_ctrl_failed:
writel_relaxed(0, dev->base + COMP_CFG);
+err_clk_get_failed:
kfree(dev->satd);
err_request_irq_failed:
- clk_disable(dev->rclk);
- clk_put(dev->rclk);
-err_clk_get_failed:
msm_slim_sps_exit(dev);
err_sps_init_failed:
iounmap(dev->bam.base);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 00e4fda..30cbdd8 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -42,6 +42,7 @@
#include <mach/clk.h>
#include <mach/msm_xo.h>
+#include <mach/msm_bus.h>
#define MSM_USB_BASE (motg->regs)
#define DRIVER_NAME "msm_otg"
@@ -607,7 +608,7 @@
struct usb_bus *bus = otg->host;
struct msm_otg_platform_data *pdata = motg->pdata;
int cnt = 0;
- bool host_bus_suspend;
+ bool host_bus_suspend, dcp;
u32 phy_ctrl_val = 0, cmd_val;
u32 portsc;
@@ -616,6 +617,7 @@
disable_irq(motg->irq);
host_bus_suspend = otg->host && !test_bit(ID, &motg->inputs);
+ dcp = motg->chg_type == USB_DCP_CHARGER;
/*
* Chipidea 45-nm PHY suspend sequence:
*
@@ -688,7 +690,11 @@
cmd_val |= ULPI_STP_CTRL;
writel_relaxed(cmd_val, USB_USBCMD);
- if (motg->caps & ALLOW_PHY_RETENTION && !host_bus_suspend) {
+ /*
+ * BC1.2 spec mandates PD to enable VDP_SRC when charging from DCP.
+ * PHY retention and collapse can not happen with VDP_SRC enabled.
+ */
+ if (motg->caps & ALLOW_PHY_RETENTION && !host_bus_suspend && !dcp) {
phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
if (motg->pdata->otg_control == OTG_PHY_CONTROL)
/* Enable PHY HV interrupts to wake MPM/Link */
@@ -707,7 +713,8 @@
/* usb phy no more require TCXO clock, hence vote for TCXO disable */
clk_disable_unprepare(motg->xo_handle);
- if (motg->caps & ALLOW_PHY_POWER_COLLAPSE && !host_bus_suspend) {
+ if (motg->caps & ALLOW_PHY_POWER_COLLAPSE &&
+ !host_bus_suspend && !dcp) {
msm_hsusb_ldo_enable(motg, 0);
motg->lpm_flags |= PHY_PWR_COLLAPSED;
}
@@ -1122,6 +1129,7 @@
static void msm_otg_start_peripheral(struct otg_transceiver *otg, int on)
{
+ int ret;
struct msm_otg *motg = container_of(otg, struct msm_otg, otg);
struct msm_otg_platform_data *pdata = motg->pdata;
@@ -1142,11 +1150,27 @@
* power collapse(pc) while running in peripheral mode.
*/
otg_pm_qos_update_latency(motg, 1);
+ /* Configure BUS performance parameters for MAX bandwidth */
+ if (motg->bus_perf_client) {
+ ret = msm_bus_scale_client_update_request(
+ motg->bus_perf_client, 1);
+ if (ret)
+ dev_err(motg->otg.dev, "%s: Failed to vote for "
+ "bus bandwidth %d\n", __func__, ret);
+ }
usb_gadget_vbus_connect(otg->gadget);
} else {
dev_dbg(otg->dev, "gadget off\n");
usb_gadget_vbus_disconnect(otg->gadget);
otg_pm_qos_update_latency(motg, 0);
+ /* Configure BUS performance parameters to default */
+ if (motg->bus_perf_client) {
+ ret = msm_bus_scale_client_update_request(
+ motg->bus_perf_client, 0);
+ if (ret)
+ dev_err(motg->otg.dev, "%s: Failed to devote "
+ "for bus bw %d\n", __func__, ret);
+ }
if (pdata->setup_gpio)
pdata->setup_gpio(OTG_STATE_UNDEFINED);
}
@@ -1415,6 +1439,9 @@
ulpi_write(otg, chg_det, 0x34);
break;
case SNPS_28NM_INTEGRATED_PHY:
+ /* Turn off VDP_SRC */
+ ulpi_write(otg, 0x3, 0x86);
+ msleep(20);
/*
* Configure DM as current source, DP as current sink
* and enable battery charging comparators.
@@ -1616,8 +1643,8 @@
#define MSM_CHG_DCD_POLL_TIME (100 * HZ/1000) /* 100 msec */
#define MSM_CHG_DCD_MAX_RETRIES 6 /* Tdcd_tmout = 6 * 100 msec */
-#define MSM_CHG_PRIMARY_DET_TIME (40 * HZ/1000) /* TVDPSRC_ON */
-#define MSM_CHG_SECONDARY_DET_TIME (40 * HZ/1000) /* TVDMSRC_ON */
+#define MSM_CHG_PRIMARY_DET_TIME (50 * HZ/1000) /* TVDPSRC_ON */
+#define MSM_CHG_SECONDARY_DET_TIME (50 * HZ/1000) /* TVDMSRC_ON */
static void msm_chg_detect_work(struct work_struct *w)
{
struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
@@ -1834,6 +1861,8 @@
case USB_CHG_STATE_DETECTED:
switch (motg->chg_type) {
case USB_DCP_CHARGER:
+ /* Enable VDP_SRC */
+ ulpi_write(otg, 0x2, 0x85);
msm_otg_notify_charger(motg,
IDEV_CHG_MAX);
pm_runtime_put_noidle(otg->dev);
@@ -2601,6 +2630,14 @@
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
+ if (motg->pdata->bus_scale_table) {
+ motg->bus_perf_client =
+ msm_bus_scale_register_client(motg->pdata->bus_scale_table);
+ if (!motg->bus_perf_client)
+ dev_err(motg->otg.dev, "%s: Failed to register BUS "
+ "scaling client!!\n", __func__);
+ }
+
return 0;
remove_otg:
@@ -2702,6 +2739,9 @@
if (motg->pdata->swfi_latency)
pm_qos_remove_request(&motg->pm_qos_req_dma);
+ if (motg->bus_perf_client)
+ msm_bus_scale_unregister_client(motg->bus_perf_client);
+
kfree(motg);
return 0;
}
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index c7759c4..b590c41 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -309,6 +309,15 @@
The panel is connected to the host
via Toshiba DSI-to-LVDS bridge.
+config FB_MSM_MIPI_CHIMEI_WUXGA
+ bool "LVDS Chimei WUXGA Panel using Toshiba MIPI DSI-to-LVDS bridge."
+ select FB_MSM_MIPI_DSI_TC358764_DSI2LVDS
+ ---help---
+ Support for Chimei WUXGA (1920x1200) panel.
+ The panel is using a serial LVDS input.
+ The panel is connected to the host
+ via Toshiba DSI-to-LVDS bridge.
+
config FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
bool
select FB_MSM_MIPI_DSI_TRULY
@@ -446,6 +455,7 @@
select FB_MSM_MIPI_NT35510_CMD_WVGA_PT
select FB_MSM_MIPI_SIMULATOR_VIDEO
select FB_MSM_MIPI_CHIMEI_WXGA
+ select FB_MSM_MIPI_CHIMEI_WUXGA
---help---
Support for MIPI panel auto detect
@@ -543,6 +553,10 @@
bool "MIPI Chimei WXGA PT Panel"
select FB_MSM_MIPI_CHIMEI_WXGA
+config FB_MSM_MIPI_CHIMEI_WUXGA_PANEL
+ bool "MIPI Chimei WUXGA Panel"
+ select FB_MSM_MIPI_CHIMEI_WUXGA
+
config FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT_PANEL
bool "MIPI Truly Video WVGA PT Panel"
select FB_MSM_MIPI_TRULY_VIDEO_WVGA_PT
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index 93205bc..bd7628d 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -119,6 +119,7 @@
obj-y += mipi_renesas_video_fwvga_pt.o mipi_renesas_cmd_fwvga_pt.o
obj-y += mipi_NT35510_video_wvga_pt.o mipi_NT35510_cmd_wvga_pt.o
obj-y += mipi_chimei_wxga_pt.o
+obj-y += mipi_chimei_wuxga.o
obj-y += mipi_truly_video_wvga_pt.o
else
obj-$(CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT) += mipi_toshiba_video_wvga_pt.o
@@ -133,6 +134,7 @@
obj-$(CONFIG_FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT) += mipi_NT35510_video_wvga_pt.o
obj-$(CONFIG_FB_MSM_MIPI_SIMULATOR_VIDEO) += mipi_simulator_video.o
obj-$(CONFIG_FB_MSM_MIPI_CHIMEI_WXGA) += mipi_chimei_wxga_pt.o
+obj-$(CONFIG_FB_MSM_MIPI_CHIMEI_WUXGA) += mipi_chimei_wuxga.o
endif
obj-$(CONFIG_FB_MSM_LCDC_PANEL) += lcdc_panel.o
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 7fd4c56..07a075c 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1000,14 +1000,15 @@
return;
external_common_state->speaker_allocation_block = sad[1];
- DEV_DBG("EDID: speaker allocation data=%s%s%s%s%s%s%s\n",
+ DEV_DBG("EDID: speaker allocation data SP byte = %08x %s%s%s%s%s%s%s\n",
+ sad[1],
(sad[1] & BIT(0)) ? "FL/FR," : "",
(sad[1] & BIT(1)) ? "LFE," : "",
(sad[1] & BIT(2)) ? "FC," : "",
(sad[1] & BIT(3)) ? "RL/RR," : "",
(sad[1] & BIT(4)) ? "RC," : "",
(sad[1] & BIT(5)) ? "FLC/FRC," : "",
- (sad[1] & BIT(6)) ? "LFE," : "");
+ (sad[1] & BIT(6)) ? "RLC/RRC," : "");
}
static void hdmi_edid_extract_audio_data_blocks(const uint8 *in_buf)
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 56a6483..93e6d40 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -64,6 +64,8 @@
EXPORT_SYMBOL(hdmi_msm_state_mutex);
static DEFINE_MUTEX(hdcp_auth_state_mutex);
+static void hdmi_msm_dump_regs(const char *prefix);
+
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
static void hdmi_msm_hdcp_enable(void);
#else
@@ -3280,14 +3282,23 @@
}
EXPORT_SYMBOL(hdmi_audio_packet_enable);
-static void hdmi_msm_audio_info_setup(boolean enabled, int num_of_channels,
- int level_shift, boolean down_mix)
+
+/* TO-DO: return -EINVAL when num_of_channels and channel_allocation
+ * does not match CEA 861-D spec.
+*/
+int hdmi_msm_audio_info_setup(bool enabled, u32 num_of_channels,
+ u32 channel_allocation, u32 level_shift, bool down_mix)
{
- uint32 channel_allocation = 0; /* Default to FR,FL */
uint32 channel_count = 1; /* Default to 2 channels
-> See Table 17 in CEA-D spec */
uint32 check_sum, audio_info_0_reg, audio_info_1_reg;
uint32 audio_info_ctrl_reg;
+ u32 aud_pck_ctrl_2_reg;
+ u32 layout;
+
+ layout = (MSM_HDMI_AUDIO_CHANNEL_2 == num_of_channels) ? 0 : 1;
+ aud_pck_ctrl_2_reg = 1 | (layout << 1);
+ HDMI_OUTP(0x00044, aud_pck_ctrl_2_reg);
/* Please see table 20 Audio InfoFrame in HDMI spec
FL = front left
@@ -3310,6 +3321,7 @@
if (enabled) {
switch (num_of_channels) {
case MSM_HDMI_AUDIO_CHANNEL_2:
+ channel_allocation = 0; /* Default to FR,FL */
break;
case MSM_HDMI_AUDIO_CHANNEL_4:
channel_count = 3;
@@ -3327,6 +3339,9 @@
channel_allocation = 0x1f;
break;
default:
+ pr_err("%s(): Unsupported num_of_channels = %u\n",
+ __func__, num_of_channels);
+ return -EINVAL;
break;
}
@@ -3382,7 +3397,14 @@
}
/* HDMI_INFOFRAME_CTRL0[0x002C] */
HDMI_OUTP(0x002C, audio_info_ctrl_reg);
+
+
+ hdmi_msm_dump_regs("HDMI-AUDIO-ON: ");
+
+ return 0;
+
}
+EXPORT_SYMBOL(hdmi_msm_audio_info_setup);
static void hdmi_msm_en_gc_packet(boolean av_mute_is_requested)
{
@@ -3488,7 +3510,7 @@
hdmi_msm_audio_acr_setup(TRUE,
external_common_state->video_resolution,
msm_hdmi_sample_rate, channels);
- hdmi_msm_audio_info_setup(TRUE, channels, 0, FALSE);
+ hdmi_msm_audio_info_setup(TRUE, channels, 0, 0, FALSE);
/* Turn on Audio FIFO and SAM DROP ISR */
HDMI_OUTP(0x02CC, HDMI_INP(0x02CC) | BIT(1) | BIT(3));
@@ -3519,7 +3541,7 @@
return -ETIMEDOUT;
}
}
- hdmi_msm_audio_info_setup(FALSE, 0, 0, FALSE);
+ hdmi_msm_audio_info_setup(FALSE, 0, 0, 0, FALSE);
hdmi_msm_audio_acr_setup(FALSE, 0, 0, 0);
DEV_INFO("HDMI Audio: Disabled\n");
return 0;
@@ -4042,7 +4064,7 @@
return rc;
}
}
- hdmi_msm_audio_info_setup(TRUE, 0, 0, FALSE);
+ hdmi_msm_audio_info_setup(TRUE, 0, 0, 0, FALSE);
mutex_lock(&external_common_state_hpd_mutex);
hdmi_msm_state->panel_power_on = TRUE;
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 5e46397..4c443ea 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -468,11 +468,16 @@
int mdp_ppp_pipe_wait(void)
{
int ret = 1;
+ boolean wait;
+ unsigned long flag;
/* wait 5 seconds for the operation to complete before declaring
the MDP hung */
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ wait = mdp_ppp_waiting;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
- if (mdp_ppp_waiting == TRUE) {
+ if (wait == TRUE) {
ret = wait_for_completion_interruptible_timeout(&mdp_ppp_comp,
5 * HZ);
@@ -548,6 +553,7 @@
void mdp_pipe_kickoff(uint32 term, struct msm_fb_data_type *mfd)
{
+ unsigned long flag;
/* complete all the writes before starting */
wmb();
@@ -561,7 +567,9 @@
mdp_enable_irq(term);
INIT_COMPLETION(mdp_ppp_comp);
+ spin_lock_irqsave(&mdp_spin_lock, flag);
mdp_ppp_waiting = TRUE;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
outpdw(MDP_BASE + 0x30, 0x1000);
wait_for_completion_killable(&mdp_ppp_comp);
mdp_disable_irq(term);
@@ -812,128 +820,137 @@
{
uint32 mdp_interrupt = 0;
struct mdp_dma_data *dma;
+ unsigned long flag;
+ /* Ensure all the register write are complete */
+ mb();
mdp_is_in_isr = TRUE;
- do {
- mdp_interrupt = inp32(MDP_INTR_STATUS);
- outp32(MDP_INTR_CLEAR, mdp_interrupt);
- mdp_interrupt &= mdp_intr_mask;
+ mdp_interrupt = inp32(MDP_INTR_STATUS);
+ outp32(MDP_INTR_CLEAR, mdp_interrupt);
- if (mdp_interrupt & TV_ENC_UNDERRUN) {
- mdp_interrupt &= ~(TV_ENC_UNDERRUN);
- mdp_tv_underflow_cnt++;
- }
+ mdp_interrupt &= mdp_intr_mask;
- if (!mdp_interrupt)
- break;
+ if (mdp_interrupt & TV_ENC_UNDERRUN) {
+ mdp_interrupt &= ~(TV_ENC_UNDERRUN);
+ mdp_tv_underflow_cnt++;
+ }
- /* DMA3 TV-Out Start */
- if (mdp_interrupt & TV_OUT_DMA3_START) {
- /* let's disable TV out interrupt */
- mdp_intr_mask &= ~TV_OUT_DMA3_START;
- outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ if (!mdp_interrupt)
+ goto out;
- dma = &dma3_data;
- if (dma->waiting) {
- dma->waiting = FALSE;
- complete(&dma->comp);
- }
- }
-#ifndef CONFIG_FB_MSM_MDP22
- if (mdp_interrupt & MDP_HIST_DONE) {
- outp32(MDP_BASE + 0x94018, 0x3);
- outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
- complete(&mdp_hist_comp);
- }
+ /* DMA3 TV-Out Start */
+ if (mdp_interrupt & TV_OUT_DMA3_START) {
+ /* let's disable TV out interrupt */
+ mdp_intr_mask &= ~TV_OUT_DMA3_START;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
- /* LCDC UnderFlow */
- if (mdp_interrupt & LCDC_UNDERFLOW) {
- mdp_lcdc_underflow_cnt++;
- /*when underflow happens HW resets all the histogram
- registers that were set before so restore them back
- to normal.*/
- MDP_OUTP(MDP_BASE + 0x94010, 1);
- MDP_OUTP(MDP_BASE + 0x9401c, 2);
- if (mdp_is_hist_start == TRUE) {
- MDP_OUTP(MDP_BASE + 0x94004,
- mdp_hist_frame_cnt);
- MDP_OUTP(MDP_BASE + 0x94000, 1);
- }
- }
- /* LCDC Frame Start */
- if (mdp_interrupt & LCDC_FRAME_START) {
- /* let's disable LCDC interrupt */
- mdp_intr_mask &= ~LCDC_FRAME_START;
- outp32(MDP_INTR_ENABLE, mdp_intr_mask);
-
- dma = &dma2_data;
- if (dma->waiting) {
- dma->waiting = FALSE;
- complete(&dma->comp);
- }
- }
-
- /* DMA2 LCD-Out Complete */
- if (mdp_interrupt & MDP_DMA_S_DONE) {
- dma = &dma_s_data;
- dma->busy = FALSE;
- mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF,
- TRUE);
+ dma = &dma3_data;
+ if (dma->waiting) {
+ dma->waiting = FALSE;
complete(&dma->comp);
}
- /* DMA_E LCD-Out Complete */
- if (mdp_interrupt & MDP_DMA_E_DONE) {
- dma = &dma_s_data;
+ }
+#ifndef CONFIG_FB_MSM_MDP22
+ if (mdp_interrupt & MDP_HIST_DONE) {
+ outp32(MDP_BASE + 0x94018, 0x3);
+ outp32(MDP_INTR_CLEAR, MDP_HIST_DONE);
+ complete(&mdp_hist_comp);
+ }
+
+ /* LCDC UnderFlow */
+ if (mdp_interrupt & LCDC_UNDERFLOW) {
+ mdp_lcdc_underflow_cnt++;
+ /*when underflow happens HW resets all the histogram
+ registers that were set before so restore them back
+ to normal.*/
+ MDP_OUTP(MDP_BASE + 0x94010, 1);
+ MDP_OUTP(MDP_BASE + 0x9401c, 2);
+ if (mdp_is_hist_start == TRUE) {
+ MDP_OUTP(MDP_BASE + 0x94004,
+ mdp_hist_frame_cnt);
+ MDP_OUTP(MDP_BASE + 0x94000, 1);
+ }
+ }
+
+ /* LCDC Frame Start */
+ if (mdp_interrupt & LCDC_FRAME_START) {
+ /* let's disable LCDC interrupt */
+ mdp_intr_mask &= ~LCDC_FRAME_START;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+
+ dma = &dma2_data;
+ if (dma->waiting) {
+ dma->waiting = FALSE;
+ complete(&dma->comp);
+ }
+ }
+
+ /* DMA2 LCD-Out Complete */
+ if (mdp_interrupt & MDP_DMA_S_DONE) {
+ dma = &dma_s_data;
+ dma->busy = FALSE;
+ mdp_pipe_ctrl(MDP_DMA_S_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+ complete(&dma->comp);
+ }
+
+ /* DMA_E LCD-Out Complete */
+ if (mdp_interrupt & MDP_DMA_E_DONE) {
+ dma = &dma_s_data;
+ dma->busy = FALSE;
+ mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+ complete(&dma->comp);
+ }
+
+#endif
+
+ /* DMA2 LCD-Out Complete */
+ if (mdp_interrupt & MDP_DMA_P_DONE) {
+ struct timeval now;
+
+ mdp_dma2_last_update_time = ktime_sub(ktime_get_real(),
+ mdp_dma2_last_update_time);
+ if (mdp_debug[MDP_DMA2_BLOCK]) {
+ jiffies_to_timeval(jiffies, &now);
+ mdp_dma2_timeval.tv_usec =
+ now.tv_usec - mdp_dma2_timeval.tv_usec;
+ }
+#ifndef CONFIG_FB_MSM_MDP303
+ dma = &dma2_data;
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ dma->busy = FALSE;
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+ complete(&dma->comp);
+#else
+ if (mdp_prim_panel_type == MIPI_CMD_PANEL) {
+ dma = &dma2_data;
+ spin_lock_irqsave(&mdp_spin_lock, flag);
dma->busy = FALSE;
- mdp_pipe_ctrl(MDP_DMA_E_BLOCK, MDP_BLOCK_POWER_OFF,
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF,
TRUE);
complete(&dma->comp);
}
-
#endif
+ }
- /* DMA2 LCD-Out Complete */
- if (mdp_interrupt & MDP_DMA_P_DONE) {
- struct timeval now;
-
- mdp_dma2_last_update_time = ktime_sub(ktime_get_real(),
- mdp_dma2_last_update_time);
- if (mdp_debug[MDP_DMA2_BLOCK]) {
- jiffies_to_timeval(jiffies, &now);
- mdp_dma2_timeval.tv_usec =
- now.tv_usec - mdp_dma2_timeval.tv_usec;
- }
-#ifndef CONFIG_FB_MSM_MDP303
- dma = &dma2_data;
- dma->busy = FALSE;
- mdp_pipe_ctrl(MDP_DMA2_BLOCK, MDP_BLOCK_POWER_OFF,
- TRUE);
- complete(&dma->comp);
-#else
- if (mdp_prim_panel_type == MIPI_CMD_PANEL) {
- dma = &dma2_data;
- dma->busy = FALSE;
- mdp_pipe_ctrl(MDP_DMA2_BLOCK,
- MDP_BLOCK_POWER_OFF, TRUE);
- complete(&dma->comp);
- }
-#endif
- }
- /* PPP Complete */
- if (mdp_interrupt & MDP_PPP_DONE) {
+ /* PPP Complete */
+ if (mdp_interrupt & MDP_PPP_DONE) {
#ifdef CONFIG_FB_MSM_MDP31
- MDP_OUTP(MDP_BASE + 0x00100, 0xFFFF);
+ MDP_OUTP(MDP_BASE + 0x00100, 0xFFFF);
#endif
- mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
- if (mdp_ppp_waiting) {
- mdp_ppp_waiting = FALSE;
- complete(&mdp_ppp_comp);
- }
+ mdp_pipe_ctrl(MDP_PPP_BLOCK, MDP_BLOCK_POWER_OFF, TRUE);
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ if (mdp_ppp_waiting) {
+ mdp_ppp_waiting = FALSE;
+ complete(&mdp_ppp_comp);
}
- } while (1);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ }
- mdp_is_in_isr = FALSE;
+out:
+mdp_is_in_isr = FALSE;
return IRQ_HANDLED;
}
diff --git a/drivers/video/msm/mdp_dma.c b/drivers/video/msm/mdp_dma.c
index f9f7954..3997814 100644
--- a/drivers/video/msm/mdp_dma.c
+++ b/drivers/video/msm/mdp_dma.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -478,16 +478,20 @@
void mdp_dma2_update(struct msm_fb_data_type *mfd)
#endif
{
+ unsigned long flag;
+
down(&mfd->dma->mutex);
if ((mfd) && (!mfd->dma->busy) && (mfd->panel_power_on)) {
down(&mfd->sem);
mfd->ibuf_flushed = TRUE;
mdp_dma2_update_lcd(mfd);
+ spin_lock_irqsave(&mdp_spin_lock, flag);
mdp_enable_irq(MDP_DMA2_TERM);
mfd->dma->busy = TRUE;
INIT_COMPLETION(mfd->dma->comp);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
/* schedule DMA to start */
mdp_dma_schedule(mfd, MDP_DMA2_TERM);
up(&mfd->sem);
diff --git a/drivers/video/msm/mipi_chimei_wuxga.c b/drivers/video/msm/mipi_chimei_wuxga.c
new file mode 100644
index 0000000..c63df46
--- /dev/null
+++ b/drivers/video/msm/mipi_chimei_wuxga.c
@@ -0,0 +1,196 @@
+/* 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.
+ *
+ */
+
+/*
+ * Chimei WUXGA LVDS Panel driver.
+ * The panel model is N101JSF-L21.
+ *
+ * The panel interface includes:
+ * 1. LVDS input for video (clock & data).
+ * 2. few configuration pins to control 3D module: Enable, Mode (2D/3D).
+ * 3. Backlight LED control (PWM 200 HZ).
+ *
+ * This panel is controled via the Toshiba DSI-to-LVDS bridge.
+ *
+ */
+
+/* #define DEBUG 1 */
+
+#include "msm_fb.h"
+#include "msm_fb_panel.h"
+#include "mipi_dsi.h"
+#include "mipi_tc358764_dsi2lvds.h"
+
+#define MHZ (1000*1000)
+
+/**
+ * Panel info parameters.
+ * The panel info is passed to the mipi framebuffer driver.
+ */
+static struct msm_panel_info chimei_wuxga_pinfo;
+
+/**
+ * The mipi_dsi_phy_ctrl is calculated according to the
+ * "dsi_timing_program.xlsm" excel sheet.
+ * Output is based on: 1200x1920, RGB565, 4 lanes , 58 frames
+ * per second.
+ */
+static struct mipi_dsi_phy_ctrl dsi_video_mode_phy_db = {
+ /* DSIPHY_REGULATOR_CTRL */
+ .regulator = {0x03, 0x0a, 0x04, 0x00, 0x20}, /* common 8960 */
+ /* DSIPHY_CTRL */
+ .ctrl = {0x5f, 0x00, 0x00, 0x10}, /* common 8960 */
+ /* DSIPHY_STRENGTH_CTRL */
+ .strength = {0xff, 0x00, 0x06, 0x00}, /* common 8960 */
+ /* DSIPHY_TIMING_CTRL */
+ .timing = { 0xC9, 0x92, 0x29, /* panel specific */
+ 0, /* DSIPHY_TIMING_CTRL_3 = 0 */
+ 0x2E, 0x9B, 0x2C, 0x94, 0x2E, 0x03, 0x04}, /* panel specific */
+
+ /* DSIPHY_PLL_CTRL */
+ .pll = { 0x00, /* common 8960 */
+ /* VCO */
+ 0x32, (0x01 | 0x30) , (0x19 | 0xC0), /* panel specific */
+ 0x00, 0x50, 0x48, 0x63,
+ 0x77, 0x88, 0x99, /* Auto update by dsi-mipi driver */
+ 0x00, 0x14, 0x03, 0x00, 0x02, /* common 8960 */
+ 0x00, 0x20, 0x00, 0x01 }, /* common 8960 */
+};
+
+/**
+ * Module init.
+ *
+ * Register the panel-info.
+ *
+ * Some parameters are from the panel datasheet
+ * and other are *calculated* by the "dsi_timing_program.xlsm"
+ * excel file
+ *
+ * @return int
+ */
+static int __init mipi_chimei_wuxga_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo = &chimei_wuxga_pinfo;
+
+ if (msm_fb_detect_client("mipi_video_chimei_wuxga"))
+ return 0;
+
+ pr_info("mipi-dsi chimei wuxga (1200x1920) driver ver 1.0.\n");
+
+ /* Portrait */
+ pinfo->xres = 1200;
+ pinfo->yres = 1920;
+ pinfo->type = MIPI_VIDEO_PANEL;
+ pinfo->pdest = DISPLAY_1; /* Primary Display */
+ pinfo->wait_cycle = 0;
+ pinfo->bpp = 24; /* RGB565 requires 24 bits-per-pixel :-O */
+ pinfo->fb_num = 2; /* using two frame buffers */
+
+ /*
+ * The CMI panel requires 80 MHZ LVDS-CLK.
+ * The D2L bridge drives the LVDS-CLK from the DSI-CLK.
+ * The DSI-CLK = bitclk/2, 640 MHZ/2= 320 MHZ.
+ * LVDS-CLK = DSI-CLK/4 , 320 MHZ/4= 80 MHZ.
+ */
+
+ pinfo->clk_rate = 640 * MHZ ; /* bitclk Calculated */
+
+ /*
+ * this panel is operated by DE,
+ * vsycn and hsync are ignored
+ */
+
+ pinfo->lcdc.h_front_porch = 16; /* thfp */
+ pinfo->lcdc.h_back_porch = 160; /* thb */
+ pinfo->lcdc.h_pulse_width = 32; /* thpw */
+
+ pinfo->lcdc.v_front_porch = 0; /* tvfp */
+ pinfo->lcdc.v_back_porch = 26; /* tvb */
+ pinfo->lcdc.v_pulse_width = 6; /* tvpw */
+
+ pinfo->lcdc.border_clr = 0; /* black */
+ pinfo->lcdc.underflow_clr = 0xff; /* blue */
+
+ pinfo->lcdc.hsync_skew = 0;
+
+ /* Backlight levels - controled via PMIC pwm gpio */
+ pinfo->bl_max = 15;
+ pinfo->bl_min = 1;
+
+ /* mipi - general */
+ pinfo->mipi.vc = 0; /* virtual channel */
+ pinfo->mipi.rgb_swap = DSI_RGB_SWAP_RGB;
+ pinfo->mipi.tx_eot_append = true;
+ pinfo->mipi.t_clk_post = 34; /* Calculated */
+ pinfo->mipi.t_clk_pre = 69; /* Calculated */
+
+ pinfo->mipi.dsi_phy_db = &dsi_video_mode_phy_db;
+
+ /* Four lanes are recomended for 1920x1200 at 60 frames per second */
+ pinfo->mipi.frame_rate = 45; /* 45 frames per second */
+ pinfo->mipi.data_lane0 = true;
+ pinfo->mipi.data_lane1 = true;
+ pinfo->mipi.data_lane2 = true;
+ pinfo->mipi.data_lane3 = true;
+
+ pinfo->mipi.mode = DSI_VIDEO_MODE;
+ /*
+ * Note: The CMI panel input is RGB888,
+ * thus the DSI-to-LVDS bridge output is RGB888.
+ * This parameter selects the DSI-Core output to the bridge.
+ */
+ pinfo->mipi.dst_format = DSI_VIDEO_DST_FORMAT_RGB565;
+
+ /* mipi - video mode */
+ pinfo->mipi.traffic_mode = DSI_NON_BURST_SYNCH_EVENT;
+ pinfo->mipi.pulse_mode_hsa_he = false; /* sync mode */
+
+ pinfo->mipi.hfp_power_stop = false;
+ pinfo->mipi.hbp_power_stop = false;
+ pinfo->mipi.hsa_power_stop = false;
+ pinfo->mipi.eof_bllp_power_stop = false;
+ pinfo->mipi.bllp_power_stop = false;
+
+ /* mipi - command mode */
+ pinfo->mipi.te_sel = 1; /* TE from vsycn gpio */
+ pinfo->mipi.interleave_max = 1;
+ /* The bridge supports only Generic Read/Write commands */
+ pinfo->mipi.insert_dcs_cmd = false;
+ pinfo->mipi.wr_mem_continue = 0;
+ pinfo->mipi.wr_mem_start = 0;
+ pinfo->mipi.stream = false; /* dma_p */
+ pinfo->mipi.mdp_trigger = DSI_CMD_TRIGGER_NONE;
+ pinfo->mipi.dma_trigger = DSI_CMD_TRIGGER_SW;
+ /*
+ * toshiba d2l chip does not need max_pkt_size dcs cmd
+ * client reply len is directly configure through
+ * RDPKTLN register (0x0404)
+ */
+ pinfo->mipi.no_max_pkt_size = 1;
+ pinfo->mipi.force_clk_lane_hs = 1;
+
+ pinfo->is_3d_panel = FB_TYPE_3D_PANEL;
+
+ ret = mipi_tc358764_dsi2lvds_register(pinfo, MIPI_DSI_PRIM, 1);
+ if (ret)
+ pr_err("%s: failed to register device!\n", __func__);
+
+ return ret;
+}
+
+module_init(mipi_chimei_wuxga_init);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Chimei WUXGA LVDS Panel driver");
+MODULE_AUTHOR("Amir Samuelov <amirs@codeaurora.org>");
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 42fa2ba..489e6d2 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -1520,8 +1520,8 @@
pdata->set_backlight(mfd);
bl_level_old = unset_bl_level;
up(&mfd->sem);
+ bl_updated = 1;
}
- bl_updated = 1;
}
++mfd->panel_info.frame_count;
@@ -2624,8 +2624,8 @@
pdata->set_backlight(mfd);
bl_level_old = unset_bl_level;
up(&mfd->sem);
+ bl_updated = 1;
}
- bl_updated = 1;
}
return ret;
diff --git a/include/linux/mfd/wcd9310/core.h b/include/linux/mfd/wcd9310/core.h
index 982803d..8605ac6 100644
--- a/include/linux/mfd/wcd9310/core.h
+++ b/include/linux/mfd/wcd9310/core.h
@@ -14,6 +14,7 @@
#define __MFD_TABLA_CORE_H__
#include <linux/interrupt.h>
+#include <linux/wakelock.h>
#define TABLA_NUM_IRQ_REGS 3
@@ -55,6 +56,12 @@
TABLA_NUM_IRQS,
};
+enum tabla_pm_state {
+ TABLA_PM_SLEEPABLE,
+ TABLA_PM_AWAKE,
+ TABLA_PM_ASLEEP,
+};
+
struct tabla {
struct device *dev;
struct slim_device *slim;
@@ -78,23 +85,33 @@
int bytes, void *src, bool interface_reg);
struct regulator_bulk_data *supplies;
+
+ enum tabla_pm_state pm_state;
+ struct mutex pm_lock;
+ /* pm_wq notifies change of pm_state */
+ wait_queue_head_t pm_wq;
+ struct wake_lock wlock;
+ int wlock_holders;
};
int tabla_reg_read(struct tabla *tabla, unsigned short reg);
-int tabla_reg_write(struct tabla *tabla, unsigned short reg,
- u8 val);
+int tabla_reg_write(struct tabla *tabla, unsigned short reg, u8 val);
int tabla_interface_reg_read(struct tabla *tabla, unsigned short reg);
-int tabla_interface_reg_write(struct tabla *tabla, unsigned short reg,
- u8 val);
-int tabla_bulk_read(struct tabla *tabla, unsigned short reg,
- int count, u8 *buf);
-int tabla_bulk_write(struct tabla *tabla, unsigned short reg,
- int count, u8 *buf);
+int tabla_interface_reg_write(struct tabla *tabla, unsigned short reg, u8 val);
+int tabla_bulk_read(struct tabla *tabla, unsigned short reg, int count,
+ u8 *buf);
+int tabla_bulk_write(struct tabla *tabla, unsigned short reg, int count,
+ u8 *buf);
int tabla_irq_init(struct tabla *tabla);
void tabla_irq_exit(struct tabla *tabla);
int tabla_get_logical_addresses(u8 *pgd_la, u8 *inf_la);
int tabla_get_intf_type(void);
+void tabla_lock_sleep(struct tabla *tabla);
+void tabla_unlock_sleep(struct tabla *tabla);
+enum tabla_pm_state tabla_pm_cmpxchg(struct tabla *tabla, enum tabla_pm_state o,
+ enum tabla_pm_state n);
+
static inline int tabla_request_irq(struct tabla *tabla, int irq,
irq_handler_t handler, const char *name,
void *data)
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 2cbe6ce..037cfe7 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -164,6 +164,7 @@
* @enable_dcd: Enable Data Contact Detection circuit. if not set
* wait for 600msec before proceeding to primary
* detection.
+ * @bus_scale_table: parameters for bus bandwidth requirements
*/
struct msm_otg_platform_data {
int *phy_init_seq;
@@ -179,6 +180,7 @@
bool disable_reset_on_disconnect;
u32 swfi_latency;
bool enable_dcd;
+ struct msm_bus_scale_pdata *bus_scale_table;
};
/**
@@ -211,6 +213,7 @@
collapse when cable is connected.
* @id_timer: The timer used for polling ID line to detect ACA states.
* @xo_handle: TCXO buffer handle
+ * @bus_perf_client: Bus performance client handle to request BUS bandwidth
*/
struct msm_otg {
struct otg_transceiver otg;
@@ -241,6 +244,7 @@
struct timer_list id_timer;
unsigned long caps;
struct clk *xo_handle;
+ uint32_t bus_perf_client;
/*
* Allowing PHY power collpase turns off the HSUSB 3.3v and 1.8v
* analog regulators while going to low power mode.
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index 8d2852b..87fbbd2 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -217,7 +217,8 @@
#define PP_SNAP 0x01
#define PP_RAW_SNAP ((0x01)<<1)
#define PP_PREV ((0x01)<<2)
-#define PP_MASK (PP_SNAP|PP_RAW_SNAP|PP_PREV)
+#define PP_THUMB ((0x01)<<3)
+#define PP_MASK (PP_SNAP|PP_RAW_SNAP|PP_PREV|PP_THUMB)
#define MSM_CAM_CTRL_CMD_DONE 0
#define MSM_CAM_SENSOR_VFE_CMD 1
@@ -295,6 +296,7 @@
struct msm_pp_frame_sp sp;
struct msm_pp_frame_mp mp[MAX_PLANES];
};
+ int node_type;
};
struct msm_cam_evt_divert_frame {
@@ -509,6 +511,9 @@
uint32_t window_height_lastline;
};
+#define VIDEO_NODE 0
+#define MCTL_NODE 1
+
#define OUTPUT_1 0
#define OUTPUT_2 1
#define OUTPUT_1_AND_2 2 /* snapshot only */
diff --git a/include/media/msm_isp.h b/include/media/msm_isp.h
index 7caafb6..5dd1445 100644
--- a/include/media/msm_isp.h
+++ b/include/media/msm_isp.h
@@ -58,6 +58,7 @@
#define MSG_ID_STATS_AWB_AEC 39
#define MSG_ID_OUTPUT_PRIMARY 40
#define MSG_ID_OUTPUT_SECONDARY 41
+#define MSG_ID_STATS_COMPOSITE 42
/* ISP command IDs */
#define VFE_CMD_DUMMY_0 0
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 30f1a7c..87bafed 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -234,10 +234,18 @@
/* HDMI_5Point1 (6-ch) = 2 */
/* HDMI_6Point1 (8-ch) = 3 */
u16 data_type; /* HDMI_Linear = 0 */
- /* HDMI_non_Linaer = 1 */
+ /* HDMI_non_Linear = 1 */
} __attribute__ ((packed));
+struct afe_port_hdmi_multi_ch_cfg {
+ u16 data_type; /* HDMI_Linear = 0 */
+ /* HDMI_non_Linear = 1 */
+ u16 channel_allocation; /* The default is 0 (Stereo) */
+ u16 reserved; /* must be set to 0 */
+} __packed;
+
+
/* Slimbus Device Ids */
#define AFE_SLIMBUS_DEVICE_1 0x0
#define AFE_SLIMBUS_DEVICE_2 0x1
@@ -276,14 +284,16 @@
int num_ch; /* 1 to 8 */
} __packed;
-#define AFE_PORT_AUDIO_IF_CONFIG 0x000100d3
+#define AFE_PORT_AUDIO_IF_CONFIG 0x000100d3
+#define AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG 0x000100D9
union afe_port_config {
- struct afe_port_pcm_cfg pcm;
- struct afe_port_mi2s_cfg mi2s;
- struct afe_port_hdmi_cfg hdmi;
- struct afe_port_slimbus_cfg slimbus;
- struct afe_port_rtproxy_cfg rtproxy;
+ struct afe_port_pcm_cfg pcm;
+ struct afe_port_mi2s_cfg mi2s;
+ struct afe_port_hdmi_cfg hdmi;
+ struct afe_port_hdmi_multi_ch_cfg hdmi_multi_ch;
+ struct afe_port_slimbus_cfg slimbus;
+ struct afe_port_rtproxy_cfg rtproxy;
} __attribute__((packed));
struct afe_audioif_config_command {
@@ -482,6 +492,20 @@
#define ADM_CMD_COPP_CLOSE 0x00010305
+#define ADM_CMD_MULTI_CHANNEL_COPP_OPEN 0x00010310
+struct adm_multi_ch_copp_open_command {
+ struct apr_hdr hdr;
+ u16 flags;
+ u16 mode; /* 1-RX, 2-Live TX, 3-Non Live TX */
+ u16 endpoint_id1;
+ u16 endpoint_id2;
+ u32 topology_id;
+ u16 channel_config;
+ u16 reserved;
+ u32 rate;
+ u8 dev_channel_mapping[8];
+} __packed;
+
#define ADM_CMD_MEMORY_MAP 0x00010C30
struct adm_cmd_memory_map{
struct apr_hdr hdr;
@@ -635,6 +659,9 @@
u16 reserved;
} __attribute__ ((packed));
+#define ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN 0x00010311
+
+
#define ASM_STREAM_PRIORITY_NORMAL 0
#define ASM_STREAM_PRIORITY_LOW 1
#define ASM_STREAM_PRIORITY_HIGH 2
@@ -676,6 +703,125 @@
u16 interleaved;
};
+#define PCM_CHANNEL_NULL 0
+
+/* Front left channel. */
+#define PCM_CHANNEL_FL 1
+
+/* Front right channel. */
+#define PCM_CHANNEL_FR 2
+
+/* Front center channel. */
+#define PCM_CHANNEL_FC 3
+
+/* Left surround channel.*/
+#define PCM_CHANNEL_LS 4
+
+/* Right surround channel.*/
+#define PCM_CHANNEL_RS 5
+
+/* Low frequency effect channel. */
+#define PCM_CHANNEL_LFE 6
+
+/* Center surround channel; Rear center channel. */
+#define PCM_CHANNEL_CS 7
+
+/* Left back channel; Rear left channel. */
+#define PCM_CHANNEL_LB 8
+
+/* Right back channel; Rear right channel. */
+#define PCM_CHANNEL_RB 9
+
+/* Top surround channel. */
+#define PCM_CHANNEL_TS 10
+
+/* Center vertical height channel.*/
+#define PCM_CHANNEL_CVH 11
+
+/* Mono surround channel.*/
+#define PCM_CHANNEL_MS 12
+
+/* Front left of center. */
+#define PCM_CHANNEL_FLC 13
+
+/* Front right of center. */
+#define PCM_CHANNEL_FRC 14
+
+/* Rear left of center. */
+#define PCM_CHANNEL_RLC 15
+
+/* Rear right of center. */
+#define PCM_CHANNEL_RRC 16
+
+#define PCM_FORMAT_MAX_NUM_CHANNEL 8
+
+
+/*
+ * Multiple-channel PCM decoder format block structure used in the
+ * #ASM_STREAM_CMD_OPEN_WRITE command.
+ * The data must be in little-endian format.
+ */
+struct asm_multi_channel_pcm_fmt_blk {
+
+ u16 num_channels; /*
+ * Number of channels.
+ * Supported values:1 to 8
+ */
+
+ u16 bits_per_sample; /*
+ * Number of bits per sample per channel.
+ * Supported values: 16, 24 When used for
+ * playback, the client must send 24-bit
+ * samples packed in 32-bit words. The
+ * 24-bit samples must be placed in the most
+ * significant 24 bits of the 32-bit word. When
+ * used for recording, the aDSP sends 24-bit
+ * samples packed in 32-bit words. The 24-bit
+ * samples are placed in the most significant
+ * 24 bits of the 32-bit word.
+ */
+
+ u32 sample_rate; /*
+ * Number of samples per second
+ * (in Hertz). Supported values:
+ * 2000 to 48000
+ */
+
+ u16 is_signed; /*
+ * Flag that indicates the samples
+ * are signed (1).
+ */
+
+ u16 is_interleaved; /*
+ * Flag that indicates whether the channels are
+ * de-interleaved (0) or interleaved (1).
+ * Interleaved format means corresponding
+ * samples from the left and right channels are
+ * interleaved within the buffer.
+ * De-interleaved format means samples from
+ * each channel are contiguous in the buffer.
+ * The samples from one channel immediately
+ * follow those of the previous channel.
+ */
+
+ u8 channel_mapping[8]; /*
+ * Supported values:
+ * PCM_CHANNEL_NULL, PCM_CHANNEL_FL,
+ * PCM_CHANNEL_FR, PCM_CHANNEL_FC,
+ * PCM_CHANNEL_LS, PCM_CHANNEL_RS,
+ * PCM_CHANNEL_LFE, PCM_CHANNEL_CS,
+ * PCM_CHANNEL_LB, PCM_CHANNEL_RB,
+ * PCM_CHANNEL_TS, PCM_CHANNEL_CVH,
+ * PCM_CHANNEL_MS, PCM_CHANNEL_FLC,
+ * PCM_CHANNEL_FRC, PCM_CHANNEL_RLC,
+ * PCM_CHANNEL_RRC.
+ * Channel[i] mapping describes channel I. Each
+ * element i of the array describes channel I
+ * inside the buffer where I < num_channels.
+ * An unused channel is set to zero.
+ */
+};
+
struct asm_adpcm_cfg {
u16 ch_cfg;
u16 bits_per_sample;
@@ -878,6 +1024,7 @@
#define MPEG4_MULTI_AAC 0x00010D86
#define US_POINT_EPOS_FORMAT 0x00012310
#define US_RAW_FORMAT 0x0001127C
+#define MULTI_CHANNEL_PCM 0x00010C66
#define ASM_ENCDEC_SBCRATE 0x00010C13
#define ASM_ENCDEC_IMMDIATE_DECODE 0x00010C14
@@ -1059,6 +1206,7 @@
struct asm_aac_cfg aac_cfg;
struct asm_flac_cfg flac_cfg;
struct asm_vorbis_cfg vorbis_cfg;
+ struct asm_multi_channel_pcm_fmt_blk multi_ch_pcm_cfg;
} __attribute__((packed)) write_cfg;
} __attribute__((packed));
diff --git a/include/sound/q6adm.h b/include/sound/q6adm.h
index 80374c5..fe25d22 100644
--- a/include/sound/q6adm.h
+++ b/include/sound/q6adm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -26,6 +26,9 @@
int adm_open(int port, int path, int rate, int mode, int topology);
+int adm_multi_ch_copp_open(int port, int path, int rate, int mode,
+ int topology);
+
int adm_memory_map_regions(uint32_t *buf_add, uint32_t mempool_id,
uint32_t *bufsz, uint32_t bufcnt);
diff --git a/include/sound/q6asm.h b/include/sound/q6asm.h
index 16439e8..d08f528 100644
--- a/include/sound/q6asm.h
+++ b/include/sound/q6asm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -39,6 +39,7 @@
#define FORMAT_WMA_V9 0x000f
#define FORMAT_AMR_WB_PLUS 0x0010
#define FORMAT_MPEG4_MULTI_AAC 0x0011
+#define FORMAT_MULTI_CHANNEL_LINEAR_PCM 0x0012
#define ENCDEC_SBCBITRATE 0x0001
#define ENCDEC_IMMEDIATE_DECODE 0x0002
@@ -244,6 +245,9 @@
int q6asm_media_format_block_pcm(struct audio_client *ac,
uint32_t rate, uint32_t channels);
+int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
+ uint32_t rate, uint32_t channels);
+
int q6asm_media_format_block_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index f0f2ac1..899c538 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -65,7 +65,7 @@
cp.peer_addr_type = conn->dst_type;
cp.conn_interval_min = cpu_to_le16(0x0008);
cp.conn_interval_max = cpu_to_le16(0x0100);
- cp.supervision_timeout = cpu_to_le16(0x0064);
+ cp.supervision_timeout = cpu_to_le16(1000);
cp.min_ce_len = cpu_to_le16(0x0001);
cp.max_ce_len = cpu_to_le16(0x0001);
diff --git a/scripts/gcc-wrapper.py b/scripts/gcc-wrapper.py
index 65744e1..0104f1a 100755
--- a/scripts/gcc-wrapper.py
+++ b/scripts/gcc-wrapper.py
@@ -57,8 +57,34 @@
"inode.c:74",
"msm_sdcc.c:126",
"msm_sdcc.c:128",
+ "nf_conntrack_core.c:1579",
+ "nf_conntrack_core.c:1580",
"nf_conntrack_netlink.c:790",
+ "nf_conntrack_proto.c:210",
+ "nf_conntrack_proto.c:345",
+ "nf_conntrack_proto.c:370",
+ "nf_nat_core.c:528",
+ "nf_nat_core.c:739",
+ "nf_nat_core.c:740",
+ "nf_nat_core.c:741",
+ "nf_nat_core.c:742",
+ "nf_nat_core.c:751",
+ "nf_nat_core.c:753",
+ "nf_nat_core.c:756",
+ "nf_nat_ftp.c:123",
+ "nf_nat_pptp.c:285",
+ "nf_nat_pptp.c:288",
+ "nf_nat_pptp.c:291",
+ "nf_nat_pptp.c:294",
+ "nf_nat_sip.c:550",
+ "nf_nat_sip.c:551",
+ "nf_nat_sip.c:552",
+ "nf_nat_sip.c:553",
+ "nf_nat_sip.c:555",
+ "nf_nat_sip.c:556",
+ "nf_nat_sip.c:554",
"nf_nat_standalone.c:118",
+ "nf_nat_tftp.c:46",
"return_address.c:62",
"sch_generic.c:678",
"soc-core.c:1719",
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index d4e9ecf..7c2073d 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -185,11 +185,6 @@
struct work_struct hphlocp_work; /* reporting left hph ocp off */
struct work_struct hphrocp_work; /* reporting right hph ocp off */
- /* pm_cnt holds number of sleep lock holders + 1
- * so if pm_cnt is 1 system is sleep-able. */
- atomic_t pm_cnt;
- wait_queue_head_t pm_wq;
-
u8 hphlocp_cnt; /* headphone left ocp retry */
u8 hphrocp_cnt; /* headphone right ocp retry */
@@ -3331,24 +3326,6 @@
return 0;
}
-static void tabla_lock_sleep(struct tabla_priv *tabla)
-{
- int ret;
- while (!(ret = wait_event_timeout(tabla->pm_wq,
- atomic_inc_not_zero(&tabla->pm_cnt),
- 2 * HZ))) {
- pr_err("%s: didn't wake up for 2000ms (%d), pm_cnt %d\n",
- __func__, ret, atomic_read(&tabla->pm_cnt));
- WARN_ON_ONCE(1);
- }
-}
-
-static void tabla_unlock_sleep(struct tabla_priv *tabla)
-{
- atomic_dec(&tabla->pm_cnt);
- wake_up(&tabla->pm_wq);
-}
-
static u16 tabla_codec_v_sta_dce(struct snd_soc_codec *codec, bool dce,
s16 vin_mv)
{
@@ -3403,11 +3380,13 @@
struct tabla_priv *tabla;
short bias_value;
int dce_mv, sta_mv;
+ struct tabla *core;
pr_debug("%s:\n", __func__);
delayed_work = to_delayed_work(work);
tabla = container_of(delayed_work, struct tabla_priv, btn0_dwork);
+ core = dev_get_drvdata(tabla->codec->dev->parent);
if (tabla) {
if (tabla->button_jack) {
@@ -3428,7 +3407,7 @@
pr_err("%s: Bad tabla private data\n", __func__);
}
- tabla_unlock_sleep(tabla);
+ tabla_unlock_sleep(core);
}
void tabla_mbhc_cal(struct snd_soc_codec *codec)
@@ -3877,10 +3856,10 @@
TABLA_MBHC_CAL_BTN_DET_PTR(priv->calibration);
short btnmeas[d->n_btn_meas + 1];
struct snd_soc_codec *codec = priv->codec;
+ struct tabla *core = dev_get_drvdata(priv->codec->dev->parent);
tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
- tabla_lock_sleep(priv);
bias_value_dce = tabla_codec_read_dce_result(codec);
bias_mv_dce = tabla_codec_sta_dce_v(codec, 1, bias_value_dce);
@@ -3926,11 +3905,12 @@
/* XXX: assuming button 0 has the lowest micbias voltage */
if (btn == 0) {
+ tabla_lock_sleep(core);
if (schedule_delayed_work(&priv->btn0_dwork,
msecs_to_jiffies(400)) == 0) {
WARN(1, "Button pressed twice without release"
"event\n");
- tabla_unlock_sleep(priv);
+ tabla_unlock_sleep(core);
}
} else {
pr_debug("%s: Reporting short button %d(0x%x) press\n",
@@ -3938,23 +3918,24 @@
tabla_snd_soc_jack_report(priv, priv->button_jack, mask,
mask);
}
- } else
+ } else {
pr_debug("%s: bogus button press, too short press?\n",
__func__);
+ }
return IRQ_HANDLED;
}
static irqreturn_t tabla_release_handler(int irq, void *data)
{
- struct tabla_priv *priv = data;
- struct snd_soc_codec *codec = priv->codec;
int ret;
short mb_v;
+ struct tabla_priv *priv = data;
+ struct snd_soc_codec *codec = priv->codec;
+ struct tabla *core = dev_get_drvdata(priv->codec->dev->parent);
pr_debug("%s: enter\n", __func__);
tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
- tabla_lock_sleep(priv);
if (priv->buttons_pressed & SND_JACK_BTN_0) {
ret = cancel_delayed_work(&priv->btn0_dwork);
@@ -3968,7 +3949,7 @@
} else {
/* if scheduled btn0_dwork is canceled from here,
* we have to unlock from here instead btn0_work */
- tabla_unlock_sleep(priv);
+ tabla_unlock_sleep(core);
mb_v = tabla_codec_sta_dce(codec, 0);
pr_debug("%s: Mic Voltage on release STA: %d,%d\n",
__func__, mb_v,
@@ -4006,7 +3987,6 @@
}
tabla_codec_start_hs_polling(codec);
- tabla_unlock_sleep(priv);
return IRQ_HANDLED;
}
@@ -4157,7 +4137,6 @@
pr_debug("%s: enter\n", __func__);
tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_INSERTION);
- tabla_lock_sleep(priv);
is_removal = snd_soc_read(codec, TABLA_A_CDC_MBHC_INT_CTL) & 0x02;
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_INT_CTL, 0x03, 0x00);
@@ -4229,7 +4208,6 @@
}
tabla_codec_shutdown_hs_removal_detect(codec);
tabla_codec_enable_hs_detect(codec, 1);
- tabla_unlock_sleep(priv);
return IRQ_HANDLED;
}
@@ -4308,7 +4286,6 @@
tabla_sync_hph_state(priv);
}
- tabla_unlock_sleep(priv);
return IRQ_HANDLED;
}
@@ -4326,7 +4303,6 @@
tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_REMOVAL);
tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_POTENTIAL);
tabla_disable_irq(codec->control_data, TABLA_IRQ_MBHC_RELEASE);
- tabla_lock_sleep(priv);
usleep_range(generic->t_shutdown_plug_rem,
generic->t_shutdown_plug_rem);
@@ -4364,7 +4340,6 @@
tabla_codec_enable_hs_detect(codec, 1);
}
- tabla_unlock_sleep(priv);
return IRQ_HANDLED;
}
@@ -4377,8 +4352,6 @@
int i, j;
u8 val;
- tabla_lock_sleep(priv);
-
for (i = 0; i < TABLA_SLIM_NUM_PORT_REG; i++) {
slimbus_value = tabla_interface_reg_read(codec->control_data,
TABLA_SLIM_PGD_PORT_INT_STATUS0 + i);
@@ -4396,7 +4369,6 @@
TABLA_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
}
- tabla_unlock_sleep(priv);
return IRQ_HANDLED;
}
@@ -4742,8 +4714,6 @@
tabla->codec = codec;
tabla->pdata = dev_get_platdata(codec->dev->parent);
tabla->intf_type = tabla_get_intf_type();
- atomic_set(&tabla->pm_cnt, 1);
- init_waitqueue_head(&tabla->pm_wq);
tabla_update_reg_address(tabla);
tabla_update_reg_defaults(codec);
@@ -4941,7 +4911,6 @@
buf = (char *)lbuf;
debug_tabla_priv->no_mic_headset_override = (*strsep(&buf, " ") == '0')
? false : true;
-
return rc;
}
@@ -4954,53 +4923,14 @@
#ifdef CONFIG_PM
static int tabla_suspend(struct device *dev)
{
- int ret = 0, cnt;
- struct platform_device *pdev = to_platform_device(dev);
- struct tabla_priv *tabla = platform_get_drvdata(pdev);
-
- cnt = atomic_read(&tabla->pm_cnt);
- if (cnt > 0) {
- if (wait_event_timeout(tabla->pm_wq,
- (atomic_cmpxchg(&tabla->pm_cnt, 1, 0)
- == 1), 5 * HZ)) {
- dev_dbg(dev, "system suspend pm_cnt %d\n",
- atomic_read(&tabla->pm_cnt));
- } else {
- dev_err(dev, "%s timed out pm_cnt = %d\n",
- __func__, atomic_read(&tabla->pm_cnt));
- WARN_ON_ONCE(1);
- ret = -EBUSY;
- }
- } else if (cnt == 0)
- dev_warn(dev, "system is already in suspend, pm_cnt %d\n",
- atomic_read(&tabla->pm_cnt));
- else {
- WARN(1, "unexpected pm_cnt %d\n", cnt);
- ret = -EFAULT;
- }
-
- return ret;
+ dev_dbg(dev, "%s: system suspend\n", __func__);
+ return 0;
}
static int tabla_resume(struct device *dev)
{
- int ret = 0, cnt;
- struct platform_device *pdev = to_platform_device(dev);
- struct tabla_priv *tabla = platform_get_drvdata(pdev);
-
- cnt = atomic_cmpxchg(&tabla->pm_cnt, 0, 1);
- if (cnt == 0) {
- dev_dbg(dev, "system resume, pm_cnt %d\n",
- atomic_read(&tabla->pm_cnt));
- wake_up_all(&tabla->pm_wq);
- } else if (cnt > 0)
- dev_warn(dev, "system is already awake, pm_cnt %d\n", cnt);
- else {
- WARN(1, "unexpected pm_cnt %d\n", cnt);
- ret = -EFAULT;
- }
-
- return ret;
+ dev_dbg(dev, "%s: system resume\n", __func__);
+ return 0;
}
static const struct dev_pm_ops tabla_pm_ops = {
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index 9e0549b..1ed5f74 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -80,6 +80,13 @@
config SND_VOIP_PCM
tristate
+config SND_SOC_MSM_QDSP6_HDMI_AUDIO
+ tristate "Soc QDSP6 HDMI Audio DAI driver"
+ depends on FB_MSM_HDMI_MSM_PANEL
+ default n
+ help
+ To support HDMI Audio on MSM8960 over QDSP6.
+
config MSM_8x60_VOIP
tristate "SoC Machine driver for voip"
depends on SND_SOC_MSM8X60
@@ -120,6 +127,7 @@
select SND_SOC_MSM_STUB
select SND_SOC_WCD9310
select SND_SOC_MSM_HOSTLESS_PCM
+ select SND_SOC_MSM_QDSP6_HDMI_AUDIO
default n
help
To add support for SoC audio on MSM8960 and APQ8064 boards
diff --git a/sound/soc/msm/Makefile b/sound/soc/msm/Makefile
index c583ce2..1b3014e 100644
--- a/sound/soc/msm/Makefile
+++ b/sound/soc/msm/Makefile
@@ -56,7 +56,8 @@
obj-$(CONFIG_SND_SOC_MSM_QDSP6_INTF) += qdsp6/
-snd-soc-qdsp6-objs := msm-dai-q6.o msm-pcm-q6.o msm-pcm-routing.o msm-dai-fe.o msm-compr-q6.o
+snd-soc-qdsp6-objs := msm-dai-q6.o msm-pcm-q6.o msm-multi-ch-pcm-q6.o msm-pcm-routing.o msm-dai-fe.o msm-compr-q6.o
+obj-$(CONFIG_SND_SOC_MSM_QDSP6_HDMI_AUDIO) += msm-dai-q6-hdmi.o
obj-$(CONFIG_SND_SOC_VOICE) += msm-pcm-voice.o msm-pcm-voip.o
snd-soc-qdsp6-objs += msm-pcm-lpa.o msm-pcm-afe.o
obj-$(CONFIG_SND_SOC_QDSP6) += snd-soc-qdsp6.o
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 42e7935..8f71e83 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -75,7 +75,7 @@
.rates = SNDRV_PCM_RATE_8000_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 6,
.rate_min = 8000,
.rate_max = 48000,
},
diff --git a/sound/soc/msm/msm-dai-q6-hdmi.c b/sound/soc/msm/msm-dai-q6-hdmi.c
new file mode 100644
index 0000000..6907ded
--- /dev/null
+++ b/sound/soc/msm/msm-dai-q6-hdmi.c
@@ -0,0 +1,283 @@
+/* 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/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/wcd9310/core.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/apr_audio.h>
+#include <sound/q6afe.h>
+#include <sound/q6adm.h>
+#include <sound/msm-dai-q6.h>
+#include <mach/clk.h>
+#include <mach/msm_hdmi_audio.h>
+
+
+enum {
+ STATUS_PORT_STARTED, /* track if AFE port has started */
+ STATUS_MAX
+};
+
+struct msm_dai_q6_hdmi_dai_data {
+ DECLARE_BITMAP(status_mask, STATUS_MAX);
+ u32 rate;
+ u32 channels;
+ union afe_port_config port_config;
+};
+
+
+/* Current implementation assumes hw_param is called once
+ * This may not be the case but what to do when ADM and AFE
+ * port are already opened and parameter changes
+ */
+static int msm_dai_q6_hdmi_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct msm_dai_q6_hdmi_dai_data *dai_data = dev_get_drvdata(dai->dev);
+ u32 channel_allocation = 0;
+ u32 level_shift = 0; /* 0dB */
+ bool down_mix = FALSE;
+
+ dai_data->channels = params_channels(params);
+ dai_data->rate = params_rate(params);
+ dai_data->port_config.hdmi_multi_ch.data_type = 0;
+ dai_data->port_config.hdmi_multi_ch.reserved = 0;
+
+ switch (dai_data->channels) {
+ case 2:
+ channel_allocation = 0;
+ hdmi_msm_audio_info_setup(1, MSM_HDMI_AUDIO_CHANNEL_2,
+ channel_allocation, level_shift, down_mix);
+ dai_data->port_config.hdmi_multi_ch.channel_allocation =
+ channel_allocation;
+ break;
+ case 6:
+ channel_allocation = 0x0B;
+ hdmi_msm_audio_info_setup(1, MSM_HDMI_AUDIO_CHANNEL_6,
+ channel_allocation, level_shift, down_mix);
+ dai_data->port_config.hdmi_multi_ch.channel_allocation =
+ channel_allocation;
+ break;
+ default:
+ dev_err(dai->dev, "invalid Channels = %u\n",
+ dai_data->channels);
+ return -EINVAL;
+ }
+ dev_dbg(dai->dev, "%s() num_ch = %u rate =%u"
+ " channel_allocation = %u\n", __func__, dai_data->channels,
+ dai_data->rate,
+ dai_data->port_config.hdmi_multi_ch.channel_allocation);
+
+ return 0;
+}
+
+
+static void msm_dai_q6_hdmi_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct msm_dai_q6_hdmi_dai_data *dai_data = dev_get_drvdata(dai->dev);
+ int rc = 0;
+
+ if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+ pr_info("%s: afe port not started. dai_data->status_mask"
+ " = %ld\n", __func__, *dai_data->status_mask);
+ return;
+ }
+
+ rc = afe_close(dai->id); /* can block */
+
+ if (IS_ERR_VALUE(rc))
+ dev_err(dai->dev, "fail to close AFE port\n");
+
+ pr_debug("%s: dai_data->status_mask = %ld\n", __func__,
+ *dai_data->status_mask);
+
+ clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
+}
+
+
+static int msm_dai_q6_hdmi_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct msm_dai_q6_hdmi_dai_data *dai_data = dev_get_drvdata(dai->dev);
+ int rc = 0;
+
+ if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+ /* PORT START should be set if prepare called in active state */
+ rc = afe_q6_interface_prepare();
+ if (IS_ERR_VALUE(rc))
+ dev_err(dai->dev, "fail to open AFE APR\n");
+ }
+ return rc;
+}
+
+static int msm_dai_q6_hdmi_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct msm_dai_q6_hdmi_dai_data *dai_data = dev_get_drvdata(dai->dev);
+
+ /* Start/stop port without waiting for Q6 AFE response. Need to have
+ * native q6 AFE driver propagates AFE response in order to handle
+ * port start/stop command error properly if error does arise.
+ */
+ pr_debug("%s:port:%d cmd:%d dai_data->status_mask = %ld",
+ __func__, dai->id, cmd, *dai_data->status_mask);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+ afe_port_start_nowait(dai->id, &dai_data->port_config,
+ dai_data->rate);
+
+ set_bit(STATUS_PORT_STARTED, dai_data->status_mask);
+ }
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+ afe_port_stop_nowait(dai->id);
+ clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
+ }
+ break;
+
+ default:
+ dev_err(dai->dev, "invalid Trigger command = %d\n", cmd);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int msm_dai_q6_hdmi_dai_probe(struct snd_soc_dai *dai)
+{
+ struct msm_dai_q6_hdmi_dai_data *dai_data;
+ int rc = 0;
+
+ dai_data = kzalloc(sizeof(struct msm_dai_q6_hdmi_dai_data),
+ GFP_KERNEL);
+
+ if (!dai_data) {
+ dev_err(dai->dev, "DAI-%d: fail to allocate dai data\n",
+ dai->id);
+ rc = -ENOMEM;
+ } else
+ dev_set_drvdata(dai->dev, dai_data);
+
+ return rc;
+}
+
+static int msm_dai_q6_hdmi_dai_remove(struct snd_soc_dai *dai)
+{
+ struct msm_dai_q6_hdmi_dai_data *dai_data;
+ int rc;
+
+ dai_data = dev_get_drvdata(dai->dev);
+
+ /* If AFE port is still up, close it */
+ if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+ rc = afe_close(dai->id); /* can block */
+
+ if (IS_ERR_VALUE(rc))
+ dev_err(dai->dev, "fail to close AFE port\n");
+
+ clear_bit(STATUS_PORT_STARTED, dai_data->status_mask);
+ }
+ kfree(dai_data);
+ snd_soc_unregister_dai(dai->dev);
+
+ return 0;
+}
+
+static struct snd_soc_dai_ops msm_dai_q6_hdmi_ops = {
+ .prepare = msm_dai_q6_hdmi_prepare,
+ .trigger = msm_dai_q6_hdmi_trigger,
+ .hw_params = msm_dai_q6_hdmi_hw_params,
+ .shutdown = msm_dai_q6_hdmi_shutdown,
+};
+
+static struct snd_soc_dai_driver msm_dai_q6_hdmi_hdmi_rx_dai = {
+ .playback = {
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 2,
+ .channels_max = 6,
+ .rate_max = 48000,
+ .rate_min = 48000,
+ },
+ .ops = &msm_dai_q6_hdmi_ops,
+ .probe = msm_dai_q6_hdmi_dai_probe,
+ .remove = msm_dai_q6_hdmi_dai_remove,
+};
+
+
+/* To do: change to register DAIs as batch */
+static __devinit int msm_dai_q6_hdmi_dev_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+
+ dev_dbg(&pdev->dev, "dev name %s dev-id %d\n",
+ dev_name(&pdev->dev), pdev->id);
+
+ switch (pdev->id) {
+ case HDMI_RX:
+ rc = snd_soc_register_dai(&pdev->dev,
+ &msm_dai_q6_hdmi_hdmi_rx_dai);
+ break;
+ default:
+ dev_err(&pdev->dev, "invalid device ID %d\n", pdev->id);
+ rc = -ENODEV;
+ break;
+ }
+ return rc;
+}
+
+static __devexit int msm_dai_q6_hdmi_dev_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_dai(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver msm_dai_q6_hdmi_driver = {
+ .probe = msm_dai_q6_hdmi_dev_probe,
+ .remove = msm_dai_q6_hdmi_dev_remove,
+ .driver = {
+ .name = "msm-dai-q6-hdmi",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init msm_dai_q6_hdmi_init(void)
+{
+ return platform_driver_register(&msm_dai_q6_hdmi_driver);
+}
+module_init(msm_dai_q6_hdmi_init);
+
+static void __exit msm_dai_q6_hdmi_exit(void)
+{
+ platform_driver_unregister(&msm_dai_q6_hdmi_driver);
+}
+module_exit(msm_dai_q6_hdmi_exit);
+
+/* Module information */
+MODULE_DESCRIPTION("MSM DSP HDMI DAI driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index c7d7004..0951795 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -206,30 +206,6 @@
return 0;
}
-static int msm_dai_q6_hdmi_hw_params(struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
-
- dev_dbg(dai->dev, "%s start HDMI port\n", __func__);
-
- dai_data->channels = params_channels(params);
- switch (dai_data->channels) {
- case 2:
- dai_data->port_config.hdmi.channel_mode = 0; /* Put in macro */
- break;
- default:
- return -EINVAL;
- break;
- }
-
- /* Q6 only supports 16 as now */
- dai_data->port_config.hdmi.bitwidth = 16;
- dai_data->port_config.hdmi.data_type = 0;
- dai_data->rate = params_rate(params);
-
- return 0;
-}
static int msm_dai_q6_slim_bus_hw_params(struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai, int stream)
@@ -425,9 +401,6 @@
case MI2S_RX:
rc = msm_dai_q6_mi2s_hw_params(params, dai, substream->stream);
break;
- case HDMI_RX:
- rc = msm_dai_q6_hdmi_hw_params(params, dai);
- break;
case SLIMBUS_0_RX:
case SLIMBUS_0_TX:
rc = msm_dai_q6_slim_bus_hw_params(params, dai,
@@ -903,20 +876,6 @@
.remove = msm_dai_q6_dai_remove,
};
-static struct snd_soc_dai_driver msm_dai_q6_hdmi_rx_dai = {
- .playback = {
- .rates = SNDRV_PCM_RATE_48000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .channels_min = 2,
- .channels_max = 2,
- .rate_max = 48000,
- .rate_min = 48000,
- },
- .ops = &msm_dai_q6_ops,
- .probe = msm_dai_q6_dai_probe,
- .remove = msm_dai_q6_dai_remove,
-};
-
static struct snd_soc_dai_driver msm_dai_q6_voice_playback_tx_dai = {
.playback = {
.rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
@@ -1101,9 +1060,6 @@
rc = snd_soc_register_dai(&pdev->dev,
&msm_dai_q6_mi2s_rx_dai);
break;
- case HDMI_RX:
- rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_hdmi_rx_dai);
- break;
case SLIMBUS_0_RX:
rc = snd_soc_register_dai(&pdev->dev,
&msm_dai_q6_slimbus_rx_dai);
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
new file mode 100644
index 0000000..1dac5d2
--- /dev/null
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -0,0 +1,723 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/time.h>
+#include <linux/wait.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/android_pmem.h>
+#include <asm/dma.h>
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+
+#include "msm-pcm-q6.h"
+#include "msm-pcm-routing.h"
+
+static struct audio_locks the_locks;
+
+struct snd_msm {
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+};
+
+#define PLAYBACK_NUM_PERIODS 8
+#define PLAYBACK_PERIOD_SIZE 4032
+#define CAPTURE_NUM_PERIODS 16
+#define CAPTURE_PERIOD_SIZE 320
+
+static struct snd_pcm_hardware msm_pcm_hardware_capture = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2,
+ .buffer_bytes_max = CAPTURE_NUM_PERIODS * CAPTURE_PERIOD_SIZE,
+ .period_bytes_min = CAPTURE_PERIOD_SIZE,
+ .period_bytes_max = CAPTURE_PERIOD_SIZE,
+ .periods_min = CAPTURE_NUM_PERIODS,
+ .periods_max = CAPTURE_NUM_PERIODS,
+ .fifo_size = 0,
+};
+
+static struct snd_pcm_hardware msm_pcm_hardware_playback = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 6,
+ .buffer_bytes_max = PLAYBACK_NUM_PERIODS * PLAYBACK_PERIOD_SIZE,
+ .period_bytes_min = PLAYBACK_PERIOD_SIZE,
+ .period_bytes_max = PLAYBACK_PERIOD_SIZE,
+ .periods_min = PLAYBACK_NUM_PERIODS,
+ .periods_max = PLAYBACK_NUM_PERIODS,
+ .fifo_size = 0,
+};
+
+/* Conventional and unconventional sample rate supported */
+static unsigned int supported_sample_rates[] = {
+ 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
+};
+
+static uint32_t in_frame_info[CAPTURE_NUM_PERIODS][2];
+
+static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
+ .count = ARRAY_SIZE(supported_sample_rates),
+ .list = supported_sample_rates,
+ .mask = 0,
+};
+
+static void event_handler(uint32_t opcode,
+ uint32_t token, uint32_t *payload, void *priv)
+{
+ struct msm_audio *prtd = priv;
+ struct snd_pcm_substream *substream = prtd->substream;
+ uint32_t *ptrmem = (uint32_t *)payload;
+ int i = 0;
+ uint32_t idx = 0;
+ uint32_t size = 0;
+
+ pr_debug("%s\n", __func__);
+ switch (opcode) {
+ case ASM_DATA_EVENT_WRITE_DONE: {
+ pr_debug("ASM_DATA_EVENT_WRITE_DONE\n");
+ pr_debug("Buffer Consumed = 0x%08x\n", *ptrmem);
+ prtd->pcm_irq_pos += prtd->pcm_count;
+ if (atomic_read(&prtd->start))
+ snd_pcm_period_elapsed(substream);
+ atomic_inc(&prtd->out_count);
+ wake_up(&the_locks.write_wait);
+ if (!atomic_read(&prtd->start))
+ break;
+ if (!prtd->mmap_flag)
+ break;
+ if (q6asm_is_cpu_buf_avail_nolock(IN,
+ prtd->audio_client,
+ &size, &idx)) {
+ pr_debug("%s:writing %d bytes of buffer to dsp 2\n",
+ __func__, prtd->pcm_count);
+ q6asm_write_nolock(prtd->audio_client,
+ prtd->pcm_count, 0, 0, NO_TIMESTAMP);
+ }
+ break;
+ }
+ case ASM_DATA_CMDRSP_EOS:
+ pr_debug("ASM_DATA_CMDRSP_EOS\n");
+ prtd->cmd_ack = 1;
+ wake_up(&the_locks.eos_wait);
+ break;
+ case ASM_DATA_EVENT_READ_DONE: {
+ pr_debug("ASM_DATA_EVENT_READ_DONE\n");
+ pr_debug("token = 0x%08x\n", token);
+ for (i = 0; i < 8; i++, ++ptrmem)
+ pr_debug("cmd[%d]=0x%08x\n", i, *ptrmem);
+ in_frame_info[token][0] = payload[2];
+ in_frame_info[token][1] = payload[3];
+ prtd->pcm_irq_pos += in_frame_info[token][0];
+ pr_debug("pcm_irq_pos=%d\n", prtd->pcm_irq_pos);
+ if (atomic_read(&prtd->start))
+ snd_pcm_period_elapsed(substream);
+ if (atomic_read(&prtd->in_count) <= prtd->periods)
+ atomic_inc(&prtd->in_count);
+ wake_up(&the_locks.read_wait);
+ if (prtd->mmap_flag
+ && q6asm_is_cpu_buf_avail_nolock(OUT,
+ prtd->audio_client,
+ &size, &idx))
+ q6asm_read_nolock(prtd->audio_client);
+ break;
+ }
+ case APR_BASIC_RSP_RESULT: {
+ switch (payload[0]) {
+ case ASM_SESSION_CMD_RUN:
+ if (substream->stream
+ != SNDRV_PCM_STREAM_PLAYBACK) {
+ atomic_set(&prtd->start, 1);
+ break;
+ }
+ if (prtd->mmap_flag) {
+ pr_debug("%s:writing %d bytes"
+ " of buffer to dsp\n",
+ __func__,
+ prtd->pcm_count);
+ q6asm_write_nolock(prtd->audio_client,
+ prtd->pcm_count,
+ 0, 0, NO_TIMESTAMP);
+ } else {
+ while (atomic_read(&prtd->out_needed)) {
+ pr_debug("%s:writing %d bytes"
+ " of buffer to dsp\n",
+ __func__,
+ prtd->pcm_count);
+ q6asm_write_nolock(prtd->audio_client,
+ prtd->pcm_count,
+ 0, 0, NO_TIMESTAMP);
+ atomic_dec(&prtd->out_needed);
+ wake_up(&the_locks.write_wait);
+ };
+ }
+ atomic_set(&prtd->start, 1);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ default:
+ pr_debug("Not Supported Event opcode[0x%x]\n", opcode);
+ break;
+ }
+}
+
+static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+ int ret;
+
+ pr_debug("%s\n", __func__);
+ prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
+ prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
+ prtd->pcm_irq_pos = 0;
+ /* rate and channels are sent to audio driver */
+ prtd->samp_rate = runtime->rate;
+ prtd->channel_mode = runtime->channels;
+ if (prtd->enabled)
+ return 0;
+
+ ret = q6asm_media_format_block_multi_ch_pcm(prtd->audio_client,
+ runtime->rate, runtime->channels);
+ if (ret < 0)
+ pr_info("%s: CMD Format block failed\n", __func__);
+
+ atomic_set(&prtd->out_count, runtime->periods);
+
+ prtd->enabled = 1;
+ prtd->cmd_ack = 0;
+
+ return 0;
+}
+
+static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+ int ret = 0;
+ int i = 0;
+ pr_debug("%s\n", __func__);
+ prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
+ prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
+ prtd->pcm_irq_pos = 0;
+
+ /* rate and channels are sent to audio driver */
+ prtd->samp_rate = runtime->rate;
+ prtd->channel_mode = runtime->channels;
+
+ if (prtd->enabled)
+ return 0;
+
+ pr_debug("Samp_rate = %d\n", prtd->samp_rate);
+ pr_debug("Channel = %d\n", prtd->channel_mode);
+ ret = q6asm_enc_cfg_blk_pcm(prtd->audio_client, prtd->samp_rate,
+ prtd->channel_mode);
+ if (ret < 0)
+ pr_debug("%s: cmd cfg pcm was block failed", __func__);
+
+ for (i = 0; i < runtime->periods; i++)
+ q6asm_read(prtd->audio_client);
+ prtd->periods = runtime->periods;
+
+ prtd->enabled = 1;
+
+ return ret;
+}
+
+static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ int ret = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ pr_debug("%s: Trigger start\n", __func__);
+ q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
+ atomic_set(&prtd->start, 0);
+ if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
+ break;
+ prtd->cmd_ack = 0;
+ q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ pr_debug("SNDRV_PCM_TRIGGER_PAUSE\n");
+ q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
+ atomic_set(&prtd->start, 0);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int msm_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+ struct msm_audio *prtd;
+ int ret = 0;
+
+ pr_debug("%s\n", __func__);
+ prtd = kzalloc(sizeof(struct msm_audio), GFP_KERNEL);
+ if (prtd == NULL) {
+ pr_err("Failed to allocate memory for msm_audio\n");
+ return -ENOMEM;
+ }
+ prtd->substream = substream;
+ prtd->audio_client = q6asm_audio_client_alloc(
+ (app_cb)event_handler, prtd);
+ if (!prtd->audio_client) {
+ pr_err("%s: Could not allocate memory\n", __func__);
+ kfree(prtd);
+ return -ENOMEM;
+ }
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ runtime->hw = msm_pcm_hardware_playback;
+ ret = q6asm_open_write(prtd->audio_client,
+ FORMAT_MULTI_CHANNEL_LINEAR_PCM);
+ if (ret < 0) {
+ pr_err("%s: pcm out open failed\n", __func__);
+ q6asm_audio_client_free(prtd->audio_client);
+ kfree(prtd);
+ return -ENOMEM;
+ }
+ }
+ /* Capture path */
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ runtime->hw = msm_pcm_hardware_capture;
+ ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM);
+ if (ret < 0) {
+ pr_err("%s: pcm in open failed\n", __func__);
+ q6asm_audio_client_free(prtd->audio_client);
+ kfree(prtd);
+ return -ENOMEM;
+ }
+ }
+
+ pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
+
+ prtd->session_id = prtd->audio_client->session;
+ msm_pcm_routing_reg_phy_stream(soc_prtd->dai_link->be_id,
+ prtd->session_id, substream->stream);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ prtd->cmd_ack = 1;
+
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &constraints_sample_rates);
+ if (ret < 0)
+ pr_err("snd_pcm_hw_constraint_list failed\n");
+ /* Ensure that buffer size is a multiple of period size */
+ ret = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ pr_err("snd_pcm_hw_constraint_integer failed\n");
+
+ prtd->dsp_cnt = 0;
+ runtime->private_data = prtd;
+
+ return 0;
+}
+
+static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
+ snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
+{
+ int ret = 0;
+ int fbytes = 0;
+ int xfer = 0;
+ char *bufptr = NULL;
+ void *data = NULL;
+ uint32_t idx = 0;
+ uint32_t size = 0;
+
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+
+ fbytes = frames_to_bytes(runtime, frames);
+ pr_debug("%s: prtd->out_count = %d\n",
+ __func__, atomic_read(&prtd->out_count));
+ ret = wait_event_timeout(the_locks.write_wait,
+ (atomic_read(&prtd->out_count)), 5 * HZ);
+ if (ret < 0) {
+ pr_err("%s: wait_event_timeout failed\n", __func__);
+ goto fail;
+ }
+
+ if (!atomic_read(&prtd->out_count)) {
+ pr_err("%s: pcm stopped out_count 0\n", __func__);
+ return 0;
+ }
+
+ data = q6asm_is_cpu_buf_avail(IN, prtd->audio_client, &size, &idx);
+ bufptr = data;
+ if (bufptr) {
+ pr_debug("%s:fbytes =%d: xfer=%d size=%d\n",
+ __func__, fbytes, xfer, size);
+ xfer = fbytes;
+ if (copy_from_user(bufptr, buf, xfer)) {
+ ret = -EFAULT;
+ goto fail;
+ }
+ buf += xfer;
+ fbytes -= xfer;
+ pr_debug("%s:fbytes = %d: xfer=%d\n", __func__, fbytes, xfer);
+ if (atomic_read(&prtd->start)) {
+ pr_debug("%s:writing %d bytes of buffer to dsp\n",
+ __func__, xfer);
+ ret = q6asm_write(prtd->audio_client, xfer,
+ 0, 0, NO_TIMESTAMP);
+ if (ret < 0) {
+ ret = -EFAULT;
+ goto fail;
+ }
+ } else
+ atomic_inc(&prtd->out_needed);
+ atomic_dec(&prtd->out_count);
+ }
+fail:
+ return ret;
+}
+
+static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+ struct msm_audio *prtd = runtime->private_data;
+ int dir = 0;
+ int ret = 0;
+
+ pr_debug("%s\n", __func__);
+
+ dir = IN;
+ ret = wait_event_timeout(the_locks.eos_wait,
+ prtd->cmd_ack, 5 * HZ);
+ if (ret < 0)
+ pr_err("%s: CMD_EOS failed\n", __func__);
+ q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+ q6asm_audio_client_buf_free_contiguous(dir,
+ prtd->audio_client);
+
+ msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ q6asm_audio_client_free(prtd->audio_client);
+ kfree(prtd);
+ return 0;
+}
+
+static int msm_pcm_capture_copy(struct snd_pcm_substream *substream,
+ int channel, snd_pcm_uframes_t hwoff, void __user *buf,
+ snd_pcm_uframes_t frames)
+{
+ int ret = 0;
+ int fbytes = 0;
+ int xfer;
+ char *bufptr;
+ void *data = NULL;
+ static uint32_t idx;
+ static uint32_t size;
+ uint32_t offset = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = substream->runtime->private_data;
+
+
+ pr_debug("%s\n", __func__);
+ fbytes = frames_to_bytes(runtime, frames);
+
+ pr_debug("appl_ptr %d\n", (int)runtime->control->appl_ptr);
+ pr_debug("hw_ptr %d\n", (int)runtime->status->hw_ptr);
+ pr_debug("avail_min %d\n", (int)runtime->control->avail_min);
+
+ ret = wait_event_timeout(the_locks.read_wait,
+ (atomic_read(&prtd->in_count)), 5 * HZ);
+ if (ret < 0) {
+ pr_debug("%s: wait_event_timeout failed\n", __func__);
+ goto fail;
+ }
+ if (!atomic_read(&prtd->in_count)) {
+ pr_debug("%s: pcm stopped in_count 0\n", __func__);
+ return 0;
+ }
+ pr_debug("Checking if valid buffer is available...%08x\n",
+ (unsigned int) data);
+ data = q6asm_is_cpu_buf_avail(OUT, prtd->audio_client, &size, &idx);
+ bufptr = data;
+ pr_debug("Size = %d\n", size);
+ pr_debug("fbytes = %d\n", fbytes);
+ pr_debug("idx = %d\n", idx);
+ if (bufptr) {
+ xfer = fbytes;
+ if (xfer > size)
+ xfer = size;
+ offset = in_frame_info[idx][1];
+ pr_debug("Offset value = %d\n", offset);
+ if (copy_to_user(buf, bufptr+offset, xfer)) {
+ pr_err("Failed to copy buf to user\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+ fbytes -= xfer;
+ size -= xfer;
+ in_frame_info[idx][1] += xfer;
+ pr_debug("%s:fbytes = %d: size=%d: xfer=%d\n",
+ __func__, fbytes, size, xfer);
+ pr_debug(" Sending next buffer to dsp\n");
+ memset(&in_frame_info[idx], 0,
+ sizeof(uint32_t) * 2);
+ atomic_dec(&prtd->in_count);
+ ret = q6asm_read(prtd->audio_client);
+ if (ret < 0) {
+ pr_err("q6asm read failed\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+ } else
+ pr_err("No valid buffer\n");
+
+ pr_debug("Returning from capture_copy... %d\n", ret);
+fail:
+ return ret;
+}
+
+static int msm_pcm_capture_close(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
+ struct msm_audio *prtd = runtime->private_data;
+ int dir = OUT;
+
+ pr_debug("%s\n", __func__);
+ q6asm_cmd(prtd->audio_client, CMD_CLOSE);
+ q6asm_audio_client_buf_free_contiguous(dir,
+ prtd->audio_client);
+ msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
+ SNDRV_PCM_STREAM_CAPTURE);
+ q6asm_audio_client_free(prtd->audio_client);
+ kfree(prtd);
+
+ return 0;
+}
+
+static int msm_pcm_copy(struct snd_pcm_substream *substream, int a,
+ snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
+{
+ int ret = 0;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = msm_pcm_playback_copy(substream, a, hwoff, buf, frames);
+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ ret = msm_pcm_capture_copy(substream, a, hwoff, buf, frames);
+ return ret;
+}
+
+static int msm_pcm_close(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = msm_pcm_playback_close(substream);
+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ ret = msm_pcm_capture_close(substream);
+ return ret;
+}
+static int msm_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ int ret = 0;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ ret = msm_pcm_playback_prepare(substream);
+ else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ ret = msm_pcm_capture_prepare(substream);
+ return ret;
+}
+
+static snd_pcm_uframes_t msm_pcm_pointer(struct snd_pcm_substream *substream)
+{
+
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+
+ if (prtd->pcm_irq_pos >= prtd->pcm_size)
+ prtd->pcm_irq_pos = 0;
+
+ pr_debug("pcm_irq_pos = %d\n", prtd->pcm_irq_pos);
+ return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
+}
+
+static int msm_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ int result = 0;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+
+ pr_debug("%s\n", __func__);
+ prtd->mmap_flag = 1;
+
+ if (runtime->dma_addr && runtime->dma_bytes) {
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ result = remap_pfn_range(vma, vma->vm_start,
+ runtime->dma_addr >> PAGE_SHIFT,
+ runtime->dma_bytes,
+ vma->vm_page_prot);
+ } else {
+ pr_err("Physical address or size of buf is NULL");
+ return -EINVAL;
+ }
+
+ return result;
+}
+
+static int msm_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+ struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
+ struct audio_buffer *buf;
+ int dir, ret;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dir = IN;
+ else
+ dir = OUT;
+
+ ret = q6asm_audio_client_buf_alloc_contiguous(dir,
+ prtd->audio_client,
+ runtime->hw.period_bytes_min,
+ runtime->hw.periods_max);
+ if (ret < 0) {
+ pr_err("Audio Start: Buffer Allocation failed rc = %d\n", ret);
+ return -ENOMEM;
+ }
+ buf = prtd->audio_client->port[dir].buf;
+
+ pr_debug("%s:buf = %p\n", __func__, buf);
+ dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ dma_buf->dev.dev = substream->pcm->card->dev;
+ dma_buf->private_data = NULL;
+ dma_buf->area = buf[0].data;
+ dma_buf->addr = buf[0].phys;
+ dma_buf->bytes = runtime->hw.buffer_bytes_max;
+ if (!dma_buf->area)
+ return -ENOMEM;
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+ return 0;
+}
+
+static struct snd_pcm_ops msm_pcm_ops = {
+ .open = msm_pcm_open,
+ .copy = msm_pcm_copy,
+ .hw_params = msm_pcm_hw_params,
+ .close = msm_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .prepare = msm_pcm_prepare,
+ .trigger = msm_pcm_trigger,
+ .pointer = msm_pcm_pointer,
+ .mmap = msm_pcm_mmap,
+};
+
+static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_card *card = rtd->card->snd_card;
+ int ret = 0;
+
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+ return ret;
+}
+
+static struct snd_soc_platform_driver msm_soc_platform = {
+ .ops = &msm_pcm_ops,
+ .pcm_new = msm_asoc_pcm_new,
+};
+
+static __devinit int msm_pcm_probe(struct platform_device *pdev)
+{
+ pr_info("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
+ return snd_soc_register_platform(&pdev->dev,
+ &msm_soc_platform);
+}
+
+static int msm_pcm_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_platform(&pdev->dev);
+ return 0;
+}
+
+static struct platform_driver msm_pcm_driver = {
+ .driver = {
+ .name = "msm-multi-ch-pcm-dsp",
+ .owner = THIS_MODULE,
+ },
+ .probe = msm_pcm_probe,
+ .remove = __devexit_p(msm_pcm_remove),
+};
+
+static int __init msm_soc_platform_init(void)
+{
+ init_waitqueue_head(&the_locks.enable_wait);
+ init_waitqueue_head(&the_locks.eos_wait);
+ init_waitqueue_head(&the_locks.write_wait);
+ init_waitqueue_head(&the_locks.read_wait);
+
+ return platform_driver_register(&msm_pcm_driver);
+}
+module_init(msm_soc_platform_init);
+
+static void __exit msm_soc_platform_exit(void)
+{
+ platform_driver_unregister(&msm_pcm_driver);
+}
+module_exit(msm_soc_platform_exit);
+
+MODULE_DESCRIPTION("Multi channel PCM module platform driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 2b4999f..8b6b5f1 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -162,6 +162,7 @@
{
int i, session_type, path_type, port_type;
struct route_payload payload;
+ u32 channels;
if (fedai_id > MSM_FRONTEND_DAI_MM_MAX_ID) {
/* bad ID assigned in machine driver */
@@ -191,11 +192,23 @@
port_type) && msm_bedais[i].active &&
(test_bit(fedai_id,
&msm_bedais[i].fe_sessions))) {
- adm_open(msm_bedais[i].port_id,
+
+ channels = params_channels(msm_bedais[i].hw_params);
+
+ if ((stream_type == SNDRV_PCM_STREAM_PLAYBACK) &&
+ (channels > 2))
+ adm_multi_ch_copp_open(msm_bedais[i].port_id,
+ path_type,
+ params_rate(msm_bedais[i].hw_params),
+ channels,
+ DEFAULT_COPP_TOPOLOGY);
+ else
+ adm_open(msm_bedais[i].port_id,
path_type,
params_rate(msm_bedais[i].hw_params),
params_channels(msm_bedais[i].hw_params),
DEFAULT_COPP_TOPOLOGY);
+
payload.copp_ids[payload.num_copps++] =
msm_bedais[i].port_id;
}
@@ -243,6 +256,7 @@
static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
{
int session_type, path_type;
+ u32 channels;
pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
@@ -271,10 +285,22 @@
set_bit(val, &msm_bedais[reg].fe_sessions);
if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
INVALID_SESSION) {
- adm_open(msm_bedais[reg].port_id, path_type,
+
+ channels = params_channels(msm_bedais[reg].hw_params);
+
+ if ((session_type == SESSION_TYPE_RX) && (channels > 2))
+ adm_multi_ch_copp_open(msm_bedais[reg].port_id,
+ path_type,
+ params_rate(msm_bedais[reg].hw_params),
+ channels,
+ DEFAULT_COPP_TOPOLOGY);
+ else
+ adm_open(msm_bedais[reg].port_id,
+ path_type,
params_rate(msm_bedais[reg].hw_params),
params_channels(msm_bedais[reg].hw_params),
DEFAULT_COPP_TOPOLOGY);
+
msm_pcm_routing_build_matrix(val,
fe_dai_map[val][session_type], path_type);
}
@@ -1463,6 +1489,7 @@
unsigned int be_id = rtd->dai_link->be_id;
int i, path_type, session_type;
struct msm_pcm_routing_bdai_data *bedai;
+ u32 channels;
if (be_id >= MSM_BACKEND_DAI_MAX) {
pr_err("%s: unexpected be_id %d\n", __func__, be_id);
@@ -1500,10 +1527,22 @@
for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MM_SIZE) {
if (fe_dai_map[i][session_type] != INVALID_SESSION) {
- adm_open(bedai->port_id, path_type,
+
+ channels = params_channels(bedai->hw_params);
+ if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
+ (channels > 2))
+ adm_multi_ch_copp_open(bedai->port_id,
+ path_type,
+ params_rate(bedai->hw_params),
+ channels,
+ DEFAULT_COPP_TOPOLOGY);
+ else
+ adm_open(bedai->port_id,
+ path_type,
params_rate(bedai->hw_params),
params_channels(bedai->hw_params),
DEFAULT_COPP_TOPOLOGY);
+
msm_pcm_routing_build_matrix(i,
fe_dai_map[i][session_type], path_type);
}
diff --git a/sound/soc/msm/msm7201.c b/sound/soc/msm/msm7201.c
index 9e041c7..6408cef 100644
--- a/sound/soc/msm/msm7201.c
+++ b/sound/soc/msm/msm7201.c
@@ -1,6 +1,6 @@
/* linux/sound/soc/msm/msm7201.c
*
- * Copyright (c) 2008-2009, 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2009, 2011, 2012 Code Aurora Forum. All rights reserved.
*
* All source code in this file is licensed under the following license except
* where indicated.
@@ -40,6 +40,8 @@
#include <mach/msm_rpcrouter.h>
static struct msm_rpc_endpoint *snd_ep;
+static uint32_t snd_mute_ear_mute;
+static uint32_t snd_mute_mic_mute;
struct msm_snd_rpc_ids {
unsigned long prog;
@@ -99,7 +101,7 @@
* The number of devices supported is 26 (0 to 25)
*/
uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 25;
+ uinfo->value.integer.max = 36;
return 0;
}
@@ -107,6 +109,8 @@
struct snd_ctl_elem_value *ucontrol)
{
ucontrol->value.integer.value[0] = (uint32_t)snd_rpc_ids.device;
+ ucontrol->value.integer.value[1] = snd_mute_ear_mute;
+ ucontrol->value.integer.value[2] = snd_mute_mic_mute;
return 0;
}
@@ -213,8 +217,11 @@
if (rc < 0) {
printk(KERN_ERR "%s: snd rpc call failed! rc = %d\n",
__func__, rc);
- } else
- printk(KERN_INFO "snd device connected \n");
+ } else {
+ 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];
+ }
return rc;
}
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 578f819..1ed73e2 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -787,8 +787,10 @@
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
+ pr_debug("%s channels->min %u channels->max %u ()\n", __func__,
+ channels->min, channels->max);
+
rate->min = rate->max = 48000;
- channels->min = channels->max = 2;
return 0;
}
@@ -936,7 +938,7 @@
.name = "MSM8960 Media2",
.stream_name = "MultiMedia2",
.cpu_dai_name = "MultiMedia2",
- .platform_name = "msm-pcm-dsp",
+ .platform_name = "msm-multi-ch-pcm-dsp",
.dynamic = 1,
.dsp_link = &fe_media,
.be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
@@ -1118,7 +1120,7 @@
{
.name = LPASS_BE_HDMI,
.stream_name = "HDMI Playback",
- .cpu_dai_name = "msm-dai-q6.8",
+ .cpu_dai_name = "msm-dai-q6-hdmi.8",
.platform_name = "msm-pcm-routing",
.codec_name = "msm-stub-codec.1",
.codec_dai_name = "msm-stub-rx",
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index 177e1d8..2710fbb 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -103,7 +103,8 @@
}
switch (data->opcode) {
- case ADM_CMDRSP_COPP_OPEN: {
+ case ADM_CMDRSP_COPP_OPEN:
+ case ADM_CMDRSP_MULTI_CHANNEL_COPP_OPEN: {
struct adm_copp_open_respond *open = data->payload;
if (open->copp_id == INVALID_COPP_ID) {
pr_err("%s: invalid coppid rxed %d\n",
@@ -360,6 +361,133 @@
return ret;
}
+
+int adm_multi_ch_copp_open(int port_id, int path, int rate, int channel_mode,
+ int topology)
+{
+ struct adm_multi_ch_copp_open_command open;
+ int ret = 0;
+ int index;
+
+ pr_debug("%s: port %d path:%d rate:%d channel :%d\n", __func__,
+ port_id, path, rate, channel_mode);
+
+ port_id = afe_convert_virtual_to_portid(port_id);
+
+ if (afe_validate_port(port_id) < 0) {
+ pr_err("%s port idi[%d] is invalid\n", __func__, port_id);
+ return -ENODEV;
+ }
+
+ index = afe_get_port_index(port_id);
+ pr_debug("%s: Port ID %d, index %d\n", __func__, port_id, index);
+
+ if (this_adm.apr == NULL) {
+ this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
+ 0xFFFFFFFF, &this_adm);
+ if (this_adm.apr == NULL) {
+ pr_err("%s: Unable to register ADM\n", __func__);
+ ret = -ENODEV;
+ return ret;
+ }
+ rtac_set_adm_handle(this_adm.apr);
+ }
+
+ /* Create a COPP if port id are not enabled */
+ if (atomic_read(&this_adm.copp_cnt[index]) == 0) {
+
+ open.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+
+ open.hdr.pkt_size =
+ sizeof(struct adm_multi_ch_copp_open_command);
+ open.hdr.opcode = ADM_CMD_MULTI_CHANNEL_COPP_OPEN;
+ memset(open.dev_channel_mapping, 0, 8);
+
+ if (channel_mode == 1) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FC;
+ } else if (channel_mode == 2) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ } else if (channel_mode == 6) {
+ open.dev_channel_mapping[0] = PCM_CHANNEL_FL;
+ open.dev_channel_mapping[1] = PCM_CHANNEL_FR;
+ open.dev_channel_mapping[2] = PCM_CHANNEL_LFE;
+ open.dev_channel_mapping[3] = PCM_CHANNEL_FC;
+ open.dev_channel_mapping[4] = PCM_CHANNEL_LB;
+ open.dev_channel_mapping[5] = PCM_CHANNEL_RB;
+ } else {
+ pr_err("%s invalid num_chan %d\n", __func__,
+ channel_mode);
+ return -EINVAL;
+ }
+
+
+ open.hdr.src_svc = APR_SVC_ADM;
+ open.hdr.src_domain = APR_DOMAIN_APPS;
+ open.hdr.src_port = port_id;
+ open.hdr.dest_svc = APR_SVC_ADM;
+ open.hdr.dest_domain = APR_DOMAIN_ADSP;
+ open.hdr.dest_port = port_id;
+ open.hdr.token = port_id;
+
+ open.mode = path;
+ open.endpoint_id1 = port_id;
+ open.endpoint_id2 = 0xFFFF;
+
+ /* convert path to acdb path */
+ if (path == ADM_PATH_PLAYBACK)
+ open.topology_id = get_adm_rx_topology();
+ else {
+ open.topology_id = get_adm_tx_topology();
+ if ((open.topology_id ==
+ VPM_TX_SM_ECNS_COPP_TOPOLOGY) ||
+ (open.topology_id ==
+ VPM_TX_DM_FLUENCE_COPP_TOPOLOGY) ||
+ (open.topology_id ==
+ VPM_TX_QMIC_FLUENCE_COPP_TOPOLOGY))
+ rate = 16000;
+ }
+
+ if (open.topology_id == 0)
+ open.topology_id = topology;
+
+ open.channel_config = channel_mode & 0x00FF;
+ open.rate = rate;
+
+ pr_debug("%s: channel_config=%d port_id=%d rate=%d"
+ " topology_id=0x%X\n", __func__, open.channel_config,
+ open.endpoint_id1, open.rate,
+ open.topology_id);
+
+ atomic_set(&this_adm.copp_stat[index], 0);
+
+ ret = apr_send_pkt(this_adm.apr, (uint32_t *)&open);
+ if (ret < 0) {
+ pr_err("%s:ADM enable for port %d failed\n",
+ __func__, port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ /* Wait for the callback with copp id */
+ ret = wait_event_timeout(this_adm.wait,
+ atomic_read(&this_adm.copp_stat[index]),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s ADM open failed for port %d\n", __func__,
+ port_id);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ }
+ atomic_inc(&this_adm.copp_cnt[index]);
+ return 0;
+
+fail_cmd:
+
+ return ret;
+}
+
int adm_matrix_map(int session_id, int path, int num_copps,
unsigned int *port_id, int copp_id)
{
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index 302ef57..ef01fb3 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -77,6 +77,7 @@
if (data->opcode == APR_BASIC_RSP_RESULT) {
switch (payload[0]) {
case AFE_PORT_AUDIO_IF_CONFIG:
+ case AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG:
case AFE_PORT_CMD_STOP:
case AFE_PORT_CMD_START:
case AFE_PORT_CMD_LOOPBACK:
@@ -280,7 +281,7 @@
ret_size = SIZEOF_CFG_CMD(afe_port_mi2s_cfg);
break;
case HDMI_RX:
- ret_size = SIZEOF_CFG_CMD(afe_port_hdmi_cfg);
+ ret_size = SIZEOF_CFG_CMD(afe_port_hdmi_multi_ch_cfg);
break;
case SLIMBUS_0_RX:
case SLIMBUS_0_TX:
@@ -400,13 +401,25 @@
ret = -ENODEV;
return ret;
}
- config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+
+ if (port_id == HDMI_RX) {
+ config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
- config.hdr.src_port = 0;
- config.hdr.dest_port = 0;
- config.hdr.token = 0;
- config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
+ config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
+ config.hdr.src_port = 0;
+ config.hdr.dest_port = 0;
+ config.hdr.token = 0;
+ config.hdr.opcode = AFE_PORT_MULTI_CHAN_HDMI_AUDIO_IF_CONFIG;
+ } else {
+
+ config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ config.hdr.pkt_size = afe_sizeof_cfg_cmd(port_id);
+ config.hdr.src_port = 0;
+ config.hdr.dest_port = 0;
+ config.hdr.token = 0;
+ config.hdr.opcode = AFE_PORT_AUDIO_IF_CONFIG;
+ }
if (afe_validate_port(port_id) < 0) {
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index 62168d2..dc49f12 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
* Author: Brian Swetland <swetland@google.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -1193,6 +1193,9 @@
case FORMAT_LINEAR_PCM:
open.format = LINEAR_PCM;
break;
+ case FORMAT_MULTI_CHANNEL_LINEAR_PCM:
+ open.format = MULTI_CHANNEL_PCM;
+ break;
case FORMAT_MPEG4_AAC:
open.format = MPEG4_AAC;
break;
@@ -1761,6 +1764,66 @@
return -EINVAL;
}
+int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac,
+ uint32_t rate, uint32_t channels)
+{
+ struct asm_stream_media_format_update fmt;
+ u8 *channel_mapping;
+ int rc = 0;
+
+ pr_debug("%s:session[%d]rate[%d]ch[%d]\n", __func__, ac->session, rate,
+ channels);
+
+ q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE);
+
+ fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FORMAT_UPDATE;
+
+ fmt.format = MULTI_CHANNEL_PCM;
+ fmt.cfg_size = sizeof(struct asm_multi_channel_pcm_fmt_blk);
+ fmt.write_cfg.multi_ch_pcm_cfg.num_channels = channels;
+ fmt.write_cfg.multi_ch_pcm_cfg.bits_per_sample = 16;
+ fmt.write_cfg.multi_ch_pcm_cfg.sample_rate = rate;
+ fmt.write_cfg.multi_ch_pcm_cfg.is_signed = 1;
+ fmt.write_cfg.multi_ch_pcm_cfg.is_interleaved = 1;
+ channel_mapping =
+ fmt.write_cfg.multi_ch_pcm_cfg.channel_mapping;
+
+ memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL);
+
+ if (channels == 1) {
+ channel_mapping[0] = PCM_CHANNEL_FL;
+ } else if (channels == 2) {
+ channel_mapping[0] = PCM_CHANNEL_FL;
+ channel_mapping[1] = PCM_CHANNEL_FR;
+ } else if (channels == 6) {
+ channel_mapping[0] = PCM_CHANNEL_FC;
+ channel_mapping[1] = PCM_CHANNEL_FL;
+ channel_mapping[2] = PCM_CHANNEL_FR;
+ channel_mapping[3] = PCM_CHANNEL_LB;
+ channel_mapping[4] = PCM_CHANNEL_RB;
+ channel_mapping[5] = PCM_CHANNEL_LFE;
+ } else {
+ pr_err("%s: ERROR.unsupported num_ch = %u\n", __func__,
+ channels);
+ return -EINVAL;
+ }
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt);
+ if (rc < 0) {
+ pr_err("%s:Comamnd open failed\n", __func__);
+ goto fail_cmd;
+ }
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) == 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s:timeout. waited for FORMAT_UPDATE\n", __func__);
+ goto fail_cmd;
+ }
+ return 0;
+fail_cmd:
+ return -EINVAL;
+}
+
int q6asm_media_format_block_aac(struct audio_client *ac,
struct asm_aac_cfg *cfg)
{