Merge "msm: mdss: Enable solid fill on pipe"
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 714311e..623a23c 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -91,6 +91,8 @@
runs using PNOC clock and synchronous to it. Hence it is must to have proper
"qcom,msm_bus,vectors" to have high bus frequency. User shouldn't try to
enable this feature without proper bus voting.
+-qcom,disable-retention-with-vdd-min: If present dont allow phy retention but allow
+ vdd min.
Example HSUSB OTG controller device node :
usb@f9690000 {
@@ -115,6 +117,7 @@
HSUSB_3p3-supply = <&pm8226_l20>;
qcom,vdd-voltage-level = <1 5 7>;
qcom,dp-manual-pullup;
+ qcom,disable-retention-with-vdd-min;
qcom,hsusb-otg-dpsehv-int = <49>;
qcom,hsusb-otg-dmsehv-int = <58>;
qcom,msm_bus,name = "usb2";
diff --git a/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi b/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
index 30eda91..5393756 100644
--- a/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
+++ b/arch/arm/boot/dts/dsi-panel-orise-720p-video.dtsi
@@ -34,7 +34,7 @@
qcom,mdss-pan-dsi-stream = <0>;
qcom,mdss-pan-dsi-mdp-tr = <0x0>;
qcom,mdss-pan-dsi-dma-tr = <0x04>;
- qcom,mdss-pan-dsi-frame-rate = <60>;
+ qcom,mdss-pan-dsi-framerate = <60>;
qcom,panel-phy-regulatorSettings = [03 01 01 00 /* Regualotor settings */
20 00 01];
qcom,panel-phy-timingSettings = [69 29 1f 00 55 55
diff --git a/arch/arm/boot/dts/msm8610-mtp.dtsi b/arch/arm/boot/dts/msm8610-mtp.dtsi
index 6ce0109..3b0f2a2 100644
--- a/arch/arm/boot/dts/msm8610-mtp.dtsi
+++ b/arch/arm/boot/dts/msm8610-mtp.dtsi
@@ -142,7 +142,7 @@
0x2800>;
capella,ps_close_thd_set = <0xa>;
capella,ps_away_thd_set = <0x5>;
- capella,ls_cmd = <0x44>; /* PS_IT=160ms, INT_PERS=2*/
+ capella,ls_cmd = <0x04>; /* ALS_IT=80ms, INT_PERS=2*/
capella,ps_conf1_val = <0x0006>;
capella,ps_conf3_val = <0x3010>;
};
diff --git a/arch/arm/boot/dts/msm8610.dtsi b/arch/arm/boot/dts/msm8610.dtsi
index 1619d1f..9ee96a7 100644
--- a/arch/arm/boot/dts/msm8610.dtsi
+++ b/arch/arm/boot/dts/msm8610.dtsi
@@ -240,6 +240,7 @@
qcom,hsusb-otg-disable-reset;
qcom,dp-manual-pullup;
qcom,ahb-async-bridge-bypass;
+ qcom,disable-retention-with-vdd-min;
qcom,msm-bus,name = "usb2";
qcom,msm-bus,num-cases = <2>;
diff --git a/arch/arm/configs/msm8610-perf_defconfig b/arch/arm/configs/msm8610-perf_defconfig
index 8366a41..84dee5d 100644
--- a/arch/arm/configs/msm8610-perf_defconfig
+++ b/arch/arm/configs/msm8610-perf_defconfig
@@ -80,6 +80,7 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_COMPACTION=y
+CONFIG_KSM=y
CONFIG_CC_STACKPROTECTOR=y
CONFIG_ENABLE_VMALLOC_SAVING=y
CONFIG_CP_ACCESS=y
diff --git a/arch/arm/configs/msm8610_defconfig b/arch/arm/configs/msm8610_defconfig
index 02db2f2..e094a23 100644
--- a/arch/arm/configs/msm8610_defconfig
+++ b/arch/arm/configs/msm8610_defconfig
@@ -81,6 +81,7 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_COMPACTION=y
+CONFIG_KSM=y
CONFIG_CC_STACKPROTECTOR=y
CONFIG_ENABLE_VMALLOC_SAVING=y
CONFIG_CP_ACCESS=y
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index c95726f..d41b52b 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -578,17 +578,6 @@
| BVAL(10, 8, s##_mm_source_val), \
}
-#define F_HDMI(f, s, div, m, n) \
- { \
- .freq_hz = (f), \
- .src_clk = &s##_clk_src, \
- .m_val = (m), \
- .n_val = ~((n)-(m)) * !!(n), \
- .d_val = ~(n),\
- .div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
- | BVAL(10, 8, s##_mm_source_val), \
- }
-
#define F_MDSS(f, s, div, m, n) \
{ \
.freq_hz = (f), \
@@ -3255,60 +3244,19 @@
},
};
-static int hdmi_pll_clk_enable(struct clk *c)
-{
- return hdmi_pll_enable();
-}
-
-static void hdmi_pll_clk_disable(struct clk *c)
-{
- hdmi_pll_disable();
-}
-
-static int hdmi_pll_clk_set_rate(struct clk *c, unsigned long rate)
-{
- return hdmi_pll_set_rate(rate);
-}
-
-static struct clk_ops clk_ops_hdmi_pll = {
- .enable = hdmi_pll_clk_enable,
- .disable = hdmi_pll_clk_disable,
- .set_rate = hdmi_pll_clk_set_rate,
-};
-
-static struct clk hdmipll_clk_src = {
- .parent = &cxo_clk_src.c,
- .dbg_name = "hdmipll_clk_src",
- .ops = &clk_ops_hdmi_pll,
- CLK_INIT(hdmipll_clk_src),
-};
-
static struct clk_freq_tbl ftbl_mdss_extpclk_clk[] = {
- /*
- * The zero rate is required since suspend/resume wipes out the HDMI PHY
- * registers. This entry allows the HDMI driver to switch the cached
- * rate to zero before suspend and back to the real rate after resume.
- */
- F_HDMI( 0, hdmipll, 1, 0, 0),
- F_HDMI( 25200000, hdmipll, 1, 0, 0),
- F_HDMI( 27000000, hdmipll, 1, 0, 0),
- F_HDMI( 27030000, hdmipll, 1, 0, 0),
- F_HDMI( 65000000, hdmipll, 1, 0, 0),
- F_HDMI( 74250000, hdmipll, 1, 0, 0),
- F_HDMI(108000000, hdmipll, 1, 0, 0),
- F_HDMI(148500000, hdmipll, 1, 0, 0),
- F_HDMI(268500000, hdmipll, 1, 0, 0),
- F_HDMI(297000000, hdmipll, 1, 0, 0),
+ F_MM(148500000, hdmipll, 1, 0, 0),
F_END
};
static struct rcg_clk extpclk_clk_src = {
.cmd_rcgr_reg = EXTPCLK_CMD_RCGR,
.freq_tbl = ftbl_mdss_extpclk_clk,
- .current_freq = &rcg_dummy_freq,
+ .current_freq = ftbl_mdss_extpclk_clk,
.base = &virt_bases[MMSS_BASE],
.c = {
.dbg_name = "extpclk_clk_src",
+ .parent = &hdmipll_clk_src.c,
.ops = &clk_ops_rcg_hdmi,
VDD_DIG_FMAX_MAP2(LOW, 148500000, NOMINAL, 297000000),
CLK_INIT(extpclk_clk_src.c),
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index 4488869..62ecfa8 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -774,27 +774,35 @@
*/
static int rcg_clk_set_rate_hdmi(struct clk *c, unsigned long rate)
{
- struct clk_freq_tbl *nf;
struct rcg_clk *rcg = to_rcg_clk(c);
+ struct clk_freq_tbl *nf = rcg->freq_tbl;
int rc;
- for (nf = rcg->freq_tbl; nf->freq_hz != rate; nf++)
- if (nf->freq_hz == FREQ_END) {
- rc = -EINVAL;
- goto out;
- }
-
rc = clk_set_rate(nf->src_clk, rate);
if (rc < 0)
goto out;
set_rate_hid(rcg, nf);
rcg->current_freq = nf;
- c->parent = nf->src_clk;
out:
return rc;
}
+static struct clk *rcg_hdmi_clk_get_parent(struct clk *c)
+{
+ struct rcg_clk *rcg = to_rcg_clk(c);
+ struct clk_freq_tbl *freq = rcg->freq_tbl;
+ u32 cmd_rcgr_regval;
+
+ /* Is there a pending configuration? */
+ cmd_rcgr_regval = readl_relaxed(CMD_RCGR_REG(rcg));
+ if (cmd_rcgr_regval & CMD_RCGR_CONFIG_DIRTY_MASK)
+ return NULL;
+
+ rcg->current_freq->freq_hz = clk_get_rate(c->parent);
+
+ return freq->src_clk;
+}
#define ENABLE_REG(x) (*(x)->base + (x)->enable_reg)
#define SELECT_REG(x) (*(x)->base + (x)->select_reg)
@@ -987,7 +995,7 @@
.list_rate = rcg_clk_list_rate,
.round_rate = rcg_clk_round_rate,
.handoff = rcg_clk_handoff,
- .get_parent = rcg_clk_get_parent,
+ .get_parent = rcg_hdmi_clk_get_parent,
};
struct clk_ops clk_ops_branch = {
diff --git a/arch/arm/mach-msm/clock-mdss-8974.c b/arch/arm/mach-msm/clock-mdss-8974.c
index cf2df18..343a6c6 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.c
+++ b/arch/arm/mach-msm/clock-mdss-8974.c
@@ -167,23 +167,71 @@
(!(readl_relaxed(gdsc_base) & BIT(0)));
}
-void hdmi_pll_disable(void)
+/* Auto PLL calibaration */
+static int mdss_ahb_clk_enable(int enable)
{
- clk_enable(mdss_ahb_clk);
+ int rc = 0;
+
+ /* todo: Ideally, we should enable/disable GDSC whenever we are
+ * attempting to enable/disable MDSS AHB clock.
+ * For now, just return error if GDSC is not enabled.
+ */
+ if (!mdss_gdsc_enabled()) {
+ pr_err("%s: mdss GDSC is not enabled\n", __func__);
+ return -EPERM;
+ }
+
+ if (enable)
+ rc = clk_prepare_enable(mdss_ahb_clk);
+ else
+ clk_disable_unprepare(mdss_ahb_clk);
+
+ return rc;
+}
+
+static void hdmi_vco_disable(struct clk *c)
+{
+ u32 rc;
+
+ if (!mdss_gdsc_enabled()) {
+ pr_err("%s: mdss GDSC is not enabled\n", __func__);
+ return;
+ }
+
+ rc = clk_enable(mdss_ahb_clk);
+ if (rc) {
+ pr_err("%s: failed to enable mdss ahb clock. rc=%d\n",
+ __func__, rc);
+ return;
+ }
+
REG_W(0x0, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
udelay(5);
REG_W(0x0, hdmi_phy_base + HDMI_PHY_GLB_CFG);
+
clk_disable(mdss_ahb_clk);
hdmi_pll_on = 0;
-} /* hdmi_pll_disable */
+} /* hdmi_vco_disable */
-int hdmi_pll_enable(void)
+static int hdmi_vco_enable(struct clk *c)
{
u32 status;
+ u32 rc;
u32 max_reads, timeout_us;
- clk_enable(mdss_ahb_clk);
+ if (!mdss_gdsc_enabled()) {
+ pr_err("%s: mdss GDSC is not enabled\n", __func__);
+ return -EPERM;
+ }
+
+ rc = clk_enable(mdss_ahb_clk);
+ if (rc) {
+ pr_err("%s: failed to enable mdss ahb clock. rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
/* Global Enable */
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
/* Power up power gen */
@@ -208,7 +256,7 @@
status, ((status & BIT(0)) == 1), max_reads, timeout_us)) {
pr_err("%s: hdmi phy pll status=%x failed to Lock\n",
__func__, status);
- hdmi_pll_disable();
+ hdmi_vco_disable(c);
clk_disable(mdss_ahb_clk);
return -EINVAL;
}
@@ -222,7 +270,7 @@
status, ((status & BIT(0)) == 1), max_reads, timeout_us)) {
pr_err("%s: hdmi phy status=%x failed to Lock\n",
__func__, status);
- hdmi_pll_disable();
+ hdmi_vco_disable(c);
clk_disable(mdss_ahb_clk);
return -EINVAL;
}
@@ -232,25 +280,173 @@
hdmi_pll_on = 1;
return 0;
-} /* hdmi_pll_enable */
+} /* hdmi_vco_enable */
-int hdmi_pll_set_rate(unsigned long rate)
+static inline struct hdmi_pll_vco_clk *to_hdmi_vco_clk(struct clk *clk)
+{
+ return container_of(clk, struct hdmi_pll_vco_clk, c);
+}
+
+static void hdmi_phy_pll_calculator(u32 vco_freq)
+{
+ u32 ref_clk = 19200000;
+ u32 sdm_mode = 1;
+ u32 ref_clk_multiplier = sdm_mode == 1 ? 2 : 1;
+ u32 int_ref_clk_freq = ref_clk * ref_clk_multiplier;
+ u32 fbclk_pre_div = 1;
+ u32 ssc_mode = 0;
+ u32 kvco = 270;
+ u32 vdd = 95;
+ u32 ten_power_six = 1000000;
+ u32 ssc_ds_ppm = ssc_mode ? 5000 : 0;
+ u32 sdm_res = 16;
+ u32 ssc_tri_step = 32;
+ u32 ssc_freq = 2;
+ u64 ssc_ds = vco_freq * ssc_ds_ppm;
+ u32 div_in_freq = vco_freq / fbclk_pre_div;
+ u64 dc_offset = (div_in_freq / int_ref_clk_freq - 1) *
+ ten_power_six * 10;
+ u32 ssc_kdiv = (int_ref_clk_freq / ssc_freq) -
+ ten_power_six;
+ u64 sdm_freq_seed;
+ u32 ssc_tri_inc;
+ u64 fb_div_n;
+
+ u32 val;
+
+ pr_debug("%s: vco_freq = %u\n", __func__, vco_freq);
+
+ do_div(ssc_ds, (u64)ten_power_six);
+
+ fb_div_n = (u64)div_in_freq * (u64)ten_power_six * 10;
+ do_div(fb_div_n, int_ref_clk_freq);
+
+ sdm_freq_seed = ((fb_div_n - dc_offset - ten_power_six * 10) *
+ (1 << sdm_res) * 10) + 5;
+ do_div(sdm_freq_seed, ((u64)ten_power_six * 100));
+
+ ssc_tri_inc = (u32)ssc_ds;
+ ssc_tri_inc = (ssc_tri_inc / int_ref_clk_freq) * (1 << 16) /
+ ssc_tri_step;
+
+ val = (ref_clk_multiplier == 2 ? 1 : 0) +
+ ((fbclk_pre_div == 2 ? 1 : 0) * 16);
+ pr_debug("%s: HDMI_UNI_PLL_REFCLK_CFG = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_REFCLK_CFG);
+
+ REG_W(0x02, hdmi_phy_pll_base + HDMI_UNI_PLL_CHFPUMP_CFG);
+ REG_W(0x19, hdmi_phy_pll_base + HDMI_UNI_PLL_VCOLPF_CFG);
+ REG_W(0x04, hdmi_phy_pll_base + HDMI_UNI_PLL_VREG_CFG);
+ REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_PWRGEN_CFG);
+ REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
+ REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
+ REG_W(0x0E, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFR_CFG);
+ REG_W(0x20, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFC1_CFG);
+ REG_W(0x0D, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFC2_CFG);
+
+ do_div(dc_offset, (u64)ten_power_six * 10);
+ val = sdm_mode == 0 ? 64 + dc_offset : 0;
+ pr_debug("%s: HDMI_UNI_PLL_SDM_CFG0 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG0);
+
+ val = 64 + dc_offset;
+ pr_debug("%s: HDMI_UNI_PLL_SDM_CFG1 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG1);
+
+ val = sdm_freq_seed & 0xFF;
+ pr_debug("%s: HDMI_UNI_PLL_SDM_CFG2 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG2);
+
+ val = (sdm_freq_seed >> 8) & 0xFF;
+ pr_debug("%s: HDMI_UNI_PLL_SDM_CFG3 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG3);
+
+ val = (sdm_freq_seed >> 16) & 0xFF;
+ pr_debug("%s: HDMI_UNI_PLL_SDM_CFG4 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG4);
+
+ val = (ssc_mode == 0 ? 128 : 0) + (ssc_kdiv / ten_power_six);
+ pr_debug("%s: HDMI_UNI_PLL_SSC_CFG0 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_SSC_CFG0);
+
+ val = ssc_tri_inc & 0xFF;
+ pr_debug("%s: HDMI_UNI_PLL_SSC_CFG1 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_SSC_CFG1);
+
+ val = (ssc_tri_inc >> 8) & 0xFF;
+ pr_debug("%s: HDMI_UNI_PLL_SSC_CFG2 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_SSC_CFG2);
+
+ pr_debug("%s: HDMI_UNI_PLL_SSC_CFG3 = 0x%x\n", __func__, ssc_tri_step);
+ REG_W(ssc_tri_step, hdmi_phy_pll_base + HDMI_UNI_PLL_SSC_CFG3);
+
+ REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
+ REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
+ REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
+ REG_W(0x0A, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG0);
+ REG_W(0x04, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG1);
+ REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
+ REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG3);
+ REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG4);
+ REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG5);
+
+ val = (kvco * vdd * 10000) / 6;
+ val += 500000;
+ val /= ten_power_six;
+ pr_debug("%s: HDMI_UNI_PLL_CAL_CFG6 = 0x%x\n", __func__, val);
+ REG_W(val & 0xFF, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG6);
+
+ val = (kvco * vdd * 10000) / 6;
+ val -= ten_power_six;
+ val /= ten_power_six;
+ val = (val >> 8) & 0xFF;
+ pr_debug("%s: HDMI_UNI_PLL_CAL_CFG7 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG7);
+
+ val = (ref_clk * 5) / ten_power_six;
+ pr_debug("%s: HDMI_UNI_PLL_CAL_CFG8 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG8);
+
+ val = ((ref_clk * 5) / ten_power_six) >> 8;
+ pr_debug("%s: HDMI_UNI_PLL_CAL_CFG9 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG9);
+
+ vco_freq /= ten_power_six;
+ val = vco_freq & 0xFF;
+ pr_debug("%s: HDMI_UNI_PLL_CAL_CFG10 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG10);
+
+ val = vco_freq >> 8;
+ pr_debug("%s: HDMI_UNI_PLL_CAL_CFG11 = 0x%x\n", __func__, val);
+ REG_W(val, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG11);
+} /* hdmi_phy_pll_calculator */
+
+static int hdmi_vco_set_rate(struct clk *c, unsigned long rate)
{
unsigned int set_power_dwn = 0;
+ int rc = 0;
+
+ struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c);
if (hdmi_pll_on) {
- hdmi_pll_disable();
+ hdmi_vco_disable(c);
set_power_dwn = 1;
}
- clk_enable(mdss_ahb_clk);
+ rc = mdss_ahb_clk_enable(1);
+ if (rc) {
+ pr_err("%s: failed to enable mdss ahb clock. rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
pr_debug("%s: rate=%ld\n", __func__, rate);
+
switch (rate) {
case 0:
- /* This case is needed for suspend/resume. */
- break;
+ break;
- case 25200000:
+ case 756000000:
/* 640x480p60 */
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
@@ -267,7 +463,6 @@
REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x03, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
@@ -295,7 +490,7 @@
udelay(200);
break;
- case 27000000:
+ case 810000000:
/* 576p50/576i50 case */
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
@@ -312,7 +507,6 @@
REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
REG_W(0X1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x03, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
@@ -340,7 +534,7 @@
udelay(200);
break;
- case 27030000:
+ case 810900000:
/* 480p60/480i60 case */
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
@@ -357,7 +551,6 @@
REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x03, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
@@ -384,7 +577,7 @@
REG_W(0x05, hdmi_phy_base + HDMI_PHY_TXCAL_CFG3);
udelay(200);
break;
- case 65000000:
+ case 650000000:
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_REFCLK_CFG);
@@ -400,7 +593,6 @@
REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
@@ -427,7 +619,7 @@
REG_W(0x05, hdmi_phy_base + HDMI_PHY_TXCAL_CFG3);
udelay(200);
break;
- case 74250000:
+ case 742500000:
/*
* 720p60/720p50/1080i60/1080i50
* 1080p24/1080p30/1080p25 case
@@ -447,7 +639,6 @@
REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
@@ -475,7 +666,7 @@
udelay(200);
break;
- case 108000000:
+ case 1080000000:
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_REFCLK_CFG);
@@ -491,7 +682,6 @@
REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
@@ -519,51 +709,7 @@
udelay(200);
break;
- case 148500000:
- REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
- REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
- REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_REFCLK_CFG);
- REG_W(0x19, hdmi_phy_pll_base + HDMI_UNI_PLL_VCOLPF_CFG);
- REG_W(0x0E, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFR_CFG);
- REG_W(0x20, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFC1_CFG);
- REG_W(0x0D, hdmi_phy_pll_base + HDMI_UNI_PLL_LPFC2_CFG);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG0);
- REG_W(0x52, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG1);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG2);
- REG_W(0x56, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG3);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_SDM_CFG4);
- REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
- REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
- REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
- REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
- REG_W(0x60, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG8);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG9);
- REG_W(0xE6, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG10);
- REG_W(0x02, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG11);
- REG_W(0x1F, hdmi_phy_base + HDMI_PHY_PD_CTRL0);
- udelay(50);
-
- REG_W(0x0F, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
- REG_W(0x00, hdmi_phy_base + HDMI_PHY_PD_CTRL1);
- REG_W(0x10, hdmi_phy_base + HDMI_PHY_ANA_CFG2);
- REG_W(0xDB, hdmi_phy_base + HDMI_PHY_ANA_CFG0);
- REG_W(0x43, hdmi_phy_base + HDMI_PHY_ANA_CFG1);
- REG_W(0x02, hdmi_phy_base + HDMI_PHY_ANA_CFG2);
- REG_W(0x00, hdmi_phy_base + HDMI_PHY_ANA_CFG3);
- REG_W(0x04, hdmi_phy_pll_base + HDMI_UNI_PLL_VREG_CFG);
- REG_W(0xD0, hdmi_phy_base + HDMI_PHY_DCC_CFG0);
- REG_W(0x1A, hdmi_phy_base + HDMI_PHY_DCC_CFG1);
- REG_W(0x00, hdmi_phy_base + HDMI_PHY_TXCAL_CFG0);
- REG_W(0x00, hdmi_phy_base + HDMI_PHY_TXCAL_CFG1);
- REG_W(0x02, hdmi_phy_base + HDMI_PHY_TXCAL_CFG2);
- REG_W(0x05, hdmi_phy_base + HDMI_PHY_TXCAL_CFG3);
- udelay(200);
- break;
-
- case 268500000:
+ case 1342500000:
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_REFCLK_CFG);
@@ -579,7 +725,6 @@
REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
@@ -607,7 +752,7 @@
udelay(200);
break;
- case 297000000:
+ case 1485000000:
REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_REFCLK_CFG);
@@ -623,7 +768,6 @@
REG_W(0x10, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG0);
REG_W(0x1A, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG1);
REG_W(0x05, hdmi_phy_pll_base + HDMI_UNI_PLL_LKDET_CFG2);
- REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV1_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV2_CFG);
REG_W(0x00, hdmi_phy_pll_base + HDMI_UNI_PLL_POSTDIV3_CFG);
REG_W(0x01, hdmi_phy_pll_base + HDMI_UNI_PLL_CAL_CFG2);
@@ -652,40 +796,68 @@
break;
default:
- pr_err("%s: not supported rate=%ld\n", __func__, rate);
+ pr_debug("%s: Use pll settings calculator for rate=%ld\n",
+ __func__, rate);
+
+ REG_W(0x81, hdmi_phy_base + HDMI_PHY_GLB_CFG);
+ hdmi_phy_pll_calculator(rate);
+ REG_W(0x1F, hdmi_phy_base + HDMI_PHY_PD_CTRL0);
+ udelay(50);
+
+ REG_W(0x0F, hdmi_phy_pll_base + HDMI_UNI_PLL_GLB_CFG);
+ REG_W(0x00, hdmi_phy_base + HDMI_PHY_PD_CTRL1);
+ REG_W(0x10, hdmi_phy_base + HDMI_PHY_ANA_CFG2);
+ REG_W(0xDB, hdmi_phy_base + HDMI_PHY_ANA_CFG0);
+ REG_W(0x43, hdmi_phy_base + HDMI_PHY_ANA_CFG1);
+
+ if (rate < 825000000) {
+ REG_W(0x01, hdmi_phy_base + HDMI_PHY_ANA_CFG2);
+ REG_W(0x00, hdmi_phy_base + HDMI_PHY_ANA_CFG3);
+ } else if (rate >= 825000000 && rate < 1342500000) {
+ REG_W(0x05, hdmi_phy_base + HDMI_PHY_ANA_CFG2);
+ REG_W(0x03, hdmi_phy_base + HDMI_PHY_ANA_CFG3);
+ } else {
+ REG_W(0x06, hdmi_phy_base + HDMI_PHY_ANA_CFG2);
+ REG_W(0x03, hdmi_phy_base + HDMI_PHY_ANA_CFG3);
+ }
+
+ REG_W(0x04, hdmi_phy_pll_base + HDMI_UNI_PLL_VREG_CFG);
+ REG_W(0xD0, hdmi_phy_base + HDMI_PHY_DCC_CFG0);
+ REG_W(0x1A, hdmi_phy_base + HDMI_PHY_DCC_CFG1);
+ REG_W(0x00, hdmi_phy_base + HDMI_PHY_TXCAL_CFG0);
+ REG_W(0x00, hdmi_phy_base + HDMI_PHY_TXCAL_CFG1);
+
+ if (rate < 825000000)
+ REG_W(0x01, hdmi_phy_base + HDMI_PHY_TXCAL_CFG2);
+ else
+ REG_W(0x00, hdmi_phy_base + HDMI_PHY_TXCAL_CFG2);
+
+ REG_W(0x05, hdmi_phy_base + HDMI_PHY_TXCAL_CFG3);
+ REG_W(0x62, hdmi_phy_base + HDMI_PHY_BIST_PATN0);
+ REG_W(0x03, hdmi_phy_base + HDMI_PHY_BIST_PATN1);
+ REG_W(0x69, hdmi_phy_base + HDMI_PHY_BIST_PATN2);
+ REG_W(0x02, hdmi_phy_base + HDMI_PHY_BIST_PATN3);
+
+ udelay(200);
+
+ REG_W(0x00, hdmi_phy_base + HDMI_PHY_BIST_CFG1);
+ REG_W(0x00, hdmi_phy_base + HDMI_PHY_BIST_CFG0);
}
/* Make sure writes complete before disabling iface clock */
mb();
- clk_disable(mdss_ahb_clk);
+ mdss_ahb_clk_enable(0);
if (set_power_dwn)
- hdmi_pll_enable();
+ hdmi_vco_enable(c);
+
+ vco->rate = rate;
+ vco->rate_set = true;
return 0;
} /* hdmi_pll_set_rate */
-/* Auto PLL calibaration */
-int mdss_ahb_clk_enable(int enable)
-{
- int rc = 0;
-
- /* todo: Ideally, we should enable/disable GDSC whenever we are
- * attempting to enable/disable MDSS AHB clock.
- * For now, just return error if GDSC is not enabled.
- */
- if (!mdss_gdsc_enabled())
- return -EPERM;
-
- if (enable)
- rc = clk_prepare_enable(mdss_ahb_clk);
- else
- clk_disable_unprepare(mdss_ahb_clk);
-
- return rc;
-}
-
int set_byte_mux_sel(struct mux_clk *clk, int sel)
{
pr_debug("%s: byte mux set to %s mode\n", __func__,
@@ -1649,6 +1821,271 @@
},
};
+/* HDMI PLL DIV CLK */
+
+static unsigned long hdmi_vco_get_rate(struct clk *c)
+{
+ unsigned long freq = 0;
+
+ if (mdss_ahb_clk_enable(1)) {
+ pr_err("%s: Failed to enable mdss ahb clock\n", __func__);
+ return freq;
+ }
+
+ freq = DSS_REG_R(hdmi_phy_pll_base, HDMI_UNI_PLL_CAL_CFG11) << 8 |
+ DSS_REG_R(hdmi_phy_pll_base, HDMI_UNI_PLL_CAL_CFG10);
+
+ switch (freq) {
+ case 742:
+ freq = 742500000;
+ break;
+ case 810:
+ if (DSS_REG_R(hdmi_phy_pll_base, HDMI_UNI_PLL_SDM_CFG3) == 0x18)
+ freq = 810000000;
+ else
+ freq = 810900000;
+ break;
+ case 1342:
+ freq = 1342500000;
+ break;
+ default:
+ freq *= 1000000;
+ }
+
+ mdss_ahb_clk_enable(0);
+
+ return freq;
+}
+
+static long hdmi_vco_round_rate(struct clk *c, unsigned long rate)
+{
+ unsigned long rrate = rate;
+ struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c);
+
+ if (rate < vco->min_rate)
+ rrate = vco->min_rate;
+ if (rate > vco->max_rate)
+ rrate = vco->max_rate;
+
+ pr_debug("%s: rrate=%ld\n", __func__, rrate);
+
+ return rrate;
+}
+
+static int hdmi_vco_prepare(struct clk *c)
+{
+ struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c);
+ int ret = 0;
+
+ pr_debug("%s: rate=%ld\n", __func__, vco->rate);
+
+ if (!vco->rate_set && vco->rate)
+ ret = hdmi_vco_set_rate(c, vco->rate);
+
+ if (!ret)
+ ret = clk_prepare(mdss_ahb_clk);
+
+ return ret;
+}
+
+static void hdmi_vco_unprepare(struct clk *c)
+{
+ struct hdmi_pll_vco_clk *vco = to_hdmi_vco_clk(c);
+
+ vco->rate_set = false;
+
+ clk_unprepare(mdss_ahb_clk);
+}
+
+static int hdmi_pll_lock_status(void)
+{
+ u32 status;
+ int pll_locked = 0;
+ int rc;
+
+ rc = mdss_ahb_clk_enable(1);
+ if (rc) {
+ pr_err("%s: failed to enable mdss ahb clock. rc=%d\n",
+ __func__, rc);
+ return 0;
+ }
+ /* poll for PLL ready status */
+ if (readl_poll_timeout_noirq((hdmi_phy_base + HDMI_PHY_STATUS),
+ status, ((status & BIT(0)) == 1),
+ PLL_POLL_MAX_READS, PLL_POLL_TIMEOUT_US)) {
+ pr_debug("%s: HDMI PLL status=%x failed to Lock\n",
+ __func__, status);
+ pll_locked = 0;
+ } else {
+ pll_locked = 1;
+ }
+ mdss_ahb_clk_enable(0);
+
+ return pll_locked;
+}
+
+static enum handoff hdmi_vco_handoff(struct clk *c)
+{
+ enum handoff ret = HANDOFF_DISABLED_CLK;
+
+ if (hdmi_pll_lock_status()) {
+ c->rate = hdmi_vco_get_rate(c);
+ ret = HANDOFF_ENABLED_CLK;
+ }
+
+ pr_debug("%s: done, ret=%d\n", __func__, ret);
+ return ret;
+}
+
+static struct clk_ops hdmi_vco_clk_ops = {
+ .enable = hdmi_vco_enable,
+ .set_rate = hdmi_vco_set_rate,
+ .get_rate = hdmi_vco_get_rate,
+ .round_rate = hdmi_vco_round_rate,
+ .prepare = hdmi_vco_prepare,
+ .unprepare = hdmi_vco_unprepare,
+ .disable = hdmi_vco_disable,
+ .handoff = hdmi_vco_handoff,
+};
+
+static struct hdmi_pll_vco_clk hdmi_vco_clk = {
+ .min_rate = 600000000,
+ .max_rate = 1800000000,
+ .c = {
+ .dbg_name = "hdmi_vco_clk",
+ .ops = &hdmi_vco_clk_ops,
+ CLK_INIT(hdmi_vco_clk.c),
+ },
+};
+
+static struct div_clk hdmipll_div1_clk = {
+ .div = 1,
+ .c = {
+ .parent = &hdmi_vco_clk.c,
+ .dbg_name = "hdmipll_div1_clk",
+ .ops = &clk_ops_div,
+ .flags = CLKFLAG_NO_RATE_CACHE,
+ CLK_INIT(hdmipll_div1_clk.c),
+ },
+};
+
+static struct div_clk hdmipll_div2_clk = {
+ .div = 2,
+ .c = {
+ .parent = &hdmi_vco_clk.c,
+ .dbg_name = "hdmipll_div2_clk",
+ .ops = &clk_ops_div,
+ .flags = CLKFLAG_NO_RATE_CACHE,
+ CLK_INIT(hdmipll_div2_clk.c),
+ },
+};
+
+static struct div_clk hdmipll_div4_clk = {
+ .div = 4,
+ .c = {
+ .parent = &hdmi_vco_clk.c,
+ .dbg_name = "hdmipll_div4_clk",
+ .ops = &clk_ops_div,
+ .flags = CLKFLAG_NO_RATE_CACHE,
+ CLK_INIT(hdmipll_div4_clk.c),
+ },
+};
+
+static struct div_clk hdmipll_div6_clk = {
+ .div = 6,
+ .c = {
+ .parent = &hdmi_vco_clk.c,
+ .dbg_name = "hdmipll_div6_clk",
+ .ops = &clk_ops_div,
+ .flags = CLKFLAG_NO_RATE_CACHE,
+ CLK_INIT(hdmipll_div6_clk.c),
+ },
+};
+
+static int hdmipll_set_mux_sel(struct mux_clk *clk, int mux_sel)
+{
+ int rc;
+
+ if (!mdss_gdsc_enabled()) {
+ pr_err("%s: mdss GDSC is not enabled\n", __func__);
+ return -EPERM;
+ }
+
+ rc = clk_enable(mdss_ahb_clk);
+ if (rc) {
+ pr_err("%s: Failed to enable mdss ahb clock\n", __func__);
+ return rc;
+ }
+
+ pr_debug("%s: mux_sel=%d\n", __func__, mux_sel);
+ DSS_REG_W(hdmi_phy_pll_base, HDMI_UNI_PLL_POSTDIV1_CFG, mux_sel);
+
+ clk_disable(mdss_ahb_clk);
+
+ return 0;
+}
+
+static int hdmipll_get_mux_sel(struct mux_clk *clk)
+{
+ int mux_sel = 0;
+
+ if (mdss_ahb_clk_enable(1)) {
+ pr_err("%s: Failed to enable mdss ahb clock\n", __func__);
+ return mux_sel;
+ }
+
+ mux_sel = DSS_REG_R(hdmi_phy_pll_base, HDMI_UNI_PLL_POSTDIV1_CFG);
+ mux_sel &= 0x03;
+ pr_debug("%s: mux_sel=%d\n", __func__, mux_sel);
+
+ mdss_ahb_clk_enable(0);
+
+ return mux_sel;
+}
+
+static struct clk_mux_ops hdmipll_mux_ops = {
+ .set_mux_sel = hdmipll_set_mux_sel,
+ .get_mux_sel = hdmipll_get_mux_sel,
+};
+
+static struct clk_ops hdmi_mux_ops;
+
+static int hdmi_mux_prepare(struct clk *c)
+{
+ int ret = 0;
+
+ if (c && c->ops && c->ops->set_rate)
+ ret = c->ops->set_rate(c, c->rate);
+
+ return ret;
+}
+
+static struct mux_clk hdmipll_mux_clk = {
+ MUX_SRC_LIST(
+ { &hdmipll_div1_clk.c, 0 },
+ { &hdmipll_div2_clk.c, 1 },
+ { &hdmipll_div4_clk.c, 2 },
+ { &hdmipll_div6_clk.c, 3 },
+ ),
+ .ops = &hdmipll_mux_ops,
+ .c = {
+ .parent = &hdmipll_div1_clk.c,
+ .dbg_name = "hdmipll_mux_clk",
+ .ops = &hdmi_mux_ops,
+ CLK_INIT(hdmipll_mux_clk.c),
+ },
+};
+
+struct div_clk hdmipll_clk_src = {
+ .div = 5,
+ .c = {
+ .parent = &hdmipll_mux_clk.c,
+ .dbg_name = "hdmipll_clk_src",
+ .ops = &clk_ops_div,
+ CLK_INIT(hdmipll_clk_src.c),
+ },
+};
+
void __init mdss_clk_ctrl_pre_init(struct clk *ahb_clk)
{
BUG_ON(ahb_clk == NULL);
@@ -1682,5 +2119,8 @@
byte_mux_clk_ops = clk_ops_gen_mux;
byte_mux_clk_ops.prepare = mux_prepare;
+
+ hdmi_mux_ops = clk_ops_gen_mux;
+ hdmi_mux_ops.prepare = hdmi_mux_prepare;
}
diff --git a/arch/arm/mach-msm/clock-mdss-8974.h b/arch/arm/mach-msm/clock-mdss-8974.h
index 9fd3026..b1d5b45 100644
--- a/arch/arm/mach-msm/clock-mdss-8974.h
+++ b/arch/arm/mach-msm/clock-mdss-8974.h
@@ -22,9 +22,15 @@
void mdss_clk_ctrl_pre_init(struct clk *ahb_clk);
void mdss_clk_ctrl_post_init(void);
-int hdmi_pll_enable(void);
-void hdmi_pll_disable(void);
-int hdmi_pll_set_rate(unsigned long rate);
+
+struct hdmi_pll_vco_clk {
+ unsigned long rate; /* current vco rate */
+ unsigned long min_rate; /* min vco rate */
+ unsigned long max_rate; /* max vco rate */
+ bool rate_set;
+
+ struct clk c;
+};
struct lpfr_cfg {
unsigned long vco_rate;
@@ -57,4 +63,6 @@
extern struct mux_clk byte_mux_8226;
extern struct div_clk byte_clk_src_8226;
+extern struct div_clk hdmipll_clk_src;
+
#endif
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
index 20e3c3b..174a50a 100644
--- a/arch/arm/mach-msm/hotplug.c
+++ b/arch/arm/mach-msm/hotplug.c
@@ -11,6 +11,7 @@
#include <linux/errno.h>
#include <linux/smp.h>
#include <linux/cpu.h>
+#include <linux/ratelimit.h>
#include <asm/cacheflush.h>
#include <asm/smp_plat.h>
@@ -150,6 +151,29 @@
.notifier_call = hotplug_rtb_callback,
};
+static int hotplug_cpu_check_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ int cpu = (int)hcpu;
+
+ switch (action & (~CPU_TASKS_FROZEN)) {
+ case CPU_DOWN_PREPARE:
+ if (cpu == 0) {
+ pr_err_ratelimited("CPU0 hotplug is not supported\n");
+ return NOTIFY_BAD;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+static struct notifier_block hotplug_cpu_check_notifier = {
+ .notifier_call = hotplug_cpu_check_callback,
+ .priority = INT_MAX,
+};
+
int msm_platform_secondary_init(unsigned int cpu)
{
int ret;
@@ -170,6 +194,12 @@
static int __init init_hotplug(void)
{
- return register_hotcpu_notifier(&hotplug_rtb_notifier);
+ int rc;
+
+ rc = register_hotcpu_notifier(&hotplug_rtb_notifier);
+ if (rc)
+ return rc;
+
+ return register_hotcpu_notifier(&hotplug_cpu_check_notifier);
}
early_initcall(init_hotplug);
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
index 5fa7b1b..5bdd10a 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_utils_aio.c
@@ -1199,6 +1199,7 @@
case AUDIO_GET_STATS: {
struct msm_audio_stats stats;
uint64_t timestamp;
+ memset(&stats, 0, sizeof(struct msm_audio_stats));
stats.byte_count = atomic_read(&audio->in_bytes);
stats.sample_count = atomic_read(&audio->in_samples);
rc = q6asm_get_session_time(audio->ac, ×tamp);
diff --git a/arch/arm/mach-msm/qdsp6v2/q6audio_v2_aio.c b/arch/arm/mach-msm/qdsp6v2/q6audio_v2_aio.c
index 4681437..21040b1 100644
--- a/arch/arm/mach-msm/qdsp6v2/q6audio_v2_aio.c
+++ b/arch/arm/mach-msm/qdsp6v2/q6audio_v2_aio.c
@@ -108,9 +108,7 @@
break;
case RESET_EVENTS:
pr_debug("%s: Received opcode:0x%x\n", __func__, opcode);
- audio->event_abort = 1;
audio->stopped = 1;
- audio->enabled = 0;
wake_up(&audio->event_wait);
break;
default:
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 921b80c..b64ada1 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -201,7 +201,7 @@
me->smmu.domain_id, 0);
buf->phys = 0;
}
- if (buf->virt) {
+ if (!IS_ERR_OR_NULL(buf->virt)) {
ion_unmap_kernel(me->iclient, buf->handle);
buf->virt = 0;
}
@@ -214,7 +214,7 @@
{
struct fastrpc_apps *me = &gfa;
if (!IS_ERR_OR_NULL(map->handle)) {
- if (map->virt) {
+ if (!IS_ERR_OR_NULL(map->virt)) {
ion_unmap_kernel(me->iclient, map->handle);
map->virt = 0;
}
@@ -233,13 +233,15 @@
unsigned long len;
buf->handle = 0;
buf->virt = 0;
+ buf->phys = 0;
heap = me->smmu.enabled ? ION_HEAP(ION_IOMMU_HEAP_ID) :
ION_HEAP(ION_ADSP_HEAP_ID) | ION_HEAP(ION_AUDIO_HEAP_ID);
buf->handle = ion_alloc(clnt, buf->size, SZ_4K, heap, ION_FLAG_CACHED);
VERIFY(err, 0 == IS_ERR_OR_NULL(buf->handle));
if (err)
goto bail;
- VERIFY(err, 0 != (buf->virt = ion_map_kernel(clnt, buf->handle)));
+ buf->virt = ion_map_kernel(clnt, buf->handle);
+ VERIFY(err, 0 == IS_ERR_OR_NULL(buf->virt));
if (err)
goto bail;
if (me->smmu.enabled) {
@@ -358,6 +360,9 @@
list[i].num = 0;
list[i].pgidx = 0;
len = pra[i].buf.len;
+ VERIFY(err, len >= 0);
+ if (err)
+ goto bail;
if (!len)
continue;
buf = pra[i].buf.pv;
@@ -843,7 +848,7 @@
context_free(ctx);
if (me->smmu.enabled) {
- bufs = REMOTE_SCALARS_LENGTH(sc);
+ bufs = REMOTE_SCALARS_INBUFS(sc) + REMOTE_SCALARS_OUTBUFS(sc);
if (fds) {
handles = (struct ion_handle **)(fds + bufs);
for (i = 0; i < bufs; i++)
@@ -1019,7 +1024,8 @@
VERIFY(err, 0 == IS_ERR_OR_NULL(map->handle));
if (err)
goto bail;
- VERIFY(err, 0 != (map->virt = ion_map_kernel(clnt, map->handle)));
+ map->virt = ion_map_kernel(clnt, map->handle);
+ VERIFY(err, 0 == IS_ERR_OR_NULL(map->virt));
if (err)
goto bail;
buf = (void *)mmap->vaddrin;
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 91b90a8..4b6ca12 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -883,7 +883,7 @@
void *buf = driver->buf_event_mask_update;
int header_size = sizeof(struct diag_ctrl_event_mask);
int wr_size = -ENOMEM, retry_count = 0, timer;
- int ret = DIAG_DCI_NO_ERROR;
+ int ret = DIAG_DCI_NO_ERROR, i;
mutex_lock(&driver->diag_cntl_mutex);
/* send event mask update */
@@ -891,8 +891,14 @@
driver->event_mask->data_len = 7 + DCI_EVENT_MASK_SIZE;
driver->event_mask->stream_id = DCI_MASK_STREAM;
driver->event_mask->status = 3; /* status for valid mask */
- driver->event_mask->event_config = 1; /* event config */
+ driver->event_mask->event_config = 0; /* event config */
driver->event_mask->event_mask_size = DCI_EVENT_MASK_SIZE;
+ for (i = 0; i < DCI_EVENT_MASK_SIZE; i++) {
+ if (dci_cumulative_event_mask[i] != 0) {
+ driver->event_mask->event_config = 1;
+ break;
+ }
+ }
memcpy(buf, driver->event_mask, header_size);
memcpy(buf+header_size, dci_cumulative_event_mask, DCI_EVENT_MASK_SIZE);
if (ch) {
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 5be77c4..12dadb0 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -348,6 +348,7 @@
int separate_cmdrsp[NUM_SMD_CONTROL_CHANNELS];
unsigned char *usb_buf_out;
unsigned char *apps_rsp_buf;
+ unsigned char *user_space_data_buf;
/* buffer for updating mask to peripherals */
unsigned char *buf_msg_mask_update;
unsigned char *buf_log_mask_update;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index f7c0d24..ae92d170c 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1609,22 +1609,15 @@
goto fail_free_hdlc;
}
if (pkt_type == USER_SPACE_DATA_TYPE) {
- user_space_data = diagmem_alloc(driver, payload_size,
- POOL_TYPE_USER);
- if (!user_space_data) {
- driver->dropped_count++;
- return -ENOMEM;
- }
- err = copy_from_user(user_space_data, buf + 4,
+ err = copy_from_user(driver->user_space_data_buf, buf + 4,
payload_size);
if (err) {
pr_err("diag: copy failed for user space data\n");
- diagmem_free(driver, user_space_data, POOL_TYPE_USER);
- user_space_data = NULL;
return -EIO;
}
/* Check for proc_type */
- remote_proc = diag_get_remote(*(int *)user_space_data);
+ remote_proc =
+ diag_get_remote(*(int *)driver->user_space_data_buf);
if (remote_proc) {
token_offset = 4;
@@ -1634,12 +1627,9 @@
/* Check masks for On-Device logging */
if (driver->mask_check) {
- if (!mask_request_validate(user_space_data +
+ if (!mask_request_validate(driver->user_space_data_buf +
token_offset)) {
pr_alert("diag: mask request Invalid\n");
- diagmem_free(driver, user_space_data,
- POOL_TYPE_USER);
- user_space_data = NULL;
return -EFAULT;
}
}
@@ -1647,7 +1637,7 @@
#ifdef DIAG_DEBUG
pr_debug("diag: user space data %d\n", payload_size);
for (i = 0; i < payload_size; i++)
- pr_debug("\t %x", *((user_space_data
+ pr_debug("\t %x", *((driver->user_space_data_buf
+ token_offset)+i));
#endif
#ifdef CONFIG_DIAG_SDIO_PIPE
@@ -1658,7 +1648,7 @@
payload_size));
if (driver->sdio_ch && (payload_size > 0)) {
sdio_write(driver->sdio_ch, (void *)
- (user_space_data + token_offset),
+ (driver->user_space_data_buf + token_offset),
payload_size);
}
}
@@ -1689,8 +1679,8 @@
diag_hsic[index].in_busy_hsic_read_on_device =
0;
err = diag_bridge_write(index,
- user_space_data + token_offset,
- payload_size);
+ driver->user_space_data_buf +
+ token_offset, payload_size);
if (err) {
pr_err("diag: err sending mask to MDM: %d\n",
err);
@@ -1711,14 +1701,12 @@
&& driver->lcid) {
if (payload_size > 0) {
err = msm_smux_write(driver->lcid, NULL,
- user_space_data + token_offset,
+ driver->user_space_data_buf +
+ token_offset,
payload_size);
if (err) {
pr_err("diag:send mask to MDM err %d",
err);
- diagmem_free(driver, user_space_data,
- POOL_TYPE_USER);
- user_space_data = NULL;
return err;
}
}
@@ -1727,9 +1715,8 @@
/* send masks to 8k now */
if (!remote_proc)
diag_process_hdlc((void *)
- (user_space_data + token_offset), payload_size);
- diagmem_free(driver, user_space_data, POOL_TYPE_USER);
- user_space_data = NULL;
+ (driver->user_space_data_buf + token_offset),
+ payload_size);
return 0;
}
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 447cb39..395bea0 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -2520,6 +2520,12 @@
&& (driver->hdlc_buf = kzalloc(HDLC_MAX, GFP_KERNEL)) == NULL)
goto err;
kmemleak_not_leak(driver->hdlc_buf);
+ if (driver->user_space_data_buf == NULL)
+ driver->user_space_data_buf = kzalloc(USER_SPACE_DATA,
+ GFP_KERNEL);
+ if (driver->user_space_data_buf == NULL)
+ goto err;
+ kmemleak_not_leak(driver->user_space_data_buf);
if (driver->client_map == NULL &&
(driver->client_map = kzalloc
((driver->num_clients) * sizeof(struct diag_client_map),
@@ -2607,6 +2613,7 @@
kfree(driver->pkt_buf);
kfree(driver->usb_read_ptr);
kfree(driver->apps_rsp_buf);
+ kfree(driver->user_space_data_buf);
if (driver->diag_wq)
destroy_workqueue(driver->diag_wq);
}
@@ -2646,5 +2653,6 @@
kfree(driver->pkt_buf);
kfree(driver->usb_read_ptr);
kfree(driver->apps_rsp_buf);
+ kfree(driver->user_space_data_buf);
destroy_workqueue(driver->diag_wq);
}
diff --git a/drivers/char/hw_random/msm_rng.c b/drivers/char/hw_random/msm_rng.c
index 369477f..4118a7a 100644
--- a/drivers/char/hw_random/msm_rng.c
+++ b/drivers/char/hw_random/msm_rng.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2013, 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,9 @@
#include <mach/msm_iomap.h>
#include <mach/socinfo.h>
#include <mach/msm_bus.h>
+#include <linux/qrng.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
#define DRIVER_NAME "msm_rng"
@@ -51,6 +54,29 @@
uint32_t qrng_perf_client;
};
+struct msm_rng_device msm_rng_device_info;
+
+static long msm_rng_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ long ret = 0;
+
+ pr_debug("ioctl: cmd = %d\n", cmd);
+ switch (cmd) {
+ case QRNG_IOCTL_RESET_BUS_BANDWIDTH:
+ pr_info("calling msm_rng_bus_scale(LOW)\n");
+ ret = msm_bus_scale_client_update_request(
+ msm_rng_device_info.qrng_perf_client, 0);
+ if (ret)
+ pr_err("failed qrng_reset_bus_bw, ret = %ld\n", ret);
+ break;
+ default:
+ pr_err("Unsupported IOCTL call");
+ break;
+ }
+ return ret;
+}
+
static int msm_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
struct msm_rng_device *msm_rng_dev;
@@ -79,12 +105,6 @@
dev_err(&pdev->dev, "failed to enable clock in callback\n");
return 0;
}
- if (msm_rng_dev->qrng_perf_client) {
- ret = msm_bus_scale_client_update_request(
- msm_rng_dev->qrng_perf_client, 1);
- if (ret)
- pr_err("bus_scale_client_update_req failed!\n");
- }
/* read random data from h/w */
do {
/* check status bit if data is available */
@@ -104,9 +124,6 @@
if ((maxsize - currsize) < 4)
break;
} while (currsize < maxsize);
- if (msm_rng_dev->qrng_perf_client)
- ret = msm_bus_scale_client_update_request(
- msm_rng_dev->qrng_perf_client, 0);
/* vote to turn off clock */
clk_disable_unprepare(msm_rng_dev->prng_clk);
@@ -161,19 +178,24 @@
mb();
}
clk_disable_unprepare(msm_rng_dev->prng_clk);
- if (msm_rng_dev->qrng_perf_client)
- ret = msm_bus_scale_client_update_request(
- msm_rng_dev->qrng_perf_client, 0);
-
return 0;
}
+static const struct file_operations msm_rng_fops = {
+ .unlocked_ioctl = msm_rng_ioctl,
+};
+static struct class *msm_rng_class;
+static struct cdev msm_rng_cdev;
+
static int __devinit msm_rng_probe(struct platform_device *pdev)
{
struct resource *res;
struct msm_rng_device *msm_rng_dev = NULL;
void __iomem *base = NULL;
int error = 0;
+ int ret = 0;
+ struct device *dev;
+
struct msm_bus_scale_pdata *qrng_platform_support = NULL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -220,6 +242,8 @@
qrng_platform_support = msm_bus_cl_get_pdata(pdev);
msm_rng_dev->qrng_perf_client = msm_bus_scale_register_client(
qrng_platform_support);
+ msm_rng_device_info.qrng_perf_client =
+ msm_rng_dev->qrng_perf_client;
if (!msm_rng_dev->qrng_perf_client)
pr_err("Unable to register bus client\n");
}
@@ -238,9 +262,27 @@
error = -EPERM;
goto rollback_clk;
}
+ ret = register_chrdev(QRNG_IOC_MAGIC, DRIVER_NAME, &msm_rng_fops);
- return 0;
+ msm_rng_class = class_create(THIS_MODULE, "msm-rng");
+ if (IS_ERR(msm_rng_class)) {
+ pr_err("class_create failed\n");
+ return PTR_ERR(msm_rng_class);
+ }
+ dev = device_create(msm_rng_class, NULL, MKDEV(QRNG_IOC_MAGIC, 0),
+ NULL, "msm-rng");
+ if (IS_ERR(dev)) {
+ pr_err("Device create failed\n");
+ error = PTR_ERR(dev);
+ goto unregister_chrdev;
+ }
+ cdev_init(&msm_rng_cdev, &msm_rng_fops);
+
+ return ret;
+
+unregister_chrdev:
+ unregister_chrdev(QRNG_IOC_MAGIC, DRIVER_NAME);
rollback_clk:
clk_put(msm_rng_dev->prng_clk);
err_clk_get:
@@ -254,7 +296,7 @@
static int __devexit msm_rng_remove(struct platform_device *pdev)
{
struct msm_rng_device *msm_rng_dev = platform_get_drvdata(pdev);
-
+ unregister_chrdev(QRNG_IOC_MAGIC, DRIVER_NAME);
hwrng_unregister(&msm_rng);
clk_put(msm_rng_dev->prng_clk);
iounmap(msm_rng_dev->base);
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index adaff41..9839595 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -147,7 +147,6 @@
struct list_head list;
int64_t die_temp;
struct delayed_work iadc_work;
- struct mutex iadc_vadc_lock;
bool iadc_mode_sel;
struct qpnp_iadc_comp iadc_comp;
struct qpnp_vadc_chip *vadc_dev;
@@ -1012,12 +1011,10 @@
if (qpnp_iadc_is_valid(iadc) < 0)
return -EPROBE_DEFER;
- if (!iadc->iadc_mode_sel) {
- rc = qpnp_check_pmic_temp(iadc);
- if (rc) {
- pr_err("Error checking pmic therm temp\n");
- return rc;
- }
+ rc = qpnp_check_pmic_temp(iadc);
+ if (rc) {
+ pr_err("Error checking pmic therm temp\n");
+ return rc;
}
mutex_lock(&iadc->adc->adc_lock);
@@ -1121,24 +1118,21 @@
enum qpnp_iadc_channels i_channel, struct qpnp_iadc_result *i_result,
enum qpnp_vadc_channels v_channel, struct qpnp_vadc_result *v_result)
{
- int rc = 0;
+ int rc = 0, mode_sel = 0, num = 0, rsense_n_ohms = 0, sign = 0;
+ uint16_t raw_data;
+ int32_t rsense_u_ohms = 0;
+ int64_t result_current;
if (qpnp_iadc_is_valid(iadc) < 0)
return -EPROBE_DEFER;
- mutex_lock(&iadc->iadc_vadc_lock);
+ mutex_lock(&iadc->adc->adc_lock);
if (iadc->iadc_poll_eoc) {
pr_debug("acquiring iadc eoc wakelock\n");
pm_stay_awake(iadc->dev);
}
- rc = qpnp_check_pmic_temp(iadc);
- if (rc) {
- pr_err("PMIC die temp check failed\n");
- goto fail;
- }
-
iadc->iadc_mode_sel = true;
rc = qpnp_vadc_iadc_sync_request(iadc->vadc_dev, v_channel);
@@ -1147,11 +1141,43 @@
goto fail;
}
- rc = qpnp_iadc_read(iadc, i_channel, i_result);
- if (rc)
- pr_err("Configuring IADC failed\n");
- /* Intentional fall through to release VADC */
+ rc = qpnp_iadc_configure(iadc, i_channel, &raw_data, mode_sel);
+ if (rc < 0) {
+ pr_err("qpnp adc result read failed with %d\n", rc);
+ goto fail_release_vadc;
+ }
+ rc = qpnp_iadc_get_rsense(iadc, &rsense_n_ohms);
+ pr_debug("current raw:0%x and rsense:%d\n",
+ raw_data, rsense_n_ohms);
+ rsense_u_ohms = rsense_n_ohms/1000;
+ num = raw_data - iadc->adc->calib.offset_raw;
+ if (num < 0) {
+ sign = 1;
+ num = -num;
+ }
+
+ i_result->result_uv = (num * QPNP_ADC_GAIN_NV)/
+ (iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw);
+ result_current = i_result->result_uv;
+ result_current *= QPNP_IADC_NANO_VOLTS_FACTOR;
+ /* Intentional fall through. Process the result w/o comp */
+ do_div(result_current, rsense_u_ohms);
+
+ if (sign) {
+ i_result->result_uv = -i_result->result_uv;
+ result_current = -result_current;
+ }
+ result_current *= -1;
+ rc = qpnp_iadc_comp_result(iadc, &result_current);
+ if (rc < 0)
+ pr_err("Error during compensating the IADC\n");
+ rc = 0;
+ result_current *= -1;
+
+ i_result->result_ua = (int32_t) result_current;
+
+fail_release_vadc:
rc = qpnp_vadc_iadc_sync_complete_request(iadc->vadc_dev, v_channel,
v_result);
if (rc)
@@ -1163,7 +1189,7 @@
pr_debug("releasing iadc eoc wakelock\n");
pm_relax(iadc->dev);
}
- mutex_unlock(&iadc->iadc_vadc_lock);
+ mutex_unlock(&iadc->adc->adc_lock);
return rc;
}
@@ -1306,7 +1332,6 @@
goto fail;
}
- mutex_init(&iadc->iadc_vadc_lock);
INIT_WORK(&iadc->trigger_completion_work, qpnp_iadc_trigger_completion);
INIT_DELAYED_WORK(&iadc->iadc_work, qpnp_iadc_work);
rc = qpnp_iadc_comp_info(iadc);
@@ -1347,7 +1372,6 @@
int i = 0;
cancel_delayed_work(&iadc->iadc_work);
- mutex_destroy(&iadc->iadc_vadc_lock);
for_each_child_of_node(node, child) {
device_remove_file(&spmi->dev,
&iadc->sens_attr[i].dev_attr);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index a8da26d..f5529cd 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -620,7 +620,10 @@
msm_camera_io_w_mb(0x0, vfe_dev->vfe_base + 0x1E0);
vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
} else if (update_state == DISABLE_CAMIF_IMMEDIATELY) {
- msm_camera_io_w_mb(0x2, vfe_dev->vfe_base + 0x1E0);
+ msm_camera_io_w_mb(0x6, vfe_dev->vfe_base + 0x1E0);
+ vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev);
+ vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev);
+ vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);
vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
}
}
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 9047c40..50a25bd 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -866,7 +866,10 @@
msm_camera_io_w_mb(0x0, vfe_dev->vfe_base + 0x2F4);
vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
} else if (update_state == DISABLE_CAMIF_IMMEDIATELY) {
- msm_camera_io_w_mb(0x2, vfe_dev->vfe_base + 0x2F4);
+ msm_camera_io_w_mb(0x6, vfe_dev->vfe_base + 0x2F4);
+ vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev);
+ vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev);
+ vfe_dev->hw_info->vfe_ops.core_ops.init_hw_reg(vfe_dev);
vfe_dev->axi_data.src_info[VFE_PIX_0].active = 0;
}
}
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 9c92a7b..3202cdb 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
@@ -318,7 +318,8 @@
stream_info->state == PAUSED ||
stream_info->state == RESUME_PENDING ||
stream_info->state == RESUMING) &&
- stream_cfg_cmd->cmd == STOP_STREAM) {
+ (stream_cfg_cmd->cmd == STOP_STREAM ||
+ stream_cfg_cmd->cmd == STOP_IMMEDIATELY)) {
stream_info->state = ACTIVE;
} else {
pr_err("%s: Invalid stream state: %d\n",
@@ -654,7 +655,9 @@
}
}
- if (vfe_dev->axi_data.pipeline_update == DISABLE_CAMIF) {
+ if (vfe_dev->axi_data.pipeline_update == DISABLE_CAMIF ||
+ (vfe_dev->axi_data.pipeline_update ==
+ DISABLE_CAMIF_IMMEDIATELY)) {
vfe_dev->hw_info->vfe_ops.stats_ops.
enable_module(vfe_dev, 0xFF, 0);
vfe_dev->axi_data.pipeline_update = NO_UPDATE;
@@ -865,6 +868,10 @@
(cur_pix_stream_cnt - pix_stream_cnt) == 0 &&
stream_cfg_cmd->cmd == STOP_STREAM)
return DISABLE_CAMIF;
+ else if (cur_pix_stream_cnt &&
+ (cur_pix_stream_cnt - pix_stream_cnt) == 0 &&
+ stream_cfg_cmd->cmd == STOP_IMMEDIATELY)
+ return DISABLE_CAMIF_IMMEDIATELY;
}
return NO_UPDATE;
}
@@ -1176,6 +1183,9 @@
if (camif_update == DISABLE_CAMIF)
vfe_dev->hw_info->vfe_ops.core_ops.
update_camif_state(vfe_dev, DISABLE_CAMIF);
+ else if (camif_update == DISABLE_CAMIF_IMMEDIATELY)
+ vfe_dev->hw_info->vfe_ops.core_ops.
+ update_camif_state(vfe_dev, DISABLE_CAMIF_IMMEDIATELY);
msm_isp_update_camif_output_count(vfe_dev, stream_cfg_cmd);
for (i = 0; i < stream_cfg_cmd->num_streams; i++) {
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_common.h b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_common.h
index 04af6b6..634beca 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_common.h
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_common.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, 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
@@ -20,7 +20,7 @@
#endif
#define JPEG_PR_ERR pr_err
-#define JPEG_DBG_HIGH pr_err
+#define JPEG_DBG_HIGH pr_debug
enum JPEG_MODE {
JPEG_MODE_DISABLE,
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
index 5d34265..44a4014 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_hw.c
@@ -216,15 +216,15 @@
if (pingpong_index == 0) {
hw_cmd_p = &hw_cmd_we_ping_update[0];
hw_cmd_p->data = p_input->y_buffer_addr;
- JPEG_PR_ERR("%s Output pln0 buffer address is %x\n", __func__,
+ JPEG_DBG_HIGH("%s Output pln0 buffer address is %x\n", __func__,
p_input->y_buffer_addr);
msm_jpeg_hw_write(hw_cmd_p++, base);
hw_cmd_p->data = p_input->cbcr_buffer_addr;
- JPEG_PR_ERR("%s Output pln1 buffer address is %x\n", __func__,
+ JPEG_DBG_HIGH("%s Output pln1 buffer address is %x\n", __func__,
p_input->cbcr_buffer_addr);
msm_jpeg_hw_write(hw_cmd_p++, base);
hw_cmd_p->data = p_input->pln2_addr;
- JPEG_PR_ERR("%s Output pln2 buffer address is %x\n", __func__,
+ JPEG_DBG_HIGH("%s Output pln2 buffer address is %x\n", __func__,
p_input->pln2_addr);
msm_jpeg_hw_write(hw_cmd_p++, base);
}
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
index d6fa2b0..8f080ce 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.c
@@ -28,6 +28,19 @@
#include "msm_jpeg_common.h"
#include "msm_jpeg_hw.h"
+int msm_jpeg_platform_set_clk_rate(struct msm_jpeg_device *pgmn_dev,
+ long clk_rate)
+{
+ struct msm_cam_clk_info jpeg_core_clk_info[] = {
+ {"core_clk", JPEG_CLK_RATE, 0}
+ };
+
+ jpeg_core_clk_info[0].clk_rate = clk_rate;
+
+ return msm_cam_clk_enable(&pgmn_dev->pdev->dev, jpeg_core_clk_info,
+ pgmn_dev->jpeg_clk, ARRAY_SIZE(jpeg_core_clk_info), 1);
+}
+
void msm_jpeg_platform_p2v(struct msm_jpeg_device *pgmn_dev, struct file *file,
struct ion_handle **ionhandle, int domain_num)
{
@@ -135,8 +148,8 @@
{
.src = MSM_BUS_MASTER_JPEG,
.dst = MSM_BUS_SLAVE_EBI_CH0,
- .ab = JPEG_CLK_RATE * 2.5,
- .ib = JPEG_CLK_RATE * 2.5,
+ .ab = JPEG_MAX_CLK_RATE * 2.5,
+ .ib = JPEG_MAX_CLK_RATE * 2.5,
},
};
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.h b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.h
index a14b8ee..7be9e19 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.h
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_platform.h
@@ -20,7 +20,10 @@
#include <mach/iommu.h>
#include "msm_jpeg_sync.h"
#define JPEG_CLK_RATE 266670000
+#define JPEG_MAX_CLK_RATE 320000000
+int msm_jpeg_platform_set_clk_rate(struct msm_jpeg_device *pgmn_dev,
+ long clk_rate);
void msm_jpeg_platform_p2v(struct msm_jpeg_device *pgmn_dev, struct file *file,
struct ion_handle **ionhandle, int domain_num);
uint32_t msm_jpeg_platform_v2p(struct msm_jpeg_device *pgmn_dev, int fd,
diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
index dffdab3..5cc51ff 100644
--- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
+++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_sync.c
@@ -806,6 +806,36 @@
return 0;
}
+int msm_jpeg_ioctl_set_clk_rate(struct msm_jpeg_device *pgmn_dev,
+ unsigned long arg)
+{
+ long clk_rate;
+ int rc;
+
+ if ((pgmn_dev->state != MSM_JPEG_INIT) &&
+ (pgmn_dev->state != MSM_JPEG_RESET)) {
+ JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+ if (get_user(clk_rate, (long __user *)arg)) {
+ JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+ JPEG_DBG("%s:%d] Requested clk rate %ld\n", __func__, __LINE__,
+ clk_rate);
+ if (clk_rate < 0) {
+ JPEG_PR_ERR("%s:%d] failed\n", __func__, __LINE__);
+ return -EFAULT;
+ }
+ rc = msm_jpeg_platform_set_clk_rate(pgmn_dev, clk_rate);
+ if (rc < 0) {
+ JPEG_PR_ERR("%s: clk failed rc = %d\n", __func__, rc);
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
long __msm_jpeg_ioctl(struct msm_jpeg_device *pgmn_dev,
unsigned int cmd, unsigned long arg)
{
@@ -875,6 +905,9 @@
rc = msm_jpeg_ioctl_test_dump_region(pgmn_dev, arg);
break;
+ case MSM_JPEG_IOCTL_SET_CLK_RATE:
+ rc = msm_jpeg_ioctl_set_clk_rate(pgmn_dev, arg);
+ break;
default:
JPEG_PR_ERR(KERN_INFO "%s:%d] cmd = %d not supported\n",
__func__, __LINE__, _IOC_NR(cmd));
diff --git a/drivers/media/platform/msm/vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c
index 5140a03..9604a09 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.c
+++ b/drivers/media/platform/msm/vidc/msm_smem.c
@@ -171,8 +171,10 @@
mem->smem_priv = hndl;
mem->device_addr = iova;
mem->size = buffer_size;
- dprintk(VIDC_DBG, "NOTE: Buffer device address: 0x%lx, size: %d\n",
- mem->device_addr, mem->size);
+ dprintk(VIDC_DBG,
+ "%s: ion_handle = 0x%p, fd = %d, device_addr = 0x%x, size = %d, kvaddr = 0x%p, buffer_type = %d\n",
+ __func__, mem->smem_priv, fd, (u32)mem->device_addr,
+ mem->size, mem->kvaddr, mem->buffer_type);
return rc;
fail_device_address:
ion_free(client->clnt, hndl);
@@ -241,10 +243,11 @@
goto fail_device_address;
}
mem->device_addr = iova;
- dprintk(VIDC_DBG,
- "device_address = 0x%lx, kvaddr = 0x%p, size = %d\n",
- mem->device_addr, mem->kvaddr, size);
mem->size = size;
+ dprintk(VIDC_DBG,
+ "%s: ion_handle = 0x%p, device_addr = 0x%x, size = %d, kvaddr = 0x%p, buffer_type = %d\n",
+ __func__, mem->smem_priv, (u32)mem->device_addr,
+ mem->size, mem->kvaddr, mem->buffer_type);
return rc;
fail_device_address:
ion_unmap_kernel(client->clnt, hndl);
@@ -258,6 +261,10 @@
{
int domain, partition, rc;
+ dprintk(VIDC_DBG,
+ "%s: ion_handle = 0x%p, device_addr = 0x%x, size = %d, kvaddr = 0x%p, buffer_type = %d\n",
+ __func__, mem->smem_priv, (u32)mem->device_addr,
+ mem->size, mem->kvaddr, mem->buffer_type);
rc = msm_smem_get_domain_partition((void *)client, mem->flags,
mem->buffer_type, &domain, &partition);
if (rc) {
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index efa195e..9dd4e93 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -971,6 +971,14 @@
rc = -EINVAL;
goto err_invalid_fmt;
}
+ if (!(get_hal_codec_type(fmt->fourcc) &
+ inst->core->dec_codec_supported)) {
+ dprintk(VIDC_ERR,
+ "Codec(0x%x) not supported\n",
+ get_hal_codec_type(fmt->fourcc));
+ rc = -EINVAL;
+ goto err_invalid_fmt;
+ }
inst->fmts[fmt->type] = fmt;
rc = msm_comm_try_state(inst, MSM_VIDC_OPEN_DONE);
if (rc) {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 25917c1..3c18241 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -489,6 +489,7 @@
temp->handle[plane]->device_addr + binfo->buff_off[i];
b->m.planes[i].m.userptr = binfo->device_addr[i];
binfo->mapped[i] = false;
+ binfo->handle[i] = temp->handle[i];
} else {
if (inst->map_output_buffer) {
binfo->handle[i] =
@@ -498,9 +499,6 @@
rc = -EINVAL;
goto exit;
}
- dprintk(VIDC_DBG,
- "[MAP] - mapped handle[%d] = %p fd[%d] = %d",
- i, binfo->handle[i], i, binfo->fd[i]);
binfo->mapped[i] = true;
binfo->device_addr[i] =
binfo->handle[i]->device_addr +
@@ -511,10 +509,6 @@
binfo->device_addr[i] =
b->m.planes[i].m.userptr;
}
- dprintk(VIDC_DBG, "Registering buffer: %d, %d, %d\n",
- b->m.planes[i].reserved[0],
- b->m.planes[i].reserved[1],
- b->m.planes[i].length);
}
/* We maintain one ref count for all planes*/
if ((i == 0) && is_dynamic_output_buffer_mode(b, inst)) {
@@ -522,8 +516,12 @@
if (rc < 0)
return rc;
}
+ dprintk(VIDC_DBG,
+ "%s: [MAP] binfo = %p, handle[%d] = %p, device_addr = 0x%x, fd = %d, offset = %d, mapped = %d\n",
+ __func__, binfo, i, binfo->handle[i],
+ binfo->device_addr[i], binfo->fd[i],
+ binfo->buff_off[i], binfo->mapped[i]);
}
- dprintk(VIDC_DBG, "[MAP] Adding binfo = %p to list\n", binfo);
mutex_lock(&inst->lock);
list_add_tail(&binfo->list, &inst->registered_bufs);
mutex_unlock(&inst->lock);
@@ -570,6 +568,11 @@
goto exit;
for (i = 0; i < temp->num_planes; i++) {
+ dprintk(VIDC_DBG,
+ "%s: [UNMAP] binfo = %p, handle[%d] = %p, device_addr = 0x%x, fd = %d, offset = %d, mapped = %d\n",
+ __func__, temp, i, temp->handle[i],
+ temp->device_addr[i], temp->fd[i],
+ temp->buff_off[i], temp->mapped[i]);
/*
* Unmap the handle only if the buffer has been mapped and no
* other buffer has a reference to this buffer.
@@ -581,9 +584,6 @@
*/
if (temp->handle[i] && temp->mapped[i] &&
!temp->same_fd_ref[i]) {
- dprintk(VIDC_DBG,
- "[UNMAP] - handle[%d] = %p fd[%d] = %d",
- i, temp->handle[i], i, temp->fd[i]);
msm_comm_smem_free(inst,
temp->handle[i]);
}
@@ -668,7 +668,8 @@
__func__, rc);
return -EINVAL;
}
- }
+ } else
+ dprintk(VIDC_ERR, "%s: WARN: NULL handle", __func__);
}
return 0;
}
@@ -742,11 +743,18 @@
buffer_info.m.planes[0].reserved[0],
buffer_info.m.planes[0].reserved[1],
buffer_info.m.planes[0].length);
+
list_del(&bi->list);
for (i = 0; i < bi->num_planes; i++) {
- if (bi->handle[i])
+ if (bi->handle[i] && bi->mapped[i]) {
+ dprintk(VIDC_DBG,
+ "%s: [UNMAP] binfo = %p, handle[%d] = %p, device_addr = 0x%x, fd = %d, offset = %d, mapped = %d\n",
+ __func__, bi, i, bi->handle[i],
+ bi->device_addr[i], bi->fd[i],
+ bi->buff_off[i], bi->mapped[i]);
msm_comm_smem_free(inst,
bi->handle[i]);
+ }
}
kfree(bi);
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 239bc34..3eb5f49 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -277,14 +277,17 @@
dprintk(VIDC_ERR, "Wrong device_id received\n");
return;
}
- dprintk(VIDC_DBG, "index = %d\n", index);
- dprintk(VIDC_DBG, "ptr = %p\n", &(core->completions[index]));
- complete(&(core->completions[index]));
sys_init_msg = response->data;
if (!sys_init_msg) {
dprintk(VIDC_ERR, "sys_init_done message not proper\n");
return;
}
+ core->enc_codec_supported = sys_init_msg->enc_codec_supported;
+ core->dec_codec_supported = sys_init_msg->dec_codec_supported;
+ dprintk(VIDC_DBG, "supported_codecs: enc = 0x%x, dec = 0x%x\n",
+ core->enc_codec_supported, core->dec_codec_supported);
+ dprintk(VIDC_DBG, "ptr[%d] = %p\n", index, &(core->completions[index]));
+ complete(&(core->completions[index]));
}
static void handle_session_release_buf_done(enum command_response cmd,
@@ -941,6 +944,12 @@
V4L2_QCOM_BUF_DATA_CORRUPT;
}
}
+ dprintk(VIDC_DBG,
+ "Got ebd from hal: device_addr: 0x%x, alloc: %d, status: 0x%x, pic_type: 0x%x, flags: 0x%x\n",
+ (u32)empty_buf_done->packet_buffer,
+ empty_buf_done->alloc_len, empty_buf_done->status,
+ empty_buf_done->picture_type, empty_buf_done->flags);
+
mutex_lock(&inst->bufq[OUTPUT_PORT].lock);
vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
mutex_unlock(&inst->bufq[OUTPUT_PORT].lock);
@@ -1099,6 +1108,7 @@
struct vb2_buffer *vb = NULL;
struct vidc_hal_fbd *fill_buf_done;
enum hal_buffer buffer_type;
+ int64_t time_usec = 0;
if (!response) {
dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
@@ -1138,7 +1148,7 @@
if (!(fill_buf_done->flags1 &
HAL_BUFFERFLAG_TIMESTAMPINVALID) &&
fill_buf_done->filled_len1) {
- int64_t time_usec = fill_buf_done->timestamp_hi;
+ time_usec = fill_buf_done->timestamp_hi;
time_usec = (time_usec << 32) |
fill_buf_done->timestamp_lo;
vb->v4l2_buf.timestamp =
@@ -1191,10 +1201,14 @@
msm_vidc_debugfs_update(inst,
MSM_VIDC_DEBUGFS_EVENT_FBD);
- dprintk(VIDC_DBG, "Filled length = %d; offset = %d; flags %x\n",
- vb->v4l2_planes[0].bytesused,
- vb->v4l2_planes[0].data_offset,
- vb->v4l2_buf.flags);
+ dprintk(VIDC_DBG,
+ "Got fbd from hal: device_addr: 0x%x, alloc: %d, filled: %d, offset: %d, ts: %lld, flags: 0x%x, crop: %d %d %d %d, pic_type: 0x%x\n",
+ (u32)fill_buf_done->packet_buffer1, fill_buf_done->alloc_len1,
+ fill_buf_done->filled_len1, fill_buf_done->offset1, time_usec,
+ fill_buf_done->flags1, fill_buf_done->start_x_coord,
+ fill_buf_done->start_y_coord, fill_buf_done->frame_width,
+ fill_buf_done->frame_height, fill_buf_done->picture_type);
+
mutex_lock(&inst->bufq[CAPTURE_PORT].lock);
vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
mutex_unlock(&inst->bufq[CAPTURE_PORT].lock);
@@ -1598,7 +1612,7 @@
return domain;
}
-static enum hal_video_codec get_hal_codec_type(int fourcc)
+enum hal_video_codec get_hal_codec_type(int fourcc)
{
enum hal_video_codec codec;
dprintk(VIDC_DBG, "codec is 0x%x", fourcc);
@@ -2430,11 +2444,10 @@
V4L2_QCOM_BUF_TIMESTAMP_INVALID)
frame_data.timestamp = LLONG_MAX;
dprintk(VIDC_DBG,
- "Sending etb to hal: device_addr: 0x%x"
- "Alloc: %d, filled: %d, offset: %d\n",
- frame_data.device_addr,
- frame_data.alloc_len, frame_data.filled_len,
- frame_data.offset);
+ "Sending etb to hal: device_addr: 0x%x, alloc: %d, filled: %d, offset: %d, ts: %lld, flags = 0x%x\n",
+ frame_data.device_addr, frame_data.alloc_len,
+ frame_data.filled_len, frame_data.offset,
+ frame_data.timestamp, frame_data.flags);
rc = call_hfi_op(hdev, session_etb, (void *)
inst->session, &frame_data);
if (!rc)
@@ -2456,11 +2469,10 @@
frame_data.extradata_addr =
vb->v4l2_planes[extra_idx].m.userptr;
dprintk(VIDC_DBG,
- "Sending ftb to hal: Alloc: %d :filled: %d",
- frame_data.alloc_len, frame_data.filled_len);
- dprintk(VIDC_DBG,
- " extradata_addr: %d\n",
- frame_data.extradata_addr);
+ "Sending ftb to hal: device_addr: 0x%x, alloc: %d, buffer_type: %d, ts: %lld, flags = 0x%x\n",
+ frame_data.device_addr, frame_data.alloc_len,
+ frame_data.buffer_type, frame_data.timestamp,
+ frame_data.flags);
if (!inst->ftb_count &&
inst->session_type == MSM_VIDC_ENCODER) {
seq_hdr.seq_hdr = (u8 *) vb->v4l2_planes[0].
@@ -2476,9 +2488,9 @@
} else {
rc = call_hfi_op(hdev, session_ftb,
(void *) inst->session, &frame_data);
- if (!rc)
- msm_vidc_debugfs_update(inst,
- MSM_VIDC_DEBUGFS_EVENT_FTB);
+ if (!rc)
+ msm_vidc_debugfs_update(inst,
+ MSM_VIDC_DEBUGFS_EVENT_FTB);
}
inst->ftb_count++;
} else {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index 0861c91..e2f7b61 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -63,4 +63,5 @@
int msm_comm_smem_get_domain_partition(struct msm_vidc_inst *inst,
u32 flags, enum hal_buffer buffer_type,
int *domain_num, int *partition_num);
+enum hal_video_codec get_hal_codec_type(int fourcc);
#endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 2b1471c..e4f920f 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -207,6 +207,8 @@
struct completion completions[SYS_MSG_END - SYS_MSG_START + 1];
enum msm_vidc_hfi_type hfi_type;
struct msm_vidc_platform_resources resources;
+ u32 enc_codec_supported;
+ u32 dec_codec_supported;
};
struct msm_vidc_inst {
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 735b783..a8178f7 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -29,6 +29,7 @@
#include "venus_hfi.h"
#include "vidc_hfi_io.h"
#include "msm_vidc_debug.h"
+#include <linux/iopoll.h>
#define FIRMWARE_SIZE 0X00A00000
#define REG_ADDR_OFFSET_BITMASK 0x000FFFFF
@@ -77,6 +78,8 @@
static int venus_hfi_power_enable(void *dev);
+static inline int venus_hfi_clk_gating_off(struct venus_hfi_device *device);
+
static void venus_hfi_dump_packet(u8 *packet)
{
u32 c = 0, packet_size = *(u32 *)packet;
@@ -875,6 +878,34 @@
static DECLARE_COMPLETION(pc_prep_done);
+static int venus_hfi_halt_axi(struct venus_hfi_device *device)
+{
+ u32 reg;
+ int rc = 0;
+ if (!device) {
+ dprintk(VIDC_ERR, "Invalid input: %p\n", device);
+ return -EINVAL;
+ }
+ if (venus_hfi_clk_gating_off(device)) {
+ dprintk(VIDC_ERR, "Failed to turn off clk gating\n");
+ return -EIO;
+ }
+ /* Halt AXI and AXI OCMEM VBIF Access */
+ reg = venus_hfi_read_register(device, VENUS_VBIF_AXI_HALT_CTRL0);
+ reg |= VENUS_VBIF_AXI_HALT_CTRL0_HALT_REQ;
+ venus_hfi_write_register(device, VENUS_VBIF_AXI_HALT_CTRL0, reg, 0);
+
+ /* Request for AXI bus port halt */
+ rc = readl_poll_timeout((u32)device->hal_data->register_base_addr
+ + VENUS_VBIF_AXI_HALT_CTRL1,
+ reg, reg & VENUS_VBIF_AXI_HALT_CTRL1_HALT_ACK,
+ POLL_INTERVAL_US,
+ VENUS_VBIF_AXI_HALT_ACK_TIMEOUT_US);
+ if (rc)
+ dprintk(VIDC_WARN, "AXI bus port halt timeout\n");
+ return rc;
+}
+
static inline int venus_hfi_power_off(struct venus_hfi_device *device)
{
int rc = 0;
@@ -3306,15 +3337,21 @@
if (device->resources.fw.cookie) {
flush_workqueue(device->vidc_workq);
flush_workqueue(device->venus_pm_workq);
+ subsystem_put(device->resources.fw.cookie);
+ venus_hfi_interface_queues_release(dev);
+ /* IOMMU operations need to be done before AXI halt.*/
+ venus_hfi_iommu_detach(device);
+ /* Halt the AXI to make sure there are no pending transactions.
+ * Clocks should be unprepared after making sure axi is halted.
+ */
+ if(venus_hfi_halt_axi(device))
+ dprintk(VIDC_WARN, "Failed to halt AXI\n");
venus_hfi_disable_clks(device);
mutex_lock(&device->clk_pwr_lock);
- subsystem_put(device->resources.fw.cookie);
regulator_disable(device->gdsc);
device->power_enabled = 0;
--device->pwr_cnt;
mutex_unlock(&device->clk_pwr_lock);
- venus_hfi_interface_queues_release(dev);
- venus_hfi_iommu_detach(device);
device->resources.fw.cookie = NULL;
}
}
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_io.h b/drivers/media/platform/msm/vidc/vidc_hfi_io.h
index 6377fbf..176db4a 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_io.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_io.h
@@ -131,6 +131,15 @@
#define VIDC_VBIF_AT_OLD_HIGH (VIDC_VBIF_BASE_OFFS + 0xC08)
#define VIDC_VBIF_AT_NEW_BASE (VIDC_VBIF_BASE_OFFS + 0xC10)
#define VIDC_VBIF_AT_NEW_HIGH (VIDC_VBIF_BASE_OFFS + 0xC18)
+#define VENUS_VBIF_AXI_HALT_CTRL0 (VIDC_VBIF_BASE_OFFS + 0x208)
+#define VENUS_VBIF_AXI_HALT_CTRL1 (VIDC_VBIF_BASE_OFFS + 0x20C)
+
+#define VENUS_VBIF_AXI_HALT_CTRL0_HALT_REQ BIT(0)
+#define VENUS_VBIF_AXI_HALT_CTRL1_HALT_ACK BIT(0)
+#define VENUS_VBIF_AXI_HALT_ACK_TIMEOUT_US 500000
+/* Poll interval in uS */
+#define POLL_INTERVAL_US 50
+
#define VIDC_VENUS0_WRAPPER_VBIF_REQ_PRIORITY \
(VIDC_WRAPPER_BASE_OFFS + 0x20)
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 2162294..84ac1c3 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -871,6 +871,8 @@
struct qseecom_client_send_service_ireq *send_svc_ireq_ptr)
{
int ret = 0;
+ void *req_buf = NULL;
+
if ((req_ptr == NULL) || (send_svc_ireq_ptr == NULL)) {
pr_err("Error with pointer: req_ptr = %p, send_svc_ptr = %p\n",
req_ptr, send_svc_ireq_ptr);
@@ -880,9 +882,29 @@
pr_err("Invalid req/resp buffer, exiting\n");
return -EINVAL;
}
+
+ if (((uint32_t)req_ptr->cmd_req_buf <
+ data_ptr->client.user_virt_sb_base)
+ || ((uint32_t)req_ptr->cmd_req_buf >=
+ (data_ptr->client.user_virt_sb_base +
+ data_ptr->client.sb_length))) {
+ pr_err("cmd buffer address not within shared bufffer\n");
+ return -EINVAL;
+ }
+
+
+ if (((uint32_t)req_ptr->resp_buf < data_ptr->client.user_virt_sb_base)
+ || ((uint32_t)req_ptr->resp_buf >=
+ (data_ptr->client.user_virt_sb_base +
+ data_ptr->client.sb_length))){
+ pr_err("response buffer address not within shared bufffer\n");
+ return -EINVAL;
+ }
+
+ req_buf = data_ptr->client.sb_virt;
send_svc_ireq_ptr->qsee_cmd_id = req_ptr->cmd_id;
send_svc_ireq_ptr->key_type =
- ((struct qseecom_rpmb_provision_key *)req_ptr->cmd_req_buf)->key_type;
+ ((struct qseecom_rpmb_provision_key *)req_buf)->key_type;
send_svc_ireq_ptr->req_len = req_ptr->cmd_req_len;
send_svc_ireq_ptr->rsp_ptr = (void *)(__qseecom_uvirt_to_kphys(data_ptr,
(uint32_t)req_ptr->resp_buf));
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 9d23e84..0eab568 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -347,7 +347,6 @@
void __iomem *wlan_tx_phy_aborts;
void __iomem *wlan_brdg_err_source;
void __iomem *fiq_reg;
- int ssr_boot;
int nv_downloaded;
unsigned char *fw_cal_data;
unsigned char *user_cal_data;
@@ -762,8 +761,6 @@
case SMD_EVENT_CLOSE:
pr_debug("wcnss: closing WCNSS SMD channel :%s",
WCNSS_CTRL_CHANNEL);
- /* This SMD is closed only during SSR */
- penv->ssr_boot = true;
penv->nv_downloaded = 0;
break;
@@ -1355,6 +1352,17 @@
goto exit;
}
+ if (penv->fw_cal_available) {
+ /* ignore cal upload from SSR */
+ smd_read(penv->smd_ch, NULL, calhdr.frag_size);
+ penv->fw_cal_exp_frag++;
+ if (calhdr.msg_flags & LAST_FRAGMENT) {
+ penv->fw_cal_exp_frag = 0;
+ goto exit;
+ }
+ return;
+ }
+
if (0 == calhdr.frag_number) {
if (calhdr.total_size > MAX_CALIBRATED_DATA_SIZE) {
pr_err("wcnss: Invalid cal data size %d",
@@ -1528,7 +1536,6 @@
break;
case WCNSS_CALDATA_UPLD_REQ:
- penv->fw_cal_available = 0;
extract_cal_data(len);
break;
@@ -1778,21 +1785,12 @@
while (!penv->user_cal_available && retry++ < 5)
msleep(500);
}
-
- /* only cal data is sent during ssr (if available) */
- if (penv->fw_cal_available && penv->ssr_boot) {
- pr_info_ratelimited("wcnss: cal download during SSR, using fw cal");
- wcnss_caldata_dnld(penv->fw_cal_data, penv->fw_cal_rcvd, false);
- return;
-
- } else if (penv->user_cal_available && penv->ssr_boot) {
- pr_info_ratelimited("wcnss: cal download during SSR, using user cal");
- wcnss_caldata_dnld(penv->user_cal_data,
- penv->user_cal_rcvd, false);
- return;
+ if (penv->fw_cal_available) {
+ pr_info_ratelimited("wcnss: cal download, using fw cal");
+ wcnss_caldata_dnld(penv->fw_cal_data, penv->fw_cal_rcvd, true);
} else if (penv->user_cal_available) {
- pr_info_ratelimited("wcnss: cal download during cold boot, using user cal");
+ pr_info_ratelimited("wcnss: cal download, using user cal");
wcnss_caldata_dnld(penv->user_cal_data,
penv->user_cal_rcvd, true);
}
diff --git a/drivers/of/of_batterydata.c b/drivers/of/of_batterydata.c
index b0d40f1..32aae74 100644
--- a/drivers/of/of_batterydata.c
+++ b/drivers/of/of_batterydata.c
@@ -228,7 +228,7 @@
OF_PROP_READ(batt_data->rbatt_capacitive_mohm,
"rbatt-capacitive-mohm", node, rc, false);
OF_PROP_READ(batt_data->flat_ocv_threshold_uv,
- "flat-ocv-threshold", node, rc, true);
+ "flat-ocv-threshold-uv", node, rc, true);
OF_PROP_READ(batt_data->max_voltage_uv,
"max-voltage-uv", node, rc, true);
OF_PROP_READ(batt_data->cutoff_uv, "v-cutoff-uv", node, rc, true);
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 095fddf..25c0237 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -70,8 +70,9 @@
#define CHGR_IBAT_TERM_CHGR 0x5B
#define CHGR_IBAT_TERM_BMS 0x5C
#define CHGR_VBAT_DET 0x5D
+#define CHGR_TTRKL_MAX_EN 0x5E
#define CHGR_TTRKL_MAX 0x5F
-#define CHGR_TTRKL_MAX_EN 0x60
+#define CHGR_TCHG_MAX_EN 0x60
#define CHGR_TCHG_MAX 0x61
#define CHGR_CHG_WDOG_TIME 0x62
#define CHGR_CHG_WDOG_DLY 0x63
@@ -1187,9 +1188,16 @@
qpnp_chg_usb_chg_gone_irq_handler(int irq, void *_chip)
{
struct qpnp_chg_chip *chip = _chip;
+ u8 usb_sts;
+ int rc;
+
+ rc = qpnp_chg_read(chip, &usb_sts,
+ INT_RT_STS(chip->usb_chgpth_base), 1);
+ if (rc)
+ pr_err("failed to read usb_chgpth_sts rc=%d\n", rc);
pr_debug("chg_gone triggered\n");
- if (qpnp_chg_is_usb_chg_plugged_in(chip)) {
+ if (qpnp_chg_is_usb_chg_plugged_in(chip) && (usb_sts & CHG_GONE_IRQ)) {
qpnp_chg_charge_en(chip, 0);
qpnp_chg_force_run_on_batt(chip, 1);
schedule_delayed_work(&chip->arb_stop_work,
@@ -2406,21 +2414,44 @@
}
#define QPNP_CHG_TCHG_MASK 0x7F
+#define QPNP_CHG_TCHG_EN_MASK 0x80
#define QPNP_CHG_TCHG_MIN 4
#define QPNP_CHG_TCHG_MAX 512
#define QPNP_CHG_TCHG_STEP 4
static int qpnp_chg_tchg_max_set(struct qpnp_chg_chip *chip, int minutes)
{
u8 temp;
+ int rc;
if (minutes < QPNP_CHG_TCHG_MIN || minutes > QPNP_CHG_TCHG_MAX) {
pr_err("bad max minutes =%d asked to set\n", minutes);
return -EINVAL;
}
- temp = (minutes - 1)/QPNP_CHG_TCHG_STEP;
- return qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX,
+ rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX_EN,
+ QPNP_CHG_TCHG_EN_MASK, 0, 1);
+ if (rc) {
+ pr_err("failed write tchg_max_en rc=%d\n", rc);
+ return rc;
+ }
+
+ temp = minutes / QPNP_CHG_TCHG_STEP - 1;
+
+ rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX,
QPNP_CHG_TCHG_MASK, temp, 1);
+ if (rc) {
+ pr_err("failed write tchg_max_en rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_chg_masked_write(chip, chip->chgr_base + CHGR_TCHG_MAX_EN,
+ QPNP_CHG_TCHG_EN_MASK, QPNP_CHG_TCHG_EN_MASK, 1);
+ if (rc) {
+ pr_err("failed write tchg_max_en rc=%d\n", rc);
+ return rc;
+ }
+
+ return 0;
}
static int
@@ -4708,6 +4739,7 @@
goto unregister_dc_psy;
}
+ qpnp_chg_usb_chg_gone_irq_handler(chip->chg_gone.irq, chip);
qpnp_chg_usb_usbin_valid_irq_handler(chip->usbin_valid.irq, chip);
qpnp_chg_dc_dcin_valid_irq_handler(chip->dcin_valid.irq, chip);
power_supply_set_present(chip->usb_psy,
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 4251968..1ad0054 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -40,6 +40,7 @@
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/swap.h>
+#include <linux/fs.h>
#ifdef CONFIG_HIGHMEM
#define _ZONE ZONE_HIGHMEM
@@ -246,8 +247,14 @@
}
other_free = global_page_state(NR_FREE_PAGES);
- other_file = global_page_state(NR_FILE_PAGES) -
- global_page_state(NR_SHMEM);
+
+ if (global_page_state(NR_SHMEM) + total_swapcache_pages <
+ global_page_state(NR_FILE_PAGES))
+ other_file = global_page_state(NR_FILE_PAGES) -
+ global_page_state(NR_SHMEM) -
+ total_swapcache_pages;
+ else
+ other_file = 0;
tune_lmk_param(&other_free, &other_file, sc);
diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c
index 523b937..41a6803 100644
--- a/drivers/staging/zsmalloc/zsmalloc-main.c
+++ b/drivers/staging/zsmalloc/zsmalloc-main.c
@@ -430,7 +430,12 @@
return next;
}
-/* Encode <page, obj_idx> as a single handle value */
+/*
+ * Encode <page, obj_idx> as a single handle value.
+ * On hardware platforms with physical memory starting at 0x0 the pfn
+ * could be 0 so we ensure that the handle will never be 0 by adjusting the
+ * encoded obj_idx value before encoding.
+ */
static void *obj_location_to_handle(struct page *page, unsigned long obj_idx)
{
unsigned long handle;
@@ -441,17 +446,21 @@
}
handle = page_to_pfn(page) << OBJ_INDEX_BITS;
- handle |= (obj_idx & OBJ_INDEX_MASK);
+ handle |= ((obj_idx + 1) & OBJ_INDEX_MASK);
return (void *)handle;
}
-/* Decode <page, obj_idx> pair from the given object handle */
+/*
+ * Decode <page, obj_idx> pair from the given object handle. We adjust the
+ * decoded obj_idx back to its original value since it was adjusted in
+ * obj_location_to_handle().
+ */
static void obj_handle_to_location(unsigned long handle, struct page **page,
unsigned long *obj_idx)
{
*page = pfn_to_page(handle >> OBJ_INDEX_BITS);
- *obj_idx = handle & OBJ_INDEX_MASK;
+ *obj_idx = (handle & OBJ_INDEX_MASK) - 1;
}
static unsigned long obj_idx_to_offset(struct page *page,
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 078929b..ecfacc0 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -67,14 +67,65 @@
#include <mach/sps.h>
#include <mach/msm_serial_hs.h>
#include <mach/msm_bus.h>
-
+#include <mach/msm_ipc_logging.h>
#include "msm_serial_hs_hwreg.h"
#define UART_SPS_CONS_PERIPHERAL 0
#define UART_SPS_PROD_PERIPHERAL 1
-static int hs_serial_debug_mask = 1;
+static void *ipc_msm_hs_log_ctxt;
+#define IPC_MSM_HS_LOG_PAGES 5
+
+/* If the debug_mask gets set to FATAL_LEV,
+ * a fatal error has happened and further IPC logging
+ * is disabled so that this problem can be detected
+ */
+enum {
+ FATAL_LEV = 0U,
+ ERR_LEV = 1U,
+ WARN_LEV = 2U,
+ INFO_LEV = 3U,
+ DBG_LEV = 4U,
+};
+
+/* Default IPC log level INFO */
+static int hs_serial_debug_mask = INFO_LEV;
module_param_named(debug_mask, hs_serial_debug_mask,
int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+#define MSM_HS_DBG(x...) do { \
+ if (hs_serial_debug_mask >= DBG_LEV) { \
+ pr_debug(x); \
+ if (ipc_msm_hs_log_ctxt) \
+ ipc_log_string(ipc_msm_hs_log_ctxt, x); \
+ } \
+} while (0)
+
+#define MSM_HS_INFO(x...) do { \
+ if (hs_serial_debug_mask >= INFO_LEV) {\
+ pr_info(x); \
+ if (ipc_msm_hs_log_ctxt) \
+ ipc_log_string(ipc_msm_hs_log_ctxt, x); \
+ } \
+} while (0)
+
+/* warnings and errors show up on console always */
+#define MSM_HS_WARN(x...) do { \
+ pr_warn(x); \
+ if (ipc_msm_hs_log_ctxt && hs_serial_debug_mask >= WARN_LEV) \
+ ipc_log_string(ipc_msm_hs_log_ctxt, x); \
+} while (0)
+
+/* ERROR condition in the driver sets the hs_serial_debug_mask
+ * to ERR_FATAL level, so that this message can be seen
+ * in IPC logging. Further errors continue to log on the console
+ */
+#define MSM_HS_ERR(x...) do { \
+ pr_err(x); \
+ if (ipc_msm_hs_log_ctxt && hs_serial_debug_mask >= ERR_LEV) { \
+ ipc_log_string(ipc_msm_hs_log_ctxt, x); \
+ hs_serial_debug_mask = FATAL_LEV; \
+ } \
+} while (0)
/*
* There are 3 different kind of UART Core available on MSM.
* High Speed UART (i.e. Legacy HSUART), GSBI based HSUART
@@ -316,19 +367,19 @@
switch (cmd) {
case MSM_ENABLE_UART_CLOCK: {
- pr_debug("%s():ENABLE UART CLOCK: cmd=%d\n", __func__, cmd);
+ MSM_HS_DBG("%s():ENABLE UART CLOCK: cmd=%d\n", __func__, cmd);
msm_hs_request_clock_on(&msm_uport->uport);
break;
}
case MSM_DISABLE_UART_CLOCK: {
- pr_debug("%s():DISABLE UART CLOCK: cmd=%d\n", __func__, cmd);
+ MSM_HS_DBG("%s():DISABLE UART CLOCK: cmd=%d\n", __func__, cmd);
msm_hs_request_clock_off(&msm_uport->uport);
break;
}
case MSM_GET_UART_CLOCK_STATUS: {
/* Return value 0 - UART CLOCK is OFF
* Return value 1 - UART CLOCK is ON */
- pr_debug("%s():GET UART CLOCK STATUS: cmd=%d\n", __func__, cmd);
+ MSM_HS_DBG("%s():GET UART CLOCK STATUS: cmd=%d\n", __func__, cmd);
spin_lock_irqsave(&msm_uport->uport.lock, flags);
clk_state = msm_uport->clk_state;
spin_unlock_irqrestore(&msm_uport->uport.lock, flags);
@@ -338,7 +389,7 @@
break;
}
default: {
- pr_debug("%s():Unknown cmd specified: cmd=%d\n", __func__, cmd);
+ MSM_HS_DBG("%s():Unknown cmd specified: cmd=%d\n", __func__, cmd);
ret = -ENOIOCTLCMD;
break;
}
@@ -470,11 +521,11 @@
int ret;
if (is_blsp_uart(msm_uport) && msm_uport->bus_perf_client) {
- pr_debug("Bus voting:%d\n", vote);
+ MSM_HS_DBG("Bus voting:%d\n", vote);
ret = msm_bus_scale_client_update_request(
msm_uport->bus_perf_client, vote);
if (ret)
- pr_err("%s(): Failed for Bus voting: %d\n",
+ MSM_HS_ERR("%s(): Failed for Bus voting: %d\n",
__func__, vote);
}
}
@@ -500,6 +551,37 @@
writel_relaxed(value, uport->membase + offset);
}
+static void hex_dump_ipc(char *prefix, char *string, int size)
+{
+ char linebuf[512];
+
+ hex_dump_to_buffer(string, size, 16, 1, linebuf, sizeof(linebuf), 1);
+ MSM_HS_DBG("%s : %s", prefix, linebuf);
+}
+
+/*
+ * This API read and provides UART Core registers information.
+*/
+static void dump_uart_hs_registers(struct msm_hs_port *msm_uport)
+{
+ msm_hs_clock_vote(msm_uport);
+ MSM_HS_DBG("============= UART Registers ================\n");
+ MSM_HS_DBG("UART_DM_MR1:%x\n", msm_hs_read(&(msm_uport->uport),
+ UART_DM_MR1));
+ MSM_HS_DBG("UART_DM_MR2:%x\n", msm_hs_read(&(msm_uport->uport),
+ UART_DM_MR2));
+ MSM_HS_DBG("UART_DM_IPR:%x\n", msm_hs_read(&(msm_uport->uport),
+ UART_DM_IPR));
+ MSM_HS_DBG("UART_DM_RFWR:%x\n", msm_hs_read(&(msm_uport->uport),
+ UART_DM_RFWR));
+ MSM_HS_DBG("UART_DM_SR:%x\n", msm_hs_read(&(msm_uport->uport),
+ UART_DM_SR));
+ MSM_HS_DBG("UART_DM_IMR: %x\n", msm_hs_read(&(msm_uport->uport),
+ UART_DM_IMR));
+ MSM_HS_DBG("=============================================\n");
+ msm_hs_clock_unvote(msm_uport);
+}
+
static void msm_hs_release_port(struct uart_port *port)
{
struct msm_hs_port *msm_uport = UARTDM_TO_MSM(port);
@@ -626,7 +708,7 @@
&loopback_enable_fops);
if (IS_ERR_OR_NULL(msm_uport->loopback_dir))
- pr_err("%s(): Cannot create loopback.%d debug entry",
+ MSM_HS_ERR("%s(): Cannot create loopback.%d debug entry",
__func__, id);
}
@@ -637,7 +719,7 @@
struct device *dev;
if (pdev->id < 0 || pdev->id >= UARTDM_NR) {
- printk(KERN_ERR "Invalid plaform device ID = %d\n", pdev->id);
+ MSM_HS_ERR(KERN_ERR "Invalid plaform device ID = %d\n", pdev->id);
return -EINVAL;
}
@@ -691,13 +773,13 @@
/* Set up the MREG/NREG/DREG/MNDREG */
ret = clk_set_rate(msm_uport->clk, uport->uartclk);
if (ret) {
- printk(KERN_WARNING "Error setting clock rate on UART\n");
+ MSM_HS_WARN("Error setting clock rate on UART\n");
return ret;
}
ret = msm_hs_clock_vote(msm_uport);
if (ret) {
- printk(KERN_ERR "Error could not turn on UART clk\n");
+ MSM_HS_ERR("Error could not turn on UART clk\n");
return ret;
}
@@ -728,14 +810,14 @@
/* Establish connection between peripheral and memory endpoint */
ret = sps_connect(sps_pipe_handle, sps_config);
if (ret) {
- pr_err("msm_serial_hs: sps_connect() failed for tx!!\n"
+ MSM_HS_ERR("msm_serial_hs: sps_connect() failed for tx!!\n"
"pipe_handle=0x%x ret=%d", (u32)sps_pipe_handle, ret);
return ret;
}
/* Register callback event for EOT (End of transfer) event. */
ret = sps_register_event(sps_pipe_handle, sps_event);
if (ret) {
- pr_err("msm_serial_hs: sps_connect() failed for tx!!\n"
+ MSM_HS_ERR("msm_serial_hs: sps_connect() failed for tx!!\n"
"pipe_handle=0x%x ret=%d", (u32)sps_pipe_handle, ret);
goto reg_event_err;
}
@@ -769,14 +851,14 @@
/* Establish connection between peripheral and memory endpoint */
ret = sps_connect(sps_pipe_handle, sps_config);
if (ret) {
- pr_err("msm_serial_hs: sps_connect() failed for rx!!\n"
+ MSM_HS_ERR("msm_serial_hs: sps_connect() failed for rx!!\n"
"pipe_handle=0x%x ret=%d", (u32)sps_pipe_handle, ret);
return ret;
}
/* Register callback event for DESC_DONE event. */
ret = sps_register_event(sps_pipe_handle, sps_event);
if (ret) {
- pr_err("msm_serial_hs: sps_connect() failed for rx!!\n"
+ MSM_HS_ERR("msm_serial_hs: sps_connect() failed for rx!!\n"
"pipe_handle=0x%x ret=%d", (u32)sps_pipe_handle, ret);
goto reg_event_err;
}
@@ -909,7 +991,7 @@
}
if (clk_set_rate(msm_uport->clk, uport->uartclk)) {
- printk(KERN_WARNING "Error setting clock rate on UART\n");
+ MSM_HS_WARN("Error setting clock rate on UART\n");
WARN_ON(1);
}
@@ -998,6 +1080,9 @@
mutex_lock(&msm_uport->clk_mutex);
msm_hs_write(uport, UART_DM_IMR, 0);
+ MSM_HS_DBG("Entering %s\n", __func__);
+ dump_uart_hs_registers(msm_uport);
+
/* Clear the Rx Ready Ctl bit - This ensures that
* flow control lines stop the other side from sending
* data while we change the parameters
@@ -1108,7 +1193,7 @@
RX_FLUSH_COMPLETE_TIMEOUT);
ret = sps_disconnect(sps_pipe_handle);
if (ret)
- pr_err("%s(): sps_disconnect failed\n",
+ MSM_HS_ERR("%s(): sps_disconnect failed\n",
__func__);
msm_hs_spsconnect_rx(uport);
msm_serial_hs_rx_tlet((unsigned long) &rx->tlet);
@@ -1116,13 +1201,13 @@
msm_uport->rx_discard_flush_issued = true;
/* do discard flush */
msm_dmov_flush(msm_uport->dma_rx_channel, 0);
- pr_debug("%s(): wainting for flush completion.\n",
+ MSM_HS_DBG("%s(): wainting for flush completion.\n",
__func__);
ret = wait_event_timeout(msm_uport->rx.wait,
msm_uport->rx_discard_flush_issued == false,
RX_FLUSH_COMPLETE_TIMEOUT);
if (!ret)
- pr_err("%s(): Discard flush pending.\n",
+ MSM_HS_ERR("%s(): Discard flush pending.\n",
__func__);
}
}
@@ -1144,6 +1229,8 @@
msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg);
mb();
mutex_unlock(&msm_uport->clk_mutex);
+ MSM_HS_DBG("Exit %s\n", __func__);
+ dump_uart_hs_registers(msm_uport);
}
/*
@@ -1157,7 +1244,7 @@
struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);
msm_hs_clock_vote(msm_uport);
- data = msm_hs_read(uport, UARTDM_SR_ADDR);
+ data = msm_hs_read(uport, UART_DM_SR);
msm_hs_clock_unvote(msm_uport);
if (data & UARTDM_SR_TXEMT_BMSK)
@@ -1190,7 +1277,7 @@
ret = sps_disconnect(sps_pipe_handle);
if (ret)
- pr_err("%s(): sps_disconnect failed\n", __func__);
+ MSM_HS_ERR("%s(): sps_disconnect failed\n", __func__);
wake_lock_timeout(&msm_uport->rx.wake_lock, HZ / 2);
msm_uport->rx.flush = FLUSH_SHUTDOWN;
@@ -1268,7 +1355,8 @@
if (tx_count > left)
tx_count = left;
-
+ MSM_HS_DBG("%s(): [UART_TX]<%d>\n", __func__, tx_count);
+ hex_dump_ipc("HSUART write: ", &tx_buf->buf[tx_buf->tail], tx_count);
src_addr = tx->dma_base + tx_buf->tail;
/* Mask the src_addr to align on a cache
* and add those bytes to tx_count */
@@ -1316,7 +1404,10 @@
sizeof(u32), DMA_TO_DEVICE);
msm_dmov_enqueue_cmd(msm_uport->dma_tx_channel, &tx->xfer);
+
}
+ MSM_HS_DBG("%s:Enqueue Tx Cmd\n", __func__);
+ dump_uart_hs_registers(msm_uport);
}
/* Start to receive the next chunk of data */
@@ -1331,7 +1422,7 @@
msm_uport->rx.buffer_pending = 0;
if (buffer_pending && hs_serial_debug_mask)
- printk(KERN_ERR "Error: rx started in buffer state = %x",
+ MSM_HS_ERR("Error: rx started in buffer state = %x",
buffer_pending);
msm_hs_write(uport, UART_DM_CR, RESET_STALE_INT);
@@ -1383,6 +1474,8 @@
msm_dmov_enqueue_cmd(msm_uport->dma_rx_channel,
&msm_uport->rx.xfer);
}
+ MSM_HS_DBG("%s:Enqueue Rx Cmd\n", __func__);
+ dump_uart_hs_registers(msm_uport);
}
static void flip_insert_work(struct work_struct *work)
@@ -1397,7 +1490,7 @@
spin_lock_irqsave(&msm_uport->uport.lock, flags);
if (msm_uport->rx.buffer_pending == NONE_PENDING) {
if (hs_serial_debug_mask)
- printk(KERN_ERR "Error: No buffer pending in %s",
+ MSM_HS_ERR("Error: No buffer pending in %s",
__func__);
return;
}
@@ -1429,11 +1522,7 @@
else
if ((msm_uport->clk_state == MSM_HS_CLK_ON) &&
(msm_uport->rx.flush <= FLUSH_IGNORE)) {
- if (hs_serial_debug_mask)
- printk(KERN_WARNING
- "msm_serial_hs: "
- "Pending buffers cleared. "
- "Restarting\n");
+ MSM_HS_WARN("Pending buffers cleared,restarting\n");
msm_hs_start_rx_locked(&msm_uport->uport);
}
spin_unlock_irqrestore(&msm_uport->uport.lock, flags);
@@ -1470,6 +1559,9 @@
if (!is_blsp_uart(msm_uport))
msm_hs_write(uport, UART_DM_CR, STALE_EVENT_DISABLE);
+ MSM_HS_DBG("In %s\n", __func__);
+ dump_uart_hs_registers(msm_uport);
+
/* overflow is not connect to data in a FIFO */
if (unlikely((status & UARTDM_SR_OVERRUN_BMSK) &&
(uport->read_status_mask & CREAD))) {
@@ -1486,7 +1578,7 @@
if (unlikely(status & UARTDM_SR_PAR_FRAME_BMSK)) {
/* Can not tell difference between parity & frame error */
if (hs_serial_debug_mask)
- printk(KERN_WARNING "msm_serial_hs: parity error\n");
+ MSM_HS_WARN("msm_serial_hs: parity error\n");
uport->icount.parity++;
error_f = 1;
if (!(uport->ignore_status_mask & IGNPAR)) {
@@ -1498,7 +1590,7 @@
if (unlikely(status & UARTDM_SR_RX_BREAK_BMSK)) {
if (hs_serial_debug_mask)
- printk(KERN_WARNING "msm_serial_hs: Rx break\n");
+ MSM_HS_WARN("msm_serial_hs: Rx break\n");
uport->icount.brk++;
error_f = 1;
if (!(uport->ignore_status_mask & IGNBRK)) {
@@ -1533,15 +1625,20 @@
rmb();
}
+ MSM_HS_DBG("%s():[UART_RX]<%d>\n", __func__, rx_count);
+ hex_dump_ipc("HSUART Read: ", msm_uport->rx.buffer, rx_count);
if (0 != (uport->read_status_mask & CREAD)) {
retval = tty_insert_flip_string(tty, msm_uport->rx.buffer,
rx_count);
if (retval != rx_count) {
+ MSM_HS_DBG("%s(): retval %d rx_count %d", __func__,
+ retval, rx_count);
msm_uport->rx.buffer_pending |= CHARS_NORMAL |
retval << 5 | (rx_count - retval) << 16;
}
}
+ MSM_HS_DBG("%s() read rx buffer complete", __func__);
/* order the read of rx.buffer and the start of next rx xfer */
wmb();
@@ -1561,11 +1658,7 @@
}
out:
if (msm_uport->rx.buffer_pending) {
- if (hs_serial_debug_mask)
- printk(KERN_WARNING
- "msm_serial_hs: "
- "tty buffer exhausted. "
- "Stalling\n");
+ MSM_HS_WARN("tty buffer exhausted.Stalling\n");
schedule_delayed_work(&msm_uport->rx.flip_insert_work
, msecs_to_jiffies(RETRY_TIMEOUT));
}
@@ -1606,7 +1699,7 @@
((struct sps_event_notify *)notify)->user;
msm_uport->notify = *notify;
- pr_debug("%s: sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
+ MSM_HS_DBG("%s: sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
__func__, notify->event_id,
notify->data.transfer.iovec.addr,
notify->data.transfer.iovec.size,
@@ -1659,6 +1752,8 @@
mb();
spin_unlock_irqrestore(&(msm_uport->uport.lock), flags);
+ MSM_HS_DBG("In %s()\n", __func__);
+ dump_uart_hs_registers(msm_uport);
}
/**
@@ -1681,7 +1776,7 @@
uport = &(msm_uport->uport);
msm_uport->notify = *notify;
- pr_debug("%s: sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
+ MSM_HS_DBG("%s: sps ev_id=%d, addr=0x%x, size=0x%x, flags=0x%x\n",
__func__, notify->event_id,
notify->data.transfer.iovec.addr,
notify->data.transfer.iovec.size,
@@ -1713,7 +1808,7 @@
msm_uport = container_of(cmd_ptr, struct msm_hs_port, rx.xfer);
uport = &(msm_uport->uport);
- pr_debug("%s(): called result:%x\n", __func__, result);
+ MSM_HS_DBG("%s(): called result:%x\n", __func__, result);
if (!(result & DMOV_RSLT_ERROR)) {
if (result & DMOV_RSLT_FLUSH) {
if (msm_uport->rx_discard_flush_issued) {
@@ -1935,13 +2030,13 @@
spin_unlock_irqrestore(&uport->lock, flags);
if (msm_uport->rx_discard_flush_issued) {
- pr_debug("%s(): wainting for flush completion.\n",
+ MSM_HS_DBG("%s(): wainting for flush completion.\n",
__func__);
ret = wait_event_timeout(msm_uport->rx.wait,
msm_uport->rx_discard_flush_issued == false,
RX_FLUSH_COMPLETE_TIMEOUT);
if (!ret)
- pr_err("%s(): Flush complete pending.\n",
+ MSM_HS_ERR("%s(): Flush complete pending.\n",
__func__);
}
@@ -2005,10 +2100,13 @@
spin_lock_irqsave(&uport->lock, flags);
isr_status = msm_hs_read(uport, UART_DM_MISR);
+ MSM_HS_DBG("%s:UART_DM_MISR %lx", __func__, isr_status);
+ dump_uart_hs_registers(msm_uport);
/* Uart RX starting */
if (isr_status & UARTDM_ISR_RXLEV_BMSK) {
wake_lock(&rx->wake_lock); /* hold wakelock while rx dma */
+ MSM_HS_DBG("%s:UARTDM_ISR_RXLEV_BMSK\n", __func__);
msm_uport->imr_reg &= ~UARTDM_ISR_RXLEV_BMSK;
msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg);
/* Complete device write for IMR. Hence mb() requires. */
@@ -2023,6 +2121,7 @@
* mb() requires here.
*/
mb();
+ MSM_HS_DBG("%s:Stal Interrupt\n", __func__);
if (msm_uport->clk_req_off_state ==
CLK_REQ_OFF_RXSTALE_ISSUED)
@@ -2036,6 +2135,7 @@
}
/* tx ready interrupt */
if (isr_status & UARTDM_ISR_TX_READY_BMSK) {
+ MSM_HS_DBG("%s: ISR_TX_READY Interrupt\n", __func__);
/* Clear TX Ready */
msm_hs_write(uport, UART_DM_CR, CLEAR_TX_READY);
@@ -2114,7 +2214,7 @@
msm_uport->clk_state = MSM_HS_CLK_REQUEST_OFF;
msm_uport->clk_req_off_state = CLK_REQ_OFF_START;
msm_uport->imr_reg |= UARTDM_ISR_TXLEV_BMSK;
- msm_hs_write(uport, UARTDM_IMR, msm_uport->imr_reg);
+ msm_hs_write(uport, UART_DM_IMR, msm_uport->imr_reg);
/*
* Complete device write before retuning back.
* Hence mb() requires here.
@@ -2252,7 +2352,7 @@
if (gpio_is_valid(pdata->uart_rfr_gpio))
gpio_free(pdata->uart_rfr_gpio);
} else {
- pr_err("Error:Pdata is NULL.\n");
+ MSM_HS_ERR("Error:Pdata is NULL.\n");
}
}
@@ -2272,7 +2372,7 @@
ret = gpio_request(pdata->uart_tx_gpio,
"UART_TX_GPIO");
if (unlikely(ret)) {
- pr_err("gpio request failed for:%d\n",
+ MSM_HS_ERR("gpio request failed for:%d\n",
pdata->uart_tx_gpio);
goto exit_uart_config;
}
@@ -2282,7 +2382,7 @@
ret = gpio_request(pdata->uart_rx_gpio,
"UART_RX_GPIO");
if (unlikely(ret)) {
- pr_err("gpio request failed for:%d\n",
+ MSM_HS_ERR("gpio request failed for:%d\n",
pdata->uart_rx_gpio);
goto uart_tx_unconfig;
}
@@ -2292,7 +2392,7 @@
ret = gpio_request(pdata->uart_cts_gpio,
"UART_CTS_GPIO");
if (unlikely(ret)) {
- pr_err("gpio request failed for:%d\n",
+ MSM_HS_ERR("gpio request failed for:%d\n",
pdata->uart_cts_gpio);
goto uart_rx_unconfig;
}
@@ -2302,13 +2402,13 @@
ret = gpio_request(pdata->uart_rfr_gpio,
"UART_RFR_GPIO");
if (unlikely(ret)) {
- pr_err("gpio request failed for:%d\n",
+ MSM_HS_ERR("gpio request failed for:%d\n",
pdata->uart_rfr_gpio);
goto uart_cts_unconfig;
}
}
} else {
- pr_err("Pdata is NULL.\n");
+ MSM_HS_ERR("Pdata is NULL.\n");
ret = -EINVAL;
}
return ret;
@@ -2354,7 +2454,7 @@
/* turn on uart clk */
ret = msm_hs_init_clk(uport);
if (unlikely(ret)) {
- pr_err("Turning ON uartclk error\n");
+ MSM_HS_ERR("Turning ON uartclk error\n");
wake_unlock(&msm_uport->dma_wake_lock);
return ret;
}
@@ -2362,7 +2462,7 @@
if (is_blsp_uart(msm_uport)) {
ret = msm_hs_config_uart_gpios(uport);
if (ret) {
- pr_err("Uart GPIO request failed\n");
+ MSM_HS_ERR("Uart GPIO request failed\n");
goto deinit_uart_clk;
}
} else {
@@ -2376,14 +2476,14 @@
/* SPS connect for TX */
ret = msm_hs_spsconnect_tx(uport);
if (ret) {
- pr_err("msm_serial_hs: SPS connect failed for TX");
+ MSM_HS_ERR("msm_serial_hs: SPS connect failed for TX");
goto unconfig_uart_gpios;
}
/* SPS connect for RX */
ret = msm_hs_spsconnect_rx(uport);
if (ret) {
- pr_err("msm_serial_hs: SPS connect failed for RX");
+ MSM_HS_ERR("msm_serial_hs: SPS connect failed for RX");
goto sps_disconnect_tx;
}
}
@@ -2461,7 +2561,7 @@
if (use_low_power_wakeup(msm_uport)) {
ret = irq_set_irq_wake(msm_uport->wakeup.irq, 1);
if (unlikely(ret)) {
- pr_err("%s():Err setting wakeup irq\n", __func__);
+ MSM_HS_ERR("%s():Err setting wakeup irq\n", __func__);
goto sps_disconnect_rx;
}
}
@@ -2469,7 +2569,7 @@
ret = request_irq(uport->irq, msm_hs_isr, IRQF_TRIGGER_HIGH,
"msm_hs_uart", msm_uport);
if (unlikely(ret)) {
- pr_err("%s():Error getting uart irq\n", __func__);
+ MSM_HS_ERR("%s():Error getting uart irq\n", __func__);
goto free_wake_irq;
}
if (use_low_power_wakeup(msm_uport)) {
@@ -2480,7 +2580,7 @@
"msm_hs_wakeup", msm_uport);
if (unlikely(ret)) {
- pr_err("%s():Err getting uart wakeup_irq\n", __func__);
+ MSM_HS_ERR("%s():Err getting uart wakeup_irq\n", __func__);
goto free_uart_irq;
}
disable_irq(msm_uport->wakeup.irq);
@@ -2543,14 +2643,14 @@
rx->pool = dma_pool_create("rx_buffer_pool", uport->dev,
UARTDM_RX_BUF_SIZE, 16, 0);
if (!rx->pool) {
- pr_err("%s(): cannot allocate rx_buffer_pool", __func__);
+ MSM_HS_ERR("%s(): cannot allocate rx_buffer_pool", __func__);
ret = -ENOMEM;
goto exit_tasket_init;
}
rx->buffer = dma_pool_alloc(rx->pool, GFP_KERNEL, &rx->rbuffer);
if (!rx->buffer) {
- pr_err("%s(): cannot allocate rx->buffer", __func__);
+ MSM_HS_ERR("%s(): cannot allocate rx->buffer", __func__);
ret = -ENOMEM;
goto free_pool;
}
@@ -2589,14 +2689,15 @@
/* Allocate the command pointer. Needs to be 64 bit aligned */
rx->command_ptr = kmalloc(sizeof(dmov_box), GFP_KERNEL | __GFP_DMA);
if (!rx->command_ptr) {
- pr_err("%s(): cannot allocate rx->command_ptr", __func__);
+ MSM_HS_ERR("%s(): cannot allocate rx->command_ptr", __func__);
ret = -ENOMEM;
goto free_tx_command_ptr_ptr;
}
rx->command_ptr_ptr = kmalloc(sizeof(u32), GFP_KERNEL | __GFP_DMA);
if (!rx->command_ptr_ptr) {
- pr_err("%s(): cannot allocate rx->command_ptr_ptr", __func__);
+ MSM_HS_ERR("%s(): cannot allocate rx->command_ptr_ptr",
+ __func__);
ret = -ENOMEM;
goto free_rx_command_ptr;
}
@@ -2664,7 +2765,7 @@
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
- pr_err("unable to allocate memory for platform data\n");
+ MSM_HS_ERR("unable to allocate memory for platform data\n");
return ERR_PTR(-ENOMEM);
}
@@ -2672,25 +2773,25 @@
pdata->uart_tx_gpio = of_get_named_gpio(node,
"qcom,tx-gpio", 0);
if (pdata->uart_tx_gpio < 0)
- pr_debug("uart_tx_gpio is not available\n");
+ MSM_HS_DBG("uart_tx_gpio is not available\n");
/* UART RX GPIO */
pdata->uart_rx_gpio = of_get_named_gpio(node,
"qcom,rx-gpio", 0);
if (pdata->uart_rx_gpio < 0)
- pr_debug("uart_rx_gpio is not available\n");
+ MSM_HS_DBG("uart_rx_gpio is not available\n");
/* UART CTS GPIO */
pdata->uart_cts_gpio = of_get_named_gpio(node,
"qcom,cts-gpio", 0);
if (pdata->uart_cts_gpio < 0)
- pr_debug("uart_cts_gpio is not available\n");
+ MSM_HS_DBG("uart_cts_gpio is not available\n");
/* UART RFR GPIO */
pdata->uart_rfr_gpio = of_get_named_gpio(node,
"qcom,rfr-gpio", 0);
if (pdata->uart_rfr_gpio < 0)
- pr_debug("uart_rfr_gpio is not available\n");
+ MSM_HS_DBG("uart_rfr_gpio is not available\n");
pdata->inject_rx_on_wakeup = of_property_read_bool(node,
"qcom,inject-rx-on-wakeup");
@@ -2699,7 +2800,7 @@
ret = of_property_read_u32(node, "qcom,rx-char-to-inject",
&rx_to_inject);
if (ret < 0) {
- pr_err("Error: Rx_char_to_inject not specified.\n");
+ MSM_HS_ERR("Error: Rx_char_to_inject not specified.\n");
return ERR_PTR(ret);
}
pdata->rx_to_inject = (char)rx_to_inject;
@@ -2708,30 +2809,30 @@
ret = of_property_read_u32(node, "qcom,bam-tx-ep-pipe-index",
&pdata->bam_tx_ep_pipe_index);
if (ret < 0) {
- pr_err("Error: Getting UART BAM TX EP Pipe Index.\n");
+ MSM_HS_ERR("Error: Getting UART BAM TX EP Pipe Index.\n");
return ERR_PTR(ret);
}
if (!(pdata->bam_tx_ep_pipe_index >= BAM_PIPE_MIN &&
pdata->bam_tx_ep_pipe_index <= BAM_PIPE_MAX)) {
- pr_err("Error: Invalid UART BAM TX EP Pipe Index.\n");
+ MSM_HS_ERR("Error: Invalid UART BAM TX EP Pipe Index.\n");
return ERR_PTR(-EINVAL);
}
ret = of_property_read_u32(node, "qcom,bam-rx-ep-pipe-index",
&pdata->bam_rx_ep_pipe_index);
if (ret < 0) {
- pr_err("Error: Getting UART BAM RX EP Pipe Index.\n");
+ MSM_HS_ERR("Error: Getting UART BAM RX EP Pipe Index.\n");
return ERR_PTR(ret);
}
if (!(pdata->bam_rx_ep_pipe_index >= BAM_PIPE_MIN &&
pdata->bam_rx_ep_pipe_index <= BAM_PIPE_MAX)) {
- pr_err("Error: Invalid UART BAM RX EP Pipe Index.\n");
+ MSM_HS_ERR("Error: Invalid UART BAM RX EP Pipe Index.\n");
return ERR_PTR(-EINVAL);
}
- pr_debug("tx_ep_pipe_index:%d rx_ep_pipe_index:%d\n"
+ MSM_HS_DBG("tx_ep_pipe_index:%d rx_ep_pipe_index:%d\n"
"tx_gpio:%d rx_gpio:%d rfr_gpio:%d cts_gpio:%d",
pdata->bam_tx_ep_pipe_index, pdata->bam_rx_ep_pipe_index,
pdata->uart_tx_gpio, pdata->uart_rx_gpio, pdata->uart_cts_gpio,
@@ -2787,7 +2888,7 @@
/* Allocate endpoint context */
sps_pipe_handle = sps_alloc_endpoint();
if (!sps_pipe_handle) {
- pr_err("msm_serial_hs: sps_alloc_endpoint() failed!!\n"
+ MSM_HS_ERR("msm_serial_hs: sps_alloc_endpoint() failed!!\n"
"is_producer=%d", is_producer);
rc = -ENOMEM;
goto out;
@@ -2796,7 +2897,7 @@
/* Get default connection configuration for an endpoint */
rc = sps_get_config(sps_pipe_handle, sps_config);
if (rc) {
- pr_err("msm_serial_hs: sps_get_config() failed!!\n"
+ MSM_HS_ERR("msm_serial_hs: sps_get_config() failed!!\n"
"pipe_handle=0x%x rc=%d", (u32)sps_pipe_handle, rc);
goto get_config_err;
}
@@ -2832,7 +2933,7 @@
GFP_KERNEL);
if (!sps_config->desc.base) {
rc = -ENOMEM;
- pr_err("msm_serial_hs: dma_alloc_coherent() failed!!\n");
+ MSM_HS_ERR("msm_serial_hs: dma_alloc_coherent() failed!!\n");
goto get_config_err;
}
memset(sps_config->desc.base, 0x00, sps_config->desc.size);
@@ -2851,7 +2952,7 @@
/* Now save the sps pipe handle */
ep->pipe_handle = sps_pipe_handle;
- pr_debug("msm_serial_hs: success !! %s: pipe_handle=0x%x\n"
+ MSM_HS_DBG("msm_serial_hs: success !! %s: pipe_handle=0x%x\n"
"desc_fifo.phys_base=0x%llx\n",
is_producer ? "READ" : "WRITE",
(u32) sps_pipe_handle, (u64) sps_config->desc.phys_base);
@@ -2895,18 +2996,18 @@
bam.irq = (u32)msm_uport->bam_irq;
bam.manage = SPS_BAM_MGR_DEVICE_REMOTE;
- pr_debug("msm_serial_hs: bam physical base=0x%x\n",
+ MSM_HS_DBG("msm_serial_hs: bam physical base=0x%x\n",
(u32)bam.phys_addr);
- pr_debug("msm_serial_hs: bam virtual base=0x%x\n",
+ MSM_HS_DBG("msm_serial_hs: bam virtual base=0x%x\n",
(u32)bam.virt_addr);
/* Register UART Peripheral BAM device to SPS driver */
rc = sps_register_bam_device(&bam, &bam_handle);
if (rc) {
- pr_err("msm_serial_hs: BAM device register failed\n");
+ MSM_HS_ERR("msm_serial_hs: BAM device register failed\n");
return rc;
}
- pr_info("msm_serial_hs: BAM device registered. bam_handle=0x%x",
+ MSM_HS_INFO("msm_serial_hs: BAM device registered. bam_handle=0x%x",
msm_uport->bam_handle);
}
msm_uport->bam_handle = bam_handle;
@@ -2914,14 +3015,14 @@
rc = msm_hs_sps_init_ep_conn(msm_uport, &msm_uport->rx.prod,
UART_SPS_PROD_PERIPHERAL);
if (rc) {
- pr_err("%s: Failed to Init Producer BAM-pipe", __func__);
+ MSM_HS_ERR("%s: Failed to Init Producer BAM-pipe", __func__);
goto deregister_bam;
}
rc = msm_hs_sps_init_ep_conn(msm_uport, &msm_uport->tx.cons,
UART_SPS_CONS_PERIPHERAL);
if (rc) {
- pr_err("%s: Failed to Init Consumer BAM-pipe", __func__);
+ MSM_HS_ERR("%s: Failed to Init Consumer BAM-pipe", __func__);
goto deinit_ep_conn_prod;
}
return 0;
@@ -2973,7 +3074,7 @@
if (deviceid[alias_num] == 0) {
pdev->id = alias_num;
} else {
- pr_err("alias_num=%d already used\n",
+ MSM_HS_ERR("alias_num=%d already used\n",
alias_num);
return -EINVAL;
}
@@ -2986,7 +3087,7 @@
}
if (pdev->id < 0 || pdev->id >= UARTDM_NR) {
- pr_err("Invalid plaform device ID = %d\n", pdev->id);
+ MSM_HS_ERR("Invalid plaform device ID = %d\n", pdev->id);
return -EINVAL;
}
@@ -3014,39 +3115,39 @@
wakeup_irqres = platform_get_irq_byname(pdev, "wakeup_irq");
if (!core_resource) {
- pr_err("Invalid core HSUART Resources.\n");
+ MSM_HS_ERR("Invalid core HSUART Resources.\n");
return -ENXIO;
}
if (!bam_resource) {
- pr_err("Invalid BAM HSUART Resources.\n");
+ MSM_HS_ERR("Invalid BAM HSUART Resources.\n");
return -ENXIO;
}
if (!core_irqres) {
- pr_err("Invalid core irqres Resources.\n");
+ MSM_HS_ERR("Invalid core irqres Resources.\n");
return -ENXIO;
}
if (!bam_irqres) {
- pr_err("Invalid bam irqres Resources.\n");
+ MSM_HS_ERR("Invalid bam irqres Resources.\n");
return -ENXIO;
}
if (!wakeup_irqres)
- pr_debug("Wakeup irq not specified.\n");
+ MSM_HS_DBG("Wakeup irq not specified.\n");
uport->mapbase = core_resource->start;
uport->membase = ioremap(uport->mapbase,
resource_size(core_resource));
if (unlikely(!uport->membase)) {
- pr_err("UART Resource ioremap Failed.\n");
+ MSM_HS_ERR("UART Resource ioremap Failed.\n");
return -ENOMEM;
}
msm_uport->bam_mem = bam_resource->start;
msm_uport->bam_base = ioremap(msm_uport->bam_mem,
resource_size(bam_resource));
if (unlikely(!msm_uport->bam_base)) {
- pr_err("UART BAM Resource ioremap Failed.\n");
+ MSM_HS_ERR("UART BAM Resource ioremap Failed.\n");
iounmap(uport->membase);
return -ENOMEM;
}
@@ -3057,13 +3158,13 @@
msm_uport->bus_scale_table = msm_bus_cl_get_pdata(pdev);
if (!msm_uport->bus_scale_table) {
- pr_err("BLSP UART: Bus scaling is disabled.\n");
+ MSM_HS_ERR("BLSP UART: Bus scaling is disabled.\n");
} else {
msm_uport->bus_perf_client =
msm_bus_scale_register_client
(msm_uport->bus_scale_table);
if (IS_ERR(&msm_uport->bus_perf_client)) {
- pr_err("%s(): Bus client register failed.\n",
+ MSM_HS_ERR("%s(): Bus client register failed.\n",
__func__);
ret = -EINVAL;
goto unmap_memory;
@@ -3082,7 +3183,7 @@
uport->irq = platform_get_irq(pdev, 0);
if (unlikely((int)uport->irq < 0)) {
- pr_err("UART IRQ Failed.\n");
+ MSM_HS_ERR("UART IRQ Failed.\n");
iounmap(uport->membase);
return -ENXIO;
}
@@ -3155,14 +3256,14 @@
ret = clk_set_rate(msm_uport->clk, uport->uartclk);
if (ret) {
- printk(KERN_WARNING "Error setting clock rate on UART\n");
+ MSM_HS_WARN("Error setting clock rate on UART\n");
goto put_clk;
}
msm_uport->hsuart_wq = alloc_workqueue("k_hsuart",
WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
if (!msm_uport->hsuart_wq) {
- pr_err("%s(): Unable to create workqueue hsuart_wq\n",
+ MSM_HS_ERR("%s(): Unable to create workqueue hsuart_wq\n",
__func__);
ret = -ENOMEM;
goto put_clk;
@@ -3181,7 +3282,7 @@
if (is_blsp_uart(msm_uport)) {
ret = msm_hs_sps_init(msm_uport);
if (unlikely(ret)) {
- pr_err("SPS Initialization failed ! err=%d", ret);
+ MSM_HS_ERR("SPS Initialization failed ! err=%d", ret);
goto destroy_mutex;
}
}
@@ -3254,28 +3355,33 @@
int ret;
int i;
+ ipc_msm_hs_log_ctxt = ipc_log_context_create(IPC_MSM_HS_LOG_PAGES,
+ "msm_serial_hs");
+ if (!ipc_msm_hs_log_ctxt)
+ MSM_HS_WARN("%s: error creating logging context", __func__);
+
/* Init all UARTS as non-configured */
for (i = 0; i < UARTDM_NR; i++)
q_uart_port[i].uport.type = PORT_UNKNOWN;
ret = uart_register_driver(&msm_hs_driver);
if (unlikely(ret)) {
- printk(KERN_ERR "%s failed to load\n", __FUNCTION__);
+ MSM_HS_WARN("%s failed to load\n", __func__);
return ret;
}
debug_base = debugfs_create_dir("msm_serial_hs", NULL);
if (IS_ERR_OR_NULL(debug_base))
- pr_info("msm_serial_hs: Cannot create debugfs dir\n");
+ MSM_HS_INFO("msm_serial_hs: Cannot create debugfs dir\n");
ret = platform_driver_register(&msm_serial_hs_platform_driver);
if (ret) {
- printk(KERN_ERR "%s failed to load\n", __FUNCTION__);
+ MSM_HS_ERR("%s failed to load\n", __FUNCTION__);
debugfs_remove_recursive(debug_base);
uart_unregister_driver(&msm_hs_driver);
return ret;
}
- printk(KERN_INFO "msm_serial_hs module loaded\n");
+ MSM_HS_INFO("msm_serial_hs module loaded\n");
return ret;
}
@@ -3318,12 +3424,12 @@
ret = wait_event_timeout(msm_uport->tx.wait,
msm_uport->tx.flush == FLUSH_SHUTDOWN, 100);
if (!ret)
- pr_err("%s():HSUART TX Stalls.\n", __func__);
+ MSM_HS_ERR("%s():HSUART TX Stalls.\n", __func__);
} else {
/* BAM Disconnect for TX */
ret = sps_disconnect(sps_pipe_handle);
if (ret)
- pr_err("%s(): sps_disconnect failed\n",
+ MSM_HS_ERR("%s(): sps_disconnect failed\n",
__func__);
}
}
@@ -3378,7 +3484,7 @@
static void __exit msm_serial_hs_exit(void)
{
- printk(KERN_INFO "msm_serial_hs module removed\n");
+ MSM_HS_INFO("msm_serial_hs module removed\n");
debugfs_remove_recursive(debug_base);
platform_driver_unregister(&msm_serial_hs_platform_driver);
uart_unregister_driver(&msm_hs_driver);
diff --git a/drivers/usb/misc/diag_bridge.c b/drivers/usb/misc/diag_bridge.c
index 22e2a25..ccd48ca 100644
--- a/drivers/usb/misc/diag_bridge.c
+++ b/drivers/usb/misc/diag_bridge.c
@@ -464,12 +464,7 @@
pr_err("unable to allocate dev");
return -ENOMEM;
}
- dev->pdev = platform_device_alloc("diag_bridge", devid);
- if (!dev->pdev) {
- pr_err("unable to allocate platform device");
- kfree(dev);
- return -ENOMEM;
- }
+
__dev[devid] = dev;
dev->id = devid;
@@ -498,7 +493,13 @@
usb_set_intfdata(ifc, dev);
diag_bridge_debugfs_init();
- platform_device_add(dev->pdev);
+ dev->pdev = platform_device_register_simple("diag_bridge", devid,
+ NULL, 0);
+ if (IS_ERR(dev->pdev)) {
+ pr_err("unable to allocate platform device");
+ ret = PTR_ERR(dev->pdev);
+ goto error;
+ }
dev_dbg(&dev->ifc->dev, "%s: complete\n", __func__);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 45fbfa8..8287ad7 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -629,6 +629,10 @@
pm8xxx_usb_id_pullup(1);
}
+ if (motg->caps & ALLOW_VDD_MIN_WITH_RETENTION_DISABLED)
+ writel_relaxed(readl_relaxed(USB_OTGSC) & ~(OTGSC_IDPU),
+ USB_OTGSC);
+
return 0;
}
@@ -889,6 +893,7 @@
u32 phy_ctrl_val = 0, cmd_val;
unsigned ret;
u32 portsc, config2;
+ u32 func_ctrl;
if (atomic_read(&motg->in_lpm))
return 0;
@@ -956,6 +961,15 @@
ulpi_write(phy, 0x08, 0x09);
}
+ if (motg->caps & ALLOW_VDD_MIN_WITH_RETENTION_DISABLED) {
+ /* put the controller in non-driving mode */
+ func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
+ func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+ func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
+ ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL);
+ ulpi_write(phy, ULPI_IFC_CTRL_AUTORESUME,
+ ULPI_CLR(ULPI_IFC_CTRL));
+ }
/* Set the PHCD bit, only if it is not set by the controller.
* PHY may take some time or even fail to enter into low power
@@ -1021,8 +1035,13 @@
}
if (host_bus_suspend)
phy_ctrl_val |= PHY_CLAMP_DPDMSE_EN;
- writel_relaxed(phy_ctrl_val & ~PHY_RETEN, USB_PHY_CTRL);
- motg->lpm_flags |= PHY_RETENTIONED;
+
+ if (!(motg->caps & ALLOW_VDD_MIN_WITH_RETENTION_DISABLED)) {
+ writel_relaxed(phy_ctrl_val & ~PHY_RETEN, USB_PHY_CTRL);
+ motg->lpm_flags |= PHY_RETENTIONED;
+ } else {
+ writel_relaxed(phy_ctrl_val, USB_PHY_CTRL);
+ }
}
/* Ensure that above operation is completed before turning off clocks */
@@ -1063,7 +1082,8 @@
motg->lpm_flags |= PHY_REGULATORS_LPM;
}
- if (motg->lpm_flags & PHY_RETENTIONED) {
+ if (motg->lpm_flags & PHY_RETENTIONED ||
+ (motg->caps & ALLOW_VDD_MIN_WITH_RETENTION_DISABLED)) {
msm_hsusb_config_vddcx(0);
msm_hsusb_mhl_switch_enable(motg, 0);
}
@@ -1116,6 +1136,7 @@
unsigned temp;
u32 phy_ctrl_val = 0;
unsigned ret;
+ u32 func_ctrl;
if (!atomic_read(&motg->in_lpm))
return 0;
@@ -1159,7 +1180,8 @@
motg->lpm_flags &= ~PHY_REGULATORS_LPM;
}
- if (motg->lpm_flags & PHY_RETENTIONED) {
+ if (motg->lpm_flags & PHY_RETENTIONED ||
+ (motg->caps & ALLOW_VDD_MIN_WITH_RETENTION_DISABLED)) {
msm_hsusb_mhl_switch_enable(motg, 1);
msm_hsusb_config_vddcx(1);
phy_ctrl_val = readl_relaxed(USB_PHY_CTRL);
@@ -1205,6 +1227,14 @@
}
skip_phy_resume:
+ if (motg->caps & ALLOW_VDD_MIN_WITH_RETENTION_DISABLED) {
+ /* put the controller in normal mode */
+ func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
+ func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+ func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
+ ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL);
+ }
+
if (device_may_wakeup(phy->dev)) {
if (motg->async_irq)
disable_irq_wake(motg->async_irq);
@@ -4183,6 +4213,8 @@
"qcom,hsusb-l1-supported");
pdata->enable_ahb2ahb_bypass = of_property_read_bool(node,
"qcom,ahb-async-bridge-bypass");
+ pdata->disable_retention_with_vdd_min = of_property_read_bool(node,
+ "qcom,disable-retention-with-vdd-min");
return pdata;
}
@@ -4568,6 +4600,9 @@
if (motg->pdata->enable_lpm_on_dev_suspend)
motg->caps |= ALLOW_LPM_ON_DEV_SUSPEND;
+ if (motg->pdata->disable_retention_with_vdd_min)
+ motg->caps |= ALLOW_VDD_MIN_WITH_RETENTION_DISABLED;
+
wake_lock(&motg->wlock);
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
diff --git a/drivers/video/fbcmap.c b/drivers/video/fbcmap.c
index 31e93a5..f26570d 100644
--- a/drivers/video/fbcmap.c
+++ b/drivers/video/fbcmap.c
@@ -203,11 +203,13 @@
fromoff = to->start - from->start;
else
tooff = from->start - to->start;
+ if ((to->len <= tooff) || (from->len <= fromoff))
+ return -EINVAL;
+
size = to->len - tooff;
+
if (size > (int) (from->len - fromoff))
size = from->len - fromoff;
- if (size <= 0)
- return -EINVAL;
size *= sizeof(u16);
if (from->red && to->red)
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index 03dbd4d..df7915a 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -837,9 +837,9 @@
pinfo->mode_gpio_state = MODE_GPIO_NOT_VALID;
}
- rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-frame-rate", &tmp);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-framerate", &tmp);
pinfo->mipi.frame_rate = (!rc ? tmp : 60);
- rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-clock-rate", &tmp);
+ rc = of_property_read_u32(np, "qcom,mdss-dsi-panel-clockrate", &tmp);
pinfo->clk_rate = (!rc ? tmp : 0);
data = of_get_property(np, "qcom,mdss-dsi-panel-timings", &len);
if ((!data) || (len != 12)) {
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 81473db..96d8be0 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -1176,9 +1176,12 @@
struct mdss_fb_proc_info *pinfo = NULL, *temp_pinfo = NULL;
int ret = 0;
int pid = current->tgid;
+ bool unknown_pid = true, release_needed = false;
+ struct task_struct *task = current->group_leader;
if (!mfd->ref_cnt) {
- pr_info("try to close unopened fb %d!\n", mfd->index);
+ pr_info("try to close unopened fb %d! from %s\n", mfd->index,
+ task->comm);
return -EINVAL;
}
@@ -1190,12 +1193,15 @@
if (!release_all && (pinfo->pid != pid))
continue;
- pr_debug("found process entry pid=%d ref=%d\n", pinfo->pid,
- pinfo->ref_cnt);
+ unknown_pid = false;
+
+ pr_debug("found process %s pid=%d mfd->ref=%d pinfo->ref=%d\n",
+ task->comm, mfd->ref_cnt, pinfo->pid, pinfo->ref_cnt);
do {
if (mfd->ref_cnt < pinfo->ref_cnt)
- pr_warn("WARN:mfd->ref_cnt < pinfo->ref_cnt\n");
+ pr_warn("WARN:mfd->ref=%d < pinfo->ref=%d\n",
+ mfd->ref_cnt, pinfo->ref_cnt);
else
mfd->ref_cnt--;
@@ -1204,14 +1210,37 @@
} while (release_all && pinfo->ref_cnt);
if (pinfo->ref_cnt == 0) {
- if (mfd->mdp.release_fnc) {
- ret = mfd->mdp.release_fnc(mfd);
- if (ret)
- pr_err("error releasing fb%d pid=%d\n",
- mfd->index, pinfo->pid);
- }
list_del(&pinfo->list);
kfree(pinfo);
+ release_needed = !release_all;
+ }
+
+ if (!release_all)
+ break;
+ }
+
+ if (release_needed) {
+ pr_debug("known process %s pid=%d mfd->ref=%d\n",
+ task->comm, pid, mfd->ref_cnt);
+
+ if (mfd->mdp.release_fnc) {
+ ret = mfd->mdp.release_fnc(mfd, false);
+ if (ret)
+ pr_err("error releasing fb%d pid=%d\n",
+ mfd->index, pid);
+ }
+ } else if (unknown_pid || release_all) {
+ pr_warn("unknown process %s pid=%d mfd->ref=%d\n",
+ task->comm, pid, mfd->ref_cnt);
+
+ if (mfd->ref_cnt)
+ mfd->ref_cnt--;
+
+ if (mfd->mdp.release_fnc) {
+ ret = mfd->mdp.release_fnc(mfd, true);
+ if (ret)
+ pr_err("error fb%d release process %s pid=%d\n",
+ mfd->index, task->comm, pid);
}
}
@@ -1219,8 +1248,8 @@
ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info,
mfd->op_enable);
if (ret) {
- pr_err("can't turn off fb%d! rc=%d\n",
- mfd->index, ret);
+ pr_err("can't turn off fb%d! rc=%d process %s pid=%d\n",
+ mfd->index, ret, task->comm, pid);
return ret;
}
}
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index 8213dbe..80e6581 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -106,7 +106,7 @@
int (*on_fnc)(struct msm_fb_data_type *mfd);
int (*off_fnc)(struct msm_fb_data_type *mfd);
/* called to release resources associated to the process */
- int (*release_fnc)(struct msm_fb_data_type *mfd);
+ int (*release_fnc)(struct msm_fb_data_type *mfd, bool release_all);
int (*kickoff_fnc)(struct msm_fb_data_type *mfd,
struct mdp_display_commit *data);
int (*ioctl_handler)(struct msm_fb_data_type *mfd, u32 cmd, void *arg);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 87b7526..466b8d2 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -1718,8 +1718,6 @@
} else {
msm_dss_enable_clk(power_data->clk_config,
power_data->num_clk, 0);
- msm_dss_clk_set_rate(power_data->clk_config,
- power_data->num_clk);
msm_dss_enable_gpio(power_data->gpio_config,
power_data->num_gpio, 0);
msm_dss_enable_vreg(power_data->vreg_config,
@@ -2473,12 +2471,6 @@
hdmi_tx_powerdown_phy(hdmi_ctrl);
- /*
- * this is needed to avoid pll lock failure due to
- * clk framework's rate caching.
- */
- hdmi_ctrl->pdata.power_data[HDMI_TX_CORE_PM].clk_config[0].rate = 0;
-
hdmi_cec_deconfig(hdmi_ctrl->feature_data[HDMI_TX_FEAT_CEC]);
hdmi_tx_core_off(hdmi_ctrl);
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index cb29be2..1198897 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -1784,6 +1784,11 @@
{
int ret;
+ if (!ctl) {
+ pr_err("invalid ctl\n");
+ return -ENODEV;
+ }
+
ret = mutex_lock_interruptible(&ctl->lock);
if (ret)
return ret;
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index a867240..1bac176 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -565,10 +565,14 @@
if ((pipe->flags & MDP_DEINTERLACE) && !pipe->scale.enable_pxl_ext) {
if (pipe->flags & MDP_SOURCE_ROTATED_90) {
+ pipe->src.x = DIV_ROUND_UP(pipe->src.x, 2);
+ pipe->src.x &= ~1;
pipe->src.w /= 2;
pipe->img_width /= 2;
} else {
pipe->src.h /= 2;
+ pipe->src.y = DIV_ROUND_UP(pipe->src.y, 2);
+ pipe->src.y &= ~1;
}
}
@@ -1158,11 +1162,13 @@
/**
* mdss_mdp_overlay_release_all() - release any overlays associated with fb dev
* @mfd: Msm frame buffer structure associated with fb device
+ * @release_all: ignore pid and release all the pipes
*
* Release any resources allocated by calling process, this can be called
* on fb_release to release any overlays/rotator sessions left open.
*/
-static int __mdss_mdp_overlay_release_all(struct msm_fb_data_type *mfd)
+static int __mdss_mdp_overlay_release_all(struct msm_fb_data_type *mfd,
+ bool release_all)
{
struct mdss_mdp_pipe *pipe;
struct mdss_mdp_rotator_session *rot, *tmp;
@@ -1176,7 +1182,7 @@
mutex_lock(&mdp5_data->ov_lock);
mutex_lock(&mfd->lock);
list_for_each_entry(pipe, &mdp5_data->pipes_used, used_list) {
- if (!mfd->ref_cnt || (pipe->pid == pid)) {
+ if (release_all || (pipe->pid == pid)) {
unset_ndx |= pipe->ndx;
cnt++;
}
@@ -1188,6 +1194,9 @@
cnt++;
}
+ pr_debug("release_all=%d mfd->ref_cnt=%d unset_ndx=0x%x cnt=%d\n",
+ release_all, mfd->ref_cnt, unset_ndx, cnt);
+
mutex_unlock(&mfd->lock);
if (unset_ndx) {
diff --git a/drivers/video/msm/mdss/mdss_mdp_pipe.c b/drivers/video/msm/mdss/mdss_mdp_pipe.c
index 78e7d29..0abd4d5 100644
--- a/drivers/video/msm/mdss/mdss_mdp_pipe.c
+++ b/drivers/video/msm/mdss/mdss_mdp_pipe.c
@@ -166,7 +166,7 @@
struct mdss_mdp_plane_sizes ps;
int i;
int rc = 0, rot_mode = 0;
- u32 nlines;
+ u32 nlines, format;
u16 width;
width = pipe->src.w >> pipe->horz_deci;
@@ -179,8 +179,25 @@
pr_debug("BWC SMP strides ystride0=%x ystride1=%x\n",
ps.ystride[0], ps.ystride[1]);
} else {
- rc = mdss_mdp_get_plane_sizes(pipe->src_fmt->format,
- width, pipe->src.h, &ps, 0);
+ format = pipe->src_fmt->format;
+ /*
+ * when decimation block is present, all chroma planes
+ * are fetched on a single SMP plane for chroma pixels
+ */
+ if (mdata->has_decimation) {
+ switch (pipe->src_fmt->chroma_sample) {
+ case MDSS_MDP_CHROMA_H2V1:
+ format = MDP_Y_CRCB_H2V1;
+ break;
+ case MDSS_MDP_CHROMA_420:
+ format = MDP_Y_CBCR_H2V2;
+ break;
+ default:
+ break;
+ }
+ }
+ rc = mdss_mdp_get_plane_sizes(format, width, pipe->src.h,
+ &ps, 0);
if (rc)
return rc;
@@ -191,15 +208,6 @@
max(pipe->mixer->width, width);
} else if (mdata->has_decimation) {
/*
- * when decimation block is used, all chroma planes
- * are fetched on a single SMP plane for chroma pixels
- */
- if (ps.num_planes == 3) {
- ps.num_planes = 2;
- ps.ystride[1] += ps.ystride[2];
- }
-
- /*
* To avoid quailty loss, MDP does one less decimation
* on chroma components if they are subsampled.
* Account for this to have enough SMPs for latency
diff --git a/drivers/video/msm/mdss/mdss_mdp_rotator.c b/drivers/video/msm/mdss/mdss_mdp_rotator.c
index 057914b..e2e41bb 100644
--- a/drivers/video/msm/mdss/mdss_mdp_rotator.c
+++ b/drivers/video/msm/mdss/mdss_mdp_rotator.c
@@ -437,6 +437,7 @@
rot->flags |= MDP_DEINTERLACE;
rot->src_rect.h /= 2;
rot->src_rect.y = DIV_ROUND_UP(rot->src_rect.y, 2);
+ rot->src_rect.y &= ~1;
}
rot->dst = rot->src_rect;
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
old mode 100644
new mode 100755
index f66a034..d9b1ef7
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -325,6 +325,7 @@
header-y += ptrace.h
header-y += qnx4_fs.h
header-y += qnxtypes.h
+header-y += qrng.h
header-y += quota.h
header-y += radeonfb.h
header-y += random.h
diff --git a/include/linux/qrng.h b/include/linux/qrng.h
new file mode 100644
index 0000000..35708e3
--- /dev/null
+++ b/include/linux/qrng.h
@@ -0,0 +1,12 @@
+#ifndef __QRNG_H_
+#define __QRNG_H_
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define QRNG_IOC_MAGIC 0x100
+
+#define QRNG_IOCTL_RESET_BUS_BANDWIDTH\
+ _IO(QRNG_IOC_MAGIC, 1)
+
+#endif /* __QRNG_H_ */
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 9eb9cd8..045a58b 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -232,6 +232,8 @@
* connected on data lines or not.
* @enable_ahb2ahb_bypass: Indicates whether enable AHB2AHB BYPASS
* mode with controller in device mode.
+ * @disable_retention_with_vdd_min: Indicates whether to enable allowing
+ * VDD min without putting PHY into retention
*/
struct msm_otg_platform_data {
int *phy_init_seq;
@@ -261,6 +263,7 @@
bool l1_supported;
bool dpdm_pulldown_added;
bool enable_ahb2ahb_bypass;
+ bool disable_retention_with_vdd_min;
};
/* phy related flags */
@@ -427,6 +430,11 @@
* voltage regulator(VDDCX) during host mode.
*/
#define ALLOW_HOST_PHY_RETENTION BIT(4)
+ /*
+ * Allow VDD minimization without putting PHY into retention
+ * for fixing PHY current leakage issue when LDOs are turned off.
+ */
+#define ALLOW_VDD_MIN_WITH_RETENTION_DISABLED BIT(5)
unsigned long lpm_flags;
#define PHY_PWR_COLLAPSED BIT(0)
#define PHY_RETENTIONED BIT(1)
diff --git a/include/media/msm_jpeg.h b/include/media/msm_jpeg.h
index 56829f1..99f0de0 100644
--- a/include/media/msm_jpeg.h
+++ b/include/media/msm_jpeg.h
@@ -55,6 +55,9 @@
#define MSM_JPEG_IOCTL_TEST_DUMP_REGION \
_IOW(MSM_JPEG_IOCTL_MAGIC, 15, unsigned long)
+#define MSM_JPEG_IOCTL_SET_CLK_RATE \
+ _IOW(MSM_JPEG_IOCTL_MAGIC, 16, unsigned long)
+
#define MSM_JPEG_MODE_REALTIME_ENCODE 0
#define MSM_JPEG_MODE_OFFLINE_ENCODE 1
#define MSM_JPEG_MODE_REALTIME_ROTATION 2
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
index 7b0ad14..568a3fa 100644
--- a/include/media/msmb_isp.h
+++ b/include/media/msmb_isp.h
@@ -152,6 +152,7 @@
enum msm_vfe_axi_stream_cmd {
STOP_STREAM,
START_STREAM,
+ STOP_IMMEDIATELY,
};
struct msm_vfe_axi_stream_cfg_cmd {
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index 41f8607..c549831 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -242,6 +242,56 @@
__entry->status ? "online" : "offline", __entry->error)
);
+/*
+ * Tracepoint for load balancing:
+ */
+#if NR_CPUS > 32
+#error "Unsupported NR_CPUS for lb tracepoint."
+#endif
+TRACE_EVENT(sched_load_balance,
+
+ TP_PROTO(int cpu, enum cpu_idle_type idle, int balance,
+ unsigned long group_mask, int busiest_nr_running,
+ unsigned long imbalance, unsigned int env_flags, int ld_moved,
+ unsigned int balance_interval),
+
+ TP_ARGS(cpu, idle, balance, group_mask, busiest_nr_running,
+ imbalance, env_flags, ld_moved, balance_interval),
+
+ TP_STRUCT__entry(
+ __field( int, cpu)
+ __field( enum cpu_idle_type, idle)
+ __field( int, balance)
+ __field( unsigned long, group_mask)
+ __field( int, busiest_nr_running)
+ __field( unsigned long, imbalance)
+ __field( unsigned int, env_flags)
+ __field( int, ld_moved)
+ __field( unsigned int, balance_interval)
+ ),
+
+ TP_fast_assign(
+ __entry->cpu = cpu;
+ __entry->idle = idle;
+ __entry->balance = balance;
+ __entry->group_mask = group_mask;
+ __entry->busiest_nr_running = busiest_nr_running;
+ __entry->imbalance = imbalance;
+ __entry->env_flags = env_flags;
+ __entry->ld_moved = ld_moved;
+ __entry->balance_interval = balance_interval;
+ ),
+
+ TP_printk("cpu=%d state=%s balance=%d group=%#lx busy_nr=%d imbalance=%ld flags=%#x ld_moved=%d bal_int=%d",
+ __entry->cpu,
+ __entry->idle == CPU_IDLE ? "idle" :
+ (__entry->idle == CPU_NEWLY_IDLE ? "newly_idle" : "busy"),
+ __entry->balance,
+ __entry->group_mask, __entry->busiest_nr_running,
+ __entry->imbalance, __entry->env_flags, __entry->ld_moved,
+ __entry->balance_interval)
+);
+
DECLARE_EVENT_CLASS(sched_process_template,
TP_PROTO(struct task_struct *p),
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 627dab1..89a5395 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -621,7 +621,19 @@
static inline bool got_nohz_idle_kick(void)
{
int cpu = smp_processor_id();
- return idle_cpu(cpu) && test_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu));
+
+ if (!test_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu)))
+ return false;
+
+ if (idle_cpu(cpu) && !need_resched())
+ return true;
+
+ /*
+ * We can't run Idle Load Balance on this CPU for this time so we
+ * cancel it and clear NOHZ_BALANCE_KICK
+ */
+ clear_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu));
+ return false;
}
#else /* CONFIG_NO_HZ */
@@ -1519,7 +1531,7 @@
/*
* Check if someone kicked us for doing the nohz idle load balance.
*/
- if (unlikely(got_nohz_idle_kick() && !need_resched())) {
+ if (unlikely(got_nohz_idle_kick())) {
this_rq()->idle_balance = 1;
raise_softirq_irqoff(SCHED_SOFTIRQ);
}
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 2e98983..08497b0 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -4422,7 +4422,7 @@
int ld_moved, active_balance = 0;
struct sched_group *group;
unsigned long imbalance;
- struct rq *busiest;
+ struct rq *busiest = NULL;
unsigned long flags;
struct cpumask *cpus = __get_cpu_var(load_balance_tmpmask);
@@ -4591,6 +4591,10 @@
ld_moved = 0;
out:
+ trace_sched_load_balance(this_cpu, idle, *balance,
+ group ? group->cpumask[0] : 0,
+ busiest ? busiest->nr_running : 0, imbalance,
+ env.flags, ld_moved, sd->balance_interval);
return ld_moved;
}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index e598400..04cfc69 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -191,7 +191,7 @@
size = SKB_DATA_ALIGN(size);
size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
data = kmalloc_node_track_caller(size, gfp_mask, node);
- if (!data)
+ if (unlikely(ZERO_OR_NULL_PTR(data)))
goto nodata;
/* kmalloc(size) might give us more room than requested.
* Put skb_shared_info exactly at the end of allocated zone,
diff --git a/sound/soc/codecs/wcd9306.c b/sound/soc/codecs/wcd9306.c
index abc628b..4076f19 100644
--- a/sound/soc/codecs/wcd9306.c
+++ b/sound/soc/codecs/wcd9306.c
@@ -2853,7 +2853,7 @@
{"DAC1", "Switch", "CLASS_H_DSM MUX"},
{"HPHL DAC", "Switch", "CLASS_H_DSM MUX"},
- {"HPHR DAC", NULL, "RX2 CHAIN"},
+ {"HPHR DAC", NULL, "RDAC3 MUX"},
{"LINEOUT1", NULL, "LINEOUT1 PA"},
{"LINEOUT2", NULL, "LINEOUT2 PA"},
@@ -2864,11 +2864,14 @@
{"LINEOUT2 PA", NULL, "LINEOUT2_PA_MIXER"},
{"LINEOUT2_PA_MIXER", NULL, "LINEOUT2 DAC"},
- {"LINEOUT1 DAC", NULL, "RX3 MIX1"},
{"RDAC5 MUX", "DEM3_INV", "RX3 MIX1"},
{"LINEOUT2 DAC", NULL, "RDAC5 MUX"},
+ {"RDAC4 MUX", "DEM3", "RX3 MIX1"},
+ {"RDAC4 MUX", "DEM2", "RX2 CHAIN"},
+ {"LINEOUT1 DAC", NULL, "RDAC4 MUX"},
+
{"SPK PA", NULL, "SPK DAC"},
{"SPK DAC", NULL, "VDD_SPKDRV"},
@@ -2881,7 +2884,7 @@
{"LINEOUT1 DAC", NULL, "CDC_CP_VDD"},
{"LINEOUT2 DAC", NULL, "CDC_CP_VDD"},
- {"RDAC3 MUX", "DEM2", "RX2 MIX1"},
+ {"RDAC3 MUX", "DEM2", "RX2 CHAIN"},
{"RDAC3 MUX", "DEM1", "RX1 CHAIN"},
{"RX1 MIX1", NULL, "RX1 MIX1 INP1"},
@@ -3016,9 +3019,6 @@
static const struct snd_soc_dapm_route wcd9302_map[] = {
{"SPK DAC", "Switch", "RX3 MIX1"},
- {"RDAC4 MUX", "DEM3", "RX3 MIX1"},
- {"RDAC4 MUX", "DEM2", "RX2 CHAIN"},
- {"LINEOUT1 DAC", NULL, "RDAC4 MUX"},
{"RDAC5 MUX", "DEM4", "RX3 MIX1"},
{"RDAC5 MUX", "DEM3_INV", "RDAC4 MUX"},
diff --git a/sound/soc/codecs/wcd9xxx-mbhc.c b/sound/soc/codecs/wcd9xxx-mbhc.c
index db7a34c..397295b 100644
--- a/sound/soc/codecs/wcd9xxx-mbhc.c
+++ b/sound/soc/codecs/wcd9xxx-mbhc.c
@@ -2065,8 +2065,11 @@
pr_debug("%s: enter\n", __func__);
WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
- current_source_enable = ((mbhc->mbhc_cfg->cs_enable_flags &
- (1 << MBHC_CS_ENABLE_INSERTION)) != 0);
+
+ current_source_enable = (((mbhc->mbhc_cfg->cs_enable_flags &
+ (1 << MBHC_CS_ENABLE_INSERTION)) != 0) &&
+ (!(snd_soc_read(mbhc->codec,
+ mbhc->mbhc_bias_regs.ctl_reg) & 0x80)));
if (current_source_enable) {
wcd9xxx_turn_onoff_current_source(mbhc, true, false);
@@ -2191,9 +2194,10 @@
unsigned long retry = 0, timeout;
bool cs_enable;
- cs_enable = ((mbhc->mbhc_cfg->cs_enable_flags &
- (1 << MBHC_CS_ENABLE_REMOVAL)) != 0);
-
+ cs_enable = (((mbhc->mbhc_cfg->cs_enable_flags &
+ (1 << MBHC_CS_ENABLE_REMOVAL)) != 0) &&
+ (!(snd_soc_read(mbhc->codec,
+ mbhc->mbhc_bias_regs.ctl_reg) & 0x80)));
if (cs_enable)
wcd9xxx_turn_onoff_current_source(mbhc, true, false);
@@ -2705,8 +2709,11 @@
mbhc = container_of(work, struct wcd9xxx_mbhc, correct_plug_swch);
codec = mbhc->codec;
- current_source_enable = ((mbhc->mbhc_cfg->cs_enable_flags &
- (1 << MBHC_CS_ENABLE_POLLING)) != 0);
+
+ current_source_enable = (((mbhc->mbhc_cfg->cs_enable_flags &
+ (1 << MBHC_CS_ENABLE_POLLING)) != 0) &&
+ (!(snd_soc_read(codec,
+ mbhc->mbhc_bias_regs.ctl_reg) & 0x80)));
wcd9xxx_onoff_ext_mclk(mbhc, true);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 1b4fae9..d56ad2b 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -54,6 +54,11 @@
#define SESSION_TYPE_RX 0
#define SESSION_TYPE_TX 1
+#define EC_PORT_ID_PRIMARY_MI2S_TX 1
+#define EC_PORT_ID_SECONDARY_MI2S_TX 2
+#define EC_PORT_ID_TERTIARY_MI2S_TX 3
+#define EC_PORT_ID_QUATERNARY_MI2S_TX 4
+
static struct mutex routing_lock;
static int fm_switch_enable;
@@ -63,6 +68,7 @@
static int slim0_rx_aanc_fb_port;
static int msm_route_ec_ref_rx = 3; /* NONE */
static uint32_t voc_session_id = ALL_SESSION_VSID;
+static int msm_route_ext_ec_ref = AFE_PORT_INVALID;
enum {
MADNONE,
@@ -1369,6 +1375,76 @@
msm_routing_ec_ref_rx_get, msm_routing_ec_ref_rx_put),
};
+static int msm_routing_ext_ec_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ pr_debug("%s: ext_ec_ref_rx = %x\n", __func__, msm_route_ext_ec_ref);
+
+ mutex_lock(&routing_lock);
+ ucontrol->value.integer.value[0] = msm_route_ext_ec_ref;
+ mutex_unlock(&routing_lock);
+ return 0;
+}
+
+static int msm_routing_ext_ec_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+ int mux = ucontrol->value.enumerated.item[0];
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ int ret = 0;
+ bool state = false;
+
+ pr_debug("%s: msm_route_ec_ref_rx = %d value = %ld\n",
+ __func__, msm_route_ext_ec_ref,
+ ucontrol->value.integer.value[0]);
+
+ mutex_lock(&routing_lock);
+ switch (ucontrol->value.integer.value[0]) {
+ case EC_PORT_ID_PRIMARY_MI2S_TX:
+ msm_route_ext_ec_ref = AFE_PORT_ID_PRIMARY_MI2S_TX;
+ state = true;
+ break;
+ case EC_PORT_ID_SECONDARY_MI2S_TX:
+ msm_route_ext_ec_ref = AFE_PORT_ID_SECONDARY_MI2S_TX;
+ state = true;
+ break;
+ case EC_PORT_ID_TERTIARY_MI2S_TX:
+ msm_route_ext_ec_ref = AFE_PORT_ID_TERTIARY_MI2S_TX;
+ state = true;
+ break;
+ case EC_PORT_ID_QUATERNARY_MI2S_TX:
+ msm_route_ext_ec_ref = AFE_PORT_ID_QUATERNARY_MI2S_TX;
+ state = true;
+ break;
+ default:
+ msm_route_ext_ec_ref = AFE_PORT_INVALID;
+ break;
+ }
+ if (voc_set_ext_ec_ref(msm_route_ext_ec_ref, state)) {
+ mutex_unlock(&routing_lock);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, 1, mux, e);
+ } else {
+ ret = -EINVAL;
+ mutex_unlock(&routing_lock);
+ }
+ return ret;
+}
+
+static const char * const ext_ec_ref_rx[] = {"NONE", "PRI_MI2S_TX",
+ "SEC_MI2S_TX", "TERT_MI2S_TX",
+ "QUAT_MI2S_TX"};
+
+static const struct soc_enum msm_route_ext_ec_ref_rx_enum[] = {
+ SOC_ENUM_SINGLE_EXT(5, ext_ec_ref_rx),
+};
+
+static const struct snd_kcontrol_new voc_ext_ec_mux =
+ SOC_DAPM_ENUM_EXT("VOC_EXT_EC MUX Mux", msm_route_ext_ec_ref_rx_enum[0],
+ msm_routing_ext_ec_get, msm_routing_ext_ec_put);
+
+
static const struct snd_kcontrol_new pri_i2s_rx_mixer_controls[] = {
SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_PRI_I2S_RX ,
MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
@@ -3235,6 +3311,8 @@
SND_SOC_DAPM_MUX("SLIM0_RX_VI_FB_LCH_MUX", SND_SOC_NOPM, 0, 0,
&slim0_rx_vi_fb_lch_mux),
+ SND_SOC_DAPM_MUX("VOC_EXT_EC MUX", SND_SOC_NOPM, 0, 0,
+ &voc_ext_ec_mux),
};
@@ -3524,6 +3602,12 @@
{"MI2S_RX_Voice Mixer", "QCHAT", "QCHAT_DL"},
{"MI2S_RX", NULL, "MI2S_RX_Voice Mixer"},
+ {"VOC_EXT_EC MUX", "PRI_MI2S_TX" , "PRI_MI2S_TX"},
+ {"VOC_EXT_EC MUX", "SEC_MI2S_TX" , "SEC_MI2S_TX"},
+ {"VOC_EXT_EC MUX", "TERT_MI2S_TX" , "TERT_MI2S_TX"},
+ {"VOC_EXT_EC MUX", "QUAT_MI2S_TX" , "QUAT_MI2S_TX"},
+ {"CS-VOICE_UL1", NULL, "VOC_EXT_EC MUX"},
+
{"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
{"Voice_Tx Mixer", "PRI_MI2S_TX_Voice", "PRI_MI2S_TX"},
{"Voice_Tx Mixer", "MI2S_TX_Voice", "MI2S_TX"},
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 7a5efb0..3d1b896 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1777,7 +1777,7 @@
struct asm_stream_cmd_open_readwrite_v2 open;
if ((ac == NULL) || (ac->apr == NULL)) {
- pr_err("APR handle NULL\n");
+ pr_err("%s: APR handle NULL\n", __func__);
return -EINVAL;
}
pr_debug("%s: session[%d]", __func__, ac->session);
@@ -1889,7 +1889,7 @@
struct asm_session_cmd_run_v2 run;
int rc;
if (!ac || ac->apr == NULL) {
- pr_err("APR handle NULL\n");
+ pr_err("%s: APR handle NULL\n", __func__);
return -EINVAL;
}
pr_debug("%s session[%d]", __func__, ac->session);
@@ -2794,7 +2794,7 @@
int cmd_size = 0;
if (!ac || ac->mmap_apr == NULL) {
- pr_err("APR handle NULL\n");
+ pr_err("%s: APR handle NULL\n", __func__);
return -EINVAL;
}
pr_debug("%s: Session[%d]\n", __func__, ac->session);
@@ -2871,7 +2871,7 @@
int rc = 0;
if (!ac || this_mmap.apr == NULL) {
- pr_err("APR handle NULL\n");
+ pr_err("%s: APR handle NULL\n", __func__);
return -EINVAL;
}
pr_debug("%s: Session[%d]\n", __func__, ac->session);
@@ -2941,7 +2941,7 @@
uint32_t bufsz_t;
if (!ac || ac->mmap_apr == NULL) {
- pr_err("APR handle NULL\n");
+ pr_err("%s: APR handle NULL\n", __func__);
return -EINVAL;
}
pr_debug("%s: Session[%d]\n", __func__, ac->session);
@@ -3050,7 +3050,7 @@
int cmd_size = 0;
if (!ac || ac->mmap_apr == NULL) {
- pr_err("APR handle NULL\n");
+ pr_err("%s: APR handle NULL\n", __func__);
return -EINVAL;
}
pr_debug("%s: Session[%d]\n", __func__, ac->session);
@@ -3436,7 +3436,7 @@
struct audio_port_data *port;
int rc;
if (!ac || ac->apr == NULL) {
- pr_err("APR handle NULL\n");
+ pr_err("%s: APR handle NULL\n", __func__);
return -EINVAL;
}
if (ac->io_mode & SYNC_IO_MODE) {
@@ -3499,7 +3499,7 @@
struct audio_port_data *port;
int rc;
if (!ac || ac->apr == NULL) {
- pr_err("APR handle NULL\n");
+ pr_err("%s: APR handle NULL\n", __func__);
return -EINVAL;
}
if (ac->io_mode & SYNC_IO_MODE) {
@@ -3696,7 +3696,7 @@
int dsp_buf = 0;
if (!ac || ac->apr == NULL) {
- pr_err("APR handle NULL\n");
+ pr_err("%s: APR handle NULL\n", __func__);
return -EINVAL;
}
pr_debug("%s: session[%d] len=%d", __func__, ac->session, len);
@@ -3764,7 +3764,7 @@
int dsp_buf = 0;
if (!ac || ac->apr == NULL) {
- pr_err("APR handle NULL\n");
+ pr_err("%s: APR handle NULL\n", __func__);
return -EINVAL;
}
pr_debug("%s: session[%d] len=%d", __func__, ac->session, len);
@@ -3823,7 +3823,7 @@
int rc;
if (!ac || ac->apr == NULL || tstamp == NULL) {
- pr_err("APR handle NULL or tstamp NULL\n");
+ pr_err("%s: APR handle NULL or tstamp NULL\n", __func__);
return -EINVAL;
}
q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE);
@@ -3861,7 +3861,7 @@
int cnt = 0;
if (!ac || ac->apr == NULL) {
- pr_err("APR handle NULL\n");
+ pr_err("%s: APR handle NULL\n", __func__);
return -EINVAL;
}
q6asm_add_hdr(ac, &hdr, sizeof(hdr), TRUE);
@@ -4011,7 +4011,7 @@
int rc;
if (!ac || ac->apr == NULL) {
- pr_err("APR handle NULL\n");
+ pr_err("%s: APR handle NULL\n", __func__);
return -EINVAL;
}
pr_debug("%s:session[%d]enable[%d]\n", __func__,
diff --git a/sound/soc/msm/qdsp6v2/q6voice.c b/sound/soc/msm/qdsp6v2/q6voice.c
index 673ecff..5aadfa5 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.c
+++ b/sound/soc/msm/qdsp6v2/q6voice.c
@@ -1861,10 +1861,18 @@
cvp_setdev_cmd.cvp_set_device_v2.tx_port_id = v->dev_tx.port_id;
cvp_setdev_cmd.cvp_set_device_v2.rx_port_id = v->dev_rx.port_id;
- cvp_setdev_cmd.cvp_set_device_v2.vocproc_mode =
+
+ if (common.ec_ref_ext) {
+ cvp_setdev_cmd.cvp_set_device_v2.vocproc_mode =
+ VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING;
+ cvp_setdev_cmd.cvp_set_device_v2.ec_ref_port_id =
+ common.ec_port_id;
+ } else {
+ cvp_setdev_cmd.cvp_set_device_v2.vocproc_mode =
VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING;
- cvp_setdev_cmd.cvp_set_device_v2.ec_ref_port_id =
+ cvp_setdev_cmd.cvp_set_device_v2.ec_ref_port_id =
VSS_IVOCPROC_PORT_ID_NONE;
+ }
pr_debug("topology=%d , tx_port_id=%d, rx_port_id=%d\n",
cvp_setdev_cmd.cvp_set_device_v2.tx_topology_id,
cvp_setdev_cmd.cvp_set_device_v2.tx_port_id,
@@ -3026,10 +3034,17 @@
cvp_session_cmd.cvp_session.rx_port_id = v->dev_rx.port_id;
cvp_session_cmd.cvp_session.profile_id =
VSS_ICOMMON_CAL_NETWORK_ID_NONE;
- cvp_session_cmd.cvp_session.vocproc_mode =
+ if (common.ec_ref_ext) {
+ cvp_session_cmd.cvp_session.vocproc_mode =
+ VSS_IVOCPROC_VOCPROC_MODE_EC_EXT_MIXING;
+ cvp_session_cmd.cvp_session.ec_ref_port_id =
+ common.ec_port_id;
+ } else {
+ cvp_session_cmd.cvp_session.vocproc_mode =
VSS_IVOCPROC_VOCPROC_MODE_EC_INT_MIXING;
- cvp_session_cmd.cvp_session.ec_ref_port_id =
+ cvp_session_cmd.cvp_session.ec_ref_port_id =
VSS_IVOCPROC_PORT_ID_NONE;
+ }
pr_debug("tx_topology: %d tx_port_id=%d, rx_port_id=%d, mode: 0x%x\n",
cvp_session_cmd.cvp_session.tx_topology_id,
@@ -4313,7 +4328,8 @@
v->voc_state = VOC_CHANGE;
}
-
+ if (common.ec_ref_ext)
+ voc_set_ext_ec_ref(AFE_PORT_INVALID, false);
fail: mutex_unlock(&v->lock);
return ret;
@@ -4756,6 +4772,8 @@
ret = -EINVAL;
}
+ if (common.ec_ref_ext)
+ voc_set_ext_ec_ref(AFE_PORT_INVALID, false);
mutex_unlock(&v->lock);
return ret;
@@ -4973,6 +4991,28 @@
return ret;
}
+int voc_set_ext_ec_ref(uint16_t port_id, bool state)
+{
+ int ret = 0;
+
+ mutex_lock(&common.common_lock);
+ if (state == true) {
+ if (port_id == AFE_PORT_INVALID) {
+ pr_err("%s: Invalid port id", __func__);
+ ret = -EINVAL;
+ goto exit;
+ }
+ common.ec_port_id = port_id;
+ common.ec_ref_ext = true;
+ } else {
+ common.ec_ref_ext = false;
+ common.ec_port_id = port_id;
+ }
+exit:
+ mutex_unlock(&common.common_lock);
+ return ret;
+}
+
void voc_register_mvs_cb(ul_cb_fn ul_cb,
dl_cb_fn dl_cb,
void *private_data)
@@ -5807,7 +5847,7 @@
common.default_vol_step_val = 0;
common.default_vol_ramp_duration_ms = DEFAULT_VOLUME_RAMP_DURATION;
common.default_mute_ramp_duration_ms = DEFAULT_MUTE_RAMP_DURATION;
-
+ common.ec_ref_ext = false;
/* Initialize MVS info. */
common.mvs_info.network_type = VSS_NETWORK_ID_DEFAULT;
diff --git a/sound/soc/msm/qdsp6v2/q6voice.h b/sound/soc/msm/qdsp6v2/q6voice.h
index 39f0986..5c0cf21 100644
--- a/sound/soc/msm/qdsp6v2/q6voice.h
+++ b/sound/soc/msm/qdsp6v2/q6voice.h
@@ -1328,6 +1328,8 @@
uint32_t default_vol_step_val;
uint32_t default_vol_ramp_duration_ms;
uint32_t default_mute_ramp_duration_ms;
+ bool ec_ref_ext;
+ uint16_t ec_port_id;
/* APR to MVM in the Q6 */
void *apr_q6_mvm;
@@ -1462,5 +1464,6 @@
int voc_start_playback(uint32_t set, uint16_t port_id);
int voc_start_record(uint32_t port_id, uint32_t set, uint32_t session_id);
int voice_get_idx_for_session(u32 session_id);
+int voc_set_ext_ec_ref(uint16_t port_id, bool state);
#endif