staticbool rt1320_readable_register(struct device *dev, unsignedint reg)
{ switch (reg) { case 0xc000 ... 0xc086: case 0xc400 ... 0xc409: case 0xc480 ... 0xc48f: case 0xc4c0 ... 0xc4c4: case 0xc4e0 ... 0xc4e7: case 0xc500: case 0xc560 ... 0xc56b: case 0xc570: case 0xc580 ... 0xc59a: case 0xc5b0 ... 0xc60f: case 0xc640 ... 0xc64f: case 0xc670: case 0xc680 ... 0xc683: case 0xc700 ... 0xc76f: case 0xc800 ... 0xc801: case 0xc820: case 0xc900 ... 0xc901: case 0xc920 ... 0xc921: case 0xca00 ... 0xca07: case 0xca20 ... 0xca27: case 0xca40 ... 0xca4b: case 0xca60 ... 0xca68: case 0xca80 ... 0xca88: case 0xcb00 ... 0xcb0c: case 0xcc00 ... 0xcc12: case 0xcc80 ... 0xcc81: case 0xcd00: case 0xcd80 ... 0xcd82: case 0xce00 ... 0xce4d: case 0xcf00 ... 0xcf25: case 0xd000 ... 0xd0ff: case 0xd100 ... 0xd1ff: case 0xd200 ... 0xd2ff: case 0xd300 ... 0xd3ff: case 0xd400 ... 0xd403: case 0xd410 ... 0xd417: case 0xd470 ... 0xd497: case 0xd4dc ... 0xd50f: case 0xd520 ... 0xd543: case 0xd560 ... 0xd5ef: case 0xd600 ... 0xd663: case 0xda00 ... 0xda6e: case 0xda80 ... 0xda9e: case 0xdb00 ... 0xdb7f: case 0xdc00: case 0xdc20 ... 0xdc21: case 0xdd00 ... 0xdd17: case 0xde00 ... 0xde09: case 0xdf00 ... 0xdf1b: case 0xe000 ... 0xe847: case 0xf01e: case 0xf717 ... 0xf719: case 0xf720 ... 0xf723: case 0x1000cd91 ... 0x1000cd96: case 0x1000f008: case 0x1000f021: case 0x3fe2e000 ... 0x3fe2e003: case 0x3fc2ab80 ... 0x3fc2abd4: /* 0x40801508/0x40801809/0x4080180a/0x40801909/0x4080190a */ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_REQ_POWER_STATE, 0): case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_MUTE, CH_01): case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_MUTE, CH_02): case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_MUTE, CH_01): case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_MUTE, CH_02): /* 0x40880900/0x40880980 */ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS113, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_CS14, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): /* 0x40881500 */ case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0): /* 0x41000189/0x4100018a */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_01): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_MUTE, CH_02): /* 0x41001388 */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE27, RT1320_SDCA_CTL_REQ_POWER_STATE, 0): /* 0x41001988 */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0): /* 0x41080000 */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0): /* 0x41080200 */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PPU21, RT1320_SDCA_CTL_POSTURE_NUMBER, 0): /* 0x41080900 */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS113, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): /* 0x41080980 */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS14, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): /* 0x41081080 */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_CS21, RT1320_SDCA_CTL_SAMPLE_FREQ_INDEX, 0): /* 0x41081480/0x41081488 */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_SAPU, RT1320_SDCA_CTL_SAPU_PROTECTION_MODE, 0): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_SAPU, RT1320_SDCA_CTL_SAPU_PROTECTION_STATUS, 0): /* 0x41081980 */ case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0): returntrue; default: returnfalse;
}
}
staticbool rt1320_volatile_register(struct device *dev, unsignedint reg)
{ switch (reg) { case 0xc000: case 0xc003: case 0xc081: case 0xc402 ... 0xc406: case 0xc48c ... 0xc48f: case 0xc560: case 0xc5b5 ... 0xc5b7: case 0xc5fc ... 0xc5ff: case 0xc820: case 0xc900: case 0xc920: case 0xca42: case 0xca62: case 0xca82: case 0xcd00: case 0xce03: case 0xce10: case 0xce14 ... 0xce17: case 0xce44 ... 0xce49: case 0xce4c ... 0xce4d: case 0xcf0c: case 0xcf10 ... 0xcf25: case 0xd486 ... 0xd487: case 0xd4e5 ... 0xd4e6: case 0xd4e8 ... 0xd4ff: case 0xd530: case 0xd540: case 0xd543: case 0xdb58 ... 0xdb5f: case 0xdb60 ... 0xdb63: case 0xdb68 ... 0xdb69: case 0xdb6d: case 0xdb70 ... 0xdb71: case 0xdb76: case 0xdb7a: case 0xdb7c ... 0xdb7f: case 0xdd0c ... 0xdd13: case 0xde02: case 0xdf14 ... 0xdf1b: case 0xe83c ... 0xe847: case 0xf01e: case 0xf717 ... 0xf719: case 0xf720 ... 0xf723: case 0x10000000 ... 0x10007fff: case 0x1000c000 ... 0x1000dfff: case 0x1000f008: case 0x1000f021: case 0x3fc2ab80 ... 0x3fc2abd4: case 0x3fc2bf80 ... 0x3fc2bf83: case 0x3fc2bfc0 ... 0x3fc2bfc7: case 0x3fe2e000 ... 0x3fe2e003: case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_PDE11, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_SAPU, RT1320_SDCA_CTL_SAPU_PROTECTION_MODE, 0): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_SAPU, RT1320_SDCA_CTL_SAPU_PROTECTION_STATUS, 0): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0): returntrue; default: returnfalse;
}
}
staticbool rt1320_mbq_readable_register(struct device *dev, unsignedint reg)
{ switch (reg) { case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_01): case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU113, RT1320_SDCA_CTL_FU_VOLUME, CH_02): case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_01): case SDW_SDCA_CTL(FUNC_NUM_MIC, RT1320_SDCA_ENT_FU14, RT1320_SDCA_CTL_FU_VOLUME, CH_02): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_01): case SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_FU21, RT1320_SDCA_CTL_FU_VOLUME, CH_02): returntrue; default: returnfalse;
}
}
/* 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;
/* waiting for Actual PDE becomes to PS0/PS3 */ while (delay) {
regmap_read(rt1320->regmap,
SDW_SDCA_CTL(func, entity, RT1320_SDCA_CTL_ACTUAL_POWER_STATE, 0), &val); if (val == ps) break;
usleep_range(1000, 1500);
delay--;
} if (!delay) {
dev_warn(&rt1320->sdw_slave->dev, "%s PDE to %s is NOT ready", __func__, ps?"PS3":"PS0"); return -ETIMEDOUT;
}
return 0;
}
/* * The 'patch code' is written to the patch code area. * The patch code area is used for SDCA register expansion flexibility.
*/ staticvoid rt1320_load_mcu_patch(struct rt1320_sdw_priv *rt1320)
{ struct sdw_slave *slave = rt1320->sdw_slave; conststruct firmware *patch; constchar *filename; unsignedint addr, val; constunsignedchar *ptr; int ret, i;
if (addr > 0x10007fff || addr < 0x10007000) {
dev_err(&slave->dev, "%s: the address 0x%x is wrong", __func__, addr); goto _exit_;
} if (val > 0xff) {
dev_err(&slave->dev, "%s: the value 0x%x is wrong", __func__, val); goto _exit_;
}
regmap_write(rt1320->regmap, addr, val);
}
}
_exit_:
release_firmware(patch);
}
}
staticvoid rt1320_vab_preset(struct rt1320_sdw_priv *rt1320)
{ unsignedint i, reg, val, delay;
for (i = 0; i < ARRAY_SIZE(rt1320_blind_write); i++) {
reg = rt1320_blind_write[i].reg;
val = rt1320_blind_write[i].def;
delay = rt1320_blind_write[i].delay_us;
if (reg == 0x3fc2bfc7)
rt1320_load_mcu_patch(rt1320);
for (i = 0; i < ARRAY_SIZE(rt1320_vc_blind_write); i++) {
reg = rt1320_vc_blind_write[i].reg;
val = rt1320_vc_blind_write[i].def;
delay = rt1320_vc_blind_write[i].delay_us;
if (reg == 0x3fc2bf83)
rt1320_load_mcu_patch(rt1320);
if ((reg == SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23, RT1320_SDCA_CTL_REQ_POWER_STATE, 0)) &&
(val == 0x00)) {
retry = 200; while (retry) {
regmap_read(rt1320->regmap, RT1320_KR0_INT_READY, &tmp);
dev_dbg(&slave->dev, "%s, RT1320_KR0_INT_READY=0x%x\n", __func__, tmp); if (tmp == 0x1f) break;
usleep_range(1000, 1500);
retry--;
} if (!retry)
dev_warn(&slave->dev, "%s MCU is NOT ready!", __func__);
}
regmap_write(rt1320->regmap, reg, val); if (delay)
usleep_range(delay, delay + 1000);
regcache_cache_only(rt1320->regmap, false);
regcache_cache_only(rt1320->mbq_regmap, false); if (rt1320->first_hw_init) {
regcache_cache_bypass(rt1320->regmap, true);
regcache_cache_bypass(rt1320->mbq_regmap, true);
} else { /* * PM runtime status is marked as 'active' only when a Slave reports as Attached
*/ /* update count of parent 'active' children */
pm_runtime_set_active(&slave->dev);
}
/* initialization write */ if ((amp_func_status & FUNCTION_NEEDS_INITIALIZATION)) { if (rt1320->version_id < RT1320_VC)
rt1320_vab_preset(rt1320); else
rt1320_vc_preset(rt1320);
regmap_write(rt1320->regmap,
SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT0, RT1320_SDCA_CTL_FUNC_STATUS, 0),
FUNCTION_NEEDS_INITIALIZATION);
} if (!rt1320->first_hw_init && rt1320->version_id == RT1320_VA) {
regmap_write(rt1320->regmap, SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23,
RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 0);
regmap_read(rt1320->regmap, RT1320_HIFI_VER_0, &val);
regmap_read(rt1320->regmap, RT1320_HIFI_VER_1, &tmp);
val = (tmp << 8) | val;
regmap_read(rt1320->regmap, RT1320_HIFI_VER_2, &tmp);
val = (tmp << 16) | val;
regmap_read(rt1320->regmap, RT1320_HIFI_VER_3, &tmp);
val = (tmp << 24) | val;
dev_dbg(dev, "%s ROM version=0x%x\n", __func__, val); /* * We call the version b which has the new DSP ROM code against version a. * Therefore, we read the DSP address to check the ID.
*/ if (val == RT1320_VER_B_ID)
rt1320->version_id = RT1320_VB;
regmap_write(rt1320->regmap, SDW_SDCA_CTL(FUNC_NUM_AMP, RT1320_SDCA_ENT_PDE23,
RT1320_SDCA_CTL_REQ_POWER_STATE, 0), 3);
}
dev_dbg(dev, "%s version_id=%d\n", __func__, rt1320->version_id);
if (rt1320->first_hw_init) {
regcache_cache_bypass(rt1320->regmap, false);
regcache_cache_bypass(rt1320->mbq_regmap, false);
regcache_mark_dirty(rt1320->regmap);
regcache_mark_dirty(rt1320->mbq_regmap);
}
if (status == SDW_SLAVE_UNATTACHED)
rt1320->hw_init = false;
/* * Perform initialization only if slave status is present and * hw_init flag is false
*/ if (rt1320->hw_init || status != SDW_SLAVE_ATTACHED) return 0;
for (i = 0; i < p->count; i++) { if (rt1320->fu_mixer_mute[i] != !ucontrol->value.integer.value[i])
changed = 1;
rt1320->fu_mixer_mute[i] = !ucontrol->value.integer.value[i];
}
err = rt1320_set_fu_capture_ctl(rt1320); if (err < 0) return err;
/* * slave_ops: callbacks for get_clock_stop_mode, clock_stop and * port_prep are not defined for now
*/ staticconststruct sdw_slave_ops rt1320_slave_ops = {
.read_prop = rt1320_read_prop,
.update_status = rt1320_update_status,
};
/* * Mark hw_init to false * HW init will be performed when device reports present
*/
rt1320->hw_init = false;
rt1320->first_hw_init = false;
rt1320->version_id = -1;
rt1320->fu_dapm_mute = true;
rt1320->fu_mixer_mute[0] = rt1320->fu_mixer_mute[1] =
rt1320->fu_mixer_mute[2] = rt1320->fu_mixer_mute[3] = true;
ret = devm_snd_soc_register_component(dev,
&soc_component_sdw_rt1320,
rt1320_sdw_dai,
ARRAY_SIZE(rt1320_sdw_dai)); if (ret < 0) return ret;
/* set autosuspend parameters */
pm_runtime_set_autosuspend_delay(dev, 3000);
pm_runtime_use_autosuspend(dev);
/* make sure the device does not suspend immediately */
pm_runtime_mark_last_busy(dev);
pm_runtime_enable(dev);
/* important note: the device is NOT tagged as 'active' and will remain * 'suspended' until the hardware is enumerated/initialized. This is required * to make sure the ASoC framework use of pm_runtime_get_sync() does not silently * fail with -EACCESS because of race conditions between card creation and enumeration
*/
/* * Version A/B will use the class id 0 * The newer version than A/B will use the class id 1, so add it in advance
*/ staticconststruct sdw_device_id rt1320_id[] = {
SDW_SLAVE_ENTRY_EXT(0x025d, 0x1320, 0x3, 0x0, 0),
SDW_SLAVE_ENTRY_EXT(0x025d, 0x1320, 0x3, 0x1, 0),
{},
};
MODULE_DEVICE_TABLE(sdw, rt1320_id);
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.