2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2010-03-29 11:45:22 +04:00
/*
* Driver for AK8813 / AK8814 TV - ecoders from Asahi Kasei Microsystems Co . , Ltd . ( AKM )
*
* Copyright ( C ) 2010 , Guennadi Liakhovetski < g . liakhovetski @ gmx . de >
*/
# include <linux/i2c.h>
# include <linux/init.h>
# include <linux/platform_device.h>
2010-05-21 01:08:23 +04:00
# include <linux/slab.h>
2010-03-29 11:45:22 +04:00
# include <linux/videodev2.h>
2011-07-03 22:03:12 +04:00
# include <linux/module.h>
2010-03-29 11:45:22 +04:00
2015-11-10 17:01:44 +03:00
# include <media/i2c/ak881x.h>
2010-03-29 11:45:22 +04:00
# include <media/v4l2-common.h>
# include <media/v4l2-device.h>
# define AK881X_INTERFACE_MODE 0
# define AK881X_VIDEO_PROCESS1 1
# define AK881X_VIDEO_PROCESS2 2
# define AK881X_VIDEO_PROCESS3 3
# define AK881X_DAC_MODE 5
# define AK881X_STATUS 0x24
# define AK881X_DEVICE_ID 0x25
# define AK881X_DEVICE_REVISION 0x26
struct ak881x {
struct v4l2_subdev subdev ;
struct ak881x_pdata * pdata ;
unsigned int lines ;
char revision ; /* DEVICE_REVISION content */
} ;
static int reg_read ( struct i2c_client * client , const u8 reg )
{
return i2c_smbus_read_byte_data ( client , reg ) ;
}
static int reg_write ( struct i2c_client * client , const u8 reg ,
const u8 data )
{
return i2c_smbus_write_byte_data ( client , reg , data ) ;
}
static int reg_set ( struct i2c_client * client , const u8 reg ,
const u8 data , u8 mask )
{
int ret = reg_read ( client , reg ) ;
if ( ret < 0 )
return ret ;
return reg_write ( client , reg , ( ret & ~ mask ) | ( data & mask ) ) ;
}
static struct ak881x * to_ak881x ( const struct i2c_client * client )
{
return container_of ( i2c_get_clientdata ( client ) , struct ak881x , subdev ) ;
}
# ifdef CONFIG_VIDEO_ADV_DEBUG
static int ak881x_g_register ( struct v4l2_subdev * sd ,
struct v4l2_dbg_register * reg )
{
struct i2c_client * client = v4l2_get_subdevdata ( sd ) ;
2013-05-29 13:59:51 +04:00
if ( reg - > reg > 0x26 )
2010-03-29 11:45:22 +04:00
return - EINVAL ;
2013-05-29 14:00:07 +04:00
reg - > size = 1 ;
2010-03-29 11:45:22 +04:00
reg - > val = reg_read ( client , reg - > reg ) ;
if ( reg - > val > 0xffff )
return - EIO ;
return 0 ;
}
static int ak881x_s_register ( struct v4l2_subdev * sd ,
2013-03-24 15:28:46 +04:00
const struct v4l2_dbg_register * reg )
2010-03-29 11:45:22 +04:00
{
struct i2c_client * client = v4l2_get_subdevdata ( sd ) ;
2013-05-29 13:59:51 +04:00
if ( reg - > reg > 0x26 )
2010-03-29 11:45:22 +04:00
return - EINVAL ;
if ( reg_write ( client , reg - > reg , reg - > val ) < 0 )
return - EIO ;
return 0 ;
}
# endif
2015-04-09 10:02:34 +03:00
static int ak881x_fill_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 ,
2015-04-09 10:02:34 +03:00
struct v4l2_subdev_format * format )
2010-03-29 11:45:22 +04:00
{
2015-04-09 10:02:34 +03:00
struct v4l2_mbus_framefmt * mf = & format - > format ;
2010-03-29 11:45:22 +04:00
struct i2c_client * client = v4l2_get_subdevdata ( sd ) ;
struct ak881x * ak881x = to_ak881x ( client ) ;
2015-04-09 10:02:34 +03:00
if ( format - > pad )
return - EINVAL ;
2010-03-29 11:45:22 +04:00
v4l_bound_align_image ( & mf - > width , 0 , 720 , 2 ,
& mf - > height , 0 , ak881x - > lines , 1 , 0 ) ;
mf - > field = V4L2_FIELD_INTERLACED ;
2014-11-10 20:28:29 +03:00
mf - > code = MEDIA_BUS_FMT_YUYV8_2X8 ;
2010-03-29 11:45:22 +04:00
mf - > colorspace = V4L2_COLORSPACE_SMPTE170M ;
return 0 ;
}
2015-04-09 10:01:33 +03:00
static int ak881x_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 ,
2015-04-09 10:01:33 +03:00
struct v4l2_subdev_mbus_code_enum * code )
2010-03-29 11:45:22 +04:00
{
2015-04-09 10:01:33 +03:00
if ( code - > pad | | code - > index )
2010-03-29 11:45:22 +04:00
return - EINVAL ;
2015-04-09 10:01:33 +03:00
code - > code = MEDIA_BUS_FMT_YUYV8_2X8 ;
2010-03-29 11:45:22 +04:00
return 0 ;
}
2015-12-14 13:25:32 +03:00
static int ak881x_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 ,
2015-12-14 13:25:32 +03:00
struct v4l2_subdev_selection * sel )
2010-03-29 11:45:22 +04:00
{
struct i2c_client * client = v4l2_get_subdevdata ( sd ) ;
struct ak881x * ak881x = to_ak881x ( client ) ;
2015-12-14 13:25:32 +03:00
if ( sel - > which ! = V4L2_SUBDEV_FORMAT_ACTIVE )
return - EINVAL ;
2010-03-29 11:45:22 +04:00
2015-12-14 13:25:32 +03:00
switch ( sel - > target ) {
case V4L2_SEL_TGT_CROP_BOUNDS :
sel - > r . left = 0 ;
sel - > r . top = 0 ;
sel - > r . width = 720 ;
sel - > r . height = ak881x - > lines ;
return 0 ;
default :
return - EINVAL ;
}
2010-03-29 11:45:22 +04:00
}
static int ak881x_s_std_output ( struct v4l2_subdev * sd , v4l2_std_id std )
{
struct i2c_client * client = v4l2_get_subdevdata ( sd ) ;
struct ak881x * ak881x = to_ak881x ( client ) ;
u8 vp1 ;
if ( std = = V4L2_STD_NTSC_443 ) {
vp1 = 3 ;
ak881x - > lines = 480 ;
} else if ( std = = V4L2_STD_PAL_M ) {
vp1 = 5 ;
ak881x - > lines = 480 ;
} else if ( std = = V4L2_STD_PAL_60 ) {
vp1 = 7 ;
ak881x - > lines = 480 ;
2015-06-15 14:33:32 +03:00
} else if ( std & V4L2_STD_NTSC ) {
2010-03-29 11:45:22 +04:00
vp1 = 0 ;
ak881x - > lines = 480 ;
2015-06-15 14:33:32 +03:00
} else if ( std & V4L2_STD_PAL ) {
vp1 = 0xf ;
ak881x - > lines = 576 ;
2010-03-29 11:45:22 +04:00
} else {
/* No SECAM or PAL_N/Nc supported */
return - EINVAL ;
}
reg_set ( client , AK881X_VIDEO_PROCESS1 , vp1 , 0xf ) ;
return 0 ;
}
static int ak881x_s_stream ( struct v4l2_subdev * sd , int enable )
{
struct i2c_client * client = v4l2_get_subdevdata ( sd ) ;
struct ak881x * ak881x = to_ak881x ( client ) ;
if ( enable ) {
u8 dac ;
/* For colour-bar testing set bit 6 of AK881X_VIDEO_PROCESS1 */
/* Default: composite output */
if ( ak881x - > pdata - > flags & AK881X_COMPONENT )
dac = 3 ;
else
dac = 4 ;
/* Turn on the DAC(s) */
reg_write ( client , AK881X_DAC_MODE , dac ) ;
dev_dbg ( & client - > dev , " chip status 0x%x \n " ,
reg_read ( client , AK881X_STATUS ) ) ;
} else {
/* ...and clear bit 6 of AK881X_VIDEO_PROCESS1 here */
reg_write ( client , AK881X_DAC_MODE , 0 ) ;
dev_dbg ( & client - > dev , " chip status 0x%x \n " ,
reg_read ( client , AK881X_STATUS ) ) ;
}
return 0 ;
}
2016-12-13 20:26:13 +03:00
static const struct v4l2_subdev_core_ops ak881x_subdev_core_ops = {
2010-03-29 11:45:22 +04:00
# ifdef CONFIG_VIDEO_ADV_DEBUG
. g_register = ak881x_g_register ,
. s_register = ak881x_s_register ,
# endif
} ;
2016-12-13 20:26:13 +03:00
static const struct v4l2_subdev_video_ops ak881x_subdev_video_ops = {
2010-03-29 11:45:22 +04:00
. s_std_output = ak881x_s_std_output ,
. s_stream = ak881x_s_stream ,
} ;
2015-04-09 10:01:33 +03:00
static const struct v4l2_subdev_pad_ops ak881x_subdev_pad_ops = {
. enum_mbus_code = ak881x_enum_mbus_code ,
2015-12-14 13:25:32 +03:00
. get_selection = ak881x_get_selection ,
2015-04-09 10:02:34 +03:00
. set_fmt = ak881x_fill_fmt ,
. get_fmt = ak881x_fill_fmt ,
2015-04-09 10:01:33 +03:00
} ;
2016-12-13 20:26:13 +03:00
static const struct v4l2_subdev_ops ak881x_subdev_ops = {
2010-03-29 11:45:22 +04:00
. core = & ak881x_subdev_core_ops ,
. video = & ak881x_subdev_video_ops ,
2015-04-09 10:01:33 +03:00
. pad = & ak881x_subdev_pad_ops ,
2010-03-29 11:45:22 +04:00
} ;
static int ak881x_probe ( struct i2c_client * client ,
const struct i2c_device_id * did )
{
2019-06-08 13:55:45 +03:00
struct i2c_adapter * adapter = client - > adapter ;
2010-03-29 11:45:22 +04:00
struct ak881x * ak881x ;
u8 ifmode , data ;
if ( ! i2c_check_functionality ( adapter , I2C_FUNC_SMBUS_BYTE_DATA ) ) {
dev_warn ( & adapter - > dev ,
" I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD \n " ) ;
return - EIO ;
}
2013-05-02 15:29:43 +04:00
ak881x = devm_kzalloc ( & client - > dev , sizeof ( * ak881x ) , GFP_KERNEL ) ;
2010-03-29 11:45:22 +04:00
if ( ! ak881x )
return - ENOMEM ;
v4l2_i2c_subdev_init ( & ak881x - > subdev , client , & ak881x_subdev_ops ) ;
data = reg_read ( client , AK881X_DEVICE_ID ) ;
switch ( data ) {
case 0x13 :
case 0x14 :
break ;
default :
dev_err ( & client - > dev ,
" No ak881x chip detected, register read %x \n " , data ) ;
return - ENODEV ;
}
ak881x - > revision = reg_read ( client , AK881X_DEVICE_REVISION ) ;
ak881x - > pdata = client - > dev . platform_data ;
if ( ak881x - > pdata ) {
if ( ak881x - > pdata - > flags & AK881X_FIELD )
ifmode = 4 ;
else
ifmode = 0 ;
switch ( ak881x - > pdata - > flags & AK881X_IF_MODE_MASK ) {
case AK881X_IF_MODE_BT656 :
ifmode | = 1 ;
break ;
case AK881X_IF_MODE_MASTER :
ifmode | = 2 ;
break ;
case AK881X_IF_MODE_SLAVE :
default :
break ;
}
dev_dbg ( & client - > dev , " IF mode %x \n " , ifmode ) ;
/*
* " Line Blanking No. " seems to be the same as the number of
* " black " lines on , e . g . , SuperH VOU , whose default value of 20
* " incidentally " matches ak881x ' default
*/
reg_write ( client , AK881X_INTERFACE_MODE , ifmode | ( 20 < < 3 ) ) ;
}
/* Hardware default: NTSC-M */
ak881x - > lines = 480 ;
dev_info ( & client - > dev , " Detected an ak881x chip ID %x, revision %x \n " ,
data , ak881x - > revision ) ;
return 0 ;
}
static int ak881x_remove ( struct i2c_client * client )
{
struct ak881x * ak881x = to_ak881x ( client ) ;
v4l2_device_unregister_subdev ( & ak881x - > subdev ) ;
return 0 ;
}
static const struct i2c_device_id ak881x_id [ ] = {
{ " ak8813 " , 0 } ,
{ " ak8814 " , 0 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( i2c , ak881x_id ) ;
static struct i2c_driver ak881x_i2c_driver = {
. driver = {
. name = " ak881x " ,
} ,
. probe = ak881x_probe ,
. remove = ak881x_remove ,
. id_table = ak881x_id ,
} ;
2012-02-12 13:56:32 +04:00
module_i2c_driver ( ak881x_i2c_driver ) ;
2010-03-29 11:45:22 +04:00
MODULE_DESCRIPTION ( " TV-output driver for ak8813/ak8814 " ) ;
MODULE_AUTHOR ( " Guennadi Liakhovetski <g.liakhovetski@gmx.de> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;