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