2011-06-21 10:51:26 -03:00
/*
2012-08-14 17:31:16 -03:00
* linux / drivers / media / platform / s5p - mfc / s5p_mfc_dec . c
2011-06-21 10:51:26 -03:00
*
* Copyright ( C ) 2011 Samsung Electronics Co . , Ltd .
* http : //www.samsung.com/
* Kamil Debski , < k . debski @ 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 <linux/clk.h>
# include <linux/interrupt.h>
# include <linux/io.h>
# include <linux/module.h>
# include <linux/platform_device.h>
# include <linux/sched.h>
# include <linux/slab.h>
# include <linux/videodev2.h>
# include <linux/workqueue.h>
# include <media/v4l2-ctrls.h>
2013-01-11 12:29:33 -03:00
# include <media/v4l2-event.h>
2015-09-22 10:30:29 -03:00
# include <media/videobuf2-v4l2.h>
2011-06-21 10:51:26 -03:00
# include "s5p_mfc_common.h"
2014-05-19 09:32:59 -03:00
# include "s5p_mfc_ctrl.h"
2011-06-21 10:51:26 -03:00
# include "s5p_mfc_debug.h"
# include "s5p_mfc_dec.h"
# include "s5p_mfc_intr.h"
2012-10-03 22:19:08 -03:00
# include "s5p_mfc_opr.h"
2011-06-21 10:51:26 -03:00
# include "s5p_mfc_pm.h"
static struct s5p_mfc_fmt formats [ ] = {
2012-10-03 22:19:11 -03:00
{
. name = " 4:2:0 2 Planes 16x16 Tiles " ,
. fourcc = V4L2_PIX_FMT_NV12MT_16X16 ,
. codec_mode = S5P_MFC_CODEC_NONE ,
. type = MFC_FMT_RAW ,
. num_planes = 2 ,
2014-05-20 10:15:13 -03:00
. versions = MFC_V6_BIT | MFC_V7_BIT ,
2012-10-03 22:19:11 -03:00
} ,
2011-06-21 10:51:26 -03:00
{
. name = " 4:2:0 2 Planes 64x32 Tiles " ,
. fourcc = V4L2_PIX_FMT_NV12MT ,
2012-10-03 22:19:08 -03:00
. codec_mode = S5P_MFC_CODEC_NONE ,
2011-06-21 10:51:26 -03:00
. type = MFC_FMT_RAW ,
. num_planes = 2 ,
2014-05-20 10:15:13 -03:00
. versions = MFC_V5_BIT ,
2012-10-03 22:19:08 -03:00
} ,
2011-06-21 10:51:26 -03:00
{
2012-10-03 22:19:11 -03:00
. name = " 4:2:0 2 Planes Y/CbCr " ,
. fourcc = V4L2_PIX_FMT_NV12M ,
. codec_mode = S5P_MFC_CODEC_NONE ,
. type = MFC_FMT_RAW ,
. num_planes = 2 ,
2014-05-19 09:50:01 -03:00
. versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT ,
2012-10-03 22:19:11 -03:00
} ,
{
. name = " 4:2:0 2 Planes Y/CrCb " ,
. fourcc = V4L2_PIX_FMT_NV21M ,
. codec_mode = S5P_MFC_CODEC_NONE ,
. type = MFC_FMT_RAW ,
. num_planes = 2 ,
2014-05-19 09:50:01 -03:00
. versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT ,
2012-10-03 22:19:11 -03:00
} ,
{
. name = " H264 Encoded Stream " ,
. fourcc = V4L2_PIX_FMT_H264 ,
. codec_mode = S5P_MFC_CODEC_H264_DEC ,
. type = MFC_FMT_DEC ,
. num_planes = 1 ,
2014-05-19 09:50:01 -03:00
. versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
MFC_V8_BIT ,
2011-06-21 10:51:26 -03:00
} ,
{
2012-10-03 22:19:11 -03:00
. name = " H264/MVC Encoded Stream " ,
. fourcc = V4L2_PIX_FMT_H264_MVC ,
. codec_mode = S5P_MFC_CODEC_H264_MVC_DEC ,
. type = MFC_FMT_DEC ,
. num_planes = 1 ,
2014-05-19 09:50:01 -03:00
. versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT ,
2011-06-21 10:51:26 -03:00
} ,
{
2012-10-03 22:19:11 -03:00
. name = " H263 Encoded Stream " ,
. fourcc = V4L2_PIX_FMT_H263 ,
. codec_mode = S5P_MFC_CODEC_H263_DEC ,
. type = MFC_FMT_DEC ,
. num_planes = 1 ,
2014-05-19 09:50:01 -03:00
. versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
MFC_V8_BIT ,
2011-06-21 10:51:26 -03:00
} ,
{
2012-10-03 22:19:11 -03:00
. name = " MPEG1 Encoded Stream " ,
. fourcc = V4L2_PIX_FMT_MPEG1 ,
. codec_mode = S5P_MFC_CODEC_MPEG2_DEC ,
. type = MFC_FMT_DEC ,
. num_planes = 1 ,
2014-05-19 09:50:01 -03:00
. versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
MFC_V8_BIT ,
2011-06-21 10:51:26 -03:00
} ,
{
2012-10-03 22:19:11 -03:00
. name = " MPEG2 Encoded Stream " ,
. fourcc = V4L2_PIX_FMT_MPEG2 ,
. codec_mode = S5P_MFC_CODEC_MPEG2_DEC ,
. type = MFC_FMT_DEC ,
. num_planes = 1 ,
2014-05-19 09:50:01 -03:00
. versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
MFC_V8_BIT ,
2011-06-21 10:51:26 -03:00
} ,
{
2012-10-03 22:19:11 -03:00
. name = " MPEG4 Encoded Stream " ,
. fourcc = V4L2_PIX_FMT_MPEG4 ,
. codec_mode = S5P_MFC_CODEC_MPEG4_DEC ,
. type = MFC_FMT_DEC ,
. num_planes = 1 ,
2014-05-19 09:50:01 -03:00
. versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
MFC_V8_BIT ,
2011-06-21 10:51:26 -03:00
} ,
{
2012-10-03 22:19:11 -03:00
. name = " XviD Encoded Stream " ,
. fourcc = V4L2_PIX_FMT_XVID ,
. codec_mode = S5P_MFC_CODEC_MPEG4_DEC ,
. type = MFC_FMT_DEC ,
. num_planes = 1 ,
2014-05-19 09:50:01 -03:00
. versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
MFC_V8_BIT ,
2011-06-21 10:51:26 -03:00
} ,
{
2012-10-03 22:19:11 -03:00
. name = " VC1 Encoded Stream " ,
. fourcc = V4L2_PIX_FMT_VC1_ANNEX_G ,
. codec_mode = S5P_MFC_CODEC_VC1_DEC ,
. type = MFC_FMT_DEC ,
. num_planes = 1 ,
2014-05-19 09:50:01 -03:00
. versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
MFC_V8_BIT ,
2011-06-21 10:51:26 -03:00
} ,
{
2012-10-03 22:19:11 -03:00
. name = " VC1 RCV Encoded Stream " ,
. fourcc = V4L2_PIX_FMT_VC1_ANNEX_L ,
. codec_mode = S5P_MFC_CODEC_VC1RCV_DEC ,
. type = MFC_FMT_DEC ,
. num_planes = 1 ,
2014-05-19 09:50:01 -03:00
. versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
MFC_V8_BIT ,
2012-10-03 22:19:11 -03:00
} ,
{
. name = " VP8 Encoded Stream " ,
. fourcc = V4L2_PIX_FMT_VP8 ,
. codec_mode = S5P_MFC_CODEC_VP8_DEC ,
. type = MFC_FMT_DEC ,
. num_planes = 1 ,
2014-05-19 09:50:01 -03:00
. versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT ,
2011-06-21 10:51:26 -03:00
} ,
} ;
# define NUM_FORMATS ARRAY_SIZE(formats)
/* Find selected format description */
static struct s5p_mfc_fmt * find_format ( struct v4l2_format * f , unsigned int t )
{
unsigned int i ;
for ( i = 0 ; i < NUM_FORMATS ; i + + ) {
if ( formats [ i ] . fourcc = = f - > fmt . pix_mp . pixelformat & &
formats [ i ] . type = = t )
return & formats [ i ] ;
}
return NULL ;
}
static struct mfc_control controls [ ] = {
{
. id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY ,
. type = V4L2_CTRL_TYPE_INTEGER ,
. name = " H264 Display Delay " ,
. minimum = 0 ,
. maximum = 16383 ,
. step = 1 ,
. default_value = 0 ,
} ,
{
. id = V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE ,
. type = V4L2_CTRL_TYPE_BOOLEAN ,
. name = " H264 Display Delay Enable " ,
. minimum = 0 ,
. maximum = 1 ,
. step = 1 ,
. default_value = 0 ,
} ,
{
. id = V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER ,
. type = V4L2_CTRL_TYPE_BOOLEAN ,
. name = " Mpeg4 Loop Filter Enable " ,
. minimum = 0 ,
. maximum = 1 ,
. step = 1 ,
. default_value = 0 ,
} ,
{
. id = V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE ,
. type = V4L2_CTRL_TYPE_BOOLEAN ,
. name = " Slice Interface Enable " ,
. minimum = 0 ,
. maximum = 1 ,
. step = 1 ,
. default_value = 0 ,
} ,
{
. id = V4L2_CID_MIN_BUFFERS_FOR_CAPTURE ,
. type = V4L2_CTRL_TYPE_INTEGER ,
. name = " Minimum number of cap bufs " ,
. minimum = 1 ,
. maximum = 32 ,
. step = 1 ,
. default_value = 1 ,
2011-12-27 10:07:24 -03:00
. is_volatile = 1 ,
2011-06-21 10:51:26 -03:00
} ,
} ;
# define NUM_CTRLS ARRAY_SIZE(controls)
/* Check whether a context should be run on hardware */
static int s5p_mfc_ctx_ready ( struct s5p_mfc_ctx * ctx )
{
/* Context is to parse header */
if ( ctx - > src_queue_cnt > = 1 & & ctx - > state = = MFCINST_GOT_INST )
return 1 ;
/* Context is to decode a frame */
if ( ctx - > src_queue_cnt > = 1 & &
ctx - > state = = MFCINST_RUNNING & &
2013-04-24 09:41:53 -03:00
ctx - > dst_queue_cnt > = ctx - > pb_count )
2011-06-21 10:51:26 -03:00
return 1 ;
/* Context is to return last frame */
if ( ctx - > state = = MFCINST_FINISHING & &
2013-04-24 09:41:53 -03:00
ctx - > dst_queue_cnt > = ctx - > pb_count )
2011-06-21 10:51:26 -03:00
return 1 ;
/* Context is to set buffers */
if ( ctx - > src_queue_cnt > = 1 & &
ctx - > state = = MFCINST_HEAD_PARSED & &
ctx - > capture_state = = QUEUE_BUFS_MMAPED )
return 1 ;
/* Resolution change */
if ( ( ctx - > state = = MFCINST_RES_CHANGE_INIT | |
ctx - > state = = MFCINST_RES_CHANGE_FLUSH ) & &
2013-04-24 09:41:53 -03:00
ctx - > dst_queue_cnt > = ctx - > pb_count )
2011-06-21 10:51:26 -03:00
return 1 ;
if ( ctx - > state = = MFCINST_RES_CHANGE_END & &
ctx - > src_queue_cnt > = 1 )
return 1 ;
mfc_debug ( 2 , " ctx is not ready \n " ) ;
return 0 ;
}
2015-11-22 05:45:34 -02:00
static const struct s5p_mfc_codec_ops decoder_codec_ops = {
2011-06-21 10:51:26 -03:00
. pre_seq_start = NULL ,
. post_seq_start = NULL ,
. pre_frame_start = NULL ,
. post_frame_start = NULL ,
} ;
/* Query capabilities of the device */
static int vidioc_querycap ( struct file * file , void * priv ,
struct v4l2_capability * cap )
{
struct s5p_mfc_dev * dev = video_drvdata ( file ) ;
2016-06-16 18:40:31 -03:00
strncpy ( cap - > driver , S5P_MFC_NAME , sizeof ( cap - > driver ) - 1 ) ;
strncpy ( cap - > card , dev - > vfd_dec - > name , sizeof ( cap - > card ) - 1 ) ;
2016-06-16 18:40:30 -03:00
snprintf ( cap - > bus_info , sizeof ( cap - > bus_info ) , " platform:%s " ,
dev_name ( & dev - > plat_dev - > dev ) ) ;
2012-07-26 09:30:00 -03:00
/*
* This is only a mem - to - mem video device . The capture and output
* device capability flags are left only for backward compatibility
* and are scheduled for removal .
*/
2014-11-24 06:37:26 -03:00
cap - > device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING ;
cap - > capabilities = cap - > device_caps | V4L2_CAP_DEVICE_CAPS ;
2011-06-21 10:51:26 -03:00
return 0 ;
}
/* Enumerate format */
2014-05-20 10:15:13 -03:00
static int vidioc_enum_fmt ( struct file * file , struct v4l2_fmtdesc * f ,
2014-09-18 16:41:12 -03:00
bool out )
2011-06-21 10:51:26 -03:00
{
2014-05-20 10:15:13 -03:00
struct s5p_mfc_dev * dev = video_drvdata ( file ) ;
2011-06-21 10:51:26 -03:00
struct s5p_mfc_fmt * fmt ;
int i , j = 0 ;
for ( i = 0 ; i < ARRAY_SIZE ( formats ) ; + + i ) {
if ( out & & formats [ i ] . type ! = MFC_FMT_DEC )
continue ;
else if ( ! out & & formats [ i ] . type ! = MFC_FMT_RAW )
continue ;
2014-05-20 10:15:13 -03:00
else if ( ( dev - > variant - > version_bit & formats [ i ] . versions ) = = 0 )
continue ;
2011-06-21 10:51:26 -03:00
if ( j = = f - > index )
break ;
+ + j ;
}
if ( i = = ARRAY_SIZE ( formats ) )
return - EINVAL ;
fmt = & formats [ i ] ;
strlcpy ( f - > description , fmt - > name , sizeof ( f - > description ) ) ;
f - > pixelformat = fmt - > fourcc ;
return 0 ;
}
static int vidioc_enum_fmt_vid_cap_mplane ( struct file * file , void * pirv ,
struct v4l2_fmtdesc * f )
{
2014-09-18 16:41:12 -03:00
return vidioc_enum_fmt ( file , f , false ) ;
2011-06-21 10:51:26 -03:00
}
2014-05-20 10:15:13 -03:00
static int vidioc_enum_fmt_vid_out_mplane ( struct file * file , void * priv ,
2011-06-21 10:51:26 -03:00
struct v4l2_fmtdesc * f )
{
2014-09-18 16:41:12 -03:00
return vidioc_enum_fmt ( file , f , true ) ;
2011-06-21 10:51:26 -03:00
}
/* Get format */
static int vidioc_g_fmt ( struct file * file , void * priv , struct v4l2_format * f )
{
struct s5p_mfc_ctx * ctx = fh_to_ctx ( priv ) ;
struct v4l2_pix_format_mplane * pix_mp ;
mfc_debug_enter ( ) ;
pix_mp = & f - > fmt . pix_mp ;
if ( f - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE & &
( ctx - > state = = MFCINST_GOT_INST | | ctx - > state = =
MFCINST_RES_CHANGE_END ) ) {
/* If the MFC is parsing the header,
* so wait until it is finished */
2012-10-03 22:19:08 -03:00
s5p_mfc_wait_for_done_ctx ( ctx , S5P_MFC_R2H_CMD_SEQ_DONE_RET ,
2011-06-21 10:51:26 -03:00
0 ) ;
}
if ( f - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE & &
ctx - > state > = MFCINST_HEAD_PARSED & &
ctx - > state < MFCINST_ABORT ) {
/* This is run on CAPTURE (decode output) */
/* Width and height are set to the dimensions
of the movie , the buffer is bigger and
further processing stages should crop to this
rectangle . */
pix_mp - > width = ctx - > buf_width ;
pix_mp - > height = ctx - > buf_height ;
pix_mp - > field = V4L2_FIELD_NONE ;
pix_mp - > num_planes = 2 ;
/* Set pixelformat to the format in which MFC
outputs the decoded frame */
2013-05-30 16:42:08 -03:00
pix_mp - > pixelformat = ctx - > dst_fmt - > fourcc ;
2011-06-21 10:51:26 -03:00
pix_mp - > plane_fmt [ 0 ] . bytesperline = ctx - > buf_width ;
pix_mp - > plane_fmt [ 0 ] . sizeimage = ctx - > luma_size ;
pix_mp - > plane_fmt [ 1 ] . bytesperline = ctx - > buf_width ;
pix_mp - > plane_fmt [ 1 ] . sizeimage = ctx - > chroma_size ;
} else if ( f - > type = = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ) {
/* This is run on OUTPUT
The buffer contains compressed image
so width and height have no meaning */
pix_mp - > width = 0 ;
pix_mp - > height = 0 ;
pix_mp - > field = V4L2_FIELD_NONE ;
pix_mp - > plane_fmt [ 0 ] . bytesperline = ctx - > dec_src_buf_size ;
pix_mp - > plane_fmt [ 0 ] . sizeimage = ctx - > dec_src_buf_size ;
pix_mp - > pixelformat = ctx - > src_fmt - > fourcc ;
pix_mp - > num_planes = ctx - > src_fmt - > num_planes ;
} else {
mfc_err ( " Format could not be read \n " ) ;
mfc_debug ( 2 , " %s-- with error \n " , __func__ ) ;
return - EINVAL ;
}
mfc_debug_leave ( ) ;
return 0 ;
}
/* Try format */
static int vidioc_try_fmt ( struct file * file , void * priv , struct v4l2_format * f )
{
2012-10-03 22:19:11 -03:00
struct s5p_mfc_dev * dev = video_drvdata ( file ) ;
2011-06-21 10:51:26 -03:00
struct s5p_mfc_fmt * fmt ;
2012-10-03 22:19:11 -03:00
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 ;
}
2013-05-30 16:42:08 -03:00
if ( fmt - > codec_mode = = S5P_FIMV_CODEC_NONE ) {
mfc_err ( " Unknown codec \n " ) ;
2012-10-03 22:19:11 -03:00
return - EINVAL ;
}
2014-05-20 10:15:13 -03:00
if ( ( dev - > variant - > version_bit & fmt - > versions ) = = 0 ) {
mfc_err ( " Unsupported format by this MFC version. \n " ) ;
return - EINVAL ;
2013-05-30 16:42:08 -03:00
}
2012-10-03 22:19:11 -03:00
} 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 ;
}
2014-05-20 10:15:13 -03:00
if ( ( dev - > variant - > version_bit & fmt - > versions ) = = 0 ) {
mfc_err ( " Unsupported format by this MFC version. \n " ) ;
2012-10-03 22:19:11 -03:00
return - EINVAL ;
}
2011-06-21 10:51:26 -03:00
}
2012-10-03 22:19:11 -03:00
2011-06-21 10:51:26 -03:00
return 0 ;
}
/* Set format */
static int vidioc_s_fmt ( struct file * file , void * priv , struct v4l2_format * f )
{
struct s5p_mfc_dev * dev = video_drvdata ( file ) ;
struct s5p_mfc_ctx * ctx = fh_to_ctx ( priv ) ;
int ret = 0 ;
struct v4l2_pix_format_mplane * pix_mp ;
2014-07-15 22:51:33 -03:00
struct s5p_mfc_buf_size * buf_size = dev - > variant - > buf_size ;
2011-06-21 10:51:26 -03:00
mfc_debug_enter ( ) ;
ret = vidioc_try_fmt ( file , priv , f ) ;
pix_mp = & f - > fmt . pix_mp ;
if ( ret )
return ret ;
2016-06-09 17:25:14 -03:00
if ( vb2_is_streaming ( & ctx - > vq_src ) | | vb2_is_streaming ( & ctx - > vq_dst ) ) {
2011-06-21 10:51:26 -03:00
v4l2_err ( & dev - > v4l2_dev , " %s queue busy \n " , __func__ ) ;
ret = - EBUSY ;
goto out ;
}
2012-10-03 22:19:11 -03:00
if ( f - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ) {
2013-05-30 16:42:08 -03:00
/* dst_fmt is validated by call to vidioc_try_fmt */
ctx - > dst_fmt = find_format ( f , MFC_FMT_RAW ) ;
ret = 0 ;
2011-06-21 10:51:26 -03:00
goto out ;
2013-05-30 16:42:08 -03:00
} else if ( f - > type = = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ) {
/* src_fmt is validated by call to vidioc_try_fmt */
ctx - > src_fmt = find_format ( f , MFC_FMT_DEC ) ;
ctx - > codec_mode = ctx - > src_fmt - > codec_mode ;
mfc_debug ( 2 , " The codec number is: %d \n " , ctx - > codec_mode ) ;
pix_mp - > height = 0 ;
pix_mp - > width = 0 ;
2014-07-15 22:51:33 -03:00
if ( pix_mp - > plane_fmt [ 0 ] . sizeimage = = 0 )
2013-05-30 16:42:08 -03:00
pix_mp - > plane_fmt [ 0 ] . sizeimage = ctx - > dec_src_buf_size =
DEF_CPB_SIZE ;
2014-07-15 22:51:33 -03:00
else if ( pix_mp - > plane_fmt [ 0 ] . sizeimage > buf_size - > cpb )
ctx - > dec_src_buf_size = buf_size - > cpb ;
else
ctx - > dec_src_buf_size = pix_mp - > plane_fmt [ 0 ] . sizeimage ;
2013-05-30 16:42:08 -03:00
pix_mp - > plane_fmt [ 0 ] . bytesperline = 0 ;
ctx - > state = MFCINST_INIT ;
ret = 0 ;
goto out ;
} else {
mfc_err ( " Wrong type error for S_FMT : %d " , f - > type ) ;
2011-06-21 10:51:26 -03:00
ret = - EINVAL ;
goto out ;
}
2013-05-30 16:42:08 -03:00
2011-06-21 10:51:26 -03:00
out :
mfc_debug_leave ( ) ;
return ret ;
}
2014-05-19 09:32:58 -03:00
static int reqbufs_output ( struct s5p_mfc_dev * dev , struct s5p_mfc_ctx * ctx ,
struct v4l2_requestbuffers * reqbufs )
2011-06-21 10:51:26 -03:00
{
int ret = 0 ;
2014-05-19 09:32:58 -03:00
s5p_mfc_clock_on ( ) ;
if ( reqbufs - > count = = 0 ) {
mfc_debug ( 2 , " Freeing buffers \n " ) ;
ret = vb2_reqbufs ( & ctx - > vq_src , reqbufs ) ;
if ( ret )
goto out ;
ctx - > src_bufs_cnt = 0 ;
2014-05-19 09:33:00 -03:00
ctx - > output_state = QUEUE_FREE ;
2014-05-19 09:32:58 -03:00
} else if ( ctx - > output_state = = QUEUE_FREE ) {
2014-05-19 09:33:00 -03:00
/* Can only request buffers when we have a valid format set. */
2014-05-19 09:32:58 -03:00
WARN_ON ( ctx - > src_bufs_cnt ! = 0 ) ;
if ( ctx - > state ! = MFCINST_INIT ) {
mfc_err ( " Reqbufs called in an invalid state \n " ) ;
ret = - EINVAL ;
goto out ;
2011-06-21 10:51:26 -03:00
}
2014-05-19 09:32:58 -03:00
mfc_debug ( 2 , " Allocating %d buffers for OUTPUT queue \n " ,
reqbufs - > count ) ;
ret = vb2_reqbufs ( & ctx - > vq_src , reqbufs ) ;
if ( ret )
goto out ;
2014-05-19 09:33:00 -03:00
ret = s5p_mfc_open_mfc_inst ( dev , ctx ) ;
if ( ret ) {
reqbufs - > count = 0 ;
vb2_reqbufs ( & ctx - > vq_src , reqbufs ) ;
goto out ;
}
2014-05-19 09:32:58 -03:00
ctx - > output_state = QUEUE_BUFS_REQUESTED ;
} else {
mfc_err ( " Buffers have already been requested \n " ) ;
ret = - EINVAL ;
}
out :
s5p_mfc_clock_off ( ) ;
if ( ret )
mfc_err ( " Failed allocating buffers for OUTPUT queue \n " ) ;
return ret ;
}
static int reqbufs_capture ( struct s5p_mfc_dev * dev , struct s5p_mfc_ctx * ctx ,
struct v4l2_requestbuffers * reqbufs )
{
int ret = 0 ;
s5p_mfc_clock_on ( ) ;
if ( reqbufs - > count = = 0 ) {
mfc_debug ( 2 , " Freeing buffers \n " ) ;
ret = vb2_reqbufs ( & ctx - > vq_dst , reqbufs ) ;
if ( ret )
goto out ;
2015-12-02 06:22:32 -02:00
s5p_mfc_hw_call ( dev - > mfc_ops , release_codec_buffers , ctx ) ;
2011-06-21 10:51:26 -03:00
ctx - > dst_bufs_cnt = 0 ;
2014-05-19 09:32:58 -03:00
} else if ( ctx - > capture_state = = QUEUE_FREE ) {
WARN_ON ( ctx - > dst_bufs_cnt ! = 0 ) ;
mfc_debug ( 2 , " Allocating %d buffers for CAPTURE queue \n " ,
reqbufs - > count ) ;
2011-06-21 10:51:26 -03:00
ret = vb2_reqbufs ( & ctx - > vq_dst , reqbufs ) ;
2014-05-19 09:32:58 -03:00
if ( ret )
goto out ;
ctx - > capture_state = QUEUE_BUFS_REQUESTED ;
2011-06-21 10:51:26 -03:00
ctx - > total_dpb_count = reqbufs - > count ;
2014-05-19 09:32:58 -03:00
2012-10-03 22:19:08 -03:00
ret = s5p_mfc_hw_call ( dev - > mfc_ops , alloc_codec_buffers , ctx ) ;
2011-06-21 10:51:26 -03:00
if ( ret ) {
mfc_err ( " Failed to allocate decoding buffers \n " ) ;
reqbufs - > count = 0 ;
2014-05-19 09:32:58 -03:00
vb2_reqbufs ( & ctx - > vq_dst , reqbufs ) ;
ret = - ENOMEM ;
ctx - > capture_state = QUEUE_FREE ;
goto out ;
2011-06-21 10:51:26 -03:00
}
2014-05-19 09:32:58 -03:00
WARN_ON ( ctx - > dst_bufs_cnt ! = ctx - > total_dpb_count ) ;
ctx - > capture_state = QUEUE_BUFS_MMAPED ;
2012-08-14 06:13:40 -03:00
if ( s5p_mfc_ctx_ready ( ctx ) )
set_work_bit_irqsave ( ctx ) ;
2015-12-02 06:22:32 -02:00
s5p_mfc_hw_call ( dev - > mfc_ops , try_run , dev ) ;
2014-05-19 09:32:58 -03:00
s5p_mfc_wait_for_done_ctx ( ctx , S5P_MFC_R2H_CMD_INIT_BUFFERS_RET ,
0 ) ;
} else {
mfc_err ( " Buffers have already been requested \n " ) ;
ret = - EINVAL ;
2011-06-21 10:51:26 -03:00
}
2014-05-19 09:32:58 -03:00
out :
s5p_mfc_clock_off ( ) ;
if ( ret )
mfc_err ( " Failed allocating buffers for CAPTURE queue \n " ) ;
2011-06-21 10:51:26 -03:00
return ret ;
}
2016-06-08 22:57:34 -03:00
/* Request buffers */
2014-05-19 09:32:58 -03:00
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 ) ;
if ( reqbufs - > memory ! = V4L2_MEMORY_MMAP ) {
2016-06-08 22:57:35 -03:00
mfc_debug ( 2 , " Only V4L2_MEMORY_MMAP is supported \n " ) ;
2014-05-19 09:32:58 -03:00
return - EINVAL ;
}
if ( reqbufs - > type = = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ) {
return reqbufs_output ( dev , ctx , reqbufs ) ;
} else if ( reqbufs - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ) {
return reqbufs_capture ( dev , ctx , reqbufs ) ;
} else {
mfc_err ( " Invalid type requested \n " ) ;
return - EINVAL ;
}
}
2011-06-21 10:51:26 -03:00
/* Query buffer */
static int vidioc_querybuf ( struct file * file , void * priv ,
struct v4l2_buffer * buf )
{
struct s5p_mfc_ctx * ctx = fh_to_ctx ( priv ) ;
int ret ;
int i ;
if ( buf - > memory ! = V4L2_MEMORY_MMAP ) {
mfc_err ( " Only mmaped buffers can be used \n " ) ;
return - EINVAL ;
}
mfc_debug ( 2 , " State: %d, buf->type: %d \n " , ctx - > state , buf - > type ) ;
2014-05-19 09:33:00 -03:00
if ( ctx - > state = = MFCINST_GOT_INST & &
2011-06-21 10:51:26 -03:00
buf - > type = = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ) {
ret = vb2_querybuf ( & ctx - > vq_src , buf ) ;
} else if ( ctx - > state = = MFCINST_RUNNING & &
buf - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ) {
ret = vb2_querybuf ( & ctx - > vq_dst , buf ) ;
for ( i = 0 ; i < buf - > length ; i + + )
buf - > m . planes [ i ] . m . mem_offset + = DST_QUEUE_OFF_BASE ;
} else {
mfc_err ( " vidioc_querybuf called in an inappropriate state \n " ) ;
ret = - EINVAL ;
}
mfc_debug_leave ( ) ;
return ret ;
}
/* Queue a buffer */
static int vidioc_qbuf ( struct file * file , void * priv , struct v4l2_buffer * buf )
{
struct s5p_mfc_ctx * ctx = fh_to_ctx ( priv ) ;
if ( ctx - > state = = MFCINST_ERROR ) {
mfc_err ( " Call on QBUF after unrecoverable error \n " ) ;
return - EIO ;
}
if ( buf - > type = = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE )
return vb2_qbuf ( & ctx - > vq_src , buf ) ;
else if ( buf - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE )
return vb2_qbuf ( & ctx - > vq_dst , buf ) ;
return - EINVAL ;
}
/* Dequeue a buffer */
static int vidioc_dqbuf ( struct file * file , void * priv , struct v4l2_buffer * buf )
{
2013-01-11 12:29:33 -03:00
const struct v4l2_event ev = {
. type = V4L2_EVENT_EOS
} ;
2011-06-21 10:51:26 -03:00
struct s5p_mfc_ctx * ctx = fh_to_ctx ( priv ) ;
2013-01-11 12:29:33 -03:00
int ret ;
2011-06-21 10:51:26 -03:00
if ( ctx - > state = = MFCINST_ERROR ) {
2016-11-16 07:04:51 -02:00
mfc_err_limited ( " Call on DQBUF after unrecoverable error \n " ) ;
2011-06-21 10:51:26 -03:00
return - EIO ;
}
2015-10-07 07:13:45 -03:00
switch ( buf - > type ) {
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE :
return vb2_dqbuf ( & ctx - > vq_src , buf , file - > f_flags & O_NONBLOCK ) ;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE :
2013-01-11 12:29:33 -03:00
ret = vb2_dqbuf ( & ctx - > vq_dst , buf , file - > f_flags & O_NONBLOCK ) ;
2015-10-07 07:13:45 -03:00
if ( ret )
return ret ;
if ( ctx - > state = = MFCINST_FINISHED & &
( ctx - > dst_bufs [ buf - > index ] . flags & MFC_BUF_FLAG_EOS ) )
2013-01-11 12:29:33 -03:00
v4l2_event_queue_fh ( & ctx - > fh , & ev ) ;
2015-10-07 07:13:45 -03:00
return 0 ;
default :
return - EINVAL ;
2013-01-11 12:29:33 -03:00
}
2011-06-21 10:51:26 -03:00
}
2012-06-14 11:32:28 -03:00
/* Export DMA buffer */
static int vidioc_expbuf ( struct file * file , void * priv ,
struct v4l2_exportbuffer * eb )
{
struct s5p_mfc_ctx * ctx = fh_to_ctx ( priv ) ;
if ( eb - > type = = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE )
return vb2_expbuf ( & ctx - > vq_src , eb ) ;
if ( eb - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE )
return vb2_expbuf ( & ctx - > vq_dst , eb ) ;
return - EINVAL ;
}
2011-06-21 10:51:26 -03:00
/* Stream on */
static int vidioc_streamon ( struct file * file , void * priv ,
enum v4l2_buf_type type )
{
struct s5p_mfc_ctx * ctx = fh_to_ctx ( priv ) ;
int ret = - EINVAL ;
mfc_debug_enter ( ) ;
2014-05-19 09:33:00 -03:00
if ( type = = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE )
2011-06-21 10:51:26 -03:00
ret = vb2_streamon ( & ctx - > vq_src , type ) ;
2014-05-19 09:33:00 -03:00
else if ( type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE )
2011-06-21 10:51:26 -03:00
ret = vb2_streamon ( & ctx - > vq_dst , type ) ;
mfc_debug_leave ( ) ;
return ret ;
}
/* Stream off, which equals to a pause */
static int vidioc_streamoff ( struct file * file , void * priv ,
enum v4l2_buf_type type )
{
struct s5p_mfc_ctx * ctx = fh_to_ctx ( priv ) ;
if ( type = = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE )
return vb2_streamoff ( & ctx - > vq_src , type ) ;
else if ( type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE )
return vb2_streamoff ( & ctx - > vq_dst , type ) ;
return - EINVAL ;
}
/* Set controls - v4l2 control framework */
static int s5p_mfc_dec_s_ctrl ( struct v4l2_ctrl * ctrl )
{
struct s5p_mfc_ctx * ctx = ctrl_to_ctx ( ctrl ) ;
switch ( ctrl - > id ) {
case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY :
2012-06-14 05:58:07 -03:00
ctx - > display_delay = ctrl - > val ;
2011-06-21 10:51:26 -03:00
break ;
case V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE :
ctx - > display_delay_enable = ctrl - > val ;
break ;
case V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER :
2012-06-14 05:58:07 -03:00
ctx - > loop_filter_mpeg4 = ctrl - > val ;
2011-06-21 10:51:26 -03:00
break ;
case V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE :
ctx - > slice_interface = ctrl - > val ;
break ;
default :
mfc_err ( " Invalid control 0x%08x \n " , ctrl - > id ) ;
return - EINVAL ;
}
return 0 ;
}
static int s5p_mfc_dec_g_v_ctrl ( struct v4l2_ctrl * ctrl )
{
struct s5p_mfc_ctx * ctx = ctrl_to_ctx ( ctrl ) ;
struct s5p_mfc_dev * dev = ctx - > dev ;
switch ( ctrl - > id ) {
case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE :
if ( ctx - > state > = MFCINST_HEAD_PARSED & &
ctx - > state < MFCINST_ABORT ) {
2013-04-24 09:41:53 -03:00
ctrl - > val = ctx - > pb_count ;
2011-06-21 10:51:26 -03:00
break ;
2014-10-21 08:07:06 -03:00
} else if ( ctx - > state ! = MFCINST_INIT & &
ctx - > state ! = MFCINST_RES_CHANGE_END ) {
2011-06-21 10:51:26 -03:00
v4l2_err ( & dev - > v4l2_dev , " Decoding not initialised \n " ) ;
return - EINVAL ;
}
/* Should wait for the header to be parsed */
s5p_mfc_wait_for_done_ctx ( ctx ,
2012-10-03 22:19:08 -03:00
S5P_MFC_R2H_CMD_SEQ_DONE_RET , 0 ) ;
2011-06-21 10:51:26 -03:00
if ( ctx - > state > = MFCINST_HEAD_PARSED & &
ctx - > state < MFCINST_ABORT ) {
2013-04-24 09:41:53 -03:00
ctrl - > val = ctx - > pb_count ;
2011-06-21 10:51:26 -03:00
} else {
v4l2_err ( & dev - > v4l2_dev , " Decoding not initialised \n " ) ;
return - EINVAL ;
}
break ;
}
return 0 ;
}
static const struct v4l2_ctrl_ops s5p_mfc_dec_ctrl_ops = {
. s_ctrl = s5p_mfc_dec_s_ctrl ,
. g_volatile_ctrl = s5p_mfc_dec_g_v_ctrl ,
} ;
/* Get cropping information */
static int vidioc_g_crop ( struct file * file , void * priv ,
struct v4l2_crop * cr )
{
struct s5p_mfc_ctx * ctx = fh_to_ctx ( priv ) ;
2012-10-03 22:19:08 -03:00
struct s5p_mfc_dev * dev = ctx - > dev ;
2011-06-21 10:51:26 -03:00
u32 left , right , top , bottom ;
if ( ctx - > state ! = MFCINST_HEAD_PARSED & &
2016-07-12 14:28:30 -03:00
ctx - > state ! = MFCINST_RUNNING & &
ctx - > state ! = MFCINST_FINISHING & &
ctx - > state ! = MFCINST_FINISHED ) {
mfc_err ( " Can not get crop information \n " ) ;
return - EINVAL ;
}
2011-06-21 10:51:26 -03:00
if ( ctx - > src_fmt - > fourcc = = V4L2_PIX_FMT_H264 ) {
2012-10-03 22:19:08 -03:00
left = s5p_mfc_hw_call ( dev - > mfc_ops , get_crop_info_h , ctx ) ;
2011-06-21 10:51:26 -03:00
right = left > > S5P_FIMV_SHARED_CROP_RIGHT_SHIFT ;
left = left & S5P_FIMV_SHARED_CROP_LEFT_MASK ;
2012-10-03 22:19:08 -03:00
top = s5p_mfc_hw_call ( dev - > mfc_ops , get_crop_info_v , ctx ) ;
2011-06-21 10:51:26 -03:00
bottom = top > > S5P_FIMV_SHARED_CROP_BOTTOM_SHIFT ;
top = top & S5P_FIMV_SHARED_CROP_TOP_MASK ;
cr - > c . left = left ;
cr - > c . top = top ;
cr - > c . width = ctx - > img_width - left - right ;
cr - > c . height = ctx - > img_height - top - bottom ;
[media] s5p-mfc: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 17:44:10 -02:00
mfc_debug ( 2 , " Cropping info [h264]: l=%d t=%d w=%d h=%d (r=%d b=%d fw=%d fh=%d \n " ,
left , top , cr - > c . width , cr - > c . height , right , bottom ,
ctx - > buf_width , ctx - > buf_height ) ;
2011-06-21 10:51:26 -03:00
} else {
cr - > c . left = 0 ;
cr - > c . top = 0 ;
cr - > c . width = ctx - > img_width ;
cr - > c . height = ctx - > img_height ;
[media] s5p-mfc: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 17:44:10 -02:00
mfc_debug ( 2 , " Cropping info: w=%d h=%d fw=%d fh=%d \n " ,
cr - > c . width , cr - > c . height , ctx - > buf_width ,
ctx - > buf_height ) ;
2011-06-21 10:51:26 -03:00
}
return 0 ;
}
2014-08-26 11:13:47 -03:00
static int vidioc_decoder_cmd ( struct file * file , void * priv ,
struct v4l2_decoder_cmd * cmd )
2013-01-11 12:29:33 -03:00
{
struct s5p_mfc_ctx * ctx = fh_to_ctx ( priv ) ;
struct s5p_mfc_dev * dev = ctx - > dev ;
struct s5p_mfc_buf * buf ;
unsigned long flags ;
switch ( cmd - > cmd ) {
2014-12-15 18:10:58 -03:00
case V4L2_DEC_CMD_STOP :
2013-01-11 12:29:33 -03:00
if ( cmd - > flags ! = 0 )
return - EINVAL ;
2016-06-09 17:25:14 -03:00
if ( ! vb2_is_streaming ( & ctx - > vq_src ) )
2013-01-11 12:29:33 -03:00
return - EINVAL ;
spin_lock_irqsave ( & dev - > irqlock , flags ) ;
if ( list_empty ( & ctx - > src_queue ) ) {
mfc_err ( " EOS: empty src queue, entering finishing state " ) ;
ctx - > state = MFCINST_FINISHING ;
if ( s5p_mfc_ctx_ready ( ctx ) )
set_work_bit_irqsave ( ctx ) ;
spin_unlock_irqrestore ( & dev - > irqlock , flags ) ;
2015-12-02 06:22:32 -02:00
s5p_mfc_hw_call ( dev - > mfc_ops , try_run , dev ) ;
2013-01-11 12:29:33 -03:00
} else {
mfc_err ( " EOS: marking last buffer of stream " ) ;
buf = list_entry ( ctx - > src_queue . prev ,
struct s5p_mfc_buf , list ) ;
if ( buf - > flags & MFC_BUF_FLAG_USED )
ctx - > state = MFCINST_FINISHING ;
else
buf - > flags | = MFC_BUF_FLAG_EOS ;
spin_unlock_irqrestore ( & dev - > irqlock , flags ) ;
}
break ;
default :
return - EINVAL ;
}
return 0 ;
}
static int vidioc_subscribe_event ( struct v4l2_fh * fh ,
const struct v4l2_event_subscription * sub )
{
switch ( sub - > type ) {
case V4L2_EVENT_EOS :
return v4l2_event_subscribe ( fh , sub , 2 , NULL ) ;
2014-05-14 03:59:43 -03:00
case V4L2_EVENT_SOURCE_CHANGE :
return v4l2_src_change_event_subscribe ( fh , sub ) ;
2013-01-11 12:29:33 -03:00
default :
return - EINVAL ;
}
}
2011-06-21 10:51:26 -03:00
/* v4l2_ioctl_ops */
static const struct v4l2_ioctl_ops s5p_mfc_dec_ioctl_ops = {
. vidioc_querycap = vidioc_querycap ,
. vidioc_enum_fmt_vid_cap_mplane = vidioc_enum_fmt_vid_cap_mplane ,
. vidioc_enum_fmt_vid_out_mplane = vidioc_enum_fmt_vid_out_mplane ,
. vidioc_g_fmt_vid_cap_mplane = vidioc_g_fmt ,
. vidioc_g_fmt_vid_out_mplane = vidioc_g_fmt ,
. vidioc_try_fmt_vid_cap_mplane = vidioc_try_fmt ,
. vidioc_try_fmt_vid_out_mplane = vidioc_try_fmt ,
. vidioc_s_fmt_vid_cap_mplane = vidioc_s_fmt ,
. vidioc_s_fmt_vid_out_mplane = vidioc_s_fmt ,
. vidioc_reqbufs = vidioc_reqbufs ,
. vidioc_querybuf = vidioc_querybuf ,
. vidioc_qbuf = vidioc_qbuf ,
. vidioc_dqbuf = vidioc_dqbuf ,
2012-06-14 11:32:28 -03:00
. vidioc_expbuf = vidioc_expbuf ,
2011-06-21 10:51:26 -03:00
. vidioc_streamon = vidioc_streamon ,
. vidioc_streamoff = vidioc_streamoff ,
. vidioc_g_crop = vidioc_g_crop ,
2013-01-11 12:29:33 -03:00
. vidioc_decoder_cmd = vidioc_decoder_cmd ,
. vidioc_subscribe_event = vidioc_subscribe_event ,
. vidioc_unsubscribe_event = v4l2_event_unsubscribe ,
2011-06-21 10:51:26 -03:00
} ;
2011-08-24 10:30:21 -03:00
static int s5p_mfc_queue_setup ( struct vb2_queue * vq ,
2015-10-28 00:50:37 -02:00
unsigned int * buf_count ,
2011-08-24 10:30:21 -03:00
unsigned int * plane_count , unsigned int psize [ ] ,
2016-04-15 09:15:05 -03:00
struct device * alloc_devs [ ] )
2011-06-21 10:51:26 -03:00
{
struct s5p_mfc_ctx * ctx = fh_to_ctx ( vq - > drv_priv ) ;
2012-10-03 22:19:11 -03:00
struct s5p_mfc_dev * dev = ctx - > dev ;
2011-06-21 10:51:26 -03:00
/* Video output for decoding (source)
* this can be set after getting an instance */
if ( ctx - > state = = MFCINST_INIT & &
vq - > type = = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ) {
/* A single plane is required for input */
* plane_count = 1 ;
if ( * buf_count < 1 )
* buf_count = 1 ;
if ( * buf_count > MFC_MAX_BUFFERS )
* buf_count = MFC_MAX_BUFFERS ;
/* Video capture for decoding (destination)
* this can be set after the header was parsed */
} else if ( ctx - > state = = MFCINST_HEAD_PARSED & &
vq - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ) {
/* Output plane count is 2 - one for Y and one for CbCr */
* plane_count = 2 ;
/* Setup buffer count */
2013-04-24 09:41:53 -03:00
if ( * buf_count < ctx - > pb_count )
* buf_count = ctx - > pb_count ;
if ( * buf_count > ctx - > pb_count + MFC_MAX_EXTRA_DPB )
* buf_count = ctx - > pb_count + MFC_MAX_EXTRA_DPB ;
2011-06-21 10:51:26 -03:00
if ( * buf_count > MFC_MAX_BUFFERS )
* buf_count = MFC_MAX_BUFFERS ;
} else {
mfc_err ( " State seems invalid. State = %d, vq->type = %d \n " ,
ctx - > state , vq - > type ) ;
return - EINVAL ;
}
mfc_debug ( 2 , " Buffer count=%d, plane count=%d \n " ,
* buf_count , * plane_count ) ;
if ( ctx - > state = = MFCINST_HEAD_PARSED & &
vq - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ) {
psize [ 0 ] = ctx - > luma_size ;
psize [ 1 ] = ctx - > chroma_size ;
2012-10-03 22:19:11 -03:00
2013-07-09 01:24:36 -03:00
if ( IS_MFCV6_PLUS ( dev ) )
2017-03-20 07:49:24 -03:00
alloc_devs [ 0 ] = ctx - > dev - > mem_dev [ BANK_L_CTX ] ;
2012-10-03 22:19:11 -03:00
else
2017-03-20 07:49:24 -03:00
alloc_devs [ 0 ] = ctx - > dev - > mem_dev [ BANK_R_CTX ] ;
alloc_devs [ 1 ] = ctx - > dev - > mem_dev [ BANK_L_CTX ] ;
2011-06-21 10:51:26 -03:00
} else if ( vq - > type = = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE & &
ctx - > state = = MFCINST_INIT ) {
psize [ 0 ] = ctx - > dec_src_buf_size ;
2017-03-20 07:49:24 -03:00
alloc_devs [ 0 ] = ctx - > dev - > mem_dev [ BANK_L_CTX ] ;
2011-06-21 10:51:26 -03:00
} else {
2013-05-21 23:13:12 +09:00
mfc_err ( " This video node is dedicated to decoding. Decoding not initialized \n " ) ;
2011-06-21 10:51:26 -03:00
return - EINVAL ;
}
return 0 ;
}
static int s5p_mfc_buf_init ( struct vb2_buffer * vb )
{
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
struct vb2_v4l2_buffer * vbuf = to_vb2_v4l2_buffer ( vb ) ;
2011-06-21 10:51:26 -03:00
struct vb2_queue * vq = vb - > vb2_queue ;
struct s5p_mfc_ctx * ctx = fh_to_ctx ( vq - > drv_priv ) ;
unsigned int i ;
if ( vq - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ) {
if ( ctx - > capture_state = = QUEUE_BUFS_MMAPED )
return 0 ;
2014-09-03 23:28:06 -03:00
for ( i = 0 ; i < ctx - > dst_fmt - > num_planes ; i + + ) {
2011-06-21 10:51:26 -03:00
if ( IS_ERR_OR_NULL ( ERR_PTR (
2011-08-29 03:20:56 -03:00
vb2_dma_contig_plane_dma_addr ( vb , i ) ) ) ) {
2011-06-21 10:51:26 -03:00
mfc_err ( " Plane mem not allocated \n " ) ;
return - EINVAL ;
}
}
if ( vb2_plane_size ( vb , 0 ) < ctx - > luma_size | |
vb2_plane_size ( vb , 1 ) < ctx - > chroma_size ) {
mfc_err ( " Plane buffer (CAPTURE) is too small \n " ) ;
return - EINVAL ;
}
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
i = vb - > index ;
ctx - > dst_bufs [ i ] . b = vbuf ;
2011-06-21 10:51:26 -03:00
ctx - > dst_bufs [ i ] . cookie . raw . luma =
2011-08-29 03:20:56 -03:00
vb2_dma_contig_plane_dma_addr ( vb , 0 ) ;
2011-06-21 10:51:26 -03:00
ctx - > dst_bufs [ i ] . cookie . raw . chroma =
2011-08-29 03:20:56 -03:00
vb2_dma_contig_plane_dma_addr ( vb , 1 ) ;
2011-06-21 10:51:26 -03:00
ctx - > dst_bufs_cnt + + ;
} else if ( vq - > type = = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ) {
if ( IS_ERR_OR_NULL ( ERR_PTR (
2011-08-29 03:20:56 -03:00
vb2_dma_contig_plane_dma_addr ( vb , 0 ) ) ) ) {
2011-06-21 10:51:26 -03:00
mfc_err ( " Plane memory not allocated \n " ) ;
return - EINVAL ;
}
if ( vb2_plane_size ( vb , 0 ) < ctx - > dec_src_buf_size ) {
mfc_err ( " Plane buffer (OUTPUT) is too small \n " ) ;
return - EINVAL ;
}
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
i = vb - > index ;
ctx - > src_bufs [ i ] . b = vbuf ;
2011-06-21 10:51:26 -03:00
ctx - > src_bufs [ i ] . cookie . stream =
2011-08-29 03:20:56 -03:00
vb2_dma_contig_plane_dma_addr ( vb , 0 ) ;
2011-06-21 10:51:26 -03:00
ctx - > src_bufs_cnt + + ;
} else {
mfc_err ( " s5p_mfc_buf_init: unknown queue type \n " ) ;
return - EINVAL ;
}
return 0 ;
}
2011-08-29 08:51:49 -03:00
static int s5p_mfc_start_streaming ( struct vb2_queue * q , unsigned int count )
2011-06-21 10:51:26 -03:00
{
struct s5p_mfc_ctx * ctx = fh_to_ctx ( q - > drv_priv ) ;
struct s5p_mfc_dev * dev = ctx - > dev ;
v4l2_ctrl_handler_setup ( & ctx - > ctrl_handler ) ;
if ( ctx - > state = = MFCINST_FINISHING | |
ctx - > state = = MFCINST_FINISHED )
ctx - > state = MFCINST_RUNNING ;
/* If context is ready then dev = work->data;schedule it to run */
2012-08-14 06:13:40 -03:00
if ( s5p_mfc_ctx_ready ( ctx ) )
set_work_bit_irqsave ( ctx ) ;
2015-12-02 06:22:32 -02:00
s5p_mfc_hw_call ( dev - > mfc_ops , try_run , dev ) ;
2011-06-21 10:51:26 -03:00
return 0 ;
}
2014-04-17 02:47:21 -03:00
static void s5p_mfc_stop_streaming ( struct vb2_queue * q )
2011-06-21 10:51:26 -03:00
{
unsigned long flags ;
struct s5p_mfc_ctx * ctx = fh_to_ctx ( q - > drv_priv ) ;
struct s5p_mfc_dev * dev = ctx - > dev ;
int aborted = 0 ;
2015-12-02 06:22:31 -02:00
spin_lock_irqsave ( & dev - > irqlock , flags ) ;
2011-06-21 10:51:26 -03:00
if ( ( ctx - > state = = MFCINST_FINISHING | |
ctx - > state = = MFCINST_RUNNING ) & &
dev - > curr_ctx = = ctx - > num & & dev - > hw_lock ) {
ctx - > state = MFCINST_ABORT ;
2015-12-02 06:22:31 -02:00
spin_unlock_irqrestore ( & dev - > irqlock , flags ) ;
2011-06-21 10:51:26 -03:00
s5p_mfc_wait_for_done_ctx ( ctx ,
2012-10-03 22:19:08 -03:00
S5P_MFC_R2H_CMD_FRAME_DONE_RET , 0 ) ;
2011-06-21 10:51:26 -03:00
aborted = 1 ;
2015-12-02 06:22:31 -02:00
spin_lock_irqsave ( & dev - > irqlock , flags ) ;
2011-06-21 10:51:26 -03:00
}
if ( q - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ) {
2015-12-02 06:22:29 -02:00
s5p_mfc_cleanup_queue ( & ctx - > dst_queue , & ctx - > vq_dst ) ;
2011-06-21 10:51:26 -03:00
INIT_LIST_HEAD ( & ctx - > dst_queue ) ;
ctx - > dst_queue_cnt = 0 ;
ctx - > dpb_flush_flag = 1 ;
ctx - > dec_dst_flag = 0 ;
2013-07-09 01:24:36 -03:00
if ( IS_MFCV6_PLUS ( dev ) & & ( ctx - > state = = MFCINST_RUNNING ) ) {
2012-11-22 06:15:55 -03:00
ctx - > state = MFCINST_FLUSH ;
set_work_bit_irqsave ( ctx ) ;
2015-12-02 06:22:32 -02:00
s5p_mfc_hw_call ( dev - > mfc_ops , try_run , dev ) ;
2015-12-02 06:22:31 -02:00
spin_unlock_irqrestore ( & dev - > irqlock , flags ) ;
2012-11-22 06:15:55 -03:00
if ( s5p_mfc_wait_for_done_ctx ( ctx ,
S5P_MFC_R2H_CMD_DPB_FLUSH_RET , 0 ) )
mfc_err ( " Err flushing buffers \n " ) ;
2015-12-02 06:22:31 -02:00
spin_lock_irqsave ( & dev - > irqlock , flags ) ;
2012-11-22 06:15:55 -03:00
}
2015-12-02 06:22:31 -02:00
} else if ( q - > type = = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ) {
2015-12-02 06:22:29 -02:00
s5p_mfc_cleanup_queue ( & ctx - > src_queue , & ctx - > vq_src ) ;
2011-06-21 10:51:26 -03:00
INIT_LIST_HEAD ( & ctx - > src_queue ) ;
ctx - > src_queue_cnt = 0 ;
}
if ( aborted )
ctx - > state = MFCINST_RUNNING ;
2015-12-02 06:22:31 -02:00
spin_unlock_irqrestore ( & dev - > irqlock , flags ) ;
2011-06-21 10:51:26 -03:00
}
static void s5p_mfc_buf_queue ( struct vb2_buffer * vb )
{
struct vb2_queue * vq = vb - > vb2_queue ;
struct s5p_mfc_ctx * ctx = fh_to_ctx ( vq - > drv_priv ) ;
struct s5p_mfc_dev * dev = ctx - > dev ;
unsigned long flags ;
struct s5p_mfc_buf * mfc_buf ;
if ( vq - > type = = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ) {
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
mfc_buf = & ctx - > src_bufs [ vb - > index ] ;
2012-08-21 08:05:32 -03:00
mfc_buf - > flags & = ~ MFC_BUF_FLAG_USED ;
2011-06-21 10:51:26 -03:00
spin_lock_irqsave ( & dev - > irqlock , flags ) ;
list_add_tail ( & mfc_buf - > list , & ctx - > src_queue ) ;
ctx - > src_queue_cnt + + ;
spin_unlock_irqrestore ( & dev - > irqlock , flags ) ;
} else if ( vq - > type = = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ) {
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
mfc_buf = & ctx - > dst_bufs [ vb - > index ] ;
2012-08-21 08:05:32 -03:00
mfc_buf - > flags & = ~ MFC_BUF_FLAG_USED ;
2011-06-21 10:51:26 -03:00
/* Mark destination as available for use by MFC */
spin_lock_irqsave ( & dev - > irqlock , flags ) ;
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 10:30:30 -03:00
set_bit ( vb - > index , & ctx - > dec_dst_flag ) ;
2011-06-21 10:51:26 -03:00
list_add_tail ( & mfc_buf - > list , & ctx - > dst_queue ) ;
ctx - > dst_queue_cnt + + ;
spin_unlock_irqrestore ( & dev - > irqlock , flags ) ;
} else {
mfc_err ( " Unsupported buffer type (%d) \n " , vq - > type ) ;
}
2012-08-14 06:13:40 -03:00
if ( s5p_mfc_ctx_ready ( ctx ) )
set_work_bit_irqsave ( ctx ) ;
2015-12-02 06:22:32 -02:00
s5p_mfc_hw_call ( dev - > mfc_ops , try_run , dev ) ;
2011-06-21 10:51:26 -03:00
}
static struct vb2_ops s5p_mfc_dec_qops = {
. queue_setup = s5p_mfc_queue_setup ,
2014-11-26 19:42:32 -03:00
. wait_prepare = vb2_ops_wait_prepare ,
. wait_finish = vb2_ops_wait_finish ,
2011-06-21 10:51:26 -03:00
. buf_init = s5p_mfc_buf_init ,
. start_streaming = s5p_mfc_start_streaming ,
. stop_streaming = s5p_mfc_stop_streaming ,
. buf_queue = s5p_mfc_buf_queue ,
} ;
2015-11-22 05:45:34 -02:00
const struct s5p_mfc_codec_ops * get_dec_codec_ops ( void )
2011-06-21 10:51:26 -03:00
{
return & decoder_codec_ops ;
}
struct vb2_ops * get_dec_queue_ops ( void )
{
return & s5p_mfc_dec_qops ;
}
const struct v4l2_ioctl_ops * get_dec_v4l2_ioctl_ops ( void )
{
return & s5p_mfc_dec_ioctl_ops ;
}
2015-10-29 08:10:28 -02:00
# define IS_MFC51_PRIV(x) ((V4L2_CTRL_ID2WHICH(x) == V4L2_CTRL_CLASS_MPEG) \
2011-06-21 10:51:26 -03:00
& & V4L2_CTRL_DRIVER_PRIV ( x ) )
int s5p_mfc_dec_ctrls_setup ( struct s5p_mfc_ctx * ctx )
{
struct v4l2_ctrl_config cfg ;
int i ;
v4l2_ctrl_handler_init ( & ctx - > ctrl_handler , NUM_CTRLS ) ;
if ( ctx - > ctrl_handler . error ) {
mfc_err ( " v4l2_ctrl_handler_init failed \n " ) ;
return ctx - > ctrl_handler . error ;
}
for ( i = 0 ; i < NUM_CTRLS ; i + + ) {
if ( IS_MFC51_PRIV ( controls [ i ] . id ) ) {
2012-06-26 04:44:40 -03:00
memset ( & cfg , 0 , sizeof ( struct v4l2_ctrl_config ) ) ;
2011-06-21 10:51:26 -03:00
cfg . ops = & s5p_mfc_dec_ctrl_ops ;
cfg . id = controls [ i ] . id ;
cfg . min = controls [ i ] . minimum ;
cfg . max = controls [ i ] . maximum ;
cfg . def = controls [ i ] . default_value ;
cfg . name = controls [ i ] . name ;
cfg . type = controls [ i ] . type ;
cfg . step = controls [ i ] . step ;
cfg . menu_skip_mask = 0 ;
ctx - > ctrls [ i ] = v4l2_ctrl_new_custom ( & ctx - > ctrl_handler ,
& cfg , NULL ) ;
} else {
ctx - > ctrls [ i ] = v4l2_ctrl_new_std ( & ctx - > ctrl_handler ,
& s5p_mfc_dec_ctrl_ops ,
controls [ i ] . id , controls [ i ] . minimum ,
controls [ i ] . maximum , controls [ i ] . step ,
controls [ i ] . default_value ) ;
}
if ( ctx - > ctrl_handler . error ) {
mfc_err ( " Adding control (%d) failed \n " , i ) ;
return ctx - > ctrl_handler . error ;
}
if ( controls [ i ] . is_volatile & & ctx - > ctrls [ i ] )
2011-08-26 07:35:14 -03:00
ctx - > ctrls [ i ] - > flags | = V4L2_CTRL_FLAG_VOLATILE ;
2011-06-21 10:51:26 -03:00
}
return 0 ;
}
void s5p_mfc_dec_ctrls_delete ( struct s5p_mfc_ctx * ctx )
{
int i ;
v4l2_ctrl_handler_free ( & ctx - > ctrl_handler ) ;
for ( i = 0 ; i < NUM_CTRLS ; i + + )
ctx - > ctrls [ i ] = NULL ;
}
2012-10-03 22:19:08 -03:00
void s5p_mfc_dec_init ( struct s5p_mfc_ctx * ctx )
{
struct v4l2_format f ;
2014-05-16 09:03:43 -03:00
f . fmt . pix_mp . pixelformat = V4L2_PIX_FMT_H264 ;
2012-10-03 22:19:08 -03:00
ctx - > src_fmt = find_format ( & f , MFC_FMT_DEC ) ;
2014-05-19 09:50:01 -03:00
if ( IS_MFCV8 ( ctx - > dev ) )
f . fmt . pix_mp . pixelformat = V4L2_PIX_FMT_NV12M ;
else if ( IS_MFCV6_PLUS ( ctx - > dev ) )
2014-05-16 09:03:43 -03:00
f . fmt . pix_mp . pixelformat = V4L2_PIX_FMT_NV12MT_16X16 ;
else
f . fmt . pix_mp . pixelformat = V4L2_PIX_FMT_NV12MT ;
2012-10-03 22:19:08 -03:00
ctx - > dst_fmt = find_format ( & f , MFC_FMT_RAW ) ;
2014-09-24 19:07:36 -03:00
mfc_debug ( 2 , " Default src_fmt is %p, dest_fmt is %p \n " ,
ctx - > src_fmt , ctx - > dst_fmt ) ;
2012-10-03 22:19:08 -03:00
}
2013-01-11 12:29:33 -03:00