2019-06-04 10:11:33 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2012-04-27 05:29:05 -03:00
/*
* Samsung EXYNOS FIMC - LITE ( camera host interface ) driver
*
2013-04-30 09:27:08 -03:00
* Copyright ( C ) 2012 - 2013 Samsung Electronics Co . , Ltd .
* Author : Sylwester Nawrocki < s . nawrocki @ samsung . com >
2012-04-27 05:29:05 -03:00
*/
# define pr_fmt(fmt) "%s:%d " fmt, __func__, __LINE__
# include <linux/bug.h>
2013-04-09 11:11:58 -03:00
# include <linux/clk.h>
2012-04-27 05:29:05 -03:00
# include <linux/device.h>
# include <linux/errno.h>
# include <linux/interrupt.h>
# include <linux/kernel.h>
# include <linux/list.h>
# include <linux/module.h>
2013-03-26 09:33:54 -03:00
# include <linux/of.h>
2012-04-27 05:29:05 -03:00
# include <linux/types.h>
# include <linux/platform_device.h>
# include <linux/pm_runtime.h>
# include <linux/slab.h>
# include <linux/videodev2.h>
# include <media/v4l2-device.h>
# include <media/v4l2-ioctl.h>
# include <media/v4l2-mem2mem.h>
2020-05-28 15:26:05 +02:00
# include <media/v4l2-rect.h>
2015-09-22 10:30:29 -03:00
# include <media/videobuf2-v4l2.h>
2012-04-27 05:29:05 -03:00
# include <media/videobuf2-dma-contig.h>
2015-11-13 19:40:07 -02:00
# include <media/drv-intf/exynos-fimc.h>
2012-04-27 05:29:05 -03:00
2013-06-10 08:51:44 -03:00
# include "common.h"
2013-04-09 11:11:58 -03:00
# include "fimc-core.h"
2012-08-14 10:46:58 -03:00
# include "fimc-lite.h"
2012-04-27 05:29:05 -03:00
# include "fimc-lite-reg.h"
static int debug ;
module_param ( debug , int , 0644 ) ;
static const struct fimc_fmt fimc_lite_formats [ ] = {
{
. fourcc = V4L2_PIX_FMT_YUYV ,
2013-06-20 10:49:09 -03:00
. colorspace = V4L2_COLORSPACE_JPEG ,
2012-04-27 05:29:05 -03:00
. depth = { 16 } ,
. color = FIMC_FMT_YCBYCR422 ,
. memplanes = 1 ,
2014-11-10 14:28:31 -03:00
. mbus_code = MEDIA_BUS_FMT_YUYV8_2X8 ,
2013-03-20 15:31:03 -03:00
. flags = FMT_FLAGS_YUV ,
2012-04-27 05:29:05 -03:00
} , {
. fourcc = V4L2_PIX_FMT_UYVY ,
2013-06-20 10:49:09 -03:00
. colorspace = V4L2_COLORSPACE_JPEG ,
2012-04-27 05:29:05 -03:00
. depth = { 16 } ,
. color = FIMC_FMT_CBYCRY422 ,
. memplanes = 1 ,
2014-11-10 14:28:31 -03:00
. mbus_code = MEDIA_BUS_FMT_UYVY8_2X8 ,
2013-03-20 15:31:03 -03:00
. flags = FMT_FLAGS_YUV ,
2012-04-27 05:29:05 -03:00
} , {
. fourcc = V4L2_PIX_FMT_VYUY ,
2013-06-20 10:49:09 -03:00
. colorspace = V4L2_COLORSPACE_JPEG ,
2012-04-27 05:29:05 -03:00
. depth = { 16 } ,
. color = FIMC_FMT_CRYCBY422 ,
. memplanes = 1 ,
2014-11-10 14:28:31 -03:00
. mbus_code = MEDIA_BUS_FMT_VYUY8_2X8 ,
2013-03-20 15:31:03 -03:00
. flags = FMT_FLAGS_YUV ,
2012-04-27 05:29:05 -03:00
} , {
. fourcc = V4L2_PIX_FMT_YVYU ,
2013-06-20 10:49:09 -03:00
. colorspace = V4L2_COLORSPACE_JPEG ,
2012-04-27 05:29:05 -03:00
. depth = { 16 } ,
. color = FIMC_FMT_YCRYCB422 ,
. memplanes = 1 ,
2014-11-10 14:28:31 -03:00
. mbus_code = MEDIA_BUS_FMT_YVYU8_2X8 ,
2013-03-20 15:31:03 -03:00
. flags = FMT_FLAGS_YUV ,
2012-04-27 05:29:05 -03:00
} , {
. fourcc = V4L2_PIX_FMT_SGRBG8 ,
2013-06-20 10:49:09 -03:00
. colorspace = V4L2_COLORSPACE_SRGB ,
2012-04-27 05:29:05 -03:00
. depth = { 8 } ,
. color = FIMC_FMT_RAW8 ,
. memplanes = 1 ,
2014-11-10 14:28:31 -03:00
. mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8 ,
2013-03-20 15:31:03 -03:00
. flags = FMT_FLAGS_RAW_BAYER ,
2012-04-27 05:29:05 -03:00
} , {
. fourcc = V4L2_PIX_FMT_SGRBG10 ,
2013-06-20 10:49:09 -03:00
. colorspace = V4L2_COLORSPACE_SRGB ,
2013-07-15 07:51:23 -03:00
. depth = { 16 } ,
2012-04-27 05:29:05 -03:00
. color = FIMC_FMT_RAW10 ,
. memplanes = 1 ,
2014-11-10 14:28:31 -03:00
. mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10 ,
2013-03-20 15:31:03 -03:00
. flags = FMT_FLAGS_RAW_BAYER ,
2012-04-27 05:29:05 -03:00
} , {
. fourcc = V4L2_PIX_FMT_SGRBG12 ,
2013-06-20 10:49:09 -03:00
. colorspace = V4L2_COLORSPACE_SRGB ,
2013-07-15 07:51:23 -03:00
. depth = { 16 } ,
2012-04-27 05:29:05 -03:00
. color = FIMC_FMT_RAW12 ,
. memplanes = 1 ,
2014-11-10 14:28:31 -03:00
. mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12 ,
2013-03-20 15:31:03 -03:00
. flags = FMT_FLAGS_RAW_BAYER ,
2012-04-27 05:29:05 -03:00
} ,
} ;
/**
* fimc_lite_find_format - lookup fimc color format by fourcc or media bus code
* @ pixelformat : fourcc to match , ignored if null
* @ mbus_code : media bus code to match , ignored if null
2013-03-20 15:31:03 -03:00
* @ mask : the color format flags to match
2012-04-27 05:29:05 -03:00
* @ index : index to the fimc_lite_formats array , ignored if negative
*/
static const struct fimc_fmt * fimc_lite_find_format ( const u32 * pixelformat ,
2013-03-20 15:31:03 -03:00
const u32 * mbus_code , unsigned int mask , int index )
2012-04-27 05:29:05 -03:00
{
const struct fimc_fmt * fmt , * def_fmt = NULL ;
unsigned int i ;
int id = 0 ;
if ( index > = ( int ) ARRAY_SIZE ( fimc_lite_formats ) )
return NULL ;
for ( i = 0 ; i < ARRAY_SIZE ( fimc_lite_formats ) ; + + i ) {
fmt = & fimc_lite_formats [ i ] ;
2013-03-20 15:31:03 -03:00
if ( mask & & ! ( fmt - > flags & mask ) )
continue ;
2012-04-27 05:29:05 -03:00
if ( pixelformat & & fmt - > fourcc = = * pixelformat )
return fmt ;
if ( mbus_code & & fmt - > mbus_code = = * mbus_code )
return fmt ;
if ( index = = id )
def_fmt = fmt ;
id + + ;
}
return def_fmt ;
}
2012-11-28 15:41:01 -03:00
static int fimc_lite_hw_init ( struct fimc_lite * fimc , bool isp_output )
2012-04-27 05:29:05 -03:00
{
2013-04-09 11:11:58 -03:00
struct fimc_source_info * si ;
2012-04-27 05:29:05 -03:00
unsigned long flags ;
2013-04-08 13:17:36 -03:00
if ( fimc - > sensor = = NULL )
2012-04-27 05:29:05 -03:00
return - ENXIO ;
2013-03-20 15:31:03 -03:00
if ( fimc - > inp_frame . fmt = = NULL | | fimc - > out_frame . fmt = = NULL )
2012-04-27 05:29:05 -03:00
return - EINVAL ;
2012-11-28 15:41:01 -03:00
/* Get sensor configuration data from the sensor subdev */
2013-04-08 13:17:36 -03:00
si = v4l2_get_subdev_hostdata ( fimc - > sensor ) ;
2013-04-09 11:11:58 -03:00
if ( ! si )
return - EINVAL ;
2012-04-27 05:29:05 -03:00
spin_lock_irqsave ( & fimc - > slock , flags ) ;
2013-04-09 11:11:58 -03:00
flite_hw_set_camera_bus ( fimc , si ) ;
2012-04-27 05:29:05 -03:00
flite_hw_set_source_format ( fimc , & fimc - > inp_frame ) ;
flite_hw_set_window_offset ( fimc , & fimc - > inp_frame ) ;
2013-06-14 12:38:15 -03:00
flite_hw_set_dma_buf_mask ( fimc , 0 ) ;
2012-11-28 15:41:01 -03:00
flite_hw_set_output_dma ( fimc , & fimc - > out_frame , ! isp_output ) ;
2012-04-27 05:29:05 -03:00
flite_hw_set_interrupt_mask ( fimc ) ;
flite_hw_set_test_pattern ( fimc , fimc - > test_pattern - > val ) ;
if ( debug > 0 )
flite_hw_dump_regs ( fimc , __func__ ) ;
spin_unlock_irqrestore ( & fimc - > slock , flags ) ;
return 0 ;
}
/*
* Reinitialize the driver so it is ready to start the streaming again .
* Set fimc - > state to indicate stream off and the hardware shut down state .
* If not suspending ( @ suspend is false ) , return any buffers to videobuf2 .
* Otherwise put any owned buffers onto the pending buffers queue , so they
* can be re - spun when the device is being resumed . Also perform FIMC
* software reset and disable streaming on the whole pipeline if required .
*/
static int fimc_lite_reinit ( struct fimc_lite * fimc , bool suspend )
{
struct flite_buffer * buf ;
unsigned long flags ;
bool streaming ;
spin_lock_irqsave ( & fimc - > slock , flags ) ;
streaming = fimc - > state & ( 1 < < ST_SENSOR_STREAM ) ;
fimc - > state & = ~ ( 1 < < ST_FLITE_RUN | 1 < < ST_FLITE_OFF |
1 < < ST_FLITE_STREAM | 1 < < ST_SENSOR_STREAM ) ;
if ( suspend )
fimc - > state | = ( 1 < < ST_FLITE_SUSPENDED ) ;
else
fimc - > state & = ~ ( 1 < < ST_FLITE_PENDING |
1 < < ST_FLITE_SUSPENDED ) ;
/* Release unused buffers */
while ( ! suspend & & ! list_empty ( & fimc - > pending_buf_q ) ) {
buf = fimc_lite_pending_queue_pop ( fimc ) ;
[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
vb2_buffer_done ( & buf - > vb . vb2_buf , VB2_BUF_STATE_ERROR ) ;
2012-04-27 05:29:05 -03:00
}
/* If suspending put unused buffers onto pending queue */
while ( ! list_empty ( & fimc - > active_buf_q ) ) {
buf = fimc_lite_active_queue_pop ( fimc ) ;
if ( suspend )
fimc_lite_pending_queue_add ( fimc , buf ) ;
else
[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
vb2_buffer_done ( & buf - > vb . vb2_buf , VB2_BUF_STATE_ERROR ) ;
2012-04-27 05:29:05 -03:00
}
spin_unlock_irqrestore ( & fimc - > slock , flags ) ;
flite_hw_reset ( fimc ) ;
if ( ! streaming )
return 0 ;
2013-05-31 11:37:22 -03:00
return fimc_pipeline_call ( & fimc - > ve , set_stream , 0 ) ;
2012-04-27 05:29:05 -03:00
}
static int fimc_lite_stop_capture ( struct fimc_lite * fimc , bool suspend )
{
unsigned long flags ;
if ( ! fimc_lite_active ( fimc ) )
return 0 ;
spin_lock_irqsave ( & fimc - > slock , flags ) ;
set_bit ( ST_FLITE_OFF , & fimc - > state ) ;
flite_hw_capture_stop ( fimc ) ;
spin_unlock_irqrestore ( & fimc - > slock , flags ) ;
wait_event_timeout ( fimc - > irq_queue ,
! test_bit ( ST_FLITE_OFF , & fimc - > state ) ,
( 2 * HZ / 10 ) ) ; /* 200 ms */
return fimc_lite_reinit ( fimc , suspend ) ;
}
/* Must be called with fimc.slock spinlock held. */
static void fimc_lite_config_update ( struct fimc_lite * fimc )
{
flite_hw_set_window_offset ( fimc , & fimc - > inp_frame ) ;
flite_hw_set_dma_window ( fimc , & fimc - > out_frame ) ;
flite_hw_set_test_pattern ( fimc , fimc - > test_pattern - > val ) ;
clear_bit ( ST_FLITE_CONFIG , & fimc - > state ) ;
}
static irqreturn_t flite_irq_handler ( int irq , void * priv )
{
struct fimc_lite * fimc = priv ;
struct flite_buffer * vbuf ;
unsigned long flags ;
u32 intsrc ;
spin_lock_irqsave ( & fimc - > slock , flags ) ;
intsrc = flite_hw_get_interrupt_source ( fimc ) ;
flite_hw_clear_pending_irq ( fimc ) ;
if ( test_and_clear_bit ( ST_FLITE_OFF , & fimc - > state ) ) {
wake_up ( & fimc - > irq_queue ) ;
goto done ;
}
if ( intsrc & FLITE_REG_CISTATUS_IRQ_SRC_OVERFLOW ) {
clear_bit ( ST_FLITE_RUN , & fimc - > state ) ;
fimc - > events . data_overflow + + ;
}
if ( intsrc & FLITE_REG_CISTATUS_IRQ_SRC_LASTCAPEND ) {
flite_hw_clear_last_capture_end ( fimc ) ;
clear_bit ( ST_FLITE_STREAM , & fimc - > state ) ;
wake_up ( & fimc - > irq_queue ) ;
}
2013-01-18 12:02:32 -03:00
if ( atomic_read ( & fimc - > out_path ) ! = FIMC_IO_DMA )
2012-04-27 05:29:05 -03:00
goto done ;
if ( ( intsrc & FLITE_REG_CISTATUS_IRQ_SRC_FRMSTART ) & &
test_bit ( ST_FLITE_RUN , & fimc - > state ) & &
! list_empty ( & fimc - > pending_buf_q ) ) {
2013-06-14 12:38:15 -03:00
vbuf = fimc_lite_pending_queue_pop ( fimc ) ;
flite_hw_set_dma_buffer ( fimc , vbuf ) ;
fimc_lite_active_queue_add ( fimc , vbuf ) ;
}
if ( ( intsrc & FLITE_REG_CISTATUS_IRQ_SRC_FRMEND ) & &
test_bit ( ST_FLITE_RUN , & fimc - > state ) & &
! list_empty ( & fimc - > active_buf_q ) ) {
2012-04-27 05:29:05 -03:00
vbuf = fimc_lite_active_queue_pop ( fimc ) ;
2015-11-03 08:16:37 -02:00
vbuf - > vb . vb2_buf . timestamp = ktime_get_ns ( ) ;
[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
vbuf - > vb . sequence = fimc - > frame_count + + ;
2013-06-14 12:38:15 -03:00
flite_hw_mask_dma_buffer ( fimc , vbuf - > index ) ;
[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
vb2_buffer_done ( & vbuf - > vb . vb2_buf , VB2_BUF_STATE_DONE ) ;
2012-04-27 05:29:05 -03:00
}
if ( test_bit ( ST_FLITE_CONFIG , & fimc - > state ) )
fimc_lite_config_update ( fimc ) ;
if ( list_empty ( & fimc - > pending_buf_q ) ) {
flite_hw_capture_stop ( fimc ) ;
clear_bit ( ST_FLITE_STREAM , & fimc - > state ) ;
}
done :
set_bit ( ST_FLITE_RUN , & fimc - > state ) ;
spin_unlock_irqrestore ( & fimc - > slock , flags ) ;
return IRQ_HANDLED ;
}
static int start_streaming ( struct vb2_queue * q , unsigned int count )
{
struct fimc_lite * fimc = q - > drv_priv ;
2013-06-14 12:38:15 -03:00
unsigned long flags ;
2012-04-27 05:29:05 -03:00
int ret ;
2013-06-14 12:38:15 -03:00
spin_lock_irqsave ( & fimc - > slock , flags ) ;
fimc - > buf_index = 0 ;
2012-04-27 05:29:05 -03:00
fimc - > frame_count = 0 ;
2013-06-14 12:38:15 -03:00
spin_unlock_irqrestore ( & fimc - > slock , flags ) ;
2012-11-28 15:41:01 -03:00
ret = fimc_lite_hw_init ( fimc , false ) ;
2012-04-27 05:29:05 -03:00
if ( ret ) {
fimc_lite_reinit ( fimc , false ) ;
return ret ;
}
set_bit ( ST_FLITE_PENDING , & fimc - > state ) ;
if ( ! list_empty ( & fimc - > active_buf_q ) & &
! test_and_set_bit ( ST_FLITE_STREAM , & fimc - > state ) ) {
flite_hw_capture_start ( fimc ) ;
if ( ! test_and_set_bit ( ST_SENSOR_STREAM , & fimc - > state ) )
2013-05-31 11:37:22 -03:00
fimc_pipeline_call ( & fimc - > ve , set_stream , 1 ) ;
2012-04-27 05:29:05 -03:00
}
if ( debug > 0 )
flite_hw_dump_regs ( fimc , __func__ ) ;
return 0 ;
}
2014-04-17 02:47:21 -03:00
static void stop_streaming ( struct vb2_queue * q )
2012-04-27 05:29:05 -03:00
{
struct fimc_lite * fimc = q - > drv_priv ;
if ( ! fimc_lite_active ( fimc ) )
2014-04-17 02:47:21 -03:00
return ;
2012-04-27 05:29:05 -03:00
2014-04-17 02:47:21 -03:00
fimc_lite_stop_capture ( fimc , false ) ;
2012-04-27 05:29:05 -03:00
}
2015-10-28 00:50:37 -02:00
static int queue_setup ( struct vb2_queue * vq ,
2012-04-27 05:29:05 -03:00
unsigned int * num_buffers , unsigned int * num_planes ,
2016-04-15 09:15:05 -03:00
unsigned int sizes [ ] , struct device * alloc_devs [ ] )
2012-04-27 05:29:05 -03:00
{
struct fimc_lite * fimc = vq - > drv_priv ;
struct flite_frame * frame = & fimc - > out_frame ;
2013-03-20 15:31:03 -03:00
const struct fimc_fmt * fmt = frame - > fmt ;
2015-10-28 00:50:37 -02:00
unsigned long wh = frame - > f_width * frame - > f_height ;
2012-04-27 05:29:05 -03:00
int i ;
if ( fmt = = NULL )
return - EINVAL ;
2015-10-28 00:50:37 -02:00
if ( * num_planes ) {
if ( * num_planes ! = fmt - > memplanes )
return - EINVAL ;
2016-02-16 07:30:19 -02:00
for ( i = 0 ; i < * num_planes ; i + + )
2015-10-28 00:50:37 -02:00
if ( sizes [ i ] < ( wh * fmt - > depth [ i ] ) / 8 )
return - EINVAL ;
return 0 ;
}
2012-04-27 05:29:05 -03:00
* num_planes = fmt - > memplanes ;
2016-02-16 07:30:19 -02:00
for ( i = 0 ; i < fmt - > memplanes ; i + + )
2015-10-28 00:50:37 -02:00
sizes [ i ] = ( wh * fmt - > depth [ i ] ) / 8 ;
2012-04-27 05:29:05 -03:00
return 0 ;
}
static int buffer_prepare ( struct vb2_buffer * vb )
{
struct vb2_queue * vq = vb - > vb2_queue ;
struct fimc_lite * fimc = vq - > drv_priv ;
int i ;
2013-03-20 15:31:03 -03:00
if ( fimc - > out_frame . fmt = = NULL )
2012-04-27 05:29:05 -03:00
return - EINVAL ;
2013-03-20 15:31:03 -03:00
for ( i = 0 ; i < fimc - > out_frame . fmt - > memplanes ; i + + ) {
2012-04-27 05:29:05 -03:00
unsigned long size = fimc - > payload [ i ] ;
if ( vb2_plane_size ( vb , i ) < size ) {
2013-05-31 11:37:18 -03:00
v4l2_err ( & fimc - > ve . vdev ,
2012-04-27 05:29:05 -03:00
" User buffer too small (%ld < %ld) \n " ,
vb2_plane_size ( vb , i ) , size ) ;
return - EINVAL ;
}
vb2_set_plane_payload ( vb , i , size ) ;
}
return 0 ;
}
static void buffer_queue ( 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 ) ;
2012-04-27 05:29:05 -03:00
struct flite_buffer * buf
[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
= container_of ( vbuf , struct flite_buffer , vb ) ;
2012-04-27 05:29:05 -03:00
struct fimc_lite * fimc = vb2_get_drv_priv ( vb - > vb2_queue ) ;
unsigned long flags ;
spin_lock_irqsave ( & fimc - > slock , flags ) ;
2020-11-24 09:41:28 +01:00
buf - > addr = vb2_dma_contig_plane_dma_addr ( vb , 0 ) ;
2012-04-27 05:29:05 -03:00
2013-06-14 12:38:15 -03:00
buf - > index = fimc - > buf_index + + ;
if ( fimc - > buf_index > = fimc - > reqbufs_count )
fimc - > buf_index = 0 ;
2012-04-27 05:29:05 -03:00
if ( ! test_bit ( ST_FLITE_SUSPENDED , & fimc - > state ) & &
! test_bit ( ST_FLITE_STREAM , & fimc - > state ) & &
list_empty ( & fimc - > active_buf_q ) ) {
2013-06-14 12:38:15 -03:00
flite_hw_set_dma_buffer ( fimc , buf ) ;
2012-04-27 05:29:05 -03:00
fimc_lite_active_queue_add ( fimc , buf ) ;
} else {
fimc_lite_pending_queue_add ( fimc , buf ) ;
}
if ( vb2_is_streaming ( & fimc - > vb_queue ) & &
! list_empty ( & fimc - > pending_buf_q ) & &
! test_and_set_bit ( ST_FLITE_STREAM , & fimc - > state ) ) {
flite_hw_capture_start ( fimc ) ;
spin_unlock_irqrestore ( & fimc - > slock , flags ) ;
if ( ! test_and_set_bit ( ST_SENSOR_STREAM , & fimc - > state ) )
2013-05-31 11:37:22 -03:00
fimc_pipeline_call ( & fimc - > ve , set_stream , 1 ) ;
2012-04-27 05:29:05 -03:00
return ;
}
spin_unlock_irqrestore ( & fimc - > slock , flags ) ;
}
static const struct vb2_ops fimc_lite_qops = {
. queue_setup = queue_setup ,
. buf_prepare = buffer_prepare ,
. buf_queue = buffer_queue ,
2013-03-25 16:43:08 -03:00
. wait_prepare = vb2_ops_wait_prepare ,
. wait_finish = vb2_ops_wait_finish ,
2012-04-27 05:29:05 -03:00
. start_streaming = start_streaming ,
. stop_streaming = stop_streaming ,
} ;
static void fimc_lite_clear_event_counters ( struct fimc_lite * fimc )
{
unsigned long flags ;
spin_lock_irqsave ( & fimc - > slock , flags ) ;
memset ( & fimc - > events , 0 , sizeof ( fimc - > events ) ) ;
spin_unlock_irqrestore ( & fimc - > slock , flags ) ;
}
static int fimc_lite_open ( struct file * file )
{
struct fimc_lite * fimc = video_drvdata ( file ) ;
2013-05-31 11:37:18 -03:00
struct media_entity * me = & fimc - > ve . vdev . entity ;
2012-05-17 14:22:10 -03:00
int ret ;
2012-04-27 05:29:05 -03:00
2012-12-06 10:26:19 -03:00
mutex_lock ( & fimc - > lock ) ;
2013-01-18 12:02:32 -03:00
if ( atomic_read ( & fimc - > out_path ) ! = FIMC_IO_DMA ) {
2012-11-28 15:41:01 -03:00
ret = - EBUSY ;
2013-03-25 16:43:08 -03:00
goto unlock ;
2012-11-28 15:41:01 -03:00
}
2012-04-27 05:29:05 -03:00
set_bit ( ST_FLITE_IN_USE , & fimc - > state ) ;
2021-04-23 17:19:17 +02:00
ret = pm_runtime_resume_and_get ( & fimc - > pdev - > dev ) ;
2012-05-17 14:22:10 -03:00
if ( ret < 0 )
2021-04-23 17:19:17 +02:00
goto err_in_use ;
2012-04-27 05:29:05 -03:00
2012-05-17 14:22:10 -03:00
ret = v4l2_fh_open ( file ) ;
if ( ret < 0 )
2013-03-25 16:43:08 -03:00
goto err_pm ;
2012-04-27 05:29:05 -03:00
2013-03-25 16:43:08 -03:00
if ( ! v4l2_fh_is_singular_file ( file ) | |
atomic_read ( & fimc - > out_path ) ! = FIMC_IO_DMA )
goto unlock ;
2012-04-27 05:29:05 -03:00
2015-08-19 12:35:21 -03:00
mutex_lock ( & me - > graph_obj . mdev - > graph_mutex ) ;
2013-05-31 11:37:20 -03:00
2013-05-31 11:37:22 -03:00
ret = fimc_pipeline_call ( & fimc - > ve , open , me , true ) ;
2013-05-31 11:37:20 -03:00
/* Mark video pipeline ending at this video node as in use. */
if ( ret = = 0 )
me - > use_count + + ;
2015-08-19 12:35:21 -03:00
mutex_unlock ( & me - > graph_obj . mdev - > graph_mutex ) ;
2013-05-31 11:37:20 -03:00
2013-03-25 16:43:08 -03:00
if ( ! ret ) {
2012-06-04 13:15:56 -03:00
fimc_lite_clear_event_counters ( fimc ) ;
2013-03-25 16:43:08 -03:00
goto unlock ;
2012-06-04 13:15:56 -03:00
}
2013-03-25 16:43:08 -03:00
v4l2_fh_release ( file ) ;
err_pm :
pm_runtime_put_sync ( & fimc - > pdev - > dev ) ;
2021-04-23 17:19:17 +02:00
err_in_use :
2013-03-25 16:43:08 -03:00
clear_bit ( ST_FLITE_IN_USE , & fimc - > state ) ;
unlock :
2012-06-04 13:15:56 -03:00
mutex_unlock ( & fimc - > lock ) ;
2012-04-27 05:29:05 -03:00
return ret ;
}
2013-03-25 16:43:08 -03:00
static int fimc_lite_release ( struct file * file )
2012-04-27 05:29:05 -03:00
{
struct fimc_lite * fimc = video_drvdata ( file ) ;
2013-05-31 11:37:20 -03:00
struct media_entity * entity = & fimc - > ve . vdev . entity ;
2012-06-04 13:15:56 -03:00
2012-11-22 11:13:04 -03:00
mutex_lock ( & fimc - > lock ) ;
2012-04-27 05:29:05 -03:00
2013-03-25 16:43:08 -03:00
if ( v4l2_fh_is_singular_file ( file ) & &
2013-01-18 12:02:32 -03:00
atomic_read ( & fimc - > out_path ) = = FIMC_IO_DMA ) {
2013-03-25 16:50:50 -03:00
if ( fimc - > streaming ) {
2016-11-21 14:48:30 -02:00
media_pipeline_stop ( entity ) ;
2013-03-25 16:50:50 -03:00
fimc - > streaming = false ;
}
2012-04-27 05:29:05 -03:00
fimc_lite_stop_capture ( fimc , false ) ;
2013-05-31 11:37:22 -03:00
fimc_pipeline_call ( & fimc - > ve , close ) ;
clear_bit ( ST_FLITE_IN_USE , & fimc - > state ) ;
2015-08-19 12:35:21 -03:00
mutex_lock ( & entity - > graph_obj . mdev - > graph_mutex ) ;
2013-05-31 11:37:20 -03:00
entity - > use_count - - ;
2015-08-19 12:35:21 -03:00
mutex_unlock ( & entity - > graph_obj . mdev - > graph_mutex ) ;
2012-04-27 05:29:05 -03:00
}
2013-11-25 05:49:02 -03:00
_vb2_fop_release ( file , NULL ) ;
2012-04-27 05:29:05 -03:00
pm_runtime_put ( & fimc - > pdev - > dev ) ;
2013-03-25 16:43:08 -03:00
clear_bit ( ST_FLITE_SUSPENDED , & fimc - > state ) ;
2012-04-27 05:29:05 -03:00
2012-06-04 13:15:56 -03:00
mutex_unlock ( & fimc - > lock ) ;
2013-03-25 16:43:08 -03:00
return 0 ;
2012-04-27 05:29:05 -03:00
}
static const struct v4l2_file_operations fimc_lite_fops = {
. owner = THIS_MODULE ,
. open = fimc_lite_open ,
2013-03-25 16:43:08 -03:00
. release = fimc_lite_release ,
. poll = vb2_fop_poll ,
2012-04-27 05:29:05 -03:00
. unlocked_ioctl = video_ioctl2 ,
2013-03-25 16:43:08 -03:00
. mmap = vb2_fop_mmap ,
2012-04-27 05:29:05 -03:00
} ;
/*
* Format and crop negotiation helpers
*/
2013-06-20 10:57:47 -03:00
static const struct fimc_fmt * fimc_lite_subdev_try_fmt ( struct fimc_lite * fimc ,
media: v4l2-subdev: add subdev-wide state struct
We have 'struct v4l2_subdev_pad_config' which contains configuration for
a single pad used for the TRY functionality, and an array of those
structs is passed to various v4l2_subdev_pad_ops.
I was working on subdev internal routing between pads, and realized that
there's no way to add TRY functionality for routes, which is not pad
specific configuration. Adding a separate struct for try-route config
wouldn't work either, as e.g. set-fmt needs to know the try-route
configuration to propagate the settings.
This patch adds a new struct, 'struct v4l2_subdev_state' (which at the
moment only contains the v4l2_subdev_pad_config array) and the new
struct is used in most of the places where v4l2_subdev_pad_config was
used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config
are changed to instead take v4l2_subdev_state.
The changes to drivers/media/v4l2-core/v4l2-subdev.c and
include/media/v4l2-subdev.h were written by hand, and all the driver
changes were done with the semantic patch below. The spatch needs to be
applied to a select list of directories. I used the following shell
commands to apply the spatch:
dirs="drivers/media/i2c drivers/media/platform drivers/media/usb drivers/media/test-drivers/vimc drivers/media/pci drivers/staging/media"
for dir in $dirs; do spatch -j8 --dir --include-headers --no-show-diff --in-place --sp-file v4l2-subdev-state.cocci $dir; done
Note that Coccinelle chokes on a few drivers (gcc extensions?). With
minor changes we can make Coccinelle run fine, and these changes can be
reverted after spatch. The diff for these changes is:
For drivers/media/i2c/s5k5baf.c:
@@ -1481,7 +1481,7 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
&s5k5baf_cis_rect,
v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
- v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
+ v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT),
};
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
For drivers/media/platform/s3c-camif/camif-capture.c:
@@ -1230,7 +1230,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
*mf = camif->mbus_fmt;
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* crop rectangle at camera interface input */
mf->width = camif->camif_crop.width;
mf->height = camif->camif_crop.height;
@@ -1332,7 +1332,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
}
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* Pixel format can be only changed on the sink pad. */
mf->code = camif->mbus_fmt.code;
mf->width = crop->width;
The semantic patch is:
// <smpl>
// Change function parameter
@@
identifier func;
identifier cfg;
@@
func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...)
{
<...
- cfg
+ sd_state
...>
}
// Change function declaration parameter
@@
identifier func;
identifier cfg;
type T;
@@
T func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...);
// Change function return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...)
{
...
}
// Change function declaration return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...);
// Some drivers pass a local pad_cfg for a single pad to a called function. Wrap it
// inside a pad_state.
@@
identifier func;
identifier pad_cfg;
@@
func(...)
{
...
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = { .pads = &pad_cfg };
<+...
(
v4l2_subdev_call
|
sensor_call
|
isi_try_fse
|
isc_try_fse
|
saa_call_all
)
(...,
- &pad_cfg
+ &pad_state
,...)
...+>
}
// If the function uses fields from pad_config, access via state->pads
@@
identifier func;
identifier state;
@@
func(...,
struct v4l2_subdev_state *state
, ...)
{
<...
(
- state->try_fmt
+ state->pads->try_fmt
|
- state->try_crop
+ state->pads->try_crop
|
- state->try_compose
+ state->pads->try_compose
)
...>
}
// If the function accesses the filehandle, use fh->state instead
@@
struct v4l2_subdev_fh *fh;
@@
- fh->pad
+ fh->state
@@
struct v4l2_subdev_fh fh;
@@
- fh.pad
+ fh.state
// Start of vsp1 specific
@@
@@
struct vsp1_entity {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
};
@@
symbol entity;
@@
vsp1_entity_init(...)
{
...
entity->config =
- v4l2_subdev_alloc_pad_config
+ v4l2_subdev_alloc_state
(&entity->subdev);
...
}
@@
symbol entity;
@@
vsp1_entity_destroy(...)
{
...
- v4l2_subdev_free_pad_config
+ v4l2_subdev_free_state
(entity->config);
...
}
@exists@
identifier func =~ "(^vsp1.*)|(hsit_set_format)|(sru_enum_frame_size)|(sru_set_format)|(uif_get_selection)|(uif_set_selection)|(uds_enum_frame_size)|(uds_set_format)|(brx_set_format)|(brx_get_selection)|(histo_get_selection)|(histo_set_selection)|(brx_set_selection)";
symbol config;
@@
func(...) {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
}
// End of vsp1 specific
// Start of rcar specific
@@
identifier sd;
identifier pad_cfg;
@@
rvin_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
// End of rcar specific
// Start of rockchip specific
@@
identifier func =~ "(rkisp1_rsz_get_pad_fmt)|(rkisp1_rsz_get_pad_crop)|(rkisp1_rsz_register)";
symbol rsz;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = rsz->pad_cfg };
...
- rsz->pad_cfg
+ &state
...
}
@@
identifier func =~ "(rkisp1_isp_get_pad_fmt)|(rkisp1_isp_get_pad_crop)";
symbol isp;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = isp->pad_cfg };
...
- isp->pad_cfg
+ &state
...
}
@@
symbol rkisp1;
symbol isp;
symbol pad_cfg;
@@
rkisp1_isp_register(...)
{
+ struct v4l2_subdev_state state = { .pads = rkisp1->isp.pad_cfg };
...
- rkisp1->isp.pad_cfg
+ &state
...
}
// End of rockchip specific
// Start of tegra-video specific
@@
identifier sd;
identifier pad_cfg;
@@
__tegra_channel_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
@@
identifier sd_state;
@@
__tegra_channel_try_format(...)
{
...
struct v4l2_subdev_state *sd_state;
<...
- sd_state->try_crop
+ sd_state->pads->try_crop
...>
}
// End of tegra-video specific
// </smpl>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2021-06-10 17:55:58 +03:00
struct v4l2_subdev_state * sd_state ,
2013-06-20 10:57:47 -03:00
struct v4l2_subdev_format * format )
2012-04-27 05:29:05 -03:00
{
2013-03-16 17:35:10 -03:00
struct flite_drvdata * dd = fimc - > dd ;
2013-06-20 10:57:47 -03:00
struct v4l2_mbus_framefmt * mf = & format - > format ;
const struct fimc_fmt * fmt = NULL ;
if ( format - > pad = = FLITE_SD_PAD_SINK ) {
v4l_bound_align_image ( & mf - > width , 8 , dd - > max_width ,
ffs ( dd - > out_width_align ) - 1 ,
& mf - > height , 0 , dd - > max_height , 0 , 0 ) ;
2012-04-27 05:29:05 -03:00
2013-06-20 10:57:47 -03:00
fmt = fimc_lite_find_format ( NULL , & mf - > code , 0 , 0 ) ;
if ( WARN_ON ( ! fmt ) )
return NULL ;
2013-06-20 10:49:09 -03:00
mf - > colorspace = fmt - > colorspace ;
2013-06-20 10:57:47 -03:00
mf - > code = fmt - > mbus_code ;
2012-04-27 05:29:05 -03:00
} else {
2013-06-20 10:57:47 -03:00
struct flite_frame * sink = & fimc - > inp_frame ;
struct v4l2_mbus_framefmt * sink_fmt ;
struct v4l2_rect * rect ;
2012-04-27 05:29:05 -03:00
2013-06-20 10:57:47 -03:00
if ( format - > which = = V4L2_SUBDEV_FORMAT_TRY ) {
media: v4l2-subdev: add subdev-wide state struct
We have 'struct v4l2_subdev_pad_config' which contains configuration for
a single pad used for the TRY functionality, and an array of those
structs is passed to various v4l2_subdev_pad_ops.
I was working on subdev internal routing between pads, and realized that
there's no way to add TRY functionality for routes, which is not pad
specific configuration. Adding a separate struct for try-route config
wouldn't work either, as e.g. set-fmt needs to know the try-route
configuration to propagate the settings.
This patch adds a new struct, 'struct v4l2_subdev_state' (which at the
moment only contains the v4l2_subdev_pad_config array) and the new
struct is used in most of the places where v4l2_subdev_pad_config was
used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config
are changed to instead take v4l2_subdev_state.
The changes to drivers/media/v4l2-core/v4l2-subdev.c and
include/media/v4l2-subdev.h were written by hand, and all the driver
changes were done with the semantic patch below. The spatch needs to be
applied to a select list of directories. I used the following shell
commands to apply the spatch:
dirs="drivers/media/i2c drivers/media/platform drivers/media/usb drivers/media/test-drivers/vimc drivers/media/pci drivers/staging/media"
for dir in $dirs; do spatch -j8 --dir --include-headers --no-show-diff --in-place --sp-file v4l2-subdev-state.cocci $dir; done
Note that Coccinelle chokes on a few drivers (gcc extensions?). With
minor changes we can make Coccinelle run fine, and these changes can be
reverted after spatch. The diff for these changes is:
For drivers/media/i2c/s5k5baf.c:
@@ -1481,7 +1481,7 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
&s5k5baf_cis_rect,
v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
- v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
+ v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT),
};
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
For drivers/media/platform/s3c-camif/camif-capture.c:
@@ -1230,7 +1230,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
*mf = camif->mbus_fmt;
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* crop rectangle at camera interface input */
mf->width = camif->camif_crop.width;
mf->height = camif->camif_crop.height;
@@ -1332,7 +1332,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
}
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* Pixel format can be only changed on the sink pad. */
mf->code = camif->mbus_fmt.code;
mf->width = crop->width;
The semantic patch is:
// <smpl>
// Change function parameter
@@
identifier func;
identifier cfg;
@@
func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...)
{
<...
- cfg
+ sd_state
...>
}
// Change function declaration parameter
@@
identifier func;
identifier cfg;
type T;
@@
T func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...);
// Change function return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...)
{
...
}
// Change function declaration return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...);
// Some drivers pass a local pad_cfg for a single pad to a called function. Wrap it
// inside a pad_state.
@@
identifier func;
identifier pad_cfg;
@@
func(...)
{
...
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = { .pads = &pad_cfg };
<+...
(
v4l2_subdev_call
|
sensor_call
|
isi_try_fse
|
isc_try_fse
|
saa_call_all
)
(...,
- &pad_cfg
+ &pad_state
,...)
...+>
}
// If the function uses fields from pad_config, access via state->pads
@@
identifier func;
identifier state;
@@
func(...,
struct v4l2_subdev_state *state
, ...)
{
<...
(
- state->try_fmt
+ state->pads->try_fmt
|
- state->try_crop
+ state->pads->try_crop
|
- state->try_compose
+ state->pads->try_compose
)
...>
}
// If the function accesses the filehandle, use fh->state instead
@@
struct v4l2_subdev_fh *fh;
@@
- fh->pad
+ fh->state
@@
struct v4l2_subdev_fh fh;
@@
- fh.pad
+ fh.state
// Start of vsp1 specific
@@
@@
struct vsp1_entity {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
};
@@
symbol entity;
@@
vsp1_entity_init(...)
{
...
entity->config =
- v4l2_subdev_alloc_pad_config
+ v4l2_subdev_alloc_state
(&entity->subdev);
...
}
@@
symbol entity;
@@
vsp1_entity_destroy(...)
{
...
- v4l2_subdev_free_pad_config
+ v4l2_subdev_free_state
(entity->config);
...
}
@exists@
identifier func =~ "(^vsp1.*)|(hsit_set_format)|(sru_enum_frame_size)|(sru_set_format)|(uif_get_selection)|(uif_set_selection)|(uds_enum_frame_size)|(uds_set_format)|(brx_set_format)|(brx_get_selection)|(histo_get_selection)|(histo_set_selection)|(brx_set_selection)";
symbol config;
@@
func(...) {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
}
// End of vsp1 specific
// Start of rcar specific
@@
identifier sd;
identifier pad_cfg;
@@
rvin_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
// End of rcar specific
// Start of rockchip specific
@@
identifier func =~ "(rkisp1_rsz_get_pad_fmt)|(rkisp1_rsz_get_pad_crop)|(rkisp1_rsz_register)";
symbol rsz;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = rsz->pad_cfg };
...
- rsz->pad_cfg
+ &state
...
}
@@
identifier func =~ "(rkisp1_isp_get_pad_fmt)|(rkisp1_isp_get_pad_crop)";
symbol isp;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = isp->pad_cfg };
...
- isp->pad_cfg
+ &state
...
}
@@
symbol rkisp1;
symbol isp;
symbol pad_cfg;
@@
rkisp1_isp_register(...)
{
+ struct v4l2_subdev_state state = { .pads = rkisp1->isp.pad_cfg };
...
- rkisp1->isp.pad_cfg
+ &state
...
}
// End of rockchip specific
// Start of tegra-video specific
@@
identifier sd;
identifier pad_cfg;
@@
__tegra_channel_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
@@
identifier sd_state;
@@
__tegra_channel_try_format(...)
{
...
struct v4l2_subdev_state *sd_state;
<...
- sd_state->try_crop
+ sd_state->pads->try_crop
...>
}
// End of tegra-video specific
// </smpl>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2021-06-10 17:55:58 +03:00
sink_fmt = v4l2_subdev_get_try_format ( & fimc - > subdev ,
sd_state ,
FLITE_SD_PAD_SINK ) ;
2013-03-20 15:31:03 -03:00
2013-06-20 10:57:47 -03:00
mf - > code = sink_fmt - > code ;
2013-06-20 10:49:09 -03:00
mf - > colorspace = sink_fmt - > colorspace ;
2013-06-20 10:57:47 -03:00
media: v4l2-subdev: add subdev-wide state struct
We have 'struct v4l2_subdev_pad_config' which contains configuration for
a single pad used for the TRY functionality, and an array of those
structs is passed to various v4l2_subdev_pad_ops.
I was working on subdev internal routing between pads, and realized that
there's no way to add TRY functionality for routes, which is not pad
specific configuration. Adding a separate struct for try-route config
wouldn't work either, as e.g. set-fmt needs to know the try-route
configuration to propagate the settings.
This patch adds a new struct, 'struct v4l2_subdev_state' (which at the
moment only contains the v4l2_subdev_pad_config array) and the new
struct is used in most of the places where v4l2_subdev_pad_config was
used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config
are changed to instead take v4l2_subdev_state.
The changes to drivers/media/v4l2-core/v4l2-subdev.c and
include/media/v4l2-subdev.h were written by hand, and all the driver
changes were done with the semantic patch below. The spatch needs to be
applied to a select list of directories. I used the following shell
commands to apply the spatch:
dirs="drivers/media/i2c drivers/media/platform drivers/media/usb drivers/media/test-drivers/vimc drivers/media/pci drivers/staging/media"
for dir in $dirs; do spatch -j8 --dir --include-headers --no-show-diff --in-place --sp-file v4l2-subdev-state.cocci $dir; done
Note that Coccinelle chokes on a few drivers (gcc extensions?). With
minor changes we can make Coccinelle run fine, and these changes can be
reverted after spatch. The diff for these changes is:
For drivers/media/i2c/s5k5baf.c:
@@ -1481,7 +1481,7 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
&s5k5baf_cis_rect,
v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
- v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
+ v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT),
};
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
For drivers/media/platform/s3c-camif/camif-capture.c:
@@ -1230,7 +1230,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
*mf = camif->mbus_fmt;
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* crop rectangle at camera interface input */
mf->width = camif->camif_crop.width;
mf->height = camif->camif_crop.height;
@@ -1332,7 +1332,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
}
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* Pixel format can be only changed on the sink pad. */
mf->code = camif->mbus_fmt.code;
mf->width = crop->width;
The semantic patch is:
// <smpl>
// Change function parameter
@@
identifier func;
identifier cfg;
@@
func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...)
{
<...
- cfg
+ sd_state
...>
}
// Change function declaration parameter
@@
identifier func;
identifier cfg;
type T;
@@
T func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...);
// Change function return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...)
{
...
}
// Change function declaration return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...);
// Some drivers pass a local pad_cfg for a single pad to a called function. Wrap it
// inside a pad_state.
@@
identifier func;
identifier pad_cfg;
@@
func(...)
{
...
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = { .pads = &pad_cfg };
<+...
(
v4l2_subdev_call
|
sensor_call
|
isi_try_fse
|
isc_try_fse
|
saa_call_all
)
(...,
- &pad_cfg
+ &pad_state
,...)
...+>
}
// If the function uses fields from pad_config, access via state->pads
@@
identifier func;
identifier state;
@@
func(...,
struct v4l2_subdev_state *state
, ...)
{
<...
(
- state->try_fmt
+ state->pads->try_fmt
|
- state->try_crop
+ state->pads->try_crop
|
- state->try_compose
+ state->pads->try_compose
)
...>
}
// If the function accesses the filehandle, use fh->state instead
@@
struct v4l2_subdev_fh *fh;
@@
- fh->pad
+ fh->state
@@
struct v4l2_subdev_fh fh;
@@
- fh.pad
+ fh.state
// Start of vsp1 specific
@@
@@
struct vsp1_entity {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
};
@@
symbol entity;
@@
vsp1_entity_init(...)
{
...
entity->config =
- v4l2_subdev_alloc_pad_config
+ v4l2_subdev_alloc_state
(&entity->subdev);
...
}
@@
symbol entity;
@@
vsp1_entity_destroy(...)
{
...
- v4l2_subdev_free_pad_config
+ v4l2_subdev_free_state
(entity->config);
...
}
@exists@
identifier func =~ "(^vsp1.*)|(hsit_set_format)|(sru_enum_frame_size)|(sru_set_format)|(uif_get_selection)|(uif_set_selection)|(uds_enum_frame_size)|(uds_set_format)|(brx_set_format)|(brx_get_selection)|(histo_get_selection)|(histo_set_selection)|(brx_set_selection)";
symbol config;
@@
func(...) {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
}
// End of vsp1 specific
// Start of rcar specific
@@
identifier sd;
identifier pad_cfg;
@@
rvin_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
// End of rcar specific
// Start of rockchip specific
@@
identifier func =~ "(rkisp1_rsz_get_pad_fmt)|(rkisp1_rsz_get_pad_crop)|(rkisp1_rsz_register)";
symbol rsz;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = rsz->pad_cfg };
...
- rsz->pad_cfg
+ &state
...
}
@@
identifier func =~ "(rkisp1_isp_get_pad_fmt)|(rkisp1_isp_get_pad_crop)";
symbol isp;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = isp->pad_cfg };
...
- isp->pad_cfg
+ &state
...
}
@@
symbol rkisp1;
symbol isp;
symbol pad_cfg;
@@
rkisp1_isp_register(...)
{
+ struct v4l2_subdev_state state = { .pads = rkisp1->isp.pad_cfg };
...
- rkisp1->isp.pad_cfg
+ &state
...
}
// End of rockchip specific
// Start of tegra-video specific
@@
identifier sd;
identifier pad_cfg;
@@
__tegra_channel_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
@@
identifier sd_state;
@@
__tegra_channel_try_format(...)
{
...
struct v4l2_subdev_state *sd_state;
<...
- sd_state->try_crop
+ sd_state->pads->try_crop
...>
}
// End of tegra-video specific
// </smpl>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2021-06-10 17:55:58 +03:00
rect = v4l2_subdev_get_try_crop ( & fimc - > subdev ,
sd_state ,
FLITE_SD_PAD_SINK ) ;
2013-06-20 10:57:47 -03:00
} else {
mf - > code = sink - > fmt - > mbus_code ;
2013-06-20 10:49:09 -03:00
mf - > colorspace = sink - > fmt - > colorspace ;
2013-06-20 10:57:47 -03:00
rect = & sink - > rect ;
}
/* Allow changing format only on sink pad */
mf - > width = rect - > width ;
mf - > height = rect - > height ;
}
2013-03-20 15:31:03 -03:00
2013-06-20 10:57:47 -03:00
mf - > field = V4L2_FIELD_NONE ;
v4l2_dbg ( 1 , debug , & fimc - > subdev , " code: %#x (%d), %dx%d \n " ,
mf - > code , mf - > colorspace , mf - > width , mf - > height ) ;
2012-04-27 05:29:05 -03:00
return fmt ;
}
static void fimc_lite_try_crop ( struct fimc_lite * fimc , struct v4l2_rect * r )
{
struct flite_frame * frame = & fimc - > inp_frame ;
v4l_bound_align_image ( & r - > width , 0 , frame - > f_width , 0 ,
& r - > height , 0 , frame - > f_height , 0 , 0 ) ;
/* Adjust left/top if cropping rectangle got out of bounds */
r - > left = clamp_t ( u32 , r - > left , 0 , frame - > f_width - r - > width ) ;
2013-03-16 17:35:10 -03:00
r - > left = round_down ( r - > left , fimc - > dd - > win_hor_offs_align ) ;
2012-04-27 05:29:05 -03:00
r - > top = clamp_t ( u32 , r - > top , 0 , frame - > f_height - r - > height ) ;
2012-12-07 16:40:08 -03:00
v4l2_dbg ( 1 , debug , & fimc - > subdev , " (%d,%d)/%dx%d, sink fmt: %dx%d \n " ,
2012-04-27 05:29:05 -03:00
r - > left , r - > top , r - > width , r - > height ,
frame - > f_width , frame - > f_height ) ;
}
static void fimc_lite_try_compose ( struct fimc_lite * fimc , struct v4l2_rect * r )
{
struct flite_frame * frame = & fimc - > out_frame ;
struct v4l2_rect * crop_rect = & fimc - > inp_frame . rect ;
/* Scaling is not supported so we enforce compose rectangle size
same as size of the sink crop rectangle . */
r - > width = crop_rect - > width ;
r - > height = crop_rect - > height ;
/* Adjust left/top if the composing rectangle got out of bounds */
r - > left = clamp_t ( u32 , r - > left , 0 , frame - > f_width - r - > width ) ;
2013-03-16 17:35:10 -03:00
r - > left = round_down ( r - > left , fimc - > dd - > out_hor_offs_align ) ;
2012-04-27 05:29:05 -03:00
r - > top = clamp_t ( u32 , r - > top , 0 , fimc - > out_frame . f_height - r - > height ) ;
2012-12-07 16:40:08 -03:00
v4l2_dbg ( 1 , debug , & fimc - > subdev , " (%d,%d)/%dx%d, source fmt: %dx%d \n " ,
2012-04-27 05:29:05 -03:00
r - > left , r - > top , r - > width , r - > height ,
frame - > f_width , frame - > f_height ) ;
}
/*
* Video node ioctl operations
*/
2013-04-30 09:27:53 -03:00
static int fimc_lite_querycap ( struct file * file , void * priv ,
2012-04-27 05:29:05 -03:00
struct v4l2_capability * cap )
{
2013-04-30 09:27:53 -03:00
struct fimc_lite * fimc = video_drvdata ( file ) ;
2018-09-10 08:19:14 -04:00
strscpy ( cap - > driver , FIMC_LITE_DRV_NAME , sizeof ( cap - > driver ) ) ;
strscpy ( cap - > card , FIMC_LITE_DRV_NAME , sizeof ( cap - > card ) ) ;
2013-04-30 09:27:53 -03:00
snprintf ( cap - > bus_info , sizeof ( cap - > bus_info ) , " platform:%s " ,
dev_name ( & fimc - > pdev - > dev ) ) ;
2012-04-27 05:29:05 -03:00
return 0 ;
}
2019-06-04 03:06:25 -04:00
static int fimc_lite_enum_fmt ( struct file * file , void * priv ,
struct v4l2_fmtdesc * f )
2012-04-27 05:29:05 -03:00
{
const struct fimc_fmt * fmt ;
if ( f - > index > = ARRAY_SIZE ( fimc_lite_formats ) )
return - EINVAL ;
fmt = & fimc_lite_formats [ f - > index ] ;
f - > pixelformat = fmt - > fourcc ;
return 0 ;
}
static int fimc_lite_g_fmt_mplane ( struct file * file , void * fh ,
struct v4l2_format * f )
{
struct fimc_lite * fimc = video_drvdata ( file ) ;
struct v4l2_pix_format_mplane * pixm = & f - > fmt . pix_mp ;
struct v4l2_plane_pix_format * plane_fmt = & pixm - > plane_fmt [ 0 ] ;
struct flite_frame * frame = & fimc - > out_frame ;
2013-03-20 15:31:03 -03:00
const struct fimc_fmt * fmt = frame - > fmt ;
2012-04-27 05:29:05 -03:00
plane_fmt - > bytesperline = ( frame - > f_width * fmt - > depth [ 0 ] ) / 8 ;
plane_fmt - > sizeimage = plane_fmt - > bytesperline * frame - > f_height ;
pixm - > num_planes = fmt - > memplanes ;
pixm - > pixelformat = fmt - > fourcc ;
pixm - > width = frame - > f_width ;
pixm - > height = frame - > f_height ;
pixm - > field = V4L2_FIELD_NONE ;
2013-06-20 10:49:09 -03:00
pixm - > colorspace = fmt - > colorspace ;
2012-04-27 05:29:05 -03:00
return 0 ;
}
static int fimc_lite_try_fmt ( struct fimc_lite * fimc ,
struct v4l2_pix_format_mplane * pixm ,
const struct fimc_fmt * * ffmt )
{
u32 bpl = pixm - > plane_fmt [ 0 ] . bytesperline ;
2013-03-16 17:35:10 -03:00
struct flite_drvdata * dd = fimc - > dd ;
2013-03-20 15:31:03 -03:00
const struct fimc_fmt * inp_fmt = fimc - > inp_frame . fmt ;
2012-04-27 05:29:05 -03:00
const struct fimc_fmt * fmt ;
2013-03-20 15:31:03 -03:00
if ( WARN_ON ( inp_fmt = = NULL ) )
return - EINVAL ;
/*
* We allow some flexibility only for YUV formats . In case of raw
* raw Bayer the FIMC - LITE ' s output format must match its camera
* interface input format .
*/
if ( inp_fmt - > flags & FMT_FLAGS_YUV )
fmt = fimc_lite_find_format ( & pixm - > pixelformat , NULL ,
inp_fmt - > flags , 0 ) ;
else
fmt = inp_fmt ;
2012-04-27 05:29:05 -03:00
if ( WARN_ON ( fmt = = NULL ) )
return - EINVAL ;
if ( ffmt )
* ffmt = fmt ;
2013-03-16 17:35:10 -03:00
v4l_bound_align_image ( & pixm - > width , 8 , dd - > max_width ,
ffs ( dd - > out_width_align ) - 1 ,
& pixm - > height , 0 , dd - > max_height , 0 , 0 ) ;
2012-04-27 05:29:05 -03:00
if ( ( bpl = = 0 | | ( ( bpl * 8 ) / fmt - > depth [ 0 ] ) < pixm - > width ) )
pixm - > plane_fmt [ 0 ] . bytesperline = ( pixm - > width *
fmt - > depth [ 0 ] ) / 8 ;
if ( pixm - > plane_fmt [ 0 ] . sizeimage = = 0 )
pixm - > plane_fmt [ 0 ] . sizeimage = ( pixm - > width * pixm - > height *
fmt - > depth [ 0 ] ) / 8 ;
pixm - > num_planes = fmt - > memplanes ;
pixm - > pixelformat = fmt - > fourcc ;
2013-06-20 10:49:09 -03:00
pixm - > colorspace = fmt - > colorspace ;
2012-04-27 05:29:05 -03:00
pixm - > field = V4L2_FIELD_NONE ;
return 0 ;
}
static int fimc_lite_try_fmt_mplane ( struct file * file , void * fh ,
struct v4l2_format * f )
{
struct fimc_lite * fimc = video_drvdata ( file ) ;
return fimc_lite_try_fmt ( fimc , & f - > fmt . pix_mp , NULL ) ;
}
static int fimc_lite_s_fmt_mplane ( struct file * file , void * priv ,
struct v4l2_format * f )
{
struct v4l2_pix_format_mplane * pixm = & f - > fmt . pix_mp ;
struct fimc_lite * fimc = video_drvdata ( file ) ;
struct flite_frame * frame = & fimc - > out_frame ;
const struct fimc_fmt * fmt = NULL ;
int ret ;
if ( vb2_is_busy ( & fimc - > vb_queue ) )
return - EBUSY ;
ret = fimc_lite_try_fmt ( fimc , & f - > fmt . pix_mp , & fmt ) ;
if ( ret < 0 )
return ret ;
2013-03-20 15:31:03 -03:00
frame - > fmt = fmt ;
2012-04-27 05:29:05 -03:00
fimc - > payload [ 0 ] = max ( ( pixm - > width * pixm - > height * fmt - > depth [ 0 ] ) / 8 ,
pixm - > plane_fmt [ 0 ] . sizeimage ) ;
frame - > f_width = pixm - > width ;
frame - > f_height = pixm - > height ;
return 0 ;
}
static int fimc_pipeline_validate ( struct fimc_lite * fimc )
{
struct v4l2_subdev * sd = & fimc - > subdev ;
struct v4l2_subdev_format sink_fmt , src_fmt ;
struct media_pad * pad ;
int ret ;
while ( 1 ) {
/* Retrieve format at the sink pad */
pad = & sd - > entity . pads [ 0 ] ;
if ( ! ( pad - > flags & MEDIA_PAD_FL_SINK ) )
break ;
/* Don't call FIMC subdev operation to avoid nested locking */
if ( sd = = & fimc - > subdev ) {
struct flite_frame * ff = & fimc - > out_frame ;
sink_fmt . format . width = ff - > f_width ;
sink_fmt . format . height = ff - > f_height ;
2013-03-20 15:31:03 -03:00
sink_fmt . format . code = fimc - > inp_frame . fmt - > mbus_code ;
2012-04-27 05:29:05 -03:00
} else {
sink_fmt . pad = pad - > index ;
sink_fmt . which = V4L2_SUBDEV_FORMAT_ACTIVE ;
ret = v4l2_subdev_call ( sd , pad , get_fmt , NULL ,
& sink_fmt ) ;
if ( ret < 0 & & ret ! = - ENOIOCTLCMD )
return - EPIPE ;
}
/* Retrieve format at the source pad */
2013-06-03 05:16:13 -03:00
pad = media_entity_remote_pad ( pad ) ;
2015-05-07 22:12:32 -03:00
if ( ! pad | | ! is_media_entity_v4l2_subdev ( pad - > entity ) )
2012-04-27 05:29:05 -03:00
break ;
sd = media_entity_to_v4l2_subdev ( pad - > entity ) ;
src_fmt . pad = pad - > index ;
src_fmt . which = V4L2_SUBDEV_FORMAT_ACTIVE ;
ret = v4l2_subdev_call ( sd , pad , get_fmt , NULL , & src_fmt ) ;
if ( ret < 0 & & ret ! = - ENOIOCTLCMD )
return - EPIPE ;
if ( src_fmt . format . width ! = sink_fmt . format . width | |
src_fmt . format . height ! = sink_fmt . format . height | |
src_fmt . format . code ! = sink_fmt . format . code )
return - EPIPE ;
}
return 0 ;
}
static int fimc_lite_streamon ( struct file * file , void * priv ,
enum v4l2_buf_type type )
{
struct fimc_lite * fimc = video_drvdata ( file ) ;
2013-05-31 11:37:18 -03:00
struct media_entity * entity = & fimc - > ve . vdev . entity ;
2012-04-27 05:29:05 -03:00
int ret ;
if ( fimc_lite_active ( fimc ) )
return - EBUSY ;
2016-11-21 14:48:30 -02:00
ret = media_pipeline_start ( entity , & fimc - > ve . pipe - > mp ) ;
2012-05-25 03:29:38 -03:00
if ( ret < 0 )
return ret ;
2012-04-27 05:29:05 -03:00
ret = fimc_pipeline_validate ( fimc ) ;
2013-03-25 16:43:08 -03:00
if ( ret < 0 )
goto err_p_stop ;
2012-04-27 05:29:05 -03:00
2013-06-10 08:51:44 -03:00
fimc - > sensor = fimc_find_remote_sensor ( & fimc - > subdev . entity ) ;
2013-04-08 13:17:36 -03:00
2013-03-25 16:43:08 -03:00
ret = vb2_ioctl_streamon ( file , priv , type ) ;
2013-03-25 16:50:50 -03:00
if ( ! ret ) {
fimc - > streaming = true ;
2013-03-25 16:43:08 -03:00
return ret ;
2013-03-25 16:50:50 -03:00
}
2013-03-25 16:43:08 -03:00
err_p_stop :
2016-11-21 14:48:30 -02:00
media_pipeline_stop ( entity ) ;
2013-03-25 16:43:08 -03:00
return 0 ;
2012-04-27 05:29:05 -03:00
}
static int fimc_lite_streamoff ( struct file * file , void * priv ,
enum v4l2_buf_type type )
{
struct fimc_lite * fimc = video_drvdata ( file ) ;
int ret ;
2013-03-25 16:43:08 -03:00
ret = vb2_ioctl_streamoff ( file , priv , type ) ;
2013-03-25 16:50:50 -03:00
if ( ret < 0 )
return ret ;
2016-11-21 14:48:30 -02:00
media_pipeline_stop ( & fimc - > ve . vdev . entity ) ;
2013-03-25 16:50:50 -03:00
fimc - > streaming = false ;
return 0 ;
2012-04-27 05:29:05 -03:00
}
static int fimc_lite_reqbufs ( struct file * file , void * priv ,
struct v4l2_requestbuffers * reqbufs )
{
struct fimc_lite * fimc = video_drvdata ( file ) ;
int ret ;
reqbufs - > count = max_t ( u32 , FLITE_REQ_BUFS_MIN , reqbufs - > count ) ;
2013-03-25 16:43:08 -03:00
ret = vb2_ioctl_reqbufs ( file , priv , reqbufs ) ;
2012-09-26 05:52:24 -03:00
if ( ! ret )
2012-04-27 05:29:05 -03:00
fimc - > reqbufs_count = reqbufs - > count ;
return ret ;
}
static int fimc_lite_g_selection ( struct file * file , void * fh ,
struct v4l2_selection * sel )
{
struct fimc_lite * fimc = video_drvdata ( file ) ;
struct flite_frame * f = & fimc - > out_frame ;
2017-05-08 11:35:05 -03:00
if ( sel - > type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE )
2012-04-27 05:29:05 -03:00
return - EINVAL ;
switch ( sel - > target ) {
case V4L2_SEL_TGT_COMPOSE_BOUNDS :
case V4L2_SEL_TGT_COMPOSE_DEFAULT :
sel - > r . left = 0 ;
sel - > r . top = 0 ;
sel - > r . width = f - > f_width ;
sel - > r . height = f - > f_height ;
return 0 ;
2012-05-20 11:17:12 -03:00
case V4L2_SEL_TGT_COMPOSE :
2012-04-27 05:29:05 -03:00
sel - > r = f - > rect ;
return 0 ;
}
return - EINVAL ;
}
static int fimc_lite_s_selection ( struct file * file , void * fh ,
struct v4l2_selection * sel )
{
struct fimc_lite * fimc = video_drvdata ( file ) ;
struct flite_frame * f = & fimc - > out_frame ;
struct v4l2_rect rect = sel - > r ;
unsigned long flags ;
2017-05-08 11:35:05 -03:00
if ( sel - > type ! = V4L2_BUF_TYPE_VIDEO_CAPTURE | |
2012-05-20 11:17:12 -03:00
sel - > target ! = V4L2_SEL_TGT_COMPOSE )
2012-04-27 05:29:05 -03:00
return - EINVAL ;
fimc_lite_try_compose ( fimc , & rect ) ;
if ( ( sel - > flags & V4L2_SEL_FLAG_LE ) & &
2020-05-28 15:26:05 +02:00
! v4l2_rect_enclosed ( & rect , & sel - > r ) )
2012-04-27 05:29:05 -03:00
return - ERANGE ;
if ( ( sel - > flags & V4L2_SEL_FLAG_GE ) & &
2020-05-28 15:26:05 +02:00
! v4l2_rect_enclosed ( & sel - > r , & rect ) )
2012-04-27 05:29:05 -03:00
return - ERANGE ;
sel - > r = rect ;
spin_lock_irqsave ( & fimc - > slock , flags ) ;
f - > rect = rect ;
set_bit ( ST_FLITE_CONFIG , & fimc - > state ) ;
spin_unlock_irqrestore ( & fimc - > slock , flags ) ;
return 0 ;
}
static const struct v4l2_ioctl_ops fimc_lite_ioctl_ops = {
2013-04-30 09:27:53 -03:00
. vidioc_querycap = fimc_lite_querycap ,
2019-06-04 03:06:25 -04:00
. vidioc_enum_fmt_vid_cap = fimc_lite_enum_fmt ,
2012-04-27 05:29:05 -03:00
. vidioc_try_fmt_vid_cap_mplane = fimc_lite_try_fmt_mplane ,
. vidioc_s_fmt_vid_cap_mplane = fimc_lite_s_fmt_mplane ,
. vidioc_g_fmt_vid_cap_mplane = fimc_lite_g_fmt_mplane ,
. vidioc_g_selection = fimc_lite_g_selection ,
. vidioc_s_selection = fimc_lite_s_selection ,
. vidioc_reqbufs = fimc_lite_reqbufs ,
2013-03-25 16:43:08 -03:00
. vidioc_querybuf = vb2_ioctl_querybuf ,
. vidioc_prepare_buf = vb2_ioctl_prepare_buf ,
. vidioc_create_bufs = vb2_ioctl_create_bufs ,
. vidioc_qbuf = vb2_ioctl_qbuf ,
. vidioc_dqbuf = vb2_ioctl_dqbuf ,
2012-04-27 05:29:05 -03:00
. vidioc_streamon = fimc_lite_streamon ,
. vidioc_streamoff = fimc_lite_streamoff ,
} ;
/* Capture subdev media entity operations */
static int fimc_lite_link_setup ( struct media_entity * entity ,
const struct media_pad * local ,
const struct media_pad * remote , u32 flags )
{
struct v4l2_subdev * sd = media_entity_to_v4l2_subdev ( entity ) ;
struct fimc_lite * fimc = v4l2_get_subdevdata ( sd ) ;
2012-11-28 15:41:01 -03:00
int ret = 0 ;
2012-04-27 05:29:05 -03:00
if ( WARN_ON ( fimc = = NULL ) )
return 0 ;
2012-12-07 16:40:08 -03:00
v4l2_dbg ( 1 , debug , sd , " %s: %s --> %s, flags: 0x%x. source_id: 0x%x \n " ,
2012-11-28 15:41:01 -03:00
__func__ , remote - > entity - > name , local - > entity - > name ,
2012-04-27 05:29:05 -03:00
flags , fimc - > source_subdev_grp_id ) ;
2012-11-28 15:41:01 -03:00
switch ( local - > index ) {
case FLITE_SD_PAD_SINK :
2012-04-27 05:29:05 -03:00
if ( flags & MEDIA_LNK_FL_ENABLED ) {
2012-11-28 15:41:01 -03:00
if ( fimc - > source_subdev_grp_id = = 0 )
fimc - > source_subdev_grp_id = sd - > grp_id ;
else
ret = - EBUSY ;
} else {
fimc - > source_subdev_grp_id = 0 ;
fimc - > sensor = NULL ;
2012-04-27 05:29:05 -03:00
}
2012-11-28 15:41:01 -03:00
break ;
2012-04-27 05:29:05 -03:00
2012-11-28 15:41:01 -03:00
case FLITE_SD_PAD_SOURCE_DMA :
if ( ! ( flags & MEDIA_LNK_FL_ENABLED ) )
2013-01-18 12:02:32 -03:00
atomic_set ( & fimc - > out_path , FIMC_IO_NONE ) ;
2012-11-28 15:41:01 -03:00
else
2016-03-01 06:31:53 -03:00
atomic_set ( & fimc - > out_path , FIMC_IO_DMA ) ;
2012-04-27 05:29:05 -03:00
break ;
2012-11-28 15:41:01 -03:00
case FLITE_SD_PAD_SOURCE_ISP :
if ( ! ( flags & MEDIA_LNK_FL_ENABLED ) )
2013-01-18 12:02:32 -03:00
atomic_set ( & fimc - > out_path , FIMC_IO_NONE ) ;
2012-04-27 05:29:05 -03:00
else
2016-03-01 06:31:53 -03:00
atomic_set ( & fimc - > out_path , FIMC_IO_ISP ) ;
2012-04-27 05:29:05 -03:00
break ;
default :
v4l2_err ( sd , " Invalid pad index \n " ) ;
2012-11-28 15:41:01 -03:00
ret = - EINVAL ;
2012-04-27 05:29:05 -03:00
}
2013-01-18 12:02:32 -03:00
mb ( ) ;
2012-04-27 05:29:05 -03:00
2012-11-28 15:41:01 -03:00
return ret ;
2012-04-27 05:29:05 -03:00
}
static const struct media_entity_operations fimc_lite_subdev_media_ops = {
. link_setup = fimc_lite_link_setup ,
} ;
static int fimc_lite_subdev_enum_mbus_code ( struct v4l2_subdev * sd ,
media: v4l2-subdev: add subdev-wide state struct
We have 'struct v4l2_subdev_pad_config' which contains configuration for
a single pad used for the TRY functionality, and an array of those
structs is passed to various v4l2_subdev_pad_ops.
I was working on subdev internal routing between pads, and realized that
there's no way to add TRY functionality for routes, which is not pad
specific configuration. Adding a separate struct for try-route config
wouldn't work either, as e.g. set-fmt needs to know the try-route
configuration to propagate the settings.
This patch adds a new struct, 'struct v4l2_subdev_state' (which at the
moment only contains the v4l2_subdev_pad_config array) and the new
struct is used in most of the places where v4l2_subdev_pad_config was
used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config
are changed to instead take v4l2_subdev_state.
The changes to drivers/media/v4l2-core/v4l2-subdev.c and
include/media/v4l2-subdev.h were written by hand, and all the driver
changes were done with the semantic patch below. The spatch needs to be
applied to a select list of directories. I used the following shell
commands to apply the spatch:
dirs="drivers/media/i2c drivers/media/platform drivers/media/usb drivers/media/test-drivers/vimc drivers/media/pci drivers/staging/media"
for dir in $dirs; do spatch -j8 --dir --include-headers --no-show-diff --in-place --sp-file v4l2-subdev-state.cocci $dir; done
Note that Coccinelle chokes on a few drivers (gcc extensions?). With
minor changes we can make Coccinelle run fine, and these changes can be
reverted after spatch. The diff for these changes is:
For drivers/media/i2c/s5k5baf.c:
@@ -1481,7 +1481,7 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
&s5k5baf_cis_rect,
v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
- v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
+ v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT),
};
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
For drivers/media/platform/s3c-camif/camif-capture.c:
@@ -1230,7 +1230,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
*mf = camif->mbus_fmt;
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* crop rectangle at camera interface input */
mf->width = camif->camif_crop.width;
mf->height = camif->camif_crop.height;
@@ -1332,7 +1332,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
}
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* Pixel format can be only changed on the sink pad. */
mf->code = camif->mbus_fmt.code;
mf->width = crop->width;
The semantic patch is:
// <smpl>
// Change function parameter
@@
identifier func;
identifier cfg;
@@
func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...)
{
<...
- cfg
+ sd_state
...>
}
// Change function declaration parameter
@@
identifier func;
identifier cfg;
type T;
@@
T func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...);
// Change function return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...)
{
...
}
// Change function declaration return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...);
// Some drivers pass a local pad_cfg for a single pad to a called function. Wrap it
// inside a pad_state.
@@
identifier func;
identifier pad_cfg;
@@
func(...)
{
...
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = { .pads = &pad_cfg };
<+...
(
v4l2_subdev_call
|
sensor_call
|
isi_try_fse
|
isc_try_fse
|
saa_call_all
)
(...,
- &pad_cfg
+ &pad_state
,...)
...+>
}
// If the function uses fields from pad_config, access via state->pads
@@
identifier func;
identifier state;
@@
func(...,
struct v4l2_subdev_state *state
, ...)
{
<...
(
- state->try_fmt
+ state->pads->try_fmt
|
- state->try_crop
+ state->pads->try_crop
|
- state->try_compose
+ state->pads->try_compose
)
...>
}
// If the function accesses the filehandle, use fh->state instead
@@
struct v4l2_subdev_fh *fh;
@@
- fh->pad
+ fh->state
@@
struct v4l2_subdev_fh fh;
@@
- fh.pad
+ fh.state
// Start of vsp1 specific
@@
@@
struct vsp1_entity {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
};
@@
symbol entity;
@@
vsp1_entity_init(...)
{
...
entity->config =
- v4l2_subdev_alloc_pad_config
+ v4l2_subdev_alloc_state
(&entity->subdev);
...
}
@@
symbol entity;
@@
vsp1_entity_destroy(...)
{
...
- v4l2_subdev_free_pad_config
+ v4l2_subdev_free_state
(entity->config);
...
}
@exists@
identifier func =~ "(^vsp1.*)|(hsit_set_format)|(sru_enum_frame_size)|(sru_set_format)|(uif_get_selection)|(uif_set_selection)|(uds_enum_frame_size)|(uds_set_format)|(brx_set_format)|(brx_get_selection)|(histo_get_selection)|(histo_set_selection)|(brx_set_selection)";
symbol config;
@@
func(...) {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
}
// End of vsp1 specific
// Start of rcar specific
@@
identifier sd;
identifier pad_cfg;
@@
rvin_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
// End of rcar specific
// Start of rockchip specific
@@
identifier func =~ "(rkisp1_rsz_get_pad_fmt)|(rkisp1_rsz_get_pad_crop)|(rkisp1_rsz_register)";
symbol rsz;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = rsz->pad_cfg };
...
- rsz->pad_cfg
+ &state
...
}
@@
identifier func =~ "(rkisp1_isp_get_pad_fmt)|(rkisp1_isp_get_pad_crop)";
symbol isp;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = isp->pad_cfg };
...
- isp->pad_cfg
+ &state
...
}
@@
symbol rkisp1;
symbol isp;
symbol pad_cfg;
@@
rkisp1_isp_register(...)
{
+ struct v4l2_subdev_state state = { .pads = rkisp1->isp.pad_cfg };
...
- rkisp1->isp.pad_cfg
+ &state
...
}
// End of rockchip specific
// Start of tegra-video specific
@@
identifier sd;
identifier pad_cfg;
@@
__tegra_channel_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
@@
identifier sd_state;
@@
__tegra_channel_try_format(...)
{
...
struct v4l2_subdev_state *sd_state;
<...
- sd_state->try_crop
+ sd_state->pads->try_crop
...>
}
// End of tegra-video specific
// </smpl>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2021-06-10 17:55:58 +03:00
struct v4l2_subdev_state * sd_state ,
2012-04-27 05:29:05 -03:00
struct v4l2_subdev_mbus_code_enum * code )
{
const struct fimc_fmt * fmt ;
2013-03-20 15:31:03 -03:00
fmt = fimc_lite_find_format ( NULL , NULL , 0 , code - > index ) ;
2012-04-27 05:29:05 -03:00
if ( ! fmt )
return - EINVAL ;
code - > code = fmt - > mbus_code ;
return 0 ;
}
2013-06-20 10:57:47 -03:00
static struct v4l2_mbus_framefmt * __fimc_lite_subdev_get_try_fmt (
2015-03-04 01:47:54 -08:00
struct v4l2_subdev * sd ,
media: v4l2-subdev: add subdev-wide state struct
We have 'struct v4l2_subdev_pad_config' which contains configuration for
a single pad used for the TRY functionality, and an array of those
structs is passed to various v4l2_subdev_pad_ops.
I was working on subdev internal routing between pads, and realized that
there's no way to add TRY functionality for routes, which is not pad
specific configuration. Adding a separate struct for try-route config
wouldn't work either, as e.g. set-fmt needs to know the try-route
configuration to propagate the settings.
This patch adds a new struct, 'struct v4l2_subdev_state' (which at the
moment only contains the v4l2_subdev_pad_config array) and the new
struct is used in most of the places where v4l2_subdev_pad_config was
used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config
are changed to instead take v4l2_subdev_state.
The changes to drivers/media/v4l2-core/v4l2-subdev.c and
include/media/v4l2-subdev.h were written by hand, and all the driver
changes were done with the semantic patch below. The spatch needs to be
applied to a select list of directories. I used the following shell
commands to apply the spatch:
dirs="drivers/media/i2c drivers/media/platform drivers/media/usb drivers/media/test-drivers/vimc drivers/media/pci drivers/staging/media"
for dir in $dirs; do spatch -j8 --dir --include-headers --no-show-diff --in-place --sp-file v4l2-subdev-state.cocci $dir; done
Note that Coccinelle chokes on a few drivers (gcc extensions?). With
minor changes we can make Coccinelle run fine, and these changes can be
reverted after spatch. The diff for these changes is:
For drivers/media/i2c/s5k5baf.c:
@@ -1481,7 +1481,7 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
&s5k5baf_cis_rect,
v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
- v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
+ v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT),
};
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
For drivers/media/platform/s3c-camif/camif-capture.c:
@@ -1230,7 +1230,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
*mf = camif->mbus_fmt;
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* crop rectangle at camera interface input */
mf->width = camif->camif_crop.width;
mf->height = camif->camif_crop.height;
@@ -1332,7 +1332,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
}
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* Pixel format can be only changed on the sink pad. */
mf->code = camif->mbus_fmt.code;
mf->width = crop->width;
The semantic patch is:
// <smpl>
// Change function parameter
@@
identifier func;
identifier cfg;
@@
func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...)
{
<...
- cfg
+ sd_state
...>
}
// Change function declaration parameter
@@
identifier func;
identifier cfg;
type T;
@@
T func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...);
// Change function return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...)
{
...
}
// Change function declaration return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...);
// Some drivers pass a local pad_cfg for a single pad to a called function. Wrap it
// inside a pad_state.
@@
identifier func;
identifier pad_cfg;
@@
func(...)
{
...
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = { .pads = &pad_cfg };
<+...
(
v4l2_subdev_call
|
sensor_call
|
isi_try_fse
|
isc_try_fse
|
saa_call_all
)
(...,
- &pad_cfg
+ &pad_state
,...)
...+>
}
// If the function uses fields from pad_config, access via state->pads
@@
identifier func;
identifier state;
@@
func(...,
struct v4l2_subdev_state *state
, ...)
{
<...
(
- state->try_fmt
+ state->pads->try_fmt
|
- state->try_crop
+ state->pads->try_crop
|
- state->try_compose
+ state->pads->try_compose
)
...>
}
// If the function accesses the filehandle, use fh->state instead
@@
struct v4l2_subdev_fh *fh;
@@
- fh->pad
+ fh->state
@@
struct v4l2_subdev_fh fh;
@@
- fh.pad
+ fh.state
// Start of vsp1 specific
@@
@@
struct vsp1_entity {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
};
@@
symbol entity;
@@
vsp1_entity_init(...)
{
...
entity->config =
- v4l2_subdev_alloc_pad_config
+ v4l2_subdev_alloc_state
(&entity->subdev);
...
}
@@
symbol entity;
@@
vsp1_entity_destroy(...)
{
...
- v4l2_subdev_free_pad_config
+ v4l2_subdev_free_state
(entity->config);
...
}
@exists@
identifier func =~ "(^vsp1.*)|(hsit_set_format)|(sru_enum_frame_size)|(sru_set_format)|(uif_get_selection)|(uif_set_selection)|(uds_enum_frame_size)|(uds_set_format)|(brx_set_format)|(brx_get_selection)|(histo_get_selection)|(histo_set_selection)|(brx_set_selection)";
symbol config;
@@
func(...) {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
}
// End of vsp1 specific
// Start of rcar specific
@@
identifier sd;
identifier pad_cfg;
@@
rvin_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
// End of rcar specific
// Start of rockchip specific
@@
identifier func =~ "(rkisp1_rsz_get_pad_fmt)|(rkisp1_rsz_get_pad_crop)|(rkisp1_rsz_register)";
symbol rsz;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = rsz->pad_cfg };
...
- rsz->pad_cfg
+ &state
...
}
@@
identifier func =~ "(rkisp1_isp_get_pad_fmt)|(rkisp1_isp_get_pad_crop)";
symbol isp;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = isp->pad_cfg };
...
- isp->pad_cfg
+ &state
...
}
@@
symbol rkisp1;
symbol isp;
symbol pad_cfg;
@@
rkisp1_isp_register(...)
{
+ struct v4l2_subdev_state state = { .pads = rkisp1->isp.pad_cfg };
...
- rkisp1->isp.pad_cfg
+ &state
...
}
// End of rockchip specific
// Start of tegra-video specific
@@
identifier sd;
identifier pad_cfg;
@@
__tegra_channel_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
@@
identifier sd_state;
@@
__tegra_channel_try_format(...)
{
...
struct v4l2_subdev_state *sd_state;
<...
- sd_state->try_crop
+ sd_state->pads->try_crop
...>
}
// End of tegra-video specific
// </smpl>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2021-06-10 17:55:58 +03:00
struct v4l2_subdev_state * sd_state , unsigned int pad )
2013-06-20 10:57:47 -03:00
{
if ( pad ! = FLITE_SD_PAD_SINK )
pad = FLITE_SD_PAD_SOURCE_DMA ;
media: v4l2-subdev: add subdev-wide state struct
We have 'struct v4l2_subdev_pad_config' which contains configuration for
a single pad used for the TRY functionality, and an array of those
structs is passed to various v4l2_subdev_pad_ops.
I was working on subdev internal routing between pads, and realized that
there's no way to add TRY functionality for routes, which is not pad
specific configuration. Adding a separate struct for try-route config
wouldn't work either, as e.g. set-fmt needs to know the try-route
configuration to propagate the settings.
This patch adds a new struct, 'struct v4l2_subdev_state' (which at the
moment only contains the v4l2_subdev_pad_config array) and the new
struct is used in most of the places where v4l2_subdev_pad_config was
used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config
are changed to instead take v4l2_subdev_state.
The changes to drivers/media/v4l2-core/v4l2-subdev.c and
include/media/v4l2-subdev.h were written by hand, and all the driver
changes were done with the semantic patch below. The spatch needs to be
applied to a select list of directories. I used the following shell
commands to apply the spatch:
dirs="drivers/media/i2c drivers/media/platform drivers/media/usb drivers/media/test-drivers/vimc drivers/media/pci drivers/staging/media"
for dir in $dirs; do spatch -j8 --dir --include-headers --no-show-diff --in-place --sp-file v4l2-subdev-state.cocci $dir; done
Note that Coccinelle chokes on a few drivers (gcc extensions?). With
minor changes we can make Coccinelle run fine, and these changes can be
reverted after spatch. The diff for these changes is:
For drivers/media/i2c/s5k5baf.c:
@@ -1481,7 +1481,7 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
&s5k5baf_cis_rect,
v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
- v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
+ v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT),
};
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
For drivers/media/platform/s3c-camif/camif-capture.c:
@@ -1230,7 +1230,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
*mf = camif->mbus_fmt;
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* crop rectangle at camera interface input */
mf->width = camif->camif_crop.width;
mf->height = camif->camif_crop.height;
@@ -1332,7 +1332,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
}
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* Pixel format can be only changed on the sink pad. */
mf->code = camif->mbus_fmt.code;
mf->width = crop->width;
The semantic patch is:
// <smpl>
// Change function parameter
@@
identifier func;
identifier cfg;
@@
func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...)
{
<...
- cfg
+ sd_state
...>
}
// Change function declaration parameter
@@
identifier func;
identifier cfg;
type T;
@@
T func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...);
// Change function return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...)
{
...
}
// Change function declaration return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...);
// Some drivers pass a local pad_cfg for a single pad to a called function. Wrap it
// inside a pad_state.
@@
identifier func;
identifier pad_cfg;
@@
func(...)
{
...
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = { .pads = &pad_cfg };
<+...
(
v4l2_subdev_call
|
sensor_call
|
isi_try_fse
|
isc_try_fse
|
saa_call_all
)
(...,
- &pad_cfg
+ &pad_state
,...)
...+>
}
// If the function uses fields from pad_config, access via state->pads
@@
identifier func;
identifier state;
@@
func(...,
struct v4l2_subdev_state *state
, ...)
{
<...
(
- state->try_fmt
+ state->pads->try_fmt
|
- state->try_crop
+ state->pads->try_crop
|
- state->try_compose
+ state->pads->try_compose
)
...>
}
// If the function accesses the filehandle, use fh->state instead
@@
struct v4l2_subdev_fh *fh;
@@
- fh->pad
+ fh->state
@@
struct v4l2_subdev_fh fh;
@@
- fh.pad
+ fh.state
// Start of vsp1 specific
@@
@@
struct vsp1_entity {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
};
@@
symbol entity;
@@
vsp1_entity_init(...)
{
...
entity->config =
- v4l2_subdev_alloc_pad_config
+ v4l2_subdev_alloc_state
(&entity->subdev);
...
}
@@
symbol entity;
@@
vsp1_entity_destroy(...)
{
...
- v4l2_subdev_free_pad_config
+ v4l2_subdev_free_state
(entity->config);
...
}
@exists@
identifier func =~ "(^vsp1.*)|(hsit_set_format)|(sru_enum_frame_size)|(sru_set_format)|(uif_get_selection)|(uif_set_selection)|(uds_enum_frame_size)|(uds_set_format)|(brx_set_format)|(brx_get_selection)|(histo_get_selection)|(histo_set_selection)|(brx_set_selection)";
symbol config;
@@
func(...) {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
}
// End of vsp1 specific
// Start of rcar specific
@@
identifier sd;
identifier pad_cfg;
@@
rvin_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
// End of rcar specific
// Start of rockchip specific
@@
identifier func =~ "(rkisp1_rsz_get_pad_fmt)|(rkisp1_rsz_get_pad_crop)|(rkisp1_rsz_register)";
symbol rsz;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = rsz->pad_cfg };
...
- rsz->pad_cfg
+ &state
...
}
@@
identifier func =~ "(rkisp1_isp_get_pad_fmt)|(rkisp1_isp_get_pad_crop)";
symbol isp;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = isp->pad_cfg };
...
- isp->pad_cfg
+ &state
...
}
@@
symbol rkisp1;
symbol isp;
symbol pad_cfg;
@@
rkisp1_isp_register(...)
{
+ struct v4l2_subdev_state state = { .pads = rkisp1->isp.pad_cfg };
...
- rkisp1->isp.pad_cfg
+ &state
...
}
// End of rockchip specific
// Start of tegra-video specific
@@
identifier sd;
identifier pad_cfg;
@@
__tegra_channel_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
@@
identifier sd_state;
@@
__tegra_channel_try_format(...)
{
...
struct v4l2_subdev_state *sd_state;
<...
- sd_state->try_crop
+ sd_state->pads->try_crop
...>
}
// End of tegra-video specific
// </smpl>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2021-06-10 17:55:58 +03:00
return v4l2_subdev_get_try_format ( sd , sd_state , pad ) ;
2013-06-20 10:57:47 -03:00
}
2012-04-27 05:29:05 -03:00
static int fimc_lite_subdev_get_fmt ( struct v4l2_subdev * sd ,
media: v4l2-subdev: add subdev-wide state struct
We have 'struct v4l2_subdev_pad_config' which contains configuration for
a single pad used for the TRY functionality, and an array of those
structs is passed to various v4l2_subdev_pad_ops.
I was working on subdev internal routing between pads, and realized that
there's no way to add TRY functionality for routes, which is not pad
specific configuration. Adding a separate struct for try-route config
wouldn't work either, as e.g. set-fmt needs to know the try-route
configuration to propagate the settings.
This patch adds a new struct, 'struct v4l2_subdev_state' (which at the
moment only contains the v4l2_subdev_pad_config array) and the new
struct is used in most of the places where v4l2_subdev_pad_config was
used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config
are changed to instead take v4l2_subdev_state.
The changes to drivers/media/v4l2-core/v4l2-subdev.c and
include/media/v4l2-subdev.h were written by hand, and all the driver
changes were done with the semantic patch below. The spatch needs to be
applied to a select list of directories. I used the following shell
commands to apply the spatch:
dirs="drivers/media/i2c drivers/media/platform drivers/media/usb drivers/media/test-drivers/vimc drivers/media/pci drivers/staging/media"
for dir in $dirs; do spatch -j8 --dir --include-headers --no-show-diff --in-place --sp-file v4l2-subdev-state.cocci $dir; done
Note that Coccinelle chokes on a few drivers (gcc extensions?). With
minor changes we can make Coccinelle run fine, and these changes can be
reverted after spatch. The diff for these changes is:
For drivers/media/i2c/s5k5baf.c:
@@ -1481,7 +1481,7 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
&s5k5baf_cis_rect,
v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
- v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
+ v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT),
};
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
For drivers/media/platform/s3c-camif/camif-capture.c:
@@ -1230,7 +1230,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
*mf = camif->mbus_fmt;
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* crop rectangle at camera interface input */
mf->width = camif->camif_crop.width;
mf->height = camif->camif_crop.height;
@@ -1332,7 +1332,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
}
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* Pixel format can be only changed on the sink pad. */
mf->code = camif->mbus_fmt.code;
mf->width = crop->width;
The semantic patch is:
// <smpl>
// Change function parameter
@@
identifier func;
identifier cfg;
@@
func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...)
{
<...
- cfg
+ sd_state
...>
}
// Change function declaration parameter
@@
identifier func;
identifier cfg;
type T;
@@
T func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...);
// Change function return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...)
{
...
}
// Change function declaration return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...);
// Some drivers pass a local pad_cfg for a single pad to a called function. Wrap it
// inside a pad_state.
@@
identifier func;
identifier pad_cfg;
@@
func(...)
{
...
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = { .pads = &pad_cfg };
<+...
(
v4l2_subdev_call
|
sensor_call
|
isi_try_fse
|
isc_try_fse
|
saa_call_all
)
(...,
- &pad_cfg
+ &pad_state
,...)
...+>
}
// If the function uses fields from pad_config, access via state->pads
@@
identifier func;
identifier state;
@@
func(...,
struct v4l2_subdev_state *state
, ...)
{
<...
(
- state->try_fmt
+ state->pads->try_fmt
|
- state->try_crop
+ state->pads->try_crop
|
- state->try_compose
+ state->pads->try_compose
)
...>
}
// If the function accesses the filehandle, use fh->state instead
@@
struct v4l2_subdev_fh *fh;
@@
- fh->pad
+ fh->state
@@
struct v4l2_subdev_fh fh;
@@
- fh.pad
+ fh.state
// Start of vsp1 specific
@@
@@
struct vsp1_entity {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
};
@@
symbol entity;
@@
vsp1_entity_init(...)
{
...
entity->config =
- v4l2_subdev_alloc_pad_config
+ v4l2_subdev_alloc_state
(&entity->subdev);
...
}
@@
symbol entity;
@@
vsp1_entity_destroy(...)
{
...
- v4l2_subdev_free_pad_config
+ v4l2_subdev_free_state
(entity->config);
...
}
@exists@
identifier func =~ "(^vsp1.*)|(hsit_set_format)|(sru_enum_frame_size)|(sru_set_format)|(uif_get_selection)|(uif_set_selection)|(uds_enum_frame_size)|(uds_set_format)|(brx_set_format)|(brx_get_selection)|(histo_get_selection)|(histo_set_selection)|(brx_set_selection)";
symbol config;
@@
func(...) {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
}
// End of vsp1 specific
// Start of rcar specific
@@
identifier sd;
identifier pad_cfg;
@@
rvin_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
// End of rcar specific
// Start of rockchip specific
@@
identifier func =~ "(rkisp1_rsz_get_pad_fmt)|(rkisp1_rsz_get_pad_crop)|(rkisp1_rsz_register)";
symbol rsz;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = rsz->pad_cfg };
...
- rsz->pad_cfg
+ &state
...
}
@@
identifier func =~ "(rkisp1_isp_get_pad_fmt)|(rkisp1_isp_get_pad_crop)";
symbol isp;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = isp->pad_cfg };
...
- isp->pad_cfg
+ &state
...
}
@@
symbol rkisp1;
symbol isp;
symbol pad_cfg;
@@
rkisp1_isp_register(...)
{
+ struct v4l2_subdev_state state = { .pads = rkisp1->isp.pad_cfg };
...
- rkisp1->isp.pad_cfg
+ &state
...
}
// End of rockchip specific
// Start of tegra-video specific
@@
identifier sd;
identifier pad_cfg;
@@
__tegra_channel_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
@@
identifier sd_state;
@@
__tegra_channel_try_format(...)
{
...
struct v4l2_subdev_state *sd_state;
<...
- sd_state->try_crop
+ sd_state->pads->try_crop
...>
}
// End of tegra-video specific
// </smpl>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2021-06-10 17:55:58 +03:00
struct v4l2_subdev_state * sd_state ,
2012-04-27 05:29:05 -03:00
struct v4l2_subdev_format * fmt )
{
struct fimc_lite * fimc = v4l2_get_subdevdata ( sd ) ;
struct v4l2_mbus_framefmt * mf = & fmt - > format ;
2013-03-20 15:31:03 -03:00
struct flite_frame * f = & fimc - > inp_frame ;
2012-04-27 05:29:05 -03:00
if ( fmt - > which = = V4L2_SUBDEV_FORMAT_TRY ) {
media: v4l2-subdev: add subdev-wide state struct
We have 'struct v4l2_subdev_pad_config' which contains configuration for
a single pad used for the TRY functionality, and an array of those
structs is passed to various v4l2_subdev_pad_ops.
I was working on subdev internal routing between pads, and realized that
there's no way to add TRY functionality for routes, which is not pad
specific configuration. Adding a separate struct for try-route config
wouldn't work either, as e.g. set-fmt needs to know the try-route
configuration to propagate the settings.
This patch adds a new struct, 'struct v4l2_subdev_state' (which at the
moment only contains the v4l2_subdev_pad_config array) and the new
struct is used in most of the places where v4l2_subdev_pad_config was
used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config
are changed to instead take v4l2_subdev_state.
The changes to drivers/media/v4l2-core/v4l2-subdev.c and
include/media/v4l2-subdev.h were written by hand, and all the driver
changes were done with the semantic patch below. The spatch needs to be
applied to a select list of directories. I used the following shell
commands to apply the spatch:
dirs="drivers/media/i2c drivers/media/platform drivers/media/usb drivers/media/test-drivers/vimc drivers/media/pci drivers/staging/media"
for dir in $dirs; do spatch -j8 --dir --include-headers --no-show-diff --in-place --sp-file v4l2-subdev-state.cocci $dir; done
Note that Coccinelle chokes on a few drivers (gcc extensions?). With
minor changes we can make Coccinelle run fine, and these changes can be
reverted after spatch. The diff for these changes is:
For drivers/media/i2c/s5k5baf.c:
@@ -1481,7 +1481,7 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
&s5k5baf_cis_rect,
v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
- v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
+ v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT),
};
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
For drivers/media/platform/s3c-camif/camif-capture.c:
@@ -1230,7 +1230,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
*mf = camif->mbus_fmt;
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* crop rectangle at camera interface input */
mf->width = camif->camif_crop.width;
mf->height = camif->camif_crop.height;
@@ -1332,7 +1332,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
}
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* Pixel format can be only changed on the sink pad. */
mf->code = camif->mbus_fmt.code;
mf->width = crop->width;
The semantic patch is:
// <smpl>
// Change function parameter
@@
identifier func;
identifier cfg;
@@
func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...)
{
<...
- cfg
+ sd_state
...>
}
// Change function declaration parameter
@@
identifier func;
identifier cfg;
type T;
@@
T func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...);
// Change function return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...)
{
...
}
// Change function declaration return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...);
// Some drivers pass a local pad_cfg for a single pad to a called function. Wrap it
// inside a pad_state.
@@
identifier func;
identifier pad_cfg;
@@
func(...)
{
...
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = { .pads = &pad_cfg };
<+...
(
v4l2_subdev_call
|
sensor_call
|
isi_try_fse
|
isc_try_fse
|
saa_call_all
)
(...,
- &pad_cfg
+ &pad_state
,...)
...+>
}
// If the function uses fields from pad_config, access via state->pads
@@
identifier func;
identifier state;
@@
func(...,
struct v4l2_subdev_state *state
, ...)
{
<...
(
- state->try_fmt
+ state->pads->try_fmt
|
- state->try_crop
+ state->pads->try_crop
|
- state->try_compose
+ state->pads->try_compose
)
...>
}
// If the function accesses the filehandle, use fh->state instead
@@
struct v4l2_subdev_fh *fh;
@@
- fh->pad
+ fh->state
@@
struct v4l2_subdev_fh fh;
@@
- fh.pad
+ fh.state
// Start of vsp1 specific
@@
@@
struct vsp1_entity {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
};
@@
symbol entity;
@@
vsp1_entity_init(...)
{
...
entity->config =
- v4l2_subdev_alloc_pad_config
+ v4l2_subdev_alloc_state
(&entity->subdev);
...
}
@@
symbol entity;
@@
vsp1_entity_destroy(...)
{
...
- v4l2_subdev_free_pad_config
+ v4l2_subdev_free_state
(entity->config);
...
}
@exists@
identifier func =~ "(^vsp1.*)|(hsit_set_format)|(sru_enum_frame_size)|(sru_set_format)|(uif_get_selection)|(uif_set_selection)|(uds_enum_frame_size)|(uds_set_format)|(brx_set_format)|(brx_get_selection)|(histo_get_selection)|(histo_set_selection)|(brx_set_selection)";
symbol config;
@@
func(...) {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
}
// End of vsp1 specific
// Start of rcar specific
@@
identifier sd;
identifier pad_cfg;
@@
rvin_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
// End of rcar specific
// Start of rockchip specific
@@
identifier func =~ "(rkisp1_rsz_get_pad_fmt)|(rkisp1_rsz_get_pad_crop)|(rkisp1_rsz_register)";
symbol rsz;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = rsz->pad_cfg };
...
- rsz->pad_cfg
+ &state
...
}
@@
identifier func =~ "(rkisp1_isp_get_pad_fmt)|(rkisp1_isp_get_pad_crop)";
symbol isp;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = isp->pad_cfg };
...
- isp->pad_cfg
+ &state
...
}
@@
symbol rkisp1;
symbol isp;
symbol pad_cfg;
@@
rkisp1_isp_register(...)
{
+ struct v4l2_subdev_state state = { .pads = rkisp1->isp.pad_cfg };
...
- rkisp1->isp.pad_cfg
+ &state
...
}
// End of rockchip specific
// Start of tegra-video specific
@@
identifier sd;
identifier pad_cfg;
@@
__tegra_channel_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
@@
identifier sd_state;
@@
__tegra_channel_try_format(...)
{
...
struct v4l2_subdev_state *sd_state;
<...
- sd_state->try_crop
+ sd_state->pads->try_crop
...>
}
// End of tegra-video specific
// </smpl>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2021-06-10 17:55:58 +03:00
mf = __fimc_lite_subdev_get_try_fmt ( sd , sd_state , fmt - > pad ) ;
2012-04-27 05:29:05 -03:00
fmt - > format = * mf ;
return 0 ;
}
mutex_lock ( & fimc - > lock ) ;
2013-06-20 10:49:09 -03:00
mf - > colorspace = f - > fmt - > colorspace ;
2013-03-20 15:31:03 -03:00
mf - > code = f - > fmt - > mbus_code ;
2012-04-27 05:29:05 -03:00
if ( fmt - > pad = = FLITE_SD_PAD_SINK ) {
/* full camera input frame size */
mf - > width = f - > f_width ;
mf - > height = f - > f_height ;
} else {
/* crop size */
mf - > width = f - > rect . width ;
mf - > height = f - > rect . height ;
}
mutex_unlock ( & fimc - > lock ) ;
return 0 ;
}
static int fimc_lite_subdev_set_fmt ( struct v4l2_subdev * sd ,
media: v4l2-subdev: add subdev-wide state struct
We have 'struct v4l2_subdev_pad_config' which contains configuration for
a single pad used for the TRY functionality, and an array of those
structs is passed to various v4l2_subdev_pad_ops.
I was working on subdev internal routing between pads, and realized that
there's no way to add TRY functionality for routes, which is not pad
specific configuration. Adding a separate struct for try-route config
wouldn't work either, as e.g. set-fmt needs to know the try-route
configuration to propagate the settings.
This patch adds a new struct, 'struct v4l2_subdev_state' (which at the
moment only contains the v4l2_subdev_pad_config array) and the new
struct is used in most of the places where v4l2_subdev_pad_config was
used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config
are changed to instead take v4l2_subdev_state.
The changes to drivers/media/v4l2-core/v4l2-subdev.c and
include/media/v4l2-subdev.h were written by hand, and all the driver
changes were done with the semantic patch below. The spatch needs to be
applied to a select list of directories. I used the following shell
commands to apply the spatch:
dirs="drivers/media/i2c drivers/media/platform drivers/media/usb drivers/media/test-drivers/vimc drivers/media/pci drivers/staging/media"
for dir in $dirs; do spatch -j8 --dir --include-headers --no-show-diff --in-place --sp-file v4l2-subdev-state.cocci $dir; done
Note that Coccinelle chokes on a few drivers (gcc extensions?). With
minor changes we can make Coccinelle run fine, and these changes can be
reverted after spatch. The diff for these changes is:
For drivers/media/i2c/s5k5baf.c:
@@ -1481,7 +1481,7 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
&s5k5baf_cis_rect,
v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
- v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
+ v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT),
};
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
For drivers/media/platform/s3c-camif/camif-capture.c:
@@ -1230,7 +1230,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
*mf = camif->mbus_fmt;
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* crop rectangle at camera interface input */
mf->width = camif->camif_crop.width;
mf->height = camif->camif_crop.height;
@@ -1332,7 +1332,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
}
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* Pixel format can be only changed on the sink pad. */
mf->code = camif->mbus_fmt.code;
mf->width = crop->width;
The semantic patch is:
// <smpl>
// Change function parameter
@@
identifier func;
identifier cfg;
@@
func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...)
{
<...
- cfg
+ sd_state
...>
}
// Change function declaration parameter
@@
identifier func;
identifier cfg;
type T;
@@
T func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...);
// Change function return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...)
{
...
}
// Change function declaration return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...);
// Some drivers pass a local pad_cfg for a single pad to a called function. Wrap it
// inside a pad_state.
@@
identifier func;
identifier pad_cfg;
@@
func(...)
{
...
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = { .pads = &pad_cfg };
<+...
(
v4l2_subdev_call
|
sensor_call
|
isi_try_fse
|
isc_try_fse
|
saa_call_all
)
(...,
- &pad_cfg
+ &pad_state
,...)
...+>
}
// If the function uses fields from pad_config, access via state->pads
@@
identifier func;
identifier state;
@@
func(...,
struct v4l2_subdev_state *state
, ...)
{
<...
(
- state->try_fmt
+ state->pads->try_fmt
|
- state->try_crop
+ state->pads->try_crop
|
- state->try_compose
+ state->pads->try_compose
)
...>
}
// If the function accesses the filehandle, use fh->state instead
@@
struct v4l2_subdev_fh *fh;
@@
- fh->pad
+ fh->state
@@
struct v4l2_subdev_fh fh;
@@
- fh.pad
+ fh.state
// Start of vsp1 specific
@@
@@
struct vsp1_entity {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
};
@@
symbol entity;
@@
vsp1_entity_init(...)
{
...
entity->config =
- v4l2_subdev_alloc_pad_config
+ v4l2_subdev_alloc_state
(&entity->subdev);
...
}
@@
symbol entity;
@@
vsp1_entity_destroy(...)
{
...
- v4l2_subdev_free_pad_config
+ v4l2_subdev_free_state
(entity->config);
...
}
@exists@
identifier func =~ "(^vsp1.*)|(hsit_set_format)|(sru_enum_frame_size)|(sru_set_format)|(uif_get_selection)|(uif_set_selection)|(uds_enum_frame_size)|(uds_set_format)|(brx_set_format)|(brx_get_selection)|(histo_get_selection)|(histo_set_selection)|(brx_set_selection)";
symbol config;
@@
func(...) {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
}
// End of vsp1 specific
// Start of rcar specific
@@
identifier sd;
identifier pad_cfg;
@@
rvin_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
// End of rcar specific
// Start of rockchip specific
@@
identifier func =~ "(rkisp1_rsz_get_pad_fmt)|(rkisp1_rsz_get_pad_crop)|(rkisp1_rsz_register)";
symbol rsz;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = rsz->pad_cfg };
...
- rsz->pad_cfg
+ &state
...
}
@@
identifier func =~ "(rkisp1_isp_get_pad_fmt)|(rkisp1_isp_get_pad_crop)";
symbol isp;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = isp->pad_cfg };
...
- isp->pad_cfg
+ &state
...
}
@@
symbol rkisp1;
symbol isp;
symbol pad_cfg;
@@
rkisp1_isp_register(...)
{
+ struct v4l2_subdev_state state = { .pads = rkisp1->isp.pad_cfg };
...
- rkisp1->isp.pad_cfg
+ &state
...
}
// End of rockchip specific
// Start of tegra-video specific
@@
identifier sd;
identifier pad_cfg;
@@
__tegra_channel_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
@@
identifier sd_state;
@@
__tegra_channel_try_format(...)
{
...
struct v4l2_subdev_state *sd_state;
<...
- sd_state->try_crop
+ sd_state->pads->try_crop
...>
}
// End of tegra-video specific
// </smpl>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2021-06-10 17:55:58 +03:00
struct v4l2_subdev_state * sd_state ,
2012-04-27 05:29:05 -03:00
struct v4l2_subdev_format * fmt )
{
struct fimc_lite * fimc = v4l2_get_subdevdata ( sd ) ;
struct v4l2_mbus_framefmt * mf = & fmt - > format ;
struct flite_frame * sink = & fimc - > inp_frame ;
2012-08-31 12:50:45 -03:00
struct flite_frame * source = & fimc - > out_frame ;
2012-04-27 05:29:05 -03:00
const struct fimc_fmt * ffmt ;
2012-12-07 16:40:08 -03:00
v4l2_dbg ( 1 , debug , sd , " pad%d: code: 0x%x, %dx%d \n " ,
2012-04-27 05:29:05 -03:00
fmt - > pad , mf - > code , mf - > width , mf - > height ) ;
mutex_lock ( & fimc - > lock ) ;
2013-01-18 12:02:32 -03:00
if ( ( atomic_read ( & fimc - > out_path ) = = FIMC_IO_ISP & &
sd - > entity . stream_count > 0 ) | |
( atomic_read ( & fimc - > out_path ) = = FIMC_IO_DMA & &
vb2_is_busy ( & fimc - > vb_queue ) ) ) {
2012-04-27 05:29:05 -03:00
mutex_unlock ( & fimc - > lock ) ;
return - EBUSY ;
}
media: v4l2-subdev: add subdev-wide state struct
We have 'struct v4l2_subdev_pad_config' which contains configuration for
a single pad used for the TRY functionality, and an array of those
structs is passed to various v4l2_subdev_pad_ops.
I was working on subdev internal routing between pads, and realized that
there's no way to add TRY functionality for routes, which is not pad
specific configuration. Adding a separate struct for try-route config
wouldn't work either, as e.g. set-fmt needs to know the try-route
configuration to propagate the settings.
This patch adds a new struct, 'struct v4l2_subdev_state' (which at the
moment only contains the v4l2_subdev_pad_config array) and the new
struct is used in most of the places where v4l2_subdev_pad_config was
used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config
are changed to instead take v4l2_subdev_state.
The changes to drivers/media/v4l2-core/v4l2-subdev.c and
include/media/v4l2-subdev.h were written by hand, and all the driver
changes were done with the semantic patch below. The spatch needs to be
applied to a select list of directories. I used the following shell
commands to apply the spatch:
dirs="drivers/media/i2c drivers/media/platform drivers/media/usb drivers/media/test-drivers/vimc drivers/media/pci drivers/staging/media"
for dir in $dirs; do spatch -j8 --dir --include-headers --no-show-diff --in-place --sp-file v4l2-subdev-state.cocci $dir; done
Note that Coccinelle chokes on a few drivers (gcc extensions?). With
minor changes we can make Coccinelle run fine, and these changes can be
reverted after spatch. The diff for these changes is:
For drivers/media/i2c/s5k5baf.c:
@@ -1481,7 +1481,7 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
&s5k5baf_cis_rect,
v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
- v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
+ v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT),
};
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
For drivers/media/platform/s3c-camif/camif-capture.c:
@@ -1230,7 +1230,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
*mf = camif->mbus_fmt;
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* crop rectangle at camera interface input */
mf->width = camif->camif_crop.width;
mf->height = camif->camif_crop.height;
@@ -1332,7 +1332,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
}
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* Pixel format can be only changed on the sink pad. */
mf->code = camif->mbus_fmt.code;
mf->width = crop->width;
The semantic patch is:
// <smpl>
// Change function parameter
@@
identifier func;
identifier cfg;
@@
func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...)
{
<...
- cfg
+ sd_state
...>
}
// Change function declaration parameter
@@
identifier func;
identifier cfg;
type T;
@@
T func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...);
// Change function return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...)
{
...
}
// Change function declaration return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...);
// Some drivers pass a local pad_cfg for a single pad to a called function. Wrap it
// inside a pad_state.
@@
identifier func;
identifier pad_cfg;
@@
func(...)
{
...
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = { .pads = &pad_cfg };
<+...
(
v4l2_subdev_call
|
sensor_call
|
isi_try_fse
|
isc_try_fse
|
saa_call_all
)
(...,
- &pad_cfg
+ &pad_state
,...)
...+>
}
// If the function uses fields from pad_config, access via state->pads
@@
identifier func;
identifier state;
@@
func(...,
struct v4l2_subdev_state *state
, ...)
{
<...
(
- state->try_fmt
+ state->pads->try_fmt
|
- state->try_crop
+ state->pads->try_crop
|
- state->try_compose
+ state->pads->try_compose
)
...>
}
// If the function accesses the filehandle, use fh->state instead
@@
struct v4l2_subdev_fh *fh;
@@
- fh->pad
+ fh->state
@@
struct v4l2_subdev_fh fh;
@@
- fh.pad
+ fh.state
// Start of vsp1 specific
@@
@@
struct vsp1_entity {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
};
@@
symbol entity;
@@
vsp1_entity_init(...)
{
...
entity->config =
- v4l2_subdev_alloc_pad_config
+ v4l2_subdev_alloc_state
(&entity->subdev);
...
}
@@
symbol entity;
@@
vsp1_entity_destroy(...)
{
...
- v4l2_subdev_free_pad_config
+ v4l2_subdev_free_state
(entity->config);
...
}
@exists@
identifier func =~ "(^vsp1.*)|(hsit_set_format)|(sru_enum_frame_size)|(sru_set_format)|(uif_get_selection)|(uif_set_selection)|(uds_enum_frame_size)|(uds_set_format)|(brx_set_format)|(brx_get_selection)|(histo_get_selection)|(histo_set_selection)|(brx_set_selection)";
symbol config;
@@
func(...) {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
}
// End of vsp1 specific
// Start of rcar specific
@@
identifier sd;
identifier pad_cfg;
@@
rvin_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
// End of rcar specific
// Start of rockchip specific
@@
identifier func =~ "(rkisp1_rsz_get_pad_fmt)|(rkisp1_rsz_get_pad_crop)|(rkisp1_rsz_register)";
symbol rsz;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = rsz->pad_cfg };
...
- rsz->pad_cfg
+ &state
...
}
@@
identifier func =~ "(rkisp1_isp_get_pad_fmt)|(rkisp1_isp_get_pad_crop)";
symbol isp;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = isp->pad_cfg };
...
- isp->pad_cfg
+ &state
...
}
@@
symbol rkisp1;
symbol isp;
symbol pad_cfg;
@@
rkisp1_isp_register(...)
{
+ struct v4l2_subdev_state state = { .pads = rkisp1->isp.pad_cfg };
...
- rkisp1->isp.pad_cfg
+ &state
...
}
// End of rockchip specific
// Start of tegra-video specific
@@
identifier sd;
identifier pad_cfg;
@@
__tegra_channel_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
@@
identifier sd_state;
@@
__tegra_channel_try_format(...)
{
...
struct v4l2_subdev_state *sd_state;
<...
- sd_state->try_crop
+ sd_state->pads->try_crop
...>
}
// End of tegra-video specific
// </smpl>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2021-06-10 17:55:58 +03:00
ffmt = fimc_lite_subdev_try_fmt ( fimc , sd_state , fmt ) ;
2012-04-27 05:29:05 -03:00
if ( fmt - > which = = V4L2_SUBDEV_FORMAT_TRY ) {
2013-06-20 10:57:47 -03:00
struct v4l2_mbus_framefmt * src_fmt ;
media: v4l2-subdev: add subdev-wide state struct
We have 'struct v4l2_subdev_pad_config' which contains configuration for
a single pad used for the TRY functionality, and an array of those
structs is passed to various v4l2_subdev_pad_ops.
I was working on subdev internal routing between pads, and realized that
there's no way to add TRY functionality for routes, which is not pad
specific configuration. Adding a separate struct for try-route config
wouldn't work either, as e.g. set-fmt needs to know the try-route
configuration to propagate the settings.
This patch adds a new struct, 'struct v4l2_subdev_state' (which at the
moment only contains the v4l2_subdev_pad_config array) and the new
struct is used in most of the places where v4l2_subdev_pad_config was
used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config
are changed to instead take v4l2_subdev_state.
The changes to drivers/media/v4l2-core/v4l2-subdev.c and
include/media/v4l2-subdev.h were written by hand, and all the driver
changes were done with the semantic patch below. The spatch needs to be
applied to a select list of directories. I used the following shell
commands to apply the spatch:
dirs="drivers/media/i2c drivers/media/platform drivers/media/usb drivers/media/test-drivers/vimc drivers/media/pci drivers/staging/media"
for dir in $dirs; do spatch -j8 --dir --include-headers --no-show-diff --in-place --sp-file v4l2-subdev-state.cocci $dir; done
Note that Coccinelle chokes on a few drivers (gcc extensions?). With
minor changes we can make Coccinelle run fine, and these changes can be
reverted after spatch. The diff for these changes is:
For drivers/media/i2c/s5k5baf.c:
@@ -1481,7 +1481,7 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
&s5k5baf_cis_rect,
v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
- v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
+ v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT),
};
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
For drivers/media/platform/s3c-camif/camif-capture.c:
@@ -1230,7 +1230,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
*mf = camif->mbus_fmt;
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* crop rectangle at camera interface input */
mf->width = camif->camif_crop.width;
mf->height = camif->camif_crop.height;
@@ -1332,7 +1332,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
}
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* Pixel format can be only changed on the sink pad. */
mf->code = camif->mbus_fmt.code;
mf->width = crop->width;
The semantic patch is:
// <smpl>
// Change function parameter
@@
identifier func;
identifier cfg;
@@
func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...)
{
<...
- cfg
+ sd_state
...>
}
// Change function declaration parameter
@@
identifier func;
identifier cfg;
type T;
@@
T func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...);
// Change function return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...)
{
...
}
// Change function declaration return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...);
// Some drivers pass a local pad_cfg for a single pad to a called function. Wrap it
// inside a pad_state.
@@
identifier func;
identifier pad_cfg;
@@
func(...)
{
...
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = { .pads = &pad_cfg };
<+...
(
v4l2_subdev_call
|
sensor_call
|
isi_try_fse
|
isc_try_fse
|
saa_call_all
)
(...,
- &pad_cfg
+ &pad_state
,...)
...+>
}
// If the function uses fields from pad_config, access via state->pads
@@
identifier func;
identifier state;
@@
func(...,
struct v4l2_subdev_state *state
, ...)
{
<...
(
- state->try_fmt
+ state->pads->try_fmt
|
- state->try_crop
+ state->pads->try_crop
|
- state->try_compose
+ state->pads->try_compose
)
...>
}
// If the function accesses the filehandle, use fh->state instead
@@
struct v4l2_subdev_fh *fh;
@@
- fh->pad
+ fh->state
@@
struct v4l2_subdev_fh fh;
@@
- fh.pad
+ fh.state
// Start of vsp1 specific
@@
@@
struct vsp1_entity {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
};
@@
symbol entity;
@@
vsp1_entity_init(...)
{
...
entity->config =
- v4l2_subdev_alloc_pad_config
+ v4l2_subdev_alloc_state
(&entity->subdev);
...
}
@@
symbol entity;
@@
vsp1_entity_destroy(...)
{
...
- v4l2_subdev_free_pad_config
+ v4l2_subdev_free_state
(entity->config);
...
}
@exists@
identifier func =~ "(^vsp1.*)|(hsit_set_format)|(sru_enum_frame_size)|(sru_set_format)|(uif_get_selection)|(uif_set_selection)|(uds_enum_frame_size)|(uds_set_format)|(brx_set_format)|(brx_get_selection)|(histo_get_selection)|(histo_set_selection)|(brx_set_selection)";
symbol config;
@@
func(...) {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
}
// End of vsp1 specific
// Start of rcar specific
@@
identifier sd;
identifier pad_cfg;
@@
rvin_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
// End of rcar specific
// Start of rockchip specific
@@
identifier func =~ "(rkisp1_rsz_get_pad_fmt)|(rkisp1_rsz_get_pad_crop)|(rkisp1_rsz_register)";
symbol rsz;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = rsz->pad_cfg };
...
- rsz->pad_cfg
+ &state
...
}
@@
identifier func =~ "(rkisp1_isp_get_pad_fmt)|(rkisp1_isp_get_pad_crop)";
symbol isp;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = isp->pad_cfg };
...
- isp->pad_cfg
+ &state
...
}
@@
symbol rkisp1;
symbol isp;
symbol pad_cfg;
@@
rkisp1_isp_register(...)
{
+ struct v4l2_subdev_state state = { .pads = rkisp1->isp.pad_cfg };
...
- rkisp1->isp.pad_cfg
+ &state
...
}
// End of rockchip specific
// Start of tegra-video specific
@@
identifier sd;
identifier pad_cfg;
@@
__tegra_channel_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
@@
identifier sd_state;
@@
__tegra_channel_try_format(...)
{
...
struct v4l2_subdev_state *sd_state;
<...
- sd_state->try_crop
+ sd_state->pads->try_crop
...>
}
// End of tegra-video specific
// </smpl>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2021-06-10 17:55:58 +03:00
mf = __fimc_lite_subdev_get_try_fmt ( sd , sd_state , fmt - > pad ) ;
2012-04-27 05:29:05 -03:00
* mf = fmt - > format ;
2013-06-20 10:57:47 -03:00
if ( fmt - > pad = = FLITE_SD_PAD_SINK ) {
unsigned int pad = FLITE_SD_PAD_SOURCE_DMA ;
media: v4l2-subdev: add subdev-wide state struct
We have 'struct v4l2_subdev_pad_config' which contains configuration for
a single pad used for the TRY functionality, and an array of those
structs is passed to various v4l2_subdev_pad_ops.
I was working on subdev internal routing between pads, and realized that
there's no way to add TRY functionality for routes, which is not pad
specific configuration. Adding a separate struct for try-route config
wouldn't work either, as e.g. set-fmt needs to know the try-route
configuration to propagate the settings.
This patch adds a new struct, 'struct v4l2_subdev_state' (which at the
moment only contains the v4l2_subdev_pad_config array) and the new
struct is used in most of the places where v4l2_subdev_pad_config was
used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config
are changed to instead take v4l2_subdev_state.
The changes to drivers/media/v4l2-core/v4l2-subdev.c and
include/media/v4l2-subdev.h were written by hand, and all the driver
changes were done with the semantic patch below. The spatch needs to be
applied to a select list of directories. I used the following shell
commands to apply the spatch:
dirs="drivers/media/i2c drivers/media/platform drivers/media/usb drivers/media/test-drivers/vimc drivers/media/pci drivers/staging/media"
for dir in $dirs; do spatch -j8 --dir --include-headers --no-show-diff --in-place --sp-file v4l2-subdev-state.cocci $dir; done
Note that Coccinelle chokes on a few drivers (gcc extensions?). With
minor changes we can make Coccinelle run fine, and these changes can be
reverted after spatch. The diff for these changes is:
For drivers/media/i2c/s5k5baf.c:
@@ -1481,7 +1481,7 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
&s5k5baf_cis_rect,
v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
- v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
+ v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT),
};
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
For drivers/media/platform/s3c-camif/camif-capture.c:
@@ -1230,7 +1230,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
*mf = camif->mbus_fmt;
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* crop rectangle at camera interface input */
mf->width = camif->camif_crop.width;
mf->height = camif->camif_crop.height;
@@ -1332,7 +1332,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
}
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* Pixel format can be only changed on the sink pad. */
mf->code = camif->mbus_fmt.code;
mf->width = crop->width;
The semantic patch is:
// <smpl>
// Change function parameter
@@
identifier func;
identifier cfg;
@@
func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...)
{
<...
- cfg
+ sd_state
...>
}
// Change function declaration parameter
@@
identifier func;
identifier cfg;
type T;
@@
T func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...);
// Change function return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...)
{
...
}
// Change function declaration return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...);
// Some drivers pass a local pad_cfg for a single pad to a called function. Wrap it
// inside a pad_state.
@@
identifier func;
identifier pad_cfg;
@@
func(...)
{
...
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = { .pads = &pad_cfg };
<+...
(
v4l2_subdev_call
|
sensor_call
|
isi_try_fse
|
isc_try_fse
|
saa_call_all
)
(...,
- &pad_cfg
+ &pad_state
,...)
...+>
}
// If the function uses fields from pad_config, access via state->pads
@@
identifier func;
identifier state;
@@
func(...,
struct v4l2_subdev_state *state
, ...)
{
<...
(
- state->try_fmt
+ state->pads->try_fmt
|
- state->try_crop
+ state->pads->try_crop
|
- state->try_compose
+ state->pads->try_compose
)
...>
}
// If the function accesses the filehandle, use fh->state instead
@@
struct v4l2_subdev_fh *fh;
@@
- fh->pad
+ fh->state
@@
struct v4l2_subdev_fh fh;
@@
- fh.pad
+ fh.state
// Start of vsp1 specific
@@
@@
struct vsp1_entity {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
};
@@
symbol entity;
@@
vsp1_entity_init(...)
{
...
entity->config =
- v4l2_subdev_alloc_pad_config
+ v4l2_subdev_alloc_state
(&entity->subdev);
...
}
@@
symbol entity;
@@
vsp1_entity_destroy(...)
{
...
- v4l2_subdev_free_pad_config
+ v4l2_subdev_free_state
(entity->config);
...
}
@exists@
identifier func =~ "(^vsp1.*)|(hsit_set_format)|(sru_enum_frame_size)|(sru_set_format)|(uif_get_selection)|(uif_set_selection)|(uds_enum_frame_size)|(uds_set_format)|(brx_set_format)|(brx_get_selection)|(histo_get_selection)|(histo_set_selection)|(brx_set_selection)";
symbol config;
@@
func(...) {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
}
// End of vsp1 specific
// Start of rcar specific
@@
identifier sd;
identifier pad_cfg;
@@
rvin_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
// End of rcar specific
// Start of rockchip specific
@@
identifier func =~ "(rkisp1_rsz_get_pad_fmt)|(rkisp1_rsz_get_pad_crop)|(rkisp1_rsz_register)";
symbol rsz;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = rsz->pad_cfg };
...
- rsz->pad_cfg
+ &state
...
}
@@
identifier func =~ "(rkisp1_isp_get_pad_fmt)|(rkisp1_isp_get_pad_crop)";
symbol isp;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = isp->pad_cfg };
...
- isp->pad_cfg
+ &state
...
}
@@
symbol rkisp1;
symbol isp;
symbol pad_cfg;
@@
rkisp1_isp_register(...)
{
+ struct v4l2_subdev_state state = { .pads = rkisp1->isp.pad_cfg };
...
- rkisp1->isp.pad_cfg
+ &state
...
}
// End of rockchip specific
// Start of tegra-video specific
@@
identifier sd;
identifier pad_cfg;
@@
__tegra_channel_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
@@
identifier sd_state;
@@
__tegra_channel_try_format(...)
{
...
struct v4l2_subdev_state *sd_state;
<...
- sd_state->try_crop
+ sd_state->pads->try_crop
...>
}
// End of tegra-video specific
// </smpl>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2021-06-10 17:55:58 +03:00
src_fmt = __fimc_lite_subdev_get_try_fmt ( sd , sd_state ,
pad ) ;
2013-06-20 10:57:47 -03:00
* src_fmt = * mf ;
}
2012-04-27 05:29:05 -03:00
mutex_unlock ( & fimc - > lock ) ;
return 0 ;
}
if ( fmt - > pad = = FLITE_SD_PAD_SINK ) {
sink - > f_width = mf - > width ;
sink - > f_height = mf - > height ;
2013-03-20 15:31:03 -03:00
sink - > fmt = ffmt ;
2012-04-27 05:29:05 -03:00
/* Set sink crop rectangle */
sink - > rect . width = mf - > width ;
sink - > rect . height = mf - > height ;
sink - > rect . left = 0 ;
sink - > rect . top = 0 ;
2012-08-31 12:50:45 -03:00
/* Reset source format and crop rectangle */
source - > rect = sink - > rect ;
source - > f_width = mf - > width ;
source - > f_height = mf - > height ;
2012-04-27 05:29:05 -03:00
}
mutex_unlock ( & fimc - > lock ) ;
return 0 ;
}
static int fimc_lite_subdev_get_selection ( struct v4l2_subdev * sd ,
media: v4l2-subdev: add subdev-wide state struct
We have 'struct v4l2_subdev_pad_config' which contains configuration for
a single pad used for the TRY functionality, and an array of those
structs is passed to various v4l2_subdev_pad_ops.
I was working on subdev internal routing between pads, and realized that
there's no way to add TRY functionality for routes, which is not pad
specific configuration. Adding a separate struct for try-route config
wouldn't work either, as e.g. set-fmt needs to know the try-route
configuration to propagate the settings.
This patch adds a new struct, 'struct v4l2_subdev_state' (which at the
moment only contains the v4l2_subdev_pad_config array) and the new
struct is used in most of the places where v4l2_subdev_pad_config was
used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config
are changed to instead take v4l2_subdev_state.
The changes to drivers/media/v4l2-core/v4l2-subdev.c and
include/media/v4l2-subdev.h were written by hand, and all the driver
changes were done with the semantic patch below. The spatch needs to be
applied to a select list of directories. I used the following shell
commands to apply the spatch:
dirs="drivers/media/i2c drivers/media/platform drivers/media/usb drivers/media/test-drivers/vimc drivers/media/pci drivers/staging/media"
for dir in $dirs; do spatch -j8 --dir --include-headers --no-show-diff --in-place --sp-file v4l2-subdev-state.cocci $dir; done
Note that Coccinelle chokes on a few drivers (gcc extensions?). With
minor changes we can make Coccinelle run fine, and these changes can be
reverted after spatch. The diff for these changes is:
For drivers/media/i2c/s5k5baf.c:
@@ -1481,7 +1481,7 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
&s5k5baf_cis_rect,
v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
- v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
+ v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT),
};
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
For drivers/media/platform/s3c-camif/camif-capture.c:
@@ -1230,7 +1230,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
*mf = camif->mbus_fmt;
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* crop rectangle at camera interface input */
mf->width = camif->camif_crop.width;
mf->height = camif->camif_crop.height;
@@ -1332,7 +1332,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
}
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* Pixel format can be only changed on the sink pad. */
mf->code = camif->mbus_fmt.code;
mf->width = crop->width;
The semantic patch is:
// <smpl>
// Change function parameter
@@
identifier func;
identifier cfg;
@@
func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...)
{
<...
- cfg
+ sd_state
...>
}
// Change function declaration parameter
@@
identifier func;
identifier cfg;
type T;
@@
T func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...);
// Change function return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...)
{
...
}
// Change function declaration return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...);
// Some drivers pass a local pad_cfg for a single pad to a called function. Wrap it
// inside a pad_state.
@@
identifier func;
identifier pad_cfg;
@@
func(...)
{
...
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = { .pads = &pad_cfg };
<+...
(
v4l2_subdev_call
|
sensor_call
|
isi_try_fse
|
isc_try_fse
|
saa_call_all
)
(...,
- &pad_cfg
+ &pad_state
,...)
...+>
}
// If the function uses fields from pad_config, access via state->pads
@@
identifier func;
identifier state;
@@
func(...,
struct v4l2_subdev_state *state
, ...)
{
<...
(
- state->try_fmt
+ state->pads->try_fmt
|
- state->try_crop
+ state->pads->try_crop
|
- state->try_compose
+ state->pads->try_compose
)
...>
}
// If the function accesses the filehandle, use fh->state instead
@@
struct v4l2_subdev_fh *fh;
@@
- fh->pad
+ fh->state
@@
struct v4l2_subdev_fh fh;
@@
- fh.pad
+ fh.state
// Start of vsp1 specific
@@
@@
struct vsp1_entity {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
};
@@
symbol entity;
@@
vsp1_entity_init(...)
{
...
entity->config =
- v4l2_subdev_alloc_pad_config
+ v4l2_subdev_alloc_state
(&entity->subdev);
...
}
@@
symbol entity;
@@
vsp1_entity_destroy(...)
{
...
- v4l2_subdev_free_pad_config
+ v4l2_subdev_free_state
(entity->config);
...
}
@exists@
identifier func =~ "(^vsp1.*)|(hsit_set_format)|(sru_enum_frame_size)|(sru_set_format)|(uif_get_selection)|(uif_set_selection)|(uds_enum_frame_size)|(uds_set_format)|(brx_set_format)|(brx_get_selection)|(histo_get_selection)|(histo_set_selection)|(brx_set_selection)";
symbol config;
@@
func(...) {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
}
// End of vsp1 specific
// Start of rcar specific
@@
identifier sd;
identifier pad_cfg;
@@
rvin_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
// End of rcar specific
// Start of rockchip specific
@@
identifier func =~ "(rkisp1_rsz_get_pad_fmt)|(rkisp1_rsz_get_pad_crop)|(rkisp1_rsz_register)";
symbol rsz;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = rsz->pad_cfg };
...
- rsz->pad_cfg
+ &state
...
}
@@
identifier func =~ "(rkisp1_isp_get_pad_fmt)|(rkisp1_isp_get_pad_crop)";
symbol isp;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = isp->pad_cfg };
...
- isp->pad_cfg
+ &state
...
}
@@
symbol rkisp1;
symbol isp;
symbol pad_cfg;
@@
rkisp1_isp_register(...)
{
+ struct v4l2_subdev_state state = { .pads = rkisp1->isp.pad_cfg };
...
- rkisp1->isp.pad_cfg
+ &state
...
}
// End of rockchip specific
// Start of tegra-video specific
@@
identifier sd;
identifier pad_cfg;
@@
__tegra_channel_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
@@
identifier sd_state;
@@
__tegra_channel_try_format(...)
{
...
struct v4l2_subdev_state *sd_state;
<...
- sd_state->try_crop
+ sd_state->pads->try_crop
...>
}
// End of tegra-video specific
// </smpl>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2021-06-10 17:55:58 +03:00
struct v4l2_subdev_state * sd_state ,
2012-04-27 05:29:05 -03:00
struct v4l2_subdev_selection * sel )
{
struct fimc_lite * fimc = v4l2_get_subdevdata ( sd ) ;
struct flite_frame * f = & fimc - > inp_frame ;
2012-05-18 09:31:18 -03:00
if ( ( sel - > target ! = V4L2_SEL_TGT_CROP & &
sel - > target ! = V4L2_SEL_TGT_CROP_BOUNDS ) | |
sel - > pad ! = FLITE_SD_PAD_SINK )
2012-04-27 05:29:05 -03:00
return - EINVAL ;
if ( sel - > which = = V4L2_SUBDEV_FORMAT_TRY ) {
media: v4l2-subdev: add subdev-wide state struct
We have 'struct v4l2_subdev_pad_config' which contains configuration for
a single pad used for the TRY functionality, and an array of those
structs is passed to various v4l2_subdev_pad_ops.
I was working on subdev internal routing between pads, and realized that
there's no way to add TRY functionality for routes, which is not pad
specific configuration. Adding a separate struct for try-route config
wouldn't work either, as e.g. set-fmt needs to know the try-route
configuration to propagate the settings.
This patch adds a new struct, 'struct v4l2_subdev_state' (which at the
moment only contains the v4l2_subdev_pad_config array) and the new
struct is used in most of the places where v4l2_subdev_pad_config was
used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config
are changed to instead take v4l2_subdev_state.
The changes to drivers/media/v4l2-core/v4l2-subdev.c and
include/media/v4l2-subdev.h were written by hand, and all the driver
changes were done with the semantic patch below. The spatch needs to be
applied to a select list of directories. I used the following shell
commands to apply the spatch:
dirs="drivers/media/i2c drivers/media/platform drivers/media/usb drivers/media/test-drivers/vimc drivers/media/pci drivers/staging/media"
for dir in $dirs; do spatch -j8 --dir --include-headers --no-show-diff --in-place --sp-file v4l2-subdev-state.cocci $dir; done
Note that Coccinelle chokes on a few drivers (gcc extensions?). With
minor changes we can make Coccinelle run fine, and these changes can be
reverted after spatch. The diff for these changes is:
For drivers/media/i2c/s5k5baf.c:
@@ -1481,7 +1481,7 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
&s5k5baf_cis_rect,
v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
- v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
+ v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT),
};
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
For drivers/media/platform/s3c-camif/camif-capture.c:
@@ -1230,7 +1230,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
*mf = camif->mbus_fmt;
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* crop rectangle at camera interface input */
mf->width = camif->camif_crop.width;
mf->height = camif->camif_crop.height;
@@ -1332,7 +1332,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
}
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* Pixel format can be only changed on the sink pad. */
mf->code = camif->mbus_fmt.code;
mf->width = crop->width;
The semantic patch is:
// <smpl>
// Change function parameter
@@
identifier func;
identifier cfg;
@@
func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...)
{
<...
- cfg
+ sd_state
...>
}
// Change function declaration parameter
@@
identifier func;
identifier cfg;
type T;
@@
T func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...);
// Change function return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...)
{
...
}
// Change function declaration return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...);
// Some drivers pass a local pad_cfg for a single pad to a called function. Wrap it
// inside a pad_state.
@@
identifier func;
identifier pad_cfg;
@@
func(...)
{
...
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = { .pads = &pad_cfg };
<+...
(
v4l2_subdev_call
|
sensor_call
|
isi_try_fse
|
isc_try_fse
|
saa_call_all
)
(...,
- &pad_cfg
+ &pad_state
,...)
...+>
}
// If the function uses fields from pad_config, access via state->pads
@@
identifier func;
identifier state;
@@
func(...,
struct v4l2_subdev_state *state
, ...)
{
<...
(
- state->try_fmt
+ state->pads->try_fmt
|
- state->try_crop
+ state->pads->try_crop
|
- state->try_compose
+ state->pads->try_compose
)
...>
}
// If the function accesses the filehandle, use fh->state instead
@@
struct v4l2_subdev_fh *fh;
@@
- fh->pad
+ fh->state
@@
struct v4l2_subdev_fh fh;
@@
- fh.pad
+ fh.state
// Start of vsp1 specific
@@
@@
struct vsp1_entity {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
};
@@
symbol entity;
@@
vsp1_entity_init(...)
{
...
entity->config =
- v4l2_subdev_alloc_pad_config
+ v4l2_subdev_alloc_state
(&entity->subdev);
...
}
@@
symbol entity;
@@
vsp1_entity_destroy(...)
{
...
- v4l2_subdev_free_pad_config
+ v4l2_subdev_free_state
(entity->config);
...
}
@exists@
identifier func =~ "(^vsp1.*)|(hsit_set_format)|(sru_enum_frame_size)|(sru_set_format)|(uif_get_selection)|(uif_set_selection)|(uds_enum_frame_size)|(uds_set_format)|(brx_set_format)|(brx_get_selection)|(histo_get_selection)|(histo_set_selection)|(brx_set_selection)";
symbol config;
@@
func(...) {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
}
// End of vsp1 specific
// Start of rcar specific
@@
identifier sd;
identifier pad_cfg;
@@
rvin_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
// End of rcar specific
// Start of rockchip specific
@@
identifier func =~ "(rkisp1_rsz_get_pad_fmt)|(rkisp1_rsz_get_pad_crop)|(rkisp1_rsz_register)";
symbol rsz;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = rsz->pad_cfg };
...
- rsz->pad_cfg
+ &state
...
}
@@
identifier func =~ "(rkisp1_isp_get_pad_fmt)|(rkisp1_isp_get_pad_crop)";
symbol isp;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = isp->pad_cfg };
...
- isp->pad_cfg
+ &state
...
}
@@
symbol rkisp1;
symbol isp;
symbol pad_cfg;
@@
rkisp1_isp_register(...)
{
+ struct v4l2_subdev_state state = { .pads = rkisp1->isp.pad_cfg };
...
- rkisp1->isp.pad_cfg
+ &state
...
}
// End of rockchip specific
// Start of tegra-video specific
@@
identifier sd;
identifier pad_cfg;
@@
__tegra_channel_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
@@
identifier sd_state;
@@
__tegra_channel_try_format(...)
{
...
struct v4l2_subdev_state *sd_state;
<...
- sd_state->try_crop
+ sd_state->pads->try_crop
...>
}
// End of tegra-video specific
// </smpl>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2021-06-10 17:55:58 +03:00
sel - > r = * v4l2_subdev_get_try_crop ( sd , sd_state , sel - > pad ) ;
2012-04-27 05:29:05 -03:00
return 0 ;
}
mutex_lock ( & fimc - > lock ) ;
2012-05-18 09:31:18 -03:00
if ( sel - > target = = V4L2_SEL_TGT_CROP ) {
2012-04-27 05:29:05 -03:00
sel - > r = f - > rect ;
} else {
sel - > r . left = 0 ;
sel - > r . top = 0 ;
sel - > r . width = f - > f_width ;
sel - > r . height = f - > f_height ;
}
mutex_unlock ( & fimc - > lock ) ;
2012-12-07 16:40:08 -03:00
v4l2_dbg ( 1 , debug , sd , " %s: (%d,%d) %dx%d, f_w: %d, f_h: %d \n " ,
2012-04-27 05:29:05 -03:00
__func__ , f - > rect . left , f - > rect . top , f - > rect . width ,
f - > rect . height , f - > f_width , f - > f_height ) ;
return 0 ;
}
static int fimc_lite_subdev_set_selection ( struct v4l2_subdev * sd ,
media: v4l2-subdev: add subdev-wide state struct
We have 'struct v4l2_subdev_pad_config' which contains configuration for
a single pad used for the TRY functionality, and an array of those
structs is passed to various v4l2_subdev_pad_ops.
I was working on subdev internal routing between pads, and realized that
there's no way to add TRY functionality for routes, which is not pad
specific configuration. Adding a separate struct for try-route config
wouldn't work either, as e.g. set-fmt needs to know the try-route
configuration to propagate the settings.
This patch adds a new struct, 'struct v4l2_subdev_state' (which at the
moment only contains the v4l2_subdev_pad_config array) and the new
struct is used in most of the places where v4l2_subdev_pad_config was
used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config
are changed to instead take v4l2_subdev_state.
The changes to drivers/media/v4l2-core/v4l2-subdev.c and
include/media/v4l2-subdev.h were written by hand, and all the driver
changes were done with the semantic patch below. The spatch needs to be
applied to a select list of directories. I used the following shell
commands to apply the spatch:
dirs="drivers/media/i2c drivers/media/platform drivers/media/usb drivers/media/test-drivers/vimc drivers/media/pci drivers/staging/media"
for dir in $dirs; do spatch -j8 --dir --include-headers --no-show-diff --in-place --sp-file v4l2-subdev-state.cocci $dir; done
Note that Coccinelle chokes on a few drivers (gcc extensions?). With
minor changes we can make Coccinelle run fine, and these changes can be
reverted after spatch. The diff for these changes is:
For drivers/media/i2c/s5k5baf.c:
@@ -1481,7 +1481,7 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
&s5k5baf_cis_rect,
v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
- v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
+ v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT),
};
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
For drivers/media/platform/s3c-camif/camif-capture.c:
@@ -1230,7 +1230,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
*mf = camif->mbus_fmt;
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* crop rectangle at camera interface input */
mf->width = camif->camif_crop.width;
mf->height = camif->camif_crop.height;
@@ -1332,7 +1332,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
}
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* Pixel format can be only changed on the sink pad. */
mf->code = camif->mbus_fmt.code;
mf->width = crop->width;
The semantic patch is:
// <smpl>
// Change function parameter
@@
identifier func;
identifier cfg;
@@
func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...)
{
<...
- cfg
+ sd_state
...>
}
// Change function declaration parameter
@@
identifier func;
identifier cfg;
type T;
@@
T func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...);
// Change function return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...)
{
...
}
// Change function declaration return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...);
// Some drivers pass a local pad_cfg for a single pad to a called function. Wrap it
// inside a pad_state.
@@
identifier func;
identifier pad_cfg;
@@
func(...)
{
...
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = { .pads = &pad_cfg };
<+...
(
v4l2_subdev_call
|
sensor_call
|
isi_try_fse
|
isc_try_fse
|
saa_call_all
)
(...,
- &pad_cfg
+ &pad_state
,...)
...+>
}
// If the function uses fields from pad_config, access via state->pads
@@
identifier func;
identifier state;
@@
func(...,
struct v4l2_subdev_state *state
, ...)
{
<...
(
- state->try_fmt
+ state->pads->try_fmt
|
- state->try_crop
+ state->pads->try_crop
|
- state->try_compose
+ state->pads->try_compose
)
...>
}
// If the function accesses the filehandle, use fh->state instead
@@
struct v4l2_subdev_fh *fh;
@@
- fh->pad
+ fh->state
@@
struct v4l2_subdev_fh fh;
@@
- fh.pad
+ fh.state
// Start of vsp1 specific
@@
@@
struct vsp1_entity {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
};
@@
symbol entity;
@@
vsp1_entity_init(...)
{
...
entity->config =
- v4l2_subdev_alloc_pad_config
+ v4l2_subdev_alloc_state
(&entity->subdev);
...
}
@@
symbol entity;
@@
vsp1_entity_destroy(...)
{
...
- v4l2_subdev_free_pad_config
+ v4l2_subdev_free_state
(entity->config);
...
}
@exists@
identifier func =~ "(^vsp1.*)|(hsit_set_format)|(sru_enum_frame_size)|(sru_set_format)|(uif_get_selection)|(uif_set_selection)|(uds_enum_frame_size)|(uds_set_format)|(brx_set_format)|(brx_get_selection)|(histo_get_selection)|(histo_set_selection)|(brx_set_selection)";
symbol config;
@@
func(...) {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
}
// End of vsp1 specific
// Start of rcar specific
@@
identifier sd;
identifier pad_cfg;
@@
rvin_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
// End of rcar specific
// Start of rockchip specific
@@
identifier func =~ "(rkisp1_rsz_get_pad_fmt)|(rkisp1_rsz_get_pad_crop)|(rkisp1_rsz_register)";
symbol rsz;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = rsz->pad_cfg };
...
- rsz->pad_cfg
+ &state
...
}
@@
identifier func =~ "(rkisp1_isp_get_pad_fmt)|(rkisp1_isp_get_pad_crop)";
symbol isp;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = isp->pad_cfg };
...
- isp->pad_cfg
+ &state
...
}
@@
symbol rkisp1;
symbol isp;
symbol pad_cfg;
@@
rkisp1_isp_register(...)
{
+ struct v4l2_subdev_state state = { .pads = rkisp1->isp.pad_cfg };
...
- rkisp1->isp.pad_cfg
+ &state
...
}
// End of rockchip specific
// Start of tegra-video specific
@@
identifier sd;
identifier pad_cfg;
@@
__tegra_channel_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
@@
identifier sd_state;
@@
__tegra_channel_try_format(...)
{
...
struct v4l2_subdev_state *sd_state;
<...
- sd_state->try_crop
+ sd_state->pads->try_crop
...>
}
// End of tegra-video specific
// </smpl>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2021-06-10 17:55:58 +03:00
struct v4l2_subdev_state * sd_state ,
2012-04-27 05:29:05 -03:00
struct v4l2_subdev_selection * sel )
{
struct fimc_lite * fimc = v4l2_get_subdevdata ( sd ) ;
struct flite_frame * f = & fimc - > inp_frame ;
int ret = 0 ;
2012-05-18 09:31:18 -03:00
if ( sel - > target ! = V4L2_SEL_TGT_CROP | | sel - > pad ! = FLITE_SD_PAD_SINK )
2012-04-27 05:29:05 -03:00
return - EINVAL ;
mutex_lock ( & fimc - > lock ) ;
fimc_lite_try_crop ( fimc , & sel - > r ) ;
if ( sel - > which = = V4L2_SUBDEV_FORMAT_TRY ) {
media: v4l2-subdev: add subdev-wide state struct
We have 'struct v4l2_subdev_pad_config' which contains configuration for
a single pad used for the TRY functionality, and an array of those
structs is passed to various v4l2_subdev_pad_ops.
I was working on subdev internal routing between pads, and realized that
there's no way to add TRY functionality for routes, which is not pad
specific configuration. Adding a separate struct for try-route config
wouldn't work either, as e.g. set-fmt needs to know the try-route
configuration to propagate the settings.
This patch adds a new struct, 'struct v4l2_subdev_state' (which at the
moment only contains the v4l2_subdev_pad_config array) and the new
struct is used in most of the places where v4l2_subdev_pad_config was
used. All v4l2_subdev_pad_ops functions taking v4l2_subdev_pad_config
are changed to instead take v4l2_subdev_state.
The changes to drivers/media/v4l2-core/v4l2-subdev.c and
include/media/v4l2-subdev.h were written by hand, and all the driver
changes were done with the semantic patch below. The spatch needs to be
applied to a select list of directories. I used the following shell
commands to apply the spatch:
dirs="drivers/media/i2c drivers/media/platform drivers/media/usb drivers/media/test-drivers/vimc drivers/media/pci drivers/staging/media"
for dir in $dirs; do spatch -j8 --dir --include-headers --no-show-diff --in-place --sp-file v4l2-subdev-state.cocci $dir; done
Note that Coccinelle chokes on a few drivers (gcc extensions?). With
minor changes we can make Coccinelle run fine, and these changes can be
reverted after spatch. The diff for these changes is:
For drivers/media/i2c/s5k5baf.c:
@@ -1481,7 +1481,7 @@ static int s5k5baf_set_selection(struct v4l2_subdev *sd,
&s5k5baf_cis_rect,
v4l2_subdev_get_try_crop(sd, cfg, PAD_CIS),
v4l2_subdev_get_try_compose(sd, cfg, PAD_CIS),
- v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT)
+ v4l2_subdev_get_try_crop(sd, cfg, PAD_OUT),
};
s5k5baf_set_rect_and_adjust(rects, rtype, &sel->r);
return 0;
For drivers/media/platform/s3c-camif/camif-capture.c:
@@ -1230,7 +1230,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
*mf = camif->mbus_fmt;
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* crop rectangle at camera interface input */
mf->width = camif->camif_crop.width;
mf->height = camif->camif_crop.height;
@@ -1332,7 +1332,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
}
break;
- case CAMIF_SD_PAD_SOURCE_C...CAMIF_SD_PAD_SOURCE_P:
+ case CAMIF_SD_PAD_SOURCE_C:
/* Pixel format can be only changed on the sink pad. */
mf->code = camif->mbus_fmt.code;
mf->width = crop->width;
The semantic patch is:
// <smpl>
// Change function parameter
@@
identifier func;
identifier cfg;
@@
func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...)
{
<...
- cfg
+ sd_state
...>
}
// Change function declaration parameter
@@
identifier func;
identifier cfg;
type T;
@@
T func(...,
- struct v4l2_subdev_pad_config *cfg
+ struct v4l2_subdev_state *sd_state
, ...);
// Change function return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...)
{
...
}
// Change function declaration return value
@@
identifier func;
@@
- struct v4l2_subdev_pad_config
+ struct v4l2_subdev_state
*func(...);
// Some drivers pass a local pad_cfg for a single pad to a called function. Wrap it
// inside a pad_state.
@@
identifier func;
identifier pad_cfg;
@@
func(...)
{
...
struct v4l2_subdev_pad_config pad_cfg;
+ struct v4l2_subdev_state pad_state = { .pads = &pad_cfg };
<+...
(
v4l2_subdev_call
|
sensor_call
|
isi_try_fse
|
isc_try_fse
|
saa_call_all
)
(...,
- &pad_cfg
+ &pad_state
,...)
...+>
}
// If the function uses fields from pad_config, access via state->pads
@@
identifier func;
identifier state;
@@
func(...,
struct v4l2_subdev_state *state
, ...)
{
<...
(
- state->try_fmt
+ state->pads->try_fmt
|
- state->try_crop
+ state->pads->try_crop
|
- state->try_compose
+ state->pads->try_compose
)
...>
}
// If the function accesses the filehandle, use fh->state instead
@@
struct v4l2_subdev_fh *fh;
@@
- fh->pad
+ fh->state
@@
struct v4l2_subdev_fh fh;
@@
- fh.pad
+ fh.state
// Start of vsp1 specific
@@
@@
struct vsp1_entity {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
};
@@
symbol entity;
@@
vsp1_entity_init(...)
{
...
entity->config =
- v4l2_subdev_alloc_pad_config
+ v4l2_subdev_alloc_state
(&entity->subdev);
...
}
@@
symbol entity;
@@
vsp1_entity_destroy(...)
{
...
- v4l2_subdev_free_pad_config
+ v4l2_subdev_free_state
(entity->config);
...
}
@exists@
identifier func =~ "(^vsp1.*)|(hsit_set_format)|(sru_enum_frame_size)|(sru_set_format)|(uif_get_selection)|(uif_set_selection)|(uds_enum_frame_size)|(uds_set_format)|(brx_set_format)|(brx_get_selection)|(histo_get_selection)|(histo_set_selection)|(brx_set_selection)";
symbol config;
@@
func(...) {
...
- struct v4l2_subdev_pad_config *config;
+ struct v4l2_subdev_state *config;
...
}
// End of vsp1 specific
// Start of rcar specific
@@
identifier sd;
identifier pad_cfg;
@@
rvin_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
// End of rcar specific
// Start of rockchip specific
@@
identifier func =~ "(rkisp1_rsz_get_pad_fmt)|(rkisp1_rsz_get_pad_crop)|(rkisp1_rsz_register)";
symbol rsz;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = rsz->pad_cfg };
...
- rsz->pad_cfg
+ &state
...
}
@@
identifier func =~ "(rkisp1_isp_get_pad_fmt)|(rkisp1_isp_get_pad_crop)";
symbol isp;
symbol pad_cfg;
@@
func(...)
{
+ struct v4l2_subdev_state state = { .pads = isp->pad_cfg };
...
- isp->pad_cfg
+ &state
...
}
@@
symbol rkisp1;
symbol isp;
symbol pad_cfg;
@@
rkisp1_isp_register(...)
{
+ struct v4l2_subdev_state state = { .pads = rkisp1->isp.pad_cfg };
...
- rkisp1->isp.pad_cfg
+ &state
...
}
// End of rockchip specific
// Start of tegra-video specific
@@
identifier sd;
identifier pad_cfg;
@@
__tegra_channel_try_format(...)
{
...
- struct v4l2_subdev_pad_config *pad_cfg;
+ struct v4l2_subdev_state *sd_state;
...
- pad_cfg = v4l2_subdev_alloc_pad_config(sd);
+ sd_state = v4l2_subdev_alloc_state(sd);
<...
- pad_cfg
+ sd_state
...>
- v4l2_subdev_free_pad_config(pad_cfg);
+ v4l2_subdev_free_state(sd_state);
...
}
@@
identifier sd_state;
@@
__tegra_channel_try_format(...)
{
...
struct v4l2_subdev_state *sd_state;
<...
- sd_state->try_crop
+ sd_state->pads->try_crop
...>
}
// End of tegra-video specific
// </smpl>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
2021-06-10 17:55:58 +03:00
* v4l2_subdev_get_try_crop ( sd , sd_state , sel - > pad ) = sel - > r ;
2012-04-27 05:29:05 -03:00
} else {
unsigned long flags ;
spin_lock_irqsave ( & fimc - > slock , flags ) ;
f - > rect = sel - > r ;
/* Same crop rectangle on the source pad */
fimc - > out_frame . rect = sel - > r ;
set_bit ( ST_FLITE_CONFIG , & fimc - > state ) ;
spin_unlock_irqrestore ( & fimc - > slock , flags ) ;
}
mutex_unlock ( & fimc - > lock ) ;
2012-12-07 16:40:08 -03:00
v4l2_dbg ( 1 , debug , sd , " %s: (%d,%d) %dx%d, f_w: %d, f_h: %d \n " ,
2012-04-27 05:29:05 -03:00
__func__ , f - > rect . left , f - > rect . top , f - > rect . width ,
f - > rect . height , f - > f_width , f - > f_height ) ;
return ret ;
}
static int fimc_lite_subdev_s_stream ( struct v4l2_subdev * sd , int on )
{
struct fimc_lite * fimc = v4l2_get_subdevdata ( sd ) ;
2012-11-28 15:41:01 -03:00
unsigned long flags ;
int ret ;
2012-04-27 05:29:05 -03:00
2012-11-28 15:41:01 -03:00
/*
* Find sensor subdev linked to FIMC - LITE directly or through
* MIPI - CSIS . This is required for configuration where FIMC - LITE
* is used as a subdev only and feeds data internally to FIMC - IS .
* The pipeline links are protected through entity . stream_count
* so there is no need to take the media graph mutex here .
*/
2013-06-10 08:51:44 -03:00
fimc - > sensor = fimc_find_remote_sensor ( & sd - > entity ) ;
2012-11-28 15:41:01 -03:00
2013-01-18 12:02:32 -03:00
if ( atomic_read ( & fimc - > out_path ) ! = FIMC_IO_ISP )
2012-04-27 05:29:05 -03:00
return - ENOIOCTLCMD ;
2013-01-18 12:02:32 -03:00
mutex_lock ( & fimc - > lock ) ;
2012-11-28 15:41:01 -03:00
if ( on ) {
flite_hw_reset ( fimc ) ;
ret = fimc_lite_hw_init ( fimc , true ) ;
if ( ! ret ) {
spin_lock_irqsave ( & fimc - > slock , flags ) ;
flite_hw_capture_start ( fimc ) ;
spin_unlock_irqrestore ( & fimc - > slock , flags ) ;
}
} else {
set_bit ( ST_FLITE_OFF , & fimc - > state ) ;
2012-04-27 05:29:05 -03:00
2012-11-28 15:41:01 -03:00
spin_lock_irqsave ( & fimc - > slock , flags ) ;
flite_hw_capture_stop ( fimc ) ;
spin_unlock_irqrestore ( & fimc - > slock , flags ) ;
ret = wait_event_timeout ( fimc - > irq_queue ,
! test_bit ( ST_FLITE_OFF , & fimc - > state ) ,
msecs_to_jiffies ( 200 ) ) ;
if ( ret = = 0 )
v4l2_err ( sd , " s_stream(0) timeout \n " ) ;
clear_bit ( ST_FLITE_RUN , & fimc - > state ) ;
}
mutex_unlock ( & fimc - > lock ) ;
return ret ;
2012-04-27 05:29:05 -03:00
}
static int fimc_lite_log_status ( struct v4l2_subdev * sd )
{
struct fimc_lite * fimc = v4l2_get_subdevdata ( sd ) ;
flite_hw_dump_regs ( fimc , __func__ ) ;
return 0 ;
}
static int fimc_lite_subdev_registered ( struct v4l2_subdev * sd )
{
struct fimc_lite * fimc = v4l2_get_subdevdata ( sd ) ;
struct vb2_queue * q = & fimc - > vb_queue ;
2013-05-31 11:37:18 -03:00
struct video_device * vfd = & fimc - > ve . vdev ;
2012-04-27 05:29:05 -03:00
int ret ;
2012-07-26 07:13:08 -03:00
memset ( vfd , 0 , sizeof ( * vfd ) ) ;
2013-01-18 12:02:32 -03:00
atomic_set ( & fimc - > out_path , FIMC_IO_DMA ) ;
2012-04-27 05:29:05 -03:00
snprintf ( vfd - > name , sizeof ( vfd - > name ) , " fimc-lite.%d.capture " ,
fimc - > index ) ;
vfd - > fops = & fimc_lite_fops ;
vfd - > ioctl_ops = & fimc_lite_ioctl_ops ;
vfd - > v4l2_dev = sd - > v4l2_dev ;
vfd - > minor = - 1 ;
2012-07-26 07:13:08 -03:00
vfd - > release = video_device_release_empty ;
2013-03-25 16:43:08 -03:00
vfd - > queue = q ;
2019-06-04 03:06:24 -04:00
vfd - > device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_STREAMING ;
2012-04-27 05:29:05 -03:00
fimc - > reqbufs_count = 0 ;
INIT_LIST_HEAD ( & fimc - > pending_buf_q ) ;
INIT_LIST_HEAD ( & fimc - > active_buf_q ) ;
memset ( q , 0 , sizeof ( * q ) ) ;
q - > type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ;
q - > io_modes = VB2_MMAP | VB2_USERPTR ;
q - > ops = & fimc_lite_qops ;
q - > mem_ops = & vb2_dma_contig_memops ;
q - > buf_struct_size = sizeof ( struct flite_buffer ) ;
q - > drv_priv = fimc ;
2014-02-25 19:12:19 -03:00
q - > timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC ;
2013-03-25 16:43:08 -03:00
q - > lock = & fimc - > lock ;
2016-02-16 07:30:19 -02:00
q - > dev = & fimc - > pdev - > dev ;
2012-04-27 05:29:05 -03:00
2012-10-19 08:24:18 -03:00
ret = vb2_queue_init ( q ) ;
if ( ret < 0 )
return ret ;
2012-04-27 05:29:05 -03:00
fimc - > vd_pad . flags = MEDIA_PAD_FL_SINK ;
2015-12-11 07:44:40 -02:00
ret = media_entity_pads_init ( & vfd - > entity , 1 , & fimc - > vd_pad ) ;
2012-07-26 07:13:08 -03:00
if ( ret < 0 )
return ret ;
2012-04-27 05:29:05 -03:00
video_set_drvdata ( vfd , fimc ) ;
2013-05-31 11:37:22 -03:00
fimc - > ve . pipe = v4l2_get_subdev_hostdata ( sd ) ;
2012-04-27 05:29:05 -03:00
2020-02-03 12:41:18 +01:00
ret = video_register_device ( vfd , VFL_TYPE_VIDEO , - 1 ) ;
2012-07-26 07:13:08 -03:00
if ( ret < 0 ) {
media_entity_cleanup ( & vfd - > entity ) ;
2013-05-31 11:37:22 -03:00
fimc - > ve . pipe = NULL ;
2012-07-26 07:13:08 -03:00
return ret ;
}
2012-04-27 05:29:05 -03:00
v4l2_info ( sd - > v4l2_dev , " Registered %s as /dev/%s \n " ,
vfd - > name , video_device_node_name ( vfd ) ) ;
return 0 ;
}
static void fimc_lite_subdev_unregistered ( struct v4l2_subdev * sd )
{
struct fimc_lite * fimc = v4l2_get_subdevdata ( sd ) ;
if ( fimc = = NULL )
return ;
2013-05-31 11:37:25 -03:00
mutex_lock ( & fimc - > lock ) ;
2013-05-31 11:37:18 -03:00
if ( video_is_registered ( & fimc - > ve . vdev ) ) {
video_unregister_device ( & fimc - > ve . vdev ) ;
media_entity_cleanup ( & fimc - > ve . vdev . entity ) ;
2013-05-31 11:37:22 -03:00
fimc - > ve . pipe = NULL ;
2012-04-27 05:29:05 -03:00
}
2013-05-31 11:37:25 -03:00
mutex_unlock ( & fimc - > lock ) ;
2012-04-27 05:29:05 -03:00
}
static const struct v4l2_subdev_internal_ops fimc_lite_subdev_internal_ops = {
. registered = fimc_lite_subdev_registered ,
. unregistered = fimc_lite_subdev_unregistered ,
} ;
static const struct v4l2_subdev_pad_ops fimc_lite_subdev_pad_ops = {
. enum_mbus_code = fimc_lite_subdev_enum_mbus_code ,
. get_selection = fimc_lite_subdev_get_selection ,
. set_selection = fimc_lite_subdev_set_selection ,
. get_fmt = fimc_lite_subdev_get_fmt ,
. set_fmt = fimc_lite_subdev_set_fmt ,
} ;
static const struct v4l2_subdev_video_ops fimc_lite_subdev_video_ops = {
. s_stream = fimc_lite_subdev_s_stream ,
} ;
static const struct v4l2_subdev_core_ops fimc_lite_core_ops = {
. log_status = fimc_lite_log_status ,
} ;
2017-08-08 06:58:31 -04:00
static const struct v4l2_subdev_ops fimc_lite_subdev_ops = {
2012-04-27 05:29:05 -03:00
. core = & fimc_lite_core_ops ,
. video = & fimc_lite_subdev_video_ops ,
. pad = & fimc_lite_subdev_pad_ops ,
} ;
static int fimc_lite_s_ctrl ( struct v4l2_ctrl * ctrl )
{
struct fimc_lite * fimc = container_of ( ctrl - > handler , struct fimc_lite ,
ctrl_handler ) ;
set_bit ( ST_FLITE_CONFIG , & fimc - > state ) ;
return 0 ;
}
static const struct v4l2_ctrl_ops fimc_lite_ctrl_ops = {
. s_ctrl = fimc_lite_s_ctrl ,
} ;
static const struct v4l2_ctrl_config fimc_lite_ctrl = {
. ops = & fimc_lite_ctrl_ops ,
. id = V4L2_CTRL_CLASS_USER | 0x1001 ,
. type = V4L2_CTRL_TYPE_BOOLEAN ,
. name = " Test Pattern 640x480 " ,
2013-02-21 07:54:18 -03:00
. step = 1 ,
2012-04-27 05:29:05 -03:00
} ;
2013-06-18 08:00:42 -03:00
static void fimc_lite_set_default_config ( struct fimc_lite * fimc )
{
struct flite_frame * sink = & fimc - > inp_frame ;
struct flite_frame * source = & fimc - > out_frame ;
sink - > fmt = & fimc_lite_formats [ 0 ] ;
sink - > f_width = FLITE_DEFAULT_WIDTH ;
sink - > f_height = FLITE_DEFAULT_HEIGHT ;
sink - > rect . width = FLITE_DEFAULT_WIDTH ;
sink - > rect . height = FLITE_DEFAULT_HEIGHT ;
sink - > rect . left = 0 ;
sink - > rect . top = 0 ;
* source = * sink ;
}
2012-04-27 05:29:05 -03:00
static int fimc_lite_create_capture_subdev ( struct fimc_lite * fimc )
{
struct v4l2_ctrl_handler * handler = & fimc - > ctrl_handler ;
struct v4l2_subdev * sd = & fimc - > subdev ;
int ret ;
v4l2_subdev_init ( sd , & fimc_lite_subdev_ops ) ;
2013-04-18 08:49:54 -03:00
sd - > flags | = V4L2_SUBDEV_FL_HAS_DEVNODE ;
2012-04-27 05:29:05 -03:00
snprintf ( sd - > name , sizeof ( sd - > name ) , " FIMC-LITE.%d " , fimc - > index ) ;
2012-11-28 15:41:01 -03:00
fimc - > subdev_pads [ FLITE_SD_PAD_SINK ] . flags = MEDIA_PAD_FL_SINK ;
fimc - > subdev_pads [ FLITE_SD_PAD_SOURCE_DMA ] . flags = MEDIA_PAD_FL_SOURCE ;
fimc - > subdev_pads [ FLITE_SD_PAD_SOURCE_ISP ] . flags = MEDIA_PAD_FL_SOURCE ;
2015-12-11 07:44:40 -02:00
ret = media_entity_pads_init ( & sd - > entity , FLITE_SD_PADS_NUM ,
2015-08-06 09:25:57 -03:00
fimc - > subdev_pads ) ;
2012-04-27 05:29:05 -03:00
if ( ret )
return ret ;
v4l2_ctrl_handler_init ( handler , 1 ) ;
fimc - > test_pattern = v4l2_ctrl_new_custom ( handler , & fimc_lite_ctrl ,
NULL ) ;
if ( handler - > error ) {
media_entity_cleanup ( & sd - > entity ) ;
return handler - > error ;
}
sd - > ctrl_handler = handler ;
sd - > internal_ops = & fimc_lite_subdev_internal_ops ;
2016-09-01 08:47:05 -03:00
sd - > entity . function = MEDIA_ENT_F_PROC_VIDEO_SCALER ;
2012-04-27 05:29:05 -03:00
sd - > entity . ops = & fimc_lite_subdev_media_ops ;
2013-04-18 13:40:42 -03:00
sd - > owner = THIS_MODULE ;
2012-04-27 05:29:05 -03:00
v4l2_set_subdevdata ( sd , fimc ) ;
return 0 ;
}
static void fimc_lite_unregister_capture_subdev ( struct fimc_lite * fimc )
{
struct v4l2_subdev * sd = & fimc - > subdev ;
v4l2_device_unregister_subdev ( sd ) ;
media_entity_cleanup ( & sd - > entity ) ;
v4l2_ctrl_handler_free ( & fimc - > ctrl_handler ) ;
v4l2_set_subdevdata ( sd , NULL ) ;
}
static void fimc_lite_clk_put ( struct fimc_lite * fimc )
{
2013-04-30 00:51:33 -03:00
if ( IS_ERR ( fimc - > clock ) )
2012-04-27 05:29:05 -03:00
return ;
clk_put ( fimc - > clock ) ;
2013-04-30 00:51:33 -03:00
fimc - > clock = ERR_PTR ( - EINVAL ) ;
2012-04-27 05:29:05 -03:00
}
static int fimc_lite_clk_get ( struct fimc_lite * fimc )
{
fimc - > clock = clk_get ( & fimc - > pdev - > dev , FLITE_CLK_NAME ) ;
2017-11-29 11:20:16 -05:00
return PTR_ERR_OR_ZERO ( fimc - > clock ) ;
2012-04-27 05:29:05 -03:00
}
2013-03-26 09:33:54 -03:00
static const struct of_device_id flite_of_match [ ] ;
2012-12-21 13:17:53 -08:00
static int fimc_lite_probe ( struct platform_device * pdev )
2012-04-27 05:29:05 -03:00
{
2013-03-26 09:33:54 -03:00
struct flite_drvdata * drv_data = NULL ;
struct device * dev = & pdev - > dev ;
const struct of_device_id * of_id ;
2012-04-27 05:29:05 -03:00
struct fimc_lite * fimc ;
struct resource * res ;
int ret ;
2013-08-02 04:58:25 -03:00
if ( ! dev - > of_node )
return - ENODEV ;
2013-03-26 09:33:54 -03:00
fimc = devm_kzalloc ( dev , sizeof ( * fimc ) , GFP_KERNEL ) ;
2012-04-27 05:29:05 -03:00
if ( ! fimc )
return - ENOMEM ;
2013-08-02 04:58:25 -03:00
of_id = of_match_node ( flite_of_match , dev - > of_node ) ;
if ( of_id )
drv_data = ( struct flite_drvdata * ) of_id - > data ;
fimc - > index = of_alias_get_id ( dev - > of_node , " fimc-lite " ) ;
2013-03-26 09:33:54 -03:00
2013-06-14 12:38:15 -03:00
if ( ! drv_data | | fimc - > index > = drv_data - > num_instances | |
fimc - > index < 0 ) {
2017-07-21 15:28:33 -04:00
dev_err ( dev , " Wrong %pOF node alias \n " , dev - > of_node ) ;
2013-03-26 09:33:54 -03:00
return - EINVAL ;
2013-06-14 12:38:15 -03:00
}
2013-03-26 09:33:54 -03:00
2013-03-16 17:35:10 -03:00
fimc - > dd = drv_data ;
2012-04-27 05:29:05 -03:00
fimc - > pdev = pdev ;
init_waitqueue_head ( & fimc - > irq_queue ) ;
spin_lock_init ( & fimc - > slock ) ;
mutex_init ( & fimc - > lock ) ;
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
2013-03-26 09:33:54 -03:00
fimc - > regs = devm_ioremap_resource ( dev , res ) ;
2013-01-21 06:09:07 -03:00
if ( IS_ERR ( fimc - > regs ) )
return PTR_ERR ( fimc - > regs ) ;
2012-04-27 05:29:05 -03:00
res = platform_get_resource ( pdev , IORESOURCE_IRQ , 0 ) ;
if ( res = = NULL ) {
2013-03-26 09:33:54 -03:00
dev_err ( dev , " Failed to get IRQ resource \n " ) ;
2012-04-27 05:29:05 -03:00
return - ENXIO ;
}
ret = fimc_lite_clk_get ( fimc ) ;
if ( ret )
return ret ;
2013-03-26 09:33:54 -03:00
ret = devm_request_irq ( dev , res - > start , flite_irq_handler ,
0 , dev_name ( dev ) , fimc ) ;
2012-04-27 05:29:05 -03:00
if ( ret ) {
2013-03-26 09:33:54 -03:00
dev_err ( dev , " Failed to install irq (%d) \n " , ret ) ;
2013-10-19 18:28:38 -03:00
goto err_clk_put ;
2012-04-27 05:29:05 -03:00
}
/* The video node will be created within the subdev's registered() op */
ret = fimc_lite_create_capture_subdev ( fimc ) ;
if ( ret )
2013-10-19 18:28:38 -03:00
goto err_clk_put ;
2012-04-27 05:29:05 -03:00
platform_set_drvdata ( pdev , fimc ) ;
2013-03-26 09:33:54 -03:00
pm_runtime_enable ( dev ) ;
2013-10-19 18:28:38 -03:00
if ( ! pm_runtime_enabled ( dev ) ) {
2016-08-31 10:25:17 -03:00
ret = clk_prepare_enable ( fimc - > clock ) ;
2013-10-19 18:28:38 -03:00
if ( ret < 0 )
2014-01-07 19:07:52 -03:00
goto err_sd ;
2013-10-19 18:28:38 -03:00
}
2012-04-27 05:29:05 -03:00
2016-05-24 09:16:07 +02:00
vb2_dma_contig_set_max_seg_size ( dev , DMA_BIT_MASK ( 32 ) ) ;
2013-06-18 08:00:42 -03:00
fimc_lite_set_default_config ( fimc ) ;
2013-03-26 09:33:54 -03:00
dev_dbg ( dev , " FIMC-LITE.%d registered successfully \n " ,
2012-04-27 05:29:05 -03:00
fimc - > index ) ;
return 0 ;
2013-10-19 18:28:38 -03:00
2012-04-27 05:29:05 -03:00
err_sd :
fimc_lite_unregister_capture_subdev ( fimc ) ;
2013-10-19 18:28:38 -03:00
err_clk_put :
2012-04-27 05:29:05 -03:00
fimc_lite_clk_put ( fimc ) ;
return ret ;
}
2014-12-04 01:10:10 +01:00
# ifdef CONFIG_PM
2012-04-27 05:29:05 -03:00
static int fimc_lite_runtime_resume ( struct device * dev )
{
struct fimc_lite * fimc = dev_get_drvdata ( dev ) ;
2016-08-31 10:25:17 -03:00
clk_prepare_enable ( fimc - > clock ) ;
2012-04-27 05:29:05 -03:00
return 0 ;
}
static int fimc_lite_runtime_suspend ( struct device * dev )
{
struct fimc_lite * fimc = dev_get_drvdata ( dev ) ;
2016-08-31 10:25:17 -03:00
clk_disable_unprepare ( fimc - > clock ) ;
2012-04-27 05:29:05 -03:00
return 0 ;
}
2014-01-16 11:49:28 -03:00
# endif
2012-04-27 05:29:05 -03:00
# ifdef CONFIG_PM_SLEEP
static int fimc_lite_resume ( struct device * dev )
{
struct fimc_lite * fimc = dev_get_drvdata ( dev ) ;
struct flite_buffer * buf ;
unsigned long flags ;
int i ;
spin_lock_irqsave ( & fimc - > slock , flags ) ;
if ( ! test_and_clear_bit ( ST_LPM , & fimc - > state ) | |
! test_bit ( ST_FLITE_IN_USE , & fimc - > state ) ) {
spin_unlock_irqrestore ( & fimc - > slock , flags ) ;
return 0 ;
}
flite_hw_reset ( fimc ) ;
spin_unlock_irqrestore ( & fimc - > slock , flags ) ;
if ( ! test_and_clear_bit ( ST_FLITE_SUSPENDED , & fimc - > state ) )
return 0 ;
INIT_LIST_HEAD ( & fimc - > active_buf_q ) ;
2013-05-31 11:37:22 -03:00
fimc_pipeline_call ( & fimc - > ve , open ,
2013-05-31 11:37:18 -03:00
& fimc - > ve . vdev . entity , false ) ;
2013-01-18 12:02:32 -03:00
fimc_lite_hw_init ( fimc , atomic_read ( & fimc - > out_path ) = = FIMC_IO_ISP ) ;
2012-04-27 05:29:05 -03:00
clear_bit ( ST_FLITE_SUSPENDED , & fimc - > state ) ;
for ( i = 0 ; i < fimc - > reqbufs_count ; i + + ) {
if ( list_empty ( & fimc - > pending_buf_q ) )
break ;
buf = fimc_lite_pending_queue_pop ( fimc ) ;
[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
buffer_queue ( & buf - > vb . vb2_buf ) ;
2012-04-27 05:29:05 -03:00
}
return 0 ;
}
static int fimc_lite_suspend ( struct device * dev )
{
struct fimc_lite * fimc = dev_get_drvdata ( dev ) ;
bool suspend = test_bit ( ST_FLITE_IN_USE , & fimc - > state ) ;
int ret ;
if ( test_and_set_bit ( ST_LPM , & fimc - > state ) )
return 0 ;
ret = fimc_lite_stop_capture ( fimc , suspend ) ;
2012-05-18 13:31:28 -03:00
if ( ret < 0 | | ! fimc_lite_active ( fimc ) )
2012-04-27 05:29:05 -03:00
return ret ;
2013-05-31 11:37:22 -03:00
return fimc_pipeline_call ( & fimc - > ve , close ) ;
2012-04-27 05:29:05 -03:00
}
# endif /* CONFIG_PM_SLEEP */
2012-12-21 13:17:53 -08:00
static int fimc_lite_remove ( struct platform_device * pdev )
2012-04-27 05:29:05 -03:00
{
struct fimc_lite * fimc = platform_get_drvdata ( pdev ) ;
struct device * dev = & pdev - > dev ;
2019-12-19 08:48:24 +01:00
if ( ! pm_runtime_enabled ( dev ) )
clk_disable_unprepare ( fimc - > clock ) ;
2012-04-27 05:29:05 -03:00
pm_runtime_disable ( dev ) ;
pm_runtime_set_suspended ( dev ) ;
fimc_lite_unregister_capture_subdev ( fimc ) ;
2016-05-24 09:16:07 +02:00
vb2_dma_contig_clear_max_seg_size ( dev ) ;
2012-04-27 05:29:05 -03:00
fimc_lite_clk_put ( fimc ) ;
dev_info ( dev , " Driver unloaded \n " ) ;
return 0 ;
}
2013-03-26 09:33:54 -03:00
static const struct dev_pm_ops fimc_lite_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS ( fimc_lite_suspend , fimc_lite_resume )
SET_RUNTIME_PM_OPS ( fimc_lite_runtime_suspend , fimc_lite_runtime_resume ,
NULL )
} ;
2017-10-04 02:38:25 -04:00
/* EXYNOS4412 */
2013-03-16 17:35:10 -03:00
static struct flite_drvdata fimc_lite_drvdata_exynos4 = {
2012-04-27 05:29:05 -03:00
. max_width = 8192 ,
. max_height = 8192 ,
. out_width_align = 8 ,
. win_hor_offs_align = 2 ,
. out_hor_offs_align = 8 ,
2013-06-14 12:38:15 -03:00
. max_dma_bufs = 1 ,
. num_instances = 2 ,
} ;
/* EXYNOS5250 */
static struct flite_drvdata fimc_lite_drvdata_exynos5 = {
. max_width = 8192 ,
. max_height = 8192 ,
. out_width_align = 8 ,
. win_hor_offs_align = 2 ,
. out_hor_offs_align = 8 ,
. max_dma_bufs = 32 ,
. num_instances = 3 ,
2012-04-27 05:29:05 -03:00
} ;
2013-03-26 09:33:54 -03:00
static const struct of_device_id flite_of_match [ ] = {
{
. compatible = " samsung,exynos4212-fimc-lite " ,
. data = & fimc_lite_drvdata_exynos4 ,
} ,
2013-06-14 12:38:15 -03:00
{
. compatible = " samsung,exynos5250-fimc-lite " ,
. data = & fimc_lite_drvdata_exynos5 ,
} ,
2013-03-26 09:33:54 -03:00
{ /* sentinel */ } ,
2012-04-27 05:29:05 -03:00
} ;
2013-03-26 09:33:54 -03:00
MODULE_DEVICE_TABLE ( of , flite_of_match ) ;
2012-04-27 05:29:05 -03:00
static struct platform_driver fimc_lite_driver = {
. probe = fimc_lite_probe ,
2012-12-21 13:17:53 -08:00
. remove = fimc_lite_remove ,
2012-04-27 05:29:05 -03:00
. driver = {
2013-03-26 09:33:54 -03:00
. of_match_table = flite_of_match ,
2012-04-27 05:29:05 -03:00
. name = FIMC_LITE_DRV_NAME ,
. pm = & fimc_lite_pm_ops ,
}
} ;
module_platform_driver ( fimc_lite_driver ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_ALIAS ( " platform: " FIMC_LITE_DRV_NAME ) ;