blob: 133f9e5252fec0f0646c3d1d34e2f92d85385199 [file] [log] [blame]
Hans Verkuilcfbb5b82005-11-13 16:07:53 -08001/*
2 * saa7127 - Philips SAA7127/SAA7129 video encoder driver
3 *
4 * Copyright (C) 2003 Roy Bulter <rbulter@hetnet.nl>
5 *
6 * Based on SAA7126 video encoder driver by Gillem & Andreas Oberritter
7 *
8 * Copyright (C) 2000-2001 Gillem <htoa@gmx.net>
9 * Copyright (C) 2002 Andreas Oberritter <obi@saftware.de>
10 *
11 * Based on Stadis 4:2:2 MPEG-2 Decoder Driver by Nathan Laredo
12 *
13 * Copyright (C) 1999 Nathan Laredo <laredo@gnu.org>
14 *
15 * This driver is designed for the Hauppauge 250/350 Linux driver
16 * from the ivtv Project
17 *
18 * Copyright (C) 2003 Kevin Thayer <nufan_wfk@yahoo.com>
19 *
20 * Dual output support:
21 * Copyright (C) 2004 Eric Varsanyi
22 *
23 * NTSC Tuning and 7.5 IRE Setup
24 * Copyright (C) 2004 Chris Kennedy <c@groovy.org>
25 *
26 * VBI additions & cleanup:
27 * Copyright (C) 2004, 2005 Hans Verkuil <hverkuil@xs4all.nl>
28 *
29 * Note: the saa7126 is identical to the saa7127, and the saa7128 is
30 * identical to the saa7129, except that the saa7126 and saa7128 have
31 * macrovision anti-taping support. This driver will almost certainly
32 * work find for those chips, except of course for the missing anti-taping
33 * support.
34 *
35 * This program is free software; you can redistribute it and/or modify
36 * it under the terms of the GNU General Public License as published by
37 * the Free Software Foundation; either version 2 of the License, or
38 * (at your option) any later version.
39 *
40 * This program is distributed in the hope that it will be useful,
41 * but WITHOUT ANY WARRANTY; without even the implied warranty of
42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43 * GNU General Public License for more details.
44 *
45 * You should have received a copy of the GNU General Public License
46 * along with this program; if not, write to the Free Software
47 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
48 */
49
50
51#include <linux/kernel.h>
52#include <linux/module.h>
53#include <linux/slab.h>
54#include <linux/i2c.h>
55#include <linux/videodev2.h>
Hans Verkuilcfbb5b82005-11-13 16:07:53 -080056#include <media/v4l2-common.h>
Hans Verkuil39b6f682006-03-25 09:50:20 -030057#include <media/saa7127.h>
Hans Verkuilcfbb5b82005-11-13 16:07:53 -080058
59static int debug = 0;
60static int test_image = 0;
61
62MODULE_DESCRIPTION("Philips SAA7127/9 video encoder driver");
Hans Verkuil1f4b3362005-11-13 16:08:05 -080063MODULE_AUTHOR("Kevin Thayer, Chris Kennedy, Hans Verkuil");
Hans Verkuilcfbb5b82005-11-13 16:07:53 -080064MODULE_LICENSE("GPL");
65module_param(debug, int, 0644);
66module_param(test_image, int, 0644);
67MODULE_PARM_DESC(debug, "debug level (0-2)");
68MODULE_PARM_DESC(test_image, "test_image (0-1)");
69
Hans Verkuilcfbb5b82005-11-13 16:07:53 -080070static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
71
72
73I2C_CLIENT_INSMOD;
74
75/*
76 * SAA7127 registers
77 */
78
79#define SAA7127_REG_STATUS 0x00
80#define SAA7127_REG_WIDESCREEN_CONFIG 0x26
81#define SAA7127_REG_WIDESCREEN_ENABLE 0x27
82#define SAA7127_REG_BURST_START 0x28
83#define SAA7127_REG_BURST_END 0x29
84#define SAA7127_REG_COPYGEN_0 0x2a
85#define SAA7127_REG_COPYGEN_1 0x2b
86#define SAA7127_REG_COPYGEN_2 0x2c
87#define SAA7127_REG_OUTPUT_PORT_CONTROL 0x2d
88#define SAA7127_REG_GAIN_LUMINANCE_RGB 0x38
89#define SAA7127_REG_GAIN_COLORDIFF_RGB 0x39
90#define SAA7127_REG_INPUT_PORT_CONTROL_1 0x3a
91#define SAA7129_REG_FADE_KEY_COL2 0x4f
92#define SAA7127_REG_CHROMA_PHASE 0x5a
93#define SAA7127_REG_GAINU 0x5b
94#define SAA7127_REG_GAINV 0x5c
95#define SAA7127_REG_BLACK_LEVEL 0x5d
96#define SAA7127_REG_BLANKING_LEVEL 0x5e
97#define SAA7127_REG_VBI_BLANKING 0x5f
98#define SAA7127_REG_DAC_CONTROL 0x61
99#define SAA7127_REG_BURST_AMP 0x62
100#define SAA7127_REG_SUBC3 0x63
101#define SAA7127_REG_SUBC2 0x64
102#define SAA7127_REG_SUBC1 0x65
103#define SAA7127_REG_SUBC0 0x66
104#define SAA7127_REG_LINE_21_ODD_0 0x67
105#define SAA7127_REG_LINE_21_ODD_1 0x68
106#define SAA7127_REG_LINE_21_EVEN_0 0x69
107#define SAA7127_REG_LINE_21_EVEN_1 0x6a
108#define SAA7127_REG_RCV_PORT_CONTROL 0x6b
109#define SAA7127_REG_VTRIG 0x6c
110#define SAA7127_REG_HTRIG_HI 0x6d
111#define SAA7127_REG_MULTI 0x6e
112#define SAA7127_REG_CLOSED_CAPTION 0x6f
113#define SAA7127_REG_RCV2_OUTPUT_START 0x70
114#define SAA7127_REG_RCV2_OUTPUT_END 0x71
115#define SAA7127_REG_RCV2_OUTPUT_MSBS 0x72
116#define SAA7127_REG_TTX_REQUEST_H_START 0x73
117#define SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH 0x74
118#define SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT 0x75
119#define SAA7127_REG_TTX_ODD_REQ_VERT_START 0x76
120#define SAA7127_REG_TTX_ODD_REQ_VERT_END 0x77
121#define SAA7127_REG_TTX_EVEN_REQ_VERT_START 0x78
122#define SAA7127_REG_TTX_EVEN_REQ_VERT_END 0x79
123#define SAA7127_REG_FIRST_ACTIVE 0x7a
124#define SAA7127_REG_LAST_ACTIVE 0x7b
125#define SAA7127_REG_MSB_VERTICAL 0x7c
126#define SAA7127_REG_DISABLE_TTX_LINE_LO_0 0x7e
127#define SAA7127_REG_DISABLE_TTX_LINE_LO_1 0x7f
128
129/*
130 **********************************************************************
131 *
132 * Arrays with configuration parameters for the SAA7127
133 *
134 **********************************************************************
135 */
136
137struct i2c_reg_value {
138 unsigned char reg;
139 unsigned char value;
140};
141
142static const struct i2c_reg_value saa7129_init_config_extra[] = {
143 { SAA7127_REG_OUTPUT_PORT_CONTROL, 0x38 },
144 { SAA7127_REG_VTRIG, 0xfa },
145};
146
147static const struct i2c_reg_value saa7127_init_config_common[] = {
148 { SAA7127_REG_WIDESCREEN_CONFIG, 0x0d },
149 { SAA7127_REG_WIDESCREEN_ENABLE, 0x00 },
150 { SAA7127_REG_COPYGEN_0, 0x77 },
151 { SAA7127_REG_COPYGEN_1, 0x41 },
152 { SAA7127_REG_COPYGEN_2, 0x00 }, /* Macrovision enable/disable */
153 { SAA7127_REG_OUTPUT_PORT_CONTROL, 0x9e },
154 { SAA7127_REG_GAIN_LUMINANCE_RGB, 0x00 },
155 { SAA7127_REG_GAIN_COLORDIFF_RGB, 0x00 },
156 { SAA7127_REG_INPUT_PORT_CONTROL_1, 0x80 }, /* for color bars */
157 { SAA7127_REG_LINE_21_ODD_0, 0x77 },
158 { SAA7127_REG_LINE_21_ODD_1, 0x41 },
159 { SAA7127_REG_LINE_21_EVEN_0, 0x88 },
160 { SAA7127_REG_LINE_21_EVEN_1, 0x41 },
161 { SAA7127_REG_RCV_PORT_CONTROL, 0x12 },
162 { SAA7127_REG_VTRIG, 0xf9 },
163 { SAA7127_REG_HTRIG_HI, 0x00 },
164 { SAA7127_REG_RCV2_OUTPUT_START, 0x41 },
165 { SAA7127_REG_RCV2_OUTPUT_END, 0xc3 },
166 { SAA7127_REG_RCV2_OUTPUT_MSBS, 0x00 },
167 { SAA7127_REG_TTX_REQUEST_H_START, 0x3e },
168 { SAA7127_REG_TTX_REQUEST_H_DELAY_LENGTH, 0xb8 },
169 { SAA7127_REG_CSYNC_ADVANCE_VSYNC_SHIFT, 0x03 },
170 { SAA7127_REG_TTX_ODD_REQ_VERT_START, 0x15 },
171 { SAA7127_REG_TTX_ODD_REQ_VERT_END, 0x16 },
172 { SAA7127_REG_TTX_EVEN_REQ_VERT_START, 0x15 },
173 { SAA7127_REG_TTX_EVEN_REQ_VERT_END, 0x16 },
174 { SAA7127_REG_FIRST_ACTIVE, 0x1a },
175 { SAA7127_REG_LAST_ACTIVE, 0x01 },
176 { SAA7127_REG_MSB_VERTICAL, 0xc0 },
177 { SAA7127_REG_DISABLE_TTX_LINE_LO_0, 0x00 },
178 { SAA7127_REG_DISABLE_TTX_LINE_LO_1, 0x00 },
179 { 0, 0 }
180};
181
182#define SAA7127_60HZ_DAC_CONTROL 0x15
183static const struct i2c_reg_value saa7127_init_config_60hz[] = {
184 { SAA7127_REG_BURST_START, 0x19 },
185 /* BURST_END is also used as a chip ID in saa7127_detect_client */
186 { SAA7127_REG_BURST_END, 0x1d },
187 { SAA7127_REG_CHROMA_PHASE, 0xa3 },
188 { SAA7127_REG_GAINU, 0x98 },
189 { SAA7127_REG_GAINV, 0xd3 },
190 { SAA7127_REG_BLACK_LEVEL, 0x39 },
191 { SAA7127_REG_BLANKING_LEVEL, 0x2e },
192 { SAA7127_REG_VBI_BLANKING, 0x2e },
193 { SAA7127_REG_DAC_CONTROL, 0x15 },
194 { SAA7127_REG_BURST_AMP, 0x4d },
195 { SAA7127_REG_SUBC3, 0x1f },
196 { SAA7127_REG_SUBC2, 0x7c },
197 { SAA7127_REG_SUBC1, 0xf0 },
198 { SAA7127_REG_SUBC0, 0x21 },
199 { SAA7127_REG_MULTI, 0x90 },
200 { SAA7127_REG_CLOSED_CAPTION, 0x11 },
201 { 0, 0 }
202};
203
204#define SAA7127_50HZ_DAC_CONTROL 0x02
Mauro Carvalho Chehab769e2432005-12-01 00:51:35 -0800205static struct i2c_reg_value saa7127_init_config_50hz[] = {
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800206 { SAA7127_REG_BURST_START, 0x21 },
207 /* BURST_END is also used as a chip ID in saa7127_detect_client */
208 { SAA7127_REG_BURST_END, 0x1d },
209 { SAA7127_REG_CHROMA_PHASE, 0x3f },
210 { SAA7127_REG_GAINU, 0x7d },
211 { SAA7127_REG_GAINV, 0xaf },
212 { SAA7127_REG_BLACK_LEVEL, 0x33 },
213 { SAA7127_REG_BLANKING_LEVEL, 0x35 },
214 { SAA7127_REG_VBI_BLANKING, 0x35 },
215 { SAA7127_REG_DAC_CONTROL, 0x02 },
216 { SAA7127_REG_BURST_AMP, 0x2f },
217 { SAA7127_REG_SUBC3, 0xcb },
218 { SAA7127_REG_SUBC2, 0x8a },
219 { SAA7127_REG_SUBC1, 0x09 },
220 { SAA7127_REG_SUBC0, 0x2a },
221 { SAA7127_REG_MULTI, 0xa0 },
222 { SAA7127_REG_CLOSED_CAPTION, 0x00 },
223 { 0, 0 }
224};
225
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800226/*
227 **********************************************************************
228 *
229 * Encoder Struct, holds the configuration state of the encoder
230 *
231 **********************************************************************
232 */
233
234struct saa7127_state {
235 v4l2_std_id std;
236 enum v4l2_chip_ident ident;
237 enum saa7127_input_type input_type;
238 enum saa7127_output_type output_type;
239 int video_enable;
240 int wss_enable;
241 u16 wss_mode;
242 int cc_enable;
243 u16 cc_data;
244 int xds_enable;
245 u16 xds_data;
246 int vps_enable;
247 u8 vps_data[5];
248 u8 reg_2d;
249 u8 reg_3a;
250 u8 reg_3a_cb; /* colorbar bit */
251 u8 reg_61;
252};
253
254static const char * const output_strs[] =
255{
256 "S-Video + Composite",
257 "Composite",
258 "S-Video",
259 "RGB",
260 "YUV C",
261 "YUV V"
262};
263
264static const char * const wss_strs[] = {
265 "invalid",
266 "letterbox 14:9 center",
267 "letterbox 14:9 top",
268 "invalid",
269 "letterbox 16:9 top",
270 "invalid",
271 "invalid",
272 "16:9 full format anamorphic"
273 "4:3 full format",
274 "invalid",
275 "invalid",
276 "letterbox 16:9 center",
277 "invalid",
278 "letterbox >16:9 center",
279 "14:9 full format center",
280 "invalid",
281};
282
283/* ----------------------------------------------------------------------- */
284
285static int saa7127_read(struct i2c_client *client, u8 reg)
286{
287 return i2c_smbus_read_byte_data(client, reg);
288}
289
290/* ----------------------------------------------------------------------- */
291
292static int saa7127_write(struct i2c_client *client, u8 reg, u8 val)
293{
294 int i;
295
296 for (i = 0; i < 3; i++) {
297 if (i2c_smbus_write_byte_data(client, reg, val) == 0)
298 return 0;
299 }
Hans Verkuilfac9e892006-01-09 15:32:40 -0200300 v4l_err(client, "I2C Write Problem\n");
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800301 return -1;
302}
303
304/* ----------------------------------------------------------------------- */
305
306static int saa7127_write_inittab(struct i2c_client *client,
307 const struct i2c_reg_value *regs)
308{
309 while (regs->reg != 0) {
310 saa7127_write(client, regs->reg, regs->value);
311 regs++;
312 }
313 return 0;
314}
315
316/* ----------------------------------------------------------------------- */
317
318static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_data *data)
319{
Andrew Morton419d4e72005-11-13 16:07:55 -0800320 struct saa7127_state *state = i2c_get_clientdata(client);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800321 int enable = (data->line != 0);
322
323 if (enable && (data->field != 0 || data->line != 16))
324 return -EINVAL;
325 if (state->vps_enable != enable) {
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200326 v4l_dbg(1, debug, client, "Turn VPS Signal %s\n", enable ? "on" : "off");
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800327 saa7127_write(client, 0x54, enable << 7);
328 state->vps_enable = enable;
329 }
330 if (!enable)
331 return 0;
332
333 state->vps_data[0] = data->data[4];
334 state->vps_data[1] = data->data[10];
335 state->vps_data[2] = data->data[11];
336 state->vps_data[3] = data->data[12];
337 state->vps_data[4] = data->data[13];
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200338 v4l_dbg(1, debug, client, "Set VPS data %02x %02x %02x %02x %02x\n",
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800339 state->vps_data[0], state->vps_data[1],
340 state->vps_data[2], state->vps_data[3],
341 state->vps_data[4]);
342 saa7127_write(client, 0x55, state->vps_data[0]);
343 saa7127_write(client, 0x56, state->vps_data[1]);
344 saa7127_write(client, 0x57, state->vps_data[2]);
345 saa7127_write(client, 0x58, state->vps_data[3]);
346 saa7127_write(client, 0x59, state->vps_data[4]);
347 return 0;
348}
349
350/* ----------------------------------------------------------------------- */
351
352static int saa7127_set_cc(struct i2c_client *client, struct v4l2_sliced_vbi_data *data)
353{
Andrew Morton419d4e72005-11-13 16:07:55 -0800354 struct saa7127_state *state = i2c_get_clientdata(client);
Hans Verkuil515432a2005-12-20 09:48:29 -0200355 u16 cc = data->data[1] << 8 | data->data[0];
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800356 int enable = (data->line != 0);
357
358 if (enable && (data->field != 0 || data->line != 21))
359 return -EINVAL;
360 if (state->cc_enable != enable) {
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200361 v4l_dbg(1, debug, client, "Turn CC %s\n", enable ? "on" : "off");
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800362 saa7127_write(client, SAA7127_REG_CLOSED_CAPTION,
Hans Verkuil515432a2005-12-20 09:48:29 -0200363 (state->xds_enable << 7) | (enable << 6) | 0x11);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800364 state->cc_enable = enable;
365 }
366 if (!enable)
367 return 0;
368
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200369 v4l_dbg(2, debug, client, "CC data: %04x\n", cc);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800370 saa7127_write(client, SAA7127_REG_LINE_21_ODD_0, cc & 0xff);
371 saa7127_write(client, SAA7127_REG_LINE_21_ODD_1, cc >> 8);
372 state->cc_data = cc;
373 return 0;
374}
375
376/* ----------------------------------------------------------------------- */
377
378static int saa7127_set_xds(struct i2c_client *client, struct v4l2_sliced_vbi_data *data)
379{
Andrew Morton419d4e72005-11-13 16:07:55 -0800380 struct saa7127_state *state = i2c_get_clientdata(client);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800381 u16 xds = data->data[1] << 8 | data->data[0];
382 int enable = (data->line != 0);
383
384 if (enable && (data->field != 1 || data->line != 21))
385 return -EINVAL;
386 if (state->xds_enable != enable) {
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200387 v4l_dbg(1, debug, client, "Turn XDS %s\n", enable ? "on" : "off");
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800388 saa7127_write(client, SAA7127_REG_CLOSED_CAPTION,
Hans Verkuil515432a2005-12-20 09:48:29 -0200389 (enable << 7) | (state->cc_enable << 6) | 0x11);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800390 state->xds_enable = enable;
391 }
392 if (!enable)
393 return 0;
394
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200395 v4l_dbg(2, debug, client, "XDS data: %04x\n", xds);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800396 saa7127_write(client, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff);
397 saa7127_write(client, SAA7127_REG_LINE_21_EVEN_1, xds >> 8);
398 state->xds_data = xds;
399 return 0;
400}
401
402/* ----------------------------------------------------------------------- */
403
404static int saa7127_set_wss(struct i2c_client *client, struct v4l2_sliced_vbi_data *data)
405{
Andrew Morton419d4e72005-11-13 16:07:55 -0800406 struct saa7127_state *state = i2c_get_clientdata(client);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800407 int enable = (data->line != 0);
408
409 if (enable && (data->field != 0 || data->line != 23))
410 return -EINVAL;
411 if (state->wss_enable != enable) {
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200412 v4l_dbg(1, debug, client, "Turn WSS %s\n", enable ? "on" : "off");
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800413 saa7127_write(client, 0x27, enable << 7);
414 state->wss_enable = enable;
415 }
416 if (!enable)
417 return 0;
418
419 saa7127_write(client, 0x26, data->data[0]);
420 saa7127_write(client, 0x27, 0x80 | (data->data[1] & 0x3f));
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200421 v4l_dbg(1, debug, client, "WSS mode: %s\n", wss_strs[data->data[0] & 0xf]);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800422 state->wss_mode = (data->data[1] & 0x3f) << 8 | data->data[0];
423 return 0;
424}
425
426/* ----------------------------------------------------------------------- */
427
428static int saa7127_set_video_enable(struct i2c_client *client, int enable)
429{
Andrew Morton419d4e72005-11-13 16:07:55 -0800430 struct saa7127_state *state = i2c_get_clientdata(client);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800431
432 if (enable) {
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200433 v4l_dbg(1, debug, client, "Enable Video Output\n");
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800434 saa7127_write(client, 0x2d, state->reg_2d);
435 saa7127_write(client, 0x61, state->reg_61);
436 } else {
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200437 v4l_dbg(1, debug, client, "Disable Video Output\n");
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800438 saa7127_write(client, 0x2d, (state->reg_2d & 0xf0));
439 saa7127_write(client, 0x61, (state->reg_61 | 0xc0));
440 }
441 state->video_enable = enable;
442 return 0;
443}
444
445/* ----------------------------------------------------------------------- */
446
447static int saa7127_set_std(struct i2c_client *client, v4l2_std_id std)
448{
Andrew Morton419d4e72005-11-13 16:07:55 -0800449 struct saa7127_state *state = i2c_get_clientdata(client);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800450 const struct i2c_reg_value *inittab;
451
452 if (std & V4L2_STD_525_60) {
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200453 v4l_dbg(1, debug, client, "Selecting 60 Hz video Standard\n");
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800454 inittab = saa7127_init_config_60hz;
455 state->reg_61 = SAA7127_60HZ_DAC_CONTROL;
456 } else {
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200457 v4l_dbg(1, debug, client, "Selecting 50 Hz video Standard\n");
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800458 inittab = saa7127_init_config_50hz;
459 state->reg_61 = SAA7127_50HZ_DAC_CONTROL;
460 }
461
462 /* Write Table */
463 saa7127_write_inittab(client, inittab);
464 state->std = std;
465 return 0;
466}
467
468/* ----------------------------------------------------------------------- */
469
470static int saa7127_set_output_type(struct i2c_client *client, int output)
471{
Andrew Morton419d4e72005-11-13 16:07:55 -0800472 struct saa7127_state *state = i2c_get_clientdata(client);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800473
474 switch (output) {
475 case SAA7127_OUTPUT_TYPE_RGB:
476 state->reg_2d = 0x0f; /* RGB + CVBS (for sync) */
477 state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */
478 break;
479
480 case SAA7127_OUTPUT_TYPE_COMPOSITE:
481 state->reg_2d = 0x08; /* 00001000 CVBS only, RGB DAC's off (high impedance mode) */
482 state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */
483 break;
484
485 case SAA7127_OUTPUT_TYPE_SVIDEO:
486 state->reg_2d = 0xff; /* 11111111 croma -> R, luma -> CVBS + G + B */
487 state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */
488 break;
489
490 case SAA7127_OUTPUT_TYPE_YUV_V:
491 state->reg_2d = 0x4f; /* reg 2D = 01001111, all DAC's on, RGB + VBS */
492 state->reg_3a = 0x0b; /* reg 3A = 00001011, bypass RGB-matrix */
493 break;
494
495 case SAA7127_OUTPUT_TYPE_YUV_C:
496 state->reg_2d = 0x0f; /* reg 2D = 00001111, all DAC's on, RGB + CVBS */
497 state->reg_3a = 0x0b; /* reg 3A = 00001011, bypass RGB-matrix */
498 break;
499
500 case SAA7127_OUTPUT_TYPE_BOTH:
501 state->reg_2d = 0xbf;
502 state->reg_3a = 0x13; /* by default switch YUV to RGB-matrix on */
503 break;
504
505 default:
506 return -EINVAL;
507 }
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200508 v4l_dbg(1, debug, client, "Selecting %s output type\n", output_strs[output]);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800509
510 /* Configure Encoder */
511 saa7127_write(client, 0x2d, state->reg_2d);
512 saa7127_write(client, 0x3a, state->reg_3a | state->reg_3a_cb);
513 state->output_type = output;
514 return 0;
515}
516
517/* ----------------------------------------------------------------------- */
518
519static int saa7127_set_input_type(struct i2c_client *client, int input)
520{
Andrew Morton419d4e72005-11-13 16:07:55 -0800521 struct saa7127_state *state = i2c_get_clientdata(client);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800522
523 switch (input) {
524 case SAA7127_INPUT_TYPE_NORMAL: /* avia */
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200525 v4l_dbg(1, debug, client, "Selecting Normal Encoder Input\n");
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800526 state->reg_3a_cb = 0;
527 break;
528
529 case SAA7127_INPUT_TYPE_TEST_IMAGE: /* color bar */
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200530 v4l_dbg(1, debug, client, "Selecting Color Bar generator\n");
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800531 state->reg_3a_cb = 0x80;
532 break;
533
534 default:
535 return -EINVAL;
536 }
537 saa7127_write(client, 0x3a, state->reg_3a | state->reg_3a_cb);
538 state->input_type = input;
539 return 0;
540}
541
542/* ----------------------------------------------------------------------- */
543
544static int saa7127_command(struct i2c_client *client,
545 unsigned int cmd, void *arg)
546{
547 struct saa7127_state *state = i2c_get_clientdata(client);
548 struct v4l2_format *fmt = arg;
Hans Verkuil39b6f682006-03-25 09:50:20 -0300549 struct v4l2_routing *route = arg;
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800550
551 switch (cmd) {
552 case VIDIOC_S_STD:
553 if (state->std == *(v4l2_std_id *)arg)
554 break;
555 return saa7127_set_std(client, *(v4l2_std_id *)arg);
556
557 case VIDIOC_G_STD:
558 *(v4l2_std_id *)arg = state->std;
559 break;
560
Hans Verkuil39b6f682006-03-25 09:50:20 -0300561 case VIDIOC_INT_G_VIDEO_ROUTING:
562 route->input = state->input_type;
563 route->output = state->output_type;
564 break;
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800565
Hans Verkuil39b6f682006-03-25 09:50:20 -0300566 case VIDIOC_INT_S_VIDEO_ROUTING:
567 {
568 int rc = 0;
569
570 if (state->input_type != route->input) {
571 rc = saa7127_set_input_type(client, route->input);
572 }
573 if (rc == 0 && state->output_type != route->output) {
574 rc = saa7127_set_output_type(client, route->output);
575 }
576 return rc;
577 }
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800578
579 case VIDIOC_STREAMON:
580 case VIDIOC_STREAMOFF:
581 if (state->video_enable == (cmd == VIDIOC_STREAMON))
582 break;
583 return saa7127_set_video_enable(client, cmd == VIDIOC_STREAMON);
584
585 case VIDIOC_G_FMT:
586 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
587 return -EINVAL;
588
589 memset(&fmt->fmt.sliced, 0, sizeof(fmt->fmt.sliced));
590 if (state->vps_enable)
591 fmt->fmt.sliced.service_lines[0][16] = V4L2_SLICED_VPS;
592 if (state->wss_enable)
593 fmt->fmt.sliced.service_lines[0][23] = V4L2_SLICED_WSS_625;
594 if (state->cc_enable) {
595 fmt->fmt.sliced.service_lines[0][21] = V4L2_SLICED_CAPTION_525;
596 fmt->fmt.sliced.service_lines[1][21] = V4L2_SLICED_CAPTION_525;
597 }
598 fmt->fmt.sliced.service_set =
599 (state->vps_enable ? V4L2_SLICED_VPS : 0) |
600 (state->wss_enable ? V4L2_SLICED_WSS_625 : 0) |
601 (state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0);
602 break;
603
604 case VIDIOC_LOG_STATUS:
Hans Verkuilfac9e892006-01-09 15:32:40 -0200605 v4l_info(client, "Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz");
606 v4l_info(client, "Input: %s\n", state->input_type ? "color bars" : "normal");
607 v4l_info(client, "Output: %s\n", state->video_enable ?
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800608 output_strs[state->output_type] : "disabled");
Hans Verkuilfac9e892006-01-09 15:32:40 -0200609 v4l_info(client, "WSS: %s\n", state->wss_enable ?
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800610 wss_strs[state->wss_mode] : "disabled");
Hans Verkuilfac9e892006-01-09 15:32:40 -0200611 v4l_info(client, "VPS: %s\n", state->vps_enable ? "enabled" : "disabled");
612 v4l_info(client, "CC: %s\n", state->cc_enable ? "enabled" : "disabled");
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800613 break;
614
615#ifdef CONFIG_VIDEO_ADV_DEBUG
616 case VIDIOC_INT_G_REGISTER:
617 {
618 struct v4l2_register *reg = arg;
619
620 if (reg->i2c_id != I2C_DRIVERID_SAA7127)
621 return -EINVAL;
622 reg->val = saa7127_read(client, reg->reg & 0xff);
623 break;
624 }
625
626 case VIDIOC_INT_S_REGISTER:
627 {
628 struct v4l2_register *reg = arg;
629
630 if (reg->i2c_id != I2C_DRIVERID_SAA7127)
631 return -EINVAL;
632 if (!capable(CAP_SYS_ADMIN))
633 return -EPERM;
634 saa7127_write(client, reg->reg & 0xff, reg->val & 0xff);
635 break;
636 }
637#endif
638
639 case VIDIOC_INT_S_VBI_DATA:
640 {
641 struct v4l2_sliced_vbi_data *data = arg;
642
643 switch (data->id) {
644 case V4L2_SLICED_WSS_625:
645 return saa7127_set_wss(client, data);
646 case V4L2_SLICED_VPS:
647 return saa7127_set_vps(client, data);
648 case V4L2_SLICED_CAPTION_525:
649 if (data->field == 0)
650 return saa7127_set_cc(client, data);
651 return saa7127_set_xds(client, data);
652 default:
653 return -EINVAL;
654 }
655 break;
656 }
657
658 case VIDIOC_INT_G_CHIP_IDENT:
659 *(enum v4l2_chip_ident *)arg = state->ident;
660 break;
661
662 default:
663 return -EINVAL;
664 }
665 return 0;
666}
667
668/* ----------------------------------------------------------------------- */
669
Mauro Carvalho Chehab769e2432005-12-01 00:51:35 -0800670static struct i2c_driver i2c_driver_saa7127;
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800671
672/* ----------------------------------------------------------------------- */
673
674static int saa7127_attach(struct i2c_adapter *adapter, int address, int kind)
675{
676 struct i2c_client *client;
677 struct saa7127_state *state;
678 struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 }; /* set to disabled */
679 int read_result = 0;
680
681 /* Check if the adapter supports the needed features */
682 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
683 return 0;
684
Panagiotis Issaris74081872006-01-11 19:40:56 -0200685 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800686 if (client == 0)
687 return -ENOMEM;
688
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800689 client->addr = address;
690 client->adapter = adapter;
691 client->driver = &i2c_driver_saa7127;
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800692 snprintf(client->name, sizeof(client->name) - 1, "saa7127");
693
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200694 v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n", address << 1);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800695
696 /* First test register 0: Bits 5-7 are a version ID (should be 0),
697 and bit 2 should also be 0.
698 This is rather general, so the second test is more specific and
699 looks at the 'ending point of burst in clock cycles' which is
700 0x1d after a reset and not expected to ever change. */
701 if ((saa7127_read(client, 0) & 0xe4) != 0 ||
702 (saa7127_read(client, 0x29) & 0x3f) != 0x1d) {
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200703 v4l_dbg(1, debug, client, "saa7127 not found\n");
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800704 kfree(client);
705 return 0;
706 }
Panagiotis Issaris74081872006-01-11 19:40:56 -0200707 state = kzalloc(sizeof(struct saa7127_state), GFP_KERNEL);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800708
709 if (state == NULL) {
710 kfree(client);
711 return (-ENOMEM);
712 }
713
714 i2c_set_clientdata(client, state);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800715
716 /* Configure Encoder */
717
Mauro Carvalho Chehabf167cb4e2006-01-11 19:41:49 -0200718 v4l_dbg(1, debug, client, "Configuring encoder\n");
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800719 saa7127_write_inittab(client, saa7127_init_config_common);
720 saa7127_set_std(client, V4L2_STD_NTSC);
721 saa7127_set_output_type(client, SAA7127_OUTPUT_TYPE_BOTH);
722 saa7127_set_vps(client, &vbi);
723 saa7127_set_wss(client, &vbi);
724 saa7127_set_cc(client, &vbi);
725 saa7127_set_xds(client, &vbi);
726 if (test_image == 1) {
727 /* The Encoder has an internal Colorbar generator */
728 /* This can be used for debugging */
729 saa7127_set_input_type(client, SAA7127_INPUT_TYPE_TEST_IMAGE);
730 } else {
731 saa7127_set_input_type(client, SAA7127_INPUT_TYPE_NORMAL);
732 }
733 saa7127_set_video_enable(client, 1);
734
735 /* Detect if it's an saa7129 */
736 read_result = saa7127_read(client, SAA7129_REG_FADE_KEY_COL2);
737 saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, 0xaa);
738 if (saa7127_read(client, SAA7129_REG_FADE_KEY_COL2) == 0xaa) {
Hans Verkuilfac9e892006-01-09 15:32:40 -0200739 v4l_info(client, "saa7129 found @ 0x%x (%s)\n", address << 1, adapter->name);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800740 saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, read_result);
741 saa7127_write_inittab(client, saa7129_init_config_extra);
742 state->ident = V4L2_IDENT_SAA7129;
743 } else {
Hans Verkuilfac9e892006-01-09 15:32:40 -0200744 v4l_info(client, "saa7127 found @ 0x%x (%s)\n", address << 1, adapter->name);
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800745 state->ident = V4L2_IDENT_SAA7127;
746 }
747
748 i2c_attach_client(client);
749
750 return 0;
751}
752
753/* ----------------------------------------------------------------------- */
754
755static int saa7127_probe(struct i2c_adapter *adapter)
756{
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800757 if (adapter->class & I2C_CLASS_TV_ANALOG)
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800758 return i2c_probe(adapter, &addr_data, saa7127_attach);
759 return 0;
760}
761
762/* ----------------------------------------------------------------------- */
763
764static int saa7127_detach(struct i2c_client *client)
765{
766 struct saa7127_state *state = i2c_get_clientdata(client);
767 int err;
768
769 /* Turn off TV output */
770 saa7127_set_video_enable(client, 0);
771
772 err = i2c_detach_client(client);
773
774 if (err) {
775 return err;
776 }
777
778 kfree(state);
779 kfree(client);
780 return 0;
781}
782
783/* ----------------------------------------------------------------------- */
784
Mauro Carvalho Chehab769e2432005-12-01 00:51:35 -0800785static struct i2c_driver i2c_driver_saa7127 = {
Laurent Riffard604f28e2005-11-26 20:43:39 +0100786 .driver = {
Laurent Riffard604f28e2005-11-26 20:43:39 +0100787 .name = "saa7127",
788 },
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800789 .id = I2C_DRIVERID_SAA7127,
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800790 .attach_adapter = saa7127_probe,
791 .detach_client = saa7127_detach,
792 .command = saa7127_command,
Hans Verkuilcfbb5b82005-11-13 16:07:53 -0800793};
794
795
796/* ----------------------------------------------------------------------- */
797
798static int __init saa7127_init_module(void)
799{
800 return i2c_add_driver(&i2c_driver_saa7127);
801}
802
803/* ----------------------------------------------------------------------- */
804
805static void __exit saa7127_cleanup_module(void)
806{
807 i2c_del_driver(&i2c_driver_saa7127);
808}
809
810/* ----------------------------------------------------------------------- */
811
812module_init(saa7127_init_module);
813module_exit(saa7127_cleanup_module);