diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index efa6db7e43b64a..0a8ff1391b2a0c 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -401,6 +401,44 @@ static void intel_shim_wake(struct sdw_intel *sdw, bool wake_enable) } } +void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx) +{ + struct sdw_intel_link_res *link; + struct sdw_master_device *md; + struct sdw_slave *slave; + struct sdw_bus *bus; + + list_for_each_entry(link, &ctx->link_list, list) { + struct sdw_intel *sdw; + u16 wake_sts; + + md = link->md; + bus = &link->cdns->bus; + sdw = cdns_to_intel(link->cdns); + wake_sts = intel_readw(sdw->link_res->shim, SDW_SHIM_WAKESTS); + + /* disable WAKEEN interrupt ASAP to prevent interrupt flood */ + intel_shim_wake(sdw, false); + + if (!(wake_sts & BIT(sdw->instance))) + continue; + + /* + * wake up master and slave so that slave can notify master + * the wakeen event and let codec driver check codec status + */ + list_for_each_entry(slave, &bus->slaves, node) { + if (slave->prop.wake_capable) { + if (slave->status != SDW_SLAVE_ATTACHED) + continue; + + pm_request_resume(&slave->dev); + } + } + } +} +EXPORT_SYMBOL(sdw_intel_process_wakeen_event); + static int intel_link_power_down(struct sdw_intel *sdw) { int link_control, spa_mask, cpa_mask, ret; diff --git a/include/linux/soundwire/sdw_intel.h b/include/linux/soundwire/sdw_intel.h index 9a9ce9fd1d71b2..d79c5c2090bc71 100644 --- a/include/linux/soundwire/sdw_intel.h +++ b/include/linux/soundwire/sdw_intel.h @@ -122,6 +122,8 @@ struct sdw_intel_res { int sdw_intel_acpi_scan(acpi_handle *parent_handle, struct sdw_intel_acpi_info *info); +void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx); + struct sdw_intel_ctx * sdw_intel_probe(struct sdw_intel_res *res);