2019-05-27 08:55:21 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2012-03-08 17:44:15 -03:00
/*
* adv7183 . c Analog Devices ADV7183 video decoder driver
*
* Copyright ( c ) 2011 Analog Devices Inc .
*/
# include <linux/delay.h>
# include <linux/errno.h>
2022-02-23 01:34:16 +01:00
# include <linux/gpio/consumer.h>
2012-03-08 17:44:15 -03:00
# include <linux/i2c.h>
# include <linux/init.h>
# include <linux/module.h>
# include <linux/slab.h>
# include <linux/types.h>
# include <linux/videodev2.h>
2015-11-10 12:01:44 -02:00
# include <media/i2c/adv7183.h>
2012-03-08 17:44:15 -03:00
# include <media/v4l2-ctrls.h>
# include <media/v4l2-device.h>
# include "adv7183_regs.h"
struct adv7183 {
struct v4l2_subdev sd ;
struct v4l2_ctrl_handler hdl ;
v4l2_std_id std ; /* Current set standard */
u32 input ;
u32 output ;
2022-02-23 01:34:16 +01:00
struct gpio_desc * reset_pin ;
struct gpio_desc * oe_pin ;
2012-03-08 17:44:15 -03:00
struct v4l2_mbus_framefmt fmt ;
} ;
/* EXAMPLES USING 27 MHz CLOCK
* Mode 1 CVBS Input ( Composite Video on AIN5 )
* All standards are supported through autodetect , 8 - bit , 4 : 2 : 2 , ITU - R BT .656 output on P15 to P8 .
*/
static const unsigned char adv7183_init_regs [ ] = {
ADV7183_IN_CTRL , 0x04 , /* CVBS input on AIN5 */
ADV7183_DIGI_CLAMP_CTRL_1 , 0x00 , /* Slow down digital clamps */
ADV7183_SHAP_FILT_CTRL , 0x41 , /* Set CSFM to SH1 */
ADV7183_ADC_CTRL , 0x16 , /* Power down ADC 1 and ADC 2 */
ADV7183_CTI_DNR_CTRL_4 , 0x04 , /* Set DNR threshold to 4 for flat response */
/* ADI recommended programming sequence */
ADV7183_ADI_CTRL , 0x80 ,
ADV7183_CTI_DNR_CTRL_4 , 0x20 ,
0x52 , 0x18 ,
0x58 , 0xED ,
0x77 , 0xC5 ,
0x7C , 0x93 ,
0x7D , 0x00 ,
0xD0 , 0x48 ,
0xD5 , 0xA0 ,
0xD7 , 0xEA ,
ADV7183_SD_SATURATION_CR , 0x3E ,
ADV7183_PAL_V_END , 0x3E ,
ADV7183_PAL_F_TOGGLE , 0x0F ,
ADV7183_ADI_CTRL , 0x00 ,
} ;
static inline struct adv7183 * to_adv7183 ( struct v4l2_subdev * sd )
{
return container_of ( sd , struct adv7183 , sd ) ;
}
static inline struct v4l2_subdev * to_sd ( struct v4l2_ctrl * ctrl )
{
return & container_of ( ctrl - > handler , struct adv7183 , hdl ) - > sd ;
}
static inline int adv7183_read ( struct v4l2_subdev * sd , unsigned char reg )
{
struct i2c_client * client = v4l2_get_subdevdata ( sd ) ;
return i2c_smbus_read_byte_data ( client , reg ) ;
}
static inline int adv7183_write ( struct v4l2_subdev * sd , unsigned char reg ,
unsigned char value )
{
struct i2c_client * client = v4l2_get_subdevdata ( sd ) ;
return i2c_smbus_write_byte_data ( client , reg , value ) ;
}
static int adv7183_writeregs ( struct v4l2_subdev * sd ,
const unsigned char * regs , unsigned int num )
{
unsigned char reg , data ;
unsigned int cnt = 0 ;
if ( num & 0x1 ) {
v4l2_err ( sd , " invalid regs array \n " ) ;
return - 1 ;
}
while ( cnt < num ) {
reg = * regs + + ;
data = * regs + + ;
cnt + = 2 ;
adv7183_write ( sd , reg , data ) ;
}
return 0 ;
}
static int adv7183_log_status ( struct v4l2_subdev * sd )
{
struct adv7183 * decoder = to_adv7183 ( sd ) ;
v4l2_info ( sd , " adv7183: Input control = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_IN_CTRL ) ) ;
v4l2_info ( sd , " adv7183: Video selection = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_VD_SEL ) ) ;
v4l2_info ( sd , " adv7183: Output control = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_OUT_CTRL ) ) ;
v4l2_info ( sd , " adv7183: Extended output control = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_EXT_OUT_CTRL ) ) ;
v4l2_info ( sd , " adv7183: Autodetect enable = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_AUTO_DET_EN ) ) ;
v4l2_info ( sd , " adv7183: Contrast = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_CONTRAST ) ) ;
v4l2_info ( sd , " adv7183: Brightness = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_BRIGHTNESS ) ) ;
v4l2_info ( sd , " adv7183: Hue = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_HUE ) ) ;
v4l2_info ( sd , " adv7183: Default value Y = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_DEF_Y ) ) ;
v4l2_info ( sd , " adv7183: Default value C = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_DEF_C ) ) ;
v4l2_info ( sd , " adv7183: ADI control = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_ADI_CTRL ) ) ;
v4l2_info ( sd , " adv7183: Power Management = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_POW_MANAGE ) ) ;
v4l2_info ( sd , " adv7183: Status 1 2 and 3 = 0x%02x 0x%02x 0x%02x \n " ,
adv7183_read ( sd , ADV7183_STATUS_1 ) ,
adv7183_read ( sd , ADV7183_STATUS_2 ) ,
adv7183_read ( sd , ADV7183_STATUS_3 ) ) ;
v4l2_info ( sd , " adv7183: Ident = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_IDENT ) ) ;
v4l2_info ( sd , " adv7183: Analog clamp control = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_ANAL_CLAMP_CTRL ) ) ;
v4l2_info ( sd , " adv7183: Digital clamp control 1 = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_DIGI_CLAMP_CTRL_1 ) ) ;
v4l2_info ( sd , " adv7183: Shaping filter control 1 and 2 = 0x%02x 0x%02x \n " ,
adv7183_read ( sd , ADV7183_SHAP_FILT_CTRL ) ,
adv7183_read ( sd , ADV7183_SHAP_FILT_CTRL_2 ) ) ;
v4l2_info ( sd , " adv7183: Comb filter control = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_COMB_FILT_CTRL ) ) ;
v4l2_info ( sd , " adv7183: ADI control 2 = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_ADI_CTRL_2 ) ) ;
v4l2_info ( sd , " adv7183: Pixel delay control = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_PIX_DELAY_CTRL ) ) ;
v4l2_info ( sd , " adv7183: Misc gain control = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_MISC_GAIN_CTRL ) ) ;
v4l2_info ( sd , " adv7183: AGC mode control = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_AGC_MODE_CTRL ) ) ;
v4l2_info ( sd , " adv7183: Chroma gain control 1 and 2 = 0x%02x 0x%02x \n " ,
adv7183_read ( sd , ADV7183_CHRO_GAIN_CTRL_1 ) ,
adv7183_read ( sd , ADV7183_CHRO_GAIN_CTRL_2 ) ) ;
v4l2_info ( sd , " adv7183: Luma gain control 1 and 2 = 0x%02x 0x%02x \n " ,
adv7183_read ( sd , ADV7183_LUMA_GAIN_CTRL_1 ) ,
adv7183_read ( sd , ADV7183_LUMA_GAIN_CTRL_2 ) ) ;
v4l2_info ( sd , " adv7183: Vsync field control 1 2 and 3 = 0x%02x 0x%02x 0x%02x \n " ,
adv7183_read ( sd , ADV7183_VS_FIELD_CTRL_1 ) ,
adv7183_read ( sd , ADV7183_VS_FIELD_CTRL_2 ) ,
adv7183_read ( sd , ADV7183_VS_FIELD_CTRL_3 ) ) ;
2013-09-30 23:19:09 +09:00
v4l2_info ( sd , " adv7183: Hsync position control 1 2 and 3 = 0x%02x 0x%02x 0x%02x \n " ,
2012-03-08 17:44:15 -03:00
adv7183_read ( sd , ADV7183_HS_POS_CTRL_1 ) ,
adv7183_read ( sd , ADV7183_HS_POS_CTRL_2 ) ,
adv7183_read ( sd , ADV7183_HS_POS_CTRL_3 ) ) ;
v4l2_info ( sd , " adv7183: Polarity = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_POLARITY ) ) ;
v4l2_info ( sd , " adv7183: ADC control = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_ADC_CTRL ) ) ;
v4l2_info ( sd , " adv7183: SD offset Cb and Cr = 0x%02x 0x%02x \n " ,
adv7183_read ( sd , ADV7183_SD_OFFSET_CB ) ,
adv7183_read ( sd , ADV7183_SD_OFFSET_CR ) ) ;
v4l2_info ( sd , " adv7183: SD saturation Cb and Cr = 0x%02x 0x%02x \n " ,
adv7183_read ( sd , ADV7183_SD_SATURATION_CB ) ,
adv7183_read ( sd , ADV7183_SD_SATURATION_CR ) ) ;
v4l2_info ( sd , " adv7183: Drive strength = 0x%02x \n " ,
adv7183_read ( sd , ADV7183_DRIVE_STR ) ) ;
v4l2_ctrl_handler_log_status ( & decoder - > hdl , sd - > name ) ;
return 0 ;
}
static int adv7183_g_std ( struct v4l2_subdev * sd , v4l2_std_id * std )
{
struct adv7183 * decoder = to_adv7183 ( sd ) ;
* std = decoder - > std ;
return 0 ;
}
static int adv7183_s_std ( struct v4l2_subdev * sd , v4l2_std_id std )
{
struct adv7183 * decoder = to_adv7183 ( sd ) ;
int reg ;
reg = adv7183_read ( sd , ADV7183_IN_CTRL ) & 0xF ;
if ( std = = V4L2_STD_PAL_60 )
reg | = 0x60 ;
else if ( std = = V4L2_STD_NTSC_443 )
reg | = 0x70 ;
else if ( std = = V4L2_STD_PAL_N )
reg | = 0x90 ;
else if ( std = = V4L2_STD_PAL_M )
reg | = 0xA0 ;
else if ( std = = V4L2_STD_PAL_Nc )
reg | = 0xC0 ;
else if ( std & V4L2_STD_PAL )
reg | = 0x80 ;
else if ( std & V4L2_STD_NTSC )
reg | = 0x50 ;
else if ( std & V4L2_STD_SECAM )
reg | = 0xE0 ;
else
return - EINVAL ;
adv7183_write ( sd , ADV7183_IN_CTRL , reg ) ;
decoder - > std = std ;
return 0 ;
}
static int adv7183_reset ( struct v4l2_subdev * sd , u32 val )
{
int reg ;
reg = adv7183_read ( sd , ADV7183_POW_MANAGE ) | 0x80 ;
adv7183_write ( sd , ADV7183_POW_MANAGE , reg ) ;
/* wait 5ms before any further i2c writes are performed */
usleep_range ( 5000 , 10000 ) ;
return 0 ;
}
static int adv7183_s_routing ( struct v4l2_subdev * sd ,
u32 input , u32 output , u32 config )
{
struct adv7183 * decoder = to_adv7183 ( sd ) ;
int reg ;
if ( ( input > ADV7183_COMPONENT1 ) | | ( output > ADV7183_16BIT_OUT ) )
return - EINVAL ;
if ( input ! = decoder - > input ) {
decoder - > input = input ;
reg = adv7183_read ( sd , ADV7183_IN_CTRL ) & 0xF0 ;
switch ( input ) {
case ADV7183_COMPOSITE1 :
reg | = 0x1 ;
break ;
case ADV7183_COMPOSITE2 :
reg | = 0x2 ;
break ;
case ADV7183_COMPOSITE3 :
reg | = 0x3 ;
break ;
case ADV7183_COMPOSITE4 :
reg | = 0x4 ;
break ;
case ADV7183_COMPOSITE5 :
reg | = 0x5 ;
break ;
case ADV7183_COMPOSITE6 :
reg | = 0xB ;
break ;
case ADV7183_COMPOSITE7 :
reg | = 0xC ;
break ;
case ADV7183_COMPOSITE8 :
reg | = 0xD ;
break ;
case ADV7183_COMPOSITE9 :
reg | = 0xE ;
break ;
case ADV7183_COMPOSITE10 :
reg | = 0xF ;
break ;
case ADV7183_SVIDEO0 :
reg | = 0x6 ;
break ;
case ADV7183_SVIDEO1 :
reg | = 0x7 ;
break ;
case ADV7183_SVIDEO2 :
reg | = 0x8 ;
break ;
case ADV7183_COMPONENT0 :
reg | = 0x9 ;
break ;
case ADV7183_COMPONENT1 :
reg | = 0xA ;
break ;
default :
break ;
}
adv7183_write ( sd , ADV7183_IN_CTRL , reg ) ;
}
if ( output ! = decoder - > output ) {
decoder - > output = output ;
reg = adv7183_read ( sd , ADV7183_OUT_CTRL ) & 0xC0 ;
switch ( output ) {
case ADV7183_16BIT_OUT :
reg | = 0x9 ;
break ;
default :
reg | = 0xC ;
break ;
}
adv7183_write ( sd , ADV7183_OUT_CTRL , reg ) ;
}
return 0 ;
}
static int adv7183_s_ctrl ( struct v4l2_ctrl * ctrl )
{
struct v4l2_subdev * sd = to_sd ( ctrl ) ;
int val = ctrl - > val ;
switch ( ctrl - > id ) {
case V4L2_CID_BRIGHTNESS :
if ( val < 0 )
val = 127 - val ;
adv7183_write ( sd , ADV7183_BRIGHTNESS , val ) ;
break ;
case V4L2_CID_CONTRAST :
adv7183_write ( sd , ADV7183_CONTRAST , val ) ;
break ;
case V4L2_CID_SATURATION :
adv7183_write ( sd , ADV7183_SD_SATURATION_CB , val > > 8 ) ;
adv7183_write ( sd , ADV7183_SD_SATURATION_CR , ( val & 0xFF ) ) ;
break ;
case V4L2_CID_HUE :
adv7183_write ( sd , ADV7183_SD_OFFSET_CB , val > > 8 ) ;
adv7183_write ( sd , ADV7183_SD_OFFSET_CR , ( val & 0xFF ) ) ;
break ;
default :
return - EINVAL ;
}
return 0 ;
}
static int adv7183_querystd ( struct v4l2_subdev * sd , v4l2_std_id * std )
{
struct adv7183 * decoder = to_adv7183 ( sd ) ;
int reg ;
/* enable autodetection block */
reg = adv7183_read ( sd , ADV7183_IN_CTRL ) & 0xF ;
adv7183_write ( sd , ADV7183_IN_CTRL , reg ) ;
/* wait autodetection switch */
mdelay ( 10 ) ;
/* get autodetection result */
reg = adv7183_read ( sd , ADV7183_STATUS_1 ) ;
switch ( ( reg > > 0x4 ) & 0x7 ) {
case 0 :
2013-05-29 10:18:54 -03:00
* std & = V4L2_STD_NTSC ;
2012-03-08 17:44:15 -03:00
break ;
case 1 :
2013-05-29 10:18:54 -03:00
* std & = V4L2_STD_NTSC_443 ;
2012-03-08 17:44:15 -03:00
break ;
case 2 :
2013-05-29 10:18:54 -03:00
* std & = V4L2_STD_PAL_M ;
2012-03-08 17:44:15 -03:00
break ;
case 3 :
2013-05-29 10:18:54 -03:00
* std & = V4L2_STD_PAL_60 ;
2012-03-08 17:44:15 -03:00
break ;
case 4 :
2013-05-29 10:18:54 -03:00
* std & = V4L2_STD_PAL ;
2012-03-08 17:44:15 -03:00
break ;
case 5 :
2013-05-29 10:18:54 -03:00
* std & = V4L2_STD_SECAM ;
2012-03-08 17:44:15 -03:00
break ;
case 6 :
2013-05-29 10:18:54 -03:00
* std & = V4L2_STD_PAL_Nc ;
2012-03-08 17:44:15 -03:00
break ;
case 7 :
2013-05-29 10:18:54 -03:00
* std & = V4L2_STD_SECAM ;
2012-03-08 17:44:15 -03:00
break ;
default :
* std = V4L2_STD_UNKNOWN ;
break ;
}
/* after std detection, write back user set std */
adv7183_s_std ( sd , decoder - > std ) ;
return 0 ;
}
static int adv7183_g_input_status ( struct v4l2_subdev * sd , u32 * status )
{
int reg ;
* status = V4L2_IN_ST_NO_SIGNAL ;
reg = adv7183_read ( sd , ADV7183_STATUS_1 ) ;
if ( reg < 0 )
return reg ;
if ( reg & 0x1 )
* status = 0 ;
return 0 ;
}
2015-04-09 04:01:33 -03:00
static int adv7183_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 04:01:33 -03:00
struct v4l2_subdev_mbus_code_enum * code )
2012-03-08 17:44:15 -03:00
{
2015-04-09 04:01:33 -03:00
if ( code - > pad | | code - > index > 0 )
2012-03-08 17:44:15 -03:00
return - EINVAL ;
2015-04-09 04:01:33 -03:00
code - > code = MEDIA_BUS_FMT_UYVY8_2X8 ;
2012-03-08 17:44:15 -03:00
return 0 ;
}
2015-04-09 06:24:36 -03:00
static int adv7183_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 ,
2015-04-09 06:24:36 -03:00
struct v4l2_subdev_format * format )
2012-03-08 17:44:15 -03:00
{
struct adv7183 * decoder = to_adv7183 ( sd ) ;
2015-04-09 06:24:36 -03:00
struct v4l2_mbus_framefmt * fmt = & format - > format ;
if ( format - > pad )
return - EINVAL ;
2012-03-08 17:44:15 -03:00
2014-11-10 14:28:29 -03:00
fmt - > code = MEDIA_BUS_FMT_UYVY8_2X8 ;
2012-03-08 17:44:15 -03:00
fmt - > colorspace = V4L2_COLORSPACE_SMPTE170M ;
if ( decoder - > std & V4L2_STD_525_60 ) {
fmt - > field = V4L2_FIELD_SEQ_TB ;
fmt - > width = 720 ;
fmt - > height = 480 ;
} else {
fmt - > field = V4L2_FIELD_SEQ_BT ;
fmt - > width = 720 ;
fmt - > height = 576 ;
}
2015-04-09 06:24:36 -03:00
if ( format - > which = = V4L2_SUBDEV_FORMAT_ACTIVE )
decoder - > fmt = * fmt ;
else
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
sd_state - > pads - > try_fmt = * fmt ;
2012-03-08 17:44:15 -03:00
return 0 ;
}
2015-04-09 04:02:34 -03:00
static int adv7183_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 ,
2015-04-09 04:02:34 -03:00
struct v4l2_subdev_format * format )
2012-03-08 17:44:15 -03:00
{
struct adv7183 * decoder = to_adv7183 ( sd ) ;
2015-04-09 04:02:34 -03:00
if ( format - > pad )
return - EINVAL ;
format - > format = decoder - > fmt ;
2012-03-08 17:44:15 -03:00
return 0 ;
}
static int adv7183_s_stream ( struct v4l2_subdev * sd , int enable )
{
struct adv7183 * decoder = to_adv7183 ( sd ) ;
if ( enable )
2022-02-23 01:34:16 +01:00
gpiod_set_value ( decoder - > oe_pin , 1 ) ;
2012-03-08 17:44:15 -03:00
else
2022-02-23 01:34:16 +01:00
gpiod_set_value ( decoder - > oe_pin , 0 ) ;
2012-03-08 17:44:15 -03:00
udelay ( 1 ) ;
return 0 ;
}
# ifdef CONFIG_VIDEO_ADV_DEBUG
static int adv7183_g_register ( struct v4l2_subdev * sd , struct v4l2_dbg_register * reg )
{
reg - > val = adv7183_read ( sd , reg - > reg & 0xff ) ;
reg - > size = 1 ;
return 0 ;
}
2013-03-24 08:28:46 -03:00
static int adv7183_s_register ( struct v4l2_subdev * sd , const struct v4l2_dbg_register * reg )
2012-03-08 17:44:15 -03:00
{
adv7183_write ( sd , reg - > reg & 0xff , reg - > val & 0xff ) ;
return 0 ;
}
# endif
static const struct v4l2_ctrl_ops adv7183_ctrl_ops = {
. s_ctrl = adv7183_s_ctrl ,
} ;
static const struct v4l2_subdev_core_ops adv7183_core_ops = {
. log_status = adv7183_log_status ,
. reset = adv7183_reset ,
# ifdef CONFIG_VIDEO_ADV_DEBUG
. g_register = adv7183_g_register ,
. s_register = adv7183_s_register ,
# endif
} ;
static const struct v4l2_subdev_video_ops adv7183_video_ops = {
2014-04-28 16:53:01 -03:00
. g_std = adv7183_g_std ,
. s_std = adv7183_s_std ,
2012-03-08 17:44:15 -03:00
. s_routing = adv7183_s_routing ,
. querystd = adv7183_querystd ,
. g_input_status = adv7183_g_input_status ,
. s_stream = adv7183_s_stream ,
} ;
2015-04-09 04:01:33 -03:00
static const struct v4l2_subdev_pad_ops adv7183_pad_ops = {
. enum_mbus_code = adv7183_enum_mbus_code ,
2015-04-09 04:02:34 -03:00
. get_fmt = adv7183_get_fmt ,
2015-04-09 06:24:36 -03:00
. set_fmt = adv7183_set_fmt ,
2015-04-09 04:01:33 -03:00
} ;
2012-03-08 17:44:15 -03:00
static const struct v4l2_subdev_ops adv7183_ops = {
. core = & adv7183_core_ops ,
. video = & adv7183_video_ops ,
2015-04-09 04:01:33 -03:00
. pad = & adv7183_pad_ops ,
2012-03-08 17:44:15 -03:00
} ;
2022-11-18 23:41:03 +01:00
static int adv7183_probe ( struct i2c_client * client )
2012-03-08 17:44:15 -03:00
{
struct adv7183 * decoder ;
struct v4l2_subdev * sd ;
struct v4l2_ctrl_handler * hdl ;
int ret ;
2015-04-09 06:24:36 -03:00
struct v4l2_subdev_format fmt = {
. which = V4L2_SUBDEV_FORMAT_ACTIVE ,
} ;
2012-03-08 17:44:15 -03:00
/* Check if the adapter supports the needed features */
if ( ! i2c_check_functionality ( client - > adapter , I2C_FUNC_SMBUS_BYTE_DATA ) )
return - EIO ;
v4l_info ( client , " chip found @ 0x%02x (%s) \n " ,
client - > addr < < 1 , client - > adapter - > name ) ;
2013-05-02 08:29:43 -03:00
decoder = devm_kzalloc ( & client - > dev , sizeof ( * decoder ) , GFP_KERNEL ) ;
2012-03-08 17:44:15 -03:00
if ( decoder = = NULL )
return - ENOMEM ;
2022-02-23 01:34:16 +01:00
/*
* Requesting high will assert reset , the line should be
* flagged as active low in descriptor table or machine description .
*/
decoder - > reset_pin = devm_gpiod_get ( & client - > dev , " reset " ,
GPIOD_OUT_HIGH ) ;
if ( IS_ERR ( decoder - > reset_pin ) )
return PTR_ERR ( decoder - > reset_pin ) ;
gpiod_set_consumer_name ( decoder - > reset_pin , " ADV7183 Reset " ) ;
/*
* Requesting low will start with output disabled , the line should be
* flagged as active low in descriptor table or machine description .
*/
decoder - > oe_pin = devm_gpiod_get ( & client - > dev , " oe " ,
GPIOD_OUT_LOW ) ;
if ( IS_ERR ( decoder - > oe_pin ) )
return PTR_ERR ( decoder - > oe_pin ) ;
gpiod_set_consumer_name ( decoder - > reset_pin , " ADV7183 Output Enable " ) ;
2012-03-08 17:44:15 -03:00
sd = & decoder - > sd ;
v4l2_i2c_subdev_init ( sd , client , & adv7183_ops ) ;
hdl = & decoder - > hdl ;
v4l2_ctrl_handler_init ( hdl , 4 ) ;
v4l2_ctrl_new_std ( hdl , & adv7183_ctrl_ops ,
V4L2_CID_BRIGHTNESS , - 128 , 127 , 1 , 0 ) ;
v4l2_ctrl_new_std ( hdl , & adv7183_ctrl_ops ,
V4L2_CID_CONTRAST , 0 , 0xFF , 1 , 0x80 ) ;
v4l2_ctrl_new_std ( hdl , & adv7183_ctrl_ops ,
V4L2_CID_SATURATION , 0 , 0xFFFF , 1 , 0x8080 ) ;
v4l2_ctrl_new_std ( hdl , & adv7183_ctrl_ops ,
V4L2_CID_HUE , 0 , 0xFFFF , 1 , 0x8080 ) ;
/* hook the control handler into the driver */
sd - > ctrl_handler = hdl ;
if ( hdl - > error ) {
ret = hdl - > error ;
v4l2_ctrl_handler_free ( hdl ) ;
2013-05-02 08:29:43 -03:00
return ret ;
2012-03-08 17:44:15 -03:00
}
/* v4l2 doesn't support an autodetect standard, pick PAL as default */
decoder - > std = V4L2_STD_PAL ;
decoder - > input = ADV7183_COMPOSITE4 ;
decoder - > output = ADV7183_8BIT_OUT ;
/* reset chip */
/* reset pulse width at least 5ms */
mdelay ( 10 ) ;
2022-02-23 01:34:16 +01:00
/* De-assert reset line (descriptor tagged active low) */
gpiod_set_value ( decoder - > reset_pin , 0 ) ;
2012-03-08 17:44:15 -03:00
/* wait 5ms before any further i2c writes are performed */
mdelay ( 5 ) ;
adv7183_writeregs ( sd , adv7183_init_regs , ARRAY_SIZE ( adv7183_init_regs ) ) ;
adv7183_s_std ( sd , decoder - > std ) ;
2015-04-09 06:24:36 -03:00
fmt . format . width = 720 ;
fmt . format . height = 576 ;
adv7183_set_fmt ( sd , NULL , & fmt ) ;
2012-03-08 17:44:15 -03:00
/* initialize the hardware to the default control values */
ret = v4l2_ctrl_handler_setup ( hdl ) ;
if ( ret ) {
v4l2_ctrl_handler_free ( hdl ) ;
2013-05-02 08:29:43 -03:00
return ret ;
2012-03-08 17:44:15 -03:00
}
return 0 ;
}
2022-08-15 10:02:30 +02:00
static void adv7183_remove ( struct i2c_client * client )
2012-03-08 17:44:15 -03:00
{
struct v4l2_subdev * sd = i2c_get_clientdata ( client ) ;
v4l2_device_unregister_subdev ( sd ) ;
v4l2_ctrl_handler_free ( sd - > ctrl_handler ) ;
}
static const struct i2c_device_id adv7183_id [ ] = {
{ " adv7183 " , 0 } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( i2c , adv7183_id ) ;
static struct i2c_driver adv7183_driver = {
. driver = {
. name = " adv7183 " ,
} ,
2022-11-18 23:41:03 +01:00
. probe_new = adv7183_probe ,
2012-12-21 13:17:53 -08:00
. remove = adv7183_remove ,
2012-03-08 17:44:15 -03:00
. id_table = adv7183_id ,
} ;
2012-10-08 10:13:41 -03:00
module_i2c_driver ( adv7183_driver ) ;
2012-03-08 17:44:15 -03:00
MODULE_DESCRIPTION ( " Analog Devices ADV7183 video decoder driver " ) ;
MODULE_AUTHOR ( " Scott Jiang <Scott.Jiang.Linux@gmail.com> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;