Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions drivers/soundwire/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -794,22 +794,23 @@ static int sdw_assign_device_num(struct sdw_slave *slave)
return 0;
}

void sdw_extract_slave_id(struct sdw_bus *bus,
u64 addr, struct sdw_slave_id *id)
void sdw_extract_slave_id(u64 addr, struct sdw_slave_id *id)
{
dev_dbg(bus->dev, "SDW Slave Addr: %llx\n", addr);

id->sdw_version = SDW_VERSION(addr);
id->unique_id = SDW_UNIQUE_ID(addr);
id->mfg_id = SDW_MFG_ID(addr);
id->part_id = SDW_PART_ID(addr);
id->class_id = SDW_CLASS_ID(addr);
}
EXPORT_SYMBOL(sdw_extract_slave_id);

dev_dbg(bus->dev,
void sdw_debug_log_slave_id(struct device *dev, const struct sdw_slave_id *id)
{
dev_dbg(dev,
"SDW Slave class_id 0x%02x, mfg_id 0x%04x, part_id 0x%04x, unique_id 0x%x, version 0x%x\n",
id->class_id, id->mfg_id, id->part_id, id->unique_id, id->sdw_version);
}
EXPORT_SYMBOL(sdw_extract_slave_id);
EXPORT_SYMBOL(sdw_debug_log_slave_id);

bool is_clock_scaling_supported_by_slave(struct sdw_slave *slave)
{
Expand Down Expand Up @@ -862,7 +863,8 @@ static int sdw_program_device_num(struct sdw_bus *bus, bool *programmed)
((u64)buf[2] << 24) | ((u64)buf[1] << 32) |
((u64)buf[0] << 40);

sdw_extract_slave_id(bus, addr, &id);
sdw_extract_slave_id(addr, &id);
sdw_debug_log_slave_id(bus->dev, &id);

found = false;
/* Now compare with entries */
Expand Down
2 changes: 0 additions & 2 deletions drivers/soundwire/bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ static inline int sdw_acpi_find_slaves(struct sdw_bus *bus)
#endif

int sdw_of_find_slaves(struct sdw_bus *bus);
void sdw_extract_slave_id(struct sdw_bus *bus,
u64 addr, struct sdw_slave_id *id);
int sdw_slave_add(struct sdw_bus *bus, struct sdw_slave_id *id,
struct fwnode_handle *fwnode);
int sdw_master_device_add(struct sdw_bus *bus, struct device *parent,
Expand Down
3 changes: 2 additions & 1 deletion drivers/soundwire/qcom.c
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,8 @@ static int qcom_swrm_enumerate(struct sdw_bus *bus)
((u64)buf1[2] << 24) | ((u64)buf1[1] << 32) |
((u64)buf1[0] << 40);

sdw_extract_slave_id(bus, addr, &id);
sdw_extract_slave_id(addr, &id);
sdw_debug_log_slave_id(bus->dev, &id);
found = false;
ctrl->clock_stop_not_supported = false;
/* Now compare with entries */
Expand Down
3 changes: 2 additions & 1 deletion drivers/soundwire/slave.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ static bool find_slave(struct sdw_bus *bus,
if (link_id != bus->link_id)
return false;

sdw_extract_slave_id(bus, addr, id);
sdw_extract_slave_id(addr, id);
sdw_debug_log_slave_id(bus->dev, id);

return true;
}
Expand Down
12 changes: 11 additions & 1 deletion include/linux/soundwire/sdw.h
Original file line number Diff line number Diff line change
Expand Up @@ -1089,13 +1089,15 @@ int sdw_bus_clk_stop(struct sdw_bus *bus);
int sdw_bus_exit_clk_stop(struct sdw_bus *bus);

int sdw_compare_devid(struct sdw_slave *slave, struct sdw_slave_id id);
void sdw_extract_slave_id(struct sdw_bus *bus, u64 addr, struct sdw_slave_id *id);
void sdw_extract_slave_id(u64 addr, struct sdw_slave_id *id);
bool is_clock_scaling_supported_by_slave(struct sdw_slave *slave);

int sdw_bpt_send_async(struct sdw_bus *bus, struct sdw_slave *slave, struct sdw_bpt_msg *msg);
int sdw_bpt_wait(struct sdw_bus *bus, struct sdw_slave *slave, struct sdw_bpt_msg *msg);
int sdw_bpt_send_sync(struct sdw_bus *bus, struct sdw_slave *slave, struct sdw_bpt_msg *msg);

void sdw_debug_log_slave_id(struct device *dev, const struct sdw_slave_id *id);

#if IS_ENABLED(CONFIG_SOUNDWIRE)

int sdw_stream_add_slave(struct sdw_slave *slave,
Expand Down Expand Up @@ -1216,6 +1218,14 @@ static inline int sdw_update_no_pm(struct sdw_slave *slave, u32 addr, u8 mask, u
return -EINVAL;
}

static inline void sdw_extract_slave_id(u64 addr, struct sdw_slave_id *id)
{
}

static inline void sdw_debug_log_slave_id(struct device *dev, const struct sdw_slave_id *id)
{
}

#endif /* CONFIG_SOUNDWIRE */

/**
Expand Down
4 changes: 4 additions & 0 deletions include/sound/soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,10 @@ struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
const char *driver_name);
struct snd_soc_component *snd_soc_lookup_component_by_name(const char *component_name);

typedef int (*snd_soc_component_walk_fn)(struct snd_soc_component *component, void *context);
struct snd_soc_component *snd_soc_lookup_component_walk(snd_soc_component_walk_fn cb,
void *context);

int soc_new_pcm(struct snd_soc_pcm_runtime *rtd);
#ifdef CONFIG_SND_SOC_COMPRESS
int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd);
Expand Down
3 changes: 3 additions & 0 deletions include/sound/soc_sdw_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ int asoc_sdw_hw_params(struct snd_pcm_substream *substream,
int asoc_sdw_hw_free(struct snd_pcm_substream *substream);
void asoc_sdw_shutdown(struct snd_pcm_substream *substream);

struct snd_soc_component *asoc_sdw_find_component(const struct asoc_sdw_dai_info *dai_info,
const struct snd_soc_acpi_link_adr *adr_link,
int adr_index);
const char *asoc_sdw_get_codec_name(struct device *dev,
const struct asoc_sdw_dai_info *dai_info,
const struct snd_soc_acpi_link_adr *adr_link,
Expand Down
73 changes: 59 additions & 14 deletions sound/soc/sdw_utils/soc_sdw_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1635,6 +1635,50 @@ static bool asoc_sdw_is_unique_device(const struct snd_soc_acpi_link_adr *adr_li
return true;
}

struct asoc_sdw_find_info {
const char *subname;
struct sdw_slave_id id;
};

static int asoc_sdw_find_component_cb(struct snd_soc_component *component, void *context)
{
const struct asoc_sdw_find_info *info = context;
struct device *dev = component->dev;

if (!is_sdw_slave(dev)) {
dev = component->dev->parent;
if (!dev || !is_sdw_slave(dev))
return 0;
}

if (sdw_compare_devid(dev_to_sdw_dev(dev), info->id) != 0)
return 0;

if (info->subname && !strstr(component->name, info->subname))
return 0;

return 1;
}

struct snd_soc_component *asoc_sdw_find_component(const struct asoc_sdw_dai_info *dai_info,
const struct snd_soc_acpi_link_adr *adr_link,
int adr_index)
{
u64 adr = adr_link->adr_d[adr_index].adr;
struct asoc_sdw_find_info info;
struct snd_soc_component *component;

sdw_extract_slave_id(adr, &info.id);
info.subname = dai_info->codec_name;

component = snd_soc_lookup_component_walk(asoc_sdw_find_component_cb, &info);
if (IS_ERR(component))
return NULL;

return component;
}
EXPORT_SYMBOL_NS(asoc_sdw_find_component, "SND_SOC_SDW_UTILS");

static const char *_asoc_sdw_get_codec_name(struct device *dev,
const struct snd_soc_acpi_link_adr *adr_link,
int adr_index)
Expand All @@ -1661,22 +1705,23 @@ const char *asoc_sdw_get_codec_name(struct device *dev,
const struct snd_soc_acpi_link_adr *adr_link,
int adr_index)
{
if (dai_info->codec_name) {
struct snd_soc_component *component;

component = snd_soc_lookup_component_by_name(dai_info->codec_name);
if (component) {
dev_dbg(dev, "%s found component %s for codec_name %s\n",
__func__, component->name, dai_info->codec_name);
return devm_kstrdup(dev, component->name, GFP_KERNEL);
} else {
dev_dbg(dev, "%s component %s is not registered yet\n",
__func__, dai_info->codec_name);
return ERR_PTR(-EPROBE_DEFER);
}
struct snd_soc_component *component;

component = asoc_sdw_find_component(dai_info, adr_link, adr_index);
if (!component) {
dev_dbg(dev, "%s component for addr %013llx subname '%s' is not registered yet\n",
__func__,
adr_link->adr_d[adr_index].adr,
dai_info->codec_name);
return ERR_PTR(-EPROBE_DEFER);
}

return _asoc_sdw_get_codec_name(dev, adr_link, adr_index);
dev_dbg(dev, "%s found component %s for adr %013llx subname '%s'\n",
__func__, component->name,
adr_link->adr_d[adr_index].adr,
dai_info->codec_name);

return devm_kstrdup(dev, component->name, GFP_KERNEL);
}
EXPORT_SYMBOL_NS(asoc_sdw_get_codec_name, "SND_SOC_SDW_UTILS");

Expand Down
33 changes: 33 additions & 0 deletions sound/soc/soc-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,39 @@ struct snd_soc_component *snd_soc_lookup_component_by_name(const char *component
}
EXPORT_SYMBOL_GPL(snd_soc_lookup_component_by_name);

/**
* snd_soc_lookup_component_walk - component lookup using callback.
* @cb: function to call for each component.
* @context: caller-defined value to be passed to callback function. Can
* be NULL.
*
* Iterate over snd_soc_component items, calling @cb for each, until @cb
* returns a non-zero value. The @context pointer is a value defined by the
* caller and is passed to @cb.
*
* Return: struct snd_soc_component* if @cb returned >0.
* ERR_PTR(-ENOENT) if @cb returned 0 on every call.
* ERR_PTR of value returned by @cb if @cb returned <0.
*/
struct snd_soc_component *snd_soc_lookup_component_walk(snd_soc_component_walk_fn cb,
void *context)
{
struct snd_soc_component *component;
int ret;

guard(mutex)(&client_mutex);
for_each_component(component) {
ret = (cb)(component, context);
if (ret > 0)
return component;
if (ret < 0)
return ERR_PTR(ret);
}

return ERR_PTR(-ENOENT);
}
EXPORT_SYMBOL_GPL(snd_soc_lookup_component_walk);

struct snd_soc_pcm_runtime
*snd_soc_get_pcm_runtime(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_link)
Expand Down
Loading