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