/* Load firmware */ int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev)
{ struct firmware *fw_blob; int i, err = -EINVAL;
/* Firmware has to be present as a separate file or compiled
* into kernel. */
mfc_debug_enter();
/* In case of MFC v12, RET_SYS_INIT response from hardware fails due to *incorrectfirmwaretransferandthereforeitisnotabletoinitialize *thehardware.ThiscausesfailedresponseforSYS_INITcommandwhen *MFCrunsforsecondtime.So,loadtheMFCv12firmwareforeachrun.
*/ if (!IS_MFCV12(dev)) if (dev->fw_get_done) return0;
for (i = MFC_FW_MAX_VERSIONS - 1; i >= 0; i--) { if (!dev->variant->fw_name[i]) continue;
err = request_firmware((conststruct firmware **)&fw_blob,
dev->variant->fw_name[i], &dev->plat_dev->dev); if (!err) {
dev->fw_ver = (enum s5p_mfc_fw_ver) i; break;
}
}
if (err != 0) {
mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); return -EINVAL;
} if (fw_blob->size > dev->fw_buf.size) {
mfc_err("MFC firmware is too big to be loaded\n");
release_firmware(fw_blob); return -ENOMEM;
}
memcpy(dev->fw_buf.virt, fw_blob->data, fw_blob->size);
wmb();
dev->fw_get_done = true;
release_firmware(fw_blob);
mfc_debug_leave(); return0;
}
/* Release firmware memory */ int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev)
{ /* Before calling this function one has to make sure
* that MFC is no longer processing */
s5p_mfc_release_priv_buf(dev, &dev->fw_buf);
dev->fw_get_done = false; return0;
}
/* Reset */
mfc_write(dev, 0x1, S5P_FIMV_MFC_BUS_RESET_CTRL);
timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT); /* Check bus status */ do { if (time_after(jiffies, timeout)) {
mfc_err("Timeout while resetting MFC.\n"); return -EIO;
}
status = mfc_read(dev, S5P_FIMV_MFC_BUS_RESET_CTRL);
} while ((status & 0x2) == 0); return0;
}
/* Reset the device */ int s5p_mfc_reset(struct s5p_mfc_dev *dev)
{ unsignedint mc_status; unsignedlong timeout; int i;
mfc_debug_enter();
if (IS_MFCV6_PLUS(dev)) { /* Zero Initialization of MFC registers */
mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6);
mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD_V6);
mfc_write(dev, 0, S5P_FIMV_FW_VERSION_V6);
for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT_V6; i++)
mfc_write(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN_V6 + (i*4));
/* check bus reset control before reset */ if (dev->risc_on && !IS_MFCV12(dev)) if (s5p_mfc_bus_reset(dev)) return -EIO; /* Reset *setRISC_ONto0duringpower_on&wake_up. *V6needsRISC_ONsetto0duringresetalso.
*/ if ((!dev->risc_on) || (!IS_MFCV7_PLUS(dev)))
mfc_write(dev, 0, S5P_FIMV_RISC_ON_V6);
timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT); /* Check MC status */ do { if (time_after(jiffies, timeout)) {
mfc_err("Timeout while resetting MFC\n"); return -EIO;
}
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.