1259 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_dec.c4 *5 * Copyright (C) 2011 Samsung Electronics Co., Ltd.6 * http://www.samsung.com/7 * Kamil Debski, <k.debski@samsung.com>8 */9 10#include <linux/clk.h>11#include <linux/interrupt.h>12#include <linux/io.h>13#include <linux/module.h>14#include <linux/platform_device.h>15#include <linux/sched.h>16#include <linux/slab.h>17#include <linux/videodev2.h>18#include <linux/workqueue.h>19#include <media/v4l2-ctrls.h>20#include <media/v4l2-event.h>21#include <media/videobuf2-v4l2.h>22#include "s5p_mfc_common.h"23#include "s5p_mfc_ctrl.h"24#include "s5p_mfc_debug.h"25#include "s5p_mfc_dec.h"26#include "s5p_mfc_intr.h"27#include "s5p_mfc_opr.h"28#include "s5p_mfc_pm.h"29 30static const struct s5p_mfc_fmt formats[] = {31 {32 .fourcc = V4L2_PIX_FMT_NV12MT_16X16,33 .codec_mode = S5P_MFC_CODEC_NONE,34 .type = MFC_FMT_RAW,35 .num_planes = 2,36 .versions = MFC_V6_BIT | MFC_V7_BIT,37 },38 {39 .fourcc = V4L2_PIX_FMT_NV12MT,40 .codec_mode = S5P_MFC_CODEC_NONE,41 .type = MFC_FMT_RAW,42 .num_planes = 2,43 .versions = MFC_V5_BIT,44 },45 {46 .fourcc = V4L2_PIX_FMT_NV12M,47 .codec_mode = S5P_MFC_CODEC_NONE,48 .type = MFC_FMT_RAW,49 .num_planes = 2,50 .versions = MFC_V6PLUS_BITS,51 },52 {53 .fourcc = V4L2_PIX_FMT_NV21M,54 .codec_mode = S5P_MFC_CODEC_NONE,55 .type = MFC_FMT_RAW,56 .num_planes = 2,57 .versions = MFC_V6PLUS_BITS,58 },59 {60 .fourcc = V4L2_PIX_FMT_YUV420M,61 .codec_mode = S5P_MFC_CODEC_NONE,62 .type = MFC_FMT_RAW,63 .num_planes = 3,64 .versions = MFC_V12_BIT,65 },66 {67 .fourcc = V4L2_PIX_FMT_YVU420M,68 .codec_mode = S5P_MFC_CODEC_NONE,69 .type = MFC_FMT_RAW,70 .num_planes = 3,71 .versions = MFC_V12_BIT72 },73 {74 .fourcc = V4L2_PIX_FMT_H264,75 .codec_mode = S5P_MFC_CODEC_H264_DEC,76 .type = MFC_FMT_DEC,77 .num_planes = 1,78 .versions = MFC_V5PLUS_BITS,79 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION |80 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,81 },82 {83 .fourcc = V4L2_PIX_FMT_H264_MVC,84 .codec_mode = S5P_MFC_CODEC_H264_MVC_DEC,85 .type = MFC_FMT_DEC,86 .num_planes = 1,87 .versions = MFC_V6PLUS_BITS,88 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION |89 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,90 },91 {92 .fourcc = V4L2_PIX_FMT_H263,93 .codec_mode = S5P_MFC_CODEC_H263_DEC,94 .type = MFC_FMT_DEC,95 .num_planes = 1,96 .versions = MFC_V5PLUS_BITS,97 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,98 },99 {100 .fourcc = V4L2_PIX_FMT_MPEG1,101 .codec_mode = S5P_MFC_CODEC_MPEG2_DEC,102 .type = MFC_FMT_DEC,103 .num_planes = 1,104 .versions = MFC_V5PLUS_BITS,105 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION |106 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,107 },108 {109 .fourcc = V4L2_PIX_FMT_MPEG2,110 .codec_mode = S5P_MFC_CODEC_MPEG2_DEC,111 .type = MFC_FMT_DEC,112 .num_planes = 1,113 .versions = MFC_V5PLUS_BITS,114 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION |115 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,116 },117 {118 .fourcc = V4L2_PIX_FMT_MPEG4,119 .codec_mode = S5P_MFC_CODEC_MPEG4_DEC,120 .type = MFC_FMT_DEC,121 .num_planes = 1,122 .versions = MFC_V5PLUS_BITS,123 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION |124 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,125 },126 {127 .fourcc = V4L2_PIX_FMT_XVID,128 .codec_mode = S5P_MFC_CODEC_MPEG4_DEC,129 .type = MFC_FMT_DEC,130 .num_planes = 1,131 .versions = MFC_V5PLUS_BITS,132 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,133 },134 {135 .fourcc = V4L2_PIX_FMT_VC1_ANNEX_G,136 .codec_mode = S5P_MFC_CODEC_VC1_DEC,137 .type = MFC_FMT_DEC,138 .num_planes = 1,139 .versions = MFC_V5PLUS_BITS,140 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,141 },142 {143 .fourcc = V4L2_PIX_FMT_VC1_ANNEX_L,144 .codec_mode = S5P_MFC_CODEC_VC1RCV_DEC,145 .type = MFC_FMT_DEC,146 .num_planes = 1,147 .versions = MFC_V5PLUS_BITS,148 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,149 },150 {151 .fourcc = V4L2_PIX_FMT_VP8,152 .codec_mode = S5P_MFC_CODEC_VP8_DEC,153 .type = MFC_FMT_DEC,154 .num_planes = 1,155 .versions = MFC_V6PLUS_BITS,156 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,157 },158 {159 .fourcc = V4L2_PIX_FMT_HEVC,160 .codec_mode = S5P_FIMV_CODEC_HEVC_DEC,161 .type = MFC_FMT_DEC,162 .num_planes = 1,163 .versions = MFC_V10PLUS_BITS,164 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION |165 V4L2_FMT_FLAG_CONTINUOUS_BYTESTREAM,166 },167 {168 .fourcc = V4L2_PIX_FMT_VP9,169 .codec_mode = S5P_FIMV_CODEC_VP9_DEC,170 .type = MFC_FMT_DEC,171 .num_planes = 1,172 .versions = MFC_V10PLUS_BITS,173 .flags = V4L2_FMT_FLAG_DYN_RESOLUTION,174 },175};176 177#define NUM_FORMATS ARRAY_SIZE(formats)178 179/* Find selected format description */180static const struct s5p_mfc_fmt *find_format(struct v4l2_format *f, unsigned int t)181{182 unsigned int i;183 184 for (i = 0; i < NUM_FORMATS; i++) {185 if (formats[i].fourcc == f->fmt.pix_mp.pixelformat &&186 formats[i].type == t)187 return &formats[i];188 }189 return NULL;190}191 192static struct mfc_control controls[] = {193 {194 .id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY,195 .type = V4L2_CTRL_TYPE_INTEGER,196 .name = "H264 Display Delay",197 .minimum = 0,198 .maximum = 16383,199 .step = 1,200 .default_value = 0,201 },202 {203 .id = V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY,204 .type = V4L2_CTRL_TYPE_INTEGER,205 .minimum = 0,206 .maximum = 16383,207 .step = 1,208 .default_value = 0,209 },210 {211 .id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE,212 .type = V4L2_CTRL_TYPE_BOOLEAN,213 .name = "H264 Display Delay Enable",214 .minimum = 0,215 .maximum = 1,216 .step = 1,217 .default_value = 0,218 },219 {220 .id = V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE,221 .type = V4L2_CTRL_TYPE_BOOLEAN,222 .minimum = 0,223 .maximum = 1,224 .default_value = 0,225 },226 {227 .id = V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER,228 .type = V4L2_CTRL_TYPE_BOOLEAN,229 .name = "Mpeg4 Loop Filter Enable",230 .minimum = 0,231 .maximum = 1,232 .step = 1,233 .default_value = 0,234 },235 {236 .id = V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE,237 .type = V4L2_CTRL_TYPE_BOOLEAN,238 .name = "Slice Interface Enable",239 .minimum = 0,240 .maximum = 1,241 .step = 1,242 .default_value = 0,243 },244 {245 .id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,246 .type = V4L2_CTRL_TYPE_INTEGER,247 .name = "Minimum number of cap bufs",248 .minimum = 1,249 .maximum = 32,250 .step = 1,251 .default_value = 1,252 .is_volatile = 1,253 },254};255 256#define NUM_CTRLS ARRAY_SIZE(controls)257 258/* Check whether a context should be run on hardware */259static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)260{261 /* Context is to parse header */262 if (ctx->src_queue_cnt >= 1 && ctx->state == MFCINST_GOT_INST)263 return 1;264 /* Context is to decode a frame */265 if (ctx->src_queue_cnt >= 1 &&266 ctx->state == MFCINST_RUNNING &&267 ctx->dst_queue_cnt >= ctx->pb_count)268 return 1;269 /* Context is to return last frame */270 if (ctx->state == MFCINST_FINISHING &&271 ctx->dst_queue_cnt >= ctx->pb_count)272 return 1;273 /* Context is to set buffers */274 if (ctx->src_queue_cnt >= 1 &&275 ctx->state == MFCINST_HEAD_PARSED &&276 ctx->capture_state == QUEUE_BUFS_MMAPED)277 return 1;278 /* Resolution change */279 if ((ctx->state == MFCINST_RES_CHANGE_INIT ||280 ctx->state == MFCINST_RES_CHANGE_FLUSH) &&281 ctx->dst_queue_cnt >= ctx->pb_count)282 return 1;283 if (ctx->state == MFCINST_RES_CHANGE_END &&284 ctx->src_queue_cnt >= 1)285 return 1;286 mfc_debug(2, "ctx is not ready\n");287 return 0;288}289 290static const struct s5p_mfc_codec_ops decoder_codec_ops = {291 .pre_seq_start = NULL,292 .post_seq_start = NULL,293 .pre_frame_start = NULL,294 .post_frame_start = NULL,295};296 297/* Query capabilities of the device */298static int vidioc_querycap(struct file *file, void *priv,299 struct v4l2_capability *cap)300{301 struct s5p_mfc_dev *dev = video_drvdata(file);302 303 strscpy(cap->driver, S5P_MFC_NAME, sizeof(cap->driver));304 strscpy(cap->card, dev->vfd_dec->name, sizeof(cap->card));305 return 0;306}307 308/* Enumerate format */309static int vidioc_enum_fmt(struct file *file, struct v4l2_fmtdesc *f,310 bool out)311{312 struct s5p_mfc_dev *dev = video_drvdata(file);313 int i, j = 0;314 315 for (i = 0; i < ARRAY_SIZE(formats); ++i) {316 if (out && formats[i].type != MFC_FMT_DEC)317 continue;318 else if (!out && formats[i].type != MFC_FMT_RAW)319 continue;320 else if ((dev->variant->version_bit & formats[i].versions) == 0)321 continue;322 323 if (j == f->index)324 break;325 ++j;326 }327 if (i == ARRAY_SIZE(formats))328 return -EINVAL;329 f->pixelformat = formats[i].fourcc;330 return 0;331}332 333static int vidioc_enum_fmt_vid_cap(struct file *file, void *pirv,334 struct v4l2_fmtdesc *f)335{336 return vidioc_enum_fmt(file, f, false);337}338 339static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,340 struct v4l2_fmtdesc *f)341{342 return vidioc_enum_fmt(file, f, true);343}344 345/* Get format */346static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)347{348 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);349 struct v4l2_pix_format_mplane *pix_mp;350 351 mfc_debug_enter();352 pix_mp = &f->fmt.pix_mp;353 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&354 (ctx->state == MFCINST_GOT_INST || ctx->state ==355 MFCINST_RES_CHANGE_END)) {356 /* If the MFC is parsing the header,357 * so wait until it is finished */358 s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET,359 0);360 }361 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE &&362 ctx->state >= MFCINST_HEAD_PARSED &&363 ctx->state < MFCINST_ABORT) {364 /* This is run on CAPTURE (decode output) */365 /* Width and height are set to the dimensions366 of the movie, the buffer is bigger and367 further processing stages should crop to this368 rectangle. */369 pix_mp->width = ctx->buf_width;370 pix_mp->height = ctx->buf_height;371 pix_mp->field = V4L2_FIELD_NONE;372 pix_mp->num_planes = ctx->dst_fmt->num_planes;373 /* Set pixelformat to the format in which MFC374 outputs the decoded frame */375 pix_mp->pixelformat = ctx->dst_fmt->fourcc;376 pix_mp->plane_fmt[0].bytesperline = ctx->stride[0];377 pix_mp->plane_fmt[0].sizeimage = ctx->luma_size;378 pix_mp->plane_fmt[1].bytesperline = ctx->stride[1];379 pix_mp->plane_fmt[1].sizeimage = ctx->chroma_size;380 if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420M || ctx->dst_fmt->fourcc ==381 V4L2_PIX_FMT_YVU420M) {382 pix_mp->plane_fmt[2].bytesperline = ctx->stride[2];383 pix_mp->plane_fmt[2].sizeimage = ctx->chroma_size_1;384 }385 } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {386 /* This is run on OUTPUT387 The buffer contains compressed image388 so width and height have no meaning */389 pix_mp->width = 0;390 pix_mp->height = 0;391 pix_mp->field = V4L2_FIELD_NONE;392 pix_mp->plane_fmt[0].bytesperline = ctx->dec_src_buf_size;393 pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size;394 pix_mp->pixelformat = ctx->src_fmt->fourcc;395 pix_mp->num_planes = ctx->src_fmt->num_planes;396 } else {397 mfc_err("Format could not be read\n");398 mfc_debug(2, "%s-- with error\n", __func__);399 return -EINVAL;400 }401 mfc_debug_leave();402 return 0;403}404 405/* Try format */406static int vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)407{408 struct s5p_mfc_dev *dev = video_drvdata(file);409 const struct s5p_mfc_fmt *fmt;410 411 mfc_debug(2, "Type is %d\n", f->type);412 if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {413 fmt = find_format(f, MFC_FMT_DEC);414 if (!fmt) {415 mfc_err("Unsupported format for source.\n");416 return -EINVAL;417 }418 if (fmt->codec_mode == S5P_FIMV_CODEC_NONE) {419 mfc_err("Unknown codec\n");420 return -EINVAL;421 }422 if ((dev->variant->version_bit & fmt->versions) == 0) {423 mfc_err("Unsupported format by this MFC version.\n");424 return -EINVAL;425 }426 } else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {427 fmt = find_format(f, MFC_FMT_RAW);428 if (!fmt) {429 mfc_err("Unsupported format for destination.\n");430 return -EINVAL;431 }432 if ((dev->variant->version_bit & fmt->versions) == 0) {433 mfc_err("Unsupported format by this MFC version.\n");434 return -EINVAL;435 }436 }437 438 return 0;439}440 441/* Set format */442static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)443{444 struct s5p_mfc_dev *dev = video_drvdata(file);445 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);446 int ret = 0;447 struct v4l2_pix_format_mplane *pix_mp;448 const struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;449 450 mfc_debug_enter();451 ret = vidioc_try_fmt(file, priv, f);452 pix_mp = &f->fmt.pix_mp;453 if (ret)454 return ret;455 if (vb2_is_streaming(&ctx->vq_src) || vb2_is_streaming(&ctx->vq_dst)) {456 v4l2_err(&dev->v4l2_dev, "%s queue busy\n", __func__);457 ret = -EBUSY;458 goto out;459 }460 if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {461 /* dst_fmt is validated by call to vidioc_try_fmt */462 ctx->dst_fmt = find_format(f, MFC_FMT_RAW);463 ret = 0;464 goto out;465 } else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {466 /* src_fmt is validated by call to vidioc_try_fmt */467 ctx->src_fmt = find_format(f, MFC_FMT_DEC);468 ctx->codec_mode = ctx->src_fmt->codec_mode;469 mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);470 pix_mp->height = 0;471 pix_mp->width = 0;472 if (pix_mp->plane_fmt[0].sizeimage == 0)473 pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size =474 DEF_CPB_SIZE;475 else if (pix_mp->plane_fmt[0].sizeimage > buf_size->cpb)476 ctx->dec_src_buf_size = buf_size->cpb;477 else478 ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage;479 pix_mp->plane_fmt[0].bytesperline = 0;480 ctx->state = MFCINST_INIT;481 ret = 0;482 goto out;483 } else {484 mfc_err("Wrong type error for S_FMT : %d", f->type);485 ret = -EINVAL;486 goto out;487 }488 489out:490 mfc_debug_leave();491 return ret;492}493 494static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,495 struct v4l2_requestbuffers *reqbufs)496{497 int ret = 0;498 499 s5p_mfc_clock_on(dev);500 501 if (reqbufs->count == 0) {502 mfc_debug(2, "Freeing buffers\n");503 ret = vb2_reqbufs(&ctx->vq_src, reqbufs);504 if (ret)505 goto out;506 ctx->src_bufs_cnt = 0;507 ctx->output_state = QUEUE_FREE;508 } else if (ctx->output_state == QUEUE_FREE) {509 /* Can only request buffers when we have a valid format set. */510 WARN_ON(ctx->src_bufs_cnt != 0);511 if (ctx->state != MFCINST_INIT) {512 mfc_err("Reqbufs called in an invalid state\n");513 ret = -EINVAL;514 goto out;515 }516 517 mfc_debug(2, "Allocating %d buffers for OUTPUT queue\n",518 reqbufs->count);519 ret = vb2_reqbufs(&ctx->vq_src, reqbufs);520 if (ret)521 goto out;522 523 ret = s5p_mfc_open_mfc_inst(dev, ctx);524 if (ret) {525 reqbufs->count = 0;526 vb2_reqbufs(&ctx->vq_src, reqbufs);527 goto out;528 }529 530 ctx->output_state = QUEUE_BUFS_REQUESTED;531 } else {532 mfc_err("Buffers have already been requested\n");533 ret = -EINVAL;534 }535out:536 s5p_mfc_clock_off(dev);537 if (ret)538 mfc_err("Failed allocating buffers for OUTPUT queue\n");539 return ret;540}541 542static int reqbufs_capture(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,543 struct v4l2_requestbuffers *reqbufs)544{545 int ret = 0;546 547 s5p_mfc_clock_on(dev);548 549 if (reqbufs->count == 0) {550 mfc_debug(2, "Freeing buffers\n");551 ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);552 if (ret)553 goto out;554 s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx);555 ctx->dst_bufs_cnt = 0;556 } else if (ctx->capture_state == QUEUE_FREE) {557 WARN_ON(ctx->dst_bufs_cnt != 0);558 mfc_debug(2, "Allocating %d buffers for CAPTURE queue\n",559 reqbufs->count);560 ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);561 if (ret)562 goto out;563 564 ctx->capture_state = QUEUE_BUFS_REQUESTED;565 ctx->total_dpb_count = reqbufs->count;566 567 ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_codec_buffers, ctx);568 if (ret) {569 mfc_err("Failed to allocate decoding buffers\n");570 reqbufs->count = 0;571 vb2_reqbufs(&ctx->vq_dst, reqbufs);572 ret = -ENOMEM;573 ctx->capture_state = QUEUE_FREE;574 goto out;575 }576 577 WARN_ON(ctx->dst_bufs_cnt != ctx->total_dpb_count);578 ctx->capture_state = QUEUE_BUFS_MMAPED;579 580 if (s5p_mfc_ctx_ready(ctx))581 set_work_bit_irqsave(ctx);582 s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);583 s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_INIT_BUFFERS_RET,584 0);585 } else {586 mfc_err("Buffers have already been requested\n");587 ret = -EINVAL;588 }589out:590 s5p_mfc_clock_off(dev);591 if (ret)592 mfc_err("Failed allocating buffers for CAPTURE queue\n");593 return ret;594}595 596/* Request buffers */597static int vidioc_reqbufs(struct file *file, void *priv,598 struct v4l2_requestbuffers *reqbufs)599{600 struct s5p_mfc_dev *dev = video_drvdata(file);601 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);602 603 if (reqbufs->memory != V4L2_MEMORY_MMAP) {604 mfc_debug(2, "Only V4L2_MEMORY_MMAP is supported\n");605 return -EINVAL;606 }607 608 if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {609 return reqbufs_output(dev, ctx, reqbufs);610 } else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {611 return reqbufs_capture(dev, ctx, reqbufs);612 } else {613 mfc_err("Invalid type requested\n");614 return -EINVAL;615 }616}617 618/* Query buffer */619static int vidioc_querybuf(struct file *file, void *priv,620 struct v4l2_buffer *buf)621{622 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);623 int ret;624 int i;625 626 if (buf->memory != V4L2_MEMORY_MMAP) {627 mfc_err("Only mmapped buffers can be used\n");628 return -EINVAL;629 }630 mfc_debug(2, "State: %d, buf->type: %d\n", ctx->state, buf->type);631 if (ctx->state == MFCINST_GOT_INST &&632 buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {633 ret = vb2_querybuf(&ctx->vq_src, buf);634 } else if (ctx->state == MFCINST_RUNNING &&635 buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {636 ret = vb2_querybuf(&ctx->vq_dst, buf);637 for (i = 0; i < buf->length; i++)638 buf->m.planes[i].m.mem_offset += DST_QUEUE_OFF_BASE;639 } else {640 mfc_err("vidioc_querybuf called in an inappropriate state\n");641 ret = -EINVAL;642 }643 mfc_debug_leave();644 return ret;645}646 647/* Queue a buffer */648static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)649{650 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);651 652 if (ctx->state == MFCINST_ERROR) {653 mfc_err("Call on QBUF after unrecoverable error\n");654 return -EIO;655 }656 if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)657 return vb2_qbuf(&ctx->vq_src, NULL, buf);658 else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)659 return vb2_qbuf(&ctx->vq_dst, NULL, buf);660 return -EINVAL;661}662 663/* Dequeue a buffer */664static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)665{666 const struct v4l2_event ev = {667 .type = V4L2_EVENT_EOS668 };669 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);670 int ret;671 672 if (ctx->state == MFCINST_ERROR) {673 mfc_err_limited("Call on DQBUF after unrecoverable error\n");674 return -EIO;675 }676 677 switch (buf->type) {678 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:679 return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);680 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:681 ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);682 if (ret)683 return ret;684 685 if (ctx->state == MFCINST_FINISHED &&686 (ctx->dst_bufs[buf->index].flags & MFC_BUF_FLAG_EOS))687 v4l2_event_queue_fh(&ctx->fh, &ev);688 return 0;689 default:690 return -EINVAL;691 }692}693 694/* Export DMA buffer */695static int vidioc_expbuf(struct file *file, void *priv,696 struct v4l2_exportbuffer *eb)697{698 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);699 700 if (eb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)701 return vb2_expbuf(&ctx->vq_src, eb);702 if (eb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)703 return vb2_expbuf(&ctx->vq_dst, eb);704 return -EINVAL;705}706 707/* Stream on */708static int vidioc_streamon(struct file *file, void *priv,709 enum v4l2_buf_type type)710{711 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);712 int ret = -EINVAL;713 714 mfc_debug_enter();715 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)716 ret = vb2_streamon(&ctx->vq_src, type);717 else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)718 ret = vb2_streamon(&ctx->vq_dst, type);719 mfc_debug_leave();720 return ret;721}722 723/* Stream off, which equals to a pause */724static int vidioc_streamoff(struct file *file, void *priv,725 enum v4l2_buf_type type)726{727 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);728 729 if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)730 return vb2_streamoff(&ctx->vq_src, type);731 else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)732 return vb2_streamoff(&ctx->vq_dst, type);733 return -EINVAL;734}735 736/* Set controls - v4l2 control framework */737static int s5p_mfc_dec_s_ctrl(struct v4l2_ctrl *ctrl)738{739 struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);740 741 switch (ctrl->id) {742 case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY:743 case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY:744 ctx->display_delay = ctrl->val;745 break;746 case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE:747 case V4L2_CID_MPEG_VIDEO_DEC_DISPLAY_DELAY_ENABLE:748 ctx->display_delay_enable = ctrl->val;749 break;750 case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER:751 ctx->loop_filter_mpeg4 = ctrl->val;752 break;753 case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE:754 ctx->slice_interface = ctrl->val;755 break;756 default:757 mfc_err("Invalid control 0x%08x\n", ctrl->id);758 return -EINVAL;759 }760 return 0;761}762 763static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl)764{765 struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);766 struct s5p_mfc_dev *dev = ctx->dev;767 768 switch (ctrl->id) {769 case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:770 if (ctx->state >= MFCINST_HEAD_PARSED &&771 ctx->state < MFCINST_ABORT) {772 ctrl->val = ctx->pb_count;773 break;774 } else if (ctx->state != MFCINST_INIT &&775 ctx->state != MFCINST_RES_CHANGE_END) {776 v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n");777 return -EINVAL;778 }779 /* Should wait for the header to be parsed */780 s5p_mfc_wait_for_done_ctx(ctx,781 S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);782 if (ctx->state >= MFCINST_HEAD_PARSED &&783 ctx->state < MFCINST_ABORT) {784 ctrl->val = ctx->pb_count;785 } else {786 v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n");787 return -EINVAL;788 }789 break;790 }791 return 0;792}793 794 795static const struct v4l2_ctrl_ops s5p_mfc_dec_ctrl_ops = {796 .s_ctrl = s5p_mfc_dec_s_ctrl,797 .g_volatile_ctrl = s5p_mfc_dec_g_v_ctrl,798};799 800/* Get compose information */801static int vidioc_g_selection(struct file *file, void *priv,802 struct v4l2_selection *s)803{804 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);805 struct s5p_mfc_dev *dev = ctx->dev;806 u32 left, right, top, bottom;807 u32 width, height;808 809 if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)810 return -EINVAL;811 812 if (ctx->state != MFCINST_HEAD_PARSED &&813 ctx->state != MFCINST_RUNNING &&814 ctx->state != MFCINST_FINISHING &&815 ctx->state != MFCINST_FINISHED) {816 mfc_err("Can not get compose information\n");817 return -EINVAL;818 }819 if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_H264) {820 left = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_h, ctx);821 right = left >> S5P_FIMV_SHARED_CROP_RIGHT_SHIFT;822 left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK;823 top = s5p_mfc_hw_call(dev->mfc_ops, get_crop_info_v, ctx);824 bottom = top >> S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT;825 top = top & S5P_FIMV_SHARED_CROP_TOP_MASK;826 width = ctx->img_width - left - right;827 height = ctx->img_height - top - bottom;828 mfc_debug(2, "Composing info [h264]: l=%d t=%d w=%d h=%d (r=%d b=%d fw=%d fh=%d\n",829 left, top, s->r.width, s->r.height, right, bottom,830 ctx->buf_width, ctx->buf_height);831 } else {832 left = 0;833 top = 0;834 width = ctx->img_width;835 height = ctx->img_height;836 mfc_debug(2, "Composing info: w=%d h=%d fw=%d fh=%d\n",837 s->r.width, s->r.height, ctx->buf_width,838 ctx->buf_height);839 }840 841 switch (s->target) {842 case V4L2_SEL_TGT_COMPOSE:843 case V4L2_SEL_TGT_COMPOSE_DEFAULT:844 case V4L2_SEL_TGT_COMPOSE_BOUNDS:845 s->r.left = left;846 s->r.top = top;847 s->r.width = width;848 s->r.height = height;849 break;850 default:851 return -EINVAL;852 }853 return 0;854}855 856static int vidioc_decoder_cmd(struct file *file, void *priv,857 struct v4l2_decoder_cmd *cmd)858{859 struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);860 struct s5p_mfc_dev *dev = ctx->dev;861 struct s5p_mfc_buf *buf;862 unsigned long flags;863 864 switch (cmd->cmd) {865 case V4L2_DEC_CMD_STOP:866 if (cmd->flags != 0)867 return -EINVAL;868 869 if (!vb2_is_streaming(&ctx->vq_src))870 return -EINVAL;871 872 spin_lock_irqsave(&dev->irqlock, flags);873 if (list_empty(&ctx->src_queue)) {874 mfc_err("EOS: empty src queue, entering finishing state");875 ctx->state = MFCINST_FINISHING;876 if (s5p_mfc_ctx_ready(ctx))877 set_work_bit_irqsave(ctx);878 spin_unlock_irqrestore(&dev->irqlock, flags);879 s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);880 } else {881 mfc_err("EOS: marking last buffer of stream");882 buf = list_entry(ctx->src_queue.prev,883 struct s5p_mfc_buf, list);884 if (buf->flags & MFC_BUF_FLAG_USED)885 ctx->state = MFCINST_FINISHING;886 else887 buf->flags |= MFC_BUF_FLAG_EOS;888 spin_unlock_irqrestore(&dev->irqlock, flags);889 }890 break;891 default:892 return -EINVAL;893 }894 return 0;895}896 897static int vidioc_subscribe_event(struct v4l2_fh *fh,898 const struct v4l2_event_subscription *sub)899{900 switch (sub->type) {901 case V4L2_EVENT_EOS:902 return v4l2_event_subscribe(fh, sub, 2, NULL);903 case V4L2_EVENT_SOURCE_CHANGE:904 return v4l2_src_change_event_subscribe(fh, sub);905 default:906 return -EINVAL;907 }908}909 910 911/* v4l2_ioctl_ops */912static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {913 .vidioc_querycap = vidioc_querycap,914 .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,915 .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,916 .vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt,917 .vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt,918 .vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt,919 .vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt,920 .vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt,921 .vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt,922 .vidioc_reqbufs = vidioc_reqbufs,923 .vidioc_querybuf = vidioc_querybuf,924 .vidioc_qbuf = vidioc_qbuf,925 .vidioc_dqbuf = vidioc_dqbuf,926 .vidioc_expbuf = vidioc_expbuf,927 .vidioc_streamon = vidioc_streamon,928 .vidioc_streamoff = vidioc_streamoff,929 .vidioc_g_selection = vidioc_g_selection,930 .vidioc_decoder_cmd = vidioc_decoder_cmd,931 .vidioc_subscribe_event = vidioc_subscribe_event,932 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,933};934 935static int s5p_mfc_queue_setup(struct vb2_queue *vq,936 unsigned int *buf_count,937 unsigned int *plane_count, unsigned int psize[],938 struct device *alloc_devs[])939{940 struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);941 struct s5p_mfc_dev *dev = ctx->dev;942 const struct v4l2_format_info *format;943 944 /* Video output for decoding (source)945 * this can be set after getting an instance */946 if (ctx->state == MFCINST_INIT &&947 vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {948 /* A single plane is required for input */949 *plane_count = 1;950 if (*buf_count < 1)951 *buf_count = 1;952 if (*buf_count > MFC_MAX_BUFFERS)953 *buf_count = MFC_MAX_BUFFERS;954 /* Video capture for decoding (destination)955 * this can be set after the header was parsed */956 } else if (ctx->state == MFCINST_HEAD_PARSED &&957 vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {958 /* Output plane count is 2 - one for Y and one for CbCr */959 format = v4l2_format_info(ctx->dst_fmt->fourcc);960 if (!format) {961 mfc_err("invalid format\n");962 return -EINVAL;963 }964 *plane_count = format->comp_planes;965 966 /* Setup buffer count */967 if (*buf_count < ctx->pb_count)968 *buf_count = ctx->pb_count;969 if (*buf_count > ctx->pb_count + MFC_MAX_EXTRA_DPB)970 *buf_count = ctx->pb_count + MFC_MAX_EXTRA_DPB;971 if (*buf_count > MFC_MAX_BUFFERS)972 *buf_count = MFC_MAX_BUFFERS;973 } else {974 mfc_err("State seems invalid. State = %d, vq->type = %d\n",975 ctx->state, vq->type);976 return -EINVAL;977 }978 mfc_debug(2, "Buffer count=%d, plane count=%d\n",979 *buf_count, *plane_count);980 if (ctx->state == MFCINST_HEAD_PARSED &&981 vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {982 psize[0] = ctx->luma_size;983 psize[1] = ctx->chroma_size;984 if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420M || ctx->dst_fmt->fourcc ==985 V4L2_PIX_FMT_YVU420M)986 psize[2] = ctx->chroma_size_1;987 if (IS_MFCV6_PLUS(dev))988 alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX];989 else990 alloc_devs[0] = ctx->dev->mem_dev[BANK_R_CTX];991 alloc_devs[1] = ctx->dev->mem_dev[BANK_L_CTX];992 if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420M || ctx->dst_fmt->fourcc ==993 V4L2_PIX_FMT_YVU420M)994 alloc_devs[2] = ctx->dev->mem_dev[BANK_L_CTX];995 } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE && ctx->state == MFCINST_INIT) {996 psize[0] = ctx->dec_src_buf_size;997 alloc_devs[0] = ctx->dev->mem_dev[BANK_L_CTX];998 } else {999 mfc_err("This video node is dedicated to decoding. Decoding not initialized\n");1000 return -EINVAL;1001 }1002 return 0;1003}1004 1005static int s5p_mfc_buf_init(struct vb2_buffer *vb)1006{1007 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);1008 struct vb2_queue *vq = vb->vb2_queue;1009 struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);1010 unsigned int i;1011 1012 if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {1013 if (ctx->capture_state == QUEUE_BUFS_MMAPED)1014 return 0;1015 for (i = 0; i < ctx->dst_fmt->num_planes; i++) {1016 if (IS_ERR_OR_NULL(ERR_PTR(1017 vb2_dma_contig_plane_dma_addr(vb, i)))) {1018 mfc_err("Plane mem not allocated\n");1019 return -EINVAL;1020 }1021 }1022 if (vb2_plane_size(vb, 0) < ctx->luma_size ||1023 vb2_plane_size(vb, 1) < ctx->chroma_size) {1024 mfc_err("Plane buffer (CAPTURE) is too small\n");1025 return -EINVAL;1026 }1027 if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420M || ctx->dst_fmt->fourcc ==1028 V4L2_PIX_FMT_YVU420M) {1029 if (vb2_plane_size(vb, 2) < ctx->chroma_size_1) {1030 mfc_err("Plane buffer (CAPTURE) is too small\n");1031 return -EINVAL;1032 }1033 }1034 i = vb->index;1035 ctx->dst_bufs[i].b = vbuf;1036 ctx->dst_bufs[i].cookie.raw.luma =1037 vb2_dma_contig_plane_dma_addr(vb, 0);1038 ctx->dst_bufs[i].cookie.raw.chroma =1039 vb2_dma_contig_plane_dma_addr(vb, 1);1040 if (ctx->dst_fmt->fourcc == V4L2_PIX_FMT_YUV420M || ctx->dst_fmt->fourcc ==1041 V4L2_PIX_FMT_YVU420M) {1042 ctx->dst_bufs[i].cookie.raw.chroma_1 =1043 vb2_dma_contig_plane_dma_addr(vb, 2);1044 }1045 ctx->dst_bufs_cnt++;1046 } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {1047 if (IS_ERR_OR_NULL(ERR_PTR(1048 vb2_dma_contig_plane_dma_addr(vb, 0)))) {1049 mfc_err("Plane memory not allocated\n");1050 return -EINVAL;1051 }1052 if (vb2_plane_size(vb, 0) < ctx->dec_src_buf_size) {1053 mfc_err("Plane buffer (OUTPUT) is too small\n");1054 return -EINVAL;1055 }1056 1057 i = vb->index;1058 ctx->src_bufs[i].b = vbuf;1059 ctx->src_bufs[i].cookie.stream =1060 vb2_dma_contig_plane_dma_addr(vb, 0);1061 ctx->src_bufs_cnt++;1062 } else {1063 mfc_err("s5p_mfc_buf_init: unknown queue type\n");1064 return -EINVAL;1065 }1066 return 0;1067}1068 1069static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)1070{1071 struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);1072 struct s5p_mfc_dev *dev = ctx->dev;1073 1074 v4l2_ctrl_handler_setup(&ctx->ctrl_handler);1075 if (ctx->state == MFCINST_FINISHING ||1076 ctx->state == MFCINST_FINISHED)1077 ctx->state = MFCINST_RUNNING;1078 /* If context is ready then dev = work->data;schedule it to run */1079 if (s5p_mfc_ctx_ready(ctx))1080 set_work_bit_irqsave(ctx);1081 s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);1082 return 0;1083}1084 1085static void s5p_mfc_stop_streaming(struct vb2_queue *q)1086{1087 unsigned long flags;1088 struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);1089 struct s5p_mfc_dev *dev = ctx->dev;1090 int aborted = 0;1091 1092 spin_lock_irqsave(&dev->irqlock, flags);1093 if ((ctx->state == MFCINST_FINISHING ||1094 ctx->state == MFCINST_RUNNING) &&1095 dev->curr_ctx == ctx->num && dev->hw_lock) {1096 ctx->state = MFCINST_ABORT;1097 spin_unlock_irqrestore(&dev->irqlock, flags);1098 s5p_mfc_wait_for_done_ctx(ctx,1099 S5P_MFC_R2H_CMD_FRAME_DONE_RET, 0);1100 aborted = 1;1101 spin_lock_irqsave(&dev->irqlock, flags);1102 }1103 if (q->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {1104 s5p_mfc_cleanup_queue(&ctx->dst_queue, &ctx->vq_dst);1105 INIT_LIST_HEAD(&ctx->dst_queue);1106 ctx->dst_queue_cnt = 0;1107 ctx->dpb_flush_flag = 1;1108 ctx->dec_dst_flag = 0;1109 if (IS_MFCV6_PLUS(dev) && (ctx->state == MFCINST_RUNNING)) {1110 ctx->state = MFCINST_FLUSH;1111 set_work_bit_irqsave(ctx);1112 s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);1113 spin_unlock_irqrestore(&dev->irqlock, flags);1114 if (s5p_mfc_wait_for_done_ctx(ctx,1115 S5P_MFC_R2H_CMD_DPB_FLUSH_RET, 0))1116 mfc_err("Err flushing buffers\n");1117 spin_lock_irqsave(&dev->irqlock, flags);1118 }1119 } else if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {1120 s5p_mfc_cleanup_queue(&ctx->src_queue, &ctx->vq_src);1121 INIT_LIST_HEAD(&ctx->src_queue);1122 ctx->src_queue_cnt = 0;1123 }1124 if (aborted)1125 ctx->state = MFCINST_RUNNING;1126 spin_unlock_irqrestore(&dev->irqlock, flags);1127}1128 1129 1130static void s5p_mfc_buf_queue(struct vb2_buffer *vb)1131{1132 struct vb2_queue *vq = vb->vb2_queue;1133 struct s5p_mfc_ctx *ctx = fh_to_ctx(vq->drv_priv);1134 struct s5p_mfc_dev *dev = ctx->dev;1135 unsigned long flags;1136 struct s5p_mfc_buf *mfc_buf;1137 1138 if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {1139 mfc_buf = &ctx->src_bufs[vb->index];1140 mfc_buf->flags &= ~MFC_BUF_FLAG_USED;1141 spin_lock_irqsave(&dev->irqlock, flags);1142 list_add_tail(&mfc_buf->list, &ctx->src_queue);1143 ctx->src_queue_cnt++;1144 spin_unlock_irqrestore(&dev->irqlock, flags);1145 } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {1146 mfc_buf = &ctx->dst_bufs[vb->index];1147 mfc_buf->flags &= ~MFC_BUF_FLAG_USED;1148 /* Mark destination as available for use by MFC */1149 spin_lock_irqsave(&dev->irqlock, flags);1150 set_bit(vb->index, &ctx->dec_dst_flag);1151 list_add_tail(&mfc_buf->list, &ctx->dst_queue);1152 ctx->dst_queue_cnt++;1153 spin_unlock_irqrestore(&dev->irqlock, flags);1154 } else {1155 mfc_err("Unsupported buffer type (%d)\n", vq->type);1156 }1157 if (s5p_mfc_ctx_ready(ctx))1158 set_work_bit_irqsave(ctx);1159 s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);1160}1161 1162static const struct vb2_ops s5p_mfc_dec_qops = {1163 .queue_setup = s5p_mfc_queue_setup,1164 .wait_prepare = vb2_ops_wait_prepare,1165 .wait_finish = vb2_ops_wait_finish,1166 .buf_init = s5p_mfc_buf_init,1167 .start_streaming = s5p_mfc_start_streaming,1168 .stop_streaming = s5p_mfc_stop_streaming,1169 .buf_queue = s5p_mfc_buf_queue,1170};1171 1172const struct s5p_mfc_codec_ops *get_dec_codec_ops(void)1173{1174 return &decoder_codec_ops;1175}1176 1177const struct vb2_ops *get_dec_queue_ops(void)1178{1179 return &s5p_mfc_dec_qops;1180}1181 1182const struct v4l2_ioctl_ops *get_dec_v4l2_ioctl_ops(void)1183{1184 return &s5p_mfc_dec_ioctl_ops;1185}1186 1187#define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2WHICH(x) == V4L2_CTRL_CLASS_CODEC) \1188 && V4L2_CTRL_DRIVER_PRIV(x))1189 1190int s5p_mfc_dec_ctrls_setup(struct s5p_mfc_ctx *ctx)1191{1192 struct v4l2_ctrl_config cfg;1193 int i;1194 1195 v4l2_ctrl_handler_init(&ctx->ctrl_handler, NUM_CTRLS);1196 if (ctx->ctrl_handler.error) {1197 mfc_err("v4l2_ctrl_handler_init failed\n");1198 return ctx->ctrl_handler.error;1199 }1200 1201 for (i = 0; i < NUM_CTRLS; i++) {1202 if (IS_MFC51_PRIV(controls[i].id)) {1203 memset(&cfg, 0, sizeof(struct v4l2_ctrl_config));1204 cfg.ops = &s5p_mfc_dec_ctrl_ops;1205 cfg.id = controls[i].id;1206 cfg.min = controls[i].minimum;1207 cfg.max = controls[i].maximum;1208 cfg.def = controls[i].default_value;1209 cfg.name = controls[i].name;1210 cfg.type = controls[i].type;1211 1212 cfg.step = controls[i].step;1213 cfg.menu_skip_mask = 0;1214 1215 ctx->ctrls[i] = v4l2_ctrl_new_custom(&ctx->ctrl_handler,1216 &cfg, NULL);1217 } else {1218 ctx->ctrls[i] = v4l2_ctrl_new_std(&ctx->ctrl_handler,1219 &s5p_mfc_dec_ctrl_ops,1220 controls[i].id, controls[i].minimum,1221 controls[i].maximum, controls[i].step,1222 controls[i].default_value);1223 }1224 if (ctx->ctrl_handler.error) {1225 mfc_err("Adding control (%d) failed\n", i);1226 return ctx->ctrl_handler.error;1227 }1228 if (controls[i].is_volatile && ctx->ctrls[i])1229 ctx->ctrls[i]->flags |= V4L2_CTRL_FLAG_VOLATILE;1230 }1231 return 0;1232}1233 1234void s5p_mfc_dec_ctrls_delete(struct s5p_mfc_ctx *ctx)1235{1236 int i;1237 1238 v4l2_ctrl_handler_free(&ctx->ctrl_handler);1239 for (i = 0; i < NUM_CTRLS; i++)1240 ctx->ctrls[i] = NULL;1241}1242 1243void s5p_mfc_dec_init(struct s5p_mfc_ctx *ctx)1244{1245 struct v4l2_format f;1246 f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_H264;1247 ctx->src_fmt = find_format(&f, MFC_FMT_DEC);1248 if (IS_MFCV8_PLUS(ctx->dev))1249 f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12M;1250 else if (IS_MFCV6_PLUS(ctx->dev))1251 f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT_16X16;1252 else1253 f.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_NV12MT;1254 ctx->dst_fmt = find_format(&f, MFC_FMT_RAW);1255 mfc_debug(2, "Default src_fmt is %p, dest_fmt is %p\n",1256 ctx->src_fmt, ctx->dst_fmt);1257}1258 1259