summary refs log tree commit diff
path: root/sound/soc/qcom/lpass-ipq806x.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/qcom/lpass-ipq806x.c')
-rw-r--r--sound/soc/qcom/lpass-ipq806x.c71
1 files changed, 69 insertions, 2 deletions
diff --git a/sound/soc/qcom/lpass-ipq806x.c b/sound/soc/qcom/lpass-ipq806x.c
index 1987605482f7..832a9161484e 100644
--- a/sound/soc/qcom/lpass-ipq806x.c
+++ b/sound/soc/qcom/lpass-ipq806x.c
@@ -55,7 +55,48 @@ static struct snd_soc_dai_driver ipq806x_lpass_cpu_dai_driver = {
 	.ops    = &asoc_qcom_lpass_cpu_dai_ops,
 };
 
-static int ipq806x_lpass_alloc_dma_channel(struct lpass_data *drvdata, int dir)
+static int ipq806x_lpass_init(struct platform_device *pdev)
+{
+	struct lpass_data *drvdata = platform_get_drvdata(pdev);
+	struct device *dev = &pdev->dev;
+	int ret;
+
+	drvdata->ahbix_clk = devm_clk_get(dev, "ahbix-clk");
+	if (IS_ERR(drvdata->ahbix_clk)) {
+		dev_err(dev, "error getting ahbix-clk: %ld\n",
+				PTR_ERR(drvdata->ahbix_clk));
+		ret = PTR_ERR(drvdata->ahbix_clk);
+		goto err_ahbix_clk;
+	}
+
+	ret = clk_set_rate(drvdata->ahbix_clk, LPASS_AHBIX_CLOCK_FREQUENCY);
+	if (ret) {
+		dev_err(dev, "error setting rate on ahbix_clk: %d\n", ret);
+		goto err_ahbix_clk;
+	}
+	dev_dbg(dev, "set ahbix_clk rate to %lu\n",
+			clk_get_rate(drvdata->ahbix_clk));
+
+	ret = clk_prepare_enable(drvdata->ahbix_clk);
+	if (ret) {
+		dev_err(dev, "error enabling ahbix_clk: %d\n", ret);
+		goto err_ahbix_clk;
+	}
+
+err_ahbix_clk:
+	return ret;
+}
+
+static int ipq806x_lpass_exit(struct platform_device *pdev)
+{
+	struct lpass_data *drvdata = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(drvdata->ahbix_clk);
+
+	return 0;
+}
+
+static int ipq806x_lpass_alloc_dma_channel(struct lpass_data *drvdata, int dir, unsigned int dai_id)
 {
 	if (dir == SNDRV_PCM_STREAM_PLAYBACK)
 		return IPQ806X_LPAIF_RDMA_CHAN_MI2S;
@@ -63,7 +104,7 @@ static int ipq806x_lpass_alloc_dma_channel(struct lpass_data *drvdata, int dir)
 		return -EINVAL;
 }
 
-static int ipq806x_lpass_free_dma_channel(struct lpass_data *drvdata, int chan)
+static int ipq806x_lpass_free_dma_channel(struct lpass_data *drvdata, int chan, unsigned int dai_id)
 {
 	return 0;
 }
@@ -82,6 +123,30 @@ static struct lpass_variant ipq806x_data = {
 	.wrdma_reg_stride	= 0x1000,
 	.wrdma_channel_start	= 5,
 	.wrdma_channels		= 4,
+	.loopback		= REG_FIELD_ID(0x0010, 15, 15, 5, 0x4),
+	.spken			= REG_FIELD_ID(0x0010, 14, 14, 5, 0x4),
+	.spkmode		= REG_FIELD_ID(0x0010, 10, 13, 5, 0x4),
+	.spkmono		= REG_FIELD_ID(0x0010, 9, 9, 5, 0x4),
+	.micen			= REG_FIELD_ID(0x0010, 8, 8, 5, 0x4),
+	.micmode		= REG_FIELD_ID(0x0010, 4, 7, 5, 0x4),
+	.micmono		= REG_FIELD_ID(0x0010, 3, 3, 5, 0x4),
+	.wssrc			= REG_FIELD_ID(0x0010, 2, 2, 5, 0x4),
+	.bitwidth		= REG_FIELD_ID(0x0010, 0, 0, 5, 0x4),
+
+	.rdma_dyncclk		= REG_FIELD_ID(0x6000, 12, 12, 4, 0x1000),
+	.rdma_bursten		= REG_FIELD_ID(0x6000, 11, 11, 4, 0x1000),
+	.rdma_wpscnt		= REG_FIELD_ID(0x6000, 8, 10, 4, 0x1000),
+	.rdma_intf		= REG_FIELD_ID(0x6000, 4, 7, 4, 0x1000),
+	.rdma_fifowm		= REG_FIELD_ID(0x6000, 1, 3, 4, 0x1000),
+	.rdma_enable		= REG_FIELD_ID(0x6000, 0, 0, 4, 0x1000),
+
+	.wrdma_dyncclk		= REG_FIELD_ID(0xB000, 12, 12, 4, 0x1000),
+	.wrdma_bursten		= REG_FIELD_ID(0xB000, 11, 11, 4, 0x1000),
+	.wrdma_wpscnt		= REG_FIELD_ID(0xB000, 8, 10, 4, 0x1000),
+	.wrdma_intf		= REG_FIELD_ID(0xB000, 4, 7, 4, 0x1000),
+	.wrdma_fifowm		= REG_FIELD_ID(0xB000, 1, 3, 4, 0x1000),
+	.wrdma_enable		= REG_FIELD_ID(0xB000, 0, 0, 4, 0x1000),
+
 	.dai_driver		= &ipq806x_lpass_cpu_dai_driver,
 	.num_dai		= 1,
 	.dai_osr_clk_names	= (const char *[]) {
@@ -90,6 +155,8 @@ static struct lpass_variant ipq806x_data = {
 	.dai_bit_clk_names	= (const char *[]) {
 				"mi2s-bit-clk",
 				},
+	.init			= ipq806x_lpass_init,
+	.exit			= ipq806x_lpass_exit,
 	.alloc_dma_channel	= ipq806x_lpass_alloc_dma_channel,
 	.free_dma_channel	= ipq806x_lpass_free_dma_channel,
 };