Merge "ASoC: mpq8064: Add FE dai link for multi channel pcm audio." into msm-3.0
diff --git a/Documentation/devicetree/bindings/gpio/qpnp-gpio.txt b/Documentation/devicetree/bindings/gpio/qpnp-gpio.txt
index dff6a3e..7cab09b 100644
--- a/Documentation/devicetree/bindings/gpio/qpnp-gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/qpnp-gpio.txt
@@ -24,27 +24,26 @@
Required properties :
- reg : Specify the spmi offset and size for this gpio device.
- - qcom,qpnp-gpio-num : Specify the PMIC GPIO number for this gpio device.
+ - qcom,gpio-num : Specify the PMIC GPIO number for this gpio device.
-Optional properties :
- - qcom,qpnp-gpio-cfg : Specify the PMIC gpio configuration.
- The format of this configuration is specified in a tuple of 9 entries.
- These entries should be specified in the same order as the entries listed
- in this following discription.
-
- @direction: indicates whether the gpio should be input, output, or
+Optional configuration properties :
+ - qcom,direction: indicates whether the gpio should be input, output, or
both.
+ QPNP_GPIO_DIR_IN = 0,
QPNP_GPIO_DIR_OUT = 1,
- QPNP_GPIO_DIR_IN = 2,
- QPNP_GPIO_DIR_BOTH = 3
+ QPNP_GPIO_DIR_BOTH = 2
- @output_type: indicates gpio should be configured as CMOS or open
+ - qcom,output-type: indicates gpio should be configured as CMOS or open
drain.
- QPNP_GPIO_OUT_BUF_OPEN_DRAIN = 1,
QPNP_GPIO_OUT_BUF_CMOS = 0
+ QPNP_GPIO_OUT_BUF_OPEN_DRAIN_NMOS = 1,
+ QPNP_GPIO_OUT_BUF_OPEN_DRAIN_PMOS = 2,
- @output_value: The gpio output value of the gpio line - 0 or 1
- @pull: Indicates whether a pull up or pull down should be
+ - qcom,invert: Invert the signal of the gpio line -
+ QPNP_GPIO_INVERT_DISABLE = 0
+ QPNP_GPIO_INVERT_ENABLE = 1
+
+ - qcom,pull: Indicates whether a pull up or pull down should be
applied. If a pullup is required the current strength
needs to be specified. Current values of 30uA, 1.5uA,
31.5uA, 1.5uA with 30uA boost are supported.
@@ -55,7 +54,7 @@
QPNP_GPIO_PULL_DN = 4,
QPNP_GPIO_PULL_NO = 5
- @vin_sel: specifies the voltage level when the output is set to 1.
+ - qcom,vin-sel: specifies the voltage level when the output is set to 1.
For an input gpio specifies the voltage level at which
the input is interpreted as a logical 1.
QPNP_GPIO_VIN0 = 0,
@@ -67,27 +66,32 @@
QPNP_GPIO_VIN6 = 6,
QPNP_GPIO_VIN7 = 7
- @out_strength: the amount of current supplied for an output gpio.
- QPNP_GPIO_OUT_STRENGTH_HIGH = 1,
+ - qcom,out-strength: the amount of current supplied for an output gpio.
+ QPNP_GPIO_OUT_STRENGTH_LOW = 1
QPNP_GPIO_OUT_STRENGTH_MED = 2,
- QPNP_GPIO_OUT_STRENGTH_LOW = 3
+ QPNP_GPIO_OUT_STRENGTH_HIGH = 3,
- @source_sel: choose alternate function for the gpio. Certain gpios
+ - qcom,source-sel: choose alternate function for the gpio. Certain gpios
can be paired (shorted) with each other. Some gpio pin
can act as alternate functions.
QPNP_GPIO_FUNC_NORMAL = 0,
QPNP_GPIO_FUNC_PAIRED = 1
QPNP_GPIO_FUNC_1 = 2,
- QPNP_GPIO_FUNC_3 = 3,
+ QPNP_GPIO_FUNC_2 = 3,
QPNP_GPIO_DTEST1 = 4,
QPNP_GPIO_DTEST2 = 5,
QPNP_GPIO_DTEST3 = 6,
QPNP_GPIO_DTEST4 = 7
- @master_en: 1 = Enable features within the GPIO block based on
- configurations.
- 0 = Completely disable the GPIO block and let the pin
- float with high impedance regardless of other settings.
+ - qcom,master-en: 1 = Enable features within the
+ GPIO block based on configurations.
+ 0 = Completely disable the GPIO
+ block and let the pin float with high impedance
+ regardless of other settings.
+
+*Note: If any of the configuration properties are not specified, then the
+ qpnp-gpio driver will not modify that respective configuration in
+ hardware.
[PMIC GPIO clients]
@@ -116,15 +120,16 @@
#address-cells = <1>;
#size-cells = <1>;
- qcom,pm8941_gpio1@0xc000 {
+ gpio@c000 {
reg = <0xc000 0x100>;
- qcom,qpnp-gpio-num = <62>;
+ qcom,gpio-num = <62>;
};
- qcom,pm8941_gpio2@0xc100 {
+ gpio@c100 {
reg = <0xc100 0x100>;
- qcom,qpnp-gpio-num = <20>;
- qcom,qpnp-gpio-cfg = <0x1 0x1 0x1 0x2 0x3 0x2 0x0 0x0 0x1>;
+ qcom,gpio-num = <20>;
+ qcom,source_sel = <2>;
+ qcom,pull = <5>;
};
};
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index c8a4ff9..2698ea7 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -17,6 +17,238 @@
interrupt-controller;
#interrupt-cells = <3>;
+ qcom,pm8941@0 {
+ spmi-slave-container;
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ pm8941_gpios {
+ spmi-dev-container;
+ compatible = "qcom,qpnp-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ gpio@c000 {
+ reg = <0xc000 0x100>;
+ qcom,gpio-num = <1>;
+ status = "disabled";
+ };
+
+ gpio@c100 {
+ reg = <0xc100 0x100>;
+ qcom,gpio-num = <2>;
+ status = "disabled";
+ };
+
+ gpio@c200 {
+ reg = <0xc200 0x100>;
+ qcom,gpio-num = <3>;
+ status = "disabled";
+ };
+
+ gpio@c300 {
+ reg = <0xc300 0x100>;
+ qcom,gpio-num = <4>;
+ status = "disabled";
+ };
+
+ gpio@c400 {
+ reg = <0xc400 0x100>;
+ qcom,gpio-num = <5>;
+ status = "disabled";
+ };
+
+ gpio@c500 {
+ reg = <0xc500 0x100>;
+ qcom,gpio-num = <6>;
+ status = "disabled";
+ };
+
+ gpio@c600 {
+ reg = <0xc600 0x100>;
+ qcom,gpio-num = <7>;
+ status = "disabled";
+ };
+
+ gpio@c700 {
+ reg = <0xc700 0x100>;
+ qcom,gpio-num = <8>;
+ status = "disabled";
+ };
+
+ gpio@c800 {
+ reg = <0xc800 0x100>;
+ qcom,gpio-num = <9>;
+ status = "disabled";
+ };
+
+ gpio@c900 {
+ reg = <0xc900 0x100>;
+ qcom,gpio-num = <10>;
+ status = "disabled";
+ };
+
+ gpio@ca00 {
+ reg = <0xca00 0x100>;
+ qcom,gpio-num = <11>;
+ status = "disabled";
+ };
+
+ gpio@cb00 {
+ reg = <0xcb00 0x100>;
+ qcom,gpio-num = <12>;
+ status = "disabled";
+ };
+
+ gpio@cc00 {
+ reg = <0xcc00 0x100>;
+ qcom,gpio-num = <13>;
+ status = "disabled";
+ };
+
+ gpio@cd00 {
+ reg = <0xcd00 0x100>;
+ qcom,gpio-num = <14>;
+ status = "disabled";
+ };
+
+ gpio@ce00 {
+ reg = <0xce00 0x100>;
+ qcom,gpio-num = <15>;
+ status = "disabled";
+ };
+
+ gpio@cf00 {
+ reg = <0xcf00 0x100>;
+ qcom,gpio-num = <16>;
+ status = "disabled";
+ };
+
+ gpio@d000 {
+ reg = <0xd000 0x100>;
+ qcom,gpio-num = <17>;
+ status = "disabled";
+ };
+
+ gpio@d100 {
+ reg = <0xd100 0x100>;
+ qcom,gpio-num = <18>;
+ status = "disabled";
+ };
+
+ gpio@d200 {
+ reg = <0xd200 0x100>;
+ qcom,gpio-num = <19>;
+ status = "disabled";
+ };
+
+ gpio@d300 {
+ reg = <0xd300 0x100>;
+ qcom,gpio-num = <20>;
+ status = "disabled";
+ };
+
+ gpio@d400 {
+ reg = <0xd400 0x100>;
+ qcom,gpio-num = <21>;
+ status = "disabled";
+ };
+
+ gpio@d500 {
+ reg = <0xd500 0x100>;
+ qcom,gpio-num = <22>;
+ status = "disabled";
+ };
+
+ gpio@d600 {
+ reg = <0xd600 0x100>;
+ qcom,gpio-num = <23>;
+ status = "disabled";
+ };
+
+ gpio@d700 {
+ reg = <0xd700 0x100>;
+ qcom,gpio-num = <24>;
+ status = "disabled";
+ };
+
+ gpio@d800 {
+ reg = <0xd800 0x100>;
+ qcom,gpio-num = <25>;
+ status = "disabled";
+ };
+
+ gpio@d900 {
+ reg = <0xd900 0x100>;
+ qcom,gpio-num = <26>;
+ status = "disabled";
+ };
+
+ gpio@da00 {
+ reg = <0xda00 0x100>;
+ qcom,gpio-num = <27>;
+ status = "disabled";
+ };
+
+ gpio@db00 {
+ reg = <0xdb00 0x100>;
+ qcom,gpio-num = <28>;
+ status = "disabled";
+ };
+
+ gpio@dc00 {
+ reg = <0xdc00 0x100>;
+ qcom,gpio-num = <29>;
+ status = "disabled";
+ };
+
+ gpio@dd00 {
+ reg = <0xdd00 0x100>;
+ qcom,gpio-num = <30>;
+ status = "disabled";
+ };
+
+ gpio@de00 {
+ reg = <0xde00 0x100>;
+ qcom,gpio-num = <31>;
+ status = "disabled";
+ };
+
+ gpio@df00 {
+ reg = <0xdf00 0x100>;
+ qcom,gpio-num = <32>;
+ status = "disabled";
+ };
+
+ gpio@e000 {
+ reg = <0xe000 0x100>;
+ qcom,gpio-num = <33>;
+ status = "disabled";
+ };
+
+ gpio@e100 {
+ reg = <0xe100 0x100>;
+ qcom,gpio-num = <34>;
+ status = "disabled";
+ };
+
+ gpio@e200 {
+ reg = <0xe200 0x100>;
+ qcom,gpio-num = <35>;
+ status = "disabled";
+ };
+
+ gpio@e300 {
+ reg = <0xe300 0x100>;
+ qcom,gpio-num = <36>;
+ status = "disabled";
+ };
+ };
+ };
+
qcom,pm8941@1 {
spmi-slave-container;
reg = <0x1>;
diff --git a/arch/arm/boot/dts/msmcopper-gpio.dtsi b/arch/arm/boot/dts/msmcopper-gpio.dtsi
new file mode 100644
index 0000000..7c3f5ce
--- /dev/null
+++ b/arch/arm/boot/dts/msmcopper-gpio.dtsi
@@ -0,0 +1,214 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+ qcom,spmi@fc4c0000 {
+
+ qcom,pm8941@0 {
+
+ pm8941_gpios: pm8941_gpios {
+
+ gpio@c000 {
+ qcom,gpio-num = <1>;
+ status = "ok";
+ };
+
+ gpio@c100 {
+ qcom,gpio-num = <2>;
+ status = "ok";
+ };
+
+ gpio@c200 {
+ qcom,gpio-num = <3>;
+ status = "ok";
+ };
+
+ gpio@c300 {
+ qcom,gpio-num = <4>;
+ status = "ok";
+ };
+
+ gpio@c400 {
+ qcom,gpio-num = <5>;
+ status = "ok";
+ };
+
+ gpio@c500 {
+ qcom,gpio-num = <6>;
+ status = "ok";
+ };
+
+ gpio@c600 {
+ qcom,gpio-num = <7>;
+ status = "ok";
+ };
+
+ gpio@c700 {
+ qcom,gpio-num = <8>;
+ status = "ok";
+ };
+
+ gpio@c800 {
+ qcom,gpio-num = <9>;
+ status = "ok";
+ };
+
+ gpio@c900 {
+ qcom,gpio-num = <10>;
+ status = "ok";
+ };
+
+ gpio@ca00 {
+ qcom,gpio-num = <11>;
+ status = "ok";
+ };
+
+ gpio@cb00 {
+ qcom,gpio-num = <12>;
+ status = "ok";
+ };
+
+ gpio@cc00 {
+ qcom,gpio-num = <13>;
+ status = "ok";
+ };
+
+ gpio@cd00 {
+ qcom,gpio-num = <14>;
+ status = "ok";
+ };
+
+ gpio@ce00 {
+ qcom,gpio-num = <15>;
+ status = "ok";
+ };
+
+ gpio@cf00 {
+ qcom,gpio-num = <16>;
+ status = "ok";
+ };
+
+ gpio@d000 {
+ qcom,gpio-num = <17>;
+ status = "ok";
+ };
+
+ gpio@d100 {
+ qcom,gpio-num = <18>;
+ status = "ok";
+ };
+
+ gpio@d200 {
+ qcom,gpio-num = <19>;
+ status = "ok";
+ };
+
+ gpio@d300 {
+ qcom,gpio-num = <20>;
+ status = "ok";
+ };
+
+ gpio@d400 {
+ qcom,gpio-num = <21>;
+ status = "ok";
+ };
+
+ gpio@d500 {
+ qcom,gpio-num = <22>;
+ status = "ok";
+ };
+
+ gpio@d600 {
+ qcom,gpio-num = <23>;
+ status = "ok";
+ };
+
+ gpio@d700 {
+ qcom,gpio-num = <24>;
+ status = "ok";
+ };
+
+ gpio@d800 {
+ qcom,gpio-num = <25>;
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@d900 {
+ qcom,gpio-num = <26>;
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@da00 {
+ qcom,gpio-num = <27>;
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@db00 {
+ qcom,gpio-num = <28>;
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@dc00 {
+ qcom,gpio-num = <29>;
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@dd00 {
+ qcom,gpio-num = <30>;
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@de00 {
+ qcom,gpio-num = <31>;
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@df00 {
+ qcom,gpio-num = <32>;
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@e000 {
+ qcom,gpio-num = <33>;
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@e100 {
+ qcom,gpio-num = <34>;
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@e200 {
+ qcom,gpio-num = <35>;
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+
+ gpio@e300 {
+ qcom,gpio-num = <36>;
+ qcom,out-strength = <1>;
+ status = "ok";
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msmcopper.dtsi b/arch/arm/boot/dts/msmcopper.dtsi
index 4821290..e998ca9 100644
--- a/arch/arm/boot/dts/msmcopper.dtsi
+++ b/arch/arm/boot/dts/msmcopper.dtsi
@@ -14,6 +14,7 @@
/include/ "msm-pm8841.dtsi"
/include/ "msm-pm8941.dtsi"
/include/ "msmcopper-regulator.dtsi"
+/include/ "msmcopper-gpio.dtsi"
/ {
model = "Qualcomm MSM Copper";
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 1107412..875b479 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -1113,3 +1113,113 @@
return 0;
}
#endif
+#ifdef CONFIG_ARCH_MSM8625
+ /*
+ * Check for any interrupts which are enabled are pending
+ * in the pending set or not.
+ * Return :
+ * 0 : No pending interrupts
+ * 1 : Pending interrupts other than A9_M2A_5
+ */
+unsigned int msm_gic_spi_ppi_pending(void)
+{
+ unsigned int i, bit = 0;
+ unsigned int pending_enb = 0, pending = 0;
+ unsigned long value = 0;
+ struct gic_chip_data *gic = &gic_data[0];
+ void __iomem *base = gic_data_dist_base(gic);
+
+ raw_spin_lock(&irq_controller_lock);
+ /*
+ * PPI and SGI to be included.
+ * MSM8625_INT_A9_M2A_5 needs to be ignored, as A9_M2A_5
+ * requesting sleep triggers it
+ */
+ for (i = 0; (i * 32) < gic->max_irq; i++) {
+ pending = readl_relaxed(base +
+ GIC_DIST_PENDING_SET + i * 4);
+ pending_enb = readl_relaxed(base +
+ GIC_DIST_ENABLE_SET + i * 4);
+ value = pending & pending_enb;
+
+ if (value) {
+ for (bit = 0; bit < 32; bit++) {
+ bit = find_next_bit(&value, 32, bit);
+ if ((bit + 32 * i) != MSM8625_INT_A9_M2A_5) {
+ raw_spin_unlock(&irq_controller_lock);
+ return 1;
+ }
+ }
+ }
+ }
+ raw_spin_unlock(&irq_controller_lock);
+
+ return 0;
+}
+
+void msm_gic_save(bool modem_wake, int from_idle)
+{
+ unsigned int i;
+ struct gic_chip_data *gic = &gic_data[0];
+ void __iomem *base = gic_data_dist_base(gic);
+
+ gic_cpu_save(0);
+ gic_dist_save(0);
+ /* Disable all the Interrupts, if we enter from idle pc */
+ if (from_idle) {
+ for (i = 0; (i * 32) < gic->max_irq; i++) {
+ raw_spin_lock(&irq_controller_lock);
+ writel_relaxed(0xffffffff, base
+ + GIC_DIST_ENABLE_CLEAR + i * 4);
+ raw_spin_unlock(&irq_controller_lock);
+ }
+ }
+}
+
+void msm_gic_restore(void)
+{
+ gic_dist_restore(0);
+ gic_cpu_restore(0);
+}
+
+/*
+ * Configure the GIC after we come out of power collapse.
+ * This function will configure some of the GIC registers so as to prepare the
+ * core1 to receive an SPI(ACSR_MP_CORE_IPC1, (32 + 8)), which will bring
+ * core1 out of GDFS.
+ */
+void core1_gic_configure_and_raise(void)
+{
+ struct gic_chip_data *gic = &gic_data[0];
+ void __iomem *base = gic_data_dist_base(gic);
+ unsigned int value = 0;
+
+ raw_spin_lock(&irq_controller_lock);
+
+ value = __raw_readl(base + GIC_DIST_ACTIVE_BIT + 0x4);
+ value |= BIT(8);
+ __raw_writel(value, base + GIC_DIST_ACTIVE_BIT + 0x4);
+ mb();
+
+ value = __raw_readl(base + GIC_DIST_TARGET + 0x24);
+ value |= BIT(13);
+ __raw_writel(value, base + GIC_DIST_TARGET + 0x24);
+ mb();
+
+ value = __raw_readl(base + GIC_DIST_TARGET + 0x28);
+ value |= BIT(1);
+ __raw_writel(value, base + GIC_DIST_TARGET + 0x28);
+ mb();
+
+ value = __raw_readl(base + GIC_DIST_ENABLE_SET + 0x4);
+ value |= BIT(8);
+ __raw_writel(value, base + GIC_DIST_ENABLE_SET + 0x4);
+ mb();
+
+ value = __raw_readl(base + GIC_DIST_PENDING_SET + 0x4);
+ value |= BIT(8);
+ __raw_writel(value, base + GIC_DIST_PENDING_SET + 0x4);
+ mb();
+ raw_spin_unlock(&irq_controller_lock);
+}
+#endif
diff --git a/arch/arm/configs/msm7627a-perf_defconfig b/arch/arm/configs/msm7627a-perf_defconfig
index 5b77374..f195d68 100644
--- a/arch/arm/configs/msm7627a-perf_defconfig
+++ b/arch/arm/configs/msm7627a-perf_defconfig
@@ -309,6 +309,7 @@
CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_MSM_PDM=y
+CONFIG_LEDS_PMIC_MPP=y
CONFIG_SWITCH=y
CONFIG_SWITCH_GPIO=y
CONFIG_RTC_CLASS=y
diff --git a/arch/arm/configs/msm7627a_defconfig b/arch/arm/configs/msm7627a_defconfig
index 287e7fb..9952818 100644
--- a/arch/arm/configs/msm7627a_defconfig
+++ b/arch/arm/configs/msm7627a_defconfig
@@ -309,6 +309,7 @@
CONFIG_MMC_MSM_SDC3_SUPPORT=y
CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT=y
CONFIG_LEDS_MSM_PDM=y
+CONFIG_LEDS_PMIC_MPP=y
CONFIG_SWITCH=y
CONFIG_SWITCH_GPIO=y
CONFIG_RTC_CLASS=y
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 5668e75..7e1989e 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -63,4 +63,10 @@
#endif
+#ifdef CONFIG_ARCH_MSM8625
+void msm_gic_save(bool modem_wake, int from_idle);
+void msm_gic_restore(void);
+void core1_gic_configure_and_raise(void);
+#endif
+
#endif
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index 99a3fa1..3431cd0 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -433,6 +433,19 @@
.drv = GPIOMUX_DRV_12MA,
.pull = GPIOMUX_PULL_NONE,
};
+
+static struct gpiomux_setting sx150x_suspended_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting sx150x_active_cfg = {
+ .func = GPIOMUX_FUNC_GPIO,
+ .drv = GPIOMUX_DRV_8MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
static struct gpiomux_setting cyts_sleep_sus_cfg = {
.func = GPIOMUX_FUNC_GPIO,
.drv = GPIOMUX_DRV_6MA,
@@ -968,6 +981,16 @@
},
};
+static struct msm_gpiomux_config sx150x_int_configs[] __initdata = {
+ {
+ .gpio = 81,
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &sx150x_suspended_cfg,
+ [GPIOMUX_ACTIVE] = &sx150x_active_cfg,
+ },
+ },
+};
+
void __init apq8064_init_gpiomux(void)
{
int rc;
@@ -989,6 +1012,8 @@
msm_gpiomux_install(vcap_configs,
ARRAY_SIZE(vcap_configs));
#endif
+ msm_gpiomux_install(sx150x_int_configs,
+ ARRAY_SIZE(sx150x_int_configs));
} else {
#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
msm_gpiomux_install(apq8064_ethernet_configs,
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 5b0b9c3..d08fe01 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -154,7 +154,7 @@
.memory_type = MEMTYPE_EBI1,
};
-static struct platform_device android_pmem_device = {
+static struct platform_device apq8064_android_pmem_device = {
.name = "android_pmem",
.id = 0,
.dev = {.platform_data = &android_pmem_pdata},
@@ -166,7 +166,7 @@
.cached = 0,
.memory_type = MEMTYPE_EBI1,
};
-static struct platform_device android_pmem_adsp_device = {
+static struct platform_device apq8064_android_pmem_adsp_device = {
.name = "android_pmem",
.id = 2,
.dev = { .platform_data = &android_pmem_adsp_pdata },
@@ -179,7 +179,7 @@
.memory_type = MEMTYPE_EBI1,
};
-static struct platform_device android_pmem_audio_device = {
+static struct platform_device apq8064_android_pmem_audio_device = {
.name = "android_pmem",
.id = 4,
.dev = { .platform_data = &android_pmem_audio_pdata },
@@ -199,7 +199,7 @@
};
#if defined(CONFIG_MSM_RTB)
-static struct msm_rtb_platform_data msm_rtb_pdata = {
+static struct msm_rtb_platform_data apq8064_rtb_pdata = {
.size = SZ_1M,
};
@@ -208,17 +208,17 @@
int s;
s = memparse(p, NULL);
- msm_rtb_pdata.size = ALIGN(s, SZ_4K);
+ apq8064_rtb_pdata.size = ALIGN(s, SZ_4K);
return 0;
}
early_param("msm_rtb_size", msm_rtb_set_buffer_size);
-static struct platform_device msm_rtb_device = {
+static struct platform_device apq8064_rtb_device = {
.name = "msm_rtb",
.id = -1,
.dev = {
- .platform_data = &msm_rtb_pdata,
+ .platform_data = &apq8064_rtb_pdata,
},
};
#endif
@@ -226,7 +226,7 @@
static void __init reserve_rtb_memory(void)
{
#if defined(CONFIG_MSM_RTB)
- apq8064_reserve_table[MEMTYPE_EBI1].size += msm_rtb_pdata.size;
+ apq8064_reserve_table[MEMTYPE_EBI1].size += apq8064_rtb_pdata.size;
#endif
}
@@ -270,22 +270,22 @@
#ifdef CONFIG_ION_MSM
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-static struct ion_cp_heap_pdata cp_mm_ion_pdata = {
+static struct ion_cp_heap_pdata cp_mm_apq8064_ion_pdata = {
.permission_type = IPT_TYPE_MM_CARVEOUT,
.align = PAGE_SIZE,
};
-static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
+static struct ion_cp_heap_pdata cp_mfc_apq8064_ion_pdata = {
.permission_type = IPT_TYPE_MFC_SHAREDMEM,
.align = PAGE_SIZE,
};
-static struct ion_co_heap_pdata co_ion_pdata = {
+static struct ion_co_heap_pdata co_apq8064_ion_pdata = {
.adjacent_mem_id = INVALID_HEAP_ID,
.align = PAGE_SIZE,
};
-static struct ion_co_heap_pdata fw_co_ion_pdata = {
+static struct ion_co_heap_pdata fw_co_apq8064_ion_pdata = {
.adjacent_mem_id = ION_CP_MM_HEAP_ID,
.align = SZ_128K,
};
@@ -302,7 +302,7 @@
* to each other.
* Don't swap the order unless you know what you are doing!
*/
-static struct ion_platform_data ion_pdata = {
+static struct ion_platform_data apq8064_ion_pdata = {
.nr = MSM_ION_HEAP_NUM,
.heaps = {
{
@@ -317,7 +317,7 @@
.name = ION_MM_HEAP_NAME,
.size = MSM_ION_MM_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &cp_mm_ion_pdata,
+ .extra_data = (void *) &cp_mm_apq8064_ion_pdata,
},
{
.id = ION_MM_FIRMWARE_HEAP_ID,
@@ -325,7 +325,7 @@
.name = ION_MM_FIRMWARE_HEAP_NAME,
.size = MSM_ION_MM_FW_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &fw_co_ion_pdata,
+ .extra_data = (void *) &fw_co_apq8064_ion_pdata,
},
{
.id = ION_CP_MFC_HEAP_ID,
@@ -333,7 +333,7 @@
.name = ION_MFC_HEAP_NAME,
.size = MSM_ION_MFC_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &cp_mfc_ion_pdata,
+ .extra_data = (void *) &cp_mfc_apq8064_ion_pdata,
},
#ifndef CONFIG_MSM_IOMMU
{
@@ -342,7 +342,7 @@
.name = ION_SF_HEAP_NAME,
.size = MSM_ION_SF_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &co_ion_pdata,
+ .extra_data = (void *) &co_apq8064_ion_pdata,
},
#endif
{
@@ -356,7 +356,7 @@
.name = ION_QSECOM_HEAP_NAME,
.size = MSM_ION_QSECOM_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &co_ion_pdata,
+ .extra_data = (void *) &co_apq8064_ion_pdata,
},
{
.id = ION_AUDIO_HEAP_ID,
@@ -364,16 +364,16 @@
.name = ION_AUDIO_HEAP_NAME,
.size = MSM_ION_AUDIO_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &co_ion_pdata,
+ .extra_data = (void *) &co_apq8064_ion_pdata,
},
#endif
}
};
-static struct platform_device ion_dev = {
+static struct platform_device apq8064_ion_dev = {
.name = "ion-msm",
.id = 1,
- .dev = { .platform_data = &ion_pdata },
+ .dev = { .platform_data = &apq8064_ion_pdata },
};
#endif
@@ -1889,13 +1889,13 @@
&msm_device_iris_fm,
#ifdef CONFIG_ANDROID_PMEM
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
- &android_pmem_device,
- &android_pmem_adsp_device,
- &android_pmem_audio_device,
+ &apq8064_android_pmem_device,
+ &apq8064_android_pmem_adsp_device,
+ &apq8064_android_pmem_audio_device,
#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
#endif /*CONFIG_ANDROID_PMEM*/
#ifdef CONFIG_ION_MSM
- &ion_dev,
+ &apq8064_ion_dev,
#endif
&msm8064_device_watchdog,
&msm8064_device_saw_regulator_core0,
@@ -1964,7 +1964,7 @@
&msm_pil_vidc,
&msm_gss,
#ifdef CONFIG_MSM_RTB
- &msm_rtb_device,
+ &apq8064_rtb_device,
#endif
&apq8064_cpu_idle_device,
&apq8064_msm_gov_device,
@@ -2356,6 +2356,7 @@
};
#define SX150X_EXP1_INT_N PM8921_MPP_IRQ(PM8921_IRQ_BASE, 9)
+#define SX150X_EXP2_INT_N MSM_GPIO_TO_INT(81)
struct sx150x_platform_data mpq8064_sx150x_pdata[] = {
[SX150X_EXP1] = {
@@ -2375,7 +2376,8 @@
.io_pulldn_ena = 0x0,
.io_open_drain_ena = 0x0,
.io_polarity = 0,
- .irq_summary = -1,
+ .irq_summary = SX150X_EXP2_INT_N,
+ .irq_base = SX150X_EXP2_IRQ_BASE,
},
[SX150X_EXP3] = {
.gpio_base = SX150X_EXP3_GPIO_BASE,
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 24e6a79..1cf1935 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -185,7 +185,7 @@
.memory_type = MEMTYPE_EBI1,
};
-static struct platform_device android_pmem_device = {
+static struct platform_device msm8930_android_pmem_device = {
.name = "android_pmem",
.id = 0,
.dev = {.platform_data = &android_pmem_pdata},
@@ -197,7 +197,7 @@
.cached = 0,
.memory_type = MEMTYPE_EBI1,
};
-static struct platform_device android_pmem_adsp_device = {
+static struct platform_device msm8930_android_pmem_adsp_device = {
.name = "android_pmem",
.id = 2,
.dev = { .platform_data = &android_pmem_adsp_pdata },
@@ -210,7 +210,7 @@
.memory_type = MEMTYPE_EBI1,
};
-static struct platform_device android_pmem_audio_device = {
+static struct platform_device msm8930_android_pmem_audio_device = {
.name = "android_pmem",
.id = 4,
.dev = { .platform_data = &android_pmem_audio_pdata },
@@ -250,7 +250,7 @@
};
#if defined(CONFIG_MSM_RTB)
-static struct msm_rtb_platform_data msm_rtb_pdata = {
+static struct msm_rtb_platform_data msm8930_rtb_pdata = {
.size = SZ_1M,
};
@@ -259,17 +259,17 @@
int s;
s = memparse(p, NULL);
- msm_rtb_pdata.size = ALIGN(s, SZ_4K);
+ msm8930_rtb_pdata.size = ALIGN(s, SZ_4K);
return 0;
}
early_param("msm_rtb_size", msm_rtb_set_buffer_size);
-static struct platform_device msm_rtb_device = {
+static struct platform_device msm8930_rtb_device = {
.name = "msm_rtb",
.id = -1,
.dev = {
- .platform_data = &msm_rtb_pdata,
+ .platform_data = &msm8930_rtb_pdata,
},
};
#endif
@@ -277,7 +277,7 @@
static void __init reserve_rtb_memory(void)
{
#if defined(CONFIG_MSM_RTB)
- msm8930_reserve_table[MEMTYPE_EBI1].size += msm_rtb_pdata.size;
+ msm8930_reserve_table[MEMTYPE_EBI1].size += msm8930_rtb_pdata.size;
#endif
}
@@ -320,20 +320,20 @@
#ifdef CONFIG_ION_MSM
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-static struct ion_cp_heap_pdata cp_mm_ion_pdata = {
+static struct ion_cp_heap_pdata cp_mm_msm8930_ion_pdata = {
.permission_type = IPT_TYPE_MM_CARVEOUT,
.align = PAGE_SIZE,
};
-static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
+static struct ion_cp_heap_pdata cp_mfc_msm8930_ion_pdata = {
.permission_type = IPT_TYPE_MFC_SHAREDMEM,
.align = PAGE_SIZE,
};
-static struct ion_co_heap_pdata co_ion_pdata = {
+static struct ion_co_heap_pdata co_msm8930_ion_pdata = {
.adjacent_mem_id = INVALID_HEAP_ID,
.align = PAGE_SIZE,
};
-static struct ion_co_heap_pdata fw_co_ion_pdata = {
+static struct ion_co_heap_pdata fw_co_msm8930_ion_pdata = {
.adjacent_mem_id = ION_CP_MM_HEAP_ID,
.align = SZ_128K,
};
@@ -350,7 +350,7 @@
* to each other.
* Don't swap the order unless you know what you are doing!
*/
-static struct ion_platform_data ion_pdata = {
+static struct ion_platform_data msm8930_ion_pdata = {
.nr = MSM_ION_HEAP_NUM,
.heaps = {
{
@@ -365,7 +365,7 @@
.name = ION_MM_HEAP_NAME,
.size = MSM_ION_MM_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &cp_mm_ion_pdata,
+ .extra_data = (void *) &cp_mm_msm8930_ion_pdata,
},
{
.id = ION_MM_FIRMWARE_HEAP_ID,
@@ -373,7 +373,7 @@
.name = ION_MM_FIRMWARE_HEAP_NAME,
.size = MSM_ION_MM_FW_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &fw_co_ion_pdata,
+ .extra_data = (void *) &fw_co_msm8930_ion_pdata,
},
{
.id = ION_CP_MFC_HEAP_ID,
@@ -381,7 +381,7 @@
.name = ION_MFC_HEAP_NAME,
.size = MSM_ION_MFC_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &cp_mfc_ion_pdata,
+ .extra_data = (void *) &cp_mfc_msm8930_ion_pdata,
},
{
.id = ION_SF_HEAP_ID,
@@ -389,7 +389,7 @@
.name = ION_SF_HEAP_NAME,
.size = MSM_ION_SF_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &co_ion_pdata,
+ .extra_data = (void *) &co_msm8930_ion_pdata,
},
{
.id = ION_IOMMU_HEAP_ID,
@@ -402,7 +402,7 @@
.name = ION_QSECOM_HEAP_NAME,
.size = MSM_ION_QSECOM_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &co_ion_pdata,
+ .extra_data = (void *) &co_msm8930_ion_pdata,
},
{
.id = ION_AUDIO_HEAP_ID,
@@ -410,16 +410,16 @@
.name = ION_AUDIO_HEAP_NAME,
.size = MSM_ION_AUDIO_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &co_ion_pdata,
+ .extra_data = (void *) &co_msm8930_ion_pdata,
},
#endif
}
};
-static struct platform_device ion_dev = {
+static struct platform_device msm8930_ion_dev = {
.name = "ion-msm",
.id = 1,
- .dev = { .platform_data = &ion_pdata },
+ .dev = { .platform_data = &msm8930_ion_pdata },
};
#endif
@@ -1286,30 +1286,35 @@
},
};
-#/* TODO: Remove this once PM8038 physically becomes
- * available.
- */
#define ISA1200_HAP_EN_GPIO 77
#define ISA1200_HAP_LEN_GPIO 78
#define ISA1200_HAP_CLK PM8038_GPIO_PM_TO_SYS(7)
static int isa1200_power(int on)
{
+ int rc = 0;
+
gpio_set_value_cansleep(ISA1200_HAP_CLK, !!on);
- return 0;
+ if (on)
+ rc = pm8xxx_aux_clk_control(CLK_MP3_1, XO_DIV_1, true);
+ else
+ rc = pm8xxx_aux_clk_control(CLK_MP3_1, XO_DIV_NONE, true);
+
+ if (rc) {
+ pr_err("%s: unable to write aux clock register(%d)\n",
+ __func__, rc);
+ }
+
+ return rc;
}
static int isa1200_dev_setup(bool enable)
{
int rc = 0;
- rc = pm8xxx_aux_clk_control(CLK_MP3_1, XO_DIV_1, enable);
- if (rc) {
- pr_err("%s: unable to write aux clock register(%d)\n",
- __func__, rc);
- return rc;
- }
+ if (!enable)
+ goto fail_gpio_dir;
rc = gpio_request(ISA1200_HAP_CLK, "haptics_clk");
if (rc) {
@@ -1749,9 +1754,9 @@
#endif
#ifdef CONFIG_ANDROID_PMEM
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
- &android_pmem_device,
- &android_pmem_adsp_device,
- &android_pmem_audio_device,
+ &msm8930_android_pmem_device,
+ &msm8930_android_pmem_adsp_device,
+ &msm8930_android_pmem_audio_device,
#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
#endif /*CONFIG_ANDROID_PMEM*/
&msm_device_bam_dmux,
@@ -1764,7 +1769,7 @@
&msm8930_rpm_log_device,
&msm8930_rpm_stat_device,
#ifdef CONFIG_ION_MSM
- &ion_dev,
+ &msm8930_ion_dev,
#endif
&msm_device_tz_log,
@@ -1781,7 +1786,7 @@
&gpio_keys_8930,
#endif
#ifdef CONFIG_MSM_RTB
- &msm_rtb_device,
+ &msm8930_rtb_device,
#endif
&msm8930_cpu_idle_device,
&msm8930_msm_gov_device,
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 6328ab3..defa33b 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -224,7 +224,7 @@
.memory_type = MEMTYPE_EBI1,
};
-static struct platform_device android_pmem_device = {
+static struct platform_device msm8960_android_pmem_device = {
.name = "android_pmem",
.id = 0,
.dev = {.platform_data = &android_pmem_pdata},
@@ -236,7 +236,7 @@
.cached = 0,
.memory_type = MEMTYPE_EBI1,
};
-static struct platform_device android_pmem_adsp_device = {
+static struct platform_device msm8960_android_pmem_adsp_device = {
.name = "android_pmem",
.id = 2,
.dev = { .platform_data = &android_pmem_adsp_pdata },
@@ -249,7 +249,7 @@
.memory_type = MEMTYPE_EBI1,
};
-static struct platform_device android_pmem_audio_device = {
+static struct platform_device msm8960_android_pmem_audio_device = {
.name = "android_pmem",
.id = 4,
.dev = { .platform_data = &android_pmem_audio_pdata },
@@ -257,7 +257,7 @@
#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
#endif /*CONFIG_ANDROID_PMEM*/
-struct fmem_platform_data fmem_pdata = {
+struct fmem_platform_data msm8960_fmem_pdata = {
};
#define DSP_RAM_BASE_8960 0x8da00000
@@ -292,7 +292,7 @@
};
#if defined(CONFIG_MSM_RTB)
-static struct msm_rtb_platform_data msm_rtb_pdata = {
+static struct msm_rtb_platform_data msm8960_rtb_pdata = {
.size = SZ_1M,
};
@@ -301,17 +301,17 @@
int s;
s = memparse(p, NULL);
- msm_rtb_pdata.size = ALIGN(s, SZ_4K);
+ msm8960_rtb_pdata.size = ALIGN(s, SZ_4K);
return 0;
}
early_param("msm_rtb_size", msm_rtb_set_buffer_size);
-static struct platform_device msm_rtb_device = {
+static struct platform_device msm8960_rtb_device = {
.name = "msm_rtb",
.id = -1,
.dev = {
- .platform_data = &msm_rtb_pdata,
+ .platform_data = &msm8960_rtb_pdata,
},
};
#endif
@@ -319,7 +319,7 @@
static void __init reserve_rtb_memory(void)
{
#if defined(CONFIG_MSM_RTB)
- msm8960_reserve_table[MEMTYPE_EBI1].size += msm_rtb_pdata.size;
+ msm8960_reserve_table[MEMTYPE_EBI1].size += msm8960_rtb_pdata.size;
#endif
}
@@ -372,7 +372,7 @@
#ifdef CONFIG_ION_MSM
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
-static struct ion_cp_heap_pdata cp_mm_ion_pdata = {
+static struct ion_cp_heap_pdata cp_mm_msm8960_ion_pdata = {
.permission_type = IPT_TYPE_MM_CARVEOUT,
.align = PAGE_SIZE,
.reusable = FMEM_ENABLED,
@@ -380,7 +380,7 @@
.fixed_position = FIXED_MIDDLE,
};
-static struct ion_cp_heap_pdata cp_mfc_ion_pdata = {
+static struct ion_cp_heap_pdata cp_mfc_msm8960_ion_pdata = {
.permission_type = IPT_TYPE_MFC_SHAREDMEM,
.align = PAGE_SIZE,
.reusable = 0,
@@ -388,13 +388,13 @@
.fixed_position = FIXED_HIGH,
};
-static struct ion_co_heap_pdata co_ion_pdata = {
+static struct ion_co_heap_pdata co_msm8960_ion_pdata = {
.adjacent_mem_id = INVALID_HEAP_ID,
.align = PAGE_SIZE,
.mem_is_fmem = 0,
};
-static struct ion_co_heap_pdata fw_co_ion_pdata = {
+static struct ion_co_heap_pdata fw_co_msm8960_ion_pdata = {
.adjacent_mem_id = ION_CP_MM_HEAP_ID,
.align = SZ_128K,
.mem_is_fmem = FMEM_ENABLED,
@@ -413,7 +413,7 @@
* to each other.
* Don't swap the order unless you know what you are doing!
*/
-static struct ion_platform_data ion_pdata = {
+static struct ion_platform_data msm8960_ion_pdata = {
.nr = MSM_ION_HEAP_NUM,
.heaps = {
{
@@ -428,7 +428,7 @@
.name = ION_MM_HEAP_NAME,
.size = MSM_ION_MM_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &cp_mm_ion_pdata,
+ .extra_data = (void *) &cp_mm_msm8960_ion_pdata,
},
{
.id = ION_MM_FIRMWARE_HEAP_ID,
@@ -436,7 +436,7 @@
.name = ION_MM_FIRMWARE_HEAP_NAME,
.size = MSM_ION_MM_FW_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &fw_co_ion_pdata,
+ .extra_data = (void *) &fw_co_msm8960_ion_pdata,
},
{
.id = ION_CP_MFC_HEAP_ID,
@@ -444,7 +444,7 @@
.name = ION_MFC_HEAP_NAME,
.size = MSM_ION_MFC_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &cp_mfc_ion_pdata,
+ .extra_data = (void *) &cp_mfc_msm8960_ion_pdata,
},
#ifndef CONFIG_MSM_IOMMU
{
@@ -453,7 +453,7 @@
.name = ION_SF_HEAP_NAME,
.size = MSM_ION_SF_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &co_ion_pdata,
+ .extra_data = (void *) &co_msm8960_ion_pdata,
},
#endif
{
@@ -467,7 +467,7 @@
.name = ION_QSECOM_HEAP_NAME,
.size = MSM_ION_QSECOM_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &co_ion_pdata,
+ .extra_data = (void *) &co_msm8960_ion_pdata,
},
{
.id = ION_AUDIO_HEAP_ID,
@@ -475,23 +475,23 @@
.name = ION_AUDIO_HEAP_NAME,
.size = MSM_ION_AUDIO_SIZE,
.memory_type = ION_EBI_TYPE,
- .extra_data = (void *) &co_ion_pdata,
+ .extra_data = (void *) &co_msm8960_ion_pdata,
},
#endif
}
};
-static struct platform_device ion_dev = {
+static struct platform_device msm8960_ion_dev = {
.name = "ion-msm",
.id = 1,
- .dev = { .platform_data = &ion_pdata },
+ .dev = { .platform_data = &msm8960_ion_pdata },
};
#endif
-struct platform_device fmem_device = {
+struct platform_device msm8960_fmem_device = {
.name = "fmem",
.id = 1,
- .dev = { .platform_data = &fmem_pdata },
+ .dev = { .platform_data = &msm8960_fmem_pdata },
};
static void __init adjust_mem_for_liquid(void)
@@ -507,9 +507,10 @@
if (machine_is_msm8960_liquid() ||
msm8960_hdmi_as_primary_selected()) {
- for (i = 0; i < ion_pdata.nr; i++) {
- if (ion_pdata.heaps[i].id == ION_SF_HEAP_ID) {
- ion_pdata.heaps[i].size =
+ for (i = 0; i < msm8960_ion_pdata.nr; i++) {
+ if (msm8960_ion_pdata.heaps[i].id ==
+ ION_SF_HEAP_ID) {
+ msm8960_ion_pdata.heaps[i].size =
msm_ion_sf_size;
pr_debug("msm_ion_sf_size 0x%x\n",
msm_ion_sf_size);
@@ -566,9 +567,9 @@
unsigned long fixed_low_start, fixed_middle_start, fixed_high_start;
adjust_mem_for_liquid();
- fmem_pdata.size = 0;
- fmem_pdata.reserved_size_low = 0;
- fmem_pdata.reserved_size_high = 0;
+ msm8960_fmem_pdata.size = 0;
+ msm8960_fmem_pdata.reserved_size_low = 0;
+ msm8960_fmem_pdata.reserved_size_high = 0;
fixed_low_size = 0;
fixed_middle_size = 0;
fixed_high_size = 0;
@@ -576,8 +577,9 @@
/* We only support 1 reusable heap. Check if more than one heap
* is specified as reusable and set as non-reusable if found.
*/
- for (i = 0; i < ion_pdata.nr; ++i) {
- const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+ for (i = 0; i < msm8960_ion_pdata.nr; ++i) {
+ const struct ion_platform_heap *heap =
+ &(msm8960_ion_pdata.heaps[i]);
if (heap->type == ION_HEAP_TYPE_CP && heap->extra_data) {
struct ion_cp_heap_pdata *data = heap->extra_data;
@@ -593,8 +595,9 @@
}
}
- for (i = 0; i < ion_pdata.nr; ++i) {
- const struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+ for (i = 0; i < msm8960_ion_pdata.nr; ++i) {
+ const struct ion_platform_heap *heap =
+ &(msm8960_ion_pdata.heaps[i]);
if (heap->extra_data) {
int fixed_position = NOT_FIXED;
@@ -630,16 +633,16 @@
fixed_high_size += heap->size;
if (mem_is_fmem)
- fmem_pdata.size += heap->size;
+ msm8960_fmem_pdata.size += heap->size;
}
}
if (!fixed_size)
return;
- if (fmem_pdata.size) {
- fmem_pdata.reserved_size_low = fixed_low_size;
- fmem_pdata.reserved_size_high = fixed_high_size;
+ if (msm8960_fmem_pdata.size) {
+ msm8960_fmem_pdata.reserved_size_low = fixed_low_size;
+ msm8960_fmem_pdata.reserved_size_high = fixed_high_size;
}
/* Since the fixed area may be carved out of lowmem,
@@ -653,8 +656,8 @@
fixed_middle_start = fixed_low_start + fixed_low_size;
fixed_high_start = fixed_middle_start + fixed_middle_size;
- for (i = 0; i < ion_pdata.nr; ++i) {
- struct ion_platform_heap *heap = &(ion_pdata.heaps[i]);
+ for (i = 0; i < msm8960_ion_pdata.nr; ++i) {
+ struct ion_platform_heap *heap = &(msm8960_ion_pdata.heaps[i]);
if (heap->extra_data) {
int fixed_position = NOT_FIXED;
@@ -696,15 +699,15 @@
}
#if defined(CONFIG_MSM_CACHE_DUMP)
-static struct msm_cache_dump_platform_data msm_cache_dump_pdata = {
+static struct msm_cache_dump_platform_data msm8960_cache_dump_pdata = {
.l2_size = L2_BUFFER_SIZE,
};
-static struct platform_device msm_cache_dump_device = {
+static struct platform_device msm8960_cache_dump_device = {
.name = "msm_cache_dump",
.id = -1,
.dev = {
- .platform_data = &msm_cache_dump_pdata,
+ .platform_data = &msm8960_cache_dump_pdata,
},
};
@@ -736,8 +739,8 @@
total = l1_size + l2_size;
msm8960_reserve_table[MEMTYPE_EBI1].size += total;
- msm_cache_dump_pdata.l1_size = l1_size;
- msm_cache_dump_pdata.l2_size = l2_size;
+ msm8960_cache_dump_pdata.l1_size = l1_size;
+ msm8960_cache_dump_pdata.l2_size = l2_size;
#endif
}
@@ -841,16 +844,17 @@
{
msm8960_set_display_params(prim_panel_name, ext_panel_name);
msm_reserve();
- if (fmem_pdata.size) {
+ if (msm8960_fmem_pdata.size) {
#if defined(CONFIG_ION_MSM) && defined(CONFIG_MSM_MULTIMEDIA_USE_ION)
- fmem_pdata.phys = reserve_info->fixed_area_start +
+ msm8960_fmem_pdata.phys = reserve_info->fixed_area_start +
MSM_MM_FW_SIZE;
pr_info("mm fw at %lx (fixed) size %x\n",
reserve_info->fixed_area_start, MSM_MM_FW_SIZE);
pr_info("fmem start %lx (fixed) size %lx\n",
- fmem_pdata.phys, fmem_pdata.size);
+ msm8960_fmem_pdata.phys, msm8960_fmem_pdata.size);
#else
- fmem_pdata.phys = reserve_memory_for_fmem(fmem_pdata.size);
+ msm8960_fmem_pdata.phys =
+ reserve_memory_for_fmem(msm8960_fmem_pdata.size);
#endif
}
}
@@ -2539,12 +2543,12 @@
#ifdef CONFIG_MSM_FAKE_BATTERY
&fish_battery_device,
#endif
- &fmem_device,
+ &msm8960_fmem_device,
#ifdef CONFIG_ANDROID_PMEM
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
- &android_pmem_device,
- &android_pmem_adsp_device,
- &android_pmem_audio_device,
+ &msm8960_android_pmem_device,
+ &msm8960_android_pmem_adsp_device,
+ &msm8960_android_pmem_audio_device,
#endif
#endif
&msm_device_vidc,
@@ -2563,7 +2567,7 @@
&msm_device_rng,
#endif
#ifdef CONFIG_ION_MSM
- &ion_dev,
+ &msm8960_ion_dev,
#endif
&msm8960_rpm_device,
&msm8960_rpm_log_device,
@@ -2579,13 +2583,13 @@
&msm_device_dspcrashd_8960,
&msm8960_device_watchdog,
#ifdef CONFIG_MSM_RTB
- &msm_rtb_device,
+ &msm8960_rtb_device,
#endif
&msm8960_cpu_idle_device,
&msm8960_msm_gov_device,
&msm8960_device_cache_erp,
#ifdef CONFIG_MSM_CACHE_DUMP
- &msm_cache_dump_device,
+ &msm8960_cache_dump_device,
#endif
&msm8960_iommu_domain_device,
};
diff --git a/arch/arm/mach-msm/board-msm7627a-io.c b/arch/arm/mach-msm/board-msm7627a-io.c
index e622dfe..7f84920 100644
--- a/arch/arm/mach-msm/board-msm7627a-io.c
+++ b/arch/arm/mach-msm/board-msm7627a-io.c
@@ -25,6 +25,7 @@
#include <asm/gpio.h>
#include <asm/mach-types.h>
#include <mach/rpc_server_handset.h>
+#include <mach/pmic.h>
#include "devices.h"
#include "board-msm7627a.h"
@@ -653,6 +654,24 @@
},
};
+static struct led_info ctp_backlight_info = {
+ .name = "button-backlight",
+ .flags = PM_MPP__I_SINK__LEVEL_40mA << 16 | PM_MPP_7,
+};
+
+static struct led_platform_data ctp_backlight_pdata = {
+ .leds = &ctp_backlight_info,
+ .num_leds = 1,
+};
+
+static struct platform_device pmic_mpp_leds_pdev = {
+ .name = "pmic-mpp-leds",
+ .id = -1,
+ .dev = {
+ .platform_data = &ctp_backlight_pdata,
+ },
+};
+
void __init msm7627a_add_io_devices(void)
{
/* touchscreen */
@@ -752,5 +771,6 @@
}
platform_device_register(&gpio_leds_8625);
+ platform_device_register(&pmic_mpp_leds_pdev);
}
}
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 0997e8bd..0832a03 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -1412,7 +1412,12 @@
.freq_hz = f, \
.src_clk = &s##_clk.c, \
}
-static struct clk_freq_tbl clk_tbl_prng[] = {
+static struct clk_freq_tbl clk_tbl_prng_32[] = {
+ F_PRNG(32000000, pll8),
+ F_END
+};
+
+static struct clk_freq_tbl clk_tbl_prng_64[] = {
F_PRNG(64000000, pll8),
F_END
};
@@ -1426,12 +1431,12 @@
.halt_bit = 10,
},
.set_rate = set_rate_nop,
- .freq_tbl = clk_tbl_prng,
+ .freq_tbl = clk_tbl_prng_32,
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "prng_clk",
.ops = &clk_ops_rcg,
- VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 65000000),
+ VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 64000000),
CLK_INIT(prng_clk.c),
},
};
@@ -4927,8 +4932,6 @@
CLK_LOOKUP("src_clk", usb_fs1_src_clk.c, ""),
CLK_LOOKUP("alt_core_clk", usb_fs1_xcvr_clk.c, ""),
CLK_LOOKUP("sys_clk", usb_fs1_sys_clk.c, ""),
- CLK_LOOKUP("iface_clk", ce1_p_clk.c, ""),
- CLK_LOOKUP("core_clk", ce1_core_clk.c, ""),
CLK_LOOKUP("ref_clk", sata_phy_ref_clk.c, ""),
CLK_LOOKUP("cfg_clk", sata_phy_cfg_clk.c, ""),
CLK_LOOKUP("iface_clk", ce3_p_clk.c, "qce.0"),
@@ -6010,6 +6013,8 @@
pll15_clk.c.rate = 900000000;
gmem_axi_clk.c.depends = &gfx3d_axi_clk_8930.c;
}
+ if ((readl_relaxed(PRNG_CLK_NS_REG) & 0x7F) == 0x2B)
+ prng_clk.freq_tbl = clk_tbl_prng_64;
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
@@ -6034,7 +6039,7 @@
/* Initialize rates for clocks that only support one. */
clk_set_rate(&pdm_clk.c, 27000000);
- clk_set_rate(&prng_clk.c, 64000000);
+ clk_set_rate(&prng_clk.c, prng_clk.freq_tbl->freq_hz);
clk_set_rate(&mdp_vsync_clk.c, 27000000);
clk_set_rate(&tsif_ref_clk.c, 105000);
clk_set_rate(&tssc_clk.c, 27000000);
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 26ccaa3..5bfd348 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -75,6 +75,7 @@
#define PLLTEST_PAD_CFG_REG REG(0x2FA4)
#define PMEM_ACLK_CTL_REG REG(0x25A0)
#define PPSS_HCLK_CTL_REG REG(0x2580)
+#define PRNG_CLK_NS_REG REG(0x2E80)
#define RINGOSC_NS_REG REG(0x2DC0)
#define RINGOSC_STATUS_REG REG(0x2DCC)
#define RINGOSC_TCXO_CTL_REG REG(0x2DC4)
@@ -1139,7 +1140,12 @@
.freq_hz = f, \
.src_clk = &s##_clk.c, \
}
-static struct clk_freq_tbl clk_tbl_prng[] = {
+static struct clk_freq_tbl clk_tbl_prng_32[] = {
+ F_PRNG(32000000, pll8),
+ F_END
+};
+
+static struct clk_freq_tbl clk_tbl_prng_64[] = {
F_PRNG(64000000, pll8),
F_END
};
@@ -1153,12 +1159,12 @@
.halt_bit = 10,
},
.set_rate = set_rate_nop,
- .freq_tbl = clk_tbl_prng,
+ .freq_tbl = clk_tbl_prng_32,
.current_freq = &rcg_dummy_freq,
.c = {
.dbg_name = "prng_clk",
.ops = &clk_ops_rcg,
- VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 65000000),
+ VDD_DIG_FMAX_MAP2(LOW, 32000000, NOMINAL, 64000000),
CLK_INIT(prng_clk.c),
},
};
@@ -3788,6 +3794,9 @@
/* Set the dsi_byte_clk src to the DSI PHY PLL,
* dsi_esc_clk to PXO/2, and the hdmi_app_clk src to PXO */
rmwreg(0x400001, MISC_CC2_REG, 0x424003);
+
+ if ((readl_relaxed(PRNG_CLK_NS_REG) & 0x7F) == 0x2B)
+ prng_clk.freq_tbl = clk_tbl_prng_64;
}
static void __init msm8660_clock_post_init(void)
@@ -3805,7 +3814,7 @@
/* Initialize rates for clocks that only support one. */
clk_set_rate(&pdm_clk.c, 27000000);
- clk_set_rate(&prng_clk.c, 64000000);
+ clk_set_rate(&prng_clk.c, prng_clk.freq_tbl->freq_hz);
clk_set_rate(&mdp_vsync_clk.c, 27000000);
clk_set_rate(&tsif_ref_clk.c, 105000);
clk_set_rate(&tssc_clk.c, 27000000);
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index 55282b6..e8e88d7 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -316,7 +316,7 @@
void __iomem *cbcr_reg,
enum branch_state br_status)
{
- char *status_str = (br_status == BRANCH_ON) ? "on" : "off";
+ char *status_str = (br_status == BRANCH_ON) ? "off" : "on";
/*
* Use a memory barrier since some halt status registers are
diff --git a/arch/arm/mach-msm/footswitch-8x60.c b/arch/arm/mach-msm/footswitch-8x60.c
index bde7713..eb334b9 100644
--- a/arch/arm/mach-msm/footswitch-8x60.c
+++ b/arch/arm/mach-msm/footswitch-8x60.c
@@ -634,10 +634,14 @@
else
fs->clk_data = mdp_8660_clks;
} else if (pdev->id == FS_GFX3D) {
- if (cpu_is_msm8930() || cpu_is_apq8064())
+ if (cpu_is_apq8064()) {
fs->clk_data = gfx3d_8064_clks;
- else
+ fs->bus_port1 = MSM_BUS_MASTER_GRAPHICS_3D_PORT1;
+ } else if (cpu_is_msm8930()) {
+ fs->clk_data = gfx3d_8064_clks;
+ } else {
fs->clk_data = gfx3d_8660_clks;
+ }
} else if (pdev->id == FS_VED) {
if (cpu_is_apq8064()) {
fs->bus_port0 = MSM_BUS_MASTER_VIDEO_ENC;
diff --git a/arch/arm/mach-msm/include/mach/camera.h b/arch/arm/mach-msm/include/mach/camera.h
index 7857e69..90d236b 100644
--- a/arch/arm/mach-msm/include/mach/camera.h
+++ b/arch/arm/mach-msm/include/mach/camera.h
@@ -343,13 +343,6 @@
enum msm_st_frame_packing s_snap_packing;
};
-struct msm_actuator_ctrl {
- int (*a_power_up)(void *);
- int (*a_power_down)(void *);
- int (*a_create_subdevice)(void *, void *);
- int (*a_config)(void __user *);
-};
-
struct msm_strobe_flash_ctrl {
int (*strobe_flash_init)
(struct msm_camera_sensor_strobe_flash_data *);
@@ -382,6 +375,11 @@
const char *name;
};
+struct msm_mctl_stats_t {
+ struct hlist_head pmem_stats_list;
+ spinlock_t pmem_stats_spinlock;
+};
+
struct msm_sync {
/* These two queues are accessed from a process context only
* They contain pmem descriptors for the preview frames and the stats
@@ -416,7 +414,6 @@
struct msm_camvpe_fn vpefn;
struct msm_sensor_ctrl sctrl;
struct msm_strobe_flash_ctrl sfctrl;
- struct msm_actuator_ctrl actctrl;
struct wake_lock wake_lock;
struct platform_device *pdev;
int16_t ignore_qcmd_type;
diff --git a/arch/arm/mach-msm/include/mach/msm_smd.h b/arch/arm/mach-msm/include/mach/msm_smd.h
index 4934c0f..2966509 100644
--- a/arch/arm/mach-msm/include/mach/msm_smd.h
+++ b/arch/arm/mach-msm/include/mach/msm_smd.h
@@ -282,6 +282,19 @@
* @returns Pointer to subsystem name or NULL if not found
*/
const char *smd_pid_to_subsystem(uint32_t pid);
+
+/*
+ * Checks to see if a new packet has arrived on the channel. Only to be
+ * called with interrupts disabled.
+ *
+ * @ch: channel to check if a packet has arrived
+ *
+ * Returns:
+ * 0 - packet not available
+ * 1 - packet available
+ * -EINVAL - NULL parameter or non-packet based channel provided
+ */
+int smd_is_pkt_avail(smd_channel_t *ch);
#else
static inline int smd_open(const char *name, smd_channel_t **ch, void *priv,
@@ -393,6 +406,11 @@
{
return NULL;
}
+
+static inline int smd_is_pkt_avail(smd_channel_t *ch)
+{
+ return -ENODEV;
+}
#endif
#endif
diff --git a/arch/arm/mach-msm/mpm-8625.c b/arch/arm/mach-msm/mpm-8625.c
index 6b88103..fa966d2 100644
--- a/arch/arm/mach-msm/mpm-8625.c
+++ b/arch/arm/mach-msm/mpm-8625.c
@@ -25,20 +25,14 @@
#include <asm/hardware/gic.h>
#include <mach/msm_smsm.h>
+#include "mpm-8625.h"
+
#define NUM_REGS_ENABLE 2
/* (NR_MSM_IRQS/32) 96 max irqs supported */
#define NUM_REGS_DISABLE 3
#define GIC_IRQ_MASK(irq) BIT(irq % 32)
#define GIC_IRQ_INDEX(irq) (irq / 32)
-#ifdef CONFIG_PM
-u32 saved_spi_enable[DIV_ROUND_UP(256, 32)];
-u32 saved_spi_conf[DIV_ROUND_UP(256, 16)];
-u32 saved_spi_target[DIV_ROUND_UP(256, 4)];
-u32 __percpu *saved_ppi_enable;
-u32 __percpu *saved_ppi_conf;
-#endif
-
enum {
IRQ_DEBUG_SLEEP_INT_TRIGGER = BIT(0),
IRQ_DEBUG_SLEEP_INT = BIT(1),
@@ -54,10 +48,6 @@
static uint32_t msm_gic_irq_smsm_wake_enable[NUM_REGS_ENABLE];
static uint32_t msm_gic_irq_idle_disable[NUM_REGS_DISABLE];
-static DEFINE_RAW_SPINLOCK(gic_controller_lock);
-static void __iomem *dist_base, *cpu_base;
-static unsigned int max_irqs;
-
/*
* Some of the interrupts which will not be considered as wake capable
* should be marked as FAKE.
@@ -162,158 +152,17 @@
return 0;
}
-#ifdef CONFIG_PM
-static void __init msm_gic_pm_init(void)
-{
- saved_ppi_enable = __alloc_percpu(DIV_ROUND_UP(32, 32) * 4,
- sizeof(u32));
- BUG_ON(!saved_ppi_enable);
-
- saved_ppi_conf = __alloc_percpu(DIV_ROUND_UP(32, 16) * 4,
- sizeof(u32));
- BUG_ON(!saved_ppi_conf);
-}
-#endif
-
void __init msm_gic_irq_extn_init(void __iomem *db, void __iomem *cb)
{
- dist_base = db;
- cpu_base = cb;
- max_irqs = readl_relaxed(dist_base + GIC_DIST_CTR) & 0x11f;
- max_irqs = (max_irqs + 1) * 32;
-
gic_arch_extn.irq_mask = msm_gic_mask_irq;
gic_arch_extn.irq_unmask = msm_gic_unmask_irq;
gic_arch_extn.irq_disable = msm_gic_mask_irq;
gic_arch_extn.irq_set_wake = msm_gic_set_irq_wake;
-
-#ifdef CONFIG_PM
- msm_gic_pm_init();
-#endif
-}
-
-/* GIC APIs */
-
- /*
- * Save the GIC cpu and distributor context before PC and
- * restor it back after coming out of PC.
- */
-static void msm_gic_save(void)
-{
- int i;
- u32 *ptr;
-
- /* Save the Per CPU PPI's */
- ptr = __this_cpu_ptr(saved_ppi_enable);
- /* 0 - 31 the SGI and PPI */
- ptr[0] = readl_relaxed(dist_base + GIC_DIST_ENABLE_SET);
-
- ptr = __this_cpu_ptr(saved_ppi_conf);
- for (i = 0; i < 2; i++)
- ptr[i] = readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
-
- /* Save the SPIs */
- for (i = 0; (i * 16) < max_irqs; i++)
- saved_spi_conf[i] =
- readl_relaxed(dist_base + GIC_DIST_CONFIG + i * 4);
-
- for (i = 0; (i * 4) < max_irqs; i++)
- saved_spi_target[i] =
- readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
-
- for (i = 0; (i * 32) < max_irqs; i++)
- saved_spi_enable[i] =
- readl_relaxed(dist_base + GIC_DIST_ENABLE_SET + i * 4);
-}
-
-static void msm_gic_restore(void)
-{
- int i;
- u32 *ptr;
-
- /* restore CPU Interface */
- /* Per CPU SGIs and PPIs */
- ptr = __this_cpu_ptr(saved_ppi_enable);
- writel_relaxed(ptr[0], dist_base + GIC_DIST_ENABLE_SET);
-
- ptr = __this_cpu_ptr(saved_ppi_conf);
- for (i = 0; i < 2; i++)
- writel_relaxed(ptr[i], dist_base + GIC_DIST_CONFIG + i * 4);
-
- for (i = 0; (i * 4) < max_irqs; i++)
- writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4);
-
- writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
- writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
-
- /* restore Distributor */
- writel_relaxed(0, dist_base + GIC_DIST_CTRL);
-
- for (i = 0; (i * 16) < max_irqs; i++)
- writel_relaxed(saved_spi_conf[i],
- dist_base + GIC_DIST_CONFIG + i * 4);
-
- for (i = 0; (i * 4) < max_irqs; i++)
- writel_relaxed(0xa0a0a0a0,
- dist_base + GIC_DIST_PRI + i * 4);
-
- for (i = 0; (i * 4) < max_irqs; i++)
- writel_relaxed(saved_spi_target[i],
- dist_base + GIC_DIST_TARGET + i * 4);
-
- for (i = 0; (i * 32) < max_irqs; i++)
- writel_relaxed(saved_spi_enable[i],
- dist_base + GIC_DIST_ENABLE_SET + i * 4);
-
- writel_relaxed(1, dist_base + GIC_DIST_CTRL);
-
- mb();
}
/* Power APIs */
/*
- * Check for any interrupts which are enabled are pending
- * in the pending set or not.
- * Return :
- * 0 : No pending interrupts
- * 1 : Pending interrupts other than A9_M2A_5
- */
-unsigned int msm_gic_spi_ppi_pending(void)
-{
- unsigned int i, bit = 0;
- unsigned int pending_enb = 0, pending = 0;
- unsigned long value = 0;
-
- raw_spin_lock(&gic_controller_lock);
- /*
- * PPI and SGI to be included.
- * MSM8625_INT_A9_M2A_5 needs to be ignored, as A9_M2A_5
- * requesting sleep triggers it
- */
- for (i = 0; (i * 32) < max_irqs; i++) {
- pending = readl_relaxed(dist_base +
- GIC_DIST_PENDING_SET + i * 4);
- pending_enb = readl_relaxed(dist_base +
- GIC_DIST_ENABLE_SET + i * 4);
- value = pending & pending_enb;
-
- if (value) {
- for (bit = 0; bit < 32; bit++) {
- bit = find_next_bit(&value, 32, bit);
- if ((bit + 32 * i) != MSM8625_INT_A9_M2A_5) {
- raw_spin_unlock(&gic_controller_lock);
- return 1;
- }
- }
- }
- }
- raw_spin_unlock(&gic_controller_lock);
-
- return 0;
-}
-
- /*
* Iterate over the disable list
*/
@@ -352,8 +201,6 @@
*/
int msm_gic_irq_enter_sleep2(bool modem_wake, int from_idle)
{
- int i;
-
if (from_idle && !modem_wake)
return 0;
@@ -371,14 +218,10 @@
}
if (modem_wake) {
- /* save the contents of GIC CPU interface and Distributor */
- msm_gic_save();
- /* Disable all the Interrupts, if we enter from idle pc */
- if (from_idle) {
- for (i = 0; (i * 32) < max_irqs; i++)
- writel_relaxed(0xffffffff, dist_base
- + GIC_DIST_ENABLE_CLEAR + i * 4);
- }
+ /* save the contents of GIC CPU interface and Distributor
+ * Disable all the Interrupts, if we enter from idle pc
+ */
+ msm_gic_save(modem_wake, from_idle);
irq_set_irq_type(MSM8625_INT_A9_M2A_6, IRQF_TRIGGER_RISING);
enable_irq(MSM8625_INT_A9_M2A_6);
pr_debug("%s going for sleep now\n", __func__);
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 60ae4d9..5eac539 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -114,7 +114,12 @@
struct resource *res;
desc = pil_q6v5_init(pdev);
+ if (IS_ERR(desc))
+ return PTR_ERR(desc);
+
drv = platform_get_drvdata(pdev);
+ if (drv == NULL)
+ return -ENODEV;
desc->ops = &pil_lpass_ops;
desc->owner = THIS_MODULE;
diff --git a/arch/arm/mach-msm/platsmp-8625.c b/arch/arm/mach-msm/platsmp-8625.c
index 23ca454..393f1bd 100644
--- a/arch/arm/mach-msm/platsmp-8625.c
+++ b/arch/arm/mach-msm/platsmp-8625.c
@@ -60,7 +60,6 @@
}
static DEFINE_SPINLOCK(boot_lock);
-static DEFINE_RAW_SPINLOCK(irq_controller_lock);
/*
* MP_CORE_IPC will be used to generate interrupt and can be used by either
@@ -79,51 +78,14 @@
mb();
}
-/*
- * Configure the GIC after we come out of power collapse.
- * This function will configure some of the GIC registers so as to prepare the
- * core1 to receive an SPI(ACSR_MP_CORE_IPC1, (32 + 8)), which will bring
- * core1 out of GDFS.
- */
-static void core1_gic_configure_and_raise(void)
-{
- unsigned int value = 0;
-
- raw_spin_lock(&irq_controller_lock);
-
- value = __raw_readl(MSM_QGIC_DIST_BASE + GIC_DIST_ACTIVE_BIT + 0x4);
- value |= BIT(8);
- __raw_writel(value, MSM_QGIC_DIST_BASE + GIC_DIST_ACTIVE_BIT + 0x4);
- mb();
-
- value = __raw_readl(MSM_QGIC_DIST_BASE + GIC_DIST_TARGET + 0x24);
- value |= BIT(13);
- __raw_writel(value, MSM_QGIC_DIST_BASE + GIC_DIST_TARGET + 0x24);
- mb();
-
- value = __raw_readl(MSM_QGIC_DIST_BASE + GIC_DIST_TARGET + 0x28);
- value |= BIT(1);
- __raw_writel(value, MSM_QGIC_DIST_BASE + GIC_DIST_TARGET + 0x28);
- mb();
-
- value = __raw_readl(MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET + 0x4);
- value |= BIT(8);
- __raw_writel(value, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET + 0x4);
- mb();
-
- value = __raw_readl(MSM_QGIC_DIST_BASE + GIC_DIST_PENDING_SET + 0x4);
- value |= BIT(8);
- __raw_writel(value, MSM_QGIC_DIST_BASE + GIC_DIST_PENDING_SET + 0x4);
- mb();
-
- raise_clear_spi(1, true);
- raw_spin_unlock(&irq_controller_lock);
-}
-
static void clear_pending_spi(unsigned int irq)
{
- /* Clear the IRQ from the ENABLE_SET */
+ struct irq_data *d = irq_get_irq_data(irq);
+ struct irq_chip *c = irq_data_get_irq_chip(d);
+
+ c->irq_mask(d);
local_irq_disable();
+ /* Clear the IRQ from the ENABLE_SET */
gic_clear_spi_pending(irq);
local_irq_enable();
}
@@ -234,10 +196,12 @@
* needs to be brought out by raising an SPI.
*/
- if (power_collapsed)
+ if (power_collapsed) {
core1_gic_configure_and_raise();
- else
+ raise_clear_spi(1, true);
+ } else {
gic_raise_softirq(cpumask_of(cpu), 1);
+ }
timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) {
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index 06e3d37..5382102 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -241,7 +241,7 @@
dload_mode_addr = MSM_IMEM_BASE + DLOAD_MODE_ADDR;
/* Reset detection is switched on below.*/
- set_dload_mode(1);
+ set_dload_mode(download_mode);
#endif
msm_tmr0_base = msm_timer_get_timer0_base();
restart_reason = MSM_IMEM_BASE + RESTART_REASON_ADDR;
diff --git a/arch/arm/mach-msm/rpc_server_handset.c b/arch/arm/mach-msm/rpc_server_handset.c
index b011aeb..6d173fb 100644
--- a/arch/arm/mach-msm/rpc_server_handset.c
+++ b/arch/arm/mach-msm/rpc_server_handset.c
@@ -1,6 +1,6 @@
/* arch/arm/mach-msm/rpc_server_handset.c
*
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2010,2012 Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -517,7 +517,7 @@
return 0;
}
-static int __init hs_rpc_cb_init(void)
+static int __devinit hs_rpc_cb_init(void)
{
int rc = 0, i, num_vers;
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 6b42325..dac0a37 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -2207,6 +2207,20 @@
}
EXPORT_SYMBOL(smd_tiocmset);
+int smd_is_pkt_avail(smd_channel_t *ch)
+{
+ if (!ch || !ch->is_pkt_ch)
+ return -EINVAL;
+
+ if (ch->current_packet)
+ return 1;
+
+ update_packet_state(ch);
+
+ return ch->current_packet ? 1 : 0;
+}
+EXPORT_SYMBOL(smd_is_pkt_avail);
+
/* -------------------------------------------------------------------------- */
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 8328ee2..cf024cf 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -485,4 +485,12 @@
help
Say 'y' here to include support for the Qualcomm QPNP gpio
support. QPNP is a SPMI based PMIC implementation.
+
+config GPIO_QPNP_DEBUG
+ depends on GPIO_QPNP
+ depends on DEBUG_FS
+ bool "Qualcomm QPNP GPIO debug support"
+ help
+ Say 'y' here to include debug support for the Qualcomm
+ QPNP gpio support
endif
diff --git a/drivers/gpio/qpnp-gpio.c b/drivers/gpio/qpnp-gpio.c
index 90cc798..bc0904ec 100644
--- a/drivers/gpio/qpnp-gpio.c
+++ b/drivers/gpio/qpnp-gpio.c
@@ -10,10 +10,13 @@
* GNU General Public License for more details.
*/
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
#include <linux/interrupt.h>
#include <linux/types.h>
#include <linux/spmi.h>
#include <linux/platform_device.h>
+#include <linux/debugfs.h>
#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/of.h>
@@ -27,49 +30,97 @@
((q_spec)->offset + reg_index)
#define Q_REG_STATUS1 0x8
-#define Q_NUM_CTL_REGS 5
+#define Q_NUM_CTL_REGS 7
+
+/* type registers base address offsets */
+#define Q_REG_TYPE 0x10
+#define Q_REG_SUBTYPE 0x11
+
+/* gpio peripheral type and subtype values */
+#define Q_GPIO_TYPE 0x10
+#define Q_GPIO_SUBTYPE_GPIO_4CH 0x1
+#define Q_GPIO_SUBTYPE_GPIOC_4CH 0x5
+#define Q_GPIO_SUBTYPE_GPIO_8CH 0x9
+#define Q_GPIO_SUBTYPE_GPIOC_8CH 0xD
/* control register base address offsets */
-#define Q_REG_IO_CTL1 0x42
-#define Q_REG_INPUT_CTL1 0x43
-#define Q_REG_OUTPUT_CTL1 0x44
-#define Q_REG_OUTPUT_CTL2 0x45
-#define Q_REG_EN_CTL1 0x46
+#define Q_REG_MODE_CTL 0x40
+#define Q_REG_DIG_PULL_CTL 0x42
+#define Q_REG_DIG_IN_CTL 0x43
+#define Q_REG_DIG_VIN_CTL 0x44
+#define Q_REG_DIG_OUT_CTL 0x45
+#define Q_REG_EN_CTL 0x46
/* control register regs array indices */
-#define Q_REG_I_IO_CTL1 0
-#define Q_REG_I_INPUT_CTL1 1
-#define Q_REG_I_OUTPUT_CTL1 2
-#define Q_REG_I_OUTPUT_CTL2 3
-#define Q_REG_I_EN_CTL1 4
+#define Q_REG_I_MODE_CTL 0
+#define Q_REG_I_DIG_PULL_CTL 2
+#define Q_REG_I_DIG_IN_CTL 3
+#define Q_REG_I_DIG_VIN_CTL 4
+#define Q_REG_I_DIG_OUT_CTL 5
+#define Q_REG_I_EN_CTL 6
-/* control register configuration */
-#define Q_REG_VIN_SHIFT 0
-#define Q_REG_VIN_MASK 0x7
-#define Q_REG_PULL_SHIFT 4
-#define Q_REG_PULL_MASK 0x70
-#define Q_REG_INPUT_EN_SHIFT 7
-#define Q_REG_INPUT_EN_MASK 0x80
-#define Q_REG_OUT_STRENGTH_SHIFT 0
-#define Q_REG_OUT_STRENGTH_MASK 0x3
-#define Q_REG_OUT_TYPE_SHIFT 6
-#define Q_REG_OUT_TYPE_MASK 0x40
+/* control reg: mode */
#define Q_REG_OUT_INVERT_SHIFT 0
#define Q_REG_OUT_INVERT_MASK 0x1
#define Q_REG_SRC_SEL_SHIFT 1
#define Q_REG_SRC_SEL_MASK 0xE
-#define Q_REG_OUTPUT_EN_SHIFT 7
-#define Q_REG_OUTPUT_EN_MASK 0x80
+#define Q_REG_MODE_SEL_SHIFT 4
+#define Q_REG_MODE_SEL_MASK 0x70
+
+/* control reg: dig_vin */
+#define Q_REG_VIN_SHIFT 0
+#define Q_REG_VIN_MASK 0x7
+
+/* control reg: dig_pull */
+#define Q_REG_PULL_SHIFT 0
+#define Q_REG_PULL_MASK 0x7
+
+/* control reg: dig_out */
+#define Q_REG_OUT_STRENGTH_SHIFT 0
+#define Q_REG_OUT_STRENGTH_MASK 0x3
+#define Q_REG_OUT_TYPE_SHIFT 4
+#define Q_REG_OUT_TYPE_MASK 0x30
+
+/* control reg: en */
#define Q_REG_MASTER_EN_SHIFT 7
#define Q_REG_MASTER_EN_MASK 0x80
+enum qpnp_gpio_param_type {
+ Q_GPIO_CFG_DIRECTION,
+ Q_GPIO_CFG_OUTPUT_TYPE,
+ Q_GPIO_CFG_INVERT,
+ Q_GPIO_CFG_PULL,
+ Q_GPIO_CFG_VIN_SEL,
+ Q_GPIO_CFG_OUT_STRENGTH,
+ Q_GPIO_CFG_SRC_SELECT,
+ Q_GPIO_CFG_MASTER_EN,
+ Q_GPIO_CFG_INVALID,
+};
+
+#define Q_NUM_PARAMS Q_GPIO_CFG_INVALID
+
+/* param error checking */
+#define QPNP_GPIO_DIR_INVALID 3
+#define QPNP_GPIO_INVERT_INVALID 2
+#define QPNP_GPIO_OUT_BUF_INVALID 3
+#define QPNP_GPIO_VIN_INVALID 8
+#define QPNP_GPIO_PULL_INVALID 6
+#define QPNP_GPIO_OUT_STRENGTH_INVALID 4
+#define QPNP_GPIO_SRC_INVALID 8
+#define QPNP_GPIO_MASTER_INVALID 2
struct qpnp_gpio_spec {
uint8_t slave; /* 0-15 */
uint16_t offset; /* 0-255 */
uint32_t gpio_chip_idx; /* offset from gpio_chip base */
+ uint32_t pmic_gpio; /* PMIC gpio number */
int irq; /* logical IRQ number */
u8 regs[Q_NUM_CTL_REGS]; /* Control regs */
+ u8 type; /* peripheral type */
+ u8 subtype; /* peripheral subtype */
+ struct device_node *node;
+ enum qpnp_gpio_param_type params[Q_NUM_PARAMS];
+ struct qpnp_gpio_chip *q_chip;
};
struct qpnp_gpio_chip {
@@ -81,6 +132,7 @@
uint32_t pmic_gpio_highest;
struct device_node *int_ctrl;
struct list_head chip_list;
+ struct dentry *dfs_dir;
};
static LIST_HEAD(qpnp_gpio_chips);
@@ -121,6 +173,131 @@
q_chip->chip_gpios[chip_gpio] = spec;
}
+static int qpnp_gpio_check_config(struct qpnp_gpio_spec *q_spec,
+ struct qpnp_gpio_cfg *param)
+{
+ int gpio = q_spec->pmic_gpio;
+
+ if (param->direction >= QPNP_GPIO_DIR_INVALID)
+ pr_err("invalid direction for gpio %d\n", gpio);
+ else if (param->invert >= QPNP_GPIO_INVERT_INVALID)
+ pr_err("invalid invert polarity for gpio %d\n", gpio);
+ else if (param->src_select >= QPNP_GPIO_SRC_INVALID)
+ pr_err("invalid source select for gpio %d\n", gpio);
+ else if (param->out_strength >= QPNP_GPIO_OUT_STRENGTH_INVALID ||
+ param->out_strength == 0)
+ pr_err("invalid out strength for gpio %d\n", gpio);
+ else if (param->output_type >= QPNP_GPIO_OUT_BUF_INVALID)
+ pr_err("invalid out type for gpio %d\n", gpio);
+ else if ((param->output_type == QPNP_GPIO_OUT_BUF_OPEN_DRAIN_NMOS ||
+ param->output_type == QPNP_GPIO_OUT_BUF_OPEN_DRAIN_PMOS) &&
+ (q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_4CH ||
+ (q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_8CH)))
+ pr_err("invalid out type for gpio %d\n"
+ "gpioc does not support open-drain\n", gpio);
+ else if (param->vin_sel >= QPNP_GPIO_VIN_INVALID)
+ pr_err("invalid vin select value for gpio %d\n", gpio);
+ else if (param->pull >= QPNP_GPIO_PULL_INVALID)
+ pr_err("invalid pull value for gpio %d\n", gpio);
+ else if (param->master_en >= QPNP_GPIO_MASTER_INVALID)
+ pr_err("invalid master_en value for gpio %d\n", gpio);
+ else
+ return 0;
+
+ return -EINVAL;
+}
+
+static inline u8 q_reg_get(u8 *reg, int shift, int mask)
+{
+ return (*reg & mask) >> shift;
+}
+
+static inline void q_reg_set(u8 *reg, int shift, int mask, int value)
+{
+ *reg |= (value << shift) & mask;
+}
+
+static inline void q_reg_clr_set(u8 *reg, int shift, int mask, int value)
+{
+ *reg &= ~mask;
+ *reg |= (value << shift) & mask;
+}
+
+static int qpnp_gpio_cache_regs(struct qpnp_gpio_chip *q_chip,
+ struct qpnp_gpio_spec *q_spec)
+{
+ int rc;
+ struct device *dev = &q_chip->spmi->dev;
+
+ rc = spmi_ext_register_readl(q_chip->spmi->ctrl, q_spec->slave,
+ Q_REG_ADDR(q_spec, Q_REG_MODE_CTL),
+ &q_spec->regs[Q_REG_I_MODE_CTL],
+ Q_NUM_CTL_REGS);
+ if (rc)
+ dev_err(dev, "%s: unable to read control regs\n", __func__);
+
+ return rc;
+}
+
+static int _qpnp_gpio_config(struct qpnp_gpio_chip *q_chip,
+ struct qpnp_gpio_spec *q_spec,
+ struct qpnp_gpio_cfg *param)
+{
+ struct device *dev = &q_chip->spmi->dev;
+ int rc;
+
+ rc = qpnp_gpio_check_config(q_spec, param);
+ if (rc)
+ goto gpio_cfg;
+
+ /* set direction */
+ q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
+ Q_REG_MODE_SEL_SHIFT, Q_REG_MODE_SEL_MASK,
+ param->direction);
+
+ /* output specific configuration */
+ q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
+ Q_REG_OUT_INVERT_SHIFT, Q_REG_OUT_INVERT_MASK,
+ param->invert);
+ q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
+ Q_REG_SRC_SEL_SHIFT, Q_REG_SRC_SEL_MASK,
+ param->src_select);
+ q_reg_clr_set(&q_spec->regs[Q_REG_I_DIG_OUT_CTL],
+ Q_REG_OUT_STRENGTH_SHIFT, Q_REG_OUT_STRENGTH_MASK,
+ param->out_strength);
+ q_reg_clr_set(&q_spec->regs[Q_REG_I_DIG_OUT_CTL],
+ Q_REG_OUT_TYPE_SHIFT, Q_REG_OUT_TYPE_MASK,
+ param->output_type);
+
+ /* config applicable for both input / output */
+ q_reg_clr_set(&q_spec->regs[Q_REG_I_DIG_VIN_CTL],
+ Q_REG_VIN_SHIFT, Q_REG_VIN_MASK,
+ param->vin_sel);
+ q_reg_clr_set(&q_spec->regs[Q_REG_I_DIG_PULL_CTL],
+ Q_REG_PULL_SHIFT, Q_REG_PULL_MASK,
+ param->pull);
+ q_reg_clr_set(&q_spec->regs[Q_REG_I_EN_CTL],
+ Q_REG_MASTER_EN_SHIFT, Q_REG_MASTER_EN_MASK,
+ param->master_en);
+
+ rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
+ Q_REG_ADDR(q_spec, Q_REG_MODE_CTL),
+ &q_spec->regs[Q_REG_I_MODE_CTL], Q_NUM_CTL_REGS);
+ if (rc) {
+ dev_err(&q_chip->spmi->dev, "%s: unable to write master"
+ " enable\n", __func__);
+ goto gpio_cfg;
+ }
+
+ return 0;
+
+gpio_cfg:
+ dev_err(dev, "%s: unable to set default config for"
+ " pmic gpio %d\n", __func__, q_spec->pmic_gpio);
+
+ return rc;
+}
+
int qpnp_gpio_config(int gpio, struct qpnp_gpio_cfg *param)
{
int rc, chip_offset;
@@ -146,47 +323,8 @@
}
}
mutex_unlock(&qpnp_gpio_chips_lock);
- if (!q_spec) {
- pr_err("gpio %d not handled by any pmic\n", gpio);
- return -EINVAL;
- }
- q_spec->regs[Q_REG_I_IO_CTL1] = (param->vin_sel <<
- Q_REG_VIN_SHIFT) & Q_REG_VIN_MASK;
- q_spec->regs[Q_REG_I_IO_CTL1] |= (param->pull <<
- Q_REG_PULL_SHIFT) & Q_REG_PULL_MASK;
- q_spec->regs[Q_REG_I_INPUT_CTL1] = ((param->direction &
- QPNP_GPIO_DIR_IN) ? ((1 << Q_REG_INPUT_EN_SHIFT)) : 0);
-
- if (param->direction & QPNP_GPIO_DIR_OUT) {
- q_spec->regs[Q_REG_I_OUTPUT_CTL1] = (param->out_strength
- << Q_REG_OUT_STRENGTH_SHIFT) & Q_REG_OUT_STRENGTH_MASK;
- q_spec->regs[Q_REG_I_OUTPUT_CTL1] |= (param->output_type
- << Q_REG_OUT_TYPE_SHIFT) & Q_REG_OUT_TYPE_MASK;
- } else {
- q_spec->regs[Q_REG_I_OUTPUT_CTL1] = 0;
- }
-
- if (param->direction & QPNP_GPIO_DIR_OUT) {
- q_spec->regs[Q_REG_I_OUTPUT_CTL2] = (param->output_value
- << Q_REG_OUT_INVERT_SHIFT) & Q_REG_OUT_INVERT_MASK;
- q_spec->regs[Q_REG_I_OUTPUT_CTL2] |= (param->src_select
- << Q_REG_SRC_SEL_SHIFT) & Q_REG_SRC_SEL_MASK;
- q_spec->regs[Q_REG_I_OUTPUT_CTL2] |= (1 <<
- Q_REG_OUTPUT_EN_SHIFT) & Q_REG_OUTPUT_EN_MASK;
- } else {
- q_spec->regs[Q_REG_I_OUTPUT_CTL2] = 0;
- }
-
- q_spec->regs[Q_REG_I_EN_CTL1] = (param->master_en <<
- Q_REG_MASTER_EN_SHIFT) & Q_REG_MASTER_EN_MASK;
-
- rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
- Q_REG_ADDR(q_spec, Q_REG_IO_CTL1),
- &q_spec->regs[Q_REG_I_IO_CTL1], Q_NUM_CTL_REGS);
- if (rc)
- dev_err(&q_chip->spmi->dev, "%s: unable to write master"
- " enable\n", __func__);
+ rc = _qpnp_gpio_config(q_chip, q_spec, param);
return rc;
}
@@ -242,7 +380,8 @@
return -ENODEV;
/* gpio val is from RT status iff input is enabled */
- if (q_spec->regs[Q_REG_I_INPUT_CTL1] & Q_REG_INPUT_EN_MASK) {
+ if ((q_spec->regs[Q_REG_I_MODE_CTL] & Q_REG_MODE_SEL_MASK)
+ == QPNP_GPIO_DIR_IN) {
/* INT_RT_STS */
rc = spmi_ext_register_readl(q_chip->spmi->ctrl, q_spec->slave,
Q_REG_ADDR(q_spec, Q_REG_STATUS1),
@@ -250,7 +389,7 @@
return buf[0];
} else {
- ret_val = (q_spec->regs[Q_REG_I_OUTPUT_CTL2] &
+ ret_val = (q_spec->regs[Q_REG_I_MODE_CTL] &
Q_REG_OUT_INVERT_MASK) >> Q_REG_OUT_INVERT_SHIFT;
return ret_val;
}
@@ -266,15 +405,16 @@
if (!q_chip || !q_spec)
return -EINVAL;
- q_spec->regs[Q_REG_I_OUTPUT_CTL2] &= ~(1 << Q_REG_OUT_INVERT_SHIFT);
-
if (value)
- q_spec->regs[Q_REG_I_OUTPUT_CTL2] |=
- (1 << Q_REG_OUT_INVERT_SHIFT);
+ q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
+ Q_REG_OUT_INVERT_SHIFT, Q_REG_OUT_INVERT_MASK, 1);
+ else
+ q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
+ Q_REG_OUT_INVERT_SHIFT, Q_REG_OUT_INVERT_MASK, 0);
rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
- Q_REG_ADDR(q_spec, Q_REG_OUTPUT_CTL2),
- &q_spec->regs[Q_REG_I_OUTPUT_CTL2], 1);
+ Q_REG_ADDR(q_spec, Q_REG_I_MODE_CTL),
+ &q_spec->regs[Q_REG_I_MODE_CTL], 1);
if (rc)
dev_err(&q_chip->spmi->dev, "%s: spmi write failed\n",
__func__);
@@ -306,21 +446,19 @@
if (!q_chip || !q_spec)
return -EINVAL;
- if (direction & QPNP_GPIO_DIR_IN) {
- q_spec->regs[Q_REG_I_INPUT_CTL1] |=
- (1 << Q_REG_INPUT_EN_SHIFT);
- q_spec->regs[Q_REG_I_OUTPUT_CTL2] &=
- ~(1 << Q_REG_OUTPUT_EN_SHIFT);
- } else {
- q_spec->regs[Q_REG_I_INPUT_CTL1] &=
- ~(1 << Q_REG_INPUT_EN_SHIFT);
- q_spec->regs[Q_REG_I_OUTPUT_CTL2] |=
- (1 << Q_REG_OUTPUT_EN_SHIFT);
+ if (direction >= QPNP_GPIO_DIR_INVALID) {
+ pr_err("invalid direction specification %d\n", direction);
+ return -EINVAL;
}
+ q_reg_clr_set(&q_spec->regs[Q_REG_I_MODE_CTL],
+ Q_REG_MODE_SEL_SHIFT,
+ Q_REG_MODE_SEL_MASK,
+ direction);
+
rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
- Q_REG_ADDR(q_spec, Q_REG_INPUT_CTL1),
- &q_spec->regs[Q_REG_I_INPUT_CTL1], 3);
+ Q_REG_ADDR(q_spec, Q_REG_I_MODE_CTL),
+ &q_spec->regs[Q_REG_I_MODE_CTL], 1);
return rc;
}
@@ -374,14 +512,13 @@
u32 n = be32_to_cpup(gpio);
if (WARN_ON(gpio_chip->of_gpio_n_cells < 2)) {
- pr_err("%s: of_gpio_n_cells < 2\n", __func__);
+ pr_err("of_gpio_n_cells < 2\n");
return -EINVAL;
}
q_spec = qpnp_pmic_gpio_get_spec(q_chip, n);
if (!q_spec) {
- pr_err("%s: no such PMIC gpio %u in device topology\n",
- __func__, n);
+ pr_err("no such PMIC gpio %u in device topology\n", n);
return -EINVAL;
}
@@ -391,32 +528,54 @@
return q_spec->gpio_chip_idx;
}
-static int qpnp_gpio_config_default(struct spmi_device *spmi,
- const __be32 *prop, int gpio)
+static int qpnp_gpio_apply_config(struct qpnp_gpio_chip *q_chip,
+ struct qpnp_gpio_spec *q_spec)
{
struct qpnp_gpio_cfg param;
+ struct device_node *node = q_spec->node;
int rc;
- dev_dbg(&spmi->dev, "%s: p[0]: 0x%x p[1]: 0x%x p[2]: 0x%x p[3]:"
- " 0x%x p[4]: 0x%x p[5]: 0x%x p[6]: 0x%x p[7]: 0x%x\n", __func__,
- be32_to_cpup(&prop[0]), be32_to_cpup(&prop[1]),
- be32_to_cpup(&prop[2]), be32_to_cpup(&prop[3]),
- be32_to_cpup(&prop[4]), be32_to_cpup(&prop[5]),
- be32_to_cpup(&prop[6]), be32_to_cpup(&prop[7]));
+ param.direction = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
+ Q_REG_MODE_SEL_SHIFT,
+ Q_REG_MODE_SEL_MASK);
+ param.output_type = q_reg_get(&q_spec->regs[Q_REG_I_DIG_OUT_CTL],
+ Q_REG_OUT_TYPE_SHIFT,
+ Q_REG_OUT_TYPE_MASK);
+ param.invert = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
+ Q_REG_OUT_INVERT_MASK,
+ Q_REG_OUT_INVERT_MASK);
+ param.pull = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
+ Q_REG_PULL_SHIFT, Q_REG_PULL_MASK);
+ param.vin_sel = q_reg_get(&q_spec->regs[Q_REG_I_DIG_VIN_CTL],
+ Q_REG_VIN_SHIFT, Q_REG_VIN_MASK);
+ param.out_strength = q_reg_get(&q_spec->regs[Q_REG_I_DIG_OUT_CTL],
+ Q_REG_OUT_STRENGTH_SHIFT,
+ Q_REG_OUT_STRENGTH_MASK);
+ param.src_select = q_reg_get(&q_spec->regs[Q_REG_I_MODE_CTL],
+ Q_REG_SRC_SEL_SHIFT, Q_REG_SRC_SEL_MASK);
+ param.master_en = q_reg_get(&q_spec->regs[Q_REG_I_EN_CTL],
+ Q_REG_MASTER_EN_SHIFT,
+ Q_REG_MASTER_EN_MASK);
- param.direction = be32_to_cpup(&prop[0]);
- param.output_type = be32_to_cpup(&prop[1]);
- param.output_value = be32_to_cpup(&prop[2]);
- param.pull = be32_to_cpup(&prop[3]);
- param.vin_sel = be32_to_cpup(&prop[4]);
- param.out_strength = be32_to_cpup(&prop[5]);
- param.src_select = be32_to_cpup(&prop[6]);
- param.master_en = be32_to_cpup(&prop[7]);
+ of_property_read_u32(node, "qcom,direction",
+ ¶m.direction);
+ of_property_read_u32(node, "qcom,output-type",
+ ¶m.output_type);
+ of_property_read_u32(node, "qcom,invert",
+ ¶m.invert);
+ of_property_read_u32(node, "qcom,pull",
+ ¶m.pull);
+ of_property_read_u32(node, "qcom,vin-sel",
+ ¶m.vin_sel);
+ of_property_read_u32(node, "qcom,out-strength",
+ ¶m.out_strength);
+ of_property_read_u32(node, "qcom,src-select",
+ ¶m.src_select);
+ rc = of_property_read_u32(node, "qcom,master-en",
+ ¶m.master_en);
- rc = qpnp_gpio_config(gpio, ¶m);
- if (rc)
- dev_err(&spmi->dev, "%s: unable to set default config for"
- " gpio %d\n", __func__, gpio);
+ rc = _qpnp_gpio_config(q_chip, q_spec, ¶m);
+
return rc;
}
@@ -442,15 +601,255 @@
return rc;
}
+#ifdef CONFIG_GPIO_QPNP_DEBUG
+struct qpnp_gpio_reg {
+ uint32_t addr;
+ uint32_t idx;
+ uint32_t shift;
+ uint32_t mask;
+};
+
+static struct dentry *driver_dfs_dir;
+
+static int qpnp_gpio_reg_attr(enum qpnp_gpio_param_type type,
+ struct qpnp_gpio_reg *cfg)
+{
+ switch (type) {
+ case Q_GPIO_CFG_DIRECTION:
+ cfg->addr = Q_REG_MODE_CTL;
+ cfg->idx = Q_REG_I_MODE_CTL;
+ cfg->shift = Q_REG_MODE_SEL_SHIFT;
+ cfg->mask = Q_REG_MODE_SEL_MASK;
+ break;
+ case Q_GPIO_CFG_OUTPUT_TYPE:
+ cfg->addr = Q_REG_DIG_OUT_CTL;
+ cfg->idx = Q_REG_I_DIG_OUT_CTL;
+ cfg->shift = Q_REG_OUT_TYPE_SHIFT;
+ cfg->mask = Q_REG_OUT_TYPE_MASK;
+ break;
+ case Q_GPIO_CFG_INVERT:
+ cfg->addr = Q_REG_MODE_CTL;
+ cfg->idx = Q_REG_I_MODE_CTL;
+ cfg->shift = Q_REG_OUT_INVERT_SHIFT;
+ cfg->mask = Q_REG_OUT_INVERT_MASK;
+ break;
+ case Q_GPIO_CFG_PULL:
+ cfg->addr = Q_REG_DIG_PULL_CTL;
+ cfg->idx = Q_REG_I_DIG_PULL_CTL;
+ cfg->shift = Q_REG_PULL_SHIFT;
+ cfg->mask = Q_REG_PULL_MASK;
+ break;
+ case Q_GPIO_CFG_VIN_SEL:
+ cfg->addr = Q_REG_DIG_VIN_CTL;
+ cfg->idx = Q_REG_I_DIG_VIN_CTL;
+ cfg->shift = Q_REG_VIN_SHIFT;
+ cfg->mask = Q_REG_VIN_MASK;
+ break;
+ case Q_GPIO_CFG_OUT_STRENGTH:
+ cfg->addr = Q_REG_DIG_OUT_CTL;
+ cfg->idx = Q_REG_I_DIG_OUT_CTL;
+ cfg->shift = Q_REG_OUT_STRENGTH_SHIFT;
+ cfg->mask = Q_REG_OUT_STRENGTH_MASK;
+ break;
+ case Q_GPIO_CFG_SRC_SELECT:
+ cfg->addr = Q_REG_MODE_CTL;
+ cfg->idx = Q_REG_I_MODE_CTL;
+ cfg->shift = Q_REG_SRC_SEL_SHIFT;
+ cfg->mask = Q_REG_SRC_SEL_MASK;
+ break;
+ case Q_GPIO_CFG_MASTER_EN:
+ cfg->addr = Q_REG_EN_CTL;
+ cfg->idx = Q_REG_I_EN_CTL;
+ cfg->shift = Q_REG_MASTER_EN_SHIFT;
+ cfg->mask = Q_REG_MASTER_EN_MASK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int qpnp_gpio_debugfs_get(void *data, u64 *val)
+{
+ enum qpnp_gpio_param_type *idx = data;
+ struct qpnp_gpio_spec *q_spec;
+ struct qpnp_gpio_reg cfg = {};
+ int rc;
+
+ rc = qpnp_gpio_reg_attr(*idx, &cfg);
+ if (rc)
+ return rc;
+ q_spec = container_of(idx, struct qpnp_gpio_spec, params[*idx]);
+ *val = q_reg_get(&q_spec->regs[cfg.idx], cfg.shift, cfg.mask);
+ return 0;
+}
+
+static int qpnp_gpio_check_reg_val(enum qpnp_gpio_param_type idx,
+ struct qpnp_gpio_spec *q_spec,
+ uint32_t val)
+{
+ switch (idx) {
+ case Q_GPIO_CFG_DIRECTION:
+ if (val >= QPNP_GPIO_DIR_INVALID)
+ return -EINVAL;
+ break;
+ case Q_GPIO_CFG_OUTPUT_TYPE:
+ if ((val >= QPNP_GPIO_OUT_BUF_INVALID) ||
+ ((val == QPNP_GPIO_OUT_BUF_OPEN_DRAIN_NMOS ||
+ val == QPNP_GPIO_OUT_BUF_OPEN_DRAIN_PMOS) &&
+ (q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_4CH ||
+ (q_spec->subtype == Q_GPIO_SUBTYPE_GPIOC_8CH))))
+ return -EINVAL;
+ break;
+ case Q_GPIO_CFG_INVERT:
+ if (val >= QPNP_GPIO_INVERT_INVALID)
+ return -EINVAL;
+ break;
+ case Q_GPIO_CFG_PULL:
+ if (val >= QPNP_GPIO_PULL_INVALID)
+ return -EINVAL;
+ break;
+ case Q_GPIO_CFG_VIN_SEL:
+ if (val >= QPNP_GPIO_VIN_INVALID)
+ return -EINVAL;
+ break;
+ case Q_GPIO_CFG_OUT_STRENGTH:
+ if (val >= QPNP_GPIO_OUT_STRENGTH_INVALID ||
+ val == 0)
+ return -EINVAL;
+ break;
+ case Q_GPIO_CFG_SRC_SELECT:
+ if (val >= QPNP_GPIO_SRC_INVALID)
+ return -EINVAL;
+ break;
+ case Q_GPIO_CFG_MASTER_EN:
+ if (val >= QPNP_GPIO_MASTER_INVALID)
+ return -EINVAL;
+ break;
+ default:
+ pr_err("invalid param type %u specified\n", idx);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int qpnp_gpio_debugfs_set(void *data, u64 val)
+{
+ enum qpnp_gpio_param_type *idx = data;
+ struct qpnp_gpio_spec *q_spec;
+ struct qpnp_gpio_chip *q_chip;
+ struct qpnp_gpio_reg cfg = {};
+ int rc;
+
+ q_spec = container_of(idx, struct qpnp_gpio_spec, params[*idx]);
+ q_chip = q_spec->q_chip;
+
+ rc = qpnp_gpio_check_reg_val(*idx, q_spec, val);
+ if (rc)
+ return rc;
+
+ rc = qpnp_gpio_reg_attr(*idx, &cfg);
+ if (rc)
+ return rc;
+ q_reg_clr_set(&q_spec->regs[cfg.idx], cfg.shift, cfg.mask, val);
+ rc = spmi_ext_register_writel(q_chip->spmi->ctrl, q_spec->slave,
+ Q_REG_ADDR(q_spec, cfg.addr),
+ &q_spec->regs[cfg.idx], 1);
+
+ return rc;
+}
+DEFINE_SIMPLE_ATTRIBUTE(qpnp_gpio_fops, qpnp_gpio_debugfs_get,
+ qpnp_gpio_debugfs_set, "%llu\n");
+
+#define DEBUGFS_BUF_SIZE 11 /* supports 2^32 in decimal */
+
+struct qpnp_gpio_debugfs_args {
+ enum qpnp_gpio_param_type type;
+ const char *filename;
+};
+
+static struct qpnp_gpio_debugfs_args dfs_args[] = {
+ { Q_GPIO_CFG_DIRECTION, "direction" },
+ { Q_GPIO_CFG_OUTPUT_TYPE, "output_type" },
+ { Q_GPIO_CFG_INVERT, "invert" },
+ { Q_GPIO_CFG_PULL, "pull" },
+ { Q_GPIO_CFG_VIN_SEL, "vin_sel" },
+ { Q_GPIO_CFG_OUT_STRENGTH, "out_strength" },
+ { Q_GPIO_CFG_SRC_SELECT, "src_select" },
+ { Q_GPIO_CFG_MASTER_EN, "master_en" }
+};
+
+static int qpnp_gpio_debugfs_create(struct qpnp_gpio_chip *q_chip)
+{
+ struct spmi_device *spmi = q_chip->spmi;
+ struct device *dev = &spmi->dev;
+ struct qpnp_gpio_spec *q_spec;
+ enum qpnp_gpio_param_type *params;
+ enum qpnp_gpio_param_type type;
+ char pmic_gpio[DEBUGFS_BUF_SIZE];
+ const char *filename;
+ struct dentry *dfs, *dfs_io_dir;
+ int i, j;
+
+ BUG_ON(Q_NUM_PARAMS != ARRAY_SIZE(dfs_args));
+
+ q_chip->dfs_dir = debugfs_create_dir(dev->of_node->name,
+ driver_dfs_dir);
+ if (q_chip->dfs_dir == NULL) {
+ dev_err(dev, "%s: cannot register chip debugfs directory %s\n",
+ __func__, dev->of_node->name);
+ return -ENODEV;
+ }
+
+ for (i = 0; i < spmi->num_dev_node; i++) {
+ q_spec = qpnp_chip_gpio_get_spec(q_chip, i);
+ params = q_spec->params;
+ snprintf(pmic_gpio, DEBUGFS_BUF_SIZE, "%u", q_spec->pmic_gpio);
+ dfs_io_dir = debugfs_create_dir(pmic_gpio,
+ q_chip->dfs_dir);
+ if (dfs_io_dir == NULL)
+ goto dfs_err;
+
+ for (j = 0; j < Q_NUM_PARAMS; j++) {
+ type = dfs_args[j].type;
+ filename = dfs_args[j].filename;
+
+ params[type] = type;
+ dfs = debugfs_create_file(
+ filename,
+ S_IRUGO | S_IWUSR,
+ dfs_io_dir,
+ &q_spec->params[type],
+ &qpnp_gpio_fops);
+ if (dfs == NULL)
+ goto dfs_err;
+ }
+ }
+ return 0;
+dfs_err:
+ dev_err(dev, "%s: cannot register debugfs for pmic gpio %u on"
+ " chip %s\n", __func__,
+ q_spec->pmic_gpio, dev->of_node->name);
+ debugfs_remove_recursive(q_chip->dfs_dir);
+ return -ENFILE;
+}
+#else
+static int qpnp_gpio_debugfs_create(struct qpnp_gpio_chip *q_chip)
+{
+ return 0;
+}
+#endif
+
static int qpnp_gpio_probe(struct spmi_device *spmi)
{
struct qpnp_gpio_chip *q_chip;
struct resource *res;
struct qpnp_gpio_spec *q_spec;
- const __be32 *prop;
- int i, rc, ret, gpio, len;
- int lowest_gpio = INT_MAX, highest_gpio = INT_MIN;
- u32 intspec[3];
+ int i, rc;
+ int lowest_gpio = UINT_MAX, highest_gpio = 0;
+ u32 intspec[3], gpio;
+ char buf[2];
q_chip = kzalloc(sizeof(*q_chip), GFP_KERNEL);
if (!q_chip) {
@@ -467,21 +866,14 @@
/* first scan through nodes to find the range required for allocation */
for (i = 0; i < spmi->num_dev_node; i++) {
- prop = of_get_property(spmi->dev_node[i].of_node,
- "qcom,qpnp-gpio-num", &len);
- if (!prop) {
+ rc = of_property_read_u32(spmi->dev_node[i].of_node,
+ "qcom,gpio-num", &gpio);
+ if (rc) {
dev_err(&spmi->dev, "%s: unable to get"
- " qcom,qpnp-gpio-num property\n", __func__);
- ret = -EINVAL;
- goto err_probe;
- } else if (len != sizeof(__be32)) {
- dev_err(&spmi->dev, "%s: Invalid qcom,qpnp-gpio-num"
- " property\n", __func__);
- ret = -EINVAL;
+ " qcom,gpio-num property\n", __func__);
goto err_probe;
}
- gpio = be32_to_cpup(prop);
if (gpio < lowest_gpio)
lowest_gpio = gpio;
if (gpio > highest_gpio)
@@ -491,12 +883,12 @@
if (highest_gpio < lowest_gpio) {
dev_err(&spmi->dev, "%s: no device nodes specified in"
" topology\n", __func__);
- ret = -EINVAL;
+ rc = -EINVAL;
goto err_probe;
} else if (lowest_gpio == 0) {
dev_err(&spmi->dev, "%s: 0 is not a valid PMIC GPIO\n",
__func__);
- ret = -EINVAL;
+ rc = -EINVAL;
goto err_probe;
}
@@ -512,7 +904,7 @@
if (!q_chip->pmic_gpios || !q_chip->chip_gpios) {
dev_err(&spmi->dev, "%s: unable to allocate memory\n",
__func__);
- ret = -ENOMEM;
+ rc = -ENOMEM;
goto err_probe;
}
@@ -521,7 +913,7 @@
if (!q_chip->int_ctrl) {
dev_err(&spmi->dev, "%s: Can't find interrupt parent\n",
__func__);
- ret = -EINVAL;
+ rc = -EINVAL;
goto err_probe;
}
@@ -534,20 +926,13 @@
__func__, spmi->dev_node[i].of_node->full_name);
}
- prop = of_get_property(spmi->dev_node[i].of_node,
- "qcom,qpnp-gpio-num", &len);
- if (!prop) {
+ rc = of_property_read_u32(spmi->dev_node[i].of_node,
+ "qcom,gpio-num", &gpio);
+ if (rc) {
dev_err(&spmi->dev, "%s: unable to get"
- " qcom,qpnp-gpio-num property\n", __func__);
- ret = -EINVAL;
- goto err_probe;
- } else if (len != sizeof(__be32)) {
- dev_err(&spmi->dev, "%s: Invalid qcom,qpnp-gpio-num"
- " property\n", __func__);
- ret = -EINVAL;
+ " qcom,gpio-num property\n", __func__);
goto err_probe;
}
- gpio = be32_to_cpup(prop);
q_spec = kzalloc(sizeof(struct qpnp_gpio_spec),
GFP_KERNEL);
@@ -555,13 +940,26 @@
dev_err(&spmi->dev, "%s: unable to allocate"
" memory\n",
__func__);
- ret = -ENOMEM;
+ rc = -ENOMEM;
goto err_probe;
}
q_spec->slave = spmi->sid;
q_spec->offset = res->start;
q_spec->gpio_chip_idx = i;
+ q_spec->pmic_gpio = gpio;
+ q_spec->node = spmi->dev_node[i].of_node;
+ q_spec->q_chip = q_chip;
+
+ rc = spmi_ext_register_readl(spmi->ctrl, q_spec->slave,
+ Q_REG_ADDR(q_spec, Q_REG_TYPE), &buf[0], 2);
+ if (rc) {
+ dev_err(&spmi->dev, "%s: unable to read type regs\n",
+ __func__);
+ goto err_probe;
+ }
+ q_spec->type = buf[0];
+ q_spec->subtype = buf[1];
/* call into irq_domain to get irq mapping */
intspec[0] = q_chip->spmi->sid;
@@ -572,10 +970,10 @@
if (!q_spec->irq) {
dev_err(&spmi->dev, "%s: invalid irq for gpio"
" %u\n", __func__, gpio);
- ret = -EINVAL;
+ rc = -EINVAL;
goto err_probe;
}
- /* initialize lookup table entries */
+ /* initialize lookup table params */
qpnp_pmic_gpio_set_spec(q_chip, gpio, q_spec);
qpnp_chip_gpio_set_spec(q_chip, i, q_spec);
}
@@ -597,69 +995,49 @@
if (rc) {
dev_err(&spmi->dev, "%s: Can't add gpio chip, rc = %d\n",
__func__, rc);
- ret = rc;
goto err_probe;
}
- /* now configure gpio defaults if they exist */
+ /* now configure gpio config defaults if they exist */
for (i = 0; i < spmi->num_dev_node; i++) {
q_spec = qpnp_chip_gpio_get_spec(q_chip, i);
- if (WARN_ON(!q_spec))
- return -ENODEV;
-
- /* It's not an error to not config a default */
- prop = of_get_property(spmi->dev_node[i].of_node,
- "qcom,qpnp-gpio-cfg", &len);
- /* 8 data values constitute one tuple */
- if (prop && (len != (8 * sizeof(__be32)))) {
- dev_err(&spmi->dev, "%s: invalid format for"
- " qcom,qpnp-gpio-cfg property\n",
- __func__);
- ret = -EINVAL;
+ if (WARN_ON(!q_spec)) {
+ rc = -ENODEV;
goto err_probe;
- } else if (prop) {
- rc = qpnp_gpio_config_default(spmi, prop,
- q_chip->gpio_chip.base + i);
- if (rc) {
- ret = rc;
- goto err_probe;
- }
- } else {
- /* initialize with hardware defaults */
- rc = spmi_ext_register_readl(
- q_chip->spmi->ctrl, q_spec->slave,
- Q_REG_ADDR(q_spec, Q_REG_IO_CTL1),
- &q_spec->regs[Q_REG_I_IO_CTL1],
- Q_NUM_CTL_REGS);
- q_spec->regs[Q_REG_I_EN_CTL1] |=
- (1 << Q_REG_MASTER_EN_SHIFT);
- rc = spmi_ext_register_writel(
- q_chip->spmi->ctrl, q_spec->slave,
- Q_REG_ADDR(q_spec, Q_REG_EN_CTL1),
- &q_spec->regs[Q_REG_EN_CTL1], 1);
- if (rc) {
- dev_err(&spmi->dev, "%s: spmi write"
- " failed\n", __func__);
- ret = rc;
- goto err_probe;
- }
}
+
+ rc = qpnp_gpio_cache_regs(q_chip, q_spec);
+ if (rc)
+ goto err_probe;
+
+ rc = qpnp_gpio_apply_config(q_chip, q_spec);
+ if (rc)
+ goto err_probe;
}
dev_dbg(&spmi->dev, "%s: gpio_chip registered between %d-%u\n",
__func__, q_chip->gpio_chip.base,
(q_chip->gpio_chip.base + q_chip->gpio_chip.ngpio) - 1);
+
+ rc = qpnp_gpio_debugfs_create(q_chip);
+ if (rc) {
+ dev_err(&spmi->dev, "%s: debugfs creation failed\n", __func__);
+ goto err_probe;
+ }
+
return 0;
err_probe:
qpnp_gpio_free_chip(q_chip);
- return ret;
+ return rc;
}
static int qpnp_gpio_remove(struct spmi_device *spmi)
{
struct qpnp_gpio_chip *q_chip = dev_get_drvdata(&spmi->dev);
+ debugfs_remove_recursive(q_chip->dfs_dir);
+
return qpnp_gpio_free_chip(q_chip);
}
@@ -687,11 +1065,21 @@
static int __init qpnp_gpio_init(void)
{
+#ifdef CONFIG_GPIO_QPNP_DEBUG
+ driver_dfs_dir = debugfs_create_dir("qpnp_gpio", NULL);
+ if (driver_dfs_dir == NULL)
+ pr_err("Cannot register top level debugfs directory\n");
+#endif
+
return spmi_driver_register(&qpnp_gpio_driver);
}
static void __exit qpnp_gpio_exit(void)
{
+#ifdef CONFIG_GPIO_QPNP_DEBUG
+ debugfs_remove_recursive(driver_dfs_dir);
+#endif
+ spmi_driver_unregister(&qpnp_gpio_driver);
}
MODULE_DESCRIPTION("QPNP PMIC gpio driver");
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 00dba96..7c152721 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -263,7 +263,7 @@
*/
if (adreno_is_a3xx(adreno_dev)) {
- kgsl_mmu_device_setstate(device, flags);
+ kgsl_mmu_device_setstate(&device->mmu, flags);
return;
}
@@ -349,7 +349,7 @@
adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_PMODE,
&link[0], sizedwords);
} else {
- kgsl_mmu_device_setstate(device, flags);
+ kgsl_mmu_device_setstate(&device->mmu, flags);
}
}
@@ -575,7 +575,7 @@
}
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
- kgsl_mmu_stop(device);
+ kgsl_mmu_stop(&device->mmu);
error_clk_off:
kgsl_pwrctrl_disable(device);
@@ -590,7 +590,7 @@
adreno_ringbuffer_stop(&adreno_dev->ringbuffer);
- kgsl_mmu_stop(device);
+ kgsl_mmu_stop(&device->mmu);
device->ftbl->irqctrl(device, 0);
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 050fd83..e10edea 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1510,7 +1510,7 @@
if (context == NULL) {
/* No context - set the default apgetable and thats it */
- kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
+ kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable);
return;
}
@@ -1523,7 +1523,7 @@
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
cmds[4] = context->id;
adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE, cmds, 5);
- kgsl_mmu_setstate(device, context->pagetable);
+ kgsl_mmu_setstate(&device->mmu, context->pagetable);
#ifndef CONFIG_MSM_KGSL_CFF_DUMP_NO_CONTEXT_MEM_DUMP
kgsl_cffdump_syncmem(NULL, &context->gpustate,
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 6b58545..8c5d76a 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2257,7 +2257,7 @@
if (context == NULL) {
/* No context - set the default pagetable and thats it */
- kgsl_mmu_setstate(device, device->mmu.defaultpagetable);
+ kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable);
return;
}
@@ -2270,7 +2270,7 @@
KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context);
cmds[4] = context->id;
adreno_ringbuffer_issuecmds(device, KGSL_CMD_FLAGS_NONE, cmds, 5);
- kgsl_mmu_setstate(device, context->pagetable);
+ kgsl_mmu_setstate(&device->mmu, context->pagetable);
/*
* Restore GMEM. (note: changes shader.
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 6bdf284..9d68c60 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -661,7 +661,7 @@
kgsl_regread(device, MH_MMU_MPU_END, &r1);
kgsl_regread(device, MH_MMU_VA_RANGE, &r2);
- r3 = kgsl_mmu_get_current_ptbase(device);
+ r3 = kgsl_mmu_get_current_ptbase(&device->mmu);
KGSL_LOG_DUMP(device,
" MPU_END = %08X | VA_RANGE = %08X | PT_BASE ="
" %08X\n", r1, r2, r3);
@@ -706,7 +706,7 @@
else if (adreno_is_a3xx(adreno_dev))
adreno_dump_a3xx(device);
- pt_base = kgsl_mmu_get_current_ptbase(device);
+ pt_base = kgsl_mmu_get_current_ptbase(&device->mmu);
cur_pt_base = pt_base;
kgsl_regread(device, REG_CP_RB_BASE, &cp_rb_base);
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index fe01764..d4089b9 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -235,10 +235,8 @@
if (rb->flags & KGSL_FLAGS_STARTED)
return 0;
- if (init_ram) {
+ if (init_ram)
rb->timestamp[KGSL_MEMSTORE_GLOBAL] = 0;
- GSL_RB_INIT_TIMESTAMP(rb);
- }
kgsl_sharedmem_set(&rb->memptrs_desc, 0, 0,
sizeof(struct kgsl_rbmemptrs));
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index 7c93b3b..ae2e4c7 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -70,7 +70,6 @@
/* enable timestamp (...scratch0) memory shadowing */
#define GSL_RB_MEMPTRS_SCRATCH_MASK 0x1
-#define GSL_RB_INIT_TIMESTAMP(rb)
/* mem rptr */
#define GSL_RB_CNTL_NO_UPDATE 0x0 /* enable */
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index 2dc6f6c..a0907d7 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -531,7 +531,7 @@
int skip_pktsize = 1;
/* Get the physical address of the MMU pagetable */
- ptbase = kgsl_mmu_get_current_ptbase(device);
+ ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
/* Get the current read pointers for the RB */
kgsl_regread(device, REG_CP_RB_RPTR, &rptr);
@@ -792,7 +792,7 @@
memset(vbo, 0, sizeof(vbo));
/* Get the physical address of the MMU pagetable */
- ptbase = kgsl_mmu_get_current_ptbase(device);
+ ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
/* Dump the ringbuffer */
snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_RB,
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index 1d80a30..5a10654 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -686,12 +686,10 @@
return 0;
}
-static int kgsl_gpummu_stop(struct kgsl_mmu *mmu)
+static void kgsl_gpummu_stop(struct kgsl_mmu *mmu)
{
kgsl_regwrite(mmu->device, MH_MMU_CONFIG, 0x00000000);
mmu->flags &= ~KGSL_FLAGS_STARTED;
-
- return 0;
}
static int kgsl_gpummu_close(struct kgsl_mmu *mmu)
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index bf2a4ee..21f14ac 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -298,7 +298,7 @@
return ret;
}
-static int kgsl_iommu_stop(struct kgsl_mmu *mmu)
+static void kgsl_iommu_stop(struct kgsl_mmu *mmu)
{
/*
* stop device mmu
@@ -312,8 +312,6 @@
mmu->flags &= ~KGSL_FLAGS_STARTED;
}
-
- return 0;
}
static int kgsl_iommu_close(struct kgsl_mmu *mmu)
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 2b359ec..e11b119 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -322,16 +322,6 @@
return 0;
}
-unsigned int kgsl_mmu_get_current_ptbase(struct kgsl_device *device)
-{
- struct kgsl_mmu *mmu = &device->mmu;
- if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
- return 0;
- else
- return mmu->mmu_ops->mmu_get_current_ptbase(mmu);
-}
-EXPORT_SYMBOL(kgsl_mmu_get_current_ptbase);
-
int
kgsl_mmu_get_ptname_from_ptbase(unsigned int pt_base)
{
@@ -351,19 +341,6 @@
}
EXPORT_SYMBOL(kgsl_mmu_get_ptname_from_ptbase);
-void kgsl_mmu_setstate(struct kgsl_device *device,
- struct kgsl_pagetable *pagetable)
-{
- struct kgsl_mmu *mmu = &device->mmu;
-
- if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
- return;
- else
- mmu->mmu_ops->mmu_setstate(mmu,
- pagetable);
-}
-EXPORT_SYMBOL(kgsl_mmu_setstate);
-
int kgsl_mmu_init(struct kgsl_device *device)
{
struct kgsl_mmu *mmu = &device->mmu;
@@ -555,16 +532,6 @@
}
EXPORT_SYMBOL(kgsl_setstate);
-void kgsl_mmu_device_setstate(struct kgsl_device *device, uint32_t flags)
-{
- struct kgsl_mmu *mmu = &device->mmu;
- if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
- return;
- else if (mmu->mmu_ops->mmu_device_setstate)
- mmu->mmu_ops->mmu_device_setstate(mmu, flags);
-}
-EXPORT_SYMBOL(kgsl_mmu_device_setstate);
-
void kgsl_mh_start(struct kgsl_device *device)
{
struct kgsl_mh *mh = &device->mh;
@@ -746,17 +713,6 @@
}
EXPORT_SYMBOL(kgsl_mmu_map_global);
-int kgsl_mmu_stop(struct kgsl_device *device)
-{
- struct kgsl_mmu *mmu = &device->mmu;
-
- if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE)
- return 0;
- else
- return mmu->mmu_ops->mmu_stop(mmu);
-}
-EXPORT_SYMBOL(kgsl_mmu_stop);
-
int kgsl_mmu_close(struct kgsl_device *device)
{
struct kgsl_mmu *mmu = &device->mmu;
@@ -814,16 +770,6 @@
}
EXPORT_SYMBOL(kgsl_mmu_enabled);
-int kgsl_mmu_pt_equal(struct kgsl_pagetable *pt,
- unsigned int pt_base)
-{
- if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
- return true;
- else
- return pt->pt_ops->mmu_pt_equal(pt, pt_base);
-}
-EXPORT_SYMBOL(kgsl_mmu_pt_equal);
-
enum kgsl_mmutype kgsl_mmu_get_mmutype(void)
{
return kgsl_mmu_type;
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index e35f368..b476add 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -122,7 +122,7 @@
int (*mmu_init) (struct kgsl_mmu *mmu);
int (*mmu_close) (struct kgsl_mmu *mmu);
int (*mmu_start) (struct kgsl_mmu *mmu);
- int (*mmu_stop) (struct kgsl_mmu *mmu);
+ void (*mmu_stop) (struct kgsl_mmu *mmu);
void (*mmu_setstate) (struct kgsl_mmu *mmu,
struct kgsl_pagetable *pagetable);
void (*mmu_device_setstate) (struct kgsl_mmu *mmu,
@@ -169,7 +169,6 @@
void kgsl_mh_intrcallback(struct kgsl_device *device);
int kgsl_mmu_init(struct kgsl_device *device);
int kgsl_mmu_start(struct kgsl_device *device);
-int kgsl_mmu_stop(struct kgsl_device *device);
int kgsl_mmu_close(struct kgsl_device *device);
int kgsl_mmu_map(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc,
@@ -180,19 +179,57 @@
struct kgsl_memdesc *memdesc);
unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr);
void kgsl_setstate(struct kgsl_mmu *mmu, uint32_t flags);
-void kgsl_mmu_device_setstate(struct kgsl_device *device, uint32_t flags);
-void kgsl_mmu_setstate(struct kgsl_device *device,
- struct kgsl_pagetable *pt);
int kgsl_mmu_get_ptname_from_ptbase(unsigned int pt_base);
int kgsl_mmu_pt_get_flags(struct kgsl_pagetable *pt,
enum kgsl_deviceid id);
void kgsl_mmu_ptpool_destroy(void *ptpool);
void *kgsl_mmu_ptpool_init(int entries);
int kgsl_mmu_enabled(void);
-int kgsl_mmu_pt_equal(struct kgsl_pagetable *pt,
- unsigned int pt_base);
void kgsl_mmu_set_mmutype(char *mmutype);
-unsigned int kgsl_mmu_get_current_ptbase(struct kgsl_device *device);
enum kgsl_mmutype kgsl_mmu_get_mmutype(void);
unsigned int kgsl_mmu_get_ptsize(void);
+
+/*
+ * Static inline functions of MMU that simply call the SMMU specific
+ * function using a function pointer. These functions can be thought
+ * of as wrappers around the actual function
+ */
+
+static inline unsigned int kgsl_mmu_get_current_ptbase(struct kgsl_mmu *mmu)
+{
+ if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_current_ptbase)
+ return mmu->mmu_ops->mmu_get_current_ptbase(mmu);
+ else
+ return 0;
+}
+
+static inline void kgsl_mmu_setstate(struct kgsl_mmu *mmu,
+ struct kgsl_pagetable *pagetable)
+{
+ if (mmu->mmu_ops && mmu->mmu_ops->mmu_setstate)
+ mmu->mmu_ops->mmu_setstate(mmu, pagetable);
+}
+
+static inline void kgsl_mmu_device_setstate(struct kgsl_mmu *mmu,
+ uint32_t flags)
+{
+ if (mmu->mmu_ops && mmu->mmu_ops->mmu_device_setstate)
+ mmu->mmu_ops->mmu_device_setstate(mmu, flags);
+}
+
+static inline void kgsl_mmu_stop(struct kgsl_mmu *mmu)
+{
+ if (mmu->mmu_ops && mmu->mmu_ops->mmu_stop)
+ mmu->mmu_ops->mmu_stop(mmu);
+}
+
+static inline int kgsl_mmu_pt_equal(struct kgsl_pagetable *pt,
+ unsigned int pt_base)
+{
+ if (KGSL_MMU_TYPE_NONE == kgsl_mmu_get_mmutype())
+ return 1;
+ else
+ return pt->pt_ops->mmu_pt_equal(pt, pt_base);
+}
+
#endif /* __KGSL_MMU_H */
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 24ea571..f61c74f 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -122,7 +122,7 @@
header->current_context = -1;
/* Get the current PT base */
- header->ptbase = kgsl_mmu_get_current_ptbase(device);
+ header->ptbase = kgsl_mmu_get_current_ptbase(&device->mmu);
/* And the PID for the task leader */
pid = header->pid = kgsl_mmu_get_ptname_from_ptbase(header->ptbase);
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 3ca9e18..2df4c80 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -464,7 +464,7 @@
(ctrl & KGSL_CONTEXT_CTX_SWITCH)) {
KGSL_CMD_INFO(device, "context switch %d -> %d\n",
context->id, z180_dev->ringbuffer.prevctx);
- kgsl_mmu_setstate(device, pagetable);
+ kgsl_mmu_setstate(&device->mmu, pagetable);
cnt = PACKETSIZE_STATESTREAM;
ofs = 0;
}
@@ -613,7 +613,7 @@
del_timer_sync(&device->idle_timer);
- kgsl_mmu_stop(device);
+ kgsl_mmu_stop(&device->mmu);
/* Disable the clocks before the power rail. */
kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 60c200e..4706c1c 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -194,6 +194,18 @@
To compile this driver as a module, choose M here: the
module will be called leds-msm-pdm.
+config LEDS_PMIC_MPP
+ tristate "LED Support for Qualcomm PMIC MPP connected LEDs"
+ depends on LEDS_CLASS && MSM_SMD
+ help
+ This option enables support for LEDs connected to PMIC MPPs
+ on Qualcomm reference boards.
+
+ If unsure, say N.
+
+ To compile this driver as a module, choose M here: the
+ module will be called leds-pmic-mpp.
+
config LEDS_GPIO_PLATFORM
bool "Platform device bindings for GPIO LEDs"
depends on LEDS_GPIO
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index 819abc0..de6dcd1 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -47,6 +47,7 @@
obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o
obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o
obj-$(CONFIG_LEDS_PMIC8058) += leds-pmic8058.o
+obj-$(CONFIG_LEDS_PMIC_MPP) += leds-pmic-mpp.o
obj-$(CONFIG_LEDS_QCIBL) += leds-qci-backlight.o
obj-$(CONFIG_LEDS_MSM_PDM) += leds-msm-pdm.o
diff --git a/drivers/leds/leds-pmic-mpp.c b/drivers/leds/leds-pmic-mpp.c
new file mode 100644
index 0000000..0de41de
--- /dev/null
+++ b/drivers/leds/leds-pmic-mpp.c
@@ -0,0 +1,140 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+
+#include <mach/pmic.h>
+
+#define LED_MPP(x) ((x) & 0xFF)
+#define LED_CURR(x) ((x) >> 16)
+
+struct pmic_mpp_led_data {
+ struct led_classdev cdev;
+ int curr;
+ int mpp;
+};
+
+static void pm_mpp_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct pmic_mpp_led_data *led;
+ int ret;
+
+ led = container_of(led_cdev, struct pmic_mpp_led_data, cdev);
+
+ if (value < LED_OFF || value > led->cdev.max_brightness) {
+ dev_err(led->cdev.dev, "Invalid brightness value");
+ return;
+ }
+
+ ret = pmic_secure_mpp_config_i_sink(led->mpp, led->curr,
+ value ? PM_MPP__I_SINK__SWITCH_ENA :
+ PM_MPP__I_SINK__SWITCH_DIS);
+ if (ret)
+ dev_err(led_cdev->dev, "can't set mpp led\n");
+}
+
+static int pmic_mpp_led_probe(struct platform_device *pdev)
+{
+ const struct led_platform_data *pdata = pdev->dev.platform_data;
+ struct pmic_mpp_led_data *led, *tmp_led;
+ int i, rc;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "platform data not supplied\n");
+ return -EINVAL;
+ }
+
+ led = kcalloc(pdata->num_leds, sizeof(*led), GFP_KERNEL);
+ if (!led) {
+ dev_err(&pdev->dev, "failed to alloc memory\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(pdev, led);
+
+ for (i = 0; i < pdata->num_leds; i++) {
+ tmp_led = &led[i];
+ tmp_led->cdev.name = pdata->leds[i].name;
+ tmp_led->cdev.brightness_set = pm_mpp_led_set;
+ tmp_led->cdev.brightness = LED_OFF;
+ tmp_led->cdev.max_brightness = LED_FULL;
+ tmp_led->mpp = LED_MPP(pdata->leds[i].flags);
+ tmp_led->curr = LED_CURR(pdata->leds[i].flags);
+
+ if (tmp_led->curr < PM_MPP__I_SINK__LEVEL_5mA ||
+ tmp_led->curr > PM_MPP__I_SINK__LEVEL_40mA) {
+ dev_err(&pdev->dev, "invalid current\n");
+ goto unreg_led_cdev;
+ }
+
+ rc = led_classdev_register(&pdev->dev, &tmp_led->cdev);
+ if (rc) {
+ dev_err(&pdev->dev, "failed to register led\n");
+ goto unreg_led_cdev;
+ }
+ }
+
+ return 0;
+
+unreg_led_cdev:
+ while (i)
+ led_classdev_unregister(&led[--i].cdev);
+
+ kfree(led);
+ return rc;
+
+}
+
+static int __devexit pmic_mpp_led_remove(struct platform_device *pdev)
+{
+ const struct led_platform_data *pdata = pdev->dev.platform_data;
+ struct pmic_mpp_led_data *led = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < pdata->num_leds; i++)
+ led_classdev_unregister(&led[i].cdev);
+
+ kfree(led);
+
+ return 0;
+}
+
+static struct platform_driver pmic_mpp_led_driver = {
+ .probe = pmic_mpp_led_probe,
+ .remove = __devexit_p(pmic_mpp_led_remove),
+ .driver = {
+ .name = "pmic-mpp-leds",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init pmic_mpp_led_init(void)
+{
+ return platform_driver_register(&pmic_mpp_led_driver);
+}
+module_init(pmic_mpp_led_init);
+
+static void __exit pmic_mpp_led_exit(void)
+{
+ platform_driver_unregister(&pmic_mpp_led_driver);
+}
+module_exit(pmic_mpp_led_exit);
+
+MODULE_DESCRIPTION("PMIC MPP LEDs driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:pmic-mpp-leds");
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index a276e84..72fba82 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -963,7 +963,8 @@
opcode = hci_opcode_pack(HCI_OGF_FM_COMMON_CTRL_CMD_REQ,
HCI_OCF_FM_DEFAULT_DATA_WRITE);
- return radio_hci_send_cmd(hdev, opcode, sizeof((*def_data_wr)),
+
+ return radio_hci_send_cmd(hdev, opcode, (def_data_wr->length+2),
def_data_wr);
}
@@ -2470,7 +2471,7 @@
radio->fm_hdev);
if (retval < 0)
FMDERR("Disable Failed after calibration %d", retval);
- return retval;
+ return retval;
}
static int iris_vidioc_g_ctrl(struct file *file, void *priv,
struct v4l2_control *ctrl)
@@ -2726,10 +2727,44 @@
case V4L2_CID_PRIVATE_IRIS_WRITE_DEFAULT:
data = (ctrl->controls[0]).string;
memset(&default_data, 0, sizeof(default_data));
- if (copy_from_user(&default_data, data, sizeof(default_data)))
+ /*
+ * Check if length of the 'FM Default Data' to be sent
+ * is within the maximum 'FM Default Data' packet limit.
+ * Max. 'FM Default Data' packet length is 251 bytes:
+ * 1 byte - XFR Mode
+ * 1 byte - length of the default data
+ * 249 bytes - actual data to be configured
+ */
+ if (ctrl->controls[0].size > (DEFAULT_DATA_SIZE + 2)) {
+ pr_err("%s: Default data buffer overflow!\n", __func__);
+ return -EINVAL;
+ }
+
+ /* copy only 'size' bytes of data as requested by user */
+ retval = copy_from_user(&default_data, data,
+ ctrl->controls[0].size);
+ if (retval > 0) {
+ pr_err("%s: Failed to copy %d bytes of default data"
+ " passed by user\n", __func__, retval);
return -EFAULT;
+ }
+ FMDBG("%s: XFR Mode\t: 0x%x\n", __func__, default_data.mode);
+ FMDBG("%s: XFR Data Length\t: %d\n", __func__,
+ default_data.length);
+ /*
+ * Check if the 'length' of the actual XFR data to be configured
+ * is valid or not. Length of actual XFR data should be always
+ * 2 bytes less than the total length of the 'FM Default Data'.
+ * Length of 'FM Default Data' DEF_DATA_LEN: (1+1+XFR Data Size)
+ * Length of 'Actual XFR Data' XFR_DATA_LEN: (DEF_DATA_LEN - 2)
+ */
+ if (default_data.length != (ctrl->controls[0].size - 2)) {
+ pr_err("%s: Invalid 'length' parameter passed for "
+ "actual xfr data\n", __func__);
+ return -EINVAL;
+ }
retval = hci_def_data_write(&default_data, radio->fm_hdev);
- break;
+ break;
case V4L2_CID_PRIVATE_IRIS_SET_CALIBRATION:
data = (ctrl->controls[0]).string;
bytes_to_copy = (ctrl->controls[0]).size;
diff --git a/drivers/media/video/msm/Makefile b/drivers/media/video/msm/Makefile
index 4fd6e49..85157f7 100644
--- a/drivers/media/video/msm/Makefile
+++ b/drivers/media/video/msm/Makefile
@@ -8,6 +8,7 @@
ifeq ($(CONFIG_MSM_CAMERA_V4L2),y)
EXTRA_CFLAGS += -Idrivers/media/video/msm/csi
EXTRA_CFLAGS += -Idrivers/media/video/msm/sensors
+ EXTRA_CFLAGS += -Idrivers/media/video/msm/actuators
obj-$(CONFIG_MSM_CAMERA) += msm_isp.o msm.o msm_mem.o msm_mctl.o msm_mctl_buf.o msm_mctl_pp.o
obj-$(CONFIG_MSM_CAMERA) += sensors/ actuators/ csi/
else
diff --git a/drivers/media/video/msm/actuators/msm_actuator.c b/drivers/media/video/msm/actuators/msm_actuator.c
index e16766c..e4d8368 100644
--- a/drivers/media/video/msm/actuators/msm_actuator.c
+++ b/drivers/media/video/msm/actuators/msm_actuator.c
@@ -368,9 +368,8 @@
return rc;
}
-int32_t msm_actuator_af_power_down(void *cfg_data)
+int32_t msm_actuator_power_down(struct msm_actuator_ctrl_t *a_ctrl)
{
- struct msm_actuator_ctrl_t *a_ctrl = &msm_actuator_t;
int32_t rc = 0;
int16_t step_pos = 0;
int16_t i = 0;
@@ -501,9 +500,9 @@
}
-int32_t msm_actuator_config(void __user *argp)
+int32_t msm_actuator_config(struct msm_actuator_ctrl_t *a_ctrl,
+ void __user *argp)
{
- struct msm_actuator_ctrl_t *a_ctrl = &msm_actuator_t;
struct msm_actuator_cfg_data cdata;
int32_t rc = 0;
if (copy_from_user(&cdata,
@@ -554,13 +553,19 @@
}
act_ctrl_t = (struct msm_actuator_ctrl_t *)(id->driver_data);
- i2c_set_clientdata(client, (void *)&act_ctrl_t->actuator_ext_ctrl);
- CDBG("%s client = %x act ctrl t = %x\n",
- __func__,
- (unsigned int) client,
- (unsigned int)&act_ctrl_t->actuator_ext_ctrl);
+ CDBG("%s client = %x\n",
+ __func__, (unsigned int) client);
act_ctrl_t->i2c_client.client = client;
+ /* Assign name for sub device */
+ snprintf(act_ctrl_t->sdev.name, sizeof(act_ctrl_t->sdev.name),
+ "%s", act_ctrl_t->i2c_driver->driver.name);
+
+ /* Initialize sub device */
+ v4l2_i2c_subdev_init(&act_ctrl_t->sdev,
+ act_ctrl_t->i2c_client.client,
+ act_ctrl_t->act_v4l2_subdev_ops);
+
CDBG("%s succeeded\n", __func__);
return rc;
@@ -569,16 +574,11 @@
return rc;
}
-int32_t msm_actuator_power_up(void *act_info)
+int32_t msm_actuator_power_up(struct msm_actuator_ctrl_t *a_ctrl)
{
int rc = 0;
- struct msm_actuator_ctrl_t *a_ctrl = &msm_actuator_t;
- struct msm_actuator_info *ptr;
CDBG("%s called\n", __func__);
- ptr = act_info;
- a_ctrl->vcm_pwd = ptr->vcm_pwd;
- a_ctrl->vcm_enable = ptr->vcm_enable;
CDBG("vcm info: %x %x\n", a_ctrl->vcm_pwd,
a_ctrl->vcm_enable);
if (a_ctrl->vcm_enable) {
@@ -591,31 +591,6 @@
return rc;
}
-
-int32_t msm_actuator_create_subdevice(void *info, void *dev)
-{
- struct msm_actuator_info *act_info = (struct msm_actuator_info *)info;
- struct i2c_board_info const *board_info = act_info->board_info;
- struct v4l2_subdev *sdev = (struct v4l2_subdev *)dev;
- struct msm_actuator_ctrl_t *a_ctrl = &msm_actuator_t;
- int32_t rc = -EFAULT;
-
- CDBG("%s called\n", __func__);
-
- /* Store the sub device in actuator structure */
- a_ctrl->sdev = sdev;
-
- /* Assign name for sub device */
- snprintf(sdev->name, sizeof(sdev->name), "%s", board_info->type);
-
- /* Initialize sub device */
- v4l2_i2c_subdev_init(sdev,
- a_ctrl->i2c_client.client,
- a_ctrl->act_v4l2_subdev_ops);
-
- return rc;
-}
-
DEFINE_MUTEX(msm_actuator_mutex);
static const struct i2c_device_id msm_actuator_i2c_id[] = {
@@ -639,7 +614,41 @@
return i2c_add_driver(msm_actuator_t.i2c_driver);
}
-static struct v4l2_subdev_core_ops msm_actuator_subdev_core_ops;
+long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg)
+{
+ struct msm_actuator_ctrl_t *a_ctrl = get_actrl(sd);
+ void __user *argp = (void __user *)arg;
+ switch (cmd) {
+ case VIDIOC_MSM_ACTUATOR_CFG:
+ return msm_actuator_config(a_ctrl, argp);
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
+
+int32_t msm_actuator_power(struct v4l2_subdev *sd, int on)
+{
+ int rc = 0;
+ struct msm_actuator_ctrl_t *a_ctrl = get_actrl(sd);
+ mutex_lock(a_ctrl->actuator_mutex);
+ if (on)
+ rc = msm_actuator_power_up(a_ctrl);
+ else
+ rc = msm_actuator_power_down(a_ctrl);
+ mutex_unlock(a_ctrl->actuator_mutex);
+ return rc;
+}
+
+struct msm_actuator_ctrl_t *get_actrl(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct msm_actuator_ctrl_t, sdev);
+}
+
+static struct v4l2_subdev_core_ops msm_actuator_subdev_core_ops = {
+ .ioctl = msm_actuator_subdev_ioctl,
+ .s_power = msm_actuator_power,
+};
static struct v4l2_subdev_ops msm_actuator_subdev_ops = {
.core = &msm_actuator_subdev_core_ops,
@@ -648,12 +657,6 @@
static struct msm_actuator_ctrl_t msm_actuator_t = {
.i2c_driver = &msm_actuator_i2c_driver,
.act_v4l2_subdev_ops = &msm_actuator_subdev_ops,
- .actuator_ext_ctrl = {
- .a_power_up = msm_actuator_power_up,
- .a_create_subdevice = msm_actuator_create_subdevice,
- .a_config = msm_actuator_config,
- .a_power_down = msm_actuator_af_power_down,
- },
.curr_step_pos = 0,
.curr_region_index = 0,
diff --git a/drivers/media/video/msm/actuators/msm_actuator.h b/drivers/media/video/msm/actuators/msm_actuator.h
index 803a641b..4f936e7 100644
--- a/drivers/media/video/msm/actuators/msm_actuator.h
+++ b/drivers/media/video/msm/actuators/msm_actuator.h
@@ -51,8 +51,6 @@
struct msm_actuator_move_params_t *);
int32_t (*actuator_move_focus) (struct msm_actuator_ctrl_t *,
struct msm_actuator_move_params_t *);
- int (*actuator_power_down) (struct msm_actuator_ctrl_t *);
- int32_t (*actuator_config)(void __user *);
int32_t (*actuator_i2c_write)(struct msm_actuator_ctrl_t *,
int16_t, uint32_t);
int32_t (*actuator_write_focus)(struct msm_actuator_ctrl_t *,
@@ -71,10 +69,9 @@
struct i2c_driver *i2c_driver;
struct msm_camera_i2c_client i2c_client;
struct mutex *actuator_mutex;
- struct msm_actuator_ctrl actuator_ext_ctrl;
struct msm_actuator_func_tbl *func_tbl;
enum msm_actuator_data_type i2c_data_type;
- struct v4l2_subdev *sdev;
+ struct v4l2_subdev sdev;
struct v4l2_subdev_ops *act_v4l2_subdev_ops;
int16_t curr_step_pos;
@@ -92,6 +89,7 @@
uint16_t initial_code;
};
+struct msm_actuator_ctrl_t *get_actrl(struct v4l2_subdev *sd);
int32_t msm_actuator_i2c_write(struct msm_actuator_ctrl_t *a_ctrl,
int16_t next_lens_position, uint32_t hw_params);
int32_t msm_actuator_init_focus(struct msm_actuator_ctrl_t *a_ctrl,
@@ -100,7 +98,6 @@
int32_t msm_actuator_i2c_write_b_af(struct msm_actuator_ctrl_t *a_ctrl,
uint8_t msb,
uint8_t lsb);
-int32_t msm_actuator_config(void __user *cfg_data);
int32_t msm_actuator_move_focus(struct msm_actuator_ctrl_t *a_ctrl,
struct msm_actuator_move_params_t *move_params);
int32_t msm_actuator_piezo_move_focus(
@@ -113,7 +110,6 @@
int32_t msm_actuator_piezo_set_default_focus(
struct msm_actuator_ctrl_t *a_ctrl,
struct msm_actuator_move_params_t *move_params);
-int32_t msm_actuator_af_power_down(void *cfg_data);
int32_t msm_actuator_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id);
int32_t msm_actuator_write_focus(struct msm_actuator_ctrl_t *a_ctrl,
@@ -122,6 +118,11 @@
int32_t msm_actuator_write_focus2(struct msm_actuator_ctrl_t *a_ctrl,
uint16_t curr_lens_pos, struct damping_params_t *damping_params,
int8_t sign_direction, int16_t code_boundary);
-int32_t msm_actuator_create_subdevice(void *info, void *dev);
+long msm_actuator_subdev_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd, void *arg);
+int32_t msm_actuator_power(struct v4l2_subdev *sd, int on);
+
+#define VIDIOC_MSM_ACTUATOR_CFG \
+ _IOWR('V', BASE_VIDIOC_PRIVATE + 11, void __user *)
#endif
diff --git a/drivers/media/video/msm/csi/msm_csic.c b/drivers/media/video/msm/csi/msm_csic.c
index b4adbaf..6a5a647 100644
--- a/drivers/media/video/msm/csi/msm_csic.c
+++ b/drivers/media/video/msm/csi/msm_csic.c
@@ -379,6 +379,8 @@
.core = &msm_csic_subdev_core_ops,
};
+static const struct v4l2_subdev_internal_ops msm_csic_internal_ops;
+
static int __devinit csic_probe(struct platform_device *pdev)
{
struct csic_device *new_csic_dev;
@@ -391,6 +393,10 @@
}
v4l2_subdev_init(&new_csic_dev->subdev, &msm_csic_subdev_ops);
+ new_csic_dev->subdev.internal_ops = &msm_csic_internal_ops;
+ new_csic_dev->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ snprintf(new_csic_dev->subdev.name,
+ ARRAY_SIZE(new_csic_dev->subdev.name), "msm_csic");
v4l2_set_subdevdata(&new_csic_dev->subdev, new_csic_dev);
platform_set_drvdata(pdev, &new_csic_dev->subdev);
mutex_init(&new_csic_dev->mutex);
@@ -431,6 +437,8 @@
new_csic_dev->base = NULL;
new_csic_dev->pdev = pdev;
+ msm_cam_register_subdev_node(
+ &new_csic_dev->subdev, CSIC_DEV, pdev->id);
return 0;
csic_no_resource:
diff --git a/drivers/media/video/msm/csi/msm_csid.c b/drivers/media/video/msm/csi/msm_csid.c
index 0cd2cf0..e643def 100644
--- a/drivers/media/video/msm/csi/msm_csid.c
+++ b/drivers/media/video/msm/csi/msm_csid.c
@@ -275,6 +275,8 @@
return rc;
}
+static const struct v4l2_subdev_internal_ops msm_csid_internal_ops;
+
static struct v4l2_subdev_core_ops msm_csid_subdev_core_ops = {
.g_chip_ident = &msm_csid_subdev_g_chip_ident,
.ioctl = &msm_csid_subdev_ioctl,
@@ -296,6 +298,10 @@
}
v4l2_subdev_init(&new_csid_dev->subdev, &msm_csid_subdev_ops);
+ new_csid_dev->subdev.internal_ops = &msm_csid_internal_ops;
+ new_csid_dev->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ snprintf(new_csid_dev->subdev.name,
+ ARRAY_SIZE(new_csid_dev->subdev.name), "msm_csid");
v4l2_set_subdevdata(&new_csid_dev->subdev, new_csid_dev);
platform_set_drvdata(pdev, &new_csid_dev->subdev);
mutex_init(&new_csid_dev->mutex);
@@ -334,6 +340,7 @@
disable_irq(new_csid_dev->irq->start);
new_csid_dev->pdev = pdev;
+ msm_cam_register_subdev_node(&new_csid_dev->subdev, CSID_DEV, pdev->id);
return 0;
csid_no_resource:
diff --git a/drivers/media/video/msm/csi/msm_csiphy.c b/drivers/media/video/msm/csi/msm_csiphy.c
index aef017f..7c59ae8 100644
--- a/drivers/media/video/msm/csi/msm_csiphy.c
+++ b/drivers/media/video/msm/csi/msm_csiphy.c
@@ -263,6 +263,8 @@
return rc;
}
+static const struct v4l2_subdev_internal_ops msm_csiphy_internal_ops;
+
static struct v4l2_subdev_core_ops msm_csiphy_subdev_core_ops = {
.g_chip_ident = &msm_csiphy_subdev_g_chip_ident,
.ioctl = &msm_csiphy_subdev_ioctl,
@@ -284,6 +286,10 @@
}
v4l2_subdev_init(&new_csiphy_dev->subdev, &msm_csiphy_subdev_ops);
+ new_csiphy_dev->subdev.internal_ops = &msm_csiphy_internal_ops;
+ new_csiphy_dev->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ snprintf(new_csiphy_dev->subdev.name,
+ ARRAY_SIZE(new_csiphy_dev->subdev.name), "msm_csiphy");
v4l2_set_subdevdata(&new_csiphy_dev->subdev, new_csiphy_dev);
platform_set_drvdata(pdev, &new_csiphy_dev->subdev);
@@ -323,6 +329,8 @@
disable_irq(new_csiphy_dev->irq->start);
new_csiphy_dev->pdev = pdev;
+ msm_cam_register_subdev_node(
+ &new_csiphy_dev->subdev, CSIPHY_DEV, pdev->id);
return 0;
csiphy_no_resource:
diff --git a/drivers/media/video/msm/csi/msm_ispif.c b/drivers/media/video/msm/csi/msm_ispif.c
index cbb9e03..728e510 100644
--- a/drivers/media/video/msm/csi/msm_ispif.c
+++ b/drivers/media/video/msm/csi/msm_ispif.c
@@ -599,6 +599,8 @@
.video = &msm_ispif_subdev_video_ops,
};
+static const struct v4l2_subdev_internal_ops msm_ispif_internal_ops;
+
static int __devinit ispif_probe(struct platform_device *pdev)
{
int rc = 0;
@@ -610,6 +612,10 @@
}
v4l2_subdev_init(&ispif->subdev, &msm_ispif_subdev_ops);
+ ispif->subdev.internal_ops = &msm_ispif_internal_ops;
+ ispif->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+ snprintf(ispif->subdev.name,
+ ARRAY_SIZE(ispif->subdev.name), "msm_ispif");
v4l2_set_subdevdata(&ispif->subdev, ispif);
platform_set_drvdata(pdev, &ispif->subdev);
snprintf(ispif->subdev.name, sizeof(ispif->subdev.name),
@@ -645,6 +651,7 @@
}
ispif->pdev = pdev;
+ msm_cam_register_subdev_node(&ispif->subdev, ISPIF_DEV, pdev->id);
return 0;
ispif_no_mem:
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index ff97fa3..eff64be 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -19,7 +19,12 @@
#include <linux/spinlock.h>
#include <linux/proc_fs.h>
#include "msm.h"
+#include "msm_csid.h"
+#include "msm_csic.h"
+#include "msm_csiphy.h"
+#include "msm_ispif.h"
#include "msm_sensor.h"
+#include "msm_actuator.h"
#define MSM_MAX_CAMERA_SENSORS 5
@@ -84,7 +89,7 @@
static int32_t msm_find_free_queue(void)
{
int i;
- for (i = 0; i < NUM_SERVER_QUEUE; i++) {
+ for (i = 0; i < MAX_NUM_ACTIVE_CAMERA; i++) {
struct msm_cam_server_queue *queue;
queue = &g_server_dev.server_queue[i];
if (!queue->queue_active)
@@ -93,11 +98,50 @@
return -EINVAL;
}
+uint32_t msm_camera_get_mctl_handle(void)
+{
+ uint32_t i;
+ if ((g_server_dev.mctl_handle_cnt << 8) == 0)
+ g_server_dev.mctl_handle_cnt++;
+ for (i = 0; i < MAX_NUM_ACTIVE_CAMERA; i++) {
+ if (g_server_dev.mctl[i].handle == 0) {
+ g_server_dev.mctl[i].handle =
+ (++g_server_dev.mctl_handle_cnt) << 8 | i;
+ memset(&g_server_dev.mctl[i].mctl,
+ 0, sizeof(g_server_dev.mctl[i].mctl));
+ return g_server_dev.mctl[i].handle;
+ }
+ }
+ return 0;
+}
+
+struct msm_cam_media_controller *msm_camera_get_mctl(uint32_t handle)
+{
+ uint32_t mctl_index;
+ mctl_index = handle & 0xff;
+ if ((mctl_index < MAX_NUM_ACTIVE_CAMERA) &&
+ (g_server_dev.mctl[mctl_index].handle == handle))
+ return &g_server_dev.mctl[mctl_index].mctl;
+ return NULL;
+}
+
+void msm_camera_free_mctl(uint32_t handle)
+{
+ uint32_t mctl_index;
+ mctl_index = handle & 0xff;
+ if ((mctl_index < MAX_NUM_ACTIVE_CAMERA) &&
+ (g_server_dev.mctl[mctl_index].handle == handle))
+ g_server_dev.mctl[mctl_index].handle = 0;
+ else
+ pr_err("%s: invalid free handle\n", __func__);
+}
+
/* callback function from all subdevices of a msm_cam_v4l2_device */
static void msm_cam_v4l2_subdev_notify(struct v4l2_subdev *sd,
unsigned int notification, void *arg)
{
struct msm_cam_v4l2_device *pcam;
+ struct msm_cam_media_controller *pmctl;
if (sd == NULL)
return;
@@ -107,10 +151,9 @@
if (pcam == NULL)
return;
- /* forward to media controller for any changes*/
- if (pcam->mctl.mctl_notify) {
- pcam->mctl.mctl_notify(&pcam->mctl, notification, arg);
- }
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ if (pmctl == NULL)
+ return;
}
static int msm_ctrl_cmd_done(void *arg)
@@ -1166,6 +1209,7 @@
int rc;
/* get the video device */
struct msm_cam_v4l2_device *pcam = video_drvdata(f);
+ struct msm_cam_media_controller *pmctl;
struct msm_cam_v4l2_dev_inst *pcam_inst;
pcam_inst = container_of(f->private_data,
struct msm_cam_v4l2_dev_inst, eventHandle);
@@ -1176,8 +1220,12 @@
(void *)pfmt->fmt.pix.priv);
WARN_ON(pctx != f->private_data);
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ if (pmctl == NULL)
+ return -EINVAL;
+
if (!pcam_inst->vbqueue_initialized) {
- pcam->mctl.mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
+ pmctl->mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
V4L2_BUF_TYPE_VIDEO_CAPTURE);
pcam_inst->vbqueue_initialized = 1;
}
@@ -1199,6 +1247,7 @@
{
int rc;
struct msm_cam_v4l2_device *pcam = video_drvdata(f);
+ struct msm_cam_media_controller *pmctl;
struct msm_cam_v4l2_dev_inst *pcam_inst;
pcam_inst = container_of(f->private_data,
struct msm_cam_v4l2_dev_inst, eventHandle);
@@ -1206,8 +1255,12 @@
D("%s Inst %p\n", __func__, pcam_inst);
WARN_ON(pctx != f->private_data);
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ if (pmctl == NULL)
+ return -EINVAL;
+
if (!pcam_inst->vbqueue_initialized) {
- pcam->mctl.mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
+ pmctl->mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
pcam_inst->vbqueue_initialized = 1;
}
@@ -1443,6 +1496,8 @@
struct msm_cam_v4l2_device *pcam)
{
int rc = 0;
+ struct msm_cam_media_controller *pmctl;
+
D("%s\n", __func__);
if (!ps || !pcam) {
@@ -1465,19 +1520,13 @@
D("config pcam = 0x%p\n", ps->pcam_active);
/* initialization the media controller module*/
- msm_mctl_init_module(pcam);
+ msm_mctl_init(pcam);
- /*yyan: for single VFE msms (8660, 8960v1), just populate the session
+ /*for single VFE msms (8660, 8960v1), just populate the session
with our VFE devices that registered*/
- pcam->mctl.isp_sdev = ps->isp_subdev[0];
-
-
- /*yyan: 8960 bring up - no VPE and flash; populate later*/
- pcam->mctl.vpe_sdev = NULL;
- pcam->mctl.flash_sdev = NULL;
-
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ pmctl->isp_sdev = ps->isp_subdev[0];
return rc;
-
}
/* close an active camera session to server */
@@ -1496,6 +1545,7 @@
atomic_dec(&ps->number_pcam_active);
ps->pcam_active = NULL;
+ msm_mctl_free(pcam);
return rc;
}
/* v4l2_file_operations */
@@ -1511,6 +1561,7 @@
/* get the video device */
struct msm_cam_v4l2_device *pcam = video_drvdata(f);
struct msm_cam_v4l2_dev_inst *pcam_inst;
+ struct msm_cam_media_controller *pmctl = NULL;
D("%s\n", __func__);
@@ -1568,13 +1619,17 @@
__func__, rc);
goto err;
}
+
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- pcam->mctl.client = msm_ion_client_create(-1, "camera");
- kref_init(&pcam->mctl.refcount);
+ pmctl->client = msm_ion_client_create(-1, "camera");
+ kref_init(&pmctl->refcount);
ion_client_created = 1;
#endif
+
/* Should be set to sensor ops if any but right now its OK!! */
- if (!pcam->mctl.mctl_open) {
+ if (!pmctl->mctl_open) {
D("%s: media contoller is not inited\n",
__func__);
rc = -ENODEV;
@@ -1583,29 +1638,14 @@
/* Now we really have to activate the camera */
D("%s: call mctl_open\n", __func__);
- rc = pcam->mctl.mctl_open(&(pcam->mctl), MSM_APPS_ID_V4L2);
+ rc = pmctl->mctl_open(pmctl, MSM_APPS_ID_V4L2);
if (rc < 0) {
pr_err("%s: HW open failed rc = 0x%x\n", __func__, rc);
goto err;
}
- pcam->mctl.sync.pcam_sync = pcam;
+ pmctl->pcam_ptr = pcam;
- /* Register isp subdev */
- rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
- pcam->mctl.isp_sdev->sd);
- if (rc < 0) {
- pr_err("%s: v4l2_device_register_subdev failed rc = %d\n",
- __func__, rc);
- goto err;
- }
- if (pcam->mctl.isp_sdev->sd_vpe) {
- rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
- pcam->mctl.isp_sdev->sd_vpe);
- if (rc < 0) {
- goto err;
- }
- }
rc = msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
pcam->pvdev);
if (rc < 0) {
@@ -1639,7 +1679,7 @@
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
if (ion_client_created) {
pr_err("%s: destroy ion client", __func__);
- kref_put(&pcam->mctl.refcount, msm_release_ion_client);
+ kref_put(&pmctl->refcount, msm_release_ion_client);
}
#endif
pcam->dev_inst[i] = NULL;
@@ -1656,10 +1696,16 @@
int phyaddr;
int retval;
unsigned long size;
- struct msm_sync *sync = &pcam_inst->pcam->mctl.sync;
int rc = 0;
+ struct msm_cam_media_controller *mctl;
- rc = msm_pmem_region_get_phy_addr(&sync->pmem_stats,
+ mctl = msm_camera_get_mctl(pcam_inst->pcam->mctl_handle);
+ if (!mctl) {
+ pr_err("%s: invalid mctl pointer", __func__);
+ return -EFAULT;
+ }
+
+ rc = msm_pmem_region_get_phy_addr(&mctl->stats_info.pmem_stats_list,
&pcam_inst->mem_map,
&phyaddr);
if (rc) {
@@ -1722,6 +1768,7 @@
struct msm_cam_v4l2_device *pcam;
struct msm_cam_v4l2_dev_inst *pcam_inst;
struct msm_cam_server_queue *queue;
+ struct msm_cam_media_controller *pmctl;
pcam_inst = container_of(f->private_data,
struct msm_cam_v4l2_dev_inst, eventHandle);
pcam = pcam_inst->pcam;
@@ -1730,17 +1777,23 @@
return -EINVAL;
}
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ if (!pmctl) {
+ pr_err("%s NULL mctl pointer\n", __func__);
+ return -EINVAL;
+ }
+
mutex_lock(&pcam->vid_lock);
if (pcam_inst->streamon) {
/*something went wrong since instance
is closing without streamoff*/
- if (pcam->mctl.mctl_release) {
- rc = pcam->mctl.mctl_release(&(pcam->mctl));
+ if (pmctl->mctl_release) {
+ rc = pmctl->mctl_release(pmctl);
if (rc < 0)
pr_err("mctl_release fails %d\n", rc);
}
- pcam->mctl.mctl_release = NULL;/*so that it isn't closed again*/
+ pmctl->mctl_release = NULL;/*so that it isn't closed again*/
}
pcam_inst->streamon = 0;
@@ -1760,24 +1813,18 @@
f->private_data = NULL;
if (pcam->use_count == 0) {
- v4l2_device_unregister_subdev(pcam->mctl.isp_sdev->sd);
- v4l2_device_unregister_subdev(pcam->mctl.isp_sdev->sd_vpe);
- rc = msm_cam_server_close_session(&g_server_dev, pcam);
- if (rc < 0)
- pr_err("msm_cam_server_close_session fails %d\n", rc);
-
if (g_server_dev.use_count > 0) {
rc = msm_send_close_server(pcam);
if (rc < 0)
pr_err("msm_send_close_server failed %d\n", rc);
}
- if (pcam->mctl.mctl_release) {
- rc = pcam->mctl.mctl_release(&(pcam->mctl));
+ if (pmctl->mctl_release) {
+ rc = pmctl->mctl_release(pmctl);
if (rc < 0)
pr_err("mctl_release fails %d\n", rc);
}
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- kref_put(&pcam->mctl.refcount, msm_release_ion_client);
+ kref_put(&pmctl->refcount, msm_release_ion_client);
#endif
queue = &g_server_dev.server_queue[pcam->server_queue_idx];
queue->queue_active = 0;
@@ -1787,6 +1834,10 @@
queue->ctrl_data = NULL;
msm_queue_drain(&queue->ctrl_q, list_control);
msm_drain_eventq(&queue->eventData_q);
+ rc = msm_cam_server_close_session(&g_server_dev, pcam);
+ if (rc < 0)
+ pr_err("msm_cam_server_close_session fails %d\n", rc);
+
if (g_server_dev.use_count == 0)
mutex_unlock(&g_server_dev.server_lock);
}
@@ -2077,7 +2128,7 @@
return -EFAULT;
}
- pcam = mctl->sync.pcam_sync;
+ pcam = mctl->pcam_ptr;
ktime_get_ts(&v4l2_ev.timestamp);
v4l2_event_queue(pcam->pvdev, &v4l2_ev);
return 0;
@@ -2098,13 +2149,13 @@
/* memory management shall be handeld here*/
case MSM_CAM_IOCTL_REGISTER_PMEM:
return msm_register_pmem(
- &config_cam->p_mctl->sync.pmem_stats,
+ &config_cam->p_mctl->stats_info.pmem_stats_list,
(void __user *)arg, config_cam->p_mctl->client);
break;
case MSM_CAM_IOCTL_UNREGISTER_PMEM:
return msm_pmem_table_del(
- &config_cam->p_mctl->sync.pmem_stats,
+ &config_cam->p_mctl->stats_info.pmem_stats_list,
(void __user *)arg, config_cam->p_mctl->client);
break;
case VIDIOC_SUBSCRIBE_EVENT:
@@ -2277,7 +2328,6 @@
static int msm_open_config(struct inode *inode, struct file *fp)
{
int rc;
-
struct msm_cam_config_dev *config_cam =
container_of(inode->i_cdev, struct msm_cam_config_dev, config_cdev);
@@ -2292,10 +2342,11 @@
/*config_cam->isp_subdev = g_server_dev.pcam_active->mctl.isp_sdev;*/
/* assume there is only one active camera possible*/
- config_cam->p_mctl = &g_server_dev.pcam_active->mctl;
+ config_cam->p_mctl =
+ msm_camera_get_mctl(g_server_dev.pcam_active->mctl_handle);
- INIT_HLIST_HEAD(&config_cam->p_mctl->sync.pmem_stats);
- spin_lock_init(&config_cam->p_mctl->sync.pmem_stats_spinlock);
+ INIT_HLIST_HEAD(&config_cam->p_mctl->stats_info.pmem_stats_list);
+ spin_lock_init(&config_cam->p_mctl->stats_info.pmem_stats_spinlock);
config_cam->p_mctl->config_device = config_cam;
kref_get(&config_cam->p_mctl->refcount);
@@ -2439,6 +2490,150 @@
}
+static void msm_cam_server_subdev_notify(struct v4l2_subdev *sd,
+ unsigned int notification, void *arg)
+{
+ int rc = -EINVAL;
+ struct msm_sensor_ctrl_t *s_ctrl;
+ struct msm_camera_sensor_info *sinfo;
+ struct msm_camera_device_platform_data *camdev;
+ uint8_t csid_core = 0;
+
+ if (notification == NOTIFY_CID_CHANGE ||
+ notification == NOTIFY_ISPIF_STREAM ||
+ notification == NOTIFY_PCLK_CHANGE ||
+ notification == NOTIFY_CSIPHY_CFG ||
+ notification == NOTIFY_CSID_CFG ||
+ notification == NOTIFY_CSIC_CFG) {
+ s_ctrl = get_sctrl(sd);
+ sinfo = (struct msm_camera_sensor_info *) s_ctrl->sensordata;
+ camdev = sinfo->pdata;
+ csid_core = camdev->csid_core;
+ }
+
+ switch (notification) {
+ case NOTIFY_CID_CHANGE:
+ /* reconfig the ISPIF*/
+ if (g_server_dev.ispif_device) {
+ struct msm_ispif_params_list ispif_params;
+ ispif_params.len = 1;
+ ispif_params.params[0].intftype = PIX0;
+ ispif_params.params[0].cid_mask = 0x0001;
+ ispif_params.params[0].csid = csid_core;
+
+ rc = v4l2_subdev_call(
+ g_server_dev.ispif_device, core, ioctl,
+ VIDIOC_MSM_ISPIF_CFG, &ispif_params);
+ if (rc < 0)
+ return;
+ }
+ break;
+ case NOTIFY_ISPIF_STREAM:
+ /* call ISPIF stream on/off */
+ rc = v4l2_subdev_call(g_server_dev.ispif_device, video,
+ s_stream, (int)arg);
+ if (rc < 0)
+ return;
+
+ break;
+ case NOTIFY_ISP_MSG_EVT:
+ case NOTIFY_VFE_MSG_OUT:
+ case NOTIFY_VFE_MSG_STATS:
+ case NOTIFY_VFE_MSG_COMP_STATS:
+ case NOTIFY_VFE_BUF_EVT:
+ case NOTIFY_VFE_BUF_FREE_EVT:
+ if (g_server_dev.isp_subdev[0] &&
+ g_server_dev.isp_subdev[0]->isp_notify) {
+ rc = g_server_dev.isp_subdev[0]->isp_notify(
+ g_server_dev.vfe_device[0], notification, arg);
+ }
+ break;
+ case NOTIFY_VPE_MSG_EVT:
+ if (g_server_dev.isp_subdev[0] &&
+ g_server_dev.isp_subdev[0]->isp_notify) {
+ rc = g_server_dev.isp_subdev[0]->isp_notify(
+ g_server_dev.vpe_device[0], notification, arg);
+ }
+ break;
+ case NOTIFY_PCLK_CHANGE:
+ rc = v4l2_subdev_call(g_server_dev.vfe_device[0], video,
+ s_crystal_freq, *(uint32_t *)arg, 0);
+ break;
+ case NOTIFY_CSIPHY_CFG:
+ rc = v4l2_subdev_call(g_server_dev.csiphy_device[csid_core],
+ core, ioctl, VIDIOC_MSM_CSIPHY_CFG, arg);
+ break;
+ case NOTIFY_CSID_CFG:
+ rc = v4l2_subdev_call(g_server_dev.csid_device[csid_core],
+ core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
+ break;
+ case NOTIFY_CSIC_CFG:
+ rc = v4l2_subdev_call(g_server_dev.csic_device[csid_core],
+ core, ioctl, VIDIOC_MSM_CSIC_CFG, arg);
+ break;
+ default:
+ break;
+ }
+
+ return;
+}
+
+int msm_cam_register_subdev_node(struct v4l2_subdev *sd,
+ enum msm_cam_subdev_type sdev_type, uint8_t index)
+{
+ struct video_device *vdev;
+ int err = 0;
+
+ if (sdev_type == CSIPHY_DEV) {
+ if (index >= MAX_NUM_CSIPHY_DEV)
+ return -EINVAL;
+ g_server_dev.csiphy_device[index] = sd;
+ } else if (sdev_type == CSID_DEV) {
+ if (index >= MAX_NUM_CSID_DEV)
+ return -EINVAL;
+ g_server_dev.csid_device[index] = sd;
+ } else if (sdev_type == CSIC_DEV) {
+ if (index >= MAX_NUM_CSIC_DEV)
+ return -EINVAL;
+ g_server_dev.csic_device[index] = sd;
+ } else if (sdev_type == ISPIF_DEV) {
+ g_server_dev.ispif_device = sd;
+ } else if (sdev_type == VFE_DEV) {
+ if (index >= MAX_NUM_VFE_DEV)
+ return -EINVAL;
+ g_server_dev.vfe_device[index] = sd;
+ } else if (sdev_type == VPE_DEV) {
+ if (index >= MAX_NUM_VPE_DEV)
+ return -EINVAL;
+ g_server_dev.vpe_device[index] = sd;
+ }
+
+ err = v4l2_device_register_subdev(&g_server_dev.v4l2_dev, sd);
+ if (err < 0)
+ return err;
+
+ /* Register a device node for every subdev marked with the
+ * V4L2_SUBDEV_FL_HAS_DEVNODE flag.
+ */
+ if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
+ return err;
+
+ vdev = &sd->devnode;
+ strlcpy(vdev->name, sd->name, sizeof(vdev->name));
+ vdev->v4l2_dev = &g_server_dev.v4l2_dev;
+ vdev->fops = &v4l2_subdev_fops;
+ vdev->release = video_device_release_empty;
+ err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
+ sd->owner);
+ if (err < 0)
+ return err;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+ sd->entity.v4l.major = VIDEO_MAJOR;
+ sd->entity.v4l.minor = vdev->minor;
+#endif
+ return 0;
+}
+
static int msm_setup_server_dev(struct platform_device *pdev)
{
int rc = -ENODEV, i;
@@ -2446,7 +2641,7 @@
D("%s\n", __func__);
g_server_dev.server_pdev = pdev;
g_server_dev.v4l2_dev.dev = &pdev->dev;
-
+ g_server_dev.v4l2_dev.notify = msm_cam_server_subdev_notify;
rc = v4l2_device_register(g_server_dev.v4l2_dev.dev,
&g_server_dev.v4l2_dev);
if (rc < 0)
@@ -2496,7 +2691,7 @@
if (rc < 0)
pr_err("%s failed to initialize event queue\n", __func__);
- for (i = 0; i < NUM_SERVER_QUEUE; i++) {
+ for (i = 0; i < MAX_NUM_ACTIVE_CAMERA; i++) {
struct msm_cam_server_queue *queue;
queue = &g_server_dev.server_queue[i];
queue->queue_active = 0;
@@ -2510,7 +2705,7 @@
{
int rc = -ENOMEM;
struct video_device *pvdev = NULL;
- struct i2c_client *client = v4l2_get_subdevdata(pcam->mctl.sensor_sdev);
+ struct i2c_client *client = v4l2_get_subdevdata(pcam->sensor_sdev);
D("%s\n", __func__);
/* first register the v4l2 device */
@@ -2529,20 +2724,20 @@
return rc;
}
- strlcpy(pcam->mctl.media_dev.model, QCAMERA_NAME,
- sizeof(pcam->mctl.media_dev.model));
- pcam->mctl.media_dev.dev = &client->dev;
- rc = media_device_register(&pcam->mctl.media_dev);
+ strlcpy(pcam->media_dev.model, QCAMERA_NAME,
+ sizeof(pcam->media_dev.model));
+ pcam->media_dev.dev = &client->dev;
+ rc = media_device_register(&pcam->media_dev);
pvdev->v4l2_dev = &pcam->v4l2_dev;
- pcam->v4l2_dev.mdev = &pcam->mctl.media_dev;
+ pcam->v4l2_dev.mdev = &pcam->media_dev;
/* init video device's driver interface */
D("sensor name = %s, sizeof(pvdev->name)=%d\n",
- pcam->mctl.sensor_sdev->name, sizeof(pvdev->name));
+ pcam->sensor_sdev->name, sizeof(pvdev->name));
/* device info - strlcpy is safer than strncpy but
only if architecture supports*/
- strlcpy(pvdev->name, pcam->mctl.sensor_sdev->name, sizeof(pvdev->name));
+ strlcpy(pvdev->name, pcam->sensor_sdev->name, sizeof(pvdev->name));
pvdev->release = video_device_release;
pvdev->fops = &g_msm_fops;
@@ -2589,23 +2784,13 @@
return rc;
}
-static int msm_sync_destroy(struct msm_sync *sync)
+static struct v4l2_subdev *msm_actuator_probe(
+ struct msm_actuator_info *actuator_info)
{
- if (sync) {
- mutex_destroy(&sync->lock);
- wake_lock_destroy(&sync->wake_lock);
- }
- return 0;
-}
-
-static int msm_actuator_probe(struct msm_actuator_info *actuator_info,
- struct v4l2_subdev *act_sdev,
- struct msm_actuator_ctrl *actctrl)
-{
- int rc = 0;
+ struct v4l2_subdev *act_sdev;
struct i2c_adapter *adapter = NULL;
+ struct msm_actuator_ctrl_t *actrl;
void *act_client = NULL;
- struct msm_actuator_ctrl *a_ext_ctrl = NULL;
D("%s called\n", __func__);
@@ -2620,14 +2805,19 @@
if (!act_client)
goto device_fail;
- a_ext_ctrl = (struct msm_actuator_ctrl *)i2c_get_clientdata(act_client);
- if (!a_ext_ctrl)
+ act_sdev = (struct v4l2_subdev *)i2c_get_clientdata(act_client);
+ if (act_sdev == NULL)
goto client_fail;
- *actctrl = *a_ext_ctrl;
- a_ext_ctrl->a_create_subdevice((void *)actuator_info,
- (void *)act_sdev);
- return rc;
+ if (actuator_info->vcm_enable) {
+ actrl = get_actrl(act_sdev);
+ if (actrl) {
+ actrl->vcm_enable = actuator_info->vcm_enable;
+ actrl->vcm_pwd = actuator_info->vcm_pwd;
+ }
+ }
+
+ return act_sdev;
client_fail:
i2c_unregister_device(act_client);
@@ -2635,21 +2825,7 @@
i2c_put_adapter(adapter);
adapter = NULL;
probe_fail:
- actctrl->a_power_up = NULL;
- actctrl->a_power_down = NULL;
- actctrl->a_config = NULL;
- actctrl->a_create_subdevice = NULL;
- return rc;
-}
-
-static int msm_sync_init(struct msm_sync *sync,
- struct platform_device *pdev)
-{
- int rc = 0;
- wake_lock_init(&sync->wake_lock, WAKE_LOCK_IDLE, "msm_camera");
- sync->opencnt = 0;
- mutex_init(&sync->lock);
- return rc;
+ return NULL;
}
/* register a msm sensor into the msm device, which will probe the
@@ -2661,8 +2837,6 @@
struct msm_camera_sensor_info *sdata;
struct msm_cam_v4l2_device *pcam;
struct msm_sensor_ctrl_t *s_ctrl;
- struct v4l2_subdev *act_sdev = NULL;
- struct msm_actuator_ctrl *actctrl = NULL;
D("%s for %s\n", __func__, sensor_sd->name);
@@ -2674,34 +2848,15 @@
return -ENOMEM;
}
- pcam->mctl.sensor_sdev = sensor_sd;
+ pcam->sensor_sdev = sensor_sd;
s_ctrl = get_sctrl(sensor_sd);
sdata = (struct msm_camera_sensor_info *) s_ctrl->sensordata;
- pcam->mctl.act_sdev = kzalloc(sizeof(struct v4l2_subdev),
- GFP_KERNEL);
- if (!pcam->mctl.act_sdev) {
- pr_err("%s: could not allocate mem for actuator v4l2_subdev\n",
- __func__);
- kfree(pcam);
- return -ENOMEM;
- }
+ pcam->act_sdev = msm_actuator_probe(sdata->actuator_info);
- act_sdev = pcam->mctl.act_sdev;
- actctrl = &pcam->mctl.sync.actctrl;
-
- msm_actuator_probe(sdata->actuator_info,
- act_sdev, actctrl);
-
- /* setup a manager object*/
- rc = msm_sync_init(&pcam->mctl.sync, NULL);
- if (rc < 0)
- goto failure;
D("%s: pcam =0x%p\n", __func__, pcam);
- D("%s: &pcam->mctl.sync =0x%p\n", __func__, &pcam->mctl.sync);
- pcam->mctl.sync.sdata = sdata;
- pcam->mctl.sync.pcam_sync = pcam;
+ pcam->sdata = sdata;
/* init the user count and lock*/
pcam->use_count = 0;
@@ -2751,8 +2906,8 @@
/*Temporary solution to store info in media device structure
until we can expand media device structure to support more
device info*/
- snprintf(pcam->mctl.media_dev.serial,
- sizeof(pcam->mctl.media_dev.serial),
+ snprintf(pcam->media_dev.serial,
+ sizeof(pcam->media_dev.serial),
"%s-%d-%d", QCAMERA_NAME,
sdata->sensor_platform_info->mount_angle,
sdata->camera_type);
@@ -2765,15 +2920,16 @@
g_server_dev.camera_info.num_cameras);
/* register the subdevice, must be done for callbacks */
- rc = v4l2_device_register_subdev(&pcam->v4l2_dev, sensor_sd);
+ rc = msm_cam_register_subdev_node(sensor_sd, SENSOR_DEV, vnode_count);
if (rc < 0) {
D("%s sensor sub device register failed\n",
__func__);
goto failure;
}
- if (sdata->actuator_info) {
- rc = v4l2_device_register_subdev(&pcam->v4l2_dev, act_sdev);
+ if (pcam->act_sdev) {
+ rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
+ pcam->act_sdev);
if (rc < 0) {
D("%s actuator sub device register failed\n",
__func__);
@@ -2785,10 +2941,6 @@
return rc;
failure:
- /* mutex_destroy not needed at this moment as the associated
- implemenation of mutex_init is not consuming resources */
- msm_sync_destroy(&pcam->mctl.sync);
- kfree(act_sdev);
kzfree(pcam);
return rc;
}
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index c4373a7..77b654d 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -50,6 +50,24 @@
#define MSM_GEMINI_DRV_NAME "msm_gemini"
#define MSM_I2C_MUX_DRV_NAME "msm_cam_i2c_mux"
+#define MAX_NUM_CSIPHY_DEV 3
+#define MAX_NUM_CSID_DEV 3
+#define MAX_NUM_CSIC_DEV 3
+#define MAX_NUM_ISPIF_DEV 1
+#define MAX_NUM_VFE_DEV 2
+#define MAX_NUM_VPE_DEV 1
+
+enum msm_cam_subdev_type {
+ CSIPHY_DEV,
+ CSID_DEV,
+ CSIC_DEV,
+ ISPIF_DEV,
+ VFE_DEV,
+ VPE_DEV,
+ SENSOR_DEV,
+ ACTUATOR_DEV,
+};
+
/* msm queue management APIs*/
#define msm_dequeue(queue, member) ({ \
@@ -204,8 +222,6 @@
int (*mctl_open)(struct msm_cam_media_controller *p_mctl,
const char *const apps_id);
int (*mctl_cb)(void);
- int (*mctl_notify)(struct msm_cam_media_controller *p_mctl,
- unsigned int notification, void *arg);
int (*mctl_cmd)(struct msm_cam_media_controller *p_mctl,
unsigned int cmd, unsigned long arg);
int (*mctl_release)(struct msm_cam_media_controller *p_mctl);
@@ -214,38 +230,35 @@
struct vb2_queue *q, enum v4l2_buf_type type);
int (*mctl_ufmt_init)(struct msm_cam_media_controller *p_mctl);
- struct v4l2_fh eventHandle; /* event queue to export events */
- /* most-frequently accessed manager object*/
- struct msm_sync sync;
-
- /*Media device node*/
- struct media_device media_dev;
-
/* the following reflect the HW topology information*/
- /*mandatory*/
struct v4l2_subdev *sensor_sdev; /* sensor sub device */
- struct v4l2_subdev mctl_sdev; /* media control sub device */
- struct platform_device *plat_dev;
- /*optional*/
- struct msm_isp_ops *isp_sdev; /* isp sub device : camif/VFE */
- struct v4l2_subdev *vpe_sdev; /* vpe sub device : VPE */
- struct v4l2_subdev *flash_sdev; /* vpe sub device : VPE */
- struct msm_cam_config_dev *config_device;
+ struct v4l2_subdev *act_sdev; /* actuator sub device */
struct v4l2_subdev *csiphy_sdev; /*csiphy sub device*/
struct v4l2_subdev *csid_sdev; /*csid sub device*/
struct v4l2_subdev *csic_sdev; /*csid sub device*/
struct v4l2_subdev *ispif_sdev; /* ispif sub device */
- struct v4l2_subdev *act_sdev; /* actuator sub device */
struct v4l2_subdev *gemini_sdev; /* gemini sub device */
+ struct msm_isp_ops *isp_sdev; /* isp sub device : camif/VFE */
+ struct msm_cam_config_dev *config_device;
+
+ /*mctl session control information*/
+ uint8_t opencnt; /*mctl ref count*/
+ const char *apps_id; /*ID for app that open this session*/
+ struct mutex lock;
+ struct wake_lock wake_lock; /*avoid low power mode when active*/
struct pm_qos_request_list pm_qos_req_list;
struct msm_mctl_pp_info pp_info;
+ struct msm_mctl_stats_t stats_info; /*stats pmem info*/
+ uint32_t vfe_output_mode; /* VFE output mode */
struct ion_client *client;
struct kref refcount;
- /* VFE output mode.
- * Used to interpret the Primary/Secondary messages
- * to preview/video/main/thumbnail image types*/
- uint32_t vfe_output_mode;
+
+ /*pcam ptr*/
+ struct msm_cam_v4l2_device *pcam_ptr;
+
+ /*sensor info*/
+ struct msm_camera_sensor_info *sdata;
};
/* abstract camera device represents a VFE and connected sensor */
@@ -254,13 +267,12 @@
/*int (*isp_init)(struct msm_cam_v4l2_device *pcam);*/
int (*isp_open)(struct v4l2_subdev *sd, struct v4l2_subdev *sd_vpe,
- struct v4l2_subdev *gemini_sdev, struct msm_sync *sync);
+ struct msm_cam_media_controller *mctl);
int (*isp_config)(struct msm_cam_media_controller *pmctl,
unsigned int cmd, unsigned long arg);
int (*isp_notify)(struct v4l2_subdev *sd,
unsigned int notification, void *arg);
- void (*isp_release)(struct msm_sync *psync,
- struct v4l2_subdev *gemini_sdev);
+ void (*isp_release)(struct v4l2_subdev *sd);
int (*isp_pp_cmd)(struct msm_cam_media_controller *pmctl,
struct msm_mctl_pp_cmd, void *data);
@@ -314,57 +326,32 @@
/* abstract camera device for each sensor successfully probed*/
struct msm_cam_v4l2_device {
- /* standard device interfaces */
- /* parent of video device to trace back */
- struct device dev;
- /* sensor's platform device*/
- struct platform_device *pdev;
- /* V4l2 device */
- struct v4l2_device v4l2_dev;
- /* will be registered as /dev/video*/
- struct video_device *pvdev;
+
+ /* device node information */
+ int vnode_id;
+ struct v4l2_device v4l2_dev; /* V4l2 device */
+ struct video_device *pvdev; /* registered as /dev/video*/
+ struct msm_cam_mctl_node mctl_node; /* node for buffer management */
+ struct media_device media_dev; /* node to get video node info*/
+
+ /* device session information */
int use_count;
- /* will be used to init/release HW */
- struct msm_cam_media_controller mctl;
-
- /* parent device */
- struct device *parent_dev;
-
struct mutex vid_lock;
+ uint32_t server_queue_idx;
+ uint32_t mctl_handle;
+ struct msm_cam_v4l2_dev_inst *dev_inst[MSM_DEV_INST_MAX];
+ struct msm_cam_v4l2_dev_inst *dev_inst_map[MSM_MAX_IMG_MODE];
+ int op_mode;
+
/* v4l2 format support */
struct msm_isp_color_fmt *usr_fmts;
int num_fmts;
- /* preview or snapshot */
- u32 mode;
- u32 memsize;
- int op_mode;
- int vnode_id;
- struct msm_cam_v4l2_dev_inst *dev_inst[MSM_DEV_INST_MAX];
- struct msm_cam_v4l2_dev_inst *dev_inst_map[MSM_MAX_IMG_MODE];
- /* native config device */
- struct cdev cdev;
-
- /* The message queue is used by the control thread to send commands
- * to the config thread, and also by the HW to send messages to the
- * config thread. Thus it is the only queue that is accessed from
- * both interrupt and process context.
- */
- /* struct msm_device_queue event_q; */
-
- /* This queue used by the config thread to send responses back to the
- * control thread. It is accessed only from a process context.
- * TO BE REMOVED
- */
- uint32_t server_queue_idx;
- struct msm_device_queue ctrl_q;
-
- struct mutex lock;
- uint8_t ctrl_data[max_control_command_size];
- struct msm_ctrl_cmd ctrl;
- uint32_t event_mask;
- struct msm_cam_mctl_node mctl_node;
+ struct v4l2_subdev *sensor_sdev; /* sensor sub device */
+ struct v4l2_subdev *act_sdev; /* actuator sub device */
+ struct msm_camera_sensor_info *sdata;
};
+
static inline struct msm_cam_v4l2_device *to_pcam(
struct v4l2_device *v4l2_dev)
{
@@ -388,7 +375,7 @@
struct msm_mem_map_info mem_map;
};
-#define NUM_SERVER_QUEUE 5
+#define MAX_NUM_ACTIVE_CAMERA 2
struct msm_cam_server_queue {
uint32_t queue_active;
@@ -399,6 +386,11 @@
uint32_t evt_id;
};
+struct msm_cam_server_mctl_inst {
+ struct msm_cam_media_controller mctl;
+ uint32_t handle;
+};
+
/* abstract camera server device for all sensor successfully probed*/
struct msm_cam_server_dev {
@@ -422,9 +414,12 @@
/* This queue used by the config thread to send responses back to the
* control thread. It is accessed only from a process context.
*/
- struct msm_cam_server_queue server_queue[NUM_SERVER_QUEUE];
+ struct msm_cam_server_queue server_queue[MAX_NUM_ACTIVE_CAMERA];
uint32_t server_evt_id;
+ struct msm_cam_server_mctl_inst mctl[MAX_NUM_ACTIVE_CAMERA];
+ uint32_t mctl_handle_cnt;
+
int use_count;
/* all the registered ISP subdevice*/
struct msm_isp_ops *isp_subdev[MSM_MAX_CAMERA_CONFIGS];
@@ -432,6 +427,13 @@
struct msm_mctl_node_info mctl_node_info;
struct mutex server_lock;
struct mutex server_queue_lock;
+ /*v4l2 subdevs*/
+ struct v4l2_subdev *csiphy_device[MAX_NUM_CSIPHY_DEV];
+ struct v4l2_subdev *csid_device[MAX_NUM_CSID_DEV];
+ struct v4l2_subdev *csic_device[MAX_NUM_CSIC_DEV];
+ struct v4l2_subdev *ispif_device;
+ struct v4l2_subdev *vfe_device[MAX_NUM_VFE_DEV];
+ struct v4l2_subdev *vpe_device[MAX_NUM_VPE_DEV];
};
/* camera server related functions */
@@ -447,7 +449,8 @@
int msm_sensor_register(struct v4l2_subdev *);
int msm_isp_init_module(int g_num_config_nodes);
-int msm_mctl_init_module(struct msm_cam_v4l2_device *pcam);
+int msm_mctl_init(struct msm_cam_v4l2_device *pcam);
+int msm_mctl_free(struct msm_cam_v4l2_device *pcam);
int msm_mctl_buf_init(struct msm_cam_v4l2_device *pcam);
int msm_mctl_init_user_formats(struct msm_cam_v4l2_device *pcam);
int msm_mctl_buf_done(struct msm_cam_media_controller *pmctl,
@@ -475,22 +478,23 @@
struct msm_pmem_region *reg,
uint8_t maxcount);
unsigned long msm_pmem_stats_vtop_lookup(
- struct msm_sync *sync,
+ struct msm_cam_media_controller *mctl,
unsigned long buffer,
int fd);
-unsigned long msm_pmem_stats_ptov_lookup(struct msm_sync *sync,
- unsigned long addr, int *fd);
+unsigned long msm_pmem_stats_ptov_lookup(
+ struct msm_cam_media_controller *mctl,
+ unsigned long addr, int *fd);
-int msm_vfe_subdev_init(struct v4l2_subdev *sd, void *data,
- struct platform_device *pdev);
-void msm_vfe_subdev_release(struct platform_device *pdev);
+int msm_vfe_subdev_init(struct v4l2_subdev *sd,
+ struct msm_cam_media_controller *mctl);
+void msm_vfe_subdev_release(struct v4l2_subdev *sd);
int msm_isp_subdev_ioctl(struct v4l2_subdev *sd,
struct msm_vfe_cfg_cmd *cfgcmd, void *data);
-int msm_vpe_subdev_init(struct v4l2_subdev *sd, void *data,
- struct platform_device *pdev);
-int msm_gemini_subdev_init(struct v4l2_subdev *sd);
-void msm_vpe_subdev_release(struct platform_device *pdev);
+int msm_vpe_subdev_init(struct v4l2_subdev *sd,
+ struct msm_cam_media_controller *mctl);
+int msm_gemini_subdev_init(struct v4l2_subdev *gemini_sd);
+void msm_vpe_subdev_release(void);
void msm_gemini_subdev_release(struct v4l2_subdev *gemini_sd);
int msm_isp_subdev_ioctl_vpe(struct v4l2_subdev *isp_subdev,
struct msm_mctl_pp_cmd *cmd, void *data);
@@ -549,6 +553,11 @@
int msm_mctl_pp_mctl_divert_done(struct msm_cam_media_controller *p_mctl,
void __user *arg);
void msm_release_ion_client(struct kref *ref);
+int msm_cam_register_subdev_node(struct v4l2_subdev *sd,
+ enum msm_cam_subdev_type sdev_type, uint8_t index);
+uint32_t msm_camera_get_mctl_handle(void);
+struct msm_cam_media_controller *msm_camera_get_mctl(uint32_t handle);
+void msm_camera_free_mctl(uint32_t handle);
#endif /* __KERNEL__ */
#endif /* _MSM_H */
diff --git a/drivers/media/video/msm/msm_isp.c b/drivers/media/video/msm/msm_isp.c
index 59e37dd..9ab4895 100644
--- a/drivers/media/video/msm/msm_isp.c
+++ b/drivers/media/video/msm/msm_isp.c
@@ -150,9 +150,9 @@
struct msm_free_buf free_buf, temp_free_buf;
struct msm_camvfe_params vfe_params;
struct msm_vfe_cfg_cmd cfgcmd;
- struct msm_sync *sync =
- (struct msm_sync *)v4l2_get_subdev_hostdata(sd);
- struct msm_cam_v4l2_device *pcam = sync->pcam_sync;
+ struct msm_cam_media_controller *pmctl =
+ (struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
+ struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
int vfe_id = vdata->evt_msg.msg_id;
if (!pcam) {
@@ -161,7 +161,7 @@
return rc;
}
/* Convert the vfe msg to the image mode */
- image_mode = msm_isp_vfe_msg_to_img_mode(&pcam->mctl, vfe_id);
+ image_mode = msm_isp_vfe_msg_to_img_mode(pmctl, vfe_id);
BUG_ON(image_mode < 0);
switch (vdata->type) {
case VFE_MSG_V32_START:
@@ -169,14 +169,14 @@
case VFE_MSG_V2X_PREVIEW:
D("%s Got V32_START_*: Getting ping addr id = %d",
__func__, vfe_id);
- msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+ msm_mctl_reserve_free_buf(pmctl, NULL,
image_mode, &free_buf);
cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR;
cfgcmd.value = &vfe_id;
vfe_params.vfe_cfg = &cfgcmd;
vfe_params.data = (void *)&free_buf;
rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
- msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+ msm_mctl_reserve_free_buf(pmctl, NULL,
image_mode, &free_buf);
cfgcmd.cmd_type = CMD_CONFIG_PONG_ADDR;
cfgcmd.value = &vfe_id;
@@ -188,7 +188,7 @@
case VFE_MSG_V2X_CAPTURE:
pr_debug("%s Got V32_CAPTURE: getting buffer for id = %d",
__func__, vfe_id);
- msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+ msm_mctl_reserve_free_buf(pmctl, NULL,
image_mode, &free_buf);
cfgcmd.cmd_type = CMD_CONFIG_PING_ADDR;
cfgcmd.value = &vfe_id;
@@ -196,7 +196,7 @@
vfe_params.data = (void *)&free_buf;
rc = v4l2_subdev_call(sd, core, ioctl, 0, &vfe_params);
temp_free_buf = free_buf;
- if (msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+ if (msm_mctl_reserve_free_buf(pmctl, NULL,
image_mode, &free_buf)) {
/* Write the same buffer into PONG */
free_buf = temp_free_buf;
@@ -234,7 +234,7 @@
case VFE_MSG_OUTPUT_IRQ:
D("%s Got OUTPUT_IRQ: Getting free buf id = %d",
__func__, vfe_id);
- msm_mctl_reserve_free_buf(&pcam->mctl, NULL,
+ msm_mctl_reserve_free_buf(pmctl, NULL,
image_mode, &free_buf);
cfgcmd.cmd_type = CMD_CONFIG_FREE_BUF_ADDR;
cfgcmd.value = &vfe_id;
@@ -259,12 +259,11 @@
int rc = 0;
struct v4l2_event v4l2_evt;
struct msm_isp_event_ctrl *isp_event;
- struct msm_sync *sync =
- (struct msm_sync *)v4l2_get_subdev_hostdata(sd);
- struct msm_cam_media_controller *pmctl = &sync->pcam_sync->mctl;
+ struct msm_cam_media_controller *pmctl =
+ (struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
struct msm_free_buf buf;
- if (!sync) {
+ if (!pmctl) {
pr_err("%s: no context in dsp callback.\n", __func__);
rc = -EINVAL;
return rc;
@@ -347,17 +346,17 @@
struct msm_stats_buf *stats_buf = NULL;
isp_event->isp_data.isp_msg.msg_id = MSG_ID_STATS_COMPOSITE;
- stats->aec.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->aec.buff = msm_pmem_stats_ptov_lookup(pmctl,
stats->aec.buff, &(stats->aec.fd));
- stats->awb.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->awb.buff = msm_pmem_stats_ptov_lookup(pmctl,
stats->awb.buff, &(stats->awb.fd));
- stats->af.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->af.buff = msm_pmem_stats_ptov_lookup(pmctl,
stats->af.buff, &(stats->af.fd));
- stats->ihist.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->ihist.buff = msm_pmem_stats_ptov_lookup(pmctl,
stats->ihist.buff, &(stats->ihist.fd));
- stats->rs.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->rs.buff = msm_pmem_stats_ptov_lookup(pmctl,
stats->rs.buff, &(stats->rs.fd));
- stats->cs.buff = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats->cs.buff = msm_pmem_stats_ptov_lookup(pmctl,
stats->cs.buff, &(stats->cs.fd));
stats_buf = kmalloc(sizeof(struct msm_stats_buf), GFP_ATOMIC);
@@ -379,7 +378,7 @@
isp_event->isp_data.isp_msg.msg_id = isp_stats->id;
isp_event->isp_data.isp_msg.frame_id =
isp_stats->frameCounter;
- stats.buffer = msm_pmem_stats_ptov_lookup(&pmctl->sync,
+ stats.buffer = msm_pmem_stats_ptov_lookup(pmctl,
isp_stats->buffer,
&(stats.fd));
switch (isp_stats->id) {
@@ -450,15 +449,15 @@
static int msm_isp_notify_vpe(struct v4l2_subdev *sd, void *arg)
{
- struct msm_sync *sync =
- (struct msm_sync *)v4l2_get_subdev_hostdata(sd);
+ struct msm_cam_media_controller *pmctl =
+ (struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
struct msm_vpe_resp *vdata = (struct msm_vpe_resp *)arg;
- if (sync == NULL) {
+ if (pmctl == NULL) {
pr_err("%s: VPE subdev hostdata not set\n", __func__);
return -EINVAL;
}
- msm_mctl_pp_notify(&sync->pcam_sync->mctl,
+ msm_mctl_pp_notify(pmctl,
(struct msm_mctl_pp_frame_info *)vdata->extdata);
return 0;
}
@@ -474,25 +473,24 @@
/* This function is called by open() function, so we need to init HW*/
static int msm_isp_open(struct v4l2_subdev *sd,
- struct v4l2_subdev *sd_vpe, struct v4l2_subdev *gemini_sdev,
- struct msm_sync *sync)
+ struct v4l2_subdev *sd_vpe,
+ struct msm_cam_media_controller *mctl)
{
/* init vfe and senor, register sync callbacks for init*/
int rc = 0;
D("%s\n", __func__);
- if (!sync) {
+ if (!mctl) {
pr_err("%s: param is NULL", __func__);
return -EINVAL;
}
-
- rc = msm_vfe_subdev_init(sd, sync, sync->pdev);
+ rc = msm_vfe_subdev_init(sd, mctl);
if (rc < 0) {
pr_err("%s: vfe_init failed at %d\n",
__func__, rc);
}
D("%s: init vpe subdev", __func__);
- rc = msm_vpe_subdev_init(sd_vpe, sync, sync->pdev);
+ rc = msm_vpe_subdev_init(sd_vpe, mctl);
if (rc < 0) {
pr_err("%s: vpe_init failed at %d\n",
__func__, rc);
@@ -500,16 +498,16 @@
return rc;
}
-static void msm_isp_release(struct msm_sync *psync,
- struct v4l2_subdev *gemini_sdev)
+static void msm_isp_release(
+ struct v4l2_subdev *sd)
{
D("%s\n", __func__);
- msm_vfe_subdev_release(psync->pdev);
- msm_vpe_subdev_release(psync->pdev);
+ msm_vfe_subdev_release(sd);
+ msm_vpe_subdev_release();
}
static int msm_config_vfe(struct v4l2_subdev *sd,
- struct msm_sync *sync, void __user *arg)
+ struct msm_cam_media_controller *mctl, void __user *arg)
{
struct msm_vfe_cfg_cmd cfgcmd;
struct msm_pmem_region region[8];
@@ -525,9 +523,10 @@
switch (cfgcmd.cmd_type) {
case CMD_STATS_AF_ENABLE:
axi_data.bufnum1 =
- msm_pmem_region_lookup(&sync->pmem_stats,
- MSM_PMEM_AF, ®ion[0],
- NUM_STAT_OUTPUT_BUFFERS);
+ msm_pmem_region_lookup(
+ &mctl->stats_info.pmem_stats_list,
+ MSM_PMEM_AF, ®ion[0],
+ NUM_STAT_OUTPUT_BUFFERS);
if (!axi_data.bufnum1) {
pr_err("%s %d: pmem region lookup error\n",
__func__, __LINE__);
@@ -538,9 +537,10 @@
&axi_data);
case CMD_STATS_AEC_ENABLE:
axi_data.bufnum1 =
- msm_pmem_region_lookup(&sync->pmem_stats,
- MSM_PMEM_AEC, ®ion[0],
- NUM_STAT_OUTPUT_BUFFERS);
+ msm_pmem_region_lookup(
+ &mctl->stats_info.pmem_stats_list,
+ MSM_PMEM_AEC, ®ion[0],
+ NUM_STAT_OUTPUT_BUFFERS);
if (!axi_data.bufnum1) {
pr_err("%s %d: pmem region lookup error\n",
__func__, __LINE__);
@@ -551,9 +551,10 @@
&axi_data);
case CMD_STATS_AWB_ENABLE:
axi_data.bufnum1 =
- msm_pmem_region_lookup(&sync->pmem_stats,
- MSM_PMEM_AWB, ®ion[0],
- NUM_STAT_OUTPUT_BUFFERS);
+ msm_pmem_region_lookup(
+ &mctl->stats_info.pmem_stats_list,
+ MSM_PMEM_AWB, ®ion[0],
+ NUM_STAT_OUTPUT_BUFFERS);
if (!axi_data.bufnum1) {
pr_err("%s %d: pmem region lookup error\n",
__func__, __LINE__);
@@ -564,9 +565,10 @@
&axi_data);
case CMD_STATS_AEC_AWB_ENABLE:
axi_data.bufnum1 =
- msm_pmem_region_lookup(&sync->pmem_stats,
- MSM_PMEM_AEC_AWB, ®ion[0],
- NUM_STAT_OUTPUT_BUFFERS);
+ msm_pmem_region_lookup(
+ &mctl->stats_info.pmem_stats_list,
+ MSM_PMEM_AEC_AWB, ®ion[0],
+ NUM_STAT_OUTPUT_BUFFERS);
if (!axi_data.bufnum1) {
pr_err("%s %d: pmem region lookup error\n",
__func__, __LINE__);
@@ -577,9 +579,10 @@
&axi_data);
case CMD_STATS_IHIST_ENABLE:
axi_data.bufnum1 =
- msm_pmem_region_lookup(&sync->pmem_stats,
- MSM_PMEM_IHIST, ®ion[0],
- NUM_STAT_OUTPUT_BUFFERS);
+ msm_pmem_region_lookup(
+ &mctl->stats_info.pmem_stats_list,
+ MSM_PMEM_IHIST, ®ion[0],
+ NUM_STAT_OUTPUT_BUFFERS);
if (!axi_data.bufnum1) {
pr_err("%s %d: pmem region lookup error\n",
__func__, __LINE__);
@@ -590,9 +593,10 @@
&axi_data);
case CMD_STATS_RS_ENABLE:
axi_data.bufnum1 =
- msm_pmem_region_lookup(&sync->pmem_stats,
- MSM_PMEM_RS, ®ion[0],
- NUM_STAT_OUTPUT_BUFFERS);
+ msm_pmem_region_lookup(
+ &mctl->stats_info.pmem_stats_list,
+ MSM_PMEM_RS, ®ion[0],
+ NUM_STAT_OUTPUT_BUFFERS);
if (!axi_data.bufnum1) {
pr_err("%s %d: pmem region lookup error\n",
__func__, __LINE__);
@@ -603,9 +607,10 @@
&axi_data);
case CMD_STATS_CS_ENABLE:
axi_data.bufnum1 =
- msm_pmem_region_lookup(&sync->pmem_stats,
- MSM_PMEM_CS, ®ion[0],
- NUM_STAT_OUTPUT_BUFFERS);
+ msm_pmem_region_lookup(
+ &mctl->stats_info.pmem_stats_list,
+ MSM_PMEM_CS, ®ion[0],
+ NUM_STAT_OUTPUT_BUFFERS);
if (!axi_data.bufnum1) {
pr_err("%s %d: pmem region lookup error\n",
__func__, __LINE__);
@@ -626,51 +631,8 @@
return -EINVAL;
}
-static int msm_vpe_frame_cfg(struct msm_sync *sync,
- void *cfgcmdin)
-{
- int rc = -EIO;
- struct axidata axi_data;
- void *data = &axi_data;
- struct msm_pmem_region region[8];
- int pmem_type;
-
- struct msm_vpe_cfg_cmd *cfgcmd;
- cfgcmd = (struct msm_vpe_cfg_cmd *)cfgcmdin;
-
- memset(&axi_data, 0, sizeof(axi_data));
- CDBG("In vpe_frame_cfg cfgcmd->cmd_type = %d\n",
- cfgcmd->cmd_type);
- switch (cfgcmd->cmd_type) {
- case CMD_AXI_CFG_VPE:
- pmem_type = MSM_PMEM_VIDEO_VPE;
- axi_data.bufnum1 =
- msm_pmem_region_lookup_2(&sync->pmem_frames, pmem_type,
- ®ion[0], 8);
- CDBG("axi_data.bufnum1 = %d\n", axi_data.bufnum1);
- if (!axi_data.bufnum1) {
- pr_err("%s %d: pmem region lookup error\n",
- __func__, __LINE__);
- return -EINVAL;
- }
- pmem_type = MSM_PMEM_VIDEO;
- break;
- default:
- pr_err("%s: unknown command type %d\n",
- __func__, cfgcmd->cmd_type);
- break;
- }
- axi_data.region = ®ion[0];
- CDBG("out vpe_frame_cfg cfgcmd->cmd_type = %d\n",
- cfgcmd->cmd_type);
- /* send the AXI configuration command to driver */
- if (sync->vpefn.vpe_config)
- rc = sync->vpefn.vpe_config(cfgcmd, data);
- return rc;
-}
-
static int msm_stats_axi_cfg(struct v4l2_subdev *sd,
- struct msm_sync *sync, struct msm_vfe_cfg_cmd *cfgcmd)
+ struct msm_cam_media_controller *mctl, struct msm_vfe_cfg_cmd *cfgcmd)
{
int rc = -EIO;
struct axidata axi_data;
@@ -695,7 +657,8 @@
if (cfgcmd->cmd_type != CMD_GENERAL) {
axi_data.bufnum1 =
- msm_pmem_region_lookup(&sync->pmem_stats, pmem_type,
+ msm_pmem_region_lookup(
+ &mctl->stats_info.pmem_stats_list, pmem_type,
®ion[0], NUM_STAT_OUTPUT_BUFFERS);
if (!axi_data.bufnum1) {
pr_err("%s %d: pmem region lookup error\n",
@@ -711,7 +674,7 @@
}
static int msm_axi_config(struct v4l2_subdev *sd,
- struct msm_sync *sync, void __user *arg)
+ struct msm_cam_media_controller *mctl, void __user *arg)
{
struct msm_vfe_cfg_cmd cfgcmd;
@@ -739,13 +702,10 @@
* controller free queue.
*/
return msm_isp_subdev_ioctl(sd, &cfgcmd, NULL);
- case CMD_AXI_CFG_VPE:
- return 0;
- return msm_vpe_frame_cfg(sync, (void *)&cfgcmd);
case CMD_STATS_AXI_CFG:
case CMD_STATS_AF_AXI_CFG:
- return msm_stats_axi_cfg(sd, sync, &cfgcmd);
+ return msm_stats_axi_cfg(sd, mctl, &cfgcmd);
default:
pr_err("%s: unknown command type %d\n",
@@ -757,39 +717,8 @@
return 0;
}
-static int msm_set_crop(struct msm_sync *sync, void __user *arg)
-{
- struct crop_info crop;
-
- if (copy_from_user(&crop,
- arg,
- sizeof(struct crop_info))) {
- ERR_COPY_FROM_USER();
- return -EFAULT;
- }
-
- if (!sync->croplen) {
- sync->cropinfo = kmalloc(crop.len, GFP_KERNEL);
- if (!sync->cropinfo)
- return -ENOMEM;
- } else if (sync->croplen < crop.len)
- return -EINVAL;
-
- if (copy_from_user(sync->cropinfo,
- crop.info,
- crop.len)) {
- ERR_COPY_FROM_USER();
- kfree(sync->cropinfo);
- return -EFAULT;
- }
-
- sync->croplen = crop.len;
-
- return 0;
-}
-
static int msm_put_stats_buffer(struct v4l2_subdev *sd,
- struct msm_sync *sync, void __user *arg)
+ struct msm_cam_media_controller *mctl, void __user *arg)
{
int rc = -EIO;
@@ -804,7 +733,7 @@
}
CDBG("%s\n", __func__);
- pphy = msm_pmem_stats_vtop_lookup(sync, buf.buffer, buf.fd);
+ pphy = msm_pmem_stats_vtop_lookup(mctl, buf.buffer, buf.fd);
if (pphy != 0) {
if (buf.type == STAT_AF)
@@ -862,7 +791,7 @@
case MSM_CAM_IOCTL_CONFIG_VFE:
/* Coming from config thread for update */
- rc = msm_config_vfe(sd, &pmctl->sync, argp);
+ rc = msm_config_vfe(sd, pmctl, argp);
break;
case MSM_CAM_IOCTL_CONFIG_VPE:
@@ -874,15 +803,11 @@
case MSM_CAM_IOCTL_AXI_CONFIG:
case MSM_CAM_IOCTL_AXI_VPE_CONFIG:
D("Received MSM_CAM_IOCTL_AXI_CONFIG\n");
- rc = msm_axi_config(sd, &pmctl->sync, argp);
- break;
-
- case MSM_CAM_IOCTL_SET_CROP:
- rc = msm_set_crop(&pmctl->sync, argp);
+ rc = msm_axi_config(sd, pmctl, argp);
break;
case MSM_CAM_IOCTL_RELEASE_STATS_BUFFER:
- rc = msm_put_stats_buffer(sd, &pmctl->sync, argp);
+ rc = msm_put_stats_buffer(sd, pmctl, argp);
break;
default:
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 37a1ff2..1f6f32a 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -33,6 +33,7 @@
#include "msm_csiphy.h"
#include "msm_ispif.h"
#include "msm_sensor.h"
+#include "msm_actuator.h"
#ifdef CONFIG_MSM_CAMERA_DEBUG
#define D(fmt, args...) pr_debug("msm_mctl: " fmt, ##args)
@@ -127,57 +128,14 @@
};
-/*
- * V4l2 subdevice operations
- */
-static int mctl_subdev_log_status(struct v4l2_subdev *sd)
-{
- return -EINVAL;
-}
-
-static long mctl_subdev_ioctl(struct v4l2_subdev *sd,
- unsigned int cmd, void *arg)
-{
- struct msm_cam_media_controller *pmctl = NULL;
- if (!sd) {
- pr_err("%s: param is NULL", __func__);
- return -EINVAL;
- } else
- pmctl = (struct msm_cam_media_controller *)
- v4l2_get_subdevdata(sd);
-
-
- return -EINVAL;
-}
-
-
-static int mctl_subdev_g_mbus_fmt(struct v4l2_subdev *sd,
- struct v4l2_mbus_framefmt *mf)
-{
- return -EINVAL;
-}
-
-static struct v4l2_subdev_core_ops mctl_subdev_core_ops = {
- .log_status = mctl_subdev_log_status,
- .ioctl = mctl_subdev_ioctl,
-};
-
-static struct v4l2_subdev_video_ops mctl_subdev_video_ops = {
- .g_mbus_fmt = mctl_subdev_g_mbus_fmt,
-};
-
-static struct v4l2_subdev_ops mctl_subdev_ops = {
- .core = &mctl_subdev_core_ops,
- .video = &mctl_subdev_video_ops,
-};
-
-static int msm_get_sensor_info(struct msm_sync *sync,
- void __user *arg)
+static int msm_get_sensor_info(
+ struct msm_cam_media_controller *mctl,
+ void __user *arg)
{
int rc = 0;
struct msm_camsensor_info info;
struct msm_camera_sensor_info *sdata;
- struct msm_cam_v4l2_device *pcam = sync->pcam_sync;
+ struct msm_cam_v4l2_device *pcam = mctl->pcam_ptr;
if (copy_from_user(&info,
arg,
sizeof(struct msm_camsensor_info))) {
@@ -185,7 +143,7 @@
return -EFAULT;
}
- sdata = sync->sdata;
+ sdata = mctl->sdata;
D("%s: sensor_name %s\n", __func__, sdata->sensor_name);
memcpy(&info.name[0], sdata->sensor_name, MAX_SENSOR_NAME);
@@ -209,110 +167,6 @@
return rc;
}
-/* called by other subdev to notify any changes*/
-
-static int msm_mctl_notify(struct msm_cam_media_controller *p_mctl,
- unsigned int notification, void *arg)
-{
- int rc = -EINVAL;
- struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(p_mctl->sensor_sdev);
- struct msm_camera_sensor_info *sinfo =
- (struct msm_camera_sensor_info *) s_ctrl->sensordata;
- struct msm_camera_device_platform_data *camdev = sinfo->pdata;
- uint8_t csid_core = camdev->csid_core;
- switch (notification) {
- case NOTIFY_CID_CHANGE:
- /* reconfig the ISPIF*/
- if (p_mctl->ispif_sdev) {
- struct msm_ispif_params_list ispif_params;
- ispif_params.len = 1;
- ispif_params.params[0].intftype = PIX0;
- ispif_params.params[0].cid_mask = 0x0001;
- ispif_params.params[0].csid = csid_core;
-
- rc = v4l2_subdev_call(p_mctl->ispif_sdev, core, ioctl,
- VIDIOC_MSM_ISPIF_CFG, &ispif_params);
- } else {
- pr_err("%s: invalid ispif_sdev\n", __func__);
- }
- break;
- case NOTIFY_ISPIF_STREAM:
- /* call ISPIF stream on/off */
- if (p_mctl->ispif_sdev) {
- rc = v4l2_subdev_call(p_mctl->ispif_sdev, video,
- s_stream, (int)arg);
- } else {
- pr_err("%s: invalid ispif_sdev\n", __func__);
- }
-
- break;
- case NOTIFY_ISP_MSG_EVT:
- case NOTIFY_VFE_MSG_OUT:
- case NOTIFY_VFE_MSG_STATS:
- case NOTIFY_VFE_MSG_COMP_STATS:
- case NOTIFY_VFE_BUF_EVT:
- case NOTIFY_VFE_BUF_FREE_EVT:
- if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
- rc = p_mctl->isp_sdev->isp_notify(
- p_mctl->isp_sdev->sd, notification, arg);
- } else {
- pr_err("%s: invalid isp_sdev\n", __func__);
- }
-
- break;
- case NOTIFY_VPE_MSG_EVT:
- if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_notify) {
- rc = p_mctl->isp_sdev->isp_notify(
- p_mctl->isp_sdev->sd_vpe, notification, arg);
- } else {
- pr_err("%s: invalid isp_sdev\n", __func__);
- }
-
- break;
- case NOTIFY_PCLK_CHANGE:
- if (p_mctl->isp_sdev && p_mctl->isp_sdev->sd) {
- rc = v4l2_subdev_call(p_mctl->isp_sdev->sd, video,
- s_crystal_freq, *(uint32_t *)arg, 0);
- } else {
- pr_err("%s: invalid ispif_sdev\n", __func__);
- }
-
- break;
- case NOTIFY_CSIPHY_CFG:
- if (p_mctl->csiphy_sdev) {
- rc = v4l2_subdev_call(p_mctl->csiphy_sdev,
- core, ioctl, VIDIOC_MSM_CSIPHY_CFG,
- arg);
- } else {
- pr_err("%s: invalid csiphy_sdev\n", __func__);
- }
-
- break;
- case NOTIFY_CSID_CFG:
- if (p_mctl->csid_sdev) {
- rc = v4l2_subdev_call(p_mctl->csid_sdev,
- core, ioctl, VIDIOC_MSM_CSID_CFG, arg);
- } else {
- pr_err("%s: invalid csid_sdev\n", __func__);
- }
-
- break;
- case NOTIFY_CSIC_CFG:
- if (p_mctl->csic_sdev) {
- rc = v4l2_subdev_call(p_mctl->csic_sdev,
- core, ioctl, VIDIOC_MSM_CSIC_CFG, arg);
- } else {
- pr_err("%s: invalid csic_sdev\n", __func__);
- }
-
- break;
- default:
- break;
- }
-
- return rc;
-}
-
static int msm_mctl_set_vfe_output_mode(struct msm_cam_media_controller
*p_mctl, void __user *arg)
{
@@ -345,7 +199,7 @@
switch (cmd) {
/* sensor config*/
case MSM_CAM_IOCTL_GET_SENSOR_INFO:
- rc = msm_get_sensor_info(&p_mctl->sync, argp);
+ rc = msm_get_sensor_info(p_mctl, argp);
break;
case MSM_CAM_IOCTL_SENSOR_IO_CFG:
@@ -394,8 +248,6 @@
case MSM_CAM_IOCTL_GET_ACTUATOR_INFO: {
struct msm_actuator_cfg_data cdata;
- CDBG("%s: act_config: %p\n", __func__,
- p_mctl->sync.actctrl.a_config);
if (copy_from_user(&cdata,
(void *)argp,
sizeof(struct msm_actuator_cfg_data))) {
@@ -405,10 +257,10 @@
cdata.is_af_supported = 0;
rc = 0;
- if (p_mctl->sync.actctrl.a_config) {
+ if (p_mctl->act_sdev) {
struct msm_camera_sensor_info *sdata;
- sdata = p_mctl->sync.sdata;
+ sdata = p_mctl->sdata;
CDBG("%s: Act_cam_Name %d\n", __func__,
sdata->actuator_info->cam_name);
@@ -433,8 +285,9 @@
case MSM_CAM_IOCTL_ACTUATOR_IO_CFG: {
struct msm_actuator_cfg_data act_data;
- if (p_mctl->sync.actctrl.a_config) {
- rc = p_mctl->sync.actctrl.a_config(argp);
+ if (p_mctl->act_sdev) {
+ rc = v4l2_subdev_call(p_mctl->act_sdev,
+ core, ioctl, VIDIOC_MSM_ACTUATOR_CFG, argp);
} else {
rc = copy_from_user(
&act_data,
@@ -475,7 +328,7 @@
ERR_COPY_FROM_USER();
rc = -EFAULT;
} else {
- rc = msm_flash_ctrl(p_mctl->sync.sdata, &flash_info);
+ rc = msm_flash_ctrl(p_mctl->sdata, &flash_info);
}
break;
}
@@ -671,7 +524,6 @@
const char *const apps_id)
{
int rc = 0;
- struct msm_sync *sync = NULL;
struct msm_sensor_ctrl_t *s_ctrl = get_sctrl(p_mctl->sensor_sdev);
struct msm_camera_sensor_info *sinfo =
(struct msm_camera_sensor_info *) s_ctrl->sensordata;
@@ -683,14 +535,11 @@
return -EINVAL;
}
- /* msm_sync_init() muct be called before*/
- sync = &(p_mctl->sync);
-
- mutex_lock(&sync->lock);
+ mutex_lock(&p_mctl->lock);
/* open sub devices - once only*/
- if (!sync->opencnt) {
+ if (!p_mctl->opencnt) {
uint32_t csid_version;
- wake_lock(&sync->wake_lock);
+ wake_lock(&p_mctl->wake_lock);
csid_core = camdev->csid_core;
rc = msm_mctl_register_subdevs(p_mctl, csid_core);
@@ -707,9 +556,9 @@
pr_err("%s: isp init failed: %d\n", __func__, rc);
goto msm_open_done;
}
- if (sync->actctrl.a_power_up)
- rc = sync->actctrl.a_power_up(
- sync->sdata->actuator_info);
+ if (p_mctl->act_sdev)
+ rc = v4l2_subdev_call(p_mctl->act_sdev,
+ core, s_power, 1);
if (rc < 0) {
pr_err("%s: act power failed:%d\n", __func__, rc);
@@ -750,8 +599,7 @@
rc = p_mctl->isp_sdev->isp_open(
p_mctl->isp_sdev->sd,
p_mctl->isp_sdev->sd_vpe,
- p_mctl->gemini_sdev,
- sync);
+ p_mctl);
if (rc < 0) {
pr_err("%s: isp init failed: %d\n", __func__, rc);
goto msm_open_done;
@@ -774,12 +622,12 @@
pm_qos_update_request(&p_mctl->pm_qos_req_list,
MSM_V4L2_SWFI_LATENCY);
}
- sync->apps_id = apps_id;
- sync->opencnt++;
+ p_mctl->apps_id = apps_id;
+ p_mctl->opencnt++;
}
msm_open_done:
- mutex_unlock(&sync->lock);
+ mutex_unlock(&p_mctl->lock);
return rc;
}
@@ -805,8 +653,8 @@
}
if (p_mctl->isp_sdev && p_mctl->isp_sdev->isp_release)
- p_mctl->isp_sdev->isp_release(&p_mctl->sync,
- p_mctl->gemini_sdev);
+ p_mctl->isp_sdev->isp_release(
+ p_mctl->isp_sdev->sd);
if (camdev->is_csid) {
v4l2_subdev_call(p_mctl->csid_sdev, core, ioctl,
@@ -823,19 +671,19 @@
PM_QOS_DEFAULT_VALUE);
pm_qos_remove_request(&p_mctl->pm_qos_req_list);
}
- if (p_mctl->sync.actctrl.a_power_down)
- p_mctl->sync.actctrl.a_power_down(
- p_mctl->sync.sdata->actuator_info);
+
+ if (p_mctl->act_sdev)
+ v4l2_subdev_call(p_mctl->act_sdev, core, s_power, 0);
v4l2_subdev_call(p_mctl->sensor_sdev, core, s_power, 0);
- wake_unlock(&p_mctl->sync.wake_lock);
+ wake_unlock(&p_mctl->wake_lock);
return rc;
}
int msm_mctl_init_user_formats(struct msm_cam_v4l2_device *pcam)
{
- struct v4l2_subdev *sd = pcam->mctl.sensor_sdev;
+ struct v4l2_subdev *sd = pcam->sensor_sdev;
enum v4l2_mbus_pixelcode pxlcode;
int numfmt_sensor = 0;
int numfmt = 0;
@@ -893,35 +741,69 @@
}
/* this function plug in the implementation of a v4l2_subdev */
-int msm_mctl_init_module(struct msm_cam_v4l2_device *pcam)
+int msm_mctl_init(struct msm_cam_v4l2_device *pcam)
{
struct msm_cam_media_controller *pmctl = NULL;
D("%s\n", __func__);
if (!pcam) {
pr_err("%s: param is NULL", __func__);
return -EINVAL;
- } else
- pmctl = &pcam->mctl;
+ }
+ pcam->mctl_handle = msm_camera_get_mctl_handle();
+ if (pcam->mctl_handle == 0) {
+ pr_err("%s: cannot get mctl handle", __func__);
+ return -EINVAL;
+ }
- pmctl->sync.opencnt = 0;
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ if (!pmctl) {
+ pr_err("%s: invalid mctl controller", __func__);
+ return -EINVAL;
+ }
+
+ wake_lock_init(&pmctl->wake_lock, WAKE_LOCK_IDLE, "msm_camera");
+ mutex_init(&pmctl->lock);
+ pmctl->opencnt = 0;
/* init module operations*/
pmctl->mctl_open = msm_mctl_open;
pmctl->mctl_cmd = msm_mctl_cmd;
- pmctl->mctl_notify = msm_mctl_notify;
pmctl->mctl_release = msm_mctl_release;
/* init mctl buf */
msm_mctl_buf_init(pcam);
memset(&pmctl->pp_info, 0, sizeof(pmctl->pp_info));
pmctl->vfe_output_mode = 0;
spin_lock_init(&pmctl->pp_info.lock);
- /* init sub device*/
- v4l2_subdev_init(&(pmctl->mctl_sdev), &mctl_subdev_ops);
- v4l2_set_subdevdata(&(pmctl->mctl_sdev), pmctl);
+
+ pmctl->act_sdev = pcam->act_sdev;
+ pmctl->sensor_sdev = pcam->sensor_sdev;
+ pmctl->sdata = pcam->sdata;
+
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ pmctl->client = msm_ion_client_create(-1, "camera");
+ kref_init(&pmctl->refcount);
+#endif
return 0;
}
+int msm_mctl_free(struct msm_cam_v4l2_device *pcam)
+{
+ int rc = 0;
+ struct msm_cam_media_controller *pmctl = NULL;
+ D("%s\n", __func__);
+
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ if (!pmctl) {
+ pr_err("%s: invalid mctl controller", __func__);
+ return -EINVAL;
+ }
+
+ mutex_destroy(&pmctl->lock);
+ wake_lock_destroy(&pmctl->wake_lock);
+ msm_camera_free_mctl(pcam->mctl_handle);
+ return rc;
+}
/* mctl node v4l2_file_operations */
static int msm_mctl_dev_open(struct file *f)
@@ -930,6 +812,7 @@
/* get the video device */
struct msm_cam_v4l2_device *pcam = NULL;
struct msm_cam_v4l2_dev_inst *pcam_inst;
+ struct msm_cam_media_controller *pmctl;
D("%s : E ", __func__);
if (f == NULL) {
@@ -942,6 +825,7 @@
pr_err("%s NULL pointer passed in!\n", __func__);
return rc;
}
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
mutex_lock(&pcam->mctl_node.dev_lock);
for (i = 0; i < MSM_DEV_INST_MAX; i++) {
@@ -966,7 +850,6 @@
D("%s pcam_inst %p my_index = %d\n", __func__,
pcam_inst, pcam_inst->my_index);
- D("%s for %s\n", __func__, pcam->mctl.sensor_sdev->name);
rc = msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
pcam->mctl_node.pvdev);
if (rc < 0) {
@@ -974,7 +857,7 @@
return rc;
}
pcam_inst->vbqueue_initialized = 0;
- kref_get(&pcam->mctl.refcount);
+ kref_get(&pmctl->refcount);
f->private_data = &pcam_inst->eventHandle;
D("f->private_data = 0x%x, pcam = 0x%x\n",
@@ -1024,6 +907,7 @@
int rc = 0;
struct msm_cam_v4l2_device *pcam;
struct msm_cam_v4l2_dev_inst *pcam_inst;
+ struct msm_cam_media_controller *pmctl;
pcam_inst = container_of(f->private_data,
struct msm_cam_v4l2_dev_inst, eventHandle);
pcam = pcam_inst->pcam;
@@ -1034,6 +918,7 @@
return -EINVAL;
}
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
mutex_lock(&pcam->mctl_node.dev_lock);
pcam_inst->streamon = 0;
pcam->mctl_node.dev_inst_map[pcam_inst->image_mode] = NULL;
@@ -1045,7 +930,7 @@
v4l2_fh_exit(&pcam_inst->eventHandle);
kfree(pcam_inst);
- kref_put(&pcam->mctl.refcount, msm_release_ion_client);
+ kref_put(&pmctl->refcount, msm_release_ion_client);
f->private_data = NULL;
mutex_unlock(&pcam->mctl_node.dev_lock);
D("%s : X ", __func__);
@@ -1085,8 +970,8 @@
return -EINVAL;
}
- strlcpy(pcaps->driver, pcam->mctl.sensor_sdev->name,
- sizeof(pcaps->driver));
+ strlcpy(pcaps->driver, pcam->media_dev.dev->driver->name,
+ sizeof(pcaps->driver));
pcaps->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
return 0;
}
@@ -1437,6 +1322,7 @@
int rc = 0;
/* get the video device */
struct msm_cam_v4l2_device *pcam = video_drvdata(f);
+ struct msm_cam_media_controller *pmctl;
struct msm_cam_v4l2_dev_inst *pcam_inst;
pcam_inst = container_of(f->private_data,
struct msm_cam_v4l2_dev_inst, eventHandle);
@@ -1447,8 +1333,9 @@
(void *)pfmt->fmt.pix.priv);
WARN_ON(pctx != f->private_data);
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
if (!pcam_inst->vbqueue_initialized) {
- pcam->mctl.mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
+ pmctl->mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
V4L2_BUF_TYPE_VIDEO_CAPTURE);
pcam_inst->vbqueue_initialized = 1;
}
@@ -1461,6 +1348,7 @@
{
int rc = 0, i;
struct msm_cam_v4l2_device *pcam = video_drvdata(f);
+ struct msm_cam_media_controller *pmctl;
struct msm_cam_v4l2_dev_inst *pcam_inst;
pcam_inst = container_of(f->private_data,
struct msm_cam_v4l2_dev_inst, eventHandle);
@@ -1469,8 +1357,9 @@
pcam_inst, pcam_inst->vbqueue_initialized);
WARN_ON(pctx != f->private_data);
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
if (!pcam_inst->vbqueue_initialized) {
- pcam->mctl.mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
+ pmctl->mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
pcam_inst->vbqueue_initialized = 1;
}
@@ -1657,7 +1546,7 @@
{
int rc = -EINVAL;
struct video_device *pvdev = NULL;
- struct i2c_client *client = v4l2_get_subdevdata(pcam->mctl.sensor_sdev);
+ struct i2c_client *client = v4l2_get_subdevdata(pcam->sensor_sdev);
D("%s\n", __func__);
@@ -1679,11 +1568,11 @@
/* init video device's driver interface */
D("sensor name = %s, sizeof(pvdev->name)=%d\n",
- pcam->mctl.sensor_sdev->name, sizeof(pvdev->name));
+ pcam->sensor_sdev->name, sizeof(pvdev->name));
/* device info - strlcpy is safer than strncpy but
only if architecture supports*/
- strlcpy(pvdev->name, pcam->mctl.sensor_sdev->name,
+ strlcpy(pvdev->name, pcam->sensor_sdev->name,
sizeof(pvdev->name));
pvdev->release = video_device_release;
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index 8148f1f..5bc81a7 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -75,6 +75,7 @@
{
struct msm_cam_v4l2_dev_inst *pcam_inst;
struct msm_cam_v4l2_device *pcam;
+ struct msm_cam_media_controller *pmctl;
struct videobuf2_contig_pmem *mem;
struct vb2_queue *vq;
uint32_t buf_idx;
@@ -112,6 +113,7 @@
pcam_inst->plane_info.plane[0].offset;
}
buf_idx = vb->v4l2_buf.index;
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
for (i = 0; i < vb->num_planes; i++) {
mem = vb2_plane_cookie(vb, i);
if (buf_type == VIDEOBUF2_MULTIPLE_PLANES)
@@ -122,7 +124,7 @@
rc = videobuf2_pmem_contig_user_get(mem, &offset,
buf_type,
pcam_inst->buf_offset[buf_idx][i].addr_offset,
- pcam_inst->path, pcam->mctl.client);
+ pcam_inst->path, pmctl->client);
else
rc = videobuf2_pmem_contig_mmap_get(mem, &offset,
buf_type, pcam_inst->path);
@@ -194,6 +196,7 @@
static void msm_vb2_ops_buf_cleanup(struct vb2_buffer *vb)
{
struct msm_cam_v4l2_dev_inst *pcam_inst;
+ struct msm_cam_media_controller *pmctl;
struct msm_cam_v4l2_device *pcam;
struct videobuf2_contig_pmem *mem;
struct msm_frame_buffer *buf, *tmp;
@@ -248,9 +251,10 @@
}
spin_unlock_irqrestore(&pcam_inst->vq_irqlock, flags);
}
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
for (i = 0; i < vb->num_planes; i++) {
mem = vb2_plane_cookie(vb, i);
- videobuf2_pmem_contig_user_put(mem, pcam->mctl.client);
+ videobuf2_pmem_contig_user_put(mem, pmctl->client);
}
buf->state = MSM_BUFFER_STATE_UNUSED;
}
@@ -328,12 +332,12 @@
int image_mode, int node_type)
{
if ((image_mode >= 0) && node_type &&
- pmctl->sync.pcam_sync->mctl_node.dev_inst_map[image_mode])
- return pmctl->sync.pcam_sync->
+ pmctl->pcam_ptr->mctl_node.dev_inst_map[image_mode])
+ return pmctl->pcam_ptr->
mctl_node.dev_inst_map[image_mode]->my_index;
else if ((image_mode >= 0) &&
- pmctl->sync.pcam_sync->dev_inst_map[image_mode])
- return pmctl->sync.pcam_sync->
+ pmctl->pcam_ptr->dev_inst_map[image_mode])
+ return pmctl->pcam_ptr->
dev_inst_map[image_mode]->my_index;
else
return -EINVAL;
@@ -440,7 +444,7 @@
__func__);
return idx;
}
- pcam_inst = p_mctl->sync.pcam_sync->dev_inst[idx];
+ pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
rc = msm_mctl_buf_done_proc(p_mctl, pcam_inst,
image_mode, fbuf,
&frame_id, 1);
@@ -450,7 +454,9 @@
int msm_mctl_buf_init(struct msm_cam_v4l2_device *pcam)
{
- pcam->mctl.mctl_vbqueue_init = msm_vbqueue_init;
+ struct msm_cam_media_controller *pmctl;
+ pmctl = msm_camera_get_mctl(pcam->mctl_handle);
+ pmctl->mctl_vbqueue_init = msm_vbqueue_init;
return 0;
}
@@ -475,7 +481,7 @@
int image_mode)
{
struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
- struct msm_cam_v4l2_device *pcam = pmctl->sync.pcam_sync;
+ struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
int idx;
if (image_mode >= 0) {
@@ -646,9 +652,9 @@
return idx;
}
if (node_type)
- pcam_inst = pmctl->sync.pcam_sync->mctl_node.dev_inst[idx];
+ pcam_inst = pmctl->pcam_ptr->mctl_node.dev_inst[idx];
else
- pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+ pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
if (!pcam_inst) {
pr_err("%s Invalid instance, cannot send buf to user",
__func__);
@@ -682,7 +688,7 @@
pr_err("%s Invalid instance, cant get buffer\n", __func__);
return NULL;
}
- pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+ pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
if (!pcam_inst->streamon) {
D("%s: stream 0x%p is off\n", __func__, pcam_inst);
return NULL;
@@ -721,7 +727,7 @@
pr_err("%s Invalid instance, cant put buffer\n", __func__);
return idx;
}
- pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+ pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
if (!pcam_inst->streamon) {
D("%s: stream 0x%p is off\n", __func__, pcam_inst);
return rc;
@@ -756,7 +762,7 @@
pr_err("%s Invalid instance, cant delete buffer\n", __func__);
return idx;
}
- pcam_inst = pmctl->sync.pcam_sync->dev_inst[idx];
+ pcam_inst = pmctl->pcam_ptr->dev_inst[idx];
D("%s: idx = %d, pinst=0x%p", __func__, idx, pcam_inst);
spin_lock_irqsave(&pcam_inst->vq_irqlock, flags);
if (!list_empty(&pcam_inst->free_vq)) {
@@ -780,7 +786,7 @@
int idx = 0;
struct msm_frame_buffer *buf = NULL;
struct msm_cam_v4l2_dev_inst *pcam_inst;
- struct msm_cam_v4l2_device *pcam = pmctl->sync.pcam_sync;
+ struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
unsigned long flags = 0;
if (pcam->mctl_node.dev_inst_map[image_mode]) {
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index 82c5bf7..2e46728 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -156,7 +156,7 @@
int image_mode, struct msm_free_buf *fbuf, int *node_type)
{
struct msm_cam_v4l2_dev_inst *pcam_inst = NULL;
- struct msm_cam_v4l2_device *pcam = pmctl->sync.pcam_sync;
+ struct msm_cam_v4l2_device *pcam = pmctl->pcam_ptr;
int idx;
if (image_mode >= 0) {
@@ -559,14 +559,14 @@
zoom->pp_frame_cmd.cookie,
zoom->pp_frame_cmd.vpe_output_action,
zoom->pp_frame_cmd.path);
- idx = msm_mctl_pp_path_to_inst_index(p_mctl->sync.pcam_sync,
+ idx = msm_mctl_pp_path_to_inst_index(p_mctl->pcam_ptr,
zoom->pp_frame_cmd.path);
if (idx < 0) {
pr_err("%s Invalid path, returning\n", __func__);
kfree(zoom);
return idx;
}
- pcam_inst = p_mctl->sync.pcam_sync->dev_inst[idx];
+ pcam_inst = p_mctl->pcam_ptr->dev_inst[idx];
if (!pcam_inst) {
pr_err("%s Invalid instance, returning\n", __func__);
kfree(zoom);
@@ -809,7 +809,7 @@
return -EINVAL;
}
/* Always reserve the buffer from user's video node */
- pcam_inst = p_mctl->sync.pcam_sync->dev_inst[image_mode];
+ pcam_inst = p_mctl->pcam_ptr->dev_inst[image_mode];
if (!pcam_inst) {
pr_err("%s Instance already closed ", __func__);
return -EINVAL;
diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/video/msm/msm_mem.c
index 4f7e5d2..751626a 100644
--- a/drivers/media/video/msm/msm_mem.c
+++ b/drivers/media/video/msm/msm_mem.c
@@ -346,14 +346,15 @@
}
unsigned long msm_pmem_stats_vtop_lookup(
- struct msm_sync *sync,
+ struct msm_cam_media_controller *mctl,
unsigned long buffer,
int fd)
{
struct msm_pmem_region *region;
struct hlist_node *node, *n;
- hlist_for_each_entry_safe(region, node, n, &sync->pmem_stats, list) {
+ hlist_for_each_entry_safe(region, node, n,
+ &mctl->stats_info.pmem_stats_list, list) {
if (((unsigned long)(region->info.vaddr) == buffer) &&
(region->info.fd == fd) &&
region->info.active == 0) {
@@ -365,13 +366,15 @@
return 0;
}
-unsigned long msm_pmem_stats_ptov_lookup(struct msm_sync *sync,
- unsigned long addr, int *fd)
+unsigned long msm_pmem_stats_ptov_lookup(
+ struct msm_cam_media_controller *mctl,
+ unsigned long addr, int *fd)
{
struct msm_pmem_region *region;
struct hlist_node *node, *n;
- hlist_for_each_entry_safe(region, node, n, &sync->pmem_stats, list) {
+ hlist_for_each_entry_safe(region, node, n,
+ &mctl->stats_info.pmem_stats_list, list) {
if (addr == region->paddr && region->info.active) {
/* offset since we could pass vaddr inside a
* registered pmem buffer */
diff --git a/drivers/media/video/msm/msm_vfe31_v4l2.c b/drivers/media/video/msm/msm_vfe31_v4l2.c
index d60f4b7..90ba214 100644
--- a/drivers/media/video/msm/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe31_v4l2.c
@@ -54,7 +54,6 @@
#define CAMIF_CFG_RMSK 0x1fffff
static struct vfe31_ctrl_type *vfe31_ctrl;
-static void *vfe_syncdata;
static uint32_t vfe_clk_rate;
struct vfe31_isr_queue_cmd {
@@ -748,31 +747,26 @@
atomic_set(&vfe31_ctrl->vstate, 1);
}
-static int vfe31_start_recording(void)
+static int vfe31_start_recording(struct msm_cam_media_controller *pmctl)
{
- struct msm_sync *sync = vfe_syncdata;
msm_camio_bus_scale_cfg(
- sync->sdata->pdata->cam_bus_scale_table, S_VIDEO);
+ pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
vfe31_ctrl->recording_state = VFE_STATE_START_REQUESTED;
msm_camera_io_w_mb(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
return 0;
}
-static int vfe31_stop_recording(void)
+static int vfe31_stop_recording(struct msm_cam_media_controller *pmctl)
{
- struct msm_sync *sync = vfe_syncdata;
vfe31_ctrl->recording_state = VFE_STATE_STOP_REQUESTED;
msm_camera_io_w_mb(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
msm_camio_bus_scale_cfg(
- sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+ pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
return 0;
}
-static void vfe31_start_liveshot(void){
- struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
- if (p_sync)
- p_sync->liveshot_enabled = true;
-
+static void vfe31_start_liveshot(struct msm_cam_media_controller *pmctl)
+{
/* Hardcode 1 live snapshot for now. */
vfe31_ctrl->outpath.out0.capture_cnt = 1;
vfe31_ctrl->vfe_capture_count = vfe31_ctrl->outpath.out0.capture_cnt;
@@ -781,9 +775,8 @@
msm_camera_io_w_mb(1, vfe31_ctrl->vfebase + VFE_REG_UPDATE_CMD);
}
-static int vfe31_zsl(void)
+static int vfe31_zsl(struct msm_cam_media_controller *pmctl)
{
- struct msm_sync *sync = vfe_syncdata;
uint32_t irq_comp_mask = 0;
/* capture command is valid for both idle and active state. */
irq_comp_mask =
@@ -845,16 +838,17 @@
msm_camera_io_w(irq_comp_mask, vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
vfe31_start_common();
msm_camio_bus_scale_cfg(
- sync->sdata->pdata->cam_bus_scale_table, S_ZSL);
+ pmctl->sdata->pdata->cam_bus_scale_table, S_ZSL);
msm_camera_io_w(1, vfe31_ctrl->vfebase + 0x18C);
msm_camera_io_w(1, vfe31_ctrl->vfebase + 0x188);
return 0;
}
-static int vfe31_capture_raw(uint32_t num_frames_capture)
+static int vfe31_capture_raw(
+ struct msm_cam_media_controller *pmctl,
+ uint32_t num_frames_capture)
{
uint32_t irq_comp_mask = 0;
- struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
vfe31_ctrl->outpath.out0.capture_cnt = num_frames_capture;
vfe31_ctrl->vfe_capture_count = num_frames_capture;
@@ -870,19 +864,16 @@
msm_camera_io_w(irq_comp_mask, vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
msm_camio_bus_scale_cfg(
- p_sync->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
+ pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
vfe31_start_common();
return 0;
}
-static int vfe31_capture(uint32_t num_frames_capture)
+static int vfe31_capture(
+ struct msm_cam_media_controller *pmctl,
+ uint32_t num_frames_capture)
{
uint32_t irq_comp_mask = 0;
- struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
- if (p_sync) {
- p_sync->snap_count = num_frames_capture;
- p_sync->thumb_count = num_frames_capture;
- }
/* capture command is valid for both idle and active state. */
vfe31_ctrl->outpath.out1.capture_cnt = num_frames_capture;
if (vfe31_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
@@ -932,7 +923,7 @@
msm_camera_io_w(irq_comp_mask, vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
msm_camera_io_r(vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
msm_camio_bus_scale_cfg(
- p_sync->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
+ pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
vfe31_start_common();
/* for debug */
@@ -941,10 +932,9 @@
return 0;
}
-static int vfe31_start(void)
+static int vfe31_start(struct msm_cam_media_controller *pmctl)
{
uint32_t irq_comp_mask = 0;
- struct msm_sync *sync = vfe_syncdata;
irq_comp_mask =
msm_camera_io_r(vfe31_ctrl->vfebase + VFE_IRQ_COMP_MASK);
@@ -1007,7 +997,7 @@
break;
}
msm_camio_bus_scale_cfg(
- sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+ pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
vfe31_start_common();
return 0;
}
@@ -1241,7 +1231,9 @@
NOTIFY_ISP_MSG_EVT, (void *)&isp_msg_evt);
}
-static int vfe31_proc_general(struct msm_isp_cmd *cmd)
+static int vfe31_proc_general(
+ struct msm_cam_media_controller *pmctl,
+ struct msm_isp_cmd *cmd)
{
int i , rc = 0;
uint32_t old_val = 0 , new_val = 0;
@@ -1278,7 +1270,7 @@
rc = -EINVAL;
goto proc_general_done;
}
- rc = vfe31_start();
+ rc = vfe31_start(pmctl);
break;
case VFE_CMD_UPDATE:
vfe31_update();
@@ -1298,7 +1290,7 @@
rc = -EINVAL;
goto proc_general_done;
}
- rc = vfe31_capture_raw(snapshot_cnt);
+ rc = vfe31_capture_raw(pmctl, snapshot_cnt);
break;
case VFE_CMD_CAPTURE:
if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
@@ -1339,7 +1331,7 @@
rc = -EINVAL;
goto proc_general_done;
}
- rc = vfe31_capture(snapshot_cnt);
+ rc = vfe31_capture(pmctl, snapshot_cnt);
break;
case VFE_CMD_START_RECORDING:
pr_info("vfe31_proc_general: cmdID = %s\n",
@@ -1360,12 +1352,12 @@
rc = -EINVAL;
goto proc_general_done;
}
- rc = vfe31_start_recording();
+ rc = vfe31_start_recording(pmctl);
break;
case VFE_CMD_STOP_RECORDING:
pr_info("vfe31_proc_general: cmdID = %s\n",
vfe31_general_cmd[cmd->id]);
- rc = vfe31_stop_recording();
+ rc = vfe31_stop_recording(pmctl);
break;
case VFE_CMD_OPERATION_CFG:
if (cmd->length != V31_OPERATION_CFG_LEN) {
@@ -1756,7 +1748,7 @@
rc = -EINVAL;
goto proc_general_done;
}
- vfe31_start_liveshot();
+ vfe31_start_liveshot(pmctl);
break;
case VFE_CMD_DEMOSAICV3:
@@ -2057,7 +2049,7 @@
if (rc < 0)
goto proc_general_done;
- rc = vfe31_zsl();
+ rc = vfe31_zsl(pmctl);
break;
case VFE_CMD_ASF_CFG:
@@ -3316,6 +3308,8 @@
static long msm_vfe_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int subdev_cmd, void *arg)
{
+ struct msm_cam_media_controller *pmctl =
+ (struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
struct msm_isp_cmd vfecmd;
struct msm_camvfe_params *vfe_params =
(struct msm_camvfe_params *)arg;
@@ -3419,7 +3413,7 @@
}
switch (cmd->cmd_type) {
case CMD_GENERAL: {
- rc = vfe31_proc_general(&vfecmd);
+ rc = vfe31_proc_general(pmctl, &vfecmd);
}
break;
case CMD_CONFIG_PING_ADDR: {
@@ -3685,13 +3679,11 @@
usleep_range(10000, 15000);
}
-int msm_vfe_subdev_init(struct v4l2_subdev *sd, void *data,
- struct platform_device *pdev)
+int msm_vfe_subdev_init(struct v4l2_subdev *sd,
+ struct msm_cam_media_controller *mctl)
{
int rc = 0;
- struct msm_sync *sync = data;
- v4l2_set_subdev_hostdata(sd, data);
- vfe_syncdata = data;
+ v4l2_set_subdev_hostdata(sd, mctl);
spin_lock_init(&vfe31_ctrl->stop_flag_lock);
spin_lock_init(&vfe31_ctrl->state_lock);
@@ -3722,7 +3714,7 @@
pr_err("%s: vfe ioremap failed\n", __func__);
goto vfe_remap_failed;
}
- if (!sync->sdata->csi_if) {
+ if (!mctl->sdata->csi_if) {
vfe31_ctrl->camifbase = ioremap(vfe31_ctrl->camifmem->start,
resource_size(vfe31_ctrl->camifmem));
if (!vfe31_ctrl->camifbase) {
@@ -3754,7 +3746,7 @@
if (rc < 0)
goto vfe_clk_enable_failed;
- if (!sync->sdata->csi_if) {
+ if (!mctl->sdata->csi_if) {
rc = msm_cam_clk_enable(&vfe31_ctrl->pdev->dev,
vfe_camif_clk_info,
vfe31_ctrl->vfe_camif_clk,
@@ -3765,9 +3757,9 @@
}
msm_camio_bus_scale_cfg(
- sync->sdata->pdata->cam_bus_scale_table, S_INIT);
+ mctl->sdata->pdata->cam_bus_scale_table, S_INIT);
msm_camio_bus_scale_cfg(
- sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+ mctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
vfe31_ctrl->register_total = VFE31_REGISTER_TOTAL;
enable_irq(vfe31_ctrl->vfeirq->start);
@@ -3779,7 +3771,7 @@
regulator_put(vfe31_ctrl->fs_vfe);
vfe31_ctrl->fs_vfe = NULL;
vfe_fs_failed:
- if (!sync->sdata->csi_if)
+ if (!mctl->sdata->csi_if)
iounmap(vfe31_ctrl->camifbase);
camif_remap_failed:
iounmap(vfe31_ctrl->vfebase);
@@ -3788,13 +3780,14 @@
return rc;
}
-void msm_vfe_subdev_release(struct platform_device *pdev)
+void msm_vfe_subdev_release(struct v4l2_subdev *sd)
{
- struct msm_sync *sync = vfe_syncdata;
+ struct msm_cam_media_controller *pmctl =
+ (struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
disable_irq(vfe31_ctrl->vfeirq->start);
tasklet_kill(&vfe31_tasklet);
- if (!sync->sdata->csi_if)
+ if (!pmctl->sdata->csi_if)
msm_cam_clk_enable(&vfe31_ctrl->pdev->dev,
vfe_camif_clk_info,
vfe31_ctrl->vfe_camif_clk,
@@ -3808,7 +3801,7 @@
vfe31_ctrl->fs_vfe = NULL;
}
CDBG("%s, 31ee_irq\n", __func__);
- if (!sync->sdata->csi_if)
+ if (!pmctl->sdata->csi_if)
iounmap(vfe31_ctrl->camifbase);
iounmap(vfe31_ctrl->vfebase);
@@ -3816,10 +3809,10 @@
pr_warning("%s, Warning IRQ Count not ZERO\n", __func__);
msm_camio_bus_scale_cfg(
- sync->sdata->pdata->cam_bus_scale_table, S_EXIT);
- vfe_syncdata = NULL;
+ pmctl->sdata->pdata->cam_bus_scale_table, S_EXIT);
}
+static const struct v4l2_subdev_internal_ops msm_vfe_internal_ops;
static int __devinit vfe31_probe(struct platform_device *pdev)
{
@@ -3832,6 +3825,8 @@
}
v4l2_subdev_init(&vfe31_ctrl->subdev, &msm_vfe_subdev_ops);
+ vfe31_ctrl->subdev.internal_ops = &msm_vfe_internal_ops;
+ vfe31_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
snprintf(vfe31_ctrl->subdev.name,
sizeof(vfe31_ctrl->subdev.name), "vfe3.1");
v4l2_set_subdevdata(&vfe31_ctrl->subdev, vfe31_ctrl);
@@ -3894,6 +3889,7 @@
disable_irq(vfe31_ctrl->vfeirq->start);
vfe31_ctrl->pdev = pdev;
+ msm_cam_register_subdev_node(&vfe31_ctrl->subdev, VFE_DEV, 0);
return 0;
vfe31_no_resource:
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index b8344fb..0ce4983 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -48,7 +48,6 @@
vfe32_put_ch_ping_addr((chn), (addr)))
static struct vfe32_ctrl_type *vfe32_ctrl;
-static void *vfe_syncdata;
static uint32_t vfe_clk_rate;
struct vfe32_isr_queue_cmd {
@@ -726,31 +725,26 @@
atomic_set(&vfe32_ctrl->vstate, 1);
}
-static int vfe32_start_recording(void)
+static int vfe32_start_recording(struct msm_cam_media_controller *pmctl)
{
- struct msm_sync *sync = vfe_syncdata;
msm_camio_bus_scale_cfg(
- sync->sdata->pdata->cam_bus_scale_table, S_VIDEO);
+ pmctl->sdata->pdata->cam_bus_scale_table, S_VIDEO);
vfe32_ctrl->recording_state = VFE_STATE_START_REQUESTED;
msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
return 0;
}
-static int vfe32_stop_recording(void)
+static int vfe32_stop_recording(struct msm_cam_media_controller *pmctl)
{
- struct msm_sync *sync = vfe_syncdata;
vfe32_ctrl->recording_state = VFE_STATE_STOP_REQUESTED;
msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
msm_camio_bus_scale_cfg(
- sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+ pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
return 0;
}
-static void vfe32_start_liveshot(void){
- struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
- if (p_sync)
- p_sync->liveshot_enabled = true;
-
+static void vfe32_start_liveshot(struct msm_cam_media_controller *pmctl)
+{
/* Hardcode 1 live snapshot for now. */
vfe32_ctrl->outpath.out0.capture_cnt = 1;
vfe32_ctrl->vfe_capture_count = vfe32_ctrl->outpath.out0.capture_cnt;
@@ -759,9 +753,8 @@
msm_camera_io_w_mb(1, vfe32_ctrl->vfebase + VFE_REG_UPDATE_CMD);
}
-static int vfe32_zsl(void)
+static int vfe32_zsl(struct msm_cam_media_controller *pmctl)
{
- struct msm_sync *sync = vfe_syncdata;
uint32_t irq_comp_mask = 0;
/* capture command is valid for both idle and active state. */
irq_comp_mask =
@@ -823,16 +816,17 @@
msm_camera_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
vfe32_start_common();
msm_camio_bus_scale_cfg(
- sync->sdata->pdata->cam_bus_scale_table, S_ZSL);
+ pmctl->sdata->pdata->cam_bus_scale_table, S_ZSL);
msm_camera_io_w(1, vfe32_ctrl->vfebase + 0x18C);
msm_camera_io_w(1, vfe32_ctrl->vfebase + 0x188);
return 0;
}
-static int vfe32_capture_raw(uint32_t num_frames_capture)
+static int vfe32_capture_raw(
+ struct msm_cam_media_controller *pmctl,
+ uint32_t num_frames_capture)
{
uint32_t irq_comp_mask = 0;
- struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
vfe32_ctrl->outpath.out0.capture_cnt = num_frames_capture;
vfe32_ctrl->vfe_capture_count = num_frames_capture;
@@ -848,19 +842,17 @@
msm_camera_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
msm_camio_bus_scale_cfg(
- p_sync->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
+ pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
vfe32_start_common();
return 0;
}
-static int vfe32_capture(uint32_t num_frames_capture)
+static int vfe32_capture(
+ struct msm_cam_media_controller *pmctl,
+ uint32_t num_frames_capture)
{
uint32_t irq_comp_mask = 0;
- struct msm_sync* p_sync = (struct msm_sync *)vfe_syncdata;
- if (p_sync) {
- p_sync->snap_count = num_frames_capture;
- p_sync->thumb_count = num_frames_capture;
- }
+
/* capture command is valid for both idle and active state. */
vfe32_ctrl->outpath.out1.capture_cnt = num_frames_capture;
if (vfe32_ctrl->operation_mode == VFE_OUTPUTS_MAIN_AND_THUMB ||
@@ -910,7 +902,7 @@
msm_camera_io_w(irq_comp_mask, vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
msm_camera_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
msm_camio_bus_scale_cfg(
- p_sync->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
+ pmctl->sdata->pdata->cam_bus_scale_table, S_CAPTURE);
vfe32_start_common();
/* for debug */
@@ -919,10 +911,9 @@
return 0;
}
-static int vfe32_start(void)
+static int vfe32_start(struct msm_cam_media_controller *pmctl)
{
uint32_t irq_comp_mask = 0;
- struct msm_sync *sync = vfe_syncdata;
irq_comp_mask =
msm_camera_io_r(vfe32_ctrl->vfebase + VFE_IRQ_COMP_MASK);
@@ -986,7 +977,7 @@
}
msm_camio_bus_scale_cfg(
- sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+ pmctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
vfe32_start_common();
return 0;
}
@@ -1259,7 +1250,9 @@
(void *)&isp_msg_evt);
}
-static int vfe32_proc_general(struct msm_isp_cmd *cmd)
+static int vfe32_proc_general(
+ struct msm_cam_media_controller *pmctl,
+ struct msm_isp_cmd *cmd)
{
int i , rc = 0;
uint32_t old_val = 0 , new_val = 0;
@@ -1296,7 +1289,7 @@
rc = -EINVAL;
goto proc_general_done;
}
- rc = vfe32_start();
+ rc = vfe32_start(pmctl);
break;
case VFE_CMD_UPDATE:
vfe32_update();
@@ -1316,7 +1309,7 @@
rc = -EINVAL;
goto proc_general_done;
}
- rc = vfe32_capture_raw(snapshot_cnt);
+ rc = vfe32_capture_raw(pmctl, snapshot_cnt);
break;
case VFE_CMD_CAPTURE:
if (copy_from_user(&snapshot_cnt, (void __user *)(cmd->value),
@@ -1357,7 +1350,7 @@
rc = -EINVAL;
goto proc_general_done;
}
- rc = vfe32_capture(snapshot_cnt);
+ rc = vfe32_capture(pmctl, snapshot_cnt);
break;
case VFE_CMD_START_RECORDING:
pr_info("vfe32_proc_general: cmdID = %s\n",
@@ -1378,12 +1371,12 @@
rc = -EINVAL;
goto proc_general_done;
}
- rc = vfe32_start_recording();
+ rc = vfe32_start_recording(pmctl);
break;
case VFE_CMD_STOP_RECORDING:
pr_info("vfe32_proc_general: cmdID = %s\n",
vfe32_general_cmd[cmd->id]);
- rc = vfe32_stop_recording();
+ rc = vfe32_stop_recording(pmctl);
break;
case VFE_CMD_OPERATION_CFG: {
if (cmd->length != V32_OPERATION_CFG_LEN) {
@@ -1793,7 +1786,7 @@
rc = -EINVAL;
goto proc_general_done;
}
- vfe32_start_liveshot();
+ vfe32_start_liveshot(pmctl);
break;
case VFE_CMD_LINEARIZATION_CFG:
@@ -2242,7 +2235,7 @@
if (rc < 0)
goto proc_general_done;
- rc = vfe32_zsl();
+ rc = vfe32_zsl(pmctl);
break;
case VFE_CMD_ASF_CFG:
@@ -3640,6 +3633,8 @@
static long msm_vfe_subdev_ioctl(struct v4l2_subdev *sd,
unsigned int subdev_cmd, void *arg)
{
+ struct msm_cam_media_controller *pmctl =
+ (struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
struct msm_isp_cmd vfecmd;
struct msm_camvfe_params *vfe_params =
(struct msm_camvfe_params *)arg;
@@ -3743,7 +3738,7 @@
}
switch (cmd->cmd_type) {
case CMD_GENERAL:
- rc = vfe32_proc_general(&vfecmd);
+ rc = vfe32_proc_general(pmctl, &vfecmd);
break;
case CMD_CONFIG_PING_ADDR: {
@@ -3941,13 +3936,11 @@
.video = &msm_vfe_subdev_video_ops,
};
-int msm_vfe_subdev_init(struct v4l2_subdev *sd, void *data,
- struct platform_device *pdev)
+int msm_vfe_subdev_init(struct v4l2_subdev *sd,
+ struct msm_cam_media_controller *mctl)
{
int rc = 0;
- struct msm_sync *sync = data;
- v4l2_set_subdev_hostdata(sd, data);
- vfe_syncdata = data;
+ v4l2_set_subdev_hostdata(sd, mctl);
spin_lock_init(&vfe32_ctrl->stop_flag_lock);
spin_lock_init(&vfe32_ctrl->state_lock);
@@ -4004,9 +3997,9 @@
goto vfe_clk_enable_failed;
msm_camio_bus_scale_cfg(
- sync->sdata->pdata->cam_bus_scale_table, S_INIT);
+ mctl->sdata->pdata->cam_bus_scale_table, S_INIT);
msm_camio_bus_scale_cfg(
- sync->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
+ mctl->sdata->pdata->cam_bus_scale_table, S_PREVIEW);
if (msm_camera_io_r(vfe32_ctrl->vfebase + V32_GET_HW_VERSION_OFF) ==
VFE32_HW_NUMBER)
@@ -4028,9 +4021,10 @@
return rc;
}
-void msm_vfe_subdev_release(struct platform_device *pdev)
+void msm_vfe_subdev_release(struct v4l2_subdev *sd)
{
- struct msm_sync *sync = vfe_syncdata;
+ struct msm_cam_media_controller *pmctl =
+ (struct msm_cam_media_controller *)v4l2_get_subdev_hostdata(sd);
CDBG("%s, free_irq\n", __func__);
disable_irq(vfe32_ctrl->vfeirq->start);
tasklet_kill(&vfe32_tasklet);
@@ -4048,10 +4042,11 @@
pr_warning("%s, Warning IRQ Count not ZERO\n", __func__);
msm_camio_bus_scale_cfg(
- sync->sdata->pdata->cam_bus_scale_table, S_EXIT);
- vfe_syncdata = NULL;
+ pmctl->sdata->pdata->cam_bus_scale_table, S_EXIT);
}
+static const struct v4l2_subdev_internal_ops msm_vfe_internal_ops;
+
static int __devinit vfe32_probe(struct platform_device *pdev)
{
int rc = 0;
@@ -4063,6 +4058,8 @@
}
v4l2_subdev_init(&vfe32_ctrl->subdev, &msm_vfe_subdev_ops);
+ vfe32_ctrl->subdev.internal_ops = &msm_vfe_internal_ops;
+ vfe32_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
snprintf(vfe32_ctrl->subdev.name,
sizeof(vfe32_ctrl->subdev.name), "vfe3.2");
v4l2_set_subdevdata(&vfe32_ctrl->subdev, vfe32_ctrl);
@@ -4104,6 +4101,7 @@
disable_irq(vfe32_ctrl->vfeirq->start);
vfe32_ctrl->pdev = pdev;
+ msm_cam_register_subdev_node(&vfe32_ctrl->subdev, VFE_DEV, 0);
return 0;
vfe32_no_resource:
diff --git a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
index acd9158..40154ef 100644
--- a/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/msm_vfe7x27a_v4l2.c
@@ -340,7 +340,6 @@
static uint32_t extlen;
struct mutex vfe_lock;
-static void *vfe_syncdata;
static int apps_reset;
static uint8_t vfestopped;
@@ -1643,12 +1642,11 @@
{"vfe_clk", 192000000},
};
-int msm_vfe_subdev_init(struct v4l2_subdev *sd, void *data,
- struct platform_device *pdev)
+int msm_vfe_subdev_init(struct v4l2_subdev *sd,
+ struct msm_cam_media_controller *mctl)
{
int rc = 0;
- v4l2_set_subdev_hostdata(sd, data);
- vfe_syncdata = data;
+ v4l2_set_subdev_hostdata(sd, mctl);
spin_lock_init(&vfe2x_ctrl->sd_notify_lock);
spin_lock_init(&vfe2x_ctrl->table_lock);
@@ -1702,24 +1700,24 @@
return rc;
}
-int msm_vpe_subdev_init(struct v4l2_subdev *sd, void *data,
- struct platform_device *pdev)
+int msm_vpe_subdev_init(struct v4l2_subdev *sd,
+ struct msm_cam_media_controller *mctl)
{
return 0;
}
-void msm_vpe_subdev_release(struct platform_device *pdev)
+void msm_vpe_subdev_release(void)
{
return;
}
-void msm_vfe_subdev_release(struct platform_device *pdev)
+void msm_vfe_subdev_release(struct v4l2_subdev *sd)
{
CDBG("msm_cam_clk_enable: disable vfe_clk\n");
msm_cam_clk_enable(&vfe2x_ctrl->pdev->dev, vfe2x_clk_info,
vfe2x_ctrl->vfe_clk, ARRAY_SIZE(vfe2x_clk_info), 0);
- vfe_syncdata = NULL;
apps_reset = 1;
+
msm_adsp_disable(qcam_mod);
msm_adsp_disable(vfe_mod);
@@ -1739,6 +1737,8 @@
.core = &msm_vfe_subdev_core_ops,
};
+static const struct v4l2_subdev_internal_ops msm_vfe_internal_ops;
+
static int __devinit vfe2x_probe(struct platform_device *pdev)
{
CDBG("%s: device id = %d\n", __func__, pdev->id);
@@ -1749,12 +1749,15 @@
}
v4l2_subdev_init(&vfe2x_ctrl->subdev, &msm_vfe_subdev_ops);
+ vfe2x_ctrl->subdev.internal_ops = &msm_vfe_internal_ops;
+ vfe2x_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
snprintf(vfe2x_ctrl->subdev.name,
sizeof(vfe2x_ctrl->subdev.name), "vfe2.x");
v4l2_set_subdevdata(&vfe2x_ctrl->subdev, vfe2x_ctrl);
platform_set_drvdata(pdev, &vfe2x_ctrl->subdev);
vfe2x_ctrl->pdev = pdev;
+ msm_cam_register_subdev_node(&vfe2x_ctrl->subdev, VFE_DEV, 0);
return 0;
}
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index cd503f9..0ab6531 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -640,10 +640,10 @@
.core = &msm_vpe_subdev_core_ops,
};
-static int msm_vpe_resource_init(struct platform_device *pdev);
+static int msm_vpe_resource_init(void);
-int msm_vpe_subdev_init(struct v4l2_subdev *sd, void *data,
- struct platform_device *pdev)
+int msm_vpe_subdev_init(struct v4l2_subdev *sd,
+ struct msm_cam_media_controller *mctl)
{
int rc = 0;
CDBG("%s:begin", __func__);
@@ -653,19 +653,19 @@
}
atomic_set(&vpe_init_done, 1);
- rc = msm_vpe_resource_init(pdev);
+ rc = msm_vpe_resource_init();
if (rc < 0) {
atomic_set(&vpe_init_done, 0);
return rc;
}
- v4l2_set_subdev_hostdata(sd, data);
+ v4l2_set_subdev_hostdata(sd, mctl);
spin_lock_init(&vpe_ctrl->lock);
CDBG("%s:end", __func__);
return rc;
}
EXPORT_SYMBOL(msm_vpe_subdev_init);
-static int msm_vpe_resource_init(struct platform_device *pdev)
+static int msm_vpe_resource_init(void)
{
int rc = 0;
@@ -686,7 +686,7 @@
return rc; /* this rc should have error code. */
}
-void msm_vpe_subdev_release(struct platform_device *pdev)
+void msm_vpe_subdev_release(void)
{
if (!atomic_read(&vpe_init_done)) {
/* no VPE object created */
@@ -702,6 +702,8 @@
}
EXPORT_SYMBOL(msm_vpe_subdev_release);
+static const struct v4l2_subdev_internal_ops msm_vpe_internal_ops;
+
static int __devinit vpe_probe(struct platform_device *pdev)
{
int rc = 0;
@@ -714,6 +716,8 @@
v4l2_subdev_init(&vpe_ctrl->subdev, &msm_vpe_subdev_ops);
v4l2_set_subdevdata(&vpe_ctrl->subdev, vpe_ctrl);
+ vpe_ctrl->subdev.internal_ops = &msm_vpe_internal_ops;
+ vpe_ctrl->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
snprintf(vpe_ctrl->subdev.name, sizeof(vpe_ctrl->subdev.name), "vpe");
platform_set_drvdata(pdev, &vpe_ctrl->subdev);
@@ -753,6 +757,7 @@
disable_irq(vpe_ctrl->vpeirq->start);
vpe_ctrl->pdev = pdev;
+ msm_cam_register_subdev_node(&vpe_ctrl->subdev, VPE_DEV, pdev->id);
return 0;
vpe_no_resource:
diff --git a/drivers/media/video/msm/wfd/enc-subdev.c b/drivers/media/video/msm/wfd/enc-subdev.c
index e9c710a..b7ae0f4 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.c
+++ b/drivers/media/video/msm/wfd/enc-subdev.c
@@ -244,9 +244,11 @@
WFD_MSG_DBG("EVENT: not expected = %d\n", event);
venc_stop_done(client_ctx, status);
break;
- case VCD_EVT_RESP_PAUSE:
case VCD_EVT_RESP_FLUSH_INPUT_DONE:
case VCD_EVT_RESP_FLUSH_OUTPUT_DONE:
+ venc_notify_client(client_ctx);
+ break;
+ case VCD_EVT_RESP_PAUSE:
case VCD_EVT_IND_OUTPUT_RECONFIG:
WFD_MSG_DBG("EVENT: not expected = %d\n", event);
break;
@@ -1935,6 +1937,46 @@
(u8 *)kernel_vaddr);
}
+static long venc_flush_buffers(struct v4l2_subdev *sd, void *arg)
+{
+ int rc = 0;
+ struct venc_inst *inst = sd->dev_priv;
+ struct video_client_ctx *client_ctx = &inst->venc_client;
+ if (!client_ctx) {
+ WFD_MSG_ERR("Invalid input\n");
+ return -EINVAL;
+ }
+ rc = vcd_flush(client_ctx->vcd_handle, VCD_FLUSH_INPUT);
+ if (rc) {
+ WFD_MSG_ERR("Failed to flush input buffers\n");
+ rc = -EIO;
+ goto flush_failed;
+ }
+ wait_for_completion(&client_ctx->event);
+ if (client_ctx->event_status) {
+ WFD_MSG_ERR("callback for vcd_flush input returned error: %u",
+ client_ctx->event_status);
+ rc = -EIO;
+ goto flush_failed;
+ }
+ rc = vcd_flush(client_ctx->vcd_handle, VCD_FLUSH_OUTPUT);
+ if (rc) {
+ WFD_MSG_ERR("Failed to flush output buffers\n");
+ rc = -EIO;
+ goto flush_failed;
+ }
+ wait_for_completion(&client_ctx->event);
+ if (client_ctx->event_status) {
+ WFD_MSG_ERR("callback for vcd_flush output returned error: %u",
+ client_ctx->event_status);
+ rc = -EIO;
+ goto flush_failed;
+ }
+
+flush_failed:
+ return rc;
+}
+
static long venc_free_input_buffer(struct v4l2_subdev *sd, void *arg)
{
int del_rc = 0, free_rc = 0;
@@ -2203,6 +2245,9 @@
case FREE_RECON_BUFFERS:
rc = venc_free_recon_buffers(sd, arg);
break;
+ case ENCODE_FLUSH:
+ rc = venc_flush_buffers(sd, arg);
+ break;
default:
rc = -1;
break;
diff --git a/drivers/media/video/msm/wfd/enc-subdev.h b/drivers/media/video/msm/wfd/enc-subdev.h
index cafc9d5..5873e62 100644
--- a/drivers/media/video/msm/wfd/enc-subdev.h
+++ b/drivers/media/video/msm/wfd/enc-subdev.h
@@ -74,6 +74,7 @@
#define FREE_OUTPUT_BUFFER _IOWR('V', 21, struct mem_region *)
#define FREE_INPUT_BUFFER _IOWR('V', 22, struct mem_region *)
#define FREE_RECON_BUFFERS _IO('V', 23)
+#define ENCODE_FLUSH _IO('V', 24)
extern int venc_init(struct v4l2_subdev *sd, u32 val);
extern int venc_load_fw(struct v4l2_subdev *sd);
diff --git a/drivers/media/video/msm/wfd/wfd-ioctl.c b/drivers/media/video/msm/wfd/wfd-ioctl.c
index 7ab5d17..0a2b1c1 100644
--- a/drivers/media/video/msm/wfd/wfd-ioctl.c
+++ b/drivers/media/video/msm/wfd/wfd-ioctl.c
@@ -614,6 +614,10 @@
WFD_MSG_ERR("Failed to stop VSG\n");
kthread_stop(inst->mdp_task);
+ rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
+ ENCODE_FLUSH, (void *)inst->venc_inst);
+ if (rc)
+ WFD_MSG_ERR("Failed to flush encoder\n");
WFD_MSG_DBG("enc stop\n");
rc = v4l2_subdev_call(&wfd_dev->enc_sdev, core, ioctl,
ENCODE_STOP, (void *)inst->venc_inst);
diff --git a/drivers/mfd/marimba-core.c b/drivers/mfd/marimba-core.c
index e168c49..8b41518 100644
--- a/drivers/mfd/marimba-core.c
+++ b/drivers/mfd/marimba-core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -748,7 +748,7 @@
}
}
-static int marimba_probe(struct i2c_client *client,
+static int __devinit marimba_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct marimba_platform_data *pdata = client->dev.platform_data;
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 39bcf16..ea5b851 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -697,7 +697,7 @@
for (i = 0; total < prop->length; total += l, p += l) {
l = strlen(p) + 1;
- if ((*p != 0) && (i++ == index)) {
+ if (i++ == index) {
*output = p;
return 0;
}
@@ -735,11 +735,9 @@
p = prop->value;
- for (i = 0; total < prop->length; total += l, p += l) {
+ for (i = 0; total < prop->length; total += l, p += l, i++)
l = strlen(p) + 1;
- if (*p != 0)
- i++;
- }
+
return i;
}
EXPORT_SYMBOL_GPL(of_property_count_strings);
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 8e9d753..de5e741 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -77,6 +77,7 @@
#define CHG_ITRIM 0x35B
#define CHG_TTRIM 0x35C
#define CHG_COMP_OVR 0x20A
+#define IUSB_FINE_RES 0x2B6
/* check EOC every 10 seconds */
#define EOC_CHECK_PERIOD_MS 10000
@@ -243,6 +244,7 @@
bool keep_btm_on_suspend;
bool ext_charging;
bool ext_charge_done;
+ bool iusb_fine_res;
DECLARE_BITMAP(enabled_irqs, PM_CHG_MAX_INTS);
struct work_struct battery_id_valid_work;
int64_t batt_id_min;
@@ -657,50 +659,110 @@
}
struct usb_ma_limit_entry {
- int usb_ma;
+ int usb_ma;
+ u8 value;
};
static struct usb_ma_limit_entry usb_ma_table[] = {
- {100},
- {500},
- {700},
- {850},
- {900},
- {1100},
- {1300},
- {1500},
+ {100, 0x0},
+ {200, 0x1},
+ {500, 0x2},
+ {600, 0x3},
+ {700, 0x4},
+ {800, 0x5},
+ {850, 0x6},
+ {900, 0x8},
+ {950, 0x7},
+ {1000, 0x9},
+ {1100, 0xA},
+ {1200, 0xB},
+ {1300, 0xC},
+ {1400, 0xD},
+ {1500, 0xE},
+ {1600, 0xF},
};
#define PM8921_CHG_IUSB_MASK 0x1C
+#define PM8921_CHG_IUSB_SHIFT 2
#define PM8921_CHG_IUSB_MAX 7
#define PM8921_CHG_IUSB_MIN 0
+#define PM8917_IUSB_FINE_RES BIT(0)
static int pm_chg_iusbmax_set(struct pm8921_chg_chip *chip, int reg_val)
{
- u8 temp;
+ u8 temp, fineres;
+ int rc;
+
+ fineres = PM8917_IUSB_FINE_RES & usb_ma_table[reg_val].value;
+ reg_val = usb_ma_table[reg_val].value >> 1;
if (reg_val < PM8921_CHG_IUSB_MIN || reg_val > PM8921_CHG_IUSB_MAX) {
pr_err("bad mA=%d asked to set\n", reg_val);
return -EINVAL;
}
- temp = reg_val << 2;
- return pm_chg_masked_write(chip, PBL_ACCESS2, PM8921_CHG_IUSB_MASK,
- temp);
+ temp = reg_val << PM8921_CHG_IUSB_SHIFT;
+
+ /* IUSB_FINE_RES */
+ if (chip->iusb_fine_res) {
+ /* Clear IUSB_FINE_RES bit to avoid overshoot */
+ rc = pm_chg_masked_write(chip, IUSB_FINE_RES,
+ PM8917_IUSB_FINE_RES, 0);
+
+ rc |= pm_chg_masked_write(chip, PBL_ACCESS2,
+ PM8921_CHG_IUSB_MASK, temp);
+
+ if (rc) {
+ pr_err("Failed to write PBL_ACCESS2 rc=%d\n", rc);
+ return rc;
+ }
+
+ if (fineres) {
+ rc = pm_chg_masked_write(chip, IUSB_FINE_RES,
+ PM8917_IUSB_FINE_RES, fineres);
+ if (rc)
+ pr_err("Failed to write ISUB_FINE_RES rc=%d\n",
+ rc);
+ }
+ } else {
+ rc = pm_chg_masked_write(chip, PBL_ACCESS2,
+ PM8921_CHG_IUSB_MASK, temp);
+ if (rc)
+ pr_err("Failed to write PBL_ACCESS2 rc=%d\n", rc);
+ }
+
+ return rc;
}
static int pm_chg_iusbmax_get(struct pm8921_chg_chip *chip, int *mA)
{
- u8 temp;
- int rc;
+ u8 temp, fineres;
+ int rc, i;
+ fineres = 0;
*mA = 0;
rc = pm8xxx_readb(chip->dev->parent, PBL_ACCESS2, &temp);
if (rc) {
pr_err("err=%d reading PBL_ACCESS2\n", rc);
return rc;
}
+
+ if (chip->iusb_fine_res) {
+ rc = pm8xxx_readb(chip->dev->parent, IUSB_FINE_RES, &fineres);
+ if (rc) {
+ pr_err("err=%d reading IUSB_FINE_RES\n", rc);
+ return rc;
+ }
+ }
temp &= PM8921_CHG_IUSB_MASK;
- temp = temp >> 2;
- *mA = usb_ma_table[temp].usb_ma;
+ temp = temp >> PM8921_CHG_IUSB_SHIFT;
+
+ temp = (temp << 1) | (fineres & PM8917_IUSB_FINE_RES);
+ for (i = ARRAY_SIZE(usb_ma_table) - 1; i >= 0; i--) {
+ if (usb_ma_table[i].value == temp)
+ break;
+ }
+
+ *mA = usb_ma_table[i].usb_ma;
+
return rc;
}
@@ -1450,8 +1512,12 @@
static void __pm8921_charger_vbus_draw(unsigned int mA)
{
int i, rc;
+ if (!the_chip) {
+ pr_err("called before init\n");
+ return;
+ }
- if (mA > 0 && mA <= 2) {
+ if (mA >= 0 && mA <= 2) {
usb_chg_current = 0;
rc = pm_chg_iusbmax_set(the_chip, 0);
if (rc) {
@@ -1468,6 +1534,11 @@
if (usb_ma_table[i].usb_ma <= mA)
break;
}
+
+ /* Check if IUSB_FINE_RES is available */
+ if ((usb_ma_table[i].value & PM8917_IUSB_FINE_RES)
+ && !the_chip->iusb_fine_res)
+ i--;
if (i < 0)
i = 0;
rc = pm_chg_iusbmax_set(the_chip, i);
@@ -1972,6 +2043,12 @@
if (i < (ARRAY_SIZE(usb_ma_table) - 1))
i++;
+ /* Get next correct entry if IUSB_FINE_RES is not available */
+ while (!the_chip->iusb_fine_res
+ && (usb_ma_table[i].value & PM8917_IUSB_FINE_RES)
+ && i < (ARRAY_SIZE(usb_ma_table) - 1))
+ i++;
+
*value = usb_ma_table[i].usb_ma;
}
}
@@ -3411,6 +3488,10 @@
if (pm8xxx_get_revision(chip->dev->parent) == PM8XXX_REVISION_8921_3p0)
pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xAC);
+ /* Enable isub_fine resolution AICL for PM8917 */
+ if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917)
+ chip->iusb_fine_res = true;
+
pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0xD9);
/* Disable EOC FSM processing */
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 1457ab2..a83f6d3 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -40,6 +40,8 @@
#include <mach/msm_xo.h>
#include <linux/spinlock.h>
+#define RUNTIME_SUSP_DELAY 500
+
#define MSM_USB_BASE (hcd->regs)
struct msm_hsic_hcd {
@@ -57,6 +59,7 @@
int peripheral_status_irq;
int wakeup_irq;
bool wakeup_irq_enabled;
+ bool pm_resume;
uint32_t bus_perf_client;
};
@@ -766,8 +769,6 @@
debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
}
-
-
static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
{
struct usb_hcd *hcd;
@@ -954,6 +955,7 @@
ehci_hsic_msm_debugfs_cleanup();
device_init_wakeup(&pdev->dev, 0);
+ mehci->pm_resume = false;
pm_runtime_set_suspended(&pdev->dev);
usb_remove_hcd(hcd);
@@ -979,6 +981,8 @@
if (device_may_wakeup(dev))
enable_irq_wake(hcd->irq);
+ mehci->pm_resume = false;
+
return msm_hsic_suspend(mehci);
}
@@ -1015,6 +1019,8 @@
disable_irq_nosync(mehci->wakeup_irq);
}
+ mehci->pm_resume = true;
+
ret = msm_hsic_resume(mehci);
if (ret)
return ret;
@@ -1031,8 +1037,17 @@
#ifdef CONFIG_PM_RUNTIME
static int msm_hsic_runtime_idle(struct device *dev)
{
+ struct usb_hcd *hcd = dev_get_drvdata(dev);
+ struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
+
dev_dbg(dev, "EHCI runtime idle\n");
+ if (mehci->pm_resume) {
+ mehci->pm_resume = false;
+ pm_schedule_suspend(dev, RUNTIME_SUSP_DELAY);
+ return -EAGAIN;
+ }
+
return 0;
}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
index 6ebc955..8156505 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
@@ -300,6 +300,27 @@
encoder->seq_header.virtual_base_addr,
encoder->seq_header.buffer_size,
ION_IOC_CLEAN_INV_CACHES);
+ if (encoder->slice_delivery_info.enable) {
+ DDL_MSG_LOW("%s: slice mode allocate memory for struct\n",
+ __func__);
+ ptr = ddl_pmem_alloc(&encoder->batch_frame.slice_batch_in,
+ DDL_ENC_SLICE_BATCH_INPSTRUCT_SIZE,
+ DDL_LINEAR_BUFFER_ALIGN_BYTES);
+ if (ptr) {
+ ptr = ddl_pmem_alloc(
+ &encoder->batch_frame.slice_batch_out,
+ DDL_ENC_SLICE_BATCH_OUTSTRUCT_SIZE,
+ DDL_LINEAR_BUFFER_ALIGN_BYTES);
+ }
+ if (!ptr) {
+ ddl_pmem_free(&encoder->batch_frame.slice_batch_in);
+ ddl_pmem_free(&encoder->batch_frame.slice_batch_out);
+ ddl_free_enc_hw_buffers(ddl);
+ ddl_pmem_free(&encoder->seq_header);
+ DDL_MSG_ERROR("ddlEncStart:SeqHdrAllocFailed");
+ return VCD_ERR_ALLOC_FAIL;
+ }
+ }
if (!ddl_take_command_channel(ddl_context, ddl, client_data))
return VCD_ERR_BUSY;
ddl_vidc_channel_set(ddl);
@@ -451,7 +472,17 @@
struct ddl_client_context *ddl =
(struct ddl_client_context *) ddl_handle;
struct ddl_context *ddl_context;
+ struct ddl_encoder_data *encoder =
+ &ddl->codec_data.encoder;
u32 vcd_status = VCD_S_SUCCESS;
+ if (encoder->slice_delivery_info.enable) {
+ return ddl_encode_frame_batch(ddl_handle,
+ input_frame,
+ output_bit,
+ 1,
+ encoder->slice_delivery_info.num_slices,
+ client_data);
+ }
DDL_MSG_HIGH("ddl_encode_frame");
if (vidc_msg_timing)
@@ -519,6 +550,76 @@
return vcd_status;
}
+u32 ddl_encode_frame_batch(u32 *ddl_handle,
+ struct ddl_frame_data_tag *input_frame,
+ struct ddl_frame_data_tag *output_bit,
+ u32 num_in_frames, u32 num_out_frames,
+ void *client_data)
+{
+ struct ddl_client_context *ddl =
+ (struct ddl_client_context *) ddl_handle;
+ struct ddl_context *ddl_context;
+ u32 vcd_status = VCD_S_SUCCESS;
+ struct ddl_encoder_data *encoder;
+
+ DDL_MSG_LOW("ddl_encode_frame_batch");
+ ddl_context = ddl_get_context();
+ if (!DDL_IS_INITIALIZED(ddl_context)) {
+ DDL_MSG_ERROR("ddl_enc_frame:Not_inited");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (DDL_IS_BUSY(ddl_context)) {
+ DDL_MSG_ERROR("ddl_enc_frame:Ddl_busy");
+ return VCD_ERR_BUSY;
+ }
+ if (!ddl || ddl->decoding) {
+ DDL_MSG_ERROR("ddl_enc_frame:Bad_handle");
+ return VCD_ERR_BAD_HANDLE;
+ }
+ if (!input_frame || !input_frame->vcd_frm.physical ||
+ !input_frame->vcd_frm.data_len) {
+ DDL_MSG_ERROR("ddl_enc_frame:Bad_input_params");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ if ((((u32) input_frame->vcd_frm.physical +
+ input_frame->vcd_frm.offset) &
+ (DDL_STREAMBUF_ALIGN_GUARD_BYTES))) {
+ DDL_MSG_ERROR("ddl_enc_frame:Un_aligned_yuv_start_address");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ if (!output_bit || !output_bit->vcd_frm.physical ||
+ !output_bit->vcd_frm.alloc_len) {
+ DDL_MSG_ERROR("ddl_enc_frame:Bad_output_params");
+ return VCD_ERR_ILLEGAL_PARM;
+ }
+ if ((ddl->codec_data.encoder.output_buf_req.sz +
+ output_bit->vcd_frm.offset) >
+ output_bit->vcd_frm.alloc_len)
+ DDL_MSG_ERROR("ddl_enc_frame:offset_large,"
+ "Exceeds_min_buf_size");
+ if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME)) {
+ DDL_MSG_ERROR("ddl_enc_frame:Wrong_state");
+ return VCD_ERR_ILLEGAL_OP;
+ }
+ if (!ddl_take_command_channel(ddl_context, ddl, client_data))
+ return VCD_ERR_BUSY;
+ encoder = &ddl->codec_data.encoder;
+ if (encoder->slice_delivery_info.enable) {
+ DDL_MEMCPY((void *)&(encoder->batch_frame.output_frame[0]),
+ (void *)output_bit,
+ sizeof(struct ddl_frame_data_tag) * num_out_frames);
+ encoder->batch_frame.num_output_frames = num_out_frames;
+ ddl->input_frame = *input_frame;
+ vcd_status = ddl_insert_input_frame_to_pool(ddl, input_frame);
+ if (!vcd_status)
+ ddl_vidc_encode_slice_batch_run(ddl);
+ else
+ DDL_MSG_ERROR("insert to frame pool failed %u",
+ vcd_status);
+ }
+ return vcd_status;
+}
+
u32 ddl_decode_end(u32 *ddl_handle, void *client_data)
{
struct ddl_client_context *ddl =
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
index c3874fa..d05e542 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
@@ -113,6 +113,7 @@
DDL_CMD_ENCODE_FRAME = 0x8,
DDL_CMD_EOS = 0x9,
DDL_CMD_CHANNEL_END = 0xA,
+ DDL_CMD_ENCODE_CONTINUE = 0xB,
DDL_CMD_32BIT = 0x7FFFFFFF
};
enum ddl_client_state{
@@ -129,6 +130,7 @@
DDL_CLIENT_WAIT_FOR_CHEND = 0xA,
DDL_CLIENT_FATAL_ERROR = 0xB,
DDL_CLIENT_FAVIDC_ERROR = 0xC,
+ DDL_CLIENT_WAIT_FOR_CONTINUE = 0xD,
DDL_CLIENT_32BIT = 0x7FFFFFFF
};
struct ddl_hw_interface{
@@ -215,6 +217,15 @@
struct ddl_codec_data_hdr{
u32 decoding;
};
+struct ddl_batch_frame_data {
+ struct ddl_buf_addr slice_batch_in;
+ struct ddl_buf_addr slice_batch_out;
+ struct ddl_frame_data_tag input_frame;
+ struct ddl_frame_data_tag output_frame
+ [DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH];
+ u32 num_output_frames;
+ u32 out_frm_next_frmindex;
+};
struct ddl_encoder_data{
struct ddl_codec_data_hdr hdr;
struct vcd_property_codec codec;
@@ -262,6 +273,8 @@
u32 ext_enc_control_val;
u32 num_references_for_p_frame;
u32 closed_gop;
+ struct vcd_property_slice_delivery_info slice_delivery_info;
+ struct ddl_batch_frame_data batch_frame;
};
struct ddl_decoder_data {
struct ddl_codec_data_hdr hdr;
@@ -344,6 +357,8 @@
(struct vidc_1080p_enc_seq_start_param *param);
void(*vidc_encode_frame_start[2])
(struct vidc_1080p_enc_frame_start_param *param);
+ void(*vidc_encode_slice_batch_start[2])
+ (struct vidc_1080p_enc_frame_start_param *param);
u32 frame_channel_depth;
};
struct ddl_client_context{
@@ -375,9 +390,12 @@
void ddl_vidc_channel_end(struct ddl_client_context *);
void ddl_vidc_encode_init_codec(struct ddl_client_context *);
void ddl_vidc_decode_init_codec(struct ddl_client_context *);
+void ddl_vidc_encode_frame_continue(struct ddl_client_context *);
void ddl_vidc_encode_frame_run(struct ddl_client_context *);
+void ddl_vidc_encode_slice_batch_run(struct ddl_client_context *);
void ddl_vidc_decode_frame_run(struct ddl_client_context *);
void ddl_vidc_decode_eos_run(struct ddl_client_context *ddl);
+void ddl_vidc_encode_eos_run(struct ddl_client_context *ddl);
void ddl_release_context_buffers(struct ddl_context *);
void ddl_release_client_internal_buffers(struct ddl_client_context *ddl);
u32 ddl_vidc_decode_set_buffers(struct ddl_client_context *);
@@ -438,9 +456,10 @@
u32 ddl_get_input_frame_from_pool(struct ddl_client_context *ddl,
u8 *input_buffer_address);
+u32 ddl_get_stream_buf_from_batch_pool(struct ddl_client_context *ddl,
+ struct ddl_frame_data_tag *stream_buffer);
u32 ddl_insert_input_frame_to_pool(struct ddl_client_context *ddl,
struct ddl_frame_data_tag *ddl_input_frame);
-
void ddl_decoder_chroma_dpb_change(struct ddl_client_context *ddl);
u32 ddl_check_reconfig(struct ddl_client_context *ddl);
void ddl_handle_reconfig(u32 res_change, struct ddl_client_context *ddl);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h
index 433dad4..5c1ee21 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_api.h
@@ -62,6 +62,11 @@
u32 disable_static_region_as_flag;
u32 disable_activity_region_flag;
};
+struct vcd_property_slice_delivery_info {
+ u32 enable;
+ u32 num_slices;
+ u32 num_slices_enc;
+};
struct ddl_property_dec_pic_buffers{
struct ddl_frame_data_tag *dec_pic_buffers;
u32 no_of_dec_pic_buf;
@@ -94,6 +99,11 @@
u32 ddl_encode_frame(u32 *ddl_handle,
struct ddl_frame_data_tag *input_frame,
struct ddl_frame_data_tag *output_bit, void *client_data);
+u32 ddl_encode_frame_batch(u32 *ddl_handle,
+ struct ddl_frame_data_tag *input_frame,
+ struct ddl_frame_data_tag *output_bit,
+ u32 num_in_frames, u32 num_out_frames,
+ void *client_data);
u32 ddl_encode_end(u32 *ddl_handle, void *client_data);
u32 ddl_decode_start(u32 *ddl_handle, struct vcd_sequence_hdr *header,
void *client_data);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
index a8ccebf..41604b0 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
@@ -64,13 +64,20 @@
#define DDL_FW_INST_GLOBAL_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(800))
#define DDL_FW_H264DEC_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(800))
#define DDL_FW_H264ENC_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(20))
-#define DDL_FW_OTHER_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(10))
+#define DDL_FW_OTHER_CONTEXT_SPACE_SIZE (DDL_KILO_BYTE(20))
#define VCD_DEC_CPB_SIZE (DDL_KILO_BYTE(512))
#define DDL_DBG_CORE_DUMP_SIZE (DDL_KILO_BYTE(10))
+#define DDL_VIDC_1080P_BASE_OFFSET_SHIFT 11
#define DDL_BUFEND_PAD 256
#define DDL_ENC_SEQHEADER_SIZE (512+DDL_BUFEND_PAD)
+#define DDL_ENC_SLICE_BATCH_FACTOR 5
+#define DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH 8
+#define DDL_ENC_SLICE_BATCH_INPSTRUCT_SIZE (128 + \
+ 32 * DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH)
+#define DDL_ENC_SLICE_BATCH_OUTSTRUCT_SIZE (64 + \
+ 64 * DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH)
#define DDL_MAX_BUFFER_COUNT 32
#define DDL_MIN_BUFFER_COUNT 1
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
index 62f0976..0d0ba3e 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -375,6 +375,8 @@
struct ddl_encoder_data *encoder =
&(ddl->codec_data.encoder);
ddl_pmem_free(&encoder->seq_header);
+ ddl_pmem_free(&encoder->batch_frame.slice_batch_in);
+ ddl_pmem_free(&encoder->batch_frame.slice_batch_out);
ddl_vidc_encode_dynamic_property(ddl, false);
encoder->dynamic_prop_change = 0;
ddl_free_enc_hw_buffers(ddl);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index 830c777c3..79e6c5d 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -29,7 +29,11 @@
enum vidc_1080p_encode_frame frame_type);
static void ddl_get_dec_profile_level(struct ddl_decoder_data *decoder,
u32 profile, u32 level);
-static void ddl_handle_enc_frame_done(struct ddl_client_context *ddl);
+static void ddl_handle_enc_frame_done(struct ddl_client_context *ddl,
+ u32 eos_present);
+static void ddl_handle_slice_done_slice_batch(struct ddl_client_context *ddl);
+static void ddl_handle_enc_frame_done_slice_mode(
+ struct ddl_client_context *ddl, u32 eos_present);
static void ddl_fw_status_done_callback(struct ddl_context *ddl_context)
{
@@ -141,7 +145,7 @@
{
struct ddl_encoder_data *encoder;
- DDL_MSG_MED("ddl_encoder_seq_done_callback");
+ DDL_MSG_HIGH("ddl_encoder_seq_done_callback");
if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_INITCODECDONE)) {
DDL_MSG_ERROR("STATE-CRITICAL-INITCODEC");
ddl_client_fatal_cb(ddl);
@@ -486,9 +490,9 @@
&(ddl->codec_data.encoder);
struct vcd_frame_data *output_frame =
&(ddl->output_frame.vcd_frm);
- u32 bottom_frame_tag;
+ u32 eos_present = false;
- DDL_MSG_MED("ddl_encoder_frame_run_callback");
+ DDL_MSG_MED("ddl_encoder_frame_run_callback\n");
if (!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_FRAME_DONE) &&
!DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE)) {
DDL_MSG_ERROR("STATE-CRITICAL-ENCFRMRUN");
@@ -499,47 +503,28 @@
DDL_MSG_LOW("ENC_FRM_RUN_DONE");
ddl->cmd_state = DDL_CMD_INVALID;
vidc_1080p_get_encode_frame_info(&encoder->enc_frame_info);
- vidc_sm_get_frame_tags(&ddl->shared_mem
- [ddl->command_channel],
- &output_frame->ip_frm_tag, &bottom_frame_tag);
if (encoder->meta_data_enable_flag)
vidc_sm_get_metadata_status(&ddl->shared_mem
[ddl->command_channel],
&encoder->enc_frame_info.meta_data_exists);
+ if (VCD_FRAME_FLAG_EOS & ddl->input_frame.vcd_frm.flags) {
+ DDL_MSG_LOW("%s EOS detected\n", __func__);
+ eos_present = true;
+ }
+
if (encoder->enc_frame_info.enc_frame_size ||
(encoder->enc_frame_info.enc_frame ==
VIDC_1080P_ENCODE_FRAMETYPE_SKIPPED) ||
DDLCLIENT_STATE_IS(ddl,
DDL_CLIENT_WAIT_FOR_EOS_DONE)) {
- u8 *input_buffer_address = NULL;
- output_frame->data_len =
- encoder->enc_frame_info.enc_frame_size;
- output_frame->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
- ddl_get_encoded_frame(output_frame,
- encoder->codec.codec,
- encoder->enc_frame_info.enc_frame);
- ddl_process_encoder_metadata(ddl);
- ddl_vidc_encode_dynamic_property(ddl, false);
- ddl->input_frame.frm_trans_end = false;
- input_buffer_address = ddl_context->dram_base_a.\
- align_physical_addr +
- encoder->enc_frame_info.enc_luma_address;
- ddl_get_input_frame_from_pool(ddl,
- input_buffer_address);
- ddl_context->ddl_callback(VCD_EVT_RESP_INPUT_DONE,
- VCD_S_SUCCESS, &(ddl->input_frame),
- sizeof(struct ddl_frame_data_tag),
- (u32 *)ddl, ddl->client_data);
- ddl->output_frame.frm_trans_end =
- DDLCLIENT_STATE_IS(ddl,
- DDL_CLIENT_WAIT_FOR_EOS_DONE) ? false : true;
- ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
- VCD_S_SUCCESS, &(ddl->output_frame),
- sizeof(struct ddl_frame_data_tag),
- (u32 *)ddl, ddl->client_data);
-
+ if (encoder->slice_delivery_info.enable) {
+ ddl_handle_enc_frame_done_slice_mode(ddl,
+ eos_present);
+ } else {
+ ddl_handle_enc_frame_done(ddl, eos_present);
+ }
if (DDLCLIENT_STATE_IS(ddl,
DDL_CLIENT_WAIT_FOR_EOS_DONE) &&
encoder->i_period.b_frames) {
@@ -547,7 +532,7 @@
(ddl->extra_output_buf_count >
encoder->i_period.b_frames)) {
DDL_MSG_ERROR("Invalid B frame output"
- "buffer index");
+ "buffer index");
} else {
struct vidc_1080p_enc_frame_start_param
enc_param;
@@ -581,7 +566,11 @@
ddl_context->vidc_encode_frame_start
[ddl->command_channel]
(&enc_param);
- } } else {
+ }
+ } else if (eos_present &&
+ encoder->slice_delivery_info.enable) {
+ ddl_vidc_encode_eos_run(ddl);
+ } else {
DDL_MSG_LOW("ddl_state_transition: %s ~~>"
"DDL_CLIENT_WAIT_FOR_FRAME",
ddl_get_state_string(
@@ -885,6 +874,7 @@
vidc_1080p_clear_returned_channel_inst_id();
ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context,
ddl_context->response_cmd_ch_id);
+ DDL_MSG_LOW("ddl_encoder_eos_done\n");
if (ddl == NULL) {
DDL_MSG_ERROR("NO_DDL_CONTEXT");
} else {
@@ -896,9 +886,11 @@
&(ddl->codec_data.encoder);
vidc_1080p_get_encode_frame_info(
&encoder->enc_frame_info);
- ddl_handle_enc_frame_done(ddl);
+ if (!encoder->slice_delivery_info.enable) {
+ ddl_handle_enc_frame_done(ddl, true);
+ ddl->cmd_state = DDL_CMD_INVALID;
+ }
DDL_MSG_LOW("encoder_eos_done");
- ddl->cmd_state = DDL_CMD_INVALID;
DDL_MSG_LOW("ddl_state_transition: %s ~~>"
"DDL_CLIENT_WAIT_FOR_FRAME",
ddl_get_state_string(ddl->client_state));
@@ -913,6 +905,35 @@
}
}
+static u32 ddl_slice_done_callback(struct ddl_context *ddl_context)
+{
+ struct ddl_client_context *ddl;
+ u32 channel_inst_id;
+ u32 return_status = true;
+ DDL_MSG_LOW("ddl_sliceDoneCallback");
+ vidc_1080p_get_returned_channel_inst_id(&channel_inst_id);
+ vidc_1080p_clear_returned_channel_inst_id();
+ ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context,
+ ddl_context->response_cmd_ch_id);
+ if (ddl == NULL) {
+ DDL_MSG_ERROR("NO_DDL_CONTEXT");
+ return_status = false;
+ } else if (ddl->cmd_state == DDL_CMD_ENCODE_FRAME) {
+ ddl->cmd_state = DDL_CMD_INVALID;
+ if (DDLCLIENT_STATE_IS(ddl,
+ DDL_CLIENT_WAIT_FOR_FRAME_DONE)) {
+ ddl_handle_slice_done_slice_batch(ddl);
+ } else {
+ DDL_MSG_ERROR("STATE-CRITICAL-ENCFRMRUN : %s\n",
+ __func__);
+ ddl_client_fatal_cb(ddl);
+ }
+ } else {
+ DDL_MSG_ERROR("UNKNOWN_SLICEDONE : %s\n", __func__);
+ }
+ return return_status;
+}
+
static u32 ddl_process_intr_status(struct ddl_context *ddl_context,
u32 intr_status)
{
@@ -931,6 +952,9 @@
case VIDC_1080P_RISC2HOST_CMD_FRAME_DONE_RET:
return_status = ddl_frame_run_callback(ddl_context);
break;
+ case VIDC_1080P_RISC2HOST_CMD_SLICE_DONE_RET:
+ ddl_slice_done_callback(ddl_context);
+ break;
case VIDC_1080P_RISC2HOST_CMD_SYS_INIT_RET:
ddl_sys_init_done_callback(ddl_context,
ddl_context->response_cmd_ch_id);
@@ -963,6 +987,8 @@
{
struct ddl_context *ddl_context;
struct ddl_hw_interface *ddl_hw_response;
+ struct ddl_client_context *ddl;
+ struct ddl_encoder_data *encoder;
ddl_context = ddl_get_context();
if (!ddl_context->core_virtual_base_addr) {
@@ -971,12 +997,37 @@
ddl_hw_response = &ddl_context->ddl_hw_response;
vidc_1080p_get_risc2host_cmd(&ddl_hw_response->cmd,
&ddl_hw_response->arg1, &ddl_hw_response->arg2,
- &ddl_hw_response->arg3, &ddl_hw_response->arg4);
+ &ddl_hw_response->arg3,
+ &ddl_hw_response->arg4);
+ DDL_MSG_LOW("%s vidc_1080p_get_risc2host_cmd cmd = %u"
+ "arg1 = %u arg2 = %u arg3 = %u"
+ "arg4 = %u\n",
+ __func__, ddl_hw_response->cmd,
+ ddl_hw_response->arg1, ddl_hw_response->arg2,
+ ddl_hw_response->arg3,
+ ddl_hw_response->arg4);
+ ddl = ddl_get_current_ddl_client_for_channel_id(ddl_context,
+ ddl_context->response_cmd_ch_id);
+ if (ddl) {
+ encoder = &(ddl->codec_data.encoder);
+ if (encoder && encoder->slice_delivery_info.enable
+ &&
+ ((ddl_hw_response->cmd ==
+ VIDC_1080P_RISC2HOST_CMD_SLICE_DONE_RET)
+ || (ddl_hw_response->cmd ==
+ VIDC_1080P_RISC2HOST_CMD_FRAME_DONE_RET))) {
+ vidc_sm_set_encoder_slice_batch_int_ctrl(
+ &ddl->shared_mem[ddl->command_channel],
+ 1);
+ }
+ }
vidc_1080p_clear_risc2host_cmd();
vidc_1080p_clear_interrupt();
vidc_1080p_get_risc2host_cmd_status(ddl_hw_response->arg2,
&ddl_context->cmd_err_status,
&ddl_context->disp_pic_err_status);
+ DDL_MSG_LOW("%s cmd_err_status = %d\n", __func__,
+ ddl_context->cmd_err_status);
ddl_context->response_cmd_ch_id = ddl_hw_response->arg1;
}
}
@@ -1638,39 +1689,214 @@
decoder->level.level = level;
}
-static void ddl_handle_enc_frame_done(struct ddl_client_context *ddl)
+static void ddl_handle_enc_frame_done(struct ddl_client_context *ddl,
+ u32 eos_present)
{
struct ddl_context *ddl_context = ddl->ddl_context;
struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
struct vcd_frame_data *output_frame = &(ddl->output_frame.vcd_frm);
u32 bottom_frame_tag;
- u8 *input_buffer_address = NULL;
+ u8 *input_buffer_address = NULL;
vidc_sm_get_frame_tags(&ddl->shared_mem[ddl->command_channel],
&output_frame->ip_frm_tag, &bottom_frame_tag);
output_frame->data_len = encoder->enc_frame_info.enc_frame_size;
output_frame->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
(void)ddl_get_encoded_frame(output_frame,
- encoder->codec.codec, encoder->enc_frame_info.enc_frame);
+ encoder->codec.codec, encoder->enc_frame_info.enc_frame
+ );
ddl_process_encoder_metadata(ddl);
ddl_vidc_encode_dynamic_property(ddl, false);
ddl->input_frame.frm_trans_end = false;
input_buffer_address = ddl_context->dram_base_a.align_physical_addr +
encoder->enc_frame_info.enc_luma_address;
ddl_get_input_frame_from_pool(ddl, input_buffer_address);
-
ddl_context->ddl_callback(VCD_EVT_RESP_INPUT_DONE,
- VCD_S_SUCCESS, &(ddl->input_frame),
- sizeof(struct ddl_frame_data_tag),
- (u32 *) ddl, ddl->client_data);
-
- ddl->output_frame.frm_trans_end =
- DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_WAIT_FOR_EOS_DONE)
- ? false : true;
-
+ VCD_S_SUCCESS, &(ddl->input_frame),
+ sizeof(struct ddl_frame_data_tag),
+ (u32 *) ddl, ddl->client_data);
+ ddl->output_frame.frm_trans_end = eos_present ?
+ false : true;
ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
- VCD_S_SUCCESS, &(ddl->output_frame),
- sizeof(struct ddl_frame_data_tag),
- (u32 *) ddl, ddl->client_data);
+ VCD_S_SUCCESS, &(ddl->output_frame),
+ sizeof(struct ddl_frame_data_tag),
+ (u32 *) ddl, ddl->client_data);
+}
+static void ddl_handle_slice_done_slice_batch(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ struct vcd_frame_data *output_frame = NULL;
+ u32 bottom_frame_tag;
+ struct vidc_1080p_enc_slice_batch_out_param *slice_output = NULL;
+ u32 num_slices_comp = 0;
+ u32 index = 0;
+ u32 start_bfr_idx = 0;
+ u32 actual_idx = 0;
+
+ DDL_MSG_LOW("%s\n", __func__);
+ vidc_sm_get_num_slices_comp(
+ &ddl->shared_mem[ddl->command_channel],
+ &num_slices_comp);
+ slice_output = (struct vidc_1080p_enc_slice_batch_out_param *)
+ (encoder->batch_frame.slice_batch_out.align_virtual_addr);
+ DDL_MSG_LOW(" after get no of slices = %d\n", num_slices_comp);
+ if (slice_output == NULL)
+ DDL_MSG_ERROR(" slice_output is NULL\n");
+ encoder->slice_delivery_info.num_slices_enc += num_slices_comp;
+ if (vidc_msg_timing) {
+ ddl_calc_core_proc_time_cnt(__func__, ENC_SLICE_OP_TIME,
+ num_slices_comp);
+ ddl_set_core_start_time(__func__, ENC_SLICE_OP_TIME);
+ }
+ DDL_MSG_LOW("%s : Slices Completed %d Total slices %d OutBfrInfo:"
+ "Cmd %d Size %d\n",
+ __func__,
+ num_slices_comp,
+ encoder->slice_delivery_info.num_slices_enc,
+ slice_output->cmd_type,
+ slice_output->output_size);
+ start_bfr_idx = encoder->batch_frame.out_frm_next_frmindex;
+ for (index = 0; index < num_slices_comp; index++) {
+ actual_idx =
+ slice_output->slice_info[start_bfr_idx+index].stream_buffer_idx;
+ DDL_MSG_LOW("Slice Info: OutBfrIndex %d SliceSize %d\n",
+ actual_idx,
+ slice_output->slice_info[start_bfr_idx+index].
+ stream_buffer_size);
+ output_frame = &(
+ encoder->batch_frame.output_frame[actual_idx].vcd_frm);
+ DDL_MSG_LOW("OutBfr: vcd_frm 0x%x frmbfr(virtual) 0x%x"
+ "frmbfr(physical) 0x%x\n",
+ &output_frame,
+ output_frame.virtual_base_addr,
+ output_frame.physical_base_addr);
+ vidc_1080p_get_encode_frame_info(&encoder->enc_frame_info);
+ vidc_sm_get_frame_tags(&ddl->shared_mem
+ [ddl->command_channel],
+ &output_frame->ip_frm_tag, &bottom_frame_tag);
+ ddl_get_encoded_frame(output_frame,
+ encoder->codec.codec,
+ encoder->enc_frame_info.enc_frame);
+ output_frame->data_len =
+ slice_output->slice_info[actual_idx].stream_buffer_size;
+ ddl->output_frame =
+ encoder->batch_frame.output_frame[actual_idx];
+ ddl->output_frame.frm_trans_end = false;
+ ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
+ VCD_S_SUCCESS, &(ddl->output_frame),
+ sizeof(struct ddl_frame_data_tag),
+ (u32 *) ddl, ddl->client_data);
+ ddl->input_frame.frm_trans_end = false;
+ DDL_MSG_LOW("%s Set i/p o/p transactions to false\n", __func__);
+ }
+ encoder->batch_frame.out_frm_next_frmindex = start_bfr_idx + index;
+ ddl->cmd_state = DDL_CMD_ENCODE_FRAME;
+ vidc_sm_set_encoder_slice_batch_int_ctrl(
+ &ddl->shared_mem[ddl->command_channel],
+ 0);
+}
+
+static void ddl_handle_enc_frame_done_slice_mode(
+ struct ddl_client_context *ddl, u32 eos_present)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ struct vcd_frame_data *output_frame = NULL;
+ u32 bottom_frame_tag;
+ u8 *input_buffer_address = NULL;
+ struct vidc_1080p_enc_slice_batch_out_param *slice_output = NULL;
+ u32 num_slices_comp = 0;
+ u32 index = 0;
+ u32 start_bfr_idx = 0;
+ u32 actual_idx = 0;
+ struct vcd_transc *transc;
+
+ DDL_MSG_LOW("%s\n", __func__);
+ vidc_sm_get_num_slices_comp(
+ &ddl->shared_mem[ddl->command_channel],
+ &num_slices_comp);
+ slice_output = (struct vidc_1080p_enc_slice_batch_out_param *)
+ encoder->batch_frame.slice_batch_out.align_virtual_addr;
+ encoder->slice_delivery_info.num_slices_enc += num_slices_comp;
+ if (vidc_msg_timing) {
+ ddl_calc_core_proc_time_cnt(__func__, ENC_OP_TIME,
+ num_slices_comp);
+ }
+ DDL_MSG_LOW("%s Slices Completed %d Total slices done = %d"
+ " OutBfrInfo: Cmd %d Size %d",
+ __func__,
+ num_slices_comp,
+ encoder->slice_delivery_info.num_slices_enc,
+ slice_output->cmd_type,
+ slice_output->output_size);
+ start_bfr_idx = encoder->batch_frame.out_frm_next_frmindex;
+ if ((encoder->slice_delivery_info.num_slices_enc %
+ encoder->batch_frame.num_output_frames) != 0) {
+ DDL_MSG_ERROR("ERROR : %d %d\n",
+ encoder->slice_delivery_info.num_slices_enc,
+ encoder->batch_frame.num_output_frames);
+ }
+ for (index = 0; index < num_slices_comp; index++) {
+ actual_idx =
+ slice_output->slice_info[start_bfr_idx+index]. \
+ stream_buffer_idx;
+ DDL_MSG_LOW("Slice Info: OutBfrIndex %d SliceSize %d",
+ actual_idx,
+ slice_output->slice_info[start_bfr_idx+index]. \
+ stream_buffer_size, 0);
+ output_frame =
+ &(encoder->batch_frame.output_frame[actual_idx].vcd_frm);
+ DDL_MSG_LOW("OutBfr: vcd_frm 0x%x frmbfr(virtual) 0x%x"
+ "frmbfr(physical) 0x%x",
+ &output_frame,
+ output_frame.virtual_base_addr,
+ output_frame.physical_base_addr);
+ vidc_1080p_get_encode_frame_info(
+ &encoder->enc_frame_info);
+ vidc_sm_get_frame_tags(&ddl->shared_mem
+ [ddl->command_channel],
+ &output_frame->ip_frm_tag, &bottom_frame_tag);
+ ddl_get_encoded_frame(output_frame,
+ encoder->codec.codec,
+ encoder->enc_frame_info.enc_frame);
+ output_frame->data_len =
+ slice_output->slice_info[actual_idx].stream_buffer_size;
+ ddl->output_frame =
+ encoder->batch_frame.output_frame[actual_idx];
+ DDL_MSG_LOW(" %s actual_idx = %d"
+ "encoder->batch_frame.num_output_frames = %d\n", __func__,
+ actual_idx, encoder->batch_frame.num_output_frames);
+ if (encoder->batch_frame.num_output_frames == (actual_idx+1)) {
+ output_frame->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
+ ddl_vidc_encode_dynamic_property(ddl, false);
+ ddl->input_frame.frm_trans_end = true;
+ DDL_MSG_LOW("%s End of frame detected\n", __func__);
+ input_buffer_address =
+ ddl_context->dram_base_a.align_physical_addr +
+ encoder->enc_frame_info.enc_luma_address;
+ ddl_get_input_frame_from_pool(ddl,
+ input_buffer_address);
+ transc = (struct vcd_transc *)(ddl->client_data);
+ if (eos_present)
+ ddl->output_frame.frm_trans_end = false;
+ else
+ ddl->output_frame.frm_trans_end = true;
+ }
+ DDL_MSG_LOW("%s Before output done cb\n", __func__);
+ transc = (struct vcd_transc *)(ddl->client_data);
+ ddl->output_frame.vcd_frm = *output_frame;
+ ddl_context->ddl_callback(VCD_EVT_RESP_OUTPUT_DONE,
+ VCD_S_SUCCESS, &(ddl->output_frame),
+ sizeof(struct ddl_frame_data_tag),
+ (u32 *) ddl, ddl->client_data);
+ }
+ if (encoder->batch_frame.num_output_frames == (actual_idx+1)) {
+ DDL_MSG_LOW("%s sending input done\n", __func__);
+ ddl_context->ddl_callback(VCD_EVT_RESP_INPUT_DONE,
+ VCD_S_SUCCESS, &(ddl->input_frame),
+ sizeof(struct ddl_frame_data_tag),
+ (u32 *) ddl, ddl->client_data);
+ }
}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index 7b284e9..2138c9c 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -287,6 +287,9 @@
ddl_set_default_decoder_buffer_req(decoder,
true);
}
+ DDL_MSG_LOW("set VCD_I_FRAME_SIZE width = %d"
+ " height = %d\n",
+ frame_size->width, frame_size->height);
vcd_status = VCD_S_SUCCESS;
}
}
@@ -608,7 +611,15 @@
struct vcd_property_multi_slice *multi_slice =
(struct vcd_property_multi_slice *)
property_value;
-
+ DDL_MSG_HIGH("VCD_I_MULTI_SLICE eMSliceSel %d nMSliceSize %d"
+ "Tot#of MB %d encoder->frame_size.width = %d"
+ "encoder->frame_size.height = %d",
+ (int)multi_slice->m_slice_sel,
+ multi_slice->m_slice_size,
+ DDL_NO_OF_MB(encoder->frame_size.width,
+ encoder->frame_size.height),
+ encoder->frame_size.width,
+ encoder->frame_size.height);
switch (multi_slice->m_slice_sel) {
case VCD_MSLICE_OFF:
vcd_status = VCD_S_SUCCESS;
@@ -618,11 +629,14 @@
vcd_status = VCD_S_SUCCESS;
break;
case VCD_MSLICE_BY_MB_COUNT:
- if (multi_slice->m_slice_size >= 1 &&
+ {
+ if ((multi_slice->m_slice_size >= 1) &&
(multi_slice->m_slice_size <=
DDL_NO_OF_MB(encoder->frame_size.width,
- encoder->frame_size.height)))
+ encoder->frame_size.height))) {
vcd_status = VCD_S_SUCCESS;
+ }
+ }
break;
case VCD_MSLICE_BY_BYTE_COUNT:
if (multi_slice->m_slice_size > 0)
@@ -850,6 +864,9 @@
encoder->client_output_buf_req.sz =
DDL_ALIGN(buffer_req->sz,
DDL_KILO_BYTE(4));
+ DDL_MSG_LOW("%s encoder->client_output_buf_req.sz"
+ " = %d\n", __func__,
+ encoder->client_output_buf_req.sz);
vcd_status = VCD_S_SUCCESS;
}
}
@@ -920,8 +937,14 @@
case VCD_I_METADATA_HEADER:
DDL_MSG_LOW("Meta Data Interface is Requested");
if (!res_trk_check_for_sec_session()) {
- vcd_status = ddl_set_metadata_params(ddl,
- property_hdr, property_value);
+ if (!encoder->slice_delivery_info.enable) {
+ vcd_status = ddl_set_metadata_params(ddl,
+ property_hdr, property_value);
+ } else {
+ DDL_MSG_ERROR("Ignoring meta data settting in "
+ "slice mode: %s\n", __func__);
+ vcd_status = VCD_S_SUCCESS;
+ }
} else {
DDL_MSG_ERROR("Meta Data Interface is not "
"supported in secure session");
@@ -946,6 +969,70 @@
}
break;
}
+ case VCD_I_SLICE_DELIVERY_MODE:
+ {
+ size_t output_buf_size;
+ u32 num_mb, num_slices;
+ struct vcd_property_hdr slice_property_hdr;
+ struct vcd_property_meta_data_enable slice_meta_data;
+ DDL_MSG_HIGH("Set property VCD_I_SLICE_DELIVERY_MODE\n");
+ if (sizeof(u32) == property_hdr->sz &&
+ encoder->codec.codec == VCD_CODEC_H264 &&
+ encoder->multi_slice.m_slice_sel
+ == VCD_MSLICE_BY_MB_COUNT &&
+ DDLCLIENT_STATE_IS(ddl, DDL_CLIENT_OPEN)) {
+ encoder->slice_delivery_info.enable
+ = *(u32 *)property_value;
+ DDL_MSG_HIGH("set encoder->slice_delivery_mode"
+ " = %u\n",
+ encoder->slice_delivery_info.enable);
+ output_buf_size =
+ encoder->client_output_buf_req.sz;
+ num_mb = DDL_NO_OF_MB(encoder->frame_size.width,
+ encoder->frame_size.height);
+ num_slices = num_mb/
+ encoder->multi_slice.m_slice_size;
+ num_slices = ((num_mb - num_slices *
+ encoder->multi_slice.m_slice_size) > 0)
+ ? (num_slices + 1) : num_slices;
+ encoder->slice_delivery_info.num_slices =
+ num_slices;
+ if (num_slices <= DDL_MAX_NUM_BFRS_FOR_SLICE_BATCH) {
+ encoder->client_output_buf_req.min_count
+ = ((DDL_ENC_SLICE_BATCH_FACTOR * num_slices + 2)
+ > DDL_MAX_BUFFER_COUNT)
+ ? DDL_MAX_BUFFER_COUNT :
+ (DDL_ENC_SLICE_BATCH_FACTOR * num_slices + 2);
+ output_buf_size =
+ encoder->client_output_buf_req.sz/num_slices;
+ encoder->client_output_buf_req.sz =
+ DDL_ALIGN(output_buf_size, DDL_KILO_BYTE(4));
+ encoder->output_buf_req =
+ encoder->client_output_buf_req;
+ DDL_MSG_HIGH("%s num_mb = %u num_slices = %u "
+ "output_buf_count = %u "
+ "output_buf_size = %u aligned size = %u\n",
+ __func__, num_mb, num_slices,
+ encoder->client_output_buf_req.min_count,
+ output_buf_size,
+ encoder->client_output_buf_req.sz);
+ slice_property_hdr.prop_id =
+ VCD_I_METADATA_ENABLE;
+ slice_property_hdr.sz =
+ sizeof(struct vcd_property_meta_data_enable);
+ ddl_get_metadata_params(ddl,
+ &slice_property_hdr,
+ &slice_meta_data);
+ slice_meta_data.meta_data_enable_flag
+ &= ~VCD_METADATA_ENC_SLICE;
+ ddl_set_metadata_params(ddl,
+ &slice_property_hdr,
+ &slice_meta_data);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ }
case VCD_REQ_PERF_LEVEL:
vcd_status = VCD_S_SUCCESS;
break;
@@ -1354,7 +1441,10 @@
property_hdr->sz) {
*(struct vcd_buffer_requirement *)
property_value = encoder->client_output_buf_req;
- vcd_status = VCD_S_SUCCESS;
+ DDL_MSG_LOW("%s encoder->client_output_buf_req = %d\n",
+ __func__,
+ encoder->client_output_buf_req.sz);
+ vcd_status = VCD_S_SUCCESS;
}
break;
case VCD_I_BUFFER_FORMAT:
@@ -1421,6 +1511,14 @@
vcd_status = VCD_S_SUCCESS;
}
break;
+ case VCD_I_SLICE_DELIVERY_MODE:
+ if (sizeof(struct vcd_property_slice_delivery_info) ==
+ property_hdr->sz) {
+ *(struct vcd_property_slice_delivery_info *)
+ property_value = encoder->slice_delivery_info;
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
default:
vcd_status = VCD_ERR_ILLEGAL_OP;
break;
@@ -1579,6 +1677,9 @@
encoder->closed_gop = true;
ddl_set_default_metadata_flag(ddl);
ddl_set_default_encoder_buffer_req(encoder);
+ encoder->slice_delivery_info.enable = 0;
+ encoder->slice_delivery_info.num_slices = 0;
+ encoder->slice_delivery_info.num_slices_enc = 0;
}
static void ddl_set_default_enc_profile(struct ddl_encoder_data *encoder)
@@ -1725,8 +1826,7 @@
encoder->client_input_buf_req = encoder->input_buf_req;
memset(&encoder->output_buf_req , 0 ,
sizeof(struct vcd_buffer_requirement));
- encoder->output_buf_req.min_count =
- encoder->i_period.b_frames + 2;
+ encoder->output_buf_req.min_count = encoder->i_period.b_frames + 2;
encoder->output_buf_req.actual_count =
encoder->output_buf_req.min_count + 3;
encoder->output_buf_req.max_count = DDL_MAX_BUFFER_COUNT;
@@ -1737,6 +1837,8 @@
DDL_ALIGN(y_cb_cr_size, DDL_KILO_BYTE(4));
ddl_set_default_encoder_metadata_buffer_size(encoder);
encoder->client_output_buf_req = encoder->output_buf_req;
+ DDL_MSG_LOW("%s encoder->client_output_buf_req.sz = %d\n",
+ __func__, encoder->client_output_buf_req.sz);
}
u32 ddl_set_default_decoder_buffer_req(struct ddl_decoder_data *decoder,
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
index cce779e..ac81916 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
@@ -156,6 +156,24 @@
#define VIDC_SM_NEW_I_PERIOD_VALUE_BMASK 0xffffffff
#define VIDC_SM_NEW_I_PERIOD_VALUE_SHFT 0
+#define VIDC_SM_BATCH_INPUT_ADDR 0x00a4
+#define VIDC_SM_BATCH_INPUT_ADDR_VALUE_BMSK 0xffffffff
+#define VIDC_SM_BATCH_INPUT_ADDRL_VALUE_SHFT 0
+#define VIDC_SM_BATCH_OUTPUT_ADDR 0x00a8
+#define VIDC_SM_BATCH_OUTPUT_ADDR_VALUE_BMSK 0xffffffff
+#define VIDC_SM_BATCH_OUTPUT_ADDR_VALUE_SHFT 0
+#define VIDC_SM_BATCH_OUTPUT_SIZE_ADDR 0x00ac
+#define VIDC_SM_BATCH_OUTPUT_SIZE_VALUE_BMSK 0xffffffff
+#define VIDC_SM_BATCH_OUTPUT_SIZE_VALUE_SHFT 0
+#define VIDC_SM_ENC_SLICE_BATCH_INT_CTRL_ADDR 0x01c8
+#define VIDC_SM_ENC_SLICE_BATCH_INT_CTRL_VALUE_BMSK 0x1
+#define VIDC_SM_ENC_SLICE_BATCH_INT_CTRL_VALUE_SHFT 0
+#define VIDC_SM_ENC_NUM_OF_SLICE_ADDR 0x01cc
+#define VIDC_SM_ENC_NUM_OF_SLICE_VALUE_BMSK 0xffffffff
+#define VIDC_SM_ENC_NUM_OF_SLICE_VALUE_SHFT 0
+#define VIDC_SM_ENC_NUM_OF_SLICE_COMP_ADDR 0x01d0
+#define VIDC_SM_ENC_NUM_OF_SLICE_COMP_VALUE_BMSK 0xffffffff
+#define VIDC_SM_ENC_NUM_OF_SLICE_COMP_VALUE_SHFT 0
#define VIDC_SM_ALLOCATED_LUMA_DPB_SIZE_ADDR 0x0064
#define VIDC_SM_ALLOCATED_CHROMA_DPB_SIZE_ADDR 0x0068
@@ -799,3 +817,48 @@
VIDC_SM_EXTENDED_PAR_HEIGHT_SHFT);
}
}
+
+void vidc_sm_set_encoder_slice_batch_int_ctrl(struct ddl_buf_addr *shared_mem,
+ u32 slice_batch_int_enable)
+{
+ u32 slice_batch_int_ctrl = VIDC_SETFIELD((slice_batch_int_enable) ?
+ 1 : 0,
+ VIDC_SM_ENC_EXT_CTRL_HEC_ENABLE_SHFT,
+ VIDC_SM_ENC_EXT_CTRL_HEC_ENABLE_BMSK);
+ DDL_MEM_WRITE_32(shared_mem,
+ VIDC_SM_ENC_SLICE_BATCH_INT_CTRL_ADDR,
+ slice_batch_int_ctrl);
+}
+
+void vidc_sm_get_num_slices_comp(struct ddl_buf_addr *shared_mem,
+ u32 *num_slices_comp)
+{
+ *num_slices_comp = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_ENC_NUM_OF_SLICE_COMP_ADDR);
+}
+
+void vidc_sm_set_encoder_batch_config(struct ddl_buf_addr *shared_mem,
+ u32 num_slices,
+ u32 input_addr, u32 output_addr,
+ u32 output_buffer_size)
+{
+ DDL_MEM_WRITE_32(shared_mem,
+ VIDC_SM_ENC_NUM_OF_SLICE_ADDR,
+ num_slices);
+ DDL_MEM_WRITE_32(shared_mem,
+ VIDC_SM_BATCH_INPUT_ADDR,
+ input_addr);
+ DDL_MEM_WRITE_32(shared_mem,
+ VIDC_SM_BATCH_OUTPUT_ADDR,
+ output_addr);
+ DDL_MEM_WRITE_32(shared_mem,
+ VIDC_SM_BATCH_OUTPUT_SIZE_ADDR,
+ output_buffer_size);
+}
+
+void vidc_sm_get_encoder_batch_output_size(struct ddl_buf_addr *shared_mem,
+ u32 *output_buffer_size)
+{
+ *output_buffer_size = DDL_MEM_READ_32(shared_mem,
+ VIDC_SM_BATCH_OUTPUT_SIZE_ADDR);
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
index b0e6758..7d9896f 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
@@ -181,4 +181,14 @@
enum vidc_sm_num_stuff_bytes_consume_info consume_info);
void vidc_sm_get_aspect_ratio_info(struct ddl_buf_addr *shared_mem,
struct vcd_aspect_ratio *aspect_ratio_info);
+void vidc_sm_set_encoder_slice_batch_int_ctrl(struct ddl_buf_addr *shared_mem,
+ u32 slice_batch_int_enable);
+void vidc_sm_get_num_slices_comp(struct ddl_buf_addr *shared_mem,
+ u32 *num_slices_comp);
+void vidc_sm_set_encoder_batch_config(struct ddl_buf_addr *shared_mem,
+ u32 num_slices,
+ u32 input_addr, u32 output_addr,
+ u32 output_buffer_size);
+void vidc_sm_get_encoder_batch_output_size(struct ddl_buf_addr *shared_mem,
+ u32 *output_buffer_size);
#endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
index 126698c..27d3b5b 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.c
@@ -385,6 +385,36 @@
}
}
+void ddl_calc_core_proc_time_cnt(const char *func_name, u32 index, u32 count)
+{
+ struct time_data *time_data = &proc_time[index];
+ if (time_data->ddl_t1) {
+ int ddl_t2;
+ struct timeval ddl_tv;
+ do_gettimeofday(&ddl_tv);
+ ddl_t2 = (ddl_tv.tv_sec * 1000) + (ddl_tv.tv_usec / 1000);
+ time_data->ddl_ttotal += (ddl_t2 - time_data->ddl_t1);
+ time_data->ddl_count += count;
+ DDL_MSG_TIME("\n%s(): cnt(%u) End Time (%u) Diff(%u) Avg(%u)",
+ func_name, time_data->ddl_count, ddl_t2,
+ ddl_t2 - time_data->ddl_t1,
+ time_data->ddl_ttotal/time_data->ddl_count);
+ time_data->ddl_t1 = 0;
+ }
+}
+
+void ddl_update_core_start_time(const char *func_name, u32 index)
+{
+ u32 act_time;
+ struct timeval ddl_tv;
+ struct time_data *time_data = &proc_time[index];
+ do_gettimeofday(&ddl_tv);
+ act_time = (ddl_tv.tv_sec * 1000) + (ddl_tv.tv_usec / 1000);
+ time_data->ddl_t1 = act_time;
+ DDL_MSG_LOW("\n%s(): Start time updated Act(%u)",
+ func_name, act_time);
+}
+
void ddl_reset_core_time_variables(u32 index)
{
proc_time[index].ddl_t1 = 0;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
index 10b3404..13bef35 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
@@ -24,6 +24,7 @@
DEC_OP_TIME,
DEC_IP_TIME,
ENC_OP_TIME,
+ ENC_SLICE_OP_TIME,
MAX_TIME_DATA
};
@@ -65,9 +66,12 @@
#define DDL_MIN(x, y) ((x < y) ? x : y)
#define DDL_MAX(x, y) ((x > y) ? x : y)
+#define DDL_MEMCPY(dest, src, len) memcpy((dest), (src), (len))
+#define DDL_MEMSET(src, value, len) memset((src), (value), (len))
void ddl_set_core_start_time(const char *func_name, u32 index);
void ddl_calc_core_proc_time(const char *func_name, u32 index);
void ddl_reset_core_time_variables(u32 index);
-
+void ddl_calc_core_proc_time_cnt(const char *func_name, u32 index, u32 count);
+void ddl_update_core_start_time(const char *func_name, u32 index);
#endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
index 66e129c..d288ba3 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
@@ -21,6 +21,7 @@
#else
#define DDL_PIX_CACHE_ENABLE true
#endif
+static unsigned int run_cnt;
void ddl_vidc_core_init(struct ddl_context *ddl_context)
{
@@ -57,6 +58,10 @@
vidc_1080p_encode_frame_start_ch0;
ddl_context->vidc_encode_frame_start[1] =
vidc_1080p_encode_frame_start_ch1;
+ ddl_context->vidc_encode_slice_batch_start[0] =
+ vidc_1080p_encode_slice_batch_start_ch0;
+ ddl_context->vidc_encode_slice_batch_start[1] =
+ vidc_1080p_encode_slice_batch_start_ch1;
vidc_1080p_release_sw_reset();
ddl_context->pix_cache_enable = DDL_PIX_CACHE_ENABLE;
if (ddl_context->pix_cache_enable) {
@@ -515,6 +520,29 @@
i_multi_slice_size, i_multi_slice_byte);
}
+static void ddl_vidc_encode_set_batch_slice_info(
+ struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ DDL_MSG_LOW("%s\n", __func__);
+ encoder->batch_frame.slice_batch_out.buffer_size =
+ encoder->output_buf_req.sz;
+ DDL_MSG_LOW("encoder->batch_frame.slice_batch_out.buffer_size = %d\n",
+ encoder->batch_frame.slice_batch_out.buffer_size);
+ vidc_sm_set_encoder_batch_config(
+ &ddl->shared_mem[ddl->command_channel],
+ 1,
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ encoder->batch_frame.slice_batch_in),
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ encoder->batch_frame.slice_batch_out),
+ encoder->batch_frame.slice_batch_out.buffer_size);
+ vidc_sm_set_encoder_slice_batch_int_ctrl(
+ &ddl->shared_mem[ddl->command_channel],
+ 0);
+}
+
void ddl_vidc_encode_init_codec(struct ddl_client_context *ddl)
{
struct ddl_context *ddl_context = ddl->ddl_context;
@@ -724,6 +752,7 @@
u32 dpb_addr_y[4], dpb_addr_c[4];
u32 index, y_addr, c_addr;
+ DDL_MSG_LOW("%s\n", __func__);
ddl_vidc_encode_set_metadata_output_buf(ddl);
encoder->enc_frame_info.meta_data_exists = false;
@@ -769,6 +798,7 @@
if (encoder->intra_frame_insertion)
encoder->intra_frame_insertion = false;
enc_param.input_flush = false;
+ enc_param.slice_enable = false;
vidc_sm_set_encoder_vop_time(
&ddl->shared_mem[ddl->command_channel], true,
encoder->vop_timing.vop_time_resolution,
@@ -800,6 +830,142 @@
&enc_param);
}
+void ddl_vidc_encode_frame_continue(struct ddl_client_context *ddl)
+{
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct vcd_frame_data *input_vcd_frm = &(ddl->input_frame.vcd_frm);
+ u32 address_offset;
+ address_offset = (u32)(ddl->output_frame.vcd_frm.physical -
+ ddl_context->dram_base_a.align_physical_addr) >>
+ DDL_VIDC_1080P_BASE_OFFSET_SHIFT;
+ DDL_MSG_LOW("%s\n", __func__);
+ if (VCD_FRAME_FLAG_EOS & input_vcd_frm->flags)
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_EOS_DONE;
+ else
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME_DONE;
+ ddl->cmd_state = DDL_CMD_ENCODE_CONTINUE;
+ vidc_1080p_set_host2risc_cmd(VIDC_1080P_HOST2RISC_CMD_CONTINUE_ENC,
+ address_offset,
+ 0, 0, 0);
+}
+
+void ddl_vidc_encode_slice_batch_run(struct ddl_client_context *ddl)
+{
+ struct vidc_1080p_enc_frame_start_param enc_param;
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ struct ddl_enc_buffers *enc_buffers = &(encoder->hw_bufs);
+ struct vcd_frame_data *input_vcd_frm =
+ &(ddl->input_frame.vcd_frm);
+ u32 dpb_addr_y[4], dpb_addr_c[4];
+ u32 index, y_addr, c_addr;
+ u32 bitstream_size;
+ struct vidc_1080p_enc_slice_batch_in_param *slice_batch_in =
+ (struct vidc_1080p_enc_slice_batch_in_param *)
+ encoder->batch_frame.slice_batch_in.align_virtual_addr;
+ DDL_MSG_LOW("%s\n", __func__);
+ DDL_MEMSET(slice_batch_in, 0,
+ sizeof(struct vidc_1080p_enc_slice_batch_in_param));
+ DDL_MEMSET(encoder->batch_frame.slice_batch_in.align_virtual_addr, 0,
+ sizeof(struct vidc_1080p_enc_slice_batch_in_param));
+ encoder->batch_frame.out_frm_next_frmindex = 0;
+ bitstream_size = encoder->batch_frame.output_frame[0].vcd_frm.alloc_len;
+ encoder->output_buf_req.sz = bitstream_size;
+ y_addr = DDL_OFFSET(ddl_context->dram_base_b.align_physical_addr,
+ input_vcd_frm->physical);
+ c_addr = (y_addr + encoder->input_buf_size.size_y);
+ enc_param.encode = VIDC_1080P_ENC_TYPE_SLICE_BATCH_START;
+ DDL_MSG_LOW("ddl_state_transition: %s ~~>"
+ "DDL_CLIENT_WAIT_FOR_FRAME_DONE",
+ ddl_get_state_string(ddl->client_state));
+ slice_batch_in->cmd_type = VIDC_1080P_ENC_TYPE_SLICE_BATCH_START;
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_FRAME_DONE;
+ ddl->cmd_state = DDL_CMD_ENCODE_FRAME;
+ vidc_1080p_set_encode_circular_intra_refresh(
+ encoder->intra_refresh.cir_mb_number);
+ ddl_vidc_encode_set_multi_slice_info(encoder);
+ enc_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
+ enc_param.inst_id = ddl->instance_id;
+ enc_param.shared_mem_addr_offset = DDL_ADDR_OFFSET(
+ ddl_context->dram_base_a,
+ ddl->shared_mem[ddl->command_channel]);
+ enc_param.current_y_addr_offset = y_addr;
+ enc_param.current_c_addr_offset = c_addr;
+ enc_param.stream_buffer_size = bitstream_size;
+ slice_batch_in->num_stream_buffer =
+ encoder->batch_frame.num_output_frames;
+ slice_batch_in->stream_buffer_size = bitstream_size;
+ DDL_MSG_LOW("%s slice_batch_in->num_stream_buffer = %u size = %u\n",
+ __func__, slice_batch_in->num_stream_buffer,
+ slice_batch_in->stream_buffer_size);
+ for (index = 0; index < encoder->batch_frame.num_output_frames;
+ index++) {
+ slice_batch_in->stream_buffer_addr_offset[index] =
+ ((DDL_OFFSET(ddl_context->dram_base_b.align_physical_addr,
+ encoder->batch_frame.output_frame[index].vcd_frm.physical)) >>
+ DDL_VIDC_1080P_BASE_OFFSET_SHIFT);
+ }
+ slice_batch_in->input_size = VIDC_1080P_SLICE_BATCH_IN_SIZE(index);
+ enc_param.intra_frame = encoder->intra_frame_insertion;
+ if (encoder->intra_frame_insertion)
+ encoder->intra_frame_insertion = false;
+ enc_param.input_flush = false;
+ enc_param.slice_enable =
+ encoder->slice_delivery_info.enable;
+ vidc_sm_set_encoder_vop_time(
+ &ddl->shared_mem[ddl->command_channel], true,
+ encoder->vop_timing.vop_time_resolution,
+ ddl->input_frame.frm_delta);
+ vidc_sm_set_frame_tag(&ddl->shared_mem[ddl->command_channel],
+ ddl->input_frame.vcd_frm.ip_frm_tag);
+ DDL_MSG_LOW("%sdpb_count = %d\n", __func__, enc_buffers->dpb_count);
+ if (ddl_context->pix_cache_enable) {
+ for (index = 0; index < enc_buffers->dpb_count;
+ index++) {
+ dpb_addr_y[index] =
+ (u32) VIDC_1080P_DEC_DPB_RESET_VALUE;
+ dpb_addr_c[index] = (u32) enc_buffers->dpb_c
+ [index].align_physical_addr;
+ }
+
+ dpb_addr_y[index] = (u32) input_vcd_frm->physical;
+ dpb_addr_c[index] = (u32) input_vcd_frm->physical +
+ encoder->input_buf_size.size_y;
+
+ vidc_pix_cache_init_luma_chroma_base_addr(
+ enc_buffers->dpb_count + 1, dpb_addr_y, dpb_addr_c);
+ vidc_pix_cache_set_frame_size(encoder->frame_size.width,
+ encoder->frame_size.height);
+ vidc_pix_cache_set_frame_range(enc_buffers->sz_dpb_y,
+ enc_buffers->sz_dpb_c);
+ vidc_pix_cache_clear_cache_tags();
+ }
+ if ((!encoder->rc_level.frame_level_rc) &&
+ (!encoder->rc_level.mb_level_rc)) {
+ encoder->session_qp.p_frame_qp++;
+ if (encoder->session_qp.p_frame_qp > encoder->qp_range.max_qp)
+ encoder->session_qp.p_frame_qp =
+ encoder->qp_range.min_qp;
+ vidc_sm_set_pand_b_frame_qp(
+ &ddl->shared_mem[ddl->command_channel],
+ encoder->session_qp.b_frame_qp,
+ encoder->session_qp.p_frame_qp);
+ }
+
+ if (vidc_msg_timing) {
+ if (run_cnt < 2) {
+ ddl_reset_core_time_variables(ENC_OP_TIME);
+ ddl_reset_core_time_variables(ENC_SLICE_OP_TIME);
+ run_cnt++;
+ }
+ ddl_update_core_start_time(__func__, ENC_SLICE_OP_TIME);
+ ddl_set_core_start_time(__func__, ENC_OP_TIME);
+ }
+ ddl_vidc_encode_set_batch_slice_info(ddl);
+ ddl_context->vidc_encode_slice_batch_start[ddl->command_channel] (
+ &enc_param);
+}
+
u32 ddl_vidc_decode_set_buffers(struct ddl_client_context *ddl)
{
struct ddl_context *ddl_context = ddl->ddl_context;
@@ -976,3 +1142,29 @@
ddl_context->vidc_decode_frame_start[ddl->command_channel] (
&dec_param);
}
+
+void ddl_vidc_encode_eos_run(struct ddl_client_context *ddl)
+{
+ struct vidc_1080p_enc_frame_start_param enc_param;
+ struct ddl_context *ddl_context = ddl->ddl_context;
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ DDL_MSG_LOW("%s\n", __func__);
+ ddl->client_state = DDL_CLIENT_WAIT_FOR_EOS_DONE;
+ ddl_vidc_encode_dynamic_property(ddl, true);
+ ddl->client_state = DDL_CMD_EOS;
+ DDL_MEMSET(&enc_param, 0, sizeof(enc_param));
+ enc_param.encode = VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA;
+ enc_param.cmd_seq_num = ++ddl_context->cmd_seq_num;
+ enc_param.inst_id = ddl->instance_id;
+ enc_param.shared_mem_addr_offset =
+ DDL_ADDR_OFFSET(ddl_context->dram_base_a,
+ ddl->shared_mem[ddl->command_channel]);
+ enc_param.current_y_addr_offset = 0;
+ enc_param.current_c_addr_offset = 0;
+ enc_param.stream_buffer_size = 0;
+ enc_param.intra_frame = encoder->intra_frame_insertion;
+ vidc_sm_set_frame_tag(&ddl->shared_mem[ddl->command_channel],
+ ddl->input_frame.vcd_frm.ip_frm_tag);
+ ddl_context->vidc_encode_frame_start[ddl->command_channel](
+ &enc_param);
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.c b/drivers/video/msm/vidc/1080p/ddl/vidc.c
index 75014cc..d399847 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -77,6 +77,10 @@
#define VIDC_1080P_ENC_TYPE_FRAME_DATA 0x00020000
#define VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA 0x00030000
+#define VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK 0x00004000
+#define VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT 14
+#define VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK 0x80000000
+#define VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT 31
#define VIDC_1080P_MAX_INTRA_PERIOD 0xffff
u8 *VIDC_BASE_PTR;
@@ -779,6 +783,7 @@
void vidc_1080p_encode_frame_start_ch0(
struct vidc_1080p_enc_frame_start_param *param)
{
+ u32 input_flush;
VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
VIDC_HWIO_OUT(REG_666957, VIDC_1080P_INIT_CH_INST_ID);
VIDC_HWIO_OUT(REG_117192,
@@ -791,8 +796,15 @@
VIDC_1080P_BASE_OFFSET_SHIFT);
VIDC_HWIO_OUT(REG_190381, param->intra_frame);
VIDC_HWIO_OUT(REG_889944, param->shared_mem_addr_offset);
- VIDC_HWIO_OUT(REG_404623, param->input_flush);
+ input_flush = VIDC_SETFIELD(param->input_flush,
+ VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
+ VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK);
+ input_flush |= VIDC_SETFIELD(param->slice_enable,
+ VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT,
+ VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK);
+ VIDC_HWIO_OUT(REG_404623, input_flush);
VIDC_HWIO_OUT(REG_397087, param->cmd_seq_num);
+
VIDC_HWIO_OUT(REG_666957, (u32)param->encode |
param->inst_id);
}
@@ -800,7 +812,7 @@
void vidc_1080p_encode_frame_start_ch1(
struct vidc_1080p_enc_frame_start_param *param)
{
-
+ u32 input_flush;
VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
VIDC_HWIO_OUT(REG_313350, VIDC_1080P_INIT_CH_INST_ID);
VIDC_HWIO_OUT(REG_980194,
@@ -813,12 +825,71 @@
VIDC_1080P_BASE_OFFSET_SHIFT);
VIDC_HWIO_OUT(REG_887095, param->intra_frame);
VIDC_HWIO_OUT(REG_652528, param->shared_mem_addr_offset);
- VIDC_HWIO_OUT(REG_404623, param->input_flush);
+ input_flush = VIDC_SETFIELD(param->input_flush,
+ VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
+ VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK);
+ input_flush |= VIDC_SETFIELD(param->slice_enable,
+ VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT,
+ VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK);
+
+ VIDC_HWIO_OUT(REG_404623, input_flush);
VIDC_HWIO_OUT(REG_254093, param->cmd_seq_num);
VIDC_HWIO_OUT(REG_313350, (u32)param->encode |
param->inst_id);
}
+void vidc_1080p_encode_slice_batch_start_ch0(
+ struct vidc_1080p_enc_frame_start_param *param)
+{
+ u32 input_flush;
+ VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_666957, VIDC_1080P_INIT_CH_INST_ID);
+ VIDC_HWIO_OUT(REG_612810, param->current_y_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_175608, param->current_c_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_190381, param->intra_frame);
+ VIDC_HWIO_OUT(REG_889944, param->shared_mem_addr_offset);
+ input_flush = VIDC_SETFIELD(param->input_flush,
+ VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
+ VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK);
+ input_flush |= VIDC_SETFIELD(param->slice_enable,
+ VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT,
+ VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK);
+ VIDC_HWIO_OUT(REG_404623, input_flush);
+ VIDC_HWIO_OUT(REG_397087, param->cmd_seq_num);
+
+ VIDC_HWIO_OUT(REG_666957, (u32)param->encode |
+ param->inst_id);
+
+}
+
+void vidc_1080p_encode_slice_batch_start_ch1(
+ struct vidc_1080p_enc_frame_start_param *param)
+{
+ u32 input_flush;
+ VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
+ VIDC_HWIO_OUT(REG_313350, VIDC_1080P_INIT_CH_INST_ID);
+ VIDC_HWIO_OUT(REG_655721, param->current_y_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_548308, param->current_c_addr_offset >>
+ VIDC_1080P_BASE_OFFSET_SHIFT);
+ VIDC_HWIO_OUT(REG_887095, param->intra_frame);
+ VIDC_HWIO_OUT(REG_652528, param->shared_mem_addr_offset);
+ input_flush = VIDC_SETFIELD(param->input_flush,
+ VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
+ VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_BMSK);
+ input_flush |= VIDC_SETFIELD(param->slice_enable,
+ VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT,
+ VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_BMSK);
+
+ VIDC_HWIO_OUT(REG_404623, input_flush);
+ VIDC_HWIO_OUT(REG_254093, param->cmd_seq_num);
+ VIDC_HWIO_OUT(REG_313350, (u32)param->encode |
+ param->inst_id);
+
+}
+
void vidc_1080p_set_encode_picture(u32 number_p, u32 number_b)
{
u32 picture, ifrm_ctrl;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.h b/drivers/video/msm/vidc/1080p/ddl/vidc.h
index 7573ee8..7460ef3 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.h
@@ -21,11 +21,13 @@
#define VIDC_1080P_RISC2HOST_CMD_CLOSE_CH_RET 2
#define VIDC_1080P_RISC2HOST_CMD_SEQ_DONE_RET 4
#define VIDC_1080P_RISC2HOST_CMD_FRAME_DONE_RET 5
+#define VIDC_1080P_RISC2HOST_CMD_SLICE_DONE_RET 6
#define VIDC_1080P_RISC2HOST_CMD_ENC_COMPLETE_RET 7
#define VIDC_1080P_RISC2HOST_CMD_SYS_INIT_RET 8
#define VIDC_1080P_RISC2HOST_CMD_FW_STATUS_RET 9
#define VIDC_1080P_RISC2HOST_CMD_FLUSH_COMMAND_RET 12
#define VIDC_1080P_RISC2HOST_CMD_ABORT_RET 13
+#define VIDC_1080P_RISC2HOST_CMD_BATCH_ENC_RET 14
#define VIDC_1080P_RISC2HOST_CMD_INIT_BUFFERS_RET 15
#define VIDC_1080P_RISC2HOST_CMD_EDFU_INT_RET 16
#define VIDC_1080P_RISC2HOST_CMD_ERROR_RET 32
@@ -188,7 +190,9 @@
#define VIDC_1080P_ITLB_MISS_EXCEPTION_HANDLER 0x100
#define VIDC_1080P_DATA_PAGE_FAULT_EXCEPTION_HANDLER 0x200
#define VIDC_1080P_INST_PAGE_FAULT_EXCEPTION_HANDLER 0x400
-
+#define VIDC_1080P_SLICE_BATCH_MAX_STRM_BFR 8
+#define VIDC_1080P_SLICE_BATCH_IN_SIZE(idx) (4 * sizeof(u32) + \
+ idx * sizeof(u32))
enum vidc_1080p_reset{
VIDC_1080P_RESET_IN_SEQ_FIRST_STAGE = 0x0,
VIDC_1080P_RESET_IN_SEQ_SECOND_STAGE = 0x1,
@@ -318,10 +322,11 @@
VIDC_1080P_DEC_TYPE_32BIT = 0x7FFFFFFF
};
enum vidc_1080p_encode{
- VIDC_1080P_ENC_TYPE_SEQ_HEADER = 0x00010000,
- VIDC_1080P_ENC_TYPE_FRAME_DATA = 0x00020000,
- VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA = 0x00030000,
- VIDC_1080P_ENC_TYPE_32BIT = 0x7FFFFFFF
+ VIDC_1080P_ENC_TYPE_SEQ_HEADER = 0x00010000,
+ VIDC_1080P_ENC_TYPE_FRAME_DATA = 0x00020000,
+ VIDC_1080P_ENC_TYPE_LAST_FRAME_DATA = 0x00030000,
+ VIDC_1080P_ENC_TYPE_SLICE_BATCH_START = 0x00070000,
+ VIDC_1080P_ENC_TYPE_32BIT = 0x7FFFFFFF
};
struct vidc_1080p_dec_seq_start_param{
u32 cmd_seq_num;
@@ -391,6 +396,7 @@
u32 stream_buffer_size;
u32 intra_frame;
u32 input_flush;
+ u32 slice_enable;
enum vidc_1080p_encode encode;
};
struct vidc_1080p_enc_frame_info{
@@ -402,6 +408,23 @@
enum vidc_1080p_encode_frame enc_frame;
u32 meta_data_exists;
};
+struct vidc_1080p_enc_slice_batch_in_param {
+ u32 cmd_type;
+ u32 input_size;
+ u32 num_stream_buffer;
+ u32 stream_buffer_size;
+ u32 stream_buffer_addr_offset[VIDC_1080P_SLICE_BATCH_MAX_STRM_BFR];
+};
+struct vidc_1080p_enc_slice_info {
+ u32 stream_buffer_idx;
+ u32 stream_buffer_size;
+};
+struct vidc_1080p_enc_slice_batch_out_param {
+ u32 cmd_type;
+ u32 output_size;
+ struct vidc_1080p_enc_slice_info slice_info
+ [VIDC_1080P_SLICE_BATCH_MAX_STRM_BFR];
+};
struct vidc_1080p_dec_disp_info{
u32 disp_resl_change;
u32 dec_resl_change;
@@ -519,6 +542,10 @@
struct vidc_1080p_enc_frame_start_param *param);
void vidc_1080p_encode_frame_start_ch1(
struct vidc_1080p_enc_frame_start_param *param);
+void vidc_1080p_encode_slice_batch_start_ch0(
+ struct vidc_1080p_enc_frame_start_param *param);
+void vidc_1080p_encode_slice_batch_start_ch1(
+ struct vidc_1080p_enc_frame_start_param *param);
void vidc_1080p_set_encode_picture(u32 ifrm_ctrl, u32 number_b);
void vidc_1080p_set_encode_multi_slice_control(
enum vidc_1080p_MSlice_selection multiple_slice_selection,
diff --git a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h
index 9dc495b..7e201cf 100644
--- a/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h
+++ b/drivers/video/msm/vidc/720p/ddl/vcd_ddl_internal_property.h
@@ -57,6 +57,12 @@
u32 activity_region_flag;
};
+struct vcd_property_slice_delivery_info {
+ u32 enable;
+ u32 num_slices;
+ u32 num_slices_enc;
+};
+
struct ddl_frame_data_tag;
struct ddl_property_dec_pic_buffers {
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index d93d07e..5542856 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -1604,6 +1604,20 @@
}
if (!result) {
ERR("setting VEN_IOCTL_(G)SET_LIVE_MODE failed\n");
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_SLICE_DELIVERY_MODE:
+ {
+ struct vcd_property_hdr vcd_property_hdr;
+ u32 vcd_status = VCD_ERR_FAIL;
+ u32 enable = true;
+ vcd_property_hdr.prop_id = VCD_I_SLICE_DELIVERY_MODE;
+ vcd_property_hdr.sz = sizeof(u32);
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &enable);
+ if (vcd_status) {
+ pr_err(" Setting slice delivery mode failed");
return -EIO;
}
break;
diff --git a/drivers/video/msm/vidc/common/init/vidc_init.c b/drivers/video/msm/vidc/common/init/vidc_init.c
index 6fdb1c6..55bbe00 100644
--- a/drivers/video/msm/vidc/common/init/vidc_init.c
+++ b/drivers/video/msm/vidc/common/init/vidc_init.c
@@ -63,7 +63,7 @@
static irqreturn_t vidc_isr(int irq, void *dev);
static spinlock_t vidc_spin_lock;
-u32 vidc_msg_timing, vidc_msg_pmem;
+u32 vidc_msg_timing, vidc_msg_pmem, vidc_msg_register;
#ifdef VIDC_ENABLE_DBGFS
struct dentry *vidc_debugfs_root;
@@ -311,6 +311,8 @@
(u32 *) &vidc_msg_timing);
vidc_debugfs_file_create(root, "vidc_msg_pmem",
(u32 *) &vidc_msg_pmem);
+ vidc_debugfs_file_create(root, "vidc_msg_register",
+ (u32 *) &vidc_msg_register);
}
#endif
return 0;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd.h b/drivers/video/msm/vidc/common/vcd/vcd.h
index 0d1ff7e..e557dab 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd.h
@@ -393,4 +393,6 @@
u32 vcd_req_perf_level(struct vcd_clnt_ctxt *cctxt,
struct vcd_property_perf_level *);
+u32 vcd_set_num_slices(struct vcd_clnt_ctxt *cctxt);
+
#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_core.h b/drivers/video/msm/vidc/common/vcd/vcd_core.h
index e33c8cd..d228146 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_core.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd_core.h
@@ -185,6 +185,7 @@
u32 live;
u32 decoding;
u32 bframe;
+ u32 num_slices;
struct vcd_property_frame_rate frm_rate;
u32 frm_p_units;
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index fd8d02a..d49f233 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -19,6 +19,7 @@
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MAP_TABLE_SZ 64
+#define VCD_ENC_MAX_OUTBFRS_PER_FRAME 8
struct vcd_msm_map_buffer {
phys_addr_t phy_addr;
@@ -942,7 +943,6 @@
list_del(&entry->list);
pool->q_len--;
}
-
return entry;
}
@@ -1122,6 +1122,7 @@
cctxt->bframe = 0;
cctxt->cmd_q.pending_cmd = VCD_CMD_NONE;
cctxt->status.last_evt = VCD_EVT_RESP_BASE;
+ cctxt->num_slices = 1;
return rc;
}
@@ -1293,6 +1294,7 @@
}
} else {
+ vcd_set_num_slices(transc->cctxt);
rc = ddl_encode_start(transc->cctxt->ddl_handle,
(void *)transc);
}
@@ -1492,7 +1494,8 @@
u32 rc = VCD_S_SUCCESS;
u32 evcode = 0;
struct ddl_frame_data_tag ddl_ip_frm;
- struct ddl_frame_data_tag ddl_op_frm;
+ struct ddl_frame_data_tag *ddl_op_frm;
+ u32 out_buf_cnt = 0;
VCD_MSG_LOW("vcd_submit_frame:");
cctxt = transc->cctxt;
@@ -1504,34 +1507,52 @@
transc->flags = ip_frm_entry->flags;
ip_frm_entry->ip_frm_tag = (u32) transc;
memset(&ddl_ip_frm, 0, sizeof(ddl_ip_frm));
- memset(&ddl_op_frm, 0, sizeof(ddl_op_frm));
if (cctxt->decoding) {
evcode = CLIENT_STATE_EVENT_NUMBER(decode_frame);
ddl_ip_frm.vcd_frm = *ip_frm_entry;
rc = ddl_decode_frame(cctxt->ddl_handle, &ddl_ip_frm,
- (void *) transc);
+ (void *) transc);
} else {
- op_buf_entry = vcd_buffer_pool_entry_de_q(
- &cctxt->out_buf_pool);
- if (!op_buf_entry) {
- VCD_MSG_ERROR("Sched provided frame when no"
- "op buffer was present");
- rc = VCD_ERR_FAIL;
- } else {
+ ddl_op_frm = (struct ddl_frame_data_tag *)
+ kmalloc((sizeof(struct ddl_frame_data_tag) *
+ VCD_ENC_MAX_OUTBFRS_PER_FRAME), GFP_KERNEL);
+ if (!ddl_op_frm) {
+ VCD_MSG_ERROR("Memory allocation failure");
+ return VCD_ERR_ALLOC_FAIL;
+ }
+ memset(ddl_op_frm, 0, (sizeof(struct ddl_frame_data_tag) *
+ VCD_ENC_MAX_OUTBFRS_PER_FRAME));
+ for (out_buf_cnt = 0; out_buf_cnt < cctxt->num_slices ;
+ out_buf_cnt++) {
+ op_buf_entry = vcd_buffer_pool_entry_de_q(
+ &cctxt->out_buf_pool);
+ if (!op_buf_entry) {
+ VCD_MSG_ERROR("Sched provided frame when no"
+ "op buffer was present");
+ rc = VCD_ERR_FAIL;
+ break;
+ }
op_buf_entry->in_use = true;
cctxt->out_buf_pool.in_use++;
- ddl_ip_frm.vcd_frm = *ip_frm_entry;
- ddl_ip_frm.frm_delta =
- vcd_calculate_frame_delta(cctxt,
- ip_frm_entry);
-
- ddl_op_frm.vcd_frm = op_buf_entry->frame;
-
- evcode = CLIENT_STATE_EVENT_NUMBER(encode_frame);
-
- rc = ddl_encode_frame(cctxt->ddl_handle,
- &ddl_ip_frm, &ddl_op_frm, (void *) transc);
+ ddl_op_frm[out_buf_cnt].vcd_frm = op_buf_entry->frame;
+ VCD_MSG_LOW("%s : buffer_cnt = %d framebfr(virtual)"
+ " 0x%p", __func__, out_buf_cnt,
+ op_buf_entry->frame.virtual);
+ VCD_MSG_LOW("framebfr(physical) 0x%p bfrlength %d",
+ op_buf_entry->frame.physical,
+ op_buf_entry->frame.alloc_len);
}
+ ddl_ip_frm.vcd_frm = *ip_frm_entry;
+ ddl_ip_frm.frm_delta =
+ vcd_calculate_frame_delta(cctxt,
+ ip_frm_entry);
+ evcode = CLIENT_STATE_EVENT_NUMBER(encode_frame);
+
+ if (!VCD_FAILED(rc)) {
+ rc = ddl_encode_frame(cctxt->ddl_handle,
+ &ddl_ip_frm, &ddl_op_frm[0], (void *) transc);
+ }
+ kfree(ddl_op_frm);
}
ip_frm_entry->ip_frm_tag = transc->ip_frm_tag;
if (!VCD_FAILED(rc)) {
@@ -1875,8 +1896,10 @@
void vcd_release_trans_tbl_entry(struct vcd_transc *trans_entry)
{
- if (trans_entry)
+ if (trans_entry) {
trans_entry->in_use = false;
+ VCD_MSG_LOW("%s in_use set to false\n", __func__);
+ }
}
u32 vcd_handle_input_done(
@@ -1888,6 +1911,7 @@
(struct ddl_frame_data_tag *) payload;
struct vcd_buffer_entry *orig_frame = NULL;
u32 rc;
+ VCD_MSG_LOW("%s\n", __func__);
if (!cctxt->status.frame_submitted &&
!cctxt->status.frame_delayed) {
@@ -1935,8 +1959,11 @@
transc->ip_buf_entry = NULL;
transc->input_done = true;
- if (transc->input_done && transc->frame_done)
+ if (transc->input_done && transc->frame_done) {
+ VCD_MSG_LOW("%s Calling vcd_release_trans_tbl_entry\n",
+ __func__);
vcd_release_trans_tbl_entry(transc);
+ }
if (VCD_FAILED(status)) {
VCD_MSG_ERROR("INPUT_DONE returned err = 0x%x", status);
@@ -1975,6 +2002,7 @@
(struct ddl_frame_data_tag *) payload;
u32 rc = VCD_ERR_FAIL, codec_config = false;
u32 core_type = res_trk_get_core_type();
+ VCD_MSG_LOW("%s\n", __func__);
rc = vcd_validate_io_done_pyld(cctxt, payload, status);
if (rc == VCD_ERR_CLIENT_FATAL)
vcd_handle_clnt_fatal_input_done(cctxt, frame->frm_trans_end);
@@ -2080,6 +2108,7 @@
struct ddl_frame_data_tag *frame =
(struct ddl_frame_data_tag *)payload;
u32 rc = VCD_S_SUCCESS;
+ VCD_MSG_LOW("%s\n", __func__);
if (!cctxt->status.frame_submitted &&
!cctxt->status.frame_delayed) {
@@ -2140,6 +2169,7 @@
struct vcd_transc *transc;
struct ddl_frame_data_tag *frame =
(struct ddl_frame_data_tag *)payload;
+ VCD_MSG_LOW("%s\n", __func__);
rc = vcd_validate_io_done_pyld(cctxt, payload, VCD_S_SUCCESS);
if (rc == VCD_ERR_CLIENT_FATAL)
@@ -2173,6 +2203,7 @@
struct vcd_transc *transc;
u32 rc;
s64 time_stamp;
+ VCD_MSG_LOW("%s\n", __func__);
rc = vcd_validate_io_done_pyld(cctxt, payload, status);
if (rc == VCD_ERR_CLIENT_FATAL)
@@ -2262,7 +2293,7 @@
struct ddl_frame_data_tag *frame =
(struct ddl_frame_data_tag *) payload;
u32 rc = VCD_S_SUCCESS;
- VCD_MSG_LOW("vcd_handle_frame_done_in_eos:");
+ VCD_MSG_LOW("%s\n", __func__);
rc = vcd_validate_io_done_pyld(cctxt, payload, status);
if (rc == VCD_ERR_CLIENT_FATAL)
vcd_handle_clnt_fatal(cctxt, frame->frm_trans_end);
@@ -3326,3 +3357,24 @@
0, cctxt, cctxt->client_data);
}
}
+
+u32 vcd_set_num_slices(struct vcd_clnt_ctxt *cctxt)
+{
+ struct vcd_property_hdr prop_hdr;
+ struct vcd_property_slice_delivery_info slice_delivery_info;
+ u32 rc = VCD_S_SUCCESS;
+ prop_hdr.prop_id = VCD_I_SLICE_DELIVERY_MODE;
+ prop_hdr.sz = prop_hdr.sz =
+ sizeof(struct vcd_property_slice_delivery_info);
+ rc = ddl_get_property(cctxt->ddl_handle, &prop_hdr,
+ &slice_delivery_info);
+ VCD_FAILED_RETURN(rc, "Failed: Get VCD_I_SLICE_DELIVERY_MODE");
+ if (slice_delivery_info.enable) {
+ cctxt->num_slices = slice_delivery_info.num_slices;
+ VCD_MSG_LOW("%s slice delivery mode num_slices = %u\n",
+ __func__, cctxt->num_slices);
+ } else {
+ cctxt->num_slices = 1;
+ }
+ return rc;
+}
diff --git a/include/linux/msm_vidc_enc.h b/include/linux/msm_vidc_enc.h
index bf149eb..519c537 100644
--- a/include/linux/msm_vidc_enc.h
+++ b/include/linux/msm_vidc_enc.h
@@ -454,6 +454,10 @@
#define VEN_IOCTL_GET_EXTRADATA \
_IOR(VEN_IOCTLBASE_ENC, 49, struct venc_ioctl_msg)
+/*IOCTL params:SET: InputData - NULL, OutputData - NULL.*/
+#define VEN_IOCTL_SET_SLICE_DELIVERY_MODE \
+ _IO(VEN_IOCTLBASE_ENC, 50)
+
struct venc_switch{
unsigned char status;
};
diff --git a/include/linux/qpnp/gpio.h b/include/linux/qpnp/gpio.h
index a31b7f3..e7fb53e 100644
--- a/include/linux/qpnp/gpio.h
+++ b/include/linux/qpnp/gpio.h
@@ -12,12 +12,16 @@
#include <mach/qpnp.h>
+#define QPNP_GPIO_DIR_IN 0
#define QPNP_GPIO_DIR_OUT 1
-#define QPNP_GPIO_DIR_IN 2
-#define QPNP_GPIO_DIR_BOTH (QPNP_GPIO_DIR_OUT | QPNP_GPIO_DIR_IN)
+#define QPNP_GPIO_DIR_BOTH 2
-#define QPNP_GPIO_OUT_BUF_OPEN_DRAIN 1
+#define QPNP_GPIO_INVERT_DISABLE 0
+#define QPNP_GPIO_INVERT_ENABLE 1
+
#define QPNP_GPIO_OUT_BUF_CMOS 0
+#define QPNP_GPIO_OUT_BUF_OPEN_DRAIN_NMOS 1
+#define QPNP_GPIO_OUT_BUF_OPEN_DRAIN_PMOS 2
#define QPNP_GPIO_VIN0 0
#define QPNP_GPIO_VIN1 1
@@ -39,14 +43,17 @@
#define QPNP_GPIO_OUT_STRENGTH_MED 2
#define QPNP_GPIO_OUT_STRENGTH_HIGH 3
-#define QPNP_GPIO_FUNC_NORMAL 0
-#define QPNP_GPIO_FUNC_PAIRED 1
-#define QPNP_GPIO_FUNC_1 2
-#define QPNP_GPIO_FUNC_2 3
-#define QPNP_GPIO_DTEST1 4
-#define QPNP_GPIO_DTEST2 5
-#define QPNP_GPIO_DTEST3 6
-#define QPNP_GPIO_DTEST4 7
+#define QPNP_GPIO_SRC_FUNC_NORMAL 0
+#define QPNP_GPIO_SRC_FUNC_PAIRED 1
+#define QPNP_GPIO_SRC_FUNC_1 2
+#define QPNP_GPIO_SRC_FUNC_2 3
+#define QPNP_GPIO_SRC_DTEST1 4
+#define QPNP_GPIO_SRC_DTEST2 5
+#define QPNP_GPIO_SRC_DTEST3 6
+#define QPNP_GPIO_SRC_DTEST4 7
+
+#define QPNP_GPIO_MASTER_DISABLE 0
+#define QPNP_GPIO_MASTER_ENABLE 1
/**
* struct qpnp_gpio_cfg - structure to specify gpio configurtion values
@@ -54,7 +61,8 @@
* both. Should be of the type QPNP_GPIO_DIR_*
* @output_type: indicates gpio should be configured as CMOS or open
* drain. Should be of the type QPNP_GPIO_OUT_BUF_*
- * @output_value: The gpio output value of the gpio line - 0 or 1
+ * @invert: Invert the signal of the gpio line -
+ * QPNP_GPIO_INVERT_DISABLE or QPNP_GPIO_INVERT_ENABLE
* @pull: Indicates whether a pull up or pull down should be
* applied. If a pullup is required the current strength
* needs to be specified. Current values of 30uA, 1.5uA,
@@ -68,21 +76,22 @@
* @source_sel: choose alternate function for the gpio. Certain gpios
* can be paired (shorted) with each other. Some gpio pin
* can act as alternate functions. This parameter should
- * be of type QPNP_GPIO_FUNC_*
- * @master_en: 1 = Enable features within the GPIO block based on
- * configurations.
- * 0 = Completely disable the GPIO block and let the pin
- * float with high impedance regardless of other settings.
+ * be of type QPNP_GPIO_SRC_*.
+ * @master_en: QPNP_GPIO_MASTER_ENABLE = Enable features within the
+ * GPIO block based on configurations.
+ * QPNP_GPIO_MASTER_DISABLE = Completely disable the GPIO
+ * block and let the pin float with high impedance
+ * regardless of other settings.
*/
struct qpnp_gpio_cfg {
- int direction;
- int output_type;
- int output_value;
- int pull;
- int vin_sel;
- int out_strength;
- int src_select;
- int master_en;
+ unsigned int direction;
+ unsigned int output_type;
+ unsigned int invert;
+ unsigned int pull;
+ unsigned int vin_sel;
+ unsigned int out_strength;
+ unsigned int src_select;
+ unsigned int master_en;
};
/**
diff --git a/include/media/msm/vcd_property.h b/include/media/msm/vcd_property.h
index 51cc78f..e776d41 100644
--- a/include/media/msm/vcd_property.h
+++ b/include/media/msm/vcd_property.h
@@ -52,6 +52,7 @@
#define VCD_I_DISABLE_DMX_SUPPORT (VCD_START_BASE + 0x24)
#define VCD_I_ENABLE_SPS_PPS_FOR_IDR (VCD_START_BASE + 0x25)
#define VCD_REQ_PERF_LEVEL (VCD_START_BASE + 0x26)
+#define VCD_I_SLICE_DELIVERY_MODE (VCD_START_BASE + 0x27)
#define VCD_START_REQ (VCD_START_BASE + 0x1000)
#define VCD_I_REQ_IFRAME (VCD_START_REQ + 0x1)
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index 7e9f5f4..d218fab 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -99,6 +99,28 @@
*/
#define BT_AMP_POLICY_PREFER_AMP 2
+#define BT_LE_PARAMS 100
+
+#define BT_LE_SCAN_WINDOW_MIN 0x0004
+#define BT_LE_SCAN_WINDOW_MAX 0x4000
+#define BT_LE_SCAN_WINDOW_DEF 0x0004
+
+#define BT_LE_SCAN_INTERVAL_MIN 0x0004
+#define BT_LE_SCAN_INTERVAL_MAX 0x4000
+#define BT_LE_SCAN_INTERVAL_DEF 0x0008
+
+#define BT_LE_CONN_INTERVAL_MIN 0x0006
+#define BT_LE_CONN_INTERVAL_MAX 0x0C80
+#define BT_LE_CONN_INTERVAL_MIN_DEF 0x0008
+#define BT_LE_CONN_INTERVAL_MAX_DEF 0x0100
+
+#define BT_LE_LATENCY_MAX 0x01F4
+#define BT_LE_LATENCY_DEF 0x0000
+
+#define BT_LE_SUP_TO_MIN 0x000A
+#define BT_LE_SUP_TO_MAX 0x0C80
+#define BT_LE_SUP_TO_DEFAULT 0X03E8
+
#define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
#define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg)
#define BT_DBG(fmt, arg...) pr_debug("%s: " fmt "\n" , __func__ , ## arg)
@@ -142,6 +164,20 @@
#define bt_sk(__sk) ((struct bt_sock *) __sk)
+struct bt_le_params {
+ __u8 prohibit_remote_chg;
+ __u8 filter_policy;
+ __u16 scan_interval;
+ __u16 scan_window;
+ __u16 interval_min;
+ __u16 interval_max;
+ __u16 latency;
+ __u16 supervision_timeout;
+ __u16 min_ce_len;
+ __u16 max_ce_len;
+ __u16 conn_timeout;
+};
+
struct bt_sock {
struct sock sk;
bdaddr_t src;
@@ -149,6 +185,7 @@
struct list_head accept_q;
struct sock *parent;
u32 defer_setup;
+ struct bt_le_params le_params;
};
struct bt_sock_list {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 5053bd8..5749293 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -304,6 +304,7 @@
__u8 auth_initiator;
__u8 power_save;
__u16 disc_timeout;
+ __u16 conn_timeout;
unsigned long pend;
__u8 remote_cap;
@@ -597,6 +598,10 @@
struct hci_conn *hci_connect(struct hci_dev *hdev, int type,
__u16 pkt_type, bdaddr_t *dst,
__u8 sec_level, __u8 auth_type);
+struct hci_conn *hci_le_connect(struct hci_dev *hdev, __u16 pkt_type,
+ bdaddr_t *dst, __u8 sec_level,
+ __u8 auth_type,
+ struct bt_le_params *le_params);
int hci_conn_check_link_mode(struct hci_conn *conn);
int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
int hci_conn_change_link_key(struct hci_conn *conn);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index b903c5c..a098f3e 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -685,6 +685,7 @@
int l2cap_ertm_tx(struct sock *sk, struct bt_l2cap_control *control,
struct sk_buff_head *skbs, u8 event);
+int l2cap_sock_le_params_valid(struct bt_le_params *le_params);
void l2cap_sock_set_timer(struct sock *sk, long timeout);
void l2cap_sock_clear_timer(struct sock *sk);
void __l2cap_sock_close(struct sock *sk, int reason);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index d60bf00..25b559b1 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -44,33 +44,77 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/l2cap.h>
-static void hci_le_connect(struct hci_conn *conn)
+struct hci_conn *hci_le_connect(struct hci_dev *hdev, __u16 pkt_type,
+ bdaddr_t *dst, __u8 sec_level, __u8 auth_type,
+ struct bt_le_params *le_params)
{
- struct hci_dev *hdev = conn->hdev;
+ struct hci_conn *le;
struct hci_cp_le_create_conn cp;
+ struct adv_entry *entry;
+ struct link_key *key;
- BT_DBG("%p", conn);
+ BT_DBG("%p", hdev);
- conn->state = BT_CONNECT;
- conn->out = 1;
- conn->link_mode |= HCI_LM_MASTER;
- conn->sec_level = BT_SECURITY_LOW;
- conn->type = LE_LINK;
+ le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
+ if (le) {
+ hci_conn_hold(le);
+ return le;
+ }
+
+ key = hci_find_link_key_type(hdev, dst, KEY_TYPE_LTK);
+ if (!key) {
+ entry = hci_find_adv_entry(hdev, dst);
+ if (entry)
+ le = hci_le_conn_add(hdev, dst,
+ entry->bdaddr_type);
+ else
+ le = hci_le_conn_add(hdev, dst, 0);
+ } else {
+ le = hci_le_conn_add(hdev, dst, key->addr_type);
+ }
+
+ if (!le)
+ return ERR_PTR(-ENOMEM);
+
+ hci_conn_hold(le);
+
+ le->state = BT_CONNECT;
+ le->out = 1;
+ le->link_mode |= HCI_LM_MASTER;
+ le->sec_level = BT_SECURITY_LOW;
+ le->type = LE_LINK;
memset(&cp, 0, sizeof(cp));
- cp.scan_interval = cpu_to_le16(0x0004);
- cp.scan_window = cpu_to_le16(0x0004);
- bacpy(&cp.peer_addr, &conn->dst);
- cp.peer_addr_type = conn->dst_type;
- cp.conn_interval_min = cpu_to_le16(0x0008);
- cp.conn_interval_max = cpu_to_le16(0x0100);
- cp.supervision_timeout = cpu_to_le16(1000);
- cp.min_ce_len = cpu_to_le16(0x0001);
- cp.max_ce_len = cpu_to_le16(0x0001);
+ if (l2cap_sock_le_params_valid(le_params)) {
+ cp.supervision_timeout =
+ cpu_to_le16(le_params->supervision_timeout);
+ cp.scan_interval = cpu_to_le16(le_params->scan_interval);
+ cp.scan_window = cpu_to_le16(le_params->scan_window);
+ cp.conn_interval_min = cpu_to_le16(le_params->interval_min);
+ cp.conn_interval_max = cpu_to_le16(le_params->interval_max);
+ cp.conn_latency = cpu_to_le16(le_params->latency);
+ cp.min_ce_len = cpu_to_le16(le_params->min_ce_len);
+ cp.max_ce_len = cpu_to_le16(le_params->max_ce_len);
+ le->conn_timeout = le_params->conn_timeout;
+ } else {
+ cp.supervision_timeout = cpu_to_le16(BT_LE_SUP_TO_DEFAULT);
+ cp.scan_interval = cpu_to_le16(BT_LE_SCAN_INTERVAL_DEF);
+ cp.scan_window = cpu_to_le16(BT_LE_SCAN_WINDOW_DEF);
+ cp.conn_interval_min = cpu_to_le16(BT_LE_CONN_INTERVAL_MIN_DEF);
+ cp.conn_interval_max = cpu_to_le16(BT_LE_CONN_INTERVAL_MAX_DEF);
+ cp.conn_latency = cpu_to_le16(BT_LE_LATENCY_DEF);
+ le->conn_timeout = 5;
+ }
+ bacpy(&cp.peer_addr, &le->dst);
+ cp.peer_addr_type = le->dst_type;
hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
+
+ return le;
}
+EXPORT_SYMBOL(hci_le_connect);
static void hci_le_connect_cancel(struct hci_conn *conn)
{
@@ -685,41 +729,12 @@
{
struct hci_conn *acl;
struct hci_conn *sco;
- struct hci_conn *le;
BT_DBG("%s dst %s", hdev->name, batostr(dst));
- if (type == LE_LINK) {
- struct adv_entry *entry;
- struct link_key *key;
-
- le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst);
- if (le) {
- hci_conn_hold(le);
- return le;
- }
-
- key = hci_find_link_key_type(hdev, dst, KEY_TYPE_LTK);
- if (!key) {
- entry = hci_find_adv_entry(hdev, dst);
- if (entry)
- le = hci_le_conn_add(hdev, dst,
- entry->bdaddr_type);
- else
- le = hci_le_conn_add(hdev, dst, 0);
- } else {
- le = hci_le_conn_add(hdev, dst, key->addr_type);
- }
-
- if (!le)
- return ERR_PTR(-ENOMEM);
-
- hci_le_connect(le);
-
- hci_conn_hold(le);
-
- return le;
- }
+ if (type == LE_LINK)
+ return hci_le_connect(hdev, pkt_type, dst, sec_level,
+ auth_type, NULL);
acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
if (!acl) {
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 598c310..395a95c 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1368,6 +1368,7 @@
{
struct hci_cp_le_create_conn *cp;
struct hci_conn *conn;
+ unsigned long exp = msecs_to_jiffies(5000);
BT_DBG("%s status 0x%x", hdev->name, status);
@@ -1396,11 +1397,11 @@
conn->out = 1;
else
BT_ERR("No memory for new connection");
- }
+ } else
+ exp = msecs_to_jiffies(conn->conn_timeout * 1000);
- if (conn)
- mod_timer(&conn->disc_timer,
- jiffies + msecs_to_jiffies(5000));
+ if (conn && exp)
+ mod_timer(&conn->disc_timer, jiffies + exp);
}
hci_dev_unlock(hdev);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 37ee9b1..9f9f17d 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1277,8 +1277,9 @@
conn = hcon->l2cap_data;
} else {
if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA)
- hcon = hci_connect(hdev, LE_LINK, 0, dst,
- l2cap_pi(sk)->sec_level, auth_type);
+ hcon = hci_le_connect(hdev, 0, dst,
+ l2cap_pi(sk)->sec_level, auth_type,
+ &bt_sk(sk)->le_params);
else
hcon = hci_connect(hdev, ACL_LINK, 0, dst,
l2cap_pi(sk)->sec_level, auth_type);
@@ -1308,7 +1309,17 @@
sk->sk_state_change(sk);
} else {
sk->sk_state = BT_CONNECT;
- l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+ /* If we have valid LE Params, let timeout override default */
+ if (l2cap_pi(sk)->dcid == L2CAP_CID_LE_DATA &&
+ l2cap_sock_le_params_valid(&bt_sk(sk)->le_params)) {
+ u16 timeout = bt_sk(sk)->le_params.conn_timeout;
+
+ if (timeout)
+ l2cap_sock_set_timer(sk,
+ msecs_to_jiffies(timeout*1000));
+ } else
+ l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
+
sk->sk_state_change(sk);
if (hcon->state == BT_CONNECTED) {
@@ -5668,7 +5679,8 @@
struct hci_conn *hcon = conn->hcon;
struct l2cap_conn_param_update_req *req;
struct l2cap_conn_param_update_rsp rsp;
- u16 min, max, latency, to_multiplier, cmd_len;
+ struct sock *sk;
+ u16 min, max, latency, timeout, cmd_len;
int err;
if (!(hcon->link_mode & HCI_LM_MASTER))
@@ -5678,28 +5690,32 @@
if (cmd_len != sizeof(struct l2cap_conn_param_update_req))
return -EPROTO;
- req = (struct l2cap_conn_param_update_req *) data;
- min = __le16_to_cpu(req->min);
- max = __le16_to_cpu(req->max);
- latency = __le16_to_cpu(req->latency);
- to_multiplier = __le16_to_cpu(req->to_multiplier);
-
- BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x",
- min, max, latency, to_multiplier);
-
memset(&rsp, 0, sizeof(rsp));
+ rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
- err = l2cap_check_conn_param(min, max, latency, to_multiplier);
- if (err)
- rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED);
- else
- rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
+ sk = l2cap_find_sock_by_fixed_cid_and_dir(4, conn->src, conn->dst, 0);
+
+ if (sk && !bt_sk(sk)->le_params.prohibit_remote_chg) {
+ req = (struct l2cap_conn_param_update_req *) data;
+ min = __le16_to_cpu(req->min);
+ max = __le16_to_cpu(req->max);
+ latency = __le16_to_cpu(req->latency);
+ timeout = __le16_to_cpu(req->to_multiplier);
+
+ err = l2cap_check_conn_param(min, max, latency, timeout);
+ if (!err) {
+ rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED);
+ hci_le_conn_update(hcon, min, max, latency, timeout);
+ bt_sk(sk)->le_params.interval_min = min;
+ bt_sk(sk)->le_params.interval_max = max;
+ bt_sk(sk)->le_params.latency = latency;
+ bt_sk(sk)->le_params.supervision_timeout = timeout;
+ }
+ }
l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP,
sizeof(rsp), &rsp);
- if (!err)
- hci_le_conn_update(hcon, min, max, latency, to_multiplier);
return 0;
}
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 8eb1e16..33d5d22 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -78,6 +78,23 @@
sk_stop_timer(sk, &sk->sk_timer);
}
+int l2cap_sock_le_params_valid(struct bt_le_params *le_params)
+{
+ if (!le_params || le_params->latency > BT_LE_LATENCY_MAX ||
+ le_params->scan_window > BT_LE_SCAN_WINDOW_MAX ||
+ le_params->scan_interval < BT_LE_SCAN_INTERVAL_MIN ||
+ le_params->scan_window > le_params->scan_interval ||
+ le_params->interval_min < BT_LE_CONN_INTERVAL_MIN ||
+ le_params->interval_max > BT_LE_CONN_INTERVAL_MAX ||
+ le_params->interval_min > le_params->interval_max ||
+ le_params->supervision_timeout < BT_LE_SUP_TO_MIN ||
+ le_params->supervision_timeout > BT_LE_SUP_TO_MAX) {
+ return 0;
+ }
+
+ return 1;
+}
+
static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
{
struct sock *sk;
@@ -547,6 +564,17 @@
err = -EFAULT;
break;
+ case BT_LE_PARAMS:
+ if (l2cap_pi(sk)->scid != L2CAP_CID_LE_DATA) {
+ err = -EINVAL;
+ break;
+ }
+
+ if (copy_to_user(optval, (char *) &bt_sk(sk)->le_params,
+ sizeof(bt_sk(sk)->le_params)))
+ err = -EFAULT;
+ break;
+
default:
err = -ENOPROTOOPT;
break;
@@ -671,6 +699,7 @@
struct sock *sk = sock->sk;
struct bt_security sec;
struct bt_power pwr;
+ struct bt_le_params le_params;
struct l2cap_conn *conn;
int len, err = 0;
u32 opt;
@@ -786,6 +815,41 @@
break;
+ case BT_LE_PARAMS:
+ if (l2cap_pi(sk)->scid != L2CAP_CID_LE_DATA) {
+ err = -EINVAL;
+ break;
+ }
+
+ if (copy_from_user((char *) &le_params, optval,
+ sizeof(struct bt_le_params))) {
+ err = -EFAULT;
+ break;
+ }
+
+ conn = l2cap_pi(sk)->conn;
+ if (!conn || !conn->hcon ||
+ l2cap_pi(sk)->scid != L2CAP_CID_LE_DATA) {
+ memcpy(&bt_sk(sk)->le_params, &le_params,
+ sizeof(le_params));
+ break;
+ }
+
+ if (!conn->hcon->out ||
+ !l2cap_sock_le_params_valid(&le_params)) {
+ err = -EINVAL;
+ break;
+ }
+
+ memcpy(&bt_sk(sk)->le_params, &le_params, sizeof(le_params));
+
+ hci_le_conn_update(conn->hcon,
+ le_params.interval_min,
+ le_params.interval_max,
+ le_params.latency,
+ le_params.supervision_timeout);
+ break;
+
default:
err = -ENOPROTOOPT;
break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index e15609c..80f4bd6 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -1623,8 +1623,8 @@
entry = hci_find_adv_entry(hdev, &cp->bdaddr);
if (entry && entry->flags & 0x04) {
- conn = hci_connect(hdev, LE_LINK, 0, &cp->bdaddr, sec_level,
- auth_type);
+ conn = hci_le_connect(hdev, 0, &cp->bdaddr, sec_level,
+ auth_type, NULL);
} else {
/* ACL-SSP does not support io_cap 0x04 (KeyboadDisplay) */
if (io_cap == 0x04)
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 1fe28a2..6b590c9 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -234,7 +234,7 @@
return -EINVAL;
}
- pr_err("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
+ pr_debug("%s: ear_pa_gain = 0x%x\n", __func__, ear_pa_gain);
return 0;
}
@@ -277,7 +277,7 @@
snd_soc_read(codec, (SITAR_A_CDC_IIR1_CTL + 16 * iir_idx)) &
(1 << band_idx);
- pr_err("%s: IIR #%d band #%d enable %d\n", __func__,
+ pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
iir_idx, band_idx,
(uint32_t)ucontrol->value.integer.value[0]);
return 0;
@@ -298,7 +298,7 @@
snd_soc_update_bits(codec, (SITAR_A_CDC_IIR1_CTL + 16 * iir_idx),
(1 << band_idx), (value << band_idx));
- pr_err("%s: IIR #%d band #%d enable %d\n", __func__,
+ pr_debug("%s: IIR #%d band #%d enable %d\n", __func__,
iir_idx, band_idx, value);
return 0;
}
@@ -344,7 +344,7 @@
ucontrol->value.integer.value[4] =
get_iir_band_coeff(codec, iir_idx, band_idx, 4);
- pr_err("%s: IIR #%d band #%d b0 = 0x%x\n"
+ pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
"%s: IIR #%d band #%d b1 = 0x%x\n"
"%s: IIR #%d band #%d b2 = 0x%x\n"
"%s: IIR #%d band #%d a1 = 0x%x\n"
@@ -412,7 +412,7 @@
set_iir_band_coeff(codec, iir_idx, band_idx, 4,
ucontrol->value.integer.value[4]);
- pr_err("%s: IIR #%d band #%d b0 = 0x%x\n"
+ pr_debug("%s: IIR #%d band #%d b0 = 0x%x\n"
"%s: IIR #%d band #%d b1 = 0x%x\n"
"%s: IIR #%d band #%d b2 = 0x%x\n"
"%s: IIR #%d band #%d a1 = 0x%x\n"
@@ -743,7 +743,7 @@
{
struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
- pr_err("%s %d\n", __func__, enable);
+ pr_debug("%s %d\n", __func__, enable);
if (enable) {
sitar->adc_count++;
@@ -765,7 +765,7 @@
struct snd_soc_codec *codec = w->codec;
u16 adc_reg;
- pr_err("%s %d\n", __func__, event);
+ pr_debug("%s %d\n", __func__, event);
if (w->reg == SITAR_A_TX_1_2_EN)
adc_reg = SITAR_A_TX_1_2_TEST_CTL;
@@ -818,7 +818,7 @@
struct snd_soc_codec *codec = w->codec;
u16 lineout_gain_reg;
- pr_err("%s %d %s\n", __func__, event, w->name);
+ pr_debug("%s %d %s\n", __func__, event, w->name);
switch (w->shift) {
case 0:
@@ -838,7 +838,7 @@
snd_soc_update_bits(codec, lineout_gain_reg, 0x10, 0x10);
break;
case SND_SOC_DAPM_POST_PMU:
- pr_err("%s: sleeping 16 ms after %s PA turn on\n",
+ pr_debug("%s: sleeping 16 ms after %s PA turn on\n",
__func__, w->name);
usleep_range(16000, 16000);
break;
@@ -886,7 +886,7 @@
tx_mux_ctl_reg = SITAR_A_CDC_TX1_MUX_CTL + 8 * (dmic - 1);
tx_dmic_ctl_reg = SITAR_A_CDC_TX1_DMIC_CTL + 8 * (dmic - 1);
- pr_err("%s %d\n", __func__, event);
+ pr_debug("%s %d\n", __func__, event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
@@ -974,7 +974,7 @@
sitar->mbhc_bias_regs.cfilt_ctl, 0x40, reg_mode_val);
if (mbhc_was_polling)
sitar_codec_start_hs_polling(codec);
- pr_err("%s: CFILT mode change (%x to %x)\n", __func__,
+ pr_debug("%s: CFILT mode change (%x to %x)\n", __func__,
cur_mode_val, reg_mode_val);
} else {
pr_err("%s: CFILT Value is already %x\n",
@@ -1113,7 +1113,7 @@
sitar_codec_start_hs_polling(codec);
sitar->mbhc_micbias_switched = true;
- pr_err("%s: Enabled MBHC Mic bias to VDDIO Switch\n",
+ pr_debug("%s: Enabled MBHC Mic bias to VDDIO Switch\n",
__func__);
}
break;
@@ -1138,7 +1138,7 @@
sitar_codec_start_hs_polling(codec);
sitar->mbhc_micbias_switched = false;
- pr_err("%s: Disabled MBHC Mic bias to VDDIO Switch\n",
+ pr_debug("%s: Disabled MBHC Mic bias to VDDIO Switch\n",
__func__);
}
break;
@@ -1156,7 +1156,7 @@
char *internal1_text = "Internal1";
char *internal2_text = "Internal2";
- pr_err("%s %d\n", __func__, event);
+ pr_debug("%s %d\n", __func__, event);
switch (w->reg) {
case SITAR_A_MICB_1_CTL:
micb_int_reg = SITAR_A_MICB_1_INT_RBIAS;
@@ -1218,7 +1218,7 @@
struct snd_soc_codec *codec = w->codec;
u16 dec_reset_reg;
- pr_err("%s %d\n", __func__, event);
+ pr_debug("%s %d\n", __func__, event);
if (w->reg == SITAR_A_CDC_CLK_TX_CLK_EN_B1_CTL)
dec_reset_reg = SITAR_A_CDC_CLK_TX_RESET_B1_CTL;
@@ -1242,7 +1242,7 @@
{
struct snd_soc_codec *codec = w->codec;
- pr_err("%s %d %s\n", __func__, event, w->name);
+ pr_debug("%s %d %s\n", __func__, event, w->name);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
@@ -1290,7 +1290,7 @@
{
struct snd_soc_codec *codec = w->codec;
- pr_err("%s %d\n", __func__, event);
+ pr_debug("%s %d\n", __func__, event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
@@ -1307,7 +1307,7 @@
{
struct snd_soc_codec *codec = w->codec;
- pr_err("%s %s %d\n", __func__, w->name, event);
+ pr_debug("%s %s %d\n", __func__, w->name, event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
@@ -1378,7 +1378,7 @@
struct snd_soc_codec *codec = w->codec;
struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
u8 mbhc_micb_ctl_val;
- pr_err("%s: event = %d\n", __func__, event);
+ pr_debug("%s: event = %d\n", __func__, event);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
@@ -1416,7 +1416,7 @@
if (sitar->mbhc_micbias_switched)
sitar_codec_switch_micbias(codec, 0);
- pr_err("%s: sleep 10 ms after %s PA disable.\n", __func__,
+ pr_debug("%s: sleep 10 ms after %s PA disable.\n", __func__,
w->name);
usleep_range(10000, 10000);
@@ -1471,7 +1471,7 @@
{
struct snd_soc_codec *codec = w->codec;
- pr_err("%s %d\n", __func__, event);
+ pr_debug("%s %d\n", __func__, event);
switch (event) {
case SND_SOC_DAPM_POST_PMU:
snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_RESET_CTL, 0x10,
@@ -1908,7 +1908,7 @@
* interrupt handlers
*/
- pr_err("%s, choice is %d, current is %d\n", __func__, choice,
+ pr_debug("%s, choice is %d, current is %d\n", __func__, choice,
sitar->bandgap_type);
if (sitar->bandgap_type == choice)
@@ -1978,7 +1978,7 @@
{
struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
- pr_err("%s\n", __func__);
+ pr_debug("%s\n", __func__);
if (config_mode) {
sitar_codec_enable_config_mode(codec, 1);
@@ -2005,7 +2005,7 @@
static void sitar_codec_disable_clock_block(struct snd_soc_codec *codec)
{
struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
- pr_err("%s\n", __func__);
+ pr_debug("%s\n", __func__);
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x04, 0x00);
ndelay(160);
snd_soc_update_bits(codec, SITAR_A_CLK_BUFF_EN2, 0x02, 0x02);
@@ -2077,7 +2077,7 @@
if ((wcd9xxx != NULL) && (wcd9xxx->dev != NULL) &&
(wcd9xxx->dev->parent != NULL))
pm_runtime_get_sync(wcd9xxx->dev->parent);
- pr_err("%s(): substream = %s stream = %d\n" , __func__,
+ pr_debug("%s(): substream = %s stream = %d\n" , __func__,
substream->name, substream->stream);
return 0;
@@ -2092,7 +2092,7 @@
pm_runtime_mark_last_busy(wcd9xxx->dev->parent);
pm_runtime_put(wcd9xxx->dev->parent);
}
- pr_err("%s(): substream = %s stream = %d\n" , __func__,
+ pr_debug("%s(): substream = %s stream = %d\n" , __func__,
substream->name, substream->stream);
}
@@ -2100,7 +2100,7 @@
{
struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
- pr_err("%s() mclk_enable = %u\n", __func__, mclk_enable);
+ pr_debug("%s() mclk_enable = %u\n", __func__, mclk_enable);
if (mclk_enable) {
sitar->mclk_enabled = true;
@@ -2149,7 +2149,7 @@
static int sitar_set_dai_sysclk(struct snd_soc_dai *dai,
int clk_id, unsigned int freq, int dir)
{
- pr_err("%s\n", __func__);
+ pr_debug("%s\n", __func__);
return 0;
}
@@ -2158,7 +2158,7 @@
u8 val = 0;
struct sitar_priv *sitar = snd_soc_codec_get_drvdata(dai->codec);
- pr_err("%s\n", __func__);
+ pr_debug("%s\n", __func__);
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBS_CFS:
/* CPU is master */
@@ -2265,7 +2265,7 @@
u16 tx_fs_reg, rx_fs_reg;
u8 tx_fs_rate, rx_fs_rate, rx_state, tx_state;
- pr_err("%s: DAI-ID %x\n", __func__, dai->id);
+ pr_debug("%s: DAI-ID %x\n", __func__, dai->id);
switch (params_rate(params)) {
case 8000:
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index cb760fa..8e4e205 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -49,7 +49,7 @@
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_8000_48000,
+ .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT,
.rate_min = 8000,
.rate_max = 48000,
.channels_min = 1,
diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c
index 23134ea..6c44cba 100644
--- a/sound/soc/msm/msm-dai-fe.c
+++ b/sound/soc/msm/msm-dai-fe.c
@@ -50,7 +50,8 @@
{
.playback = {
.stream_name = "Multimedia1 Playback",
- .rates = SNDRV_PCM_RATE_8000_48000,
+ .rates = (SNDRV_PCM_RATE_8000_48000|
+ SNDRV_PCM_RATE_KNOT),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
.channels_max = 2,
@@ -59,20 +60,22 @@
},
.capture = {
.stream_name = "Multimedia1 Capture",
- .rates = SNDRV_PCM_RATE_8000_48000,
+ .rates = (SNDRV_PCM_RATE_8000_48000|
+ SNDRV_PCM_RATE_KNOT),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
.channels_max = 4,
.rate_min = 8000,
.rate_max = 48000,
},
- .ops = &msm_fe_dai_ops,
+ .ops = &msm_fe_Multimedia_dai_ops,
.name = "MultiMedia1",
},
{
.playback = {
.stream_name = "Multimedia2 Playback",
- .rates = SNDRV_PCM_RATE_8000_48000,
+ .rates = (SNDRV_PCM_RATE_8000_48000|
+ SNDRV_PCM_RATE_KNOT),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
.channels_max = 6,
@@ -81,14 +84,15 @@
},
.capture = {
.stream_name = "Multimedia2 Capture",
- .rates = SNDRV_PCM_RATE_8000_48000,
+ .rates = (SNDRV_PCM_RATE_8000_48000|
+ SNDRV_PCM_RATE_KNOT),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.channels_min = 1,
.channels_max = 2,
.rate_min = 8000,
.rate_max = 48000,
},
- .ops = &msm_fe_dai_ops,
+ .ops = &msm_fe_Multimedia_dai_ops,
.name = "MultiMedia2",
},
{
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
index 0a8282c..b509a09 100644
--- a/sound/soc/msm/msm-multi-ch-pcm-q6.c
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -77,7 +77,7 @@
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_8000_48000,
+ .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT,
.rate_min = 8000,
.rate_max = 48000,
.channels_min = 1,
diff --git a/sound/soc/msm/msm-pcm-q6.c b/sound/soc/msm/msm-pcm-q6.c
index 4686386..39ce436 100644
--- a/sound/soc/msm/msm-pcm-q6.c
+++ b/sound/soc/msm/msm-pcm-q6.c
@@ -71,7 +71,7 @@
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_8000_48000,
+ .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT,
.rate_min = 8000,
.rate_max = 48000,
.channels_min = 1,