2013-06-04 18:22:30 +04:00
/*
* vsp1_wpf . c - - R - Car VSP1 Write Pixel Formatter
*
2014-02-06 21:42:31 +04:00
* Copyright ( C ) 2013 - 2014 Renesas Electronics Corporation
2013-06-04 18:22:30 +04:00
*
* Contact : Laurent Pinchart ( laurent . pinchart @ ideasonboard . 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/device.h>
# include <media/v4l2-subdev.h>
# include "vsp1.h"
# include "vsp1_rwpf.h"
# include "vsp1_video.h"
# define WPF_MAX_WIDTH 2048
# define WPF_MAX_HEIGHT 2048
/* -----------------------------------------------------------------------------
* Device Access
*/
static inline u32 vsp1_wpf_read ( struct vsp1_rwpf * wpf , u32 reg )
{
return vsp1_read ( wpf - > entity . vsp1 ,
reg + wpf - > entity . index * VI6_WPF_OFFSET ) ;
}
static inline void vsp1_wpf_write ( struct vsp1_rwpf * wpf , u32 reg , u32 data )
{
vsp1_write ( wpf - > entity . vsp1 ,
reg + wpf - > entity . index * VI6_WPF_OFFSET , data ) ;
}
2014-05-22 02:00:05 +04:00
/* -----------------------------------------------------------------------------
* Controls
*/
static int wpf_s_ctrl ( struct v4l2_ctrl * ctrl )
{
struct vsp1_rwpf * wpf =
container_of ( ctrl - > handler , struct vsp1_rwpf , ctrls ) ;
u32 value ;
if ( ! vsp1_entity_is_streaming ( & wpf - > entity ) )
return 0 ;
switch ( ctrl - > id ) {
case V4L2_CID_ALPHA_COMPONENT :
value = vsp1_wpf_read ( wpf , VI6_WPF_OUTFMT ) ;
value & = ~ VI6_WPF_OUTFMT_PDV_MASK ;
value | = ctrl - > val < < VI6_WPF_OUTFMT_PDV_SHIFT ;
vsp1_wpf_write ( wpf , VI6_WPF_OUTFMT , value ) ;
break ;
}
return 0 ;
}
static const struct v4l2_ctrl_ops wpf_ctrl_ops = {
. s_ctrl = wpf_s_ctrl ,
} ;
2013-06-04 18:22:30 +04:00
/* -----------------------------------------------------------------------------
* V4L2 Subdevice Core Operations
*/
static int wpf_s_stream ( struct v4l2_subdev * subdev , int enable )
{
2014-05-28 03:35:36 +04:00
struct vsp1_pipeline * pipe = to_vsp1_pipeline ( & subdev - > entity ) ;
2013-06-04 18:22:30 +04:00
struct vsp1_rwpf * wpf = to_rwpf ( subdev ) ;
struct vsp1_device * vsp1 = wpf - > entity . vsp1 ;
2013-08-25 03:49:58 +04:00
const struct v4l2_rect * crop = & wpf - > crop ;
2013-06-04 18:22:30 +04:00
unsigned int i ;
u32 srcrpf = 0 ;
u32 outfmt = 0 ;
2014-05-22 02:00:05 +04:00
int ret ;
ret = vsp1_entity_set_streaming ( & wpf - > entity , enable ) ;
if ( ret < 0 )
return ret ;
2013-06-04 18:22:30 +04:00
if ( ! enable ) {
vsp1_write ( vsp1 , VI6_WPF_IRQ_ENB ( wpf - > entity . index ) , 0 ) ;
2014-05-28 20:10:33 +04:00
vsp1_wpf_write ( wpf , VI6_WPF_SRCRPF , 0 ) ;
2013-06-04 18:22:30 +04:00
return 0 ;
}
2014-11-27 04:25:02 +03:00
/* Sources. If the pipeline has a single input and BRU is not used,
* configure it as the master layer . Otherwise configure all
* inputs as sub - layers and select the virtual RPF as the master
* layer .
2013-07-11 01:03:46 +04:00
*/
2013-06-04 18:22:30 +04:00
for ( i = 0 ; i < pipe - > num_inputs ; + + i ) {
struct vsp1_rwpf * input = pipe - > inputs [ i ] ;
2014-11-27 04:25:02 +03:00
srcrpf | = ( ! pipe - > bru & & pipe - > num_inputs = = 1 )
2013-07-11 01:03:46 +04:00
? VI6_WPF_SRCRPF_RPF_ACT_MST ( input - > entity . index )
: VI6_WPF_SRCRPF_RPF_ACT_SUB ( input - > entity . index ) ;
2013-06-04 18:22:30 +04:00
}
2014-11-27 04:25:02 +03:00
if ( pipe - > bru | | pipe - > num_inputs > 1 )
2013-07-11 01:03:46 +04:00
srcrpf | = VI6_WPF_SRCRPF_VIRACT_MST ;
2013-06-04 18:22:30 +04:00
vsp1_wpf_write ( wpf , VI6_WPF_SRCRPF , srcrpf ) ;
2013-08-25 03:49:58 +04:00
/* Destination stride. */
2013-06-04 18:22:30 +04:00
if ( ! pipe - > lif ) {
struct v4l2_pix_format_mplane * format = & wpf - > video . format ;
vsp1_wpf_write ( wpf , VI6_WPF_DSTM_STRIDE_Y ,
format - > plane_fmt [ 0 ] . bytesperline ) ;
if ( format - > num_planes > 1 )
vsp1_wpf_write ( wpf , VI6_WPF_DSTM_STRIDE_C ,
format - > plane_fmt [ 1 ] . bytesperline ) ;
}
2013-08-25 03:49:58 +04:00
vsp1_wpf_write ( wpf , VI6_WPF_HSZCLIP , VI6_WPF_SZCLIP_EN |
( crop - > left < < VI6_WPF_SZCLIP_OFST_SHIFT ) |
( crop - > width < < VI6_WPF_SZCLIP_SIZE_SHIFT ) ) ;
vsp1_wpf_write ( wpf , VI6_WPF_VSZCLIP , VI6_WPF_SZCLIP_EN |
( crop - > top < < VI6_WPF_SZCLIP_OFST_SHIFT ) |
( crop - > height < < VI6_WPF_SZCLIP_SIZE_SHIFT ) ) ;
2013-06-04 18:22:30 +04:00
/* Format */
if ( ! pipe - > lif ) {
const struct vsp1_format_info * fmtinfo = wpf - > video . fmtinfo ;
outfmt = fmtinfo - > hwfmt < < VI6_WPF_OUTFMT_WRFMT_SHIFT ;
2014-05-27 03:12:53 +04:00
if ( fmtinfo - > alpha )
outfmt | = VI6_WPF_OUTFMT_PXA ;
2013-06-04 18:22:30 +04:00
if ( fmtinfo - > swap_yc )
outfmt | = VI6_WPF_OUTFMT_SPYCS ;
if ( fmtinfo - > swap_uv )
outfmt | = VI6_WPF_OUTFMT_SPUVS ;
vsp1_wpf_write ( wpf , VI6_WPF_DSWAP , fmtinfo - > swap ) ;
}
if ( wpf - > entity . formats [ RWPF_PAD_SINK ] . code ! =
wpf - > entity . formats [ RWPF_PAD_SOURCE ] . code )
outfmt | = VI6_WPF_OUTFMT_CSC ;
2014-05-22 02:00:05 +04:00
/* Take the control handler lock to ensure that the PDV value won't be
* changed behind our back by a set control operation .
*/
mutex_lock ( wpf - > ctrls . lock ) ;
outfmt | = vsp1_wpf_read ( wpf , VI6_WPF_OUTFMT ) & VI6_WPF_OUTFMT_PDV_MASK ;
2013-06-04 18:22:30 +04:00
vsp1_wpf_write ( wpf , VI6_WPF_OUTFMT , outfmt ) ;
2014-05-22 02:00:05 +04:00
mutex_unlock ( wpf - > ctrls . lock ) ;
2013-06-04 18:22:30 +04:00
vsp1_write ( vsp1 , VI6_DPR_WPF_FPORCH ( wpf - > entity . index ) ,
VI6_DPR_WPF_FPORCH_FP_WPFN ) ;
vsp1_write ( vsp1 , VI6_WPF_WRBCK_CTRL , 0 ) ;
/* Enable interrupts */
vsp1_write ( vsp1 , VI6_WPF_IRQ_STA ( wpf - > entity . index ) , 0 ) ;
vsp1_write ( vsp1 , VI6_WPF_IRQ_ENB ( wpf - > entity . index ) ,
VI6_WFP_IRQ_ENB_FREE ) ;
return 0 ;
}
/* -----------------------------------------------------------------------------
* V4L2 Subdevice Operations
*/
static struct v4l2_subdev_video_ops wpf_video_ops = {
. s_stream = wpf_s_stream ,
} ;
static struct v4l2_subdev_pad_ops wpf_pad_ops = {
. enum_mbus_code = vsp1_rwpf_enum_mbus_code ,
. enum_frame_size = vsp1_rwpf_enum_frame_size ,
. get_fmt = vsp1_rwpf_get_format ,
. set_fmt = vsp1_rwpf_set_format ,
2013-08-25 03:49:58 +04:00
. get_selection = vsp1_rwpf_get_selection ,
. set_selection = vsp1_rwpf_set_selection ,
2013-06-04 18:22:30 +04:00
} ;
static struct v4l2_subdev_ops wpf_ops = {
. video = & wpf_video_ops ,
. pad = & wpf_pad_ops ,
} ;
/* -----------------------------------------------------------------------------
* Video Device Operations
*/
static void wpf_vdev_queue ( struct vsp1_video * video ,
struct vsp1_video_buffer * buf )
{
struct vsp1_rwpf * wpf = container_of ( video , struct vsp1_rwpf , video ) ;
vsp1_wpf_write ( wpf , VI6_WPF_DSTM_ADDR_Y , buf - > addr [ 0 ] ) ;
[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 16:30:30 +03:00
if ( buf - > buf . vb2_buf . num_planes > 1 )
2013-06-04 18:22:30 +04:00
vsp1_wpf_write ( wpf , VI6_WPF_DSTM_ADDR_C0 , buf - > addr [ 1 ] ) ;
[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 16:30:30 +03:00
if ( buf - > buf . vb2_buf . num_planes > 2 )
2013-06-04 18:22:30 +04:00
vsp1_wpf_write ( wpf , VI6_WPF_DSTM_ADDR_C1 , buf - > addr [ 2 ] ) ;
}
static const struct vsp1_video_operations wpf_vdev_ops = {
. queue = wpf_vdev_queue ,
} ;
/* -----------------------------------------------------------------------------
* Initialization and Cleanup
*/
struct vsp1_rwpf * vsp1_wpf_create ( struct vsp1_device * vsp1 , unsigned int index )
{
struct v4l2_subdev * subdev ;
struct vsp1_video * video ;
struct vsp1_rwpf * wpf ;
int ret ;
wpf = devm_kzalloc ( vsp1 - > dev , sizeof ( * wpf ) , GFP_KERNEL ) ;
if ( wpf = = NULL )
return ERR_PTR ( - ENOMEM ) ;
wpf - > max_width = WPF_MAX_WIDTH ;
wpf - > max_height = WPF_MAX_HEIGHT ;
wpf - > entity . type = VSP1_ENTITY_WPF ;
wpf - > entity . index = index ;
ret = vsp1_entity_init ( vsp1 , & wpf - > entity , 2 ) ;
if ( ret < 0 )
return ERR_PTR ( ret ) ;
/* Initialize the V4L2 subdev. */
subdev = & wpf - > entity . subdev ;
v4l2_subdev_init ( subdev , & wpf_ops ) ;
subdev - > entity . ops = & vsp1_media_ops ;
subdev - > internal_ops = & vsp1_subdev_internal_ops ;
snprintf ( subdev - > name , sizeof ( subdev - > name ) , " %s wpf.%u " ,
dev_name ( vsp1 - > dev ) , index ) ;
v4l2_set_subdevdata ( subdev , wpf ) ;
subdev - > flags | = V4L2_SUBDEV_FL_HAS_DEVNODE ;
vsp1_entity_init_formats ( subdev , NULL ) ;
2014-05-22 02:00:05 +04:00
/* Initialize the control handler. */
v4l2_ctrl_handler_init ( & wpf - > ctrls , 1 ) ;
v4l2_ctrl_new_std ( & wpf - > ctrls , & wpf_ctrl_ops , V4L2_CID_ALPHA_COMPONENT ,
0 , 255 , 1 , 255 ) ;
wpf - > entity . subdev . ctrl_handler = & wpf - > ctrls ;
if ( wpf - > ctrls . error ) {
dev_err ( vsp1 - > dev , " wpf%u: failed to initialize controls \n " ,
index ) ;
ret = wpf - > ctrls . error ;
goto error ;
}
2013-06-04 18:22:30 +04:00
/* Initialize the video device. */
video = & wpf - > video ;
video - > type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ;
video - > vsp1 = vsp1 ;
video - > ops = & wpf_vdev_ops ;
2015-07-28 19:54:03 +03:00
ret = vsp1_video_init ( video , wpf ) ;
2013-06-04 18:22:30 +04:00
if ( ret < 0 )
2014-05-28 19:49:13 +04:00
goto error ;
wpf - > entity . video = video ;
2013-06-04 18:22:30 +04:00
wpf - > entity . sink = & wpf - > video . video . entity ;
return wpf ;
2014-05-28 19:49:13 +04:00
error :
vsp1_entity_destroy ( & wpf - > entity ) ;
2013-06-04 18:22:30 +04:00
return ERR_PTR ( ret ) ;
}