Merge "power: pm8921-charger: add dc_unplug_check option" into msm-3.4
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index 6737e89..51ec10c 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -332,6 +332,25 @@
interrupts = <0x0 0x61 0x1>;
};
};
+
+ vadc@3100 {
+ compatible = "qcom,qpnp-vadc";
+ reg = <0x3100 0x100>;
+ interrupts = <0x0 0x31 0x0>;
+ qcom,adc-bit-resolution = <15>;
+ qcom,adc-vdd-reference = <1800>;
+
+ chan@0 {
+ label = "usb_in";
+ qcom,channel-num = <0>;
+ qcom,decimation = <0>;
+ qcom,pre-div-channel-scaling = <20>;
+ qcom,calibration-type = "absolute";
+ qcom,scale-function = <0>;
+ qcom,hw-settle-time = <0>;
+ qcom,fast-avg-setup = <0>;
+ };
+ };
};
qcom,pm8941@1 {
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index 91894de..b376544 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -218,9 +218,9 @@
status = "okay";
pm8941_l3: regulator-l3 {
parent-supply = <&pm8941_s1>;
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- qcom,init-voltage = <1200000>;
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,init-voltage = <1225000>;
status = "okay";
};
};
@@ -229,9 +229,9 @@
status = "okay";
pm8941_l4: regulator-l4 {
parent-supply = <&pm8941_s1>;
- regulator-min-microvolt = <1150000>;
- regulator-max-microvolt = <1150000>;
- qcom,init-voltage = <1150000>;
+ regulator-min-microvolt = <12250000>;
+ regulator-max-microvolt = <12250000>;
+ qcom,init-voltage = <12250000>;
status = "okay";
};
};
@@ -303,9 +303,9 @@
status = "okay";
pm8941_l11: regulator-l11 {
parent-supply = <&pm8941_s1>;
- regulator-min-microvolt = <1250000>;
- regulator-max-microvolt = <1250000>;
- qcom,init-voltage = <1250000>;
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,init-voltage = <1300000>;
status = "okay";
};
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index edb57dd..d34849c 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -85,7 +85,9 @@
cell-index = <1>; /* SDC1 eMMC slot */
compatible = "qcom,msm-sdcc";
reg = <0xf9824000 0x1000>;
+ reg-names = "core_mem";
interrupts = <0 123 0>;
+ interrupt-names = "core_irq";
vdd-supply = <&pm8941_l20>;
vdd-io-supply = <&pm8941_s3>;
@@ -112,7 +114,9 @@
cell-index = <2>; /* SDC2 SD card slot */
compatible = "qcom,msm-sdcc";
reg = <0xf98a4000 0x1000>;
+ reg-names = "core_mem";
interrupts = <0 125 0>;
+ interrupt-names = "core_irq";
vdd-supply = <&pm8941_l21>;
vdd-io-supply = <&pm8941_l13>;
@@ -141,7 +145,9 @@
cell-index = <3>; /* SDC3 SDIO slot */
compatible = "qcom,msm-sdcc";
reg = <0xf9864000 0x1000>;
+ reg-names = "core_mem";
interrupts = <0 127 0>;
+ interrupt-names = "core_irq";
gpios = <&msmgpio 40 0>, /* CLK */
<&msmgpio 39 0>, /* CMD */
@@ -162,7 +168,9 @@
cell-index = <4>; /* SDC4 SDIO slot */
compatible = "qcom,msm-sdcc";
reg = <0xf98e4000 0x1000>;
+ reg-names = "core_mem";
interrupts = <0 129 0>;
+ interrupt-names = "core_irq";
gpios = <&msmgpio 93 0>, /* CLK */
<&msmgpio 91 0>, /* CMD */
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 66e71fc..795a5a7 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -285,6 +285,8 @@
CONFIG_INPUT_MISC=y
CONFIG_INPUT_PMIC8XXX_PWRKEY=y
CONFIG_INPUT_UINPUT=y
+CONFIG_STM_LIS3DH=y
+CONFIG_INPUT_MPU3050=y
# CONFIG_LEGACY_PTYS is not set
CONFIG_N_SMUX=y
CONFIG_N_SMUX_LOOPBACK=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 3731845..4674584 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -289,6 +289,8 @@
CONFIG_INPUT_MISC=y
CONFIG_INPUT_PMIC8XXX_PWRKEY=y
CONFIG_INPUT_UINPUT=y
+CONFIG_STM_LIS3DH=y
+CONFIG_INPUT_MPU3050=y
# CONFIG_LEGACY_PTYS is not set
CONFIG_N_SMUX=y
CONFIG_N_SMUX_LOOPBACK=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index b9f26d9..00b4164 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -51,6 +51,7 @@
CONFIG_MSM_TZ_LOG=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
CONFIG_MSM_OCMEM=y
+CONFIG_MSM_MEMORY_DUMP=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_SMP=y
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index d65ebe1..b939dc2 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -544,40 +544,6 @@
msm_8974_stub_regulator_devices_len);
}
-static struct clk_lookup msm_clocks_dummy[] = {
- CLK_DUMMY("xo", XO_CLK, NULL, OFF),
- CLK_DUMMY("xo", XO_CLK, "pil_pronto", OFF),
- CLK_DUMMY("core_clk", BLSP2_UART_CLK, "msm_serial_hsl.0", OFF),
- CLK_DUMMY("iface_clk", BLSP2_UART_CLK, "msm_serial_hsl.0", OFF),
- CLK_DUMMY("core_clk", SDC1_CLK, NULL, OFF),
- CLK_DUMMY("iface_clk", SDC1_P_CLK, NULL, OFF),
- CLK_DUMMY("core_clk", SDC3_CLK, NULL, OFF),
- CLK_DUMMY("iface_clk", SDC3_P_CLK, NULL, OFF),
- CLK_DUMMY("phy_clk", NULL, "msm_otg", OFF),
- CLK_DUMMY("core_clk", NULL, "msm_otg", OFF),
- CLK_DUMMY("iface_clk", NULL, "msm_otg", OFF),
- CLK_DUMMY("xo", NULL, "msm_otg", OFF),
- CLK_DUMMY("dfab_clk", DFAB_CLK, NULL, 0),
- CLK_DUMMY("dma_bam_pclk", DMA_BAM_P_CLK, NULL, 0),
- CLK_DUMMY("mem_clk", NULL, NULL, 0),
- CLK_DUMMY("core_clk", SPI_CLK, "spi_qsd.1", OFF),
- CLK_DUMMY("iface_clk", SPI_P_CLK, "spi_qsd.1", OFF),
- CLK_DUMMY("core_clk", NULL, "f9966000.i2c", 0),
- CLK_DUMMY("iface_clk", NULL, "f9966000.i2c", 0),
- CLK_DUMMY("core_clk", NULL, "fe12f000.slim", OFF),
- CLK_DUMMY("core_clk", "mdp.0", NULL, 0),
- CLK_DUMMY("core_clk_src", "mdp.0", NULL, 0),
- CLK_DUMMY("lut_clk", "mdp.0", NULL, 0),
- CLK_DUMMY("vsync_clk", "mdp.0", NULL, 0),
- CLK_DUMMY("iface_clk", "mdp.0", NULL, 0),
- CLK_DUMMY("bus_clk", "mdp.0", NULL, 0),
-};
-
-struct clock_init_data msm_dummy_clock_init_data __initdata = {
- .table = msm_clocks_dummy,
- .size = ARRAY_SIZE(msm_clocks_dummy),
-};
-
/*
* Used to satisfy dependencies for devices that need to be
* run early or in a particular order. Most likely your device doesn't fall
@@ -594,7 +560,7 @@
msm_spm_device_init();
regulator_stub_init();
if (machine_is_msm8974_rumi())
- msm_clock_init(&msm_dummy_clock_init_data);
+ msm_clock_init(&msm8974_rumi_clock_init_data);
else
msm_clock_init(&msm8974_clock_init_data);
msm8974_init_buses();
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 82b7fd6..8076571 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -21,6 +21,7 @@
#include <mach/clk.h>
#include <mach/rpm-regulator-smd.h>
+#include <mach/socinfo.h>
#include "clock-local2.h"
#include "clock-pll.h"
@@ -1270,6 +1271,12 @@
F_END
};
+static struct clk_freq_tbl ftbl_gcc_sdcc_apps_rumi_clk[] = {
+ F( 400000, cxo, 12, 1, 4),
+ F( 19200000, cxo, 1, 0, 0),
+ F_END
+};
+
static struct rcg_clk sdcc1_apps_clk_src = {
.cmd_rcgr_reg = SDCC1_APPS_CMD_RCGR,
.set_rate = set_rate_mnd,
@@ -2274,7 +2281,7 @@
F_MM( 19200000, cxo, 1, 0, 0),
F_MM(150000000, gpll0, 4, 0, 0),
F_MM(282000000, mmpll1, 3, 0, 0),
- F_MM(320000000, mmpll1, 2.5, 0, 0),
+ F_MM(320000000, mmpll0, 2.5, 0, 0),
F_MM(400000000, mmpll0, 2, 0, 0),
F_END
};
@@ -4681,6 +4688,48 @@
.multiplier = 1,
};
+
+static struct clk_lookup msm_clocks_8974_rumi[] = {
+ CLK_LOOKUP("iface_clk", gcc_sdcc1_ahb_clk.c, "msm_sdcc.1"),
+ CLK_LOOKUP("core_clk", gcc_sdcc1_apps_clk.c, "msm_sdcc.1"),
+ CLK_LOOKUP("bus_clk", pnoc_sdcc1_clk.c, "msm_sdcc.1"),
+ CLK_LOOKUP("iface_clk", gcc_sdcc2_ahb_clk.c, "msm_sdcc.2"),
+ CLK_LOOKUP("core_clk", gcc_sdcc2_apps_clk.c, "msm_sdcc.2"),
+ CLK_LOOKUP("bus_clk", pnoc_sdcc2_clk.c, "msm_sdcc.2"),
+ CLK_LOOKUP("iface_clk", gcc_sdcc3_ahb_clk.c, "msm_sdcc.3"),
+ CLK_LOOKUP("core_clk", gcc_sdcc3_apps_clk.c, "msm_sdcc.3"),
+ CLK_LOOKUP("bus_clk", pnoc_sdcc3_clk.c, "msm_sdcc.3"),
+ CLK_LOOKUP("iface_clk", gcc_sdcc4_ahb_clk.c, "msm_sdcc.4"),
+ CLK_LOOKUP("core_clk", gcc_sdcc4_apps_clk.c, "msm_sdcc.4"),
+ CLK_LOOKUP("bus_clk", pnoc_sdcc4_clk.c, "msm_sdcc.4"),
+ CLK_DUMMY("xo", XO_CLK, NULL, OFF),
+ CLK_DUMMY("xo", XO_CLK, "pil_pronto", OFF),
+ CLK_DUMMY("core_clk", BLSP2_UART_CLK, "msm_serial_hsl.0", OFF),
+ CLK_DUMMY("iface_clk", BLSP2_UART_CLK, "msm_serial_hsl.0", OFF),
+ CLK_DUMMY("core_clk", SDC1_CLK, NULL, OFF),
+ CLK_DUMMY("iface_clk", SDC1_P_CLK, NULL, OFF),
+ CLK_DUMMY("core_clk", SDC3_CLK, NULL, OFF),
+ CLK_DUMMY("iface_clk", SDC3_P_CLK, NULL, OFF),
+ CLK_DUMMY("phy_clk", NULL, "msm_otg", OFF),
+ CLK_DUMMY("core_clk", NULL, "msm_otg", OFF),
+ CLK_DUMMY("iface_clk", NULL, "msm_otg", OFF),
+ CLK_DUMMY("xo", NULL, "msm_otg", OFF),
+ CLK_DUMMY("dfab_clk", DFAB_CLK, NULL, 0),
+ CLK_DUMMY("dma_bam_pclk", DMA_BAM_P_CLK, NULL, 0),
+ CLK_DUMMY("mem_clk", NULL, NULL, 0),
+ CLK_DUMMY("core_clk", SPI_CLK, "spi_qsd.1", OFF),
+ CLK_DUMMY("iface_clk", SPI_P_CLK, "spi_qsd.1", OFF),
+ CLK_DUMMY("core_clk", NULL, "f9966000.i2c", 0),
+ CLK_DUMMY("iface_clk", NULL, "f9966000.i2c", 0),
+ CLK_DUMMY("core_clk", NULL, "fe12f000.slim", OFF),
+ CLK_DUMMY("core_clk", "mdp.0", NULL, 0),
+ CLK_DUMMY("core_clk_src", "mdp.0", NULL, 0),
+ CLK_DUMMY("lut_clk", "mdp.0", NULL, 0),
+ CLK_DUMMY("vsync_clk", "mdp.0", NULL, 0),
+ CLK_DUMMY("iface_clk", "mdp.0", NULL, 0),
+ CLK_DUMMY("bus_clk", "mdp.0", NULL, 0),
+};
+
static struct clk_lookup msm_clocks_8974[] = {
CLK_LOOKUP("xo", cxo_clk_src.c, "msm_otg"),
CLK_LOOKUP("xo", cxo_clk_src.c, "pil-q6v5-lpass"),
@@ -5265,7 +5314,7 @@
vdd_dig_reg = rpm_regulator_get(NULL, "vdd_dig");
if (IS_ERR(vdd_dig_reg))
- panic("clock-copper: Unable to get the vdd_dig regulator!");
+ panic("clock-8974: Unable to get the vdd_dig regulator!");
/*
* TODO: Set a voltage and enable vdd_dig, leaving the voltage high
@@ -5284,6 +5333,32 @@
return unvote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
}
+static void __init msm8974_rumi_clock_pre_init(void)
+{
+ virt_bases[GCC_BASE] = ioremap(GCC_CC_PHYS, GCC_CC_SIZE);
+ if (!virt_bases[GCC_BASE])
+ panic("clock-8974: Unable to ioremap GCC memory!");
+
+ /* SDCC clocks are partially emulated in the RUMI */
+ sdcc1_apps_clk_src.freq_tbl = ftbl_gcc_sdcc_apps_rumi_clk;
+ sdcc2_apps_clk_src.freq_tbl = ftbl_gcc_sdcc_apps_rumi_clk;
+ sdcc3_apps_clk_src.freq_tbl = ftbl_gcc_sdcc_apps_rumi_clk;
+ sdcc4_apps_clk_src.freq_tbl = ftbl_gcc_sdcc_apps_rumi_clk;
+
+ vdd_dig_reg = rpm_regulator_get(NULL, "vdd_dig");
+ if (IS_ERR(vdd_dig_reg))
+ panic("clock-8974: Unable to get the vdd_dig regulator!");
+
+ /*
+ * TODO: Set a voltage and enable vdd_dig, leaving the voltage high
+ * until late_init. This may not be necessary with clock handoff;
+ * Investigate this code on a real non-simulator target to determine
+ * its necessity.
+ */
+ vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+ rpm_regulator_enable(vdd_dig_reg);
+}
+
struct clock_init_data msm8974_clock_init_data __initdata = {
.table = msm_clocks_8974,
.size = ARRAY_SIZE(msm_clocks_8974),
@@ -5291,3 +5366,9 @@
.post_init = msm8974_clock_post_init,
.late_init = msm8974_clock_late_init,
};
+
+struct clock_init_data msm8974_rumi_clock_init_data __initdata = {
+ .table = msm_clocks_8974_rumi,
+ .size = ARRAY_SIZE(msm_clocks_8974_rumi),
+ .pre_init = msm8974_rumi_clock_pre_init,
+};
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index df2aa4e..d236e13 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -171,6 +171,7 @@
extern struct clock_init_data msm8625_dummy_clock_init_data;
extern struct clock_init_data msm8930_clock_init_data;
extern struct clock_init_data msm8974_clock_init_data;
+extern struct clock_init_data msm8974_rumi_clock_init_data;
void msm_clock_init(struct clock_init_data *data);
int vote_vdd_level(struct clk_vdd_class *vdd_class, int level);
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index a6f18ba..ac26acf 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -1337,19 +1337,19 @@
},
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
{
- .name = "sdcc_dml_addr",
+ .name = "dml_mem",
.start = MSM_SDC1_DML_BASE,
.end = MSM_SDC1_BAM_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_addr",
+ .name = "bam_mem",
.start = MSM_SDC1_BAM_BASE,
.end = MSM_SDC1_BAM_BASE + (2 * SZ_4K) - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_irq",
+ .name = "bam_irq",
.start = SDC1_BAM_IRQ,
.end = SDC1_BAM_IRQ,
.flags = IORESOURCE_IRQ,
@@ -1372,19 +1372,19 @@
},
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
{
- .name = "sdcc_dml_addr",
+ .name = "dml_mem",
.start = MSM_SDC2_DML_BASE,
.end = MSM_SDC2_BAM_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_addr",
+ .name = "bam_mem",
.start = MSM_SDC2_BAM_BASE,
.end = MSM_SDC2_BAM_BASE + (2 * SZ_4K) - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_irq",
+ .name = "bam_irq",
.start = SDC2_BAM_IRQ,
.end = SDC2_BAM_IRQ,
.flags = IORESOURCE_IRQ,
@@ -1407,19 +1407,19 @@
},
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
{
- .name = "sdcc_dml_addr",
+ .name = "dml_mem",
.start = MSM_SDC3_DML_BASE,
.end = MSM_SDC3_BAM_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_addr",
+ .name = "bam_mem",
.start = MSM_SDC3_BAM_BASE,
.end = MSM_SDC3_BAM_BASE + (2 * SZ_4K) - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_irq",
+ .name = "bam_irq",
.start = SDC3_BAM_IRQ,
.end = SDC3_BAM_IRQ,
.flags = IORESOURCE_IRQ,
@@ -1442,19 +1442,19 @@
},
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
{
- .name = "sdcc_dml_addr",
+ .name = "dml_mem",
.start = MSM_SDC4_DML_BASE,
.end = MSM_SDC4_BAM_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_addr",
+ .name = "bam_mem",
.start = MSM_SDC4_BAM_BASE,
.end = MSM_SDC4_BAM_BASE + (2 * SZ_4K) - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_irq",
+ .name = "bam_irq",
.start = SDC4_BAM_IRQ,
.end = SDC4_BAM_IRQ,
.flags = IORESOURCE_IRQ,
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index b1ebe33..3d1926c 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -819,19 +819,19 @@
},
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
{
- .name = "sdcc_dml_addr",
+ .name = "dml_mem",
.start = MSM_SDC1_DML_BASE,
.end = MSM_SDC1_BAM_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_addr",
+ .name = "bam_mem",
.start = MSM_SDC1_BAM_BASE,
.end = MSM_SDC1_BAM_BASE + (2 * SZ_4K) - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_irq",
+ .name = "bam_irq",
.start = SDC1_BAM_IRQ,
.end = SDC1_BAM_IRQ,
.flags = IORESOURCE_IRQ,
@@ -854,19 +854,19 @@
},
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
{
- .name = "sdcc_dml_addr",
+ .name = "dml_mem",
.start = MSM_SDC2_DML_BASE,
.end = MSM_SDC2_BAM_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_addr",
+ .name = "bam_mem",
.start = MSM_SDC2_BAM_BASE,
.end = MSM_SDC2_BAM_BASE + (2 * SZ_4K) - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_irq",
+ .name = "bam_irq",
.start = SDC2_BAM_IRQ,
.end = SDC2_BAM_IRQ,
.flags = IORESOURCE_IRQ,
@@ -889,19 +889,19 @@
},
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
{
- .name = "sdcc_dml_addr",
+ .name = "dml_mem",
.start = MSM_SDC3_DML_BASE,
.end = MSM_SDC3_BAM_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_addr",
+ .name = "bam_mem",
.start = MSM_SDC3_BAM_BASE,
.end = MSM_SDC3_BAM_BASE + (2 * SZ_4K) - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_irq",
+ .name = "bam_irq",
.start = SDC3_BAM_IRQ,
.end = SDC3_BAM_IRQ,
.flags = IORESOURCE_IRQ,
@@ -924,19 +924,19 @@
},
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
{
- .name = "sdcc_dml_addr",
+ .name = "dml_mem",
.start = MSM_SDC4_DML_BASE,
.end = MSM_SDC4_BAM_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_addr",
+ .name = "bam_mem",
.start = MSM_SDC4_BAM_BASE,
.end = MSM_SDC4_BAM_BASE + (2 * SZ_4K) - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_irq",
+ .name = "bam_irq",
.start = SDC4_BAM_IRQ,
.end = SDC4_BAM_IRQ,
.flags = IORESOURCE_IRQ,
@@ -959,19 +959,19 @@
},
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
{
- .name = "sdcc_dml_addr",
+ .name = "dml_mem",
.start = MSM_SDC5_DML_BASE,
.end = MSM_SDC5_BAM_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_addr",
+ .name = "bam_mem",
.start = MSM_SDC5_BAM_BASE,
.end = MSM_SDC5_BAM_BASE + (2 * SZ_4K) - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_irq",
+ .name = "bam_irq",
.start = SDC5_BAM_IRQ,
.end = SDC5_BAM_IRQ,
.flags = IORESOURCE_IRQ,
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 9c2b26a..9f03878 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -845,19 +845,19 @@
},
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
{
- .name = "sdcc_dml_addr",
+ .name = "dml_mem",
.start = MSM_SDC1_DML_BASE,
.end = MSM_SDC1_BAM_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_addr",
+ .name = "bam_mem",
.start = MSM_SDC1_BAM_BASE,
.end = MSM_SDC1_BAM_BASE + (2 * SZ_4K) - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_irq",
+ .name = "bam_irq",
.start = SDC1_BAM_IRQ,
.end = SDC1_BAM_IRQ,
.flags = IORESOURCE_IRQ,
@@ -880,19 +880,19 @@
},
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
{
- .name = "sdcc_dml_addr",
+ .name = "dml_mem",
.start = MSM_SDC2_DML_BASE,
.end = MSM_SDC2_BAM_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_addr",
+ .name = "bam_mem",
.start = MSM_SDC2_BAM_BASE,
.end = MSM_SDC2_BAM_BASE + (2 * SZ_4K) - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_irq",
+ .name = "bam_irq",
.start = SDC2_BAM_IRQ,
.end = SDC2_BAM_IRQ,
.flags = IORESOURCE_IRQ,
diff --git a/arch/arm/mach-msm/devices-msm7x25.c b/arch/arm/mach-msm/devices-msm7x25.c
index 2be7d5e..99b2960 100644
--- a/arch/arm/mach-msm/devices-msm7x25.c
+++ b/arch/arm/mach-msm/devices-msm7x25.c
@@ -439,23 +439,25 @@
#define MSM_SDC4_BASE 0xA0700000
static struct resource resources_sdc1[] = {
{
+ .name = "core_mem",
.start = MSM_SDC1_BASE,
.end = MSM_SDC1_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC1_0,
.end = INT_SDC1_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC1_CHAN,
.end = DMOV_SDC1_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC1_CRCI,
.end = DMOV_SDC1_CRCI,
.flags = IORESOURCE_DMA,
@@ -464,23 +466,25 @@
static struct resource resources_sdc2[] = {
{
+ .name = "core_mem",
.start = MSM_SDC2_BASE,
.end = MSM_SDC2_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC2_0,
.end = INT_SDC2_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC2_CHAN,
.end = DMOV_SDC2_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC2_CRCI,
.end = DMOV_SDC2_CRCI,
.flags = IORESOURCE_DMA,
@@ -489,23 +493,25 @@
static struct resource resources_sdc3[] = {
{
+ .name = "core_mem",
.start = MSM_SDC3_BASE,
.end = MSM_SDC3_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC3_0,
.end = INT_SDC3_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC3_CHAN,
.end = DMOV_SDC3_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC3_CRCI,
.end = DMOV_SDC3_CRCI,
.flags = IORESOURCE_DMA,
@@ -514,23 +520,25 @@
static struct resource resources_sdc4[] = {
{
+ .name = "core_mem",
.start = MSM_SDC4_BASE,
.end = MSM_SDC4_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC4_0,
.end = INT_SDC4_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC4_CHAN,
.end = DMOV_SDC4_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC4_CRCI,
.end = DMOV_SDC4_CRCI,
.flags = IORESOURCE_DMA,
diff --git a/arch/arm/mach-msm/devices-msm7x27.c b/arch/arm/mach-msm/devices-msm7x27.c
index 69d7430..82c5eed 100644
--- a/arch/arm/mach-msm/devices-msm7x27.c
+++ b/arch/arm/mach-msm/devices-msm7x27.c
@@ -448,23 +448,25 @@
#define MSM_SDC4_BASE 0xA0700000
static struct resource resources_sdc1[] = {
{
+ .name = "core_mem",
.start = MSM_SDC1_BASE,
.end = MSM_SDC1_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC1_0,
.end = INT_SDC1_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC1_CHAN,
.end = DMOV_SDC1_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC1_CRCI,
.end = DMOV_SDC1_CRCI,
.flags = IORESOURCE_DMA,
@@ -473,23 +475,25 @@
static struct resource resources_sdc2[] = {
{
+ .name = "core_mem",
.start = MSM_SDC2_BASE,
.end = MSM_SDC2_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC2_0,
.end = INT_SDC2_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC2_CHAN,
.end = DMOV_SDC2_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC2_CRCI,
.end = DMOV_SDC2_CRCI,
.flags = IORESOURCE_DMA,
@@ -498,23 +502,25 @@
static struct resource resources_sdc3[] = {
{
+ .name = "core_mem",
.start = MSM_SDC3_BASE,
.end = MSM_SDC3_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC3_0,
.end = INT_SDC3_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC3_CHAN,
.end = DMOV_SDC3_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC3_CRCI,
.end = DMOV_SDC3_CRCI,
.flags = IORESOURCE_DMA,
@@ -523,23 +529,25 @@
static struct resource resources_sdc4[] = {
{
+ .name = "core_mem",
.start = MSM_SDC4_BASE,
.end = MSM_SDC4_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC4_0,
.end = INT_SDC4_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC4_CHAN,
.end = DMOV_SDC4_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC4_CRCI,
.end = DMOV_SDC4_CRCI,
.flags = IORESOURCE_DMA,
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 96984fb..8fef953 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -507,23 +507,25 @@
#define MSM_SDC4_BASE 0xA0700000
static struct resource resources_sdc1[] = {
{
+ .name = "core_mem",
.start = MSM_SDC1_BASE,
.end = MSM_SDC1_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC1_0,
.end = INT_SDC1_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC1_CHAN,
.end = DMOV_SDC1_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC1_CRCI,
.end = DMOV_SDC1_CRCI,
.flags = IORESOURCE_DMA,
@@ -532,23 +534,25 @@
static struct resource resources_sdc2[] = {
{
+ .name = "core_mem",
.start = MSM_SDC2_BASE,
.end = MSM_SDC2_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC2_0,
.end = INT_SDC2_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC2_CHAN,
.end = DMOV_SDC2_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC2_CRCI,
.end = DMOV_SDC2_CRCI,
.flags = IORESOURCE_DMA,
@@ -557,23 +561,25 @@
static struct resource resources_sdc3[] = {
{
+ .name = "core_mem",
.start = MSM_SDC3_BASE,
.end = MSM_SDC3_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC3_0,
.end = INT_SDC3_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_NAND_CHAN,
.end = DMOV_NAND_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC3_CRCI,
.end = DMOV_SDC3_CRCI,
.flags = IORESOURCE_DMA,
@@ -582,23 +588,25 @@
static struct resource resources_sdc4[] = {
{
+ .name = "core_mem",
.start = MSM_SDC4_BASE,
.end = MSM_SDC4_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC4_0,
.end = INT_SDC4_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC4_CHAN,
.end = DMOV_SDC4_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC4_CRCI,
.end = DMOV_SDC4_CRCI,
.flags = IORESOURCE_DMA,
@@ -1175,23 +1183,25 @@
static struct resource msm8625_resources_sdc1[] = {
{
+ .name = "core_mem",
.start = MSM_SDC1_BASE,
.end = MSM_SDC1_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = MSM8625_INT_SDC1_0,
.end = MSM8625_INT_SDC1_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC1_CHAN,
.end = DMOV_SDC1_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC1_CRCI,
.end = DMOV_SDC1_CRCI,
.flags = IORESOURCE_DMA,
@@ -1200,23 +1210,25 @@
static struct resource msm8625_resources_sdc2[] = {
{
+ .name = "core_mem",
.start = MSM_SDC2_BASE,
.end = MSM_SDC2_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = MSM8625_INT_SDC2_0,
.end = MSM8625_INT_SDC2_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC2_CHAN,
.end = DMOV_SDC2_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC2_CRCI,
.end = DMOV_SDC2_CRCI,
.flags = IORESOURCE_DMA,
@@ -1225,23 +1237,25 @@
static struct resource msm8625_resources_sdc3[] = {
{
+ .name = "core_mem",
.start = MSM_SDC3_BASE,
.end = MSM_SDC3_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = MSM8625_INT_SDC3_0,
.end = MSM8625_INT_SDC3_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC3_CHAN,
.end = DMOV_SDC3_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC3_CRCI,
.end = DMOV_SDC3_CRCI,
.flags = IORESOURCE_DMA,
@@ -1250,23 +1264,25 @@
static struct resource msm8625_resources_sdc4[] = {
{
+ .name = "core_mem",
.start = MSM_SDC4_BASE,
.end = MSM_SDC4_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = MSM8625_INT_SDC4_0,
.end = MSM8625_INT_SDC4_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC4_CHAN,
.end = DMOV_SDC4_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC4_CRCI,
.end = DMOV_SDC4_CRCI,
.flags = IORESOURCE_DMA,
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index f04ef9d..8a5d0e8 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -784,23 +784,25 @@
#define MSM_SDC4_BASE 0xA3100000
static struct resource resources_sdc1[] = {
{
+ .name = "core_mem",
.start = MSM_SDC1_BASE,
.end = MSM_SDC1_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC1_0,
.end = INT_SDC1_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC1_CHAN,
.end = DMOV_SDC1_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC1_CRCI,
.end = DMOV_SDC1_CRCI,
.flags = IORESOURCE_DMA,
@@ -809,23 +811,25 @@
static struct resource resources_sdc2[] = {
{
+ .name = "core_mem",
.start = MSM_SDC2_BASE,
.end = MSM_SDC2_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC2_0,
.end = INT_SDC2_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_NAND_CHAN,
.end = DMOV_NAND_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC2_CRCI,
.end = DMOV_SDC2_CRCI,
.flags = IORESOURCE_DMA,
@@ -834,23 +838,25 @@
static struct resource resources_sdc3[] = {
{
+ .name = "core_mem",
.start = MSM_SDC3_BASE,
.end = MSM_SDC3_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC3_0,
.end = INT_SDC3_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC3_CHAN,
.end = DMOV_SDC3_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC3_CRCI,
.end = DMOV_SDC3_CRCI,
.flags = IORESOURCE_DMA,
@@ -859,23 +865,25 @@
static struct resource resources_sdc4[] = {
{
+ .name = "core_mem",
.start = MSM_SDC4_BASE,
.end = MSM_SDC4_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC4_0,
.end = INT_SDC4_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC4_CHAN,
.end = DMOV_SDC4_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC4_CRCI,
.end = DMOV_SDC4_CRCI,
.flags = IORESOURCE_DMA,
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 3920abe..9ea817f 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -1091,43 +1091,45 @@
static struct resource resources_sdc1[] = {
{
+ .name = "core_mem",
.start = MSM_SDC1_BASE,
.end = MSM_SDC1_DML_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = SDC1_IRQ_0,
.end = SDC1_IRQ_0,
.flags = IORESOURCE_IRQ,
},
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
{
- .name = "sdcc_dml_addr",
+ .name = "dml_mem",
.start = MSM_SDC1_DML_BASE,
.end = MSM_SDC1_BAM_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_addr",
+ .name = "bam_mem",
.start = MSM_SDC1_BAM_BASE,
.end = MSM_SDC1_BAM_BASE + (2 * SZ_4K) - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_irq",
+ .name = "bam_irq",
.start = SDC1_BAM_IRQ,
.end = SDC1_BAM_IRQ,
.flags = IORESOURCE_IRQ,
},
#else
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC1_CHAN,
.end = DMOV_SDC1_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC1_CRCI,
.end = DMOV_SDC1_CRCI,
.flags = IORESOURCE_DMA,
@@ -1137,43 +1139,45 @@
static struct resource resources_sdc2[] = {
{
+ .name = "core_mem",
.start = MSM_SDC2_BASE,
.end = MSM_SDC2_DML_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = SDC2_IRQ_0,
.end = SDC2_IRQ_0,
.flags = IORESOURCE_IRQ,
},
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
{
- .name = "sdcc_dml_addr",
+ .name = "dml_mem",
.start = MSM_SDC2_DML_BASE,
.end = MSM_SDC2_BAM_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_addr",
+ .name = "bam_mem",
.start = MSM_SDC2_BAM_BASE,
.end = MSM_SDC2_BAM_BASE + (2 * SZ_4K) - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_irq",
+ .name = "bam_irq",
.start = SDC2_BAM_IRQ,
.end = SDC2_BAM_IRQ,
.flags = IORESOURCE_IRQ,
},
#else
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC2_CHAN,
.end = DMOV_SDC2_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC2_CRCI,
.end = DMOV_SDC2_CRCI,
.flags = IORESOURCE_DMA,
@@ -1183,43 +1187,45 @@
static struct resource resources_sdc3[] = {
{
+ .name = "core_mem",
.start = MSM_SDC3_BASE,
.end = MSM_SDC3_DML_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = SDC3_IRQ_0,
.end = SDC3_IRQ_0,
.flags = IORESOURCE_IRQ,
},
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
{
- .name = "sdcc_dml_addr",
+ .name = "dml_mem",
.start = MSM_SDC3_DML_BASE,
.end = MSM_SDC3_BAM_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_addr",
+ .name = "bam_mem",
.start = MSM_SDC3_BAM_BASE,
.end = MSM_SDC3_BAM_BASE + (2 * SZ_4K) - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_irq",
+ .name = "bam_irq",
.start = SDC3_BAM_IRQ,
.end = SDC3_BAM_IRQ,
.flags = IORESOURCE_IRQ,
},
#else
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC3_CHAN,
.end = DMOV_SDC3_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC3_CRCI,
.end = DMOV_SDC3_CRCI,
.flags = IORESOURCE_DMA,
@@ -1229,43 +1235,45 @@
static struct resource resources_sdc4[] = {
{
+ .name = "core_mem",
.start = MSM_SDC4_BASE,
.end = MSM_SDC4_DML_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = SDC4_IRQ_0,
.end = SDC4_IRQ_0,
.flags = IORESOURCE_IRQ,
},
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
{
- .name = "sdcc_dml_addr",
+ .name = "dml_mem",
.start = MSM_SDC4_DML_BASE,
.end = MSM_SDC4_BAM_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_addr",
+ .name = "bam_mem",
.start = MSM_SDC4_BAM_BASE,
.end = MSM_SDC4_BAM_BASE + (2 * SZ_4K) - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_irq",
+ .name = "bam_irq",
.start = SDC4_BAM_IRQ,
.end = SDC4_BAM_IRQ,
.flags = IORESOURCE_IRQ,
},
#else
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC4_CHAN,
.end = DMOV_SDC4_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC4_CRCI,
.end = DMOV_SDC4_CRCI,
.flags = IORESOURCE_DMA,
@@ -1275,43 +1283,45 @@
static struct resource resources_sdc5[] = {
{
+ .name = "core_mem",
.start = MSM_SDC5_BASE,
.end = MSM_SDC5_DML_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = SDC5_IRQ_0,
.end = SDC5_IRQ_0,
.flags = IORESOURCE_IRQ,
},
#ifdef CONFIG_MMC_MSM_SPS_SUPPORT
{
- .name = "sdcc_dml_addr",
+ .name = "dml_mem",
.start = MSM_SDC5_DML_BASE,
.end = MSM_SDC5_BAM_BASE - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_addr",
+ .name = "bam_mem",
.start = MSM_SDC5_BAM_BASE,
.end = MSM_SDC5_BAM_BASE + (2 * SZ_4K) - 1,
.flags = IORESOURCE_MEM,
},
{
- .name = "sdcc_bam_irq",
+ .name = "bam_irq",
.start = SDC5_BAM_IRQ,
.end = SDC5_BAM_IRQ,
.flags = IORESOURCE_IRQ,
},
#else
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC5_CHAN,
.end = DMOV_SDC5_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC5_CRCI,
.end = DMOV_SDC5_CRCI,
.flags = IORESOURCE_DMA,
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index ec4a14f..03ffa2f 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -490,23 +490,25 @@
#define MSM_SDC4_BASE 0xA0600000
static struct resource resources_sdc1[] = {
{
+ .name = "core_mem",
.start = MSM_SDC1_BASE,
.end = MSM_SDC1_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC1_0,
.end = INT_SDC1_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC1_CHAN,
.end = DMOV_SDC1_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC1_CRCI,
.end = DMOV_SDC1_CRCI,
.flags = IORESOURCE_DMA,
@@ -515,23 +517,25 @@
static struct resource resources_sdc2[] = {
{
+ .name = "core_mem",
.start = MSM_SDC2_BASE,
.end = MSM_SDC2_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC2_0,
.end = INT_SDC2_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC2_CHAN,
.end = DMOV_SDC2_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC2_CRCI,
.end = DMOV_SDC2_CRCI,
.flags = IORESOURCE_DMA,
@@ -540,23 +544,25 @@
static struct resource resources_sdc3[] = {
{
+ .name = "core_mem",
.start = MSM_SDC3_BASE,
.end = MSM_SDC3_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC3_0,
.end = INT_SDC3_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC3_CHAN,
.end = DMOV_SDC3_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC3_CRCI,
.end = DMOV_SDC3_CRCI,
.flags = IORESOURCE_DMA,
@@ -565,23 +571,25 @@
static struct resource resources_sdc4[] = {
{
+ .name = "core_mem",
.start = MSM_SDC4_BASE,
.end = MSM_SDC4_BASE + SZ_4K - 1,
.flags = IORESOURCE_MEM,
},
{
+ .name = "core_irq",
.start = INT_SDC4_0,
.end = INT_SDC4_1,
.flags = IORESOURCE_IRQ,
},
{
- .name = "sdcc_dma_chnl",
+ .name = "dma_chnl",
.start = DMOV_SDC4_CHAN,
.end = DMOV_SDC4_CHAN,
.flags = IORESOURCE_DMA,
},
{
- .name = "sdcc_dma_crci",
+ .name = "dma_crci",
.start = DMOV_SDC4_CRCI,
.end = DMOV_SDC4_CRCI,
.flags = IORESOURCE_DMA,
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index 4093935..2bb82ce 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -5,6 +5,7 @@
* power management protocol extension to H4 to support AR300x Bluetooth Chip.
*
* Copyright (c) 2009-2010 Atheros Communications Inc.
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
*
* Acknowledgements:
* This file is based on hci_h4.c, which was written
@@ -35,12 +36,53 @@
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/skbuff.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include "hci_uart.h"
+unsigned int enableuartsleep;
+module_param(enableuartsleep, uint, 0644);
+/*
+ * Global variables
+ */
+/** Global state flags */
+static unsigned long flags;
+
+/** Tasklet to respond to change in hostwake line */
+static struct tasklet_struct hostwake_task;
+
+/** Transmission timer */
+static void bluesleep_tx_timer_expire(unsigned long data);
+static DEFINE_TIMER(tx_timer, bluesleep_tx_timer_expire, 0, 0);
+
+/** Lock for state transitions */
+static spinlock_t rw_lock;
+
+#define POLARITY_LOW 0
+#define POLARITY_HIGH 1
+
+struct bluesleep_info {
+ unsigned host_wake; /* wake up host */
+ unsigned ext_wake; /* wake up device */
+ unsigned host_wake_irq;
+ int irq_polarity;
+};
+
+/* 1 second timeout */
+#define TX_TIMER_INTERVAL 1
+
+/* state variable names and bit positions */
+#define BT_TXEXPIRED 0x01
+#define BT_SLEEPENABLE 0x02
+#define BT_SLEEPCMD 0x03
+
+/* global pointer to a single hci device. */
+static struct bluesleep_info *bsi;
+
struct ath_struct {
struct hci_uart *hu;
unsigned int cur_sleep;
@@ -49,35 +91,30 @@
struct work_struct ctxtsw;
};
+static void hostwake_interrupt(unsigned long data)
+{
+ printk(KERN_INFO " wakeup host\n");
+}
+
+static void modify_timer_task(void)
+{
+ spin_lock(&rw_lock);
+ mod_timer(&tx_timer, jiffies + (TX_TIMER_INTERVAL * HZ));
+ clear_bit(BT_TXEXPIRED, &flags);
+ spin_unlock(&rw_lock);
+
+}
+
static int ath_wakeup_ar3k(struct tty_struct *tty)
{
- struct ktermios ktermios;
- int status = tty->driver->ops->tiocmget(tty);
-
- if (status & TIOCM_CTS)
- return status;
-
- /* Disable Automatic RTSCTS */
- memcpy(&ktermios, tty->termios, sizeof(ktermios));
- ktermios.c_cflag &= ~CRTSCTS;
- tty_set_termios(tty, &ktermios);
-
- /* Clear RTS first */
- status = tty->driver->ops->tiocmget(tty);
- tty->driver->ops->tiocmset(tty, 0x00, TIOCM_RTS);
- mdelay(20);
-
- /* Set RTS, wake up board */
- status = tty->driver->ops->tiocmget(tty);
- tty->driver->ops->tiocmset(tty, TIOCM_RTS, 0x00);
- mdelay(20);
-
- status = tty->driver->ops->tiocmget(tty);
-
- /* Disable Automatic RTSCTS */
- ktermios.c_cflag |= CRTSCTS;
- status = tty_set_termios(tty, &ktermios);
-
+ int status = 0;
+ if (test_bit(BT_TXEXPIRED, &flags)) {
+ printk(KERN_INFO "wakeup device\n");
+ gpio_set_value(bsi->ext_wake, 1);
+ msleep(20);
+ gpio_set_value(bsi->ext_wake, 0);
+ }
+ modify_timer_task();
return status;
}
@@ -94,12 +131,8 @@
tty = hu->tty;
/* verify and wake up controller */
- if (ath->cur_sleep) {
+ if (test_bit(BT_SLEEPENABLE, &flags))
status = ath_wakeup_ar3k(tty);
- if (!(status & TIOCM_CTS))
- return;
- }
-
/* Ready to send Data */
clear_bit(HCI_UART_SENDING, &hu->tx_state);
hci_uart_tx_wakeup(hu);
@@ -121,6 +154,11 @@
hu->priv = ath;
ath->hu = hu;
+ ath->cur_sleep = enableuartsleep;
+ if (ath->cur_sleep == 1) {
+ set_bit(BT_SLEEPENABLE, &flags);
+ modify_timer_task();
+ }
INIT_WORK(&ath->ctxtsw, ath_hci_uart_work);
return 0;
@@ -173,9 +211,10 @@
*/
if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
struct hci_command_hdr *hdr = (void *)skb->data;
-
- if (__le16_to_cpu(hdr->opcode) == HCI_OP_ATH_SLEEP)
+ if (__le16_to_cpu(hdr->opcode) == HCI_OP_ATH_SLEEP) {
+ set_bit(BT_SLEEPCMD, &flags);
ath->cur_sleep = skb->data[HCI_COMMAND_HDR_SIZE];
+ }
}
BT_DBG("hu %p skb %p", hu, skb);
@@ -201,17 +240,57 @@
/* Recv data */
static int ath_recv(struct hci_uart *hu, void *data, int count)
{
- int ret;
+ struct ath_struct *ath = hu->priv;
+ unsigned int type;
- ret = hci_recv_stream_fragment(hu->hdev, data, count);
- if (ret < 0) {
+ if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
BT_ERR("Frame Reassembly Failed");
- return ret;
- }
+ if (count & test_bit(BT_SLEEPCMD, &flags)) {
+ struct sk_buff *skb = hu->hdev->reassembly[0];
+
+ if (!skb) {
+ struct { char type; } *pkt;
+
+ /* Start of the frame */
+ pkt = data;
+ type = pkt->type;
+ } else
+ type = bt_cb(skb)->pkt_type;
+
+ if (type == HCI_EVENT_PKT) {
+ clear_bit(BT_SLEEPCMD, &flags);
+ printk(KERN_INFO "cur_sleep:%d\n", ath->cur_sleep);
+ if (ath->cur_sleep == 1)
+ set_bit(BT_SLEEPENABLE, &flags);
+ else
+ clear_bit(BT_SLEEPENABLE, &flags);
+ }
+ if (test_bit(BT_SLEEPENABLE, &flags))
+ modify_timer_task();
+ }
return count;
}
+static void bluesleep_tx_timer_expire(unsigned long data)
+{
+ unsigned long irq_flags;
+
+ if (!test_bit(BT_SLEEPENABLE, &flags))
+ return;
+ BT_DBG("Tx timer expired");
+ printk(KERN_INFO "Tx timer expired\n");
+
+ set_bit(BT_TXEXPIRED, &flags);
+}
+
+static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id)
+{
+ /* schedule a tasklet to handle the change in the host wake line */
+ tasklet_schedule(&hostwake_task);
+ return IRQ_HANDLED;
+}
+
static struct hci_uart_proto athp = {
.id = HCI_UART_ATH3K,
.open = ath_open,
@@ -222,19 +301,159 @@
.flush = ath_flush,
};
+static int __init bluesleep_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct resource *res;
+
+ bsi = kzalloc(sizeof(struct bluesleep_info), GFP_KERNEL);
+ if (!bsi) {
+ ret = -ENOMEM;
+ goto failed;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_IO,
+ "gpio_host_wake");
+ if (!res) {
+ BT_ERR("couldn't find host_wake gpio\n");
+ ret = -ENODEV;
+ goto free_bsi;
+ }
+ bsi->host_wake = res->start;
+
+ ret = gpio_request(bsi->host_wake, "bt_host_wake");
+ if (ret)
+ goto free_bsi;
+
+ /* configure host_wake as input */
+ ret = gpio_direction_input(bsi->host_wake);
+ if (ret < 0) {
+ pr_err("%s: gpio_direction_input failed for GPIO %d, error %d\n",
+ __func__, bsi->host_wake, ret);
+ gpio_free(bsi->host_wake);
+ goto free_bsi;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_IO,
+ "gpio_ext_wake");
+ if (!res) {
+ BT_ERR("couldn't find ext_wake gpio\n");
+ ret = -ENODEV;
+ goto free_bt_host_wake;
+ }
+ bsi->ext_wake = res->start;
+
+ ret = gpio_request(bsi->ext_wake, "bt_ext_wake");
+ if (ret)
+ goto free_bt_host_wake;
+
+ /* configure ext_wake as output mode*/
+ ret = gpio_direction_output(bsi->ext_wake, 1);
+ if (ret < 0) {
+ pr_err("%s: gpio_direction_output failed for GPIO %d, error %d\n",
+ __func__, bsi->ext_wake, ret);
+ gpio_free(bsi->ext_wake);
+ goto free_bt_host_wake;
+ }
+ gpio_set_value(bsi->ext_wake, 0);
+
+ bsi->host_wake_irq = platform_get_irq_byname(pdev, "host_wake");
+ if (bsi->host_wake_irq < 0) {
+ BT_ERR("couldn't find host_wake irq\n");
+ ret = -ENODEV;
+ goto free_bt_ext_wake;
+ }
+
+ bsi->irq_polarity = POLARITY_LOW; /* low edge (falling edge) */
+
+ /* Initialize spinlock. */
+ spin_lock_init(&rw_lock);
+
+ /* Initialize timer */
+ init_timer(&tx_timer);
+ tx_timer.function = bluesleep_tx_timer_expire;
+ tx_timer.data = 0;
+
+ /* initialize host wake tasklet */
+ tasklet_init(&hostwake_task, hostwake_interrupt, 0);
+
+ if (bsi->irq_polarity == POLARITY_LOW) {
+ ret = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
+ IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+ "bluetooth hostwake", NULL);
+ } else {
+ ret = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
+ IRQF_DISABLED | IRQF_TRIGGER_RISING,
+ "bluetooth hostwake", NULL);
+ }
+ if (ret < 0) {
+ BT_ERR("Couldn't acquire BT_HOST_WAKE IRQ");
+ goto free_bt_timer;
+ }
+
+ ret = enable_irq_wake(bsi->host_wake_irq);
+ if (ret < 0) {
+ BT_ERR("Couldn't enable BT_HOST_WAKE as wakeup interrupt");
+ free_irq(bsi->host_wake_irq, NULL);
+ goto free_bt_timer;
+ }
+
+ return 0;
+
+free_bt_timer:
+ del_timer(&tx_timer);
+free_bt_ext_wake:
+ gpio_free(bsi->ext_wake);
+free_bt_host_wake:
+ gpio_free(bsi->host_wake);
+free_bsi:
+ kfree(bsi);
+failed:
+ return ret;
+}
+
+static int bluesleep_remove(struct platform_device *pdev)
+{
+ /* assert bt wake */
+ gpio_set_value(bsi->ext_wake, 0);
+ if (disable_irq_wake(bsi->host_wake_irq))
+ BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n");
+ free_irq(bsi->host_wake_irq, NULL);
+ del_timer_sync(&tx_timer);
+ gpio_free(bsi->host_wake);
+ gpio_free(bsi->ext_wake);
+ kfree(bsi);
+ return 0;
+}
+
+static struct platform_driver bluesleep_driver = {
+ .remove = bluesleep_remove,
+ .driver = {
+ .name = "bluesleep",
+ .owner = THIS_MODULE,
+ },
+};
+
int __init ath_init(void)
{
- int err = hci_uart_register_proto(&athp);
+ int ret;
- if (!err)
+ ret = hci_uart_register_proto(&athp);
+
+ if (!ret)
BT_INFO("HCIATH3K protocol initialized");
- else
+ else {
BT_ERR("HCIATH3K protocol registration failed");
-
- return err;
+ return ret;
+ }
+ ret = platform_driver_probe(&bluesleep_driver, bluesleep_probe);
+ if (ret)
+ return ret;
+ return 0;
}
int __exit ath_deinit(void)
{
+ platform_driver_unregister(&bluesleep_driver);
return hci_uart_unregister_proto(&athp);
}
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index e1755de..3047693 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1181,7 +1181,7 @@
/*NOTE: with mmu enabled, gpuaddr doesn't mean
* anything to mmap().
*/
- shadowprop.gpuaddr = device->memstore.physaddr;
+ shadowprop.gpuaddr = device->memstore.gpuaddr;
shadowprop.size = device->memstore.size;
/* GSL needs this to be set, even if it
appears to be meaningless */
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 278be99..fa204c3 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2273,7 +2273,8 @@
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- result = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+ result = remap_pfn_range(vma, vma->vm_start,
+ device->memstore.physaddr >> PAGE_SHIFT,
vma_size, vma->vm_page_prot);
if (result != 0)
KGSL_MEM_ERR(device, "remap_pfn_range failed: %d\n",
@@ -2327,7 +2328,7 @@
/* Handle leagacy behavior for memstore */
- if (vma_offset == device->memstore.physaddr)
+ if (vma_offset == device->memstore.gpuaddr)
return kgsl_mmap_memstore(device, vma);
/* Find a chunk of GPU memory */
diff --git a/drivers/hwmon/pm8xxx-adc.c b/drivers/hwmon/pm8xxx-adc.c
index aa9acf7..8e35252 100644
--- a/drivers/hwmon/pm8xxx-adc.c
+++ b/drivers/hwmon/pm8xxx-adc.c
@@ -23,7 +23,6 @@
#include <linux/hwmon.h>
#include <linux/module.h>
#include <linux/debugfs.h>
-#include <linux/wakelock.h>
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/hwmon-sysfs.h>
@@ -123,6 +122,7 @@
#define PM8XXX_ADC_PA_THERM_VREG_UA_LOAD 100000
#define PM8XXX_ADC_HWMON_NAME_LENGTH 32
#define PM8XXX_ADC_BTM_INTERVAL_MAX 0x14
+#define PM8XXX_ADC_COMPLETION_TIMEOUT (2 * HZ)
struct pm8xxx_adc {
struct device *dev;
@@ -141,7 +141,6 @@
struct work_struct cool_work;
uint32_t mpp_base;
struct device *hwmon;
- struct wake_lock adc_wakelock;
int msm_suspend_check;
struct pm8xxx_adc_amux_properties *conv;
struct pm8xxx_adc_arb_btm_param batt;
@@ -223,7 +222,6 @@
pr_err("PM8xxx ADC request made after suspend_noirq "
"with channel: %d\n", channel);
data_arb_cntrl |= PM8XXX_ADC_ARB_USRP_CNTRL1_EN_ARB;
- wake_lock(&adc_pmic->adc_wakelock);
}
/* Write twice to the CNTRL register for the arbiter settings
@@ -242,8 +240,7 @@
INIT_COMPLETION(adc_pmic->adc_rslt_completion);
rc = pm8xxx_writeb(adc_pmic->dev->parent,
PM8XXX_ADC_ARB_USRP_CNTRL1, data_arb_cntrl);
- } else
- wake_unlock(&adc_pmic->adc_wakelock);
+ }
return 0;
}
@@ -734,7 +731,23 @@
goto fail;
}
- wait_for_completion(&adc_pmic->adc_rslt_completion);
+ rc = wait_for_completion_timeout(&adc_pmic->adc_rslt_completion,
+ PM8XXX_ADC_COMPLETION_TIMEOUT);
+ if (!rc) {
+ u8 data_arb_usrp_cntrl1 = 0;
+ rc = pm8xxx_adc_read_reg(PM8XXX_ADC_ARB_USRP_CNTRL1,
+ &data_arb_usrp_cntrl1);
+ if (rc < 0)
+ goto fail;
+ if (data_arb_usrp_cntrl1 == (PM8XXX_ADC_ARB_USRP_CNTRL1_EOC |
+ PM8XXX_ADC_ARB_USRP_CNTRL1_EN_ARB))
+ pr_debug("End of conversion status set\n");
+ else {
+ pr_err("EOC interrupt not received\n");
+ rc = -EINVAL;
+ goto fail;
+ }
+ }
rc = pm8xxx_adc_read_adc_code(&result->adc_code);
if (rc) {
@@ -1134,7 +1147,6 @@
struct pm8xxx_adc *adc_pmic = pmic_adc;
int i;
- wake_lock_destroy(&adc_pmic->adc_wakelock);
platform_set_drvdata(pdev, NULL);
pmic_adc = NULL;
if (!pa_therm) {
@@ -1236,8 +1248,6 @@
disable_irq_nosync(adc_pmic->btm_cool_irq);
platform_set_drvdata(pdev, adc_pmic);
- wake_lock_init(&adc_pmic->adc_wakelock, WAKE_LOCK_SUSPEND,
- "pm8xxx_adc_wakelock");
adc_pmic->msm_suspend_check = 0;
pmic_adc = adc_pmic;
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 790cc10..df71f76 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -685,6 +685,52 @@
}
}
+void dvb_dmx_swfilter_section_packets(struct dvb_demux *demux, const u8 *buf,
+ size_t count)
+{
+ struct dvb_demux_feed *feed;
+ u16 pid = ts_pid(buf);
+ struct timespec pre_time;
+
+ if (dvb_demux_performancecheck)
+ pre_time = current_kernel_time();
+
+ spin_lock(&demux->lock);
+
+ demux->sw_filter_abort = 0;
+
+ while (count--) {
+ if (buf[0] != 0x47) {
+ buf += 188;
+ continue;
+ }
+
+ if (demux->playback_mode == DMX_PB_MODE_PULL)
+ if (dvb_dmx_swfilter_buffer_check(demux, pid) < 0)
+ break;
+
+ list_for_each_entry(feed, &demux->feed_list, list_head) {
+ if (feed->pid != pid)
+ continue;
+
+ if (!feed->feed.sec.is_filtering)
+ continue;
+
+ if (dvb_dmx_swfilter_section_packet(feed, buf) < 0) {
+ feed->feed.sec.seclen = 0;
+ feed->feed.sec.secbufp = 0;
+ }
+ }
+ buf += 188;
+ }
+
+ spin_unlock(&demux->lock);
+
+ if (dvb_demux_performancecheck)
+ demux->total_process_time += dvb_dmx_calc_time_delta(pre_time);
+}
+EXPORT_SYMBOL(dvb_dmx_swfilter_section_packets);
+
void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
size_t count)
{
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.h b/drivers/media/dvb/dvb-core/dvb_demux.h
index a663191..5a32363 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.h
+++ b/drivers/media/dvb/dvb-core/dvb_demux.h
@@ -179,6 +179,8 @@
int dvb_dmx_init(struct dvb_demux *dvbdemux);
void dvb_dmx_release(struct dvb_demux *dvbdemux);
+void dvb_dmx_swfilter_section_packets(struct dvb_demux *demux, const u8 *buf,
+ size_t count);
void dvb_dmx_swfilter_packets(struct dvb_demux *dvbdmx, const u8 *buf,
size_t count);
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count);
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 3cd6a25..a69858a 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -551,7 +551,8 @@
* If mctl node doesnt have the instance, then
* search in the user's video node */
if (pmctl->vfe_output_mode == VFE_OUTPUTS_MAIN_AND_THUMB
- || pmctl->vfe_output_mode == VFE_OUTPUTS_THUMB_AND_MAIN) {
+ || pmctl->vfe_output_mode == VFE_OUTPUTS_THUMB_AND_MAIN
+ || pmctl->vfe_output_mode == VFE_OUTPUTS_MAIN_AND_PREVIEW) {
if (pcam->mctl_node.dev_inst_map[img_mode]
&& is_buffer_queued(pcam, img_mode)) {
idx = pcam->mctl_node.dev_inst_map[img_mode]->my_index;
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.c b/drivers/media/video/msm/vfe/msm_vfe32.c
index a96a945..2f50d7f 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.c
+++ b/drivers/media/video/msm/vfe/msm_vfe32.c
@@ -443,6 +443,8 @@
* at any time. stop camif immediately. */
msm_camera_io_w(CAMIF_COMMAND_STOP_IMMEDIATELY,
vfe32_ctrl->share_ctrl->vfebase + VFE_CAMIF_COMMAND);
+ vfe32_ctrl->share_ctrl->operation_mode &=
+ ~(vfe32_ctrl->share_ctrl->current_mode);
}
static void vfe32_subdev_notify(int id, int path, uint32_t inst_handle,
@@ -591,6 +593,7 @@
/* 0 for continuous mode, 1 for snapshot mode */
vfe32_ctrl->share_ctrl->operation_mode = 0;
+ vfe32_ctrl->share_ctrl->current_mode = 0;
vfe32_ctrl->share_ctrl->outpath.output_mode = 0;
vfe32_ctrl->share_ctrl->vfe_capture_count = 0;
@@ -1063,11 +1066,11 @@
{
uint32_t irq_mask = 0x00E00021, irq_mask1, reg_update;
uint16_t vfe_operation_mode =
- vfe32_ctrl->share_ctrl->operation_mode & ~(VFE_OUTPUTS_RDI0|
+ vfe32_ctrl->share_ctrl->current_mode & ~(VFE_OUTPUTS_RDI0|
VFE_OUTPUTS_RDI1);
vfe32_ctrl->start_ack_pending = TRUE;
CDBG("VFE opertaion mode = 0x%x, output mode = 0x%x\n",
- vfe32_ctrl->share_ctrl->operation_mode,
+ vfe32_ctrl->share_ctrl->current_mode,
vfe32_ctrl->share_ctrl->outpath.output_mode);
if (vfe32_ctrl->share_ctrl->stats_comp)
irq_mask |= VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK;
@@ -1088,14 +1091,14 @@
msm_camera_io_r_mb(vfe32_ctrl->share_ctrl->vfebase +
VFE_REG_UPDATE_CMD);
- if (vfe32_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI0) {
+ if (vfe32_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0) {
irq_mask1 |= VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK;
msm_camera_io_w(irq_mask1, vfe32_ctrl->share_ctrl->vfebase +
VFE_IRQ_MASK_1);
msm_camera_io_w_mb(reg_update|0x2, vfe32_ctrl->share_ctrl->
vfebase + VFE_REG_UPDATE_CMD);
}
- if (vfe32_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI1) {
+ if (vfe32_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1) {
irq_mask1 |= VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK;
msm_camera_io_w(irq_mask1, vfe32_ctrl->share_ctrl->vfebase +
VFE_IRQ_MASK_1);
@@ -1108,9 +1111,8 @@
msm_camera_io_w_mb(1, vfe32_ctrl->share_ctrl->vfebase +
VFE_CAMIF_COMMAND);
}
- msm_camera_io_dump(vfe32_ctrl->share_ctrl->vfebase,
- vfe32_ctrl->share_ctrl->register_total * 4);
-
+ vfe32_ctrl->share_ctrl->operation_mode |=
+ vfe32_ctrl->share_ctrl->current_mode;
/* Ensure the write order while writing
to the command register using the barrier */
atomic_set(&vfe32_ctrl->share_ctrl->vstate, 1);
@@ -1171,90 +1173,6 @@
struct msm_cam_media_controller *pmctl,
struct vfe32_ctrl_type *vfe32_ctrl)
{
- uint32_t irq_comp_mask = 0;
- /* capture command is valid for both idle and active state. */
- irq_comp_mask =
- msm_camera_io_r(vfe32_ctrl->
- share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-
- CDBG("%s:op mode %d O/P Mode %d\n", __func__,
- vfe32_ctrl->share_ctrl->operation_mode,
- vfe32_ctrl->share_ctrl->outpath.output_mode);
-
- if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY) {
- irq_comp_mask |= (
- (0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch0)) |
- (0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch1)));
- } else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
- irq_comp_mask |= (
- (0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch0)) |
- (0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch1)) |
- (0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch2)));
- }
-
- if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY) {
- irq_comp_mask |= ((0x1 << (vfe32_ctrl->
- share_ctrl->outpath.out1.ch0 + 8)) |
- (0x1 << (vfe32_ctrl->
- share_ctrl->outpath.out1.ch1 + 8)));
- } else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
- irq_comp_mask |= (
- (0x1 << (vfe32_ctrl->
- share_ctrl->outpath.out1.ch0 + 8)) |
- (0x1 << (vfe32_ctrl->
- share_ctrl->outpath.out1.ch1 + 8)) |
- (0x1 << (vfe32_ctrl->
- share_ctrl->outpath.out1.ch2 + 8)));
- }
-
- if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch1]);
- } else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch1]);
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch2]);
- }
-
- if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY) {
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out1.ch1]);
- } else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out1.ch1]);
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out1.ch2]);
- }
-
- msm_camera_io_w(irq_comp_mask,
- vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
vfe32_start_common(vfe32_ctrl);
msm_camio_bus_scale_cfg(
pmctl->sdata->pdata->cam_bus_scale_table, S_ZSL);
@@ -1268,26 +1186,8 @@
struct vfe32_ctrl_type *vfe32_ctrl,
uint32_t num_frames_capture)
{
- uint32_t irq_comp_mask = 0;
-
vfe32_ctrl->share_ctrl->outpath.out0.capture_cnt = num_frames_capture;
vfe32_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
-
- irq_comp_mask =
- msm_camera_io_r(
- vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-
- if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY) {
- irq_comp_mask |=
- (0x1 << (vfe32_ctrl->share_ctrl->outpath.out0.ch0));
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch0]);
- }
-
- msm_camera_io_w(irq_comp_mask,
- vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
msm_camio_bus_scale_cfg(
pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
vfe32_start_common(vfe32_ctrl);
@@ -1299,72 +1199,24 @@
uint32_t num_frames_capture,
struct vfe32_ctrl_type *vfe32_ctrl)
{
- uint32_t irq_comp_mask = 0;
-
/* capture command is valid for both idle and active state. */
vfe32_ctrl->share_ctrl->outpath.out1.capture_cnt = num_frames_capture;
- if (vfe32_ctrl->share_ctrl->operation_mode ==
+ if (vfe32_ctrl->share_ctrl->current_mode ==
VFE_OUTPUTS_MAIN_AND_THUMB ||
- vfe32_ctrl->share_ctrl->operation_mode ==
+ vfe32_ctrl->share_ctrl->current_mode ==
VFE_OUTPUTS_THUMB_AND_MAIN ||
- vfe32_ctrl->share_ctrl->operation_mode ==
+ vfe32_ctrl->share_ctrl->current_mode ==
VFE_OUTPUTS_JPEG_AND_THUMB ||
- vfe32_ctrl->share_ctrl->operation_mode ==
+ vfe32_ctrl->share_ctrl->current_mode ==
VFE_OUTPUTS_THUMB_AND_JPEG) {
vfe32_ctrl->share_ctrl->outpath.out0.capture_cnt =
num_frames_capture;
}
vfe32_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
- irq_comp_mask = msm_camera_io_r(
- vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-
- if (vfe32_ctrl->share_ctrl->operation_mode ==
- VFE_OUTPUTS_MAIN_AND_THUMB ||
- vfe32_ctrl->share_ctrl->operation_mode ==
- VFE_OUTPUTS_JPEG_AND_THUMB ||
- vfe32_ctrl->share_ctrl->operation_mode ==
- VFE_OUTPUTS_THUMB_AND_MAIN) {
- if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY) {
- irq_comp_mask |= (0x1 << vfe32_ctrl->
- share_ctrl->outpath.out0.ch0 |
- 0x1 << vfe32_ctrl->
- share_ctrl->outpath.out0.ch1);
- }
- if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY) {
- irq_comp_mask |=
- (0x1 << (vfe32_ctrl->
- share_ctrl->outpath.out1.ch0 + 8) |
- 0x1 << (vfe32_ctrl->
- share_ctrl->outpath.out1.ch1 + 8));
- }
- if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY) {
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out0.ch1]);
- }
- if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY) {
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out1.ch0]);
- msm_camera_io_w(1, vfe32_ctrl->share_ctrl->vfebase +
- vfe32_AXI_WM_CFG[vfe32_ctrl->
- share_ctrl->outpath.out1.ch1]);
- }
- }
vfe32_ctrl->share_ctrl->vfe_capture_count = num_frames_capture;
- msm_camera_io_w(irq_comp_mask,
- vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
- msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
msm_camio_bus_scale_cfg(
pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
@@ -1379,58 +1231,6 @@
struct msm_cam_media_controller *pmctl,
struct vfe32_ctrl_type *vfe32_ctrl)
{
- uint32_t irq_comp_mask = 0, irq_mask = 0;
-
- irq_comp_mask =
- msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
- VFE_IRQ_COMP_MASK);
-
- if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY) {
- irq_comp_mask |= (
- 0x1 << vfe32_ctrl->share_ctrl->outpath.out0.ch0 |
- 0x1 << vfe32_ctrl->share_ctrl->outpath.out0.ch1);
- } else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
- irq_comp_mask |= (
- 0x1 << vfe32_ctrl->share_ctrl->outpath.out0.ch0 |
- 0x1 << vfe32_ctrl->share_ctrl->outpath.out0.ch1 |
- 0x1 << vfe32_ctrl->share_ctrl->outpath.out0.ch2);
- }
- if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY) {
- irq_comp_mask |= (
- 0x1 << (vfe32_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
- 0x1 << (vfe32_ctrl->share_ctrl->outpath.out1.ch1 + 8));
- } else if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
- irq_comp_mask |= (
- 0x1 << (vfe32_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
- 0x1 << (vfe32_ctrl->share_ctrl->outpath.out1.ch1 + 8) |
- 0x1 << (vfe32_ctrl->share_ctrl->outpath.out1.ch2 + 8));
- }
- if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_TERTIARY1) {
- irq_mask = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
- irq_mask |= (0x1 << (vfe32_ctrl->share_ctrl->outpath.out2.ch0 +
- VFE_WM_OFFSET));
- msm_camera_io_w(irq_mask, vfe32_ctrl->share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
- }
- if (vfe32_ctrl->share_ctrl->outpath.output_mode &
- VFE32_OUTPUT_MODE_TERTIARY2) {
- irq_mask = msm_camera_io_r(vfe32_ctrl->share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
- irq_mask |= (0x1 << (vfe32_ctrl->share_ctrl->outpath.out3.ch0 +
- VFE_WM_OFFSET));
- msm_camera_io_w(irq_mask, vfe32_ctrl->share_ctrl->vfebase +
- VFE_IRQ_MASK_0);
- }
-
- msm_camera_io_w(irq_comp_mask,
- vfe32_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
-
msm_camio_bus_scale_cfg(
pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
vfe32_start_common(vfe32_ctrl);
@@ -1696,7 +1496,7 @@
vfe32_ctrl->share_ctrl->vfebase, outch->ch0,
outch->pong.ch_paddr[0]);
- if ((vfe32_ctrl->share_ctrl->operation_mode !=
+ if ((vfe32_ctrl->share_ctrl->current_mode !=
VFE_OUTPUTS_RAW) && (path != VFE_MSG_OUTPUT_TERTIARY1)
&& (path != VFE_MSG_OUTPUT_TERTIARY2)) {
vfe32_put_ch_ping_addr(
@@ -1769,6 +1569,7 @@
uint32_t snapshot_cnt = 0;
uint32_t temp1 = 0, temp2 = 0;
uint16_t vfe_mode = 0;
+ struct msm_camera_vfe_params_t vfe_params;
CDBG("vfe32_proc_general: cmdID = %s, length = %d\n",
vfe32_general_cmd[cmd->id], cmd->length);
@@ -1782,12 +1583,21 @@
case VFE_CMD_START:
pr_info("vfe32_proc_general: cmdID = %s\n",
vfe32_general_cmd[cmd->id]);
- vfe_mode = vfe32_ctrl->share_ctrl->operation_mode
+ if (copy_from_user(&vfe_params,
+ (void __user *)(cmd->value),
+ sizeof(struct msm_camera_vfe_params_t))) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+
+ vfe32_ctrl->share_ctrl->current_mode =
+ vfe_params.operation_mode;
+ vfe_mode = vfe32_ctrl->share_ctrl->current_mode
& ~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1);
if (vfe_mode) {
- if ((vfe32_ctrl->share_ctrl->operation_mode &
+ if ((vfe32_ctrl->share_ctrl->current_mode &
VFE_OUTPUTS_PREVIEW_AND_VIDEO) ||
- (vfe32_ctrl->share_ctrl->operation_mode &
+ (vfe32_ctrl->share_ctrl->current_mode &
VFE_OUTPUTS_PREVIEW))
/* Configure primary channel */
rc = vfe32_configure_pingpong_buffers(
@@ -1801,12 +1611,12 @@
VFE_MSG_OUTPUT_SECONDARY,
vfe32_ctrl);
}
- if (vfe32_ctrl->share_ctrl->operation_mode &
+ if (vfe32_ctrl->share_ctrl->current_mode &
VFE_OUTPUTS_RDI0)
rc = vfe32_configure_pingpong_buffers(
VFE_MSG_START, VFE_MSG_OUTPUT_TERTIARY1,
vfe32_ctrl);
- if (vfe32_ctrl->share_ctrl->operation_mode &
+ if (vfe32_ctrl->share_ctrl->current_mode &
VFE_OUTPUTS_RDI1)
rc = vfe32_configure_pingpong_buffers(
VFE_MSG_START, VFE_MSG_OUTPUT_TERTIARY2,
@@ -1825,11 +1635,16 @@
break;
case VFE_CMD_CAPTURE_RAW:
pr_info("%s: cmdID = VFE_CMD_CAPTURE_RAW\n", __func__);
- if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
- sizeof(uint32_t))) {
- rc = -EFAULT;
- goto proc_general_done;
+ if (copy_from_user(&vfe_params,
+ (void __user *)(cmd->value),
+ sizeof(struct msm_camera_vfe_params_t))) {
+ rc = -EFAULT;
+ goto proc_general_done;
}
+
+ snapshot_cnt = vfe_params.capture_count;
+ vfe32_ctrl->share_ctrl->current_mode =
+ vfe_params.operation_mode;
rc = vfe32_configure_pingpong_buffers(
VFE_MSG_CAPTURE, VFE_MSG_OUTPUT_PRIMARY,
vfe32_ctrl);
@@ -1842,15 +1657,19 @@
rc = vfe32_capture_raw(pmctl, vfe32_ctrl, snapshot_cnt);
break;
case VFE_CMD_CAPTURE:
- if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
- sizeof(uint32_t))) {
- rc = -EFAULT;
- goto proc_general_done;
+ if (copy_from_user(&vfe_params,
+ (void __user *)(cmd->value),
+ sizeof(struct msm_camera_vfe_params_t))) {
+ rc = -EFAULT;
+ goto proc_general_done;
}
- if (vfe32_ctrl->share_ctrl->operation_mode ==
+ snapshot_cnt = vfe_params.capture_count;
+ vfe32_ctrl->share_ctrl->current_mode =
+ vfe_params.operation_mode;
+ if (vfe32_ctrl->share_ctrl->current_mode ==
VFE_OUTPUTS_JPEG_AND_THUMB ||
- vfe32_ctrl->share_ctrl->operation_mode ==
+ vfe32_ctrl->share_ctrl->current_mode ==
VFE_OUTPUTS_THUMB_AND_JPEG) {
if (snapshot_cnt != 1) {
pr_err("only support 1 inline snapshot\n");
@@ -1897,7 +1716,7 @@
rc = -EFAULT;
goto proc_general_done;
}
- if (vfe32_ctrl->share_ctrl->operation_mode &
+ if (vfe32_ctrl->share_ctrl->current_mode &
VFE_OUTPUTS_PREVIEW_AND_VIDEO) {
vfe32_ctrl->share_ctrl->outpath.out1.inst_handle =
temp1;
@@ -1905,7 +1724,7 @@
VFE_MSG_START_RECORDING,
VFE_MSG_OUTPUT_SECONDARY,
vfe32_ctrl);
- } else if (vfe32_ctrl->share_ctrl->operation_mode &
+ } else if (vfe32_ctrl->share_ctrl->current_mode &
VFE_OUTPUTS_VIDEO_AND_PREVIEW) {
vfe32_ctrl->share_ctrl->outpath.out0.inst_handle =
temp1;
@@ -2958,6 +2777,15 @@
case VFE_CMD_STOP:
pr_info("vfe32_proc_general: cmdID = %s\n",
vfe32_general_cmd[cmd->id]);
+ if (copy_from_user(&vfe_params,
+ (void __user *)(cmd->value),
+ sizeof(struct msm_camera_vfe_params_t))) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+
+ vfe32_ctrl->share_ctrl->current_mode =
+ vfe_params.operation_mode;
vfe32_stop(vfe32_ctrl);
break;
@@ -3001,6 +2829,15 @@
break;
case VFE_CMD_ZSL:
+ if (copy_from_user(&vfe_params,
+ (void __user *)(cmd->value),
+ sizeof(struct msm_camera_vfe_params_t))) {
+ rc = -EFAULT;
+ goto proc_general_done;
+ }
+
+ vfe32_ctrl->share_ctrl->current_mode =
+ vfe_params.operation_mode;
rc = vfe32_configure_pingpong_buffers(VFE_MSG_START,
VFE_MSG_OUTPUT_PRIMARY, vfe32_ctrl);
if (rc < 0)
@@ -3481,13 +3318,13 @@
break;
}
- if ((vfe32_ctrl->share_ctrl->operation_mode ==
+ if ((vfe32_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_THUMB_AND_MAIN) ||
- (vfe32_ctrl->share_ctrl->operation_mode ==
+ (vfe32_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_MAIN_AND_THUMB) ||
- (vfe32_ctrl->share_ctrl->operation_mode ==
+ (vfe32_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_THUMB_AND_JPEG) ||
- (vfe32_ctrl->share_ctrl->operation_mode ==
+ (vfe32_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_JPEG_AND_THUMB)) {
/* in snapshot mode */
/* later we need to add check for live snapshot mode. */
@@ -3684,7 +3521,7 @@
static void vfe32_process_camif_sof_irq(
struct vfe32_ctrl_type *vfe32_ctrl)
{
- if (vfe32_ctrl->share_ctrl->operation_mode ==
+ if (vfe32_ctrl->share_ctrl->operation_mode &
VFE_OUTPUTS_RAW) {
if (vfe32_ctrl->start_ack_pending) {
vfe32_send_isp_msg(&vfe32_ctrl->subdev,
@@ -5288,15 +5125,116 @@
vfe32_ctrl->share_ctrl->vfebase = NULL;
}
-void axi_start(struct axi_ctrl_t *axi_ctrl)
+void axi_start(struct axi_ctrl_t *axi_ctrl, uint16_t cmd_type)
{
- uint16_t operation_mode =
+ uint32_t irq_comp_mask = 0, irq_mask = 0;
+
+ irq_comp_mask =
+ msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_COMP_MASK);
+
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY) {
+ irq_comp_mask |= (
+ 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
+ 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1);
+ } else if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ irq_comp_mask |= (
+ 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch0 |
+ 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch1 |
+ 0x1 << axi_ctrl->share_ctrl->outpath.out0.ch2);
+ }
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY) {
+ irq_comp_mask |= (
+ 0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
+ 0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch1 + 8));
+ } else if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ irq_comp_mask |= (
+ 0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch0 + 8) |
+ 0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch1 + 8) |
+ 0x1 << (axi_ctrl->share_ctrl->outpath.out1.ch2 + 8));
+ }
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_TERTIARY1) {
+ irq_mask = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ irq_mask |= (0x1 << (axi_ctrl->share_ctrl->outpath.out2.ch0 +
+ VFE_WM_OFFSET));
+ msm_camera_io_w(irq_mask, axi_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ }
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_TERTIARY2) {
+ irq_mask = msm_camera_io_r(axi_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ irq_mask |= (0x1 << (axi_ctrl->share_ctrl->outpath.out3.ch0 +
+ VFE_WM_OFFSET));
+ msm_camera_io_w(irq_mask, axi_ctrl->share_ctrl->vfebase +
+ VFE_IRQ_MASK_0);
+ }
+
+ msm_camera_io_w(irq_comp_mask,
+ axi_ctrl->share_ctrl->vfebase + VFE_IRQ_COMP_MASK);
+
+ switch (cmd_type) {
+ case AXI_CMD_PREVIEW: {
+ uint16_t operation_mode =
(axi_ctrl->share_ctrl->operation_mode &
~(VFE_OUTPUTS_RDI0|VFE_OUTPUTS_RDI1));
- switch (operation_mode) {
- case VFE_OUTPUTS_PREVIEW:
- case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
+ switch (operation_mode) {
+ case VFE_OUTPUTS_PREVIEW:
+ case VFE_OUTPUTS_PREVIEW_AND_VIDEO:
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY) {
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch1]);
+ } else if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_PRIMARY_ALL_CHNLS) {
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch0]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch1]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out0.ch2]);
+ }
+ break;
+ default:
+ if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY) {
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch1]);
+ } else if (axi_ctrl->share_ctrl->outpath.output_mode &
+ VFE32_OUTPUT_MODE_SECONDARY_ALL_CHNLS) {
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch0]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch1]);
+ msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase
+ + vfe32_AXI_WM_CFG[axi_ctrl->
+ share_ctrl->outpath.out1.ch2]);
+ }
+ break;
+ }
+ }
+ break;
+ default:
if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_PRIMARY) {
msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
@@ -5317,8 +5255,7 @@
vfe32_AXI_WM_CFG[axi_ctrl->
share_ctrl->outpath.out0.ch2]);
}
- break;
- default:
+
if (axi_ctrl->share_ctrl->outpath.output_mode &
VFE32_OUTPUT_MODE_SECONDARY) {
msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
@@ -5341,19 +5278,17 @@
}
break;
}
-
- if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI0)
+ if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI0)
msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
outpath.out2.ch0]);
- if (axi_ctrl->share_ctrl->operation_mode & VFE_OUTPUTS_RDI1)
+ if (axi_ctrl->share_ctrl->current_mode & VFE_OUTPUTS_RDI1)
msm_camera_io_w(1, axi_ctrl->share_ctrl->vfebase +
vfe32_AXI_WM_CFG[axi_ctrl->share_ctrl->
outpath.out3.ch0]);
-
}
-void axi_stop(struct axi_ctrl_t *axi_ctrl)
+void axi_stop(struct axi_ctrl_t *axi_ctrl, uint16_t cmd_type)
{
uint8_t axiBusyFlag = true;
/* axi halt command. */
@@ -5576,11 +5511,29 @@
pr_err("%s Invalid/Unsupported AXI configuration %x",
__func__, cfgcmd.cmd_type);
break;
- case CMD_AXI_START:
- axi_start(axi_ctrl);
+ case CMD_AXI_START: {
+ struct msm_camera_vfe_params_t vfe_params;
+ if (copy_from_user(&vfe_params,
+ (void __user *)(vfecmd.value),
+ sizeof(struct msm_camera_vfe_params_t))) {
+ return -EFAULT;
+ }
+ axi_ctrl->share_ctrl->current_mode =
+ vfe_params.operation_mode;
+ axi_start(axi_ctrl, vfe_params.cmd_type);
+ }
break;
- case CMD_AXI_STOP:
- axi_stop(axi_ctrl);
+ case CMD_AXI_STOP: {
+ struct msm_camera_vfe_params_t vfe_params;
+ if (copy_from_user(&vfe_params,
+ (void __user *)(vfecmd.value),
+ sizeof(struct msm_camera_vfe_params_t))) {
+ return -EFAULT;
+ }
+ axi_ctrl->share_ctrl->current_mode =
+ vfe_params.operation_mode;
+ axi_stop(axi_ctrl, vfe_params.cmd_type);
+ }
break;
default:
pr_err("%s Unsupported AXI configuration %x ", __func__,
@@ -5624,7 +5577,8 @@
/* in snapshot mode if done then send
snapshot done message */
- if (axi_ctrl->share_ctrl->operation_mode ==
+ if (
+ axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_THUMB_AND_MAIN ||
axi_ctrl->share_ctrl->operation_mode ==
VFE_OUTPUTS_MAIN_AND_THUMB ||
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.h b/drivers/media/video/msm/vfe/msm_vfe32.h
index d3575d7..170bfb7 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.h
+++ b/drivers/media/video/msm/vfe/msm_vfe32.h
@@ -948,10 +948,12 @@
enum vfe_output_state liveshot_state;
uint32_t vfe_capture_count;
- uint16_t operation_mode; /* streaming or snapshot */
+ uint32_t operation_mode; /* streaming or snapshot */
+ uint32_t current_mode;
struct vfe32_output_path outpath;
- uint32_t ref_count;
+ uint16_t port_info;
+ uint32_t skip_abort;
spinlock_t sd_notify_lock;
struct axi_ctrl_t *axi_ctrl;
diff --git a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
index b6daa5f..e1d8b48 100644
--- a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
@@ -333,6 +333,7 @@
"VFE_SCALE_OUTPUT2_CONFIG"},
{VFE_CMD_CAPTURE_RAW, VFE_START, QDSP_CMDQUEUE,
"VFE_CMD_CAPTURE_RAW", "VFE_START"},
+ {VFE_CMD_STOP_LIVESHOT, VFE_MAX, VFE_MAX},
{VFE_CMD_RECONFIG_VFE, VFE_MAX, VFE_MAX},
};
@@ -666,6 +667,8 @@
void *data = NULL;
struct buf_info *outch = NULL;
uint32_t y_phy, cbcr_phy;
+ static uint32_t liveshot_y_phy;
+ static struct vfe_endframe liveshot_swap;
struct table_cmd *table_pending = NULL;
unsigned long flags;
void *cmd_data = NULL;
@@ -833,48 +836,139 @@
if (op_mode & SNAPSHOT_MASK_MODE) {
kfree(data);
return;
- } else {
- free_buf = vfe2x_check_free_buffer(
+ }
+ free_buf = vfe2x_check_free_buffer(
VFE_MSG_OUTPUT_IRQ,
VFE_MSG_OUTPUT_PRIMARY);
- CDBG("free_buf = %x\n", (unsigned int) free_buf);
- if (free_buf) {
+ CDBG("free_buf = %x\n",
+ (unsigned int) free_buf);
+ spin_lock_irqsave(
+ &vfe2x_ctrl->liveshot_enabled_lock,
+ flags);
+ if (!vfe2x_ctrl->liveshot_enabled) {
+ spin_unlock_irqrestore(
+ &vfe2x_ctrl->
+ liveshot_enabled_lock,
+ flags);
+ if (free_buf) {
fack.header = VFE_OUTPUT2_ACK;
fack.output2newybufferaddress =
- (void *)(free_buf->ch_paddr[0]);
+ (void *)
+ (free_buf->ch_paddr[0]);
fack.output2newcbcrbufferaddress =
- (void *)(free_buf->ch_paddr[1]);
+ (void *)
+ (free_buf->ch_paddr[1]);
cmd_data = &fack;
len = sizeof(fack);
- msm_adsp_write(vfe_mod, QDSP_CMDQUEUE,
+ msm_adsp_write(vfe_mod,
+ QDSP_CMDQUEUE,
cmd_data, len);
- } else {
+ } else {
fack.header = VFE_OUTPUT2_ACK;
fack.output2newybufferaddress =
- (void *)
- ((struct vfe_endframe *)data)->y_address;
+ (void *)
+ ((struct vfe_endframe *)
+ data)->y_address;
fack.output2newcbcrbufferaddress =
- (void *)
- ((struct vfe_endframe *)data)->cbcr_address;
+ (void *)
+ ((struct vfe_endframe *)
+ data)->cbcr_address;
cmd_data = &fack;
len = sizeof(fack);
- msm_adsp_write(vfe_mod, QDSP_CMDQUEUE,
- cmd_data, len);
+ msm_adsp_write(vfe_mod,
+ QDSP_CMDQUEUE,
+ cmd_data, len);
if (!vfe2x_ctrl->zsl_mode) {
kfree(data);
return;
}
}
+ } else { /* Live snapshot */
+ spin_unlock_irqrestore(
+ &vfe2x_ctrl->
+ liveshot_enabled_lock,
+ flags);
+ if (free_buf) {
+ /* liveshot_swap to enqueue
+ when liveshot snapshot buffer
+ is obtainedi from adsp */
+ liveshot_swap.y_address =
+ ((struct vfe_endframe *)
+ data)->y_address;
+ liveshot_swap.cbcr_address =
+ ((struct vfe_endframe *)
+ data)->cbcr_address;
+
+ fack.header = VFE_OUTPUT2_ACK;
+
+ fack.output2newybufferaddress =
+ (void *)
+ (free_buf->ch_paddr[0]);
+
+ fack.output2newcbcrbufferaddress =
+ (void *)
+ (free_buf->ch_paddr[1]);
+
+ liveshot_y_phy =
+ (uint32_t)
+ fack.output2newybufferaddress;
+
+ cmd_data = &fack;
+ len = sizeof(fack);
+ msm_adsp_write(vfe_mod,
+ QDSP_CMDQUEUE,
+ cmd_data, len);
+ } else if (liveshot_y_phy !=
+ ((struct vfe_endframe *)
+ data)->y_address) {
+
+ fack.header = VFE_OUTPUT2_ACK;
+ fack.output2newybufferaddress =
+ (void *)
+ ((struct vfe_endframe *)
+ data)->y_address;
+
+ fack.output2newcbcrbufferaddress =
+ (void *)
+ ((struct vfe_endframe *)
+ data)->cbcr_address;
+
+ cmd_data = &fack;
+ len = sizeof(fack);
+ msm_adsp_write(vfe_mod,
+ QDSP_CMDQUEUE,
+ cmd_data, len);
+ kfree(data);
+ return;
+ } else {
+ /* Enque data got
+ * during freebuf */
+ fack.header = VFE_OUTPUT2_ACK;
+ fack.output2newybufferaddress =
+ (void *)
+ (liveshot_swap.y_address);
+
+ fack.output2newcbcrbufferaddress =
+ (void *)
+ (liveshot_swap.cbcr_address);
+ cmd_data = &fack;
+ len = sizeof(fack);
+ msm_adsp_write(vfe_mod,
+ QDSP_CMDQUEUE,
+ cmd_data, len);
+ }
}
- y_phy = ((struct vfe_endframe *)data)->y_address;
- cbcr_phy = ((struct vfe_endframe *)data)->cbcr_address;
+ y_phy = ((struct vfe_endframe *)data)->
+ y_address;
+ cbcr_phy = ((struct vfe_endframe *)data)->
+ cbcr_address;
- CDBG("vfe_7x_convert, y_phy = 0x%x, cbcr_phy = 0x%x\n",
- y_phy, cbcr_phy);
+ CDBG("MSG_OUT2:y_phy= 0x%x, cbcr_phy= 0x%x\n",
+ y_phy, cbcr_phy);
if (free_buf) {
for (i = 0; i < 3; i++) {
if (vfe2x_ctrl->free_buf.buf[i].
@@ -892,14 +986,23 @@
CDBG("Address doesnt match\n");
}
memcpy(((struct vfe_frame_extra *)extdata),
- &((struct vfe_endframe *)data)->extra,
- sizeof(struct vfe_frame_extra));
+ &((struct vfe_endframe *)data)->extra,
+ sizeof(struct vfe_frame_extra));
vfe2x_ctrl->vfeFrameId =
- ((struct vfe_frame_extra *)extdata)->frame_id;
- vfe_send_outmsg(&vfe2x_ctrl->subdev,
+ ((struct vfe_frame_extra *)extdata)->
+ frame_id;
+
+ if (!vfe2x_ctrl->liveshot_enabled) {
+ /* Liveshot not enalbed */
+ vfe_send_outmsg(&vfe2x_ctrl->subdev,
MSG_ID_OUTPUT_PRIMARY,
y_phy, cbcr_phy);
+ } else if (liveshot_y_phy == y_phy) {
+ vfe_send_outmsg(&vfe2x_ctrl->subdev,
+ MSG_ID_OUTPUT_PRIMARY,
+ y_phy, cbcr_phy);
+ }
break;
case MSG_RESET_ACK:
case MSG_START_ACK:
@@ -1056,6 +1159,7 @@
int cnt;
int rc = 0;
int o_mode = 0;
+ unsigned long flags;
if (op_mode & SNAPSHOT_MASK_MODE)
o_mode = SNAPSHOT_MASK_MODE;
@@ -1164,8 +1268,17 @@
ao->output2buffer1_cbcr_phy = ad->ping.ch_paddr[1];
ao->output2buffer2_y_phy = ad->pong.ch_paddr[0];
ao->output2buffer2_cbcr_phy = ad->pong.ch_paddr[1];
- ao->output2buffer3_y_phy = ad->free_buf.ch_paddr[0];
- ao->output2buffer3_cbcr_phy = ad->free_buf.ch_paddr[1];
+ spin_lock_irqsave(&vfe2x_ctrl->liveshot_enabled_lock,
+ flags);
+ if (vfe2x_ctrl->liveshot_enabled) { /* Live shot */
+ ao->output2buffer3_y_phy = ad->pong.ch_paddr[0];
+ ao->output2buffer3_cbcr_phy = ad->pong.ch_paddr[1];
+ } else {
+ ao->output2buffer3_y_phy = ad->free_buf.ch_paddr[0];
+ ao->output2buffer3_cbcr_phy = ad->free_buf.ch_paddr[1];
+ }
+ spin_unlock_irqrestore(&vfe2x_ctrl->liveshot_enabled_lock,
+ flags);
bptr = &ao->output2buffer4_y_phy;
for (cnt = 0; cnt < 5; cnt++) {
*bptr = ad->pong.ch_paddr[0];
@@ -1656,6 +1769,26 @@
vfe2x_ctrl->reconfig_vfe = 1;
return 0;
}
+ if (vfecmd.id == VFE_CMD_LIVESHOT) {
+ CDBG("live shot enabled\n");
+ spin_lock_irqsave(&vfe2x_ctrl->liveshot_enabled_lock,
+ flags);
+ vfe2x_ctrl->liveshot_enabled = 1;
+ spin_unlock_irqrestore(&vfe2x_ctrl->
+ liveshot_enabled_lock,
+ flags);
+ return 0;
+ }
+ if (vfecmd.id == VFE_CMD_STOP_LIVESHOT) {
+ CDBG("live shot disabled\n");
+ spin_lock_irqsave(&vfe2x_ctrl->liveshot_enabled_lock,
+ flags);
+ vfe2x_ctrl->liveshot_enabled = 0;
+ spin_unlock_irqrestore(
+ &vfe2x_ctrl->liveshot_enabled_lock,
+ flags);
+ return 0;
+ }
if (vfecmd.length > 256 - 4) {
cmd_data_alloc =
cmd_data = kmalloc(vfecmd.length + 4, GFP_ATOMIC);
@@ -2162,6 +2295,7 @@
spin_lock_init(&vfe2x_ctrl->sd_notify_lock);
spin_lock_init(&vfe2x_ctrl->table_lock);
spin_lock_init(&vfe2x_ctrl->vfe_msg_lock);
+ spin_lock_init(&vfe2x_ctrl->liveshot_enabled_lock);
init_waitqueue_head(&stopevent.wait);
INIT_LIST_HEAD(&vfe2x_ctrl->table_q);
INIT_LIST_HEAD(&vfe2x_ctrl->vfe_msg_q);
diff --git a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.h b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.h
index 39affc4..7693235 100644
--- a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.h
+++ b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.h
@@ -112,6 +112,9 @@
uint32_t stop_pending;
uint32_t update_pending;
+ spinlock_t liveshot_enabled_lock;
+ uint32_t liveshot_enabled;
+
/* v4l2 subdev */
struct v4l2_subdev subdev;
struct platform_device *pdev;
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 894860b..e8d9e04 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -1135,7 +1135,7 @@
goto free_res;
}
- rate = c_data->vc_format.clk_freq;
+ rate = c_data->vc_format.clk_freq / 100 * 102;
rate_rc = clk_round_rate(dev->vcap_clk, rate);
if (rate_rc <= 0) {
pr_err("%s: Failed core rnd_rate\n", __func__);
@@ -1251,7 +1251,7 @@
goto free_res;
}
- rate = c_data->vc_format.clk_freq;
+ rate = c_data->vc_format.clk_freq / 100 * 102;
rate_rc = clk_round_rate(dev->vcap_clk, rate);
if (rate_rc <= 0) {
pr_err("%s: Failed core rnd_rate\n", __func__);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 36f87df..23cb03d 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -5361,7 +5361,6 @@
struct resource *dmares = NULL;
struct resource *dma_crci_res = NULL;
int ret = 0;
- int i;
if (pdev->dev.of_node) {
plat = msmsdcc_populate_pdata(&pdev->dev);
@@ -5390,56 +5389,21 @@
pr_err("%s: Invalid resource\n", __func__);
return -ENXIO;
}
- if (pdev->dev.of_node) {
- /*
- * Device tree iomem resources are only accessible by index.
- * index = 0 -> SDCC register interface
- * index = 1 -> DML register interface
- * index = 2 -> BAM register interface
- * IRQ resources:
- * index = 0 -> SDCC IRQ
- * index = 1 -> BAM IRQ
- */
- core_memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- dml_memres = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- bam_memres = platform_get_resource(pdev, IORESOURCE_MEM, 2);
- core_irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- bam_irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
- } else {
- for (i = 0; i < pdev->num_resources; i++) {
- if (pdev->resource[i].flags & IORESOURCE_MEM) {
- if (!strncmp(pdev->resource[i].name,
- "sdcc_dml_addr",
- sizeof("sdcc_dml_addr")))
- dml_memres = &pdev->resource[i];
- else if (!strncmp(pdev->resource[i].name,
- "sdcc_bam_addr",
- sizeof("sdcc_bam_addr")))
- bam_memres = &pdev->resource[i];
- else
- core_memres = &pdev->resource[i];
- }
- if (pdev->resource[i].flags & IORESOURCE_IRQ) {
- if (!strncmp(pdev->resource[i].name,
- "sdcc_bam_irq",
- sizeof("sdcc_bam_irq")))
- bam_irqres = &pdev->resource[i];
- else
- core_irqres = &pdev->resource[i];
- }
- if (pdev->resource[i].flags & IORESOURCE_DMA) {
- if (!strncmp(pdev->resource[i].name,
- "sdcc_dma_chnl",
- sizeof("sdcc_dma_chnl")))
- dmares = &pdev->resource[i];
- else if (!strncmp(pdev->resource[i].name,
- "sdcc_dma_crci",
- sizeof("sdcc_dma_crci")))
- dma_crci_res = &pdev->resource[i];
- }
- }
- }
+ core_memres = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "core_mem");
+ bam_memres = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "bam_mem");
+ dml_memres = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "dml_mem");
+ core_irqres = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "core_irq");
+ bam_irqres = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "bam_irq");
+ dmares = platform_get_resource_byname(pdev,
+ IORESOURCE_DMA, "dma_chnl");
+ dma_crci_res = platform_get_resource_byname(pdev,
+ IORESOURCE_DMA, "dma_crci");
if (!core_irqres || !core_memres) {
pr_err("%s: Invalid sdcc core resource\n", __func__);
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index cbefe67..3c79917 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -900,8 +900,8 @@
{
struct virtnet_info *vi = netdev_priv(dev);
- ring->rx_max_pending = virtqueue_get_vring_size(vi->rvq);
- ring->tx_max_pending = virtqueue_get_vring_size(vi->svq);
+ ring->rx_max_pending = virtqueue_get_impl_size(vi->rvq);
+ ring->tx_max_pending = virtqueue_get_impl_size(vi->svq);
ring->rx_pending = ring->rx_max_pending;
ring->tx_pending = ring->tx_max_pending;
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 7695778..c0a4e0e 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -21,6 +21,7 @@
#include <linux/workqueue.h>
#include <linux/jiffies.h>
#include <linux/gpio.h>
+#include <linux/wakelock.h>
#include <mach/peripheral-loader.h>
#define DEVICE "wcnss_wlan"
@@ -48,6 +49,7 @@
void (*tm_notify)(struct device *, int);
struct wcnss_wlan_config wlan_config;
struct delayed_work wcnss_work;
+ struct wake_lock wcnss_wake_lock;
} *penv = NULL;
static ssize_t wcnss_serial_number_show(struct device *dev,
@@ -60,7 +62,7 @@
}
static ssize_t wcnss_serial_number_store(struct device *dev,
- struct device_attribute *attr, const char * buf, size_t count)
+ struct device_attribute *attr, const char *buf, size_t count)
{
unsigned int value;
@@ -88,7 +90,7 @@
}
static ssize_t wcnss_thermal_mitigation_store(struct device *dev,
- struct device_attribute *attr, const char * buf, size_t count)
+ struct device_attribute *attr, const char *buf, size_t count)
{
int value;
@@ -326,6 +328,20 @@
return 0;
}
+void wcnss_prevent_suspend()
+{
+ if (penv)
+ wake_lock(&penv->wcnss_wake_lock);
+}
+EXPORT_SYMBOL(wcnss_prevent_suspend);
+
+void wcnss_allow_suspend()
+{
+ if (penv)
+ wake_unlock(&penv->wcnss_wake_lock);
+}
+EXPORT_SYMBOL(wcnss_allow_suspend);
+
static int
wcnss_trigger_config(struct platform_device *pdev)
{
@@ -398,6 +414,8 @@
if (ret)
goto fail_sysfs;
+ wake_lock_init(&penv->wcnss_wake_lock, WAKE_LOCK_SUSPEND, "wcnss");
+
return 0;
fail_sysfs:
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index 54c486e..ac88636 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -72,6 +72,7 @@
#include "u_bam_data.c"
#include "f_mbim.c"
#include "f_qc_ecm.c"
+#include "f_qc_rndis.c"
#include "u_qc_ether.c"
#ifdef CONFIG_TARGET_CORE
#include "f_tcm.c"
@@ -965,6 +966,7 @@
struct rndis_function_config {
u8 ethaddr[ETH_ALEN];
u32 vendorID;
+ u8 max_pkt_per_xfer;
char manufacturer[256];
/* "Wireless" RNDIS; auto-detected by Windows */
bool wceis;
@@ -986,6 +988,22 @@
f->config = NULL;
}
+static int rndis_qc_function_init(struct android_usb_function *f,
+ struct usb_composite_dev *cdev)
+{
+ f->config = kzalloc(sizeof(struct rndis_function_config), GFP_KERNEL);
+ if (!f->config)
+ return -ENOMEM;
+
+ return rndis_qc_init();
+}
+
+static void rndis_qc_function_cleanup(struct android_usb_function *f)
+{
+ rndis_qc_cleanup();
+ kfree(f->config);
+}
+
static int
rndis_function_bind_config(struct android_usb_function *f,
struct usb_configuration *c)
@@ -1024,12 +1042,56 @@
rndis->manufacturer);
}
+static int rndis_qc_function_bind_config(struct android_usb_function *f,
+ struct usb_configuration *c)
+{
+ int ret;
+ struct rndis_function_config *rndis = f->config;
+
+ if (!rndis) {
+ pr_err("%s: rndis_pdata\n", __func__);
+ return -EINVAL;
+ }
+
+ pr_info("%s MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", __func__,
+ rndis->ethaddr[0], rndis->ethaddr[1], rndis->ethaddr[2],
+ rndis->ethaddr[3], rndis->ethaddr[4], rndis->ethaddr[5]);
+
+ ret = gether_qc_setup_name(c->cdev->gadget, rndis->ethaddr, "rndis");
+ if (ret) {
+ pr_err("%s: gether_setup failed\n", __func__);
+ return ret;
+ }
+
+ if (rndis->wceis) {
+ /* "Wireless" RNDIS; auto-detected by Windows */
+ rndis_qc_iad_descriptor.bFunctionClass =
+ USB_CLASS_WIRELESS_CONTROLLER;
+ rndis_qc_iad_descriptor.bFunctionSubClass = 0x01;
+ rndis_qc_iad_descriptor.bFunctionProtocol = 0x03;
+ rndis_qc_control_intf.bInterfaceClass =
+ USB_CLASS_WIRELESS_CONTROLLER;
+ rndis_qc_control_intf.bInterfaceSubClass = 0x01;
+ rndis_qc_control_intf.bInterfaceProtocol = 0x03;
+ }
+
+ return rndis_qc_bind_config_vendor(c, rndis->ethaddr, rndis->vendorID,
+ rndis->manufacturer,
+ rndis->max_pkt_per_xfer);
+}
+
static void rndis_function_unbind_config(struct android_usb_function *f,
struct usb_configuration *c)
{
gether_cleanup();
}
+static void rndis_qc_function_unbind_config(struct android_usb_function *f,
+ struct usb_configuration *c)
+{
+ gether_qc_cleanup();
+}
+
static ssize_t rndis_manufacturer_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -1136,11 +1198,38 @@
static DEVICE_ATTR(vendorID, S_IRUGO | S_IWUSR, rndis_vendorID_show,
rndis_vendorID_store);
+static ssize_t rndis_max_pkt_per_xfer_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *config = f->config;
+ return snprintf(buf, PAGE_SIZE, "%d\n", config->max_pkt_per_xfer);
+}
+
+static ssize_t rndis_max_pkt_per_xfer_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct android_usb_function *f = dev_get_drvdata(dev);
+ struct rndis_function_config *config = f->config;
+ int value;
+
+ if (sscanf(buf, "%d", &value) == 1) {
+ config->max_pkt_per_xfer = value;
+ return size;
+ }
+ return -EINVAL;
+}
+
+static DEVICE_ATTR(max_pkt_per_xfer, S_IRUGO | S_IWUSR,
+ rndis_max_pkt_per_xfer_show,
+ rndis_max_pkt_per_xfer_store);
+
static struct device_attribute *rndis_function_attributes[] = {
&dev_attr_manufacturer,
&dev_attr_wceis,
&dev_attr_ethaddr,
&dev_attr_vendorID,
+ &dev_attr_max_pkt_per_xfer,
NULL
};
@@ -1153,6 +1242,14 @@
.attributes = rndis_function_attributes,
};
+static struct android_usb_function rndis_qc_function = {
+ .name = "rndis_qc",
+ .init = rndis_qc_function_init,
+ .cleanup = rndis_qc_function_cleanup,
+ .bind_config = rndis_qc_function_bind_config,
+ .unbind_config = rndis_qc_function_unbind_config,
+ .attributes = rndis_function_attributes,
+};
struct mass_storage_function_config {
struct fsg_config fsg;
@@ -1356,6 +1453,7 @@
&mtp_function,
&ptp_function,
&rndis_function,
+ &rndis_qc_function,
&mass_storage_function,
&accessory_function,
&uasp_function,
diff --git a/drivers/usb/gadget/f_qc_rndis.c b/drivers/usb/gadget/f_qc_rndis.c
new file mode 100644
index 0000000..dcf307d
--- /dev/null
+++ b/drivers/usb/gadget/f_qc_rndis.c
@@ -0,0 +1,1151 @@
+/*
+ * f_qc_rndis.c -- RNDIS link function driver
+ *
+ * Copyright (C) 2003-2005,2008 David Brownell
+ * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
+ * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2009 Samsung Electronics
+ * Author: Michal Nazarewicz (mina86@mina86.com)
+ * 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
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* #define VERBOSE_DEBUG */
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/etherdevice.h>
+
+#include <linux/atomic.h>
+
+#include "u_ether.h"
+#include "u_qc_ether.h"
+#include "rndis.h"
+
+
+/*
+ * This function is an RNDIS Ethernet port -- a Microsoft protocol that's
+ * been promoted instead of the standard CDC Ethernet. The published RNDIS
+ * spec is ambiguous, incomplete, and needlessly complex. Variants such as
+ * ActiveSync have even worse status in terms of specification.
+ *
+ * In short: it's a protocol controlled by (and for) Microsoft, not for an
+ * Open ecosystem or markets. Linux supports it *only* because Microsoft
+ * doesn't support the CDC Ethernet standard.
+ *
+ * The RNDIS data transfer model is complex, with multiple Ethernet packets
+ * per USB message, and out of band data. The control model is built around
+ * what's essentially an "RNDIS RPC" protocol. It's all wrapped in a CDC ACM
+ * (modem, not Ethernet) veneer, with those ACM descriptors being entirely
+ * useless (they're ignored). RNDIS expects to be the only function in its
+ * configuration, so it's no real help if you need composite devices; and
+ * it expects to be the first configuration too.
+ *
+ * There is a single technical advantage of RNDIS over CDC Ethernet, if you
+ * discount the fluff that its RPC can be made to deliver: it doesn't need
+ * a NOP altsetting for the data interface. That lets it work on some of the
+ * "so smart it's stupid" hardware which takes over configuration changes
+ * from the software, and adds restrictions like "no altsettings".
+ *
+ * Unfortunately MSFT's RNDIS drivers are buggy. They hang or oops, and
+ * have all sorts of contrary-to-specification oddities that can prevent
+ * them from working sanely. Since bugfixes (or accurate specs, letting
+ * Linux work around those bugs) are unlikely to ever come from MSFT, you
+ * may want to avoid using RNDIS on purely operational grounds.
+ *
+ * Omissions from the RNDIS 1.0 specification include:
+ *
+ * - Power management ... references data that's scattered around lots
+ * of other documentation, which is incorrect/incomplete there too.
+ *
+ * - There are various undocumented protocol requirements, like the need
+ * to send garbage in some control-OUT messages.
+ *
+ * - MS-Windows drivers sometimes emit undocumented requests.
+ *
+ * This function is based on RNDIS link function driver and
+ * contains MSM specific implementation.
+ */
+
+struct f_rndis_qc {
+ struct qc_gether port;
+ u8 ctrl_id, data_id;
+ u8 ethaddr[ETH_ALEN];
+ u32 vendorID;
+ u8 max_pkt_per_xfer;
+ const char *manufacturer;
+ int config;
+ atomic_t ioctl_excl;
+ atomic_t open_excl;
+
+ struct usb_ep *notify;
+ struct usb_request *notify_req;
+ atomic_t notify_count;
+};
+
+static inline struct f_rndis_qc *func_to_rndis_qc(struct usb_function *f)
+{
+ return container_of(f, struct f_rndis_qc, port.func);
+}
+
+/* peak (theoretical) bulk transfer rate in bits-per-second */
+static unsigned int rndis_qc_bitrate(struct usb_gadget *g)
+{
+ if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
+ return 13 * 1024 * 8 * 1000 * 8;
+ else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+ return 13 * 512 * 8 * 1000 * 8;
+ else
+ return 19 * 64 * 1 * 1000 * 8;
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define RNDIS_QC_LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */
+#define RNDIS_QC_STATUS_BYTECOUNT 8 /* 8 bytes data */
+
+/* currently only one rndis instance is supported */
+#define RNDIS_QC_NO_PORTS 1
+
+/* default max packets per tarnsfer value */
+#define DEFAULT_MAX_PKT_PER_XFER 15
+
+
+#define RNDIS_QC_IOCTL_MAGIC 'i'
+#define RNDIS_QC_GET_MAX_PKT_PER_XFER _IOR(RNDIS_QC_IOCTL_MAGIC, 1, u8)
+
+
+/* interface descriptor: */
+
+static struct usb_interface_descriptor rndis_qc_control_intf = {
+ .bLength = sizeof rndis_qc_control_intf,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ /* .bInterfaceNumber = DYNAMIC */
+ /* status endpoint is optional; this could be patched later */
+ .bNumEndpoints = 1,
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
+ .bInterfaceProtocol = USB_CDC_ACM_PROTO_VENDOR,
+ /* .iInterface = DYNAMIC */
+};
+
+static struct usb_cdc_header_desc rndis_qc_header_desc = {
+ .bLength = sizeof rndis_qc_header_desc,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_HEADER_TYPE,
+
+ .bcdCDC = cpu_to_le16(0x0110),
+};
+
+static struct usb_cdc_call_mgmt_descriptor rndis_qc_call_mgmt_descriptor = {
+ .bLength = sizeof rndis_qc_call_mgmt_descriptor,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
+
+ .bmCapabilities = 0x00,
+ .bDataInterface = 0x01,
+};
+
+static struct usb_cdc_acm_descriptor rndis_qc_acm_descriptor = {
+ .bLength = sizeof rndis_qc_acm_descriptor,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_ACM_TYPE,
+
+ .bmCapabilities = 0x00,
+};
+
+static struct usb_cdc_union_desc rndis_qc_union_desc = {
+ .bLength = sizeof(rndis_qc_union_desc),
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_UNION_TYPE,
+ /* .bMasterInterface0 = DYNAMIC */
+ /* .bSlaveInterface0 = DYNAMIC */
+};
+
+/* the data interface has two bulk endpoints */
+
+static struct usb_interface_descriptor rndis_qc_data_intf = {
+ .bLength = sizeof rndis_qc_data_intf,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ /* .bInterfaceNumber = DYNAMIC */
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_CDC_DATA,
+ .bInterfaceSubClass = 0,
+ .bInterfaceProtocol = 0,
+ /* .iInterface = DYNAMIC */
+};
+
+
+static struct usb_interface_assoc_descriptor
+rndis_qc_iad_descriptor = {
+ .bLength = sizeof rndis_qc_iad_descriptor,
+ .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
+ .bFirstInterface = 0, /* XXX, hardcoded */
+ .bInterfaceCount = 2, /* control + data */
+ .bFunctionClass = USB_CLASS_COMM,
+ .bFunctionSubClass = USB_CDC_SUBCLASS_ETHERNET,
+ .bFunctionProtocol = USB_CDC_PROTO_NONE,
+ /* .iFunction = DYNAMIC */
+};
+
+/* full speed support: */
+
+static struct usb_endpoint_descriptor rndis_qc_fs_notify_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = cpu_to_le16(RNDIS_QC_STATUS_BYTECOUNT),
+ .bInterval = 1 << RNDIS_QC_LOG2_STATUS_INTERVAL_MSEC,
+};
+
+static struct usb_endpoint_descriptor rndis_qc_fs_in_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor rndis_qc_fs_out_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_descriptor_header *eth_qc_fs_function[] = {
+ (struct usb_descriptor_header *) &rndis_qc_iad_descriptor,
+ /* control interface matches ACM, not Ethernet */
+ (struct usb_descriptor_header *) &rndis_qc_control_intf,
+ (struct usb_descriptor_header *) &rndis_qc_header_desc,
+ (struct usb_descriptor_header *) &rndis_qc_call_mgmt_descriptor,
+ (struct usb_descriptor_header *) &rndis_qc_acm_descriptor,
+ (struct usb_descriptor_header *) &rndis_qc_union_desc,
+ (struct usb_descriptor_header *) &rndis_qc_fs_notify_desc,
+ /* data interface has no altsetting */
+ (struct usb_descriptor_header *) &rndis_qc_data_intf,
+ (struct usb_descriptor_header *) &rndis_qc_fs_in_desc,
+ (struct usb_descriptor_header *) &rndis_qc_fs_out_desc,
+ NULL,
+};
+
+/* high speed support: */
+
+static struct usb_endpoint_descriptor rndis_qc_hs_notify_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = cpu_to_le16(RNDIS_QC_STATUS_BYTECOUNT),
+ .bInterval = RNDIS_QC_LOG2_STATUS_INTERVAL_MSEC + 4,
+};
+static struct usb_endpoint_descriptor rndis_qc_hs_in_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor rndis_qc_hs_out_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *eth_qc_hs_function[] = {
+ (struct usb_descriptor_header *) &rndis_qc_iad_descriptor,
+ /* control interface matches ACM, not Ethernet */
+ (struct usb_descriptor_header *) &rndis_qc_control_intf,
+ (struct usb_descriptor_header *) &rndis_qc_header_desc,
+ (struct usb_descriptor_header *) &rndis_qc_call_mgmt_descriptor,
+ (struct usb_descriptor_header *) &rndis_qc_acm_descriptor,
+ (struct usb_descriptor_header *) &rndis_qc_union_desc,
+ (struct usb_descriptor_header *) &rndis_qc_hs_notify_desc,
+ /* data interface has no altsetting */
+ (struct usb_descriptor_header *) &rndis_qc_data_intf,
+ (struct usb_descriptor_header *) &rndis_qc_hs_in_desc,
+ (struct usb_descriptor_header *) &rndis_qc_hs_out_desc,
+ NULL,
+};
+
+/* super speed support: */
+
+static struct usb_endpoint_descriptor rndis_qc_ss_notify_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_INT,
+ .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT),
+ .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4,
+};
+
+static struct usb_ss_ep_comp_descriptor rndis_qc_ss_intr_comp_desc = {
+ .bLength = sizeof ss_intr_comp_desc,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ /* the following 3 values can be tweaked if necessary */
+ /* .bMaxBurst = 0, */
+ /* .bmAttributes = 0, */
+ .wBytesPerInterval = cpu_to_le16(STATUS_BYTECOUNT),
+};
+
+static struct usb_endpoint_descriptor rndis_qc_ss_in_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(1024),
+};
+
+static struct usb_endpoint_descriptor rndis_qc_ss_out_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = cpu_to_le16(1024),
+};
+
+static struct usb_ss_ep_comp_descriptor rndis_qc_ss_bulk_comp_desc = {
+ .bLength = sizeof ss_bulk_comp_desc,
+ .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
+
+ /* the following 2 values can be tweaked if necessary */
+ /* .bMaxBurst = 0, */
+ /* .bmAttributes = 0, */
+};
+
+static struct usb_descriptor_header *eth_qc_ss_function[] = {
+ (struct usb_descriptor_header *) &rndis_iad_descriptor,
+
+ /* control interface matches ACM, not Ethernet */
+ (struct usb_descriptor_header *) &rndis_qc_control_intf,
+ (struct usb_descriptor_header *) &rndis_qc_header_desc,
+ (struct usb_descriptor_header *) &rndis_qc_call_mgmt_descriptor,
+ (struct usb_descriptor_header *) &rndis_qc_acm_descriptor,
+ (struct usb_descriptor_header *) &rndis_qc_union_desc,
+ (struct usb_descriptor_header *) &rndis_qc_ss_notify_desc,
+ (struct usb_descriptor_header *) &rndis_qc_ss_intr_comp_desc,
+
+ /* data interface has no altsetting */
+ (struct usb_descriptor_header *) &rndis_qc_data_intf,
+ (struct usb_descriptor_header *) &rndis_qc_ss_in_desc,
+ (struct usb_descriptor_header *) &rndis_qc_ss_bulk_comp_desc,
+ (struct usb_descriptor_header *) &rndis_qc_ss_out_desc,
+ (struct usb_descriptor_header *) &rndis_qc_ss_bulk_comp_desc,
+ NULL,
+};
+
+/* string descriptors: */
+
+static struct usb_string rndis_qc_string_defs[] = {
+ [0].s = "RNDIS Communications Control",
+ [1].s = "RNDIS Ethernet Data",
+ [2].s = "RNDIS",
+ { } /* end of list */
+};
+
+static struct usb_gadget_strings rndis_qc_string_table = {
+ .language = 0x0409, /* en-us */
+ .strings = rndis_qc_string_defs,
+};
+
+static struct usb_gadget_strings *rndis_qc_strings[] = {
+ &rndis_qc_string_table,
+ NULL,
+};
+
+struct f_rndis_qc *_rndis_qc;
+
+static inline int rndis_qc_lock(atomic_t *excl)
+{
+ if (atomic_inc_return(excl) == 1) {
+ return 0;
+ } else {
+ atomic_dec(excl);
+ return -EBUSY;
+ }
+}
+
+static inline void rndis_qc_unlock(atomic_t *excl)
+{
+ atomic_dec(excl);
+}
+
+/* MSM bam support */
+static struct data_port rndis_qc_bam_port;
+
+static int rndis_qc_bam_setup(void)
+{
+ int ret;
+
+ ret = bam_data_setup(RNDIS_QC_NO_PORTS);
+ if (ret) {
+ pr_err("bam_data_setup failed err: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rndis_qc_bam_connect(struct f_rndis_qc *dev)
+{
+ int ret;
+
+ rndis_qc_bam_port.func = dev->port.func;
+ rndis_qc_bam_port.in = dev->port.in_ep;
+ rndis_qc_bam_port.out = dev->port.out_ep;
+
+ /* currently we use the first connection */
+ ret = bam_data_connect(&rndis_qc_bam_port, 0, 0);
+ if (ret) {
+ pr_err("bam_data_connect failed: err:%d\n",
+ ret);
+ return ret;
+ } else {
+ pr_info("rndis bam connected\n");
+ }
+
+ return 0;
+}
+
+static int rndis_qc_bam_disconnect(struct f_rndis_qc *dev)
+{
+ pr_info("dev:%p. %s Do nothing.\n",
+ dev, __func__);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct sk_buff *rndis_qc_add_header(struct qc_gether *port,
+ struct sk_buff *skb)
+{
+ struct sk_buff *skb2;
+
+ skb2 = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type));
+ if (skb2)
+ rndis_add_hdr(skb2);
+
+ dev_kfree_skb_any(skb);
+ return skb2;
+}
+
+int rndis_qc_rm_hdr(struct qc_gether *port,
+ struct sk_buff *skb,
+ struct sk_buff_head *list)
+{
+ /* tmp points to a struct rndis_packet_msg_type */
+ __le32 *tmp = (void *)skb->data;
+
+ /* MessageType, MessageLength */
+ if (cpu_to_le32(REMOTE_NDIS_PACKET_MSG)
+ != get_unaligned(tmp++)) {
+ dev_kfree_skb_any(skb);
+ return -EINVAL;
+ }
+ tmp++;
+
+ /* DataOffset, DataLength */
+ if (!skb_pull(skb, get_unaligned_le32(tmp++) + 8)) {
+ dev_kfree_skb_any(skb);
+ return -EOVERFLOW;
+ }
+ skb_trim(skb, get_unaligned_le32(tmp++));
+
+ skb_queue_tail(list, skb);
+ return 0;
+}
+
+
+static void rndis_qc_response_available(void *_rndis)
+{
+ struct f_rndis_qc *rndis = _rndis;
+ struct usb_request *req = rndis->notify_req;
+ __le32 *data = req->buf;
+ int status;
+
+ if (atomic_inc_return(&rndis->notify_count) != 1)
+ return;
+
+ /* Send RNDIS RESPONSE_AVAILABLE notification; a
+ * USB_CDC_NOTIFY_RESPONSE_AVAILABLE "should" work too
+ *
+ * This is the only notification defined by RNDIS.
+ */
+ data[0] = cpu_to_le32(1);
+ data[1] = cpu_to_le32(0);
+
+ status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC);
+ if (status) {
+ atomic_dec(&rndis->notify_count);
+ pr_info("notify/0 --> %d\n", status);
+ }
+}
+
+static void rndis_qc_response_complete(struct usb_ep *ep,
+ struct usb_request *req)
+{
+ struct f_rndis_qc *rndis = req->context;
+ int status = req->status;
+
+ /* after TX:
+ * - USB_CDC_GET_ENCAPSULATED_RESPONSE (ep0/control)
+ * - RNDIS_RESPONSE_AVAILABLE (status/irq)
+ */
+ switch (status) {
+ case -ECONNRESET:
+ case -ESHUTDOWN:
+ /* connection gone */
+ atomic_set(&rndis->notify_count, 0);
+ break;
+ default:
+ pr_info("RNDIS %s response error %d, %d/%d\n",
+ ep->name, status,
+ req->actual, req->length);
+ /* FALLTHROUGH */
+ case 0:
+ if (ep != rndis->notify)
+ break;
+
+ /* handle multiple pending RNDIS_RESPONSE_AVAILABLE
+ * notifications by resending until we're done
+ */
+ if (atomic_dec_and_test(&rndis->notify_count))
+ break;
+ status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC);
+ if (status) {
+ atomic_dec(&rndis->notify_count);
+ DBG(cdev, "notify/1 --> %d\n", status);
+ }
+ break;
+ }
+}
+
+static void rndis_qc_command_complete(struct usb_ep *ep,
+ struct usb_request *req)
+{
+ struct f_rndis_qc *rndis = req->context;
+ int status;
+
+ /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
+ status = rndis_msg_parser(rndis->config, (u8 *) req->buf);
+ if (status < 0)
+ pr_err("RNDIS command error %d, %d/%d\n",
+ status, req->actual, req->length);
+}
+
+static int
+rndis_qc_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+ struct f_rndis_qc *rndis = func_to_rndis_qc(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+ struct usb_request *req = cdev->req;
+ int value = -EOPNOTSUPP;
+ u16 w_index = le16_to_cpu(ctrl->wIndex);
+ u16 w_value = le16_to_cpu(ctrl->wValue);
+ u16 w_length = le16_to_cpu(ctrl->wLength);
+
+ /* composite driver infrastructure handles everything except
+ * CDC class messages; interface activation uses set_alt().
+ */
+ switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
+
+ /* RNDIS uses the CDC command encapsulation mechanism to implement
+ * an RPC scheme, with much getting/setting of attributes by OID.
+ */
+ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_SEND_ENCAPSULATED_COMMAND:
+ if (w_value || w_index != rndis->ctrl_id)
+ goto invalid;
+ /* read the request; process it later */
+ value = w_length;
+ req->complete = rndis_qc_command_complete;
+ req->context = rndis;
+ /* later, rndis_response_available() sends a notification */
+ break;
+
+ case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_GET_ENCAPSULATED_RESPONSE:
+ if (w_value || w_index != rndis->ctrl_id)
+ goto invalid;
+ else {
+ u8 *buf;
+ u32 n;
+
+ /* return the result */
+ buf = rndis_get_next_response(rndis->config, &n);
+ if (buf) {
+ memcpy(req->buf, buf, n);
+ req->complete = rndis_qc_response_complete;
+ rndis_free_response(rndis->config, buf);
+ value = n;
+ }
+ /* else stalls ... spec says to avoid that */
+ }
+ break;
+
+ default:
+invalid:
+ VDBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ }
+
+ /* respond with data transfer or status phase? */
+ if (value >= 0) {
+ DBG(cdev, "rndis req%02x.%02x v%04x i%04x l%d\n",
+ ctrl->bRequestType, ctrl->bRequest,
+ w_value, w_index, w_length);
+ req->zero = (value < w_length);
+ req->length = value;
+ value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
+ if (value < 0)
+ pr_err("rndis response on err %d\n", value);
+ }
+
+ /* device either stalls (value < 0) or reports success */
+ return value;
+}
+
+
+static int rndis_qc_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+ struct f_rndis_qc *rndis = func_to_rndis_qc(f);
+ struct usb_composite_dev *cdev = f->config->cdev;
+
+ /* we know alt == 0 */
+
+ if (intf == rndis->ctrl_id) {
+ if (rndis->notify->driver_data) {
+ VDBG(cdev, "reset rndis control %d\n", intf);
+ usb_ep_disable(rndis->notify);
+ }
+ if (!rndis->notify->desc) {
+ VDBG(cdev, "init rndis ctrl %d\n", intf);
+ if (config_ep_by_speed(cdev->gadget, f, rndis->notify))
+ goto fail;
+ }
+ usb_ep_enable(rndis->notify);
+ rndis->notify->driver_data = rndis;
+
+ } else if (intf == rndis->data_id) {
+ struct net_device *net;
+
+ if (rndis->port.in_ep->driver_data) {
+ DBG(cdev, "reset rndis\n");
+ gether_qc_disconnect(&rndis->port);
+ rndis_qc_bam_disconnect(rndis);
+ }
+
+ if (!rndis->port.in_ep->desc || !rndis->port.out_ep->desc) {
+ DBG(cdev, "init rndis\n");
+ if (config_ep_by_speed(cdev->gadget, f,
+ rndis->port.in_ep) ||
+ config_ep_by_speed(cdev->gadget, f,
+ rndis->port.out_ep)) {
+ rndis->port.in_ep->desc = NULL;
+ rndis->port.out_ep->desc = NULL;
+ goto fail;
+ }
+ }
+
+ /* Avoid ZLPs; they can be troublesome. */
+ rndis->port.is_zlp_ok = false;
+
+ /* RNDIS should be in the "RNDIS uninitialized" state,
+ * either never activated or after rndis_uninit().
+ *
+ * We don't want data to flow here until a nonzero packet
+ * filter is set, at which point it enters "RNDIS data
+ * initialized" state ... but we do want the endpoints
+ * to be activated. It's a strange little state.
+ *
+ * REVISIT the RNDIS gadget code has done this wrong for a
+ * very long time. We need another call to the link layer
+ * code -- gether_updown(...bool) maybe -- to do it right.
+ */
+ rndis->port.cdc_filter = 0;
+
+ DBG(cdev, "RNDIS RX/TX early activation ...\n");
+ net = gether_qc_connect(&rndis->port);
+ if (IS_ERR(net))
+ return PTR_ERR(net);
+
+ if (rndis_qc_bam_connect(rndis))
+ goto fail;
+
+ rndis_set_param_dev(rndis->config, net,
+ &rndis->port.cdc_filter);
+ } else
+ goto fail;
+
+ return 0;
+fail:
+ return -EINVAL;
+}
+
+static void rndis_qc_disable(struct usb_function *f)
+{
+ struct f_rndis_qc *rndis = func_to_rndis_qc(f);
+
+ if (!rndis->notify->driver_data)
+ return;
+
+ pr_info("rndis deactivated\n");
+
+ rndis_uninit(rndis->config);
+ gether_qc_disconnect(&rndis->port);
+ rndis_qc_bam_disconnect(rndis);
+
+ usb_ep_disable(rndis->notify);
+ rndis->notify->driver_data = NULL;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * This isn't quite the same mechanism as CDC Ethernet, since the
+ * notification scheme passes less data, but the same set of link
+ * states must be tested. A key difference is that altsettings are
+ * not used to tell whether the link should send packets or not.
+ */
+
+static void rndis_qc_open(struct qc_gether *geth)
+{
+ struct f_rndis_qc *rndis = func_to_rndis_qc(&geth->func);
+ struct usb_composite_dev *cdev = geth->func.config->cdev;
+
+ DBG(cdev, "%s\n", __func__);
+
+ rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3,
+ rndis_qc_bitrate(cdev->gadget) / 100);
+ rndis_signal_connect(rndis->config);
+}
+
+static void rndis_qc_close(struct qc_gether *geth)
+{
+ struct f_rndis_qc *rndis = func_to_rndis_qc(&geth->func);
+
+ DBG(geth->func.config->cdev, "%s\n", __func__);
+
+ rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3, 0);
+ rndis_signal_disconnect(rndis->config);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* ethernet function driver setup/binding */
+
+static int
+rndis_qc_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = c->cdev;
+ struct f_rndis_qc *rndis = func_to_rndis_qc(f);
+ int status;
+ struct usb_ep *ep;
+
+ /* allocate instance-specific interface IDs */
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ rndis->ctrl_id = status;
+ rndis_qc_iad_descriptor.bFirstInterface = status;
+
+ rndis_qc_control_intf.bInterfaceNumber = status;
+ rndis_qc_union_desc.bMasterInterface0 = status;
+
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto fail;
+ rndis->data_id = status;
+
+ rndis_qc_data_intf.bInterfaceNumber = status;
+ rndis_qc_union_desc.bSlaveInterface0 = status;
+
+ status = -ENODEV;
+
+ /* allocate instance-specific endpoints */
+ ep = usb_ep_autoconfig(cdev->gadget, &rndis_qc_fs_in_desc);
+ if (!ep)
+ goto fail;
+ rndis->port.in_ep = ep;
+ ep->driver_data = cdev; /* claim */
+
+ ep = usb_ep_autoconfig(cdev->gadget, &rndis_qc_fs_out_desc);
+ if (!ep)
+ goto fail;
+ rndis->port.out_ep = ep;
+ ep->driver_data = cdev; /* claim */
+
+ /* NOTE: a status/notification endpoint is, strictly speaking,
+ * optional. We don't treat it that way though! It's simpler,
+ * and some newer profiles don't treat it as optional.
+ */
+ ep = usb_ep_autoconfig(cdev->gadget, &rndis_qc_fs_notify_desc);
+ if (!ep)
+ goto fail;
+ rndis->notify = ep;
+ ep->driver_data = cdev; /* claim */
+
+ status = -ENOMEM;
+
+ /* allocate notification request and buffer */
+ rndis->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
+ if (!rndis->notify_req)
+ goto fail;
+ rndis->notify_req->buf = kmalloc(RNDIS_QC_STATUS_BYTECOUNT, GFP_KERNEL);
+ if (!rndis->notify_req->buf)
+ goto fail;
+ rndis->notify_req->length = RNDIS_QC_STATUS_BYTECOUNT;
+ rndis->notify_req->context = rndis;
+ rndis->notify_req->complete = rndis_qc_response_complete;
+
+ /* copy descriptors, and track endpoint copies */
+ f->descriptors = usb_copy_descriptors(eth_qc_fs_function);
+ if (!f->descriptors)
+ goto fail;
+
+ /* support all relevant hardware speeds... we expect that when
+ * hardware is dual speed, all bulk-capable endpoints work at
+ * both speeds
+ */
+ if (gadget_is_dualspeed(c->cdev->gadget)) {
+ rndis_qc_hs_in_desc.bEndpointAddress =
+ rndis_qc_fs_in_desc.bEndpointAddress;
+ rndis_qc_hs_out_desc.bEndpointAddress =
+ rndis_qc_fs_out_desc.bEndpointAddress;
+ rndis_qc_hs_notify_desc.bEndpointAddress =
+ rndis_qc_fs_notify_desc.bEndpointAddress;
+
+ /* copy descriptors, and track endpoint copies */
+ f->hs_descriptors = usb_copy_descriptors(eth_qc_hs_function);
+
+ if (!f->hs_descriptors)
+ goto fail;
+ }
+
+ if (gadget_is_superspeed(c->cdev->gadget)) {
+ rndis_qc_ss_in_desc.bEndpointAddress =
+ rndis_qc_fs_in_desc.bEndpointAddress;
+ rndis_qc_ss_out_desc.bEndpointAddress =
+ rndis_qc_fs_out_desc.bEndpointAddress;
+ rndis_qc_ss_notify_desc.bEndpointAddress =
+ rndis_qc_fs_notify_desc.bEndpointAddress;
+
+ /* copy descriptors, and track endpoint copies */
+ f->ss_descriptors = usb_copy_descriptors(eth_qc_ss_function);
+ if (!f->ss_descriptors)
+ goto fail;
+ }
+
+ rndis->port.open = rndis_qc_open;
+ rndis->port.close = rndis_qc_close;
+
+ status = rndis_register(rndis_qc_response_available, rndis);
+ if (status < 0)
+ goto fail;
+ rndis->config = status;
+
+ rndis_set_param_medium(rndis->config, NDIS_MEDIUM_802_3, 0);
+ rndis_set_host_mac(rndis->config, rndis->ethaddr);
+
+ if (rndis_set_param_vendor(rndis->config, rndis->vendorID,
+ rndis->manufacturer))
+ goto fail;
+
+ rndis_set_max_pkt_xfer(rndis->config, rndis->max_pkt_per_xfer);
+
+ /* NOTE: all that is done without knowing or caring about
+ * the network link ... which is unavailable to this code
+ * until we're activated via set_alt().
+ */
+
+ DBG(cdev, "RNDIS: %s speed IN/%s OUT/%s NOTIFY/%s\n",
+ gadget_is_superspeed(c->cdev->gadget) ? "super" :
+ gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
+ rndis->port.in_ep->name, rndis->port.out_ep->name,
+ rndis->notify->name);
+ return 0;
+
+fail:
+ if (gadget_is_superspeed(c->cdev->gadget) && f->ss_descriptors)
+ usb_free_descriptors(f->ss_descriptors);
+ if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors)
+ usb_free_descriptors(f->hs_descriptors);
+ if (f->descriptors)
+ usb_free_descriptors(f->descriptors);
+
+ if (rndis->notify_req) {
+ kfree(rndis->notify_req->buf);
+ usb_ep_free_request(rndis->notify, rndis->notify_req);
+ }
+
+ /* we might as well release our claims on endpoints */
+ if (rndis->notify)
+ rndis->notify->driver_data = NULL;
+ if (rndis->port.out_ep->desc)
+ rndis->port.out_ep->driver_data = NULL;
+ if (rndis->port.in_ep->desc)
+ rndis->port.in_ep->driver_data = NULL;
+
+ pr_err("%s: can't bind, err %d\n", f->name, status);
+
+ return status;
+}
+
+static void
+rndis_qc_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct f_rndis_qc *rndis = func_to_rndis_qc(f);
+
+ rndis_deregister(rndis->config);
+ rndis_exit();
+
+ if (gadget_is_dualspeed(c->cdev->gadget))
+ usb_free_descriptors(f->hs_descriptors);
+ usb_free_descriptors(f->descriptors);
+
+ kfree(rndis->notify_req->buf);
+ usb_ep_free_request(rndis->notify, rndis->notify_req);
+
+ kfree(rndis);
+}
+
+/* Some controllers can't support RNDIS ... */
+static inline bool can_support_rndis_qc(struct usb_configuration *c)
+{
+ /* everything else is *presumably* fine */
+ return true;
+}
+
+/**
+ * rndis_qc_bind_config - add RNDIS network link to a configuration
+ * @c: the configuration to support the network link
+ * @ethaddr: a buffer in which the ethernet address of the host side
+ * side of the link was recorded
+ * Context: single threaded during gadget setup
+ *
+ * Returns zero on success, else negative errno.
+ *
+ * Caller must have called @gether_setup(). Caller is also responsible
+ * for calling @gether_cleanup() before module unload.
+ */
+int
+rndis_qc_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
+{
+ return rndis_qc_bind_config_vendor(c, ethaddr, 0, NULL, 1);
+}
+
+int
+rndis_qc_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
+ u32 vendorID, const char *manufacturer,
+ u8 max_pkt_per_xfer)
+{
+ struct f_rndis_qc *rndis;
+ int status;
+
+ if (!can_support_rndis_qc(c) || !ethaddr)
+ return -EINVAL;
+
+ /* setup RNDIS itself */
+ status = rndis_init();
+ if (status < 0)
+ return status;
+
+ status = rndis_qc_bam_setup();
+ if (status) {
+ pr_err("bam setup failed");
+ return status;
+ }
+
+ /* maybe allocate device-global string IDs */
+ if (rndis_qc_string_defs[0].id == 0) {
+
+ /* control interface label */
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ rndis_qc_string_defs[0].id = status;
+ rndis_qc_control_intf.iInterface = status;
+
+ /* data interface label */
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ rndis_qc_string_defs[1].id = status;
+ rndis_qc_data_intf.iInterface = status;
+
+ /* IAD iFunction label */
+ status = usb_string_id(c->cdev);
+ if (status < 0)
+ return status;
+ rndis_qc_string_defs[2].id = status;
+ rndis_qc_iad_descriptor.iFunction = status;
+ }
+
+ /* allocate and initialize one new instance */
+ status = -ENOMEM;
+ rndis = kzalloc(sizeof *rndis, GFP_KERNEL);
+ if (!rndis)
+ goto fail;
+
+ memcpy(rndis->ethaddr, ethaddr, ETH_ALEN);
+ rndis->vendorID = vendorID;
+ rndis->manufacturer = manufacturer;
+
+ /* if max_pkt_per_xfer was not configured set to default value */
+ rndis->max_pkt_per_xfer =
+ max_pkt_per_xfer ? max_pkt_per_xfer : DEFAULT_MAX_PKT_PER_XFER;
+
+ /* RNDIS activates when the host changes this filter */
+ rndis->port.cdc_filter = 0;
+
+ /* RNDIS has special (and complex) framing */
+ rndis->port.header_len = sizeof(struct rndis_packet_msg_type);
+ rndis->port.wrap = rndis_qc_add_header;
+ rndis->port.unwrap = rndis_qc_rm_hdr;
+
+ rndis->port.func.name = "rndis";
+ rndis->port.func.strings = rndis_qc_strings;
+ /* descriptors are per-instance copies */
+ rndis->port.func.bind = rndis_qc_bind;
+ rndis->port.func.unbind = rndis_qc_unbind;
+ rndis->port.func.set_alt = rndis_qc_set_alt;
+ rndis->port.func.setup = rndis_qc_setup;
+ rndis->port.func.disable = rndis_qc_disable;
+
+ _rndis_qc = rndis;
+
+ status = usb_add_function(c, &rndis->port.func);
+ if (status) {
+ kfree(rndis);
+fail:
+ rndis_exit();
+ }
+ return status;
+}
+
+static int rndis_qc_open_dev(struct inode *ip, struct file *fp)
+{
+ pr_info("Open rndis QC driver\n");
+
+ if (!_rndis_qc) {
+ pr_err("rndis_qc_dev not created yet\n");
+ return -ENODEV;
+ }
+
+ if (rndis_qc_lock(&_rndis_qc->open_excl)) {
+ pr_err("Already opened\n");
+ return -EBUSY;
+ }
+
+ fp->private_data = _rndis_qc;
+ pr_info("rndis QC file opened\n");
+
+ return 0;
+}
+
+static int rndis_qc_release_dev(struct inode *ip, struct file *fp)
+{
+ struct f_rndis_qc *rndis = fp->private_data;
+
+ pr_info("Close rndis QC file");
+ rndis_qc_unlock(&rndis->open_excl);
+
+ return 0;
+}
+
+static long rndis_qc_ioctl(struct file *fp, unsigned cmd, unsigned long arg)
+{
+ struct f_rndis_qc *rndis = fp->private_data;
+ int ret = 0;
+
+ pr_info("Received command %d", cmd);
+
+ if (rndis_qc_lock(&rndis->ioctl_excl))
+ return -EBUSY;
+
+ switch (cmd) {
+ case RNDIS_QC_GET_MAX_PKT_PER_XFER:
+ ret = copy_to_user((void __user *)arg,
+ &rndis->max_pkt_per_xfer,
+ sizeof(rndis->max_pkt_per_xfer));
+ if (ret) {
+ pr_err("copying to user space failed");
+ ret = -EFAULT;
+ }
+ pr_info("Sent max packets per xfer %d",
+ rndis->max_pkt_per_xfer);
+ break;
+ default:
+ pr_err("Unsupported IOCTL");
+ ret = -EINVAL;
+ }
+
+ rndis_qc_unlock(&rndis->ioctl_excl);
+
+ return ret;
+}
+
+static const struct file_operations rndis_qc_fops = {
+ .owner = THIS_MODULE,
+ .open = rndis_qc_open_dev,
+ .release = rndis_qc_release_dev,
+ .unlocked_ioctl = rndis_qc_ioctl,
+};
+
+static struct miscdevice rndis_qc_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "android_rndis_qc",
+ .fops = &rndis_qc_fops,
+};
+
+static int rndis_qc_init(void)
+{
+ int ret;
+
+ pr_info("initialize rndis QC instance\n");
+
+ ret = misc_register(&rndis_qc_device);
+ if (ret)
+ pr_err("rndis QC driver failed to register");
+
+ return ret;
+}
+
+static void rndis_qc_cleanup(void)
+{
+ pr_info("rndis QC cleanup");
+
+ misc_deregister(&rndis_qc_device);
+ _rndis_qc = NULL;
+}
+
+
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 16c4afb..e0520c7 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -585,8 +585,8 @@
resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION);
resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS);
resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3);
- resp->MaxPacketsPerTransfer = cpu_to_le32(TX_SKB_HOLD_THRESHOLD);
- resp->MaxTransferSize = cpu_to_le32(TX_SKB_HOLD_THRESHOLD *
+ resp->MaxPacketsPerTransfer = cpu_to_le32(params->max_pkt_per_xfer);
+ resp->MaxTransferSize = cpu_to_le32(params->max_pkt_per_xfer *
(params->dev->mtu
+ sizeof(struct ethhdr)
+ sizeof(struct rndis_packet_msg_type)
@@ -902,6 +902,8 @@
rndis_per_dev_params[i].used = 1;
rndis_per_dev_params[i].resp_avail = resp_avail;
rndis_per_dev_params[i].v = v;
+ rndis_per_dev_params[i].max_pkt_per_xfer =
+ TX_SKB_HOLD_THRESHOLD;
pr_debug("%s: configNr = %d\n", __func__, i);
return i;
}
@@ -955,6 +957,13 @@
return 0;
}
+void rndis_set_max_pkt_xfer(u8 configNr, u8 max_pkt_per_xfer)
+{
+ pr_debug("%s:\n", __func__);
+
+ rndis_per_dev_params[configNr].max_pkt_per_xfer = max_pkt_per_xfer;
+}
+
void rndis_add_hdr(struct sk_buff *skb)
{
struct rndis_packet_msg_type *header;
diff --git a/drivers/usb/gadget/rndis.h b/drivers/usb/gadget/rndis.h
index 907c330..1f06c42 100644
--- a/drivers/usb/gadget/rndis.h
+++ b/drivers/usb/gadget/rndis.h
@@ -235,6 +235,7 @@
struct net_device *dev;
u32 vendorID;
+ u8 max_pkt_per_xfer;
const char *vendorDescr;
void (*resp_avail)(void *v);
void *v;
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 624c36d..366df67 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -759,7 +759,7 @@
b = intfdata->in_flight;
spin_unlock_irq(&intfdata->susp_lock);
- if (b)
+ if (b || pm_runtime_autosuspend_expiration(&serial->dev->dev))
return -EBUSY;
}
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index 7da011f..413b239 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -3291,13 +3291,6 @@
},
};
-static int mdp_iommu_fault_handler(struct iommu_domain *domain,
- struct device *dev, unsigned long iova, int flags)
-{
- pr_err("MDP IOMMU page fault: iova 0x%lx", iova);
- return 0;
-}
-
void mdp4_iommu_attach(void)
{
static int done;
@@ -3328,8 +3321,6 @@
if (!domain)
continue;
- iommu_set_fault_handler(domain,
- mdp_iommu_fault_handler);
if (iommu_attach_device(domain, ctx)) {
WARN(1, "%s: could not attach domain %d to context %s."
" iommu programming will not occur.\n",
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 5aa43c3..7e6fd75 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -172,7 +172,7 @@
}
/**
- * virtqueue_add_buf - expose buffer to other end
+ * vring_add_buf - expose buffer to other end
* @vq: the struct virtqueue we're talking about.
* @sg: the description of the buffer(s).
* @out_num: the number of sg readable by other side
@@ -188,7 +188,7 @@
* positive return values as "available": indirect buffers mean that
* we can put an entire sg[] array inside a single queue entry.
*/
-int virtqueue_add_buf(struct virtqueue *_vq,
+static int vring_add_buf(struct virtqueue *_vq,
struct scatterlist sg[],
unsigned int out,
unsigned int in,
@@ -288,20 +288,19 @@
return vq->num_free;
}
-EXPORT_SYMBOL_GPL(virtqueue_add_buf);
/**
- * virtqueue_kick_prepare - first half of split virtqueue_kick call.
+ * vring_kick_prepare - first half of split vring_kick call.
* @vq: the struct virtqueue
*
- * Instead of virtqueue_kick(), you can do:
- * if (virtqueue_kick_prepare(vq))
- * virtqueue_notify(vq);
+ * Instead of vring_kick(), you can do:
+ * if (vring_kick_prepare(vq))
+ * vring_kick_notify(vq);
*
- * This is sometimes useful because the virtqueue_kick_prepare() needs
- * to be serialized, but the actual virtqueue_notify() call does not.
+ * This is sometimes useful because the vring_kick_prepare() needs
+ * to be serialized, but the actual vring_kick_notify() call does not.
*/
-bool virtqueue_kick_prepare(struct virtqueue *_vq)
+static bool vring_kick_prepare(struct virtqueue *_vq)
{
struct vring_virtqueue *vq = to_vvq(_vq);
u16 new, old;
@@ -333,39 +332,36 @@
END_USE(vq);
return needs_kick;
}
-EXPORT_SYMBOL_GPL(virtqueue_kick_prepare);
/**
- * virtqueue_notify - second half of split virtqueue_kick call.
+ * vring_kick_notify - second half of split virtqueue_kick call.
* @vq: the struct virtqueue
*
* This does not need to be serialized.
*/
-void virtqueue_notify(struct virtqueue *_vq)
+static void vring_kick_notify(struct virtqueue *_vq)
{
struct vring_virtqueue *vq = to_vvq(_vq);
/* Prod other side to tell it about changes. */
vq->notify(_vq);
}
-EXPORT_SYMBOL_GPL(virtqueue_notify);
/**
- * virtqueue_kick - update after add_buf
+ * vring_kick - update after add_buf
* @vq: the struct virtqueue
*
- * After one or more virtqueue_add_buf calls, invoke this to kick
+ * After one or more vring_add_buf calls, invoke this to kick
* the other side.
*
* Caller must ensure we don't call this with other virtqueue
* operations at the same time (except where noted).
*/
-void virtqueue_kick(struct virtqueue *vq)
+static void vring_kick(struct virtqueue *vq)
{
- if (virtqueue_kick_prepare(vq))
- virtqueue_notify(vq);
+ if (vring_kick_prepare(vq))
+ vring_kick_notify(vq);
}
-EXPORT_SYMBOL_GPL(virtqueue_kick);
static void detach_buf(struct vring_virtqueue *vq, unsigned int head)
{
@@ -398,7 +394,7 @@
}
/**
- * virtqueue_get_buf - get the next used buffer
+ * vring_get_buf - get the next used buffer
* @vq: the struct virtqueue we're talking about.
* @len: the length written into the buffer
*
@@ -411,9 +407,9 @@
* operations at the same time (except where noted).
*
* Returns NULL if there are no used buffers, or the "data" token
- * handed to virtqueue_add_buf().
+ * handed to vring_add_buf().
*/
-void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
+static void *vring_get_buf(struct virtqueue *_vq, unsigned int *len)
{
struct vring_virtqueue *vq = to_vvq(_vq);
void *ret;
@@ -468,10 +464,9 @@
END_USE(vq);
return ret;
}
-EXPORT_SYMBOL_GPL(virtqueue_get_buf);
/**
- * virtqueue_disable_cb - disable callbacks
+ * vring_disable_cb - disable callbacks
* @vq: the struct virtqueue we're talking about.
*
* Note that this is not necessarily synchronous, hence unreliable and only
@@ -479,16 +474,15 @@
*
* Unlike other operations, this need not be serialized.
*/
-void virtqueue_disable_cb(struct virtqueue *_vq)
+static void vring_disable_cb(struct virtqueue *_vq)
{
struct vring_virtqueue *vq = to_vvq(_vq);
vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT;
}
-EXPORT_SYMBOL_GPL(virtqueue_disable_cb);
/**
- * virtqueue_enable_cb - restart callbacks after disable_cb.
+ * vring_enable_cb - restart callbacks after disable_cb.
* @vq: the struct virtqueue we're talking about.
*
* This re-enables callbacks; it returns "false" if there are pending
@@ -498,7 +492,7 @@
* Caller must ensure we don't call this with other virtqueue
* operations at the same time (except where noted).
*/
-bool virtqueue_enable_cb(struct virtqueue *_vq)
+static bool vring_enable_cb(struct virtqueue *_vq)
{
struct vring_virtqueue *vq = to_vvq(_vq);
@@ -520,10 +514,9 @@
END_USE(vq);
return true;
}
-EXPORT_SYMBOL_GPL(virtqueue_enable_cb);
/**
- * virtqueue_enable_cb_delayed - restart callbacks after disable_cb.
+ * vring_enable_cb_delayed - restart callbacks after disable_cb.
* @vq: the struct virtqueue we're talking about.
*
* This re-enables callbacks but hints to the other side to delay
@@ -535,7 +528,7 @@
* Caller must ensure we don't call this with other virtqueue
* operations at the same time (except where noted).
*/
-bool virtqueue_enable_cb_delayed(struct virtqueue *_vq)
+static bool vring_enable_cb_delayed(struct virtqueue *_vq)
{
struct vring_virtqueue *vq = to_vvq(_vq);
u16 bufs;
@@ -560,17 +553,16 @@
END_USE(vq);
return true;
}
-EXPORT_SYMBOL_GPL(virtqueue_enable_cb_delayed);
/**
- * virtqueue_detach_unused_buf - detach first unused buffer
+ * vring_detach_unused_buf - detach first unused buffer
* @vq: the struct virtqueue we're talking about.
*
- * Returns NULL or the "data" token handed to virtqueue_add_buf().
+ * Returns NULL or the "data" token handed to vring_add_buf().
* This is not valid on an active queue; it is useful only for device
* shutdown.
*/
-void *virtqueue_detach_unused_buf(struct virtqueue *_vq)
+static void *vring_detach_unused_buf(struct virtqueue *_vq)
{
struct vring_virtqueue *vq = to_vvq(_vq);
unsigned int i;
@@ -594,7 +586,6 @@
END_USE(vq);
return NULL;
}
-EXPORT_SYMBOL_GPL(virtqueue_detach_unused_buf);
irqreturn_t vring_interrupt(int irq, void *_vq)
{
@@ -616,6 +607,34 @@
}
EXPORT_SYMBOL_GPL(vring_interrupt);
+/**
+ * get_vring_size - return the size of the virtqueue's vring
+ * @vq: the struct virtqueue containing the vring of interest.
+ *
+ * Returns the size of the vring. This is mainly used for boasting to
+ * userspace. Unlike other operations, this need not be serialized.
+ */
+static unsigned int get_vring_size(struct virtqueue *_vq)
+{
+
+ struct vring_virtqueue *vq = to_vvq(_vq);
+
+ return vq->vring.num;
+}
+
+static struct virtqueue_ops vring_vq_ops = {
+ .add_buf = vring_add_buf,
+ .get_buf = vring_get_buf,
+ .kick = vring_kick,
+ .kick_prepare = vring_kick_prepare,
+ .kick_notify = vring_kick_notify,
+ .disable_cb = vring_disable_cb,
+ .enable_cb = vring_enable_cb,
+ .enable_cb_delayed = vring_enable_cb_delayed,
+ .detach_unused_buf = vring_detach_unused_buf,
+ .get_impl_size = get_vring_size,
+};
+
struct virtqueue *vring_new_virtqueue(unsigned int num,
unsigned int vring_align,
struct virtio_device *vdev,
@@ -641,6 +660,7 @@
vring_init(&vq->vring, num, pages, vring_align);
vq->vq.callback = callback;
vq->vq.vdev = vdev;
+ vq->vq.vq_ops = &vring_vq_ops;
vq->vq.name = name;
vq->notify = notify;
vq->weak_barriers = weak_barriers;
@@ -699,20 +719,4 @@
}
EXPORT_SYMBOL_GPL(vring_transport_features);
-/**
- * virtqueue_get_vring_size - return the size of the virtqueue's vring
- * @vq: the struct virtqueue containing the vring of interest.
- *
- * Returns the size of the vring. This is mainly used for boasting to
- * userspace. Unlike other operations, this need not be serialized.
- */
-unsigned int virtqueue_get_vring_size(struct virtqueue *_vq)
-{
-
- struct vring_virtqueue *vq = to_vvq(_vq);
-
- return vq->vring.num;
-}
-EXPORT_SYMBOL_GPL(virtqueue_get_vring_size);
-
MODULE_LICENSE("GPL");
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 8efd28a..0d0f6d3 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -15,6 +15,7 @@
* @callback: the function to call when buffers are consumed (can be NULL).
* @name: the name of this virtqueue (mainly for debugging)
* @vdev: the virtio device this queue was created for.
+ * @vq_ops: the operations for this virtqueue (see below).
* @priv: a pointer for the virtqueue implementation to use.
*/
struct virtqueue {
@@ -22,33 +23,235 @@
void (*callback)(struct virtqueue *vq);
const char *name;
struct virtio_device *vdev;
+ struct virtqueue_ops *vq_ops;
void *priv;
};
-int virtqueue_add_buf(struct virtqueue *vq,
- struct scatterlist sg[],
- unsigned int out_num,
- unsigned int in_num,
- void *data,
- gfp_t gfp);
+/**
+ * virtqueue_ops - operations for virtqueue abstraction layer
+ * @add_buf: expose buffer to other end
+ * vq: the struct virtqueue we're talking about.
+ * sg: the description of the buffer(s).
+ * out_num: the number of sg readable by other side
+ * in_num: the number of sg which are writable (after readable ones)
+ * data: the token identifying the buffer.
+ * Returns remaining capacity of queue (sg segments) or a negative error.
+ * @kick: update after add_buf
+ * vq: the struct virtqueue
+ * After one or more add_buf calls, invoke this to kick the other side.
+ * @get_buf: get the next used buffer
+ * vq: the struct virtqueue we're talking about.
+ * len: the length written into the buffer
+ * Returns NULL or the "data" token handed to add_buf.
+ * @disable_cb: disable callbacks
+ * vq: the struct virtqueue we're talking about.
+ * Note that this is not necessarily synchronous, hence unreliable and only
+ * useful as an optimization.
+ * @enable_cb: restart callbacks after disable_cb.
+ * vq: the struct virtqueue we're talking about.
+ * This re-enables callbacks; it returns "false" if there are pending
+ * buffers in the queue, to detect a possible race between the driver
+ * checking for more work, and enabling callbacks.
+ * @enable_cb_delayed: restart callbacks after disable_cb.
+ * vq: the struct virtqueue we're talking about.
+ * This re-enables callbacks but hints to the other side to delay
+ * interrupts until most of the available buffers have been processed;
+ * it returns "false" if there are many pending buffers in the queue,
+ * to detect a possible race between the driver checking for more work,
+ * and enabling callbacks.
+ * Caller must ensure we don't call this with other virtqueue
+ * operations at the same time (except where noted).
+ * @detach_unused_buf: detach first unused buffer
+ * vq: the struct virtqueue we're talking about.
+ * Returns NULL or the "data" token handed to add_buf
+ * @get_impl_size: return the size of the virtqueue's implementation
+ * vq: the struct virtqueue containing the implementation of interest.
+ * Returns the size of the implementation. This is mainly used for
+ * boasting to userspace. Unlike other operations, this need not
+ * be serialized.
+ *
+ * Locking rules are straightforward: the driver is responsible for
+ * locking. No two operations may be invoked simultaneously, with the exception
+ * of @disable_cb.
+ *
+ * All operations can be called in any context.
+ */
+struct virtqueue_ops {
+ int (*add_buf)(struct virtqueue *vq,
+ struct scatterlist sg[],
+ unsigned int out_num,
+ unsigned int in_num,
+ void *data,
+ gfp_t gfp);
-void virtqueue_kick(struct virtqueue *vq);
+ void (*kick)(struct virtqueue *vq);
+ bool (*kick_prepare)(struct virtqueue *vq);
+ void (*kick_notify)(struct virtqueue *vq);
+ void *(*get_buf)(struct virtqueue *vq, unsigned int *len);
+ void (*disable_cb)(struct virtqueue *vq);
+ bool (*enable_cb)(struct virtqueue *vq);
+ bool (*enable_cb_delayed)(struct virtqueue *vq);
+ void *(*detach_unused_buf)(struct virtqueue *vq);
+ unsigned int (*get_impl_size)(struct virtqueue *vq);
+};
-bool virtqueue_kick_prepare(struct virtqueue *vq);
+/**
+ * virtqueue_add_buf - expose buffer to other end
+ * @vq: the struct virtqueue we're talking about.
+ * @sg: the description of the buffer(s).
+ * @out_num: the number of sg readable by other side
+ * @in_num: the number of sg which are writable (after readable ones)
+ * @data: the token identifying the buffer.
+ * @gfp: how to do memory allocations (if necessary).
+ *
+ * Caller must ensure we don't call this with other virtqueue operations
+ * at the same time (except where noted).
+ *
+ * Returns remaining capacity of queue or a negative error.
+ */
+static inline int virtqueue_add_buf(struct virtqueue *vq,
+ struct scatterlist sg[],
+ unsigned int out_num,
+ unsigned int in_num,
+ void *data,
+ gfp_t gfp)
+{
+ return vq->vq_ops->add_buf(vq, sg, out_num, in_num, data, gfp);
+}
+/**
+ * virtqueue_kick - update after add_buf
+ * @vq: the struct virtqueue
+ *
+ * After one or more virtqueue_add_buf calls, invoke this to kick
+ * the other side.
+ *
+ * Caller must ensure we don't call this with other virtqueue
+ * operations at the same time (except where noted).
+ */
+static inline void virtqueue_kick(struct virtqueue *vq)
+{
+ vq->vq_ops->kick(vq);
+}
-void virtqueue_notify(struct virtqueue *vq);
+/**
+ * virtqueue_kick_prepare - first half of split virtqueue_kick call.
+ * @vq: the struct virtqueue
+ *
+ * Instead of virtqueue_kick(), you can do:
+ * if (virtqueue_kick_prepare(vq))
+ * virtqueue_kick_notify(vq);
+ *
+ * This is sometimes useful because the virtqueue_kick_prepare() needs
+ * to be serialized, but the actual virtqueue_kick_notify() call does not.
+ */
+static inline bool virtqueue_kick_prepare(struct virtqueue *vq)
+{
+ return vq->vq_ops->kick_prepare(vq);
+}
-void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len);
+/**
+ * virtqueue_kick_notify - second half of split virtqueue_kick call.
+ * @vq: the struct virtqueue
+ */
+static inline void virtqueue_kick_notify(struct virtqueue *vq)
+{
+ vq->vq_ops->kick_notify(vq);
+}
-void virtqueue_disable_cb(struct virtqueue *vq);
+/**
+ * virtqueue_get_buf - get the next used buffer
+ * @vq: the struct virtqueue we're talking about.
+ * @len: the length written into the buffer
+ *
+ * If the driver wrote data into the buffer, @len will be set to the
+ * amount written. This means you don't need to clear the buffer
+ * beforehand to ensure there's no data leakage in the case of short
+ * writes.
+ *
+ * Caller must ensure we don't call this with other virtqueue
+ * operations at the same time (except where noted).
+ *
+ * Returns NULL if there are no used buffers, or the "data" token
+ * handed to virtqueue_add_buf().
+ */
+static inline void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len)
+{
+ return vq->vq_ops->get_buf(vq, len);
+}
-bool virtqueue_enable_cb(struct virtqueue *vq);
+/**
+ * virtqueue_disable_cb - disable callbacks
+ * @vq: the struct virtqueue we're talking about.
+ *
+ * Note that this is not necessarily synchronous, hence unreliable and only
+ * useful as an optimization.
+ *
+ * Unlike other operations, this need not be serialized.
+ */
+static inline void virtqueue_disable_cb(struct virtqueue *vq)
+{
+ vq->vq_ops->disable_cb(vq);
+}
-bool virtqueue_enable_cb_delayed(struct virtqueue *vq);
+/**
+ * virtqueue_enable_cb - restart callbacks after disable_cb.
+ * @vq: the struct virtqueue we're talking about.
+ *
+ * This re-enables callbacks; it returns "false" if there are pending
+ * buffers in the queue, to detect a possible race between the driver
+ * checking for more work, and enabling callbacks.
+ *
+ * Caller must ensure we don't call this with other virtqueue
+ * operations at the same time (except where noted).
+ */
+static inline bool virtqueue_enable_cb(struct virtqueue *vq)
+{
+ return vq->vq_ops->enable_cb(vq);
+}
-void *virtqueue_detach_unused_buf(struct virtqueue *vq);
+/**
+ * virtqueue_enable_cb_delayed - restart callbacks after disable_cb.
+ * @vq: the struct virtqueue we're talking about.
+ *
+ * This re-enables callbacks but hints to the other side to delay
+ * interrupts until most of the available buffers have been processed;
+ * it returns "false" if there are many pending buffers in the queue,
+ * to detect a possible race between the driver checking for more work,
+ * and enabling callbacks.
+ *
+ * Caller must ensure we don't call this with other virtqueue
+ * operations at the same time (except where noted).
+ */
+static inline bool virtqueue_enable_cb_delayed(struct virtqueue *vq)
+{
+ return vq->vq_ops->enable_cb_delayed(vq);
+}
-unsigned int virtqueue_get_vring_size(struct virtqueue *vq);
+/**
+ * virtqueue_detach_unused_buf - detach first unused buffer
+ * @vq: the struct virtqueue we're talking about.
+ *
+ * Returns NULL or the "data" token handed to virtqueue_add_buf().
+ * This is not valid on an active queue; it is useful only for device
+ * shutdown.
+ */
+static inline void *virtqueue_detach_unused_buf(struct virtqueue *vq)
+{
+ return vq->vq_ops->detach_unused_buf(vq);
+}
+
+/**
+ * virtqueue_get_impl_size - return the size of the virtqueue's implementation
+ * @vq: the struct virtqueue containing the implementation of interest.
+ *
+ * Returns the size of the virtqueue implementation. This is mainly used
+ * for boasting to userspace. Unlike other operations, this need not
+ * be serialized.
+ */
+static inline unsigned int virtqueue_get_impl_size(struct virtqueue *vq)
+{
+ return vq->vq_ops->get_impl_size(vq);
+}
/**
* virtio_device - representation of a device using virtio
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index 46a5b1b..295be8f 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -48,6 +48,8 @@
int free_riva_power_on_lock(char *driver_name);
unsigned int wcnss_get_serial_number(void);
void wcnss_flush_delayed_boot_votes(void);
+void wcnss_allow_suspend(void);
+void wcnss_prevent_suspend(void);
#define wcnss_wlan_get_drvdata(dev) dev_get_drvdata(dev)
#define wcnss_wlan_set_drvdata(dev, data) dev_set_drvdata((dev), (data))
diff --git a/include/media/msm_camera.h b/include/media/msm_camera.h
index e400375..2a07002 100644
--- a/include/media/msm_camera.h
+++ b/include/media/msm_camera.h
@@ -498,6 +498,15 @@
#define CMD_AXI_START 0xE1
#define CMD_AXI_STOP 0xE2
+
+#define AXI_CMD_PREVIEW BIT(0)
+#define AXI_CMD_CAPTURE BIT(1)
+#define AXI_CMD_RECORD BIT(2)
+#define AXI_CMD_ZSL BIT(3)
+#define AXI_CMD_RAW_CAPTURE BIT(4)
+
+
+
/* vfe config command: config command(from config thread)*/
struct msm_vfe_cfg_cmd {
int cmd_type;
@@ -1749,6 +1758,14 @@
uint32_t len;
};
+struct msm_camera_vfe_params_t {
+ uint32_t operation_mode;
+ uint32_t capture_count;
+ uint32_t skip_abort;
+ uint16_t port_info;
+ uint16_t cmd_type;
+};
+
enum msm_camss_irq_idx {
CAMERA_SS_IRQ_0,
CAMERA_SS_IRQ_1,