if (!cs42l42->sclk || !cs42l42->sample_rate) return -EINVAL;
/* * At this point we know the sample rate from hw_params, and the SWIRE_CLK from bus_config() * callback. This could only fail if the ACPI or machine driver are misconfigured to allow * an unsupported SWIRE_CLK and sample_rate combination.
*/
ret = cs42l42_sdw_poll_status(peripheral, CS42L42_SDW_CMD_IN_PROGRESS, 0); if (ret < 0) return ret;
ret = sdw_read_no_pm(peripheral, reg); if (ret < 0) {
dev_err(&peripheral->dev, "Failed to issue read @0x%x: %d\n", reg, ret); return ret;
}
data = (u8)ret; /* possible non-delayed read value */
ret = sdw_read_no_pm(peripheral, CS42L42_SDW_MEM_ACCESS_STATUS); if (ret < 0) {
dev_err(&peripheral->dev, "Failed to read MEM_ACCESS_STATUS: %d\n", ret); return ret;
}
/* If read was not delayed we already have the result */ if ((ret & CS42L42_SDW_LAST_LATE) == 0) {
*val = data; return 0;
}
/* Poll for delayed read completion */ if ((ret & CS42L42_SDW_RDATA_RDY) == 0) {
ret = cs42l42_sdw_poll_status(peripheral,
CS42L42_SDW_RDATA_RDY, CS42L42_SDW_RDATA_RDY); if (ret < 0) return ret;
}
ret = sdw_read_no_pm(peripheral, CS42L42_SDW_MEM_READ_DATA); if (ret < 0) {
dev_err(&peripheral->dev, "Failed to read READ_DATA: %d\n", ret); return ret;
}
/* Initialise cs42l42 using SoundWire - this is only called once, during initialisation */ staticvoid cs42l42_sdw_init(struct sdw_slave *peripheral)
{ struct cs42l42_private *cs42l42 = dev_get_drvdata(&peripheral->dev); int ret;
regcache_cache_only(cs42l42->regmap, false);
ret = cs42l42_init(cs42l42); if (ret < 0) {
regcache_cache_only(cs42l42->regmap, true); goto err;
}
/* Write out any cached changes that happened between probe and attach */
ret = regcache_sync(cs42l42->regmap); if (ret < 0)
dev_warn(cs42l42->dev, "Failed to sync cache: %d\n", ret);
/* Disable internal logic that makes clock-stop conditional */
regmap_clear_bits(cs42l42->regmap, CS42L42_PWR_CTL3, CS42L42_SW_CLK_STP_STAT_SEL_MASK);
err: /* This cancels the pm_runtime_get_noresume() call from cs42l42_sdw_probe(). */
pm_runtime_put_autosuspend(cs42l42->dev);
}
switch (status) { case SDW_SLAVE_ATTACHED:
dev_dbg(cs42l42->dev, "ATTACHED\n");
/* * The SoundWire core can report stale ATTACH notifications * if we hard-reset CS42L42 in probe() but it had already been * enumerated. Reject the ATTACH if we haven't yet seen an * UNATTACH report for the device being in reset.
*/ if (cs42l42->sdw_waiting_first_unattach) break;
/* * Initialise codec, this only needs to be done once. * When resuming from suspend, resume callback will handle re-init of codec, * using regcache_sync().
*/ if (!cs42l42->init_done)
cs42l42_sdw_init(peripheral); break; case SDW_SLAVE_UNATTACHED:
dev_dbg(cs42l42->dev, "UNATTACHED\n");
if (cs42l42->sdw_waiting_first_unattach) { /* * SoundWire core has seen that CS42L42 is not on * the bus so release RESET and wait for ATTACH.
*/
cs42l42->sdw_waiting_first_unattach = false;
gpiod_set_value_cansleep(cs42l42->reset_gpio, 1);
}
staticconststruct sdw_slave_ops cs42l42_sdw_ops = { /* No interrupt callback because only hardware INT is supported for Jack Detect in the CS42L42 */
.read_prop = cs42l42_sdw_read_prop,
.update_status = cs42l42_sdw_update_status,
.bus_config = cs42l42_sdw_bus_config,
.port_prep = cs42l42_sdw_port_prep,
};
/* Cannot access registers until master re-attaches. */
dev_dbg(&peripheral->dev, "Wait for initialization_complete\n"); if (!wait_for_completion_timeout(&peripheral->initialization_complete,
msecs_to_jiffies(5000))) {
dev_err(&peripheral->dev, "initialization_complete timed out\n"); return -ETIMEDOUT;
}
peripheral->unattach_request = 0;
/* * After a bus reset there must be a reconfiguration reset to * reinitialize the internal state of CS42L42.
*/
regmap_multi_reg_write_bypassed(cs42l42->regmap,
cs42l42_soft_reboot_seq,
ARRAY_SIZE(cs42l42_soft_reboot_seq));
usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2);
regcache_mark_dirty(cs42l42->regmap);
/* * pm_runtime is needed to control bus manager suspend, and to * recover from an unattach_request when the manager suspends.
*/
pm_runtime_set_autosuspend_delay(cs42l42->dev, 3000);
pm_runtime_use_autosuspend(cs42l42->dev);
pm_runtime_mark_last_busy(cs42l42->dev);
pm_runtime_set_active(cs42l42->dev);
pm_runtime_get_noresume(cs42l42->dev);
pm_runtime_enable(cs42l42->dev);
ret = cs42l42_common_probe(cs42l42, component_drv, &cs42l42_sdw_dai); if (ret < 0) return ret;
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.