Re: [RFC PATCH 07/40] soundwire: intel: fix channel number reported by hardware

2019-08-02 Thread Pierre-Louis Bossart




On 8/2/19 6:57 AM, Vinod Koul wrote:

On 25-07-19, 18:39, Pierre-Louis Bossart wrote:

PDI2 reports an invalid count, force the correct hardware-supported
value

Signed-off-by: Pierre-Louis Bossart 
---
  drivers/soundwire/intel.c | 9 +
  1 file changed, 9 insertions(+)

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 497879dd9c0d..51990b192dc0 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -401,6 +401,15 @@ intel_pdi_get_ch_cap(struct sdw_intel *sdw, unsigned int 
pdi_num, bool pcm)
  
  	if (pcm) {

count = intel_readw(shim, SDW_SHIM_PCMSYCHC(link_id, pdi_num));
+
+   /*
+* TODO: pdi number 2 reports channel count as 1 even though
+* it supports 8 channel. Performing hardcoding for pdi
+* number 2.
+*/
+   if (pdi_num == 2)
+   count = 7;


Is that true for all Intel controllers or some generations. Would it not
be better to put this under some flag which is set on platform basis?


This is true of all controllers released so far.
We will change this if the hardware changes.




+
} else {
count = intel_readw(shim, SDW_SHIM_PDMSCAP(link_id));
count = ((count & SDW_SHIM_PDMSCAP_CPSS) >>
--
2.20.1




Re: [alsa-devel] [RFC PATCH 06/40] soundwire: intel: prevent possible dereference in hw_params

2019-08-02 Thread Pierre-Louis Bossart




On 8/2/19 6:55 AM, Vinod Koul wrote:

On 25-07-19, 18:39, Pierre-Louis Bossart wrote:

This should not happen in production systems but we should test for
all callback arguments before invoking the config_stream callback.


so you are saying callback arg is mandatory, if so please document that
assumption


no, what this says is that if a config_stream is provided then it needs 
to have a valid argument.


I am not sure what you mean by "document that assumption", comment in 
the code (where?) or SoundWire documentation?





Signed-off-by: Pierre-Louis Bossart 
---
  drivers/soundwire/intel.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 68832e613b1e..497879dd9c0d 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -509,7 +509,7 @@ static int intel_config_stream(struct sdw_intel *sdw,
   struct snd_soc_dai *dai,
   struct snd_pcm_hw_params *hw_params, int link_id)
  {
-   if (sdw->res->ops && sdw->res->ops->config_stream)
+   if (sdw->res->ops && sdw->res->ops->config_stream && sdw->res->arg)
return sdw->res->ops->config_stream(sdw->res->arg,
substream, dai, hw_params, link_id);
  
--

2.20.1




Re: [RFC PATCH 05/40] soundwire: intel: move interrupt enable after interrupt handler registration

2019-08-02 Thread Pierre-Louis Bossart




On 8/2/19 6:53 AM, Vinod Koul wrote:

On 25-07-19, 18:39, Pierre-Louis Bossart wrote:

Not sure why the existing code would enable interrupts without the
ability to deal with them.

Signed-off-by: Pierre-Louis Bossart 
---
  drivers/soundwire/intel.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index aeadc341c0a3..68832e613b1e 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -981,8 +981,6 @@ static int intel_probe(struct platform_device *pdev)
if (ret)
goto err_init;
  
-	ret = sdw_cdns_enable_interrupt(>cdns);

-
/* Read the PDI config and initialize cadence PDI */
intel_pdi_init(sdw, );
ret = sdw_cdns_pdi_init(>cdns, config);
@@ -1000,6 +998,8 @@ static int intel_probe(struct platform_device *pdev)
goto err_init;
}
  
+	ret = sdw_cdns_enable_interrupt(>cdns);


we should also handle the return


yes, fixed already


Re: linux-next: manual merge of the sound-asoc tree with the sound tree

2019-08-01 Thread Pierre-Louis Bossart




On 7/31/19 9:50 PM, Stephen Rothwell wrote:

Hi all,

Today's linux-next merge of the sound-asoc tree got conflicts in:

   sound/soc/intel/skylake/skl-nhlt.c
   sound/soc/intel/skylake/skl.h

between commit:

   1169cbf6b98e ("ASoC: Intel: Skylake: use common NHLT module")

from the sound tree and commit:

   bcc2a2dc3ba8 ("ASoC: Intel: Skylake: Merge skl_sst and skl into skl_dev 
struct")

from the sound-asoc tree.

I fixed it up (I think, see below (I used the sound tree version of
ound/soc/intel/skylake/skl-nhlt.c)) and can carry the fix as necessary.
This is now fixed as far as linux-next is concerned, but any non
trivial conflicts should be mentioned to your upstream maintainer when
your tree is submitted for merging.  You may also want to consider
cooperating with the maintainer of the conflicting tree to minimise any
particularly complex conflicts.


Mark, this comes my NHLT fixes merged by Takashi and available on his 
topic/hda-dmic branch.


This can be fixed by merging this topic/hda-dmic into your for-next 
branch, with a minor set of merge conflicts already identified by Stephen.


If you don't like merge conflicts, we can also do this with 
revert-merge-reapply, I pushed a branch 
https://github.com/plbossart/sound/commits/fix/nhlt-conflicts to provide 
the sequence needed


Sorry about that, let me know if I can help further.
-Pierre



Re: [alsa-devel] [RFC PATCH 17/40] soundwire: bus: use runtime_pm_get_sync/pm when enabled

2019-07-30 Thread Pierre-Louis Bossart




On 7/30/19 6:21 AM, Andy Shevchenko wrote:

On Mon, Jul 29, 2019 at 05:07:39PM -0500, Pierre-Louis Bossart wrote:

On 7/26/19 2:08 PM, Andy Shevchenko wrote:

On Fri, Jul 26, 2019 at 01:08:57PM -0500, Pierre-Louis Bossart wrote:



-   if (ret < 0)
+   if (ret < 0 && ret != -EACCES)


...and here, the pm_runtime_put_noidle() call is missed.


yes but in the example you provided, they actually do more work than just
decrement the device usage counter:


In their case they would like to do that. You decide what is appropriate call
in your case.

My point is, that reference counter in case of error handling should be
returned back to its value.


Agree on the reference count.
I am however not clear on the next step and 'what is appropriate'.

If pm_runtime_get_sync() failed, then technically the device was not 
resumed so marking it as last_busy+autosuspend, or using a plain vanilla 
put() will not result in any action. I must be missing something here.


Re: [alsa-devel] [RFC PATCH 17/40] soundwire: bus: use runtime_pm_get_sync/pm when enabled

2019-07-29 Thread Pierre-Louis Bossart




On 7/26/19 2:08 PM, Andy Shevchenko wrote:

On Fri, Jul 26, 2019 at 01:08:57PM -0500, Pierre-Louis Bossart wrote:

This thread became unreadable with interleaved top-posting, allow me restate
the options and ask PM folks what they think

On 7/25/19 6:40 PM, Pierre-Louis Bossart wrote:

Not all platforms support runtime_pm for now, let's use runtime_pm
only when enabled.


Just a side note below...


-   ret = pm_runtime_get_sync(slave->bus->dev);
-   if (ret < 0)


Here...


-   return ret;
+   if (pm_runtime_enabled(slave->bus->dev)) {
+   ret = pm_runtime_get_sync(slave->bus->dev);
+   if (ret < 0)


...and thus here...


+   return ret;
+   }
ret = sdw_transfer(slave->bus, );
-   pm_runtime_put(slave->bus->dev);
+
+   if (pm_runtime_enabled(slave->bus->dev))
+   pm_runtime_put(slave->bus->dev);


This is option1: we explicitly test if pm_runtime is enabled before calling
_get_sync() and _put()

option2 (suggested by Jan Kotas): catch the -EACCESS error code

ret = pm_runtime_get_sync(slave->bus->dev);
-   if (ret < 0)
+   if (ret < 0 && ret != -EACCES)


...and here, the pm_runtime_put_noidle() call is missed.


yes but in the example you provided, they actually do more work than 
just decrement the device usage counter:


static int
radeonfb_open(struct fb_info *info, int user)
{
struct radeon_fbdev *rfbdev = info->par;
struct radeon_device *rdev = rfbdev->rdev;
int ret = pm_runtime_get_sync(rdev->ddev->dev);
if (ret < 0 && ret != -EACCES) {
pm_runtime_mark_last_busy(rdev->ddev->dev);
pm_runtime_put_autosuspend(rdev->ddev->dev);
return ret;
}
return 0;
}

unless I am missing something pm_runtime_put_noidle() and 
_put_autosuspend() are not equivalent, are they?


Re: [RFC PATCH 17/40] soundwire: bus: use runtime_pm_get_sync/pm when enabled

2019-07-26 Thread Pierre-Louis Bossart
This thread became unreadable with interleaved top-posting, allow me 
restate the options and ask PM folks what they think


On 7/25/19 6:40 PM, Pierre-Louis Bossart wrote:

Not all platforms support runtime_pm for now, let's use runtime_pm
only when enabled.

Suggested-by: Srinivas Kandagatla 
Signed-off-by: Pierre-Louis Bossart 
---
  drivers/soundwire/bus.c | 25 -
  1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
index 5ad4109dc72f..0a45dc5713df 100644
--- a/drivers/soundwire/bus.c
+++ b/drivers/soundwire/bus.c
@@ -332,12 +332,16 @@ int sdw_nread(struct sdw_slave *slave, u32 addr, size_t 
count, u8 *val)
if (ret < 0)
return ret;
  
-	ret = pm_runtime_get_sync(slave->bus->dev);

-   if (ret < 0)
-   return ret;
+   if (pm_runtime_enabled(slave->bus->dev)) {
+   ret = pm_runtime_get_sync(slave->bus->dev);
+   if (ret < 0)
+   return ret;
+   }
  
  	ret = sdw_transfer(slave->bus, );

-   pm_runtime_put(slave->bus->dev);
+
+   if (pm_runtime_enabled(slave->bus->dev))
+   pm_runtime_put(slave->bus->dev);


This is option1: we explicitly test if pm_runtime is enabled before 
calling _get_sync() and _put()


option2 (suggested by Jan Kotas): catch the -EACCESS error code

ret = pm_runtime_get_sync(slave->bus->dev);
-   if (ret < 0)
+   if (ret < 0 && ret != -EACCES)
return ret;

option3: ignore the return value as done in quite a few drivers

Are there any other options? I am personally surprised this is not 
handled in the pm_runtime core, not sure why users need to test for this?


Thanks
Pierre


Re: [alsa-devel] [RFC PATCH 27/40] soundwire: Add Intel resource management algorithm

2019-07-26 Thread Pierre-Louis Bossart
Thanks Guennadi for looking at this code, it's hard to review and figure 
things out...

I replied to each, even trivial ones, to have a trace of all the issues.


+static void sdw_compute_slave_ports(struct sdw_master_runtime *m_rt,
+   struct sdw_transport_data *t_data)
+{
+   struct sdw_slave_runtime *s_rt = NULL;


Superfluous initialisation.


ok




+   struct sdw_port_runtime *p_rt;
+   int port_bo, sample_int;
+   unsigned int rate, bps, ch = 0;


ditto for ch


ok


+
+   port_bo = t_data->block_offset;
+
+   list_for_each_entry(s_rt, _rt->slave_rt_list, m_rt_node) {
+   rate = m_rt->stream->params.rate;
+   bps = m_rt->stream->params.bps;
+   sample_int = (m_rt->bus->params.curr_dr_freq / rate);
+
+   list_for_each_entry(p_rt, _rt->port_list, port_node) {
+   ch = sdw_ch_mask_to_ch(p_rt->ch_mask);
+
+   sdw_fill_xport_params(_rt->transport_params,
+ p_rt->num, true,
+ SDW_BLK_GRP_CNT_1,
+ sample_int, port_bo, port_bo >> 8,
+ t_data->hstart,
+ t_data->hstop,


I think the above two lines could fit in one


likely yes.




+ (SDW_BLK_GRP_CNT_1 * ch), 0x0);


superfluous parentheses


yep



+static void sdw_compute_master_ports(struct sdw_master_runtime *m_rt,
+struct sdw_group_params *params,
+int port_bo, int hstop)
+{
+   struct sdw_transport_data t_data = {0};
+   struct sdw_port_runtime *p_rt;
+   struct sdw_bus *bus = m_rt->bus;
+   int sample_int, hstart = 0;


superfluous initialisation


yes




+   unsigned int rate, bps, ch, no_ch;
+
+   rate = m_rt->stream->params.rate;
+   bps = m_rt->stream->params.bps;
+   ch = m_rt->ch_count;
+   sample_int = (bus->params.curr_dr_freq / rate);


superfluous parentheses


yes


+
+   if (rate != params->rate)
+   return;
+
+   t_data.hstop = hstop;
+   hstart = hstop - params->hwidth + 1;
+   t_data.hstart = hstart;
+
+   list_for_each_entry(p_rt, _rt->port_list, port_node) {
+   no_ch = sdw_ch_mask_to_ch(p_rt->ch_mask);
+
+   sdw_fill_xport_params(_rt->transport_params, p_rt->num,
+ true, SDW_BLK_GRP_CNT_1, sample_int,
+ port_bo, port_bo >> 8, hstart, hstop,
+ (SDW_BLK_GRP_CNT_1 * no_ch), 0x0);


superfluous parentheses


yes




+
+   sdw_fill_port_params(_rt->port_params,
+p_rt->num, bps,
+SDW_PORT_FLOW_MODE_ISOCH,
+SDW_PORT_DATA_MODE_NORMAL);
+
+   /* Check for first entry */
+   if (!(p_rt == list_first_entry(_rt->port_list,
+  struct sdw_port_runtime,
+  port_node))) {


you wanted to write "if (p_rt != ...)"


bad code indeed, thanks for spotting this. I need to double-check this 
one, now I don't trust the ==

it could also be that it was meant to be a NULL check on the first entry.




+   port_bo += bps * ch;
+   continue;
+   }
+
+   t_data.hstart = hstart;
+   t_data.hstop = hstop;


You already set these two above


need to check this as well.




+   t_data.block_offset = port_bo;
+   t_data.sub_block_offset = 0;
+   port_bo += bps * ch;
+   }
+
+   sdw_compute_slave_ports(m_rt, _data);
+}
+
+static void _sdw_compute_port_params(struct sdw_bus *bus,
+struct sdw_group_params *params, int count)
+{
+   struct sdw_master_runtime *m_rt = NULL;


superfluous initialisation


yes




+   int hstop = bus->params.col - 1;
+   int block_offset, port_bo, i;
+
+   /* Run loop for all groups to compute transport parameters */
+   for (i = 0; i < count; i++) {
+   port_bo = 1;
+   block_offset = 1;
+
+   list_for_each_entry(m_rt, >m_rt_list, bus_node) {
+   sdw_compute_master_ports(m_rt, [i],
+port_bo, hstop);
+
+   block_offset += m_rt->ch_count *
+   m_rt->stream->params.bps;
+   port_bo = block_offset;
+   }
+
+   hstop = hstop - params[i].hwidth;


hstop -= ...


yes




+   }
+}
+
+static int sdw_compute_group_params(struct sdw_bus *bus,
+   

Re: [alsa-devel] [RFC PATCH 38/40] soundwire: cadence_master: make clock stop exit configurable on init

2019-07-26 Thread Pierre-Louis Bossart




-int sdw_cdns_init(struct sdw_cdns *cdns);
+int sdw_cdns_init(struct sdw_cdns *cdns, bool clock_stop_exit);
  int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
  struct sdw_cdns_stream_config config);
  int sdw_cdns_exit_reset(struct sdw_cdns *cdns);
diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 1192d5775484..db7bf2912767 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -1043,7 +1043,7 @@ static int intel_init(struct sdw_intel *sdw)
intel_link_power_up(sdw);
intel_shim_init(sdw);
  
-	return sdw_cdns_init(>cdns);

+   return sdw_cdns_init(>cdns, false);


This is the only caller of this function so far, so, it looks like
the second argument ATM is always "false." I assume you foresee other
uses with "true" in the future, otherwise maybe just fix it to false
in the function?


Since we are at RFC level things are not set in stone, it's not fully 
clear if this test is required or not. I added it since Rander reported 
an error on one of the target platforms that I didn't see personally. 
We'll double-check if it's needed. And if indeed it's needed, yes it'll 
be set to true when we add clock stop.


Re: [alsa-devel] [RFC PATCH 37/40] soundwire: cadence_master: add hw_reset capability in debugfs

2019-07-26 Thread Pierre-Louis Bossart




+static int cdns_hw_reset(void *data, u64 value)
+{
+   struct sdw_cdns *cdns = data;
+   int ret;
+
+   if (value != 1)
+   return 0;
+
+   dev_info(cdns->dev, "starting link hw_reset\n");
+
+   ret = sdw_cdns_exit_reset(cdns);
+
+   dev_info(cdns->dev, "link hw_reset done\n");


Both really should be dev_info()? Maybe at least one of them can be dev_dbg()?


I have to walk back on what I explained to Greg. The idea was to have a 
dmesg trace when this function as called when the user plays with 
debugfs, otherwise the dmesg log is difficult to interpret (devices can 
go off the bus on their own). I'll keep the first one only and demote it 
to dev_dbg.


Re: [alsa-devel] [RFC PATCH 36/40] soundwire: intel: disable interrupts on suspend

2019-07-26 Thread Pierre-Louis Bossart




-int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns)
+int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns, bool state)
  {
u32 mask;
  
-	cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK0,

-   CDNS_MCP_SLAVE_INTMASK0_MASK);
-   cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK1,
-   CDNS_MCP_SLAVE_INTMASK1_MASK);
+   if (state) {
+   cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK0,
+   CDNS_MCP_SLAVE_INTMASK0_MASK);
+   cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK1,
+   CDNS_MCP_SLAVE_INTMASK1_MASK);
  
-	/* enable detection of slave state changes */

-   mask = CDNS_MCP_INT_SLAVE_RSVD | CDNS_MCP_INT_SLAVE_ALERT |
-   CDNS_MCP_INT_SLAVE_ATTACH | CDNS_MCP_INT_SLAVE_NATTACH;
+   /* enable detection of slave state changes */
+   mask = CDNS_MCP_INT_SLAVE_RSVD | CDNS_MCP_INT_SLAVE_ALERT |
+   CDNS_MCP_INT_SLAVE_ATTACH | CDNS_MCP_INT_SLAVE_NATTACH;
  
-	/* enable detection of bus issues */

-   mask |= CDNS_MCP_INT_CTRL_CLASH | CDNS_MCP_INT_DATA_CLASH |
-   CDNS_MCP_INT_PARITY;
+   /* enable detection of bus issues */
+   mask |= CDNS_MCP_INT_CTRL_CLASH | CDNS_MCP_INT_DATA_CLASH |
+   CDNS_MCP_INT_PARITY;
  
-	/* no detection of port interrupts for now */

+   /* no detection of port interrupts for now */
  
-	/* enable detection of RX fifo level */

-   mask |= CDNS_MCP_INT_RX_WL;
+   /* enable detection of RX fifo level */
+   mask |= CDNS_MCP_INT_RX_WL;
  
-	/* now enable all of the above */

-   mask |= CDNS_MCP_INT_IRQ;
+   /* now enable all of the above */
+   mask |= CDNS_MCP_INT_IRQ;
  
-	if (interrupt_mask) /* parameter override */

-   mask = interrupt_mask;
+   if (interrupt_mask) /* parameter override */
+   mask = interrupt_mask;
+   } else {
+   cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK0, 0);
+   cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK1, 0);
+   mask = 0;
+   }


Looks like this should be two functions? Especially since "state" is always a 
constant
when it is called. If there is still a lot of common code below, maybe make it 
a helper
function.


Yes, the code is a bit ugly. I could initialize all the masks to zero, 
have the if(state) block and write the masks.


Re: [alsa-devel] [RFC PATCH 35/40] soundwire: intel: export helper to exit reset

2019-07-26 Thread Pierre-Louis Bossart




@@ -161,6 +161,7 @@ irqreturn_t sdw_cdns_thread(int irq, void *dev_id);
  int sdw_cdns_init(struct sdw_cdns *cdns);
  int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
  struct sdw_cdns_stream_config config);
+int sdw_cdns_exit_reset(struct sdw_cdns *cdns);
  int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns);
  
  void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root);

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index a976480d6f36..9ebe38e4d979 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -1112,6 +1112,8 @@ static int intel_probe(struct platform_device *pdev)
  
  	ret = sdw_cdns_enable_interrupt(>cdns);
  
+	ret = sdw_cdns_exit_reset(>cdns);


This isn't something, that this patch changes, but if the return value above is
ignored, maybe no need to assign it at all?


The return of these two functions was used with in some logs at some 
point but they obviously vanished.

I'll re-check if we care about the status, could be that it never fails
Thanks!



+
/* Register DAIs */
ret = intel_register_dai(sdw);
if (ret) {
@@ -1199,6 +1201,8 @@ static int intel_resume(struct device *dev)
  
  	sdw_cdns_enable_interrupt(>cdns);
  
+	ret = sdw_cdns_exit_reset(>cdns);

+
return ret;


Re: [alsa-devel] [PATCH v4 1/1] ASoC: Intel: Skylake: Remove static table index when parsing topology

2019-07-26 Thread Pierre-Louis Bossart




On 7/26/19 4:09 AM, Amadeusz Sławiński wrote:

Currently when we remove and reload driver we use previous ref_count
value to start iterating over skl->modules which leads to out of table
access. To fix this just inline the function and calculate indexes
everytime we parse UUID token.

Signed-off-by: Amadeusz Sławiński 


Reviewed-by: Pierre-Louis Bossart 


---
  sound/soc/intel/skylake/skl-topology.c | 34 +-
  1 file changed, 12 insertions(+), 22 deletions(-)

diff --git a/sound/soc/intel/skylake/skl-topology.c 
b/sound/soc/intel/skylake/skl-topology.c
index 118866cd5075..c1c37ce759bd 100644
--- a/sound/soc/intel/skylake/skl-topology.c
+++ b/sound/soc/intel/skylake/skl-topology.c
@@ -,25 +,6 @@ static int skl_tplg_get_int_tkn(struct device *dev,
return tkn_count;
  }
  
-static int skl_tplg_get_manifest_uuid(struct device *dev,

-   struct skl_dev *skl,
-   struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn)
-{
-   static int ref_count;
-   struct skl_module *mod;
-
-   if (uuid_tkn->token == SKL_TKN_UUID) {
-   mod = skl->modules[ref_count];
-   guid_copy(>uuid, (guid_t *)_tkn->uuid);
-   ref_count++;
-   } else {
-   dev_err(dev, "Not an UUID token tkn %d\n", uuid_tkn->token);
-   return -EINVAL;
-   }
-
-   return 0;
-}
-
  /*
   * Fill the manifest structure by parsing the tokens based on the
   * type.
@@ -3362,6 +3343,7 @@ static int skl_tplg_get_manifest_tkn(struct device *dev,
  {
int tkn_count = 0, ret;
int off = 0, tuple_size = 0;
+   u8 uuid_index = 0;
struct snd_soc_tplg_vendor_array *array;
struct snd_soc_tplg_vendor_value_elem *tkn_elem;
  
@@ -3384,9 +3366,17 @@ static int skl_tplg_get_manifest_tkn(struct device *dev,

continue;
  
  		case SND_SOC_TPLG_TUPLE_TYPE_UUID:

-   ret = skl_tplg_get_manifest_uuid(dev, skl, array->uuid);
-   if (ret < 0)
-   return ret;
+   if (array->uuid->token != SKL_TKN_UUID) {
+   dev_err(dev, "Not an UUID token: %d\n",
+   array->uuid->token);
+   return -EINVAL;
+   }
+   if (uuid_index >= skl->nr_modules) {
+   dev_err(dev, "Too many UUID tokens\n");
+   return -EINVAL;
+   }
+   guid_copy(>modules[uuid_index++]->uuid,
+ (guid_t *)>uuid->uuid);
  
  			tuple_size += sizeof(*array->uuid);

continue;



Re: [RFC PATCH 04/40] soundwire: intel: add debugfs register dump

2019-07-26 Thread Pierre-Louis Bossart




+static const struct file_operations intel_reg_fops = {
+   .open = simple_open,
+   .read = intel_reg_read,
+   .llseek = default_llseek,
+};


DEFINE_SIMPLE_ATTRIBUTE()?


yes




+
+static void intel_debugfs_init(struct sdw_intel *sdw)
+{
+   struct dentry *root = sdw->cdns.bus.debugfs;
+
+   if (!root)
+   return;
+
+   sdw->fs = debugfs_create_dir("intel-sdw", root);
+   if (IS_ERR_OR_NULL(sdw->fs)) {
+   dev_err(sdw->cdns.dev, "debugfs root creation failed\n");


No, come on, don't do that.  I've been sweeping the kernel tree to
remove this anti-pattern.

The debugfs core will print an error if you got something wrong, just
call the function and move on, you NEVER need to check the return value
of a debugfs call.


Yes, sorry to make your blood pressure go up... I missed this one in the 
cleanups yesterday. will fix.


Re: [RFC PATCH 01/40] soundwire: add debugfs support

2019-07-26 Thread Pierre-Louis Bossart




diff --git a/drivers/soundwire/debugfs.c b/drivers/soundwire/debugfs.c
new file mode 100644
index ..8d86e100516e
--- /dev/null
+++ b/drivers/soundwire/debugfs.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)


No, for debugfs-specific code, that dual license makes no sense, right?
Don't cargo-cult SPDX identifiers please.


It's a miss, I used EXPORT_GPL and missed this line, will fix.




+// Copyright(c) 2017-19 Intel Corporation.


Spell the year out fully unless you want lawyers knocking on your door :)


haha, will fix.




+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "bus.h"
+
+#ifdef CONFIG_DEBUG_FS
+struct dentry *sdw_debugfs_root;
+#endif


This whole file is not built if that option is not enabled, so why the
#ifdef?


Ah, will look into this, thanks!


Re: [RFC PATCH 02/40] soundwire: cadence_master: add debugfs register dump

2019-07-26 Thread Pierre-Louis Bossart




+static const struct file_operations cdns_reg_fops = {
+   .open = simple_open,
+   .read = cdns_reg_read,
+   .llseek = default_llseek,
+};


DEFINE_SHOW_ATTRIBUTE()?


I remember looking at this but can't recall why I left it this way.
That was before my Summer break so will relook, thanks for suggesting this.


Re: [alsa-devel] [RFC PATCH 21/40] soundwire: export helpers to find row and column values

2019-07-26 Thread Pierre-Louis Bossart




On 7/26/19 9:43 AM, Guennadi Liakhovetski wrote:

On Thu, Jul 25, 2019 at 06:40:13PM -0500, Pierre-Louis Bossart wrote:

Add a prefix for common tables and export 2 helpers to set the frame
shapes based on row/col values.

Signed-off-by: Pierre-Louis Bossart 
---
  drivers/soundwire/bus.h|  7 +--
  drivers/soundwire/stream.c | 14 --
  2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/soundwire/bus.h b/drivers/soundwire/bus.h
index 06ac4adb0074..c57c9c23f6ca 100644
--- a/drivers/soundwire/bus.h
+++ b/drivers/soundwire/bus.h
@@ -73,8 +73,11 @@ struct sdw_msg {
  
  #define SDW_DOUBLE_RATE_FACTOR		2
  
-extern int rows[SDW_FRAME_ROWS];

-extern int cols[SDW_FRAME_COLS];
+extern int sdw_rows[SDW_FRAME_ROWS];
+extern int sdw_cols[SDW_FRAME_COLS];


So these arrays actually have to be exported? In the current (5.2) sources they
seem to only be used in stream.c, maybe make them static there?


+
+int sdw_find_row_index(int row);
+int sdw_find_col_index(int col);


yes, they need to be exported, they are used by the allocation algorithm 
(in Patch 27).
Others will need this for non-Intel solutions, it's really a part of the 
standard definition and should be shared.

I can improve the commit message to make this explicit.


Re: [alsa-devel] [RFC PATCH 00/40] soundwire: updates for 5.4

2019-07-26 Thread Pierre-Louis Bossart




Comments and feedback welcome!


Hello Pierre,

This patchset is pretty large - I'd suggest dividing next RFC into 
segments: debugfs, info, power-management, basic flow corrections and 
frame shape calculator.


There was an intent to provide a logical progression...

First debugfs, since I believe it was reviewed before, and I wanted 
folks like Greg to double-check it without burrying it too deep.


Then all corrections, followed by the allocator.

And last all PM stuff, split by regular suspend/resume and pm_runtime.

The RFC state is precisely to gather feedback, if folks want a different 
order that's fine. I just wanted to be transparent and share what we have.


Some commits have no messages and others lack additional info - tried to 
provide feedback wherever I could, though, especially for the last one, 
it would be vital to post additional info so in-depth feedback can be 
provided.


The lack of commits is a miss, I went from 170 debug/integration patches 
to 40 yesterday and my brain was fried.


Maybe nothing for calculator will come up, maybe something will. In 
general I remember it being an essential part of SDW and one where many 
bugs where found during the initial verification phase.


the frame allocation is a critical piece and it does need to be 
hardened. However we can do so in steps. The current setups we have 
support 1 Slave per link and a limited amount of bandwidth. The links 
themselves don't operate at the max frequency.
Also note that that the streams are 'statically' defined by the 
dailinks, and the allocation is not fully dynamic with random 
configurations being request. If you fail you fail fast.


Nevertheless I do plan to recheck the allocator with an additional 
scripting tool. It'd be very good to e.g. dump the current setup in a 
debugfs file and show to users what is happening (or not happening). I 
didn't recall you worked on SoundWire and I can use your practical 
knowledge to make the code and tools better :-)




Thanks for your contribution and have a good day!


Thanks for reviewing this long series and have a nice week-end.
-Pierre


Re: [alsa-devel] [RFC PATCH 23/40] soundwire: stream: fix disable sequence

2019-07-26 Thread Pierre-Louis Bossart




Unrelated to this specific patch, but I looked at _sdw_disable_stream()
and I see this there (again, maybe my version is outdated already):

struct sdw_master_runtime *m_rt = NULL;
struct sdw_bus *bus = NULL;

where both those initialisations are redundant. Moreover:


will look at this, thanks.



On Thu, Jul 25, 2019 at 06:40:15PM -0500, Pierre-Louis Bossart wrote:

When we disable the stream and then call hw_free, two bank switches
will be handled and as a result we re-enable the stream on hw_free.

Make sure the stream is disabled on both banks.

TODO: we need to completely revisit all this and make sure we have a
mirroring mechanism between current and alternate banks.

Signed-off-by: Pierre-Louis Bossart 
---
  drivers/soundwire/stream.c | 19 ++-
  1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c
index 53f5e790fcd7..75b9ad1fb1a6 100644
--- a/drivers/soundwire/stream.c
+++ b/drivers/soundwire/stream.c
@@ -1637,7 +1637,24 @@ static int _sdw_disable_stream(struct sdw_stream_runtime 
*stream)
}
}
  
-	return do_bank_switch(stream);

+   ret = do_bank_switch(stream);
+   if (ret < 0) {
+   dev_err(bus->dev, "Bank switch failed: %d\n", ret);
+   return ret;
+   }
+
+   /* make sure alternate bank (previous current) is also disabled */
+   list_for_each_entry(m_rt, >master_list, stream_node) {
+   bus = m_rt->bus;


"bus" is only used below, so at least take that line under "if (ret < 0)"
or even just do "dev_err(m_rt->bus->dev,...)" everywhere in this function
and remove the variable altogether...


will look at this, thanks Guennadi



Thanks
Guennadi


+   /* Disable port(s) */
+   ret = sdw_enable_disable_ports(m_rt, false);
+   if (ret < 0) {
+   dev_err(bus->dev, "Disable port(s) failed: %d\n", ret);
+   return ret;


Re: [alsa-devel] [RFC PATCH 37/40] soundwire: cadence_master: add hw_reset capability in debugfs

2019-07-26 Thread Pierre-Louis Bossart

Thanks for the review Greg.


+static int cdns_hw_reset(void *data, u64 value)
+{
+   struct sdw_cdns *cdns = data;
+   int ret;
+
+   if (value != 1)
+   return 0;
+
+   dev_info(cdns->dev, "starting link hw_reset\n");
+
+   ret = sdw_cdns_exit_reset(cdns);
+
+   dev_info(cdns->dev, "link hw_reset done\n");


Do not be noisy for when things always go right.  This looks like
debuggging code, please remove.


yes, missed this in the cleanup, will remove.


+DEFINE_DEBUGFS_ATTRIBUTE(cdns_hw_reset_fops, NULL, cdns_hw_reset, "%llu\n");
+
  /**
   * sdw_cdns_debugfs_init() - Cadence debugfs init
   * @cdns: Cadence instance
@@ -339,6 +358,9 @@ static const struct file_operations cdns_reg_fops = {
  void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root)
  {
debugfs_create_file("cdns-registers", 0400, root, cdns, _reg_fops);
+
+   debugfs_create_file_unsafe("cdns-hw-reset", 0200, root, cdns,
+  _hw_reset_fops);


Why unsafe?


Dunno. I followed the documentation and my take-away, along with a 
number of examples, was to use _unsafe. I really have no idea if this is 
correct or not, I can remove this qualifier if that's not needed.


Re: [alsa-devel] [RFC PATCH 32/40] soundwire: intel: add helper for initialization

2019-07-26 Thread Pierre-Louis Bossart




On 7/26/19 5:42 AM, Cezary Rojewski wrote:

On 2019-07-26 01:40, Pierre-Louis Bossart wrote:

Move code to helper for reuse in power management routines

Signed-off-by: Pierre-Louis Bossart 


---
  drivers/soundwire/intel.c | 16 +++-
  1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index c40ab443e723..215dc81cdf73 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -984,6 +984,15 @@ static struct sdw_master_ops sdw_intel_ops = {
  .post_bank_switch = intel_post_bank_switch,
  };
+static int intel_init(struct sdw_intel *sdw)
+{
+    /* Initialize shim and controller */
+    intel_link_power_up(sdw);
+    intel_shim_init(sdw);
+
+    return sdw_cdns_init(>cdns);
+}


Why don't we check polling status for _link_power_up? I've already met 
slow starting devices in the past. If polling fails and -EAGAIN is 
returned, flow of initialization should react appropriately e.g. poll 
till MAX_TIMEOUT of some sort -or- collapse.


The code does what it states, it initializes the Intel and Cadence IPs.

What you are referring to is a different problem: once the bus starts, 
then Slave devices will report as attached, and will be enumerated. This 
will take time. The devices I tested show up immediately and within a 
couple of ms the bus is operational. But MIPI allows to the sync to take 
up to 4096 frames, which is 85ms with a 48kHz frame rate, so yes we do 
need to look into this.


We currently do not have a notification that tells us the bus is back to 
normal, that's a design flaw - see the last patch of the series where I 
kicked the can down the road but adding an artificial delay.


So yes good point indeed but on the wrong patch :-)


Re: [alsa-devel] [RFC PATCH 33/40] soundwire: intel: Add basic power management support

2019-07-26 Thread Pierre-Louis Bossart




On 7/26/19 5:50 AM, Cezary Rojewski wrote:

On 2019-07-26 01:40, Pierre-Louis Bossart wrote:

+static int intel_resume(struct device *dev)
+{
+    struct sdw_intel *sdw;
+    int ret;
+
+    sdw = dev_get_drvdata(dev);
+
+    ret = intel_init(sdw);
+    if (ret) {
+    dev_err(dev, "%s failed: %d", __func__, ret);
+    return ret;
+    }
+
+    sdw_cdns_enable_interrupt(>cdns);
+
+    return ret;
+}
+
+#endif


Suggestion: the local declaration + initialization via dev_get_drvdata() 
are usually combined.


yes, will do.



Given the upstream declaration of _enable_interrupt, it does return 
error code/ success. Given current flow, if function gets to 
_enable_interrupt call, ret is already set to 0. Returning 
sdw_cds_enable_interrupt() directly would both simplify the definition 
and prevent status loss.


sounds good, will do, thanks!


Re: [alsa-devel] [RFC PATCH 31/40] soundwire: intel: move shutdown() callback and don't export symbol

2019-07-26 Thread Pierre-Louis Bossart




On 7/26/19 5:38 AM, Cezary Rojewski wrote:

On 2019-07-26 01:40, Pierre-Louis Bossart wrote:

+void intel_shutdown(struct snd_pcm_substream *substream,
+    struct snd_soc_dai *dai)
+{
+    struct sdw_cdns_dma_data *dma;
+
+    dma = snd_soc_dai_get_dma_data(dai, substream);
+    if (!dma)
+    return;
+
+    snd_soc_dai_set_dma_data(dai, substream, NULL);
+    kfree(dma);
+}


Correct me if I'm wrong, but do we really need to _get_dma_ here?
_set_dma_ seems bulletproof, same for kfree.


I must admit I have no idea why we have a reference to DMAs here, this 
looks like an abuse to store a dai-specific context, and the initial 
test looks like copy-paste to detect invalid configs, as done in other 
callbacks. Vinod and Sanyog might have more history than me here.


Re: [alsa-devel] [RFC PATCH 29/40] soundwire: intel_init: add kernel module parameter to filter out links

2019-07-26 Thread Pierre-Louis Bossart




On 7/26/19 5:30 AM, Cezary Rojewski wrote:

On 2019-07-26 01:40, Pierre-Louis Bossart wrote:

@@ -83,6 +87,9 @@ static struct sdw_intel_ctx
  caps = ioread32(res->mmio_base + SDW_SHIM_BASE + SDW_SHIM_LCAP);
  caps &= GENMASK(2, 0);
+    dev_dbg(>dev, "SoundWire links: BIOS count %d hardware caps 
%d\n",

+    count, caps);
+
  /* Check HW supported vs property value and use min of two */
  count = min_t(u8, caps, count);


This message does not look like it belongs to current patch - no 
link_mask dependency whatsoever. There have been couple "informative" 
patches in your series, maybe schedule it with them instead (as a 
separate series)?


You're right, this log should be in a different patch. it was added when 
I was debugging the DisCo properties a couple of months back and should 
be moved. thanks for noting this.


Re: [alsa-devel] [RFC PATCH 27/40] soundwire: Add Intel resource management algorithm

2019-07-26 Thread Pierre-Louis Bossart




On 7/26/19 6:07 AM, Cezary Rojewski wrote:

On 2019-07-26 01:40, Pierre-Louis Bossart wrote:

This algorithm computes bus parameters like clock frequency, frame
shape and port transport parameters based on active stream(s) running
on the bus.

This implementation is optimal for Intel platforms. Developers can
also implement their own .compute_params() callback for specific
resource management algorithm.

Credits: this patch is based on an earlier internal contribution by
Vinod Koul, Sanyog Kale, Shreyas Nc and Hardik Shah. All hard-coded
values were removed from the initial contribution to use BIOS
information instead.

FIXME: remove checkpatch report
WARNING: Reusing the krealloc arg is almost always a bug
+    group->rates = krealloc(group->rates,

Signed-off-by: Pierre-Louis Bossart 



Could you specify the requirements and limitations for this algorithm? 
Last year I written calc for Linux based on Windows (please don't burn 
me here) equivalent though said requirements/ limitiations might have 
changed and nothing is valid any longer.


The frame shape typically only changes by doubling the number of 
columns, and the priority is given to PDM streams which use columns. 
It's hard to document this on a public mailing list, it'd require making 
references to a spec that's only available to MIPI members.




I remember that some parts of specification overcomplicated the 
calculator and due to actual, realtime usecases it could be greatly 
simplified (that's why I mention that my work is probably no longer 
valid). However, these details would help me in reviewing your 
implementation and providing suggestions.


To the best of my knowledge, the algorithm follows a script that is used 
for both Windows and Linux. The code was initially written by Vinod and 
team, and I am not aware of simplifications.
There a simplifications that are possible, e.g. we don't support PDM for 
now and the notion of grouping is not needed, but we have to carefully 
balance 'optimization' with 'introducing bugs'. if this algorithm craps 
out then the entire bus operation is in the weeds.


If we really want people to experiment and get a feel for the 
performance of the algorithm, we should really provide a UI where the 
stream parameters can be entered and visually check what the algorithm 
is doing. I have a solution that shows the bits based on the stream 
parameters (need to make it available e.g. in Python), if we connected 
it with the automatic bit allocation it'd be very useful.



And yes, "Frame shape calculator" probably suits this better.
Though this might be just a preference thingy : )


Resource management is indeed a bit vague. But frame shape calculator is 
not quite right. The algorithm will find the frame shape that is 
required for the current bandwidth, but will also allocate the bitSlots 
in that frame. In MIPI circles we talk about bitSlot allocation.


Re: [alsa-devel] [RFC PATCH 26/40] soundwire: cadence_master: fix divider setting in clock register

2019-07-26 Thread Pierre-Louis Bossart




On 7/26/19 12:19 AM, Bard liao wrote:


On 7/26/2019 7:40 AM, Pierre-Louis Bossart wrote:

From: Rander Wang 

The existing code uses an OR operation which would mix the original
divider setting with the new one, resulting in an invalid
configuration that can make codecs hang.

Add the mask definition and use cdns_updatel to update divider

Signed-off-by: Rander Wang 
Signed-off-by: Pierre-Louis Bossart 


---
  drivers/soundwire/cadence_master.c | 12 +++-
  1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c

index 10ebcef2e84e..18c6ac026e85 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -57,6 +57,7 @@
  #define CDNS_MCP_SSP_CTRL1    0x28
  #define CDNS_MCP_CLK_CTRL0    0x30
  #define CDNS_MCP_CLK_CTRL1    0x38
+#define CDNS_MCP_CLK_MCLKD_MASK    GENMASK(7, 0)
  #define CDNS_MCP_STAT    0x40
@@ -988,9 +989,11 @@ int sdw_cdns_init(struct sdw_cdns *cdns)
  /* Set clock divider */
  divider    = (prop->mclk_freq / prop->max_clk_freq) - 1;
  val = cdns_readl(cdns, CDNS_MCP_CLK_CTRL0);



Do we still need to read cdns_readl(cdns, CDNS_MCP_CLK_CTRL0)

after this change?


no I don't think we do indeed.




-    val |= divider;
-    cdns_writel(cdns, CDNS_MCP_CLK_CTRL0, val);
-    cdns_writel(cdns, CDNS_MCP_CLK_CTRL1, val);
+
+    cdns_updatel(cdns, CDNS_MCP_CLK_CTRL0,
+ CDNS_MCP_CLK_MCLKD_MASK, divider);
+    cdns_updatel(cdns, CDNS_MCP_CLK_CTRL1,
+ CDNS_MCP_CLK_MCLKD_MASK, divider);
  pr_err("plb: mclk %d max_freq %d divider %d register %x\n",
 prop->mclk_freq,


and this log needs to go away or done in a better way, I missed this.

@@ -1064,8 +1067,7 @@ int cdns_bus_conf(struct sdw_bus *bus, struct 
sdw_bus_params *params)

  mcp_clkctrl_off = CDNS_MCP_CLK_CTRL0;
  mcp_clkctrl = cdns_readl(cdns, mcp_clkctrl_off);



Same here.


yep.





-    mcp_clkctrl |= divider;
-    cdns_writel(cdns, mcp_clkctrl_off, mcp_clkctrl);
+    cdns_updatel(cdns, mcp_clkctrl_off, CDNS_MCP_CLK_MCLKD_MASK, 
divider);

  pr_err("plb: mclk * 2 %d curr_dr_freq %d divider %d register %x\n",
 prop->mclk_freq * SDW_DOUBLE_RATE_FACTOR,

___
Alsa-devel mailing list
alsa-de...@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel


Re: [alsa-devel] [RFC PATCH 24/40] soundwire: cadence_master: use BIOS defaults for frame shape

2019-07-26 Thread Pierre-Louis Bossart




On 7/26/19 5:20 AM, Cezary Rojewski wrote:

On 2019-07-26 01:40, Pierre-Louis Bossart wrote:

+static u32 cdns_set_default_frame_shape(int n_rows, int n_cols)
+{
+    u32 val;
+    int c;
+    int r;
+
+    r = sdw_find_row_index(n_rows);
+    c = sdw_find_col_index(n_cols);
+
+    val = (r << 3) | c;
+
+    return val;
+}
+
  /**
   * sdw_cdns_init() - Cadence initialization
   * @cdns: Cadence instance
@@ -977,7 +990,9 @@ int sdw_cdns_init(struct sdw_cdns *cdns)
  cdns_writel(cdns, CDNS_MCP_CLK_CTRL0, val);
  /* Set the default frame shape */
-    cdns_writel(cdns, CDNS_MCP_FRAME_SHAPE_INIT, 
CDNS_DEFAULT_FRAME_SHAPE);

+    val = cdns_set_default_frame_shape(prop->default_row,
+   prop->default_col);
+    cdns_writel(cdns, CDNS_MCP_FRAME_SHAPE_INIT, val);
  /* Set SSP interval to default value */
  cdns_writel(cdns, CDNS_MCP_SSP_CTRL0, CDNS_DEFAULT_SSP_INTERVAL);



Suggestion:
declare "generic" _get_frame_frame(rows, cols) instead and let it do the 
bitwise operations for you. Pretty sure this won't be the only place in 
code where reg value for frame_shape needs to be prepared.


Said function could be as simple as:
return (row << 3) | cols;
+inline flag

i.e. could be even a macro..

Otherwise modify _set_default_frame_shape to simply:
return (r << 3) | c

without involving additional local val variable (I don't really see the 
point for any locals there though).


what this function does is take the standard-defined offsets for row and 
column and stores them in a Cadence-defined register. I think we can 
probably use a macro to remove the magic '3' value, but there are limits 
to what we can simplify. I should probably add comments so that people 
figure it out.


Re: [alsa-devel] [RFC PATCH 23/40] soundwire: stream: fix disable sequence

2019-07-26 Thread Pierre-Louis Bossart




On 7/26/19 5:14 AM, Cezary Rojewski wrote:

On 2019-07-26 01:40, Pierre-Louis Bossart wrote:

-    return do_bank_switch(stream);
+    ret = do_bank_switch(stream);
+    if (ret < 0) {
+    dev_err(bus->dev, "Bank switch failed: %d\n", ret);
+    return ret;
+    }
+
+    /* make sure alternate bank (previous current) is also disabled */
+    list_for_each_entry(m_rt, >master_list, stream_node) {
+    bus = m_rt->bus;
+    /* Disable port(s) */
+    ret = sdw_enable_disable_ports(m_rt, false);
+    if (ret < 0) {
+    dev_err(bus->dev, "Disable port(s) failed: %d\n", ret);
+    return ret;
+    }
+    }
+
+    return 0;
  }
  /**



While not directly connected to this commit, I see that you do:
link_for_each_entry(m_rt, >master_list, stream_node)

quite often in /stream.c code. Helpful macro would prove useful.


Yes, but the flip side is that people need to look at what the macro 
does to figure it out, while everyone knows what list_for_each_entry() 
means. Not sure about this one.
And on top of this we'll probably have to rework this code to have a 
background copy of the current bank in the alternate bank so it'd rather 
leave it simple for now.


Re: [alsa-devel] [RFC PATCH 20/40] soundwire: prototypes for suspend/resume

2019-07-26 Thread Pierre-Louis Bossart




On 7/26/19 5:04 AM, Cezary Rojewski wrote:

On 2019-07-26 01:40, Pierre-Louis Bossart wrote:
Signed-off-by: Pierre-Louis Bossart 


---
  drivers/soundwire/cadence_master.h | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/drivers/soundwire/cadence_master.h 
b/drivers/soundwire/cadence_master.h

index c0bf6ff00a44..d375bbfead18 100644
--- a/drivers/soundwire/cadence_master.h
+++ b/drivers/soundwire/cadence_master.h
@@ -165,6 +165,9 @@ int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns);
  void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root);
+int sdw_cdns_suspend(struct sdw_cdns *cdns);
+bool sdw_cdns_check_resume_status(struct sdw_cdns *cdns);
+
  int sdw_cdns_get_stream(struct sdw_cdns *cdns,
  struct sdw_cdns_streams *stream,
  u32 ch, u32 dir);



No commit message, guess it's SQUASHME commit and shouldn't be part of 
overall series.


I can't recall why it's separate, will look into this. Thanks.


Re: [alsa-devel] [RFC PATCH 16/40] soundwire: cadence_master: improve startup sequence with link hw_reset

2019-07-26 Thread Pierre-Louis Bossart




+static int do_reset(struct sdw_cdns *cdns)
+{
+   int ret;
+
+   /* program maximum length reset to be safe */
+   cdns_updatel(cdns, CDNS_MCP_CONTROL,
+CDNS_MCP_CONTROL_RST_DELAY,
+CDNS_MCP_CONTROL_RST_DELAY);
+
+   /* use hardware generated reset */
+   cdns_updatel(cdns, CDNS_MCP_CONTROL,
+CDNS_MCP_CONTROL_HW_RST,
+CDNS_MCP_CONTROL_HW_RST);
+
+   /* enable bus operations with clock and data */
+   cdns_updatel(cdns, CDNS_MCP_CONFIG,
+CDNS_MCP_CONFIG_OP,
+CDNS_MCP_CONFIG_OP_NORMAL);
+
+   /* commit changes */
+   ret = cdns_update_config(cdns);
+
+   return ret;


+   return cdns_update_config(cdns);

and remove the "ret" variable.


Yes, it's the same issue as previously reported. will fix.


Re: [alsa-devel] [RFC PATCH 15/40] soundwire: cadence_master: handle multiple status reports per Slave

2019-07-26 Thread Pierre-Louis Bossart




diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index 889fa2cd49ae..25d5c7267c15 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -643,13 +643,35 @@ static int cdns_update_slave_status(struct sdw_cdns *cdns,
  
  		/* first check if Slave reported multiple status */

if (set_status > 1) {
+   u32 val;
+
dev_warn_ratelimited(cdns->dev,
-"Slave reported multiple Status: 
%d\n",
-mask);
-   /*
-* TODO: we need to reread the status here by
-* issuing a PING cmd
-*/
+"Slave %d reported multiple Status: 
%d\n",
+i, mask);
+
+   /* re-check latest status extracted from PING commands 
*/
+   val = cdns_readl(cdns, CDNS_MCP_SLAVE_STAT);
+   val >>= (i * 2);


Superfluous parentheses.


Humm, I don't know my left from my right and I can't remember operator 
precedence, so i'd rather make it explicit...





+
+   switch (val & 0x3) {
+   case 0:
+   status[i] = SDW_SLAVE_UNATTACHED;
+   break;
+   case 1:
+   status[i] = SDW_SLAVE_ATTACHED;
+   break;
+   case 2:
+   status[i] = SDW_SLAVE_ALERT;
+   break;
+   default:


There aren't many values left for the "default" case :-) But I'm not sure 
whether
any of

+   case 3:

or

+   case 3:
+   default:

would improve readability.

Thanks
Guennadi


+   status[i] = SDW_SLAVE_RESERVED;
+   break;


Yes, those defaults are annoying. Some tools complain so I tend to leave 
them.


Re: [alsa-devel] [RFC PATCH 09/40] soundwire: cadence_master: fix usage of CONFIG_UPDATE

2019-07-26 Thread Pierre-Louis Bossart




@@ -943,7 +953,10 @@ int sdw_cdns_init(struct sdw_cdns *cdns)
  
  	cdns_writel(cdns, CDNS_MCP_CONFIG, val);
  
-	return 0;

+   /* commit changes */
+   ret = cdns_update_config(cdns);
+
+   return ret;


+   return cdns_update_config(cdns);


yes, will fix. thanks!


Re: [alsa-devel] [RFC PATCH 06/40] soundwire: intel: prevent possible dereference in hw_params

2019-07-26 Thread Pierre-Louis Bossart




diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 68832e613b1e..497879dd9c0d 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -509,7 +509,7 @@ static int intel_config_stream(struct sdw_intel *sdw,
 struct snd_soc_dai *dai,
 struct snd_pcm_hw_params *hw_params, int link_id)
  {
-    if (sdw->res->ops && sdw->res->ops->config_stream)
+    if (sdw->res->ops && sdw->res->ops->config_stream && sdw->res->arg)
  return sdw->res->ops->config_stream(sdw->res->arg,
  substream, dai, hw_params, link_id);



Hmm, declaring local for sdw->res should prove useful here after 
addition of 4th sdw->res dereference.


yes, it's an eyesore. I added this to quickly fix a kernel oops while 
debugging, will simplify. thanks for the note.


Re: [alsa-devel] [RFC PATCH 04/40] soundwire: intel: add debugfs register dump

2019-07-26 Thread Pierre-Louis Bossart




On 7/26/19 4:35 AM, Cezary Rojewski wrote:

On 2019-07-26 01:39, Pierre-Louis Bossart wrote:

+static void intel_debugfs_init(struct sdw_intel *sdw)
+{
+    struct dentry *root = sdw->cdns.bus.debugfs;
+
+    if (!root)
+    return;
+
+    sdw->fs = debugfs_create_dir("intel-sdw", root);
+    if (IS_ERR_OR_NULL(sdw->fs)) {
+    dev_err(sdw->cdns.dev, "debugfs root creation failed\n");
+    sdw->fs = NULL;
+    return;
+    }
+
+    debugfs_create_file("intel-registers", 0400, sdw->fs, sdw,
+    _reg_fops);
+
+    sdw_cdns_debugfs_init(>cdns, sdw->fs);
+}


I believe there should be dummy equivalent of _init and _exit if debugfs 
is not enabled (if these are defined already and I've missed it, please 
ignore).


I think the direction is just to keep going if there is an error or 
debufs is not enabled.





+static void intel_debugfs_exit(struct sdw_intel *sdw)
+{
+    debugfs_remove_recursive(sdw->fs);
+}


Re: [alsa-devel] [RFC PATCH 03/40] soundwire: cadence_master: align debugfs to 8 digits

2019-07-26 Thread Pierre-Louis Bossart




On 7/26/19 4:38 AM, Cezary Rojewski wrote:

On 2019-07-26 01:39, Pierre-Louis Bossart wrote:

SQUASHME

Signed-off-by: Pierre-Louis Bossart 


---
  drivers/soundwire/cadence_master.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c

index 91e8bacb83e3..9f611a1fff0a 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -234,7 +234,7 @@ static ssize_t cdns_sprintf(struct sdw_cdns *cdns,
  char *buf, size_t pos, unsigned int reg)
  {
  return scnprintf(buf + pos, RD_BUF - pos,
- "%4x\t%4x\n", reg, cdns_readl(cdns, reg));
+ "%4x\t%8x\n", reg, cdns_readl(cdns, reg));
  }
  static ssize_t cdns_reg_read(struct file *file, char __user *user_buf,



Should just be merged together with the introducing commit. Guess it's 
posted unintentionally.


Yep, I missed this, will squash in the updates as intended.


Re: [alsa-devel] [RFC PATCH 01/40] soundwire: add debugfs support

2019-07-26 Thread Pierre-Louis Bossart

Thanks for the feedback Cezary.

+static ssize_t sdw_slave_reg_read(struct file *file, char __user 
*user_buf,

+  size_t count, loff_t *ppos)
+{
+    struct sdw_slave *slave = file->private_data;
+    unsigned int reg;
+    char *buf;
+    ssize_t ret;
+    int i, j;
+
+    buf = kzalloc(RD_BUF, GFP_KERNEL);
+    if (!buf)
+    return -ENOMEM;
+
+    ret = scnprintf(buf, RD_BUF, "Register  Value\n");
+    ret += scnprintf(buf + ret, RD_BUF - ret, "\nDP0\n");
+
+    for (i = 0; i < 6; i++)
+    ret += sdw_sprintf(slave, buf, ret, i);


In most cases explicit reg macro is used, here it's implicit. Align with 
the rest?


I don't see what you are referring to, or I need more coffee.
we use this function sdw_printf in a number of places. Or are you 
referring to the magic value 6? That should indeed be a macro.



+
+    ret += scnprintf(buf + ret, RD_BUF - ret, "Bank0\n");
+    ret += sdw_sprintf(slave, buf, ret, SDW_DP0_CHANNELEN);
+    for (i = SDW_DP0_SAMPLECTRL1; i <= SDW_DP0_LANECTRL; i++)
+    ret += sdw_sprintf(slave, buf, ret, i);
+
+    ret += scnprintf(buf + ret, RD_BUF - ret, "Bank1\n");
+    ret += sdw_sprintf(slave, buf, ret,
+    SDW_DP0_CHANNELEN + SDW_BANK1_OFFSET);
+    for (i = SDW_DP0_SAMPLECTRL1 + SDW_BANK1_OFFSET;
+    i <= SDW_DP0_LANECTRL + SDW_BANK1_OFFSET; i++)
+    ret += sdw_sprintf(slave, buf, ret, i);


I'd advice to revisit macros declarations first.
There should be SDW_DP0_SAMPLECTRL1_B(bank) declared. In general all 
macros for SDW should be "bank-less" (name wise). Additionally, 
SDW_BANK_OFFSET(bank) could be provided for convenience i.e.: return 0 
for bank0.
Yeah, there might be some speed loss in terms of operation count but in 
most cases it is negligible.


Would simplify this entire reg dump greatly.
const array on top with {0, 1} elements and replacing explicit "bank0/1" 
strings with "bank%d" gets code size reduced while not losing on 
readability.


This could require a lot of changes in other parts of the code, and I 
don't want to do this just for debugfs. It's valid point that maybe the 
code can be simplified, but the changes are an across-the-board change 
to be done when we don't add new functionality. I'll keep this on the 
todo list.





+
+    ret += scnprintf(buf + ret, RD_BUF - ret, "\nSCP\n");
+    for (i = SDW_SCP_INT1; i <= SDW_SCP_BANKDELAY; i++)
+    ret += sdw_sprintf(slave, buf, ret, i);
+    for (i = SDW_SCP_DEVID_0; i <= SDW_SCP_DEVID_5; i++)
+    ret += sdw_sprintf(slave, buf, ret, i);
+
+    ret += scnprintf(buf + ret, RD_BUF - ret, "Bank0\n");
+    ret += sdw_sprintf(slave, buf, ret, SDW_SCP_FRAMECTRL_B0);
+    ret += sdw_sprintf(slave, buf, ret, SDW_SCP_NEXTFRAME_B0);
+
+    ret += scnprintf(buf + ret, RD_BUF - ret, "Bank1\n");
+    ret += sdw_sprintf(slave, buf, ret, SDW_SCP_FRAMECTRL_B1);
+    ret += sdw_sprintf(slave, buf, ret, SDW_SCP_NEXTFRAME_B1);
+
+    for (i = 1; i < 14; i++) {


Explicit valid slave addresses would be preferred.


no, these are ports. we should use a macro instead of the magic 14 but 
it's fine to try and read all ports. As I explained it's a good way to 
figure out how many ports the Slave device supports even in the absence 
of documentation. This also helps figure out if the DisCo properties 
make sense.





+    ret += scnprintf(buf + ret, RD_BUF - ret, "\nDP%d\n", i);
+    reg = SDW_DPN_INT(i);
+    for (j = 0; j < 6; j++)
+    ret += sdw_sprintf(slave, buf, ret, reg + j);
+
+    ret += scnprintf(buf + ret, RD_BUF - ret, "Bank0\n");
+    reg = SDW_DPN_CHANNELEN_B0(i);
+    for (j = 0; j < 9; j++)
+    ret += sdw_sprintf(slave, buf, ret, reg + j);
+
+    ret += scnprintf(buf + ret, RD_BUF - ret, "Bank1\n");
+    reg = SDW_DPN_CHANNELEN_B1(i);
+    for (j = 0; j < 9; j++)
+    ret += sdw_sprintf(slave, buf, ret, reg + j);


Some sort of MAX_CHANNELS would be nice here too.


Yes, need to use macros indeed.


+struct dentry *sdw_slave_debugfs_init(struct sdw_slave *slave)
+{
+    struct dentry *master;
+    struct dentry *d;
+    char name[32];
+
+    master = slave->bus->debugfs;
+
+    /* create the debugfs slave-name */
+    snprintf(name, sizeof(name), "%s", dev_name(>dev));
+    d = debugfs_create_dir(name, master);
+
+    debugfs_create_file("registers", 0400, d, slave, 
_slave_reg_fops);


Pointer returned by _create_file gets completely ignored here. At least 
dbg msg would be nice if it fails.



+    return d;


I understood that Greg KH doesn't want us to depend on the result of 
debugfs calls, but a dev_dbg is likely ok.


Re: [alsa-devel] [RFC PATCH 01/40] soundwire: add debugfs support

2019-07-26 Thread Pierre-Louis Bossart




On 7/25/19 5:15 PM, Guennadi Liakhovetski wrote:

Hi Pierre,

A couple of nitpicks:


Thanks for the feedback!


  create mode 100644 drivers/soundwire/debugfs.c


[snip]


diff --git a/drivers/soundwire/bus.h b/drivers/soundwire/bus.h
index 3048ca153f22..06ac4adb0074 100644
--- a/drivers/soundwire/bus.h
+++ b/drivers/soundwire/bus.h
@@ -18,6 +18,30 @@ static inline int sdw_acpi_find_slaves(struct sdw_bus *bus)
  void sdw_extract_slave_id(struct sdw_bus *bus,
  u64 addr, struct sdw_slave_id *id);
  
+#ifdef CONFIG_DEBUG_FS

+struct dentry *sdw_bus_debugfs_init(struct sdw_bus *bus);
+void sdw_bus_debugfs_exit(struct dentry *d);
+struct dentry *sdw_slave_debugfs_init(struct sdw_slave *slave);
+void sdw_slave_debugfs_exit(struct dentry *d);
+void sdw_debugfs_init(void);
+void sdw_debugfs_exit(void);
+#else
+struct dentry *sdw_bus_debugfs_init(struct sdw_bus *bus)
+{ return NULL; }


static?


+
+void sdw_bus_debugfs_exit(struct dentry *d) {}
+
+struct dentry *sdw_slave_debugfs_init(struct sdw_slave *slave)
+{ return NULL; }
+
+void sdw_slave_debugfs_exit(struct dentry *d) {}
+
+void sdw_debugfs_init(void) {}
+
+void sdw_debugfs_exit(void) {}


Same for all the above. You could also declare them inline, but I really hope
the compiler will be smart enough to do that itself.


yes, I'll add static inline for all this.


+struct dentry *sdw_bus_debugfs_init(struct sdw_bus *bus)
+{
+   struct dentry *d;


I would remove the above


+   char name[16];
+
+   if (!sdw_debugfs_root)
+   return NULL;
+
+   /* create the debugfs master-N */
+   snprintf(name, sizeof(name), "master-%d", bus->link_id);
+   d = debugfs_create_dir(name, sdw_debugfs_root);
+
+   return d;


And just do

+   return debugfs_create_dir(name, sdw_debugfs_root);


yep, will do.


+static ssize_t sdw_sprintf(struct sdw_slave *slave,
+  char *buf, size_t pos, unsigned int reg)
+{
+   int value;
+
+   value = sdw_read(slave, reg);


I personally would join the two lines above, but that's just a personal
preference.


I prefer splitting variables and code, I just can't mentally split the two.




+
+   if (value < 0)
+   return scnprintf(buf + pos, RD_BUF - pos, "%3x\tXX\n", reg);
+   else


I think it's advised to not use an else in such cases.

Thanks
Guennadi


+   return scnprintf(buf + pos, RD_BUF - pos,
+   "%3x\t%2x\n", reg, value);
+}


The intent was to provide a visual cue that the register is not 
implemented, which is quite useful. Not all registers are mandatory and 
not all vendors document the entire set of registers, so it's a good way 
to figure things out. The value is not used for any functional purpose, 
it's just a register dump for the integrator to look at. I'll add a note 
to explain the idea.


Re: [alsa-devel] [RFC PATCH 09/40] soundwire: cadence_master: fix usage of CONFIG_UPDATE

2019-07-26 Thread Pierre-Louis Bossart



@@ -758,15 +774,9 @@ static int _cdns_enable_interrupt(struct sdw_cdns 
*cdns)

   */
  int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns)
  {
-    int ret;
-
  _cdns_enable_interrupt(cdns);
-    ret = cdns_clear_bit(cdns, CDNS_MCP_CONFIG_UPDATE,
- CDNS_MCP_CONFIG_UPDATE_BIT);
-    if (ret < 0)
-    dev_err(cdns->dev, "Config update timedout\n");
-    return ret;

Should we add cdns_update_config() here?


indeed, this would be a good improvement. The code works because we 
added the exit_reset() sequence which does call cdns_update_config(), 
but better make this function self-contained. When we enable the 
clock-stop mode we will not do this reset sequence.


[RFC PATCH 40/40] soundwire: intel: add delay on restart for enumeration

2019-07-25 Thread Pierre-Louis Bossart
We have a conceptual issue on restart: the interaction with the slaves
can start before (re) enumeration is complete. Add a delay for now but
we will need to have an async notification that all devices are back
on the bus.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/intel.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 1394a2322553..e4ea430b5a8e 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -1242,6 +1242,11 @@ static int intel_resume(struct device *dev)
 
ret = sdw_cdns_exit_reset(>cdns);
 
+   /* add delay to let Slaves re-enumerate */
+   usleep_range(2, 3);
+
+   dev_dbg(dev, "%s done\n", __func__);
+
return ret;
 }
 
-- 
2.20.1



[RFC PATCH 30/40] soundwire: cadence_master: add kernel parameter to override interrupt mask

2019-07-25 Thread Pierre-Louis Bossart
The code has a set of defaults which may not be relevant in all cases,
add kernel parameter as a helper - mostly for early board bring-up.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index 18c6ac026e85..dede55072191 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -20,6 +20,10 @@
 #include "bus.h"
 #include "cadence_master.h"
 
+static int interrupt_mask;
+module_param_named(cnds_mcp_int_mask, interrupt_mask, int, 0444);
+MODULE_PARM_DESC(cdns_mcp_int_mask, "Cadence MCP IntMask");
+
 #define CDNS_MCP_CONFIG0x0
 
 #define CDNS_MCP_CONFIG_MCMD_RETRY GENMASK(27, 24)
@@ -830,6 +834,9 @@ int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns)
/* now enable all of the above */
mask |= CDNS_MCP_INT_IRQ;
 
+   if (interrupt_mask) /* parameter override */
+   mask = interrupt_mask;
+
cdns_writel(cdns, CDNS_MCP_INTMASK, mask);
 
return do_reset(cdns);
-- 
2.20.1



[RFC PATCH 33/40] soundwire: intel: Add basic power management support

2019-07-25 Thread Pierre-Louis Bossart
Implement suspend/resume capabilities (not runtime_pm for now)

Credits: this patch is based on an earlier internal contribution by
Vinod Koul, Sanyog Kale, Shreyas Nc and Hardik Shah.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/intel.c | 102 ++
 1 file changed, 102 insertions(+)

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 215dc81cdf73..1477c35f616f 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -278,6 +279,35 @@ static void intel_debugfs_exit(struct sdw_intel *sdw)
 /*
  * shim ops
  */
+static int intel_link_power_down(struct sdw_intel *sdw)
+{
+   int link_control, spa_mask, cpa_mask, ret;
+   unsigned int link_id = sdw->instance;
+   void __iomem *shim = sdw->res->shim;
+   u16 ioctl;
+
+   /* Glue logic */
+   ioctl = intel_readw(shim, SDW_SHIM_IOCTL(link_id));
+   ioctl |= SDW_SHIM_IOCTL_BKE;
+   ioctl |= SDW_SHIM_IOCTL_COE;
+   intel_writew(shim, SDW_SHIM_IOCTL(link_id), ioctl);
+
+   ioctl &= ~(SDW_SHIM_IOCTL_MIF);
+   intel_writew(shim, SDW_SHIM_IOCTL(link_id), ioctl);
+
+   /* Link power down sequence */
+   link_control = intel_readl(shim, SDW_SHIM_LCTL);
+   spa_mask = ~(SDW_SHIM_LCTL_SPA << link_id);
+   cpa_mask = (SDW_SHIM_LCTL_CPA << link_id);
+   link_control &=  spa_mask;
+
+   ret = intel_clear_bit(shim, SDW_SHIM_LCTL, link_control, cpa_mask);
+   if (ret < 0)
+   return ret;
+
+   sdw->cdns.link_up = false;
+   return 0;
+}
 
 static int intel_link_power_up(struct sdw_intel *sdw)
 {
@@ -300,6 +330,29 @@ static int intel_link_power_up(struct sdw_intel *sdw)
return 0;
 }
 
+static void intel_shim_wake(struct sdw_intel *sdw, bool wake_enable)
+{
+   void __iomem *shim = sdw->res->shim;
+   unsigned int link_id = sdw->instance;
+   u16 wake_en, wake_sts;
+
+   if (wake_enable) {
+   /* Enable the wakeup */
+   intel_writew(shim, SDW_SHIM_WAKEEN,
+(SDW_SHIM_WAKEEN_ENABLE << link_id));
+   } else {
+   /* Disable the wake up interrupt */
+   wake_en = intel_readw(shim, SDW_SHIM_WAKEEN);
+   wake_en &= ~(SDW_SHIM_WAKEEN_ENABLE << link_id);
+   intel_writew(shim, SDW_SHIM_WAKEEN, wake_en);
+
+   /* Clear wake status */
+   wake_sts = intel_readw(shim, SDW_SHIM_WAKESTS);
+   wake_sts |= (SDW_SHIM_WAKEEN_ENABLE << link_id);
+   intel_writew(shim, SDW_SHIM_WAKESTS_STATUS, wake_sts);
+   }
+}
+
 static int intel_shim_init(struct sdw_intel *sdw)
 {
void __iomem *shim = sdw->res->shim;
@@ -1095,11 +1148,60 @@ static int intel_remove(struct platform_device *pdev)
return 0;
 }
 
+/*
+ * PM calls
+ */
+
+#ifdef CONFIG_PM
+
+static int intel_suspend(struct device *dev)
+{
+   struct sdw_intel *sdw;
+   int ret;
+
+   sdw = dev_get_drvdata(dev);
+
+   ret = intel_link_power_down(sdw);
+   if (ret) {
+   dev_err(dev, "Link power down failed: %d", ret);
+   return ret;
+   }
+
+   intel_shim_wake(sdw, false);
+
+   return 0;
+}
+
+static int intel_resume(struct device *dev)
+{
+   struct sdw_intel *sdw;
+   int ret;
+
+   sdw = dev_get_drvdata(dev);
+
+   ret = intel_init(sdw);
+   if (ret) {
+   dev_err(dev, "%s failed: %d", __func__, ret);
+   return ret;
+   }
+
+   sdw_cdns_enable_interrupt(>cdns);
+
+   return ret;
+}
+
+#endif
+
+static const struct dev_pm_ops intel_pm = {
+   SET_SYSTEM_SLEEP_PM_OPS(intel_suspend, intel_resume)
+};
+
 static struct platform_driver sdw_intel_drv = {
.probe = intel_probe,
.remove = intel_remove,
.driver = {
.name = "int-sdw",
+   .pm = _pm,
 
},
 };
-- 
2.20.1



[RFC PATCH 09/40] soundwire: cadence_master: fix usage of CONFIG_UPDATE

2019-07-25 Thread Pierre-Louis Bossart
Per the hardware documentation, all changes to MCP_CONFIG,
MCP_CONTROL, MCP_CMDCTRL and MCP_PHYCTRL need to be validated with a
self-clearing write to MCP_CONFIG_UPDATE.

For some reason, the existing code only does this write to
CONFIG_UPDATE when enabling interrupts. Add a helper and do the update
when the CONFIG is changed.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 29 +
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index 9f611a1fff0a..eb46cf651d62 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -224,6 +224,22 @@ static int cdns_clear_bit(struct sdw_cdns *cdns, int 
offset, u32 value)
return -EAGAIN;
 }
 
+/*
+ * all changes to the MCP_CONFIG, MCP_CONTROL, MCP_CMDCTRL and MCP_PHYCTRL
+ * need to be confirmed with a write to MCP_CONFIG_UPDATE
+ */
+static int cdns_update_config(struct sdw_cdns *cdns)
+{
+   int ret;
+
+   ret = cdns_clear_bit(cdns, CDNS_MCP_CONFIG_UPDATE,
+CDNS_MCP_CONFIG_UPDATE_BIT);
+   if (ret < 0)
+   dev_err(cdns->dev, "Config update timedout\n");
+
+   return ret;
+}
+
 /*
  * debugfs
  */
@@ -758,15 +774,9 @@ static int _cdns_enable_interrupt(struct sdw_cdns *cdns)
  */
 int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns)
 {
-   int ret;
-
_cdns_enable_interrupt(cdns);
-   ret = cdns_clear_bit(cdns, CDNS_MCP_CONFIG_UPDATE,
-CDNS_MCP_CONFIG_UPDATE_BIT);
-   if (ret < 0)
-   dev_err(cdns->dev, "Config update timedout\n");
 
-   return ret;
+   return 0;
 }
 EXPORT_SYMBOL(sdw_cdns_enable_interrupt);
 
@@ -943,7 +953,10 @@ int sdw_cdns_init(struct sdw_cdns *cdns)
 
cdns_writel(cdns, CDNS_MCP_CONFIG, val);
 
-   return 0;
+   /* commit changes */
+   ret = cdns_update_config(cdns);
+
+   return ret;
 }
 EXPORT_SYMBOL(sdw_cdns_init);
 
-- 
2.20.1



[RFC PATCH 37/40] soundwire: cadence_master: add hw_reset capability in debugfs

2019-07-25 Thread Pierre-Louis Bossart
This is to kick devices into reset and see what software does

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index fa7230b0f200..53278aa2436f 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -331,6 +331,25 @@ static const struct file_operations cdns_reg_fops = {
.llseek = default_llseek,
 };
 
+static int cdns_hw_reset(void *data, u64 value)
+{
+   struct sdw_cdns *cdns = data;
+   int ret;
+
+   if (value != 1)
+   return 0;
+
+   dev_info(cdns->dev, "starting link hw_reset\n");
+
+   ret = sdw_cdns_exit_reset(cdns);
+
+   dev_info(cdns->dev, "link hw_reset done\n");
+
+   return ret;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(cdns_hw_reset_fops, NULL, cdns_hw_reset, "%llu\n");
+
 /**
  * sdw_cdns_debugfs_init() - Cadence debugfs init
  * @cdns: Cadence instance
@@ -339,6 +358,9 @@ static const struct file_operations cdns_reg_fops = {
 void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root)
 {
debugfs_create_file("cdns-registers", 0400, root, cdns, _reg_fops);
+
+   debugfs_create_file_unsafe("cdns-hw-reset", 0200, root, cdns,
+  _hw_reset_fops);
 }
 EXPORT_SYMBOL_GPL(sdw_cdns_debugfs_init);
 
-- 
2.20.1



[RFC PATCH 11/40] soundwire: cadence_master: simplify bus clash interrupt clear

2019-07-25 Thread Pierre-Louis Bossart
The bus clash interrupts are generated when the status is one, and
also cleared by writing a one. It's overkill/useless to use an OR when
the bit is already set.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index e85e49340986..bdc3ed844829 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -692,7 +692,6 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
if (int_status & CDNS_MCP_INT_CTRL_CLASH) {
/* Slave is driving bit slot during control word */
dev_err_ratelimited(cdns->dev, "Bus clash for control word\n");
-   int_status |= CDNS_MCP_INT_CTRL_CLASH;
}
 
if (int_status & CDNS_MCP_INT_DATA_CLASH) {
@@ -701,7 +700,6 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
 * ownership of data bits or Slave gone bonkers
 */
dev_err_ratelimited(cdns->dev, "Bus clash for data word\n");
-   int_status |= CDNS_MCP_INT_DATA_CLASH;
}
 
if (int_status & CDNS_MCP_INT_SLAVE_MASK) {
-- 
2.20.1



[RFC PATCH 16/40] soundwire: cadence_master: improve startup sequence with link hw_reset

2019-07-25 Thread Pierre-Louis Bossart
Enable interrupts first, then engage hardware bus reset with maximum
duration to make sure the Slave(s) correctly detect the reset pattern
and to ensure electrical conflicts can be resolved.

Without these changes the initialization is randomly corrupted by bus
clashes, parity errors and Slave attachment does not generate any
interrupt, despite the status showing them being attached.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 35 +-
 1 file changed, 30 insertions(+), 5 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index 25d5c7267c15..442f78c00f09 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -778,6 +778,31 @@ EXPORT_SYMBOL(sdw_cdns_thread);
  * init routines
  */
 
+static int do_reset(struct sdw_cdns *cdns)
+{
+   int ret;
+
+   /* program maximum length reset to be safe */
+   cdns_updatel(cdns, CDNS_MCP_CONTROL,
+CDNS_MCP_CONTROL_RST_DELAY,
+CDNS_MCP_CONTROL_RST_DELAY);
+
+   /* use hardware generated reset */
+   cdns_updatel(cdns, CDNS_MCP_CONTROL,
+CDNS_MCP_CONTROL_HW_RST,
+CDNS_MCP_CONTROL_HW_RST);
+
+   /* enable bus operations with clock and data */
+   cdns_updatel(cdns, CDNS_MCP_CONFIG,
+CDNS_MCP_CONFIG_OP,
+CDNS_MCP_CONFIG_OP_NORMAL);
+
+   /* commit changes */
+   ret = cdns_update_config(cdns);
+
+   return ret;
+}
+
 /**
  * sdw_cdns_enable_interrupt() - Enable SDW interrupts and update config
  * @cdns: Cadence instance
@@ -809,7 +834,7 @@ int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns)
 
cdns_writel(cdns, CDNS_MCP_INTMASK, mask);
 
-   return 0;
+   return do_reset(cdns);
 }
 EXPORT_SYMBOL(sdw_cdns_enable_interrupt);
 
@@ -958,6 +983,10 @@ int sdw_cdns_init(struct sdw_cdns *cdns)
cdns_writel(cdns, CDNS_MCP_SSP_CTRL0, CDNS_DEFAULT_SSP_INTERVAL);
cdns_writel(cdns, CDNS_MCP_SSP_CTRL1, CDNS_DEFAULT_SSP_INTERVAL);
 
+   /* flush command FIFOs */
+   cdns_updatel(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_CMD_RST,
+CDNS_MCP_CONTROL_CMD_RST);
+
/* Set cmd accept mode */
cdns_updatel(cdns, CDNS_MCP_CONTROL, CDNS_MCP_CONTROL_CMD_ACCEPT,
 CDNS_MCP_CONTROL_CMD_ACCEPT);
@@ -980,10 +1009,6 @@ int sdw_cdns_init(struct sdw_cdns *cdns)
/* Set cmd mode for Tx and Rx cmds */
val &= ~CDNS_MCP_CONFIG_CMD;
 
-   /* Set operation to normal */
-   val &= ~CDNS_MCP_CONFIG_OP;
-   val |= CDNS_MCP_CONFIG_OP_NORMAL;
-
cdns_writel(cdns, CDNS_MCP_CONFIG, val);
 
/* commit changes */
-- 
2.20.1



[RFC PATCH 01/40] soundwire: add debugfs support

2019-07-25 Thread Pierre-Louis Bossart
Add base debugfs mechanism for SoundWire bus by creating soundwire
root and master-N and slave-x hierarchy.

Also add SDW Slave SCP, DP0 and DP-N register debug file.

Registers not implemented will print as "XX"

Credits: this patch is based on an earlier internal contribution by
Vinod Koul, Sanyog Kale, Shreyas Nc and Hardik Shah. The main change
is the use of scnprintf to avoid known issues with snprintf.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/Makefile|   4 +-
 drivers/soundwire/bus.c   |   6 ++
 drivers/soundwire/bus.h   |  24 ++
 drivers/soundwire/bus_type.c  |   3 +
 drivers/soundwire/debugfs.c   | 156 ++
 drivers/soundwire/slave.c |   1 +
 include/linux/soundwire/sdw.h |   4 +
 7 files changed, 197 insertions(+), 1 deletion(-)
 create mode 100644 drivers/soundwire/debugfs.c

diff --git a/drivers/soundwire/Makefile b/drivers/soundwire/Makefile
index fd99a831b92a..88990cac48a7 100644
--- a/drivers/soundwire/Makefile
+++ b/drivers/soundwire/Makefile
@@ -4,7 +4,9 @@
 #
 
 #Bus Objs
-soundwire-bus-objs := bus_type.o bus.o slave.o mipi_disco.o stream.o
+soundwire-bus-objs := bus_type.o bus.o slave.o mipi_disco.o stream.o \
+   debugfs.o
+
 obj-$(CONFIG_SOUNDWIRE_BUS) += soundwire-bus.o
 
 #Cadence Objs
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
index fe745830a261..5ad4109dc72f 100644
--- a/drivers/soundwire/bus.c
+++ b/drivers/soundwire/bus.c
@@ -49,6 +49,8 @@ int sdw_add_bus_master(struct sdw_bus *bus)
}
}
 
+   bus->debugfs = sdw_bus_debugfs_init(bus);
+
/*
 * Device numbers in SoundWire are 0 through 15. Enumeration device
 * number (0), Broadcast device number (15), Group numbers (12 and
@@ -109,6 +111,8 @@ static int sdw_delete_slave(struct device *dev, void *data)
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct sdw_bus *bus = slave->bus;
 
+   sdw_slave_debugfs_exit(slave->debugfs);
+
mutex_lock(>bus_lock);
 
if (slave->dev_num) /* clear dev_num if assigned */
@@ -130,6 +134,8 @@ static int sdw_delete_slave(struct device *dev, void *data)
 void sdw_delete_bus_master(struct sdw_bus *bus)
 {
device_for_each_child(bus->dev, NULL, sdw_delete_slave);
+
+   sdw_bus_debugfs_exit(bus->debugfs);
 }
 EXPORT_SYMBOL(sdw_delete_bus_master);
 
diff --git a/drivers/soundwire/bus.h b/drivers/soundwire/bus.h
index 3048ca153f22..06ac4adb0074 100644
--- a/drivers/soundwire/bus.h
+++ b/drivers/soundwire/bus.h
@@ -18,6 +18,30 @@ static inline int sdw_acpi_find_slaves(struct sdw_bus *bus)
 void sdw_extract_slave_id(struct sdw_bus *bus,
  u64 addr, struct sdw_slave_id *id);
 
+#ifdef CONFIG_DEBUG_FS
+struct dentry *sdw_bus_debugfs_init(struct sdw_bus *bus);
+void sdw_bus_debugfs_exit(struct dentry *d);
+struct dentry *sdw_slave_debugfs_init(struct sdw_slave *slave);
+void sdw_slave_debugfs_exit(struct dentry *d);
+void sdw_debugfs_init(void);
+void sdw_debugfs_exit(void);
+#else
+struct dentry *sdw_bus_debugfs_init(struct sdw_bus *bus)
+{ return NULL; }
+
+void sdw_bus_debugfs_exit(struct dentry *d) {}
+
+struct dentry *sdw_slave_debugfs_init(struct sdw_slave *slave)
+{ return NULL; }
+
+void sdw_slave_debugfs_exit(struct dentry *d) {}
+
+void sdw_debugfs_init(void) {}
+
+void sdw_debugfs_exit(void) {}
+
+#endif
+
 enum {
SDW_MSG_FLAG_READ = 0,
SDW_MSG_FLAG_WRITE,
diff --git a/drivers/soundwire/bus_type.c b/drivers/soundwire/bus_type.c
index 2655602f0cfb..4a465f55039f 100644
--- a/drivers/soundwire/bus_type.c
+++ b/drivers/soundwire/bus_type.c
@@ -6,6 +6,7 @@
 #include 
 #include 
 #include 
+#include "bus.h"
 
 /**
  * sdw_get_device_id - find the matching SoundWire device id
@@ -177,11 +178,13 @@ EXPORT_SYMBOL_GPL(sdw_unregister_driver);
 
 static int __init sdw_bus_init(void)
 {
+   sdw_debugfs_init();
return bus_register(_bus_type);
 }
 
 static void __exit sdw_bus_exit(void)
 {
+   sdw_debugfs_exit();
bus_unregister(_bus_type);
 }
 
diff --git a/drivers/soundwire/debugfs.c b/drivers/soundwire/debugfs.c
new file mode 100644
index ..8d86e100516e
--- /dev/null
+++ b/drivers/soundwire/debugfs.c
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+// Copyright(c) 2017-19 Intel Corporation.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "bus.h"
+
+#ifdef CONFIG_DEBUG_FS
+struct dentry *sdw_debugfs_root;
+#endif
+
+struct dentry *sdw_bus_debugfs_init(struct sdw_bus *bus)
+{
+   struct dentry *d;
+   char name[16];
+
+   if (!sdw_debugfs_root)
+   return NULL;
+
+   /* create the debugfs master-N */
+   snprintf(name, sizeof(name), "master-%d", bus->link_id);
+   d = debugfs_create_dir(name, sdw_debugfs_root);
+
+   return d;
+}
+
+void sdw_bus_debugfs_exit(struct dentry *d)

[RFC PATCH 08/40] soundwire: intel: remove BIOS work-arounds

2019-07-25 Thread Pierre-Louis Bossart
the values passed by all existing BIOS are fine, let's use them as is.
The existing code must have been needed only on early prototypes.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/intel.c | 11 ---
 1 file changed, 11 deletions(-)

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 51990b192dc0..c718c9c67a37 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -922,17 +922,6 @@ static int intel_prop_read(struct sdw_bus *bus)
/* Initialize with default handler to read all DisCo properties */
sdw_master_read_prop(bus);
 
-   /* BIOS is not giving some values correctly. So, lets override them */
-   bus->prop.num_clk_freq = 1;
-   bus->prop.clk_freq = devm_kcalloc(bus->dev, bus->prop.num_clk_freq,
- sizeof(*bus->prop.clk_freq),
- GFP_KERNEL);
-   if (!bus->prop.clk_freq)
-   return -ENOMEM;
-
-   bus->prop.clk_freq[0] = bus->prop.max_clk_freq;
-   bus->prop.err_threshold = 5;
-
return 0;
 }
 
-- 
2.20.1



[RFC PATCH 12/40] soundwire: cadence_master: revisit interrupt settings

2019-07-25 Thread Pierre-Louis Bossart
Adding missing interrupt masks (parity, etc) and missing checks.
Clarify which masks are for which usage.

Signed-off-by: Bard Liao 
Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 25 ++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index bdc3ed844829..0f3b9c160b01 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -76,9 +76,12 @@
 #define CDNS_MCP_INT_DPINT BIT(11)
 #define CDNS_MCP_INT_CTRL_CLASHBIT(10)
 #define CDNS_MCP_INT_DATA_CLASHBIT(9)
+#define CDNS_MCP_INT_PARITYBIT(8)
 #define CDNS_MCP_INT_CMD_ERR   BIT(7)
+#define CDNS_MCP_INT_RX_NE BIT(3)
 #define CDNS_MCP_INT_RX_WL BIT(2)
 #define CDNS_MCP_INT_TXE   BIT(1)
+#define CDNS_MCP_INT_TXF   BIT(0)
 
 #define CDNS_MCP_INTSET0x4C
 
@@ -689,6 +692,11 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
}
}
 
+   if (int_status & CDNS_MCP_INT_PARITY) {
+   /* Parity error detected by Master */
+   dev_err_ratelimited(cdns->dev, "Parity error\n");
+   }
+
if (int_status & CDNS_MCP_INT_CTRL_CLASH) {
/* Slave is driving bit slot during control word */
dev_err_ratelimited(cdns->dev, "Bus clash for control word\n");
@@ -761,10 +769,21 @@ int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns)
cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK1,
CDNS_MCP_SLAVE_INTMASK1_MASK);
 
+   /* enable detection of slave state changes */
mask = CDNS_MCP_INT_SLAVE_RSVD | CDNS_MCP_INT_SLAVE_ALERT |
-   CDNS_MCP_INT_SLAVE_ATTACH | CDNS_MCP_INT_SLAVE_NATTACH |
-   CDNS_MCP_INT_CTRL_CLASH | CDNS_MCP_INT_DATA_CLASH |
-   CDNS_MCP_INT_RX_WL | CDNS_MCP_INT_IRQ | CDNS_MCP_INT_DPINT;
+   CDNS_MCP_INT_SLAVE_ATTACH | CDNS_MCP_INT_SLAVE_NATTACH;
+
+   /* enable detection of bus issues */
+   mask |= CDNS_MCP_INT_CTRL_CLASH | CDNS_MCP_INT_DATA_CLASH |
+   CDNS_MCP_INT_PARITY;
+
+   /* no detection of port interrupts for now */
+
+   /* enable detection of RX fifo level */
+   mask |= CDNS_MCP_INT_RX_WL;
+
+   /* now enable all of the above */
+   mask |= CDNS_MCP_INT_IRQ;
 
cdns_writel(cdns, CDNS_MCP_INTMASK, mask);
 
-- 
2.20.1



[RFC PATCH 34/40] soundwire: intel: ignore disabled links for suspend/resume

2019-07-25 Thread Pierre-Louis Bossart
Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/intel.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 1477c35f616f..a976480d6f36 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -1161,6 +1161,12 @@ static int intel_suspend(struct device *dev)
 
sdw = dev_get_drvdata(dev);
 
+   if (sdw->cdns.bus.prop.hw_disabled) {
+   dev_dbg(dev, "SoundWire master %d is disabled, ignoring\n",
+   sdw->cdns.bus.link_id);
+   return 0;
+   }
+
ret = intel_link_power_down(sdw);
if (ret) {
dev_err(dev, "Link power down failed: %d", ret);
@@ -1179,6 +1185,12 @@ static int intel_resume(struct device *dev)
 
sdw = dev_get_drvdata(dev);
 
+   if (sdw->cdns.bus.prop.hw_disabled) {
+   dev_dbg(dev, "SoundWire master %d is disabled, ignoring\n",
+   sdw->cdns.bus.link_id);
+   return 0;
+   }
+
ret = intel_init(sdw);
if (ret) {
dev_err(dev, "%s failed: %d", __func__, ret);
-- 
2.20.1



[RFC PATCH 10/40] soundwire: cadence_master: remove useless wrapper

2019-07-25 Thread Pierre-Louis Bossart
Now that we've removed the update config, there's no need for a wrapper.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 18 ++
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index eb46cf651d62..e85e49340986 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -749,7 +749,12 @@ EXPORT_SYMBOL(sdw_cdns_thread);
 /*
  * init routines
  */
-static int _cdns_enable_interrupt(struct sdw_cdns *cdns)
+
+/**
+ * sdw_cdns_enable_interrupt() - Enable SDW interrupts and update config
+ * @cdns: Cadence instance
+ */
+int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns)
 {
u32 mask;
 
@@ -767,17 +772,6 @@ static int _cdns_enable_interrupt(struct sdw_cdns *cdns)
 
return 0;
 }
-
-/**
- * sdw_cdns_enable_interrupt() - Enable SDW interrupts and update config
- * @cdns: Cadence instance
- */
-int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns)
-{
-   _cdns_enable_interrupt(cdns);
-
-   return 0;
-}
 EXPORT_SYMBOL(sdw_cdns_enable_interrupt);
 
 static int cdns_allocate_pdi(struct sdw_cdns *cdns,
-- 
2.20.1



[RFC PATCH 03/40] soundwire: cadence_master: align debugfs to 8 digits

2019-07-25 Thread Pierre-Louis Bossart
SQUASHME

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index 91e8bacb83e3..9f611a1fff0a 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -234,7 +234,7 @@ static ssize_t cdns_sprintf(struct sdw_cdns *cdns,
char *buf, size_t pos, unsigned int reg)
 {
return scnprintf(buf + pos, RD_BUF - pos,
-"%4x\t%4x\n", reg, cdns_readl(cdns, reg));
+"%4x\t%8x\n", reg, cdns_readl(cdns, reg));
 }
 
 static ssize_t cdns_reg_read(struct file *file, char __user *user_buf,
-- 
2.20.1



[RFC PATCH 06/40] soundwire: intel: prevent possible dereference in hw_params

2019-07-25 Thread Pierre-Louis Bossart
This should not happen in production systems but we should test for
all callback arguments before invoking the config_stream callback.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/intel.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 68832e613b1e..497879dd9c0d 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -509,7 +509,7 @@ static int intel_config_stream(struct sdw_intel *sdw,
   struct snd_soc_dai *dai,
   struct snd_pcm_hw_params *hw_params, int link_id)
 {
-   if (sdw->res->ops && sdw->res->ops->config_stream)
+   if (sdw->res->ops && sdw->res->ops->config_stream && sdw->res->arg)
return sdw->res->ops->config_stream(sdw->res->arg,
substream, dai, hw_params, link_id);
 
-- 
2.20.1



[RFC PATCH 25/40] soundwire: intel: use BIOS information to set clock dividers

2019-07-25 Thread Pierre-Louis Bossart
The BIOS provides an Intel-specific property, let's use it to avoid
hard-coded clock dividers.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 26 ++
 drivers/soundwire/intel.c  | 26 ++
 include/linux/soundwire/sdw.h  |  2 ++
 3 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index d84344e29f71..10ebcef2e84e 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -173,8 +173,6 @@
 #define CDNS_PDI_CONFIG_PORT   GENMASK(4, 0)
 
 /* Driver defaults */
-
-#define CDNS_DEFAULT_CLK_DIVIDER   0
 #define CDNS_DEFAULT_SSP_INTERVAL  0x18
 #define CDNS_TX_TIMEOUT2000
 
@@ -973,7 +971,10 @@ static u32 cdns_set_default_frame_shape(int n_rows, int 
n_cols)
  */
 int sdw_cdns_init(struct sdw_cdns *cdns)
 {
+   struct sdw_bus *bus = >bus;
+   struct sdw_master_prop *prop = >prop;
u32 val;
+   int divider;
int ret;
 
/* Exit clock stop */
@@ -985,9 +986,17 @@ int sdw_cdns_init(struct sdw_cdns *cdns)
}
 
/* Set clock divider */
+   divider = (prop->mclk_freq / prop->max_clk_freq) - 1;
val = cdns_readl(cdns, CDNS_MCP_CLK_CTRL0);
-   val |= CDNS_DEFAULT_CLK_DIVIDER;
+   val |= divider;
cdns_writel(cdns, CDNS_MCP_CLK_CTRL0, val);
+   cdns_writel(cdns, CDNS_MCP_CLK_CTRL1, val);
+
+   pr_err("plb: mclk %d max_freq %d divider %d register %x\n",
+  prop->mclk_freq,
+  prop->max_clk_freq,
+  divider,
+  val);
 
/* Set the default frame shape */
val = cdns_set_default_frame_shape(prop->default_row,
@@ -1035,6 +1044,7 @@ EXPORT_SYMBOL(sdw_cdns_init);
 
 int cdns_bus_conf(struct sdw_bus *bus, struct sdw_bus_params *params)
 {
+   struct sdw_master_prop *prop = >prop;
struct sdw_cdns *cdns = bus_to_cdns(bus);
int mcp_clkctrl_off, mcp_clkctrl;
int divider;
@@ -1044,7 +1054,9 @@ int cdns_bus_conf(struct sdw_bus *bus, struct 
sdw_bus_params *params)
return -EINVAL;
}
 
-   divider = (params->max_dr_freq / params->curr_dr_freq) - 1;
+   divider = prop->mclk_freq * SDW_DOUBLE_RATE_FACTOR /
+   params->curr_dr_freq;
+   divider--; /* divider is 1/(N+1) */
 
if (params->next_bank)
mcp_clkctrl_off = CDNS_MCP_CLK_CTRL1;
@@ -1055,6 +1067,12 @@ int cdns_bus_conf(struct sdw_bus *bus, struct 
sdw_bus_params *params)
mcp_clkctrl |= divider;
cdns_writel(cdns, mcp_clkctrl_off, mcp_clkctrl);
 
+   pr_err("plb: mclk * 2 %d curr_dr_freq %d divider %d register %x\n",
+  prop->mclk_freq * SDW_DOUBLE_RATE_FACTOR,
+  params->curr_dr_freq,
+  divider,
+  mcp_clkctrl);
+
return 0;
 }
 EXPORT_SYMBOL(cdns_bus_conf);
diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index c718c9c67a37..796ac2bc8cea 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -917,11 +917,37 @@ static int intel_register_dai(struct sdw_intel *sdw)
  dais, num_dai);
 }
 
+static int sdw_master_read_intel_prop(struct sdw_bus *bus)
+{
+   struct sdw_master_prop *prop = >prop;
+   struct fwnode_handle *link;
+   char name[32];
+   int nval, i;
+
+   /* Find master handle */
+   snprintf(name, sizeof(name),
+"mipi-sdw-link-%d-subproperties", bus->link_id);
+
+   link = device_get_named_child_node(bus->dev, name);
+   if (!link) {
+   dev_err(bus->dev, "Master node %s not found\n", name);
+   return -EIO;
+   }
+
+   fwnode_property_read_u32(link,
+"intel-sdw-ip-clock",
+>mclk_freq);
+   return 0;
+}
+
 static int intel_prop_read(struct sdw_bus *bus)
 {
/* Initialize with default handler to read all DisCo properties */
sdw_master_read_prop(bus);
 
+   /* read Intel-specific properties */
+   sdw_master_read_intel_prop(bus);
+
return 0;
 }
 
diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h
index 31d1e8acf25b..b6acc436ac80 100644
--- a/include/linux/soundwire/sdw.h
+++ b/include/linux/soundwire/sdw.h
@@ -379,6 +379,7 @@ struct sdw_slave_prop {
  * @dynamic_frame: Dynamic frame shape supported
  * @err_threshold: Number of times that software may retry sending a single
  * command
+ * @mclk_freq: clock reference passed to SoundWire Master, in Hz.
  */
 struct sdw_master_prop {
u32 revision;
@@ -393,6 +394,7 @@ struct sdw_master_prop {
u32 default_col;
bool dynamic_frame;
u32 err_threshold;
+   u32 mclk_freq;
 };
 
 int sdw_master_read_prop(struct sdw_bus *bus);
-- 
2.20.1



[RFC PATCH 07/40] soundwire: intel: fix channel number reported by hardware

2019-07-25 Thread Pierre-Louis Bossart
PDI2 reports an invalid count, force the correct hardware-supported
value

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/intel.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 497879dd9c0d..51990b192dc0 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -401,6 +401,15 @@ intel_pdi_get_ch_cap(struct sdw_intel *sdw, unsigned int 
pdi_num, bool pcm)
 
if (pcm) {
count = intel_readw(shim, SDW_SHIM_PCMSYCHC(link_id, pdi_num));
+
+   /*
+* TODO: pdi number 2 reports channel count as 1 even though
+* it supports 8 channel. Performing hardcoding for pdi
+* number 2.
+*/
+   if (pdi_num == 2)
+   count = 7;
+
} else {
count = intel_readw(shim, SDW_SHIM_PDMSCAP(link_id));
count = ((count & SDW_SHIM_PDMSCAP_CPSS) >>
-- 
2.20.1



[RFC PATCH 29/40] soundwire: intel_init: add kernel module parameter to filter out links

2019-07-25 Thread Pierre-Louis Bossart
The hardware and ACPI info may report the presence of links that are
not physically enabled (e.g. due to pin-muxing or hardware reworks),
which in turn can result in errors being thrown. This shouldn't be the
case for production devices but will happen a lot on development
devices - even more so when they expose a connector.

Add a module parameter to filter out such links, e.g. adding the
following config to a file in /etc/modprobe.d will select the second
and third links only.

options soundwire_intel_init sdw_link_mask=0x6

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/intel_init.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/soundwire/intel_init.c b/drivers/soundwire/intel_init.c
index 70637a0383d2..6ae8bb13f907 100644
--- a/drivers/soundwire/intel_init.c
+++ b/drivers/soundwire/intel_init.c
@@ -22,6 +22,10 @@
 #define SDW_LINK_BASE  0x3
 #define SDW_LINK_SIZE  0x1
 
+static int link_mask;
+module_param_named(sdw_link_mask, link_mask, int, 0444);
+MODULE_PARM_DESC(sdw_link_mask, "Intel link mask (one bit per link)");
+
 struct sdw_link_data {
struct sdw_intel_link_res res;
struct platform_device *pdev;
@@ -83,6 +87,9 @@ static struct sdw_intel_ctx
caps = ioread32(res->mmio_base + SDW_SHIM_BASE + SDW_SHIM_LCAP);
caps &= GENMASK(2, 0);
 
+   dev_dbg(>dev, "SoundWire links: BIOS count %d hardware caps %d\n",
+   count, caps);
+
/* Check HW supported vs property value and use min of two */
count = min_t(u8, caps, count);
 
@@ -111,6 +118,13 @@ static struct sdw_intel_ctx
 
/* Create SDW Master devices */
for (i = 0; i < count; i++) {
+   if (link_mask && !(link_mask & BIT(i))) {
+   dev_dbg(>dev,
+   "Link %d masked, will not be enabled\n", i);
+   link++;
+   continue;
+   }
+
link->res.irq = res->irq;
link->res.registers = res->mmio_base + SDW_LINK_BASE
+ (SDW_LINK_SIZE * i);
-- 
2.20.1



[RFC PATCH 19/40] soundwire: bus: improve dynamic debug comments for enumeration

2019-07-25 Thread Pierre-Louis Bossart
update comments to provide better understanding of enumeration flows.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/bus.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
index bca378806d00..2354675ef104 100644
--- a/drivers/soundwire/bus.c
+++ b/drivers/soundwire/bus.c
@@ -483,7 +483,8 @@ static int sdw_assign_device_num(struct sdw_slave *slave)
 
ret = sdw_write(slave, SDW_SCP_DEVNUMBER, dev_num);
if (ret < 0) {
-   dev_err(>dev, "Program device_num failed: %d\n", ret);
+   dev_err(>dev, "Program device_num %d failed: %d\n",
+   dev_num, ret);
return ret;
}
 
@@ -540,6 +541,7 @@ static int sdw_program_device_num(struct sdw_bus *bus)
do {
ret = sdw_transfer(bus, );
if (ret == -ENODATA) { /* end of device id reads */
+   dev_dbg(bus->dev, "No more devices to enumerate\n");
ret = 0;
break;
}
@@ -982,6 +984,7 @@ int sdw_handle_slave_status(struct sdw_bus *bus,
int i, ret = 0;
 
if (status[0] == SDW_SLAVE_ATTACHED) {
+   dev_err(bus->dev, "Slave attached, programming device 
number\n");
ret = sdw_program_device_num(bus);
if (ret)
dev_err(bus->dev, "Slave attach failed: %d\n", ret);
-- 
2.20.1



[RFC PATCH 13/40] soundwire: cadence_master: fix register definition for SLAVE_STATE

2019-07-25 Thread Pierre-Louis Bossart
wrong prefix and wrong macro.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index 0f3b9c160b01..d9d9e3d964dd 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -85,8 +85,8 @@
 
 #define CDNS_MCP_INTSET0x4C
 
-#define CDNS_SDW_SLAVE_STAT0x50
-#define CDNS_MCP_SLAVE_STAT_MASK   BIT(1, 0)
+#define CDNS_MCP_SLAVE_STAT0x50
+#define CDNS_MCP_SLAVE_STAT_MASK   GENMASK(1, 0)
 
 #define CDNS_MCP_SLAVE_INTSTAT00x54
 #define CDNS_MCP_SLAVE_INTSTAT10x58
-- 
2.20.1



[RFC PATCH 36/40] soundwire: intel: disable interrupts on suspend

2019-07-25 Thread Pierre-Louis Bossart
Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 42 +-
 drivers/soundwire/cadence_master.h |  2 +-
 drivers/soundwire/intel.c  |  6 +++--
 3 files changed, 29 insertions(+), 21 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index f486fe15fb46..fa7230b0f200 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -814,33 +814,39 @@ EXPORT_SYMBOL(sdw_cdns_exit_reset);
  * sdw_cdns_enable_interrupt() - Enable SDW interrupts and update config
  * @cdns: Cadence instance
  */
-int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns)
+int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns, bool state)
 {
u32 mask;
 
-   cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK0,
-   CDNS_MCP_SLAVE_INTMASK0_MASK);
-   cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK1,
-   CDNS_MCP_SLAVE_INTMASK1_MASK);
+   if (state) {
+   cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK0,
+   CDNS_MCP_SLAVE_INTMASK0_MASK);
+   cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK1,
+   CDNS_MCP_SLAVE_INTMASK1_MASK);
 
-   /* enable detection of slave state changes */
-   mask = CDNS_MCP_INT_SLAVE_RSVD | CDNS_MCP_INT_SLAVE_ALERT |
-   CDNS_MCP_INT_SLAVE_ATTACH | CDNS_MCP_INT_SLAVE_NATTACH;
+   /* enable detection of slave state changes */
+   mask = CDNS_MCP_INT_SLAVE_RSVD | CDNS_MCP_INT_SLAVE_ALERT |
+   CDNS_MCP_INT_SLAVE_ATTACH | CDNS_MCP_INT_SLAVE_NATTACH;
 
-   /* enable detection of bus issues */
-   mask |= CDNS_MCP_INT_CTRL_CLASH | CDNS_MCP_INT_DATA_CLASH |
-   CDNS_MCP_INT_PARITY;
+   /* enable detection of bus issues */
+   mask |= CDNS_MCP_INT_CTRL_CLASH | CDNS_MCP_INT_DATA_CLASH |
+   CDNS_MCP_INT_PARITY;
 
-   /* no detection of port interrupts for now */
+   /* no detection of port interrupts for now */
 
-   /* enable detection of RX fifo level */
-   mask |= CDNS_MCP_INT_RX_WL;
+   /* enable detection of RX fifo level */
+   mask |= CDNS_MCP_INT_RX_WL;
 
-   /* now enable all of the above */
-   mask |= CDNS_MCP_INT_IRQ;
+   /* now enable all of the above */
+   mask |= CDNS_MCP_INT_IRQ;
 
-   if (interrupt_mask) /* parameter override */
-   mask = interrupt_mask;
+   if (interrupt_mask) /* parameter override */
+   mask = interrupt_mask;
+   } else {
+   cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK0, 0);
+   cdns_writel(cdns, CDNS_MCP_SLAVE_INTMASK1, 0);
+   mask = 0;
+   }
 
cdns_writel(cdns, CDNS_MCP_INTMASK, mask);
 
diff --git a/drivers/soundwire/cadence_master.h 
b/drivers/soundwire/cadence_master.h
index 2b551f9226f3..1a0ba36dd78f 100644
--- a/drivers/soundwire/cadence_master.h
+++ b/drivers/soundwire/cadence_master.h
@@ -162,7 +162,7 @@ int sdw_cdns_init(struct sdw_cdns *cdns);
 int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
  struct sdw_cdns_stream_config config);
 int sdw_cdns_exit_reset(struct sdw_cdns *cdns);
-int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns);
+int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns, bool state);
 
 void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root);
 
diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 9ebe38e4d979..1192d5775484 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -1110,7 +1110,7 @@ static int intel_probe(struct platform_device *pdev)
goto err_init;
}
 
-   ret = sdw_cdns_enable_interrupt(>cdns);
+   ret = sdw_cdns_enable_interrupt(>cdns, true);
 
ret = sdw_cdns_exit_reset(>cdns);
 
@@ -1169,6 +1169,8 @@ static int intel_suspend(struct device *dev)
return 0;
}
 
+   sdw_cdns_enable_interrupt(>cdns, false);
+
ret = intel_link_power_down(sdw);
if (ret) {
dev_err(dev, "Link power down failed: %d", ret);
@@ -1199,7 +1201,7 @@ static int intel_resume(struct device *dev)
return ret;
}
 
-   sdw_cdns_enable_interrupt(>cdns);
+   sdw_cdns_enable_interrupt(>cdns, true);
 
ret = sdw_cdns_exit_reset(>cdns);
 
-- 
2.20.1



[RFC PATCH 15/40] soundwire: cadence_master: handle multiple status reports per Slave

2019-07-25 Thread Pierre-Louis Bossart
When a Slave reports multiple status in the sticky bits, find the
latest configuration from the mirror of the PING frame status and
update the status directly.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 34 --
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index 889fa2cd49ae..25d5c7267c15 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -643,13 +643,35 @@ static int cdns_update_slave_status(struct sdw_cdns *cdns,
 
/* first check if Slave reported multiple status */
if (set_status > 1) {
+   u32 val;
+
dev_warn_ratelimited(cdns->dev,
-"Slave reported multiple Status: 
%d\n",
-mask);
-   /*
-* TODO: we need to reread the status here by
-* issuing a PING cmd
-*/
+"Slave %d reported multiple 
Status: %d\n",
+i, mask);
+
+   /* re-check latest status extracted from PING commands 
*/
+   val = cdns_readl(cdns, CDNS_MCP_SLAVE_STAT);
+   val >>= (i * 2);
+
+   switch (val & 0x3) {
+   case 0:
+   status[i] = SDW_SLAVE_UNATTACHED;
+   break;
+   case 1:
+   status[i] = SDW_SLAVE_ATTACHED;
+   break;
+   case 2:
+   status[i] = SDW_SLAVE_ALERT;
+   break;
+   default:
+   status[i] = SDW_SLAVE_RESERVED;
+   break;
+   }
+
+   dev_warn_ratelimited(cdns->dev,
+"Slave %d status updated to %d\n",
+i, status[i]);
+
}
}
 
-- 
2.20.1



[RFC PATCH 35/40] soundwire: intel: export helper to exit reset

2019-07-25 Thread Pierre-Louis Bossart
Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 9 +++--
 drivers/soundwire/cadence_master.h | 1 +
 drivers/soundwire/intel.c  | 4 
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index 4a189e487830..f486fe15fb46 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -780,7 +780,11 @@ EXPORT_SYMBOL(sdw_cdns_thread);
  * init routines
  */
 
-static int do_reset(struct sdw_cdns *cdns)
+/**
+ * sdw_cdns_exit_reset() - Program reset parameters and start bus operations
+ * @cdns: Cadence instance
+ */
+int sdw_cdns_exit_reset(struct sdw_cdns *cdns)
 {
int ret;
 
@@ -804,6 +808,7 @@ static int do_reset(struct sdw_cdns *cdns)
 
return ret;
 }
+EXPORT_SYMBOL(sdw_cdns_exit_reset);
 
 /**
  * sdw_cdns_enable_interrupt() - Enable SDW interrupts and update config
@@ -839,7 +844,7 @@ int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns)
 
cdns_writel(cdns, CDNS_MCP_INTMASK, mask);
 
-   return do_reset(cdns);
+   return 0;
 }
 EXPORT_SYMBOL(sdw_cdns_enable_interrupt);
 
diff --git a/drivers/soundwire/cadence_master.h 
b/drivers/soundwire/cadence_master.h
index de97bc22acb7..2b551f9226f3 100644
--- a/drivers/soundwire/cadence_master.h
+++ b/drivers/soundwire/cadence_master.h
@@ -161,6 +161,7 @@ irqreturn_t sdw_cdns_thread(int irq, void *dev_id);
 int sdw_cdns_init(struct sdw_cdns *cdns);
 int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
  struct sdw_cdns_stream_config config);
+int sdw_cdns_exit_reset(struct sdw_cdns *cdns);
 int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns);
 
 void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root);
diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index a976480d6f36..9ebe38e4d979 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -1112,6 +1112,8 @@ static int intel_probe(struct platform_device *pdev)
 
ret = sdw_cdns_enable_interrupt(>cdns);
 
+   ret = sdw_cdns_exit_reset(>cdns);
+
/* Register DAIs */
ret = intel_register_dai(sdw);
if (ret) {
@@ -1199,6 +1201,8 @@ static int intel_resume(struct device *dev)
 
sdw_cdns_enable_interrupt(>cdns);
 
+   ret = sdw_cdns_exit_reset(>cdns);
+
return ret;
 }
 
-- 
2.20.1



[RFC PATCH 02/40] soundwire: cadence_master: add debugfs register dump

2019-07-25 Thread Pierre-Louis Bossart
Add debugfs file to dump the Cadence master registers

Credits: this patch is based on an earlier internal contribution by
Vinod Koul, Sanyog Kale, Shreyas Nc and Hardik Shah. The main change
is the use of scnprintf to avoid known issues with snprintf.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 98 ++
 drivers/soundwire/cadence_master.h |  2 +
 2 files changed, 100 insertions(+)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index ff4badc9b3de..91e8bacb83e3 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -8,6 +8,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -223,6 +224,103 @@ static int cdns_clear_bit(struct sdw_cdns *cdns, int 
offset, u32 value)
return -EAGAIN;
 }
 
+/*
+ * debugfs
+ */
+
+#define RD_BUF (2 * PAGE_SIZE)
+
+static ssize_t cdns_sprintf(struct sdw_cdns *cdns,
+   char *buf, size_t pos, unsigned int reg)
+{
+   return scnprintf(buf + pos, RD_BUF - pos,
+"%4x\t%4x\n", reg, cdns_readl(cdns, reg));
+}
+
+static ssize_t cdns_reg_read(struct file *file, char __user *user_buf,
+size_t count, loff_t *ppos)
+{
+   struct sdw_cdns *cdns = file->private_data;
+   char *buf;
+   ssize_t ret;
+   int i, j;
+
+   buf = kzalloc(RD_BUF, GFP_KERNEL);
+   if (!buf)
+   return -ENOMEM;
+
+   ret = scnprintf(buf, RD_BUF, "Register  Value\n");
+   ret += scnprintf(buf + ret, RD_BUF - ret, "\nMCP Registers\n");
+   for (i = 0; i < 8; i++) /* 8 MCP registers */
+   ret += cdns_sprintf(cdns, buf, ret, i * 4);
+
+   ret += scnprintf(buf + ret, RD_BUF - ret,
+"\nStatus & Intr Registers\n");
+   for (i = 0; i < 13; i++) /* 13 Status & Intr registers */
+   ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_STAT + i * 4);
+
+   ret += scnprintf(buf + ret, RD_BUF - ret,
+"\nSSP & Clk ctrl Registers\n");
+   ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_SSP_CTRL0);
+   ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_SSP_CTRL1);
+   ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_CLK_CTRL0);
+   ret += cdns_sprintf(cdns, buf, ret, CDNS_MCP_CLK_CTRL1);
+
+   ret += scnprintf(buf + ret, RD_BUF - ret,
+"\nDPn B0 Registers\n");
+   for (i = 0; i < 7; i++) {
+   ret += scnprintf(buf + ret, RD_BUF - ret,
+"\nDP-%d\n", i);
+   for (j = 0; j < 6; j++)
+   ret += cdns_sprintf(cdns, buf, ret,
+   CDNS_DPN_B0_CONFIG(i) + j * 4);
+   }
+
+   ret += scnprintf(buf + ret, RD_BUF - ret,
+"\nDPn B1 Registers\n");
+   for (i = 0; i < 7; i++) {
+   ret += scnprintf(buf + ret, RD_BUF - ret,
+"\nDP-%d\n", i);
+
+   for (j = 0; j < 6; j++)
+   ret += cdns_sprintf(cdns, buf, ret,
+   CDNS_DPN_B1_CONFIG(i) + j * 4);
+   }
+
+   ret += scnprintf(buf + ret, RD_BUF - ret,
+"\nDPn Control Registers\n");
+   for (i = 0; i < 7; i++)
+   ret += cdns_sprintf(cdns, buf, ret,
+   CDNS_PORTCTRL + i * CDNS_PORT_OFFSET);
+
+   ret += scnprintf(buf + ret, RD_BUF - ret,
+"\nPDIn Config Registers\n");
+   for (i = 0; i < 7; i++)
+   ret += cdns_sprintf(cdns, buf, ret, CDNS_PDI_CONFIG(i));
+
+   ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+   kfree(buf);
+
+   return ret;
+}
+
+static const struct file_operations cdns_reg_fops = {
+   .open = simple_open,
+   .read = cdns_reg_read,
+   .llseek = default_llseek,
+};
+
+/**
+ * sdw_cdns_debugfs_init() - Cadence debugfs init
+ * @cdns: Cadence instance
+ * @root: debugfs root
+ */
+void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root)
+{
+   debugfs_create_file("cdns-registers", 0400, root, cdns, _reg_fops);
+}
+EXPORT_SYMBOL_GPL(sdw_cdns_debugfs_init);
+
 /*
  * IO Calls
  */
diff --git a/drivers/soundwire/cadence_master.h 
b/drivers/soundwire/cadence_master.h
index fe2af62958b1..c0bf6ff00a44 100644
--- a/drivers/soundwire/cadence_master.h
+++ b/drivers/soundwire/cadence_master.h
@@ -163,6 +163,8 @@ int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
  struct sdw_cdns_stream_config config);
 int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns);
 
+void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root);
+
 int sdw_cdns_get_stream(struct sdw_cdns *cdns,
struct sdw_cdns_streams *stream,
u32 ch, u32 dir);
-- 
2.20.1



[RFC PATCH 31/40] soundwire: intel: move shutdown() callback and don't export symbol

2019-07-25 Thread Pierre-Louis Bossart
All DAI callbacks are in intel.c except for shutdown. Move and remove
export symbol

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 14 --
 drivers/soundwire/cadence_master.h |  2 --
 drivers/soundwire/intel.c  | 17 +++--
 3 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index dede55072191..4a189e487830 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -1381,19 +1381,5 @@ int sdw_cdns_alloc_stream(struct sdw_cdns *cdns,
 }
 EXPORT_SYMBOL(sdw_cdns_alloc_stream);
 
-void sdw_cdns_shutdown(struct snd_pcm_substream *substream,
-  struct snd_soc_dai *dai)
-{
-   struct sdw_cdns_dma_data *dma;
-
-   dma = snd_soc_dai_get_dma_data(dai, substream);
-   if (!dma)
-   return;
-
-   snd_soc_dai_set_dma_data(dai, substream, NULL);
-   kfree(dma);
-}
-EXPORT_SYMBOL(sdw_cdns_shutdown);
-
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("Cadence Soundwire Library");
diff --git a/drivers/soundwire/cadence_master.h 
b/drivers/soundwire/cadence_master.h
index d375bbfead18..de97bc22acb7 100644
--- a/drivers/soundwire/cadence_master.h
+++ b/drivers/soundwire/cadence_master.h
@@ -177,8 +177,6 @@ int sdw_cdns_alloc_stream(struct sdw_cdns *cdns,
 void sdw_cdns_config_stream(struct sdw_cdns *cdns, struct sdw_cdns_port *port,
u32 ch, u32 dir, struct sdw_cdns_pdi *pdi);
 
-void sdw_cdns_shutdown(struct snd_pcm_substream *substream,
-  struct snd_soc_dai *dai);
 int sdw_cdns_pcm_set_stream(struct snd_soc_dai *dai,
void *stream, int direction);
 int sdw_cdns_pdm_set_stream(struct snd_soc_dai *dai,
diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 5947fa8e840b..c40ab443e723 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -772,6 +772,19 @@ intel_hw_free(struct snd_pcm_substream *substream, struct 
snd_soc_dai *dai)
return ret;
 }
 
+void intel_shutdown(struct snd_pcm_substream *substream,
+   struct snd_soc_dai *dai)
+{
+   struct sdw_cdns_dma_data *dma;
+
+   dma = snd_soc_dai_get_dma_data(dai, substream);
+   if (!dma)
+   return;
+
+   snd_soc_dai_set_dma_data(dai, substream, NULL);
+   kfree(dma);
+}
+
 static int intel_pcm_set_sdw_stream(struct snd_soc_dai *dai,
void *stream, int direction)
 {
@@ -787,14 +800,14 @@ static int intel_pdm_set_sdw_stream(struct snd_soc_dai 
*dai,
 static const struct snd_soc_dai_ops intel_pcm_dai_ops = {
.hw_params = intel_hw_params,
.hw_free = intel_hw_free,
-   .shutdown = sdw_cdns_shutdown,
+   .shutdown = intel_shutdown,
.set_sdw_stream = intel_pcm_set_sdw_stream,
 };
 
 static const struct snd_soc_dai_ops intel_pdm_dai_ops = {
.hw_params = intel_hw_params,
.hw_free = intel_hw_free,
-   .shutdown = sdw_cdns_shutdown,
+   .shutdown = intel_shutdown,
.set_sdw_stream = intel_pdm_set_sdw_stream,
 };
 
-- 
2.20.1



[RFC PATCH 26/40] soundwire: cadence_master: fix divider setting in clock register

2019-07-25 Thread Pierre-Louis Bossart
From: Rander Wang 

The existing code uses an OR operation which would mix the original
divider setting with the new one, resulting in an invalid
configuration that can make codecs hang.

Add the mask definition and use cdns_updatel to update divider

Signed-off-by: Rander Wang 
Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index 10ebcef2e84e..18c6ac026e85 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -57,6 +57,7 @@
 #define CDNS_MCP_SSP_CTRL1 0x28
 #define CDNS_MCP_CLK_CTRL0 0x30
 #define CDNS_MCP_CLK_CTRL1 0x38
+#define CDNS_MCP_CLK_MCLKD_MASKGENMASK(7, 0)
 
 #define CDNS_MCP_STAT  0x40
 
@@ -988,9 +989,11 @@ int sdw_cdns_init(struct sdw_cdns *cdns)
/* Set clock divider */
divider = (prop->mclk_freq / prop->max_clk_freq) - 1;
val = cdns_readl(cdns, CDNS_MCP_CLK_CTRL0);
-   val |= divider;
-   cdns_writel(cdns, CDNS_MCP_CLK_CTRL0, val);
-   cdns_writel(cdns, CDNS_MCP_CLK_CTRL1, val);
+
+   cdns_updatel(cdns, CDNS_MCP_CLK_CTRL0,
+CDNS_MCP_CLK_MCLKD_MASK, divider);
+   cdns_updatel(cdns, CDNS_MCP_CLK_CTRL1,
+CDNS_MCP_CLK_MCLKD_MASK, divider);
 
pr_err("plb: mclk %d max_freq %d divider %d register %x\n",
   prop->mclk_freq,
@@ -1064,8 +1067,7 @@ int cdns_bus_conf(struct sdw_bus *bus, struct 
sdw_bus_params *params)
mcp_clkctrl_off = CDNS_MCP_CLK_CTRL0;
 
mcp_clkctrl = cdns_readl(cdns, mcp_clkctrl_off);
-   mcp_clkctrl |= divider;
-   cdns_writel(cdns, mcp_clkctrl_off, mcp_clkctrl);
+   cdns_updatel(cdns, mcp_clkctrl_off, CDNS_MCP_CLK_MCLKD_MASK, divider);
 
pr_err("plb: mclk * 2 %d curr_dr_freq %d divider %d register %x\n",
   prop->mclk_freq * SDW_DOUBLE_RATE_FACTOR,
-- 
2.20.1



[RFC PATCH 17/40] soundwire: bus: use runtime_pm_get_sync/pm when enabled

2019-07-25 Thread Pierre-Louis Bossart
Not all platforms support runtime_pm for now, let's use runtime_pm
only when enabled.

Suggested-by: Srinivas Kandagatla 
Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/bus.c | 25 -
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
index 5ad4109dc72f..0a45dc5713df 100644
--- a/drivers/soundwire/bus.c
+++ b/drivers/soundwire/bus.c
@@ -332,12 +332,16 @@ int sdw_nread(struct sdw_slave *slave, u32 addr, size_t 
count, u8 *val)
if (ret < 0)
return ret;
 
-   ret = pm_runtime_get_sync(slave->bus->dev);
-   if (ret < 0)
-   return ret;
+   if (pm_runtime_enabled(slave->bus->dev)) {
+   ret = pm_runtime_get_sync(slave->bus->dev);
+   if (ret < 0)
+   return ret;
+   }
 
ret = sdw_transfer(slave->bus, );
-   pm_runtime_put(slave->bus->dev);
+
+   if (pm_runtime_enabled(slave->bus->dev))
+   pm_runtime_put(slave->bus->dev);
 
return ret;
 }
@@ -359,13 +363,16 @@ int sdw_nwrite(struct sdw_slave *slave, u32 addr, size_t 
count, u8 *val)
   slave->dev_num, SDW_MSG_FLAG_WRITE, val);
if (ret < 0)
return ret;
-
-   ret = pm_runtime_get_sync(slave->bus->dev);
-   if (ret < 0)
-   return ret;
+   if (pm_runtime_enabled(slave->bus->dev)) {
+   ret = pm_runtime_get_sync(slave->bus->dev);
+   if (ret < 0)
+   return ret;
+   }
 
ret = sdw_transfer(slave->bus, );
-   pm_runtime_put(slave->bus->dev);
+
+   if (pm_runtime_enabled(slave->bus->dev))
+   pm_runtime_put(slave->bus->dev);
 
return ret;
 }
-- 
2.20.1



[RFC PATCH 27/40] soundwire: Add Intel resource management algorithm

2019-07-25 Thread Pierre-Louis Bossart
This algorithm computes bus parameters like clock frequency, frame
shape and port transport parameters based on active stream(s) running
on the bus.

This implementation is optimal for Intel platforms. Developers can
also implement their own .compute_params() callback for specific
resource management algorithm.

Credits: this patch is based on an earlier internal contribution by
Vinod Koul, Sanyog Kale, Shreyas Nc and Hardik Shah. All hard-coded
values were removed from the initial contribution to use BIOS
information instead.

FIXME: remove checkpatch report
WARNING: Reusing the krealloc arg is almost always a bug
+   group->rates = krealloc(group->rates,

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/Makefile  |   2 +-
 drivers/soundwire/algo_dynamic_allocation.c | 403 
 drivers/soundwire/bus.c |   3 +
 drivers/soundwire/bus.h |  46 ++-
 drivers/soundwire/stream.c  |  20 +
 include/linux/soundwire/sdw.h   |   5 +
 6 files changed, 476 insertions(+), 3 deletions(-)
 create mode 100644 drivers/soundwire/algo_dynamic_allocation.c

diff --git a/drivers/soundwire/Makefile b/drivers/soundwire/Makefile
index 88990cac48a7..f59a9d4a28fd 100644
--- a/drivers/soundwire/Makefile
+++ b/drivers/soundwire/Makefile
@@ -5,7 +5,7 @@
 
 #Bus Objs
 soundwire-bus-objs := bus_type.o bus.o slave.o mipi_disco.o stream.o \
-   debugfs.o
+   debugfs.o algo_dynamic_allocation.o
 
 obj-$(CONFIG_SOUNDWIRE_BUS) += soundwire-bus.o
 
diff --git a/drivers/soundwire/algo_dynamic_allocation.c 
b/drivers/soundwire/algo_dynamic_allocation.c
new file mode 100644
index ..89edb39162b8
--- /dev/null
+++ b/drivers/soundwire/algo_dynamic_allocation.c
@@ -0,0 +1,403 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+// Copyright(c) 2015-18 Intel Corporation.
+
+/*
+ * Bandwidth management algorithm based on 2^n gears
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include "bus.h"
+
+#define SDW_STRM_RATE_GROUPING 1
+
+struct sdw_group_params {
+   unsigned int rate;
+   int full_bw;
+   int payload_bw;
+   int hwidth;
+};
+
+struct sdw_group {
+   unsigned int count;
+   unsigned int max_size;
+   unsigned int *rates;
+};
+
+struct sdw_transport_data {
+   int hstart;
+   int hstop;
+   int block_offset;
+   int sub_block_offset;
+};
+
+static void sdw_compute_slave_ports(struct sdw_master_runtime *m_rt,
+   struct sdw_transport_data *t_data)
+{
+   struct sdw_slave_runtime *s_rt = NULL;
+   struct sdw_port_runtime *p_rt;
+   int port_bo, sample_int;
+   unsigned int rate, bps, ch = 0;
+
+   port_bo = t_data->block_offset;
+
+   list_for_each_entry(s_rt, _rt->slave_rt_list, m_rt_node) {
+   rate = m_rt->stream->params.rate;
+   bps = m_rt->stream->params.bps;
+   sample_int = (m_rt->bus->params.curr_dr_freq / rate);
+
+   list_for_each_entry(p_rt, _rt->port_list, port_node) {
+   ch = sdw_ch_mask_to_ch(p_rt->ch_mask);
+
+   sdw_fill_xport_params(_rt->transport_params,
+ p_rt->num, true,
+ SDW_BLK_GRP_CNT_1,
+ sample_int, port_bo, port_bo >> 8,
+ t_data->hstart,
+ t_data->hstop,
+ (SDW_BLK_GRP_CNT_1 * ch), 0x0);
+
+   sdw_fill_port_params(_rt->port_params,
+p_rt->num, bps,
+SDW_PORT_FLOW_MODE_ISOCH,
+SDW_PORT_DATA_MODE_NORMAL);
+
+   port_bo += bps * ch;
+   }
+   }
+}
+
+static void sdw_compute_master_ports(struct sdw_master_runtime *m_rt,
+struct sdw_group_params *params,
+int port_bo, int hstop)
+{
+   struct sdw_transport_data t_data = {0};
+   struct sdw_port_runtime *p_rt;
+   struct sdw_bus *bus = m_rt->bus;
+   int sample_int, hstart = 0;
+   unsigned int rate, bps, ch, no_ch;
+
+   rate = m_rt->stream->params.rate;
+   bps = m_rt->stream->params.bps;
+   ch = m_rt->ch_count;
+   sample_int = (bus->params.curr_dr_freq / rate);
+
+   if (rate != params->rate)
+   return;
+
+   t_data.hstop = hstop;
+   hstart = hstop - params->hwidth + 1;
+   t_data.hstart = hstart;
+
+   list_for_each_entry(p_rt, _rt->port_list, port_node) {
+   no_ch = sdw_ch

[RFC PATCH 22/40] soundwire: include mod_devicetable.h to avoid compiling warnings

2019-07-25 Thread Pierre-Louis Bossart
From: Bard liao 

Reported-by: kbuild test robot 
Signed-off-by: Bard liao 
Signed-off-by: Pierre-Louis Bossart 
---
 include/linux/soundwire/sdw.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h
index a49028e9d666..31d1e8acf25b 100644
--- a/include/linux/soundwire/sdw.h
+++ b/include/linux/soundwire/sdw.h
@@ -4,6 +4,8 @@
 #ifndef __SOUNDWIRE_H
 #define __SOUNDWIRE_H
 
+#include 
+
 struct sdw_bus;
 struct sdw_slave;
 
-- 
2.20.1



[RFC PATCH 28/40] soundwire: intel: handle disabled links

2019-07-25 Thread Pierre-Louis Bossart
On most hardware platforms, SoundWire interfaces are pin-muxed with
other interfaces (typically DMIC or I2S) and the status of each link
needs to be checked at boot time.

For Intel platforms, the BIOS provides a menu to enable/disable the
links separately, and the information is provided to the OS with an
Intel-specific _DSD property. The same capability will be added to
revisions of the MIPI DisCo specification.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/intel.c | 26 ++
 include/linux/soundwire/sdw.h |  2 ++
 2 files changed, 24 insertions(+), 4 deletions(-)

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 796ac2bc8cea..5947fa8e840b 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -90,6 +90,8 @@
 #define SDW_ALH_STRMZCFG_DMAT  GENMASK(7, 0)
 #define SDW_ALH_STRMZCFG_CHN   GENMASK(19, 16)
 
+#define SDW_INTEL_QUIRK_MASK_BUS_DISABLE   BIT(1)
+
 enum intel_pdi_type {
INTEL_PDI_IN = 0,
INTEL_PDI_OUT = 1,
@@ -922,7 +924,7 @@ static int sdw_master_read_intel_prop(struct sdw_bus *bus)
struct sdw_master_prop *prop = >prop;
struct fwnode_handle *link;
char name[32];
-   int nval, i;
+   u32 quirk_mask;
 
/* Find master handle */
snprintf(name, sizeof(name),
@@ -937,6 +939,14 @@ static int sdw_master_read_intel_prop(struct sdw_bus *bus)
fwnode_property_read_u32(link,
 "intel-sdw-ip-clock",
 >mclk_freq);
+
+   fwnode_property_read_u32(link,
+"intel-quirk-mask",
+_mask);
+
+   if (quirk_mask & SDW_INTEL_QUIRK_MASK_BUS_DISABLE)
+   prop->hw_disabled = true;
+
return 0;
 }
 
@@ -997,6 +1007,12 @@ static int intel_probe(struct platform_device *pdev)
goto err_master_reg;
}
 
+   if (sdw->cdns.bus.prop.hw_disabled) {
+   dev_info(>dev, "SoundWire master %d is disabled, 
ignoring\n",
+sdw->cdns.bus.link_id);
+   return 0;
+   }
+
/* Initialize shim and controller */
intel_link_power_up(sdw);
intel_shim_init(sdw);
@@ -1050,9 +1066,11 @@ static int intel_remove(struct platform_device *pdev)
 
sdw = platform_get_drvdata(pdev);
 
-   intel_debugfs_exit(sdw);
-   free_irq(sdw->res->irq, sdw);
-   snd_soc_unregister_component(sdw->cdns.dev);
+   if (!sdw->cdns.bus.prop.hw_disabled) {
+   intel_debugfs_exit(sdw);
+   free_irq(sdw->res->irq, sdw);
+   snd_soc_unregister_component(sdw->cdns.dev);
+   }
sdw_delete_bus_master(>cdns.bus);
 
return 0;
diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h
index c7dfc824be80..f78b076a8782 100644
--- a/include/linux/soundwire/sdw.h
+++ b/include/linux/soundwire/sdw.h
@@ -380,6 +380,7 @@ struct sdw_slave_prop {
  * @err_threshold: Number of times that software may retry sending a single
  * command
  * @mclk_freq: clock reference passed to SoundWire Master, in Hz.
+ * @hw_disabled: if true, the Master is not functional, typically due to 
pin-mux
  */
 struct sdw_master_prop {
u32 revision;
@@ -395,6 +396,7 @@ struct sdw_master_prop {
bool dynamic_frame;
u32 err_threshold;
u32 mclk_freq;
+   bool hw_disabled;
 };
 
 int sdw_master_read_prop(struct sdw_bus *bus);
-- 
2.20.1



[RFC PATCH 24/40] soundwire: cadence_master: use BIOS defaults for frame shape

2019-07-25 Thread Pierre-Louis Bossart
Remove hard-coding and use BIOS values. If they are wrong use default
48x2 frame shape.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 19 +--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index 442f78c00f09..d84344e29f71 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -175,7 +175,6 @@
 /* Driver defaults */
 
 #define CDNS_DEFAULT_CLK_DIVIDER   0
-#define CDNS_DEFAULT_FRAME_SHAPE   0x30
 #define CDNS_DEFAULT_SSP_INTERVAL  0x18
 #define CDNS_TX_TIMEOUT2000
 
@@ -954,6 +953,20 @@ int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
 }
 EXPORT_SYMBOL(sdw_cdns_pdi_init);
 
+static u32 cdns_set_default_frame_shape(int n_rows, int n_cols)
+{
+   u32 val;
+   int c;
+   int r;
+
+   r = sdw_find_row_index(n_rows);
+   c = sdw_find_col_index(n_cols);
+
+   val = (r << 3) | c;
+
+   return val;
+}
+
 /**
  * sdw_cdns_init() - Cadence initialization
  * @cdns: Cadence instance
@@ -977,7 +990,9 @@ int sdw_cdns_init(struct sdw_cdns *cdns)
cdns_writel(cdns, CDNS_MCP_CLK_CTRL0, val);
 
/* Set the default frame shape */
-   cdns_writel(cdns, CDNS_MCP_FRAME_SHAPE_INIT, CDNS_DEFAULT_FRAME_SHAPE);
+   val = cdns_set_default_frame_shape(prop->default_row,
+  prop->default_col);
+   cdns_writel(cdns, CDNS_MCP_FRAME_SHAPE_INIT, val);
 
/* Set SSP interval to default value */
cdns_writel(cdns, CDNS_MCP_SSP_CTRL0, CDNS_DEFAULT_SSP_INTERVAL);
-- 
2.20.1



[RFC PATCH 32/40] soundwire: intel: add helper for initialization

2019-07-25 Thread Pierre-Louis Bossart
Move code to helper for reuse in power management routines

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/intel.c | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index c40ab443e723..215dc81cdf73 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -984,6 +984,15 @@ static struct sdw_master_ops sdw_intel_ops = {
.post_bank_switch = intel_post_bank_switch,
 };
 
+static int intel_init(struct sdw_intel *sdw)
+{
+   /* Initialize shim and controller */
+   intel_link_power_up(sdw);
+   intel_shim_init(sdw);
+
+   return sdw_cdns_init(>cdns);
+}
+
 /*
  * probe and init
  */
@@ -1026,11 +1035,8 @@ static int intel_probe(struct platform_device *pdev)
return 0;
}
 
-   /* Initialize shim and controller */
-   intel_link_power_up(sdw);
-   intel_shim_init(sdw);
-
-   ret = sdw_cdns_init(>cdns);
+   /* Initialize shim, controller and Cadence IP */
+   ret = intel_init(sdw);
if (ret)
goto err_init;
 
-- 
2.20.1



[RFC PATCH 18/40] soundwire: bus: split handling of Device0 events

2019-07-25 Thread Pierre-Louis Bossart
Assigning a device number to a Slave will result in additional events
when it reports its status in a PING frame. There is no point in
dealing with all the other devices in a loop, this can be done when a
non-device0 event happens.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/bus.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
index 0a45dc5713df..bca378806d00 100644
--- a/drivers/soundwire/bus.c
+++ b/drivers/soundwire/bus.c
@@ -985,6 +985,11 @@ int sdw_handle_slave_status(struct sdw_bus *bus,
ret = sdw_program_device_num(bus);
if (ret)
dev_err(bus->dev, "Slave attach failed: %d\n", ret);
+   /*
+* programming a device number will have side effects,
+* so we deal with other devices at a later time
+*/
+   return ret;
}
 
/* Continue to check other slave statuses */
-- 
2.20.1



[RFC PATCH 20/40] soundwire: prototypes for suspend/resume

2019-07-25 Thread Pierre-Louis Bossart
Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/soundwire/cadence_master.h 
b/drivers/soundwire/cadence_master.h
index c0bf6ff00a44..d375bbfead18 100644
--- a/drivers/soundwire/cadence_master.h
+++ b/drivers/soundwire/cadence_master.h
@@ -165,6 +165,9 @@ int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns);
 
 void sdw_cdns_debugfs_init(struct sdw_cdns *cdns, struct dentry *root);
 
+int sdw_cdns_suspend(struct sdw_cdns *cdns);
+bool sdw_cdns_check_resume_status(struct sdw_cdns *cdns);
+
 int sdw_cdns_get_stream(struct sdw_cdns *cdns,
struct sdw_cdns_streams *stream,
u32 ch, u32 dir);
-- 
2.20.1



[RFC PATCH 21/40] soundwire: export helpers to find row and column values

2019-07-25 Thread Pierre-Louis Bossart
Add a prefix for common tables and export 2 helpers to set the frame
shapes based on row/col values.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/bus.h|  7 +--
 drivers/soundwire/stream.c | 14 --
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/soundwire/bus.h b/drivers/soundwire/bus.h
index 06ac4adb0074..c57c9c23f6ca 100644
--- a/drivers/soundwire/bus.h
+++ b/drivers/soundwire/bus.h
@@ -73,8 +73,11 @@ struct sdw_msg {
 
 #define SDW_DOUBLE_RATE_FACTOR 2
 
-extern int rows[SDW_FRAME_ROWS];
-extern int cols[SDW_FRAME_COLS];
+extern int sdw_rows[SDW_FRAME_ROWS];
+extern int sdw_cols[SDW_FRAME_COLS];
+
+int sdw_find_row_index(int row);
+int sdw_find_col_index(int col);
 
 /**
  * sdw_port_runtime: Runtime port parameters for Master or Slave
diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c
index a0476755a459..53f5e790fcd7 100644
--- a/drivers/soundwire/stream.c
+++ b/drivers/soundwire/stream.c
@@ -21,37 +21,39 @@
  * The rows are arranged as per the array index value programmed
  * in register. The index 15 has dummy value 0 in order to fill hole.
  */
-int rows[SDW_FRAME_ROWS] = {48, 50, 60, 64, 75, 80, 125, 147,
+int sdw_rows[SDW_FRAME_ROWS] = {48, 50, 60, 64, 75, 80, 125, 147,
96, 100, 120, 128, 150, 160, 250, 0,
192, 200, 240, 256, 72, 144, 90, 180};
 
-int cols[SDW_FRAME_COLS] = {2, 4, 6, 8, 10, 12, 14, 16};
+int sdw_cols[SDW_FRAME_COLS] = {2, 4, 6, 8, 10, 12, 14, 16};
 
-static int sdw_find_col_index(int col)
+int sdw_find_col_index(int col)
 {
int i;
 
for (i = 0; i < SDW_FRAME_COLS; i++) {
-   if (cols[i] == col)
+   if (sdw_cols[i] == col)
return i;
}
 
pr_warn("Requested column not found, selecting lowest column no: 2\n");
return 0;
 }
+EXPORT_SYMBOL(sdw_find_col_index);
 
-static int sdw_find_row_index(int row)
+int sdw_find_row_index(int row)
 {
int i;
 
for (i = 0; i < SDW_FRAME_ROWS; i++) {
-   if (rows[i] == row)
+   if (sdw_rows[i] == row)
return i;
}
 
pr_warn("Requested row not found, selecting lowest row no: 48\n");
return 0;
 }
+EXPORT_SYMBOL(sdw_find_row_index);
 
 static int _sdw_program_slave_port_params(struct sdw_bus *bus,
  struct sdw_slave *slave,
-- 
2.20.1



[RFC PATCH 23/40] soundwire: stream: fix disable sequence

2019-07-25 Thread Pierre-Louis Bossart
When we disable the stream and then call hw_free, two bank switches
will be handled and as a result we re-enable the stream on hw_free.

Make sure the stream is disabled on both banks.

TODO: we need to completely revisit all this and make sure we have a
mirroring mechanism between current and alternate banks.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/stream.c | 19 ++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c
index 53f5e790fcd7..75b9ad1fb1a6 100644
--- a/drivers/soundwire/stream.c
+++ b/drivers/soundwire/stream.c
@@ -1637,7 +1637,24 @@ static int _sdw_disable_stream(struct sdw_stream_runtime 
*stream)
}
}
 
-   return do_bank_switch(stream);
+   ret = do_bank_switch(stream);
+   if (ret < 0) {
+   dev_err(bus->dev, "Bank switch failed: %d\n", ret);
+   return ret;
+   }
+
+   /* make sure alternate bank (previous current) is also disabled */
+   list_for_each_entry(m_rt, >master_list, stream_node) {
+   bus = m_rt->bus;
+   /* Disable port(s) */
+   ret = sdw_enable_disable_ports(m_rt, false);
+   if (ret < 0) {
+   dev_err(bus->dev, "Disable port(s) failed: %d\n", ret);
+   return ret;
+   }
+   }
+
+   return 0;
 }
 
 /**
-- 
2.20.1



[RFC PATCH 38/40] soundwire: cadence_master: make clock stop exit configurable on init

2019-07-25 Thread Pierre-Louis Bossart
The use of clock stop is not a requirement, the IP can e.g. be
completely power gated and not detect any wakes while in s2idle/deep
sleep.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 15 ---
 drivers/soundwire/cadence_master.h |  2 +-
 drivers/soundwire/intel.c  |  2 +-
 3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index 53278aa2436f..4ab6f70d7705 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -1010,7 +1010,7 @@ static u32 cdns_set_default_frame_shape(int n_rows, int 
n_cols)
  * sdw_cdns_init() - Cadence initialization
  * @cdns: Cadence instance
  */
-int sdw_cdns_init(struct sdw_cdns *cdns)
+int sdw_cdns_init(struct sdw_cdns *cdns, bool clock_stop_exit)
 {
struct sdw_bus *bus = >bus;
struct sdw_master_prop *prop = >prop;
@@ -1018,12 +1018,13 @@ int sdw_cdns_init(struct sdw_cdns *cdns)
int divider;
int ret;
 
-   /* Exit clock stop */
-   ret = cdns_clear_bit(cdns, CDNS_MCP_CONTROL,
-CDNS_MCP_CONTROL_CLK_STOP_CLR);
-   if (ret < 0) {
-   dev_err(cdns->dev, "Couldn't exit from clock stop\n");
-   return ret;
+   if (clock_stop_exit) {
+   ret = cdns_clear_bit(cdns, CDNS_MCP_CONTROL,
+CDNS_MCP_CONTROL_CLK_STOP_CLR);
+   if (ret < 0) {
+   dev_err(cdns->dev, "Couldn't exit from clock stop\n");
+   return ret;
+   }
}
 
/* Set clock divider */
diff --git a/drivers/soundwire/cadence_master.h 
b/drivers/soundwire/cadence_master.h
index 1a0ba36dd78f..091b771b570d 100644
--- a/drivers/soundwire/cadence_master.h
+++ b/drivers/soundwire/cadence_master.h
@@ -158,7 +158,7 @@ extern struct sdw_master_ops sdw_cdns_master_ops;
 irqreturn_t sdw_cdns_irq(int irq, void *dev_id);
 irqreturn_t sdw_cdns_thread(int irq, void *dev_id);
 
-int sdw_cdns_init(struct sdw_cdns *cdns);
+int sdw_cdns_init(struct sdw_cdns *cdns, bool clock_stop_exit);
 int sdw_cdns_pdi_init(struct sdw_cdns *cdns,
  struct sdw_cdns_stream_config config);
 int sdw_cdns_exit_reset(struct sdw_cdns *cdns);
diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 1192d5775484..db7bf2912767 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -1043,7 +1043,7 @@ static int intel_init(struct sdw_intel *sdw)
intel_link_power_up(sdw);
intel_shim_init(sdw);
 
-   return sdw_cdns_init(>cdns);
+   return sdw_cdns_init(>cdns, false);
 }
 
 /*
-- 
2.20.1



[RFC PATCH 39/40] soundwire: intel: add pm_runtime support

2019-07-25 Thread Pierre-Louis Bossart
Add basic hooks in DAI .startup and .shutdown callbacks. The SoundWire
IP should be powered between those two calls.

By default the platform_device is in SUSPENDED mode, it is required to
call pm_runtime_set_active() before _enable()

FIXME: do we need to use mark_last_busy()?

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/intel.c | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index db7bf2912767..1394a2322553 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -707,6 +707,23 @@ static void intel_port_cleanup(struct sdw_cdns_dma_data 
*dma)
}
 }
 
+static int intel_startup(struct snd_pcm_substream *substream,
+struct snd_soc_dai *dai)
+{
+   struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
+   int ret;
+
+   ret = pm_runtime_get_sync(cdns->dev);
+   if (ret < 0) {
+   dev_err_ratelimited(cdns->dev,
+   "pm_runtime_get_sync failed in %s, ret 
%d\n",
+   __func__, ret);
+   pm_runtime_put_noidle(cdns->dev);
+   }
+
+   return ret;
+}
+
 static int intel_hw_params(struct snd_pcm_substream *substream,
   struct snd_pcm_hw_params *params,
   struct snd_soc_dai *dai)
@@ -829,6 +846,8 @@ void intel_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
 {
struct sdw_cdns_dma_data *dma;
+   struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
+   int ret;
 
dma = snd_soc_dai_get_dma_data(dai, substream);
if (!dma)
@@ -836,6 +855,13 @@ void intel_shutdown(struct snd_pcm_substream *substream,
 
snd_soc_dai_set_dma_data(dai, substream, NULL);
kfree(dma);
+
+   pm_runtime_mark_last_busy(cdns->dev);
+   ret = pm_runtime_put_autosuspend(cdns->dev);
+   if (ret < 0)
+   dev_err_ratelimited(cdns->dev,
+   "pM_runtime_put_autosuspend failed in %s:, 
ret %d\n",
+   __func__, ret);
 }
 
 static int intel_pcm_set_sdw_stream(struct snd_soc_dai *dai,
@@ -851,6 +877,7 @@ static int intel_pdm_set_sdw_stream(struct snd_soc_dai *dai,
 }
 
 static const struct snd_soc_dai_ops intel_pcm_dai_ops = {
+   .startup = intel_startup,
.hw_params = intel_hw_params,
.hw_free = intel_hw_free,
.shutdown = intel_shutdown,
@@ -1124,6 +1151,15 @@ static int intel_probe(struct platform_device *pdev)
 
intel_debugfs_init(sdw);
 
+   /* Enable PM */
+   pm_runtime_set_autosuspend_delay(>dev, 3000);
+   pm_runtime_use_autosuspend(>dev);
+
+   pm_runtime_mark_last_busy(>dev); /* FIXME: needed? */
+
+   pm_runtime_set_active(>dev);
+   pm_runtime_enable(>dev);
+
return 0;
 
 err_dai:
@@ -1141,6 +1177,7 @@ static int intel_remove(struct platform_device *pdev)
sdw = platform_get_drvdata(pdev);
 
if (!sdw->cdns.bus.prop.hw_disabled) {
+   pm_runtime_disable(>dev);
intel_debugfs_exit(sdw);
free_irq(sdw->res->irq, sdw);
snd_soc_unregister_component(sdw->cdns.dev);
@@ -1212,6 +1249,7 @@ static int intel_resume(struct device *dev)
 
 static const struct dev_pm_ops intel_pm = {
SET_SYSTEM_SLEEP_PM_OPS(intel_suspend, intel_resume)
+   SET_RUNTIME_PM_OPS(intel_suspend, intel_resume, NULL)
 };
 
 static struct platform_driver sdw_intel_drv = {
-- 
2.20.1



[RFC PATCH 00/40] soundwire: updates for 5.4

2019-07-25 Thread Pierre-Louis Bossart
The existing upstream code allows for SoundWire devices to be
enumerated and managed by the bus, but streaming is not currently
supported.

Bard Liao, Rander Wang and I did quite a bit of integration/validation
work to close this gap and we now have SoundWire streaming + basic
power managemement on Intel CometLake and IceLake reference
boards. These changes are still preliminary and should not be merged
as is, but it's time to start reviews. While the number of patches is
quite large, each of the changes is quite small.

SOF driver changes will be submitted shortly as well but are still
being validated.

ClockStop modes and synchronized playback on
multiple links are not supported for now and will likely be part of
the next cycle (dependencies on codec drivers and multi-cpu DAI
support).

Acknowledgements: This work would not have been possible without the
support of Slawomir Blauciak and Tomasz Lauda on the SOF side,
currently being reviewed, see
https://github.com/thesofproject/sof/pull/1638

Comments and feedback welcome!

Bard liao (1):
  soundwire: include mod_devicetable.h to avoid compiling warnings

Pierre-Louis Bossart (38):
  soundwire: add debugfs support
  soundwire: cadence_master: add debugfs register dump
  soundwire: cadence_master: align debugfs to 8 digits
  soundwire: intel: add debugfs register dump
  soundwire: intel: move interrupt enable after interrupt handler
registration
  soundwire: intel: prevent possible dereference in hw_params
  soundwire: intel: fix channel number reported by hardware
  soundwire: intel: remove BIOS work-arounds
  soundwire: cadence_master: fix usage of CONFIG_UPDATE
  soundwire: cadence_master: remove useless wrapper
  soundwire: cadence_master: simplify bus clash interrupt clear
  soundwire: cadence_master: revisit interrupt settings
  soundwire: cadence_master: fix register definition for SLAVE_STATE
  soundwire: cadence_master: fix definitions for INTSTAT0/1
  soundwire: cadence_master: handle multiple status reports per Slave
  soundwire: cadence_master: improve startup sequence with link hw_reset
  soundwire: bus: use runtime_pm_get_sync/pm when enabled
  soundwire: bus: split handling of Device0 events
  soundwire: bus: improve dynamic debug comments for enumeration
  soundwire: prototypes for suspend/resume
  soundwire: export helpers to find row and column values
  soundwire: stream: fix disable sequence
  soundwire: cadence_master: use BIOS defaults for frame shape
  soundwire: intel: use BIOS information to set clock dividers
  soundwire: Add Intel resource management algorithm
  soundwire: intel: handle disabled links
  soundwire: intel_init: add kernel module parameter to filter out links
  soundwire: cadence_master: add kernel parameter to override interrupt
mask
  soundwire: intel: move shutdown() callback and don't export symbol
  soundwire: intel: add helper for initialization
  soundwire: intel: Add basic power management support
  soundwire: intel: ignore disabled links for suspend/resume
  soundwire: intel: export helper to exit reset
  soundwire: intel: disable interrupts on suspend
  soundwire: cadence_master: add hw_reset capability in debugfs
  soundwire: cadence_master: make clock stop exit configurable on init
  soundwire: intel: add pm_runtime support
  soundwire: intel: add delay on restart for enumeration

Rander Wang (1):
  soundwire: cadence_master: fix divider setting in clock register

 drivers/soundwire/Makefile  |   4 +-
 drivers/soundwire/algo_dynamic_allocation.c | 403 
 drivers/soundwire/bus.c |  44 ++-
 drivers/soundwire/bus.h |  77 +++-
 drivers/soundwire/bus_type.c|   3 +
 drivers/soundwire/cadence_master.c  | 365 ++
 drivers/soundwire/cadence_master.h  |  12 +-
 drivers/soundwire/debugfs.c | 156 
 drivers/soundwire/intel.c   | 381 +-
 drivers/soundwire/intel_init.c  |  14 +
 drivers/soundwire/slave.c   |   1 +
 drivers/soundwire/stream.c  |  53 ++-
 include/linux/soundwire/sdw.h   |  15 +
 13 files changed, 1414 insertions(+), 114 deletions(-)
 create mode 100644 drivers/soundwire/algo_dynamic_allocation.c
 create mode 100644 drivers/soundwire/debugfs.c

-- 
2.20.1



[RFC PATCH 04/40] soundwire: intel: add debugfs register dump

2019-07-25 Thread Pierre-Louis Bossart
Add debugfs file to dump the Intel SoundWire registers

Credits: this patch is based on an earlier internal contribution by
Vinod Koul, Sanyog Kale, Shreyas Nc and Hardik Shah. The main change
is the use of scnprintf to avoid known issues with snprintf.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/intel.c | 115 ++
 1 file changed, 115 insertions(+)

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 317873bc0555..aeadc341c0a3 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -6,6 +6,7 @@
  */
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -16,6 +17,7 @@
 #include 
 #include 
 #include "cadence_master.h"
+#include "bus.h"
 #include "intel.h"
 
 /* Intel SHIM Registers Definition */
@@ -98,6 +100,7 @@ struct sdw_intel {
struct sdw_cdns cdns;
int instance;
struct sdw_intel_link_res *res;
+   struct dentry *fs;
 };
 
 #define cdns_to_intel(_cdns) container_of(_cdns, struct sdw_intel, cdns)
@@ -161,6 +164,115 @@ static int intel_set_bit(void __iomem *base, int offset, 
u32 value, u32 mask)
return -EAGAIN;
 }
 
+/*
+ * debugfs
+ */
+
+#define RD_BUF (2 * PAGE_SIZE)
+
+static ssize_t intel_sprintf(void __iomem *mem, bool l,
+char *buf, size_t pos, unsigned int reg)
+{
+   int value;
+
+   if (l)
+   value = intel_readl(mem, reg);
+   else
+   value = intel_readw(mem, reg);
+
+   return scnprintf(buf + pos, RD_BUF - pos, "%4x\t%4x\n", reg, value);
+}
+
+static ssize_t intel_reg_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+   struct sdw_intel *sdw = file->private_data;
+   void __iomem *s = sdw->res->shim;
+   void __iomem *a = sdw->res->alh;
+   char *buf;
+   ssize_t ret;
+   int i, j;
+   unsigned int links, reg;
+
+   buf = kzalloc(RD_BUF, GFP_KERNEL);
+   if (!buf)
+   return -ENOMEM;
+
+   links = intel_readl(s, SDW_SHIM_LCAP) & GENMASK(2, 0);
+
+   ret = scnprintf(buf, RD_BUF, "Register  Value\n");
+   ret += scnprintf(buf + ret, RD_BUF - ret, "\nShim\n");
+
+   for (i = 0; i < 4; i++) {
+   reg = SDW_SHIM_LCAP + i * 4;
+   ret += intel_sprintf(s, true, buf, ret, reg);
+   }
+
+   for (i = 0; i < links; i++) {
+   ret += scnprintf(buf + ret, RD_BUF - ret, "\nLink%d\n", i);
+   ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_CTLSCAP(i));
+   ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_CTLS0CM(i));
+   ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_CTLS1CM(i));
+   ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_CTLS2CM(i));
+   ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_CTLS3CM(i));
+   ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_PCMSCAP(i));
+
+   for (j = 0; j < 8; j++) {
+   ret += intel_sprintf(s, false, buf, ret,
+   SDW_SHIM_PCMSYCHM(i, j));
+   ret += intel_sprintf(s, false, buf, ret,
+   SDW_SHIM_PCMSYCHC(i, j));
+   }
+
+   ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_PDMSCAP(i));
+   ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_IOCTL(i));
+   ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_CTMCTL(i));
+   }
+
+   ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_WAKEEN);
+   ret += intel_sprintf(s, false, buf, ret, SDW_SHIM_WAKESTS);
+
+   ret += scnprintf(buf + ret, RD_BUF - ret, "\nALH\n");
+   for (i = 0; i < 8; i++)
+   ret += intel_sprintf(a, true, buf, ret, SDW_ALH_STRMZCFG(i));
+
+   ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+   kfree(buf);
+
+   return ret;
+}
+
+static const struct file_operations intel_reg_fops = {
+   .open = simple_open,
+   .read = intel_reg_read,
+   .llseek = default_llseek,
+};
+
+static void intel_debugfs_init(struct sdw_intel *sdw)
+{
+   struct dentry *root = sdw->cdns.bus.debugfs;
+
+   if (!root)
+   return;
+
+   sdw->fs = debugfs_create_dir("intel-sdw", root);
+   if (IS_ERR_OR_NULL(sdw->fs)) {
+   dev_err(sdw->cdns.dev, "debugfs root creation failed\n");
+   sdw->fs = NULL;
+   return;
+   }
+
+   debugfs_create_file("intel-registers", 0400, sdw->fs, sdw,
+   _reg_fops);
+
+   sdw_cdns_debugfs_init(>cdns, sdw->fs);
+}
+
+static void intel_debugfs_exit(struct sdw_intel *sdw)
+{
+   debugfs_remove_recursive(sdw->fs);
+}
+
 /*
  * shim ops
  */
@@ -896,6 +

[RFC PATCH 14/40] soundwire: cadence_master: fix definitions for INTSTAT0/1

2019-07-25 Thread Pierre-Louis Bossart
Two off-by-one errors: INTSTAT0 missed BIT(31) and INTSTAT1 is only
defined on first 16 bits.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/cadence_master.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soundwire/cadence_master.c 
b/drivers/soundwire/cadence_master.c
index d9d9e3d964dd..889fa2cd49ae 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -100,8 +100,8 @@
 #define CDNS_MCP_SLAVE_INTMASK00x5C
 #define CDNS_MCP_SLAVE_INTMASK10x60
 
-#define CDNS_MCP_SLAVE_INTMASK0_MASK   GENMASK(30, 0)
-#define CDNS_MCP_SLAVE_INTMASK1_MASK   GENMASK(16, 0)
+#define CDNS_MCP_SLAVE_INTMASK0_MASK   GENMASK(31, 0)
+#define CDNS_MCP_SLAVE_INTMASK1_MASK   GENMASK(15, 0)
 
 #define CDNS_MCP_PORT_INTSTAT  0x64
 #define CDNS_MCP_PDI_STAT  0x6C
-- 
2.20.1



[RFC PATCH 05/40] soundwire: intel: move interrupt enable after interrupt handler registration

2019-07-25 Thread Pierre-Louis Bossart
Not sure why the existing code would enable interrupts without the
ability to deal with them.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/soundwire/intel.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index aeadc341c0a3..68832e613b1e 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -981,8 +981,6 @@ static int intel_probe(struct platform_device *pdev)
if (ret)
goto err_init;
 
-   ret = sdw_cdns_enable_interrupt(>cdns);
-
/* Read the PDI config and initialize cadence PDI */
intel_pdi_init(sdw, );
ret = sdw_cdns_pdi_init(>cdns, config);
@@ -1000,6 +998,8 @@ static int intel_probe(struct platform_device *pdev)
goto err_init;
}
 
+   ret = sdw_cdns_enable_interrupt(>cdns);
+
/* Register DAIs */
ret = intel_register_dai(sdw);
if (ret) {
-- 
2.20.1



Re: [PATCH] ASoC: Intel: Fix some acpi vs apci typo in somme comments

2019-07-25 Thread Pierre-Louis Bossart

On 7/25/19 12:35 AM, Christophe JAILLET wrote:

Fix some typo to have the filaname given in a comment match the real name
of the file.
Some 'acpi' have erroneously been written 'apci'

Signed-off-by: Christophe JAILLET 


yes, thanks for the corrections.

Acked-by: Pierre-Louis Bossart 


---
  sound/soc/intel/common/soc-acpi-intel-bxt-match.c | 2 +-
  sound/soc/intel/common/soc-acpi-intel-byt-match.c | 2 +-
  sound/soc/intel/common/soc-acpi-intel-cht-match.c | 2 +-
  sound/soc/intel/common/soc-acpi-intel-cnl-match.c | 2 +-
  sound/soc/intel/common/soc-acpi-intel-glk-match.c | 2 +-
  sound/soc/intel/common/soc-acpi-intel-hda-match.c | 2 +-
  sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c | 2 +-
  sound/soc/intel/common/soc-acpi-intel-icl-match.c | 2 +-
  sound/soc/intel/common/soc-acpi-intel-kbl-match.c | 2 +-
  sound/soc/intel/common/soc-acpi-intel-skl-match.c | 2 +-
  10 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c 
b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
index 229e39586868..4a5adae1d785 100644
--- a/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-bxt-match.c
@@ -1,6 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0
  /*
- * soc-apci-intel-bxt-match.c - tables and support for BXT ACPI enumeration.
+ * soc-acpi-intel-bxt-match.c - tables and support for BXT ACPI enumeration.
   *
   * Copyright (c) 2018, Intel Corporation.
   *
diff --git a/sound/soc/intel/common/soc-acpi-intel-byt-match.c 
b/sound/soc/intel/common/soc-acpi-intel-byt-match.c
index b94b482ac34f..1cc801ba92eb 100644
--- a/sound/soc/intel/common/soc-acpi-intel-byt-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-byt-match.c
@@ -1,6 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
  /*
- * soc-apci-intel-byt-match.c - tables and support for BYT ACPI enumeration.
+ * soc-acpi-intel-byt-match.c - tables and support for BYT ACPI enumeration.
   *
   * Copyright (c) 2017, Intel Corporation.
   */
diff --git a/sound/soc/intel/common/soc-acpi-intel-cht-match.c 
b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
index b7f11f6be1cf..d0fb43c2b9f6 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cht-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cht-match.c
@@ -1,6 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
  /*
- * soc-apci-intel-cht-match.c - tables and support for CHT ACPI enumeration.
+ * soc-acpi-intel-cht-match.c - tables and support for CHT ACPI enumeration.
   *
   * Copyright (c) 2017, Intel Corporation.
   */
diff --git a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c 
b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
index c36c0aa4f683..771b0ef21051 100644
--- a/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-cnl-match.c
@@ -1,6 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0
  /*
- * soc-apci-intel-cnl-match.c - tables and support for CNL ACPI enumeration.
+ * soc-acpi-intel-cnl-match.c - tables and support for CNL ACPI enumeration.
   *
   * Copyright (c) 2018, Intel Corporation.
   *
diff --git a/sound/soc/intel/common/soc-acpi-intel-glk-match.c 
b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
index 616eb09e78a0..60dea358fa04 100644
--- a/sound/soc/intel/common/soc-acpi-intel-glk-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-glk-match.c
@@ -1,6 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0
  /*
- * soc-apci-intel-glk-match.c - tables and support for GLK ACPI enumeration.
+ * soc-acpi-intel-glk-match.c - tables and support for GLK ACPI enumeration.
   *
   * Copyright (c) 2018, Intel Corporation.
   *
diff --git a/sound/soc/intel/common/soc-acpi-intel-hda-match.c 
b/sound/soc/intel/common/soc-acpi-intel-hda-match.c
index 68ae43f7b4b2..cc972d2ac691 100644
--- a/sound/soc/intel/common/soc-acpi-intel-hda-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-hda-match.c
@@ -2,7 +2,7 @@
  // Copyright (c) 2018, Intel Corporation.
  
  /*

- * soc-apci-intel-hda-match.c - tables and support for HDA+ACPI enumeration.
+ * soc-acpi-intel-hda-match.c - tables and support for HDA+ACPI enumeration.
   *
   */
  
diff --git a/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c b/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c

index d27853e7a369..34eb0baaa951 100644
--- a/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-hsw-bdw-match.c
@@ -1,6 +1,6 @@
  // SPDX-License-Identifier: GPL-2.0-only
  /*
- * soc-apci-intel-hsw-bdw-match.c - tables and support for ACPI enumeration.
+ * soc-acpi-intel-hsw-bdw-match.c - tables and support for ACPI enumeration.
   *
   * Copyright (c) 2017, Intel Corporation.
   */
diff --git a/sound/soc/intel/common/soc-acpi-intel-icl-match.c 
b/sound/soc/intel/common/soc-acpi-intel-icl-match.c
index 0b430b9b3673..38977669b576 100644
--- a/sound/soc/intel/common/soc-acpi-intel-icl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel

Re: [Sound-open-firmware] [PATCH v2 1/5] ASoC: SOF: imx: Add i.MX8 HW support

2019-07-23 Thread Pierre-Louis Bossart




diff --git a/sound/soc/sof/imx/Makefile b/sound/soc/sof/imx/Makefile
new file mode 100644
index ..c69237971da5
--- /dev/null
+++ b/sound/soc/sof/imx/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+
+ccflags-y += -DDEBUG


this should be removed or in a separate patch.



+struct imx8_priv {
+   struct device *dev;
+   struct snd_sof_dev *sdev;
+   struct imx_dsp_ipc *dsp_ipc;
+   struct imx_sc_ipc *sc_ipc;


maybe a comment to explain what 'sc' stands for?


+};
+
+static void imx8_get_windows(struct snd_sof_dev *sdev)
+{
+   struct sof_ipc_window_elem *elem;
+   u32 outbox_offset = 0;
+   u32 stream_offset = 0;
+   u32 inbox_offset = 0;
+   u32 outbox_size = 0;
+   u32 stream_size = 0;
+   u32 inbox_size = 0;
+   int i;
+
+   if (!sdev->info_window) {
+   dev_err(sdev->dev, "error: have no window info\n");
+   return;
+   }
+
+   for (i = 0; i < sdev->info_window->num_windows; i++) {
+   elem = >info_window->window[i];
+
+   switch (elem->type) {
+   case SOF_IPC_REGION_UPBOX:
+   inbox_offset = elem->offset + MBOX_OFFSET;
+   inbox_size = elem->size;
+   snd_sof_debugfs_io_item(sdev,
+   sdev->bar[SOF_FW_BLK_TYPE_SRAM]
+   + inbox_offset,
+   elem->size, "inbox",
+   SOF_DEBUGFS_ACCESS_D0_ONLY);
+   break;
+   case SOF_IPC_REGION_DOWNBOX:
+   outbox_offset = elem->offset + MBOX_OFFSET;
+   outbox_size = elem->size;
+   snd_sof_debugfs_io_item(sdev,
+   sdev->bar[SOF_FW_BLK_TYPE_SRAM]
+   + outbox_offset,
+   elem->size, "outbox",
+   SOF_DEBUGFS_ACCESS_D0_ONLY);
+   break;
+   case SOF_IPC_REGION_TRACE:
+   snd_sof_debugfs_io_item(sdev,
+   sdev->bar[SOF_FW_BLK_TYPE_SRAM]
+   + elem->offset + MBOX_OFFSET,
+   elem->size, "etrace",
+   SOF_DEBUGFS_ACCESS_D0_ONLY);
+   break;
+   case SOF_IPC_REGION_DEBUG:
+   snd_sof_debugfs_io_item(sdev,
+   sdev->bar[SOF_FW_BLK_TYPE_SRAM]
+   + elem->offset + MBOX_OFFSET,
+   elem->size, "debug",
+   SOF_DEBUGFS_ACCESS_D0_ONLY);
+   break;
+   case SOF_IPC_REGION_STREAM:
+   stream_offset = elem->offset + MBOX_OFFSET;
+   stream_size = elem->size;
+   snd_sof_debugfs_io_item(sdev,
+   sdev->bar[SOF_FW_BLK_TYPE_SRAM]
+   + stream_offset,
+   elem->size, "stream",
+   SOF_DEBUGFS_ACCESS_D0_ONLY);
+   break;
+   case SOF_IPC_REGION_REGS:
+   snd_sof_debugfs_io_item(sdev,
+   sdev->bar[SOF_FW_BLK_TYPE_SRAM]
+   + elem->offset + MBOX_OFFSET,
+   elem->size, "regs",
+   SOF_DEBUGFS_ACCESS_D0_ONLY);
+   break;
+   case SOF_IPC_REGION_EXCEPTION:
+   sdev->dsp_oops_offset = elem->offset + MBOX_OFFSET;
+   snd_sof_debugfs_io_item(sdev,
+   sdev->bar[SOF_FW_BLK_TYPE_SRAM]
+   + elem->offset + MBOX_OFFSET,
+   elem->size, "exception",
+   SOF_DEBUGFS_ACCESS_D0_ONLY);
+   break;
+   default:
+   dev_err(sdev->dev, "error: get illegal window info\n");
+   return;
+   }
+   }
+
+   if (outbox_size == 0 || inbox_size == 0) {
+   dev_err(sdev->dev, "error: get illegal mailbox window\n");
+   return;
+   }
+
+   snd_sof_dsp_mailbox_init(sdev, inbox_offset, inbox_size,
+outbox_offset, outbox_size);

Re: [Sound-open-firmware] [PATCH v2 3/5] ASoC: SOF: Add DT DSP device support

2019-07-23 Thread Pierre-Louis Bossart




diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig
index 61b97fc55bb2..2aa3a1cdf60c 100644
--- a/sound/soc/sof/Kconfig
+++ b/sound/soc/sof/Kconfig
@@ -36,6 +36,15 @@ config SND_SOC_SOF_ACPI
  Say Y if you need this option
  If unsure select "N".
  
+config SND_SOC_SOF_DT

+   tristate "SOF DT enumeration support"
+   select SND_SOC_SOF
+   select SND_SOC_SOF_OPTIONS
+   help
+ This adds support for Device Tree enumeration. This option is
+ required to enable i.MX8 devices.
+ Say Y if you need this option. If unsure select "N".
+


[snip]


diff --git a/sound/soc/sof/imx/Kconfig b/sound/soc/sof/imx/Kconfig
index fff64a9970f0..fa35994a79c4 100644
--- a/sound/soc/sof/imx/Kconfig
+++ b/sound/soc/sof/imx/Kconfig
@@ -12,6 +12,7 @@ if SND_SOC_SOF_IMX_TOPLEVEL
  
  config SND_SOC_SOF_IMX8

tristate "SOF support for i.MX8"
+   select SND_SOC_SOF_DT


This looks upside down. You should select SOF_DT first then include the 
NXP stuff.



help
This adds support for Sound Open Firmware for NXP i.MX8 platforms
Say Y if you have such a device.
diff --git a/sound/soc/sof/sof-dt-dev.c b/sound/soc/sof/sof-dt-dev.c
new file mode 100644
index ..31429bbb5c7e
--- /dev/null
+++ b/sound/soc/sof/sof-dt-dev.c
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+//
+// Copyright 2019 NXP
+//
+// Author: Daniel Baluta 
+//
+
+#include 
+#include 
+#include 
+#include 
+
+#include "ops.h"
+
+extern struct snd_sof_dsp_ops sof_imx8_ops;
+
+static char *fw_path;
+module_param(fw_path, charp, 0444);
+MODULE_PARM_DESC(fw_path, "alternate path for SOF firmware.");
+
+static char *tplg_path;
+module_param(tplg_path, charp, 0444);
+MODULE_PARM_DESC(tplg_path, "alternate path for SOF topology.");
+
+/* platform specific devices */
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_IMX8)
+static struct sof_dev_desc sof_dt_imx8qxp_desc = {
+   .default_fw_path = "imx/sof",
+   .default_tplg_path = "imx/sof-tplg",
+   .nocodec_fw_filename = "sof-imx8.ri",
+   .nocodec_tplg_filename = "sof-imx8-nocodec.tplg",
+   .ops = _imx8_ops,
+};
+#endif
+
+static const struct dev_pm_ops sof_dt_pm = {
+   SET_SYSTEM_SLEEP_PM_OPS(snd_sof_suspend, snd_sof_resume)
+   SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume,
+  NULL)
+};
+
+static void sof_dt_probe_complete(struct device *dev)
+{
+   /* allow runtime_pm */
+   pm_runtime_set_autosuspend_delay(dev, SND_SOF_SUSPEND_DELAY_MS);
+   pm_runtime_use_autosuspend(dev);
+   pm_runtime_enable(dev);
+}
+
+static int sof_dt_probe(struct platform_device *pdev)
+{
+   struct device *dev = >dev;
+   const struct sof_dev_desc *desc;
+   /*TODO: create a generic snd_soc_xxx_mach */
+   struct snd_soc_acpi_mach *mach;


I wonder if you really need to use the same structures. For Intel we get 
absolutely zero info from the firmware so rely on an ACPI codec ID as a 
key to find information on which firmware and topology to use, and which 
machine driver to load. You could have all this information in a DT blob?



+   struct snd_sof_pdata *sof_pdata;
+   const struct snd_sof_dsp_ops *ops;
+   int ret;
+
+   dev_info(>dev, "DT DSP detected");
+
+   sof_pdata = devm_kzalloc(dev, sizeof(*sof_pdata), GFP_KERNEL);
+   if (!sof_pdata)
+   return -ENOMEM;
+
+   desc = device_get_match_data(dev);
+   if (!desc)
+   return -ENODEV;
+
+   /* get ops for platform */
+   ops = desc->ops;
+   if (!ops) {
+   dev_err(dev, "error: no matching DT descriptor ops\n");
+   return -ENODEV;
+   }
+
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE)
+   /* force nocodec mode */
+   dev_warn(dev, "Force to use nocodec mode\n");
+   mach = devm_kzalloc(dev, sizeof(*mach), GFP_KERNEL);
+   if (!mach)
+   return -ENOMEM;
+   ret = sof_nocodec_setup(dev, sof_pdata, mach, desc, ops);
+   if (ret < 0)
+   return ret;
+#else
+   /* TODO: implement case where we actually have a codec */
+   return -ENODEV;
+#endif
+
+   if (mach)
+   mach->mach_params.platform = dev_name(dev);
+
+   sof_pdata->machine = mach;
+   sof_pdata->desc = desc;
+   sof_pdata->dev = >dev;
+   sof_pdata->platform = dev_name(dev);
+
+   /* alternate fw and tplg filenames */
+   if (fw_path)
+   sof_pdata->fw_filename_prefix = fw_path;
+   else
+   sof_pdata->fw_filename_prefix =
+   sof_pdata->desc->default_fw_path;
+   if (tplg_path)
+   sof_pdata->tplg_filename_prefix = tplg_path;
+   else
+   sof_pdata->tplg_filename_prefix =
+   sof_pdata->desc->default_tplg_path;
+
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)
+   /* set callback to enable 

Re: [alsa-devel] [PATCH] ASoC: SOF: use __u32 instead of uint32_t in uapi headers

2019-07-22 Thread Pierre-Louis Bossart




On 7/22/19 8:39 AM, Arnd Bergmann wrote:

On Sun, Jul 21, 2019 at 4:25 PM Masahiro Yamada
 wrote:


  struct snd_sof_blk_hdr {
 enum snd_sof_fw_blk_type type;
-   uint32_t size;  /* bytes minus this header */
-   uint32_t offset;/* offset from base */
+   __u32 size; /* bytes minus this header */
+   __u32 offset;   /* offset from base */
  } __packed;



On a related note: Using an 'enum' in an ABI structure is not portable
across architectures. This is probably fine in a UAPI as long as user
and kernel space agree on the size of an enum, but if the same
structure is used to talk to the firmware, it won't work on architectures
that have a different size for the first field.


yes, we've removed all enums in SOF and missed this one. This should be 
changed, thanks for the note.


Re: [alsa-devel] [PATCH] ASoC: SOF: use __u32 instead of uint32_t in uapi headers

2019-07-22 Thread Pierre-Louis Bossart




On 7/22/19 8:34 AM, Arnd Bergmann wrote:

On Mon, Jul 22, 2019 at 3:16 PM Pierre-Louis Bossart
 wrote:

On 7/22/19 7:56 AM, Takashi Iwai wrote:

On Mon, 22 Jul 2019 14:49:34 +0200,
Pierre-Louis Bossart wrote:




On 7/21/19 9:23 AM, Masahiro Yamada wrote:

When CONFIG_UAPI_HEADER_TEST=y, exported headers are compile-tested to
make sure they can be included from user-space.

Currently, header.h and fw.h are excluded from the test coverage.
To make them join the compile-test, we need to fix the build errors
attached below.

For a case like this, we decided to use __u{8,16,32,64} variable types
in this discussion:

 https://lkml.org/lkml/2019/6/5/18


these files are shared with the SOF project and used as is (with minor
formatting) for the firmware compilation. I am not sure I understand
the ask here, are you really asking SOF to use linux-specific type
definitions?


Actually this is linux-kernel UAPI header files, so yes, we should
follow the convention there as much as possible.

So far we haven't been strict about these types.  But now we have a
unit test for checking it, so it's a good opportunity to address the
issues.


Maybe a bit of background. For SOF we split the includes in 4 directories

https://github.com/thesofproject/sof/tree/master/src/include

- sof: internal includes for firmware only
- ipc: definitions of the structures for information exchanged over the
IPC channel. This directory is used as is by the Linux kernel and
mirrored in include/sound/sof
- user: definitions needed for firmware tools, e.g. to generate the
image or parse the trace. this directory is not used by the Linux kernel.
- kernel: definitions for the firmware format, needed for the loader to
parse the firmware files. This is not directly used by applications
running on the target, it really defines the content passed to the
kernel with request_firmware. This directory is mirrored in the Linux
include/uapi/sound/sof directory.

Our goal is to minimize the differences and allow deltas e.g. for
license or comments. We could add a definition for __u32 when linux is
not used, I am just not sure if these two files really fall in the UAPI
category and if the checks make sense.


If you can build all the SOF user space without these headers being
installed to /usr/include/sound/sof/, you can move them from
include/uapi/sound/sof to include/sounds/sof and leave the types
unchanged.


yes we don't need those files to build userspace stuff. The idea was 
that these format definitions establish a contract between userspace 
(more specifically the files stored in /lib/firmware) and the kernel. 
IIRC we wanted to make sure that any changes would be tracked as 
breaking userspace. If the consensus is that the uapi directory is 
strictly used for builds then we should indeed move those files


Re: [alsa-devel] [PATCH] ASoC: SOF: use __u32 instead of uint32_t in uapi headers

2019-07-22 Thread Pierre-Louis Bossart




On 7/22/19 7:56 AM, Takashi Iwai wrote:

On Mon, 22 Jul 2019 14:49:34 +0200,
Pierre-Louis Bossart wrote:




On 7/21/19 9:23 AM, Masahiro Yamada wrote:

When CONFIG_UAPI_HEADER_TEST=y, exported headers are compile-tested to
make sure they can be included from user-space.

Currently, header.h and fw.h are excluded from the test coverage.
To make them join the compile-test, we need to fix the build errors
attached below.

For a case like this, we decided to use __u{8,16,32,64} variable types
in this discussion:

https://lkml.org/lkml/2019/6/5/18


these files are shared with the SOF project and used as is (with minor
formatting) for the firmware compilation. I am not sure I understand
the ask here, are you really asking SOF to use linux-specific type
definitions?


Actually this is linux-kernel UAPI header files, so yes, we should
follow the convention there as much as possible.

So far we haven't been strict about these types.  But now we have a
unit test for checking it, so it's a good opportunity to address the
issues.


Maybe a bit of background. For SOF we split the includes in 4 directories

https://github.com/thesofproject/sof/tree/master/src/include

- sof: internal includes for firmware only
- ipc: definitions of the structures for information exchanged over the 
IPC channel. This directory is used as is by the Linux kernel and 
mirrored in include/sound/sof
- user: definitions needed for firmware tools, e.g. to generate the 
image or parse the trace. this directory is not used by the Linux kernel.
- kernel: definitions for the firmware format, needed for the loader to 
parse the firmware files. This is not directly used by applications 
running on the target, it really defines the content passed to the 
kernel with request_firmware. This directory is mirrored in the Linux 
include/uapi/sound/sof directory.


Our goal is to minimize the differences and allow deltas e.g. for 
license or comments. We could add a definition for __u32 when linux is 
not used, I am just not sure if these two files really fall in the UAPI 
category and if the checks make sense.


Re: [alsa-devel] [PATCH] ASoC: SOF: use __u32 instead of uint32_t in uapi headers

2019-07-22 Thread Pierre-Louis Bossart




On 7/21/19 9:23 AM, Masahiro Yamada wrote:

When CONFIG_UAPI_HEADER_TEST=y, exported headers are compile-tested to
make sure they can be included from user-space.

Currently, header.h and fw.h are excluded from the test coverage.
To make them join the compile-test, we need to fix the build errors
attached below.

For a case like this, we decided to use __u{8,16,32,64} variable types
in this discussion:

   https://lkml.org/lkml/2019/6/5/18


these files are shared with the SOF project and used as is (with minor 
formatting) for the firmware compilation. I am not sure I understand the 
ask here, are you really asking SOF to use linux-specific type definitions?




Build log:

   CC  usr/include/sound/sof/header.h.s
   CC  usr/include/sound/sof/fw.h.s
In file included from :32:0:
./usr/include/sound/sof/header.h:19:2: error: unknown type name ‘uint32_t’
   uint32_t magic;  /**< 'S', 'O', 'F', '\0' */
   ^~~~
./usr/include/sound/sof/header.h:20:2: error: unknown type name ‘uint32_t’
   uint32_t type;  /**< component specific type */
   ^~~~
./usr/include/sound/sof/header.h:21:2: error: unknown type name ‘uint32_t’
   uint32_t size;  /**< size in bytes of data excl. this struct */
   ^~~~
./usr/include/sound/sof/header.h:22:2: error: unknown type name ‘uint32_t’
   uint32_t abi;  /**< SOF ABI version */
   ^~~~
./usr/include/sound/sof/header.h:23:2: error: unknown type name ‘uint32_t’
   uint32_t reserved[4]; /**< reserved for future use */
   ^~~~
./usr/include/sound/sof/header.h:24:2: error: unknown type name ‘uint32_t’
   uint32_t data[0]; /**< Component data - opaque to core */
   ^~~~
In file included from :32:0:
./usr/include/sound/sof/fw.h:49:2: error: unknown type name ‘uint32_t’
   uint32_t size;  /* bytes minus this header */
   ^~~~
./usr/include/sound/sof/fw.h:50:2: error: unknown type name ‘uint32_t’
   uint32_t offset; /* offset from base */
   ^~~~
./usr/include/sound/sof/fw.h:64:2: error: unknown type name ‘uint32_t’
   uint32_t size;  /* bytes minus this header */
   ^~~~
./usr/include/sound/sof/fw.h:65:2: error: unknown type name ‘uint32_t’
   uint32_t num_blocks; /* number of blocks */
   ^~~~
./usr/include/sound/sof/fw.h:73:2: error: unknown type name ‘uint32_t’
   uint32_t file_size; /* size of file minus this header */
   ^~~~
./usr/include/sound/sof/fw.h:74:2: error: unknown type name ‘uint32_t’
   uint32_t num_modules; /* number of modules */
   ^~~~
./usr/include/sound/sof/fw.h:75:2: error: unknown type name ‘uint32_t’
   uint32_t abi;  /* version of header format */
   ^~~~

Signed-off-by: Masahiro Yamada 
---

  include/uapi/sound/sof/fw.h | 16 +---
  include/uapi/sound/sof/header.h | 14 --
  2 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/include/uapi/sound/sof/fw.h b/include/uapi/sound/sof/fw.h
index 1afca973eb09..e9f697467a86 100644
--- a/include/uapi/sound/sof/fw.h
+++ b/include/uapi/sound/sof/fw.h
@@ -13,6 +13,8 @@
  #ifndef __INCLUDE_UAPI_SOF_FW_H__
  #define __INCLUDE_UAPI_SOF_FW_H__
  
+#include 

+
  #define SND_SOF_FW_SIG_SIZE   4
  #define SND_SOF_FW_ABI1
  #define SND_SOF_FW_SIG"Reef"
@@ -46,8 +48,8 @@ enum snd_sof_fw_blk_type {
  
  struct snd_sof_blk_hdr {

enum snd_sof_fw_blk_type type;
-   uint32_t size;  /* bytes minus this header */
-   uint32_t offset;/* offset from base */
+   __u32 size; /* bytes minus this header */
+   __u32 offset;   /* offset from base */
  } __packed;
  
  /*

@@ -61,8 +63,8 @@ enum snd_sof_fw_mod_type {
  
  struct snd_sof_mod_hdr {

enum snd_sof_fw_mod_type type;
-   uint32_t size;  /* bytes minus this header */
-   uint32_t num_blocks;/* number of blocks */
+   __u32 size; /* bytes minus this header */
+   __u32 num_blocks;   /* number of blocks */
  } __packed;
  
  /*

@@ -70,9 +72,9 @@ struct snd_sof_mod_hdr {
   */
  struct snd_sof_fw_header {
unsigned char sig[SND_SOF_FW_SIG_SIZE]; /* "Reef" */
-   uint32_t file_size; /* size of file minus this header */
-   uint32_t num_modules;   /* number of modules */
-   uint32_t abi;   /* version of header format */
+   __u32 file_size;/* size of file minus this header */
+   __u32 num_modules;  /* number of modules */
+   __u32 abi;  /* version of header format */
  } __packed;
  
  #endif

diff --git a/include/uapi/sound/sof/header.h b/include/uapi/sound/sof/header.h
index 7868990b0d6f..5f4518e7a972 100644
--- a/include/uapi/sound/sof/header.h
+++ b/include/uapi/sound/sof/header.h
@@ -9,6 +9,8 @@
  #ifndef __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__
  #define __INCLUDE_UAPI_SOUND_SOF_USER_HEADER_H__
  
+#include 

+
  /*
   * Header for all non IPC ABI data.
   *
@@ -16,12 +18,12 @@
   * Used by any bespoke component data structures or binary blobs.
   */
  struct sof_abi_hdr {
- 

[PATCH] soundwire: fix regmap dependencies and align with other serial links

2019-07-18 Thread Pierre-Louis Bossart
The existing code has a mixed select/depend usage which makes no sense.

config SOUNDWIRE_BUS
   tristate
   select REGMAP_SOUNDWIRE

config REGMAP_SOUNDWIRE
tristate
depends on SOUNDWIRE_BUS

Let's remove one layer of Kconfig definitions and align with the
solutions used by all other serial links.

Signed-off-by: Pierre-Louis Bossart 
---
 drivers/base/regmap/Kconfig | 2 +-
 drivers/soundwire/Kconfig   | 7 +--
 drivers/soundwire/Makefile  | 2 +-
 3 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
index 6ad5ef48b61e..8cd2ac650b50 100644
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -44,7 +44,7 @@ config REGMAP_IRQ
 
 config REGMAP_SOUNDWIRE
tristate
-   depends on SOUNDWIRE_BUS
+   depends on SOUNDWIRE
 
 config REGMAP_SCCB
tristate
diff --git a/drivers/soundwire/Kconfig b/drivers/soundwire/Kconfig
index 3a01cfd70fdc..f518273cfbe3 100644
--- a/drivers/soundwire/Kconfig
+++ b/drivers/soundwire/Kconfig
@@ -4,7 +4,7 @@
 #
 
 menuconfig SOUNDWIRE
-   bool "SoundWire support"
+   tristate "SoundWire support"
help
  SoundWire is a 2-Pin interface with data and clock line ratified
  by the MIPI Alliance. SoundWire is used for transporting data
@@ -17,17 +17,12 @@ if SOUNDWIRE
 
 comment "SoundWire Devices"
 
-config SOUNDWIRE_BUS
-   tristate
-   select REGMAP_SOUNDWIRE
-
 config SOUNDWIRE_CADENCE
tristate
 
 config SOUNDWIRE_INTEL
tristate "Intel SoundWire Master driver"
select SOUNDWIRE_CADENCE
-   select SOUNDWIRE_BUS
depends on X86 && ACPI && SND_SOC
help
  SoundWire Intel Master driver.
diff --git a/drivers/soundwire/Makefile b/drivers/soundwire/Makefile
index fd99a831b92a..45b7e5001653 100644
--- a/drivers/soundwire/Makefile
+++ b/drivers/soundwire/Makefile
@@ -5,7 +5,7 @@
 
 #Bus Objs
 soundwire-bus-objs := bus_type.o bus.o slave.o mipi_disco.o stream.o
-obj-$(CONFIG_SOUNDWIRE_BUS) += soundwire-bus.o
+obj-$(CONFIG_SOUNDWIRE) += soundwire-bus.o
 
 #Cadence Objs
 soundwire-cadence-objs := cadence_master.o
-- 
2.20.1



Re: [alsa-devel] [PATCH] ASoC: Intel: Atom: read timestamp moved to period_elapsed

2019-07-17 Thread Pierre-Louis Bossart




On 7/10/19 6:15 PM, Curtis Malainey wrote:

On Tue, Jul 9, 2019 at 4:45 AM Andy Shevchenko
 wrote:


On Mon, Jul 08, 2019 at 09:01:47PM -0700, Alex Levin wrote:

sst_platform_pcm_pointer is called from both snd_pcm_period_elapsed and
from snd_pcm_ioctl. Calling read timestamp results in recalculating
pcm_delay and buffer_ptr (sst_calc_tstamp) which consumes buffers in a
faster rate than intended.
In a tested BSW system with chtrt5650, for a rate of 48000, the
measured rate was sometimes 10 times more than that.
After moving the timestamp read to period elapsed, buffer consumption is
as expected.


 From code prospective it looks good. You may take mine
Reviewed-by: Andy Shevchenko 

Though I'm not an expert in the area, Pierre and / or Liam should give
their blessing.


Agreed, Liam or Pierre should also give their ok since this is one of
the closed source firmware drivers.

Reviewed-by: Curtis Malainey 


Humm, this first review after my Summer break isn't straightforward.

By moving the timestamp update to the period elapsed event, don't you 
prevent the use of this driver in no-interrupt mode - which I understood 
as the baseline for Chrome?


And I also don't get how this timestamp might lead to 10x speed issues, 
this driver has been around for a number of years and that specific 
error was never seen. What is different in this platform and can this be 
seen e.g. on a Cyan device?





Signed-off-by: Alex Levin 
---
  sound/soc/intel/atom/sst-mfld-platform-pcm.c | 23 +---
  1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c 
b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
index 0e8b1c5eec88..196af0b30b41 100644
--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
@@ -265,16 +265,28 @@ static void sst_period_elapsed(void *arg)
  {
   struct snd_pcm_substream *substream = arg;
   struct sst_runtime_stream *stream;
- int status;
+ struct snd_soc_pcm_runtime *rtd;
+ int status, ret_val;

   if (!substream || !substream->runtime)
   return;
   stream = substream->runtime->private_data;
   if (!stream)
   return;
+
+ rtd = substream->private_data;
+ if (!rtd)
+ return;
+
   status = sst_get_stream_status(stream);
   if (status != SST_PLATFORM_RUNNING)
   return;
+
+ ret_val = stream->ops->stream_read_tstamp(sst->dev, >stream_info);
+ if (ret_val) {
+ dev_err(rtd->dev, "stream_read_tstamp err code = %d\n", ret_val);
+ return;
+ }
   snd_pcm_period_elapsed(substream);
  }

@@ -658,20 +670,15 @@ static snd_pcm_uframes_t sst_platform_pcm_pointer
   (struct snd_pcm_substream *substream)
  {
   struct sst_runtime_stream *stream;
- int ret_val, status;
+ int status;
   struct pcm_stream_info *str_info;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;

   stream = substream->runtime->private_data;
   status = sst_get_stream_status(stream);
   if (status == SST_PLATFORM_INIT)
   return 0;
+
   str_info = >stream_info;
- ret_val = stream->ops->stream_read_tstamp(sst->dev, str_info);
- if (ret_val) {
- dev_err(rtd->dev, "sst: error code = %d\n", ret_val);
- return ret_val;
- }
   substream->runtime->delay = str_info->pcm_delay;
   return str_info->buffer_ptr;
  }
--
2.22.0.410.gd8fdbe21b5-goog



--
With Best Regards,
Andy Shevchenko



___
Alsa-devel mailing list
alsa-de...@alsa-project.org
https://mailman.alsa-project.org/mailman/listinfo/alsa-devel



Re: [alsa-devel] [PATCH 1/2] ASoC: soc-core: defer card registration if codec component is missing

2019-06-26 Thread Pierre-Louis Bossart

On 6/26/19 3:36 PM, Jerome Brunet wrote:

Like cpus and platforms, defer sound card initialization if the codec
component is missing when initializing the dai_link

Signed-off-by: Jerome Brunet 
---
  sound/soc/soc-core.c | 8 
  1 file changed, 8 insertions(+)

diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 358f1fbf9a30..002ddbf4e5a3 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1064,12 +1064,20 @@ static int soc_init_dai_link(struct snd_soc_card *card,
link->name);
return -EINVAL;
}
+
/* Codec DAI name must be specified */
if (!codec->dai_name) {
dev_err(card->dev, "ASoC: codec_dai_name not set for 
%s\n",
link->name);
return -EINVAL;
}
+
+   /*
+* Defer card registartion if codec component is not added to


registration


+* component list.
+*/
+   if (!soc_find_component(codec))
+   return -EPROBE_DEFER;
}
  
  	/*






Re: [alsa-devel] [PATCH v2 00/11] Fix driver reload issues

2019-06-25 Thread Pierre-Louis Bossart




On 6/25/19 7:04 AM, Mark Brown wrote:

On Mon, Jun 17, 2019 at 01:36:33PM +0200, Amadeusz Sławiński wrote:

Hi,

This series of patches introduces fixes to various issues found while
trying to unload all snd* modules and then loading them again. This
allows for modules to be really _modules_ and be unloaded and loaded on
demand, making it easier to develop and test them without constant
system reboots.


Pierre?  You did comment on the general concept in one of the patches
but not on any of the patches directly.


I did review the patches internally and the v1. For the v2 I could only 
do an airport lounge review and didn't see any blatant issues, so feel 
free to take the following tag for the series.


Reviewed-by: Pierre-Louis Bossart 





Re: [PATCH -next] ASoC: SOF: Intel: hda: remove duplicated include from hda.c

2019-06-20 Thread Pierre-Louis Bossart

On 6/20/19 4:57 PM, YueHaibing wrote:

Remove duplicated include.

Signed-off-by: YueHaibing 


Acked-by: Pierre-Louis Bossart 


---
  sound/soc/sof/intel/hda.c | 1 -
  1 file changed, 1 deletion(-)

diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 51c1c1787de7..7f665392618f 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -19,7 +19,6 @@
  #include 
  
  #include 

-#include 
  #include 
  #include 
  #include "../ops.h"









Re: [alsa-devel] [PATCH v2 09/11] ASoC: Intel: hdac_hdmi: Set ops to NULL on remove

2019-06-20 Thread Pierre-Louis Bossart




Could you please give a bit more context on what error you see
when this happens?


Hi,

I get Oops. This is what happens with all other patches in this
series and only this one reverted:

root@APL:~# rmmod snd_soc_sst_bxt_rt298
root@APL:~# rmmod snd_soc_hdac_hdmi
root@APL:~# rmmod snd_soc_skl


Thanks, Amadeusz. I think the order in which the drivers are
removed
is what's causing the oops in your case. With SOF, the order we
remove is

1. rmmod sof_pci_dev
2. rmmod snd_soc_sst_bxt_rt298
3. rmmod snd_soc_hdac_hdmi



Well, there is nothing enforcing the order in which modules can be
unloaded (and I see no reason to force it), as you can see from
following excerpt, you can either start unloading from
snd_soc_sst_bxt_rt298 or snd_soc_skl, and yes if you start from
snd_soc_skl, there is no problem.


there is a fundamental dependency that you are ignoring: the module 
snd_soc_sst_bxt_rt298 is a machine driver which will be probed when 
snd_soc_skl creates a platform_device.
Sure you can remove modules in a different order, but that's a bit of an 
artificial/academic exercise isn't it?





I am good with this patch. I just wanted to understand why we werent
seeing this error with SOF. Sure, there's nothing enforcing the order
in which modules are unloaded  but there must be a logical order for
testing purposes.

Pierre, can you please comment on it. I vaguely remember discussing
this with you last year.


Our tests remove the modules by taking care of dependencies and it's 
already unveiled dozens of issues.
We could add a sequence similar to Amadeusz and unbind the modules which 
are loaded with the creation of a platform_device (machine driver, 
dmic), I am just not sure how of useful this would be.


Re: [alsa-devel] [PATCH] ASoC: SOF: disallow building without CONFIG_PCI again

2019-06-17 Thread Pierre-Louis Bossart

On 6/17/19 2:45 PM, Arnd Bergmann wrote:

Compile-testing without PCI just causes warnings:

sound/soc/sof/sof-pci-dev.c:330:13: error: 'sof_pci_remove' defined but not 
used [-Werror=unused-function]
  static void sof_pci_remove(struct pci_dev *pci)
  ^~
sound/soc/sof/sof-pci-dev.c:230:12: error: 'sof_pci_probe' defined but not used 
[-Werror=unused-function]
  static int sof_pci_probe(struct pci_dev *pci,
 ^

I tried to fix this in a way that would still allow compile
tests, but it got too ugly, so this just reverts the patch
that allowed it in the first place.

Most architectures do allow enabling PCI, so the value of the
COMPILE_TEST alternative was not very high to start with.


I think COMPILE_TEST has value in that it exposed issues in the PCI 
headers, and in general COMPILE_TEST exposes code that can be 
simplified/refactored. That said I don't have the time to suggest an 
alternative at the moment so it's fine with me if you want to revert. If 
you don't mind sharing your config it'd help me work on this when I get 
a chance.

Thanks!



Fixes: e13ef82a9ab8 ("ASoC: SOF: add COMPILE_TEST for PCI options")
Signed-off-by: Arnd Bergmann 
---
  sound/soc/sof/Kconfig   |  2 +-
  sound/soc/sof/intel/hda.c   | 13 ++---
  sound/soc/sof/sof-pci-dev.c |  4 
  3 files changed, 3 insertions(+), 16 deletions(-)

diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig
index 41f79cdcbf47..fb01f0ca6027 100644
--- a/sound/soc/sof/Kconfig
+++ b/sound/soc/sof/Kconfig
@@ -11,7 +11,7 @@ if SND_SOC_SOF_TOPLEVEL
  
  config SND_SOC_SOF_PCI

tristate "SOF PCI enumeration support"
-   depends on PCI || COMPILE_TEST
+   depends on PCI
select SND_SOC_SOF
select SND_SOC_ACPI if ACPI
select SND_SOC_SOF_OPTIONS
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 140b1424f291..51c1c1787de7 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -533,9 +533,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)
 * TODO: support interrupt mode selection with kernel parameter
 *   support msi multiple vectors
 */
-#if IS_ENABLED(CONFIG_PCI)
ret = pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI);
-#endif
if (ret < 0) {
dev_info(sdev->dev, "use legacy interrupt mode\n");
/*
@@ -547,9 +545,7 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)
sdev->msi_enabled = 0;
} else {
dev_info(sdev->dev, "use msi interrupt mode\n");
-#if IS_ENABLED(CONFIG_PCI)
hdev->irq = pci_irq_vector(pci, 0);
-#endif
/* ipc irq number is the same of hda irq */
sdev->ipc_irq = hdev->irq;
sdev->msi_enabled = 1;
@@ -606,10 +602,8 @@ int hda_dsp_probe(struct snd_sof_dev *sdev)
  free_hda_irq:
free_irq(hdev->irq, bus);
  free_irq_vector:
-#if IS_ENABLED(CONFIG_PCI)
if (sdev->msi_enabled)
pci_free_irq_vectors(pci);
-#endif
  free_streams:
hda_dsp_stream_free(sdev);
  /* dsp_unmap: not currently used */
@@ -624,6 +618,7 @@ int hda_dsp_remove(struct snd_sof_dev *sdev)
  {
struct sof_intel_hda_dev *hda = sdev->pdata->hw_pdata;
struct hdac_bus *bus = sof_to_bus(sdev);
+   struct pci_dev *pci = to_pci_dev(sdev->dev);
const struct sof_intel_dsp_desc *chip = hda->desc;
  
  #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)

@@ -652,12 +647,8 @@ int hda_dsp_remove(struct snd_sof_dev *sdev)
  
  	free_irq(sdev->ipc_irq, sdev);

free_irq(hda->irq, bus);
-#if IS_ENABLED(CONFIG_PCI)
-   if (sdev->msi_enabled) {
-   struct pci_dev *pci = to_pci_dev(sdev->dev);
+   if (sdev->msi_enabled)
pci_free_irq_vectors(pci);
-   }
-#endif
  
  	hda_dsp_stream_free(sdev);

  #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c
index ab58d4f9119f..e2b19782f01a 100644
--- a/sound/soc/sof/sof-pci-dev.c
+++ b/sound/soc/sof/sof-pci-dev.c
@@ -251,11 +251,9 @@ static int sof_pci_probe(struct pci_dev *pci,
if (!sof_pdata)
return -ENOMEM;
  
-#if IS_ENABLED(CONFIG_PCI)

ret = pcim_enable_device(pci);
if (ret < 0)
return ret;
-#endif
  
  	ret = pci_request_regions(pci, "Audio DSP");

if (ret < 0)
@@ -388,7 +386,6 @@ static const struct pci_device_id sof_pci_ids[] = {
  };
  MODULE_DEVICE_TABLE(pci, sof_pci_ids);
  
-#if IS_ENABLED(CONFIG_PCI)

  /* pci_driver definition */
  static struct pci_driver snd_sof_pci_driver = {
.name = "sof-audio-pci",
@@ -400,6 +397,5 @@ static struct pci_driver snd_sof_pci_driver = {
},
  };
  module_pci_driver(snd_sof_pci_driver);
-#endif
  
  MODULE_LICENSE("Dual BSD/GPL");






Re: [alsa-devel] [RFC PATCH 6/6] soundwire: qcom: add support for SoundWire controller

2019-06-11 Thread Pierre-Louis Bossart




On 6/11/19 5:29 AM, Srinivas Kandagatla wrote:



On 10/06/2019 15:12, Pierre-Louis Bossart wrote:

+
+    if (dev_addr == SDW_BROADCAST_DEV_NUM) {
+    ctrl->fifo_status = 0;
+    ret = wait_for_completion_timeout(>sp_cmd_comp,
+  msecs_to_jiffies(TIMEOUT_MS));


This is odd. The SoundWire spec does not handle writes to a single 
device or broadcast writes differently. I don't see a clear reason 
why you would only timeout for a broadcast write.




There is danger of blocking here without timeout.


Right, and it's fine to add a timeout. The question is why add a 
timeout *only* for a broadcast operation? It should be added for every 
transaction IMO, unless you have a reason not to do so.




I did try this before, the issue is when we read/write registers from 
interrupt handler, these can be deadlocked as we will be interrupt 
handler waiting for another completion interrupt, which will never 
happen unless we return from the first interrupt.


I don't quite get the issue. With the Intel hardware we only deal with 
Master registers (some of which mirror the bus state) in the handler and 
will only modify Slave registers in the thread. All changes to Slave 
registers will be subject to a timeout as well as a check for no 
response or NAK. Not sure what is specific about your solution that 
requires a different handling of commands depending on which device 
number is used. It could very well be that you've uncovered a flaw in 
the bus design but I still don't see how it would be Qualcomm-specific?


Re: [alsa-devel] [RFC PATCH 6/6] soundwire: qcom: add support for SoundWire controller

2019-06-10 Thread Pierre-Louis Bossart




+#define SWRM_COMP_HW_VERSION    0x00


Can we please use SDW_ or QCOM_SDW_ as prefix?



SWRM prefix is as per the data sheet register names, If it help am happy 
to add QCOM_ prefix it.


That'd be fine. As long as there is no duplication and two 
terms/prefixes used for the same thing I am happy.



+
+    val = SWRM_REG_VAL_PACK(cmd_data, dev_addr, cmd_id, reg_addr);
+    ret = ctrl->reg_write(ctrl, SWRM_CMD_FIFO_WR_CMD, val);
+    if (ret < 0) {
+    dev_err(ctrl->dev, "%s: reg 0x%x write failed, err:%d\n",
+    __func__, val, ret);
+    goto err;
+    }
+
+    if (dev_addr == SDW_BROADCAST_DEV_NUM) {
+    ctrl->fifo_status = 0;
+    ret = wait_for_completion_timeout(>sp_cmd_comp,
+  msecs_to_jiffies(TIMEOUT_MS));


This is odd. The SoundWire spec does not handle writes to a single 
device or broadcast writes differently. I don't see a clear reason why 
you would only timeout for a broadcast write.




There is danger of blocking here without timeout.


Right, and it's fine to add a timeout. The question is why add a timeout 
*only* for a broadcast operation? It should be added for every 
transaction IMO, unless you have a reason not to do so.





+
+    /* Mask soundwire interrupts */
+    ctrl->reg_write(ctrl, SWRM_INTERRUPT_MASK_ADDR,
+    SWRM_INTERRUPT_STATUS_RMSK);
+
+    /* Configure No pings */
+    val = ctrl->reg_read(ctrl, SWRM_MCP_CFG_ADDR);


If there is any sort of PREQ signaling for Slave-initiated interrupts, 
disabling PINGs is likely a non-conformant implementation since the 
master is required to issue a PING command within 32 frames. That's 
also the only way to know if a device is attached, so additional 
comments are likely required.
This is the value of Maximum number of consiecutive read/write commands 
without ping command in between. I will try to collect more details and 
add some comments here.


Right, so it's probably the comment that's too strict. It's not no pings 
it's no pings during a sequence of up to N read/writes.




Re: [alsa-devel] [RFC PATCH 5/6] dt-bindings: soundwire: add bindings for Qcom controller

2019-06-10 Thread Pierre-Louis Bossart




diff --git a/Documentation/devicetree/bindings/soundwire/qcom,swr.txt 
b/Documentation/devicetree/bindings/soundwire/qcom,swr.txt
new file mode 100644
index ..eb84d0f4f36f
--- /dev/null
+++ b/Documentation/devicetree/bindings/soundwire/qcom,swr.txt
@@ -0,0 +1,62 @@
+Qualcomm SoundWire Controller
+
+This binding describes the Qualcomm SoundWire Controller Bindings.
+
+Required properties:
+
+- compatible:  Must be "qcom,soundwire-v..",
+   example:
+   "qcom,soundwire-v1.3.0"
+   "qcom,soundwire-v1.5.0"
+   "qcom,soundwire-v1.6.0"
+- reg: SoundWire controller address space.
+- interrupts:  SoundWire controller interrupt.
+- clock-names: Must contain "iface".
+- clocks:  Interface clocks needed for controller.
+- #sound-dai-cells:Must be 1 for digital audio interfaces on the 
controllers.
+- #address-cells:  Must be 1 for SoundWire devices;
+- #size-cells: Must be <0> as SoundWire addresses have no size 
component.
+- qcom,dout-ports: Must be count of data out ports
+- qcom,din-ports:  Must be count of data in ports


On these I think we should have specified dpn properties as specified in
DisCo, but then looking at spec we do not define that for master, but
bus seems to have it.

Pierre do you why master does not have dpn properties in DisCo?


Because there are no DP0 or DPn registers defined for Masters in the 
SoundWire 1.x spec. DisCo is about specifying properties for standard 
registers, when they are not standard vendor extensions need to come 
into play.





+- qcom,ports-offset1:  Must be frame offset1 of each data port.
+   Out followed by In. Used for Block size calculation.
+- qcom,ports-offset2:  Must be frame offset2 of each data port.
+   Out followed by In. Used for Block size calculation.
+- qcom,ports-sinterval-low: Must be sample interval low of each data port.
+   Out followed by In. Used for Sample Interval 
calculation.


These are software so do not belong here


Not necessarily. They define the allocation expected on that link and I 
see no problem specifying those values here. It's the moral equivalent 
of specifying which TDM slots and the bit depth of one slot you'd use 
for DSP_A/B.
And if you push back, then what would be your alternate proposal on 
where those values might be stored? This is a very specific usage of the 
link and it makes sense to me to have the information in firmware - 
exposed with properties - rather than hard-coded in a pretend bus 
allocation routine in the kernel. Either the allocation is fully dynamic 
and it's handled by the kernel or it's static and it's better to store 
it in firmware to deal with platform-to-platform variations.




Re: [PATCH] ASoC: Intel: sst: fix kmalloc call with wrong flags

2019-06-07 Thread Pierre-Louis Bossart




On 6/7/19 5:19 PM, Alex Levin wrote:

When calling kmalloc with GFP_KERNEL in case CONFIG_SLOB is unset,
kmem_cache_alloc_trace is called.

In case CONFIG_TRACING is set, kmem_cache_alloc_trace will ball
slab_alloc, which will call slab_pre_alloc_hook which might_sleep_if.

The context in which it is called in this case, the
intel_sst_interrupt_mrfld, calling a sleeping kmalloc generates a BUG():


Thanks for reporting this and suggesting a fix.

I just checked and all our test configs have CONFIG_SLOB unset and 
CONFIG_TRACING=y, but I don't recall having seen this. Could you share 
your config so that we can see if we are missing something?




Fixes: 972b0d456e64 ("ASoC: Intel: remove GFP_ATOMIC, use GFP_KERNEL")

[   20.250671] BUG: sleeping function called from invalid context at 
mm/slab.h:422
[   20.250683] in_atomic(): 1, irqs_disabled(): 1, pid: 1791, name: 
Chrome_IOThread
[   20.250690] CPU: 0 PID: 1791 Comm: Chrome_IOThread Tainted: GW   
  4.19.43 #61
[   20.250693] Hardware name: GOOGLE Kefka, BIOS Google_Kefka.7287.337.0 
03/02/2017
[   20.250697] Call Trace:
[   20.250704]  
[   20.250716]  dump_stack+0x7e/0xc3
[   20.250725]  ___might_sleep+0x12a/0x140
[   20.250731]  kmem_cache_alloc_trace+0x53/0x1c5
[   20.250736]  ? update_cfs_rq_load_avg+0x17e/0x1aa
[   20.250740]  ? cpu_load_update+0x6c/0xc2
[   20.250746]  sst_create_ipc_msg+0x2d/0x88
[   20.250752]  intel_sst_interrupt_mrfld+0x12a/0x22c
[   20.250758]  __handle_irq_event_percpu+0x133/0x228
[   20.250764]  handle_irq_event_percpu+0x35/0x7a
[   20.250768]  handle_irq_event+0x36/0x55
[   20.250773]  handle_fasteoi_irq+0xab/0x16c
[   20.250779]  handle_irq+0xd9/0x11e
[   20.250785]  do_IRQ+0x54/0xe0
[   20.250791]  common_interrupt+0xf/0xf
[   20.250795]  
[   20.250800] RIP: 0010:__lru_cache_add+0x4e/0xad
[   20.250806] Code: 00 01 48 c7 c7 b8 df 01 00 65 48 03 3c 25 28 f1 00 00 48 8b 48 
08 48 89 ca 48 ff ca f6 c1 01 48 0f 44 d0 f0 ff 42 34 0f b6 0f <89> ca fe c2 88 
17 48 89 44 cf 08 80 fa 0f 74 0e 48 8b 08 66 85 c9
[   20.250809] RSP: :a568810bfd98 EFLAGS: 0202 ORIG_RAX: 
ffd6
[   20.250814] RAX: d3b904eb1940 RBX: d3b904eb1940 RCX: 0004
[   20.250817] RDX: d3b904eb1940 RSI: a10ee5c47450 RDI: a10efba1dfb8
[   20.250821] RBP: a568810bfda8 R08: a10ef9c741c1 R09: dead0100
[   20.250824] R10:  R11:  R12: a10ee8d52a40
[   20.250827] R13: a10ee8d52000 R14: a10ee5c47450 R15: 80013ac65067
[   20.250835]  lru_cache_add_active_or_unevictable+0x4e/0xb8
[   20.250841]  handle_mm_fault+0xd98/0x10c4
[   20.250848]  __do_page_fault+0x235/0x42d
[   20.250853]  ? page_fault+0x8/0x30
[   20.250858]  do_page_fault+0x3d/0x17a
[   20.250862]  ? page_fault+0x8/0x30
[   20.250866]  page_fault+0x1e/0x30
[   20.250872] RIP: 0033:0x7962fdea9304
[   20.250875] Code: 0f 11 4c 17 f0 c3 48 3b 15 f1 26 31 00 0f 83 e2 00 00 00 48 39 
f7 72 0f 74 12 4c 8d 0c 16 4c 39 cf 0f 82 63 01 00 00 48 89 d1  a4 c3 80 fa 
08 73 12 80 fa 04 73 1e 80 fa 01 77 26 72 05 0f b6
[   20.250879] RSP: 002b:7962f4db5468 EFLAGS: 00010206
[   20.250883] RAX: 3c8cc9d47008 RBX:  RCX: 1b48
[   20.250886] RDX: 2b40 RSI: 3c8cc9551000 RDI: 3c8cc9d48000
[   20.250890] RBP: 7962f4db5820 R08:  R09: 3c8cc9552b48
[   20.250893] R10: 562dd1064d30 R11: 3c8cc825b908 R12: 3c8cc966d3c0
[   20.250896] R13: 3c8cc9e280c0 R14:  R15: 

Signed-off-by: Alex Levin 
---

  sound/soc/intel/atom/sst/sst_pvt.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/soc/intel/atom/sst/sst_pvt.c 
b/sound/soc/intel/atom/sst/sst_pvt.c
index 00a37a09dc9b..dba0ca07ebf9 100644
--- a/sound/soc/intel/atom/sst/sst_pvt.c
+++ b/sound/soc/intel/atom/sst/sst_pvt.c
@@ -166,11 +166,11 @@ int sst_create_ipc_msg(struct ipc_post **arg, bool large)
  {
struct ipc_post *msg;
  
-	msg = kzalloc(sizeof(*msg), GFP_KERNEL);

+   msg = kzalloc(sizeof(*msg), GFP_ATOMIC);
if (!msg)
return -ENOMEM;
if (large) {
-   msg->mailbox_data = kzalloc(SST_MAILBOX_SIZE, GFP_KERNEL);
+   msg->mailbox_data = kzalloc(SST_MAILBOX_SIZE, GFP_ATOMIC);
if (!msg->mailbox_data) {
kfree(msg);
return -ENOMEM;



Re: [alsa-devel] next/master boot bisection: next-20190528 on sun8i-h3-libretech-all-h3-cc

2019-06-07 Thread Pierre-Louis Bossart



On 6/7/19 2:00 PM, Mark Brown wrote:

On Fri, Jun 07, 2019 at 05:31:12PM +0100, Guillaume Tucker wrote:

On 30/05/2019 16:53, Takashi Iwai wrote:



+   mutex_lock(_mutex);
for_each_rtdcom(rtd, rtdcom) {
component = rtdcom->component;
  
  		if (component->driver->remove_order == order)

soc_remove_component(component);
}
+   mutex_unlock(_mutex);



Ranjani, which code path your patch tries to address?  Maybe better to
wrap client_mutex() in the caller side like snd_soc_unbind_card()?



Is anyone looking into this issue?



It is still occurring in next-20190606, there was a bisection
today which landed on the same commit.  There just hasn't been
any new bisection reports because they have been temporarily
disabled while we fix some issues on kernelci.org.


I was expecting that Ranjani or one of the other Intel people was
looking into it...


Ack. We've all been underwater this week and this wasn't addressed, 
sorry about the delay. It's probably wise to revert this commit at this 
point while we look for an alternate solution?


There was an initial proposal submitted on GitHub [1] (patch attached) 
which implemented what Takashi suggested in his comments. This proposal 
was later optimized further, it could be that the optimization was one 
bridge too far.


Could you let us know if this attached patch has any negative effects on 
non-Intel platforms?


Thanks!

[1] 
https://github.com/thesofproject/linux/commit/9fd09dd417bc8be7a4a8bdd1621558151f8d117b
>From 9fd09dd417bc8be7a4a8bdd1621558151f8d117b Mon Sep 17 00:00:00 2001
From: Ranjani Sridharan 
Date: Wed, 22 May 2019 10:52:40 -0700
Subject: [PATCH] ASoC: core: lock client_mutex while removing link components

Removing link components results in topology unloading. So,
acquire the client_mutex before removing components in
snd_soc_unbind_card(). This will prevent lockdep warning
when the dai link is removed.

Signed-off-by: Ranjani Sridharan 
---
 sound/soc/soc-core.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 2403bec2fccf3..5609398f05d80 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -2839,12 +2839,14 @@ static void snd_soc_unbind_card(struct snd_soc_card *card, bool unregister)
 		snd_soc_dapm_shutdown(card);
 		snd_soc_flush_all_delayed_work(card);
 
+		mutex_lock(_mutex);
 		/* remove all components used by DAI links on this card */
 		for_each_comp_order(order) {
 			for_each_card_rtds(card, rtd) {
 soc_remove_link_components(card, rtd, order);
 			}
 		}
+		mutex_unlock(_mutex);
 
 		soc_cleanup_card_resources(card);
 		if (!unregister)


Re: [alsa-devel] [RFC PATCH 6/6] soundwire: qcom: add support for SoundWire controller

2019-06-07 Thread Pierre-Louis Bossart




+config SOUNDWIRE_QCOM
+   tristate "Qualcomm SoundWire Master driver"
+   select SOUNDWIRE_BUS
+   depends on SND_SOC


depends on SLIMBUS if you need the SlimBus link to talk to your 
SoundWire Master?


Also depends on device tree since you use of_ functions?


+#define SWRM_COMP_HW_VERSION   0x00


Can we please use SDW_ or QCOM_SDW_ as prefix?


+#define SWRM_INTERRUPT_STATUS_NEW_SLAVE_AUTO_ENUM_FINISHED BIT(11)
+#define SWRM_INTERRUPT_STATUS_AUTO_ENUM_FAILED BIT(12)
+#define SWRM_INTERRUPT_STATUS_AUTO_ENUM_TABLE_IS_FULL  BIT(13)


This hints at hardware support to assign Device Numbers automagically so 
will likely have impacts on the bus driver code, no?




+#define SWRM_MAX_ROW_VAL   0 /* Rows = 48 */
+#define SWRM_DEFAULT_ROWS  48
+#define SWRM_MIN_COL_VAL   0 /* Cols = 2 */
+#define SWRM_DEFAULT_COL   16
+#define SWRM_SPECIAL_CMD_ID0xF
+#define MAX_FREQ_NUM   1
+#define TIMEOUT_MS 1000
+#define QCOM_SWRM_MAX_RD_LEN   0xf
+#define DEFAULT_CLK_FREQ   960


The clocks and frame shape don't match usual expectations for PDM.
For a 9.6 MHz support, you would typically use 8 columns and 50 rows to 
transport PDM with a 50x oversampling. I've never seen anyone use 48x 
for PDM.



+#define SWRM_MAX_DAIS  0xF
+
+struct qcom_swrm_port_config {
+   u8 si;
+   u8 off1;
+   u8 off2;
+};
+
+struct qcom_swrm_ctrl {
+   struct sdw_bus bus;
+   struct device *dev;
+   struct regmap *regmap;
+   struct completion sp_cmd_comp;
+   struct work_struct slave_work;
+   /* read/write lock */
+   struct mutex lock;
+   /* Port alloc/free lock */
+   struct mutex port_lock;
+   struct clk *hclk;
+   int fifo_status;
+   void __iomem *base;
+   u8 wr_cmd_id;
+   u8 rd_cmd_id;
+   int irq;
+   unsigned int version;
+   int num_din_ports;
+   int num_dout_ports;
+   unsigned long dout_port_mask;
+   unsigned long din_port_mask;
+   struct qcom_swrm_port_config pconfig[SDW_MAX_PORTS];


this is not necessarily correct. the initial definitions for 
SDW_MAX_PORTS was for Slave devices. There is no definitions for Masters 
in the SoundWire spec, so you could use whatever constant you want for 
your hardware.



+   struct sdw_stream_runtime *sruntime[SWRM_MAX_DAIS];
+   enum sdw_slave_status status[SDW_MAX_DEVICES];
+   u32 (*reg_read)(struct qcom_swrm_ctrl *ctrl, int reg);
+   int (*reg_write)(struct qcom_swrm_ctrl *ctrl, int reg, int val);
+};
+
+#define to_qcom_sdw(b) container_of(b, struct qcom_swrm_ctrl, bus)
+
+struct usecase {
+   u8 num_port;
+   u8 num_ch;
+   u32 chrate;
+};


this structure doesn't seem to be used?


+static int qcom_swrm_cmd_fifo_wr_cmd(struct qcom_swrm_ctrl *ctrl, u8 cmd_data,
+u8 dev_addr, u16 reg_addr)
+{
+   int ret = 0;
+   u8 cmd_id;
+   u32 val;
+
+   mutex_lock(>lock);
+   if (dev_addr == SDW_BROADCAST_DEV_NUM) {
+   cmd_id = SWRM_SPECIAL_CMD_ID;
+   } else {
+   if (++ctrl->wr_cmd_id == SWRM_SPECIAL_CMD_ID)
+   ctrl->wr_cmd_id = 0;
+
+   cmd_id = ctrl->wr_cmd_id;
+   }


might be worth having a helper/macro since you are doing the same thing 
below.



+
+   val = SWRM_REG_VAL_PACK(cmd_data, dev_addr, cmd_id, reg_addr);
+   ret = ctrl->reg_write(ctrl, SWRM_CMD_FIFO_WR_CMD, val);
+   if (ret < 0) {
+   dev_err(ctrl->dev, "%s: reg 0x%x write failed, err:%d\n",
+   __func__, val, ret);
+   goto err;
+   }
+
+   if (dev_addr == SDW_BROADCAST_DEV_NUM) {
+   ctrl->fifo_status = 0;
+   ret = wait_for_completion_timeout(>sp_cmd_comp,
+ msecs_to_jiffies(TIMEOUT_MS));


This is odd. The SoundWire spec does not handle writes to a single 
device or broadcast writes differently. I don't see a clear reason why 
you would only timeout for a broadcast write.



+
+   if (!ret || ctrl->fifo_status) {
+   dev_err(ctrl->dev, "reg 0x%x write failed\n", val);
+   ret = -ENODATA;
+   goto err;
+   }
+   }
+err:
+   mutex_unlock(>lock);
+   return ret;
+}
+
+static int qcom_swrm_cmd_fifo_rd_cmd(struct qcom_swrm_ctrl *ctrl,
+u8 dev_addr, u16 reg_addr,
+u32 len, u8 *rval)
+{
+   int i, ret = 0;
+   u8 cmd_id = 0;
+   u32 val;
+
+   mutex_lock(>lock);
+   if (dev_addr == SDW_ENUM_DEV_NUM) {
+   cmd_id = SWRM_SPECIAL_CMD_ID;
+   } else {
+   if (++ctrl->rd_cmd_id == SWRM_SPECIAL_CMD_ID)
+   ctrl->rd_cmd_id = 0;
+
+   cmd_id = ctrl->rd_cmd_id;
+   }


helper?


+  

Re: [alsa-devel] [RFC PATCH 5/6] dt-bindings: soundwire: add bindings for Qcom controller

2019-06-07 Thread Pierre-Louis Bossart

On 6/7/19 3:56 AM, Srinivas Kandagatla wrote:

This patch adds bindings for Qualcomm soundwire controller.

Qualcomm SoundWire Master controller is present in most Qualcomm SoCs
either integrated as part of WCD audio codecs via slimbus or
as part of SOC I/O.

Signed-off-by: Srinivas Kandagatla 
---
  .../bindings/soundwire/qcom,swr.txt   | 62 +++
  1 file changed, 62 insertions(+)
  create mode 100644 Documentation/devicetree/bindings/soundwire/qcom,swr.txt


you seem to use the 'swr' prefix in this patch. Most implementers use 
'sdw', and that's the default also used in the MIPI DisCo spec for 
properties. Can we align on the same naming conventions?




diff --git a/Documentation/devicetree/bindings/soundwire/qcom,swr.txt 
b/Documentation/devicetree/bindings/soundwire/qcom,swr.txt
new file mode 100644
index ..eb84d0f4f36f
--- /dev/null
+++ b/Documentation/devicetree/bindings/soundwire/qcom,swr.txt
@@ -0,0 +1,62 @@
+Qualcomm SoundWire Controller
+
+This binding describes the Qualcomm SoundWire Controller Bindings.
+
+Required properties:
+
+- compatible:  Must be "qcom,soundwire-v..",
+   example:
+   "qcom,soundwire-v1.3.0"
+   "qcom,soundwire-v1.5.0"
+   "qcom,soundwire-v1.6.0"
+- reg: SoundWire controller address space.
+- interrupts:  SoundWire controller interrupt.
+- clock-names: Must contain "iface".
+- clocks:  Interface clocks needed for controller.
+- #sound-dai-cells:Must be 1 for digital audio interfaces on the 
controllers.
+- #address-cells:  Must be 1 for SoundWire devices;
+- #size-cells: Must be <0> as SoundWire addresses have no size 
component.
+- qcom,dout-ports: Must be count of data out ports
+- qcom,din-ports:  Must be count of data in ports
+- qcom,ports-offset1:  Must be frame offset1 of each data port.
+   Out followed by In. Used for Block size calculation.
+- qcom,ports-offset2:  Must be frame offset2 of each data port.
+   Out followed by In. Used for Block size calculation.
+- qcom,ports-sinterval-low: Must be sample interval low of each data port.
+   Out followed by In. Used for Sample Interval 
calculation.


These definitions are valid only for specific types of ports, I believe 
here it's a 'reduced' port since offset2 is not required for simpler 
ports and you don't have Hstart/Hstop.


so if you state that all of these properties are required, you are 
explicitly ruling out future implementations of simple ports or will 
have to redefine them later.


Also the definition 'frame offset1/2' is incorrect. the offset is 
defined within each Payload Transport Window - not each frame - and its 
definition depends on the packing mode used, which isn't defined or 
stated here.


And last it looks like you assume a fixed frame shape - likely 50 rows 
by 8 columns, it might be worth adding a note on the max values for 
offset1/2 implied by this frame shape.



+
+= SoundWire devices
+Each subnode of the bus represents SoundWire device attached to it.
+The properties of these nodes are defined by the individual bindings.
+
+= EXAMPLE
+The following example represents a SoundWire controller on DB845c board
+which has controller integrated inside WCD934x codec on SDM845 SoC.
+
+soundwire: soundwire@c85 {
+   compatible = "qcom,soundwire-v1.3.0";
+   reg = <0xc85 0x20>;
+   interrupts = <20 IRQ_TYPE_EDGE_RISING>;
+   clocks = <>;
+   clock-names = "iface";
+   #sound-dai-cells = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   qcom,dout-ports = <6>;
+   qcom,din-ports  = <2>;
+   qcom,ports-sinterval-low =/bits/ 8  <0x07 0x1F 0x3F 0x7 0x1F 0x3F 0x0F 
0x0F>;
+   qcom,ports-offset1 = /bits/ 8 <0x01 0x02 0x0C 0x6 0x12 0x0D 0x07 0x0A >;
+   qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x1F 0x00 0x00 0x1F 0x00 0x00>;
+
+   /* Left Speaker */
+   wsa8810@1{
+   
+   reg = <1>;
+   };
+
+   /* Right Speaker */
+   wsa8810@2{
+   
+   reg = <2>;
+   };
+};





<    3   4   5   6   7   8   9   10   11   12   >