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