Merge "msm: q6dsp6v2: Configure token in APR packet correctly" into msm-3.4
diff --git a/Documentation/devicetree/bindings/gpio/qpnp-pin.txt b/Documentation/devicetree/bindings/gpio/qpnp-pin.txt
index c58e073..31c3bc2 100644
--- a/Documentation/devicetree/bindings/gpio/qpnp-pin.txt
+++ b/Documentation/devicetree/bindings/gpio/qpnp-pin.txt
@@ -94,7 +94,7 @@
QPNP_PIN_OUT_STRENGTH_MED = 2, (GPIO)
QPNP_PIN_OUT_STRENGTH_HIGH = 3, (GPIO)
- - qcom,select: select a function for the pin. Certain pins
+ - qcom,src-select: select a function for the pin. Certain pins
can be paired (shorted) with each other. Some gpio pins
can act as alternate functions.
In the context of gpio, this acts as a source select.
diff --git a/arch/arm/boot/dts/msm9625.dts b/arch/arm/boot/dts/msm9625.dts
index 42425ed..041b4dd 100644
--- a/arch/arm/boot/dts/msm9625.dts
+++ b/arch/arm/boot/dts/msm9625.dts
@@ -76,4 +76,26 @@
interrupts = <0 247 0>;
interrupt-names = "bam_irq";
};
+
+ spi@f9928000 {
+ compatible = "qcom,spi-qup-v2";
+ reg = <0xf9928000 0x1000>;
+ interrupts = <0 100 0>;
+ spi-max-frequency = <24000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ gpios = <&msmgpio 23 0>, /* CLK */
+ <&msmgpio 21 0>, /* MISO */
+ <&msmgpio 20 0>; /* MOSI */
+
+ cs-gpios = <&msmgpio 69 0>;
+
+ ethernet-switch@0 {
+ compatible = "simtec,ks8851";
+ reg = <0>;
+ interrupt-parent = <&msmgpio>;
+ interrupts = <75 0>;
+ spi-max-frequency = <5000000>;
+ };
+ };
};
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 3854403..3fad6b7 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -59,7 +59,7 @@
CONFIG_MACH_MPQ8064_HRD=y
CONFIG_MACH_MPQ8064_DTV=y
# CONFIG_MSM_STACKED_MEMORY is not set
-CONFIG_KERNEL_PMEM_EBI_REGION=y
+CONFIG_KERNEL_MSM_CONTIG_MEM_REGION=y
# CONFIG_MSM_FIQ_SUPPORT is not set
# CONFIG_MSM_PROC_COMM is not set
CONFIG_MSM_SMD=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 06501ba..cd79e98 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -58,7 +58,7 @@
CONFIG_MACH_MPQ8064_HRD=y
CONFIG_MACH_MPQ8064_DTV=y
# CONFIG_MSM_STACKED_MEMORY is not set
-CONFIG_KERNEL_PMEM_EBI_REGION=y
+CONFIG_KERNEL_MSM_CONTIG_MEM_REGION=y
# CONFIG_MSM_FIQ_SUPPORT is not set
# CONFIG_MSM_PROC_COMM is not set
CONFIG_MSM_SMD=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index c73c62e..e231db6 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -55,6 +55,7 @@
CONFIG_MSM_OCMEM_DEBUG=y
CONFIG_MSM_OCMEM_POWER_DISABLE=y
CONFIG_MSM_MEMORY_DUMP=y
+CONFIG_MSM_WATCHDOG_V2=y
CONFIG_MSM_CACHE_ERP=y
CONFIG_MSM_L1_ERR_PANIC=y
CONFIG_MSM_L2_ERP_PRINT_ACCESS_ERRORS=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 9094db7..446734f 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -56,9 +56,28 @@
CONFIG_MTD_BLOCK=y
# CONFIG_MTD_MSM_NAND is not set
CONFIG_MTD_MSM_QPIC_NAND=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IPV6=y
+# CONFIG_WIRELESS is not set
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
# CONFIG_ANDROID_PMEM is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+CONFIG_KS8851=y
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_MSM_RMNET is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_WLAN is not set
# CONFIG_INPUT_MOUSEDEV is not set
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
@@ -70,6 +89,9 @@
CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
CONFIG_HW_RANDOM=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=m
CONFIG_DEBUG_GPIO=y
CONFIG_GPIO_SYSFS=y
# CONFIG_HWMON is not set
diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c
index 43c627d..23d310d 100644
--- a/arch/arm/kernel/arch_timer.c
+++ b/arch/arm/kernel/arch_timer.c
@@ -208,11 +208,11 @@
unsigned long ctrl;
ctrl = arch_specific_timer->reg_read(ARCH_TIMER_REG_CTRL);
- ctrl |= ARCH_TIMER_CTRL_ENABLE;
- ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
-
+ ctrl &= ~(ARCH_TIMER_CTRL_ENABLE | ARCH_TIMER_CTRL_IT_MASK);
arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL, ctrl);
arch_specific_timer->reg_write(ARCH_TIMER_REG_TVAL, evt);
+ ctrl |= ARCH_TIMER_CTRL_ENABLE;
+ arch_specific_timer->reg_write(ARCH_TIMER_REG_CTRL, ctrl);
return 0;
}
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 5331f2c..145375d 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -890,12 +890,15 @@
default "0x40200000" if ARCH_MSM8X60
default "0x10000000"
-config KERNEL_PMEM_EBI_REGION
- bool "Enable in-kernel PMEM region for EBI"
+config KERNEL_MSM_CONTIG_MEM_REGION
+ bool "Enable in-kernel contiguous memory region"
default y if ARCH_MSM8X60
depends on ANDROID_PMEM && (ARCH_MSM8X60 || ARCH_MSM8960 || ARCH_MSM8974)
help
- Enable the in-kernel PMEM allocator to use EBI memory.
+ Enable the in-kernel contiguous memory allocator. Sets up a
+ region of physically contiguous memory. This memory is
+ reserved during initialization, and can be used
+ generically.
config KERNEL_PMEM_SMI_REGION
bool "Enable in-kernel PMEM region for SMI"
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index ce19336..83e559f 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -264,7 +264,7 @@
obj-$(CONFIG_MACH_MSM7X25_FFA) += board-msm7x27.o devices-msm7x25.o
obj-$(CONFIG_ARCH_MSM8960) += clock-local.o clock-dss-8960.o clock-8960.o clock-rpm.o clock-pll.o
obj-$(CONFIG_ARCH_MSM8960) += footswitch-8x60.o
-obj-$(CONFIG_ARCH_MSM8960) += acpuclock-8960.o
+obj-$(CONFIG_ARCH_MSM8960) += acpuclock-8960.o acpuclock-8960ab.o
obj-$(CONFIG_ARCH_MSM8960) += memory_topology.o
obj-$(CONFIG_ARCH_MSM8960) += saw-regulator.o
obj-$(CONFIG_ARCH_MSM8960) += devices-8960.o
@@ -287,7 +287,7 @@
obj-$(CONFIG_MACH_MPQ8064_DTV) += board-8064-all.o board-8064-regulator.o
obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o board-9615-gpiomux.o board-9615-storage.o board-9615-display.o
obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
-obj-$(CONFIG_ARCH_MSM8974) += board-8974.o board-dt.o board-8974-regulator.o board-8974-gpiomux.o
+obj-$(CONFIG_ARCH_MSM8974) += board-8974.o board-dt.o board-8974-gpiomux.o
obj-$(CONFIG_ARCH_MSM8974) += acpuclock-8974.o
obj-$(CONFIG_ARCH_MSM8974) += clock-local2.o clock-pll.o clock-8974.o clock-rpm.o clock-voter.o
obj-$(CONFIG_ARCH_MSM8974) += gdsc.o
diff --git a/arch/arm/mach-msm/acpuclock-8960ab.c b/arch/arm/mach-msm/acpuclock-8960ab.c
new file mode 100644
index 0000000..6366376
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock-8960ab.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <mach/rpm-regulator.h>
+#include <mach/msm_bus_board.h>
+#include <mach/msm_bus.h>
+
+#include "acpuclock.h"
+#include "acpuclock-krait.h"
+
+static struct hfpll_data hfpll_data __initdata = {
+ .mode_offset = 0x00,
+ .l_offset = 0x08,
+ .m_offset = 0x0C,
+ .n_offset = 0x10,
+ .config_offset = 0x04,
+ .config_val = 0x7845C665,
+ .has_droop_ctl = true,
+ .droop_offset = 0x14,
+ .droop_val = 0x0108C000,
+ .low_vdd_l_max = 37,
+ .nom_vdd_l_max = 74,
+ .vdd[HFPLL_VDD_NONE] = 0,
+ .vdd[HFPLL_VDD_LOW] = 945000,
+ .vdd[HFPLL_VDD_NOM] = 1050000,
+ .vdd[HFPLL_VDD_HIGH] = 1150000,
+};
+
+static struct scalable scalable[] __initdata = {
+ [CPU0] = {
+ .hfpll_phys_base = 0x00903200,
+ .aux_clk_sel_phys = 0x02088014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x4501,
+ .vreg[VREG_CORE] = { "krait0", 1300000 },
+ .vreg[VREG_MEM] = { "krait0_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait0_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait0_s8", 2050000 },
+ .vreg[VREG_HFPLL_B] = { "krait0_l23", 1800000 },
+ },
+ [CPU1] = {
+ .hfpll_phys_base = 0x00903300,
+ .aux_clk_sel_phys = 0x02098014,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x5501,
+ .vreg[VREG_CORE] = { "krait1", 1300000 },
+ .vreg[VREG_MEM] = { "krait1_mem", 1150000 },
+ .vreg[VREG_DIG] = { "krait1_dig", 1150000 },
+ .vreg[VREG_HFPLL_A] = { "krait1_s8", 2050000 },
+ .vreg[VREG_HFPLL_B] = { "krait1_l23", 1800000 },
+ },
+ [L2] = {
+ .hfpll_phys_base = 0x00903400,
+ .aux_clk_sel_phys = 0x02011028,
+ .aux_clk_sel = 3,
+ .l2cpmr_iaddr = 0x0500,
+ .vreg[VREG_HFPLL_A] = { "l2_s8", 2050000 },
+ .vreg[VREG_HFPLL_B] = { "l2_l23", 1800000 },
+ },
+};
+
+static struct msm_bus_paths bw_level_tbl[] __initdata = {
+ [0] = BW_MBPS(640), /* At least 80 MHz on bus. */
+ [1] = BW_MBPS(1064), /* At least 133 MHz on bus. */
+ [2] = BW_MBPS(1600), /* At least 200 MHz on bus. */
+ [3] = BW_MBPS(2128), /* At least 266 MHz on bus. */
+ [4] = BW_MBPS(3200), /* At least 400 MHz on bus. */
+ [5] = BW_MBPS(4264), /* At least 533 MHz on bus. */
+};
+
+static struct msm_bus_scale_pdata bus_scale_data __initdata = {
+ .usecase = bw_level_tbl,
+ .num_usecases = ARRAY_SIZE(bw_level_tbl),
+ .active_only = 1,
+ .name = "acpuclk-8960ab",
+};
+
+static struct l2_level l2_freq_tbl[] __initdata = {
+ [0] = { { 384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
+ [1] = { { 486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 2 },
+ [2] = { { 594000, HFPLL, 1, 0, 0x16 }, 1050000, 1050000, 2 },
+ [3] = { { 702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 4 },
+ [4] = { { 810000, HFPLL, 1, 0, 0x1E }, 1050000, 1050000, 4 },
+ [5] = { { 918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 5 },
+ [6] = { { 1026000, HFPLL, 1, 0, 0x26 }, 1150000, 1150000, 5 },
+ [7] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 5 },
+ [8] = { { 1242000, HFPLL, 1, 0, 0x2E }, 1150000, 1150000, 5 },
+ [9] = { { 1350000, HFPLL, 1, 0, 0x32 }, 1150000, 1150000, 5 },
+};
+
+static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
+ { 1, { 384000, PLL_8, 0, 2, 0x00 }, L2(0), 950000 },
+ { 0, { 432000, HFPLL, 2, 0, 0x20 }, L2(3), 975000 },
+ { 1, { 486000, HFPLL, 2, 0, 0x24 }, L2(3), 975000 },
+ { 0, { 540000, HFPLL, 2, 0, 0x28 }, L2(3), 1000000 },
+ { 1, { 594000, HFPLL, 1, 0, 0x16 }, L2(3), 1000000 },
+ { 0, { 648000, HFPLL, 1, 0, 0x18 }, L2(3), 1025000 },
+ { 1, { 702000, HFPLL, 1, 0, 0x1A }, L2(3), 1025000 },
+ { 0, { 756000, HFPLL, 1, 0, 0x1C }, L2(3), 1075000 },
+ { 1, { 810000, HFPLL, 1, 0, 0x1E }, L2(3), 1075000 },
+ { 0, { 864000, HFPLL, 1, 0, 0x20 }, L2(3), 1100000 },
+ { 1, { 918000, HFPLL, 1, 0, 0x22 }, L2(3), 1100000 },
+ { 0, { 972000, HFPLL, 1, 0, 0x24 }, L2(3), 1125000 },
+ { 1, { 1026000, HFPLL, 1, 0, 0x26 }, L2(3), 1125000 },
+ { 0, { 1080000, HFPLL, 1, 0, 0x28 }, L2(9), 1175000 },
+ { 1, { 1134000, HFPLL, 1, 0, 0x2A }, L2(9), 1175000 },
+ { 0, { 1188000, HFPLL, 1, 0, 0x2C }, L2(9), 1200000 },
+ { 1, { 1242000, HFPLL, 1, 0, 0x2E }, L2(9), 1200000 },
+ { 0, { 1296000, HFPLL, 1, 0, 0x30 }, L2(9), 1225000 },
+ { 1, { 1350000, HFPLL, 1, 0, 0x32 }, L2(9), 1225000 },
+ { 0, { 1404000, HFPLL, 1, 0, 0x34 }, L2(9), 1237500 },
+ { 1, { 1458000, HFPLL, 1, 0, 0x36 }, L2(9), 1237500 },
+ { 1, { 1512000, HFPLL, 1, 0, 0x38 }, L2(9), 1250000 },
+ { 0, { 0 } }
+};
+
+static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
+[PVS_SLOW] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow), 0 },
+[PVS_NOMINAL] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow), 0 },
+[PVS_FAST] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow), 0 },
+};
+
+static struct acpuclk_krait_params acpuclk_8960ab_params __initdata = {
+ .scalable = scalable,
+ .scalable_size = sizeof(scalable),
+ .hfpll_data = &hfpll_data,
+ .pvs_tables = pvs_tables,
+ .l2_freq_tbl = l2_freq_tbl,
+ .l2_freq_tbl_size = sizeof(l2_freq_tbl),
+ .bus_scale = &bus_scale_data,
+ .qfprom_phys_base = 0x00700000,
+};
+
+static int __init acpuclk_8960ab_probe(struct platform_device *pdev)
+{
+ return acpuclk_krait_init(&pdev->dev, &acpuclk_8960ab_params);
+}
+
+static struct platform_driver acpuclk_8960ab_driver = {
+ .driver = {
+ .name = "acpuclk-8960ab",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init acpuclk_8960ab_init(void)
+{
+ return platform_driver_probe(&acpuclk_8960ab_driver,
+ acpuclk_8960ab_probe);
+}
+device_initcall(acpuclk_8960ab_init);
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index b35e949..04e751a 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -47,16 +47,29 @@
#define BAM_MUX_HDR_CMD_STATUS 3 /* unused */
#define BAM_MUX_HDR_CMD_OPEN_NO_A2_PC 4
-#define POLLING_MIN_SLEEP 950 /* 0.95 ms */
-#define POLLING_MAX_SLEEP 1050 /* 1.05 ms */
-#define POLLING_INACTIVITY 40 /* cycles before switch to intr mode */
#define LOW_WATERMARK 2
#define HIGH_WATERMARK 4
+#define DEFAULT_POLLING_MIN_SLEEP (950)
+#define MAX_POLLING_SLEEP (6050)
+#define MIN_POLLING_SLEEP (950)
static int msm_bam_dmux_debug_enable;
module_param_named(debug_enable, msm_bam_dmux_debug_enable,
int, S_IRUGO | S_IWUSR | S_IWGRP);
+static int POLLING_MIN_SLEEP = 950;
+module_param_named(min_sleep, POLLING_MIN_SLEEP,
+ int, S_IRUGO | S_IWUSR | S_IWGRP);
+static int POLLING_MAX_SLEEP = 1050;
+module_param_named(max_sleep, POLLING_MAX_SLEEP,
+ int, S_IRUGO | S_IWUSR | S_IWGRP);
+static int POLLING_INACTIVITY = 40;
+module_param_named(inactivity, POLLING_INACTIVITY,
+ int, S_IRUGO | S_IWUSR | S_IWGRP);
+static int bam_adaptive_timer_enabled = 1;
+module_param_named(adaptive_timer_enabled,
+ bam_adaptive_timer_enabled,
+ int, S_IRUGO | S_IWUSR | S_IWGRP);
#if defined(DEBUG)
static uint32_t bam_dmux_read_cnt;
@@ -177,6 +190,7 @@
static int bam_mux_initialized;
static int polling_mode;
+static unsigned long rx_timer_interval;
static LIST_HEAD(bam_rx_pool);
static DEFINE_MUTEX(bam_rx_pool_mutexlock);
@@ -1116,6 +1130,7 @@
struct rx_pkt_info *info;
int inactive_cycles = 0;
int ret;
+ u32 buffs_unused, buffs_used;
while (bam_connection_is_active) { /* timer loop */
++inactive_cycles;
@@ -1162,12 +1177,47 @@
handle_bam_mux_cmd(&info->work);
}
- if (inactive_cycles == POLLING_INACTIVITY) {
+ if (inactive_cycles >= POLLING_INACTIVITY) {
rx_switch_to_interrupt_mode();
break;
}
- usleep_range(POLLING_MIN_SLEEP, POLLING_MAX_SLEEP);
+ if (bam_adaptive_timer_enabled) {
+ usleep_range(rx_timer_interval, rx_timer_interval + 50);
+
+ ret = sps_get_unused_desc_num(bam_rx_pipe,
+ &buffs_unused);
+
+ if (ret) {
+ pr_err("%s: error getting num buffers unused after sleep\n",
+ __func__);
+
+ break;
+ }
+
+ buffs_used = NUM_BUFFERS - buffs_unused;
+
+ if (buffs_unused == 0) {
+ rx_timer_interval = MIN_POLLING_SLEEP;
+ } else {
+ if (buffs_used > 0) {
+ rx_timer_interval =
+ (2 * NUM_BUFFERS *
+ rx_timer_interval)/
+ (3 * buffs_used);
+ } else {
+ rx_timer_interval =
+ MAX_POLLING_SLEEP;
+ }
+ }
+
+ if (rx_timer_interval > MAX_POLLING_SLEEP)
+ rx_timer_interval = MAX_POLLING_SLEEP;
+ else if (rx_timer_interval < MIN_POLLING_SLEEP)
+ rx_timer_interval = MIN_POLLING_SLEEP;
+ } else {
+ usleep_range(POLLING_MIN_SLEEP, POLLING_MAX_SLEEP);
+ }
}
}
@@ -2379,6 +2429,8 @@
bam_dmux_state_logging_disabled = 1;
}
+ rx_timer_interval = DEFAULT_POLLING_MIN_SLEEP;
+
subsys_notif_register_notifier("modem", &restart_notifier);
return platform_driver_register(&bam_dmux_driver);
}
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index da0fd31..5780ca1 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -236,18 +236,9 @@
.name = "mdp",
};
-static int mdp_core_clk_rate_table[] = {
- 59080000,
- 128000000,
- 160000000,
- 200000000,
-};
-
static struct msm_panel_common_pdata mdp_pdata = {
.gpio = MDP_VSYNC_GPIO,
- .mdp_core_clk_rate = 59080000,
- .mdp_core_clk_table = mdp_core_clk_rate_table,
- .num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
+ .mdp_max_clk = 200000000,
.mdp_bus_scale_table = &mdp_bus_scale_pdata,
.mdp_rev = MDP_REV_44,
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -1026,8 +1017,6 @@
*/
static void set_mdp_clocks_for_wuxga(void)
{
- int i;
-
mdp_ui_vectors[0].ab = 2000000000;
mdp_ui_vectors[0].ib = 2000000000;
mdp_vga_vectors[0].ab = 2000000000;
@@ -1037,11 +1026,6 @@
mdp_1080p_vectors[0].ab = 2000000000;
mdp_1080p_vectors[0].ib = 2000000000;
- mdp_pdata.mdp_core_clk_rate = 200000000;
-
- for (i = 0; i < ARRAY_SIZE(mdp_core_clk_rate_table); i++)
- mdp_core_clk_rate_table[i] = 200000000;
-
if (apq8064_hdmi_as_primary_selected()) {
dtv_bus_def_vectors[0].ab = 2000000000;
dtv_bus_def_vectors[0].ib = 2000000000;
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index e77e7c0..518579a 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -389,11 +389,11 @@
static struct pm8921_bms_platform_data
apq8064_pm8921_bms_pdata __devinitdata = {
- .battery_type = BATT_UNKNOWN,
+ .battery_type = BATT_UNKNOWN,
.r_sense = 10,
- .i_test = 2500,
- .v_failure = 3000,
+ .v_cutoff = 3400,
.max_voltage_uv = MAX_VOLTAGE_MV * 1000,
+ .shutdown_soc_valid_limit = 20,
};
static struct pm8921_platform_data
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 665b861..68a85c0 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -95,7 +95,7 @@
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
#define HOLE_SIZE 0x20000
-#define MSM_PMEM_KERNEL_EBI1_SIZE 0x65000
+#define MSM_CONTIG_MEM_SIZE 0x65000
#ifdef CONFIG_MSM_IOMMU
#define MSM_ION_MM_SIZE 0x3800000
#define MSM_ION_SF_SIZE 0
@@ -111,7 +111,7 @@
#define MSM_ION_MFC_SIZE SZ_8K
#define MSM_ION_AUDIO_SIZE MSM_PMEM_AUDIO_SIZE
#else
-#define MSM_PMEM_KERNEL_EBI1_SIZE 0x110C000
+#define MSM_CONTIG_MEM_SIZE 0x110C000
#define MSM_ION_HEAP_NUM 1
#endif
@@ -133,14 +133,14 @@
#define PCIE_PWR_EN_PMIC_GPIO 13
#define PCIE_RST_N_PMIC_MPP 1
-#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
-static unsigned pmem_kernel_ebi1_size = MSM_PMEM_KERNEL_EBI1_SIZE;
-static int __init pmem_kernel_ebi1_size_setup(char *p)
+#ifdef CONFIG_KERNEL_MSM_CONTIG_MEM_REGION
+static unsigned msm_contig_mem_size = MSM_CONTIG_MEM_SIZE;
+static int __init msm_contig_mem_size_setup(char *p)
{
- pmem_kernel_ebi1_size = memparse(p, NULL);
+ msm_contig_mem_size = memparse(p, NULL);
return 0;
}
-early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup);
+early_param("msm_contig_mem_size", msm_contig_mem_size_setup);
#endif
#ifdef CONFIG_ANDROID_PMEM
@@ -263,7 +263,7 @@
reserve_memory_for(&android_pmem_pdata);
reserve_memory_for(&android_pmem_audio_pdata);
#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
- apq8064_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
+ apq8064_reserve_table[MEMTYPE_EBI1].size += msm_contig_mem_size;
#endif /*CONFIG_ANDROID_PMEM*/
}
@@ -1022,7 +1022,7 @@
.micbias = {
.ldoh_v = TABLA_LDOH_2P85_V,
.cfilt1_mv = 1800,
- .cfilt2_mv = 1800,
+ .cfilt2_mv = 2700,
.cfilt3_mv = 1800,
.bias1_cfilt_sel = TABLA_CFILT1_SEL,
.bias2_cfilt_sel = TABLA_CFILT2_SEL,
@@ -1089,7 +1089,7 @@
.micbias = {
.ldoh_v = TABLA_LDOH_2P85_V,
.cfilt1_mv = 1800,
- .cfilt2_mv = 1800,
+ .cfilt2_mv = 2700,
.cfilt3_mv = 1800,
.bias1_cfilt_sel = TABLA_CFILT1_SEL,
.bias2_cfilt_sel = TABLA_CFILT2_SEL,
@@ -2292,6 +2292,7 @@
&apq8064_iommu_domain_device,
&msm_tsens_device,
&apq8064_cache_dump_device,
+ &msm_8064_device_tspp,
};
static struct platform_device *cdp_devices[] __initdata = {
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index d975997..2a8e918 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -413,31 +413,9 @@
#endif
-#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
-static int mdp_core_clk_rate_table[] = {
- 200000000,
- 200000000,
- 200000000,
- 200000000,
-};
-#else
-static int mdp_core_clk_rate_table[] = {
- 85330000,
- 128000000,
- 160000000,
- 200000000,
-};
-#endif
-
static struct msm_panel_common_pdata mdp_pdata = {
.gpio = MDP_VSYNC_GPIO,
-#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
- .mdp_core_clk_rate = 200000000,
-#else
- .mdp_core_clk_rate = 85330000,
-#endif
- .mdp_core_clk_table = mdp_core_clk_rate_table,
- .num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
+ .mdp_max_clk = 200000000,
#ifdef CONFIG_MSM_BUS_SCALING
.mdp_bus_scale_table = &mdp_bus_scale_pdata,
#endif
diff --git a/arch/arm/mach-msm/board-8930-pmic.c b/arch/arm/mach-msm/board-8930-pmic.c
index a1a4b7c..384b1cf 100644
--- a/arch/arm/mach-msm/board-8930-pmic.c
+++ b/arch/arm/mach-msm/board-8930-pmic.c
@@ -340,11 +340,11 @@
};
static struct pm8921_bms_platform_data pm8921_bms_pdata __devinitdata = {
- .battery_type = BATT_UNKNOWN,
+ .battery_type = BATT_UNKNOWN,
.r_sense = 10,
- .i_test = 2500,
- .v_failure = 3000,
+ .v_cutoff = 3400,
.max_voltage_uv = MAX_VOLTAGE_MV * 1000,
+ .shutdown_soc_valid_limit = 20,
};
static struct pm8038_platform_data pm8038_platform_data __devinitdata = {
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 4fce029..d5014bd 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -141,7 +141,7 @@
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
#define HOLE_SIZE 0x20000
-#define MSM_PMEM_KERNEL_EBI1_SIZE 0x65000
+#define MSM_CONTIG_MEM_SIZE 0x65000
#ifdef CONFIG_MSM_IOMMU
#define MSM_ION_MM_SIZE 0x3800000 /* Need to be multiple of 64K */
#define MSM_ION_SF_SIZE 0x0
@@ -168,18 +168,18 @@
#define MSM8930_FW_START MSM8930_FIXED_AREA_START
#else
-#define MSM_PMEM_KERNEL_EBI1_SIZE 0x110C000
+#define MSM_CONTIG_MEM_SIZE 0x110C000
#define MSM_ION_HEAP_NUM 1
#endif
-#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
-static unsigned pmem_kernel_ebi1_size = MSM_PMEM_KERNEL_EBI1_SIZE;
-static int __init pmem_kernel_ebi1_size_setup(char *p)
+#ifdef CONFIG_KERNEL_MSM_CONTIG_MEM_REGION
+static unsigned msm_contig_mem_size = MSM_CONTIG_MEM_SIZE;
+static int __init msm_contig_mem_size_setup(char *p)
{
- pmem_kernel_ebi1_size = memparse(p, NULL);
+ msm_contig_mem_size = memparse(p, NULL);
return 0;
}
-early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup);
+early_param("msm_contig_mem_size", msm_contig_mem_size_setup);
#endif
#ifdef CONFIG_ANDROID_PMEM
@@ -322,7 +322,7 @@
reserve_memory_for(&android_pmem_pdata);
reserve_memory_for(&android_pmem_audio_pdata);
#endif /*CONFIG_MSM_MULTIMEDIA_USE_ION*/
- msm8930_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
+ msm8930_reserve_table[MEMTYPE_EBI1].size += msm_contig_mem_size;
#endif /*CONFIG_ANDROID_PMEM*/
}
@@ -2297,6 +2297,7 @@
&msm_cpudai_incall_record_rx,
&msm_cpudai_incall_record_tx,
&msm_pcm_hostless,
+ &msm_multi_ch_pcm,
};
static void __init msm8930_i2c_init(void)
diff --git a/arch/arm/mach-msm/board-8960-display.c b/arch/arm/mach-msm/board-8960-display.c
index ddeba32..f993ed8 100644
--- a/arch/arm/mach-msm/board-8960-display.c
+++ b/arch/arm/mach-msm/board-8960-display.c
@@ -573,18 +573,9 @@
#endif
-static int mdp_core_clk_rate_table[] = {
- 85330000,
- 128000000,
- 160000000,
- 200000000,
-};
-
static struct msm_panel_common_pdata mdp_pdata = {
.gpio = MDP_VSYNC_GPIO,
- .mdp_core_clk_rate = 85330000,
- .mdp_core_clk_table = mdp_core_clk_rate_table,
- .num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
+ .mdp_max_clk = 200000000,
#ifdef CONFIG_MSM_BUS_SCALING
.mdp_bus_scale_table = &mdp_bus_scale_pdata,
#endif
@@ -1043,8 +1034,6 @@
*/
static void set_mdp_clocks_for_wuxga(void)
{
- int i;
-
mdp_ui_vectors[0].ab = 2000000000;
mdp_ui_vectors[0].ib = 2000000000;
mdp_vga_vectors[0].ab = 2000000000;
@@ -1054,11 +1043,6 @@
mdp_1080p_vectors[0].ab = 2000000000;
mdp_1080p_vectors[0].ib = 2000000000;
- mdp_pdata.mdp_core_clk_rate = 200000000;
-
- for (i = 0; i < ARRAY_SIZE(mdp_core_clk_rate_table); i++)
- mdp_core_clk_rate_table[i] = 200000000;
-
if (hdmi_is_primary) {
dtv_bus_def_vectors[0].ab = 2000000000;
dtv_bus_def_vectors[0].ib = 2000000000;
diff --git a/arch/arm/mach-msm/board-8960-pmic.c b/arch/arm/mach-msm/board-8960-pmic.c
index 5950026..98140b4 100644
--- a/arch/arm/mach-msm/board-8960-pmic.c
+++ b/arch/arm/mach-msm/board-8960-pmic.c
@@ -420,12 +420,12 @@
};
static struct pm8921_bms_platform_data pm8921_bms_pdata __devinitdata = {
- .battery_type = BATT_UNKNOWN,
+ .battery_type = BATT_UNKNOWN,
.r_sense = 10,
- .i_test = 2500,
- .v_failure = 3000,
+ .v_cutoff = 3400,
.max_voltage_uv = MAX_VOLTAGE_MV * 1000,
.rconn_mohm = 18,
+ .shutdown_soc_valid_limit = 20,
};
#define PM8921_LC_LED_MAX_CURRENT 4 /* I = 4mA */
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 6ad44d8..bcfd558 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -182,10 +182,12 @@
VREG_CONSUMERS(S5) = {
REGULATOR_SUPPLY("8921_s5", NULL),
REGULATOR_SUPPLY("krait0", "acpuclk-8960"),
+ REGULATOR_SUPPLY("krait0", "acpuclk-8960ab"),
};
VREG_CONSUMERS(S6) = {
REGULATOR_SUPPLY("8921_s6", NULL),
REGULATOR_SUPPLY("krait1", "acpuclk-8960"),
+ REGULATOR_SUPPLY("krait1", "acpuclk-8960ab"),
};
VREG_CONSUMERS(S7) = {
REGULATOR_SUPPLY("8921_s7", NULL),
@@ -581,6 +583,17 @@
RPM_REG_MAP(S8, 0, 1, "krait0_s8", "acpuclk-8960"),
RPM_REG_MAP(S8, 0, 2, "krait1_s8", "acpuclk-8960"),
RPM_REG_MAP(S8, 0, 6, "l2_s8", "acpuclk-8960"),
+
+ RPM_REG_MAP(L23, 0, 1, "krait0_l23", "acpuclk-8960ab"),
+ RPM_REG_MAP(L23, 0, 2, "krait1_l23", "acpuclk-8960ab"),
+ RPM_REG_MAP(L23, 0, 6, "l2_l23", "acpuclk-8960ab"),
+ RPM_REG_MAP(L24, 0, 1, "krait0_mem", "acpuclk-8960ab"),
+ RPM_REG_MAP(L24, 0, 2, "krait1_mem", "acpuclk-8960ab"),
+ RPM_REG_MAP(S3, 0, 1, "krait0_dig", "acpuclk-8960ab"),
+ RPM_REG_MAP(S3, 0, 2, "krait1_dig", "acpuclk-8960ab"),
+ RPM_REG_MAP(S8, 0, 1, "krait0_s8", "acpuclk-8960ab"),
+ RPM_REG_MAP(S8, 0, 2, "krait1_s8", "acpuclk-8960ab"),
+ RPM_REG_MAP(S8, 0, 6, "l2_s8", "acpuclk-8960ab"),
};
struct rpm_regulator_platform_data msm_rpm_regulator_pdata __devinitdata = {
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index ad788bc..22a5021 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -145,7 +145,7 @@
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
#define HOLE_SIZE 0x20000
-#define MSM_PMEM_KERNEL_EBI1_SIZE 0x65000
+#define MSM_CONTIG_MEM_SIZE 0x65000
#ifdef CONFIG_MSM_IOMMU
#define MSM_ION_MM_SIZE 0x3800000 /* Need to be multiple of 64K */
#define MSM_ION_SF_SIZE 0x0
@@ -173,18 +173,18 @@
static unsigned msm_ion_sf_size = MSM_ION_SF_SIZE;
#else
-#define MSM_PMEM_KERNEL_EBI1_SIZE 0x110C000
+#define MSM_CONTIG_MEM_SIZE 0x110C000
#define MSM_ION_HEAP_NUM 1
#endif
-#ifdef CONFIG_KERNEL_PMEM_EBI_REGION
-static unsigned pmem_kernel_ebi1_size = MSM_PMEM_KERNEL_EBI1_SIZE;
-static int __init pmem_kernel_ebi1_size_setup(char *p)
+#ifdef CONFIG_KERNEL_MSM_CONTIG_MEM_REGION
+static unsigned msm_contig_mem_size = MSM_CONTIG_MEM_SIZE;
+static int __init msm_contig_mem_size_setup(char *p)
{
- pmem_kernel_ebi1_size = memparse(p, NULL);
+ msm_contig_mem_size = memparse(p, NULL);
return 0;
}
-early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup);
+early_param("msm_contig_mem_size", msm_contig_mem_size_setup);
#endif
#ifdef CONFIG_ANDROID_PMEM
@@ -336,7 +336,7 @@
reserve_memory_for(&android_pmem_pdata);
reserve_memory_for(&android_pmem_audio_pdata);
#endif
- msm8960_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size;
+ msm8960_reserve_table[MEMTYPE_EBI1].size += msm_contig_mem_size;
#endif
}
@@ -2594,7 +2594,6 @@
#endif
static struct platform_device *common_devices[] __initdata = {
- &msm8960_device_acpuclk,
&msm8960_device_dmov,
&msm_device_smd,
&msm_device_uart_dm6,
@@ -3148,7 +3147,12 @@
msm_device_uart_dm8.dev.platform_data = &msm_uart_dm8_pdata;
platform_device_register(&msm_device_uart_dm8);
}
+ if (cpu_is_msm8960ab())
+ platform_device_register(&msm8960ab_device_acpuclk);
+ else
+ platform_device_register(&msm8960_device_acpuclk);
platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
+
msm8960_pm8921_gpio_mpp_init();
platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
msm8960_init_smsc_hub();
diff --git a/arch/arm/mach-msm/board-8974-regulator.c b/arch/arm/mach-msm/board-8974-regulator.c
deleted file mode 100644
index 1a41f09..0000000
--- a/arch/arm/mach-msm/board-8974-regulator.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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/platform_device.h>
-#include <linux/regulator/stub-regulator.h>
-
-#define VREG_CONSUMERS(_name) \
- static struct regulator_consumer_supply vreg_consumers_##_name[]
-
-/*
- * Consumer specific regulator names:
- * regulator name consumer dev_name
- */
-VREG_CONSUMERS(K0) = {
- REGULATOR_SUPPLY("krait0", "f9000000.qcom,acpuclk"),
-};
-VREG_CONSUMERS(K1) = {
- REGULATOR_SUPPLY("krait1", "f9000000.qcom,acpuclk"),
-};
-VREG_CONSUMERS(K2) = {
- REGULATOR_SUPPLY("krait2", "f9000000.qcom,acpuclk"),
-};
-VREG_CONSUMERS(K3) = {
- REGULATOR_SUPPLY("krait3", "f9000000.qcom,acpuclk"),
-};
-
-#define PM8X41_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
- _always_on, _supply_regulator, _hpm_min, _system_uA) \
- struct stub_regulator_pdata vreg_dev_##_id##_pdata __devinitdata = { \
- .init_data = { \
- .constraints = { \
- .valid_modes_mask = _modes, \
- .valid_ops_mask = _ops, \
- .min_uV = _min_uV, \
- .max_uV = _max_uV, \
- .input_uV = _max_uV, \
- .apply_uV = 0, \
- .always_on = _always_on, \
- .name = _name, \
- }, \
- .num_consumer_supplies = \
- ARRAY_SIZE(vreg_consumers_##_id), \
- .consumer_supplies = vreg_consumers_##_id, \
- .supply_regulator = _supply_regulator, \
- }, \
- .hpm_min_load = _hpm_min, \
- .system_uA = _system_uA, \
- }
-
-#define KRAIT_PWR(_id, _name, _always_on, _min_uV, _max_uV, \
- _supply_regulator, _hpm_min, _system_uA) \
- PM8X41_VREG_INIT(_id, _name, _min_uV, _max_uV, REGULATOR_MODE_NORMAL \
- | REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE | \
- REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
- REGULATOR_CHANGE_DRMS, _always_on, \
- _supply_regulator, _hpm_min, _system_uA)
-
-/* ID name a_on min_uV max_uV supply hpm_min sys_uA */
-KRAIT_PWR(K0, "krait0", 0, 850000, 1100000, NULL, 100000, 0);
-KRAIT_PWR(K1, "krait1", 0, 850000, 1100000, NULL, 100000, 0);
-KRAIT_PWR(K2, "krait2", 0, 850000, 1100000, NULL, 100000, 0);
-KRAIT_PWR(K3, "krait3", 0, 850000, 1100000, NULL, 100000, 0);
-
-#define VREG_DEVICE(_name, _devid) \
- static struct platform_device vreg_device_##_name __devinitdata = \
- { \
- .name = STUB_REGULATOR_DRIVER_NAME, \
- .id = _devid, \
- .dev = { .platform_data = &vreg_dev_##_name##_pdata }, \
- }
-
-VREG_DEVICE(K0, 0);
-VREG_DEVICE(K1, 1);
-VREG_DEVICE(K2, 2);
-VREG_DEVICE(K3, 3);
-
-struct platform_device *msm_8974_stub_regulator_devices[] __devinitdata = {
- &vreg_device_K0,
- &vreg_device_K1,
- &vreg_device_K2,
- &vreg_device_K3,
-};
-
-int msm_8974_stub_regulator_devices_len __devinitdata =
- ARRAY_SIZE(msm_8974_stub_regulator_devices);
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 3a3e208..388307b 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -24,8 +24,8 @@
#ifdef CONFIG_ANDROID_PMEM
#include <linux/android_pmem.h>
#endif
-#include <linux/regulator/stub-regulator.h>
#include <linux/regulator/machine.h>
+#include <linux/regulator/krait-regulator.h>
#include <linux/msm_thermal.h>
#include <asm/mach/map.h>
#include <asm/hardware/gic.h>
@@ -413,8 +413,6 @@
{
platform_device_register(&msm_device_smd_8974);
platform_device_register(&android_usb_device);
- platform_add_devices(msm_8974_stub_regulator_devices,
- msm_8974_stub_regulator_devices_len);
}
/*
@@ -431,7 +429,7 @@
msm_lpmrs_module_init();
rpm_regulator_smd_driver_init();
msm_spm_device_init();
- regulator_stub_init();
+ krait_power_init();
if (machine_is_msm8974_rumi())
msm_clock_init(&msm8974_rumi_clock_init_data);
else
diff --git a/arch/arm/mach-msm/board-9625-gpiomux.c b/arch/arm/mach-msm/board-9625-gpiomux.c
index e28c734..2919f06 100644
--- a/arch/arm/mach-msm/board-9625-gpiomux.c
+++ b/arch/arm/mach-msm/board-9625-gpiomux.c
@@ -24,6 +24,18 @@
.dir = GPIOMUX_OUT_HIGH,
};
+static struct gpiomux_setting gpio_spi_cs_config = {
+ .func = GPIOMUX_FUNC_9,
+ .drv = GPIOMUX_DRV_12MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gpio_spi_config = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_12MA,
+ .pull = GPIOMUX_PULL_NONE,
+};
+
static struct msm_gpiomux_config msm_blsp_configs[] __initdata = {
{
.gpio = 45, /* BLSP1 UART TX */
@@ -37,6 +49,31 @@
[GPIOMUX_SUSPENDED] = &gpio_uart_config,
},
},
+ {
+ .gpio = 69, /* BLSP6 QUP SPI_CS_N */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_cs_config,
+ },
+ },
+ {
+ .gpio = 20, /* BLSP6 QUP SPI_DATA_MOSI */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+ {
+ .gpio = 21, /* BLSP6 QUP SPI_DATA_MISO */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+ {
+ .gpio = 23, /* BLSP6 QUP SPI_CLK */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &gpio_spi_config,
+ },
+ },
+
};
void __init msm9625_init_gpiomux(void)
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index 4a9bbcd..e7ef1a9 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -46,8 +46,8 @@
CLK_DUMMY("dfab_clk", DFAB_CLK, NULL, 0),
CLK_DUMMY("dma_bam_pclk", DMA_BAM_P_CLK, NULL, 0),
CLK_DUMMY("mem_clk", NULL, NULL, 0),
- CLK_DUMMY("core_clk", NULL, "spi_qsd.1", OFF),
- CLK_DUMMY("iface_clk", NULL, "spi_qsd.1", OFF),
+ CLK_DUMMY("core_clk", SPI_CLK, "spi_qsd.1", OFF),
+ CLK_DUMMY("iface_clk", SPI_P_CLK, "spi_qsd.1", OFF),
CLK_DUMMY("core_clk", NULL, "f9966000.i2c", 0),
CLK_DUMMY("iface_clk", NULL, "f9966000.i2c", 0),
CLK_DUMMY("core_clk", NULL, "fe12f000.slim", OFF),
@@ -72,6 +72,8 @@
static struct of_dev_auxdata msm9625_auxdata_lookup[] __initdata = {
OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF991F000, \
"msm_serial_hsl.0", NULL),
+ OF_DEV_AUXDATA("qcom,spi-qup-v2", 0xF9928000, \
+ "spi_qsd.1", NULL),
{}
};
@@ -94,6 +96,8 @@
{
if (socinfo_init() < 0)
pr_err("%s: socinfo_init() failed\n", __func__);
+
+ msm9625_init_gpiomux();
msm_clock_init(&msm_dummy_clock_init_data);
of_platform_populate(NULL, of_default_bus_match_table,
msm9625_auxdata_lookup, NULL);
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 8adfdab..4524f43 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -4539,19 +4539,10 @@
.mddi_client_power = msm_fb_mddi_client_power,
};
-int mdp_core_clk_rate_table[] = {
- 122880000,
- 122880000,
- 192000000,
- 192000000,
-};
-
static struct msm_panel_common_pdata mdp_pdata = {
.hw_revision_addr = 0xac001270,
.gpio = 30,
- .mdp_core_clk_rate = 122880000,
- .mdp_core_clk_table = mdp_core_clk_rate_table,
- .num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
+ .mdp_max_clk = 192000000,
.mdp_rev = MDP_REV_40,
.mem_hid = MEMTYPE_EBI0,
};
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 7ddf88e..47d847e 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -9651,27 +9651,9 @@
}
#endif
-#ifdef CONFIG_FB_MSM_MIPI_DSI
-int mdp_core_clk_rate_table[] = {
- 85330000,
- 128000000,
- 160000000,
- 200000000,
-};
-#else
-int mdp_core_clk_rate_table[] = {
- 59080000,
- 128000000,
- 128000000,
- 200000000,
-};
-#endif
-
static struct msm_panel_common_pdata mdp_pdata = {
.gpio = MDP_VSYNC_GPIO,
- .mdp_core_clk_rate = 59080000,
- .mdp_core_clk_table = mdp_core_clk_rate_table,
- .num_mdp_clk = ARRAY_SIZE(mdp_core_clk_rate_table),
+ .mdp_max_clk = 200000000,
#ifdef CONFIG_MSM_BUS_SCALING
.mdp_bus_scale_table = &mdp_bus_scale_pdata,
#endif
@@ -9764,9 +9746,7 @@
static void __init msm_fb_add_devices(void)
{
#ifdef CONFIG_FB_MSM_LCDC_DSUB
- mdp_pdata.mdp_core_clk_table = NULL;
- mdp_pdata.num_mdp_clk = 0;
- mdp_pdata.mdp_core_clk_rate = 200000000;
+ mdp_pdata.mdp_max_clk = 200000000;
#endif
msm_fb_register_device("mdp", &mdp_pdata);
@@ -9790,8 +9770,6 @@
*/
static void set_mdp_clocks_for_wuxga(void)
{
- int i;
-
mdp_sd_smi_vectors[0].ab = 2000000000;
mdp_sd_smi_vectors[0].ib = 2000000000;
mdp_sd_smi_vectors[1].ab = 2000000000;
@@ -9817,10 +9795,7 @@
mdp_1080p_vectors[1].ab = 2000000000;
mdp_1080p_vectors[1].ib = 2000000000;
- mdp_pdata.mdp_core_clk_rate = 200000000;
-
- for (i = 0; i < ARRAY_SIZE(mdp_core_clk_rate_table); i++)
- mdp_core_clk_rate_table[i] = 200000000;
+ mdp_pdata.mdp_max_clk = 200000000;
}
#if (defined(CONFIG_MARIMBA_CORE)) && \
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 8ac1c88..91e9272 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -23,6 +23,7 @@
#include <mach/clk.h>
#include <mach/rpm-regulator-smd.h>
#include <mach/socinfo.h>
+#include <mach/rpm-smd.h>
#include "clock-local2.h"
#include "clock-pll.h"
@@ -615,13 +616,16 @@
#define RPM_BUS_CLK_TYPE 0x316b6c63
#define RPM_MEM_CLK_TYPE 0x326b6c63
-#define CXO_ID 0x0
-#define QDSS_ID 0x1
+#define RPM_SMD_KEY_ENABLE 0x62616E45
+
+#define CXO_ID 0x0
+#define QDSS_ID 0x1
+#define RPM_SCALING_ENABLE_ID 0x2
#define PNOC_ID 0x0
#define SNOC_ID 0x1
#define CNOC_ID 0x2
-#define MMSSNOC_AHB_ID 0x4
+#define MMSSNOC_AHB_ID 0x3
#define BIMC_ID 0x0
#define OCMEM_ID 0x1
@@ -4532,6 +4536,16 @@
{&camss_vfe_vfe_ahb_clk.c, MMSS_BASE, 0x003c},
{&camss_vfe_vfe_axi_clk.c, MMSS_BASE, 0x003d},
{&camss_vfe_vfe_ocmemnoc_clk.c, MMSS_BASE, 0x003e},
+ {&oxilicx_axi_clk.c, MMSS_BASE, 0x000b},
+ {&oxilicx_ahb_clk.c, MMSS_BASE, 0x000c},
+ {&ocmemcx_ocmemnoc_clk.c, MMSS_BASE, 0x0009},
+ {&oxili_gfx3d_clk.c, MMSS_BASE, 0x000d},
+ {&venus0_axi_clk.c, MMSS_BASE, 0x000f},
+ {&venus0_ocmemnoc_clk.c, MMSS_BASE, 0x0010},
+ {&venus0_ahb_clk.c, MMSS_BASE, 0x0011},
+ {&venus0_vcodec0_clk.c, MMSS_BASE, 0x000e},
+ {&mmss_s0_axi_clk.c, MMSS_BASE, 0x0005},
+ {&mmssnoc_ahb_clk.c, MMSS_BASE, 0x0001},
{&mdss_ahb_clk.c, MMSS_BASE, 0x0022},
{&mdss_hdmi_clk.c, MMSS_BASE, 0x001d},
{&mdss_mdp_clk.c, MMSS_BASE, 0x0014},
@@ -5432,6 +5446,24 @@
#define APCS_GCC_CC_PHYS 0xF9011000
#define APCS_GCC_CC_SIZE SZ_4K
+static void __init enable_rpm_scaling(void)
+{
+ int rc, value = 0x1;
+ struct msm_rpm_kvp kvp = {
+ .key = RPM_SMD_KEY_ENABLE,
+ .data = (void *)&value,
+ .length = sizeof(value),
+ };
+
+ rc = msm_rpm_send_message_noirq(MSM_RPM_CTX_SLEEP_SET,
+ RPM_MISC_CLK_TYPE, RPM_SCALING_ENABLE_ID, &kvp, 1);
+ WARN(rc < 0, "RPM clock scaling (sleep set) did not enable!\n");
+
+ rc = msm_rpm_send_message_noirq(MSM_RPM_CTX_ACTIVE_SET,
+ RPM_MISC_CLK_TYPE, RPM_SCALING_ENABLE_ID, &kvp, 1);
+ WARN(rc < 0, "RPM clock scaling (active set) did not enable!\n");
+}
+
static void __init msm8974_clock_pre_init(void)
{
virt_bases[GCC_BASE] = ioremap(GCC_CC_PHYS, GCC_CC_SIZE);
@@ -5469,6 +5501,8 @@
vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
rpm_regulator_enable(vdd_dig_reg);
+ enable_rpm_scaling();
+
reg_init();
}
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 0d05df9..e5261b0 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -29,6 +29,7 @@
#include <sound/msm-dai-q6.h>
#include <sound/apr_audio.h>
#include <mach/msm_tsif.h>
+#include <mach/msm_tspp.h>
#include <mach/msm_bus_board.h>
#include <mach/rpm.h>
#include <mach/mdm2.h>
@@ -583,6 +584,67 @@
}
};
+#define MSM_TSPP_PHYS (0x18202000)
+#define MSM_TSPP_SIZE (0x1000)
+#define MSM_TSPP_BAM_PHYS (0x18204000)
+#define MSM_TSPP_BAM_SIZE (0x2000)
+
+static const struct msm_gpio tspp_gpios[] = {
+ { .gpio_cfg = TSIF_0_CLK, .label = "tsif_clk", },
+ { .gpio_cfg = TSIF_0_EN, .label = "tsif_en", },
+ { .gpio_cfg = TSIF_0_DATA, .label = "tsif_data", },
+ { .gpio_cfg = TSIF_0_SYNC, .label = "tsif_sync", },
+ { .gpio_cfg = TSIF_1_CLK, .label = "tsif_clk", },
+ { .gpio_cfg = TSIF_1_EN, .label = "tsif_en", },
+ { .gpio_cfg = TSIF_1_DATA, .label = "tsif_data", },
+ { .gpio_cfg = TSIF_1_SYNC, .label = "tsif_sync", },
+};
+
+static struct resource tspp_resources[] = {
+ [0] = {
+ .flags = IORESOURCE_IRQ,
+ .start = TSIF_TSPP_IRQ,
+ .end = TSIF1_IRQ,
+ },
+ [1] = {
+ .flags = IORESOURCE_MEM,
+ .start = MSM_TSIF0_PHYS,
+ .end = MSM_TSIF0_PHYS + MSM_TSIF_SIZE - 1,
+ },
+ [2] = {
+ .flags = IORESOURCE_MEM,
+ .start = MSM_TSIF1_PHYS,
+ .end = MSM_TSIF1_PHYS + MSM_TSIF_SIZE - 1,
+ },
+ [3] = {
+ .flags = IORESOURCE_MEM,
+ .start = MSM_TSPP_PHYS,
+ .end = MSM_TSPP_PHYS + MSM_TSPP_SIZE - 1,
+ },
+ [4] = {
+ .flags = IORESOURCE_MEM,
+ .start = MSM_TSPP_BAM_PHYS,
+ .end = MSM_TSPP_BAM_PHYS + MSM_TSPP_BAM_SIZE - 1,
+ },
+};
+
+static struct msm_tspp_platform_data tspp_platform_data = {
+ .num_gpios = ARRAY_SIZE(tspp_gpios),
+ .gpios = tspp_gpios,
+ .tsif_pclk = "iface_clk",
+ .tsif_ref_clk = "ref_clk",
+};
+
+struct platform_device msm_8064_device_tspp = {
+ .name = "msm_tspp",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(tspp_resources),
+ .resource = tspp_resources,
+ .dev = {
+ .platform_data = &tspp_platform_data
+ },
+};
+
/*
* Machine specific data for AUX PCM Interface
* which the driver will be unware of.
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 8347580..ecfafa8 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -207,6 +207,11 @@
.id = -1,
};
+struct platform_device msm8960ab_device_acpuclk = {
+ .name = "acpuclk-8960ab",
+ .id = -1,
+};
+
#define SHARED_IMEM_TZ_BASE 0x2a03f720
static struct resource tzlog_resources[] = {
{
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 8e2ab7d..55c1e03 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -190,6 +190,7 @@
extern struct platform_device msm_device_tsif[2];
extern struct platform_device msm_8064_device_tsif[2];
+extern struct platform_device msm_8064_device_tspp;
extern struct platform_device msm_device_ssbi_pmic1;
extern struct platform_device msm_device_ssbi_pmic2;
@@ -435,6 +436,7 @@
extern struct platform_device msm8930_device_acpuclk;
extern struct platform_device msm8930aa_device_acpuclk;
extern struct platform_device msm8960_device_acpuclk;
+extern struct platform_device msm8960ab_device_acpuclk;
extern struct platform_device msm9615_device_acpuclk;
extern struct platform_device msm_gpio_device;
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 1770b97..f529522 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -391,9 +391,7 @@
void (*panel_config_gpio)(int);
int (*vga_switch)(int select_vga);
int *gpio_num;
- int mdp_core_clk_rate;
- unsigned num_mdp_clk;
- int *mdp_core_clk_table;
+ u32 mdp_max_clk;
#ifdef CONFIG_MSM_BUS_SCALING
struct msm_bus_scale_pdata *mdp_bus_scale_table;
#endif
@@ -583,6 +581,7 @@
void msm_8974_reserve(void);
void msm_8974_very_early(void);
void msm_8974_init_gpiomux(void);
+void msm9625_init_gpiomux(void);
struct mmc_platform_data;
int msm_add_sdcc(unsigned int controller,
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index 49e283d..e20e768 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -36,6 +36,7 @@
};
struct ocmem_zone {
+ bool active;
int owner;
int active_regions;
int max_regions;
@@ -178,6 +179,7 @@
}
struct ocmem_zone *get_zone(unsigned);
+int zone_active(int);
unsigned long offset_to_phys(unsigned long);
unsigned long phys_to_offset(unsigned long);
unsigned long allocate_head(struct ocmem_zone *, unsigned long);
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index e6e9acc..96c4809 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -67,10 +67,10 @@
#define LOAD_PER_PHASE 3200000
-#define CORE_VOLTAGE_MIN 500000
+#define CORE_VOLTAGE_MIN 900000
#define KRAIT_LDO_VOLTAGE_MIN 465000
-#define KRAIT_LDO_VOLTAGE_OFFSET 460000
+#define KRAIT_LDO_VOLTAGE_OFFSET 465000
#define KRAIT_LDO_STEP 5000
#define BHS_SETTLING_DELAY_US 1
@@ -734,6 +734,22 @@
module_exit(krait_power_exit);
+void secondary_cpu_hs_init(void *base_ptr)
+{
+ /* 605mV retention and 705mV operational voltage */
+ writel_relaxed(0x1C30, base_ptr + APC_LDO_VREF_SET);
+ writel_relaxed(0x430000, base_ptr + 0x20);
+ writel_relaxed(0x21, base_ptr + 0x1C);
+
+ /* Turn on the BHS, turn off LDO Bypass and power down LDO */
+ writel_relaxed(0x403F007F, base_ptr + APC_PWR_GATE_CTL);
+ mb();
+ udelay(1);
+
+ /* Finally turn on the bypass so that BHS supplies power */
+ writel_relaxed(0x403F3F7F, base_ptr + APC_PWR_GATE_CTL);
+}
+
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("KRAIT POWER regulator driver");
MODULE_VERSION("1.0");
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
index e035e35..9dcd51f 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_fabric.c
@@ -139,7 +139,7 @@
for (i = 0; i < fabric->pdata->len; i++) {
struct msm_bus_inode_info *info;
- int ctx;
+ int ctx, j;
info = kzalloc(sizeof(struct msm_bus_inode_info), GFP_KERNEL);
if (info == NULL) {
@@ -189,11 +189,17 @@
if (fabric->fabdev.hw_algo.node_init == NULL)
continue;
+ for (j = 0; j < NUM_CTX; j++)
+ clk_prepare_enable(fabric->info.nodeclk[j].clk);
+
fabric->fabdev.hw_algo.node_init(fabric->hw_data, info);
if (ret) {
MSM_BUS_ERR("Unable to init node info, ret: %d\n", ret);
kfree(info);
}
+
+ for (j = 0; j < NUM_CTX; j++)
+ clk_disable_unprepare(fabric->info.nodeclk[j].clk);
}
MSM_BUS_DBG("Fabric: %d nmasters: %d nslaves: %d\n"
@@ -337,6 +343,7 @@
{
struct msm_bus_fabric *fabric = to_msm_bus_fabric(fabdev);
void *sel_cdata;
+ int i;
/* Temporarily stub out arbitration settings for msm8974 */
if (machine_is_msm8974())
@@ -354,8 +361,14 @@
return;
}
+ for (i = 0; i < NUM_CTX; i++)
+ clk_prepare_enable(fabric->info.nodeclk[i].clk);
+
fabdev->hw_algo.update_bw(hop, info, fabric->pdata, sel_cdata,
master_tiers, add_bw);
+ for (i = 0; i < NUM_CTX; i++)
+ clk_disable_unprepare(fabric->info.nodeclk[i].clk);
+
fabric->arb_dirty = true;
}
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_noc.c b/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
index 2597e27..e6ec722 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_noc.c
@@ -388,7 +388,8 @@
(struct msm_bus_noc_info *)hw_data;
if (!IS_SLAVE(info->node_info->priv_id))
- msm_bus_noc_mas_init(ninfo, info);
+ if (info->node_info->hw_sel != MSM_BUS_RPM)
+ msm_bus_noc_mas_init(ninfo, info);
}
static int msm_bus_noc_allocate_commit_data(struct msm_bus_fabric_registration
diff --git a/arch/arm/mach-msm/ocmem.c b/arch/arm/mach-msm/ocmem.c
index a9c3f4c..8819bd2 100644
--- a/arch/arm/mach-msm/ocmem.c
+++ b/arch/arm/mach-msm/ocmem.c
@@ -103,7 +103,7 @@
const char *get_name(int id)
{
if (!check_id(id))
- return NULL;
+ return "Unknown";
return client_names[id];
}
@@ -126,6 +126,15 @@
return offset + ocmem_pdata->base;
}
+inline int zone_active(int id)
+{
+ struct ocmem_zone *z = get_zone(id);
+ if (z)
+ return z->active == true ? 1 : 0;
+ else
+ return 0;
+}
+
static struct ocmem_plat_data *parse_static_config(struct platform_device *pdev)
{
struct ocmem_plat_data *pdata = NULL;
@@ -444,6 +453,7 @@
for (i = 0; i < pdata->nr_parts; i++) {
struct ocmem_partition *part = &pdata->parts[i];
zone = get_zone(part->id);
+ zone->active = false;
dev_dbg(dev, "Partition %d, start %lx, size %lx for %s\n",
i, part->p_start, part->p_size,
@@ -501,6 +511,7 @@
z_ops->allocate = allocate_head;
z_ops->free = free_head;
}
+ zone->active = true;
active_zones++;
if (active_zones == 1)
diff --git a/arch/arm/mach-msm/ocmem_api.c b/arch/arm/mach-msm/ocmem_api.c
index a5aed5e..2604d47 100644
--- a/arch/arm/mach-msm/ocmem_api.c
+++ b/arch/arm/mach-msm/ocmem_api.c
@@ -110,6 +110,12 @@
return NULL;
}
+ if (!zone_active(client_id)) {
+ pr_err("ocmem: Client %s (id: %d) not allowed to use OCMEM\n",
+ get_name(client_id), client_id);
+ return NULL;
+ }
+
if (size < OCMEM_MIN_ALLOC) {
pr_err("ocmem: requested size %lx must be at least %x\n",
size, OCMEM_MIN_ALLOC);
@@ -136,6 +142,12 @@
return NULL;
}
+ if (!zone_active(client_id)) {
+ pr_err("ocmem: Client %s (id: %d) not allowed to use OCMEM\n",
+ get_name(client_id), client_id);
+ return NULL;
+ }
+
if (size < OCMEM_MIN_ALLOC) {
pr_err("ocmem: requested size %lx must be at least %x\n",
size, OCMEM_MIN_ALLOC);
@@ -162,6 +174,12 @@
return NULL;
}
+ if (!zone_active(client_id)) {
+ pr_err("ocmem: Client %s (id: %d) not allowed to use OCMEM\n",
+ get_name(client_id), client_id);
+ return NULL;
+ }
+
/* Asynchronous API requires notifier registration */
if (!check_notifier(client_id)) {
pr_err("ocmem: No notifier registered for client %d\n",
@@ -202,6 +220,12 @@
return NULL;
}
+ if (!zone_active(client_id)) {
+ pr_err("ocmem: Client %s (id: %d) not allowed to use OCMEM\n",
+ get_name(client_id), client_id);
+ return NULL;
+ }
+
if (size < OCMEM_MIN_ALLOC) {
pr_err("ocmem: requested size %lx must be at least %x\n",
size, OCMEM_MIN_ALLOC);
@@ -226,6 +250,12 @@
return -EINVAL;
}
+ if (!zone_active(client_id)) {
+ pr_err("ocmem: Client %s (id: %d) not allowed to use OCMEM\n",
+ get_name(client_id), client_id);
+ return -EINVAL;
+ }
+
if (!buffer) {
pr_err("ocmem: Invalid buffer\n");
return -EINVAL;
@@ -240,6 +270,13 @@
return -EINVAL;
if (len >= buffer->len)
return -EINVAL;
+
+ if (!zone_active(client_id)) {
+ pr_err("ocmem: Client id: %s (id: %d) not allowed to use OCMEM\n",
+ get_name(client_id), client_id);
+ return -EINVAL;
+ }
+
return __ocmem_shrink(client_id, buffer, len);
}
@@ -282,6 +319,12 @@
return -EINVAL;
}
+ if (!zone_active(client_id)) {
+ pr_err("ocmem: Client id: %s (id: %d) not allowed to use OCMEM\n",
+ get_name(client_id), client_id);
+ return -EINVAL;
+ }
+
/* Asynchronous API requires notifier registration */
if (!check_notifier(client_id)) {
pr_err("ocmem: No notifier registered for client %d\n",
@@ -320,6 +363,12 @@
return -EINVAL;
}
+ if (!zone_active(client_id)) {
+ pr_err("ocmem: Client id: %s (id: %d) not allowed to use OCMEM\n",
+ get_name(client_id), client_id);
+ return -EINVAL;
+ }
+
/* Asynchronous API requires notifier registration */
if (!check_notifier(client_id)) {
pr_err("ocmem: No notifier registered for client %d\n",
diff --git a/arch/arm/mach-msm/ocmem_notifier.c b/arch/arm/mach-msm/ocmem_notifier.c
index 9fbcd73..644c809 100644
--- a/arch/arm/mach-msm/ocmem_notifier.c
+++ b/arch/arm/mach-msm/ocmem_notifier.c
@@ -82,6 +82,12 @@
return NULL;
}
+ if (!zone_active(client_id)) {
+ pr_err("ocmem: Client %s (id: %d) not allowed to use OCMEM\n",
+ get_name(client_id), client_id);
+ return NULL;
+ }
+
if (!nb) {
pr_err("ocmem: Invalid Notifier Block\n");
return NULL;
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index 70e6860..75081af 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -116,7 +116,7 @@
int hw_interconnect;
} ocmem_client_table[OCMEM_CLIENT_MAX] = {
{OCMEM_GRAPHICS, PRIO_GFX, OCMEM_PERFORMANCE, OCMEM_PORT},
- {OCMEM_VIDEO, PRIO_VIDEO, OCMEM_PERFORMANCE, OCMEM_OCMEMNOC},
+ {OCMEM_VIDEO, PRIO_VIDEO, OCMEM_PERFORMANCE, OCMEM_PORT},
{OCMEM_CAMERA, NO_PRIO, OCMEM_PERFORMANCE, OCMEM_OCMEMNOC},
{OCMEM_HP_AUDIO, PRIO_HP_AUDIO, OCMEM_PASSIVE, OCMEM_BLOCKED},
{OCMEM_VOICE, PRIO_VOICE, OCMEM_PASSIVE, OCMEM_BLOCKED},
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index 28b7748..b2d3dfa 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -14,6 +14,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/regulator/krait-regulator.h>
#include <asm/hardware/gic.h>
#include <asm/cacheflush.h>
@@ -126,6 +127,8 @@
if (!base_ptr)
return -ENODEV;
+ secondary_cpu_hs_init(base_ptr);
+
writel_relaxed(0x021, base_ptr+0x04);
mb();
udelay(2);
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index 0faafc8..1225fec 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -64,7 +64,8 @@
#define GFP_FLAG(noirq) (noirq ? GFP_ATOMIC : GFP_KERNEL)
#define INV_HDR "resource does not exist"
#define ERR "err\0"
-#define MAX_ERR_BUFFER_SIZE 60
+#define MAX_ERR_BUFFER_SIZE 128
+#define INIT_ERROR 1
static ATOMIC_NOTIFIER_HEAD(msm_rpm_sleep_notifier);
static bool standalone;
@@ -388,6 +389,7 @@
init_completion(&data->ack);
data->ack_recd = false;
data->msg_id = msg_id;
+ data->errno = INIT_ERROR;
spin_lock_irqsave(&msm_rpm_list_lock, flags);
list_add(&data->list, &msm_rpm_wait_list);
spin_unlock_irqrestore(&msm_rpm_list_lock, flags);
@@ -463,7 +465,7 @@
return rc;
}
-static void msm_rpm_read_smd_data(char *buf)
+static int msm_rpm_read_smd_data(char *buf)
{
int pkt_sz;
int bytes_read = 0;
@@ -473,7 +475,7 @@
BUG_ON(pkt_sz > MAX_ERR_BUFFER_SIZE);
if (pkt_sz != smd_read_avail(msm_rpm_data.ch_info))
- return;
+ return -EAGAIN;
BUG_ON(pkt_sz == 0);
@@ -487,6 +489,8 @@
} while (pkt_sz > 0);
BUG_ON(pkt_sz < 0);
+
+ return 0;
}
static void msm_rpm_smd_work(struct work_struct *work)
@@ -498,11 +502,15 @@
while (smd_is_pkt_avail(msm_rpm_data.ch_info) && !irq_process) {
spin_lock_irqsave(&msm_rpm_data.smd_lock_read, flags);
- msm_rpm_read_smd_data(buf);
- spin_unlock_irqrestore(&msm_rpm_data.smd_lock_read, flags);
+ if (msm_rpm_read_smd_data(buf)) {
+ spin_unlock_irqrestore(&msm_rpm_data.smd_lock_read,
+ flags);
+ break;
+ }
msg_id = msm_rpm_get_msg_id_from_ack(buf);
errno = msm_rpm_get_error_from_ack(buf);
msm_rpm_process_ack(msg_id, errno);
+ spin_unlock_irqrestore(&msm_rpm_data.smd_lock_read, flags);
}
}
@@ -814,6 +822,12 @@
*/
goto wait_ack_cleanup;
+ if (elem->errno != INIT_ERROR) {
+ rc = elem->errno;
+ msm_rpm_free_list_entry(elem);
+ goto wait_ack_cleanup;
+ }
+
while ((id != msg_id) && (count++ < 10)) {
if (smd_is_pkt_avail(msm_rpm_data.ch_info)) {
int errno;
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index decee95..e82e44b 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -2264,13 +2264,17 @@
int smd_is_pkt_avail(smd_channel_t *ch)
{
+ unsigned long flags;
+
if (!ch || !ch->is_pkt_ch)
return -EINVAL;
if (ch->current_packet)
return 1;
+ spin_lock_irqsave(&smd_lock, flags);
update_packet_state(ch);
+ spin_unlock_irqrestore(&smd_lock, flags);
return ch->current_packet ? 1 : 0;
}
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index 65da903..fdde328 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -59,7 +59,7 @@
char wlname[64];
struct work_struct work;
spinlock_t restart_lock;
- bool restarting;
+ int restart_count;
void *notify;
@@ -406,8 +406,9 @@
out:
spin_lock_irqsave(&dev->restart_lock, flags);
- wake_unlock(&dev->wake_lock);
- dev->restarting = false;
+ dev->restart_count--;
+ if (!dev->restart_count)
+ wake_unlock(&dev->wake_lock);
spin_unlock_irqrestore(&dev->restart_lock, flags);
}
@@ -416,16 +417,21 @@
struct subsys_desc *desc = dev->desc;
unsigned long flags;
- spin_lock_irqsave(&dev->restart_lock, flags);
- if (!dev->restarting) {
- pr_debug("Restarting %s [level=%d]!\n", desc->name,
- restart_level);
+ pr_debug("Restarting %s [level=%d]!\n", desc->name, restart_level);
- dev->restarting = true;
+ spin_lock_irqsave(&dev->restart_lock, flags);
+ if (!dev->restart_count)
wake_lock(&dev->wake_lock);
- queue_work(ssr_wq, &dev->work);
- }
+ dev->restart_count++;
spin_unlock_irqrestore(&dev->restart_lock, flags);
+
+ if (!queue_work(ssr_wq, &dev->work)) {
+ spin_lock_irqsave(&dev->restart_lock, flags);
+ dev->restart_count--;
+ if (!dev->restart_count)
+ wake_unlock(&dev->wake_lock);
+ spin_unlock_irqrestore(&dev->restart_lock, flags);
+ }
}
int subsystem_restart_dev(struct subsys_device *dev)
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 318523b..cbf1d72 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -180,8 +180,13 @@
static void riva_crash_shutdown(const struct subsys_desc *subsys)
{
pr_err("%s: crash shutdown : %d\n", MODULE_NAME, riva_crash);
- if (riva_crash != true)
+ if (riva_crash != true) {
smsm_riva_reset();
+ /* give sufficient time for wcnss to finish it's error
+ * fatal routine */
+ msleep(3000);
+ }
+
}
static struct subsys_desc riva_8960 = {
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index b117309..cfcacff 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -44,7 +44,7 @@
#include "hci_uart.h"
-unsigned int enableuartsleep;
+unsigned int enableuartsleep = 1;
module_param(enableuartsleep, uint, 0644);
/*
* Global variables
@@ -110,9 +110,9 @@
int status = 0;
if (test_bit(BT_TXEXPIRED, &flags)) {
printk(KERN_INFO "wakeup device\n");
- gpio_set_value(bsi->ext_wake, 1);
- msleep(20);
gpio_set_value(bsi->ext_wake, 0);
+ msleep(20);
+ gpio_set_value(bsi->ext_wake, 1);
}
modify_timer_task();
return status;
@@ -353,7 +353,7 @@
gpio_free(bsi->ext_wake);
goto free_bt_host_wake;
}
- gpio_set_value(bsi->ext_wake, 0);
+ gpio_set_value(bsi->ext_wake, 1);
bsi->host_wake_irq = platform_get_irq_byname(pdev, "host_wake");
if (bsi->host_wake_irq < 0) {
diff --git a/drivers/gpio/gpio-msm-v3.c b/drivers/gpio/gpio-msm-v3.c
index e0b01cd..26716a0 100644
--- a/drivers/gpio/gpio-msm-v3.c
+++ b/drivers/gpio/gpio-msm-v3.c
@@ -141,7 +141,7 @@
void __msm_gpio_set_intr_status(unsigned gpio)
{
- __raw_writel(BIT(INTR_STATUS_BIT), GPIO_INTR_STATUS(gpio));
+ __raw_writel(0, GPIO_INTR_STATUS(gpio));
}
unsigned __msm_gpio_get_intr_config(unsigned gpio)
@@ -167,15 +167,12 @@
{
unsigned cfg;
- cfg = __raw_readl(GPIO_INTR_CFG(gpio));
-
/* RAW_STATUS_EN is left on for all gpio irqs. Due to the
* internal circuitry of TLMM, toggling the RAW_STATUS
* could cause the INTR_STATUS to be set for EDGE interrupts.
*/
- cfg |= (INTR_RAW_STATUS_EN | INTR_TARGET_PROC_APPS);
+ cfg = INTR_RAW_STATUS_EN | INTR_TARGET_PROC_APPS;
__raw_writel(cfg, GPIO_INTR_CFG(gpio));
- cfg = __raw_readl(GPIO_INTR_CFG(gpio));
cfg &= ~INTR_DECT_CTL_MASK;
if (type == IRQ_TYPE_EDGE_RISING)
cfg |= INTR_DECT_CTL_POS_EDGE;
@@ -186,10 +183,10 @@
else
cfg |= INTR_DECT_CTL_LEVEL;
- if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
- cfg |= INTR_POL_CTL_HI;
- else
+ if (type & IRQ_TYPE_LEVEL_LOW)
cfg &= ~INTR_POL_CTL_HI;
+ else
+ cfg |= INTR_POL_CTL_HI;
__raw_writel(cfg, GPIO_INTR_CFG(gpio));
/* Sometimes it might take a little while to update
diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c
index ccbbd67..6511c95 100644
--- a/drivers/gpio/qpnp-pin.c
+++ b/drivers/gpio/qpnp-pin.c
@@ -39,17 +39,17 @@
/* gpio peripheral type and subtype values */
#define Q_GPIO_TYPE 0x10
-#define Q_GPIO_SUBTYPE_GPIO_4CH 0x0
-#define Q_GPIO_SUBTYPE_GPIOC_4CH 0x2
-#define Q_GPIO_SUBTYPE_GPIO_8CH 0x4
-#define Q_GPIO_SUBTYPE_GPIOC_8CH 0x6
+#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
/* mpp peripheral type and subtype values */
#define Q_MPP_TYPE 0x11
#define Q_MPP_SUBTYPE_4CH_NO_ANA_OUT 0x3
#define Q_MPP_SUBTYPE_4CH_NO_SINK 0x5
-#define Q_MPP_SUBTYPE_4CH_FULL_FUNC 0x2
-#define Q_MPP_SUBTYPE_8CH_FULL_FUNC 0x4
+#define Q_MPP_SUBTYPE_4CH_FULL_FUNC 0x7
+#define Q_MPP_SUBTYPE_8CH_FULL_FUNC 0xF
/* control register base address offsets */
#define Q_REG_MODE_CTL 0x40
@@ -129,7 +129,8 @@
#define Q_NUM_PARAMS Q_PIN_CFG_INVALID
/* param error checking */
-#define QPNP_PIN_MODE_INVALID 3
+#define QPNP_PIN_GPIO_MODE_INVALID 3
+#define QPNP_PIN_MPP_MODE_INVALID 7
#define QPNP_PIN_INVERT_INVALID 2
#define QPNP_PIN_OUT_BUF_INVALID 3
#define QPNP_PIN_VIN_4CH_INVALID 5
@@ -225,8 +226,12 @@
{
switch (idx) {
case Q_PIN_CFG_MODE:
- if (val >= QPNP_PIN_MODE_INVALID)
- return -EINVAL;
+ if (q_spec->type == Q_GPIO_TYPE &&
+ val >= QPNP_PIN_GPIO_MODE_INVALID)
+ return -EINVAL;
+ else if (q_spec->type == Q_MPP_TYPE &&
+ val >= QPNP_PIN_MPP_MODE_INVALID)
+ return -EINVAL;
break;
case Q_PIN_CFG_OUTPUT_TYPE:
if (q_spec->type != Q_GPIO_TYPE)
@@ -327,29 +332,40 @@
name = (q_spec->type == Q_GPIO_TYPE) ? "gpio" : "mpp";
if (Q_CHK_INVALID(Q_PIN_CFG_MODE, q_spec, param->mode))
- pr_err("invalid direction for %s %d\n", name, pin);
+ pr_err("invalid direction value %d for %s %d\n",
+ param->mode, name, pin);
else if (Q_CHK_INVALID(Q_PIN_CFG_INVERT, q_spec, param->invert))
- pr_err("invalid invert polarity for %s %d\n", name, pin);
+ pr_err("invalid invert polarity value %d for %s %d\n",
+ param->invert, name, pin);
else if (Q_CHK_INVALID(Q_PIN_CFG_SELECT, q_spec, param->select))
- pr_err("invalid source select for %s %d\n", name, pin);
+ pr_err("invalid source select value %d for %s %d\n",
+ param->select, name, pin);
else if (Q_CHK_INVALID(Q_PIN_CFG_OUT_STRENGTH,
q_spec, param->out_strength))
- pr_err("invalid out strength for %s %d\n", name, pin);
+ pr_err("invalid out strength value %d for %s %d\n",
+ param->out_strength, name, pin);
else if (Q_CHK_INVALID(Q_PIN_CFG_OUTPUT_TYPE,
q_spec, param->output_type))
- pr_err("invalid out type for %s %d\n", name, pin);
+ pr_err("invalid out type value %d for %s %d\n",
+ param->output_type, name, pin);
else if (Q_CHK_INVALID(Q_PIN_CFG_VIN_SEL, q_spec, param->vin_sel))
- pr_err("invalid vin select value for %s %d\n", name, pin);
+ pr_err("invalid vin select %d value for %s %d\n",
+ param->vin_sel, name, pin);
else if (Q_CHK_INVALID(Q_PIN_CFG_PULL, q_spec, param->pull))
- pr_err("invalid pull value for pin %s %d\n", name, pin);
+ pr_err("invalid pull value %d for pin %s %d\n",
+ param->pull, name, pin);
else if (Q_CHK_INVALID(Q_PIN_CFG_MASTER_EN, q_spec, param->master_en))
- pr_err("invalid master_en value for %s %d\n", name, pin);
+ pr_err("invalid master_en value %d for %s %d\n",
+ param->master_en, name, pin);
else if (Q_CHK_INVALID(Q_PIN_CFG_AOUT_REF, q_spec, param->aout_ref))
- pr_err("invalid aout_reg value for %s %d\n", name, pin);
+ pr_err("invalid aout_reg value %d for %s %d\n",
+ param->aout_ref, name, pin);
else if (Q_CHK_INVALID(Q_PIN_CFG_AIN_ROUTE, q_spec, param->ain_route))
- pr_err("invalid ain_route value for %s %d\n", name, pin);
+ pr_err("invalid ain_route value %d for %s %d\n",
+ param->ain_route, name, pin);
else if (Q_CHK_INVALID(Q_PIN_CFG_CS_OUT, q_spec, param->cs_out))
- pr_err("invalid cs_out value for %s %d\n", name, pin);
+ pr_err("invalid cs_out value %d for %s %d\n",
+ param->cs_out, name, pin);
else
return 0;
@@ -532,7 +548,7 @@
return 0;
gpio_cfg:
- dev_err(dev, "%s: unable to set default config for pmic gpio %d\n",
+ dev_err(dev, "%s: unable to set default config for pmic pin %d\n",
__func__, q_spec->pmic_pin);
return rc;
@@ -688,7 +704,7 @@
if (!q_chip || !q_spec)
return -EINVAL;
- if (mode >= QPNP_PIN_MODE_INVALID) {
+ if (qpnp_pin_check_config(Q_PIN_CFG_MODE, q_spec, mode)) {
pr_err("invalid mode specification %d\n", mode);
return -EINVAL;
}
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 6a894c8..3d1fbc8 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -111,7 +111,7 @@
.gmem_size = SZ_256K,
.pfp_fw = NULL,
.pm4_fw = NULL,
- .wait_timeout = 10000, /* in milliseconds */
+ .wait_timeout = 0, /* in milliseconds, 0 means disabled */
.ib_check_level = 0,
};
@@ -1481,7 +1481,7 @@
* them to pass */
adreno_ringbuffer_restore(rb, rec_data->bad_rb_buffer,
rec_data->bad_rb_size);
- idle_ret = adreno_idle(device, KGSL_TIMEOUT_DEFAULT);
+ idle_ret = adreno_idle(device);
if (idle_ret) {
ret = adreno_stop(device);
if (ret) {
@@ -1524,7 +1524,7 @@
if (ret || !rec_data->bad_rb_size) {
adreno_ringbuffer_restore(rb, rec_data->rb_buffer,
rec_data->rb_size);
- ret = adreno_idle(device, KGSL_TIMEOUT_DEFAULT);
+ ret = adreno_idle(device);
if (ret) {
/* If we fail here we can try to invalidate another
* context and try recovering again */
@@ -1806,61 +1806,74 @@
adreno_regwrite(device, REG_CP_RB_WPTR, adreno_dev->ringbuffer.wptr);
}
-/* Caller must hold the device mutex. */
-int adreno_idle(struct kgsl_device *device, unsigned int timeout)
+static int adreno_ringbuffer_drain(struct kgsl_device *device,
+ unsigned int *regs)
{
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
+ unsigned long wait;
+ unsigned long timeout = jiffies + msecs_to_jiffies(ADRENO_IDLE_TIMEOUT);
+
+ if (!(rb->flags & KGSL_FLAGS_STARTED))
+ return 0;
+
+ /*
+ * The first time into the loop, wait for 100 msecs and kick wptr again
+ * to ensure that the hardware has updated correctly. After that, kick
+ * it periodically every KGSL_TIMEOUT_PART msecs until the timeout
+ * expires
+ */
+
+ wait = jiffies + msecs_to_jiffies(100);
+
+ adreno_poke(device);
+
+ do {
+ if (time_after(jiffies, wait)) {
+ adreno_poke(device);
+
+ /* Check to see if the core is hung */
+ if (adreno_hang_detect(device, regs))
+ return -ETIMEDOUT;
+
+ wait = jiffies + msecs_to_jiffies(KGSL_TIMEOUT_PART);
+ }
+ GSL_RB_GET_READPTR(rb, &rb->rptr);
+
+ if (time_after(jiffies, timeout)) {
+ KGSL_DRV_ERR(device, "rptr: %x, wptr: %x\n",
+ rb->rptr, rb->wptr);
+ return -ETIMEDOUT;
+ }
+ } while (rb->rptr != rb->wptr);
+
+ return 0;
+}
+
+/* Caller must hold the device mutex. */
+int adreno_idle(struct kgsl_device *device)
+{
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
unsigned int rbbm_status;
- unsigned long wait_timeout =
- msecs_to_jiffies(adreno_dev->wait_timeout);
unsigned long wait_time;
unsigned long wait_time_part;
- unsigned int msecs;
- unsigned int msecs_first;
- unsigned int msecs_part = KGSL_TIMEOUT_PART;
unsigned int prev_reg_val[hang_detect_regs_count];
memset(prev_reg_val, 0, sizeof(prev_reg_val));
- /* Restrict timeout value between adreno_dev->wait_timeout and 0 */
- if ((timeout == 0) || (timeout > adreno_dev->wait_timeout))
- msecs = adreno_dev->wait_timeout;
- else
- msecs = timeout;
-
kgsl_cffdump_regpoll(device->id,
adreno_dev->gpudev->reg_rbbm_status << 2,
0x00000000, 0x80000000);
- /* first, wait until the CP has consumed all the commands in
- * the ring buffer
- */
+
retry:
- if (rb->flags & KGSL_FLAGS_STARTED) {
- msecs_first = (msecs <= 100) ? ((msecs + 4) / 5) : 100;
- wait_time = jiffies + wait_timeout;
- wait_time_part = jiffies + msecs_to_jiffies(msecs_first);
- adreno_poke(device);
- do {
- if (time_after(jiffies, wait_time_part)) {
- adreno_poke(device);
- wait_time_part = jiffies +
- msecs_to_jiffies(msecs_part);
- if ((adreno_hang_detect(device, prev_reg_val)))
- goto err;
- }
- GSL_RB_GET_READPTR(rb, &rb->rptr);
- if (time_after(jiffies, wait_time)) {
- KGSL_DRV_ERR(device, "rptr: %x, wptr: %x\n",
- rb->rptr, rb->wptr);
- goto err;
- }
- } while (rb->rptr != rb->wptr);
- }
+ /* First, wait for the ringbuffer to drain */
+ if (adreno_ringbuffer_drain(device, prev_reg_val))
+ goto err;
/* now, wait for the GPU to finish its operations */
- wait_time = jiffies + wait_timeout;
- wait_time_part = jiffies + msecs_to_jiffies(msecs_part);
+ wait_time = jiffies + ADRENO_IDLE_TIMEOUT;
+ wait_time_part = jiffies + msecs_to_jiffies(KGSL_TIMEOUT_PART);
+
while (time_before(jiffies, wait_time)) {
adreno_regread(device, adreno_dev->gpudev->reg_rbbm_status,
&rbbm_status);
@@ -1876,7 +1889,7 @@
*/
if (time_after(jiffies, wait_time_part)) {
wait_time_part = jiffies +
- msecs_to_jiffies(msecs_part);
+ msecs_to_jiffies(KGSL_TIMEOUT_PART);
if ((adreno_hang_detect(device, prev_reg_val)))
goto err;
}
@@ -1887,7 +1900,7 @@
KGSL_DRV_ERR(device, "spun too long waiting for RB to idle\n");
if (KGSL_STATE_DUMP_AND_RECOVER != device->state &&
!adreno_dump_and_recover(device)) {
- wait_time = jiffies + wait_timeout;
+ wait_time = jiffies + ADRENO_IDLE_TIMEOUT;
goto retry;
}
return -ETIMEDOUT;
@@ -1934,7 +1947,7 @@
/* switch to NULL ctxt */
if (adreno_dev->drawctxt_active != NULL) {
adreno_drawctxt_switch(adreno_dev, NULL, 0);
- status = adreno_idle(device, KGSL_TIMEOUT_DEFAULT);
+ status = adreno_idle(device);
}
return status;
@@ -2184,12 +2197,11 @@
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
int retries = 0;
- unsigned int msecs_first;
- unsigned int msecs_part = KGSL_TIMEOUT_PART;
unsigned int ts_issued;
unsigned int context_id = _get_context_id(context);
unsigned int time_elapsed = 0;
unsigned int prev_reg_val[hang_detect_regs_count];
+ unsigned int wait;
memset(prev_reg_val, 0, sizeof(prev_reg_val));
@@ -2207,11 +2219,18 @@
goto done;
}
- /* Keep the first timeout as 100msecs before rewriting
- * the WPTR. Less visible impact if the WPTR has not
- * been updated properly.
+ /*
+ * Make the first timeout interval 100 msecs and then try to kick the
+ * wptr again. This helps to ensure the wptr is updated properly. If
+ * the requested timeout is less than 100 msecs, then wait 20msecs which
+ * is the minimum amount of time we can safely wait at 100HZ
*/
- msecs_first = (msecs <= 100) ? ((msecs + 4) / 5) : 100;
+
+ if (msecs == 0 || msecs >= 100)
+ wait = 100;
+ else
+ wait = 20;
+
do {
/*
* If the context ID is invalid, we are in a race with
@@ -2250,8 +2269,8 @@
device->wait_queue,
kgsl_check_interrupt_timestamp(device,
context, timestamp),
- msecs_to_jiffies(retries ?
- msecs_part : msecs_first), io);
+ msecs_to_jiffies(wait), io);
+
mutex_lock(&device->mutex);
if (status > 0) {
@@ -2264,11 +2283,12 @@
}
/*this wait timed out*/
- time_elapsed = time_elapsed +
- (retries ? msecs_part : msecs_first);
+ time_elapsed += wait;
+ wait = KGSL_TIMEOUT_PART;
+
retries++;
- } while (time_elapsed < msecs);
+ } while (!msecs || time_elapsed < msecs);
hang_dump:
/*
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index b923049e..26d5eaa 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -55,6 +55,12 @@
#define ADRENO_NUM_CTX_SWITCH_ALLOWED_BEFORE_DRAW 50
+/* One cannot wait forever for the core to idle, so set an upper limit to the
+ * amount of time to wait for the core to go idle
+ */
+
+#define ADRENO_IDLE_TIMEOUT (20 * 1000)
+
enum adreno_gpurev {
ADRENO_REV_UNKNOWN = 0,
ADRENO_REV_A200 = 200,
@@ -162,7 +168,7 @@
extern const unsigned int hang_detect_regs_count;
-int adreno_idle(struct kgsl_device *device, unsigned int timeout);
+int adreno_idle(struct kgsl_device *device);
void adreno_regread(struct kgsl_device *device, unsigned int offsetwords,
unsigned int *value);
void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords,
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 2dbfd8f..205c9ff 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2290,9 +2290,6 @@
build_quad_vtxbuff(drawctxt, &drawctxt->context_gmem_shadow,
&tmp_ctx.cmd);
- /* Dow we need to idle? */
- /* adreno_idle(&adreno_dev->dev, KGSL_TIMEOUT_DEFAULT); */
-
tmp_ctx.cmd = build_gmem2sys_cmds(adreno_dev, drawctxt,
&drawctxt->context_gmem_shadow);
tmp_ctx.cmd = build_sys2gmem_cmds(adreno_dev, drawctxt,
diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c
index 6c74dfa..bd22233 100644
--- a/drivers/gpu/msm/adreno_drawctxt.c
+++ b/drivers/gpu/msm/adreno_drawctxt.c
@@ -224,7 +224,7 @@
adreno_drawctxt_switch(adreno_dev, NULL, 0);
}
- adreno_idle(device, KGSL_TIMEOUT_DEFAULT);
+ adreno_idle(device);
kgsl_sharedmem_free(&drawctxt->gpustate);
kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow);
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index ca9e335..ad9007f 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -52,11 +52,9 @@
unsigned int freecmds;
unsigned int *cmds;
uint cmds_gpu;
- struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device);
- unsigned long wait_timeout = msecs_to_jiffies(adreno_dev->wait_timeout);
unsigned long wait_time;
+ unsigned long wait_timeout = msecs_to_jiffies(ADRENO_IDLE_TIMEOUT);
unsigned long wait_time_part;
- unsigned int msecs_part = KGSL_TIMEOUT_PART;
unsigned int prev_reg_val[hang_detect_regs_count];
memset(prev_reg_val, 0, sizeof(prev_reg_val));
@@ -87,7 +85,7 @@
}
wait_time = jiffies + wait_timeout;
- wait_time_part = jiffies + msecs_to_jiffies(msecs_part);
+ wait_time_part = jiffies + msecs_to_jiffies(KGSL_TIMEOUT_PART);
/* wait for space in ringbuffer */
while (1) {
GSL_RB_GET_READPTR(rb, &rb->rptr);
@@ -101,7 +99,7 @@
*/
if (time_after(jiffies, wait_time_part)) {
wait_time_part = jiffies +
- msecs_to_jiffies(msecs_part);
+ msecs_to_jiffies(KGSL_TIMEOUT_PART);
if ((adreno_hang_detect(rb->device,
prev_reg_val))){
KGSL_DRV_ERR(rb->device,
@@ -393,7 +391,7 @@
adreno_dev->gpudev->rb_init(adreno_dev, rb);
/* idle device to validate ME INIT */
- status = adreno_idle(device, KGSL_TIMEOUT_DEFAULT);
+ status = adreno_idle(device);
if (status == 0)
rb->flags |= KGSL_FLAGS_STARTED;
@@ -961,7 +959,7 @@
* this is conservative but works reliably and is ok
* even for performance simulations
*/
- adreno_idle(device, KGSL_TIMEOUT_DEFAULT);
+ adreno_idle(device);
#endif
/* If context hung and recovered then return error so that the
* application may handle it */
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 3d83508..e7a1c13 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -559,7 +559,7 @@
break;
case KGSL_STATE_ACTIVE:
/* Wait for the device to become idle */
- device->ftbl->idle(device, KGSL_TIMEOUT_DEFAULT);
+ device->ftbl->idle(device);
case KGSL_STATE_NAP:
case KGSL_STATE_SLEEP:
/* Get the completion ready to be waited upon. */
@@ -2605,7 +2605,7 @@
}
if (device->state == KGSL_STATE_ACTIVE)
- kgsl_idle(device, KGSL_TIMEOUT_DEFAULT);
+ kgsl_idle(device);
}
KGSL_LOG_DUMP(device, "|%s| Dump Started\n", device->name);
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index d0932ef..2a2e916 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -67,7 +67,7 @@
unsigned int offsetwords, unsigned int *value);
void (*regwrite) (struct kgsl_device *device,
unsigned int offsetwords, unsigned int value);
- int (*idle) (struct kgsl_device *device, unsigned int timeout);
+ int (*idle) (struct kgsl_device *device);
unsigned int (*isidle) (struct kgsl_device *device);
int (*suspend_context) (struct kgsl_device *device);
int (*start) (struct kgsl_device *device, unsigned int init_ram);
@@ -287,9 +287,9 @@
device->ftbl->regwrite(device, offsetwords, value);
}
-static inline int kgsl_idle(struct kgsl_device *device, unsigned int timeout)
+static inline int kgsl_idle(struct kgsl_device *device)
{
- return device->ftbl->idle(device, timeout);
+ return device->ftbl->idle(device);
}
static inline unsigned int kgsl_gpuid(struct kgsl_device *device,
diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c
index d8472f2..8cf00ea 100644
--- a/drivers/gpu/msm/kgsl_gpummu.c
+++ b/drivers/gpu/msm/kgsl_gpummu.c
@@ -472,7 +472,7 @@
return;
if (flags & KGSL_MMUFLAGS_PTUPDATE) {
- kgsl_idle(mmu->device, KGSL_TIMEOUT_DEFAULT);
+ kgsl_idle(mmu->device);
gpummu_pt = mmu->hwpagetable->priv;
kgsl_regwrite(mmu->device, MH_MMU_PT_BASE,
gpummu_pt->base.gpuaddr);
@@ -552,7 +552,7 @@
kgsl_regwrite(device, MH_MMU_CONFIG, mmu->config);
/* idle device */
- kgsl_idle(device, KGSL_TIMEOUT_DEFAULT);
+ kgsl_idle(device);
/* enable axi interrupts */
kgsl_regwrite(device, MH_INTERRUPT_MASK,
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index e858651..1eb671f 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -966,7 +966,7 @@
/* Mask off the lsb of the pt base address since lsb will not change */
pt_base &= (KGSL_IOMMU_TTBR0_PA_MASK << KGSL_IOMMU_TTBR0_PA_SHIFT);
if (flags & KGSL_MMUFLAGS_PTUPDATE) {
- kgsl_idle(mmu->device, KGSL_TIMEOUT_DEFAULT);
+ kgsl_idle(mmu->device);
for (i = 0; i < iommu->unit_count; i++) {
/* get the lsb value which should not change when
* changing ttbr0 */
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 8e6c5c0..0426339 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -560,7 +560,7 @@
struct kgsl_mh *mh = &device->mh;
/* force mmu off to for now*/
kgsl_regwrite(device, MH_MMU_CONFIG, 0);
- kgsl_idle(device, KGSL_TIMEOUT_DEFAULT);
+ kgsl_idle(device);
/* define physical memory range accessible by the core */
kgsl_regwrite(device, MH_MMU_MPU_BASE, mh->mpu_base);
@@ -824,3 +824,13 @@
kgsl_mmu_type = KGSL_MMU_TYPE_NONE;
}
EXPORT_SYMBOL(kgsl_mmu_set_mmutype);
+
+int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr)
+{
+ if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type)
+ return 1;
+ return ((gpuaddr >= KGSL_PAGETABLE_BASE) &&
+ (gpuaddr < (KGSL_PAGETABLE_BASE + kgsl_mmu_get_ptsize())));
+}
+EXPORT_SYMBOL(kgsl_mmu_gpuaddr_in_range);
+
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 5293d66..8221b80 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -205,6 +205,7 @@
void kgsl_mmu_set_mmutype(char *mmutype);
enum kgsl_mmutype kgsl_mmu_get_mmutype(void);
unsigned int kgsl_mmu_get_ptsize(void);
+int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr);
/*
* Static inline functions of MMU that simply call the SMMU specific
@@ -293,12 +294,6 @@
mmu->mmu_ops->mmu_disable_clk_on_ts(mmu, ts, ts_valid);
}
-static inline int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr)
-{
- return ((gpuaddr >= KGSL_PAGETABLE_BASE) &&
- (gpuaddr < (KGSL_PAGETABLE_BASE + kgsl_mmu_get_ptsize())));
-}
-
static inline unsigned int kgsl_mmu_get_int_mask(void)
{
/* Dont enable gpummu interrupts, if iommu is enabled */
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 4b5021d..e4d7141 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -80,8 +80,8 @@
* Idle the gpu core before changing the clock freq.
*/
if (pwr->idle_needed == true)
- device->ftbl->idle(device,
- KGSL_TIMEOUT_DEFAULT);
+ device->ftbl->idle(device);
+
/* Don't shift by more than one level at a time to
* avoid glitches.
*/
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 9037f3c..8ddc991 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -358,7 +358,7 @@
return ts_diff < Z180_PACKET_COUNT;
}
-static int z180_idle(struct kgsl_device *device, unsigned int timeout)
+static int z180_idle(struct kgsl_device *device)
{
int status = 0;
struct z180_device *z180_dev = Z180_DEVICE(device);
@@ -366,7 +366,8 @@
if (timestamp_cmp(z180_dev->current_timestamp,
z180_dev->timestamp) > 0)
status = z180_wait(device, NULL,
- z180_dev->current_timestamp, timeout);
+ z180_dev->current_timestamp,
+ Z180_IDLE_TIMEOUT);
if (status)
KGSL_DRV_ERR(device, "z180_waittimestamp() timed out\n");
@@ -583,7 +584,7 @@
static int z180_stop(struct kgsl_device *device)
{
device->ftbl->irqctrl(device, 0);
- z180_idle(device, KGSL_TIMEOUT_DEFAULT);
+ z180_idle(device);
del_timer_sync(&device->idle_timer);
@@ -852,7 +853,7 @@
{
struct z180_device *z180_dev = Z180_DEVICE(device);
- z180_idle(device, KGSL_TIMEOUT_DEFAULT);
+ z180_idle(device);
if (z180_dev->ringbuffer.prevctx == context->id) {
z180_dev->ringbuffer.prevctx = Z180_INVALID_CONTEXT;
diff --git a/drivers/gpu/msm/z180.h b/drivers/gpu/msm/z180.h
index 6e81a9d..a8973d2 100644
--- a/drivers/gpu/msm/z180.h
+++ b/drivers/gpu/msm/z180.h
@@ -28,6 +28,9 @@
#define Z180_DEFAULT_PWRSCALE_POLICY NULL
+/* Wait a maximum of 10 seconds when trying to idle the core */
+#define Z180_IDLE_TIMEOUT (10 * 1000)
+
struct z180_ringbuffer {
unsigned int prevctx;
struct kgsl_memdesc cmdbufdesc;
diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index 297afa7..c1617bff 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -1339,8 +1339,10 @@
}
free_irq(dev->err_irq, dev);
} else {
- if (dev->dev->of_node)
+ if (dev->dev->of_node) {
+ dev->adapter.dev.of_node = pdev->dev.of_node;
of_i2c_register_devices(&dev->adapter);
+ }
return 0;
}
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 1c70527..49a081e 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -36,7 +36,9 @@
/* Family ID */
#define MXT224_ID 0x80
#define MXT224E_ID 0x81
+#define MXT336S_ID 0x82
#define MXT1386_ID 0xA0
+#define MXT1664S_ID 0xA2
/* Version */
#define MXT_VER_20 20
@@ -94,6 +96,7 @@
#define MXT_TOUCH_PROXKEY_T52 52
#define MXT_PROCI_GRIPFACE_T20 20
#define MXT_PROCG_NOISE_T22 22
+#define MXT_PROCG_NOISE_T62 62
#define MXT_PROCI_ONETOUCH_T24 24
#define MXT_PROCI_TWOTOUCH_T27 27
#define MXT_PROCI_GRIP_T40 40
@@ -102,6 +105,7 @@
#define MXT_PROCI_STYLUS_T47 47
#define MXT_PROCI_ADAPTIVETHRESHOLD_T55 55
#define MXT_PROCI_SHIELDLESS_T56 56
+#define MXT_PROCI_EXTRATSDATA_T57 57
#define MXT_PROCG_NOISESUPPRESSION_T48 48
#define MXT_SPT_COMMSCONFIG_T18 18
#define MXT_SPT_GPIOPWM_T19 19
@@ -111,6 +115,7 @@
#define MXT_SPT_DIGITIZER_T43 43
#define MXT_SPT_MESSAGECOUNT_T44 44
#define MXT_SPT_CTECONFIG_T46 46
+#define MXT_SPT_TIMER_T61 61
/* MXT_GEN_COMMAND_T6 field */
#define MXT_COMMAND_RESET 0
@@ -231,6 +236,8 @@
#define MXT224_RESET_TIME 65 /* msec */
#define MXT224E_RESET_TIME 150 /* msec */
#define MXT1386_RESET_TIME 250 /* msec */
+#define MXT336S_RESET_TIME 25 /* msec */
+#define MXT1664S_RESET_TIME 65 /* msec */
#define MXT_RESET_TIME 250 /* msec */
#define MXT_RESET_NOCHGREAD 400 /* msec */
@@ -372,6 +379,7 @@
case MXT_TOUCH_PROXKEY_T52:
case MXT_PROCI_GRIPFACE_T20:
case MXT_PROCG_NOISE_T22:
+ case MXT_PROCG_NOISE_T62:
case MXT_PROCI_ONETOUCH_T24:
case MXT_PROCI_TWOTOUCH_T27:
case MXT_PROCI_GRIP_T40:
@@ -379,6 +387,7 @@
case MXT_PROCI_TOUCHSUPPRESSION_T42:
case MXT_PROCI_STYLUS_T47:
case MXT_PROCI_SHIELDLESS_T56:
+ case MXT_PROCI_EXTRATSDATA_T57:
case MXT_PROCG_NOISESUPPRESSION_T48:
case MXT_SPT_COMMSCONFIG_T18:
case MXT_SPT_GPIOPWM_T19:
@@ -387,6 +396,7 @@
case MXT_SPT_USERDATA_T38:
case MXT_SPT_DIGITIZER_T43:
case MXT_SPT_CTECONFIG_T46:
+ case MXT_SPT_TIMER_T61:
case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
return true;
default:
@@ -406,6 +416,7 @@
case MXT_TOUCH_PROXKEY_T52:
case MXT_PROCI_GRIPFACE_T20:
case MXT_PROCG_NOISE_T22:
+ case MXT_PROCG_NOISE_T62:
case MXT_PROCI_ONETOUCH_T24:
case MXT_PROCI_TWOTOUCH_T27:
case MXT_PROCI_GRIP_T40:
@@ -413,6 +424,7 @@
case MXT_PROCI_TOUCHSUPPRESSION_T42:
case MXT_PROCI_STYLUS_T47:
case MXT_PROCI_SHIELDLESS_T56:
+ case MXT_PROCI_EXTRATSDATA_T57:
case MXT_PROCG_NOISESUPPRESSION_T48:
case MXT_SPT_COMMSCONFIG_T18:
case MXT_SPT_GPIOPWM_T19:
@@ -421,6 +433,7 @@
case MXT_SPT_USERDATA_T38:
case MXT_SPT_DIGITIZER_T43:
case MXT_SPT_CTECONFIG_T46:
+ case MXT_SPT_TIMER_T61:
case MXT_PROCI_ADAPTIVETHRESHOLD_T55:
return true;
default:
@@ -1293,8 +1306,12 @@
case MXT224E_ID:
msleep(MXT224E_RESET_TIME);
break;
+ case MXT336S_ID:
+ msleep(MXT336S_RESET_TIME);
case MXT1386_ID:
msleep(MXT1386_RESET_TIME);
+ case MXT1664S_ID:
+ msleep(MXT1664S_RESET_TIME);
break;
default:
msleep(MXT_RESET_TIME);
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
index 372c612..c1d1462 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
@@ -65,6 +65,11 @@
/* Channel timeout in msec */
#define TSPP_CHANNEL_TIMEOUT 16
+/* module parameters for load time configuration */
+static int tsif0_mode = TSPP_TSIF_MODE_2;
+static int tsif1_mode = TSPP_TSIF_MODE_2;
+module_param(tsif0_mode, int, S_IRUGO);
+module_param(tsif1_mode, int, S_IRUGO);
/*
* Work scheduled each time TSPP notifies dmx
@@ -273,14 +278,17 @@
int ret;
int channel_id;
int *channel_ref_count;
+ enum tspp_tsif_mode mode;
/* determine the TSIF we are reading from */
if (mpq_demux->source == DMX_SOURCE_FRONT0) {
tsif = 0;
tspp_source = TSPP_SOURCE_TSIF0;
+ mode = (enum tspp_tsif_mode)tsif0_mode;
} else if (mpq_demux->source == DMX_SOURCE_FRONT1) {
tsif = 1;
tspp_source = TSPP_SOURCE_TSIF1;
+ mode = (enum tspp_tsif_mode)tsif1_mode;
} else {
/* invalid source */
MPQ_DVB_ERR_PRINT(
@@ -333,7 +341,7 @@
}
/* set TSPP source */
- ret = tspp_open_stream(0, channel_id, tspp_source);
+ ret = tspp_open_stream(0, channel_id, tspp_source, mode);
if (ret < 0) {
MPQ_DVB_ERR_PRINT(
"%s: tspp_select_source(%d,%d) failed (%d)\n",
diff --git a/drivers/media/video/msm/eeprom/msm_camera_eeprom.c b/drivers/media/video/msm/eeprom/msm_camera_eeprom.c
index 96a6e04..effae8b 100644
--- a/drivers/media/video/msm/eeprom/msm_camera_eeprom.c
+++ b/drivers/media/video/msm/eeprom/msm_camera_eeprom.c
@@ -100,7 +100,7 @@
}
rc = e_ctrl->func_tbl.eeprom_get_info(e_ctrl,
&cdata.cfg.get_info);
-
+ cdata.is_eeprom_supported = 1;
if (copy_to_user((void *)argp,
&cdata,
sizeof(struct msm_eeprom_cfg_data)))
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index b7f6b08..d876f12 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -341,7 +341,6 @@
case MSM_CAM_IOCTL_EEPROM_IO_CFG: {
struct msm_eeprom_cfg_data eeprom_data;
if (p_mctl->eeprom_sdev) {
- eeprom_data.is_eeprom_supported = 1;
rc = v4l2_subdev_call(p_mctl->eeprom_sdev,
core, ioctl, VIDIOC_MSM_EEPROM_CFG, argp);
} else {
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index 7d58091..0919799 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -1542,7 +1542,6 @@
case NOTIFY_VFE_MSG_STATS:
case NOTIFY_VFE_MSG_COMP_STATS:
case NOTIFY_VFE_CAMIF_ERROR:
- case NOTIFY_VFE_IRQ:
default:
interface = PIX_0;
break;
@@ -1593,11 +1592,10 @@
case NOTIFY_VFE_IRQ:{
struct msm_vfe_cfg_cmd cfg_cmd;
struct msm_camvfe_params vfe_params;
- p_mctl = msm_cam_server_get_mctl(mctl_handle);
cfg_cmd.cmd_type = CMD_VFE_PROCESS_IRQ;
vfe_params.vfe_cfg = &cfg_cmd;
vfe_params.data = arg;
- rc = v4l2_subdev_call(p_mctl->isp_sdev->sd,
+ rc = v4l2_subdev_call(sd,
core, ioctl, 0, &vfe_params);
}
break;
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.c b/drivers/media/video/msm/vfe/msm_vfe32.c
index 3e01437..c8d22d4 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.c
+++ b/drivers/media/video/msm/vfe/msm_vfe32.c
@@ -4359,7 +4359,7 @@
VFE_IRQ_STATUS0_CAMIF_SOF_MASK) {
if (stat_interrupt)
vfe32_ctrl->simultaneous_sof_stat = 1;
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_CAMIF_SOF_MASK);
}
@@ -4367,25 +4367,25 @@
/* interrupt to be processed, *qcmd has the payload. */
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_REG_UPDATE_MASK)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_REG_UPDATE_MASK);
if (qcmd->vfeInterruptStatus1 &
VFE_IRQ_STATUS1_RDI0_REG_UPDATE_MASK)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS1_RDI0_REG_UPDATE);
if (qcmd->vfeInterruptStatus1 &
VFE_IRQ_STATUS1_RDI1_REG_UPDATE_MASK)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS1_RDI1_REG_UPDATE);
if (qcmd->vfeInterruptStatus1 &
VFE_IMASK_WHILE_STOPPING_1)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IMASK_WHILE_STOPPING_1);
@@ -4410,7 +4410,7 @@
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_STATS_COMPOSIT_MASK) {
CDBG("Stats composite irq occured.\n");
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)qcmd->vfeInterruptStatus0);
}
@@ -4418,60 +4418,60 @@
/* process individual stats interrupt. */
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_STATS_AEC_BG)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_STATS_AEC_BG);
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_STATS_AWB)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_STATS_AWB);
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_STATS_AF_BF)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_STATS_AF_BF);
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_STATS_SK_BHIST)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_STATS_SK_BHIST);
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_STATS_IHIST)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_STATS_IHIST);
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_STATS_RS)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_STATS_RS);
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_STATS_CS)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_STATS_CS);
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_SYNC_TIMER0)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_SYNC_TIMER0);
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_SYNC_TIMER1)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_SYNC_TIMER1);
if (qcmd->vfeInterruptStatus0 &
VFE_IRQ_STATUS0_SYNC_TIMER2)
- v4l2_subdev_notify(&axi_ctrl->subdev,
+ v4l2_subdev_notify(&vfe32_ctrl->subdev,
NOTIFY_VFE_IRQ,
(void *)VFE_IRQ_STATUS0_SYNC_TIMER2);
}
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index c87211a..d47bdb0 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -648,6 +648,11 @@
pr_err("Failed to set scratch buffers: %d\n", rc);
goto fail_start;
}
+ rc = msm_comm_set_persist_buffers(inst);
+ if (rc) {
+ pr_err("Failed to set persist buffers: %d\n", rc);
+ goto fail_start;
+ }
rc = msm_comm_try_state(inst, MSM_VIDC_START_DONE);
if (rc) {
pr_err("Failed to move inst: %p to start done state\n",
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index 14baf79..282da64 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -621,11 +621,21 @@
unsigned long flags;
struct vb2_buf_entry *temp;
struct list_head *ptr, *next;
+ rc = msm_comm_try_get_bufreqs(inst);
+ if (rc) {
+ pr_err("Failed to get Buffer Requirements : %d\n", rc);
+ goto fail_start;
+ }
rc = msm_comm_set_scratch_buffers(inst);
if (rc) {
pr_err("Failed to set scratch buffers: %d\n", rc);
goto fail_start;
}
+ rc = msm_comm_set_persist_buffers(inst);
+ if (rc) {
+ pr_err("Failed to set persist buffers: %d\n", rc);
+ goto fail_start;
+ }
rc = msm_comm_try_state(inst, MSM_VIDC_START_DONE);
if (rc) {
pr_err("Failed to move inst: %p to start done state\n",
@@ -752,7 +762,12 @@
void *pdata;
struct msm_vidc_inst *inst = container_of(ctrl->handler,
struct msm_vidc_inst, ctrl_handler);
-
+ rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
+ if (rc) {
+ pr_err("Failed to move inst: %p to start done state\n",
+ inst);
+ goto failed_open_done;
+ }
control.id = ctrl->id;
control.value = ctrl->val;
@@ -1172,6 +1187,7 @@
}
if (rc)
pr_err("Failed to set hal property for framesize\n");
+failed_open_done:
return rc;
}
static int msm_venc_op_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/video/msm_vidc/msm_vidc.c
index 4d4cec5..72f30ea 100644
--- a/drivers/media/video/msm_vidc/msm_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_vidc.c
@@ -243,6 +243,7 @@
inst->session_type = session_type;
INIT_LIST_HEAD(&inst->pendingq);
INIT_LIST_HEAD(&inst->internalbufs);
+ INIT_LIST_HEAD(&inst->persistbufs);
inst->state = MSM_VIDC_CORE_UNINIT_DONE;
inst->core = core;
for (i = SESSION_MSG_INDEX(SESSION_MSG_START);
@@ -316,6 +317,15 @@
kfree(buf);
}
}
+ if (!list_empty(&inst->persistbufs)) {
+ list_for_each_safe(ptr, next, &inst->persistbufs) {
+ buf = list_entry(ptr, struct internal_buf,
+ list);
+ list_del(&buf->list);
+ msm_smem_free(inst->mem_client, buf->handle);
+ kfree(buf);
+ }
+ }
if (inst->extradata_handle)
msm_smem_free(inst->mem_client, inst->extradata_handle);
spin_unlock_irqrestore(&inst->lock, flags);
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index b07c63b..763477a 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -1549,3 +1549,62 @@
err_no_mem:
return rc;
}
+
+int msm_comm_set_persist_buffers(struct msm_vidc_inst *inst)
+{
+ int rc = 0;
+ struct msm_smem *handle;
+ struct internal_buf *binfo;
+ struct vidc_buffer_addr_info buffer_info;
+ unsigned long flags;
+ struct hal_buffer_requirements *persist_buf =
+ &inst->buff_req.buffer[HAL_BUFFER_INTERNAL_PERSIST];
+ int i;
+ pr_debug("persist: num = %d, size = %d\n",
+ persist_buf->buffer_count_actual,
+ persist_buf->buffer_size);
+ if (!list_empty(&inst->persistbufs)) {
+ pr_err("Persist buffers already allocated\n");
+ return rc;
+ }
+
+ if (persist_buf->buffer_size) {
+ for (i = 0; i < persist_buf->buffer_count_actual; i++) {
+ handle = msm_smem_alloc(inst->mem_client,
+ persist_buf->buffer_size, 1, 0,
+ inst->core->resources.io_map[NS_MAP].domain, 0);
+ if (!handle) {
+ pr_err("Failed to allocate persist memory\n");
+ rc = -ENOMEM;
+ goto err_no_mem;
+ }
+ binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
+ if (!binfo) {
+ pr_err("Out of memory\n");
+ rc = -ENOMEM;
+ goto fail_kzalloc;
+ }
+ binfo->handle = handle;
+ buffer_info.buffer_size = persist_buf->buffer_size;
+ buffer_info.buffer_type = HAL_BUFFER_INTERNAL_PERSIST;
+ buffer_info.num_buffers = 1;
+ buffer_info.align_device_addr = handle->device_addr;
+ rc = vidc_hal_session_set_buffers(
+ (void *) inst->session, &buffer_info);
+ if (rc) {
+ pr_err("vidc_hal_session_set_buffers failed");
+ goto fail_set_buffers;
+ }
+ spin_lock_irqsave(&inst->lock, flags);
+ list_add_tail(&binfo->list, &inst->persistbufs);
+ spin_unlock_irqrestore(&inst->lock, flags);
+ }
+ }
+ return rc;
+fail_set_buffers:
+ kfree(binfo);
+fail_kzalloc:
+ msm_smem_free(inst->mem_client, handle);
+err_no_mem:
+ return rc;
+}
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.h b/drivers/media/video/msm_vidc/msm_vidc_common.h
index 2009ca6..9430d5f 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.h
@@ -28,6 +28,7 @@
int msm_comm_try_state(struct msm_vidc_inst *inst, int state);
int msm_comm_try_get_bufreqs(struct msm_vidc_inst *inst);
int msm_comm_set_scratch_buffers(struct msm_vidc_inst *inst);
+int msm_comm_set_persist_buffers(struct msm_vidc_inst *inst);
int msm_comm_qbuf(struct vb2_buffer *vb);
int msm_comm_scale_clocks(struct msm_vidc_core *core);
#define IS_PRIV_CTRL(idx) (\
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index 8c11de8..630f383 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -207,6 +207,7 @@
spinlock_t lock;
struct list_head pendingq;
struct list_head internalbufs;
+ struct list_head persistbufs;
struct buffer_requirements buff_req;
void *mem_client;
struct v4l2_ctrl_handler ctrl_handler;
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 304dc6b..4de5752 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -20,6 +20,7 @@
#include <linux/mfd/pm8xxx/pm8921-bms.h>
#include <linux/mfd/pm8xxx/core.h>
#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
+#include <linux/mfd/pm8xxx/pm8921-charger.h>
#include <linux/mfd/pm8xxx/ccadc.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
@@ -67,16 +68,6 @@
int last_good_ocv_uv;
};
-struct pm8921_rbatt_params {
- uint16_t ocv_for_rbatt_raw;
- uint16_t vsense_for_rbatt_raw;
- uint16_t vbatt_for_rbatt_raw;
-
- int ocv_for_rbatt_uv;
- int vsense_for_rbatt_uv;
- int vbatt_for_rbatt_uv;
-};
-
/**
* struct pm8921_bms_chip -
* @bms_output_lock: lock to prevent concurrent bms reads
@@ -92,8 +83,7 @@
struct device *dev;
struct dentry *dent;
unsigned int r_sense;
- unsigned int i_test;
- unsigned int v_failure;
+ unsigned int v_cutoff;
unsigned int fcc;
struct single_row_lut *fcc_temp_lut;
struct single_row_lut *fcc_sf_lut;
@@ -102,6 +92,8 @@
struct sf_lut *rbatt_sf_lut;
int delta_rbatt_mohm;
struct work_struct calib_hkadc_work;
+ struct delayed_work calib_hkadc_delayed_work;
+ struct mutex calib_mutex;
unsigned int revision;
unsigned int xoadc_v0625_usb_present;
unsigned int xoadc_v0625_usb_absent;
@@ -119,29 +111,36 @@
unsigned int charging_began;
unsigned int start_percent;
unsigned int end_percent;
+ int charge_time_us;
+ int catch_up_time_us;
enum battery_type batt_type;
uint16_t ocv_reading_at_100;
int cc_reading_at_100;
int max_voltage_uv;
- int batt_temp_suspend;
- int soc_rbatt_suspend;
int default_rbatt_mohm;
int amux_2_trim_delta;
uint16_t prev_last_good_ocv_raw;
unsigned int rconn_mohm;
struct mutex last_ocv_uv_mutex;
int last_ocv_uv;
+ int pon_ocv_uv;
int last_cc_uah;
struct timeval t;
- int last_uuc_uah;
int enable_fcc_learning;
int shutdown_soc;
- int timer_uuc_expired;
- struct delayed_work uuc_timer_work;
- int uuc_uah_iavg_prev;
+ int shutdown_soc_timer_expired;
+ struct delayed_work shutdown_soc_work;
+ struct delayed_work calculate_soc_delayed_work;
+ struct timespec t_soc_queried;
+ int shutdown_soc_valid_limit;
};
+/*
+ * protects against simultaneous adjustment of ocv based on shutdown soc and
+ * invalidating the shutdown soc
+ */
+static DEFINE_MUTEX(soc_invalidation_mutex);
static int shutdown_soc_invalid;
static struct pm8921_bms_chip *the_chip;
@@ -157,7 +156,7 @@
module_param(last_chargecycles, int, 0644);
module_param(last_charge_increase, int, 0644);
-static int last_rbatt = -EINVAL;
+static int calculated_soc = -EINVAL;
static int last_soc = -EINVAL;
static int last_real_fcc_mah = -EINVAL;
static int last_real_fcc_batt_temp = -EINVAL;
@@ -175,7 +174,6 @@
.get = param_get_int,
};
-module_param_cb(last_rbatt, &bms_param_ops, &last_rbatt, 0644);
module_param_cb(last_soc, &bms_param_ops, &last_soc, 0644);
/*
@@ -337,19 +335,13 @@
static int usb_chg_plugged_in(void)
{
- union power_supply_propval ret = {0,};
- static struct power_supply *psy;
+ int val = pm8921_is_usb_chg_plugged_in();
- if (psy == NULL) {
- psy = power_supply_get_by_name("usb");
- if (psy == NULL)
- return 0;
- }
+ /* treat as if usb is not present in case of error */
+ if (val == -EINVAL)
+ val = 0;
- if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &ret))
- return 0;
-
- return ret.intval;
+ return val;
}
#define HOLD_OREG_DATA BIT(1)
@@ -732,6 +724,82 @@
return 0;
}
+/* get ocv given a soc -- reverse lookup */
+static int interpolate_ocv(struct pm8921_bms_chip *chip,
+ int batt_temp_degc, int pc)
+{
+ int i, ocvrow1, ocvrow2, ocv;
+ int rows, cols;
+ int row1 = 0;
+ int row2 = 0;
+
+ rows = chip->pc_temp_ocv_lut->rows;
+ cols = chip->pc_temp_ocv_lut->cols;
+ if (pc > chip->pc_temp_ocv_lut->percent[0]) {
+ pr_debug("pc %d greater than known pc ranges for sfd\n", pc);
+ row1 = 0;
+ row2 = 0;
+ }
+ if (pc < chip->pc_temp_ocv_lut->percent[rows - 1]) {
+ pr_debug("pc %d less than known pc ranges for sf\n", pc);
+ row1 = rows - 1;
+ row2 = rows - 1;
+ }
+ for (i = 0; i < rows; i++) {
+ if (pc == chip->pc_temp_ocv_lut->percent[i]) {
+ row1 = i;
+ row2 = i;
+ break;
+ }
+ if (pc > chip->pc_temp_ocv_lut->percent[i]) {
+ row1 = i - 1;
+ row2 = i;
+ break;
+ }
+ }
+
+ if (batt_temp_degc < chip->pc_temp_ocv_lut->temp[0])
+ batt_temp_degc = chip->pc_temp_ocv_lut->temp[0];
+ if (batt_temp_degc > chip->pc_temp_ocv_lut->temp[cols - 1])
+ batt_temp_degc = chip->pc_temp_ocv_lut->temp[cols - 1];
+
+ for (i = 0; i < cols; i++)
+ if (batt_temp_degc <= chip->pc_temp_ocv_lut->temp[i])
+ break;
+ if (batt_temp_degc == chip->pc_temp_ocv_lut->temp[i]) {
+ ocv = linear_interpolate(
+ chip->pc_temp_ocv_lut->ocv[row1][i],
+ chip->pc_temp_ocv_lut->percent[row1],
+ chip->pc_temp_ocv_lut->ocv[row2][i],
+ chip->pc_temp_ocv_lut->percent[row2],
+ pc);
+ return ocv;
+ }
+
+ ocvrow1 = linear_interpolate(
+ chip->pc_temp_ocv_lut->ocv[row1][i - 1],
+ chip->pc_temp_ocv_lut->temp[i - 1],
+ chip->pc_temp_ocv_lut->ocv[row1][i],
+ chip->pc_temp_ocv_lut->temp[i],
+ batt_temp_degc);
+
+ ocvrow2 = linear_interpolate(
+ chip->pc_temp_ocv_lut->ocv[row2][i - 1],
+ chip->pc_temp_ocv_lut->temp[i - 1],
+ chip->pc_temp_ocv_lut->ocv[row2][i],
+ chip->pc_temp_ocv_lut->temp[i],
+ batt_temp_degc);
+
+ ocv = linear_interpolate(
+ ocvrow1,
+ chip->pc_temp_ocv_lut->percent[row1],
+ ocvrow2,
+ chip->pc_temp_ocv_lut->percent[row2],
+ pc);
+
+ return ocv;
+}
+
static int interpolate_pc(struct pm8921_bms_chip *chip,
int batt_temp, int ocv)
{
@@ -836,7 +904,7 @@
#define BMS_MODE_BIT BIT(6)
#define EN_VBAT_BIT BIT(5)
#define OVERRIDE_MODE_DELAY_MS 20
-int pm8921_bms_get_simultaneous_battery_voltage_and_current(int *ibat_ua,
+int override_mode_simultaneous_battery_voltage_and_current(int *ibat_ua,
int *vbat_uv)
{
int16_t vsense_raw;
@@ -844,11 +912,6 @@
int vsense_uv;
int usb_chg;
- if (the_chip == NULL) {
- pr_err("Called to early\n");
- return -EINVAL;
- }
-
mutex_lock(&the_chip->bms_output_lock);
pm8xxx_writeb(the_chip->dev->parent, BMS_S1_DELAY, 0x00);
@@ -880,42 +943,6 @@
*ibat_ua, *vbat_uv);
return 0;
}
-EXPORT_SYMBOL(pm8921_bms_get_simultaneous_battery_voltage_and_current);
-
-static int read_rbatt_params_raw(struct pm8921_bms_chip *chip,
- struct pm8921_rbatt_params *raw)
-{
- int usb_chg;
-
- mutex_lock(&chip->bms_output_lock);
- pm_bms_lock_output_data(chip);
-
- pm_bms_read_output_data(chip,
- OCV_FOR_RBATT, &raw->ocv_for_rbatt_raw);
- pm_bms_read_output_data(chip,
- VBATT_FOR_RBATT, &raw->vbatt_for_rbatt_raw);
- pm_bms_read_output_data(chip,
- VSENSE_FOR_RBATT, &raw->vsense_for_rbatt_raw);
-
- pm_bms_unlock_output_data(chip);
- mutex_unlock(&chip->bms_output_lock);
-
- usb_chg = usb_chg_plugged_in();
- convert_vbatt_raw_to_uv(chip, usb_chg,
- raw->vbatt_for_rbatt_raw, &raw->vbatt_for_rbatt_uv);
- convert_vbatt_raw_to_uv(chip, usb_chg,
- raw->ocv_for_rbatt_raw, &raw->ocv_for_rbatt_uv);
- convert_vsense_to_uv(chip, raw->vsense_for_rbatt_raw,
- &raw->vsense_for_rbatt_uv);
-
- pr_debug("vbatt_for_rbatt_raw = 0x%x, vbatt_for_rbatt= %duV\n",
- raw->vbatt_for_rbatt_raw, raw->vbatt_for_rbatt_uv);
- pr_debug("ocv_for_rbatt_raw = 0x%x, ocv_for_rbatt= %duV\n",
- raw->ocv_for_rbatt_raw, raw->ocv_for_rbatt_uv);
- pr_debug("vsense_for_rbatt_raw = 0x%x, vsense_for_rbatt= %duV\n",
- raw->vsense_for_rbatt_raw, raw->vsense_for_rbatt_uv);
- return 0;
-}
#define MBG_TRANSIENT_ERROR_RAW 51
static void adjust_pon_ocv_raw(struct pm8921_bms_chip *chip,
@@ -953,6 +980,7 @@
convert_vbatt_raw_to_uv(chip, usb_chg,
raw->last_good_ocv_raw, &raw->last_good_ocv_uv);
chip->last_ocv_uv = raw->last_good_ocv_uv;
+ pr_debug("PON_OCV_UV = %d\n", chip->last_ocv_uv);
} else if (chip->prev_last_good_ocv_raw != raw->last_good_ocv_raw) {
chip->prev_last_good_ocv_raw = raw->last_good_ocv_raw;
convert_vbatt_raw_to_uv(chip, usb_chg,
@@ -988,7 +1016,7 @@
{
int rbatt, scalefactor;
- rbatt = (last_rbatt < 0) ? chip->default_rbatt_mohm : last_rbatt;
+ rbatt = chip->default_rbatt_mohm;
pr_debug("rbatt before scaling = %d\n", rbatt);
if (chip->rbatt_sf_lut == NULL) {
pr_debug("RBATT = %d\n", rbatt);
@@ -1017,27 +1045,6 @@
return rbatt;
}
-static int calculate_rbatt_resume(struct pm8921_bms_chip *chip,
- struct pm8921_rbatt_params *raw)
-{
- unsigned int r_batt;
-
- if (raw->ocv_for_rbatt_uv <= 0
- || raw->ocv_for_rbatt_uv <= raw->vbatt_for_rbatt_uv
- || raw->vsense_for_rbatt_raw <= 0) {
- pr_debug("rbatt readings unavailable ocv = %d, vbatt = %d,"
- "vsen = %d\n",
- raw->ocv_for_rbatt_uv,
- raw->vbatt_for_rbatt_uv,
- raw->vsense_for_rbatt_raw);
- return -EINVAL;
- }
- r_batt = ((raw->ocv_for_rbatt_uv - raw->vbatt_for_rbatt_uv)
- * chip->r_sense) / raw->vsense_for_rbatt_uv;
- pr_debug("r_batt = %umilliOhms", r_batt);
- return r_batt;
-}
-
static int calculate_fcc_uah(struct pm8921_bms_chip *chip, int batt_temp,
int chargecycles)
{
@@ -1090,7 +1097,7 @@
return rc;
}
- rbatt = (last_rbatt < 0) ? chip->default_rbatt_mohm : last_rbatt;
+ rbatt = chip->default_rbatt_mohm;
*ocv = vbatt + (ibatt_ua * rbatt)/1000;
return 0;
}
@@ -1148,7 +1155,7 @@
int unusable_uv, pc_unusable, uuc;
/* calculate unusable charge with itest */
- unusable_uv = (rbatt * i_ma) + (chip->v_failure * 1000);
+ unusable_uv = (rbatt * i_ma) + (chip->v_cutoff * 1000);
pc_unusable = calculate_pc(chip, unusable_uv, batt_temp, chargecycles);
uuc = (fcc_uah * pc_unusable) / 100;
pr_debug("For i_ma = %d, unusable_uv = %d unusable_pc = %d uuc = %d\n",
@@ -1156,30 +1163,6 @@
return uuc;
}
-#define SOC_RBATT_CHG 70
-#define SOC_RBATT_DISCHG 20
-
-static int uuc_iavg_div = 150;
-module_param(uuc_iavg_div, int, 0644);
-
-static int uuc_min_step_size = 120;
-module_param(uuc_min_step_size, int, 0644);
-
-static int uuc_multiplier = 1000;
-module_param(uuc_multiplier, int, 0644);
-
-#define UUC_TIMER_MS 120000
-
-static void uuc_timer_work(struct work_struct *work)
-{
- struct pm8921_bms_chip *chip = container_of(work,
- struct pm8921_bms_chip, uuc_timer_work.work);
-
- pr_debug("UUC Timer expired\n");
- /* indicates the system is done with the high load during bootup */
- chip->timer_uuc_expired = 1;
-}
-
static void calculate_iavg_ua(struct pm8921_bms_chip *chip, int cc_uah,
int *iavg_ua, int *delta_time_us)
{
@@ -1212,114 +1195,63 @@
chip->t = now;
}
-#define UUC_IAVG_THRESHOLD_UAH 50000
-static int scale_unusable_charge_uah(struct pm8921_bms_chip *chip,
- bool charging, int uuc_uah_iavg, int uuc_uah_itest,
- int uuc_uah_iavg_prev)
-{
- int stepsize = 0;
- int delta_uuc = 0;
- int uuc_reported = 0;
-
- if (charging) {
- stepsize = max(uuc_min_step_size,
- uuc_multiplier * (SOC_RBATT_CHG - last_soc));
- /*
- * set the delta only if uuc is decreasing. If it has increased
- * simply report the last uuc since we don't want to report a
- * higher uuc as charging progresses
- */
- if (chip->last_uuc_uah > uuc_uah_iavg)
- delta_uuc = (chip->last_uuc_uah - uuc_uah_iavg)
- / stepsize;
- uuc_reported = chip->last_uuc_uah - delta_uuc;
- } else {
- stepsize = max(uuc_min_step_size,
- uuc_multiplier * (last_soc - SOC_RBATT_DISCHG));
- if (uuc_uah_itest > uuc_uah_iavg) {
- if ((uuc_uah_iavg > uuc_uah_iavg_prev
- + UUC_IAVG_THRESHOLD_UAH)
- && chip->timer_uuc_expired)
- /*
- * there is a big jump in iavg current way past
- * the bootup increase uuc to this high iavg
- * based uuc in steps
- */
- delta_uuc = (uuc_uah_iavg - uuc_uah_iavg_prev)
- / uuc_iavg_div;
- else
- /* increase uuc towards itest based uuc */
- delta_uuc = (uuc_uah_itest - uuc_uah_iavg)
- / stepsize;
- } else {
- /*
- * the iavg based uuc was higher than itest based
- * uuc. This means that iavg > itest. Itest represents
- * the max current drawn from the device at anytime.
- * If we find iavg > itest, ignore iavg and simply step
- * up the uuc based on itest
- */
- delta_uuc = uuc_uah_itest / stepsize;
- }
- uuc_reported = min(uuc_uah_itest,
- chip->last_uuc_uah + delta_uuc);
- }
- pr_debug("uuc_prev = %d stepsize = %d d_uuc = %d uuc_reported = %d\n",
- chip->last_uuc_uah, (int)stepsize, delta_uuc,
- uuc_reported);
- return uuc_reported;
-}
-
+#define IAVG_SAMPLES 16
+#define CHARGING_IAVG_MA 300
static int calculate_unusable_charge_uah(struct pm8921_bms_chip *chip,
int rbatt, int fcc_uah, int cc_uah,
int soc_rbatt, int batt_temp, int chargecycles,
- int iavg_ua)
+ int iavg_ua, int delta_time_us)
{
- int uuc_uah_itest, uuc_uah_iavg, uuc_reported;
- static int firsttime = 1;
+ int uuc_uah_iavg;
+ int i;
int iavg_ma = iavg_ua / 1000;
+ static int iavg_samples[IAVG_SAMPLES];
+ static int iavg_index;
+ static int iavg_num_samples;
- /* calculate unusable charge with itest */
- uuc_uah_itest = calculate_uuc_uah_at_given_current(chip,
- batt_temp, chargecycles,
- rbatt, fcc_uah, chip->i_test);
+ if (delta_time_us == 0) {
+ /*
+ * this means uuc is being for the first time,
+ * iavg_ua will be 0 which will lead to unreasonably low uuc
+ * hence use the instantenous current instead of iavg_ua
+ * value for the first time
+ */
+ pm8921_bms_get_battery_current(&iavg_ua);
+ iavg_ma = iavg_ua / 1000;
+ }
- pr_debug("itest = %d uuc_itest = %d\n", chip->i_test, uuc_uah_itest);
+ /* if the time since last sample is small ignore it */
+ if (delta_time_us == 0 || delta_time_us > USEC_PER_SEC) {
+ /*
+ * if we are charging use a nominal avg current so that we keep
+ * a reasonable UUC while charging
+ */
+ if (iavg_ma < 0)
+ iavg_ma = CHARGING_IAVG_MA;
+ iavg_samples[iavg_index] = iavg_ma;
+ iavg_index = (iavg_index + 1) % IAVG_SAMPLES;
+ iavg_num_samples++;
+ if (iavg_num_samples >= IAVG_SAMPLES)
+ iavg_num_samples = IAVG_SAMPLES;
+ }
- /* calculate unusable charge with iavg */
- iavg_ma = max(0, iavg_ma);
+ /* now that this sample is added calcualte the average */
+ iavg_ma = 0;
+ if (iavg_num_samples != 0) {
+ for (i = 0; i < iavg_num_samples; i++) {
+ pr_debug("iavg_samples[%d] = %d\n", i, iavg_samples[i]);
+ iavg_ma += iavg_samples[i];
+ }
+
+ iavg_ma = DIV_ROUND_CLOSEST(iavg_ma, iavg_num_samples);
+ }
+
uuc_uah_iavg = calculate_uuc_uah_at_given_current(chip,
batt_temp, chargecycles,
rbatt, fcc_uah, iavg_ma);
pr_debug("iavg = %d uuc_iavg = %d\n", iavg_ma, uuc_uah_iavg);
- if (firsttime) {
- chip->uuc_uah_iavg_prev = uuc_uah_iavg;
-
- if (cc_uah < chip->last_cc_uah)
- chip->last_uuc_uah = uuc_uah_itest;
- else
- chip->last_uuc_uah = uuc_uah_iavg;
- pr_debug("firsttime uuc_prev = %d\n", chip->last_uuc_uah);
- }
-
- uuc_reported = scale_unusable_charge_uah(chip,
- cc_uah < chip->last_cc_uah,
- uuc_uah_iavg, uuc_uah_itest,
- chip->uuc_uah_iavg_prev);
-
- /* remember the last uuc_uah_iavg */
- chip->uuc_uah_iavg_prev = uuc_uah_iavg;
-
- /* remember the reported uuc */
- chip->last_uuc_uah = uuc_reported;
-
- if (firsttime == 1) {
- /* uuc calculation for the first time is done */
- firsttime = 0;
- }
-
- return uuc_reported;
+ return uuc_uah_iavg;
}
/* calculate remainging charge at the time of ocv */
@@ -1375,7 +1307,8 @@
*unusable_charge_uah = calculate_unusable_charge_uah(chip, *rbatt,
*fcc_uah, *cc_uah, soc_rbatt,
- batt_temp, chargecycles, *iavg_ua);
+ batt_temp, chargecycles, *iavg_ua,
+ *delta_time_us);
pr_debug("UUC = %uuAh\n", *unusable_charge_uah);
}
@@ -1408,6 +1341,38 @@
return real_fcc_uah;
}
+int pm8921_bms_get_simultaneous_battery_voltage_and_current(int *ibat_ua,
+ int *vbat_uv)
+{
+ int rc;
+
+ if (the_chip == NULL) {
+ pr_err("Called too early\n");
+ return -EINVAL;
+ }
+
+ if (pm8921_is_batfet_closed()) {
+ return override_mode_simultaneous_battery_voltage_and_current(
+ ibat_ua,
+ vbat_uv);
+ } else {
+ pr_debug("batfet is open using separate vbat and ibat meas\n");
+ rc = get_battery_uvolts(the_chip, vbat_uv);
+ if (rc < 0) {
+ pr_err("adc vbat failed err = %d\n", rc);
+ return rc;
+ }
+ rc = pm8921_bms_get_battery_current(ibat_ua);
+ if (rc < 0) {
+ pr_err("bms ibat failed err = %d\n", rc);
+ return rc;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(pm8921_bms_get_simultaneous_battery_voltage_and_current);
+
static int bound_soc(int soc)
{
soc = max(0, soc);
@@ -1427,9 +1392,16 @@
int pc_new = 0;
int soc_new = 0;
int m = 0;
+ int rc = 0;
- pm8921_bms_get_simultaneous_battery_voltage_and_current(&ibat_ua,
- &vbat_uv);
+ rc = pm8921_bms_get_simultaneous_battery_voltage_and_current(
+ &ibat_ua,
+ &vbat_uv);
+ if (rc < 0) {
+ pr_err("simultaneous vbat ibat failed err = %d\n", rc);
+ goto out;
+ }
+
if (ibat_ua < 0)
goto out;
@@ -1440,10 +1412,18 @@
soc_est = bound_soc(soc_est);
/*
- * do not adjust if soc_est is between 45 and 25 OR soc_est is
- * same as what bms calculated
+ * do not adjust
+ * if soc is same as what bms calculated
+ * if soc_est is between 45 and 25, this is the flat portion of the
+ * curve where soc_est is not so accurate. We generally don't want to
+ * adjust when soc_est is inaccurate except for the cases when soc is
+ * way far off (higher than 50 or lesser than 20).
+ * Also don't adjust soc if it is above 90 becuase we might pull it low
+ * and cause a bad user experience
*/
- if (is_between(45, 25, soc_est) || soc_est == soc)
+ if (soc_est == soc
+ || (is_between(45, 25, soc_est) && is_between(50, 20, soc))
+ || soc >= 90)
goto out;
if (last_soc_est == -EINVAL)
@@ -1509,46 +1489,16 @@
return soc;
}
-#define MAX_SHUTDOWN_ADJUST_SECONDS 1800
-static int adjust_for_shutdown_soc(struct pm8921_bms_chip *chip, int soc)
+#define IGNORE_SOC_TEMP_DECIDEG 50
+static void backup_soc(struct pm8921_bms_chip *chip, int batt_temp, int soc)
{
- struct timespec uptime;
- int val;
+ if (soc == 0)
+ soc = 0xFF;
- /* value of zero means the shutdown soc should not be used */
- if (chip->shutdown_soc == 0)
- return soc;
+ if (batt_temp < IGNORE_SOC_TEMP_DECIDEG)
+ soc = 0;
- if (shutdown_soc_invalid) {
- chip->shutdown_soc = 0;
- return soc;
- }
-
- do_posix_clock_monotonic_gettime(&uptime);
-
- if (uptime.tv_sec >= MAX_SHUTDOWN_ADJUST_SECONDS) {
- /*
- * adjusted for a long time now, switch to reporting the
- * calculated soc
- */
- chip->shutdown_soc = 0;
- return soc;
- }
-
- val = ((MAX_SHUTDOWN_ADJUST_SECONDS - uptime.tv_sec)
- * chip->shutdown_soc
- + uptime.tv_sec * soc);
- val /= MAX_SHUTDOWN_ADJUST_SECONDS;
- pr_debug("shutdown_soc = %d, adj soc = %d, calc soc = %d\n",
- chip->shutdown_soc, val, soc);
-
- return val;
-}
-
-static void backup_soc(struct pm8921_bms_chip *chip, int last_soc)
-{
- /* TODO: if 0x107 is free for all variants 8917, 8038 etc */
- pm8xxx_writeb(the_chip->dev->parent, TEMP_SOC_STORAGE, last_soc);
+ pm8xxx_writeb(the_chip->dev->parent, TEMP_SOC_STORAGE, soc);
}
static void read_shutdown_soc(struct pm8921_bms_chip *chip)
@@ -1568,12 +1518,222 @@
void pm8921_bms_invalidate_shutdown_soc(void)
{
pr_debug("Invalidating shutdown soc - the battery was removed\n");
+ mutex_lock(&soc_invalidation_mutex);
shutdown_soc_invalid = 1;
- if (the_chip)
- the_chip->shutdown_soc = 0;
+ last_soc = -EINVAL;
+ if (the_chip) {
+ /* reset to pon ocv undoing what the adjusting did */
+ if (the_chip->pon_ocv_uv) {
+ the_chip->last_ocv_uv = the_chip->pon_ocv_uv;
+ pr_debug("resetting ocv to pon_ocv = %d\n",
+ the_chip->pon_ocv_uv);
+ }
+ }
+ mutex_unlock(&soc_invalidation_mutex);
}
EXPORT_SYMBOL(pm8921_bms_invalidate_shutdown_soc);
+static void find_ocv_for_soc(struct pm8921_bms_chip *chip,
+ int batt_temp,
+ int chargecycles,
+ int fcc_uah,
+ int uuc_uah,
+ int cc_uah,
+ int shutdown_soc,
+ int *rc_uah,
+ int *ocv_uv)
+{
+ s64 rc;
+ int pc, new_pc;
+ int batt_temp_degc = batt_temp / 10;
+ int ocv;
+
+ rc = (s64)shutdown_soc * (fcc_uah - uuc_uah);
+ rc = div_s64(rc, 100) + cc_uah + uuc_uah;
+ pc = DIV_ROUND_CLOSEST((int)rc * 100, fcc_uah);
+ pc = clamp(pc, 0, 100);
+
+ ocv = interpolate_ocv(chip, batt_temp_degc, pc);
+
+ pr_debug("s_soc = %d, fcc = %d uuc = %d rc = %d, pc = %d, ocv mv = %d\n",
+ shutdown_soc, fcc_uah, uuc_uah, (int)rc, pc, ocv);
+ new_pc = interpolate_pc(chip, batt_temp_degc, ocv);
+ pr_debug("test revlookup pc = %d for ocv = %d\n", new_pc, ocv);
+
+ while (abs(new_pc - pc) > 1) {
+ int delta_mv = 5;
+
+ if (new_pc > pc)
+ delta_mv = -1 * delta_mv;
+
+ ocv = ocv + delta_mv;
+ new_pc = interpolate_pc(chip, batt_temp_degc, ocv);
+ pr_debug("test revlookup pc = %d for ocv = %d\n", new_pc, ocv);
+ }
+
+ *ocv_uv = ocv * 1000;
+ *rc_uah = (int)rc;
+}
+
+static void adjust_rc_and_uuc_for_shutdown_soc(
+ struct pm8921_bms_chip *chip,
+ int batt_temp,
+ int chargecycles,
+ int fcc_uah,
+ int uuc_uah,
+ int cc_uah,
+ int remaining_charge_uah,
+ int rbatt,
+ int *ret_rc,
+ int *ret_uuc,
+ int *ret_rbatt)
+{
+ int new_rbatt;
+ int ocv_uv;
+ int shutdown_soc;
+ int rc_uah;
+ int soc_rbatt;
+ int iavg_ua, iavg_ma;
+ int num_tries = 0;
+
+ mutex_lock(&soc_invalidation_mutex);
+ shutdown_soc = chip->shutdown_soc;
+ /*
+ * value of zero means the shutdown soc should not be used, the battery
+ * was removed for extended period, the coincell capacitor could have
+ * drained
+ * shutdown_soc_invalid means the shutdown soc should not be used,
+ * the battery was removed for a small period
+ */
+ if (shutdown_soc == 0 || shutdown_soc_invalid) {
+ rc_uah = remaining_charge_uah;
+ goto out;
+ }
+
+ /* value of 0xFF means shutdown soc was 0% */
+ if (shutdown_soc == 0xFF)
+ shutdown_soc = 0;
+
+ pm8921_bms_get_battery_current(&iavg_ua);
+ iavg_ma = iavg_ua / 1000;
+ if (iavg_ma < 0)
+ iavg_ma = CHARGING_IAVG_MA;
+
+recalculate_ocv:
+
+ find_ocv_for_soc(chip, batt_temp, chargecycles,
+ fcc_uah, uuc_uah, cc_uah,
+ shutdown_soc,
+ &rc_uah, &ocv_uv);
+
+ soc_rbatt = div_s64((rc_uah - cc_uah) * 100, fcc_uah);
+ new_rbatt = get_rbatt(chip, soc_rbatt, batt_temp);
+ pr_debug("for s_soc = %d rc_uah = %d ocv_uv = %d, soc_rbatt = %d rbatt = %d\n",
+ shutdown_soc, rc_uah, ocv_uv, soc_rbatt, new_rbatt);
+ if (abs(new_rbatt - rbatt) > 20 && num_tries < 10) {
+ rbatt = new_rbatt;
+ uuc_uah = calculate_uuc_uah_at_given_current(chip,
+ batt_temp, chargecycles,
+ new_rbatt, fcc_uah, iavg_ma);
+
+ pr_debug("rbatt not settled uuc = %d for rbatt = %d iavg_ma = %d num_tries = %d\n",
+ uuc_uah, rbatt, iavg_ma, num_tries);
+ num_tries++;
+ goto recalculate_ocv;
+ }
+ pr_debug("DONE for s_soc = %d rc_uah = %d ocv_uv = %d, rbatt = %d\n",
+ shutdown_soc, rc_uah, ocv_uv, new_rbatt);
+
+ chip->pon_ocv_uv = chip->last_ocv_uv;
+ chip->last_ocv_uv = ocv_uv;
+out:
+ *ret_rbatt = rbatt;
+ *ret_rc = rc_uah;
+ *ret_uuc = uuc_uah;
+ mutex_unlock(&soc_invalidation_mutex);
+}
+
+#define SOC_CATCHUP_SEC_MAX 600
+#define SOC_CATCHUP_SEC_PER_PERCENT 60
+#define MAX_CATCHUP_SOC (SOC_CATCHUP_SEC_MAX/SOC_CATCHUP_SEC_PER_PERCENT)
+static int scale_soc_while_chg(struct pm8921_bms_chip *chip,
+ int delta_time_us, int new_soc, int prev_soc)
+{
+ int chg_time_sec;
+ int catch_up_sec;
+ int scaled_soc;
+ int numerator;
+
+ /*
+ * The device must be charging for reporting a higher soc, if
+ * not ignore this soc and continue reporting the prev_soc.
+ * Also don't report a high value immediately slowly scale the
+ * value from prev_soc to the new soc based on a charge time
+ * weighted average
+ */
+
+ /* if we are not charging return last soc */
+ if (the_chip->start_percent == -EINVAL)
+ return prev_soc;
+
+ /* if soc is called in quick succession return the last soc */
+ if (delta_time_us < USEC_PER_SEC)
+ return prev_soc;
+
+ chg_time_sec = DIV_ROUND_UP(the_chip->charge_time_us, USEC_PER_SEC);
+ catch_up_sec = DIV_ROUND_UP(the_chip->catch_up_time_us, USEC_PER_SEC);
+ pr_debug("cts= %d catch_up_sec = %d\n", chg_time_sec, catch_up_sec);
+
+ /*
+ * if we have been charging for more than catch_up time simply return
+ * new soc
+ */
+ if (chg_time_sec > catch_up_sec)
+ return new_soc;
+
+ numerator = (catch_up_sec - chg_time_sec) * prev_soc
+ + chg_time_sec * new_soc;
+ scaled_soc = numerator / catch_up_sec;
+
+ pr_debug("cts = %d new_soc = %d prev_soc = %d scaled_soc = %d\n",
+ chg_time_sec, new_soc, prev_soc, scaled_soc);
+
+ return scaled_soc;
+}
+
+#define SHOW_SHUTDOWN_SOC_MS 30000
+static void shutdown_soc_work(struct work_struct *work)
+{
+ struct pm8921_bms_chip *chip = container_of(work,
+ struct pm8921_bms_chip, shutdown_soc_work.work);
+
+ pr_debug("not forcing shutdown soc anymore\n");
+ /* it has been 30 seconds since init, no need to show shutdown soc */
+ chip->shutdown_soc_timer_expired = 1;
+}
+
+static bool is_shutdown_soc_within_limits(struct pm8921_bms_chip *chip, int soc)
+{
+ int shutdown_soc;
+
+ if (chip->shutdown_soc == 0 || shutdown_soc_invalid) {
+ pr_debug("NOT forcing shutdown soc = %d\n", chip->shutdown_soc);
+ return 0;
+ }
+
+ shutdown_soc = chip->shutdown_soc;
+ if (shutdown_soc == 0xFF)
+ shutdown_soc = 0;
+
+ if (abs(shutdown_soc - soc) > chip->shutdown_soc_valid_limit) {
+ pr_debug("rejecting shutdown soc = %d, soc = %d, limit = %d\n",
+ shutdown_soc, soc, chip->shutdown_soc_valid_limit);
+ shutdown_soc_invalid = 1;
+ return 0;
+ }
+
+ return 1;
+}
/*
* Remaining Usable Charge = remaining_charge (charge at ocv instance)
* - coloumb counter charge
@@ -1588,9 +1748,11 @@
int remaining_charge_uah, soc;
int cc_uah;
int rbatt;
- int shutdown_adjusted_soc;
int iavg_ua;
int delta_time_us;
+ int new_rc_uah;
+ int new_ucc_uah;
+ int new_rbatt;
calculate_soc_params(chip, raw, batt_temp, chargecycles,
&fcc_uah,
@@ -1612,13 +1774,13 @@
fcc_uah, unusable_charge_uah);
soc = 0;
} else {
- soc = (remaining_usable_charge_uah * 100)
- / (fcc_uah - unusable_charge_uah);
+ soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
+ (fcc_uah - unusable_charge_uah));
}
if (soc > 100)
soc = 100;
- pr_debug("SOC = %u%%\n", soc);
+ pr_debug("before adjusting calculated SOC = %d%%\n", soc);
if (bms_fake_battery != -EINVAL) {
pr_debug("Returning Fake SOC = %d%%\n", bms_fake_battery);
@@ -1640,28 +1802,155 @@
soc = 0;
}
- soc = adjust_soc(chip, soc, batt_temp, rbatt,
- fcc_uah, unusable_charge_uah, cc_uah);
-
- if (last_soc == -EINVAL || soc <= last_soc) {
- last_soc = soc;
- } else {
+ if (delta_time_us == 0 && is_shutdown_soc_within_limits(chip, soc)) {
/*
- * soc > last_soc
- * the device must be charging for reporting a higher soc, if
- * not ignore this soc and continue reporting the last_soc
+ * soc for the first time - use shutdown soc
+ * to adjust pon ocv since it is a small percent away from
+ * the real soc
*/
- if (the_chip->start_percent != -EINVAL)
- last_soc = soc;
- else
- pr_debug("soc = %d reporting last_soc = %d\n", soc,
- last_soc);
+ adjust_rc_and_uuc_for_shutdown_soc(
+ chip,
+ batt_temp, chargecycles,
+ fcc_uah, unusable_charge_uah,
+ cc_uah, remaining_charge_uah,
+ rbatt,
+ &new_rc_uah, &new_ucc_uah,
+ &new_rbatt);
+
+ remaining_charge_uah = new_rc_uah;
+ unusable_charge_uah = new_ucc_uah;
+ rbatt = new_rbatt;
+
+ soc = DIV_ROUND_CLOSEST((remaining_usable_charge_uah * 100),
+ (fcc_uah - unusable_charge_uah));
}
- shutdown_adjusted_soc = adjust_for_shutdown_soc(chip, last_soc);
- backup_soc(chip, shutdown_adjusted_soc);
+ calculated_soc = adjust_soc(chip, soc, batt_temp,
+ rbatt, fcc_uah, unusable_charge_uah, cc_uah);
- return shutdown_adjusted_soc;
+ pr_debug("calculated SOC = %d\n", calculated_soc);
+ return calculated_soc;
+}
+
+#define CALCULATE_SOC_MS 20000
+static void calculate_soc_work(struct work_struct *work)
+{
+ struct pm8921_bms_chip *chip = container_of(work,
+ struct pm8921_bms_chip,
+ calculate_soc_delayed_work.work);
+ int batt_temp, rc;
+ struct pm8xxx_adc_chan_result result;
+ struct pm8921_soc_params raw;
+ int soc;
+
+ rc = pm8xxx_adc_read(chip->batt_temp_channel, &result);
+ if (rc) {
+ pr_err("error reading adc channel = %d, rc = %d\n",
+ chip->batt_temp_channel, rc);
+ return;
+ }
+ pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
+ result.measurement);
+ batt_temp = (int)result.physical;
+
+ mutex_lock(&chip->last_ocv_uv_mutex);
+ read_soc_params_raw(chip, &raw);
+
+ soc = calculate_state_of_charge(chip, &raw,
+ batt_temp, last_chargecycles);
+ mutex_unlock(&chip->last_ocv_uv_mutex);
+
+ schedule_delayed_work(&chip->calculate_soc_delayed_work,
+ round_jiffies_relative(msecs_to_jiffies
+ (CALCULATE_SOC_MS)));
+}
+
+static int report_state_of_charge(struct pm8921_bms_chip *chip)
+{
+ int soc = calculated_soc;
+ int delta_time_us;
+ struct timespec now;
+ struct pm8xxx_adc_chan_result result;
+ int batt_temp;
+ int rc;
+
+ rc = pm8xxx_adc_read(the_chip->batt_temp_channel, &result);
+ if (rc) {
+ pr_err("error reading adc channel = %d, rc = %d\n",
+ the_chip->batt_temp_channel, rc);
+ return rc;
+ }
+ pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
+ result.measurement);
+ batt_temp = (int)result.physical;
+
+ do_posix_clock_monotonic_gettime(&now);
+ if (chip->t_soc_queried.tv_sec != 0) {
+ delta_time_us
+ = (now.tv_sec - chip->t_soc_queried.tv_sec) * USEC_PER_SEC
+ + (now.tv_nsec - chip->t_soc_queried.tv_nsec) / 1000;
+ } else {
+ /* calculation for the first time */
+ delta_time_us = 0;
+ }
+
+ /*
+ * account for charge time - limit it to SOC_CATCHUP_SEC to
+ * avoid overflows when charging continues for extended periods
+ */
+ if (the_chip->start_percent != -EINVAL) {
+ if (the_chip->charge_time_us == 0) {
+ /*
+ * calculating soc for the first time
+ * after start of chg. Initialize catchup time
+ */
+ if (abs(soc - last_soc) < MAX_CATCHUP_SOC)
+ the_chip->catch_up_time_us =
+ (soc - last_soc) * SOC_CATCHUP_SEC_PER_PERCENT
+ * USEC_PER_SEC;
+ else
+ the_chip->catch_up_time_us =
+ SOC_CATCHUP_SEC_MAX * USEC_PER_SEC;
+
+ if (the_chip->catch_up_time_us < 0)
+ the_chip->catch_up_time_us = 0;
+ }
+
+ /* add charge time */
+ if (the_chip->charge_time_us
+ < SOC_CATCHUP_SEC_MAX * USEC_PER_SEC)
+ chip->charge_time_us += delta_time_us;
+
+ /* end catchup if calculated soc and last soc are same */
+ if (last_soc == soc)
+ the_chip->catch_up_time_us = 0;
+ }
+
+ /* last_soc < soc ... scale and catch up */
+ if (last_soc != -EINVAL && last_soc < soc && soc != 100)
+ soc = scale_soc_while_chg(chip, delta_time_us, soc, last_soc);
+
+ if (chip->shutdown_soc != 0
+ && !shutdown_soc_invalid
+ && !chip->shutdown_soc_timer_expired) {
+ /*
+ * force shutdown soc if it is valid and the shutdown soc show
+ * timer has not expired
+ */
+ if (chip->shutdown_soc != 0xFF)
+ soc = chip->shutdown_soc;
+ else
+ soc = 0;
+
+ pr_debug("Forcing SHUTDOWN_SOC = %d\n", soc);
+ }
+
+ last_soc = soc;
+ backup_soc(chip, batt_temp, last_soc);
+ pr_debug("Reported SOC = %d\n", last_soc);
+ chip->t_soc_queried = now;
+
+ return last_soc;
}
#define MIN_DELTA_625_UV 1000
@@ -1672,10 +1961,11 @@
int usb_chg;
int this_delta;
+ mutex_lock(&chip->calib_mutex);
rc = pm8xxx_adc_read(the_chip->ref1p25v_channel, &result);
if (rc) {
pr_err("ADC failed for 1.25volts rc = %d\n", rc);
- return;
+ goto out;
}
voltage = xoadc_reading_to_microvolt(result.adc_code);
@@ -1687,7 +1977,7 @@
rc = pm8xxx_adc_read(the_chip->ref625mv_channel, &result);
if (rc) {
pr_err("ADC failed for 1.25volts rc = %d\n", rc);
- return;
+ goto out;
}
voltage = xoadc_reading_to_microvolt(result.adc_code);
@@ -1714,6 +2004,8 @@
chip->xoadc_v0625_usb_absent,
last_usb_cal_delta_uv);
}
+out:
+ mutex_unlock(&chip->calib_mutex);
}
static void calibrate_hkadc_work(struct work_struct *work)
@@ -1729,6 +2021,19 @@
schedule_work(&the_chip->calib_hkadc_work);
}
+#define HKADC_CALIB_DELAY_MS 600000
+static void calibrate_hkadc_delayed_work(struct work_struct *work)
+{
+ struct pm8921_bms_chip *chip = container_of(work,
+ struct pm8921_bms_chip,
+ calib_hkadc_delayed_work.work);
+
+ calib_hkadc(chip);
+ schedule_delayed_work(&chip->calib_hkadc_delayed_work,
+ round_jiffies_relative(msecs_to_jiffies
+ (HKADC_CALIB_DELAY_MS)));
+}
+
int pm8921_bms_get_vsense_avg(int *result)
{
int rc = -EINVAL;
@@ -1774,33 +2079,12 @@
int pm8921_bms_get_percent_charge(void)
{
- int batt_temp, rc;
- struct pm8xxx_adc_chan_result result;
- struct pm8921_soc_params raw;
- int soc;
-
if (!the_chip) {
pr_err("called before initialization\n");
return -EINVAL;
}
- rc = pm8xxx_adc_read(the_chip->batt_temp_channel, &result);
- if (rc) {
- pr_err("error reading adc channel = %d, rc = %d\n",
- the_chip->batt_temp_channel, rc);
- return rc;
- }
- pr_debug("batt_temp phy = %lld meas = 0x%llx", result.physical,
- result.measurement);
- batt_temp = (int)result.physical;
-
- mutex_lock(&the_chip->last_ocv_uv_mutex);
- read_soc_params_raw(the_chip, &raw);
-
- soc = calculate_state_of_charge(the_chip, &raw,
- batt_temp, last_chargecycles);
- mutex_unlock(&the_chip->last_ocv_uv_mutex);
- return soc;
+ return report_state_of_charge(the_chip);
}
EXPORT_SYMBOL_GPL(pm8921_bms_get_percent_charge);
@@ -1881,32 +2165,21 @@
#define OCV_TOL_NO_OCV 0x00
void pm8921_bms_charging_began(void)
{
- int batt_temp, rc;
- struct pm8xxx_adc_chan_result result;
struct pm8921_soc_params raw;
- rc = pm8xxx_adc_read(the_chip->batt_temp_channel, &result);
- if (rc) {
- pr_err("error reading adc channel = %d, rc = %d\n",
- the_chip->batt_temp_channel, rc);
- return;
- }
- pr_debug("batt_temp phy = %lld meas = 0x%llx\n", result.physical,
- result.measurement);
- batt_temp = (int)result.physical;
-
mutex_lock(&the_chip->last_ocv_uv_mutex);
read_soc_params_raw(the_chip, &raw);
-
- the_chip->start_percent = calculate_state_of_charge(the_chip, &raw,
- batt_temp, last_chargecycles);
mutex_unlock(&the_chip->last_ocv_uv_mutex);
+ the_chip->start_percent = report_state_of_charge(the_chip);
+
bms_start_percent = the_chip->start_percent;
bms_start_ocv_uv = raw.last_good_ocv_uv;
calculate_cc_uah(the_chip, raw.cc, &bms_start_cc_uah);
pm_bms_masked_write(the_chip, BMS_TOLERANCES,
IBAT_TOL_MASK, IBAT_TOL_DEFAULT);
+ the_chip->charge_time_us = 0;
+ the_chip->catch_up_time_us = 0;
pr_debug("start_percent = %u%%\n", the_chip->start_percent);
}
EXPORT_SYMBOL_GPL(pm8921_bms_charging_began);
@@ -2011,6 +2284,8 @@
last_chargecycles);
the_chip->start_percent = -EINVAL;
the_chip->end_percent = -EINVAL;
+ the_chip->charge_time_us = 0;
+ the_chip->catch_up_time_us = 0;
pm_bms_masked_write(the_chip, BMS_TOLERANCES,
IBAT_TOL_MASK, IBAT_TOL_NOCHG);
}
@@ -2157,94 +2432,6 @@
return -EINVAL;
}
-static int pm8921_bms_suspend(struct device *dev)
-{
- int rc;
- struct pm8xxx_adc_chan_result result;
- struct pm8921_bms_chip *chip = dev_get_drvdata(dev);
- struct pm8921_soc_params raw;
- int fcc_uah;
- int remaining_charge_uah;
- int cc_uah;
-
- chip->batt_temp_suspend = 0;
- rc = pm8xxx_adc_read(chip->batt_temp_channel, &result);
- if (rc) {
- pr_err("error reading adc channel = %d, rc = %d\n",
- chip->batt_temp_channel, rc);
- }
- chip->batt_temp_suspend = (int)result.physical;
-
- mutex_lock(&chip->last_ocv_uv_mutex);
- read_soc_params_raw(chip, &raw);
-
- fcc_uah = calculate_fcc_uah(chip,
- chip->batt_temp_suspend, last_chargecycles);
- pr_debug("FCC = %uuAh batt_temp = %d, cycles = %d\n",
- fcc_uah, chip->batt_temp_suspend, last_chargecycles);
- /* calculate remainging charge */
- remaining_charge_uah = calculate_remaining_charge_uah(chip, &raw,
- fcc_uah, chip->batt_temp_suspend,
- last_chargecycles);
- pr_debug("RC = %uuAh\n", remaining_charge_uah);
-
- /* calculate cc micro_volt_hour */
- calculate_cc_uah(chip, raw.cc, &cc_uah);
- pr_debug("cc_uah = %duAh raw->cc = %x cc = %lld after subtracting %x\n",
- cc_uah, raw.cc,
- (int64_t)raw.cc - chip->cc_reading_at_100,
- chip->cc_reading_at_100);
- chip->soc_rbatt_suspend = ((remaining_charge_uah - cc_uah) * 100)
- / fcc_uah;
- mutex_unlock(&chip->last_ocv_uv_mutex);
-
- return 0;
-}
-
-#define DELTA_RBATT_PERCENT 10
-static int pm8921_bms_resume(struct device *dev)
-{
- struct pm8921_rbatt_params raw;
- struct pm8921_bms_chip *chip = dev_get_drvdata(dev);
- int rbatt;
- int expected_rbatt;
- int scalefactor;
- int delta_rbatt;
-
- read_rbatt_params_raw(chip, &raw);
- rbatt = calculate_rbatt_resume(chip, &raw);
-
- if (rbatt < 0)
- return 0;
-
- expected_rbatt
- = (last_rbatt < 0) ? chip->default_rbatt_mohm : last_rbatt;
-
- if (chip->rbatt_sf_lut) {
- scalefactor = interpolate_scalingfactor(chip,
- chip->rbatt_sf_lut,
- chip->batt_temp_suspend / 10,
- chip->soc_rbatt_suspend);
- rbatt = rbatt * 100 / scalefactor;
- }
-
- delta_rbatt = expected_rbatt - rbatt;
- if (delta_rbatt)
- delta_rbatt = -delta_rbatt;
- /*
- * only update last_rbatt if rbatt is within some
- * percent of expected_rbatt
- */
- if (delta_rbatt * 100 <= DELTA_RBATT_PERCENT * expected_rbatt)
- last_rbatt = rbatt;
-
- return 0;
-}
-
-static const struct dev_pm_ops pm8921_pm_ops = {
- .suspend = pm8921_bms_suspend,
- .resume = pm8921_bms_resume,
-};
#define EN_BMS_BIT BIT(7)
#define EN_PON_HS_BIT BIT(0)
static int __devinit pm8921_bms_hw_init(struct pm8921_bms_chip *chip)
@@ -2359,7 +2546,6 @@
}
enum bms_request_operation {
- CALC_RBATT,
CALC_FCC,
CALC_PC,
CALC_SOC,
@@ -2420,18 +2606,13 @@
int ret = 0;
int ibat_ua, vbat_uv;
struct pm8921_soc_params raw;
- struct pm8921_rbatt_params rraw;
read_soc_params_raw(the_chip, &raw);
- read_rbatt_params_raw(the_chip, &rraw);
*val = 0;
/* global irq number passed in via data */
switch (param) {
- case CALC_RBATT:
- *val = calculate_rbatt_resume(the_chip, &rraw);
- break;
case CALC_FCC:
*val = calculate_fcc_uah(the_chip, test_batt_temp,
test_chargecycle);
@@ -2490,10 +2671,8 @@
int param = (int)data;
int ret = 0;
struct pm8921_soc_params raw;
- struct pm8921_rbatt_params rraw;
read_soc_params_raw(the_chip, &raw);
- read_rbatt_params_raw(the_chip, &rraw);
*val = 0;
@@ -2505,15 +2684,6 @@
case LAST_GOOD_OCV_VALUE:
*val = raw.last_good_ocv_uv;
break;
- case VBATT_FOR_RBATT:
- *val = rraw.vbatt_for_rbatt_uv;
- break;
- case VSENSE_FOR_RBATT:
- *val = rraw.vsense_for_rbatt_uv;
- break;
- case OCV_FOR_RBATT:
- *val = rraw.ocv_for_rbatt_uv;
- break;
case VSENSE_AVG:
read_vsense_avg(the_chip, (uint *)val);
break;
@@ -2609,8 +2779,6 @@
debugfs_create_file("read_vsense_avg", 0644, chip->dent,
(void *)VSENSE_AVG, &reading_fops);
- debugfs_create_file("show_rbatt", 0644, chip->dent,
- (void *)CALC_RBATT, &calc_fops);
debugfs_create_file("show_fcc", 0644, chip->dent,
(void *)CALC_FCC, &calc_fops);
debugfs_create_file("show_pc", 0644, chip->dent,
@@ -2716,13 +2884,13 @@
mutex_init(&chip->last_ocv_uv_mutex);
chip->dev = &pdev->dev;
chip->r_sense = pdata->r_sense;
- chip->i_test = pdata->i_test;
- chip->v_failure = pdata->v_failure;
+ chip->v_cutoff = pdata->v_cutoff;
chip->max_voltage_uv = pdata->max_voltage_uv;
chip->batt_type = pdata->battery_type;
chip->rconn_mohm = pdata->rconn_mohm;
chip->start_percent = -EINVAL;
chip->end_percent = -EINVAL;
+ chip->shutdown_soc_valid_limit = pdata->shutdown_soc_valid_limit;
rc = set_battery_data(chip);
if (rc) {
pr_err("%s bad battery data %d\n", __func__, rc);
@@ -2746,7 +2914,14 @@
chip->batt_id_channel = pdata->bms_cdata.batt_id_channel;
chip->revision = pm8xxx_get_revision(chip->dev->parent);
chip->enable_fcc_learning = pdata->enable_fcc_learning;
+
+ mutex_init(&chip->calib_mutex);
INIT_WORK(&chip->calib_hkadc_work, calibrate_hkadc_work);
+ INIT_DELAYED_WORK(&chip->calib_hkadc_delayed_work,
+ calibrate_hkadc_delayed_work);
+
+ INIT_DELAYED_WORK(&chip->calculate_soc_delayed_work,
+ calculate_soc_work);
rc = request_irqs(chip, pdev);
if (rc) {
@@ -2773,20 +2948,25 @@
}
check_initial_ocv(chip);
- /* initial hkadc calibration */
- schedule_work(&chip->calib_hkadc_work);
+ /* start periodic hkadc calibration */
+ schedule_delayed_work(&chip->calib_hkadc_delayed_work, 0);
+
/* enable the vbatt reading interrupts for scheduling hkadc calib */
pm8921_bms_enable_irq(chip, PM8921_BMS_GOOD_OCV);
pm8921_bms_enable_irq(chip, PM8921_BMS_OCV_FOR_R);
- INIT_DELAYED_WORK(&chip->uuc_timer_work, uuc_timer_work);
- schedule_delayed_work(&chip->uuc_timer_work,
- msecs_to_jiffies(UUC_TIMER_MS));
+ calculate_soc_work(&(chip->calculate_soc_delayed_work.work));
get_battery_uvolts(chip, &vbatt);
pr_info("OK battery_capacity_at_boot=%d volt = %d ocv = %d\n",
pm8921_bms_get_percent_charge(),
vbatt, chip->last_ocv_uv);
+
+ INIT_DELAYED_WORK(&chip->shutdown_soc_work, shutdown_soc_work);
+ schedule_delayed_work(&chip->shutdown_soc_work,
+ round_jiffies_relative(msecs_to_jiffies
+ (SHOW_SHUTDOWN_SOC_MS)));
+
return 0;
free_irqs:
@@ -2814,7 +2994,6 @@
.driver = {
.name = PM8921_BMS_DEV_NAME,
.owner = THIS_MODULE,
- .pm = &pm8921_pm_ops
},
};
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index 85b653d..4e15e77 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -271,6 +271,7 @@
enum pm8921_chg_led_src_config led_src_config;
bool host_mode;
u8 active_path;
+ int recent_reported_soc;
};
/* user space parameter to limit usb current */
@@ -327,6 +328,10 @@
return pm_chg_get_rt_status(chip, DCIN_VALID_IRQ);
}
+static int is_batfet_closed(struct pm8921_chg_chip *chip)
+{
+ return pm_chg_get_rt_status(chip, BATFET_IRQ);
+}
#define CAPTURE_FSM_STATE_CMD 0xC2
#define READ_BANK_7 0x70
#define READ_BANK_4 0x40
@@ -1400,6 +1405,7 @@
if (percent_soc <= 10)
pr_warn("low battery charge = %d%%\n", percent_soc);
+ chip->recent_reported_soc = percent_soc;
return percent_soc;
}
@@ -1741,6 +1747,15 @@
}
EXPORT_SYMBOL(pm8921_is_battery_present);
+int pm8921_is_batfet_closed(void)
+{
+ if (!the_chip) {
+ pr_err("called before init\n");
+ return -EINVAL;
+ }
+ return is_batfet_closed(the_chip);
+}
+EXPORT_SYMBOL(pm8921_is_batfet_closed);
/*
* Disabling the charge current limit causes current
* current limits to have no monitoring. An adequate charger
@@ -2768,6 +2783,7 @@
* per update_time minutes
*
*/
+#define LOW_SOC_HEARTBEAT_MS 20000
static void update_heartbeat(struct work_struct *work)
{
struct delayed_work *dwork = to_delayed_work(work);
@@ -2776,7 +2792,12 @@
pm_chg_failed_clear(chip, 1);
power_supply_changed(&chip->batt_psy);
- schedule_delayed_work(&chip->update_heartbeat_work,
+ if (chip->recent_reported_soc <= 20)
+ schedule_delayed_work(&chip->update_heartbeat_work,
+ round_jiffies_relative(msecs_to_jiffies
+ (LOW_SOC_HEARTBEAT_MS)));
+ else
+ schedule_delayed_work(&chip->update_heartbeat_work,
round_jiffies_relative(msecs_to_jiffies
(chip->update_time)));
}
diff --git a/drivers/power/pm8xxx-ccadc.c b/drivers/power/pm8xxx-ccadc.c
index 861bac8..e48257a 100644
--- a/drivers/power/pm8xxx-ccadc.c
+++ b/drivers/power/pm8xxx-ccadc.c
@@ -685,13 +685,13 @@
goto free_chip;
}
- INIT_DELAYED_WORK(&chip->calib_ccadc_work, calibrate_ccadc_work);
- schedule_delayed_work(&chip->calib_ccadc_work, 0);
disable_irq_nosync(chip->eoc_irq);
platform_set_drvdata(pdev, chip);
the_chip = chip;
+ INIT_DELAYED_WORK(&chip->calib_ccadc_work, calibrate_ccadc_work);
+ schedule_delayed_work(&chip->calib_ccadc_work, 0);
create_debugfs_entries(chip);
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 2dd698a..7d0583c 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -97,7 +97,7 @@
#define TSENS_THRESHOLD_MAX_CODE 0x3ff
#define TSENS_THRESHOLD_MIN_CODE 0x0
-#define TSENS_CTRL_INIT_DATA1 0x3fffff9
+#define TSENS_CTRL_INIT_DATA1 0x1cfff9
#define TSENS_GLOBAL_INIT_DATA 0x302f16c
#define TSENS_S0_MAIN_CFG_INIT_DATA 0x1c3
#define TSENS_SN_MIN_MAX_STATUS_CTRL_DATA 0x3ffc00
@@ -141,27 +141,24 @@
static int tsens_tz_code_to_degc(int adc_code, int sensor_num)
{
int degcbeforefactor, degc;
- degcbeforefactor = (adc_code *
- tmdev->sensor[sensor_num].slope_mul_tsens_factor
- + tmdev->sensor[sensor_num].offset);
+ degcbeforefactor = ((adc_code * tmdev->tsens_factor) -
+ tmdev->sensor[sensor_num].offset)/
+ tmdev->sensor[sensor_num].slope_mul_tsens_factor;
if (degcbeforefactor == 0)
degc = degcbeforefactor;
else if (degcbeforefactor > 0)
- degc = (degcbeforefactor + tmdev->tsens_factor/2)
- / tmdev->tsens_factor;
+ degc = degcbeforefactor;
else
- degc = (degcbeforefactor - tmdev->tsens_factor/2)
- / tmdev->tsens_factor;
+ degc = degcbeforefactor;
+
return degc;
}
static int tsens_tz_degc_to_code(int degc, int sensor_num)
{
- int code = (degc * tmdev->tsens_factor -
- tmdev->sensor[sensor_num].offset
- + tmdev->sensor[sensor_num].slope_mul_tsens_factor/2)
- / tmdev->sensor[sensor_num].slope_mul_tsens_factor;
+ int code = ((degc * tmdev->sensor[sensor_num].slope_mul_tsens_factor)
+ + tmdev->sensor[sensor_num].offset)/tmdev->tsens_factor;
if (code > TSENS_THRESHOLD_MAX_CODE)
code = TSENS_THRESHOLD_MAX_CODE;
@@ -498,10 +495,10 @@
if (!tsens_calibration_mode) {
pr_debug("TSENS is calibrationless mode\n");
for (i = 0; i < tmdev->tsens_num_sensor; i++) {
- tmdev->sensor[i].calib_data_point2 = 78000;
- tmdev->sensor[i].calib_data_point1 = 49200;
- goto compute_intercept_slope;
+ tmdev->sensor[i].calib_data_point2 = 780;
+ tmdev->sensor[i].calib_data_point1 = 492;
}
+ goto compute_intercept_slope;
} else if (tsens_calibration_mode == TSENS_ONE_POINT_CALIB ||
TSENS_TWO_POINT_CALIB) {
tsens_base1_data = calib_data[0] & TSENS_BASE1_MASK;
@@ -595,10 +592,9 @@
num *= tmdev->tsens_factor;
tmdev->sensor[i].slope_mul_tsens_factor = num/den;
}
- tmdev->sensor[i].offset = (TSENS_CAL_DEGC_POINT1 *
- tmdev->tsens_factor)
- - (tmdev->sensor[i].calib_data_point1 *
- tmdev->sensor[i].slope_mul_tsens_factor);
+ tmdev->sensor[i].offset = (tmdev->sensor[i].calib_data_point1 *
+ tmdev->tsens_factor) - (TSENS_CAL_DEGC_POINT1 *
+ tmdev->sensor[i].slope_mul_tsens_factor);
INIT_WORK(&tmdev->sensor[i].work, notify_uspace_tsens_fn);
tmdev->prev_reading_avail = false;
}
@@ -747,6 +743,7 @@
goto fail;
tsens_hw_init();
+
tmdev->prev_reading_avail = true;
platform_set_drvdata(pdev, tmdev);
@@ -796,6 +793,7 @@
goto fail;
}
}
+
rc = request_irq(tmdev->tsens_irq, tsens_isr,
IRQF_TRIGGER_RISING, "tsens_interrupt", tmdev);
if (rc < 0) {
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 6c9b7cd..ccbaa6d 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -418,6 +418,8 @@
int count;
char *char_buf;
unsigned char *flag_buf;
+ unsigned int left = 0;
+ unsigned int max_space;
count = head->commit - head->read;
if (!count) {
@@ -432,10 +434,33 @@
line discipline as we want to empty the queue */
if (test_bit(TTY_FLUSHPENDING, &tty->flags))
break;
+
+ /* update receive room */
+ spin_lock(&tty->read_lock);
+ if (tty->update_room_in_ldisc) {
+ if ((tty->read_cnt == N_TTY_BUF_SIZE - 1) &&
+ (tty->receive_room ==
+ N_TTY_BUF_SIZE - 1))
+ tty->rr_bug++;
+ left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+ }
+ spin_unlock(&tty->read_lock);
+
if (!tty->receive_room)
break;
- if (count > tty->receive_room)
- count = tty->receive_room;
+
+ if (tty->update_room_in_ldisc && !left) {
+ schedule_work(&tty->buf.work);
+ break;
+ }
+
+ if (tty->update_room_in_ldisc)
+ max_space = min(left, tty->receive_room);
+ else
+ max_space = tty->receive_room;
+
+ if (count > max_space)
+ count = max_space;
char_buf = head->char_buf_ptr + head->read;
flag_buf = head->flag_buf_ptr + head->read;
head->read += count;
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 4dd6d68..465e512 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -47,6 +47,8 @@
#define USB_REG_START_OFFSET 0x90
#define USB_REG_END_OFFSET 0x250
+static struct workqueue_struct *ehci_wq;
+
struct msm_hsic_hcd {
struct ehci_hcd ehci;
struct device *dev;
@@ -66,6 +68,9 @@
uint32_t bus_perf_client;
uint32_t wakeup_int_cnt;
enum usb_vdd_type vdd_type;
+
+ struct work_struct bus_vote_w;
+ bool bus_vote;
};
struct msm_hsic_hcd *__mehci;
@@ -658,11 +663,8 @@
dev_err(mehci->dev, "unable to set vddcx voltage for VDD MIN\n");
if (mehci->bus_perf_client && debug_bus_voting_enabled) {
- ret = msm_bus_scale_client_update_request(
- mehci->bus_perf_client, 0);
- if (ret)
- dev_err(mehci->dev, "%s: Failed to dvote for "
- "bus bandwidth %d\n", __func__, ret);
+ mehci->bus_vote = false;
+ queue_work(ehci_wq, &mehci->bus_vote_w);
}
atomic_set(&mehci->in_lpm, 1);
@@ -697,11 +699,8 @@
}
if (mehci->bus_perf_client && debug_bus_voting_enabled) {
- ret = msm_bus_scale_client_update_request(
- mehci->bus_perf_client, 1);
- if (ret)
- dev_err(mehci->dev, "%s: Failed to vote for "
- "bus bandwidth %d\n", __func__, ret);
+ mehci->bus_vote = true;
+ queue_work(ehci_wq, &mehci->bus_vote_w);
}
min_vol = vdd_val[mehci->vdd_type][VDD_MIN];
@@ -769,6 +768,19 @@
}
#endif
+static void ehci_hsic_bus_vote_w(struct work_struct *w)
+{
+ struct msm_hsic_hcd *mehci =
+ container_of(w, struct msm_hsic_hcd, bus_vote_w);
+ int ret;
+
+ ret = msm_bus_scale_client_update_request(mehci->bus_perf_client,
+ mehci->bus_vote);
+ if (ret)
+ dev_err(mehci->dev, "%s: Failed to vote for bus bandwidth %d\n",
+ __func__, ret);
+}
+
static irqreturn_t msm_hsic_irq(struct usb_hcd *hcd)
{
struct msm_hsic_hcd *mehci = hcd_to_hsic(hcd);
@@ -1294,6 +1306,15 @@
goto deinit_vddcx;
}
+ ehci_wq = create_singlethread_workqueue("ehci_wq");
+ if (!ehci_wq) {
+ dev_err(&pdev->dev, "unable to create workqueue\n");
+ ret = -ENOMEM;
+ goto deinit_vddcx;
+ }
+
+ INIT_WORK(&mehci->bus_vote_w, ehci_hsic_bus_vote_w);
+
ret = usb_add_hcd(hcd, hcd->irq, IRQF_SHARED);
if (ret) {
dev_err(&pdev->dev, "unable to register HCD\n");
@@ -1339,11 +1360,8 @@
msm_bus_scale_register_client(pdata->bus_scale_table);
/* Configure BUS performance parameters for MAX bandwidth */
if (mehci->bus_perf_client) {
- ret = msm_bus_scale_client_update_request(
- mehci->bus_perf_client, 1);
- if (ret)
- dev_err(&pdev->dev, "%s: Failed to vote for "
- "bus bandwidth %d\n", __func__, ret);
+ mehci->bus_vote = true;
+ queue_work(ehci_wq, &mehci->bus_vote_w);
} else {
dev_err(&pdev->dev, "%s: Failed to register BUS "
"scaling client!!\n", __func__);
@@ -1369,6 +1387,7 @@
return 0;
unconfig_gpio:
+ destroy_workqueue(ehci_wq);
msm_hsic_config_gpios(mehci, 0);
deinit_vddcx:
msm_hsic_init_vddcx(mehci, 0);
@@ -1396,6 +1415,14 @@
free_irq(mehci->wakeup_irq, mehci);
}
+ /*
+ * If the update request is called after unregister, the request will
+ * fail. Results are undefined if unregister is called in the middle of
+ * update request.
+ */
+ mehci->bus_vote = false;
+ cancel_work_sync(&mehci->bus_vote_w);
+
if (mehci->bus_perf_client)
msm_bus_scale_unregister_client(mehci->bus_perf_client);
@@ -1403,6 +1430,8 @@
device_init_wakeup(&pdev->dev, 0);
pm_runtime_set_suspended(&pdev->dev);
+ destroy_workqueue(ehci_wq);
+
usb_remove_hcd(hcd);
msm_hsic_config_gpios(mehci, 0);
msm_hsic_init_vddcx(mehci, 0);
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 366df67..c3f741b 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -495,6 +495,7 @@
/* explicitly set the driver mode to raw */
tty->raw = 1;
tty->real_raw = 1;
+ tty->update_room_in_ldisc = 1;
set_bit(TTY_NO_WRITE_SPLIT, &tty->flags);
dbg("%s", __func__);
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index d911b62..6d14ec1 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -50,6 +50,7 @@
static struct clk *mdp_lut_clk;
int mdp_rev;
int mdp_iommu_split_domain;
+u32 mdp_max_clk = 200000000;
static struct platform_device *mdp_init_pdev;
static struct regulator *footswitch;
@@ -2178,33 +2179,6 @@
__func__, mdp_hw_revision);
}
-#ifdef CONFIG_FB_MSM_MDP40
-static void configure_mdp_core_clk_table(uint32 min_clk_rate)
-{
- uint8 count;
- uint32 current_rate;
- if (mdp_clk && mdp_pdata && mdp_pdata->mdp_core_clk_table) {
- min_clk_rate = clk_round_rate(mdp_clk, min_clk_rate);
- if (clk_set_rate(mdp_clk, min_clk_rate) < 0)
- printk(KERN_ERR "%s: clk_set_rate failed\n",
- __func__);
- else {
- count = 0;
- current_rate = clk_get_rate(mdp_clk);
- while (count < mdp_pdata->num_mdp_clk) {
- if (mdp_pdata->mdp_core_clk_table[count]
- < current_rate) {
- mdp_pdata->
- mdp_core_clk_table[count] =
- current_rate;
- }
- count++;
- }
- }
- }
-}
-#endif
-
#ifdef CONFIG_MSM_BUS_SCALING
static uint32_t mdp_bus_scale_handle;
int mdp_bus_scale_update_request(uint32_t index)
@@ -2223,29 +2197,24 @@
}
#endif
DEFINE_MUTEX(mdp_clk_lock);
-int mdp_set_core_clk(uint16 perf_level)
+int mdp_set_core_clk(u32 rate)
{
int ret = -EINVAL;
- if (mdp_clk && mdp_pdata
- && mdp_pdata->mdp_core_clk_table) {
- if (perf_level > mdp_pdata->num_mdp_clk)
- printk(KERN_ERR "%s invalid perf level\n", __func__);
- else {
- mutex_lock(&mdp_clk_lock);
- ret = clk_set_rate(mdp_clk,
- mdp_pdata->
- mdp_core_clk_table[mdp_pdata->num_mdp_clk
- - perf_level]);
- mutex_unlock(&mdp_clk_lock);
- if (ret) {
- printk(KERN_ERR "%s unable to set mdp_core_clk rate\n",
- __func__);
- }
- }
- }
+ if (mdp_clk)
+ ret = clk_set_rate(mdp_clk, rate);
+ if (ret)
+ pr_err("%s unable to set mdp clk rate", __func__);
+ else
+ pr_debug("%s mdp clk rate to be set %d: actual rate %ld\n",
+ __func__, rate, clk_get_rate(mdp_clk));
return ret;
}
+int mdp_clk_round_rate(u32 rate)
+{
+ return clk_round_rate(mdp_clk, rate);
+}
+
unsigned long mdp_get_core_clk(void)
{
unsigned long clk_rate = 0;
@@ -2258,25 +2227,6 @@
return clk_rate;
}
-unsigned long mdp_perf_level2clk_rate(uint32 perf_level)
-{
- unsigned long clk_rate = 0;
-
- if (mdp_pdata && mdp_pdata->mdp_core_clk_table) {
- if (perf_level > mdp_pdata->num_mdp_clk) {
- printk(KERN_ERR "%s invalid perf level\n", __func__);
- clk_rate = mdp_get_core_clk();
- } else {
- clk_rate = mdp_pdata->
- mdp_core_clk_table[mdp_pdata->num_mdp_clk
- - perf_level];
- }
- } else
- clk_rate = mdp_get_core_clk();
-
- return clk_rate;
-}
-
static int mdp_irq_clk_setup(struct platform_device *pdev,
char cont_splashScreen)
{
@@ -2333,21 +2283,25 @@
}
#ifdef CONFIG_FB_MSM_MDP40
- /*
- * mdp_clk should greater than mdp_pclk always
- */
- if (mdp_pdata && mdp_pdata->mdp_core_clk_rate) {
- if (cont_splashScreen)
- mdp_clk_rate = clk_get_rate(mdp_clk);
- else
- mdp_clk_rate = mdp_pdata->mdp_core_clk_rate;
- mutex_lock(&mdp_clk_lock);
- clk_set_rate(mdp_clk, mdp_clk_rate);
- if (mdp_lut_clk != NULL)
- clk_set_rate(mdp_lut_clk, mdp_clk_rate);
- mutex_unlock(&mdp_clk_lock);
- }
+ if (mdp_pdata)
+ mdp_max_clk = mdp_pdata->mdp_max_clk;
+ else
+ pr_err("%s cannot get mdp max clk!\n", __func__);
+
+ if (!mdp_max_clk)
+ pr_err("%s mdp max clk is zero!\n", __func__);
+
+ if (cont_splashScreen)
+ mdp_clk_rate = clk_get_rate(mdp_clk);
+ else
+ mdp_clk_rate = mdp_max_clk;
+
+ mutex_lock(&mdp_clk_lock);
+ clk_set_rate(mdp_clk, mdp_clk_rate);
+ if (mdp_lut_clk != NULL)
+ clk_set_rate(mdp_lut_clk, mdp_clk_rate);
+ mutex_unlock(&mdp_clk_lock);
MSM_FB_DEBUG("mdp_clk: mdp_clk=%d\n", (int)clk_get_rate(mdp_clk));
#endif
@@ -2468,8 +2422,6 @@
mfd->ov1_wb_buf->size = 0;
mfd->mem_hid = 0;
}
- mfd->ov0_blt_state = 0;
- mfd->use_ov0_blt = 0 ;
/* initialize Post Processing data*/
mdp_hist_lut_init();
@@ -2568,7 +2520,6 @@
case MIPI_VIDEO_PANEL:
#ifndef CONFIG_FB_MSM_MDP303
mipi = &mfd->panel_info.mipi;
- configure_mdp_core_clk_table((mipi->dsi_pclk_rate) * 23 / 20);
mdp4_dsi_vsync_init(0);
mfd->hw_refresh = TRUE;
mfd->dma_fnc = mdp4_dsi_video_overlay;
@@ -2613,7 +2564,6 @@
#ifndef CONFIG_FB_MSM_MDP303
mfd->dma_fnc = mdp4_dsi_cmd_overlay;
mipi = &mfd->panel_info.mipi;
- configure_mdp_core_clk_table((mipi->dsi_pclk_rate) * 3 / 2);
mdp4_dsi_rdptr_init(0);
if (mfd->panel_info.pdest == DISPLAY_1) {
if_no = PRIMARY_INTF_SEL;
@@ -2698,8 +2648,6 @@
#ifdef CONFIG_FB_MSM_MDP40
mdp4_lcdc_vsync_init(0);
- configure_mdp_core_clk_table((mfd->panel_info.clk_rate)
- * 23 / 20);
if (mfd->panel.type == HDMI_PANEL) {
mfd->dma = &dma_e_data;
mdp4_display_intf_sel(EXTERNAL_INTF_SEL, LCDC_RGB_INTF);
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index 76d06a0..293bd9b 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -812,7 +812,9 @@
void mdp_disable_irq_nosync(uint32 term);
int mdp_get_bytes_per_pixel(uint32_t format,
struct msm_fb_data_type *mfd);
-int mdp_set_core_clk(uint16 perf_level);
+int mdp_set_core_clk(u32 rate);
+int mdp_clk_round_rate(u32 rate);
+
unsigned long mdp_get_core_clk(void);
unsigned long mdp_perf_level2clk_rate(uint32 perf_level);
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index cf8a9b2..cc4eae5 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -27,6 +27,7 @@
extern uint32 mdp4_extn_disp;
extern char *mmss_cc_base; /* mutimedia sub system clock control */
extern spinlock_t dsi_clk_lock;
+extern u32 mdp_max_clk;
#define MDP4_OVERLAYPROC0_BASE 0x10000
#define MDP4_OVERLAYPROC1_BASE 0x18000
@@ -361,6 +362,8 @@
uint32 blt_ov_done;
uint32 blt_dmap_koff;
uint32 blt_dmap_done;
+ uint32 req_clk;
+ uint32 req_bw;
uint32 luma_align_size;
struct mdp_overlay_pp_params pp_cfg;
struct mdp_overlay req_data;
@@ -610,9 +613,6 @@
void mdp4_lcdc_wait4vsync(int cndx, long long *vtime);
void mdp4_overlay_lcdc_vsync_push(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe);
-void mdp4_overlay_dtv_set_perf(struct msm_fb_data_type *mfd);
-void mdp4_update_perf_level(u32 perf_level);
-void mdp4_set_perf_level(void);
void mdp4_mddi_overlay_dmas_restore(void);
#ifndef CONFIG_FB_MSM_MIPI_DSI
@@ -728,6 +728,12 @@
{
/* empty */
}
+static inline void mdp4_dsi_cmd_blt_start(struct msm_fb_data_type *mfd)
+{
+}
+static inline void mdp4_dsi_cmd_blt_stop(struct msm_fb_data_type *mfd)
+{
+}
#endif /* CONFIG_FB_MSM_MIPI_DSI */
void mdp4_lcdc_overlay_blt(struct msm_fb_data_type *mfd,
@@ -914,6 +920,11 @@
int mdp4_v4l2_overlay_play(struct fb_info *info, struct mdp4_overlay_pipe *pipe,
unsigned long srcp0_addr, unsigned long srcp1_addr,
unsigned long srcp2_addr);
+int mdp4_overlay_mdp_pipe_req(struct mdp4_overlay_pipe *pipe,
+ struct msm_fb_data_type *mfd);
+int mdp4_overlay_mdp_perf_req(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *plist);
+void mdp4_overlay_mdp_perf_upd(struct msm_fb_data_type *mfd, int flag);
#ifndef CONFIG_FB_MSM_WRITEBACK_MSM_PANEL
static inline void mdp4_writeback_dma_busy_wait(struct msm_fb_data_type *mfd)
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index a6ffe82..f0a3639 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -104,7 +104,21 @@
static DEFINE_MUTEX(iommu_mutex);
static struct mdp4_overlay_ctrl *ctrl = &mdp4_overlay_db;
-static int new_perf_level;
+
+struct mdp4_overlay_perf {
+ u32 mdp_clk_rate;
+ u32 use_ov0_blt;
+ u32 use_ov1_blt;
+ u32 mdp_bw;
+};
+
+struct mdp4_overlay_perf perf_request = {
+ .mdp_bw = OVERLAY_PERF_LEVEL4,
+};
+struct mdp4_overlay_perf perf_current = {
+ .mdp_bw = OVERLAY_PERF_LEVEL4,
+};
+
static struct ion_client *display_iclient;
@@ -2114,79 +2128,6 @@
}
-static int mdp4_overlay_validate_downscale(struct mdp_overlay *req,
- struct msm_fb_data_type *mfd, uint32 perf_level, uint32 pclk_rate)
-{
- __u32 panel_clk_khz, mdp_clk_khz;
- __u32 num_hsync_pix_clks, mdp_clks_per_hsync, src_wh;
- __u32 hsync_period_ps, mdp_period_ps, total_hsync_period_ps;
- unsigned long fill_rate_y_dir, fill_rate_x_dir;
- unsigned long fillratex100, mdp_pixels_produced;
- unsigned long mdp_clk_hz;
-
- pr_debug("%s: LCDC Mode Downscale validation with MDP Core"
- " Clk rate\n", __func__);
- pr_debug("src_w %u, src_h %u, dst_w %u, dst_h %u\n",
- req->src_rect.w, req->src_rect.h, req->dst_rect.w,
- req->dst_rect.h);
-
-
- panel_clk_khz = pclk_rate/1000;
- mdp_clk_hz = mdp_perf_level2clk_rate(perf_level);
-
- if (!mdp_clk_hz || !req->dst_rect.w || !req->dst_rect.h) {
- pr_debug("mdp_perf_level2clk_rate returned 0,"
- "or dst_rect height/width is 0,"
- "Downscale Validation incomplete\n");
- return 0;
- }
-
- mdp_clk_khz = mdp_clk_hz/1000;
-
- num_hsync_pix_clks = mfd->panel_info.lcdc.h_back_porch +
- mfd->panel_info.lcdc.h_front_porch +
- mfd->panel_info.lcdc.h_pulse_width +
- mfd->panel_info.xres;
-
- hsync_period_ps = 1000000000/panel_clk_khz;
- mdp_period_ps = 1000000000/mdp_clk_khz;
-
- total_hsync_period_ps = num_hsync_pix_clks * hsync_period_ps;
- mdp_clks_per_hsync = total_hsync_period_ps/mdp_period_ps;
-
- pr_debug("hsync_period_ps %u, mdp_period_ps %u,"
- "total_hsync_period_ps %u\n", hsync_period_ps,
- mdp_period_ps, total_hsync_period_ps);
-
- src_wh = req->src_rect.w * req->src_rect.h;
- if (src_wh % req->dst_rect.h)
- fill_rate_y_dir = (src_wh / req->dst_rect.h) + 1;
- else
- fill_rate_y_dir = (src_wh / req->dst_rect.h);
-
- fill_rate_x_dir = (mfd->panel_info.xres - req->dst_rect.w)
- + req->src_rect.w;
-
- if (fill_rate_y_dir >= fill_rate_x_dir)
- fillratex100 = 100 * fill_rate_y_dir / mfd->panel_info.xres;
- else
- fillratex100 = 100 * fill_rate_x_dir / mfd->panel_info.xres;
-
- pr_debug("mdp_clks_per_hsync %u, fill_rate_y_dir %lu,"
- "fill_rate_x_dir %lu\n", mdp_clks_per_hsync,
- fill_rate_y_dir, fill_rate_x_dir);
-
- mdp_pixels_produced = 100 * mdp_clks_per_hsync/fillratex100;
- pr_debug("fillratex100 %lu, mdp_pixels_produced %lu\n",
- fillratex100, mdp_pixels_produced);
- if (mdp_pixels_produced <= mfd->panel_info.xres) {
- mdp4_stat.err_underflow++;
- return -ERANGE;
- }
-
- return 0;
-}
-
static int mdp4_overlay_req2pipe(struct mdp_overlay *req, int mixer,
struct mdp4_overlay_pipe **ppipe,
struct msm_fb_data_type *mfd)
@@ -2428,11 +2369,451 @@
pipe->transp = req->transp_mask;
+ pipe->flags = req->flags;
+
*ppipe = pipe;
return 0;
}
+static int mdp4_calc_pipe_mdp_clk(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ u32 pclk;
+ u32 xscale, yscale;
+ u32 hsync = 0;
+ u32 shift = 16;
+ u64 rst;
+ int ret = -EINVAL;
+
+ if (!pipe) {
+ pr_err("%s: pipe is null!\n", __func__);
+ pipe->req_bw = OVERLAY_PERF_LEVEL4;
+ return ret;
+ }
+ if (!mfd) {
+ pr_err("%s: mfd is null!\n", __func__);
+ pipe->req_bw = OVERLAY_PERF_LEVEL4;
+ return ret;
+ }
+
+ /*
+ * Serveral special cases require the max mdp clk but cannot
+ * be explained by mdp clk equation.
+ */
+ if (pipe->flags & MDP_DEINTERLACE) {
+ pr_info("%s deinterlace requires max mdp clk.\n",
+ __func__);
+ pipe->req_clk = mdp_max_clk;
+ return 0;
+ }
+
+ pr_debug("%s: pipe sets: panel res(x,y)=(%d,%d)\n",
+ __func__, mfd->panel_info.xres, mfd->panel_info.yres);
+ pr_debug("%s: src(w,h)(%d,%d),src(x,y)(%d,%d)\n",
+ __func__, pipe->src_w, pipe->src_h, pipe->src_x, pipe->src_y);
+ pr_debug("%s: dst(w,h)(%d,%d),dst(x,y)(%d,%d)\n",
+ __func__, pipe->dst_w, pipe->dst_h, pipe->dst_x, pipe->dst_y);
+
+ pclk = (mfd->panel_info.type == MIPI_VIDEO_PANEL ||
+ mfd->panel_info.type == MIPI_CMD_PANEL) ?
+ mfd->panel_info.mipi.dsi_pclk_rate :
+ mfd->panel_info.clk_rate;
+ if (!pclk) {
+ pipe->req_clk = mdp_max_clk;
+ pr_err("%s panel pixel clk is zero!\n", __func__);
+ return ret;
+ }
+ pr_debug("%s: mdp panel pixel clk is %d.\n",
+ __func__, pclk);
+
+ if (!pipe->dst_h) {
+ pr_err("%s: pipe dst_h is zero!\n", __func__);
+ pipe->req_clk = mdp_max_clk;
+ return ret;
+ }
+
+ if (!pipe->src_h) {
+ pr_err("%s: pipe src_h is zero!\n", __func__);
+ pipe->req_clk = mdp_max_clk;
+ return ret;
+ }
+
+ if (!pipe->dst_w) {
+ pr_err("%s: pipe dst_w is zero!\n", __func__);
+ pipe->req_clk = mdp_max_clk;
+ return ret;
+ }
+
+ if (!pipe->dst_h) {
+ pr_err("%s: pipe dst_h is zero!\n", __func__);
+ pipe->req_clk = mdp_max_clk;
+ return ret;
+ }
+
+ /*
+ * For the scaling cases, make more margin by removing porch
+ * values and adding extra 20%.
+ */
+ if ((pipe->src_h != pipe->dst_h) ||
+ (pipe->src_w != pipe->dst_w)) {
+ hsync = mfd->panel_info.xres;
+ hsync *= 100;
+ hsync /= 120;
+ pr_debug("%s: panel hsync is %d. with scaling\n",
+ __func__, hsync);
+
+ } else {
+ hsync = mfd->panel_info.lcdc.h_back_porch +
+ mfd->panel_info.lcdc.h_front_porch +
+ mfd->panel_info.lcdc.h_pulse_width +
+ mfd->panel_info.xres;
+ pr_debug("%s: panel hsync is %d.\n",
+ __func__, hsync);
+ }
+
+ if (!hsync) {
+ pipe->req_clk = mdp_max_clk;
+ pr_err("%s: panel hsync is zero!\n", __func__);
+ return 0;
+ }
+
+ xscale = mfd->panel_info.xres;
+ xscale += pipe->src_w;
+
+ if (xscale < pipe->dst_w) {
+ pipe->req_clk = mdp_max_clk;
+ pr_err("%s: xres+src_w cannot be less than dst_w!\n",
+ __func__);
+ return ret;
+ }
+
+ xscale -= pipe->dst_w;
+ xscale <<= shift;
+ xscale /= hsync;
+ pr_debug("%s: the right %d shifted xscale is %d.\n",
+ __func__, shift, xscale);
+
+ if (pipe->src_h > pipe->dst_h) {
+ yscale = pipe->src_h;
+ yscale <<= shift;
+ yscale /= pipe->dst_h;
+ } else { /* upscale */
+ yscale = pipe->dst_h;
+ yscale <<= shift;
+ yscale /= pipe->src_h;
+ }
+
+ yscale *= pipe->src_w;
+ yscale /= hsync;
+
+ pr_debug("%s: the right %d shifted yscale is %d.\n",
+ __func__, shift, yscale);
+
+ rst = pclk;
+ if (yscale > xscale)
+ rst *= yscale;
+ else
+ rst *= xscale;
+
+ rst >>= shift;
+
+ /*
+ * If the calculated mdp clk is less than panel pixel clk,
+ * most likely due to upscaling, mdp clk rate will be set to
+ * greater than pclk. Now the driver uses 1.15 as the
+ * factor. Ideally this factor is passed from board file.
+ */
+ if (rst < pclk) {
+ rst = ((pclk >> shift) * 23 / 20) << shift;
+ pr_debug("%s calculated mdp clk is less than pclk.\n",
+ __func__);
+ }
+
+ pipe->req_clk = (u32) rst;
+
+ pr_debug("%s: required mdp clk %d mixer %d pipe ndx %d\n",
+ __func__, pipe->req_clk, pipe->mixer_num, pipe->pipe_ndx);
+
+ return 0;
+}
+
+#define OVERLAY_VGA_SIZE 0x04B000
+#define OVERLAY_720P_TILE_SIZE 0x0E6000
+#define OVERLAY_WSVGA_SIZE 0x98000 /* 1024x608, align 600 to 32bit */
+
+#define OVERLAY_BUS_SCALE_TABLE_BASE 6
+
+
+static int mdp4_calc_pipe_mdp_bw(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *pipe)
+{
+ u32 res;
+ int ret = -EINVAL;
+
+ if (!pipe) {
+ pr_err("%s: pipe is null!\n", __func__);
+ return ret;
+ }
+ if (!mfd) {
+ pr_err("%s: mfd is null!\n", __func__);
+ return ret;
+ }
+
+ if (pipe->flags & MDP_DEINTERLACE) {
+ pr_info("%s deinterlace requires max mdp bw.\n",
+ __func__);
+ pipe->req_bw = OVERLAY_PERF_LEVEL1;
+ return 0;
+ }
+
+ if (pipe->pipe_type == OVERLAY_TYPE_BF) {
+ pipe->req_bw = OVERLAY_PERF_LEVEL4;
+ return 0;
+ }
+
+ res = pipe->src_w * pipe->src_h;
+
+ if (res <= OVERLAY_WSVGA_SIZE)
+ pipe->req_bw = OVERLAY_PERF_LEVEL4;
+ else if (res <= OVERLAY_VGA_SIZE)
+ pipe->req_bw = OVERLAY_PERF_LEVEL3;
+ else if (res <= OVERLAY_720P_TILE_SIZE)
+ pipe->req_bw = OVERLAY_PERF_LEVEL2;
+ else
+ pipe->req_bw = OVERLAY_PERF_LEVEL1;
+
+ return 0;
+}
+
+int mdp4_overlay_mdp_perf_req(struct msm_fb_data_type *mfd,
+ struct mdp4_overlay_pipe *plist)
+{
+ u32 worst_mdp_clk = 0;
+ u32 worst_mdp_bw = OVERLAY_PERF_LEVEL4;
+ int i;
+ struct mdp4_overlay_perf *perf_req = &perf_request;
+ struct mdp4_overlay_pipe *pipe = plist;
+ u32 cnt = 0;
+ int ret = -EINVAL;
+
+ if (!mfd) {
+ pr_err("%s: mfd is null!\n", __func__);
+ return ret;
+ }
+
+ if (!plist) {
+ pr_err("%s: plist is null!\n", __func__);
+ return ret;
+ }
+
+ perf_req->use_ov0_blt = 0;
+ perf_req->use_ov1_blt = 0;
+
+ for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
+
+ if (!pipe)
+ return ret;
+
+ if (!pipe->pipe_used)
+ continue;
+ cnt++;
+ if (worst_mdp_clk < pipe->req_clk)
+ worst_mdp_clk = pipe->req_clk;
+ if (pipe->req_clk > mdp_max_clk) {
+ if (pipe->mixer_num == MDP4_MIXER0)
+ perf_req->use_ov0_blt = 1;
+ if (pipe->mixer_num == MDP4_MIXER1)
+ perf_req->use_ov1_blt = 1;
+ }
+
+ if (!pipe->req_bw) {
+ pr_err("%s mdp pipe bw request should not be zero!\n",
+ __func__);
+ pr_debug("%s %d pid %d num %d idx %d mix %d bw %d\n",
+ __func__, __LINE__, current->pid,
+ pipe->pipe_num, pipe->pipe_ndx,
+ pipe->mixer_num, pipe->req_bw);
+ pipe->req_bw = OVERLAY_PERF_LEVEL4;
+ }
+
+ if (pipe->req_bw < worst_mdp_bw)
+ worst_mdp_bw = pipe->req_bw;
+
+ if (mfd->mdp_rev == MDP_REV_41) {
+ /*
+ * writeback (blt) mode to provide work around
+ * for dsi cmd mode interface hardware bug.
+ */
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
+ if (pipe->dst_x != 0)
+ perf_req->use_ov0_blt = 1;
+ }
+ if ((mfd->panel_info.xres > 1280) &&
+ (mfd->panel_info.type != DTV_PANEL)) {
+ perf_req->use_ov0_blt = 1;
+ }
+ }
+ }
+
+ perf_req->mdp_clk_rate = worst_mdp_clk;
+ if (perf_req->mdp_clk_rate > mdp_max_clk)
+ perf_req->mdp_clk_rate = mdp_max_clk;
+
+ perf_req->mdp_clk_rate = mdp_clk_round_rate(perf_req->mdp_clk_rate);
+
+ perf_req->mdp_bw = worst_mdp_bw;
+
+ if (cnt >= 3)
+ perf_req->mdp_bw = OVERLAY_PERF_LEVEL1;
+
+ pr_debug("%s %d pid %d cnt %d clk %d ov0_blt %d, ov1_blt %d bw %d\n",
+ __func__, __LINE__, current->pid, cnt,
+ perf_req->mdp_clk_rate,
+ perf_req->use_ov0_blt,
+ perf_req->use_ov1_blt,
+ perf_req->mdp_bw);
+
+ return 0;
+}
+
+int mdp4_overlay_mdp_pipe_req(struct mdp4_overlay_pipe *pipe,
+ struct msm_fb_data_type *mfd)
+{
+ int ret = 0;
+
+ if (mdp4_calc_pipe_mdp_clk(mfd, pipe)) {
+ pr_err("%s unable to calc mdp pipe clk rate ret=%d\n",
+ __func__, ret);
+ ret = -EINVAL;
+ }
+ if (mdp4_calc_pipe_mdp_bw(mfd, pipe)) {
+ pr_err("%s unable to calc mdp pipe bandwidth ret=%d\n",
+ __func__, ret);
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+void mdp4_overlay_mdp_perf_upd(struct msm_fb_data_type *mfd,
+ int flag)
+{
+ struct mdp4_overlay_perf *perf_req = &perf_request;
+ struct mdp4_overlay_perf *perf_cur = &perf_current;
+
+ pr_debug("%s %d: req mdp clk %d, cur mdp clk %d flag %d\n",
+ __func__, __LINE__,
+ perf_req->mdp_clk_rate,
+ perf_cur->mdp_clk_rate,
+ flag);
+
+ if (!mdp4_extn_disp)
+ perf_cur->use_ov1_blt = 0;
+
+ if (flag) {
+ if (perf_req->mdp_clk_rate > perf_cur->mdp_clk_rate) {
+ mdp_set_core_clk(perf_req->mdp_clk_rate);
+ pr_info("%s mdp clk is changed [%d] from %d to %d\n",
+ __func__,
+ flag,
+ perf_cur->mdp_clk_rate,
+ perf_req->mdp_clk_rate);
+ perf_cur->mdp_clk_rate =
+ perf_req->mdp_clk_rate;
+ }
+ if (perf_req->mdp_bw < perf_cur->mdp_bw) {
+ mdp_bus_scale_update_request
+ (OVERLAY_BUS_SCALE_TABLE_BASE -
+ perf_req->mdp_bw);
+ pr_info("%s mdp bw is changed [%d] from %d to %d\n",
+ __func__,
+ flag,
+ perf_cur->mdp_bw,
+ perf_req->mdp_bw);
+ perf_cur->mdp_bw = perf_req->mdp_bw;
+ }
+ if (mfd->panel_info.pdest == DISPLAY_1 &&
+ perf_req->use_ov0_blt && !perf_cur->use_ov0_blt) {
+ mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
+ if (mfd->panel_info.type == LCDC_PANEL ||
+ mfd->panel_info.type == LVDS_PANEL)
+ mdp4_lcdc_overlay_blt_start(mfd);
+ else if (mfd->panel_info.type == MIPI_VIDEO_PANEL)
+ mdp4_dsi_video_blt_start(mfd);
+ else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
+ mdp4_dsi_cmd_blt_start(mfd);
+ pr_info("%s mixer0 start blt [%d] from %d to %d.\n",
+ __func__,
+ flag,
+ perf_cur->use_ov0_blt,
+ perf_req->use_ov0_blt);
+ perf_cur->use_ov0_blt = perf_req->use_ov0_blt;
+ }
+ if (mfd->panel_info.pdest == DISPLAY_2 &&
+ perf_req->use_ov1_blt && !perf_cur->use_ov1_blt) {
+ mdp4_allocate_writeback_buf(mfd, MDP4_MIXER1);
+ mdp4_dtv_overlay_blt_start(mfd);
+ pr_info("%s mixer1 start blt [%d] from %d to %d.\n",
+ __func__,
+ flag,
+ perf_cur->use_ov1_blt,
+ perf_req->use_ov1_blt);
+ perf_cur->use_ov1_blt = perf_req->use_ov1_blt;
+ }
+ } else {
+ if (perf_req->mdp_clk_rate < perf_cur->mdp_clk_rate) {
+ pr_info("%s mdp clk is changed [%d] from %d to %d\n",
+ __func__,
+ flag,
+ perf_cur->mdp_clk_rate,
+ perf_req->mdp_clk_rate);
+ mdp_set_core_clk(perf_req->mdp_clk_rate);
+ perf_cur->mdp_clk_rate =
+ perf_req->mdp_clk_rate;
+ }
+ if (perf_req->mdp_bw > perf_cur->mdp_bw) {
+ pr_info("%s mdp bw is changed [%d] from %d to %d\n",
+ __func__,
+ flag,
+ perf_cur->mdp_bw,
+ perf_req->mdp_bw);
+ mdp_bus_scale_update_request
+ (OVERLAY_BUS_SCALE_TABLE_BASE -
+ perf_req->mdp_bw);
+ perf_cur->mdp_bw = perf_req->mdp_bw;
+ }
+ if (mfd->panel_info.pdest == DISPLAY_1 &&
+ !perf_req->use_ov0_blt && perf_cur->use_ov0_blt) {
+ if (mfd->panel_info.type == LCDC_PANEL ||
+ mfd->panel_info.type == LVDS_PANEL)
+ mdp4_lcdc_overlay_blt_stop(mfd);
+ else if (mfd->panel_info.type == MIPI_VIDEO_PANEL)
+ mdp4_dsi_video_blt_stop(mfd);
+ else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
+ mdp4_dsi_cmd_blt_stop(mfd);
+ mdp4_free_writeback_buf(mfd, MDP4_MIXER0);
+ pr_info("%s mixer0 stop blt [%d] from %d to %d.\n",
+ __func__,
+ flag,
+ perf_cur->use_ov0_blt,
+ perf_req->use_ov0_blt);
+ perf_cur->use_ov0_blt = perf_req->use_ov0_blt;
+ }
+ if (mfd->panel_info.pdest == DISPLAY_2 &&
+ !perf_req->use_ov1_blt && perf_cur->use_ov1_blt) {
+ mdp4_dtv_overlay_blt_stop(mfd);
+ mdp4_free_writeback_buf(mfd, MDP4_MIXER1);
+ pr_info("%s mixer1 stop blt [%d] from %d to %d.\n",
+ __func__,
+ flag,
+ perf_cur->use_ov1_blt,
+ perf_req->use_ov1_blt);
+ perf_cur->use_ov1_blt = perf_req->use_ov1_blt;
+ }
+ }
+ return;
+}
+
static int get_img(struct msmfb_data *img, struct fb_info *info,
struct mdp4_overlay_pipe *pipe, unsigned int plane,
unsigned long *start, unsigned long *len, struct file **srcp_file,
@@ -2555,154 +2936,10 @@
return 0;
}
-#define OVERLAY_VGA_SIZE 0x04B000
-#define OVERLAY_720P_TILE_SIZE 0x0E6000
-#define OVERLAY_WSVGA_SIZE 0x98000 /* 1024x608, align 600 to 32bit */
-
-#define OVERLAY_BUS_SCALE_TABLE_BASE 6
-
-static int mdp4_overlay_is_rgb_type(int format)
-{
- switch (format) {
- case MDP_RGB_565:
- case MDP_RGB_888:
- case MDP_BGR_565:
- case MDP_XRGB_8888:
- case MDP_ARGB_8888:
- case MDP_RGBA_8888:
- case MDP_BGRA_8888:
- case MDP_RGBX_8888:
- return 1;
- default:
- return 0;
- }
-}
-
-static uint32 mdp4_overlay_get_perf_level(struct mdp_overlay *req,
- struct msm_fb_data_type *mfd)
-{
- int is_fg = 0, i, cnt;
-
- if (req->is_fg && ((req->alpha & 0x0ff) == 0xff))
- is_fg = 1;
-
- if (mdp4_extn_disp)
- return OVERLAY_PERF_LEVEL1;
-
- if (req->flags & (MDP_DEINTERLACE | MDP_BACKEND_COMPOSITION))
- return OVERLAY_PERF_LEVEL1;
-
- for (i = 0, cnt = 0; i < OVERLAY_PIPE_MAX; i++) {
- if (ctrl->plist[i].pipe_used && ++cnt > 2)
- return OVERLAY_PERF_LEVEL1;
- }
-
- if (mdp4_overlay_is_rgb_type(req->src.format) && is_fg &&
- ((req->src.width * req->src.height) <= OVERLAY_WSVGA_SIZE))
- return OVERLAY_PERF_LEVEL4;
- else if (mdp4_overlay_is_rgb_type(req->src.format))
- return OVERLAY_PERF_LEVEL1;
-
- if (req->src.width*req->src.height <= OVERLAY_VGA_SIZE) {
- if (mfd->mdp_rev >= MDP_REV_42)
- return OVERLAY_PERF_LEVEL4;
- else
- return OVERLAY_PERF_LEVEL3;
-
- } else if (req->src.width*req->src.height <= OVERLAY_720P_TILE_SIZE) {
- u32 max, min;
- max = (req->dst_rect.h > req->dst_rect.w) ?
- req->dst_rect.h : req->dst_rect.w;
- min = (mfd->panel_info.yres > mfd->panel_info.xres) ?
- mfd->panel_info.xres : mfd->panel_info.yres;
- if (max > min) /* landscape mode */
- return OVERLAY_PERF_LEVEL3;
- else /* potrait mode */
- return OVERLAY_PERF_LEVEL2;
- }
- else
- return OVERLAY_PERF_LEVEL1;
-}
-
-void mdp4_update_perf_level(u32 perf_level)
-{
- static int first = 1;
-
- new_perf_level = perf_level;
-
- if (first) {
- first = 0;
- mdp4_set_perf_level();
- }
-}
-
-void mdp4_set_perf_level(void)
-{
- static int old_perf_level;
- int cur_perf_level;
-
- if (mdp4_extn_disp)
- cur_perf_level = OVERLAY_PERF_LEVEL1;
- else
- cur_perf_level = new_perf_level;
-
- if (old_perf_level != cur_perf_level) {
- mdp_set_core_clk(cur_perf_level);
- old_perf_level = cur_perf_level;
- mdp_bus_scale_update_request(OVERLAY_BUS_SCALE_TABLE_BASE
- - cur_perf_level);
- }
-}
-
-static u32 mdp4_overlay_blt_enable(struct mdp_overlay *req,
- struct msm_fb_data_type *mfd, uint32 perf_level)
-{
- u32 clk_rate = mfd->panel_info.clk_rate;
- u32 blt_chq_req = 0, use_blt = 0;
-
- if ((mfd->panel_info.type == MIPI_VIDEO_PANEL) ||
- (mfd->panel_info.type == MIPI_CMD_PANEL))
- clk_rate = (&mfd->panel_info.mipi)->dsi_pclk_rate;
-
- if ((mfd->panel_info.type == LCDC_PANEL) ||
- (mfd->panel_info.type == MIPI_VIDEO_PANEL) ||
- (mfd->panel_info.type == DTV_PANEL) ||
- (mfd->panel_info.type == MIPI_CMD_PANEL))
- blt_chq_req = 1;
-
- if (blt_chq_req && (req->src_rect.h > req->dst_rect.h ||
- req->src_rect.w > req->dst_rect.w)) {
- if (mdp4_overlay_validate_downscale(req, mfd, perf_level,
- clk_rate))
- use_blt = 1;
- }
-
- if (mfd->panel_info.type == MDDI_PANEL) {
- if ((req->src_rect.h/2) >= req->dst_rect.h ||
- (req->src_rect.w/2) >= req->dst_rect.w)
- use_blt = 1;
- }
-
- if (mfd->mdp_rev == MDP_REV_41) {
- /*
- * writeback (blt) mode to provide work around for
- * dsi cmd mode interface hardware bug.
- */
- if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
- if (req->dst_rect.x != 0)
- use_blt = 1;
- }
- if ((mfd->panel_info.xres > 1280) &&
- (mfd->panel_info.type != DTV_PANEL))
- use_blt = 1;
- }
- return use_blt;
-}
-
int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
- int ret, mixer, perf_level;
+ int ret, mixer;
struct mdp4_overlay_pipe *pipe;
if (mfd == NULL) {
@@ -2732,20 +2969,10 @@
return ret;
}
- perf_level = mdp4_overlay_get_perf_level(req, mfd);
-
- if (mixer == MDP4_MIXER0) {
- u32 use_blt = mdp4_overlay_blt_enable(req, mfd, perf_level);
- mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
- mfd->use_ov0_blt |= (use_blt << (pipe->pipe_ndx-1));
- }
-
/* return id back to user */
req->id = pipe->pipe_ndx; /* pipe_ndx start from 1 */
pipe->req_data = *req; /* keep original req */
- pipe->flags = req->flags;
-
if (!IS_ERR_OR_NULL(mfd->iclient)) {
pr_debug("pipe->flags 0x%x\n", pipe->flags);
if (pipe->flags & MDP_SECURE_OVERLAY_SESSION) {
@@ -2768,47 +2995,8 @@
__func__);
}
- if (ctrl->panel_mode & MDP4_PANEL_DTV &&
- pipe->mixer_num == MDP4_MIXER1) {
- u32 use_blt = mdp4_overlay_blt_enable(req, mfd, perf_level);
+ mdp4_overlay_mdp_pipe_req(pipe, mfd);
- if (hdmi_prim_display) {
- if (!mdp4_overlay_is_rgb_type(req->src.format) &&
- pipe->pipe_type == OVERLAY_TYPE_VIDEO &&
- (req->src_rect.h > req->dst_rect.h ||
- req->src_rect.w > req->dst_rect.w))
- use_blt = 1;
- }
-
- mdp4_overlay_dtv_set(mfd, pipe);
- mfd->use_ov1_blt &= ~(1 << (pipe->pipe_ndx-1));
- mfd->use_ov1_blt |= (use_blt << (pipe->pipe_ndx-1));
- }
-
- if (new_perf_level != perf_level) {
- u32 old_level = new_perf_level;
- mdp4_update_perf_level(perf_level);
-
- /* change clck base on perf level */
- if (pipe->mixer_num == MDP4_MIXER0) {
- if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
- if (old_level > perf_level)
- mdp4_set_perf_level();
- } else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
- mdp4_set_perf_level();
- } else if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
- if (old_level > perf_level)
- mdp4_set_perf_level();
- } else if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
- mdp4_mddi_dma_busy_wait(mfd);
- mdp4_mddi_blt_dmap_busy_wait(mfd);
- mdp4_set_perf_level();
- }
- } else {
- if (ctrl->panel_mode & MDP4_PANEL_DTV)
- mdp4_overlay_dtv_set_perf(mfd);
- }
- }
mutex_unlock(&mfd->dma->ov_mutex);
return 0;
@@ -2864,7 +3052,6 @@
else {
/* mixer 0 */
ctrl->mixer0_played = 0;
-
if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
if (mfd->panel_power_on)
mdp4_mddi_blt_dmap_busy_wait(mfd);
@@ -2879,13 +3066,9 @@
if (mfd->panel_power_on)
mdp4_mddi_overlay_restore();
}
-
- mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
} else { /* mixer1, DTV, ATV */
- if (ctrl->panel_mode & MDP4_PANEL_DTV) {
+ if (ctrl->panel_mode & MDP4_PANEL_DTV)
mdp4_overlay_dtv_unset(mfd, pipe);
- mfd->use_ov1_blt &= ~(1 << (pipe->pipe_ndx-1));
- }
}
mdp4_stat.overlay_unset[pipe->mixer_num]++;
@@ -3002,7 +3185,6 @@
pr_debug("%s: pipe=%x ndx=%d num=%d used=%d\n", __func__,
(int) pipe, pipe->pipe_ndx, pipe->pipe_num, pipe->pipe_used);
-
mdp4_overlay_reg_flush(pipe, 1);
mdp4_mixer_stage_up(pipe);
}
@@ -3148,6 +3330,7 @@
}
}
+ mdp4_overlay_mdp_perf_req(mfd, ctrl->plist);
if (pipe->mixer_num == MDP4_MIXER2 ||
ctrl->panel_mode & MDP4_PANEL_MDDI)
@@ -3173,7 +3356,6 @@
return ret;
mddi:
-
if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */
} else {
diff --git a/drivers/video/msm/mdp4_overlay_atv.c b/drivers/video/msm/mdp4_overlay_atv.c
index 753ff23..3fe00ed 100644
--- a/drivers/video/msm/mdp4_overlay_atv.c
+++ b/drivers/video/msm/mdp4_overlay_atv.c
@@ -110,7 +110,6 @@
mdp4_overlay_dmae_xy(pipe); /* dma_e */
mdp4_overlay_dmae_cfg(mfd, 1);
-
mdp4_overlay_rgb_setup(pipe);
mdp4_overlayproc_cfg(pipe);
@@ -183,6 +182,8 @@
} else {
pipe->srcp0_addr = (uint32)(buf + buf_offset);
}
+ mdp4_overlay_mdp_perf_req(pipe, mfd);
+ mdp4_overlay_mdp_perf_upd(mfd, 1);
mdp4_overlay_rgb_setup(pipe);
mdp4_overlay_reg_flush(pipe, 0);
mdp4_mixer_stage_up(pipe);
@@ -201,10 +202,7 @@
spin_unlock_irqrestore(&mdp_spin_lock, flag);
wait_for_completion_killable(&atv_pipe->comp);
mdp_disable_irq(MDP_OVERLAY1_TERM);
-
- /* change mdp clk while mdp is idle` */
- mdp4_set_perf_level();
-
+ mdp4_overlay_mdp_perf_upd(mfd, 0);
mdp4_stat.kickoff_atv++;
mutex_unlock(&mfd->dma->ov_mutex);
}
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index e1fa02e..05a89b8 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -864,6 +864,7 @@
/* disable dsi trigger */
MDP_OUTP(MDP_BASE + 0x000a4, 0x00);
+
mdp4_overlay_setup_pipe_addr(mfd, pipe);
mdp4_overlay_rgb_setup(pipe);
@@ -1098,18 +1099,12 @@
mdp4_dsi_cmd_pipe_queue(0, pipe);
}
- if (mfd->use_ov0_blt != mfd->ov0_blt_state) {
-
- if (mfd->use_ov0_blt)
- mdp4_dsi_cmd_do_blt(mfd, 1);
- else
- mdp4_dsi_cmd_do_blt(mfd, 0);
-
- mfd->ov0_blt_state = mfd->use_ov0_blt;
- }
+ mdp4_overlay_mdp_perf_upd(mfd, 1);
mdp4_dsi_cmd_pipe_commit();
mdp4_dsi_cmd_wait4vsync(0, &xx);
vctrl->expire_tick = VSYNC_EXPIRE_TICK;
vctrl->clk_control = 1;
+
+ mdp4_overlay_mdp_perf_upd(mfd, 0);
}
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 851a9ad..a8b906a 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -122,9 +122,6 @@
return;
}
- /* start timing generator & mmu if they are not started yet */
- mdp4_overlay_dsi_video_start();
-
vctrl = &vsync_ctrl_db[cndx];
if (atomic_read(&vctrl->suspend) > 0)
@@ -196,6 +193,8 @@
}
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+ mdp4_overlay_mdp_perf_upd(vctrl->mfd, 1);
+
if (vctrl->blt_change) {
pipe = vctrl->base_pipe;
spin_lock_irqsave(&vctrl->spin_lock, flags);
@@ -209,6 +208,7 @@
}
pipe = vp->plist;
+
for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
if (pipe->pipe_used) {
cnt++;
@@ -224,6 +224,9 @@
mdp4_mixer_stage_commit(mixer);
+ /* start timing generator & mmu if they are not started yet */
+ mdp4_overlay_dsi_video_start();
+
pipe = vctrl->base_pipe;
spin_lock_irqsave(&vctrl->spin_lock, flags);
if (pipe->ov_blt_addr) {
@@ -539,6 +542,8 @@
pipe->dst_h = fbi->var.yres;
pipe->dst_w = fbi->var.xres;
+ mdp4_overlay_mdp_pipe_req(pipe, mfd);
+
atomic_set(&vctrl->suspend, 0);
mdp4_overlay_dmap_xy(pipe); /* dma_p */
@@ -820,13 +825,6 @@
MDP_OUTP(MDP_BASE + 0x90008, addr);
}
-void mdp4_overlay_dsi_video_set_perf(struct msm_fb_data_type *mfd)
-{
- /* change mdp clk while mdp is idle */
- mdp4_set_perf_level();
-}
-
-
/*
* mdp4_primary_vsync_dsi_video: called from isr
*/
@@ -928,8 +926,6 @@
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
- mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
-
if (mfd->ov0_wb_buf->write_addr == 0) {
pr_info("%s: no blt_base assigned\n", __func__);
return;
@@ -1011,15 +1007,7 @@
mdp4_dsi_video_pipe_queue(0, pipe);
}
- if (mfd->use_ov0_blt != mfd->ov0_blt_state) {
-
- if (mfd->use_ov0_blt)
- mdp4_dsi_video_do_blt(mfd, 1);
- else
- mdp4_dsi_video_do_blt(mfd, 0);
-
- mfd->ov0_blt_state = mfd->use_ov0_blt;
- }
+ mdp4_overlay_mdp_perf_upd(mfd, 1);
mdp4_dsi_video_pipe_commit();
@@ -1027,5 +1015,7 @@
mdp4_dsi_video_wait4ov(0);
else
mdp4_dsi_video_wait4dmap(0);
+
+ mdp4_overlay_mdp_perf_upd(mfd, 0);
}
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index d0d4f40..d22de54 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -141,9 +141,6 @@
return;
}
- /* start timing generator & mmu if they are not started yet */
- mdp4_overlay_dtv_start();
-
vctrl = &vsync_ctrl_db[cndx];
if (atomic_read(&vctrl->suspend) > 0)
@@ -210,6 +207,9 @@
}
mdp4_mixer_stage_commit(mixer);
+ /* start timing generator & mmu if they are not started yet */
+ mdp4_overlay_dtv_start();
+
pipe = vctrl->base_pipe;
spin_lock_irqsave(&vctrl->spin_lock, flags);
if (pipe->ov_blt_addr) {
@@ -647,8 +647,7 @@
void mdp4_overlay_dtv_set_perf(struct msm_fb_data_type *mfd)
{
- /* change mdp clk while mdp is idle` */
- mdp4_set_perf_level();
+
}
static void mdp4_overlay_dtv_alloc_pipe(struct msm_fb_data_type *mfd,
@@ -701,12 +700,16 @@
pipe->src_width = fbi->var.xres;
pipe->src_h = fbi->var.yres;
pipe->src_w = fbi->var.xres;
+ pipe->dst_h = fbi->var.yres;
+ pipe->dst_w = fbi->var.xres;
pipe->src_y = 0;
pipe->src_x = 0;
pipe->dst_h = fbi->var.yres;
pipe->dst_w = fbi->var.xres;
pipe->srcp0_ystride = fbi->fix.line_length;
+ mdp4_overlay_mdp_pipe_req(pipe, mfd);
+
ret = mdp4_overlay_format2pipe(pipe);
if (ret < 0)
pr_warn("%s: format2type failed\n", __func__);
@@ -838,6 +841,7 @@
} else {
mdp4_overlay_dma_commit(MDP4_MIXER1);
}
+
vsync_irq_disable(INTR_DMA_E_DONE, MDP_DMA_E_TERM);
spin_unlock(&vctrl->spin_lock);
}
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index feba8b8..4a478cd 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -128,9 +128,6 @@
return;
}
- /* start timing generator & mmu if they are not started yet */
- mdp4_overlay_lcdc_start();
-
vctrl = &vsync_ctrl_db[cndx];
if (atomic_read(&vctrl->suspend) > 0)
@@ -201,6 +198,8 @@
}
spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+ mdp4_overlay_mdp_perf_upd(vctrl->mfd, 1);
+
if (vctrl->blt_change) {
pipe = vctrl->base_pipe;
spin_lock_irqsave(&vctrl->spin_lock, flags);
@@ -229,6 +228,9 @@
mdp4_mixer_stage_commit(mixer);
+ /* start timing generator & mmu if they are not started yet */
+ mdp4_overlay_lcdc_start();
+
pipe = vctrl->base_pipe;
spin_lock_irqsave(&vctrl->spin_lock, flags);
if (pipe->ov_blt_addr) {
@@ -513,6 +515,8 @@
pipe->srcp0_ystride = fbi->fix.line_length;
pipe->bpp = bpp;
+ mdp4_overlay_mdp_pipe_req(pipe, mfd);
+
atomic_set(&vctrl->suspend, 0);
mdp4_overlay_dmap_xy(pipe);
@@ -714,12 +718,6 @@
MDP_OUTP(MDP_BASE + 0x90008, addr);
}
-void mdp4_overlay_lcdc_set_perf(struct msm_fb_data_type *mfd)
-{
- /* change mdp clk while mdp is idle */
- mdp4_set_perf_level();
-}
-
/*
* mdp4_primary_vsync_lcdc: called from isr
*/
@@ -900,15 +898,7 @@
mdp4_lcdc_pipe_queue(0, pipe);
}
- if (mfd->use_ov0_blt != mfd->ov0_blt_state) {
-
- if (mfd->use_ov0_blt)
- mdp4_lcdc_do_blt(mfd, 1);
- else
- mdp4_lcdc_do_blt(mfd, 0);
-
- mfd->ov0_blt_state = mfd->use_ov0_blt;
- }
+ mdp4_overlay_mdp_perf_upd(mfd, 1);
mdp4_lcdc_pipe_commit();
@@ -916,4 +906,6 @@
mdp4_lcdc_wait4ov(0);
else
mdp4_lcdc_wait4dmap(0);
+
+ mdp4_overlay_mdp_perf_upd(mfd, 0);
}
diff --git a/drivers/video/msm/mdp4_overlay_mddi.c b/drivers/video/msm/mdp4_overlay_mddi.c
index 103419e..d10e669 100644
--- a/drivers/video/msm/mdp4_overlay_mddi.c
+++ b/drivers/video/msm/mdp4_overlay_mddi.c
@@ -574,8 +574,6 @@
struct mdp4_overlay_pipe *pipe)
{
unsigned long flag;
- /* change mdp clk while mdp is idle` */
- mdp4_set_perf_level();
mdp_enable_irq(MDP_OVERLAY0_TERM);
spin_lock_irqsave(&mdp_spin_lock, flag);
@@ -660,9 +658,6 @@
void mdp4_mddi_dma_s_kickoff(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe)
{
- /* change mdp clk while mdp is idle` */
- mdp4_set_perf_level();
-
mdp_enable_irq(MDP_DMA_S_TERM);
if (mddi_pipe->ov_blt_addr == 0)
@@ -698,9 +693,10 @@
if (mddi_pipe && mddi_pipe->ov_blt_addr)
mdp4_mddi_blt_dmap_busy_wait(mfd);
-
+ mdp4_overlay_mdp_perf_upd(mfd, 0);
mdp4_overlay_update_lcd(mfd);
+ mdp4_overlay_mdp_perf_upd(mfd, 1);
if (mdp_hw_revision < MDP4_REVISION_V2_1) {
/* dmas dmap switch */
if (mdp4_overlay_mixer_play(mddi_pipe->mixer_num)
diff --git a/drivers/video/msm/mdp4_overlay_writeback.c b/drivers/video/msm/mdp4_overlay_writeback.c
index 9c06992..d8e4be4 100644
--- a/drivers/video/msm/mdp4_overlay_writeback.c
+++ b/drivers/video/msm/mdp4_overlay_writeback.c
@@ -174,6 +174,8 @@
pipe->dst_y = 0;
pipe->dst_x = 0;
+ mdp4_overlay_mdp_pipe_req(pipe, mfd);
+
if (mfd->display_iova)
pipe->srcp0_addr = mfd->display_iova + buf_offset;
else
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index e76b8ba..ca73a70 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -249,7 +249,7 @@
/* MDP cmd block enable */
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- mdp4_update_perf_level(OVERLAY_PERF_LEVEL4);
+ mdp_bus_scale_update_request(5);
#ifdef MDP4_ERROR
/*
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_video.c b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
index 2f0a1f5..bc64d2e 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_video.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_video.c
@@ -304,7 +304,7 @@
itp.h_back_porch = pinfo->lcdc.h_back_porch;
itp.h_front_porch = pinfo->lcdc.h_front_porch;
itp.v_back_porch = pinfo->lcdc.v_back_porch;
- itp.v_front_porch = pinfo->lcdc.h_front_porch;
+ itp.v_front_porch = pinfo->lcdc.v_front_porch;
itp.hsync_pulse_width = pinfo->lcdc.h_pulse_width;
itp.vsync_pulse_width = pinfo->lcdc.v_pulse_width;
diff --git a/drivers/video/msm/msm_fb.h b/drivers/video/msm/msm_fb.h
index efe6160..ae5acf4 100644
--- a/drivers/video/msm/msm_fb.h
+++ b/drivers/video/msm/msm_fb.h
@@ -184,8 +184,6 @@
u32 ov_start;
u32 mem_hid;
u32 mdp_rev;
- u32 use_ov0_blt, ov0_blt_state;
- u32 use_ov1_blt, ov1_blt_state;
u32 writeback_state;
bool writeback_active_cnt;
int cont_splash_done;
diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h
index 7769950..c953613 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -112,7 +112,7 @@
#define EVENT_LAST_ID 0x08AD
#define MSG_SSID_0 0
-#define MSG_SSID_0_LAST 91
+#define MSG_SSID_0_LAST 93
#define MSG_SSID_1 500
#define MSG_SSID_1_LAST 506
#define MSG_SSID_2 1000
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h
index f1e2527..771cb35 100644
--- a/include/linux/irqdesc.h
+++ b/include/linux/irqdesc.h
@@ -154,6 +154,14 @@
return desc->status_use_accessors & IRQ_NO_BALANCING_MASK;
}
+static inline int irq_is_per_cpu(unsigned int irq)
+{
+ struct irq_desc *desc;
+
+ desc = irq_to_desc(irq);
+ return desc->status_use_accessors & IRQ_PER_CPU;
+}
+
static inline void
irq_set_lockdep_class(unsigned int irq, struct lock_class_key *class)
{
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index bbd032d..d17125a 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -116,7 +116,8 @@
* @r_sense: sense resistor value in (mOhms)
* @i_test: current at which the unusable charger cutoff is to be
* calculated or the peak system current (mA)
- * @v_failure: the voltage at which the battery is considered empty(mV)
+ * @v_cutoff: the loaded voltage at which the battery
+ * is considered empty(mV)
* @enable_fcc_learning: if set the driver will learn full charge
* capacity of the battery upon end of charge
*/
@@ -125,10 +126,11 @@
enum battery_type battery_type;
unsigned int r_sense;
unsigned int i_test;
- unsigned int v_failure;
+ unsigned int v_cutoff;
unsigned int max_voltage_uv;
unsigned int rconn_mohm;
int enable_fcc_learning;
+ int shutdown_soc_valid_limit;
};
#if defined(CONFIG_PM8921_BMS) || defined(CONFIG_PM8921_BMS_MODULE)
diff --git a/include/linux/mfd/pm8xxx/pm8921-charger.h b/include/linux/mfd/pm8xxx/pm8921-charger.h
index b00e050..6bd4cb2 100644
--- a/include/linux/mfd/pm8xxx/pm8921-charger.h
+++ b/include/linux/mfd/pm8xxx/pm8921-charger.h
@@ -281,6 +281,13 @@
*
*/
int pm8921_usb_ovp_disable(int disable);
+/**
+ * pm8921_is_batfet_closed - battery fet status
+ *
+ * Returns 1 if batfet is closed 0 if open. On configurations without
+ * batfet this will return 0.
+ */
+int pm8921_is_batfet_closed(void);
#else
static inline void pm8921_charger_vbus_draw(unsigned int mA)
{
@@ -353,6 +360,10 @@
{
return -ENXIO;
}
+static inline int pm8921_is_batfet_closed(void)
+{
+ return 1;
+}
#endif
#endif
diff --git a/include/linux/regulator/krait-regulator.h b/include/linux/regulator/krait-regulator.h
index 1f85952..eb1c3fd 100644
--- a/include/linux/regulator/krait-regulator.h
+++ b/include/linux/regulator/krait-regulator.h
@@ -23,5 +23,6 @@
* success and error on failure.
*/
int __init krait_power_init(void);
+void secondary_cpu_hs_init(void *base_ptr);
#endif
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 6a0259d..6fcafa8 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -282,8 +282,10 @@
struct winsize winsize; /* termios mutex */
unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1;
unsigned char low_latency:1, warned:1;
+ unsigned char update_room_in_ldisc:1;
unsigned char ctrl_status; /* ctrl_lock */
unsigned int receive_room; /* Bytes free for queue */
+ unsigned int rr_bug;
struct tty_struct *link;
struct fasync_struct *fasync;
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index f4f55fa..5c5ee30 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -1573,10 +1573,22 @@
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ if (w->reg == SITAR_A_RX_HPH_L_DAC_CTL) {
+ snd_soc_update_bits(codec, SITAR_A_CDC_CONN_CLSG_CTL,
+ 0x30, 0x20);
+ snd_soc_update_bits(codec, SITAR_A_CDC_CONN_CLSG_CTL,
+ 0x0C, 0x08);
+ }
snd_soc_update_bits(codec, w->reg, 0x40, 0x40);
break;
case SND_SOC_DAPM_POST_PMD:
snd_soc_update_bits(codec, w->reg, 0x40, 0x00);
+ if (w->reg == SITAR_A_RX_HPH_L_DAC_CTL) {
+ snd_soc_update_bits(codec, SITAR_A_CDC_CONN_CLSG_CTL,
+ 0x30, 0x10);
+ snd_soc_update_bits(codec, SITAR_A_CDC_CONN_CLSG_CTL,
+ 0x0C, 0x04);
+ }
break;
}
return 0;
@@ -2018,13 +2030,16 @@
{"HEADPHONE", NULL, "HPHL"},
{"HEADPHONE", NULL, "HPHR"},
+
{"HPHL DAC", NULL, "CP"},
{"HPHR DAC", NULL, "CP"},
{"HPHL", NULL, "HPHL DAC"},
- {"HPHL DAC", "NULL", "DAC4 MUX"},
+ {"HPHL DAC", "NULL", "RX2 CHAIN"},
+ {"RX2 CHAIN", NULL, "DAC4 MUX"},
{"HPHR", NULL, "HPHR DAC"},
- {"HPHR DAC", NULL, "RX3 MIX1"},
+ {"HPHR DAC", NULL, "RX3 CHAIN"},
+ {"RX3 CHAIN", NULL, "RX3 MIX1"},
{"DAC1 MUX", "RX1", "RX1 CHAIN"},
{"DAC2 MUX", "RX1", "RX1 CHAIN"},
@@ -2459,19 +2474,6 @@
return 0;
}
-static void sitar_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct wcd9xxx *wcd9xxx = dev_get_drvdata(dai->codec->dev->parent);
- if ((wcd9xxx != NULL) && (wcd9xxx->dev != NULL) &&
- (wcd9xxx->dev->parent != NULL)) {
- pm_runtime_mark_last_busy(wcd9xxx->dev->parent);
- pm_runtime_put(wcd9xxx->dev->parent);
- }
- pr_debug("%s(): substream = %s stream = %d\n" , __func__,
- substream->name, substream->stream);
-}
-
int sitar_mclk_enable(struct snd_soc_codec *codec, int mclk_enable, bool dapm)
{
struct sitar_priv *sitar = snd_soc_codec_get_drvdata(codec);
@@ -2767,7 +2769,6 @@
static struct snd_soc_dai_ops sitar_dai_ops = {
.startup = sitar_startup,
- .shutdown = sitar_shutdown,
.hw_params = sitar_hw_params,
.set_sysclk = sitar_set_dai_sysclk,
.set_fmt = sitar_set_dai_fmt,
@@ -2872,6 +2873,15 @@
return ret;
}
+static void sitar_codec_pm_runtime_put(struct wcd9xxx *sitar)
+{
+ if (sitar->dev != NULL &&
+ sitar->dev->parent != NULL) {
+ pm_runtime_mark_last_busy(sitar->dev->parent);
+ pm_runtime_put(sitar->dev->parent);
+ }
+}
+
static int sitar_codec_enable_slimrx(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -2881,9 +2891,14 @@
u32 j = 0, ret = 0;
codec->control_data = dev_get_drvdata(codec->dev->parent);
sitar = codec->control_data;
+
/* Execute the callback only if interface type is slimbus */
- if (sitar_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+ if (sitar_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
+ if (event == SND_SOC_DAPM_POST_PMD && (sitar != NULL))
+ sitar_codec_pm_runtime_put(sitar);
return 0;
+ }
+
switch (event) {
case SND_SOC_DAPM_POST_PMU:
for (j = 0; j < ARRAY_SIZE(sitar_dai); j++) {
@@ -2922,6 +2937,8 @@
sitar_p->dai[j].ch_tot));
sitar_p->dai[j].ch_tot = 0;
ret = sitar_codec_enable_chmask(sitar_p, event, j);
+ if (sitar != NULL)
+ sitar_codec_pm_runtime_put(sitar);
}
}
return ret;
@@ -2940,8 +2957,12 @@
sitar = codec->control_data;
/* Execute the callback only if interface type is slimbus */
- if (sitar_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS)
+ if (sitar_p->intf_type != WCD9XXX_INTERFACE_TYPE_SLIMBUS) {
+ if (event == SND_SOC_DAPM_POST_PMD && (sitar != NULL))
+ sitar_codec_pm_runtime_put(sitar);
return 0;
+ }
+
switch (event) {
case SND_SOC_DAPM_POST_PMU:
for (j = 0; j < ARRAY_SIZE(sitar_dai); j++) {
@@ -2980,6 +3001,8 @@
sitar_p->dai[j].ch_tot));
sitar_p->dai[j].ch_tot = 0;
ret = sitar_codec_enable_chmask(sitar_p, event, j);
+ if (sitar != NULL)
+ sitar_codec_pm_runtime_put(sitar);
}
}
return ret;
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index a596f03..81bde3f 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -796,7 +796,7 @@
#undef S
#define S(X, Y) ((TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla_cal)->X) = (Y))
S(v_no_mic, 30);
- S(v_hs_max, 1550);
+ S(v_hs_max, 2400);
#undef S
#define S(X, Y) ((TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal)->X) = (Y))
S(c[0], 62);
@@ -814,24 +814,24 @@
btn_low = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_LOW);
btn_high = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_HIGH);
btn_low[0] = -50;
- btn_high[0] = 10;
- btn_low[1] = 11;
- btn_high[1] = 38;
- btn_low[2] = 39;
- btn_high[2] = 64;
- btn_low[3] = 65;
- btn_high[3] = 91;
- btn_low[4] = 92;
- btn_high[4] = 115;
- btn_low[5] = 116;
- btn_high[5] = 141;
- btn_low[6] = 142;
- btn_high[6] = 163;
- btn_low[7] = 164;
- btn_high[7] = 250;
+ btn_high[0] = 20;
+ btn_low[1] = 21;
+ btn_high[1] = 62;
+ btn_low[2] = 62;
+ btn_high[2] = 104;
+ btn_low[3] = 105;
+ btn_high[3] = 143;
+ btn_low[4] = 144;
+ btn_high[4] = 181;
+ btn_low[5] = 182;
+ btn_high[5] = 218;
+ btn_low[6] = 219;
+ btn_high[6] = 254;
+ btn_low[7] = 255;
+ btn_high[7] = 330;
n_ready = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_READY);
- n_ready[0] = 48;
- n_ready[1] = 38;
+ n_ready[0] = 80;
+ n_ready[1] = 68;
n_cic = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_CIC);
n_cic[0] = 60;
n_cic[1] = 47;