All of lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v2 2/2] [media] s5p-mfc: update MFC v4l2 driver to support MFC6.x
@ 2012-07-12 12:43 Arun Kumar K
  0 siblings, 0 replies; 5+ messages in thread
From: Arun Kumar K @ 2012-07-12 12:43 UTC (permalink / raw)
  To: Kyungmin Park
  Cc: linux-media, Jeongtae Park, Jang-Hyuck Kim, peter Oh,
	NAVEEN KRISHNA CHATRADHI, Marek Szyprowski, Kamil Debski,
	Sylwester Nawrocki, hans.verkuil, mchehab

Hi Kyungmin Park,

Thank you for the review.
Please find my comments inline.

On Fri, Jul 6, 2012 at 7:51 PM, Kyungmin Park <kmpark@infradead.org> wrote:
> Hi,
>
> On Fri, Jul 6, 2012 at 11:00 PM, Arun Kumar K <arun.kk@samsung.com> wrote:
>> From: Jeongtae Park <jtp.park@samsung.com>
>>
>> Multi Format Codec 6.x is a hardware video coding acceleration
>> module fount in new Exynos5 SoC series.
>> It is capable of handling a range of video codecs and this driver
>> provides a V4L2 interface for video decoding and encoding.
>>
>> Signed-off-by: Jeongtae Park <jtp.park@samsung.com>
>> Singed-off-by: Janghyuck Kim <janghyuck.kim@samsung.com>
>> Singed-off-by: Jaeryul Oh <jaeryul.oh@samsung.com>
>> Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
>> Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
>> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
>> Cc: Kamil Debski <k.debski@samsung.com>
>> ---
>>  drivers/media/video/Kconfig                  |   16 +-
>>  drivers/media/video/s5p-mfc/Makefile         |    7 +-
>>  drivers/media/video/s5p-mfc/regs-mfc-v6.h    |  676 ++++++++++
>>  drivers/media/video/s5p-mfc/regs-mfc.h       |   29 +
>>  drivers/media/video/s5p-mfc/s5p_mfc.c        |  163 ++-
>>  drivers/media/video/s5p-mfc/s5p_mfc_cmd.c    |    6 +-
>>  drivers/media/video/s5p-mfc/s5p_mfc_cmd.h    |    3 +
>>  drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c |   96 ++
>>  drivers/media/video/s5p-mfc/s5p_mfc_common.h |  123 ++-
>>  drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c   |  160 ++-
>>  drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h   |    1 +
>>  drivers/media/video/s5p-mfc/s5p_mfc_dec.c    |  210 +++-
>>  drivers/media/video/s5p-mfc/s5p_mfc_dec.h    |    1 +
>>  drivers/media/video/s5p-mfc/s5p_mfc_enc.c    |  191 ++--
>>  drivers/media/video/s5p-mfc/s5p_mfc_enc.h    |    1 +
>>  drivers/media/video/s5p-mfc/s5p_mfc_intr.c   |    1 -
>>  drivers/media/video/s5p-mfc/s5p_mfc_opr.c    |  278 +++--
>>  drivers/media/video/s5p-mfc/s5p_mfc_opr.h    |   25 +-
>>  drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c | 1697 ++++++++++++++++++++++++++
>>  drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h |  140 +++
>>  drivers/media/video/s5p-mfc/s5p_mfc_pm.c     |    6 +-
>>  drivers/media/video/s5p-mfc/s5p_mfc_shm.c    |   28 +-
>>  drivers/media/video/s5p-mfc/s5p_mfc_shm.h    |   13 +-
>>  drivers/media/video/v4l2-ctrls.c             |    1 -
>>  24 files changed, 3476 insertions(+), 396 deletions(-)
>
> Doesn't it too big for one patch? Can you split it into several patches?
>

Ok. I will split it in the next patch.

>>  create mode 100644 drivers/media/video/s5p-mfc/regs-mfc-v6.h
>>  create mode 100644 drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c
>>  create mode 100644 drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c
>>  create mode 100644 drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h
>>
>> diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
>> index 99937c9..0d7fe77 100644
>> --- a/drivers/media/video/Kconfig
>> +++ b/drivers/media/video/Kconfig
>> @@ -1198,13 +1198,27 @@ config VIDEO_SAMSUNG_S5P_JPEG
>>           This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec
>>
>>  config VIDEO_SAMSUNG_S5P_MFC
>> +       bool
>> +
>> +config VIDEO_SAMSUNG_S5P_MFC_V5
>>         tristate "Samsung S5P MFC 5.1 Video Codec"
>> -       depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
>> +       depends on VIDEO_DEV && VIDEO_V4L2 && ARCH_EXYNOS4
>> +       select VIDEO_SAMSUNG_S5P_MFC
>>         select VIDEOBUF2_DMA_CONTIG
>>         default n
>>         help
>>             MFC 5.1 driver for V4L2.
>>
>> +config VIDEO_SAMSUNG_S5P_MFC_V6
>
> Yes, I know it's exynos5 series features. however, it's not good idea
> to add new config.
> It already handled platform device with proper name.
> e.g., s5p-mfc-v5, s5p-mfc-v6 and handle it with platform data.
>

Ok. Code changes are required for compiling both v5 and v6 together.
Will incorporate in next patch.

[snip]

>> -#define MFC_CLKNAME            "sclk_mfc"
>> +#if defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V5)
>> +#define MFC_CLKNAME            "sclk_mfc"
>> +#elif defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V6)
>> +#define MFC_CLKNAME            "aclk_333"
> I think it can handle clkname without new config.
>

Yes I will change it.

Regards
Arun

^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [PATCH v2 2/2] [media] s5p-mfc: update MFC v4l2 driver to support MFC6.x
@ 2012-07-12 12:54 Arun Kumar K
  0 siblings, 0 replies; 5+ messages in thread
From: Arun Kumar K @ 2012-07-12 12:54 UTC (permalink / raw)
  To: Kamil Debski, linux-media
  Cc: Jeongtae Park, Jang-Hyuck Kim, peter Oh,
	NAVEEN KRISHNA CHATRADHI, Marek Szyprowski, Sylwester Nawrocki,
	hans.verkuil, mchehab

Hi Kamil,

Thank you for the review. Please find my comments inline.

On Tue, Jul 10, 2012 at 8:40 PM, Kamil Debski <k.debski@samsung.com> wrote:
>
> Hi Arun,
>
> Please find some additional comments below.
>
> > From: Arun Kumar K [mailto:arun.kk@samsung.com]
> > Sent: 06 July 2012 16:00
>
> [snip]
>
>
> > diff --git a/drivers/media/video/s5p-mfc/Makefile
> > b/drivers/media/video/s5p-mfc/Makefile
> > index d066340..0308d74 100644
> > --- a/drivers/media/video/s5p-mfc/Makefile
> > +++ b/drivers/media/video/s5p-mfc/Makefile
> > @@ -1,5 +1,6 @@
> >  obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o
> > -s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o s5p_mfc_opr.o
> > +s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o
> >  s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o
> > -s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_cmd.o
> > -s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_shm.o
> > +s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_pm.o
> > +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V5) += s5p_mfc_opr.o s5p_mfc_cmd.o
> > s5p_mfc_shm.o
> > +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V6) += s5p_mfc_opr_v6.o
> > s5p_mfc_cmd_v6.o
> > diff --git a/drivers/media/video/s5p-mfc/regs-mfc-v6.h
> > b/drivers/media/video/s5p-mfc/regs-mfc-v6.h
> > new file mode 100644
> > index 0000000..f22a159
>
> This Makefile does not work when compiling the driver as a module.
> (I also wrote about this in my previous email)
>

Yes. I will fix it.

> [snip]
>
> >
> >  #endif /* _REGS_FIMV_H */
> > diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c
> > b/drivers/media/video/s5p-mfc/s5p_mfc.c
> > index 9bb68e7..bec94bc 100644
> > --- a/drivers/media/video/s5p-mfc/s5p_mfc.c
> > +++ b/drivers/media/video/s5p-mfc/s5p_mfc.c
>
> [snip]
>
> > @@ -285,12 +276,13 @@ static void s5p_mfc_handle_frame(struct
> > s5p_mfc_ctx
> > *ctx,
> >
> >       dst_frame_status = s5p_mfc_get_dspl_status()
> >                               &
> > S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
> > -     res_change = s5p_mfc_get_dspl_status()
> > -                             & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK;
> > +     res_change = (s5p_mfc_get_dspl_status()
> > +                             & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK)
> > +                             >> S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT;
> >       mfc_debug(2, "Frame Status: %x\n", dst_frame_status);
> >       if (ctx->state == MFCINST_RES_CHANGE_INIT)
> >               ctx->state = MFCINST_RES_CHANGE_FLUSH;
> > -     if (res_change) {
> > +     if (res_change && res_change != 3) {
>
> Maybe
> If (res_change == 1 || res_change == 2) {
> would be better, at least it would be more clear.
>

Sure I will change it that way.

> [snip]
>
>
> > diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_common.h
> > b/drivers/media/video/s5p-mfc/s5p_mfc_common.h
> > index bd5706a..8c646f4 100644
> > --- a/drivers/media/video/s5p-mfc/s5p_mfc_common.h
> > +++ b/drivers/media/video/s5p-mfc/s5p_mfc_common.h
>
> [snip]
>
> > @@ -499,37 +563,42 @@ struct s5p_mfc_ctx {
> >       int display_delay;
> >       int display_delay_enable;
> >       int after_packed_pb;
> > +     int sei_fp_parse;
> >
> >       int dpb_count;
> >       int total_dpb_count;
> >
> >       /* Buffers */
> > -     void *ctx_buf;
> > -     size_t ctx_phys;
> > -     size_t ctx_ofs;
> > -     size_t ctx_size;
> > -
> > -     void *desc_buf;
> > -     size_t desc_phys;
> > -
> > -
> > -     void *shm_alloc;
> > -     void *shm;
> > -     size_t shm_ofs;
> > +     unsigned int ctx_size;
> > +     struct s5p_mfc_priv_buf ctx;
> > +     struct s5p_mfc_priv_buf dsc;
> > +     struct s5p_mfc_priv_buf shm;
>
> I think that ctx_size could be integrated in struct s5p_mfc_priv_buf.
> Also - why unsigned int, where in other places you use size_t for size?
> I think it should be consistent. I would choose size_t.
>

Yes. size_t is better. I will change it.

> >
> >       struct s5p_mfc_enc_params enc_params;
> >
> >       size_t enc_dst_buf_size;
> > +     size_t luma_dpb_size;
> > +     size_t chroma_dpb_size;
> > +     size_t me_buffer_size;
> > +     size_t tmv_buffer_size;
> >
>
> ^^ You use size_t here.
>
> [snip]
>
> > diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
> > b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
> > index 08a5cfe..65ff15d 100644
> > --- a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
> > +++ b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
> > @@ -15,7 +15,6 @@
> >  #include <linux/firmware.h>
> >  #include <linux/jiffies.h>
> >  #include <linux/sched.h>
> > -#include "regs-mfc.h"
> >  #include "s5p_mfc_cmd.h"
> >  #include "s5p_mfc_common.h"
> >  #include "s5p_mfc_debug.h"
> > @@ -38,12 +37,12 @@ int s5p_mfc_alloc_and_load_firmware(struct
> > s5p_mfc_dev *dev)
> >        * into kernel. */
> >       mfc_debug_enter();
> >       err = request_firmware((const struct firmware **)&fw_blob,
> > -                                  "s5p-mfc.fw", dev->v4l2_dev.dev);
> > +                                  "mfc_fw.bin", dev->v4l2_dev.dev);
>
> Another name change? This is getting ridiculous. Nein, nein, nein ! ;)
> If you _*really*_ need such a change then go ahead and try to convince
> me, but I tell you - it's going to be hard.
>

Ok. I will retain the old name :)
And as discussed will add new name s5p-mfc-v6.fw for V6.


> >       if (err != 0) {
> >               mfc_err("Firmware is not present in the /lib/firmware
> > directory nor compiled in kernel\n");
> >               return -EINVAL;
> >       }
> > -     dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN);
> > +     dev->fw_size = dev->variant->buf_size->fw;
>
> Why is size taken from there instead of the size of the firmware file?
> Even if there was some point to do it this way then you really *should*
> check if the firmware read from the file fits in the allocated buffer.
>
> This is a straight way to a buffer overflow error. All I need is to
> prepare an extra big firmware file and "viola!" we have a buffer overflow
> that could be fatal to the system.

Yes. Will fix it.

>
> >       if (s5p_mfc_bitproc_buf) {
> >               mfc_err("Attempting to allocate firmware when it seems
> > that
> > it is already loaded\n");
> >               release_firmware(fw_blob);
> > @@ -77,28 +76,33 @@ int s5p_mfc_alloc_and_load_firmware(struct
> > s5p_mfc_dev *dev)
> >               return -EIO;
> >       }
> >       dev->bank1 = s5p_mfc_bitproc_phys;
> > -     b_base = vb2_dma_contig_memops.alloc(
> > -             dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 <<
> > MFC_BANK2_ALIGN_ORDER);
> > -     if (IS_ERR(b_base)) {
> > -             vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> > -             s5p_mfc_bitproc_phys = 0;
> > -             s5p_mfc_bitproc_buf = NULL;
> > -             mfc_err("Allocating bank2 base failed\n");
> > -     release_firmware(fw_blob);
> > -             return -ENOMEM;
> > -     }
> > -     bank2_base_phys = s5p_mfc_mem_cookie(
> > -             dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
> > -     vb2_dma_contig_memops.put(b_base);
> > -     if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
> > -             mfc_err("The base memory for bank 2 is not aligned to
> > 128KB\n");
> > -             vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> > -             s5p_mfc_bitproc_phys = 0;
> > -             s5p_mfc_bitproc_buf = NULL;
> > -             release_firmware(fw_blob);
> > -             return -EIO;
> > +     if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) {
> > +             b_base = vb2_dma_contig_memops.alloc(
> > +                     dev->alloc_ctx[MFC_BANK2_ALLOC_CTX],
> > +                     1 << MFC_BANK2_ALIGN_ORDER);
> > +             if (IS_ERR(b_base)) {
> > +                     vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> > +                     s5p_mfc_bitproc_phys = 0;
> > +                     s5p_mfc_bitproc_buf = 0;
> > +                     mfc_err("Allocating bank2 base failed\n");
> > +                     release_firmware(fw_blob);
> > +                     return -ENOMEM;
> > +             }
> > +             bank2_base_phys = s5p_mfc_mem_cookie(
> > +                     dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
> > +             vb2_dma_contig_memops.put(b_base);
> > +             if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
> > +                     mfc_err("The base memory for bank 2 is not aligned
> > to
> > 128KB\n");
> > +                     vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> > +                     s5p_mfc_bitproc_phys = 0;
> > +                     s5p_mfc_bitproc_buf = 0;
> > +                     release_firmware(fw_blob);
> > +                     return -EIO;
> > +             }
> > +             dev->bank2 = bank2_base_phys;
> > +     } else {
> > +             dev->bank2 = dev->bank1;
> >       }
> > -     dev->bank2 = bank2_base_phys;
> >       memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
> >       wmb();
> >       release_firmware(fw_blob);
> > @@ -116,7 +120,7 @@ int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
> >        * into kernel. */
> >       mfc_debug_enter();
> >       err = request_firmware((const struct firmware **)&fw_blob,
> > -                                  "s5p-mfc.fw", dev->v4l2_dev.dev);
> > +                                  "mfc_fw.bin", dev->v4l2_dev.dev);
>
> Ditto.
>
> [snip]
>
>
> > diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
> > b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
> > index 61dc23b..b72c8c6 100644
> > --- a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
> > +++ b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
>
> [snip]
>
> >
> > @@ -336,21 +364,35 @@ static int vidioc_g_fmt(struct file *file, void
> > *priv, struct v4l2_format *f)
> >  /* Try format */
> >  static int vidioc_try_fmt(struct file *file, void *priv, struct
> > v4l2_format *f)
> >  {
> > +     struct s5p_mfc_dev *dev = video_drvdata(file);
> >       struct s5p_mfc_fmt *fmt;
> >
> > -     if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> > -             mfc_err("This node supports decoding only\n");
> > -             return -EINVAL;
> > -     }
> > -     fmt = find_format(f, MFC_FMT_DEC);
> > -     if (!fmt) {
> > -             mfc_err("Unsupported format\n");
> > -             return -EINVAL;
> > -     }
> > -     if (fmt->type != MFC_FMT_DEC) {
> > -             mfc_err("\n");
> > -             return -EINVAL;
> > +     mfc_debug(2, "Type is %d\n", f->type);
> > +     if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> > +             fmt = find_format(f, MFC_FMT_DEC);
> > +             if (!fmt) {
> > +                     mfc_err("Unsupported format for source.\n");
> > +                     return -EINVAL;
> > +             }
> > +             if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
> > +                     mfc_err("Not supported format.\n");
> > +                     return -EINVAL;
> > +             }
> > +     } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
> > +             fmt = find_format(f, MFC_FMT_RAW);
> > +             if (!fmt) {
> > +                     mfc_err("Unsupported format for destination.\n");
> > +                     return -EINVAL;
> > +             }
> > +             if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT))
> > {
>
> Ok. Let's see.
> If IS_MFCV6(dev) is 1 and
> fmt->fourcc == V4L2_PIX_FMT_NV12MT is 0
> then the following code is not run.
>
> > +                     mfc_err("Not supported format.\n");
> > +                     return -EINVAL;
>
> And we get here.
>
> > +             } else if (fmt->fourcc != V4L2_PIX_FMT_NV12MT) {
>
> fmt->fourcc == V4L2_PIX_FMT_NV12MT is still 0, so
> fmt->fourcc != V4L2_PIX_FMT_NV12MT is 1 and this code is run
>
> > +                     mfc_err("Not supported format.\n");
> > +                     return -EINVAL;
> > +             }
> >       }
> > +
> >       return 0;
> >  }
>
> My question is - what targets did you run this code on? Did you run it
> on Exynos5 with MFC v6? Arun, it is important that you test the patches
> that you send to the mailing list. Maybe you have sent different files
> than the ones you have tested?
>

Yes this is a bug in the code. 
The patch was tested well on Exynos5 with MFCv6 using the v4l example
test app. Unfortuately the test app doesnt call s_fmt on CAPTURE_MPLANE 
and this issue never surfaced.


> [snip]
>
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
> b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
> index 03d8334..645a8ef 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
> @@ -24,48 +24,63 @@
>  #include <linux/workqueue.h>
>  #include <media/v4l2-ctrls.h>
>  #include <media/videobuf2-core.h>
> -#include "regs-mfc.h"
>  #include "s5p_mfc_common.h"
>  #include "s5p_mfc_debug.h"
>  #include "s5p_mfc_enc.h"
>  #include "s5p_mfc_intr.h"
> -#include "s5p_mfc_opr.h"
> +
> +#define DEF_SRC_FMT    2
> +#define DEF_DST_FMT    4
>
> I would add ENC/DEC to the name of this define as it has confused me
> because there are two symbols with the same name in different files.
> Same applies to the s5p_mfc_dec.c file.
>

Ok. Will change it.

> [snip]
>
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
> b/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
> index 405bdd3..413f22f 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
> @@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops
> *get_enc_v4l2_ioctl_ops(void);
>  struct s5p_mfc_fmt *get_enc_def_fmt(bool src);
>  int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx);
>  void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx);
>
>  #endif /* S5P_MFC_ENC_H_  */
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
> b/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
> index 8f2f8bf..dfdc558 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
> @@ -17,7 +17,6 @@
>  #include <linux/io.h>
>  #include <linux/sched.h>
>  #include <linux/wait.h>
> -#include "regs-mfc.h"
>  #include "s5p_mfc_common.h"
>  #include "s5p_mfc_debug.h"
>  #include "s5p_mfc_intr.h"
>
>
> > diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
> > b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
> > index e6217cb..1fd9c92 100644
> > --- a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
> > +++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
> > @@ -12,15 +12,12 @@
> >   * published by the Free Software Foundation.
> >   */
> >
> > -#include "regs-mfc.h"
> > -#include "s5p_mfc_cmd.h"
> >  #include "s5p_mfc_common.h"
> > +#include "s5p_mfc_cmd.h"
> >  #include "s5p_mfc_ctrl.h"
> >  #include "s5p_mfc_debug.h"
> >  #include "s5p_mfc_intr.h"
> > -#include "s5p_mfc_opr.h"
> >  #include "s5p_mfc_pm.h"
> > -#include "s5p_mfc_shm.h"
> >  #include <asm/cacheflush.h>
> >  #include <linux/delay.h>
> >  #include <linux/dma-mapping.h>
> > @@ -37,39 +34,31 @@
> >  /* Allocate temporary buffers for decoding */
> >  int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx)
> >  {
> > -     void *desc_virt;
> >       struct s5p_mfc_dev *dev = ctx->dev;
> > +     struct s5p_mfc_buf_size_v5 *buf_size =
> > dev->variant->buf_size->priv;
> >
> > -     ctx->desc_buf = vb2_dma_contig_memops.alloc(
> > -                     dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
> > DESC_BUF_SIZE);
> > -     if (IS_ERR_VALUE((int)ctx->desc_buf)) {
> > -             ctx->desc_buf = NULL;
> > +     ctx->dsc.alloc = vb2_dma_contig_memops.alloc(
> > +                     dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
> > +                     buf_size->dsc);
> > +     if (IS_ERR_VALUE((int)ctx->dsc.alloc)) {
> > +             ctx->dsc.alloc = NULL;
> >               mfc_err("Allocating DESC buffer failed\n");
> >               return -ENOMEM;
> >       }
> > -     ctx->desc_phys = s5p_mfc_mem_cookie(
> > -                     dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
> > ctx->desc_buf);
> > -     BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> > -     desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf);
> > -     if (desc_virt == NULL) {
> > -             vb2_dma_contig_memops.put(ctx->desc_buf);
> > -             ctx->desc_phys = 0;
> > -             ctx->desc_buf = NULL;
> > -             mfc_err("Remapping DESC buffer failed\n");
> > -             return -ENOMEM;
> > -     }
> > -     memset(desc_virt, 0, DESC_BUF_SIZE);
> > -     wmb();
>
> Why was this removed?
> The driver should work with older firmware versions on Exynos4/S5PC110.
> I remember that zeroing the desc buffer was (and still is?) mandatory.
>

This was removed in the original patch itself. I tested it on Exynos4 origen board
and it worked without any problems.
Anyway memset seems logical and I will revert this change.


> [snip]
>
> >
> > @@ -1395,3 +1471,21 @@ void s5p_mfc_cleanup_queue(struct list_head *lh,
> > struct vb2_queue *vq)
> >       }
> >  }
> >
> > +void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
> > +{
> > +     mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
> > +     mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> > +     mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
> > +}
> > +
> > +void s5p_mfc_write_info(struct s5p_mfc_ctx *ctx, unsigned int data,
> > +                     unsigned int ofs)
> > +{
> > +     s5p_mfc_write_shm(ctx, data, ofs);
> > +}
> > +
> > +unsigned int s5p_mfc_read_info(struct s5p_mfc_ctx *ctx,
> > +                             unsigned int ofs)
> > +{
> > +     return s5p_mfc_read_shm(ctx, ofs);
>
> About s5p_mfc_*_shm functions. If you are adding this kind of support for
> two variants of MFC then maybe it would be a good idea to remove the
> s5p_mfc_shm.c and s5p_mfc_shm.h files altogether. All register definitions
> are already in the regs-mfc.h and regs-mfc-v6.h files. Instead of calling
> s5p_mfc_*_shm from s5p_mfc_*_info it might be better to do the hardware
> calls there. Also s5p_mfc_init_shm can be move to
> s5p_mfc_alloc_instance_buffer.
>

Yes right. I will change it.

> > +}
>
> [snip]
>
> > diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
> > b/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
> > index 738a607..4fa0b54 100644
> > --- a/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
> > +++ b/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
> > @@ -20,7 +20,11 @@
> >  #include "s5p_mfc_debug.h"
> >  #include "s5p_mfc_pm.h"
> >
> > -#define MFC_CLKNAME          "sclk_mfc"
> > +#if defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V5)
> > +#define MFC_CLKNAME            "sclk_mfc"
> > +#elif defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V6)
> > +#define MFC_CLKNAME            "aclk_333"
> > +#endif
> >  #define MFC_GATE_CLK_NAME    "mfc"
>
> Maybe it would be better to check the variant during init
> than use a define.
>

Yes. I will change it.

Regards
Arun

^ permalink raw reply	[flat|nested] 5+ messages in thread

* RE: [PATCH v2 2/2] [media] s5p-mfc: update MFC v4l2 driver to support MFC6.x
  2012-07-06 14:00 ` [PATCH v2 2/2] [media] s5p-mfc: " Arun Kumar K
  2012-07-06 14:21   ` Kyungmin Park
@ 2012-07-10 15:10   ` Kamil Debski
  1 sibling, 0 replies; 5+ messages in thread
From: Kamil Debski @ 2012-07-10 15:10 UTC (permalink / raw)
  To: 'Arun Kumar K', linux-media
  Cc: jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen, Marek Szyprowski,
	Sylwester Nawrocki, hans.verkuil, mchehab

Hi Arun,

Please find some additional comments below.

> From: Arun Kumar K [mailto:arun.kk@samsung.com]
> Sent: 06 July 2012 16:00

[snip]


> diff --git a/drivers/media/video/s5p-mfc/Makefile
> b/drivers/media/video/s5p-mfc/Makefile
> index d066340..0308d74 100644
> --- a/drivers/media/video/s5p-mfc/Makefile
> +++ b/drivers/media/video/s5p-mfc/Makefile
> @@ -1,5 +1,6 @@
>  obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o
> -s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o s5p_mfc_opr.o
> +s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o
>  s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o
> -s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_cmd.o
> -s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_shm.o
> +s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_pm.o
> +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V5) += s5p_mfc_opr.o s5p_mfc_cmd.o
> s5p_mfc_shm.o
> +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V6) += s5p_mfc_opr_v6.o
> s5p_mfc_cmd_v6.o
> diff --git a/drivers/media/video/s5p-mfc/regs-mfc-v6.h
> b/drivers/media/video/s5p-mfc/regs-mfc-v6.h
> new file mode 100644
> index 0000000..f22a159

This Makefile does not work when compiling the driver as a module.
(I also wrote about this in my previous email)

[snip]

> 
>  #endif /* _REGS_FIMV_H */
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c
> b/drivers/media/video/s5p-mfc/s5p_mfc.c
> index 9bb68e7..bec94bc 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc.c

[snip]

> @@ -285,12 +276,13 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx
> *ctx,
> 
>  	dst_frame_status = s5p_mfc_get_dspl_status()
>  				& S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
> -	res_change = s5p_mfc_get_dspl_status()
> -				& S5P_FIMV_DEC_STATUS_RESOLUTION_MASK;
> +	res_change = (s5p_mfc_get_dspl_status()
> +				& S5P_FIMV_DEC_STATUS_RESOLUTION_MASK)
> +				>> S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT;
>  	mfc_debug(2, "Frame Status: %x\n", dst_frame_status);
>  	if (ctx->state == MFCINST_RES_CHANGE_INIT)
>  		ctx->state = MFCINST_RES_CHANGE_FLUSH;
> -	if (res_change) {
> +	if (res_change && res_change != 3) {

Maybe 
If (res_change == 1 || res_change == 2) {
would be better, at least it would be more clear.

[snip]


> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_common.h
> b/drivers/media/video/s5p-mfc/s5p_mfc_common.h
> index bd5706a..8c646f4 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_common.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_common.h

[snip]

> @@ -499,37 +563,42 @@ struct s5p_mfc_ctx {
>  	int display_delay;
>  	int display_delay_enable;
>  	int after_packed_pb;
> +	int sei_fp_parse;
> 
>  	int dpb_count;
>  	int total_dpb_count;
> 
>  	/* Buffers */
> -	void *ctx_buf;
> -	size_t ctx_phys;
> -	size_t ctx_ofs;
> -	size_t ctx_size;
> -
> -	void *desc_buf;
> -	size_t desc_phys;
> -
> -
> -	void *shm_alloc;
> -	void *shm;
> -	size_t shm_ofs;
> +	unsigned int ctx_size;
> +	struct s5p_mfc_priv_buf ctx;
> +	struct s5p_mfc_priv_buf dsc;
> +	struct s5p_mfc_priv_buf shm;

I think that ctx_size could be integrated in struct s5p_mfc_priv_buf.
Also - why unsigned int, where in other places you use size_t for size?
I think it should be consistent. I would choose size_t.

> 
>  	struct s5p_mfc_enc_params enc_params;
> 
>  	size_t enc_dst_buf_size;
> +	size_t luma_dpb_size;
> +	size_t chroma_dpb_size;
> +	size_t me_buffer_size;
> +	size_t tmv_buffer_size;
> 

^^ You use size_t here.

[snip]

> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
> b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
> index 08a5cfe..65ff15d 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
> @@ -15,7 +15,6 @@
>  #include <linux/firmware.h>
>  #include <linux/jiffies.h>
>  #include <linux/sched.h>
> -#include "regs-mfc.h"
>  #include "s5p_mfc_cmd.h"
>  #include "s5p_mfc_common.h"
>  #include "s5p_mfc_debug.h"
> @@ -38,12 +37,12 @@ int s5p_mfc_alloc_and_load_firmware(struct
> s5p_mfc_dev *dev)
>  	 * into kernel. */
>  	mfc_debug_enter();
>  	err = request_firmware((const struct firmware **)&fw_blob,
> -				     "s5p-mfc.fw", dev->v4l2_dev.dev);
> +				     "mfc_fw.bin", dev->v4l2_dev.dev);

Another name change? This is getting ridiculous. Nein, nein, nein ! ;)
If you _*really*_ need such a change then go ahead and try to convince
me, but I tell you - it's going to be hard.

>  	if (err != 0) {
>  		mfc_err("Firmware is not present in the /lib/firmware
> directory nor compiled in kernel\n");
>  		return -EINVAL;
>  	}
> -	dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN);
> +	dev->fw_size = dev->variant->buf_size->fw;

Why is size taken from there instead of the size of the firmware file?
Even if there was some point to do it this way then you really *should*
check if the firmware read from the file fits in the allocated buffer.

This is a straight way to a buffer overflow error. All I need is to
prepare an extra big firmware file and "viola!" we have a buffer overflow
that could be fatal to the system. 

>  	if (s5p_mfc_bitproc_buf) {
>  		mfc_err("Attempting to allocate firmware when it seems that
> it is already loaded\n");
>  		release_firmware(fw_blob);
> @@ -77,28 +76,33 @@ int s5p_mfc_alloc_and_load_firmware(struct
> s5p_mfc_dev *dev)
>  		return -EIO;
>  	}
>  	dev->bank1 = s5p_mfc_bitproc_phys;
> -	b_base = vb2_dma_contig_memops.alloc(
> -		dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 <<
> MFC_BANK2_ALIGN_ORDER);
> -	if (IS_ERR(b_base)) {
> -		vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> -		s5p_mfc_bitproc_phys = 0;
> -		s5p_mfc_bitproc_buf = NULL;
> -		mfc_err("Allocating bank2 base failed\n");
> -	release_firmware(fw_blob);
> -		return -ENOMEM;
> -	}
> -	bank2_base_phys = s5p_mfc_mem_cookie(
> -		dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
> -	vb2_dma_contig_memops.put(b_base);
> -	if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
> -		mfc_err("The base memory for bank 2 is not aligned to
> 128KB\n");
> -		vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> -		s5p_mfc_bitproc_phys = 0;
> -		s5p_mfc_bitproc_buf = NULL;
> -		release_firmware(fw_blob);
> -		return -EIO;
> +	if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) {
> +		b_base = vb2_dma_contig_memops.alloc(
> +			dev->alloc_ctx[MFC_BANK2_ALLOC_CTX],
> +			1 << MFC_BANK2_ALIGN_ORDER);
> +		if (IS_ERR(b_base)) {
> +			vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> +			s5p_mfc_bitproc_phys = 0;
> +			s5p_mfc_bitproc_buf = 0;
> +			mfc_err("Allocating bank2 base failed\n");
> +			release_firmware(fw_blob);
> +			return -ENOMEM;
> +		}
> +		bank2_base_phys = s5p_mfc_mem_cookie(
> +			dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
> +		vb2_dma_contig_memops.put(b_base);
> +		if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
> +			mfc_err("The base memory for bank 2 is not aligned to
> 128KB\n");
> +			vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> +			s5p_mfc_bitproc_phys = 0;
> +			s5p_mfc_bitproc_buf = 0;
> +			release_firmware(fw_blob);
> +			return -EIO;
> +		}
> +		dev->bank2 = bank2_base_phys;
> +	} else {
> +		dev->bank2 = dev->bank1;
>  	}
> -	dev->bank2 = bank2_base_phys;
>  	memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
>  	wmb();
>  	release_firmware(fw_blob);
> @@ -116,7 +120,7 @@ int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
>  	 * into kernel. */
>  	mfc_debug_enter();
>  	err = request_firmware((const struct firmware **)&fw_blob,
> -				     "s5p-mfc.fw", dev->v4l2_dev.dev);
> +				     "mfc_fw.bin", dev->v4l2_dev.dev);

Ditto.

[snip]


> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
> b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
> index 61dc23b..b72c8c6 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h

[snip]

> 
> @@ -336,21 +364,35 @@ static int vidioc_g_fmt(struct file *file, void
> *priv, struct v4l2_format *f)
>  /* Try format */
>  static int vidioc_try_fmt(struct file *file, void *priv, struct
> v4l2_format *f)
>  {
> +	struct s5p_mfc_dev *dev = video_drvdata(file);
>  	struct s5p_mfc_fmt *fmt;
> 
> -	if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> -		mfc_err("This node supports decoding only\n");
> -		return -EINVAL;
> -	}
> -	fmt = find_format(f, MFC_FMT_DEC);
> -	if (!fmt) {
> -		mfc_err("Unsupported format\n");
> -		return -EINVAL;
> -	}
> -	if (fmt->type != MFC_FMT_DEC) {
> -		mfc_err("\n");
> -		return -EINVAL;
> +	mfc_debug(2, "Type is %d\n", f->type);
> +	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> +		fmt = find_format(f, MFC_FMT_DEC);
> +		if (!fmt) {
> +			mfc_err("Unsupported format for source.\n");
> +			return -EINVAL;
> +		}
> +		if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
> +			mfc_err("Not supported format.\n");
> +			return -EINVAL;
> +		}
> +	} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
> +		fmt = find_format(f, MFC_FMT_RAW);
> +		if (!fmt) {
> +			mfc_err("Unsupported format for destination.\n");
> +			return -EINVAL;
> +		}
> +		if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {

Ok. Let's see.
If IS_MFCV6(dev) is 1 and
fmt->fourcc == V4L2_PIX_FMT_NV12MT is 0
then the following code is not run.

> +			mfc_err("Not supported format.\n");
> +			return -EINVAL;

And we get here.

> +		} else if (fmt->fourcc != V4L2_PIX_FMT_NV12MT) {

fmt->fourcc == V4L2_PIX_FMT_NV12MT is still 0, so
fmt->fourcc != V4L2_PIX_FMT_NV12MT is 1 and this code is run

> +			mfc_err("Not supported format.\n");
> +			return -EINVAL;
> +		}
>  	}
> +
>  	return 0;
>  }

My question is - what targets did you run this code on? Did you run it
on Exynos5 with MFC v6? Arun, it is important that you test the patches
that you send to the mailing list. Maybe you have sent different files
than the ones you have tested?

[snip]

diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
index 03d8334..645a8ef 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
@@ -24,48 +24,63 @@
 #include <linux/workqueue.h>
 #include <media/v4l2-ctrls.h>
 #include <media/videobuf2-core.h>
-#include "regs-mfc.h"
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_enc.h"
 #include "s5p_mfc_intr.h"
-#include "s5p_mfc_opr.h"
+
+#define DEF_SRC_FMT	2
+#define DEF_DST_FMT	4

I would add ENC/DEC to the name of this define as it has confused me
because there are two symbols with the same name in different files.
Same applies to the s5p_mfc_dec.c file.

[snip] 

diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
b/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
index 405bdd3..413f22f 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
@@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void);
 struct s5p_mfc_fmt *get_enc_def_fmt(bool src);
 int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx);
 void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx);
 
 #endif /* S5P_MFC_ENC_H_  */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
b/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
index 8f2f8bf..dfdc558 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
@@ -17,7 +17,6 @@
 #include <linux/io.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
-#include "regs-mfc.h"
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_intr.h"


> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
> b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
> index e6217cb..1fd9c92 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
> @@ -12,15 +12,12 @@
>   * published by the Free Software Foundation.
>   */
> 
> -#include "regs-mfc.h"
> -#include "s5p_mfc_cmd.h"
>  #include "s5p_mfc_common.h"
> +#include "s5p_mfc_cmd.h"
>  #include "s5p_mfc_ctrl.h"
>  #include "s5p_mfc_debug.h"
>  #include "s5p_mfc_intr.h"
> -#include "s5p_mfc_opr.h"
>  #include "s5p_mfc_pm.h"
> -#include "s5p_mfc_shm.h"
>  #include <asm/cacheflush.h>
>  #include <linux/delay.h>
>  #include <linux/dma-mapping.h>
> @@ -37,39 +34,31 @@
>  /* Allocate temporary buffers for decoding */
>  int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx)
>  {
> -	void *desc_virt;
>  	struct s5p_mfc_dev *dev = ctx->dev;
> +	struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
> 
> -	ctx->desc_buf = vb2_dma_contig_memops.alloc(
> -			dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], DESC_BUF_SIZE);
> -	if (IS_ERR_VALUE((int)ctx->desc_buf)) {
> -		ctx->desc_buf = NULL;
> +	ctx->dsc.alloc = vb2_dma_contig_memops.alloc(
> +			dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
> +			buf_size->dsc);
> +	if (IS_ERR_VALUE((int)ctx->dsc.alloc)) {
> +		ctx->dsc.alloc = NULL;
>  		mfc_err("Allocating DESC buffer failed\n");
>  		return -ENOMEM;
>  	}
> -	ctx->desc_phys = s5p_mfc_mem_cookie(
> -			dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->desc_buf);
> -	BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> -	desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf);
> -	if (desc_virt == NULL) {
> -		vb2_dma_contig_memops.put(ctx->desc_buf);
> -		ctx->desc_phys = 0;
> -		ctx->desc_buf = NULL;
> -		mfc_err("Remapping DESC buffer failed\n");
> -		return -ENOMEM;
> -	}
> -	memset(desc_virt, 0, DESC_BUF_SIZE);
> -	wmb();

Why was this removed?
The driver should work with older firmware versions on Exynos4/S5PC110.
I remember that zeroing the desc buffer was (and still is?) mandatory.

[snip]

> 
> @@ -1395,3 +1471,21 @@ void s5p_mfc_cleanup_queue(struct list_head *lh,
> struct vb2_queue *vq)
>  	}
>  }
> 
> +void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
> +{
> +	mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
> +	mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> +	mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
> +}
> +
> +void s5p_mfc_write_info(struct s5p_mfc_ctx *ctx, unsigned int data,
> +			unsigned int ofs)
> +{
> +	s5p_mfc_write_shm(ctx, data, ofs);
> +}
> +
> +unsigned int s5p_mfc_read_info(struct s5p_mfc_ctx *ctx,
> +				unsigned int ofs)
> +{
> +	return s5p_mfc_read_shm(ctx, ofs);

About s5p_mfc_*_shm functions. If you are adding this kind of support for
two variants of MFC then maybe it would be a good idea to remove the
s5p_mfc_shm.c and s5p_mfc_shm.h files altogether. All register definitions
are already in the regs-mfc.h and regs-mfc-v6.h files. Instead of calling
s5p_mfc_*_shm from s5p_mfc_*_info it might be better to do the hardware
calls there. Also s5p_mfc_init_shm can be move to
s5p_mfc_alloc_instance_buffer.

> +}

[snip]

> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
> b/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
> index 738a607..4fa0b54 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
> @@ -20,7 +20,11 @@
>  #include "s5p_mfc_debug.h"
>  #include "s5p_mfc_pm.h"
> 
> -#define MFC_CLKNAME		"sclk_mfc"
> +#if defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V5)
> +#define MFC_CLKNAME            "sclk_mfc"
> +#elif defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V6)
> +#define MFC_CLKNAME            "aclk_333"
> +#endif
>  #define MFC_GATE_CLK_NAME	"mfc"

Maybe it would be better to check the variant during init
than use a define. 

> 
>  #define CLK_DEBUG
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
> b/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
> index 91fdbac..9ee269d 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
> @@ -21,26 +21,28 @@ int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx)
>  {
>  	struct s5p_mfc_dev *dev = ctx->dev;
>  	void *shm_alloc_ctx = dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
> +	struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
> 
> -	ctx->shm_alloc = vb2_dma_contig_memops.alloc(shm_alloc_ctx,
> -							SHARED_BUF_SIZE);
> -	if (IS_ERR(ctx->shm_alloc)) {
> +	ctx->shm.alloc = vb2_dma_contig_memops.alloc(shm_alloc_ctx,
> +							buf_size->shm);
> +	if (IS_ERR(ctx->shm.alloc)) {
>  		mfc_err("failed to allocate shared memory\n");
> -		return PTR_ERR(ctx->shm_alloc);
> +		return PTR_ERR(ctx->shm.alloc);
>  	}
> -	/* shm_ofs only keeps the offset from base (port a) */
> -	ctx->shm_ofs = s5p_mfc_mem_cookie(shm_alloc_ctx, ctx->shm_alloc)
> +	/* shared memory offset only keeps the offset from base (port a) */
> +	ctx->shm.ofs = s5p_mfc_mem_cookie(shm_alloc_ctx, ctx->shm.alloc)
>  								- dev->bank1;
> -	BUG_ON(ctx->shm_ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> -	ctx->shm = vb2_dma_contig_memops.vaddr(ctx->shm_alloc);
> -	if (!ctx->shm) {
> -		vb2_dma_contig_memops.put(ctx->shm_alloc);
> -		ctx->shm_ofs = 0;
> -		ctx->shm_alloc = NULL;
> +	BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> +
> +	ctx->shm.virt = vb2_dma_contig_memops.vaddr(ctx->shm.alloc);
> +	if (!ctx->shm.virt) {
> +		vb2_dma_contig_memops.put(ctx->shm.alloc);
> +		ctx->shm.alloc = NULL;
> +		ctx->shm.ofs = 0;
>  		mfc_err("failed to virt addr of shared memory\n");
>  		return -ENOMEM;
>  	}
> -	memset((void *)ctx->shm, 0, SHARED_BUF_SIZE);
> +	memset((void *)ctx->shm.virt, 0, buf_size->shm);
>  	wmb();
>  	return 0;
>  }
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
> b/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
> index cf962a4..8400ab0 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
> @@ -71,20 +71,23 @@ enum MFC_SHM_OFS {
>  	DBG_HISTORY_INPUT1	= 0xD4,	/* C */
>  	DBG_HISTORY_OUTPUT	= 0xD8,	/* C */
>  	HIERARCHICAL_P_QP	= 0xE0, /* E, H.264 */
> +	FRAME_PACK_SEI_ENABLE	= 0x168, /* C */
> +	FRAME_PACK_SEI_AVAIL	= 0x16c, /* D */
> +	FRAME_PACK_SEI_INFO	= 0x17c, /* E */
>  };
> 
>  int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx);
> 
> -#define s5p_mfc_write_shm(ctx, x, ofs)		\
> -	do {					\
> -		writel(x, (ctx->shm + ofs));	\
> -		wmb();				\
> +#define s5p_mfc_write_shm(ctx, x, ofs)			\
> +	do {						\
> +		writel(x, (ctx->shm.virt + ofs));	\
> +		wmb();					\
>  	} while (0)
> 
>  static inline u32 s5p_mfc_read_shm(struct s5p_mfc_ctx *ctx, unsigned int
> ofs)
>  {
>  	rmb();
> -	return readl(ctx->shm + ofs);
> +	return readl(ctx->shm.virt + ofs);
>  }
> 
>  #endif /* S5P_MFC_SHM_H_ */
> diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-
> ctrls.c
> index 9abd9ab..61d6583 100644
> --- a/drivers/media/video/v4l2-ctrls.c
> +++ b/drivers/media/video/v4l2-ctrls.c
> @@ -502,7 +502,6 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
>  		return mpeg4_profile;
>  	case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
>  		return jpeg_chroma_subsampling;
> -
>  	default:
>  		return NULL;
>  	}
> --
> 1.7.0.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 2/2] [media] s5p-mfc: update MFC v4l2 driver to support MFC6.x
  2012-07-06 14:00 ` [PATCH v2 2/2] [media] s5p-mfc: " Arun Kumar K
@ 2012-07-06 14:21   ` Kyungmin Park
  2012-07-10 15:10   ` Kamil Debski
  1 sibling, 0 replies; 5+ messages in thread
From: Kyungmin Park @ 2012-07-06 14:21 UTC (permalink / raw)
  To: Arun Kumar K
  Cc: linux-media, jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen,
	m.szyprowski, k.debski, s.nawrocki, hans.verkuil, mchehab

Hi,

On Fri, Jul 6, 2012 at 11:00 PM, Arun Kumar K <arun.kk@samsung.com> wrote:
> From: Jeongtae Park <jtp.park@samsung.com>
>
> Multi Format Codec 6.x is a hardware video coding acceleration
> module fount in new Exynos5 SoC series.
> It is capable of handling a range of video codecs and this driver
> provides a V4L2 interface for video decoding and encoding.
>
> Signed-off-by: Jeongtae Park <jtp.park@samsung.com>
> Singed-off-by: Janghyuck Kim <janghyuck.kim@samsung.com>
> Singed-off-by: Jaeryul Oh <jaeryul.oh@samsung.com>
> Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
> Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Cc: Kamil Debski <k.debski@samsung.com>
> ---
>  drivers/media/video/Kconfig                  |   16 +-
>  drivers/media/video/s5p-mfc/Makefile         |    7 +-
>  drivers/media/video/s5p-mfc/regs-mfc-v6.h    |  676 ++++++++++
>  drivers/media/video/s5p-mfc/regs-mfc.h       |   29 +
>  drivers/media/video/s5p-mfc/s5p_mfc.c        |  163 ++-
>  drivers/media/video/s5p-mfc/s5p_mfc_cmd.c    |    6 +-
>  drivers/media/video/s5p-mfc/s5p_mfc_cmd.h    |    3 +
>  drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c |   96 ++
>  drivers/media/video/s5p-mfc/s5p_mfc_common.h |  123 ++-
>  drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c   |  160 ++-
>  drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h   |    1 +
>  drivers/media/video/s5p-mfc/s5p_mfc_dec.c    |  210 +++-
>  drivers/media/video/s5p-mfc/s5p_mfc_dec.h    |    1 +
>  drivers/media/video/s5p-mfc/s5p_mfc_enc.c    |  191 ++--
>  drivers/media/video/s5p-mfc/s5p_mfc_enc.h    |    1 +
>  drivers/media/video/s5p-mfc/s5p_mfc_intr.c   |    1 -
>  drivers/media/video/s5p-mfc/s5p_mfc_opr.c    |  278 +++--
>  drivers/media/video/s5p-mfc/s5p_mfc_opr.h    |   25 +-
>  drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c | 1697 ++++++++++++++++++++++++++
>  drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h |  140 +++
>  drivers/media/video/s5p-mfc/s5p_mfc_pm.c     |    6 +-
>  drivers/media/video/s5p-mfc/s5p_mfc_shm.c    |   28 +-
>  drivers/media/video/s5p-mfc/s5p_mfc_shm.h    |   13 +-
>  drivers/media/video/v4l2-ctrls.c             |    1 -
>  24 files changed, 3476 insertions(+), 396 deletions(-)

Doesn't it too big for one patch? Can you split it into several patches?

>  create mode 100644 drivers/media/video/s5p-mfc/regs-mfc-v6.h
>  create mode 100644 drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c
>  create mode 100644 drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c
>  create mode 100644 drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h
>
> diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
> index 99937c9..0d7fe77 100644
> --- a/drivers/media/video/Kconfig
> +++ b/drivers/media/video/Kconfig
> @@ -1198,13 +1198,27 @@ config VIDEO_SAMSUNG_S5P_JPEG
>           This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec
>
>  config VIDEO_SAMSUNG_S5P_MFC
> +       bool
> +
> +config VIDEO_SAMSUNG_S5P_MFC_V5
>         tristate "Samsung S5P MFC 5.1 Video Codec"
> -       depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
> +       depends on VIDEO_DEV && VIDEO_V4L2 && ARCH_EXYNOS4
> +       select VIDEO_SAMSUNG_S5P_MFC
>         select VIDEOBUF2_DMA_CONTIG
>         default n
>         help
>             MFC 5.1 driver for V4L2.
>
> +config VIDEO_SAMSUNG_S5P_MFC_V6

Yes, I know it's exynos5 series features. however, it's not good idea
to add new config.
It already handled platform device with proper name.
e.g., s5p-mfc-v5, s5p-mfc-v6 and handle it with platform data.

> +       tristate "Samsung S5P MFC 6.x Video Codec"
> +       depends on VIDEO_DEV && VIDEO_V4L2 && ARCH_EXYNOS5
> +       select VIDEO_SAMSUNG_S5P_MFC
> +       select VIDEOBUF2_DMA_CONTIG
> +       select DMA_SHARED_BUFFER
> +       default n
> +       help
> +           MFC 6.x driver for V4L2.
> +
>  config VIDEO_MX2_EMMAPRP
>         tristate "MX2 eMMa-PrP support"
>         depends on VIDEO_DEV && VIDEO_V4L2 && SOC_IMX27
> diff --git a/drivers/media/video/s5p-mfc/Makefile b/drivers/media/video/s5p-mfc/Makefile
> index d066340..0308d74 100644
> --- a/drivers/media/video/s5p-mfc/Makefile
> +++ b/drivers/media/video/s5p-mfc/Makefile
> @@ -1,5 +1,6 @@
>  obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o
> -s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o s5p_mfc_opr.o
> +s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o
>  s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o
> -s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_cmd.o
> -s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_shm.o
> +s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_pm.o
> +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V5) += s5p_mfc_opr.o s5p_mfc_cmd.o s5p_mfc_shm.o
> +obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V6) += s5p_mfc_opr_v6.o s5p_mfc_cmd_v6.o
> diff --git a/drivers/media/video/s5p-mfc/regs-mfc-v6.h b/drivers/media/video/s5p-mfc/regs-mfc-v6.h
> new file mode 100644
> index 0000000..f22a159
> --- /dev/null
> +++ b/drivers/media/video/s5p-mfc/regs-mfc-v6.h
> @@ -0,0 +1,676 @@
> +/*
> + * Register definition file for Samsung MFC V6.x Interface (FIMV) driver
> + *
> + * Copyright (c) 2012 Samsung Electronics
> + *             http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef _REGS_FIMV_V6_H
> +#define _REGS_FIMV_V6_H
> +
> +#define S5P_FIMV_REG_SIZE      (S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
> +#define S5P_FIMV_REG_COUNT     ((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
> +
> +/* Number of bits that the buffer address should be shifted for particular
> + * MFC buffers.  */
> +#define S5P_FIMV_MEM_OFFSET            0
> +
> +#define S5P_FIMV_START_ADDR            0x0000
> +#define S5P_FIMV_END_ADDR              0xfd80
> +
> +#define S5P_FIMV_REG_CLEAR_BEGIN       0xf000
> +#define S5P_FIMV_REG_CLEAR_COUNT       1024
> +
> +/* Codec Common Registers */
> +#define S5P_FIMV_RISC_ON                       0x0000
> +#define S5P_FIMV_RISC2HOST_INT                 0x003C
> +#define S5P_FIMV_HOST2RISC_INT                 0x0044
> +#define S5P_FIMV_RISC_BASE_ADDRESS             0x0054
> +
> +#define S5P_FIMV_MFC_RESET                     0x1070
> +
> +#define S5P_FIMV_HOST2RISC_CMD                 0x1100
> +#define S5P_FIMV_H2R_CMD_EMPTY                 0
> +#define S5P_FIMV_H2R_CMD_SYS_INIT              1
> +#define S5P_FIMV_H2R_CMD_OPEN_INSTANCE         2
> +#define S5P_FIMV_CH_SEQ_HEADER                 3
> +#define S5P_FIMV_CH_INIT_BUFS                  4
> +#define S5P_FIMV_CH_FRAME_START                        5
> +#define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE                6
> +#define S5P_FIMV_H2R_CMD_SLEEP                 7
> +#define S5P_FIMV_H2R_CMD_WAKEUP                        8
> +#define S5P_FIMV_CH_LAST_FRAME                 9
> +#define S5P_FIMV_H2R_CMD_FLUSH                 10
> +/* RMVME: REALLOC used? */
> +#define S5P_FIMV_CH_FRAME_START_REALLOC                5
> +
> +#define S5P_FIMV_RISC2HOST_CMD                 0x1104
> +#define S5P_FIMV_R2H_CMD_EMPTY                 0
> +#define S5P_FIMV_R2H_CMD_SYS_INIT_RET          1
> +#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET     2
> +#define S5P_FIMV_R2H_CMD_SEQ_DONE_RET          3
> +#define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET      4
> +
> +#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET    6
> +#define S5P_FIMV_R2H_CMD_SLEEP_RET             7
> +#define S5P_FIMV_R2H_CMD_WAKEUP_RET            8
> +#define S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET      9
> +#define S5P_FIMV_R2H_CMD_DPB_FLUSH_RET         10
> +#define S5P_FIMV_R2H_CMD_NAL_ABORT_RET         11
> +#define S5P_FIMV_R2H_CMD_FW_STATUS_RET         12
> +#define S5P_FIMV_R2H_CMD_FRAME_DONE_RET                13
> +#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET                14
> +#define S5P_FIMV_R2H_CMD_SLICE_DONE_RET                15
> +#define S5P_FIMV_R2H_CMD_ENC_BUFFER_FUL_RET    16
> +#define S5P_FIMV_R2H_CMD_ERR_RET               32
> +
> +#define S5P_FIMV_FW_VERSION                    0xF000
> +
> +#define S5P_FIMV_INSTANCE_ID                   0xF008
> +#define S5P_FIMV_CODEC_TYPE                    0xF00C
> +#define S5P_FIMV_CONTEXT_MEM_ADDR              0xF014
> +#define S5P_FIMV_CONTEXT_MEM_SIZE              0xF018
> +#define S5P_FIMV_PIXEL_FORMAT                  0xF020
> +
> +#define S5P_FIMV_METADATA_ENABLE               0xF024
> +#define S5P_FIMV_DBG_BUFFER_ADDR               0xF030
> +#define S5P_FIMV_DBG_BUFFER_SIZE               0xF034
> +#define S5P_FIMV_RET_INSTANCE_ID               0xF070
> +
> +#define S5P_FIMV_ERROR_CODE                    0xF074
> +#define S5P_FIMV_ERR_WARNINGS_START            160
> +#define S5P_FIMV_ERR_DEC_MASK                  0xFFFF
> +#define S5P_FIMV_ERR_DEC_SHIFT                 0
> +#define S5P_FIMV_ERR_DSPL_MASK                 0xFFFF0000
> +#define S5P_FIMV_ERR_DSPL_SHIFT                        16
> +
> +#define S5P_FIMV_DBG_BUFFER_OUTPUT_SIZE                0xF078
> +#define S5P_FIMV_METADATA_STATUS               0xF07C
> +#define S5P_FIMV_METADATA_ADDR_MB_INFO         0xF080
> +#define S5P_FIMV_METADATA_SIZE_MB_INFO         0xF084
> +
> +/* Decoder Registers */
> +#define S5P_FIMV_D_CRC_CTRL                    0xF0B0
> +#define S5P_FIMV_D_DEC_OPTIONS                 0xF0B4
> +#define S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK       4
> +#define S5P_FIMV_D_OPT_DDELAY_EN_SHIFT         3
> +#define S5P_FIMV_D_OPT_LF_CTRL_SHIFT           1
> +#define S5P_FIMV_D_OPT_LF_CTRL_MASK            0x3
> +#define S5P_FIMV_D_OPT_TILE_MODE_SHIFT         0
> +
> +#define S5P_FIMV_D_DISPLAY_DELAY               0xF0B8
> +
> +#define S5P_FIMV_D_SET_FRAME_WIDTH             0xF0BC
> +#define S5P_FIMV_D_SET_FRAME_HEIGHT            0xF0C0
> +
> +#define S5P_FIMV_D_SEI_ENABLE                  0xF0C4
> +
> +/* Buffer setting registers */
> +#define S5P_FIMV_D_MIN_NUM_DPB                 0xF0F0
> +#define S5P_FIMV_D_MIN_LUMA_DPB_SIZE           0xF0F4
> +#define S5P_FIMV_D_MIN_CHROMA_DPB_SIZE         0xF0F8
> +#define S5P_FIMV_D_MVC_NUM_VIEWS               0xF0FC
> +#define S5P_FIMV_D_NUM_DPB                     0xF130
> +#define S5P_FIMV_D_LUMA_DPB_SIZE               0xF134
> +#define S5P_FIMV_D_CHROMA_DPB_SIZE             0xF138
> +#define S5P_FIMV_D_MV_BUFFER_SIZE              0xF13C
> +
> +#define S5P_FIMV_D_LUMA_DPB                    0xF140
> +#define S5P_FIMV_D_CHROMA_DPB                  0xF240
> +#define S5P_FIMV_D_MV_BUFFER                   0xF340
> +
> +#define S5P_FIMV_D_SCRATCH_BUFFER_ADDR         0xF440
> +#define S5P_FIMV_D_SCRATCH_BUFFER_SIZE         0xF444
> +#define S5P_FIMV_D_METADATA_BUFFER_ADDR                0xF448
> +#define S5P_FIMV_D_METADATA_BUFFER_SIZE                0xF44C
> +#define S5P_FIMV_D_CPB_BUFFER_ADDR             0xF4B0
> +#define S5P_FIMV_D_CPB_BUFFER_SIZE             0xF4B4
> +
> +#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER    0xF4B8
> +#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER    0xF4BC
> +#define S5P_FIMV_D_CPB_BUFFER_OFFSET           0xF4C0
> +#define S5P_FIMV_D_SLICE_IF_ENABLE             0xF4C4
> +#define S5P_FIMV_D_PICTURE_TAG                 0xF4C8
> +#define S5P_FIMV_D_STREAM_DATA_SIZE            0xF4D0
> +
> +/* Display information register */
> +#define S5P_FIMV_D_DISPLAY_FRAME_WIDTH         0xF500
> +#define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT                0xF504
> +
> +/* Display status */
> +#define S5P_FIMV_D_DISPLAY_STATUS              0xF508
> +#define S5P_FIMV_DEC_STATUS_DECODING_ONLY              0
> +#define S5P_FIMV_DEC_STATUS_DECODING_DISPLAY           1
> +#define S5P_FIMV_DEC_STATUS_DISPLAY_ONLY               2
> +#define S5P_FIMV_DEC_STATUS_DECODING_EMPTY             3
> +#define S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK       7
> +#define S5P_FIMV_DEC_STATUS_PROGRESSIVE                        (0<<3)
> +#define S5P_FIMV_DEC_STATUS_INTERLACE                  (1<<3)
> +#define S5P_FIMV_DEC_STATUS_INTERLACE_MASK             (1<<3)
> +#define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK            (3<<4)
> +#define S5P_FIMV_DEC_STATUS_RESOLUTION_INC             (1<<4)
> +#define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC             (2<<4)
> +#define S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT           4
> +#define S5P_FIMV_DEC_STATUS_CRC_GENERATED              (1<<5)
> +#define S5P_FIMV_DEC_STATUS_CRC_NOT_GENERATED          (0<<5)
> +#define S5P_FIMV_DEC_STATUS_CRC_MASK                   (1<<5)
> +
> +#define S5P_FIMV_D_DISPLAY_LUMA_ADDR           0xF50C
> +#define S5P_FIMV_D_DISPLAY_CHROMA_ADDR         0xF510
> +
> +#define S5P_FIMV_D_DISPLAY_FRAME_TYPE          0xF514
> +#define S5P_FIMV_DECODE_FRAME_SKIPPED          0
> +#define S5P_FIMV_DECODE_FRAME_I_FRAME          1
> +#define S5P_FIMV_DECODE_FRAME_P_FRAME          2
> +#define S5P_FIMV_DECODE_FRAME_B_FRAME          3
> +#define S5P_FIMV_DECODE_FRAME_OTHER_FRAME      4
> +#define S5P_FIMV_SHARED_CROP_INFO_H            0x0020
> +#define S5P_FIMV_SHARED_CROP_LEFT_MASK         0xFFFF
> +#define S5P_FIMV_SHARED_CROP_LEFT_SHIFT                0
> +#define S5P_FIMV_SHARED_CROP_RIGHT_MASK                0xFFFF0000
> +#define S5P_FIMV_SHARED_CROP_RIGHT_SHIFT       16
> +#define S5P_FIMV_SHARED_CROP_INFO_V            0x0024
> +#define S5P_FIMV_SHARED_CROP_TOP_MASK          0xFFFF
> +#define S5P_FIMV_SHARED_CROP_TOP_SHIFT         0
> +#define S5P_FIMV_SHARED_CROP_BOTTOM_MASK       0xFFFF0000
> +#define S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT      16
> +
> +#define S5P_FIMV_D_DISPLAY_CROP_INFO1          0xF518
> +#define S5P_FIMV_D_DISPLAY_CROP_INFO2          0xF51C
> +#define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE     0xF520
> +#define S5P_FIMV_D_DISPLAY_LUMA_CRC_TOP                0xF524
> +#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_TOP      0xF528
> +#define S5P_FIMV_D_DISPLAY_LUMA_CRC_BOT                0xF52C
> +#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_BOT      0xF530
> +#define S5P_FIMV_D_DISPLAY_ASPECT_RATIO                0xF534
> +#define S5P_FIMV_D_DISPLAY_EXTENDED_AR         0xF538
> +
> +/* Decoded picture information register */
> +#define S5P_FIMV_D_DECODED_FRAME_WIDTH         0xF53C
> +#define S5P_FIMV_D_DECODED_FRAME_HEIGHT                0xF540
> +#define S5P_FIMV_D_DECODED_STATUS              0xF544
> +#define S5P_FIMV_DEC_CRC_GEN_MASK              0x1
> +#define S5P_FIMV_DEC_CRC_GEN_SHIFT             6
> +
> +#define S5P_FIMV_D_DECODED_LUMA_ADDR           0xF548
> +#define S5P_FIMV_D_DECODED_CHROMA_ADDR         0xF54C
> +
> +#define S5P_FIMV_D_DECODED_FRAME_TYPE          0xF550
> +#define S5P_FIMV_DECODE_FRAME_MASK             7
> +
> +#define S5P_FIMV_D_DECODED_CROP_INFO1          0xF554
> +#define S5P_FIMV_D_DECODED_CROP_INFO2          0xF558
> +#define S5P_FIMV_D_DECODED_PICTURE_PROFILE     0xF55C
> +#define S5P_FIMV_D_DECODED_NAL_SIZE            0xF560
> +#define S5P_FIMV_D_DECODED_LUMA_CRC_TOP                0xF564
> +#define S5P_FIMV_D_DECODED_CHROMA_CRC_TOP      0xF568
> +#define S5P_FIMV_D_DECODED_LUMA_CRC_BOT                0xF56C
> +#define S5P_FIMV_D_DECODED_CHROMA_CRC_BOT      0xF570
> +
> +/* Returned value register for specific setting */
> +#define S5P_FIMV_D_RET_PICTURE_TAG_TOP         0xF574
> +#define S5P_FIMV_D_RET_PICTURE_TAG_BOT         0xF578
> +#define S5P_FIMV_D_RET_PICTURE_TIME_TOP                0xF57C
> +#define S5P_FIMV_D_RET_PICTURE_TIME_BOT                0xF580
> +#define S5P_FIMV_D_CHROMA_FORMAT               0xF588
> +#define S5P_FIMV_D_MPEG4_INFO                  0xF58C
> +#define S5P_FIMV_D_H264_INFO                   0xF590
> +
> +#define S5P_FIMV_D_METADATA_ADDR_CONCEALED_MB  0xF594
> +#define S5P_FIMV_D_METADATA_SIZE_CONCEALED_MB  0xF598
> +#define S5P_FIMV_D_METADATA_ADDR_VC1_PARAM     0xF59C
> +#define S5P_FIMV_D_METADATA_SIZE_VC1_PARAM     0xF5A0
> +#define S5P_FIMV_D_METADATA_ADDR_SEI_NAL       0xF5A4
> +#define S5P_FIMV_D_METADATA_SIZE_SEI_NAL       0xF5A8
> +#define S5P_FIMV_D_METADATA_ADDR_VUI           0xF5AC
> +#define S5P_FIMV_D_METADATA_SIZE_VUI           0xF5B0
> +
> +#define S5P_FIMV_D_MVC_VIEW_ID                 0xF5B4
> +
> +/* SEI related information */
> +#define S5P_FIMV_D_FRAME_PACK_SEI_AVAIL                0xF5F0
> +#define S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID      0xF5F4
> +#define S5P_FIMV_D_FRAME_PACK_SEI_INFO         0xF5F8
> +#define S5P_FIMV_D_FRAME_PACK_GRID_POS         0xF5FC
> +
> +/* Encoder Registers */
> +#define S5P_FIMV_E_FRAME_WIDTH                 0xF770
> +#define S5P_FIMV_E_FRAME_HEIGHT                        0xF774
> +#define S5P_FIMV_E_CROPPED_FRAME_WIDTH         0xF778
> +#define S5P_FIMV_E_CROPPED_FRAME_HEIGHT                0xF77C
> +#define S5P_FIMV_E_FRAME_CROP_OFFSET           0xF780
> +#define S5P_FIMV_E_ENC_OPTIONS                 0xF784
> +#define S5P_FIMV_E_PICTURE_PROFILE             0xF788
> +#define S5P_FIMV_ENC_PROFILE_H264_MAIN                 0
> +#define S5P_FIMV_ENC_PROFILE_H264_HIGH                 1
> +#define S5P_FIMV_ENC_PROFILE_H264_BASELINE             2
> +#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE 3
> +#define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE              0
> +#define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE     1
> +#define S5P_FIMV_E_FIXED_PICTURE_QP            0xF790
> +
> +#define S5P_FIMV_E_RC_CONFIG                   0xF794
> +#define S5P_FIMV_E_RC_QP_BOUND                 0xF798
> +#define S5P_FIMV_E_RC_RPARAM                   0xF79C
> +#define S5P_FIMV_E_MB_RC_CONFIG                        0xF7A0
> +#define S5P_FIMV_E_PADDING_CTRL                        0xF7A4
> +#define S5P_FIMV_E_MV_HOR_RANGE                        0xF7AC
> +#define S5P_FIMV_E_MV_VER_RANGE                        0xF7B0
> +
> +#define S5P_FIMV_E_VBV_BUFFER_SIZE             0xF84C
> +#define S5P_FIMV_E_VBV_INIT_DELAY              0xF850
> +#define S5P_FIMV_E_NUM_DPB                     0xF890
> +#define S5P_FIMV_E_LUMA_DPB                    0xF8C0
> +#define S5P_FIMV_E_CHROMA_DPB                  0xF904
> +#define S5P_FIMV_E_ME_BUFFER                   0xF948
> +
> +#define S5P_FIMV_E_SCRATCH_BUFFER_ADDR         0xF98C
> +#define S5P_FIMV_E_SCRATCH_BUFFER_SIZE         0xF990
> +#define S5P_FIMV_E_TMV_BUFFER0                 0xF994
> +#define S5P_FIMV_E_TMV_BUFFER1                 0xF998
> +#define S5P_FIMV_E_SOURCE_LUMA_ADDR            0xF9F0
> +#define S5P_FIMV_E_SOURCE_CHROMA_ADDR          0xF9F4
> +#define S5P_FIMV_E_STREAM_BUFFER_ADDR          0xF9F8
> +#define S5P_FIMV_E_STREAM_BUFFER_SIZE          0xF9FC
> +#define S5P_FIMV_E_ROI_BUFFER_ADDR             0xFA00
> +
> +#define S5P_FIMV_E_PARAM_CHANGE                        0xFA04
> +#define S5P_FIMV_E_IR_SIZE                     0xFA08
> +#define S5P_FIMV_E_GOP_CONFIG                  0xFA0C
> +#define S5P_FIMV_E_MSLICE_MODE                 0xFA10
> +#define S5P_FIMV_E_MSLICE_SIZE_MB              0xFA14
> +#define S5P_FIMV_E_MSLICE_SIZE_BITS            0xFA18
> +#define S5P_FIMV_E_FRAME_INSERTION             0xFA1C
> +
> +#define S5P_FIMV_E_RC_FRAME_RATE               0xFA20
> +#define S5P_FIMV_E_RC_BIT_RATE                 0xFA24
> +#define S5P_FIMV_E_RC_QP_OFFSET                        0xFA28
> +#define S5P_FIMV_E_RC_ROI_CTRL                 0xFA2C
> +#define S5P_FIMV_E_PICTURE_TAG                 0xFA30
> +#define S5P_FIMV_E_BIT_COUNT_ENABLE            0xFA34
> +#define S5P_FIMV_E_MAX_BIT_COUNT               0xFA38
> +#define S5P_FIMV_E_MIN_BIT_COUNT               0xFA3C
> +
> +#define S5P_FIMV_E_METADATA_BUFFER_ADDR                0xFA40
> +#define S5P_FIMV_E_METADATA_BUFFER_SIZE                0xFA44
> +#define S5P_FIMV_E_STREAM_SIZE                 0xFA80
> +#define S5P_FIMV_E_SLICE_TYPE                  0xFA84
> +#define S5P_FIMV_ENC_SI_SLICE_TYPE_NON_CODED   0
> +#define S5P_FIMV_ENC_SI_SLICE_TYPE_I           1
> +#define S5P_FIMV_ENC_SI_SLICE_TYPE_P           2
> +#define S5P_FIMV_ENC_SI_SLICE_TYPE_B           3
> +#define S5P_FIMV_ENC_SI_SLICE_TYPE_SKIPPED     4
> +#define S5P_FIMV_ENC_SI_SLICE_TYPE_OTHERS      5
> +#define S5P_FIMV_E_PICTURE_COUNT               0xFA88
> +#define S5P_FIMV_E_RET_PICTURE_TAG             0xFA8C
> +#define S5P_FIMV_E_STREAM_BUFFER_WRITE_POINTER 0xFA90
> +
> +#define S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR    0xFA94
> +#define S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR  0xFA98
> +#define S5P_FIMV_E_RECON_LUMA_DPB_ADDR         0xFA9C
> +#define S5P_FIMV_E_RECON_CHROMA_DPB_ADDR       0xFAA0
> +#define S5P_FIMV_E_METADATA_ADDR_ENC_SLICE     0xFAA4
> +#define S5P_FIMV_E_METADATA_SIZE_ENC_SLICE     0xFAA8
> +
> +#define S5P_FIMV_E_MPEG4_OPTIONS               0xFB10
> +#define S5P_FIMV_E_MPEG4_HEC_PERIOD            0xFB14
> +#define S5P_FIMV_E_ASPECT_RATIO                        0xFB50
> +#define S5P_FIMV_E_EXTENDED_SAR                        0xFB54
> +
> +#define S5P_FIMV_E_H264_OPTIONS                        0xFB58
> +#define S5P_FIMV_E_H264_LF_ALPHA_OFFSET                0xFB5C
> +#define S5P_FIMV_E_H264_LF_BETA_OFFSET         0xFB60
> +#define S5P_FIMV_E_H264_I_PERIOD               0xFB64
> +
> +#define S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE                 0xFB68
> +#define S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1               0xFB6C
> +#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR               0xFB70
> +#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1       0xFB74
> +#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0        0xFB78
> +#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_1        0xFB7C
> +#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_2        0xFB80
> +#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_3        0xFB84
> +
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_0      0xFB88
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_1      0xFB8C
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_2      0xFB90
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_3      0xFB94
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_4      0xFB98
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_5      0xFB9C
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_6      0xFBA0
> +#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_7      0xFBA4
> +
> +#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET       0xFBA8
> +#define S5P_FIMV_E_H264_NUM_T_LAYER            0xFBAC
> +
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0 0xFBB0
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER1 0xFBB4
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER2 0xFBB8
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER3 0xFBBC
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER4 0xFBC0
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER5 0xFBC4
> +#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER6 0xFBC8
> +
> +#define S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO 0xFC4C
> +#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE  0
> +#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TOP_BOTTOM    1
> +#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TEMPORAL      2
> +
> +#define S5P_FIMV_E_MVC_FRAME_QP_VIEW1          0xFD40
> +#define S5P_FIMV_E_MVC_RC_FRAME_RATE_VIEW1     0xFD44
> +#define S5P_FIMV_E_MVC_RC_BIT_RATE_VIEW1       0xFD48
> +#define S5P_FIMV_E_MVC_RC_QBOUND_VIEW1         0xFD4C
> +#define S5P_FIMV_E_MVC_RC_RPARA_VIEW1          0xFD50
> +#define S5P_FIMV_E_MVC_INTER_VIEW_PREDICTION_ON        0xFD80
> +
> +/* Codec numbers  */
> +#define S5P_FIMV_CODEC_NONE            -1
> +
> +
> +#define S5P_FIMV_CODEC_H264_DEC        0
> +#define S5P_FIMV_CODEC_H264_MVC_DEC    1
> +
> +#define S5P_FIMV_CODEC_MPEG4_DEC       3
> +#define S5P_FIMV_CODEC_FIMV1_DEC       4
> +#define S5P_FIMV_CODEC_FIMV2_DEC       5
> +#define S5P_FIMV_CODEC_FIMV3_DEC       6
> +#define S5P_FIMV_CODEC_FIMV4_DEC       7
> +#define S5P_FIMV_CODEC_H263_DEC        8
> +#define S5P_FIMV_CODEC_VC1RCV_DEC      9
> +#define S5P_FIMV_CODEC_VC1_DEC         10
> +/* FIXME: Add 11~12 */
> +#define S5P_FIMV_CODEC_MPEG2_DEC       13
> +#define S5P_FIMV_CODEC_VP8_DEC         14
> +/* FIXME: Add 15~16 */
> +#define S5P_FIMV_CODEC_H264_ENC        20
> +#define S5P_FIMV_CODEC_H264_MVC_ENC    21
> +
> +#define S5P_FIMV_CODEC_MPEG4_ENC       23
> +#define S5P_FIMV_CODEC_H263_ENC        24
> +/***   Definitions for MFCv5 compatibility ***/
> +#define S5P_FIMV_SI_DISPLAY_Y_ADR              S5P_FIMV_D_DISPLAY_LUMA_ADDR
> +#define S5P_FIMV_SI_DISPLAY_C_ADR              S5P_FIMV_D_DISPLAY_CHROMA_ADDR
> +
> +#define S5P_FIMV_CRC_LUMA0                     S5P_FIMV_D_DECODED_LUMA_CRC_TOP
> +#define S5P_FIMV_CRC_CHROMA0                   S5P_FIMV_D_DECODED_CHROMA_CRC_TOP
> +#define S5P_FIMV_CRC_LUMA1                     S5P_FIMV_D_DECODED_LUMA_CRC_BOT
> +#define S5P_FIMV_CRC_CHROMA1                   S5P_FIMV_D_DECODED_CHROMA_CRC_BOT
> +#define S5P_FIMV_CRC_DISP_LUMA0                        S5P_FIMV_D_DISPLAY_LUMA_CRC_TOP
> +#define S5P_FIMV_CRC_DISP_CHROMA0              S5P_FIMV_D_DISPLAY_CHROMA_CRC_TOP
> +
> +#define S5P_FIMV_SI_DECODED_STATUS             S5P_FIMV_D_DECODED_STATUS
> +#define S5P_FIMV_SI_DISPLAY_STATUS             S5P_FIMV_D_DISPLAY_STATUS
> +#define S5P_FIMV_SHARED_SET_FRAME_TAG          S5P_FIMV_D_PICTURE_TAG
> +#define S5P_FIMV_SHARED_GET_FRAME_TAG_TOP      S5P_FIMV_D_RET_PICTURE_TAG_TOP
> +#define S5P_FIMV_CRC_DISP_STATUS               S5P_FIMV_D_DISPLAY_STATUS
> +
> +/* SEI related information */
> +#define S5P_FIMV_FRAME_PACK_SEI_AVAIL          S5P_FIMV_D_FRAME_PACK_SEI_AVAIL
> +#define S5P_FIMV_FRAME_PACK_ARRGMENT_ID                S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID
> +#define S5P_FIMV_FRAME_PACK_SEI_INFO           S5P_FIMV_D_FRAME_PACK_SEI_INFO
> +#define S5P_FIMV_FRAME_PACK_GRID_POS           S5P_FIMV_D_FRAME_PACK_GRID_POS
> +
> +#define S5P_FIMV_SHARED_SET_E_FRAME_TAG                S5P_FIMV_E_PICTURE_TAG
> +#define S5P_FIMV_SHARED_GET_E_FRAME_TAG                S5P_FIMV_E_RET_PICTURE_TAG
> +#define S5P_FIMV_ENCODED_LUMA_ADDR             S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR
> +#define S5P_FIMV_ENCODED_CHROMA_ADDR           S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR
> +#define        S5P_FIMV_FRAME_INSERTION                S5P_FIMV_E_FRAME_INSERTION
> +
> +#define S5P_FIMV_PARAM_CHANGE_FLAG             S5P_FIMV_E_PARAM_CHANGE /* flag */
> +#define S5P_FIMV_NEW_I_PERIOD                  S5P_FIMV_E_GOP_CONFIG
> +#define S5P_FIMV_NEW_RC_FRAME_RATE             S5P_FIMV_E_RC_FRAME_RATE
> +#define S5P_FIMV_NEW_RC_BIT_RATE               S5P_FIMV_E_RC_BIT_RATE
> +/*** End of MFCv5 compatibility definitions ***/
> +
> +/***      old definitions     ***/
> +#define S5P_FIMV_SW_RESET              0x0000
> +#define S5P_FIMV_RISC_HOST_INT         0x0008
> +
> +/* Command from HOST to RISC */
> +#define S5P_FIMV_HOST2RISC_ARG1                0x0034
> +#define S5P_FIMV_HOST2RISC_ARG2                0x0038
> +#define S5P_FIMV_HOST2RISC_ARG3                0x003c
> +#define S5P_FIMV_HOST2RISC_ARG4                0x0040
> +
> +/* Command from RISC to HOST */
> +#define S5P_FIMV_RISC2HOST_CMD_MASK    0x1FFFF
> +#define S5P_FIMV_RISC2HOST_ARG1                0x0048
> +#define S5P_FIMV_RISC2HOST_ARG2                0x004c
> +#define S5P_FIMV_RISC2HOST_ARG3                0x0050
> +#define S5P_FIMV_RISC2HOST_ARG4                0x0054
> +
> +#define S5P_FIMV_SYS_MEM_SZ            0x005c
> +#define S5P_FIMV_FW_STATUS             0x0080
> +
> +/* Memory controller register */
> +#define S5P_FIMV_MC_DRAMBASE_ADR_A     0x0508
> +#define S5P_FIMV_MC_DRAMBASE_ADR_B     0x050c
> +#define S5P_FIMV_MC_STATUS             0x0510
> +
> +/* Common register */
> +#define S5P_FIMV_COMMON_BASE_A         0x0600
> +#define S5P_FIMV_COMMON_BASE_B         0x0700
> +
> +/* Decoder */
> +#define S5P_FIMV_DEC_CHROMA_ADR                (S5P_FIMV_COMMON_BASE_A)
> +#define S5P_FIMV_DEC_LUMA_ADR          (S5P_FIMV_COMMON_BASE_B)
> +
> +/* H.264 decoding */
> +#define S5P_FIMV_H264_VERT_NB_MV_ADR   (S5P_FIMV_COMMON_BASE_A + 0x8c) /* vertical neighbor motion vector */
> +#define S5P_FIMV_H264_NB_IP_ADR                (S5P_FIMV_COMMON_BASE_A + 0x90) /* neighbor pixels for intra pred */
> +#define S5P_FIMV_H264_MV_ADR           (S5P_FIMV_COMMON_BASE_B + 0x80) /* H264 motion vector */
> +
> +/* MPEG4 decoding */
> +#define S5P_FIMV_MPEG4_NB_DCAC_ADR     (S5P_FIMV_COMMON_BASE_A + 0x8c) /* neighbor AC/DC coeff. */
> +#define S5P_FIMV_MPEG4_UP_NB_MV_ADR    (S5P_FIMV_COMMON_BASE_A + 0x90) /* upper neighbor motion vector */
> +#define S5P_FIMV_MPEG4_SA_MV_ADR       (S5P_FIMV_COMMON_BASE_A + 0x94) /* subseq. anchor motion vector */
> +#define S5P_FIMV_MPEG4_OT_LINE_ADR     (S5P_FIMV_COMMON_BASE_A + 0x98) /* overlap transform line */
> +#define S5P_FIMV_MPEG4_SP_ADR          (S5P_FIMV_COMMON_BASE_A + 0xa8) /* syntax parser */
> +
> +/* H.263 decoding */
> +#define S5P_FIMV_H263_NB_DCAC_ADR      (S5P_FIMV_COMMON_BASE_A + 0x8c)
> +#define S5P_FIMV_H263_UP_NB_MV_ADR     (S5P_FIMV_COMMON_BASE_A + 0x90)
> +#define S5P_FIMV_H263_SA_MV_ADR                (S5P_FIMV_COMMON_BASE_A + 0x94)
> +#define S5P_FIMV_H263_OT_LINE_ADR      (S5P_FIMV_COMMON_BASE_A + 0x98)
> +
> +/* VC-1 decoding */
> +#define S5P_FIMV_VC1_NB_DCAC_ADR       (S5P_FIMV_COMMON_BASE_A + 0x8c)
> +#define S5P_FIMV_VC1_UP_NB_MV_ADR      (S5P_FIMV_COMMON_BASE_A + 0x90)
> +#define S5P_FIMV_VC1_SA_MV_ADR         (S5P_FIMV_COMMON_BASE_A + 0x94)
> +#define S5P_FIMV_VC1_OT_LINE_ADR       (S5P_FIMV_COMMON_BASE_A + 0x98)
> +#define S5P_FIMV_VC1_BITPLANE3_ADR     (S5P_FIMV_COMMON_BASE_A + 0x9c) /* bitplane3 */
> +#define S5P_FIMV_VC1_BITPLANE2_ADR     (S5P_FIMV_COMMON_BASE_A + 0xa0) /* bitplane2 */
> +#define S5P_FIMV_VC1_BITPLANE1_ADR     (S5P_FIMV_COMMON_BASE_A + 0xa4) /* bitplane1 */
> +
> +/* Encoder */
> +#define S5P_FIMV_ENC_REF0_LUMA_ADR     (S5P_FIMV_COMMON_BASE_A + 0x1c) /* reconstructed luma */
> +#define S5P_FIMV_ENC_REF1_LUMA_ADR     (S5P_FIMV_COMMON_BASE_A + 0x20)
> +#define S5P_FIMV_ENC_REF0_CHROMA_ADR   (S5P_FIMV_COMMON_BASE_B)        /* reconstructed chroma */
> +#define S5P_FIMV_ENC_REF1_CHROMA_ADR   (S5P_FIMV_COMMON_BASE_B + 0x04)
> +#define S5P_FIMV_ENC_REF2_LUMA_ADR     (S5P_FIMV_COMMON_BASE_B + 0x10)
> +#define S5P_FIMV_ENC_REF2_CHROMA_ADR   (S5P_FIMV_COMMON_BASE_B + 0x08)
> +#define S5P_FIMV_ENC_REF3_LUMA_ADR     (S5P_FIMV_COMMON_BASE_B + 0x14)
> +#define S5P_FIMV_ENC_REF3_CHROMA_ADR   (S5P_FIMV_COMMON_BASE_B + 0x0c)
> +
> +/* H.264 encoding */
> +#define S5P_FIMV_H264_UP_MV_ADR                (S5P_FIMV_COMMON_BASE_A)        /* upper motion vector */
> +#define S5P_FIMV_H264_NBOR_INFO_ADR    (S5P_FIMV_COMMON_BASE_A + 0x04) /* entropy engine's neighbor info. */
> +#define S5P_FIMV_H264_UP_INTRA_MD_ADR  (S5P_FIMV_COMMON_BASE_A + 0x08) /* upper intra MD */
> +#define S5P_FIMV_H264_COZERO_FLAG_ADR  (S5P_FIMV_COMMON_BASE_A + 0x10) /* direct cozero flag */
> +#define S5P_FIMV_H264_UP_INTRA_PRED_ADR        (S5P_FIMV_COMMON_BASE_B + 0x40) /* upper intra PRED */
> +
> +/* H.263 encoding */
> +#define S5P_FIMV_H263_UP_MV_ADR                (S5P_FIMV_COMMON_BASE_A)        /* upper motion vector */
> +#define S5P_FIMV_H263_ACDC_COEF_ADR    (S5P_FIMV_COMMON_BASE_A + 0x04) /* upper Q coeff. */
> +
> +/* MPEG4 encoding */
> +#define S5P_FIMV_MPEG4_UP_MV_ADR       (S5P_FIMV_COMMON_BASE_A)        /* upper motion vector */
> +#define S5P_FIMV_MPEG4_ACDC_COEF_ADR   (S5P_FIMV_COMMON_BASE_A + 0x04) /* upper Q coeff. */
> +#define S5P_FIMV_MPEG4_COZERO_FLAG_ADR (S5P_FIMV_COMMON_BASE_A + 0x10) /* direct cozero flag */
> +
> +#define S5P_FIMV_ENC_REF_B_LUMA_ADR     0x062c /* ref B Luma addr */
> +#define S5P_FIMV_ENC_REF_B_CHROMA_ADR   0x0630 /* ref B Chroma addr */
> +
> +#define S5P_FIMV_ENC_CUR_LUMA_ADR      0x0718 /* current Luma addr */
> +#define S5P_FIMV_ENC_CUR_CHROMA_ADR    0x071C /* current Chroma addr */
> +
> +/* Codec common register */
> +#define S5P_FIMV_ENC_HSIZE_PX          0x0818 /* frame width at encoder */
> +#define S5P_FIMV_ENC_VSIZE_PX          0x081c /* frame height at encoder */
> +#define S5P_FIMV_ENC_PROFILE           0x0830 /* profile register */
> +#define S5P_FIMV_ENC_PIC_STRUCT                0x083c /* picture field/frame flag */
> +#define S5P_FIMV_ENC_LF_CTRL           0x0848 /* loop filter control */
> +#define S5P_FIMV_ENC_ALPHA_OFF         0x084c /* loop filter alpha offset */
> +#define S5P_FIMV_ENC_BETA_OFF          0x0850 /* loop filter beta offset */
> +#define S5P_FIMV_MR_BUSIF_CTRL         0x0854 /* hidden, bus interface ctrl */
> +#define S5P_FIMV_ENC_PXL_CACHE_CTRL    0x0a00 /* pixel cache control */
> +
> +/* Channel & stream interface register */
> +#define S5P_FIMV_SI_RTN_CHID           0x2000 /* Return CH instance ID register */
> +#define S5P_FIMV_SI_CH0_INST_ID                0x2040 /* codec instance ID */
> +#define S5P_FIMV_SI_CH1_INST_ID                0x2080 /* codec instance ID */
> +/* Decoder */
> +#define S5P_FIMV_SI_VRESOL             0x2004 /* vertical resolution of decoder */
> +#define S5P_FIMV_SI_HRESOL             0x2008 /* horizontal resolution of decoder */
> +#define S5P_FIMV_SI_BUF_NUMBER         0x200c /* number of frames in the decoded pic */
> +#define S5P_FIMV_SI_CONSUMED_BYTES     0x2018 /* Consumed number of bytes to decode
> +                                                               a frame */
> +#define S5P_FIMV_SI_FRAME_TYPE         0x2020 /* frame type such as skip/I/P/B */
> +
> +#define S5P_FIMV_SI_CH0_SB_ST_ADR      0x2044 /* start addr of stream buf */
> +#define S5P_FIMV_SI_CH0_SB_FRM_SIZE    0x2048 /* size of stream buf */
> +#define S5P_FIMV_SI_CH0_DESC_ADR       0x204c /* addr of descriptor buf */
> +#define S5P_FIMV_SI_CH0_CPB_SIZE       0x2058 /* max size of coded pic. buf */
> +#define S5P_FIMV_SI_CH0_DESC_SIZE      0x205c /* max size of descriptor buf */
> +
> +#define S5P_FIMV_SI_CH1_SB_ST_ADR      0x2084 /* start addr of stream buf */
> +#define S5P_FIMV_SI_CH1_SB_FRM_SIZE    0x2088 /* size of stream buf */
> +#define S5P_FIMV_SI_CH1_DESC_ADR       0x208c /* addr of descriptor buf */
> +#define S5P_FIMV_SI_CH1_CPB_SIZE       0x2098 /* max size of coded pic. buf */
> +#define S5P_FIMV_SI_CH1_DESC_SIZE      0x209c /* max size of descriptor buf */
> +
> +#define S5P_FIMV_SI_FIMV1_HRESOL       0x2054 /* horizontal resolution */
> +#define S5P_FIMV_SI_FIMV1_VRESOL       0x2050 /* vertical resolution */
> +
> +/* Decode frame address */
> +#define S5P_FIMV_DECODE_Y_ADR                  0x2024
> +#define S5P_FIMV_DECODE_C_ADR                  0x2028
> +
> +/* Decoded frame type */
> +#define S5P_FIMV_DECODE_FRAME_TYPE             0x2020
> +
> +/* Sizes of buffers required for decoding */
> +#define S5P_FIMV_DEC_NB_IP_SIZE                        (32 * 1024)
> +#define S5P_FIMV_DEC_VERT_NB_MV_SIZE           (16 * 1024)
> +#define S5P_FIMV_DEC_NB_DCAC_SIZE              (16 * 1024)
> +#define S5P_FIMV_DEC_UPNB_MV_SIZE              (68 * 1024)
> +#define S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE                (136 * 1024)
> +#define S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE     (32 * 1024)
> +#define S5P_FIMV_DEC_VC1_BITPLANE_SIZE         (2 * 1024)
> +#define S5P_FIMV_DEC_STX_PARSER_SIZE           (68 * 1024)
> +
> +#define S5P_FIMV_NV12M_HALIGN                  16
> +#define S5P_FIMV_NV12MT_HALIGN                 16
> +#define S5P_FIMV_NV12MT_VALIGN                 16
> +
> +/* Sizes of buffers required for encoding */
> +#define S5P_FIMV_ENC_UPMV_SIZE                 (0x10000)
> +#define S5P_FIMV_ENC_COLFLG_SIZE               (0x10000)
> +#define S5P_FIMV_ENC_INTRAMD_SIZE              (0x10000)
> +#define S5P_FIMV_ENC_INTRAPRED_SIZE            (0x4000)
> +#define S5P_FIMV_ENC_NBORINFO_SIZE             (0x10000)
> +#define S5P_FIMV_ENC_ACDCCOEF_SIZE             (0x10000)
> +
> +/* Encoder */
> +#define S5P_FIMV_ENC_SI_STRM_SIZE      0x2004 /* stream size */
> +#define S5P_FIMV_ENC_SI_PIC_CNT                0x2008 /* picture count */
> +#define S5P_FIMV_ENC_SI_WRITE_PTR      0x200c /* write pointer */
> +#define S5P_FIMV_ENC_SI_SLICE_TYPE     0x2010 /* slice type(I/P/B/IDR) */
> +
> +#define S5P_FIMV_ENCODED_Y_ADDR         0x2014 /* the addr of the encoded luma pic */
> +#define S5P_FIMV_ENCODED_C_ADDR         0x2018 /* the addr of the encoded chroma pic */
> +
> +#define S5P_FIMV_ENC_SI_CH0_SB_ADR     0x2044 /* addr of stream buf */
> +#define S5P_FIMV_ENC_SI_CH0_SB_SIZE    0x204c /* size of stream buf */
> +#define S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR  0x2050 /* current Luma addr */
> +#define S5P_FIMV_ENC_SI_CH0_CUR_C_ADR  0x2054 /* current Chroma addr */
> +#define S5P_FIMV_ENC_SI_CH0_FRAME_INS  0x2058 /* frame insertion */
> +
> +#define S5P_FIMV_ENC_SI_CH1_SB_ADR     0x2084 /* addr of stream buf */
> +#define S5P_FIMV_ENC_SI_CH1_SB_SIZE    0x208c /* size of stream buf */
> +#define S5P_FIMV_ENC_SI_CH1_CUR_Y_ADR  0x2090 /* current Luma addr */
> +#define S5P_FIMV_ENC_SI_CH1_CUR_C_ADR  0x2094 /* current Chroma addr */
> +#define S5P_FIMV_ENC_SI_CH1_FRAME_INS  0x2098 /* frame insertion */
> +
> +#define S5P_FIMV_ENC_PIC_TYPE_CTRL     0xc504 /* pic type level control */
> +#define S5P_FIMV_ENC_B_RECON_WRITE_ON  0xc508 /* B frame recon write ctrl */
> +#define S5P_FIMV_ENC_MSLICE_CTRL       0xc50c /* multi slice control */
> +#define S5P_FIMV_ENC_MSLICE_MB         0xc510 /* MB number in the one slice */
> +#define S5P_FIMV_ENC_MSLICE_BIT                0xc514 /* bit count for one slice */
> +#define S5P_FIMV_ENC_CIR_CTRL          0xc518 /* number of intra refresh MB */
> +#define S5P_FIMV_ENC_MAP_FOR_CUR       0xc51c /* linear or 64x32 tiled mode */
> +#define S5P_FIMV_ENC_PADDING_CTRL      0xc520 /* padding control */
> +
> +#define S5P_FIMV_ENC_RC_CONFIG         0xc5a0 /* RC config */
> +#define S5P_FIMV_ENC_RC_BIT_RATE       0xc5a8 /* bit rate */
> +#define S5P_FIMV_ENC_RC_QBOUND         0xc5ac /* max/min QP */
> +#define S5P_FIMV_ENC_RC_RPARA          0xc5b0 /* rate control reaction coeff */
> +#define S5P_FIMV_ENC_RC_MB_CTRL                0xc5b4 /* MB adaptive scaling */
> +
> +/* Encoder for H264 only */
> +#define S5P_FIMV_ENC_H264_ENTRP_MODE   0xd004 /* CAVLC or CABAC */
> +#define S5P_FIMV_ENC_H264_ALPHA_OFF    0xd008 /* loop filter alpha offset */
> +#define S5P_FIMV_ENC_H264_BETA_OFF     0xd00c /* loop filter beta offset */
> +#define S5P_FIMV_ENC_H264_NUM_OF_REF   0xd010 /* number of reference for P/B */
> +#define S5P_FIMV_ENC_H264_TRANS_FLAG   0xd034 /* 8x8 transform flag in PPS & high profile */
> +
> +#define S5P_FIMV_ENC_RC_FRAME_RATE     0xd0d0 /* frame rate */
> +
> +/* Encoder for MPEG4 only */
> +#define S5P_FIMV_ENC_MPEG4_QUART_PXL   0xe008 /* qpel interpolation ctrl */
> +
> +/* Additional */
> +#define S5P_FIMV_SI_CH0_DPB_CONF_CTRL   0x2068 /* DPB Config Control Register */
> +#define S5P_FIMV_DPB_COUNT_MASK                0xffff
> +
> +#define S5P_FIMV_SI_CH0_RELEASE_BUF     0x2060 /* DPB release buffer register */
> +#define S5P_FIMV_SI_CH0_HOST_WR_ADR    0x2064 /* address of shared memory */
> +
> +/* Channel Control Register */
> +#define S5P_FIMV_CH_FRAME_START_REALLOC        5
> +
> +#define S5P_FIMV_CH_MASK               7
> +#define S5P_FIMV_CH_SHIFT              16
> +
> +/* Host to RISC command */
> +#define S5P_FIMV_R2H_CMD_RSV_RET               3
> +#define S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET      7
> +#define S5P_FIMV_R2H_CMD_FLUSH_RET             12
> +#define S5P_FIMV_R2H_CMD_EDFU_INIT_RET         16
> +
> +/* Shared memory registers' offsets */
> +
> +/* An offset of the start position in the stream when
> + * the start position is not aligned */
> +#define S5P_FIMV_SHARED_GET_FRAME_TAG_BOT      0x000C
> +#define S5P_FIMV_SHARED_START_BYTE_NUM         0x0018
> +#define S5P_FIMV_SHARED_RC_VOP_TIMING          0x0030
> +#define S5P_FIMV_SHARED_LUMA_DPB_SIZE          0x0064
> +#define S5P_FIMV_SHARED_CHROMA_DPB_SIZE                0x0068
> +#define S5P_FIMV_SHARED_MV_SIZE                        0x006C
> +#define S5P_FIMV_SHARED_PIC_TIME_TOP           0x0010
> +#define S5P_FIMV_SHARED_PIC_TIME_BOTTOM                0x0014
> +#define S5P_FIMV_SHARED_EXT_ENC_CONTROL                0x0028
> +#define S5P_FIMV_SHARED_P_B_FRAME_QP           0x0070
> +#define S5P_FIMV_SHARED_ASPECT_RATIO_IDC       0x0074
> +#define S5P_FIMV_SHARED_EXTENDED_SAR           0x0078
> +#define S5P_FIMV_SHARED_H264_I_PERIOD          0x009C
> +#define S5P_FIMV_SHARED_RC_CONTROL_CONFIG      0x00A0
> +
> +/* End of old definitions */
> +
> +#endif /* _REGS_FIMV_V6_H */
> diff --git a/drivers/media/video/s5p-mfc/regs-mfc.h b/drivers/media/video/s5p-mfc/regs-mfc.h
> index a19bece..d2dfb06 100644
> --- a/drivers/media/video/s5p-mfc/regs-mfc.h
> +++ b/drivers/media/video/s5p-mfc/regs-mfc.h
> @@ -144,6 +144,7 @@
>  #define S5P_FIMV_ENC_PROFILE_H264_MAIN                 0
>  #define S5P_FIMV_ENC_PROFILE_H264_HIGH                 1
>  #define S5P_FIMV_ENC_PROFILE_H264_BASELINE             2
> +#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE 3
>  #define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE              0
>  #define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE     1
>  #define S5P_FIMV_ENC_PIC_STRUCT                0x083c /* picture field/frame flag */
> @@ -213,6 +214,7 @@
>  #define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK            (3<<4)
>  #define S5P_FIMV_DEC_STATUS_RESOLUTION_INC             (1<<4)
>  #define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC             (2<<4)
> +#define S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT           4
>
>  /* Decode frame address */
>  #define S5P_FIMV_DECODE_Y_ADR                  0x2024
> @@ -377,6 +379,16 @@
>  #define S5P_FIMV_R2H_CMD_EDFU_INIT_RET         16
>  #define S5P_FIMV_R2H_CMD_ERR_RET               32
>
> +/* Dummy definition for MFCv6 compatibilty */
> +#define S5P_FIMV_CODEC_H264_MVC_DEC            -1
> +#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET                -1
> +#define S5P_FIMV_MFC_RESET                     -1
> +#define S5P_FIMV_RISC_ON                       -1
> +#define S5P_FIMV_RISC_BASE_ADDRESS             -1
> +#define S5P_FIMV_CODEC_VP8_DEC                 -1
> +#define S5P_FIMV_REG_CLEAR_BEGIN               0
> +#define S5P_FIMV_REG_CLEAR_COUNT               0
> +
>  /* Error handling defines */
>  #define S5P_FIMV_ERR_WARNINGS_START            145
>  #define S5P_FIMV_ERR_DEC_MASK                  0xFFFF
> @@ -414,5 +426,22 @@
>  #define S5P_FIMV_SHARED_EXTENDED_SAR           0x0078
>  #define S5P_FIMV_SHARED_H264_I_PERIOD          0x009C
>  #define S5P_FIMV_SHARED_RC_CONTROL_CONFIG      0x00A0
> +#define S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT  2
> +
> +#define S5P_FIMV_SHARED_FRAME_PACK_SEI_AVAIL    0x16C
> +#define S5P_FIMV_SHARED_FRAME_PACK_ARRGMENT_ID  0x170
> +#define S5P_FIMV_SHARED_FRAME_PACK_SEI_INFO     0x174
> +#define S5P_FIMV_SHARED_FRAME_PACK_GRID_POS     0x178
> +
> +/* SEI related information */
> +#define S5P_FIMV_FRAME_PACK_SEI_AVAIL           S5P_FIMV_SHARED_FRAME_PACK_SEI_AVAIL
> +#define S5P_FIMV_FRAME_PACK_ARRGMENT_ID         S5P_FIMV_SHARED_FRAME_PACK_ARRGMENT_ID
> +#define S5P_FIMV_FRAME_PACK_SEI_INFO            S5P_FIMV_SHARED_FRAME_PACK_SEI_INFO
> +#define S5P_FIMV_FRAME_PACK_GRID_POS            S5P_FIMV_SHARED_FRAME_PACK_GRID_POS
> +
> +#define S5P_FIMV_SHARED_SET_E_FRAME_TAG                S5P_FIMV_SHARED_SET_FRAME_TAG
> +#define S5P_FIMV_SHARED_GET_E_FRAME_TAG                S5P_FIMV_SHARED_GET_FRAME_TAG_TOP
> +#define S5P_FIMV_ENCODED_LUMA_ADDR             S5P_FIMV_ENCODED_Y_ADDR
> +#define S5P_FIMV_ENCODED_CHROMA_ADDR           S5P_FIMV_ENCODED_C_ADDR
>
>  #endif /* _REGS_FIMV_H */
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p-mfc/s5p_mfc.c
> index 9bb68e7..bec94bc 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc.c
> @@ -21,15 +21,13 @@
>  #include <linux/videodev2.h>
>  #include <linux/workqueue.h>
>  #include <media/videobuf2-core.h>
> -#include "regs-mfc.h"
> +#include "s5p_mfc_common.h"
>  #include "s5p_mfc_ctrl.h"
>  #include "s5p_mfc_debug.h"
>  #include "s5p_mfc_dec.h"
>  #include "s5p_mfc_enc.h"
>  #include "s5p_mfc_intr.h"
> -#include "s5p_mfc_opr.h"
>  #include "s5p_mfc_pm.h"
> -#include "s5p_mfc_shm.h"
>
>  #define S5P_MFC_NAME           "s5p-mfc"
>  #define S5P_MFC_DEC_NAME       "s5p-mfc-dec"
> @@ -155,13 +153,6 @@ static enum s5p_mfc_node_type s5p_mfc_get_node_type(struct file *file)
>         return MFCNODE_INVALID;
>  }
>
> -static void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
> -{
> -       mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
> -       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> -       mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
> -}
> -
>  static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
>  {
>         struct s5p_mfc_buf *dst_buf;
> @@ -179,8 +170,8 @@ static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
>                 ctx->dst_queue_cnt--;
>                 dst_buf->b->v4l2_buf.sequence = (ctx->sequence++);
>
> -               if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
> -                       s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
> +               if (s5p_mfc_read_info(ctx, PIC_TIME_TOP) ==
> +                       s5p_mfc_read_info(ctx, PIC_TIME_BOT))
>                         dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
>                 else
>                         dst_buf->b->v4l2_buf.field = V4L2_FIELD_INTERLACED;
> @@ -195,7 +186,7 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
>         struct s5p_mfc_dev *dev = ctx->dev;
>         struct s5p_mfc_buf  *dst_buf, *src_buf;
>         size_t dec_y_addr = s5p_mfc_get_dec_y_adr();
> -       unsigned int frame_type = s5p_mfc_get_frame_type();
> +       unsigned int frame_type = s5p_mfc_get_dec_frame_type();
>
>         /* Copy timestamp / timecode from decoded src to dst and set
>            appropraite flags */
> @@ -232,7 +223,7 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
>         struct s5p_mfc_dev *dev = ctx->dev;
>         struct s5p_mfc_buf  *dst_buf;
>         size_t dspl_y_addr = s5p_mfc_get_dspl_y_adr();
> -       unsigned int frame_type = s5p_mfc_get_frame_type();
> +       unsigned int frame_type = s5p_mfc_get_dec_frame_type();
>         unsigned int index;
>
>         /* If frame is same as previous then skip and do not dequeue */
> @@ -251,8 +242,8 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
>                         list_del(&dst_buf->list);
>                         ctx->dst_queue_cnt--;
>                         dst_buf->b->v4l2_buf.sequence = ctx->sequence;
> -                       if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
> -                               s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
> +                       if (s5p_mfc_read_info(ctx, PIC_TIME_TOP) ==
> +                               s5p_mfc_read_info(ctx, PIC_TIME_BOT))
>                                 dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
>                         else
>                                 dst_buf->b->v4l2_buf.field =
> @@ -285,12 +276,13 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
>
>         dst_frame_status = s5p_mfc_get_dspl_status()
>                                 & S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
> -       res_change = s5p_mfc_get_dspl_status()
> -                               & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK;
> +       res_change = (s5p_mfc_get_dspl_status()
> +                               & S5P_FIMV_DEC_STATUS_RESOLUTION_MASK)
> +                               >> S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT;
>         mfc_debug(2, "Frame Status: %x\n", dst_frame_status);
>         if (ctx->state == MFCINST_RES_CHANGE_INIT)
>                 ctx->state = MFCINST_RES_CHANGE_FLUSH;
> -       if (res_change) {
> +       if (res_change && res_change != 3) {
>                 ctx->state = MFCINST_RES_CHANGE_INIT;
>                 s5p_mfc_clear_int_flags(dev);
>                 wake_up_ctx(ctx, reason, err);
> @@ -333,7 +325,8 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
>                                                                 list);
>                 ctx->consumed_stream += s5p_mfc_get_consumed_stream();
>                 if (ctx->codec_mode != S5P_FIMV_CODEC_H264_DEC &&
> -                       s5p_mfc_get_frame_type() == S5P_FIMV_DECODE_FRAME_P_FRAME
> +                       s5p_mfc_get_dec_frame_type() ==
> +                                       S5P_FIMV_DECODE_FRAME_P_FRAME
>                                         && ctx->consumed_stream + STUFF_BYTE <
>                                         src_buf->b->v4l2_planes[0].bytesused) {
>                         /* Run MFC again on the same buffer */
> @@ -427,7 +420,6 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
>                                  unsigned int reason, unsigned int err)
>  {
>         struct s5p_mfc_dev *dev;
> -       unsigned int guard_width, guard_height;
>
>         if (ctx == NULL)
>                 return;
> @@ -439,45 +431,28 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
>                 ctx->img_width = s5p_mfc_get_img_width();
>                 ctx->img_height = s5p_mfc_get_img_height();
>
> -               ctx->buf_width = ALIGN(ctx->img_width,
> -                                               S5P_FIMV_NV12MT_HALIGN);
> -               ctx->buf_height = ALIGN(ctx->img_height,
> -                                               S5P_FIMV_NV12MT_VALIGN);
> -               mfc_debug(2, "SEQ Done: Movie dimensions %dx%d, "
> -                       "buffer dimensions: %dx%d\n", ctx->img_width,
> -                               ctx->img_height, ctx->buf_width,
> -                                               ctx->buf_height);
> -               if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
> -                       ctx->luma_size = ALIGN(ctx->buf_width *
> -                               ctx->buf_height, S5P_FIMV_DEC_BUF_ALIGN);
> -                       ctx->chroma_size = ALIGN(ctx->buf_width *
> -                                        ALIGN((ctx->img_height >> 1),
> -                                              S5P_FIMV_NV12MT_VALIGN),
> -                                              S5P_FIMV_DEC_BUF_ALIGN);
> -                       ctx->mv_size = ALIGN(ctx->buf_width *
> -                                       ALIGN((ctx->buf_height >> 2),
> -                                       S5P_FIMV_NV12MT_VALIGN),
> -                                       S5P_FIMV_DEC_BUF_ALIGN);
> -               } else {
> -                       guard_width = ALIGN(ctx->img_width + 24,
> -                                       S5P_FIMV_NV12MT_HALIGN);
> -                       guard_height = ALIGN(ctx->img_height + 16,
> -                                               S5P_FIMV_NV12MT_VALIGN);
> -                       ctx->luma_size = ALIGN(guard_width *
> -                               guard_height, S5P_FIMV_DEC_BUF_ALIGN);
> -                       guard_width = ALIGN(ctx->img_width + 16,
> -                                               S5P_FIMV_NV12MT_HALIGN);
> -                       guard_height = ALIGN((ctx->img_height >> 1) + 4,
> -                                               S5P_FIMV_NV12MT_VALIGN);
> -                       ctx->chroma_size = ALIGN(guard_width *
> -                               guard_height, S5P_FIMV_DEC_BUF_ALIGN);
> -                       ctx->mv_size = 0;
> -               }
> +               s5p_mfc_dec_calc_dpb_size(ctx);
> +
>                 ctx->dpb_count = s5p_mfc_get_dpb_count();
>                 if (ctx->img_width == 0 || ctx->img_height == 0)
>                         ctx->state = MFCINST_ERROR;
>                 else
>                         ctx->state = MFCINST_HEAD_PARSED;
> +
> +               if ((ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
> +                       ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC) &&
> +                               !list_empty(&ctx->src_queue)) {
> +                       struct s5p_mfc_buf *src_buf;
> +                       src_buf = list_entry(ctx->src_queue.next,
> +                                       struct s5p_mfc_buf, list);
> +                       mfc_debug(2, "Check consumed size of header. ");
> +                       mfc_debug(2, "source : %d, consumed : %d\n",
> +                                       s5p_mfc_get_consumed_stream(),
> +                                       src_buf->b->v4l2_planes[0].bytesused);
> +                       if (s5p_mfc_get_consumed_stream() <
> +                                       src_buf->b->v4l2_planes[0].bytesused)
> +                               ctx->remained = 1;
> +               }
>         }
>         s5p_mfc_clear_int_flags(dev);
>         clear_work_bit(ctx);
> @@ -508,7 +483,7 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
>         spin_unlock(&dev->condlock);
>         if (err == 0) {
>                 ctx->state = MFCINST_RUNNING;
> -               if (!ctx->dpb_flush_flag) {
> +               if (!ctx->dpb_flush_flag && !ctx->remained) {
>                         spin_lock_irqsave(&dev->irqlock, flags);
>                         if (!list_empty(&ctx->src_queue)) {
>                                 src_buf = list_entry(ctx->src_queue.next,
> @@ -567,6 +542,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
>                 break;
>
>         case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
> +       case S5P_FIMV_R2H_CMD_FIELD_DONE_RET:
>         case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
>                 if (ctx->c_ops->post_frame_start) {
>                         if (ctx->c_ops->post_frame_start(ctx))
> @@ -679,6 +655,7 @@ static int s5p_mfc_open(struct file *file)
>         if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) {
>                 ctx->type = MFCINST_DECODER;
>                 ctx->c_ops = get_dec_codec_ops();
> +               s5p_mfc_dec_init(ctx);
>                 /* Setup ctrl handler */
>                 ret = s5p_mfc_dec_ctrls_setup(ctx);
>                 if (ret) {
> @@ -691,6 +668,7 @@ static int s5p_mfc_open(struct file *file)
>                 /* only for encoder */
>                 INIT_LIST_HEAD(&ctx->ref_queue);
>                 ctx->ref_queue_cnt = 0;
> +               s5p_mfc_enc_init(ctx);
>                 /* Setup ctrl handler */
>                 ret = s5p_mfc_enc_ctrls_setup(ctx);
>                 if (ret) {
> @@ -842,6 +820,7 @@ static int s5p_mfc_release(struct file *file)
>                 mfc_debug(2, "Last instance - release firmware\n");
>                 /* reset <-> F/W release */
>                 s5p_mfc_reset(dev);
> +               s5p_mfc_deinit_hw(dev);
>                 s5p_mfc_release_firmware(dev);
>                 del_timer_sync(&dev->watchdog_timer);
>                 if (s5p_mfc_power_off() < 0)
> @@ -1086,6 +1065,9 @@ static int s5p_mfc_probe(struct platform_device *pdev)
>         dev->watchdog_timer.data = (unsigned long)dev;
>         dev->watchdog_timer.function = s5p_mfc_watchdog;
>
> +       dev->variant = (struct s5p_mfc_variant *)
> +               platform_get_device_id(pdev)->driver_data;
> +
>         pr_debug("%s--\n", __func__);
>         return 0;
>
> @@ -1205,9 +1187,74 @@ static const struct dev_pm_ops s5p_mfc_pm_ops = {
>                            NULL)
>  };
>
> +struct s5p_mfc_buf_size_v5 mfc_buf_size_v5 = {
> +       .h264_ctx       = 0x96000,
> +       .non_h264_ctx   = 0x2800,
> +       .dsc            = 0x20000,
> +       .shm            = 0x1000,
> +};
> +
> +struct s5p_mfc_buf_size buf_size_v5 = {
> +       .fw     = 0x60000,
> +       .cpb    = 0x400000,     /*   4MB */
> +       .priv   = &mfc_buf_size_v5,
> +};
> +
> +struct s5p_mfc_buf_align mfc_buf_align_v5 = {
> +       .base = 17,
> +};
> +
> +static struct s5p_mfc_variant mfc_drvdata_v5 = {
> +       .version        = 0x51,
> +       .port_num       = 2,
> +       .buf_size       = &buf_size_v5,
> +       .buf_align      = &mfc_buf_align_v5,
> +};
> +
> +struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = {
> +       .dev_ctx        = 0x7000,       /*  28KB */
> +       .h264_dec_ctx   = 0x200000,     /* 1.6MB */
> +       .other_dec_ctx  = 0x5000,       /*  20KB */
> +       .h264_enc_ctx   = 0x19000,      /* 100KB */
> +       .other_enc_ctx  = 0x3000,       /*  12KB */
> +};
> +
> +struct s5p_mfc_buf_size buf_size_v6 = {
> +       .fw     = 0x100000,     /*   1MB */
> +       .cpb    = 0x300000,     /*   3MB */
> +       .priv   = &mfc_buf_size_v6,
> +};
> +
> +struct s5p_mfc_buf_align mfc_buf_align_v6 = {
> +       .base = 0,
> +};
> +
> +static struct s5p_mfc_variant mfc_drvdata_v6 = {
> +       .version        = 0x61,
> +       .port_num       = 1,
> +       .buf_size       = &buf_size_v6,
> +       .buf_align      = &mfc_buf_align_v6,
> +};
> +
> +static struct platform_device_id mfc_driver_ids[] = {
> +       {
> +               .name = "s5p-mfc",
> +               .driver_data = (unsigned long)&mfc_drvdata_v5,
> +       }, {
> +               .name = "s5p-mfc-v5",
> +               .driver_data = (unsigned long)&mfc_drvdata_v5,
> +       }, {
> +               .name = "s5p-mfc-v6",
> +               .driver_data = (unsigned long)&mfc_drvdata_v6,
> +       },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(platform, mfc_driver_ids);
> +
>  static struct platform_driver s5p_mfc_driver = {
> -       .probe  = s5p_mfc_probe,
> -       .remove = __devexit_p(s5p_mfc_remove),
> +       .probe          = s5p_mfc_probe,
> +       .remove         = __devexit_p(s5p_mfc_remove),
> +       .id_table       = mfc_driver_ids,
>         .driver = {
>                 .name   = S5P_MFC_NAME,
>                 .owner  = THIS_MODULE,
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
> index f0665ed..e3c64db 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
> @@ -16,8 +16,8 @@
>  #include "s5p_mfc_debug.h"
>
>  /* This function is used to send a command to the MFC */
> -static int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
> -                                               struct s5p_mfc_cmd_args *args)
> +int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
> +                               struct s5p_mfc_cmd_args *args)
>  {
>         int cur_cmd;
>         unsigned long timeout;
> @@ -81,7 +81,7 @@ int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
>         memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
>         h2r_args.arg[0] = ctx->codec_mode;
>         h2r_args.arg[1] = 0; /* no crc & no pixelcache */
> -       h2r_args.arg[2] = ctx->ctx_ofs;
> +       h2r_args.arg[2] = ctx->ctx.ofs;
>         h2r_args.arg[3] = ctx->ctx_size;
>         ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
>                                                                 &h2r_args);
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h
> index 5ceebfe..5c9e662 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h
> @@ -21,6 +21,9 @@ struct s5p_mfc_cmd_args {
>         unsigned int    arg[MAX_H2R_ARG];
>  };
>
> +int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
> +       struct s5p_mfc_cmd_args *args);
> +
>  int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev);
>  int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev);
>  int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev);
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c
> new file mode 100644
> index 0000000..6a631e0
> --- /dev/null
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c
> @@ -0,0 +1,96 @@
> +/*
> + * linux/drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c
> + *
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + *             http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include "s5p_mfc_common.h"
> +
> +#include "s5p_mfc_cmd.h"
> +#include "s5p_mfc_debug.h"
> +#include "s5p_mfc_intr.h"
> +
> +int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
> +                               struct s5p_mfc_cmd_args *args)
> +{
> +       mfc_debug(2, "Issue the command: %d\n", cmd);
> +
> +       /* Reset RISC2HOST command */
> +       mfc_write(dev, 0x0, S5P_FIMV_RISC2HOST_CMD);
> +
> +       /* Issue the command */
> +       mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
> +       mfc_write(dev, 0x1, S5P_FIMV_HOST2RISC_INT);
> +
> +       return 0;
> +}
> +
> +int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev)
> +{
> +       struct s5p_mfc_cmd_args h2r_args;
> +       struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
> +
> +       s5p_mfc_alloc_dev_context_buffer(dev);
> +       mfc_write(dev, dev->ctx_buf.dma, S5P_FIMV_CONTEXT_MEM_ADDR);
> +       mfc_write(dev, buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE);
> +       return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args);
> +}
> +
> +int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev)
> +{
> +       struct s5p_mfc_cmd_args h2r_args;
> +
> +       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> +       return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
> +}
> +
> +int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev)
> +{
> +       struct s5p_mfc_cmd_args h2r_args;
> +
> +       memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
> +       return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_WAKEUP, &h2r_args);
> +}
> +
> +/* Open a new instance and get its number */
> +int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       struct s5p_mfc_cmd_args h2r_args;
> +
> +       mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode);
> +       dev->curr_ctx = ctx->num;
> +       mfc_write(dev, ctx->codec_mode, S5P_FIMV_CODEC_TYPE);
> +       mfc_write(dev, ctx->ctx.dma, S5P_FIMV_CONTEXT_MEM_ADDR);
> +       mfc_write(dev, ctx->ctx_size, S5P_FIMV_CONTEXT_MEM_SIZE);
> +       mfc_write(dev, 0, S5P_FIMV_D_CRC_CTRL); /* no crc */
> +
> +       return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
> +                                       &h2r_args);
> +}
> +
> +/* Close instance */
> +int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       struct s5p_mfc_cmd_args h2r_args;
> +       int ret = 0;
> +
> +       dev->curr_ctx = ctx->num;
> +       if (ctx->state != MFCINST_FREE) {
> +               mfc_write(dev, ctx->inst_no, S5P_FIMV_INSTANCE_ID);
> +               ret = s5p_mfc_cmd_host2risc(dev,
> +                                       S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
> +                                       &h2r_args);
> +       } else {
> +               ret = -EINVAL;
> +       }
> +
> +       return ret;
> +}
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_common.h b/drivers/media/video/s5p-mfc/s5p_mfc_common.h
> index bd5706a..8c646f4 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_common.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_common.h
> @@ -16,7 +16,6 @@
>  #ifndef S5P_MFC_COMMON_H_
>  #define S5P_MFC_COMMON_H_
>
> -#include "regs-mfc.h"
>  #include <linux/platform_device.h>
>  #include <linux/videodev2.h>
>  #include <media/v4l2-ctrls.h>
> @@ -34,10 +33,6 @@
>  #define MFC_OFFSET_SHIFT       11
>
>  #define FIRMWARE_ALIGN         0x20000         /* 128KB */
> -#define MFC_H264_CTX_BUF_SIZE  0x96000         /* 600KB per H264 instance */
> -#define MFC_CTX_BUF_SIZE       0x2800          /* 10KB per instance */
> -#define DESC_BUF_SIZE          0x20000         /* 128KB for DESC buffer */
> -#define SHARED_BUF_SIZE                0x2000          /* 8KB for shared buffer */
>
>  #define DEF_CPB_SIZE           0x40000         /* 512KB */
>
> @@ -174,6 +169,54 @@ struct s5p_mfc_pm {
>         struct device   *device;
>  };
>
> +struct s5p_mfc_buf_size_v5 {
> +       unsigned int h264_ctx;
> +       unsigned int non_h264_ctx;
> +       unsigned int dsc;
> +       unsigned int shm;
> +};
> +
> +struct s5p_mfc_buf_size_v6 {
> +       unsigned int dev_ctx;
> +       unsigned int h264_dec_ctx;
> +       unsigned int other_dec_ctx;
> +       unsigned int h264_enc_ctx;
> +       unsigned int other_enc_ctx;
> +};
> +
> +struct s5p_mfc_buf_size {
> +       unsigned int fw;
> +       unsigned int cpb;
> +       void *priv;
> +};
> +
> +struct s5p_mfc_buf_align {
> +       unsigned int base;
> +};
> +
> +struct s5p_mfc_variant {
> +       unsigned int version;
> +       unsigned int port_num;
> +       struct s5p_mfc_buf_size *buf_size;
> +       struct s5p_mfc_buf_align *buf_align;
> +};
> +
> +/**
> + * struct s5p_mfc_priv_buf - represents internal used buffer
> + * @alloc:             allocation-specific context for each buffer
> + *                     (videobuf2 allocator)
> + * @ofs:               offset of each buffer, will be used for MFC
> + * @virt:              kernel virtual address, only valid when the
> + *                     buffer accessed by driver
> + * @dma:               DMA address, only valid when kernel DMA API used
> + */
> +struct s5p_mfc_priv_buf {
> +       void            *alloc;
> +       unsigned long   ofs;
> +       void            *virt;
> +       dma_addr_t      dma;
> +};
> +
>  /**
>   * struct s5p_mfc_dev - The struct containing driver internal parameters.
>   *
> @@ -209,6 +252,7 @@ struct s5p_mfc_pm {
>   * @watchdog_work:     worker for the watchdog
>   * @alloc_ctx:         videobuf2 allocator contexts for two memory banks
>   * @enter_suspend:     flag set when entering suspend
> + * @ctx_buf:           common context memory (MFCv6)
>   *
>   */
>  struct s5p_mfc_dev {
> @@ -223,6 +267,7 @@ struct s5p_mfc_dev {
>         struct v4l2_ctrl_handler dec_ctrl_handler;
>         struct v4l2_ctrl_handler enc_ctrl_handler;
>         struct s5p_mfc_pm       pm;
> +       struct s5p_mfc_variant  *variant;
>         int num_inst;
>         spinlock_t irqlock;     /* lock when operating on videobuf2 queues */
>         spinlock_t condlock;    /* lock when changing/checking if a context is
> @@ -245,6 +290,8 @@ struct s5p_mfc_dev {
>         struct work_struct watchdog_work;
>         void *alloc_ctx[2];
>         unsigned long enter_suspend;
> +
> +       struct s5p_mfc_priv_buf ctx_buf;
>  };
>
>  /**
> @@ -278,6 +325,23 @@ struct s5p_mfc_h264_enc_params {
>         enum v4l2_mpeg_video_h264_level level_v4l2;
>         int level;
>         u16 cpb_size;
> +       int interlace;
> +       u8 hier_qp;
> +       u8 hier_qp_type;
> +       u8 hier_qp_layer;
> +       u8 hier_qp_layer_qp[7];
> +       u8 sei_frame_packing;
> +       u8 sei_fp_curr_frame_0;
> +       u8 sei_fp_arrangement_type;
> +
> +       u8 fmo;
> +       u8 fmo_map_type;
> +       u8 fmo_slice_grp;
> +       u8 fmo_chg_dir;
> +       u32 fmo_chg_rate;
> +       u32 fmo_run_len[4];
> +       u8 aso;
> +       u32 aso_slice_order[8];
>  };
>
>  /**
> @@ -288,8 +352,6 @@ struct s5p_mfc_mpeg4_enc_params {
>         enum v4l2_mpeg_video_mpeg4_profile profile;
>         int quarter_pixel;
>         /* Common for MPEG4, H263 */
> -       u16 vop_time_res;
> -       u16 vop_frm_delta;
>         u8 rc_frame_qp;
>         u8 rc_min_qp;
>         u8 rc_max_qp;
> @@ -316,9 +378,11 @@ struct s5p_mfc_enc_params {
>         u8 pad_cb;
>         u8 pad_cr;
>         int rc_frame;
> +       int rc_mb;
>         u32 rc_bitrate;
>         u16 rc_reaction_coeff;
>         u16 vbv_size;
> +       u32 vbv_delay;
>
>         enum v4l2_mpeg_video_header_mode seq_hdr_mode;
>         enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode;
> @@ -327,7 +391,6 @@ struct s5p_mfc_enc_params {
>         u8 num_b_frame;
>         u32 rc_framerate_num;
>         u32 rc_framerate_denom;
> -       int interlace;
>
>         union {
>                 struct s5p_mfc_h264_enc_params h264;
> @@ -470,6 +533,7 @@ struct s5p_mfc_ctx {
>         unsigned long consumed_stream;
>
>         unsigned int dpb_flush_flag;
> +       unsigned int remained;
>
>         /* Buffers */
>         void *bank1_buf;
> @@ -499,37 +563,42 @@ struct s5p_mfc_ctx {
>         int display_delay;
>         int display_delay_enable;
>         int after_packed_pb;
> +       int sei_fp_parse;
>
>         int dpb_count;
>         int total_dpb_count;
>
>         /* Buffers */
> -       void *ctx_buf;
> -       size_t ctx_phys;
> -       size_t ctx_ofs;
> -       size_t ctx_size;
> -
> -       void *desc_buf;
> -       size_t desc_phys;
> -
> -
> -       void *shm_alloc;
> -       void *shm;
> -       size_t shm_ofs;
> +       unsigned int ctx_size;
> +       struct s5p_mfc_priv_buf ctx;
> +       struct s5p_mfc_priv_buf dsc;
> +       struct s5p_mfc_priv_buf shm;
>
>         struct s5p_mfc_enc_params enc_params;
>
>         size_t enc_dst_buf_size;
> +       size_t luma_dpb_size;
> +       size_t chroma_dpb_size;
> +       size_t me_buffer_size;
> +       size_t tmv_buffer_size;
>
>         enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type;
>
>         struct list_head ref_queue;
>         unsigned int ref_queue_cnt;
>
> +       enum v4l2_mpeg_video_multi_slice_mode slice_mode;
> +       union {
> +               unsigned int mb;
> +               unsigned int bits;
> +       } slice_size;
> +
>         struct s5p_mfc_codec_ops *c_ops;
>
>         struct v4l2_ctrl *ctrls[MFC_MAX_CTRLS];
>         struct v4l2_ctrl_handler ctrl_handler;
> +       unsigned int frame_tag;
> +       size_t scratch_buf_size;
>  };
>
>  /*
> @@ -567,4 +636,18 @@ struct mfc_control {
>  #define ctrl_to_ctx(__ctrl) \
>         container_of((__ctrl)->handler, struct s5p_mfc_ctx, ctrl_handler)
>
> +#define HAS_PORTNUM(dev)       (dev ? (dev->variant ? \
> +                               (dev->variant->port_num ? 1 : 0) : 0) : 0)
> +#define IS_TWOPORT(dev)                (dev->variant->port_num == 2 ? 1 : 0)
> +#define IS_MFCV6(dev)          (dev->variant->version >= 0x60 ? 1 : 0)
> +
> +#if defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V5)
> +#include "regs-mfc.h"
> +#include "s5p_mfc_opr.h"
> +#include "s5p_mfc_shm.h"
> +#elif defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V6)
> +#include "regs-mfc-v6.h"
> +#include "s5p_mfc_opr_v6.h"
> +#endif
> +
>  #endif /* S5P_MFC_COMMON_H_ */
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
> index 08a5cfe..65ff15d 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
> @@ -15,7 +15,6 @@
>  #include <linux/firmware.h>
>  #include <linux/jiffies.h>
>  #include <linux/sched.h>
> -#include "regs-mfc.h"
>  #include "s5p_mfc_cmd.h"
>  #include "s5p_mfc_common.h"
>  #include "s5p_mfc_debug.h"
> @@ -38,12 +37,12 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
>          * into kernel. */
>         mfc_debug_enter();
>         err = request_firmware((const struct firmware **)&fw_blob,
> -                                    "s5p-mfc.fw", dev->v4l2_dev.dev);
> +                                    "mfc_fw.bin", dev->v4l2_dev.dev);
>         if (err != 0) {
>                 mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
>                 return -EINVAL;
>         }
> -       dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN);
> +       dev->fw_size = dev->variant->buf_size->fw;
>         if (s5p_mfc_bitproc_buf) {
>                 mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
>                 release_firmware(fw_blob);
> @@ -77,28 +76,33 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
>                 return -EIO;
>         }
>         dev->bank1 = s5p_mfc_bitproc_phys;
> -       b_base = vb2_dma_contig_memops.alloc(
> -               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BANK2_ALIGN_ORDER);
> -       if (IS_ERR(b_base)) {
> -               vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> -               s5p_mfc_bitproc_phys = 0;
> -               s5p_mfc_bitproc_buf = NULL;
> -               mfc_err("Allocating bank2 base failed\n");
> -       release_firmware(fw_blob);
> -               return -ENOMEM;
> -       }
> -       bank2_base_phys = s5p_mfc_mem_cookie(
> -               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
> -       vb2_dma_contig_memops.put(b_base);
> -       if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
> -               mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
> -               vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> -               s5p_mfc_bitproc_phys = 0;
> -               s5p_mfc_bitproc_buf = NULL;
> -               release_firmware(fw_blob);
> -               return -EIO;
> +       if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) {
> +               b_base = vb2_dma_contig_memops.alloc(
> +                       dev->alloc_ctx[MFC_BANK2_ALLOC_CTX],
> +                       1 << MFC_BANK2_ALIGN_ORDER);
> +               if (IS_ERR(b_base)) {
> +                       vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> +                       s5p_mfc_bitproc_phys = 0;
> +                       s5p_mfc_bitproc_buf = 0;
> +                       mfc_err("Allocating bank2 base failed\n");
> +                       release_firmware(fw_blob);
> +                       return -ENOMEM;
> +               }
> +               bank2_base_phys = s5p_mfc_mem_cookie(
> +                       dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
> +               vb2_dma_contig_memops.put(b_base);
> +               if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
> +                       mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
> +                       vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
> +                       s5p_mfc_bitproc_phys = 0;
> +                       s5p_mfc_bitproc_buf = 0;
> +                       release_firmware(fw_blob);
> +                       return -EIO;
> +               }
> +               dev->bank2 = bank2_base_phys;
> +       } else {
> +               dev->bank2 = dev->bank1;
>         }
> -       dev->bank2 = bank2_base_phys;
>         memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
>         wmb();
>         release_firmware(fw_blob);
> @@ -116,7 +120,7 @@ int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
>          * into kernel. */
>         mfc_debug_enter();
>         err = request_firmware((const struct firmware **)&fw_blob,
> -                                    "s5p-mfc.fw", dev->v4l2_dev.dev);
> +                                    "mfc_fw.bin", dev->v4l2_dev.dev);
>         if (err != 0) {
>                 mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
>                 return -EINVAL;
> @@ -157,46 +161,81 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev)
>  {
>         unsigned int mc_status;
>         unsigned long timeout;
> +       int i;
>
>         mfc_debug_enter();
> -       /* Stop procedure */
> -       /*  reset RISC */
> -       mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
> -       /*  All reset except for MC */
> -       mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
> -       mdelay(10);
> -
> -       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;
> -               }
>
> -               mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
> +       if (IS_MFCV6(dev)) {
> +               /* Reset IP */
> +               /*  except RISC, reset */
> +               mfc_write(dev, 0xFEE, S5P_FIMV_MFC_RESET);
> +               /*  reset release */
> +               mfc_write(dev, 0x0, S5P_FIMV_MFC_RESET);
>
> -       } while (mc_status & 0x3);
> +               /* Zero Initialization of MFC registers */
> +               mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> +               mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
> +               mfc_write(dev, 0, S5P_FIMV_FW_VERSION);
> +
> +               for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT; i++)
> +                       mfc_write(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN + (i*4));
> +
> +               /* Reset */
> +               mfc_write(dev, 0, S5P_FIMV_RISC_ON);
> +               mfc_write(dev, 0x1FFF, S5P_FIMV_MFC_RESET);
> +               mfc_write(dev, 0, S5P_FIMV_MFC_RESET);
> +       } else {
> +               /* Stop procedure */
> +               /*  reset RISC */
> +               mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
> +               /*  All reset except for MC */
> +               mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
> +               mdelay(10);
> +
> +               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;
> +                       }
> +
> +                       mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
> +
> +               } while (mc_status & 0x3);
> +
> +               mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
> +               mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
> +       }
>
> -       mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
> -       mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
>         mfc_debug_leave();
>         return 0;
>  }
>
>  static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
>  {
> -       mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
> -       mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
> -       mfc_debug(2, "Bank1: %08x, Bank2: %08x\n", dev->bank1, dev->bank2);
> +       if (IS_MFCV6(dev)) {
> +               mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS);
> +               mfc_debug(2, "Base Address : %08x\n", dev->bank1);
> +       } else {
> +               mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
> +               mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
> +               mfc_debug(2, "Bank1: %08x, Bank2: %08x\n",
> +                               dev->bank1, dev->bank2);
> +       }
>  }
>
>  static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
>  {
> -       mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
> -       mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
> -       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> -       mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
> +       if (IS_MFCV6(dev)) {
> +               /* Zero initialization should be done before RESET.
> +                * Nothing to do here. */
> +       } else {
> +               mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
> +               mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
> +               mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> +               mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
> +       }
>  }
>
>  /* Initialize hardware */
> @@ -224,7 +263,10 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
>         s5p_mfc_clear_cmds(dev);
>         /* 3. Release reset signal to the RISC */
>         s5p_mfc_clean_dev_int_flags(dev);
> -       mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
> +       if (IS_MFCV6(dev))
> +               mfc_write(dev, 0x1, S5P_FIMV_RISC_ON);
> +       else
> +               mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
>         mfc_debug(2, "Will now wait for completion of firmware transfer\n");
>         if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
>                 mfc_err("Failed to load firmware\n");
> @@ -267,6 +309,17 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
>  }
>
>
> +/* Deinitialize hardware */
> +void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev)
> +{
> +       s5p_mfc_clock_on();
> +
> +       s5p_mfc_reset(dev);
> +       s5p_mfc_release_dev_context_buffer(dev);
> +
> +       s5p_mfc_clock_off();
> +}
> +
>  int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
>  {
>         int ret;
> @@ -322,7 +375,10 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
>                 return ret;
>         }
>         /* 4. Release reset signal to the RISC */
> -       mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
> +       if (IS_MFCV6(dev))
> +               mfc_write(dev, 0x1, S5P_FIMV_RISC_ON);
> +       else
> +               mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
>         mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
>         if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) {
>                 mfc_err("Failed to load firmware\n");
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
> index 61dc23b..b72c8c6 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
> @@ -20,6 +20,7 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev);
>  int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev);
>
>  int s5p_mfc_init_hw(struct s5p_mfc_dev *dev);
> +void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev);
>
>  int s5p_mfc_sleep(struct s5p_mfc_dev *dev);
>  int s5p_mfc_wakeup(struct s5p_mfc_dev *dev);
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
> index 4dd32fc..d4c6cf2 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
> @@ -23,85 +23,113 @@
>  #include <linux/workqueue.h>
>  #include <media/v4l2-ctrls.h>
>  #include <media/videobuf2-core.h>
> -#include "regs-mfc.h"
>  #include "s5p_mfc_common.h"
>  #include "s5p_mfc_debug.h"
>  #include "s5p_mfc_dec.h"
>  #include "s5p_mfc_intr.h"
> -#include "s5p_mfc_opr.h"
>  #include "s5p_mfc_pm.h"
> -#include "s5p_mfc_shm.h"
> +
> +#define DEF_SRC_FMT    4
> +#define DEF_DST_FMT    0
>
>  static struct s5p_mfc_fmt formats[] = {
>         {
> +               .name           = "4:2:0 2 Planes 16x16 Tiles",
> +               .fourcc         = V4L2_PIX_FMT_NV12MT_16X16,
> +               .codec_mode     = S5P_FIMV_CODEC_NONE,
> +               .type           = MFC_FMT_RAW,
> +               .num_planes     = 2,
> +       },
> +       {
>                 .name           = "4:2:0 2 Planes 64x32 Tiles",
>                 .fourcc         = V4L2_PIX_FMT_NV12MT,
>                 .codec_mode     = S5P_FIMV_CODEC_NONE,
>                 .type           = MFC_FMT_RAW,
>                 .num_planes     = 2,
> -        },
> +       },
> +       {
> +               .name           = "4:2:0 2 Planes Y/CbCr",
> +               .fourcc         = V4L2_PIX_FMT_NV12M,
> +               .codec_mode     = S5P_FIMV_CODEC_NONE,
> +               .type           = MFC_FMT_RAW,
> +               .num_planes     = 2,
> +       },
> +       {
> +               .name           = "4:2:0 2 Planes Y/CrCb",
> +               .fourcc         = V4L2_PIX_FMT_NV21M,
> +               .codec_mode     = S5P_FIMV_CODEC_NONE,
> +               .type           = MFC_FMT_RAW,
> +               .num_planes     = 2,
> +       },
>         {
> -               .name = "4:2:0 2 Planes",
> -               .fourcc = V4L2_PIX_FMT_NV12M,
> -               .codec_mode = S5P_FIMV_CODEC_NONE,
> -               .type = MFC_FMT_RAW,
> -               .num_planes = 2,
> +               .name           = "H264 Encoded Stream",
> +               .fourcc         = V4L2_PIX_FMT_H264,
> +               .codec_mode     = S5P_FIMV_CODEC_H264_DEC,
> +               .type           = MFC_FMT_DEC,
> +               .num_planes     = 1,
>         },
>         {
> -               .name = "H264 Encoded Stream",
> -               .fourcc = V4L2_PIX_FMT_H264,
> -               .codec_mode = S5P_FIMV_CODEC_H264_DEC,
> -               .type = MFC_FMT_DEC,
> -               .num_planes = 1,
> +               .name           = "H264/MVC Encoded Stream",
> +               .fourcc         = V4L2_PIX_FMT_H264_MVC,
> +               .codec_mode     = S5P_FIMV_CODEC_H264_MVC_DEC,
> +               .type           = MFC_FMT_DEC,
> +               .num_planes     = 1,
>         },
>         {
> -               .name = "H263 Encoded Stream",
> -               .fourcc = V4L2_PIX_FMT_H263,
> -               .codec_mode = S5P_FIMV_CODEC_H263_DEC,
> -               .type = MFC_FMT_DEC,
> -               .num_planes = 1,
> +               .name           = "H263 Encoded Stream",
> +               .fourcc         = V4L2_PIX_FMT_H263,
> +               .codec_mode     = S5P_FIMV_CODEC_H263_DEC,
> +               .type           = MFC_FMT_DEC,
> +               .num_planes     = 1,
>         },
>         {
> -               .name = "MPEG1 Encoded Stream",
> -               .fourcc = V4L2_PIX_FMT_MPEG1,
> -               .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
> -               .type = MFC_FMT_DEC,
> -               .num_planes = 1,
> +               .name           = "MPEG1 Encoded Stream",
> +               .fourcc         = V4L2_PIX_FMT_MPEG1,
> +               .codec_mode     = S5P_FIMV_CODEC_MPEG2_DEC,
> +               .type           = MFC_FMT_DEC,
> +               .num_planes     = 1,
>         },
>         {
> -               .name = "MPEG2 Encoded Stream",
> -               .fourcc = V4L2_PIX_FMT_MPEG2,
> -               .codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
> -               .type = MFC_FMT_DEC,
> -               .num_planes = 1,
> +               .name           = "MPEG2 Encoded Stream",
> +               .fourcc         = V4L2_PIX_FMT_MPEG2,
> +               .codec_mode     = S5P_FIMV_CODEC_MPEG2_DEC,
> +               .type           = MFC_FMT_DEC,
> +               .num_planes     = 1,
>         },
>         {
> -               .name = "MPEG4 Encoded Stream",
> -               .fourcc = V4L2_PIX_FMT_MPEG4,
> -               .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
> -               .type = MFC_FMT_DEC,
> -               .num_planes = 1,
> +               .name           = "MPEG4 Encoded Stream",
> +               .fourcc         = V4L2_PIX_FMT_MPEG4,
> +               .codec_mode     = S5P_FIMV_CODEC_MPEG4_DEC,
> +               .type           = MFC_FMT_DEC,
> +               .num_planes     = 1,
>         },
>         {
> -               .name = "XviD Encoded Stream",
> -               .fourcc = V4L2_PIX_FMT_XVID,
> -               .codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
> -               .type = MFC_FMT_DEC,
> -               .num_planes = 1,
> +               .name           = "XviD Encoded Stream",
> +               .fourcc         = V4L2_PIX_FMT_XVID,
> +               .codec_mode     = S5P_FIMV_CODEC_MPEG4_DEC,
> +               .type           = MFC_FMT_DEC,
> +               .num_planes     = 1,
>         },
>         {
> -               .name = "VC1 Encoded Stream",
> -               .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
> -               .codec_mode = S5P_FIMV_CODEC_VC1_DEC,
> -               .type = MFC_FMT_DEC,
> -               .num_planes = 1,
> +               .name           = "VC1 Encoded Stream",
> +               .fourcc         = V4L2_PIX_FMT_VC1_ANNEX_G,
> +               .codec_mode     = S5P_FIMV_CODEC_VC1_DEC,
> +               .type           = MFC_FMT_DEC,
> +               .num_planes     = 1,
>         },
>         {
> -               .name = "VC1 RCV Encoded Stream",
> -               .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
> -               .codec_mode = S5P_FIMV_CODEC_VC1RCV_DEC,
> -               .type = MFC_FMT_DEC,
> -               .num_planes = 1,
> +               .name           = "VC1 RCV Encoded Stream",
> +               .fourcc         = V4L2_PIX_FMT_VC1_ANNEX_L,
> +               .codec_mode     = S5P_FIMV_CODEC_VC1RCV_DEC,
> +               .type           = MFC_FMT_DEC,
> +               .num_planes     = 1,
> +       },
> +       {
> +               .name           = "VC8 Encoded Stream",
> +               .fourcc         = V4L2_PIX_FMT_VP8,
> +               .codec_mode     = S5P_FIMV_CODEC_VP8_DEC,
> +               .type           = MFC_FMT_DEC,
> +               .num_planes     = 1,
>         },
>  };
>
> @@ -336,21 +364,35 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
>  /* Try format */
>  static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
>  {
> +       struct s5p_mfc_dev *dev = video_drvdata(file);
>         struct s5p_mfc_fmt *fmt;
>
> -       if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> -               mfc_err("This node supports decoding only\n");
> -               return -EINVAL;
> -       }
> -       fmt = find_format(f, MFC_FMT_DEC);
> -       if (!fmt) {
> -               mfc_err("Unsupported format\n");
> -               return -EINVAL;
> -       }
> -       if (fmt->type != MFC_FMT_DEC) {
> -               mfc_err("\n");
> -               return -EINVAL;
> +       mfc_debug(2, "Type is %d\n", f->type);
> +       if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> +               fmt = find_format(f, MFC_FMT_DEC);
> +               if (!fmt) {
> +                       mfc_err("Unsupported format for source.\n");
> +                       return -EINVAL;
> +               }
> +               if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
> +                       mfc_err("Not supported format.\n");
> +                       return -EINVAL;
> +               }
> +       } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
> +               fmt = find_format(f, MFC_FMT_RAW);
> +               if (!fmt) {
> +                       mfc_err("Unsupported format for destination.\n");
> +                       return -EINVAL;
> +               }
> +               if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
> +                       mfc_err("Not supported format.\n");
> +                       return -EINVAL;
> +               } else if (fmt->fourcc != V4L2_PIX_FMT_NV12MT) {
> +                       mfc_err("Not supported format.\n");
> +                       return -EINVAL;
> +               }
>         }
> +
>         return 0;
>  }
>
> @@ -373,6 +415,26 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
>                 ret = -EBUSY;
>                 goto out;
>         }
> +       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
> +               fmt = find_format(f, MFC_FMT_RAW);
> +               if (!fmt) {
> +                       mfc_err("Unsupported format for source.\n");
> +                       return -EINVAL;
> +               }
> +               if (!IS_MFCV6(dev) && (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) {
> +                       mfc_err("Not supported format.\n");
> +                       return -EINVAL;
> +               } else if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
> +                       mfc_err("Not supported format.\n");
> +                       return -EINVAL;
> +               }
> +               ctx->dst_fmt = fmt;
> +               mfc_debug_leave();
> +               return ret;
> +       } else if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
> +               mfc_err("Wrong type error for S_FMT : %d", f->type);
> +               return -EINVAL;
> +       }
>         fmt = find_format(f, MFC_FMT_DEC);
>         if (!fmt || fmt->codec_mode == S5P_FIMV_CODEC_NONE) {
>                 mfc_err("Unknown codec\n");
> @@ -385,6 +447,10 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
>                 ret = -EINVAL;
>                 goto out;
>         }
> +       if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
> +               mfc_err("Not supported format.\n");
> +               return -EINVAL;
> +       }
>         ctx->src_fmt = fmt;
>         ctx->codec_mode = fmt->codec_mode;
>         mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
> @@ -498,7 +564,7 @@ static int vidioc_reqbufs(struct file *file, void *priv,
>                 }
>                 s5p_mfc_try_run(dev);
>                 s5p_mfc_wait_for_done_ctx(ctx,
> -                                        S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0);
> +                                       S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0);
>         }
>         return ret;
>  }
> @@ -696,10 +762,10 @@ static int vidioc_g_crop(struct file *file, void *priv,
>                         return -EINVAL;
>                 }
>         if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) {
> -               left = s5p_mfc_read_shm(ctx, CROP_INFO_H);
> +               left = s5p_mfc_read_info(ctx, CROP_INFO_H);
>                 right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT;
>                 left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK;
> -               top = s5p_mfc_read_shm(ctx, CROP_INFO_V);
> +               top = s5p_mfc_read_info(ctx, CROP_INFO_V);
>                 bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT;
>                 top = top & S5P_FIMV_SHARED_CROP_TOP_MASK;
>                 cr->c.left = left;
> @@ -750,6 +816,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
>                         void *allocators[])
>  {
>         struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
> +       struct s5p_mfc_dev *dev = ctx->dev;
>
>         /* Video output for decoding (source)
>          * this can be set after getting an instance */
> @@ -785,7 +852,13 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
>             vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
>                 psize[0] = ctx->luma_size;
>                 psize[1] = ctx->chroma_size;
> -               allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> +
> +               if (IS_MFCV6(dev))
> +                       allocators[0] =
> +                               ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
> +               else
> +                       allocators[0] =
> +                               ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
>                 allocators[1] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
>         } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
>                    ctx->state == MFCINST_INIT) {
> @@ -1035,3 +1108,10 @@ void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx)
>                 ctx->ctrls[i] = NULL;
>  }
>
> +void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx)
> +{
> +       ctx->src_fmt = &formats[DEF_SRC_FMT];
> +       ctx->dst_fmt = &formats[DEF_DST_FMT];
> +       mfc_debug(2, "Default src_fmt is %x, dest_fmt is %x\n",
> +                       (unsigned int)ctx->src_fmt, (unsigned int)ctx->dst_fmt);
> +}
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.h b/drivers/media/video/s5p-mfc/s5p_mfc_dec.h
> index fb8b215..c53baf8 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_dec.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.h
> @@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void);
>  struct s5p_mfc_fmt *get_dec_def_fmt(bool src);
>  int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx);
>  void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx);
>
>  #endif /* S5P_MFC_DEC_H_ */
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
> index 03d8334..645a8ef 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
> @@ -24,48 +24,63 @@
>  #include <linux/workqueue.h>
>  #include <media/v4l2-ctrls.h>
>  #include <media/videobuf2-core.h>
> -#include "regs-mfc.h"
>  #include "s5p_mfc_common.h"
>  #include "s5p_mfc_debug.h"
>  #include "s5p_mfc_enc.h"
>  #include "s5p_mfc_intr.h"
> -#include "s5p_mfc_opr.h"
> +
> +#define DEF_SRC_FMT    2
> +#define DEF_DST_FMT    4
>
>  static struct s5p_mfc_fmt formats[] = {
>         {
> -               .name = "4:2:0 2 Planes 64x32 Tiles",
> -               .fourcc = V4L2_PIX_FMT_NV12MT,
> -               .codec_mode = S5P_FIMV_CODEC_NONE,
> -               .type = MFC_FMT_RAW,
> -               .num_planes = 2,
> +               .name           = "4:2:0 2 Planes 16x16 Tiles",
> +               .fourcc         = V4L2_PIX_FMT_NV12MT_16X16,
> +               .codec_mode     = S5P_FIMV_CODEC_NONE,
> +               .type           = MFC_FMT_RAW,
> +               .num_planes     = 2,
> +       },
> +       {
> +               .name           = "4:2:0 2 Planes 64x32 Tiles",
> +               .fourcc         = V4L2_PIX_FMT_NV12MT,
> +               .codec_mode     = S5P_FIMV_CODEC_NONE,
> +               .type           = MFC_FMT_RAW,
> +               .num_planes     = 2,
> +       },
> +       {
> +               .name           = "4:2:0 2 Planes Y/CbCr",
> +               .fourcc         = V4L2_PIX_FMT_NV12M,
> +               .codec_mode     = S5P_FIMV_CODEC_NONE,
> +               .type           = MFC_FMT_RAW,
> +               .num_planes     = 2,
>         },
>         {
> -               .name = "4:2:0 2 Planes",
> -               .fourcc = V4L2_PIX_FMT_NV12M,
> -               .codec_mode = S5P_FIMV_CODEC_NONE,
> -               .type = MFC_FMT_RAW,
> -               .num_planes = 2,
> +               .name           = "4:2:0 2 Planes Y/CrCb",
> +               .fourcc         = V4L2_PIX_FMT_NV21M,
> +               .codec_mode     = S5P_FIMV_CODEC_NONE,
> +               .type           = MFC_FMT_RAW,
> +               .num_planes     = 2,
>         },
>         {
> -               .name = "H264 Encoded Stream",
> -               .fourcc = V4L2_PIX_FMT_H264,
> -               .codec_mode = S5P_FIMV_CODEC_H264_ENC,
> -               .type = MFC_FMT_ENC,
> -               .num_planes = 1,
> +               .name           = "H264 Encoded Stream",
> +               .fourcc         = V4L2_PIX_FMT_H264,
> +               .codec_mode     = S5P_FIMV_CODEC_H264_ENC,
> +               .type           = MFC_FMT_ENC,
> +               .num_planes     = 1,
>         },
>         {
> -               .name = "MPEG4 Encoded Stream",
> -               .fourcc = V4L2_PIX_FMT_MPEG4,
> -               .codec_mode = S5P_FIMV_CODEC_MPEG4_ENC,
> -               .type = MFC_FMT_ENC,
> -               .num_planes = 1,
> +               .name           = "MPEG4 Encoded Stream",
> +               .fourcc         = V4L2_PIX_FMT_MPEG4,
> +               .codec_mode     = S5P_FIMV_CODEC_MPEG4_ENC,
> +               .type           = MFC_FMT_ENC,
> +               .num_planes     = 1,
>         },
>         {
> -               .name = "H263 Encoded Stream",
> -               .fourcc = V4L2_PIX_FMT_H263,
> -               .codec_mode = S5P_FIMV_CODEC_H263_ENC,
> -               .type = MFC_FMT_ENC,
> -               .num_planes = 1,
> +               .name           = "H263 Encoded Stream",
> +               .fourcc         = V4L2_PIX_FMT_H263,
> +               .codec_mode     = S5P_FIMV_CODEC_H263_ENC,
> +               .type           = MFC_FMT_ENC,
> +               .num_planes     = 1,
>         },
>  };
>
> @@ -641,13 +656,22 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
>                 vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE);
>                 spin_unlock_irqrestore(&dev->irqlock, flags);
>         }
> -       ctx->state = MFCINST_RUNNING;
> -       if (s5p_mfc_ctx_ready(ctx)) {
> -               spin_lock_irqsave(&dev->condlock, flags);
> -               set_bit(ctx->num, &dev->ctx_work_bits);
> -               spin_unlock_irqrestore(&dev->condlock, flags);
> +
> +       if (IS_MFCV6(dev)) {
> +               ctx->state = MFCINST_HEAD_PARSED; /* for INIT_BUFFER cmd */
> +       } else {
> +               ctx->state = MFCINST_RUNNING;
> +               if (s5p_mfc_ctx_ready(ctx)) {
> +                       spin_lock_irqsave(&dev->condlock, flags);
> +                       set_bit(ctx->num, &dev->ctx_work_bits);
> +                       spin_unlock_irqrestore(&dev->condlock, flags);
> +               }
> +               s5p_mfc_try_run(dev);
>         }
> -       s5p_mfc_try_run(dev);
> +
> +       if (IS_MFCV6(dev))
> +               ctx->dpb_count = s5p_mfc_get_enc_dpb_count();
> +
>         return 0;
>  }
>
> @@ -961,6 +985,17 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
>                         mfc_err("failed to set output format\n");
>                         return -EINVAL;
>                 }
> +
> +               if (!IS_MFCV6(dev) &&
> +                               (fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)) {
> +                       mfc_err("Not supported format.\n");
> +                       return -EINVAL;
> +               } else if (IS_MFCV6(dev) &&
> +                               (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
> +                       mfc_err("Not supported format.\n");
> +                       return -EINVAL;
> +               }
> +
>                 if (fmt->num_planes != pix_fmt_mp->num_planes) {
>                         mfc_err("failed to set output format\n");
>                         ret = -EINVAL;
> @@ -973,45 +1008,13 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
>                 mfc_debug(2, "fmt - w: %d, h: %d, ctx - w: %d, h: %d\n",
>                         pix_fmt_mp->width, pix_fmt_mp->height,
>                         ctx->img_width, ctx->img_height);
> -               if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
> -                       ctx->buf_width = ALIGN(ctx->img_width,
> -                                                       S5P_FIMV_NV12M_HALIGN);
> -                       ctx->luma_size = ALIGN(ctx->img_width,
> -                               S5P_FIMV_NV12M_HALIGN) * ALIGN(ctx->img_height,
> -                               S5P_FIMV_NV12M_LVALIGN);
> -                       ctx->chroma_size = ALIGN(ctx->img_width,
> -                               S5P_FIMV_NV12M_HALIGN) * ALIGN((ctx->img_height
> -                               >> 1), S5P_FIMV_NV12M_CVALIGN);
> -
> -                       ctx->luma_size = ALIGN(ctx->luma_size,
> -                                                       S5P_FIMV_NV12M_SALIGN);
> -                       ctx->chroma_size = ALIGN(ctx->chroma_size,
> -                                                       S5P_FIMV_NV12M_SALIGN);
> -
> -                       pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
> -                       pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
> -                       pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
> -                       pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
> -
> -               } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
> -                       ctx->buf_width = ALIGN(ctx->img_width,
> -                                                       S5P_FIMV_NV12MT_HALIGN);
> -                       ctx->luma_size = ALIGN(ctx->img_width,
> -                               S5P_FIMV_NV12MT_HALIGN) * ALIGN(ctx->img_height,
> -                               S5P_FIMV_NV12MT_VALIGN);
> -                       ctx->chroma_size = ALIGN(ctx->img_width,
> -                               S5P_FIMV_NV12MT_HALIGN) * ALIGN((ctx->img_height
> -                               >> 1), S5P_FIMV_NV12MT_VALIGN);
> -                       ctx->luma_size = ALIGN(ctx->luma_size,
> -                                                       S5P_FIMV_NV12MT_SALIGN);
> -                       ctx->chroma_size = ALIGN(ctx->chroma_size,
> -                                                       S5P_FIMV_NV12MT_SALIGN);
> -
> -                       pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
> -                       pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
> -                       pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
> -                       pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
> -               }
> +
> +               s5p_mfc_enc_calc_src_size(ctx);
> +               pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
> +               pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
> +               pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
> +               pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
> +
>                 ctx->src_bufs_cnt = 0;
>                 ctx->output_state = QUEUE_FREE;
>         } else {
> @@ -1026,6 +1029,7 @@ out:
>  static int vidioc_reqbufs(struct file *file, void *priv,
>                                           struct v4l2_requestbuffers *reqbufs)
>  {
> +       struct s5p_mfc_dev *dev = video_drvdata(file);
>         struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
>         int ret = 0;
>
> @@ -1045,12 +1049,15 @@ static int vidioc_reqbufs(struct file *file, void *priv,
>                         return ret;
>                 }
>                 ctx->capture_state = QUEUE_BUFS_REQUESTED;
> -               ret = s5p_mfc_alloc_codec_buffers(ctx);
> -               if (ret) {
> -                       mfc_err("Failed to allocate encoding buffers\n");
> -                       reqbufs->count = 0;
> -                       ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
> -                       return -ENOMEM;
> +
> +               if (!IS_MFCV6(dev)) {
> +                       ret = s5p_mfc_alloc_codec_buffers(ctx);
> +                       if (ret) {
> +                               mfc_err("Failed to allocate encoding buffers\n");
> +                               reqbufs->count = 0;
> +                               ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
> +                               return -ENOMEM;
> +                       }
>                 }
>         } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
>                 if (ctx->output_state != QUEUE_FREE) {
> @@ -1297,6 +1304,13 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
>                         p->codec.h264.profile =
>                                 S5P_FIMV_ENC_PROFILE_H264_BASELINE;
>                         break;
> +               case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
> +                       if (IS_MFCV6(dev))
> +                               p->codec.h264.profile =
> +                               S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE;
> +                       else
> +                               ret = -EINVAL;
> +                       break;
>                 default:
>                         ret = -EINVAL;
>                 }
> @@ -1516,6 +1530,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
>                         unsigned int psize[], void *allocators[])
>  {
>         struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
> +       struct s5p_mfc_dev *dev = ctx->dev;
>
>         if (ctx->state != MFCINST_GOT_INST) {
>                 mfc_err("inavlid state: %d\n", ctx->state);
> @@ -1544,8 +1559,17 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
>                         *buf_count = MFC_MAX_BUFFERS;
>                 psize[0] = ctx->luma_size;
>                 psize[1] = ctx->chroma_size;
> -               allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> -               allocators[1] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> +               if (IS_MFCV6(dev)) {
> +                       allocators[0] =
> +                               ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
> +                       allocators[1] =
> +                               ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
> +               } else {
> +                       allocators[0] =
> +                               ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> +                       allocators[1] =
> +                               ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
> +               }
>         } else {
>                 mfc_err("inavlid queue type: %d\n", vq->type);
>                 return -EINVAL;
> @@ -1826,3 +1850,10 @@ void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx)
>         for (i = 0; i < NUM_CTRLS; i++)
>                 ctx->ctrls[i] = NULL;
>  }
> +
> +void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx)
> +{
> +       ctx->src_fmt = &formats[DEF_SRC_FMT];
> +       ctx->dst_fmt = &formats[DEF_DST_FMT];
> +}
> +
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.h b/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
> index 405bdd3..413f22f 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
> @@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void);
>  struct s5p_mfc_fmt *get_enc_def_fmt(bool src);
>  int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx);
>  void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx);
>
>  #endif /* S5P_MFC_ENC_H_  */
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_intr.c b/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
> index 8f2f8bf..dfdc558 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
> @@ -17,7 +17,6 @@
>  #include <linux/io.h>
>  #include <linux/sched.h>
>  #include <linux/wait.h>
> -#include "regs-mfc.h"
>  #include "s5p_mfc_common.h"
>  #include "s5p_mfc_debug.h"
>  #include "s5p_mfc_intr.h"
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
> index e6217cb..1fd9c92 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
> @@ -12,15 +12,12 @@
>   * published by the Free Software Foundation.
>   */
>
> -#include "regs-mfc.h"
> -#include "s5p_mfc_cmd.h"
>  #include "s5p_mfc_common.h"
> +#include "s5p_mfc_cmd.h"
>  #include "s5p_mfc_ctrl.h"
>  #include "s5p_mfc_debug.h"
>  #include "s5p_mfc_intr.h"
> -#include "s5p_mfc_opr.h"
>  #include "s5p_mfc_pm.h"
> -#include "s5p_mfc_shm.h"
>  #include <asm/cacheflush.h>
>  #include <linux/delay.h>
>  #include <linux/dma-mapping.h>
> @@ -37,39 +34,31 @@
>  /* Allocate temporary buffers for decoding */
>  int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx)
>  {
> -       void *desc_virt;
>         struct s5p_mfc_dev *dev = ctx->dev;
> +       struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
>
> -       ctx->desc_buf = vb2_dma_contig_memops.alloc(
> -                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], DESC_BUF_SIZE);
> -       if (IS_ERR_VALUE((int)ctx->desc_buf)) {
> -               ctx->desc_buf = NULL;
> +       ctx->dsc.alloc = vb2_dma_contig_memops.alloc(
> +                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
> +                       buf_size->dsc);
> +       if (IS_ERR_VALUE((int)ctx->dsc.alloc)) {
> +               ctx->dsc.alloc = NULL;
>                 mfc_err("Allocating DESC buffer failed\n");
>                 return -ENOMEM;
>         }
> -       ctx->desc_phys = s5p_mfc_mem_cookie(
> -                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->desc_buf);
> -       BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> -       desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf);
> -       if (desc_virt == NULL) {
> -               vb2_dma_contig_memops.put(ctx->desc_buf);
> -               ctx->desc_phys = 0;
> -               ctx->desc_buf = NULL;
> -               mfc_err("Remapping DESC buffer failed\n");
> -               return -ENOMEM;
> -       }
> -       memset(desc_virt, 0, DESC_BUF_SIZE);
> -       wmb();
> +       ctx->dsc.dma = s5p_mfc_mem_cookie(
> +                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->dsc.alloc);
> +       BUG_ON(ctx->dsc.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> +
>         return 0;
>  }
>
>  /* Release temporary buffers for decoding */
>  void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
>  {
> -       if (ctx->desc_phys) {
> -               vb2_dma_contig_memops.put(ctx->desc_buf);
> -               ctx->desc_phys = 0;
> -               ctx->desc_buf = NULL;
> +       if (ctx->dsc.dma) {
> +               vb2_dma_contig_memops.put(ctx->dsc.alloc);
> +               ctx->dsc.alloc = NULL;
> +               ctx->dsc.dma = 0;
>         }
>  }
>
> @@ -231,41 +220,43 @@ void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx)
>  /* Allocate memory for instance data buffer */
>  int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx)
>  {
> -       void *context_virt;
>         struct s5p_mfc_dev *dev = ctx->dev;
> +       struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
>
>         if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
>                 ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
> -               ctx->ctx_size = MFC_H264_CTX_BUF_SIZE;
> +               ctx->ctx_size = buf_size->h264_ctx;
>         else
> -               ctx->ctx_size = MFC_CTX_BUF_SIZE;
> -       ctx->ctx_buf = vb2_dma_contig_memops.alloc(
> +               ctx->ctx_size = buf_size->non_h264_ctx;
> +       ctx->ctx.alloc = vb2_dma_contig_memops.alloc(
>                 dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size);
> -       if (IS_ERR(ctx->ctx_buf)) {
> +       if (IS_ERR(ctx->ctx.alloc)) {
>                 mfc_err("Allocating context buffer failed\n");
> -               ctx->ctx_phys = 0;
> -               ctx->ctx_buf = NULL;
> +               ctx->ctx.alloc = NULL;
>                 return -ENOMEM;
>         }
> -       ctx->ctx_phys = s5p_mfc_mem_cookie(
> -               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_buf);
> -       BUG_ON(ctx->ctx_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> -       ctx->ctx_ofs = OFFSETA(ctx->ctx_phys);
> -       context_virt = vb2_dma_contig_memops.vaddr(ctx->ctx_buf);
> -       if (context_virt == NULL) {
> +       ctx->ctx.dma = s5p_mfc_mem_cookie(
> +               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc);
> +       BUG_ON(ctx->ctx.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> +       ctx->ctx.ofs = OFFSETA(ctx->ctx.dma);
> +       ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc);
> +       if (!ctx->ctx.virt) {
>                 mfc_err("Remapping instance buffer failed\n");
> -               vb2_dma_contig_memops.put(ctx->ctx_buf);
> -               ctx->ctx_phys = 0;
> -               ctx->ctx_buf = NULL;
> +               vb2_dma_contig_memops.put(ctx->ctx.alloc);
> +               ctx->ctx.alloc = NULL;
> +               ctx->ctx.ofs = 0;
> +               ctx->ctx.dma = 0;
>                 return -ENOMEM;
>         }
>         /* Zero content of the allocated memory */
> -       memset(context_virt, 0, ctx->ctx_size);
> +       memset(ctx->ctx.virt, 0, ctx->ctx_size);
>         wmb();
>         if (s5p_mfc_init_shm(ctx) < 0) {
> -               vb2_dma_contig_memops.put(ctx->ctx_buf);
> -               ctx->ctx_phys = 0;
> -               ctx->ctx_buf = NULL;
> +               vb2_dma_contig_memops.put(ctx->ctx.alloc);
> +               ctx->ctx.alloc = NULL;
> +               ctx->ctx.ofs = 0;
> +               ctx->ctx.virt = NULL;
> +               ctx->ctx.dma = 0;
>                 return -ENOMEM;
>         }
>         return 0;
> @@ -274,15 +265,100 @@ int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx)
>  /* Release instance buffer */
>  void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx)
>  {
> -       if (ctx->ctx_buf) {
> -               vb2_dma_contig_memops.put(ctx->ctx_buf);
> -               ctx->ctx_phys = 0;
> -               ctx->ctx_buf = NULL;
> +       if (ctx->ctx.alloc) {
> +               vb2_dma_contig_memops.put(ctx->ctx.alloc);
> +               ctx->ctx.alloc = NULL;
> +               ctx->ctx.ofs = 0;
> +               ctx->ctx.virt = NULL;
> +               ctx->ctx.dma = 0;
>         }
> -       if (ctx->shm_alloc) {
> -               vb2_dma_contig_memops.put(ctx->shm_alloc);
> -               ctx->shm_alloc = NULL;
> -               ctx->shm = NULL;
> +       if (ctx->shm.alloc) {
> +               vb2_dma_contig_memops.put(ctx->shm.alloc);
> +               ctx->shm.alloc = NULL;
> +               ctx->shm.ofs = 0;
> +               ctx->shm.virt = NULL;
> +       }
> +}
> +
> +int s5p_mfc_alloc_dev_context_buffer(struct s5p_mfc_dev *dev)
> +{
> +       /* NOP */
> +
> +       return 0;
> +}
> +
> +void s5p_mfc_release_dev_context_buffer(struct s5p_mfc_dev *dev)
> +{
> +       /* NOP */
> +}
> +
> +void s5p_mfc_dec_calc_dpb_size(struct s5p_mfc_ctx *ctx)
> +{
> +       unsigned int guard_width, guard_height;
> +
> +       ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
> +       ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
> +       mfc_debug(2,
> +               "SEQ Done: Movie dimensions %dx%d, buffer dimensions: %dx%d\n",
> +               ctx->img_width, ctx->img_height, ctx->buf_width,
> +               ctx->buf_height);
> +
> +       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
> +               ctx->luma_size = ALIGN(ctx->buf_width * ctx->buf_height,
> +                               S5P_FIMV_DEC_BUF_ALIGN);
> +               ctx->chroma_size = ALIGN(ctx->buf_width *
> +                               ALIGN((ctx->img_height >> 1),
> +                                       S5P_FIMV_NV12MT_VALIGN),
> +                               S5P_FIMV_DEC_BUF_ALIGN);
> +               ctx->mv_size = ALIGN(ctx->buf_width *
> +                               ALIGN((ctx->buf_height >> 2),
> +                                       S5P_FIMV_NV12MT_VALIGN),
> +                               S5P_FIMV_DEC_BUF_ALIGN);
> +       } else {
> +               guard_width =
> +                       ALIGN(ctx->img_width + 24, S5P_FIMV_NV12MT_HALIGN);
> +               guard_height =
> +                       ALIGN(ctx->img_height + 16, S5P_FIMV_NV12MT_VALIGN);
> +               ctx->luma_size = ALIGN(guard_width * guard_height,
> +                               S5P_FIMV_DEC_BUF_ALIGN);
> +
> +               guard_width =
> +                       ALIGN(ctx->img_width + 16, S5P_FIMV_NV12MT_HALIGN);
> +               guard_height =
> +                       ALIGN((ctx->img_height >> 1) + 4,
> +                                       S5P_FIMV_NV12MT_VALIGN);
> +               ctx->chroma_size = ALIGN(guard_width * guard_height,
> +                               S5P_FIMV_DEC_BUF_ALIGN);
> +
> +               ctx->mv_size = 0;
> +       }
> +}
> +
> +void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx)
> +{
> +       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
> +               ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN);
> +
> +               ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
> +                       * ALIGN(ctx->img_height, S5P_FIMV_NV12M_LVALIGN);
> +               ctx->chroma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
> +                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12M_CVALIGN);
> +
> +               ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12M_SALIGN);
> +               ctx->chroma_size =
> +                       ALIGN(ctx->chroma_size, S5P_FIMV_NV12M_SALIGN);
> +       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
> +               ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
> +
> +               ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
> +                       * ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
> +               ctx->chroma_size =
> +                       ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
> +                       * ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
> +
> +               ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12MT_SALIGN);
> +               ctx->chroma_size =
> +                       ALIGN(ctx->chroma_size, S5P_FIMV_NV12MT_SALIGN);
>         }
>  }
>
> @@ -290,16 +366,17 @@ void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx)
>  void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
>  {
>         struct s5p_mfc_dev *dev = ctx->dev;
> +       struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
>
> -       mfc_write(dev, OFFSETA(ctx->desc_phys), S5P_FIMV_SI_CH0_DESC_ADR);
> -       mfc_write(dev, DESC_BUF_SIZE, S5P_FIMV_SI_CH0_DESC_SIZE);
> +       mfc_write(dev, OFFSETA(ctx->dsc.dma), S5P_FIMV_SI_CH0_DESC_ADR);
> +       mfc_write(dev, buf_size->dsc, S5P_FIMV_SI_CH0_DESC_SIZE);
>  }
>
>  /* Set registers for shared buffer */
>  static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
>  {
>         struct s5p_mfc_dev *dev = ctx->dev;
> -       mfc_write(dev, ctx->shm_ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
> +       mfc_write(dev, ctx->shm.ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
>  }
>
>  /* Set registers for decoding stream buffer */
> @@ -311,7 +388,7 @@ int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
>         mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);
>         mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);
>         mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);
> -       s5p_mfc_write_shm(ctx, start_num_byte, START_BYTE_NUM);
> +       s5p_mfc_write_info(ctx, start_num_byte, START_BYTE_NUM);
>         return 0;
>  }
>
> @@ -438,10 +515,10 @@ int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx)
>                 mfc_debug(2, "Not enough memory has been allocated\n");
>                 return -ENOMEM;
>         }
> -       s5p_mfc_write_shm(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
> -       s5p_mfc_write_shm(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
> +       s5p_mfc_write_info(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
> +       s5p_mfc_write_info(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
>         if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC)
> -               s5p_mfc_write_shm(ctx, frame_size_mv, ALLOC_MV_SIZE);
> +               s5p_mfc_write_info(ctx, frame_size_mv, ALLOC_MV_SIZE);
>         mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
>                                         << S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
>                                                 S5P_FIMV_SI_CH0_INST_ID);
> @@ -685,16 +762,16 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
>         /* reaction coefficient */
>         if (p->rc_frame)
>                 mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);
> -       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
> +       shm = s5p_mfc_read_info(ctx, EXT_ENC_CONTROL);
>         /* seq header ctrl */
>         shm &= ~(0x1 << 3);
>         shm |= (p->seq_hdr_mode << 3);
>         /* frame skip mode */
>         shm &= ~(0x3 << 1);
>         shm |= (p->frame_skip_mode << 1);
> -       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
> +       s5p_mfc_write_info(ctx, shm, EXT_ENC_CONTROL);
>         /* fixed target bit */
> -       s5p_mfc_write_shm(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
> +       s5p_mfc_write_info(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
>         return 0;
>  }
>
> @@ -723,9 +800,9 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
>         reg |= p_264->profile;
>         mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
>         /* interlace  */
> -       mfc_write(dev, p->interlace, S5P_FIMV_ENC_PIC_STRUCT);
> +       mfc_write(dev, p_264->interlace, S5P_FIMV_ENC_PIC_STRUCT);
>         /* height */
> -       if (p->interlace)
> +       if (p_264->interlace)
>                 mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
>         /* loopfilter ctrl */
>         mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
> @@ -767,7 +844,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
>         reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
>         /* macroblock level rate control */
>         reg &= ~(0x1 << 8);
> -       reg |= (p_264->rc_mb << 8);
> +       reg |= (p->rc_mb << 8);
>         /* frame QP */
>         reg &= ~(0x3F);
>         reg |= p_264->rc_frame_qp;
> @@ -788,7 +865,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
>         reg |= p_264->rc_min_qp;
>         mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
>         /* macroblock adaptive scaling features */
> -       if (p_264->rc_mb) {
> +       if (p->rc_mb) {
>                 reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
>                 /* dark region */
>                 reg &= ~(0x1 << 3);
> @@ -804,37 +881,36 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
>                 reg |= p_264->rc_mb_activity;
>                 mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
>         }
> -       if (!p->rc_frame &&
> -           !p_264->rc_mb) {
> -               shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
> +       if (!p->rc_frame && !p->rc_mb) {
> +               shm = s5p_mfc_read_info(ctx, P_B_FRAME_QP);
>                 shm &= ~(0xFFF);
>                 shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
>                 shm |= (p_264->rc_p_frame_qp & 0x3F);
> -               s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
> +               s5p_mfc_write_info(ctx, shm, P_B_FRAME_QP);
>         }
>         /* extended encoder ctrl */
> -       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
> +       shm = s5p_mfc_read_info(ctx, EXT_ENC_CONTROL);
>         /* AR VUI control */
>         shm &= ~(0x1 << 15);
>         shm |= (p_264->vui_sar << 1);
> -       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
> +       s5p_mfc_write_info(ctx, shm, EXT_ENC_CONTROL);
>         if (p_264->vui_sar) {
>                 /* aspect ration IDC */
> -               shm = s5p_mfc_read_shm(ctx, SAMPLE_ASPECT_RATIO_IDC);
> +               shm = s5p_mfc_read_info(ctx, SAMPLE_ASPECT_RATIO_IDC);
>                 shm &= ~(0xFF);
>                 shm |= p_264->vui_sar_idc;
> -               s5p_mfc_write_shm(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
> +               s5p_mfc_write_info(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
>                 if (p_264->vui_sar_idc == 0xFF) {
>                         /* sample  AR info */
> -                       shm = s5p_mfc_read_shm(ctx, EXTENDED_SAR);
> +                       shm = s5p_mfc_read_info(ctx, EXTENDED_SAR);
>                         shm &= ~(0xFFFFFFFF);
>                         shm |= p_264->vui_ext_sar_width << 16;
>                         shm |= p_264->vui_ext_sar_height;
> -                       s5p_mfc_write_shm(ctx, shm, EXTENDED_SAR);
> +                       s5p_mfc_write_info(ctx, shm, EXTENDED_SAR);
>                 }
>         }
>         /* intra picture period for H.264 */
> -       shm = s5p_mfc_read_shm(ctx, H264_I_PERIOD);
> +       shm = s5p_mfc_read_info(ctx, H264_I_PERIOD);
>         /* control */
>         shm &= ~(0x1 << 16);
>         shm |= (p_264->open_gop << 16);
> @@ -843,16 +919,16 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
>                 shm &= ~(0xFFFF);
>                 shm |= p_264->open_gop_size;
>         }
> -       s5p_mfc_write_shm(ctx, shm, H264_I_PERIOD);
> +       s5p_mfc_write_info(ctx, shm, H264_I_PERIOD);
>         /* extended encoder ctrl */
> -       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
> +       shm = s5p_mfc_read_info(ctx, EXT_ENC_CONTROL);
>         /* vbv buffer size */
>         if (p->frame_skip_mode ==
>                         V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
>                 shm &= ~(0xFFFF << 16);
>                 shm |= (p_264->cpb_size << 16);
>         }
> -       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
> +       s5p_mfc_write_info(ctx, shm, EXT_ENC_CONTROL);
>         return 0;
>  }
>
> @@ -885,11 +961,11 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
>         mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);
>         /* qp */
>         if (!p->rc_frame) {
> -               shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
> +               shm = s5p_mfc_read_info(ctx, P_B_FRAME_QP);
>                 shm &= ~(0xFFF);
>                 shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);
>                 shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);
> -               s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
> +               s5p_mfc_write_info(ctx, shm, P_B_FRAME_QP);
>         }
>         /* frame rate */
>         if (p->rc_frame) {
> @@ -898,12 +974,12 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
>                                                 p->rc_framerate_denom;
>                         mfc_write(dev, framerate,
>                                 S5P_FIMV_ENC_RC_FRAME_RATE);
> -                       shm = s5p_mfc_read_shm(ctx, RC_VOP_TIMING);
> +                       shm = s5p_mfc_read_info(ctx, RC_VOP_TIMING);
>                         shm &= ~(0xFFFFFFFF);
>                         shm |= (1 << 31);
>                         shm |= ((p->rc_framerate_num & 0x7FFF) << 16);
>                         shm |= (p->rc_framerate_denom & 0xFFFF);
> -                       s5p_mfc_write_shm(ctx, shm, RC_VOP_TIMING);
> +                       s5p_mfc_write_info(ctx, shm, RC_VOP_TIMING);
>                 }
>         } else {
>                 mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
> @@ -924,14 +1000,14 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
>         reg |= p_mpeg4->rc_min_qp;
>         mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
>         /* extended encoder ctrl */
> -       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
> +       shm = s5p_mfc_read_info(ctx, EXT_ENC_CONTROL);
>         /* vbv buffer size */
>         if (p->frame_skip_mode ==
>                         V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
>                 shm &= ~(0xFFFF << 16);
>                 shm |= (p->vbv_size << 16);
>         }
> -       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
> +       s5p_mfc_write_info(ctx, shm, EXT_ENC_CONTROL);
>         return 0;
>  }
>
> @@ -946,10 +1022,10 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
>         s5p_mfc_set_enc_params(ctx);
>         /* qp */
>         if (!p->rc_frame) {
> -               shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
> +               shm = s5p_mfc_read_info(ctx, P_B_FRAME_QP);
>                 shm &= ~(0xFFF);
>                 shm |= (p_h263->rc_p_frame_qp & 0x3F);
> -               s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
> +               s5p_mfc_write_info(ctx, shm, P_B_FRAME_QP);
>         }
>         /* frame rate */
>         if (p->rc_frame && p->rc_framerate_denom)
> @@ -973,14 +1049,14 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
>         reg |= p_h263->rc_min_qp;
>         mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
>         /* extended encoder ctrl */
> -       shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
> +       shm = s5p_mfc_read_info(ctx, EXT_ENC_CONTROL);
>         /* vbv buffer size */
>         if (p->frame_skip_mode ==
>                         V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
>                 shm &= ~(0xFFFF << 16);
>                 shm |= (p->vbv_size << 16);
>         }
> -       s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
> +       s5p_mfc_write_info(ctx, shm, EXT_ENC_CONTROL);
>         return 0;
>  }
>
> @@ -1395,3 +1471,21 @@ void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq)
>         }
>  }
>
> +void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
> +{
> +       mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
> +       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> +       mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
> +}
> +
> +void s5p_mfc_write_info(struct s5p_mfc_ctx *ctx, unsigned int data,
> +                       unsigned int ofs)
> +{
> +       s5p_mfc_write_shm(ctx, data, ofs);
> +}
> +
> +unsigned int s5p_mfc_read_info(struct s5p_mfc_ctx *ctx,
> +                               unsigned int ofs)
> +{
> +       return s5p_mfc_read_shm(ctx, ofs);
> +}
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr.h b/drivers/media/video/s5p-mfc/s5p_mfc_opr.h
> index 5932d1c..6b49a7c 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_opr.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr.h
> @@ -50,8 +50,20 @@ void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx);
>  int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx);
>  void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx);
>
> +int s5p_mfc_alloc_dev_context_buffer(struct s5p_mfc_dev *dev);
> +void s5p_mfc_release_dev_context_buffer(struct s5p_mfc_dev *dev);
> +
> +void s5p_mfc_dec_calc_dpb_size(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx);
> +
>  void s5p_mfc_try_run(struct s5p_mfc_dev *dev);
>  void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
> +void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev);
> +
> +void s5p_mfc_write_info(struct s5p_mfc_ctx *ctx, unsigned int data,
> +               unsigned int ofs);
> +unsigned int s5p_mfc_read_info(struct s5p_mfc_ctx *ctx,
> +               unsigned int ofs);
>
>  #define s5p_mfc_get_dspl_y_adr()       (readl(dev->regs_base + \
>                                         S5P_FIMV_SI_DISPLAY_Y_ADR) << \
> @@ -63,9 +75,13 @@ void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
>                                                 S5P_FIMV_SI_DISPLAY_STATUS)
>  #define s5p_mfc_get_dec_status()       readl(dev->regs_base + \
>                                                 S5P_FIMV_SI_DECODE_STATUS)
> -#define s5p_mfc_get_frame_type()       (readl(dev->regs_base + \
> +#define s5p_mfc_get_dec_frame_type()   (readl(dev->regs_base + \
>                                                 S5P_FIMV_DECODE_FRAME_TYPE) \
>                                         & S5P_FIMV_DECODE_FRAME_MASK)
> +#define s5p_mfc_get_disp_frame_type()  ((s5p_mfc_read_shm(ctx, \
> +                                               DISP_PIC_FRAME_TYPE) \
> +                                               >> S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT) \
> +                                       & S5P_FIMV_DECODE_FRAME_MASK)
>  #define s5p_mfc_get_consumed_stream()  readl(dev->regs_base + \
>                                                 S5P_FIMV_SI_CONSUMED_BYTES)
>  #define s5p_mfc_get_int_reason()       (readl(dev->regs_base + \
> @@ -89,5 +105,12 @@ void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
>                                                 S5P_FIMV_ENC_SI_STRM_SIZE)
>  #define s5p_mfc_get_enc_slice_type()   readl(dev->regs_base + \
>                                                 S5P_FIMV_ENC_SI_SLICE_TYPE)
> +#define s5p_mfc_get_enc_dpb_count()    -1
> +#define s5p_mfc_get_enc_pic_count()    readl(dev->regs_base + \
> +                                               S5P_FIMV_ENC_SI_PIC_CNT)
> +#define s5p_mfc_get_sei_avail_status() s5p_mfc_read_shm(ctx, \
> +                                               FRAME_PACK_SEI_AVAIL)
> +#define s5p_mfc_get_mvc_num_views()    -1
> +#define s5p_mfc_get_mvc_view_id()      -1
>
>  #endif /* S5P_MFC_OPR_H_ */
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c
> new file mode 100644
> index 0000000..8e68ecc
> --- /dev/null
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c
> @@ -0,0 +1,1697 @@
> +/*
> + * drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c
> + *
> + * Samsung MFC (Multi Function Codec - FIMV) driver
> + * This file contains hw related functions.
> + *
> + * Copyright (c) 2012 Samsung Electronics
> + *             http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#undef DEBUG
> +
> +#include <linux/delay.h>
> +#include <linux/mm.h>
> +#include <linux/io.h>
> +#include <linux/jiffies.h>
> +#include <linux/firmware.h>
> +#include <linux/err.h>
> +#include <linux/sched.h>
> +#include <linux/dma-mapping.h>
> +
> +#include <asm/cacheflush.h>
> +
> +#include "s5p_mfc_common.h"
> +#include "s5p_mfc_cmd.h"
> +#include "s5p_mfc_intr.h"
> +#include "s5p_mfc_pm.h"
> +#include "s5p_mfc_debug.h"
> +
> +/* #define S5P_MFC_DEBUG_REGWRITE  */
> +#ifdef S5P_MFC_DEBUG_REGWRITE
> +#undef writel
> +#define writel(v, r)                                                   \
> +       do {                                                            \
> +               pr_err("MFCWRITE(%p): %08x\n", r, (unsigned int)v);     \
> +       __raw_writel(v, r);                                             \
> +       } while (0)
> +#endif /* S5P_MFC_DEBUG_REGWRITE */
> +
> +#define READL(offset)          readl(dev->regs_base + (offset))
> +#define WRITEL(data, offset)   writel((data), dev->regs_base + (offset))
> +#define OFFSETA(x)             (((x) - dev->port_a) >> S5P_FIMV_MEM_OFFSET)
> +#define OFFSETB(x)             (((x) - dev->port_b) >> S5P_FIMV_MEM_OFFSET)
> +
> +/* Allocate temporary buffers for decoding */
> +int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx)
> +{
> +       /* NOP */
> +
> +       return 0;
> +}
> +
> +/* Release temproary buffers for decoding */
> +void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
> +{
> +       /* NOP */
> +}
> +
> +/* Allocate codec buffers */
> +int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       unsigned int mb_width, mb_height;
> +
> +       mb_width = mb_width(ctx->img_width);
> +       mb_height = mb_height(ctx->img_height);
> +
> +       if (ctx->type == MFCINST_DECODER) {
> +               mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
> +                         ctx->luma_size, ctx->chroma_size, ctx->mv_size);
> +               mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
> +       } else if (ctx->type == MFCINST_ENCODER) {
> +               ctx->tmv_buffer_size = 2 * ALIGN((mb_width + 1) *
> +                               (mb_height + 1) * 8, 16);
> +               ctx->luma_dpb_size = ALIGN((mb_width * mb_height) * 256, 256);
> +               ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) * 128, 256);
> +               ctx->me_buffer_size = ALIGN(((((ctx->img_width+63)/64) * 16) *
> +                       (((ctx->img_height+63)/64) * 16)) +
> +                        ((((mb_width*mb_height)+31)/32) * 16), 256);
> +
> +               mfc_debug(2, "recon luma size: %d chroma size: %d\n",
> +                         ctx->luma_dpb_size, ctx->chroma_dpb_size);
> +       } else {
> +               return -EINVAL;
> +       }
> +
> +       /* Codecs have different memory requirements */
> +       switch (ctx->codec_mode) {
> +       case S5P_FIMV_CODEC_H264_DEC:
> +       case S5P_FIMV_CODEC_H264_MVC_DEC:
> +               ctx->scratch_buf_size = (mb_width * 128) + 65536;
> +               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
> +               ctx->bank1_size =
> +                       ctx->scratch_buf_size +
> +                       (ctx->total_dpb_count * ctx->mv_size);
> +               break;
> +       case S5P_FIMV_CODEC_MPEG4_DEC:
> +               /* mb_width * (mb_height * 64 + 144) + 8192 * mb_height +
> +                * 41088 */
> +               ctx->scratch_buf_size = mb_width * (mb_height * 64 + 144) +
> +                       ((2048 + 15)/16 * mb_height * 64) +
> +                       ((2048 + 15)/16 * 256 + 8320);
> +               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
> +               ctx->bank1_size = ctx->scratch_buf_size;
> +               break;
> +       case S5P_FIMV_CODEC_VC1RCV_DEC:
> +       case S5P_FIMV_CODEC_VC1_DEC:
> +               ctx->scratch_buf_size = 2096 * (mb_width + mb_height + 1);
> +               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
> +               ctx->bank1_size = ctx->scratch_buf_size;
> +               break;
> +       case S5P_FIMV_CODEC_MPEG2_DEC:
> +               ctx->bank1_size = 0;
> +               ctx->bank2_size = 0;
> +               break;
> +       case S5P_FIMV_CODEC_H263_DEC:
> +               ctx->scratch_buf_size = mb_width * 400;
> +               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
> +               ctx->bank1_size = ctx->scratch_buf_size;
> +               break;
> +       case S5P_FIMV_CODEC_VP8_DEC:
> +               ctx->scratch_buf_size = mb_width * 32 + mb_height * 128 + 34816;
> +               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
> +               ctx->bank1_size = ctx->scratch_buf_size;
> +               break;
> +       case S5P_FIMV_CODEC_H264_ENC:
> +               ctx->scratch_buf_size = (mb_width * 64) +
> +                       ((mb_width + 1) * 16) + (4096 * 16);
> +               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
> +               ctx->bank1_size =
> +                       ctx->scratch_buf_size + ctx->tmv_buffer_size +
> +                       (ctx->dpb_count * (ctx->luma_dpb_size +
> +                       ctx->chroma_dpb_size + ctx->me_buffer_size));
> +               ctx->bank2_size = 0;
> +               break;
> +       case S5P_FIMV_CODEC_MPEG4_ENC:
> +       case S5P_FIMV_CODEC_H263_ENC:
> +               ctx->scratch_buf_size = (mb_width * 16) + ((mb_width + 1) * 16);
> +               ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
> +               ctx->bank1_size =
> +                       ctx->scratch_buf_size + ctx->tmv_buffer_size +
> +                       (ctx->dpb_count * (ctx->luma_dpb_size +
> +                       ctx->chroma_dpb_size + ctx->me_buffer_size));
> +               ctx->bank2_size = 0;
> +               break;
> +       default:
> +               break;
> +       }
> +
> +       /* Allocate only if memory from bank 1 is necessary */
> +       if (ctx->bank1_size > 0) {
> +               ctx->bank1_buf = vb2_dma_contig_memops.alloc(
> +               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
> +               if (IS_ERR(ctx->bank1_buf)) {
> +                       ctx->bank1_buf = 0;
> +                       pr_err("Buf alloc for decoding failed (port A)\n");
> +                       return -ENOMEM;
> +               }
> +               ctx->bank1_phys = s5p_mfc_mem_cookie(
> +                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
> +               BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> +       }
> +
> +       return 0;
> +}
> +
> +/* Release buffers allocated for codec */
> +void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx)
> +{
> +       if (ctx->bank1_buf) {
> +               vb2_dma_contig_memops.put(ctx->bank1_buf);
> +               ctx->bank1_buf = 0;
> +               ctx->bank1_phys = 0;
> +               ctx->bank1_size = 0;
> +       }
> +}
> +
> +/* Allocate memory for instance data buffer */
> +int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
> +
> +       mfc_debug_enter();
> +
> +       switch (ctx->codec_mode) {
> +       case S5P_FIMV_CODEC_H264_DEC:
> +       case S5P_FIMV_CODEC_H264_MVC_DEC:
> +               ctx->ctx_size = buf_size->h264_dec_ctx;
> +               break;
> +       case S5P_FIMV_CODEC_MPEG4_DEC:
> +       case S5P_FIMV_CODEC_H263_DEC:
> +       case S5P_FIMV_CODEC_VC1RCV_DEC:
> +       case S5P_FIMV_CODEC_VC1_DEC:
> +       case S5P_FIMV_CODEC_MPEG2_DEC:
> +       case S5P_FIMV_CODEC_VP8_DEC:
> +               ctx->ctx_size = buf_size->other_dec_ctx;
> +               break;
> +       case S5P_FIMV_CODEC_H264_ENC:
> +               ctx->ctx_size = buf_size->h264_enc_ctx;
> +               break;
> +       case S5P_FIMV_CODEC_MPEG4_ENC:
> +       case S5P_FIMV_CODEC_H263_ENC:
> +               ctx->ctx_size = buf_size->other_enc_ctx;
> +               break;
> +       default:
> +               ctx->ctx_size = 0;
> +               mfc_err("Codec type(%d) should be checked!\n", ctx->codec_mode);
> +               break;
> +       }
> +
> +       ctx->ctx.alloc = vb2_dma_contig_memops.alloc(
> +               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size);
> +       if (IS_ERR(ctx->ctx.alloc)) {
> +               mfc_err("Allocating context buffer failed.\n");
> +               return PTR_ERR(ctx->ctx.alloc);
> +       }
> +
> +       ctx->ctx.dma = s5p_mfc_mem_cookie(
> +               dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc);
> +
> +       ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc);
> +       if (!ctx->ctx.virt) {
> +               vb2_dma_contig_memops.put(ctx->ctx.alloc);
> +               ctx->ctx.alloc = NULL;
> +               ctx->ctx.dma = 0;
> +               ctx->ctx.virt = NULL;
> +
> +               mfc_err("Remapping context buffer failed.\n");
> +               return -ENOMEM;
> +       }
> +
> +       memset(ctx->ctx.virt, 0, ctx->ctx_size);
> +       wmb();
> +
> +       mfc_debug_leave();
> +
> +       return 0;
> +}
> +
> +/* Release instance buffer */
> +void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx)
> +{
> +       mfc_debug_enter();
> +
> +       if (ctx->ctx.alloc) {
> +               vb2_dma_contig_memops.put(ctx->ctx.alloc);
> +               ctx->ctx.alloc = NULL;
> +               ctx->ctx.dma = 0;
> +               ctx->ctx.virt = NULL;
> +       }
> +
> +       mfc_debug_leave();
> +}
> +
> +/* Allocate context buffers for SYS_INIT */
> +int s5p_mfc_alloc_dev_context_buffer(struct s5p_mfc_dev *dev)
> +{
> +       struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
> +
> +       mfc_debug_enter();
> +
> +       dev->ctx_buf.alloc = vb2_dma_contig_memops.alloc(
> +                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], buf_size->dev_ctx);
> +       if (IS_ERR(dev->ctx_buf.alloc)) {
> +               mfc_err("Allocating DESC buffer failed.\n");
> +               return PTR_ERR(dev->ctx_buf.alloc);
> +       }
> +
> +       dev->ctx_buf.dma = s5p_mfc_mem_cookie(
> +                       dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
> +                       dev->ctx_buf.alloc);
> +
> +       dev->ctx_buf.virt = vb2_dma_contig_memops.vaddr(dev->ctx_buf.alloc);
> +       if (!dev->ctx_buf.virt) {
> +               vb2_dma_contig_memops.put(dev->ctx_buf.alloc);
> +               dev->ctx_buf.alloc = NULL;
> +               dev->ctx_buf.dma = 0;
> +
> +               mfc_err("Remapping DESC buffer failed.\n");
> +               return -ENOMEM;
> +       }
> +
> +       memset(dev->ctx_buf.virt, 0, buf_size->dev_ctx);
> +       wmb();
> +
> +       mfc_debug_leave();
> +
> +       return 0;
> +}
> +
> +/* Release context buffers for SYS_INIT */
> +void s5p_mfc_release_dev_context_buffer(struct s5p_mfc_dev *dev)
> +{
> +       if (dev->ctx_buf.alloc) {
> +               vb2_dma_contig_memops.put(dev->ctx_buf.alloc);
> +               dev->ctx_buf.alloc = NULL;
> +               dev->ctx_buf.dma = 0;
> +               dev->ctx_buf.virt = NULL;
> +       }
> +}
> +
> +static int calc_plane(int width, int height)
> +{
> +       int mbX, mbY;
> +
> +       mbX = (width + 15)/16;
> +       mbY = (height + 15)/16;
> +
> +       if (width * height < 2048 * 1024)
> +               mbY = (mbY + 1) / 2 * 2;
> +
> +       return (mbX * 16) * (mbY * 16);
> +}
> +
> +void s5p_mfc_dec_calc_dpb_size(struct s5p_mfc_ctx *ctx)
> +{
> +       ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
> +       ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
> +       mfc_debug(2, "SEQ Done: Movie dimensions %dx%d,\n"
> +                       "buffer dimensions: %dx%d\n", ctx->img_width,
> +                       ctx->img_height, ctx->buf_width, ctx->buf_height);
> +
> +       ctx->luma_size = calc_plane(ctx->img_width, ctx->img_height);
> +       ctx->chroma_size = calc_plane(ctx->img_width, (ctx->img_height >> 1));
> +       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
> +                       ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC) {
> +               ctx->mv_size = s5p_mfc_dec_mv_size(ctx->img_width,
> +                               ctx->img_height);
> +               ctx->mv_size = ALIGN(ctx->mv_size, 16);
> +       } else {
> +               ctx->mv_size = 0;
> +       }
> +}
> +
> +void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx)
> +{
> +       unsigned int mb_width, mb_height;
> +
> +       mb_width = mb_width(ctx->img_width);
> +       mb_height = mb_height(ctx->img_height);
> +
> +       ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN);
> +       ctx->luma_size = ALIGN((mb_width * mb_height) * 256, 256);
> +       ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256);
> +}
> +
> +/* Set registers for decoding stream buffer */
> +int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
> +                 unsigned int start_num_byte, unsigned int strm_size)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;
> +
> +       mfc_debug_enter();
> +       mfc_debug(2, "inst_no: %d, buf_addr: 0x%08x,\n"
> +               "buf_size: 0x%08x (%d)\n",
> +               ctx->inst_no, buf_addr, strm_size, strm_size);
> +       WRITEL(strm_size, S5P_FIMV_D_STREAM_DATA_SIZE);
> +       WRITEL(buf_addr, S5P_FIMV_D_CPB_BUFFER_ADDR);
> +       WRITEL(buf_size->cpb, S5P_FIMV_D_CPB_BUFFER_SIZE);
> +       WRITEL(start_num_byte, S5P_FIMV_D_CPB_BUFFER_OFFSET);
> +
> +       mfc_debug_leave();
> +       return 0;
> +}
> +
> +/* Set decoding frame buffer */
> +int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx)
> +{
> +       unsigned int frame_size, i;
> +       unsigned int frame_size_ch, frame_size_mv;
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       size_t buf_addr1;
> +       int buf_size1;
> +       int align_gap;
> +
> +       buf_addr1 = ctx->bank1_phys;
> +       buf_size1 = ctx->bank1_size;
> +
> +       mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
> +       mfc_debug(2, "Total DPB COUNT: %d\n", ctx->total_dpb_count);
> +       mfc_debug(2, "Setting display delay to %d\n", ctx->display_delay);
> +
> +       WRITEL(ctx->total_dpb_count, S5P_FIMV_D_NUM_DPB);
> +       WRITEL(ctx->luma_size, S5P_FIMV_D_LUMA_DPB_SIZE);
> +       WRITEL(ctx->chroma_size, S5P_FIMV_D_CHROMA_DPB_SIZE);
> +
> +       WRITEL(buf_addr1, S5P_FIMV_D_SCRATCH_BUFFER_ADDR);
> +       WRITEL(ctx->scratch_buf_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE);
> +       buf_addr1 += ctx->scratch_buf_size;
> +       buf_size1 -= ctx->scratch_buf_size;
> +
> +       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
> +                       ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC)
> +               WRITEL(ctx->mv_size, S5P_FIMV_D_MV_BUFFER_SIZE);
> +
> +       frame_size = ctx->luma_size;
> +       frame_size_ch = ctx->chroma_size;
> +       frame_size_mv = ctx->mv_size;
> +       mfc_debug(2, "Frame size: %d ch: %d mv: %d\n",
> +                       frame_size, frame_size_ch, frame_size_mv);
> +
> +       for (i = 0; i < ctx->total_dpb_count; i++) {
> +               /* Bank2 */
> +               mfc_debug(2, "Luma %d: %x\n", i,
> +                                       ctx->dst_bufs[i].cookie.raw.luma);
> +               WRITEL(ctx->dst_bufs[i].cookie.raw.luma,
> +                               S5P_FIMV_D_LUMA_DPB + i * 4);
> +               mfc_debug(2, "\tChroma %d: %x\n", i,
> +                                       ctx->dst_bufs[i].cookie.raw.chroma);
> +               WRITEL(ctx->dst_bufs[i].cookie.raw.chroma,
> +                               S5P_FIMV_D_CHROMA_DPB + i * 4);
> +
> +               if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
> +                               ctx->codec_mode ==
> +                               S5P_FIMV_CODEC_H264_MVC_DEC) {
> +                       /* To test alignment */
> +                       align_gap = buf_addr1;
> +                       buf_addr1 = ALIGN(buf_addr1, 16);
> +                       align_gap = buf_addr1 - align_gap;
> +                       buf_size1 -= align_gap;
> +
> +                       mfc_debug(2, "\tBuf1: %x, size: %d\n",
> +                                       buf_addr1, buf_size1);
> +                       WRITEL(buf_addr1, S5P_FIMV_D_MV_BUFFER + i * 4);
> +                       buf_addr1 += frame_size_mv;
> +                       buf_size1 -= frame_size_mv;
> +               }
> +       }
> +
> +       mfc_debug(2, "Buf1: %u, buf_size1: %d (frames %d)\n",
> +                       buf_addr1, buf_size1, ctx->total_dpb_count);
> +       if (buf_size1 < 0) {
> +               mfc_debug(2, "Not enough memory has been allocated.\n");
> +               return -ENOMEM;
> +       }
> +
> +       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
> +       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_INIT_BUFS, NULL);
> +
> +       mfc_debug(2, "After setting buffers.\n");
> +       return 0;
> +}
> +
> +/* Set registers for encoding stream buffer */
> +int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
> +               unsigned long addr, unsigned int size)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +
> +       WRITEL(addr, S5P_FIMV_E_STREAM_BUFFER_ADDR); /* 16B align */
> +       WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE);
> +
> +       mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%d",
> +               addr, size);
> +
> +       return 0;
> +}
> +
> +void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
> +               unsigned long y_addr, unsigned long c_addr)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +
> +       WRITEL(y_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR); /* 256B align */
> +       WRITEL(c_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR);
> +
> +       mfc_debug(2, "enc src y buf addr: 0x%08lx", y_addr);
> +       mfc_debug(2, "enc src c buf addr: 0x%08lx", c_addr);
> +}
> +
> +void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
> +               unsigned long *y_addr, unsigned long *c_addr)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       unsigned long enc_recon_y_addr, enc_recon_c_addr;
> +
> +       *y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR);
> +       *c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR);
> +
> +       enc_recon_y_addr = READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR);
> +       enc_recon_c_addr = READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR);
> +
> +       mfc_debug(2, "recon y addr: 0x%08lx", enc_recon_y_addr);
> +       mfc_debug(2, "recon c addr: 0x%08lx", enc_recon_c_addr);
> +}
> +
> +/* Set encoding ref & codec buffer */
> +int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       size_t buf_addr1, buf_size1;
> +       int i;
> +
> +       mfc_debug_enter();
> +
> +       buf_addr1 = ctx->bank1_phys;
> +       buf_size1 = ctx->bank1_size;
> +
> +       mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
> +
> +       for (i = 0; i < ctx->dpb_count; i++) {
> +               WRITEL(buf_addr1, S5P_FIMV_E_LUMA_DPB + (4 * i));
> +               buf_addr1 += ctx->luma_dpb_size;
> +               WRITEL(buf_addr1, S5P_FIMV_E_CHROMA_DPB + (4 * i));
> +               buf_addr1 += ctx->chroma_dpb_size;
> +               WRITEL(buf_addr1, S5P_FIMV_E_ME_BUFFER + (4 * i));
> +               buf_addr1 += ctx->me_buffer_size;
> +               buf_size1 -= (ctx->luma_dpb_size + ctx->chroma_dpb_size +
> +                       ctx->me_buffer_size);
> +       }
> +
> +       WRITEL(buf_addr1, S5P_FIMV_E_SCRATCH_BUFFER_ADDR);
> +       WRITEL(ctx->scratch_buf_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE);
> +       buf_addr1 += ctx->scratch_buf_size;
> +       buf_size1 -= ctx->scratch_buf_size;
> +
> +       WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER0);
> +       buf_addr1 += ctx->tmv_buffer_size >> 1;
> +       WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER1);
> +       buf_addr1 += ctx->tmv_buffer_size >> 1;
> +       buf_size1 -= ctx->tmv_buffer_size;
> +
> +       mfc_debug(2, "Buf1: %u, buf_size1: %d (ref frames %d)\n",
> +                       buf_addr1, buf_size1, ctx->dpb_count);
> +       if (buf_size1 < 0) {
> +               mfc_debug(2, "Not enough memory has been allocated.\n");
> +               return -ENOMEM;
> +       }
> +
> +       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
> +       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_INIT_BUFS, NULL);
> +
> +       mfc_debug_leave();
> +
> +       return 0;
> +}
> +
> +static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +
> +       /* multi-slice control */
> +       /* multi-slice MB number or bit size */
> +       WRITEL(ctx->slice_mode, S5P_FIMV_E_MSLICE_MODE);
> +       if (ctx->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
> +               WRITEL(ctx->slice_size.mb, S5P_FIMV_E_MSLICE_SIZE_MB);
> +       } else if (ctx->slice_mode ==
> +                       V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
> +               WRITEL(ctx->slice_size.bits, S5P_FIMV_E_MSLICE_SIZE_BITS);
> +       } else {
> +               WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_MB);
> +               WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_BITS);
> +       }
> +
> +       return 0;
> +}
> +
> +static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       struct s5p_mfc_enc_params *p = &ctx->enc_params;
> +       unsigned int reg = 0;
> +
> +       mfc_debug_enter();
> +
> +       /* width */
> +       WRITEL(ctx->img_width, S5P_FIMV_E_FRAME_WIDTH); /* 16 align */
> +       /* height */
> +       WRITEL(ctx->img_height, S5P_FIMV_E_FRAME_HEIGHT); /* 16 align */
> +
> +       /* cropped width */
> +       WRITEL(ctx->img_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH);
> +       /* cropped height */
> +       WRITEL(ctx->img_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT);
> +       /* cropped offset */
> +       WRITEL(0x0, S5P_FIMV_E_FRAME_CROP_OFFSET);
> +
> +       /* pictype : IDR period */
> +       reg = 0;
> +       reg |= p->gop_size & 0xFFFF;
> +       WRITEL(reg, S5P_FIMV_E_GOP_CONFIG);
> +
> +       /* multi-slice control */
> +       /* multi-slice MB number or bit size */
> +       ctx->slice_mode = p->slice_mode;
> +       reg = 0;
> +       if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
> +               reg |= (0x1 << 3);
> +               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
> +               ctx->slice_size.mb = p->slice_mb;
> +       } else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
> +               reg |= (0x1 << 3);
> +               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
> +               ctx->slice_size.bits = p->slice_bit;
> +       } else {
> +               reg &= ~(0x1 << 3);
> +               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
> +       }
> +
> +       s5p_mfc_set_slice_mode(ctx);
> +
> +       /* cyclic intra refresh */
> +       WRITEL(p->intra_refresh_mb, S5P_FIMV_E_IR_SIZE);
> +       reg = READL(S5P_FIMV_E_ENC_OPTIONS);
> +       if (p->intra_refresh_mb == 0)
> +               reg &= ~(0x1 << 4);
> +       else
> +               reg |= (0x1 << 4);
> +       WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
> +
> +       /* 'NON_REFERENCE_STORE_ENABLE' for debugging */
> +       reg = READL(S5P_FIMV_E_ENC_OPTIONS);
> +       reg &= ~(0x1 << 9);
> +       WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
> +
> +       /* memory structure cur. frame */
> +       if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
> +               /* 0: Linear, 1: 2D tiled*/
> +               reg = READL(S5P_FIMV_E_ENC_OPTIONS);
> +               reg &= ~(0x1 << 7);
> +               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
> +               /* 0: NV12(CbCr), 1: NV21(CrCb) */
> +               WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT);
> +       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M) {
> +               /* 0: Linear, 1: 2D tiled*/
> +               reg = READL(S5P_FIMV_E_ENC_OPTIONS);
> +               reg &= ~(0x1 << 7);
> +               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
> +               /* 0: NV12(CbCr), 1: NV21(CrCb) */
> +               WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT);
> +       } else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) {
> +               /* 0: Linear, 1: 2D tiled*/
> +               reg = READL(S5P_FIMV_E_ENC_OPTIONS);
> +               reg |= (0x1 << 7);
> +               WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
> +               /* 0: NV12(CbCr), 1: NV21(CrCb) */
> +               WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT);
> +       }
> +
> +       /* memory structure recon. frame */
> +       /* 0: Linear, 1: 2D tiled */
> +       reg = READL(S5P_FIMV_E_ENC_OPTIONS);
> +       reg |= (0x1 << 8);
> +       WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
> +
> +       /* padding control & value */
> +       WRITEL(0x0, S5P_FIMV_E_PADDING_CTRL);
> +       if (p->pad) {
> +               reg = 0;
> +               /** enable */
> +               reg |= (1 << 31);
> +               /** cr value */
> +               reg |= ((p->pad_cr & 0xFF) << 16);
> +               /** cb value */
> +               reg |= ((p->pad_cb & 0xFF) << 8);
> +               /** y value */
> +               reg |= p->pad_luma & 0xFF;
> +               WRITEL(reg, S5P_FIMV_E_PADDING_CTRL);
> +       }
> +
> +       /* rate control config. */
> +       reg = 0;
> +       /* frame-level rate control */
> +       reg |= ((p->rc_frame & 0x1) << 9);
> +       WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
> +
> +       /* bit rate */
> +       if (p->rc_frame)
> +               WRITEL(p->rc_bitrate,
> +                       S5P_FIMV_E_RC_BIT_RATE);
> +       else
> +               WRITEL(1, S5P_FIMV_E_RC_BIT_RATE);
> +
> +       /* reaction coefficient */
> +       if (p->rc_frame) {
> +               if (p->rc_reaction_coeff < TIGHT_CBR_MAX) /* tight CBR */
> +                       WRITEL(1, S5P_FIMV_E_RC_RPARAM);
> +               else                                      /* loose CBR */
> +                       WRITEL(2, S5P_FIMV_E_RC_RPARAM);
> +       }
> +
> +       /* seq header ctrl */
> +       reg = READL(S5P_FIMV_E_ENC_OPTIONS);
> +       reg &= ~(0x1 << 2);
> +       reg |= ((p->seq_hdr_mode & 0x1) << 2);
> +
> +       /* frame skip mode */
> +       reg &= ~(0x3);
> +       reg |= (p->frame_skip_mode & 0x3);
> +       WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
> +
> +       /* 'DROP_CONTROL_ENABLE', disable */
> +       reg = READL(S5P_FIMV_E_RC_CONFIG);
> +       reg &= ~(0x1 << 10);
> +       WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
> +
> +       /* setting for MV range [16, 256] */
> +       reg = 0;
> +       reg &= ~(0x3FFF);
> +       reg = 256;
> +       WRITEL(reg, S5P_FIMV_E_MV_HOR_RANGE);
> +
> +       reg = 0;
> +       reg &= ~(0x3FFF);
> +       reg = 256;
> +       WRITEL(reg, S5P_FIMV_E_MV_VER_RANGE);
> +
> +       WRITEL(0x0, S5P_FIMV_E_FRAME_INSERTION);
> +       WRITEL(0x0, S5P_FIMV_E_ROI_BUFFER_ADDR);
> +       WRITEL(0x0, S5P_FIMV_E_PARAM_CHANGE);
> +       WRITEL(0x0, S5P_FIMV_E_RC_ROI_CTRL);
> +       WRITEL(0x0, S5P_FIMV_E_PICTURE_TAG);
> +
> +       WRITEL(0x0, S5P_FIMV_E_BIT_COUNT_ENABLE);
> +       WRITEL(0x0, S5P_FIMV_E_MAX_BIT_COUNT);
> +       WRITEL(0x0, S5P_FIMV_E_MIN_BIT_COUNT);
> +
> +       WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_ADDR);
> +       WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_SIZE);
> +
> +       mfc_debug_leave();
> +
> +       return 0;
> +}
> +
> +static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       struct s5p_mfc_enc_params *p = &ctx->enc_params;
> +       struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
> +       unsigned int reg = 0;
> +       int i;
> +
> +       mfc_debug_enter();
> +
> +       s5p_mfc_set_enc_params(ctx);
> +
> +       /* pictype : number of B */
> +       reg = READL(S5P_FIMV_E_GOP_CONFIG);
> +       reg &= ~(0x3 << 16);
> +       reg |= ((p->num_b_frame & 0x3) << 16);
> +       WRITEL(reg, S5P_FIMV_E_GOP_CONFIG);
> +
> +       /* profile & level */
> +       reg = 0;
> +       /** level */
> +       reg |= ((p_h264->level & 0xFF) << 8);
> +       /** profile - 0 ~ 3 */
> +       reg |= p_h264->profile & 0x3F;
> +       WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
> +
> +       /* rate control config. */
> +       reg = READL(S5P_FIMV_E_RC_CONFIG);
> +       /** macroblock level rate control */
> +       reg &= ~(0x1 << 8);
> +       reg |= ((p->rc_mb & 0x1) << 8);
> +       WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
> +       /** frame QP */
> +       reg &= ~(0x3F);
> +       reg |= p_h264->rc_frame_qp & 0x3F;
> +       WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
> +
> +       /* max & min value of QP */
> +       reg = 0;
> +       /** max QP */
> +       reg |= ((p_h264->rc_max_qp & 0x3F) << 8);
> +       /** min QP */
> +       reg |= p_h264->rc_min_qp & 0x3F;
> +       WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
> +
> +       /* other QPs */
> +       WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP);
> +       if (!p->rc_frame && !p->rc_mb) {
> +               reg = 0;
> +               reg |= ((p_h264->rc_b_frame_qp & 0x3F) << 16);
> +               reg |= ((p_h264->rc_p_frame_qp & 0x3F) << 8);
> +               reg |= p_h264->rc_frame_qp & 0x3F;
> +               WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
> +       }
> +
> +       /* frame rate */
> +       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
> +               reg = 0;
> +               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
> +               reg |= p->rc_framerate_denom & 0xFFFF;
> +               WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
> +       }
> +
> +       /* vbv buffer size */
> +       if (p->frame_skip_mode ==
> +                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> +               WRITEL(p_h264->cpb_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE);
> +
> +               if (p->rc_frame)
> +                       WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY);
> +       }
> +
> +       /* interlace */
> +       reg = 0;
> +       reg |= ((p_h264->interlace & 0x1) << 3);
> +       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +
> +       /* height */
> +       if (p_h264->interlace) {
> +               WRITEL(ctx->img_height >> 1,
> +                               S5P_FIMV_E_FRAME_HEIGHT); /* 32 align */
> +               /* cropped height */
> +               WRITEL(ctx->img_height >> 1, S5P_FIMV_E_CROPPED_FRAME_HEIGHT);
> +       }
> +
> +       /* loop filter ctrl */
> +       reg = READL(S5P_FIMV_E_H264_OPTIONS);
> +       reg &= ~(0x3 << 1);
> +       reg |= ((p_h264->loop_filter_mode & 0x3) << 1);
> +       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +
> +       /* loopfilter alpha offset */
> +       if (p_h264->loop_filter_alpha < 0) {
> +               reg = 0x10;
> +               reg |= (0xFF - p_h264->loop_filter_alpha) + 1;
> +       } else {
> +               reg = 0x00;
> +               reg |= (p_h264->loop_filter_alpha & 0xF);
> +       }
> +       WRITEL(reg, S5P_FIMV_E_H264_LF_ALPHA_OFFSET);
> +
> +       /* loopfilter beta offset */
> +       if (p_h264->loop_filter_beta < 0) {
> +               reg = 0x10;
> +               reg |= (0xFF - p_h264->loop_filter_beta) + 1;
> +       } else {
> +               reg = 0x00;
> +               reg |= (p_h264->loop_filter_beta & 0xF);
> +       }
> +       WRITEL(reg, S5P_FIMV_E_H264_LF_BETA_OFFSET);
> +
> +       /* entropy coding mode */
> +       reg = READL(S5P_FIMV_E_H264_OPTIONS);
> +       reg &= ~(0x1);
> +       reg |= p_h264->entropy_mode & 0x1;
> +       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +
> +       /* number of ref. picture */
> +       reg = READL(S5P_FIMV_E_H264_OPTIONS);
> +       reg &= ~(0x1 << 7);
> +       reg |= (((p_h264->num_ref_pic_4p - 1) & 0x1) << 7);
> +       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +
> +       /* 8x8 transform enable */
> +       reg = READL(S5P_FIMV_E_H264_OPTIONS);
> +       reg &= ~(0x3 << 12);
> +       reg |= ((p_h264->_8x8_transform & 0x3) << 12);
> +       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +
> +       /* macroblock adaptive scaling features */
> +       WRITEL(0x0, S5P_FIMV_E_MB_RC_CONFIG);
> +       if (p->rc_mb) {
> +               reg = 0;
> +               /** dark region */
> +               reg |= ((p_h264->rc_mb_dark & 0x1) << 3);
> +               /** smooth region */
> +               reg |= ((p_h264->rc_mb_smooth & 0x1) << 2);
> +               /** static region */
> +               reg |= ((p_h264->rc_mb_static & 0x1) << 1);
> +               /** high activity region */
> +               reg |= p_h264->rc_mb_activity & 0x1;
> +               WRITEL(reg, S5P_FIMV_E_MB_RC_CONFIG);
> +       }
> +
> +       /* aspect ratio VUI */
> +       reg = READL(S5P_FIMV_E_H264_OPTIONS);
> +       reg &= ~(0x1 << 5);
> +       reg |= ((p_h264->vui_sar & 0x1) << 5);
> +       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +
> +       WRITEL(0x0, S5P_FIMV_E_ASPECT_RATIO);
> +       WRITEL(0x0, S5P_FIMV_E_EXTENDED_SAR);
> +       if (p_h264->vui_sar) {
> +               /* aspect ration IDC */
> +               reg = 0;
> +               reg |= p_h264->vui_sar_idc & 0xFF;
> +               WRITEL(reg, S5P_FIMV_E_ASPECT_RATIO);
> +               if (p_h264->vui_sar_idc == 0xFF) {
> +                       /* extended SAR */
> +                       reg = 0;
> +                       reg |= (p_h264->vui_ext_sar_width & 0xFFFF) << 16;
> +                       reg |= p_h264->vui_ext_sar_height & 0xFFFF;
> +                       WRITEL(reg, S5P_FIMV_E_EXTENDED_SAR);
> +               }
> +       }
> +
> +       /* intra picture period for H.264 open GOP */
> +       /* control */
> +       reg = READL(S5P_FIMV_E_H264_OPTIONS);
> +       reg &= ~(0x1 << 4);
> +       reg |= ((p_h264->open_gop & 0x1) << 4);
> +       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +       /* value */
> +       WRITEL(0x0, S5P_FIMV_E_H264_I_PERIOD);
> +       if (p_h264->open_gop) {
> +               reg = 0;
> +               reg |= p_h264->open_gop_size & 0xFFFF;
> +               WRITEL(reg, S5P_FIMV_E_H264_I_PERIOD);
> +       }
> +
> +       /* 'WEIGHTED_BI_PREDICTION' for B is disable */
> +       reg = READL(S5P_FIMV_E_H264_OPTIONS);
> +       reg &= ~(0x3 << 9);
> +       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +
> +       /* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */
> +       reg = READL(S5P_FIMV_E_H264_OPTIONS);
> +       reg &= ~(0x1 << 14);
> +       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +
> +       /* ASO */
> +       reg = READL(S5P_FIMV_E_H264_OPTIONS);
> +       reg &= ~(0x1 << 6);
> +       reg |= ((p_h264->aso & 0x1) << 6);
> +       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +
> +       /* hier qp enable */
> +       reg = READL(S5P_FIMV_E_H264_OPTIONS);
> +       reg &= ~(0x1 << 8);
> +       reg |= ((p_h264->open_gop & 0x1) << 8);
> +       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +       reg = 0;
> +       if (p_h264->hier_qp && p_h264->hier_qp_layer) {
> +               reg |= (p_h264->hier_qp_type & 0x1) << 0x3;
> +               reg |= p_h264->hier_qp_layer & 0x7;
> +               WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER);
> +               /* QP value for each layer */
> +               for (i = 0; i < (p_h264->hier_qp_layer & 0x7); i++)
> +                       WRITEL(p_h264->hier_qp_layer_qp[i],
> +                               S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0 + i * 4);
> +       }
> +       /* number of coding layer should be zero when hierarchical is disable */
> +       WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER);
> +
> +       /* frame packing SEI generation */
> +       reg = READL(S5P_FIMV_E_H264_OPTIONS);
> +       reg &= ~(0x1 << 25);
> +       reg |= ((p_h264->sei_frame_packing & 0x1) << 25);
> +       WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
> +       if (p_h264->sei_frame_packing) {
> +               reg = 0;
> +               /** current frame0 flag */
> +               reg |= ((p_h264->sei_fp_curr_frame_0 & 0x1) << 2);
> +               /** arrangement type */
> +               reg |= p_h264->sei_fp_arrangement_type & 0x3;
> +               WRITEL(reg, S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO);
> +       }
> +
> +       if (p_h264->fmo) {
> +               switch (p_h264->fmo_map_type) {
> +               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES:
> +                       if (p_h264->fmo_slice_grp > 4)
> +                               p_h264->fmo_slice_grp = 4;
> +                       for (i = 0; i < (p_h264->fmo_slice_grp & 0xF); i++)
> +                               WRITEL(p_h264->fmo_run_len[i] - 1,
> +                               S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0 +
> +                               i * 4);
> +                       break;
> +               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES:
> +                       if (p_h264->fmo_slice_grp > 4)
> +                               p_h264->fmo_slice_grp = 4;
> +                       break;
> +               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN:
> +               case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN:
> +                       if (p_h264->fmo_slice_grp > 2)
> +                               p_h264->fmo_slice_grp = 2;
> +                       WRITEL(p_h264->fmo_chg_dir & 0x1,
> +                               S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR);
> +                       /* the valid range is 0 ~ number of macroblocks -1 */
> +                       WRITEL(p_h264->fmo_chg_rate,
> +                               S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1);
> +                       break;
> +               default:
> +                       mfc_err("Unsupported map type for FMO: %d\n",
> +                                       p_h264->fmo_map_type);
> +                       p_h264->fmo_map_type = 0;
> +                       p_h264->fmo_slice_grp = 1;
> +                       break;
> +               }
> +
> +               WRITEL(p_h264->fmo_map_type,
> +                               S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE);
> +               WRITEL(p_h264->fmo_slice_grp - 1,
> +                               S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1);
> +       } else {
> +               WRITEL(0, S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1);
> +       }
> +
> +       mfc_debug_leave();
> +
> +       return 0;
> +}
> +
> +static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       struct s5p_mfc_enc_params *p = &ctx->enc_params;
> +       struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
> +       unsigned int reg = 0;
> +
> +       mfc_debug_enter();
> +
> +       s5p_mfc_set_enc_params(ctx);
> +
> +       /* pictype : number of B */
> +       reg = READL(S5P_FIMV_E_GOP_CONFIG);
> +       reg &= ~(0x3 << 16);
> +       reg |= ((p->num_b_frame & 0x3) << 16);
> +       WRITEL(reg, S5P_FIMV_E_GOP_CONFIG);
> +
> +       /* profile & level */
> +       reg = 0;
> +       /** level */
> +       reg |= ((p_mpeg4->level & 0xFF) << 8);
> +       /** profile - 0 ~ 1 */
> +       reg |= p_mpeg4->profile & 0x3F;
> +       WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
> +
> +       /* rate control config. */
> +       reg = READL(S5P_FIMV_E_RC_CONFIG);
> +       /** macroblock level rate control */
> +       reg &= ~(0x1 << 8);
> +       reg |= ((p->rc_mb & 0x1) << 8);
> +       WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
> +       /** frame QP */
> +       reg &= ~(0x3F);
> +       reg |= p_mpeg4->rc_frame_qp & 0x3F;
> +       WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
> +
> +       /* max & min value of QP */
> +       reg = 0;
> +       /** max QP */
> +       reg |= ((p_mpeg4->rc_max_qp & 0x3F) << 8);
> +       /** min QP */
> +       reg |= p_mpeg4->rc_min_qp & 0x3F;
> +       WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
> +
> +       /* other QPs */
> +       WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP);
> +       if (!p->rc_frame && !p->rc_mb) {
> +               reg = 0;
> +               reg |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 16);
> +               reg |= ((p_mpeg4->rc_p_frame_qp & 0x3F) << 8);
> +               reg |= p_mpeg4->rc_frame_qp & 0x3F;
> +               WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
> +       }
> +
> +       /* frame rate */
> +       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
> +               reg = 0;
> +               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
> +               reg |= p->rc_framerate_denom & 0xFFFF;
> +               WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
> +       }
> +
> +       /* vbv buffer size */
> +       if (p->frame_skip_mode ==
> +                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> +               WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE);
> +
> +               if (p->rc_frame)
> +                       WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY);
> +       }
> +
> +       /* Disable HEC */
> +       WRITEL(0x0, S5P_FIMV_E_MPEG4_OPTIONS);
> +       WRITEL(0x0, S5P_FIMV_E_MPEG4_HEC_PERIOD);
> +
> +       mfc_debug_leave();
> +
> +       return 0;
> +}
> +
> +static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       struct s5p_mfc_enc_params *p = &ctx->enc_params;
> +       struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
> +       unsigned int reg = 0;
> +
> +       mfc_debug_enter();
> +
> +       s5p_mfc_set_enc_params(ctx);
> +
> +       /* profile & level */
> +       reg = 0;
> +       /** profile */
> +       reg |= (0x1 << 4);
> +       WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
> +
> +       /* rate control config. */
> +       reg = READL(S5P_FIMV_E_RC_CONFIG);
> +       /** macroblock level rate control */
> +       reg &= ~(0x1 << 8);
> +       reg |= ((p->rc_mb & 0x1) << 8);
> +       WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
> +       /** frame QP */
> +       reg &= ~(0x3F);
> +       reg |= p_h263->rc_frame_qp & 0x3F;
> +       WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
> +
> +       /* max & min value of QP */
> +       reg = 0;
> +       /** max QP */
> +       reg |= ((p_h263->rc_max_qp & 0x3F) << 8);
> +       /** min QP */
> +       reg |= p_h263->rc_min_qp & 0x3F;
> +       WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
> +
> +       /* other QPs */
> +       WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP);
> +       if (!p->rc_frame && !p->rc_mb) {
> +               reg = 0;
> +               reg |= ((p_h263->rc_b_frame_qp & 0x3F) << 16);
> +               reg |= ((p_h263->rc_p_frame_qp & 0x3F) << 8);
> +               reg |= p_h263->rc_frame_qp & 0x3F;
> +               WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
> +       }
> +
> +       /* frame rate */
> +       if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
> +               reg = 0;
> +               reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
> +               reg |= p->rc_framerate_denom & 0xFFFF;
> +               WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
> +       }
> +
> +       /* vbv buffer size */
> +       if (p->frame_skip_mode ==
> +                       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
> +               WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE);
> +
> +               if (p->rc_frame)
> +                       WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY);
> +       }
> +
> +       mfc_debug_leave();
> +
> +       return 0;
> +}
> +
> +/* Initialize decoding */
> +int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       unsigned int reg = 0;
> +       int fmo_aso_ctrl = 0;
> +
> +       mfc_debug_enter();
> +       mfc_debug(2, "InstNo: %d/%d\n", ctx->inst_no, S5P_FIMV_CH_SEQ_HEADER);
> +       mfc_debug(2, "BUFs: %08x %08x %08x\n",
> +                 READL(S5P_FIMV_D_CPB_BUFFER_ADDR),
> +                 READL(S5P_FIMV_D_CPB_BUFFER_ADDR),
> +                 READL(S5P_FIMV_D_CPB_BUFFER_ADDR));
> +
> +       /* FMO_ASO_CTRL - 0: Enable, 1: Disable */
> +       reg |= (fmo_aso_ctrl << S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK);
> +
> +       /* When user sets desplay_delay to 0,
> +        * It works as "display_delay enable" and delay set to 0.
> +        * If user wants display_delay disable, It should be
> +        * set to negative value. */
> +       if (ctx->display_delay >= 0) {
> +               reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT);
> +               WRITEL(ctx->display_delay, S5P_FIMV_D_DISPLAY_DELAY);
> +       }
> +       /* Setup loop filter, for decoding this is only valid for MPEG4 */
> +       if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_DEC) {
> +               mfc_debug(2, "Set loop filter to: %d\n",
> +                               ctx->loop_filter_mpeg4);
> +               reg |= (ctx->loop_filter_mpeg4 <<
> +                               S5P_FIMV_D_OPT_LF_CTRL_SHIFT);
> +       }
> +       if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)
> +               reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT);
> +
> +       WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS);
> +
> +       /* 0: NV12(CbCr), 1: NV21(CrCb) */
> +       if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M)
> +               WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT);
> +       else
> +               WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT);
> +
> +       /* sei parse */
> +       WRITEL(ctx->sei_fp_parse & 0x1, S5P_FIMV_D_SEI_ENABLE);
> +
> +       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
> +       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_SEQ_HEADER, NULL);
> +
> +       mfc_debug_leave();
> +       return 0;
> +}
> +
> +static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       unsigned int dpb;
> +       if (flush)
> +               dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (1 << 14);
> +       else
> +               dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & ~(1 << 14);
> +       WRITEL(dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
> +}
> +
> +/* Decode a single frame */
> +int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +
> +       WRITEL(0xffffffff, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER);
> +       WRITEL(0xffffffff, S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER);
> +       WRITEL(ctx->slice_interface & 0x1, S5P_FIMV_D_SLICE_IF_ENABLE);
> +
> +       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
> +       /* Issue different commands to instance basing on whether it
> +        * is the last frame or not. */
> +       switch (last_frame) {
> +       case 0:
> +               s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_FRAME_START, NULL);
> +               break;
> +       case 1:
> +               s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_LAST_FRAME, NULL);
> +               break;
> +       }
> +
> +       mfc_debug(2, "Decoding a usual frame.\n");
> +       return 0;
> +}
> +
> +int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +
> +       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
> +               s5p_mfc_set_enc_params_h264(ctx);
> +       else if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_ENC)
> +               s5p_mfc_set_enc_params_mpeg4(ctx);
> +       else if (ctx->codec_mode == S5P_FIMV_CODEC_H263_ENC)
> +               s5p_mfc_set_enc_params_h263(ctx);
> +       else {
> +               mfc_err("Unknown codec for encoding (%x).\n",
> +                       ctx->codec_mode);
> +               return -EINVAL;
> +       }
> +
> +       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
> +       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_SEQ_HEADER, NULL);
> +
> +       return 0;
> +}
> +
> +int s5p_mfc_h264_set_aso_slice_order(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       struct s5p_mfc_enc_params *p = &ctx->enc_params;
> +       struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
> +       int i;
> +
> +       if (p_h264->aso) {
> +               for (i = 0; i < 8; i++)
> +                       WRITEL(p_h264->aso_slice_order[i],
> +                               S5P_FIMV_E_H264_ASO_SLICE_ORDER_0 + i * 4);
> +       }
> +       return 0;
> +}
> +
> +/* Encode a single frame */
> +int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +
> +       mfc_debug(2, "++\n");
> +
> +       /* memory structure cur. frame */
> +
> +       if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
> +               s5p_mfc_h264_set_aso_slice_order(ctx);
> +
> +       s5p_mfc_set_slice_mode(ctx);
> +
> +       WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
> +       s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_FRAME_START, NULL);
> +
> +       mfc_debug(2, "--\n");
> +
> +       return 0;
> +}
> +
> +static inline int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
> +{
> +       unsigned long flags;
> +       int new_ctx;
> +       int cnt;
> +
> +       spin_lock_irqsave(&dev->condlock, flags);
> +       mfc_debug(2, "Previos context: %d (bits %08lx)\n", dev->curr_ctx,
> +                                                       dev->ctx_work_bits);
> +       new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
> +       cnt = 0;
> +       while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
> +               new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
> +               cnt++;
> +               if (cnt > MFC_NUM_CONTEXTS) {
> +                       /* No contexts to run */
> +                       spin_unlock_irqrestore(&dev->condlock, flags);
> +                       return -EAGAIN;
> +               }
> +       }
> +       spin_unlock_irqrestore(&dev->condlock, flags);
> +       return new_ctx;
> +}
> +
> +static inline void s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       struct s5p_mfc_buf *temp_vb;
> +       unsigned long flags;
> +
> +       spin_lock_irqsave(&dev->irqlock, flags);
> +
> +       /* Frames are being decoded */
> +       if (list_empty(&ctx->src_queue)) {
> +               mfc_debug(2, "No src buffers.\n");
> +               spin_unlock_irqrestore(&dev->irqlock, flags);
> +               return;
> +       }
> +       /* Get the next source buffer */
> +       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> +       temp_vb->used = 1;
> +       s5p_mfc_set_dec_stream_buffer(ctx,
> +                       vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0, 0);
> +       spin_unlock_irqrestore(&dev->irqlock, flags);
> +
> +       dev->curr_ctx = ctx->num;
> +       s5p_mfc_clean_ctx_int_flags(ctx);
> +       s5p_mfc_decode_one_frame(ctx, 1);
> +}
> +
> +static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       struct s5p_mfc_buf *temp_vb;
> +       unsigned long flags;
> +       int last_frame = 0;
> +       unsigned int index;
> +
> +       spin_lock_irqsave(&dev->irqlock, flags);
> +
> +       /* Frames are being decoded */
> +       if (list_empty(&ctx->src_queue)) {
> +               mfc_debug(2, "No src buffers.\n");
> +               spin_unlock_irqrestore(&dev->irqlock, flags);
> +               return -EAGAIN;
> +       }
> +       /* Get the next source buffer */
> +       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> +       temp_vb->used = 1;
> +       s5p_mfc_set_dec_stream_buffer(ctx,
> +               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0,
> +                       temp_vb->b->v4l2_planes[0].bytesused);
> +       spin_unlock_irqrestore(&dev->irqlock, flags);
> +
> +       index = temp_vb->b->v4l2_buf.index;
> +
> +       dev->curr_ctx = ctx->num;
> +       s5p_mfc_clean_ctx_int_flags(ctx);
> +       if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
> +               last_frame = 1;
> +               mfc_debug(2, "Setting ctx->state to FINISHING\n");
> +               ctx->state = MFCINST_FINISHING;
> +       }
> +       s5p_mfc_decode_one_frame(ctx, last_frame);
> +
> +       return 0;
> +}
> +
> +static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       unsigned long flags;
> +       struct s5p_mfc_buf *dst_mb;
> +       struct s5p_mfc_buf *src_mb;
> +       unsigned long src_y_addr, src_c_addr, dst_addr;
> +       /*
> +       unsigned int src_y_size, src_c_size;
> +       */
> +       unsigned int dst_size;
> +       unsigned int index;
> +
> +       spin_lock_irqsave(&dev->irqlock, flags);
> +
> +       if (list_empty(&ctx->src_queue)) {
> +               mfc_debug(2, "no src buffers.\n");
> +               spin_unlock_irqrestore(&dev->irqlock, flags);
> +               return -EAGAIN;
> +       }
> +
> +       if (list_empty(&ctx->dst_queue)) {
> +               mfc_debug(2, "no dst buffers.\n");
> +               spin_unlock_irqrestore(&dev->irqlock, flags);
> +               return -EAGAIN;
> +       }
> +
> +       src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> +       src_mb->used = 1;
> +       src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
> +       src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
> +
> +       mfc_debug(2, "enc src y addr: 0x%08lx", src_y_addr);
> +       mfc_debug(2, "enc src c addr: 0x%08lx", src_c_addr);
> +
> +       s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
> +
> +       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
> +       dst_mb->used = 1;
> +       dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
> +       dst_size = vb2_plane_size(dst_mb->b, 0);
> +
> +       s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
> +
> +       spin_unlock_irqrestore(&dev->irqlock, flags);
> +
> +       index = src_mb->b->v4l2_buf.index;
> +
> +       dev->curr_ctx = ctx->num;
> +       s5p_mfc_clean_ctx_int_flags(ctx);
> +       s5p_mfc_encode_one_frame(ctx);
> +
> +       return 0;
> +}
> +
> +static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       unsigned long flags;
> +       struct s5p_mfc_buf *temp_vb;
> +
> +       /* Initializing decoding - parsing header */
> +       spin_lock_irqsave(&dev->irqlock, flags);
> +       mfc_debug(2, "Preparing to init decoding.\n");
> +       temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
> +       mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
> +       s5p_mfc_set_dec_stream_buffer(ctx,
> +               vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0,
> +                       temp_vb->b->v4l2_planes[0].bytesused);
> +       spin_unlock_irqrestore(&dev->irqlock, flags);
> +       dev->curr_ctx = ctx->num;
> +       s5p_mfc_clean_ctx_int_flags(ctx);
> +       s5p_mfc_init_decode(ctx);
> +}
> +
> +static inline void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       unsigned long flags;
> +       struct s5p_mfc_buf *dst_mb;
> +       unsigned long dst_addr;
> +       unsigned int dst_size;
> +
> +       spin_lock_irqsave(&dev->irqlock, flags);
> +
> +       dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
> +       dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
> +       dst_size = vb2_plane_size(dst_mb->b, 0);
> +       s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
> +       spin_unlock_irqrestore(&dev->irqlock, flags);
> +       dev->curr_ctx = ctx->num;
> +       s5p_mfc_clean_ctx_int_flags(ctx);
> +       s5p_mfc_init_encode(ctx);
> +}
> +
> +static inline int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       int ret;
> +       /* Header was parsed now start processing
> +        * First set the output frame buffers
> +        * s5p_mfc_alloc_dec_buffers(ctx); */
> +
> +       if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
> +               mfc_err("It seems that not all destionation buffers were\n"
> +                       "mmaped.MFC requires that all destination are mmaped\n"
> +                       "before starting processing.\n");
> +               return -EAGAIN;
> +       }
> +
> +       dev->curr_ctx = ctx->num;
> +       s5p_mfc_clean_ctx_int_flags(ctx);
> +       ret = s5p_mfc_set_dec_frame_buffer(ctx);
> +       if (ret) {
> +               mfc_err("Failed to alloc frame mem.\n");
> +               ctx->state = MFCINST_ERROR;
> +       }
> +       return ret;
> +}
> +
> +static inline int s5p_mfc_run_init_enc_buffers(struct s5p_mfc_ctx *ctx)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       int ret;
> +
> +       ret = s5p_mfc_alloc_codec_buffers(ctx);
> +       if (ret) {
> +               mfc_err("Failed to allocate encoding buffers.\n");
> +               return -ENOMEM;
> +       }
> +
> +       /* Header was generated now starting processing
> +        * First set the reference frame buffers
> +        */
> +       if (ctx->capture_state != QUEUE_BUFS_REQUESTED) {
> +               mfc_err("It seems that destionation buffers were not\n"
> +                       "requested.MFC requires that header should be generated\n"
> +                       "before allocating codec buffer.\n");
> +               return -EAGAIN;
> +       }
> +
> +       dev->curr_ctx = ctx->num;
> +       s5p_mfc_clean_ctx_int_flags(ctx);
> +       ret = s5p_mfc_set_enc_ref_buffer(ctx);
> +       if (ret) {
> +               mfc_err("Failed to alloc frame mem.\n");
> +               ctx->state = MFCINST_ERROR;
> +       }
> +       return ret;
> +}
> +
> +/* Try running an operation on hardware */
> +void s5p_mfc_try_run(struct s5p_mfc_dev *dev)
> +{
> +       struct s5p_mfc_ctx *ctx;
> +       int new_ctx;
> +       unsigned int ret = 0;
> +
> +       mfc_debug(1, "Try run dev: %p\n", dev);
> +
> +       /* Check whether hardware is not running */
> +       if (test_and_set_bit(0, &dev->hw_lock) != 0) {
> +               /* This is perfectly ok, the scheduled ctx should wait */
> +               mfc_debug(1, "Couldn't lock HW.\n");
> +               return;
> +       }
> +
> +       /* Choose the context to run */
> +       new_ctx = s5p_mfc_get_new_ctx(dev);
> +       if (new_ctx < 0) {
> +               /* No contexts to run */
> +               if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
> +                       mfc_err("Failed to unlock hardware.\n");
> +                       return;
> +               }
> +
> +               mfc_debug(1, "No ctx is scheduled to be run.\n");
> +               return;
> +       }
> +
> +       mfc_debug(1, "New context: %d\n", new_ctx);
> +       ctx = dev->ctx[new_ctx];
> +       mfc_debug(1, "Seting new context to %p\n", ctx);
> +       /* Got context to run in ctx */
> +       mfc_debug(1, "ctx->dst_queue_cnt=%d ctx->dpb_count=%d ctx->src_queue_cnt=%d\n",
> +               ctx->dst_queue_cnt, ctx->dpb_count, ctx->src_queue_cnt);
> +       mfc_debug(1, "ctx->state=%d\n", ctx->state);
> +       /* Last frame has already been sent to MFC
> +        * Now obtaining frames from MFC buffer */
> +
> +       s5p_mfc_clock_on();
> +       if (ctx->type == MFCINST_DECODER) {
> +               switch (ctx->state) {
> +               case MFCINST_FINISHING:
> +                       s5p_mfc_run_dec_last_frames(ctx);
> +                       break;
> +               case MFCINST_RUNNING:
> +                       ret = s5p_mfc_run_dec_frame(ctx);
> +                       break;
> +               case MFCINST_INIT:
> +                       s5p_mfc_clean_ctx_int_flags(ctx);
> +                       ret = s5p_mfc_open_inst_cmd(ctx);
> +                       break;
> +               case MFCINST_RETURN_INST:
> +                       s5p_mfc_clean_ctx_int_flags(ctx);
> +                       ret = s5p_mfc_close_inst_cmd(ctx);
> +                       break;
> +               case MFCINST_GOT_INST:
> +                       s5p_mfc_run_init_dec(ctx);
> +                       break;
> +               case MFCINST_HEAD_PARSED:
> +                       ret = s5p_mfc_run_init_dec_buffers(ctx);
> +                       break;
> +               case MFCINST_RES_CHANGE_INIT:
> +                       s5p_mfc_run_dec_last_frames(ctx);
> +                       break;
> +               case MFCINST_RES_CHANGE_FLUSH:
> +                       s5p_mfc_run_dec_last_frames(ctx);
> +                       break;
> +               case MFCINST_RES_CHANGE_END:
> +                       mfc_debug(2, "Finished remaining frames after resolution change.\n");
> +                       ctx->capture_state = QUEUE_FREE;
> +                       mfc_debug(2, "Will re-init the codec`.\n");
> +                       s5p_mfc_run_init_dec(ctx);
> +                       break;
> +               default:
> +                       ret = -EAGAIN;
> +               }
> +       } else if (ctx->type == MFCINST_ENCODER) {
> +               switch (ctx->state) {
> +               case MFCINST_FINISHING:
> +               case MFCINST_RUNNING:
> +                       ret = s5p_mfc_run_enc_frame(ctx);
> +                       break;
> +               case MFCINST_INIT:
> +                       ret = s5p_mfc_open_inst_cmd(ctx);
> +                       break;
> +               case MFCINST_RETURN_INST:
> +                       ret = s5p_mfc_close_inst_cmd(ctx);
> +                       break;
> +               case MFCINST_GOT_INST:
> +                       s5p_mfc_run_init_enc(ctx);
> +                       break;
> +               case MFCINST_HEAD_PARSED: /* Only for MFC6.x */
> +                       ret = s5p_mfc_run_init_enc_buffers(ctx);
> +                       break;
> +               default:
> +                       ret = -EAGAIN;
> +               }
> +       } else {
> +               mfc_err("invalid context type: %d\n", ctx->type);
> +               ret = -EAGAIN;
> +       }
> +
> +       if (ret) {
> +               /* Free hardware lock */
> +               if (test_and_clear_bit(0, &dev->hw_lock) == 0)
> +                       mfc_err("Failed to unlock hardware.\n");
> +
> +               /* This is in deed imporant, as no operation has been
> +                * scheduled, reduce the clock count as no one will
> +                * ever do this, because no interrupt related to this try_run
> +                * will ever come from hardware. */
> +               s5p_mfc_clock_off();
> +       }
> +}
> +
> +
> +void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq)
> +{
> +       struct s5p_mfc_buf *b;
> +       int i;
> +
> +       while (!list_empty(lh)) {
> +               b = list_entry(lh->next, struct s5p_mfc_buf, list);
> +               for (i = 0; i < b->b->num_planes; i++)
> +                       vb2_set_plane_payload(b->b, i, 0);
> +               vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
> +               list_del(&b->list);
> +       }
> +}
> +
> +void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
> +{
> +       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
> +       mfc_write(dev, 0, S5P_FIMV_RISC2HOST_INT);
> +}
> +
> +void s5p_mfc_write_info(struct s5p_mfc_ctx *ctx, unsigned int data,
> +               unsigned int ofs)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +
> +       s5p_mfc_clock_on();
> +       WRITEL(data, ofs);
> +       s5p_mfc_clock_off();
> +}
> +
> +unsigned int s5p_mfc_read_info(struct s5p_mfc_ctx *ctx, unsigned int ofs)
> +{
> +       struct s5p_mfc_dev *dev = ctx->dev;
> +       int ret;
> +
> +       s5p_mfc_clock_on();
> +       ret = READL(ofs);
> +       s5p_mfc_clock_off();
> +
> +       return ret;
> +}
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h b/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h
> new file mode 100644
> index 0000000..93ce2d8
> --- /dev/null
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h
> @@ -0,0 +1,140 @@
> +/*
> + * drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h
> + *
> + * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
> + * Contains declarations of hw related functions.
> + *
> + * Copyright (c) 2012 Samsung Electronics
> + *             http://www.samsung.com/
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef S5P_MFC_OPR_V6_H_
> +#define S5P_MFC_OPR_V6_H_
> +
> +#include "s5p_mfc_common.h"
> +
> +#define MFC_CTRL_MODE_CUSTOM   MFC_CTRL_MODE_SFR
> +
> +int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx);
> +int s5p_mfc_init_encode(struct s5p_mfc_ctx *mfc_ctx);
> +
> +int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx);
> +int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
> +                                                 unsigned int start_num_byte,
> +                                                 unsigned int buf_size);
> +
> +void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
> +               unsigned long y_addr, unsigned long c_addr);
> +int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
> +               unsigned long addr, unsigned int size);
> +void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
> +               unsigned long *y_addr, unsigned long *c_addr);
> +int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *mfc_ctx);
> +
> +int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame);
> +int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *mfc_ctx);
> +
> +/* Memory allocation */
> +int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
> +
> +int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx);
> +
> +int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx);
> +int s5p_mfc_alloc_dev_context_buffer(struct s5p_mfc_dev *dev);
> +void s5p_mfc_release_dev_context_buffer(struct s5p_mfc_dev *dev);
> +
> +void s5p_mfc_dec_calc_dpb_size(struct s5p_mfc_ctx *ctx);
> +void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx);
> +
> +#define s5p_mfc_get_dspl_y_adr()       (readl(dev->regs_base + \
> +                                       S5P_FIMV_SI_DISPLAY_Y_ADR))
> +#define s5p_mfc_get_dec_y_adr()                (readl(dev->regs_base + \
> +                                       S5P_FIMV_D_DISPLAY_LUMA_ADDR))
> +#define s5p_mfc_get_dspl_status()      readl(dev->regs_base + \
> +                                               S5P_FIMV_D_DISPLAY_STATUS)
> +#define s5p_mfc_get_decoded_status()   readl(dev->regs_base + \
> +                                               S5P_FIMV_D_DECODED_STATUS)
> +#define s5p_mfc_get_dec_frame_type()   (readl(dev->regs_base + \
> +                                               S5P_FIMV_D_DECODED_FRAME_TYPE) \
> +                                               & S5P_FIMV_DECODE_FRAME_MASK)
> +#define s5p_mfc_get_disp_frame_type()  (readl(ctx->dev->regs_base + \
> +                                               S5P_FIMV_D_DISPLAY_FRAME_TYPE) \
> +                                               & S5P_FIMV_DECODE_FRAME_MASK)
> +#define s5p_mfc_get_consumed_stream()  readl(dev->regs_base + \
> +                                               S5P_FIMV_D_DECODED_NAL_SIZE)
> +#define s5p_mfc_get_int_reason()       (readl(dev->regs_base + \
> +                                       S5P_FIMV_RISC2HOST_CMD) & \
> +                                       S5P_FIMV_RISC2HOST_CMD_MASK)
> +#define s5p_mfc_get_int_err()          readl(dev->regs_base + \
> +                                               S5P_FIMV_ERROR_CODE)
> +#define s5p_mfc_err_dec(x)             (((x) & S5P_FIMV_ERR_DEC_MASK) >> \
> +                                               S5P_FIMV_ERR_DEC_SHIFT)
> +#define s5p_mfc_err_dspl(x)            (((x) & S5P_FIMV_ERR_DSPL_MASK) >> \
> +                                               S5P_FIMV_ERR_DSPL_SHIFT)
> +#define s5p_mfc_get_img_width()                readl(dev->regs_base + \
> +                                               S5P_FIMV_D_DISPLAY_FRAME_WIDTH)
> +#define s5p_mfc_get_img_height()       readl(dev->regs_base + \
> +                                               S5P_FIMV_D_DISPLAY_FRAME_HEIGHT)
> +#define s5p_mfc_get_dpb_count()                readl(dev->regs_base + \
> +                                               S5P_FIMV_D_MIN_NUM_DPB)
> +#define s5p_mfc_get_inst_no()          readl(dev->regs_base + \
> +                                               S5P_FIMV_RET_INSTANCE_ID)
> +#define s5p_mfc_get_enc_dpb_count()    readl(dev->regs_base + \
> +                                               S5P_FIMV_E_NUM_DPB)
> +#define s5p_mfc_get_enc_strm_size()    readl(dev->regs_base + \
> +                                               S5P_FIMV_E_STREAM_SIZE)
> +#define s5p_mfc_get_enc_slice_type()   readl(dev->regs_base + \
> +                                               S5P_FIMV_E_SLICE_TYPE)
> +#define s5p_mfc_get_enc_pic_count()    readl(dev->regs_base + \
> +                                               S5P_FIMV_E_PICTURE_COUNT)
> +#define s5p_mfc_get_sei_avail_status() readl(dev->regs_base + \
> +                                               S5P_FIMV_D_FRAME_PACK_SEI_AVAIL)
> +#define s5p_mfc_get_mvc_num_views()    readl(dev->regs_base + \
> +                                               S5P_FIMV_D_MVC_NUM_VIEWS)
> +#define s5p_mfc_get_mvc_view_id()      readl(dev->regs_base + \
> +                                               S5P_FIMV_D_MVC_VIEW_ID)
> +
> +#define mb_width(x_size)               ((x_size + 15) / 16)
> +#define mb_height(y_size)              ((y_size + 15) / 16)
> +#define s5p_mfc_dec_mv_size(x, y)      (mb_width(x) * \
> +                                       (((mb_height(y)+1)/2)*2) * 64 + 128)
> +
> +/* Definition */
> +#define ENC_MULTI_SLICE_MB_MAX         ((1 << 30) - 1)
> +#define ENC_MULTI_SLICE_BIT_MIN                2800
> +#define ENC_INTRA_REFRESH_MB_MAX       ((1 << 18) - 1)
> +#define ENC_VBV_BUF_SIZE_MAX           ((1 << 30) - 1)
> +#define ENC_H264_LOOP_FILTER_AB_MIN    -12
> +#define ENC_H264_LOOP_FILTER_AB_MAX    12
> +#define ENC_H264_RC_FRAME_RATE_MAX     ((1 << 16) - 1)
> +#define ENC_H263_RC_FRAME_RATE_MAX     ((1 << 16) - 1)
> +#define ENC_H264_PROFILE_MAX           3
> +#define ENC_H264_LEVEL_MAX             42
> +#define ENC_MPEG4_VOP_TIME_RES_MAX     ((1 << 16) - 1)
> +#define FRAME_DELTA_H264_H263          1
> +#define TIGHT_CBR_MAX                  10
> +
> +/* Definitions for shared memory compatibility */
> +#define PIC_TIME_TOP           S5P_FIMV_D_RET_PICTURE_TAG_TOP
> +#define PIC_TIME_BOT           S5P_FIMV_D_RET_PICTURE_TAG_BOT
> +#define CROP_INFO_H            S5P_FIMV_D_DISPLAY_CROP_INFO1
> +#define CROP_INFO_V            S5P_FIMV_D_DISPLAY_CROP_INFO2
> +
> +void s5p_mfc_try_run(struct s5p_mfc_dev *dev);
> +
> +void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
> +void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev);
> +
> +void s5p_mfc_write_info(struct s5p_mfc_ctx *ctx, unsigned int data,
> +               unsigned int ofs);
> +unsigned int s5p_mfc_read_info(struct s5p_mfc_ctx *ctx, unsigned int ofs);
> +
> +#endif /* S5P_MFC_OPR_V6_H_ */
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_pm.c b/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
> index 738a607..4fa0b54 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
> @@ -20,7 +20,11 @@
>  #include "s5p_mfc_debug.h"
>  #include "s5p_mfc_pm.h"
>
> -#define MFC_CLKNAME            "sclk_mfc"
> +#if defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V5)
> +#define MFC_CLKNAME            "sclk_mfc"
> +#elif defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V6)
> +#define MFC_CLKNAME            "aclk_333"
I think it can handle clkname without new config.

Thank you,
Kyungmin Park
> +#endif
>  #define MFC_GATE_CLK_NAME      "mfc"
>
>  #define CLK_DEBUG
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_shm.c b/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
> index 91fdbac..9ee269d 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
> @@ -21,26 +21,28 @@ int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx)
>  {
>         struct s5p_mfc_dev *dev = ctx->dev;
>         void *shm_alloc_ctx = dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
> +       struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
>
> -       ctx->shm_alloc = vb2_dma_contig_memops.alloc(shm_alloc_ctx,
> -                                                       SHARED_BUF_SIZE);
> -       if (IS_ERR(ctx->shm_alloc)) {
> +       ctx->shm.alloc = vb2_dma_contig_memops.alloc(shm_alloc_ctx,
> +                                                       buf_size->shm);
> +       if (IS_ERR(ctx->shm.alloc)) {
>                 mfc_err("failed to allocate shared memory\n");
> -               return PTR_ERR(ctx->shm_alloc);
> +               return PTR_ERR(ctx->shm.alloc);
>         }
> -       /* shm_ofs only keeps the offset from base (port a) */
> -       ctx->shm_ofs = s5p_mfc_mem_cookie(shm_alloc_ctx, ctx->shm_alloc)
> +       /* shared memory offset only keeps the offset from base (port a) */
> +       ctx->shm.ofs = s5p_mfc_mem_cookie(shm_alloc_ctx, ctx->shm.alloc)
>                                                                 - dev->bank1;
> -       BUG_ON(ctx->shm_ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> -       ctx->shm = vb2_dma_contig_memops.vaddr(ctx->shm_alloc);
> -       if (!ctx->shm) {
> -               vb2_dma_contig_memops.put(ctx->shm_alloc);
> -               ctx->shm_ofs = 0;
> -               ctx->shm_alloc = NULL;
> +       BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
> +
> +       ctx->shm.virt = vb2_dma_contig_memops.vaddr(ctx->shm.alloc);
> +       if (!ctx->shm.virt) {
> +               vb2_dma_contig_memops.put(ctx->shm.alloc);
> +               ctx->shm.alloc = NULL;
> +               ctx->shm.ofs = 0;
>                 mfc_err("failed to virt addr of shared memory\n");
>                 return -ENOMEM;
>         }
> -       memset((void *)ctx->shm, 0, SHARED_BUF_SIZE);
> +       memset((void *)ctx->shm.virt, 0, buf_size->shm);
>         wmb();
>         return 0;
>  }
> diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_shm.h b/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
> index cf962a4..8400ab0 100644
> --- a/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
> +++ b/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
> @@ -71,20 +71,23 @@ enum MFC_SHM_OFS {
>         DBG_HISTORY_INPUT1      = 0xD4, /* C */
>         DBG_HISTORY_OUTPUT      = 0xD8, /* C */
>         HIERARCHICAL_P_QP       = 0xE0, /* E, H.264 */
> +       FRAME_PACK_SEI_ENABLE   = 0x168, /* C */
> +       FRAME_PACK_SEI_AVAIL    = 0x16c, /* D */
> +       FRAME_PACK_SEI_INFO     = 0x17c, /* E */
>  };
>
>  int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx);
>
> -#define s5p_mfc_write_shm(ctx, x, ofs)         \
> -       do {                                    \
> -               writel(x, (ctx->shm + ofs));    \
> -               wmb();                          \
> +#define s5p_mfc_write_shm(ctx, x, ofs)                 \
> +       do {                                            \
> +               writel(x, (ctx->shm.virt + ofs));       \
> +               wmb();                                  \
>         } while (0)
>
>  static inline u32 s5p_mfc_read_shm(struct s5p_mfc_ctx *ctx, unsigned int ofs)
>  {
>         rmb();
> -       return readl(ctx->shm + ofs);
> +       return readl(ctx->shm.virt + ofs);
>  }
>
>  #endif /* S5P_MFC_SHM_H_ */
> diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
> index 9abd9ab..61d6583 100644
> --- a/drivers/media/video/v4l2-ctrls.c
> +++ b/drivers/media/video/v4l2-ctrls.c
> @@ -502,7 +502,6 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
>                 return mpeg4_profile;
>         case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
>                 return jpeg_chroma_subsampling;
> -
>         default:
>                 return NULL;
>         }
> --
> 1.7.0.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 2/2] [media] s5p-mfc: update MFC v4l2 driver to support MFC6.x
  2012-07-06 14:00 [PATCH v2 0/2] " Arun Kumar K
@ 2012-07-06 14:00 ` Arun Kumar K
  2012-07-06 14:21   ` Kyungmin Park
  2012-07-10 15:10   ` Kamil Debski
  0 siblings, 2 replies; 5+ messages in thread
From: Arun Kumar K @ 2012-07-06 14:00 UTC (permalink / raw)
  To: linux-media
  Cc: jtp.park, janghyuck.kim, jaeryul.oh, ch.naveen, arun.kk,
	m.szyprowski, k.debski, s.nawrocki, hans.verkuil, mchehab

From: Jeongtae Park <jtp.park@samsung.com>

Multi Format Codec 6.x is a hardware video coding acceleration
module fount in new Exynos5 SoC series.
It is capable of handling a range of video codecs and this driver
provides a V4L2 interface for video decoding and encoding.

Signed-off-by: Jeongtae Park <jtp.park@samsung.com>
Singed-off-by: Janghyuck Kim <janghyuck.kim@samsung.com>
Singed-off-by: Jaeryul Oh <jaeryul.oh@samsung.com>
Signed-off-by: Naveen Krishna Chatradhi <ch.naveen@samsung.com>
Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: Kamil Debski <k.debski@samsung.com>
---
 drivers/media/video/Kconfig                  |   16 +-
 drivers/media/video/s5p-mfc/Makefile         |    7 +-
 drivers/media/video/s5p-mfc/regs-mfc-v6.h    |  676 ++++++++++
 drivers/media/video/s5p-mfc/regs-mfc.h       |   29 +
 drivers/media/video/s5p-mfc/s5p_mfc.c        |  163 ++-
 drivers/media/video/s5p-mfc/s5p_mfc_cmd.c    |    6 +-
 drivers/media/video/s5p-mfc/s5p_mfc_cmd.h    |    3 +
 drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c |   96 ++
 drivers/media/video/s5p-mfc/s5p_mfc_common.h |  123 ++-
 drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c   |  160 ++-
 drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h   |    1 +
 drivers/media/video/s5p-mfc/s5p_mfc_dec.c    |  210 +++-
 drivers/media/video/s5p-mfc/s5p_mfc_dec.h    |    1 +
 drivers/media/video/s5p-mfc/s5p_mfc_enc.c    |  191 ++--
 drivers/media/video/s5p-mfc/s5p_mfc_enc.h    |    1 +
 drivers/media/video/s5p-mfc/s5p_mfc_intr.c   |    1 -
 drivers/media/video/s5p-mfc/s5p_mfc_opr.c    |  278 +++--
 drivers/media/video/s5p-mfc/s5p_mfc_opr.h    |   25 +-
 drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c | 1697 ++++++++++++++++++++++++++
 drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h |  140 +++
 drivers/media/video/s5p-mfc/s5p_mfc_pm.c     |    6 +-
 drivers/media/video/s5p-mfc/s5p_mfc_shm.c    |   28 +-
 drivers/media/video/s5p-mfc/s5p_mfc_shm.h    |   13 +-
 drivers/media/video/v4l2-ctrls.c             |    1 -
 24 files changed, 3476 insertions(+), 396 deletions(-)
 create mode 100644 drivers/media/video/s5p-mfc/regs-mfc-v6.h
 create mode 100644 drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c
 create mode 100644 drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c
 create mode 100644 drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h

diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index 99937c9..0d7fe77 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -1198,13 +1198,27 @@ config VIDEO_SAMSUNG_S5P_JPEG
 	  This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec
 
 config VIDEO_SAMSUNG_S5P_MFC
+	bool
+
+config VIDEO_SAMSUNG_S5P_MFC_V5
 	tristate "Samsung S5P MFC 5.1 Video Codec"
-	depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
+	depends on VIDEO_DEV && VIDEO_V4L2 && ARCH_EXYNOS4
+	select VIDEO_SAMSUNG_S5P_MFC
 	select VIDEOBUF2_DMA_CONTIG
 	default n
 	help
 	    MFC 5.1 driver for V4L2.
 
+config VIDEO_SAMSUNG_S5P_MFC_V6
+	tristate "Samsung S5P MFC 6.x Video Codec"
+	depends on VIDEO_DEV && VIDEO_V4L2 && ARCH_EXYNOS5
+	select VIDEO_SAMSUNG_S5P_MFC
+	select VIDEOBUF2_DMA_CONTIG
+	select DMA_SHARED_BUFFER
+	default n
+	help
+	    MFC 6.x driver for V4L2.
+
 config VIDEO_MX2_EMMAPRP
 	tristate "MX2 eMMa-PrP support"
 	depends on VIDEO_DEV && VIDEO_V4L2 && SOC_IMX27
diff --git a/drivers/media/video/s5p-mfc/Makefile b/drivers/media/video/s5p-mfc/Makefile
index d066340..0308d74 100644
--- a/drivers/media/video/s5p-mfc/Makefile
+++ b/drivers/media/video/s5p-mfc/Makefile
@@ -1,5 +1,6 @@
 obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) := s5p-mfc.o
-s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o s5p_mfc_opr.o
+s5p-mfc-y += s5p_mfc.o s5p_mfc_intr.o
 s5p-mfc-y += s5p_mfc_dec.o s5p_mfc_enc.o
-s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_cmd.o
-s5p-mfc-y += s5p_mfc_pm.o s5p_mfc_shm.o
+s5p-mfc-y += s5p_mfc_ctrl.o s5p_mfc_pm.o
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V5) += s5p_mfc_opr.o s5p_mfc_cmd.o s5p_mfc_shm.o
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V6) += s5p_mfc_opr_v6.o s5p_mfc_cmd_v6.o
diff --git a/drivers/media/video/s5p-mfc/regs-mfc-v6.h b/drivers/media/video/s5p-mfc/regs-mfc-v6.h
new file mode 100644
index 0000000..f22a159
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/regs-mfc-v6.h
@@ -0,0 +1,676 @@
+/*
+ * Register definition file for Samsung MFC V6.x Interface (FIMV) driver
+ *
+ * Copyright (c) 2012 Samsung Electronics
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _REGS_FIMV_V6_H
+#define _REGS_FIMV_V6_H
+
+#define S5P_FIMV_REG_SIZE	(S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR)
+#define S5P_FIMV_REG_COUNT	((S5P_FIMV_END_ADDR - S5P_FIMV_START_ADDR) / 4)
+
+/* Number of bits that the buffer address should be shifted for particular
+ * MFC buffers.  */
+#define S5P_FIMV_MEM_OFFSET		0
+
+#define S5P_FIMV_START_ADDR		0x0000
+#define S5P_FIMV_END_ADDR		0xfd80
+
+#define S5P_FIMV_REG_CLEAR_BEGIN	0xf000
+#define S5P_FIMV_REG_CLEAR_COUNT	1024
+
+/* Codec Common Registers */
+#define S5P_FIMV_RISC_ON			0x0000
+#define S5P_FIMV_RISC2HOST_INT			0x003C
+#define S5P_FIMV_HOST2RISC_INT			0x0044
+#define S5P_FIMV_RISC_BASE_ADDRESS		0x0054
+
+#define S5P_FIMV_MFC_RESET			0x1070
+
+#define S5P_FIMV_HOST2RISC_CMD			0x1100
+#define S5P_FIMV_H2R_CMD_EMPTY			0
+#define S5P_FIMV_H2R_CMD_SYS_INIT		1
+#define S5P_FIMV_H2R_CMD_OPEN_INSTANCE		2
+#define S5P_FIMV_CH_SEQ_HEADER			3
+#define S5P_FIMV_CH_INIT_BUFS			4
+#define S5P_FIMV_CH_FRAME_START			5
+#define S5P_FIMV_H2R_CMD_CLOSE_INSTANCE		6
+#define S5P_FIMV_H2R_CMD_SLEEP			7
+#define S5P_FIMV_H2R_CMD_WAKEUP			8
+#define S5P_FIMV_CH_LAST_FRAME			9
+#define S5P_FIMV_H2R_CMD_FLUSH			10
+/* RMVME: REALLOC used? */
+#define S5P_FIMV_CH_FRAME_START_REALLOC		5
+
+#define S5P_FIMV_RISC2HOST_CMD			0x1104
+#define S5P_FIMV_R2H_CMD_EMPTY			0
+#define S5P_FIMV_R2H_CMD_SYS_INIT_RET		1
+#define S5P_FIMV_R2H_CMD_OPEN_INSTANCE_RET	2
+#define S5P_FIMV_R2H_CMD_SEQ_DONE_RET		3
+#define S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET	4
+
+#define S5P_FIMV_R2H_CMD_CLOSE_INSTANCE_RET	6
+#define S5P_FIMV_R2H_CMD_SLEEP_RET		7
+#define S5P_FIMV_R2H_CMD_WAKEUP_RET		8
+#define S5P_FIMV_R2H_CMD_COMPLETE_SEQ_RET	9
+#define S5P_FIMV_R2H_CMD_DPB_FLUSH_RET		10
+#define S5P_FIMV_R2H_CMD_NAL_ABORT_RET		11
+#define S5P_FIMV_R2H_CMD_FW_STATUS_RET		12
+#define S5P_FIMV_R2H_CMD_FRAME_DONE_RET		13
+#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET		14
+#define S5P_FIMV_R2H_CMD_SLICE_DONE_RET		15
+#define S5P_FIMV_R2H_CMD_ENC_BUFFER_FUL_RET	16
+#define S5P_FIMV_R2H_CMD_ERR_RET		32
+
+#define S5P_FIMV_FW_VERSION			0xF000
+
+#define S5P_FIMV_INSTANCE_ID			0xF008
+#define S5P_FIMV_CODEC_TYPE			0xF00C
+#define S5P_FIMV_CONTEXT_MEM_ADDR		0xF014
+#define S5P_FIMV_CONTEXT_MEM_SIZE		0xF018
+#define S5P_FIMV_PIXEL_FORMAT			0xF020
+
+#define S5P_FIMV_METADATA_ENABLE		0xF024
+#define S5P_FIMV_DBG_BUFFER_ADDR		0xF030
+#define S5P_FIMV_DBG_BUFFER_SIZE		0xF034
+#define S5P_FIMV_RET_INSTANCE_ID		0xF070
+
+#define S5P_FIMV_ERROR_CODE			0xF074
+#define S5P_FIMV_ERR_WARNINGS_START		160
+#define S5P_FIMV_ERR_DEC_MASK			0xFFFF
+#define S5P_FIMV_ERR_DEC_SHIFT			0
+#define S5P_FIMV_ERR_DSPL_MASK			0xFFFF0000
+#define S5P_FIMV_ERR_DSPL_SHIFT			16
+
+#define S5P_FIMV_DBG_BUFFER_OUTPUT_SIZE		0xF078
+#define S5P_FIMV_METADATA_STATUS		0xF07C
+#define S5P_FIMV_METADATA_ADDR_MB_INFO		0xF080
+#define S5P_FIMV_METADATA_SIZE_MB_INFO		0xF084
+
+/* Decoder Registers */
+#define S5P_FIMV_D_CRC_CTRL			0xF0B0
+#define S5P_FIMV_D_DEC_OPTIONS			0xF0B4
+#define S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK	4
+#define S5P_FIMV_D_OPT_DDELAY_EN_SHIFT		3
+#define S5P_FIMV_D_OPT_LF_CTRL_SHIFT		1
+#define S5P_FIMV_D_OPT_LF_CTRL_MASK		0x3
+#define S5P_FIMV_D_OPT_TILE_MODE_SHIFT		0
+
+#define S5P_FIMV_D_DISPLAY_DELAY		0xF0B8
+
+#define S5P_FIMV_D_SET_FRAME_WIDTH		0xF0BC
+#define S5P_FIMV_D_SET_FRAME_HEIGHT		0xF0C0
+
+#define S5P_FIMV_D_SEI_ENABLE			0xF0C4
+
+/* Buffer setting registers */
+#define S5P_FIMV_D_MIN_NUM_DPB			0xF0F0
+#define S5P_FIMV_D_MIN_LUMA_DPB_SIZE		0xF0F4
+#define S5P_FIMV_D_MIN_CHROMA_DPB_SIZE		0xF0F8
+#define S5P_FIMV_D_MVC_NUM_VIEWS		0xF0FC
+#define S5P_FIMV_D_NUM_DPB			0xF130
+#define S5P_FIMV_D_LUMA_DPB_SIZE		0xF134
+#define S5P_FIMV_D_CHROMA_DPB_SIZE		0xF138
+#define S5P_FIMV_D_MV_BUFFER_SIZE		0xF13C
+
+#define S5P_FIMV_D_LUMA_DPB			0xF140
+#define S5P_FIMV_D_CHROMA_DPB			0xF240
+#define S5P_FIMV_D_MV_BUFFER			0xF340
+
+#define S5P_FIMV_D_SCRATCH_BUFFER_ADDR		0xF440
+#define S5P_FIMV_D_SCRATCH_BUFFER_SIZE		0xF444
+#define S5P_FIMV_D_METADATA_BUFFER_ADDR		0xF448
+#define S5P_FIMV_D_METADATA_BUFFER_SIZE		0xF44C
+#define S5P_FIMV_D_CPB_BUFFER_ADDR		0xF4B0
+#define S5P_FIMV_D_CPB_BUFFER_SIZE		0xF4B4
+
+#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER	0xF4B8
+#define S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER	0xF4BC
+#define S5P_FIMV_D_CPB_BUFFER_OFFSET		0xF4C0
+#define S5P_FIMV_D_SLICE_IF_ENABLE		0xF4C4
+#define S5P_FIMV_D_PICTURE_TAG			0xF4C8
+#define S5P_FIMV_D_STREAM_DATA_SIZE		0xF4D0
+
+/* Display information register */
+#define S5P_FIMV_D_DISPLAY_FRAME_WIDTH		0xF500
+#define S5P_FIMV_D_DISPLAY_FRAME_HEIGHT		0xF504
+
+/* Display status */
+#define S5P_FIMV_D_DISPLAY_STATUS		0xF508
+#define S5P_FIMV_DEC_STATUS_DECODING_ONLY		0
+#define S5P_FIMV_DEC_STATUS_DECODING_DISPLAY		1
+#define S5P_FIMV_DEC_STATUS_DISPLAY_ONLY		2
+#define S5P_FIMV_DEC_STATUS_DECODING_EMPTY		3
+#define S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK	7
+#define S5P_FIMV_DEC_STATUS_PROGRESSIVE			(0<<3)
+#define S5P_FIMV_DEC_STATUS_INTERLACE			(1<<3)
+#define S5P_FIMV_DEC_STATUS_INTERLACE_MASK		(1<<3)
+#define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK		(3<<4)
+#define S5P_FIMV_DEC_STATUS_RESOLUTION_INC		(1<<4)
+#define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC		(2<<4)
+#define S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT		4
+#define S5P_FIMV_DEC_STATUS_CRC_GENERATED		(1<<5)
+#define S5P_FIMV_DEC_STATUS_CRC_NOT_GENERATED		(0<<5)
+#define S5P_FIMV_DEC_STATUS_CRC_MASK			(1<<5)
+
+#define S5P_FIMV_D_DISPLAY_LUMA_ADDR		0xF50C
+#define S5P_FIMV_D_DISPLAY_CHROMA_ADDR		0xF510
+
+#define S5P_FIMV_D_DISPLAY_FRAME_TYPE		0xF514
+#define S5P_FIMV_DECODE_FRAME_SKIPPED		0
+#define S5P_FIMV_DECODE_FRAME_I_FRAME		1
+#define S5P_FIMV_DECODE_FRAME_P_FRAME		2
+#define S5P_FIMV_DECODE_FRAME_B_FRAME		3
+#define S5P_FIMV_DECODE_FRAME_OTHER_FRAME	4
+#define S5P_FIMV_SHARED_CROP_INFO_H		0x0020
+#define S5P_FIMV_SHARED_CROP_LEFT_MASK		0xFFFF
+#define S5P_FIMV_SHARED_CROP_LEFT_SHIFT		0
+#define S5P_FIMV_SHARED_CROP_RIGHT_MASK		0xFFFF0000
+#define S5P_FIMV_SHARED_CROP_RIGHT_SHIFT	16
+#define S5P_FIMV_SHARED_CROP_INFO_V		0x0024
+#define S5P_FIMV_SHARED_CROP_TOP_MASK		0xFFFF
+#define S5P_FIMV_SHARED_CROP_TOP_SHIFT		0
+#define S5P_FIMV_SHARED_CROP_BOTTOM_MASK	0xFFFF0000
+#define S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT	16
+
+#define S5P_FIMV_D_DISPLAY_CROP_INFO1		0xF518
+#define S5P_FIMV_D_DISPLAY_CROP_INFO2		0xF51C
+#define S5P_FIMV_D_DISPLAY_PICTURE_PROFILE	0xF520
+#define S5P_FIMV_D_DISPLAY_LUMA_CRC_TOP		0xF524
+#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_TOP	0xF528
+#define S5P_FIMV_D_DISPLAY_LUMA_CRC_BOT		0xF52C
+#define S5P_FIMV_D_DISPLAY_CHROMA_CRC_BOT	0xF530
+#define S5P_FIMV_D_DISPLAY_ASPECT_RATIO		0xF534
+#define S5P_FIMV_D_DISPLAY_EXTENDED_AR		0xF538
+
+/* Decoded picture information register */
+#define S5P_FIMV_D_DECODED_FRAME_WIDTH		0xF53C
+#define S5P_FIMV_D_DECODED_FRAME_HEIGHT		0xF540
+#define S5P_FIMV_D_DECODED_STATUS		0xF544
+#define S5P_FIMV_DEC_CRC_GEN_MASK		0x1
+#define S5P_FIMV_DEC_CRC_GEN_SHIFT		6
+
+#define S5P_FIMV_D_DECODED_LUMA_ADDR		0xF548
+#define S5P_FIMV_D_DECODED_CHROMA_ADDR		0xF54C
+
+#define S5P_FIMV_D_DECODED_FRAME_TYPE		0xF550
+#define S5P_FIMV_DECODE_FRAME_MASK		7
+
+#define S5P_FIMV_D_DECODED_CROP_INFO1		0xF554
+#define S5P_FIMV_D_DECODED_CROP_INFO2		0xF558
+#define S5P_FIMV_D_DECODED_PICTURE_PROFILE	0xF55C
+#define S5P_FIMV_D_DECODED_NAL_SIZE		0xF560
+#define S5P_FIMV_D_DECODED_LUMA_CRC_TOP		0xF564
+#define S5P_FIMV_D_DECODED_CHROMA_CRC_TOP	0xF568
+#define S5P_FIMV_D_DECODED_LUMA_CRC_BOT		0xF56C
+#define S5P_FIMV_D_DECODED_CHROMA_CRC_BOT	0xF570
+
+/* Returned value register for specific setting */
+#define S5P_FIMV_D_RET_PICTURE_TAG_TOP		0xF574
+#define S5P_FIMV_D_RET_PICTURE_TAG_BOT		0xF578
+#define S5P_FIMV_D_RET_PICTURE_TIME_TOP		0xF57C
+#define S5P_FIMV_D_RET_PICTURE_TIME_BOT		0xF580
+#define S5P_FIMV_D_CHROMA_FORMAT		0xF588
+#define S5P_FIMV_D_MPEG4_INFO			0xF58C
+#define S5P_FIMV_D_H264_INFO			0xF590
+
+#define S5P_FIMV_D_METADATA_ADDR_CONCEALED_MB	0xF594
+#define S5P_FIMV_D_METADATA_SIZE_CONCEALED_MB	0xF598
+#define S5P_FIMV_D_METADATA_ADDR_VC1_PARAM	0xF59C
+#define S5P_FIMV_D_METADATA_SIZE_VC1_PARAM	0xF5A0
+#define S5P_FIMV_D_METADATA_ADDR_SEI_NAL	0xF5A4
+#define S5P_FIMV_D_METADATA_SIZE_SEI_NAL	0xF5A8
+#define S5P_FIMV_D_METADATA_ADDR_VUI		0xF5AC
+#define S5P_FIMV_D_METADATA_SIZE_VUI		0xF5B0
+
+#define S5P_FIMV_D_MVC_VIEW_ID			0xF5B4
+
+/* SEI related information */
+#define S5P_FIMV_D_FRAME_PACK_SEI_AVAIL		0xF5F0
+#define S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID	0xF5F4
+#define S5P_FIMV_D_FRAME_PACK_SEI_INFO		0xF5F8
+#define S5P_FIMV_D_FRAME_PACK_GRID_POS		0xF5FC
+
+/* Encoder Registers */
+#define S5P_FIMV_E_FRAME_WIDTH			0xF770
+#define S5P_FIMV_E_FRAME_HEIGHT			0xF774
+#define S5P_FIMV_E_CROPPED_FRAME_WIDTH		0xF778
+#define S5P_FIMV_E_CROPPED_FRAME_HEIGHT		0xF77C
+#define S5P_FIMV_E_FRAME_CROP_OFFSET		0xF780
+#define S5P_FIMV_E_ENC_OPTIONS			0xF784
+#define S5P_FIMV_E_PICTURE_PROFILE		0xF788
+#define S5P_FIMV_ENC_PROFILE_H264_MAIN			0
+#define S5P_FIMV_ENC_PROFILE_H264_HIGH			1
+#define S5P_FIMV_ENC_PROFILE_H264_BASELINE		2
+#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE	3
+#define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE		0
+#define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE	1
+#define S5P_FIMV_E_FIXED_PICTURE_QP		0xF790
+
+#define S5P_FIMV_E_RC_CONFIG			0xF794
+#define S5P_FIMV_E_RC_QP_BOUND			0xF798
+#define S5P_FIMV_E_RC_RPARAM			0xF79C
+#define S5P_FIMV_E_MB_RC_CONFIG			0xF7A0
+#define S5P_FIMV_E_PADDING_CTRL			0xF7A4
+#define S5P_FIMV_E_MV_HOR_RANGE			0xF7AC
+#define S5P_FIMV_E_MV_VER_RANGE			0xF7B0
+
+#define S5P_FIMV_E_VBV_BUFFER_SIZE		0xF84C
+#define S5P_FIMV_E_VBV_INIT_DELAY		0xF850
+#define S5P_FIMV_E_NUM_DPB			0xF890
+#define S5P_FIMV_E_LUMA_DPB			0xF8C0
+#define S5P_FIMV_E_CHROMA_DPB			0xF904
+#define S5P_FIMV_E_ME_BUFFER			0xF948
+
+#define S5P_FIMV_E_SCRATCH_BUFFER_ADDR		0xF98C
+#define S5P_FIMV_E_SCRATCH_BUFFER_SIZE		0xF990
+#define S5P_FIMV_E_TMV_BUFFER0			0xF994
+#define S5P_FIMV_E_TMV_BUFFER1			0xF998
+#define S5P_FIMV_E_SOURCE_LUMA_ADDR		0xF9F0
+#define S5P_FIMV_E_SOURCE_CHROMA_ADDR		0xF9F4
+#define S5P_FIMV_E_STREAM_BUFFER_ADDR		0xF9F8
+#define S5P_FIMV_E_STREAM_BUFFER_SIZE		0xF9FC
+#define S5P_FIMV_E_ROI_BUFFER_ADDR		0xFA00
+
+#define S5P_FIMV_E_PARAM_CHANGE			0xFA04
+#define S5P_FIMV_E_IR_SIZE			0xFA08
+#define S5P_FIMV_E_GOP_CONFIG			0xFA0C
+#define S5P_FIMV_E_MSLICE_MODE			0xFA10
+#define S5P_FIMV_E_MSLICE_SIZE_MB		0xFA14
+#define S5P_FIMV_E_MSLICE_SIZE_BITS		0xFA18
+#define S5P_FIMV_E_FRAME_INSERTION		0xFA1C
+
+#define S5P_FIMV_E_RC_FRAME_RATE		0xFA20
+#define S5P_FIMV_E_RC_BIT_RATE			0xFA24
+#define S5P_FIMV_E_RC_QP_OFFSET			0xFA28
+#define S5P_FIMV_E_RC_ROI_CTRL			0xFA2C
+#define S5P_FIMV_E_PICTURE_TAG			0xFA30
+#define S5P_FIMV_E_BIT_COUNT_ENABLE		0xFA34
+#define S5P_FIMV_E_MAX_BIT_COUNT		0xFA38
+#define S5P_FIMV_E_MIN_BIT_COUNT		0xFA3C
+
+#define S5P_FIMV_E_METADATA_BUFFER_ADDR		0xFA40
+#define S5P_FIMV_E_METADATA_BUFFER_SIZE		0xFA44
+#define S5P_FIMV_E_STREAM_SIZE			0xFA80
+#define S5P_FIMV_E_SLICE_TYPE			0xFA84
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_NON_CODED	0
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_I		1
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_P		2
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_B		3
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_SKIPPED	4
+#define S5P_FIMV_ENC_SI_SLICE_TYPE_OTHERS	5
+#define S5P_FIMV_E_PICTURE_COUNT		0xFA88
+#define S5P_FIMV_E_RET_PICTURE_TAG		0xFA8C
+#define S5P_FIMV_E_STREAM_BUFFER_WRITE_POINTER	0xFA90
+
+#define S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR	0xFA94
+#define S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR	0xFA98
+#define S5P_FIMV_E_RECON_LUMA_DPB_ADDR		0xFA9C
+#define S5P_FIMV_E_RECON_CHROMA_DPB_ADDR	0xFAA0
+#define S5P_FIMV_E_METADATA_ADDR_ENC_SLICE	0xFAA4
+#define S5P_FIMV_E_METADATA_SIZE_ENC_SLICE	0xFAA8
+
+#define S5P_FIMV_E_MPEG4_OPTIONS		0xFB10
+#define S5P_FIMV_E_MPEG4_HEC_PERIOD		0xFB14
+#define S5P_FIMV_E_ASPECT_RATIO			0xFB50
+#define S5P_FIMV_E_EXTENDED_SAR			0xFB54
+
+#define S5P_FIMV_E_H264_OPTIONS			0xFB58
+#define S5P_FIMV_E_H264_LF_ALPHA_OFFSET		0xFB5C
+#define S5P_FIMV_E_H264_LF_BETA_OFFSET		0xFB60
+#define S5P_FIMV_E_H264_I_PERIOD		0xFB64
+
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE			0xFB68
+#define S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1		0xFB6C
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR		0xFB70
+#define S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1	0xFB74
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0	0xFB78
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_1	0xFB7C
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_2	0xFB80
+#define S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_3	0xFB84
+
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_0	0xFB88
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_1	0xFB8C
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_2	0xFB90
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_3	0xFB94
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_4	0xFB98
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_5	0xFB9C
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_6	0xFBA0
+#define S5P_FIMV_E_H264_ASO_SLICE_ORDER_7	0xFBA4
+
+#define S5P_FIMV_E_H264_CHROMA_QP_OFFSET	0xFBA8
+#define S5P_FIMV_E_H264_NUM_T_LAYER		0xFBAC
+
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0	0xFBB0
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER1	0xFBB4
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER2	0xFBB8
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER3	0xFBBC
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER4	0xFBC0
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER5	0xFBC4
+#define S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER6	0xFBC8
+
+#define S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO	0xFC4C
+#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_SIDE_BY_SIDE	0
+#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TOP_BOTTOM	1
+#define S5P_FIMV_ENC_FP_ARRANGEMENT_TYPE_TEMPORAL	2
+
+#define S5P_FIMV_E_MVC_FRAME_QP_VIEW1		0xFD40
+#define S5P_FIMV_E_MVC_RC_FRAME_RATE_VIEW1	0xFD44
+#define S5P_FIMV_E_MVC_RC_BIT_RATE_VIEW1	0xFD48
+#define S5P_FIMV_E_MVC_RC_QBOUND_VIEW1		0xFD4C
+#define S5P_FIMV_E_MVC_RC_RPARA_VIEW1		0xFD50
+#define S5P_FIMV_E_MVC_INTER_VIEW_PREDICTION_ON	0xFD80
+
+/* Codec numbers  */
+#define S5P_FIMV_CODEC_NONE		-1
+
+
+#define S5P_FIMV_CODEC_H264_DEC	0
+#define S5P_FIMV_CODEC_H264_MVC_DEC	1
+
+#define S5P_FIMV_CODEC_MPEG4_DEC	3
+#define S5P_FIMV_CODEC_FIMV1_DEC	4
+#define S5P_FIMV_CODEC_FIMV2_DEC	5
+#define S5P_FIMV_CODEC_FIMV3_DEC	6
+#define S5P_FIMV_CODEC_FIMV4_DEC	7
+#define S5P_FIMV_CODEC_H263_DEC	8
+#define S5P_FIMV_CODEC_VC1RCV_DEC	9
+#define S5P_FIMV_CODEC_VC1_DEC		10
+/* FIXME: Add 11~12 */
+#define S5P_FIMV_CODEC_MPEG2_DEC	13
+#define S5P_FIMV_CODEC_VP8_DEC		14
+/* FIXME: Add 15~16 */
+#define S5P_FIMV_CODEC_H264_ENC	20
+#define S5P_FIMV_CODEC_H264_MVC_ENC	21
+
+#define S5P_FIMV_CODEC_MPEG4_ENC	23
+#define S5P_FIMV_CODEC_H263_ENC	24
+/***	Definitions for MFCv5 compatibility ***/
+#define S5P_FIMV_SI_DISPLAY_Y_ADR		S5P_FIMV_D_DISPLAY_LUMA_ADDR
+#define S5P_FIMV_SI_DISPLAY_C_ADR		S5P_FIMV_D_DISPLAY_CHROMA_ADDR
+
+#define S5P_FIMV_CRC_LUMA0			S5P_FIMV_D_DECODED_LUMA_CRC_TOP
+#define S5P_FIMV_CRC_CHROMA0			S5P_FIMV_D_DECODED_CHROMA_CRC_TOP
+#define S5P_FIMV_CRC_LUMA1			S5P_FIMV_D_DECODED_LUMA_CRC_BOT
+#define S5P_FIMV_CRC_CHROMA1			S5P_FIMV_D_DECODED_CHROMA_CRC_BOT
+#define S5P_FIMV_CRC_DISP_LUMA0			S5P_FIMV_D_DISPLAY_LUMA_CRC_TOP
+#define S5P_FIMV_CRC_DISP_CHROMA0		S5P_FIMV_D_DISPLAY_CHROMA_CRC_TOP
+
+#define S5P_FIMV_SI_DECODED_STATUS		S5P_FIMV_D_DECODED_STATUS
+#define S5P_FIMV_SI_DISPLAY_STATUS		S5P_FIMV_D_DISPLAY_STATUS
+#define S5P_FIMV_SHARED_SET_FRAME_TAG		S5P_FIMV_D_PICTURE_TAG
+#define S5P_FIMV_SHARED_GET_FRAME_TAG_TOP	S5P_FIMV_D_RET_PICTURE_TAG_TOP
+#define S5P_FIMV_CRC_DISP_STATUS		S5P_FIMV_D_DISPLAY_STATUS
+
+/* SEI related information */
+#define S5P_FIMV_FRAME_PACK_SEI_AVAIL		S5P_FIMV_D_FRAME_PACK_SEI_AVAIL
+#define S5P_FIMV_FRAME_PACK_ARRGMENT_ID		S5P_FIMV_D_FRAME_PACK_ARRGMENT_ID
+#define S5P_FIMV_FRAME_PACK_SEI_INFO		S5P_FIMV_D_FRAME_PACK_SEI_INFO
+#define S5P_FIMV_FRAME_PACK_GRID_POS		S5P_FIMV_D_FRAME_PACK_GRID_POS
+
+#define S5P_FIMV_SHARED_SET_E_FRAME_TAG		S5P_FIMV_E_PICTURE_TAG
+#define S5P_FIMV_SHARED_GET_E_FRAME_TAG		S5P_FIMV_E_RET_PICTURE_TAG
+#define S5P_FIMV_ENCODED_LUMA_ADDR		S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR
+#define S5P_FIMV_ENCODED_CHROMA_ADDR		S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR
+#define	S5P_FIMV_FRAME_INSERTION		S5P_FIMV_E_FRAME_INSERTION
+
+#define S5P_FIMV_PARAM_CHANGE_FLAG		S5P_FIMV_E_PARAM_CHANGE /* flag */
+#define S5P_FIMV_NEW_I_PERIOD			S5P_FIMV_E_GOP_CONFIG
+#define S5P_FIMV_NEW_RC_FRAME_RATE		S5P_FIMV_E_RC_FRAME_RATE
+#define S5P_FIMV_NEW_RC_BIT_RATE		S5P_FIMV_E_RC_BIT_RATE
+/*** End of MFCv5 compatibility definitions ***/
+
+/***      old definitions     ***/
+#define S5P_FIMV_SW_RESET		0x0000
+#define S5P_FIMV_RISC_HOST_INT		0x0008
+
+/* Command from HOST to RISC */
+#define S5P_FIMV_HOST2RISC_ARG1		0x0034
+#define S5P_FIMV_HOST2RISC_ARG2		0x0038
+#define S5P_FIMV_HOST2RISC_ARG3		0x003c
+#define S5P_FIMV_HOST2RISC_ARG4		0x0040
+
+/* Command from RISC to HOST */
+#define S5P_FIMV_RISC2HOST_CMD_MASK	0x1FFFF
+#define S5P_FIMV_RISC2HOST_ARG1		0x0048
+#define S5P_FIMV_RISC2HOST_ARG2		0x004c
+#define S5P_FIMV_RISC2HOST_ARG3		0x0050
+#define S5P_FIMV_RISC2HOST_ARG4		0x0054
+
+#define S5P_FIMV_SYS_MEM_SZ		0x005c
+#define S5P_FIMV_FW_STATUS		0x0080
+
+/* Memory controller register */
+#define S5P_FIMV_MC_DRAMBASE_ADR_A	0x0508
+#define S5P_FIMV_MC_DRAMBASE_ADR_B	0x050c
+#define S5P_FIMV_MC_STATUS		0x0510
+
+/* Common register */
+#define S5P_FIMV_COMMON_BASE_A		0x0600
+#define S5P_FIMV_COMMON_BASE_B		0x0700
+
+/* Decoder */
+#define S5P_FIMV_DEC_CHROMA_ADR		(S5P_FIMV_COMMON_BASE_A)
+#define S5P_FIMV_DEC_LUMA_ADR		(S5P_FIMV_COMMON_BASE_B)
+
+/* H.264 decoding */
+#define S5P_FIMV_H264_VERT_NB_MV_ADR	(S5P_FIMV_COMMON_BASE_A + 0x8c)	/* vertical neighbor motion vector */
+#define S5P_FIMV_H264_NB_IP_ADR		(S5P_FIMV_COMMON_BASE_A + 0x90)	/* neighbor pixels for intra pred */
+#define S5P_FIMV_H264_MV_ADR		(S5P_FIMV_COMMON_BASE_B + 0x80)	/* H264 motion vector */
+
+/* MPEG4 decoding */
+#define S5P_FIMV_MPEG4_NB_DCAC_ADR	(S5P_FIMV_COMMON_BASE_A + 0x8c)	/* neighbor AC/DC coeff. */
+#define S5P_FIMV_MPEG4_UP_NB_MV_ADR	(S5P_FIMV_COMMON_BASE_A + 0x90)	/* upper neighbor motion vector */
+#define S5P_FIMV_MPEG4_SA_MV_ADR	(S5P_FIMV_COMMON_BASE_A + 0x94)	/* subseq. anchor motion vector */
+#define S5P_FIMV_MPEG4_OT_LINE_ADR	(S5P_FIMV_COMMON_BASE_A + 0x98)	/* overlap transform line */
+#define S5P_FIMV_MPEG4_SP_ADR		(S5P_FIMV_COMMON_BASE_A + 0xa8)	/* syntax parser */
+
+/* H.263 decoding */
+#define S5P_FIMV_H263_NB_DCAC_ADR	(S5P_FIMV_COMMON_BASE_A + 0x8c)
+#define S5P_FIMV_H263_UP_NB_MV_ADR	(S5P_FIMV_COMMON_BASE_A + 0x90)
+#define S5P_FIMV_H263_SA_MV_ADR		(S5P_FIMV_COMMON_BASE_A + 0x94)
+#define S5P_FIMV_H263_OT_LINE_ADR	(S5P_FIMV_COMMON_BASE_A + 0x98)
+
+/* VC-1 decoding */
+#define S5P_FIMV_VC1_NB_DCAC_ADR	(S5P_FIMV_COMMON_BASE_A + 0x8c)
+#define S5P_FIMV_VC1_UP_NB_MV_ADR	(S5P_FIMV_COMMON_BASE_A + 0x90)
+#define S5P_FIMV_VC1_SA_MV_ADR		(S5P_FIMV_COMMON_BASE_A + 0x94)
+#define S5P_FIMV_VC1_OT_LINE_ADR	(S5P_FIMV_COMMON_BASE_A + 0x98)
+#define S5P_FIMV_VC1_BITPLANE3_ADR	(S5P_FIMV_COMMON_BASE_A + 0x9c)	/* bitplane3 */
+#define S5P_FIMV_VC1_BITPLANE2_ADR	(S5P_FIMV_COMMON_BASE_A + 0xa0)	/* bitplane2 */
+#define S5P_FIMV_VC1_BITPLANE1_ADR	(S5P_FIMV_COMMON_BASE_A + 0xa4)	/* bitplane1 */
+
+/* Encoder */
+#define S5P_FIMV_ENC_REF0_LUMA_ADR	(S5P_FIMV_COMMON_BASE_A + 0x1c)	/* reconstructed luma */
+#define S5P_FIMV_ENC_REF1_LUMA_ADR	(S5P_FIMV_COMMON_BASE_A + 0x20)
+#define S5P_FIMV_ENC_REF0_CHROMA_ADR	(S5P_FIMV_COMMON_BASE_B)	/* reconstructed chroma */
+#define S5P_FIMV_ENC_REF1_CHROMA_ADR	(S5P_FIMV_COMMON_BASE_B + 0x04)
+#define S5P_FIMV_ENC_REF2_LUMA_ADR	(S5P_FIMV_COMMON_BASE_B + 0x10)
+#define S5P_FIMV_ENC_REF2_CHROMA_ADR	(S5P_FIMV_COMMON_BASE_B + 0x08)
+#define S5P_FIMV_ENC_REF3_LUMA_ADR	(S5P_FIMV_COMMON_BASE_B + 0x14)
+#define S5P_FIMV_ENC_REF3_CHROMA_ADR	(S5P_FIMV_COMMON_BASE_B + 0x0c)
+
+/* H.264 encoding */
+#define S5P_FIMV_H264_UP_MV_ADR		(S5P_FIMV_COMMON_BASE_A)	/* upper motion vector */
+#define S5P_FIMV_H264_NBOR_INFO_ADR	(S5P_FIMV_COMMON_BASE_A + 0x04)	/* entropy engine's neighbor info. */
+#define S5P_FIMV_H264_UP_INTRA_MD_ADR	(S5P_FIMV_COMMON_BASE_A + 0x08)	/* upper intra MD */
+#define S5P_FIMV_H264_COZERO_FLAG_ADR	(S5P_FIMV_COMMON_BASE_A + 0x10)	/* direct cozero flag */
+#define S5P_FIMV_H264_UP_INTRA_PRED_ADR	(S5P_FIMV_COMMON_BASE_B + 0x40)	/* upper intra PRED */
+
+/* H.263 encoding */
+#define S5P_FIMV_H263_UP_MV_ADR		(S5P_FIMV_COMMON_BASE_A)	/* upper motion vector */
+#define S5P_FIMV_H263_ACDC_COEF_ADR	(S5P_FIMV_COMMON_BASE_A + 0x04)	/* upper Q coeff. */
+
+/* MPEG4 encoding */
+#define S5P_FIMV_MPEG4_UP_MV_ADR	(S5P_FIMV_COMMON_BASE_A)	/* upper motion vector */
+#define S5P_FIMV_MPEG4_ACDC_COEF_ADR	(S5P_FIMV_COMMON_BASE_A + 0x04)	/* upper Q coeff. */
+#define S5P_FIMV_MPEG4_COZERO_FLAG_ADR	(S5P_FIMV_COMMON_BASE_A + 0x10)	/* direct cozero flag */
+
+#define S5P_FIMV_ENC_REF_B_LUMA_ADR     0x062c /* ref B Luma addr */
+#define S5P_FIMV_ENC_REF_B_CHROMA_ADR   0x0630 /* ref B Chroma addr */
+
+#define S5P_FIMV_ENC_CUR_LUMA_ADR	0x0718 /* current Luma addr */
+#define S5P_FIMV_ENC_CUR_CHROMA_ADR	0x071C /* current Chroma addr */
+
+/* Codec common register */
+#define S5P_FIMV_ENC_HSIZE_PX		0x0818 /* frame width at encoder */
+#define S5P_FIMV_ENC_VSIZE_PX		0x081c /* frame height at encoder */
+#define S5P_FIMV_ENC_PROFILE		0x0830 /* profile register */
+#define S5P_FIMV_ENC_PIC_STRUCT		0x083c /* picture field/frame flag */
+#define S5P_FIMV_ENC_LF_CTRL		0x0848 /* loop filter control */
+#define S5P_FIMV_ENC_ALPHA_OFF		0x084c /* loop filter alpha offset */
+#define S5P_FIMV_ENC_BETA_OFF		0x0850 /* loop filter beta offset */
+#define S5P_FIMV_MR_BUSIF_CTRL		0x0854 /* hidden, bus interface ctrl */
+#define S5P_FIMV_ENC_PXL_CACHE_CTRL	0x0a00 /* pixel cache control */
+
+/* Channel & stream interface register */
+#define S5P_FIMV_SI_RTN_CHID		0x2000 /* Return CH instance ID register */
+#define S5P_FIMV_SI_CH0_INST_ID		0x2040 /* codec instance ID */
+#define S5P_FIMV_SI_CH1_INST_ID		0x2080 /* codec instance ID */
+/* Decoder */
+#define S5P_FIMV_SI_VRESOL		0x2004 /* vertical resolution of decoder */
+#define S5P_FIMV_SI_HRESOL		0x2008 /* horizontal resolution of decoder */
+#define S5P_FIMV_SI_BUF_NUMBER		0x200c /* number of frames in the decoded pic */
+#define S5P_FIMV_SI_CONSUMED_BYTES	0x2018 /* Consumed number of bytes to decode
+								a frame */
+#define S5P_FIMV_SI_FRAME_TYPE		0x2020 /* frame type such as skip/I/P/B */
+
+#define S5P_FIMV_SI_CH0_SB_ST_ADR	0x2044 /* start addr of stream buf */
+#define S5P_FIMV_SI_CH0_SB_FRM_SIZE	0x2048 /* size of stream buf */
+#define S5P_FIMV_SI_CH0_DESC_ADR	0x204c /* addr of descriptor buf */
+#define S5P_FIMV_SI_CH0_CPB_SIZE	0x2058 /* max size of coded pic. buf */
+#define S5P_FIMV_SI_CH0_DESC_SIZE	0x205c /* max size of descriptor buf */
+
+#define S5P_FIMV_SI_CH1_SB_ST_ADR	0x2084 /* start addr of stream buf */
+#define S5P_FIMV_SI_CH1_SB_FRM_SIZE	0x2088 /* size of stream buf */
+#define S5P_FIMV_SI_CH1_DESC_ADR	0x208c /* addr of descriptor buf */
+#define S5P_FIMV_SI_CH1_CPB_SIZE	0x2098 /* max size of coded pic. buf */
+#define S5P_FIMV_SI_CH1_DESC_SIZE	0x209c /* max size of descriptor buf */
+
+#define S5P_FIMV_SI_FIMV1_HRESOL	0x2054 /* horizontal resolution */
+#define S5P_FIMV_SI_FIMV1_VRESOL	0x2050 /* vertical resolution */
+
+/* Decode frame address */
+#define S5P_FIMV_DECODE_Y_ADR			0x2024
+#define S5P_FIMV_DECODE_C_ADR			0x2028
+
+/* Decoded frame type */
+#define S5P_FIMV_DECODE_FRAME_TYPE		0x2020
+
+/* Sizes of buffers required for decoding */
+#define S5P_FIMV_DEC_NB_IP_SIZE			(32 * 1024)
+#define S5P_FIMV_DEC_VERT_NB_MV_SIZE		(16 * 1024)
+#define S5P_FIMV_DEC_NB_DCAC_SIZE		(16 * 1024)
+#define S5P_FIMV_DEC_UPNB_MV_SIZE		(68 * 1024)
+#define S5P_FIMV_DEC_SUB_ANCHOR_MV_SIZE		(136 * 1024)
+#define S5P_FIMV_DEC_OVERLAP_TRANSFORM_SIZE     (32 * 1024)
+#define S5P_FIMV_DEC_VC1_BITPLANE_SIZE		(2 * 1024)
+#define S5P_FIMV_DEC_STX_PARSER_SIZE		(68 * 1024)
+
+#define S5P_FIMV_NV12M_HALIGN			16
+#define S5P_FIMV_NV12MT_HALIGN			16
+#define S5P_FIMV_NV12MT_VALIGN			16
+
+/* Sizes of buffers required for encoding */
+#define S5P_FIMV_ENC_UPMV_SIZE			(0x10000)
+#define S5P_FIMV_ENC_COLFLG_SIZE		(0x10000)
+#define S5P_FIMV_ENC_INTRAMD_SIZE		(0x10000)
+#define S5P_FIMV_ENC_INTRAPRED_SIZE		(0x4000)
+#define S5P_FIMV_ENC_NBORINFO_SIZE		(0x10000)
+#define S5P_FIMV_ENC_ACDCCOEF_SIZE		(0x10000)
+
+/* Encoder */
+#define S5P_FIMV_ENC_SI_STRM_SIZE	0x2004 /* stream size */
+#define S5P_FIMV_ENC_SI_PIC_CNT		0x2008 /* picture count */
+#define S5P_FIMV_ENC_SI_WRITE_PTR	0x200c /* write pointer */
+#define S5P_FIMV_ENC_SI_SLICE_TYPE	0x2010 /* slice type(I/P/B/IDR) */
+
+#define S5P_FIMV_ENCODED_Y_ADDR         0x2014 /* the addr of the encoded luma pic */
+#define S5P_FIMV_ENCODED_C_ADDR         0x2018 /* the addr of the encoded chroma pic */
+
+#define S5P_FIMV_ENC_SI_CH0_SB_ADR	0x2044 /* addr of stream buf */
+#define S5P_FIMV_ENC_SI_CH0_SB_SIZE	0x204c /* size of stream buf */
+#define S5P_FIMV_ENC_SI_CH0_CUR_Y_ADR	0x2050 /* current Luma addr */
+#define S5P_FIMV_ENC_SI_CH0_CUR_C_ADR	0x2054 /* current Chroma addr */
+#define S5P_FIMV_ENC_SI_CH0_FRAME_INS	0x2058 /* frame insertion */
+
+#define S5P_FIMV_ENC_SI_CH1_SB_ADR	0x2084 /* addr of stream buf */
+#define S5P_FIMV_ENC_SI_CH1_SB_SIZE	0x208c /* size of stream buf */
+#define S5P_FIMV_ENC_SI_CH1_CUR_Y_ADR	0x2090 /* current Luma addr */
+#define S5P_FIMV_ENC_SI_CH1_CUR_C_ADR	0x2094 /* current Chroma addr */
+#define S5P_FIMV_ENC_SI_CH1_FRAME_INS	0x2098 /* frame insertion */
+
+#define S5P_FIMV_ENC_PIC_TYPE_CTRL	0xc504 /* pic type level control */
+#define S5P_FIMV_ENC_B_RECON_WRITE_ON	0xc508 /* B frame recon write ctrl */
+#define S5P_FIMV_ENC_MSLICE_CTRL	0xc50c /* multi slice control */
+#define S5P_FIMV_ENC_MSLICE_MB		0xc510 /* MB number in the one slice */
+#define S5P_FIMV_ENC_MSLICE_BIT		0xc514 /* bit count for one slice */
+#define S5P_FIMV_ENC_CIR_CTRL		0xc518 /* number of intra refresh MB */
+#define S5P_FIMV_ENC_MAP_FOR_CUR	0xc51c /* linear or 64x32 tiled mode */
+#define S5P_FIMV_ENC_PADDING_CTRL	0xc520 /* padding control */
+
+#define S5P_FIMV_ENC_RC_CONFIG		0xc5a0 /* RC config */
+#define S5P_FIMV_ENC_RC_BIT_RATE	0xc5a8 /* bit rate */
+#define S5P_FIMV_ENC_RC_QBOUND		0xc5ac /* max/min QP */
+#define S5P_FIMV_ENC_RC_RPARA		0xc5b0 /* rate control reaction coeff */
+#define S5P_FIMV_ENC_RC_MB_CTRL		0xc5b4 /* MB adaptive scaling */
+
+/* Encoder for H264 only */
+#define S5P_FIMV_ENC_H264_ENTRP_MODE	0xd004 /* CAVLC or CABAC */
+#define S5P_FIMV_ENC_H264_ALPHA_OFF	0xd008 /* loop filter alpha offset */
+#define S5P_FIMV_ENC_H264_BETA_OFF	0xd00c /* loop filter beta offset */
+#define S5P_FIMV_ENC_H264_NUM_OF_REF	0xd010 /* number of reference for P/B */
+#define S5P_FIMV_ENC_H264_TRANS_FLAG	0xd034 /* 8x8 transform flag in PPS & high profile */
+
+#define S5P_FIMV_ENC_RC_FRAME_RATE	0xd0d0 /* frame rate */
+
+/* Encoder for MPEG4 only */
+#define S5P_FIMV_ENC_MPEG4_QUART_PXL	0xe008 /* qpel interpolation ctrl */
+
+/* Additional */
+#define S5P_FIMV_SI_CH0_DPB_CONF_CTRL   0x2068 /* DPB Config Control Register */
+#define S5P_FIMV_DPB_COUNT_MASK		0xffff
+
+#define S5P_FIMV_SI_CH0_RELEASE_BUF     0x2060 /* DPB release buffer register */
+#define S5P_FIMV_SI_CH0_HOST_WR_ADR	0x2064 /* address of shared memory */
+
+/* Channel Control Register */
+#define S5P_FIMV_CH_FRAME_START_REALLOC	5
+
+#define S5P_FIMV_CH_MASK		7
+#define S5P_FIMV_CH_SHIFT		16
+
+/* Host to RISC command */
+#define S5P_FIMV_R2H_CMD_RSV_RET		3
+#define S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET	7
+#define S5P_FIMV_R2H_CMD_FLUSH_RET		12
+#define S5P_FIMV_R2H_CMD_EDFU_INIT_RET		16
+
+/* Shared memory registers' offsets */
+
+/* An offset of the start position in the stream when
+ * the start position is not aligned */
+#define S5P_FIMV_SHARED_GET_FRAME_TAG_BOT	0x000C
+#define S5P_FIMV_SHARED_START_BYTE_NUM		0x0018
+#define S5P_FIMV_SHARED_RC_VOP_TIMING		0x0030
+#define S5P_FIMV_SHARED_LUMA_DPB_SIZE		0x0064
+#define S5P_FIMV_SHARED_CHROMA_DPB_SIZE		0x0068
+#define S5P_FIMV_SHARED_MV_SIZE			0x006C
+#define S5P_FIMV_SHARED_PIC_TIME_TOP		0x0010
+#define S5P_FIMV_SHARED_PIC_TIME_BOTTOM		0x0014
+#define S5P_FIMV_SHARED_EXT_ENC_CONTROL		0x0028
+#define S5P_FIMV_SHARED_P_B_FRAME_QP		0x0070
+#define S5P_FIMV_SHARED_ASPECT_RATIO_IDC	0x0074
+#define S5P_FIMV_SHARED_EXTENDED_SAR		0x0078
+#define S5P_FIMV_SHARED_H264_I_PERIOD		0x009C
+#define S5P_FIMV_SHARED_RC_CONTROL_CONFIG	0x00A0
+
+/* End of old definitions */
+
+#endif /* _REGS_FIMV_V6_H */
diff --git a/drivers/media/video/s5p-mfc/regs-mfc.h b/drivers/media/video/s5p-mfc/regs-mfc.h
index a19bece..d2dfb06 100644
--- a/drivers/media/video/s5p-mfc/regs-mfc.h
+++ b/drivers/media/video/s5p-mfc/regs-mfc.h
@@ -144,6 +144,7 @@
 #define S5P_FIMV_ENC_PROFILE_H264_MAIN			0
 #define S5P_FIMV_ENC_PROFILE_H264_HIGH			1
 #define S5P_FIMV_ENC_PROFILE_H264_BASELINE		2
+#define S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE	3
 #define S5P_FIMV_ENC_PROFILE_MPEG4_SIMPLE		0
 #define S5P_FIMV_ENC_PROFILE_MPEG4_ADVANCED_SIMPLE	1
 #define S5P_FIMV_ENC_PIC_STRUCT		0x083c /* picture field/frame flag */
@@ -213,6 +214,7 @@
 #define S5P_FIMV_DEC_STATUS_RESOLUTION_MASK		(3<<4)
 #define S5P_FIMV_DEC_STATUS_RESOLUTION_INC		(1<<4)
 #define S5P_FIMV_DEC_STATUS_RESOLUTION_DEC		(2<<4)
+#define S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT		4
 
 /* Decode frame address */
 #define S5P_FIMV_DECODE_Y_ADR			0x2024
@@ -377,6 +379,16 @@
 #define S5P_FIMV_R2H_CMD_EDFU_INIT_RET		16
 #define S5P_FIMV_R2H_CMD_ERR_RET		32
 
+/* Dummy definition for MFCv6 compatibilty */
+#define S5P_FIMV_CODEC_H264_MVC_DEC		-1
+#define S5P_FIMV_R2H_CMD_FIELD_DONE_RET		-1
+#define S5P_FIMV_MFC_RESET			-1
+#define S5P_FIMV_RISC_ON			-1
+#define S5P_FIMV_RISC_BASE_ADDRESS		-1
+#define S5P_FIMV_CODEC_VP8_DEC			-1
+#define S5P_FIMV_REG_CLEAR_BEGIN		0
+#define S5P_FIMV_REG_CLEAR_COUNT		0
+
 /* Error handling defines */
 #define S5P_FIMV_ERR_WARNINGS_START		145
 #define S5P_FIMV_ERR_DEC_MASK			0xFFFF
@@ -414,5 +426,22 @@
 #define S5P_FIMV_SHARED_EXTENDED_SAR		0x0078
 #define S5P_FIMV_SHARED_H264_I_PERIOD		0x009C
 #define S5P_FIMV_SHARED_RC_CONTROL_CONFIG	0x00A0
+#define S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT	2
+
+#define S5P_FIMV_SHARED_FRAME_PACK_SEI_AVAIL    0x16C
+#define S5P_FIMV_SHARED_FRAME_PACK_ARRGMENT_ID  0x170
+#define S5P_FIMV_SHARED_FRAME_PACK_SEI_INFO     0x174
+#define S5P_FIMV_SHARED_FRAME_PACK_GRID_POS     0x178
+
+/* SEI related information */
+#define S5P_FIMV_FRAME_PACK_SEI_AVAIL           S5P_FIMV_SHARED_FRAME_PACK_SEI_AVAIL
+#define S5P_FIMV_FRAME_PACK_ARRGMENT_ID         S5P_FIMV_SHARED_FRAME_PACK_ARRGMENT_ID
+#define S5P_FIMV_FRAME_PACK_SEI_INFO            S5P_FIMV_SHARED_FRAME_PACK_SEI_INFO
+#define S5P_FIMV_FRAME_PACK_GRID_POS            S5P_FIMV_SHARED_FRAME_PACK_GRID_POS
+
+#define S5P_FIMV_SHARED_SET_E_FRAME_TAG		S5P_FIMV_SHARED_SET_FRAME_TAG
+#define S5P_FIMV_SHARED_GET_E_FRAME_TAG		S5P_FIMV_SHARED_GET_FRAME_TAG_TOP
+#define S5P_FIMV_ENCODED_LUMA_ADDR		S5P_FIMV_ENCODED_Y_ADDR
+#define S5P_FIMV_ENCODED_CHROMA_ADDR		S5P_FIMV_ENCODED_C_ADDR
 
 #endif /* _REGS_FIMV_H */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p-mfc/s5p_mfc.c
index 9bb68e7..bec94bc 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc.c
@@ -21,15 +21,13 @@
 #include <linux/videodev2.h>
 #include <linux/workqueue.h>
 #include <media/videobuf2-core.h>
-#include "regs-mfc.h"
+#include "s5p_mfc_common.h"
 #include "s5p_mfc_ctrl.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_dec.h"
 #include "s5p_mfc_enc.h"
 #include "s5p_mfc_intr.h"
-#include "s5p_mfc_opr.h"
 #include "s5p_mfc_pm.h"
-#include "s5p_mfc_shm.h"
 
 #define S5P_MFC_NAME		"s5p-mfc"
 #define S5P_MFC_DEC_NAME	"s5p-mfc-dec"
@@ -155,13 +153,6 @@ static enum s5p_mfc_node_type s5p_mfc_get_node_type(struct file *file)
 	return MFCNODE_INVALID;
 }
 
-static void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
-{
-	mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
-	mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
-	mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
-}
-
 static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_buf *dst_buf;
@@ -179,8 +170,8 @@ static void s5p_mfc_handle_frame_all_extracted(struct s5p_mfc_ctx *ctx)
 		ctx->dst_queue_cnt--;
 		dst_buf->b->v4l2_buf.sequence = (ctx->sequence++);
 
-		if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
-			s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
+		if (s5p_mfc_read_info(ctx, PIC_TIME_TOP) ==
+			s5p_mfc_read_info(ctx, PIC_TIME_BOT))
 			dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
 		else
 			dst_buf->b->v4l2_buf.field = V4L2_FIELD_INTERLACED;
@@ -195,7 +186,7 @@ static void s5p_mfc_handle_frame_copy_time(struct s5p_mfc_ctx *ctx)
 	struct s5p_mfc_dev *dev = ctx->dev;
 	struct s5p_mfc_buf  *dst_buf, *src_buf;
 	size_t dec_y_addr = s5p_mfc_get_dec_y_adr();
-	unsigned int frame_type = s5p_mfc_get_frame_type();
+	unsigned int frame_type = s5p_mfc_get_dec_frame_type();
 
 	/* Copy timestamp / timecode from decoded src to dst and set
 	   appropraite flags */
@@ -232,7 +223,7 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
 	struct s5p_mfc_dev *dev = ctx->dev;
 	struct s5p_mfc_buf  *dst_buf;
 	size_t dspl_y_addr = s5p_mfc_get_dspl_y_adr();
-	unsigned int frame_type = s5p_mfc_get_frame_type();
+	unsigned int frame_type = s5p_mfc_get_dec_frame_type();
 	unsigned int index;
 
 	/* If frame is same as previous then skip and do not dequeue */
@@ -251,8 +242,8 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
 			list_del(&dst_buf->list);
 			ctx->dst_queue_cnt--;
 			dst_buf->b->v4l2_buf.sequence = ctx->sequence;
-			if (s5p_mfc_read_shm(ctx, PIC_TIME_TOP) ==
-				s5p_mfc_read_shm(ctx, PIC_TIME_BOT))
+			if (s5p_mfc_read_info(ctx, PIC_TIME_TOP) ==
+				s5p_mfc_read_info(ctx, PIC_TIME_BOT))
 				dst_buf->b->v4l2_buf.field = V4L2_FIELD_NONE;
 			else
 				dst_buf->b->v4l2_buf.field =
@@ -285,12 +276,13 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
 
 	dst_frame_status = s5p_mfc_get_dspl_status()
 				& S5P_FIMV_DEC_STATUS_DECODING_STATUS_MASK;
-	res_change = s5p_mfc_get_dspl_status()
-				& S5P_FIMV_DEC_STATUS_RESOLUTION_MASK;
+	res_change = (s5p_mfc_get_dspl_status()
+				& S5P_FIMV_DEC_STATUS_RESOLUTION_MASK)
+				>> S5P_FIMV_DEC_STATUS_RESOLUTION_SHIFT;
 	mfc_debug(2, "Frame Status: %x\n", dst_frame_status);
 	if (ctx->state == MFCINST_RES_CHANGE_INIT)
 		ctx->state = MFCINST_RES_CHANGE_FLUSH;
-	if (res_change) {
+	if (res_change && res_change != 3) {
 		ctx->state = MFCINST_RES_CHANGE_INIT;
 		s5p_mfc_clear_int_flags(dev);
 		wake_up_ctx(ctx, reason, err);
@@ -333,7 +325,8 @@ static void s5p_mfc_handle_frame(struct s5p_mfc_ctx *ctx,
 								list);
 		ctx->consumed_stream += s5p_mfc_get_consumed_stream();
 		if (ctx->codec_mode != S5P_FIMV_CODEC_H264_DEC &&
-			s5p_mfc_get_frame_type() == S5P_FIMV_DECODE_FRAME_P_FRAME
+			s5p_mfc_get_dec_frame_type() ==
+					S5P_FIMV_DECODE_FRAME_P_FRAME
 					&& ctx->consumed_stream + STUFF_BYTE <
 					src_buf->b->v4l2_planes[0].bytesused) {
 			/* Run MFC again on the same buffer */
@@ -427,7 +420,6 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
 				 unsigned int reason, unsigned int err)
 {
 	struct s5p_mfc_dev *dev;
-	unsigned int guard_width, guard_height;
 
 	if (ctx == NULL)
 		return;
@@ -439,45 +431,28 @@ static void s5p_mfc_handle_seq_done(struct s5p_mfc_ctx *ctx,
 		ctx->img_width = s5p_mfc_get_img_width();
 		ctx->img_height = s5p_mfc_get_img_height();
 
-		ctx->buf_width = ALIGN(ctx->img_width,
-						S5P_FIMV_NV12MT_HALIGN);
-		ctx->buf_height = ALIGN(ctx->img_height,
-						S5P_FIMV_NV12MT_VALIGN);
-		mfc_debug(2, "SEQ Done: Movie dimensions %dx%d, "
-			"buffer dimensions: %dx%d\n", ctx->img_width,
-				ctx->img_height, ctx->buf_width,
-						ctx->buf_height);
-		if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
-			ctx->luma_size = ALIGN(ctx->buf_width *
-				ctx->buf_height, S5P_FIMV_DEC_BUF_ALIGN);
-			ctx->chroma_size = ALIGN(ctx->buf_width *
-					 ALIGN((ctx->img_height >> 1),
-					       S5P_FIMV_NV12MT_VALIGN),
-					       S5P_FIMV_DEC_BUF_ALIGN);
-			ctx->mv_size = ALIGN(ctx->buf_width *
-					ALIGN((ctx->buf_height >> 2),
-					S5P_FIMV_NV12MT_VALIGN),
-					S5P_FIMV_DEC_BUF_ALIGN);
-		} else {
-			guard_width = ALIGN(ctx->img_width + 24,
-					S5P_FIMV_NV12MT_HALIGN);
-			guard_height = ALIGN(ctx->img_height + 16,
-						S5P_FIMV_NV12MT_VALIGN);
-			ctx->luma_size = ALIGN(guard_width *
-				guard_height, S5P_FIMV_DEC_BUF_ALIGN);
-			guard_width = ALIGN(ctx->img_width + 16,
-						S5P_FIMV_NV12MT_HALIGN);
-			guard_height = ALIGN((ctx->img_height >> 1) + 4,
-						S5P_FIMV_NV12MT_VALIGN);
-			ctx->chroma_size = ALIGN(guard_width *
-				guard_height, S5P_FIMV_DEC_BUF_ALIGN);
-			ctx->mv_size = 0;
-		}
+		s5p_mfc_dec_calc_dpb_size(ctx);
+
 		ctx->dpb_count = s5p_mfc_get_dpb_count();
 		if (ctx->img_width == 0 || ctx->img_height == 0)
 			ctx->state = MFCINST_ERROR;
 		else
 			ctx->state = MFCINST_HEAD_PARSED;
+
+		if ((ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
+			ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC) &&
+				!list_empty(&ctx->src_queue)) {
+			struct s5p_mfc_buf *src_buf;
+			src_buf = list_entry(ctx->src_queue.next,
+					struct s5p_mfc_buf, list);
+			mfc_debug(2, "Check consumed size of header. ");
+			mfc_debug(2, "source : %d, consumed : %d\n",
+					s5p_mfc_get_consumed_stream(),
+					src_buf->b->v4l2_planes[0].bytesused);
+			if (s5p_mfc_get_consumed_stream() <
+					src_buf->b->v4l2_planes[0].bytesused)
+				ctx->remained = 1;
+		}
 	}
 	s5p_mfc_clear_int_flags(dev);
 	clear_work_bit(ctx);
@@ -508,7 +483,7 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
 	spin_unlock(&dev->condlock);
 	if (err == 0) {
 		ctx->state = MFCINST_RUNNING;
-		if (!ctx->dpb_flush_flag) {
+		if (!ctx->dpb_flush_flag && !ctx->remained) {
 			spin_lock_irqsave(&dev->irqlock, flags);
 			if (!list_empty(&ctx->src_queue)) {
 				src_buf = list_entry(ctx->src_queue.next,
@@ -567,6 +542,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
 		break;
 
 	case S5P_FIMV_R2H_CMD_SLICE_DONE_RET:
+	case S5P_FIMV_R2H_CMD_FIELD_DONE_RET:
 	case S5P_FIMV_R2H_CMD_FRAME_DONE_RET:
 		if (ctx->c_ops->post_frame_start) {
 			if (ctx->c_ops->post_frame_start(ctx))
@@ -679,6 +655,7 @@ static int s5p_mfc_open(struct file *file)
 	if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) {
 		ctx->type = MFCINST_DECODER;
 		ctx->c_ops = get_dec_codec_ops();
+		s5p_mfc_dec_init(ctx);
 		/* Setup ctrl handler */
 		ret = s5p_mfc_dec_ctrls_setup(ctx);
 		if (ret) {
@@ -691,6 +668,7 @@ static int s5p_mfc_open(struct file *file)
 		/* only for encoder */
 		INIT_LIST_HEAD(&ctx->ref_queue);
 		ctx->ref_queue_cnt = 0;
+		s5p_mfc_enc_init(ctx);
 		/* Setup ctrl handler */
 		ret = s5p_mfc_enc_ctrls_setup(ctx);
 		if (ret) {
@@ -842,6 +820,7 @@ static int s5p_mfc_release(struct file *file)
 		mfc_debug(2, "Last instance - release firmware\n");
 		/* reset <-> F/W release */
 		s5p_mfc_reset(dev);
+		s5p_mfc_deinit_hw(dev);
 		s5p_mfc_release_firmware(dev);
 		del_timer_sync(&dev->watchdog_timer);
 		if (s5p_mfc_power_off() < 0)
@@ -1086,6 +1065,9 @@ static int s5p_mfc_probe(struct platform_device *pdev)
 	dev->watchdog_timer.data = (unsigned long)dev;
 	dev->watchdog_timer.function = s5p_mfc_watchdog;
 
+	dev->variant = (struct s5p_mfc_variant *)
+		platform_get_device_id(pdev)->driver_data;
+
 	pr_debug("%s--\n", __func__);
 	return 0;
 
@@ -1205,9 +1187,74 @@ static const struct dev_pm_ops s5p_mfc_pm_ops = {
 			   NULL)
 };
 
+struct s5p_mfc_buf_size_v5 mfc_buf_size_v5 = {
+	.h264_ctx	= 0x96000,
+	.non_h264_ctx	= 0x2800,
+	.dsc		= 0x20000,
+	.shm		= 0x1000,
+};
+
+struct s5p_mfc_buf_size buf_size_v5 = {
+	.fw	= 0x60000,
+	.cpb	= 0x400000,	/*   4MB */
+	.priv	= &mfc_buf_size_v5,
+};
+
+struct s5p_mfc_buf_align mfc_buf_align_v5 = {
+	.base = 17,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v5 = {
+	.version	= 0x51,
+	.port_num	= 2,
+	.buf_size	= &buf_size_v5,
+	.buf_align	= &mfc_buf_align_v5,
+};
+
+struct s5p_mfc_buf_size_v6 mfc_buf_size_v6 = {
+	.dev_ctx	= 0x7000,	/*  28KB */
+	.h264_dec_ctx	= 0x200000,	/* 1.6MB */
+	.other_dec_ctx	= 0x5000,	/*  20KB */
+	.h264_enc_ctx	= 0x19000,	/* 100KB */
+	.other_enc_ctx	= 0x3000,	/*  12KB */
+};
+
+struct s5p_mfc_buf_size buf_size_v6 = {
+	.fw	= 0x100000,	/*   1MB */
+	.cpb	= 0x300000,	/*   3MB */
+	.priv	= &mfc_buf_size_v6,
+};
+
+struct s5p_mfc_buf_align mfc_buf_align_v6 = {
+	.base = 0,
+};
+
+static struct s5p_mfc_variant mfc_drvdata_v6 = {
+	.version	= 0x61,
+	.port_num	= 1,
+	.buf_size	= &buf_size_v6,
+	.buf_align	= &mfc_buf_align_v6,
+};
+
+static struct platform_device_id mfc_driver_ids[] = {
+	{
+		.name = "s5p-mfc",
+		.driver_data = (unsigned long)&mfc_drvdata_v5,
+	}, {
+		.name = "s5p-mfc-v5",
+		.driver_data = (unsigned long)&mfc_drvdata_v5,
+	}, {
+		.name = "s5p-mfc-v6",
+		.driver_data = (unsigned long)&mfc_drvdata_v6,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(platform, mfc_driver_ids);
+
 static struct platform_driver s5p_mfc_driver = {
-	.probe	= s5p_mfc_probe,
-	.remove	= __devexit_p(s5p_mfc_remove),
+	.probe		= s5p_mfc_probe,
+	.remove		= __devexit_p(s5p_mfc_remove),
+	.id_table	= mfc_driver_ids,
 	.driver	= {
 		.name	= S5P_MFC_NAME,
 		.owner	= THIS_MODULE,
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
index f0665ed..e3c64db 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
@@ -16,8 +16,8 @@
 #include "s5p_mfc_debug.h"
 
 /* This function is used to send a command to the MFC */
-static int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
-						struct s5p_mfc_cmd_args *args)
+int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
+				struct s5p_mfc_cmd_args *args)
 {
 	int cur_cmd;
 	unsigned long timeout;
@@ -81,7 +81,7 @@ int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
 	memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
 	h2r_args.arg[0] = ctx->codec_mode;
 	h2r_args.arg[1] = 0; /* no crc & no pixelcache */
-	h2r_args.arg[2] = ctx->ctx_ofs;
+	h2r_args.arg[2] = ctx->ctx.ofs;
 	h2r_args.arg[3] = ctx->ctx_size;
 	ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
 								&h2r_args);
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h
index 5ceebfe..5c9e662 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h
@@ -21,6 +21,9 @@ struct s5p_mfc_cmd_args {
 	unsigned int	arg[MAX_H2R_ARG];
 };
 
+int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
+	struct s5p_mfc_cmd_args *args);
+
 int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev);
 int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev);
 int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev);
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c b/drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c
new file mode 100644
index 0000000..6a631e0
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c
@@ -0,0 +1,96 @@
+/*
+ * linux/drivers/media/video/s5p-mfc/s5p_mfc_cmd_v6.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "s5p_mfc_common.h"
+
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_debug.h"
+#include "s5p_mfc_intr.h"
+
+int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
+				struct s5p_mfc_cmd_args *args)
+{
+	mfc_debug(2, "Issue the command: %d\n", cmd);
+
+	/* Reset RISC2HOST command */
+	mfc_write(dev, 0x0, S5P_FIMV_RISC2HOST_CMD);
+
+	/* Issue the command */
+	mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
+	mfc_write(dev, 0x1, S5P_FIMV_HOST2RISC_INT);
+
+	return 0;
+}
+
+int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev)
+{
+	struct s5p_mfc_cmd_args h2r_args;
+	struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
+
+	s5p_mfc_alloc_dev_context_buffer(dev);
+	mfc_write(dev, dev->ctx_buf.dma, S5P_FIMV_CONTEXT_MEM_ADDR);
+	mfc_write(dev, buf_size->dev_ctx, S5P_FIMV_CONTEXT_MEM_SIZE);
+	return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args);
+}
+
+int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev)
+{
+	struct s5p_mfc_cmd_args h2r_args;
+
+	memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+	return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
+}
+
+int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev)
+{
+	struct s5p_mfc_cmd_args h2r_args;
+
+	memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
+	return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_WAKEUP, &h2r_args);
+}
+
+/* Open a new instance and get its number */
+int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	struct s5p_mfc_cmd_args h2r_args;
+
+	mfc_debug(2, "Requested codec mode: %d\n", ctx->codec_mode);
+	dev->curr_ctx = ctx->num;
+	mfc_write(dev, ctx->codec_mode, S5P_FIMV_CODEC_TYPE);
+	mfc_write(dev, ctx->ctx.dma, S5P_FIMV_CONTEXT_MEM_ADDR);
+	mfc_write(dev, ctx->ctx_size, S5P_FIMV_CONTEXT_MEM_SIZE);
+	mfc_write(dev, 0, S5P_FIMV_D_CRC_CTRL); /* no crc */
+
+	return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
+					&h2r_args);
+}
+
+/* Close instance */
+int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	struct s5p_mfc_cmd_args h2r_args;
+	int ret = 0;
+
+	dev->curr_ctx = ctx->num;
+	if (ctx->state != MFCINST_FREE) {
+		mfc_write(dev, ctx->inst_no, S5P_FIMV_INSTANCE_ID);
+		ret = s5p_mfc_cmd_host2risc(dev,
+					S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
+					&h2r_args);
+	} else {
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_common.h b/drivers/media/video/s5p-mfc/s5p_mfc_common.h
index bd5706a..8c646f4 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_common.h
@@ -16,7 +16,6 @@
 #ifndef S5P_MFC_COMMON_H_
 #define S5P_MFC_COMMON_H_
 
-#include "regs-mfc.h"
 #include <linux/platform_device.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-ctrls.h>
@@ -34,10 +33,6 @@
 #define MFC_OFFSET_SHIFT	11
 
 #define FIRMWARE_ALIGN		0x20000		/* 128KB */
-#define MFC_H264_CTX_BUF_SIZE	0x96000		/* 600KB per H264 instance */
-#define MFC_CTX_BUF_SIZE	0x2800		/* 10KB per instance */
-#define DESC_BUF_SIZE		0x20000		/* 128KB for DESC buffer */
-#define SHARED_BUF_SIZE		0x2000		/* 8KB for shared buffer */
 
 #define DEF_CPB_SIZE		0x40000		/* 512KB */
 
@@ -174,6 +169,54 @@ struct s5p_mfc_pm {
 	struct device	*device;
 };
 
+struct s5p_mfc_buf_size_v5 {
+	unsigned int h264_ctx;
+	unsigned int non_h264_ctx;
+	unsigned int dsc;
+	unsigned int shm;
+};
+
+struct s5p_mfc_buf_size_v6 {
+	unsigned int dev_ctx;
+	unsigned int h264_dec_ctx;
+	unsigned int other_dec_ctx;
+	unsigned int h264_enc_ctx;
+	unsigned int other_enc_ctx;
+};
+
+struct s5p_mfc_buf_size {
+	unsigned int fw;
+	unsigned int cpb;
+	void *priv;
+};
+
+struct s5p_mfc_buf_align {
+	unsigned int base;
+};
+
+struct s5p_mfc_variant {
+	unsigned int version;
+	unsigned int port_num;
+	struct s5p_mfc_buf_size *buf_size;
+	struct s5p_mfc_buf_align *buf_align;
+};
+
+/**
+ * struct s5p_mfc_priv_buf - represents internal used buffer
+ * @alloc:		allocation-specific context for each buffer
+ *			(videobuf2 allocator)
+ * @ofs:		offset of each buffer, will be used for MFC
+ * @virt:		kernel virtual address, only valid when the
+ *			buffer accessed by driver
+ * @dma:		DMA address, only valid when kernel DMA API used
+ */
+struct s5p_mfc_priv_buf {
+	void		*alloc;
+	unsigned long	ofs;
+	void		*virt;
+	dma_addr_t	dma;
+};
+
 /**
  * struct s5p_mfc_dev - The struct containing driver internal parameters.
  *
@@ -209,6 +252,7 @@ struct s5p_mfc_pm {
  * @watchdog_work:	worker for the watchdog
  * @alloc_ctx:		videobuf2 allocator contexts for two memory banks
  * @enter_suspend:	flag set when entering suspend
+ * @ctx_buf:		common context memory (MFCv6)
  *
  */
 struct s5p_mfc_dev {
@@ -223,6 +267,7 @@ struct s5p_mfc_dev {
 	struct v4l2_ctrl_handler dec_ctrl_handler;
 	struct v4l2_ctrl_handler enc_ctrl_handler;
 	struct s5p_mfc_pm	pm;
+	struct s5p_mfc_variant	*variant;
 	int num_inst;
 	spinlock_t irqlock;	/* lock when operating on videobuf2 queues */
 	spinlock_t condlock;	/* lock when changing/checking if a context is
@@ -245,6 +290,8 @@ struct s5p_mfc_dev {
 	struct work_struct watchdog_work;
 	void *alloc_ctx[2];
 	unsigned long enter_suspend;
+
+	struct s5p_mfc_priv_buf ctx_buf;
 };
 
 /**
@@ -278,6 +325,23 @@ struct s5p_mfc_h264_enc_params {
 	enum v4l2_mpeg_video_h264_level level_v4l2;
 	int level;
 	u16 cpb_size;
+	int interlace;
+	u8 hier_qp;
+	u8 hier_qp_type;
+	u8 hier_qp_layer;
+	u8 hier_qp_layer_qp[7];
+	u8 sei_frame_packing;
+	u8 sei_fp_curr_frame_0;
+	u8 sei_fp_arrangement_type;
+
+	u8 fmo;
+	u8 fmo_map_type;
+	u8 fmo_slice_grp;
+	u8 fmo_chg_dir;
+	u32 fmo_chg_rate;
+	u32 fmo_run_len[4];
+	u8 aso;
+	u32 aso_slice_order[8];
 };
 
 /**
@@ -288,8 +352,6 @@ struct s5p_mfc_mpeg4_enc_params {
 	enum v4l2_mpeg_video_mpeg4_profile profile;
 	int quarter_pixel;
 	/* Common for MPEG4, H263 */
-	u16 vop_time_res;
-	u16 vop_frm_delta;
 	u8 rc_frame_qp;
 	u8 rc_min_qp;
 	u8 rc_max_qp;
@@ -316,9 +378,11 @@ struct s5p_mfc_enc_params {
 	u8 pad_cb;
 	u8 pad_cr;
 	int rc_frame;
+	int rc_mb;
 	u32 rc_bitrate;
 	u16 rc_reaction_coeff;
 	u16 vbv_size;
+	u32 vbv_delay;
 
 	enum v4l2_mpeg_video_header_mode seq_hdr_mode;
 	enum v4l2_mpeg_mfc51_video_frame_skip_mode frame_skip_mode;
@@ -327,7 +391,6 @@ struct s5p_mfc_enc_params {
 	u8 num_b_frame;
 	u32 rc_framerate_num;
 	u32 rc_framerate_denom;
-	int interlace;
 
 	union {
 		struct s5p_mfc_h264_enc_params h264;
@@ -470,6 +533,7 @@ struct s5p_mfc_ctx {
 	unsigned long consumed_stream;
 
 	unsigned int dpb_flush_flag;
+	unsigned int remained;
 
 	/* Buffers */
 	void *bank1_buf;
@@ -499,37 +563,42 @@ struct s5p_mfc_ctx {
 	int display_delay;
 	int display_delay_enable;
 	int after_packed_pb;
+	int sei_fp_parse;
 
 	int dpb_count;
 	int total_dpb_count;
 
 	/* Buffers */
-	void *ctx_buf;
-	size_t ctx_phys;
-	size_t ctx_ofs;
-	size_t ctx_size;
-
-	void *desc_buf;
-	size_t desc_phys;
-
-
-	void *shm_alloc;
-	void *shm;
-	size_t shm_ofs;
+	unsigned int ctx_size;
+	struct s5p_mfc_priv_buf ctx;
+	struct s5p_mfc_priv_buf dsc;
+	struct s5p_mfc_priv_buf shm;
 
 	struct s5p_mfc_enc_params enc_params;
 
 	size_t enc_dst_buf_size;
+	size_t luma_dpb_size;
+	size_t chroma_dpb_size;
+	size_t me_buffer_size;
+	size_t tmv_buffer_size;
 
 	enum v4l2_mpeg_mfc51_video_force_frame_type force_frame_type;
 
 	struct list_head ref_queue;
 	unsigned int ref_queue_cnt;
 
+	enum v4l2_mpeg_video_multi_slice_mode slice_mode;
+	union {
+		unsigned int mb;
+		unsigned int bits;
+	} slice_size;
+
 	struct s5p_mfc_codec_ops *c_ops;
 
 	struct v4l2_ctrl *ctrls[MFC_MAX_CTRLS];
 	struct v4l2_ctrl_handler ctrl_handler;
+	unsigned int frame_tag;
+	size_t scratch_buf_size;
 };
 
 /*
@@ -567,4 +636,18 @@ struct mfc_control {
 #define ctrl_to_ctx(__ctrl) \
 	container_of((__ctrl)->handler, struct s5p_mfc_ctx, ctrl_handler)
 
+#define HAS_PORTNUM(dev)	(dev ? (dev->variant ? \
+				(dev->variant->port_num ? 1 : 0) : 0) : 0)
+#define IS_TWOPORT(dev)		(dev->variant->port_num == 2 ? 1 : 0)
+#define IS_MFCV6(dev)		(dev->variant->version >= 0x60 ? 1 : 0)
+
+#if defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V5)
+#include "regs-mfc.h"
+#include "s5p_mfc_opr.h"
+#include "s5p_mfc_shm.h"
+#elif defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V6)
+#include "regs-mfc-v6.h"
+#include "s5p_mfc_opr_v6.h"
+#endif
+
 #endif /* S5P_MFC_COMMON_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
index 08a5cfe..65ff15d 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
@@ -15,7 +15,6 @@
 #include <linux/firmware.h>
 #include <linux/jiffies.h>
 #include <linux/sched.h>
-#include "regs-mfc.h"
 #include "s5p_mfc_cmd.h"
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
@@ -38,12 +37,12 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
 	 * into kernel. */
 	mfc_debug_enter();
 	err = request_firmware((const struct firmware **)&fw_blob,
-				     "s5p-mfc.fw", dev->v4l2_dev.dev);
+				     "mfc_fw.bin", dev->v4l2_dev.dev);
 	if (err != 0) {
 		mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
 		return -EINVAL;
 	}
-	dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN);
+	dev->fw_size = dev->variant->buf_size->fw;
 	if (s5p_mfc_bitproc_buf) {
 		mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
 		release_firmware(fw_blob);
@@ -77,28 +76,33 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
 		return -EIO;
 	}
 	dev->bank1 = s5p_mfc_bitproc_phys;
-	b_base = vb2_dma_contig_memops.alloc(
-		dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BANK2_ALIGN_ORDER);
-	if (IS_ERR(b_base)) {
-		vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
-		s5p_mfc_bitproc_phys = 0;
-		s5p_mfc_bitproc_buf = NULL;
-		mfc_err("Allocating bank2 base failed\n");
-	release_firmware(fw_blob);
-		return -ENOMEM;
-	}
-	bank2_base_phys = s5p_mfc_mem_cookie(
-		dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
-	vb2_dma_contig_memops.put(b_base);
-	if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
-		mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
-		vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
-		s5p_mfc_bitproc_phys = 0;
-		s5p_mfc_bitproc_buf = NULL;
-		release_firmware(fw_blob);
-		return -EIO;
+	if (HAS_PORTNUM(dev) && IS_TWOPORT(dev)) {
+		b_base = vb2_dma_contig_memops.alloc(
+			dev->alloc_ctx[MFC_BANK2_ALLOC_CTX],
+			1 << MFC_BANK2_ALIGN_ORDER);
+		if (IS_ERR(b_base)) {
+			vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
+			s5p_mfc_bitproc_phys = 0;
+			s5p_mfc_bitproc_buf = 0;
+			mfc_err("Allocating bank2 base failed\n");
+			release_firmware(fw_blob);
+			return -ENOMEM;
+		}
+		bank2_base_phys = s5p_mfc_mem_cookie(
+			dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
+		vb2_dma_contig_memops.put(b_base);
+		if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
+			mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
+			vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
+			s5p_mfc_bitproc_phys = 0;
+			s5p_mfc_bitproc_buf = 0;
+			release_firmware(fw_blob);
+			return -EIO;
+		}
+		dev->bank2 = bank2_base_phys;
+	} else {
+		dev->bank2 = dev->bank1;
 	}
-	dev->bank2 = bank2_base_phys;
 	memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
 	wmb();
 	release_firmware(fw_blob);
@@ -116,7 +120,7 @@ int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
 	 * into kernel. */
 	mfc_debug_enter();
 	err = request_firmware((const struct firmware **)&fw_blob,
-				     "s5p-mfc.fw", dev->v4l2_dev.dev);
+				     "mfc_fw.bin", dev->v4l2_dev.dev);
 	if (err != 0) {
 		mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
 		return -EINVAL;
@@ -157,46 +161,81 @@ int s5p_mfc_reset(struct s5p_mfc_dev *dev)
 {
 	unsigned int mc_status;
 	unsigned long timeout;
+	int i;
 
 	mfc_debug_enter();
-	/* Stop procedure */
-	/*  reset RISC */
-	mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
-	/*  All reset except for MC */
-	mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
-	mdelay(10);
-
-	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;
-		}
 
-		mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
+	if (IS_MFCV6(dev)) {
+		/* Reset IP */
+		/*  except RISC, reset */
+		mfc_write(dev, 0xFEE, S5P_FIMV_MFC_RESET);
+		/*  reset release */
+		mfc_write(dev, 0x0, S5P_FIMV_MFC_RESET);
 
-	} while (mc_status & 0x3);
+		/* Zero Initialization of MFC registers */
+		mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
+		mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
+		mfc_write(dev, 0, S5P_FIMV_FW_VERSION);
+
+		for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT; i++)
+			mfc_write(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN + (i*4));
+
+		/* Reset */
+		mfc_write(dev, 0, S5P_FIMV_RISC_ON);
+		mfc_write(dev, 0x1FFF, S5P_FIMV_MFC_RESET);
+		mfc_write(dev, 0, S5P_FIMV_MFC_RESET);
+	} else {
+		/* Stop procedure */
+		/*  reset RISC */
+		mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
+		/*  All reset except for MC */
+		mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
+		mdelay(10);
+
+		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;
+			}
+
+			mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
+
+		} while (mc_status & 0x3);
+
+		mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
+		mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
+	}
 
-	mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
-	mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
 	mfc_debug_leave();
 	return 0;
 }
 
 static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
 {
-	mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
-	mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
-	mfc_debug(2, "Bank1: %08x, Bank2: %08x\n", dev->bank1, dev->bank2);
+	if (IS_MFCV6(dev)) {
+		mfc_write(dev, dev->bank1, S5P_FIMV_RISC_BASE_ADDRESS);
+		mfc_debug(2, "Base Address : %08x\n", dev->bank1);
+	} else {
+		mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
+		mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
+		mfc_debug(2, "Bank1: %08x, Bank2: %08x\n",
+				dev->bank1, dev->bank2);
+	}
 }
 
 static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
 {
-	mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
-	mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
-	mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
-	mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
+	if (IS_MFCV6(dev)) {
+		/* Zero initialization should be done before RESET.
+		 * Nothing to do here. */
+	} else {
+		mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
+		mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
+		mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
+		mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
+	}
 }
 
 /* Initialize hardware */
@@ -224,7 +263,10 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
 	s5p_mfc_clear_cmds(dev);
 	/* 3. Release reset signal to the RISC */
 	s5p_mfc_clean_dev_int_flags(dev);
-	mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
+	if (IS_MFCV6(dev))
+		mfc_write(dev, 0x1, S5P_FIMV_RISC_ON);
+	else
+		mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
 	mfc_debug(2, "Will now wait for completion of firmware transfer\n");
 	if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
 		mfc_err("Failed to load firmware\n");
@@ -267,6 +309,17 @@ int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
 }
 
 
+/* Deinitialize hardware */
+void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev)
+{
+	s5p_mfc_clock_on();
+
+	s5p_mfc_reset(dev);
+	s5p_mfc_release_dev_context_buffer(dev);
+
+	s5p_mfc_clock_off();
+}
+
 int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
 {
 	int ret;
@@ -322,7 +375,10 @@ int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
 		return ret;
 	}
 	/* 4. Release reset signal to the RISC */
-	mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
+	if (IS_MFCV6(dev))
+		mfc_write(dev, 0x1, S5P_FIMV_RISC_ON);
+	else
+		mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
 	mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
 	if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) {
 		mfc_err("Failed to load firmware\n");
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
index 61dc23b..b72c8c6 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
@@ -20,6 +20,7 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev);
 int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev);
 
 int s5p_mfc_init_hw(struct s5p_mfc_dev *dev);
+void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev);
 
 int s5p_mfc_sleep(struct s5p_mfc_dev *dev);
 int s5p_mfc_wakeup(struct s5p_mfc_dev *dev);
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
index 4dd32fc..d4c6cf2 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
@@ -23,85 +23,113 @@
 #include <linux/workqueue.h>
 #include <media/v4l2-ctrls.h>
 #include <media/videobuf2-core.h>
-#include "regs-mfc.h"
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_dec.h"
 #include "s5p_mfc_intr.h"
-#include "s5p_mfc_opr.h"
 #include "s5p_mfc_pm.h"
-#include "s5p_mfc_shm.h"
+
+#define DEF_SRC_FMT	4
+#define DEF_DST_FMT	0
 
 static struct s5p_mfc_fmt formats[] = {
 	{
+		.name		= "4:2:0 2 Planes 16x16 Tiles",
+		.fourcc		= V4L2_PIX_FMT_NV12MT_16X16,
+		.codec_mode	= S5P_FIMV_CODEC_NONE,
+		.type		= MFC_FMT_RAW,
+		.num_planes	= 2,
+	},
+	{
 		.name		= "4:2:0 2 Planes 64x32 Tiles",
 		.fourcc		= V4L2_PIX_FMT_NV12MT,
 		.codec_mode	= S5P_FIMV_CODEC_NONE,
 		.type		= MFC_FMT_RAW,
 		.num_planes	= 2,
-	 },
+	},
+	{
+		.name		= "4:2:0 2 Planes Y/CbCr",
+		.fourcc		= V4L2_PIX_FMT_NV12M,
+		.codec_mode	= S5P_FIMV_CODEC_NONE,
+		.type		= MFC_FMT_RAW,
+		.num_planes	= 2,
+	},
+	{
+		.name		= "4:2:0 2 Planes Y/CrCb",
+		.fourcc		= V4L2_PIX_FMT_NV21M,
+		.codec_mode	= S5P_FIMV_CODEC_NONE,
+		.type		= MFC_FMT_RAW,
+		.num_planes	= 2,
+	},
 	{
-		.name = "4:2:0 2 Planes",
-		.fourcc = V4L2_PIX_FMT_NV12M,
-		.codec_mode = S5P_FIMV_CODEC_NONE,
-		.type = MFC_FMT_RAW,
-		.num_planes = 2,
+		.name		= "H264 Encoded Stream",
+		.fourcc		= V4L2_PIX_FMT_H264,
+		.codec_mode	= S5P_FIMV_CODEC_H264_DEC,
+		.type		= MFC_FMT_DEC,
+		.num_planes	= 1,
 	},
 	{
-		.name = "H264 Encoded Stream",
-		.fourcc = V4L2_PIX_FMT_H264,
-		.codec_mode = S5P_FIMV_CODEC_H264_DEC,
-		.type = MFC_FMT_DEC,
-		.num_planes = 1,
+		.name		= "H264/MVC Encoded Stream",
+		.fourcc		= V4L2_PIX_FMT_H264_MVC,
+		.codec_mode	= S5P_FIMV_CODEC_H264_MVC_DEC,
+		.type		= MFC_FMT_DEC,
+		.num_planes	= 1,
 	},
 	{
-		.name = "H263 Encoded Stream",
-		.fourcc = V4L2_PIX_FMT_H263,
-		.codec_mode = S5P_FIMV_CODEC_H263_DEC,
-		.type = MFC_FMT_DEC,
-		.num_planes = 1,
+		.name		= "H263 Encoded Stream",
+		.fourcc		= V4L2_PIX_FMT_H263,
+		.codec_mode	= S5P_FIMV_CODEC_H263_DEC,
+		.type		= MFC_FMT_DEC,
+		.num_planes	= 1,
 	},
 	{
-		.name = "MPEG1 Encoded Stream",
-		.fourcc = V4L2_PIX_FMT_MPEG1,
-		.codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
-		.type = MFC_FMT_DEC,
-		.num_planes = 1,
+		.name		= "MPEG1 Encoded Stream",
+		.fourcc		= V4L2_PIX_FMT_MPEG1,
+		.codec_mode	= S5P_FIMV_CODEC_MPEG2_DEC,
+		.type		= MFC_FMT_DEC,
+		.num_planes	= 1,
 	},
 	{
-		.name = "MPEG2 Encoded Stream",
-		.fourcc = V4L2_PIX_FMT_MPEG2,
-		.codec_mode = S5P_FIMV_CODEC_MPEG2_DEC,
-		.type = MFC_FMT_DEC,
-		.num_planes = 1,
+		.name		= "MPEG2 Encoded Stream",
+		.fourcc		= V4L2_PIX_FMT_MPEG2,
+		.codec_mode	= S5P_FIMV_CODEC_MPEG2_DEC,
+		.type		= MFC_FMT_DEC,
+		.num_planes	= 1,
 	},
 	{
-		.name = "MPEG4 Encoded Stream",
-		.fourcc = V4L2_PIX_FMT_MPEG4,
-		.codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
-		.type = MFC_FMT_DEC,
-		.num_planes = 1,
+		.name		= "MPEG4 Encoded Stream",
+		.fourcc		= V4L2_PIX_FMT_MPEG4,
+		.codec_mode	= S5P_FIMV_CODEC_MPEG4_DEC,
+		.type		= MFC_FMT_DEC,
+		.num_planes	= 1,
 	},
 	{
-		.name = "XviD Encoded Stream",
-		.fourcc = V4L2_PIX_FMT_XVID,
-		.codec_mode = S5P_FIMV_CODEC_MPEG4_DEC,
-		.type = MFC_FMT_DEC,
-		.num_planes = 1,
+		.name		= "XviD Encoded Stream",
+		.fourcc		= V4L2_PIX_FMT_XVID,
+		.codec_mode	= S5P_FIMV_CODEC_MPEG4_DEC,
+		.type		= MFC_FMT_DEC,
+		.num_planes	= 1,
 	},
 	{
-		.name = "VC1 Encoded Stream",
-		.fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,
-		.codec_mode = S5P_FIMV_CODEC_VC1_DEC,
-		.type = MFC_FMT_DEC,
-		.num_planes = 1,
+		.name		= "VC1 Encoded Stream",
+		.fourcc		= V4L2_PIX_FMT_VC1_ANNEX_G,
+		.codec_mode	= S5P_FIMV_CODEC_VC1_DEC,
+		.type		= MFC_FMT_DEC,
+		.num_planes	= 1,
 	},
 	{
-		.name = "VC1 RCV Encoded Stream",
-		.fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,
-		.codec_mode = S5P_FIMV_CODEC_VC1RCV_DEC,
-		.type = MFC_FMT_DEC,
-		.num_planes = 1,
+		.name		= "VC1 RCV Encoded Stream",
+		.fourcc		= V4L2_PIX_FMT_VC1_ANNEX_L,
+		.codec_mode	= S5P_FIMV_CODEC_VC1RCV_DEC,
+		.type		= MFC_FMT_DEC,
+		.num_planes	= 1,
+	},
+	{
+		.name		= "VC8 Encoded Stream",
+		.fourcc		= V4L2_PIX_FMT_VP8,
+		.codec_mode	= S5P_FIMV_CODEC_VP8_DEC,
+		.type		= MFC_FMT_DEC,
+		.num_planes	= 1,
 	},
 };
 
@@ -336,21 +364,35 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
 /* Try format */
 static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
 {
+	struct s5p_mfc_dev *dev = video_drvdata(file);
 	struct s5p_mfc_fmt *fmt;
 
-	if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-		mfc_err("This node supports decoding only\n");
-		return -EINVAL;
-	}
-	fmt = find_format(f, MFC_FMT_DEC);
-	if (!fmt) {
-		mfc_err("Unsupported format\n");
-		return -EINVAL;
-	}
-	if (fmt->type != MFC_FMT_DEC) {
-		mfc_err("\n");
-		return -EINVAL;
+	mfc_debug(2, "Type is %d\n", f->type);
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		fmt = find_format(f, MFC_FMT_DEC);
+		if (!fmt) {
+			mfc_err("Unsupported format for source.\n");
+			return -EINVAL;
+		}
+		if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
+			mfc_err("Not supported format.\n");
+			return -EINVAL;
+		}
+	} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		fmt = find_format(f, MFC_FMT_RAW);
+		if (!fmt) {
+			mfc_err("Unsupported format for destination.\n");
+			return -EINVAL;
+		}
+		if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
+			mfc_err("Not supported format.\n");
+			return -EINVAL;
+		} else if (fmt->fourcc != V4L2_PIX_FMT_NV12MT) {
+			mfc_err("Not supported format.\n");
+			return -EINVAL;
+		}
 	}
+
 	return 0;
 }
 
@@ -373,6 +415,26 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
 		ret = -EBUSY;
 		goto out;
 	}
+	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+		fmt = find_format(f, MFC_FMT_RAW);
+		if (!fmt) {
+			mfc_err("Unsupported format for source.\n");
+			return -EINVAL;
+		}
+		if (!IS_MFCV6(dev) && (fmt->fourcc != V4L2_PIX_FMT_NV12MT)) {
+			mfc_err("Not supported format.\n");
+			return -EINVAL;
+		} else if (IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
+			mfc_err("Not supported format.\n");
+			return -EINVAL;
+		}
+		ctx->dst_fmt = fmt;
+		mfc_debug_leave();
+		return ret;
+	} else if (f->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		mfc_err("Wrong type error for S_FMT : %d", f->type);
+		return -EINVAL;
+	}
 	fmt = find_format(f, MFC_FMT_DEC);
 	if (!fmt || fmt->codec_mode == S5P_FIMV_CODEC_NONE) {
 		mfc_err("Unknown codec\n");
@@ -385,6 +447,10 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
 		ret = -EINVAL;
 		goto out;
 	}
+	if (!IS_MFCV6(dev) && (fmt->fourcc == V4L2_PIX_FMT_VP8)) {
+		mfc_err("Not supported format.\n");
+		return -EINVAL;
+	}
 	ctx->src_fmt = fmt;
 	ctx->codec_mode = fmt->codec_mode;
 	mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
@@ -498,7 +564,7 @@ static int vidioc_reqbufs(struct file *file, void *priv,
 		}
 		s5p_mfc_try_run(dev);
 		s5p_mfc_wait_for_done_ctx(ctx,
-					 S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0);
+					S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0);
 	}
 	return ret;
 }
@@ -696,10 +762,10 @@ static int vidioc_g_crop(struct file *file, void *priv,
 			return -EINVAL;
 		}
 	if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) {
-		left = s5p_mfc_read_shm(ctx, CROP_INFO_H);
+		left = s5p_mfc_read_info(ctx, CROP_INFO_H);
 		right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT;
 		left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK;
-		top = s5p_mfc_read_shm(ctx, CROP_INFO_V);
+		top = s5p_mfc_read_info(ctx, CROP_INFO_V);
 		bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT;
 		top = top & S5P_FIMV_SHARED_CROP_TOP_MASK;
 		cr->c.left = left;
@@ -750,6 +816,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
 			void *allocators[])
 {
 	struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+	struct s5p_mfc_dev *dev = ctx->dev;
 
 	/* Video output for decoding (source)
 	 * this can be set after getting an instance */
@@ -785,7 +852,13 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
 	    vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 		psize[0] = ctx->luma_size;
 		psize[1] = ctx->chroma_size;
-		allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+
+		if (IS_MFCV6(dev))
+			allocators[0] =
+				ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+		else
+			allocators[0] =
+				ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
 		allocators[1] = ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
 	} else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
 		   ctx->state == MFCINST_INIT) {
@@ -1035,3 +1108,10 @@ void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx)
 		ctx->ctrls[i] = NULL;
 }
 
+void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx)
+{
+	ctx->src_fmt = &formats[DEF_SRC_FMT];
+	ctx->dst_fmt = &formats[DEF_DST_FMT];
+	mfc_debug(2, "Default src_fmt is %x, dest_fmt is %x\n",
+			(unsigned int)ctx->src_fmt, (unsigned int)ctx->dst_fmt);
+}
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_dec.h b/drivers/media/video/s5p-mfc/s5p_mfc_dec.h
index fb8b215..c53baf8 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_dec.h
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_dec.h
@@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void);
 struct s5p_mfc_fmt *get_dec_def_fmt(bool src);
 int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx);
 void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx);
 
 #endif /* S5P_MFC_DEC_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
index 03d8334..645a8ef 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
@@ -24,48 +24,63 @@
 #include <linux/workqueue.h>
 #include <media/v4l2-ctrls.h>
 #include <media/videobuf2-core.h>
-#include "regs-mfc.h"
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_enc.h"
 #include "s5p_mfc_intr.h"
-#include "s5p_mfc_opr.h"
+
+#define DEF_SRC_FMT	2
+#define DEF_DST_FMT	4
 
 static struct s5p_mfc_fmt formats[] = {
 	{
-		.name = "4:2:0 2 Planes 64x32 Tiles",
-		.fourcc = V4L2_PIX_FMT_NV12MT,
-		.codec_mode = S5P_FIMV_CODEC_NONE,
-		.type = MFC_FMT_RAW,
-		.num_planes = 2,
+		.name		= "4:2:0 2 Planes 16x16 Tiles",
+		.fourcc		= V4L2_PIX_FMT_NV12MT_16X16,
+		.codec_mode	= S5P_FIMV_CODEC_NONE,
+		.type		= MFC_FMT_RAW,
+		.num_planes	= 2,
+	},
+	{
+		.name		= "4:2:0 2 Planes 64x32 Tiles",
+		.fourcc		= V4L2_PIX_FMT_NV12MT,
+		.codec_mode	= S5P_FIMV_CODEC_NONE,
+		.type		= MFC_FMT_RAW,
+		.num_planes	= 2,
+	},
+	{
+		.name		= "4:2:0 2 Planes Y/CbCr",
+		.fourcc		= V4L2_PIX_FMT_NV12M,
+		.codec_mode	= S5P_FIMV_CODEC_NONE,
+		.type		= MFC_FMT_RAW,
+		.num_planes	= 2,
 	},
 	{
-		.name = "4:2:0 2 Planes",
-		.fourcc = V4L2_PIX_FMT_NV12M,
-		.codec_mode = S5P_FIMV_CODEC_NONE,
-		.type = MFC_FMT_RAW,
-		.num_planes = 2,
+		.name		= "4:2:0 2 Planes Y/CrCb",
+		.fourcc		= V4L2_PIX_FMT_NV21M,
+		.codec_mode	= S5P_FIMV_CODEC_NONE,
+		.type		= MFC_FMT_RAW,
+		.num_planes	= 2,
 	},
 	{
-		.name = "H264 Encoded Stream",
-		.fourcc = V4L2_PIX_FMT_H264,
-		.codec_mode = S5P_FIMV_CODEC_H264_ENC,
-		.type = MFC_FMT_ENC,
-		.num_planes = 1,
+		.name		= "H264 Encoded Stream",
+		.fourcc		= V4L2_PIX_FMT_H264,
+		.codec_mode	= S5P_FIMV_CODEC_H264_ENC,
+		.type		= MFC_FMT_ENC,
+		.num_planes	= 1,
 	},
 	{
-		.name = "MPEG4 Encoded Stream",
-		.fourcc = V4L2_PIX_FMT_MPEG4,
-		.codec_mode = S5P_FIMV_CODEC_MPEG4_ENC,
-		.type = MFC_FMT_ENC,
-		.num_planes = 1,
+		.name		= "MPEG4 Encoded Stream",
+		.fourcc		= V4L2_PIX_FMT_MPEG4,
+		.codec_mode	= S5P_FIMV_CODEC_MPEG4_ENC,
+		.type		= MFC_FMT_ENC,
+		.num_planes	= 1,
 	},
 	{
-		.name = "H263 Encoded Stream",
-		.fourcc = V4L2_PIX_FMT_H263,
-		.codec_mode = S5P_FIMV_CODEC_H263_ENC,
-		.type = MFC_FMT_ENC,
-		.num_planes = 1,
+		.name		= "H263 Encoded Stream",
+		.fourcc		= V4L2_PIX_FMT_H263,
+		.codec_mode	= S5P_FIMV_CODEC_H263_ENC,
+		.type		= MFC_FMT_ENC,
+		.num_planes	= 1,
 	},
 };
 
@@ -641,13 +656,22 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
 		vb2_buffer_done(dst_mb->b, VB2_BUF_STATE_DONE);
 		spin_unlock_irqrestore(&dev->irqlock, flags);
 	}
-	ctx->state = MFCINST_RUNNING;
-	if (s5p_mfc_ctx_ready(ctx)) {
-		spin_lock_irqsave(&dev->condlock, flags);
-		set_bit(ctx->num, &dev->ctx_work_bits);
-		spin_unlock_irqrestore(&dev->condlock, flags);
+
+	if (IS_MFCV6(dev)) {
+		ctx->state = MFCINST_HEAD_PARSED; /* for INIT_BUFFER cmd */
+	} else {
+		ctx->state = MFCINST_RUNNING;
+		if (s5p_mfc_ctx_ready(ctx)) {
+			spin_lock_irqsave(&dev->condlock, flags);
+			set_bit(ctx->num, &dev->ctx_work_bits);
+			spin_unlock_irqrestore(&dev->condlock, flags);
+		}
+		s5p_mfc_try_run(dev);
 	}
-	s5p_mfc_try_run(dev);
+
+	if (IS_MFCV6(dev))
+		ctx->dpb_count = s5p_mfc_get_enc_dpb_count();
+
 	return 0;
 }
 
@@ -961,6 +985,17 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
 			mfc_err("failed to set output format\n");
 			return -EINVAL;
 		}
+
+		if (!IS_MFCV6(dev) &&
+				(fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)) {
+			mfc_err("Not supported format.\n");
+			return -EINVAL;
+		} else if (IS_MFCV6(dev) &&
+				(fmt->fourcc == V4L2_PIX_FMT_NV12MT)) {
+			mfc_err("Not supported format.\n");
+			return -EINVAL;
+		}
+
 		if (fmt->num_planes != pix_fmt_mp->num_planes) {
 			mfc_err("failed to set output format\n");
 			ret = -EINVAL;
@@ -973,45 +1008,13 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
 		mfc_debug(2, "fmt - w: %d, h: %d, ctx - w: %d, h: %d\n",
 			pix_fmt_mp->width, pix_fmt_mp->height,
 			ctx->img_width, ctx->img_height);
-		if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
-			ctx->buf_width = ALIGN(ctx->img_width,
-							S5P_FIMV_NV12M_HALIGN);
-			ctx->luma_size = ALIGN(ctx->img_width,
-				S5P_FIMV_NV12M_HALIGN) * ALIGN(ctx->img_height,
-				S5P_FIMV_NV12M_LVALIGN);
-			ctx->chroma_size = ALIGN(ctx->img_width,
-				S5P_FIMV_NV12M_HALIGN) * ALIGN((ctx->img_height
-				>> 1), S5P_FIMV_NV12M_CVALIGN);
-
-			ctx->luma_size = ALIGN(ctx->luma_size,
-							S5P_FIMV_NV12M_SALIGN);
-			ctx->chroma_size = ALIGN(ctx->chroma_size,
-							S5P_FIMV_NV12M_SALIGN);
-
-			pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
-			pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
-			pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
-			pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
-
-		} else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
-			ctx->buf_width = ALIGN(ctx->img_width,
-							S5P_FIMV_NV12MT_HALIGN);
-			ctx->luma_size = ALIGN(ctx->img_width,
-				S5P_FIMV_NV12MT_HALIGN)	* ALIGN(ctx->img_height,
-				S5P_FIMV_NV12MT_VALIGN);
-			ctx->chroma_size = ALIGN(ctx->img_width,
-				S5P_FIMV_NV12MT_HALIGN) * ALIGN((ctx->img_height
-				>> 1), S5P_FIMV_NV12MT_VALIGN);
-			ctx->luma_size = ALIGN(ctx->luma_size,
-							S5P_FIMV_NV12MT_SALIGN);
-			ctx->chroma_size = ALIGN(ctx->chroma_size,
-							S5P_FIMV_NV12MT_SALIGN);
-
-			pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
-			pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
-			pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
-			pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
-		}
+
+		s5p_mfc_enc_calc_src_size(ctx);
+		pix_fmt_mp->plane_fmt[0].sizeimage = ctx->luma_size;
+		pix_fmt_mp->plane_fmt[0].bytesperline = ctx->buf_width;
+		pix_fmt_mp->plane_fmt[1].sizeimage = ctx->chroma_size;
+		pix_fmt_mp->plane_fmt[1].bytesperline = ctx->buf_width;
+
 		ctx->src_bufs_cnt = 0;
 		ctx->output_state = QUEUE_FREE;
 	} else {
@@ -1026,6 +1029,7 @@ out:
 static int vidioc_reqbufs(struct file *file, void *priv,
 					  struct v4l2_requestbuffers *reqbufs)
 {
+	struct s5p_mfc_dev *dev = video_drvdata(file);
 	struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
 	int ret = 0;
 
@@ -1045,12 +1049,15 @@ static int vidioc_reqbufs(struct file *file, void *priv,
 			return ret;
 		}
 		ctx->capture_state = QUEUE_BUFS_REQUESTED;
-		ret = s5p_mfc_alloc_codec_buffers(ctx);
-		if (ret) {
-			mfc_err("Failed to allocate encoding buffers\n");
-			reqbufs->count = 0;
-			ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
-			return -ENOMEM;
+
+		if (!IS_MFCV6(dev)) {
+			ret = s5p_mfc_alloc_codec_buffers(ctx);
+			if (ret) {
+				mfc_err("Failed to allocate encoding buffers\n");
+				reqbufs->count = 0;
+				ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
+				return -ENOMEM;
+			}
 		}
 	} else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 		if (ctx->output_state != QUEUE_FREE) {
@@ -1297,6 +1304,13 @@ static int s5p_mfc_enc_s_ctrl(struct v4l2_ctrl *ctrl)
 			p->codec.h264.profile =
 				S5P_FIMV_ENC_PROFILE_H264_BASELINE;
 			break;
+		case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE:
+			if (IS_MFCV6(dev))
+				p->codec.h264.profile =
+				S5P_FIMV_ENC_PROFILE_H264_CONSTRAINED_BASELINE;
+			else
+				ret = -EINVAL;
+			break;
 		default:
 			ret = -EINVAL;
 		}
@@ -1516,6 +1530,7 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
 			unsigned int psize[], void *allocators[])
 {
 	struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);
+	struct s5p_mfc_dev *dev = ctx->dev;
 
 	if (ctx->state != MFCINST_GOT_INST) {
 		mfc_err("inavlid state: %d\n", ctx->state);
@@ -1544,8 +1559,17 @@ static int s5p_mfc_queue_setup(struct vb2_queue *vq,
 			*buf_count = MFC_MAX_BUFFERS;
 		psize[0] = ctx->luma_size;
 		psize[1] = ctx->chroma_size;
-		allocators[0] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
-		allocators[1] = ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+		if (IS_MFCV6(dev)) {
+			allocators[0] =
+				ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+			allocators[1] =
+				ctx->dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+		} else {
+			allocators[0] =
+				ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+			allocators[1] =
+				ctx->dev->alloc_ctx[MFC_BANK2_ALLOC_CTX];
+		}
 	} else {
 		mfc_err("inavlid queue type: %d\n", vq->type);
 		return -EINVAL;
@@ -1826,3 +1850,10 @@ void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx)
 	for (i = 0; i < NUM_CTRLS; i++)
 		ctx->ctrls[i] = NULL;
 }
+
+void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx)
+{
+	ctx->src_fmt = &formats[DEF_SRC_FMT];
+	ctx->dst_fmt = &formats[DEF_DST_FMT];
+}
+
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_enc.h b/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
index 405bdd3..413f22f 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
@@ -19,5 +19,6 @@ const struct v4l2_ioctl_ops *get_enc_v4l2_ioctl_ops(void);
 struct s5p_mfc_fmt *get_enc_def_fmt(bool src);
 int s5p_mfc_enc_ctrls_setup(struct s5p_mfc_ctx *ctx);
 void s5p_mfc_enc_ctrls_delete(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_enc_init(struct s5p_mfc_ctx *ctx);
 
 #endif /* S5P_MFC_ENC_H_  */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_intr.c b/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
index 8f2f8bf..dfdc558 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_intr.c
@@ -17,7 +17,6 @@
 #include <linux/io.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
-#include "regs-mfc.h"
 #include "s5p_mfc_common.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_intr.h"
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
index e6217cb..1fd9c92 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr.c
@@ -12,15 +12,12 @@
  * published by the Free Software Foundation.
  */
 
-#include "regs-mfc.h"
-#include "s5p_mfc_cmd.h"
 #include "s5p_mfc_common.h"
+#include "s5p_mfc_cmd.h"
 #include "s5p_mfc_ctrl.h"
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_intr.h"
-#include "s5p_mfc_opr.h"
 #include "s5p_mfc_pm.h"
-#include "s5p_mfc_shm.h"
 #include <asm/cacheflush.h>
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
@@ -37,39 +34,31 @@
 /* Allocate temporary buffers for decoding */
 int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx)
 {
-	void *desc_virt;
 	struct s5p_mfc_dev *dev = ctx->dev;
+	struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
 
-	ctx->desc_buf = vb2_dma_contig_memops.alloc(
-			dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], DESC_BUF_SIZE);
-	if (IS_ERR_VALUE((int)ctx->desc_buf)) {
-		ctx->desc_buf = NULL;
+	ctx->dsc.alloc = vb2_dma_contig_memops.alloc(
+			dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
+			buf_size->dsc);
+	if (IS_ERR_VALUE((int)ctx->dsc.alloc)) {
+		ctx->dsc.alloc = NULL;
 		mfc_err("Allocating DESC buffer failed\n");
 		return -ENOMEM;
 	}
-	ctx->desc_phys = s5p_mfc_mem_cookie(
-			dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->desc_buf);
-	BUG_ON(ctx->desc_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
-	desc_virt = vb2_dma_contig_memops.vaddr(ctx->desc_buf);
-	if (desc_virt == NULL) {
-		vb2_dma_contig_memops.put(ctx->desc_buf);
-		ctx->desc_phys = 0;
-		ctx->desc_buf = NULL;
-		mfc_err("Remapping DESC buffer failed\n");
-		return -ENOMEM;
-	}
-	memset(desc_virt, 0, DESC_BUF_SIZE);
-	wmb();
+	ctx->dsc.dma = s5p_mfc_mem_cookie(
+			dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->dsc.alloc);
+	BUG_ON(ctx->dsc.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+
 	return 0;
 }
 
 /* Release temporary buffers for decoding */
 void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
 {
-	if (ctx->desc_phys) {
-		vb2_dma_contig_memops.put(ctx->desc_buf);
-		ctx->desc_phys = 0;
-		ctx->desc_buf = NULL;
+	if (ctx->dsc.dma) {
+		vb2_dma_contig_memops.put(ctx->dsc.alloc);
+		ctx->dsc.alloc = NULL;
+		ctx->dsc.dma = 0;
 	}
 }
 
@@ -231,41 +220,43 @@ void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx)
 /* Allocate memory for instance data buffer */
 int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx)
 {
-	void *context_virt;
 	struct s5p_mfc_dev *dev = ctx->dev;
+	struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
 
 	if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
 		ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
-		ctx->ctx_size = MFC_H264_CTX_BUF_SIZE;
+		ctx->ctx_size = buf_size->h264_ctx;
 	else
-		ctx->ctx_size = MFC_CTX_BUF_SIZE;
-	ctx->ctx_buf = vb2_dma_contig_memops.alloc(
+		ctx->ctx_size = buf_size->non_h264_ctx;
+	ctx->ctx.alloc = vb2_dma_contig_memops.alloc(
 		dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size);
-	if (IS_ERR(ctx->ctx_buf)) {
+	if (IS_ERR(ctx->ctx.alloc)) {
 		mfc_err("Allocating context buffer failed\n");
-		ctx->ctx_phys = 0;
-		ctx->ctx_buf = NULL;
+		ctx->ctx.alloc = NULL;
 		return -ENOMEM;
 	}
-	ctx->ctx_phys = s5p_mfc_mem_cookie(
-		dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_buf);
-	BUG_ON(ctx->ctx_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
-	ctx->ctx_ofs = OFFSETA(ctx->ctx_phys);
-	context_virt = vb2_dma_contig_memops.vaddr(ctx->ctx_buf);
-	if (context_virt == NULL) {
+	ctx->ctx.dma = s5p_mfc_mem_cookie(
+		dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc);
+	BUG_ON(ctx->ctx.dma & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+	ctx->ctx.ofs = OFFSETA(ctx->ctx.dma);
+	ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc);
+	if (!ctx->ctx.virt) {
 		mfc_err("Remapping instance buffer failed\n");
-		vb2_dma_contig_memops.put(ctx->ctx_buf);
-		ctx->ctx_phys = 0;
-		ctx->ctx_buf = NULL;
+		vb2_dma_contig_memops.put(ctx->ctx.alloc);
+		ctx->ctx.alloc = NULL;
+		ctx->ctx.ofs = 0;
+		ctx->ctx.dma = 0;
 		return -ENOMEM;
 	}
 	/* Zero content of the allocated memory */
-	memset(context_virt, 0, ctx->ctx_size);
+	memset(ctx->ctx.virt, 0, ctx->ctx_size);
 	wmb();
 	if (s5p_mfc_init_shm(ctx) < 0) {
-		vb2_dma_contig_memops.put(ctx->ctx_buf);
-		ctx->ctx_phys = 0;
-		ctx->ctx_buf = NULL;
+		vb2_dma_contig_memops.put(ctx->ctx.alloc);
+		ctx->ctx.alloc = NULL;
+		ctx->ctx.ofs = 0;
+		ctx->ctx.virt = NULL;
+		ctx->ctx.dma = 0;
 		return -ENOMEM;
 	}
 	return 0;
@@ -274,15 +265,100 @@ int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx)
 /* Release instance buffer */
 void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx)
 {
-	if (ctx->ctx_buf) {
-		vb2_dma_contig_memops.put(ctx->ctx_buf);
-		ctx->ctx_phys = 0;
-		ctx->ctx_buf = NULL;
+	if (ctx->ctx.alloc) {
+		vb2_dma_contig_memops.put(ctx->ctx.alloc);
+		ctx->ctx.alloc = NULL;
+		ctx->ctx.ofs = 0;
+		ctx->ctx.virt = NULL;
+		ctx->ctx.dma = 0;
 	}
-	if (ctx->shm_alloc) {
-		vb2_dma_contig_memops.put(ctx->shm_alloc);
-		ctx->shm_alloc = NULL;
-		ctx->shm = NULL;
+	if (ctx->shm.alloc) {
+		vb2_dma_contig_memops.put(ctx->shm.alloc);
+		ctx->shm.alloc = NULL;
+		ctx->shm.ofs = 0;
+		ctx->shm.virt = NULL;
+	}
+}
+
+int s5p_mfc_alloc_dev_context_buffer(struct s5p_mfc_dev *dev)
+{
+	/* NOP */
+
+	return 0;
+}
+
+void s5p_mfc_release_dev_context_buffer(struct s5p_mfc_dev *dev)
+{
+	/* NOP */
+}
+
+void s5p_mfc_dec_calc_dpb_size(struct s5p_mfc_ctx *ctx)
+{
+	unsigned int guard_width, guard_height;
+
+	ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
+	ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+	mfc_debug(2,
+		"SEQ Done: Movie dimensions %dx%d, buffer dimensions: %dx%d\n",
+		ctx->img_width,	ctx->img_height, ctx->buf_width,
+		ctx->buf_height);
+
+	if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC) {
+		ctx->luma_size = ALIGN(ctx->buf_width * ctx->buf_height,
+				S5P_FIMV_DEC_BUF_ALIGN);
+		ctx->chroma_size = ALIGN(ctx->buf_width *
+				ALIGN((ctx->img_height >> 1),
+					S5P_FIMV_NV12MT_VALIGN),
+				S5P_FIMV_DEC_BUF_ALIGN);
+		ctx->mv_size = ALIGN(ctx->buf_width *
+				ALIGN((ctx->buf_height >> 2),
+					S5P_FIMV_NV12MT_VALIGN),
+				S5P_FIMV_DEC_BUF_ALIGN);
+	} else {
+		guard_width =
+			ALIGN(ctx->img_width + 24, S5P_FIMV_NV12MT_HALIGN);
+		guard_height =
+			ALIGN(ctx->img_height + 16, S5P_FIMV_NV12MT_VALIGN);
+		ctx->luma_size = ALIGN(guard_width * guard_height,
+				S5P_FIMV_DEC_BUF_ALIGN);
+
+		guard_width =
+			ALIGN(ctx->img_width + 16, S5P_FIMV_NV12MT_HALIGN);
+		guard_height =
+			ALIGN((ctx->img_height >> 1) + 4,
+					S5P_FIMV_NV12MT_VALIGN);
+		ctx->chroma_size = ALIGN(guard_width * guard_height,
+				S5P_FIMV_DEC_BUF_ALIGN);
+
+		ctx->mv_size = 0;
+	}
+}
+
+void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx)
+{
+	if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
+		ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN);
+
+		ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
+			* ALIGN(ctx->img_height, S5P_FIMV_NV12M_LVALIGN);
+		ctx->chroma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN)
+			* ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12M_CVALIGN);
+
+		ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12M_SALIGN);
+		ctx->chroma_size =
+			ALIGN(ctx->chroma_size, S5P_FIMV_NV12M_SALIGN);
+	} else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT) {
+		ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
+
+		ctx->luma_size = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+			* ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+		ctx->chroma_size =
+			ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN)
+			* ALIGN((ctx->img_height >> 1), S5P_FIMV_NV12MT_VALIGN);
+
+		ctx->luma_size = ALIGN(ctx->luma_size, S5P_FIMV_NV12MT_SALIGN);
+		ctx->chroma_size =
+			ALIGN(ctx->chroma_size, S5P_FIMV_NV12MT_SALIGN);
 	}
 }
 
@@ -290,16 +366,17 @@ void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx)
 void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
+	struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
 
-	mfc_write(dev, OFFSETA(ctx->desc_phys), S5P_FIMV_SI_CH0_DESC_ADR);
-	mfc_write(dev, DESC_BUF_SIZE, S5P_FIMV_SI_CH0_DESC_SIZE);
+	mfc_write(dev, OFFSETA(ctx->dsc.dma), S5P_FIMV_SI_CH0_DESC_ADR);
+	mfc_write(dev, buf_size->dsc, S5P_FIMV_SI_CH0_DESC_SIZE);
 }
 
 /* Set registers for shared buffer */
 static void s5p_mfc_set_shared_buffer(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
-	mfc_write(dev, ctx->shm_ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
+	mfc_write(dev, ctx->shm.ofs, S5P_FIMV_SI_CH0_HOST_WR_ADR);
 }
 
 /* Set registers for decoding stream buffer */
@@ -311,7 +388,7 @@ int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
 	mfc_write(dev, OFFSETA(buf_addr), S5P_FIMV_SI_CH0_SB_ST_ADR);
 	mfc_write(dev, ctx->dec_src_buf_size, S5P_FIMV_SI_CH0_CPB_SIZE);
 	mfc_write(dev, buf_size, S5P_FIMV_SI_CH0_SB_FRM_SIZE);
-	s5p_mfc_write_shm(ctx, start_num_byte, START_BYTE_NUM);
+	s5p_mfc_write_info(ctx, start_num_byte, START_BYTE_NUM);
 	return 0;
 }
 
@@ -438,10 +515,10 @@ int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx)
 		mfc_debug(2, "Not enough memory has been allocated\n");
 		return -ENOMEM;
 	}
-	s5p_mfc_write_shm(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
-	s5p_mfc_write_shm(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
+	s5p_mfc_write_info(ctx, frame_size, ALLOC_LUMA_DPB_SIZE);
+	s5p_mfc_write_info(ctx, frame_size_ch, ALLOC_CHROMA_DPB_SIZE);
 	if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC)
-		s5p_mfc_write_shm(ctx, frame_size_mv, ALLOC_MV_SIZE);
+		s5p_mfc_write_info(ctx, frame_size_mv, ALLOC_MV_SIZE);
 	mfc_write(dev, ((S5P_FIMV_CH_INIT_BUFS & S5P_FIMV_CH_MASK)
 					<< S5P_FIMV_CH_SHIFT) | (ctx->inst_no),
 						S5P_FIMV_SI_CH0_INST_ID);
@@ -685,16 +762,16 @@ static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
 	/* reaction coefficient */
 	if (p->rc_frame)
 		mfc_write(dev, p->rc_reaction_coeff, S5P_FIMV_ENC_RC_RPARA);
-	shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
+	shm = s5p_mfc_read_info(ctx, EXT_ENC_CONTROL);
 	/* seq header ctrl */
 	shm &= ~(0x1 << 3);
 	shm |= (p->seq_hdr_mode << 3);
 	/* frame skip mode */
 	shm &= ~(0x3 << 1);
 	shm |= (p->frame_skip_mode << 1);
-	s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
+	s5p_mfc_write_info(ctx, shm, EXT_ENC_CONTROL);
 	/* fixed target bit */
-	s5p_mfc_write_shm(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
+	s5p_mfc_write_info(ctx, p->fixed_target_bit, RC_CONTROL_CONFIG);
 	return 0;
 }
 
@@ -723,9 +800,9 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
 	reg |= p_264->profile;
 	mfc_write(dev, reg, S5P_FIMV_ENC_PROFILE);
 	/* interlace  */
-	mfc_write(dev, p->interlace, S5P_FIMV_ENC_PIC_STRUCT);
+	mfc_write(dev, p_264->interlace, S5P_FIMV_ENC_PIC_STRUCT);
 	/* height */
-	if (p->interlace)
+	if (p_264->interlace)
 		mfc_write(dev, ctx->img_height >> 1, S5P_FIMV_ENC_VSIZE_PX);
 	/* loopfilter ctrl */
 	mfc_write(dev, p_264->loop_filter_mode, S5P_FIMV_ENC_LF_CTRL);
@@ -767,7 +844,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
 	reg = mfc_read(dev, S5P_FIMV_ENC_RC_CONFIG);
 	/* macroblock level rate control */
 	reg &= ~(0x1 << 8);
-	reg |= (p_264->rc_mb << 8);
+	reg |= (p->rc_mb << 8);
 	/* frame QP */
 	reg &= ~(0x3F);
 	reg |= p_264->rc_frame_qp;
@@ -788,7 +865,7 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
 	reg |= p_264->rc_min_qp;
 	mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
 	/* macroblock adaptive scaling features */
-	if (p_264->rc_mb) {
+	if (p->rc_mb) {
 		reg = mfc_read(dev, S5P_FIMV_ENC_RC_MB_CTRL);
 		/* dark region */
 		reg &= ~(0x1 << 3);
@@ -804,37 +881,36 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
 		reg |= p_264->rc_mb_activity;
 		mfc_write(dev, reg, S5P_FIMV_ENC_RC_MB_CTRL);
 	}
-	if (!p->rc_frame &&
-	    !p_264->rc_mb) {
-		shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
+	if (!p->rc_frame && !p->rc_mb) {
+		shm = s5p_mfc_read_info(ctx, P_B_FRAME_QP);
 		shm &= ~(0xFFF);
 		shm |= ((p_264->rc_b_frame_qp & 0x3F) << 6);
 		shm |= (p_264->rc_p_frame_qp & 0x3F);
-		s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
+		s5p_mfc_write_info(ctx, shm, P_B_FRAME_QP);
 	}
 	/* extended encoder ctrl */
-	shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
+	shm = s5p_mfc_read_info(ctx, EXT_ENC_CONTROL);
 	/* AR VUI control */
 	shm &= ~(0x1 << 15);
 	shm |= (p_264->vui_sar << 1);
-	s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
+	s5p_mfc_write_info(ctx, shm, EXT_ENC_CONTROL);
 	if (p_264->vui_sar) {
 		/* aspect ration IDC */
-		shm = s5p_mfc_read_shm(ctx, SAMPLE_ASPECT_RATIO_IDC);
+		shm = s5p_mfc_read_info(ctx, SAMPLE_ASPECT_RATIO_IDC);
 		shm &= ~(0xFF);
 		shm |= p_264->vui_sar_idc;
-		s5p_mfc_write_shm(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
+		s5p_mfc_write_info(ctx, shm, SAMPLE_ASPECT_RATIO_IDC);
 		if (p_264->vui_sar_idc == 0xFF) {
 			/* sample  AR info */
-			shm = s5p_mfc_read_shm(ctx, EXTENDED_SAR);
+			shm = s5p_mfc_read_info(ctx, EXTENDED_SAR);
 			shm &= ~(0xFFFFFFFF);
 			shm |= p_264->vui_ext_sar_width << 16;
 			shm |= p_264->vui_ext_sar_height;
-			s5p_mfc_write_shm(ctx, shm, EXTENDED_SAR);
+			s5p_mfc_write_info(ctx, shm, EXTENDED_SAR);
 		}
 	}
 	/* intra picture period for H.264 */
-	shm = s5p_mfc_read_shm(ctx, H264_I_PERIOD);
+	shm = s5p_mfc_read_info(ctx, H264_I_PERIOD);
 	/* control */
 	shm &= ~(0x1 << 16);
 	shm |= (p_264->open_gop << 16);
@@ -843,16 +919,16 @@ static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
 		shm &= ~(0xFFFF);
 		shm |= p_264->open_gop_size;
 	}
-	s5p_mfc_write_shm(ctx, shm, H264_I_PERIOD);
+	s5p_mfc_write_info(ctx, shm, H264_I_PERIOD);
 	/* extended encoder ctrl */
-	shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
+	shm = s5p_mfc_read_info(ctx, EXT_ENC_CONTROL);
 	/* vbv buffer size */
 	if (p->frame_skip_mode ==
 			V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
 		shm &= ~(0xFFFF << 16);
 		shm |= (p_264->cpb_size << 16);
 	}
-	s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
+	s5p_mfc_write_info(ctx, shm, EXT_ENC_CONTROL);
 	return 0;
 }
 
@@ -885,11 +961,11 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
 	mfc_write(dev, p_mpeg4->quarter_pixel, S5P_FIMV_ENC_MPEG4_QUART_PXL);
 	/* qp */
 	if (!p->rc_frame) {
-		shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
+		shm = s5p_mfc_read_info(ctx, P_B_FRAME_QP);
 		shm &= ~(0xFFF);
 		shm |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 6);
 		shm |= (p_mpeg4->rc_p_frame_qp & 0x3F);
-		s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
+		s5p_mfc_write_info(ctx, shm, P_B_FRAME_QP);
 	}
 	/* frame rate */
 	if (p->rc_frame) {
@@ -898,12 +974,12 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
 						p->rc_framerate_denom;
 			mfc_write(dev, framerate,
 				S5P_FIMV_ENC_RC_FRAME_RATE);
-			shm = s5p_mfc_read_shm(ctx, RC_VOP_TIMING);
+			shm = s5p_mfc_read_info(ctx, RC_VOP_TIMING);
 			shm &= ~(0xFFFFFFFF);
 			shm |= (1 << 31);
 			shm |= ((p->rc_framerate_num & 0x7FFF) << 16);
 			shm |= (p->rc_framerate_denom & 0xFFFF);
-			s5p_mfc_write_shm(ctx, shm, RC_VOP_TIMING);
+			s5p_mfc_write_info(ctx, shm, RC_VOP_TIMING);
 		}
 	} else {
 		mfc_write(dev, 0, S5P_FIMV_ENC_RC_FRAME_RATE);
@@ -924,14 +1000,14 @@ static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
 	reg |= p_mpeg4->rc_min_qp;
 	mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
 	/* extended encoder ctrl */
-	shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
+	shm = s5p_mfc_read_info(ctx, EXT_ENC_CONTROL);
 	/* vbv buffer size */
 	if (p->frame_skip_mode ==
 			V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
 		shm &= ~(0xFFFF << 16);
 		shm |= (p->vbv_size << 16);
 	}
-	s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
+	s5p_mfc_write_info(ctx, shm, EXT_ENC_CONTROL);
 	return 0;
 }
 
@@ -946,10 +1022,10 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
 	s5p_mfc_set_enc_params(ctx);
 	/* qp */
 	if (!p->rc_frame) {
-		shm = s5p_mfc_read_shm(ctx, P_B_FRAME_QP);
+		shm = s5p_mfc_read_info(ctx, P_B_FRAME_QP);
 		shm &= ~(0xFFF);
 		shm |= (p_h263->rc_p_frame_qp & 0x3F);
-		s5p_mfc_write_shm(ctx, shm, P_B_FRAME_QP);
+		s5p_mfc_write_info(ctx, shm, P_B_FRAME_QP);
 	}
 	/* frame rate */
 	if (p->rc_frame && p->rc_framerate_denom)
@@ -973,14 +1049,14 @@ static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
 	reg |= p_h263->rc_min_qp;
 	mfc_write(dev, reg, S5P_FIMV_ENC_RC_QBOUND);
 	/* extended encoder ctrl */
-	shm = s5p_mfc_read_shm(ctx, EXT_ENC_CONTROL);
+	shm = s5p_mfc_read_info(ctx, EXT_ENC_CONTROL);
 	/* vbv buffer size */
 	if (p->frame_skip_mode ==
 			V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
 		shm &= ~(0xFFFF << 16);
 		shm |= (p->vbv_size << 16);
 	}
-	s5p_mfc_write_shm(ctx, shm, EXT_ENC_CONTROL);
+	s5p_mfc_write_info(ctx, shm, EXT_ENC_CONTROL);
 	return 0;
 }
 
@@ -1395,3 +1471,21 @@ void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq)
 	}
 }
 
+void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
+{
+	mfc_write(dev, 0, S5P_FIMV_RISC_HOST_INT);
+	mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
+	mfc_write(dev, 0xffff, S5P_FIMV_SI_RTN_CHID);
+}
+
+void s5p_mfc_write_info(struct s5p_mfc_ctx *ctx, unsigned int data,
+			unsigned int ofs)
+{
+	s5p_mfc_write_shm(ctx, data, ofs);
+}
+
+unsigned int s5p_mfc_read_info(struct s5p_mfc_ctx *ctx,
+				unsigned int ofs)
+{
+	return s5p_mfc_read_shm(ctx, ofs);
+}
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr.h b/drivers/media/video/s5p-mfc/s5p_mfc_opr.h
index 5932d1c..6b49a7c 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_opr.h
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr.h
@@ -50,8 +50,20 @@ void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx);
 int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx);
 void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx);
 
+int s5p_mfc_alloc_dev_context_buffer(struct s5p_mfc_dev *dev);
+void s5p_mfc_release_dev_context_buffer(struct s5p_mfc_dev *dev);
+
+void s5p_mfc_dec_calc_dpb_size(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx);
+
 void s5p_mfc_try_run(struct s5p_mfc_dev *dev);
 void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
+void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev);
+
+void s5p_mfc_write_info(struct s5p_mfc_ctx *ctx, unsigned int data,
+		unsigned int ofs);
+unsigned int s5p_mfc_read_info(struct s5p_mfc_ctx *ctx,
+		unsigned int ofs);
 
 #define s5p_mfc_get_dspl_y_adr()	(readl(dev->regs_base + \
 					S5P_FIMV_SI_DISPLAY_Y_ADR) << \
@@ -63,9 +75,13 @@ void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
 						S5P_FIMV_SI_DISPLAY_STATUS)
 #define s5p_mfc_get_dec_status()	readl(dev->regs_base + \
 						S5P_FIMV_SI_DECODE_STATUS)
-#define s5p_mfc_get_frame_type()	(readl(dev->regs_base + \
+#define s5p_mfc_get_dec_frame_type()	(readl(dev->regs_base + \
 						S5P_FIMV_DECODE_FRAME_TYPE) \
 					& S5P_FIMV_DECODE_FRAME_MASK)
+#define s5p_mfc_get_disp_frame_type()	((s5p_mfc_read_shm(ctx, \
+						DISP_PIC_FRAME_TYPE) \
+						>> S5P_FIMV_SHARED_DISP_FRAME_TYPE_SHIFT) \
+					& S5P_FIMV_DECODE_FRAME_MASK)
 #define s5p_mfc_get_consumed_stream()	readl(dev->regs_base + \
 						S5P_FIMV_SI_CONSUMED_BYTES)
 #define s5p_mfc_get_int_reason()	(readl(dev->regs_base + \
@@ -89,5 +105,12 @@ void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
 						S5P_FIMV_ENC_SI_STRM_SIZE)
 #define s5p_mfc_get_enc_slice_type()	readl(dev->regs_base + \
 						S5P_FIMV_ENC_SI_SLICE_TYPE)
+#define s5p_mfc_get_enc_dpb_count()	-1
+#define s5p_mfc_get_enc_pic_count()	readl(dev->regs_base + \
+						S5P_FIMV_ENC_SI_PIC_CNT)
+#define s5p_mfc_get_sei_avail_status()	s5p_mfc_read_shm(ctx, \
+						FRAME_PACK_SEI_AVAIL)
+#define s5p_mfc_get_mvc_num_views()	-1
+#define s5p_mfc_get_mvc_view_id()	-1
 
 #endif /* S5P_MFC_OPR_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c
new file mode 100644
index 0000000..8e68ecc
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c
@@ -0,0 +1,1697 @@
+/*
+ * drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.c
+ *
+ * Samsung MFC (Multi Function Codec - FIMV) driver
+ * This file contains hw related functions.
+ *
+ * Copyright (c) 2012 Samsung Electronics
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#undef DEBUG
+
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/firmware.h>
+#include <linux/err.h>
+#include <linux/sched.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/cacheflush.h>
+
+#include "s5p_mfc_common.h"
+#include "s5p_mfc_cmd.h"
+#include "s5p_mfc_intr.h"
+#include "s5p_mfc_pm.h"
+#include "s5p_mfc_debug.h"
+
+/* #define S5P_MFC_DEBUG_REGWRITE  */
+#ifdef S5P_MFC_DEBUG_REGWRITE
+#undef writel
+#define writel(v, r)							\
+	do {								\
+		pr_err("MFCWRITE(%p): %08x\n", r, (unsigned int)v);	\
+	__raw_writel(v, r);						\
+	} while (0)
+#endif /* S5P_MFC_DEBUG_REGWRITE */
+
+#define READL(offset)		readl(dev->regs_base + (offset))
+#define WRITEL(data, offset)	writel((data), dev->regs_base + (offset))
+#define OFFSETA(x)		(((x) - dev->port_a) >> S5P_FIMV_MEM_OFFSET)
+#define OFFSETB(x)		(((x) - dev->port_b) >> S5P_FIMV_MEM_OFFSET)
+
+/* Allocate temporary buffers for decoding */
+int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx)
+{
+	/* NOP */
+
+	return 0;
+}
+
+/* Release temproary buffers for decoding */
+void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx)
+{
+	/* NOP */
+}
+
+/* Allocate codec buffers */
+int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	unsigned int mb_width, mb_height;
+
+	mb_width = mb_width(ctx->img_width);
+	mb_height = mb_height(ctx->img_height);
+
+	if (ctx->type == MFCINST_DECODER) {
+		mfc_debug(2, "Luma size:%d Chroma size:%d MV size:%d\n",
+			  ctx->luma_size, ctx->chroma_size, ctx->mv_size);
+		mfc_debug(2, "Totals bufs: %d\n", ctx->total_dpb_count);
+	} else if (ctx->type == MFCINST_ENCODER) {
+		ctx->tmv_buffer_size = 2 * ALIGN((mb_width + 1) *
+				(mb_height + 1) * 8, 16);
+		ctx->luma_dpb_size = ALIGN((mb_width * mb_height) * 256, 256);
+		ctx->chroma_dpb_size = ALIGN((mb_width * mb_height) * 128, 256);
+		ctx->me_buffer_size = ALIGN(((((ctx->img_width+63)/64) * 16) *
+			(((ctx->img_height+63)/64) * 16)) +
+			 ((((mb_width*mb_height)+31)/32) * 16), 256);
+
+		mfc_debug(2, "recon luma size: %d chroma size: %d\n",
+			  ctx->luma_dpb_size, ctx->chroma_dpb_size);
+	} else {
+		return -EINVAL;
+	}
+
+	/* Codecs have different memory requirements */
+	switch (ctx->codec_mode) {
+	case S5P_FIMV_CODEC_H264_DEC:
+	case S5P_FIMV_CODEC_H264_MVC_DEC:
+		ctx->scratch_buf_size = (mb_width * 128) + 65536;
+		ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+		ctx->bank1_size =
+			ctx->scratch_buf_size +
+			(ctx->total_dpb_count * ctx->mv_size);
+		break;
+	case S5P_FIMV_CODEC_MPEG4_DEC:
+		/* mb_width * (mb_height * 64 + 144) + 8192 * mb_height +
+		 * 41088 */
+		ctx->scratch_buf_size = mb_width * (mb_height * 64 + 144) +
+			((2048 + 15)/16 * mb_height * 64) +
+			((2048 + 15)/16 * 256 + 8320);
+		ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+		ctx->bank1_size = ctx->scratch_buf_size;
+		break;
+	case S5P_FIMV_CODEC_VC1RCV_DEC:
+	case S5P_FIMV_CODEC_VC1_DEC:
+		ctx->scratch_buf_size = 2096 * (mb_width + mb_height + 1);
+		ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+		ctx->bank1_size = ctx->scratch_buf_size;
+		break;
+	case S5P_FIMV_CODEC_MPEG2_DEC:
+		ctx->bank1_size = 0;
+		ctx->bank2_size = 0;
+		break;
+	case S5P_FIMV_CODEC_H263_DEC:
+		ctx->scratch_buf_size = mb_width * 400;
+		ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+		ctx->bank1_size = ctx->scratch_buf_size;
+		break;
+	case S5P_FIMV_CODEC_VP8_DEC:
+		ctx->scratch_buf_size = mb_width * 32 + mb_height * 128 + 34816;
+		ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+		ctx->bank1_size = ctx->scratch_buf_size;
+		break;
+	case S5P_FIMV_CODEC_H264_ENC:
+		ctx->scratch_buf_size = (mb_width * 64) +
+			((mb_width + 1) * 16) + (4096 * 16);
+		ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+		ctx->bank1_size =
+			ctx->scratch_buf_size + ctx->tmv_buffer_size +
+			(ctx->dpb_count * (ctx->luma_dpb_size +
+			ctx->chroma_dpb_size + ctx->me_buffer_size));
+		ctx->bank2_size = 0;
+		break;
+	case S5P_FIMV_CODEC_MPEG4_ENC:
+	case S5P_FIMV_CODEC_H263_ENC:
+		ctx->scratch_buf_size = (mb_width * 16) + ((mb_width + 1) * 16);
+		ctx->scratch_buf_size = ALIGN(ctx->scratch_buf_size, 256);
+		ctx->bank1_size =
+			ctx->scratch_buf_size + ctx->tmv_buffer_size +
+			(ctx->dpb_count * (ctx->luma_dpb_size +
+			ctx->chroma_dpb_size + ctx->me_buffer_size));
+		ctx->bank2_size = 0;
+		break;
+	default:
+		break;
+	}
+
+	/* Allocate only if memory from bank 1 is necessary */
+	if (ctx->bank1_size > 0) {
+		ctx->bank1_buf = vb2_dma_contig_memops.alloc(
+		dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_size);
+		if (IS_ERR(ctx->bank1_buf)) {
+			ctx->bank1_buf = 0;
+			pr_err("Buf alloc for decoding failed (port A)\n");
+			return -ENOMEM;
+		}
+		ctx->bank1_phys = s5p_mfc_mem_cookie(
+			dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->bank1_buf);
+		BUG_ON(ctx->bank1_phys & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+	}
+
+	return 0;
+}
+
+/* Release buffers allocated for codec */
+void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx)
+{
+	if (ctx->bank1_buf) {
+		vb2_dma_contig_memops.put(ctx->bank1_buf);
+		ctx->bank1_buf = 0;
+		ctx->bank1_phys = 0;
+		ctx->bank1_size = 0;
+	}
+}
+
+/* Allocate memory for instance data buffer */
+int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
+
+	mfc_debug_enter();
+
+	switch (ctx->codec_mode) {
+	case S5P_FIMV_CODEC_H264_DEC:
+	case S5P_FIMV_CODEC_H264_MVC_DEC:
+		ctx->ctx_size = buf_size->h264_dec_ctx;
+		break;
+	case S5P_FIMV_CODEC_MPEG4_DEC:
+	case S5P_FIMV_CODEC_H263_DEC:
+	case S5P_FIMV_CODEC_VC1RCV_DEC:
+	case S5P_FIMV_CODEC_VC1_DEC:
+	case S5P_FIMV_CODEC_MPEG2_DEC:
+	case S5P_FIMV_CODEC_VP8_DEC:
+		ctx->ctx_size = buf_size->other_dec_ctx;
+		break;
+	case S5P_FIMV_CODEC_H264_ENC:
+		ctx->ctx_size = buf_size->h264_enc_ctx;
+		break;
+	case S5P_FIMV_CODEC_MPEG4_ENC:
+	case S5P_FIMV_CODEC_H263_ENC:
+		ctx->ctx_size = buf_size->other_enc_ctx;
+		break;
+	default:
+		ctx->ctx_size = 0;
+		mfc_err("Codec type(%d) should be checked!\n", ctx->codec_mode);
+		break;
+	}
+
+	ctx->ctx.alloc = vb2_dma_contig_memops.alloc(
+		dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx_size);
+	if (IS_ERR(ctx->ctx.alloc)) {
+		mfc_err("Allocating context buffer failed.\n");
+		return PTR_ERR(ctx->ctx.alloc);
+	}
+
+	ctx->ctx.dma = s5p_mfc_mem_cookie(
+		dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], ctx->ctx.alloc);
+
+	ctx->ctx.virt = vb2_dma_contig_memops.vaddr(ctx->ctx.alloc);
+	if (!ctx->ctx.virt) {
+		vb2_dma_contig_memops.put(ctx->ctx.alloc);
+		ctx->ctx.alloc = NULL;
+		ctx->ctx.dma = 0;
+		ctx->ctx.virt = NULL;
+
+		mfc_err("Remapping context buffer failed.\n");
+		return -ENOMEM;
+	}
+
+	memset(ctx->ctx.virt, 0, ctx->ctx_size);
+	wmb();
+
+	mfc_debug_leave();
+
+	return 0;
+}
+
+/* Release instance buffer */
+void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx)
+{
+	mfc_debug_enter();
+
+	if (ctx->ctx.alloc) {
+		vb2_dma_contig_memops.put(ctx->ctx.alloc);
+		ctx->ctx.alloc = NULL;
+		ctx->ctx.dma = 0;
+		ctx->ctx.virt = NULL;
+	}
+
+	mfc_debug_leave();
+}
+
+/* Allocate context buffers for SYS_INIT */
+int s5p_mfc_alloc_dev_context_buffer(struct s5p_mfc_dev *dev)
+{
+	struct s5p_mfc_buf_size_v6 *buf_size = dev->variant->buf_size->priv;
+
+	mfc_debug_enter();
+
+	dev->ctx_buf.alloc = vb2_dma_contig_memops.alloc(
+			dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], buf_size->dev_ctx);
+	if (IS_ERR(dev->ctx_buf.alloc)) {
+		mfc_err("Allocating DESC buffer failed.\n");
+		return PTR_ERR(dev->ctx_buf.alloc);
+	}
+
+	dev->ctx_buf.dma = s5p_mfc_mem_cookie(
+			dev->alloc_ctx[MFC_BANK1_ALLOC_CTX],
+			dev->ctx_buf.alloc);
+
+	dev->ctx_buf.virt = vb2_dma_contig_memops.vaddr(dev->ctx_buf.alloc);
+	if (!dev->ctx_buf.virt) {
+		vb2_dma_contig_memops.put(dev->ctx_buf.alloc);
+		dev->ctx_buf.alloc = NULL;
+		dev->ctx_buf.dma = 0;
+
+		mfc_err("Remapping DESC buffer failed.\n");
+		return -ENOMEM;
+	}
+
+	memset(dev->ctx_buf.virt, 0, buf_size->dev_ctx);
+	wmb();
+
+	mfc_debug_leave();
+
+	return 0;
+}
+
+/* Release context buffers for SYS_INIT */
+void s5p_mfc_release_dev_context_buffer(struct s5p_mfc_dev *dev)
+{
+	if (dev->ctx_buf.alloc) {
+		vb2_dma_contig_memops.put(dev->ctx_buf.alloc);
+		dev->ctx_buf.alloc = NULL;
+		dev->ctx_buf.dma = 0;
+		dev->ctx_buf.virt = NULL;
+	}
+}
+
+static int calc_plane(int width, int height)
+{
+	int mbX, mbY;
+
+	mbX = (width + 15)/16;
+	mbY = (height + 15)/16;
+
+	if (width * height < 2048 * 1024)
+		mbY = (mbY + 1) / 2 * 2;
+
+	return (mbX * 16) * (mbY * 16);
+}
+
+void s5p_mfc_dec_calc_dpb_size(struct s5p_mfc_ctx *ctx)
+{
+	ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12MT_HALIGN);
+	ctx->buf_height = ALIGN(ctx->img_height, S5P_FIMV_NV12MT_VALIGN);
+	mfc_debug(2, "SEQ Done: Movie dimensions %dx%d,\n"
+			"buffer dimensions: %dx%d\n", ctx->img_width,
+			ctx->img_height, ctx->buf_width, ctx->buf_height);
+
+	ctx->luma_size = calc_plane(ctx->img_width, ctx->img_height);
+	ctx->chroma_size = calc_plane(ctx->img_width, (ctx->img_height >> 1));
+	if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
+			ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC) {
+		ctx->mv_size = s5p_mfc_dec_mv_size(ctx->img_width,
+				ctx->img_height);
+		ctx->mv_size = ALIGN(ctx->mv_size, 16);
+	} else {
+		ctx->mv_size = 0;
+	}
+}
+
+void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx)
+{
+	unsigned int mb_width, mb_height;
+
+	mb_width = mb_width(ctx->img_width);
+	mb_height = mb_height(ctx->img_height);
+
+	ctx->buf_width = ALIGN(ctx->img_width, S5P_FIMV_NV12M_HALIGN);
+	ctx->luma_size = ALIGN((mb_width * mb_height) * 256, 256);
+	ctx->chroma_size = ALIGN((mb_width * mb_height) * 128, 256);
+}
+
+/* Set registers for decoding stream buffer */
+int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
+		  unsigned int start_num_byte, unsigned int strm_size)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;
+
+	mfc_debug_enter();
+	mfc_debug(2, "inst_no: %d, buf_addr: 0x%08x,\n"
+		"buf_size: 0x%08x (%d)\n",
+		ctx->inst_no, buf_addr, strm_size, strm_size);
+	WRITEL(strm_size, S5P_FIMV_D_STREAM_DATA_SIZE);
+	WRITEL(buf_addr, S5P_FIMV_D_CPB_BUFFER_ADDR);
+	WRITEL(buf_size->cpb, S5P_FIMV_D_CPB_BUFFER_SIZE);
+	WRITEL(start_num_byte, S5P_FIMV_D_CPB_BUFFER_OFFSET);
+
+	mfc_debug_leave();
+	return 0;
+}
+
+/* Set decoding frame buffer */
+int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx)
+{
+	unsigned int frame_size, i;
+	unsigned int frame_size_ch, frame_size_mv;
+	struct s5p_mfc_dev *dev = ctx->dev;
+	size_t buf_addr1;
+	int buf_size1;
+	int align_gap;
+
+	buf_addr1 = ctx->bank1_phys;
+	buf_size1 = ctx->bank1_size;
+
+	mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
+	mfc_debug(2, "Total DPB COUNT: %d\n", ctx->total_dpb_count);
+	mfc_debug(2, "Setting display delay to %d\n", ctx->display_delay);
+
+	WRITEL(ctx->total_dpb_count, S5P_FIMV_D_NUM_DPB);
+	WRITEL(ctx->luma_size, S5P_FIMV_D_LUMA_DPB_SIZE);
+	WRITEL(ctx->chroma_size, S5P_FIMV_D_CHROMA_DPB_SIZE);
+
+	WRITEL(buf_addr1, S5P_FIMV_D_SCRATCH_BUFFER_ADDR);
+	WRITEL(ctx->scratch_buf_size, S5P_FIMV_D_SCRATCH_BUFFER_SIZE);
+	buf_addr1 += ctx->scratch_buf_size;
+	buf_size1 -= ctx->scratch_buf_size;
+
+	if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
+			ctx->codec_mode == S5P_FIMV_CODEC_H264_MVC_DEC)
+		WRITEL(ctx->mv_size, S5P_FIMV_D_MV_BUFFER_SIZE);
+
+	frame_size = ctx->luma_size;
+	frame_size_ch = ctx->chroma_size;
+	frame_size_mv = ctx->mv_size;
+	mfc_debug(2, "Frame size: %d ch: %d mv: %d\n",
+			frame_size, frame_size_ch, frame_size_mv);
+
+	for (i = 0; i < ctx->total_dpb_count; i++) {
+		/* Bank2 */
+		mfc_debug(2, "Luma %d: %x\n", i,
+					ctx->dst_bufs[i].cookie.raw.luma);
+		WRITEL(ctx->dst_bufs[i].cookie.raw.luma,
+				S5P_FIMV_D_LUMA_DPB + i * 4);
+		mfc_debug(2, "\tChroma %d: %x\n", i,
+					ctx->dst_bufs[i].cookie.raw.chroma);
+		WRITEL(ctx->dst_bufs[i].cookie.raw.chroma,
+				S5P_FIMV_D_CHROMA_DPB + i * 4);
+
+		if (ctx->codec_mode == S5P_FIMV_CODEC_H264_DEC ||
+				ctx->codec_mode ==
+				S5P_FIMV_CODEC_H264_MVC_DEC) {
+			/* To test alignment */
+			align_gap = buf_addr1;
+			buf_addr1 = ALIGN(buf_addr1, 16);
+			align_gap = buf_addr1 - align_gap;
+			buf_size1 -= align_gap;
+
+			mfc_debug(2, "\tBuf1: %x, size: %d\n",
+					buf_addr1, buf_size1);
+			WRITEL(buf_addr1, S5P_FIMV_D_MV_BUFFER + i * 4);
+			buf_addr1 += frame_size_mv;
+			buf_size1 -= frame_size_mv;
+		}
+	}
+
+	mfc_debug(2, "Buf1: %u, buf_size1: %d (frames %d)\n",
+			buf_addr1, buf_size1, ctx->total_dpb_count);
+	if (buf_size1 < 0) {
+		mfc_debug(2, "Not enough memory has been allocated.\n");
+		return -ENOMEM;
+	}
+
+	WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
+	s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_INIT_BUFS, NULL);
+
+	mfc_debug(2, "After setting buffers.\n");
+	return 0;
+}
+
+/* Set registers for encoding stream buffer */
+int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
+		unsigned long addr, unsigned int size)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+
+	WRITEL(addr, S5P_FIMV_E_STREAM_BUFFER_ADDR); /* 16B align */
+	WRITEL(size, S5P_FIMV_E_STREAM_BUFFER_SIZE);
+
+	mfc_debug(2, "stream buf addr: 0x%08lx, size: 0x%d",
+		addr, size);
+
+	return 0;
+}
+
+void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
+		unsigned long y_addr, unsigned long c_addr)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+
+	WRITEL(y_addr, S5P_FIMV_E_SOURCE_LUMA_ADDR); /* 256B align */
+	WRITEL(c_addr, S5P_FIMV_E_SOURCE_CHROMA_ADDR);
+
+	mfc_debug(2, "enc src y buf addr: 0x%08lx", y_addr);
+	mfc_debug(2, "enc src c buf addr: 0x%08lx", c_addr);
+}
+
+void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
+		unsigned long *y_addr, unsigned long *c_addr)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	unsigned long enc_recon_y_addr, enc_recon_c_addr;
+
+	*y_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_LUMA_ADDR);
+	*c_addr = READL(S5P_FIMV_E_ENCODED_SOURCE_CHROMA_ADDR);
+
+	enc_recon_y_addr = READL(S5P_FIMV_E_RECON_LUMA_DPB_ADDR);
+	enc_recon_c_addr = READL(S5P_FIMV_E_RECON_CHROMA_DPB_ADDR);
+
+	mfc_debug(2, "recon y addr: 0x%08lx", enc_recon_y_addr);
+	mfc_debug(2, "recon c addr: 0x%08lx", enc_recon_c_addr);
+}
+
+/* Set encoding ref & codec buffer */
+int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	size_t buf_addr1, buf_size1;
+	int i;
+
+	mfc_debug_enter();
+
+	buf_addr1 = ctx->bank1_phys;
+	buf_size1 = ctx->bank1_size;
+
+	mfc_debug(2, "Buf1: %p (%d)\n", (void *)buf_addr1, buf_size1);
+
+	for (i = 0; i < ctx->dpb_count; i++) {
+		WRITEL(buf_addr1, S5P_FIMV_E_LUMA_DPB + (4 * i));
+		buf_addr1 += ctx->luma_dpb_size;
+		WRITEL(buf_addr1, S5P_FIMV_E_CHROMA_DPB + (4 * i));
+		buf_addr1 += ctx->chroma_dpb_size;
+		WRITEL(buf_addr1, S5P_FIMV_E_ME_BUFFER + (4 * i));
+		buf_addr1 += ctx->me_buffer_size;
+		buf_size1 -= (ctx->luma_dpb_size + ctx->chroma_dpb_size +
+			ctx->me_buffer_size);
+	}
+
+	WRITEL(buf_addr1, S5P_FIMV_E_SCRATCH_BUFFER_ADDR);
+	WRITEL(ctx->scratch_buf_size, S5P_FIMV_E_SCRATCH_BUFFER_SIZE);
+	buf_addr1 += ctx->scratch_buf_size;
+	buf_size1 -= ctx->scratch_buf_size;
+
+	WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER0);
+	buf_addr1 += ctx->tmv_buffer_size >> 1;
+	WRITEL(buf_addr1, S5P_FIMV_E_TMV_BUFFER1);
+	buf_addr1 += ctx->tmv_buffer_size >> 1;
+	buf_size1 -= ctx->tmv_buffer_size;
+
+	mfc_debug(2, "Buf1: %u, buf_size1: %d (ref frames %d)\n",
+			buf_addr1, buf_size1, ctx->dpb_count);
+	if (buf_size1 < 0) {
+		mfc_debug(2, "Not enough memory has been allocated.\n");
+		return -ENOMEM;
+	}
+
+	WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
+	s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_INIT_BUFS, NULL);
+
+	mfc_debug_leave();
+
+	return 0;
+}
+
+static int s5p_mfc_set_slice_mode(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+
+	/* multi-slice control */
+	/* multi-slice MB number or bit size */
+	WRITEL(ctx->slice_mode, S5P_FIMV_E_MSLICE_MODE);
+	if (ctx->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
+		WRITEL(ctx->slice_size.mb, S5P_FIMV_E_MSLICE_SIZE_MB);
+	} else if (ctx->slice_mode ==
+			V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
+		WRITEL(ctx->slice_size.bits, S5P_FIMV_E_MSLICE_SIZE_BITS);
+	} else {
+		WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_MB);
+		WRITEL(0x0, S5P_FIMV_E_MSLICE_SIZE_BITS);
+	}
+
+	return 0;
+}
+
+static int s5p_mfc_set_enc_params(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	struct s5p_mfc_enc_params *p = &ctx->enc_params;
+	unsigned int reg = 0;
+
+	mfc_debug_enter();
+
+	/* width */
+	WRITEL(ctx->img_width, S5P_FIMV_E_FRAME_WIDTH); /* 16 align */
+	/* height */
+	WRITEL(ctx->img_height, S5P_FIMV_E_FRAME_HEIGHT); /* 16 align */
+
+	/* cropped width */
+	WRITEL(ctx->img_width, S5P_FIMV_E_CROPPED_FRAME_WIDTH);
+	/* cropped height */
+	WRITEL(ctx->img_height, S5P_FIMV_E_CROPPED_FRAME_HEIGHT);
+	/* cropped offset */
+	WRITEL(0x0, S5P_FIMV_E_FRAME_CROP_OFFSET);
+
+	/* pictype : IDR period */
+	reg = 0;
+	reg |= p->gop_size & 0xFFFF;
+	WRITEL(reg, S5P_FIMV_E_GOP_CONFIG);
+
+	/* multi-slice control */
+	/* multi-slice MB number or bit size */
+	ctx->slice_mode = p->slice_mode;
+	reg = 0;
+	if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB) {
+		reg |= (0x1 << 3);
+		WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
+		ctx->slice_size.mb = p->slice_mb;
+	} else if (p->slice_mode == V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES) {
+		reg |= (0x1 << 3);
+		WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
+		ctx->slice_size.bits = p->slice_bit;
+	} else {
+		reg &= ~(0x1 << 3);
+		WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
+	}
+
+	s5p_mfc_set_slice_mode(ctx);
+
+	/* cyclic intra refresh */
+	WRITEL(p->intra_refresh_mb, S5P_FIMV_E_IR_SIZE);
+	reg = READL(S5P_FIMV_E_ENC_OPTIONS);
+	if (p->intra_refresh_mb == 0)
+		reg &= ~(0x1 << 4);
+	else
+		reg |= (0x1 << 4);
+	WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
+
+	/* 'NON_REFERENCE_STORE_ENABLE' for debugging */
+	reg = READL(S5P_FIMV_E_ENC_OPTIONS);
+	reg &= ~(0x1 << 9);
+	WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
+
+	/* memory structure cur. frame */
+	if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M) {
+		/* 0: Linear, 1: 2D tiled*/
+		reg = READL(S5P_FIMV_E_ENC_OPTIONS);
+		reg &= ~(0x1 << 7);
+		WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
+		/* 0: NV12(CbCr), 1: NV21(CrCb) */
+		WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT);
+	} else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV21M) {
+		/* 0: Linear, 1: 2D tiled*/
+		reg = READL(S5P_FIMV_E_ENC_OPTIONS);
+		reg &= ~(0x1 << 7);
+		WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
+		/* 0: NV12(CbCr), 1: NV21(CrCb) */
+		WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT);
+	} else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16) {
+		/* 0: Linear, 1: 2D tiled*/
+		reg = READL(S5P_FIMV_E_ENC_OPTIONS);
+		reg |= (0x1 << 7);
+		WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
+		/* 0: NV12(CbCr), 1: NV21(CrCb) */
+		WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT);
+	}
+
+	/* memory structure recon. frame */
+	/* 0: Linear, 1: 2D tiled */
+	reg = READL(S5P_FIMV_E_ENC_OPTIONS);
+	reg |= (0x1 << 8);
+	WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
+
+	/* padding control & value */
+	WRITEL(0x0, S5P_FIMV_E_PADDING_CTRL);
+	if (p->pad) {
+		reg = 0;
+		/** enable */
+		reg |= (1 << 31);
+		/** cr value */
+		reg |= ((p->pad_cr & 0xFF) << 16);
+		/** cb value */
+		reg |= ((p->pad_cb & 0xFF) << 8);
+		/** y value */
+		reg |= p->pad_luma & 0xFF;
+		WRITEL(reg, S5P_FIMV_E_PADDING_CTRL);
+	}
+
+	/* rate control config. */
+	reg = 0;
+	/* frame-level rate control */
+	reg |= ((p->rc_frame & 0x1) << 9);
+	WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
+
+	/* bit rate */
+	if (p->rc_frame)
+		WRITEL(p->rc_bitrate,
+			S5P_FIMV_E_RC_BIT_RATE);
+	else
+		WRITEL(1, S5P_FIMV_E_RC_BIT_RATE);
+
+	/* reaction coefficient */
+	if (p->rc_frame) {
+		if (p->rc_reaction_coeff < TIGHT_CBR_MAX) /* tight CBR */
+			WRITEL(1, S5P_FIMV_E_RC_RPARAM);
+		else					  /* loose CBR */
+			WRITEL(2, S5P_FIMV_E_RC_RPARAM);
+	}
+
+	/* seq header ctrl */
+	reg = READL(S5P_FIMV_E_ENC_OPTIONS);
+	reg &= ~(0x1 << 2);
+	reg |= ((p->seq_hdr_mode & 0x1) << 2);
+
+	/* frame skip mode */
+	reg &= ~(0x3);
+	reg |= (p->frame_skip_mode & 0x3);
+	WRITEL(reg, S5P_FIMV_E_ENC_OPTIONS);
+
+	/* 'DROP_CONTROL_ENABLE', disable */
+	reg = READL(S5P_FIMV_E_RC_CONFIG);
+	reg &= ~(0x1 << 10);
+	WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
+
+	/* setting for MV range [16, 256] */
+	reg = 0;
+	reg &= ~(0x3FFF);
+	reg = 256;
+	WRITEL(reg, S5P_FIMV_E_MV_HOR_RANGE);
+
+	reg = 0;
+	reg &= ~(0x3FFF);
+	reg = 256;
+	WRITEL(reg, S5P_FIMV_E_MV_VER_RANGE);
+
+	WRITEL(0x0, S5P_FIMV_E_FRAME_INSERTION);
+	WRITEL(0x0, S5P_FIMV_E_ROI_BUFFER_ADDR);
+	WRITEL(0x0, S5P_FIMV_E_PARAM_CHANGE);
+	WRITEL(0x0, S5P_FIMV_E_RC_ROI_CTRL);
+	WRITEL(0x0, S5P_FIMV_E_PICTURE_TAG);
+
+	WRITEL(0x0, S5P_FIMV_E_BIT_COUNT_ENABLE);
+	WRITEL(0x0, S5P_FIMV_E_MAX_BIT_COUNT);
+	WRITEL(0x0, S5P_FIMV_E_MIN_BIT_COUNT);
+
+	WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_ADDR);
+	WRITEL(0x0, S5P_FIMV_E_METADATA_BUFFER_SIZE);
+
+	mfc_debug_leave();
+
+	return 0;
+}
+
+static int s5p_mfc_set_enc_params_h264(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	struct s5p_mfc_enc_params *p = &ctx->enc_params;
+	struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
+	unsigned int reg = 0;
+	int i;
+
+	mfc_debug_enter();
+
+	s5p_mfc_set_enc_params(ctx);
+
+	/* pictype : number of B */
+	reg = READL(S5P_FIMV_E_GOP_CONFIG);
+	reg &= ~(0x3 << 16);
+	reg |= ((p->num_b_frame & 0x3) << 16);
+	WRITEL(reg, S5P_FIMV_E_GOP_CONFIG);
+
+	/* profile & level */
+	reg = 0;
+	/** level */
+	reg |= ((p_h264->level & 0xFF) << 8);
+	/** profile - 0 ~ 3 */
+	reg |= p_h264->profile & 0x3F;
+	WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
+
+	/* rate control config. */
+	reg = READL(S5P_FIMV_E_RC_CONFIG);
+	/** macroblock level rate control */
+	reg &= ~(0x1 << 8);
+	reg |= ((p->rc_mb & 0x1) << 8);
+	WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
+	/** frame QP */
+	reg &= ~(0x3F);
+	reg |= p_h264->rc_frame_qp & 0x3F;
+	WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
+
+	/* max & min value of QP */
+	reg = 0;
+	/** max QP */
+	reg |= ((p_h264->rc_max_qp & 0x3F) << 8);
+	/** min QP */
+	reg |= p_h264->rc_min_qp & 0x3F;
+	WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
+
+	/* other QPs */
+	WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP);
+	if (!p->rc_frame && !p->rc_mb) {
+		reg = 0;
+		reg |= ((p_h264->rc_b_frame_qp & 0x3F) << 16);
+		reg |= ((p_h264->rc_p_frame_qp & 0x3F) << 8);
+		reg |= p_h264->rc_frame_qp & 0x3F;
+		WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
+	}
+
+	/* frame rate */
+	if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
+		reg = 0;
+		reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
+		reg |= p->rc_framerate_denom & 0xFFFF;
+		WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
+	}
+
+	/* vbv buffer size */
+	if (p->frame_skip_mode ==
+			V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+		WRITEL(p_h264->cpb_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE);
+
+		if (p->rc_frame)
+			WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY);
+	}
+
+	/* interlace */
+	reg = 0;
+	reg |= ((p_h264->interlace & 0x1) << 3);
+	WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+
+	/* height */
+	if (p_h264->interlace) {
+		WRITEL(ctx->img_height >> 1,
+				S5P_FIMV_E_FRAME_HEIGHT); /* 32 align */
+		/* cropped height */
+		WRITEL(ctx->img_height >> 1, S5P_FIMV_E_CROPPED_FRAME_HEIGHT);
+	}
+
+	/* loop filter ctrl */
+	reg = READL(S5P_FIMV_E_H264_OPTIONS);
+	reg &= ~(0x3 << 1);
+	reg |= ((p_h264->loop_filter_mode & 0x3) << 1);
+	WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+
+	/* loopfilter alpha offset */
+	if (p_h264->loop_filter_alpha < 0) {
+		reg = 0x10;
+		reg |= (0xFF - p_h264->loop_filter_alpha) + 1;
+	} else {
+		reg = 0x00;
+		reg |= (p_h264->loop_filter_alpha & 0xF);
+	}
+	WRITEL(reg, S5P_FIMV_E_H264_LF_ALPHA_OFFSET);
+
+	/* loopfilter beta offset */
+	if (p_h264->loop_filter_beta < 0) {
+		reg = 0x10;
+		reg |= (0xFF - p_h264->loop_filter_beta) + 1;
+	} else {
+		reg = 0x00;
+		reg |= (p_h264->loop_filter_beta & 0xF);
+	}
+	WRITEL(reg, S5P_FIMV_E_H264_LF_BETA_OFFSET);
+
+	/* entropy coding mode */
+	reg = READL(S5P_FIMV_E_H264_OPTIONS);
+	reg &= ~(0x1);
+	reg |= p_h264->entropy_mode & 0x1;
+	WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+
+	/* number of ref. picture */
+	reg = READL(S5P_FIMV_E_H264_OPTIONS);
+	reg &= ~(0x1 << 7);
+	reg |= (((p_h264->num_ref_pic_4p - 1) & 0x1) << 7);
+	WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+
+	/* 8x8 transform enable */
+	reg = READL(S5P_FIMV_E_H264_OPTIONS);
+	reg &= ~(0x3 << 12);
+	reg |= ((p_h264->_8x8_transform & 0x3) << 12);
+	WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+
+	/* macroblock adaptive scaling features */
+	WRITEL(0x0, S5P_FIMV_E_MB_RC_CONFIG);
+	if (p->rc_mb) {
+		reg = 0;
+		/** dark region */
+		reg |= ((p_h264->rc_mb_dark & 0x1) << 3);
+		/** smooth region */
+		reg |= ((p_h264->rc_mb_smooth & 0x1) << 2);
+		/** static region */
+		reg |= ((p_h264->rc_mb_static & 0x1) << 1);
+		/** high activity region */
+		reg |= p_h264->rc_mb_activity & 0x1;
+		WRITEL(reg, S5P_FIMV_E_MB_RC_CONFIG);
+	}
+
+	/* aspect ratio VUI */
+	reg = READL(S5P_FIMV_E_H264_OPTIONS);
+	reg &= ~(0x1 << 5);
+	reg |= ((p_h264->vui_sar & 0x1) << 5);
+	WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+
+	WRITEL(0x0, S5P_FIMV_E_ASPECT_RATIO);
+	WRITEL(0x0, S5P_FIMV_E_EXTENDED_SAR);
+	if (p_h264->vui_sar) {
+		/* aspect ration IDC */
+		reg = 0;
+		reg |= p_h264->vui_sar_idc & 0xFF;
+		WRITEL(reg, S5P_FIMV_E_ASPECT_RATIO);
+		if (p_h264->vui_sar_idc == 0xFF) {
+			/* extended SAR */
+			reg = 0;
+			reg |= (p_h264->vui_ext_sar_width & 0xFFFF) << 16;
+			reg |= p_h264->vui_ext_sar_height & 0xFFFF;
+			WRITEL(reg, S5P_FIMV_E_EXTENDED_SAR);
+		}
+	}
+
+	/* intra picture period for H.264 open GOP */
+	/* control */
+	reg = READL(S5P_FIMV_E_H264_OPTIONS);
+	reg &= ~(0x1 << 4);
+	reg |= ((p_h264->open_gop & 0x1) << 4);
+	WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+	/* value */
+	WRITEL(0x0, S5P_FIMV_E_H264_I_PERIOD);
+	if (p_h264->open_gop) {
+		reg = 0;
+		reg |= p_h264->open_gop_size & 0xFFFF;
+		WRITEL(reg, S5P_FIMV_E_H264_I_PERIOD);
+	}
+
+	/* 'WEIGHTED_BI_PREDICTION' for B is disable */
+	reg = READL(S5P_FIMV_E_H264_OPTIONS);
+	reg &= ~(0x3 << 9);
+	WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+
+	/* 'CONSTRAINED_INTRA_PRED_ENABLE' is disable */
+	reg = READL(S5P_FIMV_E_H264_OPTIONS);
+	reg &= ~(0x1 << 14);
+	WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+
+	/* ASO */
+	reg = READL(S5P_FIMV_E_H264_OPTIONS);
+	reg &= ~(0x1 << 6);
+	reg |= ((p_h264->aso & 0x1) << 6);
+	WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+
+	/* hier qp enable */
+	reg = READL(S5P_FIMV_E_H264_OPTIONS);
+	reg &= ~(0x1 << 8);
+	reg |= ((p_h264->open_gop & 0x1) << 8);
+	WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+	reg = 0;
+	if (p_h264->hier_qp && p_h264->hier_qp_layer) {
+		reg |= (p_h264->hier_qp_type & 0x1) << 0x3;
+		reg |= p_h264->hier_qp_layer & 0x7;
+		WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER);
+		/* QP value for each layer */
+		for (i = 0; i < (p_h264->hier_qp_layer & 0x7); i++)
+			WRITEL(p_h264->hier_qp_layer_qp[i],
+				S5P_FIMV_E_H264_HIERARCHICAL_QP_LAYER0 + i * 4);
+	}
+	/* number of coding layer should be zero when hierarchical is disable */
+	WRITEL(reg, S5P_FIMV_E_H264_NUM_T_LAYER);
+
+	/* frame packing SEI generation */
+	reg = READL(S5P_FIMV_E_H264_OPTIONS);
+	reg &= ~(0x1 << 25);
+	reg |= ((p_h264->sei_frame_packing & 0x1) << 25);
+	WRITEL(reg, S5P_FIMV_E_H264_OPTIONS);
+	if (p_h264->sei_frame_packing) {
+		reg = 0;
+		/** current frame0 flag */
+		reg |= ((p_h264->sei_fp_curr_frame_0 & 0x1) << 2);
+		/** arrangement type */
+		reg |= p_h264->sei_fp_arrangement_type & 0x3;
+		WRITEL(reg, S5P_FIMV_E_H264_FRAME_PACKING_SEI_INFO);
+	}
+
+	if (p_h264->fmo) {
+		switch (p_h264->fmo_map_type) {
+		case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_INTERLEAVED_SLICES:
+			if (p_h264->fmo_slice_grp > 4)
+				p_h264->fmo_slice_grp = 4;
+			for (i = 0; i < (p_h264->fmo_slice_grp & 0xF); i++)
+				WRITEL(p_h264->fmo_run_len[i] - 1,
+				S5P_FIMV_E_H264_FMO_RUN_LENGTH_MINUS1_0 +
+				i * 4);
+			break;
+		case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_SCATTERED_SLICES:
+			if (p_h264->fmo_slice_grp > 4)
+				p_h264->fmo_slice_grp = 4;
+			break;
+		case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_RASTER_SCAN:
+		case V4L2_MPEG_VIDEO_H264_FMO_MAP_TYPE_WIPE_SCAN:
+			if (p_h264->fmo_slice_grp > 2)
+				p_h264->fmo_slice_grp = 2;
+			WRITEL(p_h264->fmo_chg_dir & 0x1,
+				S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_DIR);
+			/* the valid range is 0 ~ number of macroblocks -1 */
+			WRITEL(p_h264->fmo_chg_rate,
+				S5P_FIMV_E_H264_FMO_SLICE_GRP_CHANGE_RATE_MINUS1);
+			break;
+		default:
+			mfc_err("Unsupported map type for FMO: %d\n",
+					p_h264->fmo_map_type);
+			p_h264->fmo_map_type = 0;
+			p_h264->fmo_slice_grp = 1;
+			break;
+		}
+
+		WRITEL(p_h264->fmo_map_type,
+				S5P_FIMV_E_H264_FMO_SLICE_GRP_MAP_TYPE);
+		WRITEL(p_h264->fmo_slice_grp - 1,
+				S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1);
+	} else {
+		WRITEL(0, S5P_FIMV_E_H264_FMO_NUM_SLICE_GRP_MINUS1);
+	}
+
+	mfc_debug_leave();
+
+	return 0;
+}
+
+static int s5p_mfc_set_enc_params_mpeg4(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	struct s5p_mfc_enc_params *p = &ctx->enc_params;
+	struct s5p_mfc_mpeg4_enc_params *p_mpeg4 = &p->codec.mpeg4;
+	unsigned int reg = 0;
+
+	mfc_debug_enter();
+
+	s5p_mfc_set_enc_params(ctx);
+
+	/* pictype : number of B */
+	reg = READL(S5P_FIMV_E_GOP_CONFIG);
+	reg &= ~(0x3 << 16);
+	reg |= ((p->num_b_frame & 0x3) << 16);
+	WRITEL(reg, S5P_FIMV_E_GOP_CONFIG);
+
+	/* profile & level */
+	reg = 0;
+	/** level */
+	reg |= ((p_mpeg4->level & 0xFF) << 8);
+	/** profile - 0 ~ 1 */
+	reg |= p_mpeg4->profile & 0x3F;
+	WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
+
+	/* rate control config. */
+	reg = READL(S5P_FIMV_E_RC_CONFIG);
+	/** macroblock level rate control */
+	reg &= ~(0x1 << 8);
+	reg |= ((p->rc_mb & 0x1) << 8);
+	WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
+	/** frame QP */
+	reg &= ~(0x3F);
+	reg |= p_mpeg4->rc_frame_qp & 0x3F;
+	WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
+
+	/* max & min value of QP */
+	reg = 0;
+	/** max QP */
+	reg |= ((p_mpeg4->rc_max_qp & 0x3F) << 8);
+	/** min QP */
+	reg |= p_mpeg4->rc_min_qp & 0x3F;
+	WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
+
+	/* other QPs */
+	WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP);
+	if (!p->rc_frame && !p->rc_mb) {
+		reg = 0;
+		reg |= ((p_mpeg4->rc_b_frame_qp & 0x3F) << 16);
+		reg |= ((p_mpeg4->rc_p_frame_qp & 0x3F) << 8);
+		reg |= p_mpeg4->rc_frame_qp & 0x3F;
+		WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
+	}
+
+	/* frame rate */
+	if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
+		reg = 0;
+		reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
+		reg |= p->rc_framerate_denom & 0xFFFF;
+		WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
+	}
+
+	/* vbv buffer size */
+	if (p->frame_skip_mode ==
+			V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+		WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE);
+
+		if (p->rc_frame)
+			WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY);
+	}
+
+	/* Disable HEC */
+	WRITEL(0x0, S5P_FIMV_E_MPEG4_OPTIONS);
+	WRITEL(0x0, S5P_FIMV_E_MPEG4_HEC_PERIOD);
+
+	mfc_debug_leave();
+
+	return 0;
+}
+
+static int s5p_mfc_set_enc_params_h263(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	struct s5p_mfc_enc_params *p = &ctx->enc_params;
+	struct s5p_mfc_mpeg4_enc_params *p_h263 = &p->codec.mpeg4;
+	unsigned int reg = 0;
+
+	mfc_debug_enter();
+
+	s5p_mfc_set_enc_params(ctx);
+
+	/* profile & level */
+	reg = 0;
+	/** profile */
+	reg |= (0x1 << 4);
+	WRITEL(reg, S5P_FIMV_E_PICTURE_PROFILE);
+
+	/* rate control config. */
+	reg = READL(S5P_FIMV_E_RC_CONFIG);
+	/** macroblock level rate control */
+	reg &= ~(0x1 << 8);
+	reg |= ((p->rc_mb & 0x1) << 8);
+	WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
+	/** frame QP */
+	reg &= ~(0x3F);
+	reg |= p_h263->rc_frame_qp & 0x3F;
+	WRITEL(reg, S5P_FIMV_E_RC_CONFIG);
+
+	/* max & min value of QP */
+	reg = 0;
+	/** max QP */
+	reg |= ((p_h263->rc_max_qp & 0x3F) << 8);
+	/** min QP */
+	reg |= p_h263->rc_min_qp & 0x3F;
+	WRITEL(reg, S5P_FIMV_E_RC_QP_BOUND);
+
+	/* other QPs */
+	WRITEL(0x0, S5P_FIMV_E_FIXED_PICTURE_QP);
+	if (!p->rc_frame && !p->rc_mb) {
+		reg = 0;
+		reg |= ((p_h263->rc_b_frame_qp & 0x3F) << 16);
+		reg |= ((p_h263->rc_p_frame_qp & 0x3F) << 8);
+		reg |= p_h263->rc_frame_qp & 0x3F;
+		WRITEL(reg, S5P_FIMV_E_FIXED_PICTURE_QP);
+	}
+
+	/* frame rate */
+	if (p->rc_frame && p->rc_framerate_num && p->rc_framerate_denom) {
+		reg = 0;
+		reg |= ((p->rc_framerate_num & 0xFFFF) << 16);
+		reg |= p->rc_framerate_denom & 0xFFFF;
+		WRITEL(reg, S5P_FIMV_E_RC_FRAME_RATE);
+	}
+
+	/* vbv buffer size */
+	if (p->frame_skip_mode ==
+			V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT) {
+		WRITEL(p->vbv_size & 0xFFFF, S5P_FIMV_E_VBV_BUFFER_SIZE);
+
+		if (p->rc_frame)
+			WRITEL(p->vbv_delay, S5P_FIMV_E_VBV_INIT_DELAY);
+	}
+
+	mfc_debug_leave();
+
+	return 0;
+}
+
+/* Initialize decoding */
+int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	unsigned int reg = 0;
+	int fmo_aso_ctrl = 0;
+
+	mfc_debug_enter();
+	mfc_debug(2, "InstNo: %d/%d\n", ctx->inst_no, S5P_FIMV_CH_SEQ_HEADER);
+	mfc_debug(2, "BUFs: %08x %08x %08x\n",
+		  READL(S5P_FIMV_D_CPB_BUFFER_ADDR),
+		  READL(S5P_FIMV_D_CPB_BUFFER_ADDR),
+		  READL(S5P_FIMV_D_CPB_BUFFER_ADDR));
+
+	/* FMO_ASO_CTRL - 0: Enable, 1: Disable */
+	reg |= (fmo_aso_ctrl << S5P_FIMV_D_OPT_FMO_ASO_CTRL_MASK);
+
+	/* When user sets desplay_delay to 0,
+	 * It works as "display_delay enable" and delay set to 0.
+	 * If user wants display_delay disable, It should be
+	 * set to negative value. */
+	if (ctx->display_delay >= 0) {
+		reg |= (0x1 << S5P_FIMV_D_OPT_DDELAY_EN_SHIFT);
+		WRITEL(ctx->display_delay, S5P_FIMV_D_DISPLAY_DELAY);
+	}
+	/* Setup loop filter, for decoding this is only valid for MPEG4 */
+	if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_DEC) {
+		mfc_debug(2, "Set loop filter to: %d\n",
+				ctx->loop_filter_mpeg4);
+		reg |= (ctx->loop_filter_mpeg4 <<
+				S5P_FIMV_D_OPT_LF_CTRL_SHIFT);
+	}
+	if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV12MT_16X16)
+		reg |= (0x1 << S5P_FIMV_D_OPT_TILE_MODE_SHIFT);
+
+	WRITEL(reg, S5P_FIMV_D_DEC_OPTIONS);
+
+	/* 0: NV12(CbCr), 1: NV21(CrCb) */
+	if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_NV21M)
+		WRITEL(0x1, S5P_FIMV_PIXEL_FORMAT);
+	else
+		WRITEL(0x0, S5P_FIMV_PIXEL_FORMAT);
+
+	/* sei parse */
+	WRITEL(ctx->sei_fp_parse & 0x1, S5P_FIMV_D_SEI_ENABLE);
+
+	WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
+	s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_SEQ_HEADER, NULL);
+
+	mfc_debug_leave();
+	return 0;
+}
+
+static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	unsigned int dpb;
+	if (flush)
+		dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) | (1 << 14);
+	else
+		dpb = READL(S5P_FIMV_SI_CH0_DPB_CONF_CTRL) & ~(1 << 14);
+	WRITEL(dpb, S5P_FIMV_SI_CH0_DPB_CONF_CTRL);
+}
+
+/* Decode a single frame */
+int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+
+	WRITEL(0xffffffff, S5P_FIMV_D_AVAILABLE_DPB_FLAG_LOWER);
+	WRITEL(0xffffffff, S5P_FIMV_D_AVAILABLE_DPB_FLAG_UPPER);
+	WRITEL(ctx->slice_interface & 0x1, S5P_FIMV_D_SLICE_IF_ENABLE);
+
+	WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
+	/* Issue different commands to instance basing on whether it
+	 * is the last frame or not. */
+	switch (last_frame) {
+	case 0:
+		s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_FRAME_START, NULL);
+		break;
+	case 1:
+		s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_LAST_FRAME, NULL);
+		break;
+	}
+
+	mfc_debug(2, "Decoding a usual frame.\n");
+	return 0;
+}
+
+int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+
+	if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
+		s5p_mfc_set_enc_params_h264(ctx);
+	else if (ctx->codec_mode == S5P_FIMV_CODEC_MPEG4_ENC)
+		s5p_mfc_set_enc_params_mpeg4(ctx);
+	else if (ctx->codec_mode == S5P_FIMV_CODEC_H263_ENC)
+		s5p_mfc_set_enc_params_h263(ctx);
+	else {
+		mfc_err("Unknown codec for encoding (%x).\n",
+			ctx->codec_mode);
+		return -EINVAL;
+	}
+
+	WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
+	s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_SEQ_HEADER, NULL);
+
+	return 0;
+}
+
+int s5p_mfc_h264_set_aso_slice_order(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	struct s5p_mfc_enc_params *p = &ctx->enc_params;
+	struct s5p_mfc_h264_enc_params *p_h264 = &p->codec.h264;
+	int i;
+
+	if (p_h264->aso) {
+		for (i = 0; i < 8; i++)
+			WRITEL(p_h264->aso_slice_order[i],
+				S5P_FIMV_E_H264_ASO_SLICE_ORDER_0 + i * 4);
+	}
+	return 0;
+}
+
+/* Encode a single frame */
+int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+
+	mfc_debug(2, "++\n");
+
+	/* memory structure cur. frame */
+
+	if (ctx->codec_mode == S5P_FIMV_CODEC_H264_ENC)
+		s5p_mfc_h264_set_aso_slice_order(ctx);
+
+	s5p_mfc_set_slice_mode(ctx);
+
+	WRITEL(ctx->inst_no, S5P_FIMV_INSTANCE_ID);
+	s5p_mfc_cmd_host2risc(dev, S5P_FIMV_CH_FRAME_START, NULL);
+
+	mfc_debug(2, "--\n");
+
+	return 0;
+}
+
+static inline int s5p_mfc_get_new_ctx(struct s5p_mfc_dev *dev)
+{
+	unsigned long flags;
+	int new_ctx;
+	int cnt;
+
+	spin_lock_irqsave(&dev->condlock, flags);
+	mfc_debug(2, "Previos context: %d (bits %08lx)\n", dev->curr_ctx,
+							dev->ctx_work_bits);
+	new_ctx = (dev->curr_ctx + 1) % MFC_NUM_CONTEXTS;
+	cnt = 0;
+	while (!test_bit(new_ctx, &dev->ctx_work_bits)) {
+		new_ctx = (new_ctx + 1) % MFC_NUM_CONTEXTS;
+		cnt++;
+		if (cnt > MFC_NUM_CONTEXTS) {
+			/* No contexts to run */
+			spin_unlock_irqrestore(&dev->condlock, flags);
+			return -EAGAIN;
+		}
+	}
+	spin_unlock_irqrestore(&dev->condlock, flags);
+	return new_ctx;
+}
+
+static inline void s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	struct s5p_mfc_buf *temp_vb;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->irqlock, flags);
+
+	/* Frames are being decoded */
+	if (list_empty(&ctx->src_queue)) {
+		mfc_debug(2, "No src buffers.\n");
+		spin_unlock_irqrestore(&dev->irqlock, flags);
+		return;
+	}
+	/* Get the next source buffer */
+	temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+	temp_vb->used = 1;
+	s5p_mfc_set_dec_stream_buffer(ctx,
+			vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0, 0);
+	spin_unlock_irqrestore(&dev->irqlock, flags);
+
+	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
+	s5p_mfc_decode_one_frame(ctx, 1);
+}
+
+static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	struct s5p_mfc_buf *temp_vb;
+	unsigned long flags;
+	int last_frame = 0;
+	unsigned int index;
+
+	spin_lock_irqsave(&dev->irqlock, flags);
+
+	/* Frames are being decoded */
+	if (list_empty(&ctx->src_queue)) {
+		mfc_debug(2, "No src buffers.\n");
+		spin_unlock_irqrestore(&dev->irqlock, flags);
+		return -EAGAIN;
+	}
+	/* Get the next source buffer */
+	temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+	temp_vb->used = 1;
+	s5p_mfc_set_dec_stream_buffer(ctx,
+		vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0,
+			temp_vb->b->v4l2_planes[0].bytesused);
+	spin_unlock_irqrestore(&dev->irqlock, flags);
+
+	index = temp_vb->b->v4l2_buf.index;
+
+	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
+	if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
+		last_frame = 1;
+		mfc_debug(2, "Setting ctx->state to FINISHING\n");
+		ctx->state = MFCINST_FINISHING;
+	}
+	s5p_mfc_decode_one_frame(ctx, last_frame);
+
+	return 0;
+}
+
+static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	unsigned long flags;
+	struct s5p_mfc_buf *dst_mb;
+	struct s5p_mfc_buf *src_mb;
+	unsigned long src_y_addr, src_c_addr, dst_addr;
+	/*
+	unsigned int src_y_size, src_c_size;
+	*/
+	unsigned int dst_size;
+	unsigned int index;
+
+	spin_lock_irqsave(&dev->irqlock, flags);
+
+	if (list_empty(&ctx->src_queue)) {
+		mfc_debug(2, "no src buffers.\n");
+		spin_unlock_irqrestore(&dev->irqlock, flags);
+		return -EAGAIN;
+	}
+
+	if (list_empty(&ctx->dst_queue)) {
+		mfc_debug(2, "no dst buffers.\n");
+		spin_unlock_irqrestore(&dev->irqlock, flags);
+		return -EAGAIN;
+	}
+
+	src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+	src_mb->used = 1;
+	src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
+	src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
+
+	mfc_debug(2, "enc src y addr: 0x%08lx", src_y_addr);
+	mfc_debug(2, "enc src c addr: 0x%08lx", src_c_addr);
+
+	s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
+
+	dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+	dst_mb->used = 1;
+	dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
+	dst_size = vb2_plane_size(dst_mb->b, 0);
+
+	s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
+
+	spin_unlock_irqrestore(&dev->irqlock, flags);
+
+	index = src_mb->b->v4l2_buf.index;
+
+	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
+	s5p_mfc_encode_one_frame(ctx);
+
+	return 0;
+}
+
+static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	unsigned long flags;
+	struct s5p_mfc_buf *temp_vb;
+
+	/* Initializing decoding - parsing header */
+	spin_lock_irqsave(&dev->irqlock, flags);
+	mfc_debug(2, "Preparing to init decoding.\n");
+	temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+	mfc_debug(2, "Header size: %d\n", temp_vb->b->v4l2_planes[0].bytesused);
+	s5p_mfc_set_dec_stream_buffer(ctx,
+		vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0,
+			temp_vb->b->v4l2_planes[0].bytesused);
+	spin_unlock_irqrestore(&dev->irqlock, flags);
+	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
+	s5p_mfc_init_decode(ctx);
+}
+
+static inline void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	unsigned long flags;
+	struct s5p_mfc_buf *dst_mb;
+	unsigned long dst_addr;
+	unsigned int dst_size;
+
+	spin_lock_irqsave(&dev->irqlock, flags);
+
+	dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
+	dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
+	dst_size = vb2_plane_size(dst_mb->b, 0);
+	s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
+	spin_unlock_irqrestore(&dev->irqlock, flags);
+	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
+	s5p_mfc_init_encode(ctx);
+}
+
+static inline int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	int ret;
+	/* Header was parsed now start processing
+	 * First set the output frame buffers
+	 * s5p_mfc_alloc_dec_buffers(ctx); */
+
+	if (ctx->capture_state != QUEUE_BUFS_MMAPED) {
+		mfc_err("It seems that not all destionation buffers were\n"
+			"mmaped.MFC requires that all destination are mmaped\n"
+			"before starting processing.\n");
+		return -EAGAIN;
+	}
+
+	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
+	ret = s5p_mfc_set_dec_frame_buffer(ctx);
+	if (ret) {
+		mfc_err("Failed to alloc frame mem.\n");
+		ctx->state = MFCINST_ERROR;
+	}
+	return ret;
+}
+
+static inline int s5p_mfc_run_init_enc_buffers(struct s5p_mfc_ctx *ctx)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	int ret;
+
+	ret = s5p_mfc_alloc_codec_buffers(ctx);
+	if (ret) {
+		mfc_err("Failed to allocate encoding buffers.\n");
+		return -ENOMEM;
+	}
+
+	/* Header was generated now starting processing
+	 * First set the reference frame buffers
+	 */
+	if (ctx->capture_state != QUEUE_BUFS_REQUESTED) {
+		mfc_err("It seems that destionation buffers were not\n"
+			"requested.MFC requires that header should be generated\n"
+			"before allocating codec buffer.\n");
+		return -EAGAIN;
+	}
+
+	dev->curr_ctx = ctx->num;
+	s5p_mfc_clean_ctx_int_flags(ctx);
+	ret = s5p_mfc_set_enc_ref_buffer(ctx);
+	if (ret) {
+		mfc_err("Failed to alloc frame mem.\n");
+		ctx->state = MFCINST_ERROR;
+	}
+	return ret;
+}
+
+/* Try running an operation on hardware */
+void s5p_mfc_try_run(struct s5p_mfc_dev *dev)
+{
+	struct s5p_mfc_ctx *ctx;
+	int new_ctx;
+	unsigned int ret = 0;
+
+	mfc_debug(1, "Try run dev: %p\n", dev);
+
+	/* Check whether hardware is not running */
+	if (test_and_set_bit(0, &dev->hw_lock) != 0) {
+		/* This is perfectly ok, the scheduled ctx should wait */
+		mfc_debug(1, "Couldn't lock HW.\n");
+		return;
+	}
+
+	/* Choose the context to run */
+	new_ctx = s5p_mfc_get_new_ctx(dev);
+	if (new_ctx < 0) {
+		/* No contexts to run */
+		if (test_and_clear_bit(0, &dev->hw_lock) == 0) {
+			mfc_err("Failed to unlock hardware.\n");
+			return;
+		}
+
+		mfc_debug(1, "No ctx is scheduled to be run.\n");
+		return;
+	}
+
+	mfc_debug(1, "New context: %d\n", new_ctx);
+	ctx = dev->ctx[new_ctx];
+	mfc_debug(1, "Seting new context to %p\n", ctx);
+	/* Got context to run in ctx */
+	mfc_debug(1, "ctx->dst_queue_cnt=%d ctx->dpb_count=%d ctx->src_queue_cnt=%d\n",
+		ctx->dst_queue_cnt, ctx->dpb_count, ctx->src_queue_cnt);
+	mfc_debug(1, "ctx->state=%d\n", ctx->state);
+	/* Last frame has already been sent to MFC
+	 * Now obtaining frames from MFC buffer */
+
+	s5p_mfc_clock_on();
+	if (ctx->type == MFCINST_DECODER) {
+		switch (ctx->state) {
+		case MFCINST_FINISHING:
+			s5p_mfc_run_dec_last_frames(ctx);
+			break;
+		case MFCINST_RUNNING:
+			ret = s5p_mfc_run_dec_frame(ctx);
+			break;
+		case MFCINST_INIT:
+			s5p_mfc_clean_ctx_int_flags(ctx);
+			ret = s5p_mfc_open_inst_cmd(ctx);
+			break;
+		case MFCINST_RETURN_INST:
+			s5p_mfc_clean_ctx_int_flags(ctx);
+			ret = s5p_mfc_close_inst_cmd(ctx);
+			break;
+		case MFCINST_GOT_INST:
+			s5p_mfc_run_init_dec(ctx);
+			break;
+		case MFCINST_HEAD_PARSED:
+			ret = s5p_mfc_run_init_dec_buffers(ctx);
+			break;
+		case MFCINST_RES_CHANGE_INIT:
+			s5p_mfc_run_dec_last_frames(ctx);
+			break;
+		case MFCINST_RES_CHANGE_FLUSH:
+			s5p_mfc_run_dec_last_frames(ctx);
+			break;
+		case MFCINST_RES_CHANGE_END:
+			mfc_debug(2, "Finished remaining frames after resolution change.\n");
+			ctx->capture_state = QUEUE_FREE;
+			mfc_debug(2, "Will re-init the codec`.\n");
+			s5p_mfc_run_init_dec(ctx);
+			break;
+		default:
+			ret = -EAGAIN;
+		}
+	} else if (ctx->type == MFCINST_ENCODER) {
+		switch (ctx->state) {
+		case MFCINST_FINISHING:
+		case MFCINST_RUNNING:
+			ret = s5p_mfc_run_enc_frame(ctx);
+			break;
+		case MFCINST_INIT:
+			ret = s5p_mfc_open_inst_cmd(ctx);
+			break;
+		case MFCINST_RETURN_INST:
+			ret = s5p_mfc_close_inst_cmd(ctx);
+			break;
+		case MFCINST_GOT_INST:
+			s5p_mfc_run_init_enc(ctx);
+			break;
+		case MFCINST_HEAD_PARSED: /* Only for MFC6.x */
+			ret = s5p_mfc_run_init_enc_buffers(ctx);
+			break;
+		default:
+			ret = -EAGAIN;
+		}
+	} else {
+		mfc_err("invalid context type: %d\n", ctx->type);
+		ret = -EAGAIN;
+	}
+
+	if (ret) {
+		/* Free hardware lock */
+		if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+			mfc_err("Failed to unlock hardware.\n");
+
+		/* This is in deed imporant, as no operation has been
+		 * scheduled, reduce the clock count as no one will
+		 * ever do this, because no interrupt related to this try_run
+		 * will ever come from hardware. */
+		s5p_mfc_clock_off();
+	}
+}
+
+
+void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq)
+{
+	struct s5p_mfc_buf *b;
+	int i;
+
+	while (!list_empty(lh)) {
+		b = list_entry(lh->next, struct s5p_mfc_buf, list);
+		for (i = 0; i < b->b->num_planes; i++)
+			vb2_set_plane_payload(b->b, i, 0);
+		vb2_buffer_done(b->b, VB2_BUF_STATE_ERROR);
+		list_del(&b->list);
+	}
+}
+
+void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev)
+{
+	mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
+	mfc_write(dev, 0, S5P_FIMV_RISC2HOST_INT);
+}
+
+void s5p_mfc_write_info(struct s5p_mfc_ctx *ctx, unsigned int data,
+		unsigned int ofs)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+
+	s5p_mfc_clock_on();
+	WRITEL(data, ofs);
+	s5p_mfc_clock_off();
+}
+
+unsigned int s5p_mfc_read_info(struct s5p_mfc_ctx *ctx, unsigned int ofs)
+{
+	struct s5p_mfc_dev *dev = ctx->dev;
+	int ret;
+
+	s5p_mfc_clock_on();
+	ret = READL(ofs);
+	s5p_mfc_clock_off();
+
+	return ret;
+}
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h b/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h
new file mode 100644
index 0000000..93ce2d8
--- /dev/null
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h
@@ -0,0 +1,140 @@
+/*
+ * drivers/media/video/s5p-mfc/s5p_mfc_opr_v6.h
+ *
+ * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
+ * Contains declarations of hw related functions.
+ *
+ * Copyright (c) 2012 Samsung Electronics
+ *		http://www.samsung.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef S5P_MFC_OPR_V6_H_
+#define S5P_MFC_OPR_V6_H_
+
+#include "s5p_mfc_common.h"
+
+#define MFC_CTRL_MODE_CUSTOM	MFC_CTRL_MODE_SFR
+
+int s5p_mfc_init_decode(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_init_encode(struct s5p_mfc_ctx *mfc_ctx);
+
+int s5p_mfc_set_dec_frame_buffer(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_set_dec_stream_buffer(struct s5p_mfc_ctx *ctx, int buf_addr,
+						  unsigned int start_num_byte,
+						  unsigned int buf_size);
+
+void s5p_mfc_set_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
+		unsigned long y_addr, unsigned long c_addr);
+int s5p_mfc_set_enc_stream_buffer(struct s5p_mfc_ctx *ctx,
+		unsigned long addr, unsigned int size);
+void s5p_mfc_get_enc_frame_buffer(struct s5p_mfc_ctx *ctx,
+		unsigned long *y_addr, unsigned long *c_addr);
+int s5p_mfc_set_enc_ref_buffer(struct s5p_mfc_ctx *mfc_ctx);
+
+int s5p_mfc_decode_one_frame(struct s5p_mfc_ctx *ctx, int last_frame);
+int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *mfc_ctx);
+
+/* Memory allocation */
+int s5p_mfc_alloc_dec_temp_buffers(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_set_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_release_dec_desc_buffer(struct s5p_mfc_ctx *ctx);
+
+int s5p_mfc_alloc_codec_buffers(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_release_codec_buffers(struct s5p_mfc_ctx *ctx);
+
+int s5p_mfc_alloc_instance_buffer(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_release_instance_buffer(struct s5p_mfc_ctx *ctx);
+int s5p_mfc_alloc_dev_context_buffer(struct s5p_mfc_dev *dev);
+void s5p_mfc_release_dev_context_buffer(struct s5p_mfc_dev *dev);
+
+void s5p_mfc_dec_calc_dpb_size(struct s5p_mfc_ctx *ctx);
+void s5p_mfc_enc_calc_src_size(struct s5p_mfc_ctx *ctx);
+
+#define s5p_mfc_get_dspl_y_adr()	(readl(dev->regs_base + \
+					S5P_FIMV_SI_DISPLAY_Y_ADR))
+#define s5p_mfc_get_dec_y_adr()		(readl(dev->regs_base + \
+					S5P_FIMV_D_DISPLAY_LUMA_ADDR))
+#define s5p_mfc_get_dspl_status()	readl(dev->regs_base + \
+						S5P_FIMV_D_DISPLAY_STATUS)
+#define s5p_mfc_get_decoded_status()	readl(dev->regs_base + \
+						S5P_FIMV_D_DECODED_STATUS)
+#define s5p_mfc_get_dec_frame_type()	(readl(dev->regs_base + \
+						S5P_FIMV_D_DECODED_FRAME_TYPE) \
+						& S5P_FIMV_DECODE_FRAME_MASK)
+#define s5p_mfc_get_disp_frame_type()	(readl(ctx->dev->regs_base + \
+						S5P_FIMV_D_DISPLAY_FRAME_TYPE) \
+						& S5P_FIMV_DECODE_FRAME_MASK)
+#define s5p_mfc_get_consumed_stream()	readl(dev->regs_base + \
+						S5P_FIMV_D_DECODED_NAL_SIZE)
+#define s5p_mfc_get_int_reason()	(readl(dev->regs_base + \
+					S5P_FIMV_RISC2HOST_CMD) & \
+					S5P_FIMV_RISC2HOST_CMD_MASK)
+#define s5p_mfc_get_int_err()		readl(dev->regs_base + \
+						S5P_FIMV_ERROR_CODE)
+#define s5p_mfc_err_dec(x)		(((x) & S5P_FIMV_ERR_DEC_MASK) >> \
+						S5P_FIMV_ERR_DEC_SHIFT)
+#define s5p_mfc_err_dspl(x)		(((x) & S5P_FIMV_ERR_DSPL_MASK) >> \
+						S5P_FIMV_ERR_DSPL_SHIFT)
+#define s5p_mfc_get_img_width()		readl(dev->regs_base + \
+						S5P_FIMV_D_DISPLAY_FRAME_WIDTH)
+#define s5p_mfc_get_img_height()	readl(dev->regs_base + \
+						S5P_FIMV_D_DISPLAY_FRAME_HEIGHT)
+#define s5p_mfc_get_dpb_count()		readl(dev->regs_base + \
+						S5P_FIMV_D_MIN_NUM_DPB)
+#define s5p_mfc_get_inst_no()		readl(dev->regs_base + \
+						S5P_FIMV_RET_INSTANCE_ID)
+#define s5p_mfc_get_enc_dpb_count()	readl(dev->regs_base + \
+						S5P_FIMV_E_NUM_DPB)
+#define s5p_mfc_get_enc_strm_size()	readl(dev->regs_base + \
+						S5P_FIMV_E_STREAM_SIZE)
+#define s5p_mfc_get_enc_slice_type()	readl(dev->regs_base + \
+						S5P_FIMV_E_SLICE_TYPE)
+#define s5p_mfc_get_enc_pic_count()	readl(dev->regs_base + \
+						S5P_FIMV_E_PICTURE_COUNT)
+#define s5p_mfc_get_sei_avail_status()	readl(dev->regs_base + \
+						S5P_FIMV_D_FRAME_PACK_SEI_AVAIL)
+#define s5p_mfc_get_mvc_num_views()	readl(dev->regs_base + \
+						S5P_FIMV_D_MVC_NUM_VIEWS)
+#define s5p_mfc_get_mvc_view_id()	readl(dev->regs_base + \
+						S5P_FIMV_D_MVC_VIEW_ID)
+
+#define mb_width(x_size)		((x_size + 15) / 16)
+#define mb_height(y_size)		((y_size + 15) / 16)
+#define s5p_mfc_dec_mv_size(x, y)	(mb_width(x) * \
+					(((mb_height(y)+1)/2)*2) * 64 + 128)
+
+/* Definition */
+#define ENC_MULTI_SLICE_MB_MAX		((1 << 30) - 1)
+#define ENC_MULTI_SLICE_BIT_MIN		2800
+#define ENC_INTRA_REFRESH_MB_MAX	((1 << 18) - 1)
+#define ENC_VBV_BUF_SIZE_MAX		((1 << 30) - 1)
+#define ENC_H264_LOOP_FILTER_AB_MIN	-12
+#define ENC_H264_LOOP_FILTER_AB_MAX	12
+#define ENC_H264_RC_FRAME_RATE_MAX	((1 << 16) - 1)
+#define ENC_H263_RC_FRAME_RATE_MAX	((1 << 16) - 1)
+#define ENC_H264_PROFILE_MAX		3
+#define ENC_H264_LEVEL_MAX		42
+#define ENC_MPEG4_VOP_TIME_RES_MAX	((1 << 16) - 1)
+#define FRAME_DELTA_H264_H263		1
+#define TIGHT_CBR_MAX			10
+
+/* Definitions for shared memory compatibility */
+#define PIC_TIME_TOP		S5P_FIMV_D_RET_PICTURE_TAG_TOP
+#define PIC_TIME_BOT		S5P_FIMV_D_RET_PICTURE_TAG_BOT
+#define CROP_INFO_H		S5P_FIMV_D_DISPLAY_CROP_INFO1
+#define CROP_INFO_V		S5P_FIMV_D_DISPLAY_CROP_INFO2
+
+void s5p_mfc_try_run(struct s5p_mfc_dev *dev);
+
+void s5p_mfc_cleanup_queue(struct list_head *lh, struct vb2_queue *vq);
+void s5p_mfc_clear_int_flags(struct s5p_mfc_dev *dev);
+
+void s5p_mfc_write_info(struct s5p_mfc_ctx *ctx, unsigned int data,
+		unsigned int ofs);
+unsigned int s5p_mfc_read_info(struct s5p_mfc_ctx *ctx, unsigned int ofs);
+
+#endif /* S5P_MFC_OPR_V6_H_ */
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_pm.c b/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
index 738a607..4fa0b54 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
@@ -20,7 +20,11 @@
 #include "s5p_mfc_debug.h"
 #include "s5p_mfc_pm.h"
 
-#define MFC_CLKNAME		"sclk_mfc"
+#if defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V5)
+#define MFC_CLKNAME            "sclk_mfc"
+#elif defined(CONFIG_VIDEO_SAMSUNG_S5P_MFC_V6)
+#define MFC_CLKNAME            "aclk_333"
+#endif
 #define MFC_GATE_CLK_NAME	"mfc"
 
 #define CLK_DEBUG
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_shm.c b/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
index 91fdbac..9ee269d 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
@@ -21,26 +21,28 @@ int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx)
 {
 	struct s5p_mfc_dev *dev = ctx->dev;
 	void *shm_alloc_ctx = dev->alloc_ctx[MFC_BANK1_ALLOC_CTX];
+	struct s5p_mfc_buf_size_v5 *buf_size = dev->variant->buf_size->priv;
 
-	ctx->shm_alloc = vb2_dma_contig_memops.alloc(shm_alloc_ctx,
-							SHARED_BUF_SIZE);
-	if (IS_ERR(ctx->shm_alloc)) {
+	ctx->shm.alloc = vb2_dma_contig_memops.alloc(shm_alloc_ctx,
+							buf_size->shm);
+	if (IS_ERR(ctx->shm.alloc)) {
 		mfc_err("failed to allocate shared memory\n");
-		return PTR_ERR(ctx->shm_alloc);
+		return PTR_ERR(ctx->shm.alloc);
 	}
-	/* shm_ofs only keeps the offset from base (port a) */
-	ctx->shm_ofs = s5p_mfc_mem_cookie(shm_alloc_ctx, ctx->shm_alloc)
+	/* shared memory offset only keeps the offset from base (port a) */
+	ctx->shm.ofs = s5p_mfc_mem_cookie(shm_alloc_ctx, ctx->shm.alloc)
 								- dev->bank1;
-	BUG_ON(ctx->shm_ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
-	ctx->shm = vb2_dma_contig_memops.vaddr(ctx->shm_alloc);
-	if (!ctx->shm) {
-		vb2_dma_contig_memops.put(ctx->shm_alloc);
-		ctx->shm_ofs = 0;
-		ctx->shm_alloc = NULL;
+	BUG_ON(ctx->shm.ofs & ((1 << MFC_BANK1_ALIGN_ORDER) - 1));
+
+	ctx->shm.virt = vb2_dma_contig_memops.vaddr(ctx->shm.alloc);
+	if (!ctx->shm.virt) {
+		vb2_dma_contig_memops.put(ctx->shm.alloc);
+		ctx->shm.alloc = NULL;
+		ctx->shm.ofs = 0;
 		mfc_err("failed to virt addr of shared memory\n");
 		return -ENOMEM;
 	}
-	memset((void *)ctx->shm, 0, SHARED_BUF_SIZE);
+	memset((void *)ctx->shm.virt, 0, buf_size->shm);
 	wmb();
 	return 0;
 }
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc_shm.h b/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
index cf962a4..8400ab0 100644
--- a/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
+++ b/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
@@ -71,20 +71,23 @@ enum MFC_SHM_OFS {
 	DBG_HISTORY_INPUT1	= 0xD4,	/* C */
 	DBG_HISTORY_OUTPUT	= 0xD8,	/* C */
 	HIERARCHICAL_P_QP	= 0xE0, /* E, H.264 */
+	FRAME_PACK_SEI_ENABLE	= 0x168, /* C */
+	FRAME_PACK_SEI_AVAIL	= 0x16c, /* D */
+	FRAME_PACK_SEI_INFO	= 0x17c, /* E */
 };
 
 int s5p_mfc_init_shm(struct s5p_mfc_ctx *ctx);
 
-#define s5p_mfc_write_shm(ctx, x, ofs)		\
-	do {					\
-		writel(x, (ctx->shm + ofs));	\
-		wmb();				\
+#define s5p_mfc_write_shm(ctx, x, ofs)			\
+	do {						\
+		writel(x, (ctx->shm.virt + ofs));	\
+		wmb();					\
 	} while (0)
 
 static inline u32 s5p_mfc_read_shm(struct s5p_mfc_ctx *ctx, unsigned int ofs)
 {
 	rmb();
-	return readl(ctx->shm + ofs);
+	return readl(ctx->shm.virt + ofs);
 }
 
 #endif /* S5P_MFC_SHM_H_ */
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c
index 9abd9ab..61d6583 100644
--- a/drivers/media/video/v4l2-ctrls.c
+++ b/drivers/media/video/v4l2-ctrls.c
@@ -502,7 +502,6 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
 		return mpeg4_profile;
 	case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
 		return jpeg_chroma_subsampling;
-
 	default:
 		return NULL;
 	}
-- 
1.7.0.4


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-07-12 12:55 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-12 12:43 [PATCH v2 2/2] [media] s5p-mfc: update MFC v4l2 driver to support MFC6.x Arun Kumar K
  -- strict thread matches above, loose matches on Subject: below --
2012-07-12 12:54 Arun Kumar K
2012-07-06 14:00 [PATCH v2 0/2] " Arun Kumar K
2012-07-06 14:00 ` [PATCH v2 2/2] [media] s5p-mfc: " Arun Kumar K
2012-07-06 14:21   ` Kyungmin Park
2012-07-10 15:10   ` Kamil Debski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.