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