Merge "msm: board-msm7627a-display: Create separate board file for display" into msm-3.0
diff --git a/Documentation/driver-model/devres.txt b/Documentation/driver-model/devres.txt
index d79aead..b1db115 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -266,3 +266,6 @@
pcim_iounmap()
pcim_iomap_table() : array of mapped addresses indexed by BAR
pcim_iomap_regions() : do request_region() and iomap() on multiple BARs
+
+REGULATOR
+ devm_regulator_get()
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..5a10ddb 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -33,6 +33,7 @@
#include <mach/msm_smsm.h>
#include <mach/subsystem_notif.h>
#include <mach/socinfo.h>
+#include <mach/subsystem_restart.h>
#define BAM_CH_LOCAL_OPEN 0x1
#define BAM_CH_REMOTE_OPEN 0x2
@@ -63,6 +64,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 +98,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 +558,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;
@@ -662,6 +669,8 @@
if (!bam_is_connected) {
read_unlock(&ul_wakeup_lock);
ul_wakeup();
+ if (unlikely(in_global_reset == 1))
+ return -EFAULT;
read_lock(&ul_wakeup_lock);
notify_all(BAM_DMUX_UL_CONNECTED, (unsigned long)(NULL));
}
@@ -718,12 +727,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 +738,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);
@@ -800,6 +808,8 @@
if (!bam_is_connected) {
read_unlock(&ul_wakeup_lock);
ul_wakeup();
+ if (unlikely(in_global_reset == 1))
+ return -EFAULT;
read_lock(&ul_wakeup_lock);
notify_all(BAM_DMUX_UL_CONNECTED, (unsigned long)(NULL));
}
@@ -835,6 +845,8 @@
if (!bam_is_connected && !bam_ch_is_in_reset(id)) {
read_unlock(&ul_wakeup_lock);
ul_wakeup();
+ if (unlikely(in_global_reset == 1))
+ return -EFAULT;
read_lock(&ul_wakeup_lock);
notify_all(BAM_DMUX_UL_CONNECTED, (unsigned long)(NULL));
}
@@ -1124,10 +1136,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;
@@ -1281,6 +1295,8 @@
if (!bam_is_connected) {
read_unlock(&ul_wakeup_lock);
ul_wakeup();
+ if (unlikely(in_global_reset == 1))
+ return;
read_lock(&ul_wakeup_lock);
ul_packet_written = 1;
notify_all(BAM_DMUX_UL_CONNECTED, (unsigned long)(NULL));
@@ -1352,6 +1368,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;
@@ -1364,6 +1395,26 @@
write_unlock_irqrestore(&ul_wakeup_lock, flags);
ul_powerdown_finish();
}
+
+static int ssrestart_check(void)
+{
+ /*
+ * if the restart level is RESET_SOC, SSR is not on
+ * so the crashed modem will end up crashing the system
+ * anyways, so use BUG() to report the error
+ * else prepare for the restart event which should
+ * happen soon
+ */
+ DMUX_LOG_KERR("%s: modem timeout\n", __func__);
+ if (get_restart_level() <= RESET_SOC) {
+ BUG();
+ return 0;
+ } else {
+ in_global_reset = 1;
+ return 1;
+ }
+}
+
static void ul_wakeup(void)
{
int ret;
@@ -1407,17 +1458,29 @@
bam_dmux_log("%s waiting for previous ack\n", __func__);
ret = wait_for_completion_timeout(
&ul_wakeup_ack_completion, HZ);
- BUG_ON(ret == 0);
wait_for_ack = 0;
+ if (unlikely(ret == 0) && ssrestart_check()) {
+ mutex_unlock(&wakeup_lock);
+ bam_dmux_log("%s timeout previous ack\n", __func__);
+ return;
+ }
}
INIT_COMPLETION(ul_wakeup_ack_completion);
power_vote(1);
bam_dmux_log("%s waiting for wakeup ack\n", __func__);
ret = wait_for_completion_timeout(&ul_wakeup_ack_completion, HZ);
- BUG_ON(ret == 0);
+ if (unlikely(ret == 0) && ssrestart_check()) {
+ mutex_unlock(&wakeup_lock);
+ bam_dmux_log("%s timeout wakeup ack\n", __func__);
+ return;
+ }
bam_dmux_log("%s waiting completion\n", __func__);
ret = wait_for_completion_timeout(&bam_connection_completion, HZ);
- BUG_ON(ret == 0);
+ if (unlikely(ret == 0) && ssrestart_check()) {
+ mutex_unlock(&wakeup_lock);
+ bam_dmux_log("%s timeout power on\n", __func__);
+ return;
+ }
bam_is_connected = 1;
bam_dmux_log("%s complete\n", __func__);
@@ -1588,6 +1651,11 @@
ul_powerdown();
wait_for_ack = 0;
}
+ /*
+ * if modem crash during ul_wakeup(), power_vote is 1, needs to be
+ * reset to 0. harmless if bam_is_connected check above passes
+ */
+ power_vote(0);
write_unlock_irqrestore(&ul_wakeup_lock, flags);
ul_powerdown_finish();
a2_pc_disabled = 0;
@@ -1639,6 +1707,7 @@
int ret;
void *a2_virt_addr;
int i;
+ int skip_iounmap = 0;
vote_dfab();
/* init BAM */
@@ -1786,7 +1855,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 +1902,7 @@
return 0;
register_bam_failed:
+ iounmap(a2_virt_addr);
ioremap_failed:
return ret;
}
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 47b20e4..5df252c 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -39,6 +39,7 @@
REGULATOR_SUPPLY("HSUSB_1p8", "msm_otg"),
REGULATOR_SUPPLY("HSUSB_1p8", "msm_ehci_host.0"),
REGULATOR_SUPPLY("HSUSB_1p8", "msm_ehci_host.1"),
+ REGULATOR_SUPPLY("iris_vddxo", "wcnss_wlan.0"),
};
VREG_CONSUMERS(L5) = {
REGULATOR_SUPPLY("8921_l5", NULL),
@@ -60,6 +61,7 @@
};
VREG_CONSUMERS(L10) = {
REGULATOR_SUPPLY("8921_l10", NULL),
+ REGULATOR_SUPPLY("iris_vddpa", "wcnss_wlan.0"),
};
VREG_CONSUMERS(L11) = {
REGULATOR_SUPPLY("8921_l11", NULL),
@@ -90,6 +92,7 @@
};
VREG_CONSUMERS(L24) = {
REGULATOR_SUPPLY("8921_l24", NULL),
+ REGULATOR_SUPPLY("riva_vddmx", "wcnss_wlan.0"),
};
VREG_CONSUMERS(L25) = {
REGULATOR_SUPPLY("8921_l25", NULL),
@@ -110,12 +113,14 @@
};
VREG_CONSUMERS(S2) = {
REGULATOR_SUPPLY("8921_s2", NULL),
+ REGULATOR_SUPPLY("iris_vddrfa", "wcnss_wlan.0"),
};
VREG_CONSUMERS(S3) = {
REGULATOR_SUPPLY("8921_s3", NULL),
REGULATOR_SUPPLY("HSUSB_VDDCX", "msm_otg"),
REGULATOR_SUPPLY("HSUSB_VDDCX", "msm_ehci_host.0"),
REGULATOR_SUPPLY("HSUSB_VDDCX", "msm_ehci_host.1"),
+ REGULATOR_SUPPLY("riva_vddcx", "wcnss_wlan.0"),
};
VREG_CONSUMERS(S4) = {
REGULATOR_SUPPLY("8921_s4", NULL),
@@ -124,6 +129,7 @@
REGULATOR_SUPPLY("CDC_VDD_CP", "tabla-slim"),
REGULATOR_SUPPLY("CDC_VDDA_TX", "tabla-slim"),
REGULATOR_SUPPLY("CDC_VDDA_RX", "tabla-slim"),
+ REGULATOR_SUPPLY("riva_vddpx", "wcnss_wlan.0"),
};
VREG_CONSUMERS(S5) = {
REGULATOR_SUPPLY("8921_s5", NULL),
@@ -136,9 +142,11 @@
};
VREG_CONSUMERS(LVS1) = {
REGULATOR_SUPPLY("8921_lvs1", NULL),
+ REGULATOR_SUPPLY("iris_vddio", "wcnss_wlan.0"),
};
VREG_CONSUMERS(LVS2) = {
REGULATOR_SUPPLY("8921_lvs2", NULL),
+ REGULATOR_SUPPLY("iris_vdddig", "wcnss_wlan.0"),
};
VREG_CONSUMERS(LVS3) = {
REGULATOR_SUPPLY("8921_lvs3", NULL),
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/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 68c5059..09f70f1 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -4450,11 +4450,7 @@
static DEFINE_CLK_VOTER(dfab_scm_clk, &dfab_clk.c);
static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c);
-/*
- * TODO: replace dummy_clk below with ebi1_clk.c once the
- * bus driver starts voting on ebi1 rates.
- */
-static DEFINE_CLK_VOTER(ebi1_adm_clk, &dummy_clk);
+static DEFINE_CLK_VOTER(ebi1_adm_clk, &ebi1_clk.c);
#ifdef CONFIG_DEBUG_FS
struct measure_sel {
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/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index fd282d5..8961c79 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -155,8 +155,12 @@
struct msm_vpe_phy_info {
uint32_t sbuf_phy;
- uint32_t y_phy;
- uint32_t cbcr_phy;
+ uint32_t planar0_off;
+ uint32_t planar1_off;
+ uint32_t planar2_off;
+ uint32_t p0_phy;
+ uint32_t p1_phy;
+ uint32_t p2_phy;
uint8_t output_id; /* VFE31_OUTPUT_MODE_PT/S/V */
uint32_t frame_id;
};
@@ -193,6 +197,7 @@
#define VFE31_OUTPUT_MODE_V (0x1 << 2)
#define VFE31_OUTPUT_MODE_P (0x1 << 3)
#define VFE31_OUTPUT_MODE_T (0x1 << 4)
+#define VFE31_OUTPUT_MODE_P_ALL_CHNLS (0x1 << 5)
#define CSI_EMBED_DATA 0x12
#define CSI_YUV422_8 0x1E
@@ -206,8 +211,12 @@
struct msm_vfe_phy_info {
uint32_t sbuf_phy;
- uint32_t y_phy;
- uint32_t cbcr_phy;
+ uint32_t planar0_off;
+ uint32_t planar1_off;
+ uint32_t planar2_off;
+ uint32_t p0_phy;
+ uint32_t p1_phy;
+ uint32_t p2_phy;
uint8_t output_id; /* VFE31_OUTPUT_MODE_PT/S/V */
uint32_t frame_id;
};
@@ -238,8 +247,8 @@
};
struct msm_vpe_buf_info {
- uint32_t y_phy;
- uint32_t cbcr_phy;
+ uint32_t p0_phy;
+ uint32_t p1_phy;
struct timespec ts;
uint32_t frame_id;
struct video_crop_t vpe_crop;
@@ -303,7 +312,7 @@
struct msm_camvpe_fn {
int (*vpe_reg)(struct msm_vpe_callback *);
int (*vpe_cfg_update) (void *);
- void (*send_frame_to_vpe) (uint32_t y_phy, uint32_t cbcr_phy,
+ void (*send_frame_to_vpe) (uint32_t planar0_off, uint32_t planar1_off,
struct timespec *ts, int output_id);
int (*vpe_config)(struct msm_vpe_cfg_cmd *, void *);
void (*vpe_cfg_offset)(int frame_pack, uint32_t pyaddr,
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/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index 9cd73db..e1fc054 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -1,7 +1,7 @@
/* arch/arm/mach-msm/include/mach/memory.h
*
* 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
@@ -23,8 +23,13 @@
#define MAX_PHYSMEM_BITS 32
#define SECTION_SIZE_BITS 28
-/* Maximum number of Memory Regions */
-#define MAX_NR_REGIONS 4
+/* Maximum number of Memory Regions
+* The largest system can have 4 memory banks, each divided into 8 regions
+*/
+#define MAX_NR_REGIONS 32
+
+/* The number of regions each memory bank is divided into */
+#define NR_REGIONS_PER_BANK 8
/* Certain configurations of MSM7x30 have multiple memory banks.
* One or more of these banks can contain holes in the memory map as well.
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8064.h b/arch/arm/mach-msm/include/mach/msm_iomap-8064.h
index 15b2856..c584c66 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8064.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8064.h
@@ -97,5 +97,7 @@
#define APQ8064_SAW_L2_PHYS 0x02012000
#define APQ8064_SAW_L2_SIZE SZ_4K
+#define APQ8064_QFPROM_PHYS 0x00700000
+#define APQ8064_QFPROM_SIZE SZ_4K
#endif
diff --git a/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
index 16751fe..a55dee6 100644
--- a/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.h
+++ b/arch/arm/mach-msm/include/mach/qdsp6v2/audio_acdb.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
@@ -28,9 +28,15 @@
uint32_t cal_paddr;
};
+struct acdb_atomic_cal_block {
+ atomic_t cal_size;
+ atomic_t cal_kvaddr;
+ atomic_t cal_paddr;
+};
+
struct acdb_cal_data {
- uint32_t num_cal_blocks;
- struct acdb_cal_block *cal_blocks;
+ uint32_t num_cal_blocks;
+ struct acdb_atomic_cal_block *cal_blocks;
};
uint32_t get_voice_rx_topology(void);
@@ -44,6 +50,7 @@
void get_all_vocstrm_cal(struct acdb_cal_block *cal_block);
void get_all_vocvol_cal(struct acdb_cal_block *cal_block);
void get_anc_cal(struct acdb_cal_block *cal_block);
+void get_afe_cal(int32_t path, struct acdb_cal_block *cal_block);
void get_audproc_cal(int32_t path, struct acdb_cal_block *cal_block);
void get_audstrm_cal(int32_t path, struct acdb_cal_block *cal_block);
void get_audvol_cal(int32_t path, struct acdb_cal_block *cal_block);
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index 9622a4c..0f9d707 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -278,6 +278,7 @@
.length = MSM_SHARED_RAM_SIZE,
.type = MT_DEVICE,
},
+ MSM_CHIP_DEVICE(QFPROM, APQ8064),
};
void __init msm_map_apq8064_io(void)
diff --git a/arch/arm/mach-msm/memory_topology.c b/arch/arm/mach-msm/memory_topology.c
index 5854a23..6208a0d 100644
--- a/arch/arm/mach-msm/memory_topology.c
+++ b/arch/arm/mach-msm/memory_topology.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
@@ -31,11 +31,11 @@
/* reserved for future use */
u64 num_partitions;
int state;
- int mask;
- struct mutex state_mutex;
} mem_regions[MAX_NR_REGIONS];
+static struct mutex mem_regions_mutex;
static unsigned int nr_mem_regions;
+static int mem_regions_mask;
enum {
STATE_POWER_DOWN = 0x0,
@@ -43,14 +43,6 @@
STATE_DEFAULT = STATE_ACTIVE
};
-enum {
- MEM_NO_CHANGE = 0x0,
- MEM_DEEP_POWER_DOWN,
- MEM_SELF_REFRESH,
-};
-
-static unsigned int dmm_mode;
-
static int default_mask = ~0x0;
/* Return the number of chipselects populated with a memory bank */
@@ -111,50 +103,55 @@
}
}
-static int switch_memory_state(int id, int new_state)
+static int switch_memory_state(int mask, int new_state, int start_region,
+ int end_region)
{
- int mask = 0;
- int power_down_masks[MAX_NR_REGIONS] = { 0xFFFFFF00, 0xFFFF00FF,
- 0xFF00FFFF, 0x00FFFFFF };
- int self_refresh_masks[MAX_NR_REGIONS] = { 0xFFFFFFF0, 0xFFFFFF0F,
- 0xFFFFF0FF, 0xFFFF0FFF };
- mutex_lock(&mem_regions[id].state_mutex);
+ int final_mask = 0;
+ int i;
- if (new_state == mem_regions[id].state)
- goto no_change;
+ mutex_lock(&mem_regions_mutex);
- pr_info("request memory %d state switch (%d->%d) mode %d\n", id,
- mem_regions[id].state, new_state, dmm_mode);
- if (new_state == STATE_POWER_DOWN) {
- if (dmm_mode == MEM_DEEP_POWER_DOWN)
- mask = mem_regions[id].mask & power_down_masks[id];
- else
- mask = mem_regions[id].mask & self_refresh_masks[id];
- } else if (new_state == STATE_ACTIVE) {
- if (dmm_mode == MEM_DEEP_POWER_DOWN)
- mask = mem_regions[id].mask | (~power_down_masks[id]);
- else
- mask = mem_regions[id].mask | (~self_refresh_masks[id]);
+ for (i = start_region; i <= end_region; i++) {
+ if (new_state == mem_regions[i].state)
+ goto no_change;
+ /* All region states must be the same to change them */
+ if (mem_regions[i].state != mem_regions[start_region].state)
+ goto no_change;
}
- if (rpm_change_memory_state(mask, mask) == 0) {
- mem_regions[id].state = new_state;
- mem_regions[id].mask = mask;
- pr_info("completed memory %d state switch to %d mode %d\n",
- id, new_state, dmm_mode);
- mutex_unlock(&mem_regions[id].state_mutex);
+ if (new_state == STATE_POWER_DOWN)
+ final_mask = mem_regions_mask & mask;
+ else if (new_state == STATE_ACTIVE)
+ final_mask = mem_regions_mask | ~mask;
+ else
+ goto no_change;
+
+ pr_info("request memory %d to %d state switch (%d->%d)\n",
+ start_region, end_region, mem_regions[start_region].state,
+ new_state);
+ if (rpm_change_memory_state(final_mask, final_mask) == 0) {
+ for (i = start_region; i <= end_region; i++)
+ mem_regions[i].state = new_state;
+ mem_regions_mask = final_mask;
+
+ pr_info("completed memory %d to %d state switch to %d\n",
+ start_region, end_region, new_state);
+ mutex_unlock(&mem_regions_mutex);
return 0;
}
- pr_err("failed memory %d state switch (%d->%d) mode %d\n", id,
- mem_regions[id].state, new_state, dmm_mode);
+ pr_err("failed memory %d to %d state switch (%d->%d)\n",
+ start_region, end_region, mem_regions[start_region].state,
+ new_state);
+
no_change:
- mutex_unlock(&mem_regions[id].state_mutex);
+ mutex_unlock(&mem_regions_mutex);
return -EINVAL;
}
#else
-static int switch_memory_state(int id, int new_state)
+static int switch_memory_state(int mask, int new_state, int start_region,
+ int end_region)
{
return -EINVAL;
}
@@ -165,29 +162,34 @@
*/
int soc_change_memory_power(u64 start, u64 size, int change)
{
-
int i = 0;
- int match = 0;
-
- /* Find the memory region starting just below start */
- for (i = 0; i < nr_mem_regions; i++) {
- if (mem_regions[i].start <= start &&
- mem_regions[i].start >= mem_regions[match].start) {
- match = i;
- }
- }
-
- if (start + size > mem_regions[match].start + mem_regions[match].size) {
- pr_info("passed size exceeds size of memory bank\n");
- return 0;
- }
+ int mask = default_mask;
+ u64 end = start + size;
+ int start_region = 0;
+ int end_region = 0;
if (change != STATE_ACTIVE && change != STATE_POWER_DOWN) {
pr_info("requested state transition invalid\n");
return 0;
}
+ /* Find the memory regions that fall within the range */
+ for (i = 0; i < nr_mem_regions; i++) {
+ if (mem_regions[i].start <= start &&
+ mem_regions[i].start >=
+ mem_regions[start_region].start) {
+ start_region = i;
+ }
+ if (end <= mem_regions[i].start + mem_regions[i].size) {
+ end_region = i;
+ break;
+ }
+ }
- if (!switch_memory_state(match, change))
+ /* Set the bitmask for each region in the range */
+ for (i = start_region; i <= end_region; i++)
+ mask &= ~(0x1 << i);
+
+ if (!switch_memory_state(mask, change, start_region, end_region))
return size;
else
return 0;
@@ -212,9 +214,10 @@
int __init meminfo_init(unsigned int type, unsigned int min_bank_size)
{
- unsigned int i;
+ unsigned int i, j;
unsigned long bank_size;
unsigned long bank_start;
+ unsigned long region_size;
struct smem_ram_ptable *ram_ptable;
/* physical memory banks */
unsigned int nr_mem_banks = 0;
@@ -229,40 +232,35 @@
return -EINVAL;
}
- /* Determine power control mode based on the hw version */
- /* This check will be removed when PASR is fully supported */
- if (cpu_is_msm8960() &&
- SOCINFO_VERSION_MAJOR(socinfo_get_version()) < 2)
- dmm_mode = MEM_DEEP_POWER_DOWN;
- else
- dmm_mode = MEM_SELF_REFRESH;
-
pr_info("meminfo_init: smem ram ptable found: ver: %d len: %d\n",
ram_ptable->version, ram_ptable->len);
for (i = 0; i < ram_ptable->len; i++) {
+ /* A bank is valid only if is greater than min_bank_size. If
+ * non-valid memory (e.g. modem memory) became greater than
+ * min_bank_size, there is currently no way to differentiate.
+ */
if (ram_ptable->parts[i].type == type &&
ram_ptable->parts[i].size >= min_bank_size) {
bank_start = ram_ptable->parts[i].start;
bank_size = ram_ptable->parts[i].size;
- /* Divide into logical memory regions of same size */
- while (bank_size) {
+ region_size = bank_size / NR_REGIONS_PER_BANK;
+
+ for (j = 0; j < NR_REGIONS_PER_BANK; j++) {
mem_regions[nr_mem_regions].start =
bank_start;
mem_regions[nr_mem_regions].size =
- MIN_MEMORY_BLOCK_SIZE;
- mutex_init(&mem_regions[nr_mem_regions]
- .state_mutex);
+ region_size;
mem_regions[nr_mem_regions].state =
STATE_DEFAULT;
- mem_regions[nr_mem_regions].mask = default_mask;
- bank_start += MIN_MEMORY_BLOCK_SIZE;
- bank_size -= MIN_MEMORY_BLOCK_SIZE;
+ bank_start += region_size;
nr_mem_regions++;
}
nr_mem_banks++;
}
}
+ mutex_init(&mem_regions_mutex);
+ mem_regions_mask = default_mask;
pr_info("Found %d memory banks grouped into %d memory regions\n",
nr_mem_banks, nr_mem_regions);
return 0;
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/qdsp6v2/audio_acdb.c b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
index 37a6900..2e61e90 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
@@ -22,43 +22,52 @@
#define MAX_NETWORKS 12
+struct sidetone_atomic_cal {
+ atomic_t enable;
+ atomic_t gain;
+};
+
+
struct acdb_data {
struct mutex acdb_mutex;
/* ANC Cal */
- struct acdb_cal_block anc_cal;
+ struct acdb_atomic_cal_block anc_cal;
/* AudProc Cal */
- uint32_t asm_topology;
- uint32_t adm_topology[MAX_AUDPROC_TYPES];
- struct acdb_cal_block audproc_cal[MAX_AUDPROC_TYPES];
- struct acdb_cal_block audstrm_cal[MAX_AUDPROC_TYPES];
- struct acdb_cal_block audvol_cal[MAX_AUDPROC_TYPES];
+ atomic_t asm_topology;
+ atomic_t adm_topology[MAX_AUDPROC_TYPES];
+ struct acdb_atomic_cal_block audproc_cal[MAX_AUDPROC_TYPES];
+ struct acdb_atomic_cal_block audstrm_cal[MAX_AUDPROC_TYPES];
+ struct acdb_atomic_cal_block audvol_cal[MAX_AUDPROC_TYPES];
/* VocProc Cal */
- uint32_t voice_rx_topology;
- uint32_t voice_tx_topology;
- struct acdb_cal_block vocproc_cal[MAX_NETWORKS];
- struct acdb_cal_block vocstrm_cal[MAX_NETWORKS];
- struct acdb_cal_block vocvol_cal[MAX_NETWORKS];
+ atomic_t voice_rx_topology;
+ atomic_t voice_tx_topology;
+ struct acdb_atomic_cal_block vocproc_cal[MAX_NETWORKS];
+ struct acdb_atomic_cal_block vocstrm_cal[MAX_NETWORKS];
+ struct acdb_atomic_cal_block vocvol_cal[MAX_NETWORKS];
/* size of cal block tables above*/
- uint32_t vocproc_cal_size;
- uint32_t vocstrm_cal_size;
- uint32_t vocvol_cal_size;
+ atomic_t vocproc_cal_size;
+ atomic_t vocstrm_cal_size;
+ atomic_t vocvol_cal_size;
/* Total size of cal data for all networks */
- uint32_t vocproc_total_cal_size;
- uint32_t vocstrm_total_cal_size;
- uint32_t vocvol_total_cal_size;
+ atomic_t vocproc_total_cal_size;
+ atomic_t vocstrm_total_cal_size;
+ atomic_t vocvol_total_cal_size;
+
+ /* AFE cal */
+ struct acdb_atomic_cal_block afe_cal[MAX_AUDPROC_TYPES];
/* Sidetone Cal */
- struct sidetone_cal sidetone_cal;
+ struct sidetone_atomic_cal sidetone_cal;
/* PMEM information */
- int pmem_fd;
- unsigned long paddr;
- unsigned long kvaddr;
- unsigned long pmem_len;
- struct file *file;
+ atomic_t pmem_fd;
+ atomic64_t paddr;
+ atomic64_t kvaddr;
+ atomic64_t pmem_len;
+ struct file *file;
};
@@ -67,90 +76,105 @@
uint32_t get_voice_rx_topology(void)
{
- return acdb_data.voice_rx_topology;
+ return atomic_read(&acdb_data.voice_rx_topology);
}
void store_voice_rx_topology(uint32_t topology)
{
- acdb_data.voice_rx_topology = topology;
+ atomic_set(&acdb_data.voice_rx_topology, topology);
}
uint32_t get_voice_tx_topology(void)
{
- return acdb_data.voice_tx_topology;
+ return atomic_read(&acdb_data.voice_tx_topology);
}
void store_voice_tx_topology(uint32_t topology)
{
- acdb_data.voice_tx_topology = topology;
+ atomic_set(&acdb_data.voice_tx_topology, topology);
}
uint32_t get_adm_rx_topology(void)
{
- return acdb_data.adm_topology[RX_CAL];
+ return atomic_read(&acdb_data.adm_topology[RX_CAL]);
}
void store_adm_rx_topology(uint32_t topology)
{
- acdb_data.adm_topology[RX_CAL] = topology;
+ atomic_set(&acdb_data.adm_topology[RX_CAL], topology);
}
uint32_t get_adm_tx_topology(void)
{
- return acdb_data.adm_topology[TX_CAL];
+ return atomic_read(&acdb_data.adm_topology[TX_CAL]);
}
void store_adm_tx_topology(uint32_t topology)
{
- acdb_data.adm_topology[TX_CAL] = topology;
+ atomic_set(&acdb_data.adm_topology[TX_CAL], topology);
}
uint32_t get_asm_topology(void)
{
- return acdb_data.asm_topology;
+ return atomic_read(&acdb_data.asm_topology);
}
void store_asm_topology(uint32_t topology)
{
- acdb_data.asm_topology = topology;
+ atomic_set(&acdb_data.asm_topology, topology);
}
void get_all_voice_cal(struct acdb_cal_block *cal_block)
{
- cal_block->cal_kvaddr = acdb_data.vocproc_cal[0].cal_kvaddr;
- cal_block->cal_paddr = acdb_data.vocproc_cal[0].cal_paddr;
- cal_block->cal_size = acdb_data.vocproc_total_cal_size +
- acdb_data.vocstrm_total_cal_size +
- acdb_data.vocvol_total_cal_size;
+ cal_block->cal_kvaddr =
+ atomic_read(&acdb_data.vocproc_cal[0].cal_kvaddr);
+ cal_block->cal_paddr =
+ atomic_read(&acdb_data.vocproc_cal[0].cal_paddr);
+ cal_block->cal_size =
+ atomic_read(&acdb_data.vocproc_total_cal_size) +
+ atomic_read(&acdb_data.vocstrm_total_cal_size) +
+ atomic_read(&acdb_data.vocvol_total_cal_size);
}
void get_all_cvp_cal(struct acdb_cal_block *cal_block)
{
- cal_block->cal_kvaddr = acdb_data.vocproc_cal[0].cal_kvaddr;
- cal_block->cal_paddr = acdb_data.vocproc_cal[0].cal_paddr;
- cal_block->cal_size = acdb_data.vocproc_total_cal_size +
- acdb_data.vocvol_total_cal_size;
+ cal_block->cal_kvaddr =
+ atomic_read(&acdb_data.vocproc_cal[0].cal_kvaddr);
+ cal_block->cal_paddr =
+ atomic_read(&acdb_data.vocproc_cal[0].cal_paddr);
+ cal_block->cal_size =
+ atomic_read(&acdb_data.vocproc_total_cal_size) +
+ atomic_read(&acdb_data.vocvol_total_cal_size);
}
void get_all_vocproc_cal(struct acdb_cal_block *cal_block)
{
- cal_block->cal_kvaddr = acdb_data.vocproc_cal[0].cal_kvaddr;
- cal_block->cal_paddr = acdb_data.vocproc_cal[0].cal_paddr;
- cal_block->cal_size = acdb_data.vocproc_total_cal_size;
+ cal_block->cal_kvaddr =
+ atomic_read(&acdb_data.vocproc_cal[0].cal_kvaddr);
+ cal_block->cal_paddr =
+ atomic_read(&acdb_data.vocproc_cal[0].cal_paddr);
+ cal_block->cal_size =
+ atomic_read(&acdb_data.vocproc_total_cal_size);
}
void get_all_vocstrm_cal(struct acdb_cal_block *cal_block)
{
- cal_block->cal_kvaddr = acdb_data.vocstrm_cal[0].cal_kvaddr;
- cal_block->cal_paddr = acdb_data.vocstrm_cal[0].cal_paddr;
- cal_block->cal_size = acdb_data.vocstrm_total_cal_size;
+ cal_block->cal_kvaddr =
+ atomic_read(&acdb_data.vocstrm_cal[0].cal_kvaddr);
+ cal_block->cal_paddr =
+ atomic_read(&acdb_data.vocstrm_cal[0].cal_paddr);
+ cal_block->cal_size =
+ atomic_read(&acdb_data.vocstrm_total_cal_size);
}
void get_all_vocvol_cal(struct acdb_cal_block *cal_block)
{
- cal_block->cal_kvaddr = acdb_data.vocvol_cal[0].cal_kvaddr;
- cal_block->cal_paddr = acdb_data.vocvol_cal[0].cal_paddr;
- cal_block->cal_size = acdb_data.vocvol_total_cal_size;
+ cal_block->cal_kvaddr =
+ atomic_read(&acdb_data.vocvol_cal[0].cal_kvaddr);
+ cal_block->cal_paddr =
+ atomic_read(&acdb_data.vocvol_cal[0].cal_paddr);
+ cal_block->cal_size =
+ atomic_read(&acdb_data.vocvol_total_cal_size);
}
void get_anc_cal(struct acdb_cal_block *cal_block)
@@ -162,13 +186,12 @@
goto done;
}
- mutex_lock(&acdb_data.acdb_mutex);
-
- cal_block->cal_kvaddr = acdb_data.anc_cal.cal_kvaddr;
- cal_block->cal_paddr = acdb_data.anc_cal.cal_paddr;
- cal_block->cal_size = acdb_data.anc_cal.cal_size;
-
- mutex_unlock(&acdb_data.acdb_mutex);
+ cal_block->cal_kvaddr =
+ atomic_read(&acdb_data.anc_cal.cal_kvaddr);
+ cal_block->cal_paddr =
+ atomic_read(&acdb_data.anc_cal.cal_paddr);
+ cal_block->cal_size =
+ atomic_read(&acdb_data.anc_cal.cal_size);
done:
return;
}
@@ -177,23 +200,69 @@
{
pr_debug("%s,\n", __func__);
- if (cal_block->cal_offset > acdb_data.pmem_len) {
+ if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
pr_err("%s: offset %d is > pmem_len %ld\n",
__func__, cal_block->cal_offset,
- acdb_data.pmem_len);
+ (long)atomic64_read(&acdb_data.pmem_len));
goto done;
}
- mutex_lock(&acdb_data.acdb_mutex);
+ atomic_set(&acdb_data.anc_cal.cal_kvaddr,
+ cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+ atomic_set(&acdb_data.anc_cal.cal_paddr,
+ cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+ atomic_set(&acdb_data.anc_cal.cal_size,
+ cal_block->cal_size);
+done:
+ return;
+}
- acdb_data.anc_cal.cal_kvaddr =
- cal_block->cal_offset + acdb_data.kvaddr;
- acdb_data.anc_cal.cal_paddr =
- cal_block->cal_offset + acdb_data.paddr;
- acdb_data.anc_cal.cal_size =
- cal_block->cal_size;
+void store_afe_cal(int32_t path, struct cal_block *cal_block)
+{
+ pr_debug("%s, path = %d\n", __func__, path);
- mutex_unlock(&acdb_data.acdb_mutex);
+ if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
+ pr_err("%s: offset %d is > pmem_len %ld\n",
+ __func__, cal_block->cal_offset,
+ (long)atomic64_read(&acdb_data.pmem_len));
+ goto done;
+ }
+ if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
+ pr_err("ACDB=> Bad path sent to %s, path: %d\n",
+ __func__, path);
+ goto done;
+ }
+
+ atomic_set(&acdb_data.afe_cal[path].cal_kvaddr,
+ cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+ atomic_set(&acdb_data.afe_cal[path].cal_paddr,
+ cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+ atomic_set(&acdb_data.afe_cal[path].cal_size,
+ cal_block->cal_size);
+done:
+ return;
+}
+
+void get_afe_cal(int32_t path, struct acdb_cal_block *cal_block)
+{
+ pr_debug("%s, path = %d\n", __func__, path);
+
+ if (cal_block == NULL) {
+ pr_err("ACDB=> NULL pointer sent to %s\n", __func__);
+ goto done;
+ }
+ if ((path >= MAX_AUDPROC_TYPES) || (path < 0)) {
+ pr_err("ACDB=> Bad path sent to %s, path: %d\n",
+ __func__, path);
+ goto done;
+ }
+
+ cal_block->cal_kvaddr =
+ atomic_read(&acdb_data.afe_cal[path].cal_kvaddr);
+ cal_block->cal_paddr =
+ atomic_read(&acdb_data.afe_cal[path].cal_paddr);
+ cal_block->cal_size =
+ atomic_read(&acdb_data.afe_cal[path].cal_size);
done:
return;
}
@@ -202,12 +271,10 @@
{
pr_debug("%s, path = %d\n", __func__, path);
- mutex_lock(&acdb_data.acdb_mutex);
-
- if (cal_block->cal_offset > acdb_data.pmem_len) {
+ if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
pr_err("%s: offset %d is > pmem_len %ld\n",
__func__, cal_block->cal_offset,
- acdb_data.pmem_len);
+ (long)atomic64_read(&acdb_data.pmem_len));
goto done;
}
if (path >= MAX_AUDPROC_TYPES) {
@@ -216,15 +283,13 @@
goto done;
}
- acdb_data.audproc_cal[path].cal_kvaddr =
- cal_block->cal_offset + acdb_data.kvaddr;
- acdb_data.audproc_cal[path].cal_paddr =
- cal_block->cal_offset + acdb_data.paddr;
- acdb_data.audproc_cal[path].cal_size =
- cal_block->cal_size;
-
+ atomic_set(&acdb_data.audproc_cal[path].cal_kvaddr,
+ cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+ atomic_set(&acdb_data.audproc_cal[path].cal_paddr,
+ cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+ atomic_set(&acdb_data.audproc_cal[path].cal_size,
+ cal_block->cal_size);
done:
- mutex_unlock(&acdb_data.acdb_mutex);
return;
}
@@ -242,13 +307,12 @@
goto done;
}
- mutex_lock(&acdb_data.acdb_mutex);
-
- cal_block->cal_kvaddr = acdb_data.audproc_cal[path].cal_kvaddr;
- cal_block->cal_paddr = acdb_data.audproc_cal[path].cal_paddr;
- cal_block->cal_size = acdb_data.audproc_cal[path].cal_size;
-
- mutex_unlock(&acdb_data.acdb_mutex);
+ cal_block->cal_kvaddr =
+ atomic_read(&acdb_data.audproc_cal[path].cal_kvaddr);
+ cal_block->cal_paddr =
+ atomic_read(&acdb_data.audproc_cal[path].cal_paddr);
+ cal_block->cal_size =
+ atomic_read(&acdb_data.audproc_cal[path].cal_size);
done:
return;
}
@@ -257,12 +321,10 @@
{
pr_debug("%s, path = %d\n", __func__, path);
- mutex_lock(&acdb_data.acdb_mutex);
-
- if (cal_block->cal_offset > acdb_data.pmem_len) {
+ if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
pr_err("%s: offset %d is > pmem_len %ld\n",
__func__, cal_block->cal_offset,
- acdb_data.pmem_len);
+ (long)atomic64_read(&acdb_data.pmem_len));
goto done;
}
if (path >= MAX_AUDPROC_TYPES) {
@@ -271,15 +333,13 @@
goto done;
}
- acdb_data.audstrm_cal[path].cal_kvaddr =
- cal_block->cal_offset + acdb_data.kvaddr;
- acdb_data.audstrm_cal[path].cal_paddr =
- cal_block->cal_offset + acdb_data.paddr;
- acdb_data.audstrm_cal[path].cal_size =
- cal_block->cal_size;
-
+ atomic_set(&acdb_data.audstrm_cal[path].cal_kvaddr,
+ cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+ atomic_set(&acdb_data.audstrm_cal[path].cal_paddr,
+ cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+ atomic_set(&acdb_data.audstrm_cal[path].cal_size,
+ cal_block->cal_size);
done:
- mutex_unlock(&acdb_data.acdb_mutex);
return;
}
@@ -297,13 +357,12 @@
goto done;
}
- mutex_lock(&acdb_data.acdb_mutex);
-
- cal_block->cal_kvaddr = acdb_data.audstrm_cal[path].cal_kvaddr;
- cal_block->cal_paddr = acdb_data.audstrm_cal[path].cal_paddr;
- cal_block->cal_size = acdb_data.audstrm_cal[path].cal_size;
-
- mutex_unlock(&acdb_data.acdb_mutex);
+ cal_block->cal_kvaddr =
+ atomic_read(&acdb_data.audstrm_cal[path].cal_kvaddr);
+ cal_block->cal_paddr =
+ atomic_read(&acdb_data.audstrm_cal[path].cal_paddr);
+ cal_block->cal_size =
+ atomic_read(&acdb_data.audstrm_cal[path].cal_size);
done:
return;
}
@@ -312,12 +371,10 @@
{
pr_debug("%s, path = %d\n", __func__, path);
- mutex_lock(&acdb_data.acdb_mutex);
-
- if (cal_block->cal_offset > acdb_data.pmem_len) {
+ if (cal_block->cal_offset > atomic64_read(&acdb_data.pmem_len)) {
pr_err("%s: offset %d is > pmem_len %ld\n",
__func__, cal_block->cal_offset,
- acdb_data.pmem_len);
+ (long)atomic64_read(&acdb_data.pmem_len));
goto done;
}
if (path >= MAX_AUDPROC_TYPES) {
@@ -326,15 +383,13 @@
goto done;
}
- acdb_data.audvol_cal[path].cal_kvaddr =
- cal_block->cal_offset + acdb_data.kvaddr;
- acdb_data.audvol_cal[path].cal_paddr =
- cal_block->cal_offset + acdb_data.paddr;
- acdb_data.audvol_cal[path].cal_size =
- cal_block->cal_size;
-
+ atomic_set(&acdb_data.audvol_cal[path].cal_kvaddr,
+ cal_block->cal_offset + atomic64_read(&acdb_data.kvaddr));
+ atomic_set(&acdb_data.audvol_cal[path].cal_paddr,
+ cal_block->cal_offset + atomic64_read(&acdb_data.paddr));
+ atomic_set(&acdb_data.audvol_cal[path].cal_size,
+ cal_block->cal_size);
done:
- mutex_unlock(&acdb_data.acdb_mutex);
return;
}
@@ -352,13 +407,12 @@
goto done;
}
- mutex_lock(&acdb_data.acdb_mutex);
-
- cal_block->cal_kvaddr = acdb_data.audvol_cal[path].cal_kvaddr;
- cal_block->cal_paddr = acdb_data.audvol_cal[path].cal_paddr;
- cal_block->cal_size = acdb_data.audvol_cal[path].cal_size;
-
- mutex_unlock(&acdb_data.acdb_mutex);
+ cal_block->cal_kvaddr =
+ atomic_read(&acdb_data.audvol_cal[path].cal_kvaddr);
+ cal_block->cal_paddr =
+ atomic_read(&acdb_data.audvol_cal[path].cal_paddr);
+ cal_block->cal_size =
+ atomic_read(&acdb_data.audvol_cal[path].cal_size);
done:
return;
}
@@ -375,31 +429,28 @@
goto done;
}
-
- mutex_lock(&acdb_data.acdb_mutex);
-
- acdb_data.vocproc_total_cal_size = 0;
+ atomic_set(&acdb_data.vocproc_total_cal_size, 0);
for (i = 0; i < len; i++) {
- if (cal_blocks[i].cal_offset > acdb_data.pmem_len) {
+ if (cal_blocks[i].cal_offset >
+ atomic64_read(&acdb_data.pmem_len)) {
pr_err("%s: offset %d is > pmem_len %ld\n",
__func__, cal_blocks[i].cal_offset,
- acdb_data.pmem_len);
- acdb_data.vocproc_cal[i].cal_size = 0;
+ (long)atomic64_read(&acdb_data.pmem_len));
+ atomic_set(&acdb_data.vocproc_cal[i].cal_size, 0);
} else {
- acdb_data.vocproc_total_cal_size +=
- cal_blocks[i].cal_size;
- acdb_data.vocproc_cal[i].cal_size =
- cal_blocks[i].cal_size;
- acdb_data.vocproc_cal[i].cal_paddr =
+ atomic_add(cal_blocks[i].cal_size,
+ &acdb_data.vocproc_total_cal_size);
+ atomic_set(&acdb_data.vocproc_cal[i].cal_size,
+ cal_blocks[i].cal_size);
+ atomic_set(&acdb_data.vocproc_cal[i].cal_paddr,
cal_blocks[i].cal_offset +
- acdb_data.paddr;
- acdb_data.vocproc_cal[i].cal_kvaddr =
+ atomic64_read(&acdb_data.paddr));
+ atomic_set(&acdb_data.vocproc_cal[i].cal_kvaddr,
cal_blocks[i].cal_offset +
- acdb_data.kvaddr;
+ atomic64_read(&acdb_data.kvaddr));
}
}
- acdb_data.vocproc_cal_size = len;
- mutex_unlock(&acdb_data.acdb_mutex);
+ atomic_set(&acdb_data.vocproc_cal_size, len);
done:
return;
}
@@ -413,12 +464,8 @@
goto done;
}
- mutex_lock(&acdb_data.acdb_mutex);
-
- cal_data->num_cal_blocks = acdb_data.vocproc_cal_size;
+ cal_data->num_cal_blocks = atomic_read(&acdb_data.vocproc_cal_size);
cal_data->cal_blocks = &acdb_data.vocproc_cal[0];
-
- mutex_unlock(&acdb_data.acdb_mutex);
done:
return;
}
@@ -434,30 +481,28 @@
goto done;
}
- mutex_lock(&acdb_data.acdb_mutex);
-
- acdb_data.vocstrm_total_cal_size = 0;
+ atomic_set(&acdb_data.vocstrm_total_cal_size, 0);
for (i = 0; i < len; i++) {
- if (cal_blocks[i].cal_offset > acdb_data.pmem_len) {
+ if (cal_blocks[i].cal_offset >
+ atomic64_read(&acdb_data.pmem_len)) {
pr_err("%s: offset %d is > pmem_len %ld\n",
__func__, cal_blocks[i].cal_offset,
- acdb_data.pmem_len);
- acdb_data.vocstrm_cal[i].cal_size = 0;
+ (long)atomic64_read(&acdb_data.pmem_len));
+ atomic_set(&acdb_data.vocstrm_cal[i].cal_size, 0);
} else {
- acdb_data.vocstrm_total_cal_size +=
- cal_blocks[i].cal_size;
- acdb_data.vocstrm_cal[i].cal_size =
- cal_blocks[i].cal_size;
- acdb_data.vocstrm_cal[i].cal_paddr =
+ atomic_add(cal_blocks[i].cal_size,
+ &acdb_data.vocstrm_total_cal_size);
+ atomic_set(&acdb_data.vocstrm_cal[i].cal_size,
+ cal_blocks[i].cal_size);
+ atomic_set(&acdb_data.vocstrm_cal[i].cal_paddr,
cal_blocks[i].cal_offset +
- acdb_data.paddr;
- acdb_data.vocstrm_cal[i].cal_kvaddr =
+ atomic64_read(&acdb_data.paddr));
+ atomic_set(&acdb_data.vocstrm_cal[i].cal_kvaddr,
cal_blocks[i].cal_offset +
- acdb_data.kvaddr;
+ atomic64_read(&acdb_data.kvaddr));
}
}
- acdb_data.vocstrm_cal_size = len;
- mutex_unlock(&acdb_data.acdb_mutex);
+ atomic_set(&acdb_data.vocstrm_cal_size, len);
done:
return;
}
@@ -471,12 +516,8 @@
goto done;
}
- mutex_lock(&acdb_data.acdb_mutex);
-
- cal_data->num_cal_blocks = acdb_data.vocstrm_cal_size;
+ cal_data->num_cal_blocks = atomic_read(&acdb_data.vocstrm_cal_size);
cal_data->cal_blocks = &acdb_data.vocstrm_cal[0];
-
- mutex_unlock(&acdb_data.acdb_mutex);
done:
return;
}
@@ -492,30 +533,28 @@
goto done;
}
- mutex_lock(&acdb_data.acdb_mutex);
-
- acdb_data.vocvol_total_cal_size = 0;
+ atomic_set(&acdb_data.vocvol_total_cal_size, 0);
for (i = 0; i < len; i++) {
- if (cal_blocks[i].cal_offset > acdb_data.pmem_len) {
+ if (cal_blocks[i].cal_offset >
+ atomic64_read(&acdb_data.pmem_len)) {
pr_err("%s: offset %d is > pmem_len %ld\n",
__func__, cal_blocks[i].cal_offset,
- acdb_data.pmem_len);
- acdb_data.vocvol_cal[i].cal_size = 0;
+ (long)atomic64_read(&acdb_data.pmem_len));
+ atomic_set(&acdb_data.vocvol_cal[i].cal_size, 0);
} else {
- acdb_data.vocvol_total_cal_size +=
- cal_blocks[i].cal_size;
- acdb_data.vocvol_cal[i].cal_size =
- cal_blocks[i].cal_size;
- acdb_data.vocvol_cal[i].cal_paddr =
+ atomic_add(cal_blocks[i].cal_size,
+ &acdb_data.vocvol_total_cal_size);
+ atomic_set(&acdb_data.vocvol_cal[i].cal_size,
+ cal_blocks[i].cal_size);
+ atomic_set(&acdb_data.vocvol_cal[i].cal_paddr,
cal_blocks[i].cal_offset +
- acdb_data.paddr;
- acdb_data.vocvol_cal[i].cal_kvaddr =
+ atomic64_read(&acdb_data.paddr));
+ atomic_set(&acdb_data.vocvol_cal[i].cal_kvaddr,
cal_blocks[i].cal_offset +
- acdb_data.kvaddr;
+ atomic64_read(&acdb_data.kvaddr));
}
}
- acdb_data.vocvol_cal_size = len;
- mutex_unlock(&acdb_data.acdb_mutex);
+ atomic_set(&acdb_data.vocvol_cal_size, len);
done:
return;
}
@@ -529,12 +568,8 @@
goto done;
}
- mutex_lock(&acdb_data.acdb_mutex);
-
- cal_data->num_cal_blocks = acdb_data.vocvol_cal_size;
+ cal_data->num_cal_blocks = atomic_read(&acdb_data.vocvol_cal_size);
cal_data->cal_blocks = &acdb_data.vocvol_cal[0];
-
- mutex_unlock(&acdb_data.acdb_mutex);
done:
return;
}
@@ -543,12 +578,8 @@
{
pr_debug("%s\n", __func__);
- mutex_lock(&acdb_data.acdb_mutex);
-
- acdb_data.sidetone_cal.enable = cal_data->enable;
- acdb_data.sidetone_cal.gain = cal_data->gain;
-
- mutex_unlock(&acdb_data.acdb_mutex);
+ atomic_set(&acdb_data.sidetone_cal.enable, cal_data->enable);
+ atomic_set(&acdb_data.sidetone_cal.gain, cal_data->gain);
}
@@ -561,12 +592,8 @@
goto done;
}
- mutex_lock(&acdb_data.acdb_mutex);
-
- cal_data->enable = acdb_data.sidetone_cal.enable;
- cal_data->gain = acdb_data.sidetone_cal.gain;
-
- mutex_unlock(&acdb_data.acdb_mutex);
+ cal_data->enable = atomic_read(&acdb_data.sidetone_cal.enable);
+ cal_data->gain = atomic_read(&acdb_data.sidetone_cal.gain);
done:
return;
}
@@ -574,14 +601,12 @@
static int acdb_open(struct inode *inode, struct file *f)
{
s32 result = 0;
- pr_info("%s\n", __func__);
+ pr_debug("%s\n", __func__);
- mutex_lock(&acdb_data.acdb_mutex);
- if (acdb_data.pmem_fd) {
- pr_info("%s: ACDB opened but PMEM allocated, using existing PMEM!\n",
+ if (atomic_read(&acdb_data.pmem_fd)) {
+ pr_debug("%s: ACDB opened but PMEM allocated, using existing PMEM!\n",
__func__);
}
- mutex_unlock(&acdb_data.acdb_mutex);
atomic_inc(&usage_count);
return result;
@@ -589,9 +614,11 @@
static int deregister_pmem(void)
{
- if (acdb_data.pmem_fd) {
+ if (atomic_read(&acdb_data.pmem_fd)) {
+ mutex_lock(&acdb_data.acdb_mutex);
put_pmem_file(acdb_data.file);
- acdb_data.pmem_fd = 0;
+ mutex_unlock(&acdb_data.acdb_mutex);
+ atomic_set(&acdb_data.pmem_fd, 0);
}
return 0;
}
@@ -599,19 +626,30 @@
static int register_pmem(void)
{
int result;
+ unsigned long paddr;
+ unsigned long kvaddr;
+ unsigned long pmem_len;
- result = get_pmem_file(acdb_data.pmem_fd, &acdb_data.paddr,
- &acdb_data.kvaddr, &acdb_data.pmem_len,
+ mutex_lock(&acdb_data.acdb_mutex);
+ result = get_pmem_file(atomic_read(&acdb_data.pmem_fd),
+ &paddr, &kvaddr, &pmem_len,
&acdb_data.file);
+ mutex_unlock(&acdb_data.acdb_mutex);
if (result != 0) {
- acdb_data.pmem_fd = 0;
+ atomic_set(&acdb_data.pmem_fd, 0);
+ atomic64_set(&acdb_data.pmem_len, 0);
pr_err("%s: Could not register PMEM!!!\n", __func__);
goto done;
}
+ atomic64_set(&acdb_data.paddr, paddr);
+ atomic64_set(&acdb_data.kvaddr, kvaddr);
+ atomic64_set(&acdb_data.pmem_len, pmem_len);
pr_debug("AUDIO_REGISTER_PMEM done! paddr = 0x%lx, "
- "kvaddr = 0x%lx, len = x%lx\n", acdb_data.paddr,
- acdb_data.kvaddr, acdb_data.pmem_len);
+ "kvaddr = 0x%lx, len = x%lx\n",
+ (long)atomic64_read(&acdb_data.paddr),
+ (long)atomic64_read(&acdb_data.kvaddr),
+ (long)atomic64_read(&acdb_data.pmem_len));
done:
return result;
@@ -619,37 +657,33 @@
static long acdb_ioctl(struct file *f,
unsigned int cmd, unsigned long arg)
{
- s32 result = 0;
- s32 audproc_path;
- s32 size;
- u32 topology;
+ int32_t result = 0;
+ int32_t size;
+ int32_t pmem_fd;
+ uint32_t topology;
struct cal_block data[MAX_NETWORKS];
pr_debug("%s\n", __func__);
switch (cmd) {
case AUDIO_REGISTER_PMEM:
pr_debug("AUDIO_REGISTER_PMEM\n");
- mutex_lock(&acdb_data.acdb_mutex);
- if (acdb_data.pmem_fd) {
+ if (atomic_read(&acdb_data.pmem_fd)) {
deregister_pmem();
- pr_info("Remove the existing PMEM\n");
+ pr_debug("Remove the existing PMEM\n");
}
- if (copy_from_user(&acdb_data.pmem_fd, (void *)arg,
- sizeof(acdb_data.pmem_fd))) {
+ if (copy_from_user(&pmem_fd, (void *)arg, sizeof(pmem_fd))) {
pr_err("%s: fail to copy pmem handle!\n", __func__);
result = -EFAULT;
} else {
+ atomic_set(&acdb_data.pmem_fd, pmem_fd);
result = register_pmem();
}
- mutex_unlock(&acdb_data.acdb_mutex);
goto done;
case AUDIO_DEREGISTER_PMEM:
pr_debug("AUDIO_DEREGISTER_PMEM\n");
- mutex_lock(&acdb_data.acdb_mutex);
deregister_pmem();
- mutex_unlock(&acdb_data.acdb_mutex);
goto done;
case AUDIO_SET_VOICE_RX_TOPOLOGY:
if (copy_from_user(&topology, (void *)arg,
@@ -721,45 +755,51 @@
switch (cmd) {
case AUDIO_SET_AUDPROC_TX_CAL:
- audproc_path = TX_CAL;
if (size > sizeof(struct cal_block))
pr_err("%s: More Audproc Cal then expected, "
"size received: %d\n", __func__, size);
- store_audproc_cal(audproc_path, data);
+ store_audproc_cal(TX_CAL, data);
break;
case AUDIO_SET_AUDPROC_RX_CAL:
- audproc_path = RX_CAL;
if (size > sizeof(struct cal_block))
pr_err("%s: More Audproc Cal then expected, "
"size received: %d\n", __func__, size);
- store_audproc_cal(audproc_path, data);
+ store_audproc_cal(RX_CAL, data);
break;
case AUDIO_SET_AUDPROC_TX_STREAM_CAL:
- audproc_path = TX_CAL;
if (size > sizeof(struct cal_block))
pr_err("%s: More Audproc Cal then expected, "
"size received: %d\n", __func__, size);
- store_audstrm_cal(audproc_path, data);
+ store_audstrm_cal(TX_CAL, data);
break;
case AUDIO_SET_AUDPROC_RX_STREAM_CAL:
- audproc_path = RX_CAL;
if (size > sizeof(struct cal_block))
pr_err("%s: More Audproc Cal then expected, "
"size received: %d\n", __func__, size);
- store_audstrm_cal(audproc_path, data);
+ store_audstrm_cal(RX_CAL, data);
break;
case AUDIO_SET_AUDPROC_TX_VOL_CAL:
- audproc_path = TX_CAL;
if (size > sizeof(struct cal_block))
pr_err("%s: More Audproc Cal then expected, "
"size received: %d\n", __func__, size);
- store_audvol_cal(audproc_path, data);
+ store_audvol_cal(TX_CAL, data);
case AUDIO_SET_AUDPROC_RX_VOL_CAL:
- audproc_path = RX_CAL;
if (size > sizeof(struct cal_block))
pr_err("%s: More Audproc Cal then expected, "
"size received: %d\n", __func__, size);
- store_audvol_cal(audproc_path, data);
+ store_audvol_cal(RX_CAL, data);
+ break;
+ case AUDIO_SET_AFE_TX_CAL:
+ if (size > sizeof(struct cal_block))
+ pr_err("%s: More AFE Cal then expected, "
+ "size received: %d\n", __func__, size);
+ store_afe_cal(TX_CAL, data);
+ break;
+ case AUDIO_SET_AFE_RX_CAL:
+ if (size > sizeof(struct cal_block))
+ pr_err("%s: More AFE Cal then expected, "
+ "size received: %d\n", __func__, size);
+ store_afe_cal(RX_CAL, data);
break;
case AUDIO_SET_VOCPROC_CAL:
store_vocproc_cal(size / sizeof(struct cal_block), data);
@@ -794,14 +834,13 @@
pr_debug("%s\n", __func__);
- mutex_lock(&acdb_data.acdb_mutex);
- if (acdb_data.pmem_fd) {
- if (size <= acdb_data.pmem_len) {
+ if (atomic_read(&acdb_data.pmem_fd)) {
+ if (size <= atomic64_read(&acdb_data.pmem_len)) {
vma->vm_page_prot = pgprot_noncached(
vma->vm_page_prot);
result = remap_pfn_range(vma,
vma->vm_start,
- acdb_data.paddr >> PAGE_SHIFT,
+ atomic64_read(&acdb_data.paddr) >> PAGE_SHIFT,
size,
vma->vm_page_prot);
} else {
@@ -812,7 +851,6 @@
pr_err("%s: PMEM is not allocated, yet!\n", __func__);
result = -ENODEV;
}
- mutex_unlock(&acdb_data.acdb_mutex);
return result;
}
@@ -824,16 +862,13 @@
atomic_dec(&usage_count);
atomic_read(&usage_count);
- pr_info("%s: ref count %d!\n", __func__,
+ pr_debug("%s: ref count %d!\n", __func__,
atomic_read(&usage_count));
- if (atomic_read(&usage_count) >= 1) {
+ if (atomic_read(&usage_count) >= 1)
result = -EBUSY;
- } else {
- mutex_lock(&acdb_data.acdb_mutex);
+ else
result = deregister_pmem();
- mutex_unlock(&acdb_data.acdb_mutex);
- }
return result;
}
diff --git a/arch/arm/mach-msm/qdsp6v2/q6voice.c b/arch/arm/mach-msm/qdsp6v2/q6voice.c
index 34169c0..12a02c5 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6voice.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6voice.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
@@ -791,7 +791,7 @@
struct apr_hdr cvs_cal_cmd_hdr;
uint32_t *cmd_buf;
struct acdb_cal_data cal_data;
- struct acdb_cal_block *cal_blk;
+ struct acdb_atomic_cal_block *cal_blk;
int32_t cal_size_per_network;
uint32_t *cal_data_per_network;
int index = 0;
@@ -830,11 +830,12 @@
pr_debug("cal_blk =%x\n", (uint32_t)cal_data.cal_blocks);
for (; index < cal_data.num_cal_blocks; index++) {
- cal_size_per_network = cal_blk[index].cal_size;
+ cal_size_per_network = atomic_read(&cal_blk[index].cal_size);
pr_debug(" cal size =%d\n", cal_size_per_network);
if (cal_size_per_network >= BUFFER_PAYLOAD_SIZE)
pr_err("Cal size is too big\n");
- cal_data_per_network = (u32 *)cal_blk[index].cal_kvaddr;
+ cal_data_per_network =
+ (u32 *)atomic_read(&cal_blk[index].cal_kvaddr);
pr_debug(" cal data=%x\n", (uint32_t)cal_data_per_network);
cvs_cal_cmd_hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
cal_size_per_network);
@@ -868,7 +869,7 @@
struct apr_hdr cvp_cal_cmd_hdr;
uint32_t *cmd_buf;
struct acdb_cal_data cal_data;
- struct acdb_cal_block *cal_blk;
+ struct acdb_atomic_cal_block *cal_blk;
int32_t cal_size_per_network;
uint32_t *cal_data_per_network;
int index = 0;
@@ -907,11 +908,12 @@
pr_debug(" cal_blk =%x\n", (uint32_t)cal_data.cal_blocks);
for (; index < cal_data.num_cal_blocks; index++) {
- cal_size_per_network = cal_blk[index].cal_size;
+ cal_size_per_network = atomic_read(&cal_blk[index].cal_size);
if (cal_size_per_network >= BUFFER_PAYLOAD_SIZE)
pr_err("Cal size is too big\n");
pr_debug(" cal size =%d\n", cal_size_per_network);
- cal_data_per_network = (u32 *)cal_blk[index].cal_kvaddr;
+ cal_data_per_network =
+ (u32 *)atomic_read(&cal_blk[index].cal_kvaddr);
pr_debug(" cal data=%x\n", (uint32_t)cal_data_per_network);
cvp_cal_cmd_hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
@@ -945,11 +947,9 @@
struct apr_hdr cvp_vol_cal_cmd_hdr;
uint32_t *cmd_buf;
struct acdb_cal_data cal_data;
- struct acdb_cal_block *cal_blk;
+ struct acdb_atomic_cal_block *cal_blk;
int32_t cal_size_per_network;
uint32_t *cal_data_per_network;
- uint32_t num_volume_steps;
- int offset = 0;
int index = 0;
int ret = 0;
void *apr_cvp = voice_get_apr_cvp();
@@ -986,27 +986,18 @@
pr_debug("Cal_blk =%x\n", (uint32_t)cal_data.cal_blocks);
for (; index < cal_data.num_cal_blocks; index++) {
- cal_size_per_network = cal_blk[index].cal_size;
- cal_data_per_network = (u32 *)cal_blk[index].cal_kvaddr;
-
- /* Number of volume steps are only included in the */
- /* first block, need to be inserted into the rest */
- if (index != 0) {
- offset = sizeof(num_volume_steps);
- memcpy(cmd_buf + (APR_HDR_SIZE / sizeof(uint32_t)),
- &num_volume_steps, offset);
- } else {
- num_volume_steps = *cal_data_per_network;
- }
+ cal_size_per_network = atomic_read(&cal_blk[index].cal_size);
+ cal_data_per_network =
+ (u32 *)atomic_read(&cal_blk[index].cal_kvaddr);
pr_debug("Cal size =%d, index=%d\n", cal_size_per_network,
index);
pr_debug("Cal data=%x\n", (uint32_t)cal_data_per_network);
cvp_vol_cal_cmd_hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- cal_size_per_network + offset);
+ cal_size_per_network);
memcpy(cmd_buf, &cvp_vol_cal_cmd_hdr, APR_HDR_SIZE);
- memcpy(cmd_buf + (APR_HDR_SIZE / sizeof(uint32_t)) +
- offset, cal_data_per_network, cal_size_per_network);
+ memcpy(cmd_buf + (APR_HDR_SIZE / sizeof(uint32_t)),
+ cal_data_per_network, cal_size_per_network);
pr_debug("Send vol table\n");
v->cvp_state = CMD_STATUS_FAIL;
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/gpu/ion/ion.c b/drivers/gpu/ion/ion.c
index 34145fe..386593f5 100644
--- a/drivers/gpu/ion/ion.c
+++ b/drivers/gpu/ion/ion.c
@@ -1315,12 +1315,14 @@
/* now map it to userspace */
ret = buffer->heap->ops->map_user(buffer->heap, buffer, vma,
flags);
- mutex_unlock(&buffer->lock);
+
+ buffer->umap_cnt++;
if (ret) {
pr_err("%s: failure mapping buffer to userspace\n",
__func__);
goto err2;
}
+ mutex_unlock(&buffer->lock);
vma->vm_ops = &ion_vm_ops;
/* move the handle into the vm_private_data so we can access it from
@@ -1335,6 +1337,7 @@
err2:
buffer->umap_cnt--;
+ mutex_unlock(&buffer->lock);
/* drop the reference to the handle */
err1:
ion_handle_put(handle);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index e9c3f08..34e83a0 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -497,8 +497,8 @@
struct kgsl_device, display_off);
KGSL_PWR_WARN(device, "early suspend start\n");
mutex_lock(&device->mutex);
- kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
kgsl_pwrctrl_stop_work(device);
+ kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
kgsl_pwrctrl_sleep(device);
mutex_unlock(&device->mutex);
KGSL_PWR_WARN(device, "early suspend end\n");
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index c29da39..60bd232 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -622,7 +622,10 @@
KGSL_PWR_INFO(device, "idle timer expired device %d\n", device->id);
if (device->requested_state == KGSL_STATE_NONE) {
- kgsl_pwrctrl_request_state(device, KGSL_STATE_SLEEP);
+ if (device->pwrctrl.restore_slumber)
+ kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
+ else
+ kgsl_pwrctrl_request_state(device, KGSL_STATE_SLEEP);
/* Have work run in a non-interrupt context. */
queue_work(device->work_queue, &device->idle_check_ws);
}
@@ -631,9 +634,33 @@
void kgsl_pre_hwaccess(struct kgsl_device *device)
{
BUG_ON(!mutex_is_locked(&device->mutex));
- if (device->state & (KGSL_STATE_SLEEP | KGSL_STATE_NAP |
- KGSL_STATE_SLUMBER))
+ switch (device->state) {
+ case KGSL_STATE_ACTIVE:
+ return;
+ case KGSL_STATE_NAP:
+ case KGSL_STATE_SLEEP:
+ case KGSL_STATE_SLUMBER:
kgsl_pwrctrl_wake(device);
+ break;
+ case KGSL_STATE_SUSPEND:
+ kgsl_check_suspended(device);
+ break;
+ case KGSL_STATE_INIT:
+ case KGSL_STATE_HUNG:
+ case KGSL_STATE_DUMP_AND_RECOVER:
+ if (test_bit(KGSL_PWRFLAGS_CLK_ON,
+ &device->pwrctrl.power_flags))
+ break;
+ else
+ KGSL_PWR_ERR(device,
+ "hw access while clocks off from state %d\n",
+ device->state);
+ break;
+ default:
+ KGSL_PWR_ERR(device, "hw access while in unknown state %d\n",
+ device->state);
+ break;
+ }
}
EXPORT_SYMBOL(kgsl_pre_hwaccess);
@@ -764,17 +791,10 @@
/* Work through the legal state transitions */
switch (device->requested_state) {
case KGSL_STATE_NAP:
- if (device->pwrctrl.restore_slumber) {
- kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
- break;
- }
status = _nap(device);
break;
case KGSL_STATE_SLEEP:
- if (device->pwrctrl.restore_slumber)
- status = _slumber(device);
- else
- status = _sleep(device);
+ status = _sleep(device);
break;
case KGSL_STATE_SLUMBER:
status = _slumber(device);
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 5ed2ad7..ff0e00d 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -97,6 +97,7 @@
struct hci_fm_riva_poke riva_data_req;
struct hci_fm_ssbi_req ssbi_data_accs;
struct hci_fm_ssbi_peek ssbi_peek_reg;
+ struct hci_fm_sig_threshold_rsp sig_th;
};
static struct video_device *priv_videodev;
@@ -1587,13 +1588,11 @@
{
struct hci_fm_sig_threshold_rsp *rsp = (void *)skb->data;
struct iris_device *radio = video_get_drvdata(video_get_dev());
- struct v4l2_control *v4l_ctl = radio->g_ctl;
if (rsp->status)
return;
- v4l_ctl->value = rsp->sig_threshold;
-
+ memcpy(&radio->sig_th, rsp, sizeof(struct hci_fm_sig_threshold_rsp));
radio_hci_req_complete(hdev, rsp->status);
}
@@ -2433,6 +2432,11 @@
break;
case V4L2_CID_PRIVATE_IRIS_SIGNAL_TH:
retval = hci_cmd(HCI_FM_GET_SIGNAL_TH_CMD, radio->fm_hdev);
+ if (retval < 0) {
+ FMDERR("Error in get signal threshold %d\n", retval);
+ return retval;
+ }
+ ctrl->value = radio->sig_th.sig_threshold;
break;
case V4L2_CID_PRIVATE_IRIS_SRCH_PTY:
ctrl->value = radio->srch_rds.srch_pty;
diff --git a/drivers/media/video/msm/msm_camera.c b/drivers/media/video/msm/msm_camera.c
index 65b33c2..dbf0eae 100644
--- a/drivers/media/video/msm/msm_camera.c
+++ b/drivers/media/video/msm/msm_camera.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-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
@@ -279,16 +279,18 @@
{
if (info->offset < len &&
info->offset + info->len <= len &&
- info->y_off < len &&
- info->cbcr_off < len)
+ info->planar0_off < len &&
+ info->planar1_off < len &&
+ info->planar2_off < len)
return 0;
- pr_err("%s: check failed: off %d len %d y %d cbcr %d (total len %d)\n",
+ pr_err("%s: check failed: off %d len %d y 0x%x cbcr_p1 0x%x p2_add 0x%x(total len %d)\n",
__func__,
info->offset,
info->len,
- info->y_off,
- info->cbcr_off,
+ info->planar0_off,
+ info->planar1_off,
+ info->planar2_off,
len);
return -EINVAL;
}
@@ -352,8 +354,10 @@
hlist_add_head(&(region->list), ptype);
spin_unlock_irqrestore(pmem_spinlock, flags);
- CDBG("%s: type %d, paddr 0x%lx, vaddr 0x%lx\n",
- __func__, info->type, paddr, (unsigned long)info->vaddr);
+ CDBG("%s: type %d, paddr 0x%lx, vaddr 0x%lx p0_add = 0x%x"
+ "p1_addr = 0x%x p2_addr = 0x%x\n",
+ __func__, info->type, paddr, (unsigned long)info->vaddr,
+ info->planar0_off, info->planar1_off, info->planar2_off);
return 0;
out2:
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -439,8 +443,9 @@
}
static int msm_pmem_frame_ptov_lookup(struct msm_sync *sync,
- unsigned long pyaddr,
- unsigned long pcbcraddr,
+ unsigned long p0addr,
+ unsigned long p1addr,
+ unsigned long p2addr,
struct msm_pmem_info *pmem_info,
int clear_active)
{
@@ -450,10 +455,10 @@
spin_lock_irqsave(&sync->pmem_frame_spinlock, flags);
hlist_for_each_entry_safe(region, node, n, &sync->pmem_frames, list) {
- if (pyaddr == (region->paddr + region->info.y_off) &&
- pcbcraddr == (region->paddr +
- region->info.cbcr_off) &&
- region->info.active) {
+ if (p0addr == (region->paddr + region->info.planar0_off) &&
+ p1addr == (region->paddr + region->info.planar1_off) &&
+ p2addr == (region->paddr + region->info.planar2_off) &&
+ region->info.active) {
/* offset since we could pass vaddr inside
* a registerd pmem buffer
*/
@@ -466,12 +471,13 @@
}
}
/* After lookup failure, dump all the list entries... */
- pr_err("%s, for pyaddr 0x%lx, pcbcraddr 0x%lx\n",
- __func__, pyaddr, pcbcraddr);
+ pr_err("%s, for plane0 addr = 0x%lx, plane1 addr = 0x%lx plane2 addr = 0x%lx\n",
+ __func__, p0addr, p1addr, p2addr);
hlist_for_each_entry_safe(region, node, n, &sync->pmem_frames, list) {
- pr_err("listed pyaddr 0x%lx, pcbcraddr 0x%lx, active = %d",
- (region->paddr + region->info.y_off),
- (region->paddr + region->info.cbcr_off),
+ pr_err("listed p0addr 0x%lx, p1addr 0x%lx, p2addr 0x%lx, active = %d",
+ (region->paddr + region->info.planar0_off),
+ (region->paddr + region->info.planar1_off),
+ (region->paddr + region->info.planar2_off),
region->info.active);
}
@@ -480,7 +486,7 @@
}
static int msm_pmem_frame_ptov_lookup2(struct msm_sync *sync,
- unsigned long pyaddr,
+ unsigned long p0_phy,
struct msm_pmem_info *pmem_info,
int clear_active)
{
@@ -490,7 +496,7 @@
spin_lock_irqsave(&sync->pmem_frame_spinlock, flags);
hlist_for_each_entry_safe(region, node, n, &sync->pmem_frames, list) {
- if (pyaddr == (region->paddr + region->info.y_off) &&
+ if (p0_phy == (region->paddr + region->info.planar0_off) &&
region->info.active) {
/* offset since we could pass vaddr inside
* a registerd pmem buffer
@@ -541,8 +547,8 @@
}
static unsigned long msm_pmem_frame_vtop_lookup(struct msm_sync *sync,
- unsigned long buffer,
- uint32_t yoff, uint32_t cbcroff, int fd, int change_flag)
+ unsigned long buffer, uint32_t p0_off, uint32_t p1_off,
+ uint32_t p2_off, int fd, int change_flag)
{
struct msm_pmem_region *region;
struct hlist_node *node, *n;
@@ -552,8 +558,9 @@
hlist_for_each_entry_safe(region,
node, n, &sync->pmem_frames, list) {
if (((unsigned long)(region->info.vaddr) == buffer) &&
- (region->info.y_off == yoff) &&
- (region->info.cbcr_off == cbcroff) &&
+ (region->info.planar0_off == p0_off) &&
+ (region->info.planar1_off == p1_off) &&
+ (region->info.planar2_off == p2_off) &&
(region->info.fd == fd) &&
(region->info.active == 0)) {
if (change_flag)
@@ -564,13 +571,16 @@
}
}
/* After lookup failure, dump all the list entries... */
- pr_err("%s, failed for vaddr 0x%lx, yoff %d cbcroff %d\n",
- __func__, buffer, yoff, cbcroff);
+ pr_err("%s, failed for vaddr 0x%lx, p0_off %d p1_off %d\n",
+ __func__, buffer, p0_off, p1_off);
hlist_for_each_entry_safe(region, node, n, &sync->pmem_frames, list) {
- pr_err("listed vaddr 0x%p, cbcroff %d, active = %d",
- (region->info.vaddr),
- (region->info.cbcr_off),
- region->info.active);
+ pr_err("%s, listed vaddr 0x%lx, r_p0 = 0x%x p0_off 0x%x"
+ "r_p1 = 0x%x, p1_off 0x%x, r_p2 = 0x%x, p2_off = 0x%x"
+ " active = %d\n", __func__, buffer,
+ region->info.planar0_off,
+ p0_off, region->info.planar1_off,
+ p1_off, region->info.planar2_off, p2_off,
+ region->info.active);
}
spin_unlock_irqrestore(&sync->pmem_frame_spinlock, flags);
@@ -741,33 +751,36 @@
vdata = (struct msm_vfe_resp *)(qcmd->command);
pphy = &vdata->phy;
+ CDBG("%s, pphy->p2_phy = 0x%x\n", __func__, pphy->p2_phy);
rc = msm_pmem_frame_ptov_lookup(sync,
- pphy->y_phy,
- pphy->cbcr_phy,
+ pphy->p0_phy,
+ pphy->p1_phy,
+ pphy->p2_phy,
&pmem_info,
1); /* Clear the active flag */
if (rc < 0) {
- pr_err("%s: cannot get frame, invalid lookup address "
- "y %x cbcr %x\n",
- __func__,
- pphy->y_phy,
- pphy->cbcr_phy);
+ pr_err("%s: cannot get frame, invalid lookup address"
+ "plane0 add %x plane1 add %x plane2 add%x\n",
+ __func__,
+ pphy->p0_phy,
+ pphy->p1_phy,
+ pphy->p2_phy);
goto err;
}
frame->ts = qcmd->ts;
frame->buffer = (unsigned long)pmem_info.vaddr;
- frame->y_off = pmem_info.y_off;
- frame->cbcr_off = pmem_info.cbcr_off;
+ frame->planar0_off = pmem_info.planar0_off;
+ frame->planar1_off = pmem_info.planar1_off;
+ frame->planar2_off = pmem_info.planar2_off;
frame->fd = pmem_info.fd;
frame->path = vdata->phy.output_id;
frame->frame_id = vdata->phy.frame_id;
-
- CDBG("%s: y %x, cbcr %x, qcmd %x, virt_addr %x\n",
- __func__,
- pphy->y_phy, pphy->cbcr_phy, (int) qcmd, (int) frame->buffer);
+ CDBG("%s: plane0 %x, plane1 %x, plane2 %x,qcmd %x, virt_addr %x\n",
+ __func__, pphy->p0_phy, pphy->p1_phy, pphy->p2_phy,
+ (int) qcmd, (int) frame->buffer);
err:
free_qcmd(qcmd);
@@ -1078,8 +1091,8 @@
return -EINVAL;
}
- rc = msm_pmem_frame_ptov_lookup(sync, data->phy.y_phy,
- data->phy.cbcr_phy, &pinfo,
+ rc = msm_pmem_frame_ptov_lookup(sync, data->phy.p0_phy,
+ data->phy.p1_phy, data->phy.p2_phy, &pinfo,
0); /* do not clear the active flag */
if (rc < 0) {
@@ -1088,8 +1101,8 @@
}
buf.fmain.buffer = (unsigned long)pinfo.vaddr;
- buf.fmain.y_off = pinfo.y_off;
- buf.fmain.cbcr_off = pinfo.cbcr_off;
+ buf.fmain.planar0_off = pinfo.planar0_off;
+ buf.fmain.planar1_off = pinfo.planar1_off;
buf.fmain.fd = pinfo.fd;
CDBG("%s: buf 0x%x fd %d\n", __func__, (unsigned int)buf.fmain.buffer,
@@ -1119,14 +1132,14 @@
buf.type = OUTPUT_TYPE_ST_R;
} else {
if (se->resptype == MSM_CAM_RESP_STEREO_OP_1) {
- rc = msm_pmem_frame_ptov_lookup(sync, data->phy.y_phy,
- data->phy.cbcr_phy, &pinfo,
- 1); /* do clear the active flag */
+ rc = msm_pmem_frame_ptov_lookup(sync, data->phy.p0_phy,
+ data->phy.p1_phy, data->phy.p2_phy, &pinfo,
+ 1); /* do clear the active flag */
buf.buf_info.path = path;
} else if (se->resptype == MSM_CAM_RESP_STEREO_OP_2) {
- rc = msm_pmem_frame_ptov_lookup(sync, data->phy.y_phy,
- data->phy.cbcr_phy, &pinfo,
- 0); /* do not clear the active flag */
+ rc = msm_pmem_frame_ptov_lookup(sync, data->phy.p0_phy,
+ data->phy.p1_phy, data->phy.p2_phy, &pinfo,
+ 0); /* do not clear the active flag */
buf.buf_info.path = path;
} else
CDBG("%s: Invalid resptype = %d\n", __func__,
@@ -1184,8 +1197,9 @@
buf.buf_info.buffer = (unsigned long)pinfo.vaddr;
buf.buf_info.phy_offset = pinfo.offset;
- buf.buf_info.y_off = pinfo.y_off;
- buf.buf_info.cbcr_off = pinfo.cbcr_off;
+ buf.buf_info.planar0_off = pinfo.planar0_off;
+ buf.buf_info.planar1_off = pinfo.planar1_off;
+ buf.buf_info.planar2_off = pinfo.planar2_off;
buf.buf_info.fd = pinfo.fd;
CDBG("%s: buf 0x%x fd %d\n", __func__,
@@ -1837,6 +1851,7 @@
}
break;
+ case CMD_AXI_CFG_VIDEO_ALL_CHNLS:
case CMD_AXI_CFG_VIDEO:
pmem_type = MSM_PMEM_PREVIEW;
axi_data.bufnum1 =
@@ -1889,6 +1904,7 @@
}
break;
+ case CMD_AXI_CFG_ZSL_ALL_CHNLS:
case CMD_AXI_CFG_ZSL:
CDBG("%s, CMD_AXI_CFG_ZSL, type = %d\n", __func__,
cfgcmd->cmd_type);
@@ -2044,7 +2060,7 @@
/* Change the active flag. */
pphy = msm_pmem_frame_vtop_lookup(sync,
pb->buffer,
- pb->y_off, pb->cbcr_off, pb->fd, 1);
+ pb->planar0_off, pb->planar1_off, pb->planar2_off, pb->fd, 1);
if (pphy != 0) {
CDBG("%s: rel: vaddr %lx, paddr %lx\n",
@@ -2072,7 +2088,7 @@
pphy = msm_pmem_frame_vtop_lookup(sync,
pb->buffer,
- pb->y_off, pb->cbcr_off, pb->fd, 1);
+ pb->planar0_off, pb->planar1_off, pb->planar2_off, pb->fd, 1);
if (pphy != 0) {
CDBG("%s: rel: vaddr %lx, paddr %lx\n",
@@ -2295,6 +2311,8 @@
case CMD_AXI_CFG_SNAP:
case CMD_RAW_PICT_AXI_CFG:
case CMD_AXI_CFG_ZSL:
+ case CMD_AXI_CFG_VIDEO_ALL_CHNLS:
+ case CMD_AXI_CFG_ZSL_ALL_CHNLS:
CDBG("%s, cfgcmd.cmd_type = %d\n", __func__, cfgcmd.cmd_type);
return msm_frame_axi_cfg(sync, &cfgcmd);
@@ -2340,21 +2358,21 @@
pphy = &vdata->phy;
rc = msm_pmem_frame_ptov_lookup2(sync,
- pphy->y_phy,
+ pphy->p0_phy,
&pmem_info,
1); /* mark pic frame in use */
if (rc < 0) {
pr_err("%s: cannot get pic frame, invalid lookup"
- " address y %x cbcr %x\n",
- __func__, pphy->y_phy, pphy->cbcr_phy);
+ " address p0_phy add %x p1_phy add%x\n",
+ __func__, pphy->p0_phy, pphy->p1_phy);
goto err;
}
frame->ts = qcmd->ts;
frame->buffer = (unsigned long)pmem_info.vaddr;
- frame->y_off = pmem_info.y_off;
- frame->cbcr_off = pmem_info.cbcr_off;
+ frame->planar0_off = pmem_info.planar0_off;
+ frame->planar1_off = pmem_info.planar1_off;
frame->fd = pmem_info.fd;
if (sync->stereocam_enabled &&
sync->stereo_state != STEREO_RAW_SNAP_STARTED) {
@@ -2365,20 +2383,20 @@
} else
frame->path = vdata->phy.output_id;
- CDBG("%s: y %x, cbcr %x, qcmd %x, virt_addr %x\n",
- __func__, pphy->y_phy,
- pphy->cbcr_phy, (int) qcmd, (int) frame->buffer);
+ CDBG("%s:p0_phy add %x, p0_phy add %x, qcmd %x, virt_addr %x\n",
+ __func__, pphy->p0_phy,
+ pphy->p1_phy, (int) qcmd, (int) frame->buffer);
} else { /* PP */
pframe = (struct msm_frame *)(qcmd->command);
frame->ts = qcmd->ts;
frame->buffer = pframe->buffer;
- frame->y_off = pframe->y_off;
- frame->cbcr_off = pframe->cbcr_off;
+ frame->planar0_off = pframe->planar0_off;
+ frame->planar1_off = pframe->planar1_off;
frame->fd = pframe->fd;
frame->path = pframe->path;
CDBG("%s: PP y_off %x, cbcr_off %x, path %d vaddr 0x%x\n",
- __func__, frame->y_off, frame->cbcr_off, frame->path,
- (int) frame->buffer);
+ __func__, frame->planar0_off, frame->planar1_off, frame->path,
+ (int) frame->buffer);
}
err:
@@ -2604,13 +2622,13 @@
vfe_rp = (struct msm_vfe_resp *)qcmd->command;
CDBG("%s: Left Py = 0x%x y_off = %d cbcr_off = %d\n",
- __func__, vfe_rp->phy.y_phy,
- stereo_frame_half.L.buf_y_off,
- stereo_frame_half.L.buf_cbcr_off);
+ __func__, vfe_rp->phy.p0_phy,
+ stereo_frame_half.L.buf_p0_off,
+ stereo_frame_half.L.buf_p1_off);
sync->vpefn.vpe_cfg_offset(stereo_frame_half.packing,
- vfe_rp->phy.y_phy + stereo_frame_half.L.buf_y_off,
- vfe_rp->phy.y_phy + stereo_frame_half.L.buf_cbcr_off,
+ vfe_rp->phy.p0_phy + stereo_frame_half.L.buf_p0_off,
+ vfe_rp->phy.p1_phy + stereo_frame_half.L.buf_p1_off,
&(qcmd->ts), OUTPUT_TYPE_ST_L, stereo_frame_half.L,
stereo_frame_half.frame_id);
@@ -2626,14 +2644,15 @@
st_pphy = msm_pmem_frame_vtop_lookup(sync,
stereo_frame_half.buf_info.buffer,
- stereo_frame_half.buf_info.y_off,
- stereo_frame_half.buf_info.cbcr_off,
+ stereo_frame_half.buf_info.planar0_off,
+ stereo_frame_half.buf_info.planar1_off,
+ stereo_frame_half.buf_info.planar2_off,
stereo_frame_half.buf_info.fd,
0); /* Do not change the active flag. */
sync->vpefn.vpe_cfg_offset(stereo_frame_half.packing,
- st_pphy + stereo_frame_half.R.buf_y_off,
- st_pphy + stereo_frame_half.R.buf_cbcr_off,
+ st_pphy + stereo_frame_half.R.buf_p0_off,
+ st_pphy + stereo_frame_half.R.buf_p1_off,
NULL, OUTPUT_TYPE_ST_R, stereo_frame_half.R,
stereo_frame_half.frame_id);
@@ -3332,10 +3351,10 @@
switch (vdata->type) {
case VFE_MSG_OUTPUT_P:
if (sync->pp_mask & PP_PREV) {
- CDBG("%s: PP_PREV in progress: phy_y %x phy_cbcr %x\n",
+ CDBG("%s: PP_PREV in progress: p0_add %x p1_add %x\n",
__func__,
- vdata->phy.y_phy,
- vdata->phy.cbcr_phy);
+ vdata->phy.p0_phy,
+ vdata->phy.p1_phy);
spin_lock_irqsave(&pp_prev_spinlock, flags);
if (sync->pp_prev)
CDBG("%s: overwriting pp_prev!\n",
@@ -3493,8 +3512,8 @@
vdata->vpe_bf.vpe_crop =
*(struct video_crop_t *)(sync->cropinfo);
- vdata->vpe_bf.y_phy = vdata->phy.y_phy;
- vdata->vpe_bf.cbcr_phy = vdata->phy.cbcr_phy;
+ vdata->vpe_bf.p0_phy = vdata->phy.p0_phy;
+ vdata->vpe_bf.p1_phy = vdata->phy.p1_phy;
vdata->vpe_bf.ts = (qcmd->ts);
vdata->vpe_bf.frame_id = vdata->phy.frame_id;
qcmd->command = vdata;
@@ -3506,8 +3525,8 @@
"= %ld\n", __func__, qcmd->ts.tv_nsec);
sync->vpefn.send_frame_to_vpe(
- vdata->phy.y_phy,
- vdata->phy.cbcr_phy,
+ vdata->phy.p0_phy,
+ vdata->phy.p1_phy,
&(qcmd->ts), OUTPUT_TYPE_V);
free_qcmd(qcmd);
diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/video/msm/msm_mem.c
index c13e7e5..b631981 100644
--- a/drivers/media/video/msm/msm_mem.c
+++ b/drivers/media/video/msm/msm_mem.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
@@ -84,16 +84,16 @@
{
if (info->offset < len &&
info->offset + info->len <= len &&
- info->y_off < len &&
- info->cbcr_off < len)
+ info->planar0_off < len &&
+ info->planar1_off < len)
return 0;
pr_err("%s: check failed: off %d len %d y %d cbcr %d (total len %d)\n",
__func__,
info->offset,
info->len,
- info->y_off,
- info->cbcr_off,
+ info->planar0_off,
+ info->planar1_off,
len);
return -EINVAL;
}
diff --git a/drivers/media/video/msm/msm_vfe31.c b/drivers/media/video/msm/msm_vfe31.c
index b22b6c5..2b3732c 100644
--- a/drivers/media/video/msm/msm_vfe31.c
+++ b/drivers/media/video/msm/msm_vfe31.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
@@ -337,10 +337,12 @@
break;
}
pinfo->output_id = outid;
- pinfo->y_phy =
- ((struct vfe_message *)data)->_u.msgOut.yBuffer;
- pinfo->cbcr_phy =
- ((struct vfe_message *)data)->_u.msgOut.cbcrBuffer;
+ pinfo->p0_phy =
+ ((struct vfe_message *)data)->_u.msgOut.p0_addr;
+ pinfo->p1_phy =
+ ((struct vfe_message *)data)->_u.msgOut.p1_addr;
+ pinfo->p2_phy =
+ ((struct vfe_message *)data)->_u.msgOut.p2_addr;
pinfo->frame_id =
((struct vfe_message *)data)->_u.msgOut.frameCounter;
@@ -458,8 +460,8 @@
GFP_ATOMIC);
}
-static void vfe_send_outmsg(uint8_t msgid, uint32_t pyaddr,
- uint32_t pcbcraddr)
+static void vfe_send_outmsg(uint8_t msgid, uint32_t p0_addr,
+ uint32_t p1_addr, uint32_t p2_addr)
{
struct vfe_message msg;
uint8_t outid;
@@ -485,9 +487,10 @@
break;
}
msg._u.msgOut.output_id = msgid;
- msg._u.msgOut.yBuffer = pyaddr;
- msg._u.msgOut.cbcrBuffer = pcbcraddr;
-
+ msg._u.msgOut.p0_addr = p0_addr;
+ msg._u.msgOut.p1_addr = p1_addr;
+ msg._u.msgOut.p2_addr = p2_addr;
+ CDBG("%s p2_addr = 0x%x\n", __func__, p2_addr);
vfe31_proc_ops(msgid, &msg, sizeof(struct vfe_message));
return;
}
@@ -542,7 +545,7 @@
}
static int vfe31_add_free_buf2(struct vfe31_output_ch *outch,
- uint32_t paddr, uint32_t y_off, uint32_t cbcr_off)
+ uint32_t paddr, uint32_t p0_off, uint32_t p1_off, uint32_t p2_off)
{
struct vfe31_free_buf *free_buf = NULL;
unsigned long flags = 0;
@@ -552,20 +555,23 @@
spin_lock_irqsave(&outch->free_buf_lock, flags);
free_buf->paddr = paddr;
- free_buf->y_off = y_off;
- free_buf->cbcr_off = cbcr_off;
+ free_buf->planar0_off = p0_off;
+ free_buf->planar1_off = p1_off;
+ free_buf->planar2_off = p2_off;
list_add_tail(&free_buf->node, &outch->free_buf_head);
CDBG("%s: free_buf paddr = 0x%x, y_off = %d, cbcr_off = %d\n",
- __func__, free_buf->paddr, free_buf->y_off,
- free_buf->cbcr_off);
+ __func__, free_buf->paddr, free_buf->planar0_off,
+ free_buf->planar1_off);
spin_unlock_irqrestore(&outch->free_buf_lock, flags);
return 0;
}
#define vfe31_add_free_buf(outch, regptr) \
- vfe31_add_free_buf2(outch, regptr->paddr, regptr->info.y_off, \
- regptr->info.cbcr_off)
+ vfe31_add_free_buf2(outch, regptr->paddr, \
+ regptr->info.planar0_off, \
+ regptr->info.planar1_off, \
+ regptr->info.planar2_off)
#define vfe31_free_buf_available(outch) \
(!list_empty(&outch.free_buf_head))
@@ -662,10 +668,10 @@
for (i = 0; i < 2; i++) {
p1 = ao + 6 + i; /* wm0 for y */
- *p1 = (regp1->paddr + regp1->info.y_off);
+ *p1 = (regp1->paddr + regp1->info.planar0_off);
p1 = ao + 12 + i; /* wm1 for cbcr */
- *p1 = (regp1->paddr + regp1->info.cbcr_off);
+ *p1 = (regp1->paddr + regp1->info.planar1_off);
regp1++;
}
ret = vfe31_add_free_buf(outp1, regp1);
@@ -694,47 +700,47 @@
/* Parse the buffers!!! */
if (ad->bufnum2 == 1) { /* assuming bufnum1 = bufnum2 */
p1 = ao + 6; /* wm0 ping */
- *p1++ = (regp1->paddr + regp1->info.y_off);
+ *p1++ = (regp1->paddr + regp1->info.planar0_off);
/* this is to duplicate ping address to pong.*/
- *p1 = (regp1->paddr + regp1->info.y_off);
+ *p1 = (regp1->paddr + regp1->info.planar0_off);
p1 = ao + 30; /* wm4 ping */
- *p1++ = (regp1->paddr + regp1->info.cbcr_off);
+ *p1++ = (regp1->paddr + regp1->info.planar1_off);
CDBG("%s: regp1->info.cbcr_off = 0x%x\n", __func__,
- regp1->info.cbcr_off);
+ regp1->info.planar1_off);
/* this is to duplicate ping address to pong.*/
- *p1 = (regp1->paddr + regp1->info.cbcr_off);
+ *p1 = (regp1->paddr + regp1->info.planar1_off);
p1 = ao + 12; /* wm1 ping */
- *p1++ = (regp2->paddr + regp2->info.y_off);
+ *p1++ = (regp2->paddr + regp2->info.planar0_off);
/* pong = ping,*/
- *p1 = (regp2->paddr + regp2->info.y_off);
+ *p1 = (regp2->paddr + regp2->info.planar0_off);
p1 = ao + 36; /* wm5 */
- *p1++ = (regp2->paddr + regp2->info.cbcr_off);
+ *p1++ = (regp2->paddr + regp2->info.planar1_off);
CDBG("%s: regp2->info.cbcr_off = 0x%x\n", __func__,
- regp2->info.cbcr_off);
+ regp2->info.planar1_off);
/* pong = ping,*/
- *p1 = (regp2->paddr + regp2->info.cbcr_off);
+ *p1 = (regp2->paddr + regp2->info.planar1_off);
} else { /* more than one snapshot */
/* first fill ping & pong */
for (i = 0; i < 2; i++) {
p1 = ao + 6 + i; /* wm0 for y */
- *p1 = (regp1->paddr + regp1->info.y_off);
+ *p1 = (regp1->paddr + regp1->info.planar0_off);
p1 = ao + 30 + i; /* wm4 for cbcr */
- *p1 = (regp1->paddr + regp1->info.cbcr_off);
+ *p1 = (regp1->paddr + regp1->info.planar1_off);
regp1--;
}
for (i = 0; i < 2; i++) {
p2 = ao + 12 + i; /* wm1 for y */
- *p2 = (regp2->paddr + regp2->info.y_off);
+ *p2 = (regp2->paddr + regp2->info.planar0_off);
p2 = ao + 36 + i; /* wm5 for cbcr */
- *p2 = (regp2->paddr + regp2->info.cbcr_off);
+ *p2 = (regp2->paddr + regp2->info.planar1_off);
regp2--;
}
@@ -783,25 +789,25 @@
/* first fill ping & pong */
for (i = 0; i < 2; i++) {
p1 = ao + 6 + i; /* wm0 for y */
- *p1 = (regp1->paddr + regp1->info.y_off);
+ *p1 = (regp1->paddr + regp1->info.planar0_off);
p1 = ao + 30 + i; /* wm4 for cbcr */
- *p1 = (regp1->paddr + regp1->info.cbcr_off);
+ *p1 = (regp1->paddr + regp1->info.planar1_off);
regp1++;
}
for (i = 0; i < 2; i++) {
p2 = ao + 12 + i; /* wm1 for y */
- *p2 = (regp2->paddr + regp2->info.y_off);
+ *p2 = (regp2->paddr + regp2->info.planar0_off);
p2 = ao + 36 + i; /* wm5 for cbcr */
- *p2 = (regp2->paddr + regp2->info.cbcr_off);
+ *p2 = (regp2->paddr + regp2->info.planar1_off);
regp2++;
}
for (i = 0; i < 2; i++) {
p3 = ao + 18 + i; /* wm2 for y */
- *p3 = (regp3->paddr + regp3->info.y_off);
+ *p3 = (regp3->paddr + regp3->info.planar0_off);
p3 = ao + 42 + i; /* wm6 for cbcr */
- *p3 = (regp3->paddr + regp3->info.cbcr_off);
+ *p3 = (regp3->paddr + regp3->info.planar1_off);
regp3++;
}
@@ -827,6 +833,80 @@
}
break;
+ case OUTPUT_ZSL_ALL_CHNLS:
+ CDBG("%s: OUTPUT_ZSL_ALL_CHNLS", __func__);
+ CDBG("%s: %d %d %d", __func__, ad->bufnum1, ad->bufnum2,
+ ad->bufnum3);
+ /* use wm0& 4 for postview, wm1&5 for preview.*/
+ /* use wm2& 6 for main img */
+ if ((ad->bufnum1 < 1) || (ad->bufnum2 < 1) || (ad->bufnum3 < 1))
+ return -EINVAL;
+ vfe31_ctrl->outpath.output_mode |=
+ VFE31_OUTPUT_MODE_S; /* main image.*/
+ vfe31_ctrl->outpath.output_mode |=
+ VFE31_OUTPUT_MODE_P_ALL_CHNLS; /* preview. */
+ vfe31_ctrl->outpath.output_mode |=
+ VFE31_OUTPUT_MODE_T; /* thumbnail. */
+
+ /* this is preview buffer. */
+ regp1 = &(ad->region[0]);
+ /* this is thumbnail buffer. */
+ regp2 = &(ad->region[ad->bufnum1]);
+ /* this is main image buffer. */
+ regp3 = &(ad->region[ad->bufnum1+ad->bufnum2]);
+ outp1 = &(vfe31_ctrl->outpath.out0);
+ outp2 = &(vfe31_ctrl->outpath.out1);
+ outp3 = &(vfe31_ctrl->outpath.out2);
+
+ /* Parse the buffers!!! */
+ /* first fill ping & pong */
+ for (i = 0; i < 2; i++) {
+ p1 = ao + 6 + i; /* wm0 for y */
+ *p1 = (regp2->paddr + regp2->info.planar0_off);
+ p1 = ao + 12 + i; /* wm1 for cbcr */
+ *p1 = (regp2->paddr + regp2->info.planar1_off);
+ regp2++;
+ }
+
+ for (i = 0; i < 2; i++) {
+ p2 = ao + 30 + i; /* wm4 for y */
+ *p2 = (regp1->paddr + regp1->info.planar0_off);
+ p2 = ao + 36 + i; /* wm5 for cbcr */
+ *p2 = (regp1->paddr + regp1->info.planar1_off);
+ p2 = ao + 42 + i; /* wm5 for cbcr */
+ *p2 = (regp1->paddr + regp1->info.planar2_off);
+ regp1++;
+ }
+
+ for (i = 0; i < 2; i++) {
+ p3 = ao + 18 + i; /* wm2 for y */
+ *p3 = (regp3->paddr + regp3->info.planar0_off);
+ p3 = ao + 24 + i; /* wm3 for cbcr */
+ *p3 = (regp3->paddr + regp3->info.planar1_off);
+ regp3++;
+ }
+ for (i = 2; i < ad->bufnum1; i++) {
+ ret = vfe31_add_free_buf(outp1, regp1);
+ if (ret < 0)
+ return ret;
+ regp1++;
+ }
+
+ for (i = 2; i < ad->bufnum2; i++) {
+ ret = vfe31_add_free_buf(outp2, regp2);
+ if (ret < 0)
+ return ret;
+ regp2++;
+ }
+
+ for (i = 2; i < ad->bufnum3; i++) {
+ ret = vfe31_add_free_buf(outp3, regp3);
+ if (ret < 0)
+ return ret;
+ regp3++;
+ }
+ break;
+
case OUTPUT_1_AND_3: {
/* use wm0&4 for preview, wm1&5 for video.*/
if ((ad->bufnum1 < 2) || (ad->bufnum2 < 2))
@@ -849,19 +929,19 @@
for (i = 0; i < 2; i++) {
p1 = ao + 6 + i; /* wm0 for y */
- *p1 = (regp1->paddr + regp1->info.y_off);
+ *p1 = (regp1->paddr + regp1->info.planar0_off);
p1 = ao + 30 + i; /* wm4 for cbcr */
- *p1 = (regp1->paddr + regp1->info.cbcr_off);
+ *p1 = (regp1->paddr + regp1->info.planar1_off);
regp1++;
}
for (i = 0; i < 2; i++) {
p2 = ao + 12 + i; /* wm1 for y */
- *p2 = (regp2->paddr + regp2->info.y_off);
+ *p2 = (regp2->paddr + regp2->info.planar0_off);
p2 = ao + 36 + i; /* wm5 for cbcr */
- *p2 = (regp2->paddr + regp2->info.cbcr_off);
+ *p2 = (regp2->paddr + regp2->info.planar1_off);
regp2++;
}
for (i = 2; i < ad->bufnum1; i++) {
@@ -879,6 +959,52 @@
}
}
break;
+
+ case OUTPUT_VIDEO_ALL_CHNLS: {
+ /* use wm0&4 for preview, wm1&5 for video.*/
+ vfe31_ctrl->outpath.output_mode |=
+ VFE31_OUTPUT_MODE_V; /* video*/
+ vfe31_ctrl->outpath.output_mode |=
+ VFE31_OUTPUT_MODE_P_ALL_CHNLS;
+ regp1 = &(ad->region[0]);
+ regp2 = &(ad->region[ad->bufnum1]);
+ outp1 = &(vfe31_ctrl->outpath.out0);
+ outp2 = &(vfe31_ctrl->outpath.out2);
+
+ for (i = 0; i < 2; i++) {
+ p1 = ao + 6 + i; /* wm0 for y */
+ *p1 = (regp1->paddr + regp1->info.planar0_off);
+
+ p1 = ao + 12 + i; /* wm1 for cbcr */
+ *p1 = (regp1->paddr + regp1->info.planar1_off);
+
+ p1 = ao + 18 + i; /* wm2 for cbcr */
+ *p1 = (regp1->paddr + regp1->info.planar2_off);
+ regp1++;
+ }
+ for (i = 0; i < 2; i++) {
+ p2 = ao + 30 + i; /* wm4 for y */
+ *p2 = (regp2->paddr + regp2->info.planar0_off);
+
+ p2 = ao + 36 + i; /* wm5 for cbcr */
+ *p2 = (regp2->paddr + regp2->info.planar1_off);
+ regp2++;
+ }
+ for (i = 2; i < ad->bufnum1; i++) {
+ ret = vfe31_add_free_buf(outp1, regp1);
+ if (ret < 0)
+ return ret;
+ regp1++;
+ }
+ for (i = 2; i < ad->bufnum2; i++) {
+ ret = vfe31_add_free_buf(outp2, regp2);
+ if (ret < 0)
+ return ret;
+ regp2++;
+ }
+ }
+ break;
+
case CAMIF_TO_AXI_VIA_OUTPUT_2: { /* use wm0 only */
if (ad->bufnum2 < 1)
return -EINVAL;
@@ -887,7 +1013,7 @@
regp1 = &(ad->region[ad->bufnum1]);
vfe31_ctrl->outpath.output_mode |= VFE31_OUTPUT_MODE_S;
p1 = ao + 6; /* wm0 for y */
- *p1 = (regp1->paddr + regp1->info.y_off);
+ *p1 = (regp1->paddr + regp1->info.planar0_off);
if (p_sync->stereocam_enabled)
p_sync->stereo_state = STEREO_RAW_SNAP_IDLE;
}
@@ -1193,6 +1319,11 @@
irq_comp_mask |=
((0x1 << (vfe31_ctrl->outpath.out0.ch0)) |
(0x1 << (vfe31_ctrl->outpath.out0.ch1)));
+ } else if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_P_ALL_CHNLS) {
+ irq_comp_mask |= (0x1 << vfe31_ctrl->outpath.out0.ch0 |
+ 0x1 << vfe31_ctrl->outpath.out0.ch1 |
+ 0x1 << vfe31_ctrl->outpath.out0.ch2);
}
if (vfe31_ctrl->outpath.output_mode & VFE31_OUTPUT_MODE_T) {
irq_comp_mask |=
@@ -1209,6 +1340,14 @@
vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
msm_io_w(1, vfe31_ctrl->vfebase +
vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+ } else if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_P_ALL_CHNLS) {
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch2]);
}
if (vfe31_ctrl->outpath.output_mode & VFE31_OUTPUT_MODE_T) {
msm_io_w(1, vfe31_ctrl->vfebase +
@@ -1302,12 +1441,22 @@
if ((vfe31_ctrl->operation_mode != VFE_MODE_OF_OPERATION_CONTINUOUS) &&
(vfe31_ctrl->operation_mode != VFE_MODE_OF_OPERATION_VIDEO))
return 0;
- irq_comp_mask =
+ irq_comp_mask =
msm_io_r(vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
if (vfe31_ctrl->outpath.output_mode & VFE31_OUTPUT_MODE_PT) {
irq_comp_mask |= (0x1 << vfe31_ctrl->outpath.out0.ch0 |
0x1 << vfe31_ctrl->outpath.out0.ch1);
+ if (vfe31_ctrl->outpath.out0.ch2 >= 0)
+ irq_comp_mask |=
+ (0x1 << vfe31_ctrl->outpath.out0.ch0 |
+ 0x1 << vfe31_ctrl->outpath.out0.ch1 |
+ 0x1 << vfe31_ctrl->outpath.out0.ch2);
+ } else if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_P_ALL_CHNLS) {
+ irq_comp_mask |= (0x1 << vfe31_ctrl->outpath.out0.ch0 |
+ 0x1 << vfe31_ctrl->outpath.out0.ch1 |
+ 0x1 << vfe31_ctrl->outpath.out0.ch2);
}
if (vfe31_ctrl->outpath.output_mode & VFE31_OUTPUT_MODE_V) {
@@ -1323,7 +1472,19 @@
vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
msm_io_w(1, vfe31_ctrl->vfebase +
vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+ if (vfe31_ctrl->outpath.out0.ch2 >= 0)
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch2]);
+ } else if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_P_ALL_CHNLS) {
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch0]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch1]);
+ msm_io_w(1, vfe31_ctrl->vfebase +
+ vfe31_AXI_WM_CFG[vfe31_ctrl->outpath.out0.ch2]);
}
+
if (p_sync->stereocam_enabled)
msm_camio_set_perf_lvl(S_STEREO_VIDEO);
else
@@ -2240,7 +2401,8 @@
break;
}
- ret = vfe31_add_free_buf2(outch, p, b->y_off, b->cbcr_off);
+ ret = vfe31_add_free_buf2(outch, p, b->planar0_off,
+ b->planar1_off, b->planar2_off);
if (ret < 0)
return ret;
break;
@@ -2267,7 +2429,8 @@
} else
return -EFAULT;
- ret = vfe31_add_free_buf2(outch, p, b->y_off, b->cbcr_off);
+ ret = vfe31_add_free_buf2(outch, p, b->planar0_off,
+ b->planar1_off, b->planar2_off);
if (ret < 0)
return ret;
break;
@@ -2403,6 +2566,32 @@
}
break;
+ case CMD_AXI_CFG_ZSL_ALL_CHNLS: {
+ struct axidata *axid;
+ uint32_t *axio;
+ CDBG("%s, CMD_AXI_CFG_ZSL\n", __func__);
+ axid = data;
+ if (!axid)
+ return -EFAULT;
+ axio =
+ kmalloc(vfe31_cmd[V31_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio) {
+ rc = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe31_cmd[V31_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ rc = -EFAULT;
+ break;
+ }
+ vfe31_config_axi(OUTPUT_ZSL_ALL_CHNLS, axid, axio);
+ kfree(axio);
+ }
+ break;
+
case CMD_AXI_CFG_VIDEO: {
struct axidata *axid;
uint32_t *axio = NULL;
@@ -2431,6 +2620,34 @@
break;
}
+ case CMD_AXI_CFG_VIDEO_ALL_CHNLS: {
+ struct axidata *axid;
+ uint32_t *axio = NULL;
+ axid = data;
+ if (!axid) {
+ rc = -EFAULT;
+ break;
+ }
+
+ axio =
+ kmalloc(vfe31_cmd[V31_AXI_OUT_CFG].length,
+ GFP_ATOMIC);
+ if (!axio) {
+ rc = -ENOMEM;
+ break;
+ }
+
+ if (copy_from_user(axio, (void __user *)(vfecmd.value),
+ vfe31_cmd[V31_AXI_OUT_CFG].length)) {
+ kfree(axio);
+ rc = -EFAULT;
+ break;
+ }
+ vfe31_config_axi(OUTPUT_VIDEO_ALL_CHNLS, axid, axio);
+ kfree(axio);
+ break;
+ }
+
default:
break;
}
@@ -2804,7 +3021,7 @@
static void vfe31_process_output_path_irq_0(uint32_t ping_pong)
{
- uint32_t pyaddr, pcbcraddr;
+ uint32_t p0_addr, p1_addr, p2_addr;
#ifdef CONFIG_MSM_CAMERA_V4L2
uint32_t pyaddr_ping, pcbcraddr_ping, pyaddr_pong, pcbcraddr_pong;
#endif
@@ -2816,26 +3033,37 @@
if (free_buf) {
/* Y channel */
- pyaddr = vfe31_get_ch_addr(ping_pong,
+ p0_addr = vfe31_get_ch_addr(ping_pong,
vfe31_ctrl->outpath.out0.ch0);
/* Chroma channel */
- pcbcraddr = vfe31_get_ch_addr(ping_pong,
+ p1_addr = vfe31_get_ch_addr(ping_pong,
vfe31_ctrl->outpath.out0.ch1);
-
- CDBG("output path 0, pyaddr = 0x%x, pcbcraddr = 0x%x\n",
- pyaddr, pcbcraddr);
+ if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_P_ALL_CHNLS) {
+ p2_addr = vfe31_get_ch_addr(ping_pong,
+ vfe31_ctrl->outpath.out0.ch2);
+ } else {
+ p2_addr = p0_addr;
+ }
+ CDBG("Output path 0, p0_addr = 0x%x, p1_addr = 0x%x,"
+ "p2_addr = 0x%x\n", p0_addr, p1_addr, p2_addr);
/* Y channel */
vfe31_put_ch_addr(ping_pong,
vfe31_ctrl->outpath.out0.ch0,
- free_buf->paddr + free_buf->y_off);
+ free_buf->paddr + free_buf->planar0_off);
/* Chroma channel */
vfe31_put_ch_addr(ping_pong,
vfe31_ctrl->outpath.out0.ch1,
- free_buf->paddr + free_buf->cbcr_off);
-
- kfree(free_buf);
- /* if continuous mode, for display. (preview) */
- vfe_send_outmsg(MSG_ID_OUTPUT_P, pyaddr, pcbcraddr);
+ free_buf->paddr + free_buf->planar1_off);
+ if (vfe31_ctrl->outpath.output_mode &
+ VFE31_OUTPUT_MODE_P_ALL_CHNLS)
+ vfe31_put_ch_addr(ping_pong,
+ vfe31_ctrl->outpath.out0.ch2,
+ free_buf->paddr + free_buf->planar2_off);
+ kfree(free_buf);
+ /* if continuous mode, for display. (preview) */
+ vfe_send_outmsg(MSG_ID_OUTPUT_P, p0_addr, p1_addr,
+ p2_addr);
} else {
vfe31_ctrl->outpath.out0.frame_drop_cnt++;
pr_warning("path_irq_0 - no free buffer!\n");
@@ -2880,54 +3108,54 @@
static void vfe31_process_snapshot_frame(uint32_t ping_pong)
{
- uint32_t pyaddr, pcbcraddr;
+ uint32_t p0_addr, p1_addr;
struct vfe31_free_buf *free_buf = NULL;
/* Y channel- Main Image */
- pyaddr = vfe31_get_ch_addr(ping_pong,
+ p0_addr = vfe31_get_ch_addr(ping_pong,
vfe31_ctrl->outpath.out1.ch0);
/* Chroma channel - TN Image */
- pcbcraddr = vfe31_get_ch_addr(ping_pong,
+ p1_addr = vfe31_get_ch_addr(ping_pong,
vfe31_ctrl->outpath.out1.ch1);
free_buf = vfe31_get_free_buf(&vfe31_ctrl->outpath.out1);
- CDBG("%s: snapshot main, pyaddr = 0x%x, pcbcraddr = 0x%x\n",
- __func__, pyaddr, pcbcraddr);
+ CDBG("%s: snapshot main, p0_addr = 0x%x, p1_addr = 0x%x\n",
+ __func__, p0_addr, p1_addr);
if (free_buf) {
/* Y channel */
vfe31_put_ch_addr(ping_pong,
vfe31_ctrl->outpath.out1.ch0,
- free_buf->paddr + free_buf->y_off);
+ free_buf->paddr + free_buf->planar0_off);
/* Chroma channel */
vfe31_put_ch_addr(ping_pong,
vfe31_ctrl->outpath.out1.ch1,
- free_buf->paddr + free_buf->cbcr_off);
+ free_buf->paddr + free_buf->planar1_off);
kfree(free_buf);
}
- vfe_send_outmsg(MSG_ID_OUTPUT_S, pyaddr, pcbcraddr);
+ vfe_send_outmsg(MSG_ID_OUTPUT_S, p0_addr, p1_addr, p0_addr);
/* Y channel- TN Image */
- pyaddr = vfe31_get_ch_addr(ping_pong,
+ p0_addr = vfe31_get_ch_addr(ping_pong,
vfe31_ctrl->outpath.out0.ch0);
/* Chroma channel - TN Image */
- pcbcraddr = vfe31_get_ch_addr(ping_pong,
+ p1_addr = vfe31_get_ch_addr(ping_pong,
vfe31_ctrl->outpath.out0.ch1);
free_buf = vfe31_get_free_buf(&vfe31_ctrl->outpath.out0);
- CDBG("%s: snapshot TN, pyaddr = 0x%x, pcbcraddr = 0x%x\n",
- __func__, pyaddr, pcbcraddr);
+ CDBG("%s: snapshot TN, p0_addr = 0x%x, p1_addr = 0x%x\n",
+ __func__, p0_addr, p1_addr);
if (free_buf) {
/* Y channel */
vfe31_put_ch_addr(ping_pong,
vfe31_ctrl->outpath.out0.ch0,
- free_buf->paddr + free_buf->y_off);
+ free_buf->paddr + free_buf->planar0_off);
/* Chroma channel */
vfe31_put_ch_addr(ping_pong,
vfe31_ctrl->outpath.out0.ch1,
- free_buf->paddr + free_buf->cbcr_off);
+ free_buf->paddr + free_buf->planar1_off);
kfree(free_buf);
}
- vfe_send_outmsg(MSG_ID_OUTPUT_T, pyaddr, pcbcraddr);
+ vfe_send_outmsg(MSG_ID_OUTPUT_T, p0_addr, p1_addr, p0_addr);
/* in snapshot mode if done then send
snapshot done message */
@@ -2964,14 +3192,14 @@
/* Y channel */
vfe31_put_ch_addr(ping_pong,
vfe31_ctrl->outpath.out1.ch0,
- free_buf->paddr + free_buf->y_off);
+ free_buf->paddr + free_buf->planar0_off);
/* Chroma channel */
vfe31_put_ch_addr(ping_pong,
vfe31_ctrl->outpath.out1.ch1,
- free_buf->paddr + free_buf->cbcr_off);
+ free_buf->paddr + free_buf->planar1_off);
kfree(free_buf);
}
- vfe_send_outmsg(MSG_ID_OUTPUT_S, pyaddr, pcbcraddr);
+ vfe_send_outmsg(MSG_ID_OUTPUT_S, pyaddr, pcbcraddr, 0);
/* in snapshot mode if done then send
snapshot done message */
@@ -2986,54 +3214,54 @@
}
static void vfe31_process_zsl_frame(uint32_t ping_pong)
{
- uint32_t pyaddr, pcbcraddr;
+ uint32_t p0_addr, p1_addr;
struct vfe31_free_buf *free_buf = NULL;
/* Y channel- Main Image */
- pyaddr = vfe31_get_ch_addr(ping_pong,
+ p0_addr = vfe31_get_ch_addr(ping_pong,
vfe31_ctrl->outpath.out2.ch0);
/* Chroma channel - Main Image */
- pcbcraddr = vfe31_get_ch_addr(ping_pong,
+ p1_addr = vfe31_get_ch_addr(ping_pong,
vfe31_ctrl->outpath.out2.ch1);
free_buf = vfe31_get_free_buf(&vfe31_ctrl->outpath.out2);
CDBG("%s: snapshot main, pyaddr = 0x%x, pcbcraddr = 0x%x\n",
- __func__, pyaddr, pcbcraddr);
+ __func__, p0_addr, p1_addr);
if (free_buf) {
/* Y channel */
vfe31_put_ch_addr(ping_pong,
vfe31_ctrl->outpath.out2.ch0,
- free_buf->paddr + free_buf->y_off);
+ free_buf->paddr + free_buf->planar0_off);
/* Chroma channel */
vfe31_put_ch_addr(ping_pong,
vfe31_ctrl->outpath.out2.ch1,
- free_buf->paddr + free_buf->cbcr_off);
+ free_buf->paddr + free_buf->planar1_off);
kfree(free_buf);
}
- vfe_send_outmsg(MSG_ID_OUTPUT_S, pyaddr, pcbcraddr);
+ vfe_send_outmsg(MSG_ID_OUTPUT_S, p0_addr, p1_addr, p0_addr);
/* Y channel- TN Image */
- pyaddr = vfe31_get_ch_addr(ping_pong,
+ p0_addr = vfe31_get_ch_addr(ping_pong,
vfe31_ctrl->outpath.out1.ch0);
/* Chroma channel - TN Image */
- pcbcraddr = vfe31_get_ch_addr(ping_pong,
+ p1_addr = vfe31_get_ch_addr(ping_pong,
vfe31_ctrl->outpath.out1.ch1);
free_buf = vfe31_get_free_buf(&vfe31_ctrl->outpath.out1);
CDBG("%s: snapshot TN, pyaddr = 0x%x, pcbcraddr = 0x%x\n",
- __func__, pyaddr, pcbcraddr);
+ __func__, p0_addr, p1_addr);
if (free_buf) {
/* Y channel */
vfe31_put_ch_addr(ping_pong,
vfe31_ctrl->outpath.out1.ch0,
- free_buf->paddr + free_buf->y_off);
+ free_buf->paddr + free_buf->planar0_off);
/* Chroma channel */
vfe31_put_ch_addr(ping_pong,
vfe31_ctrl->outpath.out1.ch1,
- free_buf->paddr + free_buf->cbcr_off);
+ free_buf->paddr + free_buf->planar1_off);
kfree(free_buf);
}
- vfe_send_outmsg(MSG_ID_OUTPUT_T, pyaddr, pcbcraddr);
+ vfe_send_outmsg(MSG_ID_OUTPUT_T, p0_addr, p1_addr, p0_addr);
}
static void vfe31_process_output_path_irq_1(uint32_t ping_pong)
@@ -3105,7 +3333,7 @@
static void vfe31_process_output_path_irq_2(uint32_t ping_pong)
{
- uint32_t pyaddr, pcbcraddr;
+ uint32_t p0_addr, p1_addr, p2_addr;
struct vfe31_free_buf *free_buf = NULL;
#ifdef CONFIG_MSM_CAMERA_V4L2
@@ -3135,25 +3363,25 @@
if (free_buf) {
/* Y channel */
- pyaddr = vfe31_get_ch_addr(ping_pong,
+ p0_addr = vfe31_get_ch_addr(ping_pong,
vfe31_ctrl->outpath.out2.ch0);
/* Chroma channel */
- pcbcraddr = vfe31_get_ch_addr(ping_pong,
+ p1_addr = vfe31_get_ch_addr(ping_pong,
vfe31_ctrl->outpath.out2.ch1);
-
+ p2_addr = p0_addr;
CDBG("video output, pyaddr = 0x%x, pcbcraddr = 0x%x\n",
- pyaddr, pcbcraddr);
+ p0_addr, p1_addr);
/* Y channel */
vfe31_put_ch_addr(ping_pong,
vfe31_ctrl->outpath.out2.ch0,
- free_buf->paddr + free_buf->y_off);
+ free_buf->paddr + free_buf->planar0_off);
/* Chroma channel */
vfe31_put_ch_addr(ping_pong,
vfe31_ctrl->outpath.out2.ch1,
- free_buf->paddr + free_buf->cbcr_off);
+ free_buf->paddr + free_buf->planar1_off);
kfree(free_buf);
- vfe_send_outmsg(MSG_ID_OUTPUT_V, pyaddr, pcbcraddr);
+ vfe_send_outmsg(MSG_ID_OUTPUT_V, p0_addr, p1_addr, p2_addr);
} else {
vfe31_ctrl->outpath.out2.frame_drop_cnt++;
pr_warning("path_irq_2 - no free buffer!\n");
diff --git a/drivers/media/video/msm/msm_vfe31.h b/drivers/media/video/msm/msm_vfe31.h
index c47c7de..d1df2dd 100644
--- a/drivers/media/video/msm/msm_vfe31.h
+++ b/drivers/media/video/msm/msm_vfe31.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
@@ -842,8 +842,9 @@
struct vfe_msg_output {
uint8_t output_id;
- uint32_t yBuffer;
- uint32_t cbcrBuffer;
+ uint32_t p0_addr;
+ uint32_t p1_addr;
+ uint32_t p2_addr;
struct vfe_frame_bpc_info bpcInfo;
struct vfe_frame_asf_info asfInfo;
uint32_t frameCounter;
@@ -878,7 +879,9 @@
struct vfe31_free_buf {
struct list_head node;
uint32_t paddr;
- uint32_t y_off;
+ uint32_t planar0_off;
+ uint32_t planar1_off;
+ uint32_t planar2_off;
uint32_t cbcr_off;
};
diff --git a/drivers/media/video/msm/msm_vfe7x.c b/drivers/media/video/msm/msm_vfe7x.c
index 316aacf..d74bebc 100644
--- a/drivers/media/video/msm/msm_vfe7x.c
+++ b/drivers/media/video/msm/msm_vfe7x.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-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
@@ -72,14 +72,14 @@
{
switch (type) {
case VFE_MSG_OUTPUT_P: {
- pinfo->y_phy = ((struct vfe_endframe *)data)->y_address;
- pinfo->cbcr_phy =
+ pinfo->p0_phy = ((struct vfe_endframe *)data)->y_address;
+ pinfo->p1_phy =
((struct vfe_endframe *)data)->cbcr_address;
-
+ pinfo->p2_phy = pinfo->p0_phy;
pinfo->output_id = OUTPUT_TYPE_P;
CDBG("vfe_7x_convert, y_phy = 0x%x, cbcr_phy = 0x%x\n",
- pinfo->y_phy, pinfo->cbcr_phy);
+ pinfo->p0_phy, pinfo->p1_phy);
((struct vfe_frame_extra *)extdata)->bl_evencol =
((struct vfe_endframe *)data)->blacklevelevencolumn;
@@ -99,20 +99,22 @@
break;
case VFE_MSG_OUTPUT_S: {
- pinfo->y_phy = paddr_s_y;
- pinfo->cbcr_phy = paddr_s_cbcr;
+ pinfo->p0_phy = paddr_s_y;
+ pinfo->p1_phy = paddr_s_cbcr;
+ pinfo->p2_phy = pinfo->p0_phy;
pinfo->output_id = OUTPUT_TYPE_S;
CDBG("vfe_7x_convert: y_phy = 0x%x cbcr_phy = 0x%x\n",
- pinfo->y_phy, pinfo->cbcr_phy);
+ pinfo->p0_phy, pinfo->p1_phy);
}
break;
case VFE_MSG_OUTPUT_T: {
- pinfo->y_phy = paddr_t_y;
- pinfo->cbcr_phy = paddr_t_cbcr;
+ pinfo->p0_phy = paddr_t_y;
+ pinfo->p1_phy = paddr_t_cbcr;
+ pinfo->p2_phy = pinfo->p0_phy;
pinfo->output_id = OUTPUT_TYPE_T;
CDBG("vfe_7x_convert: y_phy = 0x%x cbcr_phy = 0x%x\n",
- pinfo->y_phy, pinfo->cbcr_phy);
+ pinfo->p0_phy, pinfo->p1_phy);
}
break;
@@ -372,19 +374,19 @@
CDBG("bufnum1 = %d\n", ad->bufnum1);
if (mode == OUTPUT_1_AND_2) {
- paddr_t_y = regptr->paddr + regptr->info.y_off;
- paddr_t_cbcr = regptr->paddr + regptr->info.cbcr_off;
+ paddr_t_y = regptr->paddr + regptr->info.planar0_off;
+ paddr_t_cbcr = regptr->paddr + regptr->info.planar1_off;
}
CDBG("config_axi1: O1, phy = 0x%lx, y_off = %d, cbcr_off =%d\n",
- regptr->paddr, regptr->info.y_off,
- regptr->info.cbcr_off);
+ regptr->paddr, regptr->info.planar0_off,
+ regptr->info.planar1_off);
bptr = &ao->output1buffer1_y_phy;
for (cnt = 0; cnt < ad->bufnum1; cnt++) {
- *bptr = regptr->paddr + regptr->info.y_off;
+ *bptr = regptr->paddr + regptr->info.planar0_off;
bptr++;
- *bptr = regptr->paddr + regptr->info.cbcr_off;
+ *bptr = regptr->paddr + regptr->info.planar1_off;
bptr++;
regptr++;
@@ -392,9 +394,9 @@
regptr--;
for (cnt = 0; cnt < (8 - ad->bufnum1); cnt++) {
- *bptr = regptr->paddr + regptr->info.y_off;
+ *bptr = regptr->paddr + regptr->info.planar0_off;
bptr++;
- *bptr = regptr->paddr + regptr->info.cbcr_off;
+ *bptr = regptr->paddr + regptr->info.planar1_off;
bptr++;
}
} /* if OUTPUT1 or Both */
@@ -403,16 +405,17 @@
regptr = &(ad->region[ad->bufnum1]);
CDBG("bufnum2 = %d\n", ad->bufnum2);
- paddr_s_y = regptr->paddr + regptr->info.y_off;
- paddr_s_cbcr = regptr->paddr + regptr->info.cbcr_off;
+ paddr_s_y = regptr->paddr + regptr->info.planar0_off;
+ paddr_s_cbcr = regptr->paddr + regptr->info.planar1_off;
CDBG("config_axi2: O2, phy = 0x%lx, y_off = %d, cbcr_off =%d\n",
- regptr->paddr, regptr->info.y_off, regptr->info.cbcr_off);
+ regptr->paddr, regptr->info.planar0_off,
+ regptr->info.planar1_off);
bptr = &ao->output2buffer1_y_phy;
for (cnt = 0; cnt < ad->bufnum2; cnt++) {
- *bptr = regptr->paddr + regptr->info.y_off;
+ *bptr = regptr->paddr + regptr->info.planar0_off;
bptr++;
- *bptr = regptr->paddr + regptr->info.cbcr_off;
+ *bptr = regptr->paddr + regptr->info.planar1_off;
bptr++;
regptr++;
@@ -420,9 +423,9 @@
regptr--;
for (cnt = 0; cnt < (8 - ad->bufnum2); cnt++) {
- *bptr = regptr->paddr + regptr->info.y_off;
+ *bptr = regptr->paddr + regptr->info.planar0_off;
bptr++;
- *bptr = regptr->paddr + regptr->info.cbcr_off;
+ *bptr = regptr->paddr + regptr->info.planar1_off;
bptr++;
}
}
@@ -584,10 +587,10 @@
fack.header = VFE_FRAME_ACK;
fack.output2newybufferaddress =
- (void *)(p + b->y_off);
+ (void *)(p + b->planar0_off);
fack.output2newcbcrbufferaddress =
- (void *)(p + b->cbcr_off);
+ (void *)(p + b->planar1_off);
vfecmd->queue = QDSP_CMDQUEUE;
vfecmd->length = sizeof(struct vfe_outputack);
diff --git a/drivers/media/video/msm/msm_vfe7x27a.c b/drivers/media/video/msm/msm_vfe7x27a.c
index 9f7dff7..337085d 100644
--- a/drivers/media/video/msm/msm_vfe7x27a.c
+++ b/drivers/media/video/msm/msm_vfe7x27a.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
@@ -72,14 +72,14 @@
{
switch (type) {
case VFE_MSG_OUTPUT_P: {
- pinfo->y_phy = ((struct vfe_endframe *)data)->y_address;
- pinfo->cbcr_phy =
+ pinfo->p0_phy = ((struct vfe_endframe *)data)->y_address;
+ pinfo->p1_phy =
((struct vfe_endframe *)data)->cbcr_address;
-
+ pinfo->p2_phy = pinfo->p0_phy;
pinfo->output_id = OUTPUT_TYPE_P;
CDBG("vfe_7x_convert, y_phy = 0x%x, cbcr_phy = 0x%x\n",
- pinfo->y_phy, pinfo->cbcr_phy);
+ pinfo->p0_phy, pinfo->p1_phy);
memcpy(((struct vfe_frame_extra *)extdata),
&((struct vfe_endframe *)data)->extra,
@@ -92,19 +92,21 @@
}
break;
case VFE_MSG_OUTPUT_S: {
- pinfo->y_phy = paddr_s_y;
- pinfo->cbcr_phy = paddr_s_cbcr;
+ pinfo->p0_phy = paddr_s_y;
+ pinfo->p1_phy = paddr_s_cbcr;
+ pinfo->p2_phy = pinfo->p0_phy;
pinfo->output_id = OUTPUT_TYPE_S;
CDBG("vfe_7x_convert: y_phy = 0x%x cbcr_phy = 0x%x\n",
- pinfo->y_phy, pinfo->cbcr_phy);
+ pinfo->p0_phy, pinfo->p1_phy);
}
break;
case VFE_MSG_OUTPUT_T: {
- pinfo->y_phy = paddr_t_y;
- pinfo->cbcr_phy = paddr_t_cbcr;
+ pinfo->p0_phy = paddr_t_y;
+ pinfo->p1_phy = paddr_t_cbcr;
+ pinfo->p2_phy = pinfo->p0_phy;
pinfo->output_id = OUTPUT_TYPE_T;
CDBG("vfe_7x_convert: y_phy = 0x%x cbcr_phy = 0x%x\n",
- pinfo->y_phy, pinfo->cbcr_phy);
+ pinfo->p0_phy, pinfo->p1_phy);
}
break;
case VFE_MSG_STATS_AF:
@@ -354,19 +356,20 @@
CDBG("bufnum1 = %d\n", ad->bufnum1);
if (mode == OUTPUT_1_AND_2) {
- paddr_t_y = regptr->paddr + regptr->info.y_off;
- paddr_t_cbcr = regptr->paddr + regptr->info.cbcr_off;
+ paddr_t_y = regptr->paddr + regptr->info.planar0_off;
+ paddr_t_cbcr = regptr->paddr +
+ regptr->info.planar1_off;
}
CDBG("config_axi1: O1, phy = 0x%lx, y_off = %d, cbcr_off =%d\n",
- regptr->paddr, regptr->info.y_off,
- regptr->info.cbcr_off);
+ regptr->paddr, regptr->info.planar0_off,
+ regptr->info.planar1_off);
bptr = &ao->output1buffer1_y_phy;
for (cnt = 0; cnt < ad->bufnum1; cnt++) {
- *bptr = regptr->paddr + regptr->info.y_off;
+ *bptr = regptr->paddr + regptr->info.planar0_off;
bptr++;
- *bptr = regptr->paddr + regptr->info.cbcr_off;
+ *bptr = regptr->paddr + regptr->info.planar1_off;
bptr++;
regptr++;
@@ -374,9 +377,9 @@
regptr--;
for (cnt = 0; cnt < (8 - ad->bufnum1); cnt++) {
- *bptr = regptr->paddr + regptr->info.y_off;
+ *bptr = regptr->paddr + regptr->info.planar0_off;
bptr++;
- *bptr = regptr->paddr + regptr->info.cbcr_off;
+ *bptr = regptr->paddr + regptr->info.planar1_off;
bptr++;
}
}
@@ -385,17 +388,18 @@
regptr = &(ad->region[ad->bufnum1]);
CDBG("bufnum2 = %d\n", ad->bufnum2);
- paddr_s_y = regptr->paddr + regptr->info.y_off;
- paddr_s_cbcr = regptr->paddr + regptr->info.cbcr_off;
+ paddr_s_y = regptr->paddr + regptr->info.planar0_off;
+ paddr_s_cbcr = regptr->paddr + regptr->info.planar1_off;
CDBG("config_axi2: O2, phy = 0x%lx, y_off = %d, cbcr_off =%d\n",
- regptr->paddr, regptr->info.y_off, regptr->info.cbcr_off);
+ regptr->paddr, regptr->info.planar0_off,
+ regptr->info.planar1_off);
bptr = &ao->output2buffer1_y_phy;
for (cnt = 0; cnt < ad->bufnum2; cnt++) {
- *bptr = regptr->paddr + regptr->info.y_off;
+ *bptr = regptr->paddr + regptr->info.planar0_off;
bptr++;
- *bptr = regptr->paddr + regptr->info.cbcr_off;
+ *bptr = regptr->paddr + regptr->info.planar1_off;
bptr++;
regptr++;
@@ -403,9 +407,9 @@
regptr--;
for (cnt = 0; cnt < (8 - ad->bufnum2); cnt++) {
- *bptr = regptr->paddr + regptr->info.y_off;
+ *bptr = regptr->paddr + regptr->info.planar0_off;
bptr++;
- *bptr = regptr->paddr + regptr->info.cbcr_off;
+ *bptr = regptr->paddr + regptr->info.planar1_off;
bptr++;
}
}
@@ -563,10 +567,10 @@
fack.header = VFE_FRAME_ACK;
fack.output2newybufferaddress =
- (void *)(p + b->y_off);
+ (void *)(p + b->planar0_off);
fack.output2newcbcrbufferaddress =
- (void *)(p + b->cbcr_off);
+ (void *)(p + b->planar1_off);
vfecmd->queue = QDSP_CMDQUEUE;
vfecmd->length = sizeof(struct vfe_outputack);
diff --git a/drivers/media/video/msm/msm_vfe8x.c b/drivers/media/video/msm/msm_vfe8x.c
index 0bf1785..a99c6f1 100644
--- a/drivers/media/video/msm/msm_vfe8x.c
+++ b/drivers/media/video/msm/msm_vfe8x.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009, 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
@@ -122,10 +122,10 @@
for (j = 0; j < ao->output1.fragmentCount; j++) {
- *p1 = regptr->paddr + regptr->info.y_off;
+ *p1 = regptr->paddr + regptr->info.planar0_off;
p1++;
- *p2 = regptr->paddr + regptr->info.cbcr_off;
+ *p2 = regptr->paddr + regptr->info.planar1_off;
p2++;
}
regptr++;
@@ -144,15 +144,16 @@
CDBG("config_axi: O2, phy = 0x%lx, y_off = %d, "\
"cbcr_off = %d\n", regptr->paddr,
- regptr->info.y_off, regptr->info.cbcr_off);
+ regptr->info.planar0_off,
+ regptr->info.planar1_off);
for (j = 0; j < ao->output2.fragmentCount; j++) {
- *p1 = regptr->paddr + regptr->info.y_off;
+ *p1 = regptr->paddr + regptr->info.planar0_off;
CDBG("vfe_config_axi: p1 = 0x%x\n", *p1);
p1++;
- *p2 = regptr->paddr + regptr->info.cbcr_off;
+ *p2 = regptr->paddr + regptr->info.planar1_off;
CDBG("vfe_config_axi: p2 = 0x%x\n", *p2);
p2++;
}
@@ -174,15 +175,15 @@
CDBG("config_axi: O1, phy = 0x%lx, y_off = %d, "\
"cbcr_off = %d\n", regptr->paddr,
- regptr->info.y_off, regptr->info.cbcr_off);
+ regptr->info.planar0_off, regptr->info.planar1_off);
for (j = 0; j < ao->output1.fragmentCount; j++) {
- *p1 = regptr->paddr + regptr->info.y_off;
+ *p1 = regptr->paddr + regptr->info.planar0_off;
CDBG("vfe_config_axi: p1 = 0x%x\n", *p1);
p1++;
- *p2 = regptr->paddr + regptr->info.cbcr_off;
+ *p2 = regptr->paddr + regptr->info.planar1_off;
CDBG("vfe_config_axi: p2 = 0x%x\n", *p2);
p2++;
}
@@ -194,15 +195,15 @@
CDBG("config_axi: O2, phy = 0x%lx, y_off = %d, "\
"cbcr_off = %d\n", regptr1->paddr,
- regptr1->info.y_off, regptr1->info.cbcr_off);
+ regptr1->info.planar0_off, regptr1->info.planar1_off);
for (j = 0; j < ao->output2.fragmentCount; j++) {
-
- *p1 = regptr1->paddr + regptr1->info.y_off;
+ *p1 = regptr1->paddr +
+ regptr1->info.planar0_off;
CDBG("vfe_config_axi: p1 = 0x%x\n", *p1);
p1++;
-
- *p2 = regptr1->paddr + regptr1->info.cbcr_off;
+ *p2 = regptr1->paddr +
+ r1->info.planar1_off;
CDBG("vfe_config_axi: p2 = 0x%x\n", *p2);
p2++;
}
@@ -689,9 +690,9 @@
b = (struct msm_frame *)(cmd->value);
p = *(unsigned long *)data;
- fack.ybufaddr[0] = (uint32_t) (p + b->y_off);
+ fack.ybufaddr[0] = (uint32_t) (p + b->planar0_off);
- fack.chromabufaddr[0] = (uint32_t) (p + b->cbcr_off);
+ fack.chromabufaddr[0] = (uint32_t) (p + b->planar1_off);
if (b->path == OUTPUT_TYPE_P)
vfe_output_p_ack(&fack);
diff --git a/drivers/media/video/msm/msm_vfe8x_proc.c b/drivers/media/video/msm/msm_vfe8x_proc.c
index 9764557..055b244 100644
--- a/drivers/media/video/msm/msm_vfe8x_proc.c
+++ b/drivers/media/video/msm/msm_vfe8x_proc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-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
@@ -608,11 +608,12 @@
switch (type) {
case VFE_MSG_OUTPUT_P:
case VFE_MSG_OUTPUT_V:{
- pinfo->y_phy =
+ pinfo->planar0_off =
((struct vfe_message *)data)->_u.msgOutput2.yBuffer;
- pinfo->cbcr_phy =
+ pinfo->planar1_off =
((struct vfe_message *)data)->_u.msgOutput2.
cbcrBuffer;
+ pinfo->planar2_off = pinfo->planar0_off;
ctrl->extdata.bpcInfo =
((struct vfe_message *)data)->_u.msgOutput2.bpcInfo;
ctrl->extdata.asfInfo =
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index 3a7faa2..fcf2495 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* 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
@@ -466,6 +466,11 @@
struct msm_vpe_resp rp;
memset(&rp, 0, sizeof(rp));
spin_lock_irqsave(&vpe_ctrl->lock, flags);
+ if (vpe_ctrl->state == VPE_STATE_IDLE) {
+ pr_err("%s VPE is in IDLE state. Ignore the ack msg", __func__);
+ spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
+ return;
+ }
rp.type = vpe_ctrl->pp_frame_info->pp_frame_cmd.path;
rp.extdata = (void *)vpe_ctrl->pp_frame_info;
rp.extlen = sizeof(*vpe_ctrl->pp_frame_info);
@@ -558,7 +563,6 @@
spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
return rc;
}
- vpe_ctrl->state = VPE_STATE_IDLE;
spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
@@ -569,6 +573,9 @@
vpe_ctrl->fs_vpe = NULL;
disable_irq(vpe_ctrl->vpeirq->start);
tasklet_kill(&vpe_tasklet);
+ spin_lock_irqsave(&vpe_ctrl->lock, flags);
+ vpe_ctrl->state = VPE_STATE_IDLE;
+ spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
return rc;
}
diff --git a/drivers/media/video/msm/msm_vpe1.c b/drivers/media/video/msm/msm_vpe1.c
index 891816f..5f128e1 100644
--- a/drivers/media/video/msm/msm_vpe1.c
+++ b/drivers/media/video/msm/msm_vpe1.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
@@ -709,15 +709,15 @@
return 1;
}
-void msm_send_frame_to_vpe(uint32_t pyaddr, uint32_t pcbcraddr,
+void msm_send_frame_to_vpe(uint32_t p0_phy_add, uint32_t p1_phy_add,
struct timespec *ts, int output_type)
{
uint32_t temp_pyaddr = 0, temp_pcbcraddr = 0;
- CDBG("vpe input, pyaddr = 0x%x, pcbcraddr = 0x%x\n",
- pyaddr, pcbcraddr);
- msm_io_w(pyaddr, vpe_device->vpebase + VPE_SRCP0_ADDR_OFFSET);
- msm_io_w(pcbcraddr, vpe_device->vpebase + VPE_SRCP1_ADDR_OFFSET);
+ CDBG("vpe input, p0_phy_add = 0x%x, p1_phy_add = 0x%x\n",
+ p0_phy_add, p1_phy_add);
+ msm_io_w(p0_phy_add, vpe_device->vpebase + VPE_SRCP0_ADDR_OFFSET);
+ msm_io_w(p1_phy_add, vpe_device->vpebase + VPE_SRCP1_ADDR_OFFSET);
if (vpe_ctrl->state == VPE_STATE_ACTIVE)
CDBG(" =====VPE is busy!!! Wrong!========\n");
@@ -881,7 +881,7 @@
vpe_update_scaler_with_dis(&(vpe_buf->vpe_crop),
&(vpe_ctrl->dis_offset));
- msm_send_frame_to_vpe(vpe_buf->y_phy, vpe_buf->cbcr_phy,
+ msm_send_frame_to_vpe(vpe_buf->p0_phy, vpe_buf->p1_phy,
&(vpe_buf->ts), OUTPUT_TYPE_V);
if (!qcmd || !atomic_read(&qcmd->on_heap)) {
@@ -919,10 +919,10 @@
CDBG("In vpe_addr_convert output_id = %d\n", pinfo->output_id);
- pinfo->y_phy =
- ((struct vpe_message *)data)->_u.msgOut.yBuffer;
- pinfo->cbcr_phy =
- ((struct vpe_message *)data)->_u.msgOut.cbcrBuffer;
+ pinfo->p0_phy =
+ ((struct vpe_message *)data)->_u.msgOut.p0_Buffer;
+ pinfo->p1_phy =
+ ((struct vpe_message *)data)->_u.msgOut.p1_Buffer;
*ext = vpe_ctrl->extdata;
*elen = vpe_ctrl->extlen;
}
@@ -987,10 +987,10 @@
regp1 = &(ad->region[0]);
/* for video Y address */
- p1 = (regp1->paddr + regp1->info.y_off);
+ p1 = (regp1->paddr + regp1->info.planar0_off);
msm_io_w(p1, vpe_device->vpebase + VPE_OUTP0_ADDR_OFFSET);
/* for video CbCr address */
- p1 = (regp1->paddr + regp1->info.cbcr_off);
+ p1 = (regp1->paddr + regp1->info.planar1_off);
msm_io_w(p1, vpe_device->vpebase + VPE_OUTP1_ADDR_OFFSET);
return 0;
@@ -1048,8 +1048,8 @@
vpe_ctrl->frame_pack = frame_pack;
vpe_ctrl->output_type = output_id;
- input_stride = (st_half.buf_cbcr_stride * (1<<16)) +
- st_half.buf_y_stride;
+ input_stride = (st_half.buf_p1_stride * (1<<16)) +
+ st_half.buf_p0_stride;
msm_io_w(input_stride, vpe_device->vpebase + VPE_SRC_YSTRIDE1_OFFSET);
@@ -1059,15 +1059,16 @@
msm_send_frame_to_vpe(pyaddr, pcbcraddr, ts, output_id);
}
-static void vpe_send_outmsg(uint8_t msgid, uint32_t pyaddr,
- uint32_t pcbcraddr)
+static void vpe_send_outmsg(uint8_t msgid, uint32_t p0_addr,
+ uint32_t p1_addr, uint32_t p2_addr)
{
struct vpe_message msg;
uint8_t outid;
msg._d = outid = msgid;
msg._u.msgOut.output_id = msgid;
- msg._u.msgOut.yBuffer = pyaddr;
- msg._u.msgOut.cbcrBuffer = pcbcraddr;
+ msg._u.msgOut.p0_Buffer = p0_addr;
+ msg._u.msgOut.p1_Buffer = p1_addr;
+ msg._u.msgOut.p2_Buffer = p2_addr;
vpe_proc_ops(outid, &msg, sizeof(struct vpe_message));
return;
}
@@ -1203,10 +1204,11 @@
if (vpe_ctrl->output_type == OUTPUT_TYPE_ST_R) {
CDBG("vpe send out R msg.\n");
vpe_send_outmsg(MSG_ID_VPE_OUTPUT_ST_R, pyaddr,
- pcbcraddr);
+ pcbcraddr, pyaddr);
} else if (vpe_ctrl->output_type == OUTPUT_TYPE_V) {
CDBG("vpe send out V msg.\n");
- vpe_send_outmsg(MSG_ID_VPE_OUTPUT_V, pyaddr, pcbcraddr);
+ vpe_send_outmsg(MSG_ID_VPE_OUTPUT_V, pyaddr,
+ pcbcraddr, pyaddr);
}
vpe_ctrl->output_type = 0;
diff --git a/drivers/media/video/msm/msm_vpe1.h b/drivers/media/video/msm/msm_vpe1.h
index ed7112e..f4d328d 100644
--- a/drivers/media/video/msm/msm_vpe1.h
+++ b/drivers/media/video/msm/msm_vpe1.h
@@ -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
@@ -212,8 +212,9 @@
struct vpe_msg_output {
uint8_t output_id;
- uint32_t yBuffer;
- uint32_t cbcrBuffer;
+ uint32_t p0_Buffer;
+ uint32_t p1_Buffer;
+ uint32_t p2_Buffer;
uint32_t frameCounter;
};
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/net/msm_rmnet_bam.c b/drivers/net/msm_rmnet_bam.c
index a0924ed..f11fb60 100644
--- a/drivers/net/msm_rmnet_bam.c
+++ b/drivers/net/msm_rmnet_bam.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
@@ -311,7 +311,7 @@
/* if write() succeeds, skb access is unsafe in this process */
bam_ret = msm_bam_dmux_write(p->ch_id, skb);
- if (bam_ret != 0 && bam_ret != -EAGAIN) {
+ if (bam_ret != 0 && bam_ret != -EAGAIN && bam_ret != -EFAULT) {
pr_err("[%s] %s: write returned error %d",
dev->name, __func__, bam_ret);
return -EPERM;
@@ -464,6 +464,16 @@
if (ret == -EPERM)
return NETDEV_TX_BUSY;
+ /*
+ * detected SSR a bit early. shut some things down now, and leave
+ * the rest to the main ssr handling code when that happens later
+ */
+ if (ret == -EFAULT) {
+ netif_carrier_off(dev);
+ dev_kfree_skb_any(skb);
+ return 0;
+ }
+
if (ret == -EAGAIN) {
/*
* This should not happen
@@ -690,6 +700,7 @@
p = netdev_priv(netdevs[i]);
p->in_reset = 1;
+ p->waiting_for_ul = 0;
msm_bam_dmux_close(p->ch_id);
netif_carrier_off(netdevs[i]);
netif_stop_queue(netdevs[i]);
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 5b2328d..2b58215 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1319,6 +1319,40 @@
}
EXPORT_SYMBOL_GPL(regulator_get);
+static void devm_regulator_release(struct device *dev, void *res)
+{
+ regulator_put(*(struct regulator **)res);
+}
+
+/**
+ * devm_regulator_get - Resource managed regulator_get()
+ * @dev: device for regulator "consumer"
+ * @id: Supply name or regulator ID.
+ *
+ * Managed regulator_get(). Regulators returned from this function are
+ * automatically regulator_put() on driver detach. See regulator_get() for more
+ * information.
+ */
+struct regulator *devm_regulator_get(struct device *dev, const char *id)
+{
+ struct regulator **ptr, *regulator;
+
+ ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ regulator = regulator_get(dev, id);
+ if (!IS_ERR(regulator)) {
+ *ptr = regulator;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return regulator;
+}
+EXPORT_SYMBOL_GPL(devm_regulator_get);
+
/**
* regulator_get_exclusive - obtain exclusive access to a regulator.
* @dev: device for regulator "consumer"
diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c
index e13b4c4..a0763da 100644
--- a/drivers/staging/android/binder.c
+++ b/drivers/staging/android/binder.c
@@ -3,6 +3,7 @@
* Android IPC Subsystem
*
* Copyright (C) 2007-2008 Google, Inc.
+ * Copyright (c) 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
@@ -97,9 +98,9 @@
BINDER_DEBUG_BUFFER_ALLOC = 1U << 13,
BINDER_DEBUG_PRIORITY_CAP = 1U << 14,
BINDER_DEBUG_BUFFER_ALLOC_ASYNC = 1U << 15,
+ BINDER_DEBUG_TOP_ERRORS = 1U << 16,
};
-static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR |
- BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION;
+static uint32_t binder_debug_mask;
module_param_named(debug_mask, binder_debug_mask, uint, S_IWUSR | S_IRUGO);
static int binder_debug_no_lock;
@@ -638,7 +639,8 @@
goto free_range;
if (vma == NULL) {
- printk(KERN_ERR "binder: %d: binder_alloc_buf failed to "
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: %d: binder_alloc_buf failed to "
"map pages in userspace, no vma\n", proc->pid);
goto err_no_vma;
}
@@ -651,7 +653,8 @@
BUG_ON(*page);
*page = alloc_page(GFP_KERNEL | __GFP_ZERO);
if (*page == NULL) {
- printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: %d: binder_alloc_buf failed "
"for page at %p\n", proc->pid, page_addr);
goto err_alloc_page_failed;
}
@@ -660,7 +663,8 @@
page_array_ptr = page;
ret = map_vm_area(&tmp_area, PAGE_KERNEL, &page_array_ptr);
if (ret) {
- printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: %d: binder_alloc_buf failed "
"to map page at %p in kernel\n",
proc->pid, page_addr);
goto err_map_kernel_failed;
@@ -669,7 +673,8 @@
(uintptr_t)page_addr + proc->user_buffer_offset;
ret = vm_insert_page(vma, user_page_addr, page[0]);
if (ret) {
- printk(KERN_ERR "binder: %d: binder_alloc_buf failed "
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: %d: binder_alloc_buf failed "
"to map page at %lx in userspace\n",
proc->pid, user_page_addr);
goto err_vm_insert_page_failed;
@@ -718,7 +723,8 @@
size_t size;
if (proc->vma == NULL) {
- printk(KERN_ERR "binder: %d: binder_alloc_buf, no vma\n",
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: %d: binder_alloc_buf, no vma\n",
proc->pid);
return NULL;
}
@@ -756,7 +762,8 @@
}
}
if (best_fit == NULL) {
- printk(KERN_ERR "binder: %d: binder_alloc_buf size %zd failed, "
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: %d: binder_alloc_buf size %zd failed, "
"no address space\n", proc->pid, size);
return NULL;
}
@@ -991,7 +998,8 @@
node->internal_strong_refs == 0 &&
!(node == binder_context_mgr_node &&
node->has_strong_ref)) {
- printk(KERN_ERR "binder: invalid inc strong "
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: invalid inc strong "
"node for %d\n", node->debug_id);
return -EINVAL;
}
@@ -1007,7 +1015,8 @@
node->local_weak_refs++;
if (!node->has_weak_ref && list_empty(&node->work.entry)) {
if (target_list == NULL) {
- printk(KERN_ERR "binder: invalid inc weak node "
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: invalid inc weak node "
"for %d\n", node->debug_id);
return -EINVAL;
}
@@ -1044,7 +1053,7 @@
if (node->proc) {
rb_erase(&node->rb_node, &node->proc->nodes);
binder_debug(BINDER_DEBUG_INTERNAL_REFS,
- "binder: refless node %d deleted\n",
+ "binder: refless node %d deleted\n",
node->debug_id);
} else {
hlist_del(&node->dead_node);
@@ -1263,14 +1272,16 @@
binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
"binder: send failed reply for "
"transaction %d to %d:%d\n",
- t->debug_id, target_thread->proc->pid,
+ t->debug_id,
+ target_thread->proc->pid,
target_thread->pid);
binder_pop_transaction(target_thread, t);
target_thread->return_error = error_code;
wake_up_interruptible(&target_thread->wait);
} else {
- printk(KERN_ERR "binder: reply failed, target "
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: reply failed, target "
"thread, %d:%d, has error code %d "
"already\n", target_thread->proc->pid,
target_thread->pid,
@@ -1308,14 +1319,15 @@
int debug_id = buffer->debug_id;
binder_debug(BINDER_DEBUG_TRANSACTION,
- "binder: %d buffer release %d, size %zd-%zd, failed at %p\n",
- proc->pid, buffer->debug_id,
+ "binder: %d buffer release %d, size %zd-%zd, failed at"
+ " %p\n", proc->pid, buffer->debug_id,
buffer->data_size, buffer->offsets_size, failed_at);
if (buffer->target_node)
binder_dec_node(buffer->target_node, 1, 0);
- offp = (size_t *)(buffer->data + ALIGN(buffer->data_size, sizeof(void *)));
+ offp = (size_t *)(buffer->data + ALIGN(buffer->data_size,
+ sizeof(void *)));
if (failed_at)
off_end = failed_at;
else
@@ -1325,7 +1337,8 @@
if (*offp > buffer->data_size - sizeof(*fp) ||
buffer->data_size < sizeof(*fp) ||
!IS_ALIGNED(*offp, sizeof(void *))) {
- printk(KERN_ERR "binder: transaction release %d bad"
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: transaction release %d bad"
"offset %zd, size %zd\n", debug_id,
*offp, buffer->data_size);
continue;
@@ -1334,29 +1347,35 @@
switch (fp->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER: {
- struct binder_node *node = binder_get_node(proc, fp->binder);
+ struct binder_node *node = binder_get_node(proc,
+ fp->binder);
if (node == NULL) {
- printk(KERN_ERR "binder: transaction release %d"
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: transaction release %d"
" bad node %p\n", debug_id, fp->binder);
break;
}
binder_debug(BINDER_DEBUG_TRANSACTION,
" node %d u%p\n",
node->debug_id, node->ptr);
- binder_dec_node(node, fp->type == BINDER_TYPE_BINDER, 0);
+ binder_dec_node(node, fp->type == BINDER_TYPE_BINDER,
+ 0);
} break;
case BINDER_TYPE_HANDLE:
case BINDER_TYPE_WEAK_HANDLE: {
- struct binder_ref *ref = binder_get_ref(proc, fp->handle);
+ struct binder_ref *ref = binder_get_ref(proc,
+ fp->handle);
if (ref == NULL) {
- printk(KERN_ERR "binder: transaction release %d"
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: transaction release %d"
" bad handle %ld\n", debug_id,
fp->handle);
break;
}
binder_debug(BINDER_DEBUG_TRANSACTION,
" ref %d desc %d (node %d)\n",
- ref->debug_id, ref->desc, ref->node->debug_id);
+ ref->debug_id, ref->desc,
+ ref->node->debug_id);
binder_dec_ref(ref, fp->type == BINDER_TYPE_HANDLE);
} break;
@@ -1368,7 +1387,8 @@
break;
default:
- printk(KERN_ERR "binder: transaction release %d bad "
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: transaction release %d bad "
"object type %lx\n", debug_id, fp->type);
break;
}
@@ -1594,15 +1614,19 @@
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER: {
struct binder_ref *ref;
- struct binder_node *node = binder_get_node(proc, fp->binder);
+ struct binder_node *node = binder_get_node(proc,
+ fp->binder);
if (node == NULL) {
- node = binder_new_node(proc, fp->binder, fp->cookie);
+ node = binder_new_node(proc, fp->binder,
+ fp->cookie);
if (node == NULL) {
return_error = BR_FAILED_REPLY;
goto err_binder_new_node_failed;
}
- node->min_priority = fp->flags & FLAT_BINDER_FLAG_PRIORITY_MASK;
- node->accept_fds = !!(fp->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS);
+ node->min_priority = fp->flags &
+ FLAT_BINDER_FLAG_PRIORITY_MASK;
+ node->accept_fds = !!(fp->flags &
+ FLAT_BINDER_FLAG_ACCEPTS_FDS);
}
if (fp->cookie != node->cookie) {
binder_user_error("binder: %d:%d sending u%p "
@@ -1632,7 +1656,8 @@
} break;
case BINDER_TYPE_HANDLE:
case BINDER_TYPE_WEAK_HANDLE: {
- struct binder_ref *ref = binder_get_ref(proc, fp->handle);
+ struct binder_ref *ref = binder_get_ref(proc,
+ fp->handle);
if (ref == NULL) {
binder_user_error("binder: %d:%d got "
"transaction with invalid "
@@ -1648,24 +1673,31 @@
fp->type = BINDER_TYPE_WEAK_BINDER;
fp->binder = ref->node->ptr;
fp->cookie = ref->node->cookie;
- binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
+ binder_inc_node(ref->node, fp->type ==
+ BINDER_TYPE_BINDER, 0, NULL);
binder_debug(BINDER_DEBUG_TRANSACTION,
- " ref %d desc %d -> node %d u%p\n",
- ref->debug_id, ref->desc, ref->node->debug_id,
- ref->node->ptr);
+ " ref %d desc %d -> node %d u%p\n",
+ ref->debug_id, ref->desc,
+ ref->node->debug_id,
+ ref->node->ptr);
} else {
struct binder_ref *new_ref;
- new_ref = binder_get_ref_for_node(target_proc, ref->node);
+ new_ref = binder_get_ref_for_node(target_proc,
+ ref->node);
if (new_ref == NULL) {
return_error = BR_FAILED_REPLY;
goto err_binder_get_ref_for_node_failed;
}
fp->handle = new_ref->desc;
- binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
+ binder_inc_ref(new_ref, fp->type ==
+ BINDER_TYPE_HANDLE, NULL);
binder_debug(BINDER_DEBUG_TRANSACTION,
- " ref %d desc %d -> ref %d desc %d (node %d)\n",
- ref->debug_id, ref->desc, new_ref->debug_id,
- new_ref->desc, ref->node->debug_id);
+ " ref %d desc %d -> ref %d"
+ " desc %d (node %d)\n",
+ ref->debug_id, ref->desc,
+ new_ref->debug_id,
+ new_ref->desc,
+ ref->node->debug_id);
}
} break;
@@ -1675,13 +1707,19 @@
if (reply) {
if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {
- binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n",
- proc->pid, thread->pid, fp->handle);
+ binder_user_error("binder: %d:%d got"
+ " reply with fd, %ld, but"
+ " target does not allow fds\n",
+ proc->pid, thread->pid,
+ fp->handle);
return_error = BR_FAILED_REPLY;
goto err_fd_not_allowed;
}
} else if (!target_node->accept_fds) {
- binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n",
+ binder_user_error(
+ "binder: %d:%d got transaction"
+ " with fd, %ld, but target does"
+ " not allow fds\n",
proc->pid, thread->pid, fp->handle);
return_error = BR_FAILED_REPLY;
goto err_fd_not_allowed;
@@ -1689,12 +1727,15 @@
file = fget(fp->handle);
if (file == NULL) {
- binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n",
+ binder_user_error(
+ "binder: %d:%d got transaction"
+ " with invalid fd, %ld\n",
proc->pid, thread->pid, fp->handle);
return_error = BR_FAILED_REPLY;
goto err_fget_failed;
}
- target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);
+ target_fd = task_get_unused_fd_flags(target_proc,
+ O_CLOEXEC);
if (target_fd < 0) {
fput(file);
return_error = BR_FAILED_REPLY;
@@ -1702,7 +1743,8 @@
}
task_fd_install(target_proc, target_fd, file);
binder_debug(BINDER_DEBUG_TRANSACTION,
- " fd %ld -> %d\n", fp->handle, target_fd);
+ " fd %ld -> %d\n", fp->handle,
+ target_fd);
/* TODO: fput? */
fp->handle = target_fd;
} break;
@@ -1851,9 +1893,11 @@
break;
}
binder_debug(BINDER_DEBUG_USER_REFS,
- "binder: %d:%d %s ref %d desc %d s %d w %d for node %d\n",
- proc->pid, thread->pid, debug_string, ref->debug_id,
- ref->desc, ref->strong, ref->weak, ref->node->debug_id);
+ "binder: %d:%d %s ref %d desc %d s %d w %d"
+ " for node %d\n", proc->pid, thread->pid,
+ debug_string, ref->debug_id, ref->desc,
+ ref->strong, ref->weak,
+ ref->node->debug_id);
break;
}
case BC_INCREFS_DONE:
@@ -1914,15 +1958,19 @@
binder_debug(BINDER_DEBUG_USER_REFS,
"binder: %d:%d %s node %d ls %d lw %d\n",
proc->pid, thread->pid,
- cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE" : "BC_ACQUIRE_DONE",
- node->debug_id, node->local_strong_refs, node->local_weak_refs);
+ cmd == BC_INCREFS_DONE ? "BC_INCREFS_DONE"
+ : "BC_ACQUIRE_DONE",
+ node->debug_id, node->local_strong_refs,
+ node->local_weak_refs);
break;
}
case BC_ATTEMPT_ACQUIRE:
- printk(KERN_ERR "binder: BC_ATTEMPT_ACQUIRE not supported\n");
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: BC_ATTEMPT_ACQUIRE not supported\n");
return -EINVAL;
case BC_ACQUIRE_RESULT:
- printk(KERN_ERR "binder: BC_ACQUIRE_RESULT not supported\n");
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: BC_ACQUIRE_RESULT not supported\n");
return -EINVAL;
case BC_FREE_BUFFER: {
@@ -1948,9 +1996,11 @@
break;
}
binder_debug(BINDER_DEBUG_FREE_BUFFER,
- "binder: %d:%d BC_FREE_BUFFER u%p found buffer %d for %s transaction\n",
- proc->pid, thread->pid, data_ptr, buffer->debug_id,
- buffer->transaction ? "active" : "finished");
+ "binder: %d:%d BC_FREE_BUFFER u%p found"
+ " buffer %d for %s transaction\n",
+ proc->pid, thread->pid, data_ptr,
+ buffer->debug_id, buffer->transaction ?
+ "active" : "finished");
if (buffer->transaction) {
buffer->transaction->buffer = NULL;
@@ -2047,13 +2097,15 @@
}
binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
- "binder: %d:%d %s %p ref %d desc %d s %d w %d for node %d\n",
+ "binder: %d:%d %s %p ref %d desc %d s %d"
+ " w %d for node %d\n",
proc->pid, thread->pid,
cmd == BC_REQUEST_DEATH_NOTIFICATION ?
"BC_REQUEST_DEATH_NOTIFICATION" :
"BC_CLEAR_DEATH_NOTIFICATION",
cookie, ref->debug_id, ref->desc,
- ref->strong, ref->weak, ref->node->debug_id);
+ ref->strong, ref->weak,
+ ref->node->debug_id);
if (cmd == BC_REQUEST_DEATH_NOTIFICATION) {
if (ref->death) {
@@ -2067,10 +2119,12 @@
death = kzalloc(sizeof(*death), GFP_KERNEL);
if (death == NULL) {
thread->return_error = BR_ERROR;
- binder_debug(BINDER_DEBUG_FAILED_TRANSACTION,
- "binder: %d:%d "
- "BC_REQUEST_DEATH_NOTIFICATION failed\n",
- proc->pid, thread->pid);
+ binder_debug(
+ BINDER_DEBUG_FAILED_TRANSACTION,
+ "binder: %d:%d "
+ "BC_REQUEST_DEATH_NOTIFICATION"
+ " failed\n",
+ proc->pid, thread->pid);
break;
}
binder_stats_created(BINDER_STAT_DEATH);
@@ -2159,7 +2213,8 @@
} break;
default:
- printk(KERN_ERR "binder: %d:%d unknown command %d\n",
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: %d:%d unknown command %d\n",
proc->pid, thread->pid, cmd);
return -EINVAL;
}
@@ -2629,9 +2684,11 @@
unsigned int size = _IOC_SIZE(cmd);
void __user *ubuf = (void __user *)arg;
- /*printk(KERN_INFO "binder_ioctl: %d:%d %x %lx\n", proc->pid, current->pid, cmd, arg);*/
+ /*binder_debug(BINDER_DEBUG_TOP_ERRORS, "binder_ioctl: %d:%d %x %lx\n",
+ proc->pid, current->pid, cmd, arg);*/
- ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
+ ret = wait_event_interruptible(binder_user_error_wait,
+ binder_stop_on_user_error < 2);
if (ret)
return ret;
@@ -2688,20 +2745,23 @@
break;
}
case BINDER_SET_MAX_THREADS:
- if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
+ if (copy_from_user(&proc->max_threads, ubuf,
+ sizeof(proc->max_threads))) {
ret = -EINVAL;
goto err;
}
break;
case BINDER_SET_CONTEXT_MGR:
if (binder_context_mgr_node != NULL) {
- printk(KERN_ERR "binder: BINDER_SET_CONTEXT_MGR already set\n");
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: BINDER_SET_CONTEXT_MGR already set\n");
ret = -EBUSY;
goto err;
}
if (binder_context_mgr_uid != -1) {
if (binder_context_mgr_uid != current->cred->euid) {
- printk(KERN_ERR "binder: BINDER_SET_"
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: BINDER_SET_"
"CONTEXT_MGR bad uid %d != %d\n",
current->cred->euid,
binder_context_mgr_uid);
@@ -2747,7 +2807,9 @@
mutex_unlock(&binder_lock);
wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
if (ret && ret != -ERESTARTSYS)
- printk(KERN_INFO "binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: %d:%d ioctl %x %lx returned %d\n",
+ proc->pid, current->pid, cmd, arg, ret);
return ret;
}
@@ -2821,7 +2883,9 @@
#ifdef CONFIG_CPU_CACHE_VIPT
if (cache_is_vipt_aliasing()) {
while (CACHE_COLOUR((vma->vm_start ^ (uint32_t)proc->buffer))) {
- printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p bad alignment\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder_mmap: %d %lx-%lx maps %p bad alignment\n",
+ proc->pid, vma->vm_start, vma->vm_end, proc->buffer);
vma->vm_start += PAGE_SIZE;
}
}
@@ -2852,7 +2916,8 @@
proc->files = get_files_struct(current);
proc->vma = vma;
- /*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n",
+ /*binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder_mmap: %d %lx-%lx maps %p\n",
proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/
return 0;
@@ -2865,7 +2930,8 @@
err_get_vm_area_failed:
err_already_mapped:
err_bad_arg:
- printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n",
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder_mmap: %d %lx-%lx %s failed %d\n",
proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
return ret;
}
@@ -3020,7 +3086,8 @@
if (t) {
t->buffer = NULL;
buffer->transaction = NULL;
- printk(KERN_ERR "binder: release proc %d, "
+ binder_debug(BINDER_DEBUG_TOP_ERRORS,
+ "binder: release proc %d, "
"transaction %d, not freed\n",
proc->pid, t->debug_id);
/*BUG();*/
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/misc/mdm_ctrl_bridge.c b/drivers/usb/misc/mdm_ctrl_bridge.c
index 11d388c..584503a 100644
--- a/drivers/usb/misc/mdm_ctrl_bridge.c
+++ b/drivers/usb/misc/mdm_ctrl_bridge.c
@@ -333,6 +333,7 @@
static void ctrl_write_callback(struct urb *urb)
{
+ struct ctrl_bridge *dev = urb->context;
if (urb->status) {
pr_debug("Write status/size %d/%d\n",
@@ -342,6 +343,7 @@
kfree(urb->transfer_buffer);
kfree(urb->setup_packet);
usb_free_urb(urb);
+ usb_autopm_put_interface_async(dev->intf);
}
int ctrl_bridge_write(unsigned int id, char *data, size_t size)
@@ -406,7 +408,7 @@
usb_sndctrlpipe(udev, 0),
(unsigned char *)out_ctlreq,
(void *)data, size,
- ctrl_write_callback, NULL);
+ ctrl_write_callback, dev);
result = usb_autopm_get_interface_async(dev->intf);
if (result < 0) {
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/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 60a40b2..fc6054f 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -2324,29 +2324,6 @@
msm_hdmi_init_ddc();
- /* Read Bksv 5 bytes at 0x00 in HDCP port */
- ret = hdmi_msm_ddc_read(0x74, 0x00, bksv, 5, 5, "Bksv", TRUE);
- if (ret) {
- DEV_ERR("%s(%d): Read BKSV failed", __func__, __LINE__);
- goto error;
- }
- /* check there are 20 ones in BKSV */
- if (hdmi_msm_count_one(bksv, 5) != 20) {
- DEV_ERR("HDCP: BKSV read from Sink doesn't have "
- "20 1's and 20 0's, FAIL (BKSV="
- "%02x%02x%02x%02x%02x)\n",
- bksv[4], bksv[3], bksv[2], bksv[1], bksv[0]);
- ret = -EINVAL;
- goto error;
- }
-
- link0_bksv_0 = bksv[3];
- link0_bksv_0 = (link0_bksv_0 << 8) | bksv[2];
- link0_bksv_0 = (link0_bksv_0 << 8) | bksv[1];
- link0_bksv_0 = (link0_bksv_0 << 8) | bksv[0];
- link0_bksv_1 = bksv[4];
- DEV_DBG("HDCP: BKSV=%02x%08x\n", link0_bksv_1, link0_bksv_0);
-
/* read Bcaps at 0x40 in HDCP Port */
ret = hdmi_msm_ddc_read(0x74, 0x40, &bcaps, 1, 5, "Bcaps",
TRUE);
@@ -2494,6 +2471,29 @@
DEV_DBG("HDCP: Link0-AKSV=%02x%08x\n",
link0_aksv_1 & 0xFF, link0_aksv_0);
+ /* Read Bksv 5 bytes at 0x00 in HDCP port */
+ ret = hdmi_msm_ddc_read(0x74, 0x00, bksv, 5, 5, "Bksv", TRUE);
+ if (ret) {
+ DEV_ERR("%s(%d): Read BKSV failed", __func__, __LINE__);
+ goto error;
+ }
+ /* check there are 20 ones in BKSV */
+ if (hdmi_msm_count_one(bksv, 5) != 20) {
+ DEV_ERR("HDCP: BKSV read from Sink doesn't have "
+ "20 1's and 20 0's, FAIL (BKSV="
+ "%02x%02x%02x%02x%02x)\n",
+ bksv[4], bksv[3], bksv[2], bksv[1], bksv[0]);
+ ret = -EINVAL;
+ goto error;
+ }
+
+ link0_bksv_0 = bksv[3];
+ link0_bksv_0 = (link0_bksv_0 << 8) | bksv[2];
+ link0_bksv_0 = (link0_bksv_0 << 8) | bksv[1];
+ link0_bksv_0 = (link0_bksv_0 << 8) | bksv[0];
+ link0_bksv_1 = bksv[4];
+ DEV_DBG("HDCP: BKSV=%02x%08x\n", link0_bksv_1, link0_bksv_0);
+
/* 0x0134 HDCP_RCVPORT_DATA0
[31:0] LINK0_BKSV_0 */
HDMI_OUTP(0x0134, link0_bksv_0);
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/msm_audio_acdb.h b/include/linux/msm_audio_acdb.h
index 3d756c2..e7f06b5 100644
--- a/include/linux/msm_audio_acdb.h
+++ b/include/linux/msm_audio_acdb.h
@@ -35,6 +35,13 @@
(AUDIO_MAX_COMMON_IOCTL_NUM+14), unsigned)
#define AUDIO_SET_ASM_TOPOLOGY _IOW(AUDIO_IOCTL_MAGIC, \
(AUDIO_MAX_COMMON_IOCTL_NUM+15), unsigned)
+#define AUDIO_SET_AFE_TX_CAL _IOW(AUDIO_IOCTL_MAGIC, \
+ (AUDIO_MAX_COMMON_IOCTL_NUM+16), unsigned)
+#define AUDIO_SET_AFE_RX_CAL _IOW(AUDIO_IOCTL_MAGIC, \
+ (AUDIO_MAX_COMMON_IOCTL_NUM+17), unsigned)
+
+
+#define AUDIO_MAX_ACDB_IOCTL (AUDIO_MAX_COMMON_IOCTL_NUM+30)
/* ACDB structures */
struct cal_block {
@@ -49,25 +56,26 @@
/* For Real-Time Audio Calibration */
#define AUDIO_GET_RTAC_ADM_INFO _IOR(AUDIO_IOCTL_MAGIC, \
- (AUDIO_MAX_COMMON_IOCTL_NUM+16), unsigned)
+ (AUDIO_MAX_ACDB_IOCTL+1), unsigned)
#define AUDIO_GET_RTAC_VOICE_INFO _IOR(AUDIO_IOCTL_MAGIC, \
- (AUDIO_MAX_COMMON_IOCTL_NUM+17), unsigned)
+ (AUDIO_MAX_ACDB_IOCTL+2), unsigned)
#define AUDIO_GET_RTAC_ADM_CAL _IOWR(AUDIO_IOCTL_MAGIC, \
- (AUDIO_MAX_COMMON_IOCTL_NUM+18), unsigned)
+ (AUDIO_MAX_ACDB_IOCTL+3), unsigned)
#define AUDIO_SET_RTAC_ADM_CAL _IOWR(AUDIO_IOCTL_MAGIC, \
- (AUDIO_MAX_COMMON_IOCTL_NUM+19), unsigned)
+ (AUDIO_MAX_ACDB_IOCTL+4), unsigned)
#define AUDIO_GET_RTAC_ASM_CAL _IOWR(AUDIO_IOCTL_MAGIC, \
- (AUDIO_MAX_COMMON_IOCTL_NUM+20), unsigned)
+ (AUDIO_MAX_ACDB_IOCTL+5), unsigned)
#define AUDIO_SET_RTAC_ASM_CAL _IOWR(AUDIO_IOCTL_MAGIC, \
- (AUDIO_MAX_COMMON_IOCTL_NUM+21), unsigned)
+ (AUDIO_MAX_ACDB_IOCTL+6), unsigned)
#define AUDIO_GET_RTAC_CVS_CAL _IOWR(AUDIO_IOCTL_MAGIC, \
- (AUDIO_MAX_COMMON_IOCTL_NUM+22), unsigned)
+ (AUDIO_MAX_ACDB_IOCTL+7), unsigned)
#define AUDIO_SET_RTAC_CVS_CAL _IOWR(AUDIO_IOCTL_MAGIC, \
- (AUDIO_MAX_COMMON_IOCTL_NUM+23), unsigned)
+ (AUDIO_MAX_ACDB_IOCTL+8), unsigned)
#define AUDIO_GET_RTAC_CVP_CAL _IOWR(AUDIO_IOCTL_MAGIC, \
- (AUDIO_MAX_COMMON_IOCTL_NUM+24), unsigned)
+ (AUDIO_MAX_ACDB_IOCTL+9), unsigned)
#define AUDIO_SET_RTAC_CVP_CAL _IOWR(AUDIO_IOCTL_MAGIC, \
- (AUDIO_MAX_COMMON_IOCTL_NUM+25), unsigned)
+ (AUDIO_MAX_ACDB_IOCTL+10), unsigned)
+#define AUDIO_MAX_RTAC_IOCTL (AUDIO_MAX_ACDB_IOCTL+20)
#endif /* __MSM_AUDIO_ACDB_H */
diff --git a/include/linux/regulator/consumer.h b/include/linux/regulator/consumer.h
index fb5d4e4..f46449a 100644
--- a/include/linux/regulator/consumer.h
+++ b/include/linux/regulator/consumer.h
@@ -135,6 +135,8 @@
/* regulator get and put */
struct regulator *__must_check regulator_get(struct device *dev,
const char *id);
+struct regulator *__must_check devm_regulator_get(struct device *dev,
+ const char *id);
struct regulator *__must_check regulator_get_exclusive(struct device *dev,
const char *id);
void regulator_put(struct regulator *regulator);
@@ -202,6 +204,13 @@
*/
return NULL;
}
+
+static inline struct regulator *__must_check
+devm_regulator_get(struct device *dev, const char *id)
+{
+ return NULL;
+}
+
static inline void regulator_put(struct regulator *regulator)
{
}
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/include/media/msm_camera.h b/include/media/msm_camera.h
index 423a849..a984943 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -396,11 +396,11 @@
#define CMD_AXI_CFG_ZSL 43
#define CMD_AXI_CFG_SNAP_VPE 44
#define CMD_AXI_CFG_SNAP_THUMB_VPE 45
-#define CMD_AXI_CFG_VIDEO_ALL_CHNLS 46
-#define CMD_AXI_CFG_ZSL_ALL_CHNLS 47
-#define CMD_CONFIG_PING_ADDR 48
-#define CMD_CONFIG_PONG_ADDR 49
-#define CMD_CONFIG_FREE_BUF_ADDR 50
+#define CMD_CONFIG_PING_ADDR 46
+#define CMD_CONFIG_PONG_ADDR 47
+#define CMD_CONFIG_FREE_BUF_ADDR 48
+#define CMD_AXI_CFG_ZSL_ALL_CHNLS 49
+#define CMD_AXI_CFG_VIDEO_ALL_CHNLS 50
/* vfe config command: config command(from config thread)*/
struct msm_vfe_cfg_cmd {
@@ -467,6 +467,9 @@
uint32_t len;
uint32_t y_off;
uint32_t cbcr_off;
+ uint32_t planar0_off;
+ uint32_t planar1_off;
+ uint32_t planar2_off;
uint8_t active;
};
@@ -487,8 +490,9 @@
#define OUTPUT_2_AND_CAMIF_TO_AXI_VIA_OUTPUT_1 6
#define OUTPUT_1_2_AND_3 7
#define OUTPUT_ALL_CHNLS 8
-#define OUTPUT_ZSL_ALL_CHNLS 9
-#define LAST_AXI_OUTPUT_MODE_ENUM OUTPUT_ZSL_ALL_CHNLS
+#define OUTPUT_VIDEO_ALL_CHNLS 9
+#define OUTPUT_ZSL_ALL_CHNLS 10
+#define LAST_AXI_OUTPUT_MODE_ENUM = OUTPUT_ZSL_ALL_CHNLS
#define MSM_FRAME_PREV_1 0
#define MSM_FRAME_PREV_2 1
@@ -528,6 +532,9 @@
uint32_t phy_offset;
uint32_t y_off;
uint32_t cbcr_off;
+ uint32_t planar0_off;
+ uint32_t planar1_off;
+ uint32_t planar2_off;
int fd;
void *cropinfo;
@@ -557,10 +564,10 @@
};
struct msm_st_half {
- uint32_t buf_y_off;
- uint32_t buf_cbcr_off;
- uint32_t buf_y_stride;
- uint32_t buf_cbcr_stride;
+ uint32_t buf_p0_off;
+ uint32_t buf_p1_off;
+ uint32_t buf_p0_stride;
+ uint32_t buf_p1_stride;
uint32_t pix_x_off;
uint32_t pix_y_off;
struct msm_st_crop stCropInfo;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 857f654..8e66a25 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1047,6 +1047,8 @@
/* LE SMP Management interface */
int le_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, void *cp);
int mgmt_remote_class(u16 index, bdaddr_t *bdaddr, u8 dev_class[3]);
+int mgmt_remote_version(u16 index, bdaddr_t *bdaddr, u8 ver, u16 mnf,
+ u16 sub_ver);
/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 30536a2..312de3f 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -294,8 +294,6 @@
struct l2cap_conf_prm {
__u8 fcs;
- __le16 retrans_timeout;
- __le16 monitor_timeout;
__le32 flush_to;
};
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index de61c32..9e79fb3 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -347,3 +347,11 @@
bdaddr_t bdaddr;
__u8 dev_class[3];
} __packed;
+
+#define MGMT_EV_REMOTE_VERSION 0x0018
+struct mgmt_ev_remote_version {
+ bdaddr_t bdaddr;
+ __u8 lmp_ver;
+ __u16 manufacturer;
+ __u16 lmp_subver;
+} __packed;
diff --git a/include/sound/apr_audio.h b/include/sound/apr_audio.h
index 798ed89..30f1a7c 100644
--- a/include/sound/apr_audio.h
+++ b/include/sound/apr_audio.h
@@ -1,7 +1,6 @@
-
/*
*
- * 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
@@ -353,6 +352,12 @@
struct afe_param_payload payload;
} __attribute__ ((packed));
+struct afe_port_cmd_set_param_no_payload {
+ struct apr_hdr hdr;
+ u16 port_id;
+ u16 payload_size;
+ u32 payload_address;
+} __packed;
#define AFE_EVENT_GET_ACTIVE_PORTS 0x00010100
struct afe_get_active_ports_rsp {
diff --git a/include/sound/q6afe.h b/include/sound/q6afe.h
index 6206838..2d0f53f 100644
--- a/include/sound/q6afe.h
+++ b/include/sound/q6afe.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
@@ -76,7 +76,9 @@
int afe_start_pseudo_port(u16 port_id);
int afe_stop_pseudo_port(u16 port_id);
int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz);
+int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz);
int afe_cmd_memory_unmap(u32 dma_addr_p);
+int afe_cmd_memory_unmap_nowait(u32 dma_addr_p);
int afe_register_get_events(u16 port_id,
void (*cb) (uint32_t opcode,
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/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index f98a90e..675b34f 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1606,12 +1606,12 @@
if (test_bit(HCI_ENCRYPT, &hdev->flags))
conn->link_mode |= HCI_LM_ENCRYPT;
- /* Get remote features */
+ /* Get remote version */
if (conn->type == ACL_LINK) {
- struct hci_cp_read_remote_features cp;
+ struct hci_cp_read_remote_version cp;
cp.handle = ev->handle;
- hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
- sizeof(cp), &cp);
+ hci_send_cmd(hdev, HCI_OP_READ_REMOTE_VERSION,
+ sizeof(cp), &cp);
}
/* Set packet type for incoming connection */
@@ -1959,7 +1959,24 @@
static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
- BT_DBG("%s", hdev->name);
+ struct hci_ev_remote_version *ev = (void *) skb->data;
+ struct hci_cp_read_remote_features cp;
+ struct hci_conn *conn;
+ BT_DBG("%s status %d", hdev->name, ev->status);
+
+ hci_dev_lock(hdev);
+ cp.handle = ev->handle;
+ hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
+ sizeof(cp), &cp);
+
+ conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
+ if (!conn)
+ goto unlock;
+ if (!ev->status)
+ mgmt_remote_version(hdev->id, &conn->dst, ev->lmp_ver,
+ ev->manufacturer, ev->lmp_subver);
+unlock:
+ hci_dev_unlock(hdev);
}
static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index cf6cf59..ded74dc 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3212,6 +3212,44 @@
return chan;
}
+static void l2cap_get_ertm_timeouts(struct l2cap_conf_rfc *rfc,
+ struct l2cap_pinfo *pi)
+{
+ if (pi->amp_id && pi->ampcon) {
+ u64 ertm_to = pi->ampcon->hdev->amp_be_flush_to;
+
+ /* Class 1 devices have must have ERTM timeouts
+ * exceeding the Link Supervision Timeout. The
+ * default Link Supervision Timeout for AMP
+ * controllers is 10 seconds.
+ *
+ * Class 1 devices use 0xffffffff for their
+ * best-effort flush timeout, so the clamping logic
+ * will result in a timeout that meets the above
+ * requirement. ERTM timeouts are 16-bit values, so
+ * the maximum timeout is 65.535 seconds.
+ */
+
+ /* Convert timeout to milliseconds and round */
+ ertm_to = div_u64(ertm_to + 999, 1000);
+
+ /* This is the recommended formula for class 2 devices
+ * that start ERTM timers when packets are sent to the
+ * controller.
+ */
+ ertm_to = 3 * ertm_to + 500;
+
+ if (ertm_to > 0xffff)
+ ertm_to = 0xffff;
+
+ rfc->retrans_timeout = cpu_to_le16((u16) ertm_to);
+ rfc->monitor_timeout = rfc->retrans_timeout;
+ } else {
+ rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
+ rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
+ }
+}
+
int l2cap_build_conf_req(struct sock *sk, void *data)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
@@ -3262,10 +3300,10 @@
rfc.txwin_size = L2CAP_TX_WIN_MAX_ENHANCED;
else
rfc.txwin_size = pi->tx_win;
- rfc.max_transmit = pi->max_tx;
- rfc.retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
- rfc.monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
- rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
+ rfc.max_transmit = pi->max_tx;
+ rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
+ l2cap_get_ertm_timeouts(&rfc, pi);
+
if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->imtu)
rfc.max_pdu_size = cpu_to_le16(pi->imtu);
@@ -3337,30 +3375,16 @@
struct l2cap_conf_req *req = data;
struct l2cap_conf_rfc rfc = { .mode = pi->mode };
void *ptr = req->data;
- u32 be_flush_to;
BT_DBG("sk %p", sk);
- /* convert to milliseconds, round up */
- be_flush_to = (pi->conn->hcon->hdev->amp_be_flush_to + 999) / 1000;
-
switch (pi->mode) {
case L2CAP_MODE_ERTM:
rfc.mode = L2CAP_MODE_ERTM;
rfc.txwin_size = pi->tx_win;
rfc.max_transmit = pi->max_tx;
- if (pi->amp_move_id) {
- rfc.retrans_timeout =
- cpu_to_le16((3 * be_flush_to) + 500);
- rfc.monitor_timeout =
- cpu_to_le16((3 * be_flush_to) + 500);
- } else {
- rfc.retrans_timeout =
- cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
- rfc.monitor_timeout =
- cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
- }
rfc.max_pdu_size = cpu_to_le16(L2CAP_DEFAULT_MAX_PDU_SIZE);
+ l2cap_get_ertm_timeouts(&rfc, pi);
if (L2CAP_DEFAULT_MAX_PDU_SIZE > pi->imtu)
rfc.max_pdu_size = cpu_to_le16(pi->imtu);
@@ -3374,17 +3398,16 @@
(unsigned long) &rfc);
if (pi->conn->feat_mask & L2CAP_FEAT_FCS) {
-
/* TODO assign fcs for br/edr based on socket config option */
- if (pi->amp_move_id)
+ /* FCS is not used with AMP because it is redundant - lower
+ * layers already include a checksum. */
+ if (pi->amp_id)
pi->local_conf.fcs = L2CAP_FCS_NONE;
else
pi->local_conf.fcs = L2CAP_FCS_CRC16;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
- pi->local_conf.fcs);
-
- pi->fcs = pi->local_conf.fcs | pi->remote_conf.fcs;
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->local_conf.fcs);
+ pi->fcs = pi->local_conf.fcs | pi->remote_conf.fcs;
}
req->dcid = cpu_to_le16(pi->dcid);
@@ -3546,15 +3569,9 @@
case L2CAP_MODE_ERTM:
if (!(pi->conf_state & L2CAP_CONF_EXT_WIN_RECV))
pi->remote_tx_win = rfc.txwin_size;
-
pi->remote_max_tx = rfc.max_transmit;
-
pi->remote_mps = le16_to_cpu(rfc.max_pdu_size);
-
- rfc.retrans_timeout =
- cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO);
- rfc.monitor_timeout =
- cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO);
+ l2cap_get_ertm_timeouts(&rfc, pi);
pi->conf_state |= L2CAP_CONF_MODE_DONE;
@@ -3660,9 +3677,6 @@
case L2CAP_CONF_RFC:
if (olen == sizeof(rfc))
memcpy(&rfc, (void *) val, olen);
- if (pi->mode != rfc.mode ||
- rfc.mode == L2CAP_MODE_BASIC)
- result = L2CAP_CONF_UNACCEPT;
break;
case L2CAP_CONF_FCS:
@@ -3698,6 +3712,9 @@
BT_DBG("result 0x%2.2x cur mode 0x%2.2x req mode 0x%2.2x",
result, pi->mode, rfc.mode);
+ if (pi->mode != rfc.mode || rfc.mode == L2CAP_MODE_BASIC)
+ result = L2CAP_CONF_UNACCEPT;
+
if (result == L2CAP_CONF_SUCCESS) {
/* Configure output options and let the other side know
* which ones we don't like. */
@@ -3717,38 +3734,26 @@
pi->remote_tx_win);
}
+ pi->remote_mps = rfc.max_pdu_size;
+
if (rfc.mode == L2CAP_MODE_ERTM) {
- pi->remote_conf.retrans_timeout =
- le16_to_cpu(rfc.retrans_timeout);
- pi->remote_conf.monitor_timeout =
- le16_to_cpu(rfc.monitor_timeout);
-
- BT_DBG("remote conf monitor timeout %d",
- pi->remote_conf.monitor_timeout);
-
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ l2cap_get_ertm_timeouts(&rfc, pi);
+ } else {
+ rfc.retrans_timeout = 0;
+ rfc.monitor_timeout = 0;
}
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
+ sizeof(rfc), (unsigned long) &rfc);
}
if (result != L2CAP_CONF_SUCCESS)
goto done;
- pi->fcs = pi->remote_conf.fcs | pi->local_conf.fcs ;
+ pi->fcs = pi->remote_conf.fcs | pi->local_conf.fcs;
- if (pi->rx_state == L2CAP_ERTM_RX_STATE_WAIT_F_FLAG) {
+ if (pi->rx_state == L2CAP_ERTM_RX_STATE_WAIT_F_FLAG)
pi->flush_to = pi->remote_conf.flush_to;
- pi->retrans_timeout = pi->remote_conf.retrans_timeout;
-
- if (pi->amp_move_id)
- pi->monitor_timeout = pi->remote_conf.monitor_timeout;
- else
- pi->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
- BT_DBG("mode %d monitor timeout %d",
- pi->mode, pi->monitor_timeout);
-
- }
done:
rsp->scid = cpu_to_le16(pi->dcid);
@@ -3972,34 +3977,41 @@
if (type == L2CAP_CONF_RFC) {
if (olen == sizeof(rfc))
memcpy(&rfc, (void *)val, olen);
- if (rfc.mode != pi->mode &&
- rfc.mode != L2CAP_MODE_ERTM) {
- err = -ECONNREFUSED;
- goto done;
+
+ if (rfc.mode != pi->mode) {
+ l2cap_send_disconn_req(pi->conn, sk,
+ ECONNRESET);
+ return -ECONNRESET;
}
- break;
+
+ goto done;
}
}
}
+ BT_ERR("Expected RFC option was missing, using existing values");
+
+ rfc.mode = pi->mode;
+ rfc.retrans_timeout = cpu_to_le16(pi->retrans_timeout);
+ rfc.monitor_timeout = cpu_to_le16(pi->monitor_timeout);
+
done:
l2cap_ertm_stop_ack_timer(pi);
l2cap_ertm_stop_retrans_timer(pi);
l2cap_ertm_stop_monitor_timer(pi);
+ pi->mps = le16_to_cpu(rfc.max_pdu_size);
+ if (pi->mode == L2CAP_MODE_ERTM) {
+ pi->retrans_timeout = le16_to_cpu(rfc.retrans_timeout);
+ pi->monitor_timeout = le16_to_cpu(rfc.monitor_timeout);
+ }
+
if (l2cap_pi(sk)->reconf_state == L2CAP_RECONF_ACC) {
l2cap_pi(sk)->reconf_state = L2CAP_RECONF_NONE;
/* Respond to poll */
err = l2cap_answer_move_poll(sk);
-
} else if (l2cap_pi(sk)->reconf_state == L2CAP_RECONF_INT) {
-
- /* If moving to BR/EDR, use default timeout defined by
- * the spec */
- if (pi->amp_move_id == 0)
- pi->monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
-
if (pi->mode == L2CAP_MODE_ERTM) {
l2cap_ertm_tx(sk, NULL, NULL,
L2CAP_ERTM_EVENT_EXPLICIT_POLL);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 93e7b04..94cacde 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1,6 +1,6 @@
/*
BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
+ Copyright (c) 2000-2001, 2011-2012 Code Aurora Forum. All rights reserved.
Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Copyright (C) 2010 Google Inc.
@@ -1123,8 +1123,6 @@
static void set_default_config(struct l2cap_conf_prm *conf_prm)
{
conf_prm->fcs = L2CAP_FCS_CRC16;
- conf_prm->retrans_timeout = 0;
- conf_prm->monitor_timeout = 0;
conf_prm->flush_to = L2CAP_DEFAULT_FLUSH_TO;
}
@@ -1186,14 +1184,6 @@
pi->extended_control = 0;
pi->local_conf.fcs = pi->fcs;
- if (pi->mode == L2CAP_MODE_BASIC) {
- pi->local_conf.retrans_timeout = 0;
- pi->local_conf.monitor_timeout = 0;
- } else {
- pi->local_conf.retrans_timeout = L2CAP_DEFAULT_RETRANS_TO;
- pi->local_conf.monitor_timeout = L2CAP_DEFAULT_MONITOR_TO;
- }
-
pi->local_conf.flush_to = pi->flush_to;
set_default_config(&pi->remote_conf);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 67a2900..74b1d2d 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2893,3 +2893,18 @@
return mgmt_event(MGMT_EV_REMOTE_CLASS, index, &ev, sizeof(ev), NULL);
}
+
+int mgmt_remote_version(u16 index, bdaddr_t *bdaddr, u8 ver, u16 mnf,
+ u16 sub_ver)
+{
+ struct mgmt_ev_remote_version ev;
+
+ memset(&ev, 0, sizeof(ev));
+
+ bacpy(&ev.bdaddr, bdaddr);
+ ev.lmp_ver = ver;
+ ev.manufacturer = mnf;
+ ev.lmp_subver = sub_ver;
+
+ return mgmt_event(MGMT_EV_REMOTE_VERSION, index, &ev, sizeof(ev), NULL);
+}
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 30da5c6..cec01f1 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -106,6 +106,7 @@
u16 dce_mb;
u16 sta_z;
u16 sta_mb;
+ u32 t_sta_dce;
u32 t_dce;
u32 t_sta;
u32 micb_mv;
@@ -3081,6 +3082,8 @@
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x4);
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
+ usleep_range(tabla->mbhc_data.t_sta_dce,
+ tabla->mbhc_data.t_sta_dce);
snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x4);
usleep_range(tabla->mbhc_data.t_dce,
tabla->mbhc_data.t_dce);
@@ -3089,7 +3092,8 @@
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x2);
snd_soc_update_bits(codec, TABLA_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
- usleep_range(50, 50);
+ usleep_range(tabla->mbhc_data.t_sta_dce,
+ tabla->mbhc_data.t_sta_dce);
snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x2);
usleep_range(tabla->mbhc_data.t_sta,
tabla->mbhc_data.t_sta);
@@ -3386,19 +3390,8 @@
nmeas = TABLA_MBHC_CAL_BTN_DET_PTR(tabla->calibration)->n_meas;
navg = TABLA_MBHC_CAL_GENERAL_PTR(tabla->calibration)->mbhc_navg;
mclk_rate = tabla->mclk_freq;
- dce_wait = (1000 * 512 * ncic * nmeas) / (mclk_rate / 1000);
- if (tabla->mclk_freq == TABLA_MCLK_RATE_12288KHZ)
- dce_wait = dce_wait + 10000;
- else if (tabla->mclk_freq == TABLA_MCLK_RATE_9600KHZ)
- dce_wait = dce_wait + 9810;
- else
- WARN(1, "Unsupported mclk freq %d\n", tabla->mclk_freq);
-
- sta_wait = (1000 * 128 * navg) / (mclk_rate / 1000);
-
- /* Add 10 microseconds to handle error margin */
- dce_wait = dce_wait + 10;
- sta_wait = sta_wait + 10;
+ dce_wait = (1000 * 512 * ncic * (nmeas + 1)) / (mclk_rate / 1000);
+ sta_wait = (1000 * 128 * (navg + 1)) / (mclk_rate / 1000);
tabla->mbhc_data.t_dce = dce_wait;
tabla->mbhc_data.t_sta = sta_wait;
@@ -3515,8 +3508,11 @@
tabla->mbhc_data.nready = 2;
tabla->mbhc_data.npoll = 7;
tabla->mbhc_data.nbounce_wait = 23;
- }
+ } else
+ WARN(1, "Unsupported mclk freq %d\n", tabla->mclk_freq);
+ tabla->mbhc_data.t_sta_dce = ((1000 * 256) / (tabla->mclk_freq / 1000) *
+ tabla->mbhc_data.nready) + 10;
tabla->mbhc_data.v_ins_hu =
tabla_codec_v_sta_dce(codec, STA, plug_type->v_hs_max);
tabla->mbhc_data.v_ins_h =
@@ -4477,6 +4473,7 @@
/* Make sure mbhc intenal calibration data is zeroed out */
memset(&tabla->mbhc_data, 0,
sizeof(struct mbhc_internal_cal_data));
+ tabla->mbhc_data.t_sta_dce = DEFAULT_DCE_STA_WAIT;
tabla->mbhc_data.t_dce = DEFAULT_DCE_WAIT;
tabla->mbhc_data.t_sta = DEFAULT_STA_WAIT;
snd_soc_codec_set_drvdata(codec, tabla);
diff --git a/sound/soc/codecs/wcd9310.h b/sound/soc/codecs/wcd9310.h
index 3f987cc..77bfc73 100644
--- a/sound/soc/codecs/wcd9310.h
+++ b/sound/soc/codecs/wcd9310.h
@@ -21,7 +21,7 @@
#define TABLA_REG_VAL(reg, val) {reg, 0, val}
-
+#define DEFAULT_DCE_STA_WAIT 55
#define DEFAULT_DCE_WAIT 60000
#define DEFAULT_STA_WAIT 5000
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,
diff --git a/sound/soc/msm/qdsp6/q6adm.c b/sound/soc/msm/qdsp6/q6adm.c
index 18dfc01..d8d9c64 100644
--- a/sound/soc/msm/qdsp6/q6adm.c
+++ b/sound/soc/msm/qdsp6/q6adm.c
@@ -457,7 +457,7 @@
int i = 0;
int cmd_size = 0;
- pr_info("%s\n", __func__);
+ pr_debug("%s\n", __func__);
if (this_adm.apr == NULL) {
this_adm.apr = apr_register("ADSP", "ADM", adm_callback,
0xFFFFFFFF, &this_adm);
@@ -532,7 +532,7 @@
int i = 0;
int cmd_size = 0;
- pr_info("%s\n", __func__);
+ pr_debug("%s\n", __func__);
if (this_adm.apr == NULL) {
pr_err("%s APR handle NULL\n", __func__);
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index 74a66945..a214529 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.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
@@ -17,6 +17,7 @@
#include <linux/wait.h>
#include <linux/jiffies.h>
#include <linux/sched.h>
+#include <mach/qdsp6v2/audio_acdb.h>
#include <sound/apr_audio.h>
#include <sound/q6afe.h>
@@ -36,6 +37,8 @@
static struct afe_ctl this_afe;
+static uint32_t afe_cal_addr[MAX_AUDPROC_TYPES];
+
#define TIMEOUT_MS 1000
#define Q6AFE_MAX_VOLUME 0x3FFF
@@ -314,6 +317,63 @@
return ret;
}
+static void afe_send_cal_block(int32_t path, u16 port_id)
+{
+ int result = 0;
+ struct acdb_cal_block cal_block;
+ struct afe_port_cmd_set_param_no_payload afe_cal;
+ pr_debug("%s: path %d\n", __func__, path);
+
+ get_afe_cal(path, &cal_block);
+ if (cal_block.cal_size <= 0) {
+ pr_debug("%s: No AFE cal to send!\n", __func__);
+ goto done;
+ }
+
+ if (afe_cal_addr[path] != cal_block.cal_paddr) {
+ if (afe_cal_addr[path] != 0)
+ afe_cmd_memory_unmap_nowait(afe_cal_addr[path]);
+ afe_cmd_memory_map_nowait(cal_block.cal_paddr,
+ cal_block.cal_size);
+ afe_cal_addr[path] = cal_block.cal_paddr;
+ }
+
+ afe_cal.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ afe_cal.hdr.pkt_size = sizeof(afe_cal);
+ afe_cal.hdr.src_port = 0;
+ afe_cal.hdr.dest_port = 0;
+ afe_cal.hdr.token = 0;
+ afe_cal.hdr.opcode = AFE_PORT_CMD_SET_PARAM;
+ afe_cal.port_id = port_id;
+ afe_cal.payload_size = cal_block.cal_size;
+ afe_cal.payload_address = cal_block.cal_paddr;
+
+ pr_debug("%s: AFE cal sent for device port = %d, path = %d, "
+ "cal size = %d, cal addr = 0x%x\n", __func__,
+ port_id, path, cal_block.cal_size, cal_block.cal_paddr);
+
+ result = apr_send_pkt(this_afe.apr, (uint32_t *) &afe_cal);
+ if (result < 0) {
+ pr_err("%s: AFE cal for port %d failed\n",
+ __func__, port_id);
+ }
+
+ pr_debug("%s: AFE cal sent for path %d device!\n", __func__, path);
+done:
+ return;
+}
+
+void afe_send_cal(u16 port_id)
+{
+ pr_debug("%s\n", __func__);
+
+ if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_TX)
+ afe_send_cal_block(TX_CAL, port_id);
+ else if (afe_get_port_type(port_id) == MSM_AFE_PORT_TYPE_RX)
+ afe_send_cal_block(RX_CAL, port_id);
+}
+
int afe_port_start_nowait(u16 port_id, union afe_port_config *afe_config,
u32 rate) /* This function is no blocking */
{
@@ -365,6 +425,10 @@
ret = -EINVAL;
goto fail_cmd;
}
+
+ /* send AFE cal */
+ afe_send_cal(port_id);
+
start.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
start.hdr.pkt_size = sizeof(start);
@@ -875,6 +939,45 @@
return 0;
}
+int afe_cmd_memory_map_nowait(u32 dma_addr_p, u32 dma_buf_sz)
+{
+ int ret = 0;
+ struct afe_cmd_memory_map mregion;
+
+ pr_debug("%s:\n", __func__);
+
+ if (this_afe.apr == NULL) {
+ this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
+ 0xFFFFFFFF, &this_afe);
+ pr_debug("%s: Register AFE\n", __func__);
+ if (this_afe.apr == NULL) {
+ pr_err("%s: Unable to register AFE\n", __func__);
+ ret = -ENODEV;
+ return ret;
+ }
+ }
+
+ mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ mregion.hdr.pkt_size = sizeof(mregion);
+ mregion.hdr.src_port = 0;
+ mregion.hdr.dest_port = 0;
+ mregion.hdr.token = 0;
+ mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_MAP;
+ mregion.phy_addr = dma_addr_p;
+ mregion.mem_sz = dma_buf_sz;
+ mregion.mem_id = 0;
+ mregion.rsvd = 0;
+
+ ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
+ if (ret < 0) {
+ pr_err("%s: AFE memory map cmd failed %d\n",
+ __func__, ret);
+ ret = -EINVAL;
+ }
+ return 0;
+}
+
int afe_cmd_memory_unmap(u32 dma_addr_p)
{
int ret = 0;
@@ -905,7 +1008,7 @@
atomic_set(&this_afe.state, 1);
ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
if (ret < 0) {
- pr_err("%s: AFE memory map cmd failed %d\n",
+ pr_err("%s: AFE memory unmap cmd failed %d\n",
__func__, ret);
ret = -EINVAL;
return ret;
@@ -919,7 +1022,42 @@
ret = -EINVAL;
return ret;
}
+ return 0;
+}
+int afe_cmd_memory_unmap_nowait(u32 dma_addr_p)
+{
+ int ret = 0;
+ struct afe_cmd_memory_unmap mregion;
+
+ pr_debug("%s:\n", __func__);
+
+ if (this_afe.apr == NULL) {
+ this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
+ 0xFFFFFFFF, &this_afe);
+ pr_debug("%s: Register AFE\n", __func__);
+ if (this_afe.apr == NULL) {
+ pr_err("%s: Unable to register AFE\n", __func__);
+ ret = -ENODEV;
+ return ret;
+ }
+ }
+
+ mregion.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ mregion.hdr.pkt_size = sizeof(mregion);
+ mregion.hdr.src_port = 0;
+ mregion.hdr.dest_port = 0;
+ mregion.hdr.token = 0;
+ mregion.hdr.opcode = AFE_SERVICE_CMD_MEMORY_UNMAP;
+ mregion.phy_addr = dma_addr_p;
+
+ ret = apr_send_pkt(this_afe.apr, (uint32_t *) &mregion);
+ if (ret < 0) {
+ pr_err("%s: AFE memory unmap cmd failed %d\n",
+ __func__, ret);
+ ret = -EINVAL;
+ }
return 0;
}
@@ -1389,12 +1527,17 @@
static void __exit afe_exit(void)
{
+ int i;
#ifdef CONFIG_DEBUG_FS
if (debugfs_afelb)
debugfs_remove(debugfs_afelb);
if (debugfs_afelb_gain)
debugfs_remove(debugfs_afelb_gain);
#endif
+ for (i = 0; i < MAX_AUDPROC_TYPES; i++) {
+ if (afe_cal_addr[i] != 0)
+ afe_cmd_memory_unmap_nowait(afe_cal_addr[i]);
+ }
}
device_initcall(afe_init);
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index ab7f9f7..62168d2 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -515,6 +515,7 @@
pr_err("%s:map_buffer failed,"
"error = %ld\n",
__func__, PTR_ERR((void *)buf[cnt].mem_buffer));
+ mutex_unlock(&ac->cmd_lock);
goto fail;
}
buf[cnt].data =
@@ -522,6 +523,7 @@
if (!buf[cnt].data) {
pr_err("%s:invalid vaddr,"
" iomap failed\n", __func__);
+ mutex_unlock(&ac->cmd_lock);
goto fail;
}
buf[cnt].used = 1;
@@ -944,6 +946,7 @@
idx = port->cpu_buf;
if (port->buf == NULL) {
pr_debug("%s:Buffer pointer null\n", __func__);
+ mutex_unlock(&port->lock);
return NULL;
}
/* dir 0: used = 0 means buf in use