staticbool rt721_sdca_readable_register(struct device *dev, unsignedint reg)
{ switch (reg) { case 0x2f01 ... 0x2f0a: case 0x2f35: case 0x2f50: case 0x2f51: case 0x2f58 ... 0x2f5d: case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_XUV,
RT721_SDCA_CTL_XUV, 0): case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_GE49,
RT721_SDCA_CTL_SELECTED_MODE, 0): case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_GE49,
RT721_SDCA_CTL_DETECTED_MODE, 0): case SDW_SDCA_CTL(FUNC_NUM_HID, RT721_SDCA_ENT_HID01,
RT721_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ... SDW_SDCA_CTL(FUNC_NUM_HID,
RT721_SDCA_ENT_HID01, RT721_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): case RT721_BUF_ADDR_HID1 ... RT721_BUF_ADDR_HID2: returntrue; default: returnfalse;
}
}
staticbool rt721_sdca_volatile_register(struct device *dev, unsignedint reg)
{ switch (reg) { case 0x2f01: case 0x2f51: case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_GE49,
RT721_SDCA_CTL_DETECTED_MODE, 0): case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_XUV,
RT721_SDCA_CTL_XUV, 0): case SDW_SDCA_CTL(FUNC_NUM_HID, RT721_SDCA_ENT_HID01,
RT721_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ... SDW_SDCA_CTL(FUNC_NUM_HID,
RT721_SDCA_ENT_HID01, RT721_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): case RT721_BUF_ADDR_HID1 ... RT721_BUF_ADDR_HID2: returntrue; default: returnfalse;
}
}
staticbool rt721_sdca_mbq_readable_register(struct device *dev, unsignedint reg)
{ switch (reg) { case 0x0900007: case 0x0a00005: case 0x0c00005: case 0x0d00014: case 0x0310100: case 0x2000001: case 0x2000002: case 0x2000003: case 0x2000013: case 0x200003c: case 0x2000046: case 0x5810000: case 0x5810036: case 0x5810037: case 0x5810038: case 0x5810039: case 0x5b10018: case 0x5b10019: case 0x5f00045: case 0x5f00048: case 0x6100000: case 0x6100005: case 0x6100006: case 0x610000d: case 0x6100010: case 0x6100011: case 0x6100013: case 0x6100015: case 0x6100017: case 0x6100025: case 0x6100029: case 0x610002c ... 0x610002f: case 0x6100053 ... 0x6100055: case 0x6100057: case 0x610005a: case 0x610005b: case 0x610006a: case 0x610006d: case 0x6100092: case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, RT721_SDCA_CTL_FU_VOLUME,
CH_L): case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU05, RT721_SDCA_CTL_FU_VOLUME,
CH_R): case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F, RT721_SDCA_CTL_FU_VOLUME,
CH_L): case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_USER_FU0F, RT721_SDCA_CTL_FU_VOLUME,
CH_R): case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PLATFORM_FU44,
RT721_SDCA_CTL_FU_CH_GAIN, CH_L): case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT721_SDCA_ENT_PLATFORM_FU44,
RT721_SDCA_CTL_FU_CH_GAIN, CH_R): case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME,
CH_01): case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME,
CH_02): case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME,
CH_03): case SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT721_SDCA_ENT_USER_FU1E, RT721_SDCA_CTL_FU_VOLUME,
CH_04): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, RT721_SDCA_CTL_FU_VOLUME, CH_L): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT721_SDCA_ENT_USER_FU06, RT721_SDCA_CTL_FU_VOLUME, CH_R): returntrue; default: returnfalse;
}
}
staticbool rt721_sdca_mbq_volatile_register(struct device *dev, unsignedint reg)
{ switch (reg) { case 0x0310100: case 0x0a00005: case 0x0c00005: case 0x0d00014: case 0x2000000: case 0x200000d: case 0x2000019: case 0x2000020: case 0x2000030: case 0x2000046: case 0x2000067: case 0x2000084: case 0x2000086: case 0x5810000: case 0x5810036: case 0x5810037: case 0x5810038: case 0x5810039: case 0x5b10018: case 0x5b10019: returntrue; default: returnfalse;
}
}
if (status == SDW_SLAVE_UNATTACHED)
rt721->hw_init = false;
if (status == SDW_SLAVE_ATTACHED) { if (rt721->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 rt721_sdca_jack_init set.
*/
sdw_write_no_pm(rt721->slave, SDW_SCP_SDCA_INTMASK1,
SDW_SCP_SDCA_INTMASK_SDCA_0);
sdw_write_no_pm(rt721->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 (rt721->hw_init || status != SDW_SLAVE_ATTACHED) return 0;
/* 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(&rt721->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 (rt721->scp_sdca_stat2)
scp_sdca_stat2 = rt721->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(&rt721->disable_irq_lock);
ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT1); if (ret < 0) goto io_error;
rt721->scp_sdca_stat1 = ret;
ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT2); if (ret < 0) goto io_error;
rt721->scp_sdca_stat2 = ret; if (scp_sdca_stat2)
rt721->scp_sdca_stat2 |= scp_sdca_stat2; do { /* clear flag */
ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT1); if (ret < 0) goto io_error; if (ret & SDW_SCP_SDCA_INTMASK_SDCA_0) {
ret = sdw_update_no_pm(rt721->slave, SDW_SCP_SDCA_INT1,
SDW_SCP_SDCA_INT_SDCA_0, SDW_SCP_SDCA_INT_SDCA_0); if (ret < 0) goto io_error;
}
ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT2); if (ret < 0) goto io_error; if (ret & SDW_SCP_SDCA_INTMASK_SDCA_8) {
ret = sdw_write_no_pm(rt721->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(rt721->slave, SDW_DP0_INT); if (ret < 0) goto io_error;
sdca_cascade = ret & SDW_DP0_SDCA_CASCADE;
ret = sdw_read_no_pm(rt721->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(rt721->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__,
rt721->scp_sdca_stat1, rt721->scp_sdca_stat2);
ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT1);
ret = sdw_read_no_pm(rt721->slave, SDW_SCP_SDCA_INT2);
if (status->sdca_cascade && !rt721->disable_irq)
mod_delayed_work(system_power_efficient_wq,
&rt721->jack_detect_work, msecs_to_jiffies(280));
mutex_unlock(&rt721->disable_irq_lock);
return 0;
io_error:
mutex_unlock(&rt721->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(&rt721_sdca->disable_irq_lock);
rt721_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(&rt721_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__);
}
time = wait_for_completion_timeout(&slave->initialization_complete,
msecs_to_jiffies(RT721_PROBE_TIMEOUT)); if (!time) {
dev_err(&slave->dev, "Initialization not complete, timed out\n");
sdw_show_ping_status(slave->bus, true);
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.