Merge "usb: mdm_bridge: Decrement PM-usage counter in completion handler" into msm-3.0
diff --git a/arch/arm/boot/dts/msmcopper.dts b/arch/arm/boot/dts/msmcopper.dts
index b00237a..fea1c52 100644
--- a/arch/arm/boot/dts/msmcopper.dts
+++ b/arch/arm/boot/dts/msmcopper.dts
@@ -10,26 +10,26 @@
intc: interrupt-controller@F9000000 {
compatible = "qcom,msm-qgic2";
interrupt-controller;
- #interrupt-cells = <1>;
+ #interrupt-cells = <3>;
reg = <0xF9000000 0x1000>,
<0xF9002000 0x1000>;
};
timer {
compatible = "qcom,msm-qtimer";
- interrupts = <18>;
+ interrupts = <1 2 0>;
};
serial@F991F000 {
compatible = "qcom,msm-lsuart-v14";
reg = <0xF991F000 0x1000>;
- interrupts = <109>;
+ interrupts = <0 109 0>;
};
usb@F9A55000 {
compatible = "qcom,hsusb-otg";
reg = <0xF9A55000 0x400>;
- interrupts = <134>;
+ interrupts = <0 134 0>;
qcom,hsusb-otg-phy-type = <2>;
qcom,hsusb-otg-mode = <1>;
@@ -40,7 +40,7 @@
cell-index = <1>;
compatible = "qcom,msm-sdcc";
reg = <0xF980B000 0x1000>;
- interrupts = <123>;
+ interrupts = <0 123 0>;
qcom,sdcc-clk-rates = <400000 24000000 48000000>;
qcom,sdcc-sup-voltages = <3300 3300>;
@@ -53,7 +53,7 @@
cell-index = <3>;
compatible = "qcom,msm-sdcc";
reg = <0xF984B000 0x1000>;
- interrupts = <127>;
+ interrupts = <0 127 0>;
qcom,sdcc-clk-rates = <400000 24000000 48000000>;
qcom,sdcc-sup-voltages = <3300 3300>;
@@ -65,7 +65,7 @@
compatible = "qcom,msm_sps";
reg = <0xF9984000 0x15000>,
<0xF9999000 0xB000>;
- interrupts = <94>;
+ interrupts = <0 94 0>;
qcom,bam-dma-res-pipes = <6>;
};
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index d69305c..3421fa1 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -1,6 +1,7 @@
CONFIG_EXPERIMENTAL=y
# CONFIG_LOCALVERSION_AUTO is not set
CONFIG_SYSVIPC=y
+CONFIG_SPARSE_IRQ=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_CGROUPS=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index bd92fe3..5f9bd89 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -49,6 +49,9 @@
CONFIG_MACH_MSM8627_MTP=y
CONFIG_MACH_APQ8064_SIM=y
CONFIG_MACH_APQ8064_RUMI3=y
+CONFIG_MACH_APQ8064_CDP=y
+CONFIG_MACH_APQ8064_MTP=y
+CONFIG_MACH_APQ8064_LIQUID=y
# CONFIG_MSM_STACKED_MEMORY is not set
CONFIG_KERNEL_PMEM_EBI_REGION=y
# CONFIG_MSM_FIQ_SUPPORT is not set
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index b44f46f..bd6df88 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -21,7 +21,7 @@
const char **dt_compat; /* array of device tree
* 'compatible' strings */
- unsigned int nr_irqs; /* number of IRQs */
+ int nr_irqs; /* number of IRQs */
unsigned int video_start; /* start of video RAM */
unsigned int video_end; /* end of video RAM */
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 4468153..7561081 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -134,8 +134,18 @@
#ifdef CONFIG_SPARSE_IRQ
int __init arch_probe_nr_irqs(void)
{
- nr_irqs = machine_desc->nr_irqs ? machine_desc->nr_irqs : NR_IRQS;
- return nr_irqs;
+ /*
+ * machine_desc->nr_irqs < 0 is a special case that
+ * specifies not to preallocate any irq_descs.
+ */
+ if (machine_desc->nr_irqs < 0) {
+ nr_irqs = 0;
+ return nr_irqs;
+ } else {
+ nr_irqs = machine_desc->nr_irqs ?
+ machine_desc->nr_irqs : NR_IRQS;
+ return nr_irqs;
+ }
}
#endif
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 9df90cd..f77e883 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -198,7 +198,6 @@
config ARCH_APQ8064
bool "APQ8064"
select ARCH_MSM_KRAITMP
- select MACH_APQ8064_SIM if !MACH_APQ8064_RUMI3
select MSM_V2_TLMM
select ARM_GIC
select CPU_V7
@@ -675,6 +674,24 @@
help
Support for the Qualcomm APQ8064 RUMI3 emulator.
+config MACH_APQ8064_CDP
+ depends on ARCH_APQ8064
+ bool "APQ8064 CDP"
+ help
+ Support for the Qualcomm APQ8064 CDP device.
+
+config MACH_APQ8064_MTP
+ depends on ARCH_APQ8064
+ bool "APQ8064 MTP"
+ help
+ Support for the Qualcomm APQ8064 MTP device.
+
+config MACH_APQ8064_LIQUID
+ depends on ARCH_APQ8064
+ bool "APQ8064 LIQUID"
+ help
+ Support for the Qualcomm APQ8064 LIQUID device.
+
config MACH_FSM9XXX_SURF
depends on ARCH_FSM9XXX
depends on !MSM_STACKED_MEMORY
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 0e4c756..d001282 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -63,6 +63,7 @@
static uint32_t bam_dmux_write_cpy_cnt;
static uint32_t bam_dmux_write_cpy_bytes;
static uint32_t bam_dmux_tx_sps_failure_cnt;
+static uint32_t bam_dmux_tx_stall_cnt;
#define DBG(x...) do { \
if (msm_bam_dmux_debug_enable) \
@@ -96,12 +97,17 @@
bam_dmux_tx_sps_failure_cnt++; \
} while (0)
+#define DBG_INC_TX_STALL_CNT() do { \
+ bam_dmux_tx_stall_cnt++; \
+} while (0)
+
#else
#define DBG(x...) do { } while (0)
#define DBG_INC_READ_CNT(x...) do { } while (0)
#define DBG_INC_WRITE_CNT(x...) do { } while (0)
#define DBG_INC_WRITE_CPY(x...) do { } while (0)
#define DBG_INC_TX_SPS_FAILURE_CNT() do { } while (0)
+#define DBG_INC_TX_STALL_CNT() do { } while (0)
#endif
struct bam_ch_info {
@@ -551,16 +557,16 @@
INIT_WORK(&pkt->work, bam_mux_write_done);
spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
list_add_tail(&pkt->list_node, &bam_tx_pool);
- spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
rc = sps_transfer_one(bam_tx_pipe, dma_address, len,
pkt, SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
if (rc) {
DBG("%s sps_transfer_one failed rc=%d\n", __func__, rc);
- spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
list_del(&pkt->list_node);
DBG_INC_TX_SPS_FAILURE_CNT();
spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
kfree(pkt);
+ } else {
+ spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
}
ul_packet_written = 1;
@@ -718,12 +724,10 @@
INIT_WORK(&pkt->work, bam_mux_write_done);
spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
list_add_tail(&pkt->list_node, &bam_tx_pool);
- spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
rc = sps_transfer_one(bam_tx_pipe, dma_address, skb->len,
pkt, SPS_IOVEC_FLAG_INT | SPS_IOVEC_FLAG_EOT);
if (rc) {
DBG("%s sps_transfer_one failed rc=%d\n", __func__, rc);
- spin_lock_irqsave(&bam_tx_pool_spinlock, flags);
list_del(&pkt->list_node);
DBG_INC_TX_SPS_FAILURE_CNT();
spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
@@ -731,6 +735,7 @@
if (new_skb)
dev_kfree_skb_any(new_skb);
} else {
+ spin_unlock_irqrestore(&bam_tx_pool_spinlock, flags);
spin_lock_irqsave(&bam_ch[id].lock, flags);
bam_ch[id].num_tx_pkts++;
spin_unlock_irqrestore(&bam_ch[id].lock, flags);
@@ -1124,10 +1129,12 @@
i += scnprintf(buf + i, max - i,
"skb copy cnt: %u\n"
"skb copy bytes: %u\n"
- "sps tx failures: %u\n",
+ "sps tx failures: %u\n"
+ "sps tx stalls: %u\n",
bam_dmux_write_cpy_cnt,
bam_dmux_write_cpy_bytes,
- bam_dmux_tx_sps_failure_cnt
+ bam_dmux_tx_sps_failure_cnt,
+ bam_dmux_tx_stall_cnt
);
return i;
@@ -1352,6 +1359,21 @@
return;
}
if (bam_is_connected) {
+ if (!ul_packet_written) {
+ spin_lock(&bam_tx_pool_spinlock);
+ if (!list_empty(&bam_tx_pool)) {
+ struct tx_pkt_info *info;
+
+ info = list_first_entry(&bam_tx_pool,
+ struct tx_pkt_info, list_node);
+ DMUX_LOG_KERR("%s: UL delayed ts=%u.%09lu\n",
+ __func__, info->ts_sec, info->ts_nsec);
+ DBG_INC_TX_STALL_CNT();
+ ul_packet_written = 1;
+ }
+ spin_unlock(&bam_tx_pool_spinlock);
+ }
+
if (ul_packet_written) {
bam_dmux_log("%s: packet written\n", __func__);
ul_packet_written = 0;
@@ -1639,6 +1661,7 @@
int ret;
void *a2_virt_addr;
int i;
+ int skip_iounmap = 0;
vote_dfab();
/* init BAM */
@@ -1786,7 +1809,15 @@
sps_free_endpoint(bam_tx_pipe);
tx_mem_failed:
sps_deregister_bam_device(h);
+ /*
+ * sps_deregister_bam_device() calls iounmap. calling iounmap on the
+ * same handle below will cause a crash, so skip it if we've freed
+ * the handle here.
+ */
+ skip_iounmap = 1;
register_bam_failed:
+ if (!skip_iounmap)
+ iounmap(a2_virt_addr);
ioremap_failed:
/*destroy_workqueue(bam_mux_workqueue);*/
return ret;
@@ -1825,6 +1856,7 @@
return 0;
register_bam_failed:
+ iounmap(a2_virt_addr);
ioremap_failed:
return ret;
}
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 0ba7434..a582260 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -653,6 +653,11 @@
&msm_device_sps_apq8064,
};
+static struct platform_device *cdp_devices[] __initdata = {
+ &apq8064_device_uart_gsbi1,
+ &msm_device_sps_apq8064,
+};
+
static struct msm_spi_platform_data apq8064_qup_spi_gsbi5_pdata = {
.max_clock_speed = 24000000,
};
@@ -759,6 +764,14 @@
spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
}
+static void __init apq8064_cdp_init(void)
+{
+ apq8064_common_init();
+ ethernet_init();
+ platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
+ spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info));
+}
+
MACHINE_START(APQ8064_SIM, "QCT APQ8064 SIMULATOR")
.map_io = apq8064_map_io,
.reserve = apq8064_reserve,
@@ -777,3 +790,30 @@
.init_machine = apq8064_rumi3_init,
MACHINE_END
+MACHINE_START(APQ8064_CDP, "QCT APQ8064 CDP")
+ .map_io = apq8064_map_io,
+ .reserve = apq8064_reserve,
+ .init_irq = apq8064_init_irq,
+ .handle_irq = gic_handle_irq,
+ .timer = &msm_timer,
+ .init_machine = apq8064_cdp_init,
+MACHINE_END
+
+MACHINE_START(APQ8064_MTP, "QCT APQ8064 MTP")
+ .map_io = apq8064_map_io,
+ .reserve = apq8064_reserve,
+ .init_irq = apq8064_init_irq,
+ .handle_irq = gic_handle_irq,
+ .timer = &msm_timer,
+ .init_machine = apq8064_cdp_init,
+MACHINE_END
+
+MACHINE_START(APQ8064_LIQUID, "QCT APQ8064 LIQUID")
+ .map_io = apq8064_map_io,
+ .reserve = apq8064_reserve,
+ .init_irq = apq8064_init_irq,
+ .handle_irq = gic_handle_irq,
+ .timer = &msm_timer,
+ .init_machine = apq8064_cdp_init,
+MACHINE_END
+
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 598e18d..f7ff370 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -480,8 +480,8 @@
if (high - low <= bank_size)
return;
- msm8960_reserve_info.low_unstable_address = high -
- MIN_MEMORY_BLOCK_SIZE;
+ msm8960_reserve_info.low_unstable_address = mb->start -
+ MIN_MEMORY_BLOCK_SIZE + mb->size;
msm8960_reserve_info.max_unstable_size = MIN_MEMORY_BLOCK_SIZE;
msm8960_reserve_info.bank_size = bank_size;
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index f26187e..5f31f88 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -18,6 +18,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
+#include <linux/of_irq.h>
#include <asm/mach/map.h>
#include <asm/hardware/gic.h>
#include <mach/board.h>
@@ -43,24 +44,20 @@
{
}
-static struct of_device_id msm_copper_gic_match[] __initdata = {
- { .compatible = "qcom,msm-qgic2", },
+static struct of_device_id irq_match[] __initdata = {
+ { .compatible = "qcom,msm-qgic2", .data = gic_of_init, },
{}
};
void __init msm_copper_init_irq(void)
{
- gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
- (void *)MSM_QGIC_CPU_BASE);
-
/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
writel_relaxed(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
writel_relaxed(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
mb();
- irq_domain_generate_simple(msm_copper_gic_match,
- COPPER_QGIC_DIST_PHYS, GIC_SPI_START);
+ of_irq_init(irq_match);
}
static struct clk_lookup msm_clocks_dummy[] = {
diff --git a/arch/arm/mach-msm/board-dt.c b/arch/arm/mach-msm/board-dt.c
index 19f54cf..6c5f74a 100644
--- a/arch/arm/mach-msm/board-dt.c
+++ b/arch/arm/mach-msm/board-dt.c
@@ -28,7 +28,7 @@
{
struct device_node *node;
struct resource res;
- struct of_irq oirq;
+ int rc;
node = of_find_compatible_node(NULL, NULL, "qcom,msm-qtimer");
if (!node) {
@@ -36,13 +36,12 @@
return;
}
- if (of_irq_map_one(node, 0, &oirq)) {
+ rc = of_irq_to_resource(node, 0, &res);
+ if (rc < 0)
pr_err("interrupt not specified in timer node\n");
- } else {
- res.start = res.end = oirq.specifier[0];
- res.flags = IORESOURCE_IRQ;
+ else
arch_timer_register(&res, 1);
- }
+
of_node_put(node);
}
@@ -98,4 +97,5 @@
.handle_irq = gic_handle_irq,
.timer = &msm_dt_timer,
.dt_compat = msm_dt_match,
+ .nr_irqs = -1,
MACHINE_END
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 4fa3e92..8fdcbdd 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -2065,7 +2065,7 @@
.src = MSM_BUS_MASTER_GRAPHICS_3D,
.dst = MSM_BUS_SLAVE_EBI_CH0,
.ab = 0,
- .ib = KGSL_CONVERT_TO_MBPS(1200),
+ .ib = KGSL_CONVERT_TO_MBPS(1000),
},
};
@@ -2139,7 +2139,7 @@
.src = MSM_BUS_MASTER_GRAPHICS_2D_CORE0,
.dst = MSM_BUS_SLAVE_EBI_CH0,
.ab = 0,
- .ib = KGSL_CONVERT_TO_MBPS(1200),
+ .ib = KGSL_CONVERT_TO_MBPS(1000),
},
};
@@ -2187,7 +2187,7 @@
.src = MSM_BUS_MASTER_GRAPHICS_2D_CORE1,
.dst = MSM_BUS_SLAVE_EBI_CH0,
.ab = 0,
- .ib = KGSL_CONVERT_TO_MBPS(1200),
+ .ib = KGSL_CONVERT_TO_MBPS(1000),
},
};
diff --git a/arch/arm/mach-msm/include/mach/irqs-copper.h b/arch/arm/mach-msm/include/mach/irqs-copper.h
index 24da0a4..821eaeb 100644
--- a/arch/arm/mach-msm/include/mach/irqs-copper.h
+++ b/arch/arm/mach-msm/include/mach/irqs-copper.h
@@ -34,7 +34,7 @@
#define TLMM_MSM_SUMMARY_IRQ (GIC_SPI_START + 16)
#define SPS_BAM_DMA_IRQ (GIC_SPI_START + 105)
-#define NR_MSM_IRQS 256
+#define NR_MSM_IRQS 1020 /* Should be 256 - but higher due to bug in sim */
#define NR_GPIO_IRQS 156
#define NR_BOARD_IRQS 100
#define NR_TLMM_MSM_DIR_CONN_IRQ 8
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
index 8175738..feabe04 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_arb.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
@@ -305,7 +305,13 @@
*info->link_info.sel_bw += add_bw;
info->pnode[index].sel_bw = &info->pnode[index].bw[ctx];
- info->pnode[index].sel_clk = &info->pnode[index].clk[ctx];
+
+ /**
+ * To select the right clock, AND the context with
+ * client active flag.
+ */
+ info->pnode[index].sel_clk = &info->pnode[index].clk[ctx &
+ cl_active_flag];
*info->pnode[index].sel_bw += add_bw;
info->link_info.num_tiers = info->node_info->num_tiers;
@@ -345,7 +351,8 @@
*hop->link_info.sel_bw += add_bw;
hop->pnode[index].sel_bw = &hop->pnode[index].bw[ctx];
- hop->pnode[index].sel_clk = &hop->pnode[index].clk[ctx];
+ hop->pnode[index].sel_clk = &hop->pnode[index].clk[ctx &
+ cl_active_flag];
if (!hop->node_info->buswidth) {
MSM_BUS_WARN("No bus width found. Using default\n");
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index b06e5dd..3b178b5 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.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
@@ -216,6 +216,13 @@
struct msm_bus_fabric *fabric = to_msm_bus_fabric(fabdev);
struct nodeclk *nodeclk;
+ /**
+ * Integration for clock rates is not required if context is not
+ * same as client's active-only flag
+ */
+ if (ctx != cl_active_flag)
+ goto skip_set_clks;
+
/* Maximum for this gateway */
for (i = 0; i <= slave->num_pnodes; i++) {
if (i == index && (req_clk_hz < curr_clk_hz))
@@ -272,13 +279,7 @@
if (clk_flag) {
nodeclk = &fabric->info.nodeclk[ctx];
- /**
- * Send a clock request only when the client requests in active
- * context and the ACTIVE_CTX clock rate is selected OR the
- * client request is in normal context and normal clock rate
- * is selected.
- */
- if (nodeclk->clk && (!((ctx == ACTIVE_CTX) ^ cl_active_flag))) {
+ if (nodeclk->clk) {
MSM_BUS_DBG("clks: id: %d set-clk: %lu bwsum_hz:%lu\n",
fabric->fabdev.id, *pclk, bwsum_hz);
if (nodeclk->rate != *pclk) {
@@ -289,7 +290,7 @@
}
} else {
nodeclk = &slave->nodeclk[ctx];
- if (nodeclk->clk && (!((ctx == ACTIVE_CTX) ^ cl_active_flag))) {
+ if (nodeclk->clk) {
rate = *pclk;
MSM_BUS_DBG("AXI_clks: id: %d set-clk: %lu "
"bwsum_hz: %lu\n" , slave->node_info->priv_id, rate,
@@ -299,8 +300,7 @@
nodeclk->rate = rate;
}
}
- if (!status && slave->memclk.clk &&
- (!((ctx == ACTIVE_CTX) ^ cl_active_flag))) {
+ if (!status && slave->memclk.clk) {
rate = *slave->link_info.sel_clk;
if (slave->memclk.rate != rate) {
slave->memclk.rate = rate;
diff --git a/arch/arm/mach-msm/smd_tty.c b/arch/arm/mach-msm/smd_tty.c
index c8248a7..4248be4 100644
--- a/arch/arm/mach-msm/smd_tty.c
+++ b/arch/arm/mach-msm/smd_tty.c
@@ -1,7 +1,7 @@
/* arch/arm/mach-msm/smd_tty.c
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-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
@@ -552,8 +552,11 @@
legacy_ds |= cpu_is_msm7x01() || cpu_is_msm7x25();
legacy_ds |= cpu_is_msm7x27() || cpu_is_msm7x30();
legacy_ds |= cpu_is_qsd8x50() || cpu_is_msm8x55();
+ /*
+ * use legacy mode for 8660 Standalone (subtype 0)
+ */
legacy_ds |= cpu_is_msm8x60() &&
- (socinfo_get_platform_subtype() == 0x1);
+ (socinfo_get_platform_subtype() == 0x0);
if (!legacy_ds)
continue;
diff --git a/drivers/bluetooth/hci_smd.c b/drivers/bluetooth/hci_smd.c
index 101697f..4e78152 100644
--- a/drivers/bluetooth/hci_smd.c
+++ b/drivers/bluetooth/hci_smd.c
@@ -2,7 +2,7 @@
* HCI_SMD (HCI Shared Memory Driver) is Qualcomm's Shared memory driver
* for the BT HCI protocol.
*
- * Copyright (c) 2000-2001, 2011 Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2000-2001, 2011-2012 Code Aurora Forum. All rights reserved.
* Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
* Copyright (C) 2004-2006 Marcel Holtmann <marcel@holtmann.org>
*
@@ -51,8 +51,7 @@
struct wake_lock wake_lock_tx;
struct wake_lock wake_lock_rx;
struct timer_list rx_q_timer;
- struct tasklet_struct hci_event_task;
- struct tasklet_struct hci_data_task;
+ struct tasklet_struct rx_task;
};
static struct hci_smd_data hs;
@@ -129,111 +128,95 @@
kfree(hdev->driver_data);
}
-static void hci_smd_recv_data(unsigned long arg)
+static void hci_smd_recv_data(void)
{
int len = 0;
int rc = 0;
struct sk_buff *skb = NULL;
- unsigned char *buf = NULL;
struct hci_smd_data *hsmd = &hs;
wake_lock(&hs.wake_lock_rx);
len = smd_read_avail(hsmd->data_channel);
if (len > HCI_MAX_FRAME_SIZE) {
- BT_ERR("Frame larger than the allowed size");
+ BT_ERR("Frame larger than the allowed size, flushing frame");
+ smd_read(hsmd->data_channel, NULL, len);
goto out_data;
}
- while (len > 0) {
- skb = bt_skb_alloc(len, GFP_ATOMIC);
- if (!skb) {
- BT_ERR("Error in allocating socket buffer");
- goto out_data;
- }
- buf = kmalloc(len, GFP_ATOMIC);
- if (!buf) {
- BT_ERR("Error in allocating buffer");
- rc = -ENOMEM;
- goto out_data;
- }
+ if (len <= 0)
+ goto out_data;
- rc = smd_read(hsmd->data_channel, (void *)buf, len);
- if (rc < len) {
- BT_ERR("Error in reading from the channel");
- goto out_data;
- }
-
- memcpy(skb_put(skb, len), buf, len);
- skb->dev = (void *)hsmd->hdev;
- bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
-
- skb_orphan(skb);
-
- rc = hci_recv_frame(skb);
- if (rc < 0) {
- BT_ERR("Error in passing the packet to HCI Layer");
- /*
- * skb is getting freed in hci_recv_frame, making it
- * to null to avoid multiple access
- */
- skb = NULL;
- goto out_data;
- }
-
- kfree(buf);
- buf = NULL;
- len = smd_read_avail(hsmd->data_channel);
- /*
- * Start the timer to monitor whether the Rx queue is
- * empty for releasing the Rx wake lock
- */
- BT_DBG("Rx Timer is starting");
- mod_timer(&hsmd->rx_q_timer,
- jiffies + msecs_to_jiffies(RX_Q_MONITOR));
+ skb = bt_skb_alloc(len, GFP_ATOMIC);
+ if (!skb) {
+ BT_ERR("Error in allocating socket buffer");
+ smd_read(hsmd->data_channel, NULL, len);
+ goto out_data;
}
+
+ rc = smd_read(hsmd->data_channel, skb_put(skb, len), len);
+ if (rc < len) {
+ BT_ERR("Error in reading from the channel");
+ goto out_data;
+ }
+
+ skb->dev = (void *)hsmd->hdev;
+ bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
+ skb_orphan(skb);
+
+ rc = hci_recv_frame(skb);
+ if (rc < 0) {
+ BT_ERR("Error in passing the packet to HCI Layer");
+ /*
+ * skb is getting freed in hci_recv_frame, making it
+ * to null to avoid multiple access
+ */
+ skb = NULL;
+ goto out_data;
+ }
+
+ /*
+ * Start the timer to monitor whether the Rx queue is
+ * empty for releasing the Rx wake lock
+ */
+ BT_DBG("Rx Timer is starting");
+ mod_timer(&hsmd->rx_q_timer,
+ jiffies + msecs_to_jiffies(RX_Q_MONITOR));
+
out_data:
release_lock();
- if (rc) {
- if (skb)
- kfree_skb(skb);
- kfree(buf);
- }
+ if (rc)
+ kfree_skb(skb);
}
-static void hci_smd_recv_event(unsigned long arg)
+static void hci_smd_recv_event(void)
{
int len = 0;
int rc = 0;
struct sk_buff *skb = NULL;
- unsigned char *buf = NULL;
struct hci_smd_data *hsmd = &hs;
wake_lock(&hs.wake_lock_rx);
len = smd_read_avail(hsmd->event_channel);
if (len > HCI_MAX_FRAME_SIZE) {
- BT_ERR("Frame larger than the allowed size");
+ BT_ERR("Frame larger than the allowed size, flushing frame");
+ rc = smd_read(hsmd->event_channel, NULL, len);
goto out_event;
}
while (len > 0) {
skb = bt_skb_alloc(len, GFP_ATOMIC);
if (!skb) {
- BT_ERR("Error in allocating socket buffer");
+ BT_ERR("Error in allocating socket buffer");
+ smd_read(hsmd->event_channel, NULL, len);
goto out_event;
}
- buf = kmalloc(len, GFP_ATOMIC);
- if (!buf) {
- BT_ERR("Error in allocating buffer");
- rc = -ENOMEM;
- goto out_event;
- }
- rc = smd_read(hsmd->event_channel, (void *)buf, len);
+
+ rc = smd_read(hsmd->event_channel, skb_put(skb, len), len);
if (rc < len) {
BT_ERR("Error in reading from the event channel");
goto out_event;
}
- memcpy(skb_put(skb, len), buf, len);
skb->dev = (void *)hsmd->hdev;
bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
@@ -250,8 +233,6 @@
goto out_event;
}
- kfree(buf);
- buf = NULL;
len = smd_read_avail(hsmd->event_channel);
/*
* Start the timer to monitor whether the Rx queue is
@@ -263,11 +244,8 @@
}
out_event:
release_lock();
- if (rc) {
- if (skb)
- kfree_skb(skb);
- kfree(buf);
- }
+ if (rc)
+ kfree_skb(skb);
}
static int hci_smd_send_frame(struct sk_buff *skb)
@@ -314,6 +292,16 @@
return ret;
}
+static void hci_smd_rx(unsigned long arg)
+{
+ struct hci_smd_data *hsmd = &hs;
+
+ while ((smd_read_avail(hsmd->event_channel) > 0) ||
+ (smd_read_avail(hsmd->data_channel) > 0)) {
+ hci_smd_recv_event();
+ hci_smd_recv_data();
+ }
+}
static void hci_smd_notify_event(void *data, unsigned int event)
{
@@ -330,7 +318,7 @@
case SMD_EVENT_DATA:
len = smd_read_avail(hsmd->event_channel);
if (len > 0)
- tasklet_hi_schedule(&hs.hci_event_task);
+ tasklet_hi_schedule(&hs.rx_task);
else if (len < 0)
BT_ERR("Failed to read event from smd %d", len);
@@ -355,7 +343,7 @@
int len = 0;
if (!hdev) {
- BT_ERR("HCI device (hdev=NULL)");
+ BT_ERR("Frame for unknown HCI device (hdev=NULL)");
return;
}
@@ -363,7 +351,7 @@
case SMD_EVENT_DATA:
len = smd_read_avail(hsmd->data_channel);
if (len > 0)
- tasklet_hi_schedule(&hs.hci_data_task);
+ tasklet_hi_schedule(&hs.rx_task);
else if (len < 0)
BT_ERR("Failed to read data from smd %d", len);
break;
@@ -402,10 +390,9 @@
hdev->destruct = hci_smd_destruct;
hdev->owner = THIS_MODULE;
- tasklet_init(&hsmd->hci_event_task,
- hci_smd_recv_event, (unsigned long) hsmd);
- tasklet_init(&hsmd->hci_data_task,
- hci_smd_recv_data, (unsigned long) hsmd);
+
+ tasklet_init(&hsmd->rx_task,
+ hci_smd_rx, (unsigned long) hsmd);
/*
* Setup the timer to monitor whether the Rx queue is empty,
* to control the wake lock release
@@ -445,6 +432,8 @@
static void hci_smd_deregister_dev(struct hci_smd_data *hsmd)
{
+ tasklet_kill(&hs.rx_task);
+
if (hsmd->hdev) {
if (hci_unregister_dev(hsmd->hdev) < 0)
BT_ERR("Can't unregister HCI device %s",
@@ -468,9 +457,6 @@
hs.rx_q_timer.function = NULL;
hs.rx_q_timer.data = 0;
}
-
- tasklet_kill(&hs.hci_event_task);
- tasklet_kill(&hs.hci_data_task);
}
static int hcismd_set_enable(const char *val, struct kernel_param *kp)
diff --git a/drivers/mfd/pm8xxx-misc.c b/drivers/mfd/pm8xxx-misc.c
index 7314c7e..283f985 100644
--- a/drivers/mfd/pm8xxx-misc.c
+++ b/drivers/mfd/pm8xxx-misc.c
@@ -944,6 +944,63 @@
}
EXPORT_SYMBOL(pm8xxx_uart_gpio_mux_ctrl);
+static int __pm8901_preload_dVdd(struct pm8xxx_misc_chip *chip)
+{
+ int rc;
+
+ rc = pm8xxx_writeb(chip->dev->parent, 0x0BD, 0x0F);
+ if (rc)
+ pr_err("pm8xxx_writeb failed for 0x0BD, rc=%d\n", rc);
+
+ rc = pm8xxx_writeb(chip->dev->parent, 0x001, 0xB4);
+ if (rc)
+ pr_err("pm8xxx_writeb failed for 0x001, rc=%d\n", rc);
+
+ pr_info("dVdd preloaded\n");
+
+ return rc;
+}
+
+/**
+ * pm8xxx_preload_dVdd - preload the dVdd regulator during off state.
+ *
+ * This can help to reduce fluctuations in the dVdd voltage during startup
+ * at the cost of additional off state current draw.
+ *
+ * This API should only be called if dVdd startup issues are suspected.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_preload_dVdd(void)
+{
+ struct pm8xxx_misc_chip *chip;
+ unsigned long flags;
+ int rc = 0;
+
+ spin_lock_irqsave(&pm8xxx_misc_chips_lock, flags);
+
+ /* Loop over all attached PMICs and call specific functions for them. */
+ list_for_each_entry(chip, &pm8xxx_misc_chips, link) {
+ switch (chip->version) {
+ case PM8XXX_VERSION_8901:
+ rc = __pm8901_preload_dVdd(chip);
+ break;
+ default:
+ /* PMIC doesn't have preload_dVdd; do nothing. */
+ break;
+ }
+ if (rc) {
+ pr_err("preload_dVdd failed, rc=%d\n", rc);
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&pm8xxx_misc_chips_lock, flags);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(pm8xxx_preload_dVdd);
+
static int __devinit pm8xxx_misc_probe(struct platform_device *pdev)
{
const struct pm8xxx_misc_platform_data *pdata = pdev->dev.platform_data;
diff --git a/drivers/misc/pmem.c b/drivers/misc/pmem.c
index 7ee7c11..f0d523e 100644
--- a/drivers/misc/pmem.c
+++ b/drivers/misc/pmem.c
@@ -1,7 +1,7 @@
/* drivers/android/pmem.c
*
* Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -2594,6 +2594,7 @@
{
int i, index = 0, id;
struct vm_struct *pmem_vma = NULL;
+ struct page *page;
if (id_count >= PMEM_MAX_DEVICES) {
pr_alert("pmem: %s: unable to register driver(%s) - no more "
@@ -2794,6 +2795,11 @@
pmem[id].base = allocate_contiguous_memory_nomap(pmem[id].size,
pmem[id].memory_type, PAGE_SIZE);
+ if (!pmem[id].base) {
+ pr_err("pmem: Cannot allocate from reserved memory for %s\n",
+ pdata->name);
+ goto err_misc_deregister;
+ }
pr_info("allocating %lu bytes at %p (%lx physical) for %s\n",
pmem[id].size, pmem[id].vbase, pmem[id].base, pmem[id].name);
@@ -2810,7 +2816,7 @@
if (!pmem_vma) {
pr_err("pmem: Failed to allocate virtual space for "
"%s\n", pdata->name);
- goto out_put_kobj;
+ goto err_free;
}
pr_err("pmem: Reserving virtual address range %lx - %lx for"
" %s\n", (unsigned long) pmem_vma->addr,
@@ -2821,7 +2827,12 @@
} else
pmem[id].area = NULL;
- pmem[id].garbage_pfn = page_to_pfn(alloc_page(GFP_KERNEL));
+ page = alloc_page(GFP_KERNEL);
+ if (!page) {
+ pr_err("pmem: Failed to allocate page for %s\n", pdata->name);
+ goto cleanup_vm;
+ }
+ pmem[id].garbage_pfn = page_to_pfn(page);
atomic_set(&pmem[id].allocation_cnt, 0);
if (pdata->setup_region)
@@ -2835,6 +2846,12 @@
return 0;
+cleanup_vm:
+ remove_vm_area(pmem_vma);
+err_free:
+ free_contiguous_memory_by_paddr(pmem[id].base);
+err_misc_deregister:
+ misc_deregister(&pmem[id].dev);
err_cant_register_device:
out_put_kobj:
kobject_put(&pmem[id].kobj);
@@ -2872,6 +2889,19 @@
int id = pdev->id;
__free_page(pfn_to_page(pmem[id].garbage_pfn));
pm_runtime_disable(&pdev->dev);
+ if (pmem[id].vbase)
+ iounmap(pmem[id].vbase);
+ if (pmem[id].map_on_demand && !pmem[id].reusable && pmem[id].area)
+ free_vm_area(pmem[id].area);
+ if (pmem[id].base)
+ free_contiguous_memory_by_paddr(pmem[id].base);
+ kobject_put(&pmem[id].kobj);
+ if (pmem[id].allocator_type == PMEM_ALLOCATORTYPE_BUDDYBESTFIT)
+ kfree(pmem[id].allocator.buddy_bestfit.buddy_bitmap);
+ else if (pmem[id].allocator_type == PMEM_ALLOCATORTYPE_BITMAP) {
+ kfree(pmem[id].allocator.bitmap.bitmap);
+ kfree(pmem[id].allocator.bitmap.bitm_alloc);
+ }
misc_deregister(&pmem[id].dev);
return 0;
}
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 9dc4044..ee7a2a9 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -2,7 +2,7 @@
* Gadget Driver for Android
*
* Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
* Author: Mike Lockwood <lockwood@android.com>
*
* This software is licensed under the terms of the GNU General Public
@@ -1472,13 +1472,23 @@
return 0;
}
+static void android_destroy_device(struct android_dev *dev)
+{
+ struct device_attribute **attrs = android_usb_attributes;
+ struct device_attribute *attr;
+
+ while ((attr = *attrs++))
+ device_remove_file(dev->dev, attr);
+ device_destroy(android_class, dev->dev->devt);
+}
+
static int __devinit android_probe(struct platform_device *pdev)
{
struct android_usb_platform_data *pdata = pdev->dev.platform_data;
struct android_dev *dev = _android_dev;
dev->pdata = pdata;
-
+
return 0;
}
@@ -1489,36 +1499,55 @@
static int __init init(void)
{
struct android_dev *dev;
- int err;
+ int ret;
android_class = class_create(THIS_MODULE, "android_usb");
if (IS_ERR(android_class))
return PTR_ERR(android_class);
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
+ if (!dev) {
+ pr_err("%s(): Failed to alloc memory for android_dev\n",
+ __func__);
+ class_destroy(android_class);
return -ENOMEM;
-
+ }
dev->functions = supported_functions;
INIT_LIST_HEAD(&dev->enabled_functions);
INIT_WORK(&dev->work, android_work);
- err = android_create_device(dev);
- if (err) {
- class_destroy(android_class);
- kfree(dev);
- return err;
+ ret = android_create_device(dev);
+ if (ret) {
+ pr_err("%s(): android_create_device failed\n", __func__);
+ goto err_dev;
}
-
_android_dev = dev;
/* Override composite driver functions */
composite_driver.setup = android_setup;
composite_driver.disconnect = android_disconnect;
- platform_driver_probe(&android_platform_driver, android_probe);
+ ret = platform_driver_probe(&android_platform_driver, android_probe);
+ if (ret) {
+ pr_err("%s(): Failed to register android"
+ "platform driver\n", __func__);
+ goto err_probe;
+ }
+ ret = usb_composite_probe(&android_usb_driver, android_bind);
+ if (ret) {
+ pr_err("%s(): Failed to register android"
+ "composite driver\n", __func__);
+ platform_driver_unregister(&android_platform_driver);
+ goto err_probe;
+ }
+ return ret;
- return usb_composite_probe(&android_usb_driver, android_bind);
+err_probe:
+ android_destroy_device(dev);
+err_dev:
+ kfree(dev);
+ class_destroy(android_class);
+ return ret;
}
module_init(init);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index ec9ac24..787514c 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1592,14 +1592,15 @@
{
struct msm_otg *motg = container_of(w, struct msm_otg, chg_work.work);
struct otg_transceiver *otg = &motg->otg;
- bool is_dcd, tmout, vout, is_aca;
+ bool is_dcd = false, tmout, vout, is_aca;
unsigned long delay;
dev_dbg(otg->dev, "chg detection work\n");
switch (motg->chg_state) {
case USB_CHG_STATE_UNDEFINED:
msm_chg_block_on(motg);
- msm_chg_enable_dcd(motg);
+ if (motg->pdata->enable_dcd)
+ msm_chg_enable_dcd(motg);
msm_chg_enable_aca_det(motg);
motg->chg_state = USB_CHG_STATE_WAIT_FOR_DCD;
motg->dcd_retries = 0;
@@ -1619,10 +1620,12 @@
break;
}
}
- is_dcd = msm_chg_check_dcd(motg);
+ if (motg->pdata->enable_dcd)
+ is_dcd = msm_chg_check_dcd(motg);
tmout = ++motg->dcd_retries == MSM_CHG_DCD_MAX_RETRIES;
if (is_dcd || tmout) {
- msm_chg_disable_dcd(motg);
+ if (motg->pdata->enable_dcd)
+ msm_chg_disable_dcd(motg);
msm_chg_enable_primary_det(motg);
delay = MSM_CHG_PRIMARY_DET_TIME;
motg->chg_state = USB_CHG_STATE_DCD_DONE;
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index de6bf1a..448194a 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -301,6 +301,13 @@
---help---
Support for MDP4 OVERLAY0 write back mode
+
+config FB_MSM_OVERLAY1_WRITEBACK
+ depends on FB_MSM_OVERLAY
+ bool "MDP overlay1 write back mode enable"
+ ---help---
+ Support for MDP4 OVERLAY1 write back mode
+
config FB_MSM_WRITEBACK_MSM_PANEL
depends on FB_MSM_OVERLAY
bool "MDP overlay write back panel enable"
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 1a4ce91..7b5f464 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -320,6 +320,7 @@
uint32 blt_cnt;
uint32 ov_cnt;
uint32 dmap_cnt;
+ uint32 dmae_cnt;
uint32 blt_end;
uint32 luma_align_size;
struct mdp4_hsic_regs hsic_regs;
@@ -409,8 +410,6 @@
uint32 mdp4_overlay_op_mode(struct mdp4_overlay_pipe *pipe);
void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd);
#ifdef CONFIG_FB_MSM_DTV
-void mdp4_overlay_dtv_vsync_push(struct msm_fb_data_type *mfd,
- struct mdp4_overlay_pipe *pipe);
void mdp4_overlay_dtv_ov_done_push(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe);
void mdp4_overlay_dtv_wait_for_ov(struct msm_fb_data_type *mfd,
@@ -420,11 +419,6 @@
int mdp4_overlay_dtv_unset(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe);
#else
-static inline void mdp4_overlay_dtv_vsync_push(struct msm_fb_data_type *mfd,
- struct mdp4_overlay_pipe *pipe)
-{
- /* empty */
-}
static inline void mdp4_overlay_dtv_ov_done_push(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe)
{
@@ -612,6 +606,8 @@
struct msmfb_overlay_blt *req);
void mdp4_lcdc_overlay_blt_start(struct msm_fb_data_type *mfd);
void mdp4_lcdc_overlay_blt_stop(struct msm_fb_data_type *mfd);
+void mdp4_dtv_overlay_blt_start(struct msm_fb_data_type *mfd);
+void mdp4_dtv_overlay_blt_stop(struct msm_fb_data_type *mfd);
int mdp4_mddi_overlay_blt_offset(int *off);
void mdp4_mddi_overlay_blt(ulong addr);
@@ -687,6 +683,7 @@
struct mdp4_overlay_pipe *pipe);
void mdp4_writeback_dma_busy_wait(struct msm_fb_data_type *mfd);
void mdp4_overlay1_done_writeback(struct mdp_dma_data *dma);
+void mdp4_dma_e_done_dtv(void);
int mdp4_writeback_start(struct fb_info *info);
int mdp4_writeback_stop(struct fb_info *info);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index ecb0a24..1fd0766 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -239,13 +239,27 @@
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- /* dma_p source */
MDP_OUTP(MDP_BASE + 0xb0004,
(pipe->src_height << 16 | pipe->src_width));
- MDP_OUTP(MDP_BASE + 0xb0008, pipe->srcp0_addr);
- MDP_OUTP(MDP_BASE + 0xb000c, pipe->srcp0_ystride);
-
- /* dma_p dest */
+ if (pipe->blt_addr) {
+ uint32 off, bpp;
+#ifdef BLT_RGB565
+ bpp = 2; /* overlay ouput is RGB565 */
+#else
+ bpp = 3; /* overlay ouput is RGB888 */
+#endif
+ off = 0;
+ if (pipe->ov_cnt & 0x01)
+ off = pipe->src_height * pipe->src_width * bpp;
+ MDP_OUTP(MDP_BASE + 0xb0008, pipe->blt_addr + off);
+ /* RGB888, output of overlay blending */
+ MDP_OUTP(MDP_BASE + 0xb000c, pipe->src_width * bpp);
+ } else {
+ /* dma_e source */
+ MDP_OUTP(MDP_BASE + 0xb0008, pipe->srcp0_addr);
+ MDP_OUTP(MDP_BASE + 0xb000c, pipe->srcp0_ystride);
+ }
+ /* dma_e dest */
MDP_OUTP(MDP_BASE + 0xb0010, (pipe->dst_y << 16 | pipe->dst_x));
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
@@ -1114,7 +1128,7 @@
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
/*
- * BLT only siupport at primary display
+ * BLT support both primary and external external
*/
if (pipe->blt_addr) {
int off, bpp;
@@ -1127,7 +1141,8 @@
data <<= 16;
data |= pipe->src_width;
outpdw(overlay_base + 0x0008, data); /* ROI, height + width */
- if (pipe->mixer_num == MDP4_MIXER0) {
+ if (pipe->mixer_num == MDP4_MIXER0 ||
+ pipe->mixer_num == MDP4_MIXER1) {
off = 0;
if (pipe->ov_cnt & 0x01)
off = pipe->src_height * pipe->src_width * bpp;
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index f2065fd..f454d89 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -264,36 +264,6 @@
return ret;
}
-static void mdp4_overlay_dtv_wait4vsync(struct msm_fb_data_type *mfd)
-{
- unsigned long flag;
-
- /* enable irq */
- spin_lock_irqsave(&mdp_spin_lock, flag);
- mdp_enable_irq(MDP_OVERLAY1_TERM);
- INIT_COMPLETION(dtv_pipe->comp);
- mfd->dma->waiting = TRUE;
- outp32(MDP_INTR_CLEAR, INTR_EXTERNAL_VSYNC);
- mdp_intr_mask |= INTR_EXTERNAL_VSYNC;
- outp32(MDP_INTR_ENABLE, mdp_intr_mask);
- spin_unlock_irqrestore(&mdp_spin_lock, flag);
- wait_for_completion_killable(&dtv_pipe->comp);
- mdp_disable_irq(MDP_OVERLAY1_TERM);
-}
-
-void mdp4_overlay_dtv_vsync_push(struct msm_fb_data_type *mfd,
- struct mdp4_overlay_pipe *pipe)
-{
- mdp4_overlay_reg_flush(pipe, 1);
- if (pipe->flags & MDP_OV_PLAY_NOWAIT)
- return;
-
- mdp4_overlay_dtv_wait4vsync(mfd);
-
- /* change mdp clk while mdp is idle` */
- mdp4_set_perf_level();
-}
-
static void mdp4_overlay_dtv_alloc_pipe(struct msm_fb_data_type *mfd,
int32 ptype)
{
@@ -406,6 +376,54 @@
return result;
}
+static void mdp4_dtv_blt_ov_update(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 off, addr;
+ int bpp;
+ char *overlay_base;
+
+ if (pipe->blt_addr == 0)
+ return;
+#ifdef BLT_RGB565
+ bpp = 2; /* overlay ouput is RGB565 */
+#else
+ bpp = 3; /* overlay ouput is RGB888 */
+#endif
+ off = (pipe->ov_cnt & 0x01) ?
+ pipe->src_height * pipe->src_width * bpp : 0;
+
+ addr = pipe->blt_addr + off;
+ pr_debug("%s overlay addr 0x%x\n", __func__, addr);
+ /* overlay 1 */
+ overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
+ outpdw(overlay_base + 0x000c, addr);
+ outpdw(overlay_base + 0x001c, addr);
+}
+
+static inline void mdp4_dtv_blt_dmae_update(struct mdp4_overlay_pipe *pipe)
+{
+ uint32 off, addr;
+ int bpp;
+
+ if (pipe->blt_addr == 0)
+ return;
+
+#ifdef BLT_RGB565
+ bpp = 2; /* overlay ouput is RGB565 */
+#else
+ bpp = 3; /* overlay ouput is RGB888 */
+#endif
+ off = (pipe->dmae_cnt & 0x01) ?
+ pipe->src_height * pipe->src_width * bpp : 0;
+ addr = pipe->blt_addr + off;
+ MDP_OUTP(MDP_BASE + 0xb0008, addr);
+}
+
+static inline void mdp4_overlay_dtv_ov_kick_start(void)
+{
+ outpdw(MDP_BASE + 0x0008, 0);
+}
+
static void mdp4_overlay_dtv_ov_start(struct msm_fb_data_type *mfd)
{
unsigned long flag;
@@ -414,6 +432,12 @@
if (mfd->ov_start)
return;
+ if (dtv_pipe->blt_addr) {
+ mdp4_dtv_blt_ov_update(dtv_pipe);
+ dtv_pipe->ov_cnt++;
+ mdp4_overlay_dtv_ov_kick_start();
+ }
+
spin_lock_irqsave(&mdp_spin_lock, flag);
mdp_enable_irq(MDP_OVERLAY1_TERM);
INIT_COMPLETION(dtv_pipe->comp);
@@ -444,6 +468,7 @@
void mdp4_overlay_dtv_ov_done_push(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe)
{
+
mdp4_overlay_reg_flush(pipe, 1);
mdp4_overlay_dtv_ov_start(mfd);
@@ -463,6 +488,11 @@
mdp4_set_perf_level();
}
+void mdp4_dma_e_done_dtv()
+{
+ complete(&dtv_pipe->comp);
+}
+
void mdp4_external_vsync_dtv()
{
complete_all(&dtv_pipe->comp);
@@ -473,6 +503,10 @@
*/
void mdp4_overlay1_done_dtv()
{
+ if (dtv_pipe->blt_addr) {
+ mdp4_dtv_blt_dmae_update(dtv_pipe);
+ dtv_pipe->dmae_cnt++;
+ }
complete_all(&dtv_pipe->comp);
}
@@ -506,6 +540,70 @@
}
#endif
+static void mdp4_overlay_dtv_wait4dmae(struct msm_fb_data_type *mfd)
+{
+ unsigned long flag;
+
+ /* enable irq */
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ mdp_enable_irq(MDP_DMA_E_TERM);
+ INIT_COMPLETION(dtv_pipe->comp);
+ mfd->dma->waiting = TRUE;
+ outp32(MDP_INTR_CLEAR, INTR_DMA_E_DONE);
+ mdp_intr_mask |= INTR_DMA_E_DONE;
+ outp32(MDP_INTR_ENABLE, mdp_intr_mask);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+ wait_for_completion_killable(&dtv_pipe->comp);
+ mdp_disable_irq(MDP_DMA_E_TERM);
+}
+
+static void mdp4_dtv_do_blt(struct msm_fb_data_type *mfd, int enable)
+{
+ unsigned long flag;
+ int change = 0;
+
+ if (!mfd->ov1_wb_buf->phys_addr) {
+ pr_debug("%s: no writeback buf assigned\n", __func__);
+ return;
+ }
+
+ spin_lock_irqsave(&mdp_spin_lock, flag);
+ if (enable && dtv_pipe->blt_addr == 0) {
+ dtv_pipe->blt_addr = mfd->ov1_wb_buf->phys_addr;
+ change++;
+ dtv_pipe->ov_cnt = 0;
+ dtv_pipe->dmae_cnt = 0;
+ } else if (enable == 0 && dtv_pipe->blt_addr) {
+ dtv_pipe->blt_addr = 0;
+ change++;
+ }
+ pr_debug("%s: blt_addr=%x\n", __func__, (int)dtv_pipe->blt_addr);
+ spin_unlock_irqrestore(&mdp_spin_lock, flag);
+
+ if (!change)
+ return;
+
+ mdp4_overlay_dtv_wait4dmae(mfd);
+
+ MDP_OUTP(MDP_BASE + DTV_BASE, 0); /* stop dtv */
+ msleep(20);
+ mdp4_overlayproc_cfg(dtv_pipe);
+ mdp4_overlay_dmae_xy(dtv_pipe);
+ MDP_OUTP(MDP_BASE + DTV_BASE, 1); /* start dtv */
+}
+
+void mdp4_dtv_overlay_blt_start(struct msm_fb_data_type *mfd)
+{
+ mdp4_allocate_writeback_buf(mfd, MDP4_MIXER1);
+ mdp4_dtv_do_blt(mfd, 1);
+}
+
+void mdp4_dtv_overlay_blt_stop(struct msm_fb_data_type *mfd)
+{
+ mdp4_free_writeback_buf(mfd, MDP4_MIXER1);
+ mdp4_dtv_do_blt(mfd, 0);
+}
+
void mdp4_dtv_overlay(struct msm_fb_data_type *mfd)
{
struct mdp4_overlay_pipe *pipe;
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index bd8ec55..ba6c746 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -554,7 +554,7 @@
mdp_intr_mask &= ~INTR_DMA_E_DONE;
outp32(MDP_INTR_ENABLE, mdp_intr_mask);
dma->busy = FALSE;
-
+ mdp4_dma_e_done_dtv();
if (dma->waiting) {
dma->waiting = FALSE;
complete(&dma->comp);
diff --git a/include/linux/mfd/pm8xxx/misc.h b/include/linux/mfd/pm8xxx/misc.h
index 32189b2..f9fc498 100644
--- a/include/linux/mfd/pm8xxx/misc.h
+++ b/include/linux/mfd/pm8xxx/misc.h
@@ -160,6 +160,18 @@
*/
int pm8xxx_stay_on(void);
+/**
+ * pm8xxx_preload_dVdd - preload the dVdd regulator during off state.
+ *
+ * This can help to reduce fluctuations in the dVdd voltage during startup
+ * at the cost of additional off state current draw.
+ *
+ * This API should only be called if dVdd startup issues are suspected.
+ *
+ * RETURNS: an appropriate -ERRNO error value on error, or zero for success.
+ */
+int pm8xxx_preload_dVdd(void);
+
#else
static inline int pm8xxx_reset_pwr_off(int reset)
@@ -196,6 +208,10 @@
{
return -ENODEV;
}
+static inline int pm8xxx_preload_dVdd(void)
+{
+ return -ENODEV;
+}
#endif
#endif
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 9373064..e03944d 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -160,6 +160,9 @@
* @disable_reset_on_disconnect: perform USB PHY and LINK reset
* on USB cable disconnection.
* @swfi_latency: miminum latency to allow swfi.
+ * @enable_dcd: Enable Data Contact Detection circuit. if not set
+ * wait for 600msec before proceeding to primary
+ * detection.
*/
struct msm_otg_platform_data {
int *phy_init_seq;
@@ -174,6 +177,7 @@
bool mhl_enable;
bool disable_reset_on_disconnect;
u32 swfi_latency;
+ bool enable_dcd;
};
/**
diff --git a/mm/ashmem.c b/mm/ashmem.c
index bc977ee..e4aab56 100644
--- a/mm/ashmem.c
+++ b/mm/ashmem.c
@@ -673,10 +673,28 @@
void (*cache_func)(unsigned long vstart, unsigned long length,
unsigned long pstart))
{
+ int ret = 0;
+ struct vm_area_struct *vma;
#ifdef CONFIG_OUTER_CACHE
unsigned long vaddr;
#endif
- mutex_lock(&ashmem_mutex);
+ if (!asma->vm_start)
+ return -EINVAL;
+
+ down_read(¤t->mm->mmap_sem);
+ vma = find_vma(current->mm, asma->vm_start);
+ if (!vma) {
+ ret = -EINVAL;
+ goto done;
+ }
+ if (vma->vm_file != asma->file) {
+ ret = -EINVAL;
+ goto done;
+ }
+ if ((asma->vm_start + asma->size) > (vma->vm_start + vma->vm_end)) {
+ ret = -EINVAL;
+ goto done;
+ }
#ifndef CONFIG_OUTER_CACHE
cache_func(asma->vm_start, asma->size, 0);
#else
@@ -689,8 +707,11 @@
cache_func(vaddr, PAGE_SIZE, physaddr);
}
#endif
- mutex_unlock(&ashmem_mutex);
- return 0;
+done:
+ up_read(¤t->mm->mmap_sem);
+ if (ret)
+ asma->vm_start = 0;
+ return ret;
}
static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 16d149e..fea11d9 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.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
@@ -236,6 +236,19 @@
.ops = &msm_fe_dai_ops,
.name = "AFE-PROXY",
},
+ {
+ .playback = {
+ .stream_name = "HDMI_Rx Hostless Playback",
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_fe_dai_ops,
+ .name = "HDMI_HOSTLESS"
+ },
};
static __devinit int msm_fe_dai_dev_probe(struct platform_device *pdev)
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 2815daa..1331ebf 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.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
@@ -1128,6 +1128,8 @@
0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("INTFM_UL_HL", "INT_FM_HOSTLESS Capture",
0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("HDMI_DL_HL", "HDMI_HOSTLESS Playback", 0, 0, 0, 0),
+
/* Backend AIF */
/* Stream name equals to backend dai link stream name
*/
@@ -1312,6 +1314,7 @@
{"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
{"HDMI_RX_Voice Mixer", "Voip", "VOIP_DL"},
{"HDMI", NULL, "HDMI_RX_Voice Mixer"},
+ {"HDMI", NULL, "HDMI_DL_HL"},
{"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
{"Voice_Tx Mixer", "SLIM_0_TX_Voice", "SLIMBUS_0_TX"},
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 60fa5f3..0dc3b57 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -724,6 +724,14 @@
},
};
+static struct snd_soc_dsp_link hdmi_rx_hl = {
+ .playback = true,
+ .trigger = {
+ SND_SOC_DSP_TRIGGER_POST,
+ SND_SOC_DSP_TRIGGER_POST
+ },
+};
+
static int msm8960_slim_0_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -1010,6 +1018,18 @@
.dsp_link = &lpa_fe_media,
.be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
},
+ /* HDMI Hostless */
+ {
+ .name = "HDMI_RX_HOSTLESS",
+ .stream_name = "HDMI_RX_HOSTLESS",
+ .cpu_dai_name = "HDMI_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .dsp_link = &hdmi_rx_hl,
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .no_codec = 1,
+ .ignore_suspend = 1,
+ },
/* Backend DAI Links */
{
.name = LPASS_BE_SLIMBUS_0_RX,