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
20 changes: 15 additions & 5 deletions drivers/soundwire/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,13 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent,
bus->params.curr_dr_freq = bus->params.max_dr_freq;
bus->params.curr_bank = SDW_BANK0;
bus->params.next_bank = SDW_BANK1;
/*
* Set is_present = true by default. It will be set to false when no peripherals
* are attached on the bus.
*/
bus->is_present = true;

init_completion(&bus->enumeration_complete);
return 0;
Comment on lines +164 to 171
}
EXPORT_SYMBOL(sdw_bus_master_add);
Expand Down Expand Up @@ -309,12 +315,12 @@ int sdw_transfer(struct sdw_bus *bus, struct sdw_msg *msg)
* @bus: SDW bus
* @sync_delay: Delay before reading status
*/
void sdw_show_ping_status(struct sdw_bus *bus, bool sync_delay)
int sdw_show_ping_status(struct sdw_bus *bus, bool sync_delay)
{
u32 status;

if (!bus->ops->read_ping_status)
return;
return -ENOTSUPP;

/*
* wait for peripheral to sync if desired. 10-15ms should be more than
Expand All @@ -329,10 +335,13 @@ void sdw_show_ping_status(struct sdw_bus *bus, bool sync_delay)

mutex_unlock(&bus->msg_lock);

if (!status)
if (!status) {
dev_warn(bus->dev, "%s: no peripherals attached\n", __func__);
else
dev_dbg(bus->dev, "PING status: %#x\n", status);
return 0;
}

dev_dbg(bus->dev, "PING status: %#x\n", status);
return 1;
}
EXPORT_SYMBOL(sdw_show_ping_status);

Expand Down Expand Up @@ -847,6 +856,7 @@ static int sdw_program_device_num(struct sdw_bus *bus, bool *programmed)
if (ret == -ENODATA) { /* end of device id reads */
dev_dbg(bus->dev, "No more devices to enumerate\n");
ret = 0;
complete_all(&bus->enumeration_complete);
break;
}
if (ret < 0) {
Expand Down
7 changes: 6 additions & 1 deletion include/linux/soundwire/sdw.h
Original file line number Diff line number Diff line change
Expand Up @@ -901,7 +901,7 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent,
struct fwnode_handle *fwnode);
void sdw_bus_master_delete(struct sdw_bus *bus);

void sdw_show_ping_status(struct sdw_bus *bus, bool sync_delay);
int sdw_show_ping_status(struct sdw_bus *bus, bool sync_delay);

/**
* struct sdw_port_config: Master or Slave Port configuration
Expand Down Expand Up @@ -1001,6 +1001,8 @@ struct sdw_stream_runtime {
* transport and port parameters
* @defer_msg: Defer message
* @params: Current bus parameters
* @enumeration_complete: completion utility to control potential races between
* enumeration completion and peripheral presence checks.
* @stream_refcount: number of streams currently using this bus
* @bpt_stream_refcount: number of BTP streams currently using this bus (should
* be zero or one, multiple streams per link is not supported).
Expand Down Expand Up @@ -1029,6 +1031,7 @@ struct sdw_stream_runtime {
* are supported. This flag is populated by drivers after reading
* appropriate firmware (ACPI/DT).
* @lane_used_bandwidth: how much bandwidth in bits per second is used by each lane
* @is_present: indicates is there any peripheral present on the bus or not.
*/
Comment on lines 1033 to 1035
struct sdw_bus {
struct device *dev;
Expand All @@ -1042,6 +1045,7 @@ struct sdw_bus {
struct list_head m_rt_list;
struct sdw_defer defer_msg;
struct sdw_bus_params params;
struct completion enumeration_complete;
int stream_refcount;
Comment thread
bardliao marked this conversation as resolved.
int bpt_stream_refcount;
struct sdw_stream_runtime *bpt_stream;
Expand All @@ -1064,6 +1068,7 @@ struct sdw_bus {
#endif
bool multi_link;
unsigned int lane_used_bandwidth[SDW_MAX_LANES];
bool is_present;
};

struct sdw_stream_runtime *sdw_alloc_stream(const char *stream_name, enum sdw_stream_type type);
Expand Down
38 changes: 36 additions & 2 deletions sound/soc/sof/intel/hda.c
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,8 @@ static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev,
return adr_dev;
}

#define SDW_ENUM_TIMEOUT_MS 3000

static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev)
{
struct snd_sof_pdata *pdata = sdev->pdata;
Expand All @@ -1313,7 +1315,9 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
struct sdw_peripherals *peripherals;
struct snd_soc_acpi_mach *mach;
struct sof_intel_hda_dev *hdev;
struct sdw_slave *slave;
int link_index, link_num;
unsigned long time;
int amp_index = 1;
u32 link_mask = 0;
int i;
Expand Down Expand Up @@ -1415,14 +1419,44 @@ static struct snd_soc_acpi_mach *hda_sdw_machine_select(struct snd_sof_dev *sdev
if (!links)
return NULL;

/*
* Recalculate the link_mask as a link will be empty if all peripherals on the link are
* not enumerated
*/
link_mask = 0;
/* Generate snd_soc_acpi_link_adr struct for each peripheral reported by the ACPI table */
for (i = 0; i < peripherals->num_peripherals; i++) {
slave = peripherals->array[i];

if (!slave->bus->is_present)
continue;

if (sdw_show_ping_status(slave->bus, true) == 0) {
/* no peripherals attached on this link */
slave->bus->is_present = false;
continue;
}

time = wait_for_completion_timeout(&slave->bus->enumeration_complete,
msecs_to_jiffies(SDW_ENUM_TIMEOUT_MS));
Comment on lines +1431 to +1441
if (!time) {
dev_warn(slave->bus->dev, "No peripheral is present\n");
slave->bus->is_present = false;
continue;
}

/* Check if the SoundWire peripheral is present */
if (!slave->dev_num_sticky) {
dev_warn(&slave->dev, "SoundWire peripheral is not present\n");
continue;
}
/* link_index = the number of used links below the current link */
link_index = hweight32(link_mask & (BIT(peripherals->array[i]->bus->link_id) - 1));
links[link_index].adr_d = find_acpi_adr_device(sdev->dev, peripherals->array[i],
link_index = hweight32(link_mask & (BIT(slave->bus->link_id) - 1));
links[link_index].adr_d = find_acpi_adr_device(sdev->dev, slave,
&links[link_index], &amp_index);
if (!links[link_index].adr_d)
return NULL;
link_mask |= BIT(slave->bus->link_id);
}

mach->drv_name = "sof_sdw";
Expand Down
Loading