mbox series

[0/2] slimbus: Add Stream Support

Message ID 20180621134009.27116-1-srinivas.kandagatla@linaro.org
Headers show
Series slimbus: Add Stream Support | expand

Message

Srinivas Kandagatla June 21, 2018, 1:40 p.m. UTC
This patchset adds basic stream support for SLIMbus devices and
controllers. Mostly inspired by soundwire stream patches. But slimbus
stream is much simpler compared to soundwire

From slim_device side, we have below 6 new apis.
slim_stream_allocate() - allocating runtime slim stream
slim_stream_prepare() - to configure runtime stream with config
slim_stream_enable() - enable channels/ports for data
slim_stream_disable() - disable channels/ports.
slim_stream_unprepare() - un configure runtime stream
slim_stream_free() - free all associated memory.

From Controller side:
Data channel Management and reconfiguration messages are applicable for
all the controllers which are inline with SLIMbus specs. However light
weight controller like NGD which have user specific implementation of
some messages need to be invoked instead of standard message commands.
For usecases like this simple enable/disable stream apis are provided.

Assumptions:
1> Current design assumes that the channel and ports are statically allocated
to the device during SoC integration, which is the case with all the
Qualcomm SoCs.
2> One-to-One mapping between Port and Channel, SLIMBus versions earlier
than 2.0 has only one endpoint per port. Current patchset can be extended
to support more than one endpoints per port.
3> Only audio usecase, This patchset only supports Isochronous and Push/Pull
transport protocols, which are sufficient for audio use cases.
4> DSP does all the data handling for the allocated channels. Which is true
for Qcom SoCs.

TODO:
	Bandwidth management.

Dependency:
	This patchset has dependency on the NGD driver
	https://patchwork.kernel.org/patch/10474959/

Tested this patchset with WCD9335 codec playback on DB820c on
top of 4.18-rc1 with qdsp6.

I have pushed my working branch to [1] incase someone want to try.

[1]:https://git.linaro.org/people/srinivas.kandagatla/linux.git/log/?h=slimbus-ngd


Thanks,
srini

Srinivas Kandagatla (2):
  slimbus: stream: add stream support
  slimbus: ngd: add stream support

 Documentation/driver-api/slimbus.rst |   5 +
 drivers/slimbus/Makefile             |   2 +-
 drivers/slimbus/core.c               |   2 +
 drivers/slimbus/qcom-ngd-ctrl.c      | 144 +++++++++-
 drivers/slimbus/slimbus.h            | 206 +++++++++++++++
 drivers/slimbus/stream.c             | 493 +++++++++++++++++++++++++++++++++++
 include/linux/slimbus.h              |  56 ++++
 7 files changed, 905 insertions(+), 3 deletions(-)
 create mode 100644 drivers/slimbus/stream.c

-- 
2.16.2

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Vinod Koul June 22, 2018, 12:50 p.m. UTC | #1
On 21-06-18, 14:40, Srinivas Kandagatla wrote:
> This patch adds support to SLIMbus stream apis for slimbus device.

> SLIMbus streaming involves adding support to Data Channel Management and

> channel Reconfiguration Messages to slim core plus few stream apis.

> >From slim device side the apis are very simple mostly inline with other

  ^^
Bad char >

> +/**

> + * enum slim_port_direction: SLIMbus port direction


blank line here makes it more readable

> +/**

> + * struct slim_presence_rate - Presense Rate table for all Natural Frequencies

> + *	The Presense rate of a constant bitrate stram is mean flow rate of the

                                                ^^^^^
Do you mean stream?

> +static struct slim_presence_rate {

> +	int rate;

> +	int pr_code;

> +} prate_table[] = {

> +	{12000,		0x01},

> +	{24000,		0x02},

> +	{48000,		0x03},

> +	{96000,		0x04},

> +	{192000,	0x05},

> +	{384000,	0x06},

> +	{768000,	0x07},

> +	{110250,	0x09},

> +	{220500,	0x0a},

> +	{441000,	0x0b},

> +	{882000,	0x0c},

> +	{176400,	0x0d},

> +	{352800,	0x0e},

> +	{705600,	0x0f},

> +	{4000,		0x10},

> +	{8000,		0x11},

> +	{16000,		0x12},

> +	{32000,		0x13},

> +	{64000,		0x14},

> +	{128000,	0x15},

> +	{256000,	0x16},

> +	{512000,	0x17},


this table values are indices, so how about using only rate and removing
pr_code and use array index for that, saves half the space..

> +struct slim_stream_runtime *slim_stream_allocate(struct slim_device *dev,

> +						 const char *name)

> +{

> +	struct slim_stream_runtime *rt;

> +	unsigned long flags;

> +

> +	rt = kzalloc(sizeof(*rt), GFP_KERNEL);

> +	if (!rt)

> +		return ERR_PTR(-ENOMEM);

> +

> +	rt->name = kasprintf(GFP_KERNEL, "slim-%s", name);

> +	if (!rt->name) {

> +		kfree(rt);

> +		return ERR_PTR(-ENOMEM);

> +	}

> +

> +	rt->dev = dev;

> +	rt->state = SLIM_STREAM_STATE_ALLOCATED;

> +	spin_lock_irqsave(&dev->stream_list_lock, flags);

> +	list_add_tail(&rt->node, &dev->stream_list);

> +	spin_unlock_irqrestore(&dev->stream_list_lock, flags);


Any reason for _irqsave variant? Do you expect stream APIs to be called
from ISR?

> +/*

> + * slim_stream_prepare() - Prepare a SLIMbus Stream

> + *

> + * @rt: instance of slim stream runtime to configure

> + * @cfg: new configuration for the stream

> + *

> + * This API will configure SLIMbus stream with config parameters from cfg.

> + * return zero on success and error code on failure. From ASoC DPCM framework,

> + * this state is linked to hw_params()/prepare() operation.


so would this be called from either.. btw prepare can be invoked
multiple times, so that should be taken into consideration by caller.

> + */

> +int slim_stream_prepare(struct slim_stream_runtime *rt,

> +			struct slim_stream_config *cfg)

> +{

> +	struct slim_controller *ctrl = rt->dev->ctrl;

> +	struct slim_port *port;

> +	int num_ports, i, port_id;

> +

> +	num_ports = hweight32(cfg->port_mask);

> +	rt->ports = kcalloc(num_ports, sizeof(*port), GFP_ATOMIC);


since this is supposed to be invoked in hw_params()/prepare, why would
we need GFP_ATOMIC here?

> +static int slim_activate_channel(struct slim_stream_runtime *stream,

> +				 struct slim_port *port)

> +{

> +	struct slim_device *sdev = stream->dev;

> +	struct slim_val_inf msg = {0, 0, NULL, NULL};

> +	u8 mc = SLIM_MSG_MC_NEXT_ACTIVATE_CHANNEL;

> +	DEFINE_SLIM_LDEST_TXN(txn, mc, 5, stream->dev->laddr, &msg);

> +	u8 wbuf[1];

> +

> +	txn.msg->num_bytes = 1;

> +	txn.msg->wbuf = wbuf;

> +	wbuf[0] = port->ch.id;

> +	port->ch.state = SLIM_CH_STATE_ACTIVE;

> +

> +	return slim_do_transfer(sdev->ctrl, &txn);

> +}


how about adding a macro for sending message, which fills slim_val_inf
and you invoke that with required parameters to be filled.

> +/*

> + * slim_stream_enable() - Enable a prepared SLIMbus Stream


Do you want to check if it is already prepared ..?

> +/**

> + * slim_stream_direction: SLIMbus stream direction

> + *

> + * @SLIM_STREAM_DIR_PLAYBACK: Playback

> + * @SLIM_STREAM_DIR_CAPTURE: Capture

> + */

> +enum slim_stream_direction {

> +	SLIM_STREAM_DIR_PLAYBACK = 0,

> +	SLIM_STREAM_DIR_CAPTURE,


this is same as SNDRV_PCM_STREAM_PLAYBACK, so should we use that here?
-- 
~Vinod
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Srinivas Kandagatla June 25, 2018, 10:11 a.m. UTC | #2
Thanks Vinod for the Review,

On 22/06/18 13:50, Vinod wrote:
> On 21-06-18, 14:40, Srinivas Kandagatla wrote:

>> This patch adds support to SLIMbus stream apis for slimbus device.

>> SLIMbus streaming involves adding support to Data Channel Management and

>> channel Reconfiguration Messages to slim core plus few stream apis.

>> >From slim device side the apis are very simple mostly inline with other

>    ^^

> Bad char >

Yep, will fix it.
> 

>> +/**

>> + * enum slim_port_direction: SLIMbus port direction

> 

> blank line here makes it more readable

> 

Sure it makes sense.
>> +/**

>> + * struct slim_presence_rate - Presense Rate table for all Natural Frequencies

>> + *	The Presense rate of a constant bitrate stram is mean flow rate of the

>                                                  ^^^^^

> Do you mean stream?

Yep will fix it.
> 

>> +static struct slim_presence_rate {

>> +	int rate;

>> +	int pr_code;

>> +} prate_table[] = {

>> +	{12000,		0x01},

>> +	{24000,		0x02},

>> +	{48000,		0x03},

>> +	{96000,		0x04},

>> +	{192000,	0x05},

>> +	{384000,	0x06},

>> +	{768000,	0x07},

>> +	{110250,	0x09},

>> +	{220500,	0x0a},

>> +	{441000,	0x0b},

>> +	{882000,	0x0c},

>> +	{176400,	0x0d},

>> +	{352800,	0x0e},

>> +	{705600,	0x0f},

>> +	{4000,		0x10},

>> +	{8000,		0x11},

>> +	{16000,		0x12},

>> +	{32000,		0x13},

>> +	{64000,		0x14},

>> +	{128000,	0x15},

>> +	{256000,	0x16},

>> +	{512000,	0x17},

> 

> this table values are indices, so how about using only rate and removing

> pr_code and use array index for that, saves half the space..

> 

look like I over done it, I will fix this in next version.

>> +struct slim_stream_runtime *slim_stream_allocate(struct slim_device *dev,

>> +						 const char *name)

>> +{

>> +	struct slim_stream_runtime *rt;

>> +	unsigned long flags;

>> +

>> +	rt = kzalloc(sizeof(*rt), GFP_KERNEL);

>> +	if (!rt)

>> +		return ERR_PTR(-ENOMEM);

>> +

>> +	rt->name = kasprintf(GFP_KERNEL, "slim-%s", name);

>> +	if (!rt->name) {

>> +		kfree(rt);

>> +		return ERR_PTR(-ENOMEM);

>> +	}

>> +

>> +	rt->dev = dev;

>> +	rt->state = SLIM_STREAM_STATE_ALLOCATED;

>> +	spin_lock_irqsave(&dev->stream_list_lock, flags);

>> +	list_add_tail(&rt->node, &dev->stream_list);

>> +	spin_unlock_irqrestore(&dev->stream_list_lock, flags);

> 

> Any reason for _irqsave variant? Do you expect stream APIs to be called

> from ISR?We can move to non irqsave variant here, as i do not see a case where 

this list would be interrupted from irq context.


> 

>> +/*

>> + * slim_stream_prepare() - Prepare a SLIMbus Stream

>> + *

>> + * @rt: instance of slim stream runtime to configure

>> + * @cfg: new configuration for the stream

>> + *

>> + * This API will configure SLIMbus stream with config parameters from cfg.

>> + * return zero on success and error code on failure. From ASoC DPCM framework,

>> + * this state is linked to hw_params()/prepare() operation.

> 

> so would this be called from either.. btw prepare can be invoked

> multiple times, so that should be taken into consideration by caller.


This should be just hw_params() where we have more information on the 
audio parameters, I will make this more clear in the doc about this.

> 

>> + */

>> +int slim_stream_prepare(struct slim_stream_runtime *rt,

>> +			struct slim_stream_config *cfg)

>> +{

>> +	struct slim_controller *ctrl = rt->dev->ctrl;

>> +	struct slim_port *port;

>> +	int num_ports, i, port_id;

>> +

>> +	num_ports = hweight32(cfg->port_mask);

>> +	rt->ports = kcalloc(num_ports, sizeof(*port), GFP_ATOMIC);

> 

> since this is supposed to be invoked in hw_params()/prepare, why would

> we need GFP_ATOMIC here?

No, we do not need this to be ATOMIC, will remove this!

> 

>> +static int slim_activate_channel(struct slim_stream_runtime *stream,

>> +				 struct slim_port *port)

>> +{

>> +	struct slim_device *sdev = stream->dev;

>> +	struct slim_val_inf msg = {0, 0, NULL, NULL};

>> +	u8 mc = SLIM_MSG_MC_NEXT_ACTIVATE_CHANNEL;

>> +	DEFINE_SLIM_LDEST_TXN(txn, mc, 5, stream->dev->laddr, &msg);

>> +	u8 wbuf[1];

>> +

>> +	txn.msg->num_bytes = 1;

>> +	txn.msg->wbuf = wbuf;

>> +	wbuf[0] = port->ch.id;

>> +	port->ch.state = SLIM_CH_STATE_ACTIVE;

>> +

>> +	return slim_do_transfer(sdev->ctrl, &txn);

>> +}

> 

> how about adding a macro for sending message, which fills slim_val_inf

> and you invoke that with required parameters to be filled.

> 

Sounds sensible thing, I will give that a try and see!

>> +/*

>> + * slim_stream_enable() - Enable a prepared SLIMbus Stream

> 

> Do you want to check if it is already prepared ..?

Yep, I think most of the code needs similar state machine check, I will 
add this in next version.
> 

>> +/**

>> + * slim_stream_direction: SLIMbus stream direction

>> + *

>> + * @SLIM_STREAM_DIR_PLAYBACK: Playback

>> + * @SLIM_STREAM_DIR_CAPTURE: Capture

>> + */

>> +enum slim_stream_direction {

>> +	SLIM_STREAM_DIR_PLAYBACK = 0,

>> +	SLIM_STREAM_DIR_CAPTURE,

> 

> this is same as SNDRV_PCM_STREAM_PLAYBACK, so should we use that here?

Sure will do, makes it clear!

> 

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Srinivas Kandagatla June 25, 2018, 4:15 p.m. UTC | #3
Thanks Stephen for review,

On 25/06/18 17:12, Stephen Boyd wrote:
> Quoting Srinivas Kandagatla (2018-06-21 06:40:08)

>> new file mode 100644

>> index 000000000000..f8af9474d286

>> --- /dev/null

>> +++ b/drivers/slimbus/stream.c

>> @@ -0,0 +1,493 @@

>> +// SPDX-License-Identifier: GPL-2.0

>> +// Copyright (c) 2018, Linaro Limited

>> +

>> +#include <linux/kernel.h>

>> +#include <linux/errno.h>

>> +#include <linux/slab.h>

>> +#include <linux/list.h>

>> +#include <linux/slimbus.h>

>> +#include "slimbus.h"

>> +

>> +/**

>> + * struct segdist_code - Segment Distributions code from

>> + *     Table 20 of SLIMbus Specs Version 2.0

>> + *

>> + * @ratem: Channel Rate Multipler(Segments per Superframe)

>> + * @seg_interval: Number of slots between the first Slot of Segment

>> + *             and the first slot of the next  consecutive Segment.

>> + * @segdist_code: Segment Distribution Code SD[11:0]

>> + * @seg_offset_mask: Segment offset mask in SD[11:0]

>> + * @segdist_codes: List of all possible Segmet Distribution codes.

>> + */

>> +static struct segdist_code {

> 

> const?

> 

Yep, Will fix this and presence rate in next version.!

>> +       int ratem;

>> +       int seg_interval;

>> +       int segdist_code;

>> +       u32 seg_offset_mask;

>> +

>> +} segdist_codes[] = {

>> +       {1,     1536,   0x200,   0xdff},

>> +       {2,     768,    0x100,   0xcff},

>> +       {4,     384,    0x080,   0xc7f},

>> +       {8,     192,    0x040,   0xc3f},

>> +       {16,    96,     0x020,   0xc1f},

>> +       {32,    48,     0x010,   0xc0f},

>> +       {64,    24,     0x008,   0xc07},

>> +       {128,   12,     0x004,   0xc03},

>> +       {256,   6,      0x002,   0xc01},

>> +       {512,   3,      0x001,   0xc00},

>> +       {3,     512,    0xe00,   0x1ff},

>> +       {6,     256,    0xd00,   0x0ff},

>> +       {12,    128,    0xc80,   0x07f},

>> +       {24,    64,     0xc40,   0x03f},

>> +       {48,    32,     0xc20,   0x01f},

>> +       {96,    16,     0xc10,   0x00f},

>> +       {192,   8,      0xc08,   0x007},

>> +       {364,   4,      0xc04,   0x003},

>> +       {768,   2,      0xc02,   0x001},

>> +};

>> +

>> +/**

>> + * struct slim_presence_rate - Presense Rate table for all Natural Frequencies

>> + *     The Presense rate of a constant bitrate stram is mean flow rate of the

>> + *     stream expressed in occupied Segments of that Data Channel per second.

>> + *     Table 66 from SLIMbus 2.0 Specs

>> + *

>> + * @rate: data rate

>> + * @pr_code: presence rate code PR[6:0]

>> + * @prate_table: All possible presence rate code for Natural Frequencies

>> + */

>> +static struct slim_presence_rate {

> 

> const?

> 

>> +       int rate;

>> +       int pr_code;

>> +} prate_table[] = {

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Vinod Koul June 25, 2018, 4:21 p.m. UTC | #4
On 25-06-18, 11:11, Srinivas Kandagatla wrote:

> > > +struct slim_stream_runtime *slim_stream_allocate(struct slim_device *dev,

> > > +						 const char *name)

> > > +{

> > > +	struct slim_stream_runtime *rt;

> > > +	unsigned long flags;

> > > +

> > > +	rt = kzalloc(sizeof(*rt), GFP_KERNEL);

> > > +	if (!rt)

> > > +		return ERR_PTR(-ENOMEM);

> > > +

> > > +	rt->name = kasprintf(GFP_KERNEL, "slim-%s", name);

> > > +	if (!rt->name) {

> > > +		kfree(rt);

> > > +		return ERR_PTR(-ENOMEM);

> > > +	}

> > > +

> > > +	rt->dev = dev;

> > > +	rt->state = SLIM_STREAM_STATE_ALLOCATED;

> > > +	spin_lock_irqsave(&dev->stream_list_lock, flags);

> > > +	list_add_tail(&rt->node, &dev->stream_list);

> > > +	spin_unlock_irqrestore(&dev->stream_list_lock, flags);

> > 

> > Any reason for _irqsave variant? Do you expect stream APIs to be called

> > from ISR?We can move to non irqsave variant here, as i do not see a case

> > where

> this list would be interrupted from irq context.


That's interesting can you please describe how?
Also, won't it be modified from bottom half...

> > > +/*

> > > + * slim_stream_enable() - Enable a prepared SLIMbus Stream

> > 

> > Do you want to check if it is already prepared ..?

> Yep, I think most of the code needs similar state machine check, I will add

> this in next version.


so if you are tying to snd stream states then I don't think you need a
state machine here. ALSA already does that for you so you can skip it :D

-- 
~Vinod
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Srinivas Kandagatla June 25, 2018, 4:30 p.m. UTC | #5
On 25/06/18 17:21, Vinod wrote:
>>>> +/*

>>>> + * slim_stream_enable() - Enable a prepared SLIMbus Stream

>>> Do you want to check if it is already prepared ..?

>> Yep, I think most of the code needs similar state machine check, I will add

>> this in next version.

> so if you are tying to snd stream states then I don't think you need a

> state machine here. ALSA already does that for you so you can skip it :D

Stream state machine looks redundant, I will try to skip it and see how 
things look at the end! before sending next version.

thanks,
srini
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html