V4L/DVB (9296): Patch to remove warning message during cx88-dvb compilation
[deliverable/linux.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>
3434eb7e 48#include <media/v4l2-chip-ident.h>
fbaa3d0d 49#include <media/v4l2-i2c-drv-legacy.h>
1f8f5fa9 50#include <media/saa7115.h>
3578d3dd 51#include <asm/div64.h>
e19b2fcc 52
97d9e80e 53#define VRES_60HZ (480+16)
d9dce96f 54
89f75ffc 55MODULE_DESCRIPTION("Philips SAA7111/SAA7113/SAA7114/SAA7115/SAA7118 video decoder driver");
f5762e44
MCC
56MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
57 "Hans Verkuil, Mauro Carvalho Chehab");
e19b2fcc
HV
58MODULE_LICENSE("GPL");
59
ff699e6b 60static int debug;
fac9e899 61module_param(debug, bool, 0644);
e19b2fcc
HV
62
63MODULE_PARM_DESC(debug, "Debug level (0-1)");
64
f5762e44 65static unsigned short normal_i2c[] = {
89f75ffc
MCC
66 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */
67 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */
f5762e44 68 I2C_CLIENT_END };
e19b2fcc 69
e19b2fcc
HV
70I2C_CLIENT_INSMOD;
71
66ec1193 72struct saa711x_state {
e19b2fcc
HV
73 v4l2_std_id std;
74 int input;
4cbca185 75 int output;
e19b2fcc 76 int enable;
3faeeae4 77 int radio;
e19b2fcc
HV
78 int bright;
79 int contrast;
80 int hue;
81 int sat;
d9dce96f
MCC
82 int width;
83 int height;
3434eb7e 84 u32 ident;
3578d3dd 85 u32 audclk_freq;
b7f8292c
HV
86 u32 crystal_freq;
87 u8 ucgc;
88 u8 cgcdiv;
89 u8 apll;
e19b2fcc
HV
90};
91
92/* ----------------------------------------------------------------------- */
93
66ec1193 94static inline int saa711x_write(struct i2c_client *client, u8 reg, u8 value)
e19b2fcc
HV
95{
96 return i2c_smbus_write_byte_data(client, reg, value);
97}
98
89f75ffc
MCC
99/* Sanity routine to check if a register is present */
100static int saa711x_has_reg(const int id, const u8 reg)
101{
d9dce96f
MCC
102 if (id == V4L2_IDENT_SAA7111)
103 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
104 (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e;
105
106 /* common for saa7113/4/5/8 */
107 if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f ||
108 reg == 0xa3 || reg == 0xa7 || reg == 0xab || reg == 0xaf || (reg >= 0xb5 && reg <= 0xb7) ||
109 reg == 0xd3 || reg == 0xd7 || reg == 0xdb || reg == 0xdf || (reg >= 0xe5 && reg <= 0xe7) ||
110 reg == 0x82 || (reg >= 0x89 && reg <= 0x8e)))
111 return 0;
112
89f75ffc 113 switch (id) {
89f75ffc 114 case V4L2_IDENT_SAA7113:
d9dce96f
MCC
115 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
116 reg != 0x5d && reg < 0x63;
89f75ffc 117 case V4L2_IDENT_SAA7114:
d9dce96f
MCC
118 return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
119 (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
120 reg != 0x81 && reg < 0xf0;
89f75ffc 121 case V4L2_IDENT_SAA7115:
d9dce96f 122 return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe);
89f75ffc 123 case V4L2_IDENT_SAA7118:
d9dce96f
MCC
124 return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
125 (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
126 (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
89f75ffc 127 }
89f75ffc
MCC
128 return 1;
129}
130
66ec1193 131static int saa711x_writeregs(struct i2c_client *client, const unsigned char *regs)
e19b2fcc 132{
66ec1193 133 struct saa711x_state *state = i2c_get_clientdata(client);
e19b2fcc
HV
134 unsigned char reg, data;
135
136 while (*regs != 0x00) {
137 reg = *(regs++);
138 data = *(regs++);
89f75ffc
MCC
139
140 /* According with datasheets, reserved regs should be
141 filled with 0 - seems better not to touch on they */
142 if (saa711x_has_reg(state->ident,reg)) {
66ec1193 143 if (saa711x_write(client, reg, data) < 0)
89f75ffc 144 return -1;
d87edf26
MCC
145 } else {
146 v4l_dbg(1, debug, client, "tried to access reserved reg 0x%02x\n", reg);
89f75ffc 147 }
e19b2fcc
HV
148 }
149 return 0;
150}
151
66ec1193 152static inline int saa711x_read(struct i2c_client *client, u8 reg)
e19b2fcc
HV
153{
154 return i2c_smbus_read_byte_data(client, reg);
155}
156
157/* ----------------------------------------------------------------------- */
158
89f75ffc 159/* SAA7111 initialization table */
183d896a 160static const unsigned char saa7111_init[] = {
89f75ffc
MCC
161 R_01_INC_DELAY, 0x00, /* reserved */
162
163 /*front end */
164 R_02_INPUT_CNTL_1, 0xd0, /* FUSE=3, GUDL=2, MODE=0 */
165 R_03_INPUT_CNTL_2, 0x23, /* HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0,
166 * GAFIX=0, GAI1=256, GAI2=256 */
167 R_04_INPUT_CNTL_3, 0x00, /* GAI1=256 */
168 R_05_INPUT_CNTL_4, 0x00, /* GAI2=256 */
169
170 /* decoder */
171 R_06_H_SYNC_START, 0xf3, /* HSB at 13(50Hz) / 17(60Hz)
172 * pixels after end of last line */
173 R_07_H_SYNC_STOP, 0xe8, /* HSS seems to be needed to
174 * work with NTSC, too */
175 R_08_SYNC_CNTL, 0xc8, /* AUFD=1, FSEL=1, EXFIL=0,
176 * VTRC=1, HPLL=0, VNOI=0 */
177 R_09_LUMA_CNTL, 0x01, /* BYPS=0, PREF=0, BPSS=0,
178 * VBLB=0, UPTCV=0, APER=1 */
179 R_0A_LUMA_BRIGHT_CNTL, 0x80,
180 R_0B_LUMA_CONTRAST_CNTL, 0x47, /* 0b - CONT=1.109 */
181 R_0C_CHROMA_SAT_CNTL, 0x40,
182 R_0D_CHROMA_HUE_CNTL, 0x00,
183 R_0E_CHROMA_CNTL_1, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0,
184 * FCTC=0, CHBW=1 */
185 R_0F_CHROMA_GAIN_CNTL, 0x00, /* reserved */
186 R_10_CHROMA_CNTL_2, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
187 R_11_MODE_DELAY_CNTL, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
188 * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
189 R_12_RT_SIGNAL_CNTL, 0x00, /* 12 - output control 2 */
190 R_13_RT_X_PORT_OUT_CNTL, 0x00, /* 13 - output control 3 */
191 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
192 R_15_VGATE_START_FID_CHG, 0x00,
193 R_16_VGATE_STOP, 0x00,
194 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
195
196 0x00, 0x00
197};
198
199/* SAA7113 init codes */
183d896a 200static const unsigned char saa7113_init[] = {
89f75ffc
MCC
201 R_01_INC_DELAY, 0x08,
202 R_02_INPUT_CNTL_1, 0xc2,
203 R_03_INPUT_CNTL_2, 0x30,
204 R_04_INPUT_CNTL_3, 0x00,
205 R_05_INPUT_CNTL_4, 0x00,
206 R_06_H_SYNC_START, 0x89,
207 R_07_H_SYNC_STOP, 0x0d,
208 R_08_SYNC_CNTL, 0x88,
209 R_09_LUMA_CNTL, 0x01,
210 R_0A_LUMA_BRIGHT_CNTL, 0x80,
211 R_0B_LUMA_CONTRAST_CNTL, 0x47,
212 R_0C_CHROMA_SAT_CNTL, 0x40,
213 R_0D_CHROMA_HUE_CNTL, 0x00,
214 R_0E_CHROMA_CNTL_1, 0x01,
215 R_0F_CHROMA_GAIN_CNTL, 0x2a,
216 R_10_CHROMA_CNTL_2, 0x08,
217 R_11_MODE_DELAY_CNTL, 0x0c,
218 R_12_RT_SIGNAL_CNTL, 0x07,
219 R_13_RT_X_PORT_OUT_CNTL, 0x00,
220 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
221 R_15_VGATE_START_FID_CHG, 0x00,
222 R_16_VGATE_STOP, 0x00,
223 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
224
225 0x00, 0x00
226};
227
e19b2fcc
HV
228/* If a value differs from the Hauppauge driver values, then the comment starts with
229 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
230 Hauppauge driver sets. */
231
89f75ffc 232/* SAA7114 and SAA7115 initialization table */
e19b2fcc 233static const unsigned char saa7115_init_auto_input[] = {
f5762e44 234 /* Front-End Part */
96ecfc4e
MCC
235 R_01_INC_DELAY, 0x48, /* white peak control disabled */
236 R_03_INPUT_CNTL_2, 0x20, /* was 0x30. 0x20: long vertical blanking */
237 R_04_INPUT_CNTL_3, 0x90, /* analog gain set to 0 */
238 R_05_INPUT_CNTL_4, 0x90, /* analog gain set to 0 */
f5762e44 239 /* Decoder Part */
96ecfc4e
MCC
240 R_06_H_SYNC_START, 0xeb, /* horiz sync begin = -21 */
241 R_07_H_SYNC_STOP, 0xe0, /* horiz sync stop = -17 */
183d896a 242 R_09_LUMA_CNTL, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */
96ecfc4e
MCC
243 R_0A_LUMA_BRIGHT_CNTL, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */
244 R_0B_LUMA_CONTRAST_CNTL, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */
245 R_0C_CHROMA_SAT_CNTL, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */
246 R_0D_CHROMA_HUE_CNTL, 0x00,
247 R_0F_CHROMA_GAIN_CNTL, 0x00, /* use automatic gain */
248 R_10_CHROMA_CNTL_2, 0x06, /* chroma: active adaptive combfilter */
249 R_11_MODE_DELAY_CNTL, 0x00,
250 R_12_RT_SIGNAL_CNTL, 0x9d, /* RTS0 output control: VGATE */
251 R_13_RT_X_PORT_OUT_CNTL, 0x80, /* ITU656 standard mode, RTCO output enable RTCE */
252 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
253 R_18_RAW_DATA_GAIN_CNTL, 0x40, /* gain 0x00 = nominal */
254 R_19_RAW_DATA_OFF_CNTL, 0x80,
255 R_1A_COLOR_KILL_LVL_CNTL, 0x77, /* recommended value */
256 R_1B_MISC_TVVCRDET, 0x42, /* recommended value */
257 R_1C_ENHAN_COMB_CTRL1, 0xa9, /* recommended value */
258 R_1D_ENHAN_COMB_CTRL2, 0x01, /* recommended value */
f5762e44 259
d9dce96f
MCC
260
261 R_80_GLOBAL_CNTL_1, 0x0, /* No tasks enabled at init */
262
f5762e44 263 /* Power Device Control */
96ecfc4e
MCC
264 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset device */
265 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* set device programmed, all in operational mode */
e19b2fcc
HV
266 0x00, 0x00
267};
268
89f75ffc 269/* Used to reset saa7113, saa7114 and saa7115 */
e19b2fcc 270static const unsigned char saa7115_cfg_reset_scaler[] = {
96ecfc4e
MCC
271 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00, /* disable I-port output */
272 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
273 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
274 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* enable I-port output */
e19b2fcc
HV
275 0x00, 0x00
276};
277
278/* ============== SAA7715 VIDEO templates ============= */
279
e19b2fcc 280static const unsigned char saa7115_cfg_60hz_video[] = {
96ecfc4e
MCC
281 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
282 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
e19b2fcc 283
96ecfc4e
MCC
284 R_15_VGATE_START_FID_CHG, 0x03,
285 R_16_VGATE_STOP, 0x11,
286 R_17_MISC_VGATE_CONF_AND_MSB, 0x9c,
e19b2fcc 287
96ecfc4e
MCC
288 R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
289 R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */
e19b2fcc 290
96ecfc4e 291 R_5A_V_OFF_FOR_SLICER, 0x06, /* standard 60hz value for ITU656 line counting */
e19b2fcc
HV
292
293 /* Task A */
96ecfc4e
MCC
294 R_90_A_TASK_HANDLING_CNTL, 0x80,
295 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
296 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
297 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
298
299 /* hoffset low (input), 0x0002 is minimum */
300 R_94_A_HORIZ_INPUT_WINDOW_START, 0x01,
301 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
302
303 /* hsize low (input), 0x02d0 = 720 */
304 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
305 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
306
307 R_98_A_VERT_INPUT_WINDOW_START, 0x05,
308 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
309
310 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x0c,
311 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
312
313 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
314 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
315
316 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x0c,
317 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
e19b2fcc
HV
318
319 /* Task B */
96ecfc4e
MCC
320 R_C0_B_TASK_HANDLING_CNTL, 0x00,
321 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
322 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
323 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
324
325 /* 0x0002 is minimum */
326 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x02,
327 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
328
329 /* 0x02d0 = 720 */
330 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
331 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
332
333 /* vwindow start 0x12 = 18 */
334 R_C8_B_VERT_INPUT_WINDOW_START, 0x12,
335 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
336
337 /* vwindow length 0xf8 = 248 */
97d9e80e
MCC
338 R_CA_B_VERT_INPUT_WINDOW_LENGTH, VRES_60HZ>>1,
339 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, VRES_60HZ>>9,
96ecfc4e
MCC
340
341 /* hwindow 0x02d0 = 720 */
342 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
343 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
344
345 R_F0_LFCO_PER_LINE, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
346 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0 */
347 R_F5_PULSGEN_LINE_LENGTH, 0xad,
348 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
349
e19b2fcc
HV
350 0x00, 0x00
351};
352
e19b2fcc 353static const unsigned char saa7115_cfg_50hz_video[] = {
96ecfc4e
MCC
354 R_80_GLOBAL_CNTL_1, 0x00,
355 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
e19b2fcc 356
96ecfc4e
MCC
357 R_15_VGATE_START_FID_CHG, 0x37, /* VGATE start */
358 R_16_VGATE_STOP, 0x16,
359 R_17_MISC_VGATE_CONF_AND_MSB, 0x99,
e19b2fcc 360
96ecfc4e
MCC
361 R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */
362 R_0E_CHROMA_CNTL_1, 0x07,
e19b2fcc 363
96ecfc4e 364 R_5A_V_OFF_FOR_SLICER, 0x03, /* standard 50hz value */
e19b2fcc
HV
365
366 /* Task A */
96ecfc4e
MCC
367 R_90_A_TASK_HANDLING_CNTL, 0x81,
368 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
369 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
370 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
371
e19b2fcc
HV
372 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
373 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
96ecfc4e
MCC
374 /* hoffset low (input), 0x0002 is minimum */
375 R_94_A_HORIZ_INPUT_WINDOW_START, 0x00,
376 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
377
378 /* hsize low (input), 0x02d0 = 720 */
379 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
380 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
381
382 R_98_A_VERT_INPUT_WINDOW_START, 0x03,
383 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
384
385 /* vsize 0x12 = 18 */
386 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x12,
387 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
388
389 /* hsize 0x05a0 = 1440 */
390 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
391 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05, /* hsize hi (output) */
392 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x12, /* vsize low (output), 0x12 = 18 */
393 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00, /* vsize hi (output) */
e19b2fcc
HV
394
395 /* Task B */
96ecfc4e
MCC
396 R_C0_B_TASK_HANDLING_CNTL, 0x00,
397 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
398 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
399 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
400
401 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
402 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
403 /* hoffset low (input), 0x0002 is minimum. See comment above. */
404 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x00,
405 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
406
407 /* hsize 0x02d0 = 720 */
408 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
409 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
410
411 /* voffset 0x16 = 22 */
412 R_C8_B_VERT_INPUT_WINDOW_START, 0x16,
413 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
414
415 /* vsize 0x0120 = 288 */
416 R_CA_B_VERT_INPUT_WINDOW_LENGTH, 0x20,
417 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, 0x01,
418
419 /* hsize 0x02d0 = 720 */
420 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
421 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
422
96ecfc4e
MCC
423 R_F0_LFCO_PER_LINE, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
424 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0, (was 0x05) */
425 R_F5_PULSGEN_LINE_LENGTH, 0xb0,
426 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
427
e19b2fcc
HV
428 0x00, 0x00
429};
430
431/* ============== SAA7715 VIDEO templates (end) ======= */
432
433static const unsigned char saa7115_cfg_vbi_on[] = {
96ecfc4e
MCC
434 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
435 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
436 R_80_GLOBAL_CNTL_1, 0x30, /* Activate both tasks */
437 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
438 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
439
e19b2fcc
HV
440 0x00, 0x00
441};
442
443static const unsigned char saa7115_cfg_vbi_off[] = {
96ecfc4e
MCC
444 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
445 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
446 R_80_GLOBAL_CNTL_1, 0x20, /* Activate only task "B" */
447 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
448 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
449
e19b2fcc
HV
450 0x00, 0x00
451};
452
f5762e44 453
e19b2fcc 454static const unsigned char saa7115_init_misc[] = {
96ecfc4e 455 R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
96ecfc4e
MCC
456 R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 0x01,
457 R_84_I_PORT_SIGNAL_DEF, 0x20,
458 R_85_I_PORT_SIGNAL_POLAR, 0x21,
459 R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT, 0xc5,
460 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
e19b2fcc
HV
461
462 /* Task A */
96ecfc4e
MCC
463 R_A0_A_HORIZ_PRESCALING, 0x01,
464 R_A1_A_ACCUMULATION_LENGTH, 0x00,
465 R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
466
467 /* Configure controls at nominal value*/
468 R_A4_A_LUMA_BRIGHTNESS_CNTL, 0x80,
469 R_A5_A_LUMA_CONTRAST_CNTL, 0x40,
470 R_A6_A_CHROMA_SATURATION_CNTL, 0x40,
471
472 /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
473 R_A8_A_HORIZ_LUMA_SCALING_INC, 0x00,
474 R_A9_A_HORIZ_LUMA_SCALING_INC_MSB, 0x02,
475
476 R_AA_A_HORIZ_LUMA_PHASE_OFF, 0x00,
477
478 /* must be horiz lum scaling / 2 */
479 R_AC_A_HORIZ_CHROMA_SCALING_INC, 0x00,
480 R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB, 0x01,
481
482 /* must be offset luma / 2 */
483 R_AE_A_HORIZ_CHROMA_PHASE_OFF, 0x00,
484
485 R_B0_A_VERT_LUMA_SCALING_INC, 0x00,
486 R_B1_A_VERT_LUMA_SCALING_INC_MSB, 0x04,
487
488 R_B2_A_VERT_CHROMA_SCALING_INC, 0x00,
489 R_B3_A_VERT_CHROMA_SCALING_INC_MSB, 0x04,
490
491 R_B4_A_VERT_SCALING_MODE_CNTL, 0x01,
492
493 R_B8_A_VERT_CHROMA_PHASE_OFF_00, 0x00,
494 R_B9_A_VERT_CHROMA_PHASE_OFF_01, 0x00,
495 R_BA_A_VERT_CHROMA_PHASE_OFF_10, 0x00,
496 R_BB_A_VERT_CHROMA_PHASE_OFF_11, 0x00,
497
498 R_BC_A_VERT_LUMA_PHASE_OFF_00, 0x00,
499 R_BD_A_VERT_LUMA_PHASE_OFF_01, 0x00,
500 R_BE_A_VERT_LUMA_PHASE_OFF_10, 0x00,
501 R_BF_A_VERT_LUMA_PHASE_OFF_11, 0x00,
e19b2fcc
HV
502
503 /* Task B */
96ecfc4e
MCC
504 R_D0_B_HORIZ_PRESCALING, 0x01,
505 R_D1_B_ACCUMULATION_LENGTH, 0x00,
506 R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
507
508 /* Configure controls at nominal value*/
509 R_D4_B_LUMA_BRIGHTNESS_CNTL, 0x80,
510 R_D5_B_LUMA_CONTRAST_CNTL, 0x40,
511 R_D6_B_CHROMA_SATURATION_CNTL, 0x40,
512
513 /* hor lum scaling 0x0400 = 1 */
514 R_D8_B_HORIZ_LUMA_SCALING_INC, 0x00,
515 R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, 0x04,
516
517 R_DA_B_HORIZ_LUMA_PHASE_OFF, 0x00,
518
519 /* must be hor lum scaling / 2 */
520 R_DC_B_HORIZ_CHROMA_SCALING, 0x00,
521 R_DD_B_HORIZ_CHROMA_SCALING_MSB, 0x02,
522
523 /* must be offset luma / 2 */
524 R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA, 0x00,
525
526 R_E0_B_VERT_LUMA_SCALING_INC, 0x00,
527 R_E1_B_VERT_LUMA_SCALING_INC_MSB, 0x04,
528
529 R_E2_B_VERT_CHROMA_SCALING_INC, 0x00,
530 R_E3_B_VERT_CHROMA_SCALING_INC_MSB, 0x04,
531
532 R_E4_B_VERT_SCALING_MODE_CNTL, 0x01,
533
534 R_E8_B_VERT_CHROMA_PHASE_OFF_00, 0x00,
535 R_E9_B_VERT_CHROMA_PHASE_OFF_01, 0x00,
536 R_EA_B_VERT_CHROMA_PHASE_OFF_10, 0x00,
537 R_EB_B_VERT_CHROMA_PHASE_OFF_11, 0x00,
538
539 R_EC_B_VERT_LUMA_PHASE_OFF_00, 0x00,
540 R_ED_B_VERT_LUMA_PHASE_OFF_01, 0x00,
541 R_EE_B_VERT_LUMA_PHASE_OFF_10, 0x00,
542 R_EF_B_VERT_LUMA_PHASE_OFF_11, 0x00,
543
544 R_F2_NOMINAL_PLL2_DTO, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */
545 R_F3_PLL_INCREMENT, 0x46,
546 R_F4_PLL2_STATUS, 0x00,
547 R_F7_PULSE_A_POS_MSB, 0x4b, /* not the recommended settings! */
548 R_F8_PULSE_B_POS, 0x00,
549 R_F9_PULSE_B_POS_MSB, 0x4b,
550 R_FA_PULSE_C_POS, 0x00,
551 R_FB_PULSE_C_POS_MSB, 0x4b,
552
553 /* PLL2 lock detection settings: 71 lines 50% phase error */
554 R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES, 0x88,
e19b2fcc
HV
555
556 /* Turn off VBI */
96ecfc4e
MCC
557 R_40_SLICER_CNTL_1, 0x20, /* No framing code errors allowed. */
558 R_41_LCR_BASE, 0xff,
559 R_41_LCR_BASE+1, 0xff,
560 R_41_LCR_BASE+2, 0xff,
561 R_41_LCR_BASE+3, 0xff,
562 R_41_LCR_BASE+4, 0xff,
563 R_41_LCR_BASE+5, 0xff,
564 R_41_LCR_BASE+6, 0xff,
565 R_41_LCR_BASE+7, 0xff,
566 R_41_LCR_BASE+8, 0xff,
567 R_41_LCR_BASE+9, 0xff,
568 R_41_LCR_BASE+10, 0xff,
569 R_41_LCR_BASE+11, 0xff,
570 R_41_LCR_BASE+12, 0xff,
571 R_41_LCR_BASE+13, 0xff,
572 R_41_LCR_BASE+14, 0xff,
573 R_41_LCR_BASE+15, 0xff,
574 R_41_LCR_BASE+16, 0xff,
575 R_41_LCR_BASE+17, 0xff,
576 R_41_LCR_BASE+18, 0xff,
577 R_41_LCR_BASE+19, 0xff,
578 R_41_LCR_BASE+20, 0xff,
579 R_41_LCR_BASE+21, 0xff,
580 R_41_LCR_BASE+22, 0xff,
581 R_58_PROGRAM_FRAMING_CODE, 0x40,
582 R_59_H_OFF_FOR_SLICER, 0x47,
583 R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF, 0x83,
584 R_5D_DID, 0xbd,
585 R_5E_SDID, 0x35,
586
587 R_02_INPUT_CNTL_1, 0x84, /* input tuner -> input 4, amplifier active */
96ecfc4e
MCC
588
589 R_80_GLOBAL_CNTL_1, 0x20, /* enable task B */
590 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
591 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
e19b2fcc
HV
592 0x00, 0x00
593};
594
66ec1193 595static int saa711x_odd_parity(u8 c)
e19b2fcc
HV
596{
597 c ^= (c >> 4);
598 c ^= (c >> 2);
599 c ^= (c >> 1);
600
601 return c & 1;
602}
603
66ec1193 604static int saa711x_decode_vps(u8 * dst, u8 * p)
e19b2fcc
HV
605{
606 static const u8 biphase_tbl[] = {
607 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
608 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
609 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
610 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
611 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
612 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
613 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
614 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
615 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
616 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
617 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
618 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
619 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
620 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
621 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
622 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
623 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
624 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
625 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
626 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
627 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
628 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
629 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
630 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
631 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
632 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
633 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
634 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
635 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
636 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
637 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
638 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
639 };
640 int i;
641 u8 c, err = 0;
642
643 for (i = 0; i < 2 * 13; i += 2) {
644 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
645 c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
646 dst[i / 2] = c;
647 }
648 return err & 0xf0;
649}
650
66ec1193 651static int saa711x_decode_wss(u8 * p)
e19b2fcc
HV
652{
653 static const int wss_bits[8] = {
654 0, 0, 0, 1, 0, 1, 1, 1
655 };
656 unsigned char parity;
657 int wss = 0;
658 int i;
659
660 for (i = 0; i < 16; i++) {
661 int b1 = wss_bits[p[i] & 7];
662 int b2 = wss_bits[(p[i] >> 3) & 7];
663
664 if (b1 == b2)
665 return -1;
666 wss |= b2 << i;
667 }
668 parity = wss & 15;
669 parity ^= parity >> 2;
670 parity ^= parity >> 1;
671
672 if (!(parity & 1))
673 return -1;
674
675 return wss;
676}
677
66ec1193 678static int saa711x_set_audio_clock_freq(struct i2c_client *client, u32 freq)
e19b2fcc 679{
66ec1193 680 struct saa711x_state *state = i2c_get_clientdata(client);
3578d3dd
HV
681 u32 acpf;
682 u32 acni;
683 u32 hz;
684 u64 f;
b7f8292c 685 u8 acc = 0; /* reg 0x3a, audio clock control */
e19b2fcc 686
89f75ffc
MCC
687 /* Checks for chips that don't have audio clock (saa7111, saa7113) */
688 if (!saa711x_has_reg(state->ident,R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
689 return 0;
690
f167cb4e 691 v4l_dbg(1, debug, client, "set audio clock freq: %d\n", freq);
3578d3dd
HV
692
693 /* sanity check */
694 if (freq < 32000 || freq > 48000)
695 return -EINVAL;
696
697 /* hz is the refresh rate times 100 */
698 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
699 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
700 acpf = (25600 * freq) / hz;
701 /* acni = (256 * freq * 2^23) / crystal_frequency =
702 (freq * 2^(8+23)) / crystal_frequency =
b7f8292c 703 (freq << 31) / crystal_frequency */
3578d3dd
HV
704 f = freq;
705 f = f << 31;
b7f8292c 706 do_div(f, state->crystal_freq);
3578d3dd 707 acni = f;
b7f8292c
HV
708 if (state->ucgc) {
709 acpf = acpf * state->cgcdiv / 16;
710 acni = acni * state->cgcdiv / 16;
711 acc = 0x80;
712 if (state->cgcdiv == 3)
713 acc |= 0x40;
714 }
715 if (state->apll)
716 acc |= 0x08;
3578d3dd 717
66ec1193
MCC
718 saa711x_write(client, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
719 saa711x_write(client, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10);
720 saa711x_write(client, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
96ecfc4e 721
66ec1193
MCC
722 saa711x_write(client, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
723 saa711x_write(client, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
96ecfc4e 724 (acpf >> 8) & 0xff);
66ec1193 725 saa711x_write(client, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
96ecfc4e
MCC
726 (acpf >> 16) & 0x03);
727
66ec1193
MCC
728 saa711x_write(client, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
729 saa711x_write(client, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
730 saa711x_write(client, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
e19b2fcc
HV
731 state->audclk_freq = freq;
732 return 0;
733}
734
66ec1193 735static int saa711x_set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
e19b2fcc 736{
66ec1193 737 struct saa711x_state *state = i2c_get_clientdata(client);
e19b2fcc
HV
738
739 switch (ctrl->id) {
740 case V4L2_CID_BRIGHTNESS:
741 if (ctrl->value < 0 || ctrl->value > 255) {
fac9e899 742 v4l_err(client, "invalid brightness setting %d\n", ctrl->value);
e19b2fcc
HV
743 return -ERANGE;
744 }
745
746 state->bright = ctrl->value;
66ec1193 747 saa711x_write(client, R_0A_LUMA_BRIGHT_CNTL, state->bright);
e19b2fcc
HV
748 break;
749
750 case V4L2_CID_CONTRAST:
751 if (ctrl->value < 0 || ctrl->value > 127) {
fac9e899 752 v4l_err(client, "invalid contrast setting %d\n", ctrl->value);
e19b2fcc
HV
753 return -ERANGE;
754 }
755
756 state->contrast = ctrl->value;
66ec1193 757 saa711x_write(client, R_0B_LUMA_CONTRAST_CNTL, state->contrast);
e19b2fcc
HV
758 break;
759
760 case V4L2_CID_SATURATION:
761 if (ctrl->value < 0 || ctrl->value > 127) {
fac9e899 762 v4l_err(client, "invalid saturation setting %d\n", ctrl->value);
e19b2fcc
HV
763 return -ERANGE;
764 }
765
766 state->sat = ctrl->value;
66ec1193 767 saa711x_write(client, R_0C_CHROMA_SAT_CNTL, state->sat);
e19b2fcc
HV
768 break;
769
770 case V4L2_CID_HUE:
771 if (ctrl->value < -127 || ctrl->value > 127) {
fac9e899 772 v4l_err(client, "invalid hue setting %d\n", ctrl->value);
e19b2fcc
HV
773 return -ERANGE;
774 }
775
776 state->hue = ctrl->value;
66ec1193 777 saa711x_write(client, R_0D_CHROMA_HUE_CNTL, state->hue);
e19b2fcc 778 break;
3faeeae4
HV
779
780 default:
781 return -EINVAL;
e19b2fcc
HV
782 }
783
784 return 0;
785}
786
66ec1193 787static int saa711x_get_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
e19b2fcc 788{
66ec1193 789 struct saa711x_state *state = i2c_get_clientdata(client);
e19b2fcc
HV
790
791 switch (ctrl->id) {
792 case V4L2_CID_BRIGHTNESS:
793 ctrl->value = state->bright;
794 break;
795 case V4L2_CID_CONTRAST:
796 ctrl->value = state->contrast;
797 break;
798 case V4L2_CID_SATURATION:
799 ctrl->value = state->sat;
800 break;
801 case V4L2_CID_HUE:
802 ctrl->value = state->hue;
803 break;
804 default:
805 return -EINVAL;
806 }
807
808 return 0;
809}
810
d9dce96f
MCC
811static int saa711x_set_size(struct i2c_client *client, int width, int height)
812{
813 struct saa711x_state *state = i2c_get_clientdata(client);
814 int HPSC, HFSC;
815 int VSCY;
816 int res;
817 int is_50hz = state->std & V4L2_STD_625_50;
818 int Vsrc = is_50hz ? 576 : 480;
819
820 v4l_dbg(1, debug, client, "decoder set size to %ix%i\n",width,height);
821
822 /* FIXME need better bounds checking here */
823 if ((width < 1) || (width > 1440))
824 return -EINVAL;
825 if ((height < 1) || (height > Vsrc))
826 return -EINVAL;
827
828 if (!saa711x_has_reg(state->ident,R_D0_B_HORIZ_PRESCALING)) {
829 /* Decoder only supports 720 columns and 480 or 576 lines */
830 if (width != 720)
831 return -EINVAL;
832 if (height != Vsrc)
833 return -EINVAL;
834 }
835
836 state->width = width;
837 state->height = height;
838
839 if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
840 return 0;
841
842 /* probably have a valid size, let's set it */
843 /* Set output width/height */
844 /* width */
845
846 saa711x_write(client, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
847 (u8) (width & 0xff));
848 saa711x_write(client, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
849 (u8) ((width >> 8) & 0xff));
850
851 /* Vertical Scaling uses height/2 */
852 res=height/2;
853
854 /* On 60Hz, it is using a higher Vertical Output Size */
855 if (!is_50hz)
d0d30c03 856 res += (VRES_60HZ - 480) >> 1;
d9dce96f
MCC
857
858 /* height */
859 saa711x_write(client, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
860 (u8) (res & 0xff));
861 saa711x_write(client, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
862 (u8) ((res >> 8) & 0xff));
863
864 /* Scaling settings */
865 /* Hprescaler is floor(inres/outres) */
866 HPSC = (int)(720 / width);
867 /* 0 is not allowed (div. by zero) */
868 HPSC = HPSC ? HPSC : 1;
869 HFSC = (int)((1024 * 720) / (HPSC * width));
870 /* FIXME hardcodes to "Task B"
871 * write H prescaler integer */
872 saa711x_write(client, R_D0_B_HORIZ_PRESCALING,
873 (u8) (HPSC & 0x3f));
874
875 v4l_dbg(1, debug, client, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
876 /* write H fine-scaling (luminance) */
877 saa711x_write(client, R_D8_B_HORIZ_LUMA_SCALING_INC,
878 (u8) (HFSC & 0xff));
879 saa711x_write(client, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
880 (u8) ((HFSC >> 8) & 0xff));
881 /* write H fine-scaling (chrominance)
882 * must be lum/2, so i'll just bitshift :) */
883 saa711x_write(client, R_DC_B_HORIZ_CHROMA_SCALING,
884 (u8) ((HFSC >> 1) & 0xff));
885 saa711x_write(client, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
886 (u8) ((HFSC >> 9) & 0xff));
887
888 VSCY = (int)((1024 * Vsrc) / height);
889 v4l_dbg(1, debug, client, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
890
891 /* Correct Contrast and Luminance */
892 saa711x_write(client, R_D5_B_LUMA_CONTRAST_CNTL,
893 (u8) (64 * 1024 / VSCY));
894 saa711x_write(client, R_D6_B_CHROMA_SATURATION_CNTL,
895 (u8) (64 * 1024 / VSCY));
896
897 /* write V fine-scaling (luminance) */
898 saa711x_write(client, R_E0_B_VERT_LUMA_SCALING_INC,
899 (u8) (VSCY & 0xff));
900 saa711x_write(client, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
901 (u8) ((VSCY >> 8) & 0xff));
902 /* write V fine-scaling (chrominance) */
903 saa711x_write(client, R_E2_B_VERT_CHROMA_SCALING_INC,
904 (u8) (VSCY & 0xff));
905 saa711x_write(client, R_E3_B_VERT_CHROMA_SCALING_INC_MSB,
906 (u8) ((VSCY >> 8) & 0xff));
907
908 saa711x_writeregs(client, saa7115_cfg_reset_scaler);
909
910 /* Activates task "B" */
911 saa711x_write(client, R_80_GLOBAL_CNTL_1,
d0d30c03 912 saa711x_read(client,R_80_GLOBAL_CNTL_1) | 0x20);
d9dce96f
MCC
913
914 return 0;
915}
916
66ec1193 917static void saa711x_set_v4lstd(struct i2c_client *client, v4l2_std_id std)
e19b2fcc 918{
66ec1193 919 struct saa711x_state *state = i2c_get_clientdata(client);
e19b2fcc 920
30b54d50
HV
921 /* Prevent unnecessary standard changes. During a standard
922 change the I-Port is temporarily disabled. Any devices
923 reading from that port can get confused.
924 Note that VIDIOC_S_STD is also used to switch from
925 radio to TV mode, so if a VIDIOC_S_STD is broadcast to
926 all I2C devices then you do not want to have an unwanted
927 side-effect here. */
928 if (std == state->std)
929 return;
930
d9dce96f
MCC
931 state->std = std;
932
e19b2fcc
HV
933 // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
934 if (std & V4L2_STD_525_60) {
f167cb4e 935 v4l_dbg(1, debug, client, "decoder set standard 60 Hz\n");
66ec1193 936 saa711x_writeregs(client, saa7115_cfg_60hz_video);
d0d30c03 937 saa711x_set_size(client, 720, 480);
e19b2fcc 938 } else {
f167cb4e 939 v4l_dbg(1, debug, client, "decoder set standard 50 Hz\n");
66ec1193 940 saa711x_writeregs(client, saa7115_cfg_50hz_video);
d0d30c03 941 saa711x_set_size(client, 720, 576);
e19b2fcc
HV
942 }
943
f89982a9 944 /* Register 0E - Bits D6-D4 on NO-AUTO mode
89f75ffc 945 (SAA7111 and SAA7113 doesn't have auto mode)
f89982a9
MCC
946 50 Hz / 625 lines 60 Hz / 525 lines
947 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz)
948 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz)
949 010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz)
950 011 NTSC N (3.58MHz) PAL M (3.58MHz)
951 100 reserved NTSC-Japan (3.58MHz)
952 */
89f75ffc
MCC
953 if (state->ident == V4L2_IDENT_SAA7111 ||
954 state->ident == V4L2_IDENT_SAA7113) {
66ec1193 955 u8 reg = saa711x_read(client, R_0E_CHROMA_CNTL_1) & 0x8f;
f89982a9 956
02c17224 957 if (std == V4L2_STD_PAL_M) {
01342358 958 reg |= 0x30;
e0028027 959 } else if (std == V4L2_STD_PAL_Nc) {
01342358 960 reg |= 0x20;
02c17224 961 } else if (std == V4L2_STD_PAL_60) {
01342358 962 reg |= 0x10;
02c17224 963 } else if (std == V4L2_STD_NTSC_M_JP) {
01342358 964 reg |= 0x40;
a9aaec4e 965 } else if (std & V4L2_STD_SECAM) {