Merge "ASoC: apq8064-i2s: Update machine driver for APQ8064 I2S platform"
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 0eb186e..2864fd1 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -48,6 +48,12 @@
- compatible : "qcom,msm-dai-fe"
+* msm-pcm-afe
+
+Required properties:
+
+ - compatible : "qcom,msm-pcm-afe"
+
* msm-dai-q6
[First Level Nodes]
@@ -63,6 +69,8 @@
- compatible : "qcom,msm-dai-q6-dev"
- qcom,msm-dai-q6-dev-id : The slimbus multi channel port ID
Value is from 16384 to 16393
+ BT SCO port ID value from 12288 to 12289
+ RT Proxy port ID values from 224 to 225 and 240 to 241
* msm-auxpcm
@@ -166,6 +174,36 @@
compatible = "qcom,msm-dai-q6-dev";
qcom,msm-dai-q6-dev-id = <16385>;
};
+
+ qcom,msm-dai-q6-bt-sco-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12288>;
+ };
+
+ qcom,msm-dai-q6-bt-sco-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12289>;
+ };
+
+ qcom,msm-dai-q6-be-afe-pcm-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <224>;
+ };
+
+ qcom,msm-dai-q6-be-afe-pcm-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <225>;
+ };
+
+ qcom,msm-dai-q6-afe-proxy-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <241>;
+ };
+
+ qcom,msm-dai-q6-afe-proxy-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <240>;
+ };
};
qcom,msm-auxpcm {
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index 9c2ce6c..12fbfec 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -6,6 +6,8 @@
- compatible : should be "qcom,hsusb-otg"
- regs : offset and length of the register set in the memory map
- interrupts: IRQ line
+- interrupt-names: OTG interrupt name(s) referenced in interrupts above
+ HSUSB OTG expects "core_irq" and optionally "async_irq".
- qcom,hsusb-otg-phy-type: PHY type can be one of
1 - Chipidea 45nm PHY
2 - Synopsis 28nm PHY
@@ -48,6 +50,7 @@
compatible = "qcom,hsusb-otg";
reg = <0xf9690000 0x400>;
interrupts = <134>;
+ interrupt-names = "core_irq";
qcom,hsusb-otg-phy-type = <2>;
qcom,hsusb-otg-mode = <1>;
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index c3c0d56..9ed61ed 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -673,6 +673,10 @@
compatible = "qcom,msm-dai-fe";
};
+ qcom,msm-pcm-afe {
+ compatible = "qcom,msm-pcm-afe";
+ };
+
qcom,msm-dai-q6 {
compatible = "qcom,msm-dai-q6";
qcom,msm-dai-q6-sb-0-rx {
@@ -684,6 +688,36 @@
compatible = "qcom,msm-dai-q6-dev";
qcom,msm-dai-q6-dev-id = <16385>;
};
+
+ qcom,msm-dai-q6-bt-sco-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12288>;
+ };
+
+ qcom,msm-dai-q6-bt-sco-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <12289>;
+ };
+
+ qcom,msm-dai-q6-be-afe-pcm-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <224>;
+ };
+
+ qcom,msm-dai-q6-be-afe-pcm-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <225>;
+ };
+
+ qcom,msm-dai-q6-afe-proxy-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <241>;
+ };
+
+ qcom,msm-dai-q6-afe-proxy-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <240>;
+ };
};
qcom,msm-auxpcm {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index 767f385..36fad49 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -66,6 +66,26 @@
interrupts = <0 109 0>;
};
+ usb@f9a55000 {
+ compatible = "qcom,hsusb-otg";
+ reg = <0xf9a55000 0x400>;
+ interrupts = <0 134 0 0 140 0>;
+ interrupt-names = "core_irq", "async_irq";
+ HSUSB_VDDCX-supply = <&pm8019_l12>;
+ HSUSB_1p8-supply = <&pm8019_l2>;
+ HSUSB_3p3-supply = <&pm8019_l4>;
+
+ qcom,hsusb-otg-phy-type = <2>;
+ qcom,hsusb-otg-mode = <1>;
+ qcom,hsusb-otg-otg-control = <1>;
+ qcom,hsusb-otg-disable-reset;
+ };
+
+ android_usb@fc42b0c8 {
+ compatible = "qcom,android-usb";
+ reg = <0xfc42b0c8 0xc8>;
+ };
+
qcom,nand@f9ac0000 {
compatible = "qcom,msm-nand";
reg = <0xf9ac0000 0x1000>,
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index d2e37e0..60eb505 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -87,6 +87,7 @@
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_MSM_HSL=y
CONFIG_SERIAL_MSM_HSL_CONSOLE=y
+CONFIG_DIAG_CHAR=y
CONFIG_HW_RANDOM=y
CONFIG_SPI=y
CONFIG_SPI_QUP=y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 3c44a06..d00acc9 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -274,7 +274,7 @@
obj-$(CONFIG_MACH_MSM8930_CDP) += board-8930-all.o board-8930-regulator-pm8038.o board-8930-regulator-pm8917.o
obj-$(CONFIG_MACH_MSM8930_MTP) += board-8930-all.o board-8930-regulator-pm8038.o board-8930-regulator-pm8917.o
obj-$(CONFIG_MACH_MSM8930_FLUID) += board-8930-all.o board-8930-regulator-pm8038.o board-8930-regulator-pm8917.o
-obj-$(CONFIG_PM8921_BMS) += bms-batterydata.o bms-batterydata-desay.o
+obj-$(CONFIG_PM8921_BMS) += bms-batterydata.o bms-batterydata-desay.o batterydata-lib.o
obj-$(CONFIG_MACH_APQ8064_CDP) += board-8064-all.o board-8064-regulator.o
obj-$(CONFIG_MACH_APQ8064_MTP) += board-8064-all.o board-8064-regulator.o
obj-$(CONFIG_MACH_APQ8064_LIQUID) += board-8064-all.o board-8064-regulator.o
diff --git a/arch/arm/mach-msm/batterydata-lib.c b/arch/arm/mach-msm/batterydata-lib.c
new file mode 100644
index 0000000..2be591c
--- /dev/null
+++ b/arch/arm/mach-msm/batterydata-lib.c
@@ -0,0 +1,338 @@
+/* Copyright (c) 2012, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/mfd/pm8xxx/batterydata-lib.h>
+
+int linear_interpolate(int y0, int x0, int y1, int x1, int x)
+{
+ if (y0 == y1 || x == x0)
+ return y0;
+ if (x1 == x0 || x == x1)
+ return y1;
+
+ return y0 + ((y1 - y0) * (x - x0) / (x1 - x0));
+}
+
+int is_between(int left, int right, int value)
+{
+ if (left >= right && left >= value && value >= right)
+ return 1;
+ if (left <= right && left <= value && value <= right)
+ return 1;
+ return 0;
+}
+
+static int interpolate_single_lut(struct single_row_lut *lut, int x)
+{
+ int i, result;
+
+ if (x < lut->x[0]) {
+ pr_debug("x %d less than known range return y = %d lut = %pS\n",
+ x, lut->y[0], lut);
+ return lut->y[0];
+ }
+ if (x > lut->x[lut->cols - 1]) {
+ pr_debug("x %d more than known range return y = %d lut = %pS\n",
+ x, lut->y[lut->cols - 1], lut);
+ return lut->y[lut->cols - 1];
+ }
+
+ for (i = 0; i < lut->cols; i++)
+ if (x <= lut->x[i])
+ break;
+ if (x == lut->x[i]) {
+ result = lut->y[i];
+ } else {
+ result = linear_interpolate(
+ lut->y[i - 1],
+ lut->x[i - 1],
+ lut->y[i],
+ lut->x[i],
+ x);
+ }
+ return result;
+}
+
+int interpolate_fcc(struct single_row_lut *fcc_temp_lut, int batt_temp)
+{
+ /* batt_temp is in tenths of degC - convert it to degC for lookups */
+ batt_temp = batt_temp/10;
+ return interpolate_single_lut(fcc_temp_lut, batt_temp);
+}
+
+int interpolate_scalingfactor_fcc(struct single_row_lut *fcc_sf_lut,
+ int cycles)
+{
+ /*
+ * sf table could be null when no battery aging data is available, in
+ * that case return 100%
+ */
+ if (fcc_sf_lut)
+ return interpolate_single_lut(fcc_sf_lut, cycles);
+ else
+ return 100;
+}
+
+int interpolate_scalingfactor(struct sf_lut *sf_lut, int row_entry, int pc)
+{
+ int i, scalefactorrow1, scalefactorrow2, scalefactor, rows, cols;
+ int row1 = 0;
+ int row2 = 0;
+
+ /*
+ * sf table could be null when no battery aging data is available, in
+ * that case return 100%
+ */
+ if (!sf_lut)
+ return 100;
+
+ rows = sf_lut->rows;
+ cols = sf_lut->cols;
+ if (pc > sf_lut->percent[0]) {
+ pr_debug("pc %d greater than known pc ranges for sfd\n", pc);
+ row1 = 0;
+ row2 = 0;
+ }
+ if (pc < sf_lut->percent[rows - 1]) {
+ pr_debug("pc %d less than known pc ranges for sf\n", pc);
+ row1 = rows - 1;
+ row2 = rows - 1;
+ }
+ for (i = 0; i < rows; i++) {
+ if (pc == sf_lut->percent[i]) {
+ row1 = i;
+ row2 = i;
+ break;
+ }
+ if (pc > sf_lut->percent[i]) {
+ row1 = i - 1;
+ row2 = i;
+ break;
+ }
+ }
+
+ if (row_entry < sf_lut->row_entries[0])
+ row_entry = sf_lut->row_entries[0];
+ if (row_entry > sf_lut->row_entries[cols - 1])
+ row_entry = sf_lut->row_entries[cols - 1];
+
+ for (i = 0; i < cols; i++)
+ if (row_entry <= sf_lut->row_entries[i])
+ break;
+ if (row_entry == sf_lut->row_entries[i]) {
+ scalefactor = linear_interpolate(
+ sf_lut->sf[row1][i],
+ sf_lut->percent[row1],
+ sf_lut->sf[row2][i],
+ sf_lut->percent[row2],
+ pc);
+ return scalefactor;
+ }
+
+ scalefactorrow1 = linear_interpolate(
+ sf_lut->sf[row1][i - 1],
+ sf_lut->row_entries[i - 1],
+ sf_lut->sf[row1][i],
+ sf_lut->row_entries[i],
+ row_entry);
+
+ scalefactorrow2 = linear_interpolate(
+ sf_lut->sf[row2][i - 1],
+ sf_lut->row_entries[i - 1],
+ sf_lut->sf[row2][i],
+ sf_lut->row_entries[i],
+ row_entry);
+
+ scalefactor = linear_interpolate(
+ scalefactorrow1,
+ sf_lut->percent[row1],
+ scalefactorrow2,
+ sf_lut->percent[row2],
+ pc);
+
+ return scalefactor;
+}
+
+/* get ocv given a soc -- reverse lookup */
+int interpolate_ocv(struct pc_temp_ocv_lut *pc_temp_ocv,
+ int batt_temp_degc, int pc)
+{
+ int i, ocvrow1, ocvrow2, ocv, rows, cols;
+ int row1 = 0;
+ int row2 = 0;
+
+ rows = pc_temp_ocv->rows;
+ cols = pc_temp_ocv->cols;
+ if (pc > pc_temp_ocv->percent[0]) {
+ pr_debug("pc %d greater than known pc ranges for sfd\n", pc);
+ row1 = 0;
+ row2 = 0;
+ }
+ if (pc < pc_temp_ocv->percent[rows - 1]) {
+ pr_debug("pc %d less than known pc ranges for sf\n", pc);
+ row1 = rows - 1;
+ row2 = rows - 1;
+ }
+ for (i = 0; i < rows; i++) {
+ if (pc == pc_temp_ocv->percent[i]) {
+ row1 = i;
+ row2 = i;
+ break;
+ }
+ if (pc > pc_temp_ocv->percent[i]) {
+ row1 = i - 1;
+ row2 = i;
+ break;
+ }
+ }
+
+ if (batt_temp_degc < pc_temp_ocv->temp[0])
+ batt_temp_degc = pc_temp_ocv->temp[0];
+ if (batt_temp_degc > pc_temp_ocv->temp[cols - 1])
+ batt_temp_degc = pc_temp_ocv->temp[cols - 1];
+
+ for (i = 0; i < cols; i++)
+ if (batt_temp_degc <= pc_temp_ocv->temp[i])
+ break;
+ if (batt_temp_degc == pc_temp_ocv->temp[i]) {
+ ocv = linear_interpolate(
+ pc_temp_ocv->ocv[row1][i],
+ pc_temp_ocv->percent[row1],
+ pc_temp_ocv->ocv[row2][i],
+ pc_temp_ocv->percent[row2],
+ pc);
+ return ocv;
+ }
+
+ ocvrow1 = linear_interpolate(
+ pc_temp_ocv->ocv[row1][i - 1],
+ pc_temp_ocv->temp[i - 1],
+ pc_temp_ocv->ocv[row1][i],
+ pc_temp_ocv->temp[i],
+ batt_temp_degc);
+
+ ocvrow2 = linear_interpolate(
+ pc_temp_ocv->ocv[row2][i - 1],
+ pc_temp_ocv->temp[i - 1],
+ pc_temp_ocv->ocv[row2][i],
+ pc_temp_ocv->temp[i],
+ batt_temp_degc);
+
+ ocv = linear_interpolate(
+ ocvrow1,
+ pc_temp_ocv->percent[row1],
+ ocvrow2,
+ pc_temp_ocv->percent[row2],
+ pc);
+
+ return ocv;
+}
+
+int interpolate_pc(struct pc_temp_ocv_lut *pc_temp_ocv,
+ int batt_temp_degc, int ocv)
+{
+ int i, j, pcj, pcj_minus_one, pc;
+ int rows = pc_temp_ocv->rows;
+ int cols = pc_temp_ocv->cols;
+
+ if (batt_temp_degc < pc_temp_ocv->temp[0]) {
+ pr_debug("batt_temp %d < known temp range\n", batt_temp_degc);
+ batt_temp_degc = pc_temp_ocv->temp[0];
+ }
+
+ if (batt_temp_degc > pc_temp_ocv->temp[cols - 1]) {
+ pr_debug("batt_temp %d > known temp range\n", batt_temp_degc);
+ batt_temp_degc = pc_temp_ocv->temp[cols - 1];
+ }
+
+ for (j = 0; j < cols; j++)
+ if (batt_temp_degc <= pc_temp_ocv->temp[j])
+ break;
+ if (batt_temp_degc == pc_temp_ocv->temp[j]) {
+ /* found an exact match for temp in the table */
+ if (ocv >= pc_temp_ocv->ocv[0][j])
+ return pc_temp_ocv->percent[0];
+ if (ocv <= pc_temp_ocv->ocv[rows - 1][j])
+ return pc_temp_ocv->percent[rows - 1];
+ for (i = 0; i < rows; i++) {
+ if (ocv >= pc_temp_ocv->ocv[i][j]) {
+ if (ocv == pc_temp_ocv->ocv[i][j])
+ return pc_temp_ocv->percent[i];
+ pc = linear_interpolate(
+ pc_temp_ocv->percent[i],
+ pc_temp_ocv->ocv[i][j],
+ pc_temp_ocv->percent[i - 1],
+ pc_temp_ocv->ocv[i - 1][j],
+ ocv);
+ return pc;
+ }
+ }
+ }
+
+ /*
+ * batt_temp_degc is within temperature for
+ * column j-1 and j
+ */
+ if (ocv >= pc_temp_ocv->ocv[0][j])
+ return pc_temp_ocv->percent[0];
+ if (ocv <= pc_temp_ocv->ocv[rows - 1][j - 1])
+ return pc_temp_ocv->percent[rows - 1];
+
+ pcj_minus_one = 0;
+ pcj = 0;
+ for (i = 0; i < rows-1; i++) {
+ if (pcj == 0
+ && is_between(pc_temp_ocv->ocv[i][j],
+ pc_temp_ocv->ocv[i+1][j], ocv)) {
+ pcj = linear_interpolate(
+ pc_temp_ocv->percent[i],
+ pc_temp_ocv->ocv[i][j],
+ pc_temp_ocv->percent[i + 1],
+ pc_temp_ocv->ocv[i+1][j],
+ ocv);
+ }
+
+ if (pcj_minus_one == 0
+ && is_between(pc_temp_ocv->ocv[i][j-1],
+ pc_temp_ocv->ocv[i+1][j-1], ocv)) {
+ pcj_minus_one = linear_interpolate(
+ pc_temp_ocv->percent[i],
+ pc_temp_ocv->ocv[i][j-1],
+ pc_temp_ocv->percent[i + 1],
+ pc_temp_ocv->ocv[i+1][j-1],
+ ocv);
+ }
+
+ if (pcj && pcj_minus_one) {
+ pc = linear_interpolate(
+ pcj_minus_one,
+ pc_temp_ocv->temp[j-1],
+ pcj,
+ pc_temp_ocv->temp[j],
+ batt_temp_degc);
+ return pc;
+ }
+ }
+
+ if (pcj)
+ return pcj;
+
+ if (pcj_minus_one)
+ return pcj_minus_one;
+
+ pr_debug("%d ocv wasn't found for temp %d in the LUT returning 100%%\n",
+ ocv, batt_temp_degc);
+ return 100;
+}
diff --git a/arch/arm/mach-msm/bms-batterydata-desay.c b/arch/arm/mach-msm/bms-batterydata-desay.c
index f362a72..d9fa061 100644
--- a/arch/arm/mach-msm/bms-batterydata-desay.c
+++ b/arch/arm/mach-msm/bms-batterydata-desay.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*/
-#include <linux/mfd/pm8xxx/pm8921-bms.h>
+#include <linux/mfd/pm8xxx/batterydata-lib.h>
static struct single_row_lut desay_5200_fcc_temp = {
.x = {-20, 0, 25, 40},
@@ -76,7 +76,7 @@
},
};
-struct pm8921_bms_battery_data desay_5200_data = {
+struct bms_battery_data desay_5200_data = {
.fcc = 5200,
.fcc_temp_lut = &desay_5200_fcc_temp,
.fcc_sf_lut = &desay_5200_fcc_sf,
diff --git a/arch/arm/mach-msm/bms-batterydata.c b/arch/arm/mach-msm/bms-batterydata.c
index 81ab121..fb4f967 100644
--- a/arch/arm/mach-msm/bms-batterydata.c
+++ b/arch/arm/mach-msm/bms-batterydata.c
@@ -10,7 +10,7 @@
* GNU General Public License for more details.
*/
-#include <linux/mfd/pm8xxx/pm8921-bms.h>
+#include <linux/mfd/pm8xxx/batterydata-lib.h>
static struct single_row_lut fcc_temp = {
.x = {-20, 0, 25, 40, 65},
@@ -99,7 +99,7 @@
}
};
-struct pm8921_bms_battery_data palladium_1500_data = {
+struct bms_battery_data palladium_1500_data = {
.fcc = 1500,
.fcc_temp_lut = &fcc_temp,
.pc_temp_ocv_lut = &pc_temp_ocv,
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index e9b4867..a64e6a5 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -5128,7 +5128,9 @@
CLK_LOOKUP("core_clk", mdss_esc1_clk.c, ""),
CLK_LOOKUP("pixel_clk", mdss_pclk0_clk.c, "fd922800.qcom,mdss_dsi"),
CLK_LOOKUP("pixel_clk", mdss_pclk1_clk.c, ""),
- CLK_LOOKUP("iface_clk", mdss_hdmi_ahb_clk.c, "fd922100.qcom,hdmi_tx"),
+ CLK_LOOKUP("iface_clk", mdss_ahb_clk.c, "fd922100.qcom,hdmi_tx"),
+ CLK_LOOKUP("alt_iface_clk", mdss_hdmi_ahb_clk.c,
+ "fd922100.qcom,hdmi_tx"),
CLK_LOOKUP("core_clk", mdss_hdmi_clk.c, "fd922100.qcom,hdmi_tx"),
CLK_LOOKUP("extp_clk", mdss_extpclk_clk.c, "fd922100.qcom,hdmi_tx"),
CLK_LOOKUP("core_clk", mdss_mdp_clk.c, "mdp.0"),
diff --git a/drivers/net/ethernet/msm/msm_rmnet_smux.c b/drivers/net/ethernet/msm/msm_rmnet_smux.c
index fbb3489..5f29406 100644
--- a/drivers/net/ethernet/msm/msm_rmnet_smux.c
+++ b/drivers/net/ethernet/msm/msm_rmnet_smux.c
@@ -79,6 +79,7 @@
unsigned long timeout_us;
#endif
spinlock_t lock;
+ spinlock_t tx_queue_lock;
struct tasklet_struct tsklt;
/* IOCTL specified mode (protocol, QoS header) */
u32 operation_mode;
@@ -346,12 +347,15 @@
((struct net_device *)(dev))->name, p->stats.tx_packets,
skb->len, skb->mark);
dev_kfree_skb_any(skb);
+
+ spin_lock_irqsave(&p->tx_queue_lock, flags);
if (netif_queue_stopped(dev) &&
msm_smux_is_ch_low(p->ch_id)) {
DBG0("%s: Low WM hit, waking queue=%p\n",
__func__, skb);
netif_wake_queue(dev);
}
+ spin_unlock_irqrestore(&p->tx_queue_lock, flags);
}
void rmnet_smux_notify(void *priv, int event_type, const void *metadata)
@@ -475,14 +479,20 @@
case SMUX_LOW_WM_HIT:
dev = priv;
+ p = netdev_priv(priv);
DBG0("[%s] Low WM hit dev:%s\n", __func__, dev->name);
+ spin_lock_irqsave(&p->tx_queue_lock, flags);
netif_start_queue(dev);
+ spin_unlock_irqrestore(&p->tx_queue_lock, flags);
break;
case SMUX_HIGH_WM_HIT:
dev = priv;
- DBG0("[%s] Low WM hit dev:%s\n", __func__, dev->name);
+ p = netdev_priv(priv);
+ DBG0("[%s] High WM hit dev:%s\n", __func__, dev->name);
+ spin_lock_irqsave(&p->tx_queue_lock, flags);
netif_stop_queue(dev);
+ spin_unlock_irqrestore(&p->tx_queue_lock, flags);
break;
default:
@@ -573,7 +583,6 @@
static int _rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct rmnet_private *p = netdev_priv(dev);
- int smux_ret;
struct QMI_QOS_HDR_S *qmih;
u32 opmode;
unsigned long flags;
@@ -593,21 +602,13 @@
dev->trans_start = jiffies;
- /* if write() succeeds, skb access is unsafe in this process */
- smux_ret = msm_smux_write(p->ch_id, skb, skb->data, skb->len);
-
- if (smux_ret != 0 && smux_ret != -EAGAIN) {
- pr_err("[%s] %s: write returned error %d",
- dev->name, __func__, smux_ret);
- return -EPERM;
- }
-
- return smux_ret;
+ return msm_smux_write(p->ch_id, skb, skb->data, skb->len);
}
static int rmnet_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct rmnet_private *p = netdev_priv(dev);
+ unsigned long flags;
int ret = 0;
if (netif_queue_stopped(dev) || (p->device_state == DEVICE_INACTIVE)) {
@@ -616,17 +617,10 @@
return 0;
}
+ spin_lock_irqsave(&p->tx_queue_lock, flags);
ret = _rmnet_xmit(skb, dev);
- if (ret == -EPERM) {
- /* Do not stop the queue here.
- * It will lead to ir-recoverable state.
- */
- ret = NETDEV_TX_BUSY;
- goto exit;
- }
-
- if (msm_smux_is_ch_full(p->ch_id) || (ret == -EAGAIN)) {
+ if (ret == -EAGAIN) {
/*
* EAGAIN means we attempted to overflow the high watermark
* Clearly the queue is not stopped like it should be, so
@@ -636,9 +630,9 @@
*/
netif_stop_queue(dev);
ret = NETDEV_TX_BUSY;
- goto exit;
}
-exit:
+ spin_unlock_irqrestore(&p->tx_queue_lock, flags);
+
return ret;
}
@@ -892,6 +886,7 @@
p->ch_id = n;
p->in_reset = 0;
spin_lock_init(&p->lock);
+ spin_lock_init(&p->tx_queue_lock);
#ifdef CONFIG_MSM_RMNET_DEBUG
p->timeout_us = timeout_us;
p->wakeups_xmit = p->wakeups_rcv = 0;
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index c63c99f..b107040 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -10,8 +10,8 @@
* GNU General Public License for more details.
*
*/
-#define pr_fmt(fmt) "%s: " fmt, __func__
+#define pr_fmt(fmt) "%s: " fmt, __func__
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/platform_device.h>
@@ -22,6 +22,7 @@
#include <linux/mfd/pm8xxx/pm8xxx-adc.h>
#include <linux/mfd/pm8xxx/pm8921-charger.h>
#include <linux/mfd/pm8xxx/ccadc.h>
+#include <linux/mfd/pm8xxx/batterydata-lib.h>
#include <linux/interrupt.h>
#include <linux/bitops.h>
#include <linux/debugfs.h>
@@ -224,7 +225,6 @@
module_param_cb(bms_end_ocv_uv, &bms_ro_param_ops, &bms_end_ocv_uv, 0644);
module_param_cb(bms_end_cc_uah, &bms_ro_param_ops, &bms_end_cc_uah, 0644);
-static int interpolate_fcc(struct pm8921_bms_chip *chip, int batt_temp);
static void readjust_fcc_table(void)
{
struct single_row_lut *temp, *old;
@@ -241,7 +241,7 @@
return;
}
- fcc = interpolate_fcc(the_chip, last_real_fcc_batt_temp);
+ fcc = interpolate_fcc(the_chip->fcc_temp_lut, last_real_fcc_batt_temp);
temp->cols = the_chip->fcc_temp_lut->cols;
for (i = 0; i < the_chip->fcc_temp_lut->cols; i++) {
@@ -583,342 +583,6 @@
return 0;
}
-static int linear_interpolate(int y0, int x0, int y1, int x1, int x)
-{
- if (y0 == y1 || x == x0)
- return y0;
- if (x1 == x0 || x == x1)
- return y1;
-
- return y0 + ((y1 - y0) * (x - x0) / (x1 - x0));
-}
-
-static int interpolate_single_lut(struct single_row_lut *lut, int x)
-{
- int i, result;
-
- if (x < lut->x[0]) {
- pr_debug("x %d less than known range return y = %d lut = %pS\n",
- x, lut->y[0], lut);
- return lut->y[0];
- }
- if (x > lut->x[lut->cols - 1]) {
- pr_debug("x %d more than known range return y = %d lut = %pS\n",
- x, lut->y[lut->cols - 1], lut);
- return lut->y[lut->cols - 1];
- }
-
- for (i = 0; i < lut->cols; i++)
- if (x <= lut->x[i])
- break;
- if (x == lut->x[i]) {
- result = lut->y[i];
- } else {
- result = linear_interpolate(
- lut->y[i - 1],
- lut->x[i - 1],
- lut->y[i],
- lut->x[i],
- x);
- }
- return result;
-}
-
-static int interpolate_fcc(struct pm8921_bms_chip *chip, int batt_temp)
-{
- /* batt_temp is in tenths of degC - convert it to degC for lookups */
- batt_temp = batt_temp/10;
- return interpolate_single_lut(chip->fcc_temp_lut, batt_temp);
-}
-
-static int interpolate_fcc_adjusted(struct pm8921_bms_chip *chip, int batt_temp)
-{
- /* batt_temp is in tenths of degC - convert it to degC for lookups */
- batt_temp = batt_temp/10;
- return interpolate_single_lut(chip->adjusted_fcc_temp_lut, batt_temp);
-}
-
-static int interpolate_scalingfactor_fcc(struct pm8921_bms_chip *chip,
- int cycles)
-{
- /*
- * sf table could be null when no battery aging data is available, in
- * that case return 100%
- */
- if (chip->fcc_sf_lut)
- return interpolate_single_lut(chip->fcc_sf_lut, cycles);
- else
- return 100;
-}
-
-static int interpolate_scalingfactor(struct pm8921_bms_chip *chip,
- struct sf_lut *sf_lut,
- int row_entry, int pc)
-{
- int i, scalefactorrow1, scalefactorrow2, scalefactor;
- int rows, cols;
- int row1 = 0;
- int row2 = 0;
-
- /*
- * sf table could be null when no battery aging data is available, in
- * that case return 100%
- */
- if (!sf_lut)
- return 100;
-
- rows = sf_lut->rows;
- cols = sf_lut->cols;
- if (pc > sf_lut->percent[0]) {
- pr_debug("pc %d greater than known pc ranges for sfd\n", pc);
- row1 = 0;
- row2 = 0;
- }
- if (pc < sf_lut->percent[rows - 1]) {
- pr_debug("pc %d less than known pc ranges for sf", pc);
- row1 = rows - 1;
- row2 = rows - 1;
- }
- for (i = 0; i < rows; i++) {
- if (pc == sf_lut->percent[i]) {
- row1 = i;
- row2 = i;
- break;
- }
- if (pc > sf_lut->percent[i]) {
- row1 = i - 1;
- row2 = i;
- break;
- }
- }
-
- if (row_entry < sf_lut->row_entries[0])
- row_entry = sf_lut->row_entries[0];
- if (row_entry > sf_lut->row_entries[cols - 1])
- row_entry = sf_lut->row_entries[cols - 1];
-
- for (i = 0; i < cols; i++)
- if (row_entry <= sf_lut->row_entries[i])
- break;
- if (row_entry == sf_lut->row_entries[i]) {
- scalefactor = linear_interpolate(
- sf_lut->sf[row1][i],
- sf_lut->percent[row1],
- sf_lut->sf[row2][i],
- sf_lut->percent[row2],
- pc);
- return scalefactor;
- }
-
- scalefactorrow1 = linear_interpolate(
- sf_lut->sf[row1][i - 1],
- sf_lut->row_entries[i - 1],
- sf_lut->sf[row1][i],
- sf_lut->row_entries[i],
- row_entry);
-
- scalefactorrow2 = linear_interpolate(
- sf_lut->sf[row2][i - 1],
- sf_lut->row_entries[i - 1],
- sf_lut->sf[row2][i],
- sf_lut->row_entries[i],
- row_entry);
-
- scalefactor = linear_interpolate(
- scalefactorrow1,
- sf_lut->percent[row1],
- scalefactorrow2,
- sf_lut->percent[row2],
- pc);
-
- return scalefactor;
-}
-
-static int is_between(int left, int right, int value)
-{
- if (left >= right && left >= value && value >= right)
- return 1;
- if (left <= right && left <= value && value <= right)
- return 1;
-
- return 0;
-}
-
-/* get ocv given a soc -- reverse lookup */
-static int interpolate_ocv(struct pm8921_bms_chip *chip,
- int batt_temp_degc, int pc)
-{
- int i, ocvrow1, ocvrow2, ocv;
- int rows, cols;
- int row1 = 0;
- int row2 = 0;
-
- rows = chip->pc_temp_ocv_lut->rows;
- cols = chip->pc_temp_ocv_lut->cols;
- if (pc > chip->pc_temp_ocv_lut->percent[0]) {
- pr_debug("pc %d greater than known pc ranges for sfd\n", pc);
- row1 = 0;
- row2 = 0;
- }
- if (pc < chip->pc_temp_ocv_lut->percent[rows - 1]) {
- pr_debug("pc %d less than known pc ranges for sf\n", pc);
- row1 = rows - 1;
- row2 = rows - 1;
- }
- for (i = 0; i < rows; i++) {
- if (pc == chip->pc_temp_ocv_lut->percent[i]) {
- row1 = i;
- row2 = i;
- break;
- }
- if (pc > chip->pc_temp_ocv_lut->percent[i]) {
- row1 = i - 1;
- row2 = i;
- break;
- }
- }
-
- if (batt_temp_degc < chip->pc_temp_ocv_lut->temp[0])
- batt_temp_degc = chip->pc_temp_ocv_lut->temp[0];
- if (batt_temp_degc > chip->pc_temp_ocv_lut->temp[cols - 1])
- batt_temp_degc = chip->pc_temp_ocv_lut->temp[cols - 1];
-
- for (i = 0; i < cols; i++)
- if (batt_temp_degc <= chip->pc_temp_ocv_lut->temp[i])
- break;
- if (batt_temp_degc == chip->pc_temp_ocv_lut->temp[i]) {
- ocv = linear_interpolate(
- chip->pc_temp_ocv_lut->ocv[row1][i],
- chip->pc_temp_ocv_lut->percent[row1],
- chip->pc_temp_ocv_lut->ocv[row2][i],
- chip->pc_temp_ocv_lut->percent[row2],
- pc);
- return ocv;
- }
-
- ocvrow1 = linear_interpolate(
- chip->pc_temp_ocv_lut->ocv[row1][i - 1],
- chip->pc_temp_ocv_lut->temp[i - 1],
- chip->pc_temp_ocv_lut->ocv[row1][i],
- chip->pc_temp_ocv_lut->temp[i],
- batt_temp_degc);
-
- ocvrow2 = linear_interpolate(
- chip->pc_temp_ocv_lut->ocv[row2][i - 1],
- chip->pc_temp_ocv_lut->temp[i - 1],
- chip->pc_temp_ocv_lut->ocv[row2][i],
- chip->pc_temp_ocv_lut->temp[i],
- batt_temp_degc);
-
- ocv = linear_interpolate(
- ocvrow1,
- chip->pc_temp_ocv_lut->percent[row1],
- ocvrow2,
- chip->pc_temp_ocv_lut->percent[row2],
- pc);
-
- return ocv;
-}
-
-static int interpolate_pc(struct pm8921_bms_chip *chip,
- int batt_temp_degc, int ocv)
-{
- int i, j, pcj, pcj_minus_one, pc;
- int rows = chip->pc_temp_ocv_lut->rows;
- int cols = chip->pc_temp_ocv_lut->cols;
-
-
- if (batt_temp_degc < chip->pc_temp_ocv_lut->temp[0]) {
- pr_debug("batt_temp %d < known temp range\n", batt_temp_degc);
- batt_temp_degc = chip->pc_temp_ocv_lut->temp[0];
- }
- if (batt_temp_degc > chip->pc_temp_ocv_lut->temp[cols - 1]) {
- pr_debug("batt_temp %d > known temp range\n", batt_temp_degc);
- batt_temp_degc = chip->pc_temp_ocv_lut->temp[cols - 1];
- }
-
- for (j = 0; j < cols; j++)
- if (batt_temp_degc <= chip->pc_temp_ocv_lut->temp[j])
- break;
- if (batt_temp_degc == chip->pc_temp_ocv_lut->temp[j]) {
- /* found an exact match for temp in the table */
- if (ocv >= chip->pc_temp_ocv_lut->ocv[0][j])
- return chip->pc_temp_ocv_lut->percent[0];
- if (ocv <= chip->pc_temp_ocv_lut->ocv[rows - 1][j])
- return chip->pc_temp_ocv_lut->percent[rows - 1];
- for (i = 0; i < rows; i++) {
- if (ocv >= chip->pc_temp_ocv_lut->ocv[i][j]) {
- if (ocv == chip->pc_temp_ocv_lut->ocv[i][j])
- return
- chip->pc_temp_ocv_lut->percent[i];
- pc = linear_interpolate(
- chip->pc_temp_ocv_lut->percent[i],
- chip->pc_temp_ocv_lut->ocv[i][j],
- chip->pc_temp_ocv_lut->percent[i - 1],
- chip->pc_temp_ocv_lut->ocv[i - 1][j],
- ocv);
- return pc;
- }
- }
- }
-
- /*
- * batt_temp_degc is within temperature for
- * column j-1 and j
- */
- if (ocv >= chip->pc_temp_ocv_lut->ocv[0][j])
- return chip->pc_temp_ocv_lut->percent[0];
- if (ocv <= chip->pc_temp_ocv_lut->ocv[rows - 1][j - 1])
- return chip->pc_temp_ocv_lut->percent[rows - 1];
-
- pcj_minus_one = 0;
- pcj = 0;
- for (i = 0; i < rows-1; i++) {
- if (pcj == 0
- && is_between(chip->pc_temp_ocv_lut->ocv[i][j],
- chip->pc_temp_ocv_lut->ocv[i+1][j], ocv)) {
- pcj = linear_interpolate(
- chip->pc_temp_ocv_lut->percent[i],
- chip->pc_temp_ocv_lut->ocv[i][j],
- chip->pc_temp_ocv_lut->percent[i + 1],
- chip->pc_temp_ocv_lut->ocv[i+1][j],
- ocv);
- }
-
- if (pcj_minus_one == 0
- && is_between(chip->pc_temp_ocv_lut->ocv[i][j-1],
- chip->pc_temp_ocv_lut->ocv[i+1][j-1], ocv)) {
-
- pcj_minus_one = linear_interpolate(
- chip->pc_temp_ocv_lut->percent[i],
- chip->pc_temp_ocv_lut->ocv[i][j-1],
- chip->pc_temp_ocv_lut->percent[i + 1],
- chip->pc_temp_ocv_lut->ocv[i+1][j-1],
- ocv);
- }
-
- if (pcj && pcj_minus_one) {
- pc = linear_interpolate(
- pcj_minus_one,
- chip->pc_temp_ocv_lut->temp[j-1],
- pcj,
- chip->pc_temp_ocv_lut->temp[j],
- batt_temp_degc);
- return pc;
- }
- }
-
- if (pcj)
- return pcj;
-
- if (pcj_minus_one)
- return pcj_minus_one;
-
- pr_debug("%d ocv wasn't found for temp %d in the LUT returning 100%%",
- ocv, batt_temp_degc);
- return 100;
-}
-
#define BMS_MODE_BIT BIT(6)
#define EN_VBAT_BIT BIT(5)
#define OVERRIDE_MODE_DELAY_MS 20
@@ -1042,7 +706,7 @@
}
/* Convert the batt_temp to DegC from deciDegC */
batt_temp = batt_temp / 10;
- scalefactor = interpolate_scalingfactor(chip, chip->rbatt_sf_lut,
+ scalefactor = interpolate_scalingfactor(chip->rbatt_sf_lut,
batt_temp, soc_rbatt);
pr_debug("rbatt sf = %d for batt_temp = %d, soc_rbatt = %d\n",
scalefactor, batt_temp, soc_rbatt);
@@ -1069,16 +733,18 @@
int initfcc, result, scalefactor = 0;
if (chip->adjusted_fcc_temp_lut == NULL) {
- initfcc = interpolate_fcc(chip, batt_temp);
+ initfcc = interpolate_fcc(chip->fcc_temp_lut, batt_temp);
- scalefactor = interpolate_scalingfactor_fcc(chip, chargecycles);
+ scalefactor = interpolate_scalingfactor_fcc(chip->fcc_sf_lut,
+ chargecycles);
/* Multiply the initial FCC value by the scale factor. */
result = (initfcc * scalefactor * 1000) / 100;
pr_debug("fcc = %d uAh\n", result);
return result;
} else {
- return 1000 * interpolate_fcc_adjusted(chip, batt_temp);
+ return 1000 * interpolate_fcc(chip->adjusted_fcc_temp_lut,
+ batt_temp);
}
}
@@ -1120,17 +786,18 @@
return 0;
}
-static int calculate_pc(struct pm8921_bms_chip *chip, int ocv_uv, int batt_temp,
- int chargecycles)
+static int calculate_pc(struct pm8921_bms_chip *chip, int ocv_uv,
+ int batt_temp, int chargecycles)
{
int pc, scalefactor;
- pc = interpolate_pc(chip, batt_temp / 10, ocv_uv / 1000);
+ pc = interpolate_pc(chip->pc_temp_ocv_lut,
+ batt_temp / 10, ocv_uv / 1000);
pr_debug("pc = %u for ocv = %dmicroVolts batt_temp = %d\n",
pc, ocv_uv, batt_temp);
- scalefactor = interpolate_scalingfactor(chip,
- chip->pc_sf_lut, chargecycles, pc);
+ scalefactor = interpolate_scalingfactor(chip->pc_sf_lut,
+ chargecycles, pc);
pr_debug("scalefactor = %u batt_temp = %d\n", scalefactor, batt_temp);
/* Multiply the initial FCC value by the scale factor. */
@@ -1183,7 +850,8 @@
int uuc_rbatt_uv;
for (i = 0; i <= 100; i++) {
- ocv_mv = interpolate_ocv(chip, batt_temp_degc, i);
+ ocv_mv = interpolate_ocv(chip->pc_temp_ocv_lut,
+ batt_temp_degc, i);
rbatt_mohm = get_rbatt(chip, i, batt_temp);
unusable_uv = (rbatt_mohm * i_ma) + (chip->v_cutoff * 1000);
delta_uv = ocv_mv * 1000 - unusable_uv;
@@ -1239,8 +907,8 @@
new_uuc = (fcc_uah * chip->prev_pc_unusable) / 100;
/* also find update the iavg_ma accordingly */
- new_unusable_mv = interpolate_ocv(chip, batt_temp_degc,
- chip->prev_pc_unusable);
+ new_unusable_mv = interpolate_ocv(chip->pc_temp_ocv_lut,
+ batt_temp_degc, chip->prev_pc_unusable);
if (new_unusable_mv < chip->v_cutoff)
new_unusable_mv = chip->v_cutoff;
@@ -1531,11 +1199,11 @@
pc = DIV_ROUND_CLOSEST((int)rc * 100, fcc_uah);
pc = clamp(pc, 0, 100);
- ocv = interpolate_ocv(chip, batt_temp_degc, pc);
+ ocv = interpolate_ocv(chip->pc_temp_ocv_lut, batt_temp_degc, pc);
pr_debug("s_soc = %d, fcc = %d uuc = %d rc = %d, pc = %d, ocv mv = %d\n",
shutdown_soc, fcc_uah, uuc_uah, (int)rc, pc, ocv);
- new_pc = interpolate_pc(chip, batt_temp_degc, ocv);
+ new_pc = interpolate_pc(chip->pc_temp_ocv_lut, batt_temp_degc, ocv);
pr_debug("test revlookup pc = %d for ocv = %d\n", new_pc, ocv);
while (abs(new_pc - pc) > 1) {
@@ -1545,7 +1213,8 @@
delta_mv = -1 * delta_mv;
ocv = ocv + delta_mv;
- new_pc = interpolate_pc(chip, batt_temp_degc, ocv);
+ new_pc = interpolate_pc(chip->pc_temp_ocv_lut,
+ batt_temp_degc, ocv);
pr_debug("test revlookup pc = %d for ocv = %d\n", new_pc, ocv);
}
diff --git a/drivers/usb/gadget/android.c b/drivers/usb/gadget/android.c
index e3bfbd0..817bfbb 100644
--- a/drivers/usb/gadget/android.c
+++ b/drivers/usb/gadget/android.c
@@ -80,8 +80,10 @@
#ifdef CONFIG_TARGET_CORE
#include "f_tcm.c"
#endif
+#ifdef CONFIG_SND_PCM
#include "u_uac1.c"
#include "f_uac1.c"
+#endif
MODULE_AUTHOR("Mike Lockwood");
MODULE_DESCRIPTION("Android Composite USB Driver");
@@ -704,6 +706,7 @@
.init = mbim_function_init,
};
+#ifdef CONFIG_SND_PCM
/* PERIPHERAL AUDIO */
static int audio_function_bind_config(struct android_usb_function *f,
struct usb_configuration *c)
@@ -715,6 +718,7 @@
.name = "audio",
.bind_config = audio_function_bind_config,
};
+#endif
/* DIAG */
@@ -1520,7 +1524,9 @@
static struct android_usb_function *supported_functions[] = {
&mbim_function,
&ecm_qc_function,
+#ifdef CONFIG_SND_PCM
&audio_function,
+#endif
&rmnet_smd_function,
&rmnet_sdio_function,
&rmnet_smd_sdio_function,
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index a9f810f..8f4f4d5 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -303,6 +303,7 @@
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x5C, data);
}
+ mdss_dsi_sw_reset(pdata);
mdss_dsi_host_init(mipi, pdata);
if (mipi->force_clk_lane_hs) {
diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c
index 3abf4d0..125644e 100644
--- a/drivers/video/msm/mdss/mdss_dsi_host.c
+++ b/drivers/video/msm/mdss/mdss_dsi_host.c
@@ -813,6 +813,7 @@
void mdss_dsi_sw_reset(struct mdss_panel_data *pdata)
{
struct mdss_dsi_ctrl_pdata *ctrl_pdata = NULL;
+ u32 dsi_ctrl;
ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
panel_data);
@@ -821,6 +822,16 @@
return;
}
+ dsi_ctrl = MIPI_INP((ctrl_pdata->ctrl_base) + 0x0004);
+ dsi_ctrl &= ~0x01;
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x0004, dsi_ctrl);
+ wmb();
+
+ /* turn esc, byte, dsi, pclk, sclk, hclk on */
+ MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x11c,
+ 0x23f); /* DSI_CLK_CTRL */
+ wmb();
+
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x118, 0x01);
wmb();
MIPI_OUTP((ctrl_pdata->ctrl_base) + 0x118, 0x00);
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index b247e4d..fd52e1c 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -106,8 +106,6 @@
pr_debug("%s:%d, debug info (mode) : %d\n", __func__, __LINE__,
mipi->mode);
- mdss_dsi_sw_reset(pdata);
-
if (mipi->mode == DSI_VIDEO_MODE) {
mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf, dsi_panel_on_cmds,
num_of_on_cmds);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.c b/drivers/video/msm/mdss/mdss_hdmi_edid.c
index f720a2f..8db38d6 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_edid.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_edid.c
@@ -358,34 +358,25 @@
DEV_DBG("EDID: reading block(%d) with block-size=%d\n",
block, block_size);
for (i = 0; i < 0x80; i += block_size) {
- /*Read EDID twice with 32bit alighnment too */
- if (block < 2) {
- memset(&ddc_data, 0, sizeof(ddc_data));
- ddc_data.dev_addr = 0xA0;
- ddc_data.offset = block*0x80 + i;
- ddc_data.data_buf = edid_buf+i;
- ddc_data.data_len = block_size;
- ddc_data.retry = 1;
- ddc_data.what = "EDID";
- ddc_data.no_align = false;
+ memset(&ddc_data, 0, sizeof(ddc_data));
+ ddc_data.dev_addr = 0xA0;
+ ddc_data.offset = block*0x80 + i;
+ ddc_data.data_buf = edid_buf+i;
+ ddc_data.data_len = block_size;
+ ddc_data.request_len = block_size;
+ ddc_data.retry = 1;
+ ddc_data.what = "EDID";
+ ddc_data.no_align = false;
+ /*Read EDID twice with 32bit alighnment too */
+ if (block < 2)
status = hdmi_ddc_read(
edid_ctrl->init_data.ddc_ctrl,
&ddc_data);
- } else {
- memset(&ddc_data, 0, sizeof(ddc_data));
- ddc_data.dev_addr = 0xA0;
- ddc_data.offset = block*0x80 + i;
- ddc_data.data_buf = edid_buf+i;
- ddc_data.data_len = block_size;
- ddc_data.request_len = block_size;
- ddc_data.retry = 1;
- ddc_data.what = "EDID";
-
+ else
status = hdmi_ddc_read_seg(
edid_ctrl->init_data.ddc_ctrl,
&ddc_data);
- }
if (status)
break;
}
@@ -413,7 +404,7 @@
}
print_len = 0x80;
- for (ndx = 0; ndx < print_len; ndx += 16)
+ for (ndx = 0; ndx < print_len; ndx += 4)
DEV_DBG("EDID[%02x-%02x] %02x %02x %02x %02x\n",
ndx, ndx+3,
b[ndx+0], b[ndx+1], b[ndx+2], b[ndx+3]);
@@ -1392,7 +1383,7 @@
{
struct hdmi_edid_ctrl *edid_ctrl = NULL;
- if (!init_data || !init_data->base ||
+ if (!init_data || !init_data->io ||
!init_data->mutex || !init_data->sysfs_kobj ||
!init_data->ddc_ctrl) {
DEV_ERR("%s: invalid input\n", __func__);
diff --git a/drivers/video/msm/mdss/mdss_hdmi_edid.h b/drivers/video/msm/mdss/mdss_hdmi_edid.h
index d10ae49..5c51e7e 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_edid.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_edid.h
@@ -16,7 +16,7 @@
#include "mdss_hdmi_util.h"
struct hdmi_edid_init_data {
- void __iomem *base;
+ struct dss_io_data *io;
struct mutex *mutex;
struct kobject *sysfs_kobj;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.c b/drivers/video/msm/mdss/mdss_hdmi_tx.c
index 9278029..7f41221 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.c
@@ -12,7 +12,6 @@
*/
#include <linux/bitops.h>
-#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/mutex.h>
@@ -20,7 +19,7 @@
#include <linux/of_gpio.h>
#include <linux/types.h>
-/* #define DEBUG */
+#define REG_DUMP 0
#include "mdss_fb.h"
#include "mdss_hdmi_tx.h"
@@ -91,19 +90,19 @@
0x07, 0x07, 0x07, 0x07, 0x02, 0x02, 0x02} /*12*/
};
-static const char *hdmi_tx_clk_name(u32 clk)
+const char *hdmi_tx_pm_name(enum hdmi_tx_power_module_type module)
{
- switch (clk) {
- case HDMI_TX_AHB_CLK: return "hdmi_ahb_clk";
- case HDMI_TX_APP_CLK: return "hdmi_app_clk";
- case HDMI_TX_EXTP_CLK: return "hdmi_extp_clk";
- default: return "???";
+ switch (module) {
+ case HDMI_TX_HPD_PM: return "HDMI_TX_HPD_PM";
+ case HDMI_TX_CORE_PM: return "HDMI_TX_CORE_PM";
+ case HDMI_TX_CEC_PM: return "HDMI_TX_CEC_PM";
+ default: return "???";
}
-} /* hdmi_tx_clk_name */
+} /* hdmi_tx_pm_name */
-static const char *hdmi_tx_io_name(u32 io)
+static const char *hdmi_tx_io_name(u32 type)
{
- switch (io) {
+ switch (type) {
case HDMI_TX_CORE_IO: return "core_physical";
case HDMI_TX_PHY_IO: return "phy_physical";
case HDMI_TX_QFPROM_IO: return "qfprom_physical";
@@ -190,75 +189,6 @@
return ret;
} /* hdmi_tx_sysfs_rda_connected */
-static ssize_t hdmi_tx_sysfs_rda_fake_hpd(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- ssize_t ret;
- struct hdmi_tx_ctrl *hdmi_ctrl =
- hdmi_tx_get_drvdata_from_sysfs_dev(dev);
-
- if (!hdmi_ctrl) {
- DEV_ERR("%s: invalid input\n", __func__);
- return -EINVAL;
- }
-
- mutex_lock(&hdmi_ctrl->mutex);
- ret = snprintf(buf, PAGE_SIZE, "%d\n", hdmi_ctrl->hpd_state);
- DEV_DBG("%s: '%d'\n", __func__, hdmi_ctrl->hpd_state);
- mutex_unlock(&hdmi_ctrl->mutex);
-
- return ret;
-} /* hdmi_tx_sysfs_rda_fake_hpd */
-
-static ssize_t hdmi_tx_sysfs_wta_fake_hpd(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- int fake_hpd, rc = 0;
- ssize_t ret = strnlen(buf, PAGE_SIZE);
- struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
-
- DEV_DBG("%s:\n", __func__);
- hdmi_ctrl = hdmi_tx_get_drvdata_from_sysfs_dev(dev);
-
- if (!hdmi_ctrl) {
- DEV_ERR("%s: invalid input\n", __func__);
- return -EINVAL;
- }
-
- rc = kstrtoint(buf, 10, &fake_hpd);
- if (rc) {
- DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc);
- return rc;
- }
-
- mutex_lock(&hdmi_ctrl->mutex);
- DEV_INFO("%s: fake_hpd=%d\n", __func__, fake_hpd);
- if (fake_hpd) {
- hdmi_ctrl->hpd_state = true;
-
- /* todo: Remove this once HPD line is available in HW */
- DEV_INFO("HDMI HPD: sense CONNECTED: send ONLINE\n");
- if (kobject_uevent(hdmi_ctrl->kobj, KOBJ_ONLINE))
- DEV_ERR("%s: failed sending online event\n", __func__);
- switch_set_state(&hdmi_ctrl->sdev, 1);
- DEV_INFO("%s: Hdmi state switch to %d\n", __func__,
- hdmi_ctrl->sdev.state);
- } else {
- hdmi_ctrl->hpd_state = false;
-
- /* todo: Remove this once HPD line is available in HW */
- DEV_INFO("HDMI HPD: sense CONNECTED: send ONLINE\n");
- if (kobject_uevent(hdmi_ctrl->kobj, KOBJ_OFFLINE))
- DEV_ERR("%s: failed sending online event\n", __func__);
- switch_set_state(&hdmi_ctrl->sdev, 0);
- DEV_INFO("%s: Hdmi state switch to %d\n", __func__,
- hdmi_ctrl->sdev.state);
- }
- mutex_unlock(&hdmi_ctrl->mutex);
-
- return ret;
-} /* hdmi_tx_sysfs_wta_fake_hpd */
-
static ssize_t hdmi_tx_sysfs_rda_hpd(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -298,16 +228,13 @@
return rc;
}
- /* todo: Remove this once HPD line is available in HW */
- if (0) {
- if (0 == hpd && hdmi_ctrl->hpd_feature_on) {
- rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, false);
- } else if (1 == hpd && !hdmi_ctrl->hpd_feature_on) {
- rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, true);
- } else {
- rc = -EPERM;
- ret = rc;
- }
+ if (0 == hpd && hdmi_ctrl->hpd_feature_on) {
+ rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, false);
+ } else if (1 == hpd && !hdmi_ctrl->hpd_feature_on) {
+ rc = hdmi_tx_sysfs_enable_hpd(hdmi_ctrl, true);
+ } else {
+ rc = -EPERM;
+ ret = rc;
}
if (!rc) {
@@ -325,13 +252,10 @@
static DEVICE_ATTR(connected, S_IRUGO, hdmi_tx_sysfs_rda_connected, NULL);
static DEVICE_ATTR(hpd, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_hpd,
hdmi_tx_sysfs_wta_hpd);
-static DEVICE_ATTR(fake_hpd, S_IRUGO | S_IWUSR, hdmi_tx_sysfs_rda_fake_hpd,
- hdmi_tx_sysfs_wta_fake_hpd);
static struct attribute *hdmi_tx_fs_attrs[] = {
&dev_attr_connected.attr,
&dev_attr_hpd.attr,
- &dev_attr_fake_hpd.attr,
NULL,
};
static struct attribute_group hdmi_tx_fs_attrs_group = {
@@ -385,7 +309,7 @@
return -EINVAL;
}
- edid_init_data.base = hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base;
+ edid_init_data.io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
edid_init_data.mutex = &hdmi_ctrl->mutex;
edid_init_data.sysfs_kobj = hdmi_ctrl->kobj;
edid_init_data.ddc_ctrl = &hdmi_ctrl->ddc_ctrl;
@@ -405,14 +329,14 @@
static inline u32 hdmi_tx_is_controller_on(struct hdmi_tx_ctrl *hdmi_ctrl)
{
- return HDMI_REG_R_ND(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base,
- HDMI_CTRL) & BIT(0);
+ struct dss_io_data *io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+ return DSS_REG_R_ND(io, HDMI_CTRL) & BIT(0);
} /* hdmi_tx_is_controller_on */
static inline u32 hdmi_tx_is_dvi_mode(struct hdmi_tx_ctrl *hdmi_ctrl)
{
- return !(HDMI_REG_R_ND(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base,
- HDMI_CTRL) & BIT(1));
+ struct dss_io_data *io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+ return !(DSS_REG_R_ND(io, HDMI_CTRL) & BIT(1));
} /* hdmi_tx_is_dvi_mode */
static int hdmi_tx_init_panel_info(uint32_t resolution,
@@ -473,44 +397,6 @@
hdmi_set_supported_mode(HDMI_VFRMT_1920x1080p60_16_9);
} /* hdmi_tx_setup_video_mode_lut */
-static inline struct clk *hdmi_tx_get_clk(struct hdmi_tx_platform_data *pdata,
- u32 clk_idx)
-{
- if (!pdata || clk_idx > HDMI_TX_MAX_CLK) {
- DEV_ERR("%s: invalid input\n", __func__);
- return NULL;
- }
-
- return pdata->clk[clk_idx];
-} /* hdmi_tx_get_clk */
-
-static int hdmi_tx_clk_set_rate(struct hdmi_tx_platform_data *pdata,
- u32 clk_idx, unsigned long clk_rate)
-{
- int rc = 0;
- struct clk *clk = NULL;
-
- if (!pdata) {
- DEV_ERR("%s: invalid input\n", __func__);
- return -EINVAL;
- }
-
- clk = hdmi_tx_get_clk(pdata, clk_idx);
- if (clk) {
- rc = clk_set_rate(clk, clk_rate);
- if (IS_ERR_VALUE(rc))
- DEV_ERR("%s: failed rc=%d\n", __func__, rc);
- else
- DEV_DBG("%s: name='%s' rate=%lu\n", __func__,
- hdmi_tx_clk_name(clk_idx), clk_rate);
- } else {
- DEV_ERR("%s: FAILED: invalid clk_idx=%d\n", __func__, clk_idx);
- rc = -EINVAL;
- }
-
- return rc;
-} /* hdmi_tx_clk_set_rate */
-
static int hdmi_tx_read_sink_info(struct hdmi_tx_ctrl *hdmi_ctrl)
{
int status;
@@ -551,9 +437,14 @@
}
io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+ if (!io->base) {
+ DEV_ERR("%s: Core io is not initialized\n", __func__);
+ return;
+ }
+
DEV_DBG("%s: Got HPD interrupt\n", __func__);
- hpd_state = (HDMI_REG_R(io->base, HDMI_HPD_INT_STATUS) & BIT(1)) >> 1;
+ hpd_state = (DSS_REG_R(io, HDMI_HPD_INT_STATUS) & BIT(1)) >> 1;
mutex_lock(&hdmi_ctrl->mutex);
if ((hdmi_ctrl->hpd_prev_state != hdmi_ctrl->hpd_state) ||
(hdmi_ctrl->hpd_state != hpd_state)) {
@@ -605,22 +496,62 @@
}
/* Set IRQ for HPD */
- HDMI_REG_W(io->base, HDMI_HPD_INT_CTRL, 4 | (hpd_state ? 0 : 2));
+ DSS_REG_W(io, HDMI_HPD_INT_CTRL, 4 | (hpd_state ? 0 : 2));
} /* hdmi_tx_hpd_state_work */
-static int hdmi_tx_check_capability(void __iomem *base)
+static void hdmi_tx_hpd_int_work(struct work_struct *work)
+{
+ u32 hpd_int_status;
+ u32 hpd_int_ctrl;
+ u32 cable_detected;
+ struct hdmi_tx_ctrl *hdmi_ctrl = NULL;
+ struct dss_io_data *io = NULL;
+
+ hdmi_ctrl = container_of(work, struct hdmi_tx_ctrl, hpd_int_work);
+ if (!hdmi_ctrl || !hdmi_ctrl->hpd_initialized) {
+ DEV_DBG("%s: invalid input\n", __func__);
+ return;
+ }
+
+ io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+ if (!io->base) {
+ DEV_ERR("%s: Core io is not initialized\n", __func__);
+ return;
+ }
+
+ /* Process HPD Interrupt */
+ hpd_int_status = DSS_REG_R(io, HDMI_HPD_INT_STATUS);
+ hpd_int_ctrl = DSS_REG_R(io, HDMI_HPD_INT_CTRL);
+
+ DSS_REG_W(io, HDMI_HPD_INT_CTRL, BIT(2));
+
+ cable_detected = hpd_int_status & BIT(1);
+ mutex_lock(&hdmi_ctrl->mutex);
+ hdmi_ctrl->hpd_cable_chg_detected = true;
+ hdmi_ctrl->hpd_prev_state = cable_detected ? 0 : 1;
+ hdmi_ctrl->hpd_stable = 0;
+ mutex_unlock(&hdmi_ctrl->mutex);
+
+ mod_timer(&hdmi_ctrl->hpd_state_timer, jiffies + HZ/2);
+
+ DEV_DBG("%s: HPD<Ctrl=%04x, State=%04x>\n", __func__, hpd_int_ctrl,
+ hpd_int_status);
+} /* hdmi_tx_hpd_int_work */
+
+static int hdmi_tx_check_capability(struct dss_io_data *io)
{
u32 hdmi_disabled, hdcp_disabled;
- if (!base) {
+ if (!io) {
DEV_ERR("%s: invalid input\n", __func__);
return -EINVAL;
}
- /* QFPROM_RAW_FEAT_CONFIG_ROW0_LSB */
- hdcp_disabled = HDMI_REG_R_ND(base, 0x000000F8) & BIT(31);
- /* QFPROM_RAW_FEAT_CONFIG_ROW0_MSB */
- hdmi_disabled = HDMI_REG_R_ND(base, 0x000000FC) & BIT(0);
+ hdcp_disabled = DSS_REG_R_ND(io,
+ QFPROM_RAW_FEAT_CONFIG_ROW0_LSB) & BIT(31);
+
+ hdmi_disabled = DSS_REG_R_ND(io,
+ QFPROM_RAW_FEAT_CONFIG_ROW0_MSB) & BIT(0);
DEV_DBG("%s: Features <HDMI:%s, HDCP:%s>\n", __func__,
hdmi_disabled ? "OFF" : "ON", hdcp_disabled ? "OFF" : "ON");
@@ -710,25 +641,9 @@
goto end;
}
- /*
- * extpclk is driven by hdmi phy pll. This phy pll programming requires
- * hdmi_ahb_clk. So enable it and then disable.
- */
- rc = clk_prepare_enable(pdata->clk[HDMI_TX_AHB_CLK]);
- if (rc) {
- DEV_ERR("%s: failed to enable '%s' clk\n", __func__,
- hdmi_tx_clk_name(HDMI_TX_AHB_CLK));
- goto end;
- }
- rc = hdmi_tx_clk_set_rate(pdata, HDMI_TX_EXTP_CLK,
- timing->pixel_freq * 1000);
- if (rc) {
- DEV_ERR("%s: FAILED: '%s' clk set rate\n", __func__,
- hdmi_tx_clk_name(HDMI_TX_EXTP_CLK));
- clk_disable_unprepare(pdata->clk[HDMI_TX_AHB_CLK]);
- goto end;
- }
- clk_disable_unprepare(pdata->clk[HDMI_TX_AHB_CLK]);
+ /* todo: find a better way */
+ hdmi_ctrl->pdata.power_data[HDMI_TX_CORE_PM].clk_config[0].rate =
+ timing->pixel_freq * 1000;
hdmi_ctrl->video_resolution = format;
hdmi_edid_set_video_resolution(
@@ -772,35 +687,35 @@
timing->back_porch_h + timing->pulse_width_h - 1;
total_v = timing->active_v + timing->front_porch_v +
timing->back_porch_v + timing->pulse_width_v - 1;
- HDMI_REG_W(io->base, HDMI_TOTAL,
+ DSS_REG_W(io, HDMI_TOTAL,
((total_v << 16) & 0x0FFF0000) |
((total_h << 0) & 0x00000FFF));
start_h = timing->back_porch_h + timing->pulse_width_h;
end_h = (total_h + 1) - timing->front_porch_h;
- HDMI_REG_W(io->base, HDMI_ACTIVE_H,
+ DSS_REG_W(io, HDMI_ACTIVE_H,
((end_h << 16) & 0x0FFF0000) |
((start_h << 0) & 0x00000FFF));
start_v = timing->back_porch_v + timing->pulse_width_v - 1;
end_v = total_v - timing->front_porch_v;
- HDMI_REG_W(io->base, HDMI_ACTIVE_V,
+ DSS_REG_W(io, HDMI_ACTIVE_V,
((end_v << 16) & 0x0FFF0000) |
((start_v << 0) & 0x00000FFF));
if (timing->interlaced) {
- HDMI_REG_W(io->base, HDMI_V_TOTAL_F2,
+ DSS_REG_W(io, HDMI_V_TOTAL_F2,
((total_v + 1) << 0) & 0x00000FFF);
- HDMI_REG_W(io->base, HDMI_ACTIVE_V_F2,
+ DSS_REG_W(io, HDMI_ACTIVE_V_F2,
(((start_v + 1) << 0) & 0x00000FFF) |
(((end_v + 1) << 16) & 0x0FFF0000));
} else {
- HDMI_REG_W(io->base, HDMI_V_TOTAL_F2, 0);
- HDMI_REG_W(io->base, HDMI_ACTIVE_V_F2, 0);
+ DSS_REG_W(io, HDMI_V_TOTAL_F2, 0);
+ DSS_REG_W(io, HDMI_ACTIVE_V_F2, 0);
}
- HDMI_REG_W(io->base, HDMI_FRAME_CTRL,
+ DSS_REG_W(io, HDMI_FRAME_CTRL,
((timing->interlaced << 31) & 0x80000000) |
((timing->active_low_h << 29) & 0x20000000) |
((timing->active_low_v << 28) & 0x10000000));
@@ -929,28 +844,28 @@
regVal = regVal << 8 | avi_iframe[4];
regVal = regVal << 8 | avi_iframe[3];
regVal = regVal << 8 | checksum;
- HDMI_REG_W(io->base, HDMI_AVI_INFO0, regVal);
+ DSS_REG_W(io, HDMI_AVI_INFO0, regVal);
regVal = avi_iframe[9];
regVal = regVal << 8 | avi_iframe[8];
regVal = regVal << 8 | avi_iframe[7];
regVal = regVal << 8 | avi_iframe[6];
- HDMI_REG_W(io->base, HDMI_AVI_INFO1, regVal);
+ DSS_REG_W(io, HDMI_AVI_INFO1, regVal);
regVal = avi_iframe[13];
regVal = regVal << 8 | avi_iframe[12];
regVal = regVal << 8 | avi_iframe[11];
regVal = regVal << 8 | avi_iframe[10];
- HDMI_REG_W(io->base, HDMI_AVI_INFO2, regVal);
+ DSS_REG_W(io, HDMI_AVI_INFO2, regVal);
regVal = avi_iframe[1];
regVal = regVal << 16 | avi_iframe[15];
regVal = regVal << 8 | avi_iframe[14];
- HDMI_REG_W(io->base, HDMI_AVI_INFO3, regVal);
+ DSS_REG_W(io, HDMI_AVI_INFO3, regVal);
/* 0x3 for AVI InfFrame enable (every frame) */
- HDMI_REG_W(io->base, HDMI_INFOFRAME_CTRL0,
- HDMI_REG_R(io->base, HDMI_INFOFRAME_CTRL0) |
+ DSS_REG_W(io, HDMI_INFOFRAME_CTRL0,
+ DSS_REG_R(io, HDMI_INFOFRAME_CTRL0) |
0x00000003L);
} /* hdmi_tx_set_avi_infoframe */
@@ -986,14 +901,14 @@
* 0x19 Length of Source Product Description InfoFrame
*/
packet_header = 0x83 | (0x01 << 8) | (0x19 << 16);
- HDMI_REG_W(io->base, HDMI_GENERIC1_HDR, packet_header);
+ DSS_REG_W(io, HDMI_GENERIC1_HDR, packet_header);
check_sum += IFRAME_CHECKSUM_32(packet_header);
packet_payload = (vendor_name[3] & 0x7f)
| ((vendor_name[4] & 0x7f) << 8)
| ((vendor_name[5] & 0x7f) << 16)
| ((vendor_name[6] & 0x7f) << 24);
- HDMI_REG_W(io->base, HDMI_GENERIC1_1, packet_payload);
+ DSS_REG_W(io, HDMI_GENERIC1_1, packet_payload);
check_sum += IFRAME_CHECKSUM_32(packet_payload);
/* Product Description (7-bit ASCII code) */
@@ -1001,28 +916,28 @@
| ((product_description[0] & 0x7f) << 8)
| ((product_description[1] & 0x7f) << 16)
| ((product_description[2] & 0x7f) << 24);
- HDMI_REG_W(io->base, HDMI_GENERIC1_2, packet_payload);
+ DSS_REG_W(io, HDMI_GENERIC1_2, packet_payload);
check_sum += IFRAME_CHECKSUM_32(packet_payload);
packet_payload = (product_description[3] & 0x7f)
| ((product_description[4] & 0x7f) << 8)
| ((product_description[5] & 0x7f) << 16)
| ((product_description[6] & 0x7f) << 24);
- HDMI_REG_W(io->base, HDMI_GENERIC1_3, packet_payload);
+ DSS_REG_W(io, HDMI_GENERIC1_3, packet_payload);
check_sum += IFRAME_CHECKSUM_32(packet_payload);
packet_payload = (product_description[7] & 0x7f)
| ((product_description[8] & 0x7f) << 8)
| ((product_description[9] & 0x7f) << 16)
| ((product_description[10] & 0x7f) << 24);
- HDMI_REG_W(io->base, HDMI_GENERIC1_4, packet_payload);
+ DSS_REG_W(io, HDMI_GENERIC1_4, packet_payload);
check_sum += IFRAME_CHECKSUM_32(packet_payload);
packet_payload = (product_description[11] & 0x7f)
| ((product_description[12] & 0x7f) << 8)
| ((product_description[13] & 0x7f) << 16)
| ((product_description[14] & 0x7f) << 24);
- HDMI_REG_W(io->base, HDMI_GENERIC1_5, packet_payload);
+ DSS_REG_W(io, HDMI_GENERIC1_5, packet_payload);
check_sum += IFRAME_CHECKSUM_32(packet_payload);
/*
@@ -1039,7 +954,7 @@
* 09h PC general
*/
packet_payload = (product_description[15] & 0x7f) | 0x00 << 8;
- HDMI_REG_W(io->base, HDMI_GENERIC1_6, packet_payload);
+ DSS_REG_W(io, HDMI_GENERIC1_6, packet_payload);
check_sum += IFRAME_CHECKSUM_32(packet_payload);
/* Vendor Name (7bit ASCII code) */
@@ -1048,7 +963,7 @@
| ((vendor_name[2] & 0x7f) << 24);
check_sum += IFRAME_CHECKSUM_32(packet_payload);
packet_payload |= ((0x100 - (0xff & check_sum)) & 0xff);
- HDMI_REG_W(io->base, HDMI_GENERIC1_0, packet_payload);
+ DSS_REG_W(io, HDMI_GENERIC1_0, packet_payload);
/*
* GENERIC1_LINE | GENERIC1_CONT | GENERIC1_SEND
@@ -1056,9 +971,9 @@
* Enable this packet to transmit every frame
* Enable HDMI TX engine to transmit Generic packet 1
*/
- packet_control = HDMI_REG_R_ND(io->base, HDMI_GEN_PKT_CTRL);
+ packet_control = DSS_REG_R_ND(io, HDMI_GEN_PKT_CTRL);
packet_control |= ((0x1 << 24) | (1 << 5) | (1 << 4));
- HDMI_REG_W(io->base, HDMI_GEN_PKT_CTRL, packet_control);
+ DSS_REG_W(io, HDMI_GEN_PKT_CTRL, packet_control);
} /* hdmi_tx_set_spd_infoframe */
/* todo: revisit when new HPD debouncing logic is avialble */
@@ -1075,11 +990,17 @@
static void hdmi_tx_set_mode(struct hdmi_tx_ctrl *hdmi_ctrl, u32 power_on)
{
u32 reg_val = 0;
+ struct dss_io_data *io = NULL;
if (!hdmi_ctrl) {
DEV_ERR("%s: invalid input\n", __func__);
return;
}
+ io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+ if (!io->base) {
+ DEV_ERR("%s: Core io is not initialized\n", __func__);
+ return;
+ }
if (power_on) {
/* ENABLE */
@@ -1101,77 +1022,12 @@
reg_val = BIT(1);
}
- HDMI_REG_W(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base, HDMI_CTRL,
- reg_val);
+ DSS_REG_W(io, HDMI_CTRL, reg_val);
DEV_DBG("HDMI Core: %s, HDMI_CTRL=0x%08x\n",
power_on ? "Enable" : "Disable", reg_val);
} /* hdmi_tx_set_mode */
-static int hdmi_tx_clk_update(struct hdmi_tx_platform_data *pdata, u32 clk_idx,
- u32 enable)
-{
- int rc = 0;
- struct clk *clk = hdmi_tx_get_clk(pdata, clk_idx);
-
- if (clk) {
- DEV_DBG("%s: clk=%d en=%d\n", __func__, clk_idx, enable);
- if (enable) {
- rc = clk_prepare_enable(clk);
- if (rc)
- DEV_ERR("%s: clk=%d enable failed\n",
- __func__, clk_idx);
- } else {
- clk_disable_unprepare(clk);
- }
- } else {
- DEV_ERR("%s: FAILED: invalid input for clk='%s'\n", __func__,
- hdmi_tx_clk_name(clk_idx));
- rc = -EINVAL;
- }
-
- return rc;
-} /* hdmi_tx_clk_update */
-
-/* Note: Before accessing extpclk, always make sure that hdmi_ahb_clk is on */
-static int hdmi_tx_clk_ctrl_update(struct hdmi_tx_platform_data *pdata, int on)
-{
- int rc = 0;
- DEV_DBG("%s: HDMI Clk: %s\n", __func__, on ? "Enable" : "Disable");
-
- rc = hdmi_tx_clk_update(pdata, HDMI_TX_APP_CLK, on);
- if (on && rc) {
- DEV_ERR("%s: '%s' on failed\n", __func__,
- hdmi_tx_clk_name(HDMI_TX_APP_CLK));
- goto fail_hdmi_app_clk;
- }
- if (on) {
- rc = hdmi_tx_clk_update(pdata, HDMI_TX_AHB_CLK, on);
- if (rc) {
- DEV_ERR("%s: '%s' on failed\n", __func__,
- hdmi_tx_clk_name(HDMI_TX_AHB_CLK));
- goto fail_hdmi_ahb_clk;
- }
- rc = hdmi_tx_clk_update(pdata, HDMI_TX_EXTP_CLK, on);
- if (rc) {
- DEV_ERR("%s: '%s' on failed\n", __func__,
- hdmi_tx_clk_name(HDMI_TX_EXTP_CLK));
- goto fail_hdmi_extp_clk;
- }
- } else {
- hdmi_tx_clk_update(pdata, HDMI_TX_EXTP_CLK, on);
- hdmi_tx_clk_update(pdata, HDMI_TX_AHB_CLK, on);
- }
- return rc;
-
-fail_hdmi_extp_clk:
- hdmi_tx_clk_update(pdata, HDMI_TX_AHB_CLK, 0);
-fail_hdmi_ahb_clk:
- hdmi_tx_clk_update(pdata, HDMI_TX_APP_CLK, 0);
-fail_hdmi_app_clk:
- return rc;
-} /* hdmi_tx_clk_ctrl_update */
-
static int hdmi_tx_config_power(struct hdmi_tx_ctrl *hdmi_ctrl,
enum hdmi_tx_power_module_type module, int config)
{
@@ -1191,17 +1047,33 @@
goto exit;
}
- if (config)
+ if (config) {
rc = msm_dss_config_vreg(&hdmi_ctrl->pdev->dev,
power_data->vreg_config, power_data->num_vreg, 1);
- else
+ if (rc) {
+ DEV_ERR("%s: Failed to config %s vreg. Err=%d\n",
+ __func__, hdmi_tx_pm_name(module), rc);
+ goto exit;
+ }
+
+ rc = msm_dss_get_clk(&hdmi_ctrl->pdev->dev,
+ power_data->clk_config, power_data->num_clk);
+ if (rc) {
+ DEV_ERR("%s: Failed to get %s clk. Err=%d\n",
+ __func__, hdmi_tx_pm_name(module), rc);
+
+ msm_dss_config_vreg(&hdmi_ctrl->pdev->dev,
+ power_data->vreg_config, power_data->num_vreg, 0);
+ }
+ } else {
+ msm_dss_put_clk(power_data->clk_config, power_data->num_clk);
+
rc = msm_dss_config_vreg(&hdmi_ctrl->pdev->dev,
power_data->vreg_config, power_data->num_vreg, 0);
-
- if (rc)
- DEV_ERR("%s: Failed to %s %s vreg. Error=%d\n",
- __func__, config ? "config" : "deconfig",
- hdmi_pm_name(module), rc);
+ if (rc)
+ DEV_ERR("%s: Fail to deconfig %s vreg. Err=%d\n",
+ __func__, hdmi_tx_pm_name(module), rc);
+ }
exit:
return rc;
@@ -1231,18 +1103,36 @@
power_data->num_vreg, 1);
if (rc) {
DEV_ERR("%s: Failed to enable %s vreg. Error=%d\n",
- __func__, hdmi_pm_name(module), rc);
+ __func__, hdmi_tx_pm_name(module), rc);
goto error;
}
rc = msm_dss_enable_gpio(power_data->gpio_config,
- power_data->num_gpio, enable);
+ power_data->num_gpio, 1);
if (rc) {
DEV_ERR("%s: Failed to enable %s gpio. Error=%d\n",
- __func__, hdmi_pm_name(module), rc);
+ __func__, hdmi_tx_pm_name(module), rc);
goto disable_vreg;
}
+
+ rc = msm_dss_clk_set_rate(power_data->clk_config,
+ power_data->num_clk);
+ if (rc) {
+ DEV_ERR("%s: failed to set clks rate for %s. err=%d\n",
+ __func__, hdmi_tx_pm_name(module), rc);
+ goto disable_gpio;
+ }
+
+ rc = msm_dss_enable_clk(power_data->clk_config,
+ power_data->num_clk, 1);
+ if (rc) {
+ DEV_ERR("%s: Failed to enable clks for %s. Error=%d\n",
+ __func__, hdmi_tx_pm_name(module), rc);
+ goto disable_gpio;
+ }
} else {
+ msm_dss_enable_clk(power_data->clk_config,
+ power_data->num_clk, 0);
msm_dss_enable_gpio(power_data->gpio_config,
power_data->num_gpio, 0);
msm_dss_enable_vreg(power_data->vreg_config,
@@ -1251,6 +1141,8 @@
return rc;
+disable_gpio:
+ msm_dss_enable_gpio(power_data->gpio_config, power_data->num_gpio, 0);
disable_vreg:
msm_dss_enable_vreg(power_data->vreg_config, power_data->num_vreg, 0);
error:
@@ -1281,7 +1173,7 @@
if (rc) {
DEV_ERR("%s: core hdmi_msm_enable_power failed rc = %d\n",
__func__, rc);
- goto error;
+ goto disable_hpd_power;
}
rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_CEC_PM, 1);
if (rc) {
@@ -1293,7 +1185,8 @@
return rc;
disable_core_power:
hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_CORE_PM, 0);
-error:
+disable_hpd_power:
+ hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_HPD_PM, 0);
return rc;
} /* hdmi_tx_core_on */
@@ -1311,36 +1204,34 @@
io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
if (!io->base) {
- DEV_ERR("%s: io not inititalized\n", __func__);
+ DEV_ERR("%s: core io not inititalized\n", __func__);
return;
}
- val = HDMI_REG_R_ND(io->base, HDMI_PHY_CTRL);
+ val = DSS_REG_R_ND(io, HDMI_PHY_CTRL);
phy_reset_polarity = val >> 3 & 0x1;
pll_reset_polarity = val >> 1 & 0x1;
if (phy_reset_polarity == 0)
- HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val | SW_RESET);
+ DSS_REG_W_ND(io, HDMI_PHY_CTRL, val | SW_RESET);
else
- HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val & (~SW_RESET));
+ DSS_REG_W_ND(io, HDMI_PHY_CTRL, val & (~SW_RESET));
if (pll_reset_polarity == 0)
- HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val | SW_RESET_PLL);
+ DSS_REG_W_ND(io, HDMI_PHY_CTRL, val | SW_RESET_PLL);
else
- HDMI_REG_W_ND(io->base,
- HDMI_PHY_CTRL, val & (~SW_RESET_PLL));
+ DSS_REG_W_ND(io, HDMI_PHY_CTRL, val & (~SW_RESET_PLL));
if (phy_reset_polarity == 0)
- HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val & (~SW_RESET));
+ DSS_REG_W_ND(io, HDMI_PHY_CTRL, val & (~SW_RESET));
else
- HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val | SW_RESET);
+ DSS_REG_W_ND(io, HDMI_PHY_CTRL, val | SW_RESET);
if (pll_reset_polarity == 0)
- HDMI_REG_W_ND(io->base,
- HDMI_PHY_CTRL, val & (~SW_RESET_PLL));
+ DSS_REG_W_ND(io, HDMI_PHY_CTRL, val & (~SW_RESET_PLL));
else
- HDMI_REG_W_ND(io->base, HDMI_PHY_CTRL, val | SW_RESET_PLL);
+ DSS_REG_W_ND(io, HDMI_PHY_CTRL, val | SW_RESET_PLL);
} /* hdmi_tx_phy_reset */
static void hdmi_tx_init_phy(struct hdmi_tx_ctrl *hdmi_ctrl)
@@ -1354,55 +1245,58 @@
io = &hdmi_ctrl->pdata.io[HDMI_TX_PHY_IO];
if (!io->base) {
- DEV_ERR("%s: Core io is not initialized\n", __func__);
+ DEV_ERR("%s: phy io is not initialized\n", __func__);
return;
}
- HDMI_REG_W_ND(io->base, HDMI_PHY_ANA_CFG0, 0x1B);
- HDMI_REG_W_ND(io->base, HDMI_PHY_ANA_CFG1, 0xF2);
- HDMI_REG_W_ND(io->base, HDMI_PHY_BIST_CFG0, 0x0);
- HDMI_REG_W_ND(io->base, HDMI_PHY_BIST_PATN0, 0x0);
- HDMI_REG_W_ND(io->base, HDMI_PHY_BIST_PATN1, 0x0);
- HDMI_REG_W_ND(io->base, HDMI_PHY_BIST_PATN2, 0x0);
- HDMI_REG_W_ND(io->base, HDMI_PHY_BIST_PATN3, 0x0);
+ DSS_REG_W_ND(io, HDMI_PHY_ANA_CFG0, 0x1B);
+ DSS_REG_W_ND(io, HDMI_PHY_ANA_CFG1, 0xF2);
+ DSS_REG_W_ND(io, HDMI_PHY_BIST_CFG0, 0x0);
+ DSS_REG_W_ND(io, HDMI_PHY_BIST_PATN0, 0x0);
+ DSS_REG_W_ND(io, HDMI_PHY_BIST_PATN1, 0x0);
+ DSS_REG_W_ND(io, HDMI_PHY_BIST_PATN2, 0x0);
+ DSS_REG_W_ND(io, HDMI_PHY_BIST_PATN3, 0x0);
- HDMI_REG_W_ND(io->base, HDMI_PHY_PD_CTRL1, 0x20);
+ DSS_REG_W_ND(io, HDMI_PHY_PD_CTRL1, 0x20);
} /* hdmi_tx_init_phy */
static void hdmi_tx_powerdown_phy(struct hdmi_tx_ctrl *hdmi_ctrl)
{
+ struct dss_io_data *io = NULL;
+
if (!hdmi_ctrl) {
DEV_ERR("%s: invalid input\n", __func__);
return;
}
+ io = &hdmi_ctrl->pdata.io[HDMI_TX_PHY_IO];
+ if (!io->base) {
+ DEV_ERR("%s: phy io is not initialized\n", __func__);
+ return;
+ }
- HDMI_REG_W_ND(hdmi_ctrl->pdata.io[HDMI_TX_PHY_IO].base,
- HDMI_PHY_PD_CTRL0, 0x7F);
+ DSS_REG_W_ND(io, HDMI_PHY_PD_CTRL0, 0x7F);
} /* hdmi_tx_powerdown_phy */
static int hdmi_tx_start(struct hdmi_tx_ctrl *hdmi_ctrl)
{
int rc = 0;
+ struct dss_io_data *io = NULL;
if (!hdmi_ctrl) {
DEV_ERR("%s: invalid input\n", __func__);
return -EINVAL;
}
+ io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+ if (!io->base) {
+ DEV_ERR("%s: core io is not initialized\n", __func__);
+ return -EINVAL;
+ }
+
/* todo: Audio */
hdmi_tx_set_mode(hdmi_ctrl, false);
- mutex_lock(&hdmi_ctrl->mutex);
- rc = hdmi_tx_clk_ctrl_update(&hdmi_ctrl->pdata, 1);
- if (rc) {
- DEV_ERR("%s: hdmi_tx_clk_enable failed.\n", __func__);
- mutex_unlock(&hdmi_ctrl->mutex);
- return rc;
- }
- mutex_unlock(&hdmi_ctrl->mutex);
-
hdmi_tx_init_phy(hdmi_ctrl);
- HDMI_REG_W(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base,
- HDMI_USEC_REFTIMER, 0x0001001B);
+ DSS_REG_W(io, HDMI_USEC_REFTIMER, 0x0001001B);
hdmi_tx_set_mode(hdmi_ctrl, true);
@@ -1413,8 +1307,7 @@
hdmi_tx_set_spd_infoframe(hdmi_ctrl);
/* Set IRQ for HPD */
- HDMI_REG_W(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base,
- HDMI_HPD_INT_CTRL, 4 | (hdmi_ctrl->hpd_state ? 0 : 2));
+ DSS_REG_W(io, HDMI_HPD_INT_CTRL, 4 | (hdmi_ctrl->hpd_state ? 0 : 2));
/* todo: HDCP/CEC */
@@ -1437,12 +1330,6 @@
/* todo: Audio */
hdmi_tx_powerdown_phy(hdmi_ctrl);
hdmi_ctrl->panel_power_on = false;
-
- mutex_lock(&hdmi_ctrl->mutex);
- if (hdmi_tx_clk_ctrl_update(&hdmi_ctrl->pdata, 0))
- DEV_ERR("%s: hdmi_tx_clk_disable failed.\n", __func__);
- mutex_unlock(&hdmi_ctrl->mutex);
-
hdmi_tx_core_off(hdmi_ctrl);
return 0;
@@ -1451,6 +1338,7 @@
static int hdmi_tx_power_on(struct mdss_panel_data *panel_data)
{
int rc = 0;
+ struct dss_io_data *io = NULL;
struct hdmi_tx_ctrl *hdmi_ctrl =
hdmi_tx_get_drvdata_from_panel_data(panel_data);
@@ -1458,11 +1346,10 @@
DEV_ERR("%s: invalid input\n", __func__);
return -EINVAL;
}
-
- rc = hdmi_tx_core_on(hdmi_ctrl);
- if (rc) {
- DEV_ERR("%s: hdmi_msm_core_on failed\n", __func__);
- return rc;
+ io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
+ if (!io->base) {
+ DEV_ERR("%s: core io is not initialized\n", __func__);
+ return -EINVAL;
}
DEV_INFO("power: ON (%dx%d %ld)\n", hdmi_ctrl->xres, hdmi_ctrl->yres,
@@ -1471,7 +1358,12 @@
rc = hdmi_tx_set_video_fmt(hdmi_ctrl);
if (rc) {
DEV_ERR("%s: cannot set video_fmt.rc=%d\n", __func__, rc);
- hdmi_tx_core_off(hdmi_ctrl);
+ return rc;
+ }
+
+ rc = hdmi_tx_core_on(hdmi_ctrl);
+ if (rc) {
+ DEV_ERR("%s: hdmi_msm_core_on failed\n", __func__);
return rc;
}
@@ -1494,8 +1386,7 @@
mutex_unlock(&hdmi_ctrl->mutex);
}
- hdmi_reg_dump(hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].base,
- hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO].len, "HDMI-ON: ");
+ dss_reg_dump(io->base, io->len, "HDMI-ON: ", REG_DUMP);
DEV_INFO("%s: HDMI=%s DVI= %s\n", __func__,
hdmi_tx_is_controller_on(hdmi_ctrl) ? "ON" : "OFF" ,
@@ -1524,13 +1415,6 @@
hdmi_tx_set_mode(hdmi_ctrl, false);
- mutex_lock(&hdmi_ctrl->mutex);
- rc = hdmi_tx_clk_ctrl_update(&hdmi_ctrl->pdata, 0);
- if (rc)
- DEV_INFO("%s: Failed to disable clock. Error=%d\n",
- __func__, rc);
- mutex_unlock(&hdmi_ctrl->mutex);
-
rc = hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_HPD_PM, 0);
if (rc)
DEV_INFO("%s: Failed to disable hpd power. Error=%d\n",
@@ -1552,7 +1436,7 @@
io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
if (!io->base) {
- DEV_ERR("%s: io not inititalized\n", __func__);
+ DEV_ERR("%s: core io not inititalized\n", __func__);
return -EINVAL;
}
@@ -1566,31 +1450,21 @@
return rc;
}
- mutex_lock(&hdmi_ctrl->mutex);
- rc = hdmi_tx_clk_ctrl_update(&hdmi_ctrl->pdata, true);
- if (rc) {
- DEV_ERR("%s: Failed to enable clocks. rc=%d\n",
- __func__, rc);
- mutex_unlock(&hdmi_ctrl->mutex);
- goto disable_hpd_power;
- }
- mutex_unlock(&hdmi_ctrl->mutex);
-
- hdmi_reg_dump(io->base, io->len, "HDMI-INIT: ");
+ dss_reg_dump(io->base, io->len, "HDMI-INIT: ", REG_DUMP);
hdmi_tx_set_mode(hdmi_ctrl, false);
hdmi_tx_phy_reset(hdmi_ctrl);
hdmi_tx_set_mode(hdmi_ctrl, true);
- HDMI_REG_W(io->base, HDMI_USEC_REFTIMER, 0x0001001B);
+ DSS_REG_W(io, HDMI_USEC_REFTIMER, 0x0001001B);
/* set timeout to 4.1ms (max) for hardware debounce */
- reg_val = HDMI_REG_R(io->base, HDMI_HPD_CTRL) | 0x1FFF;
+ reg_val = DSS_REG_R(io, HDMI_HPD_CTRL) | 0x1FFF;
/* Toggle HPD circuit to trigger HPD sense */
- HDMI_REG_W(io->base, HDMI_HPD_CTRL,
+ DSS_REG_W(io, HDMI_HPD_CTRL,
~(1 << 28) & reg_val);
- HDMI_REG_W(io->base, HDMI_HPD_CTRL, (1 << 28) | reg_val);
+ DSS_REG_W(io, HDMI_HPD_CTRL, (1 << 28) | reg_val);
hdmi_ctrl->hpd_initialized = true;
@@ -1607,11 +1481,6 @@
mutex_unlock(&hdmi_ctrl->mutex);
mod_timer(&hdmi_ctrl->hpd_state_timer, jiffies + HZ/2);
- return 0;
-
-disable_hpd_power:
- hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_HPD_PM, false);
-
return rc;
} /* hdmi_tx_hpd_on */
@@ -1629,7 +1498,6 @@
rc = hdmi_tx_hpd_on(hdmi_ctrl);
} else {
hdmi_tx_hpd_off(hdmi_ctrl);
- /* Set HDMI switch node to 0 on HPD feature disable */
switch_set_state(&hdmi_ctrl->sdev, 0);
DEV_INFO("%s: Hdmi state switch to %d\n", __func__,
hdmi_ctrl->sdev.state);
@@ -1640,8 +1508,6 @@
static irqreturn_t hdmi_tx_isr(int irq, void *data)
{
- u32 hpd_int_status;
- u32 hpd_int_ctrl;
struct dss_io_data *io = NULL;
struct hdmi_tx_ctrl *hdmi_ctrl = (struct hdmi_tx_ctrl *)data;
@@ -1652,108 +1518,26 @@
io = &hdmi_ctrl->pdata.io[HDMI_TX_CORE_IO];
if (!io->base) {
- DEV_WARN("%s: io not initialized, ISR ignored\n", __func__);
+ DEV_WARN("%s: core io not initialized, ISR ignored\n",
+ __func__);
return IRQ_HANDLED;
}
- /* Process HPD Interrupt */
- hpd_int_status = HDMI_REG_R(io->base, HDMI_HPD_INT_STATUS);
- hpd_int_ctrl = HDMI_REG_R(io->base, HDMI_HPD_INT_CTRL);
- if ((hpd_int_ctrl & BIT(2)) && (hpd_int_status & BIT(0))) {
- u32 cable_detected = hpd_int_status & BIT(1);
-
+ if (DSS_REG_R(io, HDMI_HPD_INT_STATUS) & BIT(0)) {
/*
- * Clear all interrupts, timer will turn IRQ back on
- * Leaving the bit[2] on, else core goes off
- * on getting HPD during power off.
+ * Turn off HPD irq and clear all interrupts,
+ * worker will turn IRQ back on
*/
- HDMI_REG_W(io->base, HDMI_HPD_INT_CTRL, BIT(2) | BIT(0));
-
- DEV_DBG("%s: HPD IRQ, Ctrl=%04x, State=%04x\n", __func__,
- hpd_int_ctrl, hpd_int_status);
-
- mutex_lock(&hdmi_ctrl->mutex);
- hdmi_ctrl->hpd_cable_chg_detected = true;
- hdmi_ctrl->hpd_prev_state = cable_detected ? 0 : 1;
- hdmi_ctrl->hpd_stable = 0;
- mutex_unlock(&hdmi_ctrl->mutex);
-
- mod_timer(&hdmi_ctrl->hpd_state_timer, jiffies + HZ/2);
-
- return IRQ_HANDLED;
+ DSS_REG_W(io, HDMI_HPD_INT_CTRL, ~BIT(2) | BIT(0));
+ queue_work(hdmi_ctrl->workq, &hdmi_ctrl->hpd_int_work);
}
- if (!hdmi_ddc_isr(&hdmi_ctrl->ddc_ctrl))
- return IRQ_HANDLED;
-
- DEV_DBG("%s: HPD<Ctrl=%04x, State=%04x>\n", __func__, hpd_int_ctrl,
- hpd_int_status);
+ if (hdmi_ddc_isr(&hdmi_ctrl->ddc_ctrl) < 0)
+ DEV_ERR("%s: hdmi_ddc_isr failed\n", __func__);
return IRQ_HANDLED;
} /* hdmi_tx_isr */
-static void hdmi_tx_clk_deinit(struct hdmi_tx_platform_data *pdata)
-{
- int i;
- if (!pdata) {
- DEV_ERR("%s: invalid input\n", __func__);
- return;
- }
-
- for (i = HDMI_TX_MAX_CLK - 1; i >= 0; i--) {
- if (pdata->clk[i])
- clk_put(pdata->clk[i]);
- pdata->clk[i] = NULL;
- }
-} /* hdmi_tx_clk_deinit */
-
-static int hdmi_tx_clk_init(struct platform_device *pdev,
- struct hdmi_tx_platform_data *pdata)
-{
- int rc = 0;
- struct device *dev = NULL;
- struct clk *clk = NULL;
-
- if (!pdev || !pdata) {
- DEV_ERR("%s: invalid input\n", __func__);
- return -EINVAL;
- }
- dev = &pdev->dev;
-
- clk = clk_get(dev, "iface_clk");
- rc = IS_ERR(clk);
- if (rc) {
- DEV_ERR("%s: ERROR: '%s' clk not found\n", __func__,
- hdmi_tx_clk_name(HDMI_TX_AHB_CLK));
- goto error;
- }
- pdata->clk[HDMI_TX_AHB_CLK] = clk;
-
- clk = clk_get(dev, "core_clk");
- rc = IS_ERR(clk);
- if (rc) {
- DEV_ERR("%s: ERROR: '%s' clk not found\n", __func__,
- hdmi_tx_clk_name(HDMI_TX_APP_CLK));
- goto error;
- }
- pdata->clk[HDMI_TX_APP_CLK] = clk;
-
- clk = clk_get(dev, "extp_clk");
- rc = IS_ERR(clk);
- if (rc) {
- DEV_ERR("%s: ERROR: '%s' clk not found\n", __func__,
- hdmi_tx_clk_name(HDMI_TX_EXTP_CLK));
- goto error;
- }
- pdata->clk[HDMI_TX_EXTP_CLK] = clk;
-
- return rc;
-
-error:
- hdmi_tx_clk_deinit(pdata);
- return rc;
-} /* hdmi_tx_clk_init */
-
static void hdmi_tx_dev_deinit(struct hdmi_tx_ctrl *hdmi_ctrl)
{
if (!hdmi_ctrl) {
@@ -1785,7 +1569,7 @@
pdata = &hdmi_ctrl->pdata;
- rc = hdmi_tx_check_capability(pdata->io[HDMI_TX_QFPROM_IO].base);
+ rc = hdmi_tx_check_capability(&pdata->io[HDMI_TX_QFPROM_IO]);
if (rc) {
DEV_ERR("%s: no HDMI device\n", __func__);
goto fail_no_hdmi;
@@ -1802,11 +1586,11 @@
goto fail_create_workq;
}
- /* todo: May be move this ? */
- hdmi_ctrl->ddc_ctrl.base = pdata->io[HDMI_TX_CORE_IO].base;
+ hdmi_ctrl->ddc_ctrl.io = &pdata->io[HDMI_TX_CORE_IO];
init_completion(&hdmi_ctrl->ddc_ctrl.ddc_sw_done);
INIT_WORK(&hdmi_ctrl->hpd_state_work, hdmi_tx_hpd_state_work);
+ INIT_WORK(&hdmi_ctrl->hpd_int_work, hdmi_tx_hpd_int_work);
init_timer(&hdmi_ctrl->hpd_state_timer);
hdmi_ctrl->hpd_state_timer.function = hdmi_tx_hpd_state_timer;
hdmi_ctrl->hpd_state_timer.data = (u32)hdmi_ctrl;
@@ -1868,23 +1652,16 @@
return;
}
- /* CLK */
- hdmi_tx_clk_deinit(&hdmi_ctrl->pdata);
-
- /* VREG */
+ /* VREG & CLK */
for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--) {
if (hdmi_tx_config_power(hdmi_ctrl, i, 0))
DEV_ERR("%s: '%s' power deconfig fail\n",
- __func__, hdmi_pm_name(i));
+ __func__, hdmi_tx_pm_name(i));
}
/* IO */
- for (i = HDMI_TX_MAX_IO - 1; i >= 0; i--) {
- if (hdmi_ctrl->pdata.io[i].base)
- iounmap(hdmi_ctrl->pdata.io[i].base);
- hdmi_ctrl->pdata.io[i].base = NULL;
- hdmi_ctrl->pdata.io[i].len = 0;
- }
+ for (i = HDMI_TX_MAX_IO - 1; i >= 0; i--)
+ msm_dss_iounmap(&hdmi_ctrl->pdata.io[i]);
} /* hdmi_tx_deinit_resource */
static int hdmi_tx_init_resource(struct hdmi_tx_ctrl *hdmi_ctrl)
@@ -1913,23 +1690,16 @@
pdata->io[i].len);
}
- /* VREG */
+ /* VREG & CLK */
for (i = 0; i < HDMI_TX_MAX_PM; i++) {
rc = hdmi_tx_config_power(hdmi_ctrl, i, 1);
if (rc) {
DEV_ERR("%s: '%s' power config failed.rc=%d\n",
- __func__, hdmi_pm_name(i), rc);
+ __func__, hdmi_tx_pm_name(i), rc);
goto error;
}
}
- /* CLK */
- rc = hdmi_tx_clk_init(hdmi_ctrl->pdev, pdata);
- if (rc) {
- DEV_ERR("%s: FAILED: clk init. rc=%d\n", __func__, rc);
- goto error;
- }
-
return rc;
error:
@@ -1937,6 +1707,98 @@
return rc;
} /* hdmi_tx_init_resource */
+static void hdmi_tx_put_dt_clk_data(struct device *dev,
+ struct dss_module_power *module_power)
+{
+ if (!module_power) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return;
+ }
+
+ if (module_power->clk_config) {
+ devm_kfree(dev, module_power->clk_config);
+ module_power->clk_config = NULL;
+ }
+ module_power->num_clk = 0;
+} /* hdmi_tx_put_dt_clk_data */
+
+/* todo: once clk are moved to device tree then change this implementation */
+static int hdmi_tx_get_dt_clk_data(struct device *dev,
+ struct dss_module_power *mp, u32 module_type)
+{
+ int rc = 0;
+
+ if (!dev || !mp) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ rc = -EINVAL;
+ goto error;
+ }
+
+ DEV_DBG("%s: module: '%s'\n", __func__, hdmi_tx_pm_name(module_type));
+
+ switch (module_type) {
+ case HDMI_TX_HPD_PM:
+ mp->num_clk = 2;
+ mp->clk_config = devm_kzalloc(dev, sizeof(struct dss_clk) *
+ mp->num_clk, GFP_KERNEL);
+ if (!mp->clk_config) {
+ DEV_ERR("%s: can't alloc '%s' clk mem\n", __func__,
+ hdmi_tx_pm_name(module_type));
+ goto error;
+ }
+
+ snprintf(mp->clk_config[0].clk_name, 32, "%s", "iface_clk");
+ mp->clk_config[0].type = DSS_CLK_AHB;
+ mp->clk_config[0].rate = 0;
+
+ snprintf(mp->clk_config[1].clk_name, 32, "%s", "core_clk");
+ mp->clk_config[1].type = DSS_CLK_OTHER;
+ mp->clk_config[1].rate = 19200000;
+ break;
+
+ case HDMI_TX_CORE_PM:
+ mp->num_clk = 2;
+ mp->clk_config = devm_kzalloc(dev, sizeof(struct dss_clk) *
+ mp->num_clk, GFP_KERNEL);
+ if (!mp->clk_config) {
+ DEV_ERR("%s: can't alloc '%s' clk mem\n", __func__,
+ hdmi_tx_pm_name(module_type));
+ goto error;
+ }
+
+ snprintf(mp->clk_config[0].clk_name, 32, "%s", "extp_clk");
+ mp->clk_config[0].type = DSS_CLK_PCLK;
+ /* This rate will be overwritten when core is powered on */
+ mp->clk_config[0].rate = 148500000;
+
+ snprintf(mp->clk_config[1].clk_name, 32, "%s", "alt_iface_clk");
+ mp->clk_config[1].type = DSS_CLK_AHB;
+ mp->clk_config[1].rate = 0;
+ break;
+
+ case HDMI_TX_CEC_PM:
+ mp->num_clk = 0;
+ DEV_DBG("%s: no clk\n", __func__);
+ break;
+
+ default:
+ DEV_ERR("%s: invalid module type=%d\n", __func__,
+ module_type);
+ return -EINVAL;
+ }
+
+ return rc;
+
+error:
+ if (mp->clk_config) {
+ devm_kfree(dev, mp->clk_config);
+ mp->clk_config = NULL;
+ }
+ mp->num_clk = 0;
+
+ return rc;
+} /* hdmi_tx_get_dt_clk_data */
+
static void hdmi_tx_put_dt_vreg_data(struct device *dev,
struct dss_module_power *module_power)
{
@@ -1985,7 +1847,7 @@
return -EINVAL;
}
- DEV_DBG("%s: module: '%s'\n", __func__, hdmi_pm_name(module_type));
+ DEV_DBG("%s: module: '%s'\n", __func__, hdmi_tx_pm_name(module_type));
of_node = dev->of_node;
@@ -2025,7 +1887,7 @@
mod_vreg_total, GFP_KERNEL);
if (!mp->vreg_config) {
DEV_ERR("%s: can't alloc '%s' vreg mem\n", __func__,
- hdmi_pm_name(module_type));
+ hdmi_tx_pm_name(module_type));
goto error;
}
} else {
@@ -2070,7 +1932,7 @@
prop_name, val_array, dt_vreg_total);
if (rc) {
DEV_ERR("%s: error read '%s' vreg type. rc=%d\n",
- __func__, hdmi_pm_name(module_type), rc);
+ __func__, hdmi_tx_pm_name(module_type), rc);
goto error;
}
mp->vreg_config[j].type = val_array[i];
@@ -2085,7 +1947,7 @@
dt_vreg_total);
if (rc) {
DEV_ERR("%s: error read '%s' min volt. rc=%d\n",
- __func__, hdmi_pm_name(module_type), rc);
+ __func__, hdmi_tx_pm_name(module_type), rc);
goto error;
}
mp->vreg_config[j].min_voltage = val_array[i];
@@ -2100,7 +1962,7 @@
dt_vreg_total);
if (rc) {
DEV_ERR("%s: error read '%s' max volt. rc=%d\n",
- __func__, hdmi_pm_name(module_type), rc);
+ __func__, hdmi_tx_pm_name(module_type), rc);
goto error;
}
mp->vreg_config[j].max_voltage = val_array[i];
@@ -2115,7 +1977,7 @@
dt_vreg_total);
if (rc) {
DEV_ERR("%s: error read '%s' min volt. rc=%d\n",
- __func__, hdmi_pm_name(module_type), rc);
+ __func__, hdmi_tx_pm_name(module_type), rc);
goto error;
}
mp->vreg_config[j].optimum_voltage = val_array[i];
@@ -2136,8 +1998,12 @@
return rc;
error:
- for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--)
- hdmi_tx_put_dt_vreg_data(dev, mp);
+ if (mp->vreg_config) {
+ devm_kfree(dev, mp->vreg_config);
+ mp->vreg_config = NULL;
+ }
+ mp->num_vreg = 0;
+
if (val_array)
devm_kfree(dev, val_array);
return rc;
@@ -2191,7 +2057,7 @@
return -EINVAL;
}
- DEV_DBG("%s: module: '%s'\n", __func__, hdmi_pm_name(module_type));
+ DEV_DBG("%s: module: '%s'\n", __func__, hdmi_tx_pm_name(module_type));
of_node = dev->of_node;
@@ -2227,7 +2093,7 @@
mod_gpio_total, GFP_KERNEL);
if (!mp->gpio_config) {
DEV_ERR("%s: can't alloc '%s' gpio mem\n", __func__,
- hdmi_pm_name(module_type));
+ hdmi_tx_pm_name(module_type));
goto error;
}
} else {
@@ -2268,8 +2134,11 @@
return rc;
error:
- for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--)
- hdmi_tx_put_dt_gpio_data(dev, mp);
+ if (mp->gpio_config) {
+ devm_kfree(dev, mp->gpio_config);
+ mp->gpio_config = NULL;
+ }
+ mp->num_gpio = 0;
return rc;
} /* hdmi_tx_get_dt_gpio_data */
@@ -2284,6 +2153,9 @@
}
for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--)
+ hdmi_tx_put_dt_clk_data(dev, &pdata->power_data[i]);
+
+ for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--)
hdmi_tx_put_dt_vreg_data(dev, &pdata->power_data[i]);
for (i = HDMI_TX_MAX_PM - 1; i >= 0; i--)
@@ -2317,7 +2189,7 @@
&pdata->power_data[i], i);
if (rc) {
DEV_ERR("%s: '%s' get_dt_gpio_data failed.rc=%d\n",
- __func__, hdmi_pm_name(i), rc);
+ __func__, hdmi_tx_pm_name(i), rc);
goto error;
}
}
@@ -2328,7 +2200,18 @@
&pdata->power_data[i], i);
if (rc) {
DEV_ERR("%s: '%s' get_dt_vreg_data failed.rc=%d\n",
- __func__, hdmi_pm_name(i), rc);
+ __func__, hdmi_tx_pm_name(i), rc);
+ goto error;
+ }
+ }
+
+ /* CLK */
+ for (i = 0; i < HDMI_TX_MAX_PM; i++) {
+ rc = hdmi_tx_get_dt_clk_data(&pdev->dev,
+ &pdata->power_data[i], i);
+ if (rc) {
+ DEV_ERR("%s: '%s' get_dt_clk_data failed.rc=%d\n",
+ __func__, hdmi_tx_pm_name(i), rc);
goto error;
}
}
diff --git a/drivers/video/msm/mdss/mdss_hdmi_tx.h b/drivers/video/msm/mdss/mdss_hdmi_tx.h
index 7e37d28..94e0fda 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_tx.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_tx.h
@@ -15,14 +15,6 @@
#include <linux/switch.h>
#include "mdss_hdmi_util.h"
-#include "mdss_io_util.h"
-
-enum hdmi_tx_clk_type {
- HDMI_TX_AHB_CLK,
- HDMI_TX_APP_CLK,
- HDMI_TX_EXTP_CLK,
- HDMI_TX_MAX_CLK
-};
enum hdmi_tx_io_type {
HDMI_TX_CORE_IO,
@@ -42,9 +34,6 @@
/* Data filled from device tree nodes */
struct dss_io_data io[HDMI_TX_MAX_IO];
struct dss_module_power power_data[HDMI_TX_MAX_PM];
-
- /* clk and regulator handles */
- struct clk *clk[HDMI_TX_MAX_CLK];
};
struct hdmi_tx_ctrl {
@@ -67,6 +56,7 @@
u32 hpd_state;
u32 hpd_feature_on;
struct work_struct hpd_state_work;
+ struct work_struct hpd_int_work;
struct timer_list hpd_state_timer;
unsigned long pixel_clk;
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.c b/drivers/video/msm/mdss/mdss_hdmi_util.c
index 3ba9f89..e7ea8c9 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.c
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.c
@@ -15,226 +15,6 @@
#include <mach/board.h>
#include "mdss_hdmi_util.h"
-const char *hdmi_reg_name(u32 offset)
-{
- switch (offset) {
- case 0x00000000: return "HDMI_CTRL";
- case 0x00000010: return "HDMI_TEST_PATTERN";
- case 0x00000014: return "HDMI_RANDOM_PATTERN";
- case 0x00000018: return "HDMI_PKT_BLK_CTRL";
- case 0x0000001C: return "HDMI_STATUS";
- case 0x00000020: return "HDMI_AUDIO_PKT_CTRL";
- case 0x00000024: return "HDMI_ACR_PKT_CTRL";
- case 0x00000028: return "HDMI_VBI_PKT_CTRL";
- case 0x0000002C: return "HDMI_INFOFRAME_CTRL0";
- case 0x00000030: return "HDMI_INFOFRAME_CTRL1";
- case 0x00000034: return "HDMI_GEN_PKT_CTRL";
- case 0x0000003C: return "HDMI_ACP";
- case 0x00000040: return "HDMI_GC";
- case 0x00000044: return "HDMI_AUDIO_PKT_CTRL2";
- case 0x00000048: return "HDMI_ISRC1_0";
- case 0x0000004C: return "HDMI_ISRC1_1";
- case 0x00000050: return "HDMI_ISRC1_2";
- case 0x00000054: return "HDMI_ISRC1_3";
- case 0x00000058: return "HDMI_ISRC1_4";
- case 0x0000005C: return "HDMI_ISRC2_0";
- case 0x00000060: return "HDMI_ISRC2_1";
- case 0x00000064: return "HDMI_ISRC2_2";
- case 0x00000068: return "HDMI_ISRC2_3";
- case 0x0000006C: return "HDMI_AVI_INFO0";
- case 0x00000070: return "HDMI_AVI_INFO1";
- case 0x00000074: return "HDMI_AVI_INFO2";
- case 0x00000078: return "HDMI_AVI_INFO3";
- case 0x0000007C: return "HDMI_MPEG_INFO0";
- case 0x00000080: return "HDMI_MPEG_INFO1";
- case 0x00000084: return "HDMI_GENERIC0_HDR";
- case 0x00000088: return "HDMI_GENERIC0_0";
- case 0x0000008C: return "HDMI_GENERIC0_1";
- case 0x00000090: return "HDMI_GENERIC0_2";
- case 0x00000094: return "HDMI_GENERIC0_3";
- case 0x00000098: return "HDMI_GENERIC0_4";
- case 0x0000009C: return "HDMI_GENERIC0_5";
- case 0x000000A0: return "HDMI_GENERIC0_6";
- case 0x000000A4: return "HDMI_GENERIC1_HDR";
- case 0x000000A8: return "HDMI_GENERIC1_0";
- case 0x000000AC: return "HDMI_GENERIC1_1";
- case 0x000000B0: return "HDMI_GENERIC1_2";
- case 0x000000B4: return "HDMI_GENERIC1_3";
- case 0x000000B8: return "HDMI_GENERIC1_4";
- case 0x000000BC: return "HDMI_GENERIC1_5";
- case 0x000000C0: return "HDMI_GENERIC1_6";
- case 0x000000C4: return "HDMI_ACR_32_0";
- case 0x000000C8: return "HDMI_ACR_32_1";
- case 0x000000CC: return "HDMI_ACR_44_0";
- case 0x000000D0: return "HDMI_ACR_44_1";
- case 0x000000D4: return "HDMI_ACR_48_0";
- case 0x000000D8: return "HDMI_ACR_48_1";
- case 0x000000DC: return "HDMI_ACR_STATUS_0";
- case 0x000000E0: return "HDMI_ACR_STATUS_1";
- case 0x000000E4: return "HDMI_AUDIO_INFO0";
- case 0x000000E8: return "HDMI_AUDIO_INFO1";
- case 0x000000EC: return "HDMI_CS_60958_0";
- case 0x000000F0: return "HDMI_CS_60958_1";
- case 0x000000F8: return "HDMI_RAMP_CTRL0";
- case 0x000000FC: return "HDMI_RAMP_CTRL1";
- case 0x00000100: return "HDMI_RAMP_CTRL2";
- case 0x00000104: return "HDMI_RAMP_CTRL3";
- case 0x00000108: return "HDMI_CS_60958_2";
- case 0x00000110: return "HDMI_HDCP_CTRL";
- case 0x00000114: return "HDMI_HDCP_DEBUG_CTRL";
- case 0x00000118: return "HDMI_HDCP_INT_CTRL";
- case 0x0000011C: return "HDMI_HDCP_LINK0_STATUS";
- case 0x00000120: return "HDMI_HDCP_DDC_CTRL_0";
- case 0x00000124: return "HDMI_HDCP_DDC_CTRL_1";
- case 0x00000128: return "HDMI_HDCP_DDC_STATUS";
- case 0x0000012C: return "HDMI_HDCP_ENTROPY_CTRL0";
- case 0x00000130: return "HDMI_HDCP_RESET";
- case 0x00000134: return "HDMI_HDCP_RCVPORT_DATA0";
- case 0x00000138: return "HDMI_HDCP_RCVPORT_DATA1";
- case 0x0000013C: return "HDMI_HDCP_RCVPORT_DATA2_0";
- case 0x00000140: return "HDMI_HDCP_RCVPORT_DATA2_1";
- case 0x00000144: return "HDMI_HDCP_RCVPORT_DATA3";
- case 0x00000148: return "HDMI_HDCP_RCVPORT_DATA4";
- case 0x0000014C: return "HDMI_HDCP_RCVPORT_DATA5";
- case 0x00000150: return "HDMI_HDCP_RCVPORT_DATA6";
- case 0x00000154: return "HDMI_HDCP_RCVPORT_DATA7";
- case 0x00000158: return "HDMI_HDCP_RCVPORT_DATA8";
- case 0x0000015C: return "HDMI_HDCP_RCVPORT_DATA9";
- case 0x00000160: return "HDMI_HDCP_RCVPORT_DATA10";
- case 0x00000164: return "HDMI_HDCP_RCVPORT_DATA11";
- case 0x00000168: return "HDMI_HDCP_RCVPORT_DATA12";
- case 0x0000016C: return "HDMI_VENSPEC_INFO0";
- case 0x00000170: return "HDMI_VENSPEC_INFO1";
- case 0x00000174: return "HDMI_VENSPEC_INFO2";
- case 0x00000178: return "HDMI_VENSPEC_INFO3";
- case 0x0000017C: return "HDMI_VENSPEC_INFO4";
- case 0x00000180: return "HDMI_VENSPEC_INFO5";
- case 0x00000184: return "HDMI_VENSPEC_INFO6";
- case 0x00000194: return "HDMI_HDCP_DEBUG";
- case 0x0000019C: return "HDMI_TMDS_CTRL_CHAR";
- case 0x000001A4: return "HDMI_TMDS_CTRL_SEL";
- case 0x000001A8: return "HDMI_TMDS_SYNCCHAR01";
- case 0x000001AC: return "HDMI_TMDS_SYNCCHAR23";
- case 0x000001B4: return "HDMI_TMDS_DEBUG";
- case 0x000001B8: return "HDMI_TMDS_CTL_BITS";
- case 0x000001BC: return "HDMI_TMDS_DCBAL_CTRL";
- case 0x000001C0: return "HDMI_TMDS_DCBAL_CHAR";
- case 0x000001C8: return "HDMI_TMDS_CTL01_GEN";
- case 0x000001CC: return "HDMI_TMDS_CTL23_GEN";
- case 0x000001D0: return "HDMI_AUDIO_CFG";
- case 0x00000204: return "HDMI_DEBUG";
- case 0x00000208: return "HDMI_USEC_REFTIMER";
- case 0x0000020C: return "HDMI_DDC_CTRL";
- case 0x00000210: return "HDMI_DDC_ARBITRATION";
- case 0x00000214: return "HDMI_DDC_INT_CTRL";
- case 0x00000218: return "HDMI_DDC_SW_STATUS";
- case 0x0000021C: return "HDMI_DDC_HW_STATUS";
- case 0x00000220: return "HDMI_DDC_SPEED";
- case 0x00000224: return "HDMI_DDC_SETUP";
- case 0x00000228: return "HDMI_DDC_TRANS0";
- case 0x0000022C: return "HDMI_DDC_TRANS1";
- case 0x00000230: return "HDMI_DDC_TRANS2";
- case 0x00000234: return "HDMI_DDC_TRANS3";
- case 0x00000238: return "HDMI_DDC_DATA";
- case 0x0000023C: return "HDMI_HDCP_SHA_CTRL";
- case 0x00000240: return "HDMI_HDCP_SHA_STATUS";
- case 0x00000244: return "HDMI_HDCP_SHA_DATA";
- case 0x00000248: return "HDMI_HDCP_SHA_DBG_M0_0";
- case 0x0000024C: return "HDMI_HDCP_SHA_DBG_M0_1";
- case 0x00000250: return "HDMI_HPD_INT_STATUS";
- case 0x00000254: return "HDMI_HPD_INT_CTRL";
- case 0x00000258: return "HDMI_HPD_CTRL";
- case 0x0000025C: return "HDMI_HDCP_ENTROPY_CTRL1";
- case 0x00000260: return "HDMI_HDCP_SW_UPPER_AN";
- case 0x00000264: return "HDMI_HDCP_SW_LOWER_AN";
- case 0x00000268: return "HDMI_CRC_CTRL";
- case 0x0000026C: return "HDMI_VID_CRC";
- case 0x00000270: return "HDMI_AUD_CRC";
- case 0x00000274: return "HDMI_VBI_CRC";
- case 0x0000027C: return "HDMI_DDC_REF";
- case 0x00000284: return "HDMI_HDCP_SW_UPPER_AKSV";
- case 0x00000288: return "HDMI_HDCP_SW_LOWER_AKSV";
- case 0x0000028C: return "HDMI_CEC_CTRL";
- case 0x00000290: return "HDMI_CEC_WR_DATA";
- case 0x00000294: return "HDMI_CEC_RETRANSMIT";
- case 0x00000298: return "HDMI_CEC_STATUS";
- case 0x0000029C: return "HDMI_CEC_INT";
- case 0x000002A0: return "HDMI_CEC_ADDR";
- case 0x000002A4: return "HDMI_CEC_TIME";
- case 0x000002A8: return "HDMI_CEC_REFTIMER";
- case 0x000002AC: return "HDMI_CEC_RD_DATA";
- case 0x000002B0: return "HDMI_CEC_RD_FILTER";
- case 0x000002B4: return "HDMI_ACTIVE_H";
- case 0x000002B8: return "HDMI_ACTIVE_V";
- case 0x000002BC: return "HDMI_ACTIVE_V_F2";
- case 0x000002C0: return "HDMI_TOTAL";
- case 0x000002C4: return "HDMI_V_TOTAL_F2";
- case 0x000002C8: return "HDMI_FRAME_CTRL";
- case 0x000002CC: return "HDMI_AUD_INT";
- case 0x000002D0: return "HDMI_DEBUG_BUS_CTRL";
- case 0x000002D4: return "HDMI_PHY_CTRL";
- case 0x000002DC: return "HDMI_CEC_WR_RANGE";
- case 0x000002E0: return "HDMI_CEC_RD_RANGE";
- case 0x000002E4: return "HDMI_VERSION";
- case 0x000002F4: return "HDMI_BIST_ENABLE";
- case 0x000002F8: return "HDMI_TIMING_ENGINE_EN";
- case 0x000002FC: return "HDMI_INTF_CONFIG";
- case 0x00000300: return "HDMI_HSYNC_CTL";
- case 0x00000304: return "HDMI_VSYNC_PERIOD_F0";
- case 0x00000308: return "HDMI_VSYNC_PERIOD_F1";
- case 0x0000030C: return "HDMI_VSYNC_PULSE_WIDTH_F0";
- case 0x00000310: return "HDMI_VSYNC_PULSE_WIDTH_F1";
- case 0x00000314: return "HDMI_DISPLAY_V_START_F0";
- case 0x00000318: return "HDMI_DISPLAY_V_START_F1";
- case 0x0000031C: return "HDMI_DISPLAY_V_END_F0";
- case 0x00000320: return "HDMI_DISPLAY_V_END_F1";
- case 0x00000324: return "HDMI_ACTIVE_V_START_F0";
- case 0x00000328: return "HDMI_ACTIVE_V_START_F1";
- case 0x0000032C: return "HDMI_ACTIVE_V_END_F0";
- case 0x00000330: return "HDMI_ACTIVE_V_END_F1";
- case 0x00000334: return "HDMI_DISPLAY_HCTL";
- case 0x00000338: return "HDMI_ACTIVE_HCTL";
- case 0x0000033C: return "HDMI_HSYNC_SKEW";
- case 0x00000340: return "HDMI_POLARITY_CTL";
- case 0x00000344: return "HDMI_TPG_MAIN_CONTROL";
- case 0x00000348: return "HDMI_TPG_VIDEO_CONFIG";
- case 0x0000034C: return "HDMI_TPG_COMPONENT_LIMITS";
- case 0x00000350: return "HDMI_TPG_RECTANGLE";
- case 0x00000354: return "HDMI_TPG_INITIAL_VALUE";
- case 0x00000358: return "HDMI_TPG_BLK_WHT_PATTERN_FRAMES";
- case 0x0000035C: return "HDMI_TPG_RGB_MAPPING";
- default: return "???";
- }
-} /* hdmi_reg_name */
-
-void hdmi_reg_w(void __iomem *addr, u32 offset, u32 value, u32 debug)
-{
- u32 in_val;
-
- writel_relaxed(value, addr+offset);
- if (debug && PORT_DEBUG) {
- in_val = readl_relaxed(addr+offset);
- DEV_DBG("HDMI[%04x] => %08x [%08x] %s\n", offset, value,
- in_val, hdmi_reg_name(offset));
- }
-} /* hdmi_reg_w */
-
-u32 hdmi_reg_r(void __iomem *addr, u32 offset, u32 debug)
-{
- u32 value = readl_relaxed(addr+offset);
- if (debug && PORT_DEBUG)
- DEV_DBG("HDMI[%04x] <= %08x %s\n", offset, value,
- hdmi_reg_name(offset));
- return value;
-} /* hdmi_reg_r */
-
-void hdmi_reg_dump(void __iomem *base, u32 length, const char *prefix)
-{
- if (REG_DUMP)
- print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET, 32, 4,
- (void *)base, length, false);
-} /* hdmi_reg_dump */
-
static struct hdmi_disp_mode_timing_type
hdmi_supported_video_mode_lut[HDMI_VFRMT_MAX] = {
HDMI_SETTINGS_640x480p60_4_3,
@@ -505,7 +285,7 @@
{
u32 reg_val, time_out_count;
- if (!ddc_ctrl || !ddc_ctrl->base) {
+ if (!ddc_ctrl || !ddc_ctrl->io) {
DEV_ERR("%s: invalid input\n", __func__);
return -EINVAL;
}
@@ -515,9 +295,9 @@
do {
--time_out_count;
/* Clear and Enable DDC interrupt */
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL,
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL,
BIT(2) | BIT(1));
- reg_val = HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL);
+ reg_val = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
} while ((reg_val & BIT(0)) && time_out_count);
if (!time_out_count) {
@@ -535,7 +315,7 @@
int status = 0;
int log_retry_fail;
- if (!ddc_ctrl || !ddc_ctrl->base || !ddc_data) {
+ if (!ddc_ctrl || !ddc_ctrl->io || !ddc_data) {
DEV_ERR("%s: invalid input\n", __func__);
return -EINVAL;
}
@@ -565,7 +345,7 @@
* INDEX = 0x0 (initial offset into buffer)
* INDEX_WRITE = 0x1 (setting initial offset)
*/
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA,
BIT(31) | (ddc_data->dev_addr << 8));
/*
@@ -576,7 +356,7 @@
* INDEX = 0x0
* INDEX_WRITE = 0x0 (auto-increment by hardware)
*/
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, ddc_data->offset << 8);
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA, ddc_data->offset << 8);
/*
* 3. Write to HDMI_I2C_DATA with the following fields set in order to
@@ -586,7 +366,7 @@
* INDEX = 0x0
* INDEX_WRITE = 0x0 (auto-increment by hardware)
*/
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA,
(ddc_data->dev_addr | BIT(0)) << 8);
/* Data setup is complete, now setup the transaction characteristics */
@@ -599,7 +379,7 @@
* STOP0 = 0x0 (do NOT insert STOP bit)
* CNT0 = 0x1 (single byte transaction excluding address)
*/
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS0, BIT(12) | BIT(16));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_TRANS0, BIT(12) | BIT(16));
/*
* 5. Write to HDMI_I2C_TRANSACTION1 with the following fields set in
@@ -609,7 +389,7 @@
* STOP1 = 0x1 (insert STOP bit)
* CNT1 = data_len (it's 128 (0x80) for a blk read)
*/
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS1,
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_TRANS1,
BIT(0) | BIT(12) | BIT(13) | (ddc_data->request_len << 16));
/* Trigger the I2C transfer */
@@ -624,11 +404,11 @@
* GO = 0x1 (kicks off hardware)
*/
INIT_COMPLETION(ddc_ctrl->ddc_sw_done);
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(0) | BIT(20));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0) | BIT(20));
time_out_count = wait_for_completion_interruptible_timeout(
&ddc_ctrl->ddc_sw_done, HZ/2);
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL, BIT(1));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, BIT(1));
if (!time_out_count) {
if (ddc_data->retry-- > 0) {
DEV_INFO("%s: failed timout, retry=%d\n", __func__,
@@ -637,26 +417,26 @@
}
status = -ETIMEDOUT;
DEV_ERR("%s: timedout(7), Int Ctrl=%08x\n", __func__,
- HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_INT_CTRL));
+ DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL));
DEV_ERR("%s: DDC SW Status=%08x, HW Status=%08x\n",
__func__,
- HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_SW_STATUS),
- HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_HW_STATUS));
+ DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS),
+ DSS_REG_R(ddc_ctrl->io, HDMI_DDC_HW_STATUS));
goto error;
}
/* Read DDC status */
- reg_val = HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_SW_STATUS);
+ reg_val = DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS);
reg_val &= BIT(12) | BIT(13) | BIT(14) | BIT(15);
/* Check if any NACK occurred */
if (reg_val) {
/* SW_STATUS_RESET */
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(3));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(3));
if (ddc_data->retry == 1)
/* SOFT_RESET */
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(1));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(1));
if (ddc_data->retry-- > 0) {
DEV_DBG("%s(%s): failed NACK=0x%08x, retry=%d\n",
@@ -687,13 +467,13 @@
* INDEX_WRITE = 0x1 (explicitly define offset)
*/
/* Write this data to DDC buffer */
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA,
BIT(0) | (3 << 16) | BIT(31));
/* Discard first byte */
- HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_DATA);
+ DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_DATA);
for (ndx = 0; ndx < ddc_data->data_len; ++ndx) {
- reg_val = HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_DATA);
+ reg_val = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_DATA);
ddc_data->data_buf[ndx] = (u8)((reg_val & 0x0000FF00) >> 8);
}
@@ -705,46 +485,44 @@
void hdmi_ddc_config(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
{
- if (!ddc_ctrl || !ddc_ctrl->base) {
+ if (!ddc_ctrl || !ddc_ctrl->io) {
DEV_ERR("%s: invalid input\n", __func__);
return;
}
/* Configure Pre-Scale multiplier & Threshold */
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_SPEED, (10 << 16) | (2 << 0));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_SPEED, (10 << 16) | (2 << 0));
/*
* Setting 31:24 bits : Time units to wait before timeout
* when clock is being stalled by external sink device
*/
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_SETUP, 0xFF000000);
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_SETUP, 0xFF000000);
/* Enable reference timer to 27 micro-seconds */
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_REF, (1 << 16) | (27 << 0));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_REF, (1 << 16) | (27 << 0));
} /* hdmi_ddc_config */
int hdmi_ddc_isr(struct hdmi_tx_ddc_ctrl *ddc_ctrl)
{
- int rc = -1;
u32 ddc_int_ctrl;
- if (!ddc_ctrl || !ddc_ctrl->base) {
+ if (!ddc_ctrl || !ddc_ctrl->io) {
DEV_ERR("%s: invalid input\n", __func__);
return -EINVAL;
}
- ddc_int_ctrl = HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL);
+ ddc_int_ctrl = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
if ((ddc_int_ctrl & BIT(2)) && (ddc_int_ctrl & BIT(0))) {
/* SW_DONE INT occured, clr it */
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL,
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL,
ddc_int_ctrl | BIT(1));
complete(&ddc_ctrl->ddc_sw_done);
- return 0;
}
DEV_DBG("%s: ddc_int_ctrl=%04x\n", __func__, ddc_int_ctrl);
- return rc;
+ return 0;
} /* hdmi_ddc_isr */
int hdmi_ddc_read(struct hdmi_tx_ddc_ctrl *ddc_ctrl,
@@ -779,7 +557,7 @@
int log_retry_fail;
int seg_addr = 0x60, seg_num = 0x01;
- if (!ddc_ctrl || !ddc_ctrl->base || !ddc_data) {
+ if (!ddc_ctrl || !ddc_ctrl->io || !ddc_data) {
DEV_ERR("%s: invalid input\n", __func__);
return -EINVAL;
}
@@ -808,7 +586,7 @@
* INDEX = 0x0 (initial offset into buffer)
* INDEX_WRITE = 0x1 (setting initial offset)
*/
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, BIT(31) | (seg_addr << 8));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA, BIT(31) | (seg_addr << 8));
/*
* 2. Write to HDMI_I2C_DATA with the following fields set in order to
@@ -818,7 +596,7 @@
* INDEX = 0x0
* INDEX_WRITE = 0x0 (auto-increment by hardware)
*/
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, seg_num << 8);
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA, seg_num << 8);
/*
* 3. Write to HDMI_I2C_DATA with the following fields set in order to
@@ -828,9 +606,9 @@
* INDEX = 0x0
* INDEX_WRITE = 0x0 (auto-increment by hardware)
*/
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, ddc_data->dev_addr << 8);
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, ddc_data->offset << 8);
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA, ddc_data->dev_addr << 8);
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA, ddc_data->offset << 8);
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA,
(ddc_data->dev_addr | BIT(0)) << 8);
/* Data setup is complete, now setup the transaction characteristics */
@@ -843,7 +621,7 @@
* STOP0 = 0x0 (do NOT insert STOP bit)
* CNT0 = 0x1 (single byte transaction excluding address)
*/
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS0, BIT(12) | BIT(16));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_TRANS0, BIT(12) | BIT(16));
/*
* 5. Write to HDMI_I2C_TRANSACTION1 with the following fields set in
@@ -853,7 +631,7 @@
* STOP1 = 0x1 (insert STOP bit)
* CNT1 = data_len (it's 128 (0x80) for a blk read)
*/
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS1, BIT(12) | BIT(16));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_TRANS1, BIT(12) | BIT(16));
/*
* 5. Write to HDMI_I2C_TRANSACTION1 with the following fields set in
@@ -863,7 +641,7 @@
* STOP1 = 0x1 (insert STOP bit)
* CNT1 = data_len (it's 128 (0x80) for a blk read)
*/
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS2,
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_TRANS2,
BIT(0) | BIT(12) | BIT(13) | (ddc_data->request_len << 16));
/* Trigger the I2C transfer */
@@ -877,13 +655,13 @@
* GO = 0x1 (kicks off hardware)
*/
INIT_COMPLETION(ddc_ctrl->ddc_sw_done);
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(0) | BIT(21));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0) | BIT(21));
time_out_count = wait_for_completion_interruptible_timeout(
&ddc_ctrl->ddc_sw_done, HZ/2);
- reg_val = HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_INT_CTRL);
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2)));
+ reg_val = DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2)));
if (!time_out_count) {
if (ddc_data->retry-- > 0) {
DEV_INFO("%s: failed timout, retry=%d\n", __func__,
@@ -892,25 +670,25 @@
}
status = -ETIMEDOUT;
DEV_ERR("%s: timedout(7), Int Ctrl=%08x\n", __func__,
- HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_INT_CTRL));
+ DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL));
DEV_ERR("%s: DDC SW Status=%08x, HW Status=%08x\n",
__func__,
- HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_SW_STATUS),
- HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_HW_STATUS));
+ DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS),
+ DSS_REG_R(ddc_ctrl->io, HDMI_DDC_HW_STATUS));
goto error;
}
/* Read DDC status */
- reg_val = HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_SW_STATUS);
+ reg_val = DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS);
reg_val &= BIT(12) | BIT(13) | BIT(14) | BIT(15);
/* Check if any NACK occurred */
if (reg_val) {
/* SW_STATUS_RESET */
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(3));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(3));
if (ddc_data->retry == 1)
/* SOFT_RESET */
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(1));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(1));
if (ddc_data->retry-- > 0) {
DEV_DBG("%s(%s): failed NACK=0x%08x, retry=%d\n",
__func__, ddc_data->what, reg_val,
@@ -940,14 +718,14 @@
* INDEX_WRITE = 0x1 (explicitly define offset)
*/
/* Write this data to DDC buffer */
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA,
BIT(0) | (5 << 16) | BIT(31));
/* Discard first byte */
- HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_DATA);
+ DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_DATA);
for (ndx = 0; ndx < ddc_data->data_len; ++ndx) {
- reg_val = HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_DATA);
+ reg_val = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_DATA);
ddc_data->data_buf[ndx] = (u8) ((reg_val & 0x0000FF00) >> 8);
}
@@ -964,7 +742,7 @@
int status = 0, retry = 10;
u32 time_out_count;
- if (!ddc_ctrl || !ddc_ctrl->base || !ddc_data) {
+ if (!ddc_ctrl || !ddc_ctrl->io || !ddc_data) {
DEV_ERR("%s: invalid input\n", __func__);
return -EINVAL;
}
@@ -991,7 +769,7 @@
* INDEX = 0x0 (initial offset into buffer)
* INDEX_WRITE = 0x1 (setting initial offset)
*/
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA,
BIT(31) | (ddc_data->dev_addr << 8));
/*
@@ -1002,7 +780,7 @@
* INDEX = 0x0
* INDEX_WRITE = 0x0 (auto-increment by hardware)
*/
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA, ddc_data->offset << 8);
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA, ddc_data->offset << 8);
/*
* 3. Write to HDMI_I2C_DATA with the following fields set in order to
@@ -1013,7 +791,7 @@
* INDEX_WRITE = 0x0 (auto-increment by hardware)
*/
for (ndx = 0; ndx < ddc_data->data_len; ++ndx)
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_DATA,
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_DATA,
((u32)ddc_data->data_buf[ndx]) << 8);
/* Data setup is complete, now setup the transaction characteristics */
@@ -1026,7 +804,7 @@
* STOP0 = 0x0 (do NOT insert STOP bit)
* CNT0 = 0x1 (single byte transaction excluding address)
*/
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS0, BIT(12) | BIT(16));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_TRANS0, BIT(12) | BIT(16));
/*
* 5. Write to HDMI_I2C_TRANSACTION1 with the following fields set in
@@ -1038,7 +816,7 @@
* Byte count for second transition (excluding the first
* Byte which is usually the address)
*/
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_TRANS1,
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_TRANS1,
BIT(13) | ((ddc_data->data_len-1) << 16));
/* Trigger the I2C transfer */
@@ -1051,13 +829,13 @@
* GO = 0x1 (kicks off hardware)
*/
INIT_COMPLETION(ddc_ctrl->ddc_sw_done);
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(0) | BIT(20));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(0) | BIT(20));
time_out_count = wait_for_completion_interruptible_timeout(
&ddc_ctrl->ddc_sw_done, HZ/2);
- reg_val = HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_INT_CTRL);
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2)));
+ reg_val = DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL);
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_INT_CTRL, reg_val & (~BIT(2)));
if (!time_out_count) {
if (retry-- > 0) {
DEV_INFO("%s[%s]: failed timout, retry=%d\n", __func__,
@@ -1067,26 +845,26 @@
status = -ETIMEDOUT;
DEV_ERR("%s[%s]: timedout, Int Ctrl=%08x\n",
__func__, ddc_data->what,
- HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_INT_CTRL));
+ DSS_REG_R(ddc_ctrl->io, HDMI_DDC_INT_CTRL));
DEV_ERR("%s: DDC SW Status=%08x, HW Status=%08x\n",
__func__,
- HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_SW_STATUS),
- HDMI_REG_R(ddc_ctrl->base, HDMI_DDC_HW_STATUS));
+ DSS_REG_R(ddc_ctrl->io, HDMI_DDC_SW_STATUS),
+ DSS_REG_R(ddc_ctrl->io, HDMI_DDC_HW_STATUS));
goto error;
}
/* Read DDC status */
- reg_val = HDMI_REG_R_ND(ddc_ctrl->base, HDMI_DDC_SW_STATUS);
+ reg_val = DSS_REG_R_ND(ddc_ctrl->io, HDMI_DDC_SW_STATUS);
reg_val &= 0x00001000 | 0x00002000 | 0x00004000 | 0x00008000;
/* Check if any NACK occurred */
if (reg_val) {
if (retry > 1)
/* SW_STATUS_RESET */
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(3));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(3));
else
/* SOFT_RESET */
- HDMI_REG_W_ND(ddc_ctrl->base, HDMI_DDC_CTRL, BIT(1));
+ DSS_REG_W_ND(ddc_ctrl->io, HDMI_DDC_CTRL, BIT(1));
if (retry-- > 0) {
DEV_DBG("%s[%s]: failed NACK=%08x, retry=%d\n",
diff --git a/drivers/video/msm/mdss/mdss_hdmi_util.h b/drivers/video/msm/mdss/mdss_hdmi_util.h
index 47515ba..852a93c 100644
--- a/drivers/video/msm/mdss/mdss_hdmi_util.h
+++ b/drivers/video/msm/mdss/mdss_hdmi_util.h
@@ -12,26 +12,7 @@
#ifndef __HDMI_UTIL_H__
#define __HDMI_UTIL_H__
-
-#define DEV_INFO(fmt, args...) pr_info(fmt, ##args)
-#define DEV_WARN(fmt, args...) pr_warn(fmt, ##args)
-#define DEV_ERR(fmt, args...) pr_err(fmt, ##args)
-
-#ifdef DEBUG
-#define DEV_DBG(fmt, args...) pr_err(fmt, ##args)
-#else
-#define DEV_DBG(args...) (void)0
-#endif
-
-#define PORT_DEBUG 0
-#define REG_DUMP 0
-void hdmi_reg_w(void __iomem *addr, u32 offset, u32 value, u32 debug);
-u32 hdmi_reg_r(void __iomem *addr, u32 offset, u32 debug);
-
-#define HDMI_REG_W_ND(addr, offset, val) hdmi_reg_w(addr, offset, val, false)
-#define HDMI_REG_W(addr, offset, val) hdmi_reg_w(addr, offset, val, true)
-#define HDMI_REG_R_ND(addr, offset) hdmi_reg_r(addr, offset, false)
-#define HDMI_REG_R(addr, offset) hdmi_reg_r(addr, offset, true)
+#include "mdss_io_util.h"
/* HDMI_TX Registers */
#define HDMI_CTRL (0x00000000)
@@ -220,7 +201,7 @@
#define HDMI_TPG_BLK_WHT_PATTERN_FRAMES (0x00000358)
#define HDMI_TPG_RGB_MAPPING (0x0000035C)
-/* HDMI PHY Registers, use them with PHY base and _ND macro */
+/* HDMI PHY Registers */
#define HDMI_PHY_ANA_CFG0 (0x00000000)
#define HDMI_PHY_ANA_CFG1 (0x00000004)
#define HDMI_PHY_PD_CTRL0 (0x00000010)
@@ -231,6 +212,10 @@
#define HDMI_PHY_BIST_PATN2 (0x00000044)
#define HDMI_PHY_BIST_PATN3 (0x00000048)
+/* QFPROM Registers for HDMI/HDCP */
+#define QFPROM_RAW_FEAT_CONFIG_ROW0_LSB (0x000000F8)
+#define QFPROM_RAW_FEAT_CONFIG_ROW0_MSB (0x000000FC)
+
/* all video formats defined by EIA CEA 861D */
#define HDMI_VFRMT_640x480p60_4_3 0
#define HDMI_VFRMT_720x480p60_4_3 1
@@ -397,7 +382,7 @@
};
struct hdmi_tx_ddc_ctrl {
- void __iomem *base;
+ struct dss_io_data *io;
struct completion ddc_sw_done;
};
@@ -412,9 +397,6 @@
int retry;
};
-void hdmi_reg_dump(void __iomem *base, u32 length, const char *prefix);
-const char *hdmi_reg_name(u32 offset);
-
const struct hdmi_disp_mode_timing_type *hdmi_get_supported_mode(u32 mode);
void hdmi_set_supported_mode(u32 mode);
const char *hdmi_get_video_fmt_2string(u32 format);
diff --git a/drivers/video/msm/mdss/mdss_io_util.c b/drivers/video/msm/mdss/mdss_io_util.c
index 65d08d3..5778525 100644
--- a/drivers/video/msm/mdss/mdss_io_util.c
+++ b/drivers/video/msm/mdss/mdss_io_util.c
@@ -10,10 +10,65 @@
* GNU General Public License for more details.
*/
+#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include "mdss_io_util.h"
+void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug)
+{
+ u32 in_val;
+
+ if (!io || !io->base) {
+ DEV_ERR("%pS->%s: invalid input\n",
+ __builtin_return_address(0), __func__);
+ return;
+ }
+
+ if (offset > io->len) {
+ DEV_ERR("%pS->%s: offset out of range\n",
+ __builtin_return_address(0), __func__);
+ return;
+ }
+
+ writel_relaxed(value, io->base + offset);
+ if (debug) {
+ in_val = readl_relaxed(io->base + offset);
+ DEV_DBG("[%08x] => %08x [%08x]\n", (u32)(io->base + offset),
+ value, in_val);
+ }
+} /* dss_reg_w */
+
+u32 dss_reg_r(struct dss_io_data *io, u32 offset, u32 debug)
+{
+ u32 value;
+ if (!io || !io->base) {
+ DEV_ERR("%pS->%s: invalid input\n",
+ __builtin_return_address(0), __func__);
+ return -EINVAL;
+ }
+
+ if (offset > io->len) {
+ DEV_ERR("%pS->%s: offset out of range\n",
+ __builtin_return_address(0), __func__);
+ return -EINVAL;
+ }
+
+ value = readl_relaxed(io->base + offset);
+ if (debug)
+ DEV_DBG("[%08x] <= %08x\n", (u32)(io->base + offset), value);
+
+ return value;
+} /* dss_reg_r */
+
+void dss_reg_dump(void __iomem *base, u32 length, const char *prefix,
+ u32 debug)
+{
+ if (debug)
+ print_hex_dump(KERN_INFO, prefix, DUMP_PREFIX_OFFSET, 32, 4,
+ (void *)base, length, false);
+} /* dss_reg_dump */
+
static struct resource *msm_dss_get_res_byname(struct platform_device *pdev,
unsigned int type, const char *name)
{
@@ -21,11 +76,10 @@
res = platform_get_resource_byname(pdev, type, name);
if (!res)
- pr_err("%s: '%s' resource not found\n", __func__, name);
+ DEV_ERR("%s: '%s' resource not found\n", __func__, name);
return res;
-}
-
+} /* msm_dss_get_res_byname */
int msm_dss_ioremap_byname(struct platform_device *pdev,
struct dss_io_data *io_data, const char *name)
@@ -33,32 +87,49 @@
struct resource *res = NULL;
if (!pdev || !io_data) {
- pr_err("%s: invalid input\n", __func__);
+ DEV_ERR("%pS->%s: invalid input\n",
+ __builtin_return_address(0), __func__);
return -EINVAL;
}
res = msm_dss_get_res_byname(pdev, IORESOURCE_MEM, name);
if (!res) {
- pr_err("%s: '%s' msm_dss_get_res_byname failed\n",
- __func__, name);
+ DEV_ERR("%pS->%s: '%s' msm_dss_get_res_byname failed\n",
+ __builtin_return_address(0), __func__, name);
return -ENODEV;
}
io_data->len = resource_size(res);
io_data->base = ioremap(res->start, io_data->len);
if (!io_data->base) {
- pr_err("%s: '%s' ioremap failed\n", __func__, name);
+ DEV_ERR("%pS->%s: '%s' ioremap failed\n",
+ __builtin_return_address(0), __func__, name);
return -EIO;
}
return 0;
-}
+} /* msm_dss_ioremap_byname */
+
+void msm_dss_iounmap(struct dss_io_data *io_data)
+{
+ if (!io_data) {
+ DEV_ERR("%pS->%s: invalid input\n",
+ __builtin_return_address(0), __func__);
+ return;
+ }
+
+ if (io_data->base) {
+ iounmap(io_data->base);
+ io_data->base = NULL;
+ }
+ io_data->len = 0;
+} /* msm_dss_iounmap */
int msm_dss_config_vreg(struct device *dev, struct dss_vreg *in_vreg,
int num_vreg, int config)
{
int i = 0, rc = 0;
- struct dss_vreg *curr_vreg;
+ struct dss_vreg *curr_vreg = NULL;
if (config) {
for (i = 0; i < num_vreg; i++) {
@@ -67,8 +138,8 @@
curr_vreg->vreg_name);
rc = IS_ERR(curr_vreg->vreg);
if (rc) {
- pr_err("%s: %s get failed. rc=%d\n",
- __func__,
+ DEV_ERR("%pS->%s: %s get failed. rc=%d\n",
+ __builtin_return_address(0), __func__,
curr_vreg->vreg_name, rc);
curr_vreg->vreg = NULL;
goto vreg_get_fail;
@@ -79,7 +150,8 @@
curr_vreg->min_voltage,
curr_vreg->max_voltage);
if (rc < 0) {
- pr_err("%s: %s set voltage failed\n",
+ DEV_ERR("%pS->%s: %s set vltg fail\n",
+ __builtin_return_address(0),
__func__,
curr_vreg->vreg_name);
goto vreg_set_voltage_fail;
@@ -89,8 +161,9 @@
curr_vreg->vreg,
curr_vreg->optimum_voltage);
if (rc < 0) {
- pr_err(
- "%s: %s set opt mode failed\n",
+ DEV_ERR(
+ "%pS->%s: %s set opt m fail\n",
+ __builtin_return_address(0),
__func__,
curr_vreg->vreg_name);
goto vreg_set_opt_mode_fail;
@@ -144,14 +217,16 @@
for (i = 0; i < num_vreg; i++) {
rc = IS_ERR(in_vreg[i].vreg);
if (rc) {
- pr_err("%s: %s regulator error. rc=%d\n",
- __func__, in_vreg[i].vreg_name, rc);
+ DEV_ERR("%pS->%s: %s regulator error. rc=%d\n",
+ __builtin_return_address(0), __func__,
+ in_vreg[i].vreg_name, rc);
goto disable_vreg;
}
rc = regulator_enable(in_vreg[i].vreg);
if (rc < 0) {
- pr_err("%s: %s enable failed\n",
- __func__, in_vreg[i].vreg_name);
+ DEV_ERR("%pS->%s: %s enable failed\n",
+ __builtin_return_address(0), __func__,
+ in_vreg[i].vreg_name);
goto disable_vreg;
}
}
@@ -176,8 +251,9 @@
rc = gpio_request(in_gpio[i].gpio,
in_gpio[i].gpio_name);
if (rc < 0) {
- pr_err("%s: %s enable failed\n",
- __func__, in_gpio[i].gpio_name);
+ DEV_ERR("%pS->%s: %s enable failed\n",
+ __builtin_return_address(0), __func__,
+ in_gpio[i].gpio_name);
goto disable_gpio;
}
}
@@ -192,3 +268,117 @@
gpio_free(in_gpio[i].gpio);
return rc;
} /* msm_dss_enable_gpio */
+
+void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk)
+{
+ int i;
+
+ for (i = num_clk - 1; i >= 0; i--) {
+ if (clk_arry[i].clk)
+ clk_put(clk_arry[i].clk);
+ clk_arry[i].clk = NULL;
+ }
+} /* msm_dss_put_clk */
+
+int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk)
+{
+ int i, rc = 0;
+
+ for (i = 0; i < num_clk; i++) {
+ clk_arry[i].clk = clk_get(dev, clk_arry[i].clk_name);
+ rc = IS_ERR(clk_arry[i].clk);
+ if (rc) {
+ DEV_ERR("%pS->%s: '%s' get failed. rc=%d\n",
+ __builtin_return_address(0), __func__,
+ clk_arry[i].clk_name, rc);
+ goto error;
+ }
+ }
+
+ return rc;
+
+error:
+ msm_dss_put_clk(clk_arry, num_clk);
+
+ return rc;
+} /* msm_dss_get_clk */
+
+int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk)
+{
+ int i, rc = 0;
+
+ for (i = 0; i < num_clk; i++) {
+ if (clk_arry[i].clk) {
+ if (DSS_CLK_AHB != clk_arry[i].type) {
+ DEV_DBG("%pS->%s: '%s' rate %ld\n",
+ __builtin_return_address(0), __func__,
+ clk_arry[i].clk_name,
+ clk_arry[i].rate);
+ rc = clk_set_rate(clk_arry[i].clk,
+ clk_arry[i].rate);
+ if (rc) {
+ DEV_ERR("%pS->%s: %s failed. rc=%d\n",
+ __builtin_return_address(0),
+ __func__,
+ clk_arry[i].clk_name, rc);
+ break;
+ }
+ }
+ } else {
+ DEV_ERR("%pS->%s: '%s' is not available\n",
+ __builtin_return_address(0), __func__,
+ clk_arry[i].clk_name);
+ rc = -EPERM;
+ break;
+ }
+ }
+
+ return rc;
+} /* msm_dss_clk_set_rate */
+
+int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable)
+{
+ int i, rc = 0;
+
+ if (enable) {
+ for (i = 0; i < num_clk; i++) {
+ DEV_DBG("%pS->%s: enable '%s'\n",
+ __builtin_return_address(0), __func__,
+ clk_arry[i].clk_name);
+ if (clk_arry[i].clk) {
+ rc = clk_prepare_enable(clk_arry[i].clk);
+ if (rc)
+ DEV_ERR("%pS->%s: %s en fail. rc=%d\n",
+ __builtin_return_address(0),
+ __func__,
+ clk_arry[i].clk_name, rc);
+ } else {
+ DEV_ERR("%pS->%s: '%s' is not available\n",
+ __builtin_return_address(0), __func__,
+ clk_arry[i].clk_name);
+ rc = -EPERM;
+ }
+
+ if (rc) {
+ msm_dss_enable_clk(&clk_arry[i],
+ i, false);
+ break;
+ }
+ }
+ } else {
+ for (i = num_clk - 1; i >= 0; i--) {
+ DEV_DBG("%pS->%s: disable '%s'\n",
+ __builtin_return_address(0), __func__,
+ clk_arry[i].clk_name);
+
+ if (clk_arry[i].clk)
+ clk_disable_unprepare(clk_arry[i].clk);
+ else
+ DEV_ERR("%pS->%s: '%s' is not available\n",
+ __builtin_return_address(0), __func__,
+ clk_arry[i].clk_name);
+ }
+ }
+
+ return rc;
+} /* msm_dss_enable_clk */
diff --git a/drivers/video/msm/mdss/mdss_io_util.h b/drivers/video/msm/mdss/mdss_io_util.h
index 9671414..51e9e54 100644
--- a/drivers/video/msm/mdss/mdss_io_util.h
+++ b/drivers/video/msm/mdss/mdss_io_util.h
@@ -17,11 +17,29 @@
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
+#ifdef DEBUG
+#define DEV_DBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define DEV_DBG(fmt, args...) pr_debug(fmt, ##args)
+#endif
+#define DEV_INFO(fmt, args...) pr_info(fmt, ##args)
+#define DEV_WARN(fmt, args...) pr_warn(fmt, ##args)
+#define DEV_ERR(fmt, args...) pr_err(fmt, ##args)
+
struct dss_io_data {
u32 len;
void __iomem *base;
};
+void dss_reg_w(struct dss_io_data *io, u32 offset, u32 value, u32 debug);
+u32 dss_reg_r(struct dss_io_data *io, u32 offset, u32 debug);
+void dss_reg_dump(void __iomem *base, u32 len, const char *prefix, u32 debug);
+
+#define DSS_REG_W_ND(io, offset, val) dss_reg_w(io, offset, val, false)
+#define DSS_REG_W(io, offset, val) dss_reg_w(io, offset, val, true)
+#define DSS_REG_R_ND(io, offset) dss_reg_r(io, offset, false)
+#define DSS_REG_R(io, offset) dss_reg_r(io, offset, true)
+
enum dss_vreg_type {
DSS_REG_LDO,
DSS_REG_VS,
@@ -41,19 +59,42 @@
char gpio_name[32];
};
+enum dss_clk_type {
+ DSS_CLK_AHB, /* no set rate. rate controlled through rpm */
+ DSS_CLK_PCLK,
+ DSS_CLK_OTHER,
+};
+
+struct dss_clk {
+ struct clk *clk; /* clk handle */
+ char clk_name[32];
+ enum dss_clk_type type;
+ unsigned long rate;
+};
+
struct dss_module_power {
unsigned num_vreg;
struct dss_vreg *vreg_config;
unsigned num_gpio;
struct dss_gpio *gpio_config;
+ unsigned num_clk;
+ struct dss_clk *clk_config;
};
int msm_dss_ioremap_byname(struct platform_device *pdev,
struct dss_io_data *io_data, const char *name);
+void msm_dss_iounmap(struct dss_io_data *io_data);
+
int msm_dss_enable_gpio(struct dss_gpio *in_gpio, int num_gpio, int enable);
int msm_dss_gpio_enable(struct dss_gpio *in_gpio, int num_gpio, int enable);
+
int msm_dss_config_vreg(struct device *dev, struct dss_vreg *in_vreg,
int num_vreg, int config);
int msm_dss_enable_vreg(struct dss_vreg *in_vreg, int num_vreg, int enable);
+int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk);
+void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk);
+int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk);
+int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable);
+
#endif /* __MDSS_IO_UTIL_H__ */
diff --git a/include/linux/mfd/pm8xxx/batterydata-lib.h b/include/linux/mfd/pm8xxx/batterydata-lib.h
new file mode 100644
index 0000000..c55e47e
--- /dev/null
+++ b/include/linux/mfd/pm8xxx/batterydata-lib.h
@@ -0,0 +1,155 @@
+/* Copyright (c) 2012, 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
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __PM8XXX_BMS_BATTERYDATA_H
+#define __PM8XXX_BMS_BATTERYDATA_H
+
+#include <linux/errno.h>
+
+#define FCC_CC_COLS 5
+#define FCC_TEMP_COLS 8
+
+#define PC_CC_ROWS 29
+#define PC_CC_COLS 13
+
+#define PC_TEMP_ROWS 29
+#define PC_TEMP_COLS 8
+
+#define MAX_SINGLE_LUT_COLS 20
+
+struct single_row_lut {
+ int x[MAX_SINGLE_LUT_COLS];
+ int y[MAX_SINGLE_LUT_COLS];
+ int cols;
+};
+
+/**
+ * struct sf_lut -
+ * @rows: number of percent charge entries should be <= PC_CC_ROWS
+ * @cols: number of charge cycle entries should be <= PC_CC_COLS
+ * @row_entries: the charge cycles/temperature at which sf data
+ * is available in the table.
+ * The charge cycles must be in increasing order from 0 to rows.
+ * @percent: the percent charge at which sf data is available in the table
+ * The percentcharge must be in decreasing order from 0 to cols.
+ * @sf: the scaling factor data
+ */
+struct sf_lut {
+ int rows;
+ int cols;
+ int row_entries[PC_CC_COLS];
+ int percent[PC_CC_ROWS];
+ int sf[PC_CC_ROWS][PC_CC_COLS];
+};
+
+/**
+ * struct pc_temp_ocv_lut -
+ * @rows: number of percent charge entries should be <= PC_TEMP_ROWS
+ * @cols: number of temperature entries should be <= PC_TEMP_COLS
+ * @temp: the temperatures at which ocv data is available in the table
+ * The temperatures must be in increasing order from 0 to rows.
+ * @percent: the percent charge at which ocv data is available in the table
+ * The percentcharge must be in decreasing order from 0 to cols.
+ * @ocv: the open circuit voltage
+ */
+struct pc_temp_ocv_lut {
+ int rows;
+ int cols;
+ int temp[PC_TEMP_COLS];
+ int percent[PC_TEMP_ROWS];
+ int ocv[PC_TEMP_ROWS][PC_TEMP_COLS];
+};
+
+enum battery_type {
+ BATT_UNKNOWN = 0,
+ BATT_PALLADIUM,
+ BATT_DESAY,
+};
+
+/**
+ * struct bms_battery_data -
+ * @fcc: full charge capacity (mAmpHour)
+ * @fcc_temp_lut: table to get fcc at a given temp
+ * @pc_temp_ocv_lut: table to get percent charge given batt temp and cycles
+ * @pc_sf_lut: table to get percent charge scaling factor given cycles
+ * and percent charge
+ * @rbatt_sf_lut: table to get battery resistance scaling factor given
+ * temperature and percent charge
+ * @default_rbatt_mohm: the default value of battery resistance to use when
+ * readings from bms are not available.
+ * @delta_rbatt_mohm: the resistance to be added towards lower soc to
+ * compensate for battery capacitance.
+ */
+
+struct bms_battery_data {
+ unsigned int fcc;
+ struct single_row_lut *fcc_temp_lut;
+ struct single_row_lut *fcc_sf_lut;
+ struct pc_temp_ocv_lut *pc_temp_ocv_lut;
+ struct sf_lut *pc_sf_lut;
+ struct sf_lut *rbatt_sf_lut;
+ int default_rbatt_mohm;
+ int delta_rbatt_mohm;
+};
+
+#if defined(CONFIG_PM8921_BMS) || \
+ defined(CONFIG_PM8921_BMS_MODULE)
+extern struct bms_battery_data palladium_1500_data;
+extern struct bms_battery_data desay_5200_data;
+
+int interpolate_fcc(struct single_row_lut *fcc_temp_lut, int batt_temp);
+int interpolate_scalingfactor(struct sf_lut *sf_lut, int row_entry, int pc);
+int interpolate_scalingfactor_fcc(struct single_row_lut *fcc_sf_lut,
+ int cycles);
+int interpolate_pc(struct pc_temp_ocv_lut *pc_temp_ocv,
+ int batt_temp_degc, int ocv);
+int interpolate_ocv(struct pc_temp_ocv_lut *pc_temp_ocv,
+ int batt_temp_degc, int pc);
+int linear_interpolate(int y0, int x0, int y1, int x1, int x);
+int is_between(int left, int right, int value);
+#else
+static inline int interpolate_fcc(struct single_row_lut *fcc_temp_lut,
+ int batt_temp)
+{
+ return -EINVAL;
+}
+static inline int interpolate_scalingfactor(struct sf_lut *sf_lut,
+ int row_entry, int pc)
+{
+ return -EINVAL;
+}
+static inline int interpolate_scalingfactor_fcc(
+ struct single_row_lut *fcc_sf_lut, int cycles)
+{
+ return -EINVAL;
+}
+static inline int interpolate_pc(struct pc_temp_ocv_lut *pc_temp_ocv,
+ int batt_temp_degc, int ocv)
+{
+ return -EINVAL;
+}
+static inline int interpolate_ocv(struct pc_temp_ocv_lut *pc_temp_ocv,
+ int batt_temp_degc, int pc)
+{
+ return -EINVAL;
+}
+static inline int linear_interpolate(int y0, int x0, int y1, int x1, int x)
+{
+ return -EINVAL;
+}
+static inline int is_between(int left, int right, int value)
+{
+ return -EINVAL;
+}
+#endif
+
+#endif
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index a73a284..5f2fe9f 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -14,87 +14,10 @@
#define __PM8XXX_BMS_H
#include <linux/errno.h>
+#include <linux/mfd/pm8xxx/batterydata-lib.h>
#define PM8921_BMS_DEV_NAME "pm8921-bms"
-#define FCC_CC_COLS 5
-#define FCC_TEMP_COLS 8
-
-#define PC_CC_ROWS 29
-#define PC_CC_COLS 13
-
-#define PC_TEMP_ROWS 29
-#define PC_TEMP_COLS 8
-
-#define MAX_SINGLE_LUT_COLS 20
-
-struct single_row_lut {
- int x[MAX_SINGLE_LUT_COLS];
- int y[MAX_SINGLE_LUT_COLS];
- int cols;
-};
-
-/**
- * struct sf_lut -
- * @rows: number of percent charge entries should be <= PC_CC_ROWS
- * @cols: number of charge cycle entries should be <= PC_CC_COLS
- * @row_entries: the charge cycles/temperature at which sf data
- * is available in the table.
- * The charge cycles must be in increasing order from 0 to rows.
- * @percent: the percent charge at which sf data is available in the table
- * The percentcharge must be in decreasing order from 0 to cols.
- * @sf: the scaling factor data
- */
-struct sf_lut {
- int rows;
- int cols;
- int row_entries[PC_CC_COLS];
- int percent[PC_CC_ROWS];
- int sf[PC_CC_ROWS][PC_CC_COLS];
-};
-
-/**
- * struct pc_temp_ocv_lut -
- * @rows: number of percent charge entries should be <= PC_TEMP_ROWS
- * @cols: number of temperature entries should be <= PC_TEMP_COLS
- * @temp: the temperatures at which ocv data is available in the table
- * The temperatures must be in increasing order from 0 to rows.
- * @percent: the percent charge at which ocv data is available in the table
- * The percentcharge must be in decreasing order from 0 to cols.
- * @ocv: the open circuit voltage
- */
-struct pc_temp_ocv_lut {
- int rows;
- int cols;
- int temp[PC_TEMP_COLS];
- int percent[PC_TEMP_ROWS];
- int ocv[PC_TEMP_ROWS][PC_TEMP_COLS];
-};
-
-/**
- * struct pm8921_bms_battery_data -
- * @fcc: full charge capacity (mAmpHour)
- * @fcc_temp_lut: table to get fcc at a given temp
- * @pc_temp_ocv_lut: table to get percent charge given batt temp and cycles
- * @pc_sf_lut: table to get percent charge scaling factor given cycles
- * and percent charge
- * @rbatt_sf_lut: table to get battery resistance scaling factor given
- * temperature and percent charge
- * @default_rbatt_mohm: the default value of battery resistance to use when
- * readings from bms are not available.
- * @delta_rbatt_mohm: the resistance to be added towards lower soc to
- * compensate for battery capacitance.
- */
-struct pm8921_bms_battery_data {
- unsigned int fcc;
- struct single_row_lut *fcc_temp_lut;
- struct single_row_lut *fcc_sf_lut;
- struct pc_temp_ocv_lut *pc_temp_ocv_lut;
- struct sf_lut *pc_sf_lut;
- struct sf_lut *rbatt_sf_lut;
- int default_rbatt_mohm;
- int delta_rbatt_mohm;
-};
struct pm8xxx_bms_core_data {
unsigned int batt_temp_channel;
@@ -104,12 +27,6 @@
unsigned int batt_id_channel;
};
-enum battery_type {
- BATT_UNKNOWN = 0,
- BATT_PALLADIUM,
- BATT_DESAY,
-};
-
/**
* struct pm8921_bms_platform_data -
* @batt_type: allows to force chose battery calibration data
@@ -137,8 +54,6 @@
};
#if defined(CONFIG_PM8921_BMS) || defined(CONFIG_PM8921_BMS_MODULE)
-extern struct pm8921_bms_battery_data palladium_1500_data;
-extern struct pm8921_bms_battery_data desay_5200_data;
/**
* pm8921_bms_get_vsense_avg - return the voltage across the sense
* resitor in microvolts
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 647a7ef..03390b1 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -223,9 +223,14 @@
extern int power_supply_set_supply_type(struct power_supply *psy,
enum power_supply_type supply_type);
extern int power_supply_is_system_supplied(void);
+extern int power_supply_register(struct device *parent,
+ struct power_supply *psy);
+extern void power_supply_unregister(struct power_supply *psy);
+extern int power_supply_powers(struct power_supply *psy, struct device *dev);
#else
static inline struct power_supply *power_supply_get_by_name(char *name)
- { return -ENOSYS; }
+ { return NULL; }
+static inline void power_supply_changed(struct power_supply *psy) { }
static inline int power_supply_am_i_supplied(struct power_supply *psy)
{ return -ENOSYS; }
static inline int power_supply_set_battery_charged(struct power_supply *psy)
@@ -243,16 +248,18 @@
int type)
{ return -ENOSYS; }
static inline int power_supply_set_supply_type(struct power_supply *psy,
- enum power_supply_type supply_type);
+ enum power_supply_type supply_type)
{ return -ENOSYS; }
static inline int power_supply_is_system_supplied(void) { return -ENOSYS; }
+static inline int power_supply_register(struct device *parent,
+ struct power_supply *psy)
+ { return -ENOSYS; }
+static inline void power_supply_unregister(struct power_supply *psy) { }
+static inline int power_supply_powers(struct power_supply *psy,
+ struct device *dev)
+ { return -ENOSYS; }
#endif
-extern int power_supply_register(struct device *parent,
- struct power_supply *psy);
-extern void power_supply_unregister(struct power_supply *psy);
-extern int power_supply_powers(struct power_supply *psy, struct device *dev);
-
/* For APM emulation, think legacy userspace. */
extern struct class *power_supply_class;
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 1da6aa2..d902881 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -1890,6 +1890,7 @@
struct afe_param_id_hdmi_multi_chan_audio_cfg hdmi_multi_ch;
struct afe_param_id_slimbus_cfg slim_sch;
struct afe_param_id_rt_proxy_port_cfg rtproxy;
+ struct afe_param_id_internal_bt_fm_cfg int_bt_fm;
} __packed;
struct afe_audioif_config_command {
diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h
index 8ccc9f4..e107130 100644
--- a/include/sound/q6afe-v2.h
+++ b/include/sound/q6afe-v2.h
@@ -13,6 +13,8 @@
#define __Q6AFE_V2_H__
#include <sound/apr_audio-v2.h>
+#define IN 0x000
+#define OUT 0x001
#define MSM_AFE_MONO 0
#define MSM_AFE_MONO_RIGHT 1
#define MSM_AFE_MONO_LEFT 2
@@ -71,6 +73,40 @@
AFE_MAX_PORTS
};
+struct afe_audio_buffer {
+ dma_addr_t phys;
+ void *data;
+ uint32_t used;
+ uint32_t size;/* size of buffer */
+ uint32_t actual_size; /* actual number of bytes read by DSP */
+ struct ion_handle *handle;
+ struct ion_client *client;
+};
+
+struct afe_audio_port_data {
+ struct afe_audio_buffer *buf;
+ uint32_t max_buf_cnt;
+ uint32_t dsp_buf;
+ uint32_t cpu_buf;
+ struct list_head mem_map_handle;
+ uint32_t tmp_hdl;
+ /* read or write locks */
+ struct mutex lock;
+ spinlock_t dsp_lock;
+};
+
+struct afe_audio_client {
+ atomic_t cmd_state;
+ /* Relative or absolute TS */
+ uint32_t time_flag;
+ void *priv;
+ uint64_t time_stamp;
+ struct mutex cmd_lock;
+ /* idx:1 out port, 0: in port*/
+ struct afe_audio_port_data port[2];
+ wait_queue_head_t cmd_wait;
+};
+
int afe_open(u16 port_id, union afe_port_config *afe_config, int rate);
int afe_close(int port_id);
int afe_loopback(u16 enable, u16 rx_port, u16 tx_port);
@@ -80,6 +116,7 @@
int afe_get_port_index(u16 port_id);
int afe_start_pseudo_port(u16 port_id);
int afe_stop_pseudo_port(u16 port_id);
+uint32_t afe_req_mmap_handle(void);
int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz);
int afe_cmd_memory_map_nowait(int port_id, u32 dma_addr_p, u32 dma_buf_sz);
int afe_cmd_memory_unmap(u32 dma_addr_p);
@@ -98,6 +135,14 @@
int afe_apply_gain(u16 port_id, u16 gain);
int afe_q6_interface_prepare(void);
int afe_get_port_type(u16 port_id);
+int q6afe_audio_client_buf_alloc_contiguous(unsigned int dir,
+ struct afe_audio_client *ac,
+ unsigned int bufsz,
+ unsigned int bufcnt);
+struct afe_audio_client *q6afe_audio_client_alloc(void *priv);
+int q6afe_audio_client_buf_free_contiguous(unsigned int dir,
+ struct afe_audio_client *ac);
+void q6afe_audio_client_free(struct afe_audio_client *ac);
/* if port_id is virtual, convert to physical..
* if port_id is already physical, return physical
*/
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index 92b7324..f462299 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -81,6 +81,7 @@
static int msm_slim_0_tx_ch = 1;
static int msm_btsco_rate = BTSCO_RATE_8KHZ;
+static int msm_btsco_ch = 1;
static struct snd_soc_jack hs_jack;
static struct snd_soc_jack button_jack;
@@ -480,6 +481,21 @@
msm_btsco_rate_get, msm_btsco_rate_put),
};
+static int msm_btsco_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+
+ rate->min = rate->max = msm_btsco_rate;
+ channels->min = channels->max = msm_btsco_ch;
+
+ return 0;
+}
+
static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params)
{
@@ -495,6 +511,19 @@
return 0;
}
+
+static int msm_proxy_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_interval *rate = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_RATE);
+
+ pr_debug("%s()\n", __func__);
+ rate->min = rate->max = 48000;
+
+ return 0;
+}
+
static int msm_aux_pcm_get_gpios(void)
{
int ret = 0;
@@ -780,19 +809,19 @@
.be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
},
{
- .name = "MSM VoIP",
- .stream_name = "VoIP",
- .cpu_dai_name = "VoIP",
- .platform_name = "msm-voip-dsp",
+ .name = "MSM8974 Media2",
+ .stream_name = "MultiMedia2",
+ .cpu_dai_name = "MultiMedia2",
+ .platform_name = "msm-pcm-dsp",
.dynamic = 1,
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
.ignore_suspend = 1,
/* this dainlink has playback support */
.ignore_pmdown_time = 1,
- .be_id = MSM_FRONTEND_DAI_VOIP,
+ .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
},
{
.name = "Circuit-Switch Voice",
@@ -811,6 +840,21 @@
.be_id = MSM_FRONTEND_DAI_CS_VOICE,
},
{
+ .name = "MSM VoIP",
+ .stream_name = "VoIP",
+ .cpu_dai_name = "VoIP",
+ .platform_name = "msm-voip-dsp",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .be_id = MSM_FRONTEND_DAI_VOIP,
+ },
+ {
.name = "MSM8974 LPA",
.stream_name = "LPA",
.cpu_dai_name = "MultiMedia3",
@@ -841,6 +885,41 @@
.codec_name = "snd-soc-dummy",
},
{
+ .name = "INT_FM Hostless",
+ .stream_name = "INT_FM Hostless",
+ .cpu_dai_name = "INT_FM_HOSTLESS",
+ .platform_name = "msm-pcm-hostless",
+ .dynamic = 1,
+ .trigger = {SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST},
+ .no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ .codec_dai_name = "snd-soc-dummy-dai",
+ .codec_name = "snd-soc-dummy",
+ },
+ {
+ .name = "MSM AFE-PCM RX",
+ .stream_name = "AFE-PROXY RX",
+ .cpu_dai_name = "msm-dai-q6-dev.241",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .platform_name = "msm-pcm-afe",
+ .ignore_suspend = 1,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ },
+ {
+ .name = "MSM AFE-PCM TX",
+ .stream_name = "AFE-PROXY TX",
+ .cpu_dai_name = "msm-dai-q6-dev.240",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .platform_name = "msm-pcm-afe",
+ .ignore_suspend = 1,
+ },
+ {
.name = "MSM8974 Compr",
.stream_name = "COMPR",
.cpu_dai_name = "MultiMedia4",
@@ -870,19 +949,55 @@
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
},
+ /* Backend BT/FM DAI Links */
{
- .name = "MSM8974 Media2",
- .stream_name = "MultiMedia2",
- .cpu_dai_name = "MultiMedia2",
- .platform_name = "msm-pcm-dsp",
- .dynamic = 1,
- .codec_dai_name = "snd-soc-dummy-dai",
- .codec_name = "snd-soc-dummy",
- .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- SND_SOC_DPCM_TRIGGER_POST},
- .ignore_suspend = 1,
+ .name = LPASS_BE_INT_BT_SCO_RX,
+ .stream_name = "Internal BT-SCO Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.12288",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_INT_BT_SCO_RX,
+ .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
+ /* this dainlink has playback support */
.ignore_pmdown_time = 1,
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
+ },
+ {
+ .name = LPASS_BE_INT_BT_SCO_TX,
+ .stream_name = "Internal BT-SCO Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.12289",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_INT_BT_SCO_TX,
+ .be_hw_params_fixup = msm_btsco_be_hw_params_fixup,
+ },
+ /* Backend AFE DAI Links */
+ {
+ .name = LPASS_BE_AFE_PCM_RX,
+ .stream_name = "AFE Playback",
+ .cpu_dai_name = "msm-dai-q6-dev.224",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-rx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+ .be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
+ /* this dainlink has playback support */
+ .ignore_pmdown_time = 1,
+ },
+ {
+ .name = LPASS_BE_AFE_PCM_TX,
+ .stream_name = "AFE Capture",
+ .cpu_dai_name = "msm-dai-q6-dev.225",
+ .platform_name = "msm-pcm-routing",
+ .codec_name = "msm-stub-codec.1",
+ .codec_dai_name = "msm-stub-tx",
+ .no_pcm = 1,
+ .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
+ .be_hw_params_fixup = msm_proxy_be_hw_params_fixup,
},
/* AUX PCM Backend DAI Links */
{
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 3eab972..a6cdad2 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -540,6 +540,14 @@
memset(&dai_data->port_config, 0, sizeof(dai_data->port_config));
+ pr_debug("%s: setting bt_fm parameters\n", __func__);
+
+ dai_data->port_config.int_bt_fm.bt_fm_cfg_minor_version =
+ AFE_API_VERSION_INTERNAL_BT_FM_CONFIG;
+ dai_data->port_config.int_bt_fm.num_channels = dai_data->channels;
+ dai_data->port_config.int_bt_fm.sample_rate = dai_data->rate;
+ dai_data->port_config.int_bt_fm.bit_width = 16;
+
return 0;
}
@@ -805,6 +813,36 @@
return 0;
}
+static struct snd_soc_dai_driver msm_dai_q6_afe_rx_dai = {
+ .playback = {
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_dai_q6_ops,
+ .probe = msm_dai_q6_dai_probe,
+ .remove = msm_dai_q6_dai_remove,
+};
+
+static struct snd_soc_dai_driver msm_dai_q6_afe_tx_dai = {
+ .capture = {
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
+ SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 4,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ },
+ .ops = &msm_dai_q6_ops,
+ .probe = msm_dai_q6_dai_probe,
+ .remove = msm_dai_q6_dai_remove,
+};
+
static struct snd_soc_dai_driver msm_dai_q6_slimbus_1_rx_dai = {
.playback = {
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
@@ -833,6 +871,34 @@
.remove = msm_dai_q6_dai_remove,
};
+static struct snd_soc_dai_driver msm_dai_q6_bt_sco_rx_dai = {
+ .playback = {
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 1,
+ .rate_max = 16000,
+ .rate_min = 8000,
+ },
+ .ops = &msm_dai_q6_ops,
+ .probe = msm_dai_q6_dai_probe,
+ .remove = msm_dai_q6_dai_remove,
+};
+
+static struct snd_soc_dai_driver msm_dai_q6_bt_sco_tx_dai = {
+ .capture = {
+ .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .channels_min = 1,
+ .channels_max = 1,
+ .rate_max = 16000,
+ .rate_min = 8000,
+ },
+ .ops = &msm_dai_q6_ops,
+ .probe = msm_dai_q6_dai_probe,
+ .remove = msm_dai_q6_dai_remove,
+};
+
static int __devinit msm_auxpcm_dev_probe(struct platform_device *pdev)
{
int id;
@@ -1084,6 +1150,22 @@
rc = snd_soc_register_dai(&pdev->dev,
&msm_dai_q6_slimbus_1_tx_dai);
break;
+ case INT_BT_SCO_RX:
+ rc = snd_soc_register_dai(&pdev->dev,
+ &msm_dai_q6_bt_sco_rx_dai);
+ break;
+ case INT_BT_SCO_TX:
+ rc = snd_soc_register_dai(&pdev->dev,
+ &msm_dai_q6_bt_sco_tx_dai);
+ break;
+ case RT_PROXY_DAI_001_RX:
+ case RT_PROXY_DAI_002_RX:
+ rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_rx_dai);
+ break;
+ case RT_PROXY_DAI_001_TX:
+ case RT_PROXY_DAI_002_TX:
+ rc = snd_soc_register_dai(&pdev->dev, &msm_dai_q6_afe_tx_dai);
+ break;
default:
rc = -ENODEV;
break;
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
index 4593784..73a04c2 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.c
@@ -29,6 +29,8 @@
#include <sound/control.h>
#include <sound/q6adm-v2.h>
#include <asm/dma.h>
+#include <linux/memory_alloc.h>
+#include <mach/msm_subsystem_map.h>
#include "msm-pcm-afe-v2.h"
#define MIN_PERIOD_SIZE (128 * 2)
@@ -63,6 +65,11 @@
struct snd_pcm_substream *substream = prtd->substream;
struct snd_pcm_runtime *runtime = substream->runtime;
u32 mem_map_handle = 0;
+
+ mem_map_handle = afe_req_mmap_handle();
+ if (!mem_map_handle)
+ pr_err("%s: mem_map_handle is NULL\n", __func__);
+
if (prtd->start) {
pr_debug("sending frame to DSP: poll_time: %d\n",
prtd->poll_time);
@@ -89,10 +96,15 @@
struct snd_pcm_substream *substream = prtd->substream;
struct snd_pcm_runtime *runtime = substream->runtime;
u32 mem_map_handle = 0;
+
+ mem_map_handle = afe_req_mmap_handle();
+ if (!mem_map_handle)
+ pr_err("%s: mem_map_handle is NULL\n", __func__);
+
if (prtd->start) {
if (prtd->dsp_cnt == runtime->periods)
prtd->dsp_cnt = 0;
- pr_err("%s: mem_map_handle 0x%x\n", __func__, mem_map_handle);
+ pr_debug("%s: mem_map_handle 0x%x\n", __func__, mem_map_handle);
afe_rt_proxy_port_read(
(prtd->dma_addr + (prtd->dsp_cnt
* snd_pcm_lib_period_bytes(prtd->substream))), mem_map_handle,
@@ -137,9 +149,6 @@
runtime->channels * 2)));
pr_debug("prtd->poll_time: %d",
prtd->poll_time);
- hrtimer_start(&prtd->hrt,
- ns_to_ktime(0),
- HRTIMER_MODE_REL);
break;
}
case AFE_EVENT_RTPORT_STOP:
@@ -203,9 +212,6 @@
snd_pcm_lib_period_bytes(prtd->substream)
* 1000 * 1000)/(runtime->rate
* runtime->channels * 2)));
- hrtimer_start(&prtd->hrt,
- ns_to_ktime(0),
- HRTIMER_MODE_REL);
pr_debug("prtd->poll_time : %d", prtd->poll_time);
break;
}
@@ -321,13 +327,21 @@
runtime->hw = msm_afe_hardware;
prtd->substream = substream;
runtime->private_data = prtd;
- mutex_unlock(&prtd->lock);
+ prtd->audio_client = q6afe_audio_client_alloc(prtd);
+ if (!prtd->audio_client) {
+ pr_debug("%s: Could not allocate memory\n", __func__);
+ kfree(prtd);
+ mutex_unlock(&prtd->lock);
+ return -ENOMEM;
+ }
+
hrtimer_init(&prtd->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
prtd->hrt.function = afe_hrtimer_callback;
else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
prtd->hrt.function = afe_hrtimer_rec_callback;
+ mutex_unlock(&prtd->lock);
ret = snd_pcm_hw_constraint_list(runtime, 0,
SNDRV_PCM_HW_PARAM_RATE,
&constraints_sample_rates);
@@ -350,6 +364,7 @@
struct pcm_afe_info *prtd;
struct snd_soc_pcm_runtime *rtd = NULL;
struct snd_soc_dai *dai = NULL;
+ int dir = IN;
int ret = 0;
pr_debug("%s\n", __func__);
@@ -365,17 +380,19 @@
mutex_lock(&prtd->lock);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ dir = IN;
ret = afe_unregister_get_events(dai->id);
if (ret < 0)
pr_err("AFE unregister for events failed\n");
} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ dir = OUT;
ret = afe_unregister_get_events(dai->id);
if (ret < 0)
pr_err("AFE unregister for events failed\n");
}
hrtimer_cancel(&prtd->hrt);
- rc = afe_cmd_memory_unmap(runtime->dma_addr);
+ rc = afe_cmd_memory_unmap(afe_req_mmap_handle());
if (rc < 0)
pr_err("AFE memory unmap failed\n");
@@ -384,15 +401,14 @@
if (dma_buf == NULL) {
pr_debug("dma_buf is NULL\n");
goto done;
- }
- if (dma_buf->area != NULL) {
- dma_free_coherent(substream->pcm->card->dev,
- runtime->hw.buffer_bytes_max, dma_buf->area,
- dma_buf->addr);
- dma_buf->area = NULL;
}
+
+ if (dma_buf->area)
+ dma_buf->area = NULL;
+ q6afe_audio_client_buf_free_contiguous(dir, prtd->audio_client);
done:
pr_debug("%s: dai->id =%x\n", __func__, dai->id);
+ q6afe_audio_client_free(prtd->audio_client);
mutex_unlock(&prtd->lock);
prtd->prepared--;
kfree(prtd);
@@ -420,14 +436,21 @@
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct pcm_afe_info *prtd = runtime->private_data;
+ int result = 0;
pr_debug("%s\n", __func__);
prtd->mmap_flag = 1;
- dma_mmap_coherent(substream->pcm->card->dev, vma,
- runtime->dma_area,
- runtime->dma_addr,
- runtime->dma_bytes);
- return 0;
+ if (runtime->dma_addr && runtime->dma_bytes) {
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ result = remap_pfn_range(vma, vma->vm_start,
+ runtime->dma_addr >> PAGE_SHIFT,
+ runtime->dma_bytes,
+ vma->vm_page_prot);
+ } else {
+ pr_err("Physical address or size of buf is NULL");
+ return -EINVAL;
+ }
+ return result;
}
static int msm_afe_trigger(struct snd_pcm_substream *substream, int cmd)
{
@@ -441,6 +464,8 @@
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
pr_debug("%s: SNDRV_PCM_TRIGGER_START\n", __func__);
prtd->start = 1;
+ hrtimer_start(&prtd->hrt, ns_to_ktime(0),
+ HRTIMER_MODE_REL);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -460,27 +485,45 @@
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
struct pcm_afe_info *prtd = runtime->private_data;
- int rc;
+ struct afe_audio_buffer *buf;
+ int dir, rc;
pr_debug("%s:\n", __func__);
mutex_lock(&prtd->lock);
-
- dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
- dma_buf->dev.dev = substream->pcm->card->dev;
- dma_buf->private_data = NULL;
- dma_buf->area = dma_alloc_coherent(dma_buf->dev.dev,
- runtime->hw.buffer_bytes_max,
- &dma_buf->addr, GFP_KERNEL);
-
- pr_debug("%s: dma_buf->area: 0x%p, dma_buf->addr: 0x%x", __func__,
- (unsigned int *) dma_buf->area, dma_buf->addr);
- if (!dma_buf->area) {
- pr_err("%s:MSM AFE memory allocation failed\n", __func__);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dir = IN;
+ else
+ dir = OUT;
+ rc = q6afe_audio_client_buf_alloc_contiguous(dir,
+ prtd->audio_client,
+ runtime->hw.period_bytes_min,
+ runtime->hw.periods_max);
+ if (rc < 0) {
+ pr_err("Audio Start: Buffer Allocation failed rc = %d\n", rc);
mutex_unlock(&prtd->lock);
return -ENOMEM;
}
+ buf = prtd->audio_client->port[dir].buf;
+
+ if (buf == NULL || buf[0].data == NULL) {
+ mutex_unlock(&prtd->lock);
+ return -ENOMEM;
+ }
+
+ pr_debug("%s:buf = %p\n", __func__, buf);
+ dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ dma_buf->dev.dev = substream->pcm->card->dev;
+ dma_buf->private_data = NULL;
+ dma_buf->area = buf[0].data;
+ dma_buf->addr = buf[0].phys;
dma_buf->bytes = runtime->hw.buffer_bytes_max;
+ if (!dma_buf->area) {
+ pr_err("%s:MSM AFE physical memory allocation failed\n",
+ __func__);
+ mutex_unlock(&prtd->lock);
+ return -ENOMEM;
+ }
memset(dma_buf->area, 0, runtime->hw.buffer_bytes_max);
prtd->dma_addr = (u32) dma_buf->addr;
@@ -542,6 +585,9 @@
static __devinit int msm_afe_probe(struct platform_device *pdev)
{
+ if (pdev->dev.of_node)
+ dev_set_name(&pdev->dev, "%s", "msm-pcm-afe");
+
pr_debug("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
return snd_soc_register_platform(&pdev->dev,
&msm_soc_platform);
@@ -553,11 +599,17 @@
snd_soc_unregister_platform(&pdev->dev);
return 0;
}
+static const struct of_device_id msm_pcm_afe_dt_match[] = {
+ {.compatible = "qcom,msm-pcm-afe"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, msm_pcm_afe_dt_match);
static struct platform_driver msm_afe_driver = {
.driver = {
.name = "msm-pcm-afe",
.owner = THIS_MODULE,
+ .of_match_table = msm_pcm_afe_dt_match,
},
.probe = msm_afe_probe,
.remove = __devexit_p(msm_afe_remove),
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.h
index 20d6377..446409f 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.h
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-afe-v2.h
@@ -30,6 +30,7 @@
int prepared;
struct hrtimer hrt;
int poll_time;
+ struct afe_audio_client *audio_client;
};
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 0b25545..f0465a5 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -18,6 +18,7 @@
#include <linux/wait.h>
#include <linux/jiffies.h>
#include <linux/sched.h>
+#include <linux/msm_ion.h>
#include <mach/qdsp6v2/audio_acdb.h>
#include <sound/apr_audio-v2.h>
#include <sound/q6afe-v2.h>
@@ -37,6 +38,7 @@
uint32_t token, uint32_t *payload, void *priv);
void *tx_private_data;
void *rx_private_data;
+ uint32_t mmap_handle;
};
static struct afe_ctl this_afe;
@@ -107,6 +109,13 @@
payload[0]);
break;
}
+ } else if (data->opcode ==
+ AFE_SERVICE_CMDRSP_SHARED_MEM_MAP_REGIONS) {
+ pr_debug("%s: mmap_handle: 0x%x\n",
+ __func__, payload[0]);
+ this_afe.mmap_handle = (uint32_t)payload[0];
+ atomic_set(&this_afe.state, 0);
+ wake_up(&this_afe.wait[data->token]);
} else if (data->opcode == AFE_EVENT_RT_PROXY_PORT_STATUS) {
port_id = (uint16_t)(0x0000FFFF & payload[0]);
}
@@ -266,17 +275,21 @@
ret = -EINVAL;
return ret;
}
- index = q6audio_get_port_index(port_id);
- if (q6audio_validate_port(port_id) < 0)
- return -EINVAL;
if ((port_id == RT_PROXY_DAI_001_RX) ||
(port_id == RT_PROXY_DAI_002_TX))
- return -EINVAL;
+ return 0;
if ((port_id == RT_PROXY_DAI_002_RX) ||
(port_id == RT_PROXY_DAI_001_TX))
port_id = VIRTUAL_ID_TO_PORTID(port_id);
+ pr_debug("%s: port id: %d\n", __func__, port_id);
+ index = q6audio_get_port_index(port_id);
+ if (q6audio_validate_port(port_id) < 0) {
+ pr_err("%s: port id: %d\n", __func__, port_id);
+ return -EINVAL;
+ }
+
ret = afe_q6_interface_prepare();
if (IS_ERR_VALUE(ret))
return ret;
@@ -325,6 +338,14 @@
case SLIMBUS_4_TX:
cfg_type = AFE_PARAM_ID_SLIMBUS_CONFIG;
break;
+ case RT_PROXY_PORT_001_RX:
+ case RT_PROXY_PORT_001_TX:
+ cfg_type = AFE_PARAM_ID_RT_PROXY_CONFIG;
+ break;
+ case INT_BT_SCO_RX:
+ case INT_BT_SCO_TX:
+ cfg_type = AFE_PARAM_ID_INTERNAL_BT_FM_CONFIG;
+ break;
default:
pr_err("%s: Invalid port id 0x%x\n", __func__, port_id);
ret = -EINVAL;
@@ -904,7 +925,133 @@
return 0;
}
-/*bharath, memory map handle needs to be stored by AFE client */
+uint32_t afe_req_mmap_handle(void)
+{
+ return this_afe.mmap_handle;
+}
+
+struct afe_audio_client *q6afe_audio_client_alloc(void *priv)
+{
+ struct afe_audio_client *ac;
+ int lcnt = 0;
+
+ ac = kzalloc(sizeof(struct afe_audio_client), GFP_KERNEL);
+ if (!ac) {
+ pr_err("%s: cannot allocate audio client for afe\n", __func__);
+ return NULL;
+ }
+ ac->priv = priv;
+
+ init_waitqueue_head(&ac->cmd_wait);
+ INIT_LIST_HEAD(&ac->port[0].mem_map_handle);
+ INIT_LIST_HEAD(&ac->port[1].mem_map_handle);
+ pr_debug("%s: mem_map_handle list init'ed\n", __func__);
+ mutex_init(&ac->cmd_lock);
+ for (lcnt = 0; lcnt <= OUT; lcnt++) {
+ mutex_init(&ac->port[lcnt].lock);
+ spin_lock_init(&ac->port[lcnt].dsp_lock);
+ }
+ atomic_set(&ac->cmd_state, 0);
+
+ return ac;
+}
+
+int q6afe_audio_client_buf_alloc_contiguous(unsigned int dir,
+ struct afe_audio_client *ac,
+ unsigned int bufsz,
+ unsigned int bufcnt)
+{
+ int cnt = 0;
+ int rc = 0;
+ struct afe_audio_buffer *buf;
+ int len;
+
+ if (!(ac) || ((dir != IN) && (dir != OUT)))
+ return -EINVAL;
+
+ pr_debug("%s: bufsz[%d]bufcnt[%d]\n",
+ __func__,
+ bufsz, bufcnt);
+
+ if (ac->port[dir].buf) {
+ pr_debug("%s: buffer already allocated\n", __func__);
+ return 0;
+ }
+ mutex_lock(&ac->cmd_lock);
+ buf = kzalloc(((sizeof(struct afe_audio_buffer))*bufcnt),
+ GFP_KERNEL);
+
+ if (!buf) {
+ mutex_unlock(&ac->cmd_lock);
+ goto fail;
+ }
+
+ ac->port[dir].buf = buf;
+
+ buf[0].client = msm_ion_client_create(UINT_MAX, "audio_client");
+ if (IS_ERR_OR_NULL((void *)buf[0].client)) {
+ pr_err("%s: ION create client for AUDIO failed\n", __func__);
+ goto fail;
+ }
+ buf[0].handle = ion_alloc(buf[0].client, bufsz * bufcnt, SZ_4K,
+ (0x1 << ION_AUDIO_HEAP_ID), 0);
+ if (IS_ERR_OR_NULL((void *) buf[0].handle)) {
+ pr_err("%s: ION memory allocation for AUDIO failed\n",
+ __func__);
+ goto fail;
+ }
+
+ rc = ion_phys(buf[0].client, buf[0].handle,
+ (ion_phys_addr_t *)&buf[0].phys, (size_t *)&len);
+ if (rc) {
+ pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
+ __func__, rc);
+ goto fail;
+ }
+
+ buf[0].data = ion_map_kernel(buf[0].client, buf[0].handle);
+ if (IS_ERR_OR_NULL((void *) buf[0].data)) {
+ pr_err("%s: ION memory mapping for AUDIO failed\n", __func__);
+ goto fail;
+ }
+ memset((void *)buf[0].data, 0, (bufsz * bufcnt));
+ if (!buf[0].data) {
+ pr_err("%s:invalid vaddr, iomap failed\n", __func__);
+ mutex_unlock(&ac->cmd_lock);
+ goto fail;
+ }
+
+ buf[0].used = dir ^ 1;
+ buf[0].size = bufsz;
+ buf[0].actual_size = bufsz;
+ cnt = 1;
+ while (cnt < bufcnt) {
+ if (bufsz > 0) {
+ buf[cnt].data = buf[0].data + (cnt * bufsz);
+ buf[cnt].phys = buf[0].phys + (cnt * bufsz);
+ if (!buf[cnt].data) {
+ pr_err("%s Buf alloc failed\n",
+ __func__);
+ mutex_unlock(&ac->cmd_lock);
+ goto fail;
+ }
+ buf[cnt].used = dir ^ 1;
+ buf[cnt].size = bufsz;
+ buf[cnt].actual_size = bufsz;
+ pr_debug("%s data[%p]phys[%p][%p]\n", __func__,
+ (void *)buf[cnt].data,
+ (void *)buf[cnt].phys,
+ (void *)&buf[cnt].phys);
+ }
+ cnt++;
+ }
+ ac->port[dir].max_buf_cnt = cnt;
+ mutex_unlock(&ac->cmd_lock);
+ return 0;
+fail:
+ q6afe_audio_client_buf_free_contiguous(dir, ac);
+ return -EINVAL;
+}
int afe_cmd_memory_map(u32 dma_addr_p, u32 dma_buf_sz)
{
int ret = 0;
@@ -941,7 +1088,7 @@
mmap_region_cmd;
mregion->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- mregion->hdr.pkt_size = sizeof(mregion);
+ mregion->hdr.pkt_size = cmd_size;
mregion->hdr.src_port = 0;
mregion->hdr.dest_port = 0;
mregion->hdr.token = 0;
@@ -961,13 +1108,15 @@
mregion_pl->shm_addr_msw = 0x00;
mregion_pl->mem_size_bytes = dma_buf_sz;
+ pr_debug("%s: dma_addr_p 0x%x , size %d\n", __func__,
+ dma_addr_p, dma_buf_sz);
atomic_set(&this_afe.state, 1);
ret = apr_send_pkt(this_afe.apr, (uint32_t *) mmap_region_cmd);
if (ret < 0) {
pr_err("%s: AFE memory map cmd failed %d\n",
__func__, ret);
ret = -EINVAL;
- return ret;
+ goto fail_cmd;
}
ret = wait_event_timeout(this_afe.wait[index],
@@ -976,10 +1125,13 @@
if (!ret) {
pr_err("%s: wait_event timeout\n", __func__);
ret = -EINVAL;
- return ret;
+ goto fail_cmd;
}
-
+ pr_debug("%s: mmap handle 0x%x\n", __func__, this_afe.mmap_handle);
return 0;
+fail_cmd:
+ kfree(mmap_region_cmd);
+ return ret;
}
int afe_cmd_memory_map_nowait(int port_id, u32 dma_addr_p, u32 dma_buf_sz)
@@ -1047,6 +1199,60 @@
}
return 0;
}
+int q6afe_audio_client_buf_free_contiguous(unsigned int dir,
+ struct afe_audio_client *ac)
+{
+ struct afe_audio_port_data *port;
+ int cnt = 0;
+ mutex_lock(&ac->cmd_lock);
+ port = &ac->port[dir];
+ if (!port->buf) {
+ mutex_unlock(&ac->cmd_lock);
+ return 0;
+ }
+ cnt = port->max_buf_cnt - 1;
+
+ if (port->buf[0].data) {
+ ion_unmap_kernel(port->buf[0].client, port->buf[0].handle);
+ ion_free(port->buf[0].client, port->buf[0].handle);
+ ion_client_destroy(port->buf[0].client);
+ pr_debug("%s:data[%p]phys[%p][%p] , client[%p] handle[%p]\n",
+ __func__,
+ (void *)port->buf[0].data,
+ (void *)port->buf[0].phys,
+ (void *)&port->buf[0].phys,
+ (void *)port->buf[0].client,
+ (void *)port->buf[0].handle);
+ }
+
+ while (cnt >= 0) {
+ port->buf[cnt].data = NULL;
+ port->buf[cnt].phys = 0;
+ cnt--;
+ }
+ port->max_buf_cnt = 0;
+ kfree(port->buf);
+ port->buf = NULL;
+ mutex_unlock(&ac->cmd_lock);
+ return 0;
+}
+
+void q6afe_audio_client_free(struct afe_audio_client *ac)
+{
+ int loopcnt;
+ struct afe_audio_port_data *port;
+ if (!ac)
+ return;
+ for (loopcnt = 0; loopcnt <= OUT; loopcnt++) {
+ port = &ac->port[loopcnt];
+ if (!port->buf)
+ continue;
+ pr_debug("%s:loopcnt = %d\n", __func__, loopcnt);
+ q6afe_audio_client_buf_free_contiguous(loopcnt, ac);
+ }
+ kfree(ac);
+ return;
+}
int afe_cmd_memory_unmap(u32 mem_map_handle)
{
@@ -1143,7 +1349,7 @@
int ret = 0;
struct afe_service_cmd_register_rt_port_driver rtproxy;
- pr_debug("%s:\n", __func__);
+ pr_debug("%s: port_id: %d\n", __func__, port_id);
if (this_afe.apr == NULL) {
this_afe.apr = apr_register("ADSP", "AFE", afe_callback,
@@ -1206,9 +1412,6 @@
return ret;
}
}
- index = q6audio_get_port_index(port_id);
- if (q6audio_validate_port(port_id) < 0)
- return -EINVAL;
if ((port_id == RT_PROXY_DAI_002_RX) ||
(port_id == RT_PROXY_DAI_001_TX))
@@ -1216,6 +1419,10 @@
else
return -EINVAL;
+ index = q6audio_get_port_index(port_id);
+ if (q6audio_validate_port(port_id) < 0)
+ return -EINVAL;
+
rtproxy.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
rtproxy.hdr.pkt_size = sizeof(rtproxy);
@@ -1318,6 +1525,7 @@
afecmd_rd.buffer_address_lsw = (uint32_t)buf_addr_p;
afecmd_rd.buffer_address_msw = 0x00;
afecmd_rd.available_bytes = bytes;
+ afecmd_rd.mem_map_handle = mem_map_handle;
ret = apr_send_pkt(this_afe.apr, (uint32_t *) &afecmd_rd);
if (ret < 0) {
@@ -1665,11 +1873,11 @@
}
pr_debug("%s: port_id=%d\n", __func__, port_id);
+ port_id = q6audio_convert_virtual_to_portid(port_id);
index = q6audio_get_port_index(port_id);
if (q6audio_validate_port(port_id) < 0)
return -EINVAL;
- port_id = q6audio_convert_virtual_to_portid(port_id);
stop.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
@@ -1708,6 +1916,7 @@
atomic_set(&this_afe.state, 0);
atomic_set(&this_afe.status, 0);
this_afe.apr = NULL;
+ this_afe.mmap_handle = 0;
for (i = 0; i < AFE_MAX_PORTS; i++)
init_waitqueue_head(&this_afe.wait[i]);