On 4/5/18 11:48 AM, Vinod Koul wrote:
Add support for Cadence stream initialization and implement stream APIs.
Signed-off-by: Sanyog Kale sanyog.r.kale@intel.com Signed-off-by: Shreyas NC shreyas.nc@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com
drivers/soundwire/cadence_master.c | 180 +++++++++++++++++++++++++++++++++++++ drivers/soundwire/cadence_master.h | 43 +++++++++ 2 files changed, 223 insertions(+)
diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c index 89a4ae86d36a..9400327c9fe2 100644 --- a/drivers/soundwire/cadence_master.c +++ b/drivers/soundwire/cadence_master.c @@ -13,6 +13,8 @@ #include <linux/mod_devicetable.h> #include <linux/soundwire/sdw_registers.h> #include <linux/soundwire/sdw.h> +#include <sound/pcm_params.h> +#include <sound/soc.h> #include "bus.h" #include "cadence_master.h"
@@ -998,5 +1000,183 @@ int sdw_cdns_probe(struct sdw_cdns *cdns) } EXPORT_SYMBOL(sdw_cdns_probe);
+int cdns_set_sdw_stream(struct snd_soc_dai *dai,
void *stream, bool pcm, int direction)
+{
- struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
- struct sdw_cdns_dma_data *dma;
- dma = kzalloc(sizeof(*dma), GFP_KERNEL);
- if (!dma)
return -ENOMEM;
- if (pcm)
dma->stream_type = SDW_STREAM_PCM;
- else
dma->stream_type = SDW_STREAM_PDM;
- dma->bus = &cdns->bus;
- dma->link_id = cdns->instance;
- dma->stream = stream;
- if (direction == SNDRV_PCM_STREAM_PLAYBACK)
dai->playback_dma_data = dma;
- else
dai->capture_dma_data = dma;
- return 0;
+} +EXPORT_SYMBOL(cdns_set_sdw_stream);
+static struct sdw_cdns_pdi *cdns_find_pdi(struct sdw_cdns *cdns,
unsigned int num, struct sdw_cdns_pdi *pdi)
+{
- int i;
- for (i = 0; i < num; i++) {
if (pdi[i].assigned == true)
continue;
pdi[i].assigned = true;
return &pdi[i];
- }
- return NULL;
+}
+/**
- sdw_cdns_config_stream: Configure a stream
- @cdns: Cadence instance
- @port: Cadence data port
- @ch: Channel count
- @dir: Data direction
- @pdi: PDI to be used
- */
+void sdw_cdns_config_stream(struct sdw_cdns *cdns,
struct sdw_cdns_port *port,
u32 ch, u32 dir, struct sdw_cdns_pdi *pdi)
+{
- u32 offset, val = 0;
- if (dir == SDW_DATA_DIR_RX)
val = CDNS_PORTCTRL_DIRN;
- offset = CDNS_PORTCTRL + port->num * CDNS_PORT_OFFSET;
- cdns_updatel(cdns, offset, CDNS_PORTCTRL_DIRN, val);
- val = port->num;
- val |= ((1 << ch) - 1) << SDW_REG_SHIFT(CDNS_PDI_CONFIG_CHANNEL);
- cdns_writel(cdns, CDNS_PDI_CONFIG(pdi->num), val);
+} +EXPORT_SYMBOL(sdw_cdns_config_stream);
+static int cdns_get_pdi(struct sdw_cdns *cdns,
struct sdw_cdns_pdi *pdi,
unsigned int num, u32 ch)
+{
- int i, pdis = 0;
- u32 ch_count = ch;
redundant variable without added value...
- for (i = 0; i < num; i++) {
if (pdi[i].assigned == true)
continue;
if (pdi[i].ch_count < ch_count)
ch_count -= pdi[i].ch_count;
else
ch_count = 0;
pdis++;
if (!ch_count)
break;
- }
- if (ch_count)
return 0;
- return pdis;
+}
+/**
- sdw_cdns_get_stream: Get stream information
- @cdns: Cadence instance
- @stream: Stream to be allocated
- @ch: Channel count
- @dir: Data direction
- */
+int sdw_cdns_get_stream(struct sdw_cdns *cdns,
struct sdw_cdns_streams *stream,
u32 ch, u32 dir)
+{
- int pdis = 0;
- if (dir == SDW_DATA_DIR_RX)
pdis = cdns_get_pdi(cdns, stream->in, stream->num_in, ch);
- else
pdis = cdns_get_pdi(cdns, stream->out, stream->num_out, ch);
- /* check if we found PDI, else find in bi-directional */
- if (!pdis)
pdis = cdns_get_pdi(cdns, stream->bd, stream->num_bd, ch);
- return pdis;
+} +EXPORT_SYMBOL(sdw_cdns_get_stream);
+/**
- sdw_cdns_alloc_stream: Allocate a stream
- @cdns: Cadence instance
- @stream: Stream to be allocated
- @port: Cadence data port
- @ch: Channel count
- @dir: Data direction
- */
+int sdw_cdns_alloc_stream(struct sdw_cdns *cdns,
struct sdw_cdns_streams *stream,
struct sdw_cdns_port *port, u32 ch, u32 dir)
+{
- struct sdw_cdns_pdi *pdi = NULL;
- if (dir == SDW_DATA_DIR_RX)
pdi = cdns_find_pdi(cdns, stream->num_in, stream->in);
- else
pdi = cdns_find_pdi(cdns, stream->num_out, stream->out);
- /* check if we found a PDI, else find in bi-directional */
- if (!pdi)
pdi = cdns_find_pdi(cdns, stream->num_bd, stream->bd);
- if (!pdi)
return -EIO;
- port->pdi = pdi;
- pdi->l_ch_num = 0;
- pdi->h_ch_num = ch - 1;
- pdi->dir = dir;
- pdi->ch_count = ch;
- return 0;
+} +EXPORT_SYMBOL(sdw_cdns_alloc_stream);
can you clarify the difference between _get_pdi and _find_pdi and alloc_stream/get_stream.
It's pretty confusing.
+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 98a17f57918f..eb902b19c5a4 100644 --- a/drivers/soundwire/cadence_master.h +++ b/drivers/soundwire/cadence_master.h @@ -1,5 +1,6 @@ // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) // Copyright(c) 2015-17 Intel Corporation. +#include <sound/soc.h>
#ifndef __SDW_CADENCE_H #define __SDW_CADENCE_H @@ -91,6 +92,26 @@ struct sdw_cdns_stream_config { };
/**
- struct sdw_cdns_dma_data: Cadence DMA data
- @name: SoundWire stream name
- @nr_ports: Number of ports
- @port: Ports
- @bus: Bus handle
- @stream_type: Stream type
- @link_id: Master link id
- */
+struct sdw_cdns_dma_data {
- char *name;
- struct sdw_stream_runtime *stream;
- int nr_ports;
- struct sdw_cdns_port **port;
- struct sdw_bus *bus;
- enum sdw_stream_type stream_type;
- int link_id;
+};
+/**
- struct sdw_cdns - Cadence driver context
- @dev: Linux device
- @bus: Bus handle
@@ -142,6 +163,25 @@ int sdw_cdns_pdi_init(struct sdw_cdns *cdns, struct sdw_cdns_stream_config config); int sdw_cdns_enable_interrupt(struct sdw_cdns *cdns);
+int sdw_cdns_get_stream(struct sdw_cdns *cdns,
struct sdw_cdns_streams *stream,
u32 ch, u32 dir);
+int sdw_cdns_alloc_stream(struct sdw_cdns *cdns,
struct sdw_cdns_streams *stream,
struct sdw_cdns_port *port, u32 ch, u32 dir);
+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,
void *stream, int direction);
+enum sdw_command_response +cdns_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num);
- enum sdw_command_response cdns_xfer_msg(struct sdw_bus *bus, struct sdw_msg *msg);
@@ -153,4 +193,7 @@ enum sdw_command_response cdns_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num);
int cdns_bus_conf(struct sdw_bus *bus, struct sdw_bus_params *params);
+int cdns_set_sdw_stream(struct snd_soc_dai *dai,
#endif /* __SDW_CADENCE_H */void *stream, bool pcm, int direction);