Merge "video: msm: Load correct default values to QSEED at init" into msm-3.0
diff --git a/AndroidKernel.mk b/AndroidKernel.mk
index cc94b69..3ee63c0 100644
--- a/AndroidKernel.mk
+++ b/AndroidKernel.mk
@@ -15,19 +15,21 @@
KERNEL_USE_OF ?= $(shell $(PERL) -e '$$of = "n"; while (<>) { if (/CONFIG_USE_OF=y/) { $$of = "y"; break; } } print $$of;' kernel/arch/arm/configs/$(KERNEL_DEFCONFIG))
ifeq "$(KERNEL_USE_OF)" "y"
+DTS_NAME ?= $(MSM_ARCH)
+DTS_FILES = $(wildcard $(TOP)/kernel/arch/arm/boot/dts/$(DTS_NAME)*.dts)
+DTS_FILE = $(lastword $(subst /, ,$(1)))
+DTB_FILE = $(addprefix $(KERNEL_OUT)/arch/arm/boot/,$(patsubst %.dts,%.dtb,$(call DTS_FILE,$(1))))
+ZIMG_FILE = $(addprefix $(KERNEL_OUT)/arch/arm/boot/,$(patsubst %.dts,%-zImage,$(call DTS_FILE,$(1))))
KERNEL_ZIMG = $(KERNEL_OUT)/arch/arm/boot/zImage
-DTB_FILE = $(KERNEL_OUT)/arch/arm/boot/$(MSM_ARCH).dtb
-DTS_FILE = $(TOP)/kernel/arch/arm/boot/dts/$(MSM_ARCH).dts
-FULL_KERNEL = $(KERNEL_OUT)/arch/arm/boot/$(MSM_ARCH)-zImage
DTC = $(KERNEL_OUT)/scripts/dtc/dtc
define append-dtb
-md $(KERNEL_OUT)/arch/arm/boot;\
-$(DTC) -p 1024 -O dtb -o $(DTB_FILE) $(DTS_FILE);\
-cat $(KERNEL_ZIMG) $(DTB_FILE) > $(FULL_KERNEL)
+mkdir -p $(KERNEL_OUT)/arch/arm/boot;\
+$(foreach d, $(DTS_FILES), \
+ $(DTC) -p 1024 -O dtb -o $(call DTB_FILE,$(d)) $(d); \
+ cat $(KERNEL_ZIMG) $(call DTB_FILE,$(d)) > $(call ZIMG_FILE,$(d));)
endef
else
-FULL_KERNEL = $(KERNEL_IMG)
define append-dtb
endef
diff --git a/arch/arm/boot/dts/msmcopper-rumi.dts b/arch/arm/boot/dts/msmcopper-rumi.dts
new file mode 100644
index 0000000..bb53ff8
--- /dev/null
+++ b/arch/arm/boot/dts/msmcopper-rumi.dts
@@ -0,0 +1,60 @@
+/* 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.
+ */
+
+/dts-v1/;
+
+/include/ "msmcopper.dtsi"
+
+/ {
+ model = "Qualcomm MSM Copper RUMI";
+ compatible = "qcom,msmcopper-rumi", "qcom,msmcopper";
+
+ timer {
+ clock-frequency = <5000000>;
+ };
+
+ serial@f991f000 {
+ status = "disable";
+ };
+
+ usb@f9a55000 {
+ status = "disable";
+ };
+
+ qcom,sdcc@f980b000 {
+ status = "disable";
+ };
+
+ qcom,sdcc@f984b000 {
+ status = "disable";
+ };
+
+ qcom,sps@f998000 {
+ status = "disable";
+ };
+
+ spi@f9924000 {
+ status = "disable";
+ };
+
+ slim@fe12f000 {
+ status = "disable";
+ };
+
+ qcom,spmi@fc4c0000 {
+ status = "disable";
+ };
+
+ i2c@f9966000 {
+ status = "disable";
+ };
+};
diff --git a/arch/arm/boot/dts/msmcopper-sim.dts b/arch/arm/boot/dts/msmcopper-sim.dts
new file mode 100644
index 0000000..ab6b8ba
--- /dev/null
+++ b/arch/arm/boot/dts/msmcopper-sim.dts
@@ -0,0 +1,20 @@
+/* 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.
+ */
+
+/dts-v1/;
+
+/include/ "msmcopper.dtsi"
+
+/ {
+ model = "Qualcomm MSM Copper Simulator";
+ compatible = "qcom,msmcopper-sim", "qcom,msmcopper";
+};
diff --git a/arch/arm/boot/dts/msmcopper.dts b/arch/arm/boot/dts/msmcopper.dtsi
similarity index 89%
rename from arch/arm/boot/dts/msmcopper.dts
rename to arch/arm/boot/dts/msmcopper.dtsi
index 8c8cc12..4aa05e0 100644
--- a/arch/arm/boot/dts/msmcopper.dts
+++ b/arch/arm/boot/dts/msmcopper.dtsi
@@ -1,10 +1,20 @@
-/dts-v1/;
+/* 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/ "skeleton.dtsi"
/ {
model = "Qualcomm MSM Copper";
- compatible = "qcom,msmcopper-sim", "qcom,msmcopper";
+ compatible = "qcom,msmcopper";
interrupt-parent = <&intc>;
intc: interrupt-controller@F9000000 {
@@ -34,6 +44,12 @@
interrupts = <0 109 0>;
};
+ serial@f995e000 {
+ compatible = "qcom,msm-lsuart-v14";
+ reg = <0xf995e000 0x1000>;
+ interrupts = <0 114 0>;
+ };
+
usb@f9a55000 {
compatible = "qcom,hsusb-otg";
reg = <0xf9a55000 0x400>;
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 8594562..c6e314e 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -146,6 +146,8 @@
CONFIG_SPS=y
CONFIG_SPS_SUPPORT_BAMDMA=y
CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_SLIMBUS=y
+CONFIG_SLIMBUS_MSM_CTRL=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 3384b48..2bc922a 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -53,6 +53,7 @@
CONFIG_MACH_APQ8064_CDP=y
CONFIG_MACH_APQ8064_MTP=y
CONFIG_MACH_APQ8064_LIQUID=y
+CONFIG_MACH_MPQ8064_CDP=y
CONFIG_MACH_MPQ8064_HRD=y
CONFIG_MACH_MPQ8064_DTV=y
# CONFIG_MSM_STACKED_MEMORY is not set
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index c186be4..706bc88 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -52,6 +52,7 @@
CONFIG_MACH_APQ8064_CDP=y
CONFIG_MACH_APQ8064_MTP=y
CONFIG_MACH_APQ8064_LIQUID=y
+CONFIG_MACH_MPQ8064_CDP=y
CONFIG_MACH_MPQ8064_HRD=y
CONFIG_MACH_MPQ8064_DTV=y
# CONFIG_MSM_STACKED_MEMORY is not set
@@ -94,6 +95,7 @@
CONFIG_MSM_L2_ERP_1BIT_PANIC=y
CONFIG_MSM_L2_ERP_2BIT_PANIC=y
CONFIG_MSM_CACHE_DUMP=y
+CONFIG_MSM_CACHE_DUMP_ON_PANIC=y
CONFIG_STRICT_MEMORY_RWX=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
diff --git a/arch/arm/configs/msm9615_defconfig b/arch/arm/configs/msm9615_defconfig
index f5193da..f085d77 100644
--- a/arch/arm/configs/msm9615_defconfig
+++ b/arch/arm/configs/msm9615_defconfig
@@ -231,7 +231,8 @@
CONFIG_USB_STORAGE_CYPRESS_ATACB=y
CONFIG_USB_EHSET_TEST_FIXTURE=y
CONFIG_USB_GADGET=y
-CONFIG_USB_CI13XXX_MSM=y
+CONFIG_USB_CI13XXX_MSM=m
+CONFIG_USB_CI13XXX_MSM_HSIC=m
CONFIG_USB_G_ANDROID=y
CONFIG_RMNET_SMD_CTL_CHANNEL="DATA36_CNTL"
CONFIG_RMNET_SMD_DATA_CHANNEL="DATA36"
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 5bb5139..5668e75 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -50,8 +50,11 @@
void gic_enable_ppi(unsigned int);
bool gic_is_spi_pending(unsigned int irq);
void gic_clear_spi_pending(unsigned int irq);
+#ifdef CONFIG_ARM_GIC
void gic_set_irq_secure(unsigned int irq);
-
+#else
+static inline void gic_set_irq_secure(unsigned int irq) { }
+#endif
static inline void gic_init(unsigned int nr, int start,
void __iomem *dist , void __iomem *cpu)
{
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index 2e37431..0202746 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -265,6 +265,7 @@
select MSM_XO
select MSM_QDSP6_APR
select MSM_AUDIO_QDSP6 if SND_SOC
+ select FIQ
config ARCH_MSM8625
bool "MSM8625"
@@ -780,6 +781,12 @@
help
Support for the Qualcomm APQ8064 LIQUID device.
+config MACH_MPQ8064_CDP
+ depends on ARCH_APQ8064
+ bool "MPQ8064 CDP"
+ help
+ Support for the Qualcomm MPQ8064 CDP device.
+
config MACH_MPQ8064_HRD
depends on ARCH_APQ8064
bool "MPQ8064 HRD"
@@ -2229,4 +2236,13 @@
This allows for analysis of the caches in case cache corruption is
suspected.
+config MSM_CACHE_DUMP_ON_PANIC
+ bool "Dump caches on panic"
+ depends on MSM_CACHE_DUMP
+ help
+ By default, the caches are flushed on panic. This means that trying to
+ look at them in a RAM dump will give useless data. Select this if you
+ want to dump the L1 and L2 caches on panic before any flush occurs.
+ If unsure, say N
+
endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 4c40e3c..f331c4e 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -204,6 +204,7 @@
obj-$(CONFIG_ARCH_FSM9XXX) += restart-fsm9xxx.o xo-fsm9xxx.o
obj-$(CONFIG_MSM_WATCHDOG) += msm_watchdog.o
+obj-$(CONFIG_MSM_WATCHDOG) += msm_watchdog_asm.o
obj-$(CONFIG_MACH_MSM8X60_RUMI3) += board-msm8x60.o
obj-$(CONFIG_MACH_MSM8X60_SIM) += board-msm8x60.o
obj-$(CONFIG_MACH_MSM8X60_SURF) += board-msm8x60.o
@@ -258,7 +259,7 @@
obj-$(CONFIG_PM8921_BMS) += bms-batterydata.o bms-batterydata-desay.o
obj-$(CONFIG_MACH_APQ8064_SIM) += board-8064-all.o board-8064-regulator.o
obj-$(CONFIG_MACH_APQ8064_RUMI3) += 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
+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
obj-$(CONFIG_ARCH_MSMCOPPER) += board-copper.o board-dt.o board-copper-regulator.o
diff --git a/arch/arm/mach-msm/bam_dmux.c b/arch/arm/mach-msm/bam_dmux.c
index 4dac062..89d7fc9 100644
--- a/arch/arm/mach-msm/bam_dmux.c
+++ b/arch/arm/mach-msm/bam_dmux.c
@@ -2036,6 +2036,7 @@
goto register_bam_failed;
}
a2_device_handle = h;
+ toggle_apps_ack();
return 0;
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index 2708283..0ff931a 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -16,10 +16,36 @@
#include <linux/msm_kgsl.h>
#include <mach/msm_bus_board.h>
#include <mach/board.h>
+#include <mach/msm_dcvs.h>
#include "devices.h"
#include "board-8064.h"
+#ifdef CONFIG_MSM_DCVS
+static struct msm_dcvs_freq_entry grp3d_freq[] = {
+ {0, 0, 333932},
+ {0, 0, 497532},
+ {0, 0, 707610},
+ {0, 0, 844545},
+};
+
+static struct msm_dcvs_core_info grp3d_core_info = {
+ .freq_tbl = &grp3d_freq[0],
+ .core_param = {
+ .max_time_us = 100000,
+ .num_freq = ARRAY_SIZE(grp3d_freq),
+ },
+ .algo_param = {
+ .slack_time_us = 39000,
+ .disable_pc_threshold = 86000,
+ .ss_window_size = 1000000,
+ .ss_util_pct = 95,
+ .em_max_util_pct = 97,
+ .ss_iobusy_conv = 100,
+ },
+};
+#endif /* CONFIG_MSM_DCVS */
+
#ifdef CONFIG_MSM_BUS_SCALING
static struct msm_bus_vectors grp3d_init_vectors[] = {
{
@@ -180,6 +206,9 @@
#endif
.iommu_data = kgsl_3d0_iommu_data,
.iommu_count = ARRAY_SIZE(kgsl_3d0_iommu_data),
+#ifdef CONFIG_MSM_DCVS
+ .core_info = &grp3d_core_info,
+#endif
};
struct platform_device device_kgsl_3d0 = {
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 5a6db27..73f02f5 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1868,6 +1868,11 @@
&apq8064_msm_gov_device,
&apq8064_device_cache_erp,
&epm_adc_device,
+ &apq8064_qdss_device,
+ &msm_etb_device,
+ &msm_tpiu_device,
+ &msm_funnel_device,
+ &apq8064_etm_device,
};
static struct platform_device *sim_devices[] __initdata = {
@@ -2365,6 +2370,17 @@
.init_very_early = apq8064_early_reserve,
MACHINE_END
+MACHINE_START(MPQ8064_CDP, "QCT MPQ8064 CDP")
+ .map_io = apq8064_map_io,
+ .reserve = apq8064_reserve,
+ .init_irq = apq8064_init_irq,
+ .handle_irq = gic_handle_irq,
+ .timer = &msm_timer,
+ .init_machine = apq8064_cdp_init,
+ .init_early = apq8064_allocate_memory_regions,
+ .init_very_early = apq8064_early_reserve,
+MACHINE_END
+
MACHINE_START(MPQ8064_HRD, "QCT MPQ8064 HRD")
.map_io = apq8064_map_io,
.reserve = apq8064_reserve,
diff --git a/arch/arm/mach-msm/board-8930-gpiomux.c b/arch/arm/mach-msm/board-8930-gpiomux.c
index cd201ef..854f318 100644
--- a/arch/arm/mach-msm/board-8930-gpiomux.c
+++ b/arch/arm/mach-msm/board-8930-gpiomux.c
@@ -171,26 +171,6 @@
},
};
#endif
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
-static struct gpiomux_setting hsic_act_cfg = {
- .func = GPIOMUX_FUNC_1,
- .drv = GPIOMUX_DRV_12MA,
- .pull = GPIOMUX_PULL_NONE,
-};
-
-static struct gpiomux_setting hsic_sus_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_DOWN,
- .dir = GPIOMUX_OUT_LOW,
-};
-
-static struct gpiomux_setting hsic_hub_act_cfg = {
- .func = GPIOMUX_FUNC_GPIO,
- .drv = GPIOMUX_DRV_2MA,
- .pull = GPIOMUX_PULL_NONE,
-};
-#endif
static struct gpiomux_setting hap_lvl_shft_suspended_config = {
.func = GPIOMUX_FUNC_GPIO,
@@ -487,32 +467,6 @@
},
};
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
-static struct msm_gpiomux_config msm8960_hsic_configs[] = {
- {
- .gpio = 150, /*HSIC_STROBE */
- .settings = {
- [GPIOMUX_ACTIVE] = &hsic_act_cfg,
- [GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
- },
- },
- {
- .gpio = 151, /* HSIC_DATA */
- .settings = {
- [GPIOMUX_ACTIVE] = &hsic_act_cfg,
- [GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
- },
- },
- {
- .gpio = 91, /* HSIC_HUB_RESET */
- .settings = {
- [GPIOMUX_ACTIVE] = &hsic_hub_act_cfg,
- [GPIOMUX_SUSPENDED] = &hsic_sus_cfg,
- },
- },
-};
-#endif
-
static struct msm_gpiomux_config hap_lvl_shft_config[] __initdata = {
{
.gpio = 47,
@@ -689,14 +643,6 @@
msm_gpiomux_install(msm8930_haptics_configs,
ARRAY_SIZE(msm8930_haptics_configs));
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
- if ((SOCINFO_VERSION_MAJOR(socinfo_get_version()) != 1) &&
- !machine_is_msm8930_mtp() &&
- !machine_is_msm8930_fluid())
- msm_gpiomux_install(msm8960_hsic_configs,
- ARRAY_SIZE(msm8960_hsic_configs));
-#endif
-
#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL
msm_gpiomux_install(msm8960_hdmi_configs,
ARRAY_SIZE(msm8960_hdmi_configs));
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index c713567..5493628 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -1024,16 +1024,6 @@
};
#endif
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
-#define HSIC_HUB_RESET_GPIO 91
-static struct msm_hsic_host_platform_data msm_hsic_pdata = {
- .strobe = 150,
- .data = 151,
-};
-#else
-static struct msm_hsic_host_platform_data msm_hsic_pdata;
-#endif
-
#define PID_MAGIC_ID 0x71432909
#define SERIAL_NUM_MAGIC_ID 0x61945374
#define SERIAL_NUMBER_LENGTH 127
@@ -1693,6 +1683,7 @@
&msm_device_tz_log,
#ifdef CONFIG_MSM_QDSS
+ &msm_qdss_device,
&msm_etb_device,
&msm_tpiu_device,
&msm_funnel_device,
@@ -1941,24 +1932,6 @@
int len;
};
-static void __init msm8930_init_hsic(void)
-{
-#ifdef CONFIG_USB_EHCI_MSM_HSIC
- uint32_t version = socinfo_get_version();
-
- pr_info("%s: version:%d mtp:%d\n", __func__,
- SOCINFO_VERSION_MAJOR(version),
- machine_is_msm8930_mtp());
-
- if ((SOCINFO_VERSION_MAJOR(version) == 1) ||
- machine_is_msm8930_mtp() ||
- machine_is_msm8930_fluid())
- return;
-
- platform_device_register(&msm_device_hsic_host);
-#endif
-}
-
#ifdef CONFIG_ISL9519_CHARGER
static struct isl_platform_data isl_data __initdata = {
.valid_n_gpio = 0, /* Not required when notify-by-pmic */
@@ -2058,7 +2031,6 @@
platform_device_register(&msm8930_device_rpm_regulator);
msm_clock_init(&msm8930_clock_init_data);
msm8960_device_otg.dev.platform_data = &msm_otg_pdata;
- msm_device_hsic_host.dev.platform_data = &msm_hsic_pdata;
msm8930_init_gpiomux();
msm8960_device_qup_spi_gsbi1.dev.platform_data =
&msm8960_qup_spi_gsbi1_pdata;
@@ -2094,7 +2066,6 @@
msm8930_pm8038_gpio_mpp_init();
#endif
platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
- msm8930_init_hsic();
msm8930_init_cam();
msm8930_init_mmc();
acpuclk_init(&acpuclk_8930_soc_data);
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 70a65d0..3f0d8df 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -612,6 +612,7 @@
#ifdef CONFIG_MSM_CACHE_DUMP
unsigned int spare;
unsigned int l1_size;
+ unsigned int l2_size;
unsigned int total;
int ret;
@@ -622,10 +623,18 @@
/* Fall back to something reasonable here */
l1_size = L1_BUFFER_SIZE;
- total = l1_size + L2_BUFFER_SIZE;
+ ret = scm_call(L1C_SERVICE_ID, L2C_BUFFER_GET_SIZE_COMMAND_ID, &spare,
+ sizeof(spare), &l2_size, sizeof(l2_size));
+
+ if (ret)
+ /* Fall back to something reasonable here */
+ l2_size = L2_BUFFER_SIZE;
+
+ total = l1_size + l2_size;
msm8960_reserve_table[MEMTYPE_EBI1].size += total;
msm_cache_dump_pdata.l1_size = l1_size;
+ msm_cache_dump_pdata.l2_size = l2_size;
#endif
}
@@ -2241,6 +2250,7 @@
&msm8960_rpm_stat_device,
&msm_device_tz_log,
#ifdef CONFIG_MSM_QDSS
+ &msm_qdss_device,
&msm_etb_device,
&msm_tpiu_device,
&msm_funnel_device,
diff --git a/arch/arm/mach-msm/board-9615-display.c b/arch/arm/mach-msm/board-9615-display.c
new file mode 100644
index 0000000..74bc984
--- /dev/null
+++ b/arch/arm/mach-msm/board-9615-display.c
@@ -0,0 +1,169 @@
+/* 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/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/bootmem.h>
+#include <linux/ion.h>
+#include <asm/mach-types.h>
+#include <mach/msm_memtypes.h>
+#include <mach/board.h>
+#include <mach/gpio.h>
+#include <mach/gpiomux.h>
+#include <mach/ion.h>
+#include <mach/msm_bus_board.h>
+
+#include "devices.h"
+#include "board-9615.h"
+
+/* prim = 240 x 320 x 4(bpp) x 2(pages) */
+#define MSM_FB_PRIM_BUF_SIZE roundup(240 * 320 * 4 * 2, 0x10000)
+#define MSM_FB_SIZE roundup(MSM_FB_PRIM_BUF_SIZE, 4096)
+
+#define GPIO_PIN_EBI2_LCD_A_D 21
+#define GPIO_PIN_EBI2_LCD_CS 22
+#define GPIO_PIN_EBI2_LCD_RS 24
+
+
+#ifdef CONFIG_FB_MSM
+
+static struct resource msm_fb_resources[] = {
+ {
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+static int msm_fb_detect_panel(const char *name)
+{
+ return 0;
+}
+
+static struct msm_fb_platform_data msm_fb_pdata = {
+ .detect_client = msm_fb_detect_panel,
+};
+
+static struct platform_device msm_fb_device = {
+ .name = "msm_fb",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(msm_fb_resources),
+ .resource = msm_fb_resources,
+ .dev.platform_data = &msm_fb_pdata,
+};
+
+void __init mdm9615_allocate_fb_region(void)
+{
+ void *addr;
+ unsigned long size;
+
+ size = MSM_FB_SIZE;
+ addr = alloc_bootmem_align(size, 0x1000);
+ msm_fb_resources[0].start = __pa(addr);
+ msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1;
+ pr_info("allocating %lu bytes at %p (%lx physical) for fb\n",
+ size, addr, __pa(addr));
+}
+
+
+static bool ebi2_power_init;
+static int ebi2_panel_power(int on)
+{
+ static struct regulator *panel_power;
+ int rc;
+
+ pr_debug("%s: on=%d\n", __func__, on);
+
+ if (!ebi2_power_init) {
+ panel_power = regulator_get(&msm_ebi2_lcdc_device.dev,
+ "VDDI2");
+ if (IS_ERR_OR_NULL(panel_power)) {
+ pr_err("could not get L14, rc = %ld\n",
+ PTR_ERR(panel_power));
+ return -ENODEV;
+ }
+
+ rc = regulator_set_voltage(panel_power, 2800000, 3800000);
+ if (rc) {
+ pr_err("set_voltage L14 failed, rc=%d\n", rc);
+ return -EINVAL;
+ }
+
+ ebi2_power_init = true;
+ }
+
+ if (on) {
+ rc = regulator_enable(panel_power);
+ if (rc) {
+ pr_err("enable L14 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ rc = gpio_request(GPIO_PIN_EBI2_LCD_A_D, "disp_a_d");
+ if (rc) {
+ pr_err("request gpio EBI2_LCD_A_D failed, rc=%d\n", rc);
+ goto error1;
+ }
+ rc = gpio_request(GPIO_PIN_EBI2_LCD_CS, "disp_cs");
+ if (rc) {
+ pr_err("request gpio EBI2_LCD_CS failed, rc=%d\n", rc);
+ goto error2;
+ }
+ rc = gpio_request(GPIO_PIN_EBI2_LCD_RS, "disp_rs");
+ if (rc) {
+ pr_err("request gpio EBI2_LCD_RS failed, rc=%d\n", rc);
+ goto error3;
+ }
+ } else {
+ gpio_free(GPIO_PIN_EBI2_LCD_RS);
+ gpio_free(GPIO_PIN_EBI2_LCD_CS);
+ gpio_free(GPIO_PIN_EBI2_LCD_A_D);
+
+ rc = regulator_disable(panel_power);
+ if (rc) {
+ pr_err("disable L14 failed, rc=%d\n", rc);
+ return -ENODEV;
+ }
+ }
+
+ return 0;
+error3:
+ gpio_free(GPIO_PIN_EBI2_LCD_CS);
+error2:
+ gpio_free(GPIO_PIN_EBI2_LCD_A_D);
+error1:
+ regulator_disable(panel_power);
+ return rc;
+
+}
+
+static struct lcdc_platform_data ebi2_lcdc_pdata = {
+ .lcdc_power_save = ebi2_panel_power,
+};
+
+static struct lvds_panel_platform_data ebi2_epson_s1d_pdata;
+
+static struct platform_device ebi2_epson_s1d_panel_device = {
+ .name = "ebi2_epson_s1d_qvga",
+ .id = 0,
+ .dev = {
+ .platform_data = &ebi2_epson_s1d_pdata,
+ }
+};
+
+void __init mdm9615_init_fb(void)
+{
+ platform_device_register(&msm_fb_device);
+ platform_device_register(&ebi2_epson_s1d_panel_device);
+
+ msm_fb_register_device("ebi2_lcd", &ebi2_lcdc_pdata);
+}
+#endif
diff --git a/arch/arm/mach-msm/board-9615-gpiomux.c b/arch/arm/mach-msm/board-9615-gpiomux.c
index e61f001..0e18918 100644
--- a/arch/arm/mach-msm/board-9615-gpiomux.c
+++ b/arch/arm/mach-msm/board-9615-gpiomux.c
@@ -85,6 +85,26 @@
.pull = GPIOMUX_PULL_NONE,
};
+#ifdef CONFIG_FB_MSM_EBI2
+static struct gpiomux_setting ebi2_lcdc_a_d = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_12MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+
+static struct gpiomux_setting ebi2_lcdc_cs = {
+ .func = GPIOMUX_FUNC_2,
+ .drv = GPIOMUX_DRV_12MA,
+ .pull = GPIOMUX_PULL_UP,
+};
+
+static struct gpiomux_setting ebi2_lcdc_rs = {
+ .func = GPIOMUX_FUNC_3,
+ .drv = GPIOMUX_DRV_12MA,
+ .pull = GPIOMUX_PULL_DOWN,
+};
+#endif
+
static struct msm_gpiomux_config msm9615_audio_codec_configs[] __initdata = {
{
.gpio = 24,
@@ -263,6 +283,29 @@
},
};
+#ifdef CONFIG_FB_MSM_EBI2
+static struct msm_gpiomux_config msm9615_ebi2_lcdc_configs[] __initdata = {
+ {
+ .gpio = 21, /* a_d */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ebi2_lcdc_a_d,
+ },
+ },
+ {
+ .gpio = 22, /* cs */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ebi2_lcdc_cs,
+ },
+ },
+ {
+ .gpio = 24, /* rs */
+ .settings = {
+ [GPIOMUX_SUSPENDED] = &ebi2_lcdc_rs,
+ },
+ },
+};
+#endif
+
int __init msm9615_init_gpiomux(void)
{
int rc;
@@ -289,5 +332,10 @@
msm_gpiomux_install(msm9615_audio_codec_configs,
ARRAY_SIZE(msm9615_audio_codec_configs));
+#ifdef CONFIG_FB_MSM_EBI2
+ msm_gpiomux_install(msm9615_ebi2_lcdc_configs,
+ ARRAY_SIZE(msm9615_ebi2_lcdc_configs));
+#endif
+
return 0;
}
diff --git a/arch/arm/mach-msm/board-9615-regulator.c b/arch/arm/mach-msm/board-9615-regulator.c
index dd83d6f..8328501 100644
--- a/arch/arm/mach-msm/board-9615-regulator.c
+++ b/arch/arm/mach-msm/board-9615-regulator.c
@@ -65,6 +65,7 @@
};
VREG_CONSUMERS(L14) = {
REGULATOR_SUPPLY("8018_l14", NULL),
+ REGULATOR_SUPPLY("VDDI2", "ebi2_lcd.0"),
};
VREG_CONSUMERS(S1) = {
REGULATOR_SUPPLY("8018_s1", NULL),
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index 77ee09f..e0bfc16 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -722,6 +722,9 @@
static void __init msm9615_cdp_init(void)
{
msm9615_common_init();
+#ifdef CONFIG_FB_MSM
+ mdm9615_init_fb();
+#endif
}
static void __init msm9615_mtp_init(void)
@@ -729,6 +732,13 @@
msm9615_common_init();
}
+#ifdef CONFIG_FB_MSM
+static void __init mdm9615_allocate_memory_regions(void)
+{
+ mdm9615_allocate_fb_region();
+}
+#endif
+
MACHINE_START(MSM9615_CDP, "QCT MSM9615 CDP")
.map_io = msm9615_map_io,
.init_irq = msm9615_init_irq,
@@ -736,6 +746,9 @@
.timer = &msm_timer,
.init_machine = msm9615_cdp_init,
.reserve = msm9615_reserve,
+#ifdef CONFIG_FB_MSM
+ .init_early = mdm9615_allocate_memory_regions,
+#endif
MACHINE_END
MACHINE_START(MSM9615_MTP, "QCT MSM9615 MTP")
diff --git a/arch/arm/mach-msm/board-9615.h b/arch/arm/mach-msm/board-9615.h
index 27f5d81..239453f 100644
--- a/arch/arm/mach-msm/board-9615.h
+++ b/arch/arm/mach-msm/board-9615.h
@@ -40,4 +40,6 @@
int msm9615_init_gpiomux(void);
void msm9615_init_mmc(void);
+void mdm9615_allocate_fb_region(void);
+void mdm9615_init_fb(void);
#endif
diff --git a/arch/arm/mach-msm/board-msm7627a-bt.c b/arch/arm/mach-msm/board-msm7627a-bt.c
index fcbf2a6..81abbc0 100644
--- a/arch/arm/mach-msm/board-msm7627a-bt.c
+++ b/arch/arm/mach-msm/board-msm7627a-bt.c
@@ -20,6 +20,7 @@
#include <asm/gpio.h>
#include <asm/mach-types.h>
#include <mach/rpc_pmapp.h>
+#include <mach/socinfo.h>
#include "board-msm7627a.h"
#include "devices-msm7x2xa.h"
@@ -98,12 +99,19 @@
int gpio_bt_sys_rest_en = 133;
static void gpio_bt_config(void)
{
+ u32 socinfo = socinfo_get_platform_version();
if (machine_is_msm7627a_qrd1())
gpio_bt_sys_rest_en = 114;
if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
gpio_bt_sys_rest_en = 16;
if (machine_is_msm8625_qrd7())
gpio_bt_sys_rest_en = 88;
+ if (machine_is_msm7627a_qrd3()) {
+ if (socinfo == 0x70002)
+ gpio_bt_sys_rest_en = 88;
+ else
+ gpio_bt_sys_rest_en = 85;
+ }
}
static int bt_set_gpio(int on)
@@ -962,8 +970,6 @@
int i, rc = 0;
struct device *dev;
- if (machine_is_msm7627a_qrd3())
- return;
gpio_bt_config();
diff --git a/arch/arm/mach-msm/board-msm7627a-io.c b/arch/arm/mach-msm/board-msm7627a-io.c
index 757c166..8a2f53a 100644
--- a/arch/arm/mach-msm/board-msm7627a-io.c
+++ b/arch/arm/mach-msm/board-msm7627a-io.c
@@ -142,7 +142,7 @@
};
static struct gpio_event_platform_data kp_pdata_8625 = {
- .name = "8625_kp",
+ .name = "7x27a_kp",
.info = kp_info_8625,
.info_count = ARRAY_SIZE(kp_info_8625)
};
@@ -612,6 +612,47 @@
ARRAY_SIZE(ft5x06_device_info));
}
+/* SKU3/SKU7 keypad device information */
+#define KP_INDEX_SKU3(row, col) ((row)*ARRAY_SIZE(kp_col_gpios_sku3) + (col))
+static unsigned int kp_row_gpios_sku3[] = {31, 32};
+static unsigned int kp_col_gpios_sku3[] = {36, 37};
+
+static const unsigned short keymap_sku3[] = {
+ [KP_INDEX_SKU3(0, 0)] = KEY_VOLUMEUP,
+ [KP_INDEX_SKU3(0, 1)] = KEY_VOLUMEDOWN,
+ [KP_INDEX_SKU3(1, 1)] = KEY_CAMERA,
+};
+
+static struct gpio_event_matrix_info kp_matrix_info_sku3 = {
+ .info.func = gpio_event_matrix_func,
+ .keymap = keymap_sku3,
+ .output_gpios = kp_row_gpios_sku3,
+ .input_gpios = kp_col_gpios_sku3,
+ .noutputs = ARRAY_SIZE(kp_row_gpios_sku3),
+ .ninputs = ARRAY_SIZE(kp_col_gpios_sku3),
+ .settle_time.tv_nsec = 40 * NSEC_PER_USEC,
+ .poll_time.tv_nsec = 20 * NSEC_PER_MSEC,
+ .flags = GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_DRIVE_INACTIVE |
+ GPIOKPF_PRINT_UNMAPPED_KEYS,
+};
+
+static struct gpio_event_info *kp_info_sku3[] = {
+ &kp_matrix_info_sku3.info,
+};
+static struct gpio_event_platform_data kp_pdata_sku3 = {
+ .name = "7x27a_kp",
+ .info = kp_info_sku3,
+ .info_count = ARRAY_SIZE(kp_info_sku3)
+};
+
+static struct platform_device kp_pdev_sku3 = {
+ .name = GPIO_EVENT_DEV_NAME,
+ .id = -1,
+ .dev = {
+ .platform_data = &kp_pdata_sku3,
+ },
+};
+
void __init msm7627a_add_io_devices(void)
{
/* touchscreen */
@@ -689,6 +730,8 @@
/* keypad */
if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
platform_device_register(&kp_pdev_8625);
+ else if (machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7())
+ platform_device_register(&kp_pdev_sku3);
/* leds */
if (machine_is_msm7627a_evb() || machine_is_msm8625_evb()) {
diff --git a/arch/arm/mach-msm/board-msm7627a-storage.c b/arch/arm/mach-msm/board-msm7627a-storage.c
index e4ee52e..564c59d 100644
--- a/arch/arm/mach-msm/board-msm7627a-storage.c
+++ b/arch/arm/mach-msm/board-msm7627a-storage.c
@@ -151,7 +151,9 @@
static void gpio_sdc1_config(void)
{
if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()
- || machine_is_msm8625_evb())
+ || machine_is_msm8625_evb()
+ || machine_is_msm7627a_qrd3()
+ || machine_is_msm8625_qrd7())
gpio_sdc1_hw_det = 42;
}
@@ -253,7 +255,9 @@
if (!status) {
if (machine_is_msm7627a_qrd1() ||
machine_is_msm7627a_evb() ||
- machine_is_msm8625_evb())
+ machine_is_msm8625_evb() ||
+ machine_is_msm7627a_qrd3() ||
+ machine_is_msm8625_qrd7())
status = !gpio_get_value(gpio_sdc1_hw_det);
else
status = gpio_get_value(gpio_sdc1_hw_det);
@@ -367,11 +371,15 @@
{
/* eMMC slot */
#ifdef CONFIG_MMC_MSM_SDC3_SUPPORT
- if (mmc_regulator_init(3, "emmc", 3000000))
- return;
- sdc3_plat_data.swfi_latency = msm7627a_power_collapse_latency(
+
+ /* There is no eMMC on SDC3 for QRD3 based devices */
+ if (!(machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7())) {
+ if (mmc_regulator_init(3, "emmc", 3000000))
+ return;
+ sdc3_plat_data.swfi_latency = msm7627a_power_collapse_latency(
MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT);
- msm_add_sdcc(3, &sdc3_plat_data);
+ msm_add_sdcc(3, &sdc3_plat_data);
+ }
#endif
/* Micro-SD slot */
#ifdef CONFIG_MMC_MSM_SDC1_SUPPORT
@@ -392,9 +400,12 @@
/* Not Used */
#if (defined(CONFIG_MMC_MSM_SDC4_SUPPORT)\
&& !defined(CONFIG_MMC_MSM_SDC3_8_BIT_SUPPORT))
- if (mmc_regulator_init(4, "smps3", 1800000))
- return;
- msm_add_sdcc(4, &sdc4_plat_data);
+ /* There is no SDC4 for QRD3/7 based devices */
+ if (!(machine_is_msm7627a_qrd3() || machine_is_msm8625_qrd7())) {
+ if (mmc_regulator_init(4, "smps3", 1800000))
+ return;
+ msm_add_sdcc(4, &sdc4_plat_data);
+ }
#endif
}
#endif
diff --git a/arch/arm/mach-msm/board-msm7627a-wlan.c b/arch/arm/mach-msm/board-msm7627a-wlan.c
index 53d3c56..b72ecd4 100644
--- a/arch/arm/mach-msm/board-msm7627a-wlan.c
+++ b/arch/arm/mach-msm/board-msm7627a-wlan.c
@@ -49,7 +49,9 @@
static void gpio_wlan_config(void)
{
if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()
- || machine_is_msm8625_evb())
+ || machine_is_msm8625_evb()
+ || machine_is_msm7627a_qrd3()
+ || machine_is_msm8625_qrd7())
gpio_wlan_sys_rest_en = 124;
}
@@ -231,7 +233,9 @@
* EVB1.0 and QRD8625,so the below step is required for those devices.
*/
if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()
- || machine_is_msm8625_evb()) {
+ || machine_is_msm8625_evb()
+ || machine_is_msm7627a_qrd3()
+ || machine_is_msm8625_qrd7()) {
rc = gpio_tlmm_config(GPIO_CFG(gpio_wlan_sys_rest_en, 0,
GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
GPIO_CFG_2MA), GPIO_CFG_ENABLE);
@@ -305,7 +309,9 @@
* EVB1.0 and QRD8625,so the below step is required for those devices.
*/
if (machine_is_msm7627a_qrd1() || machine_is_msm7627a_evb()
- || machine_is_msm8625_evb()) {
+ || machine_is_msm8625_evb()
+ || machine_is_msm7627a_qrd3()
+ || machine_is_msm8625_qrd7()) {
rc = gpio_tlmm_config(GPIO_CFG(gpio_wlan_sys_rest_en, 0,
GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
GPIO_CFG_2MA), GPIO_CFG_ENABLE);
diff --git a/arch/arm/mach-msm/board-msm7627a.h b/arch/arm/mach-msm/board-msm7627a.h
index 48848d5..e3c9469 100644
--- a/arch/arm/mach-msm/board-msm7627a.h
+++ b/arch/arm/mach-msm/board-msm7627a.h
@@ -22,7 +22,7 @@
void __init msm_fb_add_devices(void);
#define PMEM_KERNEL_EBI1_SIZE 0x3A000
-#define MSM_PMEM_AUDIO_SIZE 0x5B000
+#define MSM_PMEM_AUDIO_SIZE 0x1F4000
#define MSM_PMEM_MDP_SIZE 0x2300000
#define MSM_PMEM_ADSP_SIZE 0x1100000
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 44138a5e..b203c29 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -809,6 +809,8 @@
msm7627a_add_io_devices();
/*7x25a kgsl initializations*/
msm7x25a_kgsl_3d0_init();
+ /*8x25 kgsl initializations*/
+ msm8x25_kgsl_3d0_init();
}
static void __init msm7x2x_init_early(void)
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 44ba518..f3b2178 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -566,6 +566,7 @@
msm7627a_camera_init();
qrd7627a_add_io_devices();
msm7x25a_kgsl_3d0_init();
+ msm8x25_kgsl_3d0_init();
}
static void __init qrd7627a_init_early(void)
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index a2882a5..e3447b8 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -2965,8 +2965,7 @@
{USBH3_NS_REG, BIT(6), BIT(6)},
};
-/* Local clock driver initialization. */
-static void __init msm7x30_clock_init(void)
+static void __init msm7x30_clock_pre_init(void)
{
int i;
uint32_t val;
@@ -2979,15 +2978,17 @@
* function is a NOP since writes to shadow regions that we don't own
* are ignored. */
- clk_set_rate(&usb_hs_src_clk.c, clk_tbl_usb[1].freq_hz);
-
for (i = 0; i < ARRAY_SIZE(ri_list); i++) {
val = readl_relaxed(ri_list[i].reg);
val &= ~ri_list[i].mask;
val |= ri_list[i].val;
writel_relaxed(val, ri_list[i].reg);
}
+}
+static void __init msm7x30_clock_post_init(void)
+{
+ clk_set_rate(&usb_hs_src_clk.c, 60000000);
clk_set_rate(&i2c_clk.c, 19200000);
clk_set_rate(&i2c_2_clk.c, 19200000);
clk_set_rate(&qup_i2c_clk.c, 19200000);
@@ -3006,7 +3007,8 @@
struct clock_init_data msm7x30_clock_init_data __initdata = {
.table = msm_clocks_7x30,
.size = ARRAY_SIZE(msm_clocks_7x30),
- .init = msm7x30_clock_init,
+ .pre_init = msm7x30_clock_pre_init,
+ .post_init = msm7x30_clock_post_init,
};
/*
@@ -3035,5 +3037,4 @@
.set_flags = soc_clk_set_flags,
.is_local = local_clk_is_local,
.get_parent = branch_clk_get_parent,
- .set_parent = branch_clk_set_parent,
};
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 67d5618..3c06f98 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -581,7 +581,6 @@
.reset = branch_clk_reset,
.is_local = local_clk_is_local,
.get_parent = branch_clk_get_parent,
- .set_parent = branch_clk_set_parent,
.handoff = branch_clk_handoff,
.set_flags = branch_clk_set_flags,
};
@@ -2866,16 +2865,22 @@
return -ENXIO;
}
-static int pix_rdi_clk_handoff(struct clk *c)
+static enum handoff pix_rdi_clk_handoff(struct clk *c)
{
u32 reg;
struct pix_rdi_clk *clk = to_pix_rdi_clk(c);
+ enum handoff ret;
+
+ ret = branch_handoff(&clk->b, &clk->c);
+ if (ret == HANDOFF_DISABLED_CLK)
+ return ret;
reg = readl_relaxed(clk->s_reg);
clk->cur_rate = reg & clk->s_mask ? 1 : 0;
reg = readl_relaxed(clk->s2_reg);
clk->cur_rate = reg & clk->s2_mask ? 2 : clk->cur_rate;
- return 0;
+
+ return HANDOFF_ENABLED_CLK;
}
static struct clk_ops clk_ops_pix_rdi_8960 = {
@@ -5479,7 +5484,7 @@
};
static struct clk_lookup msm_clocks_8930[] = {
- CLK_LOOKUP("xo", cxo_clk.c, "msm_otg"),
+ CLK_LOOKUP("xo", cxo_clk.c, "msm_xo"),
CLK_LOOKUP("cxo", cxo_clk.c, "wcnss_wlan.0"),
CLK_LOOKUP("cxo", cxo_clk.c, "pil_riva"),
CLK_LOOKUP("xo", pxo_clk.c, "pil_qdsp6v4.0"),
@@ -5996,12 +6001,8 @@
}
}
-/* Local clock driver initialization. */
-static void __init msm8960_clock_init(void)
+static void __init msm8960_clock_pre_init(void)
{
- /* Keep PXO on whenever APPS cpu is active */
- clk_prepare_enable(&pxo_a_clk.c);
-
if (cpu_is_apq8064()) {
vdd_sr2_pll.set_vdd = set_vdd_sr2_pll_8064;
} else if (cpu_is_msm8930() || cpu_is_msm8627()) {
@@ -6050,6 +6051,12 @@
/* Initialize clock registers. */
reg_init();
+}
+
+static void __init msm8960_clock_post_init(void)
+{
+ /* Keep PXO on whenever APPS cpu is active */
+ clk_prepare_enable(&pxo_a_clk.c);
/* Initialize rates for clocks that only support one. */
clk_set_rate(&pdm_clk.c, 27000000);
@@ -6131,20 +6138,23 @@
struct clock_init_data msm8960_clock_init_data __initdata = {
.table = msm_clocks_8960,
.size = ARRAY_SIZE(msm_clocks_8960),
- .init = msm8960_clock_init,
+ .pre_init = msm8960_clock_pre_init,
+ .post_init = msm8960_clock_post_init,
.late_init = msm8960_clock_late_init,
};
struct clock_init_data apq8064_clock_init_data __initdata = {
.table = msm_clocks_8064,
.size = ARRAY_SIZE(msm_clocks_8064),
- .init = msm8960_clock_init,
+ .pre_init = msm8960_clock_pre_init,
+ .post_init = msm8960_clock_post_init,
.late_init = msm8960_clock_late_init,
};
struct clock_init_data msm8930_clock_init_data __initdata = {
.table = msm_clocks_8930,
.size = ARRAY_SIZE(msm_clocks_8930),
- .init = msm8960_clock_init,
+ .pre_init = msm8960_clock_pre_init,
+ .post_init = msm8960_clock_post_init,
.late_init = msm8960_clock_late_init,
};
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index c2632ee..771a4bf 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -452,7 +452,6 @@
.reset = branch_clk_reset,
.is_local = local_clk_is_local,
.get_parent = branch_clk_get_parent,
- .set_parent = branch_clk_set_parent,
.set_flags = branch_clk_set_flags,
};
@@ -3751,8 +3750,10 @@
writel_relaxed(regval, reg);
}
-static void __init reg_init(void)
+static void __init msm8660_clock_pre_init(void)
{
+ vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+
/* Setup MM_PLL2 (PLL3), but turn it off. Rate set by set_rate_tv(). */
rmwreg(0, MM_PLL2_MODE_REG, BIT(0)); /* Disable output */
/* Set ref, bypass, assert reset, disable output, disable test mode */
@@ -3836,14 +3837,10 @@
rmwreg(0x400001, MISC_CC2_REG, 0x424003);
}
-/* Local clock driver initialization. */
-static void __init msm8660_clock_init(void)
+static void __init msm8660_clock_post_init(void)
{
- vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
/* Keep PXO on whenever APPS cpu is active */
clk_prepare_enable(&pxo_a_clk.c);
- /* Initialize clock registers. */
- reg_init();
/* Initialize rates for clocks that only support one. */
clk_set_rate(&pdm_clk.c, 27000000);
@@ -3885,6 +3882,7 @@
struct clock_init_data msm8x60_clock_init_data __initdata = {
.table = msm_clocks_8x60,
.size = ARRAY_SIZE(msm_clocks_8x60),
- .init = msm8660_clock_init,
+ .pre_init = msm8660_clock_pre_init,
+ .post_init = msm8660_clock_post_init,
.late_init = msm8660_clock_late_init,
};
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index cc71c0b..48ee4a9 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -388,7 +388,6 @@
.reset = branch_clk_reset,
.is_local = local_clk_is_local,
.get_parent = branch_clk_get_parent,
- .set_parent = branch_clk_set_parent,
};
/*
@@ -1739,10 +1738,14 @@
/*
* Miscellaneous clock register initializations
*/
-static void __init reg_init(void)
+static void __init msm9615_clock_pre_init(void)
{
u32 regval, is_pll_enabled, pll9_lval;
+ vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
+
+ clk_ops_pll.enable = sr_pll_clk_enable;
+
/* Enable PDM CXO source. */
regval = readl_relaxed(PDM_CLK_NS_REG);
writel_relaxed(BIT(13) | regval, PDM_CLK_NS_REG);
@@ -1831,18 +1834,11 @@
writel_relaxed(regval, DMA_BAM_HCLK_CTL);
}
-/* Local clock driver initialization. */
-static void __init msm9615_clock_init(void)
+static void __init msm9615_clock_post_init(void)
{
- vote_vdd_level(&vdd_dig, VDD_DIG_HIGH);
/* Keep CXO on whenever APPS cpu is active */
clk_prepare_enable(&cxo_a_clk.c);
- clk_ops_pll.enable = sr_pll_clk_enable;
-
- /* Initialize clock registers. */
- reg_init();
-
/* Initialize rates for clocks that only support one. */
clk_set_rate(&pdm_clk.c, 19200000);
clk_set_rate(&prng_clk.c, 32000000);
@@ -1868,6 +1864,7 @@
struct clock_init_data msm9615_clock_init_data __initdata = {
.table = msm_clocks_9615,
.size = ARRAY_SIZE(msm_clocks_9615),
- .init = msm9615_clock_init,
+ .pre_init = msm9615_clock_pre_init,
+ .post_init = msm9615_clock_post_init,
.late_init = msm9615_clock_late_init,
};
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 3546ce0..f990998 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -567,34 +567,36 @@
}
/* Disable hw clock gating if not set at boot */
-static void branch_handoff(struct branch *clk, struct clk *c)
+enum handoff branch_handoff(struct branch *clk, struct clk *c)
{
if (!branch_in_hwcg_mode(clk)) {
clk->hwcg_mask = 0;
c->flags &= ~CLKFLAG_HWCG;
+ if (readl_relaxed(clk->ctl_reg) & clk->en_mask)
+ return HANDOFF_ENABLED_CLK;
} else {
c->flags |= CLKFLAG_HWCG;
}
+ return HANDOFF_DISABLED_CLK;
}
-int branch_clk_handoff(struct clk *c)
+enum handoff branch_clk_handoff(struct clk *c)
{
struct branch_clk *clk = to_branch_clk(c);
- branch_handoff(&clk->b, &clk->c);
- return 0;
+ return branch_handoff(&clk->b, &clk->c);
}
-int rcg_clk_handoff(struct clk *c)
+enum handoff rcg_clk_handoff(struct clk *c)
{
struct rcg_clk *clk = to_rcg_clk(c);
uint32_t ctl_val, ns_val, md_val, ns_mask;
struct clk_freq_tbl *freq;
-
- branch_handoff(&clk->b, &clk->c);
+ enum handoff ret;
ctl_val = readl_relaxed(clk->b.ctl_reg);
- if (!(ctl_val & clk->root_en_mask))
- return 0;
+ ret = branch_handoff(&clk->b, &clk->c);
+ if (ret == HANDOFF_DISABLED_CLK)
+ return HANDOFF_DISABLED_CLK;
if (clk->bank_info) {
const struct bank_masks *bank_masks = clk->bank_info;
@@ -611,7 +613,8 @@
ns_mask = clk->ns_mask;
md_val = clk->md_reg ? readl_relaxed(clk->md_reg) : 0;
}
-
+ if (!ns_mask)
+ return HANDOFF_UNKNOWN_RATE;
ns_val = readl_relaxed(clk->ns_reg) & ns_mask;
for (freq = clk->freq_tbl; freq->freq_hz != FREQ_END; freq++) {
if ((freq->ns_val & ns_mask) == ns_val &&
@@ -621,12 +624,12 @@
}
}
if (freq->freq_hz == FREQ_END)
- return 0;
+ return HANDOFF_UNKNOWN_RATE;
clk->current_freq = freq;
c->rate = freq->freq_hz;
- return 1;
+ return HANDOFF_ENABLED_CLK;
}
int pll_vote_clk_enable(struct clk *clk)
@@ -829,19 +832,6 @@
return branch->parent;
}
-int branch_clk_set_parent(struct clk *clk, struct clk *parent)
-{
- /*
- * We setup the parent pointer at init time in msm_clock_init().
- * This check is to make sure drivers can't change the parent.
- */
- if (parent && list_empty(&clk->siblings)) {
- list_add(&clk->siblings, &parent->children);
- return 0;
- }
- return -EINVAL;
-}
-
int branch_clk_is_enabled(struct clk *clk)
{
struct branch_clk *branch = to_branch_clk(clk);
@@ -1058,12 +1048,15 @@
return n > clk->max_div ? -ENXIO : n;
}
-static int cdiv_clk_handoff(struct clk *c)
+static enum handoff cdiv_clk_handoff(struct clk *c)
{
struct cdiv_clk *clk = to_cdiv_clk(c);
+ enum handoff ret;
u32 reg_val;
- branch_handoff(&clk->b, &clk->c);
+ ret = branch_handoff(&clk->b, &clk->c);
+ if (ret == HANDOFF_DISABLED_CLK)
+ return ret;
reg_val = readl_relaxed(clk->ns_reg);
if (reg_val & clk->ext_mask) {
@@ -1073,7 +1066,7 @@
clk->cur_div = (reg_val & (clk->max_div - 1)) + 1;
}
- return 0;
+ return HANDOFF_ENABLED_CLK;
}
static void cdiv_clk_enable_hwcg(struct clk *c)
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 44e86b1..bc9298f 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -171,7 +171,8 @@
int branch_reset(struct branch *b, enum clk_reset_action action);
void __branch_clk_enable_reg(const struct branch *clk, const char *name);
u32 __branch_clk_disable_reg(const struct branch *clk, const char *name);
-int branch_clk_handoff(struct clk *c);
+enum handoff branch_clk_handoff(struct clk *c);
+enum handoff branch_handoff(struct branch *clk, struct clk *c);
int branch_clk_set_flags(struct clk *clk, unsigned flags);
/*
@@ -211,7 +212,7 @@
int rcg_clk_is_enabled(struct clk *clk);
long rcg_clk_round_rate(struct clk *clk, unsigned long rate);
struct clk *rcg_clk_get_parent(struct clk *c);
-int rcg_clk_handoff(struct clk *c);
+enum handoff rcg_clk_handoff(struct clk *c);
int rcg_clk_reset(struct clk *clk, enum clk_reset_action action);
void rcg_clk_enable_hwcg(struct clk *clk);
void rcg_clk_disable_hwcg(struct clk *clk);
@@ -330,7 +331,6 @@
int branch_clk_enable(struct clk *clk);
void branch_clk_disable(struct clk *clk);
struct clk *branch_clk_get_parent(struct clk *clk);
-int branch_clk_set_parent(struct clk *clk, struct clk *parent);
int branch_clk_is_enabled(struct clk *clk);
int branch_clk_reset(struct clk *c, enum clk_reset_action action);
void branch_clk_enable_hwcg(struct clk *clk);
diff --git a/arch/arm/mach-msm/clock-pcom-lookup.c b/arch/arm/mach-msm/clock-pcom-lookup.c
index a0defe3..ed3b8c2 100644
--- a/arch/arm/mach-msm/clock-pcom-lookup.c
+++ b/arch/arm/mach-msm/clock-pcom-lookup.c
@@ -307,7 +307,7 @@
struct clock_init_data msm7x27_clock_init_data __initdata = {
.table = msm_clocks_7x27,
.size = ARRAY_SIZE(msm_clocks_7x27),
- .init = msm_shared_pll_control_init,
+ .pre_init = msm_shared_pll_control_init,
};
/* Clock table for common clocks between 7627a and 7625a */
@@ -413,7 +413,7 @@
static struct clk_lookup msm_clk_7627a_7625a[ARRAY_SIZE(msm_cmn_clk_7625a_7627a)
+ ARRAY_SIZE(msm_clk_7627a)];
-static void __init msm7627a_clock_init(void)
+static void __init msm7627a_clock_pre_init(void)
{
int size = ARRAY_SIZE(msm_cmn_clk_7625a_7627a);
@@ -432,7 +432,7 @@
struct clock_init_data msm7x27a_clock_init_data __initdata = {
.table = msm_clk_7627a_7625a,
- .init = msm7627a_clock_init,
+ .pre_init = msm7627a_clock_pre_init,
};
static struct clk_lookup msm_clocks_8x50[] = {
diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c
index b5b6ca7..68c390a 100644
--- a/arch/arm/mach-msm/clock-pll.c
+++ b/arch/arm/mach-msm/clock-pll.c
@@ -156,7 +156,7 @@
return true;
}
-static int pll_clk_handoff(struct clk *clk)
+static enum handoff pll_clk_handoff(struct clk *clk)
{
struct pll_shared_clk *pll = to_pll_shared_clk(clk);
unsigned int pll_lval;
@@ -184,7 +184,7 @@
BUG();
}
- return 0;
+ return HANDOFF_ENABLED_CLK;
}
struct clk_ops clk_pll_ops = {
diff --git a/arch/arm/mach-msm/clock-voter.c b/arch/arm/mach-msm/clock-voter.c
index ef502b3..9ad653d 100644
--- a/arch/arm/mach-msm/clock-voter.c
+++ b/arch/arm/mach-msm/clock-voter.c
@@ -148,18 +148,6 @@
return clk_round_rate(v->parent, rate);
}
-static int voter_clk_set_parent(struct clk *clk, struct clk *parent)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&voter_clk_lock, flags);
- if (list_empty(&clk->siblings))
- list_add(&clk->siblings, &parent->children);
- spin_unlock_irqrestore(&voter_clk_lock, flags);
-
- return 0;
-}
-
static struct clk *voter_clk_get_parent(struct clk *clk)
{
struct clk_voter *v = to_clk_voter(clk);
@@ -178,7 +166,6 @@
.get_rate = voter_clk_get_rate,
.is_enabled = voter_clk_is_enabled,
.round_rate = voter_clk_round_rate,
- .set_parent = voter_clk_set_parent,
.get_parent = voter_clk_get_parent,
.is_local = voter_clk_is_local,
};
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 884a27e..dcded38 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -401,8 +401,8 @@
size_t num_clocks;
clk_init_data = data;
- if (clk_init_data->init)
- clk_init_data->init();
+ if (clk_init_data->pre_init)
+ clk_init_data->pre_init();
clock_tbl = data->table;
num_clocks = data->size;
@@ -410,9 +410,10 @@
for (n = 0; n < num_clocks; n++) {
struct clk *clk = clock_tbl[n].clk;
struct clk *parent = clk_get_parent(clk);
- clk_set_parent(clk, parent);
+ if (parent && list_empty(&clk->siblings))
+ list_add(&clk->siblings, &parent->children);
if (clk->ops->handoff && !(clk->flags & CLKFLAG_HANDOFF_RATE)) {
- if (clk->ops->handoff(clk)) {
+ if (clk->ops->handoff(clk) == HANDOFF_ENABLED_CLK) {
clk->flags |= CLKFLAG_HANDOFF_RATE;
clk_prepare_enable(clk);
}
@@ -420,6 +421,9 @@
}
clkdev_add_table(clock_tbl, num_clocks);
+
+ if (clk_init_data->post_init)
+ clk_init_data->post_init();
}
/*
@@ -439,24 +443,24 @@
bool handoff = false;
clock_debug_add(clk);
+ spin_lock_irqsave(&clk->lock, flags);
if (!(clk->flags & CLKFLAG_SKIP_AUTO_OFF)) {
- spin_lock_irqsave(&clk->lock, flags);
if (!clk->count && clk->ops->auto_off) {
count++;
clk->ops->auto_off(clk);
}
- if (clk->flags & CLKFLAG_HANDOFF_RATE) {
- clk->flags &= ~CLKFLAG_HANDOFF_RATE;
- handoff = true;
- }
- spin_unlock_irqrestore(&clk->lock, flags);
- /*
- * Calling this outside the lock is safe since
- * it doesn't need to be atomic with the flag change.
- */
- if (handoff)
- clk_disable_unprepare(clk);
}
+ if (clk->flags & CLKFLAG_HANDOFF_RATE) {
+ clk->flags &= ~CLKFLAG_HANDOFF_RATE;
+ handoff = true;
+ }
+ spin_unlock_irqrestore(&clk->lock, flags);
+ /*
+ * Calling this outside the lock is safe since
+ * it doesn't need to be atomic with the flag change.
+ */
+ if (handoff)
+ clk_disable_unprepare(clk);
}
pr_info("clock_late_init() disabled %d unused clocks\n", count);
if (clk_init_data->late_init)
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 785e838..60be654 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -63,6 +63,12 @@
.lock = __SPIN_LOCK_UNLOCKED(lock) \
}
+enum handoff {
+ HANDOFF_ENABLED_CLK,
+ HANDOFF_DISABLED_CLK,
+ HANDOFF_UNKNOWN_RATE,
+};
+
struct clk_ops {
int (*prepare)(struct clk *clk);
int (*enable)(struct clk *clk);
@@ -72,7 +78,7 @@
void (*enable_hwcg)(struct clk *clk);
void (*disable_hwcg)(struct clk *clk);
int (*in_hwcg_mode)(struct clk *clk);
- int (*handoff)(struct clk *clk);
+ enum handoff (*handoff)(struct clk *clk);
int (*reset)(struct clk *clk, enum clk_reset_action action);
int (*set_rate)(struct clk *clk, unsigned long rate);
int (*set_max_rate)(struct clk *clk, unsigned long rate);
@@ -126,13 +132,15 @@
* struct clock_init_data - SoC specific clock initialization data
* @table: table of lookups to add
* @size: size of @table
- * @init: called before registering @table
+ * @pre_init: called before initializing the clock driver.
+ * @post_init: called after registering @table. clock APIs can be called inside.
* @late_init: called during late init
*/
struct clock_init_data {
struct clk_lookup *table;
size_t size;
- void (*init)(void);
+ void (*pre_init)(void);
+ void (*post_init)(void);
int (*late_init)(void);
};
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 3965413..7c2fca4 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -31,6 +31,7 @@
#include <mach/mdm2.h>
#include <mach/msm_smd.h>
#include <mach/msm_dcvs.h>
+#include <mach/qdss.h>
#include <linux/ion.h>
#include "clock.h"
#include "devices.h"
@@ -2210,3 +2211,42 @@
.num_resources = ARRAY_SIZE(msm_cache_erp_resources),
.resource = msm_cache_erp_resources,
};
+
+#define MSM_QDSS_PHYS_BASE 0x01A00000
+#define MSM_ETM_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x1C000)
+
+#define QDSS_SOURCE(src_name, fpm) { .name = src_name, .fport_mask = fpm, }
+
+static struct qdss_source msm_qdss_sources[] = {
+ QDSS_SOURCE("msm_etm", 0x33),
+ QDSS_SOURCE("msm_oxili", 0x80),
+};
+
+static struct msm_qdss_platform_data qdss_pdata = {
+ .src_table = msm_qdss_sources,
+ .size = ARRAY_SIZE(msm_qdss_sources),
+ .afamily = 1,
+};
+
+struct platform_device apq8064_qdss_device = {
+ .name = "msm_qdss",
+ .id = -1,
+ .dev = {
+ .platform_data = &qdss_pdata,
+ },
+};
+
+static struct resource msm_etm_resources[] = {
+ {
+ .start = MSM_ETM_PHYS_BASE,
+ .end = MSM_ETM_PHYS_BASE + (SZ_4K * 4) - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device apq8064_etm_device = {
+ .name = "msm_etm",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(msm_etm_resources),
+ .resource = msm_etm_resources,
+};
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index b03f137..a653353 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -31,9 +31,11 @@
#include <mach/msm_bus_board.h>
#include <mach/msm_memtypes.h>
#include <mach/msm_smd.h>
+#include <mach/msm_dcvs.h>
#include <sound/msm-dai-q6.h>
#include <sound/apr_audio.h>
#include <mach/msm_tsif.h>
+#include <mach/qdss.h>
#include "clock.h"
#include "devices.h"
#include "devices-msm8x60.h"
@@ -2402,6 +2404,49 @@
},
};
+static struct msm_dcvs_freq_entry grp3d_freq[] = {
+ {0, 0, 333932},
+ {0, 0, 497532},
+ {0, 0, 707610},
+ {0, 0, 844545},
+};
+
+static struct msm_dcvs_freq_entry grp2d_freq[] = {
+ {0, 0, 86000},
+ {0, 0, 200000},
+};
+
+static struct msm_dcvs_core_info grp3d_core_info = {
+ .freq_tbl = &grp3d_freq[0],
+ .core_param = {
+ .max_time_us = 100000,
+ .num_freq = ARRAY_SIZE(grp3d_freq),
+ },
+ .algo_param = {
+ .slack_time_us = 39000,
+ .disable_pc_threshold = 86000,
+ .ss_window_size = 1000000,
+ .ss_util_pct = 95,
+ .em_max_util_pct = 97,
+ .ss_iobusy_conv = 100,
+ },
+};
+
+static struct msm_dcvs_core_info grp2d_core_info = {
+ .freq_tbl = &grp2d_freq[0],
+ .core_param = {
+ .max_time_us = 100000,
+ .num_freq = ARRAY_SIZE(grp2d_freq),
+ },
+ .algo_param = {
+ .slack_time_us = 39000,
+ .disable_pc_threshold = 90000,
+ .ss_window_size = 1000000,
+ .ss_util_pct = 90,
+ .em_max_util_pct = 95,
+ },
+};
+
#ifdef CONFIG_MSM_BUS_SCALING
static struct msm_bus_vectors grp3d_init_vectors[] = {
{
@@ -2631,7 +2676,7 @@
},
},
.init_level = 0,
- .num_levels = 5,
+ .num_levels = ARRAY_SIZE(grp3d_freq) + 1,
.set_grp_async = NULL,
.idle_timeout = HZ/20,
.nap_allowed = true,
@@ -2641,6 +2686,7 @@
#endif
.iommu_data = kgsl_3d0_iommu_data,
.iommu_count = ARRAY_SIZE(kgsl_3d0_iommu_data),
+ .core_info = &grp3d_core_info,
};
struct platform_device msm_kgsl_3d0 = {
@@ -2697,7 +2743,7 @@
},
},
.init_level = 0,
- .num_levels = 3,
+ .num_levels = ARRAY_SIZE(grp2d_freq) + 1,
.set_grp_async = NULL,
.idle_timeout = HZ/5,
.nap_allowed = true,
@@ -2707,6 +2753,7 @@
#endif
.iommu_data = kgsl_2d0_iommu_data,
.iommu_count = ARRAY_SIZE(kgsl_2d0_iommu_data),
+ .core_info = &grp2d_core_info,
};
struct platform_device msm_kgsl_2d0 = {
@@ -2763,7 +2810,7 @@
},
},
.init_level = 0,
- .num_levels = 3,
+ .num_levels = ARRAY_SIZE(grp2d_freq) + 1,
.set_grp_async = NULL,
.idle_timeout = HZ/5,
.nap_allowed = true,
@@ -2773,6 +2820,7 @@
#endif
.iommu_data = kgsl_2d1_iommu_data,
.iommu_count = ARRAY_SIZE(kgsl_2d1_iommu_data),
+ .core_info = &grp2d_core_info,
};
struct platform_device msm_kgsl_2d1 = {
@@ -3167,6 +3215,26 @@
#define MSM_FUNNEL_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x4000)
#define MSM_ETM_PHYS_BASE (MSM_QDSS_PHYS_BASE + 0x1C000)
+#define QDSS_SOURCE(src_name, fpm) { .name = src_name, .fport_mask = fpm, }
+
+static struct qdss_source msm_qdss_sources[] = {
+ QDSS_SOURCE("msm_etm", 0x3),
+};
+
+static struct msm_qdss_platform_data qdss_pdata = {
+ .src_table = msm_qdss_sources,
+ .size = ARRAY_SIZE(msm_qdss_sources),
+ .afamily = 1,
+};
+
+struct platform_device msm_qdss_device = {
+ .name = "msm_qdss",
+ .id = -1,
+ .dev = {
+ .platform_data = &qdss_pdata,
+ },
+};
+
static struct resource msm_etb_resources[] = {
{
.start = MSM_ETB_PHYS_BASE,
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 1acc833..f7306d2 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -64,7 +64,8 @@
static struct msm_watchdog_pdata msm_watchdog_pdata = {
.pet_time = 10000,
.bark_time = 11000,
- .has_secure = true,
+ .has_secure = false,
+ .use_kernel_fiq = true,
};
struct platform_device msm9615_device_watchdog = {
@@ -849,6 +850,30 @@
return platform_device_register(pdev);
}
+#ifdef CONFIG_FB_MSM_EBI2
+static struct resource msm_ebi2_lcdc_resources[] = {
+ {
+ .name = "base",
+ .start = 0x1B300000,
+ .end = 0x1B300000 + PAGE_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "lcd01",
+ .start = 0x1FC00000,
+ .end = 0x1FC00000 + 0x80000 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+struct platform_device msm_ebi2_lcdc_device = {
+ .name = "ebi2_lcd",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(msm_ebi2_lcdc_resources),
+ .resource = msm_ebi2_lcdc_resources,
+};
+#endif
+
#ifdef CONFIG_CACHE_L2X0
static int __init l2x0_cache_init(void)
{
@@ -1272,3 +1297,26 @@
.name = "msm_bus_fabric",
.id = MSM_BUS_FAB_DEFAULT,
};
+
+#ifdef CONFIG_FB_MSM_EBI2
+static void __init msm_register_device(struct platform_device *pdev, void *data)
+{
+ int ret;
+
+ pdev->dev.platform_data = data;
+
+ ret = platform_device_register(pdev);
+ if (ret)
+ dev_err(&pdev->dev,
+ "%s: platform_device_register() failed = %d\n",
+ __func__, ret);
+}
+
+void __init msm_fb_register_device(char *name, void *data)
+{
+ if (!strncmp(name, "ebi2", 4))
+ msm_register_device(&msm_ebi2_lcdc_device, data);
+ else
+ pr_err("%s: unknown device! %s\n", __func__, name);
+}
+#endif
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index 96ee564..29e8180 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -364,11 +364,13 @@
static struct msm_iommu_dev gfx3d_iommu = {
.name = "gfx3d",
.ncb = 3,
+ .ttbr_split = 2,
};
static struct msm_iommu_dev gfx3d1_iommu = {
.name = "gfx3d1",
.ncb = 3,
+ .ttbr_split = 2,
};
static struct msm_iommu_dev gfx2d0_iommu = {
diff --git a/arch/arm/mach-msm/devices-msm7x27.c b/arch/arm/mach-msm/devices-msm7x27.c
index 3008fe9..77314e7 100644
--- a/arch/arm/mach-msm/devices-msm7x27.c
+++ b/arch/arm/mach-msm/devices-msm7x27.c
@@ -854,7 +854,7 @@
.init_level = 0,
.num_levels = 1,
.set_grp_async = NULL,
- .idle_timeout = HZ/5,
+ .idle_timeout = HZ,
.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM,
};
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 8236e1e..4575166 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -808,7 +808,7 @@
.init_level = 0,
.num_levels = 3,
.set_grp_async = set_grp_xbar_async,
- .idle_timeout = HZ/5,
+ .idle_timeout = HZ,
.nap_allowed = false,
.clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM,
};
@@ -834,6 +834,12 @@
}
}
+void __init msm8x25_kgsl_3d0_init(void)
+{
+ if (cpu_is_msm8625())
+ kgsl_3d0_pdata.idle_timeout = HZ/5;
+}
+
static void __init msm_register_device(struct platform_device *pdev, void *data)
{
int ret;
diff --git a/arch/arm/mach-msm/devices-msm7x2xa.h b/arch/arm/mach-msm/devices-msm7x2xa.h
index 3c81ccf..407554c 100644
--- a/arch/arm/mach-msm/devices-msm7x2xa.h
+++ b/arch/arm/mach-msm/devices-msm7x2xa.h
@@ -31,4 +31,5 @@
void __init msm8625_map_io(void);
int ar600x_wlan_power(bool on);
void __init msm8x25_spm_device_init(void);
+void __init msm8x25_kgsl_3d0_init(void);
#endif
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 3ad3ee4..ba7ac2a 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -331,6 +331,7 @@
.config_gpio = 1,
.uart_tx_gpio = 67,
.uart_rx_gpio = 66,
+ .line = 1,
};
static struct resource msm_uart_gsbi9_resources[] = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index ac9feee..3c7b22a 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -267,6 +267,7 @@
extern struct platform_device msm_mipi_dsi1_device;
extern struct platform_device msm_lvds_device;
+extern struct platform_device msm_ebi2_lcdc_device;
extern struct clk_lookup msm_clocks_fsm9xxx[];
extern unsigned msm_num_clocks_fsm9xxx;
@@ -318,10 +319,13 @@
extern struct platform_device msm9615_device_watchdog;
extern struct platform_device fsm9xxx_device_watchdog;
+extern struct platform_device apq8064_qdss_device;
+extern struct platform_device msm_qdss_device;
extern struct platform_device msm_etb_device;
extern struct platform_device msm_tpiu_device;
extern struct platform_device msm_funnel_device;
extern struct platform_device msm_etm_device;
+extern struct platform_device apq8064_etm_device;
#endif
extern struct platform_device msm_bus_8064_apps_fabric;
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index d5a2ed4..994150f 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -41,6 +41,7 @@
struct msm_iommu_dev {
const char *name;
int ncb;
+ int ttbr_split;
};
/**
@@ -74,6 +75,7 @@
void __iomem *base;
int irq;
int ncb;
+ int ttbr_split;
struct clk *clk;
struct clk *pclk;
const char *name;
diff --git a/arch/arm/mach-msm/include/mach/irqs-9615.h b/arch/arm/mach-msm/include/mach/irqs-9615.h
index 6252cef..39058a6 100644
--- a/arch/arm/mach-msm/include/mach/irqs-9615.h
+++ b/arch/arm/mach-msm/include/mach/irqs-9615.h
@@ -21,6 +21,7 @@
* 32+: SPI (shared peripheral interrupts)
*/
+#define FIQ_START 16
#define GIC_PPI_START 16
#define GIC_SPI_START 32
diff --git a/arch/arm/mach-msm/include/mach/msm_cache_dump.h b/arch/arm/mach-msm/include/mach/msm_cache_dump.h
index a8d2987..6e4f628 100644
--- a/arch/arm/mach-msm/include/mach/msm_cache_dump.h
+++ b/arch/arm/mach-msm/include/mach/msm_cache_dump.h
@@ -58,12 +58,15 @@
};
#define L1_BUFFER_SIZE SZ_1M
-#define L2_BUFFER_SIZE (sizeof(struct l2_cache_dump))
+#define L2_BUFFER_SIZE SZ_4M
#define CACHE_BUFFER_DUMP_SIZE (L1_BUFFER_SIZE + L2_BUFFER_SIZE)
#define L1C_SERVICE_ID 3
#define L1C_BUFFER_SET_COMMAND_ID 4
+#define CACHE_BUFFER_DUMP_COMMAND_ID 5
#define L1C_BUFFER_GET_SIZE_COMMAND_ID 6
+#define L2C_BUFFER_SET_COMMAND_ID 7
+#define L2C_BUFFER_GET_SIZE_COMMAND_ID 8
#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_serial_hs_lite.h b/arch/arm/mach-msm/include/mach/msm_serial_hs_lite.h
index e2bdaea..577a097 100644
--- a/arch/arm/mach-msm/include/mach/msm_serial_hs_lite.h
+++ b/arch/arm/mach-msm/include/mach/msm_serial_hs_lite.h
@@ -18,6 +18,7 @@
unsigned config_gpio;
unsigned uart_tx_gpio;
unsigned uart_rx_gpio;
+ int line;
};
#endif
diff --git a/arch/arm/mach-msm/include/mach/qdss.h b/arch/arm/mach-msm/include/mach/qdss.h
index 530bcb2..3b236b8 100644
--- a/arch/arm/mach-msm/include/mach/qdss.h
+++ b/arch/arm/mach-msm/include/mach/qdss.h
@@ -13,10 +13,30 @@
#ifndef __MACH_QDSS_H
#define __MACH_QDSS_H
+struct qdss_source {
+ struct list_head link;
+ const char *name;
+ uint32_t fport_mask;
+};
+
+struct msm_qdss_platform_data {
+ struct qdss_source *src_table;
+ size_t size;
+ uint8_t afamily;
+};
+
#ifdef CONFIG_MSM_QDSS
+extern struct qdss_source *qdss_get(const char *name);
+extern void qdss_put(struct qdss_source *src);
+extern int qdss_enable(struct qdss_source *src);
+extern void qdss_disable(struct qdss_source *src);
extern int qdss_clk_enable(void);
extern void qdss_clk_disable(void);
#else
+static inline struct qdss_source *qdss_get(const char *name) { return NULL; }
+static inline void qdss_put(struct qdss_source *src) {}
+static inline int qdss_enable(struct qdss_source *src) { return -ENOSYS; }
+static inline void qdss_disable(struct qdss_source *src) {}
static inline int qdss_clk_enable(void) { return -ENOSYS; }
static inline void qdss_clk_disable(void) {}
#endif
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
index a310ba0..d495c1b 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/arch/arm/mach-msm/iommu.c
@@ -176,7 +176,8 @@
}
static void __program_context(void __iomem *base, int ctx, int ncb,
- phys_addr_t pgtable, int redirect)
+ phys_addr_t pgtable, int redirect,
+ int ttbr_split)
{
unsigned int prrr, nmrr;
int i, j, found;
@@ -189,8 +190,10 @@
/* V2P configuration: HTW for access */
SET_V2PCFG(base, ctx, 0x3);
- SET_TTBCR(base, ctx, 0);
+ SET_TTBCR(base, ctx, ttbr_split);
SET_TTBR0_PA(base, ctx, (pgtable >> TTBR0_PA_SHIFT));
+ if (ttbr_split)
+ SET_TTBR1_PA(base, ctx, (pgtable >> TTBR1_PA_SHIFT));
/* Enable context fault interrupt */
SET_CFEIE(base, ctx, 1);
@@ -365,7 +368,8 @@
goto fail;
__program_context(iommu_drvdata->base, ctx_dev->num, iommu_drvdata->ncb,
- __pa(priv->pgtable), priv->redirect);
+ __pa(priv->pgtable), priv->redirect,
+ iommu_drvdata->ttbr_split);
__disable_clocks(iommu_drvdata);
list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
index 70e96b0..6633cae 100644
--- a/arch/arm/mach-msm/iommu_dev.c
+++ b/arch/arm/mach-msm/iommu_dev.c
@@ -239,6 +239,7 @@
drvdata->base = regs_base;
drvdata->irq = irq;
drvdata->ncb = iommu_dev->ncb;
+ drvdata->ttbr_split = iommu_dev->ttbr_split;
drvdata->name = iommu_dev->name;
pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index d26d76b..8dbf304 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -146,7 +146,7 @@
flush_axi_bus_buffer();
}
-void *alloc_bootmem_aligned(unsigned long size, unsigned long alignment)
+void * __init alloc_bootmem_aligned(unsigned long size, unsigned long alignment)
{
void *unused_addr = NULL;
unsigned long addr, tmp_size, unused_size;
diff --git a/arch/arm/mach-msm/msm_cache_dump.c b/arch/arm/mach-msm/msm_cache_dump.c
index 40c358a..404c8f0 100644
--- a/arch/arm/mach-msm/msm_cache_dump.c
+++ b/arch/arm/mach-msm/msm_cache_dump.c
@@ -20,6 +20,7 @@
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/memory_alloc.h>
+#include <linux/notifier.h>
#include <mach/scm.h>
#include <mach/msm_cache_dump.h>
#include <mach/memory.h>
@@ -38,6 +39,25 @@
static struct l1_cache_dump __used *l1_dump;
static struct l2_cache_dump __used *l2_dump;
+static int msm_cache_dump_panic(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+#ifdef CONFIG_MSM_CACHE_DUMP_ON_PANIC
+ scm_call_atomic1(L1C_SERVICE_ID, CACHE_BUFFER_DUMP_COMMAND_ID, 2);
+ scm_call_atomic1(L1C_SERVICE_ID, CACHE_BUFFER_DUMP_COMMAND_ID, 1);
+#endif
+ return 0;
+}
+
+static struct notifier_block msm_cache_dump_blk = {
+ .notifier_call = msm_cache_dump_panic,
+ /*
+ * higher priority to ensure this runs before another panic handler
+ * flushes the caches.
+ */
+ .priority = 1,
+};
+
static int msm_cache_dump_probe(struct platform_device *pdev)
{
struct msm_cache_dump_platform_data *d = pdev->dev.platform_data;
@@ -46,7 +66,9 @@
unsigned long buf;
unsigned long size;
} l1_cache_data;
+#ifndef CONFIG_MSM_CACHE_DUMP_ON_PANIC
unsigned int *imem_loc;
+#endif
void *temp;
unsigned long total_size = d->l1_size + d->l2_size;
@@ -72,14 +94,36 @@
pr_err("%s: could not register L1 buffer ret = %d.\n",
__func__, ret);
+#if defined(CONFIG_MSM_CACHE_DUMP_ON_PANIC)
+ l1_cache_data.buf = msm_cache_dump_addr + d->l1_size;
+ l1_cache_data.size = d->l2_size;
+
+ ret = scm_call(L1C_SERVICE_ID, L2C_BUFFER_SET_COMMAND_ID,
+ &l1_cache_data, sizeof(l1_cache_data), NULL, 0);
+
+ if (ret)
+ pr_err("%s: could not register L2 buffer ret = %d.\n",
+ __func__, ret);
+#else
imem_loc = ioremap(L2C_IMEM_ADDR, SZ_4K);
__raw_writel(msm_cache_dump_addr + d->l1_size, imem_loc);
iounmap(imem_loc);
+#endif
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &msm_cache_dump_blk);
+ return 0;
+}
+
+static int msm_cache_dump_remove(struct platform_device *pdev)
+{
+ atomic_notifier_chain_unregister(&panic_notifier_list,
+ &msm_cache_dump_blk);
return 0;
}
static struct platform_driver msm_cache_dump_driver = {
+ .remove = __devexit_p(msm_cache_dump_remove),
.driver = {
.name = "msm_cache_dump",
.owner = THIS_MODULE
diff --git a/arch/arm/mach-msm/msm_watchdog.c b/arch/arm/mach-msm/msm_watchdog.c
index 994dca6..aabb644 100644
--- a/arch/arm/mach-msm/msm_watchdog.c
+++ b/arch/arm/mach-msm/msm_watchdog.c
@@ -23,6 +23,8 @@
#include <linux/suspend.h>
#include <linux/percpu.h>
#include <linux/interrupt.h>
+#include <asm/fiq.h>
+#include <asm/hardware/gic.h>
#include <mach/msm_iomap.h>
#include <asm/mach-types.h>
#include <mach/scm.h>
@@ -42,6 +44,8 @@
#define WDT_HZ 32768
+struct msm_watchdog_dump msm_dump_cpu_ctx;
+
static void __iomem *msm_tmr0_base;
static unsigned long delay_time;
@@ -78,6 +82,8 @@
static int appsbark;
module_param(appsbark, int, 0);
+static int appsbark_fiq;
+
/*
* Use /sys/module/msm_watchdog/parameters/print_all_stacks
* to control whether stacks of all running
@@ -96,6 +102,13 @@
static DECLARE_DELAYED_WORK(dogwork_struct, pet_watchdog_work);
static DECLARE_WORK(init_dogwork_struct, init_watchdog_work);
+/* Called from the FIQ bark handler */
+void msm_wdog_bark_fin(void)
+{
+ pr_crit("\nApps Watchdog bark received - Calling Panic\n");
+ panic("Apps Watchdog Bark received\n");
+}
+
static int msm_watchdog_suspend(struct device *dev)
{
if (!enable)
@@ -166,9 +179,11 @@
free_irq(WDT0_ACCSCSSNBARK_INT, 0);
} else {
disable_percpu_irq(WDT0_ACCSCSSNBARK_INT);
- free_percpu_irq(WDT0_ACCSCSSNBARK_INT,
- percpu_pdata);
- free_percpu(percpu_pdata);
+ if (!appsbark_fiq) {
+ free_percpu_irq(WDT0_ACCSCSSNBARK_INT,
+ percpu_pdata);
+ free_percpu(percpu_pdata);
+ }
}
enable = 0;
atomic_notifier_chain_unregister(&panic_notifier_list,
@@ -231,8 +246,11 @@
free_irq(WDT0_ACCSCSSNBARK_INT, 0);
} else {
disable_percpu_irq(WDT0_ACCSCSSNBARK_INT);
- free_percpu_irq(WDT0_ACCSCSSNBARK_INT, percpu_pdata);
- free_percpu(percpu_pdata);
+ if (!appsbark_fiq) {
+ free_percpu_irq(WDT0_ACCSCSSNBARK_INT,
+ percpu_pdata);
+ free_percpu(percpu_pdata);
+ }
}
enable = 0;
/* In case we got suspended mid-exit */
@@ -329,26 +347,35 @@
__raw_writel(1, msm_tmr0_base + WDT0_RST);
last_pet = sched_clock();
+ if (!has_vic)
+ enable_percpu_irq(WDT0_ACCSCSSNBARK_INT, IRQ_TYPE_EDGE_RISING);
+
printk(KERN_INFO "MSM Watchdog Initialized\n");
return;
}
+struct fiq_handler wdog_fh = {
+ .name = MODULE_NAME,
+};
+
static int msm_watchdog_probe(struct platform_device *pdev)
{
struct msm_watchdog_pdata *pdata = pdev->dev.platform_data;
int ret;
+ void *stack;
if (!enable || !pdata || !pdata->pet_time || !pdata->bark_time) {
printk(KERN_INFO "MSM Watchdog Not Initialized\n");
return -ENODEV;
}
- if (!pdata->has_secure)
- appsbark = 1;
-
bark_time = pdata->bark_time;
has_vic = pdata->has_vic;
+ if (!pdata->has_secure) {
+ appsbark = 1;
+ appsbark_fiq = pdata->use_kernel_fiq;
+ }
msm_tmr0_base = msm_timer_get_timer0_base();
@@ -357,6 +384,18 @@
"apps_wdog_bark", NULL);
if (ret)
return ret;
+ } else if (appsbark_fiq) {
+ claim_fiq(&wdog_fh);
+ set_fiq_handler(&msm_wdog_fiq_start, msm_wdog_fiq_length);
+ stack = (void *)__get_free_pages(GFP_KERNEL, THREAD_SIZE_ORDER);
+ if (!stack) {
+ pr_info("No free pages available - %s fails\n",
+ __func__);
+ return -ENOMEM;
+ }
+
+ msm_wdog_fiq_setup(stack);
+ gic_set_irq_secure(WDT0_ACCSCSSNBARK_INT);
} else {
percpu_pdata = alloc_percpu(struct msm_watchdog_pdata *);
if (!percpu_pdata) {
@@ -373,8 +412,6 @@
free_percpu(percpu_pdata);
return ret;
}
-
- enable_percpu_irq(WDT0_ACCSCSSNBARK_INT, IRQ_TYPE_EDGE_RISING);
}
/*
diff --git a/arch/arm/mach-msm/msm_watchdog.h b/arch/arm/mach-msm/msm_watchdog.h
index 7156dfc..00ff0b6 100644
--- a/arch/arm/mach-msm/msm_watchdog.h
+++ b/arch/arm/mach-msm/msm_watchdog.h
@@ -21,8 +21,53 @@
bool has_secure;
bool needs_expired_enable;
bool has_vic;
+ /* You have to be running in secure mode to use FIQ */
+ bool use_kernel_fiq;
};
+struct msm_watchdog_dump {
+ uint32_t magic;
+ uint32_t curr_cpsr;
+ uint32_t usr_r0;
+ uint32_t usr_r1;
+ uint32_t usr_r2;
+ uint32_t usr_r3;
+ uint32_t usr_r4;
+ uint32_t usr_r5;
+ uint32_t usr_r6;
+ uint32_t usr_r7;
+ uint32_t usr_r8;
+ uint32_t usr_r9;
+ uint32_t usr_r10;
+ uint32_t usr_r11;
+ uint32_t usr_r12;
+ uint32_t usr_r13;
+ uint32_t usr_r14;
+ uint32_t irq_spsr;
+ uint32_t irq_r13;
+ uint32_t irq_r14;
+ uint32_t svc_spsr;
+ uint32_t svc_r13;
+ uint32_t svc_r14;
+ uint32_t abt_spsr;
+ uint32_t abt_r13;
+ uint32_t abt_r14;
+ uint32_t und_spsr;
+ uint32_t und_r13;
+ uint32_t und_r14;
+ uint32_t fiq_spsr;
+ uint32_t fiq_r8;
+ uint32_t fiq_r9;
+ uint32_t fiq_r10;
+ uint32_t fiq_r11;
+ uint32_t fiq_r12;
+ uint32_t fiq_r13;
+ uint32_t fiq_r14;
+};
+
+void msm_wdog_fiq_setup(void *stack);
+extern unsigned int msm_wdog_fiq_length, msm_wdog_fiq_start;
+
#ifdef CONFIG_MSM_WATCHDOG
void pet_watchdog(void);
#else
diff --git a/arch/arm/mach-msm/msm_watchdog_asm.S b/arch/arm/mach-msm/msm_watchdog_asm.S
new file mode 100644
index 0000000..c0377d6
--- /dev/null
+++ b/arch/arm/mach-msm/msm_watchdog_asm.S
@@ -0,0 +1,84 @@
+/* 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/linkage.h>
+#include <asm/assembler.h>
+
+#define VERSION_ID 0x1
+#define MAGIC 0xDEAD0000 | VERSION_ID
+
+ .text
+
+ .align 3
+
+ENTRY(msm_wdog_fiq_start)
+ mov sp, r8 @get stack
+ ldr r8, Ldump_cpu_ctx
+ @ store magic to indicate a valid dump
+ ldr r9, Lmagic
+ str r9, [r8], #4
+ @ get the current cpsr
+ mrs r9, cpsr
+ str r9, [r8],#4
+ @ get the USR r0-r7
+ stmia r8!, {r0-r7}
+ mov r4, r8
+ mov r5, #PSR_I_BIT | PSR_F_BIT | SYSTEM_MODE
+ msr cpsr_c, r5 @ select SYSTEM mode
+ stmia r4!, {r8-r14}
+ mov r5, #PSR_I_BIT | PSR_F_BIT | IRQ_MODE
+ msr cpsr_c, r5 @ select IRQ mode
+ mrs r5, spsr
+ str r5, [r4], #4
+ stmia r4!, {r13-r14}
+ mov r5, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
+ msr cpsr_c, r5 @ select SVC mode
+ mrs r5, spsr
+ str r5, [r4], #4
+ stmia r4!, {r13-r14}
+ mov r5, #PSR_I_BIT | PSR_F_BIT | ABT_MODE
+ msr cpsr_c, r5 @ select ABT mode
+ mrs r5, spsr
+ str r5, [r4], #4
+ stmia r4!, {r13-r14}
+ mov r5, #PSR_I_BIT | PSR_F_BIT | UND_MODE
+ msr cpsr_c, r5 @ select UND mode
+ mrs r5, spsr
+ str r5, [r4], #4
+ stmia r4!, {r13-r14}
+ mov r5, #PSR_I_BIT | PSR_F_BIT | FIQ_MODE
+ msr cpsr_c, r5 @ select FIQ mode
+ mrs r5, spsr
+ str r5, [r4], #4
+ stmia r4!, {r8-r14}
+ dsb
+ mov r5, #PSR_F_BIT | SVC_MODE
+ msr cpsr_c, r5 @ select SVC mode
+ ldr r2, Lwatchdog_bark_fin
+ blx r2
+Ldump_cpu_ctx:
+ .word msm_dump_cpu_ctx
+Lmagic:
+ .word MAGIC
+Lwatchdog_bark_fin:
+ .word msm_wdog_bark_fin
+ENTRY(msm_wdog_fiq_length)
+ .word . - msm_wdog_fiq_start
+
+/* setup the stack */
+ENTRY(msm_wdog_fiq_setup)
+ mrs r3, cpsr
+ msr cpsr_c, #(FIQ_MODE | PSR_I_BIT | PSR_F_BIT)
+ mov r8, r0
+ msr cpsr_c, r3
+ bx lr
diff --git a/arch/arm/mach-msm/msm_xo.c b/arch/arm/mach-msm/msm_xo.c
index 86776d3..407231a 100644
--- a/arch/arm/mach-msm/msm_xo.c
+++ b/arch/arm/mach-msm/msm_xo.c
@@ -15,7 +15,7 @@
#include <linux/init.h>
#include <linux/err.h>
#include <linux/module.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
#include <linux/debugfs.h>
#include <linux/list.h>
#include <linux/seq_file.h>
@@ -29,7 +29,7 @@
#include "rpm_resources.h"
-static DEFINE_SPINLOCK(msm_xo_lock);
+static DEFINE_MUTEX(msm_xo_lock);
struct msm_xo {
unsigned votes[NUM_MSM_XO_MODES];
@@ -151,13 +151,12 @@
static int msm_xo_show_voters(struct seq_file *m, void *v)
{
- unsigned long flags;
int i;
- spin_lock_irqsave(&msm_xo_lock, flags);
+ mutex_lock(&msm_xo_lock);
for (i = 0; i < ARRAY_SIZE(msm_xo_sources); i++)
msm_xo_dump_xo(m, &msm_xo_sources[i], msm_xo_to_str[i]);
- spin_unlock_irqrestore(&msm_xo_lock, flags);
+ mutex_unlock(&msm_xo_lock);
return 0;
}
@@ -221,7 +220,7 @@
*/
((msm_xo_sources[MSM_XO_CORE].mode ? 1 : 0) << 20) |
((msm_xo_sources[MSM_XO_CORE].mode ? 1 : 0) << 18);
- ret = msm_rpm_set_noirq(MSM_RPM_CTX_SET_0, &cmd, 1);
+ ret = msm_rpm_set(MSM_RPM_CTX_SET_0, &cmd, 1);
if (ret)
xo->mode = prev_vote;
@@ -281,7 +280,6 @@
int msm_xo_mode_vote(struct msm_xo_voter *xo_voter, enum msm_xo_modes mode)
{
int ret;
- unsigned long flags;
if (!xo_voter)
return 0;
@@ -289,9 +287,9 @@
if (mode >= NUM_MSM_XO_MODES || IS_ERR(xo_voter))
return -EINVAL;
- spin_lock_irqsave(&msm_xo_lock, flags);
+ mutex_lock(&msm_xo_lock);
ret = __msm_xo_mode_vote(xo_voter, mode);
- spin_unlock_irqrestore(&msm_xo_lock, flags);
+ mutex_unlock(&msm_xo_lock);
return ret;
}
@@ -310,7 +308,6 @@
struct msm_xo_voter *msm_xo_get(enum msm_xo_ids xo_id, const char *voter)
{
int ret;
- unsigned long flags;
struct msm_xo_voter *xo_voter;
if (xo_id >= NUM_MSM_XO_IDS) {
@@ -333,10 +330,10 @@
xo_voter->xo = &msm_xo_sources[xo_id];
/* Voters vote for OFF by default */
- spin_lock_irqsave(&msm_xo_lock, flags);
+ mutex_lock(&msm_xo_lock);
xo_voter->xo->votes[MSM_XO_MODE_OFF]++;
list_add(&xo_voter->list, &xo_voter->xo->voters);
- spin_unlock_irqrestore(&msm_xo_lock, flags);
+ mutex_unlock(&msm_xo_lock);
return xo_voter;
@@ -357,16 +354,14 @@
*/
void msm_xo_put(struct msm_xo_voter *xo_voter)
{
- unsigned long flags;
-
if (!xo_voter || IS_ERR(xo_voter))
return;
- spin_lock_irqsave(&msm_xo_lock, flags);
+ mutex_lock(&msm_xo_lock);
__msm_xo_mode_vote(xo_voter, MSM_XO_MODE_OFF);
xo_voter->xo->votes[MSM_XO_MODE_OFF]--;
list_del(&xo_voter->list);
- spin_unlock_irqrestore(&msm_xo_lock, flags);
+ mutex_unlock(&msm_xo_lock);
kfree(xo_voter->name);
kfree(xo_voter);
diff --git a/arch/arm/mach-msm/pil-riva.c b/arch/arm/mach-msm/pil-riva.c
index 92339e9..ecbbcb9 100644
--- a/arch/arm/mach-msm/pil-riva.c
+++ b/arch/arm/mach-msm/pil-riva.c
@@ -80,7 +80,6 @@
void __iomem *base;
unsigned long start_addr;
struct clk *xo;
- bool use_cxo;
struct regulator *pll_supply;
struct pil_device *pil;
};
@@ -97,18 +96,15 @@
struct riva_data *drv = dev_get_drvdata(pil->dev);
int ret;
- drv->use_cxo = cxo_is_needed(drv);
ret = regulator_enable(drv->pll_supply);
if (ret) {
dev_err(pil->dev, "failed to enable pll supply\n");
goto err;
}
- if (drv->use_cxo) {
- ret = clk_prepare_enable(drv->xo);
- if (ret) {
- dev_err(pil->dev, "failed to enable xo\n");
- goto err_clk;
- }
+ ret = clk_prepare_enable(drv->xo);
+ if (ret) {
+ dev_err(pil->dev, "failed to enable xo\n");
+ goto err_clk;
}
return 0;
err_clk:
@@ -121,8 +117,7 @@
{
struct riva_data *drv = dev_get_drvdata(pil->dev);
regulator_disable(drv->pll_supply);
- if (drv->use_cxo)
- clk_disable_unprepare(drv->xo);
+ clk_disable_unprepare(drv->xo);
}
static int pil_riva_init_image(struct pil_desc *pil, const u8 *metadata,
@@ -140,11 +135,8 @@
struct riva_data *drv = dev_get_drvdata(pil->dev);
void __iomem *base = drv->base;
unsigned long start_addr = drv->start_addr;
- int ret;
+ bool use_cxo = cxo_is_needed(drv);
- ret = clk_prepare_enable(drv->xo);
- if (ret)
- return ret;
/* Enable A2XB bridge */
reg = readl_relaxed(base + RIVA_PMU_A2XB_CFG);
reg |= RIVA_PMU_A2XB_CFG_EN;
@@ -155,7 +147,7 @@
reg &= ~(PLL_MODE_BYPASSNL | PLL_MODE_OUTCTRL | PLL_MODE_RESET_N);
writel_relaxed(reg, RIVA_PLL_MODE);
- if (drv->use_cxo)
+ if (use_cxo)
writel_relaxed(0x40000C00 | 50, RIVA_PLL_L_VAL);
else
writel_relaxed(0x40000C00 | 40, RIVA_PLL_L_VAL);
@@ -165,7 +157,7 @@
reg = readl_relaxed(RIVA_PLL_MODE);
reg &= ~(PLL_MODE_REF_XO_SEL);
- reg |= drv->use_cxo ? PLL_MODE_REF_XO_SEL_CXO : PLL_MODE_REF_XO_SEL_RF;
+ reg |= use_cxo ? PLL_MODE_REF_XO_SEL_CXO : PLL_MODE_REF_XO_SEL_RF;
writel_relaxed(reg, RIVA_PLL_MODE);
/* Enable PLL 13 */
@@ -230,7 +222,6 @@
/* Take cCPU out of reset */
reg |= RIVA_PMU_OVRD_VAL_CCPU_RESET;
writel_relaxed(reg, base + RIVA_PMU_OVRD_VAL);
- clk_disable_unprepare(drv->xo);
return 0;
}
@@ -239,11 +230,7 @@
{
struct riva_data *drv = dev_get_drvdata(pil->dev);
u32 reg;
- int ret;
- ret = clk_prepare_enable(drv->xo);
- if (ret)
- return ret;
/* Put cCPU and cCPU clock into reset */
reg = readl_relaxed(drv->base + RIVA_PMU_OVRD_VAL);
reg &= ~(RIVA_PMU_OVRD_VAL_CCPU_RESET | RIVA_PMU_OVRD_VAL_CCPU_CLK);
@@ -262,8 +249,6 @@
writel_relaxed(0, RIVA_RESET);
mb();
- clk_disable_unprepare(drv->xo);
-
return 0;
}
@@ -283,30 +268,12 @@
static int pil_riva_reset_trusted(struct pil_desc *pil)
{
- struct riva_data *drv = dev_get_drvdata(pil->dev);
- int ret;
-
- ret = clk_prepare_enable(drv->xo);
- if (ret)
- return ret;
- /* Proxy-vote for resources RIVA needs */
- ret = pas_auth_and_reset(PAS_RIVA);
- clk_disable_unprepare(drv->xo);
- return ret;
+ return pas_auth_and_reset(PAS_RIVA);
}
static int pil_riva_shutdown_trusted(struct pil_desc *pil)
{
- int ret;
- struct riva_data *drv = dev_get_drvdata(pil->dev);
-
- ret = clk_prepare_enable(drv->xo);
- if (ret)
- return ret;
- ret = pas_shutdown(PAS_RIVA);
- clk_disable_unprepare(drv->xo);
-
- return ret;
+ return pas_shutdown(PAS_RIVA);
}
static struct pil_reset_ops pil_riva_ops_trusted = {
diff --git a/arch/arm/mach-msm/qdsp5/audio_lpa.c b/arch/arm/mach-msm/qdsp5/audio_lpa.c
index 9521e87..8760e443 100644
--- a/arch/arm/mach-msm/qdsp5/audio_lpa.c
+++ b/arch/arm/mach-msm/qdsp5/audio_lpa.c
@@ -73,7 +73,7 @@
/* Size must be power of 2 */
#define MAX_BUF 2
-#define BUFSZ (167210)
+#define BUFSZ (1024000)
#define AUDDEC_DEC_PCM 0
diff --git a/arch/arm/mach-msm/qdss-etb.c b/arch/arm/mach-msm/qdss-etb.c
index 8b5f8db..96eba26 100644
--- a/arch/arm/mach-msm/qdss-etb.c
+++ b/arch/arm/mach-msm/qdss-etb.c
@@ -318,7 +318,7 @@
return ret;
}
-static void etb_sysfs_exit(void)
+static void __exit etb_sysfs_exit(void)
{
sysfs_remove_file(etb.kobj, &trigger_cntr_attr.attr);
kobject_put(etb.kobj);
@@ -371,7 +371,7 @@
return ret;
}
-static int etb_remove(struct platform_device *pdev)
+static int __devexit etb_remove(struct platform_device *pdev)
{
if (etb.enabled)
etb_disable();
@@ -386,18 +386,23 @@
static struct platform_driver etb_driver = {
.probe = etb_probe,
- .remove = etb_remove,
+ .remove = __devexit_p(etb_remove),
.driver = {
.name = "msm_etb",
},
};
-int __init etb_init(void)
+static int __init etb_init(void)
{
return platform_driver_register(&etb_driver);
}
+module_init(etb_init);
-void etb_exit(void)
+static void __exit etb_exit(void)
{
platform_driver_unregister(&etb_driver);
}
+module_exit(etb_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Embedded Trace Buffer driver");
diff --git a/arch/arm/mach-msm/qdss-etm.c b/arch/arm/mach-msm/qdss-etm.c
index eeb7519..251db45 100644
--- a/arch/arm/mach-msm/qdss-etm.c
+++ b/arch/arm/mach-msm/qdss-etm.c
@@ -156,6 +156,7 @@
bool enabled;
struct wake_lock wake_lock;
struct pm_qos_request_list qos_req;
+ struct qdss_source *src;
struct mutex mutex;
struct device *dev;
struct kobject *kobj;
@@ -339,10 +340,6 @@
goto err;
}
- ret = qdss_clk_enable();
- if (ret)
- goto err;
-
wake_lock(&etm.wake_lock);
/* 1. causes all online cpus to come out of idle PC
* 2. prevents idle PC until save restore flag is enabled atomically
@@ -353,11 +350,10 @@
*/
pm_qos_update_request(&etm.qos_req, 0);
- etb_disable();
- tpiu_disable();
- /* enable ETB first to avoid loosing any trace data */
- etb_enable();
- funnel_enable(0x0, 0x3);
+ ret = qdss_enable(etm.src);
+ if (ret)
+ goto err_qdss;
+
for_each_online_cpu(cpu)
__etm_enable(cpu);
@@ -368,6 +364,10 @@
dev_info(etm.dev, "ETM tracing enabled\n");
return 0;
+
+err_qdss:
+ pm_qos_update_request(&etm.qos_req, PM_QOS_DEFAULT_VALUE);
+ wake_unlock(&etm.wake_lock);
err:
return ret;
}
@@ -407,17 +407,14 @@
for_each_online_cpu(cpu)
__etm_disable(cpu);
- etb_dump();
- etb_disable();
- funnel_disable(0x0, 0x3);
+
+ qdss_disable(etm.src);
etm.enabled = false;
pm_qos_update_request(&etm.qos_req, PM_QOS_DEFAULT_VALUE);
wake_unlock(&etm.wake_lock);
- qdss_clk_disable();
-
dev_info(etm.dev, "ETM tracing disabled\n");
return 0;
err:
@@ -1151,14 +1148,14 @@
return ret;
}
-static void etm_sysfs_exit(void)
+static void __exit etm_sysfs_exit(void)
{
sysfs_remove_group(etm.kobj, &etm_attr_grp);
sysfs_remove_file(etm.kobj, &enabled_attr.attr);
kobject_put(etm.kobj);
}
-static bool etm_arch_supported(uint8_t arch)
+static bool __init etm_arch_supported(uint8_t arch)
{
switch (arch) {
case PFT_ARCH_V1_1:
@@ -1249,6 +1246,12 @@
wake_lock_init(&etm.wake_lock, WAKE_LOCK_SUSPEND, "msm_etm");
pm_qos_add_request(&etm.qos_req, PM_QOS_CPU_DMA_LATENCY,
PM_QOS_DEFAULT_VALUE);
+ etm.src = qdss_get("msm_etm");
+ if (IS_ERR(etm.src)) {
+ ret = PTR_ERR(etm.src);
+ goto err_qdssget;
+ }
+
ret = qdss_clk_enable();
if (ret)
goto err_clk;
@@ -1276,6 +1279,8 @@
err_arch:
qdss_clk_disable();
err_clk:
+ qdss_put(etm.src);
+err_qdssget:
pm_qos_remove_request(&etm.qos_req);
wake_lock_destroy(&etm.wake_lock);
mutex_destroy(&etm.mutex);
@@ -1286,11 +1291,12 @@
return ret;
}
-static int etm_remove(struct platform_device *pdev)
+static int __devexit etm_remove(struct platform_device *pdev)
{
if (etm.enabled)
etm_disable();
etm_sysfs_exit();
+ qdss_put(etm.src);
pm_qos_remove_request(&etm.qos_req);
wake_lock_destroy(&etm.wake_lock);
mutex_destroy(&etm.mutex);
@@ -1301,7 +1307,7 @@
static struct platform_driver etm_driver = {
.probe = etm_probe,
- .remove = etm_remove,
+ .remove = __devexit_p(etm_remove),
.driver = {
.name = "msm_etm",
},
@@ -1311,8 +1317,13 @@
{
return platform_driver_register(&etm_driver);
}
+module_init(etm_init);
-void etm_exit(void)
+void __exit etm_exit(void)
{
platform_driver_unregister(&etm_driver);
}
+module_exit(etm_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Program Flow Trace driver");
diff --git a/arch/arm/mach-msm/qdss-funnel.c b/arch/arm/mach-msm/qdss-funnel.c
index 990295b..2d80603 100644
--- a/arch/arm/mach-msm/qdss-funnel.c
+++ b/arch/arm/mach-msm/qdss-funnel.c
@@ -159,7 +159,7 @@
return ret;
}
-static void funnel_sysfs_exit(void)
+static void __exit funnel_sysfs_exit(void)
{
sysfs_remove_file(funnel.kobj, &priority_attr.attr);
kobject_put(funnel.kobj);
@@ -197,7 +197,7 @@
return ret;
}
-static int funnel_remove(struct platform_device *pdev)
+static int __devexit funnel_remove(struct platform_device *pdev)
{
if (funnel.enabled)
funnel_disable(0x0, 0xFF);
@@ -210,18 +210,23 @@
static struct platform_driver funnel_driver = {
.probe = funnel_probe,
- .remove = funnel_remove,
+ .remove = __devexit_p(funnel_remove),
.driver = {
.name = "msm_funnel",
},
};
-int __init funnel_init(void)
+static int __init funnel_init(void)
{
return platform_driver_register(&funnel_driver);
}
+module_init(funnel_init);
-void funnel_exit(void)
+static void __exit funnel_exit(void)
{
platform_driver_unregister(&funnel_driver);
}
+module_exit(funnel_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Funnel driver");
diff --git a/arch/arm/mach-msm/qdss-priv.h b/arch/arm/mach-msm/qdss-priv.h
index b9f3072..f39bc52 100644
--- a/arch/arm/mach-msm/qdss-priv.h
+++ b/arch/arm/mach-msm/qdss-priv.h
@@ -58,15 +58,6 @@
#define BMVAL(val, lsb, msb) ((val & BM(lsb, msb)) >> lsb)
#define BVAL(val, n) ((val & BIT(n)) >> n)
-int etb_init(void);
-void etb_exit(void);
-int tpiu_init(void);
-void tpiu_exit(void);
-int funnel_init(void);
-void funnel_exit(void);
-int etm_init(void);
-void etm_exit(void);
-
void etb_enable(void);
void etb_disable(void);
void etb_dump(void);
diff --git a/arch/arm/mach-msm/qdss-tpiu.c b/arch/arm/mach-msm/qdss-tpiu.c
index 4481a0a..fa15635 100644
--- a/arch/arm/mach-msm/qdss-tpiu.c
+++ b/arch/arm/mach-msm/qdss-tpiu.c
@@ -108,7 +108,7 @@
return ret;
}
-static int tpiu_remove(struct platform_device *pdev)
+static int __devexit tpiu_remove(struct platform_device *pdev)
{
if (tpiu.enabled)
tpiu_disable();
@@ -119,18 +119,23 @@
static struct platform_driver tpiu_driver = {
.probe = tpiu_probe,
- .remove = tpiu_remove,
+ .remove = __devexit_p(tpiu_remove),
.driver = {
.name = "msm_tpiu",
},
};
-int __init tpiu_init(void)
+static int __init tpiu_init(void)
{
return platform_driver_register(&tpiu_driver);
}
+module_init(tpiu_init);
-void tpiu_exit(void)
+static void __exit tpiu_exit(void)
{
platform_driver_unregister(&tpiu_driver);
}
+module_exit(tpiu_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Trace Port Interface Unit driver");
diff --git a/arch/arm/mach-msm/qdss.c b/arch/arm/mach-msm/qdss.c
index 80ec65a..cfe65ad 100644
--- a/arch/arm/mach-msm/qdss.c
+++ b/arch/arm/mach-msm/qdss.c
@@ -24,26 +24,155 @@
#include "rpm_resources.h"
#include "qdss-priv.h"
+#define MAX_STR_LEN (65535)
+
enum {
QDSS_CLK_OFF,
QDSS_CLK_ON_DBG,
QDSS_CLK_ON_HSDBG,
};
+/*
+ * Exclusion rules for structure fields.
+ *
+ * S: qdss.sources_mutex protected.
+ * I: qdss.sink_mutex protected.
+ * C: qdss.clk_mutex protected.
+ */
struct qdss_ctx {
- struct kobject *modulekobj;
- uint8_t max_clk;
- uint8_t clk_count;
- struct mutex clk_mutex;
+ struct kobject *modulekobj;
+ struct msm_qdss_platform_data *pdata;
+ struct list_head sources; /* S: sources list */
+ struct mutex sources_mutex;
+ uint8_t sink_count; /* I: sink count */
+ struct mutex sink_mutex;
+ uint8_t max_clk;
+ uint8_t clk_count; /* C: clk count */
+ struct mutex clk_mutex;
};
static struct qdss_ctx qdss;
-
-struct kobject *qdss_get_modulekobj(void)
+/**
+ * qdss_get - get the qdss source handle
+ * @name: name of the qdss source
+ *
+ * Searches the sources list to get the qdss source handle for this source.
+ *
+ * CONTEXT:
+ * Typically called from init or probe functions
+ *
+ * RETURNS:
+ * pointer to struct qdss_source on success, %NULL on failure
+ */
+struct qdss_source *qdss_get(const char *name)
{
- return qdss.modulekobj;
+ struct qdss_source *src, *source = NULL;
+
+ mutex_lock(&qdss.sources_mutex);
+ list_for_each_entry(src, &qdss.sources, link) {
+ if (src->name) {
+ if (strncmp(src->name, name, MAX_STR_LEN))
+ continue;
+ source = src;
+ break;
+ }
+ }
+ mutex_unlock(&qdss.sources_mutex);
+
+ return source ? source : ERR_PTR(-ENOENT);
}
+EXPORT_SYMBOL(qdss_get);
+
+/**
+ * qdss_put - release the qdss source handle
+ * @name: name of the qdss source
+ *
+ * CONTEXT:
+ * Typically called from driver remove or exit functions
+ */
+void qdss_put(struct qdss_source *src)
+{
+}
+EXPORT_SYMBOL(qdss_put);
+
+/**
+ * qdss_enable - enable qdss for the source
+ * @src: handle for the source making the call
+ *
+ * Enables qdss block (relevant funnel ports and sink) if not already
+ * enabled, otherwise increments the reference count
+ *
+ * CONTEXT:
+ * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
+ *
+ * RETURNS:
+ * 0 on success, non-zero on failure
+ */
+int qdss_enable(struct qdss_source *src)
+{
+ int ret;
+
+ if (!src)
+ return -EINVAL;
+
+ ret = qdss_clk_enable();
+ if (ret)
+ goto err;
+
+ if ((qdss.pdata)->afamily) {
+ mutex_lock(&qdss.sink_mutex);
+ if (qdss.sink_count == 0) {
+ etb_disable();
+ tpiu_disable();
+ /* enable ETB first to avoid losing any trace data */
+ etb_enable();
+ }
+ qdss.sink_count++;
+ mutex_unlock(&qdss.sink_mutex);
+ }
+
+ funnel_enable(0x0, src->fport_mask);
+ return 0;
+err:
+ return ret;
+}
+EXPORT_SYMBOL(qdss_enable);
+
+/**
+ * qdss_disable - disable qdss for the source
+ * @src: handle for the source making the call
+ *
+ * Disables qdss block (relevant funnel ports and sink) if the reference count
+ * is one, otherwise decrements the reference count
+ *
+ * CONTEXT:
+ * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
+ */
+void qdss_disable(struct qdss_source *src)
+{
+ if (!src)
+ return;
+
+ if ((qdss.pdata)->afamily) {
+ mutex_lock(&qdss.sink_mutex);
+ if (WARN(qdss.sink_count == 0, "qdss is unbalanced\n"))
+ goto out;
+ if (qdss.sink_count == 1) {
+ etb_dump();
+ etb_disable();
+ }
+ qdss.sink_count--;
+ mutex_unlock(&qdss.sink_mutex);
+ }
+
+ funnel_disable(0x0, src->fport_mask);
+ qdss_clk_disable();
+ return;
+out:
+ mutex_unlock(&qdss.sink_mutex);
+}
+EXPORT_SYMBOL(qdss_disable);
/**
* qdss_clk_enable - enable qdss clocks
@@ -111,6 +240,11 @@
}
EXPORT_SYMBOL(qdss_clk_disable);
+struct kobject *qdss_get_modulekobj(void)
+{
+ return qdss.modulekobj;
+}
+
#define QDSS_ATTR(name) \
static struct kobj_attribute name##_attr = \
__ATTR(name, S_IRUGO | S_IWUSR, name##_show, name##_store)
@@ -136,6 +270,16 @@
}
QDSS_ATTR(max_clk);
+static void __init qdss_add_sources(struct qdss_source *srcs, size_t num)
+{
+ mutex_lock(&qdss.sources_mutex);
+ while (num--) {
+ list_add_tail(&srcs->link, &qdss.sources);
+ srcs++;
+ }
+ mutex_unlock(&qdss.sources_mutex);
+}
+
static int __init qdss_sysfs_init(void)
{
int ret;
@@ -158,58 +302,85 @@
return ret;
}
-static void qdss_sysfs_exit(void)
+static void __exit qdss_sysfs_exit(void)
{
sysfs_remove_file(qdss.modulekobj, &max_clk_attr.attr);
}
-static int __init qdss_init(void)
+static int __devinit qdss_probe(struct platform_device *pdev)
{
int ret;
+ struct qdss_source *src_table;
+ size_t num_srcs;
+ mutex_init(&qdss.sources_mutex);
mutex_init(&qdss.clk_mutex);
+ mutex_init(&qdss.sink_mutex);
+
+ if (pdev->dev.platform_data == NULL) {
+ pr_err("%s: platform data is NULL\n", __func__);
+ ret = -ENODEV;
+ goto err_pdata;
+ }
+ qdss.pdata = pdev->dev.platform_data;
+
+ INIT_LIST_HEAD(&qdss.sources);
+ src_table = (qdss.pdata)->src_table;
+ num_srcs = (qdss.pdata)->size;
+ qdss_add_sources(src_table, num_srcs);
+
+ pr_info("QDSS arch initialized\n");
+ return 0;
+err_pdata:
+ mutex_destroy(&qdss.sink_mutex);
+ mutex_destroy(&qdss.clk_mutex);
+ mutex_destroy(&qdss.sources_mutex);
+ pr_err("QDSS init failed\n");
+ return ret;
+}
+
+static int __devexit qdss_remove(struct platform_device *pdev)
+{
+ qdss_sysfs_exit();
+ mutex_destroy(&qdss.sink_mutex);
+ mutex_destroy(&qdss.clk_mutex);
+ mutex_destroy(&qdss.sources_mutex);
+
+ return 0;
+}
+
+static struct platform_driver qdss_driver = {
+ .probe = qdss_probe,
+ .remove = __devexit_p(qdss_remove),
+ .driver = {
+ .name = "msm_qdss",
+ },
+};
+
+static int __init qdss_init(void)
+{
+ return platform_driver_register(&qdss_driver);
+}
+arch_initcall(qdss_init);
+
+static int __init qdss_module_init(void)
+{
+ int ret;
ret = qdss_sysfs_init();
if (ret)
goto err_sysfs;
- ret = etb_init();
- if (ret)
- goto err_etb;
- ret = tpiu_init();
- if (ret)
- goto err_tpiu;
- ret = funnel_init();
- if (ret)
- goto err_funnel;
- ret = etm_init();
- if (ret)
- goto err_etm;
- pr_info("QDSS initialized\n");
+ pr_info("QDSS module initialized\n");
return 0;
-err_etm:
- funnel_exit();
-err_funnel:
- tpiu_exit();
-err_tpiu:
- etb_exit();
-err_etb:
- qdss_sysfs_exit();
err_sysfs:
- mutex_destroy(&qdss.clk_mutex);
- pr_err("QDSS init failed\n");
return ret;
}
-module_init(qdss_init);
+module_init(qdss_module_init);
static void __exit qdss_exit(void)
{
- qdss_sysfs_exit();
- etm_exit();
- funnel_exit();
- tpiu_exit();
- etb_exit();
- mutex_destroy(&qdss.clk_mutex);
+ platform_driver_unregister(&qdss_driver);
}
module_exit(qdss_exit);
diff --git a/arch/arm/mach-msm/rpm.c b/arch/arm/mach-msm/rpm.c
index 2eac3c1..b0fa3d2 100644
--- a/arch/arm/mach-msm/rpm.c
+++ b/arch/arm/mach-msm/rpm.c
@@ -437,7 +437,6 @@
*
* Return value:
* 0: success
- * -EINTR: interrupted
* -EINVAL: invalid <ctx> or invalid id in <req> array
* -ENOSPC: request rejected
* -ENODEV: RPM driver not initialized
@@ -464,10 +463,7 @@
rc = msm_rpm_set_exclusive_noirq(ctx, sel_masks, req, count);
spin_unlock_irqrestore(&msm_rpm_lock, flags);
} else {
- rc = mutex_lock_interruptible(&msm_rpm_mutex);
- if (rc)
- goto set_common_exit;
-
+ mutex_lock(&msm_rpm_mutex);
rc = msm_rpm_set_exclusive(ctx, sel_masks, req, count);
mutex_unlock(&msm_rpm_mutex);
}
@@ -479,7 +475,6 @@
/*
* Return value:
* 0: success
- * -EINTR: interrupted
* -EINVAL: invalid <ctx> or invalid id in <req> array
* -ENODEV: RPM driver not initialized.
*/
@@ -518,10 +513,7 @@
spin_unlock_irqrestore(&msm_rpm_lock, flags);
BUG_ON(rc);
} else {
- rc = mutex_lock_interruptible(&msm_rpm_mutex);
- if (rc)
- goto clear_common_exit;
-
+ mutex_lock(&msm_rpm_mutex);
rc = msm_rpm_set_exclusive(ctx, sel_masks, r, ARRAY_SIZE(r));
mutex_unlock(&msm_rpm_mutex);
BUG_ON(rc);
@@ -683,7 +675,6 @@
*
* Return value:
* 0: success
- * -EINTR: interrupted
* -EINVAL: invalid <ctx> or invalid id in <req> array
* -ENOSPC: request rejected
* -ENODEV: RPM driver not initialized
@@ -724,7 +715,6 @@
*
* Return value:
* 0: success
- * -EINTR: interrupted
* -EINVAL: invalid <ctx> or invalid id in <req> array
*/
int msm_rpm_clear(int ctx, struct msm_rpm_iv_pair *req, int count)
@@ -769,7 +759,6 @@
*
* Return value:
* 0: success
- * -EINTR: interrupted
* -EINVAL: invalid id in <req> array
* -ENODEV: RPM driver not initialized
*/
@@ -787,9 +776,7 @@
if (rc)
goto register_notification_exit;
- rc = mutex_lock_interruptible(&msm_rpm_mutex);
- if (rc)
- goto register_notification_exit;
+ mutex_lock(&msm_rpm_mutex);
if (!msm_rpm_init_notif_done) {
msm_rpm_initialize_notification();
@@ -823,7 +810,6 @@
*
* Return value:
* 0: success
- * -EINTR: interrupted
* -ENODEV: RPM driver not initialized
*/
int msm_rpm_unregister_notification(struct msm_rpm_notification *n)
@@ -831,13 +817,10 @@
unsigned long flags;
unsigned int ctx;
struct msm_rpm_notif_config cfg;
- int rc;
+ int rc = 0;
int i;
- rc = mutex_lock_interruptible(&msm_rpm_mutex);
- if (rc)
- goto unregister_notification_exit;
-
+ mutex_lock(&msm_rpm_mutex);
ctx = MSM_RPM_CTX_SET_0;
cfg = msm_rpm_notif_cfgs[ctx];
@@ -854,7 +837,6 @@
msm_rpm_update_notification(ctx, &msm_rpm_notif_cfgs[ctx], &cfg);
mutex_unlock(&msm_rpm_mutex);
-unregister_notification_exit:
return rc;
}
EXPORT_SYMBOL(msm_rpm_unregister_notification);
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 546a917..6282eca 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -895,6 +895,9 @@
if (latency_us < level->latency_us)
continue;
+ if (sleep_us <= level->time_overhead_us)
+ continue;
+
if (!msm_rpmrs_irqs_detectable(&level->rs_limits,
irqs_detectable, gpio_detectable))
continue;
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index 04dc392..bc4bd21 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -23,6 +23,8 @@
#include <linux/io.h>
#include <linux/kthread.h>
#include <linux/time.h>
+#include <linux/wakelock.h>
+#include <linux/suspend.h>
#include <asm/current.h>
@@ -43,9 +45,12 @@
struct subsys_data *subsys_ptrs[];
};
-struct restart_thread_data {
+struct restart_wq_data {
struct subsys_data *subsys;
+ struct wake_lock ssr_wake_lock;
+ char wakelockname[64];
int coupled;
+ struct work_struct work;
};
struct restart_log {
@@ -56,6 +61,7 @@
static int restart_level;
static int enable_ramdumps;
+struct workqueue_struct *ssr_wq;
static LIST_HEAD(restart_log_list);
static LIST_HEAD(subsystem_list);
@@ -297,9 +303,10 @@
mutex_unlock(&restart_log_mutex);
}
-static int subsystem_restart_thread(void *data)
+static void subsystem_restart_wq_func(struct work_struct *work)
{
- struct restart_thread_data *r_work = data;
+ struct restart_wq_data *r_work = container_of(work,
+ struct restart_wq_data, work);
struct subsys_data **restart_list;
struct subsys_data *subsys = r_work->subsys;
struct subsys_soc_restart_order *soc_restart_order = NULL;
@@ -334,10 +341,8 @@
/* Try to acquire shutdown_lock. If this fails, these subsystems are
* already being restarted - return.
*/
- if (!mutex_trylock(shutdown_lock)) {
- kfree(data);
- do_exit(0);
- }
+ if (!mutex_trylock(shutdown_lock))
+ goto out;
pr_debug("[%p]: Attempting to get powerup lock!\n", current);
@@ -430,15 +435,17 @@
pr_debug("[%p]: Released powerup lock!\n", current);
- kfree(data);
- do_exit(0);
+out:
+ wake_unlock(&r_work->ssr_wake_lock);
+ wake_lock_destroy(&r_work->ssr_wake_lock);
+ kfree(r_work);
}
int subsystem_restart(const char *subsys_name)
{
struct subsys_data *subsys;
- struct task_struct *tsk;
- struct restart_thread_data *data = NULL;
+ struct restart_wq_data *data = NULL;
+ int rc;
if (!subsys_name) {
pr_err("Invalid subsystem name.\n");
@@ -459,7 +466,7 @@
}
if (restart_level != RESET_SOC) {
- data = kzalloc(sizeof(struct restart_thread_data), GFP_KERNEL);
+ data = kzalloc(sizeof(struct restart_wq_data), GFP_KERNEL);
if (!data) {
restart_level = RESET_SOC;
pr_warn("Failed to alloc restart data. Resetting.\n");
@@ -482,18 +489,18 @@
pr_debug("Restarting %s [level=%d]!\n", subsys_name,
restart_level);
- /* Let the kthread handle the actual restarting. Using a
- * workqueue will not work since all restart requests are
- * serialized and it prevents the short circuiting of
- * restart requests for subsystems already in a restart
- * sequence.
- */
- tsk = kthread_run(subsystem_restart_thread, data,
- "subsystem_restart_thread");
- if (IS_ERR(tsk))
- panic("%s: Unable to create thread to restart %s",
- __func__, subsys->name);
+ snprintf(data->wakelockname, sizeof(data->wakelockname),
+ "ssr(%s)", subsys_name);
+ wake_lock_init(&data->ssr_wake_lock, WAKE_LOCK_SUSPEND,
+ data->wakelockname);
+ wake_lock(&data->ssr_wake_lock);
+ INIT_WORK(&data->work, subsystem_restart_wq_func);
+ rc = schedule_work(&data->work);
+
+ if (rc < 0)
+ panic("%s: Unable to schedule work to restart %s",
+ __func__, subsys->name);
break;
case RESET_SOC:
@@ -597,6 +604,11 @@
restart_level = RESET_SOC;
+ ssr_wq = alloc_workqueue("ssr_wq", 0, 0);
+
+ if (!ssr_wq)
+ panic("Couldn't allocate workqueue for subsystem restart.\n");
+
ret = ssr_init_soc_restart_orders();
return ret;
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 1bdec12..90948ea 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -84,7 +84,6 @@
MODULE_NAME);
return IRQ_HANDLED;
}
- disable_irq_nosync(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ);
ss_restart_inprogress = true;
ret = schedule_work(&riva_fatal_work);
return IRQ_HANDLED;
@@ -115,6 +114,7 @@
{
pil_force_shutdown("wcnss");
flush_delayed_work(&cancel_vote_work);
+ disable_irq_nosync(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ);
return 0;
}
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index cde8031..0ff30c3 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -1136,6 +1136,7 @@
apq8064_cdp MACH_APQ8064_CDP APQ8064_CDP 3948
apq8064_mtp MACH_APQ8064_MTP APQ8064_MTP 3949
apq8064_liquid MACH_APQ8064_LIQUID APQ8064_LIQUID 3951
+mpq8064_cdp MACH_MPQ8064_CDP MPQ8064_CDP 3993
mpq8064_hrd MACH_MPQ8064_HRD MPQ8064_HRD 3994
mpq8064_dtv MACH_MPQ8064_DTV MPQ8064_DTV 3995
msm7627a_qrd3 MACH_MSM7627A_QRD3 MSM7627A_QRD3 4005
diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile
index 5189388..c3367b5 100644
--- a/drivers/gpu/msm/Makefile
+++ b/drivers/gpu/msm/Makefile
@@ -16,6 +16,7 @@
msm_kgsl_core-$(CONFIG_MSM_KGSL_DRM) += kgsl_drm.o
msm_kgsl_core-$(CONFIG_MSM_SCM) += kgsl_pwrscale_trustzone.o
msm_kgsl_core-$(CONFIG_MSM_SLEEP_STATS_DEVICE) += kgsl_pwrscale_idlestats.o
+msm_kgsl_core-$(CONFIG_MSM_DCVS) += kgsl_pwrscale_msm.o
msm_adreno-y += \
adreno_ringbuffer.o \
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 8ccd462..6f575ec 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -601,9 +601,7 @@
mutex_lock(&device->mutex);
if (device->state & (KGSL_STATE_ACTIVE | KGSL_STATE_NAP)) {
- if ((device->requested_state != KGSL_STATE_SLEEP) &&
- (device->requested_state != KGSL_STATE_SLUMBER))
- kgsl_pwrscale_idle(device);
+ kgsl_pwrscale_idle(device);
if (kgsl_pwrctrl_sleep(device) != 0) {
mod_timer(&device->idle_timer,
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index f474c21..2222cdf 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -21,6 +21,7 @@
#define KGSL_PWRLEVEL_TURBO 0
#define KGSL_PWRLEVEL_NOMINAL 1
+#define KGSL_PWRLEVEL_LAST_OFFSET 2
#define KGSL_MAX_CLKS 5
diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c
index d0b2a41..1cecbc7 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.c
+++ b/drivers/gpu/msm/kgsl_pwrscale.c
@@ -45,6 +45,9 @@
#ifdef CONFIG_MSM_SLEEP_STATS_DEVICE
&kgsl_pwrscale_policy_idlestats,
#endif
+#ifdef CONFIG_MSM_DCVS
+ &kgsl_pwrscale_policy_msm,
+#endif
NULL
};
diff --git a/drivers/gpu/msm/kgsl_pwrscale.h b/drivers/gpu/msm/kgsl_pwrscale.h
index b4f831e..6023476 100644
--- a/drivers/gpu/msm/kgsl_pwrscale.h
+++ b/drivers/gpu/msm/kgsl_pwrscale.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -54,6 +54,7 @@
extern struct kgsl_pwrscale_policy kgsl_pwrscale_policy_tz;
extern struct kgsl_pwrscale_policy kgsl_pwrscale_policy_idlestats;
+extern struct kgsl_pwrscale_policy kgsl_pwrscale_policy_msm;
int kgsl_pwrscale_init(struct kgsl_device *device);
void kgsl_pwrscale_close(struct kgsl_device *device);
diff --git a/drivers/gpu/msm/kgsl_pwrscale_msm.c b/drivers/gpu/msm/kgsl_pwrscale_msm.c
new file mode 100644
index 0000000..f77a02b
--- /dev/null
+++ b/drivers/gpu/msm/kgsl_pwrscale_msm.c
@@ -0,0 +1,195 @@
+/* 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/slab.h>
+#include <mach/msm_dcvs.h>
+#include "kgsl.h"
+#include "kgsl_pwrscale.h"
+#include "kgsl_device.h"
+
+struct msm_priv {
+ struct kgsl_device *device;
+ int enabled;
+ int handle;
+ unsigned int cur_freq;
+ struct msm_dcvs_idle idle_source;
+ struct msm_dcvs_freq freq_sink;
+ struct msm_dcvs_core_info *core_info;
+};
+
+static int msm_idle_enable(struct msm_dcvs_idle *self,
+ enum msm_core_control_event event)
+{
+ struct msm_priv *priv = container_of(self, struct msm_priv,
+ idle_source);
+
+ switch (event) {
+ case MSM_DCVS_ENABLE_IDLE_PULSE:
+ priv->enabled = true;
+ break;
+ case MSM_DCVS_DISABLE_IDLE_PULSE:
+ priv->enabled = false;
+ break;
+ case MSM_DCVS_ENABLE_HIGH_LATENCY_MODES:
+ case MSM_DCVS_DISABLE_HIGH_LATENCY_MODES:
+ break;
+ }
+ return 0;
+}
+
+/* Set the requested frequency if it is within 5MHz (delta) of a
+ * supported frequency.
+ */
+static int msm_set_freq(struct msm_dcvs_freq *self,
+ unsigned int freq)
+{
+ int i, delta = 5000000;
+ struct msm_priv *priv = container_of(self, struct msm_priv,
+ freq_sink);
+ struct kgsl_device *device = priv->device;
+ struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+
+ /* msm_dcvs manager uses frequencies in kHz */
+ freq *= 1000;
+ for (i = 0; i < pwr->num_pwrlevels; i++)
+ if (abs(pwr->pwrlevels[i].gpu_freq - freq) < delta)
+ break;
+ if (i == pwr->num_pwrlevels)
+ return 0;
+
+ mutex_lock(&device->mutex);
+ kgsl_pwrctrl_pwrlevel_change(device, i);
+ priv->cur_freq = pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq;
+ mutex_unlock(&device->mutex);
+
+ /* return current frequency in kHz */
+ return priv->cur_freq / 1000;
+}
+
+static unsigned int msm_get_freq(struct msm_dcvs_freq *self)
+{
+ struct msm_priv *priv = container_of(self, struct msm_priv,
+ freq_sink);
+ /* return current frequency in kHz */
+ return priv->cur_freq / 1000;
+}
+
+static void msm_busy(struct kgsl_device *device,
+ struct kgsl_pwrscale *pwrscale)
+{
+ struct msm_priv *priv = pwrscale->priv;
+ if (priv->enabled)
+ msm_dcvs_idle(priv->handle, MSM_DCVS_IDLE_EXIT, 0);
+ return;
+}
+
+static void msm_idle(struct kgsl_device *device,
+ struct kgsl_pwrscale *pwrscale)
+{
+ struct msm_priv *priv = pwrscale->priv;
+ if (priv->enabled && pwrscale->gpu_busy)
+ msm_dcvs_idle(priv->handle, MSM_DCVS_IDLE_ENTER, 0);
+
+ return;
+}
+
+static void msm_sleep(struct kgsl_device *device,
+ struct kgsl_pwrscale *pwrscale)
+{
+ /* do we need to reset any parameters here? */
+}
+
+static int msm_init(struct kgsl_device *device,
+ struct kgsl_pwrscale *pwrscale)
+{
+ struct msm_priv *priv;
+ struct msm_dcvs_freq_entry *tbl;
+ int i, ret, low_level;
+ struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+ struct platform_device *pdev =
+ container_of(device->parentdev, struct platform_device, dev);
+ struct kgsl_device_platform_data *pdata = pdev->dev.platform_data;
+
+ priv = pwrscale->priv = kzalloc(sizeof(struct msm_priv),
+ GFP_KERNEL);
+ if (pwrscale->priv == NULL)
+ return -ENOMEM;
+
+ priv->core_info = pdata->core_info;
+ tbl = priv->core_info->freq_tbl;
+ /* Fill in frequency table from low to high, reversing order. */
+ low_level = pwr->num_pwrlevels - KGSL_PWRLEVEL_LAST_OFFSET;
+ for (i = 0; i <= low_level; i++)
+ tbl[i].freq =
+ pwr->pwrlevels[low_level - i].gpu_freq / 1000;
+ ret = msm_dcvs_register_core(device->name, 0, priv->core_info);
+ if (ret) {
+ KGSL_PWR_ERR(device, "msm_dcvs_register_core failed");
+ goto err;
+ }
+
+ priv->device = device;
+ priv->idle_source.enable = msm_idle_enable;
+ priv->idle_source.core_name = device->name;
+ priv->handle = msm_dcvs_idle_source_register(&priv->idle_source);
+ if (priv->handle < 0) {
+ ret = priv->handle;
+ KGSL_PWR_ERR(device, "msm_dcvs_idle_source_register failed\n");
+ goto err;
+ }
+
+ priv->freq_sink.core_name = device->name;
+ priv->freq_sink.set_frequency = msm_set_freq;
+ priv->freq_sink.get_frequency = msm_get_freq;
+ ret = msm_dcvs_freq_sink_register(&priv->freq_sink);
+ if (ret >= 0) {
+ if (device->ftbl->isidle(device)) {
+ device->pwrscale.gpu_busy = 0;
+ msm_dcvs_idle(priv->handle, MSM_DCVS_IDLE_ENTER, 0);
+ } else {
+ device->pwrscale.gpu_busy = 1;
+ }
+ return 0;
+ }
+
+ KGSL_PWR_ERR(device, "msm_dcvs_freq_sink_register failed\n");
+ msm_dcvs_idle_source_unregister(&priv->idle_source);
+
+err:
+ kfree(pwrscale->priv);
+ pwrscale->priv = NULL;
+
+ return ret;
+}
+
+static void msm_close(struct kgsl_device *device,
+ struct kgsl_pwrscale *pwrscale)
+{
+ struct msm_priv *priv = pwrscale->priv;
+
+ if (pwrscale->priv == NULL)
+ return;
+ msm_dcvs_idle_source_unregister(&priv->idle_source);
+ msm_dcvs_freq_sink_unregister(&priv->freq_sink);
+ kfree(pwrscale->priv);
+ pwrscale->priv = NULL;
+}
+
+struct kgsl_pwrscale_policy kgsl_pwrscale_policy_msm = {
+ .name = "msm",
+ .init = msm_init,
+ .idle = msm_idle,
+ .busy = msm_busy,
+ .sleep = msm_sleep,
+ .close = msm_close,
+};
diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c
index d083702..5634a19 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.c
+++ b/drivers/gpu/msm/kgsl_sharedmem.c
@@ -443,7 +443,7 @@
sg_set_page(&memdesc->sg[i], page, PAGE_SIZE, 0);
}
- kgsl_cache_range_op(memdesc, KGSL_CACHE_OP_INV);
+ kgsl_cache_range_op(memdesc, KGSL_CACHE_OP_FLUSH);
ret = kgsl_mmu_map(pagetable, memdesc, protflags);
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index a9b8e40..6744479 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -21,27 +21,22 @@
#include <media/rc-core.h>
#include <media/gpio-ir-recv.h>
-#define TSOP_DRIVER_NAME "gpio-rc-recv"
-#define TSOP_DEVICE_NAME "gpio_ir_recv"
+#define GPIO_IR_DRIVER_NAME "gpio-rc-recv"
+#define GPIO_IR_DEVICE_NAME "gpio_ir_recv"
struct gpio_rc_dev {
struct rc_dev *rcdev;
- struct mutex lock;
unsigned int gpio_nr;
bool active_low;
- bool can_wakeup;
- struct work_struct work;
};
-static void ir_decoder_work(struct work_struct *work)
+static irqreturn_t gpio_ir_recv_irq(int irq, void *dev_id)
{
- struct gpio_rc_dev *gpio_dev = container_of(work,
- struct gpio_rc_dev, work);
+ struct gpio_rc_dev *gpio_dev = dev_id;
unsigned int gval;
int rc = 0;
enum raw_event_type type = IR_SPACE;
- mutex_lock(&gpio_dev->lock);
gval = gpio_get_value_cansleep(gpio_dev->gpio_nr);
if (gval < 0)
@@ -60,15 +55,6 @@
ir_raw_event_handle(gpio_dev->rcdev);
err_get_value:
- mutex_unlock(&gpio_dev->lock);
-}
-
-static irqreturn_t gpio_ir_recv_irq_handler(int irq, void *data)
-{
- struct gpio_rc_dev *gpio_dev = data;
-
- schedule_work(&gpio_dev->work);
-
return IRQ_HANDLED;
}
@@ -78,7 +64,7 @@
struct rc_dev *rcdev;
const struct gpio_ir_recv_platform_data *pdata =
pdev->dev.platform_data;
- int rc = 0;
+ int rc;
if (!pdata)
return -EINVAL;
@@ -90,8 +76,6 @@
if (!gpio_dev)
return -ENOMEM;
- mutex_init(&gpio_dev->lock);
-
rcdev = rc_allocate_device();
if (!rcdev) {
rc = -ENOMEM;
@@ -99,18 +83,15 @@
}
rcdev->driver_type = RC_DRIVER_IR_RAW;
- rcdev->allowed_protos = RC_TYPE_NEC;
- rcdev->input_name = TSOP_DEVICE_NAME;
+ rcdev->allowed_protos = RC_TYPE_ALL;
+ rcdev->input_name = GPIO_IR_DEVICE_NAME;
rcdev->input_id.bustype = BUS_HOST;
- rcdev->driver_name = TSOP_DRIVER_NAME;
- rcdev->map_name = RC_MAP_SAMSUNG_NECX;
+ rcdev->driver_name = GPIO_IR_DRIVER_NAME;
+ rcdev->map_name = RC_MAP_EMPTY;
gpio_dev->rcdev = rcdev;
gpio_dev->gpio_nr = pdata->gpio_nr;
gpio_dev->active_low = pdata->active_low;
- gpio_dev->can_wakeup = pdata->can_wakeup;
-
- INIT_WORK(&gpio_dev->work, ir_decoder_work);
rc = gpio_request(pdata->gpio_nr, "gpio-ir-recv");
if (rc < 0)
@@ -127,22 +108,15 @@
platform_set_drvdata(pdev, gpio_dev);
- rc = request_irq(gpio_to_irq(pdata->gpio_nr), gpio_ir_recv_irq_handler,
+ rc = request_any_context_irq(gpio_to_irq(pdata->gpio_nr),
+ gpio_ir_recv_irq,
IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
- "gpio-ir-recv-irq", gpio_dev);
+ "gpio-ir-recv-irq", gpio_dev);
if (rc < 0)
goto err_request_irq;
- if (pdata->can_wakeup == true) {
- rc = enable_irq_wake(gpio_to_irq(pdata->gpio_nr));
- if (rc < 0)
- goto err_enable_irq_wake;
- }
-
return 0;
-err_enable_irq_wake:
- free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev);
err_request_irq:
platform_set_drvdata(pdev, NULL);
rc_unregister_device(rcdev);
@@ -153,7 +127,6 @@
rc_free_device(rcdev);
rcdev = NULL;
err_allocate_device:
- mutex_destroy(&gpio_dev->lock);
kfree(gpio_dev);
return rc;
}
@@ -162,24 +135,57 @@
{
struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);
- flush_work_sync(&gpio_dev->work);
- disable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr));
free_irq(gpio_to_irq(gpio_dev->gpio_nr), gpio_dev);
platform_set_drvdata(pdev, NULL);
rc_unregister_device(gpio_dev->rcdev);
gpio_free(gpio_dev->gpio_nr);
rc_free_device(gpio_dev->rcdev);
- mutex_destroy(&gpio_dev->lock);
kfree(gpio_dev);
return 0;
}
+#ifdef CONFIG_PM
+static int gpio_ir_recv_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr));
+ else
+ disable_irq(gpio_to_irq(gpio_dev->gpio_nr));
+
+ return 0;
+}
+
+static int gpio_ir_recv_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct gpio_rc_dev *gpio_dev = platform_get_drvdata(pdev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(gpio_to_irq(gpio_dev->gpio_nr));
+ else
+ enable_irq(gpio_to_irq(gpio_dev->gpio_nr));
+
+ return 0;
+}
+
+static const struct dev_pm_ops gpio_ir_recv_pm_ops = {
+ .suspend = gpio_ir_recv_suspend,
+ .resume = gpio_ir_recv_resume,
+};
+#endif
+
static struct platform_driver gpio_ir_recv_driver = {
.probe = gpio_ir_recv_probe,
.remove = __devexit_p(gpio_ir_recv_remove),
.driver = {
- .name = TSOP_DRIVER_NAME,
+ .name = GPIO_IR_DRIVER_NAME,
.owner = THIS_MODULE,
+#ifdef CONFIG_PM
+ .pm = &gpio_ir_recv_pm_ops,
+#endif
},
};
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 175a441..8d59590 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -1366,6 +1366,14 @@
return rc;
}
+ /* The number of camera instance should be controlled by the
+ resource manager. Currently supporting one active instance
+ until multiple instances are supported */
+ if (atomic_read(&ps->number_pcam_active) > 0) {
+ pr_err("%s Cannot have more than one active camera %d\n",
+ __func__, atomic_read(&ps->number_pcam_active));
+ return -EINVAL;
+ }
/* book keeping this camera session*/
ps->pcam_active = pcam;
atomic_inc(&ps->number_pcam_active);
@@ -1411,6 +1419,9 @@
{
int i;
int rc = -EINVAL;
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ int ion_client_created = 0;
+#endif
/*struct msm_isp_ops *p_isp = 0;*/
/* get the video device */
struct msm_cam_v4l2_device *pcam = video_drvdata(f);
@@ -1442,7 +1453,9 @@
pcam_inst->pcam = pcam;
pcam->dev_inst[i] = pcam_inst;
- D("%s for %s\n", __func__, pcam->pdev->name);
+ D("%s index %d nodeid %d count %d\n", __func__,
+ pcam_inst->my_index,
+ pcam->vnode_id, pcam->use_count);
pcam->use_count++;
if (pcam->use_count == 1) {
@@ -1450,19 +1463,19 @@
if (rc < 0) {
pr_err("%s: cam_server_open_session failed %d\n",
__func__, rc);
- mutex_unlock(&pcam->vid_lock);
- return rc;
+ goto err;
}
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
pcam->mctl.client = msm_ion_client_create(-1, "camera");
kref_init(&pcam->mctl.refcount);
+ ion_client_created = 1;
#endif
/* Should be set to sensor ops if any but right now its OK!! */
if (!pcam->mctl.mctl_open) {
D("%s: media contoller is not inited\n",
__func__);
- mutex_unlock(&pcam->vid_lock);
- return -ENODEV;
+ rc = -ENODEV;
+ goto err;
}
/* Now we really have to activate the camera */
@@ -1470,9 +1483,8 @@
rc = pcam->mctl.mctl_open(&(pcam->mctl), MSM_APPS_ID_V4L2);
if (rc < 0) {
- mutex_unlock(&pcam->vid_lock);
pr_err("%s: HW open failed rc = 0x%x\n", __func__, rc);
- return rc;
+ goto err;
}
pcam->mctl.sync.pcam_sync = pcam;
@@ -1480,24 +1492,21 @@
rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
pcam->mctl.isp_sdev->sd);
if (rc < 0) {
- mutex_unlock(&pcam->vid_lock);
pr_err("%s: v4l2_device_register_subdev failed rc = %d\n",
__func__, rc);
- return rc;
+ goto err;
}
if (pcam->mctl.isp_sdev->sd_vpe) {
rc = v4l2_device_register_subdev(&pcam->v4l2_dev,
pcam->mctl.isp_sdev->sd_vpe);
if (rc < 0) {
- mutex_unlock(&pcam->vid_lock);
- return rc;
+ goto err;
}
}
rc = msm_setup_v4l2_event_queue(&pcam_inst->eventHandle,
pcam->pvdev);
if (rc < 0) {
- mutex_unlock(&pcam->vid_lock);
- return rc;
+ goto err;
}
}
pcam_inst->vbqueue_initialized = 0;
@@ -1522,6 +1531,21 @@
D("%s: end", __func__);
/* rc = msm_cam_server_open_session(g_server_dev, pcam);*/
return rc;
+
+err:
+ if (pcam->use_count == 1) {
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ if (ion_client_created) {
+ pr_err("%s: destroy ion client", __func__);
+ kref_put(&pcam->mctl.refcount, msm_release_ion_client);
+ }
+#endif
+ pcam->dev_inst[i] = NULL;
+ pcam->use_count = 0;
+ }
+ mutex_unlock(&pcam->vid_lock);
+ kfree(pcam_inst);
+ return rc;
}
static int msm_addr_remap(struct msm_cam_v4l2_dev_inst *pcam_inst,
@@ -1622,6 +1646,8 @@
if (pcam_inst->vbqueue_initialized)
vb2_queue_release(&pcam_inst->vid_bufq);
D("%s Closing down instance %p ", __func__, pcam_inst);
+ D("%s index %d nodeid %d count %d\n", __func__, pcam_inst->my_index,
+ pcam->vnode_id, pcam->use_count);
pcam->dev_inst[pcam_inst->my_index] = NULL;
if (pcam_inst->my_index == 0) {
v4l2_fh_del(&pcam_inst->eventHandle);
@@ -2638,7 +2664,7 @@
D("%s done, rc = %d\n", __func__, rc);
D("%s number of sensors connected is %d\n", __func__,
- g_server_dev.camera_info.num_cameras);
+ g_server_dev.camera_info.num_cameras);
/* register the subdevice, must be done for callbacks */
rc = v4l2_device_register_subdev(&pcam->v4l2_dev, sensor_sd);
diff --git a/drivers/mfd/pm8xxx-misc.c b/drivers/mfd/pm8xxx-misc.c
index b655848..64c0bd1 100644
--- a/drivers/mfd/pm8xxx-misc.c
+++ b/drivers/mfd/pm8xxx-misc.c
@@ -999,6 +999,10 @@
{
int rc;
+ /* dVdd preloading is not needed for PMIC PM8901 rev 2.3 and beyond. */
+ if (pm8xxx_get_revision(chip->dev->parent) >= PM8XXX_REVISION_8901_2p3)
+ return 0;
+
rc = pm8xxx_writeb(chip->dev->parent, 0x0BD, 0x0F);
if (rc)
pr_err("pm8xxx_writeb failed for 0x0BD, rc=%d\n", rc);
diff --git a/drivers/mfd/pmic8901.c b/drivers/mfd/pmic8901.c
index aec382a..63ea55a 100644
--- a/drivers/mfd/pmic8901.c
+++ b/drivers/mfd/pmic8901.c
@@ -270,11 +270,23 @@
return rc;
}
+static const char * const pm8901_rev_names[] = {
+ [PM8XXX_REVISION_8901_TEST] = "test",
+ [PM8XXX_REVISION_8901_1p0] = "1.0",
+ [PM8XXX_REVISION_8901_1p1] = "1.1",
+ [PM8XXX_REVISION_8901_2p0] = "2.0",
+ [PM8XXX_REVISION_8901_2p1] = "2.1",
+ [PM8XXX_REVISION_8901_2p2] = "2.2",
+ [PM8XXX_REVISION_8901_2p3] = "2.3",
+};
+
static int __devinit pm8901_probe(struct platform_device *pdev)
{
int rc;
struct pm8901_platform_data *pdata = pdev->dev.platform_data;
+ const char *revision_name = "unknown";
struct pm8901_chip *pmic;
+ int revision;
if (pdata == NULL) {
pr_err("%s: No platform_data or IRQ.\n", __func__);
@@ -298,7 +310,11 @@
pr_err("%s: Failed reading version register rc=%d.\n",
__func__, rc);
- pr_info("%s: PMIC REVISION = %X\n", __func__, pmic->revision);
+ pr_info("%s: PMIC revision reg: %02X\n", __func__, pmic->revision);
+ revision = pm8xxx_get_revision(pmic->dev);
+ if (revision >= 0 && revision < ARRAY_SIZE(pm8901_rev_names))
+ revision_name = pm8901_rev_names[revision];
+ pr_info("%s: PMIC version: PM8901 rev %s\n", __func__, revision_name);
(void) memcpy((void *)&pmic->pdata, (const void *)pdata,
sizeof(pmic->pdata));
diff --git a/drivers/misc/pmic8058-xoadc.c b/drivers/misc/pmic8058-xoadc.c
index 14b790f..3452672 100644
--- a/drivers/misc/pmic8058-xoadc.c
+++ b/drivers/misc/pmic8058-xoadc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -650,23 +650,6 @@
#define PM8058_XOADC_DEV_PM_OPS NULL
#endif
-static int __devexit pm8058_xoadc_teardown(struct platform_device *pdev)
-{
- struct pmic8058_adc *adc_pmic = platform_get_drvdata(pdev);
-
- if (adc_pmic->pdata->xoadc_vreg_shutdown != NULL)
- adc_pmic->pdata->xoadc_vreg_shutdown();
-
- wake_lock_destroy(&adc_pmic->adc_wakelock);
- msm_xo_put(adc_pmic->adc_voter);
- platform_set_drvdata(pdev, NULL);
- device_init_wakeup(&pdev->dev, 0);
- kfree(adc_pmic);
- xoadc_initialized = false;
-
- return 0;
-}
-
static int __devinit pm8058_xoadc_probe(struct platform_device *pdev)
{
struct xoadc_platform_data *pdata = pdev->dev.platform_data;
@@ -678,7 +661,7 @@
return -EINVAL;
}
- adc_pmic = kzalloc(sizeof(struct pmic8058_adc), GFP_KERNEL);
+ adc_pmic = devm_kzalloc(&pdev->dev, sizeof(*adc_pmic), GFP_KERNEL);
if (!adc_pmic) {
dev_err(&pdev->dev, "Unable to allocate memory\n");
return -ENOMEM;
@@ -693,17 +676,16 @@
if (adc_pmic->xoadc_num > XOADC_PMIC_0) {
dev_err(&pdev->dev, "ADC device not supported\n");
- rc = -EINVAL;
- goto err_cleanup;
+ return -EINVAL;
}
adc_pmic->pdata = pdata;
- adc_pmic->adc_graph = kzalloc(sizeof(struct linear_graph)
- * MAX_CHANNEL_PROPERTIES_QUEUE, GFP_KERNEL);
+ adc_pmic->adc_graph = devm_kzalloc(&pdev->dev,
+ sizeof(struct linear_graph) * MAX_CHANNEL_PROPERTIES_QUEUE,
+ GFP_KERNEL);
if (!adc_pmic->adc_graph) {
dev_err(&pdev->dev, "Unable to allocate memory\n");
- rc = -ENOMEM;
- goto err_cleanup;
+ return -ENOMEM;
}
/* Will be replaced by individual channel calibration */
@@ -739,32 +721,29 @@
INIT_LIST_HEAD(&adc_pmic->conv_queue_list->slots);
adc_pmic->adc_irq = platform_get_irq(pdev, 0);
- if (adc_pmic->adc_irq < 0) {
- rc = -ENXIO;
- goto err_cleanup;
- }
+ if (adc_pmic->adc_irq < 0)
+ return -ENXIO;
rc = request_threaded_irq(adc_pmic->adc_irq,
NULL, pm8058_xoadc,
IRQF_TRIGGER_RISING, "pm8058_adc_interrupt", adc_pmic);
if (rc) {
dev_err(&pdev->dev, "failed to request adc irq\n");
- goto err_cleanup;
+ return rc;
}
disable_irq(adc_pmic->adc_irq);
- device_init_wakeup(&pdev->dev, pdata->xoadc_wakeup);
-
if (adc_pmic->adc_voter == NULL) {
adc_pmic->adc_voter = msm_xo_get(MSM_XO_TCXO_D1,
"pmic8058_xoadc");
if (IS_ERR(adc_pmic->adc_voter)) {
dev_err(&pdev->dev, "Failed to get XO vote\n");
- goto err_cleanup;
+ return PTR_ERR(adc_pmic->adc_voter);
}
}
+ device_init_wakeup(&pdev->dev, pdata->xoadc_wakeup);
wake_lock_init(&adc_pmic->adc_wakelock, WAKE_LOCK_SUSPEND,
"pmic8058_xoadc_wakelock");
@@ -777,11 +756,21 @@
xoadc_calib_first_adc = false;
return 0;
+}
-err_cleanup:
- pm8058_xoadc_teardown(pdev);
+static int __devexit pm8058_xoadc_teardown(struct platform_device *pdev)
+{
+ struct pmic8058_adc *adc_pmic = platform_get_drvdata(pdev);
- return rc;
+ if (adc_pmic->pdata->xoadc_vreg_shutdown != NULL)
+ adc_pmic->pdata->xoadc_vreg_shutdown();
+
+ wake_lock_destroy(&adc_pmic->adc_wakelock);
+ msm_xo_put(adc_pmic->adc_voter);
+ device_init_wakeup(&pdev->dev, 0);
+ xoadc_initialized = false;
+
+ return 0;
}
static struct platform_driver pm8058_xoadc_driver = {
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 26a69f1..60e1e55 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1132,11 +1132,13 @@
int ret = 0;
if (!qsee_perf_client)
- return -EINVAL;
+ return ret;
/* Check if the clk is valid */
- if (IS_ERR_OR_NULL(qseecom_bus_clk))
+ if (IS_ERR_OR_NULL(qseecom_bus_clk)) {
+ pr_warn("qseecom bus clock is null or error");
return -EINVAL;
+ }
mutex_lock(&qsee_bw_mutex);
if (!qsee_bw_count) {
@@ -1166,8 +1168,10 @@
return;
/* Check if the clk is valid */
- if (IS_ERR_OR_NULL(qseecom_bus_clk))
+ if (IS_ERR_OR_NULL(qseecom_bus_clk)) {
+ pr_warn("qseecom bus clock is null or error");
return;
+ }
mutex_lock(&qsee_bw_mutex);
if (qsee_bw_count > 0) {
@@ -1420,6 +1424,10 @@
char qsee_not_legacy = 0;
uint32_t system_call_id = QSEOS_CHECK_VERSION_CMD;
+ qsee_bw_count = 0;
+ qseecom_bus_clk = NULL;
+ qsee_perf_client = 0;
+
rc = alloc_chrdev_region(&qseecom_device_no, 0, 1, QSEECOM_DEV);
if (rc < 0) {
pr_err("alloc_chrdev_region failed %d\n", rc);
@@ -1483,8 +1491,8 @@
&qsee_bus_pdata);
if (!qsee_perf_client) {
pr_err("Unable to register bus client\n");
-
- qseecom_bus_clk = clk_get(class_dev, "qseecom");
+ } else {
+ qseecom_bus_clk = clk_get(class_dev, "bus_clk");
if (IS_ERR(qseecom_bus_clk)) {
qseecom_bus_clk = NULL;
} else if (qseecom_bus_clk != NULL) {
diff --git a/drivers/of/of_spmi.c b/drivers/of/of_spmi.c
index 112497c..61085c9 100644
--- a/drivers/of/of_spmi.c
+++ b/drivers/of/of_spmi.c
@@ -203,9 +203,18 @@
struct device_node *node;
int rc, i, num_dev_node = 0;
- /* first count the total number of device_nodes */
- for_each_child_of_node(container, node)
+ if (!of_device_is_available(container))
+ return;
+
+ /*
+ * Count the total number of device_nodes so we know how much
+ * device_store to allocate.
+ */
+ for_each_child_of_node(container, node) {
+ if (!of_device_is_available(node))
+ continue;
num_dev_node++;
+ }
rc = of_spmi_alloc_device_store(d_info, num_dev_node);
if (rc) {
@@ -214,9 +223,10 @@
return;
}
- /* allocate resources per device_node */
i = 0;
for_each_child_of_node(container, node) {
+ if (!of_device_is_available(node))
+ continue;
of_spmi_init_resource(&r_info, node);
of_spmi_sum_node_resources(&r_info, 1);
rc = of_spmi_allocate_node_resources(d_info, &r_info, i);
@@ -226,17 +236,6 @@
of_spmi_free_device_resources(d_info);
return;
}
- i++;
- }
-
- /**
- * Now we need to cycle through again and actually populate
- * the resources for each node.
- */
- i = 0;
- for_each_child_of_node(container, node) {
- of_spmi_init_resource(&r_info, node);
- of_spmi_sum_node_resources(&r_info, 1);
of_spmi_populate_node_resources(d_info, &r_info, i);
i++;
}
@@ -265,6 +264,9 @@
for_each_child_of_node(container, node) {
struct of_spmi_res_info r_info;
+ if (!of_device_is_available(node))
+ continue;
+
/**
* Check to see if this node contains children which
* should be all created as the same spmi_device.
@@ -365,6 +367,9 @@
continue;
}
+ if (!of_device_is_available(node))
+ continue;
+
rc = of_spmi_alloc_device_store(&d_info, 1);
if (rc) {
dev_err(&ctrl->dev, "%s: unable to allocate"
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index 9a8d552..285d1de 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -141,6 +141,16 @@
return UART_TO_MSM(port)->is_uartdm;
}
+static int get_line(struct platform_device *pdev)
+{
+ const struct msm_serial_hslite_platform_data *pdata =
+ pdev->dev.platform_data;
+ if (pdata)
+ return pdata->line;
+
+ return pdev->id;
+}
+
static int clk_en(struct uart_port *port, int enable)
{
struct msm_hsl_port *msm_hsl_port = UART_TO_MSM(port);
@@ -1243,7 +1253,7 @@
struct uart_port *port;
struct platform_device *pdev = to_platform_device(dev);
- port = get_port_from_line(pdev->id);
+ port = get_port_from_line(get_line(pdev));
enable = get_console_state(port);
@@ -1264,7 +1274,7 @@
struct uart_port *port;
struct platform_device *pdev = to_platform_device(dev);
- port = get_port_from_line(pdev->id);
+ port = get_port_from_line(get_line(pdev));
cur_state = get_console_state(port);
enable = buf[0] - '0';
@@ -1332,12 +1342,12 @@
if (pdev->id == -1)
pdev->id = atomic_inc_return(&msm_serial_hsl_next_id) - 1;
- if (unlikely(pdev->id < 0 || pdev->id >= UART_NR))
+ if (unlikely(get_line(pdev) < 0 || get_line(pdev) >= UART_NR))
return -ENXIO;
printk(KERN_INFO "msm_serial_hsl: detected port #%d\n", pdev->id);
- port = get_port_from_line(pdev->id);
+ port = get_port_from_line(get_line(pdev));
port->dev = &pdev->dev;
msm_hsl_port = UART_TO_MSM(port);
@@ -1395,7 +1405,7 @@
if (unlikely(ret))
pr_err("%s():Can't create console attribute\n", __func__);
#endif
- msm_hsl_debugfs_init(msm_hsl_port, pdev->id);
+ msm_hsl_debugfs_init(msm_hsl_port, get_line(pdev));
/* Temporarily increase the refcount on the GSBI clock to avoid a race
* condition with the earlyprintk handover mechanism.
@@ -1413,7 +1423,7 @@
struct msm_hsl_port *msm_hsl_port = platform_get_drvdata(pdev);
struct uart_port *port;
- port = get_port_from_line(pdev->id);
+ port = get_port_from_line(get_line(pdev));
#ifdef CONFIG_SERIAL_MSM_HSL_CONSOLE
device_remove_file(&pdev->dev, &dev_attr_console);
#endif
@@ -1436,7 +1446,7 @@
{
struct platform_device *pdev = to_platform_device(dev);
struct uart_port *port;
- port = get_port_from_line(pdev->id);
+ port = get_port_from_line(get_line(pdev));
if (port) {
@@ -1455,7 +1465,7 @@
{
struct platform_device *pdev = to_platform_device(dev);
struct uart_port *port;
- port = get_port_from_line(pdev->id);
+ port = get_port_from_line(get_line(pdev));
if (port) {
@@ -1478,7 +1488,7 @@
{
struct platform_device *pdev = to_platform_device(dev);
struct uart_port *port;
- port = get_port_from_line(pdev->id);
+ port = get_port_from_line(get_line(pdev));
dev_dbg(dev, "pm_runtime: suspending\n");
msm_hsl_deinit_clock(port);
@@ -1489,7 +1499,7 @@
{
struct platform_device *pdev = to_platform_device(dev);
struct uart_port *port;
- port = get_port_from_line(pdev->id);
+ port = get_port_from_line(get_line(pdev));
dev_dbg(dev, "pm_runtime: resuming\n");
msm_hsl_init_clock(port);
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index ee44846..3e5c6f1 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -183,6 +183,12 @@
.bConfigurationValue = 1,
};
+enum android_device_state {
+ USB_DISCONNECTED,
+ USB_CONNECTED,
+ USB_CONFIGURED,
+};
+
static void android_work(struct work_struct *data)
{
struct android_dev *dev = container_of(data, struct android_dev, work);
@@ -191,18 +197,45 @@
char *connected[2] = { "USB_STATE=CONNECTED", NULL };
char *configured[2] = { "USB_STATE=CONFIGURED", NULL };
char **uevent_envp = NULL;
+ static enum android_device_state last_uevent, next_state;
unsigned long flags;
spin_lock_irqsave(&cdev->lock, flags);
- if (cdev->config)
+ if (cdev->config) {
uevent_envp = configured;
- else if (dev->connected != dev->sw_connected)
+ next_state = USB_CONFIGURED;
+ } else if (dev->connected != dev->sw_connected) {
uevent_envp = dev->connected ? connected : disconnected;
+ next_state = dev->connected ? USB_CONNECTED : USB_DISCONNECTED;
+ }
dev->sw_connected = dev->connected;
spin_unlock_irqrestore(&cdev->lock, flags);
if (uevent_envp) {
+ /*
+ * Some userspace modules, e.g. MTP, work correctly only if
+ * CONFIGURED uevent is preceded by DISCONNECT uevent.
+ * Check if we missed sending out a DISCONNECT uevent. This can
+ * happen if host PC resets and configures device really quick.
+ */
+ if (((uevent_envp == connected) &&
+ (last_uevent != USB_DISCONNECTED)) ||
+ ((uevent_envp == configured) &&
+ (last_uevent == USB_CONFIGURED))) {
+ pr_info("%s: sent missed DISCONNECT event\n", __func__);
+ kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE,
+ disconnected);
+ msleep(20);
+ }
+ /*
+ * Before sending out CONFIGURED uevent give function drivers
+ * a chance to wakeup userspace threads and notify disconnect
+ */
+ if (uevent_envp == configured)
+ msleep(50);
+
kobject_uevent_env(&dev->dev->kobj, KOBJ_CHANGE, uevent_envp);
+ last_uevent = next_state;
pr_info("%s: sent uevent %s\n", __func__, uevent_envp[0]);
} else {
pr_info("%s: did not send uevent (%d %d %p)\n", __func__,
diff --git a/drivers/usb/gadget/f_diag.c b/drivers/usb/gadget/f_diag.c
index c4c7941..72bff49 100644
--- a/drivers/usb/gadget/f_diag.c
+++ b/drivers/usb/gadget/f_diag.c
@@ -664,21 +664,20 @@
struct usb_diag_ch *ch;
list_for_each_entry(ch, &usb_diag_ch_list, list) {
- struct diag_context *ctxt;
+ struct diag_context *ctxt = ch->priv_usb;
- ctxt = ch->priv_usb;
-
- temp += scnprintf(buf + temp, PAGE_SIZE - temp,
- "---Name: %s---\n"
- "endpoints: %s, %s\n"
- "dpkts_tolaptop: %lu\n"
- "dpkts_tomodem: %lu\n"
- "pkts_tolaptop_pending: %u\n",
- ch->name,
- ctxt->in->name, ctxt->out->name,
- ctxt->dpkts_tolaptop,
- ctxt->dpkts_tomodem,
- ctxt->dpkts_tolaptop_pending);
+ if (ctxt)
+ temp += scnprintf(buf + temp, PAGE_SIZE - temp,
+ "---Name: %s---\n"
+ "endpoints: %s, %s\n"
+ "dpkts_tolaptop: %lu\n"
+ "dpkts_tomodem: %lu\n"
+ "pkts_tolaptop_pending: %u\n",
+ ch->name,
+ ctxt->in->name, ctxt->out->name,
+ ctxt->dpkts_tolaptop,
+ ctxt->dpkts_tomodem,
+ ctxt->dpkts_tolaptop_pending);
}
return simple_read_from_buffer(ubuf, count, ppos, buf, temp);
@@ -690,13 +689,13 @@
struct usb_diag_ch *ch;
list_for_each_entry(ch, &usb_diag_ch_list, list) {
- struct diag_context *ctxt;
+ struct diag_context *ctxt = ch->priv_usb;
- ctxt = ch->priv_usb;
-
- ctxt->dpkts_tolaptop = 0;
- ctxt->dpkts_tomodem = 0;
- ctxt->dpkts_tolaptop_pending = 0;
+ if (ctxt) {
+ ctxt->dpkts_tolaptop = 0;
+ ctxt->dpkts_tomodem = 0;
+ ctxt->dpkts_tolaptop_pending = 0;
+ }
}
return count;
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index e6c869f..5a72ad4 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -3,6 +3,8 @@
obj-$(CONFIG_FB_MSM_LOGO) += logo.o
obj-$(CONFIG_FB_BACKLIGHT) += msm_fb_bl.o
+ifeq ($(CONFIG_FB_MSM_MDP_HW),y)
+
# MDP
obj-y += mdp.o
@@ -177,6 +179,12 @@
obj-$(CONFIG_MSM_VIDC_1080P) += vidc/
obj-$(CONFIG_MSM_VIDC_720P) += vidc/
+else
+obj-$(CONFIG_FB_MSM_EBI2) += ebi2_host.o
+obj-$(CONFIG_FB_MSM_EBI2) += ebi2_lcd.o
+obj-y += msm_fb_panel.o
+obj-$(CONFIG_FB_MSM_EBI2_EPSON_S1D_QVGA_PANEL) += ebi2_epson_s1d_qvga.o
+endif
clean:
rm *.o .*cmd
diff --git a/drivers/video/msm/adv7520.c b/drivers/video/msm/adv7520.c
index 7386983..df501dd 100644
--- a/drivers/video/msm/adv7520.c
+++ b/drivers/video/msm/adv7520.c
@@ -874,11 +874,11 @@
} else
DEV_ERR("adv7520_probe: failed to add fb device\n");
-#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
- external_common_state->sdev.name = "hdmi_as_primary";
-#else
- external_common_state->sdev.name = "hdmi";
-#endif
+ if (hdmi_prim_display)
+ external_common_state->sdev.name = "hdmi_as_primary";
+ else
+ external_common_state->sdev.name = "hdmi";
+
if (switch_dev_register(&external_common_state->sdev) < 0)
DEV_ERR("Hdmi switch registration failed\n");
diff --git a/drivers/video/msm/ebi2_epson_s1d_qvga.c b/drivers/video/msm/ebi2_epson_s1d_qvga.c
new file mode 100644
index 0000000..8821eab
--- /dev/null
+++ b/drivers/video/msm/ebi2_epson_s1d_qvga.c
@@ -0,0 +1,374 @@
+/* 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 "msm_fb.h"
+
+#include <linux/memory.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include "linux/proc_fs.h"
+
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+
+#define CMD_NOP_C 0x00
+#define CMD_SOFT_RESET_C 0x99
+#define CMD_DISPLAY_ON_C 0xAF
+#define CMD_DISPLAY_OFF_C 0xAE
+#define CMD_SET_DISPLAY_C 0xCA
+#define CMD_SET_DISPLAY_TIMING_C 0xA1
+#define CMD_SET_DATA_C 0xBC
+#define CMD_SET_START_ADDRESS_C 0x15
+#define CMD_SET_END_ADDRESS_C 0x75
+#define CMD_RAM_WRITE_C 0x5C
+#define CMD_RAM_READ_C 0x5D
+#define CMD_SET_AREA_SCROLLING_C 0xAA
+#define CMD_SET_DISPLAY_START_LINE_C 0xAB
+#define CMD_PARTIAL_DISPLAY_IN_C 0xA8
+#define CMD_PARTIAL_DISPLAY_OUT_C 0xA9
+#define CMD_SET_DISPLAY_DATA_INTERFACE_C 0x31
+#define CMD_SET_DISPLAY_COLOR_MODE_C 0x8B
+#define CMD_SELECT_MTP_ROM_MODE_C 0x65
+#define CMD_MTP_ROM_MODE_IN_C 0x67
+#define CMD_MTP_ROM_MODE_OUT_C 0x68
+#define CMD_MTP_ROM_OPERATION_IN_C 0x69
+#define CMD_MTP_ROM_OPERATION_OUT_C 0x70
+#define CMD_GATE_LINE_SCAN_MODE_C 0x6F
+#define CMD_SET_AC_OPERATION_DRIVE_C 0x8C
+#define CMD_SET_ELECTRONIC_CONTROL_C 0x20
+#define CMD_SET_POSITIVE_CORRECTION_CHARS_C 0x22
+#define CMD_SET_NEGATIVE_CORRECTION_CHARS_C 0x25
+#define CMD_SET_POWER_CONTROL_C 0x21
+#define CMD_SET_PARTIAL_POWER_CONTROL_C 0x23
+#define CMD_SET_8_COLOR_CONTROL_C 0x24
+#define CMD_SLEEP_IN_C 0x95
+#define CMD_SLEEP_OUT_C 0x94
+#define CMD_VDD_OFF_C 0x97
+#define CMD_VDD_ON_C 0x96
+#define CMD_STOP_OSCILLATION_C 0x93
+#define CMD_START_OSCILLATION_C 0x92
+#define CMD_TEST_SOURCE_C 0xFD
+#define CMD_TEST_FUSE_C 0xFE
+#define CMD_TEST_C 0xFF
+#define CMD_STATUS_READ_C 0xE8
+#define CMD_REVISION_READ_C 0xE9
+
+#define PANEL_WIDTH 240
+#define PANEL_HEIGHT 320
+#define ACTIVE_WIN_WIDTH PANEL_WIDTH
+#define ACTIVE_WIN_HEIGHT PANEL_HEIGHT
+
+#define ACTIVE_WIN_H_START 0
+#define ACTIVE_WIN_V_START 0
+
+#define DISP_CMD_OUT(cmd) outpw(DISP_CMD_PORT, (cmd << 1));
+#define DISP_DATA_OUT(data) outpw(DISP_DATA_PORT, (data << 1));
+#define DISP_DATA_IN() inpw(DISP_DATA_PORT);
+
+static void *DISP_CMD_PORT;
+static void *DISP_DATA_PORT;
+static boolean disp_initialized;
+static boolean display_on;
+static struct msm_panel_common_pdata *ebi2_epson_pdata;
+
+static void epson_s1d_disp_init(struct platform_device *pdev);
+static int epson_s1d_disp_off(struct platform_device *pdev);
+static int epson_s1d_disp_on(struct platform_device *pdev);
+static void epson_s1d_disp_set_rect(int x, int y, int xres, int yres);
+
+static void epson_s1d_disp_set_rect(int x, int y, int xres, int yres)
+{
+ int right, bottom;
+
+ if (!disp_initialized)
+ return;
+
+ right = x + xres - 1;
+ bottom = y + yres - 1;
+
+ x += ACTIVE_WIN_H_START;
+ y += ACTIVE_WIN_V_START;
+ right += ACTIVE_WIN_H_START;
+ bottom += ACTIVE_WIN_V_START;
+
+ if ((PANEL_WIDTH > x) &&
+ (PANEL_HEIGHT > y) &&
+ (PANEL_WIDTH > right) &&
+ (PANEL_HEIGHT > bottom)) {
+ DISP_CMD_OUT(CMD_SET_START_ADDRESS_C);
+ DISP_DATA_OUT((uint8)x);
+ DISP_DATA_OUT((uint8)(y>>8));
+ DISP_DATA_OUT((uint8)y);
+
+ DISP_CMD_OUT(CMD_SET_END_ADDRESS_C);
+ DISP_DATA_OUT((uint8)right);
+ DISP_DATA_OUT((uint8)(bottom>>8));
+ DISP_DATA_OUT((uint8)bottom);
+ DISP_CMD_OUT(CMD_RAM_WRITE_C);
+ }
+}
+
+static void epson_s1d_disp_init(struct platform_device *pdev)
+{
+ struct msm_fb_data_type *mfd;
+
+ if (disp_initialized)
+ return;
+
+ mfd = platform_get_drvdata(pdev);
+
+ DISP_CMD_PORT = mfd->cmd_port;
+ DISP_DATA_PORT = mfd->data_port;
+
+ disp_initialized = TRUE;
+}
+
+static int epson_s1d_disp_off(struct platform_device *pdev)
+{
+ if (!disp_initialized)
+ epson_s1d_disp_init(pdev);
+
+ if (display_on) {
+ DISP_CMD_OUT(CMD_SOFT_RESET_C);
+ DISP_CMD_OUT(CMD_VDD_OFF_C);
+ display_on = FALSE;
+ }
+
+ return 0;
+}
+
+static int epson_s1d_disp_on(struct platform_device *pdev)
+{
+ int i;
+ if (!disp_initialized)
+ epson_s1d_disp_init(pdev);
+
+ if (!display_on) {
+ /* Enable Vdd regulator */
+ DISP_CMD_OUT(CMD_VDD_ON_C);
+ msleep(20);
+
+ /* Soft Reset before configuring display */
+ DISP_CMD_OUT(CMD_SOFT_RESET_C);
+ msleep(20);
+
+ /* Set display attributes */
+
+ /* GATESCAN */
+ DISP_CMD_OUT(CMD_GATE_LINE_SCAN_MODE_C);
+ DISP_DATA_OUT(0x0);
+
+ /* DISSET */
+ DISP_CMD_OUT(CMD_SET_DISPLAY_C);
+ DISP_DATA_OUT(0x31);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT((uint8)((PANEL_HEIGHT - 1)>>8));
+ DISP_DATA_OUT((uint8)(PANEL_HEIGHT - 1));
+ DISP_DATA_OUT(0x03);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x08);
+
+ /* VOLSET */
+ DISP_CMD_OUT(
+ CMD_SET_ELECTRONIC_CONTROL_C);
+ DISP_DATA_OUT(0x10);
+ DISP_DATA_OUT(0x80);
+ DISP_DATA_OUT(0x11);
+ DISP_DATA_OUT(0x1B);
+ DISP_DATA_OUT(0x02);
+ DISP_DATA_OUT(0x0D);
+ DISP_DATA_OUT(0x00);
+
+ /* PWRCTL */
+ DISP_CMD_OUT(CMD_SET_POWER_CONTROL_C);
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x24);
+ DISP_DATA_OUT(0x0F);
+ DISP_DATA_OUT(0xFE);
+ DISP_DATA_OUT(0x33);
+ DISP_DATA_OUT(0x31);
+ DISP_DATA_OUT(0xFF);
+ DISP_DATA_OUT(0x03);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x77);
+ DISP_DATA_OUT(0x33);
+ DISP_DATA_OUT(0x11);
+ DISP_DATA_OUT(0x44);
+ DISP_DATA_OUT(0x00);
+
+ /* PPWRCTL */
+ DISP_CMD_OUT(CMD_SET_PARTIAL_POWER_CONTROL_C);
+ DISP_DATA_OUT(0x33);
+ DISP_DATA_OUT(0xFF);
+ DISP_DATA_OUT(0x03);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x44);
+ DISP_DATA_OUT(0x00);
+
+ /* SPLOUT */
+ DISP_CMD_OUT(CMD_SLEEP_OUT_C);
+ msleep(100);
+
+ /* DATSET */
+ DISP_CMD_OUT(CMD_SET_DATA_C);
+ DISP_DATA_OUT(0x00);
+
+ /* DISTMEMSET */
+ DISP_CMD_OUT(CMD_SET_DISPLAY_TIMING_C);
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x2E);
+ DISP_DATA_OUT(0x0A);
+ DISP_DATA_OUT(0x2C);
+ DISP_DATA_OUT(0x23);
+ DISP_DATA_OUT(0x2F);
+ DISP_DATA_OUT(0x00);
+
+ /* GAMSETP */
+ DISP_CMD_OUT(CMD_SET_POSITIVE_CORRECTION_CHARS_C);
+ DISP_DATA_OUT(0x37);
+ DISP_DATA_OUT(0xFF);
+ DISP_DATA_OUT(0x7F);
+ DISP_DATA_OUT(0x15);
+ DISP_DATA_OUT(0x37);
+ DISP_DATA_OUT(0x05);
+
+ /* GAMSETN */
+ DISP_CMD_OUT(CMD_SET_NEGATIVE_CORRECTION_CHARS_C);
+ DISP_DATA_OUT(0x37);
+ DISP_DATA_OUT(0xFF);
+ DISP_DATA_OUT(0x7F);
+ DISP_DATA_OUT(0x15);
+ DISP_DATA_OUT(0x37);
+ DISP_DATA_OUT(0x05);
+
+ /* ACDRIVE */
+ DISP_CMD_OUT(CMD_SET_AC_OPERATION_DRIVE_C);
+ DISP_DATA_OUT(0x00);
+
+ /* TEST */
+ DISP_CMD_OUT(CMD_TEST_C);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x01);
+
+ /* COLMOD */
+ DISP_CMD_OUT(CMD_SET_DISPLAY_COLOR_MODE_C);
+ DISP_DATA_OUT(0x00);
+
+ /* STADDSET */
+ DISP_CMD_OUT(CMD_SET_START_ADDRESS_C);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x00);
+
+ /* EDADDSET */
+ DISP_CMD_OUT(CMD_SET_END_ADDRESS_C);
+ DISP_DATA_OUT(0xEF);
+ DISP_DATA_OUT(0x01);
+ DISP_DATA_OUT(0x3F);
+
+ /* Set Display Start Line */
+ DISP_CMD_OUT(CMD_SET_DISPLAY_START_LINE_C);
+ DISP_DATA_OUT(0x00);
+
+ /* Set Display Data Interface */
+ DISP_CMD_OUT(CMD_SET_DISPLAY_DATA_INTERFACE_C);
+ DISP_DATA_OUT(0x00);
+ DISP_DATA_OUT(0x04);
+
+ epson_s1d_disp_set_rect(0,
+ 0,
+ ACTIVE_WIN_WIDTH,
+ ACTIVE_WIN_HEIGHT);
+
+ for (i = 0; i < (ACTIVE_WIN_WIDTH * ACTIVE_WIN_HEIGHT); i++)
+ outpdw(DISP_DATA_PORT, 0);
+
+ /* DISON */
+ DISP_CMD_OUT(CMD_DISPLAY_ON_C);
+ msleep(60);
+
+ display_on = TRUE;
+ }
+
+ return 0;
+}
+
+static int epson_s1d_probe(struct platform_device *pdev)
+{
+ if (pdev->id == 0) {
+ ebi2_epson_pdata = pdev->dev.platform_data;
+ return 0;
+ }
+
+ msm_fb_add_device(pdev);
+ return 0;
+}
+
+static struct platform_driver this_driver = {
+ .probe = epson_s1d_probe,
+ .driver = {
+ .name = "ebi2_epson_s1d_qvga",
+ },
+};
+
+static struct msm_fb_panel_data epson_s1d_panel_data = {
+ .on = epson_s1d_disp_on,
+ .off = epson_s1d_disp_off,
+ .set_rect = epson_s1d_disp_set_rect,
+};
+
+static struct platform_device this_device = {
+ .name = "ebi2_epson_s1d_qvga",
+ .id = 1,
+ .dev = {
+ .platform_data = &epson_s1d_panel_data,
+ }
+};
+
+static int __init epson_s1d_init(void)
+{
+ int ret;
+ struct msm_panel_info *pinfo;
+
+ ret = platform_driver_register(&this_driver);
+ if (!ret) {
+ pinfo = &epson_s1d_panel_data.panel_info;
+ pinfo->xres = PANEL_WIDTH;
+ pinfo->yres = PANEL_HEIGHT;
+ MSM_FB_SINGLE_MODE_PANEL(pinfo);
+ pinfo->type = EBI2_PANEL;
+ pinfo->pdest = DISPLAY_1;
+ pinfo->wait_cycle = 0x048423E8;
+ pinfo->bpp = 18;
+ pinfo->fb_num = 2;
+ pinfo->lcd.vsync_enable = FALSE;
+
+ ret = platform_device_register(&this_device);
+ if (ret)
+ platform_driver_unregister(&this_driver);
+ }
+
+ return ret;
+}
+
+module_init(epson_s1d_init);
diff --git a/drivers/video/msm/ebi2_host.c b/drivers/video/msm/ebi2_host.c
new file mode 100644
index 0000000..8ba5506
--- /dev/null
+++ b/drivers/video/msm/ebi2_host.c
@@ -0,0 +1,307 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/hrtimer.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/semaphore.h>
+#include <linux/uaccess.h>
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <mach/clk.h>
+#include <mach/hardware.h>
+#include "msm_fb.h"
+
+struct mdp_ccs mdp_ccs_rgb2yuv;
+struct mdp_ccs mdp_ccs_yuv2rgb;
+
+static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
+static int pdev_list_cnt;
+static int ebi2_host_resource_initialized;
+static struct msm_panel_common_pdata *ebi2_host_pdata;
+
+static int ebi2_host_probe(struct platform_device *pdev);
+static int ebi2_host_remove(struct platform_device *pdev);
+
+static int ebi2_host_runtime_suspend(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: suspending...\n");
+ return 0;
+}
+
+static int ebi2_host_runtime_resume(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: resuming...\n");
+ return 0;
+}
+
+static const struct dev_pm_ops ebi2_host_dev_pm_ops = {
+ .runtime_suspend = ebi2_host_runtime_suspend,
+ .runtime_resume = ebi2_host_runtime_resume,
+};
+
+
+static struct platform_driver ebi2_host_driver = {
+ .probe = ebi2_host_probe,
+ .remove = ebi2_host_remove,
+ .shutdown = NULL,
+ .driver = {
+ /*
+ * Simulate mdp hw
+ */
+ .name = "mdp",
+ .pm = &ebi2_host_dev_pm_ops,
+ },
+};
+
+void mdp_pipe_ctrl(MDP_BLOCK_TYPE block, MDP_BLOCK_POWER_STATE state,
+ boolean isr)
+{
+ return;
+}
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req)
+{
+ return 0;
+}
+int mdp_start_histogram(struct fb_info *info)
+{
+ return 0;
+}
+int mdp_stop_histogram(struct fb_info *info)
+{
+ return 0;
+}
+void mdp_refresh_screen(unsigned long data)
+{
+ return;
+}
+
+static int ebi2_host_off(struct platform_device *pdev)
+{
+ int ret;
+ ret = panel_next_off(pdev);
+ return ret;
+}
+
+static int ebi2_host_on(struct platform_device *pdev)
+{
+ int ret;
+ ret = panel_next_on(pdev);
+ return ret;
+}
+
+
+static int ebi2_host_probe(struct platform_device *pdev)
+{
+ struct platform_device *msm_fb_dev = NULL;
+ struct msm_fb_data_type *mfd;
+ struct msm_fb_panel_data *pdata = NULL;
+ int rc;
+
+ if ((pdev->id == 0) && (pdev->num_resources > 0)) {
+
+ ebi2_host_pdata = pdev->dev.platform_data;
+
+ ebi2_host_resource_initialized = 1;
+ return 0;
+ }
+
+ ebi2_host_resource_initialized = 1;
+ if (!ebi2_host_resource_initialized)
+ return -EPERM;
+
+ mfd = platform_get_drvdata(pdev);
+
+ if (!mfd)
+ return -ENODEV;
+
+ if (mfd->key != MFD_KEY)
+ return -EINVAL;
+
+ if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
+ return -ENOMEM;
+
+ msm_fb_dev = platform_device_alloc("msm_fb", pdev->id);
+ if (!msm_fb_dev)
+ return -ENOMEM;
+
+ /* link to the latest pdev */
+ mfd->pdev = msm_fb_dev;
+
+ if (ebi2_host_pdata) {
+ mfd->mdp_rev = ebi2_host_pdata->mdp_rev;
+ mfd->mem_hid = ebi2_host_pdata->mem_hid;
+ }
+
+ /* add panel data */
+ if (platform_device_add_data
+ (msm_fb_dev, pdev->dev.platform_data,
+ sizeof(struct msm_fb_panel_data))) {
+ pr_err("ebi2_host_probe: platform_device_add_data failed!\n");
+ rc = -ENOMEM;
+ goto ebi2_host_probe_err;
+ }
+ /* data chain */
+ pdata = msm_fb_dev->dev.platform_data;
+ pdata->on = ebi2_host_on;
+ pdata->off = ebi2_host_off;
+ pdata->next = pdev;
+
+ /* set driver data */
+ platform_set_drvdata(msm_fb_dev, mfd);
+
+ rc = platform_device_add(msm_fb_dev);
+ if (rc)
+ goto ebi2_host_probe_err;
+
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ pdev_list[pdev_list_cnt++] = pdev;
+ return 0;
+
+ebi2_host_probe_err:
+ platform_device_put(msm_fb_dev);
+ return rc;
+}
+
+void mdp_set_dma_pan_info(struct fb_info *info, struct mdp_dirty_region *dirty,
+ boolean sync)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct fb_info *fbi = mfd->fbi;
+ struct msm_panel_info *panel_info = &mfd->panel_info;
+ MDPIBUF *iBuf;
+ int bpp = info->var.bits_per_pixel / 8;
+ int yres, remainder;
+
+ if (panel_info->mode2_yres != 0) {
+ yres = panel_info->mode2_yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ } else {
+ yres = panel_info->yres;
+ remainder = (fbi->fix.line_length*yres)%PAGE_SIZE;
+ }
+
+ if (!remainder)
+ remainder = PAGE_SIZE;
+
+ down(&mfd->sem);
+
+ iBuf = &mfd->ibuf;
+ /* use virtual address */
+ iBuf->buf = (uint8 *) fbi->screen_base;
+
+ if (fbi->var.yoffset < yres) {
+ iBuf->buf += fbi->var.xoffset * bpp;
+ } else if (fbi->var.yoffset >= yres && fbi->var.yoffset < 2 * yres) {
+ iBuf->buf += fbi->var.xoffset * bpp + yres *
+ fbi->fix.line_length + PAGE_SIZE - remainder;
+ } else {
+ iBuf->buf += fbi->var.xoffset * bpp + 2 * yres *
+ fbi->fix.line_length + 2 * (PAGE_SIZE - remainder);
+ }
+
+ iBuf->ibuf_width = info->var.xres_virtual;
+ iBuf->bpp = bpp;
+
+ iBuf->vsync_enable = sync;
+
+ if (dirty) {
+ /*
+ * ToDo: dirty region check inside var.xoffset+xres
+ * <-> var.yoffset+yres
+ */
+ iBuf->dma_x = dirty->xoffset % info->var.xres;
+ iBuf->dma_y = dirty->yoffset % info->var.yres;
+ iBuf->dma_w = dirty->width;
+ iBuf->dma_h = dirty->height;
+ } else {
+ iBuf->dma_x = 0;
+ iBuf->dma_y = 0;
+ iBuf->dma_w = info->var.xres;
+ iBuf->dma_h = info->var.yres;
+ }
+ mfd->ibuf_flushed = FALSE;
+ up(&mfd->sem);
+}
+
+void mdp_dma_pan_update(struct fb_info *info)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ MDPIBUF *iBuf;
+ int i, j;
+ uint32 data;
+ uint8 *src;
+ struct msm_fb_panel_data *pdata =
+ (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+ struct fb_info *fbi = mfd->fbi;
+
+ iBuf = &mfd->ibuf;
+
+ invalidate_caches((unsigned long)fbi->screen_base,
+ (unsigned long)info->fix.smem_len,
+ (unsigned long)info->fix.smem_start);
+
+ pdata->set_rect(iBuf->dma_x, iBuf->dma_y, iBuf->dma_w,
+ iBuf->dma_h);
+ for (i = 0; i < iBuf->dma_h; i++) {
+ src = iBuf->buf + (fbi->fix.line_length * (iBuf->dma_y + i))
+ + (iBuf->dma_x * iBuf->bpp);
+ for (j = 0; j < iBuf->dma_w; j++) {
+ data = (uint32)(*src++ >> 2) << 12;
+ data |= (uint32)(*src++ >> 2) << 6;
+ data |= (uint32)(*src++ >> 2);
+ data = ((data&0x1FF)<<16) | ((data&0x3FE00)>>9);
+ outpdw(mfd->data_port, data);
+ }
+ }
+}
+
+static int ebi2_host_remove(struct platform_device *pdev)
+{
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+static int ebi2_host_register_driver(void)
+{
+ return platform_driver_register(&ebi2_host_driver);
+}
+
+static int __init ebi2_host_driver_init(void)
+{
+ int ret;
+
+ ret = ebi2_host_register_driver();
+ if (ret) {
+ pr_err("ebi2_host_register_driver() failed!\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+module_init(ebi2_host_driver_init);
diff --git a/drivers/video/msm/ebi2_lcd.c b/drivers/video/msm/ebi2_lcd.c
index 68590af..966f974 100644
--- a/drivers/video/msm/ebi2_lcd.c
+++ b/drivers/video/msm/ebi2_lcd.c
@@ -56,8 +56,6 @@
.probe = ebi2_lcd_probe,
.remove = ebi2_lcd_remove,
.suspend = NULL,
- .suspend_late = NULL,
- .resume_early = NULL,
.resume = NULL,
.shutdown = NULL,
.driver = {
@@ -71,17 +69,42 @@
static void *ebi2_lcd_cfg1;
static void __iomem *lcd01_base;
static void __iomem *lcd02_base;
+static int lcd01_base_phys;
static int ebi2_lcd_resource_initialized;
static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
static int pdev_list_cnt;
+static struct lcdc_platform_data *ebi2_pdata;
+
+static int ebi2_lcd_on(struct platform_device *pdev)
+{
+ int ret;
+
+ if (ebi2_pdata && ebi2_pdata->lcdc_power_save)
+ ebi2_pdata->lcdc_power_save(1);
+
+ ret = panel_next_on(pdev);
+ return ret;
+}
+
+static int ebi2_lcd_off(struct platform_device *pdev)
+{
+ int ret;
+
+ ret = panel_next_off(pdev);
+
+ if (ebi2_pdata && ebi2_pdata->lcdc_power_save)
+ ebi2_pdata->lcdc_power_save(0);
+
+ return ret;
+}
static int ebi2_lcd_probe(struct platform_device *pdev)
{
struct msm_fb_data_type *mfd;
struct platform_device *mdp_dev = NULL;
struct msm_fb_panel_data *pdata = NULL;
- int rc, i;
+ int rc, i, hw_version;
if (pdev->id == 0) {
for (i = 0; i < pdev->num_resources; i++) {
@@ -98,6 +121,7 @@
ebi2_lcd_cfg1 = (void *)(ebi2_base + 0x24);
} else if (!strncmp(pdev->resource[i].name,
"lcd01", 5)) {
+ lcd01_base_phys = pdev->resource[i].start;
lcd01_base = ioremap(pdev->resource[i].start,
pdev->resource[i].end -
pdev->resource[i].start + 1);
@@ -118,7 +142,9 @@
}
}
}
+ ebi2_pdata = pdev->dev.platform_data;
ebi2_lcd_resource_initialized = 1;
+
return 0;
}
@@ -158,15 +184,19 @@
/* data chain */
pdata = mdp_dev->dev.platform_data;
- pdata->on = panel_next_on;
- pdata->off = panel_next_off;
+ pdata->on = ebi2_lcd_on;
+ pdata->off = ebi2_lcd_off;
pdata->next = pdev;
/* get/set panel specific fb info */
mfd->panel_info = pdata->panel_info;
+ hw_version = inp32((int)ebi2_base + 8);
+
if (mfd->panel_info.bpp == 24)
mfd->fb_imgType = MDP_RGB_888;
+ else if (mfd->panel_info.bpp == 18)
+ mfd->fb_imgType = MDP_RGB_888;
else
mfd->fb_imgType = MDP_RGB_565;
@@ -181,10 +211,12 @@
* configure both.
*/
outp32(ebi2_lcd_cfg0, mfd->panel_info.wait_cycle);
- if (mfd->panel_info.bpp == 18)
- outp32(ebi2_lcd_cfg1, 0x01000000);
- else
- outp32(ebi2_lcd_cfg1, 0x0);
+ if (hw_version < 0x2020) {
+ if (mfd->panel_info.bpp == 18)
+ outp32(ebi2_lcd_cfg1, 0x01000000);
+ else
+ outp32(ebi2_lcd_cfg1, 0x0);
+ }
} else {
#ifdef DEBUG_EBI2_LCD
/*
@@ -201,10 +233,18 @@
*/
if (mfd->panel_info.pdest == DISPLAY_1) {
mfd->cmd_port = lcd01_base;
- mfd->data_port =
- (void *)((uint32) mfd->cmd_port + EBI2_PRIM_LCD_RS_PIN);
- mfd->data_port_phys =
- (void *)(LCD_PRIM_BASE_PHYS + EBI2_PRIM_LCD_RS_PIN);
+ if (hw_version >= 0x2020) {
+ mfd->data_port =
+ (void *)((uint32) mfd->cmd_port + 0x80);
+ mfd->data_port_phys =
+ (void *)(lcd01_base_phys + 0x80);
+ } else {
+ mfd->data_port =
+ (void *)((uint32) mfd->cmd_port +
+ EBI2_PRIM_LCD_RS_PIN);
+ mfd->data_port_phys =
+ (void *)(LCD_PRIM_BASE_PHYS + EBI2_PRIM_LCD_RS_PIN);
+ }
} else {
mfd->cmd_port = lcd01_base;
mfd->data_port =
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 90702f3..f6e43bf 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -18,6 +18,9 @@
/* #define DEBUG */
#define DEV_DBG_PREFIX "EXT_COMMON: "
+/* The start of the data block collection within the CEA Extension Version 3 */
+#define DBC_START_OFFSET 4
+
#include "msm_fb.h"
#include "hdmi_msm.h"
#include "external_common.h"
@@ -317,6 +320,29 @@
return ret;
}
+static ssize_t hdmi_common_rda_edid_physical_address(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "%d\n",
+ external_common_state->physical_address);
+
+ DEV_DBG("%s: '%d'\n", __func__,
+ external_common_state->physical_address);
+ return ret;
+}
+
+
+static ssize_t hdmi_common_rda_edid_scan_info(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ ssize_t ret = snprintf(buf, PAGE_SIZE, "%d, %d, %d\n",
+ external_common_state->pt_scan_info,
+ external_common_state->it_scan_info,
+ external_common_state->ce_scan_info);
+ DEV_DBG("%s: '%s'\n", __func__, buf);
+ return ret;
+}
+
static ssize_t hdmi_common_rda_hdcp(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -681,6 +707,10 @@
static DEVICE_ATTR(hpd, S_IRUGO | S_IWUGO, hdmi_common_rda_hpd,
hdmi_common_wta_hpd);
static DEVICE_ATTR(hdcp, S_IRUGO, hdmi_common_rda_hdcp, NULL);
+static DEVICE_ATTR(pa, S_IRUGO,
+ hdmi_common_rda_edid_physical_address, NULL);
+static DEVICE_ATTR(scan_info, S_IRUGO,
+ hdmi_common_rda_edid_scan_info, NULL);
static DEVICE_ATTR(3d_present, S_IRUGO, hdmi_common_rda_3d_present, NULL);
static DEVICE_ATTR(hdcp_present, S_IRUGO, hdmi_common_rda_hdcp_present, NULL);
#endif
@@ -699,6 +729,8 @@
&dev_attr_edid_modes.attr,
&dev_attr_hdcp.attr,
&dev_attr_hpd.attr,
+ &dev_attr_pa.attr,
+ &dev_attr_scan_info.attr,
&dev_attr_3d_present.attr,
&dev_attr_hdcp_present.attr,
#endif
@@ -926,11 +958,12 @@
31500, 60000, 108108, 60000, TRUE},
};
-static const uint8 *hdmi_edid_find_block(const uint8 *in_buf, uint8 type,
- uint8 *len)
+static const uint8 *hdmi_edid_find_block(const uint8 *in_buf,
+ uint32 start_offset, uint8 type, uint8 *len)
{
/* the start of data block collection, start of Video Data Block */
- uint32 offset = 4;
+ uint32 offset = start_offset;
+ uint32 end_dbc_offset = in_buf[2];
*len = 0;
@@ -938,11 +971,11 @@
present.
edid buffer 1, byte 2 being 0 menas no non-DTD/DATA block collection
present and no DTD data present.*/
- if ((in_buf[2] == 0) || (in_buf[2] == 4)) {
+ if ((end_dbc_offset == 0) || (end_dbc_offset == 4)) {
DEV_WARN("EDID: no DTD or non-DTD data present\n");
return NULL;
}
- while (offset < 0x80) {
+ while (offset < end_dbc_offset) {
uint8 block_len = in_buf[offset] & 0x1F;
if ((in_buf[offset] >> 5) == type) {
*len = block_len;
@@ -970,20 +1003,24 @@
static uint32 hdmi_edid_extract_ieee_reg_id(const uint8 *in_buf)
{
uint8 len;
- const uint8 *vsd = hdmi_edid_find_block(in_buf, 3, &len);
+ const uint8 *vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3,
+ &len);
if (vsd == NULL)
return 0;
DEV_DBG("EDID: VSD PhyAddr=%04x, MaxTMDS=%dMHz\n",
- ((uint32)vsd[6] << 8) + (uint32)vsd[5], (uint32)vsd[7] * 5);
+ ((uint32)vsd[4] << 8) + (uint32)vsd[5], (uint32)vsd[7] * 5);
+ external_common_state->physical_address =
+ ((uint16)vsd[4] << 8) + (uint16)vsd[5];
return ((uint32)vsd[3] << 16) + ((uint32)vsd[2] << 8) + (uint32)vsd[1];
}
static void hdmi_edid_extract_3d_present(const uint8 *in_buf)
{
uint8 len, offset;
- const uint8 *vsd = hdmi_edid_find_block(in_buf, 3, &len);
+ const uint8 *vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3,
+ &len);
external_common_state->present_3d = 0;
if (vsd == NULL || len < 9) {
@@ -1003,7 +1040,8 @@
static void hdmi_edid_extract_latency_fields(const uint8 *in_buf)
{
uint8 len;
- const uint8 *vsd = hdmi_edid_find_block(in_buf, 3, &len);
+ const uint8 *vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 3,
+ &len);
if (vsd == NULL || len < 12 || !(vsd[8] & BIT(7))) {
external_common_state->video_latency = (uint16)-1;
@@ -1021,7 +1059,8 @@
static void hdmi_edid_extract_speaker_allocation_data(const uint8 *in_buf)
{
uint8 len;
- const uint8 *sad = hdmi_edid_find_block(in_buf, 4, &len);
+ const uint8 *sad = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 4,
+ &len);
if (sad == NULL)
return;
@@ -1041,7 +1080,8 @@
static void hdmi_edid_extract_audio_data_blocks(const uint8 *in_buf)
{
uint8 len;
- const uint8 *sad = hdmi_edid_find_block(in_buf, 1, &len);
+ const uint8 *sad = hdmi_edid_find_block(in_buf, DBC_START_OFFSET, 1,
+ &len);
uint32 *adb = external_common_state->audio_data_blocks;
if (sad == NULL)
@@ -1060,6 +1100,63 @@
}
}
+static void hdmi_edid_extract_extended_data_blocks(const uint8 *in_buf)
+{
+ uint8 len = 0;
+ uint8 const *prev_etag = in_buf;
+ uint32 start_offset = DBC_START_OFFSET;
+
+ /* A Tage code of 7 identifies extended data blocks */
+ uint8 const *etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len);
+
+ while (etag != NULL) {
+ /* The extended data block should at least be 2 bytes long */
+ if (len < 2) {
+ DEV_DBG("EDID: Found an extended data block of length"
+ "less than 2 bytes. Ignoring ...\n");
+ } else {
+ /*
+ * The second byte of the extended data block has the
+ * extended tag code
+ */
+ switch (etag[1]) {
+ case 0:
+ /* Video Capability Data Block */
+ DEV_DBG("EDID: VCDB=%02X %02X\n", etag[1],
+ etag[2]);
+
+ /*
+ * Check if the sink specifies underscan
+ * support for:
+ * BIT 5: preferred video format
+ * BIT 3: IT video format
+ * BIT 1: CE video format
+ */
+ external_common_state->pt_scan_info = (etag[2] &
+ (BIT(4) | BIT(5))) >> 4;
+ external_common_state->it_scan_info = (etag[2] &
+ (BIT(3) | BIT(2))) >> 2;
+ external_common_state->ce_scan_info = etag[2] &
+ (BIT(1) | BIT(0));
+ DEV_DBG("EDID: Scan Information (pt|it|ce): "
+ "(%d|%d|%d)",
+ external_common_state->pt_scan_info,
+ external_common_state->it_scan_info,
+ external_common_state->ce_scan_info);
+ break;
+ default:
+ DEV_DBG("EDID: Extend Tag Code %d not"
+ "supported\n", etag[1]);
+ break;
+ }
+ }
+
+ /* There could be more that one extended data block */
+ start_offset = etag - prev_etag + len + 1;
+ prev_etag = etag;
+ etag = hdmi_edid_find_block(in_buf, start_offset, 7, &len);
+ }
+}
static void hdmi_edid_detail_desc(const uint8 *data_buf, uint32 *disp_mode)
{
@@ -1204,7 +1301,8 @@
const uint8 *edid_blk0 = &data_buf[0x0];
const uint8 *edid_blk1 = &data_buf[0x80];
const uint8 *svd = num_og_cea_blocks ?
- hdmi_edid_find_block(data_buf+0x80, 2, &len) : NULL;
+ hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET,
+ 2, &len) : NULL;
disp_mode_list->num_of_elements = 0;
if (svd != NULL) {
@@ -1216,6 +1314,11 @@
video_format = (*svd & 0x7F) - 1;
add_supported_video_format(disp_mode_list,
video_format);
+ /* Make a note of the preferred video format */
+ if (i == 0) {
+ external_common_state->preferred_video_format =
+ video_format;
+ }
if (video_format == HDMI_VFRMT_640x480p60_4_3)
has480p = TRUE;
}
@@ -1238,6 +1341,11 @@
video_format);
if (video_format == HDMI_VFRMT_640x480p60_4_3)
has480p = TRUE;
+ /* Make a note of the preferred video format */
+ if (i == 0) {
+ external_common_state->preferred_video_format =
+ video_format;
+ }
desc_offset += 0x12;
++i;
}
@@ -1258,6 +1366,11 @@
video_format);
if (video_format == HDMI_VFRMT_640x480p60_4_3)
has480p = TRUE;
+ /* Make a note of the preferred video format */
+ if (i == 0) {
+ external_common_state->preferred_video_format =
+ video_format;
+ }
desc_offset += 0x12;
++i;
}
@@ -1281,6 +1394,11 @@
video_format);
if (video_format == HDMI_VFRMT_640x480p60_4_3)
has480p = TRUE;
+ /* Make a note of the preferred video format */
+ if (i == 0) {
+ external_common_state->preferred_video_format =
+ video_format;
+ }
desc_offset += 0x12;
++i;
}
@@ -1359,6 +1477,7 @@
/* EDID_BLOCK_SIZE[0x80] Each page size in the EDID ROM */
uint8 edid_buf[0x80 * 4];
+ external_common_state->preferred_video_format = 0;
external_common_state->present_3d = 0;
memset(&external_common_state->disp_mode_list, 0,
sizeof(external_common_state->disp_mode_list));
@@ -1410,6 +1529,7 @@
edid_buf+0x80);
hdmi_edid_extract_audio_data_blocks(edid_buf+0x80);
hdmi_edid_extract_3d_present(edid_buf+0x80);
+ hdmi_edid_extract_extended_data_blocks(edid_buf+0x80);
}
break;
case 2:
diff --git a/drivers/video/msm/external_common.h b/drivers/video/msm/external_common.h
index c9ab88e..b8d2e5f 100644
--- a/drivers/video/msm/external_common.h
+++ b/drivers/video/msm/external_common.h
@@ -216,6 +216,11 @@
uint8 speaker_allocation_block;
uint16 video_latency, audio_latency;
uint8 audio_data_block_cnt;
+ uint16 physical_address;
+ uint32 preferred_video_format;
+ uint8 pt_scan_info;
+ uint8 it_scan_info;
+ uint8 ce_scan_info;
boolean present_3d;
boolean present_hdcp;
uint32 audio_data_blocks[16];
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 1ea6403..918f8f2 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -3675,6 +3675,7 @@
uint32 regVal;
int i;
int mode = 0;
+ boolean use_ce_scan_info = TRUE;
switch (external_common_state->video_resolution) {
case HDMI_VFRMT_720x480p60_4_3:
@@ -3740,6 +3741,48 @@
/* Data Byte 01: 0 Y1 Y0 A0 B1 B0 S1 S0 */
aviInfoFrame[3] = hdmi_msm_avi_iframe_lut[0][mode];
+
+ /*
+ * If the sink specified support for both underscan/overscan
+ * then, by default, set the underscan bit.
+ * Only checking underscan support for preferred format and cea formats
+ */
+ if ((external_common_state->video_resolution ==
+ external_common_state->preferred_video_format)) {
+ use_ce_scan_info = FALSE;
+ switch (external_common_state->pt_scan_info) {
+ case 0:
+ /*
+ * Need to use the info specified for the corresponding
+ * IT or CE format
+ */
+ DEV_DBG("%s: No underscan information specified for the"
+ " preferred video format\n", __func__);
+ use_ce_scan_info = TRUE;
+ break;
+ case 3:
+ DEV_DBG("%s: Setting underscan bit for the preferred"
+ " video format\n", __func__);
+ aviInfoFrame[3] |= 0x02;
+ break;
+ default:
+ DEV_DBG("%s: Underscan information not set for the"
+ " preferred video format\n", __func__);
+ break;
+ }
+ }
+
+ if (use_ce_scan_info) {
+ if (3 == external_common_state->ce_scan_info) {
+ DEV_DBG("%s: Setting underscan bit for the CE video"
+ " format\n", __func__);
+ aviInfoFrame[3] |= 0x02;
+ } else {
+ DEV_DBG("%s: Not setting underscan bit for the CE video"
+ " format\n", __func__);
+ }
+ }
+
/* Data Byte 02: C1 C0 M1 M0 R3 R2 R1 R0 */
aviInfoFrame[4] = hdmi_msm_avi_iframe_lut[1][mode];
/* Data Byte 03: ITC EC2 EC1 EC0 Q1 Q0 SC1 SC0 */
@@ -4414,11 +4457,10 @@
queue_work(hdmi_work_queue, &hdmi_msm_state->hpd_read_work);
/* Initialize hdmi node and register with switch driver */
-#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
- external_common_state->sdev.name = "hdmi_as_primary";
-#else
- external_common_state->sdev.name = "hdmi";
-#endif
+ if (hdmi_prim_display)
+ external_common_state->sdev.name = "hdmi_as_primary";
+ else
+ external_common_state->sdev.name = "hdmi";
if (switch_dev_register(&external_common_state->sdev) < 0)
DEV_ERR("Hdmi switch registration failed\n");
diff --git a/drivers/video/msm/lvds.c b/drivers/video/msm/lvds.c
index e93b238..d9785d8 100644
--- a/drivers/video/msm/lvds.c
+++ b/drivers/video/msm/lvds.c
@@ -181,6 +181,8 @@
lvds_intf = 0x0001078c;
lvds_phy_cfg0 = BIT(6);
}
+ } else {
+ BUG();
}
/* MDP_LVDSPHY_CFG0 */
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 199e472..a6f03ba 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/msm/mdp_ppp.c
@@ -1417,7 +1417,7 @@
iBuf.mdpImg.mdpOp |= MDPOP_DITHER;
if (req->flags & MDP_BLEND_FG_PREMULT) {
-#ifdef CONFIG_FB_MSM_MDP31
+#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP303)
iBuf.mdpImg.mdpOp |= MDPOP_FG_PM_ALPHA;
#else
put_img(p_src_file);
diff --git a/drivers/video/msm/mdp_ppp_v20.c b/drivers/video/msm/mdp_ppp_v20.c
index fd04009..fe237ee 100644
--- a/drivers/video/msm/mdp_ppp_v20.c
+++ b/drivers/video/msm/mdp_ppp_v20.c
@@ -2429,37 +2429,102 @@
uint32 *tpVal,
uint32 perPixelAlpha, uint32 *pppop_reg_ptr)
{
- if (perPixelAlpha) {
- *pppop_reg_ptr |= PPP_OP_ROT_ON |
- PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
+ if (mdp_rev == MDP_REV_303) {
+ int bg_alpha;
+
+ *alpha = iBuf->mdpImg.alpha;
+ *tpVal = iBuf->mdpImg.tpVal;
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_FG_PM_ALPHA) {
+ if (perPixelAlpha) {
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_CONSTANT_ALPHA;
+ } else {
+ if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+ && (iBuf->mdpImg.alpha == 0xff)) {
+ iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
+ }
+
+ if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+ || (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
+
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_CONSTANT_ALPHA |
+ PPP_OP_BLEND_ALPHA_BLEND_NORMAL;
+ }
+ }
+
+ bg_alpha = PPP_BLEND_BG_USE_ALPHA_SEL |
+ PPP_BLEND_BG_ALPHA_REVERSE;
+
+ if (perPixelAlpha) {
+ bg_alpha |= PPP_BLEND_BG_SRCPIXEL_ALPHA;
+ } else {
+ bg_alpha |= PPP_BLEND_BG_CONSTANT_ALPHA;
+ bg_alpha |= iBuf->mdpImg.alpha << 24;
+ }
+ outpdw(MDP_BASE + 0x70010, bg_alpha);
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
+ *pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
+ } else if (perPixelAlpha) {
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_SRCPIXEL_ALPHA;
+ } else {
+ if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+ && (iBuf->mdpImg.alpha == 0xff)) {
+ iBuf->mdpImg.mdpOp &=
+ ~(MDPOP_ALPHAB);
+ }
+
+ if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+ || (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_CONSTANT_ALPHA |
+ PPP_OP_BLEND_ALPHA_BLEND_NORMAL;
+ }
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
+ *pppop_reg_ptr |=
+ PPP_BLEND_CALPHA_TRNASP;
+ }
} else {
- if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
- && (iBuf->mdpImg.alpha == 0xff)) {
- iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
- }
-
- if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
- && (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
- *pppop_reg_ptr |=
- PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
- PPP_OP_BLEND_CONSTANT_ALPHA |
- PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
- PPP_BLEND_CALPHA_TRNASP;
-
- *alpha = iBuf->mdpImg.alpha;
- *tpVal = iBuf->mdpImg.tpVal;
+ if (perPixelAlpha) {
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
} else {
- if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
- *pppop_reg_ptr |= PPP_OP_ROT_ON |
- PPP_OP_BLEND_ON |
- PPP_OP_BLEND_SRCPIXEL_TRANSP;
- *tpVal = iBuf->mdpImg.tpVal;
- } else if (iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) {
- *pppop_reg_ptr |= PPP_OP_ROT_ON |
- PPP_OP_BLEND_ON |
+ if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+ && (iBuf->mdpImg.alpha == 0xff)) {
+ iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
+ }
+
+ if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
+ && (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
+ *pppop_reg_ptr |=
+ PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_CONSTANT_ALPHA |
PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
- PPP_OP_BLEND_CONSTANT_ALPHA;
+ PPP_BLEND_CALPHA_TRNASP;
+
*alpha = iBuf->mdpImg.alpha;
+ *tpVal = iBuf->mdpImg.tpVal;
+ } else {
+ if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_SRCPIXEL_TRANSP;
+ *tpVal = iBuf->mdpImg.tpVal;
+ } else if (iBuf->mdpImg.mdpOp & MDPOP_ALPHAB) {
+ *pppop_reg_ptr |= PPP_OP_ROT_ON |
+ PPP_OP_BLEND_ON |
+ PPP_OP_BLEND_ALPHA_BLEND_NORMAL |
+ PPP_OP_BLEND_CONSTANT_ALPHA;
+ *alpha = iBuf->mdpImg.alpha;
+ }
}
}
}
diff --git a/drivers/video/msm/mipi_truly_tft540960_1_e.c b/drivers/video/msm/mipi_truly_tft540960_1_e.c
index 937a598..30e255e 100644
--- a/drivers/video/msm/mipi_truly_tft540960_1_e.c
+++ b/drivers/video/msm/mipi_truly_tft540960_1_e.c
@@ -59,7 +59,7 @@
/* add 0X BD command */
static char cmd26_2[6] = {
- 0xBD, 0x01, 0x60, 0x10, 0x38, 0x01 /* 55 HZ */
+ 0xBD, 0x01, 0x48, 0x10, 0x38, 0x01 /* 59 HZ */
};
static char cmd5[5] = {
diff --git a/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c b/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c
index 82efbef..b3805c5 100644
--- a/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c
+++ b/drivers/video/msm/mipi_truly_tft540960_1_e_cmd_qhd_pt.c
@@ -64,7 +64,7 @@
pinfo.lcd.vsync_enable = TRUE;
pinfo.lcd.hw_vsync_mode = TRUE;
- pinfo.lcd.refx100 = 6000; /* adjust refx100 to prevent tearing */
+ pinfo.lcd.refx100 = 6100; /* adjust refx100 to prevent tearing */
pinfo.mipi.mode = DSI_CMD_MODE;
pinfo.mipi.dst_format = DSI_CMD_DST_FORMAT_RGB888;
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 91dc16c..6ec5d70 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -1239,6 +1239,8 @@
snprintf(fix->id, sizeof(fix->id), "msmfb31_%x", (__u32) *id);
#elif defined(CONFIG_FB_MSM_MDP40)
snprintf(fix->id, sizeof(fix->id), "msmfb40_%x", (__u32) *id);
+#elif defined(CONFIG_FB_MSM_MDP_NONE)
+ snprintf(fix->id, sizeof(fix->id), "msmfb0_%x", (__u32) *id);
#else
error CONFIG_FB_MSM_MDP undefined !
#endif
diff --git a/include/linux/mfd/pm8xxx/core.h b/include/linux/mfd/pm8xxx/core.h
index e7bf820..b907219 100644
--- a/include/linux/mfd/pm8xxx/core.h
+++ b/include/linux/mfd/pm8xxx/core.h
@@ -42,6 +42,8 @@
#define PM8XXX_REVISION_8901_1p1 2
#define PM8XXX_REVISION_8901_2p0 3
#define PM8XXX_REVISION_8901_2p1 4
+#define PM8XXX_REVISION_8901_2p2 5
+#define PM8XXX_REVISION_8901_2p3 6
#define PM8XXX_REVISION_8921_TEST 0
#define PM8XXX_REVISION_8921_1p0 1
diff --git a/include/linux/mfd/pm8xxx/misc.h b/include/linux/mfd/pm8xxx/misc.h
index c90d8d1..77683ce 100644
--- a/include/linux/mfd/pm8xxx/misc.h
+++ b/include/linux/mfd/pm8xxx/misc.h
@@ -79,7 +79,7 @@
};
enum pm8xxx_aux_clk_div {
- X0_DIV_NONE,
+ XO_DIV_NONE,
XO_DIV_1,
XO_DIV_2,
XO_DIV_4,
diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h
index 0e62644..22c3772 100644
--- a/include/linux/msm_kgsl.h
+++ b/include/linux/msm_kgsl.h
@@ -170,6 +170,7 @@
struct msm_bus_scale_pdata *bus_scale_table;
struct kgsl_device_iommu_data *iommu_data;
int iommu_count;
+ struct msm_dcvs_core_info *core_info;
};
#endif
diff --git a/include/media/gpio-ir-recv.h b/include/media/gpio-ir-recv.h
index 3eab611..61a7fbb 100644
--- a/include/media/gpio-ir-recv.h
+++ b/include/media/gpio-ir-recv.h
@@ -16,7 +16,6 @@
struct gpio_ir_recv_platform_data {
unsigned int gpio_nr;
bool active_low;
- bool can_wakeup;
};
#endif /* __GPIO_IR_RECV_H__ */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 4c86f24..d98a79d 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -586,10 +586,7 @@
}
int hci_chan_put(struct hci_chan *chan);
-struct hci_chan *hci_chan_accept(struct hci_conn *hcon,
- struct hci_ext_fs *tx_fs,
- struct hci_ext_fs *rx_fs);
-struct hci_chan *hci_chan_create(struct hci_conn *hcon,
+struct hci_chan *hci_chan_create(struct hci_chan *chan,
struct hci_ext_fs *tx_fs,
struct hci_ext_fs *rx_fs);
void hci_chan_modify(struct hci_chan *chan,
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index 2854395..f87be20 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -520,6 +520,7 @@
return chan;
}
+EXPORT_SYMBOL(hci_chan_add);
int hci_chan_del(struct hci_chan *chan)
{
@@ -1001,18 +1002,12 @@
}
}
-struct hci_chan *hci_chan_accept(struct hci_conn *conn,
+struct hci_chan *hci_chan_create(struct hci_chan *chan,
struct hci_ext_fs *tx_fs, struct hci_ext_fs *rx_fs)
{
- struct hci_chan *chan;
struct hci_cp_create_logical_link cp;
- chan = hci_chan_add(conn->hdev);
- if (!chan)
- return NULL;
-
chan->state = BT_CONNECT;
- chan->conn = conn;
chan->tx_fs = *tx_fs;
chan->rx_fs = *rx_fs;
cp.phy_handle = chan->conn->handle;
@@ -1029,40 +1024,12 @@
cp.rx_fs.acc_latency = cpu_to_le32(chan->rx_fs.acc_latency);
cp.rx_fs.flush_to = cpu_to_le32(chan->rx_fs.flush_to);
hci_conn_hold(chan->conn);
- hci_send_cmd(conn->hdev, HCI_OP_ACCEPT_LOGICAL_LINK, sizeof(cp), &cp);
- return chan;
-}
-EXPORT_SYMBOL(hci_chan_accept);
-
-struct hci_chan *hci_chan_create(struct hci_conn *conn,
- struct hci_ext_fs *tx_fs, struct hci_ext_fs *rx_fs)
-{
- struct hci_chan *chan;
- struct hci_cp_create_logical_link cp;
-
- chan = hci_chan_add(conn->hdev);
- if (!chan)
- return NULL;
-
- chan->state = BT_CONNECT;
- chan->conn = conn;
- chan->tx_fs = *tx_fs;
- chan->rx_fs = *rx_fs;
- cp.phy_handle = chan->conn->handle;
- cp.tx_fs.id = chan->tx_fs.id;
- cp.tx_fs.type = chan->tx_fs.type;
- cp.tx_fs.max_sdu = cpu_to_le16(chan->tx_fs.max_sdu);
- cp.tx_fs.sdu_arr_time = cpu_to_le32(chan->tx_fs.sdu_arr_time);
- cp.tx_fs.acc_latency = cpu_to_le32(chan->tx_fs.acc_latency);
- cp.tx_fs.flush_to = cpu_to_le32(chan->tx_fs.flush_to);
- cp.rx_fs.id = chan->rx_fs.id;
- cp.rx_fs.type = chan->rx_fs.type;
- cp.rx_fs.max_sdu = cpu_to_le16(chan->rx_fs.max_sdu);
- cp.rx_fs.sdu_arr_time = cpu_to_le32(chan->rx_fs.sdu_arr_time);
- cp.rx_fs.acc_latency = cpu_to_le32(chan->rx_fs.acc_latency);
- cp.rx_fs.flush_to = cpu_to_le32(chan->rx_fs.flush_to);
- hci_conn_hold(chan->conn);
- hci_send_cmd(conn->hdev, HCI_OP_CREATE_LOGICAL_LINK, sizeof(cp), &cp);
+ if (chan->conn->out)
+ hci_send_cmd(chan->conn->hdev, HCI_OP_CREATE_LOGICAL_LINK,
+ sizeof(cp), &cp);
+ else
+ hci_send_cmd(chan->conn->hdev, HCI_OP_ACCEPT_LOGICAL_LINK,
+ sizeof(cp), &cp);
return chan;
}
EXPORT_SYMBOL(hci_chan_create);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 739b04c..de3ab22 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3186,8 +3186,9 @@
return 1;
}
-static struct hci_chan *l2cap_chan_admit(u8 amp_id, struct l2cap_pinfo *pi)
+static struct hci_chan *l2cap_chan_admit(u8 amp_id, struct sock *sk)
{
+ struct l2cap_pinfo *pi = l2cap_pi(sk);
struct hci_dev *hdev;
struct hci_conn *hcon;
struct hci_chan *chan;
@@ -3207,19 +3208,23 @@
chan = hci_chan_list_lookup_id(hdev, hcon->handle);
if (chan) {
l2cap_aggregate(chan, pi);
+ sock_hold(sk);
+ chan->l2cap_sk = sk;
+ hci_chan_hold(chan);
+ pi->ampchan = chan;
goto done;
}
- if (bt_sk(pi)->parent) {
- /* Incoming connection */
- chan = hci_chan_accept(hcon,
- (struct hci_ext_fs *) &pi->local_fs,
- (struct hci_ext_fs *) &pi->remote_fs);
- } else {
- /* Outgoing connection */
- chan = hci_chan_create(hcon,
- (struct hci_ext_fs *) &pi->local_fs,
- (struct hci_ext_fs *) &pi->remote_fs);
+ chan = hci_chan_add(hdev);
+ if (chan) {
+ chan->conn = hcon;
+ sock_hold(sk);
+ chan->l2cap_sk = sk;
+ hci_chan_hold(chan);
+ pi->ampchan = chan;
+ hci_chan_create(chan,
+ (struct hci_ext_fs *) &pi->local_fs,
+ (struct hci_ext_fs *) &pi->remote_fs);
}
done:
hci_dev_put(hdev);
@@ -3625,14 +3630,10 @@
struct hci_chan *chan;
/* Trigger logical link creation only on AMP */
- chan = l2cap_chan_admit(pi->amp_id, pi);
+ chan = l2cap_chan_admit(pi->amp_id, sk);
if (!chan)
return -ECONNREFUSED;
- hci_chan_hold(chan);
- pi->ampchan = chan;
- chan->l2cap_sk = sk;
-
if (chan->state == BT_CONNECTED)
l2cap_create_cfm(chan, 0);
}
@@ -4466,17 +4467,13 @@
/* Already sent a 'pending' response, so set up
* the logical link now
*/
- chan = l2cap_chan_admit(pi->amp_id, pi);
+ chan = l2cap_chan_admit(pi->amp_id, sk);
if (!chan) {
l2cap_send_disconn_req(pi->conn, sk,
ECONNRESET);
goto done;
}
- hci_chan_hold(chan);
- pi->ampchan = chan;
- chan->l2cap_sk = sk;
-
if (chan->state == BT_CONNECTED)
l2cap_create_cfm(chan, 0);
}
@@ -5004,7 +5001,7 @@
}
pi->remote_fs = default_fs;
pi->local_fs = default_fs;
- chan = l2cap_chan_admit(pi->amp_move_id, pi);
+ chan = l2cap_chan_admit(pi->amp_move_id, sk);
if (!chan) {
/* Logical link not available */
l2cap_send_move_chan_cfm(conn, pi, pi->scid,
@@ -5012,10 +5009,6 @@
break;
}
- hci_chan_hold(chan);
- pi->ampchan = chan;
- chan->l2cap_sk = sk;
-
if (chan->state == BT_CONNECTED) {
/* Logical link is already ready to go */
pi->ampcon = chan->conn;
@@ -5323,12 +5316,8 @@
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
pi->remote_fs = default_fs;
pi->local_fs = default_fs;
- chan = l2cap_chan_admit(local_id, pi);
+ chan = l2cap_chan_admit(local_id, sk);
if (chan) {
- hci_chan_hold(chan);
- pi->ampchan = chan;
- chan->l2cap_sk = sk;
-
if (chan->state == BT_CONNECTED) {
/* Logical link is ready to go */
pi->ampcon = chan->conn;
@@ -5465,7 +5454,9 @@
} else if ((pi->amp_move_state !=
L2CAP_AMP_STATE_WAIT_MOVE_RSP_SUCCESS) &&
(pi->amp_move_state !=
- L2CAP_AMP_STATE_WAIT_MOVE_CONFIRM)) {
+ L2CAP_AMP_STATE_WAIT_MOVE_CONFIRM) &&
+ (pi->amp_move_state !=
+ L2CAP_AMP_STATE_WAIT_MOVE_CONFIRM_RSP)) {
/* Move was not in expected state, free the channel */
ampchan = pi->ampchan;
ampcon = pi->ampcon;
@@ -5544,9 +5535,7 @@
{
struct l2cap_logical_link_work *amp_work;
- if (chan->l2cap_sk) {
- sock_hold(chan->l2cap_sk);
- } else {
+ if (!chan->l2cap_sk) {
BT_ERR("Expected l2cap_sk to point to connecting socket");
return -EFAULT;
}
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 2c43792..74e2dc0 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -3591,6 +3591,7 @@
ret = wcd9xxx_close_slim_sch_rx(tabla,
tabla_p->dai[j].ch_num,
tabla_p->dai[j].ch_tot);
+ usleep_range(5000, 5000);
tabla_p->dai[j].rate = 0;
memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
tabla_p->dai[j].ch_tot));