@@ -132,6 +132,7 @@
#define S5P_FIMV_D_METADATA_BUFFER_ADDR_V6 0xf448
#define S5P_FIMV_D_METADATA_BUFFER_SIZE_V6 0xf44c
#define S5P_FIMV_D_NUM_MV_V6 0xf478
+#define S5P_FIMV_D_INIT_BUFFER_OPTIONS_V6 0xf47c
#define S5P_FIMV_D_CPB_BUFFER_ADDR_V6 0xf4b0
#define S5P_FIMV_D_CPB_BUFFER_SIZE_V6 0xf4b4
@@ -18,8 +18,6 @@
#define S5P_FIMV_CODEC_VP8_ENC_V7 25
/* Additional registers for v7 */
-#define S5P_FIMV_D_INIT_BUFFER_OPTIONS_V7 0xf47c
-
#define S5P_FIMV_E_SOURCE_FIRST_ADDR_V7 0xf9e0
#define S5P_FIMV_E_SOURCE_SECOND_ADDR_V7 0xf9e4
#define S5P_FIMV_E_SOURCE_THIRD_ADDR_V7 0xf9e8
@@ -287,6 +287,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
+ * @ver: firmware sub version
*
*/
struct s5p_mfc_dev {
@@ -330,6 +331,7 @@ struct s5p_mfc_dev {
int warn_start;
struct s5p_mfc_hw_ops *mfc_ops;
struct s5p_mfc_hw_cmds *mfc_cmds;
+ int ver;
};
/**
@@ -238,7 +238,6 @@ static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
/* Initialize hardware */
int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
{
- unsigned int ver;
int ret;
mfc_debug_enter();
@@ -300,12 +299,13 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
return -EIO;
}
if (IS_MFCV6_PLUS(dev))
- ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6);
+ dev->ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6);
else
- ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
+ dev->ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n",
- (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
+ (dev->ver >> 16) & 0xFF, (dev->ver >> 8) & 0xFF,
+ dev->ver & 0xFF);
s5p_mfc_clock_off();
mfc_debug_leave();
return 0;
@@ -48,6 +48,9 @@
#define OFFSETA(x) (((x) - dev->port_a) >> S5P_FIMV_MEM_OFFSET)
#define OFFSETB(x) (((x) - dev->port_b) >> S5P_FIMV_MEM_OFFSET)
+/* v2 interface version date of MFCv6 firmware */
+#define MFC_V6_FIRMWARE_INTERFACE_V2 0x120629
+
/* Allocate temporary buffers for decoding */
static int s5p_mfc_alloc_dec_temp_buffers_v6(struct s5p_mfc_ctx *ctx)
{
@@ -1269,6 +1272,18 @@ static int s5p_mfc_set_enc_params_vp8(struct s5p_mfc_ctx *ctx)
return 0;
}
+/* Check if newer v6 firmware with changed init buffer interface */
+static bool s5p_mfc_is_v6_fw_v2(struct s5p_mfc_dev *dev)
+{
+ if (IS_MFCV7(dev))
+ return false;
+ /*
+ * FW date is in BCD format xx120629. So checking for
+ * LSB 24 bits is greater than new interface date.
+ */
+ return (dev->ver & 0xffffff) >= MFC_V6_FIRMWARE_INTERFACE_V2;
+}
+
/* Initialize decoding */
static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx)
{
@@ -1296,7 +1311,7 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx)
WRITEL(ctx->display_delay, S5P_FIMV_D_DISPLAY_DELAY_V6);
}
- if (IS_MFCV7(dev)) {
+ if (IS_MFCV7(dev) || s5p_mfc_is_v6_fw_v2(dev)) {
WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS_V6);
reg = 0;
}
@@ -1311,8 +1326,8 @@ static int s5p_mfc_init_decode_v6(struct s5p_mfc_ctx *ctx)
if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)
reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT_V6);
- if (IS_MFCV7(dev))
- WRITEL(reg, S5P_FIMV_D_INIT_BUFFER_OPTIONS_V7);
+ if (IS_MFCV7(dev) || s5p_mfc_is_v6_fw_v2(dev))
+ WRITEL(reg, S5P_FIMV_D_INIT_BUFFER_OPTIONS_V6);
else
WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS_V6);