Merge "msm: mdss: indicate splash screen condition explicitly"
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
index e8b02cf..b88c3ce 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-ctrl.txt
@@ -6,8 +6,12 @@
Required properties:
- compatible: Must be "qcom,mdss-dsi-ctrl"
- cell-index: Specifies the controller used among the two controllers.
-- reg: Offset and length of the register regions(s) for the device.
+- reg: Base address and length of the different register
+ regions(s) required for DSI device functionality.
- reg-names: A list of strings that map in order to the list of regs.
+ "dsi_ctrl" - MDSS DSI controller register region
+ "dsi_phy" - MDSS DSI PHY register region
+ "mmss_misc_phys" - Register region for MMSS DSI clamps
- vdd-supply: Phandle for vdd regulator device node.
- vddio-supply: Phandle for vdd-io regulator device node.
- vdda-supply: Phandle for vreg regulator device node.
@@ -53,9 +57,10 @@
compatible = "qcom,mdss-dsi-ctrl";
label = "MDSS DSI CTRL->0";
cell-index = <0>;
- reg = <0xfd922800 0x600>,
+ reg = <0xfd922800 0x1f8>,
+ <0xfd922b00 0x2b0>,
<0xfd828000 0x108>;
- reg-names = "dsi_phys", "mmss_misc_phys";
+ reg-names = "dsi_ctrl", "dsi_phy", "mmss_misc_phys";
vdd-supply = <&pm8226_l15>;
vddio-supply = <&pm8226_l8>;
vdda-supply = <&pm8226_l4>;
diff --git a/arch/arm/boot/dts/msm8226-mdss.dtsi b/arch/arm/boot/dts/msm8226-mdss.dtsi
index 68521bc..5edc43b 100644
--- a/arch/arm/boot/dts/msm8226-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8226-mdss.dtsi
@@ -99,9 +99,10 @@
compatible = "qcom,mdss-dsi-ctrl";
label = "MDSS DSI CTRL->0";
cell-index = <0>;
- reg = <0xfd922800 0x600>,
+ reg = <0xfd922800 0x1f8>,
+ <0xfd922b00 0x2b0>,
<0xfd828000 0x108>;
- reg-names = "dsi_phys", "mmss_misc_phys";
+ reg-names = "dsi_ctrl", "dsi_phy", "mmss_misc_phys";
qcom,mdss-fb-map = <&mdss_fb0>;
qcom,mdss-mdp = <&mdss_mdp>;
vdd-supply = <&pm8226_l15>;
diff --git a/arch/arm/boot/dts/msm8974-mdss.dtsi b/arch/arm/boot/dts/msm8974-mdss.dtsi
index b41ab6c..d83a235 100644
--- a/arch/arm/boot/dts/msm8974-mdss.dtsi
+++ b/arch/arm/boot/dts/msm8974-mdss.dtsi
@@ -122,9 +122,10 @@
compatible = "qcom,mdss-dsi-ctrl";
label = "MDSS DSI CTRL->0";
cell-index = <0>;
- reg = <0xfd922800 0x600>,
+ reg = <0xfd922800 0x1f8>,
+ <0xfd922b00 0x2b0>,
<0xfdf30000 0x108>;
- reg-names = "dsi_phys", "mmss_misc_phys";
+ reg-names = "dsi_ctrl", "dsi_phy", "mmss_misc_phys";
vdd-supply = <&pm8941_l22>;
vddio-supply = <&pm8941_l12>;
vdda-supply = <&pm8941_l2>;
@@ -180,9 +181,10 @@
compatible = "qcom,mdss-dsi-ctrl";
label = "MDSS DSI CTRL->1";
cell-index = <1>;
- reg = <0xfd922e00 0x600>,
+ reg = <0xfd922e00 0x1f8>,
+ <0xfd923100 0x2b0>,
<0xfdf30000 0x108>;
- reg-names = "dsi_phys", "mmss_misc_phys";
+ reg-names = "dsi_ctrl", "dsi_phy", "mmss_misc_phys";
vdd-supply = <&pm8941_l22>;
vddio-supply = <&pm8941_l12>;
vdda-supply = <&pm8941_l2>;
diff --git a/arch/arm/configs/apq8084_defconfig b/arch/arm/configs/apq8084_defconfig
index 823e4f8..2f5e776 100644
--- a/arch/arm/configs/apq8084_defconfig
+++ b/arch/arm/configs/apq8084_defconfig
@@ -365,6 +365,7 @@
CONFIG_QPNP_CLKDIV=y
CONFIG_MSM_IOMMU_V1=y
CONFIG_IOMMU_PGTABLES_L2=y
+CONFIG_MSM_IOMMU_VBIF_CHECK=y
CONFIG_IOMMU_NON_SECURE=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
diff --git a/arch/arm/configs/msm8226-perf_defconfig b/arch/arm/configs/msm8226-perf_defconfig
index 9debb02..b0f52b2 100644
--- a/arch/arm/configs/msm8226-perf_defconfig
+++ b/arch/arm/configs/msm8226-perf_defconfig
@@ -427,6 +427,7 @@
CONFIG_QPNP_VIBRATOR=y
CONFIG_QPNP_REVID=y
CONFIG_MSM_IOMMU_V1=y
+CONFIG_MSM_IOMMU_VBIF_CHECK=y
CONFIG_EXT2_FS=y
CONFIG_EXT2_FS_XATTR=y
CONFIG_EXT3_FS=y
diff --git a/arch/arm/configs/msm8226_defconfig b/arch/arm/configs/msm8226_defconfig
index 38171e6..c7af9f9 100644
--- a/arch/arm/configs/msm8226_defconfig
+++ b/arch/arm/configs/msm8226_defconfig
@@ -451,6 +451,7 @@
CONFIG_QPNP_VIBRATOR=y
CONFIG_QPNP_REVID=y
CONFIG_MSM_IOMMU_V1=y
+CONFIG_MSM_IOMMU_VBIF_CHECK=y
CONFIG_CORESIGHT=y
CONFIG_CORESIGHT_FUSE=y
CONFIG_CORESIGHT_TMC=y
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 915b1c3..0421131 100755
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -463,6 +463,7 @@
CONFIG_QPNP_COINCELL=y
CONFIG_MSM_IOMMU_V1=y
CONFIG_IOMMU_PGTABLES_L2=y
+CONFIG_MSM_IOMMU_VBIF_CHECK=y
CONFIG_MOBICORE_SUPPORT=m
CONFIG_MOBICORE_API=m
CONFIG_BIF=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 55f0c3e..3c3de4a 100755
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -488,6 +488,7 @@
CONFIG_MSM_IOMMU_V1=y
CONFIG_MSM_IOMMU_PMON=y
CONFIG_IOMMU_PGTABLES_L2=y
+CONFIG_MSM_IOMMU_VBIF_CHECK=y
CONFIG_MOBICORE_SUPPORT=m
CONFIG_MOBICORE_API=m
CONFIG_CORESIGHT=y
diff --git a/arch/arm/mach-msm/clock-8226.c b/arch/arm/mach-msm/clock-8226.c
index 08a6427..7a7c008 100644
--- a/arch/arm/mach-msm/clock-8226.c
+++ b/arch/arm/mach-msm/clock-8226.c
@@ -3410,13 +3410,13 @@
/* MM sensor clocks */
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6f.qcom,camera"),
- CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "90.qcom,camera"),
+ CLK_LOOKUP("cam_src_clk", mclk1_clk_src.c, "90.qcom,camera"),
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6d.qcom,camera"),
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6a.qcom,camera"),
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "6c.qcom,camera"),
CLK_LOOKUP("cam_src_clk", mclk0_clk_src.c, "20.qcom,camera"),
CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6f.qcom,camera"),
- CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "90.qcom,camera"),
+ CLK_LOOKUP("cam_clk", camss_mclk1_clk.c, "90.qcom,camera"),
CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6d.qcom,camera"),
CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6a.qcom,camera"),
CLK_LOOKUP("cam_clk", camss_mclk0_clk.c, "6c.qcom,camera"),
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index c4db727..0f69a7b 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -86,6 +86,7 @@
* struct msm_iommu_drvdata - A single IOMMU hardware instance
* @base: IOMMU config port base address (VA)
* @glb_base: IOMMU config port base address for global register space (VA)
+ * @phys_base: IOMMU physical base address.
* @ncb The number of contexts on this IOMMU
* @irq: Interrupt number
* @clk: The bus clock for this IOMMU hardware instance
@@ -108,6 +109,7 @@
*/
struct msm_iommu_drvdata {
void __iomem *base;
+ phys_addr_t phys_base;
void __iomem *glb_base;
int ncb;
int ttbr_split;
diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-v1.h b/arch/arm/mach-msm/include/mach/iommu_hw-v1.h
index 04cd441..4509092 100644
--- a/arch/arm/mach-msm/include/mach/iommu_hw-v1.h
+++ b/arch/arm/mach-msm/include/mach/iommu_hw-v1.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. 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
@@ -16,17 +16,19 @@
#define CTX_SHIFT 12
#define CTX_OFFSET 0x8000
-#define GET_GLOBAL_REG(reg, base) (readl_relaxed((base) + (reg)))
-#define GET_CTX_REG(reg, base, ctx) \
- (readl_relaxed((base) + CTX_OFFSET + (reg) + ((ctx) << CTX_SHIFT)))
-#define GET_CTX_REG_L(reg, base, ctx) \
- (readll_relaxed((base) + CTX_OFFSET + (reg) + ((ctx) << CTX_SHIFT)))
+#define CTX_REG(reg, base, ctx) \
+ ((base) + CTX_OFFSET + (reg) + ((ctx) << CTX_SHIFT))
+#define GLB_REG(reg, base) \
+ ((base) + (reg))
+
+#define GET_GLOBAL_REG(reg, base) (readl_relaxed(GLB_REG(reg, base)))
+#define GET_CTX_REG(reg, base, ctx) (readl_relaxed(CTX_REG(reg, base, ctx)))
+#define GET_CTX_REG_L(reg, base, ctx) (readll_relaxed(CTX_REG(reg, base, ctx)))
#define SET_GLOBAL_REG(reg, base, val) writel_relaxed((val), ((base) + (reg)))
#define SET_CTX_REG(reg, base, ctx, val) \
- writel_relaxed((val), \
- ((base) + CTX_OFFSET + (reg) + ((ctx) << CTX_SHIFT)))
+ writel_relaxed((val), (CTX_REG(reg, base, ctx)))
/* Wrappers for numbered registers */
#define SET_GLOBAL_REG_N(b, n, r, v) SET_GLOBAL_REG((b), ((r) + (n << 2)), (v))
@@ -150,6 +152,11 @@
SET_GLOBAL_FIELD(b, MICRO_MMU_CTRL, HALT_REQ, v)
#define GET_MICRO_MMU_CTRL_IDLE(b) \
GET_GLOBAL_FIELD(b, MICRO_MMU_CTRL, IDLE)
+#define SET_MICRO_MMU_CTRL_RESERVED(b, v) \
+ SET_GLOBAL_FIELD(b, MICRO_MMU_CTRL, RESERVED, v)
+
+#define MMU_CTRL_IDLE (MICRO_MMU_CTRL_IDLE_MASK << MICRO_MMU_CTRL_IDLE_SHIFT)
+
#define SET_PREDICTIONDIS0(b, v) SET_GLOBAL_REG(PREDICTIONDIS0, (b), (v))
#define SET_PREDICTIONDIS1(b, v) SET_GLOBAL_REG(PREDICTIONDIS1, (b), (v))
#define SET_S1L1BFBLP0(b, v) SET_GLOBAL_REG(S1L1BFBLP0, (b), (v))
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index a291b90..b0a1a7c 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. 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
@@ -708,8 +708,10 @@
static int switch_to_using_ldo(struct krait_power_vreg *kvreg)
{
- if (kvreg->mode == LDO_MODE
- && get_krait_ldo_uv(kvreg) == kvreg->uV - kvreg->ldo_delta_uV)
+ int uV = kvreg->uV - kvreg->ldo_delta_uV;
+ int ldo_uV = DIV_ROUND_UP(uV, KRAIT_LDO_STEP) * KRAIT_LDO_STEP;
+
+ if (kvreg->mode == LDO_MODE && get_krait_ldo_uv(kvreg) == ldo_uV)
return 0;
return smp_call_function_single(kvreg->cpu_num,
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 3196911..695095f 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -1960,6 +1960,10 @@
for (i = 6; i < FT_DETECT_REGS_COUNT; i++)
ft_detect_regs[i] = 0;
+ /* turn on hang interrupt for a330v2 by default */
+ if (adreno_is_a330v2(adreno_dev))
+ set_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv);
+
ret = adreno_perfcounter_init(device);
if (ret)
goto done;
@@ -2537,6 +2541,88 @@
return snprintf(buf, PAGE_SIZE, "%d\n", _wake_timeout);
}
+/**
+ * _ft_hang_intr_status_store - Routine to enable/disable h/w hang interrupt
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value to write
+ * @count: size of the value to write
+ */
+static ssize_t _ft_hang_intr_status_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ unsigned int new_setting, old_setting;
+ struct kgsl_device *device = kgsl_device_from_dev(dev);
+ struct adreno_device *adreno_dev;
+ int ret;
+ if (device == NULL)
+ return 0;
+ adreno_dev = ADRENO_DEVICE(device);
+
+ mutex_lock(&device->mutex);
+ ret = _ft_sysfs_store(buf, count, &new_setting);
+ if (ret != count)
+ goto done;
+ if (new_setting)
+ new_setting = 1;
+ old_setting =
+ (test_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv) ? 1 : 0);
+ if (new_setting != old_setting) {
+ if (new_setting)
+ set_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv);
+ else
+ clear_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv);
+ /* Set the new setting based on device state */
+ switch (device->state) {
+ case KGSL_STATE_NAP:
+ case KGSL_STATE_SLEEP:
+ kgsl_pwrctrl_wake(device, 0);
+ case KGSL_STATE_ACTIVE:
+ adreno_dev->gpudev->irq_control(adreno_dev, 1);
+ /*
+ * For following states setting will be picked up on device
+ * start. Still need them in switch statement to differentiate
+ * from default
+ */
+ case KGSL_STATE_SLUMBER:
+ case KGSL_STATE_SUSPEND:
+ break;
+ default:
+ ret = -EACCES;
+ /* reset back to old setting on error */
+ if (new_setting)
+ clear_bit(ADRENO_DEVICE_HANG_INTR,
+ &adreno_dev->priv);
+ else
+ set_bit(ADRENO_DEVICE_HANG_INTR,
+ &adreno_dev->priv);
+ goto done;
+ }
+ }
+done:
+ mutex_unlock(&device->mutex);
+ return ret;
+}
+
+/**
+ * _ft_hang_intr_status_show() - Routine to read hardware hang interrupt
+ * enablement
+ * @dev: device ptr
+ * @attr: Device attribute
+ * @buf: value read
+ */
+static ssize_t _ft_hang_intr_status_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct adreno_device *adreno_dev = _get_adreno_dev(dev);
+ if (adreno_dev == NULL)
+ return 0;
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ test_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv) ? 1 : 0);
+}
+
#define FT_DEVICE_ATTR(name) \
DEVICE_ATTR(name, 0644, _ ## name ## _show, _ ## name ## _store);
@@ -2544,6 +2630,7 @@
FT_DEVICE_ATTR(ft_pagefault_policy);
FT_DEVICE_ATTR(ft_fast_hang_detect);
FT_DEVICE_ATTR(ft_long_ib_detect);
+FT_DEVICE_ATTR(ft_hang_intr_status);
static DEVICE_INT_ATTR(wake_nice, 0644, _wake_nice);
static FT_DEVICE_ATTR(wake_timeout);
@@ -2555,6 +2642,7 @@
&dev_attr_ft_long_ib_detect,
&dev_attr_wake_nice.attr,
&dev_attr_wake_timeout,
+ &dev_attr_ft_hang_intr_status,
NULL,
};
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 9092a03..976a355 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -217,6 +217,7 @@
ADRENO_DEVICE_PWRON_FIXUP = 1,
ADRENO_DEVICE_INITIALIZED = 2,
ADRENO_DEVICE_STARTED = 3,
+ ADRENO_DEVICE_HANG_INTR = 4,
};
#define PERFCOUNTER_FLAG_NONE 0x0
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 47ba854..2faa278 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -3039,6 +3039,25 @@
return 0;
}
+static void a3xx_fatal_err_callback(struct adreno_device *adreno_dev, int bit)
+{
+ struct kgsl_device *device = &adreno_dev->dev;
+ const char *err = "";
+
+ switch (bit) {
+ case A3XX_INT_MISC_HANG_DETECT:
+ err = "MISC: GPU hang detected\n";
+ break;
+ default:
+ return;
+ }
+ KGSL_DRV_CRIT(device, "%s\n", err);
+ kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
+
+ /* Trigger a fault in the dispatcher - this will effect a restart */
+ adreno_dispatcher_irq_fault(device);
+}
+
static void a3xx_err_callback(struct adreno_device *adreno_dev, int bit)
{
struct kgsl_device *device = &adreno_dev->dev;
@@ -3063,7 +3082,7 @@
/* Clear the error */
kgsl_regwrite(device, A3XX_RBBM_AHB_CMD, (1 << 3));
- goto done;
+ return;
}
case A3XX_INT_RBBM_REG_TIMEOUT:
err = "RBBM: AHB register timeout";
@@ -3100,14 +3119,10 @@
"CP | Protected mode error| %s | addr=%x\n",
reg & (1 << 24) ? "WRITE" : "READ",
(reg & 0x1FFFF) >> 2);
- goto done;
}
case A3XX_INT_CP_AHB_ERROR_HALT:
err = "ringbuffer AHB error interrupt";
break;
- case A3XX_INT_MISC_HANG_DETECT:
- err = "MISC: GPU hang detected";
- break;
case A3XX_INT_UCHE_OOB_ACCESS:
err = "UCHE: Out of bounds access";
break;
@@ -3115,11 +3130,6 @@
return;
}
KGSL_DRV_CRIT(device, "%s\n", err);
- kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
-
-done:
- /* Trigger a fault in the dispatcher - this will effect a restart */
- adreno_dispatcher_irq_fault(device);
}
static void a3xx_cp_callback(struct adreno_device *adreno_dev, int irq)
@@ -3561,7 +3571,7 @@
A3XX_IRQ_CALLBACK(a3xx_err_callback), /* 21 - CP_AHB_ERROR_FAULT */
A3XX_IRQ_CALLBACK(NULL), /* 22 - Unused */
A3XX_IRQ_CALLBACK(NULL), /* 23 - Unused */
- A3XX_IRQ_CALLBACK(NULL), /* 24 - MISC_HANG_DETECT */
+ A3XX_IRQ_CALLBACK(a3xx_fatal_err_callback),/* 24 - MISC_HANG_DETECT */
A3XX_IRQ_CALLBACK(a3xx_err_callback), /* 25 - UCHE_OOB_ACCESS */
/* 26 to 31 - Unused */
};
@@ -3602,7 +3612,9 @@
struct kgsl_device *device = &adreno_dev->dev;
if (state)
- kgsl_regwrite(device, A3XX_RBBM_INT_0_MASK, A3XX_INT_MASK);
+ kgsl_regwrite(device, A3XX_RBBM_INT_0_MASK, A3XX_INT_MASK |
+ (test_bit(ADRENO_DEVICE_HANG_INTR, &adreno_dev->priv) ?
+ (1 << A3XX_INT_MISC_HANG_DETECT) : 0));
else
kgsl_regwrite(device, A3XX_RBBM_INT_0_MASK, 0);
}
@@ -4193,9 +4205,12 @@
/* Turn on hang detection - this spews a lot of useful information
* into the RBBM registers on a hang */
-
- kgsl_regwrite(device, A3XX_RBBM_INTERFACE_HANG_INT_CTL,
- (1 << 16) | 0xFFF);
+ if (adreno_is_a330v2(adreno_dev))
+ kgsl_regwrite(device, A3XX_RBBM_INTERFACE_HANG_INT_CTL,
+ (1 << 31) | 0xFFFF);
+ else
+ kgsl_regwrite(device, A3XX_RBBM_INTERFACE_HANG_INT_CTL,
+ (1 << 16) | 0xFFF);
/* Enable 64-byte cacheline size. HW Default is 32-byte (0x000000E0). */
kgsl_regwrite(device, A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001);
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index ab9d220..7aae397 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -947,6 +947,12 @@
if (dispatcher->inflight == 0) {
KGSL_DRV_WARN(device,
"dispatcher_do_fault with 0 inflight commands\n");
+ /*
+ * For certain faults like h/w fault the interrupts are
+ * turned off, re-enable here
+ */
+ if (kgsl_pwrctrl_isenabled(device))
+ kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
return 0;
}
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 656d7e2..fb9bdb1 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -78,7 +78,7 @@
};
static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state,
- int requested_state);
+ int requested_state);
static void kgsl_pwrctrl_axi(struct kgsl_device *device, int state);
static void kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state);
@@ -883,7 +883,7 @@
}
}
-static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state,
+void kgsl_pwrctrl_clk(struct kgsl_device *device, int state,
int requested_state)
{
struct kgsl_pwrctrl *pwr = &device->pwrctrl;
diff --git a/drivers/input/misc/mma8x5x.c b/drivers/input/misc/mma8x5x.c
index a605720..d576752 100644
--- a/drivers/input/misc/mma8x5x.c
+++ b/drivers/input/misc/mma8x5x.c
@@ -503,9 +503,12 @@
{
struct mma8x5x_data *pdata = container_of((struct delayed_work *)work,
struct mma8x5x_data, dwork);
- mma8x5x_report_data(pdata);
- schedule_delayed_work(&pdata->dwork,
- msecs_to_jiffies(pdata->poll_delay));
+
+ if ((pdata->active & MMA_STATE_MASK) == MMA_ACTIVED) {
+ mma8x5x_report_data(pdata);
+ schedule_delayed_work(&pdata->dwork,
+ msecs_to_jiffies(pdata->poll_delay));
+ }
}
static irqreturn_t mma8x5x_interrupt(int vec, void *data)
@@ -570,9 +573,9 @@
dev_err(&client->dev, "change device state failed!");
goto err_failed;
}
-
- schedule_delayed_work(&pdata->dwork,
- msecs_to_jiffies(pdata->poll_delay));
+ if (!pdata->use_int)
+ schedule_delayed_work(&pdata->dwork,
+ msecs_to_jiffies(pdata->poll_delay));
pdata->active = MMA_ACTIVED;
dev_dbg(&client->dev, "%s:mma enable setting active.\n",
@@ -580,8 +583,6 @@
}
} else if (enable == 0) {
if (pdata->active == MMA_ACTIVED) {
- cancel_delayed_work_sync(&pdata->dwork);
-
val = i2c_smbus_read_byte_data(client,
MMA8X5X_CTRL_REG1);
if (val < 0) {
@@ -596,7 +597,10 @@
dev_err(&client->dev, "change device state failed!");
goto err_failed;
}
-
+ /*
+ * Set standby state,
+ * polling work queue will stop after next call.
+ */
pdata->active = MMA_STANDBY;
dev_dbg(&client->dev, "%s:mma enable setting inactive.\n",
__func__);
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 8e70129..cb1dbd4 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -87,6 +87,16 @@
section mappings and TLB misses should be quite infrequent.
Most people can probably say Y here.
+config MSM_IOMMU_VBIF_CHECK
+ bool "Enable support for VBIF check when IOMMU gets stuck"
+ depends on MSM_IOMMU
+ help
+ Enables an extra check in the IOMMU driver that logs debugging
+ information when TLB sync or iommu halt issue occurs. This helps
+ in debugging such issues.
+
+ If unsure, say N here.
+
config IOMMU_NON_SECURE
bool "Turns on programming of secure SMMU by kernel"
depends on MSM_IOMMU
diff --git a/drivers/iommu/msm_iommu-v1.c b/drivers/iommu/msm_iommu-v1.c
index 84f81bf..911a9e7 100644
--- a/drivers/iommu/msm_iommu-v1.c
+++ b/drivers/iommu/msm_iommu-v1.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. 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
@@ -16,6 +16,7 @@
#include <linux/platform_device.h>
#include <linux/errno.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/mutex.h>
@@ -143,13 +144,141 @@
.iommu_lock_release = _iommu_lock_release,
};
-void iommu_halt(const struct msm_iommu_drvdata *iommu_drvdata)
+#ifdef CONFIG_MSM_IOMMU_VBIF_CHECK
+
+#define VBIF_XIN_HALT_CTRL0 0x200
+#define VBIF_XIN_HALT_CTRL1 0x204
+#define VBIF_AXI_HALT_CTRL0 0x208
+#define VBIF_AXI_HALT_CTRL1 0x20C
+
+static void __halt_vbif_xin(void __iomem *vbif_base)
+{
+ pr_err("Halting VBIF_XIN\n");
+ writel_relaxed(0xFFFFFFFF, vbif_base + VBIF_XIN_HALT_CTRL0);
+}
+
+static void __dump_vbif_state(void __iomem *base, void __iomem *vbif_base)
+{
+ unsigned int reg_val;
+
+ reg_val = readl_relaxed(base + MICRO_MMU_CTRL);
+ pr_err("Value of SMMU_IMPLDEF_MICRO_MMU_CTRL = 0x%x\n", reg_val);
+
+ reg_val = readl_relaxed(vbif_base + VBIF_XIN_HALT_CTRL0);
+ pr_err("Value of VBIF_XIN_HALT_CTRL0 = 0x%x\n", reg_val);
+ reg_val = readl_relaxed(vbif_base + VBIF_XIN_HALT_CTRL1);
+ pr_err("Value of VBIF_XIN_HALT_CTRL1 = 0x%x\n", reg_val);
+ reg_val = readl_relaxed(vbif_base + VBIF_AXI_HALT_CTRL0);
+ pr_err("Value of VBIF_AXI_HALT_CTRL0 = 0x%x\n", reg_val);
+ reg_val = readl_relaxed(vbif_base + VBIF_AXI_HALT_CTRL1);
+ pr_err("Value of VBIF_AXI_HALT_CTRL1 = 0x%x\n", reg_val);
+}
+
+static int __check_vbif_state(struct msm_iommu_drvdata const *drvdata)
+{
+ phys_addr_t addr = (phys_addr_t) (drvdata->phys_base
+ - (phys_addr_t) 0x4000);
+ void __iomem *base = ioremap(addr, 0x1000);
+ int ret = 0;
+
+ if (base) {
+ __dump_vbif_state(drvdata->base, base);
+ __halt_vbif_xin(drvdata->base);
+ __dump_vbif_state(drvdata->base, base);
+ iounmap(base);
+ } else {
+ pr_err("%s: Unable to ioremap\n", __func__);
+ ret = -ENOMEM;
+ }
+ return ret;
+}
+
+static void check_halt_state(struct msm_iommu_drvdata const *drvdata)
+{
+ int res;
+ unsigned int val;
+ void __iomem *base = drvdata->base;
+ char const *name = drvdata->name;
+
+ pr_err("Timed out waiting for IOMMU halt to complete for %s\n", name);
+ res = __check_vbif_state(drvdata);
+ if (res)
+ BUG();
+
+ pr_err("Checking if IOMMU halt completed for %s\n", name);
+
+ res = readl_tight_poll_timeout(
+ GLB_REG(MICRO_MMU_CTRL, base), val,
+ (val & MMU_CTRL_IDLE) == MMU_CTRL_IDLE, 5000000);
+
+ if (res) {
+ pr_err("Timed out (again) waiting for IOMMU halt to complete for %s\n",
+ name);
+ } else {
+ pr_err("IOMMU halt completed. VBIF FIFO most likely not getting drained by master\n");
+ }
+ BUG();
+}
+
+static void check_tlb_sync_state(struct msm_iommu_drvdata const *drvdata,
+ int ctx)
+{
+ int res;
+ unsigned int val;
+ void __iomem *base = drvdata->base;
+ char const *name = drvdata->name;
+
+ pr_err("Timed out waiting for TLB SYNC to complete for %s\n", name);
+ res = __check_vbif_state(drvdata);
+ if (res)
+ BUG();
+
+ pr_err("Checking if TLB sync completed for %s\n", name);
+
+ res = readl_tight_poll_timeout(CTX_REG(CB_TLBSTATUS, base, ctx), val,
+ (val & CB_TLBSTATUS_SACTIVE) == 0, 5000000);
+ if (res) {
+ pr_err("Timed out (again) waiting for TLB SYNC to complete for %s\n",
+ name);
+ } else {
+ pr_err("TLB Sync completed. VBIF FIFO most likely not getting drained by master\n");
+ }
+ BUG();
+}
+
+#else
+
+/*
+ * For targets without VBIF or for targets with the VBIF check disabled
+ * we directly just crash to capture the issue
+ */
+static void check_halt_state(struct msm_iommu_drvdata const *drvdata)
+{
+ BUG();
+}
+
+static void check_tlb_sync_state(struct msm_iommu_drvdata const *drvdata,
+ int ctx)
+{
+ BUG();
+}
+
+#endif
+
+void iommu_halt(struct msm_iommu_drvdata const *iommu_drvdata)
{
if (iommu_drvdata->halt_enabled) {
- SET_MICRO_MMU_CTRL_HALT_REQ(iommu_drvdata->base, 1);
+ unsigned int val;
+ void __iomem *base = iommu_drvdata->base;
+ int res;
- while (GET_MICRO_MMU_CTRL_IDLE(iommu_drvdata->base) == 0)
- cpu_relax();
+ SET_MICRO_MMU_CTRL_HALT_REQ(base, 1);
+ res = readl_tight_poll_timeout(
+ GLB_REG(MICRO_MMU_CTRL, base), val,
+ (val & MMU_CTRL_IDLE) == MMU_CTRL_IDLE, 5000000);
+
+ if (res)
+ check_halt_state(iommu_drvdata);
/* Ensure device is idle before continuing */
mb();
}
@@ -173,15 +302,19 @@
}
}
-static void __sync_tlb(void __iomem *base, int ctx)
+static void __sync_tlb(struct msm_iommu_drvdata *iommu_drvdata, int ctx)
{
+ unsigned int val;
+ unsigned int res;
+ void __iomem *base = iommu_drvdata->base;
+
SET_TLBSYNC(base, ctx, 0);
-
- /* No barrier needed due to register proximity */
- while (GET_CB_TLBSTATUS_SACTIVE(base, ctx))
- cpu_relax();
-
/* No barrier needed due to read dependency */
+
+ res = readl_tight_poll_timeout(CTX_REG(CB_TLBSTATUS, base, ctx), val,
+ (val & CB_TLBSTATUS_SACTIVE) == 0, 5000000);
+ if (res)
+ check_tlb_sync_state(iommu_drvdata, ctx);
}
static int __flush_iotlb_va(struct iommu_domain *domain, unsigned int va)
@@ -205,7 +338,7 @@
SET_TLBIVA(iommu_drvdata->base, ctx_drvdata->num,
ctx_drvdata->asid | (va & CB_TLBIVA_VA));
mb();
- __sync_tlb(iommu_drvdata->base, ctx_drvdata->num);
+ __sync_tlb(iommu_drvdata, ctx_drvdata->num);
__disable_clocks(iommu_drvdata);
}
fail:
@@ -232,7 +365,7 @@
SET_TLBIASID(iommu_drvdata->base, ctx_drvdata->num,
ctx_drvdata->asid);
mb();
- __sync_tlb(iommu_drvdata->base, ctx_drvdata->num);
+ __sync_tlb(iommu_drvdata, ctx_drvdata->num);
__disable_clocks(iommu_drvdata);
}
diff --git a/drivers/iommu/msm_iommu_dev-v1.c b/drivers/iommu/msm_iommu_dev-v1.c
index a9d164e..ff6b58c 100644
--- a/drivers/iommu/msm_iommu_dev-v1.c
+++ b/drivers/iommu/msm_iommu_dev-v1.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. 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
@@ -299,6 +299,7 @@
if (!drvdata->base)
return -ENOMEM;
+ drvdata->phys_base = r->start;
drvdata->glb_base = drvdata->base;
if (of_get_property(pdev->dev.of_node, "vdd-supply", NULL)) {
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index e443e9a..c3fb176 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -13,7 +13,7 @@
#include <linux/module.h>
#include <mach/iommu.h>
#include <linux/ratelimit.h>
-
+#include <asm/div64.h>
#include "msm_isp40.h"
#include "msm_isp_util.h"
#include "msm_isp_axi_util.h"
@@ -36,8 +36,8 @@
#define VFE40_8x26_VERSION 0x20000013
#define VFE40_8x26V2_VERSION 0x20010014
-#define VFE40_BURST_LEN 3
-#define VFE40_STATS_BURST_LEN 2
+#define VFE40_BURST_LEN 1
+#define VFE40_STATS_BURST_LEN 1
#define VFE40_UB_SIZE 1536
#define VFE40_EQUAL_SLICE_UB 228
#define VFE40_WM_BASE(idx) (0x6C + 0x24 * idx)
@@ -1078,7 +1078,6 @@
uint8_t num_used_wms = 0;
uint32_t prop_size = 0;
uint32_t wm_ub_size;
- uint32_t delta;
for (i = 0; i < axi_data->hw_info->num_wm; i++) {
if (axi_data->free_wm[i] > 0) {
@@ -1090,9 +1089,11 @@
axi_data->hw_info->min_wm_ub * num_used_wms;
for (i = 0; i < axi_data->hw_info->num_wm; i++) {
if (axi_data->free_wm[i]) {
- delta =
- (axi_data->wm_image_size[i] *
- prop_size)/total_image_size;
+ uint64_t delta = 0;
+ uint64_t temp = (uint64_t)axi_data->wm_image_size[i] *
+ (uint64_t)prop_size;
+ do_div(temp, total_image_size);
+ delta = temp;
wm_ub_size = axi_data->hw_info->min_wm_ub + delta;
msm_camera_io_w(ub_offset << 16 | (wm_ub_size - 1),
vfe_dev->vfe_base + VFE40_WM_BASE(i) + 0x10);
@@ -1119,7 +1120,7 @@
static void msm_vfe40_cfg_axi_ub(struct vfe_device *vfe_dev)
{
struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data;
- axi_data->wm_ub_cfg_policy = MSM_WM_UB_EQUAL_SLICING;
+ axi_data->wm_ub_cfg_policy = MSM_WM_UB_CFG_DEFAULT;
if (axi_data->wm_ub_cfg_policy == MSM_WM_UB_EQUAL_SLICING)
msm_vfe40_cfg_axi_ub_equal_slicing(vfe_dev);
else
@@ -1408,8 +1409,8 @@
}
static struct msm_vfe_axi_hardware_info msm_vfe40_axi_hw_info = {
- .num_wm = 5,
- .num_comp_mask = 2,
+ .num_wm = 7,
+ .num_comp_mask = 3,
.num_rdi = 3,
.num_rdi_master = 3,
.min_wm_ub = 64,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 206620c..a60fa09 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -1294,7 +1294,15 @@
rc = msm_isp_axi_wait_for_cfg_done(vfe_dev, camif_update);
if (rc < 0) {
pr_err("%s: wait for config done failed\n", __func__);
- return rc;
+ for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
+ stream_info = &axi_data->stream_info[
+ HANDLE_TO_IDX(
+ stream_cfg_cmd->stream_handle[i])];
+ stream_info->state = STOP_PENDING;
+ msm_isp_axi_stream_enable_cfg(
+ vfe_dev, stream_info);
+ stream_info->state = INACTIVE;
+ }
}
}
msm_isp_update_stream_bandwidth(vfe_dev);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index 60c9aef..cb46e9c 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -25,8 +25,8 @@
static DEFINE_MUTEX(bandwidth_mgr_mutex);
static struct msm_isp_bandwidth_mgr isp_bandwidth_mgr;
-#define MSM_ISP_MIN_AB 300000000
-#define MSM_ISP_MIN_IB 450000000
+#define MSM_ISP_MIN_AB 450000000
+#define MSM_ISP_MIN_IB 900000000
#define VFE40_8974V2_VERSION 0x1001001A
static struct msm_bus_vectors msm_isp_init_vectors[] = {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 051f171..3430311 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -1774,10 +1774,16 @@
dprintk(VIDC_ERR, "%s invalid parameters", __func__);
return -EINVAL;
}
- if (inst->state == MSM_VIDC_CORE_INVALID ||
- inst->core->state == VIDC_CORE_INVALID) {
+
+ if (inst->core->state == VIDC_CORE_INVALID) {
dprintk(VIDC_ERR,
- "Core is in bad state can't do load res");
+ "Core is in bad state can't do load res\n");
+ return -EINVAL;
+ }
+
+ if (inst->state == MSM_VIDC_CORE_INVALID) {
+ dprintk(VIDC_ERR,
+ "Instance is in invalid state can't do load res\n");
return -EINVAL;
}
diff --git a/drivers/media/platform/msm/wfd/vsg-subdev.c b/drivers/media/platform/msm/wfd/vsg-subdev.c
index 433468e..960e45c 100644
--- a/drivers/media/platform/msm/wfd/vsg-subdev.c
+++ b/drivers/media/platform/msm/wfd/vsg-subdev.c
@@ -337,6 +337,7 @@
static int vsg_start(struct v4l2_subdev *sd)
{
struct vsg_context *context = NULL;
+ int rc = 0;
if (!sd) {
WFD_MSG_ERR("ERROR, invalid arguments into %s\n", __func__);
@@ -345,18 +346,24 @@
context = (struct vsg_context *)sd->dev_priv;
+ mutex_lock(&context->mutex);
if (context->state == VSG_STATE_STARTED) {
WFD_MSG_ERR("VSG not stopped, start not allowed\n");
- return -EINPROGRESS;
+ rc = -EINPROGRESS;
+ goto err_bad_state;
} else if (context->state == VSG_STATE_ERROR) {
WFD_MSG_ERR("VSG in error state, not allowed to restart\n");
- return -ENOTRECOVERABLE;
+ rc = -ENOTRECOVERABLE;
+ goto err_bad_state;
}
context->state = VSG_STATE_STARTED;
hrtimer_start(&context->threshold_timer, ns_to_ktime(context->
max_frame_interval), HRTIMER_MODE_REL);
- return 0;
+
+err_bad_state:
+ mutex_unlock(&context->mutex);
+ return rc;
}
static int vsg_stop(struct v4l2_subdev *sd)
diff --git a/drivers/media/radio/radio-iris.c b/drivers/media/radio/radio-iris.c
index 9f18508..02441ec 100644
--- a/drivers/media/radio/radio-iris.c
+++ b/drivers/media/radio/radio-iris.c
@@ -1892,13 +1892,6 @@
return;
}
- if (radio->mode == FM_RECV_TURNING_ON) {
- radio->mode = FM_RECV;
- iris_q_event(radio, IRIS_EVT_RADIO_READY);
- } else if (radio->mode == FM_TRANS_TURNING_ON) {
- radio->mode = FM_TRANS;
- iris_q_event(radio, IRIS_EVT_RADIO_READY);
- }
radio_hci_req_complete(hdev, rsp->status);
}
@@ -3777,7 +3770,19 @@
radio->mode = FM_OFF;
goto END;
} else {
- initialise_recv(radio);
+ retval = initialise_recv(radio);
+ if (retval < 0) {
+ FMDERR("Error while initialising"\
+ "radio %d\n", retval);
+ hci_cmd(HCI_FM_DISABLE_RECV_CMD,
+ radio->fm_hdev);
+ radio->mode = FM_OFF;
+ goto END;
+ }
+ }
+ if (radio->mode == FM_RECV_TURNING_ON) {
+ radio->mode = FM_RECV;
+ iris_q_event(radio, IRIS_EVT_RADIO_READY);
}
break;
case FM_TRANS:
@@ -3794,7 +3799,19 @@
radio->mode = FM_OFF;
goto END;
} else {
- initialise_trans(radio);
+ retval = initialise_trans(radio);
+ if (retval < 0) {
+ FMDERR("Error while initialising"\
+ "radio %d\n", retval);
+ hci_cmd(HCI_FM_DISABLE_TRANS_CMD,
+ radio->fm_hdev);
+ radio->mode = FM_OFF;
+ goto END;
+ }
+ }
+ if (radio->mode == FM_TRANS_TURNING_ON) {
+ radio->mode = FM_TRANS;
+ iris_q_event(radio, IRIS_EVT_RADIO_READY);
}
break;
case FM_OFF:
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index a3e88b4..d3d8d0e 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -147,6 +147,7 @@
#define PRONTO_PLL_STATUS_OFFSET 0x1c
#define MSM_PRONTO_MCU_BASE 0xfb080c00
+#define MCU_APB2PHY_STATUS_OFFSET 0xec
#define MCU_CBR_CCAHB_ERR_OFFSET 0x380
#define MCU_CBR_CAHB_ERR_OFFSET 0x384
#define MCU_CBR_CCAHB_TIMEOUT_OFFSET 0x388
@@ -741,6 +742,10 @@
reg = readl_relaxed(penv->wlan_tx_phy_aborts);
pr_err("WLAN_TX_PHY_ABORTS %08x\n", reg);
+ reg_addr = penv->pronto_mcu_base + MCU_APB2PHY_STATUS_OFFSET;
+ reg = readl_relaxed(reg_addr);
+ pr_err("MCU_APB2PHY_STATUS %08x\n", reg);
+
reg_addr = penv->pronto_mcu_base + MCU_CBR_CCAHB_ERR_OFFSET;
reg = readl_relaxed(reg_addr);
pr_err("MCU_CBR_CCAHB_ERR %08x\n", reg);
diff --git a/drivers/platform/msm/qpnp-power-on.c b/drivers/platform/msm/qpnp-power-on.c
index f489566..462bd3b 100644
--- a/drivers/platform/msm/qpnp-power-on.c
+++ b/drivers/platform/msm/qpnp-power-on.c
@@ -24,6 +24,13 @@
#include <linux/log2.h>
#include <linux/qpnp/power-on.h>
+#define PMIC_VER_8941 0x01
+#define PMIC_VERSION_REG 0x0105
+#define PMIC_VERSION_REV4_REG 0x0103
+
+#define PMIC8941_V1_REV4 0x01
+#define PMIC8941_V2_REV4 0x02
+
/* Common PNP defines */
#define QPNP_PON_REVISION2(base) (base + 0x01)
@@ -776,6 +783,8 @@
struct device_node *pp = NULL;
struct qpnp_pon_config *cfg;
u8 pon_ver;
+ u8 pmic_type;
+ u8 revid_rev4;
/* Check if it is rev B */
rc = spmi_ext_register_readl(pon->spmi->ctrl, pon->spmi->sid,
@@ -858,6 +867,38 @@
cfg->use_bark = of_property_read_bool(pp,
"qcom,use-bark");
+
+ rc = spmi_ext_register_readl(pon->spmi->ctrl,
+ pon->spmi->sid, PMIC_VERSION_REG,
+ &pmic_type, 1);
+
+ if (rc) {
+ dev_err(&pon->spmi->dev,
+ "Unable to read PMIC type\n");
+ return rc;
+ }
+
+ if (pmic_type == PMIC_VER_8941) {
+
+ rc = spmi_ext_register_readl(pon->spmi->ctrl,
+ pon->spmi->sid, PMIC_VERSION_REV4_REG,
+ &revid_rev4, 1);
+
+ if (rc) {
+ dev_err(&pon->spmi->dev,
+ "Unable to read PMIC revision ID\n");
+ return rc;
+ }
+
+ /*PM8941 V3 does not have harware bug. Hence
+ bark is not required from PMIC versions 3.0*/
+ if (!(revid_rev4 == PMIC8941_V1_REV4 ||
+ revid_rev4 == PMIC8941_V2_REV4)) {
+ cfg->support_reset = false;
+ cfg->use_bark = false;
+ }
+ }
+
if (cfg->use_bark) {
cfg->bark_irq = spmi_get_irq_byname(pon->spmi,
NULL, "resin-bark");
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 4058bec..a701ec8 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -251,7 +251,6 @@
struct workqueue_struct *hsuart_wq; /* hsuart workqueue */
struct mutex clk_mutex; /* mutex to guard against clock off/clock on */
struct work_struct disconnect_rx_endpoint; /* disconnect rx_endpoint */
- bool tty_flush_receive;
enum uart_core_type uart_type;
u32 bam_handle;
resource_size_t bam_mem;
@@ -319,6 +318,7 @@
[UART_DM_TXFS] = 0x4c,
[UART_DM_RXFS] = 0x50,
[UART_DM_RX_TRANS_CTRL] = 0xcc,
+ [UART_DM_BCR] = 0xc8,
};
static struct of_device_id msm_hs_match_table[] = {
@@ -1838,12 +1838,13 @@
* Do the work buffer related work in BAM
* mode that is equivalent to legacy mode
*/
+ spin_lock_irqsave(&(msm_uport->uport.lock), flags);
- if (!msm_uport->tty_flush_receive)
+ if (!uart_circ_empty(tx_buf))
tx_buf->tail = (tx_buf->tail +
tx->tx_count) & ~UART_XMIT_SIZE;
else
- msm_uport->tty_flush_receive = false;
+ MSM_HS_DBG("%s:circ buffer is empty\n", __func__);
tx->dma_in_flight = 0;
@@ -1860,7 +1861,6 @@
if (uart_circ_chars_pending(tx_buf) < WAKEUP_CHARS)
uart_write_wakeup(uport);
- spin_lock_irqsave(&(msm_uport->uport.lock), flags);
if (msm_uport->tx.flush == FLUSH_STOP) {
msm_uport->tx.flush = FLUSH_SHUTDOWN;
wake_up(&msm_uport->tx.wait);
@@ -2036,14 +2036,6 @@
}
-static void msm_hs_flush_buffer(struct uart_port *uport)
-{
- struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
-
- if (msm_uport->tx.dma_in_flight)
- msm_uport->tty_flush_receive = true;
-}
-
/*
* Standard API, Break Signal
*
@@ -2281,11 +2273,9 @@
/* Do not update tx_buf.tail if uart_flush_buffer already
* called in serial core
*/
- if (!msm_uport->tty_flush_receive)
+ if (!uart_circ_empty(tx_buf))
tx_buf->tail = (tx_buf->tail +
tx->tx_count) & ~UART_XMIT_SIZE;
- else
- msm_uport->tty_flush_receive = false;
tx->dma_in_flight = 0;
@@ -2665,7 +2655,11 @@
}
}
- msm_hs_write(uport, UARTDM_BCR_ADDR, 0x003F);
+ data = (UARTDM_BCR_TX_BREAK_DISABLE | UARTDM_BCR_STALE_IRQ_EMPTY |
+ UARTDM_BCR_RX_DMRX_LOW_EN | UARTDM_BCR_RX_STAL_IRQ_DMRX_EQL |
+ UARTDM_BCR_RX_DMRX_1BYTE_RES_EN);
+ msm_hs_write(uport, UART_DM_BCR, data);
+
/* Set auto RFR Level */
data = msm_hs_read(uport, UART_DM_MR1);
data &= ~UARTDM_MR1_AUTO_RFR_LEVEL1_BMSK;
@@ -2708,8 +2702,6 @@
tx->tx_ready_int_en = 0;
tx->dma_in_flight = 0;
rx->rx_cmd_exec = false;
- msm_uport->tty_flush_receive = false;
- MSM_HS_DBG("%s: Setting tty_flush_receive to false\n", __func__);
if (!is_blsp_uart(msm_uport)) {
tx->xfer.complete_func = msm_hs_dmov_tx_callback;
@@ -3751,7 +3743,7 @@
.config_port = msm_hs_config_port,
.release_port = msm_hs_release_port,
.request_port = msm_hs_request_port,
- .flush_buffer = msm_hs_flush_buffer,
+ .flush_buffer = NULL,
.ioctl = msm_hs_ioctl,
};
diff --git a/drivers/tty/serial/msm_serial_hs_hwreg.h b/drivers/tty/serial/msm_serial_hs_hwreg.h
index d912b9f..064bbda 100644
--- a/drivers/tty/serial/msm_serial_hs_hwreg.h
+++ b/drivers/tty/serial/msm_serial_hs_hwreg.h
@@ -81,6 +81,7 @@
UART_DM_TXFS,
UART_DM_RXFS,
UART_DM_RX_TRANS_CTRL,
+ UART_DM_BCR,
UART_DM_LAST,
};
@@ -94,7 +95,11 @@
* UARTDM Core v1.4 STALE_IRQ_EMPTY bit defination
* Stale interrupt will fire if bit is set when RX-FIFO is empty
*/
+#define UARTDM_BCR_TX_BREAK_DISABLE 0x1
#define UARTDM_BCR_STALE_IRQ_EMPTY 0x2
+#define UARTDM_BCR_RX_DMRX_LOW_EN 0x4
+#define UARTDM_BCR_RX_STAL_IRQ_DMRX_EQL 0x10
+#define UARTDM_BCR_RX_DMRX_1BYTE_RES_EN 0x20
/* TRANSFER_CONTROL Register for UARTDM Core v1.4 */
#define UARTDM_RX_TRANS_CTRL_ADDR 0xcc
diff --git a/drivers/video/msm/mdss/dsi_host_v2.c b/drivers/video/msm/mdss/dsi_host_v2.c
index 884f7f2..e62cc59 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.c
+++ b/drivers/video/msm/mdss/dsi_host_v2.c
@@ -203,6 +203,13 @@
struct mdss_dsi_ctrl_pdata *ctrl =
(struct mdss_dsi_ctrl_pdata *)ptr;
+ spin_lock(&ctrl->mdp_lock);
+
+ if (ctrl->dsi_irq_mask == 0) {
+ spin_unlock(&ctrl->mdp_lock);
+ return IRQ_HANDLED;
+ }
+
isr = MIPI_INP(dsi_host_private->dsi_base + DSI_INT_CTRL);
MIPI_OUTP(dsi_host_private->dsi_base + DSI_INT_CTRL, isr);
@@ -213,22 +220,20 @@
msm_dsi_error(dsi_host_private->dsi_base);
}
- spin_lock(&ctrl->mdp_lock);
-
if (isr & DSI_INTR_VIDEO_DONE)
complete(&ctrl->video_comp);
if (isr & DSI_INTR_CMD_DMA_DONE)
complete(&ctrl->dma_comp);
- spin_unlock(&ctrl->mdp_lock);
-
if (isr & DSI_INTR_BTA_DONE)
complete(&ctrl->bta_comp);
if (isr & DSI_INTR_CMD_MDP_DONE)
complete(&ctrl->mdp_comp);
+ spin_unlock(&ctrl->mdp_lock);
+
return IRQ_HANDLED;
}
@@ -236,6 +241,13 @@
struct mdss_dsi_ctrl_pdata *ctrl)
{
int ret;
+ u32 isr;
+
+ msm_dsi_ahb_ctrl(1);
+ isr = MIPI_INP(dsi_host_private->dsi_base + DSI_INT_CTRL);
+ isr &= ~DSI_INTR_ALL_MASK;
+ MIPI_OUTP(dsi_host_private->dsi_base + DSI_INT_CTRL, isr);
+ msm_dsi_ahb_ctrl(0);
ret = devm_request_irq(dev, irq_no, msm_dsi_isr_handler,
IRQF_DISABLED, "DSI", ctrl);
@@ -1510,14 +1522,6 @@
__func__, __LINE__);
rc = -ENODEV;
goto error_irq_resource;
- } else {
- rc = msm_dsi_irq_init(&pdev->dev, mdss_dsi_mres->start,
- ctrl_pdata);
- if (rc) {
- dev_err(&pdev->dev, "%s: failed to init irq, rc=%d\n",
- __func__, rc);
- goto error_irq_resource;
- }
}
rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
@@ -1580,6 +1584,14 @@
msm_dsi_ctrl_init(ctrl_pdata);
+ rc = msm_dsi_irq_init(&pdev->dev, mdss_dsi_mres->start,
+ ctrl_pdata);
+ if (rc) {
+ dev_err(&pdev->dev, "%s: failed to init irq, rc=%d\n",
+ __func__, rc);
+ goto error_device_register;
+ }
+
rc = dsi_panel_device_register_v2(pdev, ctrl_pdata);
if (rc) {
pr_err("%s: dsi panel dev reg failed\n", __func__);
diff --git a/drivers/video/msm/mdss/dsi_host_v2.h b/drivers/video/msm/mdss/dsi_host_v2.h
index b297452..0f3ea8d 100644
--- a/drivers/video/msm/mdss/dsi_host_v2.h
+++ b/drivers/video/msm/mdss/dsi_host_v2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014, The Linux Foundation. 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
@@ -25,6 +25,7 @@
#define DSI_INTR_CMD_MDP_DONE BIT(8)
#define DSI_INTR_CMD_DMA_DONE_MASK BIT(1)
#define DSI_INTR_CMD_DMA_DONE BIT(0)
+#define DSI_INTR_ALL_MASK 0x2220202
#define DSI_BTA_TERM BIT(1)
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index 7b4b065..6de0df6 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -321,7 +321,7 @@
ctrl_pdata, ctrl_pdata->ndx);
if (pdata->panel_info.type == MIPI_CMD_PANEL)
- mdss_dsi_clk_ctrl(ctrl_pdata, 1);
+ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);
/* disable DSI controller */
mdss_dsi_controller_cfg(0, pdata);
@@ -329,7 +329,7 @@
/* disable DSI phy */
mdss_dsi_phy_disable(ctrl_pdata);
- mdss_dsi_clk_ctrl(ctrl_pdata, 0);
+ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0);
ret = mdss_dsi_panel_power_on(pdata, 0);
if (ret) {
@@ -465,14 +465,20 @@
goto error;
}
- if (__mdss_dsi_clk_enabled(ctrl_pdata)) {
+ if (__mdss_dsi_clk_enabled(ctrl_pdata, DSI_LINK_CLKS)) {
pr_err("%s: cannot enter ulps mode if dsi clocks are on\n",
__func__);
ret = -EPERM;
goto error;
}
- mdss_dsi_clk_ctrl(ctrl_pdata, 1);
+ ret = mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);
+ if (ret) {
+ pr_err("%s: Failed to enable clocks. rc=%d\n",
+ __func__, ret);
+ goto error;
+ }
+
/*
* ULPS Entry Request.
* Wait for a short duration to ensure that the lanes
@@ -480,6 +486,14 @@
*/
MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, 0x01F);
usleep(100);
+ lane_status = MIPI_INP(ctrl_pdata->ctrl_base + 0xA8);
+ if (lane_status & 0x1F00) {
+ pr_err("%s: ULPS entry req failed. Lane status=0x%08x\n",
+ __func__, lane_status);
+ ret = -EINVAL;
+ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0);
+ goto error;
+ }
/* Enable MMSS DSI Clamps */
MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, 0x3FF);
@@ -491,10 +505,17 @@
/* disable DSI controller */
mdss_dsi_controller_cfg(0, pdata);
- lane_status = MIPI_INP(ctrl_pdata->ctrl_base + 0xA8),
- mdss_dsi_clk_ctrl(ctrl_pdata, 0);
+ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0);
ctrl_pdata->ulps = true;
} else if (ctrl_pdata->ulps) {
+ ret = mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 1);
+ if (ret) {
+ pr_err("%s: Failed to enable bus clocks. rc=%d\n",
+ __func__, ret);
+ goto error;
+ }
+
+ MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x108, 0x0);
mdss_dsi_phy_init(pdata);
__mdss_dsi_ctrl_setup(pdata);
@@ -503,9 +524,28 @@
mdss_dsi_op_mode_config(pdata->panel_info.mipi.mode,
pdata);
+ /*
+ * ULPS Entry Request. This is needed because, after power
+ * collapse and reset, the DSI controller resets back to
+ * idle state and not ULPS.
+ * Wait for a short duration to ensure that the lanes
+ * enter ULP state.
+ */
+ MIPI_OUTP(ctrl_pdata->ctrl_base + 0x0AC, 0x01F);
+ usleep(100);
+
/* Disable MMSS DSI Clamps */
+ MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, 0x3FF);
MIPI_OUTP(ctrl_pdata->mmss_misc_io.base + 0x14, 0x0);
+ ret = mdss_dsi_clk_ctrl(ctrl_pdata, DSI_LINK_CLKS, 1);
+ if (ret) {
+ pr_err("%s: Failed to enable link clocks. rc=%d\n",
+ __func__, ret);
+ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 0);
+ goto error;
+ }
+
/*
* ULPS Exit Request
* Hardware requirement is to wait for at least 1ms
@@ -520,7 +560,9 @@
*/
usleep(100);
- lane_status = MIPI_INP(ctrl_pdata->ctrl_base + 0xA8),
+ lane_status = MIPI_INP(ctrl_pdata->ctrl_base + 0xA8);
+ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_LINK_CLKS, 0);
+ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 0);
ctrl_pdata->ulps = false;
}
@@ -535,21 +577,31 @@
int enable)
{
int rc;
- struct mdss_dsi_ctrl_pdata *sctrl = NULL;
+ struct mdss_dsi_ctrl_pdata *mctrl = NULL;
- if (ctrl->flags & DSI_FLAG_CLOCK_MASTER)
- sctrl = mdss_dsi_ctrl_slave(ctrl);
+ if (&ctrl->mmss_misc_io == NULL) {
+ pr_err("%s: mmss_misc_io is NULL. ULPS not valid\n", __func__);
+ return -EINVAL;
+ }
- if (sctrl) {
- pr_debug("%s: configuring ulps (%s) for slave ctrl\n",
- __func__, (enable ? "on" : "off"));
- rc = mdss_dsi_ulps_config_sub(sctrl, enable);
+ if (mdss_dsi_is_slave_ctrl(ctrl)) {
+ mctrl = mdss_dsi_get_master_ctrl();
+ if (!mctrl) {
+ pr_err("%s: Unable to get master control\n", __func__);
+ return -EINVAL;
+ }
+ }
+
+ if (mctrl) {
+ pr_debug("%s: configuring ulps (%s) for master ctrl%d\n",
+ __func__, (enable ? "on" : "off"), ctrl->ndx);
+ rc = mdss_dsi_ulps_config_sub(mctrl, enable);
if (rc)
return rc;
}
- pr_debug("%s: configuring ulps (%s) for master ctrl\n",
- __func__, (enable ? "on" : "off"));
+ pr_debug("%s: configuring ulps (%s) for ctrl%d\n",
+ __func__, (enable ? "on" : "off"), ctrl->ndx);
return mdss_dsi_ulps_config_sub(ctrl, enable);
}
@@ -585,7 +637,7 @@
return ret;
}
- ret = mdss_dsi_bus_clk_start(ctrl_pdata);
+ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 1);
if (ret) {
pr_err("%s: failed to enable bus clocks. rc=%d\n", __func__,
ret);
@@ -602,9 +654,9 @@
mdss_dsi_phy_sw_reset((ctrl_pdata->ctrl_base));
mdss_dsi_phy_init(pdata);
- mdss_dsi_bus_clk_stop(ctrl_pdata);
+ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_BUS_CLKS, 0);
- mdss_dsi_clk_ctrl(ctrl_pdata, 1);
+ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);
__mdss_dsi_ctrl_setup(pdata);
mdss_dsi_sw_reset(pdata);
@@ -630,7 +682,7 @@
}
if (pdata->panel_info.type == MIPI_CMD_PANEL)
- mdss_dsi_clk_ctrl(ctrl_pdata, 0);
+ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0);
pr_debug("%s-:\n", __func__);
return 0;
@@ -834,8 +886,8 @@
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004,
dsi_ctrl);
mdss_dsi_controller_cfg(true, pdata);
- mdss_dsi_clk_ctrl(ctrl_pdata, 0);
- mdss_dsi_clk_ctrl(ctrl_pdata, 1);
+ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0);
+ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);
dsi_ctrl |= 0x2;
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004,
dsi_ctrl);
@@ -1190,6 +1242,8 @@
mdss_dsi_put_dt_vreg_data(&pdev->dev, &ctrl_pdata->power_data);
mfd = platform_get_drvdata(pdev);
msm_dss_iounmap(&ctrl_pdata->mmss_misc_io);
+ msm_dss_iounmap(&ctrl_pdata->phy_io);
+ msm_dss_iounmap(&ctrl_pdata->ctrl_io);
return 0;
}
@@ -1200,7 +1254,6 @@
{
int rc = 0;
u32 index;
- struct resource *mdss_dsi_mres;
rc = of_property_read_u32(pdev->dev.of_node, "cell-index", &index);
if (rc) {
@@ -1228,31 +1281,32 @@
return -EPERM;
}
- mdss_dsi_mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mdss_dsi_mres) {
- pr_err("%s:%d unable to get the DSI ctrl resources",
+ rc = msm_dss_ioremap_byname(pdev, &ctrl->ctrl_io, "dsi_ctrl");
+ if (rc) {
+ pr_err("%s:%d unable to remap dsi ctrl resources",
__func__, __LINE__);
- return -ENOMEM;
+ return rc;
}
- ctrl->ctrl_base = ioremap(mdss_dsi_mres->start,
- resource_size(mdss_dsi_mres));
- if (!(ctrl->ctrl_base)) {
- pr_err("%s:%d unable to remap dsi resources",
+ ctrl->ctrl_base = ctrl->ctrl_io.base;
+ ctrl->reg_size = ctrl->ctrl_io.len;
+
+ rc = msm_dss_ioremap_byname(pdev, &ctrl->phy_io, "dsi_phy");
+ if (rc) {
+ pr_err("%s:%d unable to remap dsi phy resources",
__func__, __LINE__);
- return -ENOMEM;
+ return rc;
}
- ctrl->reg_size = resource_size(mdss_dsi_mres);
-
- pr_info("%s: dsi base=%x size=%x\n",
- __func__, (int)ctrl->ctrl_base, ctrl->reg_size);
+ pr_info("%s: ctrl_base=%p ctrl_size=%x phy_base=%p phy_size=%x\n",
+ __func__, ctrl->ctrl_base, ctrl->reg_size, ctrl->phy_io.base,
+ ctrl->phy_io.len);
rc = msm_dss_ioremap_byname(pdev, &ctrl->mmss_misc_io,
"mmss_misc_phys");
if (rc) {
- pr_err("%s:%d mmss_misc IO remap failed\n", __func__, __LINE__);
- return rc;
+ pr_debug("%s:%d mmss_misc IO remap failed\n",
+ __func__, __LINE__);
}
return 0;
@@ -1492,7 +1546,7 @@
return rc;
}
- mdss_dsi_clk_ctrl(ctrl_pdata, 1);
+ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);
ctrl_pdata->ctrl_state |=
(CTRL_STATE_PANEL_INIT | CTRL_STATE_MDP_ACTIVE);
} else {
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 57b0e75..b0b884f 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -151,8 +151,8 @@
#define DSI_CMD_TERM BIT(0)
extern struct device dsi_dev;
-extern int mdss_dsi_clk_on;
extern u32 dsi_irq;
+extern struct mdss_dsi_ctrl_pdata *ctrl_list[];
struct dsiphy_pll_divider_config {
u32 clk_rate;
@@ -223,12 +223,18 @@
DSI_CTRL_MAX,
};
+/* DSI controller #0 is always treated as a master in broadcast mode */
+#define DSI_CTRL_MASTER DSI_CTRL_0
+#define DSI_CTRL_SLAVE DSI_CTRL_1
+
+#define DSI_BUS_CLKS BIT(0)
+#define DSI_LINK_CLKS BIT(1)
+#define DSI_ALL_CLKS ((DSI_BUS_CLKS) | (DSI_LINK_CLKS))
+
#define DSI_EV_PLL_UNLOCKED 0x0001
#define DSI_EV_MDP_FIFO_UNDERFLOW 0x0002
#define DSI_EV_MDP_BUSY_RELEASE 0x80000000
-#define DSI_FLAG_CLOCK_MASTER 0x80000000
-
struct mdss_dsi_ctrl_pdata {
int ndx; /* panel_num */
int (*on) (struct mdss_panel_data *pdata);
@@ -238,10 +244,12 @@
int (*cmdlist_commit)(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp);
struct mdss_panel_data panel_data;
unsigned char *ctrl_base;
+ struct dss_io_data ctrl_io;
struct dss_io_data mmss_misc_io;
+ struct dss_io_data phy_io;
int reg_size;
- u32 clk_cnt;
- int clk_cnt_sub;
+ u32 bus_clk_cnt;
+ u32 link_clk_cnt;
u32 flags;
struct clk *mdp_core_clk;
struct clk *ahb_clk;
@@ -253,7 +261,6 @@
u8 ctrl_state;
int panel_mode;
int irq_cnt;
- int mdss_dsi_clk_on;
int rst_gpio;
int disp_en_gpio;
int disp_te_gpio;
@@ -312,20 +319,14 @@
void mdss_dsi_cmd_mdp_start(struct mdss_dsi_ctrl_pdata *ctrl);
void mdss_dsi_cmd_bta_sw_trigger(struct mdss_panel_data *pdata);
void mdss_dsi_ack_err_status(struct mdss_dsi_ctrl_pdata *ctrl);
-void mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable);
-int mdss_dsi_link_clk_start(struct mdss_dsi_ctrl_pdata *ctrl);
-void mdss_dsi_link_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl);
-int mdss_dsi_bus_clk_start(struct mdss_dsi_ctrl_pdata *ctrl);
-void mdss_dsi_bus_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl);
+int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl,
+ u8 clk_type, int enable);
void mdss_dsi_clk_req(struct mdss_dsi_ctrl_pdata *ctrl,
int enable);
void mdss_dsi_controller_cfg(int enable,
struct mdss_panel_data *pdata);
void mdss_dsi_sw_reset(struct mdss_panel_data *pdata);
-struct mdss_dsi_ctrl_pdata *mdss_dsi_ctrl_slave(
- struct mdss_dsi_ctrl_pdata *ctrl);
-
irqreturn_t mdss_dsi_isr(int irq, void *ptr);
void mdss_dsi_irq_handler_config(struct mdss_dsi_ctrl_pdata *ctrl_pdata);
@@ -351,9 +352,52 @@
int mdss_dsi_cmdlist_commit(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp);
void mdss_dsi_cmdlist_kickoff(int intf);
int mdss_dsi_bta_status_check(struct mdss_dsi_ctrl_pdata *ctrl);
-bool __mdss_dsi_clk_enabled(struct mdss_dsi_ctrl_pdata *ctrl);
+bool __mdss_dsi_clk_enabled(struct mdss_dsi_ctrl_pdata *ctrl, u8 clk_type);
int mdss_dsi_panel_init(struct device_node *node,
struct mdss_dsi_ctrl_pdata *ctrl_pdata,
bool cmd_cfg_cont_splash);
+
+static inline bool mdss_dsi_broadcast_mode_enabled(void)
+{
+ return ctrl_list[DSI_CTRL_MASTER]->shared_pdata.broadcast_enable &&
+ ctrl_list[DSI_CTRL_SLAVE] &&
+ ctrl_list[DSI_CTRL_SLAVE]->shared_pdata.broadcast_enable;
+}
+
+static inline struct mdss_dsi_ctrl_pdata *mdss_dsi_get_master_ctrl(void)
+{
+ if (mdss_dsi_broadcast_mode_enabled())
+ return ctrl_list[DSI_CTRL_MASTER];
+ else
+ return NULL;
+}
+
+static inline struct mdss_dsi_ctrl_pdata *mdss_dsi_get_slave_ctrl(void)
+{
+ if (mdss_dsi_broadcast_mode_enabled())
+ return ctrl_list[DSI_CTRL_SLAVE];
+ else
+ return NULL;
+}
+
+static inline bool mdss_dsi_is_master_ctrl(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ return mdss_dsi_broadcast_mode_enabled() &&
+ (ctrl->ndx == DSI_CTRL_MASTER);
+}
+
+static inline bool mdss_dsi_is_slave_ctrl(struct mdss_dsi_ctrl_pdata *ctrl)
+{
+ return mdss_dsi_broadcast_mode_enabled() &&
+ (ctrl->ndx == DSI_CTRL_SLAVE);
+}
+
+static inline struct mdss_dsi_ctrl_pdata *mdss_dsi_get_ctrl_by_index(int ndx)
+{
+ if (ndx >= DSI_CTRL_MAX)
+ return NULL;
+
+ return ctrl_list[ndx];
+}
#endif /* MDSS_DSI_H */
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index f342c56..a570914 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -29,10 +29,7 @@
#define VSYNC_PERIOD 17
-static struct mdss_dsi_ctrl_pdata *left_ctrl_pdata;
-
-static struct mdss_dsi_ctrl_pdata *ctrl_list[DSI_CTRL_MAX];
-
+struct mdss_dsi_ctrl_pdata *ctrl_list[DSI_CTRL_MAX];
struct mdss_hw mdss_dsi0_hw = {
.hw_ndx = MDSS_HW_DSI0,
@@ -72,14 +69,6 @@
void mdss_dsi_ctrl_init(struct mdss_dsi_ctrl_pdata *ctrl)
{
- if (ctrl->shared_pdata.broadcast_enable)
- if (ctrl->panel_data.panel_info.pdest
- == DISPLAY_1) {
- pr_debug("%s: Broadcast mode enabled.\n",
- __func__);
- left_ctrl_pdata = ctrl;
- }
-
if (ctrl->panel_data.panel_info.pdest == DISPLAY_1) {
mdss_dsi0_hw.ptr = (void *)(ctrl);
ctrl->dsi_hw = &mdss_dsi0_hw;
@@ -94,10 +83,6 @@
ctrl_list[ctrl->ndx] = ctrl; /* keep it */
- if (ctrl->shared_pdata.broadcast_enable)
- if (ctrl->ndx == DSI_CTRL_1)
- ctrl->flags |= DSI_FLAG_CLOCK_MASTER;
-
if (mdss_register_irq(ctrl->dsi_hw))
pr_err("%s: mdss_register_irq failed.\n", __func__);
@@ -123,22 +108,6 @@
}
}
-struct mdss_dsi_ctrl_pdata *mdss_dsi_ctrl_slave(
- struct mdss_dsi_ctrl_pdata *ctrl)
-{
- int ndx;
- struct mdss_dsi_ctrl_pdata *sctrl = NULL;
-
- /* only two controllers */
- ndx = ctrl->ndx;
- ndx += 1;
- ndx %= DSI_CTRL_MAX;
- sctrl = ctrl_list[ndx];
-
- return sctrl;
-
-}
-
void mdss_dsi_clk_req(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
{
if (enable == 0) {
@@ -148,22 +117,26 @@
mutex_unlock(&ctrl->cmd_mutex);
}
- mdss_dsi_clk_ctrl(ctrl, enable);
+ mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, enable);
}
void mdss_dsi_pll_relock(struct mdss_dsi_ctrl_pdata *ctrl)
{
int i, cnt;
- cnt = ctrl->clk_cnt;
+ /*
+ * todo: this code does not work very well with dual
+ * dsi use cases. Need to fix this eventually.
+ */
+ cnt = ctrl->link_clk_cnt;
/* disable dsi clk */
for (i = 0; i < cnt; i++)
- mdss_dsi_clk_ctrl(ctrl, 0);
+ mdss_dsi_clk_ctrl(ctrl, DSI_LINK_CLKS, 0);
/* enable dsi clk */
for (i = 0; i < cnt; i++)
- mdss_dsi_clk_ctrl(ctrl, 1);
+ mdss_dsi_clk_ctrl(ctrl, DSI_LINK_CLKS, 1);
}
void mdss_dsi_enable_irq(struct mdss_dsi_ctrl_pdata *ctrl, u32 term)
@@ -341,7 +314,7 @@
/* from frame buffer, low power mode */
/* DSI_COMMAND_MODE_DMA_CTRL */
- if (ctrl_pdata->shared_pdata.broadcast_enable)
+ if (mdss_dsi_broadcast_mode_enabled())
MIPI_OUTP(ctrl_pdata->ctrl_base + 0x3C, 0x94000000);
else
MIPI_OUTP(ctrl_pdata->ctrl_base + 0x3C, 0x14000000);
@@ -544,6 +517,7 @@
{
u32 dsi_ctrl, intr_ctrl;
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+ struct mdss_dsi_ctrl_pdata *mctrl = NULL;
if (pdata == NULL) {
pr_err("%s: Invalid input data\n", __func__);
@@ -553,12 +527,15 @@
ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
panel_data);
- if (ctrl_pdata->shared_pdata.broadcast_enable)
- if (pdata->panel_info.pdest == DISPLAY_1) {
- pr_debug("%s: Broadcast mode. 1st ctrl\n",
- __func__);
- return;
- }
+ /*
+ * In broadcast mode, the configuration for master controller
+ * would be done when the slave controller is configured
+ */
+ if (mdss_dsi_is_master_ctrl(ctrl_pdata)) {
+ pr_debug("%s: Broadcast mode enabled. skipping config for ctrl%d\n",
+ __func__, ctrl_pdata->ndx);
+ return;
+ }
dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004);
/*If Video enabled, Keep Video and Cmd mode ON */
@@ -579,17 +556,22 @@
DSI_INTR_CMD_MDP_DONE_MASK | DSI_INTR_BTA_DONE_MASK;
}
- if (ctrl_pdata->shared_pdata.broadcast_enable)
- if ((pdata->panel_info.pdest == DISPLAY_2)
- && (left_ctrl_pdata != NULL)) {
- MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0110,
- intr_ctrl); /* DSI_INTL_CTRL */
- MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
- dsi_ctrl);
+ /* Ensure that for slave controller, master is also configured */
+ if (mdss_dsi_is_slave_ctrl(ctrl_pdata)) {
+ mctrl = mdss_dsi_get_master_ctrl();
+ if (mctrl) {
+ pr_debug("%s: configuring ctrl%d\n", __func__,
+ mctrl->ndx);
+ MIPI_OUTP(mctrl->ctrl_base + 0x0110, intr_ctrl);
+ MIPI_OUTP(mctrl->ctrl_base + 0x0004, dsi_ctrl);
+ } else {
+ pr_warn("%s: Unable to get master control\n",
+ __func__);
}
+ }
- MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0110,
- intr_ctrl); /* DSI_INTL_CTRL */
+ pr_debug("%s: configuring ctrl%d\n", __func__, ctrl_pdata->ndx);
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0110, intr_ctrl);
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl);
wmb();
}
@@ -640,7 +622,7 @@
pr_debug("%s: Checking BTA status\n", __func__);
- mdss_dsi_clk_ctrl(ctrl_pdata, 1);
+ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 1);
spin_lock_irqsave(&ctrl_pdata->mdp_lock, flag);
INIT_COMPLETION(ctrl_pdata->bta_comp);
mdss_dsi_enable_irq(ctrl_pdata, DSI_BTA_TERM);
@@ -655,7 +637,7 @@
pr_err("%s: DSI BTA error: %i\n", __func__, ret);
}
- mdss_dsi_clk_ctrl(ctrl_pdata, 0);
+ mdss_dsi_clk_ctrl(ctrl_pdata, DSI_ALL_CLKS, 0);
pr_debug("%s: BTA done with ret: %d\n", __func__, ret);
return ret;
@@ -744,6 +726,40 @@
return tot;
}
+/**
+ * __mdss_dsi_cmd_mode_config() - Enable/disable command mode engine
+ * @ctrl: pointer to the dsi controller structure
+ * @enable: true to enable command mode, false to disable command mode
+ *
+ * This function can be used to temporarily enable the command mode
+ * engine (even for video mode panels) so as to transfer any dma commands to
+ * the panel. It can also be used to disable the command mode engine
+ * when no longer needed.
+ *
+ * Return: true, if there was a mode switch to command mode for video mode
+ * panels.
+ */
+static inline bool __mdss_dsi_cmd_mode_config(
+ struct mdss_dsi_ctrl_pdata *ctrl, bool enable)
+{
+ bool mode_changed = false;
+ u32 dsi_ctrl;
+
+ dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004);
+ /* if currently in video mode, enable command mode */
+ if (enable) {
+ if ((dsi_ctrl) & BIT(1)) {
+ MIPI_OUTP((ctrl->ctrl_base) + 0x0004,
+ dsi_ctrl | BIT(2));
+ mode_changed = true;
+ }
+ } else {
+ MIPI_OUTP((ctrl->ctrl_base) + 0x0004, dsi_ctrl & ~BIT(2));
+ }
+
+ return mode_changed;
+}
+
/*
* mdss_dsi_cmds_tx:
* thread context only
@@ -751,61 +767,49 @@
int mdss_dsi_cmds_tx(struct mdss_dsi_ctrl_pdata *ctrl,
struct dsi_cmd_desc *cmds, int cnt)
{
- u32 dsi_ctrl, data;
- int video_mode, ret = 0;
- u32 left_dsi_ctrl = 0;
- bool left_ctrl_restore = false;
+ int ret = 0;
+ bool ctrl_restore = false, mctrl_restore = false;
+ struct mdss_dsi_ctrl_pdata *mctrl = NULL;
- if (ctrl->shared_pdata.broadcast_enable) {
- if (ctrl->ndx == DSI_CTRL_0) {
- pr_debug("%s: Broadcast mode. 1st ctrl\n",
- __func__);
- return 0;
- }
+ /*
+ * In broadcast mode, the configuration for master controller
+ * would be done when the slave controller is configured
+ */
+ if (mdss_dsi_is_master_ctrl(ctrl)) {
+ pr_debug("%s: Broadcast mode enabled. skipping config for ctrl%d\n",
+ __func__, ctrl->ndx);
+ return 0;
}
- if (ctrl->shared_pdata.broadcast_enable) {
- if ((ctrl->ndx == DSI_CTRL_1)
- && (left_ctrl_pdata != NULL)) {
- left_dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
- + 0x0004);
- video_mode =
- left_dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
- if (video_mode) {
- data = left_dsi_ctrl | 0x04; /* CMD_MODE_EN */
- MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
- data);
- left_ctrl_restore = true;
- }
- }
+ /*
+ * Turn on cmd mode in order to transmit the commands.
+ * For video mode, do not send cmds more than one pixel line,
+ * since it only transmit it during BLLP.
+ * Ensure that for slave controller, master is also configured
+ */
+ if (mdss_dsi_is_slave_ctrl(ctrl)) {
+ mctrl = mdss_dsi_get_master_ctrl();
+ if (!mctrl)
+ pr_warn("%s: Unable to get master control\n",
+ __func__);
+ else
+ mctrl_restore = __mdss_dsi_cmd_mode_config(mctrl, 1);
}
- /* turn on cmd mode
- * for video mode, do not send cmds more than
- * one pixel line, since it only transmit it
- * during BLLP.
- */
- dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004);
- video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
- if (video_mode) {
- data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
- MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data);
- }
+ ctrl_restore = __mdss_dsi_cmd_mode_config(ctrl, 1);
ret = mdss_dsi_cmds2buf_tx(ctrl, cmds, cnt);
if (IS_ERR_VALUE(ret)) {
- pr_err("%s: failed to call\n",
- __func__);
+ pr_err("%s: failed to call\n", __func__);
cnt = -EINVAL;
}
- if (left_ctrl_restore)
- MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
- left_dsi_ctrl); /*restore */
+ if (mctrl_restore)
+ __mdss_dsi_cmd_mode_config(mctrl, 0);
- if (video_mode)
- MIPI_OUTP((ctrl->ctrl_base) + 0x0004,
- dsi_ctrl); /* restore */
+ if (ctrl_restore)
+ __mdss_dsi_cmd_mode_config(ctrl, 0);
+
return cnt;
}
@@ -838,45 +842,35 @@
int short_response, diff, pkt_size, ret = 0;
struct dsi_buf *tp, *rp;
char cmd;
- u32 dsi_ctrl, data;
- int video_mode;
- u32 left_dsi_ctrl = 0;
- bool left_ctrl_restore = false;
+ bool ctrl_restore = false, mctrl_restore = false;
+ struct mdss_dsi_ctrl_pdata *mctrl = NULL;
- if (ctrl->shared_pdata.broadcast_enable) {
- if (ctrl->ndx == DSI_CTRL_0) {
- pr_debug("%s: Broadcast mode. 1st ctrl\n",
- __func__);
- return 0;
- }
+ /*
+ * In broadcast mode, the configuration for master controller
+ * would be done when the slave controller is configured
+ */
+ if (mdss_dsi_is_master_ctrl(ctrl)) {
+ pr_debug("%s: Broadcast mode enabled. skipping config for ctrl%d\n",
+ __func__, ctrl->ndx);
+ return 0;
}
- if (ctrl->shared_pdata.broadcast_enable) {
- if ((ctrl->ndx == DSI_CTRL_1)
- && (left_ctrl_pdata != NULL)) {
- left_dsi_ctrl = MIPI_INP(left_ctrl_pdata->ctrl_base
- + 0x0004);
- video_mode = left_dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
- if (video_mode) {
- data = left_dsi_ctrl | 0x04; /* CMD_MODE_EN */
- MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
- data);
- left_ctrl_restore = true;
- }
- }
+ /*
+ * Turn on cmd mode in order to transmit the commands.
+ * For video mode, do not send cmds more than one pixel line,
+ * since it only transmit it during BLLP.
+ * Ensure that for slave controller, master is also configured
+ */
+ if (mdss_dsi_is_slave_ctrl(ctrl)) {
+ mctrl = mdss_dsi_get_master_ctrl();
+ if (!mctrl)
+ pr_warn("%s: Unable to get master control\n",
+ __func__);
+ else
+ mctrl_restore = __mdss_dsi_cmd_mode_config(mctrl, 1);
}
- /* turn on cmd mode
- * for video mode, do not send cmds more than
- * one pixel line, since it only transmit it
- * during BLLP.
- */
- dsi_ctrl = MIPI_INP((ctrl->ctrl_base) + 0x0004);
- video_mode = dsi_ctrl & 0x02; /* VIDEO_MODE_EN */
- if (video_mode) {
- data = dsi_ctrl | 0x04; /* CMD_MODE_EN */
- MIPI_OUTP((ctrl->ctrl_base) + 0x0004, data);
- }
+ ctrl_restore = __mdss_dsi_cmd_mode_config(ctrl, 1);
if (rlen == 0) {
short_response = 1;
@@ -1003,12 +997,11 @@
rp->len = 0;
}
end:
- if (left_ctrl_restore)
- MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0004,
- left_dsi_ctrl); /*restore */
- if (video_mode)
- MIPI_OUTP((ctrl->ctrl_base) + 0x0004,
- dsi_ctrl); /* restore */
+ if (mctrl_restore)
+ __mdss_dsi_cmd_mode_config(mctrl, 0);
+
+ if (ctrl_restore)
+ __mdss_dsi_cmd_mode_config(ctrl, 0);
return rp->len;
}
@@ -1022,6 +1015,7 @@
int domain = MDSS_IOMMU_DOMAIN_UNSECURE;
char *bp;
unsigned long size, addr;
+ struct mdss_dsi_ctrl_pdata *mctrl = NULL;
bp = tp->data;
@@ -1043,24 +1037,27 @@
INIT_COMPLETION(ctrl->dma_comp);
- if (ctrl->shared_pdata.broadcast_enable)
- if ((ctrl->ndx == DSI_CTRL_1)
- && (left_ctrl_pdata != NULL)) {
- MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x048, addr);
- MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x04c, len);
+ /* Ensure that for slave controller, master is also configured */
+ if (mdss_dsi_is_slave_ctrl(ctrl)) {
+ mctrl = mdss_dsi_get_master_ctrl();
+ if (mctrl) {
+ MIPI_OUTP(mctrl->ctrl_base + 0x048, addr);
+ MIPI_OUTP(mctrl->ctrl_base + 0x04c, len);
+ } else {
+ pr_warn("%s: Unable to get master control\n",
+ __func__);
}
+ }
MIPI_OUTP((ctrl->ctrl_base) + 0x048, addr);
MIPI_OUTP((ctrl->ctrl_base) + 0x04c, len);
wmb();
- if (ctrl->shared_pdata.broadcast_enable)
- if ((ctrl->ndx == DSI_CTRL_1)
- && (left_ctrl_pdata != NULL)) {
- MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x090, 0x01);
- }
+ /* Trigger on master controller as well */
+ if (mctrl)
+ MIPI_OUTP(mctrl->ctrl_base + 0x090, 0x01);
- MIPI_OUTP((ctrl->ctrl_base) + 0x090, 0x01); /* trigger */
+ MIPI_OUTP((ctrl->ctrl_base) + 0x090, 0x01);
wmb();
ret = wait_for_completion_timeout(&ctrl->dma_comp,
@@ -1210,13 +1207,11 @@
len = mdss_dsi_cmds_rx(ctrl, req->cmds, req->rlen);
memcpy(req->rbuf, rp->data, rp->len);
/*
- * For dual DSI cases, early return of controller - 0
+ * For dual DSI cases, early return of master ctrl
* is valid. Hence, for those cases the return value
* is zero even though we don't send any commands.
- *
*/
- if ((ctrl->shared_pdata.broadcast_enable &&
- ctrl->ndx == DSI_CTRL_0) || (len != 0))
+ if (mdss_dsi_is_master_ctrl(ctrl) || (len != 0))
ret = 0;
} else {
pr_err("%s: No rx buffer provided\n", __func__);
@@ -1253,14 +1248,14 @@
mdss_bus_bandwidth_ctrl(1);
pr_debug("%s: from_mdp=%d pid=%d\n", __func__, from_mdp, current->pid);
- mdss_dsi_clk_ctrl(ctrl, 1);
+ mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 1);
if (req->flags & CMD_REQ_RX)
ret = mdss_dsi_cmdlist_rx(ctrl, req);
else
ret = mdss_dsi_cmdlist_tx(ctrl, req);
- mdss_dsi_clk_ctrl(ctrl, 0);
+ mdss_dsi_clk_ctrl(ctrl, DSI_ALL_CLKS, 0);
mdss_bus_bandwidth_ctrl(0);
need_lock:
@@ -1465,6 +1460,7 @@
u32 isr;
struct mdss_dsi_ctrl_pdata *ctrl =
(struct mdss_dsi_ctrl_pdata *)ptr;
+ struct mdss_dsi_ctrl_pdata *mctrl = NULL;
if (!ctrl->ctrl_base)
pr_err("%s:%d DSI base adr no Initialized",
@@ -1473,16 +1469,19 @@
isr = MIPI_INP(ctrl->ctrl_base + 0x0110);/* DSI_INTR_CTRL */
MIPI_OUTP(ctrl->ctrl_base + 0x0110, isr);
- if (ctrl->shared_pdata.broadcast_enable)
- if ((ctrl->panel_data.panel_info.pdest == DISPLAY_2)
- && (left_ctrl_pdata != NULL)) {
+ if (mdss_dsi_is_slave_ctrl(ctrl)) {
+ mctrl = mdss_dsi_get_master_ctrl();
+ if (mctrl) {
u32 isr0;
- isr0 = MIPI_INP(left_ctrl_pdata->ctrl_base
- + 0x0110);/* DSI_INTR_CTRL */
+ isr0 = MIPI_INP(mctrl->ctrl_base + 0x0110);
if (isr0 & DSI_INTR_CMD_DMA_DONE)
- MIPI_OUTP(left_ctrl_pdata->ctrl_base + 0x0110,
+ MIPI_OUTP(mctrl->ctrl_base + 0x0110,
DSI_INTR_CMD_DMA_DONE);
+ } else {
+ pr_warn("%s: Unable to get master control\n",
+ __func__);
}
+ }
pr_debug("%s: ndx=%d isr=%x\n", __func__, ctrl->ndx, isr);
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 5415a7e..f450dec 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -317,17 +317,6 @@
return rc;
}
-static struct mdss_dsi_ctrl_pdata *get_rctrl_data(struct mdss_panel_data *pdata)
-{
- if (!pdata || !pdata->next) {
- pr_err("%s: Invalid panel data\n", __func__);
- return NULL;
- }
-
- return container_of(pdata->next, struct mdss_dsi_ctrl_pdata,
- panel_data);
-}
-
static void mdss_dsi_panel_bl_ctrl(struct mdss_panel_data *pdata,
u32 bl_level)
{
@@ -359,15 +348,15 @@
break;
case BL_DCS_CMD:
mdss_dsi_panel_bklt_dcs(ctrl_pdata, bl_level);
- if (ctrl_pdata->shared_pdata.broadcast_enable &&
- ctrl_pdata->ndx == DSI_CTRL_0) {
- struct mdss_dsi_ctrl_pdata *rctrl_pdata = NULL;
- rctrl_pdata = get_rctrl_data(pdata);
- if (!rctrl_pdata) {
- pr_err("%s: Right ctrl data NULL\n", __func__);
+ if (mdss_dsi_is_master_ctrl(ctrl_pdata)) {
+ struct mdss_dsi_ctrl_pdata *sctrl =
+ mdss_dsi_get_slave_ctrl();
+ if (!sctrl) {
+ pr_err("%s: Invalid slave ctrl data\n",
+ __func__);
return;
}
- mdss_dsi_panel_bklt_dcs(rctrl_pdata, bl_level);
+ mdss_dsi_panel_bklt_dcs(sctrl, bl_level);
}
break;
default:
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 252a86e..1aec58e 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -828,6 +828,8 @@
}
break;
}
+ /* Notify listeners */
+ sysfs_notify(&mfd->fbi->dev->kobj, NULL, "show_blank_event");
return ret;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
index 78ecf16..96da27e 100644
--- a/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
+++ b/drivers/video/msm/mdss/mdss_mdp_intf_cmd.c
@@ -200,13 +200,17 @@
{
unsigned long flags;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+
+ if (!ctx->panel_on)
+ return;
+
mutex_lock(&ctx->clk_mtx);
if (!ctx->clk_enabled) {
ctx->clk_enabled = 1;
if (cancel_delayed_work_sync(&ctx->ulps_work))
pr_debug("deleted pending ulps work\n");
- mdss_mdp_ctl_intf_event
- (ctx->ctl, MDSS_EVENT_PANEL_CLK_CTRL, (void *)1);
+
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
if (ctx->ulps) {
if (mdss_mdp_cmd_tearcheck_setup(ctx->ctl, 1))
@@ -216,7 +220,9 @@
ctx->ulps = false;
}
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
+ mdss_mdp_ctl_intf_event
+ (ctx->ctl, MDSS_EVENT_PANEL_CLK_CTRL, (void *)1);
+
mdss_mdp_hist_intr_setup(&mdata->hist_intr, MDSS_IRQ_RESUME);
}
spin_lock_irqsave(&ctx->clk_lock, flags);
@@ -277,6 +283,10 @@
if (!ctx->vsync_enabled) {
if (ctx->rdptr_enabled)
ctx->rdptr_enabled--;
+
+ /* keep clk on during kickoff */
+ if (ctx->rdptr_enabled == 0 && ctx->koff_cnt)
+ ctx->rdptr_enabled++;
}
if (ctx->rdptr_enabled == 0) {
@@ -561,22 +571,22 @@
WARN(rc, "intf %d panel on error (%d)\n", ctl->intf_num, rc);
}
- mdss_mdp_cmd_set_partial_roi(ctl);
+ spin_lock_irqsave(&ctx->clk_lock, flags);
+ ctx->koff_cnt++;
+ spin_unlock_irqrestore(&ctx->clk_lock, flags);
mdss_mdp_cmd_clk_on(ctx);
+ mdss_mdp_cmd_set_partial_roi(ctl);
+
/*
* tx dcs command if had any
*/
mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_DSI_CMDLIST_KOFF,
(void *)&ctx->recovery);
-
INIT_COMPLETION(ctx->pp_comp);
mdss_mdp_irq_enable(MDSS_MDP_IRQ_PING_PONG_COMP, ctx->pp_num);
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_START, 1);
- spin_lock_irqsave(&ctx->clk_lock, flags);
- ctx->koff_cnt++;
- spin_unlock_irqrestore(&ctx->clk_lock, flags);
mb();
return 0;
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index da168b8..7628380 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -321,10 +321,6 @@
rc, src, pipe->dst.h);
return rc;
}
- pipe->scale.init_phase_x[0] = (pipe->scale.phase_step_x[0] -
- (1 << PHASE_STEP_SHIFT)) / 2;
- pipe->scale.init_phase_y[0] = (pipe->scale.phase_step_y[0] -
- (1 << PHASE_STEP_SHIFT)) / 2;
return rc;
}
@@ -1789,7 +1785,7 @@
vsync_ticks = ktime_to_ns(mdp5_data->vsync_time);
pr_debug("fb%d vsync=%llu", mfd->index, vsync_ticks);
- ret = scnprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_ticks);
+ ret = scnprintf(buf, PAGE_SIZE, "VSYNC=%llu\n", vsync_ticks);
return ret;
}
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 6b4f19d..50bee17 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -216,7 +216,7 @@
struct mdss_mdp_plane_sizes ps;
int i;
int rc = 0, rot_mode = 0, wb_mixer = 0;
- u32 nlines, format;
+ u32 nlines, format, seg_w;
u16 width;
width = pipe->src.w >> pipe->horz_deci;
@@ -228,19 +228,17 @@
return rc;
/*
* Override fetch strides with SMP buffer size for both the
- * planes
+ * planes. BWC line buffer needs to be divided into 16
+ * segments and every segment is aligned to format
+ * specific RAU size
*/
+ seg_w = DIV_ROUND_UP(pipe->src.w, 16);
if (pipe->src_fmt->fetch_planes == MDSS_MDP_PLANE_INTERLEAVED) {
- /*
- * BWC line buffer needs to be divided into 16
- * segments and every segment is aligned to format
- * specific RAU size
- */
- ps.ystride[0] = ALIGN(pipe->src.w / 16 , 32) * 16 *
- ps.rau_h[0] * pipe->src_fmt->bpp;
+ ps.ystride[0] = ALIGN(seg_w, 32) * 16 * ps.rau_h[0] *
+ pipe->src_fmt->bpp;
ps.ystride[1] = 0;
} else {
- u32 bwc_width = ALIGN(pipe->src.w / 16, 64) * 16;
+ u32 bwc_width = ALIGN(seg_w, 64) * 16;
ps.ystride[0] = bwc_width * ps.rau_h[0];
ps.ystride[1] = bwc_width * ps.rau_h[1];
/*
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
index a0663e3..834ef66 100644
--- a/drivers/video/msm/mdss/msm_mdss_io_8974.c
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -259,7 +259,7 @@
return 0;
}
-int mdss_dsi_bus_clk_start(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+static int mdss_dsi_bus_clk_start(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
int rc = 0;
@@ -303,7 +303,7 @@
return rc;
}
-void mdss_dsi_bus_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
+static void mdss_dsi_bus_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl_pdata)
{
if (ctrl_pdata->mmss_misc_ahb_clk)
clk_disable_unprepare(ctrl_pdata->mmss_misc_ahb_clk);
@@ -408,11 +408,6 @@
pr_debug("%s: ndx=%d\n", __func__, ctrl_pdata->ndx);
- if (ctrl_pdata->mdss_dsi_clk_on) {
- pr_info("%s: mdss_dsi_clks already ON\n", __func__);
- return 0;
- }
-
rc = clk_enable(ctrl_pdata->esc_clk);
if (rc) {
pr_err("%s: Failed to enable dsi esc clk\n", __func__);
@@ -431,8 +426,6 @@
goto pixel_clk_err;
}
- ctrl_pdata->mdss_dsi_clk_on = 1;
-
return rc;
pixel_clk_err:
@@ -452,19 +445,12 @@
pr_debug("%s: ndx=%d\n", __func__, ctrl_pdata->ndx);
- if (ctrl_pdata->mdss_dsi_clk_on == 0) {
- pr_info("%s: mdss_dsi_clks already OFF\n", __func__);
- return;
- }
-
clk_disable(ctrl_pdata->esc_clk);
clk_disable(ctrl_pdata->pixel_clk);
clk_disable(ctrl_pdata->byte_clk);
-
- ctrl_pdata->mdss_dsi_clk_on = 0;
}
-int mdss_dsi_link_clk_start(struct mdss_dsi_ctrl_pdata *ctrl)
+static int mdss_dsi_link_clk_start(struct mdss_dsi_ctrl_pdata *ctrl)
{
int rc = 0;
@@ -494,90 +480,191 @@
return rc;
}
-void mdss_dsi_link_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl)
+static void mdss_dsi_link_clk_stop(struct mdss_dsi_ctrl_pdata *ctrl)
{
mdss_dsi_link_clk_disable(ctrl);
mdss_dsi_link_clk_unprepare(ctrl);
}
-static void mdss_dsi_clk_ctrl_sub(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
+static int __mdss_dsi_update_clk_cnt(u32 *clk_cnt, int enable)
{
int changed = 0;
if (enable) {
- if (ctrl->clk_cnt_sub == 0)
+ if (*clk_cnt == 0)
changed++;
- ctrl->clk_cnt_sub++;
+ (*clk_cnt)++;
} else {
- if (ctrl->clk_cnt_sub) {
- ctrl->clk_cnt_sub--;
- if (ctrl->clk_cnt_sub == 0)
+ if (*clk_cnt != 0) {
+ (*clk_cnt)--;
+ if (*clk_cnt == 0)
changed++;
} else {
- pr_debug("%s: Can not be turned off\n", __func__);
+ pr_debug("%s: clk cnt already zero\n", __func__);
}
}
- pr_debug("%s: ndx=%d clk_cnt_sub=%d changed=%d enable=%d\n",
- __func__, ctrl->ndx, ctrl->clk_cnt_sub, changed, enable);
- if (changed) {
- if (enable) {
- if (mdss_dsi_bus_clk_start(ctrl) == 0)
- mdss_dsi_link_clk_start(ctrl);
- } else {
- mdss_dsi_link_clk_stop(ctrl);
- mdss_dsi_bus_clk_stop(ctrl);
+ return changed;
+}
+
+static int mdss_dsi_clk_ctrl_sub(struct mdss_dsi_ctrl_pdata *ctrl,
+ u8 clk_type, int enable)
+{
+ int rc = 0;
+
+ pr_debug("%s: ndx=%d clk_type=%08x enable=%d\n", __func__,
+ ctrl->ndx, clk_type, enable);
+
+ if (enable) {
+ if (clk_type & DSI_BUS_CLKS) {
+ rc = mdss_dsi_bus_clk_start(ctrl);
+ if (rc) {
+ pr_err("Failed to start bus clocks. rc=%d\n",
+ rc);
+ goto error;
+ }
}
+ if (clk_type & DSI_LINK_CLKS) {
+ rc = mdss_dsi_link_clk_start(ctrl);
+ if (rc) {
+ pr_err("Failed to start link clocks. rc=%d\n",
+ rc);
+ if (clk_type & DSI_BUS_CLKS)
+ mdss_dsi_bus_clk_stop(ctrl);
+ goto error;
+ }
+ }
+ } else {
+ if (clk_type & DSI_LINK_CLKS)
+ mdss_dsi_link_clk_stop(ctrl);
+ if (clk_type & DSI_BUS_CLKS)
+ mdss_dsi_bus_clk_stop(ctrl);
}
+
+error:
+ return rc;
}
static DEFINE_MUTEX(dsi_clk_lock); /* per system */
-bool __mdss_dsi_clk_enabled(struct mdss_dsi_ctrl_pdata *ctrl)
+bool __mdss_dsi_clk_enabled(struct mdss_dsi_ctrl_pdata *ctrl, u8 clk_type)
{
- bool enabled;
+ bool bus_enabled = true;
+ bool link_enabled = true;
+
mutex_lock(&dsi_clk_lock);
- enabled = ctrl->clk_cnt ? true : false;
+ if (clk_type & DSI_BUS_CLKS)
+ bus_enabled = ctrl->bus_clk_cnt ? true : false;
+ if (clk_type & DSI_LINK_CLKS)
+ link_enabled = ctrl->link_clk_cnt ? true : false;
mutex_unlock(&dsi_clk_lock);
- return enabled;
+ return bus_enabled && link_enabled;
}
-void mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl, int enable)
+int mdss_dsi_clk_ctrl(struct mdss_dsi_ctrl_pdata *ctrl,
+ u8 clk_type, int enable)
{
- int changed = 0;
- struct mdss_dsi_ctrl_pdata *sctrl = NULL;
+ int rc = 0;
+ int changed = 0, m_changed = 0;
+ struct mdss_dsi_ctrl_pdata *mctrl = NULL;
+
+ if (!ctrl) {
+ pr_err("%s: Invalid arg\n", __func__);
+ return -EINVAL;
+ }
+
+ /*
+ * In broadcast mode, we need to enable clocks for the
+ * master controller as well when enabling clocks for the
+ * slave controller
+ */
+ if (mdss_dsi_is_slave_ctrl(ctrl)) {
+ mctrl = mdss_dsi_get_master_ctrl();
+ if (!mctrl)
+ pr_warn("%s: Unable to get master control\n", __func__);
+ }
+
+ pr_debug("%s++: ndx=%d clk_type=%d bus_clk_cnt=%d link_clk_cnt=%d",
+ __func__, ctrl->ndx, clk_type, ctrl->bus_clk_cnt,
+ ctrl->link_clk_cnt);
+ pr_debug("%s++: mctrl=%s m_bus_clk_cnt=%d m_link_clk_cnt=%d\n, enable=%d\n",
+ __func__, mctrl ? "yes" : "no", mctrl ? mctrl->bus_clk_cnt : -1,
+ mctrl ? mctrl->link_clk_cnt : -1, enable);
mutex_lock(&dsi_clk_lock);
- if (enable) {
- if (ctrl->clk_cnt == 0)
- changed++;
- ctrl->clk_cnt++;
- } else {
- if (ctrl->clk_cnt) {
- ctrl->clk_cnt--;
- if (ctrl->clk_cnt == 0)
- changed++;
- } else {
- pr_debug("%s: Can not be turned off\n", __func__);
- }
+ if (clk_type & DSI_BUS_CLKS) {
+ changed = __mdss_dsi_update_clk_cnt(&ctrl->bus_clk_cnt,
+ enable);
+ if (changed && mctrl)
+ m_changed = __mdss_dsi_update_clk_cnt(
+ &mctrl->bus_clk_cnt, enable);
}
- pr_debug("%s: ndx=%d clk_cnt=%d changed=%d enable=%d\n",
- __func__, ctrl->ndx, ctrl->clk_cnt, changed, enable);
- if (ctrl->flags & DSI_FLAG_CLOCK_MASTER)
- sctrl = mdss_dsi_ctrl_slave(ctrl);
+ if (clk_type & DSI_LINK_CLKS) {
+ changed += __mdss_dsi_update_clk_cnt(&ctrl->link_clk_cnt,
+ enable);
+ if (changed && mctrl)
+ m_changed += __mdss_dsi_update_clk_cnt(
+ &mctrl->link_clk_cnt, enable);
+ }
if (changed) {
- if (enable && sctrl)
- mdss_dsi_clk_ctrl_sub(sctrl, enable);
+ if (enable && m_changed) {
+ rc = mdss_dsi_clk_ctrl_sub(mctrl, clk_type, enable);
+ if (rc) {
+ pr_err("Failed to start mctrl clocks. rc=%d\n",
+ rc);
+ goto error_mctrl_start;
+ }
+ }
- mdss_dsi_clk_ctrl_sub(ctrl, enable);
+ rc = mdss_dsi_clk_ctrl_sub(ctrl, clk_type, enable);
+ if (rc) {
+ pr_err("Failed to %s ctrl clocks. rc=%d\n",
+ (enable ? "start" : "stop"), rc);
+ goto error_ctrl;
+ }
- if (!enable && sctrl)
- mdss_dsi_clk_ctrl_sub(sctrl, enable);
+ if (!enable && m_changed) {
+ rc = mdss_dsi_clk_ctrl_sub(mctrl, clk_type, enable);
+ if (rc) {
+ pr_err("Failed to stop mctrl clocks. rc=%d\n",
+ rc);
+ goto error_mctrl_stop;
+ }
+ }
}
+ goto no_error;
+
+error_mctrl_stop:
+ mdss_dsi_clk_ctrl_sub(ctrl, clk_type, enable ? 0 : 1);
+error_ctrl:
+ mdss_dsi_clk_ctrl_sub(mctrl, clk_type, 0);
+error_mctrl_start:
+ if (clk_type & DSI_BUS_CLKS) {
+ if (mctrl)
+ __mdss_dsi_update_clk_cnt(&mctrl->bus_clk_cnt,
+ enable ? 0 : 1);
+ __mdss_dsi_update_clk_cnt(&ctrl->bus_clk_cnt, enable ? 0 : 1);
+ }
+ if (clk_type & DSI_LINK_CLKS) {
+ if (mctrl)
+ __mdss_dsi_update_clk_cnt(&mctrl->link_clk_cnt,
+ enable ? 0 : 1);
+ __mdss_dsi_update_clk_cnt(&ctrl->link_clk_cnt, enable ? 0 : 1);
+ }
+
+no_error:
mutex_unlock(&dsi_clk_lock);
+ pr_debug("%s++: ndx=%d clk_type=%d bus_clk_cnt=%d link_clk_cnt=%d changed=%d",
+ __func__, ctrl->ndx, clk_type, ctrl->bus_clk_cnt,
+ ctrl->link_clk_cnt, changed);
+ pr_debug("%s++: mctrl=%s m_bus_clk_cnt=%d m_link_clk_cnt=%d\n, m_changed=%d, enable=%d\n",
+ __func__, mctrl ? "yes" : "no", mctrl ? mctrl->bus_clk_cnt : -1,
+ mctrl ? mctrl->link_clk_cnt : -1, m_changed, enable);
+
+ return rc;
}
void mdss_dsi_phy_sw_reset(unsigned char *ctrl_base)
@@ -594,29 +681,39 @@
void mdss_dsi_phy_disable(struct mdss_dsi_ctrl_pdata *ctrl)
{
- static struct mdss_dsi_ctrl_pdata *left_ctrl;
+ struct mdss_dsi_ctrl_pdata *ctrl0 = NULL;
if (ctrl == NULL) {
pr_err("%s: Invalid input data\n", __func__);
return;
}
- if (left_ctrl &&
- (ctrl->panel_data.panel_info.pdest == DISPLAY_1))
+ /*
+ * In dual-dsi configuration, the phy should be disabled for the
+ * first controller only when the second controller is disabled.
+ * This is true regardless of whether broadcast mode is enabled
+ * or not.
+ */
+ if ((ctrl->ndx == DSI_CTRL_0) &&
+ mdss_dsi_get_ctrl_by_index(DSI_CTRL_1)) {
+ pr_debug("%s: Dual dsi detected. skipping config for ctrl%d\n",
+ __func__, ctrl->ndx);
return;
-
- if (left_ctrl &&
- (ctrl->panel_data.panel_info.pdest
- ==
- DISPLAY_2)) {
- MIPI_OUTP(left_ctrl->ctrl_base + 0x0470,
- 0x000);
- MIPI_OUTP(left_ctrl->ctrl_base + 0x0598,
- 0x000);
}
- MIPI_OUTP(ctrl->ctrl_base + 0x0470, 0x000);
- MIPI_OUTP(ctrl->ctrl_base + 0x0598, 0x000);
+ if (ctrl->ndx == DSI_CTRL_1) {
+ ctrl0 = mdss_dsi_get_ctrl_by_index(DSI_CTRL_0);
+ if (ctrl0) {
+ MIPI_OUTP(ctrl0->phy_io.base + 0x0170, 0x000);
+ MIPI_OUTP(ctrl0->phy_io.base + 0x0298, 0x000);
+ } else {
+ pr_warn("%s: Unable to get control%d\n",
+ __func__, DSI_CTRL_0);
+ }
+ }
+
+ MIPI_OUTP(ctrl->phy_io.base + 0x0170, 0x000);
+ MIPI_OUTP(ctrl->phy_io.base + 0x0298, 0x000);
/*
* Wait for the registers writes to complete in order to
@@ -629,7 +726,7 @@
{
struct mdss_dsi_phy_ctrl *pd;
int i, off, ln, offset;
- struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+ struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL, *temp_ctrl = NULL;
ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
panel_data);
@@ -637,67 +734,75 @@
pr_err("%s: Invalid input data\n", __func__);
return;
}
+ temp_ctrl = ctrl_pdata;
pd = &(((ctrl_pdata->panel_data).panel_info.mipi).dsi_phy_db);
/* Strength ctrl 0 */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0484, pd->strength[0]);
+ MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0184, pd->strength[0]);
- /* phy regulator ctrl settings. Both the DSI controller
- have one regulator */
- if ((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1)
- off = 0x0580;
- else
- off = 0x0580 - 0x600;
+ /*
+ * Phy regulator ctrl settings.
+ * In dual dsi configuration, the second controller also uses
+ * the regulators of the first controller, irrespective of whether
+ * broadcast mode is enabled or not.
+ */
+ if (ctrl_pdata->ndx == DSI_CTRL_1) {
+ temp_ctrl = mdss_dsi_get_ctrl_by_index(DSI_CTRL_0);
+ if (!temp_ctrl) {
+ pr_err("%s: Unable to get master ctrl\n", __func__);
+ return;
+ }
+ }
/* Regulator ctrl 0 */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 0), 0x0);
+ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x280, 0x0);
/* Regulator ctrl - CAL_PWR_CFG */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 6), pd->regulator[6]);
+ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x298, pd->regulator[6]);
/* Regulator ctrl - TEST */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 5), pd->regulator[5]);
+ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x294, pd->regulator[5]);
/* Regulator ctrl 3 */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 3), pd->regulator[3]);
+ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x28c, pd->regulator[3]);
/* Regulator ctrl 2 */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 2), pd->regulator[2]);
+ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x288, pd->regulator[2]);
/* Regulator ctrl 1 */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 1), pd->regulator[1]);
+ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x284, pd->regulator[1]);
/* Regulator ctrl 0 */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 0), pd->regulator[0]);
+ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x280, pd->regulator[0]);
/* Regulator ctrl 4 */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + off + (4 * 4), pd->regulator[4]);
+ MIPI_OUTP((temp_ctrl->phy_io.base) + 0x290, pd->regulator[4]);
/* LDO ctrl 0 */
if ((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1)
- MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x4dc, 0x00);
+ MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x1dc, 0x00);
else
- MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x4dc, 0x00);
+ MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x1dc, 0x00);
- off = 0x0440; /* phy timing ctrl 0 - 11 */
+ off = 0x0140; /* phy timing ctrl 0 - 11 */
for (i = 0; i < 12; i++) {
- MIPI_OUTP((ctrl_pdata->ctrl_base) + off, pd->timing[i]);
+ MIPI_OUTP((ctrl_pdata->phy_io.base) + off, pd->timing[i]);
wmb();
off += 4;
}
/* MMSS_DSI_0_PHY_DSIPHY_CTRL_1 */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0474, 0x00);
+ MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0174, 0x00);
/* MMSS_DSI_0_PHY_DSIPHY_CTRL_0 */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0470, 0x5f);
+ MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0170, 0x5f);
wmb();
/* Strength ctrl 1 */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0488, pd->strength[1]);
+ MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0188, pd->strength[1]);
wmb();
/* 4 lanes + clk lane configuration */
/* lane config n * (0 - 4) & DataPath setup */
for (ln = 0; ln < 5; ln++) {
- off = 0x0300 + (ln * 0x40);
+ off = (ln * 0x40);
for (i = 0; i < 9; i++) {
offset = i + (ln * 9);
- MIPI_OUTP((ctrl_pdata->ctrl_base) + off,
+ MIPI_OUTP((ctrl_pdata->phy_io.base) + off,
pd->lanecfg[offset]);
wmb();
off += 4;
@@ -705,19 +810,19 @@
}
/* MMSS_DSI_0_PHY_DSIPHY_CTRL_0 */
- MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0470, 0x5f);
+ MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x0170, 0x5f);
wmb();
/* DSI_0_PHY_DSIPHY_GLBL_TEST_CTRL */
if ((ctrl_pdata->panel_data).panel_info.pdest == DISPLAY_1)
- MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x04d4, 0x01);
+ MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x01d4, 0x01);
else
- MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x04d4, 0x00);
+ MIPI_OUTP((ctrl_pdata->phy_io.base) + 0x01d4, 0x00);
wmb();
- off = 0x04b4; /* phy BIST ctrl 0 - 5 */
+ off = 0x01b4; /* phy BIST ctrl 0 - 5 */
for (i = 0; i < 6; i++) {
- MIPI_OUTP((ctrl_pdata->ctrl_base) + off, pd->bistctrl[i]);
+ MIPI_OUTP((ctrl_pdata->phy_io.base) + off, pd->bistctrl[i]);
wmb();
off += 4;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 02ced89..157d63a 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -725,9 +725,9 @@
if (voc_get_route_flag(session_id, RX_PATH) &&
voc_get_route_flag(session_id, TX_PATH))
- voc_enable_cvp(session_id);
+ voc_enable_device(session_id);
} else {
- voc_disable_cvp(session_id);
+ voc_disable_device(session_id);
}
} else {
voc_set_route_flag(session_id, TX_PATH, set);
@@ -736,9 +736,9 @@
msm_bedais[reg].port_id, DEV_TX);
if (voc_get_route_flag(session_id, RX_PATH) &&
voc_get_route_flag(session_id, TX_PATH))
- voc_enable_cvp(session_id);
+ voc_enable_device(session_id);
} else {
- voc_disable_cvp(session_id);
+ voc_disable_device(session_id);
}
}
}
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 48bf2f4..0d19657 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -393,60 +393,52 @@
struct list_head *ptr, *next;
int result;
int size = 4096;
+
+ if (!set_custom_topology)
+ return;
+
get_asm_custom_topology(&cal_block);
if (cal_block.cal_size == 0) {
- pr_debug("%s: no cal to send addr= 0x%x\n",
- __func__, cal_block.cal_paddr);
- goto done;
+ pr_debug("%s: no cal to send addr= 0x%pa\n",
+ __func__, &cal_block.cal_paddr);
+ return;
}
- if (set_custom_topology) {
- if (common_client.mmap_apr == NULL) {
- common_client.mmap_apr = q6asm_mmap_apr_reg();
- common_client.apr = common_client.mmap_apr;
- if (common_client.mmap_apr == NULL) {
- pr_err("%s: q6asm_mmap_apr_reg failed\n",
- __func__);
- result = -EPERM;
- goto done;
- }
- }
- /* Only call this once */
- set_custom_topology = 0;
+ common_client.mmap_apr = q6asm_mmap_apr_reg();
+ common_client.apr = common_client.mmap_apr;
+ if (common_client.mmap_apr == NULL) {
+ pr_err("%s: q6asm_mmap_apr_reg failed\n",
+ __func__);
+ result = -EPERM;
+ goto mmap_fail;
+ }
+ /* Only call this once */
+ set_custom_topology = 0;
- /* Use first asm buf to map memory */
- if (common_client.port[IN].buf == NULL) {
- pr_err("%s: common buf is NULL\n",
- __func__);
- goto done;
- }
- common_client.port[IN].buf->phys = cal_block.cal_paddr;
+ /* Use first asm buf to map memory */
+ if (common_client.port[IN].buf == NULL) {
+ pr_err("%s: common buf is NULL\n",
+ __func__);
+ goto err_map;
+ }
+ common_client.port[IN].buf->phys = cal_block.cal_paddr;
- result = q6asm_memory_map_regions(&common_client,
- IN, size, 1, 1);
- if (result < 0) {
- pr_err("%s: mmap did not work! addr = 0x%x, size = %d\n",
- __func__, cal_block.cal_paddr,
- cal_block.cal_size);
- goto done;
- }
+ result = q6asm_memory_map_regions(&common_client,
+ IN, size, 1, 1);
+ if (result < 0) {
+ pr_err("%s: mmap did not work! addr = 0x%pa, size = %zd\n",
+ __func__, &cal_block.cal_paddr,
+ cal_block.cal_size);
+ goto err_map;
+ }
- list_for_each_safe(ptr, next,
- &common_client.port[IN].mem_map_handle) {
- buf_node = list_entry(ptr, struct asm_buffer_node,
- list);
- if (buf_node->buf_addr_lsw == cal_block.cal_paddr) {
- topology_map_handle = buf_node->mmap_hdl;
- break;
- }
- }
-
- result = q6asm_mmap_apr_dereg();
- if (result < 0) {
- pr_err("%s: q6asm_mmap_apr_dereg failed, err %d\n",
- __func__, result);
- } else {
- common_client.mmap_apr = NULL;
+ list_for_each_safe(ptr, next,
+ &common_client.port[IN].mem_map_handle) {
+ buf_node = list_entry(ptr, struct asm_buffer_node,
+ list);
+ if (buf_node->buf_addr_lsw == cal_block.cal_paddr) {
+ topology_map_handle = buf_node->mmap_hdl;
+ break;
}
}
@@ -468,7 +460,7 @@
if (result < 0) {
pr_err("%s: Set topologies failed payload = 0x%x\n",
__func__, cal_block.cal_paddr);
- goto done;
+ goto err_unmap;
}
result = wait_event_timeout(ac->cmd_wait,
@@ -476,10 +468,15 @@
if (!result) {
pr_err("%s: Set topologies failed after timedout payload = 0x%x\n",
__func__, cal_block.cal_paddr);
- goto done;
+ goto err_unmap;
}
-
-done:
+ return;
+err_unmap:
+ q6asm_memory_unmap_regions(ac, IN);
+err_map:
+ q6asm_mmap_apr_dereg();
+ set_custom_topology = 1;
+mmap_fail:
return;
}
@@ -768,6 +765,7 @@
apr_deregister(ac->apr);
ac->apr = NULL;
ac->mmap_apr = NULL;
+ rtac_set_asm_handle(ac->session, ac->apr);
q6asm_session_free(ac);
q6asm_mmap_apr_dereg();
@@ -857,7 +855,7 @@
if (ac->apr == NULL) {
pr_err("%s Registration with APR failed\n", __func__);
mutex_unlock(&session_lock);
- goto fail;
+ goto fail_apr1;
}
ac->apr2 = apr_register("ADSP", "ASM", \
(apr_fn)q6asm_callback,\
@@ -867,16 +865,17 @@
if (ac->apr2 == NULL) {
pr_err("%s Registration with APR-2 failed\n", __func__);
mutex_unlock(&session_lock);
- goto fail;
+ goto fail_apr2;
}
+
rtac_set_asm_handle(n, ac->apr);
pr_debug("%s Registering the common port with APR\n", __func__);
ac->mmap_apr = q6asm_mmap_apr_reg();
if (ac->mmap_apr == NULL) {
mutex_unlock(&session_lock);
- goto fail;
- }
+ goto fail_mmap;
+ }
init_waitqueue_head(&ac->cmd_wait);
init_waitqueue_head(&ac->time_wait);
@@ -899,9 +898,12 @@
mutex_unlock(&session_lock);
return ac;
-fail:
- q6asm_audio_client_free(ac);
- return NULL;
+fail_mmap:
+ apr_deregister(ac->apr2);
+fail_apr2:
+ apr_deregister(ac->apr);
+fail_apr1:
+ q6asm_session_free(ac);
fail_session:
kfree(ac);
return NULL;
@@ -1115,12 +1117,20 @@
payload = data->payload;
if (data->opcode == RESET_EVENTS) {
+ struct audio_client *ac_mmap = (struct audio_client *)priv;
+ if (ac_mmap == NULL) {
+ pr_err("%s ac or priv NULL\n", __func__);
+ return -EINVAL;
+ }
pr_debug("%s: Reset event is received: %d %d apr[%p]\n",
__func__,
data->reset_event,
data->reset_proc,
this_mmap.apr);
+ atomic_set(&this_mmap.ref_cnt, 0);
apr_reset(this_mmap.apr);
+ this_mmap.apr = NULL;
+ ac_mmap->mmap_apr = NULL;
for (; i <= OUT; i++) {
list_for_each_safe(ptr, next,
&common_client.port[i].mem_map_handle) {
@@ -1135,7 +1145,6 @@
}
pr_debug("%s:Clearing custom topology\n", __func__);
}
- this_mmap.apr = NULL;
reset_custom_topology_flags();
set_custom_topology = 1;
topology_map_handle = 0;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index e051c31..1ca9b1a 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -94,6 +94,8 @@
static int voice_alloc_oob_mem_table(void);
static int voice_alloc_and_map_cal_mem(struct voice_data *v);
static int voice_alloc_and_map_oob_mem(struct voice_data *v);
+static int voc_disable_cvp(uint32_t session_id);
+static int voc_enable_cvp(uint32_t session_id);
static struct voice_data *voice_get_session_by_idx(int idx);
@@ -1081,39 +1083,37 @@
}
mvm_handle = voice_get_mvm_handle(v);
- if (v->tty_mode) {
- /* send tty mode cmd to mvm */
- mvm_tty_mode_cmd.hdr.hdr_field = APR_HDR_FIELD(
- APR_MSG_TYPE_SEQ_CMD,
- APR_HDR_LEN(APR_HDR_SIZE),
- APR_PKT_VER);
- mvm_tty_mode_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
- sizeof(mvm_tty_mode_cmd) -
- APR_HDR_SIZE);
- pr_debug("%s: pkt size = %d\n",
- __func__, mvm_tty_mode_cmd.hdr.pkt_size);
- mvm_tty_mode_cmd.hdr.src_port =
- voice_get_idx_for_session(v->session_id);
- mvm_tty_mode_cmd.hdr.dest_port = mvm_handle;
- mvm_tty_mode_cmd.hdr.token = 0;
- mvm_tty_mode_cmd.hdr.opcode = VSS_ISTREAM_CMD_SET_TTY_MODE;
- mvm_tty_mode_cmd.tty_mode.mode = v->tty_mode;
- pr_debug("tty mode =%d\n", mvm_tty_mode_cmd.tty_mode.mode);
+ /* send tty mode cmd to mvm */
+ mvm_tty_mode_cmd.hdr.hdr_field = APR_HDR_FIELD(
+ APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE),
+ APR_PKT_VER);
+ mvm_tty_mode_cmd.hdr.pkt_size = APR_PKT_SIZE(APR_HDR_SIZE,
+ sizeof(mvm_tty_mode_cmd) -
+ APR_HDR_SIZE);
+ pr_debug("%s: pkt size = %d\n",
+ __func__, mvm_tty_mode_cmd.hdr.pkt_size);
+ mvm_tty_mode_cmd.hdr.src_port =
+ voice_get_idx_for_session(v->session_id);
+ mvm_tty_mode_cmd.hdr.dest_port = mvm_handle;
+ mvm_tty_mode_cmd.hdr.token = 0;
+ mvm_tty_mode_cmd.hdr.opcode = VSS_ISTREAM_CMD_SET_TTY_MODE;
+ mvm_tty_mode_cmd.tty_mode.mode = v->tty_mode;
+ pr_debug("tty mode =%d\n", mvm_tty_mode_cmd.tty_mode.mode);
- v->mvm_state = CMD_STATUS_FAIL;
- ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_tty_mode_cmd);
- if (ret < 0) {
- pr_err("%s: Error %d sending SET_TTY_MODE\n",
- __func__, ret);
- goto fail;
- }
- ret = wait_event_timeout(v->mvm_wait,
- (v->mvm_state == CMD_STATUS_SUCCESS),
- msecs_to_jiffies(TIMEOUT_MS));
- if (!ret) {
- pr_err("%s: wait_event timeout\n", __func__);
- goto fail;
- }
+ v->mvm_state = CMD_STATUS_FAIL;
+ ret = apr_send_pkt(apr_mvm, (uint32_t *) &mvm_tty_mode_cmd);
+ if (ret < 0) {
+ pr_err("%s: Error %d sending SET_TTY_MODE\n",
+ __func__, ret);
+ goto fail;
+ }
+ ret = wait_event_timeout(v->mvm_wait,
+ (v->mvm_state == CMD_STATUS_SUCCESS),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: wait_event timeout\n", __func__);
+ goto fail;
}
return 0;
fail:
@@ -3166,8 +3166,7 @@
voice_send_netid_timing_cmd(v);
}
- /* enable slowtalk if st_enable is set */
- if (v->st_enable)
+ if (v->st_enable && !v->tty_mode)
voice_send_set_pp_enable_cmd(v,
MODULE_ID_VOICE_MODULE_ST,
v->st_enable);
@@ -4379,7 +4378,7 @@
return ret;
}
-int voc_disable_cvp(uint32_t session_id)
+static int voc_disable_cvp(uint32_t session_id)
{
struct voice_data *v = voice_get_session(session_id);
int ret = 0;
@@ -4414,7 +4413,7 @@
return ret;
}
-int voc_enable_cvp(uint32_t session_id)
+static int voc_enable_cvp(uint32_t session_id)
{
struct voice_data *v = voice_get_session(session_id);
int ret = 0;
@@ -4486,10 +4485,8 @@
goto fail;
}
- /* Send tty mode if tty device is used */
voice_send_tty_mode_cmd(v);
- /* enable slowtalk */
- if (v->st_enable)
+ if (v->st_enable && !v->tty_mode)
voice_send_set_pp_enable_cmd(v,
MODULE_ID_VOICE_MODULE_ST,
v->st_enable);
@@ -4689,8 +4686,8 @@
v->st_enable = enable;
if (v->voc_state == VOC_RUN) {
- if (module_id ==
- MODULE_ID_VOICE_MODULE_ST)
+ if ((module_id == MODULE_ID_VOICE_MODULE_ST) &&
+ (!v->tty_mode))
ret = voice_send_set_pp_enable_cmd(v,
MODULE_ID_VOICE_MODULE_ST,
enable);
@@ -4913,6 +4910,110 @@
return ret;
}
+int voc_disable_device(uint32_t session_id)
+{
+ struct voice_data *v = voice_get_session(session_id);
+ int ret = 0;
+
+ pr_debug("%s: voc state=%d\n", __func__, v->voc_state);
+ if (v == NULL) {
+ pr_err("%s: v is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&v->lock);
+ if (v->voc_state == VOC_RUN) {
+ ret = voice_pause_voice_call(v);
+ if (ret < 0) {
+ pr_err("%s: Pause Voice Call failed for session 0x%x, err %d!\n",
+ __func__, v->session_id, ret);
+ goto done;
+ }
+ rtac_remove_voice(voice_get_cvs_handle(v));
+ voice_send_cvp_deregister_vol_cal_cmd(v);
+ voice_send_cvp_deregister_cal_cmd(v);
+ voice_send_cvp_deregister_dev_cfg_cmd(v);
+
+ v->voc_state = VOC_CHANGE;
+ } else {
+ pr_debug("%s: called in voc state=%d, No_OP\n",
+ __func__, v->voc_state);
+ }
+
+ if (common.ec_ref_ext)
+ voc_set_ext_ec_ref(AFE_PORT_INVALID, false);
+done:
+ mutex_unlock(&v->lock);
+
+ return ret;
+}
+
+int voc_enable_device(uint32_t session_id)
+{
+ struct voice_data *v = voice_get_session(session_id);
+ int ret = 0;
+
+ pr_debug("%s: voc state=%d\n", __func__, v->voc_state);
+ if (v == NULL) {
+ pr_err("%s: v is NULL\n", __func__);
+ return -EINVAL;
+ }
+
+ mutex_lock(&v->lock);
+ if (v->voc_state == VOC_CHANGE) {
+ ret = voice_send_tty_mode_cmd(v);
+ if (ret < 0) {
+ pr_err("%s: Sending TTY mode failed, ret=%d\n",
+ __func__, ret);
+ /* Not a critical error, allow voice call to continue */
+ }
+
+ if (v->tty_mode) {
+ /* disable slowtalk */
+ voice_send_set_pp_enable_cmd(v,
+ MODULE_ID_VOICE_MODULE_ST,
+ 0);
+ } else {
+ /* restore slowtalk */
+ voice_send_set_pp_enable_cmd(v,
+ MODULE_ID_VOICE_MODULE_ST,
+ v->st_enable);
+ }
+
+ ret = voice_send_set_device_cmd(v);
+ if (ret < 0) {
+ pr_err("%s: Set device failed, ret=%d\n",
+ __func__, ret);
+ goto done;
+ }
+
+ voice_send_cvp_register_dev_cfg_cmd(v);
+ voice_send_cvp_register_cal_cmd(v);
+ voice_send_cvp_register_vol_cal_cmd(v);
+
+ rtac_add_voice(voice_get_cvs_handle(v),
+ voice_get_cvp_handle(v),
+ v->dev_rx.port_id, v->dev_tx.port_id,
+ v->session_id);
+
+ ret = voice_send_start_voice_cmd(v);
+ if (ret < 0) {
+ pr_err("%s: Fail in sending START_VOICE, ret=%d\n",
+ __func__, ret);
+ goto done;
+ }
+ v->voc_state = VOC_RUN;
+ } else {
+ pr_debug("%s: called in voc state=%d, No_OP\n",
+ __func__, v->voc_state);
+ }
+
+done:
+ mutex_unlock(&v->lock);
+
+ return ret;
+}
+
int voc_set_lch(uint32_t session_id, enum voice_lch_mode lch_mode)
{
struct voice_data *v = voice_get_session(session_id);
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index b1a6c04..c6f3482 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1447,8 +1447,6 @@
int voc_set_device_mute(uint32_t session_id, uint32_t dir, uint32_t mute,
uint32_t ramp_duration);
int voc_get_rx_device_mute(uint32_t session_id);
-int voc_disable_cvp(uint32_t session_id);
-int voc_enable_cvp(uint32_t session_id);
int voc_set_route_flag(uint32_t session_id, uint8_t path_dir, uint8_t set);
uint8_t voc_get_route_flag(uint32_t session_id, uint8_t path_dir);
int voc_enable_dtmf_rx_detection(uint32_t session_id, uint32_t enable);
@@ -1470,5 +1468,7 @@
int voice_get_idx_for_session(u32 session_id);
int voc_set_ext_ec_ref(uint16_t port_id, bool state);
int voc_update_amr_vocoder_rate(uint32_t session_id);
+int voc_disable_device(uint32_t session_id);
+int voc_enable_device(uint32_t session_id);
#endif