Skip to content

Commit 264d3d7

Browse files
charleskeepaxbroonie
authored andcommitted
ASoC: SDCA: Add a helper to get the SoundWire port number
Add a helper function to extract the SoundWire hardware port number from the SDCA DataPort Selector Control. Typically this would be called from hw_params() and used to call sdw_stream_add_slave(). Signed-off-by: Charles Keepax <[email protected]> Reviewed-by: Pierre-Louis Bossart <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 7b0d60d commit 264d3d7

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

include/sound/sdca_asoc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,8 @@ int sdca_asoc_set_constraints(struct device *dev, struct regmap *regmap,
4848
struct snd_soc_dai *dai);
4949
void sdca_asoc_free_constraints(struct snd_pcm_substream *substream,
5050
struct snd_soc_dai *dai);
51+
int sdca_asoc_get_port(struct device *dev, struct regmap *regmap,
52+
struct sdca_function_data *function,
53+
struct snd_soc_dai *dai);
5154

5255
#endif // __SDCA_ASOC_H__

include/sound/sdca_function.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,14 @@ enum sdca_usage_range {
185185
SDCA_USAGE_NCOLS = 7,
186186
};
187187

188+
/**
189+
* enum sdca_dataport_selector_range - Column definitions for DataPort_Selector
190+
*/
191+
enum sdca_dataport_selector_range {
192+
SDCA_DATAPORT_SELECTOR_NCOLS = 16,
193+
SDCA_DATAPORT_SELECTOR_NROWS = 4,
194+
};
195+
188196
/**
189197
* enum sdca_mu_controls - SDCA Controls for Mixer Unit
190198
*

sound/soc/sdca/sdca_asoc.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/regmap.h>
2020
#include <linux/soundwire/sdw_registers.h>
2121
#include <linux/string_helpers.h>
22+
#include <linux/types.h>
2223
#include <sound/control.h>
2324
#include <sound/pcm.h>
2425
#include <sound/sdca.h>
@@ -1368,3 +1369,77 @@ void sdca_asoc_free_constraints(struct snd_pcm_substream *substream,
13681369
kfree(constraint);
13691370
}
13701371
EXPORT_SYMBOL_NS(sdca_asoc_free_constraints, "SND_SOC_SDCA");
1372+
1373+
/**
1374+
* sdca_asoc_get_port - return SoundWire port for a DAI
1375+
* @dev: Pointer to the device, used for error messages.
1376+
* @regmap: Pointer to the Function register map.
1377+
* @function: Pointer to the Function information.
1378+
* @dai: Pointer to the ASoC DAI.
1379+
*
1380+
* Typically called from hw_params().
1381+
*
1382+
* Return: Returns a positive port number on success, and a negative error
1383+
* code on failure.
1384+
*/
1385+
int sdca_asoc_get_port(struct device *dev, struct regmap *regmap,
1386+
struct sdca_function_data *function,
1387+
struct snd_soc_dai *dai)
1388+
{
1389+
struct sdca_entity *entity = &function->entities[dai->id];
1390+
struct sdca_control_range *range;
1391+
unsigned int reg, val;
1392+
int sel = -EINVAL;
1393+
int i, ret;
1394+
1395+
switch (entity->type) {
1396+
case SDCA_ENTITY_TYPE_IT:
1397+
sel = SDCA_CTL_IT_DATAPORT_SELECTOR;
1398+
break;
1399+
case SDCA_ENTITY_TYPE_OT:
1400+
sel = SDCA_CTL_OT_DATAPORT_SELECTOR;
1401+
break;
1402+
default:
1403+
break;
1404+
}
1405+
1406+
if (sel < 0 || !entity->iot.is_dataport) {
1407+
dev_err(dev, "%s: port number only available for dataports\n",
1408+
entity->label);
1409+
return -EINVAL;
1410+
}
1411+
1412+
range = sdca_selector_find_range(dev, entity, sel, SDCA_DATAPORT_SELECTOR_NCOLS,
1413+
SDCA_DATAPORT_SELECTOR_NROWS);
1414+
if (!range)
1415+
return -EINVAL;
1416+
1417+
reg = SDW_SDCA_CTL(function->desc->adr, entity->id, sel, 0);
1418+
1419+
ret = regmap_read(regmap, reg, &val);
1420+
if (ret) {
1421+
dev_err(dev, "%s: failed to read dataport selector: %d\n",
1422+
entity->label, ret);
1423+
return ret;
1424+
}
1425+
1426+
for (i = 0; i < range->rows; i++) {
1427+
static const u8 port_mask = 0xF;
1428+
1429+
sel = sdca_range(range, val & port_mask, i);
1430+
1431+
/*
1432+
* FIXME: Currently only a single dataport is supported, so
1433+
* return the first one found, technically up to 4 dataports
1434+
* could be linked, but this is not yet supported.
1435+
*/
1436+
if (sel != 0xFF)
1437+
return sel;
1438+
1439+
val >>= hweight8(port_mask);
1440+
}
1441+
1442+
dev_err(dev, "%s: no dataport found\n", entity->label);
1443+
return -ENODEV;
1444+
}
1445+
EXPORT_SYMBOL_NS(sdca_asoc_get_port, "SND_SOC_SDCA");

0 commit comments

Comments
 (0)