Merge changes I05c08088,I0fea4c5f into msm-3.0
* changes:
tty: n_smux: Add Dedicated Power Control Queue
tty: n_smux: Add support for SMUX subsystem restart
diff --git a/Documentation/devicetree/bindings/pil/pil-mba.txt b/Documentation/devicetree/bindings/pil/pil-mba.txt
new file mode 100644
index 0000000..7aafd219
--- /dev/null
+++ b/Documentation/devicetree/bindings/pil/pil-mba.txt
@@ -0,0 +1,27 @@
+Qualcomm Modem Boot Authenticator Peripheral Image Loader
+
+pil-mba is a peripheral image loader (PIL) driver. It is used for loading
+modem images using the self-authenticating hardware and software features
+of the Modem Boot Authenticator.
+
+Required properties:
+- compatible: Must be "qcom,pil-mba"
+- reg: Two pairs of physical base addresses and sizes. The
+ first corresponds to the Relay Message Buffer (RMB)
+ register base. The second specifies the address at which
+ the primary modem image metadata should be stored.
+- qcom,firmware-name: Base name of the firmware image. Ex. "modem"
+
+Optional properties:
+- qcom,depends-on: firmware-name of a prerequisite image that must already
+ be running.
+
+Example:
+ qcom,mba@fc820000 {
+ compatible = "qcom,pil-mba";
+ reg = <0xfc820000 0x0020>,
+ <0x0d1f0000 0x4000>;
+
+ qcom,firmware-name = "modem";
+ qcom,depends-on = "mba";
+ };
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
new file mode 100644
index 0000000..95e7f88
--- /dev/null
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -0,0 +1,32 @@
+Qualcomm MSS QDSP6v5 Peripheral Image Loader
+
+pil-qdsp6v5-mss is a peripheral image loader (PIL) driver. It is used for
+loading QDSP6v5 (Hexagon) firmware images for modem subsystems into memory and
+preparing the subsystem's processor to execute code. It's also responsible for
+shutting down the processor when it's not needed.
+
+Required properties:
+- compatible: Must be "qcom,pil-q6v5-mss"
+- reg: Four pairs of physical base addresses and region sizes of
+ memory mapped registers. The first region corresponds to
+ QDSP6SS_PUB, the second to the bus port halt register
+ base, the third to the MSS_RELAY_MSG_BUFFER base, and the
+ fourth to the MSS_RESTART register.
+- vdd_mss-supply: Reference to the regulator that supplies the processor.
+- qcom,firmware-name: Base name of the firmware image. Ex. "mdsp"
+- qcom,pil-self-auth: <0> if the hardware does not require self-authenticating
+ images and self-authentication is not desired;
+ <1> if the hardware requires self-authenticating images.
+
+Example:
+ qcom,mss@fc880000 {
+ compatible = "qcom,pil-q6v5-mss";
+ reg = <0xfc880000 0x100>,
+ <0xfd485000 0x400>,
+ <0xfc820000 0x020>,
+ <0xfc401680 0x004>;
+ vdd_mss-supply = <&pm8841_s3>;
+
+ qcom,firmware-name = "mba";
+ qcom,pil-self-auth = <1>;
+ };
diff --git a/arch/arm/boot/dts/msmcopper.dtsi b/arch/arm/boot/dts/msmcopper.dtsi
index 60f59d3..a902ba5 100644
--- a/arch/arm/boot/dts/msmcopper.dtsi
+++ b/arch/arm/boot/dts/msmcopper.dtsi
@@ -289,6 +289,27 @@
qcom,firmware-name = "adsp";
};
+ qcom,mss@fc880000 {
+ compatible = "qcom,pil-q6v5-mss";
+ reg = <0xfc880000 0x100>,
+ <0xfd485000 0x400>,
+ <0xfc820000 0x020>,
+ <0xfc401680 0x004>;
+ vdd_mss-supply = <&pm8841_s3>;
+
+ qcom,firmware-name = "mba";
+ qcom,pil-self-auth = <1>;
+ };
+
+ qcom,mba@fc820000 {
+ compatible = "qcom,pil-mba";
+ reg = <0xfc820000 0x0020>,
+ <0x0d1fc000 0x4000>;
+
+ qcom,firmware-name = "modem";
+ qcom,depends-on = "mba";
+ };
+
qcom,pronto@fb21b000 {
compatible = "qcom,pil-pronto";
reg = <0xfb21b000 0x3000>,
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 39f04cb..0b44865 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -43,6 +43,8 @@
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
# CONFIG_MSM_HW3D is not set
CONFIG_MSM_PIL_LPASS_QDSP6V5=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_MSM_PIL_MBA=y
CONFIG_MSM_PIL_PRONTO=y
CONFIG_MSM_IOMMU=y
CONFIG_MSM_DIRECT_SCLK_ACCESS=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index a24498c..e603703 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1857,8 +1857,22 @@
tristate "LPASS QDSP6v5 (Hexagon) Boot Support"
depends on MSM_PIL
help
- Support for booting and shutting down QDSP6v5 processors (Hexagon)
- processors in low power audio subsystems.
+ Support for booting and shutting down QDSP6v5 (Hexagon) processors
+ in low power audio subsystems.
+
+config MSM_PIL_MSS_QDSP6V5
+ tristate "MSS QDSP6v5 (Hexagon) Boot Support"
+ depends on MSM_PIL
+ help
+ Support for booting and shutting down QDSP6v5 (Hexagon) processors
+ in modem subsystems.
+
+config MSM_PIL_MBA
+ tristate "Support for modem self-authentication"
+ depends on MSM_PIL_MSS_QDSP6V5
+ help
+ Support for booting self-authenticating modems using the Modem Boot
+ Authenticator.
config MSM_PIL_RIVA
tristate "RIVA (WCNSS) Boot Support"
@@ -2311,6 +2325,16 @@
For production builds, you should probably say 'N' here.
+config MSM_L1_ERR_LOG
+ bool "Log CPU ERP events to system memory"
+ depends on MSM_CACHE_ERP
+ help
+ Enable logging CPU ERP events to an area of memory that will be
+ preserved across a system reset. This may be useful for detecting and
+ troubleshooting ERP-related system crashes in the field.
+
+ For production builds, you may want to say 'Y' here.
+
config MSM_L2_ERP_PRINT_ACCESS_ERRORS
bool "Report L2 master port slave/decode errors in kernel log"
depends on MSM_CACHE_ERP
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index bcc6582..2ad51cd 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -68,6 +68,8 @@
obj-$(CONFIG_MSM_PIL_QDSP6V3) += pil-q6v3.o
obj-$(CONFIG_MSM_PIL_QDSP6V4) += pil-q6v4.o
obj-$(CONFIG_MSM_PIL_LPASS_QDSP6V5) += pil-q6v5.o pil-q6v5-lpass.o
+obj-$(CONFIG_MSM_PIL_MSS_QDSP6V5) += pil-q6v5.o pil-q6v5-mss.o
+obj-$(CONFIG_MSM_PIL_MBA) += pil-mba.o
obj-$(CONFIG_MSM_PIL_RIVA) += pil-riva.o
obj-$(CONFIG_MSM_PIL_TZAPPS) += pil-tzapps.o
obj-$(CONFIG_MSM_PIL_VIDC) += pil-vidc.o
diff --git a/arch/arm/mach-msm/board-8064-pmic.c b/arch/arm/mach-msm/board-8064-pmic.c
index 1a0a287..7e04ca7 100644
--- a/arch/arm/mach-msm/board-8064-pmic.c
+++ b/arch/arm/mach-msm/board-8064-pmic.c
@@ -126,7 +126,6 @@
PM8921_GPIO_INPUT(38, PM_GPIO_PULL_UP_30),
/* TABLA CODEC RESET */
PM8921_GPIO_OUTPUT(34, 1, MED),
- PM8921_GPIO_INPUT(31, PM_GPIO_PULL_NO),
PM8921_GPIO_OUTPUT(13, 0, HIGH), /* PCIE_CLK_PWR_EN */
};
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 40222b8..ccd9c54 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -589,7 +589,7 @@
RPM_LDO(L22, 0, 1, 0, 2600000, 2600000, NULL, 0, 0),
RPM_LDO(L23, 0, 1, 0, 1800000, 1800000, NULL, 0, 0),
RPM_LDO(L24, 0, 1, 1, 750000, 1150000, "8921_s1", 10000, 10000),
- RPM_LDO(L25, 1, 1, 0, 1225000, 1225000, "8921_s1", 10000, 10000),
+ RPM_LDO(L25, 1, 1, 0, 1250000, 1250000, "8921_s1", 10000, 10000),
RPM_LDO(L27, 0, 1, 0, 1100000, 1100000, "8921_s7", 0, 0),
RPM_LDO(L28, 0, 1, 0, 1050000, 1050000, "8921_s7", 0, 0),
RPM_LDO(L29, 0, 1, 0, 2000000, 2000000, NULL, 0, 0),
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index 96e54b6..f3790dd 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -366,10 +366,29 @@
}
if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
machine_is_mpq8064_dtv()) {
+ int rc;
+ struct pm_gpio sd_card_det_init_cfg = {
+ .direction = PM_GPIO_DIR_IN,
+ .output_buffer = PM_GPIO_OUT_BUF_CMOS,
+ .pull = PM_GPIO_PULL_UP_30,
+ .vin_sel = PM_GPIO_VIN_S4,
+ .out_strength = PM_GPIO_STRENGTH_NO,
+ .function = PM_GPIO_FUNC_NORMAL,
+ };
+
apq8064_sdc3_pdata->status_gpio =
PM8921_GPIO_PM_TO_SYS(31);
apq8064_sdc3_pdata->status_irq =
PM8921_GPIO_IRQ(PM8921_IRQ_BASE, 31);
+ rc = pm8xxx_gpio_config(apq8064_sdc3_pdata->status_gpio,
+ &sd_card_det_init_cfg);
+ if (rc) {
+ pr_info("%s: SD_CARD_DET GPIO%d config "
+ "failed(%d)\n", __func__,
+ apq8064_sdc3_pdata->status_gpio, rc);
+ apq8064_sdc3_pdata->status_gpio = 0;
+ apq8064_sdc3_pdata->status_irq = 0;
+ }
}
apq8064_add_sdcc(3, apq8064_sdc3_pdata);
}
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 566befb..12d67a9 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1026,13 +1026,13 @@
{
.name = "VDDD_CDC_D",
.min_uV = 1225000,
- .max_uV = 1225000,
+ .max_uV = 1250000,
.optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
},
{
.name = "CDC_VDDA_A_1P2V",
.min_uV = 1225000,
- .max_uV = 1225000,
+ .max_uV = 1250000,
.optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
},
},
@@ -1093,13 +1093,13 @@
{
.name = "VDDD_CDC_D",
.min_uV = 1225000,
- .max_uV = 1225000,
+ .max_uV = 1250000,
.optimum_uA = WCD9XXX_VDDD_CDC_D_CUR_MAX,
},
{
.name = "CDC_VDDA_A_1P2V",
.min_uV = 1225000,
- .max_uV = 1225000,
+ .max_uV = 1250000,
.optimum_uA = WCD9XXX_VDDD_CDC_A_CUR_MAX,
},
},
@@ -2188,6 +2188,7 @@
&apq_cpudai_slimbus_1_tx,
&apq_cpudai_slimbus_2_tx,
&apq_cpudai_slimbus_3_rx,
+ &apq_cpudai_slimbus_3_tx,
&apq8064_rpm_device,
&apq8064_rpm_log_device,
&apq8064_rpm_stat_device,
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index 62bab86..53de3b2 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -495,6 +495,8 @@
"msm_sdcc.4", NULL),
OF_DEV_AUXDATA("qcom,pil-q6v5-lpass", 0xFE200000, \
"pil-q6v5-lpass", NULL),
+ OF_DEV_AUXDATA("qcom,pil-q6v5-mss", 0xFC880000, "pil-q6v5-mss", NULL),
+ OF_DEV_AUXDATA("qcom,pil-mba", 0xFC820000, "pil-mba", NULL),
OF_DEV_AUXDATA("qcom,pil-pronto", 0xFB21B000, \
"pil_pronto", NULL),
OF_DEV_AUXDATA("qcom,msm-rng", 0xF9BFF000, \
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index e2ec60f..c6e20ca 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -2650,11 +2650,19 @@
#define USER_SMI_SIZE (MSM_SMI_SIZE - KERNEL_SMI_SIZE)
#define MSM_PMEM_SMIPOOL_SIZE USER_SMI_SIZE
+#define MSM_ION_HOLE_SIZE SZ_128K /* (128KB) */
+#define MSM_MM_FW_SIZE (0x200000 - MSM_ION_HOLE_SIZE) /*(2MB-128KB)*/
+#define MSM_ION_MM_SIZE 0x3800000 /* (56MB) */
+#define MSM_ION_MFC_SIZE SZ_8K
+
+#define MSM_MM_FW_BASE MSM_SMI_BASE
+#define MSM_ION_HOLE_BASE (MSM_MM_FW_BASE + MSM_MM_FW_SIZE)
+#define MSM_ION_MM_BASE (MSM_ION_HOLE_BASE + MSM_ION_HOLE_SIZE)
+#define MSM_ION_MFC_BASE (MSM_ION_MM_BASE + MSM_ION_MM_SIZE)
+
#define MSM_ION_SF_SIZE 0x4000000 /* 64MB */
#define MSM_ION_CAMERA_SIZE MSM_PMEM_ADSP_SIZE
-#define MSM_ION_MM_FW_SIZE 0x200000 /* (2MB) */
-#define MSM_ION_MM_SIZE 0x3c00000 /* (60MB) Must be a multiple of 64K */
-#define MSM_ION_MFC_SIZE SZ_8K
+
#ifdef CONFIG_FB_MSM_OVERLAY1_WRITEBACK
#define MSM_ION_WB_SIZE 0xC00000 /* 12MB */
#else
@@ -5296,6 +5304,8 @@
.request_region = request_smi_region,
.release_region = release_smi_region,
.setup_region = setup_smi_region,
+ .secure_base = MSM_ION_HOLE_BASE,
+ .secure_size = MSM_ION_HOLE_SIZE + MSM_ION_MM_SIZE,
.iommu_map_all = 1,
.iommu_2x_map_domain = VIDEO_DOMAIN,
};
@@ -5313,9 +5323,8 @@
.align = PAGE_SIZE,
};
-static struct ion_co_heap_pdata fw_co_ion_pdata = {
+static struct ion_co_heap_pdata hole_co_ion_pdata = {
.adjacent_mem_id = ION_CP_MM_HEAP_ID,
- .align = SZ_128K,
};
static struct ion_co_heap_pdata co_ion_pdata = {
@@ -5348,6 +5357,7 @@
.id = ION_CP_MM_HEAP_ID,
.type = ION_HEAP_TYPE_CP,
.name = ION_MM_HEAP_NAME,
+ .base = MSM_ION_MM_BASE,
.size = MSM_ION_MM_SIZE,
.memory_type = ION_SMI_TYPE,
.extra_data = (void *) &cp_mm_ion_pdata,
@@ -5356,14 +5366,16 @@
.id = ION_MM_FIRMWARE_HEAP_ID,
.type = ION_HEAP_TYPE_CARVEOUT,
.name = ION_MM_FIRMWARE_HEAP_NAME,
- .size = MSM_ION_MM_FW_SIZE,
+ .base = MSM_ION_HOLE_BASE,
+ .size = MSM_ION_HOLE_SIZE,
.memory_type = ION_SMI_TYPE,
- .extra_data = (void *) &fw_co_ion_pdata,
+ .extra_data = (void *) &hole_co_ion_pdata,
},
{
.id = ION_CP_MFC_HEAP_ID,
.type = ION_HEAP_TYPE_CP,
.name = ION_MFC_HEAP_NAME,
+ .base = MSM_ION_MFC_BASE,
.size = MSM_ION_MFC_SIZE,
.memory_type = ION_SMI_TYPE,
.extra_data = (void *) &cp_mfc_ion_pdata,
@@ -5432,12 +5444,7 @@
.size = KERNEL_SMI_SIZE,
.flags = MEMTYPE_FLAGS_FIXED,
},
- /* User space SMI memory pool for video core */
- /* used for encoder, decoder input & output buffers */
[MEMTYPE_SMI] = {
- .start = USER_SMI_BASE,
- .limit = USER_SMI_SIZE,
- .flags = MEMTYPE_FLAGS_FIXED,
},
[MEMTYPE_EBI0] = {
.flags = MEMTYPE_FLAGS_1M_ALIGN,
@@ -5482,9 +5489,6 @@
}
msm8x60_reserve_table[MEMTYPE_EBI1].size += msm_ion_sf_size;
- msm8x60_reserve_table[MEMTYPE_SMI].size += MSM_ION_MM_FW_SIZE;
- msm8x60_reserve_table[MEMTYPE_SMI].size += MSM_ION_MM_SIZE;
- msm8x60_reserve_table[MEMTYPE_SMI].size += MSM_ION_MFC_SIZE;
msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_CAMERA_SIZE;
msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_WB_SIZE;
msm8x60_reserve_table[MEMTYPE_EBI1].size += MSM_ION_AUDIO_SIZE;
diff --git a/arch/arm/mach-msm/cache_erp.c b/arch/arm/mach-msm/cache_erp.c
index 97225ac..4d7ce12 100644
--- a/arch/arm/mach-msm/cache_erp.c
+++ b/arch/arm/mach-msm/cache_erp.c
@@ -35,6 +35,9 @@
/* Print a message for everything but TLB MH events */
#define CESR_PRINT_MASK 0x000000FF
+/* Log everything but TLB MH events */
+#define CESR_LOG_EVENT_MASK 0x000000FF
+
#define L2ESR_IND_ADDR 0x204
#define L2ESYNR0_IND_ADDR 0x208
#define L2ESYNR1_IND_ADDR 0x209
@@ -87,6 +90,9 @@
#define MODULE_NAME "msm_cache_erp"
+#define ERP_LOG_MAGIC_ADDR 0x748
+#define ERP_LOG_MAGIC 0x11C39893
+
struct msm_l1_err_stats {
unsigned int dctpe;
unsigned int dcdpe;
@@ -114,6 +120,10 @@
static int l1_erp_irq, l2_erp_irq;
static struct proc_dir_entry *procfs_entry;
+#ifdef CONFIG_MSM_L1_ERR_LOG
+static struct proc_dir_entry *procfs_log_entry;
+#endif
+
static inline unsigned int read_cesr(void)
{
unsigned int cesr;
@@ -192,6 +202,48 @@
return len;
}
+#ifdef CONFIG_MSM_L1_ERR_LOG
+static int proc_read_log(char *page, char **start, off_t off, int count,
+ int *eof, void *data)
+{
+ char *p = page;
+ int len, log_value;
+ log_value = __raw_readl(MSM_IMEM_BASE + ERP_LOG_MAGIC_ADDR) ==
+ ERP_LOG_MAGIC ? 1 : 0;
+
+ p += snprintf(p, PAGE_SIZE, "%d\n", log_value);
+
+ len = (p - page) - off;
+ if (len < 0)
+ len = 0;
+
+ *eof = (len <= count) ? 1 : 0;
+ *start = page + off;
+
+ return len;
+}
+
+static void log_cpu_event(void)
+{
+ __raw_writel(ERP_LOG_MAGIC, MSM_IMEM_BASE + ERP_LOG_MAGIC_ADDR);
+ mb();
+}
+
+static int procfs_event_log_init(void)
+{
+ procfs_log_entry = create_proc_entry("cpu/msm_erp_log", S_IRUGO, NULL);
+
+ if (!procfs_log_entry)
+ return -ENODEV;
+ procfs_log_entry->read_proc = proc_read_log;
+ return 0;
+}
+
+#else
+static inline void log_cpu_event(void) { }
+static inline int procfs_event_log_init(void) { return 0; }
+#endif
+
static irqreturn_t msm_l1_erp_irq(int irq, void *dev_id)
{
struct msm_l1_err_stats *l1_stats = dev_id;
@@ -199,6 +251,7 @@
unsigned int i_cesynr, d_cesynr;
unsigned int cpu = smp_processor_id();
int print_regs = cesr & CESR_PRINT_MASK;
+ int log_event = cesr & CESR_LOG_EVENT_MASK;
void *const saw_bases[] = {
MSM_SAW0_BASE,
@@ -271,6 +324,9 @@
pr_alert("D-side CESYNR = 0x%08x\n", d_cesynr);
}
+ if (log_event)
+ log_cpu_event();
+
/* Clear the interrupt bits we processed */
write_cesr(cesr);
@@ -459,6 +515,11 @@
put_online_cpus();
procfs_entry->read_proc = proc_read_status;
+
+ ret = procfs_event_log_init();
+ if (ret)
+ pr_err("Failed to create procfs node for ERP log access\n");
+
return 0;
fail_l2:
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 7b4ca29..79fb69f 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -4605,6 +4605,11 @@
static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c, LONG_MAX);
static DEFINE_CLK_VOTER(ebi1_adm_clk, &ebi1_clk.c, 0);
+static DEFINE_CLK_VOTER(ebi1_acpu_a_clk, &ebi1_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ebi1_msmbus_a_clk, &ebi1_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(afab_acpu_a_clk, &afab_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(afab_msmbus_a_clk, &afab_a_clk.c, LONG_MAX);
+
#ifdef CONFIG_DEBUG_FS
struct measure_sel {
u32 test_vector;
@@ -5030,8 +5035,25 @@
CLK_LOOKUP("pll4", pll4_clk.c, NULL),
CLK_LOOKUP("measure", measure_clk.c, "debug"),
+ CLK_LOOKUP("bus_clk", afab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", afab_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", cfpb_clk.c, ""),
+ CLK_LOOKUP("bus_clk", cfpb_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", dfab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", dfab_a_clk.c, ""),
+ CLK_LOOKUP("mem_clk", ebi1_clk.c, ""),
+ CLK_LOOKUP("mem_clk", ebi1_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmfab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmfab_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmfpb_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmfpb_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfab_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfpb_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfpb_a_clk.c, ""),
+
CLK_LOOKUP("bus_clk", afab_clk.c, "msm_apps_fab"),
- CLK_LOOKUP("bus_a_clk", afab_a_clk.c, "msm_apps_fab"),
+ CLK_LOOKUP("bus_a_clk", afab_msmbus_a_clk.c, "msm_apps_fab"),
CLK_LOOKUP("bus_clk", cfpb_clk.c, "msm_cpss_fpb"),
CLK_LOOKUP("bus_a_clk", cfpb_a_clk.c, "msm_cpss_fpb"),
CLK_LOOKUP("bus_clk", sfab_clk.c, "msm_sys_fab"),
@@ -5041,7 +5063,7 @@
CLK_LOOKUP("bus_clk", mmfab_clk.c, "msm_mm_fab"),
CLK_LOOKUP("bus_a_clk", mmfab_a_clk.c, "msm_mm_fab"),
CLK_LOOKUP("mem_clk", ebi1_msmbus_clk.c, "msm_bus"),
- CLK_LOOKUP("mem_a_clk", ebi1_a_clk.c, "msm_bus"),
+ CLK_LOOKUP("mem_a_clk", ebi1_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
@@ -5313,6 +5335,8 @@
CLK_LOOKUP("smmu_iface_clk", smmu_p_clk.c, "pil_vidc"),
CLK_LOOKUP("mem_clk", ebi1_adm_clk.c, "msm_dmov"),
+ CLK_LOOKUP("mem_clk", ebi1_acpu_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", afab_acpu_a_clk.c, ""),
CLK_LOOKUP("l2_mclk", l2_m_clk, ""),
CLK_LOOKUP("krait0_mclk", krait0_m_clk, ""),
@@ -5336,8 +5360,25 @@
CLK_LOOKUP("pll4", pll4_clk.c, NULL),
CLK_LOOKUP("measure", measure_clk.c, "debug"),
+ CLK_LOOKUP("bus_clk", afab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", afab_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", cfpb_clk.c, ""),
+ CLK_LOOKUP("bus_clk", cfpb_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", dfab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", dfab_a_clk.c, ""),
+ CLK_LOOKUP("mem_clk", ebi1_clk.c, ""),
+ CLK_LOOKUP("mem_clk", ebi1_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmfab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmfab_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmfpb_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmfpb_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfab_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfpb_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfpb_a_clk.c, ""),
+
CLK_LOOKUP("bus_clk", afab_clk.c, "msm_apps_fab"),
- CLK_LOOKUP("bus_a_clk", afab_a_clk.c, "msm_apps_fab"),
+ CLK_LOOKUP("bus_a_clk", afab_msmbus_a_clk.c, "msm_apps_fab"),
CLK_LOOKUP("bus_clk", cfpb_clk.c, "msm_cpss_fpb"),
CLK_LOOKUP("bus_a_clk", cfpb_a_clk.c, "msm_cpss_fpb"),
CLK_LOOKUP("bus_clk", sfab_clk.c, "msm_sys_fab"),
@@ -5347,7 +5388,7 @@
CLK_LOOKUP("bus_clk", mmfab_clk.c, "msm_mm_fab"),
CLK_LOOKUP("bus_a_clk", mmfab_a_clk.c, "msm_mm_fab"),
CLK_LOOKUP("mem_clk", ebi1_msmbus_clk.c, "msm_bus"),
- CLK_LOOKUP("mem_a_clk", ebi1_a_clk.c, "msm_bus"),
+ CLK_LOOKUP("mem_a_clk", ebi1_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
@@ -5611,6 +5652,8 @@
CLK_LOOKUP("bus_clk", dfab_tzcom_clk.c, "tzcom"),
CLK_LOOKUP("mem_clk", ebi1_adm_clk.c, "msm_dmov"),
+ CLK_LOOKUP("mem_clk", ebi1_acpu_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", afab_acpu_a_clk.c, ""),
CLK_LOOKUP("l2_mclk", l2_m_clk, ""),
CLK_LOOKUP("krait0_mclk", krait0_m_clk, ""),
@@ -5633,8 +5676,25 @@
CLK_LOOKUP("pll4", pll4_clk.c, NULL),
CLK_LOOKUP("measure", measure_clk.c, "debug"),
+ CLK_LOOKUP("bus_clk", afab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", afab_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", cfpb_clk.c, ""),
+ CLK_LOOKUP("bus_clk", cfpb_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", dfab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", dfab_a_clk.c, ""),
+ CLK_LOOKUP("mem_clk", ebi1_clk.c, ""),
+ CLK_LOOKUP("mem_clk", ebi1_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmfab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmfab_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmfpb_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmfpb_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfab_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfpb_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfpb_a_clk.c, ""),
+
CLK_LOOKUP("bus_clk", afab_clk.c, "msm_apps_fab"),
- CLK_LOOKUP("bus_a_clk", afab_a_clk.c, "msm_apps_fab"),
+ CLK_LOOKUP("bus_a_clk", afab_msmbus_a_clk.c, "msm_apps_fab"),
CLK_LOOKUP("bus_clk", cfpb_clk.c, "msm_cpss_fpb"),
CLK_LOOKUP("bus_a_clk", cfpb_a_clk.c, "msm_cpss_fpb"),
CLK_LOOKUP("bus_clk", sfab_clk.c, "msm_sys_fab"),
@@ -5644,7 +5704,7 @@
CLK_LOOKUP("bus_clk", mmfab_clk.c, "msm_mm_fab"),
CLK_LOOKUP("bus_a_clk", mmfab_a_clk.c, "msm_mm_fab"),
CLK_LOOKUP("mem_clk", ebi1_msmbus_clk.c, "msm_bus"),
- CLK_LOOKUP("mem_a_clk", ebi1_a_clk.c, "msm_bus"),
+ CLK_LOOKUP("mem_a_clk", ebi1_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
@@ -5885,6 +5945,8 @@
CLK_LOOKUP("bus_clk", dfab_qseecom_clk.c, "qseecom"),
CLK_LOOKUP("mem_clk", ebi1_adm_clk.c, "msm_dmov"),
+ CLK_LOOKUP("mem_clk", ebi1_acpu_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", afab_acpu_a_clk.c, ""),
CLK_LOOKUP("l2_mclk", l2_m_clk, ""),
CLK_LOOKUP("krait0_mclk", krait0_m_clk, ""),
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 7aed579..975587d 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -3117,6 +3117,11 @@
static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c, LONG_MAX);
static DEFINE_CLK_VOTER(ebi1_adm0_clk, &ebi1_clk.c, 0);
static DEFINE_CLK_VOTER(ebi1_adm1_clk, &ebi1_clk.c, 0);
+static DEFINE_CLK_VOTER(ebi1_acpu_a_clk, &ebi1_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ebi1_msmbus_a_clk, &ebi1_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(afab_acpu_a_clk, &afab_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(afab_msmbus_a_clk, &afab_a_clk.c, LONG_MAX);
+
static DEFINE_CLK_MEASURE(sc0_m_clk);
static DEFINE_CLK_MEASURE(sc1_m_clk);
static DEFINE_CLK_MEASURE(l2_m_clk);
@@ -3479,8 +3484,27 @@
CLK_LOOKUP("pll4", pll4_clk.c, "pil_qdsp6v3"),
CLK_LOOKUP("measure", measure_clk.c, "debug"),
+ CLK_LOOKUP("bus_clk", afab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", afab_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", cfpb_clk.c, ""),
+ CLK_LOOKUP("bus_clk", cfpb_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", dfab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", dfab_a_clk.c, ""),
+ CLK_LOOKUP("mem_clk", ebi1_clk.c, ""),
+ CLK_LOOKUP("mem_clk", ebi1_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmfab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmfab_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmfpb_clk.c, ""),
+ CLK_LOOKUP("bus_clk", mmfpb_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfab_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfpb_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfpb_a_clk.c, ""),
+ CLK_LOOKUP("mem_clk", smi_clk.c, ""),
+ CLK_LOOKUP("mem_clk", smi_a_clk.c, ""),
+
CLK_LOOKUP("bus_clk", afab_clk.c, "msm_apps_fab"),
- CLK_LOOKUP("bus_a_clk", afab_a_clk.c, "msm_apps_fab"),
+ CLK_LOOKUP("bus_a_clk", afab_msmbus_a_clk.c, "msm_apps_fab"),
CLK_LOOKUP("bus_clk", sfab_clk.c, "msm_sys_fab"),
CLK_LOOKUP("bus_a_clk", sfab_a_clk.c, "msm_sys_fab"),
CLK_LOOKUP("bus_clk", sfpb_clk.c, "msm_sys_fpb"),
@@ -3490,16 +3514,10 @@
CLK_LOOKUP("bus_clk", cfpb_clk.c, "msm_cpss_fpb"),
CLK_LOOKUP("bus_a_clk", cfpb_a_clk.c, "msm_cpss_fpb"),
CLK_LOOKUP("mem_clk", ebi1_msmbus_clk.c, "msm_bus"),
- CLK_LOOKUP("mem_a_clk", ebi1_a_clk.c, "msm_bus"),
+ CLK_LOOKUP("mem_a_clk", ebi1_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("smi_clk", smi_clk.c, "msm_bus"),
CLK_LOOKUP("smi_a_clk", smi_a_clk.c, "msm_bus"),
- CLK_LOOKUP("ebi1_clk", ebi1_clk.c, NULL),
- CLK_LOOKUP("dfab_clk", dfab_clk.c, NULL),
- CLK_LOOKUP("dfab_a_clk", dfab_a_clk.c, NULL),
- CLK_LOOKUP("mmfpb_clk", mmfpb_clk.c, NULL),
- CLK_LOOKUP("mmfpb_a_clk", mmfpb_a_clk.c, NULL),
-
CLK_LOOKUP("core_clk", gp0_clk.c, ""),
CLK_LOOKUP("core_clk", gp1_clk.c, ""),
CLK_LOOKUP("core_clk", gp2_clk.c, ""),
@@ -3713,6 +3731,8 @@
CLK_LOOKUP("mem_clk", ebi1_adm0_clk.c, "msm_dmov.0"),
CLK_LOOKUP("mem_clk", ebi1_adm1_clk.c, "msm_dmov.1"),
+ CLK_LOOKUP("mem_clk", ebi1_acpu_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", afab_acpu_a_clk.c, ""),
CLK_LOOKUP("sc0_mclk", sc0_m_clk, ""),
CLK_LOOKUP("sc1_mclk", sc1_m_clk, ""),
diff --git a/arch/arm/mach-msm/clock-9615.c b/arch/arm/mach-msm/clock-9615.c
index 66d849a..f7c5a6a 100644
--- a/arch/arm/mach-msm/clock-9615.c
+++ b/arch/arm/mach-msm/clock-9615.c
@@ -1338,7 +1338,11 @@
static DEFINE_CLK_VOTER(dfab_msmbus_clk, &dfab_clk.c, 0);
static DEFINE_CLK_VOTER(dfab_msmbus_a_clk, &dfab_a_clk.c, 0);
static DEFINE_CLK_VOTER(ebi1_msmbus_clk, &ebi1_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ebi1_msmbus_a_clk, &ebi1_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ebi1_acpu_a_clk, &ebi1_a_clk.c, LONG_MAX);
static DEFINE_CLK_VOTER(ebi1_adm_clk, &ebi1_clk.c, 0);
+static DEFINE_CLK_VOTER(sfab_msmbus_a_clk, &sfab_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(sfab_acpu_a_clk, &sfab_a_clk.c, LONG_MAX);
#ifdef CONFIG_DEBUG_FS
struct measure_sel {
@@ -1588,19 +1592,24 @@
CLK_LOOKUP("measure", measure_clk.c, "debug"),
+ CLK_LOOKUP("bus_clk", cfpb_clk.c, ""),
+ CLK_LOOKUP("bus_clk", cfpb_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", dfab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", dfab_a_clk.c, ""),
+ CLK_LOOKUP("mem_clk", ebi1_clk.c, ""),
+ CLK_LOOKUP("mem_clk", ebi1_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfab_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfab_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfpb_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfpb_a_clk.c, ""),
+
CLK_LOOKUP("bus_clk", sfab_clk.c, "msm_sys_fab"),
- CLK_LOOKUP("bus_a_clk", sfab_a_clk.c, "msm_sys_fab"),
+ CLK_LOOKUP("bus_a_clk", sfab_msmbus_a_clk.c, "msm_sys_fab"),
CLK_LOOKUP("mem_clk", ebi1_msmbus_clk.c, "msm_bus"),
- CLK_LOOKUP("mem_a_clk", ebi1_a_clk.c, "msm_bus"),
+ CLK_LOOKUP("mem_a_clk", ebi1_msmbus_a_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_clk", dfab_msmbus_clk.c, "msm_bus"),
CLK_LOOKUP("dfab_a_clk", dfab_msmbus_a_clk.c, "msm_bus"),
- CLK_LOOKUP("bus_clk", sfpb_clk.c, NULL),
- CLK_LOOKUP("bus_a_clk", sfpb_a_clk.c, NULL),
- CLK_LOOKUP("bus_clk", cfpb_clk.c, NULL),
- CLK_LOOKUP("bus_a_clk", cfpb_a_clk.c, NULL),
- CLK_LOOKUP("ebi1_clk", ebi1_clk.c, NULL),
-
CLK_LOOKUP("core_clk", gp0_clk.c, ""),
CLK_LOOKUP("core_clk", gp1_clk.c, ""),
CLK_LOOKUP("core_clk", gp2_clk.c, ""),
@@ -1682,6 +1691,8 @@
CLK_LOOKUP("dfab_clk", dfab_sps_clk.c, "msm_sps"),
CLK_LOOKUP("bus_clk", dfab_bam_dmux_clk.c, "BAM_RMNT"),
CLK_LOOKUP("mem_clk", ebi1_adm_clk.c, "msm_dmov"),
+ CLK_LOOKUP("mem_clk", ebi1_acpu_a_clk.c, ""),
+ CLK_LOOKUP("bus_clk", sfab_acpu_a_clk.c, ""),
CLK_LOOKUP("iface_clk", ce1_p_clk.c, "qce.0"),
CLK_LOOKUP("iface_clk", ce1_p_clk.c, "qcrypto.0"),
diff --git a/arch/arm/mach-msm/clock-copper.c b/arch/arm/mach-msm/clock-copper.c
index fc0b0af..c33d486 100644
--- a/arch/arm/mach-msm/clock-copper.c
+++ b/arch/arm/mach-msm/clock-copper.c
@@ -4577,6 +4577,8 @@
static struct clk_lookup msm_clocks_copper[] = {
CLK_LOOKUP("xo", cxo_clk_src.c, "msm_otg"),
CLK_LOOKUP("xo", cxo_clk_src.c, "pil-q6v5-lpass"),
+ CLK_LOOKUP("xo", cxo_clk_src.c, "pil-q6v5-mss"),
+ CLK_LOOKUP("xo", cxo_clk_src.c, "pil-mba"),
CLK_LOOKUP("xo", cxo_clk_src.c, "pil_pronto"),
CLK_LOOKUP("measure", measure_clk.c, "debug"),
@@ -4773,12 +4775,12 @@
CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm1_ebit_clk.c, ""),
CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm1_ibit_clk.c, ""),
- CLK_LOOKUP("core_clk", mss_xo_q6_clk.c, ""),
- CLK_LOOKUP("bus_clk", mss_bus_q6_clk.c, ""),
+ CLK_LOOKUP("core_clk", mss_xo_q6_clk.c, "pil-q6v5-mss"),
+ CLK_LOOKUP("bus_clk", mss_bus_q6_clk.c, "pil-q6v5-mss"),
+ CLK_LOOKUP("bus_clk", gcc_mss_cfg_ahb_clk.c, ""),
+ CLK_LOOKUP("mem_clk", gcc_boot_rom_ahb_clk.c, "pil-q6v5-mss"),
CLK_LOOKUP("core_clk", q6ss_xo_clk.c, "pil-q6v5-lpass"),
CLK_LOOKUP("bus_clk", q6ss_ahb_lfabif_clk.c, "pil-q6v5-lpass"),
- CLK_LOOKUP("mem_clk", gcc_boot_rom_ahb_clk.c, ""),
- CLK_LOOKUP("bus_clk", gcc_mss_cfg_ahb_clk.c, ""),
CLK_LOOKUP("core_clk", gcc_prng_ahb_clk.c, "msm_rng"),
/* TODO: Remove dummy clocks as soon as they become unnecessary */
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 075c124..42c4c11 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -618,6 +618,11 @@
.id = 0x4006,
};
+struct platform_device apq_cpudai_slimbus_3_tx = {
+ .name = "msm-dai-q6",
+ .id = 0x4007,
+};
+
static struct resource resources_ssbi_pmic1[] = {
{
.start = MSM_PMIC1_SSBI_CMD_PHYS,
@@ -1663,6 +1668,21 @@
.bus_port0 = MSM_BUS_MASTER_JPEG_ENC,
};
+static struct fs_driver_data mdp_fs_data = {
+ .clks = (struct fs_clk_data[]){
+ { .name = "core_clk" },
+ { .name = "iface_clk" },
+ { .name = "bus_clk" },
+ { .name = "vsync_clk" },
+ { .name = "lut_clk" },
+ { .name = "tv_src_clk" },
+ { .name = "tv_clk" },
+ { 0 }
+ },
+ .bus_port0 = MSM_BUS_MASTER_MDP_PORT0,
+ .bus_port1 = MSM_BUS_MASTER_MDP_PORT1,
+};
+
static struct fs_driver_data rot_fs_data = {
.clks = (struct fs_clk_data[]){
{ .name = "core_clk" },
@@ -1715,6 +1735,7 @@
};
struct platform_device *apq8064_footswitch[] __initdata = {
+ FS_8X60(FS_MDP, "vdd", "mdp.0", &mdp_fs_data),
FS_8X60(FS_ROT, "vdd", "msm_rotator.0", &rot_fs_data),
FS_8X60(FS_IJPEG, "vdd", "msm_gemini.0", &ijpeg_fs_data),
FS_8X60(FS_VFE, "fs_vfe", NULL, &vfe_fs_data),
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index f180aa5..4fd262f 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -269,6 +269,7 @@
extern struct platform_device apq_cpudai_slimbus_1_tx;
extern struct platform_device apq_cpudai_slimbus_2_tx;
extern struct platform_device apq_cpudai_slimbus_3_rx;
+extern struct platform_device apq_cpudai_slimbus_3_tx;
extern struct platform_device apq_cpudai_slim_4_rx;
extern struct platform_device apq_cpudai_slim_4_tx;
diff --git a/arch/arm/mach-msm/pil-mba.c b/arch/arm/mach-msm/pil-mba.c
new file mode 100644
index 0000000..7405ab9
--- /dev/null
+++ b/arch/arm/mach-msm/pil-mba.c
@@ -0,0 +1,242 @@
+/*
+ * 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/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+#include <linux/elf.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/of.h>
+
+#include "peripheral-loader.h"
+
+#define RMB_MBA_COMMAND 0x08
+#define RMB_MBA_STATUS 0x0C
+#define RMB_PMI_META_DATA 0x10
+#define RMB_PMI_CODE_START 0x14
+#define RMB_PMI_CODE_LENGTH 0x18
+
+#define CMD_META_DATA_READY 0x1
+#define CMD_LOAD_READY 0x2
+
+#define STATUS_META_DATA_AUTH_SUCCESS 0x3
+#define STATUS_AUTH_COMPLETE 0x4
+#define STATUS_ERROR_MASK BIT(31)
+
+#define AUTH_TIMEOUT_US 10000000
+#define PROXY_TIMEOUT_MS 10000
+#define POLL_INTERVAL_US 50
+
+struct mba_data {
+ void __iomem *reg_base;
+ void __iomem *metadata_base;
+ unsigned long metadata_phys;
+ struct pil_device *pil;
+ struct clk *xo;
+ u32 img_length;
+};
+
+static int pil_mba_make_proxy_votes(struct pil_desc *pil)
+{
+ int ret;
+ struct mba_data *drv = dev_get_drvdata(pil->dev);
+
+ ret = clk_prepare_enable(drv->xo);
+ if (ret) {
+ dev_err(pil->dev, "Failed to enable XO\n");
+ return ret;
+ }
+ return 0;
+}
+
+static void pil_mba_remove_proxy_votes(struct pil_desc *pil)
+{
+ struct mba_data *drv = dev_get_drvdata(pil->dev);
+ clk_disable_unprepare(drv->xo);
+}
+
+static int pil_mba_init_image(struct pil_desc *pil,
+ const u8 *metadata, size_t size)
+{
+ struct mba_data *drv = dev_get_drvdata(pil->dev);
+ u32 status;
+ int ret;
+
+ /* Copy metadata to assigned shared buffer location */
+ memcpy(drv->metadata_base, metadata, size);
+
+ /* Initialize length counter to 0 */
+ writel_relaxed(0, drv->reg_base + RMB_PMI_CODE_LENGTH);
+ drv->img_length = 0;
+
+ /* Pass address of meta-data to the MBA and perform authentication */
+ writel_relaxed(drv->metadata_phys, drv->reg_base + RMB_PMI_META_DATA);
+ writel_relaxed(CMD_META_DATA_READY, drv->reg_base + RMB_MBA_COMMAND);
+ ret = readl_poll_timeout(drv->reg_base + RMB_MBA_STATUS, status,
+ status == STATUS_META_DATA_AUTH_SUCCESS,
+ POLL_INTERVAL_US, AUTH_TIMEOUT_US);
+ if (ret)
+ dev_err(pil->dev, "MBA authentication timed out\n");
+
+ return ret;
+}
+
+static int pil_mba_verify_blob(struct pil_desc *pil, u32 phy_addr,
+ size_t size)
+{
+ struct mba_data *drv = dev_get_drvdata(pil->dev);
+
+ /* Begin image authentication */
+ if (drv->img_length == 0) {
+ writel_relaxed(phy_addr, drv->reg_base + RMB_PMI_CODE_START);
+ writel_relaxed(CMD_LOAD_READY, drv->reg_base + RMB_MBA_COMMAND);
+ }
+ /* Increment length counter */
+ drv->img_length += size;
+ writel_relaxed(drv->img_length, drv->reg_base + RMB_PMI_CODE_LENGTH);
+
+ return readl_relaxed(drv->reg_base + RMB_MBA_STATUS)
+ & STATUS_ERROR_MASK;
+}
+
+static int pil_mba_auth(struct pil_desc *pil)
+{
+ struct mba_data *drv = dev_get_drvdata(pil->dev);
+ int ret;
+ u32 status;
+
+ /* Wait for all segments to be authenticated or an error to occur */
+ ret = readl_poll_timeout(drv->reg_base + RMB_MBA_STATUS, status,
+ status == STATUS_AUTH_COMPLETE ||
+ status & STATUS_ERROR_MASK,
+ 50, AUTH_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ if (status & STATUS_ERROR_MASK)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int pil_mba_shutdown(struct pil_desc *pil)
+{
+ return 0;
+}
+
+static struct pil_reset_ops pil_mba_ops = {
+ .init_image = pil_mba_init_image,
+ .proxy_vote = pil_mba_make_proxy_votes,
+ .proxy_unvote = pil_mba_remove_proxy_votes,
+ .verify_blob = pil_mba_verify_blob,
+ .auth_and_reset = pil_mba_auth,
+ .shutdown = pil_mba_shutdown,
+};
+
+static int __devinit pil_mba_driver_probe(struct platform_device *pdev)
+{
+ struct mba_data *drv;
+ struct resource *res;
+ struct pil_desc *desc;
+ int ret;
+
+ drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+ if (!drv)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, drv);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+ drv->reg_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!drv->reg_base)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (res) {
+ drv->metadata_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!drv->metadata_base)
+ return -ENOMEM;
+ drv->metadata_phys = res->start;
+ }
+
+ desc = devm_kzalloc(&pdev->dev, sizeof(*desc), GFP_KERNEL);
+ if (!drv)
+ return -ENOMEM;
+
+ ret = of_property_read_string(pdev->dev.of_node, "qcom,firmware-name",
+ &desc->name);
+ if (ret)
+ return ret;
+
+ of_property_read_string(pdev->dev.of_node, "qcom,depends-on",
+ &desc->depends_on);
+
+ drv->xo = devm_clk_get(&pdev->dev, "xo");
+ if (IS_ERR(drv->xo))
+ return PTR_ERR(drv->xo);
+
+ desc->dev = &pdev->dev;
+ desc->ops = &pil_mba_ops;
+ desc->owner = THIS_MODULE;
+ desc->proxy_timeout = PROXY_TIMEOUT_MS;
+
+ drv->pil = msm_pil_register(desc);
+ if (IS_ERR(drv->pil))
+ return PTR_ERR(drv->pil);
+
+ return 0;
+}
+
+static int __devexit pil_mba_driver_exit(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct of_device_id mba_match_table[] = {
+ { .compatible = "qcom,pil-mba" },
+ {}
+};
+
+struct platform_driver pil_mba_driver = {
+ .probe = pil_mba_driver_probe,
+ .remove = __devexit_p(pil_mba_driver_exit),
+ .driver = {
+ .name = "pil-mba",
+ .of_match_table = mba_match_table,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init pil_mba_init(void)
+{
+ return platform_driver_register(&pil_mba_driver);
+}
+module_init(pil_mba_init);
+
+static void __exit pil_mba_exit(void)
+{
+ platform_driver_unregister(&pil_mba_driver);
+}
+module_exit(pil_mba_exit);
+
+MODULE_DESCRIPTION("Support for modem boot using the Modem Boot Authenticator");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
new file mode 100644
index 0000000..e279f99
--- /dev/null
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -0,0 +1,291 @@
+/*
+ * 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/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/ioport.h>
+#include <linux/elf.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/clk.h>
+
+#include "peripheral-loader.h"
+#include "pil-q6v5.h"
+
+/* Q6 Register Offsets */
+#define QDSP6SS_RST_EVB 0x010
+
+/* AXI Halting Registers */
+#define MSS_Q6_HALT_BASE 0x180
+#define MSS_MODEM_HALT_BASE 0x200
+#define MSS_NC_HALT_BASE 0x280
+
+/* RMB Status Register Values */
+#define STATUS_PBL_SUCCESS 0x1
+#define STATUS_XPU_UNLOCKED 0x1
+#define STATUS_XPU_UNLOCKED_SCRIBBLED 0x2
+
+/* PBL/MBA interface registers */
+#define RMB_MBA_IMAGE 0x00
+#define RMB_PBL_STATUS 0x04
+#define RMB_MBA_STATUS 0x0C
+
+#define PBL_MBA_WAIT_TIMEOUT_US 100000
+#define PROXY_TIMEOUT_MS 10000
+#define POLL_INTERVAL_US 50
+
+static int pil_mss_power_up(struct device *dev)
+{
+ int ret;
+ struct q6v5_data *drv = dev_get_drvdata(dev);
+
+ ret = regulator_enable(drv->vreg);
+ if (ret)
+ dev_err(dev, "Failed to enable regulator.\n");
+
+ return ret;
+}
+
+static int pil_mss_power_down(struct device *dev)
+{
+ struct q6v5_data *drv = dev_get_drvdata(dev);
+
+ return regulator_disable(drv->vreg);
+}
+
+static int wait_for_mba_ready(struct device *dev)
+{
+ struct q6v5_data *drv = dev_get_drvdata(dev);
+ int ret;
+ u32 status;
+
+ /* Wait for PBL completion. */
+ ret = readl_poll_timeout(drv->rmb_base + RMB_PBL_STATUS, status,
+ status != 0, POLL_INTERVAL_US, PBL_MBA_WAIT_TIMEOUT_US);
+ if (ret) {
+ dev_err(dev, "PBL boot timed out\n");
+ return ret;
+ }
+ if (status != STATUS_PBL_SUCCESS) {
+ dev_err(dev, "PBL returned unexpected status %d\n", status);
+ return -EINVAL;
+ }
+
+ /* Wait for MBA completion. */
+ ret = readl_poll_timeout(drv->rmb_base + RMB_MBA_STATUS, status,
+ status != 0, POLL_INTERVAL_US, PBL_MBA_WAIT_TIMEOUT_US);
+ if (ret) {
+ dev_err(dev, "MBA boot timed out\n");
+ return ret;
+ }
+ if (status != STATUS_XPU_UNLOCKED &&
+ status != STATUS_XPU_UNLOCKED_SCRIBBLED) {
+ dev_err(dev, "MBA returned unexpected status %d\n", status);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int pil_mss_shutdown(struct pil_desc *pil)
+{
+ struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+
+ pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_Q6_HALT_BASE);
+ pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_MODEM_HALT_BASE);
+ pil_q6v5_halt_axi_port(pil, drv->axi_halt_base + MSS_NC_HALT_BASE);
+
+ /*
+ * If the shutdown function is called before the reset function, clocks
+ * and power will not be enabled yet. Enable them here so that register
+ * writes performed during the shutdown succeed.
+ */
+ if (drv->is_booted == false) {
+ pil_mss_power_up(pil->dev);
+ pil_q6v5_enable_clks(pil);
+ }
+ pil_q6v5_shutdown(pil);
+
+ pil_q6v5_disable_clks(pil);
+ pil_mss_power_down(pil->dev);
+
+ writel_relaxed(1, drv->restart_reg);
+
+ drv->is_booted = false;
+
+ return 0;
+}
+
+static int pil_mss_reset(struct pil_desc *pil)
+{
+ struct q6v5_data *drv = dev_get_drvdata(pil->dev);
+ int ret;
+
+ writel_relaxed(0, drv->restart_reg);
+ mb();
+
+ /*
+ * Bring subsystem out of reset and enable required
+ * regulators and clocks.
+ */
+ ret = pil_mss_power_up(pil->dev);
+ if (ret)
+ goto err_power;
+
+ ret = pil_q6v5_enable_clks(pil);
+ if (ret)
+ goto err_clks;
+
+ /* Program Image Address */
+ if (drv->self_auth)
+ writel_relaxed(drv->start_addr, drv->rmb_base + RMB_MBA_IMAGE);
+ else
+ writel_relaxed((drv->start_addr >> 4) & 0x0FFFFFF0,
+ drv->reg_base + QDSP6SS_RST_EVB);
+
+ ret = pil_q6v5_reset(pil);
+ if (ret)
+ goto err_q6v5_reset;
+
+ /* Wait for MBA to start. Check for PBL and MBA errors while waiting. */
+ if (drv->self_auth) {
+ ret = wait_for_mba_ready(pil->dev);
+ if (ret)
+ goto err_auth;
+ }
+
+ drv->is_booted = true;
+
+ return 0;
+
+err_auth:
+ pil_q6v5_shutdown(pil);
+err_q6v5_reset:
+ pil_q6v5_disable_clks(pil);
+err_clks:
+ pil_mss_power_down(pil->dev);
+err_power:
+ return ret;
+}
+
+static struct pil_reset_ops pil_mss_ops = {
+ .init_image = pil_q6v5_init_image,
+ .proxy_vote = pil_q6v5_make_proxy_votes,
+ .proxy_unvote = pil_q6v5_remove_proxy_votes,
+ .auth_and_reset = pil_mss_reset,
+ .shutdown = pil_mss_shutdown,
+};
+
+static int __devinit pil_mss_driver_probe(struct platform_device *pdev)
+{
+ struct q6v5_data *drv;
+ struct pil_desc *desc;
+ struct resource *res;
+ int ret;
+
+ desc = pil_q6v5_init(pdev);
+ if (IS_ERR(desc))
+ return PTR_ERR(desc);
+ drv = platform_get_drvdata(pdev);
+ if (drv == NULL)
+ return -ENODEV;
+
+ desc->ops = &pil_mss_ops;
+ desc->owner = THIS_MODULE;
+ desc->proxy_timeout = PROXY_TIMEOUT_MS;
+
+ of_property_read_u32(pdev->dev.of_node, "qcom,pil-self-auth",
+ &drv->self_auth);
+ if (drv->self_auth) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ drv->rmb_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!drv->rmb_base)
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+ drv->restart_reg = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!drv->restart_reg)
+ return -ENOMEM;
+
+ drv->vreg = devm_regulator_get(&pdev->dev, "vdd_mss");
+ if (IS_ERR(drv->vreg))
+ return PTR_ERR(drv->vreg);
+
+ ret = regulator_set_voltage(drv->vreg, 1150000, 1150000);
+ if (ret)
+ dev_err(&pdev->dev, "Failed to set regulator's voltage.\n");
+
+ ret = regulator_set_optimum_mode(drv->vreg, 100000);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to set regulator's mode.\n");
+ return ret;
+ }
+
+ drv->mem_clk = devm_clk_get(&pdev->dev, "mem_clk");
+ if (IS_ERR(drv->mem_clk))
+ return PTR_ERR(drv->mem_clk);
+
+ drv->pil = msm_pil_register(desc);
+ if (IS_ERR(drv->pil))
+ return PTR_ERR(drv->pil);
+
+ return 0;
+}
+
+static int __devexit pil_mss_driver_exit(struct platform_device *pdev)
+{
+ struct q6v5_data *drv = platform_get_drvdata(pdev);
+ msm_pil_unregister(drv->pil);
+ return 0;
+}
+
+static struct of_device_id mss_match_table[] = {
+ { .compatible = "qcom,pil-q6v5-mss" },
+ {}
+};
+
+static struct platform_driver pil_mss_driver = {
+ .probe = pil_mss_driver_probe,
+ .remove = __devexit_p(pil_mss_driver_exit),
+ .driver = {
+ .name = "pil-q6v5-mss",
+ .of_match_table = mss_match_table,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init pil_mss_init(void)
+{
+ return platform_driver_register(&pil_mss_driver);
+}
+module_init(pil_mss_init);
+
+static void __exit pil_mss_exit(void)
+{
+ platform_driver_unregister(&pil_mss_driver);
+}
+module_exit(pil_mss_exit);
+
+MODULE_DESCRIPTION("Support for booting modem subsystems with QDSP6v5 Hexagon processors");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/pil-q6v5.c b/arch/arm/mach-msm/pil-q6v5.c
index 6a96990..a362a7e3 100644
--- a/arch/arm/mach-msm/pil-q6v5.c
+++ b/arch/arm/mach-msm/pil-q6v5.c
@@ -121,9 +121,16 @@
ret = clk_prepare_enable(drv->bus_clk);
if (ret)
goto err_bus_clk;
+ if (drv->mem_clk) {
+ ret = clk_prepare_enable(drv->mem_clk);
+ if (ret)
+ goto err_mem_clk;
+ }
return 0;
+err_mem_clk:
+ clk_disable_unprepare(drv->bus_clk);
err_bus_clk:
clk_disable_unprepare(drv->core_clk);
err_core_clk:
@@ -139,6 +146,7 @@
clk_disable_unprepare(drv->bus_clk);
clk_disable_unprepare(drv->core_clk);
+ clk_disable_unprepare(drv->mem_clk);
clk_reset(drv->core_clk, CLK_RESET_ASSERT);
}
EXPORT_SYMBOL(pil_q6v5_disable_clks);
diff --git a/arch/arm/mach-msm/pil-q6v5.h b/arch/arm/mach-msm/pil-q6v5.h
index a9a8d07..e0d7a20 100644
--- a/arch/arm/mach-msm/pil-q6v5.h
+++ b/arch/arm/mach-msm/pil-q6v5.h
@@ -24,8 +24,10 @@
struct clk *xo;
struct clk *bus_clk;
struct clk *core_clk;
+ struct clk *mem_clk;
void __iomem *axi_halt_base;
void __iomem *rmb_base;
+ void __iomem *restart_reg;
unsigned long start_addr;
struct regulator *vreg;
bool is_booted;
diff --git a/arch/arm/mach-msm/pm-boot.c b/arch/arm/mach-msm/pm-boot.c
index f6105af1..079ed9c 100644
--- a/arch/arm/mach-msm/pm-boot.c
+++ b/arch/arm/mach-msm/pm-boot.c
@@ -41,7 +41,7 @@
}
#ifdef CONFIG_MSM_SCM
-static int __init msm_pm_tz_boot_init(void)
+static int __devinit msm_pm_tz_boot_init(void)
{
int flag = 0;
if (num_possible_cpus() == 1)
@@ -72,7 +72,7 @@
unsigned long entry) {}
#endif
-static int __init msm_pm_boot_reset_vector_init(uint32_t *reset_vector)
+static int __devinit msm_pm_boot_reset_vector_init(uint32_t *reset_vector)
{
if (!reset_vector)
return -ENODEV;
@@ -110,7 +110,7 @@
}
#define BOOT_REMAP_ENABLE BIT(0)
-int __init msm_pm_boot_init(struct msm_pm_boot_platform_data *pdata)
+int __devinit msm_pm_boot_init(struct msm_pm_boot_platform_data *pdata)
{
int ret = 0;
unsigned long entry;
diff --git a/arch/arm/mach-msm/qdsp5/adsp.c b/arch/arm/mach-msm/qdsp5/adsp.c
index 6f5ccbf..b485058 100644
--- a/arch/arm/mach-msm/qdsp5/adsp.c
+++ b/arch/arm/mach-msm/qdsp5/adsp.c
@@ -865,7 +865,8 @@
unsigned msg_id;
unsigned msg_length;
#ifdef CONFIG_DEBUG_FS
- uint16_t *ptr;
+ uint16_t *ptr16;
+ uint32_t *ptr32;
int ii;
#endif /* CONFIG_DEBUG_FS */
void (*func)(void *, size_t);
@@ -909,12 +910,20 @@
return 0;
}
#ifdef CONFIG_DEBUG_FS
- if (rdump > 0) {
- ptr = read_event_addr;
+ if (rdump > 0 &&
+ (dsp_addr >= (void *)(MSM_AD5_BASE + QDSP_RAMC_OFFSET))) {
+ ptr32 = read_event_addr;
+ pr_info("D->A\n");
+ pr_info("m_id = %x id = %x\n", module->id, msg_id);
+ for (ii = 0; ii < msg_length/4; ii++)
+ pr_info("%x ", ptr32[ii]);
+ pr_info("\n");
+ } else if (rdump > 0) {
+ ptr16 = read_event_addr;
pr_info("D->A\n");
pr_info("m_id = %x id = %x\n", module->id, msg_id);
for (ii = 0; ii < msg_length/2; ii++)
- pr_info("%x ", ptr[ii]);
+ pr_info("%x ", ptr16[ii]);
pr_info("\n");
}
#endif /* CONFIG_DEBUG_FS */
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index 90948ea..266c8b4 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -28,6 +28,7 @@
#include "ramdump.h"
#define MODULE_NAME "wcnss_8960"
+#define MAX_BUF_SIZE 0x51
static void riva_smsm_cb_fn(struct work_struct *);
static DECLARE_WORK(riva_smsm_cb_work, riva_smsm_cb_fn);
@@ -52,12 +53,37 @@
static void smsm_state_cb_hdlr(void *data, uint32_t old_state,
uint32_t new_state)
{
+ char *smem_reset_reason;
+ char buffer[MAX_BUF_SIZE];
+ unsigned smem_reset_size;
+ unsigned size;
+
if (!(new_state & SMSM_RESET))
return;
riva_crash = true;
pr_err("%s: smsm state changed to smsm reset\n", MODULE_NAME);
+ smem_reset_reason = smem_get_entry(SMEM_SSR_REASON_WCNSS0,
+ &smem_reset_size);
+
+ if (!smem_reset_reason || !smem_reset_size) {
+ pr_err("%s: wcnss subsystem failure reason: %s\n", __func__,
+ "(unknown, smem_get_entry failed)");
+ } else if (!smem_reset_reason[0]) {
+ pr_err("%s: wcnss subsystem failure reason: %s\n", __func__,
+ "(unknown, init string found)");
+ } else {
+ size = smem_reset_size < MAX_BUF_SIZE ? smem_reset_size :
+ (MAX_BUF_SIZE - 1);
+ memcpy(buffer, smem_reset_reason, size);
+ buffer[size] = '\0';
+ pr_err("%s: wcnss subsystem failure reason: %s\n", __func__,
+ buffer);
+ memset(smem_reset_reason, 0, smem_reset_size);
+ wmb();
+ }
+
if (ss_restart_inprogress) {
pr_err("%s: Ignoring smsm reset req, restart in progress\n",
MODULE_NAME);
diff --git a/drivers/char/diag/Kconfig b/drivers/char/diag/Kconfig
index 53df29b..8f8707f 100644
--- a/drivers/char/diag/Kconfig
+++ b/drivers/char/diag/Kconfig
@@ -32,10 +32,10 @@
menu "HSIC support for DIAG"
-config DIAG_HSIC_PIPE
+config DIAG_BRIDGE_CODE
depends on USB_QCOM_DIAG_BRIDGE
default y
- bool "Enable 9K DIAG traffic over HSIC"
+ bool "Enable QSC/9K DIAG traffic over SMUX/HSIC"
help
- HSIC Transport Layer for DIAG Router
+ SMUX/HSIC Transport Layer for DIAG Router
endmenu
diff --git a/drivers/char/diag/Makefile b/drivers/char/diag/Makefile
index 3181d29..ea75ffd 100644
--- a/drivers/char/diag/Makefile
+++ b/drivers/char/diag/Makefile
@@ -1,4 +1,5 @@
obj-$(CONFIG_DIAG_CHAR) := diagchar.o
obj-$(CONFIG_DIAG_SDIO_PIPE) += diagfwd_sdio.o
-obj-$(CONFIG_DIAG_HSIC_PIPE) += diagfwd_hsic.o
+obj-$(CONFIG_DIAG_BRIDGE_CODE) += diagfwd_hsic.o
+obj-$(CONFIG_DIAG_BRIDGE_CODE) += diagfwd_smux.o
diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagmem.o diagfwd_cntl.o diag_dci.o
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 49d687d..7e7b514 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -41,6 +41,7 @@
#define SDIO_DATA 4
#define WCNSS_DATA 5
#define HSIC_DATA 6
+#define SMUX_DATA 7
#define MODEM_PROC 0
#define APPS_PROC 1
#define QDSP_PROC 2
@@ -254,24 +255,30 @@
struct diag_request *usb_read_mdm_ptr;
struct diag_request *write_ptr_mdm;
#endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+ /* SGLTE variables */
+ int lcid;
+ unsigned char *buf_in_smux;
+ int in_busy_smux;
+ int diag_smux_enabled;
+ /* HSIC variables */
unsigned char *buf_in_hsic;
- unsigned char *usb_buf_mdm_out;
- int hsic_initialized;
int hsic_ch;
int hsic_device_enabled;
int hsic_device_opened;
int hsic_suspend;
- int read_len_mdm;
int in_busy_hsic_read_on_device;
int in_busy_hsic_write_on_device;
int in_busy_hsic_write;
int in_busy_hsic_read;
- int usb_mdm_connected;
- struct usb_diag_ch *mdm_ch;
- struct workqueue_struct *diag_hsic_wq;
- struct work_struct diag_read_mdm_work;
struct work_struct diag_read_hsic_work;
+ /* USB MDM channel variables */
+ int usb_mdm_connected;
+ int read_len_mdm;
+ unsigned char *usb_buf_mdm_out;
+ struct usb_diag_ch *mdm_ch;
+ struct workqueue_struct *diag_bridge_wq;
+ struct work_struct diag_read_mdm_work;
struct work_struct diag_disconnect_work;
struct work_struct diag_usb_read_complete_work;
struct diag_request *usb_read_mdm_ptr;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 7b7549a..8d6a607 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -32,8 +32,9 @@
#ifdef CONFIG_DIAG_SDIO_PIPE
#include "diagfwd_sdio.h"
#endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
#include "diagfwd_hsic.h"
+#include "diagfwd_smux.h"
#endif
#include <linux/timer.h>
@@ -234,9 +235,9 @@
if (driver->logging_process_id == current->tgid) {
driver->logging_mode = USB_MODE;
diagfwd_connect();
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
diagfwd_cancel_hsic();
- diagfwd_connect_hsic(0);
+ diagfwd_connect_bridge(0);
#endif
}
#endif /* DIAG over USB */
@@ -481,8 +482,8 @@
#ifdef CONFIG_DIAG_SDIO_PIPE
driver->in_busy_sdio = 1;
#endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
- diagfwd_disconnect_hsic(0);
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+ diagfwd_disconnect_bridge(0);
#endif
} else if (temp == NO_LOGGING_MODE && driver->logging_mode
== MEMORY_DEVICE_MODE) {
@@ -509,22 +510,22 @@
queue_work(driver->diag_sdio_wq,
&(driver->diag_read_sdio_work));
#endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
- diagfwd_connect_hsic(0);
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+ diagfwd_connect_bridge(0);
#endif
}
#ifdef CONFIG_DIAG_OVER_USB
else if (temp == USB_MODE && driver->logging_mode
== NO_LOGGING_MODE) {
diagfwd_disconnect();
-#ifdef CONFIG_DIAG_HSIC_PIPE
- diagfwd_disconnect_hsic(0);
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+ diagfwd_disconnect_bridge(0);
#endif
} else if (temp == NO_LOGGING_MODE && driver->logging_mode
== USB_MODE) {
diagfwd_connect();
-#ifdef CONFIG_DIAG_HSIC_PIPE
- diagfwd_connect_hsic(0);
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+ diagfwd_connect_bridge(0);
#endif
} else if (temp == USB_MODE && driver->logging_mode
== MEMORY_DEVICE_MODE) {
@@ -552,16 +553,16 @@
queue_work(driver->diag_sdio_wq,
&(driver->diag_read_sdio_work));
#endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
diagfwd_cancel_hsic();
- diagfwd_connect_hsic(0);
+ diagfwd_connect_bridge(0);
#endif
} else if (temp == MEMORY_DEVICE_MODE &&
driver->logging_mode == USB_MODE) {
diagfwd_connect();
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
diagfwd_cancel_hsic();
- diagfwd_connect_hsic(0);
+ diagfwd_connect_bridge(0);
#endif
}
#endif /* DIAG over USB */
@@ -720,7 +721,7 @@
driver->in_busy_sdio = 0;
}
#endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
pr_debug("diag: Copy data to user space %d\n",
driver->in_busy_hsic_write_on_device);
if (driver->in_busy_hsic_write_on_device == 1) {
@@ -898,7 +899,7 @@
}
}
#endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
/* send masks to 9k too */
if (driver->hsic_ch && (payload_size > 0)) {
/* wait sending mask updates if HSIC ch not ready */
@@ -1199,16 +1200,16 @@
inline void diag_sdio_fn(int type) {}
#endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
-void diag_hsic_fn(int type)
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+void diag_bridge_fn(int type)
{
if (type == INIT)
- diagfwd_hsic_init();
+ diagfwd_bridge_init();
else if (type == EXIT)
- diagfwd_hsic_exit();
+ diagfwd_bridge_exit();
}
#else
-inline void diag_hsic_fn(int type) {}
+inline void diag_bridge_fn(int type) {}
#endif
static int __init diagchar_init(void)
@@ -1255,7 +1256,7 @@
diagfwd_cntl_init();
driver->dci_state = diag_dci_init();
diag_sdio_fn(INIT);
- diag_hsic_fn(INIT);
+ diag_bridge_fn(INIT);
pr_debug("diagchar initializing ..\n");
driver->num = 1;
driver->name = ((void *)driver) + sizeof(struct diagchar_dev);
@@ -1289,7 +1290,7 @@
diagfwd_exit();
diagfwd_cntl_exit();
diag_sdio_fn(EXIT);
- diag_hsic_fn(EXIT);
+ diag_bridge_fn(EXIT);
return -1;
}
@@ -1302,7 +1303,7 @@
diagfwd_exit();
diagfwd_cntl_exit();
diag_sdio_fn(EXIT);
- diag_hsic_fn(EXIT);
+ diag_bridge_fn(EXIT);
diag_debugfs_cleanup();
diagchar_cleanup();
printk(KERN_INFO "done diagchar exit\n");
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 4ac2643..a920f56 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -300,12 +300,12 @@
&(driver->diag_read_sdio_work));
}
#endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
else if (proc_num == HSIC_DATA) {
driver->in_busy_hsic_read = 0;
driver->in_busy_hsic_write_on_device = 0;
if (driver->hsic_ch)
- queue_work(driver->diag_hsic_wq,
+ queue_work(driver->diag_bridge_wq,
&(driver->diag_read_hsic_work));
}
#endif
@@ -352,7 +352,7 @@
"while USB write\n");
}
#endif
-#ifdef CONFIG_DIAG_HSIC_PIPE
+#ifdef CONFIG_DIAG_BRIDGE_CODE
else if (proc_num == HSIC_DATA) {
if (driver->hsic_device_enabled) {
write_ptr->buf = buf;
@@ -360,6 +360,10 @@
} else
pr_err("diag: Incorrect hsic data "
"while USB write\n");
+ } else if (proc_num == SMUX_DATA) {
+ write_ptr->buf = buf;
+ pr_debug("diag: writing SMUX data\n");
+ err = usb_diag_write(driver->mdm_ch, write_ptr);
}
#endif
APPEND_DEBUG('d');
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index a3c6f26..d54d3dc 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -19,6 +19,7 @@
#include <linux/workqueue.h>
#include <linux/pm_runtime.h>
#include <linux/platform_device.h>
+#include <linux/smux.h>
#include <asm/current.h>
#ifdef CONFIG_DIAG_OVER_USB
#include <mach/usbdiag.h>
@@ -28,6 +29,7 @@
#include "diagchar.h"
#include "diagfwd.h"
#include "diagfwd_hsic.h"
+#include "diagfwd_smux.h"
static void diag_read_hsic_work_fn(struct work_struct *work)
{
@@ -71,7 +73,8 @@
* the next read
*/
if (!driver->in_busy_hsic_read)
- queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+ queue_work(driver->diag_bridge_wq,
+ &driver->diag_read_hsic_work);
}
static void diag_hsic_read_complete_callback(void *ctxt, char *buf,
@@ -114,7 +117,8 @@
if (!driver->in_busy_hsic_write_on_device && ((driver->logging_mode
== MEMORY_DEVICE_MODE) || (driver->usb_mdm_connected &&
!driver->hsic_suspend)))
- queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+ queue_work(driver->diag_bridge_wq,
+ &driver->diag_read_hsic_work);
}
static void diag_hsic_write_complete_callback(void *ctxt, char *buf,
@@ -132,7 +136,7 @@
pr_err("DIAG in %s: actual_size: %d\n", __func__, actual_size);
if (driver->usb_mdm_connected)
- queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+ queue_work(driver->diag_bridge_wq, &driver->diag_read_mdm_work);
}
static int diag_hsic_suspend(void *ctxt)
@@ -157,7 +161,8 @@
if (!driver->in_busy_hsic_write_on_device && (driver->logging_mode
== MEMORY_DEVICE_MODE || driver->usb_mdm_connected))
- queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+ queue_work(driver->diag_bridge_wq,
+ &driver->diag_read_hsic_work);
}
static struct diag_bridge_ops hsic_diag_bridge_ops = {
@@ -209,42 +214,48 @@
return 0;
}
-/* diagfwd_connect_hsic is called when the USB mdm channel is connected */
-int diagfwd_connect_hsic(int process_cable)
+/* diagfwd_connect_bridge is called when the USB mdm channel is connected */
+int diagfwd_connect_bridge(int process_cable)
{
int err;
- pr_debug("DIAG in %s\n", __func__);
+ pr_debug("diag: in %s\n", __func__);
/* If the usb cable is being connected */
if (process_cable) {
err = usb_diag_alloc_req(driver->mdm_ch, N_MDM_WRITE,
N_MDM_READ);
if (err)
- pr_err("DIAG: unable to alloc USB req on mdm"
+ pr_err("diag: unable to alloc USB req on mdm"
" ch err:%d\n", err);
driver->usb_mdm_connected = 1;
}
- driver->in_busy_hsic_write_on_device = 0;
- driver->in_busy_hsic_read_on_device = 0;
- driver->in_busy_hsic_write = 0;
- driver->in_busy_hsic_read = 0;
+ if (driver->hsic_device_enabled) {
+ driver->in_busy_hsic_write_on_device = 0;
+ driver->in_busy_hsic_read_on_device = 0;
+ driver->in_busy_hsic_write = 0;
+ driver->in_busy_hsic_read = 0;
+ } else if (driver->diag_smux_enabled) {
+ driver->in_busy_smux = 0;
+ diagfwd_connect_smux();
+ return 0;
+ }
/* If the hsic (diag_bridge) platform device is not open */
if (driver->hsic_device_enabled) {
if (!driver->hsic_device_opened) {
err = diag_bridge_open(&hsic_diag_bridge_ops);
if (err) {
- pr_err("DIAG: HSIC channel open error: %d\n",
+ pr_err("diag: HSIC channel open error: %d\n",
err);
} else {
- pr_debug("DIAG: opened HSIC channel\n");
+ pr_debug("diag: opened HSIC channel\n");
driver->hsic_device_opened = 1;
}
} else {
- pr_debug("DIAG: HSIC channel already open\n");
+ pr_debug("diag: HSIC channel already open\n");
}
/*
@@ -256,24 +267,25 @@
/* Poll USB mdm channel to check for data */
if (driver->logging_mode == USB_MODE)
- queue_work(driver->diag_hsic_wq,
+ queue_work(driver->diag_bridge_wq,
&driver->diag_read_mdm_work);
/* Poll HSIC channel to check for data */
- queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+ queue_work(driver->diag_bridge_wq,
+ &driver->diag_read_hsic_work);
} else {
/* The hsic device driver has not yet been enabled */
- pr_info("DIAG: HSIC channel not yet enabled\n");
+ pr_info("diag: HSIC channel not yet enabled\n");
}
return 0;
}
/*
- * diagfwd_disconnect_hsic is called when the USB mdm channel
+ * diagfwd_disconnect_bridge is called when the USB mdm channel
* is disconnected
*/
-int diagfwd_disconnect_hsic(int process_cable)
+int diagfwd_disconnect_bridge(int process_cable)
{
pr_debug("DIAG in %s\n", __func__);
@@ -284,12 +296,19 @@
}
if (driver->logging_mode != MEMORY_DEVICE_MODE) {
- driver->in_busy_hsic_write_on_device = 1;
- driver->in_busy_hsic_read_on_device = 1;
- driver->in_busy_hsic_write = 1;
- driver->in_busy_hsic_read = 1;
- /* Turn off communication over usb mdm and hsic */
- return diag_hsic_close();
+ if (driver->hsic_device_enabled) {
+ driver->in_busy_hsic_write_on_device = 1;
+ driver->in_busy_hsic_read_on_device = 1;
+ driver->in_busy_hsic_write = 1;
+ driver->in_busy_hsic_read = 1;
+ /* Turn off communication over usb mdm and hsic */
+ return diag_hsic_close();
+ } else if (driver->diag_smux_enabled) {
+ driver->in_busy_smux = 1;
+ driver->lcid = LCID_INVALID;
+ /* Turn off communication over usb mdm and smux */
+ msm_smux_close(LCID_VALID);
+ }
}
return 0;
}
@@ -313,18 +332,23 @@
APPEND_DEBUG('q');
/* Read data from the hsic */
- queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+ queue_work(driver->diag_bridge_wq, &driver->diag_read_hsic_work);
return 0;
}
/* Called after the asychronous usb_diag_read() on mdm channel is complete */
-static int diagfwd_read_complete_hsic(struct diag_request *diag_read_ptr)
+static int diagfwd_read_complete_bridge(struct diag_request *diag_read_ptr)
{
/* The read of the usb driver on the mdm (not hsic) has completed */
driver->in_busy_hsic_read_on_device = 0;
driver->read_len_mdm = diag_read_ptr->actual;
+ if (driver->diag_smux_enabled) {
+ diagfwd_read_complete_smux();
+ return 0;
+ }
+ /* If SMUX not enabled, check for HSIC */
if (!driver->hsic_ch) {
pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
return 0;
@@ -366,30 +390,34 @@
* hsic channel
*/
if (!driver->in_busy_hsic_write)
- queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+ queue_work(driver->diag_bridge_wq, &driver->diag_read_mdm_work);
return 0;
}
-static void diagfwd_hsic_notifier(void *priv, unsigned event,
+static void diagfwd_bridge_notifier(void *priv, unsigned event,
struct diag_request *d_req)
{
switch (event) {
case USB_DIAG_CONNECT:
- diagfwd_connect_hsic(1);
+ diagfwd_connect_bridge(1);
break;
case USB_DIAG_DISCONNECT:
- queue_work(driver->diag_hsic_wq, &driver->diag_disconnect_work);
+ queue_work(driver->diag_bridge_wq,
+ &driver->diag_disconnect_work);
break;
case USB_DIAG_READ_DONE:
- queue_work(driver->diag_hsic_wq,
+ queue_work(driver->diag_bridge_wq,
&driver->diag_usb_read_complete_work);
break;
case USB_DIAG_WRITE_DONE:
- diagfwd_write_complete_hsic();
+ if (driver->hsic_device_enabled)
+ diagfwd_write_complete_hsic();
+ else if (driver->diag_smux_enabled)
+ diagfwd_write_complete_smux();
break;
default:
- pr_err("DIAG in %s: Unknown event from USB diag:%u\n",
+ pr_err("diag: in %s: Unknown event from USB diag:%u\n",
__func__, event);
break;
}
@@ -397,16 +425,33 @@
static void diag_usb_read_complete_fn(struct work_struct *w)
{
- diagfwd_read_complete_hsic(driver->usb_read_mdm_ptr);
+ diagfwd_read_complete_bridge(driver->usb_read_mdm_ptr);
}
static void diag_disconnect_work_fn(struct work_struct *w)
{
- diagfwd_disconnect_hsic(1);
+ diagfwd_disconnect_bridge(1);
}
static void diag_read_mdm_work_fn(struct work_struct *work)
{
+ int ret;
+ if (driver->diag_smux_enabled) {
+ if (driver->lcid && driver->usb_buf_mdm_out &&
+ (driver->read_len_mdm > 0)) {
+ ret = msm_smux_write(driver->lcid, NULL,
+ driver->usb_buf_mdm_out, driver->read_len_mdm);
+ if (ret)
+ pr_err("diag: writing to SMUX ch, r = %d,"
+ "lcid = %d\n", ret, driver->lcid);
+ }
+ driver->usb_read_mdm_ptr->buf = driver->usb_buf_mdm_out;
+ driver->usb_read_mdm_ptr->length = USB_MAX_OUT_BUF;
+ usb_diag_read(driver->mdm_ch, driver->usb_read_mdm_ptr);
+ return;
+ }
+
+ /* if SMUX not enabled, check for HSIC */
if (!driver->hsic_ch) {
pr_err("DIAG in %s: driver->hsic_ch == 0\n", __func__);
return;
@@ -434,7 +479,8 @@
* queue up the reading of data from the mdm channel
*/
if (!driver->in_busy_hsic_read_on_device)
- queue_work(driver->diag_hsic_wq, &driver->diag_read_mdm_work);
+ queue_work(driver->diag_bridge_wq,
+ &driver->diag_read_mdm_work);
}
static int diag_hsic_probe(struct platform_device *pdev)
@@ -442,31 +488,10 @@
int err = 0;
pr_debug("diag: in %s\n", __func__);
if (!driver->hsic_device_enabled) {
- driver->read_len_mdm = 0;
if (driver->buf_in_hsic == NULL)
driver->buf_in_hsic = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
- if (driver->buf_in_hsic == NULL)
- goto err;
- if (driver->usb_buf_mdm_out == NULL)
- driver->usb_buf_mdm_out = kzalloc(USB_MAX_OUT_BUF,
- GFP_KERNEL);
- if (driver->usb_buf_mdm_out == NULL)
- goto err;
- if (driver->write_ptr_mdm == NULL)
- driver->write_ptr_mdm = kzalloc(
- sizeof(struct diag_request), GFP_KERNEL);
- if (driver->write_ptr_mdm == NULL)
- goto err;
- if (driver->usb_read_mdm_ptr == NULL)
- driver->usb_read_mdm_ptr = kzalloc(
- sizeof(struct diag_request), GFP_KERNEL);
- if (driver->usb_read_mdm_ptr == NULL)
- goto err;
-#ifdef CONFIG_DIAG_OVER_USB
- INIT_WORK(&(driver->diag_read_mdm_work), diag_read_mdm_work_fn);
-#endif
INIT_WORK(&(driver->diag_read_hsic_work),
- diag_read_hsic_work_fn);
+ diag_read_hsic_work_fn);
driver->hsic_device_enabled = 1;
}
@@ -495,25 +520,16 @@
if (driver->usb_mdm_connected) {
/* Poll USB mdm channel to check for data */
- queue_work(driver->diag_hsic_wq,
+ queue_work(driver->diag_bridge_wq,
&driver->diag_read_mdm_work);
}
/* Poll HSIC channel to check for data */
- queue_work(driver->diag_hsic_wq, &driver->diag_read_hsic_work);
+ queue_work(driver->diag_bridge_wq,
+ &driver->diag_read_hsic_work);
}
return err;
-err:
- pr_err("DIAG could not initialize buf for HSIC\n");
- kfree(driver->buf_in_hsic);
- kfree(driver->usb_buf_mdm_out);
- kfree(driver->write_ptr_mdm);
- kfree(driver->usb_read_mdm_ptr);
- if (driver->diag_hsic_wq)
- destroy_workqueue(driver->diag_hsic_wq);
-
- return -ENOMEM;
}
static int diag_hsic_remove(struct platform_device *pdev)
@@ -550,55 +566,93 @@
},
};
-void diagfwd_hsic_init(void)
+void diagfwd_bridge_init(void)
{
int ret;
- pr_debug("DIAG in %s\n", __func__);
+ pr_debug("diag: in %s\n", __func__);
+ driver->diag_bridge_wq = create_singlethread_workqueue(
+ "diag_bridge_wq");
+ driver->read_len_mdm = 0;
+ if (driver->usb_buf_mdm_out == NULL)
+ driver->usb_buf_mdm_out = kzalloc(USB_MAX_OUT_BUF,
+ GFP_KERNEL);
+ if (driver->usb_buf_mdm_out == NULL)
+ goto err;
+ if (driver->write_ptr_mdm == NULL)
+ driver->write_ptr_mdm = kzalloc(
+ sizeof(struct diag_request), GFP_KERNEL);
+ if (driver->write_ptr_mdm == NULL)
+ goto err;
+ if (driver->usb_read_mdm_ptr == NULL)
+ driver->usb_read_mdm_ptr = kzalloc(
+ sizeof(struct diag_request), GFP_KERNEL);
+ if (driver->usb_read_mdm_ptr == NULL)
+ goto err;
- driver->diag_hsic_wq = create_singlethread_workqueue("diag_hsic_wq");
+#ifdef CONFIG_DIAG_OVER_USB
+ INIT_WORK(&(driver->diag_read_mdm_work), diag_read_mdm_work_fn);
+#endif
INIT_WORK(&(driver->diag_disconnect_work), diag_disconnect_work_fn);
INIT_WORK(&(driver->diag_usb_read_complete_work),
diag_usb_read_complete_fn);
-
#ifdef CONFIG_DIAG_OVER_USB
- driver->mdm_ch = usb_diag_open(DIAG_MDM, driver, diagfwd_hsic_notifier);
+ driver->mdm_ch = usb_diag_open(DIAG_MDM, driver,
+ diagfwd_bridge_notifier);
if (IS_ERR(driver->mdm_ch)) {
- pr_err("DIAG Unable to open USB diag MDM channel\n");
+ pr_err("diag: Unable to open USB diag MDM channel\n");
goto err;
}
#endif
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+ INIT_WORK(&(driver->diag_disconnect_work), diag_disconnect_work_fn);
+ INIT_WORK(&(driver->diag_usb_read_complete_work),
+ diag_usb_read_complete_fn);
+ /* register HSIC device */
ret = platform_driver_register(&msm_hsic_ch_driver);
if (ret)
- pr_err("DIAG could not register HSIC device, ret: %d\n", ret);
- else
- driver->hsic_initialized = 1;
-
+ pr_err("diag: could not register HSIC device, ret: %d\n", ret);
+ /* register SMUX device */
+ ret = platform_driver_register(&msm_diagfwd_smux_driver);
+ if (ret)
+ pr_err("diag: could not register SMUX device, ret: %d\n", ret);
+#endif
return;
err:
- pr_err("DIAG could not initialize for HSIC execution\n");
-}
-
-void diagfwd_hsic_exit(void)
-{
- pr_debug("DIAG in %s\n", __func__);
-
- if (driver->hsic_initialized)
- diag_hsic_close();
-
-#ifdef CONFIG_DIAG_OVER_USB
- if (driver->usb_mdm_connected)
- usb_diag_free_req(driver->mdm_ch);
-#endif
- platform_driver_unregister(&msm_hsic_ch_driver);
-#ifdef CONFIG_DIAG_OVER_USB
- usb_diag_close(driver->mdm_ch);
-#endif
- kfree(driver->buf_in_hsic);
+ pr_err("diag: Could not initialize for bridge forwarding\n");
kfree(driver->usb_buf_mdm_out);
kfree(driver->write_ptr_mdm);
kfree(driver->usb_read_mdm_ptr);
- destroy_workqueue(driver->diag_hsic_wq);
+ if (driver->diag_bridge_wq)
+ destroy_workqueue(driver->diag_bridge_wq);
- driver->hsic_device_enabled = 0;
+ return;
+}
+
+void diagfwd_bridge_exit(void)
+{
+ pr_debug("diag: in %s\n", __func__);
+
+ if (driver->hsic_device_enabled) {
+ diag_hsic_close();
+ kfree(driver->buf_in_hsic);
+ driver->hsic_device_enabled = 0;
+ }
+ if (driver->diag_smux_enabled) {
+ driver->lcid = LCID_INVALID;
+ kfree(driver->buf_in_smux);
+ driver->diag_smux_enabled = 0;
+ }
+ platform_driver_unregister(&msm_hsic_ch_driver);
+ platform_driver_unregister(&msm_diagfwd_smux_driver);
+ /* destroy USB MDM specific variables */
+#ifdef CONFIG_DIAG_OVER_USB
+ if (driver->usb_mdm_connected)
+ usb_diag_free_req(driver->mdm_ch);
+ usb_diag_close(driver->mdm_ch);
+#endif
+ kfree(driver->usb_buf_mdm_out);
+ kfree(driver->write_ptr_mdm);
+ kfree(driver->usb_read_mdm_ptr);
+ destroy_workqueue(driver->diag_bridge_wq);
}
diff --git a/drivers/char/diag/diagfwd_hsic.h b/drivers/char/diag/diagfwd_hsic.h
index 8785d9f..b189c94 100644
--- a/drivers/char/diag/diagfwd_hsic.h
+++ b/drivers/char/diag/diagfwd_hsic.h
@@ -17,11 +17,11 @@
#define N_MDM_WRITE 1 /* Upgrade to 2 with ping pong buffer */
#define N_MDM_READ 1
-int diagfwd_connect_hsic(int);
-int diagfwd_disconnect_hsic(int);
+int diagfwd_connect_bridge(int);
+int diagfwd_disconnect_bridge(int);
int diagfwd_write_complete_hsic(void);
int diagfwd_cancel_hsic(void);
-void diagfwd_hsic_init(void);
-void diagfwd_hsic_exit(void);
+void diagfwd_bridge_init(void);
+void diagfwd_bridge_exit(void);
#endif
diff --git a/drivers/char/diag/diagfwd_smux.c b/drivers/char/diag/diagfwd_smux.c
new file mode 100644
index 0000000..8bbc67e
--- /dev/null
+++ b/drivers/char/diag/diagfwd_smux.c
@@ -0,0 +1,156 @@
+/* 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/termios.h>
+#include <linux/slab.h>
+#include <linux/diagchar.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <mach/usbdiag.h>
+#include "diagchar.h"
+#include "diagfwd.h"
+#include "diagfwd_smux.h"
+
+void diag_smux_event(void *priv, int event_type, const void *metadata)
+{
+ unsigned char *rx_buf;
+ int len;
+
+ switch (event_type) {
+ case SMUX_CONNECTED:
+ pr_debug("diag: SMUX_CONNECTED received\n");
+ driver->in_busy_smux = 0;
+ /* read data from USB MDM channel & Initiate first write */
+ queue_work(driver->diag_bridge_wq,
+ &(driver->diag_read_mdm_work));
+ break;
+ case SMUX_DISCONNECTED:
+ pr_info("diag: SMUX_DISCONNECTED received\n");
+ break;
+ case SMUX_WRITE_DONE:
+ pr_debug("diag: SMUX Write done\n");
+ break;
+ case SMUX_WRITE_FAIL:
+ pr_info("diag: SMUX Write Failed\n");
+ break;
+ case SMUX_READ_FAIL:
+ pr_info("diag: SMUX Read Failed\n");
+ break;
+ case SMUX_READ_DONE:
+ len = ((struct smux_meta_read *)metadata)->len;
+ rx_buf = ((struct smux_meta_read *)metadata)->buffer;
+ driver->write_ptr_mdm->length = len;
+ diag_device_write(driver->buf_in_smux, SMUX_DATA,
+ driver->write_ptr_mdm);
+ break;
+ };
+}
+
+int diagfwd_write_complete_smux(void)
+{
+ pr_debug("diag: clear in_busy_smux\n");
+ driver->in_busy_smux = 0;
+ return 0;
+}
+
+int diagfwd_read_complete_smux(void)
+{
+ queue_work(driver->diag_bridge_wq, &(driver->diag_read_mdm_work));
+ return 0;
+}
+
+int diag_get_rx_buffer(void *priv, void **pkt_priv, void **buffer, int size)
+{
+ if (!driver->in_busy_smux) {
+ *pkt_priv = (void *)0x1234;
+ *buffer = driver->buf_in_smux;
+ pr_debug("diag: set in_busy_smux as 1\n");
+ driver->in_busy_smux = 1;
+ } else {
+ pr_debug("diag: read buffer for SMUX is BUSY\n");
+ return -EAGAIN;
+ }
+ return 0;
+}
+
+static int diagfwd_smux_runtime_suspend(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: suspending...\n");
+ return 0;
+}
+
+static int diagfwd_smux_runtime_resume(struct device *dev)
+{
+ dev_dbg(dev, "pm_runtime: resuming...\n");
+ return 0;
+}
+
+static const struct dev_pm_ops diagfwd_smux_dev_pm_ops = {
+ .runtime_suspend = diagfwd_smux_runtime_suspend,
+ .runtime_resume = diagfwd_smux_runtime_resume,
+};
+
+int diagfwd_connect_smux(void)
+{
+ void *priv = NULL;
+ int ret = 0;
+
+ if (driver->lcid == LCID_INVALID) {
+ ret = msm_smux_open(LCID_VALID, priv, diag_smux_event,
+ diag_get_rx_buffer);
+ if (!ret) {
+ driver->lcid = LCID_VALID;
+ msm_smux_tiocm_set(driver->lcid, TIOCM_DTR, 0);
+ pr_info("diag: open SMUX ch, r = %d\n", ret);
+ } else {
+ pr_err("diag: failed to open SMUX ch, r = %d\n", ret);
+ }
+ }
+ /* Poll USB channel to check for data*/
+ queue_work(driver->diag_bridge_wq, &(driver->diag_read_mdm_work));
+ return ret;
+}
+
+static int diagfwd_smux_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+
+ pr_info("diag: SMUX probe called\n");
+ driver->lcid = LCID_INVALID;
+ driver->diag_smux_enabled = 1;
+ if (driver->buf_in_smux == NULL) {
+ driver->buf_in_smux = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
+ if (driver->buf_in_smux == NULL)
+ goto err;
+ }
+ /* Only required for Local loopback test
+ * ret = msm_smux_set_ch_option(LCID_VALID,
+ SMUX_CH_OPTION_LOCAL_LOOPBACK, 0);
+ * if (ret)
+ * pr_err("diag: error setting SMUX ch option, r = %d\n", ret);
+ */
+ ret = diagfwd_connect_smux();
+ return ret;
+
+err:
+ pr_err("diag: Could not initialize SMUX buffer\n");
+ kfree(driver->buf_in_smux);
+ return ret;
+}
+
+struct platform_driver msm_diagfwd_smux_driver = {
+ .probe = diagfwd_smux_probe,
+ .driver = {
+ .name = "SMUX_DIAG",
+ .owner = THIS_MODULE,
+ .pm = &diagfwd_smux_dev_pm_ops,
+ },
+};
diff --git a/drivers/char/diag/diagfwd_smux.h b/drivers/char/diag/diagfwd_smux.h
new file mode 100644
index 0000000..e78b7ed
--- /dev/null
+++ b/drivers/char/diag/diagfwd_smux.h
@@ -0,0 +1,25 @@
+/* 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.
+ */
+
+#ifndef DIAGFWD_SMUX_H
+#define DIAGFWD_SMUX_H
+
+#include <linux/smux.h>
+#define LCID_VALID SMUX_USB_DIAG_0
+#define LCID_INVALID 0
+
+int diagfwd_read_complete_smux(void);
+int diagfwd_write_complete_smux(void);
+int diagfwd_connect_smux(void);
+extern struct platform_driver msm_diagfwd_smux_driver;
+
+#endif
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 8362b65..ce8b429 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2471,7 +2471,6 @@
#define A3XX_INT_MASK \
((1 << A3XX_INT_RBBM_AHB_ERROR) | \
- (1 << A3XX_INT_RBBM_REG_TIMEOUT) | \
(1 << A3XX_INT_RBBM_ATB_BUS_OVERFLOW) | \
(1 << A3XX_INT_CP_T0_PACKET_IN_IB) | \
(1 << A3XX_INT_CP_OPCODE_ERROR) | \
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index a0907d7..5572695 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -674,6 +674,12 @@
adreno_find_ctxtmem(device, ptbase, ibaddr,
ibsize);
+ /* IOMMU uses a NOP IB placed in setsate memory */
+ if (NULL == memdesc)
+ if (kgsl_gpuaddr_in_memdesc(
+ &device->mmu.setstate_memory,
+ ibaddr, ibsize))
+ memdesc = &device->mmu.setstate_memory;
/*
* The IB from CP_IB1_BASE and the IBs for legacy
* context switch go into the snapshot all
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 9092b96..07ce90c 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -760,7 +760,7 @@
return 0;
spin_lock(&pt->lock);
- if (pt->tlb_flags && (1<<id)) {
+ if (pt->tlb_flags & (1<<id)) {
result = KGSL_MMUFLAGS_TLBFLUSH;
pt->tlb_flags &= ~(1<<id);
}
diff --git a/drivers/media/video/msm/sensors/ov5647_v4l2.c b/drivers/media/video/msm/sensors/ov5647_v4l2.c
index 90186ee..9dfbf8d 100644
--- a/drivers/media/video/msm/sensors/ov5647_v4l2.c
+++ b/drivers/media/video/msm/sensors/ov5647_v4l2.c
@@ -556,10 +556,10 @@
static int32_t ov5647_write_prev_exp_gain(struct msm_sensor_ctrl_t *s_ctrl,
uint16_t gain, uint32_t line)
{
-
- static uint16_t max_line = 984;
u8 intg_time_hsb, intg_time_msb, intg_time_lsb;
uint8_t gain_lsb, gain_hsb;
+ uint32_t fl_lines = s_ctrl->curr_frame_length_lines;
+ uint8_t offset = s_ctrl->sensor_exp_gain_info->vert_offset;
CDBG(KERN_ERR "preview exposure setting 0x%x, 0x%x, %d",
gain, line, line);
@@ -567,33 +567,23 @@
gain_lsb = (uint8_t) (gain);
gain_hsb = (uint8_t)((gain & 0x300)>>8);
+ fl_lines = (fl_lines * s_ctrl->fps_divider) / Q10;
+
s_ctrl->func_tbl->sensor_group_hold_on(s_ctrl);
/* adjust frame rate */
- if (line > 980) {
- msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ if (line > (fl_lines - offset))
+ fl_lines = line + offset;
+
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
s_ctrl->sensor_output_reg_addr->frame_length_lines,
- (uint8_t)((line+4) >> 8),
+ (uint8_t)(fl_lines >> 8),
MSM_CAMERA_I2C_BYTE_DATA);
- msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
+ msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
s_ctrl->sensor_output_reg_addr->frame_length_lines + 1,
- (uint8_t)((line+4) & 0x00FF),
+ (uint8_t)(fl_lines & 0x00FF),
MSM_CAMERA_I2C_BYTE_DATA);
- max_line = line + 4;
- } else if (max_line > 984) {
-
- msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
- s_ctrl->sensor_output_reg_addr->frame_length_lines,
- (uint8_t)(984 >> 8),
- MSM_CAMERA_I2C_BYTE_DATA);
-
- msm_camera_i2c_write(s_ctrl->sensor_i2c_client,
- s_ctrl->sensor_output_reg_addr->frame_length_lines + 1 ,
- (uint8_t)(984 & 0x00FF),
- MSM_CAMERA_I2C_BYTE_DATA);
- max_line = 984;
- }
line = line<<4;
/* ov5647 need this operation */
diff --git a/drivers/mfd/marimba-tsadc.c b/drivers/mfd/marimba-tsadc.c
index 8a7b781..32b93e1 100644
--- a/drivers/mfd/marimba-tsadc.c
+++ b/drivers/mfd/marimba-tsadc.c
@@ -437,7 +437,7 @@
struct marimba_tsadc *tsadc = dev_get_drvdata(dev);
if (tsadc->clk_enabled == true) {
- clk_disable(tsadc->codec_ssbi);
+ clk_disable_unprepare(tsadc->codec_ssbi);
tsadc->clk_enabled = false;
}
@@ -462,7 +462,7 @@
marimba_tsadc_configure(tsadc_dev);
fail_shutdown:
if (tsadc->clk_enabled == false) {
- ret = clk_enable(tsadc->codec_ssbi);
+ ret = clk_prepare_enable(tsadc->codec_ssbi);
if (ret == 0)
tsadc->clk_enabled = true;
}
@@ -475,7 +475,7 @@
struct marimba_tsadc *tsadc = dev_get_drvdata(dev);
if (tsadc->clk_enabled == false) {
- rc = clk_enable(tsadc->codec_ssbi);
+ rc = clk_prepare_enable(tsadc->codec_ssbi);
if (rc != 0) {
pr_err("%s: Clk enable failed\n", __func__);
return rc;
@@ -515,7 +515,7 @@
tsadc->pdata->marimba_tsadc_power(0);
fail_tsadc_power:
if (tsadc->clk_enabled == true) {
- clk_disable(tsadc->codec_ssbi);
+ clk_disable_unprepare(tsadc->codec_ssbi);
tsadc->clk_enabled = false;
}
return rc;
@@ -591,7 +591,7 @@
rc = PTR_ERR(tsadc->codec_ssbi);
goto fail_clk_get;
}
- rc = clk_enable(tsadc->codec_ssbi);
+ rc = clk_prepare_enable(tsadc->codec_ssbi);
if (rc != 0)
goto fail_clk_enable;
@@ -623,7 +623,7 @@
return rc;
fail_add_subdev:
- clk_disable(tsadc->codec_ssbi);
+ clk_disable_unprepare(tsadc->codec_ssbi);
fail_clk_enable:
clk_put(tsadc->codec_ssbi);
@@ -647,7 +647,7 @@
device_init_wakeup(&pdev->dev, 0);
if (tsadc->clk_enabled == true)
- clk_disable(tsadc->codec_ssbi);
+ clk_disable_unprepare(tsadc->codec_ssbi);
clk_put(tsadc->codec_ssbi);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 4854614..2e6e422 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -4381,7 +4381,7 @@
}
static ssize_t
-set_polling(struct device *dev, struct device_attribute *attr,
+store_polling(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct mmc_host *mmc = dev_get_drvdata(dev);
@@ -4405,9 +4405,6 @@
return count;
}
-static DEVICE_ATTR(polling, S_IRUGO | S_IWUSR,
- show_polling, set_polling);
-
static ssize_t
show_sdcc_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -4420,7 +4417,7 @@
}
static ssize_t
-set_sdcc_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
+store_sdcc_to_mem_max_bus_bw(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct mmc_host *mmc = dev_get_drvdata(dev);
@@ -4437,20 +4434,6 @@
return count;
}
-static DEVICE_ATTR(max_bus_bw, S_IRUGO | S_IWUSR,
- show_sdcc_to_mem_max_bus_bw, set_sdcc_to_mem_max_bus_bw);
-
-static struct attribute *dev_attrs[] = {
- &dev_attr_max_bus_bw.attr,
- /* if polling is enabled, this will be filled with dev_attr_polling */
- NULL,
- NULL,
-};
-
-static struct attribute_group dev_attr_grp = {
- .attrs = dev_attrs,
-};
-
#ifdef CONFIG_HAS_EARLYSUSPEND
static void msmsdcc_early_suspend(struct early_suspend *h)
{
@@ -5212,14 +5195,30 @@
#if defined(CONFIG_DEBUG_FS)
msmsdcc_dbg_createhost(host);
#endif
- if (!plat->status_irq)
- dev_attrs[1] = &dev_attr_polling.attr;
- ret = sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp);
+ host->max_bus_bw.show = show_sdcc_to_mem_max_bus_bw;
+ host->max_bus_bw.store = store_sdcc_to_mem_max_bus_bw;
+ sysfs_attr_init(&host->max_bus_bw.attr);
+ host->max_bus_bw.attr.name = "max_bus_bw";
+ host->max_bus_bw.attr.mode = S_IRUGO | S_IWUSR;
+ ret = device_create_file(&pdev->dev, &host->max_bus_bw);
if (ret)
goto platform_irq_free;
+
+ if (!plat->status_irq) {
+ host->polling.show = show_polling;
+ host->polling.store = store_polling;
+ sysfs_attr_init(&host->polling.attr);
+ host->polling.attr.name = "polling";
+ host->polling.attr.mode = S_IRUGO | S_IWUSR;
+ ret = device_create_file(&pdev->dev, &host->polling);
+ if (ret)
+ goto remove_max_bus_bw_file;
+ }
return 0;
+ remove_max_bus_bw_file:
+ device_remove_file(&pdev->dev, &host->max_bus_bw);
platform_irq_free:
del_timer_sync(&host->req_tout_timer);
pm_runtime_disable(&(pdev)->dev);
@@ -5296,8 +5295,9 @@
DBG(host, "Removing SDCC device = %d\n", pdev->id);
plat = host->plat;
+ device_remove_file(&pdev->dev, &host->max_bus_bw);
if (!plat->status_irq)
- sysfs_remove_group(&pdev->dev.kobj, &dev_attr_grp);
+ device_remove_file(&pdev->dev, &host->polling);
del_timer_sync(&host->req_tout_timer);
tasklet_kill(&host->dma_tlet);
diff --git a/drivers/mmc/host/msm_sdcc.h b/drivers/mmc/host/msm_sdcc.h
index 0c53102..ef1e05f 100644
--- a/drivers/mmc/host/msm_sdcc.h
+++ b/drivers/mmc/host/msm_sdcc.h
@@ -411,6 +411,8 @@
struct mutex clk_mutex;
bool pending_resume;
struct msmsdcc_msm_bus_vote msm_bus_vote;
+ struct device_attribute max_bus_bw;
+ struct device_attribute polling;
};
int msmsdcc_set_pwrsave(struct mmc_host *mmc, int pwrsave);
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
index 20a290a..f0cb924 100644
--- a/drivers/spmi/spmi.c
+++ b/drivers/spmi/spmi.c
@@ -19,7 +19,7 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/spmi.h>
-
+#include <linux/pm_runtime.h>
struct spmii_boardinfo {
struct list_head list;
struct spmi_boardinfo board_info;
diff --git a/drivers/tty/serial/msm_serial_hs_lite.c b/drivers/tty/serial/msm_serial_hs_lite.c
index 59104ed..4a65177 100644
--- a/drivers/tty/serial/msm_serial_hs_lite.c
+++ b/drivers/tty/serial/msm_serial_hs_lite.c
@@ -1220,6 +1220,9 @@
msm_hsl_write(port, CR_PROTECTION_EN, regmap[vid][UARTDM_CR]);
msm_hsl_write(port, UARTDM_CR_TX_EN_BMSK, regmap[vid][UARTDM_CR]);
+ msm_hsl_write(port, 1, regmap[vid][UARTDM_NCF_TX]);
+ msm_hsl_read(port, regmap[vid][UARTDM_NCF_TX]);
+
printk(KERN_INFO "msm_serial_hsl: console setup on port #%d\n",
port->line);
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 6bd0577..5ed16cc 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -690,6 +690,13 @@
skip_phy_resume:
+ if (!(readl_relaxed(USB_USBCMD) & CMD_RUN) &&
+ (readl_relaxed(USB_PORTSC) & PORT_SUSPEND)) {
+ writel_relaxed(readl_relaxed(USB_USBCMD) | CMD_RUN ,
+ USB_USBCMD);
+ dbg_log_event(NULL, "Set RS", readl_relaxed(USB_USBCMD));
+ }
+
usb_hcd_resume_root_hub(hcd);
atomic_set(&mehci->in_lpm, 0);
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 7fd2d91..30579e7 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -1887,7 +1887,7 @@
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
if (mdp_rev >= MDP_REV_41 && mfd->panel.type == MIPI_CMD_PANEL)
- mdp_dsi_cmd_overlay_suspend();
+ mdp_dsi_cmd_overlay_suspend(mfd);
return ret;
}
@@ -1897,7 +1897,6 @@
#ifdef CONFIG_FB_MSM_MDP40
struct msm_fb_data_type *mfd;
- mdp4_overlay_ctrl_db_reset();
mfd = platform_get_drvdata(pdev);
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index b104b33..f1a6899 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -825,7 +825,7 @@
#endif
#ifndef CONFIG_FB_MSM_MDP40
-static inline void mdp_dsi_cmd_overlay_suspend(void)
+static inline void mdp_dsi_cmd_overlay_suspend(struct msm_fb_data_type *mfd)
{
/* empty */
}
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 905fc21..21513a4 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -173,6 +173,7 @@
MDP4_MIXER_STAGE0, /* zorder 0 */
MDP4_MIXER_STAGE1, /* zorder 1 */
MDP4_MIXER_STAGE2, /* zorder 2 */
+ MDP4_MIXER_STAGE3, /* zorder 3 */
MDP4_MIXER_STAGE_MAX
};
@@ -256,6 +257,19 @@
u8 mark_unmap;
};
+struct blend_cfg {
+ u32 op;
+ u32 bg_alpha;
+ u32 fg_alpha;
+ u32 co3_sel;
+ u32 transp_low0;
+ u32 transp_low1;
+ u32 transp_high0;
+ u32 transp_high1;
+ int solidfill;
+ struct mdp4_overlay_pipe *solidfill_pipe;
+};
+
struct mdp4_overlay_pipe {
uint32 pipe_used;
uint32 pipe_type; /* rgb, video/graphic */
@@ -403,6 +417,7 @@
void mdp4_intr_clear_set(ulong clear, ulong set);
void mdp4_dma_p_cfg(void);
unsigned is_mdp4_hw_reset(void);
+void mdp4_overlay_cfg_init(void);
void mdp4_hw_init(void);
void mdp4_isr_read(int);
void mdp4_clear_lcdc(void);
@@ -417,6 +432,7 @@
uint32 mdp4_overlay_format(struct mdp4_overlay_pipe *pipe);
uint32 mdp4_overlay_unpack_pattern(struct mdp4_overlay_pipe *pipe);
uint32 mdp4_overlay_op_mode(struct mdp4_overlay_pipe *pipe);
+void mdp4_lcdc_base_swap(struct mdp4_overlay_pipe *pipe);
void mdp4_lcdc_overlay(struct msm_fb_data_type *mfd);
#ifdef CONFIG_FB_MSM_DTV
void mdp4_overlay_dtv_start(void);
@@ -489,6 +505,7 @@
struct mdp4_overlay_pipe *pipe);
int mdp4_overlay_dtv_unset(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe);
+void mdp4_dtv_base_swap(struct mdp4_overlay_pipe *pipe);
void mdp4_dtv_overlay(struct msm_fb_data_type *mfd);
int mdp4_dtv_on(struct platform_device *pdev);
int mdp4_dtv_off(struct platform_device *pdev);
@@ -506,7 +523,7 @@
int mdp4_overlay_dsi_state_get(void);
void mdp4_overlay_rgb_setup(struct mdp4_overlay_pipe *pipe);
void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all);
-void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe);
+void mdp4_mixer_blend_setup(int mixer);
struct mdp4_overlay_pipe *mdp4_overlay_stage_pipe(int mixer, int stage);
void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe);
void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe);
@@ -519,6 +536,7 @@
int mdp4_overlay_get(struct fb_info *info, struct mdp_overlay *req);
int mdp4_overlay_set(struct fb_info *info, struct mdp_overlay *req);
int mdp4_overlay_unset(struct fb_info *info, int ndx);
+int mdp4_overlay_unset_mixer(int mixer);
int mdp4_overlay_play_wait(struct fb_info *info,
struct msmfb_overlay_data *req);
int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req);
@@ -612,6 +630,7 @@
struct msmfb_overlay_blt *req);
int mdp4_dsi_video_overlay_blt_offset(struct msm_fb_data_type *mfd,
struct msmfb_overlay_blt *req);
+void mdp4_dsi_video_base_swap(struct mdp4_overlay_pipe *pipe);
#ifdef CONFIG_FB_MSM_MDP40
static inline void mdp3_dsi_cmd_dma_busy_wait(struct msm_fb_data_type *mfd)
@@ -659,6 +678,10 @@
{
return -ENODEV;
}
+static inline void mdp4_dsi_video_base_swap(struct mdp4_overlay_pipe *pipe)
+{
+ /* empty */
+}
#endif
void mdp4_lcdc_overlay_blt(struct msm_fb_data_type *mfd,
@@ -690,7 +713,7 @@
void mdp4_overlay_dsi_video_vsync_push(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe);
void mdp4_dsi_cmd_overlay_restore(void);
-void mdp_dsi_cmd_overlay_suspend(void);
+void mdp_dsi_cmd_overlay_suspend(struct msm_fb_data_type *mfd);
#else
static inline void mdp4_dsi_cmd_dma_busy_wait(struct msm_fb_data_type *mfd)
{
@@ -714,7 +737,7 @@
/* empty */
}
#ifdef CONFIG_FB_MSM_MDP40
-static inline void mdp_dsi_cmd_overlay_suspend(void)
+static inline void mdp_dsi_cmd_overlay_suspend(struct msm_fb_data_type *mfd)
{
/* empty */
}
@@ -727,6 +750,7 @@
struct mdp4_overlay_pipe *pipe);
void mdp4_dsi_cmd_overlay_kickoff(struct msm_fb_data_type *mfd,
struct mdp4_overlay_pipe *pipe);
+void mdp4_dsi_cmd_base_swap(struct mdp4_overlay_pipe *pipe);
void mdp4_overlay_panel_3d(int mixer_num, uint32 panel_3d);
int mdp4_overlay_3d_sbys(struct fb_info *info, struct msmfb_overlay_3d *req);
@@ -747,7 +771,7 @@
void mdp4_overlay_dsi_video_wait4vsync(struct msm_fb_data_type *mfd);
void mdp4_primary_vsync_dsi_video(void);
uint32_t mdp4_ss_table_value(int8_t param, int8_t index);
-void mdp4_overlay_ctrl_db_reset(void);
+void mdp4_overlay_borderfill_stage_down(struct mdp4_overlay_pipe *pipe);
int mdp4_overlay_writeback_on(struct platform_device *pdev);
int mdp4_overlay_writeback_off(struct platform_device *pdev);
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index ce0dd3d..b4712a1 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -46,8 +46,12 @@
struct mdp4_overlay_ctrl {
struct mdp4_overlay_pipe plist[OVERLAY_PIPE_MAX];
struct mdp4_overlay_pipe *stage[MDP4_MIXER_MAX][MDP4_MIXER_STAGE_MAX];
+ struct mdp4_overlay_pipe *baselayer[MDP4_MIXER_MAX];
+ struct blend_cfg blend[MDP4_MIXER_MAX][MDP4_MIXER_STAGE_MAX];
uint32 mixer_cfg[MDP4_MIXER_MAX];
+ uint32 flush[MDP4_MIXER_MAX];
uint32 cs_controller;
+ uint32 hw_version;
uint32 panel_3d;
uint32 panel_mode;
uint32 mixer0_played;
@@ -198,14 +202,6 @@
}
}
-void mdp4_overlay_ctrl_db_reset(void)
-{
- int i;
-
- for (i = MDP4_MIXER0; i < MDP4_MIXER_MAX; i++)
- ctrl->mixer_cfg[i] = 0;
-}
-
int mdp4_overlay_mixer_play(int mixer_num)
{
if (mixer_num == MDP4_MIXER2)
@@ -236,6 +232,20 @@
return ctrl->panel_mode;
}
+void mdp4_overlay_cfg_init(void)
+{
+ if (ctrl->hw_version == 0) {
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ ctrl->hw_version = inpdw(MDP_BASE + 0x0); /* MDP_HW_VERSION */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ }
+
+ if (ctrl->hw_version >= 0x0402030b) {
+ /* MDP_LAYERMIXER_IN_CFG_UPDATE_METHOD */
+ outpdw(MDP_BASE + 0x100fc, 0x01);
+ }
+}
+
void mdp4_overlay_dmae_cfg(struct msm_fb_data_type *mfd, int atv)
{
uint32 dmae_cfg_reg;
@@ -847,6 +857,8 @@
case MDP_YCRCB_H1V1:
case MDP_YCBCR_H1V1:
return OVERLAY_TYPE_VIDEO;
+ case MDP_RGB_BORDERFILL:
+ return OVERLAY_TYPE_BF;
default:
mdp4_stat.err_format++;
return -ERANGE;
@@ -1120,6 +1132,9 @@
pipe->element2 = C2_R_Cr; /* R */
}
pipe->bpp = 3; /* 3 bpp */
+ case MDP_RGB_BORDERFILL:
+ pipe->alpha_enable = 0;
+ pipe->alpha = 0;
break;
default:
/* not likely */
@@ -1441,13 +1456,13 @@
return -ENODEV;
cnt = 0;
- ndx = 1; /* ndx 0 if not used */
-
+ ndx = MDP4_MIXER_STAGE_BASE;
for ( ; ndx < MDP4_MIXER_STAGE_MAX; ndx++) {
pipe = ctrl->stage[mixer_num][ndx];
if (pipe == NULL)
continue;
info->z_order = pipe->mixer_stage - MDP4_MIXER_STAGE0;
+ /* z_order == -1, means base layer */
info->ptype = pipe->pipe_type;
info->pnum = pipe->pipe_num;
info->pndx = pipe->pipe_ndx;
@@ -1458,331 +1473,458 @@
return cnt;
}
-static void mdp4_overlay_bg_solidfill_clear(uint32 mixer_num)
-{
- struct mdp4_overlay_pipe *bg_pipe;
- unsigned char *rgb_base;
- uint32 rgb_src_format;
- int pnum;
-
- bg_pipe = mdp4_overlay_stage_pipe(mixer_num,
- MDP4_MIXER_STAGE_BASE);
- if (bg_pipe && bg_pipe->pipe_type == OVERLAY_TYPE_BF) {
- bg_pipe = mdp4_overlay_stage_pipe(mixer_num,
- MDP4_MIXER_STAGE0);
- }
-
- if (bg_pipe && bg_pipe->pipe_type == OVERLAY_TYPE_RGB) {
- rgb_src_format = mdp4_overlay_format(bg_pipe);
- if (!(rgb_src_format & MDP4_FORMAT_SOLID_FILL)) {
- pnum = bg_pipe->pipe_num - OVERLAY_PIPE_RGB1;
- rgb_base = MDP_BASE + MDP4_RGB_BASE;
- rgb_base += MDP4_RGB_OFF * pnum;
- outpdw(rgb_base + 0x50, rgb_src_format);
- outpdw(rgb_base + 0x0058, bg_pipe->op_mode);
- mdp4_overlay_reg_flush(bg_pipe, 0);
- }
- }
-}
-
-void mdp4_mixer_pipe_cleanup(int mixer)
-{
- struct mdp4_overlay_pipe *pipe;
- int j;
-
- for (j = MDP4_MIXER_STAGE_MAX - 1; j > MDP4_MIXER_STAGE_BASE; j--) {
- pipe = ctrl->stage[mixer][j];
- if (pipe == NULL)
- continue;
- pr_debug("%s(): pipe %u\n", __func__, pipe->pipe_ndx);
- mdp4_mixer_stage_down(pipe);
- mdp4_overlay_pipe_free(pipe);
- }
-}
-
static void mdp4_mixer_stage_commit(int mixer)
{
struct mdp4_overlay_pipe *pipe;
- int i, j, off;
- u32 data = 0, stage, flush_bits = 0, pipe_cnt = 0, pull_mode = 0;
- u32 cfg[MDP4_MIXER_MAX];
+ int i, num;
+ u32 data, stage;
+ int off;
+ unsigned long flags;
- if (mixer == MDP4_MIXER0)
- flush_bits |= 0x1;
- else if (mixer == MDP4_MIXER1)
- flush_bits |= 0x2;
+ data = 0;
+ for (i = MDP4_MIXER_STAGE_BASE; i < MDP4_MIXER_STAGE_MAX; i++) {
+ pipe = ctrl->stage[mixer][i];
+ if (pipe == NULL)
+ continue;
+ pr_debug("%s: mixer=%d ndx=%d stage=%d\n", __func__,
+ mixer, pipe->pipe_ndx, i);
+ stage = pipe->mixer_stage;
+ if (mixer >= MDP4_MIXER1)
+ stage += 8;
+ stage <<= (4 * pipe->pipe_num);
+ data |= stage;
+ }
- for (i = MDP4_MIXER0; i < MDP4_MIXER_MAX; i++) {
- cfg[i] = 0;
- for (j = MDP4_MIXER_STAGE_BASE; j < MDP4_MIXER_STAGE_MAX; j++) {
- pipe = ctrl->stage[i][j];
- if (pipe == NULL)
- break;
- stage = pipe->mixer_stage;
- if (i >= MDP4_MIXER1)
- stage += 8;
- stage <<= (4 * pipe->pipe_num);
- cfg[i] |= stage;
- pipe_cnt++;
+ mdp4_mixer_blend_setup(mixer);
- mdp4_mixer_blend_setup(pipe);
+ off = 0;
+ if (data != ctrl->mixer_cfg[mixer]) {
+ ctrl->mixer_cfg[mixer] = data;
+ if (mixer >= MDP4_MIXER2) {
+ /* MDP_LAYERMIXER2_IN_CFG */
+ off = 0x100f0;
+ } else {
+ /* mixer 0 or 1 */
+ num = mixer + 1;
+ num &= 0x01;
+ data |= ctrl->mixer_cfg[num];
+ off = 0x10100;
}
+ pr_debug("%s: mixer=%d data=%x flush=%x\n", __func__,
+ mixer, data, ctrl->flush[mixer]);
}
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- if (ctrl->mixer_cfg[mixer] != cfg[mixer]) {
- if ((ctrl->mixer_cfg[MDP4_MIXER0] != cfg[MDP4_MIXER0]) ||
- (ctrl->mixer_cfg[MDP4_MIXER1] != cfg[MDP4_MIXER1])) {
- off = 0x10100;
- if (ctrl->mixer_cfg[MDP4_MIXER0] != cfg[MDP4_MIXER0]) {
- flush_bits |= 0x1;
- ctrl->mixer_cfg[MDP4_MIXER0] = cfg[MDP4_MIXER0];
+ local_irq_save(flags);
+ if (off)
+ outpdw(MDP_BASE + off, data);
- if ((ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) ||
- (ctrl->panel_mode & MDP4_PANEL_LCDC))
- pull_mode = 1;
- }
- if (ctrl->mixer_cfg[MDP4_MIXER1] != cfg[MDP4_MIXER1]) {
- flush_bits |= 0x2;
- ctrl->mixer_cfg[MDP4_MIXER1] = cfg[MDP4_MIXER1];
-
- pull_mode = 1;
- }
-
- data = cfg[MDP4_MIXER0] | cfg[MDP4_MIXER1];
-
- pr_debug("%s: mixer=%d data=%x flush=%x\n", __func__,
- mixer, data, flush_bits);
-
- outpdw(MDP_BASE + off, data); /* LAYERMIXER_IN_CFG */
- if (pull_mode) {
- outpdw(MDP_BASE + 0x18000, flush_bits);
- /* wait for vsync on both pull mode interfaces */
- msleep(20);
- }
- }
-
- if (ctrl->mixer_cfg[MDP4_MIXER2] != cfg[MDP4_MIXER2]) {
- off = 0x100F0;
- ctrl->mixer_cfg[MDP4_MIXER2] = cfg[MDP4_MIXER2];
- data = cfg[MDP4_MIXER2];
-
- pr_debug("%s: mixer=%d data=%x\n", __func__,
- mixer, data);
-
- outpdw(MDP_BASE + off, data); /* LAYERMIXER_IN_CFG */
- }
- } else {
- if (mixer == MDP4_MIXER0) {
- if ((ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) ||
- (ctrl->panel_mode & MDP4_PANEL_LCDC))
- pull_mode = 1;
- } else if (mixer == MDP4_MIXER1) {
- pull_mode = 1;
- }
-
- if (pull_mode)
- outpdw(MDP_BASE + 0x18000, flush_bits);
+ if (ctrl->flush[mixer]) {
+ outpdw(MDP_BASE + 0x18000, ctrl->flush[mixer]);
+ ctrl->flush[mixer] = 0;
}
+ local_irq_restore(flags);
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
-
- if (data && pipe_cnt == 1)
- mdp4_update_perf_level(OVERLAY_PERF_LEVEL4);
}
+
void mdp4_mixer_stage_up(struct mdp4_overlay_pipe *pipe)
{
- struct mdp4_overlay_pipe *spipe;
- int mixer;
+ struct mdp4_overlay_pipe *pp;
+ int i, mixer;
mixer = pipe->mixer_num;
- spipe = ctrl->stage[mixer][pipe->mixer_stage];
- if ((spipe != NULL) && (spipe->pipe_num != pipe->pipe_num)) {
- mdp4_stat.err_stage++;
- return;
+ for (i = MDP4_MIXER_STAGE_BASE; i < MDP4_MIXER_STAGE_MAX; i++) {
+ pp = ctrl->stage[mixer][i];
+ if (pp == pipe) {
+ ctrl->stage[mixer][i] = NULL;
+ break;
+ }
}
ctrl->stage[mixer][pipe->mixer_stage] = pipe; /* keep it */
- if (!(pipe->flags & MDP_OV_PLAY_NOWAIT))
+ if (!(pipe->flags & MDP_OV_PLAY_NOWAIT)) {
+ pr_debug("%s: mixer=%d ndx=%d stage=%d flags=%x\n",
+ __func__, mixer, pipe->pipe_ndx,
+ pipe->mixer_stage, pipe->flags);
mdp4_mixer_stage_commit(mixer);
+ }
}
void mdp4_mixer_stage_down(struct mdp4_overlay_pipe *pipe)
{
- struct mdp4_overlay_pipe *spipe;
+ struct mdp4_overlay_pipe *pp;
+ int i, mixer;
- spipe = ctrl->stage[pipe->mixer_num][pipe->mixer_stage];
- if (spipe == NULL) /* not running */
+ mixer = pipe->mixer_num;
+
+ for (i = MDP4_MIXER_STAGE_BASE; i < MDP4_MIXER_STAGE_MAX; i++) {
+ pp = ctrl->stage[mixer][i];
+ if (pp == pipe)
+ ctrl->stage[mixer][i] = NULL; /* clear it */
+ }
+
+ if (!(pipe->flags & MDP_OV_PLAY_NOWAIT)) {
+ pr_debug("%s: mixer=%d ndx=%d stage=%d flags=%x\n",
+ __func__, pipe->mixer_num, pipe->pipe_ndx,
+ pipe->mixer_stage, pipe->flags);
+ mdp4_mixer_stage_commit(pipe->mixer_num);
+ }
+}
+/*
+ * mixer0: rgb3: border color at register 0x15004, 0x15008
+ * mixer1: vg3: border color at register 0x1D004, 0x1D008
+ * mixer2: xxx: border color at register 0x8D004, 0x8D008
+ */
+void mdp4_overlay_borderfill_stage_up(struct mdp4_overlay_pipe *pipe)
+{
+ struct mdp4_overlay_pipe *bspipe;
+ int ptype, pnum, pndx, mixer;
+ int format, alpha_enable, alpha;
+
+ if (pipe->pipe_type != OVERLAY_TYPE_BF)
return;
- ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL; /* clear it */
+ mixer = pipe->mixer_num;
- mdp4_mixer_stage_commit(pipe->mixer_num);
+ if (ctrl->baselayer[mixer])
+ return;
+
+ bspipe = ctrl->stage[mixer][MDP4_MIXER_STAGE_BASE];
+
+ /* save original base layer */
+ ctrl->baselayer[mixer] = bspipe;
+
+ pipe->alpha = 0; /* make sure bf pipe has alpha 0 */
+ ptype = pipe->pipe_type;
+ pnum = pipe->pipe_num;
+ pndx = pipe->pipe_ndx;
+ format = pipe->src_format;
+ alpha_enable = pipe->alpha_enable;
+ alpha = pipe->alpha;
+ *pipe = *bspipe; /* keep base layer configuration */
+ pipe->pipe_type = ptype;
+ pipe->pipe_num = pnum;
+ pipe->pipe_ndx = pndx;
+ pipe->src_format = format;
+ pipe->alpha_enable = alpha_enable;
+ pipe->alpha = alpha;
+
+ /* free original base layer pipe to be sued as normal pipe */
+ bspipe->pipe_used = 0;
+
+ if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
+ mdp4_dsi_video_base_swap(pipe);
+ else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
+ mdp4_lcdc_base_swap(pipe);
+ else if (ctrl->panel_mode & MDP4_PANEL_DTV)
+ mdp4_dtv_base_swap(pipe);
+
+ mdp4_overlay_reg_flush(bspipe, 1);
+ /* borderfill pipe as base layer */
+ mdp4_mixer_stage_up(pipe);
}
-void mdp4_mixer_blend_setup(struct mdp4_overlay_pipe *pipe)
+void mdp4_overlay_borderfill_stage_down(struct mdp4_overlay_pipe *pipe)
{
- struct mdp4_overlay_pipe *bg_pipe;
- unsigned char *overlay_base, *rgb_base;
- uint32 c0, c1, c2, blend_op, constant_color = 0, rgb_src_format;
- uint32 fg_color3_out, fg_alpha = 0, bg_alpha = 0;
- int off, pnum;
+ struct mdp4_overlay_pipe *bspipe;
+ int ptype, pnum, pndx, mixer;
+ int format, alpha_enable, alpha;
- if (pipe->mixer_stage == MDP4_MIXER_STAGE_BASE)
+ if (pipe->pipe_type != OVERLAY_TYPE_BF)
return;
+ mixer = pipe->mixer_num;
+
+ /* retrieve original base layer */
+ bspipe = ctrl->baselayer[mixer];
+ if (bspipe == NULL) {
+ pr_err("%s: no base layer at mixer=%d\n",
+ __func__, mixer);
+ return;
+ }
+
+ ptype = bspipe->pipe_type;
+ pnum = bspipe->pipe_num;
+ pndx = bspipe->pipe_ndx;
+ format = bspipe->src_format;
+ alpha_enable = bspipe->alpha_enable;
+ alpha = bspipe->alpha;
+ *bspipe = *pipe; /* restore base layer configuration */
+ bspipe->pipe_type = ptype;
+ bspipe->pipe_num = pnum;
+ bspipe->pipe_ndx = pndx;
+ bspipe->src_format = format;
+ bspipe->alpha_enable = alpha_enable;
+ bspipe->alpha = alpha;
+
+ bspipe->pipe_used++; /* mark base layer pipe used */
+
+ ctrl->baselayer[mixer] = NULL;
+
+ /* free borderfill pipe */
+ pipe->pipe_used = 0;
+
+ mdp4_dsi_video_base_swap(bspipe);
+
+ /* free borderfill pipe */
+ mdp4_overlay_reg_flush(pipe, 1);
+ mdp4_mixer_stage_down(pipe);
+ mdp4_overlay_pipe_free(pipe);
+
+ /* stage up base layer */
+ mdp4_overlay_reg_flush(bspipe, 1);
+ /* restore original base layer */
+ mdp4_mixer_stage_up(bspipe);
+}
+
+
+static struct mdp4_overlay_pipe *mdp4_background_layer(int mixer,
+ struct mdp4_overlay_pipe *sp)
+{
+ struct mdp4_overlay_pipe *pp;
+ struct mdp4_overlay_pipe *kp;
+ int i;
+
+ kp = ctrl->stage[mixer][MDP4_MIXER_STAGE_BASE];
+ for (i = MDP4_MIXER_STAGE_BASE; i < MDP4_MIXER_STAGE_MAX; i++) {
+ pp = ctrl->stage[mixer][i];
+ if (pp == NULL)
+ continue;
+ if (pp == sp)
+ break;
+
+ if ((pp->dst_x <= sp->dst_x) &&
+ ((pp->dst_x + pp->dst_w) >= (sp->dst_x + sp->dst_w))) {
+ if ((pp->dst_y <= sp->dst_y) &&
+ ((pp->dst_y + pp->dst_h) >=
+ (sp->dst_y + sp->dst_h))) {
+ kp = pp;
+ }
+ }
+ }
+ return kp;
+}
+
+static void mdp4_overlay_bg_solidfill(struct blend_cfg *blend)
+{
+ struct mdp4_overlay_pipe *pipe;
+ char *base;
+ u32 op_mode, format;
+ int pnum, ptype;
+
+ pipe = blend->solidfill_pipe;
+ if (pipe == NULL)
+ return;
+
+ if (pipe->pipe_type == OVERLAY_TYPE_BF)
+ return;
+
+ ptype = mdp4_overlay_format2type(pipe->src_format);
+ if (ptype == OVERLAY_TYPE_RGB) {
+ pnum = pipe->pipe_num - OVERLAY_PIPE_RGB1;
+ base = MDP_BASE + MDP4_RGB_BASE;
+ base += MDP4_RGB_OFF * pnum;
+ } else {
+ pnum = pipe->pipe_num - OVERLAY_PIPE_VG1;
+ base = MDP_BASE + MDP4_VIDEO_BASE;
+ base += MDP4_VIDEO_OFF * pnum;
+ }
+
+ format = inpdw(base + 0x50);
+ if (blend->solidfill) {
+ format |= MDP4_FORMAT_SOLID_FILL;
+ /*
+ * If solid fill is enabled, flip and scale
+ * have to be disabled. otherwise, h/w
+ * underruns.
+ */
+ op_mode = inpdw(base + 0x0058);
+ op_mode &= ~(MDP4_OP_FLIP_LR + MDP4_OP_SCALEX_EN);
+ op_mode &= ~(MDP4_OP_FLIP_UD + MDP4_OP_SCALEY_EN);
+ outpdw(base + 0x0058, op_mode);
+ outpdw(base + 0x1008, 0); /* black */
+ } else {
+ format &= ~MDP4_FORMAT_SOLID_FILL;
+ blend->solidfill_pipe = NULL;
+ }
+
+ outpdw(base + 0x50, format);
+
+ mdp4_overlay_reg_flush(pipe, 0);
+}
+
+/*
+ * D(i+1) = Ks * S + Kd * D(i)
+ */
+void mdp4_mixer_blend_setup(int mixer)
+{
+ struct mdp4_overlay_pipe *d_pipe;
+ struct mdp4_overlay_pipe *s_pipe;
+ struct blend_cfg *blend;
+ int i, off, ptype;
+ int d_alpha, s_alpha;
+ unsigned char *overlay_base;
+ uint32 c0, c1, c2;
+
+
+ d_pipe = ctrl->stage[mixer][MDP4_MIXER_STAGE_BASE];
+ if (d_pipe == NULL) {
+ pr_err("%s: Error: no bg_pipe at mixer=%d\n", __func__, mixer);
+ return;
+ }
+
+ blend = &ctrl->blend[mixer][MDP4_MIXER_STAGE0];
+ for (i = MDP4_MIXER_STAGE0; i < MDP4_MIXER_STAGE_MAX; i++) {
+ blend->solidfill = 0;
+ blend->op = (MDP4_BLEND_FG_ALPHA_FG_CONST |
+ MDP4_BLEND_BG_ALPHA_BG_CONST);
+ s_pipe = ctrl->stage[mixer][i];
+ if (s_pipe == NULL) {
+ blend++;
+ d_pipe = NULL;
+ d_alpha = 0;
+ continue;
+ }
+ d_pipe = mdp4_background_layer(mixer, s_pipe);
+ d_alpha = d_pipe->alpha_enable;
+ s_alpha = s_pipe->alpha_enable;
+ pr_debug("%s: stage=%d: bg: ndx=%d da=%d dalpha=%x "
+ "fg: ndx=%d sa=%d salpha=%x is_fg=%d\n",
+ __func__, i-2, d_pipe->pipe_ndx, d_alpha, d_pipe->alpha,
+ s_pipe->pipe_ndx, s_alpha, s_pipe->alpha, s_pipe->is_fg);
+
+ /* base on fg's alpha */
+ blend->bg_alpha = 0x0ff - s_pipe->alpha;
+ blend->fg_alpha = s_pipe->alpha;
+ blend->co3_sel = 1; /* use fg alpha */
+
+ if (s_pipe->is_fg) {
+ if (s_pipe->alpha == 0xff) {
+ blend->solidfill = 1;
+ blend->solidfill_pipe = d_pipe;
+ }
+ } else if (s_alpha) {
+ blend->op = (MDP4_BLEND_BG_ALPHA_FG_PIXEL |
+ MDP4_BLEND_BG_INV_ALPHA);
+ } else if (d_alpha) {
+ ptype = mdp4_overlay_format2type(s_pipe->src_format);
+ if (ptype == OVERLAY_TYPE_VIDEO) {
+ blend->op = (MDP4_BLEND_BG_ALPHA_BG_PIXEL |
+ MDP4_BLEND_FG_ALPHA_BG_PIXEL |
+ MDP4_BLEND_FG_INV_ALPHA);
+ blend->co3_sel = 0; /* use bg alpha */
+ } else {
+ /* s_pipe is rgb without alpha */
+ blend->op = (MDP4_BLEND_FG_ALPHA_FG_CONST |
+ MDP4_BLEND_BG_ALPHA_BG_CONST);
+ blend->bg_alpha = 0;
+ }
+ }
+
+ if (s_pipe->transp != MDP_TRANSP_NOP) {
+ if (s_pipe->is_fg) {
+ transp_color_key(s_pipe->src_format,
+ s_pipe->transp, &c0, &c1, &c2);
+ /* Fg blocked */
+ blend->op |= MDP4_BLEND_FG_TRANSP_EN;
+ /* lower limit */
+ blend->transp_low0 = (c1 << 16 | c0);
+ blend->transp_low1 = c2;
+ /* upper limit */
+ blend->transp_high0 = (c1 << 16 | c0);
+ blend->transp_high1 = c2;
+ } else {
+ transp_color_key(d_pipe->src_format,
+ s_pipe->transp, &c0, &c1, &c2);
+ /* Fg blocked */
+ blend->op |= MDP4_BLEND_BG_TRANSP_EN;
+ blend--; /* one stage back */
+ /* lower limit */
+ blend->transp_low0 = (c1 << 16 | c0);
+ blend->transp_low1 = c2;
+ /* upper limit */
+ blend->transp_high0 = (c1 << 16 | c0);
+ blend->transp_high1 = c2;
+ blend++; /* back to original stage */
+ }
+ }
+ blend++;
+ }
+
/* mixer numer, /dev/fb0, /dev/fb1, /dev/fb2 */
- if (pipe->mixer_num == MDP4_MIXER2)
+ if (mixer == MDP4_MIXER2)
overlay_base = MDP_BASE + MDP4_OVERLAYPROC2_BASE;/* 0x88000 */
- else if (pipe->mixer_num == MDP4_MIXER1)
+ else if (mixer == MDP4_MIXER1)
overlay_base = MDP_BASE + MDP4_OVERLAYPROC1_BASE;/* 0x18000 */
else
overlay_base = MDP_BASE + MDP4_OVERLAYPROC0_BASE;/* 0x10000 */
- /* stage 0 to stage 2 */
- off = 0x20 * (pipe->mixer_stage - MDP4_MIXER_STAGE0);
-
- bg_pipe = mdp4_overlay_stage_pipe(pipe->mixer_num,
- MDP4_MIXER_STAGE_BASE);
- if (bg_pipe == NULL) {
- pr_err("%s: Error: no bg_pipe\n", __func__);
- return;
- }
-
- if (bg_pipe->pipe_type == OVERLAY_TYPE_BF &&
- pipe->mixer_stage > MDP4_MIXER_STAGE0) {
- bg_pipe = mdp4_overlay_stage_pipe(pipe->mixer_num,
- MDP4_MIXER_STAGE0);
- }
-
- if (pipe->alpha_enable) {
- /* alpha channel is lost on VG pipe when downscaling */
- if (pipe->pipe_type == OVERLAY_TYPE_VIDEO &&
- (pipe->dst_w < pipe->src_w || pipe->dst_h < pipe->src_h))
- fg_alpha = 0;
- else
- fg_alpha = 1;
- }
-
- if (!fg_alpha && bg_pipe && bg_pipe->alpha_enable) {
- struct mdp4_overlay_pipe *tmp;
- int stage;
-
- bg_alpha = 1;
- /* check all bg layers are opaque to propagate bg alpha */
- stage = bg_pipe->mixer_stage + 1;
- for (; stage < pipe->mixer_stage; stage++) {
- tmp = mdp4_overlay_stage_pipe(pipe->mixer_num, stage);
- if (!tmp || tmp->alpha_enable || tmp->is_fg) {
- bg_alpha = 0;
- break;
- }
- }
- }
-
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+ blend = &ctrl->blend[mixer][MDP4_MIXER_STAGE_BASE];
+ /* lower limit */
+ outpdw(overlay_base + 0x180, blend->transp_low0);
+ outpdw(overlay_base + 0x184, blend->transp_low1);
+ /* upper limit */
+ outpdw(overlay_base + 0x188, blend->transp_high0);
+ outpdw(overlay_base + 0x18c, blend->transp_high1);
+ blend++; /* stage0 */
+ for (i = MDP4_MIXER_STAGE0; i < MDP4_MIXER_STAGE_MAX; i++) {
+ off = 20 * i;
+ off = 0x20 * (i - MDP4_MIXER_STAGE0);
+ if (i == MDP4_MIXER_STAGE3)
+ off -= 4;
- blend_op = (MDP4_BLEND_FG_ALPHA_FG_CONST |
- MDP4_BLEND_BG_ALPHA_BG_CONST);
- outpdw(overlay_base + off + 0x108, pipe->alpha);
- outpdw(overlay_base + off + 0x10c, 0xff - pipe->alpha);
- fg_color3_out = 1; /* keep fg alpha by default */
+ if (blend->solidfill_pipe)
+ mdp4_overlay_bg_solidfill(blend);
- if (pipe->is_fg) {
- if (pipe->alpha == 0xff &&
- bg_pipe->pipe_type == OVERLAY_TYPE_RGB) {
- u32 op_mode;
- pnum = bg_pipe->pipe_num - OVERLAY_PIPE_RGB1;
- rgb_base = MDP_BASE + MDP4_RGB_BASE;
- rgb_base += MDP4_RGB_OFF * pnum;
- rgb_src_format = inpdw(rgb_base + 0x50);
- rgb_src_format |= MDP4_FORMAT_SOLID_FILL;
- /*
- * If solid fill is enabled, flip and scale
- * have to be disabled. otherwise, h/w
- * underruns. Also flush the pipe inorder
- * to take solid fill into effect.
- */
- op_mode = inpdw(rgb_base + 0x0058);
- op_mode &= ~(MDP4_OP_FLIP_LR + MDP4_OP_SCALEX_EN);
- op_mode &= ~(MDP4_OP_FLIP_UD + MDP4_OP_SCALEY_EN);
- outpdw(rgb_base + 0x0058, op_mode);
- outpdw(rgb_base + 0x50, rgb_src_format);
- outpdw(rgb_base + 0x1008, constant_color);
- mdp4_overlay_reg_flush(bg_pipe, 0);
- }
- } else if (fg_alpha) {
- blend_op = (MDP4_BLEND_BG_ALPHA_FG_PIXEL |
- MDP4_BLEND_BG_INV_ALPHA);
- fg_color3_out = 1; /* keep fg alpha */
- } else if (bg_alpha) {
- blend_op = (MDP4_BLEND_BG_ALPHA_BG_PIXEL |
- MDP4_BLEND_FG_ALPHA_BG_PIXEL |
- MDP4_BLEND_FG_INV_ALPHA);
- fg_color3_out = 0; /* keep bg alpha */
- }
-
- if (pipe->transp != MDP_TRANSP_NOP) {
- if (pipe->is_fg) {
- transp_color_key(pipe->src_format, pipe->transp,
- &c0, &c1, &c2);
- /* Fg blocked */
- blend_op |= MDP4_BLEND_FG_TRANSP_EN;
- /* lower limit */
- outpdw(overlay_base + off + 0x110,
- (c1 << 16 | c0));/* low */
- outpdw(overlay_base + off + 0x114, c2);/* low */
+ outpdw(overlay_base + off + 0x108, blend->fg_alpha);
+ outpdw(overlay_base + off + 0x10c, blend->bg_alpha);
+ outpdw(overlay_base + off + 0x104, blend->op);
+ outpdw(overlay_base + (off << 5) + 0x1004, blend->co3_sel);
+ outpdw(overlay_base + off + 0x110, blend->transp_low0);/* low */
+ outpdw(overlay_base + off + 0x114, blend->transp_low1);/* low */
/* upper limit */
- outpdw(overlay_base + off + 0x118,
- (c1 << 16 | c0));
- outpdw(overlay_base + off + 0x11c, c2);
- } else if (bg_pipe) {
- transp_color_key(bg_pipe->src_format,
- pipe->transp, &c0, &c1, &c2);
- /* bg blocked */
- blend_op |= MDP4_BLEND_BG_TRANSP_EN;
- /* lower limit */
- outpdw(overlay_base + 0x180,
- (c1 << 16 | c0));/* low */
- outpdw(overlay_base + 0x184, c2);/* low */
- /* upper limit */
- outpdw(overlay_base + 0x188,
- (c1 << 16 | c0));/* high */
- outpdw(overlay_base + 0x18c, c2);/* high */
- }
+ outpdw(overlay_base + off + 0x118, blend->transp_high0);
+ outpdw(overlay_base + off + 0x11c, blend->transp_high1);
+ blend++;
}
-
- outpdw(overlay_base + off + 0x104, blend_op);
- outpdw(overlay_base + (off << 5) + 0x1004, fg_color3_out);
-
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
void mdp4_overlay_reg_flush(struct mdp4_overlay_pipe *pipe, int all)
{
- struct mdp4_overlay_pipe *bg_pipe;
- uint32 bits = 0;
+ int mixer;
+ uint32 *reg;
+
+ mixer = pipe->mixer_num;
+ reg = &ctrl->flush[mixer];
+ *reg |= (1 << (2 + pipe->pipe_num));
if (all) {
- if (pipe->mixer_num == MDP4_MIXER1)
- bits |= 0x02;
+ if (mixer == MDP4_MIXER0)
+ *reg |= 0x01;
else
- bits |= 0x01;
+ *reg |= 0x02;
}
+}
- if (pipe->pipe_num <= OVERLAY_PIPE_RGB2)
- bits |= 1 << (2 + pipe->pipe_num);
- if (pipe->is_fg && pipe->alpha == 0xFF) {
- bg_pipe = mdp4_overlay_stage_pipe(pipe->mixer_num,
- MDP4_MIXER_STAGE_BASE);
- bits |= 1 << (2 + bg_pipe->pipe_num);
- }
+void mdp4_overlay_flush_piggyback(int m0, int m1)
+{
+ u32 data;
- mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- outpdw(MDP_BASE + 0x18000, bits); /* MDP_OVERLAY_REG_FLUSH */
- mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ data = ctrl->flush[m0] | ctrl->flush[m1];
+ ctrl->flush[m0] = data;
+}
+
+void mdp4_overlay_reg_flush_reset(struct mdp4_overlay_pipe *pipe)
+{
+ int mixer;
+
+ mixer = pipe->mixer_num;
+ ctrl->flush[mixer] = 0;
}
struct mdp4_overlay_pipe *mdp4_overlay_stage_pipe(int mixer, int stage)
@@ -1810,6 +1952,11 @@
int i;
struct mdp4_overlay_pipe *pipe;
+ if (ptype == OVERLAY_TYPE_BF) {
+ if (!mdp4_overlay_borderfill_supported())
+ return NULL;
+ }
+
for (i = 0; i < OVERLAY_PIPE_MAX; i++) {
pipe = &ctrl->plist[i];
if ((pipe->pipe_used == 0) && ((pipe->pipe_type == ptype) ||
@@ -1951,7 +2098,7 @@
return -ERANGE;
}
- if (req->z_order < 0 || req->z_order > 2) {
+ if (req->z_order < 0 || req->z_order > 3) {
pr_err("%s: z_order=%d out of range!\n", __func__,
req->z_order);
mdp4_stat.err_zorder++;
@@ -2076,12 +2223,12 @@
if (req->id == MSMFB_NEW_REQUEST) { /* new request */
pipe->pipe_used++;
pipe->mixer_num = mixer;
- pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0;
pr_debug("%s: zorder=%d pipe ndx=%d num=%d\n", __func__,
req->z_order, pipe->pipe_ndx, pipe->pipe_num);
}
+ pipe->mixer_stage = req->z_order + MDP4_MIXER_STAGE0;
pipe->src_width = req->src.width & 0x1fff; /* source img width */
pipe->src_height = req->src.height & 0x1fff; /* source img height */
pipe->src_h = req->src_rect.h & 0x07ff;
@@ -2335,7 +2482,14 @@
void mdp4_update_perf_level(u32 perf_level)
{
+ static int first = 1;
+
new_perf_level = perf_level;
+
+ if (first) {
+ first = 0;
+ mdp4_set_perf_level();
+ }
}
void mdp4_set_perf_level(void)
@@ -2568,6 +2722,24 @@
return 0;
}
+int mdp4_overlay_unset_mixer(int mixer)
+{
+ struct mdp4_overlay_pipe *pipe;
+ int i, cnt = 0;
+
+ for (i = MDP4_MIXER_STAGE3; i >= MDP4_MIXER_STAGE_BASE; i--) {
+ pipe = ctrl->stage[mixer][i];
+ if (pipe == NULL)
+ continue;
+ pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
+ mdp4_mixer_stage_down(pipe);
+ mdp4_overlay_pipe_free(pipe);
+ cnt++;
+ }
+
+ return cnt;
+}
+
int mdp4_overlay_unset(struct fb_info *info, int ndx)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
@@ -2588,6 +2760,12 @@
return -ENODEV;
}
+ if (pipe->pipe_type == OVERLAY_TYPE_BF) {
+ mdp4_overlay_borderfill_stage_down(pipe);
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return 0;
+ }
+
if (pipe->mixer_num == MDP4_MIXER2)
ctrl->mixer2_played = 0;
else if (pipe->mixer_num == MDP4_MIXER1)
@@ -2609,16 +2787,12 @@
#endif
}
- if (mfd->mdp_rev >= MDP_REV_41 &&
- mdp4_overlay_is_rgb_type(pipe->src_format) &&
- !mfd->use_ov0_blt && (pipe->mixer_num == MDP4_MIXER0 ||
- hdmi_prim_display)) {
- ctrl->stage[pipe->mixer_num][pipe->mixer_stage] = NULL;
- } else {
- if (pipe->is_fg &&
- !mdp4_overlay_is_rgb_type(pipe->src_format)) {
- mdp4_overlay_bg_solidfill_clear(pipe->mixer_num);
- pipe->is_fg = 0;
+ {
+ mdp4_overlay_reg_flush(pipe, 1);
+
+ if (mfd->use_ov0_blt || pipe->mixer_num == MDP4_MIXER1) {
+ /* unstage pipe forcedly */
+ pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
}
mdp4_mixer_stage_down(pipe);
@@ -2779,6 +2953,12 @@
if (mutex_lock_interruptible(&mfd->dma->ov_mutex))
return -EINTR;
+ if (pipe->pipe_type == OVERLAY_TYPE_BF) {
+ mdp4_overlay_borderfill_stage_up(pipe);
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return 0;
+ }
+
img = &req->data;
get_img(img, info, pipe, 0, &start, &len, &srcp0_file,
&ps0_need, &srcp0_ihdl);
@@ -2793,6 +2973,10 @@
pipe->srcp0_addr = addr;
pipe->srcp0_ystride = pipe->src_width * pipe->bpp;
+
+ pr_debug("%s: mixer=%d ndx=%x addr=%x flags=%x\n", __func__,
+ pipe->mixer_num, pipe->pipe_ndx, (int)addr, pipe->flags);
+
if ((req->version_key & VERSION_KEY_MASK) == 0xF9E8D700)
overlay_version = (req->version_key & ~VERSION_KEY_MASK);
@@ -2889,6 +3073,7 @@
if (mfd->use_ov1_blt)
mdp4_overlay1_update_blt_mode(mfd);
+
if (pipe->pipe_type == OVERLAY_TYPE_VIDEO) {
mdp4_overlay_vg_setup(pipe); /* video/graphic pipe */
} else {
@@ -2901,11 +3086,7 @@
mdp4_overlay_rgb_setup(pipe); /* rgb pipe */
}
- if ((ctrl->panel_mode & MDP4_PANEL_DTV) ||
- (ctrl->panel_mode & MDP4_PANEL_LCDC) ||
- (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO))
- mdp4_overlay_reg_flush(pipe, 0);
-
+ mdp4_overlay_reg_flush(pipe, 1);
mdp4_mixer_stage_up(pipe);
if (pipe->mixer_num == MDP4_MIXER2) {
@@ -2920,6 +3101,9 @@
ctrl->mixer1_played++;
/* enternal interface */
if (ctrl->panel_mode & MDP4_PANEL_DTV) {
+ if (pipe->flags & MDP_OV_PLAY_NOWAIT)
+ mdp4_overlay_flush_piggyback(MDP4_MIXER0,
+ MDP4_MIXER1);
mdp4_overlay_dtv_start();
mdp4_overlay_dtv_ov_done_push(mfd, pipe);
if (!mfd->use_ov1_blt)
@@ -2948,6 +3132,7 @@
}
#endif
else {
+ mdp4_overlay_reg_flush_reset(pipe);
/* mddi & mipi dsi cmd mode */
if (pipe->flags & MDP_OV_PLAY_NOWAIT) {
mdp4_stat.overlay_play[pipe->mixer_num]++;
@@ -3107,7 +3292,7 @@
return err;
}
- mdp4_mixer_blend_setup(pipe);
+ mdp4_mixer_blend_setup(pipe->mixer_num);
*ppipe = pipe;
return 0;
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index a5b4b3e..7ba4e75 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -114,6 +114,11 @@
}
}
+void mdp4_dsi_cmd_base_swap(struct mdp4_overlay_pipe *pipe)
+{
+ dsi_pipe = pipe;
+}
+
void mdp4_overlay_update_dsi_cmd(struct msm_fb_data_type *mfd)
{
MDPIBUF *iBuf = &mfd->ibuf;
@@ -162,6 +167,14 @@
} else {
pipe = dsi_pipe;
}
+
+ if (pipe->pipe_used == 0 ||
+ pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) {
+ pr_err("%s: NOT baselayer\n", __func__);
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return;
+ }
+
/*
* configure dsi stream id
* dma_p = 0, dma_s = 1
@@ -207,6 +220,8 @@
mdp4_overlay_rgb_setup(pipe);
+ mdp4_overlay_reg_flush(pipe, 1);
+
mdp4_mixer_stage_up(pipe);
mdp4_overlayproc_cfg(pipe);
@@ -240,6 +255,12 @@
dsi_pipe->src_width_3d = r3d->width;
pipe = dsi_pipe;
+ if (pipe->pipe_used == 0 ||
+ pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) {
+ pr_err("%s: NOT baselayer\n", __func__);
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return;
+ }
if (pipe->is_3d)
mdp4_overlay_panel_3d(pipe->mixer_num, MDP4_3D_SIDE_BY_SIDE);
@@ -282,6 +303,8 @@
mdp4_overlay_rgb_setup(pipe);
+ mdp4_overlay_reg_flush(pipe, 1);
+
mdp4_mixer_stage_up(pipe);
mdp4_overlayproc_cfg(pipe);
@@ -651,12 +674,22 @@
mdp4_stat.kickoff_ov0++;
}
-void mdp_dsi_cmd_overlay_suspend(void)
+void mdp_dsi_cmd_overlay_suspend(struct msm_fb_data_type *mfd)
{
/* dis-engage rgb0 from mixer0 */
if (dsi_pipe) {
- mdp4_mixer_stage_down(dsi_pipe);
- mdp4_iommu_unmap(dsi_pipe);
+ if (mfd->ref_cnt == 0) {
+ /* adb stop */
+ if (dsi_pipe->pipe_type == OVERLAY_TYPE_BF)
+ mdp4_overlay_borderfill_stage_down(dsi_pipe);
+
+ /* dsi_pipe == rgb1 */
+ mdp4_overlay_unset_mixer(dsi_pipe->mixer_num);
+ dsi_pipe = NULL;
+ } else {
+ mdp4_mixer_stage_down(dsi_pipe);
+ mdp4_iommu_unmap(dsi_pipe);
+ }
}
}
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 574a657..47e6432 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -72,6 +72,11 @@
static void mdp4_overlay_dsi_video_wait4event(struct msm_fb_data_type *mfd,
int intr_done);
+void mdp4_dsi_video_base_swap(struct mdp4_overlay_pipe *pipe)
+{
+ dsi_pipe = pipe;
+}
+
int mdp4_dsi_video_on(struct platform_device *pdev)
{
int dsi_width;
@@ -121,8 +126,6 @@
if (mfd->key != MFD_KEY)
return -EINVAL;
- mdp4_overlay_ctrl_db_reset();
-
fbi = mfd->fbi;
var = &fbi->var;
@@ -195,8 +198,9 @@
mdp4_overlay_dmap_xy(pipe); /* dma_p */
mdp4_overlay_dmap_cfg(mfd, 1);
-
mdp4_overlay_rgb_setup(pipe);
+ mdp4_overlay_reg_flush(pipe, 1);
+ mdp4_mixer_stage_up(pipe);
mdp4_overlayproc_cfg(pipe);
@@ -294,10 +298,12 @@
int mdp4_dsi_video_off(struct platform_device *pdev)
{
int ret = 0;
+ struct msm_fb_data_type *mfd;
+
+ mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
/* MDP cmd block enable */
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- mdp4_mixer_pipe_cleanup(dsi_pipe->mixer_num);
MDP_OUTP(MDP_BASE + DSI_VIDEO_BASE, 0);
dsi_video_enabled = 0;
/* MDP cmd block disable */
@@ -311,8 +317,18 @@
/* dis-engage rgb0 from mixer0 */
if (dsi_pipe) {
- mdp4_mixer_stage_down(dsi_pipe);
- mdp4_iommu_unmap(dsi_pipe);
+ if (mfd->ref_cnt == 0) {
+ /* adb stop */
+ if (dsi_pipe->pipe_type == OVERLAY_TYPE_BF)
+ mdp4_overlay_borderfill_stage_down(dsi_pipe);
+
+ /* dsi_pipe == rgb1 */
+ mdp4_overlay_unset_mixer(dsi_pipe->mixer_num);
+ dsi_pipe = NULL;
+ } else {
+ mdp4_mixer_stage_down(dsi_pipe);
+ mdp4_iommu_unmap(dsi_pipe);
+ }
}
return ret;
@@ -387,7 +403,6 @@
mdp4_overlay_dmap_cfg(mfd, 1);
mdp4_overlay_reg_flush(pipe, 1);
-
mdp4_mixer_stage_up(pipe);
mb();
@@ -740,7 +755,6 @@
spin_unlock_irqrestore(&mdp_spin_lock, flag);
-
/*
* may need mutex here to sync with whom dsiable
* timing generator
@@ -801,6 +815,12 @@
mutex_lock(&mfd->dma->ov_mutex);
pipe = dsi_pipe;
+ if (pipe->pipe_used == 0 ||
+ pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) {
+ pr_err("%s: NOT baselayer\n", __func__);
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return;
+ }
if (mfd->display_iova)
pipe->srcp0_addr = mfd->display_iova + buf_offset;
@@ -808,7 +828,7 @@
pipe->srcp0_addr = (uint32)(buf + buf_offset);
mdp4_overlay_rgb_setup(pipe);
- mdp4_overlay_reg_flush(pipe, 0);
+ mdp4_overlay_reg_flush(pipe, 1);
mdp4_mixer_stage_up(pipe);
mdp4_overlay_dsi_video_start();
mdp4_overlay_dsi_video_vsync_push(mfd, pipe);
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index dd96439..c57bd64 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -56,6 +56,12 @@
static struct mdp4_overlay_pipe *dtv_pipe;
static DECLARE_COMPLETION(dtv_comp);
+void mdp4_dtv_base_swap(struct mdp4_overlay_pipe *pipe)
+{
+ if (hdmi_prim_display)
+ dtv_pipe = pipe;
+}
+
static int mdp4_dtv_start(struct msm_fb_data_type *mfd)
{
int dtv_width;
@@ -208,7 +214,6 @@
/* MDP cmd block enable */
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- mdp4_mixer_pipe_cleanup(dtv_pipe->mixer_num);
msleep(20);
MDP_OUTP(MDP_BASE + DTV_BASE, 0);
dtv_enabled = 0;
@@ -262,14 +267,20 @@
if (dtv_pipe != NULL) {
mdp4_dtv_stop(mfd);
+ if (hdmi_prim_display && mfd->ref_cnt == 0) {
+ /* adb stop */
+ if (dtv_pipe->pipe_type == OVERLAY_TYPE_BF)
+ mdp4_overlay_borderfill_stage_down(dtv_pipe);
- /* delay to make sure the last frame finishes */
- msleep(20);
-
- mdp4_mixer_stage_down(dtv_pipe);
- mdp4_overlay_pipe_free(dtv_pipe);
- mdp4_iommu_unmap(dtv_pipe);
- dtv_pipe = NULL;
+ /* dtv_pipe == rgb1 */
+ mdp4_overlay_unset_mixer(dtv_pipe->mixer_num);
+ dtv_pipe = NULL;
+ } else {
+ mdp4_mixer_stage_down(dtv_pipe);
+ mdp4_overlay_pipe_free(dtv_pipe);
+ mdp4_iommu_unmap(dtv_pipe);
+ dtv_pipe = NULL;
+ }
}
mdp4_overlay_panel_mode_unset(MDP4_MIXER1, MDP4_PANEL_DTV);
@@ -610,7 +621,8 @@
*/
temp_src_format = inpdw(rgb_base + 0x0050);
MDP_OUTP(rgb_base + 0x0050, temp_src_format | BIT(22));
- mdp4_overlay_reg_flush(dtv_pipe, 0);
+ mdp4_overlay_reg_flush(dtv_pipe, 1);
+ mdp4_mixer_stage_up(dtv_pipe);
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
}
@@ -696,11 +708,19 @@
}
mutex_lock(&mfd->dma->ov_mutex);
pipe = dtv_pipe;
+
+ if (hdmi_prim_display && (pipe->pipe_used == 0 ||
+ pipe->mixer_stage != MDP4_MIXER_STAGE_BASE)) {
+ pr_err("%s: NOT baselayer\n", __func__);
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return;
+ }
+
if (pipe->pipe_type == OVERLAY_TYPE_RGB) {
pipe->srcp0_addr = (uint32) mfd->ibuf.buf;
mdp4_overlay_rgb_setup(pipe);
}
- mdp4_overlay_reg_flush(pipe, 0);
+ mdp4_overlay_reg_flush(pipe, 1);
mdp4_mixer_stage_up(pipe);
mdp4_overlay_dtv_start();
mdp4_overlay_dtv_ov_done_push(mfd, pipe);
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index a1fecb6..18d2107 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -46,6 +46,11 @@
static struct mdp4_overlay_pipe *lcdc_pipe;
static struct completion lcdc_comp;
+void mdp4_lcdc_base_swap(struct mdp4_overlay_pipe *pipe)
+{
+ lcdc_pipe = pipe;
+}
+
int mdp_lcdc_on(struct platform_device *pdev)
{
int lcdc_width;
@@ -95,8 +100,6 @@
if (mfd->key != MFD_KEY)
return -EINVAL;
- mdp4_overlay_ctrl_db_reset();
-
fbi = mfd->fbi;
var = &fbi->var;
@@ -155,6 +158,8 @@
mdp4_overlay_dmap_cfg(mfd, 1);
mdp4_overlay_rgb_setup(pipe);
+ mdp4_overlay_reg_flush(pipe, 1);
+ mdp4_mixer_stage_up(pipe);
mdp4_overlayproc_cfg(pipe);
@@ -263,7 +268,6 @@
/* MDP cmd block enable */
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
- mdp4_mixer_pipe_cleanup(lcdc_pipe->mixer_num);
MDP_OUTP(MDP_BASE + LCDC_BASE, 0);
lcdc_enabled = 0;
/* MDP cmd block disable */
@@ -280,8 +284,18 @@
/* dis-engage rgb0 from mixer0 */
if (lcdc_pipe) {
- mdp4_mixer_stage_down(lcdc_pipe);
- mdp4_iommu_unmap(lcdc_pipe);
+ if (mfd->ref_cnt == 0) {
+ /* adb stop */
+ if (lcdc_pipe->pipe_type == OVERLAY_TYPE_BF)
+ mdp4_overlay_borderfill_stage_down(lcdc_pipe);
+
+ /* lcdc_pipe == rgb1 */
+ mdp4_overlay_unset_mixer(lcdc_pipe->mixer_num);
+ lcdc_pipe = NULL;
+ } else {
+ mdp4_mixer_stage_down(lcdc_pipe);
+ mdp4_iommu_unmap(lcdc_pipe);
+ }
}
#ifdef CONFIG_MSM_BUS_SCALING
@@ -494,7 +508,7 @@
}
}
/*
- * make sure the MIPI_DSI_WRITEBACK_SIZE defined at boardfile
+ * make sure the WRITEBACK_SIZE defined at boardfile
* has enough space h * w * 3 * 2
*/
static void mdp4_lcdc_do_blt(struct msm_fb_data_type *mfd, int enable)
@@ -585,6 +599,12 @@
mutex_lock(&mfd->dma->ov_mutex);
pipe = lcdc_pipe;
+ if (pipe->pipe_used == 0 ||
+ pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) {
+ pr_err("%s: NOT baselayer\n", __func__);
+ mutex_unlock(&mfd->dma->ov_mutex);
+ return;
+ }
if (mfd->display_iova)
pipe->srcp0_addr = mfd->display_iova + buf_offset;
@@ -592,7 +612,7 @@
pipe->srcp0_addr = (uint32)(buf + buf_offset);
mdp4_overlay_rgb_setup(pipe);
- mdp4_overlay_reg_flush(pipe, 0);
+ mdp4_overlay_reg_flush(pipe, 1);
mdp4_mixer_stage_up(pipe);
mdp4_overlay_lcdc_start();
mdp4_overlay_lcdc_vsync_push(mfd, pipe);
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 82fbb65..f192b12 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -314,6 +314,8 @@
clk_rate = mdp_get_core_clk();
mdp4_fetch_cfg(clk_rate);
+ mdp4_overlay_cfg_init();
+
/* Mark hardware as initialized. Only revisions > v2.1 have a register
* for tracking core reset status. */
if (mdp_hw_revision > MDP4_REVISION_V2_1)
@@ -378,6 +380,7 @@
outpdw(MDP_INTR_CLEAR, isr);
if (isr & INTR_PRIMARY_INTF_UDERRUN) {
+ pr_debug("%s: UNDERRUN -- primary\n", __func__);
mdp4_stat.intr_underrun_p++;
/* When underun occurs mdp clear the histogram registers
that are set before in hw_init so restore them back so
@@ -395,8 +398,10 @@
}
}
- if (isr & INTR_EXTERNAL_INTF_UDERRUN)
+ if (isr & INTR_EXTERNAL_INTF_UDERRUN) {
+ pr_debug("%s: UNDERRUN -- external\n", __func__);
mdp4_stat.intr_underrun_e++;
+ }
isr &= mask;
diff --git a/drivers/video/msm/mdp_debugfs.c b/drivers/video/msm/mdp_debugfs.c
index 7defd82..4a0ea4c 100644
--- a/drivers/video/msm/mdp_debugfs.c
+++ b/drivers/video/msm/mdp_debugfs.c
@@ -437,38 +437,38 @@
len = snprintf(bp, dlen, "frame_push:\n");
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "rgb1: %08lu\t\t",
+ len = snprintf(bp, dlen, "rgb1: %08lu\t",
mdp4_stat.pipe[OVERLAY_PIPE_RGB1]);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "rgb2: %08lu\n",
+ len = snprintf(bp, dlen, "rgb2: %08lu\n",
mdp4_stat.pipe[OVERLAY_PIPE_RGB2]);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "vg1: %08lu\t\t",
+ len = snprintf(bp, dlen, "vg1 : %08lu\t",
mdp4_stat.pipe[OVERLAY_PIPE_VG1]);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "vg2: %08lu\n",
+ len = snprintf(bp, dlen, "vg2 : %08lu\n",
mdp4_stat.pipe[OVERLAY_PIPE_VG2]);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "err_mixer: %08lu\t", mdp4_stat.err_mixer);
+ len = snprintf(bp, dlen, "err_mixer : %08lu\t", mdp4_stat.err_mixer);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "err_size : %08lu\n", mdp4_stat.err_size);
+ len = snprintf(bp, dlen, "err_size : %08lu\n", mdp4_stat.err_size);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "err_scale: %08lu\t", mdp4_stat.err_scale);
+ len = snprintf(bp, dlen, "err_scale : %08lu\t", mdp4_stat.err_scale);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "err_format: %08lu\n", mdp4_stat.err_format);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "err_play: %08lu\t", mdp4_stat.err_play);
+ len = snprintf(bp, dlen, "err_play : %08lu\t", mdp4_stat.err_play);
bp += len;
dlen -= len;
- len = snprintf(bp, dlen, "err_stage: %08lu\n", mdp4_stat.err_stage);
+ len = snprintf(bp, dlen, "err_stage : %08lu\n", mdp4_stat.err_stage);
bp += len;
dlen -= len;
len = snprintf(bp, dlen, "err_underflow: %08lu\n\n",
diff --git a/drivers/video/msm/mdp_ppp_v20.c b/drivers/video/msm/mdp_ppp_v20.c
index d271b85..418528e 100644
--- a/drivers/video/msm/mdp_ppp_v20.c
+++ b/drivers/video/msm/mdp_ppp_v20.c
@@ -2403,7 +2403,10 @@
uint32 width,
uint32 height, int bpp, MDPIBUF *iBuf, int layer)
{
- *src0 += (x + y * width) * bpp;
+ if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO && layer == 0)
+ *src0 += (x + y * ALIGN(width, 32)) * bpp;
+ else
+ *src0 += (x + y * width) * bpp;
/* if it's dest/bg buffer, we need to adjust it for rotation */
if (layer != 0)
@@ -2414,9 +2417,14 @@
* MDP_Y_CBCR_H2V2/MDP_Y_CRCB_H2V2 cosite for now
* we need to shift x direction same as y dir for offsite
*/
- *src1 +=
- ((x / h_slice) * h_slice +
- ((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
+ if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO
+ && layer == 0)
+ *src1 += ((x / h_slice) * h_slice + ((y == 0) ? 0 :
+ (((y + 1) / v_slice - 1) * (ALIGN(width/2, 32) * 2))))
+ * bpp;
+ else
+ *src1 += ((x / h_slice) * h_slice +
+ ((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp;
/* if it's dest/bg buffer, we need to adjust it for rotation */
if (layer != 0)
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
index 50c3696..8a33512 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
@@ -30,6 +30,9 @@
#define DDL_MAX_FRAME_WIDTH 1920
#define DDL_MAX_FRAME_HEIGHT 1088
+#define DDL_MAX_VC1_FRAME_WIDTH (DDL_MAX_FRAME_WIDTH)
+#define DDL_MAX_VC1_FRAME_HEIGHT (1280)
+
#define MAX_DPB_SIZE_L4PT0_MBS DDL_KILO_BYTE(32)
#define MAX_FRAME_SIZE_L4PT0_MBS DDL_KILO_BYTE(8)
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index e2c0a2a..6b8f5b2 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -312,6 +312,20 @@
return process_further;
}
break;
+ case VCD_CODEC_VC1:
+ case VCD_CODEC_VC1_RCV:
+ if ((seq_hdr_info.img_size_x >
+ DDL_MAX_VC1_FRAME_WIDTH) ||
+ (seq_hdr_info.img_size_y >
+ DDL_MAX_VC1_FRAME_HEIGHT)) {
+ DDL_MSG_ERROR("Unsupported VC1 clip: "
+ "Resolution X=%d and Y=%d",
+ seq_hdr_info.img_size_x,
+ seq_hdr_info.img_size_y);
+ ddl_client_fatal_cb(ddl);
+ return process_further;
+ }
+ break;
default:
break;
}
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index a0af4b5..f757fae 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -99,6 +99,7 @@
MDP_YCRCB_H1V1, /* YCrCb interleave */
MDP_YCBCR_H1V1, /* YCbCr interleave */
MDP_IMGTYPE_LIMIT,
+ MDP_RGB_BORDERFILL, /* border fill pipe */
MDP_BGR_565 = MDP_IMGTYPE2_START, /* BGR 565 planer */
MDP_FB_FORMAT, /* framebuffer format */
MDP_IMGTYPE_LIMIT2 /* Non valid image type after this enum */
diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h
index 42d5c21..45855b1 100644
--- a/include/linux/videodev2.h
+++ b/include/linux/videodev2.h
@@ -388,6 +388,7 @@
#define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */
#define V4L2_PIX_FMT_DIVX_311 v4l2_fourcc('D', 'I', 'V', '3') /* DIVX311 */
#define V4L2_PIX_FMT_DIVX v4l2_fourcc('D', 'I', 'V', 'X') /* DIVX */
+#define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0') /* ON2 VP8 stream */
/* Vendor-specific formats */
#define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index 0c72880..72c7e47 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -66,7 +66,8 @@
SLIM_1_TX_1 = 146, /* BT-SCO and USB RX */
SLIM_3_RX_1 = 151, /* External echo-cancellation ref */
SLIM_3_RX_2 = 152, /* External echo-cancellation ref */
- SLIM_3_TX_1 = 147, /* HDMI RX */
+ SLIM_3_TX_1 = 153, /* HDMI RX */
+ SLIM_3_TX_2 = 154, /* HDMI RX */
SLIM_4_TX_1 = 148, /* In-call recording RX */
SLIM_4_TX_2 = 149, /* In-call recording RX */
SLIM_4_RX_1 = 150, /* In-call music delivery TX */
@@ -984,6 +985,7 @@
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int ret = 0;
unsigned int rx_ch[2] = {SLIM_3_RX_1, SLIM_3_RX_2};
+ unsigned int tx_ch[2] = {SLIM_3_TX_1, SLIM_3_TX_2};
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
pr_debug("%s: slim_3_rx_ch %d, sch %d %d\n",
@@ -999,7 +1001,16 @@
goto end;
}
} else {
- pr_err("%s: SLIMBUS_3_TX not defined for this DAI\n", __func__);
+ pr_debug("%s: MDM RX -> SLIMBUS_3_TX -> APQ HDMI ch: %d, %d\n",
+ __func__, tx_ch[0], tx_ch[1]);
+
+ ret = snd_soc_dai_set_channel_map(cpu_dai, 2, tx_ch, 0, 0);
+ if (ret < 0) {
+ pr_err("%s: Erorr %d setting SLIM_3 TX channel map\n",
+ __func__, ret);
+
+ goto end;
+ }
}
end:
@@ -1238,6 +1249,22 @@
return 0;
}
+static int msm_slim_3_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ pr_debug("%s()\n", __func__);
+ rate->min = rate->max = 48000;
+ channels->min = channels->max = 2;
+
+ return 0;
+}
+
static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -1800,6 +1827,18 @@
.be_hw_params_fixup = msm_slim_3_rx_be_hw_params_fixup,
.ops = &msm_slimbus_3_be_ops,
},
+ {
+ .name = LPASS_BE_SLIMBUS_3_TX,
+ .stream_name = "Slimbus3 Capture",
+ .cpu_dai_name = "msm-dai-q6.16391",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
+ .be_hw_params_fixup = msm_slim_3_tx_be_hw_params_fixup,
+ .ops = &msm_slimbus_3_be_ops,
+ },
};
struct snd_soc_card snd_soc_card_msm = {
diff --git a/sound/soc/msm/msm-dai-q6.c b/sound/soc/msm/msm-dai-q6.c
index 284320d..965559f 100644
--- a/sound/soc/msm/msm-dai-q6.c
+++ b/sound/soc/msm/msm-dai-q6.c
@@ -606,6 +606,7 @@
case SLIMBUS_1_TX:
case SLIMBUS_2_RX:
case SLIMBUS_2_TX:
+ case SLIMBUS_3_TX:
case SLIMBUS_4_RX:
case SLIMBUS_4_TX:
rc = msm_dai_q6_slim_bus_hw_params(params, dai,
@@ -1164,6 +1165,7 @@
case SLIMBUS_0_TX:
case SLIMBUS_1_TX:
case SLIMBUS_2_TX:
+ case SLIMBUS_3_TX:
case SLIMBUS_4_TX:
/* channel number to be between 128 and 255. For RX port
* use channel numbers from 138 to 144, for TX port
@@ -1550,6 +1552,7 @@
break;
case SLIMBUS_0_TX:
case SLIMBUS_4_TX:
+ case SLIMBUS_3_TX:
rc = snd_soc_register_dai(&pdev->dev,
&msm_dai_q6_slimbus_tx_dai);
break;
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 9ca6569..217158c 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -172,6 +172,7 @@
{ SLIMBUS_4_RX, 0, 0, 0, 0, 0},
{ SLIMBUS_4_TX, 0, 0, 0, 0, 0},
{ SLIMBUS_3_RX, 0, 0, 0, 0, 0},
+ { SLIMBUS_3_TX, 0, 0, 0, 0, 0},
{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
{ SLIMBUS_EXTPROC_RX, 0, 0, 0, 0, 0},
@@ -1408,6 +1409,9 @@
SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_MI2S_TX,
MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
msm_routing_put_voice_stub_mixer),
+ SOC_SINGLE_EXT("SLIM_3_TX", MSM_BACKEND_DAI_SLIMBUS_3_TX,
+ MSM_FRONTEND_DAI_VOICE_STUB, 1, 0, msm_routing_get_voice_stub_mixer,
+ msm_routing_put_voice_stub_mixer),
};
static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
@@ -1465,6 +1469,9 @@
SOC_SINGLE_EXT("MI2S_TX", MSM_BACKEND_DAI_HDMI_RX,
MSM_BACKEND_DAI_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
+ SOC_SINGLE_EXT("SLIM_3_TX", MSM_BACKEND_DAI_HDMI_RX,
+ MSM_BACKEND_DAI_SLIMBUS_3_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
};
static const struct snd_kcontrol_new sec_i2s_rx_port_mixer_controls[] = {
@@ -1825,6 +1832,7 @@
SND_SOC_DAPM_AIF_IN("SLIMBUS_1_TX", "Slimbus1 Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_IN("STUB_1_TX", "Stub1 Capture", 0, 0, 0, 0),
SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_RX", "Slimbus3 Playback", 0, 0, 0, 0),
+ SND_SOC_DAPM_AIF_IN("SLIMBUS_3_TX", "Slimbus3 Capture", 0, 0, 0, 0),
/* Switch Definitions */
SND_SOC_DAPM_SWITCH("SLIMBUS_DL_HL", SND_SOC_NOPM, 0, 0,
@@ -2103,6 +2111,7 @@
{"Voice Stub Tx Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
{"Voice Stub Tx Mixer", "STUB_1_TX_HL", "STUB_1_TX"},
{"Voice Stub Tx Mixer", "MI2S_TX", "MI2S_TX"},
+ {"Voice Stub Tx Mixer", "SLIM_3_TX", "SLIMBUS_3_TX"},
{"VOICE_STUB_UL", NULL, "Voice Stub Tx Mixer"},
{"STUB_RX Mixer", "Voice Stub", "VOICE_STUB_DL"},
@@ -2112,6 +2121,7 @@
{"INTERNAL_BT_SCO_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
{"MI2S_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
{"MI2S_RX", NULL, "MI2S_RX_Voice Mixer"},
+ {"HDMI_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
{"SLIMBUS_3_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"},
{"SLIMBUS_3_RX", NULL, "SLIMBUS_3_RX_Voice Mixer"},
@@ -2126,6 +2136,7 @@
{"HDMI_RX Port Mixer", "MI2S_TX", "MI2S_TX"},
+ {"HDMI_RX Port Mixer", "SLIM_3_TX", "SLIMBUS_3_TX"},
{"HDMI", NULL, "HDMI_RX Port Mixer"},
{"SEC_I2S_RX Port Mixer", "MI2S_TX", "MI2S_TX"},
diff --git a/sound/soc/msm/msm-pcm-routing.h b/sound/soc/msm/msm-pcm-routing.h
index 5f5c12a..e1a0e6c 100644
--- a/sound/soc/msm/msm-pcm-routing.h
+++ b/sound/soc/msm/msm-pcm-routing.h
@@ -39,6 +39,7 @@
#define LPASS_BE_SLIMBUS_1_TX "(Backend) SLIMBUS_1_TX"
#define LPASS_BE_STUB_1_TX "(Backend) STUB_1_TX"
#define LPASS_BE_SLIMBUS_3_RX "(Backend) SLIMBUS_3_RX"
+#define LPASS_BE_SLIMBUS_3_TX "(Backend) SLIMBUS_3_TX"
#define LPASS_BE_SLIMBUS_4_RX "(Backend) SLIMBUS_4_RX"
#define LPASS_BE_SLIMBUS_4_TX "(Backend) SLIMBUS_4_TX"
@@ -90,6 +91,7 @@
MSM_BACKEND_DAI_SLIMBUS_4_RX,
MSM_BACKEND_DAI_SLIMBUS_4_TX,
MSM_BACKEND_DAI_SLIMBUS_3_RX,
+ MSM_BACKEND_DAI_SLIMBUS_3_TX,
MSM_BACKEND_DAI_EXTPROC_RX,
MSM_BACKEND_DAI_EXTPROC_TX,
MSM_BACKEND_DAI_EXTPROC_EC_TX,
diff --git a/sound/soc/msm/qdsp6/q6afe.c b/sound/soc/msm/qdsp6/q6afe.c
index 51ef359..ce81cca 100644
--- a/sound/soc/msm/qdsp6/q6afe.c
+++ b/sound/soc/msm/qdsp6/q6afe.c
@@ -167,6 +167,7 @@
case SLIMBUS_0_TX:
case SLIMBUS_1_TX:
case SLIMBUS_2_TX:
+ case SLIMBUS_3_TX:
case INT_FM_TX:
case VOICE_RECORD_RX:
case INT_BT_SCO_TX:
@@ -210,6 +211,7 @@
case SLIMBUS_2_RX:
case SLIMBUS_2_TX:
case SLIMBUS_3_RX:
+ case SLIMBUS_3_TX:
case INT_BT_SCO_RX:
case INT_BT_SCO_TX:
case INT_BT_A2DP_RX:
@@ -277,6 +279,7 @@
case SLIMBUS_2_RX: return IDX_SLIMBUS_2_RX;
case SLIMBUS_2_TX: return IDX_SLIMBUS_2_TX;
case SLIMBUS_3_RX: return IDX_SLIMBUS_3_RX;
+ case SLIMBUS_3_TX: return IDX_SLIMBUS_3_TX;
case INT_BT_SCO_RX: return IDX_INT_BT_SCO_RX;
case INT_BT_SCO_TX: return IDX_INT_BT_SCO_TX;
case INT_BT_A2DP_RX: return IDX_INT_BT_A2DP_RX;
@@ -313,6 +316,7 @@
case SLIMBUS_2_RX:
case SLIMBUS_2_TX:
case SLIMBUS_3_RX:
+ case SLIMBUS_3_TX:
case SLIMBUS_4_RX:
case SLIMBUS_4_TX:
ret_size = SIZEOF_CFG_CMD(afe_port_slimbus_sch_cfg);