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{
713	const struct i2c_device_id *id = i2c_client_get_device_id(client);
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 void 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}
796
797/* ----------------------------------------------------------------------- */
798
799static const struct i2c_device_id saa7127_id[] = {
800	{ "saa7127_auto", 0 },	/* auto-detection */
801	{ "saa7126", SAA7127 },
802	{ "saa7127", SAA7127 },
803	{ "saa7128", SAA7129 },
804	{ "saa7129", SAA7129 },
805	{ }
806};
807MODULE_DEVICE_TABLE(i2c, saa7127_id);
808
809static struct i2c_driver saa7127_driver = {
810	.driver = {
811		.name	= "saa7127",
812	},
813	.probe		= saa7127_probe,
814	.remove		= saa7127_remove,
815	.id_table	= saa7127_id,
816};
817
818module_i2c_driver(saa7127_driver);
819