V4L/DVB (4597): Improve resolution limit enforcements in pvrusb2
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / media / video / saa7115.c
CommitLineData
89f75ffc
MCC
1/* saa711x - Philips SAA711x video decoder driver
2 * This driver can work with saa7111, saa7111a, saa7113, saa7114,
3 * saa7115 and saa7118.
e19b2fcc
HV
4 *
5 * Based on saa7114 driver by Maxim Yevtyushkin, which is based on
6 * the saa7111 driver by Dave Perks.
7 *
8 * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
9 * Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
10 *
11 * Slight changes for video timing and attachment output by
12 * Wolfgang Scherr <scherr@net4you.net>
13 *
14 * Moved over to the linux >= 2.4.x i2c protocol (1/1/2003)
15 * by Ronald Bultje <rbultje@ronald.bitfreak.net>
16 *
17 * Added saa7115 support by Kevin Thayer <nufan_wfk at yahoo.com>
18 * (2/17/2003)
19 *
20 * VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@xs4all.nl>
89f75ffc
MCC
21 *
22 * Copyright (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
23 * SAA7111, SAA7113 and SAA7118 support
e19b2fcc
HV
24 *
25 * This program is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU General Public License
27 * as published by the Free Software Foundation; either version 2
28 * of the License, or (at your option) any later version.
29 *
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
34 *
35 * You should have received a copy of the GNU General Public License
36 * along with this program; if not, write to the Free Software
37 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
38 */
39
96ecfc4e 40#include "saa711x_regs.h"
e19b2fcc
HV
41
42#include <linux/kernel.h>
43#include <linux/module.h>
44#include <linux/slab.h>
45#include <linux/i2c.h>
46#include <linux/videodev2.h>
e19b2fcc 47#include <media/v4l2-common.h>
1f8f5fa9 48#include <media/saa7115.h>
3578d3dd 49#include <asm/div64.h>
e19b2fcc 50
d9dce96f
MCC
51#define HRES_60HZ (480+16)
52
89f75ffc 53MODULE_DESCRIPTION("Philips SAA7111/SAA7113/SAA7114/SAA7115/SAA7118 video decoder driver");
f5762e44
MCC
54MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
55 "Hans Verkuil, Mauro Carvalho Chehab");
e19b2fcc
HV
56MODULE_LICENSE("GPL");
57
58static int debug = 0;
fac9e899 59module_param(debug, bool, 0644);
e19b2fcc
HV
60
61MODULE_PARM_DESC(debug, "Debug level (0-1)");
62
f5762e44 63static unsigned short normal_i2c[] = {
89f75ffc
MCC
64 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */
65 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */
f5762e44 66 I2C_CLIENT_END };
e19b2fcc
HV
67
68
69I2C_CLIENT_INSMOD;
70
66ec1193 71struct saa711x_state {
e19b2fcc
HV
72 v4l2_std_id std;
73 int input;
74 int enable;
3faeeae4 75 int radio;
e19b2fcc
HV
76 int bright;
77 int contrast;
78 int hue;
79 int sat;
d9dce96f
MCC
80 int width;
81 int height;
e19b2fcc 82 enum v4l2_chip_ident ident;
3578d3dd 83 u32 audclk_freq;
b7f8292c
HV
84 u32 crystal_freq;
85 u8 ucgc;
86 u8 cgcdiv;
87 u8 apll;
e19b2fcc
HV
88};
89
90/* ----------------------------------------------------------------------- */
91
66ec1193 92static inline int saa711x_write(struct i2c_client *client, u8 reg, u8 value)
e19b2fcc
HV
93{
94 return i2c_smbus_write_byte_data(client, reg, value);
95}
96
89f75ffc
MCC
97/* Sanity routine to check if a register is present */
98static int saa711x_has_reg(const int id, const u8 reg)
99{
d9dce96f
MCC
100 if (id == V4L2_IDENT_SAA7111)
101 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
102 (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e;
103
104 /* common for saa7113/4/5/8 */
105 if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f ||
106 reg == 0xa3 || reg == 0xa7 || reg == 0xab || reg == 0xaf || (reg >= 0xb5 && reg <= 0xb7) ||
107 reg == 0xd3 || reg == 0xd7 || reg == 0xdb || reg == 0xdf || (reg >= 0xe5 && reg <= 0xe7) ||
108 reg == 0x82 || (reg >= 0x89 && reg <= 0x8e)))
109 return 0;
110
89f75ffc 111 switch (id) {
89f75ffc 112 case V4L2_IDENT_SAA7113:
d9dce96f
MCC
113 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
114 reg != 0x5d && reg < 0x63;
89f75ffc 115 case V4L2_IDENT_SAA7114:
d9dce96f
MCC
116 return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
117 (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
118 reg != 0x81 && reg < 0xf0;
89f75ffc 119 case V4L2_IDENT_SAA7115:
d9dce96f 120 return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe);
89f75ffc 121 case V4L2_IDENT_SAA7118:
d9dce96f
MCC
122 return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
123 (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
124 (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
89f75ffc 125 }
89f75ffc
MCC
126 return 1;
127}
128
66ec1193 129static int saa711x_writeregs(struct i2c_client *client, const unsigned char *regs)
e19b2fcc 130{
66ec1193 131 struct saa711x_state *state = i2c_get_clientdata(client);
e19b2fcc
HV
132 unsigned char reg, data;
133
134 while (*regs != 0x00) {
135 reg = *(regs++);
136 data = *(regs++);
89f75ffc
MCC
137
138 /* According with datasheets, reserved regs should be
139 filled with 0 - seems better not to touch on they */
140 if (saa711x_has_reg(state->ident,reg)) {
66ec1193 141 if (saa711x_write(client, reg, data) < 0)
89f75ffc 142 return -1;
d87edf26
MCC
143 } else {
144 v4l_dbg(1, debug, client, "tried to access reserved reg 0x%02x\n", reg);
89f75ffc 145 }
e19b2fcc
HV
146 }
147 return 0;
148}
149
66ec1193 150static inline int saa711x_read(struct i2c_client *client, u8 reg)
e19b2fcc
HV
151{
152 return i2c_smbus_read_byte_data(client, reg);
153}
154
155/* ----------------------------------------------------------------------- */
156
89f75ffc
MCC
157/* SAA7111 initialization table */
158static const unsigned char saa7111_init_auto_input[] = {
159 R_01_INC_DELAY, 0x00, /* reserved */
160
161 /*front end */
162 R_02_INPUT_CNTL_1, 0xd0, /* FUSE=3, GUDL=2, MODE=0 */
163 R_03_INPUT_CNTL_2, 0x23, /* HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0,
164 * GAFIX=0, GAI1=256, GAI2=256 */
165 R_04_INPUT_CNTL_3, 0x00, /* GAI1=256 */
166 R_05_INPUT_CNTL_4, 0x00, /* GAI2=256 */
167
168 /* decoder */
169 R_06_H_SYNC_START, 0xf3, /* HSB at 13(50Hz) / 17(60Hz)
170 * pixels after end of last line */
171 R_07_H_SYNC_STOP, 0xe8, /* HSS seems to be needed to
172 * work with NTSC, too */
173 R_08_SYNC_CNTL, 0xc8, /* AUFD=1, FSEL=1, EXFIL=0,
174 * VTRC=1, HPLL=0, VNOI=0 */
175 R_09_LUMA_CNTL, 0x01, /* BYPS=0, PREF=0, BPSS=0,
176 * VBLB=0, UPTCV=0, APER=1 */
177 R_0A_LUMA_BRIGHT_CNTL, 0x80,
178 R_0B_LUMA_CONTRAST_CNTL, 0x47, /* 0b - CONT=1.109 */
179 R_0C_CHROMA_SAT_CNTL, 0x40,
180 R_0D_CHROMA_HUE_CNTL, 0x00,
181 R_0E_CHROMA_CNTL_1, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0,
182 * FCTC=0, CHBW=1 */
183 R_0F_CHROMA_GAIN_CNTL, 0x00, /* reserved */
184 R_10_CHROMA_CNTL_2, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
185 R_11_MODE_DELAY_CNTL, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
186 * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
187 R_12_RT_SIGNAL_CNTL, 0x00, /* 12 - output control 2 */
188 R_13_RT_X_PORT_OUT_CNTL, 0x00, /* 13 - output control 3 */
189 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
190 R_15_VGATE_START_FID_CHG, 0x00,
191 R_16_VGATE_STOP, 0x00,
192 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
193
194 0x00, 0x00
195};
196
197/* SAA7113 init codes */
198static const unsigned char saa7113_init_auto_input[] = {
199 R_01_INC_DELAY, 0x08,
200 R_02_INPUT_CNTL_1, 0xc2,
201 R_03_INPUT_CNTL_2, 0x30,
202 R_04_INPUT_CNTL_3, 0x00,
203 R_05_INPUT_CNTL_4, 0x00,
204 R_06_H_SYNC_START, 0x89,
205 R_07_H_SYNC_STOP, 0x0d,
206 R_08_SYNC_CNTL, 0x88,
207 R_09_LUMA_CNTL, 0x01,
208 R_0A_LUMA_BRIGHT_CNTL, 0x80,
209 R_0B_LUMA_CONTRAST_CNTL, 0x47,
210 R_0C_CHROMA_SAT_CNTL, 0x40,
211 R_0D_CHROMA_HUE_CNTL, 0x00,
212 R_0E_CHROMA_CNTL_1, 0x01,
213 R_0F_CHROMA_GAIN_CNTL, 0x2a,
214 R_10_CHROMA_CNTL_2, 0x08,
215 R_11_MODE_DELAY_CNTL, 0x0c,
216 R_12_RT_SIGNAL_CNTL, 0x07,
217 R_13_RT_X_PORT_OUT_CNTL, 0x00,
218 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
219 R_15_VGATE_START_FID_CHG, 0x00,
220 R_16_VGATE_STOP, 0x00,
221 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
222
223 0x00, 0x00
224};
225
e19b2fcc
HV
226/* If a value differs from the Hauppauge driver values, then the comment starts with
227 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
228 Hauppauge driver sets. */
229
89f75ffc 230/* SAA7114 and SAA7115 initialization table */
e19b2fcc 231static const unsigned char saa7115_init_auto_input[] = {
f5762e44 232 /* Front-End Part */
96ecfc4e
MCC
233 R_01_INC_DELAY, 0x48, /* white peak control disabled */
234 R_03_INPUT_CNTL_2, 0x20, /* was 0x30. 0x20: long vertical blanking */
235 R_04_INPUT_CNTL_3, 0x90, /* analog gain set to 0 */
236 R_05_INPUT_CNTL_4, 0x90, /* analog gain set to 0 */
f5762e44 237 /* Decoder Part */
96ecfc4e
MCC
238 R_06_H_SYNC_START, 0xeb, /* horiz sync begin = -21 */
239 R_07_H_SYNC_STOP, 0xe0, /* horiz sync stop = -17 */
240 R_0A_LUMA_BRIGHT_CNTL, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */
241 R_0B_LUMA_CONTRAST_CNTL, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */
242 R_0C_CHROMA_SAT_CNTL, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */
243 R_0D_CHROMA_HUE_CNTL, 0x00,
244 R_0F_CHROMA_GAIN_CNTL, 0x00, /* use automatic gain */
245 R_10_CHROMA_CNTL_2, 0x06, /* chroma: active adaptive combfilter */
246 R_11_MODE_DELAY_CNTL, 0x00,
247 R_12_RT_SIGNAL_CNTL, 0x9d, /* RTS0 output control: VGATE */
248 R_13_RT_X_PORT_OUT_CNTL, 0x80, /* ITU656 standard mode, RTCO output enable RTCE */
249 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
250 R_18_RAW_DATA_GAIN_CNTL, 0x40, /* gain 0x00 = nominal */
251 R_19_RAW_DATA_OFF_CNTL, 0x80,
252 R_1A_COLOR_KILL_LVL_CNTL, 0x77, /* recommended value */
253 R_1B_MISC_TVVCRDET, 0x42, /* recommended value */
254 R_1C_ENHAN_COMB_CTRL1, 0xa9, /* recommended value */
255 R_1D_ENHAN_COMB_CTRL2, 0x01, /* recommended value */
f5762e44 256
d9dce96f
MCC
257
258 R_80_GLOBAL_CNTL_1, 0x0, /* No tasks enabled at init */
259
f5762e44 260 /* Power Device Control */
96ecfc4e
MCC
261 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset device */
262 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* set device programmed, all in operational mode */
e19b2fcc
HV
263 0x00, 0x00
264};
265
89f75ffc 266/* Used to reset saa7113, saa7114 and saa7115 */
e19b2fcc 267static const unsigned char saa7115_cfg_reset_scaler[] = {
96ecfc4e
MCC
268 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00, /* disable I-port output */
269 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
270 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
271 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* enable I-port output */
e19b2fcc
HV
272 0x00, 0x00
273};
274
275/* ============== SAA7715 VIDEO templates ============= */
276
e19b2fcc 277static const unsigned char saa7115_cfg_60hz_video[] = {
96ecfc4e
MCC
278 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
279 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
e19b2fcc 280
96ecfc4e
MCC
281 R_15_VGATE_START_FID_CHG, 0x03,
282 R_16_VGATE_STOP, 0x11,
283 R_17_MISC_VGATE_CONF_AND_MSB, 0x9c,
e19b2fcc 284
96ecfc4e
MCC
285 R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
286 R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */
e19b2fcc 287
96ecfc4e 288 R_5A_V_OFF_FOR_SLICER, 0x06, /* standard 60hz value for ITU656 line counting */
e19b2fcc
HV
289
290 /* Task A */
96ecfc4e
MCC
291 R_90_A_TASK_HANDLING_CNTL, 0x80,
292 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
293 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
294 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
295
296 /* hoffset low (input), 0x0002 is minimum */
297 R_94_A_HORIZ_INPUT_WINDOW_START, 0x01,
298 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
299
300 /* hsize low (input), 0x02d0 = 720 */
301 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
302 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
303
304 R_98_A_VERT_INPUT_WINDOW_START, 0x05,
305 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
306
307 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x0c,
308 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
309
310 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
311 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
312
313 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x0c,
314 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
e19b2fcc
HV
315
316 /* Task B */
96ecfc4e
MCC
317 R_C0_B_TASK_HANDLING_CNTL, 0x00,
318 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
319 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
320 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
321
322 /* 0x0002 is minimum */
323 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x02,
324 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
325
326 /* 0x02d0 = 720 */
327 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
328 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
329
330 /* vwindow start 0x12 = 18 */
331 R_C8_B_VERT_INPUT_WINDOW_START, 0x12,
332 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
333
334 /* vwindow length 0xf8 = 248 */
d9dce96f
MCC
335 R_CA_B_VERT_INPUT_WINDOW_LENGTH, HRES_60HZ>>1,
336 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, HRES_60HZ>>9,
96ecfc4e
MCC
337
338 /* hwindow 0x02d0 = 720 */
339 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
340 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
341
342 R_F0_LFCO_PER_LINE, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
343 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0 */
344 R_F5_PULSGEN_LINE_LENGTH, 0xad,
345 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
346
e19b2fcc
HV
347 0x00, 0x00
348};
349
e19b2fcc 350static const unsigned char saa7115_cfg_50hz_video[] = {
96ecfc4e
MCC
351 R_80_GLOBAL_CNTL_1, 0x00,
352 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
e19b2fcc 353
96ecfc4e
MCC
354 R_15_VGATE_START_FID_CHG, 0x37, /* VGATE start */
355 R_16_VGATE_STOP, 0x16,
356 R_17_MISC_VGATE_CONF_AND_MSB, 0x99,
e19b2fcc 357
96ecfc4e
MCC
358 R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */
359 R_0E_CHROMA_CNTL_1, 0x07,
e19b2fcc 360
96ecfc4e 361 R_5A_V_OFF_FOR_SLICER, 0x03, /* standard 50hz value */
e19b2fcc
HV
362
363 /* Task A */
96ecfc4e
MCC
364 R_90_A_TASK_HANDLING_CNTL, 0x81,
365 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
366 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
367 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
368
e19b2fcc
HV
369 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
370 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
96ecfc4e
MCC
371 /* hoffset low (input), 0x0002 is minimum */
372 R_94_A_HORIZ_INPUT_WINDOW_START, 0x00,
373 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
374
375 /* hsize low (input), 0x02d0 = 720 */
376 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
377 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
378
379 R_98_A_VERT_INPUT_WINDOW_START, 0x03,
380 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
381
382 /* vsize 0x12 = 18 */
383 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x12,
384 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
385
386 /* hsize 0x05a0 = 1440 */
387 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
388 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05, /* hsize hi (output) */
389 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x12, /* vsize low (output), 0x12 = 18 */
390 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00, /* vsize hi (output) */
e19b2fcc
HV
391
392 /* Task B */
96ecfc4e
MCC
393 R_C0_B_TASK_HANDLING_CNTL, 0x00,
394 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
395 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
396 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
397
398 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
399 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
400 /* hoffset low (input), 0x0002 is minimum. See comment above. */
401 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x00,
402 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
403
404 /* hsize 0x02d0 = 720 */
405 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
406 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
407
408 /* voffset 0x16 = 22 */
409 R_C8_B_VERT_INPUT_WINDOW_START, 0x16,
410 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
411
412 /* vsize 0x0120 = 288 */
413 R_CA_B_VERT_INPUT_WINDOW_LENGTH, 0x20,
414 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, 0x01,
415
416 /* hsize 0x02d0 = 720 */
417 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
418 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
419
96ecfc4e
MCC
420 R_F0_LFCO_PER_LINE, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
421 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0, (was 0x05) */
422 R_F5_PULSGEN_LINE_LENGTH, 0xb0,
423 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
424
e19b2fcc
HV
425 0x00, 0x00
426};
427
428/* ============== SAA7715 VIDEO templates (end) ======= */
429
430static const unsigned char saa7115_cfg_vbi_on[] = {
96ecfc4e
MCC
431 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
432 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
433 R_80_GLOBAL_CNTL_1, 0x30, /* Activate both tasks */
434 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
435 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
436
e19b2fcc
HV
437 0x00, 0x00
438};
439
440static const unsigned char saa7115_cfg_vbi_off[] = {
96ecfc4e
MCC
441 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
442 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
443 R_80_GLOBAL_CNTL_1, 0x20, /* Activate only task "B" */
444 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
445 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
446
e19b2fcc
HV
447 0x00, 0x00
448};
449
f5762e44 450
e19b2fcc 451static const unsigned char saa7115_init_misc[] = {
96ecfc4e 452 R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
96ecfc4e
MCC
453 R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 0x01,
454 R_84_I_PORT_SIGNAL_DEF, 0x20,
455 R_85_I_PORT_SIGNAL_POLAR, 0x21,
456 R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT, 0xc5,
457 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
e19b2fcc
HV
458
459 /* Task A */
96ecfc4e
MCC
460 R_A0_A_HORIZ_PRESCALING, 0x01,
461 R_A1_A_ACCUMULATION_LENGTH, 0x00,
462 R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
463
464 /* Configure controls at nominal value*/
465 R_A4_A_LUMA_BRIGHTNESS_CNTL, 0x80,
466 R_A5_A_LUMA_CONTRAST_CNTL, 0x40,
467 R_A6_A_CHROMA_SATURATION_CNTL, 0x40,
468
469 /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
470 R_A8_A_HORIZ_LUMA_SCALING_INC, 0x00,
471 R_A9_A_HORIZ_LUMA_SCALING_INC_MSB, 0x02,
472
473 R_AA_A_HORIZ_LUMA_PHASE_OFF, 0x00,
474
475 /* must be horiz lum scaling / 2 */
476 R_AC_A_HORIZ_CHROMA_SCALING_INC, 0x00,
477 R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB, 0x01,
478
479 /* must be offset luma / 2 */
480 R_AE_A_HORIZ_CHROMA_PHASE_OFF, 0x00,
481
482 R_B0_A_VERT_LUMA_SCALING_INC, 0x00,
483 R_B1_A_VERT_LUMA_SCALING_INC_MSB, 0x04,
484
485 R_B2_A_VERT_CHROMA_SCALING_INC, 0x00,
486 R_B3_A_VERT_CHROMA_SCALING_INC_MSB, 0x04,
487
488 R_B4_A_VERT_SCALING_MODE_CNTL, 0x01,
489
490 R_B8_A_VERT_CHROMA_PHASE_OFF_00, 0x00,
491 R_B9_A_VERT_CHROMA_PHASE_OFF_01, 0x00,
492 R_BA_A_VERT_CHROMA_PHASE_OFF_10, 0x00,
493 R_BB_A_VERT_CHROMA_PHASE_OFF_11, 0x00,
494
495 R_BC_A_VERT_LUMA_PHASE_OFF_00, 0x00,
496 R_BD_A_VERT_LUMA_PHASE_OFF_01, 0x00,
497 R_BE_A_VERT_LUMA_PHASE_OFF_10, 0x00,
498 R_BF_A_VERT_LUMA_PHASE_OFF_11, 0x00,
e19b2fcc
HV
499
500 /* Task B */
96ecfc4e
MCC
501 R_D0_B_HORIZ_PRESCALING, 0x01,
502 R_D1_B_ACCUMULATION_LENGTH, 0x00,
503 R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
504
505 /* Configure controls at nominal value*/
506 R_D4_B_LUMA_BRIGHTNESS_CNTL, 0x80,
507 R_D5_B_LUMA_CONTRAST_CNTL, 0x40,
508 R_D6_B_CHROMA_SATURATION_CNTL, 0x40,
509
510 /* hor lum scaling 0x0400 = 1 */
511 R_D8_B_HORIZ_LUMA_SCALING_INC, 0x00,
512 R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, 0x04,
513
514 R_DA_B_HORIZ_LUMA_PHASE_OFF, 0x00,
515
516 /* must be hor lum scaling / 2 */
517 R_DC_B_HORIZ_CHROMA_SCALING, 0x00,
518 R_DD_B_HORIZ_CHROMA_SCALING_MSB, 0x02,
519
520 /* must be offset luma / 2 */
521 R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA, 0x00,
522
523 R_E0_B_VERT_LUMA_SCALING_INC, 0x00,
524 R_E1_B_VERT_LUMA_SCALING_INC_MSB, 0x04,
525
526 R_E2_B_VERT_CHROMA_SCALING_INC, 0x00,
527 R_E3_B_VERT_CHROMA_SCALING_INC_MSB, 0x04,
528
529 R_E4_B_VERT_SCALING_MODE_CNTL, 0x01,
530
531 R_E8_B_VERT_CHROMA_PHASE_OFF_00, 0x00,
532 R_E9_B_VERT_CHROMA_PHASE_OFF_01, 0x00,
533 R_EA_B_VERT_CHROMA_PHASE_OFF_10, 0x00,
534 R_EB_B_VERT_CHROMA_PHASE_OFF_11, 0x00,
535
536 R_EC_B_VERT_LUMA_PHASE_OFF_00, 0x00,
537 R_ED_B_VERT_LUMA_PHASE_OFF_01, 0x00,
538 R_EE_B_VERT_LUMA_PHASE_OFF_10, 0x00,
539 R_EF_B_VERT_LUMA_PHASE_OFF_11, 0x00,
540
541 R_F2_NOMINAL_PLL2_DTO, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */
542 R_F3_PLL_INCREMENT, 0x46,
543 R_F4_PLL2_STATUS, 0x00,
544 R_F7_PULSE_A_POS_MSB, 0x4b, /* not the recommended settings! */
545 R_F8_PULSE_B_POS, 0x00,
546 R_F9_PULSE_B_POS_MSB, 0x4b,
547 R_FA_PULSE_C_POS, 0x00,
548 R_FB_PULSE_C_POS_MSB, 0x4b,
549
550 /* PLL2 lock detection settings: 71 lines 50% phase error */
551 R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES, 0x88,
e19b2fcc
HV
552
553 /* Turn off VBI */
96ecfc4e
MCC
554 R_40_SLICER_CNTL_1, 0x20, /* No framing code errors allowed. */
555 R_41_LCR_BASE, 0xff,
556 R_41_LCR_BASE+1, 0xff,
557 R_41_LCR_BASE+2, 0xff,
558 R_41_LCR_BASE+3, 0xff,
559 R_41_LCR_BASE+4, 0xff,
560 R_41_LCR_BASE+5, 0xff,
561 R_41_LCR_BASE+6, 0xff,
562 R_41_LCR_BASE+7, 0xff,
563 R_41_LCR_BASE+8, 0xff,
564 R_41_LCR_BASE+9, 0xff,
565 R_41_LCR_BASE+10, 0xff,
566 R_41_LCR_BASE+11, 0xff,
567 R_41_LCR_BASE+12, 0xff,
568 R_41_LCR_BASE+13, 0xff,
569 R_41_LCR_BASE+14, 0xff,
570 R_41_LCR_BASE+15, 0xff,
571 R_41_LCR_BASE+16, 0xff,
572 R_41_LCR_BASE+17, 0xff,
573 R_41_LCR_BASE+18, 0xff,
574 R_41_LCR_BASE+19, 0xff,
575 R_41_LCR_BASE+20, 0xff,
576 R_41_LCR_BASE+21, 0xff,
577 R_41_LCR_BASE+22, 0xff,
578 R_58_PROGRAM_FRAMING_CODE, 0x40,
579 R_59_H_OFF_FOR_SLICER, 0x47,
580 R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF, 0x83,
581 R_5D_DID, 0xbd,
582 R_5E_SDID, 0x35,
583
584 R_02_INPUT_CNTL_1, 0x84, /* input tuner -> input 4, amplifier active */
585 R_09_LUMA_CNTL, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */
586
587 R_80_GLOBAL_CNTL_1, 0x20, /* enable task B */
588 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
589 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
e19b2fcc
HV
590 0x00, 0x00
591};
592
66ec1193 593static int saa711x_odd_parity(u8 c)
e19b2fcc
HV
594{
595 c ^= (c >> 4);
596 c ^= (c >> 2);
597 c ^= (c >> 1);
598
599 return c & 1;
600}
601
66ec1193 602static int saa711x_decode_vps(u8 * dst, u8 * p)
e19b2fcc
HV
603{
604 static const u8 biphase_tbl[] = {
605 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
606 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
607 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
608 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
609 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
610 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
611 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
612 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
613 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
614 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
615 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
616 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
617 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
618 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
619 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
620 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
621 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
622 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
623 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
624 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
625 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
626 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
627 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
628 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
629 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
630 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
631 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
632 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
633 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
634 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
635 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
636 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
637 };
638 int i;
639 u8 c, err = 0;
640
641 for (i = 0; i < 2 * 13; i += 2) {
642 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
643 c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
644 dst[i / 2] = c;
645 }
646 return err & 0xf0;
647}
648
66ec1193 649static int saa711x_decode_wss(u8 * p)
e19b2fcc
HV
650{
651 static const int wss_bits[8] = {
652 0, 0, 0, 1, 0, 1, 1, 1
653 };
654 unsigned char parity;
655 int wss = 0;
656 int i;
657
658 for (i = 0; i < 16; i++) {
659 int b1 = wss_bits[p[i] & 7];
660 int b2 = wss_bits[(p[i] >> 3) & 7];
661
662 if (b1 == b2)
663 return -1;
664 wss |= b2 << i;
665 }
666 parity = wss & 15;
667 parity ^= parity >> 2;
668 parity ^= parity >> 1;
669
670 if (!(parity & 1))
671 return -1;
672
673 return wss;
674}
675
66ec1193 676static int saa711x_set_audio_clock_freq(struct i2c_client *client, u32 freq)
e19b2fcc 677{
66ec1193 678 struct saa711x_state *state = i2c_get_clientdata(client);
3578d3dd
HV
679 u32 acpf;
680 u32 acni;
681 u32 hz;
682 u64 f;
b7f8292c 683 u8 acc = 0; /* reg 0x3a, audio clock control */
e19b2fcc 684
89f75ffc
MCC
685 /* Checks for chips that don't have audio clock (saa7111, saa7113) */
686 if (!saa711x_has_reg(state->ident,R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
687 return 0;
688
f167cb4e 689 v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq);
3578d3dd
HV
690
691 /* sanity check */
692 if (freq < 32000 || freq > 48000)
693 return -EINVAL;
694
695 /* hz is the refresh rate times 100 */
696 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
697 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
698 acpf = (25600 * freq) / hz;
699 /* acni = (256 * freq * 2^23) / crystal_frequency =
700 (freq * 2^(8+23)) / crystal_frequency =
b7f8292c 701 (freq << 31) / crystal_frequency */
3578d3dd
HV
702 f = freq;
703 f = f << 31;
b7f8292c 704 do_div(f, state->crystal_freq);
3578d3dd 705 acni = f;
b7f8292c
HV
706 if (state->ucgc) {
707 acpf = acpf * state->cgcdiv / 16;
708 acni = acni * state->cgcdiv / 16;
709 acc = 0x80;
710 if (state->cgcdiv == 3)
711 acc |= 0x40;
712 }
713 if (state->apll)
714 acc |= 0x08;
3578d3dd 715
66ec1193
MCC
716 saa711x_write(client, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
717 saa711x_write(client, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10);
718 saa711x_write(client, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
96ecfc4e 719
66ec1193
MCC
720 saa711x_write(client, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
721 saa711x_write(client, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
96ecfc4e 722 (acpf >> 8) & 0xff);
66ec1193 723 saa711x_write(client, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
96ecfc4e
MCC
724 (acpf >> 16) & 0x03);
725
66ec1193
MCC
726 saa711x_write(client, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
727 saa711x_write(client, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
728 saa711x_write(client, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
e19b2fcc
HV
729 state->audclk_freq = freq;
730 return 0;
731}
732
66ec1193 733static int saa711x_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
e19b2fcc 734{
66ec1193 735 struct saa711x_state *state = i2c_get_clientdata(client);
e19b2fcc
HV
736
737 switch (ctrl->id) {
738 case V4L2_CID_BRIGHTNESS:
739 if (ctrl->value < 0 || ctrl->value > 255) {
fac9e899 740 v4l_err(client, "invalid brightness setting %d\n", ctrl->value);
e19b2fcc
HV
741 return -ERANGE;
742 }
743
744 state->bright = ctrl->value;
66ec1193 745 saa711x_write(client, R_0A_LUMA_BRIGHT_CNTL, state->bright);
e19b2fcc
HV
746 break;
747
748 case V4L2_CID_CONTRAST:
749 if (ctrl->value < 0 || ctrl->value > 127) {
fac9e899 750 v4l_err(client, "invalid contrast setting %d\n", ctrl->value);
e19b2fcc
HV
751 return -ERANGE;
752 }
753
754 state->contrast = ctrl->value;
66ec1193 755 saa711x_write(client, R_0B_LUMA_CONTRAST_CNTL, state->contrast);
e19b2fcc
HV
756 break;
757
758 case V4L2_CID_SATURATION:
759 if (ctrl->value < 0 || ctrl->value > 127) {
fac9e899 760 v4l_err(client, "invalid saturation setting %d\n", ctrl->value);
e19b2fcc
HV
761 return -ERANGE;
762 }
763
764 state->sat = ctrl->value;
66ec1193 765 saa711x_write(client, R_0C_CHROMA_SAT_CNTL, state->sat);
e19b2fcc
HV
766 break;
767
768 case V4L2_CID_HUE:
769 if (ctrl->value < -127 || ctrl->value > 127) {
fac9e899 770 v4l_err(client, "invalid hue setting %d\n", ctrl->value);
e19b2fcc
HV
771 return -ERANGE;
772 }
773
774 state->hue = ctrl->value;
66ec1193 775 saa711x_write(client, R_0D_CHROMA_HUE_CNTL, state->hue);
e19b2fcc 776 break;
3faeeae4
HV
777
778 default:
779 return -EINVAL;
e19b2fcc
HV
780 }
781
782 return 0;
783}
784
66ec1193 785static int saa711x_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
e19b2fcc 786{
66ec1193 787 struct saa711x_state *state = i2c_get_clientdata(client);
e19b2fcc
HV
788
789 switch (ctrl->id) {
790 case V4L2_CID_BRIGHTNESS:
791 ctrl->value = state->bright;
792 break;
793 case V4L2_CID_CONTRAST:
794 ctrl->value = state->contrast;
795 break;
796 case V4L2_CID_SATURATION:
797 ctrl->value = state->sat;
798 break;
799 case V4L2_CID_HUE:
800 ctrl->value = state->hue;
801 break;
802 default:
803 return -EINVAL;
804 }
805
806 return 0;
807}
808
d9dce96f
MCC
809static int saa711x_set_size(struct i2c_client *client, int width, int height)
810{
811 struct saa711x_state *state = i2c_get_clientdata(client);
812 int HPSC, HFSC;
813 int VSCY;
814 int res;
815 int is_50hz = state->std & V4L2_STD_625_50;
816 int Vsrc = is_50hz ? 576 : 480;
817
818 v4l_dbg(1, debug, client, "decoder set size to %ix%i\n",width,height);
819
820 /* FIXME need better bounds checking here */
821 if ((width < 1) || (width > 1440))
822 return -EINVAL;
823 if ((height < 1) || (height > Vsrc))
824 return -EINVAL;
825
826 if (!saa711x_has_reg(state->ident,R_D0_B_HORIZ_PRESCALING)) {
827 /* Decoder only supports 720 columns and 480 or 576 lines */
828 if (width != 720)
829 return -EINVAL;
830 if (height != Vsrc)
831 return -EINVAL;
832 }
833
834 state->width = width;
835 state->height = height;
836
837 if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
838 return 0;
839
840 /* probably have a valid size, let's set it */
841 /* Set output width/height */
842 /* width */
843
844 saa711x_write(client, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
845 (u8) (width & 0xff));
846 saa711x_write(client, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
847 (u8) ((width >> 8) & 0xff));
848
849 /* Vertical Scaling uses height/2 */
850 res=height/2;
851
852 /* On 60Hz, it is using a higher Vertical Output Size */
853 if (!is_50hz)
22ebb77d 854 res+=(HRES_60HZ-480)>>1;
d9dce96f
MCC
855
856 /* height */
857 saa711x_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
858 (u8) (res & 0xff));
859 saa711x_write(client, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
860 (u8) ((res >> 8) & 0xff));
861
862 /* Scaling settings */
863 /* Hprescaler is floor(inres/outres) */
864 HPSC = (int)(720 / width);
865 /* 0 is not allowed (div. by zero) */
866 HPSC = HPSC ? HPSC : 1;
867 HFSC = (int)((1024 * 720) / (HPSC * width));
868 /* FIXME hardcodes to "Task B"
869 * write H prescaler integer */
870 saa711x_write(client, R_D0_B_HORIZ_PRESCALING,
871 (u8) (HPSC & 0x3f));
872
873 v4l_dbg(1, debug, client, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
874 /* write H fine-scaling (luminance) */
875 saa711x_write(client, R_D8_B_HORIZ_LUMA_SCALING_INC,
876 (u8) (HFSC & 0xff));
877 saa711x_write(client, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
878 (u8) ((HFSC >> 8) & 0xff));
879 /* write H fine-scaling (chrominance)
880 * must be lum/2, so i'll just bitshift :) */
881 saa711x_write(client, R_DC_B_HORIZ_CHROMA_SCALING,
882 (u8) ((HFSC >> 1) & 0xff));
883 saa711x_write(client, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
884 (u8) ((HFSC >> 9) & 0xff));
885
886 VSCY = (int)((1024 * Vsrc) / height);
887 v4l_dbg(1, debug, client, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
888
889 /* Correct Contrast and Luminance */
890 saa711x_write(client, R_D5_B_LUMA_CONTRAST_CNTL,
891 (u8) (64 * 1024 / VSCY));
892 saa711x_write(client, R_D6_B_CHROMA_SATURATION_CNTL,
893 (u8) (64 * 1024 / VSCY));
894
895 /* write V fine-scaling (luminance) */
896 saa711x_write(client, R_E0_B_VERT_LUMA_SCALING_INC,
897 (u8) (VSCY & 0xff));
898 saa711x_write(client, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
899 (u8) ((VSCY >> 8) & 0xff));
900 /* write V fine-scaling (chrominance) */
901 saa711x_write(client, R_E2_B_VERT_CHROMA_SCALING_INC,
902 (u8) (VSCY & 0xff));
903 saa711x_write(client, R_E3_B_VERT_CHROMA_SCALING_INC_MSB,
904 (u8) ((VSCY >> 8) & 0xff));
905
906 saa711x_writeregs(client, saa7115_cfg_reset_scaler);
907
908 /* Activates task "B" */
909 saa711x_write(client, R_80_GLOBAL_CNTL_1,
910 saa711x_read(client,R_80_GLOBAL_CNTL_1)|0x20);
911
912 return 0;
913}
914
66ec1193 915static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
e19b2fcc 916{
66ec1193 917 struct saa711x_state *state = i2c_get_clientdata(client);
e19b2fcc 918
30b54d50
HV
919 /* Prevent unnecessary standard changes. During a standard
920 change the I-Port is temporarily disabled. Any devices
921 reading from that port can get confused.
922 Note that VIDIOC_S_STD is also used to switch from
923 radio to TV mode, so if a VIDIOC_S_STD is broadcast to
924 all I2C devices then you do not want to have an unwanted
925 side-effect here. */
926 if (std == state->std)
927 return;
928
d9dce96f
MCC
929 state->std = std;
930
e19b2fcc
HV
931 // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
932 if (std & V4L2_STD_525_60) {
f167cb4e 933 v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n");
66ec1193 934 saa711x_writeregs(client, saa7115_cfg_60hz_video);
d9dce96f 935 saa711x_set_size(client,720,480);
e19b2fcc 936 } else {
f167cb4e 937 v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n");
66ec1193 938 saa711x_writeregs(client, saa7115_cfg_50hz_video);
d9dce96f 939 saa711x_set_size(client,720,576);
e19b2fcc
HV
940 }
941
f89982a9 942 /* Register 0E - Bits D6-D4 on NO-AUTO mode
89f75ffc 943 (SAA7111 and SAA7113 doesn't have auto mode)
f89982a9
MCC
944 50 Hz / 625 lines 60 Hz / 525 lines
945 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz)
946 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz)
947 010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz)
948 011 NTSC N (3.58MHz) PAL M (3.58MHz)
949 100 reserved NTSC-Japan (3.58MHz)
950 */
89f75ffc
MCC
951 if (state->ident == V4L2_IDENT_SAA7111 ||
952 state->ident == V4L2_IDENT_SAA7113) {
66ec1193 953 u8 reg = saa711x_read(client, R_0E_CHROMA_CNTL_1) & 0x8f;
f89982a9 954
02c17224 955 if (std == V4L2_STD_PAL_M) {
01342358 956 reg |= 0x30;
02c17224 957 } else if (std == V4L2_STD_PAL_N) {
01342358 958 reg |= 0x20;
02c17224 959 } else if (std == V4L2_STD_PAL_60) {
01342358 960 reg |= 0x10;
02c17224 961 } else if (std == V4L2_STD_NTSC_M_JP) {
01342358 962 reg |= 0x40;
f89982a9 963 }
66ec1193 964 saa711x_write(client, R_0E_CHROMA_CNTL_1, reg);
89f75ffc
MCC
965 } else {
966 /* restart task B if needed */
66ec1193 967 int taskb = saa711x_read(client, R_80_GLOBAL_CNTL_1) & 0x10;
f89982a9 968
89f75ffc 969 if (taskb && state->ident == V4L2_IDENT_SAA7114) {
66ec1193 970 saa711x_writeregs(client, saa7115_cfg_vbi_on);
89f75ffc 971 }
e19b2fcc 972
89f75ffc 973 /* switch audio mode too! */
66ec1193 974 saa711x_set_audio_clock_freq(client, state->audclk_freq);
e19b2fcc 975 }
e19b2fcc
HV
976}
977
66ec1193 978static v4l2_std_id saa711x_get_v4lstd(struct i2c_client *client)
e19b2fcc 979{
66ec1193 980 struct saa711x_state *state = i2c_get_clientdata(client);
e19b2fcc
HV
981
982 return state->std;
983}
984
66ec1193 985static void saa711x_log_status(struct i2c_client *client)
e19b2fcc 986{
66ec1193 987 struct saa711x_state *state = i2c_get_clientdata(client);
e19b2fcc
HV
988 int reg1e, reg1f;
989 int signalOk;
990 int vcr;
991
fac9e899 992 v4l_info(client, "Audio frequency: %d Hz\n", state->audclk_freq);
f5762e44 993 if (state->ident != V4L2_IDENT_SAA7115) {
e19b2fcc 994 /* status for the saa7114 */
66ec1193 995 reg1f = saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC);
e19b2fcc 996 signalOk = (reg1f & 0xc1) == 0x81;
fac9e899
HV
997 v4l_info(client, "Video signal: %s\n", signalOk ? "ok" : "bad");
998 v4l_info(client, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
e19b2fcc
HV
999 return;
1000 }
1001
1002 /* status for the saa7115 */
66ec1193
MCC
1003 reg1e = saa711x_read(client, R_1E_STATUS_BYTE_1_VD_DEC);
1004 reg1f = saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC);
e19b2fcc
HV
1005
1006 signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
1007 vcr = !(reg1f & 0x10);
1008
21fa715e 1009 if (state->input >= 6) {
fac9e899 1010 v4l_info(client, "Input: S-Video %d\n", state->input - 6);
21fa715e 1011 } else {
fac9e899 1012 v4l_info(client, "Input: Composite %d\n", state->input);
21fa715e 1013 }
fac9e899
HV
1014 v4l_info(client, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
1015 v4l_info(client, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
e19b2fcc
HV
1016
1017 switch (reg1e & 0x03) {
1018 case 1:
fac9e899 1019 v4l_info(client, "Detected format: NTSC\n");
e19b2fcc
HV
1020 break;
1021 case 2:
fac9e899 1022 v4l_info(client, "Detected format: PAL\n");
e19b2fcc
HV
1023 break;
1024 case 3:
fac9e899 1025 v4l_info(client, "Detected format: SECAM\n");
e19b2fcc
HV
1026 break;
1027 default:
fac9e899 1028 v4l_info(client, "Detected format: BW/No color\n");
e19b2fcc
HV
1029 break;
1030 }
d9dce96f 1031 v4l_info(client, "Width, Height: %d, %d\n", state->width, state->height);
e19b2fcc
HV
1032}
1033
1034/* setup the sliced VBI lcr registers according to the sliced VBI format */
66ec1193 1035static void saa711x_set_lcr(struct i2c_client *client, struct v4l2_sliced_vbi_format *fmt)
e19b2fcc 1036{
66ec1193 1037 struct saa711x_state *state = i2c_get_clientdata(client);
e19b2fcc
HV
1038 int is_50hz = (state->std & V4L2_STD_625_50);
1039 u8 lcr[24];
1040 int i, x;
1041
89f75ffc
MCC
1042#if 1
1043 /* saa7113/7114/7118 VBI support are experimental */
1044 if (!saa711x_has_reg(state->ident,R_41_LCR_BASE))
1045 return;
1046
1047#else
1048 /* SAA7113 and SAA7118 also should support VBI - Need testing */
f5762e44 1049 if (state->ident != V4L2_IDENT_SAA7115)
e19b2fcc 1050 return;
89f75ffc 1051#endif
e19b2fcc
HV
1052
1053 for (i = 0; i <= 23; i++)
1054 lcr[i] = 0xff;
1055
1056 if (fmt->service_set == 0) {
1057 /* raw VBI */
1058 if (is_50hz)
1059 for (i = 6; i <= 23; i++)
1060 lcr[i] = 0xdd;
1061 else
1062 for (i = 10; i <= 21; i++)
1063 lcr[i] = 0xdd;
1064 } else {
1065 /* sliced VBI */
1066 /* first clear lines that cannot be captured */
1067 if (is_50hz) {
1068 for (i = 0; i <= 5; i++)
1069 fmt->service_lines[0][i] =
1070 fmt->service_lines[1][i] = 0;
1071 }
1072 else {
1073 for (i = 0; i <= 9; i++)
1074 fmt->service_lines[0][i] =
1075 fmt->service_lines[1][i] = 0;
1076 for (i = 22; i <= 23; i++)
1077 fmt->service_lines[0][i] =
1078 fmt->service_lines[1][i] = 0;
1079 }
1080
1081 /* Now set the lcr values according to the specified service */
1082 for (i = 6; i <= 23; i++) {
1083 lcr[i] = 0;
1084 for (x = 0; x <= 1; x++) {
1085 switch (fmt->service_lines[1-x][i]) {
1086 case 0:
1087 lcr[i] |= 0xf << (4 * x);
1088 break;
9bc7400a 1089 case V4L2_SLICED_TELETEXT_B:
e19b2fcc
HV
1090 lcr[i] |= 1 << (4 * x);
1091 break;
1092 case V4L2_SLICED_CAPTION_525:
1093 lcr[i] |= 4 << (4 * x);
1094 break;
1095 case V4L2_SLICED_WSS_625:
1096 lcr[i] |= 5 << (4 * x);
1097 break;
1098 case V4L2_SLICED_VPS:
1099 lcr[i] |= 7 << (4 * x);
1100 break;
1101 }
1102 }
1103 }
1104 }
1105
1106 /* write the lcr registers */
1107 for (i = 2; i <= 23; i++) {
66ec1193 1108 saa711x_write(client, i - 2 + R_41_LCR_BASE, lcr[i]);
e19b2fcc
HV
1109 }
1110
1111 /* enable/disable raw VBI capturing */
66ec1193 1112 saa711x_writeregs(client, fmt->service_set == 0 ?
96ecfc4e
MCC
1113 saa7115_cfg_vbi_on :
1114 saa7115_cfg_vbi_off);
e19b2fcc
HV
1115}
1116
66ec1193 1117static int saa711x_get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
e19b2fcc
HV
1118{
1119 static u16 lcr2vbi[] = {
9bc7400a 1120 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
e19b2fcc
HV
1121 0, V4L2_SLICED_CAPTION_525, /* 4 */
1122 V4L2_SLICED_WSS_625, 0, /* 5 */
1123 V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
1124 0, 0, 0, 0
1125 };
1126 struct v4l2_sliced_vbi_format *sliced = &fmt->fmt.sliced;
1127 int i;
1128
1129 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
1130 return -EINVAL;
1131 memset(sliced, 0, sizeof(*sliced));
1132 /* done if using raw VBI */
66ec1193 1133 if (saa711x_read(client, R_80_GLOBAL_CNTL_1) & 0x10)
e19b2fcc
HV
1134 return 0;
1135 for (i = 2; i <= 23; i++) {
66ec1193 1136 u8 v = saa711x_read(client, i - 2 + R_41_LCR_BASE);
e19b2fcc
HV
1137
1138 sliced->service_lines[0][i] = lcr2vbi[v >> 4];
1139 sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
1140 sliced->service_set |=
1141 sliced->service_lines[0][i] | sliced->service_lines[1][i];
1142 }
1143 return 0;
1144}
1145
59ba9154
MCC
1146static int saa711x_set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
1147{
1148 if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
1149 saa711x_set_lcr(client, &fmt->fmt.sliced);
1150 return 0;
1151 }
1152 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1153 return -EINVAL;
1154
1155 return saa711x_set_size(client,fmt->fmt.pix.width,fmt->fmt.pix.height);
1156}
1157
e19b2fcc
HV
1158/* Decode the sliced VBI data stream as created by the saa7115.
1159 The format is described in the saa7115 datasheet in Tables 25 and 26
1160 and in Figure 33.
1161 The current implementation uses SAV/EAV codes and not the ancillary data
96ecfc4e 1162 headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV
e19b2fcc 1163 code. */
66ec1193 1164static void saa711x_decode_vbi_line(struct i2c_client *client,
e19b2fcc
HV
1165 struct v4l2_decode_vbi_line *vbi)
1166{
1167 static const char vbi_no_data_pattern[] = {
1168 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
1169 };
66ec1193 1170 struct saa711x_state *state = i2c_get_clientdata(client);
e19b2fcc
HV
1171 u8 *p = vbi->p;
1172 u32 wss;
1173 int id1, id2; /* the ID1 and ID2 bytes from the internal header */
1174
1175 vbi->type = 0; /* mark result as a failure */
1176 id1 = p[2];
1177 id2 = p[3];
1178 /* Note: the field bit is inverted for 60 Hz video */
1179 if (state->std & V4L2_STD_525_60)
1180 id1 ^= 0x40;
1181
1182 /* Skip internal header, p now points to the start of the payload */
1183 p += 4;
1184 vbi->p = p;
1185
1186 /* calculate field and line number of the VBI packet (1-23) */
1187 vbi->is_second_field = ((id1 & 0x40) != 0);
1188 vbi->line = (id1 & 0x3f) << 3;
1189 vbi->line |= (id2 & 0x70) >> 4;
1190
1191 /* Obtain data type */
1192 id2 &= 0xf;
1193
1194 /* If the VBI slicer does not detect any signal it will fill up
1195 the payload buffer with 0xa0 bytes. */
1196 if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
1197 return;
1198
1199 /* decode payloads */
1200 switch (id2) {
1201 case 1:
9bc7400a 1202 vbi->type = V4L2_SLICED_TELETEXT_B;
e19b2fcc
HV
1203 break;
1204 case 4:
59ba9154 1205 if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
e19b2fcc
HV
1206 return;
1207 vbi->type = V4L2_SLICED_CAPTION_525;
1208 break;
1209 case 5:
66ec1193 1210 wss = saa711x_decode_wss(p);
e19b2fcc
HV
1211 if (wss == -1)
1212 return;
1213 p[0] = wss & 0xff;
1214 p[1] = wss >> 8;
1215 vbi->type = V4L2_SLICED_WSS_625;
1216 break;
1217 case 7:
66ec1193 1218 if (saa711x_decode_vps(p, p) != 0)
e19b2fcc
HV
1219 return;
1220 vbi->type = V4L2_SLICED_VPS;
1221 break;
1222 default:
1223 return;
1224 }
1225}
1226
1227/* ============ SAA7115 AUDIO settings (end) ============= */
1228
66ec1193 1229static int saa711x_command(struct i2c_client *client, unsigned int cmd, void *arg)
e19b2fcc 1230{
66ec1193 1231 struct saa711x_state *state = i2c_get_clientdata(client);
e19b2fcc
HV
1232 int *iarg = arg;
1233
1234 /* ioctls to allow direct access to the saa7115 registers for testing */
1235 switch (cmd) {
1236 case VIDIOC_S_FMT:
66ec1193 1237 return saa711x_set_v4lfmt(client, (struct v4l2_format *)arg);
e19b2fcc
HV
1238
1239 case VIDIOC_G_FMT:
66ec1193 1240 return saa711x_get_v4lfmt(client, (struct v4l2_format *)arg);
e19b2fcc
HV
1241
1242 case VIDIOC_INT_AUDIO_CLOCK_FREQ:
66ec1193 1243 return saa711x_set_audio_clock_freq(client, *(u32 *)arg);
e19b2fcc
HV
1244
1245 case VIDIOC_G_TUNER:
1246 {
1247 struct v4l2_tuner *vt = arg;
1248 int status;
1249
3faeeae4
HV
1250 if (state->radio)
1251 break;
66ec1193 1252 status = saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC);
e19b2fcc 1253
f167cb4e 1254 v4l_dbg(1, debug, client, "status: 0x%02x\n", status);
e19b2fcc
HV
1255 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1256 break;
1257 }
1258
1259 case VIDIOC_LOG_STATUS:
66ec1193 1260 saa711x_log_status(client);
e19b2fcc
HV
1261 break;
1262
1263 case VIDIOC_G_CTRL:
66ec1193 1264 return saa711x_get_v4lctrl(client, (struct v4l2_control *)arg);
e19b2fcc
HV
1265
1266 case VIDIOC_S_CTRL:
66ec1193 1267 return saa711x_set_v4lctrl(client, (struct v4l2_control *)arg);
e19b2fcc 1268
da4ae5a7
HV
1269 case VIDIOC_QUERYCTRL:
1270 {
1271 struct v4l2_queryctrl *qc = arg;
da4ae5a7 1272
18318e00
HV
1273 switch (qc->id) {
1274 case V4L2_CID_BRIGHTNESS:
1275 case V4L2_CID_CONTRAST:
1276 case V4L2_CID_SATURATION:
1277 case V4L2_CID_HUE:
1278 return v4l2_ctrl_query_fill_std(qc);
1279 default:
1280 return -EINVAL;
1281 }
da4ae5a7
HV
1282 }
1283
e19b2fcc 1284 case VIDIOC_G_STD:
66ec1193 1285 *(v4l2_std_id *)arg = saa711x_get_v4lstd(client);
e19b2fcc
HV
1286 break;
1287
1288 case VIDIOC_S_STD:
3faeeae4 1289 state->radio = 0;
66ec1193 1290 saa711x_set_v4lstd(client, *(v4l2_std_id *)arg);
e19b2fcc
HV
1291 break;
1292
3faeeae4
HV
1293 case AUDC_SET_RADIO:
1294 state->radio = 1;
1295 break;
1296
1f8f5fa9
HV
1297 case VIDIOC_INT_G_VIDEO_ROUTING:
1298 {
1299 struct v4l2_routing *route = arg;
1300
1301 route->input = state->input;
1302 route->output = 0;
1303 break;
1304 }
1305
1306 case VIDIOC_INT_S_VIDEO_ROUTING:
1307 {
1308 struct v4l2_routing *route = arg;
1309
1310 v4l_dbg(1, debug, client, "decoder set input %d\n", route->input);
1311 /* saa7113 does not have these inputs */
1312 if (state->ident == V4L2_IDENT_SAA7113 &&
1313 (route->input == SAA7115_COMPOSITE4 ||
1314 route->input == SAA7115_COMPOSITE5)) {
1315 return -EINVAL;
1316 }
1317 if (route->input > SAA7115_SVIDEO3)
1318 return -EINVAL;
1319 if (state->input == route->input)
1320 break;
1321 v4l_dbg(1, debug, client, "now setting %s input\n",
1322 (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite");
1323 state->input = route->input;
1324
1325 /* select mode */
66ec1193
MCC
1326 saa711x_write(client, R_02_INPUT_CNTL_1,
1327 (saa711x_read(client, R_02_INPUT_CNTL_1) & 0xf0) |
1f8f5fa9
HV
1328 state->input);
1329
1330 /* bypass chrominance trap for S-Video modes */
66ec1193
MCC
1331 saa711x_write(client, R_09_LUMA_CNTL,
1332 (saa711x_read(client, R_09_LUMA_CNTL) & 0x7f) |
1f8f5fa9
HV
1333 (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
1334 break;
1335 }
1336
e19b2fcc
HV
1337 case VIDIOC_STREAMON:
1338 case VIDIOC_STREAMOFF:
f167cb4e 1339 v4l_dbg(1, debug, client, "%s output\n",
e19b2fcc
HV
1340 (cmd == VIDIOC_STREAMON) ? "enable" : "disable");
1341
1342 if (state->enable != (cmd == VIDIOC_STREAMON)) {
1343 state->enable = (cmd == VIDIOC_STREAMON);
66ec1193 1344 saa711x_write(client,
96ecfc4e
MCC
1345 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED,
1346 state->enable);
e19b2fcc
HV
1347 }
1348 break;
1349
b7f8292c
HV
1350 case VIDIOC_INT_S_CRYSTAL_FREQ:
1351 {
1352 struct v4l2_crystal_freq *freq = arg;
1353
1354 if (freq->freq != SAA7115_FREQ_32_11_MHZ &&
1355 freq->freq != SAA7115_FREQ_24_576_MHZ)
1356 return -EINVAL;
1357 state->crystal_freq = freq->freq;
1358 state->cgcdiv = (freq->flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
1359 state->ucgc = (freq->flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;
1360 state->apll = (freq->flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;
66ec1193 1361 saa711x_set_audio_clock_freq(client, state->audclk_freq);
b7f8292c
HV
1362 break;
1363 }
1364
e19b2fcc 1365 case VIDIOC_INT_DECODE_VBI_LINE:
66ec1193 1366 saa711x_decode_vbi_line(client, arg);
e19b2fcc
HV
1367 break;
1368
1369 case VIDIOC_INT_RESET:
f167cb4e 1370 v4l_dbg(1, debug, client, "decoder RESET\n");
66ec1193 1371 saa711x_writeregs(client, saa7115_cfg_reset_scaler);
e19b2fcc
HV
1372 break;
1373
1374 case VIDIOC_INT_G_VBI_DATA:
1375 {
1376 struct v4l2_sliced_vbi_data *data = arg;
1377
1378 switch (data->id) {
1379 case V4L2_SLICED_WSS_625:
66ec1193 1380 if (saa711x_read(client, 0x6b) & 0xc0)
e19b2fcc 1381 return -EIO;
66ec1193
MCC
1382 data->data[0] = saa711x_read(client, 0x6c);
1383 data->data[1] = saa711x_read(client, 0x6d);
e19b2fcc
HV
1384 return 0;
1385 case V4L2_SLICED_CAPTION_525:
1386 if (data->field == 0) {
1387 /* CC */
66ec1193 1388 if (saa711x_read(client, 0x66) & 0xc0)
e19b2fcc 1389 return -EIO;
66ec1193
MCC
1390 data->data[0] = saa711x_read(client, 0x67);
1391 data->data[1] = saa711x_read(client, 0x68);
e19b2fcc
HV
1392 return 0;
1393 }
1394 /* XDS */
66ec1193 1395 if (saa711x_read(client, 0x66) & 0x30)
e19b2fcc 1396 return -EIO;
66ec1193
MCC
1397 data->data[0] = saa711x_read(client, 0x69);
1398 data->data[1] = saa711x_read(client, 0x6a);
e19b2fcc
HV
1399 return 0;
1400 default:
1401 return -EINVAL;
1402 }
1403 break;
1404 }
1405
1406#ifdef CONFIG_VIDEO_ADV_DEBUG
1407 case VIDIOC_INT_G_REGISTER:
1408 {
1409 struct v4l2_register *reg = arg;
1410
1411 if (reg->i2c_id != I2C_DRIVERID_SAA711X)
1412 return -EINVAL;
66ec1193 1413 reg->val = saa711x_read(client, reg->reg & 0xff);
e19b2fcc
HV
1414 break;
1415 }
1416
1417 case VIDIOC_INT_S_REGISTER:
1418 {
1419 struct v4l2_register *reg = arg;
1420
1421 if (reg->i2c_id != I2C_DRIVERID_SAA711X)
1422 return -EINVAL;
1423 if (!capable(CAP_SYS_ADMIN))
1424 return -EPERM;
66ec1193 1425 saa711x_write(client, reg->reg & 0xff, reg->val & 0xff);
e19b2fcc
HV
1426 break;
1427 }
1428#endif
1429
1430 case VIDIOC_INT_G_CHIP_IDENT:
1431 *iarg = state->ident;
1432 break;
1433
1434 default:
1435 return -EINVAL;
1436 }
1437
1438 return 0;
1439}
1440
1441/* ----------------------------------------------------------------------- */
1442
66ec1193 1443static struct i2c_driver i2c_driver_saa711x;
e19b2fcc 1444
66ec1193 1445static int saa711x_attach(struct i2c_adapter *adapter, int address, int kind)
e19b2fcc
HV
1446{
1447 struct i2c_client *client;
66ec1193 1448 struct saa711x_state *state;
236f16d2
MCC
1449 int i;
1450 char name[17];
e19b2fcc
HV
1451 u8 chip_id;
1452
1453 /* Check if the adapter supports the needed features */
1454 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
1455 return 0;
1456
7408187d 1457 client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
e19b2fcc
HV
1458 if (client == 0)
1459 return -ENOMEM;
e19b2fcc
HV
1460 client->addr = address;
1461 client->adapter = adapter;
66ec1193 1462 client->driver = &i2c_driver_saa711x;
e19b2fcc
HV
1463 snprintf(client->name, sizeof(client->name) - 1, "saa7115");
1464
f167cb4e 1465 v4l_dbg(1, debug, client, "detecting saa7115 client on address 0x%x\n", address << 1);
e19b2fcc 1466
236f16d2 1467 for (i=0;i<0x0f;i++) {
66ec1193
MCC
1468 saa711x_write(client, 0, i);
1469 name[i] = (saa711x_read(client, 0) &0x0f) +'0';
236f16d2
MCC
1470 if (name[i]>'9')
1471 name[i]+='a'-'9'-1;
1472 }
1473 name[i]='\0';
1474
66ec1193
MCC
1475 saa711x_write(client, 0, 5);
1476 chip_id = saa711x_read(client, 0) & 0x0f;
3e7d3e57 1477
f5762e44 1478 snprintf(client->name, sizeof(client->name) - 1, "saa711%d",chip_id);
236f16d2 1479 v4l_info(client, "saa711%d found (%s) @ 0x%x (%s)\n", chip_id, name, address << 1, adapter->name);
e19b2fcc 1480
66ec1193 1481 state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL);
e19b2fcc
HV
1482 i2c_set_clientdata(client, state);
1483 if (state == NULL) {
1484 kfree(client);
1485 return -ENOMEM;
1486 }
e19b2fcc
HV
1487 state->input = -1;
1488 state->enable = 1;
3faeeae4 1489 state->radio = 0;
e19b2fcc
HV
1490 state->bright = 128;
1491 state->contrast = 64;
1492 state->hue = 0;
1493 state->sat = 64;
f5762e44 1494 switch (chip_id) {
89f75ffc
MCC
1495 case 1:
1496 state->ident = V4L2_IDENT_SAA7111;
1497 break;
f5762e44
MCC
1498 case 3:
1499 state->ident = V4L2_IDENT_SAA7113;
1500 break;
1501 case 4:
1502 state->ident = V4L2_IDENT_SAA7114;
1503 break;
89f75ffc 1504 case 5:
f5762e44
MCC
1505 state->ident = V4L2_IDENT_SAA7115;
1506 break;
89f75ffc
MCC
1507 case 8:
1508 state->ident = V4L2_IDENT_SAA7118;
1509 break;
1510 default:
1511 state->ident = V4L2_IDENT_SAA7111;
1512 v4l_info(client, "WARNING: Chip is not known - Falling back to saa7111\n");
1513
f5762e44
MCC
1514 }
1515
3578d3dd 1516 state->audclk_freq = 48000;
e19b2fcc 1517
f167cb4e 1518 v4l_dbg(1, debug, client, "writing init values\n");
e19b2fcc
HV
1519
1520 /* init to 60hz/48khz */
89f75ffc
MCC
1521 if (state->ident == V4L2_IDENT_SAA7111 ||
1522 state->ident == V4L2_IDENT_SAA7113) {
b7f8292c 1523 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
66ec1193 1524 saa711x_writeregs(client, saa7113_init_auto_input);
b7f8292c
HV
1525 } else {
1526 state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
66ec1193 1527 saa711x_writeregs(client, saa7115_init_auto_input);
b7f8292c 1528 }
66ec1193 1529 saa711x_writeregs(client, saa7115_init_misc);
d9dce96f 1530 saa711x_set_v4lstd(client, V4L2_STD_NTSC);
e19b2fcc
HV
1531
1532 i2c_attach_client(client);
1533
f167cb4e 1534 v4l_dbg(1, debug, client, "status: (1E) 0x%02x, (1F) 0x%02x\n",
59ba9154 1535 saa711x_read(client, R_1E_STATUS_BYTE_1_VD_DEC), saa711x_read(client, R_1F_STATUS_BYTE_2_VD_DEC));
e19b2fcc
HV
1536
1537 return 0;
1538}
1539
66ec1193 1540static int saa711x_probe(struct i2c_adapter *adapter)
e19b2fcc 1541{
e19b2fcc 1542 if (adapter->class & I2C_CLASS_TV_ANALOG)
66ec1193 1543 return i2c_probe(adapter, &addr_data, &saa711x_attach);
e19b2fcc
HV
1544 return 0;
1545}
1546
66ec1193 1547static int saa711x_detach(struct i2c_client *client)
e19b2fcc 1548{
66ec1193 1549 struct saa711x_state *state = i2c_get_clientdata(client);
e19b2fcc
HV
1550 int err;
1551
1552 err = i2c_detach_client(client);
1553 if (err) {
1554 return err;
1555 }
1556
1557 kfree(state);
1558 kfree(client);
1559 return 0;
1560}
1561
1562/* ----------------------------------------------------------------------- */
1563
1564/* i2c implementation */
66ec1193 1565static struct i2c_driver i2c_driver_saa711x = {
604f28e2 1566 .driver = {
604f28e2
LR
1567 .name = "saa7115",
1568 },
e19b2fcc 1569 .id = I2C_DRIVERID_SAA711X,
66ec1193
MCC
1570 .attach_adapter = saa711x_probe,
1571 .detach_client = saa711x_detach,
1572 .command = saa711x_command,
e19b2fcc
HV
1573};
1574
1575
66ec1193 1576static int __init saa711x_init_module(void)
e19b2fcc 1577{
66ec1193 1578 return i2c_add_driver(&i2c_driver_saa711x);
e19b2fcc
HV
1579}
1580
66ec1193 1581static void __exit saa711x_cleanup_module(void)
e19b2fcc 1582{
66ec1193 1583 i2c_del_driver(&i2c_driver_saa711x);
e19b2fcc
HV
1584}
1585
66ec1193
MCC
1586module_init(saa711x_init_module);
1587module_exit(saa711x_cleanup_module);