/* Make sure there are no non-displayable characaters in the string */ if (!sigma_fw_validate_control_name(ctrl_chunk->name, name_len)) return -EINVAL;
name = kmemdup_nul(ctrl_chunk->name, name_len, GFP_KERNEL); if (!name) {
ret = -ENOMEM; goto err_free_ctrl;
}
ctrl->name = name;
/* * Readbacks doesn't work with non-volatile controls, since the * firmware updates the control value without driver interaction. Mark * the readbacks to ensure that the values are not cached.
*/ if (ctrl->name && strncmp(ctrl->name, READBACK_CTRL_NAME,
(sizeof(READBACK_CTRL_NAME) - 1)) == 0)
ctrl->is_readback = true;
/* * Make sure that there is at least one chunk to avoid integer * underflows later on. Empty firmware is still valid though.
*/ if (fw->size < sizeof(*chunk) + sizeof(struct sigma_firmware_header)) return 0;
switch (le32_to_cpu(chunk->tag)) { case SIGMA_FW_CHUNK_TYPE_DATA:
ret = sigma_fw_load_data(sigmadsp, chunk, length); break; case SIGMA_FW_CHUNK_TYPE_CONTROL:
ret = sigma_fw_load_control(sigmadsp, chunk, length); break; case SIGMA_FW_CHUNK_TYPE_SAMPLERATES:
ret = sigma_fw_load_samplerates(sigmadsp, chunk, length); break; default:
dev_warn(sigmadsp->dev, "Unknown chunk type: %d\n",
chunk->tag);
ret = 0; break;
}
if (ret) return ret;
/* * This can not overflow since if length is larger than the * maximum firmware size (0x4000000) we'll error out earilier.
*/
pos += ALIGN(length, sizeof(__le32));
}
switch (sa->instr) { case SIGMA_ACTION_WRITEXBYTES: case SIGMA_ACTION_WRITESINGLE: case SIGMA_ACTION_WRITESAFELOAD:
payload = sigma_action_len(sa); break; default: break;
}
payload = ALIGN(payload, 2);
return payload + sizeof(struct sigma_action);
}
/* * Returns a negative error value in case of an error, 0 if processing of * the firmware should be stopped after this action, 1 otherwise.
*/ staticint process_sigma_action(struct sigmadsp *sigmadsp, struct sigma_action *sa)
{
size_t len = sigma_action_len(sa); struct sigmadsp_data *data;
/* first load the blob */
ret = request_firmware(&fw, name, sigmadsp->dev); if (ret) {
pr_debug("%s: request_firmware() failed with %i\n", __func__, ret); goto done;
}
/* then verify the header */
ret = -EINVAL;
/* * Reject too small or unreasonable large files. The upper limit has been * chosen a bit arbitrarily, but it should be enough for all practical * purposes and having the limit makes it easier to avoid integer * overflows later in the loading process.
*/ if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) {
dev_err(sigmadsp->dev, "Failed to load firmware: Invalid size\n"); goto done;
}
ssfw_head = (void *)fw->data; if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) {
dev_err(sigmadsp->dev, "Failed to load firmware: Invalid magic\n"); goto done;
}
/** * devm_sigmadsp_init() - Initialize SigmaDSP instance * @dev: The parent device * @ops: The sigmadsp_ops to use for this instance * @firmware_name: Name of the firmware file to load * * Allocates a SigmaDSP instance and loads the specified firmware file. * * Returns a pointer to a struct sigmadsp on success, or a PTR_ERR() on error.
*/ struct sigmadsp *devm_sigmadsp_init(struct device *dev, conststruct sigmadsp_ops *ops, constchar *firmware_name)
{ struct sigmadsp *sigmadsp; int ret;
sigmadsp = devres_alloc(devm_sigmadsp_release, sizeof(*sigmadsp),
GFP_KERNEL); if (!sigmadsp) return ERR_PTR(-ENOMEM);
ret = sigmadsp_init(sigmadsp, dev, ops, firmware_name); if (ret) {
devres_free(sigmadsp); return ERR_PTR(ret);
}
active = sigmadsp_samplerate_valid(ctrl->samplerates, samplerate_mask); if (!ctrl->kcontrol) return;
changed = snd_ctl_activate_id(card, &ctrl->kcontrol->id, active); if (active && changed > 0) {
mutex_lock(&sigmadsp->lock); if (ctrl->cached)
sigmadsp_ctrl_write(sigmadsp, ctrl, ctrl->cache);
mutex_unlock(&sigmadsp->lock);
}
}
/** * sigmadsp_attach() - Attach a sigmadsp instance to a ASoC component * @sigmadsp: The sigmadsp instance to attach * @component: The component to attach to * * Typically called in the components probe callback. * * Note, once this function has been called the firmware must not be released * until after the ALSA snd_card that the component belongs to has been * disconnected, even if sigmadsp_attach() returns an error.
*/ int sigmadsp_attach(struct sigmadsp *sigmadsp, struct snd_soc_component *component)
{ struct sigmadsp_control *ctrl; unsignedint samplerate_mask; int ret;
list_for_each_entry(ctrl, &sigmadsp->ctrl_list, head) {
ret = sigmadsp_alloc_control(sigmadsp, ctrl, samplerate_mask); if (ret) return ret;
}
return 0;
}
EXPORT_SYMBOL_GPL(sigmadsp_attach);
/** * sigmadsp_setup() - Setup the DSP for the specified samplerate * @sigmadsp: The sigmadsp instance to configure * @samplerate: The samplerate the DSP should be configured for * * Loads the appropriate firmware program and parameter memory (if not already * loaded) and enables the controls for the specified samplerate. Any control * parameter changes that have been made previously will be restored. * * Returns 0 on success, a negative error code otherwise.
*/ int sigmadsp_setup(struct sigmadsp *sigmadsp, unsignedint samplerate)
{ struct sigmadsp_control *ctrl; unsignedint samplerate_mask; struct sigmadsp_data *data; int ret;
if (sigmadsp->current_samplerate == samplerate) return 0;
samplerate_mask = sigmadsp_get_samplerate_mask(sigmadsp, samplerate); if (samplerate_mask == 0) return -EINVAL;
list_for_each_entry(data, &sigmadsp->data_list, head) { if (!sigmadsp_samplerate_valid(data->samplerates,
samplerate_mask)) continue;
ret = sigmadsp_write(sigmadsp, data->addr, data->data,
data->length); if (ret) goto err;
}
/** * sigmadsp_reset() - Notify the sigmadsp instance that the DSP has been reset * @sigmadsp: The sigmadsp instance to reset * * Should be called whenever the DSP has been reset and parameter and program * memory need to be re-loaded.
*/ void sigmadsp_reset(struct sigmadsp *sigmadsp)
{ struct sigmadsp_control *ctrl;
/** * sigmadsp_restrict_params() - Applies DSP firmware specific constraints * @sigmadsp: The sigmadsp instance * @substream: The substream to restrict * * Applies samplerate constraints that may be required by the firmware Should * typically be called from the CODEC/component drivers startup callback. * * Returns 0 on success, a negative error code otherwise.
*/ int sigmadsp_restrict_params(struct sigmadsp *sigmadsp, struct snd_pcm_substream *substream)
{ if (sigmadsp->rate_constraints.count == 0) return 0;
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.