Skip to contentSkip to conversation

Qualcomm's lpass-hdmi ASoC driver to support audio over dp port

PATCH Superseded Srinivasa Rao Mandadapu 2 participants 10 messages Oct 5, 2020 – Oct 7, 2020

Subsystems (5)

v10 of 11 Superseded Latest is v11 →

lore
Share & tools
lore
#0 lore raw

v10 cover Qualcomm's lpass-hdmi ASoC driver to support audio over dp port

These patches are to support audio over DP port on Qualcomm's SC7180 LPASS Asoc. It includes machine driver, cpu driver, platform driver updates for HDMI path support, device tree documention, lpass variant structure optimization and configuration changes.
These patches depends on the DP patch series
https://patchwork.kernel.org/project/dri-devel/list/?series=332029
https://lore.kernel.org/patchwork/project/lkml/list/?series=464856

changes since V9:
-- Removed unused structures lpass_hdmi.h
changes since V8:
-- Removed redundant structure wrapper for reg map field memebrs
-- Updated lpass_hdmi_regmap_volatile API with appropriate registers as true
and others as false.
changes since V7:
-- Fixed typo errors
-- Created Separate patch for buffer size change
changes since V6:
-- Removed compile time define flag, which used for enabling
HDMI code, based on corresponding config param is included.
-- Updated reg map alloc API with reg map bulk API.
-- Removed unnecessary line splits
changes since V5:
-- Removed unused struct regmap *map in lpass_platform_alloc_hdmidmactl_fields. -- DMA alloc and free API signature change in lpass-apq8016.c, lpass-ipq806x.c -- Keeping API "irqreturn_t lpass_platform_hdmiif_irq" under ifdef macro
Changes Since v4:
-- Updated with single compatible node for both I2S and HDMI.
Changes Since v3:
-- Removed id in lpass variant structure and used snd_soc_dai_driver id.
Changes Since v2:
-- Audio buffer size(i.e. LPASS_PLATFORM_BUFFER_SIZE) in lpass-platform.c increased.
Changes Since v1:
-- Commit messages are updated
-- Addressed Rob Herring review comments

V Sujith Kumar Reddy (8):
ASoC: Add sc7180-lpass binding header hdmi define
ASoC: dt-bindings: Add dt binding for lpass hdmi Asoc:qcom:lpass-cpu:Update dts property read API
Asoc: qcom: lpass:Update lpaif_dmactl members order
ASoC: qcom: Add support for lpass hdmi driver
Asoc: qcom: lpass-platform : Increase buffer size
ASoC: qcom: sc7180: Add support for audio over DP

 .../devicetree/bindings/sound/qcom,lpass-cpu.yaml  |  74 +++-
 include/dt-bindings/sound/sc7180-lpass.h           |   1 +
 sound/soc/qcom/Kconfig                             |   5 +
 sound/soc/qcom/Makefile                            |   2 +
 sound/soc/qcom/lpass-apq8016.c                     |   4 +-
 sound/soc/qcom/lpass-cpu.c                         |  53 ++-
 sound/soc/qcom/lpass-hdmi.c                        | 468 +++++++++++++++++++++
 sound/soc/qcom/lpass-hdmi.h                        | 106 +++++
 sound/soc/qcom/lpass-ipq806x.c                     |   4 +-
 sound/soc/qcom/lpass-lpaif-reg.h                   |  52 ++-
 sound/soc/qcom/lpass-platform.c                    | 403 ++++++++++++++----
 sound/soc/qcom/lpass-sc7180.c                      | 116 ++++-
 sound/soc/qcom/lpass.h                             | 119 +++++-
 13 files changed, 1262 insertions(+), 145 deletions(-)
 create mode 100644 sound/soc/qcom/lpass-hdmi.c
 create mode 100644 sound/soc/qcom/lpass-hdmi.h
Signature · 2 lines
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc.,
is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
#1 lore raw

PATCH v10 1/7 ASoC: Add sc7180-lpass binding header hdmi define

From: V Sujith Kumar Reddy <[email protected]>

Add header defining hdmi dai-id for SC7180 lpass soc in dt bindings.

---
 include/dt-bindings/sound/sc7180-lpass.h | 1 +
 1 file changed, 1 insertion(+)
include/dt-bindings/sound/sc7180-lpass.h +1 -0
index 7d988f6..56ecaaf 100644
@@ -4,6 +4,7 @@
 
 #define MI2S_PRIMARY	0
 #define MI2S_SECONDARY	1
+#define LPASS_DP_RX	2
 
 #define LPASS_MCLK0	0
 
Signature · 2 lines
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc.,
is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
#2 lore raw

PATCH v10 2/7 ASoC: dt-bindings: Add dt binding for lpass hdmi

In reply to Srinivasa Rao Mandadapu

From: V Sujith Kumar Reddy <[email protected]>

Adds bindings for lpass hdmi interface
which can support audio path over dp.

---
 .../devicetree/bindings/sound/qcom,lpass-cpu.yaml  | 74 +++++++++++++++-------
 1 file changed, 52 insertions(+), 22 deletions(-)
Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml +52 -22
index 09c9bd2..f6f9fb4 100644
@@ -24,9 +24,10 @@ properties:
       - qcom,sc7180-lpass-cpu
 
   reg:
-    maxItems: 1
+    maxItems: 2
     description: LPAIF core registers
-
+  reg-names:
+     maxItems: 2
   clocks:
     minItems: 3
     maxItems: 6
@@ -36,15 +37,16 @@ properties:
     maxItems: 6
 
   interrupts:
-    maxItems: 1
+    maxItems: 2
     description: LPAIF DMA buffer interrupt
-
+  interrupt-names:
+    maxItems: 2
   qcom,adsp:
     $ref: /schemas/types.yaml#/definitions/phandle
     description: Phandle for the audio DSP node
 
   iommus:
-    maxItems: 1
+    maxItems: 2
     description: Phandle to apps_smmu node with sid mask
 
   power-domains:
@@ -60,10 +62,12 @@ properties:
     const: 0
 
 patternProperties:
-  "(^mi2s-[0-9a-f]$|mi2s)":
+  "^dai-link@[0-9a-f]$":
     type: object
-    description: Required properties for each DAI
-
+    description: |
+      LPASS CPU dai node for each I2S device. Bindings of each node
+      depends on the specific driver providing the functionality and
+      properties.
     properties:
       reg:
         maxItems: 1
@@ -85,9 +89,11 @@ patternProperties:
 required:
   - compatible
   - reg
+  - reg-names
   - clocks
   - clock-names
   - interrupts
+  - interrupt-names
   - '#sound-dai-cells'
 
 additionalProperties: false
@@ -134,13 +140,32 @@ allOf:
     then:
       properties:
         clock-names:
-          items:
-            - const: pcnoc-sway-clk
-            - const: audio-core
-            - const: mclk0
-            - const: pcnoc-mport-clk
-            - const: mi2s-bit-clk0
-            - const: mi2s-bit-clk1
+          oneOf:
+           - items:   #for I2S
+              - const: pcnoc-sway-clk
+              - const: audio-core
+              - const: mclk0
+              - const: pcnoc-mport-clk
+              - const: mi2s-bit-clk0
+              - const: mi2s-bit-clk1
+           - items:   #for HDMI
+              - const: pcnoc-sway-clk
+              - const: audio-core
+              - const: pcnoc-mport-clk
+        reg-names:
+          anyOf:
+            - items:   #for I2S
+              - const: lpass-lpaif
+            - items:   #for I2S and HDMI
+              - const: lpass-hdmiif
+              - const: lpass-lpaif
+        interrupt-names:
+          anyOf:
+            - items:   #for I2S
+              - const: lpass-irq-lpaif
+            - items:   #for I2S and HDMI
+              - const: lpass-irq-lpaif
+              - const: lpass-irq-hdmi
       required:
         - iommus
         - power-domains
@@ -152,12 +177,15 @@ examples:
     soc {
         #address-cells = <2>;
         #size-cells = <2>;
-        lpass@62f00000 {
+        lpass@62d80000 {
             compatible = "qcom,sc7180-lpass-cpu";
 
-            reg = <0 0x62f00000  0 0x29000>;
-
-            iommus = <&apps_smmu 0x1020 0>;
+            reg = <0 0x62d87000 0 0x68000>,
+                  <0 0x62f00000 0 0x29000>;
+            reg-names = "lpass-hdmiif",
+                        "lpass-lpaif";
+            iommus = <&apps_smmu 0x1020 0>,
+                     <&apps_smmu 0x1032 0>;
             power-domains = <&lpass_hm 0>;
 
             clocks = <&gcc 131>,
@@ -171,14 +199,16 @@ examples:
                           "mclk0", "pcnoc-mport-clk",
                           "mi2s-bit-clk0", "mi2s-bit-clk1";
 
-            interrupts = <0 160 1>;
-
+            interrupts = <0 160 1>,
+                         <0 268 1>;
+            interrupt-names = "lpass-irq-lpaif",
+                              "lpass-irq-hdmi";
             #sound-dai-cells = <1>;
 
             #address-cells = <1>;
             #size-cells = <0>;
             /* Optional to set different MI2S SD lines */
-            mi2s-primary@0 {
+            dai-link@0 {
                 reg = <MI2S_PRIMARY>;
                 qcom,playback-sd-lines = <1>;
                 qcom,capture-sd-lines = <0>;
Signature · 2 lines
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc.,
is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
#3 lore raw

PATCH v10 3/7 Asoc:qcom:lpass-cpu:Update dts property read API

In reply to Srinivasa Rao Mandadapu

From: V Sujith Kumar Reddy <[email protected]>

Update dts property read API call with platform get property by name, as it make code more readable and avoid conflicts when array of properties to be used.

---
 sound/soc/qcom/lpass-cpu.c      | 2 +-
 sound/soc/qcom/lpass-platform.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
sound/soc/qcom/lpass-cpu.c +1 -1
index 0718a0f..12950d2 100644
@@ -575,7 +575,7 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
 
 	of_lpass_cpu_parse_dai_data(dev, drvdata);
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif");
 
 	drvdata->lpaif = devm_ioremap_resource(dev, res);
 	if (IS_ERR((void const __force *)drvdata->lpaif)) {
sound/soc/qcom/lpass-platform.c +1 -1
index 7ac2629..e7cf4e5 100644
@@ -621,7 +621,7 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev)
 	struct lpass_variant *v = drvdata->variant;
 	int ret;
 
-	drvdata->lpaif_irq = platform_get_irq(pdev, 0);
+	drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif");
 	if (drvdata->lpaif_irq < 0)
 		return -ENODEV;
 
Signature · 2 lines
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc.,
is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
#4 lore raw

PATCH v10 4/7 Asoc: qcom: lpass:Update lpaif_dmactl members order

In reply to Srinivasa Rao Mandadapu

From: V Sujith Kumar Reddy <[email protected]>

Update the lpaif_dmactl struct members order to match HDMI reg map members sequence. Separate Interface reg map as it is used for I2S control but not for HDMI control, to make use of bulk API, which makes code more readable.

---
 sound/soc/qcom/lpass-platform.c | 8 ++++----
 sound/soc/qcom/lpass.h          | 6 +++---
 2 files changed, 7 insertions(+), 7 deletions(-)
sound/soc/qcom/lpass-platform.c +4 -4
index e7cf4e5..db0d959 100644
@@ -71,13 +71,13 @@ static int lpass_platform_alloc_dmactl_fields(struct device *dev,
 	rd_dmactl = drvdata->rd_dmactl;
 	wr_dmactl = drvdata->wr_dmactl;
 
-	rval = devm_regmap_field_bulk_alloc(dev, map, &rd_dmactl->bursten,
-					    &v->rdma_bursten, 6);
+	rval = devm_regmap_field_bulk_alloc(dev, map, &rd_dmactl->intf,
+					    &v->rdma_intf, 6);
 	if (rval)
 		return rval;
 
-	return devm_regmap_field_bulk_alloc(dev, map, &wr_dmactl->bursten,
-					    &v->wrdma_bursten, 6);
+	return devm_regmap_field_bulk_alloc(dev, map, &wr_dmactl->intf,
+					    &v->wrdma_intf, 6);
 }
 
 static int lpass_platform_pcmops_open(struct snd_soc_component *component,
sound/soc/qcom/lpass.h +3 -3
index 51c9991..7089d4c 100644
@@ -31,9 +31,9 @@ struct lpaif_i2sctl {
 
 
 struct lpaif_dmactl {
+	struct regmap_field *intf;
 	struct regmap_field *bursten;
 	struct regmap_field *wpscnt;
-	struct regmap_field *intf;
 	struct regmap_field *fifowm;
 	struct regmap_field *enable;
 	struct regmap_field *dyncclk;
@@ -110,17 +110,17 @@ struct lpass_variant {
 	struct reg_field bitwidth;
 
 	/* RD_DMA Register fields */
+	struct reg_field rdma_intf;
 	struct reg_field rdma_bursten;
 	struct reg_field rdma_wpscnt;
-	struct reg_field rdma_intf;
 	struct reg_field rdma_fifowm;
 	struct reg_field rdma_enable;
 	struct reg_field rdma_dyncclk;
 
 	/* WR_DMA Register fields */
+	struct reg_field wrdma_intf;
 	struct reg_field wrdma_bursten;
 	struct reg_field wrdma_wpscnt;
-	struct reg_field wrdma_intf;
 	struct reg_field wrdma_fifowm;
 	struct reg_field wrdma_enable;
 	struct reg_field wrdma_dyncclk;
Signature · 2 lines
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc.,
is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
#5 lore raw

PATCH v10 5/7 ASoC: qcom: Add support for lpass hdmi driver

In reply to Srinivasa Rao Mandadapu

From: V Sujith Kumar Reddy <[email protected]>

Upadate lpass cpu and platform driver to support audio over dp. Also add lpass-hdmi.c and lpass-hdmi.h.

---
 sound/soc/qcom/Kconfig           |   5 +
 sound/soc/qcom/Makefile          |   2 +
 sound/soc/qcom/lpass-apq8016.c   |   4 +-
 sound/soc/qcom/lpass-cpu.c       |  51 ++++-
 sound/soc/qcom/lpass-hdmi.c      | 468 +++++++++++++++++++++++++++++++++++++++
 sound/soc/qcom/lpass-hdmi.h      | 106 +++++++++
 sound/soc/qcom/lpass-ipq806x.c   |   4 +-
 sound/soc/qcom/lpass-lpaif-reg.h |  52 ++++-
 sound/soc/qcom/lpass-platform.c  | 391 ++++++++++++++++++++++++++------
 sound/soc/qcom/lpass.h           | 113 +++++++++-
 10 files changed, 1097 insertions(+), 99 deletions(-)
 create mode 100644 sound/soc/qcom/lpass-hdmi.c
 create mode 100644 sound/soc/qcom/lpass-hdmi.h
sound/soc/qcom/Kconfig +5 -0
index a7ef626..28e775f 100644
@@ -12,6 +12,10 @@ config SND_SOC_LPASS_CPU
 	tristate
 	select REGMAP_MMIO
 
+config SND_SOC_LPASS_HDMI
+	tristate
+	select REGMAP_MMIO
+
 config SND_SOC_LPASS_PLATFORM
 	tristate
 	select REGMAP_MMIO
@@ -30,6 +34,7 @@ config SND_SOC_LPASS_SC7180
 	tristate
 	select SND_SOC_LPASS_CPU
 	select SND_SOC_LPASS_PLATFORM
+	select SND_SOC_LPASS_HDMI
 
 config SND_SOC_STORM
 	tristate "ASoC I2S support for Storm boards"
sound/soc/qcom/Makefile +2 -0
index 7972c94..0bd90d7 100644
@@ -1,12 +1,14 @@
 # SPDX-License-Identifier: GPL-2.0
 # Platform
 snd-soc-lpass-cpu-objs := lpass-cpu.o
+snd-soc-lpass-hdmi-objs := lpass-hdmi.o
 snd-soc-lpass-platform-objs := lpass-platform.o
 snd-soc-lpass-ipq806x-objs := lpass-ipq806x.o
 snd-soc-lpass-apq8016-objs := lpass-apq8016.o
 snd-soc-lpass-sc7180-objs := lpass-sc7180.o
 
 obj-$(CONFIG_SND_SOC_LPASS_CPU) += snd-soc-lpass-cpu.o
+obj-$(CONFIG_SND_SOC_LPASS_HDMI) += snd-soc-lpass-hdmi.o
 obj-$(CONFIG_SND_SOC_LPASS_PLATFORM) += snd-soc-lpass-platform.o
 obj-$(CONFIG_SND_SOC_LPASS_IPQ806X) += snd-soc-lpass-ipq806x.o
 obj-$(CONFIG_SND_SOC_LPASS_APQ8016) += snd-soc-lpass-apq8016.o
sound/soc/qcom/lpass-apq8016.c +2 -2
index 5c8ae22..0aedb3a 100644
@@ -125,7 +125,7 @@ static struct snd_soc_dai_driver apq8016_lpass_cpu_dai_driver[] = {
 };
 
 static int apq8016_lpass_alloc_dma_channel(struct lpass_data *drvdata,
-					   int direction)
+					   int direction, unsigned int dai_id)
 {
 	struct lpass_variant *v = drvdata->variant;
 	int chan = 0;
@@ -151,7 +151,7 @@ static int apq8016_lpass_alloc_dma_channel(struct lpass_data *drvdata,
 	return chan;
 }
 
-static int apq8016_lpass_free_dma_channel(struct lpass_data *drvdata, int chan)
+static int apq8016_lpass_free_dma_channel(struct lpass_data *drvdata, int chan, unsigned int dai_id)
 {
 	clear_bit(chan, &drvdata->dma_ch_bit_map);
 
sound/soc/qcom/lpass-cpu.c +42 -9

78 lines not on this page · raw message

sound/soc/qcom/lpass-hdmi.c new file +468 -0

468 lines not on this page · raw message

sound/soc/qcom/lpass-hdmi.h new file +106 -0

106 lines not on this page · raw message

sound/soc/qcom/lpass-ipq806x.c +2 -2
index 72f09b3..832a916 100644
@@ -96,7 +96,7 @@ static int ipq806x_lpass_exit(struct platform_device *pdev)
 	return 0;
 }
 
-static int ipq806x_lpass_alloc_dma_channel(struct lpass_data *drvdata, int dir)
+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;
@@ -104,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;
 }
sound/soc/qcom/lpass-lpaif-reg.h +40 -12

78 lines not on this page · raw message

sound/soc/qcom/lpass-platform.c +324 -67

629 lines not on this page · raw message

sound/soc/qcom/lpass.h +106 -7

188 lines not on this page · raw message

Signature · 2 lines
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc.,
is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
#6 lore raw

Re: [PATCH v10 5/7] ASoC: qcom: Add support for lpass hdmi driver

Quoted 22 lines · Srinivasa Rao Mandadapu

From: V Sujith Kumar Reddy <[email protected]>

Upadate lpass cpu and platform driver to support audio over dp. Also add lpass-hdmi.c and lpass-hdmi.h.

---
  sound/soc/qcom/Kconfig           |   5 +
  sound/soc/qcom/Makefile          |   2 +
  sound/soc/qcom/lpass-apq8016.c   |   4 +-
  sound/soc/qcom/lpass-cpu.c       |  51 ++++-
  sound/soc/qcom/lpass-hdmi.c      | 468 +++++++++++++++++++++++++++++++++++++++
  sound/soc/qcom/lpass-hdmi.h      | 106 +++++++++
  sound/soc/qcom/lpass-ipq806x.c   |   4 +-
  sound/soc/qcom/lpass-lpaif-reg.h |  52 ++++-
  sound/soc/qcom/lpass-platform.c  | 391 ++++++++++++++++++++++++++------
  sound/soc/qcom/lpass.h           | 113 +++++++++-
  10 files changed, 1097 insertions(+), 99 deletions(-)

create mode 100644 sound/soc/qcom/lpass-hdmi.c
create mode 100644 sound/soc/qcom/lpass-hdmi.h

...

Quoted 14 lines
sound/soc/qcom/lpass-hdmi.c new file +8 -0
new file mode 100644
index 0000000..ee737f0
@@ -0,0 +1,468 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ *
+ * lpass-hdmi.c -- ALSA SoC HDMI-CPU DAI driver for QTi LPASS HDMI
+ */
+
+

sound/soc/qcom/lpass-hdmi.c line 18

Quoted 10 lines
sound/soc/qcom/lpass-hdmi.c new file +10 -0
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <sound/pcm_params.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <dt-bindings/sound/sc7180-lpass.h>
+#include "lpass-lpaif-reg.h"
+#include "lpass.h"
+

[

sound/soc/qcom/lpass-hdmi.c line 26

Quoted 8 lines
sound/soc/qcom/lpass-hdmi.c new file +8 -0
+#define QCOM_REGMAP_FIELD_ALLOC(d, m, f, mf)    \
+	do { \
+		mf = devm_regmap_field_alloc(d, m, f);     \
+		if (IS_ERR(mf))                \
+			return -EINVAL;         \
+	} while (0)
+
+

]
should go into lpass.h

[

Quoted 67 lines
sound/soc/qcom/lpass-hdmi.c new file +67 -0
+int lpass_hdmi_init_bitfields(struct device *dev, struct regmap *map)
+{
+	struct lpass_data *drvdata = dev_get_drvdata(dev);
+	struct lpass_variant *v = drvdata->variant;
+	unsigned int i;
+	struct lpass_hdmi_tx_ctl *tx_ctl;
+	struct regmap_field *legacy_en;
+	struct lpass_vbit_ctrl *vbit_ctl;
+	struct regmap_field *tx_parity;
+	struct lpass_dp_metadata_ctl *meta_ctl;
+	struct lpass_sstream_ctl *sstream_ctl;
+	struct regmap_field *ch_msb;
+	struct regmap_field *ch_lsb;
+	struct lpass_hdmitx_dmactl *tx_dmactl;
+	int rval;
+
+	tx_ctl = devm_kzalloc(dev, sizeof(*tx_ctl), GFP_KERNEL);
+	if (!tx_ctl)
+		return -ENOMEM;
+
+	QCOM_REGMAP_FIELD_ALLOC(dev, map, v->soft_reset, tx_ctl->soft_reset);
+	QCOM_REGMAP_FIELD_ALLOC(dev, map, v->force_reset, tx_ctl->force_reset);
+	drvdata->tx_ctl = tx_ctl;
+
+	QCOM_REGMAP_FIELD_ALLOC(dev, map, v->legacy_en, legacy_en);
+	drvdata->hdmitx_legacy_en = legacy_en;
+
+	vbit_ctl = devm_kzalloc(dev, sizeof(*vbit_ctl), GFP_KERNEL);
+	if (!vbit_ctl)
+		return -ENOMEM;
+
+	QCOM_REGMAP_FIELD_ALLOC(dev, map, v->replace_vbit, vbit_ctl->replace_vbit);
+	QCOM_REGMAP_FIELD_ALLOC(dev, map, v->vbit_stream, vbit_ctl->vbit_stream);
+	drvdata->vbit_ctl = vbit_ctl;
+
+
+	QCOM_REGMAP_FIELD_ALLOC(dev, map, v->calc_en, tx_parity);
+	drvdata->hdmitx_parity_calc_en = tx_parity;
+
+	meta_ctl = devm_kzalloc(dev, sizeof(*meta_ctl), GFP_KERNEL);
+	if (!meta_ctl)
+		return -ENOMEM;
+
+	rval = devm_regmap_field_bulk_alloc(dev, map, &meta_ctl->mute, &v->mute, 7);
+	if (rval)
+		return rval;
+	drvdata->meta_ctl = meta_ctl;
+
+	sstream_ctl = devm_kzalloc(dev, sizeof(*sstream_ctl), GFP_KERNEL);
+	if (!sstream_ctl)
+		return -ENOMEM;
+
+	rval = devm_regmap_field_bulk_alloc(dev, map, &sstream_ctl->sstream_en, &v->sstream_en, 9);
+	if (rval)
+		return rval;
+
+	drvdata->sstream_ctl = sstream_ctl;
+
+	for (i = 0; i < LPASS_MAX_HDMI_DMA_CHANNELS; i++) {
+		QCOM_REGMAP_FIELD_ALLOC(dev, map, v->msb_bits, ch_msb);
+		drvdata->hdmitx_ch_msb[i] = ch_msb;
+
+		QCOM_REGMAP_FIELD_ALLOC(dev, map, v->lsb_bits, ch_lsb);
+		drvdata->hdmitx_ch_lsb[i] = ch_lsb;
+
+		tx_dmactl = devm_kzalloc(dev, sizeof(*tx_dmactl), GFP_KERNEL);
+		if (!tx_dmactl)

sound/soc/qcom/lpass-hdmi.c line 103

Quoted 10 lines
sound/soc/qcom/lpass-hdmi.c new file +10 -0
+			return -ENOMEM;
+
+		QCOM_REGMAP_FIELD_ALLOC(dev, map, v->use_hw_chs, tx_dmactl->use_hw_chs);
+		QCOM_REGMAP_FIELD_ALLOC(dev, map, v->use_hw_usr, tx_dmactl->use_hw_usr);
+		QCOM_REGMAP_FIELD_ALLOC(dev, map, v->hw_chs_sel, tx_dmactl->hw_chs_sel);
+		QCOM_REGMAP_FIELD_ALLOC(dev, map, v->hw_usr_sel, tx_dmactl->hw_usr_sel);
+		drvdata->hdmi_tx_dmactl[i] = tx_dmactl;
+	}
+	return 0;
+}

]
This should go into lpass-cpu.c

Quoted 231 lines
sound/soc/qcom/lpass-hdmi.c new file +230 -0
+EXPORT_SYMBOL(lpass_hdmi_init_bitfields);
 
+
+static int lpass_hdmi_daiops_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	snd_pcm_format_t format = params_format(params);
+	unsigned int rate = params_rate(params);
+	unsigned int channels = params_channels(params);
+	unsigned int ret;
+	unsigned int bitwidth;
+	unsigned int word_length;
+	unsigned int ch_sts_buf0;
+	unsigned int ch_sts_buf1;
+	unsigned int data_format;
+	unsigned int sampling_freq;
+	unsigned int ch = 0;
+	struct lpass_dp_metadata_ctl *meta_ctl = drvdata->meta_ctl;
+	struct lpass_sstream_ctl *sstream_ctl = drvdata->sstream_ctl;
+
+	bitwidth = snd_pcm_format_width(format);
+	if (bitwidth < 0) {
+		dev_err(dai->dev, "%s invalid bit width given : %d\n",
+					__func__, bitwidth);
+		return bitwidth;
+	}
+
+	switch (bitwidth) {
+	case 16:
+		word_length = LPASS_DP_AUDIO_BITWIDTH16;
+		break;
+	case 24:
+		word_length = LPASS_DP_AUDIO_BITWIDTH24;
+		break;
+	default:
+		dev_err(dai->dev, "%s invalid bit width given : %d\n",
+					__func__, bitwidth);
+		return -EINVAL;
+	}
+
+	switch (rate) {
+	case 32000:
+		sampling_freq = LPASS_SAMPLING_FREQ32;
+		break;
+	case 44100:
+		sampling_freq = LPASS_SAMPLING_FREQ44;
+		break;
+	case 48000:
+		sampling_freq = LPASS_SAMPLING_FREQ48;
+		break;
+	default:
+		dev_err(dai->dev, "%s invalid bit width given : %d\n",
+					__func__, bitwidth);
+		return -EINVAL;
+	}
+	data_format = LPASS_DATA_FORMAT_LINEAR;
+	ch_sts_buf0 = (((data_format << LPASS_DATA_FORMAT_SHIFT) & LPASS_DATA_FORMAT_MASK)
+				| ((sampling_freq << LPASS_FREQ_BIT_SHIFT) & LPASS_FREQ_BIT_MASK));
+	ch_sts_buf1 = (word_length) & LPASS_WORDLENGTH_MASK;
+
+	ret = regmap_field_write(drvdata->tx_ctl->soft_reset, LPASS_TX_CTL_RESET);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(drvdata->tx_ctl->soft_reset, LPASS_TX_CTL_CLEAR);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(drvdata->hdmitx_legacy_en, LPASS_HDMITX_LEGACY_DISABLE);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(drvdata->hdmitx_parity_calc_en, HDMITX_PARITY_CALC_EN);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(drvdata->vbit_ctl->replace_vbit, REPLACE_VBIT);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(drvdata->vbit_ctl->vbit_stream, LINEAR_PCM_DATA);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(drvdata->hdmitx_ch_msb[0], ch_sts_buf1);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(drvdata->hdmitx_ch_lsb[0], ch_sts_buf0);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(drvdata->hdmi_tx_dmactl[0]->use_hw_chs, HW_MODE);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(drvdata->hdmi_tx_dmactl[0]->hw_chs_sel, SW_MODE);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(drvdata->hdmi_tx_dmactl[0]->use_hw_usr, HW_MODE);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(drvdata->hdmi_tx_dmactl[0]->hw_usr_sel, SW_MODE);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(meta_ctl->mute, LPASS_MUTE_ENABLE);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(meta_ctl->as_sdp_cc, channels - 1);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(meta_ctl->as_sdp_ct, LPASS_META_DEFAULT_VAL);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(meta_ctl->aif_db4, LPASS_META_DEFAULT_VAL);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(meta_ctl->frequency, sampling_freq);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(meta_ctl->mst_index, LPASS_META_DEFAULT_VAL);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(meta_ctl->dptx_index, LPASS_META_DEFAULT_VAL);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(sstream_ctl->sstream_en, LPASS_SSTREAM_DISABLE);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(sstream_ctl->dma_sel, ch);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(sstream_ctl->auto_bbit_en, LPASS_SSTREAM_DEFAULT_ENABLE);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(sstream_ctl->layout, LPASS_SSTREAM_DEFAULT_DISABLE);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(sstream_ctl->layout_sp, LPASS_LAYOUT_SP_DEFAULT);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(sstream_ctl->dp_audio, LPASS_SSTREAM_DEFAULT_ENABLE);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(sstream_ctl->set_sp_on_en, LPASS_SSTREAM_DEFAULT_ENABLE);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(sstream_ctl->dp_sp_b_hw_en, LPASS_SSTREAM_DEFAULT_ENABLE);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(sstream_ctl->dp_staffing_en, LPASS_SSTREAM_DEFAULT_ENABLE);
+	if (ret)
+		return ret;
+
+	return ret;
+}
+
+static int lpass_hdmi_daiops_prepare(struct snd_pcm_substream *substream,
+		struct snd_soc_dai *dai)
+{
+	int ret;
+	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+
+	ret = regmap_field_write(drvdata->sstream_ctl->sstream_en, LPASS_SSTREAM_ENABLE);
+	if (ret)
+		return ret;
+
+	ret = regmap_field_write(drvdata->meta_ctl->mute, LPASS_MUTE_DISABLE);
+	if (ret)
+		return ret;
+
+	return ret;
+}
+
+static int lpass_hdmi_daiops_trigger(struct snd_pcm_substream *substream,
+		int cmd, struct snd_soc_dai *dai)
+{
+	struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+	struct lpass_dp_metadata_ctl *meta_ctl = drvdata->meta_ctl;
+	struct lpass_sstream_ctl *sstream_ctl = drvdata->sstream_ctl;
+	int ret = -EINVAL;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		ret = regmap_field_write(sstream_ctl->sstream_en, LPASS_SSTREAM_ENABLE);
+		if (ret)
+			return ret;
+
+		ret = regmap_field_write(meta_ctl->mute, LPASS_MUTE_DISABLE);
+		if (ret)
+			return ret;
+
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		ret = regmap_field_write(sstream_ctl->sstream_en, LPASS_SSTREAM_DISABLE);
+		if (ret)
+			return ret;
+
+		ret = regmap_field_write(meta_ctl->mute, LPASS_MUTE_ENABLE);
+		if (ret)
+			return ret;
+
+		ret = regmap_field_write(sstream_ctl->dp_audio, 0);
+		if (ret)
+			return ret;
+
+		break;
+	}

sound/soc/qcom/lpass-hdmi.c line 343

Quoted 10 lines
sound/soc/qcom/lpass-hdmi.c new file +10 -0
+	return ret;
+}
+
+const struct snd_soc_dai_ops asoc_qcom_lpass_hdmi_dai_ops = {
+	.hw_params	= lpass_hdmi_daiops_hw_params,
+	.prepare	= lpass_hdmi_daiops_prepare,
+	.trigger	= lpass_hdmi_daiops_trigger,
+};
+EXPORT_SYMBOL_GPL(asoc_qcom_lpass_hdmi_dai_ops);
+

[

Quoted 111 lines
sound/soc/qcom/lpass-hdmi.c new file +111 -0
+static bool lpass_hdmi_regmap_writeable(struct device *dev, unsigned int reg)
+{
+	struct lpass_data *drvdata = dev_get_drvdata(dev);
+	struct lpass_variant *v = drvdata->variant;
+	int i;
+
+	if (reg == LPASS_HDMI_TX_CTL_ADDR(v))
+		return true;
+	if (reg == LPASS_HDMI_TX_LEGACY_ADDR(v))
+		return true;
+	if (reg == LPASS_HDMI_TX_VBIT_CTL_ADDR(v))
+		return true;
+	if (reg == LPASS_HDMI_TX_PARITY_ADDR(v))
+		return true;
+	if (reg == LPASS_HDMI_TX_DP_ADDR(v))
+		return true;
+	if (reg == LPASS_HDMI_TX_SSTREAM_ADDR(v))
+		return true;
+	if (reg == LPASS_HDMITX_APP_IRQEN_REG(v))
+		return true;
+	if (reg == LPASS_HDMITX_APP_IRQCLEAR_REG(v))
+		return true;
+
+	for (i = 0; i < v->hdmi_rdma_channels; i++) {
+		if (reg == LPASS_HDMI_TX_CH_LSB_ADDR(v, i))
+			return true;
+		if (reg == LPASS_HDMI_TX_CH_MSB_ADDR(v, i))
+			return true;
+		if (reg == LPASS_HDMI_TX_DMA_ADDR(v, i))
+			return true;
+	}
+
+	for (i = 0; i < v->rdma_channels; ++i) {
+		if (reg == LPAIF_HDMI_RDMACTL_REG(v, i))
+			return true;
+		if (reg == LPAIF_HDMI_RDMABASE_REG(v, i))
+			return true;
+		if (reg == LPAIF_HDMI_RDMABUFF_REG(v, i))
+			return true;
+		if (reg == LPAIF_HDMI_RDMAPER_REG(v, i))
+			return true;
+	}
+	return false;
+}
+
+static bool lpass_hdmi_regmap_readable(struct device *dev, unsigned int reg)
+{
+	struct lpass_data *drvdata = dev_get_drvdata(dev);
+	struct lpass_variant *v = drvdata->variant;
+	int i;
+
+	if (reg == LPASS_HDMI_TX_CTL_ADDR(v))
+		return true;
+	if (reg == LPASS_HDMI_TX_LEGACY_ADDR(v))
+		return true;
+	if (reg == LPASS_HDMI_TX_VBIT_CTL_ADDR(v))
+		return true;
+
+	for (i = 0; i < v->hdmi_rdma_channels; i++) {
+		if (reg == LPASS_HDMI_TX_CH_LSB_ADDR(v, i))
+			return true;
+		if (reg == LPASS_HDMI_TX_CH_MSB_ADDR(v, i))
+			return true;
+		if (reg == LPASS_HDMI_TX_DMA_ADDR(v, i))
+			return true;
+	}
+
+	if (reg == LPASS_HDMI_TX_PARITY_ADDR(v))
+		return true;
+	if (reg == LPASS_HDMI_TX_DP_ADDR(v))
+		return true;
+	if (reg == LPASS_HDMI_TX_SSTREAM_ADDR(v))
+		return true;
+	if (reg == LPASS_HDMITX_APP_IRQEN_REG(v))
+		return true;
+	if (reg == LPASS_HDMITX_APP_IRQSTAT_REG(v))
+		return true;
+
+	for (i = 0; i < v->rdma_channels; ++i) {
+		if (reg == LPAIF_HDMI_RDMACTL_REG(v, i))
+			return true;
+		if (reg == LPAIF_HDMI_RDMABASE_REG(v, i))
+			return true;
+		if (reg == LPAIF_HDMI_RDMABUFF_REG(v, i))
+			return true;
+		if (reg == LPAIF_HDMI_RDMAPER_REG(v, i))
+			return true;
+		if (reg == LPAIF_HDMI_RDMACURR_REG(v, i))
+			return true;
+	}
+
+	return false;
+}
+
+static bool lpass_hdmi_regmap_volatile(struct device *dev, unsigned int reg)
+{
+	struct lpass_data *drvdata = dev_get_drvdata(dev);
+	struct lpass_variant *v = drvdata->variant;
+	int i;
+
+	if (reg == LPASS_HDMITX_APP_IRQSTAT_REG(v))
+		return true;
+	if (reg == LPASS_HDMI_TX_LEGACY_ADDR(v))
+		return true;
+
+	for (i = 0; i < v->rdma_channels; ++i) {
+		if (reg == LPAIF_HDMI_RDMACURR_REG(v, i))
+			return true;
+	}
+	return false;
+}

sound/soc/qcom/lpass-hdmi.c line 464

Quoted 10 lines
sound/soc/qcom/lpass-hdmi.c new file +10 -0
+
+struct regmap_config lpass_hdmi_regmap_config = {
+	.reg_bits = 32,
+	.reg_stride = 4,
+	.val_bits = 32,
+	.writeable_reg = lpass_hdmi_regmap_writeable,
+	.readable_reg = lpass_hdmi_regmap_readable,
+	.volatile_reg = lpass_hdmi_regmap_volatile,
+	.cache_type = REGCACHE_FLAT,
+};

]
This should go into lpass-cpu.c

look below for the reasons!

Quoted 101 lines
sound/soc/qcom/lpass-hdmi.c new file +4 -0
+EXPORT_SYMBOL(lpass_hdmi_regmap_config);
+
+MODULE_DESCRIPTION("QTi LPASS HDMI Driver");
+MODULE_LICENSE("GPL v2");
sound/soc/qcom/lpass-hdmi.h new file +91 -0
new file mode 100644
index 0000000..93f0057
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ *
+ * lpass_hdmi.h - Definitions for the QTi LPASS HDMI
+ */
+
+#ifndef __LPASS_HDMI_H__
+#define __LPASS_HDMI_H__
+
+#include <linux/regmap.h>
+
+#define LPASS_HDMITX_LEGACY_DISABLE		0x0
+#define LPASS_HDMITX_LEGACY_ENABLE		0x1
+#define LPASS_DP_AUDIO_BITWIDTH16		0x0
+#define LPASS_DP_AUDIO_BITWIDTH24		0xb
+#define LPASS_DATA_FORMAT_SHIFT			0x1
+#define LPASS_FREQ_BIT_SHIFT			24
+#define LPASS_DATA_FORMAT_LINEAR		0x0
+#define LPASS_DATA_FORMAT_NON_LINEAR	0x1
+#define LPASS_SAMPLING_FREQ32			0x3
+#define LPASS_SAMPLING_FREQ44			0x0
+#define LPASS_SAMPLING_FREQ48			0x2
+#define LPASS_TX_CTL_RESET				0x1
+#define LPASS_TX_CTL_CLEAR				0x0
+#define LPASS_SSTREAM_ENABLE			1
+#define LPASS_SSTREAM_DISABLE			0
+#define LPASS_LAYOUT_SP_DEFAULT			0xf
+#define LPASS_SSTREAM_DEFAULT_ENABLE	1
+#define LPASS_SSTREAM_DEFAULT_DISABLE	0
+#define LPASS_MUTE_ENABLE				1
+#define LPASS_MUTE_DISABLE				0
+#define LPASS_META_DEFAULT_VAL			0
+#define HW_MODE							1
+#define SW_MODE							0
+#define LEGACY_LPASS_LPAIF				1
+#define LEGACY_LPASS_HDMI				0
+#define REPLACE_VBIT					0x1
+#define LINEAR_PCM_DATA					0x0
+#define NON_LINEAR_PCM_DATA				0x1
+#define HDMITX_PARITY_CALC_EN			0x1
+#define HDMITX_PARITY_CALC_DIS			0x0
+#define LPASS_DATA_FORMAT_MASK			GENMASK(1, 1)
+#define LPASS_WORDLENGTH_MASK			GENMASK(3, 0)
+#define LPASS_FREQ_BIT_MASK				GENMASK(27, 24)
+
+#define LPASS_HDMI_TX_CTL_ADDR(v)		(v->hdmi_tx_ctl_addr)
+#define LPASS_HDMI_TX_LEGACY_ADDR(v)	(v->hdmi_legacy_addr)
+#define LPASS_HDMI_TX_VBIT_CTL_ADDR(v)	(v->hdmi_vbit_addr)
+#define LPASS_HDMI_TX_PARITY_ADDR(v)	(v->hdmi_parity_addr)
+#define LPASS_HDMI_TX_DP_ADDR(v)		(v->hdmi_DP_addr)
+#define LPASS_HDMI_TX_SSTREAM_ADDR(v)	(v->hdmi_sstream_addr)
+
+#define LPASS_HDMI_TX_CH_LSB_ADDR(v, port) \
+		(v->hdmi_ch_lsb_addr + v->ch_stride * (port))
+#define LPASS_HDMI_TX_CH_MSB_ADDR(v, port) \
+		(v->hdmi_ch_msb_addr + v->ch_stride * (port))
+#define LPASS_HDMI_TX_DMA_ADDR(v, port) \
+		(v->hdmi_dmactl_addr + v->hdmi_dma_stride * (port))
+
+struct lpass_sstream_ctl {
+	struct regmap_field *sstream_en;
+	struct regmap_field *dma_sel;
+	struct regmap_field *auto_bbit_en;
+	struct regmap_field *layout;
+	struct regmap_field *layout_sp;
+	struct regmap_field *set_sp_on_en;
+	struct regmap_field *dp_audio;
+	struct regmap_field *dp_staffing_en;
+	struct regmap_field *dp_sp_b_hw_en;
+};
+
+struct lpass_dp_metadata_ctl {
+	struct regmap_field *mute;
+	struct regmap_field *as_sdp_cc;
+	struct regmap_field *as_sdp_ct;
+	struct regmap_field *aif_db4;
+	struct regmap_field *frequency;
+	struct regmap_field *mst_index;
+	struct regmap_field *dptx_index;
+};
+
+struct lpass_hdmi_tx_ctl {
+	struct regmap_field *soft_reset;
+	struct regmap_field *force_reset;
+};
+
+struct lpass_hdmitx_dmactl {
+	struct regmap_field *use_hw_chs;
+	struct regmap_field *use_hw_usr;
+	struct regmap_field *hw_chs_sel;Please

sound/soc/qcom/lpass-hdmi.h line 101

Quoted 10 lines
sound/soc/qcom/lpass-hdmi.h new file +10 -0
+	struct regmap_field *hw_usr_sel;
+};
+
+struct lpass_vbit_ctrl {
+		struct regmap_field *replace_vbit;
+		struct regmap_field *vbit_stream;
+};
+
+extern int lpass_hdmi_init_bitfields(struct device *dev, struct regmap *map);
+extern struct regmap_config lpass_hdmi_regmap_config;

I have already commented about this in my previous reviews, This is not really going to work on other platforms that do not have HDMI configs enabled. You will get "undefined reference" compile error when build for apq8016 or other platforms.

Move these to lpass-cpu.c as that is the only user for these two!

Also try to address comments before sending new versions, I see no point in repeating same comments over multiple versions!

Quoted 35 lines
sound/soc/qcom/lpass-hdmi.h new file +5 -0
+extern const struct snd_soc_dai_ops asoc_qcom_lpass_hdmi_dai_ops;
+
+
+
+#endif /* __LPASS_HDMI_H__ */
sound/soc/qcom/lpass-ipq806x.c +2 -2
index 72f09b3..832a916 100644
@@ -96,7 +96,7 @@ static int ipq806x_lpass_exit(struct platform_device *pdev)
  	return 0;
  }
 
-static int ipq806x_lpass_alloc_dma_channel(struct lpass_data *drvdata, int dir)
+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;
@@ -104,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;
  }
sound/soc/qcom/lpass-platform.c +0 -0
index db0d959..a5ab5f1 100644
@@ -80,6 +80,23 @@ static int lpass_platform_alloc_dmactl_fields(struct device *dev,
  					    &v->wrdma_intf, 6);
  }
 

...

Quoted 30 lines
sound/soc/qcom/lpass-platform.c +12 -4
@@ -232,16 +296,24 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
  			regval = LPAIF_DMACTL_WPSCNT_ONE;
  			break;
  		case 2:
-			regval = LPAIF_DMACTL_WPSCNT_TWO;
+			regval = (dai_id == LPASS_DP_RX ?
+			LPAIF_DMACTL_WPSCNT_ONE :
+			LPAIF_DMACTL_WPSCNT_TWO);
  			break;
  		case 4:
-			regval = LPAIF_DMACTL_WPSCNT_FOUR;
+			regval = (dai_id == LPASS_DP_RX ?
+			LPAIF_DMACTL_WPSCNT_TWO :
+			LPAIF_DMACTL_WPSCNT_FOUR);
  			break;
  		case 6:
-			regval = LPAIF_DMACTL_WPSCNT_SIX;
+			regval = (dai_id == LPASS_DP_RX ?
+			LPAIF_DMACTL_WPSCNT_THREE :
+			LPAIF_DMACTL_WPSCNT_SIX);
  			break;
  		case 8:
-			regval = LPAIF_DMACTL_WPSCNT_EIGHT;
+			regval = (dai_id == LPASS_DP_RX ?
+			LPAIF_DMACTL_WPSCNT_FOUR :
+			LPAIF_DMACTL_WPSCNT_EIGHT);
  			break;
  		default:
  			dev_err(soc_runtime->dev,

sound/soc/qcom/lpass-platform.c static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component, · line 327

Quoted 6 lines
sound/soc/qcom/lpass-platform.c +2 -1
@@ -251,7 +323,8 @@ static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
  		}
  		break;
  	default:
-		dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n",
+		dev_err(soc_runtime->dev,
+			"invalid PCM config given: bw=%d,ch=%u\n",

unnecessary change!

Quoted 3 lines
sound/soc/qcom/lpass-platform.c +0 -0
  			bitwidth, channels);
  		return -EINVAL;
  	}

...

Quoted 22 lines
sound/soc/qcom/lpass-platform.c +22 -0
+static irqreturn_t lpass_platform_hdmiif_irq(int irq, void *data)
+{
+	struct lpass_data *drvdata = data;
+	struct lpass_variant *v = drvdata->variant;
+	unsigned int irqs;
+	int rv, chan;
+
+	rv = regmap_read(drvdata->hdmiif_map,
+			LPASS_HDMITX_APP_IRQSTAT_REG(v), &irqs);
+	if (rv) {
+		pr_err("error reading from irqstat reg: %d\n", rv);
+		return IRQ_NONE;
+	}
+
+	/* Handle per channel interrupts */
+	for (chan = 0; chan < LPASS_MAX_HDMI_DMA_CHANNELS; chan++) {
+		if (irqs & (LPAIF_IRQ_ALL(chan) | LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(chan) |
+				LPAIF_IRQ_HDMI_METADONE |
+				LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(chan))
+			&& drvdata->hdmi_substream[chan]) {
+			rv = lpass_dma_interrupt_handler(
+						drvdata->hdmi_substream[chan],

sound/soc/qcom/lpass-platform.c static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) · line 781

Quoted 10 lines
sound/soc/qcom/lpass-platform.c +10 -0
+						drvdata, chan, irqs);
+			if (rv != IRQ_HANDLED)
+				return rv;
+		}
+	}
+
+	return IRQ_HANDLED;
+}
+
+

2 lines not required!

Quoted 51 lines

static int lpass_platform_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *soc_runtime)
{

sound/soc/qcom/lpass-platform.c +26 -0
@@ -649,6 +880,32 @@ int asoc_qcom_lpass_platform_register(struct platform_device *pdev)
  		return ret;
  	}
 
+	if (drvdata->hdmi_port_enable) {
+		drvdata->hdmiif_irq = platform_get_irq_byname(pdev, "lpass-irq-hdmi");
+		if (drvdata->hdmiif_irq < 0)
+			return -ENODEV;
+
+		ret = devm_request_irq(&pdev->dev, drvdata->hdmiif_irq,
+				lpass_platform_hdmiif_irq, 0, "lpass-irq-hdmi", drvdata);
+		if (ret) {
+			dev_err(&pdev->dev, "irq hdmi request failed: %d\n", ret);
+			return ret;
+		}
+		ret = regmap_write(drvdata->hdmiif_map,
+				LPASS_HDMITX_APP_IRQEN_REG(v), 0);
+		if (ret) {
+			dev_err(&pdev->dev, "error writing to hdmi irqen reg: %d\n", ret);
+			return ret;
+		}
+
+		ret = lpass_platform_alloc_hdmidmactl_fields(&pdev->dev,
+							 drvdata->hdmiif_map);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"error initializing hdmidmactl fields: %d\n", ret);
+			return ret;
+		}
+	}
  	return devm_snd_soc_register_component(&pdev->dev,
  			&lpass_component_driver, NULL, 0);
  }
sound/soc/qcom/lpass.h +1 -1
index 7089d4c..2bbb0b9 100644
@@ -1,6 +1,6 @@
  /* SPDX-License-Identifier: GPL-2.0-only */
  /*
- * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2011,2013-2015,2020 The Linux Foundation. All rights reserved.
   *
   * lpass.h - Definitions for the QTi LPASS
   */
@@ -12,10 +12,15 @@
  #include <linux/compiler.h>
  #include <linux/platform_device.h>

sound/soc/qcom/lpass.h line 23

Quoted 10 lines
sound/soc/qcom/lpass.h +5 -0
  #include <linux/regmap.h>
+#include <dt-bindings/sound/sc7180-lpass.h>
+#include "lpass-hdmi.h"
 
  #define LPASS_AHBIX_CLOCK_FREQUENCY		131072000
  #define LPASS_MAX_MI2S_PORTS			(8)
  #define LPASS_MAX_DMA_CHANNELS			(8)
+#define LPASS_MAX_HDMI_DMA_CHANNELS		(4)
+
+

no need for two empty lines here!

sound/soc/qcom/lpass.h struct lpaif_dmactl { · line 49

Quoted 12 lines
sound/soc/qcom/lpass.h +3 -0
  struct lpaif_i2sctl {
  	struct regmap_field *loopback;
@@ -37,6 +42,9 @@ struct lpaif_dmactl {
  	struct regmap_field *fifowm;
  	struct regmap_field *enable;
  	struct regmap_field *dyncclk;
+	struct regmap_field *burst8;
+	struct regmap_field *burst16;
+	struct regmap_field *dynburst;
  };
 

thanks,
srini

#7 lore raw

Re: [PATCH v10 5/7] ASoC: qcom: Add support for lpass hdmi driver

Thanks for review comments Srinivas!!!

Quoted 53 lines · Srinivas Kandagatla
Quoted 24 lines · Srinivasa Rao Mandadapu

From: V Sujith Kumar Reddy <[email protected]>

Upadate lpass cpu and platform driver to support audio over dp. Also add lpass-hdmi.c and lpass-hdmi.h.

---
  sound/soc/qcom/Kconfig           |   5 + sound/soc/qcom/Makefile          |   2 + sound/soc/qcom/lpass-apq8016.c   |   4 +- sound/soc/qcom/lpass-cpu.c       |  51 ++++- sound/soc/qcom/lpass-hdmi.c      | 468
+++++++++++++++++++++++++++++++++++++++
  sound/soc/qcom/lpass-hdmi.h      | 106 +++++++++ sound/soc/qcom/lpass-ipq806x.c   |   4 +- sound/soc/qcom/lpass-lpaif-reg.h |  52 ++++- sound/soc/qcom/lpass-platform.c  | 391
++++++++++++++++++++++++++------
  sound/soc/qcom/lpass.h           | 113 +++++++++-

  10 files changed, 1097 insertions(+), 99 deletions(-)

  create mode 100644 sound/soc/qcom/lpass-hdmi.c
  create mode 100644 sound/soc/qcom/lpass-hdmi.h

...

Quoted 14 lines
sound/soc/qcom/lpass-hdmi.c new file +8 -0
new file mode 100644
index 0000000..ee737f0
@@ -0,0 +1,468 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ *
+ * lpass-hdmi.c -- ALSA SoC HDMI-CPU DAI driver for QTi LPASS HDMI
+ */
+
+

sound/soc/qcom/lpass-hdmi.c line 18

Quoted 10 lines
sound/soc/qcom/lpass-hdmi.c new file +10 -0
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <sound/pcm_params.h>
+#include <linux/regmap.h>
+#include <sound/soc.h>
+#include <sound/soc-dai.h>
+#include <dt-bindings/sound/sc7180-lpass.h>
+#include "lpass-lpaif-reg.h"
+#include "lpass.h"
+

[

Quoted 11 lines

sound/soc/qcom/lpass-hdmi.c line 26

Quoted 8 lines
sound/soc/qcom/lpass-hdmi.c new file +8 -0
+#define QCOM_REGMAP_FIELD_ALLOC(d, m, f, mf)    \
+    do { \
+        mf = devm_regmap_field_alloc(d, m, f);     \
+        if (IS_ERR(mf))                \
+            return -EINVAL;         \
+    } while (0)
+
+

]
should go into lpass.h

okay!. will move to lpass.h

Quoted 83 lines

[

Quoted 82 lines
sound/soc/qcom/lpass-hdmi.c new file +21 -0
+int lpass_hdmi_init_bitfields(struct device *dev, struct regmap *map)
+{
+    struct lpass_data *drvdata = dev_get_drvdata(dev);
+    struct lpass_variant *v = drvdata->variant;
+    unsigned int i;
+    struct lpass_hdmi_tx_ctl *tx_ctl;
+    struct regmap_field *legacy_en;
+    struct lpass_vbit_ctrl *vbit_ctl;
+    struct regmap_field *tx_parity;
+    struct lpass_dp_metadata_ctl *meta_ctl;
+    struct lpass_sstream_ctl *sstream_ctl;
+    struct regmap_field *ch_msb;
+    struct regmap_field *ch_lsb;
+    struct lpass_hdmitx_dmactl *tx_dmactl;
+    int rval;
+
+    tx_ctl = devm_kzalloc(dev, sizeof(*tx_ctl), GFP_KERNEL);
+    if (!tx_ctl)
+        return -ENOMEM;
+
+    QCOM_REGMAP_FIELD_ALLOC(dev, map, v->soft_reset, 

tx_ctl->soft_reset);
+    QCOM_REGMAP_FIELD_ALLOC(dev, map, v->force_reset, tx_ctl->force_reset);
+    drvdata->tx_ctl = tx_ctl;

sound/soc/qcom/lpass-hdmi.c new file +9 -0
+
+    QCOM_REGMAP_FIELD_ALLOC(dev, map, v->legacy_en, legacy_en);
+    drvdata->hdmitx_legacy_en = legacy_en;
+
+    vbit_ctl = devm_kzalloc(dev, sizeof(*vbit_ctl), GFP_KERNEL);
+    if (!vbit_ctl)
+        return -ENOMEM;
+
+    QCOM_REGMAP_FIELD_ALLOC(dev, map, v->replace_vbit, 

vbit_ctl->replace_vbit);
+    QCOM_REGMAP_FIELD_ALLOC(dev, map, v->vbit_stream, vbit_ctl->vbit_stream);
+    drvdata->vbit_ctl = vbit_ctl;

sound/soc/qcom/lpass-hdmi.c new file +10 -0
+
+
+    QCOM_REGMAP_FIELD_ALLOC(dev, map, v->calc_en, tx_parity);
+    drvdata->hdmitx_parity_calc_en = tx_parity;
+
+    meta_ctl = devm_kzalloc(dev, sizeof(*meta_ctl), GFP_KERNEL);
+    if (!meta_ctl)
+        return -ENOMEM;
+
+    rval = devm_regmap_field_bulk_alloc(dev, map, &meta_ctl->mute, 

&v->mute, 7);
+    if (rval)
+        return rval;
+    drvdata->meta_ctl = meta_ctl;

sound/soc/qcom/lpass-hdmi.c new file +6 -0
+
+    sstream_ctl = devm_kzalloc(dev, sizeof(*sstream_ctl), GFP_KERNEL);
+    if (!sstream_ctl)
+        return -ENOMEM;
+
+    rval = devm_regmap_field_bulk_alloc(dev, map, 

&sstream_ctl->sstream_en, &v->sstream_en, 9);
+    if (rval)
+        return rval;

sound/soc/qcom/lpass-hdmi.c new file +15 -0
+
+    drvdata->sstream_ctl = sstream_ctl;
+
+    for (i = 0; i < LPASS_MAX_HDMI_DMA_CHANNELS; i++) {
+        QCOM_REGMAP_FIELD_ALLOC(dev, map, v->msb_bits, ch_msb);
+        drvdata->hdmitx_ch_msb[i] = ch_msb;
+
+        QCOM_REGMAP_FIELD_ALLOC(dev, map, v->lsb_bits, ch_lsb);
+        drvdata->hdmitx_ch_lsb[i] = ch_lsb;
+
+        tx_dmactl = devm_kzalloc(dev, sizeof(*tx_dmactl), GFP_KERNEL);
+        if (!tx_dmactl)
+            return -ENOMEM;
+
+        QCOM_REGMAP_FIELD_ALLOC(dev, map, v->use_hw_chs, 

tx_dmactl->use_hw_chs);
+        QCOM_REGMAP_FIELD_ALLOC(dev, map, v->use_hw_usr, tx_dmactl->use_hw_usr);
+        QCOM_REGMAP_FIELD_ALLOC(dev, map, v->hw_chs_sel, tx_dmactl->hw_chs_sel);
+        QCOM_REGMAP_FIELD_ALLOC(dev, map, v->hw_usr_sel,

Quoted 9 lines
Quoted 5 lines

tx_dmactl->hw_usr_sel);
+        drvdata->hdmi_tx_dmactl[i] = tx_dmactl;
+    }
+    return 0;
+}

]
This should go into lpass-cpu.c

Okay!. Will move to lpass-cpu.c

Quoted 395 lines
Quoted 263 lines
sound/soc/qcom/lpass-hdmi.c new file +3 -0
+EXPORT_SYMBOL(lpass_hdmi_init_bitfields);
 
+
+static int lpass_hdmi_daiops_hw_params(struct snd_pcm_substream 

*substream,
+        struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)

sound/soc/qcom/lpass-hdmi.c new file +53 -0
+{
+    struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+    snd_pcm_format_t format = params_format(params);
+    unsigned int rate = params_rate(params);
+    unsigned int channels = params_channels(params);
+    unsigned int ret;
+    unsigned int bitwidth;
+    unsigned int word_length;
+    unsigned int ch_sts_buf0;
+    unsigned int ch_sts_buf1;
+    unsigned int data_format;
+    unsigned int sampling_freq;
+    unsigned int ch = 0;
+    struct lpass_dp_metadata_ctl *meta_ctl = drvdata->meta_ctl;
+    struct lpass_sstream_ctl *sstream_ctl = drvdata->sstream_ctl;
+
+    bitwidth = snd_pcm_format_width(format);
+    if (bitwidth < 0) {
+        dev_err(dai->dev, "%s invalid bit width given : %d\n",
+                    __func__, bitwidth);
+        return bitwidth;
+    }
+
+    switch (bitwidth) {
+    case 16:
+        word_length = LPASS_DP_AUDIO_BITWIDTH16;
+        break;
+    case 24:
+        word_length = LPASS_DP_AUDIO_BITWIDTH24;
+        break;
+    default:
+        dev_err(dai->dev, "%s invalid bit width given : %d\n",
+                    __func__, bitwidth);
+        return -EINVAL;
+    }
+
+    switch (rate) {
+    case 32000:
+        sampling_freq = LPASS_SAMPLING_FREQ32;
+        break;
+    case 44100:
+        sampling_freq = LPASS_SAMPLING_FREQ44;
+        break;
+    case 48000:
+        sampling_freq = LPASS_SAMPLING_FREQ48;
+        break;
+    default:
+        dev_err(dai->dev, "%s invalid bit width given : %d\n",
+                    __func__, bitwidth);
+        return -EINVAL;
+    }
+    data_format = LPASS_DATA_FORMAT_LINEAR;
+    ch_sts_buf0 = (((data_format << LPASS_DATA_FORMAT_SHIFT) & 

LPASS_DATA_FORMAT_MASK)
+                | ((sampling_freq << LPASS_FREQ_BIT_SHIFT) & LPASS_FREQ_BIT_MASK));
+    ch_sts_buf1 = (word_length) & LPASS_WORDLENGTH_MASK; +
+    ret = regmap_field_write(drvdata->tx_ctl->soft_reset, LPASS_TX_CTL_RESET);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(drvdata->tx_ctl->soft_reset, LPASS_TX_CTL_CLEAR);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(drvdata->hdmitx_legacy_en, LPASS_HDMITX_LEGACY_DISABLE);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(drvdata->hdmitx_parity_calc_en, HDMITX_PARITY_CALC_EN);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(drvdata->vbit_ctl->replace_vbit, REPLACE_VBIT);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(drvdata->vbit_ctl->vbit_stream, LINEAR_PCM_DATA);
+    if (ret)
+        return ret;

sound/soc/qcom/lpass-hdmi.c new file +10 -0
+
+    ret = regmap_field_write(drvdata->hdmitx_ch_msb[0], ch_sts_buf1);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(drvdata->hdmitx_ch_lsb[0], ch_sts_buf0);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(drvdata->hdmi_tx_dmactl[0]->use_hw_chs, 

HW_MODE);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(drvdata->hdmi_tx_dmactl[0]->hw_chs_sel, SW_MODE);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(drvdata->hdmi_tx_dmactl[0]->use_hw_usr, HW_MODE);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(drvdata->hdmi_tx_dmactl[0]->hw_usr_sel, SW_MODE);
+    if (ret)
+        return ret;

sound/soc/qcom/lpass-hdmi.c new file +10 -0
+
+    ret = regmap_field_write(meta_ctl->mute, LPASS_MUTE_ENABLE);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(meta_ctl->as_sdp_cc, channels - 1);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(meta_ctl->as_sdp_ct, 

LPASS_META_DEFAULT_VAL);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(meta_ctl->aif_db4,
LPASS_META_DEFAULT_VAL);
+    if (ret)
+        return ret;

sound/soc/qcom/lpass-hdmi.c new file +6 -0
+
+    ret = regmap_field_write(meta_ctl->frequency, sampling_freq);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(meta_ctl->mst_index, 

LPASS_META_DEFAULT_VAL);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(meta_ctl->dptx_index, LPASS_META_DEFAULT_VAL);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(sstream_ctl->sstream_en, LPASS_SSTREAM_DISABLE);
+    if (ret)
+        return ret;

sound/soc/qcom/lpass-hdmi.c new file +6 -0
+
+    ret = regmap_field_write(sstream_ctl->dma_sel, ch);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(sstream_ctl->auto_bbit_en, 

LPASS_SSTREAM_DEFAULT_ENABLE);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(sstream_ctl->layout, LPASS_SSTREAM_DEFAULT_DISABLE);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(sstream_ctl->layout_sp, LPASS_LAYOUT_SP_DEFAULT);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(sstream_ctl->dp_audio, LPASS_SSTREAM_DEFAULT_ENABLE);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(sstream_ctl->set_sp_on_en, LPASS_SSTREAM_DEFAULT_ENABLE);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(sstream_ctl->dp_sp_b_hw_en, LPASS_SSTREAM_DEFAULT_ENABLE);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(sstream_ctl->dp_staffing_en, LPASS_SSTREAM_DEFAULT_ENABLE);
+    if (ret)
+        return ret;

sound/soc/qcom/lpass-hdmi.c new file +5 -0
+
+    return ret;
+}
+
+static int lpass_hdmi_daiops_prepare(struct snd_pcm_substream 

*substream,
+        struct snd_soc_dai *dai)

sound/soc/qcom/lpass-hdmi.c new file +5 -0
+{
+    int ret;
+    struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+
+    ret = regmap_field_write(drvdata->sstream_ctl->sstream_en, 

LPASS_SSTREAM_ENABLE);
+    if (ret)
+        return ret;
+
+    ret = regmap_field_write(drvdata->meta_ctl->mute, LPASS_MUTE_DISABLE);
+    if (ret)
+        return ret;

sound/soc/qcom/lpass-hdmi.c new file +5 -0
+
+    return ret;
+}
+
+static int lpass_hdmi_daiops_trigger(struct snd_pcm_substream 

*substream,
+        int cmd, struct snd_soc_dai *dai)

sound/soc/qcom/lpass-hdmi.c new file +11 -0
+{
+    struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai);
+    struct lpass_dp_metadata_ctl *meta_ctl = drvdata->meta_ctl;
+    struct lpass_sstream_ctl *sstream_ctl = drvdata->sstream_ctl;
+    int ret = -EINVAL;
+
+    switch (cmd) {
+    case SNDRV_PCM_TRIGGER_START:
+    case SNDRV_PCM_TRIGGER_RESUME:
+    case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+        ret = regmap_field_write(sstream_ctl->sstream_en, 

LPASS_SSTREAM_ENABLE);
+        if (ret)
+            return ret;

sound/soc/qcom/lpass-hdmi.c new file +10 -0
+
+        ret = regmap_field_write(meta_ctl->mute, LPASS_MUTE_DISABLE);
+        if (ret)
+            return ret;
+
+        break;
+    case SNDRV_PCM_TRIGGER_STOP:
+    case SNDRV_PCM_TRIGGER_SUSPEND:
+    case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+        ret = regmap_field_write(sstream_ctl->sstream_en, 

LPASS_SSTREAM_DISABLE);
+        if (ret)
+            return ret;

sound/soc/qcom/lpass-hdmi.c new file +11 -0
+
+        ret = regmap_field_write(meta_ctl->mute, LPASS_MUTE_ENABLE);
+        if (ret)
+            return ret;
+
+        ret = regmap_field_write(sstream_ctl->dp_audio, 0);
+        if (ret)
+            return ret;
+
+        break;
+    }

sound/soc/qcom/lpass-hdmi.c line 343

Quoted 10 lines
sound/soc/qcom/lpass-hdmi.c new file +10 -0
+    return ret;
+}
+
+const struct snd_soc_dai_ops asoc_qcom_lpass_hdmi_dai_ops = {
+    .hw_params    = lpass_hdmi_daiops_hw_params,
+    .prepare    = lpass_hdmi_daiops_prepare,
+    .trigger    = lpass_hdmi_daiops_trigger,
+};
+EXPORT_SYMBOL_GPL(asoc_qcom_lpass_hdmi_dai_ops);
+

[

Quoted 119 lines

+static bool lpass_hdmi_regmap_writeable(struct device *dev, unsigned int reg)

sound/soc/qcom/lpass-hdmi.c new file +45 -0
+{
+    struct lpass_data *drvdata = dev_get_drvdata(dev);
+    struct lpass_variant *v = drvdata->variant;
+    int i;
+
+    if (reg == LPASS_HDMI_TX_CTL_ADDR(v))
+        return true;
+    if (reg == LPASS_HDMI_TX_LEGACY_ADDR(v))
+        return true;
+    if (reg == LPASS_HDMI_TX_VBIT_CTL_ADDR(v))
+        return true;
+    if (reg == LPASS_HDMI_TX_PARITY_ADDR(v))
+        return true;
+    if (reg == LPASS_HDMI_TX_DP_ADDR(v))
+        return true;
+    if (reg == LPASS_HDMI_TX_SSTREAM_ADDR(v))
+        return true;
+    if (reg == LPASS_HDMITX_APP_IRQEN_REG(v))
+        return true;
+    if (reg == LPASS_HDMITX_APP_IRQCLEAR_REG(v))
+        return true;
+
+    for (i = 0; i < v->hdmi_rdma_channels; i++) {
+        if (reg == LPASS_HDMI_TX_CH_LSB_ADDR(v, i))
+            return true;
+        if (reg == LPASS_HDMI_TX_CH_MSB_ADDR(v, i))
+            return true;
+        if (reg == LPASS_HDMI_TX_DMA_ADDR(v, i))
+            return true;
+    }
+
+    for (i = 0; i < v->rdma_channels; ++i) {
+        if (reg == LPAIF_HDMI_RDMACTL_REG(v, i))
+            return true;
+        if (reg == LPAIF_HDMI_RDMABASE_REG(v, i))
+            return true;
+        if (reg == LPAIF_HDMI_RDMABUFF_REG(v, i))
+            return true;
+        if (reg == LPAIF_HDMI_RDMAPER_REG(v, i))
+            return true;
+    }
+    return false;
+}
+
+static bool lpass_hdmi_regmap_readable(struct device *dev, unsigned 

int reg)

sound/soc/qcom/lpass-hdmi.c new file +49 -0
+{
+    struct lpass_data *drvdata = dev_get_drvdata(dev);
+    struct lpass_variant *v = drvdata->variant;
+    int i;
+
+    if (reg == LPASS_HDMI_TX_CTL_ADDR(v))
+        return true;
+    if (reg == LPASS_HDMI_TX_LEGACY_ADDR(v))
+        return true;
+    if (reg == LPASS_HDMI_TX_VBIT_CTL_ADDR(v))
+        return true;
+
+    for (i = 0; i < v->hdmi_rdma_channels; i++) {
+        if (reg == LPASS_HDMI_TX_CH_LSB_ADDR(v, i))
+            return true;
+        if (reg == LPASS_HDMI_TX_CH_MSB_ADDR(v, i))
+            return true;
+        if (reg == LPASS_HDMI_TX_DMA_ADDR(v, i))
+            return true;
+    }
+
+    if (reg == LPASS_HDMI_TX_PARITY_ADDR(v))
+        return true;
+    if (reg == LPASS_HDMI_TX_DP_ADDR(v))
+        return true;
+    if (reg == LPASS_HDMI_TX_SSTREAM_ADDR(v))
+        return true;
+    if (reg == LPASS_HDMITX_APP_IRQEN_REG(v))
+        return true;
+    if (reg == LPASS_HDMITX_APP_IRQSTAT_REG(v))
+        return true;
+
+    for (i = 0; i < v->rdma_channels; ++i) {
+        if (reg == LPAIF_HDMI_RDMACTL_REG(v, i))
+            return true;
+        if (reg == LPAIF_HDMI_RDMABASE_REG(v, i))
+            return true;
+        if (reg == LPAIF_HDMI_RDMABUFF_REG(v, i))
+            return true;
+        if (reg == LPAIF_HDMI_RDMAPER_REG(v, i))
+            return true;
+        if (reg == LPAIF_HDMI_RDMACURR_REG(v, i))
+            return true;
+    }
+
+    return false;
+}
+
+static bool lpass_hdmi_regmap_volatile(struct device *dev, unsigned 

int reg)

sound/soc/qcom/lpass-hdmi.c new file +21 -0
+{
+    struct lpass_data *drvdata = dev_get_drvdata(dev);
+    struct lpass_variant *v = drvdata->variant;
+    int i;
+
+    if (reg == LPASS_HDMITX_APP_IRQSTAT_REG(v))
+        return true;
+    if (reg == LPASS_HDMI_TX_LEGACY_ADDR(v))
+        return true;
+
+    for (i = 0; i < v->rdma_channels; ++i) {
+        if (reg == LPAIF_HDMI_RDMACURR_REG(v, i))
+            return true;
+    }
+    return false;
+}
+
+struct regmap_config lpass_hdmi_regmap_config = {
+    .reg_bits = 32,
+    .reg_stride = 4,
+    .val_bits = 32,
Quoted 9 lines
Quoted 5 lines

+    .writeable_reg = lpass_hdmi_regmap_writeable, +    .readable_reg = lpass_hdmi_regmap_readable, +    .volatile_reg = lpass_hdmi_regmap_volatile, +    .cache_type = REGCACHE_FLAT,
+};

]
This should go into lpass-cpu.c

okay! Will move these APIs and struct to lpass-cpu.c.

Quoted 109 lines

look below for the reasons!

Quoted 106 lines
sound/soc/qcom/lpass-hdmi.c new file +4 -0
+EXPORT_SYMBOL(lpass_hdmi_regmap_config);
+
+MODULE_DESCRIPTION("QTi LPASS HDMI Driver");
+MODULE_LICENSE("GPL v2");
sound/soc/qcom/lpass-hdmi.h new file +96 -0
new file mode 100644
index 0000000..93f0057
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
+ *
+ * lpass_hdmi.h - Definitions for the QTi LPASS HDMI
+ */
+
+#ifndef __LPASS_HDMI_H__
+#define __LPASS_HDMI_H__
+
+#include <linux/regmap.h>
+
+#define LPASS_HDMITX_LEGACY_DISABLE        0x0
+#define LPASS_HDMITX_LEGACY_ENABLE        0x1
+#define LPASS_DP_AUDIO_BITWIDTH16        0x0
+#define LPASS_DP_AUDIO_BITWIDTH24        0xb
+#define LPASS_DATA_FORMAT_SHIFT            0x1
+#define LPASS_FREQ_BIT_SHIFT            24
+#define LPASS_DATA_FORMAT_LINEAR        0x0
+#define LPASS_DATA_FORMAT_NON_LINEAR    0x1
+#define LPASS_SAMPLING_FREQ32            0x3
+#define LPASS_SAMPLING_FREQ44            0x0
+#define LPASS_SAMPLING_FREQ48            0x2
+#define LPASS_TX_CTL_RESET                0x1
+#define LPASS_TX_CTL_CLEAR                0x0
+#define LPASS_SSTREAM_ENABLE            1
+#define LPASS_SSTREAM_DISABLE            0
+#define LPASS_LAYOUT_SP_DEFAULT            0xf
+#define LPASS_SSTREAM_DEFAULT_ENABLE    1
+#define LPASS_SSTREAM_DEFAULT_DISABLE    0
+#define LPASS_MUTE_ENABLE                1
+#define LPASS_MUTE_DISABLE                0
+#define LPASS_META_DEFAULT_VAL            0
+#define HW_MODE                            1
+#define SW_MODE                            0
+#define LEGACY_LPASS_LPAIF                1
+#define LEGACY_LPASS_HDMI                0
+#define REPLACE_VBIT                    0x1
+#define LINEAR_PCM_DATA                    0x0
+#define NON_LINEAR_PCM_DATA                0x1
+#define HDMITX_PARITY_CALC_EN            0x1
+#define HDMITX_PARITY_CALC_DIS            0x0
+#define LPASS_DATA_FORMAT_MASK            GENMASK(1, 1)
+#define LPASS_WORDLENGTH_MASK            GENMASK(3, 0)
+#define LPASS_FREQ_BIT_MASK                GENMASK(27, 24)
+
+#define LPASS_HDMI_TX_CTL_ADDR(v) (v->hdmi_tx_ctl_addr)
+#define LPASS_HDMI_TX_LEGACY_ADDR(v) (v->hdmi_legacy_addr)
+#define LPASS_HDMI_TX_VBIT_CTL_ADDR(v) (v->hdmi_vbit_addr)
+#define LPASS_HDMI_TX_PARITY_ADDR(v) (v->hdmi_parity_addr)
+#define LPASS_HDMI_TX_DP_ADDR(v)        (v->hdmi_DP_addr)
+#define LPASS_HDMI_TX_SSTREAM_ADDR(v) (v->hdmi_sstream_addr)
+
+#define LPASS_HDMI_TX_CH_LSB_ADDR(v, port) \
+        (v->hdmi_ch_lsb_addr + v->ch_stride * (port))
+#define LPASS_HDMI_TX_CH_MSB_ADDR(v, port) \
+        (v->hdmi_ch_msb_addr + v->ch_stride * (port))
+#define LPASS_HDMI_TX_DMA_ADDR(v, port) \
+        (v->hdmi_dmactl_addr + v->hdmi_dma_stride * (port))
+
+struct lpass_sstream_ctl {
+    struct regmap_field *sstream_en;
+    struct regmap_field *dma_sel;
+    struct regmap_field *auto_bbit_en;
+    struct regmap_field *layout;
+    struct regmap_field *layout_sp;
+    struct regmap_field *set_sp_on_en;
+    struct regmap_field *dp_audio;
+    struct regmap_field *dp_staffing_en;
+    struct regmap_field *dp_sp_b_hw_en;
+};
+
+struct lpass_dp_metadata_ctl {
+    struct regmap_field *mute;
+    struct regmap_field *as_sdp_cc;
+    struct regmap_field *as_sdp_ct;
+    struct regmap_field *aif_db4;
+    struct regmap_field *frequency;
+    struct regmap_field *mst_index;
+    struct regmap_field *dptx_index;
+};
+
+struct lpass_hdmi_tx_ctl {
+    struct regmap_field *soft_reset;
+    struct regmap_field *force_reset;
+};
+
+struct lpass_hdmitx_dmactl {
+    struct regmap_field *use_hw_chs;
+    struct regmap_field *use_hw_usr;
+    struct regmap_field *hw_chs_sel;Please
+    struct regmap_field *hw_usr_sel;
+};
+
+struct lpass_vbit_ctrl {
+        struct regmap_field *replace_vbit;
Quoted 8 lines
Quoted 6 lines
sound/soc/qcom/lpass-hdmi.h new file +4 -0
+        struct regmap_field *vbit_stream;
+};
+
+extern int lpass_hdmi_init_bitfields(struct device *dev, struct 

regmap *map);
+extern struct regmap_config lpass_hdmi_regmap_config;

I have already commented about this in my previous reviews, This is not really going to work on other platforms that do not have HDMI configs enabled. You will get "undefined reference" compile error when build for apq8016 or other platforms.

Yeah.. Actually we thought of keeping all HDMI API's in one file. didn't think of it's affect. Thanks for pointing out it's impact.

Quoted 2 lines

Move these to lpass-cpu.c as that is the only user for these two!

Okay!. We will move it.

Quoted 2 lines

Also try to address comments before sending new versions, I see no point in repeating same comments over multiple versions!

Okay!. Actually I have been addressing comments. But few comments after reply we encountered some ambiguity.

so is the reason we couldn't fix some comments. will take care next time. After verifying changes we will reply on review comments.

Quoted 75 lines
Quoted 38 lines
sound/soc/qcom/lpass-hdmi.h new file +5 -0
+extern const struct snd_soc_dai_ops asoc_qcom_lpass_hdmi_dai_ops;
+
+
+
+#endif /* __LPASS_HDMI_H__ */
sound/soc/qcom/lpass-ipq806x.c +1 -0
index 72f09b3..832a916 100644
@@ -96,7 +96,7 @@ static int ipq806x_lpass_exit(struct 
 platform_device *pdev)
       return 0;
   }
   -static int ipq806x_lpass_alloc_dma_channel(struct lpass_data *drvdata, int dir)
+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;

sound/soc/qcom/lpass-ipq806x.c +1 -0
@@ -104,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;
  }

sound/soc/qcom/lpass-platform.c +0 -0
index db0d959..a5ab5f1 100644
@@ -80,6 +80,23 @@ static int 
 lpass_platform_alloc_dmactl_fields(struct device *dev,
                           &v->wrdma_intf, 6);
   }

...

Quoted 33 lines
sound/soc/qcom/lpass-platform.c +0 -0
@@ -232,16 +296,24 @@ static int 
 lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
               regval = LPAIF_DMACTL_WPSCNT_ONE;
               break;

          case 2:
-            regval = LPAIF_DMACTL_WPSCNT_TWO;
+            regval = (dai_id == LPASS_DP_RX ?
+            LPAIF_DMACTL_WPSCNT_ONE :
+            LPAIF_DMACTL_WPSCNT_TWO);
              break;
          case 4:
-            regval = LPAIF_DMACTL_WPSCNT_FOUR;
+            regval = (dai_id == LPASS_DP_RX ?
+            LPAIF_DMACTL_WPSCNT_TWO :
+            LPAIF_DMACTL_WPSCNT_FOUR);
              break;
          case 6:
-            regval = LPAIF_DMACTL_WPSCNT_SIX;
+            regval = (dai_id == LPASS_DP_RX ?
+            LPAIF_DMACTL_WPSCNT_THREE :
+            LPAIF_DMACTL_WPSCNT_SIX);
              break;
          case 8:
-            regval = LPAIF_DMACTL_WPSCNT_EIGHT;
+            regval = (dai_id == LPASS_DP_RX ?
+            LPAIF_DMACTL_WPSCNT_FOUR :
+            LPAIF_DMACTL_WPSCNT_EIGHT);
              break;
          default:
              dev_err(soc_runtime->dev,

sound/soc/qcom/lpass-platform.c +0 -0
@@ -251,7 +323,8 @@ static int lpass_platform_pcmops_hw_params(struct 
 snd_soc_component *component,
           }
Quoted 8 lines
Quoted 6 lines
sound/soc/qcom/lpass-platform.c +0 -0
           break;

      default:
-        dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n",
+        dev_err(soc_runtime->dev,
+            "invalid PCM config given: bw=%d,ch=%u\n",

unnecessary change!

Okay!. Will revert this change.

Quoted 101 lines
Quoted 5 lines

              bitwidth, channels);
          return -EINVAL;
      }

...

Quoted 28 lines
sound/soc/qcom/lpass-platform.c +17 -0
+static irqreturn_t lpass_platform_hdmiif_irq(int irq, void *data)
+{
+    struct lpass_data *drvdata = data;
+    struct lpass_variant *v = drvdata->variant;
+    unsigned int irqs;
+    int rv, chan;
+
+    rv = regmap_read(drvdata->hdmiif_map,
+            LPASS_HDMITX_APP_IRQSTAT_REG(v), &irqs);
+    if (rv) {
+        pr_err("error reading from irqstat reg: %d\n", rv);
+        return IRQ_NONE;
+    }
+
+    /* Handle per channel interrupts */
+    for (chan = 0; chan < LPASS_MAX_HDMI_DMA_CHANNELS; chan++) {
+        if (irqs & (LPAIF_IRQ_ALL(chan) | 

LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(chan) |
+                LPAIF_IRQ_HDMI_METADONE |
+                LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(chan)) +            && drvdata->hdmi_substream[chan]) { +            rv = lpass_dma_interrupt_handler( +                        drvdata->hdmi_substream[chan], +                        drvdata, chan, irqs); +            if (rv != IRQ_HANDLED)
+                return rv;
+        }
+    }

sound/soc/qcom/lpass-platform.c static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) · line 781

Quoted 5 lines
sound/soc/qcom/lpass-platform.c +5 -0
+
+    return IRQ_HANDLED;
+}
+
+

2 lines not required!

Quoted 58 lines

  static int lpass_platform_pcm_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *soc_runtime) {

sound/soc/qcom/lpass-platform.c +14 -0
@@ -649,6 +880,32 @@ int asoc_qcom_lpass_platform_register(struct 
 platform_device *pdev)
           return ret;
       }
   +    if (drvdata->hdmi_port_enable) {
+        drvdata->hdmiif_irq = platform_get_irq_byname(pdev, 
 "lpass-irq-hdmi");
+        if (drvdata->hdmiif_irq < 0)
+            return -ENODEV;
+
+        ret = devm_request_irq(&pdev->dev, drvdata->hdmiif_irq,
+                lpass_platform_hdmiif_irq, 0, "lpass-irq-hdmi", 
 drvdata);
+        if (ret) {
+            dev_err(&pdev->dev, "irq hdmi request failed: %d\n", ret);
+            return ret;
+        }
+        ret = regmap_write(drvdata->hdmiif_map,
+                LPASS_HDMITX_APP_IRQEN_REG(v), 0);
+        if (ret) {
+            dev_err(&pdev->dev, "error writing to hdmi irqen reg: 

%d\n", ret);
+            return ret;
+        }
+
+        ret = lpass_platform_alloc_hdmidmactl_fields(&pdev->dev, +                             drvdata->hdmiif_map);
+        if (ret) {
+            dev_err(&pdev->dev,
+                "error initializing hdmidmactl fields: %d\n", ret); +            return ret;
+        }
+    }
      return devm_snd_soc_register_component(&pdev->dev, &lpass_component_driver, NULL, 0);
  }

sound/soc/qcom/lpass.h +0 -1
index 7089d4c..2bbb0b9 100644
@@ -1,6 +1,6 @@
   /* SPDX-License-Identifier: GPL-2.0-only */
   /*
- * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All 

rights reserved.
+ * Copyright (c) 2010-2011,2013-2015,2020 The Linux Foundation. All rights reserved.
   *
   * lpass.h - Definitions for the QTi LPASS
   */

sound/soc/qcom/lpass.h +1 -0
@@ -12,10 +12,15 @@
   #include <linux/compiler.h>
   #include <linux/platform_device.h>
   #include <linux/regmap.h>
+#include <dt-bindings/sound/sc7180-lpass.h>
Quoted 8 lines

sound/soc/qcom/lpass.h line 23

Quoted 7 lines
sound/soc/qcom/lpass.h +4 -0
+#include "lpass-hdmi.h"
     #define LPASS_AHBIX_CLOCK_FREQUENCY        131072000
   #define LPASS_MAX_MI2S_PORTS            (8)
   #define LPASS_MAX_DMA_CHANNELS            (8)
+#define LPASS_MAX_HDMI_DMA_CHANNELS        (4)
+
+

no need for two empty lines here!

Okay!. will remove extra lines.

Quoted 14 lines

sound/soc/qcom/lpass.h struct lpaif_dmactl { · line 48

Quoted 11 lines
sound/soc/qcom/lpass.h +3 -0
     struct lpaif_i2sctl {
       struct regmap_field *loopback;
@@ -37,6 +42,9 @@ struct lpaif_dmactl {
       struct regmap_field *fifowm;
       struct regmap_field *enable;
       struct regmap_field *dyncclk;
+    struct regmap_field *burst8;
+    struct regmap_field *burst16;
+    struct regmap_field *dynburst;
   };

thanks,
srini

Signature · 2 lines
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc.,
is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
#8 lore raw

PATCH v10 6/7 Asoc: qcom: lpass-platform : Increase buffer size

In reply to Srinivasa Rao Mandadapu

From: V Sujith Kumar Reddy <[email protected]>

Increase buffer size to support audio over DP.

---
 sound/soc/qcom/lpass-platform.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/qcom/lpass-platform.c +1 -1
index a5ab5f1..92ccedb 100644
@@ -23,7 +23,7 @@ struct lpass_pcm_data {
 	int i2s_port;
 };
 
-#define LPASS_PLATFORM_BUFFER_SIZE	(16 * 1024)
+#define LPASS_PLATFORM_BUFFER_SIZE	(24 *  2 * 1024)
 #define LPASS_PLATFORM_PERIODS		2
 
 static const struct snd_pcm_hardware lpass_platform_pcm_hardware = {
Signature · 2 lines
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc.,
is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
#9 lore raw

PATCH v10 7/7 ASoC: qcom: sc7180: Add support for audio over DP

In reply to Srinivasa Rao Mandadapu

From: V Sujith Kumar Reddy <[email protected]>

Add support for audio playback over DP in lpass
sc7180 platform driver. Update lpass_variant
structure for hdmi data configuaration.

---
 sound/soc/qcom/lpass-sc7180.c | 116 +++++++++++++++++++++++++++++++++++++-----
 1 file changed, 102 insertions(+), 14 deletions(-)
sound/soc/qcom/lpass-sc7180.c +102 -14
index a8a3d8f..c6292f9e 100644
@@ -60,38 +60,65 @@ static struct snd_soc_dai_driver sc7180_lpass_cpu_dai_driver[] = {
 		.probe	= &asoc_qcom_lpass_cpu_dai_probe,
 		.ops    = &asoc_qcom_lpass_cpu_dai_ops,
 	},
+	[LPASS_DP_RX] = {
+		.id = LPASS_DP_RX,
+		.name = "Hdmi",
+		.playback = {
+			.stream_name = "Hdmi Playback",
+			.formats	= SNDRV_PCM_FMTBIT_S24,
+			.rates = SNDRV_PCM_RATE_48000,
+			.rate_min	= 48000,
+			.rate_max	= 48000,
+			.channels_min	= 2,
+			.channels_max	= 2,
+		},
+		.ops    = &asoc_qcom_lpass_hdmi_dai_ops,
+	},
 };
 
 static int sc7180_lpass_alloc_dma_channel(struct lpass_data *drvdata,
-					   int direction)
+					   int direction, unsigned int dai_id)
 {
 	struct lpass_variant *v = drvdata->variant;
 	int chan = 0;
 
-	if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
-		chan = find_first_zero_bit(&drvdata->dma_ch_bit_map,
-					v->rdma_channels);
+	if (dai_id == LPASS_DP_RX) {
+		if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+			chan = find_first_zero_bit(&drvdata->hdmi_dma_ch_bit_map,
+						v->hdmi_rdma_channels);
+
+			if (chan >= v->hdmi_rdma_channels)
+				return -EBUSY;
+		}
+		set_bit(chan, &drvdata->hdmi_dma_ch_bit_map);
+	} else {
+		if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
+			chan = find_first_zero_bit(&drvdata->dma_ch_bit_map,
+						v->rdma_channels);
 
 		if (chan >= v->rdma_channels)
 			return -EBUSY;
-	} else {
-		chan = find_next_zero_bit(&drvdata->dma_ch_bit_map,
+		} else {
+			chan = find_next_zero_bit(&drvdata->dma_ch_bit_map,
 					v->wrdma_channel_start +
 					v->wrdma_channels,
 					v->wrdma_channel_start);
 
-		if (chan >=  v->wrdma_channel_start + v->wrdma_channels)
-			return -EBUSY;
-	}
-
-	set_bit(chan, &drvdata->dma_ch_bit_map);
+			if (chan >=  v->wrdma_channel_start + v->wrdma_channels)
+				return -EBUSY;
+		}
 
+		set_bit(chan, &drvdata->dma_ch_bit_map);
+	}
 	return chan;
 }
 
-static int sc7180_lpass_free_dma_channel(struct lpass_data *drvdata, int chan)
+static int sc7180_lpass_free_dma_channel(struct lpass_data *drvdata, int chan, unsigned int dai_id)
 {
-	clear_bit(chan, &drvdata->dma_ch_bit_map);
+	if (dai_id == LPASS_DP_RX)
+		clear_bit(chan, &drvdata->hdmi_dma_ch_bit_map);
+	else
+		clear_bit(chan, &drvdata->dma_ch_bit_map);
 
 	return 0;
 }
@@ -144,6 +171,9 @@ static struct lpass_variant sc7180_data = {
 	.rdma_reg_base		= 0xC000,
 	.rdma_reg_stride	= 0x1000,
 	.rdma_channels		= 5,
+	.hdmi_rdma_reg_base		= 0x64000,
+	.hdmi_rdma_reg_stride	= 0x1000,
+	.hdmi_rdma_channels		= 4,
 	.dmactl_audif_start	= 1,
 	.wrdma_reg_base		= 0x18000,
 	.wrdma_reg_stride	= 0x1000,
@@ -163,7 +193,7 @@ static struct lpass_variant sc7180_data = {
 	.rdma_dyncclk		= REG_FIELD_ID(0xC000, 21, 21, 5, 0x1000),
 	.rdma_bursten		= REG_FIELD_ID(0xC000, 20, 20, 5, 0x1000),
 	.rdma_wpscnt		= REG_FIELD_ID(0xC000, 16, 19, 5, 0x1000),
-	.rdma_intf		= REG_FIELD_ID(0xC000, 12, 15, 5, 0x1000),
+	.rdma_intf			= REG_FIELD_ID(0xC000, 12, 15, 5, 0x1000),
 	.rdma_fifowm		= REG_FIELD_ID(0xC000, 1, 5, 5, 0x1000),
 	.rdma_enable		= REG_FIELD_ID(0xC000, 0, 0, 5, 0x1000),
 
@@ -174,6 +204,64 @@ static struct lpass_variant sc7180_data = {
 	.wrdma_fifowm		= REG_FIELD_ID(0x18000, 1, 5, 4, 0x1000),
 	.wrdma_enable		= REG_FIELD_ID(0x18000, 0, 0, 4, 0x1000),
 
+	.hdmi_tx_ctl_addr	= 0x1000,
+	.hdmi_legacy_addr	= 0x1008,
+	.hdmi_vbit_addr		= 0x610c0,
+	.hdmi_ch_lsb_addr	= 0x61048,
+	.hdmi_ch_msb_addr	= 0x6104c,
+	.ch_stride		= 0x8,
+	.hdmi_parity_addr	= 0x61034,
+	.hdmi_dmactl_addr	= 0x61038,
+	.hdmi_dma_stride	= 0x4,
+	.hdmi_DP_addr		= 0x610c8,
+	.hdmi_sstream_addr	= 0x6101c,
+	.hdmi_irq_reg_base		= 0x63000,
+	.hdmi_irq_ports		= 1,
+
+	.hdmi_rdma_dyncclk		= REG_FIELD_ID(0x64000, 14, 14, 4, 0x1000),
+	.hdmi_rdma_bursten		= REG_FIELD_ID(0x64000, 13, 13, 4, 0x1000),
+	.hdmi_rdma_burst8		= REG_FIELD_ID(0x64000, 15, 15, 4, 0x1000),
+	.hdmi_rdma_burst16		= REG_FIELD_ID(0x64000, 16, 16, 4, 0x1000),
+	.hdmi_rdma_dynburst		= REG_FIELD_ID(0x64000, 18, 18, 4, 0x1000),
+	.hdmi_rdma_wpscnt		= REG_FIELD_ID(0x64000, 10, 12, 4, 0x1000),
+	.hdmi_rdma_fifowm		= REG_FIELD_ID(0x64000, 1, 5, 4, 0x1000),
+	.hdmi_rdma_enable		= REG_FIELD_ID(0x64000, 0, 0, 4, 0x1000),
+
+	.sstream_en		= REG_FIELD(0x6101c, 0, 0),
+	.dma_sel			= REG_FIELD(0x6101c, 1, 2),
+	.auto_bbit_en	= REG_FIELD(0x6101c, 3, 3),
+	.layout			= REG_FIELD(0x6101c, 4, 4),
+	.layout_sp		= REG_FIELD(0x6101c, 5, 8),
+	.set_sp_on_en	= REG_FIELD(0x6101c, 10, 10),
+	.dp_audio		= REG_FIELD(0x6101c, 11, 11),
+	.dp_staffing_en	= REG_FIELD(0x6101c, 12, 12),
+	.dp_sp_b_hw_en	= REG_FIELD(0x6101c, 13, 13),
+
+	.mute			= REG_FIELD(0x610c8, 0, 0),
+	.as_sdp_cc		= REG_FIELD(0x610c8, 1, 3),
+	.as_sdp_ct		= REG_FIELD(0x610c8, 4, 7),
+	.aif_db4			= REG_FIELD(0x610c8, 8, 15),
+	.frequency		= REG_FIELD(0x610c8, 16, 21),
+	.mst_index		= REG_FIELD(0x610c8, 28, 29),
+	.dptx_index		= REG_FIELD(0x610c8, 30, 31),
+
+	.soft_reset		= REG_FIELD(0x1000, 31, 31),
+	.force_reset	= REG_FIELD(0x1000, 30, 30),
+
+	.use_hw_chs		= REG_FIELD(0x61038, 0, 0),
+	.use_hw_usr		= REG_FIELD(0x61038, 1, 1),
+	.hw_chs_sel		= REG_FIELD(0x61038, 2, 4),
+	.hw_usr_sel		= REG_FIELD(0x61038, 5, 6),
+
+	.replace_vbit	= REG_FIELD(0x610c0, 0, 0),
+	.vbit_stream	= REG_FIELD(0x610c0, 1, 1),
+
+	.legacy_en		=  REG_FIELD(0x1008, 0, 0),
+	.calc_en		=  REG_FIELD(0x61034, 0, 0),
+	.lsb_bits		=  REG_FIELD(0x61048, 0, 31),
+	.msb_bits		=  REG_FIELD(0x6104c, 0, 31),
+
+
 	.clk_name		= (const char*[]) {
 				   "pcnoc-sway-clk",
 				   "audio-core",
Signature · 2 lines
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc.,
is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.