if (status == SDW_SLAVE_UNATTACHED)
rt711->hw_init = false;
if (status == SDW_SLAVE_ATTACHED) { if (rt711->hs_jack) { /* * Due to the SCP_SDCA_INTMASK will be cleared by any reset, and then * if the device attached again, we will need to set the setting back. * It could avoid losing the jack detection interrupt. * This also could sync with the cache value as the rt711_sdca_jack_init set.
*/
sdw_write_no_pm(rt711->slave, SDW_SCP_SDCA_INTMASK1,
SDW_SCP_SDCA_INTMASK_SDCA_0);
sdw_write_no_pm(rt711->slave, SDW_SCP_SDCA_INTMASK2,
SDW_SCP_SDCA_INTMASK_SDCA_8);
}
}
/* * Perform initialization only if slave status is present and * hw_init flag is false
*/ if (rt711->hw_init || status != SDW_SLAVE_ATTACHED) return0;
/* first we need to allocate memory for set bits in port lists */
prop->source_ports = 0x14; /* BITMAP: 00010100 */
prop->sink_ports = 0x8; /* BITMAP: 00001000 */
/* do this again for sink now */
nval = hweight32(prop->sink_ports);
prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, sizeof(*prop->sink_dpn_prop), GFP_KERNEL); if (!prop->sink_dpn_prop) return -ENOMEM;
if (cancel_delayed_work_sync(&rt711->jack_detect_work)) {
dev_warn(&slave->dev, "%s the pending delayed_work was cancelled", __func__); /* avoid the HID owner doesn't change to device */ if (rt711->scp_sdca_stat2)
scp_sdca_stat2 = rt711->scp_sdca_stat2;
}
/* * The critical section below intentionally protects a rather large piece of code. * We don't want to allow the system suspend to disable an interrupt while we are * processing it, which could be problematic given the quirky SoundWire interrupt * scheme. We do want however to prevent new workqueues from being scheduled if * the disable_irq flag was set during system suspend.
*/
mutex_lock(&rt711->disable_irq_lock);
ret = sdw_read_no_pm(rt711->slave, SDW_SCP_SDCA_INT1); if (ret < 0) goto io_error;
rt711->scp_sdca_stat1 = ret;
ret = sdw_read_no_pm(rt711->slave, SDW_SCP_SDCA_INT2); if (ret < 0) goto io_error;
rt711->scp_sdca_stat2 = ret; if (scp_sdca_stat2)
rt711->scp_sdca_stat2 |= scp_sdca_stat2;
do { /* clear flag */
ret = sdw_read_no_pm(rt711->slave, SDW_SCP_SDCA_INT1); if (ret < 0) goto io_error; if (ret & SDW_SCP_SDCA_INTMASK_SDCA_0) {
ret = sdw_write_no_pm(rt711->slave, SDW_SCP_SDCA_INT1,
SDW_SCP_SDCA_INTMASK_SDCA_0); if (ret < 0) goto io_error;
}
ret = sdw_read_no_pm(rt711->slave, SDW_SCP_SDCA_INT2); if (ret < 0) goto io_error; if (ret & SDW_SCP_SDCA_INTMASK_SDCA_8) {
ret = sdw_write_no_pm(rt711->slave, SDW_SCP_SDCA_INT2,
SDW_SCP_SDCA_INTMASK_SDCA_8); if (ret < 0) goto io_error;
}
/* check if flag clear or not */
ret = sdw_read_no_pm(rt711->slave, SDW_DP0_INT); if (ret < 0) goto io_error;
sdca_cascade = ret & SDW_DP0_SDCA_CASCADE;
ret = sdw_read_no_pm(rt711->slave, SDW_SCP_SDCA_INT1); if (ret < 0) goto io_error;
scp_sdca_stat1 = ret & SDW_SCP_SDCA_INTMASK_SDCA_0;
ret = sdw_read_no_pm(rt711->slave, SDW_SCP_SDCA_INT2); if (ret < 0) goto io_error;
scp_sdca_stat2 = ret & SDW_SCP_SDCA_INTMASK_SDCA_8;
stat = scp_sdca_stat1 || scp_sdca_stat2 || sdca_cascade;
count++;
} while (stat != 0 && count < retry);
if (stat)
dev_warn(&slave->dev, "%s scp_sdca_stat1=0x%x, scp_sdca_stat2=0x%x\n", __func__,
rt711->scp_sdca_stat1, rt711->scp_sdca_stat2);
if (status->sdca_cascade && !rt711->disable_irq)
mod_delayed_work(system_power_efficient_wq,
&rt711->jack_detect_work, msecs_to_jiffies(30));
mutex_unlock(&rt711->disable_irq_lock);
return0;
io_error:
mutex_unlock(&rt711->disable_irq_lock);
pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret); return ret;
}
/* * prevent new interrupts from being handled after the * deferred work completes and before the parent disables * interrupts on the link
*/
mutex_lock(&rt711_sdca->disable_irq_lock);
rt711_sdca->disable_irq = true;
ret1 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK1,
SDW_SCP_SDCA_INTMASK_SDCA_0, 0);
ret2 = sdw_update_no_pm(slave, SDW_SCP_SDCA_INTMASK2,
SDW_SCP_SDCA_INTMASK_SDCA_8, 0);
mutex_unlock(&rt711_sdca->disable_irq_lock);
if (ret1 < 0 || ret2 < 0) { /* log but don't prevent suspend from happening */
dev_dbg(&slave->dev, "%s: could not disable SDCA interrupts\n:", __func__);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.