Re: [PATCH 2/3] ASoC: lpass-platform: Fix broken pcm data usage

2016-10-29 Thread Kenneth Westfield
On Fri, Oct 28, 2016 at 04:32:19PM +0100, Srinivas Kandagatla wrote:
> This patch fixes lpass-platform driver which was broken in v4.9-rc1.
> lpass_pcm_data data structure holds information specific to stream.
> Holding a single private pointer to it in global lpass_data
> will not work, because it would be overwritten by for each pcm instance.
> 
> This code was breaking playback when we have both playback and capture
> pcm streams, as playback settings are over written by capture settings.
> 
> Fix this by moving channel allocation logic out of pcm_new to pcm_open
> so that we can store the stream specific information private_data of
> snd_pcm_runtime.
> 
> Fixes: 6adcbdcd4b6e ("ASoC: lpass-platform: don't use 
> snd_soc_pcm_set_drvdata()")
> Signed-off-by: Srinivas Kandagatla 
> ---
>  sound/soc/qcom/lpass-platform.c | 151 
> ++--
>  sound/soc/qcom/lpass.h  |   1 -
>  2 files changed, 67 insertions(+), 85 deletions(-)

After you address Mark's comments:

Acked-by: Kenneth Westfield 

-- 
Kenneth Westfield
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, 
a Linux Foundation Collaborative Project


Re: [PATCH 2/3] ASoC: lpass-platform: Fix broken pcm data usage

2016-10-29 Thread Kenneth Westfield
On Fri, Oct 28, 2016 at 04:32:19PM +0100, Srinivas Kandagatla wrote:
> This patch fixes lpass-platform driver which was broken in v4.9-rc1.
> lpass_pcm_data data structure holds information specific to stream.
> Holding a single private pointer to it in global lpass_data
> will not work, because it would be overwritten by for each pcm instance.
> 
> This code was breaking playback when we have both playback and capture
> pcm streams, as playback settings are over written by capture settings.
> 
> Fix this by moving channel allocation logic out of pcm_new to pcm_open
> so that we can store the stream specific information private_data of
> snd_pcm_runtime.
> 
> Fixes: 6adcbdcd4b6e ("ASoC: lpass-platform: don't use 
> snd_soc_pcm_set_drvdata()")
> Signed-off-by: Srinivas Kandagatla 
> ---
>  sound/soc/qcom/lpass-platform.c | 151 
> ++--
>  sound/soc/qcom/lpass.h  |   1 -
>  2 files changed, 67 insertions(+), 85 deletions(-)

After you address Mark's comments:

Acked-by: Kenneth Westfield 

-- 
Kenneth Westfield
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, 
a Linux Foundation Collaborative Project


Re: [PATCH 2/3] ASoC: lpass-platform: Fix broken pcm data usage

2016-10-28 Thread Srinivas Kandagatla



On 28/10/16 19:26, Mark Brown wrote:

On Fri, Oct 28, 2016 at 04:32:19PM +0100, Srinivas Kandagatla wrote:

This patch fixes lpass-platform driver which was broken in v4.9-rc1.
lpass_pcm_data data structure holds information specific to stream.
Holding a single private pointer to it in global lpass_data
will not work, because it would be overwritten by for each pcm instance.


This is a bug fix but you've made it depend on patch 1 which is just a
refactoring and should therefore not be sent to Linus as a fix.  Please
don't do this, fix bugs first then do any cleanups and new
functionality.  That way we can send fixes to Linus without needing to
pull in extra stuff.

Sorry about that, I will resend the fix patch without any dependencies.

Thanks,
srini






Re: [PATCH 2/3] ASoC: lpass-platform: Fix broken pcm data usage

2016-10-28 Thread Srinivas Kandagatla



On 28/10/16 19:26, Mark Brown wrote:

On Fri, Oct 28, 2016 at 04:32:19PM +0100, Srinivas Kandagatla wrote:

This patch fixes lpass-platform driver which was broken in v4.9-rc1.
lpass_pcm_data data structure holds information specific to stream.
Holding a single private pointer to it in global lpass_data
will not work, because it would be overwritten by for each pcm instance.


This is a bug fix but you've made it depend on patch 1 which is just a
refactoring and should therefore not be sent to Linus as a fix.  Please
don't do this, fix bugs first then do any cleanups and new
functionality.  That way we can send fixes to Linus without needing to
pull in extra stuff.

Sorry about that, I will resend the fix patch without any dependencies.

Thanks,
srini






Re: [PATCH 2/3] ASoC: lpass-platform: Fix broken pcm data usage

2016-10-28 Thread Mark Brown
On Fri, Oct 28, 2016 at 04:32:19PM +0100, Srinivas Kandagatla wrote:
> This patch fixes lpass-platform driver which was broken in v4.9-rc1.
> lpass_pcm_data data structure holds information specific to stream.
> Holding a single private pointer to it in global lpass_data
> will not work, because it would be overwritten by for each pcm instance.

This is a bug fix but you've made it depend on patch 1 which is just a
refactoring and should therefore not be sent to Linus as a fix.  Please
don't do this, fix bugs first then do any cleanups and new
functionality.  That way we can send fixes to Linus without needing to
pull in extra stuff.


signature.asc
Description: PGP signature


Re: [PATCH 2/3] ASoC: lpass-platform: Fix broken pcm data usage

2016-10-28 Thread Mark Brown
On Fri, Oct 28, 2016 at 04:32:19PM +0100, Srinivas Kandagatla wrote:
> This patch fixes lpass-platform driver which was broken in v4.9-rc1.
> lpass_pcm_data data structure holds information specific to stream.
> Holding a single private pointer to it in global lpass_data
> will not work, because it would be overwritten by for each pcm instance.

This is a bug fix but you've made it depend on patch 1 which is just a
refactoring and should therefore not be sent to Linus as a fix.  Please
don't do this, fix bugs first then do any cleanups and new
functionality.  That way we can send fixes to Linus without needing to
pull in extra stuff.


signature.asc
Description: PGP signature


[PATCH 2/3] ASoC: lpass-platform: Fix broken pcm data usage

2016-10-28 Thread Srinivas Kandagatla
This patch fixes lpass-platform driver which was broken in v4.9-rc1.
lpass_pcm_data data structure holds information specific to stream.
Holding a single private pointer to it in global lpass_data
will not work, because it would be overwritten by for each pcm instance.

This code was breaking playback when we have both playback and capture
pcm streams, as playback settings are over written by capture settings.

Fix this by moving channel allocation logic out of pcm_new to pcm_open
so that we can store the stream specific information private_data of
snd_pcm_runtime.

Fixes: 6adcbdcd4b6e ("ASoC: lpass-platform: don't use 
snd_soc_pcm_set_drvdata()")
Signed-off-by: Srinivas Kandagatla 
---
 sound/soc/qcom/lpass-platform.c | 151 ++--
 sound/soc/qcom/lpass.h  |   1 -
 2 files changed, 67 insertions(+), 85 deletions(-)

diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c
index 2570c96..4554cae 100644
--- a/sound/soc/qcom/lpass-platform.c
+++ b/sound/soc/qcom/lpass-platform.c
@@ -60,7 +60,36 @@ static int lpass_platform_pcmops_open(struct 
snd_pcm_substream *substream)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-   int ret;
+   struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
+   struct lpass_data *drvdata =
+   snd_soc_platform_get_drvdata(soc_runtime->platform);
+   struct lpass_variant *v = drvdata->variant;
+   int ret, dir = substream->stream;
+   struct lpass_pcm_data *data;
+
+   data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL);
+   if (!data)
+   return -ENOMEM;
+
+   data->i2s_port = cpu_dai->driver->id;
+   runtime->private_data = data;
+
+   if (v->alloc_dma_channel)
+   data->dma_ch = v->alloc_dma_channel(drvdata, dir);
+   if (data->dma_ch < 0)
+   return data->dma_ch;
+
+   drvdata->substream[data->dma_ch] = substream;
+
+   ret = regmap_write(drvdata->lpaif_map,
+   LPAIF_DMACTL_REG(v, data->dma_ch, dir), 0);
+   if (ret) {
+   dev_err(soc_runtime->dev,
+   "%s() error writing to rdmactl reg: %d\n",
+   __func__, ret);
+   return ret;
+   }
+
 
snd_soc_set_runtime_hwparams(substream, _platform_pcm_hardware);
 
@@ -79,13 +108,32 @@ static int lpass_platform_pcmops_open(struct 
snd_pcm_substream *substream)
return 0;
 }
 
+static int lpass_platform_pcmops_close(struct snd_pcm_substream *substream)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+   struct lpass_data *drvdata =
+   snd_soc_platform_get_drvdata(soc_runtime->platform);
+   struct lpass_variant *v = drvdata->variant;
+   struct lpass_pcm_data *data;
+
+   data = runtime->private_data;
+   v = drvdata->variant;
+   drvdata->substream[data->dma_ch] = NULL;
+   if (v->free_dma_channel)
+   v->free_dma_channel(drvdata, data->dma_ch);
+
+   return 0;
+}
+
 static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
 {
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
struct lpass_data *drvdata =
snd_soc_platform_get_drvdata(soc_runtime->platform);
-   struct lpass_pcm_data *pcm_data = drvdata->private_data;
+   struct snd_pcm_runtime *rt = substream->runtime;
+   struct lpass_pcm_data *pcm_data = rt->private_data;
struct lpass_variant *v = drvdata->variant;
snd_pcm_format_t format = params_format(params);
unsigned int channels = params_channels(params);
@@ -175,7 +223,8 @@ static int lpass_platform_pcmops_hw_free(struct 
snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
struct lpass_data *drvdata =
snd_soc_platform_get_drvdata(soc_runtime->platform);
-   struct lpass_pcm_data *pcm_data = drvdata->private_data;
+   struct snd_pcm_runtime *rt = substream->runtime;
+   struct lpass_pcm_data *pcm_data = rt->private_data;
struct lpass_variant *v = drvdata->variant;
unsigned int reg;
int ret;
@@ -195,7 +244,8 @@ static int lpass_platform_pcmops_prepare(struct 
snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
struct lpass_data *drvdata =
snd_soc_platform_get_drvdata(soc_runtime->platform);
-   struct lpass_pcm_data *pcm_data = drvdata->private_data;
+   struct snd_pcm_runtime *rt = substream->runtime;
+   struct lpass_pcm_data *pcm_data = rt->private_data;
struct lpass_variant *v = drvdata->variant;

[PATCH 2/3] ASoC: lpass-platform: Fix broken pcm data usage

2016-10-28 Thread Srinivas Kandagatla
This patch fixes lpass-platform driver which was broken in v4.9-rc1.
lpass_pcm_data data structure holds information specific to stream.
Holding a single private pointer to it in global lpass_data
will not work, because it would be overwritten by for each pcm instance.

This code was breaking playback when we have both playback and capture
pcm streams, as playback settings are over written by capture settings.

Fix this by moving channel allocation logic out of pcm_new to pcm_open
so that we can store the stream specific information private_data of
snd_pcm_runtime.

Fixes: 6adcbdcd4b6e ("ASoC: lpass-platform: don't use 
snd_soc_pcm_set_drvdata()")
Signed-off-by: Srinivas Kandagatla 
---
 sound/soc/qcom/lpass-platform.c | 151 ++--
 sound/soc/qcom/lpass.h  |   1 -
 2 files changed, 67 insertions(+), 85 deletions(-)

diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c
index 2570c96..4554cae 100644
--- a/sound/soc/qcom/lpass-platform.c
+++ b/sound/soc/qcom/lpass-platform.c
@@ -60,7 +60,36 @@ static int lpass_platform_pcmops_open(struct 
snd_pcm_substream *substream)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
-   int ret;
+   struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
+   struct lpass_data *drvdata =
+   snd_soc_platform_get_drvdata(soc_runtime->platform);
+   struct lpass_variant *v = drvdata->variant;
+   int ret, dir = substream->stream;
+   struct lpass_pcm_data *data;
+
+   data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL);
+   if (!data)
+   return -ENOMEM;
+
+   data->i2s_port = cpu_dai->driver->id;
+   runtime->private_data = data;
+
+   if (v->alloc_dma_channel)
+   data->dma_ch = v->alloc_dma_channel(drvdata, dir);
+   if (data->dma_ch < 0)
+   return data->dma_ch;
+
+   drvdata->substream[data->dma_ch] = substream;
+
+   ret = regmap_write(drvdata->lpaif_map,
+   LPAIF_DMACTL_REG(v, data->dma_ch, dir), 0);
+   if (ret) {
+   dev_err(soc_runtime->dev,
+   "%s() error writing to rdmactl reg: %d\n",
+   __func__, ret);
+   return ret;
+   }
+
 
snd_soc_set_runtime_hwparams(substream, _platform_pcm_hardware);
 
@@ -79,13 +108,32 @@ static int lpass_platform_pcmops_open(struct 
snd_pcm_substream *substream)
return 0;
 }
 
+static int lpass_platform_pcmops_close(struct snd_pcm_substream *substream)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
+   struct lpass_data *drvdata =
+   snd_soc_platform_get_drvdata(soc_runtime->platform);
+   struct lpass_variant *v = drvdata->variant;
+   struct lpass_pcm_data *data;
+
+   data = runtime->private_data;
+   v = drvdata->variant;
+   drvdata->substream[data->dma_ch] = NULL;
+   if (v->free_dma_channel)
+   v->free_dma_channel(drvdata, data->dma_ch);
+
+   return 0;
+}
+
 static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
 {
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
struct lpass_data *drvdata =
snd_soc_platform_get_drvdata(soc_runtime->platform);
-   struct lpass_pcm_data *pcm_data = drvdata->private_data;
+   struct snd_pcm_runtime *rt = substream->runtime;
+   struct lpass_pcm_data *pcm_data = rt->private_data;
struct lpass_variant *v = drvdata->variant;
snd_pcm_format_t format = params_format(params);
unsigned int channels = params_channels(params);
@@ -175,7 +223,8 @@ static int lpass_platform_pcmops_hw_free(struct 
snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
struct lpass_data *drvdata =
snd_soc_platform_get_drvdata(soc_runtime->platform);
-   struct lpass_pcm_data *pcm_data = drvdata->private_data;
+   struct snd_pcm_runtime *rt = substream->runtime;
+   struct lpass_pcm_data *pcm_data = rt->private_data;
struct lpass_variant *v = drvdata->variant;
unsigned int reg;
int ret;
@@ -195,7 +244,8 @@ static int lpass_platform_pcmops_prepare(struct 
snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
struct lpass_data *drvdata =
snd_soc_platform_get_drvdata(soc_runtime->platform);
-   struct lpass_pcm_data *pcm_data = drvdata->private_data;
+   struct snd_pcm_runtime *rt = substream->runtime;
+   struct lpass_pcm_data *pcm_data = rt->private_data;
struct lpass_variant *v = drvdata->variant;
int ret, ch, dir =