@@ -1343,7 +1343,7 @@ static struct s5p_mfc_variant mfc_drvdata_v5 = {
.port_num = MFC_NUM_PORTS,
.buf_size = &buf_size_v5,
.buf_align = &mfc_buf_align_v5,
- .fw_name = "s5p-mfc.fw",
+ .fw_name[0] = "s5p-mfc.fw",
};
struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = {
@@ -1370,7 +1370,12 @@ static struct s5p_mfc_variant mfc_drvdata_v6 = {
.port_num = MFC_NUM_PORTS_V6,
.buf_size = &buf_size_v6,
.buf_align = &mfc_buf_align_v6,
- .fw_name = "s5p-mfc-v6.fw",
+ .fw_name[0] = "s5p-mfc-v6.fw",
+ /*
+ * v6-v2 firmware contains bug fixes and interface change
+ * for init buffer command
+ */
+ .fw_name[1] = "s5p-mfc-v6-v2.fw",
};
struct s5p_mfc_buf_size_v6 mfc_buf_size_v7 = {
@@ -1397,7 +1402,7 @@ static struct s5p_mfc_variant mfc_drvdata_v7 = {
.port_num = MFC_NUM_PORTS_V7,
.buf_size = &buf_size_v7,
.buf_align = &mfc_buf_align_v7,
- .fw_name = "s5p-mfc-v7.fw",
+ .fw_name[0] = "s5p-mfc-v7.fw",
};
struct s5p_mfc_buf_size_v6 mfc_buf_size_v8 = {
@@ -1424,7 +1429,7 @@ static struct s5p_mfc_variant mfc_drvdata_v8 = {
.port_num = MFC_NUM_PORTS_V8,
.buf_size = &buf_size_v8,
.buf_align = &mfc_buf_align_v8,
- .fw_name = "s5p-mfc-v8.fw",
+ .fw_name[0] = "s5p-mfc-v8.fw",
};
static struct platform_device_id mfc_driver_ids[] = {
@@ -38,6 +38,8 @@
#define MFC_BANK2_ALIGN_ORDER 13
#define MFC_BASE_ALIGN_ORDER 17
+#define MFC_FW_MAX_VERSIONS 2
+
#include <media/videobuf2-dma-contig.h>
static inline dma_addr_t s5p_mfc_mem_cookie(void *a, void *b)
@@ -163,6 +165,11 @@ enum s5p_mfc_decode_arg {
MFC_DEC_RES_CHANGE,
};
+enum s5p_mfc_fw_ver {
+ MFC_FW_V1,
+ MFC_FW_V2,
+};
+
#define MFC_BUF_FLAG_USED (1 << 0)
#define MFC_BUF_FLAG_EOS (1 << 1)
@@ -225,7 +232,7 @@ struct s5p_mfc_variant {
u32 version_bit;
struct s5p_mfc_buf_size *buf_size;
struct s5p_mfc_buf_align *buf_align;
- char *fw_name;
+ char *fw_name[MFC_FW_MAX_VERSIONS];
};
/**
@@ -287,6 +294,7 @@ struct s5p_mfc_priv_buf {
* @warn_start: hardware error code from which warnings start
* @mfc_ops: ops structure holding HW operation function pointers
* @mfc_cmds: cmd structure holding HW commands function pointers
+ * @fw_ver: loaded firmware sub-version
*
*/
struct s5p_mfc_dev {
@@ -331,6 +339,7 @@ struct s5p_mfc_dev {
struct s5p_mfc_hw_ops *mfc_ops;
struct s5p_mfc_hw_cmds *mfc_cmds;
const struct s5p_mfc_regs *mfc_regs;
+ enum s5p_mfc_fw_ver fw_ver;
};
/**
@@ -78,14 +78,23 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev)
{
struct firmware *fw_blob;
- int err;
+ int i, err = -EINVAL;
/* Firmare has to be present as a separate file or compiled
* into kernel. */
mfc_debug_enter();
- err = request_firmware((const struct firmware **)&fw_blob,
- dev->variant->fw_name, dev->v4l2_dev.dev);
+ for (i = MFC_FW_MAX_VERSIONS - 1; i >= 0; i--) {
+ if (!dev->variant->fw_name[i])
+ continue;
+ err = request_firmware((const struct firmware **)&fw_blob,
+ dev->variant->fw_name[i], dev->v4l2_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;