Skip to content
Open
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
1 change: 1 addition & 0 deletions include/sound/sdca.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ enum sdca_quirk {
#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SDCA)

void sdca_lookup_functions(struct sdw_slave *slave);
int sdca_get_mic_count(struct sdw_slave *slave, struct sdca_function_desc *function);
void sdca_lookup_swft(struct sdw_slave *slave);
void sdca_lookup_interface_revision(struct sdw_slave *slave);
bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk);
Comment on lines 65 to 69
Expand Down
52 changes: 52 additions & 0 deletions sound/soc/intel/boards/sof_sdw.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
#include <linux/soundwire/sdw_type.h>
#include <linux/soundwire/sdw_intel.h>
#include <sound/core.h>
#include <sound/sdca.h>
#include <sound/sdca_function.h>
#include <sound/soc.h>
#include <sound/soc-acpi.h>
#include "sof_sdw_common.h"
#include "../../codecs/rt711.h"
Expand Down Expand Up @@ -900,6 +903,23 @@ static const struct snd_soc_ops sdw_ops = {

static const char * const type_strings[] = {"SimpleJack", "SmartAmp", "SmartMic"};

static struct sdw_slave *sof_sdw_get_peripheral_by_codec_name(const char *codec_name)
{
struct snd_soc_component *component;

component = snd_soc_lookup_component_by_name(codec_name);
if (!component)
return NULL;

if (is_sdw_slave(component->dev))
return dev_to_sdw_dev(component->dev);

if (component->dev->parent && is_sdw_slave(component->dev->parent))
return dev_to_sdw_dev(component->dev->parent);

return NULL;
}

static int create_sdw_dailink(struct snd_soc_card *card,
struct asoc_sdw_dailink *sof_dai,
struct snd_soc_dai_link **dai_links,
Expand Down Expand Up @@ -1011,6 +1031,37 @@ static int create_sdw_dailink(struct snd_soc_card *card,

codecs[j].name = sof_end->codec_name;
codecs[j].dai_name = sof_end->dai_info->dai_name;

if (sof_end->dai_info->dai_type == SOC_SDW_DAI_TYPE_MIC) {
struct sdw_slave *peripheral;
int sdw_mic_num;
int k;

peripheral = sof_sdw_get_peripheral_by_codec_name(sof_end->codec_name);
if (!peripheral) {
dev_warn(dev, "failed to get peripheral for codec %s\n",
sof_end->codec_name);
continue;
}

for (k = 0; k < peripheral->sdca_data.num_functions; k++) {
if (peripheral->sdca_data.function[k].type != SDCA_FUNCTION_TYPE_SMART_MIC)
continue;

sdw_mic_num = sdca_get_mic_count(peripheral, &peripheral->sdca_data.function[k]);
dev_dbg(dev, "%s mic num %d\n", sof_end->codec_name, sdw_mic_num);
if (sdw_mic_num > 0) {
char *tmp = name;
name = devm_kasprintf(dev, GFP_KERNEL, "%s-%dch", name, sdw_mic_num);
if (!name)
return -ENOMEM;

devm_kfree(dev, tmp);
}
}
Comment on lines +1047 to +1061

}

if (sof_end->dai_info->dai_type == SOC_SDW_DAI_TYPE_MIC &&
mach_params->dmic_num > 0) {
dev_warn(dev,
Expand Down Expand Up @@ -1582,3 +1633,4 @@ MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS("SND_SOC_INTEL_HDA_DSP_COMMON");
MODULE_IMPORT_NS("SND_SOC_SDW_UTILS");
MODULE_IMPORT_NS("SND_SOC_SDCA");
105 changes: 105 additions & 0 deletions sound/soc/sdca/sdca_functions.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,111 @@ void sdca_lookup_functions(struct sdw_slave *slave)
}
EXPORT_SYMBOL_NS(sdca_lookup_functions, "SND_SOC_SDCA");

int sdca_get_mic_count(struct sdw_slave *slave, struct sdca_function_desc *function)
{
struct fwnode_handle *function_node;
u32 *entity_list __free(kfree) = NULL;
u32 transducer_count = 0;
u32 terminal_type;
int num_entities;
int ret;
int i;

if (!function || !function->node)
return -EINVAL;

function_node = function->node;

num_entities = fwnode_property_count_u32(function_node,
"mipi-sdca-entity-id-list");
if (num_entities <= 0) {
dev_err(&slave->dev,
"%pfwP: no entity list found for function type %u\n",
function_node, function->type);
return -EINVAL;
}

entity_list = kcalloc(num_entities, sizeof(*entity_list), GFP_KERNEL);
if (!entity_list)
return -ENOMEM;

ret = fwnode_property_read_u32_array(function_node,
"mipi-sdca-entity-id-list",
entity_list, num_entities);
if (ret) {
dev_err(&slave->dev,
"%pfwP: failed to read entity id list for function type %u: %d\n",
function_node, function->type, ret);
return -EINVAL;
}
Comment on lines +235 to +239

for (i = 0; i < num_entities; i++) {
struct fwnode_handle *entity_node;
const char *entity_label = "<unknown>";
u32 entity_type;
char entity_property[SDCA_PROPERTY_LENGTH];

/* DisCo uses upper-case for hex numbers */
snprintf(entity_property, sizeof(entity_property),
"mipi-sdca-entity-id-0x%X-subproperties", entity_list[i]);

entity_node = fwnode_get_named_child_node(function_node, entity_property);
if (!entity_node) {
dev_dbg(&slave->dev, "%pfwP: missing entity node %s\n",
function_node, entity_property);
continue;
}

fwnode_property_read_string(entity_node, "mipi-sdca-entity-label",
&entity_label);

ret = fwnode_property_read_u32(entity_node, "mipi-sdca-entity-type",
&entity_type);
if (ret) {
dev_info(&slave->dev,
"SDCA function %s (type %u adr 0x%x): entity 0x%x label %s type missing\n",
function->name, function->type, function->adr,
entity_list[i], entity_label);
fwnode_handle_put(entity_node);
goto put_entity_node;
}
Comment on lines +264 to +270

dev_dbg(&slave->dev,
"SDCA function %s (type %u adr 0x%x): entity 0x%x label %s type 0x%x\n",
function->name, function->type, function->adr,
entity_list[i], entity_label, entity_type);

if (entity_type == SDCA_ENTITY_TYPE_IT) {
ret = fwnode_property_read_u32(entity_node,
"mipi-sdca-terminal-type",
&terminal_type);
if (ret)
goto put_entity_node;

if (terminal_type != SDCA_TERM_TYPE_MICROPHONE_TRANSDUCER &&
terminal_type != SDCA_TERM_TYPE_MICROPHONE_ARRAY_TRANSDUCER)
goto put_entity_node;

ret = fwnode_property_read_u32(entity_node,
"mipi-sdca-terminal-transducer-count",
&transducer_count);
if (ret)
goto put_entity_node;

dev_info(&slave->dev,
"SDCA function %s entity %s: iot mipi-sdca-terminal-type=%#x mipi-sdca-terminal-transducer-count=%u\n",
function->name, entity_label, terminal_type, transducer_count);
Comment on lines +294 to +296
break;
}

put_entity_node:
fwnode_handle_put(entity_node);
}

return transducer_count;
}
EXPORT_SYMBOL_NS(sdca_get_mic_count, "SND_SOC_SDCA");

struct raw_init_write {
__le32 addr;
u8 val;
Expand Down
Loading