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