@@ -1255,6 +1255,50 @@ static int intel_master_remove(struct sdw_master_device *md)
return 0;
}
+static int intel_master_process_wakeen_event(struct sdw_master_device *md)
+{
+ struct sdw_intel *sdw;
+ struct sdw_slave *slave;
+ struct sdw_bus *bus;
+ void __iomem *shim;
+ u16 wake_sts;
+
+ sdw = md->pdata;
+
+ if (sdw->cdns.bus.prop.hw_disabled) {
+ dev_info(&md->dev,
+ "SoundWire master %d is disabled, ignoring\n",
+ sdw->cdns.bus.link_id);
+ return 0;
+ }
+
+ shim = sdw->link_res->shim;
+ wake_sts = intel_readw(shim, SDW_SHIM_WAKESTS);
+
+ if (!(wake_sts & BIT(sdw->instance)))
+ return 0;
+
+ /* disable WAKEEN interrupt ASAP to prevent interrupt flood */
+ intel_shim_wake(sdw, false);
+
+ bus = &sdw->cdns.bus;
+
+ /*
+ * 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 &&
+ slave->status != SDW_SLAVE_ALERT)
+ continue;
+
+ pm_request_resume(&slave->dev);
+ }
+ }
+
+ return 0;
+}
static struct sdw_master_driver intel_sdw_driver = {
.driver = {
@@ -1265,6 +1309,7 @@ static struct sdw_master_driver intel_sdw_driver = {
.probe = intel_master_probe,
.startup = intel_master_startup,
.remove = intel_master_remove,
+ .process_wake_event = intel_master_process_wakeen_event,
};
module_sdw_master_driver(intel_sdw_driver);
@@ -413,5 +413,17 @@ void sdw_intel_exit(struct sdw_intel_ctx *ctx)
}
EXPORT_SYMBOL_NS(sdw_intel_exit, SOUNDWIRE_INTEL_INIT);
+void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx)
+{
+ struct sdw_intel_link_res *link;
+
+ if (!ctx->links)
+ return;
+
+ list_for_each_entry(link, &ctx->link_list, list)
+ sdw_master_device_process_wake_event(link->md);
+}
+EXPORT_SYMBOL_NS(sdw_intel_process_wakeen_event, SOUNDWIRE_INTEL_INIT);
+
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("Intel Soundwire Init Library");