cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

saa7127.c (25346B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * saa7127 - Philips SAA7127/SAA7129 video encoder driver
      4 *
      5 * Copyright (C) 2003 Roy Bulter <rbulter@hetnet.nl>
      6 *
      7 * Based on SAA7126 video encoder driver by Gillem & Andreas Oberritter
      8 *
      9 * Copyright (C) 2000-2001 Gillem <htoa@gmx.net>
     10 * Copyright (C) 2002 Andreas Oberritter <obi@saftware.de>
     11 *
     12 * Based on Stadis 4:2:2 MPEG-2 Decoder Driver by Nathan Laredo
     13 *
     14 * Copyright (C) 1999 Nathan Laredo <laredo@gnu.org>
     15 *
     16 * This driver is designed for the Hauppauge 250/350 Linux driver
     17 * from the ivtv Project
     18 *
     19 * Copyright (C) 2003 Kevin Thayer <nufan_wfk@yahoo.com>
     20 *
     21 * Dual output support:
     22 * Copyright (C) 2004 Eric Varsanyi
     23 *
     24 * NTSC Tuning and 7.5 IRE Setup
     25 * Copyright (C) 2004  Chris Kennedy <c@groovy.org>
     26 *
     27 * VBI additions & cleanup:
     28 * Copyright (C) 2004, 2005 Hans Verkuil <hverkuil@xs4all.nl>
     29 *
     30 * Note: the saa7126 is identical to the saa7127, and the saa7128 is
     31 * identical to the saa7129, except that the saa7126 and saa7128 have
     32 * macrovision anti-taping support. This driver will almost certainly
     33 * work fine for those chips, except of course for the missing anti-taping
     34 * support.
     35 */
     36
     37
     38#include <linux/kernel.h>
     39#include <linux/module.h>
     40#include <linux/slab.h>
     41#include <linux/i2c.h>
     42#include <linux/videodev2.h>
     43#include <media/v4l2-device.h>
     44#include <media/i2c/saa7127.h>
     45
     46static int debug;
     47static int test_image;
     48
     49MODULE_DESCRIPTION("Philips SAA7127/9 video encoder driver");
     50MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil");
     51MODULE_LICENSE("GPL");
     52module_param(debug, int, 0644);
     53module_param(test_image, int, 0644);
     54MODULE_PARM_DESC(debug, "debug level (0-2)");
     55MODULE_PARM_DESC(test_image, "test_image (0-1)");
     56
     57
     58/*
     59 * SAA7127 registers
     60 */
     61
     62#define SAA7127_REG_STATUS                           0x00
     63#define SAA7127_REG_WIDESCREEN_CONFIG                0x26
     64#define SAA7127_REG_WIDESCREEN_ENABLE                0x27
     65#define SAA7127_REG_BURST_START                      0x28
     66#define SAA7127_REG_BURST_END                        0x29
     67#define SAA7127_REG_COPYGEN_0                        0x2a
     68#define SAA7127_REG_COPYGEN_1                        0x2b
     69#define SAA7127_REG_COPYGEN_2                        0x2c
     70#define SAA7127_REG_OUTPUT_PORT_CONTROL              0x2d
     71#define SAA7127_REG_GAIN_LUMINANCE_RGB               0x38
     72#define SAA7127_REG_GAIN_COLORDIFF_RGB               0x39
     73#define SAA7127_REG_INPUT_PORT_CONTROL_1             0x3a
     74#define SAA7129_REG_FADE_KEY_COL2		     0x4f
     75#define SAA7127_REG_CHROMA_PHASE                     0x5a
     76#define SAA7127_REG_GAINU                            0x5b
     77#define SAA7127_REG_GAINV                            0x5c
     78#define SAA7127_REG_BLACK_LEVEL                      0x5d
     79#define SAA7127_REG_BLANKING_LEVEL                   0x5e
     80#define SAA7127_REG_VBI_BLANKING                     0x5f
     81#define SAA7127_REG_DAC_CONTROL                      0x61
     82#define SAA7127_REG_BURST_AMP                        0x62
     83#define SAA7127_REG_SUBC3                            0x63
     84#define SAA7127_REG_SUBC2                            0x64
     85#define SAA7127_REG_SUBC1                            0x65
     86#define SAA7127_REG_SUBC0                            0x66
     87#define SAA7127_REG_LINE_21_ODD_0                    0x67
     88#define SAA7127_REG_LINE_21_ODD_1                    0x68
     89#define SAA7127_REG_LINE_21_EVEN_0                   0x69
     90#define SAA7127_REG_LINE_21_EVEN_1                   0x6a
     91#define SAA7127_REG_RCV_PORT_CONTROL                 0x6b
     92#define SAA7127_REG_VTRIG                            0x6c
     93#define SAA7127_REG_HTRIG_HI                         0x6d
     94#define SAA7127_REG_MULTI                            0x6e
     95#define SAA7127_REG_CLOSED_CAPTION                   0x6f
     96#define SAA7127_REG_RCV2_OUTPUT_START                0x70
     97#define SAA7127_REG_RCV2_OUTPUT_END                  0x71
     98#define SAA7127_REG_RCV2_OUTPUT_MSBS                 0x72
     99#define SAA7127_REG_TTX_REQUEST_H_START              0x73
    100#define SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH       0x74
    101#define SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT        0x75
    102#define SAA7127_REG_TTX_ODD_REQ_VERT_START           0x76
    103#define SAA7127_REG_TTX_ODD_REQ_VERT_END             0x77
    104#define SAA7127_REG_TTX_EVEN_REQ_VERT_START          0x78
    105#define SAA7127_REG_TTX_EVEN_REQ_VERT_END            0x79
    106#define SAA7127_REG_FIRST_ACTIVE                     0x7a
    107#define SAA7127_REG_LAST_ACTIVE                      0x7b
    108#define SAA7127_REG_MSB_VERTICAL                     0x7c
    109#define SAA7127_REG_DISABLE_TTX_LINE_LO_0            0x7e
    110#define SAA7127_REG_DISABLE_TTX_LINE_LO_1            0x7f
    111
    112/*
    113 **********************************************************************
    114 *
    115 *  Arrays with configuration parameters for the SAA7127
    116 *
    117 **********************************************************************
    118 */
    119
    120struct i2c_reg_value {
    121	unsigned char reg;
    122	unsigned char value;
    123};
    124
    125static const struct i2c_reg_value saa7129_init_config_extra[] = {
    126	{ SAA7127_REG_OUTPUT_PORT_CONTROL,		0x38 },
    127	{ SAA7127_REG_VTRIG,				0xfa },
    128	{ 0, 0 }
    129};
    130
    131static const struct i2c_reg_value saa7127_init_config_common[] = {
    132	{ SAA7127_REG_WIDESCREEN_CONFIG,		0x0d },
    133	{ SAA7127_REG_WIDESCREEN_ENABLE,		0x00 },
    134	{ SAA7127_REG_COPYGEN_0,			0x77 },
    135	{ SAA7127_REG_COPYGEN_1,			0x41 },
    136	{ SAA7127_REG_COPYGEN_2,			0x00 },	/* Macrovision enable/disable */
    137	{ SAA7127_REG_OUTPUT_PORT_CONTROL,		0xbf },
    138	{ SAA7127_REG_GAIN_LUMINANCE_RGB,		0x00 },
    139	{ SAA7127_REG_GAIN_COLORDIFF_RGB,		0x00 },
    140	{ SAA7127_REG_INPUT_PORT_CONTROL_1,		0x80 },	/* for color bars */
    141	{ SAA7127_REG_LINE_21_ODD_0,			0x77 },
    142	{ SAA7127_REG_LINE_21_ODD_1,			0x41 },
    143	{ SAA7127_REG_LINE_21_EVEN_0,			0x88 },
    144	{ SAA7127_REG_LINE_21_EVEN_1,			0x41 },
    145	{ SAA7127_REG_RCV_PORT_CONTROL,			0x12 },
    146	{ SAA7127_REG_VTRIG,				0xf9 },
    147	{ SAA7127_REG_HTRIG_HI,				0x00 },
    148	{ SAA7127_REG_RCV2_OUTPUT_START,		0x41 },
    149	{ SAA7127_REG_RCV2_OUTPUT_END,			0xc3 },
    150	{ SAA7127_REG_RCV2_OUTPUT_MSBS,			0x00 },
    151	{ SAA7127_REG_TTX_REQUEST_H_START,		0x3e },
    152	{ SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH,	0xb8 },
    153	{ SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT,	0x03 },
    154	{ SAA7127_REG_TTX_ODD_REQ_VERT_START,		0x15 },
    155	{ SAA7127_REG_TTX_ODD_REQ_VERT_END,		0x16 },
    156	{ SAA7127_REG_TTX_EVEN_REQ_VERT_START,		0x15 },
    157	{ SAA7127_REG_TTX_EVEN_REQ_VERT_END,		0x16 },
    158	{ SAA7127_REG_FIRST_ACTIVE,			0x1a },
    159	{ SAA7127_REG_LAST_ACTIVE,			0x01 },
    160	{ SAA7127_REG_MSB_VERTICAL,			0xc0 },
    161	{ SAA7127_REG_DISABLE_TTX_LINE_LO_0,		0x00 },
    162	{ SAA7127_REG_DISABLE_TTX_LINE_LO_1,		0x00 },
    163	{ 0, 0 }
    164};
    165
    166#define SAA7127_60HZ_DAC_CONTROL 0x15
    167static const struct i2c_reg_value saa7127_init_config_60hz[] = {
    168	{ SAA7127_REG_BURST_START,			0x19 },
    169	/* BURST_END is also used as a chip ID in saa7127_probe */
    170	{ SAA7127_REG_BURST_END,			0x1d },
    171	{ SAA7127_REG_CHROMA_PHASE,			0xa3 },
    172	{ SAA7127_REG_GAINU,				0x98 },
    173	{ SAA7127_REG_GAINV,				0xd3 },
    174	{ SAA7127_REG_BLACK_LEVEL,			0x39 },
    175	{ SAA7127_REG_BLANKING_LEVEL,			0x2e },
    176	{ SAA7127_REG_VBI_BLANKING,			0x2e },
    177	{ SAA7127_REG_DAC_CONTROL,			0x15 },
    178	{ SAA7127_REG_BURST_AMP,			0x4d },
    179	{ SAA7127_REG_SUBC3,				0x1f },
    180	{ SAA7127_REG_SUBC2,				0x7c },
    181	{ SAA7127_REG_SUBC1,				0xf0 },
    182	{ SAA7127_REG_SUBC0,				0x21 },
    183	{ SAA7127_REG_MULTI,				0x90 },
    184	{ SAA7127_REG_CLOSED_CAPTION,			0x11 },
    185	{ 0, 0 }
    186};
    187
    188#define SAA7127_50HZ_PAL_DAC_CONTROL 0x02
    189static struct i2c_reg_value saa7127_init_config_50hz_pal[] = {
    190	{ SAA7127_REG_BURST_START,			0x21 },
    191	/* BURST_END is also used as a chip ID in saa7127_probe */
    192	{ SAA7127_REG_BURST_END,			0x1d },
    193	{ SAA7127_REG_CHROMA_PHASE,			0x3f },
    194	{ SAA7127_REG_GAINU,				0x7d },
    195	{ SAA7127_REG_GAINV,				0xaf },
    196	{ SAA7127_REG_BLACK_LEVEL,			0x33 },
    197	{ SAA7127_REG_BLANKING_LEVEL,			0x35 },
    198	{ SAA7127_REG_VBI_BLANKING,			0x35 },
    199	{ SAA7127_REG_DAC_CONTROL,			0x02 },
    200	{ SAA7127_REG_BURST_AMP,			0x2f },
    201	{ SAA7127_REG_SUBC3,				0xcb },
    202	{ SAA7127_REG_SUBC2,				0x8a },
    203	{ SAA7127_REG_SUBC1,				0x09 },
    204	{ SAA7127_REG_SUBC0,				0x2a },
    205	{ SAA7127_REG_MULTI,				0xa0 },
    206	{ SAA7127_REG_CLOSED_CAPTION,			0x00 },
    207	{ 0, 0 }
    208};
    209
    210#define SAA7127_50HZ_SECAM_DAC_CONTROL 0x08
    211static struct i2c_reg_value saa7127_init_config_50hz_secam[] = {
    212	{ SAA7127_REG_BURST_START,			0x21 },
    213	/* BURST_END is also used as a chip ID in saa7127_probe */
    214	{ SAA7127_REG_BURST_END,			0x1d },
    215	{ SAA7127_REG_CHROMA_PHASE,			0x3f },
    216	{ SAA7127_REG_GAINU,				0x6a },
    217	{ SAA7127_REG_GAINV,				0x81 },
    218	{ SAA7127_REG_BLACK_LEVEL,			0x33 },
    219	{ SAA7127_REG_BLANKING_LEVEL,			0x35 },
    220	{ SAA7127_REG_VBI_BLANKING,			0x35 },
    221	{ SAA7127_REG_DAC_CONTROL,			0x08 },
    222	{ SAA7127_REG_BURST_AMP,			0x2f },
    223	{ SAA7127_REG_SUBC3,				0xb2 },
    224	{ SAA7127_REG_SUBC2,				0x3b },
    225	{ SAA7127_REG_SUBC1,				0xa3 },
    226	{ SAA7127_REG_SUBC0,				0x28 },
    227	{ SAA7127_REG_MULTI,				0x90 },
    228	{ SAA7127_REG_CLOSED_CAPTION,			0x00 },
    229	{ 0, 0 }
    230};
    231
    232/*
    233 **********************************************************************
    234 *
    235 *  Encoder Struct, holds the configuration state of the encoder
    236 *
    237 **********************************************************************
    238 */
    239
    240enum saa712x_model {
    241	SAA7127,
    242	SAA7129,
    243};
    244
    245struct saa7127_state {
    246	struct v4l2_subdev sd;
    247	v4l2_std_id std;
    248	enum saa712x_model ident;
    249	enum saa7127_input_type input_type;
    250	enum saa7127_output_type output_type;
    251	int video_enable;
    252	int wss_enable;
    253	u16 wss_mode;
    254	int cc_enable;
    255	u16 cc_data;
    256	int xds_enable;
    257	u16 xds_data;
    258	int vps_enable;
    259	u8 vps_data[5];
    260	u8 reg_2d;
    261	u8 reg_3a;
    262	u8 reg_3a_cb;   /* colorbar bit */
    263	u8 reg_61;
    264};
    265
    266static inline struct saa7127_state *to_state(struct v4l2_subdev *sd)
    267{
    268	return container_of(sd, struct saa7127_state, sd);
    269}
    270
    271static const char * const output_strs[] =
    272{
    273	"S-Video + Composite",
    274	"Composite",
    275	"S-Video",
    276	"RGB",
    277	"YUV C",
    278	"YUV V"
    279};
    280
    281static const char * const wss_strs[] = {
    282	"invalid",
    283	"letterbox 14:9 center",
    284	"letterbox 14:9 top",
    285	"invalid",
    286	"letterbox 16:9 top",
    287	"invalid",
    288	"invalid",
    289	"16:9 full format anamorphic",
    290	"4:3 full format",
    291	"invalid",
    292	"invalid",
    293	"letterbox 16:9 center",
    294	"invalid",
    295	"letterbox >16:9 center",
    296	"14:9 full format center",
    297	"invalid",
    298};
    299
    300/* ----------------------------------------------------------------------- */
    301
    302static int saa7127_read(struct v4l2_subdev *sd, u8 reg)
    303{
    304	struct i2c_client *client = v4l2_get_subdevdata(sd);
    305
    306	return i2c_smbus_read_byte_data(client, reg);
    307}
    308
    309/* ----------------------------------------------------------------------- */
    310
    311static int saa7127_write(struct v4l2_subdev *sd, u8 reg, u8 val)
    312{
    313	struct i2c_client *client = v4l2_get_subdevdata(sd);
    314	int i;
    315
    316	for (i = 0; i < 3; i++) {
    317		if (i2c_smbus_write_byte_data(client, reg, val) == 0)
    318			return 0;
    319	}
    320	v4l2_err(sd, "I2C Write Problem\n");
    321	return -1;
    322}
    323
    324/* ----------------------------------------------------------------------- */
    325
    326static int saa7127_write_inittab(struct v4l2_subdev *sd,
    327				 const struct i2c_reg_value *regs)
    328{
    329	while (regs->reg != 0) {
    330		saa7127_write(sd, regs->reg, regs->value);
    331		regs++;
    332	}
    333	return 0;
    334}
    335
    336/* ----------------------------------------------------------------------- */
    337
    338static int saa7127_set_vps(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
    339{
    340	struct saa7127_state *state = to_state(sd);
    341	int enable = (data->line != 0);
    342
    343	if (enable && (data->field != 0 || data->line != 16))
    344		return -EINVAL;
    345	if (state->vps_enable != enable) {
    346		v4l2_dbg(1, debug, sd, "Turn VPS Signal %s\n", enable ? "on" : "off");
    347		saa7127_write(sd, 0x54, enable << 7);
    348		state->vps_enable = enable;
    349	}
    350	if (!enable)
    351		return 0;
    352
    353	state->vps_data[0] = data->data[2];
    354	state->vps_data[1] = data->data[8];
    355	state->vps_data[2] = data->data[9];
    356	state->vps_data[3] = data->data[10];
    357	state->vps_data[4] = data->data[11];
    358	v4l2_dbg(1, debug, sd, "Set VPS data %*ph\n", 5, state->vps_data);
    359	saa7127_write(sd, 0x55, state->vps_data[0]);
    360	saa7127_write(sd, 0x56, state->vps_data[1]);
    361	saa7127_write(sd, 0x57, state->vps_data[2]);
    362	saa7127_write(sd, 0x58, state->vps_data[3]);
    363	saa7127_write(sd, 0x59, state->vps_data[4]);
    364	return 0;
    365}
    366
    367/* ----------------------------------------------------------------------- */
    368
    369static int saa7127_set_cc(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
    370{
    371	struct saa7127_state *state = to_state(sd);
    372	u16 cc = data->data[1] << 8 | data->data[0];
    373	int enable = (data->line != 0);
    374
    375	if (enable && (data->field != 0 || data->line != 21))
    376		return -EINVAL;
    377	if (state->cc_enable != enable) {
    378		v4l2_dbg(1, debug, sd,
    379			"Turn CC %s\n", enable ? "on" : "off");
    380		saa7127_write(sd, SAA7127_REG_CLOSED_CAPTION,
    381			(state->xds_enable << 7) | (enable << 6) | 0x11);
    382		state->cc_enable = enable;
    383	}
    384	if (!enable)
    385		return 0;
    386
    387	v4l2_dbg(2, debug, sd, "CC data: %04x\n", cc);
    388	saa7127_write(sd, SAA7127_REG_LINE_21_ODD_0, cc & 0xff);
    389	saa7127_write(sd, SAA7127_REG_LINE_21_ODD_1, cc >> 8);
    390	state->cc_data = cc;
    391	return 0;
    392}
    393
    394/* ----------------------------------------------------------------------- */
    395
    396static int saa7127_set_xds(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
    397{
    398	struct saa7127_state *state = to_state(sd);
    399	u16 xds = data->data[1] << 8 | data->data[0];
    400	int enable = (data->line != 0);
    401
    402	if (enable && (data->field != 1 || data->line != 21))
    403		return -EINVAL;
    404	if (state->xds_enable != enable) {
    405		v4l2_dbg(1, debug, sd, "Turn XDS %s\n", enable ? "on" : "off");
    406		saa7127_write(sd, SAA7127_REG_CLOSED_CAPTION,
    407				(enable << 7) | (state->cc_enable << 6) | 0x11);
    408		state->xds_enable = enable;
    409	}
    410	if (!enable)
    411		return 0;
    412
    413	v4l2_dbg(2, debug, sd, "XDS data: %04x\n", xds);
    414	saa7127_write(sd, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff);
    415	saa7127_write(sd, SAA7127_REG_LINE_21_EVEN_1, xds >> 8);
    416	state->xds_data = xds;
    417	return 0;
    418}
    419
    420/* ----------------------------------------------------------------------- */
    421
    422static int saa7127_set_wss(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
    423{
    424	struct saa7127_state *state = to_state(sd);
    425	int enable = (data->line != 0);
    426
    427	if (enable && (data->field != 0 || data->line != 23))
    428		return -EINVAL;
    429	if (state->wss_enable != enable) {
    430		v4l2_dbg(1, debug, sd, "Turn WSS %s\n", enable ? "on" : "off");
    431		saa7127_write(sd, 0x27, enable << 7);
    432		state->wss_enable = enable;
    433	}
    434	if (!enable)
    435		return 0;
    436
    437	saa7127_write(sd, 0x26, data->data[0]);
    438	saa7127_write(sd, 0x27, 0x80 | (data->data[1] & 0x3f));
    439	v4l2_dbg(1, debug, sd,
    440		"WSS mode: %s\n", wss_strs[data->data[0] & 0xf]);
    441	state->wss_mode = (data->data[1] & 0x3f) << 8 | data->data[0];
    442	return 0;
    443}
    444
    445/* ----------------------------------------------------------------------- */
    446
    447static int saa7127_set_video_enable(struct v4l2_subdev *sd, int enable)
    448{
    449	struct saa7127_state *state = to_state(sd);
    450
    451	if (enable) {
    452		v4l2_dbg(1, debug, sd, "Enable Video Output\n");
    453		saa7127_write(sd, 0x2d, state->reg_2d);
    454		saa7127_write(sd, 0x61, state->reg_61);
    455	} else {
    456		v4l2_dbg(1, debug, sd, "Disable Video Output\n");
    457		saa7127_write(sd, 0x2d, (state->reg_2d & 0xf0));
    458		saa7127_write(sd, 0x61, (state->reg_61 | 0xc0));
    459	}
    460	state->video_enable = enable;
    461	return 0;
    462}
    463
    464/* ----------------------------------------------------------------------- */
    465
    466static int saa7127_set_std(struct v4l2_subdev *sd, v4l2_std_id std)
    467{
    468	struct saa7127_state *state = to_state(sd);
    469	const struct i2c_reg_value *inittab;
    470
    471	if (std & V4L2_STD_525_60) {
    472		v4l2_dbg(1, debug, sd, "Selecting 60 Hz video Standard\n");
    473		inittab = saa7127_init_config_60hz;
    474		state->reg_61 = SAA7127_60HZ_DAC_CONTROL;
    475
    476	} else if (state->ident == SAA7129 &&
    477		   (std & V4L2_STD_SECAM) &&
    478		   !(std & (V4L2_STD_625_50 & ~V4L2_STD_SECAM))) {
    479
    480		/* If and only if SECAM, with a SAA712[89] */
    481		v4l2_dbg(1, debug, sd,
    482			 "Selecting 50 Hz SECAM video Standard\n");
    483		inittab = saa7127_init_config_50hz_secam;
    484		state->reg_61 = SAA7127_50HZ_SECAM_DAC_CONTROL;
    485
    486	} else {
    487		v4l2_dbg(1, debug, sd, "Selecting 50 Hz PAL video Standard\n");
    488		inittab = saa7127_init_config_50hz_pal;
    489		state->reg_61 = SAA7127_50HZ_PAL_DAC_CONTROL;
    490	}
    491
    492	/* Write Table */
    493	saa7127_write_inittab(sd, inittab);
    494	state->std = std;
    495	return 0;
    496}
    497
    498/* ----------------------------------------------------------------------- */
    499
    500static int saa7127_set_output_type(struct v4l2_subdev *sd, int output)
    501{
    502	struct saa7127_state *state = to_state(sd);
    503
    504	switch (output) {
    505	case SAA7127_OUTPUT_TYPE_RGB:
    506		state->reg_2d = 0x0f;	/* RGB + CVBS (for sync) */
    507		state->reg_3a = 0x13;	/* by default switch YUV to RGB-matrix on */
    508		break;
    509
    510	case SAA7127_OUTPUT_TYPE_COMPOSITE:
    511		if (state->ident == SAA7129)
    512			state->reg_2d = 0x20;	/* CVBS only */
    513		else
    514			state->reg_2d = 0x08;	/* 00001000 CVBS only, RGB DAC's off (high impedance mode) */
    515		state->reg_3a = 0x13;	/* by default switch YUV to RGB-matrix on */
    516		break;
    517
    518	case SAA7127_OUTPUT_TYPE_SVIDEO:
    519		if (state->ident == SAA7129)
    520			state->reg_2d = 0x18;	/* Y + C */
    521		else
    522			state->reg_2d = 0xff;   /*11111111  croma -> R, luma -> CVBS + G + B */
    523		state->reg_3a = 0x13;	/* by default switch YUV to RGB-matrix on */
    524		break;
    525
    526	case SAA7127_OUTPUT_TYPE_YUV_V:
    527		state->reg_2d = 0x4f;	/* reg 2D = 01001111, all DAC's on, RGB + VBS */
    528		state->reg_3a = 0x0b;	/* reg 3A = 00001011, bypass RGB-matrix */
    529		break;
    530
    531	case SAA7127_OUTPUT_TYPE_YUV_C:
    532		state->reg_2d = 0x0f;	/* reg 2D = 00001111, all DAC's on, RGB + CVBS */
    533		state->reg_3a = 0x0b;	/* reg 3A = 00001011, bypass RGB-matrix */
    534		break;
    535
    536	case SAA7127_OUTPUT_TYPE_BOTH:
    537		if (state->ident == SAA7129)
    538			state->reg_2d = 0x38;
    539		else
    540			state->reg_2d = 0xbf;
    541		state->reg_3a = 0x13;	/* by default switch YUV to RGB-matrix on */
    542		break;
    543
    544	default:
    545		return -EINVAL;
    546	}
    547	v4l2_dbg(1, debug, sd,
    548		"Selecting %s output type\n", output_strs[output]);
    549
    550	/* Configure Encoder */
    551	saa7127_write(sd, 0x2d, state->reg_2d);
    552	saa7127_write(sd, 0x3a, state->reg_3a | state->reg_3a_cb);
    553	state->output_type = output;
    554	return 0;
    555}
    556
    557/* ----------------------------------------------------------------------- */
    558
    559static int saa7127_set_input_type(struct v4l2_subdev *sd, int input)
    560{
    561	struct saa7127_state *state = to_state(sd);
    562
    563	switch (input) {
    564	case SAA7127_INPUT_TYPE_NORMAL:	/* avia */
    565		v4l2_dbg(1, debug, sd, "Selecting Normal Encoder Input\n");
    566		state->reg_3a_cb = 0;
    567		break;
    568
    569	case SAA7127_INPUT_TYPE_TEST_IMAGE:	/* color bar */
    570		v4l2_dbg(1, debug, sd, "Selecting Color Bar generator\n");
    571		state->reg_3a_cb = 0x80;
    572		break;
    573
    574	default:
    575		return -EINVAL;
    576	}
    577	saa7127_write(sd, 0x3a, state->reg_3a | state->reg_3a_cb);
    578	state->input_type = input;
    579	return 0;
    580}
    581
    582/* ----------------------------------------------------------------------- */
    583
    584static int saa7127_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
    585{
    586	struct saa7127_state *state = to_state(sd);
    587
    588	if (state->std == std)
    589		return 0;
    590	return saa7127_set_std(sd, std);
    591}
    592
    593static int saa7127_s_routing(struct v4l2_subdev *sd,
    594			     u32 input, u32 output, u32 config)
    595{
    596	struct saa7127_state *state = to_state(sd);
    597	int rc = 0;
    598
    599	if (state->input_type != input)
    600		rc = saa7127_set_input_type(sd, input);
    601	if (rc == 0 && state->output_type != output)
    602		rc = saa7127_set_output_type(sd, output);
    603	return rc;
    604}
    605
    606static int saa7127_s_stream(struct v4l2_subdev *sd, int enable)
    607{
    608	struct saa7127_state *state = to_state(sd);
    609
    610	if (state->video_enable == enable)
    611		return 0;
    612	return saa7127_set_video_enable(sd, enable);
    613}
    614
    615static int saa7127_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
    616{
    617	struct saa7127_state *state = to_state(sd);
    618
    619	memset(fmt->service_lines, 0, sizeof(fmt->service_lines));
    620	if (state->vps_enable)
    621		fmt->service_lines[0][16] = V4L2_SLICED_VPS;
    622	if (state->wss_enable)
    623		fmt->service_lines[0][23] = V4L2_SLICED_WSS_625;
    624	if (state->cc_enable) {
    625		fmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
    626		fmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
    627	}
    628	fmt->service_set =
    629		(state->vps_enable ? V4L2_SLICED_VPS : 0) |
    630		(state->wss_enable ? V4L2_SLICED_WSS_625 : 0) |
    631		(state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0);
    632	return 0;
    633}
    634
    635static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
    636{
    637	switch (data->id) {
    638	case V4L2_SLICED_WSS_625:
    639		return saa7127_set_wss(sd, data);
    640	case V4L2_SLICED_VPS:
    641		return saa7127_set_vps(sd, data);
    642	case V4L2_SLICED_CAPTION_525:
    643		if (data->field == 0)
    644			return saa7127_set_cc(sd, data);
    645		return saa7127_set_xds(sd, data);
    646	default:
    647		return -EINVAL;
    648	}
    649	return 0;
    650}
    651
    652#ifdef CONFIG_VIDEO_ADV_DEBUG
    653static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
    654{
    655	reg->val = saa7127_read(sd, reg->reg & 0xff);
    656	reg->size = 1;
    657	return 0;
    658}
    659
    660static int saa7127_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
    661{
    662	saa7127_write(sd, reg->reg & 0xff, reg->val & 0xff);
    663	return 0;
    664}
    665#endif
    666
    667static int saa7127_log_status(struct v4l2_subdev *sd)
    668{
    669	struct saa7127_state *state = to_state(sd);
    670
    671	v4l2_info(sd, "Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz");
    672	v4l2_info(sd, "Input:    %s\n", state->input_type ?  "color bars" : "normal");
    673	v4l2_info(sd, "Output:   %s\n", state->video_enable ?
    674			output_strs[state->output_type] : "disabled");
    675	v4l2_info(sd, "WSS:      %s\n", state->wss_enable ?
    676			wss_strs[state->wss_mode] : "disabled");
    677	v4l2_info(sd, "VPS:      %s\n", state->vps_enable ? "enabled" : "disabled");
    678	v4l2_info(sd, "CC:       %s\n", state->cc_enable ? "enabled" : "disabled");
    679	return 0;
    680}
    681
    682/* ----------------------------------------------------------------------- */
    683
    684static const struct v4l2_subdev_core_ops saa7127_core_ops = {
    685	.log_status = saa7127_log_status,
    686#ifdef CONFIG_VIDEO_ADV_DEBUG
    687	.g_register = saa7127_g_register,
    688	.s_register = saa7127_s_register,
    689#endif
    690};
    691
    692static const struct v4l2_subdev_video_ops saa7127_video_ops = {
    693	.s_std_output = saa7127_s_std_output,
    694	.s_routing = saa7127_s_routing,
    695	.s_stream = saa7127_s_stream,
    696};
    697
    698static const struct v4l2_subdev_vbi_ops saa7127_vbi_ops = {
    699	.s_vbi_data = saa7127_s_vbi_data,
    700	.g_sliced_fmt = saa7127_g_sliced_fmt,
    701};
    702
    703static const struct v4l2_subdev_ops saa7127_ops = {
    704	.core = &saa7127_core_ops,
    705	.video = &saa7127_video_ops,
    706	.vbi = &saa7127_vbi_ops,
    707};
    708
    709/* ----------------------------------------------------------------------- */
    710
    711static int saa7127_probe(struct i2c_client *client,
    712			 const struct i2c_device_id *id)
    713{
    714	struct saa7127_state *state;
    715	struct v4l2_subdev *sd;
    716	struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 };  /* set to disabled */
    717
    718	/* Check if the adapter supports the needed features */
    719	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
    720		return -EIO;
    721
    722	v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n",
    723			client->addr << 1);
    724
    725	state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
    726	if (state == NULL)
    727		return -ENOMEM;
    728
    729	sd = &state->sd;
    730	v4l2_i2c_subdev_init(sd, client, &saa7127_ops);
    731
    732	/* First test register 0: Bits 5-7 are a version ID (should be 0),
    733	   and bit 2 should also be 0.
    734	   This is rather general, so the second test is more specific and
    735	   looks at the 'ending point of burst in clock cycles' which is
    736	   0x1d after a reset and not expected to ever change. */
    737	if ((saa7127_read(sd, 0) & 0xe4) != 0 ||
    738			(saa7127_read(sd, 0x29) & 0x3f) != 0x1d) {
    739		v4l2_dbg(1, debug, sd, "saa7127 not found\n");
    740		return -ENODEV;
    741	}
    742
    743	if (id->driver_data) {	/* Chip type is already known */
    744		state->ident = id->driver_data;
    745	} else {		/* Needs detection */
    746		int read_result;
    747
    748		/* Detect if it's an saa7129 */
    749		read_result = saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2);
    750		saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2, 0xaa);
    751		if (saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2) == 0xaa) {
    752			saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2,
    753					read_result);
    754			state->ident = SAA7129;
    755			strscpy(client->name, "saa7129", I2C_NAME_SIZE);
    756		} else {
    757			state->ident = SAA7127;
    758			strscpy(client->name, "saa7127", I2C_NAME_SIZE);
    759		}
    760	}
    761
    762	v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
    763			client->addr << 1, client->adapter->name);
    764
    765	v4l2_dbg(1, debug, sd, "Configuring encoder\n");
    766	saa7127_write_inittab(sd, saa7127_init_config_common);
    767	saa7127_set_std(sd, V4L2_STD_NTSC);
    768	saa7127_set_output_type(sd, SAA7127_OUTPUT_TYPE_BOTH);
    769	saa7127_set_vps(sd, &vbi);
    770	saa7127_set_wss(sd, &vbi);
    771	saa7127_set_cc(sd, &vbi);
    772	saa7127_set_xds(sd, &vbi);
    773	if (test_image == 1)
    774		/* The Encoder has an internal Colorbar generator */
    775		/* This can be used for debugging */
    776		saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_TEST_IMAGE);
    777	else
    778		saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL);
    779	saa7127_set_video_enable(sd, 1);
    780
    781	if (state->ident == SAA7129)
    782		saa7127_write_inittab(sd, saa7129_init_config_extra);
    783	return 0;
    784}
    785
    786/* ----------------------------------------------------------------------- */
    787
    788static int saa7127_remove(struct i2c_client *client)
    789{
    790	struct v4l2_subdev *sd = i2c_get_clientdata(client);
    791
    792	v4l2_device_unregister_subdev(sd);
    793	/* Turn off TV output */
    794	saa7127_set_video_enable(sd, 0);
    795	return 0;
    796}
    797
    798/* ----------------------------------------------------------------------- */
    799
    800static const struct i2c_device_id saa7127_id[] = {
    801	{ "saa7127_auto", 0 },	/* auto-detection */
    802	{ "saa7126", SAA7127 },
    803	{ "saa7127", SAA7127 },
    804	{ "saa7128", SAA7129 },
    805	{ "saa7129", SAA7129 },
    806	{ }
    807};
    808MODULE_DEVICE_TABLE(i2c, saa7127_id);
    809
    810static struct i2c_driver saa7127_driver = {
    811	.driver = {
    812		.name	= "saa7127",
    813	},
    814	.probe		= saa7127_probe,
    815	.remove		= saa7127_remove,
    816	.id_table	= saa7127_id,
    817};
    818
    819module_i2c_driver(saa7127_driver);