summaryrefslogtreecommitdiff
path: root/drivers/soundwire
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/soundwire')
-rw-r--r--drivers/soundwire/cadence_master.c50
-rw-r--r--drivers/soundwire/cadence_master.h9
-rw-r--r--drivers/soundwire/dmi-quirks.c8
-rw-r--r--drivers/soundwire/intel.c111
-rw-r--r--drivers/soundwire/qcom.c25
5 files changed, 114 insertions, 89 deletions
diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c
index 93929f19d083..a1de363eba3f 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -1707,47 +1707,45 @@ int cdns_set_sdw_stream(struct snd_soc_dai *dai,
void *stream, int direction)
{
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
- struct sdw_cdns_dma_data *dma;
+ struct sdw_cdns_dai_runtime *dai_runtime;
+
+ dai_runtime = cdns->dai_runtime_array[dai->id];
if (stream) {
/* first paranoia check */
- if (direction == SNDRV_PCM_STREAM_PLAYBACK)
- dma = dai->playback_dma_data;
- else
- dma = dai->capture_dma_data;
-
- if (dma) {
+ if (dai_runtime) {
dev_err(dai->dev,
- "dma_data already allocated for dai %s\n",
+ "dai_runtime already allocated for dai %s\n",
dai->name);
return -EINVAL;
}
- /* allocate and set dma info */
- dma = kzalloc(sizeof(*dma), GFP_KERNEL);
- if (!dma)
+ /* allocate and set dai_runtime info */
+ dai_runtime = kzalloc(sizeof(*dai_runtime), GFP_KERNEL);
+ if (!dai_runtime)
return -ENOMEM;
- dma->stream_type = SDW_STREAM_PCM;
+ dai_runtime->stream_type = SDW_STREAM_PCM;
- dma->bus = &cdns->bus;
- dma->link_id = cdns->instance;
+ dai_runtime->bus = &cdns->bus;
+ dai_runtime->link_id = cdns->instance;
- dma->stream = stream;
+ dai_runtime->stream = stream;
+ dai_runtime->direction = direction;
- if (direction == SNDRV_PCM_STREAM_PLAYBACK)
- dai->playback_dma_data = dma;
- else
- dai->capture_dma_data = dma;
+ cdns->dai_runtime_array[dai->id] = dai_runtime;
} else {
- /* for NULL stream we release allocated dma_data */
- if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
- kfree(dai->playback_dma_data);
- dai->playback_dma_data = NULL;
- } else {
- kfree(dai->capture_dma_data);
- dai->capture_dma_data = NULL;
+ /* second paranoia check */
+ if (!dai_runtime) {
+ dev_err(dai->dev,
+ "dai_runtime not allocated for dai %s\n",
+ dai->name);
+ return -EINVAL;
}
+
+ /* for NULL stream we release allocated dai_runtime */
+ kfree(dai_runtime);
+ cdns->dai_runtime_array[dai->id] = NULL;
}
return 0;
}
diff --git a/drivers/soundwire/cadence_master.h b/drivers/soundwire/cadence_master.h
index ca9e805bab88..0434d70d4b1f 100644
--- a/drivers/soundwire/cadence_master.h
+++ b/drivers/soundwire/cadence_master.h
@@ -70,7 +70,7 @@ struct sdw_cdns_stream_config {
};
/**
- * struct sdw_cdns_dma_data: Cadence DMA data
+ * struct sdw_cdns_dai_runtime: Cadence DAI runtime data
*
* @name: SoundWire stream name
* @stream: stream runtime
@@ -81,8 +81,9 @@ struct sdw_cdns_stream_config {
* @hw_params: hw_params to be applied in .prepare step
* @suspended: status set when suspended, to be used in .prepare
* @paused: status set in .trigger, to be used in suspend
+ * @direction: stream direction
*/
-struct sdw_cdns_dma_data {
+struct sdw_cdns_dai_runtime {
char *name;
struct sdw_stream_runtime *stream;
struct sdw_cdns_pdi *pdi;
@@ -92,6 +93,7 @@ struct sdw_cdns_dma_data {
struct snd_pcm_hw_params *hw_params;
bool suspended;
bool paused;
+ int direction;
};
/**
@@ -108,6 +110,7 @@ struct sdw_cdns_dma_data {
* @registers: Cadence registers
* @link_up: Link status
* @msg_count: Messages sent on bus
+ * @dai_runtime_array: runtime context for each allocated DAI.
*/
struct sdw_cdns {
struct device *dev;
@@ -135,6 +138,8 @@ struct sdw_cdns {
struct work_struct work;
struct list_head list;
+
+ struct sdw_cdns_dai_runtime **dai_runtime_array;
};
#define bus_to_cdns(_bus) container_of(_bus, struct sdw_cdns, bus)
diff --git a/drivers/soundwire/dmi-quirks.c b/drivers/soundwire/dmi-quirks.c
index f81cdd83ec26..7969881f126d 100644
--- a/drivers/soundwire/dmi-quirks.c
+++ b/drivers/soundwire/dmi-quirks.c
@@ -91,6 +91,14 @@ static const struct dmi_system_id adr_remap_quirk_table[] = {
.driver_data = (void *)intel_tgl_bios,
},
{
+ /* quirk used for NUC15 LAPBC710 skew */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "LAPBC710"),
+ },
+ .driver_data = (void *)intel_tgl_bios,
+ },
+ {
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc"),
DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "0A3E")
diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 8c76541d553f..b9cb7e31ddb3 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -824,15 +824,15 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
{
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
struct sdw_intel *sdw = cdns_to_intel(cdns);
- struct sdw_cdns_dma_data *dma;
+ struct sdw_cdns_dai_runtime *dai_runtime;
struct sdw_cdns_pdi *pdi;
struct sdw_stream_config sconfig;
struct sdw_port_config *pconfig;
int ch, dir;
int ret;
- dma = snd_soc_dai_get_dma_data(dai, substream);
- if (!dma)
+ dai_runtime = cdns->dai_runtime_array[dai->id];
+ if (!dai_runtime)
return -EIO;
ch = params_channels(params);
@@ -854,10 +854,10 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
sdw_cdns_config_stream(cdns, ch, dir, pdi);
/* store pdi and hw_params, may be needed in prepare step */
- dma->paused = false;
- dma->suspended = false;
- dma->pdi = pdi;
- dma->hw_params = params;
+ dai_runtime->paused = false;
+ dai_runtime->suspended = false;
+ dai_runtime->pdi = pdi;
+ dai_runtime->hw_params = params;
/* Inform DSP about PDI stream number */
ret = intel_params_stream(sdw, substream->stream, dai, params,
@@ -869,7 +869,7 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
sconfig.direction = dir;
sconfig.ch_count = ch;
sconfig.frame_rate = params_rate(params);
- sconfig.type = dma->stream_type;
+ sconfig.type = dai_runtime->stream_type;
sconfig.bps = snd_pcm_format_width(params_format(params));
@@ -884,7 +884,7 @@ static int intel_hw_params(struct snd_pcm_substream *substream,
pconfig->ch_mask = (1 << ch) - 1;
ret = sdw_stream_add_master(&cdns->bus, &sconfig,
- pconfig, 1, dma->stream);
+ pconfig, 1, dai_runtime->stream);
if (ret)
dev_err(cdns->dev, "add master to stream failed:%d\n", ret);
@@ -898,19 +898,19 @@ static int intel_prepare(struct snd_pcm_substream *substream,
{
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
struct sdw_intel *sdw = cdns_to_intel(cdns);
- struct sdw_cdns_dma_data *dma;
+ struct sdw_cdns_dai_runtime *dai_runtime;
int ch, dir;
int ret = 0;
- dma = snd_soc_dai_get_dma_data(dai, substream);
- if (!dma) {
- dev_err(dai->dev, "failed to get dma data in %s\n",
+ dai_runtime = cdns->dai_runtime_array[dai->id];
+ if (!dai_runtime) {
+ dev_err(dai->dev, "failed to get dai runtime in %s\n",
__func__);
return -EIO;
}
- if (dma->suspended) {
- dma->suspended = false;
+ if (dai_runtime->suspended) {
+ dai_runtime->suspended = false;
/*
* .prepare() is called after system resume, where we
@@ -921,21 +921,21 @@ static int intel_prepare(struct snd_pcm_substream *substream,
*/
/* configure stream */
- ch = params_channels(dma->hw_params);
+ ch = params_channels(dai_runtime->hw_params);
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
dir = SDW_DATA_DIR_RX;
else
dir = SDW_DATA_DIR_TX;
- intel_pdi_shim_configure(sdw, dma->pdi);
- intel_pdi_alh_configure(sdw, dma->pdi);
- sdw_cdns_config_stream(cdns, ch, dir, dma->pdi);
+ intel_pdi_shim_configure(sdw, dai_runtime->pdi);
+ intel_pdi_alh_configure(sdw, dai_runtime->pdi);
+ sdw_cdns_config_stream(cdns, ch, dir, dai_runtime->pdi);
/* Inform DSP about PDI stream number */
ret = intel_params_stream(sdw, substream->stream, dai,
- dma->hw_params,
+ dai_runtime->hw_params,
sdw->instance,
- dma->pdi->intel_alh_id);
+ dai_runtime->pdi->intel_alh_id);
}
return ret;
@@ -946,11 +946,11 @@ intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
{
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
struct sdw_intel *sdw = cdns_to_intel(cdns);
- struct sdw_cdns_dma_data *dma;
+ struct sdw_cdns_dai_runtime *dai_runtime;
int ret;
- dma = snd_soc_dai_get_dma_data(dai, substream);
- if (!dma)
+ dai_runtime = cdns->dai_runtime_array[dai->id];
+ if (!dai_runtime)
return -EIO;
/*
@@ -959,10 +959,10 @@ intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
* DEPREPARED for the first cpu-dai and to RELEASED for the last
* cpu-dai.
*/
- ret = sdw_stream_remove_master(&cdns->bus, dma->stream);
+ ret = sdw_stream_remove_master(&cdns->bus, dai_runtime->stream);
if (ret < 0) {
dev_err(dai->dev, "remove master from stream %s failed: %d\n",
- dma->stream->name, ret);
+ dai_runtime->stream->name, ret);
return ret;
}
@@ -972,8 +972,8 @@ intel_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
return ret;
}
- dma->hw_params = NULL;
- dma->pdi = NULL;
+ dai_runtime->hw_params = NULL;
+ dai_runtime->pdi = NULL;
return 0;
}
@@ -996,17 +996,14 @@ static int intel_pcm_set_sdw_stream(struct snd_soc_dai *dai,
static void *intel_get_sdw_stream(struct snd_soc_dai *dai,
int direction)
{
- struct sdw_cdns_dma_data *dma;
-
- if (direction == SNDRV_PCM_STREAM_PLAYBACK)
- dma = dai->playback_dma_data;
- else
- dma = dai->capture_dma_data;
+ struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
+ struct sdw_cdns_dai_runtime *dai_runtime;
- if (!dma)
+ dai_runtime = cdns->dai_runtime_array[dai->id];
+ if (!dai_runtime)
return ERR_PTR(-EINVAL);
- return dma->stream;
+ return dai_runtime->stream;
}
static int intel_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
@@ -1014,7 +1011,7 @@ static int intel_trigger(struct snd_pcm_substream *substream, int cmd, struct sn
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
struct sdw_intel *sdw = cdns_to_intel(cdns);
struct sdw_intel_link_res *res = sdw->link_res;
- struct sdw_cdns_dma_data *dma;
+ struct sdw_cdns_dai_runtime *dai_runtime;
int ret = 0;
/*
@@ -1025,9 +1022,9 @@ static int intel_trigger(struct snd_pcm_substream *substream, int cmd, struct sn
if (res->ops && res->ops->trigger)
res->ops->trigger(dai, cmd, substream->stream);
- dma = snd_soc_dai_get_dma_data(dai, substream);
- if (!dma) {
- dev_err(dai->dev, "failed to get dma data in %s\n",
+ dai_runtime = cdns->dai_runtime_array[dai->id];
+ if (!dai_runtime) {
+ dev_err(dai->dev, "failed to get dai runtime in %s\n",
__func__);
return -EIO;
}
@@ -1042,17 +1039,17 @@ static int intel_trigger(struct snd_pcm_substream *substream, int cmd, struct sn
* the .trigger callback is used to track the suspend case only.
*/
- dma->suspended = true;
+ dai_runtime->suspended = true;
ret = intel_free_stream(sdw, substream->stream, dai, sdw->instance);
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- dma->paused = true;
+ dai_runtime->paused = true;
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- dma->paused = false;
+ dai_runtime->paused = false;
break;
default:
break;
@@ -1091,27 +1088,21 @@ static int intel_component_dais_suspend(struct snd_soc_component *component)
for_each_component_dais(component, dai) {
struct sdw_cdns *cdns = snd_soc_dai_get_drvdata(dai);
struct sdw_intel *sdw = cdns_to_intel(cdns);
- struct sdw_cdns_dma_data *dma;
- int stream;
+ struct sdw_cdns_dai_runtime *dai_runtime;
int ret;
- dma = dai->playback_dma_data;
- stream = SNDRV_PCM_STREAM_PLAYBACK;
- if (!dma) {
- dma = dai->capture_dma_data;
- stream = SNDRV_PCM_STREAM_CAPTURE;
- }
+ dai_runtime = cdns->dai_runtime_array[dai->id];
- if (!dma)
+ if (!dai_runtime)
continue;
- if (dma->suspended)
+ if (dai_runtime->suspended)
continue;
- if (dma->paused) {
- dma->suspended = true;
+ if (dai_runtime->paused) {
+ dai_runtime->suspended = true;
- ret = intel_free_stream(sdw, stream, dai, sdw->instance);
+ ret = intel_free_stream(sdw, dai_runtime->direction, dai, sdw->instance);
if (ret < 0)
return ret;
}
@@ -1178,6 +1169,7 @@ static int intel_create_dai(struct sdw_cdns *cdns,
static int intel_register_dai(struct sdw_intel *sdw)
{
+ struct sdw_cdns_dai_runtime **dai_runtime_array;
struct sdw_cdns_stream_config config;
struct sdw_cdns *cdns = &sdw->cdns;
struct sdw_cdns_streams *stream;
@@ -1195,6 +1187,13 @@ static int intel_register_dai(struct sdw_intel *sdw)
/* DAIs are created based on total number of PDIs supported */
num_dai = cdns->pcm.num_pdi;
+ dai_runtime_array = devm_kcalloc(cdns->dev, num_dai,
+ sizeof(struct sdw_cdns_dai_runtime *),
+ GFP_KERNEL);
+ if (!dai_runtime_array)
+ return -ENOMEM;
+ cdns->dai_runtime_array = dai_runtime_array;
+
dais = devm_kcalloc(cdns->dev, num_dai, sizeof(*dais), GFP_KERNEL);
if (!dais)
return -ENOMEM;
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
index cee2b2223141..335424870290 100644
--- a/drivers/soundwire/qcom.c
+++ b/drivers/soundwire/qcom.c
@@ -25,6 +25,8 @@
#define SWRM_COMP_SW_RESET 0x008
#define SWRM_COMP_STATUS 0x014
+#define SWRM_LINK_MANAGER_EE 0x018
+#define SWRM_EE_CPU 1
#define SWRM_FRM_GEN_ENABLED BIT(0)
#define SWRM_COMP_HW_VERSION 0x00
#define SWRM_COMP_CFG_ADDR 0x04
@@ -104,7 +106,6 @@
#define SWRM_REG_VAL_PACK(data, dev, id, reg) \
((reg) | ((id) << 16) | ((dev) << 20) | ((data) << 24))
-#define SWRM_SPECIAL_CMD_ID 0xF
#define MAX_FREQ_NUM 1
#define TIMEOUT_MS 100
#define QCOM_SWRM_MAX_RD_LEN 0x1
@@ -694,7 +695,14 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
u32p_replace_bits(&val, SWRM_DEF_CMD_NO_PINGS, SWRM_MCP_CFG_MAX_NUM_OF_CMD_NO_PINGS_BMSK);
ctrl->reg_write(ctrl, SWRM_MCP_CFG_ADDR, val);
- ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START);
+ if (ctrl->version >= 0x01070000) {
+ ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU);
+ ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL,
+ SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU);
+ } else {
+ ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START);
+ }
+
/* Configure number of retries of a read/write cmd */
if (ctrl->version > 0x01050001) {
/* Only for versions >= 1.5.1 */
@@ -1331,8 +1339,8 @@ static int qcom_swrm_probe(struct platform_device *pdev)
}
if (data->sw_clk_gate_required) {
- ctrl->audio_cgcr = devm_reset_control_get_exclusive(dev, "swr_audio_cgcr");
- if (IS_ERR_OR_NULL(ctrl->audio_cgcr)) {
+ ctrl->audio_cgcr = devm_reset_control_get_optional_exclusive(dev, "swr_audio_cgcr");
+ if (IS_ERR(ctrl->audio_cgcr)) {
dev_err(dev, "Failed to get cgcr reset ctrl required for SW gating\n");
ret = PTR_ERR(ctrl->audio_cgcr);
goto err_init;
@@ -1519,7 +1527,13 @@ static int __maybe_unused swrm_runtime_resume(struct device *dev)
} else {
reset_control_reset(ctrl->audio_cgcr);
- ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START);
+ if (ctrl->version >= 0x01070000) {
+ ctrl->reg_write(ctrl, SWRM_LINK_MANAGER_EE, SWRM_EE_CPU);
+ ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL,
+ SWRM_MCP_BUS_CLK_START << SWRM_EE_CPU);
+ } else {
+ ctrl->reg_write(ctrl, SWRM_MCP_BUS_CTRL, SWRM_MCP_BUS_CLK_START);
+ }
ctrl->reg_write(ctrl, SWRM_INTERRUPT_CLEAR,
SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET);
@@ -1583,6 +1597,7 @@ static const struct of_device_id qcom_swrm_of_match[] = {
{ .compatible = "qcom,soundwire-v1.3.0", .data = &swrm_v1_3_data },
{ .compatible = "qcom,soundwire-v1.5.1", .data = &swrm_v1_5_data },
{ .compatible = "qcom,soundwire-v1.6.0", .data = &swrm_v1_6_data },
+ { .compatible = "qcom,soundwire-v1.7.0", .data = &swrm_v1_5_data },
{/* sentinel */},
};