[PATCH] ASoC: rt5682: Have global name clock option for parent clk

2020-09-06 Thread Akshu Agrawal
When adding parent clk(mclk) to wclk, this adds fallback option
for the case where global clk name is used.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/codecs/rt5682.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c
index 93ebf0279b62..26928bc49bcb 100644
--- a/sound/soc/codecs/rt5682.c
+++ b/sound/soc/codecs/rt5682.c
@@ -2780,6 +2780,7 @@ static int rt5682_register_dai_clks(struct 
snd_soc_component *component)
if (rt5682->mclk) {
init.parent_data = &(struct clk_parent_data){
.fw_name = "mclk",
+   .name = __clk_get_name(rt5682->mclk),
};
init.num_parents = 1;
}
-- 
2.20.1



[v2] ASoC: AMD: Clean kernel log from deferred probe error messages

2020-08-26 Thread Akshu Agrawal
While the driver waits for DAIs to be probed and retries probing,
have the error messages at debug level instead of error.

Signed-off-by: Akshu Agrawal 
---
v2: Add a debug level message for -EPROBE_DEFER

 sound/soc/amd/acp3x-rt5682-max9836.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c 
b/sound/soc/amd/acp3x-rt5682-max9836.c
index 406526e79af3..1a4e8ca0f99c 100644
--- a/sound/soc/amd/acp3x-rt5682-max9836.c
+++ b/sound/soc/amd/acp3x-rt5682-max9836.c
@@ -472,12 +472,17 @@ static int acp3x_probe(struct platform_device *pdev)
 
ret = devm_snd_soc_register_card(>dev, card);
if (ret) {
-   dev_err(>dev,
+   if (ret != -EPROBE_DEFER)
+   dev_err(>dev,
"devm_snd_soc_register_card(%s) failed: %d\n",
card->name, ret);
-   return ret;
+   else
+   dev_dbg(>dev,
+   "devm_snd_soc_register_card(%s) probe deferred: 
%d\n",
+   card->name, ret);
}
-   return 0;
+
+   return ret;
 }
 
 static const struct acpi_device_id acp3x_audio_acpi_match[] = {
-- 
2.20.1



[PATCH] ASoC: AMD: Clean kernel log from deferred probe error messages

2020-08-26 Thread Akshu Agrawal
While the driver waits for DAIs to be probed and retries probing,
avoid printing error messages.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp3x-rt5682-max9836.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c 
b/sound/soc/amd/acp3x-rt5682-max9836.c
index 406526e79af3..67f80ba51de0 100644
--- a/sound/soc/amd/acp3x-rt5682-max9836.c
+++ b/sound/soc/amd/acp3x-rt5682-max9836.c
@@ -471,13 +471,11 @@ static int acp3x_probe(struct platform_device *pdev)
}
 
ret = devm_snd_soc_register_card(>dev, card);
-   if (ret) {
+   if (ret && ret != -EPROBE_DEFER)
dev_err(>dev,
"devm_snd_soc_register_card(%s) failed: %d\n",
card->name, ret);
-   return ret;
-   }
-   return 0;
+   return ret;
 }
 
 static const struct acpi_device_id acp3x_audio_acpi_match[] = {
-- 
2.20.1



[3/4] ACPI: APD: Add a fmw property is_raven

2020-07-31 Thread Akshu Agrawal
Since there is slight difference in AMD RV based soc in misc
clk architecture. The fmw property will help in differentiating
the SoCs.

Signed-off-by: Akshu Agrawal 
---
 drivers/acpi/acpi_apd.c   | 4 
 include/linux/platform_data/clk-fch.h | 1 +
 2 files changed, 5 insertions(+)

diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index 2d99e46add1a..d879ba28826c 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -82,6 +82,7 @@ static int misc_check_res(struct acpi_resource *ares, void 
*data)
 static int fch_misc_setup(struct apd_private_data *pdata)
 {
struct acpi_device *adev = pdata->adev;
+   const union acpi_object *obj;
struct platform_device *clkdev;
struct fch_clk_data *clk_data;
struct resource_entry *rentry;
@@ -98,6 +99,9 @@ static int fch_misc_setup(struct apd_private_data *pdata)
if (ret < 0)
return -ENOENT;
 
+   acpi_dev_get_property(adev, "is-rv", ACPI_TYPE_INTEGER, );
+   clk_data->is_rv = obj->integer.value;
+
list_for_each_entry(rentry, _list, node) {
clk_data->base = devm_ioremap(>dev, rentry->res->start,
  resource_size(rentry->res));
diff --git a/include/linux/platform_data/clk-fch.h 
b/include/linux/platform_data/clk-fch.h
index 850ca776156d..b9f682459f08 100644
--- a/include/linux/platform_data/clk-fch.h
+++ b/include/linux/platform_data/clk-fch.h
@@ -12,6 +12,7 @@
 
 struct fch_clk_data {
void __iomem *base;
+   u32 is_rv;
 };
 
 #endif /* __CLK_FCH_H */
-- 
2.20.1



[v3 4/4] clk: x86: Support RV architecture

2020-07-31 Thread Akshu Agrawal
There is minor difference between previous family of SoC and
the current one. Which is the there is only 48Mh fixed clk.
There is no mux and no option to select another freq as there in previous.

Signed-off-by: Akshu Agrawal 
Reviewed-by: Stephen Boyd 
---
v2: Consolidated the loops in remove.
v3: Removed negation in condition to make it simple

 drivers/clk/x86/clk-fch.c | 53 ---
 1 file changed, 38 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/x86/clk-fch.c b/drivers/clk/x86/clk-fch.c
index b252f0cf0628..8f7c5142b0f0 100644
--- a/drivers/clk/x86/clk-fch.c
+++ b/drivers/clk/x86/clk-fch.c
@@ -26,6 +26,10 @@
 #define ST_CLK_GATE3
 #define ST_MAX_CLKS4
 
+#define RV_CLK_48M 0
+#define RV_CLK_GATE1
+#define RV_MAX_CLKS2
+
 static const char * const clk_oscout1_parents[] = { "clk48MHz", "clk25MHz" };
 static struct clk_hw *hws[ST_MAX_CLKS];
 
@@ -37,33 +41,52 @@ static int fch_clk_probe(struct platform_device *pdev)
if (!fch_data || !fch_data->base)
return -EINVAL;
 
-   hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz", NULL, 0,
-4800);
-   hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz", NULL, 0,
-2500);
+   if (!fch_data->is_rv) {
+   hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
+   NULL, 0, 4800);
+   hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz",
+   NULL, 0, 2500);
+
+   hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
+   clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
+   0, fch_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0,
+   NULL);
 
-   hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
-   clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
-   0, fch_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
+   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
 
-   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
+   hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1",
+   "oscout1_mux", 0, fch_data->base + MISCCLKCNTL1,
+   OSCCLKENB, CLK_GATE_SET_TO_DISABLE, NULL);
 
-   hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", "oscout1_mux",
-   0, fch_data->base + MISCCLKCNTL1, OSCCLKENB,
-   CLK_GATE_SET_TO_DISABLE, NULL);
+   devm_clk_hw_register_clkdev(>dev, hws[ST_CLK_GATE],
+   "oscout1", NULL);
+   } else {
+   hws[RV_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
+   NULL, 0, 4800);
 
-   devm_clk_hw_register_clkdev(>dev, hws[ST_CLK_GATE], "oscout1",
-   NULL);
+   hws[RV_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1",
+   "clk48MHz", 0, fch_data->base + MISCCLKCNTL1,
+   OSCCLKENB, CLK_GATE_SET_TO_DISABLE, NULL);
+
+   devm_clk_hw_register_clkdev(>dev, hws[RV_CLK_GATE],
+   "oscout1", NULL);
+   }
 
return 0;
 }
 
 static int fch_clk_remove(struct platform_device *pdev)
 {
-   int i;
+   int i, clks;
+   struct fch_clk_data *fch_data;
 
-   for (i = 0; i < ST_MAX_CLKS; i++)
+   fch_data = dev_get_platdata(>dev);
+
+   clks = fch_data->is_rv ? RV_MAX_CLKS : ST_MAX_CLKS;
+
+   for (i = 0; i < clks; i++)
clk_hw_unregister(hws[i]);
+
return 0;
 }
 
-- 
2.20.1



[v2 2/4] clk: x86: Change name from ST to FCH

2020-07-31 Thread Akshu Agrawal
AMD SoC general pupose clk is present in new platforms with
minor differences. We can reuse the same clk driver for other
platforms. Hence, changing name from ST(SoC) to FCH(IP)

Signed-off-by: Akshu Agrawal 
Reviewed-by: Stephen Boyd 
---
v2: Moved some changes to acp:apd patch so that individual patches
compile

 drivers/clk/x86/Makefile|  2 +-
 drivers/clk/x86/{clk-st.c => clk-fch.c} | 24 
 2 files changed, 13 insertions(+), 13 deletions(-)
 rename drivers/clk/x86/{clk-st.c => clk-fch.c} (75%)

diff --git a/drivers/clk/x86/Makefile b/drivers/clk/x86/Makefile
index 7c774ea7ddeb..18564efdc651 100644
--- a/drivers/clk/x86/Makefile
+++ b/drivers/clk/x86/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_PMC_ATOM) += clk-pmc-atom.o
-obj-$(CONFIG_X86_AMD_PLATFORM_DEVICE)  += clk-st.o
+obj-$(CONFIG_X86_AMD_PLATFORM_DEVICE)  += clk-fch.o
 clk-x86-lpss-objs  := clk-lpt.o
 obj-$(CONFIG_X86_INTEL_LPSS)   += clk-x86-lpss.o
 obj-$(CONFIG_CLK_LGM_CGU)  += clk-cgu.o clk-cgu-pll.o clk-lgm.o
diff --git a/drivers/clk/x86/clk-st.c b/drivers/clk/x86/clk-fch.c
similarity index 75%
rename from drivers/clk/x86/clk-st.c
rename to drivers/clk/x86/clk-fch.c
index c2438874d9f2..b252f0cf0628 100644
--- a/drivers/clk/x86/clk-st.c
+++ b/drivers/clk/x86/clk-fch.c
@@ -29,12 +29,12 @@
 static const char * const clk_oscout1_parents[] = { "clk48MHz", "clk25MHz" };
 static struct clk_hw *hws[ST_MAX_CLKS];
 
-static int st_clk_probe(struct platform_device *pdev)
+static int fch_clk_probe(struct platform_device *pdev)
 {
-   struct fch_clk_data *st_data;
+   struct fch_clk_data *fch_data;
 
-   st_data = dev_get_platdata(>dev);
-   if (!st_data || !st_data->base)
+   fch_data = dev_get_platdata(>dev);
+   if (!fch_data || !fch_data->base)
return -EINVAL;
 
hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz", NULL, 0,
@@ -44,12 +44,12 @@ static int st_clk_probe(struct platform_device *pdev)
 
hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
-   0, st_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
+   0, fch_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
 
clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
 
hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", "oscout1_mux",
-   0, st_data->base + MISCCLKCNTL1, OSCCLKENB,
+   0, fch_data->base + MISCCLKCNTL1, OSCCLKENB,
CLK_GATE_SET_TO_DISABLE, NULL);
 
devm_clk_hw_register_clkdev(>dev, hws[ST_CLK_GATE], "oscout1",
@@ -58,7 +58,7 @@ static int st_clk_probe(struct platform_device *pdev)
return 0;
 }
 
-static int st_clk_remove(struct platform_device *pdev)
+static int fch_clk_remove(struct platform_device *pdev)
 {
int i;
 
@@ -67,12 +67,12 @@ static int st_clk_remove(struct platform_device *pdev)
return 0;
 }
 
-static struct platform_driver st_clk_driver = {
+static struct platform_driver fch_clk_driver = {
.driver = {
-   .name = "clk-st",
+   .name = "clk-fch",
.suppress_bind_attrs = true,
},
-   .probe = st_clk_probe,
-   .remove = st_clk_remove,
+   .probe = fch_clk_probe,
+   .remove = fch_clk_remove,
 };
-builtin_platform_driver(st_clk_driver);
+builtin_platform_driver(fch_clk_driver);
-- 
2.20.1



[0/4] Extend AMD SoC general purpose clk for all versions

2020-07-31 Thread Akshu Agrawal
Hi,

This series of patch does the following:
1. Changes the name of the AMD SoC general purpose clk
from ST(a version of SoC) to FCH (name of the IP).
2. Then make the drivers support both older and newer versions of
SoC.

Thanks,
Akshu

Akshu Agrawal (4):
  ACPI: APD: Change name from ST to FCH
  clk: x86: Change name from ST to FCH
  ACPI: APD: Add a fmw property is_raven
  clk: x86: Support RV architecture

 drivers/acpi/acpi_apd.c   |  18 ++--
 drivers/clk/x86/Makefile  |   2 +-
 drivers/clk/x86/clk-fch.c | 101 ++
 drivers/clk/x86/clk-st.c  |  78 --
 .../platform_data/{clk-st.h => clk-fch.h} |  11 +-
 5 files changed, 119 insertions(+), 91 deletions(-)
 create mode 100644 drivers/clk/x86/clk-fch.c
 delete mode 100644 drivers/clk/x86/clk-st.c
 rename include/linux/platform_data/{clk-st.h => clk-fch.h} (51%)

-- 
2.20.1



[v2 1/4] ACPI: APD: Change name from ST to FCH

2020-07-31 Thread Akshu Agrawal
AMD SoC general pupose clk is present in new platforms with
same MMIO mappings. We can reuse the same clk handler support
for other platforms. Hence, changing name from ST(SoC) to FCH(IP)

Signed-off-by: Akshu Agrawal 
Acked-by: Stephen Boyd 
---
v2: pulled in clk changes so that patch compiles individually

 drivers/acpi/acpi_apd.c| 14 +++---
 drivers/clk/x86/clk-st.c   |  4 ++--
 .../linux/platform_data/{clk-st.h => clk-fch.h}| 10 +-
 3 files changed, 14 insertions(+), 14 deletions(-)
 rename include/linux/platform_data/{clk-st.h => clk-fch.h} (53%)

diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index ba2612e9a0eb..2d99e46add1a 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -8,7 +8,7 @@
  */
 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -79,11 +79,11 @@ static int misc_check_res(struct acpi_resource *ares, void 
*data)
return !acpi_dev_resource_memory(ares, );
 }
 
-static int st_misc_setup(struct apd_private_data *pdata)
+static int fch_misc_setup(struct apd_private_data *pdata)
 {
struct acpi_device *adev = pdata->adev;
struct platform_device *clkdev;
-   struct st_clk_data *clk_data;
+   struct fch_clk_data *clk_data;
struct resource_entry *rentry;
struct list_head resource_list;
int ret;
@@ -106,7 +106,7 @@ static int st_misc_setup(struct apd_private_data *pdata)
 
acpi_dev_free_resource_list(_list);
 
-   clkdev = platform_device_register_data(>dev, "clk-st",
+   clkdev = platform_device_register_data(>dev, "clk-fch",
   PLATFORM_DEVID_NONE, clk_data,
   sizeof(*clk_data));
return PTR_ERR_OR_ZERO(clkdev);
@@ -135,8 +135,8 @@ static const struct apd_device_desc cz_uart_desc = {
.properties = uart_properties,
 };
 
-static const struct apd_device_desc st_misc_desc = {
-   .setup = st_misc_setup,
+static const struct apd_device_desc fch_misc_desc = {
+   .setup = fch_misc_setup,
 };
 #endif
 
@@ -239,7 +239,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
{ "AMD0020", APD_ADDR(cz_uart_desc) },
{ "AMDI0020", APD_ADDR(cz_uart_desc) },
{ "AMD0030", },
-   { "AMD0040", APD_ADDR(st_misc_desc)},
+   { "AMD0040", APD_ADDR(fch_misc_desc)},
 #endif
 #ifdef CONFIG_ARM64
{ "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
diff --git a/drivers/clk/x86/clk-st.c b/drivers/clk/x86/clk-st.c
index 25d4b97aff9b..c2438874d9f2 100644
--- a/drivers/clk/x86/clk-st.c
+++ b/drivers/clk/x86/clk-st.c
@@ -8,7 +8,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 
 /* Clock Driving Strength 2 register */
@@ -31,7 +31,7 @@ static struct clk_hw *hws[ST_MAX_CLKS];
 
 static int st_clk_probe(struct platform_device *pdev)
 {
-   struct st_clk_data *st_data;
+   struct fch_clk_data *st_data;
 
st_data = dev_get_platdata(>dev);
if (!st_data || !st_data->base)
diff --git a/include/linux/platform_data/clk-st.h 
b/include/linux/platform_data/clk-fch.h
similarity index 53%
rename from include/linux/platform_data/clk-st.h
rename to include/linux/platform_data/clk-fch.h
index 7cdb6a402b35..850ca776156d 100644
--- a/include/linux/platform_data/clk-st.h
+++ b/include/linux/platform_data/clk-fch.h
@@ -1,17 +1,17 @@
 /* SPDX-License-Identifier: MIT */
 /*
- * clock framework for AMD Stoney based clock
+ * clock framework for AMD misc clocks
  *
  * Copyright 2018 Advanced Micro Devices, Inc.
  */
 
-#ifndef __CLK_ST_H
-#define __CLK_ST_H
+#ifndef __CLK_FCH_H
+#define __CLK_FCH_H
 
 #include 
 
-struct st_clk_data {
+struct fch_clk_data {
void __iomem *base;
 };
 
-#endif /* __CLK_ST_H */
+#endif /* __CLK_FCH_H */
-- 
2.20.1



[3/4] ACPI: APD: Add a fmw property is_raven

2020-07-28 Thread Akshu Agrawal
Since there is slight difference in AMD RV based soc in misc
clk architecture. The fmw property will help in differentiating
the SoCs.

Signed-off-by: Akshu Agrawal 
---
 drivers/acpi/acpi_apd.c   | 4 
 include/linux/platform_data/clk-fch.h | 1 +
 2 files changed, 5 insertions(+)

diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index 2d99e46add1a..d879ba28826c 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -82,6 +82,7 @@ static int misc_check_res(struct acpi_resource *ares, void 
*data)
 static int fch_misc_setup(struct apd_private_data *pdata)
 {
struct acpi_device *adev = pdata->adev;
+   const union acpi_object *obj;
struct platform_device *clkdev;
struct fch_clk_data *clk_data;
struct resource_entry *rentry;
@@ -98,6 +99,9 @@ static int fch_misc_setup(struct apd_private_data *pdata)
if (ret < 0)
return -ENOENT;
 
+   acpi_dev_get_property(adev, "is-rv", ACPI_TYPE_INTEGER, );
+   clk_data->is_rv = obj->integer.value;
+
list_for_each_entry(rentry, _list, node) {
clk_data->base = devm_ioremap(>dev, rentry->res->start,
  resource_size(rentry->res));
diff --git a/include/linux/platform_data/clk-fch.h 
b/include/linux/platform_data/clk-fch.h
index 850ca776156d..b9f682459f08 100644
--- a/include/linux/platform_data/clk-fch.h
+++ b/include/linux/platform_data/clk-fch.h
@@ -12,6 +12,7 @@
 
 struct fch_clk_data {
void __iomem *base;
+   u32 is_rv;
 };
 
 #endif /* __CLK_FCH_H */
-- 
2.20.1



[v3 4/4] clk: x86: Support RV architecture

2020-07-28 Thread Akshu Agrawal
There is minor difference between previous family of SoC and
the current one. Which is the there is only 48Mh fixed clk.
There is no mux and no option to select another freq as there in previous.

Signed-off-by: Akshu Agrawal 
---
v2: Consolidated the loops in remove.
v3: Removed negation in condition to make it simple

 drivers/clk/x86/clk-fch.c | 53 ---
 1 file changed, 38 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/x86/clk-fch.c b/drivers/clk/x86/clk-fch.c
index b252f0cf0628..8f7c5142b0f0 100644
--- a/drivers/clk/x86/clk-fch.c
+++ b/drivers/clk/x86/clk-fch.c
@@ -26,6 +26,10 @@
 #define ST_CLK_GATE3
 #define ST_MAX_CLKS4
 
+#define RV_CLK_48M 0
+#define RV_CLK_GATE1
+#define RV_MAX_CLKS2
+
 static const char * const clk_oscout1_parents[] = { "clk48MHz", "clk25MHz" };
 static struct clk_hw *hws[ST_MAX_CLKS];
 
@@ -37,33 +41,52 @@ static int fch_clk_probe(struct platform_device *pdev)
if (!fch_data || !fch_data->base)
return -EINVAL;
 
-   hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz", NULL, 0,
-4800);
-   hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz", NULL, 0,
-2500);
+   if (!fch_data->is_rv) {
+   hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
+   NULL, 0, 4800);
+   hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz",
+   NULL, 0, 2500);
+
+   hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
+   clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
+   0, fch_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0,
+   NULL);
 
-   hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
-   clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
-   0, fch_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
+   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
 
-   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
+   hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1",
+   "oscout1_mux", 0, fch_data->base + MISCCLKCNTL1,
+   OSCCLKENB, CLK_GATE_SET_TO_DISABLE, NULL);
 
-   hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", "oscout1_mux",
-   0, fch_data->base + MISCCLKCNTL1, OSCCLKENB,
-   CLK_GATE_SET_TO_DISABLE, NULL);
+   devm_clk_hw_register_clkdev(>dev, hws[ST_CLK_GATE],
+   "oscout1", NULL);
+   } else {
+   hws[RV_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
+   NULL, 0, 4800);
 
-   devm_clk_hw_register_clkdev(>dev, hws[ST_CLK_GATE], "oscout1",
-   NULL);
+   hws[RV_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1",
+   "clk48MHz", 0, fch_data->base + MISCCLKCNTL1,
+   OSCCLKENB, CLK_GATE_SET_TO_DISABLE, NULL);
+
+   devm_clk_hw_register_clkdev(>dev, hws[RV_CLK_GATE],
+   "oscout1", NULL);
+   }
 
return 0;
 }
 
 static int fch_clk_remove(struct platform_device *pdev)
 {
-   int i;
+   int i, clks;
+   struct fch_clk_data *fch_data;
 
-   for (i = 0; i < ST_MAX_CLKS; i++)
+   fch_data = dev_get_platdata(>dev);
+
+   clks = fch_data->is_rv ? RV_MAX_CLKS : ST_MAX_CLKS;
+
+   for (i = 0; i < clks; i++)
clk_hw_unregister(hws[i]);
+
return 0;
 }
 
-- 
2.20.1



[3/4] ACPI: APD: Add a fmw property is_raven

2020-07-28 Thread Akshu Agrawal
Since there is slight difference in AMD RV based soc in misc
clk architecture. The fmw property will help in differentiating
the SoCs.

Signed-off-by: Akshu Agrawal 
---
 drivers/acpi/acpi_apd.c   | 4 
 include/linux/platform_data/clk-fch.h | 1 +
 2 files changed, 5 insertions(+)

diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index 2d99e46add1a..d879ba28826c 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -82,6 +82,7 @@ static int misc_check_res(struct acpi_resource *ares, void 
*data)
 static int fch_misc_setup(struct apd_private_data *pdata)
 {
struct acpi_device *adev = pdata->adev;
+   const union acpi_object *obj;
struct platform_device *clkdev;
struct fch_clk_data *clk_data;
struct resource_entry *rentry;
@@ -98,6 +99,9 @@ static int fch_misc_setup(struct apd_private_data *pdata)
if (ret < 0)
return -ENOENT;
 
+   acpi_dev_get_property(adev, "is-rv", ACPI_TYPE_INTEGER, );
+   clk_data->is_rv = obj->integer.value;
+
list_for_each_entry(rentry, _list, node) {
clk_data->base = devm_ioremap(>dev, rentry->res->start,
  resource_size(rentry->res));
diff --git a/include/linux/platform_data/clk-fch.h 
b/include/linux/platform_data/clk-fch.h
index 850ca776156d..b9f682459f08 100644
--- a/include/linux/platform_data/clk-fch.h
+++ b/include/linux/platform_data/clk-fch.h
@@ -12,6 +12,7 @@
 
 struct fch_clk_data {
void __iomem *base;
+   u32 is_rv;
 };
 
 #endif /* __CLK_FCH_H */
-- 
2.20.1



[v2 2/4] clk: x86: Change name from ST to FCH

2020-07-28 Thread Akshu Agrawal
AMD SoC general pupose clk is present in new platforms with
minor differences. We can reuse the same clk driver for other
platforms. Hence, changing name from ST(SoC) to FCH(IP)

Signed-off-by: Akshu Agrawal 
---
v2: Moved some changes to acp:apd patch so that individual patches
compile

 drivers/clk/x86/Makefile|  2 +-
 drivers/clk/x86/{clk-st.c => clk-fch.c} | 24 
 2 files changed, 13 insertions(+), 13 deletions(-)
 rename drivers/clk/x86/{clk-st.c => clk-fch.c} (75%)

diff --git a/drivers/clk/x86/Makefile b/drivers/clk/x86/Makefile
index 7c774ea7ddeb..18564efdc651 100644
--- a/drivers/clk/x86/Makefile
+++ b/drivers/clk/x86/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_PMC_ATOM) += clk-pmc-atom.o
-obj-$(CONFIG_X86_AMD_PLATFORM_DEVICE)  += clk-st.o
+obj-$(CONFIG_X86_AMD_PLATFORM_DEVICE)  += clk-fch.o
 clk-x86-lpss-objs  := clk-lpt.o
 obj-$(CONFIG_X86_INTEL_LPSS)   += clk-x86-lpss.o
 obj-$(CONFIG_CLK_LGM_CGU)  += clk-cgu.o clk-cgu-pll.o clk-lgm.o
diff --git a/drivers/clk/x86/clk-st.c b/drivers/clk/x86/clk-fch.c
similarity index 75%
rename from drivers/clk/x86/clk-st.c
rename to drivers/clk/x86/clk-fch.c
index c2438874d9f2..b252f0cf0628 100644
--- a/drivers/clk/x86/clk-st.c
+++ b/drivers/clk/x86/clk-fch.c
@@ -29,12 +29,12 @@
 static const char * const clk_oscout1_parents[] = { "clk48MHz", "clk25MHz" };
 static struct clk_hw *hws[ST_MAX_CLKS];
 
-static int st_clk_probe(struct platform_device *pdev)
+static int fch_clk_probe(struct platform_device *pdev)
 {
-   struct fch_clk_data *st_data;
+   struct fch_clk_data *fch_data;
 
-   st_data = dev_get_platdata(>dev);
-   if (!st_data || !st_data->base)
+   fch_data = dev_get_platdata(>dev);
+   if (!fch_data || !fch_data->base)
return -EINVAL;
 
hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz", NULL, 0,
@@ -44,12 +44,12 @@ static int st_clk_probe(struct platform_device *pdev)
 
hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
-   0, st_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
+   0, fch_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
 
clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
 
hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", "oscout1_mux",
-   0, st_data->base + MISCCLKCNTL1, OSCCLKENB,
+   0, fch_data->base + MISCCLKCNTL1, OSCCLKENB,
CLK_GATE_SET_TO_DISABLE, NULL);
 
devm_clk_hw_register_clkdev(>dev, hws[ST_CLK_GATE], "oscout1",
@@ -58,7 +58,7 @@ static int st_clk_probe(struct platform_device *pdev)
return 0;
 }
 
-static int st_clk_remove(struct platform_device *pdev)
+static int fch_clk_remove(struct platform_device *pdev)
 {
int i;
 
@@ -67,12 +67,12 @@ static int st_clk_remove(struct platform_device *pdev)
return 0;
 }
 
-static struct platform_driver st_clk_driver = {
+static struct platform_driver fch_clk_driver = {
.driver = {
-   .name = "clk-st",
+   .name = "clk-fch",
.suppress_bind_attrs = true,
},
-   .probe = st_clk_probe,
-   .remove = st_clk_remove,
+   .probe = fch_clk_probe,
+   .remove = fch_clk_remove,
 };
-builtin_platform_driver(st_clk_driver);
+builtin_platform_driver(fch_clk_driver);
-- 
2.20.1



[v2 1/4] ACPI: APD: Change name from ST to FCH

2020-07-28 Thread Akshu Agrawal
AMD SoC general pupose clk is present in new platforms with
same MMIO mappings. We can reuse the same clk handler support
for other platforms. Hence, changing name from ST(SoC) to FCH(IP)

Signed-off-by: Akshu Agrawal 
---
v2: pulled in clk changes so that patch compiles individually

 drivers/acpi/acpi_apd.c| 14 +++---
 drivers/clk/x86/clk-st.c   |  4 ++--
 .../linux/platform_data/{clk-st.h => clk-fch.h}| 10 +-
 3 files changed, 14 insertions(+), 14 deletions(-)
 rename include/linux/platform_data/{clk-st.h => clk-fch.h} (53%)

diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index ba2612e9a0eb..2d99e46add1a 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -8,7 +8,7 @@
  */
 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -79,11 +79,11 @@ static int misc_check_res(struct acpi_resource *ares, void 
*data)
return !acpi_dev_resource_memory(ares, );
 }
 
-static int st_misc_setup(struct apd_private_data *pdata)
+static int fch_misc_setup(struct apd_private_data *pdata)
 {
struct acpi_device *adev = pdata->adev;
struct platform_device *clkdev;
-   struct st_clk_data *clk_data;
+   struct fch_clk_data *clk_data;
struct resource_entry *rentry;
struct list_head resource_list;
int ret;
@@ -106,7 +106,7 @@ static int st_misc_setup(struct apd_private_data *pdata)
 
acpi_dev_free_resource_list(_list);
 
-   clkdev = platform_device_register_data(>dev, "clk-st",
+   clkdev = platform_device_register_data(>dev, "clk-fch",
   PLATFORM_DEVID_NONE, clk_data,
   sizeof(*clk_data));
return PTR_ERR_OR_ZERO(clkdev);
@@ -135,8 +135,8 @@ static const struct apd_device_desc cz_uart_desc = {
.properties = uart_properties,
 };
 
-static const struct apd_device_desc st_misc_desc = {
-   .setup = st_misc_setup,
+static const struct apd_device_desc fch_misc_desc = {
+   .setup = fch_misc_setup,
 };
 #endif
 
@@ -239,7 +239,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
{ "AMD0020", APD_ADDR(cz_uart_desc) },
{ "AMDI0020", APD_ADDR(cz_uart_desc) },
{ "AMD0030", },
-   { "AMD0040", APD_ADDR(st_misc_desc)},
+   { "AMD0040", APD_ADDR(fch_misc_desc)},
 #endif
 #ifdef CONFIG_ARM64
{ "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
diff --git a/drivers/clk/x86/clk-st.c b/drivers/clk/x86/clk-st.c
index 25d4b97aff9b..c2438874d9f2 100644
--- a/drivers/clk/x86/clk-st.c
+++ b/drivers/clk/x86/clk-st.c
@@ -8,7 +8,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 
 /* Clock Driving Strength 2 register */
@@ -31,7 +31,7 @@ static struct clk_hw *hws[ST_MAX_CLKS];
 
 static int st_clk_probe(struct platform_device *pdev)
 {
-   struct st_clk_data *st_data;
+   struct fch_clk_data *st_data;
 
st_data = dev_get_platdata(>dev);
if (!st_data || !st_data->base)
diff --git a/include/linux/platform_data/clk-st.h 
b/include/linux/platform_data/clk-fch.h
similarity index 53%
rename from include/linux/platform_data/clk-st.h
rename to include/linux/platform_data/clk-fch.h
index 7cdb6a402b35..850ca776156d 100644
--- a/include/linux/platform_data/clk-st.h
+++ b/include/linux/platform_data/clk-fch.h
@@ -1,17 +1,17 @@
 /* SPDX-License-Identifier: MIT */
 /*
- * clock framework for AMD Stoney based clock
+ * clock framework for AMD misc clocks
  *
  * Copyright 2018 Advanced Micro Devices, Inc.
  */
 
-#ifndef __CLK_ST_H
-#define __CLK_ST_H
+#ifndef __CLK_FCH_H
+#define __CLK_FCH_H
 
 #include 
 
-struct st_clk_data {
+struct fch_clk_data {
void __iomem *base;
 };
 
-#endif /* __CLK_ST_H */
+#endif /* __CLK_FCH_H */
-- 
2.20.1



[PATCH] ASoC: AMD: Restore PME_EN state at Power On

2020-07-24 Thread Akshu Agrawal
PME_EN state needs to restored to the value set by fmw.
For the devices which are not using I2S wake event which gets
enabled by PME_EN bit, keeping PME_EN enabled burns considerable amount
of power as it blocks low power state.
For the devices using I2S wake event, PME_EN gets enabled in fmw and the
state should be maintained after ACP Power On.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/raven/pci-acp3x.c | 21 +
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c
index ebf4388b6262..31b797c8bfe6 100644
--- a/sound/soc/amd/raven/pci-acp3x.c
+++ b/sound/soc/amd/raven/pci-acp3x.c
@@ -19,10 +19,12 @@ struct acp3x_dev_data {
bool acp3x_audio_mode;
struct resource *res;
struct platform_device *pdev[ACP3x_DEVS];
+   u32 pme_en;
 };
 
-static int acp3x_power_on(void __iomem *acp3x_base)
+static int acp3x_power_on(struct acp3x_dev_data *adata)
 {
+   void __iomem *acp3x_base = adata->acp3x_base;
u32 val;
int timeout;
 
@@ -39,10 +41,10 @@ static int acp3x_power_on(void __iomem *acp3x_base)
while (++timeout < 500) {
val = rv_readl(acp3x_base + mmACP_PGFSM_STATUS);
if (!val) {
-   /* Set PME_EN as after ACP power On,
-* PME_EN gets cleared
+   /* ACP power On clears PME_EN.
+* Restore the value to its prior state
 */
-   rv_writel(0x1, acp3x_base + mmACP_PME_EN);
+   rv_writel(adata->pme_en, acp3x_base + mmACP_PME_EN);
return 0;
}
udelay(1);
@@ -74,12 +76,13 @@ static int acp3x_reset(void __iomem *acp3x_base)
return -ETIMEDOUT;
 }
 
-static int acp3x_init(void __iomem *acp3x_base)
+static int acp3x_init(struct acp3x_dev_data *adata)
 {
+   void __iomem *acp3x_base = adata->acp3x_base;
int ret;
 
/* power on */
-   ret = acp3x_power_on(acp3x_base);
+   ret = acp3x_power_on(adata);
if (ret) {
pr_err("ACP3x power on failed\n");
return ret;
@@ -151,7 +154,9 @@ static int snd_acp3x_probe(struct pci_dev *pci,
}
pci_set_master(pci);
pci_set_drvdata(pci, adata);
-   ret = acp3x_init(adata->acp3x_base);
+   /* Save ACP_PME_EN state */
+   adata->pme_en = rv_readl(adata->acp3x_base + mmACP_PME_EN);
+   ret = acp3x_init(adata);
if (ret)
goto disable_msi;
 
@@ -274,7 +279,7 @@ static int snd_acp3x_resume(struct device *dev)
struct acp3x_dev_data *adata;
 
adata = dev_get_drvdata(dev);
-   ret = acp3x_init(adata->acp3x_base);
+   ret = acp3x_init(adata);
if (ret) {
dev_err(dev, "ACP init failed\n");
return ret;
-- 
2.20.1



[PATCH 3/4] ACPI: APD: Add a fmw property is_raven

2020-07-19 Thread Akshu Agrawal
Since there is slight difference in AMD RV based soc in misc
clk architecture. The fmw property will help in differentiating
the SoCs.

Signed-off-by: Akshu Agrawal 
---
 drivers/acpi/acpi_apd.c   | 4 
 include/linux/platform_data/clk-fch.h | 1 +
 2 files changed, 5 insertions(+)

diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index 2d99e46add1a..d879ba28826c 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -82,6 +82,7 @@ static int misc_check_res(struct acpi_resource *ares, void 
*data)
 static int fch_misc_setup(struct apd_private_data *pdata)
 {
struct acpi_device *adev = pdata->adev;
+   const union acpi_object *obj;
struct platform_device *clkdev;
struct fch_clk_data *clk_data;
struct resource_entry *rentry;
@@ -98,6 +99,9 @@ static int fch_misc_setup(struct apd_private_data *pdata)
if (ret < 0)
return -ENOENT;
 
+   acpi_dev_get_property(adev, "is-rv", ACPI_TYPE_INTEGER, );
+   clk_data->is_rv = obj->integer.value;
+
list_for_each_entry(rentry, _list, node) {
clk_data->base = devm_ioremap(>dev, rentry->res->start,
  resource_size(rentry->res));
diff --git a/include/linux/platform_data/clk-fch.h 
b/include/linux/platform_data/clk-fch.h
index 850ca776156d..b9f682459f08 100644
--- a/include/linux/platform_data/clk-fch.h
+++ b/include/linux/platform_data/clk-fch.h
@@ -12,6 +12,7 @@
 
 struct fch_clk_data {
void __iomem *base;
+   u32 is_rv;
 };
 
 #endif /* __CLK_FCH_H */
-- 
2.20.1



[PATCH 1/4] ACPI: APD: Change name from ST to FCH

2020-07-19 Thread Akshu Agrawal
AMD SoC general pupose clk is present in new platforms with
same MMIO mappings. We can reuse the same clk handler support
for other platforms. Hence, changing name from ST(SoC) to FCH(IP)

Signed-off-by: Akshu Agrawal 
---
 drivers/acpi/acpi_apd.c| 14 +++---
 .../linux/platform_data/{clk-st.h => clk-fch.h}| 10 +-
 2 files changed, 12 insertions(+), 12 deletions(-)
 rename include/linux/platform_data/{clk-st.h => clk-fch.h} (53%)

diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index ba2612e9a0eb..2d99e46add1a 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -8,7 +8,7 @@
  */
 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -79,11 +79,11 @@ static int misc_check_res(struct acpi_resource *ares, void 
*data)
return !acpi_dev_resource_memory(ares, );
 }
 
-static int st_misc_setup(struct apd_private_data *pdata)
+static int fch_misc_setup(struct apd_private_data *pdata)
 {
struct acpi_device *adev = pdata->adev;
struct platform_device *clkdev;
-   struct st_clk_data *clk_data;
+   struct fch_clk_data *clk_data;
struct resource_entry *rentry;
struct list_head resource_list;
int ret;
@@ -106,7 +106,7 @@ static int st_misc_setup(struct apd_private_data *pdata)
 
acpi_dev_free_resource_list(_list);
 
-   clkdev = platform_device_register_data(>dev, "clk-st",
+   clkdev = platform_device_register_data(>dev, "clk-fch",
   PLATFORM_DEVID_NONE, clk_data,
   sizeof(*clk_data));
return PTR_ERR_OR_ZERO(clkdev);
@@ -135,8 +135,8 @@ static const struct apd_device_desc cz_uart_desc = {
.properties = uart_properties,
 };
 
-static const struct apd_device_desc st_misc_desc = {
-   .setup = st_misc_setup,
+static const struct apd_device_desc fch_misc_desc = {
+   .setup = fch_misc_setup,
 };
 #endif
 
@@ -239,7 +239,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
{ "AMD0020", APD_ADDR(cz_uart_desc) },
{ "AMDI0020", APD_ADDR(cz_uart_desc) },
{ "AMD0030", },
-   { "AMD0040", APD_ADDR(st_misc_desc)},
+   { "AMD0040", APD_ADDR(fch_misc_desc)},
 #endif
 #ifdef CONFIG_ARM64
{ "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
diff --git a/include/linux/platform_data/clk-st.h 
b/include/linux/platform_data/clk-fch.h
similarity index 53%
rename from include/linux/platform_data/clk-st.h
rename to include/linux/platform_data/clk-fch.h
index 7cdb6a402b35..850ca776156d 100644
--- a/include/linux/platform_data/clk-st.h
+++ b/include/linux/platform_data/clk-fch.h
@@ -1,17 +1,17 @@
 /* SPDX-License-Identifier: MIT */
 /*
- * clock framework for AMD Stoney based clock
+ * clock framework for AMD misc clocks
  *
  * Copyright 2018 Advanced Micro Devices, Inc.
  */
 
-#ifndef __CLK_ST_H
-#define __CLK_ST_H
+#ifndef __CLK_FCH_H
+#define __CLK_FCH_H
 
 #include 
 
-struct st_clk_data {
+struct fch_clk_data {
void __iomem *base;
 };
 
-#endif /* __CLK_ST_H */
+#endif /* __CLK_FCH_H */
-- 
2.20.1



[v2 4/4] clk: x86: Support RV architecture

2020-07-19 Thread Akshu Agrawal
There is minor difference between previous family of SoC and
the current one. Which is the there is only 48Mh fixed clk.
There is no mux and no option to select another freq as there in previous.

Signed-off-by: Akshu Agrawal 
---
v2: Consolidated the loops in remove.

 drivers/clk/x86/clk-fch.c | 53 ---
 1 file changed, 38 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/x86/clk-fch.c b/drivers/clk/x86/clk-fch.c
index b252f0cf0628..d68bca7b213f 100644
--- a/drivers/clk/x86/clk-fch.c
+++ b/drivers/clk/x86/clk-fch.c
@@ -26,6 +26,10 @@
 #define ST_CLK_GATE3
 #define ST_MAX_CLKS4
 
+#define RV_CLK_48M 0
+#define RV_CLK_GATE1
+#define RV_MAX_CLKS2
+
 static const char * const clk_oscout1_parents[] = { "clk48MHz", "clk25MHz" };
 static struct clk_hw *hws[ST_MAX_CLKS];
 
@@ -37,33 +41,52 @@ static int fch_clk_probe(struct platform_device *pdev)
if (!fch_data || !fch_data->base)
return -EINVAL;
 
-   hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz", NULL, 0,
-4800);
-   hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz", NULL, 0,
-2500);
+   if (!fch_data->is_rv) {
+   hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
+   NULL, 0, 4800);
+   hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz",
+   NULL, 0, 2500);
+
+   hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
+   clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
+   0, fch_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0,
+   NULL);
 
-   hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
-   clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
-   0, fch_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
+   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
 
-   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
+   hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1",
+   "oscout1_mux", 0, fch_data->base + MISCCLKCNTL1,
+   OSCCLKENB, CLK_GATE_SET_TO_DISABLE, NULL);
 
-   hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", "oscout1_mux",
-   0, fch_data->base + MISCCLKCNTL1, OSCCLKENB,
-   CLK_GATE_SET_TO_DISABLE, NULL);
+   devm_clk_hw_register_clkdev(>dev, hws[ST_CLK_GATE],
+   "oscout1", NULL);
+   } else {
+   hws[RV_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
+   NULL, 0, 4800);
 
-   devm_clk_hw_register_clkdev(>dev, hws[ST_CLK_GATE], "oscout1",
-   NULL);
+   hws[RV_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1",
+   "clk48MHz", 0, fch_data->base + MISCCLKCNTL1,
+   OSCCLKENB, CLK_GATE_SET_TO_DISABLE, NULL);
+
+   devm_clk_hw_register_clkdev(>dev, hws[RV_CLK_GATE],
+   "oscout1", NULL);
+   }
 
return 0;
 }
 
 static int fch_clk_remove(struct platform_device *pdev)
 {
-   int i;
+   int i, clks;
+   struct fch_clk_data *fch_data;
 
-   for (i = 0; i < ST_MAX_CLKS; i++)
+   fch_data = dev_get_platdata(>dev);
+
+   clks = (!fch_data->is_rv) ? ST_MAX_CLKS : RV_MAX_CLKS;
+
+   for (i = 0; i < clks; i++)
clk_hw_unregister(hws[i]);
+
return 0;
 }
 
-- 
2.20.1



[PATCH 2/4] clk: x86: Change name from ST to FCH

2020-07-19 Thread Akshu Agrawal
AMD SoC general pupose clk is present in new platforms with
minor differences. We can reuse the same clk driver for other
platforms. Hence, changing name from ST(SoC) to FCH(IP)

Signed-off-by: Akshu Agrawal 
---
 drivers/clk/x86/Makefile|  2 +-
 drivers/clk/x86/{clk-st.c => clk-fch.c} | 26 -
 2 files changed, 14 insertions(+), 14 deletions(-)
 rename drivers/clk/x86/{clk-st.c => clk-fch.c} (73%)

diff --git a/drivers/clk/x86/Makefile b/drivers/clk/x86/Makefile
index 7c774ea7ddeb..18564efdc651 100644
--- a/drivers/clk/x86/Makefile
+++ b/drivers/clk/x86/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_PMC_ATOM) += clk-pmc-atom.o
-obj-$(CONFIG_X86_AMD_PLATFORM_DEVICE)  += clk-st.o
+obj-$(CONFIG_X86_AMD_PLATFORM_DEVICE)  += clk-fch.o
 clk-x86-lpss-objs  := clk-lpt.o
 obj-$(CONFIG_X86_INTEL_LPSS)   += clk-x86-lpss.o
 obj-$(CONFIG_CLK_LGM_CGU)  += clk-cgu.o clk-cgu-pll.o clk-lgm.o
diff --git a/drivers/clk/x86/clk-st.c b/drivers/clk/x86/clk-fch.c
similarity index 73%
rename from drivers/clk/x86/clk-st.c
rename to drivers/clk/x86/clk-fch.c
index 25d4b97aff9b..b252f0cf0628 100644
--- a/drivers/clk/x86/clk-st.c
+++ b/drivers/clk/x86/clk-fch.c
@@ -8,7 +8,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 
 /* Clock Driving Strength 2 register */
@@ -29,12 +29,12 @@
 static const char * const clk_oscout1_parents[] = { "clk48MHz", "clk25MHz" };
 static struct clk_hw *hws[ST_MAX_CLKS];
 
-static int st_clk_probe(struct platform_device *pdev)
+static int fch_clk_probe(struct platform_device *pdev)
 {
-   struct st_clk_data *st_data;
+   struct fch_clk_data *fch_data;
 
-   st_data = dev_get_platdata(>dev);
-   if (!st_data || !st_data->base)
+   fch_data = dev_get_platdata(>dev);
+   if (!fch_data || !fch_data->base)
return -EINVAL;
 
hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz", NULL, 0,
@@ -44,12 +44,12 @@ static int st_clk_probe(struct platform_device *pdev)
 
hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
-   0, st_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
+   0, fch_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
 
clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
 
hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", "oscout1_mux",
-   0, st_data->base + MISCCLKCNTL1, OSCCLKENB,
+   0, fch_data->base + MISCCLKCNTL1, OSCCLKENB,
CLK_GATE_SET_TO_DISABLE, NULL);
 
devm_clk_hw_register_clkdev(>dev, hws[ST_CLK_GATE], "oscout1",
@@ -58,7 +58,7 @@ static int st_clk_probe(struct platform_device *pdev)
return 0;
 }
 
-static int st_clk_remove(struct platform_device *pdev)
+static int fch_clk_remove(struct platform_device *pdev)
 {
int i;
 
@@ -67,12 +67,12 @@ static int st_clk_remove(struct platform_device *pdev)
return 0;
 }
 
-static struct platform_driver st_clk_driver = {
+static struct platform_driver fch_clk_driver = {
.driver = {
-   .name = "clk-st",
+   .name = "clk-fch",
.suppress_bind_attrs = true,
},
-   .probe = st_clk_probe,
-   .remove = st_clk_remove,
+   .probe = fch_clk_probe,
+   .remove = fch_clk_remove,
 };
-builtin_platform_driver(st_clk_driver);
+builtin_platform_driver(fch_clk_driver);
-- 
2.20.1



[PATCH 4/5] clk: x86: Support RV architecture

2020-07-12 Thread Akshu Agrawal
There is minor difference between previous family of SoC and
the current one. Which is the there is only 48Mh fixed clk.
There is no mux and no option to select another freq as there in previous.

Signed-off-by: Akshu Agrawal 
---
 drivers/clk/x86/clk-fch.c | 55 ---
 1 file changed, 40 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/x86/clk-fch.c b/drivers/clk/x86/clk-fch.c
index b252f0cf0628..a8aac71a3b65 100644
--- a/drivers/clk/x86/clk-fch.c
+++ b/drivers/clk/x86/clk-fch.c
@@ -26,6 +26,10 @@
 #define ST_CLK_GATE3
 #define ST_MAX_CLKS4
 
+#define RV_CLK_48M 0
+#define RV_CLK_GATE1
+#define RV_MAX_CLKS2
+
 static const char * const clk_oscout1_parents[] = { "clk48MHz", "clk25MHz" };
 static struct clk_hw *hws[ST_MAX_CLKS];
 
@@ -37,23 +41,36 @@ static int fch_clk_probe(struct platform_device *pdev)
if (!fch_data || !fch_data->base)
return -EINVAL;
 
-   hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz", NULL, 0,
-4800);
-   hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz", NULL, 0,
-2500);
+   if (!fch_data->is_rv) {
+   hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
+   NULL, 0, 4800);
+   hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz",
+   NULL, 0, 2500);
+
+   hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
+   clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
+   0, fch_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0,
+   NULL);
+
+   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
 
-   hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
-   clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
-   0, fch_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
+   hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1",
+   "oscout1_mux", 0, fch_data->base + MISCCLKCNTL1,
+   OSCCLKENB, CLK_GATE_SET_TO_DISABLE, NULL);
 
-   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
+   devm_clk_hw_register_clkdev(>dev, hws[ST_CLK_GATE],
+   "oscout1", NULL);
+   } else {
+   hws[RV_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
+   NULL, 0, 4800);
 
-   hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", "oscout1_mux",
-   0, fch_data->base + MISCCLKCNTL1, OSCCLKENB,
-   CLK_GATE_SET_TO_DISABLE, NULL);
+   hws[RV_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1",
+   "clk48MHz", 0, fch_data->base + MISCCLKCNTL1,
+   OSCCLKENB, CLK_GATE_SET_TO_DISABLE, NULL);
 
-   devm_clk_hw_register_clkdev(>dev, hws[ST_CLK_GATE], "oscout1",
-   NULL);
+   devm_clk_hw_register_clkdev(>dev, hws[RV_CLK_GATE],
+   "oscout1", NULL);
+   }
 
return 0;
 }
@@ -61,9 +78,17 @@ static int fch_clk_probe(struct platform_device *pdev)
 static int fch_clk_remove(struct platform_device *pdev)
 {
int i;
+   struct fch_clk_data *fch_data;
+
+   fch_data = dev_get_platdata(>dev);
 
-   for (i = 0; i < ST_MAX_CLKS; i++)
-   clk_hw_unregister(hws[i]);
+   if (!fch_data->is_rv) {
+   for (i = 0; i < ST_MAX_CLKS; i++)
+   clk_hw_unregister(hws[i]);
+   } else {
+   for (i = 0; i < RV_MAX_CLKS; i++)
+   clk_hw_unregister(hws[i]);
+   }
return 0;
 }
 
-- 
2.20.1



[PATCH 2/5] clk: x86: Change name from ST to FCH

2020-07-12 Thread Akshu Agrawal
AMD SoC general pupose clk is present in new platforms with
minor differences. We can reuse the same clk driver for other
platforms. Hence, changing name from ST(SoC) to FCH(IP)

Signed-off-by: Akshu Agrawal 
---
 drivers/clk/x86/Makefile|  2 +-
 drivers/clk/x86/{clk-st.c => clk-fch.c} | 26 -
 2 files changed, 14 insertions(+), 14 deletions(-)
 rename drivers/clk/x86/{clk-st.c => clk-fch.c} (73%)

diff --git a/drivers/clk/x86/Makefile b/drivers/clk/x86/Makefile
index 7c774ea7ddeb..18564efdc651 100644
--- a/drivers/clk/x86/Makefile
+++ b/drivers/clk/x86/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_PMC_ATOM) += clk-pmc-atom.o
-obj-$(CONFIG_X86_AMD_PLATFORM_DEVICE)  += clk-st.o
+obj-$(CONFIG_X86_AMD_PLATFORM_DEVICE)  += clk-fch.o
 clk-x86-lpss-objs  := clk-lpt.o
 obj-$(CONFIG_X86_INTEL_LPSS)   += clk-x86-lpss.o
 obj-$(CONFIG_CLK_LGM_CGU)  += clk-cgu.o clk-cgu-pll.o clk-lgm.o
diff --git a/drivers/clk/x86/clk-st.c b/drivers/clk/x86/clk-fch.c
similarity index 73%
rename from drivers/clk/x86/clk-st.c
rename to drivers/clk/x86/clk-fch.c
index 25d4b97aff9b..b252f0cf0628 100644
--- a/drivers/clk/x86/clk-st.c
+++ b/drivers/clk/x86/clk-fch.c
@@ -8,7 +8,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 
 /* Clock Driving Strength 2 register */
@@ -29,12 +29,12 @@
 static const char * const clk_oscout1_parents[] = { "clk48MHz", "clk25MHz" };
 static struct clk_hw *hws[ST_MAX_CLKS];
 
-static int st_clk_probe(struct platform_device *pdev)
+static int fch_clk_probe(struct platform_device *pdev)
 {
-   struct st_clk_data *st_data;
+   struct fch_clk_data *fch_data;
 
-   st_data = dev_get_platdata(>dev);
-   if (!st_data || !st_data->base)
+   fch_data = dev_get_platdata(>dev);
+   if (!fch_data || !fch_data->base)
return -EINVAL;
 
hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz", NULL, 0,
@@ -44,12 +44,12 @@ static int st_clk_probe(struct platform_device *pdev)
 
hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
-   0, st_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
+   0, fch_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
 
clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
 
hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", "oscout1_mux",
-   0, st_data->base + MISCCLKCNTL1, OSCCLKENB,
+   0, fch_data->base + MISCCLKCNTL1, OSCCLKENB,
CLK_GATE_SET_TO_DISABLE, NULL);
 
devm_clk_hw_register_clkdev(>dev, hws[ST_CLK_GATE], "oscout1",
@@ -58,7 +58,7 @@ static int st_clk_probe(struct platform_device *pdev)
return 0;
 }
 
-static int st_clk_remove(struct platform_device *pdev)
+static int fch_clk_remove(struct platform_device *pdev)
 {
int i;
 
@@ -67,12 +67,12 @@ static int st_clk_remove(struct platform_device *pdev)
return 0;
 }
 
-static struct platform_driver st_clk_driver = {
+static struct platform_driver fch_clk_driver = {
.driver = {
-   .name = "clk-st",
+   .name = "clk-fch",
.suppress_bind_attrs = true,
},
-   .probe = st_clk_probe,
-   .remove = st_clk_remove,
+   .probe = fch_clk_probe,
+   .remove = fch_clk_remove,
 };
-builtin_platform_driver(st_clk_driver);
+builtin_platform_driver(fch_clk_driver);
-- 
2.20.1



[PATCH 1/5] ACPI: APD: Change name from ST to FCH

2020-07-12 Thread Akshu Agrawal
AMD SoC general pupose clk is present in new platforms with
same MMIO mappings. We can reuse the same clk handler support
for other platforms. Hence, changing name from ST(SoC) to FCH(IP)

Signed-off-by: Akshu Agrawal 
---
 drivers/acpi/acpi_apd.c| 14 +++---
 .../linux/platform_data/{clk-st.h => clk-fch.h}| 10 +-
 2 files changed, 12 insertions(+), 12 deletions(-)
 rename include/linux/platform_data/{clk-st.h => clk-fch.h} (53%)

diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index ba2612e9a0eb..2d99e46add1a 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -8,7 +8,7 @@
  */
 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -79,11 +79,11 @@ static int misc_check_res(struct acpi_resource *ares, void 
*data)
return !acpi_dev_resource_memory(ares, );
 }
 
-static int st_misc_setup(struct apd_private_data *pdata)
+static int fch_misc_setup(struct apd_private_data *pdata)
 {
struct acpi_device *adev = pdata->adev;
struct platform_device *clkdev;
-   struct st_clk_data *clk_data;
+   struct fch_clk_data *clk_data;
struct resource_entry *rentry;
struct list_head resource_list;
int ret;
@@ -106,7 +106,7 @@ static int st_misc_setup(struct apd_private_data *pdata)
 
acpi_dev_free_resource_list(_list);
 
-   clkdev = platform_device_register_data(>dev, "clk-st",
+   clkdev = platform_device_register_data(>dev, "clk-fch",
   PLATFORM_DEVID_NONE, clk_data,
   sizeof(*clk_data));
return PTR_ERR_OR_ZERO(clkdev);
@@ -135,8 +135,8 @@ static const struct apd_device_desc cz_uart_desc = {
.properties = uart_properties,
 };
 
-static const struct apd_device_desc st_misc_desc = {
-   .setup = st_misc_setup,
+static const struct apd_device_desc fch_misc_desc = {
+   .setup = fch_misc_setup,
 };
 #endif
 
@@ -239,7 +239,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
{ "AMD0020", APD_ADDR(cz_uart_desc) },
{ "AMDI0020", APD_ADDR(cz_uart_desc) },
{ "AMD0030", },
-   { "AMD0040", APD_ADDR(st_misc_desc)},
+   { "AMD0040", APD_ADDR(fch_misc_desc)},
 #endif
 #ifdef CONFIG_ARM64
{ "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
diff --git a/include/linux/platform_data/clk-st.h 
b/include/linux/platform_data/clk-fch.h
similarity index 53%
rename from include/linux/platform_data/clk-st.h
rename to include/linux/platform_data/clk-fch.h
index 7cdb6a402b35..850ca776156d 100644
--- a/include/linux/platform_data/clk-st.h
+++ b/include/linux/platform_data/clk-fch.h
@@ -1,17 +1,17 @@
 /* SPDX-License-Identifier: MIT */
 /*
- * clock framework for AMD Stoney based clock
+ * clock framework for AMD misc clocks
  *
  * Copyright 2018 Advanced Micro Devices, Inc.
  */
 
-#ifndef __CLK_ST_H
-#define __CLK_ST_H
+#ifndef __CLK_FCH_H
+#define __CLK_FCH_H
 
 #include 
 
-struct st_clk_data {
+struct fch_clk_data {
void __iomem *base;
 };
 
-#endif /* __CLK_ST_H */
+#endif /* __CLK_FCH_H */
-- 
2.20.1



[PATCH 3/5] ACPI: APD: Add a fmw property is_raven

2020-07-12 Thread Akshu Agrawal
Since there is slight difference in AMD RV based soc in misc
clk architecture. The fmw property will help in differentiating
the SoCs.

Signed-off-by: Akshu Agrawal 
---
 drivers/acpi/acpi_apd.c   | 4 
 include/linux/platform_data/clk-fch.h | 1 +
 2 files changed, 5 insertions(+)

diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index 2d99e46add1a..d879ba28826c 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -82,6 +82,7 @@ static int misc_check_res(struct acpi_resource *ares, void 
*data)
 static int fch_misc_setup(struct apd_private_data *pdata)
 {
struct acpi_device *adev = pdata->adev;
+   const union acpi_object *obj;
struct platform_device *clkdev;
struct fch_clk_data *clk_data;
struct resource_entry *rentry;
@@ -98,6 +99,9 @@ static int fch_misc_setup(struct apd_private_data *pdata)
if (ret < 0)
return -ENOENT;
 
+   acpi_dev_get_property(adev, "is-rv", ACPI_TYPE_INTEGER, );
+   clk_data->is_rv = obj->integer.value;
+
list_for_each_entry(rentry, _list, node) {
clk_data->base = devm_ioremap(>dev, rentry->res->start,
  resource_size(rentry->res));
diff --git a/include/linux/platform_data/clk-fch.h 
b/include/linux/platform_data/clk-fch.h
index 850ca776156d..b9f682459f08 100644
--- a/include/linux/platform_data/clk-fch.h
+++ b/include/linux/platform_data/clk-fch.h
@@ -12,6 +12,7 @@
 
 struct fch_clk_data {
void __iomem *base;
+   u32 is_rv;
 };
 
 #endif /* __CLK_FCH_H */
-- 
2.20.1



[PATCH] ASoC: rt5682: Add fmw property to get name of mclk

2020-07-07 Thread Akshu Agrawal
Non-dts based systems can use ACPI DSDT to pass on the mclk.
Thus add fmw property mclk-name to get the name of the system clk
and link it to rt5682 mclk.

Signed-off-by: Akshu Agrawal 
---
 include/sound/rt5682.h| 1 +
 sound/soc/codecs/rt5682.c | 7 ++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/include/sound/rt5682.h b/include/sound/rt5682.h
index e1f790561ac1..8717c02f89b8 100644
--- a/include/sound/rt5682.h
+++ b/include/sound/rt5682.h
@@ -42,6 +42,7 @@ struct rt5682_platform_data {
unsigned int dmic_delay;
 
const char *dai_clk_names[RT5682_DAI_NUM_CLKS];
+   const char *mclk_name;
 };
 
 #endif
diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c
index de40b6cd16cf..8b223bd0929e 100644
--- a/sound/soc/codecs/rt5682.c
+++ b/sound/soc/codecs/rt5682.c
@@ -2849,7 +2849,10 @@ static int rt5682_probe(struct snd_soc_component 
*component)
} else {
 #ifdef CONFIG_COMMON_CLK
/* Check if MCLK provided */
-   rt5682->mclk = devm_clk_get(component->dev, "mclk");
+   if (rt5682->pdata.mclk_name)
+   rt5682->mclk = clk_get(NULL, rt5682->pdata.mclk_name);
+   if (!rt5682->mclk)
+   rt5682->mclk = devm_clk_get(component->dev, "mclk");
if (IS_ERR(rt5682->mclk)) {
if (PTR_ERR(rt5682->mclk) != -ENOENT) {
ret = PTR_ERR(rt5682->mclk);
@@ -2976,6 +2979,8 @@ int rt5682_parse_dt(struct rt5682_priv *rt5682, struct 
device *dev)
 rt5682->pdata.dai_clk_names[RT5682_DAI_WCLK_IDX],
 rt5682->pdata.dai_clk_names[RT5682_DAI_BCLK_IDX]);
 
+   device_property_read_string(dev, "realtek,mclk-name", 
>pdata.mclk_name);
+
return 0;
 }
 EXPORT_SYMBOL_GPL(rt5682_parse_dt);
-- 
2.20.1



[PATCH 1/2] clk: x86: Change name from ST to FCH

2020-07-07 Thread Akshu Agrawal
AMD SoC general pupose clk is present in new platforms with
minor differences. We can reuse the same clk driver for other
platforms. Hence, changing name from ST(SoC) to FCH(IP)

Signed-off-by: Akshu Agrawal 
---
This patch is dependant on https://patchwork.kernel.org/patch/11648129/

 drivers/clk/x86/Makefile|  2 +-
 drivers/clk/x86/{clk-st.c => clk-fch.c} | 26 -
 2 files changed, 14 insertions(+), 14 deletions(-)
 rename drivers/clk/x86/{clk-st.c => clk-fch.c} (73%)

diff --git a/drivers/clk/x86/Makefile b/drivers/clk/x86/Makefile
index 7c774ea7ddeb..18564efdc651 100644
--- a/drivers/clk/x86/Makefile
+++ b/drivers/clk/x86/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_PMC_ATOM) += clk-pmc-atom.o
-obj-$(CONFIG_X86_AMD_PLATFORM_DEVICE)  += clk-st.o
+obj-$(CONFIG_X86_AMD_PLATFORM_DEVICE)  += clk-fch.o
 clk-x86-lpss-objs  := clk-lpt.o
 obj-$(CONFIG_X86_INTEL_LPSS)   += clk-x86-lpss.o
 obj-$(CONFIG_CLK_LGM_CGU)  += clk-cgu.o clk-cgu-pll.o clk-lgm.o
diff --git a/drivers/clk/x86/clk-st.c b/drivers/clk/x86/clk-fch.c
similarity index 73%
rename from drivers/clk/x86/clk-st.c
rename to drivers/clk/x86/clk-fch.c
index 25d4b97aff9b..b252f0cf0628 100644
--- a/drivers/clk/x86/clk-st.c
+++ b/drivers/clk/x86/clk-fch.c
@@ -8,7 +8,7 @@
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 
 /* Clock Driving Strength 2 register */
@@ -29,12 +29,12 @@
 static const char * const clk_oscout1_parents[] = { "clk48MHz", "clk25MHz" };
 static struct clk_hw *hws[ST_MAX_CLKS];
 
-static int st_clk_probe(struct platform_device *pdev)
+static int fch_clk_probe(struct platform_device *pdev)
 {
-   struct st_clk_data *st_data;
+   struct fch_clk_data *fch_data;
 
-   st_data = dev_get_platdata(>dev);
-   if (!st_data || !st_data->base)
+   fch_data = dev_get_platdata(>dev);
+   if (!fch_data || !fch_data->base)
return -EINVAL;
 
hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz", NULL, 0,
@@ -44,12 +44,12 @@ static int st_clk_probe(struct platform_device *pdev)
 
hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
-   0, st_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
+   0, fch_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
 
clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
 
hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", "oscout1_mux",
-   0, st_data->base + MISCCLKCNTL1, OSCCLKENB,
+   0, fch_data->base + MISCCLKCNTL1, OSCCLKENB,
CLK_GATE_SET_TO_DISABLE, NULL);
 
devm_clk_hw_register_clkdev(>dev, hws[ST_CLK_GATE], "oscout1",
@@ -58,7 +58,7 @@ static int st_clk_probe(struct platform_device *pdev)
return 0;
 }
 
-static int st_clk_remove(struct platform_device *pdev)
+static int fch_clk_remove(struct platform_device *pdev)
 {
int i;
 
@@ -67,12 +67,12 @@ static int st_clk_remove(struct platform_device *pdev)
return 0;
 }
 
-static struct platform_driver st_clk_driver = {
+static struct platform_driver fch_clk_driver = {
.driver = {
-   .name = "clk-st",
+   .name = "clk-fch",
.suppress_bind_attrs = true,
},
-   .probe = st_clk_probe,
-   .remove = st_clk_remove,
+   .probe = fch_clk_probe,
+   .remove = fch_clk_remove,
 };
-builtin_platform_driver(st_clk_driver);
+builtin_platform_driver(fch_clk_driver);
-- 
2.20.1



[PATCH 2/2] clk: x86: Support RV architecture

2020-07-07 Thread Akshu Agrawal
There is minor difference between previous family of SoC and
the current one. Which is the there is only 48Mh fixed clk.
There is no mux and no option to select another freq as there in previous.

Signed-off-by: Akshu Agrawal 
---
This patch is dependant on https://patchwork.kernel.org/patch/11648131/

 drivers/clk/x86/clk-fch.c | 55 ---
 1 file changed, 40 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/x86/clk-fch.c b/drivers/clk/x86/clk-fch.c
index b252f0cf0628..a8aac71a3b65 100644
--- a/drivers/clk/x86/clk-fch.c
+++ b/drivers/clk/x86/clk-fch.c
@@ -26,6 +26,10 @@
 #define ST_CLK_GATE3
 #define ST_MAX_CLKS4
 
+#define RV_CLK_48M 0
+#define RV_CLK_GATE1
+#define RV_MAX_CLKS2
+
 static const char * const clk_oscout1_parents[] = { "clk48MHz", "clk25MHz" };
 static struct clk_hw *hws[ST_MAX_CLKS];
 
@@ -37,23 +41,36 @@ static int fch_clk_probe(struct platform_device *pdev)
if (!fch_data || !fch_data->base)
return -EINVAL;
 
-   hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz", NULL, 0,
-4800);
-   hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz", NULL, 0,
-2500);
+   if (!fch_data->is_rv) {
+   hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
+   NULL, 0, 4800);
+   hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz",
+   NULL, 0, 2500);
+
+   hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
+   clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
+   0, fch_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0,
+   NULL);
+
+   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
 
-   hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
-   clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
-   0, fch_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
+   hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1",
+   "oscout1_mux", 0, fch_data->base + MISCCLKCNTL1,
+   OSCCLKENB, CLK_GATE_SET_TO_DISABLE, NULL);
 
-   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
+   devm_clk_hw_register_clkdev(>dev, hws[ST_CLK_GATE],
+   "oscout1", NULL);
+   } else {
+   hws[RV_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz",
+   NULL, 0, 4800);
 
-   hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", "oscout1_mux",
-   0, fch_data->base + MISCCLKCNTL1, OSCCLKENB,
-   CLK_GATE_SET_TO_DISABLE, NULL);
+   hws[RV_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1",
+   "clk48MHz", 0, fch_data->base + MISCCLKCNTL1,
+   OSCCLKENB, CLK_GATE_SET_TO_DISABLE, NULL);
 
-   devm_clk_hw_register_clkdev(>dev, hws[ST_CLK_GATE], "oscout1",
-   NULL);
+   devm_clk_hw_register_clkdev(>dev, hws[RV_CLK_GATE],
+   "oscout1", NULL);
+   }
 
return 0;
 }
@@ -61,9 +78,17 @@ static int fch_clk_probe(struct platform_device *pdev)
 static int fch_clk_remove(struct platform_device *pdev)
 {
int i;
+   struct fch_clk_data *fch_data;
+
+   fch_data = dev_get_platdata(>dev);
 
-   for (i = 0; i < ST_MAX_CLKS; i++)
-   clk_hw_unregister(hws[i]);
+   if (!fch_data->is_rv) {
+   for (i = 0; i < ST_MAX_CLKS; i++)
+   clk_hw_unregister(hws[i]);
+   } else {
+   for (i = 0; i < RV_MAX_CLKS; i++)
+   clk_hw_unregister(hws[i]);
+   }
return 0;
 }
 
-- 
2.20.1



[PATCH 1/2] ACPI: APD: Change name from ST to FCH

2020-07-07 Thread Akshu Agrawal
AMD SoC general pupose clk is present in new platforms with
same MMIO mappings. We can reuse the same clk handler support
for other platforms. Hence, changing name from ST(SoC) to FCH(IP)

Signed-off-by: Akshu Agrawal 
---
 drivers/acpi/acpi_apd.c| 14 +++---
 .../linux/platform_data/{clk-st.h => clk-fch.h}| 10 +-
 2 files changed, 12 insertions(+), 12 deletions(-)
 rename include/linux/platform_data/{clk-st.h => clk-fch.h} (53%)

diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index ba2612e9a0eb..2d99e46add1a 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -8,7 +8,7 @@
  */
 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -79,11 +79,11 @@ static int misc_check_res(struct acpi_resource *ares, void 
*data)
return !acpi_dev_resource_memory(ares, );
 }
 
-static int st_misc_setup(struct apd_private_data *pdata)
+static int fch_misc_setup(struct apd_private_data *pdata)
 {
struct acpi_device *adev = pdata->adev;
struct platform_device *clkdev;
-   struct st_clk_data *clk_data;
+   struct fch_clk_data *clk_data;
struct resource_entry *rentry;
struct list_head resource_list;
int ret;
@@ -106,7 +106,7 @@ static int st_misc_setup(struct apd_private_data *pdata)
 
acpi_dev_free_resource_list(_list);
 
-   clkdev = platform_device_register_data(>dev, "clk-st",
+   clkdev = platform_device_register_data(>dev, "clk-fch",
   PLATFORM_DEVID_NONE, clk_data,
   sizeof(*clk_data));
return PTR_ERR_OR_ZERO(clkdev);
@@ -135,8 +135,8 @@ static const struct apd_device_desc cz_uart_desc = {
.properties = uart_properties,
 };
 
-static const struct apd_device_desc st_misc_desc = {
-   .setup = st_misc_setup,
+static const struct apd_device_desc fch_misc_desc = {
+   .setup = fch_misc_setup,
 };
 #endif
 
@@ -239,7 +239,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
{ "AMD0020", APD_ADDR(cz_uart_desc) },
{ "AMDI0020", APD_ADDR(cz_uart_desc) },
{ "AMD0030", },
-   { "AMD0040", APD_ADDR(st_misc_desc)},
+   { "AMD0040", APD_ADDR(fch_misc_desc)},
 #endif
 #ifdef CONFIG_ARM64
{ "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
diff --git a/include/linux/platform_data/clk-st.h 
b/include/linux/platform_data/clk-fch.h
similarity index 53%
rename from include/linux/platform_data/clk-st.h
rename to include/linux/platform_data/clk-fch.h
index 7cdb6a402b35..850ca776156d 100644
--- a/include/linux/platform_data/clk-st.h
+++ b/include/linux/platform_data/clk-fch.h
@@ -1,17 +1,17 @@
 /* SPDX-License-Identifier: MIT */
 /*
- * clock framework for AMD Stoney based clock
+ * clock framework for AMD misc clocks
  *
  * Copyright 2018 Advanced Micro Devices, Inc.
  */
 
-#ifndef __CLK_ST_H
-#define __CLK_ST_H
+#ifndef __CLK_FCH_H
+#define __CLK_FCH_H
 
 #include 
 
-struct st_clk_data {
+struct fch_clk_data {
void __iomem *base;
 };
 
-#endif /* __CLK_ST_H */
+#endif /* __CLK_FCH_H */
-- 
2.20.1



[PATCH 2/2] ACPI: APD: Add a fmw property is_raven

2020-07-07 Thread Akshu Agrawal
Since there is slight difference in AMD RV based soc in misc
clk architecture. The fmw property will help in differentiating
the SoCs.

Signed-off-by: Akshu Agrawal 
---
 drivers/acpi/acpi_apd.c   | 4 
 include/linux/platform_data/clk-fch.h | 1 +
 2 files changed, 5 insertions(+)

diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index 2d99e46add1a..d879ba28826c 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -82,6 +82,7 @@ static int misc_check_res(struct acpi_resource *ares, void 
*data)
 static int fch_misc_setup(struct apd_private_data *pdata)
 {
struct acpi_device *adev = pdata->adev;
+   const union acpi_object *obj;
struct platform_device *clkdev;
struct fch_clk_data *clk_data;
struct resource_entry *rentry;
@@ -98,6 +99,9 @@ static int fch_misc_setup(struct apd_private_data *pdata)
if (ret < 0)
return -ENOENT;
 
+   acpi_dev_get_property(adev, "is-rv", ACPI_TYPE_INTEGER, );
+   clk_data->is_rv = obj->integer.value;
+
list_for_each_entry(rentry, _list, node) {
clk_data->base = devm_ioremap(>dev, rentry->res->start,
  resource_size(rentry->res));
diff --git a/include/linux/platform_data/clk-fch.h 
b/include/linux/platform_data/clk-fch.h
index 850ca776156d..b9f682459f08 100644
--- a/include/linux/platform_data/clk-fch.h
+++ b/include/linux/platform_data/clk-fch.h
@@ -12,6 +12,7 @@
 
 struct fch_clk_data {
void __iomem *base;
+   u32 is_rv;
 };
 
 #endif /* __CLK_FCH_H */
-- 
2.20.1



[PATCH] ASoC: amd: Enable interrupt in dma_open

2020-06-30 Thread Akshu Agrawal
Fixes interrupt enable condition check with which now
interrupt gets enabled in dma_open.
Prior to this patch it was getting enabled in runtime_resume only.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/raven/acp3x-pcm-dma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c 
b/sound/soc/amd/raven/acp3x-pcm-dma.c
index e6386de20ac7..5bd458e0fe31 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -238,7 +238,7 @@ static int acp3x_dma_open(struct snd_soc_component 
*component,
}
 
if (!adata->play_stream && !adata->capture_stream &&
-   adata->i2ssp_play_stream && !adata->i2ssp_capture_stream)
+   !adata->i2ssp_play_stream && !adata->i2ssp_capture_stream)
rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 
i2s_data->acp3x_base = adata->acp3x_base;
-- 
2.20.1



[PATCH] mmc: sdhci-acpi: For amd device set driver type as MMC_SET_DRIVER_TYPE_A

2020-06-23 Thread Akshu Agrawal
HS400/HS200/eMMC HS doesn't have Preset Value register.
Hence, sdhci_set_ios function overrides the value set by fmw to
SDHCI_CTRL_DRV_TYPE_B.
This patch sets drv_type to MMC_SET_DRIVER_TYPE_A
so that host_control2 register gets updated with the required
strength value.

Signed-off-by: Akshu Agrawal 
---
 drivers/mmc/host/sdhci-acpi.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c
index d8b76cb8698a..48ecbd0b180d 100644
--- a/drivers/mmc/host/sdhci-acpi.c
+++ b/drivers/mmc/host/sdhci-acpi.c
@@ -542,6 +542,7 @@ static int amd_select_drive_strength(struct mmc_card *card,
 unsigned int max_dtr, int host_drv,
 int card_drv, int *drv_type)
 {
+   *drv_type = MMC_SET_DRIVER_TYPE_A;
return MMC_SET_DRIVER_TYPE_A;
 }
 
-- 
2.20.1



[PATCH] ASoC: rt5682: Register clocks even when mclk is NULL

2020-06-12 Thread Akshu Agrawal
Fixes kernel crash on platforms which do not have mclk exposed
in CCF framework. For these platforms have mclk as NULL and
continue to register clocks.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/codecs/rt5682.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c
index d3245123101d..7c8b8d839db8 100644
--- a/sound/soc/codecs/rt5682.c
+++ b/sound/soc/codecs/rt5682.c
@@ -2829,12 +2829,11 @@ static int rt5682_probe(struct snd_soc_component 
*component)
return ret;
}
rt5682->mclk = NULL;
-   } else {
-   /* Register CCF DAI clock control */
-   ret = rt5682_register_dai_clks(component);
-   if (ret)
-   return ret;
}
+   /* Register CCF DAI clock control */
+   ret = rt5682_register_dai_clks(component);
+   if (ret)
+   return ret;
/* Initial setup for CCF */
rt5682->lrck[RT5682_AIF1] = CLK_48;
 #endif
-- 
2.20.1



[v3] ASoC: AMD: Use mixer control to switch between DMICs

2020-05-30 Thread Akshu Agrawal
Having mixer control to switch between DMICs prevents user to
initiate capture simultaneously on both the DMIcs.
Earlier 2 separate devices, one for each DMIC, gave an option of
using them simultaneously, which is not supported.

Signed-off-by: Akshu Agrawal 
---
v2: Modified "Front Mic" to "DMIC Switch"
v3: Changed to using of Mux

 sound/soc/amd/acp3x-rt5682-max9836.c | 58 +++-
 1 file changed, 31 insertions(+), 27 deletions(-)

diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c 
b/sound/soc/amd/acp3x-rt5682-max9836.c
index e499c00e0c66..f745b42dfd23 100644
--- a/sound/soc/amd/acp3x-rt5682-max9836.c
+++ b/sound/soc/amd/acp3x-rt5682-max9836.c
@@ -188,25 +188,27 @@ static int acp3x_ec_dmic0_startup(struct 
snd_pcm_substream *substream)
 
machine->cap_i2s_instance = I2S_BT_INSTANCE;
snd_soc_dai_set_bclk_ratio(codec_dai, 64);
-   if (dmic_sel)
-   gpiod_set_value(dmic_sel, 0);
 
return rt5682_clk_enable(substream);
 }
 
-static int acp3x_ec_dmic1_startup(struct snd_pcm_substream *substream)
-{
-   struct snd_soc_pcm_runtime *rtd = substream->private_data;
-   struct snd_soc_card *card = rtd->card;
-   struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
-   struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card);
+static int dmic_switch;
 
-   machine->cap_i2s_instance = I2S_BT_INSTANCE;
-   snd_soc_dai_set_bclk_ratio(codec_dai, 64);
-   if (dmic_sel)
-   gpiod_set_value(dmic_sel, 1);
+static int dmic_get(struct snd_kcontrol *kcontrol,
+struct snd_ctl_elem_value *ucontrol)
+{
+   ucontrol->value.integer.value[0] = dmic_switch;
+   return 0;
+}
 
-   return rt5682_clk_enable(substream);
+static int dmic_set(struct snd_kcontrol *kcontrol,
+struct snd_ctl_elem_value *ucontrol)
+{
+   if (dmic_sel) {
+   dmic_switch = ucontrol->value.integer.value[0];
+   gpiod_set_value(dmic_sel, dmic_switch);
+   }
+   return 0;
 }
 
 static void rt5682_shutdown(struct snd_pcm_substream *substream)
@@ -229,11 +231,6 @@ static const struct snd_soc_ops acp3x_ec_cap0_ops = {
.shutdown = rt5682_shutdown,
 };
 
-static const struct snd_soc_ops acp3x_ec_cap1_ops = {
-   .startup = acp3x_ec_dmic1_startup,
-   .shutdown = rt5682_shutdown,
-};
-
 SND_SOC_DAILINK_DEF(acp3x_i2s,
DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.0")));
 SND_SOC_DAILINK_DEF(acp3x_bt,
@@ -279,21 +276,26 @@ static struct snd_soc_dai_link acp3x_dai_5682_98357[] = {
.ops = _ec_cap0_ops,
SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform),
},
-   {
-   .name = "acp3x-ec-dmic1-capture",
-   .stream_name = "Capture DMIC1",
-   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
-   | SND_SOC_DAIFMT_CBS_CFS,
-   .dpcm_capture = 1,
-   .ops = _ec_cap1_ops,
-   SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform),
-   },
 };
 
+static const char * const dmic_mux_text[] = {
+   "Front Mic",
+   "Rear Mic",
+};
+
+static SOC_ENUM_SINGLE_DECL(
+   acp3x_dmic_enum, SND_SOC_NOPM, 0, dmic_mux_text);
+
+static const struct snd_kcontrol_new acp3x_dmic_mux_control =
+   SOC_DAPM_ENUM_EXT("DMIC Select Mux", acp3x_dmic_enum,
+ dmic_get, dmic_set);
+
 static const struct snd_soc_dapm_widget acp3x_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
SND_SOC_DAPM_SPK("Spk", NULL),
SND_SOC_DAPM_MIC("Headset Mic", NULL),
+   SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0,
+_dmic_mux_control),
 };
 
 static const struct snd_soc_dapm_route acp3x_audio_route[] = {
@@ -301,6 +303,8 @@ static const struct snd_soc_dapm_route acp3x_audio_route[] 
= {
{"Headphone Jack", NULL, "HPOR"},
{"IN1P", NULL, "Headset Mic"},
{"Spk", NULL, "Speaker"},
+   {"Dmic Mux", "Front Mic", "DMIC"},
+   {"Dmic Mux", "Rear Mic", "DMIC"},
 };
 
 static const struct snd_kcontrol_new acp3x_mc_controls[] = {
-- 
2.20.1



[v2] ASoC: AMD: Use mixer control to switch between DMICs

2020-05-28 Thread Akshu Agrawal
Having mixer control to switch between DMICs prevents user to
initiate capture simultaneously on both the DMIcs.
Earlier 2 separate devices, one for each DMIC, gave an option of
using them simultaneously, which is not supported.

Signed-off-by: Akshu Agrawal 
---
v2: Modified "Front Mic" to "DMIC Switch"
 sound/soc/amd/acp3x-rt5682-max9836.c | 43 +++-
 1 file changed, 16 insertions(+), 27 deletions(-)

diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c 
b/sound/soc/amd/acp3x-rt5682-max9836.c
index e499c00e0c66..0d3422b5f1a9 100644
--- a/sound/soc/amd/acp3x-rt5682-max9836.c
+++ b/sound/soc/amd/acp3x-rt5682-max9836.c
@@ -188,25 +188,27 @@ static int acp3x_ec_dmic0_startup(struct 
snd_pcm_substream *substream)
 
machine->cap_i2s_instance = I2S_BT_INSTANCE;
snd_soc_dai_set_bclk_ratio(codec_dai, 64);
-   if (dmic_sel)
-   gpiod_set_value(dmic_sel, 0);
 
return rt5682_clk_enable(substream);
 }
 
-static int acp3x_ec_dmic1_startup(struct snd_pcm_substream *substream)
-{
-   struct snd_soc_pcm_runtime *rtd = substream->private_data;
-   struct snd_soc_card *card = rtd->card;
-   struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
-   struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card);
+static int dmic_switch;
 
-   machine->cap_i2s_instance = I2S_BT_INSTANCE;
-   snd_soc_dai_set_bclk_ratio(codec_dai, 64);
-   if (dmic_sel)
-   gpiod_set_value(dmic_sel, 1);
+static int dmic_get(struct snd_kcontrol *kcontrol,
+struct snd_ctl_elem_value *ucontrol)
+{
+   ucontrol->value.integer.value[0] = dmic_switch;
+   return 0;
+}
 
-   return rt5682_clk_enable(substream);
+static int dmic_set(struct snd_kcontrol *kcontrol,
+struct snd_ctl_elem_value *ucontrol)
+{
+   if (dmic_sel) {
+   dmic_switch = ucontrol->value.integer.value[0];
+   gpiod_set_value(dmic_sel, !dmic_switch);
+   }
+   return 0;
 }
 
 static void rt5682_shutdown(struct snd_pcm_substream *substream)
@@ -229,11 +231,6 @@ static const struct snd_soc_ops acp3x_ec_cap0_ops = {
.shutdown = rt5682_shutdown,
 };
 
-static const struct snd_soc_ops acp3x_ec_cap1_ops = {
-   .startup = acp3x_ec_dmic1_startup,
-   .shutdown = rt5682_shutdown,
-};
-
 SND_SOC_DAILINK_DEF(acp3x_i2s,
DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.0")));
 SND_SOC_DAILINK_DEF(acp3x_bt,
@@ -279,15 +276,6 @@ static struct snd_soc_dai_link acp3x_dai_5682_98357[] = {
.ops = _ec_cap0_ops,
SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform),
},
-   {
-   .name = "acp3x-ec-dmic1-capture",
-   .stream_name = "Capture DMIC1",
-   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
-   | SND_SOC_DAIFMT_CBS_CFS,
-   .dpcm_capture = 1,
-   .ops = _ec_cap1_ops,
-   SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform),
-   },
 };
 
 static const struct snd_soc_dapm_widget acp3x_widgets[] = {
@@ -307,6 +295,7 @@ static const struct snd_kcontrol_new acp3x_mc_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone Jack"),
SOC_DAPM_PIN_SWITCH("Spk"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
+   SOC_SINGLE_BOOL_EXT("DMIC Switch", 0, dmic_get, dmic_set),
 };
 
 static struct snd_soc_card acp3x_card = {
-- 
2.20.1



[PATCH] ASoC: AMD: Use mixer control to switch between DMICs

2020-05-26 Thread Akshu Agrawal
Having mixer control to switch between DMICs prevents user to
initiate capture simultaneously on both the DMIcs.
Earlier 2 separate devices, one for each DMIC, gave an option of
using them simultaneously, which is not supported.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp3x-rt5682-max9836.c | 43 +++-
 1 file changed, 16 insertions(+), 27 deletions(-)

diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c 
b/sound/soc/amd/acp3x-rt5682-max9836.c
index e499c00e0c66..19f55a814547 100644
--- a/sound/soc/amd/acp3x-rt5682-max9836.c
+++ b/sound/soc/amd/acp3x-rt5682-max9836.c
@@ -188,25 +188,27 @@ static int acp3x_ec_dmic0_startup(struct 
snd_pcm_substream *substream)
 
machine->cap_i2s_instance = I2S_BT_INSTANCE;
snd_soc_dai_set_bclk_ratio(codec_dai, 64);
-   if (dmic_sel)
-   gpiod_set_value(dmic_sel, 0);
 
return rt5682_clk_enable(substream);
 }
 
-static int acp3x_ec_dmic1_startup(struct snd_pcm_substream *substream)
-{
-   struct snd_soc_pcm_runtime *rtd = substream->private_data;
-   struct snd_soc_card *card = rtd->card;
-   struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0);
-   struct acp3x_platform_info *machine = snd_soc_card_get_drvdata(card);
+static int front_mic_enabled;
 
-   machine->cap_i2s_instance = I2S_BT_INSTANCE;
-   snd_soc_dai_set_bclk_ratio(codec_dai, 64);
-   if (dmic_sel)
-   gpiod_set_value(dmic_sel, 1);
+static int front_mic_get(struct snd_kcontrol *kcontrol,
+struct snd_ctl_elem_value *ucontrol)
+{
+   ucontrol->value.integer.value[0] = front_mic_enabled;
+   return 0;
+}
 
-   return rt5682_clk_enable(substream);
+static int front_mic_set(struct snd_kcontrol *kcontrol,
+struct snd_ctl_elem_value *ucontrol)
+{
+   if (dmic_sel) {
+   front_mic_enabled = ucontrol->value.integer.value[0];
+   gpiod_set_value(dmic_sel, !front_mic_enabled);
+   }
+   return 0;
 }
 
 static void rt5682_shutdown(struct snd_pcm_substream *substream)
@@ -229,11 +231,6 @@ static const struct snd_soc_ops acp3x_ec_cap0_ops = {
.shutdown = rt5682_shutdown,
 };
 
-static const struct snd_soc_ops acp3x_ec_cap1_ops = {
-   .startup = acp3x_ec_dmic1_startup,
-   .shutdown = rt5682_shutdown,
-};
-
 SND_SOC_DAILINK_DEF(acp3x_i2s,
DAILINK_COMP_ARRAY(COMP_CPU("acp3x_i2s_playcap.0")));
 SND_SOC_DAILINK_DEF(acp3x_bt,
@@ -279,15 +276,6 @@ static struct snd_soc_dai_link acp3x_dai_5682_98357[] = {
.ops = _ec_cap0_ops,
SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform),
},
-   {
-   .name = "acp3x-ec-dmic1-capture",
-   .stream_name = "Capture DMIC1",
-   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
-   | SND_SOC_DAIFMT_CBS_CFS,
-   .dpcm_capture = 1,
-   .ops = _ec_cap1_ops,
-   SND_SOC_DAILINK_REG(acp3x_bt, cros_ec, platform),
-   },
 };
 
 static const struct snd_soc_dapm_widget acp3x_widgets[] = {
@@ -307,6 +295,7 @@ static const struct snd_kcontrol_new acp3x_mc_controls[] = {
SOC_DAPM_PIN_SWITCH("Headphone Jack"),
SOC_DAPM_PIN_SWITCH("Spk"),
SOC_DAPM_PIN_SWITCH("Headset Mic"),
+   SOC_SINGLE_BOOL_EXT("Front Mic", 0, front_mic_get, front_mic_set),
 };
 
 static struct snd_soc_card acp3x_card = {
-- 
2.20.1



[PATCH] ASoC: amd: raven: Make the driver name consistent across files

2020-05-17 Thread Akshu Agrawal
This fixes the issue of driver not getting auto loaded with
MODULE_ALIAS.

With this patch:
$find /sys/devices -name modalias -print0 | xargs -0 grep -i acp3x
/sys/devices/pci:00/:00:08.1/:03:00.5/acp3x_i2s_playcap.2/
modalias:platform:acp3x_i2s_playcap
/sys/devices/pci:00/:00:08.1/:03:00.5/acp3x_i2s_playcap.0/
modalias:platform:acp3x_i2s_playcap
/sys/devices/pci:00/:00:08.1/:03:00.5/acp3x_rv_i2s_dma.0/
modalias:platform:acp3x_rv_i2s_dma
/sys/devices/pci:00/:00:08.1/:03:00.5/acp3x_i2s_playcap.1/
modalias:platform:acp3x_i2s_playcap

Signed-off-by: Akshu Agrawal 
---
Resending the patch https://patchwork.kernel.org/patch/11355713/

 sound/soc/amd/raven/acp3x-i2s.c | 6 +++---
 sound/soc/amd/raven/acp3x-pcm-dma.c | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/sound/soc/amd/raven/acp3x-i2s.c b/sound/soc/amd/raven/acp3x-i2s.c
index f160d35a6832..a532e01a2622 100644
--- a/sound/soc/amd/raven/acp3x-i2s.c
+++ b/sound/soc/amd/raven/acp3x-i2s.c
@@ -15,7 +15,7 @@
 
 #include "acp3x.h"
 
-#define DRV_NAME "acp3x-i2s"
+#define DRV_NAME "acp3x_i2s_playcap"
 
 static int acp3x_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
unsigned int fmt)
@@ -269,7 +269,7 @@ static struct snd_soc_dai_ops acp3x_i2s_dai_ops = {
 };
 
 static const struct snd_soc_component_driver acp3x_dai_component = {
-   .name   = "acp3x-i2s",
+   .name   = DRV_NAME,
 };
 
 static struct snd_soc_dai_driver acp3x_i2s_dai = {
@@ -348,4 +348,4 @@ module_platform_driver(acp3x_dai_driver);
 MODULE_AUTHOR("vishnuvardhanrao.ravulap...@amd.com");
 MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver");
 MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_ALIAS("platform:"DRV_NAME);
diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c 
b/sound/soc/amd/raven/acp3x-pcm-dma.c
index a36c5cb848cd..620b568bc414 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -15,7 +15,7 @@
 
 #include "acp3x.h"
 
-#define DRV_NAME "acp3x-i2s-audio"
+#define DRV_NAME "acp3x_rv_i2s_dma"
 
 static const struct snd_pcm_hardware acp3x_pcm_hardware_playback = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
@@ -542,4 +542,4 @@ MODULE_AUTHOR("maruthi.bayyavar...@amd.com");
 MODULE_AUTHOR("vijendar.muku...@amd.com");
 MODULE_DESCRIPTION("AMD ACP 3.x PCM Driver");
 MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_ALIAS("platform:"DRV_NAME);
-- 
2.17.1



[PATCH] ASoC: amd :High hw_level while simultaneous capture

2020-05-06 Thread Akshu Agrawal
Simultaneous capture on dmic and headset mic is having
issue with high hw_level being reported.

Issue Can be reproduced by:
arecord -D hw:2,0 -f dat -d 60 /tmp/test0 &
arecord -D hw:2,2 -f dat -d 60 /tmp/test1 &
cat /proc/asound/card2/pcm?c/sub0/status

Actual issue is :
When we open one capture stream on one instance lets say I2S_SP and then
once again if we open other capture on other instance lets say I2S_BT while
first capture is in progress and when we try to read the status of both
running instances by below command cat /proc/asound/card2/pcm?c/sub0/status
we observe that avail_max is being doubled on first opened
capture(I2S_SP in the example).

This is because our previous implementation was like when any instance is
opened it gets initialized in dma_open irrespective of on what instance it
called open.

For example:
First I2S_SP called opened it initializes both SP/BT capture streams
irrespective of on which instance the stream opened.next time I2S_BT
called opened and it initializes both SP/BT this corrupts the behaviour .

So with this patch the stream gets initialized only on specific instance
when ever it gets opened calls hw_params.

This rectifies the issue.

Signed-off-by: Ravulapati Vishnu vardhan rao 

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/raven/acp3x-pcm-dma.c | 37 +++--
 1 file changed, 24 insertions(+), 13 deletions(-)

diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c 
b/sound/soc/amd/raven/acp3x-pcm-dma.c
index e362f0bc9e46..a36c5cb848cd 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -241,14 +241,6 @@ static int acp3x_dma_open(struct snd_soc_component 
*component,
adata->i2ssp_play_stream && !adata->i2ssp_capture_stream)
rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 
-   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-   adata->play_stream = substream;
-   adata->i2ssp_play_stream = substream;
-   } else {
-   adata->capture_stream = substream;
-   adata->i2ssp_capture_stream = substream;
-   }
-
i2s_data->acp3x_base = adata->acp3x_base;
runtime->private_data = i2s_data;
return ret;
@@ -263,23 +255,42 @@ static int acp3x_dma_hw_params(struct snd_soc_component 
*component,
struct snd_soc_pcm_runtime *prtd;
struct snd_soc_card *card;
struct acp3x_platform_info *pinfo;
+   struct i2s_dev_data *adata;
u64 size;
 
prtd = substream->private_data;
card = prtd->card;
pinfo = snd_soc_card_get_drvdata(card);
+   adata = dev_get_drvdata(component->dev);
rtd = substream->runtime->private_data;
if (!rtd)
return -EINVAL;
 
-   if (pinfo)
-   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+   if (pinfo) {
+   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
rtd->i2s_instance = pinfo->play_i2s_instance;
-   else
+   switch (rtd->i2s_instance) {
+   case I2S_BT_INSTANCE:
+   adata->play_stream = substream;
+   break;
+   case I2S_SP_INSTANCE:
+   default:
+   adata->i2ssp_play_stream = substream;
+   }
+   } else {
rtd->i2s_instance = pinfo->cap_i2s_instance;
-   else
+   switch (rtd->i2s_instance) {
+   case I2S_BT_INSTANCE:
+   adata->capture_stream = substream;
+   break;
+   case I2S_SP_INSTANCE:
+   default:
+   adata->i2ssp_capture_stream = substream;
+   }
+   }
+   } else {
pr_err("pinfo failed\n");
-
+   }
size = params_buffer_bytes(params);
rtd->dma_addr = substream->dma_buffer.addr;
rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
-- 
2.17.1



[PATCH] ASoC: amd :High hw_level while simultaneous capture

2020-05-05 Thread Akshu Agrawal
From: Ravulapati Vishnu vardhan rao 

Simultaneous capture on dmic and headset mic is having
issue with high hw_level being reported.

Issue Can be reproduced by:
arecord -D hw:2,0 -f dat -d 60 /tmp/test0 &
arecord -D hw:2,2 -f dat -d 60 /tmp/test1 &
cat /proc/asound/card2/pcm?c/sub0/status

Signed-off-by: Ravulapati Vishnu vardhan rao 

---
 sound/soc/amd/raven/acp3x-pcm-dma.c | 37 +++--
 1 file changed, 24 insertions(+), 13 deletions(-)

diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c 
b/sound/soc/amd/raven/acp3x-pcm-dma.c
index e362f0bc9e46..a36c5cb848cd 100644
--- a/sound/soc/amd/raven/acp3x-pcm-dma.c
+++ b/sound/soc/amd/raven/acp3x-pcm-dma.c
@@ -241,14 +241,6 @@ static int acp3x_dma_open(struct snd_soc_component 
*component,
adata->i2ssp_play_stream && !adata->i2ssp_capture_stream)
rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
 
-   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-   adata->play_stream = substream;
-   adata->i2ssp_play_stream = substream;
-   } else {
-   adata->capture_stream = substream;
-   adata->i2ssp_capture_stream = substream;
-   }
-
i2s_data->acp3x_base = adata->acp3x_base;
runtime->private_data = i2s_data;
return ret;
@@ -263,23 +255,42 @@ static int acp3x_dma_hw_params(struct snd_soc_component 
*component,
struct snd_soc_pcm_runtime *prtd;
struct snd_soc_card *card;
struct acp3x_platform_info *pinfo;
+   struct i2s_dev_data *adata;
u64 size;
 
prtd = substream->private_data;
card = prtd->card;
pinfo = snd_soc_card_get_drvdata(card);
+   adata = dev_get_drvdata(component->dev);
rtd = substream->runtime->private_data;
if (!rtd)
return -EINVAL;
 
-   if (pinfo)
-   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+   if (pinfo) {
+   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
rtd->i2s_instance = pinfo->play_i2s_instance;
-   else
+   switch (rtd->i2s_instance) {
+   case I2S_BT_INSTANCE:
+   adata->play_stream = substream;
+   break;
+   case I2S_SP_INSTANCE:
+   default:
+   adata->i2ssp_play_stream = substream;
+   }
+   } else {
rtd->i2s_instance = pinfo->cap_i2s_instance;
-   else
+   switch (rtd->i2s_instance) {
+   case I2S_BT_INSTANCE:
+   adata->capture_stream = substream;
+   break;
+   case I2S_SP_INSTANCE:
+   default:
+   adata->i2ssp_capture_stream = substream;
+   }
+   }
+   } else {
pr_err("pinfo failed\n");
-
+   }
size = params_buffer_bytes(params);
rtd->dma_addr = substream->dma_buffer.addr;
rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
-- 
2.17.1



[PATCH] ASoC: AMD: Add SND_JACK_LINEOUT jack type

2018-10-15 Thread Akshu Agrawal
Some 3 pole connectors report impedance greater than threshold of
1000Ohm. Thus, da7219 reports them as LINEOUT.
Adding the SND_JACK_LINEOUT type so that we don't fail to detect
any 3 pole jack type.
Also, changing
SND_JACK_HEADPHONE | SND_JACK_MICROPHONE -> SND_JACK_HEADSET

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-da7219-max98357a.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index 0d97d00698a0..eced4820b0bc 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -75,7 +75,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
da7219_dai_clk = clk_get(component->dev, "da7219-dai-clks");
 
ret = snd_soc_card_jack_new(card, "Headset Jack",
-   SND_JACK_HEADPHONE | SND_JACK_MICROPHONE |
+   SND_JACK_HEADSET | SND_JACK_LINEOUT |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
_jack, NULL, 0);
-- 
2.16.4



[PATCH] ASoC: AMD: Add SND_JACK_LINEOUT jack type

2018-10-15 Thread Akshu Agrawal
Some 3 pole connectors report impedance greater than threshold of
1000Ohm. Thus, da7219 reports them as LINEOUT.
Adding the SND_JACK_LINEOUT type so that we don't fail to detect
any 3 pole jack type.
Also, changing
SND_JACK_HEADPHONE | SND_JACK_MICROPHONE -> SND_JACK_HEADSET

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-da7219-max98357a.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index 0d97d00698a0..eced4820b0bc 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -75,7 +75,7 @@ static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
da7219_dai_clk = clk_get(component->dev, "da7219-dai-clks");
 
ret = snd_soc_card_jack_new(card, "Headset Jack",
-   SND_JACK_HEADPHONE | SND_JACK_MICROPHONE |
+   SND_JACK_HEADSET | SND_JACK_LINEOUT |
SND_JACK_BTN_0 | SND_JACK_BTN_1 |
SND_JACK_BTN_2 | SND_JACK_BTN_3,
_jack, NULL, 0);
-- 
2.16.4



[PATCH v2] ASoC: AMD: Fix capture unstable in beginning for some runs

2018-09-18 Thread Akshu Agrawal
alsa_conformance_test -C hw:0,4 -p 1024 --debug
would sometime show:
TIME_DIFF(s)HW_LEVEL   READ  RATE
0.95970 1024   102410670001.041992
0.042609555 1024   2048   24032.168372
0.021330364 1024   3072   48006.681930
0.021339559 1024   4096   47985.996337
The issue is that in dma pointer function we can have stale value
of the register for current descriptor of channel.
The register retains the number of the last descriptor that
was transferred.

Fix ensures that we report position, 0, till the one period worth of
data is transferred.  After one period of data, in handler of period
completion interrupt we update the config and correct value of descriptor
starts reflecting.

Signed-off-by: Akshu Agrawal 

---
v2: fix overrun issue and missed case where bytescount = rtd->bytescount
 sound/soc/amd/acp-pcm-dma.c | 22 ++
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index b0e245c..0ac4b5b 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -1035,16 +1035,22 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
 
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
period_bytes = frames_to_bytes(runtime, runtime->period_size);
-   dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr);
-   if (dscr == rtd->dma_dscr_idx_1)
-   pos = period_bytes;
-   else
-   pos = 0;
bytescount = acp_get_byte_count(rtd);
-   if (bytescount > rtd->bytescount)
+   if (bytescount >= rtd->bytescount)
bytescount -= rtd->bytescount;
-   delay = do_div(bytescount, period_bytes);
-   runtime->delay = bytes_to_frames(runtime, delay);
+   if (bytescount < period_bytes) {
+   pos = 0;
+   } else {
+   dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr);
+   if (dscr == rtd->dma_dscr_idx_1)
+   pos = period_bytes;
+   else
+   pos = 0;
+   }
+   if (bytescount > 0) {
+   delay = do_div(bytescount, period_bytes);
+   runtime->delay = bytes_to_frames(runtime, delay);
+   }
} else {
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
bytescount = acp_get_byte_count(rtd);
-- 
1.9.1



[PATCH v2] ASoC: AMD: Fix capture unstable in beginning for some runs

2018-09-18 Thread Akshu Agrawal
alsa_conformance_test -C hw:0,4 -p 1024 --debug
would sometime show:
TIME_DIFF(s)HW_LEVEL   READ  RATE
0.95970 1024   102410670001.041992
0.042609555 1024   2048   24032.168372
0.021330364 1024   3072   48006.681930
0.021339559 1024   4096   47985.996337
The issue is that in dma pointer function we can have stale value
of the register for current descriptor of channel.
The register retains the number of the last descriptor that
was transferred.

Fix ensures that we report position, 0, till the one period worth of
data is transferred.  After one period of data, in handler of period
completion interrupt we update the config and correct value of descriptor
starts reflecting.

Signed-off-by: Akshu Agrawal 

---
v2: fix overrun issue and missed case where bytescount = rtd->bytescount
 sound/soc/amd/acp-pcm-dma.c | 22 ++
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index b0e245c..0ac4b5b 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -1035,16 +1035,22 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
 
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
period_bytes = frames_to_bytes(runtime, runtime->period_size);
-   dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr);
-   if (dscr == rtd->dma_dscr_idx_1)
-   pos = period_bytes;
-   else
-   pos = 0;
bytescount = acp_get_byte_count(rtd);
-   if (bytescount > rtd->bytescount)
+   if (bytescount >= rtd->bytescount)
bytescount -= rtd->bytescount;
-   delay = do_div(bytescount, period_bytes);
-   runtime->delay = bytes_to_frames(runtime, delay);
+   if (bytescount < period_bytes) {
+   pos = 0;
+   } else {
+   dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr);
+   if (dscr == rtd->dma_dscr_idx_1)
+   pos = period_bytes;
+   else
+   pos = 0;
+   }
+   if (bytescount > 0) {
+   delay = do_div(bytescount, period_bytes);
+   runtime->delay = bytes_to_frames(runtime, delay);
+   }
} else {
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
bytescount = acp_get_byte_count(rtd);
-- 
1.9.1



[PATCH] ASoC: AMD: Fix capture unstable in beginning for some runs

2018-09-17 Thread Akshu Agrawal
alsa_conformance_test -C hw:0,4 -p 1024 --debug
would sometime show:
TIME_DIFF(s)HW_LEVEL   READ  RATE
0.95970 1024   102410670001.041992
0.042609555 1024   2048   24032.168372
0.021330364 1024   3072   48006.681930
0.021339559 1024   4096   47985.996337
The issue is that in dma pointer function we can have stale value
of the register for current descriptor of channel.
The register retains the number of the last descriptor that
was transferred.

Fix ensures that we report position, 0, till the one period worth of
data is transferred.  After one period of data, in handler of period
completion interrupt we update the config and correct value of descriptor
starts reflecting.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index c7e972b..f27e20c 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -1050,6 +1050,8 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
bytescount -= rtd->bytescount;
delay = do_div(bytescount, period_bytes);
runtime->delay = bytes_to_frames(runtime, delay);
+   if (bytescount < period_bytes)
+   pos = 0;
} else {
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
bytescount = acp_get_byte_count(rtd);
-- 
1.9.1



[PATCH] ASoC: AMD: Fix capture unstable in beginning for some runs

2018-09-17 Thread Akshu Agrawal
alsa_conformance_test -C hw:0,4 -p 1024 --debug
would sometime show:
TIME_DIFF(s)HW_LEVEL   READ  RATE
0.95970 1024   102410670001.041992
0.042609555 1024   2048   24032.168372
0.021330364 1024   3072   48006.681930
0.021339559 1024   4096   47985.996337
The issue is that in dma pointer function we can have stale value
of the register for current descriptor of channel.
The register retains the number of the last descriptor that
was transferred.

Fix ensures that we report position, 0, till the one period worth of
data is transferred.  After one period of data, in handler of period
completion interrupt we update the config and correct value of descriptor
starts reflecting.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index c7e972b..f27e20c 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -1050,6 +1050,8 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
bytescount -= rtd->bytescount;
delay = do_div(bytescount, period_bytes);
runtime->delay = bytes_to_frames(runtime, delay);
+   if (bytescount < period_bytes)
+   pos = 0;
} else {
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
bytescount = acp_get_byte_count(rtd);
-- 
1.9.1



[PATCH v2] ASoC: AMD: Fix simultaneous playback and capture on different channel

2018-09-10 Thread Akshu Agrawal
If capture and playback are started on different channel (I2S/BT)
there is a possibilty that channel information passed from machine driver
is overwritten before the configuration is done in dma driver.
Example:
113.597588: cz_max_startup: ---playback sets BT channel
113.597694: cz_dmic1_startup: ---capture sets I2S channel
113.597979: acp_dma_hw_params: ---configures capture for I2S channel
113.598114: acp_dma_hw_params: ---configures playback for I2S channel

This is fixed by having 2 separate instance for playback and capture.

Signed-off-by: Akshu Agrawal 

---
 sound/soc/amd/acp-da7219-max98357a.c | 40 +---
 sound/soc/amd/acp-pcm-dma.c  |  8 ++--
 sound/soc/amd/acp.h  |  3 ++-
 3 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index 55d7f61..0d97d00 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -133,7 +133,7 @@ static void da7219_clk_disable(void)
.mask = 0,
 };
 
-static int cz_da7219_startup(struct snd_pcm_substream *substream)
+static int cz_da7219_play_startup(struct snd_pcm_substream *substream)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -150,7 +150,28 @@ static int cz_da7219_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
-   machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->play_i2s_instance = I2S_SP_INSTANCE;
+   return da7219_clk_enable(substream);
+}
+
+static int cz_da7219_cap_startup(struct snd_pcm_substream *substream)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct snd_soc_card *card = rtd->card;
+   struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
+
+   /*
+* On this platform for PCM device we support stereo
+*/
+
+   runtime->hw.channels_max = DUAL_CHANNEL;
+   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+  _channels);
+   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+  _rates);
+
+   machine->cap_i2s_instance = I2S_SP_INSTANCE;
machine->capture_channel = CAP_CHANNEL1;
return da7219_clk_enable(substream);
 }
@@ -177,7 +198,7 @@ static int cz_max_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
-   machine->i2s_instance = I2S_BT_INSTANCE;
+   machine->play_i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
 }
 
@@ -203,7 +224,7 @@ static int cz_dmic0_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
-   machine->i2s_instance = I2S_BT_INSTANCE;
+   machine->cap_i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
 }
 
@@ -224,7 +245,7 @@ static int cz_dmic1_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
-   machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->cap_i2s_instance = I2S_SP_INSTANCE;
machine->capture_channel = CAP_CHANNEL0;
return da7219_clk_enable(substream);
 }
@@ -234,8 +255,13 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
da7219_clk_disable();
 }
 
+static const struct snd_soc_ops cz_da7219_play_ops = {
+   .startup = cz_da7219_play_startup,
+   .shutdown = cz_da7219_shutdown,
+};
+
 static const struct snd_soc_ops cz_da7219_cap_ops = {
-   .startup = cz_da7219_startup,
+   .startup = cz_da7219_cap_startup,
.shutdown = cz_da7219_shutdown,
 };
 
@@ -266,7 +292,7 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
| SND_SOC_DAIFMT_CBM_CFM,
.init = cz_da7219_init,
.dpcm_playback = 1,
-   .ops = _da7219_cap_ops,
+   .ops = _da7219_play_ops,
},
{
.name = "amd-da7219-cap",
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index b43f0a1..b0e245c 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -862,8 +862,12 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
return -EINVAL;
 
if (pinfo) {
-   rtd->i2s_instance = pinfo->i2s_instance;
-   rtd->capture_c

[PATCH v2] ASoC: AMD: Fix simultaneous playback and capture on different channel

2018-09-10 Thread Akshu Agrawal
If capture and playback are started on different channel (I2S/BT)
there is a possibilty that channel information passed from machine driver
is overwritten before the configuration is done in dma driver.
Example:
113.597588: cz_max_startup: ---playback sets BT channel
113.597694: cz_dmic1_startup: ---capture sets I2S channel
113.597979: acp_dma_hw_params: ---configures capture for I2S channel
113.598114: acp_dma_hw_params: ---configures playback for I2S channel

This is fixed by having 2 separate instance for playback and capture.

Signed-off-by: Akshu Agrawal 

---
 sound/soc/amd/acp-da7219-max98357a.c | 40 +---
 sound/soc/amd/acp-pcm-dma.c  |  8 ++--
 sound/soc/amd/acp.h  |  3 ++-
 3 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index 55d7f61..0d97d00 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -133,7 +133,7 @@ static void da7219_clk_disable(void)
.mask = 0,
 };
 
-static int cz_da7219_startup(struct snd_pcm_substream *substream)
+static int cz_da7219_play_startup(struct snd_pcm_substream *substream)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -150,7 +150,28 @@ static int cz_da7219_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
-   machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->play_i2s_instance = I2S_SP_INSTANCE;
+   return da7219_clk_enable(substream);
+}
+
+static int cz_da7219_cap_startup(struct snd_pcm_substream *substream)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct snd_soc_card *card = rtd->card;
+   struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
+
+   /*
+* On this platform for PCM device we support stereo
+*/
+
+   runtime->hw.channels_max = DUAL_CHANNEL;
+   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+  _channels);
+   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+  _rates);
+
+   machine->cap_i2s_instance = I2S_SP_INSTANCE;
machine->capture_channel = CAP_CHANNEL1;
return da7219_clk_enable(substream);
 }
@@ -177,7 +198,7 @@ static int cz_max_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
-   machine->i2s_instance = I2S_BT_INSTANCE;
+   machine->play_i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
 }
 
@@ -203,7 +224,7 @@ static int cz_dmic0_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
-   machine->i2s_instance = I2S_BT_INSTANCE;
+   machine->cap_i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
 }
 
@@ -224,7 +245,7 @@ static int cz_dmic1_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
-   machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->cap_i2s_instance = I2S_SP_INSTANCE;
machine->capture_channel = CAP_CHANNEL0;
return da7219_clk_enable(substream);
 }
@@ -234,8 +255,13 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
da7219_clk_disable();
 }
 
+static const struct snd_soc_ops cz_da7219_play_ops = {
+   .startup = cz_da7219_play_startup,
+   .shutdown = cz_da7219_shutdown,
+};
+
 static const struct snd_soc_ops cz_da7219_cap_ops = {
-   .startup = cz_da7219_startup,
+   .startup = cz_da7219_cap_startup,
.shutdown = cz_da7219_shutdown,
 };
 
@@ -266,7 +292,7 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
| SND_SOC_DAIFMT_CBM_CFM,
.init = cz_da7219_init,
.dpcm_playback = 1,
-   .ops = _da7219_cap_ops,
+   .ops = _da7219_play_ops,
},
{
.name = "amd-da7219-cap",
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index b43f0a1..b0e245c 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -862,8 +862,12 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
return -EINVAL;
 
if (pinfo) {
-   rtd->i2s_instance = pinfo->i2s_instance;
-   rtd->capture_c

[PATCH 1/2] ASoC: AMD: Fix simultaneous playback and capture on different channel

2018-09-10 Thread Akshu Agrawal
If capture and playback are started on different channel (I2S/BT)
there is a possibilty that channel information passed from machine driver
is overwritten before the configuration is done in dma driver.
Example:
113.597588: cz_max_startup: ---playback sets BT channel
113.597694: cz_dmic1_startup: ---capture sets I2S channel
113.597979: acp_dma_hw_params: ---configures capture for I2S channel
113.598114: acp_dma_hw_params: ---configures playback for I2S channel

This is fixed by having lock between startup and prepare. This ensures
no other codec startup gets called between a codec's startup(where channel
info is set) and hw_params(where channel info is read).

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-da7219-max98357a.c | 28 
 1 file changed, 28 insertions(+)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index 3879ccc..b98ffbc 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -47,6 +47,7 @@
 
 static struct snd_soc_jack cz_jack;
 static struct clk *da7219_dai_clk;
+static struct mutex instance_lock;
 extern int bt_uart_enable;
 
 static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
@@ -150,6 +151,7 @@ static int cz_da7219_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
+   mutex_lock(_lock);
machine->i2s_instance = I2S_SP_INSTANCE;
machine->capture_channel = CAP_CHANNEL1;
return da7219_clk_enable(substream);
@@ -160,6 +162,12 @@ static void cz_da7219_shutdown(struct snd_pcm_substream 
*substream)
da7219_clk_disable();
 }
 
+static int cz_da7219_prepare(struct snd_pcm_substream *substream)
+{
+   mutex_unlock(_lock);
+   return 0;
+}
+
 static int cz_max_startup(struct snd_pcm_substream *substream)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -177,6 +185,7 @@ static int cz_max_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
+   mutex_lock(_lock);
machine->i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
 }
@@ -186,6 +195,12 @@ static void cz_max_shutdown(struct snd_pcm_substream 
*substream)
da7219_clk_disable();
 }
 
+static int cz_max_prepare(struct snd_pcm_substream *substream)
+{
+   mutex_unlock(_lock);
+   return 0;
+}
+
 static int cz_dmic0_startup(struct snd_pcm_substream *substream)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -203,6 +218,7 @@ static int cz_dmic0_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
+   mutex_lock(_lock);
machine->i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
 }
@@ -224,6 +240,7 @@ static int cz_dmic1_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
+   mutex_lock(_lock);
machine->i2s_instance = I2S_SP_INSTANCE;
machine->capture_channel = CAP_CHANNEL0;
return da7219_clk_enable(substream);
@@ -234,24 +251,34 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
da7219_clk_disable();
 }
 
+static int cz_dmic_prepare(struct snd_pcm_substream *substream)
+{
+   mutex_unlock(_lock);
+   return 0;
+}
+
 static const struct snd_soc_ops cz_da7219_cap_ops = {
.startup = cz_da7219_startup,
.shutdown = cz_da7219_shutdown,
+   .prepare = cz_da7219_prepare,
 };
 
 static const struct snd_soc_ops cz_max_play_ops = {
.startup = cz_max_startup,
.shutdown = cz_max_shutdown,
+   .prepare = cz_max_prepare,
 };
 
 static const struct snd_soc_ops cz_dmic0_cap_ops = {
.startup = cz_dmic0_startup,
.shutdown = cz_dmic_shutdown,
+   .prepare = cz_dmic_prepare,
 };
 
 static const struct snd_soc_ops cz_dmic1_cap_ops = {
.startup = cz_dmic1_startup,
.shutdown = cz_dmic_shutdown,
+   .prepare = cz_dmic_prepare,
 };
 
 static struct snd_soc_dai_link cz_dai_7219_98357[] = {
@@ -409,6 +436,7 @@ static int cz_probe(struct platform_device *pdev)
card = _card;
cz_card.dev = >dev;
platform_set_drvdata(pdev, card);
+   mutex_init(_lock);
snd_soc_card_set_drvdata(card, machine);
ret = devm_snd_soc_register_card(>dev, _card);
if (ret) {
-- 
1.9.1



[PATCH 1/2] ASoC: AMD: Fix simultaneous playback and capture on different channel

2018-09-10 Thread Akshu Agrawal
If capture and playback are started on different channel (I2S/BT)
there is a possibilty that channel information passed from machine driver
is overwritten before the configuration is done in dma driver.
Example:
113.597588: cz_max_startup: ---playback sets BT channel
113.597694: cz_dmic1_startup: ---capture sets I2S channel
113.597979: acp_dma_hw_params: ---configures capture for I2S channel
113.598114: acp_dma_hw_params: ---configures playback for I2S channel

This is fixed by having lock between startup and prepare. This ensures
no other codec startup gets called between a codec's startup(where channel
info is set) and hw_params(where channel info is read).

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-da7219-max98357a.c | 28 
 1 file changed, 28 insertions(+)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index 3879ccc..b98ffbc 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -47,6 +47,7 @@
 
 static struct snd_soc_jack cz_jack;
 static struct clk *da7219_dai_clk;
+static struct mutex instance_lock;
 extern int bt_uart_enable;
 
 static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd)
@@ -150,6 +151,7 @@ static int cz_da7219_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
+   mutex_lock(_lock);
machine->i2s_instance = I2S_SP_INSTANCE;
machine->capture_channel = CAP_CHANNEL1;
return da7219_clk_enable(substream);
@@ -160,6 +162,12 @@ static void cz_da7219_shutdown(struct snd_pcm_substream 
*substream)
da7219_clk_disable();
 }
 
+static int cz_da7219_prepare(struct snd_pcm_substream *substream)
+{
+   mutex_unlock(_lock);
+   return 0;
+}
+
 static int cz_max_startup(struct snd_pcm_substream *substream)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -177,6 +185,7 @@ static int cz_max_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
+   mutex_lock(_lock);
machine->i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
 }
@@ -186,6 +195,12 @@ static void cz_max_shutdown(struct snd_pcm_substream 
*substream)
da7219_clk_disable();
 }
 
+static int cz_max_prepare(struct snd_pcm_substream *substream)
+{
+   mutex_unlock(_lock);
+   return 0;
+}
+
 static int cz_dmic0_startup(struct snd_pcm_substream *substream)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -203,6 +218,7 @@ static int cz_dmic0_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
+   mutex_lock(_lock);
machine->i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
 }
@@ -224,6 +240,7 @@ static int cz_dmic1_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
+   mutex_lock(_lock);
machine->i2s_instance = I2S_SP_INSTANCE;
machine->capture_channel = CAP_CHANNEL0;
return da7219_clk_enable(substream);
@@ -234,24 +251,34 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
da7219_clk_disable();
 }
 
+static int cz_dmic_prepare(struct snd_pcm_substream *substream)
+{
+   mutex_unlock(_lock);
+   return 0;
+}
+
 static const struct snd_soc_ops cz_da7219_cap_ops = {
.startup = cz_da7219_startup,
.shutdown = cz_da7219_shutdown,
+   .prepare = cz_da7219_prepare,
 };
 
 static const struct snd_soc_ops cz_max_play_ops = {
.startup = cz_max_startup,
.shutdown = cz_max_shutdown,
+   .prepare = cz_max_prepare,
 };
 
 static const struct snd_soc_ops cz_dmic0_cap_ops = {
.startup = cz_dmic0_startup,
.shutdown = cz_dmic_shutdown,
+   .prepare = cz_dmic_prepare,
 };
 
 static const struct snd_soc_ops cz_dmic1_cap_ops = {
.startup = cz_dmic1_startup,
.shutdown = cz_dmic_shutdown,
+   .prepare = cz_dmic_prepare,
 };
 
 static struct snd_soc_dai_link cz_dai_7219_98357[] = {
@@ -409,6 +436,7 @@ static int cz_probe(struct platform_device *pdev)
card = _card;
cz_card.dev = >dev;
platform_set_drvdata(pdev, card);
+   mutex_init(_lock);
snd_soc_card_set_drvdata(card, machine);
ret = devm_snd_soc_register_card(>dev, _card);
if (ret) {
-- 
1.9.1



[PATCH 2/2] ASoC: AMD: Ensure reset bit is cleared before configuring

2018-09-10 Thread Akshu Agrawal
HW register descriptions says:
"DMA Channel Reset...Software must confirm that this bit is
cleared before reprogramming any of the channel configuration registers."
There could be cases where dma stop errored out leaving dma channel
in reset state. We need to ensure that before the start of another dma,
channel is out of the reset state.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index e359938..77b265b 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -184,6 +185,24 @@ static void config_dma_descriptor_in_sram(void __iomem 
*acp_mmio,
acp_reg_write(descr_info->xfer_val, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
 }
 
+static void pre_config_reset(void __iomem *acp_mmio, u16 ch_num)
+{
+   u32 dma_ctrl;
+   int ret;
+
+   /* clear the reset bit */
+   dma_ctrl = acp_reg_read(acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
+   dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChRst_MASK;
+   acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
+   /* check the reset bit before programming configuration registers */
+   ret = readl_poll_timeout(acp_mmio + ((mmACP_DMA_CNTL_0 + ch_num) * 4),
+dma_ctrl,
+!(dma_ctrl & ACP_DMA_CNTL_0__DMAChRst_MASK),
+100, ACP_DMA_RESET_TIME);
+   if (ret < 0)
+   pr_err("Failed to clear reset of channel : %d\n", ch_num);
+}
+
 /*
  * Initialize the DMA descriptor information for transfer between
  * system memory <-> ACP SRAM
@@ -236,6 +255,7 @@ static void set_acp_sysmem_dma_descriptors(void __iomem 
*acp_mmio,
config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx,
  [i]);
}
+   pre_config_reset(acp_mmio, ch);
config_acp_dma_channel(acp_mmio, ch,
   dma_dscr_idx - 1,
   NUM_DSCRS_PER_CHANNEL,
@@ -275,6 +295,7 @@ static void set_acp_to_i2s_dma_descriptors(void __iomem 
*acp_mmio, u32 size,
config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx,
  [i]);
}
+   pre_config_reset(acp_mmio, ch);
/* Configure the DMA channel with the above descriptore */
config_acp_dma_channel(acp_mmio, ch, dma_dscr_idx - 1,
   NUM_DSCRS_PER_CHANNEL,
-- 
1.9.1



[PATCH 2/2] ASoC: AMD: Ensure reset bit is cleared before configuring

2018-09-10 Thread Akshu Agrawal
HW register descriptions says:
"DMA Channel Reset...Software must confirm that this bit is
cleared before reprogramming any of the channel configuration registers."
There could be cases where dma stop errored out leaving dma channel
in reset state. We need to ensure that before the start of another dma,
channel is out of the reset state.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index e359938..77b265b 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -184,6 +185,24 @@ static void config_dma_descriptor_in_sram(void __iomem 
*acp_mmio,
acp_reg_write(descr_info->xfer_val, acp_mmio, mmACP_SRBM_Targ_Idx_Data);
 }
 
+static void pre_config_reset(void __iomem *acp_mmio, u16 ch_num)
+{
+   u32 dma_ctrl;
+   int ret;
+
+   /* clear the reset bit */
+   dma_ctrl = acp_reg_read(acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
+   dma_ctrl &= ~ACP_DMA_CNTL_0__DMAChRst_MASK;
+   acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
+   /* check the reset bit before programming configuration registers */
+   ret = readl_poll_timeout(acp_mmio + ((mmACP_DMA_CNTL_0 + ch_num) * 4),
+dma_ctrl,
+!(dma_ctrl & ACP_DMA_CNTL_0__DMAChRst_MASK),
+100, ACP_DMA_RESET_TIME);
+   if (ret < 0)
+   pr_err("Failed to clear reset of channel : %d\n", ch_num);
+}
+
 /*
  * Initialize the DMA descriptor information for transfer between
  * system memory <-> ACP SRAM
@@ -236,6 +255,7 @@ static void set_acp_sysmem_dma_descriptors(void __iomem 
*acp_mmio,
config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx,
  [i]);
}
+   pre_config_reset(acp_mmio, ch);
config_acp_dma_channel(acp_mmio, ch,
   dma_dscr_idx - 1,
   NUM_DSCRS_PER_CHANNEL,
@@ -275,6 +295,7 @@ static void set_acp_to_i2s_dma_descriptors(void __iomem 
*acp_mmio, u32 size,
config_dma_descriptor_in_sram(acp_mmio, dma_dscr_idx,
  [i]);
}
+   pre_config_reset(acp_mmio, ch);
/* Configure the DMA channel with the above descriptore */
config_acp_dma_channel(acp_mmio, ch, dma_dscr_idx - 1,
   NUM_DSCRS_PER_CHANNEL,
-- 
1.9.1



[PATCH] ASoC: AMD: Change MCLK to 48Mhz

2018-08-21 Thread Akshu Agrawal
25Mhz MCLK which was earlier used was of spread type.
Thus, we were not getting accurate rate. The 48Mhz system
clk is of non-spread type and we are changing to it to get
accurate rate.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-da7219-max98357a.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index cf2f648..55d7f61 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -42,7 +42,7 @@
 #include "../codecs/da7219.h"
 #include "../codecs/da7219-aad.h"
 
-#define CZ_PLAT_CLK 2500
+#define CZ_PLAT_CLK 4800
 #define DUAL_CHANNEL   2
 
 static struct snd_soc_jack cz_jack;
-- 
1.9.1



[PATCH] ASoC: AMD: Change MCLK to 48Mhz

2018-08-21 Thread Akshu Agrawal
25Mhz MCLK which was earlier used was of spread type.
Thus, we were not getting accurate rate. The 48Mhz system
clk is of non-spread type and we are changing to it to get
accurate rate.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-da7219-max98357a.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index cf2f648..55d7f61 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -42,7 +42,7 @@
 #include "../codecs/da7219.h"
 #include "../codecs/da7219-aad.h"
 
-#define CZ_PLAT_CLK 2500
+#define CZ_PLAT_CLK 4800
 #define DUAL_CHANNEL   2
 
 static struct snd_soc_jack cz_jack;
-- 
1.9.1



[PATCH] ASoC: AMD: Set constraints for DMIC and MAX98357a codec

2018-08-21 Thread Akshu Agrawal
We support dual channel, 48Khz. This constraint was set only for
da7219. It is being extended to DMIC and MAX98357a.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-da7219-max98357a.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index 066d5489..cf2f648 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -162,10 +162,21 @@ static void cz_da7219_shutdown(struct snd_pcm_substream 
*substream)
 
 static int cz_max_startup(struct snd_pcm_substream *substream)
 {
+   struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
 
+   /*
+* On this platform for PCM device we support stereo
+*/
+
+   runtime->hw.channels_max = DUAL_CHANNEL;
+   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+  _channels);
+   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+  _rates);
+
machine->i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
 }
@@ -177,20 +188,42 @@ static void cz_max_shutdown(struct snd_pcm_substream 
*substream)
 
 static int cz_dmic0_startup(struct snd_pcm_substream *substream)
 {
+   struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
 
+   /*
+* On this platform for PCM device we support stereo
+*/
+
+   runtime->hw.channels_max = DUAL_CHANNEL;
+   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+  _channels);
+   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+  _rates);
+
machine->i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
 }
 
 static int cz_dmic1_startup(struct snd_pcm_substream *substream)
 {
+   struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
 
+   /*
+* On this platform for PCM device we support stereo
+*/
+
+   runtime->hw.channels_max = DUAL_CHANNEL;
+   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+  _channels);
+   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+  _rates);
+
machine->i2s_instance = I2S_SP_INSTANCE;
machine->capture_channel = CAP_CHANNEL0;
return da7219_clk_enable(substream);
-- 
1.9.1



[PATCH] ASoC: AMD: Set constraints for DMIC and MAX98357a codec

2018-08-21 Thread Akshu Agrawal
We support dual channel, 48Khz. This constraint was set only for
da7219. It is being extended to DMIC and MAX98357a.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-da7219-max98357a.c | 33 +
 1 file changed, 33 insertions(+)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index 066d5489..cf2f648 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -162,10 +162,21 @@ static void cz_da7219_shutdown(struct snd_pcm_substream 
*substream)
 
 static int cz_max_startup(struct snd_pcm_substream *substream)
 {
+   struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
 
+   /*
+* On this platform for PCM device we support stereo
+*/
+
+   runtime->hw.channels_max = DUAL_CHANNEL;
+   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+  _channels);
+   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+  _rates);
+
machine->i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
 }
@@ -177,20 +188,42 @@ static void cz_max_shutdown(struct snd_pcm_substream 
*substream)
 
 static int cz_dmic0_startup(struct snd_pcm_substream *substream)
 {
+   struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
 
+   /*
+* On this platform for PCM device we support stereo
+*/
+
+   runtime->hw.channels_max = DUAL_CHANNEL;
+   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+  _channels);
+   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+  _rates);
+
machine->i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
 }
 
 static int cz_dmic1_startup(struct snd_pcm_substream *substream)
 {
+   struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
 
+   /*
+* On this platform for PCM device we support stereo
+*/
+
+   runtime->hw.channels_max = DUAL_CHANNEL;
+   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
+  _channels);
+   snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
+  _rates);
+
machine->i2s_instance = I2S_SP_INSTANCE;
machine->capture_channel = CAP_CHANNEL0;
return da7219_clk_enable(substream);
-- 
1.9.1



[PATCH] clk: x86: Set default parent to 48Mhz

2018-08-21 Thread Akshu Agrawal
System clk provided in ST soc can be set to:
48Mhz, non-spread
25Mhz, spread
To get accurate rate, we need it to set it at non-spread
option which is 48Mhz.

Signed-off-by: Akshu Agrawal 
---
 drivers/clk/x86/clk-st.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/x86/clk-st.c b/drivers/clk/x86/clk-st.c
index fb62f39..3a0996f 100644
--- a/drivers/clk/x86/clk-st.c
+++ b/drivers/clk/x86/clk-st.c
@@ -46,7 +46,7 @@ static int st_clk_probe(struct platform_device *pdev)
clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
0, st_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
 
-   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_25M]->clk);
+   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
 
hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", "oscout1_mux",
0, st_data->base + MISCCLKCNTL1, OSCCLKENB,
-- 
1.9.1



[PATCH] clk: x86: Set default parent to 48Mhz

2018-08-21 Thread Akshu Agrawal
System clk provided in ST soc can be set to:
48Mhz, non-spread
25Mhz, spread
To get accurate rate, we need it to set it at non-spread
option which is 48Mhz.

Signed-off-by: Akshu Agrawal 
---
 drivers/clk/x86/clk-st.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/x86/clk-st.c b/drivers/clk/x86/clk-st.c
index fb62f39..3a0996f 100644
--- a/drivers/clk/x86/clk-st.c
+++ b/drivers/clk/x86/clk-st.c
@@ -46,7 +46,7 @@ static int st_clk_probe(struct platform_device *pdev)
clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
0, st_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
 
-   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_25M]->clk);
+   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_48M]->clk);
 
hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", "oscout1_mux",
0, st_data->base + MISCCLKCNTL1, OSCCLKENB,
-- 
1.9.1



[PATCH v2 3/3] ASoC: AMD: Set delay value for the capture case

2018-08-06 Thread Akshu Agrawal
ACP->SYSMEM DMA happens at every I2S->SYSMEM period
completion. Thus, there is delay of x frames till
I2S->SYSMEM reaches a period length. This delay is
communicated to user space.

Signed-off-by: Akshu Agrawal 
---
v2: moved reading of bytes transfered from I2S->ACP to get
more accurate delay information.
 sound/soc/amd/acp-pcm-dma.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 32f27c5..e359938 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -922,6 +922,10 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
rtd->destination = FROM_BLUETOOTH;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH10;
rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH11;
+   rtd->byte_cnt_high_reg_offset =
+   mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH;
+   rtd->byte_cnt_low_reg_offset =
+   mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW;
rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_11;
adata->capture_i2sbt_stream = substream;
break;
@@ -942,6 +946,10 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
rtd->destination = FROM_ACP_I2S_1;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH14;
rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH15;
+   rtd->byte_cnt_high_reg_offset =
+   mmACP_I2S_RECEIVED_BYTE_CNT_HIGH;
+   rtd->byte_cnt_low_reg_offset =
+   mmACP_I2S_RECEIVED_BYTE_CNT_LOW;
rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_15;
adata->capture_i2ssp_stream = substream;
}
@@ -997,7 +1005,7 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
u32 pos = 0;
u64 bytescount = 0;
u16 dscr;
-   u32 period_bytes;
+   u32 period_bytes, delay;
 
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
@@ -1012,6 +1020,11 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
pos = period_bytes;
else
pos = 0;
+   bytescount = acp_get_byte_count(rtd);
+   if (bytescount > rtd->bytescount)
+   bytescount -= rtd->bytescount;
+   delay = do_div(bytescount, period_bytes);
+   runtime->delay = bytes_to_frames(runtime, delay);
} else {
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
bytescount = acp_get_byte_count(rtd);
-- 
1.9.1



[PATCH v2 3/3] ASoC: AMD: Set delay value for the capture case

2018-08-06 Thread Akshu Agrawal
ACP->SYSMEM DMA happens at every I2S->SYSMEM period
completion. Thus, there is delay of x frames till
I2S->SYSMEM reaches a period length. This delay is
communicated to user space.

Signed-off-by: Akshu Agrawal 
---
v2: moved reading of bytes transfered from I2S->ACP to get
more accurate delay information.
 sound/soc/amd/acp-pcm-dma.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 32f27c5..e359938 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -922,6 +922,10 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
rtd->destination = FROM_BLUETOOTH;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH10;
rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH11;
+   rtd->byte_cnt_high_reg_offset =
+   mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH;
+   rtd->byte_cnt_low_reg_offset =
+   mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW;
rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_11;
adata->capture_i2sbt_stream = substream;
break;
@@ -942,6 +946,10 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
rtd->destination = FROM_ACP_I2S_1;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH14;
rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH15;
+   rtd->byte_cnt_high_reg_offset =
+   mmACP_I2S_RECEIVED_BYTE_CNT_HIGH;
+   rtd->byte_cnt_low_reg_offset =
+   mmACP_I2S_RECEIVED_BYTE_CNT_LOW;
rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_15;
adata->capture_i2ssp_stream = substream;
}
@@ -997,7 +1005,7 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
u32 pos = 0;
u64 bytescount = 0;
u16 dscr;
-   u32 period_bytes;
+   u32 period_bytes, delay;
 
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
@@ -1012,6 +1020,11 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
pos = period_bytes;
else
pos = 0;
+   bytescount = acp_get_byte_count(rtd);
+   if (bytescount > rtd->bytescount)
+   bytescount -= rtd->bytescount;
+   delay = do_div(bytescount, period_bytes);
+   runtime->delay = bytes_to_frames(runtime, delay);
} else {
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
bytescount = acp_get_byte_count(rtd);
-- 
1.9.1



[PATCH v2 2/3] ASoC: AMD: Modified DMA pointer for capture

2018-08-06 Thread Akshu Agrawal
From: "Mukunda, Vijendar" 

Give position on ACP->SYSMEM DMA channel for
the number of bytes that have been transferred on
the basis of current descriptor under service.

Signed-off-by: Vijendar Mukunda 
Signed-off-by: Akshu Agrawal 
---
v2: Fixed position, now position = 0 if on 1st descriptor and
pos = period_bytes if on second descriptor.
 sound/soc/amd/acp-pcm-dma.c | 31 ++-
 sound/soc/amd/acp.h |  1 +
 2 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 816abd6..32f27c5 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -922,10 +922,7 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
rtd->destination = FROM_BLUETOOTH;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH10;
rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH11;
-   rtd->byte_cnt_high_reg_offset =
-   mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH;
-   rtd->byte_cnt_low_reg_offset =
-   mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW;
+   rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_11;
adata->capture_i2sbt_stream = substream;
break;
case I2S_SP_INSTANCE:
@@ -945,10 +942,7 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
rtd->destination = FROM_ACP_I2S_1;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH14;
rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH15;
-   rtd->byte_cnt_high_reg_offset =
-   mmACP_I2S_RECEIVED_BYTE_CNT_HIGH;
-   rtd->byte_cnt_low_reg_offset =
-   mmACP_I2S_RECEIVED_BYTE_CNT_LOW;
+   rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_15;
adata->capture_i2ssp_stream = substream;
}
}
@@ -1002,6 +996,8 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
u32 buffersize;
u32 pos = 0;
u64 bytescount = 0;
+   u16 dscr;
+   u32 period_bytes;
 
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
@@ -1009,11 +1005,20 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
if (!rtd)
return -EINVAL;
 
-   buffersize = frames_to_bytes(runtime, runtime->buffer_size);
-   bytescount = acp_get_byte_count(rtd);
-
-   bytescount -= rtd->bytescount;
-   pos = do_div(bytescount, buffersize);
+   if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+   period_bytes = frames_to_bytes(runtime, runtime->period_size);
+   dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr);
+   if (dscr == rtd->dma_dscr_idx_1)
+   pos = period_bytes;
+   else
+   pos = 0;
+   } else {
+   buffersize = frames_to_bytes(runtime, runtime->buffer_size);
+   bytescount = acp_get_byte_count(rtd);
+   if (bytescount > rtd->bytescount)
+   bytescount -= rtd->bytescount;
+   pos = do_div(bytescount, buffersize);
+   }
return bytes_to_frames(runtime, pos);
 }
 
diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h
index 0a2240b..be3963e 100644
--- a/sound/soc/amd/acp.h
+++ b/sound/soc/amd/acp.h
@@ -138,6 +138,7 @@ struct audio_substream_data {
u32 sram_bank;
u32 byte_cnt_high_reg_offset;
u32 byte_cnt_low_reg_offset;
+   u32 dma_curr_dscr;
uint64_t size;
u64 bytescount;
void __iomem *acp_mmio;
-- 
1.9.1



[PATCH v2 2/3] ASoC: AMD: Modified DMA pointer for capture

2018-08-06 Thread Akshu Agrawal
From: "Mukunda, Vijendar" 

Give position on ACP->SYSMEM DMA channel for
the number of bytes that have been transferred on
the basis of current descriptor under service.

Signed-off-by: Vijendar Mukunda 
Signed-off-by: Akshu Agrawal 
---
v2: Fixed position, now position = 0 if on 1st descriptor and
pos = period_bytes if on second descriptor.
 sound/soc/amd/acp-pcm-dma.c | 31 ++-
 sound/soc/amd/acp.h |  1 +
 2 files changed, 19 insertions(+), 13 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 816abd6..32f27c5 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -922,10 +922,7 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
rtd->destination = FROM_BLUETOOTH;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH10;
rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH11;
-   rtd->byte_cnt_high_reg_offset =
-   mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH;
-   rtd->byte_cnt_low_reg_offset =
-   mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW;
+   rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_11;
adata->capture_i2sbt_stream = substream;
break;
case I2S_SP_INSTANCE:
@@ -945,10 +942,7 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
rtd->destination = FROM_ACP_I2S_1;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH14;
rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH15;
-   rtd->byte_cnt_high_reg_offset =
-   mmACP_I2S_RECEIVED_BYTE_CNT_HIGH;
-   rtd->byte_cnt_low_reg_offset =
-   mmACP_I2S_RECEIVED_BYTE_CNT_LOW;
+   rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_15;
adata->capture_i2ssp_stream = substream;
}
}
@@ -1002,6 +996,8 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
u32 buffersize;
u32 pos = 0;
u64 bytescount = 0;
+   u16 dscr;
+   u32 period_bytes;
 
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
@@ -1009,11 +1005,20 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
if (!rtd)
return -EINVAL;
 
-   buffersize = frames_to_bytes(runtime, runtime->buffer_size);
-   bytescount = acp_get_byte_count(rtd);
-
-   bytescount -= rtd->bytescount;
-   pos = do_div(bytescount, buffersize);
+   if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+   period_bytes = frames_to_bytes(runtime, runtime->period_size);
+   dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr);
+   if (dscr == rtd->dma_dscr_idx_1)
+   pos = period_bytes;
+   else
+   pos = 0;
+   } else {
+   buffersize = frames_to_bytes(runtime, runtime->buffer_size);
+   bytescount = acp_get_byte_count(rtd);
+   if (bytescount > rtd->bytescount)
+   bytescount -= rtd->bytescount;
+   pos = do_div(bytescount, buffersize);
+   }
return bytes_to_frames(runtime, pos);
 }
 
diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h
index 0a2240b..be3963e 100644
--- a/sound/soc/amd/acp.h
+++ b/sound/soc/amd/acp.h
@@ -138,6 +138,7 @@ struct audio_substream_data {
u32 sram_bank;
u32 byte_cnt_high_reg_offset;
u32 byte_cnt_low_reg_offset;
+   u32 dma_curr_dscr;
uint64_t size;
u64 bytescount;
void __iomem *acp_mmio;
-- 
1.9.1



[PATCH 1/3] ASoC: AMD: Make ACP->SYSMEM DMA non circular

2018-08-06 Thread Akshu Agrawal
In capture case we don't want ACP to SYSMEM dma
to be circular. This is because if an in place DSP
filter is applied to captured output then circular DMA
can overwrite the filter value with stale data.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 36 +++-
 1 file changed, 31 insertions(+), 5 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 94bcf69..816abd6 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -400,7 +400,7 @@ static void acp_dma_cap_channel_disable(void __iomem 
*acp_mmio,
 }
 
 /* Start a given DMA channel transfer */
-static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
+static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num, bool is_circular)
 {
u32 dma_ctrl;
 
@@ -429,8 +429,11 @@ static void acp_dma_start(void __iomem *acp_mmio, u16 
ch_num)
break;
}
 
-   /* circular for both DMA channel */
-   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
+   /* enable for ACP to SRAM DMA channel */
+   if (is_circular == true)
+   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
+   else
+   dma_ctrl &= ~ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
 
acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
 }
@@ -674,6 +677,7 @@ static int acp_deinit(void __iomem *acp_mmio)
 /* ACP DMA irq handler routine for playback, capture usecases */
 static irqreturn_t dma_irq_handler(int irq, void *arg)
 {
+   u16 dscr_idx;
u32 intr_flag, ext_intr_status;
struct audio_drv_data *irq_data;
void __iomem *acp_mmio;
@@ -705,6 +709,15 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
valid_irq = true;
+   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_14) ==
+   CAPTURE_START_DMA_DESCR_CH15)
+   dscr_idx = CAPTURE_END_DMA_DESCR_CH14;
+   else
+   dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
+   config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM, dscr_idx,
+  1, 0);
+   acp_dma_start(acp_mmio, ACP_TO_SYSRAM_CH_NUM, false);
+
snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
@@ -712,6 +725,17 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
+   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_10) ==
+   CAPTURE_START_DMA_DESCR_CH11)
+   dscr_idx = CAPTURE_END_DMA_DESCR_CH10;
+   else
+   dscr_idx = CAPTURE_START_DMA_DESCR_CH10;
+   config_acp_dma_channel(acp_mmio,
+  ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM,
+  dscr_idx, 1, 0);
+   acp_dma_start(acp_mmio, ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM,
+ false);
+
snd_pcm_period_elapsed(irq_data->capture_i2sbt_stream);
acp_reg_write((intr_flag &
  BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16,
@@ -1053,9 +1077,11 @@ static int acp_dma_trigger(struct snd_pcm_substream 
*substream, int cmd)
acp_dma_cap_channel_enable(rtd->acp_mmio,
   CAP_CHANNEL1);
}
+   acp_dma_start(rtd->acp_mmio, rtd->ch1, true);
+   } else {
+   acp_dma_start(rtd->acp_mmio, rtd->ch1, true);
+   acp_dma_start(rtd->acp_mmio, rtd->ch2, true);
}
-   acp_dma_start(rtd->acp_mmio, rtd->ch1);
-   acp_dma_start(rtd->acp_mmio, rtd->ch2);
ret = 0;
break;
case SNDRV_PCM_TRIGGER_STOP:
-- 
1.9.1



[PATCH 1/3] ASoC: AMD: Make ACP->SYSMEM DMA non circular

2018-08-06 Thread Akshu Agrawal
In capture case we don't want ACP to SYSMEM dma
to be circular. This is because if an in place DSP
filter is applied to captured output then circular DMA
can overwrite the filter value with stale data.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 36 +++-
 1 file changed, 31 insertions(+), 5 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 94bcf69..816abd6 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -400,7 +400,7 @@ static void acp_dma_cap_channel_disable(void __iomem 
*acp_mmio,
 }
 
 /* Start a given DMA channel transfer */
-static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
+static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num, bool is_circular)
 {
u32 dma_ctrl;
 
@@ -429,8 +429,11 @@ static void acp_dma_start(void __iomem *acp_mmio, u16 
ch_num)
break;
}
 
-   /* circular for both DMA channel */
-   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
+   /* enable for ACP to SRAM DMA channel */
+   if (is_circular == true)
+   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
+   else
+   dma_ctrl &= ~ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
 
acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
 }
@@ -674,6 +677,7 @@ static int acp_deinit(void __iomem *acp_mmio)
 /* ACP DMA irq handler routine for playback, capture usecases */
 static irqreturn_t dma_irq_handler(int irq, void *arg)
 {
+   u16 dscr_idx;
u32 intr_flag, ext_intr_status;
struct audio_drv_data *irq_data;
void __iomem *acp_mmio;
@@ -705,6 +709,15 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
valid_irq = true;
+   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_14) ==
+   CAPTURE_START_DMA_DESCR_CH15)
+   dscr_idx = CAPTURE_END_DMA_DESCR_CH14;
+   else
+   dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
+   config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM, dscr_idx,
+  1, 0);
+   acp_dma_start(acp_mmio, ACP_TO_SYSRAM_CH_NUM, false);
+
snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
@@ -712,6 +725,17 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
+   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_10) ==
+   CAPTURE_START_DMA_DESCR_CH11)
+   dscr_idx = CAPTURE_END_DMA_DESCR_CH10;
+   else
+   dscr_idx = CAPTURE_START_DMA_DESCR_CH10;
+   config_acp_dma_channel(acp_mmio,
+  ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM,
+  dscr_idx, 1, 0);
+   acp_dma_start(acp_mmio, ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM,
+ false);
+
snd_pcm_period_elapsed(irq_data->capture_i2sbt_stream);
acp_reg_write((intr_flag &
  BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16,
@@ -1053,9 +1077,11 @@ static int acp_dma_trigger(struct snd_pcm_substream 
*substream, int cmd)
acp_dma_cap_channel_enable(rtd->acp_mmio,
   CAP_CHANNEL1);
}
+   acp_dma_start(rtd->acp_mmio, rtd->ch1, true);
+   } else {
+   acp_dma_start(rtd->acp_mmio, rtd->ch1, true);
+   acp_dma_start(rtd->acp_mmio, rtd->ch2, true);
}
-   acp_dma_start(rtd->acp_mmio, rtd->ch1);
-   acp_dma_start(rtd->acp_mmio, rtd->ch2);
ret = 0;
break;
case SNDRV_PCM_TRIGGER_STOP:
-- 
1.9.1



[PATCH 1/3] ASoC: AMD: Make ACP->SYSMEM DMA non circular

2018-08-02 Thread Akshu Agrawal
In capture case we don't want ACP to SYSMEM dma
to be circular. This is because if an in place DSP
filter is applied to captured output then circular DMA
can overwrite the filter value with stale data.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 36 +++-
 1 file changed, 31 insertions(+), 5 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 94bcf69..816abd6 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -400,7 +400,7 @@ static void acp_dma_cap_channel_disable(void __iomem 
*acp_mmio,
 }
 
 /* Start a given DMA channel transfer */
-static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
+static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num, bool is_circular)
 {
u32 dma_ctrl;
 
@@ -429,8 +429,11 @@ static void acp_dma_start(void __iomem *acp_mmio, u16 
ch_num)
break;
}
 
-   /* circular for both DMA channel */
-   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
+   /* enable for ACP to SRAM DMA channel */
+   if (is_circular == true)
+   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
+   else
+   dma_ctrl &= ~ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
 
acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
 }
@@ -674,6 +677,7 @@ static int acp_deinit(void __iomem *acp_mmio)
 /* ACP DMA irq handler routine for playback, capture usecases */
 static irqreturn_t dma_irq_handler(int irq, void *arg)
 {
+   u16 dscr_idx;
u32 intr_flag, ext_intr_status;
struct audio_drv_data *irq_data;
void __iomem *acp_mmio;
@@ -705,6 +709,15 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
valid_irq = true;
+   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_14) ==
+   CAPTURE_START_DMA_DESCR_CH15)
+   dscr_idx = CAPTURE_END_DMA_DESCR_CH14;
+   else
+   dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
+   config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM, dscr_idx,
+  1, 0);
+   acp_dma_start(acp_mmio, ACP_TO_SYSRAM_CH_NUM, false);
+
snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
@@ -712,6 +725,17 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
+   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_10) ==
+   CAPTURE_START_DMA_DESCR_CH11)
+   dscr_idx = CAPTURE_END_DMA_DESCR_CH10;
+   else
+   dscr_idx = CAPTURE_START_DMA_DESCR_CH10;
+   config_acp_dma_channel(acp_mmio,
+  ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM,
+  dscr_idx, 1, 0);
+   acp_dma_start(acp_mmio, ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM,
+ false);
+
snd_pcm_period_elapsed(irq_data->capture_i2sbt_stream);
acp_reg_write((intr_flag &
  BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16,
@@ -1053,9 +1077,11 @@ static int acp_dma_trigger(struct snd_pcm_substream 
*substream, int cmd)
acp_dma_cap_channel_enable(rtd->acp_mmio,
   CAP_CHANNEL1);
}
+   acp_dma_start(rtd->acp_mmio, rtd->ch1, true);
+   } else {
+   acp_dma_start(rtd->acp_mmio, rtd->ch1, true);
+   acp_dma_start(rtd->acp_mmio, rtd->ch2, true);
}
-   acp_dma_start(rtd->acp_mmio, rtd->ch1);
-   acp_dma_start(rtd->acp_mmio, rtd->ch2);
ret = 0;
break;
case SNDRV_PCM_TRIGGER_STOP:
-- 
1.9.1



[PATCH 1/3] ASoC: AMD: Make ACP->SYSMEM DMA non circular

2018-08-02 Thread Akshu Agrawal
In capture case we don't want ACP to SYSMEM dma
to be circular. This is because if an in place DSP
filter is applied to captured output then circular DMA
can overwrite the filter value with stale data.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 36 +++-
 1 file changed, 31 insertions(+), 5 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 94bcf69..816abd6 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -400,7 +400,7 @@ static void acp_dma_cap_channel_disable(void __iomem 
*acp_mmio,
 }
 
 /* Start a given DMA channel transfer */
-static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
+static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num, bool is_circular)
 {
u32 dma_ctrl;
 
@@ -429,8 +429,11 @@ static void acp_dma_start(void __iomem *acp_mmio, u16 
ch_num)
break;
}
 
-   /* circular for both DMA channel */
-   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
+   /* enable for ACP to SRAM DMA channel */
+   if (is_circular == true)
+   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
+   else
+   dma_ctrl &= ~ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
 
acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
 }
@@ -674,6 +677,7 @@ static int acp_deinit(void __iomem *acp_mmio)
 /* ACP DMA irq handler routine for playback, capture usecases */
 static irqreturn_t dma_irq_handler(int irq, void *arg)
 {
+   u16 dscr_idx;
u32 intr_flag, ext_intr_status;
struct audio_drv_data *irq_data;
void __iomem *acp_mmio;
@@ -705,6 +709,15 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
valid_irq = true;
+   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_14) ==
+   CAPTURE_START_DMA_DESCR_CH15)
+   dscr_idx = CAPTURE_END_DMA_DESCR_CH14;
+   else
+   dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
+   config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM, dscr_idx,
+  1, 0);
+   acp_dma_start(acp_mmio, ACP_TO_SYSRAM_CH_NUM, false);
+
snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
@@ -712,6 +725,17 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
+   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_10) ==
+   CAPTURE_START_DMA_DESCR_CH11)
+   dscr_idx = CAPTURE_END_DMA_DESCR_CH10;
+   else
+   dscr_idx = CAPTURE_START_DMA_DESCR_CH10;
+   config_acp_dma_channel(acp_mmio,
+  ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM,
+  dscr_idx, 1, 0);
+   acp_dma_start(acp_mmio, ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM,
+ false);
+
snd_pcm_period_elapsed(irq_data->capture_i2sbt_stream);
acp_reg_write((intr_flag &
  BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16,
@@ -1053,9 +1077,11 @@ static int acp_dma_trigger(struct snd_pcm_substream 
*substream, int cmd)
acp_dma_cap_channel_enable(rtd->acp_mmio,
   CAP_CHANNEL1);
}
+   acp_dma_start(rtd->acp_mmio, rtd->ch1, true);
+   } else {
+   acp_dma_start(rtd->acp_mmio, rtd->ch1, true);
+   acp_dma_start(rtd->acp_mmio, rtd->ch2, true);
}
-   acp_dma_start(rtd->acp_mmio, rtd->ch1);
-   acp_dma_start(rtd->acp_mmio, rtd->ch2);
ret = 0;
break;
case SNDRV_PCM_TRIGGER_STOP:
-- 
1.9.1



[PATCH 3/3] ASoC: AMD: Set delay value for the capture case

2018-08-02 Thread Akshu Agrawal
ACP->SYSMEM DMA happens at every I2S->SYSMEM period
completion. Thus, there is delay of x frames till
I2S->SYSMEM reaches a period length. This delay is
communicated to user space.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 19 +++
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 6240a77..c24611c 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -922,6 +922,10 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
rtd->destination = FROM_BLUETOOTH;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH10;
rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH11;
+   rtd->byte_cnt_high_reg_offset =
+   mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH;
+   rtd->byte_cnt_low_reg_offset =
+   mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW;
rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_11;
rtd->cur_trans_cnt = mmACP_DMA_CUR_TRANS_CNT_11;
rtd->end_dma_dscr = CAPTURE_END_DMA_DESCR_CH10;
@@ -944,6 +948,10 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
rtd->destination = FROM_ACP_I2S_1;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH14;
rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH15;
+   rtd->byte_cnt_high_reg_offset =
+   mmACP_I2S_RECEIVED_BYTE_CNT_HIGH;
+   rtd->byte_cnt_low_reg_offset =
+   mmACP_I2S_RECEIVED_BYTE_CNT_LOW;
rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_15;
rtd->cur_trans_cnt = mmACP_DMA_CUR_TRANS_CNT_15;
rtd->end_dma_dscr = CAPTURE_END_DMA_DESCR_CH14;
@@ -1002,7 +1010,7 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
u64 bytescount = 0;
u32 dma_count = 0;
u16 dscr;
-   u32 period_bytes;
+   u32 period_bytes, delay;
 
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
@@ -1011,6 +1019,10 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
return -EINVAL;
 
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
+   bytescount = acp_get_byte_count(rtd);
+   if (bytescount > rtd->bytescount)
+   bytescount -= rtd->bytescount;
+
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
period_bytes = frames_to_bytes(runtime, runtime->period_size);
dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr);
@@ -1018,10 +1030,9 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
if (dscr == rtd->end_dma_dscr)
dma_count += period_bytes;
pos = dma_count % buffersize;
+   delay = do_div(bytescount, period_bytes);
+   runtime->delay = bytes_to_frames(runtime, delay);
} else {
-   bytescount = acp_get_byte_count(rtd);
-   if (bytescount > rtd->bytescount)
-   bytescount -= rtd->bytescount;
pos = do_div(bytescount, buffersize);
}
return bytes_to_frames(runtime, pos);
-- 
1.9.1



[PATCH 2/3] ASoC: AMD: Modified DMA pointer for capture

2018-08-02 Thread Akshu Agrawal
From: "Mukunda, Vijendar" 

Give position on ACP->SYSMEM DMA channel for
the number of bytes that have been transferred on
the current descriptor under service.

Signed-off-by: Vijendar Mukunda 
Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 34 ++
 sound/soc/amd/acp.h |  3 +++
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 816abd6..6240a77 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -922,10 +922,9 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
rtd->destination = FROM_BLUETOOTH;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH10;
rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH11;
-   rtd->byte_cnt_high_reg_offset =
-   mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH;
-   rtd->byte_cnt_low_reg_offset =
-   mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW;
+   rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_11;
+   rtd->cur_trans_cnt = mmACP_DMA_CUR_TRANS_CNT_11;
+   rtd->end_dma_dscr = CAPTURE_END_DMA_DESCR_CH10;
adata->capture_i2sbt_stream = substream;
break;
case I2S_SP_INSTANCE:
@@ -945,10 +944,9 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
rtd->destination = FROM_ACP_I2S_1;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH14;
rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH15;
-   rtd->byte_cnt_high_reg_offset =
-   mmACP_I2S_RECEIVED_BYTE_CNT_HIGH;
-   rtd->byte_cnt_low_reg_offset =
-   mmACP_I2S_RECEIVED_BYTE_CNT_LOW;
+   rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_15;
+   rtd->cur_trans_cnt = mmACP_DMA_CUR_TRANS_CNT_15;
+   rtd->end_dma_dscr = CAPTURE_END_DMA_DESCR_CH14;
adata->capture_i2ssp_stream = substream;
}
}
@@ -1002,6 +1000,9 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
u32 buffersize;
u32 pos = 0;
u64 bytescount = 0;
+   u32 dma_count = 0;
+   u16 dscr;
+   u32 period_bytes;
 
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
@@ -1010,10 +1011,19 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
return -EINVAL;
 
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
-   bytescount = acp_get_byte_count(rtd);
-
-   bytescount -= rtd->bytescount;
-   pos = do_div(bytescount, buffersize);
+   if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+   period_bytes = frames_to_bytes(runtime, runtime->period_size);
+   dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr);
+   dma_count = acp_reg_read(rtd->acp_mmio, rtd->cur_trans_cnt);
+   if (dscr == rtd->end_dma_dscr)
+   dma_count += period_bytes;
+   pos = dma_count % buffersize;
+   } else {
+   bytescount = acp_get_byte_count(rtd);
+   if (bytescount > rtd->bytescount)
+   bytescount -= rtd->bytescount;
+   pos = do_div(bytescount, buffersize);
+   }
return bytes_to_frames(runtime, pos);
 }
 
diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h
index 0a2240b..cf7c0b9 100644
--- a/sound/soc/amd/acp.h
+++ b/sound/soc/amd/acp.h
@@ -134,10 +134,13 @@ struct audio_substream_data {
u16 destination;
u16 dma_dscr_idx_1;
u16 dma_dscr_idx_2;
+   u16 end_dma_dscr;
u32 pte_offset;
u32 sram_bank;
u32 byte_cnt_high_reg_offset;
u32 byte_cnt_low_reg_offset;
+   u32 dma_curr_dscr;
+   u32 cur_trans_cnt;
uint64_t size;
u64 bytescount;
void __iomem *acp_mmio;
-- 
1.9.1



[PATCH 2/3] ASoC: AMD: Modified DMA pointer for capture

2018-08-02 Thread Akshu Agrawal
From: "Mukunda, Vijendar" 

Give position on ACP->SYSMEM DMA channel for
the number of bytes that have been transferred on
the current descriptor under service.

Signed-off-by: Vijendar Mukunda 
Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 34 ++
 sound/soc/amd/acp.h |  3 +++
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 816abd6..6240a77 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -922,10 +922,9 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
rtd->destination = FROM_BLUETOOTH;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH10;
rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH11;
-   rtd->byte_cnt_high_reg_offset =
-   mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH;
-   rtd->byte_cnt_low_reg_offset =
-   mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW;
+   rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_11;
+   rtd->cur_trans_cnt = mmACP_DMA_CUR_TRANS_CNT_11;
+   rtd->end_dma_dscr = CAPTURE_END_DMA_DESCR_CH10;
adata->capture_i2sbt_stream = substream;
break;
case I2S_SP_INSTANCE:
@@ -945,10 +944,9 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
rtd->destination = FROM_ACP_I2S_1;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH14;
rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH15;
-   rtd->byte_cnt_high_reg_offset =
-   mmACP_I2S_RECEIVED_BYTE_CNT_HIGH;
-   rtd->byte_cnt_low_reg_offset =
-   mmACP_I2S_RECEIVED_BYTE_CNT_LOW;
+   rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_15;
+   rtd->cur_trans_cnt = mmACP_DMA_CUR_TRANS_CNT_15;
+   rtd->end_dma_dscr = CAPTURE_END_DMA_DESCR_CH14;
adata->capture_i2ssp_stream = substream;
}
}
@@ -1002,6 +1000,9 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
u32 buffersize;
u32 pos = 0;
u64 bytescount = 0;
+   u32 dma_count = 0;
+   u16 dscr;
+   u32 period_bytes;
 
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
@@ -1010,10 +1011,19 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
return -EINVAL;
 
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
-   bytescount = acp_get_byte_count(rtd);
-
-   bytescount -= rtd->bytescount;
-   pos = do_div(bytescount, buffersize);
+   if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+   period_bytes = frames_to_bytes(runtime, runtime->period_size);
+   dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr);
+   dma_count = acp_reg_read(rtd->acp_mmio, rtd->cur_trans_cnt);
+   if (dscr == rtd->end_dma_dscr)
+   dma_count += period_bytes;
+   pos = dma_count % buffersize;
+   } else {
+   bytescount = acp_get_byte_count(rtd);
+   if (bytescount > rtd->bytescount)
+   bytescount -= rtd->bytescount;
+   pos = do_div(bytescount, buffersize);
+   }
return bytes_to_frames(runtime, pos);
 }
 
diff --git a/sound/soc/amd/acp.h b/sound/soc/amd/acp.h
index 0a2240b..cf7c0b9 100644
--- a/sound/soc/amd/acp.h
+++ b/sound/soc/amd/acp.h
@@ -134,10 +134,13 @@ struct audio_substream_data {
u16 destination;
u16 dma_dscr_idx_1;
u16 dma_dscr_idx_2;
+   u16 end_dma_dscr;
u32 pte_offset;
u32 sram_bank;
u32 byte_cnt_high_reg_offset;
u32 byte_cnt_low_reg_offset;
+   u32 dma_curr_dscr;
+   u32 cur_trans_cnt;
uint64_t size;
u64 bytescount;
void __iomem *acp_mmio;
-- 
1.9.1



[PATCH 3/3] ASoC: AMD: Set delay value for the capture case

2018-08-02 Thread Akshu Agrawal
ACP->SYSMEM DMA happens at every I2S->SYSMEM period
completion. Thus, there is delay of x frames till
I2S->SYSMEM reaches a period length. This delay is
communicated to user space.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 19 +++
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 6240a77..c24611c 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -922,6 +922,10 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
rtd->destination = FROM_BLUETOOTH;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH10;
rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH11;
+   rtd->byte_cnt_high_reg_offset =
+   mmACP_I2S_BT_RECEIVE_BYTE_CNT_HIGH;
+   rtd->byte_cnt_low_reg_offset =
+   mmACP_I2S_BT_RECEIVE_BYTE_CNT_LOW;
rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_11;
rtd->cur_trans_cnt = mmACP_DMA_CUR_TRANS_CNT_11;
rtd->end_dma_dscr = CAPTURE_END_DMA_DESCR_CH10;
@@ -944,6 +948,10 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
rtd->destination = FROM_ACP_I2S_1;
rtd->dma_dscr_idx_1 = CAPTURE_START_DMA_DESCR_CH14;
rtd->dma_dscr_idx_2 = CAPTURE_START_DMA_DESCR_CH15;
+   rtd->byte_cnt_high_reg_offset =
+   mmACP_I2S_RECEIVED_BYTE_CNT_HIGH;
+   rtd->byte_cnt_low_reg_offset =
+   mmACP_I2S_RECEIVED_BYTE_CNT_LOW;
rtd->dma_curr_dscr = mmACP_DMA_CUR_DSCR_15;
rtd->cur_trans_cnt = mmACP_DMA_CUR_TRANS_CNT_15;
rtd->end_dma_dscr = CAPTURE_END_DMA_DESCR_CH14;
@@ -1002,7 +1010,7 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
u64 bytescount = 0;
u32 dma_count = 0;
u16 dscr;
-   u32 period_bytes;
+   u32 period_bytes, delay;
 
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
@@ -1011,6 +1019,10 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
return -EINVAL;
 
buffersize = frames_to_bytes(runtime, runtime->buffer_size);
+   bytescount = acp_get_byte_count(rtd);
+   if (bytescount > rtd->bytescount)
+   bytescount -= rtd->bytescount;
+
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
period_bytes = frames_to_bytes(runtime, runtime->period_size);
dscr = acp_reg_read(rtd->acp_mmio, rtd->dma_curr_dscr);
@@ -1018,10 +1030,9 @@ static snd_pcm_uframes_t acp_dma_pointer(struct 
snd_pcm_substream *substream)
if (dscr == rtd->end_dma_dscr)
dma_count += period_bytes;
pos = dma_count % buffersize;
+   delay = do_div(bytescount, period_bytes);
+   runtime->delay = bytes_to_frames(runtime, delay);
} else {
-   bytescount = acp_get_byte_count(rtd);
-   if (bytescount > rtd->bytescount)
-   bytescount -= rtd->bytescount;
pos = do_div(bytescount, buffersize);
}
return bytes_to_frames(runtime, pos);
-- 
1.9.1



[PATCH v2] ASoC: soc-pcm: Use delay set in component pointer function

2018-08-01 Thread Akshu Agrawal
Take into account the base delay set in pointer callback.

There are cases where a pointer function populates
runtime->delay, such as:
./sound/pci/hda/hda_controller.c
./sound/soc/intel/atom/sst-mfld-platform-pcm.c

This delay was getting lost and was overwritten by delays
from codec or cpu dai delay function if exposed.

Now,
Total delay = base delay + cpu_dai delay + codec_dai delay

Signed-off-by: Akshu Agrawal 
---
 sound/soc/soc-pcm.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 98be04b..e8b98bfd 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1179,6 +1179,9 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct 
snd_pcm_substream *substream)
snd_pcm_sframes_t codec_delay = 0;
int i;
 
+   /* clearing the previous total delay */
+   runtime->delay = 0;
+
for_each_rtdcom(rtd, rtdcom) {
component = rtdcom->component;
 
@@ -1190,6 +1193,8 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct 
snd_pcm_substream *substream)
offset = component->driver->ops->pointer(substream);
break;
}
+   /* base delay if assigned in pointer callback */
+   delay = runtime->delay;
 
if (cpu_dai->driver->ops->delay)
delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
-- 
1.9.1



[PATCH v2] ASoC: soc-pcm: Use delay set in component pointer function

2018-08-01 Thread Akshu Agrawal
Take into account the base delay set in pointer callback.

There are cases where a pointer function populates
runtime->delay, such as:
./sound/pci/hda/hda_controller.c
./sound/soc/intel/atom/sst-mfld-platform-pcm.c

This delay was getting lost and was overwritten by delays
from codec or cpu dai delay function if exposed.

Now,
Total delay = base delay + cpu_dai delay + codec_dai delay

Signed-off-by: Akshu Agrawal 
---
 sound/soc/soc-pcm.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 98be04b..e8b98bfd 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1179,6 +1179,9 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct 
snd_pcm_substream *substream)
snd_pcm_sframes_t codec_delay = 0;
int i;
 
+   /* clearing the previous total delay */
+   runtime->delay = 0;
+
for_each_rtdcom(rtd, rtdcom) {
component = rtdcom->component;
 
@@ -1190,6 +1193,8 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct 
snd_pcm_substream *substream)
offset = component->driver->ops->pointer(substream);
break;
}
+   /* base delay if assigned in pointer callback */
+   delay = runtime->delay;
 
if (cpu_dai->driver->ops->delay)
delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
-- 
1.9.1



[PATCH] ASoC: soc-pcm: Use delay set in pointer function

2018-07-27 Thread Akshu Agrawal
There are cases where a pointer function populates
runtime->delay, such as:
./sound/pci/hda/hda_controller.c
./sound/soc/intel/atom/sst-mfld-platform-pcm.c

Also, in some cases cpu dai used is generic and the pcm
driver needs to set delay.

This delay was getting lost and was overwritten by delays
from codec or cpu dai delay function if exposed.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/soc-pcm.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 98be04b..b1a2bc2 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1179,6 +1179,9 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct 
snd_pcm_substream *substream)
snd_pcm_sframes_t codec_delay = 0;
int i;
 
+   /* clearing the previous delay */
+   runtime->delay = 0;
+
for_each_rtdcom(rtd, rtdcom) {
component = rtdcom->component;
 
@@ -1203,7 +1206,7 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct 
snd_pcm_substream *substream)
}
delay += codec_delay;
 
-   runtime->delay = delay;
+   runtime->delay += delay;
 
return offset;
 }
-- 
1.9.1



[PATCH] ASoC: soc-pcm: Use delay set in pointer function

2018-07-27 Thread Akshu Agrawal
There are cases where a pointer function populates
runtime->delay, such as:
./sound/pci/hda/hda_controller.c
./sound/soc/intel/atom/sst-mfld-platform-pcm.c

Also, in some cases cpu dai used is generic and the pcm
driver needs to set delay.

This delay was getting lost and was overwritten by delays
from codec or cpu dai delay function if exposed.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/soc-pcm.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 98be04b..b1a2bc2 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1179,6 +1179,9 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct 
snd_pcm_substream *substream)
snd_pcm_sframes_t codec_delay = 0;
int i;
 
+   /* clearing the previous delay */
+   runtime->delay = 0;
+
for_each_rtdcom(rtd, rtdcom) {
component = rtdcom->component;
 
@@ -1203,7 +1206,7 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct 
snd_pcm_substream *substream)
}
delay += codec_delay;
 
-   runtime->delay = delay;
+   runtime->delay += delay;
 
return offset;
 }
-- 
1.9.1



[PATCH v2] ASoC: AMD: Fix build warning

2018-07-26 Thread Akshu Agrawal
Fixes
sound/soc/amd/acp-da7219-max98357a.c: In function 'cz_probe':
sound/soc/amd/acp-da7219-max98357a.c:367:3: warning: 'ret' may
be used uninitialized in this function [-Wmaybe-uninitialized]
   dev_err(>dev, "Failed to register regulator: %d\n",
ret);

Signed-off-by: Akshu Agrawal 
---
v2: closing braces missing
 sound/soc/amd/acp-da7219-max98357a.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index cd3cf6e..8e3275a 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -365,7 +365,7 @@ static int cz_probe(struct platform_device *pdev)
   _da7219_cfg);
if (IS_ERR(rdev)) {
dev_err(>dev, "Failed to register regulator: %d\n",
-   ret);
+   (int)PTR_ERR(rdev));
return -EINVAL;
}
 
-- 
1.9.1



[PATCH v2] ASoC: AMD: Fix build warning

2018-07-26 Thread Akshu Agrawal
Fixes
sound/soc/amd/acp-da7219-max98357a.c: In function 'cz_probe':
sound/soc/amd/acp-da7219-max98357a.c:367:3: warning: 'ret' may
be used uninitialized in this function [-Wmaybe-uninitialized]
   dev_err(>dev, "Failed to register regulator: %d\n",
ret);

Signed-off-by: Akshu Agrawal 
---
v2: closing braces missing
 sound/soc/amd/acp-da7219-max98357a.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index cd3cf6e..8e3275a 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -365,7 +365,7 @@ static int cz_probe(struct platform_device *pdev)
   _da7219_cfg);
if (IS_ERR(rdev)) {
dev_err(>dev, "Failed to register regulator: %d\n",
-   ret);
+   (int)PTR_ERR(rdev));
return -EINVAL;
}
 
-- 
1.9.1



[PATCH] ASoC: AMD: Fix build warning

2018-07-25 Thread Akshu Agrawal
Fixes
sound/soc/amd/acp-da7219-max98357a.c: In function 'cz_probe':
sound/soc/amd/acp-da7219-max98357a.c:367:3: warning: 'ret' may
be used uninitialized in this function [-Wmaybe-uninitialized]
   dev_err(>dev, "Failed to register regulator: %d\n",
ret);

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-da7219-max98357a.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index cd3cf6e..48c1d94 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -365,7 +365,7 @@ static int cz_probe(struct platform_device *pdev)
   _da7219_cfg);
if (IS_ERR(rdev)) {
dev_err(>dev, "Failed to register regulator: %d\n",
-   ret);
+   (int)PTR_ERR(rdev);
return -EINVAL;
}
 
-- 
1.9.1



[PATCH] ASoC: AMD: Fix build warning

2018-07-25 Thread Akshu Agrawal
Fixes
sound/soc/amd/acp-da7219-max98357a.c: In function 'cz_probe':
sound/soc/amd/acp-da7219-max98357a.c:367:3: warning: 'ret' may
be used uninitialized in this function [-Wmaybe-uninitialized]
   dev_err(>dev, "Failed to register regulator: %d\n",
ret);

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-da7219-max98357a.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index cd3cf6e..48c1d94 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -365,7 +365,7 @@ static int cz_probe(struct platform_device *pdev)
   _da7219_cfg);
if (IS_ERR(rdev)) {
dev_err(>dev, "Failed to register regulator: %d\n",
-   ret);
+   (int)PTR_ERR(rdev);
return -EINVAL;
}
 
-- 
1.9.1



[PATCH v2] ASoC: AMD: Add a fix voltage regulator for DA7219 and ADAU7002

2018-07-25 Thread Akshu Agrawal
DA7219 for our platform need to be configured for 1.8V.
Hence, we add a volatge regulator with supplies
of 1.8V in the machine driver.

Signed-off-by: Adam Thomson 
Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/Kconfig|  1 +
 sound/soc/amd/acp-da7219-max98357a.c | 43 
 2 files changed, 44 insertions(+)

diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index 6cbf9cf..58c1dcb 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -8,6 +8,7 @@ config SND_SOC_AMD_CZ_DA7219MX98357_MACH
select SND_SOC_DA7219
select SND_SOC_MAX98357A
select SND_SOC_ADAU7002
+   select REGULATOR
depends on SND_SOC_AMD_ACP && I2C
help
 This option enables machine driver for DA7219 and MAX9835.
diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index f42606e..cd3cf6e 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -32,6 +32,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -320,11 +322,52 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.num_controls = ARRAY_SIZE(cz_mc_controls),
 };
 
+static struct regulator_consumer_supply acp_da7219_supplies[] = {
+   REGULATOR_SUPPLY("VDD", "i2c-DLGS7219:00"),
+   REGULATOR_SUPPLY("VDDMIC", "i2c-DLGS7219:00"),
+   REGULATOR_SUPPLY("VDDIO", "i2c-DLGS7219:00"),
+   REGULATOR_SUPPLY("IOVDD", "ADAU7002:00"),
+};
+
+static struct regulator_init_data acp_da7219_data = {
+   .constraints = {
+   .always_on = 1,
+   },
+   .num_consumer_supplies = ARRAY_SIZE(acp_da7219_supplies),
+   .consumer_supplies = acp_da7219_supplies,
+};
+
+static struct regulator_config acp_da7219_cfg = {
+   .init_data = _da7219_data,
+};
+
+static struct regulator_ops acp_da7219_ops = {
+};
+
+static struct regulator_desc acp_da7219_desc = {
+   .name = "reg-fixed-1.8V",
+   .type = REGULATOR_VOLTAGE,
+   .owner = THIS_MODULE,
+   .ops = _da7219_ops,
+   .fixed_uV = 180, /* 1.8V */
+   .n_voltages = 1,
+};
+
 static int cz_probe(struct platform_device *pdev)
 {
int ret;
struct snd_soc_card *card;
struct acp_platform_info *machine;
+   struct regulator_dev *rdev;
+
+   acp_da7219_cfg.dev = >dev;
+   rdev = devm_regulator_register(>dev, _da7219_desc,
+  _da7219_cfg);
+   if (IS_ERR(rdev)) {
+   dev_err(>dev, "Failed to register regulator: %d\n",
+   ret);
+   return -EINVAL;
+   }
 
machine = devm_kzalloc(>dev, sizeof(struct acp_platform_info),
   GFP_KERNEL);
-- 
1.9.1



[PATCH v2] ASoC: AMD: Add a fix voltage regulator for DA7219 and ADAU7002

2018-07-25 Thread Akshu Agrawal
DA7219 for our platform need to be configured for 1.8V.
Hence, we add a volatge regulator with supplies
of 1.8V in the machine driver.

Signed-off-by: Adam Thomson 
Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/Kconfig|  1 +
 sound/soc/amd/acp-da7219-max98357a.c | 43 
 2 files changed, 44 insertions(+)

diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index 6cbf9cf..58c1dcb 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -8,6 +8,7 @@ config SND_SOC_AMD_CZ_DA7219MX98357_MACH
select SND_SOC_DA7219
select SND_SOC_MAX98357A
select SND_SOC_ADAU7002
+   select REGULATOR
depends on SND_SOC_AMD_ACP && I2C
help
 This option enables machine driver for DA7219 and MAX9835.
diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index f42606e..cd3cf6e 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -32,6 +32,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -320,11 +322,52 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.num_controls = ARRAY_SIZE(cz_mc_controls),
 };
 
+static struct regulator_consumer_supply acp_da7219_supplies[] = {
+   REGULATOR_SUPPLY("VDD", "i2c-DLGS7219:00"),
+   REGULATOR_SUPPLY("VDDMIC", "i2c-DLGS7219:00"),
+   REGULATOR_SUPPLY("VDDIO", "i2c-DLGS7219:00"),
+   REGULATOR_SUPPLY("IOVDD", "ADAU7002:00"),
+};
+
+static struct regulator_init_data acp_da7219_data = {
+   .constraints = {
+   .always_on = 1,
+   },
+   .num_consumer_supplies = ARRAY_SIZE(acp_da7219_supplies),
+   .consumer_supplies = acp_da7219_supplies,
+};
+
+static struct regulator_config acp_da7219_cfg = {
+   .init_data = _da7219_data,
+};
+
+static struct regulator_ops acp_da7219_ops = {
+};
+
+static struct regulator_desc acp_da7219_desc = {
+   .name = "reg-fixed-1.8V",
+   .type = REGULATOR_VOLTAGE,
+   .owner = THIS_MODULE,
+   .ops = _da7219_ops,
+   .fixed_uV = 180, /* 1.8V */
+   .n_voltages = 1,
+};
+
 static int cz_probe(struct platform_device *pdev)
 {
int ret;
struct snd_soc_card *card;
struct acp_platform_info *machine;
+   struct regulator_dev *rdev;
+
+   acp_da7219_cfg.dev = >dev;
+   rdev = devm_regulator_register(>dev, _da7219_desc,
+  _da7219_cfg);
+   if (IS_ERR(rdev)) {
+   dev_err(>dev, "Failed to register regulator: %d\n",
+   ret);
+   return -EINVAL;
+   }
 
machine = devm_kzalloc(>dev, sizeof(struct acp_platform_info),
   GFP_KERNEL);
-- 
1.9.1



[PATCH] ASoC: AMD: Add a fix voltage regulator for DA7219 and ADAU7002

2018-07-20 Thread Akshu Agrawal
DA7219 for our platform need to be configured for 1.8V.
Hence, we add a fixed volatge regulator with supplies
of 1.8V in the machine driver.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/Kconfig|  2 ++
 sound/soc/amd/acp-da7219-max98357a.c | 45 
 2 files changed, 47 insertions(+)

diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index 6cbf9cf..c447a51 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -8,6 +8,8 @@ config SND_SOC_AMD_CZ_DA7219MX98357_MACH
select SND_SOC_DA7219
select SND_SOC_MAX98357A
select SND_SOC_ADAU7002
+   select REGULATOR
+   select REGULATOR_FIXED_VOLTAGE
depends on SND_SOC_AMD_ACP && I2C
help
 This option enables machine driver for DA7219 and MAX9835.
diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index f42606e..fdf8972 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -31,7 +31,10 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -320,11 +323,53 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.num_controls = ARRAY_SIZE(cz_mc_controls),
 };
 
+static struct regulator_consumer_supply acp_da7219_supplies[] = {
+   REGULATOR_SUPPLY("VDD", "i2c-DLGS7219:00"),
+   REGULATOR_SUPPLY("VDDMIC", "i2c-DLGS7219:00"),
+   REGULATOR_SUPPLY("VDDIO", "i2c-DLGS7219:00"),
+   REGULATOR_SUPPLY("IOVDD", "ADAU7002:00"),
+};
+
+static struct regulator_init_data acp_da7219_data = {
+   .constraints = {
+   .always_on = 1,
+   },
+   .num_consumer_supplies = ARRAY_SIZE(acp_da7219_supplies),
+   .consumer_supplies = acp_da7219_supplies,
+};
+
+static struct fixed_voltage_config acp_da7219 = {
+   .supply_name = "reg-fixed-1.8V",
+   .microvolts = 180, /* 1.8V */
+   .gpio = -EINVAL,
+   .enabled_at_boot = 1,
+   .init_data = _da7219_data,
+};
+
+static struct platform_device acp_da7219_regulator = {
+   .name = "reg-fixed-voltage",
+   .id = PLATFORM_DEVID_AUTO,
+   .dev = {
+   .platform_data = _da7219,
+   },
+};
+
 static int cz_probe(struct platform_device *pdev)
 {
int ret;
struct snd_soc_card *card;
struct acp_platform_info *machine;
+   static bool regulators_registered;
+
+   if (!regulators_registered) {
+   ret = platform_device_register(_da7219_regulator);
+   if (ret) {
+   dev_err(>dev, "Failed to register regulator: 
%d\n",
+   ret);
+   return ret;
+   }
+   regulators_registered = true;
+   }
 
machine = devm_kzalloc(>dev, sizeof(struct acp_platform_info),
   GFP_KERNEL);
-- 
1.9.1



[PATCH] ASoC: AMD: Add a fix voltage regulator for DA7219 and ADAU7002

2018-07-20 Thread Akshu Agrawal
DA7219 for our platform need to be configured for 1.8V.
Hence, we add a fixed volatge regulator with supplies
of 1.8V in the machine driver.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/Kconfig|  2 ++
 sound/soc/amd/acp-da7219-max98357a.c | 45 
 2 files changed, 47 insertions(+)

diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index 6cbf9cf..c447a51 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -8,6 +8,8 @@ config SND_SOC_AMD_CZ_DA7219MX98357_MACH
select SND_SOC_DA7219
select SND_SOC_MAX98357A
select SND_SOC_ADAU7002
+   select REGULATOR
+   select REGULATOR_FIXED_VOLTAGE
depends on SND_SOC_AMD_ACP && I2C
help
 This option enables machine driver for DA7219 and MAX9835.
diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index f42606e..fdf8972 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -31,7 +31,10 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -320,11 +323,53 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.num_controls = ARRAY_SIZE(cz_mc_controls),
 };
 
+static struct regulator_consumer_supply acp_da7219_supplies[] = {
+   REGULATOR_SUPPLY("VDD", "i2c-DLGS7219:00"),
+   REGULATOR_SUPPLY("VDDMIC", "i2c-DLGS7219:00"),
+   REGULATOR_SUPPLY("VDDIO", "i2c-DLGS7219:00"),
+   REGULATOR_SUPPLY("IOVDD", "ADAU7002:00"),
+};
+
+static struct regulator_init_data acp_da7219_data = {
+   .constraints = {
+   .always_on = 1,
+   },
+   .num_consumer_supplies = ARRAY_SIZE(acp_da7219_supplies),
+   .consumer_supplies = acp_da7219_supplies,
+};
+
+static struct fixed_voltage_config acp_da7219 = {
+   .supply_name = "reg-fixed-1.8V",
+   .microvolts = 180, /* 1.8V */
+   .gpio = -EINVAL,
+   .enabled_at_boot = 1,
+   .init_data = _da7219_data,
+};
+
+static struct platform_device acp_da7219_regulator = {
+   .name = "reg-fixed-voltage",
+   .id = PLATFORM_DEVID_AUTO,
+   .dev = {
+   .platform_data = _da7219,
+   },
+};
+
 static int cz_probe(struct platform_device *pdev)
 {
int ret;
struct snd_soc_card *card;
struct acp_platform_info *machine;
+   static bool regulators_registered;
+
+   if (!regulators_registered) {
+   ret = platform_device_register(_da7219_regulator);
+   if (ret) {
+   dev_err(>dev, "Failed to register regulator: 
%d\n",
+   ret);
+   return ret;
+   }
+   regulators_registered = true;
+   }
 
machine = devm_kzalloc(>dev, sizeof(struct acp_platform_info),
   GFP_KERNEL);
-- 
1.9.1



[PATCH 2/2] ASoC: AMD: For capture have interrupts on I2S->ACP channel

2018-07-16 Thread Akshu Agrawal
Having interrupts enabled for ACP<->SYSMEM DMA transfer, we are in
for an interrupt storm.
For both playback and capture interrupts should be enabled for
I2S<->ACP DMA.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index eeb8677..94bcf69 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -224,13 +224,11 @@ static void set_acp_sysmem_dma_descriptors(void __iomem 
*acp_mmio,
switch (asic_type) {
case CHIP_STONEY:
dmadscr[i].xfer_val |=
-   BIT(22) |
(ACP_DMA_ATTR_SHARED_MEM_TO_DAGB_GARLIC << 16) |
(size / 2);
break;
default:
dmadscr[i].xfer_val |=
-   BIT(22) |
(ACP_DMA_ATTR_SHAREDMEM_TO_DAGB_ONION << 16) |
(size / 2);
}
@@ -421,9 +419,9 @@ static void acp_dma_start(void __iomem *acp_mmio, u16 
ch_num)
 
switch (ch_num) {
case ACP_TO_I2S_DMA_CH_NUM:
-   case ACP_TO_SYSRAM_CH_NUM:
+   case I2S_TO_ACP_DMA_CH_NUM:
case ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM:
-   case ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM:
+   case I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM:
dma_ctrl |= ACP_DMA_CNTL_0__DMAChIOCEn_MASK;
break;
default:
@@ -705,18 +703,18 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-   if ((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) != 0) {
+   if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
valid_irq = true;
snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
-   acp_reg_write((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) << 16,
+   acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-   if ((intr_flag & BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) != 0) {
+   if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
snd_pcm_period_elapsed(irq_data->capture_i2sbt_stream);
acp_reg_write((intr_flag &
- BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) << 16,
+ BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-- 
1.9.1



[PATCH 2/2] ASoC: AMD: For capture have interrupts on I2S->ACP channel

2018-07-16 Thread Akshu Agrawal
Having interrupts enabled for ACP<->SYSMEM DMA transfer, we are in
for an interrupt storm.
For both playback and capture interrupts should be enabled for
I2S<->ACP DMA.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index eeb8677..94bcf69 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -224,13 +224,11 @@ static void set_acp_sysmem_dma_descriptors(void __iomem 
*acp_mmio,
switch (asic_type) {
case CHIP_STONEY:
dmadscr[i].xfer_val |=
-   BIT(22) |
(ACP_DMA_ATTR_SHARED_MEM_TO_DAGB_GARLIC << 16) |
(size / 2);
break;
default:
dmadscr[i].xfer_val |=
-   BIT(22) |
(ACP_DMA_ATTR_SHAREDMEM_TO_DAGB_ONION << 16) |
(size / 2);
}
@@ -421,9 +419,9 @@ static void acp_dma_start(void __iomem *acp_mmio, u16 
ch_num)
 
switch (ch_num) {
case ACP_TO_I2S_DMA_CH_NUM:
-   case ACP_TO_SYSRAM_CH_NUM:
+   case I2S_TO_ACP_DMA_CH_NUM:
case ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM:
-   case ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM:
+   case I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM:
dma_ctrl |= ACP_DMA_CNTL_0__DMAChIOCEn_MASK;
break;
default:
@@ -705,18 +703,18 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-   if ((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) != 0) {
+   if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
valid_irq = true;
snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
-   acp_reg_write((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) << 16,
+   acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-   if ((intr_flag & BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) != 0) {
+   if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
snd_pcm_period_elapsed(irq_data->capture_i2sbt_stream);
acp_reg_write((intr_flag &
- BIT(ACP_TO_SYSRAM_BT_INSTANCE_CH_NUM)) << 16,
+ BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
-- 
1.9.1



[PATCH 1/2] ASoC: AMD: Send correct channel for configuring DMA descriptors

2018-07-16 Thread Akshu Agrawal
Earlier, ch1 was used to define ACP-SYSMEM transfer and ch2 for
ACP-I2S transfer. With recent patches ch1 is used to define channel
order number 1 and ch2 as channel order number 2. Thus,
Playback:
ch1:SYSMEM->ACP
ch2:ACP->I2S
Capture:
ch1:I2S->ACP
ch1:ACP->SYSMEM

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 26 ++
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 65c1033..eeb8677 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -322,17 +322,27 @@ static void config_acp_dma(void __iomem *acp_mmio,
   struct audio_substream_data *rtd,
   u32 asic_type)
 {
+   u16 ch_acp_sysmem, ch_acp_i2s;
+
acp_pte_config(acp_mmio, rtd->pg, rtd->num_of_pages,
   rtd->pte_offset);
+
+   if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) {
+   ch_acp_sysmem = rtd->ch1;
+   ch_acp_i2s = rtd->ch2;
+   } else {
+   ch_acp_i2s = rtd->ch1;
+   ch_acp_sysmem = rtd->ch2;
+   }
/* Configure System memory <-> ACP SRAM DMA descriptors */
set_acp_sysmem_dma_descriptors(acp_mmio, rtd->size,
   rtd->direction, rtd->pte_offset,
-  rtd->ch1, rtd->sram_bank,
+  ch_acp_sysmem, rtd->sram_bank,
   rtd->dma_dscr_idx_1, asic_type);
/* Configure ACP SRAM <-> I2S DMA descriptors */
set_acp_to_i2s_dma_descriptors(acp_mmio, rtd->size,
   rtd->direction, rtd->sram_bank,
-  rtd->destination, rtd->ch2,
+  rtd->destination, ch_acp_i2s,
   rtd->dma_dscr_idx_2, asic_type);
 }
 
@@ -995,16 +1005,24 @@ static int acp_dma_prepare(struct snd_pcm_substream 
*substream)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
+   u16 ch_acp_sysmem, ch_acp_i2s;
 
if (!rtd)
return -EINVAL;
 
+   if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) {
+   ch_acp_sysmem = rtd->ch1;
+   ch_acp_i2s = rtd->ch2;
+   } else {
+   ch_acp_i2s = rtd->ch1;
+   ch_acp_sysmem = rtd->ch2;
+   }
config_acp_dma_channel(rtd->acp_mmio,
-  rtd->ch1,
+  ch_acp_sysmem,
   rtd->dma_dscr_idx_1,
   NUM_DSCRS_PER_CHANNEL, 0);
config_acp_dma_channel(rtd->acp_mmio,
-  rtd->ch2,
+  ch_acp_i2s,
   rtd->dma_dscr_idx_2,
   NUM_DSCRS_PER_CHANNEL, 0);
return 0;
-- 
1.9.1



[PATCH 1/2] ASoC: AMD: Send correct channel for configuring DMA descriptors

2018-07-16 Thread Akshu Agrawal
Earlier, ch1 was used to define ACP-SYSMEM transfer and ch2 for
ACP-I2S transfer. With recent patches ch1 is used to define channel
order number 1 and ch2 as channel order number 2. Thus,
Playback:
ch1:SYSMEM->ACP
ch2:ACP->I2S
Capture:
ch1:I2S->ACP
ch1:ACP->SYSMEM

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 26 ++
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 65c1033..eeb8677 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -322,17 +322,27 @@ static void config_acp_dma(void __iomem *acp_mmio,
   struct audio_substream_data *rtd,
   u32 asic_type)
 {
+   u16 ch_acp_sysmem, ch_acp_i2s;
+
acp_pte_config(acp_mmio, rtd->pg, rtd->num_of_pages,
   rtd->pte_offset);
+
+   if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) {
+   ch_acp_sysmem = rtd->ch1;
+   ch_acp_i2s = rtd->ch2;
+   } else {
+   ch_acp_i2s = rtd->ch1;
+   ch_acp_sysmem = rtd->ch2;
+   }
/* Configure System memory <-> ACP SRAM DMA descriptors */
set_acp_sysmem_dma_descriptors(acp_mmio, rtd->size,
   rtd->direction, rtd->pte_offset,
-  rtd->ch1, rtd->sram_bank,
+  ch_acp_sysmem, rtd->sram_bank,
   rtd->dma_dscr_idx_1, asic_type);
/* Configure ACP SRAM <-> I2S DMA descriptors */
set_acp_to_i2s_dma_descriptors(acp_mmio, rtd->size,
   rtd->direction, rtd->sram_bank,
-  rtd->destination, rtd->ch2,
+  rtd->destination, ch_acp_i2s,
   rtd->dma_dscr_idx_2, asic_type);
 }
 
@@ -995,16 +1005,24 @@ static int acp_dma_prepare(struct snd_pcm_substream 
*substream)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct audio_substream_data *rtd = runtime->private_data;
+   u16 ch_acp_sysmem, ch_acp_i2s;
 
if (!rtd)
return -EINVAL;
 
+   if (rtd->direction == SNDRV_PCM_STREAM_PLAYBACK) {
+   ch_acp_sysmem = rtd->ch1;
+   ch_acp_i2s = rtd->ch2;
+   } else {
+   ch_acp_i2s = rtd->ch1;
+   ch_acp_sysmem = rtd->ch2;
+   }
config_acp_dma_channel(rtd->acp_mmio,
-  rtd->ch1,
+  ch_acp_sysmem,
   rtd->dma_dscr_idx_1,
   NUM_DSCRS_PER_CHANNEL, 0);
config_acp_dma_channel(rtd->acp_mmio,
-  rtd->ch2,
+  ch_acp_i2s,
   rtd->dma_dscr_idx_2,
   NUM_DSCRS_PER_CHANNEL, 0);
return 0;
-- 
1.9.1



[v2, 2/2] ASoC: AMD: Configure channel 1 or channel 0 for capture

2018-06-20 Thread Akshu Agrawal
ST/CZ SoC have 2 channels for capture in the I2SSP path.
The DMA though these channels is done using the same dma
descriptors.
We configure the channel and enable it on the basis of
channel selected by machine driver. Machine driver knows
which codec sits on which channel and thus sends the information
to dma driver.

Signed-off-by: Akshu Agrawal 
---
v2: Split acp_dma_cap_channel into 2 functions.

 sound/soc/amd/acp-da7219-max98357a.c | 43 +++---
 sound/soc/amd/acp-pcm-dma.c  | 71 +++-
 sound/soc/amd/acp.h  |  4 ++
 3 files changed, 111 insertions(+), 7 deletions(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index 566bd26..f42606e 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -149,6 +149,7 @@ static int cz_da7219_startup(struct snd_pcm_substream 
*substream)
   _rates);
 
machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->capture_channel = CAP_CHANNEL1;
return da7219_clk_enable(substream);
 }
 
@@ -172,7 +173,7 @@ static void cz_max_shutdown(struct snd_pcm_substream 
*substream)
da7219_clk_disable();
 }
 
-static int cz_dmic_startup(struct snd_pcm_substream *substream)
+static int cz_dmic0_startup(struct snd_pcm_substream *substream)
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
@@ -182,6 +183,17 @@ static int cz_dmic_startup(struct snd_pcm_substream 
*substream)
return da7219_clk_enable(substream);
 }
 
+static int cz_dmic1_startup(struct snd_pcm_substream *substream)
+{
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct snd_soc_card *card = rtd->card;
+   struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
+
+   machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->capture_channel = CAP_CHANNEL0;
+   return da7219_clk_enable(substream);
+}
+
 static void cz_dmic_shutdown(struct snd_pcm_substream *substream)
 {
da7219_clk_disable();
@@ -197,8 +209,13 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.shutdown = cz_max_shutdown,
 };
 
-static const struct snd_soc_ops cz_dmic_cap_ops = {
-   .startup = cz_dmic_startup,
+static const struct snd_soc_ops cz_dmic0_cap_ops = {
+   .startup = cz_dmic0_startup,
+   .shutdown = cz_dmic_shutdown,
+};
+
+static const struct snd_soc_ops cz_dmic1_cap_ops = {
+   .startup = cz_dmic1_startup,
.shutdown = cz_dmic_shutdown,
 };
 
@@ -241,8 +258,9 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.ops = _max_play_ops,
},
{
-   .name = "dmic",
-   .stream_name = "DMIC Capture",
+   /* C panel DMIC */
+   .name = "dmic0",
+   .stream_name = "DMIC0 Capture",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.3.auto",
.codec_dai_name = "adau7002-hifi",
@@ -250,7 +268,20 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1,
-   .ops = _dmic_cap_ops,
+   .ops = _dmic0_cap_ops,
+   },
+   {
+   /* A/B panel DMIC */
+   .name = "dmic1",
+   .stream_name = "DMIC1 Capture",
+   .platform_name = "acp_audio_dma.0.auto",
+   .cpu_dai_name = "designware-i2s.2.auto",
+   .codec_dai_name = "adau7002-hifi",
+   .codec_name = "ADAU7002:00",
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+   | SND_SOC_DAIFMT_CBM_CFM,
+   .dpcm_capture = 1,
+   .ops = _dmic1_cap_ops,
},
 };
 
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 1458b50..3c3d398 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -336,6 +336,61 @@ static void config_acp_dma(void __iomem *acp_mmio,
   rtd->dma_dscr_idx_2, asic_type);
 }
 
+static void acp_dma_cap_channel_enable(void __iomem *acp_mmio,
+  u16 cap_channel)
+{
+   u32 val, ch_reg, imr_reg, res_reg;
+
+   switch (cap_channel) {
+   case CAP_CHANNEL1:
+   ch_reg = mmACP_I2SMICSP_RER1;
+   res_reg = mmACP_I2SMICSP_RCR1;
+   imr_reg = mmACP_I2SMICSP_IMR1;
+   break;
+   case CAP_CHANNEL0:
+   default:
+   ch_reg = mmACP_I2SMICSP_RER0;
+

[v2, 2/2] ASoC: AMD: Configure channel 1 or channel 0 for capture

2018-06-20 Thread Akshu Agrawal
ST/CZ SoC have 2 channels for capture in the I2SSP path.
The DMA though these channels is done using the same dma
descriptors.
We configure the channel and enable it on the basis of
channel selected by machine driver. Machine driver knows
which codec sits on which channel and thus sends the information
to dma driver.

Signed-off-by: Akshu Agrawal 
---
v2: Split acp_dma_cap_channel into 2 functions.

 sound/soc/amd/acp-da7219-max98357a.c | 43 +++---
 sound/soc/amd/acp-pcm-dma.c  | 71 +++-
 sound/soc/amd/acp.h  |  4 ++
 3 files changed, 111 insertions(+), 7 deletions(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index 566bd26..f42606e 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -149,6 +149,7 @@ static int cz_da7219_startup(struct snd_pcm_substream 
*substream)
   _rates);
 
machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->capture_channel = CAP_CHANNEL1;
return da7219_clk_enable(substream);
 }
 
@@ -172,7 +173,7 @@ static void cz_max_shutdown(struct snd_pcm_substream 
*substream)
da7219_clk_disable();
 }
 
-static int cz_dmic_startup(struct snd_pcm_substream *substream)
+static int cz_dmic0_startup(struct snd_pcm_substream *substream)
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
@@ -182,6 +183,17 @@ static int cz_dmic_startup(struct snd_pcm_substream 
*substream)
return da7219_clk_enable(substream);
 }
 
+static int cz_dmic1_startup(struct snd_pcm_substream *substream)
+{
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct snd_soc_card *card = rtd->card;
+   struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
+
+   machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->capture_channel = CAP_CHANNEL0;
+   return da7219_clk_enable(substream);
+}
+
 static void cz_dmic_shutdown(struct snd_pcm_substream *substream)
 {
da7219_clk_disable();
@@ -197,8 +209,13 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.shutdown = cz_max_shutdown,
 };
 
-static const struct snd_soc_ops cz_dmic_cap_ops = {
-   .startup = cz_dmic_startup,
+static const struct snd_soc_ops cz_dmic0_cap_ops = {
+   .startup = cz_dmic0_startup,
+   .shutdown = cz_dmic_shutdown,
+};
+
+static const struct snd_soc_ops cz_dmic1_cap_ops = {
+   .startup = cz_dmic1_startup,
.shutdown = cz_dmic_shutdown,
 };
 
@@ -241,8 +258,9 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.ops = _max_play_ops,
},
{
-   .name = "dmic",
-   .stream_name = "DMIC Capture",
+   /* C panel DMIC */
+   .name = "dmic0",
+   .stream_name = "DMIC0 Capture",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.3.auto",
.codec_dai_name = "adau7002-hifi",
@@ -250,7 +268,20 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1,
-   .ops = _dmic_cap_ops,
+   .ops = _dmic0_cap_ops,
+   },
+   {
+   /* A/B panel DMIC */
+   .name = "dmic1",
+   .stream_name = "DMIC1 Capture",
+   .platform_name = "acp_audio_dma.0.auto",
+   .cpu_dai_name = "designware-i2s.2.auto",
+   .codec_dai_name = "adau7002-hifi",
+   .codec_name = "ADAU7002:00",
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+   | SND_SOC_DAIFMT_CBM_CFM,
+   .dpcm_capture = 1,
+   .ops = _dmic1_cap_ops,
},
 };
 
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 1458b50..3c3d398 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -336,6 +336,61 @@ static void config_acp_dma(void __iomem *acp_mmio,
   rtd->dma_dscr_idx_2, asic_type);
 }
 
+static void acp_dma_cap_channel_enable(void __iomem *acp_mmio,
+  u16 cap_channel)
+{
+   u32 val, ch_reg, imr_reg, res_reg;
+
+   switch (cap_channel) {
+   case CAP_CHANNEL1:
+   ch_reg = mmACP_I2SMICSP_RER1;
+   res_reg = mmACP_I2SMICSP_RCR1;
+   imr_reg = mmACP_I2SMICSP_IMR1;
+   break;
+   case CAP_CHANNEL0:
+   default:
+   ch_reg = mmACP_I2SMICSP_RER0;
+

[PATCH 1/2] ASoC: AMD: Change codec to channel link as per hardware redesign

2018-06-20 Thread Akshu Agrawal
From: "Agrawal, Akshu" 

This is a correction to match acutal hardware configuration.
The hardware configuration looks like:
I2S_BT -> SPK(Max) + DMIC(Adau)
I2S_SP -> DA7219 Headset

No actual products have been shipped with previous configuration.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-da7219-max98357a.c | 27 +++
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index ccddc66..566bd26 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -148,7 +148,7 @@ static int cz_da7219_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
-   machine->i2s_instance = I2S_BT_INSTANCE;
+   machine->i2s_instance = I2S_SP_INSTANCE;
return da7219_clk_enable(substream);
 }
 
@@ -163,7 +163,7 @@ static int cz_max_startup(struct snd_pcm_substream 
*substream)
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
 
-   machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
 }
 
@@ -178,7 +178,7 @@ static int cz_dmic_startup(struct snd_pcm_substream 
*substream)
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
 
-   machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
 }
 
@@ -204,16 +204,27 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
 
 static struct snd_soc_dai_link cz_dai_7219_98357[] = {
{
-   .name = "amd-da7219-play-cap",
-   .stream_name = "Playback and Capture",
+   .name = "amd-da7219-play",
+   .stream_name = "Playback",
.platform_name = "acp_audio_dma.0.auto",
-   .cpu_dai_name = "designware-i2s.3.auto",
+   .cpu_dai_name = "designware-i2s.1.auto",
.codec_dai_name = "da7219-hifi",
.codec_name = "i2c-DLGS7219:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.init = cz_da7219_init,
.dpcm_playback = 1,
+   .ops = _da7219_cap_ops,
+   },
+   {
+   .name = "amd-da7219-cap",
+   .stream_name = "Capture",
+   .platform_name = "acp_audio_dma.0.auto",
+   .cpu_dai_name = "designware-i2s.2.auto",
+   .codec_dai_name = "da7219-hifi",
+   .codec_name = "i2c-DLGS7219:00",
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+   | SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1,
.ops = _da7219_cap_ops,
},
@@ -221,7 +232,7 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.name = "amd-max98357-play",
.stream_name = "HiFi Playback",
.platform_name = "acp_audio_dma.0.auto",
-   .cpu_dai_name = "designware-i2s.1.auto",
+   .cpu_dai_name = "designware-i2s.3.auto",
.codec_dai_name = "HiFi",
.codec_name = "MX98357A:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
@@ -233,7 +244,7 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.name = "dmic",
.stream_name = "DMIC Capture",
.platform_name = "acp_audio_dma.0.auto",
-   .cpu_dai_name = "designware-i2s.2.auto",
+   .cpu_dai_name = "designware-i2s.3.auto",
.codec_dai_name = "adau7002-hifi",
.codec_name = "ADAU7002:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
-- 
1.9.1



[PATCH 1/2] ASoC: AMD: Change codec to channel link as per hardware redesign

2018-06-20 Thread Akshu Agrawal
From: "Agrawal, Akshu" 

This is a correction to match acutal hardware configuration.
The hardware configuration looks like:
I2S_BT -> SPK(Max) + DMIC(Adau)
I2S_SP -> DA7219 Headset

No actual products have been shipped with previous configuration.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-da7219-max98357a.c | 27 +++
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index ccddc66..566bd26 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -148,7 +148,7 @@ static int cz_da7219_startup(struct snd_pcm_substream 
*substream)
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
   _rates);
 
-   machine->i2s_instance = I2S_BT_INSTANCE;
+   machine->i2s_instance = I2S_SP_INSTANCE;
return da7219_clk_enable(substream);
 }
 
@@ -163,7 +163,7 @@ static int cz_max_startup(struct snd_pcm_substream 
*substream)
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
 
-   machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
 }
 
@@ -178,7 +178,7 @@ static int cz_dmic_startup(struct snd_pcm_substream 
*substream)
struct snd_soc_card *card = rtd->card;
struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
 
-   machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->i2s_instance = I2S_BT_INSTANCE;
return da7219_clk_enable(substream);
 }
 
@@ -204,16 +204,27 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
 
 static struct snd_soc_dai_link cz_dai_7219_98357[] = {
{
-   .name = "amd-da7219-play-cap",
-   .stream_name = "Playback and Capture",
+   .name = "amd-da7219-play",
+   .stream_name = "Playback",
.platform_name = "acp_audio_dma.0.auto",
-   .cpu_dai_name = "designware-i2s.3.auto",
+   .cpu_dai_name = "designware-i2s.1.auto",
.codec_dai_name = "da7219-hifi",
.codec_name = "i2c-DLGS7219:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.init = cz_da7219_init,
.dpcm_playback = 1,
+   .ops = _da7219_cap_ops,
+   },
+   {
+   .name = "amd-da7219-cap",
+   .stream_name = "Capture",
+   .platform_name = "acp_audio_dma.0.auto",
+   .cpu_dai_name = "designware-i2s.2.auto",
+   .codec_dai_name = "da7219-hifi",
+   .codec_name = "i2c-DLGS7219:00",
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+   | SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1,
.ops = _da7219_cap_ops,
},
@@ -221,7 +232,7 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.name = "amd-max98357-play",
.stream_name = "HiFi Playback",
.platform_name = "acp_audio_dma.0.auto",
-   .cpu_dai_name = "designware-i2s.1.auto",
+   .cpu_dai_name = "designware-i2s.3.auto",
.codec_dai_name = "HiFi",
.codec_name = "MX98357A:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
@@ -233,7 +244,7 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.name = "dmic",
.stream_name = "DMIC Capture",
.platform_name = "acp_audio_dma.0.auto",
-   .cpu_dai_name = "designware-i2s.2.auto",
+   .cpu_dai_name = "designware-i2s.3.auto",
.codec_dai_name = "adau7002-hifi",
.codec_name = "ADAU7002:00",
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
-- 
1.9.1



[v2, 2/2] ASoC: AMD: Configure channel 1 or channel 0 for capture

2018-06-07 Thread Akshu Agrawal
ST/CZ SoC have 2 channels for capture in the I2SSP path.
The DMA though these channels is done using the same dma
descriptors.
We configure the channel and enable it on the basis of
channel selected by machine driver. Machine driver knows
which codec sits on which channel and thus sends the information
to dma driver.

Signed-off-by: Akshu Agrawal 
---
v2: Split acp_dma_cap_channel into 2 functions.

This patch is dependent on ASoC: AMD: Change codec to channel link as per 
hardware redesign
https://patchwork.kernel.org/patch/10388099/

 sound/soc/amd/acp-da7219-max98357a.c | 43 +++---
 sound/soc/amd/acp-pcm-dma.c  | 71 +++-
 sound/soc/amd/acp.h  |  4 ++
 3 files changed, 111 insertions(+), 7 deletions(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index 566bd26..f42606e 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -149,6 +149,7 @@ static int cz_da7219_startup(struct snd_pcm_substream 
*substream)
   _rates);
 
machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->capture_channel = CAP_CHANNEL1;
return da7219_clk_enable(substream);
 }
 
@@ -172,7 +173,7 @@ static void cz_max_shutdown(struct snd_pcm_substream 
*substream)
da7219_clk_disable();
 }
 
-static int cz_dmic_startup(struct snd_pcm_substream *substream)
+static int cz_dmic0_startup(struct snd_pcm_substream *substream)
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
@@ -182,6 +183,17 @@ static int cz_dmic_startup(struct snd_pcm_substream 
*substream)
return da7219_clk_enable(substream);
 }
 
+static int cz_dmic1_startup(struct snd_pcm_substream *substream)
+{
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct snd_soc_card *card = rtd->card;
+   struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
+
+   machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->capture_channel = CAP_CHANNEL0;
+   return da7219_clk_enable(substream);
+}
+
 static void cz_dmic_shutdown(struct snd_pcm_substream *substream)
 {
da7219_clk_disable();
@@ -197,8 +209,13 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.shutdown = cz_max_shutdown,
 };
 
-static const struct snd_soc_ops cz_dmic_cap_ops = {
-   .startup = cz_dmic_startup,
+static const struct snd_soc_ops cz_dmic0_cap_ops = {
+   .startup = cz_dmic0_startup,
+   .shutdown = cz_dmic_shutdown,
+};
+
+static const struct snd_soc_ops cz_dmic1_cap_ops = {
+   .startup = cz_dmic1_startup,
.shutdown = cz_dmic_shutdown,
 };
 
@@ -241,8 +258,9 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.ops = _max_play_ops,
},
{
-   .name = "dmic",
-   .stream_name = "DMIC Capture",
+   /* C panel DMIC */
+   .name = "dmic0",
+   .stream_name = "DMIC0 Capture",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.3.auto",
.codec_dai_name = "adau7002-hifi",
@@ -250,7 +268,20 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1,
-   .ops = _dmic_cap_ops,
+   .ops = _dmic0_cap_ops,
+   },
+   {
+   /* A/B panel DMIC */
+   .name = "dmic1",
+   .stream_name = "DMIC1 Capture",
+   .platform_name = "acp_audio_dma.0.auto",
+   .cpu_dai_name = "designware-i2s.2.auto",
+   .codec_dai_name = "adau7002-hifi",
+   .codec_name = "ADAU7002:00",
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+   | SND_SOC_DAIFMT_CBM_CFM,
+   .dpcm_capture = 1,
+   .ops = _dmic1_cap_ops,
},
 };
 
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 1458b50..3c3d398 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -336,6 +336,61 @@ static void config_acp_dma(void __iomem *acp_mmio,
   rtd->dma_dscr_idx_2, asic_type);
 }
 
+static void acp_dma_cap_channel_enable(void __iomem *acp_mmio,
+  u16 cap_channel)
+{
+   u32 val, ch_reg, imr_reg, res_reg;
+
+   switch (cap_channel) {
+   case CAP_CHANNEL1:
+   ch_reg = mmACP_I2SMICSP_RER1;
+   res_reg = mmACP_I2SMICSP_RCR1;
+   imr_reg = 

[v2, 2/2] ASoC: AMD: Configure channel 1 or channel 0 for capture

2018-06-07 Thread Akshu Agrawal
ST/CZ SoC have 2 channels for capture in the I2SSP path.
The DMA though these channels is done using the same dma
descriptors.
We configure the channel and enable it on the basis of
channel selected by machine driver. Machine driver knows
which codec sits on which channel and thus sends the information
to dma driver.

Signed-off-by: Akshu Agrawal 
---
v2: Split acp_dma_cap_channel into 2 functions.

This patch is dependent on ASoC: AMD: Change codec to channel link as per 
hardware redesign
https://patchwork.kernel.org/patch/10388099/

 sound/soc/amd/acp-da7219-max98357a.c | 43 +++---
 sound/soc/amd/acp-pcm-dma.c  | 71 +++-
 sound/soc/amd/acp.h  |  4 ++
 3 files changed, 111 insertions(+), 7 deletions(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index 566bd26..f42606e 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -149,6 +149,7 @@ static int cz_da7219_startup(struct snd_pcm_substream 
*substream)
   _rates);
 
machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->capture_channel = CAP_CHANNEL1;
return da7219_clk_enable(substream);
 }
 
@@ -172,7 +173,7 @@ static void cz_max_shutdown(struct snd_pcm_substream 
*substream)
da7219_clk_disable();
 }
 
-static int cz_dmic_startup(struct snd_pcm_substream *substream)
+static int cz_dmic0_startup(struct snd_pcm_substream *substream)
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
@@ -182,6 +183,17 @@ static int cz_dmic_startup(struct snd_pcm_substream 
*substream)
return da7219_clk_enable(substream);
 }
 
+static int cz_dmic1_startup(struct snd_pcm_substream *substream)
+{
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct snd_soc_card *card = rtd->card;
+   struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
+
+   machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->capture_channel = CAP_CHANNEL0;
+   return da7219_clk_enable(substream);
+}
+
 static void cz_dmic_shutdown(struct snd_pcm_substream *substream)
 {
da7219_clk_disable();
@@ -197,8 +209,13 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.shutdown = cz_max_shutdown,
 };
 
-static const struct snd_soc_ops cz_dmic_cap_ops = {
-   .startup = cz_dmic_startup,
+static const struct snd_soc_ops cz_dmic0_cap_ops = {
+   .startup = cz_dmic0_startup,
+   .shutdown = cz_dmic_shutdown,
+};
+
+static const struct snd_soc_ops cz_dmic1_cap_ops = {
+   .startup = cz_dmic1_startup,
.shutdown = cz_dmic_shutdown,
 };
 
@@ -241,8 +258,9 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.ops = _max_play_ops,
},
{
-   .name = "dmic",
-   .stream_name = "DMIC Capture",
+   /* C panel DMIC */
+   .name = "dmic0",
+   .stream_name = "DMIC0 Capture",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.3.auto",
.codec_dai_name = "adau7002-hifi",
@@ -250,7 +268,20 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1,
-   .ops = _dmic_cap_ops,
+   .ops = _dmic0_cap_ops,
+   },
+   {
+   /* A/B panel DMIC */
+   .name = "dmic1",
+   .stream_name = "DMIC1 Capture",
+   .platform_name = "acp_audio_dma.0.auto",
+   .cpu_dai_name = "designware-i2s.2.auto",
+   .codec_dai_name = "adau7002-hifi",
+   .codec_name = "ADAU7002:00",
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+   | SND_SOC_DAIFMT_CBM_CFM,
+   .dpcm_capture = 1,
+   .ops = _dmic1_cap_ops,
},
 };
 
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 1458b50..3c3d398 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -336,6 +336,61 @@ static void config_acp_dma(void __iomem *acp_mmio,
   rtd->dma_dscr_idx_2, asic_type);
 }
 
+static void acp_dma_cap_channel_enable(void __iomem *acp_mmio,
+  u16 cap_channel)
+{
+   u32 val, ch_reg, imr_reg, res_reg;
+
+   switch (cap_channel) {
+   case CAP_CHANNEL1:
+   ch_reg = mmACP_I2SMICSP_RER1;
+   res_reg = mmACP_I2SMICSP_RCR1;
+   imr_reg = 

[PATCH 1/2] ASoC: AMD: Add NULL pointer check

2018-06-07 Thread Akshu Agrawal
Fix crash in those platforms whose machine driver does not expose
platform_info. For those platforms we rely on default value and
select I2SSP channel.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 7720384..1458b50 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -773,7 +773,8 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
if (WARN_ON(!rtd))
return -EINVAL;
 
-   rtd->i2s_instance = pinfo->i2s_instance;
+   if (pinfo)
+   rtd->i2s_instance = pinfo->i2s_instance;
if (adata->asic_type == CHIP_STONEY) {
val = acp_reg_read(adata->acp_mmio,
   mmACP_I2S_16BIT_RESOLUTION_EN);
-- 
1.9.1



[PATCH 1/2] ASoC: AMD: Add NULL pointer check

2018-06-07 Thread Akshu Agrawal
Fix crash in those platforms whose machine driver does not expose
platform_info. For those platforms we rely on default value and
select I2SSP channel.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 7720384..1458b50 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -773,7 +773,8 @@ static int acp_dma_hw_params(struct snd_pcm_substream 
*substream,
if (WARN_ON(!rtd))
return -EINVAL;
 
-   rtd->i2s_instance = pinfo->i2s_instance;
+   if (pinfo)
+   rtd->i2s_instance = pinfo->i2s_instance;
if (adata->asic_type == CHIP_STONEY) {
val = acp_reg_read(adata->acp_mmio,
   mmACP_I2S_16BIT_RESOLUTION_EN);
-- 
1.9.1



[PATCH] ASoC: AMD: Configure channel 1 or channel 0 for capture

2018-05-31 Thread Akshu Agrawal
ST/CZ SoC have 2 channels for capture in the I2SSP path.
The DMA though these channels is done using the same dma
descriptors.
We configure the channel and enable it on the basis of
channel selected by machine driver. Machine driver knows
which codec sits on which channel and thus sends the information
to dma driver.

Signed-off-by: Akshu Agrawal 
---
This patch is dependent on ASoC: AMD: Change codec to channel link as per 
hardware redesign
https://patchwork.kernel.org/patch/10388099/

 sound/soc/amd/acp-da7219-max98357a.c | 43 +---
 sound/soc/amd/acp-pcm-dma.c  | 79 +++-
 sound/soc/amd/acp.h  |  4 ++
 3 files changed, 119 insertions(+), 7 deletions(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index 566bd26..f42606e 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -149,6 +149,7 @@ static int cz_da7219_startup(struct snd_pcm_substream 
*substream)
   _rates);
 
machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->capture_channel = CAP_CHANNEL1;
return da7219_clk_enable(substream);
 }
 
@@ -172,7 +173,7 @@ static void cz_max_shutdown(struct snd_pcm_substream 
*substream)
da7219_clk_disable();
 }
 
-static int cz_dmic_startup(struct snd_pcm_substream *substream)
+static int cz_dmic0_startup(struct snd_pcm_substream *substream)
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
@@ -182,6 +183,17 @@ static int cz_dmic_startup(struct snd_pcm_substream 
*substream)
return da7219_clk_enable(substream);
 }
 
+static int cz_dmic1_startup(struct snd_pcm_substream *substream)
+{
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct snd_soc_card *card = rtd->card;
+   struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
+
+   machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->capture_channel = CAP_CHANNEL0;
+   return da7219_clk_enable(substream);
+}
+
 static void cz_dmic_shutdown(struct snd_pcm_substream *substream)
 {
da7219_clk_disable();
@@ -197,8 +209,13 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.shutdown = cz_max_shutdown,
 };
 
-static const struct snd_soc_ops cz_dmic_cap_ops = {
-   .startup = cz_dmic_startup,
+static const struct snd_soc_ops cz_dmic0_cap_ops = {
+   .startup = cz_dmic0_startup,
+   .shutdown = cz_dmic_shutdown,
+};
+
+static const struct snd_soc_ops cz_dmic1_cap_ops = {
+   .startup = cz_dmic1_startup,
.shutdown = cz_dmic_shutdown,
 };
 
@@ -241,8 +258,9 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.ops = _max_play_ops,
},
{
-   .name = "dmic",
-   .stream_name = "DMIC Capture",
+   /* C panel DMIC */
+   .name = "dmic0",
+   .stream_name = "DMIC0 Capture",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.3.auto",
.codec_dai_name = "adau7002-hifi",
@@ -250,7 +268,20 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1,
-   .ops = _dmic_cap_ops,
+   .ops = _dmic0_cap_ops,
+   },
+   {
+   /* A/B panel DMIC */
+   .name = "dmic1",
+   .stream_name = "DMIC1 Capture",
+   .platform_name = "acp_audio_dma.0.auto",
+   .cpu_dai_name = "designware-i2s.2.auto",
+   .codec_dai_name = "adau7002-hifi",
+   .codec_name = "ADAU7002:00",
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+   | SND_SOC_DAIFMT_CBM_CFM,
+   .dpcm_capture = 1,
+   .ops = _dmic1_cap_ops,
},
 };
 
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 7720384..ad85354 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -336,6 +336,68 @@ static void config_acp_dma(void __iomem *acp_mmio,
   rtd->dma_dscr_idx_2, asic_type);
 }
 
+static void acp_dma_cap_channel(void __iomem *acp_mmio, u16 cap_channel,
+   bool enable)
+{
+   u32 val;
+
+   if (enable) {
+   switch (cap_channel) {
+   case CAP_CHANNEL1:
+   val = acp_reg_read(acp_mmio,
+  mmA

[PATCH] ASoC: AMD: Configure channel 1 or channel 0 for capture

2018-05-31 Thread Akshu Agrawal
ST/CZ SoC have 2 channels for capture in the I2SSP path.
The DMA though these channels is done using the same dma
descriptors.
We configure the channel and enable it on the basis of
channel selected by machine driver. Machine driver knows
which codec sits on which channel and thus sends the information
to dma driver.

Signed-off-by: Akshu Agrawal 
---
This patch is dependent on ASoC: AMD: Change codec to channel link as per 
hardware redesign
https://patchwork.kernel.org/patch/10388099/

 sound/soc/amd/acp-da7219-max98357a.c | 43 +---
 sound/soc/amd/acp-pcm-dma.c  | 79 +++-
 sound/soc/amd/acp.h  |  4 ++
 3 files changed, 119 insertions(+), 7 deletions(-)

diff --git a/sound/soc/amd/acp-da7219-max98357a.c 
b/sound/soc/amd/acp-da7219-max98357a.c
index 566bd26..f42606e 100644
--- a/sound/soc/amd/acp-da7219-max98357a.c
+++ b/sound/soc/amd/acp-da7219-max98357a.c
@@ -149,6 +149,7 @@ static int cz_da7219_startup(struct snd_pcm_substream 
*substream)
   _rates);
 
machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->capture_channel = CAP_CHANNEL1;
return da7219_clk_enable(substream);
 }
 
@@ -172,7 +173,7 @@ static void cz_max_shutdown(struct snd_pcm_substream 
*substream)
da7219_clk_disable();
 }
 
-static int cz_dmic_startup(struct snd_pcm_substream *substream)
+static int cz_dmic0_startup(struct snd_pcm_substream *substream)
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_card *card = rtd->card;
@@ -182,6 +183,17 @@ static int cz_dmic_startup(struct snd_pcm_substream 
*substream)
return da7219_clk_enable(substream);
 }
 
+static int cz_dmic1_startup(struct snd_pcm_substream *substream)
+{
+   struct snd_soc_pcm_runtime *rtd = substream->private_data;
+   struct snd_soc_card *card = rtd->card;
+   struct acp_platform_info *machine = snd_soc_card_get_drvdata(card);
+
+   machine->i2s_instance = I2S_SP_INSTANCE;
+   machine->capture_channel = CAP_CHANNEL0;
+   return da7219_clk_enable(substream);
+}
+
 static void cz_dmic_shutdown(struct snd_pcm_substream *substream)
 {
da7219_clk_disable();
@@ -197,8 +209,13 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.shutdown = cz_max_shutdown,
 };
 
-static const struct snd_soc_ops cz_dmic_cap_ops = {
-   .startup = cz_dmic_startup,
+static const struct snd_soc_ops cz_dmic0_cap_ops = {
+   .startup = cz_dmic0_startup,
+   .shutdown = cz_dmic_shutdown,
+};
+
+static const struct snd_soc_ops cz_dmic1_cap_ops = {
+   .startup = cz_dmic1_startup,
.shutdown = cz_dmic_shutdown,
 };
 
@@ -241,8 +258,9 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.ops = _max_play_ops,
},
{
-   .name = "dmic",
-   .stream_name = "DMIC Capture",
+   /* C panel DMIC */
+   .name = "dmic0",
+   .stream_name = "DMIC0 Capture",
.platform_name = "acp_audio_dma.0.auto",
.cpu_dai_name = "designware-i2s.3.auto",
.codec_dai_name = "adau7002-hifi",
@@ -250,7 +268,20 @@ static void cz_dmic_shutdown(struct snd_pcm_substream 
*substream)
.dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
| SND_SOC_DAIFMT_CBM_CFM,
.dpcm_capture = 1,
-   .ops = _dmic_cap_ops,
+   .ops = _dmic0_cap_ops,
+   },
+   {
+   /* A/B panel DMIC */
+   .name = "dmic1",
+   .stream_name = "DMIC1 Capture",
+   .platform_name = "acp_audio_dma.0.auto",
+   .cpu_dai_name = "designware-i2s.2.auto",
+   .codec_dai_name = "adau7002-hifi",
+   .codec_name = "ADAU7002:00",
+   .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+   | SND_SOC_DAIFMT_CBM_CFM,
+   .dpcm_capture = 1,
+   .ops = _dmic1_cap_ops,
},
 };
 
diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index 7720384..ad85354 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -336,6 +336,68 @@ static void config_acp_dma(void __iomem *acp_mmio,
   rtd->dma_dscr_idx_2, asic_type);
 }
 
+static void acp_dma_cap_channel(void __iomem *acp_mmio, u16 cap_channel,
+   bool enable)
+{
+   u32 val;
+
+   if (enable) {
+   switch (cap_channel) {
+   case CAP_CHANNEL1:
+   val = acp_reg_read(acp_mmio,
+  mmA

[v2] ASoC: AMD: make channel 1 dma as circular

2018-05-27 Thread Akshu Agrawal
channel 1: SYSMEM<->ACP
channel 2: ACP<->I2S
Instead of waiting on period interrupt of ch 2 and then starting
dma on ch1, we make ch1 dma as circular.
This removes dependency of period granularity on hw pointer.

Signed-off-by: Akshu Agrawal <akshu.agra...@amd.com>
Reviewed-by: Daniel Kurtz <djku...@chromium.org>
Tested-by: Daniel Kurtz <djku...@chromium.org>
---
v2: Fixed kbuild error

 sound/soc/amd/acp-pcm-dma.c | 74 ++---
 1 file changed, 10 insertions(+), 64 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index ac32dea..7720384 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -337,8 +337,7 @@ static void config_acp_dma(void __iomem *acp_mmio,
 }
 
 /* Start a given DMA channel transfer */
-static void acp_dma_start(void __iomem *acp_mmio,
- u16 ch_num, bool is_circular)
+static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
 {
u32 dma_ctrl;
 
@@ -369,11 +368,8 @@ static void acp_dma_start(void __iomem *acp_mmio,
break;
}
 
-   /* enable  for ACP SRAM to/from I2S DMA channel */
-   if (is_circular == true)
-   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
-   else
-   dma_ctrl &= ~ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
+   /* circular for both DMA channel */
+   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
 
acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
 }
@@ -617,7 +613,6 @@ static int acp_deinit(void __iomem *acp_mmio)
 /* ACP DMA irq handler routine for playback, capture usecases */
 static irqreturn_t dma_irq_handler(int irq, void *arg)
 {
-   u16 dscr_idx;
u32 intr_flag, ext_intr_status;
struct audio_drv_data *irq_data;
void __iomem *acp_mmio;
@@ -634,33 +629,13 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
if ((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) != 0) {
valid_irq = true;
-   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_13) ==
-   PLAYBACK_START_DMA_DESCR_CH13)
-   dscr_idx = PLAYBACK_END_DMA_DESCR_CH12;
-   else
-   dscr_idx = PLAYBACK_START_DMA_DESCR_CH12;
-   config_acp_dma_channel(acp_mmio, SYSRAM_TO_ACP_CH_NUM, dscr_idx,
-  1, 0);
-   acp_dma_start(acp_mmio, SYSRAM_TO_ACP_CH_NUM, false);
-
snd_pcm_period_elapsed(irq_data->play_i2ssp_stream);
-
acp_reg_write((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
if ((intr_flag & BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
-   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_9) ==
-   PLAYBACK_START_DMA_DESCR_CH9)
-   dscr_idx = PLAYBACK_END_DMA_DESCR_CH8;
-   else
-   dscr_idx = PLAYBACK_START_DMA_DESCR_CH8;
-   config_acp_dma_channel(acp_mmio,
-  SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM,
-  dscr_idx, 1, 0);
-   acp_dma_start(acp_mmio, SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM,
- false);
snd_pcm_period_elapsed(irq_data->play_i2sbt_stream);
acp_reg_write((intr_flag &
  BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) << 16,
@@ -669,38 +644,20 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
valid_irq = true;
-   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_15) ==
-   CAPTURE_START_DMA_DESCR_CH15)
-   dscr_idx = CAPTURE_END_DMA_DESCR_CH14;
-   else
-   dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
-   config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM, dscr_idx,
-  1, 0);
-   acp_dma_start(acp_mmio, ACP_TO_SYSRAM_CH_NUM, false);
-
+   snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
if ((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) != 0) {
valid_irq = true;
-   snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
acp_reg_write((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) 

[v2] ASoC: AMD: make channel 1 dma as circular

2018-05-27 Thread Akshu Agrawal
channel 1: SYSMEM<->ACP
channel 2: ACP<->I2S
Instead of waiting on period interrupt of ch 2 and then starting
dma on ch1, we make ch1 dma as circular.
This removes dependency of period granularity on hw pointer.

Signed-off-by: Akshu Agrawal 
Reviewed-by: Daniel Kurtz 
Tested-by: Daniel Kurtz 
---
v2: Fixed kbuild error

 sound/soc/amd/acp-pcm-dma.c | 74 ++---
 1 file changed, 10 insertions(+), 64 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index ac32dea..7720384 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -337,8 +337,7 @@ static void config_acp_dma(void __iomem *acp_mmio,
 }
 
 /* Start a given DMA channel transfer */
-static void acp_dma_start(void __iomem *acp_mmio,
- u16 ch_num, bool is_circular)
+static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
 {
u32 dma_ctrl;
 
@@ -369,11 +368,8 @@ static void acp_dma_start(void __iomem *acp_mmio,
break;
}
 
-   /* enable  for ACP SRAM to/from I2S DMA channel */
-   if (is_circular == true)
-   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
-   else
-   dma_ctrl &= ~ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
+   /* circular for both DMA channel */
+   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
 
acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
 }
@@ -617,7 +613,6 @@ static int acp_deinit(void __iomem *acp_mmio)
 /* ACP DMA irq handler routine for playback, capture usecases */
 static irqreturn_t dma_irq_handler(int irq, void *arg)
 {
-   u16 dscr_idx;
u32 intr_flag, ext_intr_status;
struct audio_drv_data *irq_data;
void __iomem *acp_mmio;
@@ -634,33 +629,13 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
if ((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) != 0) {
valid_irq = true;
-   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_13) ==
-   PLAYBACK_START_DMA_DESCR_CH13)
-   dscr_idx = PLAYBACK_END_DMA_DESCR_CH12;
-   else
-   dscr_idx = PLAYBACK_START_DMA_DESCR_CH12;
-   config_acp_dma_channel(acp_mmio, SYSRAM_TO_ACP_CH_NUM, dscr_idx,
-  1, 0);
-   acp_dma_start(acp_mmio, SYSRAM_TO_ACP_CH_NUM, false);
-
snd_pcm_period_elapsed(irq_data->play_i2ssp_stream);
-
acp_reg_write((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
if ((intr_flag & BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
-   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_9) ==
-   PLAYBACK_START_DMA_DESCR_CH9)
-   dscr_idx = PLAYBACK_END_DMA_DESCR_CH8;
-   else
-   dscr_idx = PLAYBACK_START_DMA_DESCR_CH8;
-   config_acp_dma_channel(acp_mmio,
-  SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM,
-  dscr_idx, 1, 0);
-   acp_dma_start(acp_mmio, SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM,
- false);
snd_pcm_period_elapsed(irq_data->play_i2sbt_stream);
acp_reg_write((intr_flag &
  BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) << 16,
@@ -669,38 +644,20 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
valid_irq = true;
-   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_15) ==
-   CAPTURE_START_DMA_DESCR_CH15)
-   dscr_idx = CAPTURE_END_DMA_DESCR_CH14;
-   else
-   dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
-   config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM, dscr_idx,
-  1, 0);
-   acp_dma_start(acp_mmio, ACP_TO_SYSRAM_CH_NUM, false);
-
+   snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
if ((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) != 0) {
valid_irq = true;
-   snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
acp_reg_write((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
-   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_11) =

[PATCH] ASoC: AMD: make channel 1 dma as circular

2018-05-25 Thread Akshu Agrawal
channel 1: SYSMEM<->ACP
channel 2: ACP<->I2S
Instead of waiting on period interrupt of ch 2 and then starting
dma on ch1, we make ch1 dma as circular.
This removes dependency of period granularity on hw pointer.

Signed-off-by: Akshu Agrawal <akshu.agra...@amd.com>
---
 sound/soc/amd/acp-pcm-dma.c | 72 +++--
 1 file changed, 10 insertions(+), 62 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index ac32dea..f1d8678 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -337,8 +337,7 @@ static void config_acp_dma(void __iomem *acp_mmio,
 }
 
 /* Start a given DMA channel transfer */
-static void acp_dma_start(void __iomem *acp_mmio,
- u16 ch_num, bool is_circular)
+static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
 {
u32 dma_ctrl;
 
@@ -369,11 +368,8 @@ static void acp_dma_start(void __iomem *acp_mmio,
break;
}
 
-   /* enable  for ACP SRAM to/from I2S DMA channel */
-   if (is_circular == true)
-   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
-   else
-   dma_ctrl &= ~ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
+   /* circular for both DMA channel */
+   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
 
acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
 }
@@ -617,7 +613,6 @@ static int acp_deinit(void __iomem *acp_mmio)
 /* ACP DMA irq handler routine for playback, capture usecases */
 static irqreturn_t dma_irq_handler(int irq, void *arg)
 {
-   u16 dscr_idx;
u32 intr_flag, ext_intr_status;
struct audio_drv_data *irq_data;
void __iomem *acp_mmio;
@@ -634,33 +629,13 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
if ((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) != 0) {
valid_irq = true;
-   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_13) ==
-   PLAYBACK_START_DMA_DESCR_CH13)
-   dscr_idx = PLAYBACK_END_DMA_DESCR_CH12;
-   else
-   dscr_idx = PLAYBACK_START_DMA_DESCR_CH12;
-   config_acp_dma_channel(acp_mmio, SYSRAM_TO_ACP_CH_NUM, dscr_idx,
-  1, 0);
-   acp_dma_start(acp_mmio, SYSRAM_TO_ACP_CH_NUM, false);
-
snd_pcm_period_elapsed(irq_data->play_i2ssp_stream);
-
acp_reg_write((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
if ((intr_flag & BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
-   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_9) ==
-   PLAYBACK_START_DMA_DESCR_CH9)
-   dscr_idx = PLAYBACK_END_DMA_DESCR_CH8;
-   else
-   dscr_idx = PLAYBACK_START_DMA_DESCR_CH8;
-   config_acp_dma_channel(acp_mmio,
-  SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM,
-  dscr_idx, 1, 0);
-   acp_dma_start(acp_mmio, SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM,
- false);
snd_pcm_period_elapsed(irq_data->play_i2sbt_stream);
acp_reg_write((intr_flag &
  BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) << 16,
@@ -669,38 +644,20 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
valid_irq = true;
-   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_15) ==
-   CAPTURE_START_DMA_DESCR_CH15)
-   dscr_idx = CAPTURE_END_DMA_DESCR_CH14;
-   else
-   dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
-   config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM, dscr_idx,
-  1, 0);
-   acp_dma_start(acp_mmio, ACP_TO_SYSRAM_CH_NUM, false);
-
+   snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
if ((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) != 0) {
valid_irq = true;
-   snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
acp_reg_write((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
-   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_11) ==
-   CAPTURE_START_DMA_D

[PATCH] ASoC: AMD: make channel 1 dma as circular

2018-05-25 Thread Akshu Agrawal
channel 1: SYSMEM<->ACP
channel 2: ACP<->I2S
Instead of waiting on period interrupt of ch 2 and then starting
dma on ch1, we make ch1 dma as circular.
This removes dependency of period granularity on hw pointer.

Signed-off-by: Akshu Agrawal 
---
 sound/soc/amd/acp-pcm-dma.c | 72 +++--
 1 file changed, 10 insertions(+), 62 deletions(-)

diff --git a/sound/soc/amd/acp-pcm-dma.c b/sound/soc/amd/acp-pcm-dma.c
index ac32dea..f1d8678 100644
--- a/sound/soc/amd/acp-pcm-dma.c
+++ b/sound/soc/amd/acp-pcm-dma.c
@@ -337,8 +337,7 @@ static void config_acp_dma(void __iomem *acp_mmio,
 }
 
 /* Start a given DMA channel transfer */
-static void acp_dma_start(void __iomem *acp_mmio,
- u16 ch_num, bool is_circular)
+static void acp_dma_start(void __iomem *acp_mmio, u16 ch_num)
 {
u32 dma_ctrl;
 
@@ -369,11 +368,8 @@ static void acp_dma_start(void __iomem *acp_mmio,
break;
}
 
-   /* enable  for ACP SRAM to/from I2S DMA channel */
-   if (is_circular == true)
-   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
-   else
-   dma_ctrl &= ~ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
+   /* circular for both DMA channel */
+   dma_ctrl |= ACP_DMA_CNTL_0__Circular_DMA_En_MASK;
 
acp_reg_write(dma_ctrl, acp_mmio, mmACP_DMA_CNTL_0 + ch_num);
 }
@@ -617,7 +613,6 @@ static int acp_deinit(void __iomem *acp_mmio)
 /* ACP DMA irq handler routine for playback, capture usecases */
 static irqreturn_t dma_irq_handler(int irq, void *arg)
 {
-   u16 dscr_idx;
u32 intr_flag, ext_intr_status;
struct audio_drv_data *irq_data;
void __iomem *acp_mmio;
@@ -634,33 +629,13 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
if ((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) != 0) {
valid_irq = true;
-   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_13) ==
-   PLAYBACK_START_DMA_DESCR_CH13)
-   dscr_idx = PLAYBACK_END_DMA_DESCR_CH12;
-   else
-   dscr_idx = PLAYBACK_START_DMA_DESCR_CH12;
-   config_acp_dma_channel(acp_mmio, SYSRAM_TO_ACP_CH_NUM, dscr_idx,
-  1, 0);
-   acp_dma_start(acp_mmio, SYSRAM_TO_ACP_CH_NUM, false);
-
snd_pcm_period_elapsed(irq_data->play_i2ssp_stream);
-
acp_reg_write((intr_flag & BIT(ACP_TO_I2S_DMA_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
if ((intr_flag & BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
-   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_9) ==
-   PLAYBACK_START_DMA_DESCR_CH9)
-   dscr_idx = PLAYBACK_END_DMA_DESCR_CH8;
-   else
-   dscr_idx = PLAYBACK_START_DMA_DESCR_CH8;
-   config_acp_dma_channel(acp_mmio,
-  SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM,
-  dscr_idx, 1, 0);
-   acp_dma_start(acp_mmio, SYSRAM_TO_ACP_BT_INSTANCE_CH_NUM,
- false);
snd_pcm_period_elapsed(irq_data->play_i2sbt_stream);
acp_reg_write((intr_flag &
  BIT(ACP_TO_I2S_DMA_BT_INSTANCE_CH_NUM)) << 16,
@@ -669,38 +644,20 @@ static irqreturn_t dma_irq_handler(int irq, void *arg)
 
if ((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) != 0) {
valid_irq = true;
-   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_15) ==
-   CAPTURE_START_DMA_DESCR_CH15)
-   dscr_idx = CAPTURE_END_DMA_DESCR_CH14;
-   else
-   dscr_idx = CAPTURE_START_DMA_DESCR_CH14;
-   config_acp_dma_channel(acp_mmio, ACP_TO_SYSRAM_CH_NUM, dscr_idx,
-  1, 0);
-   acp_dma_start(acp_mmio, ACP_TO_SYSRAM_CH_NUM, false);
-
+   snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
acp_reg_write((intr_flag & BIT(I2S_TO_ACP_DMA_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
if ((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) != 0) {
valid_irq = true;
-   snd_pcm_period_elapsed(irq_data->capture_i2ssp_stream);
acp_reg_write((intr_flag & BIT(ACP_TO_SYSRAM_CH_NUM)) << 16,
  acp_mmio, mmACP_EXTERNAL_INTR_STAT);
}
 
if ((intr_flag & BIT(I2S_TO_ACP_DMA_BT_INSTANCE_CH_NUM)) != 0) {
valid_irq = true;
-   if (acp_reg_read(acp_mmio, mmACP_DMA_CUR_DSCR_11) ==
-   CAPTURE_START_DMA_DESCR_C

[PATCH v3 2/2] ACPI: APD: Add AMD misc clock handler support

2018-05-09 Thread Akshu Agrawal
AMD SoC exposes clock for general purpose use. The clock registration
is done in clk-st driver. The MMIO mapping are passed on to the
clock driver for accessing the registers.
The misc clock handler will create MMIO mappings to access the
clock registers and enable the clock driver to expose the clock
for use of drivers which will connect to it.

Signed-off-by: Akshu Agrawal <akshu.agra...@amd.com>
---
v2: Submitted with dependent patch, removed unneeded kfree for devm_kzalloc
v3: used devm_ioremap and fix coccinelle warning
 drivers/acpi/acpi_apd.c | 47 +++
 1 file changed, 47 insertions(+)

diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index d553b00..2664452 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -11,6 +11,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -72,6 +73,47 @@ static int acpi_apd_setup(struct apd_private_data *pdata)
 }
 
 #ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
+
+static int misc_check_res(struct acpi_resource *ares, void *data)
+{
+   struct resource res;
+
+   return !acpi_dev_resource_memory(ares, );
+}
+
+static int st_misc_setup(struct apd_private_data *pdata)
+{
+   struct acpi_device *adev = pdata->adev;
+   struct platform_device *clkdev;
+   struct st_clk_data *clk_data;
+   struct resource_entry *rentry;
+   struct list_head resource_list;
+   int ret;
+
+   clk_data = devm_kzalloc(>dev, sizeof(*clk_data), GFP_KERNEL);
+   if (!clk_data)
+   return -ENOMEM;
+
+   INIT_LIST_HEAD(_list);
+   ret = acpi_dev_get_resources(adev, _list, misc_check_res,
+NULL);
+   if (ret < 0)
+   return -ENOENT;
+
+   list_for_each_entry(rentry, _list, node) {
+   clk_data->base = devm_ioremap(>dev, rentry->res->start,
+ resource_size(rentry->res));
+   break;
+   }
+
+   acpi_dev_free_resource_list(_list);
+
+   clkdev = platform_device_register_data(>dev, "clk-st",
+  PLATFORM_DEVID_NONE, clk_data,
+  sizeof(*clk_data));
+   return PTR_ERR_OR_ZERO(clkdev);
+}
+
 static const struct apd_device_desc cz_i2c_desc = {
.setup = acpi_apd_setup,
.fixed_clk_rate = 13300,
@@ -94,6 +136,10 @@ static int acpi_apd_setup(struct apd_private_data *pdata)
.fixed_clk_rate = 4800,
.properties = uart_properties,
 };
+
+static const struct apd_device_desc st_misc_desc = {
+   .setup = st_misc_setup,
+};
 #endif
 
 #ifdef CONFIG_ARM64
@@ -179,6 +225,7 @@ static int acpi_apd_create_device(struct acpi_device *adev,
{ "AMD0020", APD_ADDR(cz_uart_desc) },
{ "AMDI0020", APD_ADDR(cz_uart_desc) },
{ "AMD0030", },
+   { "AMD0040", APD_ADDR(st_misc_desc)},
 #endif
 #ifdef CONFIG_ARM64
{ "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
-- 
1.9.1



[PATCH v3 2/2] ACPI: APD: Add AMD misc clock handler support

2018-05-09 Thread Akshu Agrawal
AMD SoC exposes clock for general purpose use. The clock registration
is done in clk-st driver. The MMIO mapping are passed on to the
clock driver for accessing the registers.
The misc clock handler will create MMIO mappings to access the
clock registers and enable the clock driver to expose the clock
for use of drivers which will connect to it.

Signed-off-by: Akshu Agrawal 
---
v2: Submitted with dependent patch, removed unneeded kfree for devm_kzalloc
v3: used devm_ioremap and fix coccinelle warning
 drivers/acpi/acpi_apd.c | 47 +++
 1 file changed, 47 insertions(+)

diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c
index d553b00..2664452 100644
--- a/drivers/acpi/acpi_apd.c
+++ b/drivers/acpi/acpi_apd.c
@@ -11,6 +11,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -72,6 +73,47 @@ static int acpi_apd_setup(struct apd_private_data *pdata)
 }
 
 #ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
+
+static int misc_check_res(struct acpi_resource *ares, void *data)
+{
+   struct resource res;
+
+   return !acpi_dev_resource_memory(ares, );
+}
+
+static int st_misc_setup(struct apd_private_data *pdata)
+{
+   struct acpi_device *adev = pdata->adev;
+   struct platform_device *clkdev;
+   struct st_clk_data *clk_data;
+   struct resource_entry *rentry;
+   struct list_head resource_list;
+   int ret;
+
+   clk_data = devm_kzalloc(>dev, sizeof(*clk_data), GFP_KERNEL);
+   if (!clk_data)
+   return -ENOMEM;
+
+   INIT_LIST_HEAD(_list);
+   ret = acpi_dev_get_resources(adev, _list, misc_check_res,
+NULL);
+   if (ret < 0)
+   return -ENOENT;
+
+   list_for_each_entry(rentry, _list, node) {
+   clk_data->base = devm_ioremap(>dev, rentry->res->start,
+ resource_size(rentry->res));
+   break;
+   }
+
+   acpi_dev_free_resource_list(_list);
+
+   clkdev = platform_device_register_data(>dev, "clk-st",
+  PLATFORM_DEVID_NONE, clk_data,
+  sizeof(*clk_data));
+   return PTR_ERR_OR_ZERO(clkdev);
+}
+
 static const struct apd_device_desc cz_i2c_desc = {
.setup = acpi_apd_setup,
.fixed_clk_rate = 13300,
@@ -94,6 +136,10 @@ static int acpi_apd_setup(struct apd_private_data *pdata)
.fixed_clk_rate = 4800,
.properties = uart_properties,
 };
+
+static const struct apd_device_desc st_misc_desc = {
+   .setup = st_misc_setup,
+};
 #endif
 
 #ifdef CONFIG_ARM64
@@ -179,6 +225,7 @@ static int acpi_apd_create_device(struct acpi_device *adev,
{ "AMD0020", APD_ADDR(cz_uart_desc) },
{ "AMDI0020", APD_ADDR(cz_uart_desc) },
{ "AMD0030", },
+   { "AMD0040", APD_ADDR(st_misc_desc)},
 #endif
 #ifdef CONFIG_ARM64
{ "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
-- 
1.9.1



[PATCH v5 1/2] clk: x86: Add ST oscout platform clock

2018-05-09 Thread Akshu Agrawal
Stoney SoC provides oscout clock. This clock can support 25Mhz and
48Mhz of frequency.
The clock is available for general system use.

Signed-off-by: Akshu Agrawal <akshu.agra...@amd.com>
---
v2: config change, added SPDX tag and used clk_hw_register_.
v3: Fix kbuild warning for checking of NULL pointer
v4: unregister clk_hw in driver remove, add .suppress_bind_attrs
v5: Fix license, used static array
 drivers/clk/x86/Makefile |  3 +-
 drivers/clk/x86/clk-st.c | 77 
 include/linux/platform_data/clk-st.h | 17 
 3 files changed, 96 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/x86/clk-st.c
 create mode 100644 include/linux/platform_data/clk-st.h

diff --git a/drivers/clk/x86/Makefile b/drivers/clk/x86/Makefile
index 1367afb..00303bc 100644
--- a/drivers/clk/x86/Makefile
+++ b/drivers/clk/x86/Makefile
@@ -1,3 +1,4 @@
+obj-$(CONFIG_PMC_ATOM) += clk-pmc-atom.o
+obj-$(CONFIG_X86_AMD_PLATFORM_DEVICE)  += clk-st.o
 clk-x86-lpss-objs  := clk-lpt.o
 obj-$(CONFIG_X86_INTEL_LPSS)   += clk-x86-lpss.o
-obj-$(CONFIG_PMC_ATOM) += clk-pmc-atom.o
diff --git a/drivers/clk/x86/clk-st.c b/drivers/clk/x86/clk-st.c
new file mode 100644
index 000..fb62f39
--- /dev/null
+++ b/drivers/clk/x86/clk-st.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: MIT
+/*
+ * clock framework for AMD Stoney based clocks
+ *
+ * Copyright 2018 Advanced Micro Devices, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/* Clock Driving Strength 2 register */
+#define CLKDRVSTR2 0x28
+/* Clock Control 1 register */
+#define MISCCLKCNTL1   0x40
+/* Auxiliary clock1 enable bit */
+#define OSCCLKENB  2
+/* 25Mhz auxiliary output clock freq bit */
+#define OSCOUT1CLK25MHZ16
+
+#define ST_CLK_48M 0
+#define ST_CLK_25M 1
+#define ST_CLK_MUX 2
+#define ST_CLK_GATE3
+#define ST_MAX_CLKS4
+
+static const char * const clk_oscout1_parents[] = { "clk48MHz", "clk25MHz" };
+static struct clk_hw *hws[ST_MAX_CLKS];
+
+static int st_clk_probe(struct platform_device *pdev)
+{
+   struct st_clk_data *st_data;
+
+   st_data = dev_get_platdata(>dev);
+   if (!st_data || !st_data->base)
+   return -EINVAL;
+
+   hws[ST_CLK_48M] = clk_hw_register_fixed_rate(NULL, "clk48MHz", NULL, 0,
+4800);
+   hws[ST_CLK_25M] = clk_hw_register_fixed_rate(NULL, "clk25MHz", NULL, 0,
+2500);
+
+   hws[ST_CLK_MUX] = clk_hw_register_mux(NULL, "oscout1_mux",
+   clk_oscout1_parents, ARRAY_SIZE(clk_oscout1_parents),
+   0, st_data->base + CLKDRVSTR2, OSCOUT1CLK25MHZ, 3, 0, NULL);
+
+   clk_set_parent(hws[ST_CLK_MUX]->clk, hws[ST_CLK_25M]->clk);
+
+   hws[ST_CLK_GATE] = clk_hw_register_gate(NULL, "oscout1", "oscout1_mux",
+   0, st_data->base + MISCCLKCNTL1, OSCCLKENB,
+   CLK_GATE_SET_TO_DISABLE, NULL);
+
+   clk_hw_register_clkdev(hws[ST_CLK_GATE], "oscout1", NULL);
+
+   return 0;
+}
+
+static int st_clk_remove(struct platform_device *pdev)
+{
+   int i;
+
+   for (i = 0; i < ST_MAX_CLKS; i++)
+   clk_hw_unregister(hws[i]);
+   return 0;
+}
+
+static struct platform_driver st_clk_driver = {
+   .driver = {
+   .name = "clk-st",
+   .suppress_bind_attrs = true,
+   },
+   .probe = st_clk_probe,
+   .remove = st_clk_remove,
+};
+builtin_platform_driver(st_clk_driver);
diff --git a/include/linux/platform_data/clk-st.h 
b/include/linux/platform_data/clk-st.h
new file mode 100644
index 000..7cdb6a4
--- /dev/null
+++ b/include/linux/platform_data/clk-st.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * clock framework for AMD Stoney based clock
+ *
+ * Copyright 2018 Advanced Micro Devices, Inc.
+ */
+
+#ifndef __CLK_ST_H
+#define __CLK_ST_H
+
+#include 
+
+struct st_clk_data {
+   void __iomem *base;
+};
+
+#endif /* __CLK_ST_H */
-- 
1.9.1



[PATCH v3 0/2] Add support for general system clock on ST AMD platform

2018-05-09 Thread Akshu Agrawal
AMD ST/CZ platform provides a general system clock which can be used
by any driver. Registration of this clock will done in clk-st driver.
While the ACPI misc device will create the required MMIO mappings
and pass the same to the clk-st driver. The clk-st driver will
use the address to enable/disable and set frequency.

Changelog:
v2:
  clk: x86: Add ST oscout platform clock: v3->v4 unregister clk_hw
  ACPI: APD: Add AMD misc clock handler support: No change (v2)
v3:
  clk: x86: Add ST oscout platform clock:
v4->v5 use static array, change license
  ACPI: APD: Add AMD misc clock handler support:
v2->v3 use devm_ioremap, fix warning

Akshu Agrawal (2):
  clk: x86: Add ST oscout platform clock
  ACPI: APD: Add AMD misc clock handler support

 drivers/acpi/acpi_apd.c  | 50 
 drivers/clk/x86/Makefile |  1 +
 drivers/clk/x86/clk-st.c | 88 
 include/linux/platform_data/clk-st.h | 35 ++
 4 files changed, 174 insertions(+)
 create mode 100644 drivers/clk/x86/clk-st.c
 create mode 100644 include/linux/platform_data/clk-st.h

-- 
1.9.1



  1   2   >