blob: cf77318ede4314fcbffb5d1fcba3cc64e0c43f12 [file] [log] [blame]
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001/* saa711x - Philips SAA711x video decoder driver
2 * This driver can work with saa7111, saa7111a, saa7113, saa7114,
3 * saa7115 and saa7118.
Hans Verkuile19b2fc2005-11-13 16:08:04 -08004 *
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>
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -030021 *
22 * Copyright (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
23 * SAA7111, SAA7113 and SAA7118 support
Hans Verkuile19b2fc2005-11-13 16:08:04 -080024 *
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
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -030040#include "saa711x_regs.h"
Hans Verkuile19b2fc2005-11-13 16:08:04 -080041
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>
Hans Verkuil9415f4b2008-11-29 12:55:19 -030047#include <media/v4l2-device.h>
Hans Verkuil3434eb72007-04-27 12:31:08 -030048#include <media/v4l2-chip-ident.h>
Hans Verkuilef6078e2009-03-29 17:32:35 -030049#include <media/v4l2-i2c-drv.h>
Hans Verkuil1f8f5fa2006-03-25 09:20:28 -030050#include <media/saa7115.h>
Hans Verkuil3578d3d2006-01-09 15:25:41 -020051#include <asm/div64.h>
Hans Verkuile19b2fc2005-11-13 16:08:04 -080052
Mauro Carvalho Chehab97d9e802006-09-03 09:38:11 -030053#define VRES_60HZ (480+16)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -030054
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -030055MODULE_DESCRIPTION("Philips SAA7111/SAA7113/SAA7114/SAA7115/SAA7118 video decoder driver");
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -030056MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
57 "Hans Verkuil, Mauro Carvalho Chehab");
Hans Verkuile19b2fc2005-11-13 16:08:04 -080058MODULE_LICENSE("GPL");
59
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030060static int debug;
Hans Verkuilfac9e892006-01-09 15:32:40 -020061module_param(debug, bool, 0644);
Hans Verkuile19b2fc2005-11-13 16:08:04 -080062
63MODULE_PARM_DESC(debug, "Debug level (0-1)");
64
Hans Verkuile19b2fc2005-11-13 16:08:04 -080065
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -030066struct saa711x_state {
Hans Verkuil9415f4b2008-11-29 12:55:19 -030067 struct v4l2_subdev sd;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080068 v4l2_std_id std;
69 int input;
Marco Schluessler4cbca182007-01-21 19:43:38 -030070 int output;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080071 int enable;
Hans Verkuil3faeeae2006-01-09 15:25:44 -020072 int radio;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080073 int bright;
74 int contrast;
75 int hue;
76 int sat;
Devin Heitmueller87a6fe42010-03-11 21:49:24 -030077 int chroma_agc;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -030078 int width;
79 int height;
Hans Verkuil3434eb72007-04-27 12:31:08 -030080 u32 ident;
Hans Verkuil3578d3d2006-01-09 15:25:41 -020081 u32 audclk_freq;
Hans Verkuilb7f82922006-04-02 12:50:42 -030082 u32 crystal_freq;
83 u8 ucgc;
84 u8 cgcdiv;
85 u8 apll;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080086};
87
Hans Verkuil9415f4b2008-11-29 12:55:19 -030088static inline struct saa711x_state *to_state(struct v4l2_subdev *sd)
89{
90 return container_of(sd, struct saa711x_state, sd);
91}
92
Hans Verkuile19b2fc2005-11-13 16:08:04 -080093/* ----------------------------------------------------------------------- */
94
Hans Verkuil9415f4b2008-11-29 12:55:19 -030095static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value)
Hans Verkuile19b2fc2005-11-13 16:08:04 -080096{
Hans Verkuil9415f4b2008-11-29 12:55:19 -030097 struct i2c_client *client = v4l2_get_subdevdata(sd);
98
Hans Verkuile19b2fc2005-11-13 16:08:04 -080099 return i2c_smbus_write_byte_data(client, reg, value);
100}
101
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300102/* Sanity routine to check if a register is present */
103static int saa711x_has_reg(const int id, const u8 reg)
104{
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300105 if (id == V4L2_IDENT_SAA7111)
106 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
107 (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e;
Hans Verkuil340dde82010-02-20 08:07:51 -0300108 if (id == V4L2_IDENT_SAA7111A)
109 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
110 reg != 0x14 && reg != 0x18 && reg != 0x19 &&
111 reg != 0x1d && reg != 0x1e;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300112
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300113 /* common for saa7113/4/5/8 */
114 if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f ||
115 reg == 0xa3 || reg == 0xa7 || reg == 0xab || reg == 0xaf || (reg >= 0xb5 && reg <= 0xb7) ||
116 reg == 0xd3 || reg == 0xd7 || reg == 0xdb || reg == 0xdf || (reg >= 0xe5 && reg <= 0xe7) ||
117 reg == 0x82 || (reg >= 0x89 && reg <= 0x8e)))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300118 return 0;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300119
120 switch (id) {
121 case V4L2_IDENT_SAA7113:
122 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
123 reg != 0x5d && reg < 0x63;
124 case V4L2_IDENT_SAA7114:
125 return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
126 (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
127 reg != 0x81 && reg < 0xf0;
128 case V4L2_IDENT_SAA7115:
129 return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe);
130 case V4L2_IDENT_SAA7118:
131 return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
132 (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
133 (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
134 }
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300135 return 1;
136}
137
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300138static int saa711x_writeregs(struct v4l2_subdev *sd, const unsigned char *regs)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800139{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300140 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800141 unsigned char reg, data;
142
143 while (*regs != 0x00) {
144 reg = *(regs++);
145 data = *(regs++);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300146
147 /* According with datasheets, reserved regs should be
148 filled with 0 - seems better not to touch on they */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300149 if (saa711x_has_reg(state->ident, reg)) {
150 if (saa711x_write(sd, reg, data) < 0)
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300151 return -1;
Mauro Carvalho Chehabd87edf22006-09-01 09:37:11 -0300152 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300153 v4l2_dbg(1, debug, sd, "tried to access reserved reg 0x%02x\n", reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300154 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800155 }
156 return 0;
157}
158
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300159static inline int saa711x_read(struct v4l2_subdev *sd, u8 reg)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800160{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300161 struct i2c_client *client = v4l2_get_subdevdata(sd);
162
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800163 return i2c_smbus_read_byte_data(client, reg);
164}
165
166/* ----------------------------------------------------------------------- */
167
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300168/* SAA7111 initialization table */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300169static const unsigned char saa7111_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300170 R_01_INC_DELAY, 0x00, /* reserved */
171
172 /*front end */
173 R_02_INPUT_CNTL_1, 0xd0, /* FUSE=3, GUDL=2, MODE=0 */
174 R_03_INPUT_CNTL_2, 0x23, /* HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0,
175 * GAFIX=0, GAI1=256, GAI2=256 */
176 R_04_INPUT_CNTL_3, 0x00, /* GAI1=256 */
177 R_05_INPUT_CNTL_4, 0x00, /* GAI2=256 */
178
179 /* decoder */
180 R_06_H_SYNC_START, 0xf3, /* HSB at 13(50Hz) / 17(60Hz)
181 * pixels after end of last line */
182 R_07_H_SYNC_STOP, 0xe8, /* HSS seems to be needed to
183 * work with NTSC, too */
184 R_08_SYNC_CNTL, 0xc8, /* AUFD=1, FSEL=1, EXFIL=0,
185 * VTRC=1, HPLL=0, VNOI=0 */
186 R_09_LUMA_CNTL, 0x01, /* BYPS=0, PREF=0, BPSS=0,
187 * VBLB=0, UPTCV=0, APER=1 */
188 R_0A_LUMA_BRIGHT_CNTL, 0x80,
189 R_0B_LUMA_CONTRAST_CNTL, 0x47, /* 0b - CONT=1.109 */
190 R_0C_CHROMA_SAT_CNTL, 0x40,
191 R_0D_CHROMA_HUE_CNTL, 0x00,
192 R_0E_CHROMA_CNTL_1, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0,
193 * FCTC=0, CHBW=1 */
194 R_0F_CHROMA_GAIN_CNTL, 0x00, /* reserved */
195 R_10_CHROMA_CNTL_2, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
196 R_11_MODE_DELAY_CNTL, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
197 * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
198 R_12_RT_SIGNAL_CNTL, 0x00, /* 12 - output control 2 */
199 R_13_RT_X_PORT_OUT_CNTL, 0x00, /* 13 - output control 3 */
200 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
201 R_15_VGATE_START_FID_CHG, 0x00,
202 R_16_VGATE_STOP, 0x00,
203 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
204
205 0x00, 0x00
206};
207
208/* SAA7113 init codes */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300209static const unsigned char saa7113_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300210 R_01_INC_DELAY, 0x08,
211 R_02_INPUT_CNTL_1, 0xc2,
212 R_03_INPUT_CNTL_2, 0x30,
213 R_04_INPUT_CNTL_3, 0x00,
214 R_05_INPUT_CNTL_4, 0x00,
215 R_06_H_SYNC_START, 0x89,
216 R_07_H_SYNC_STOP, 0x0d,
217 R_08_SYNC_CNTL, 0x88,
218 R_09_LUMA_CNTL, 0x01,
219 R_0A_LUMA_BRIGHT_CNTL, 0x80,
220 R_0B_LUMA_CONTRAST_CNTL, 0x47,
221 R_0C_CHROMA_SAT_CNTL, 0x40,
222 R_0D_CHROMA_HUE_CNTL, 0x00,
223 R_0E_CHROMA_CNTL_1, 0x01,
224 R_0F_CHROMA_GAIN_CNTL, 0x2a,
225 R_10_CHROMA_CNTL_2, 0x08,
226 R_11_MODE_DELAY_CNTL, 0x0c,
227 R_12_RT_SIGNAL_CNTL, 0x07,
228 R_13_RT_X_PORT_OUT_CNTL, 0x00,
229 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
230 R_15_VGATE_START_FID_CHG, 0x00,
231 R_16_VGATE_STOP, 0x00,
232 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
233
234 0x00, 0x00
235};
236
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800237/* If a value differs from the Hauppauge driver values, then the comment starts with
238 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
239 Hauppauge driver sets. */
240
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300241/* SAA7114 and SAA7115 initialization table */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800242static const unsigned char saa7115_init_auto_input[] = {
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300243 /* Front-End Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300244 R_01_INC_DELAY, 0x48, /* white peak control disabled */
245 R_03_INPUT_CNTL_2, 0x20, /* was 0x30. 0x20: long vertical blanking */
246 R_04_INPUT_CNTL_3, 0x90, /* analog gain set to 0 */
247 R_05_INPUT_CNTL_4, 0x90, /* analog gain set to 0 */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300248 /* Decoder Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300249 R_06_H_SYNC_START, 0xeb, /* horiz sync begin = -21 */
250 R_07_H_SYNC_STOP, 0xe0, /* horiz sync stop = -17 */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300251 R_09_LUMA_CNTL, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300252 R_0A_LUMA_BRIGHT_CNTL, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */
253 R_0B_LUMA_CONTRAST_CNTL, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */
254 R_0C_CHROMA_SAT_CNTL, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */
255 R_0D_CHROMA_HUE_CNTL, 0x00,
256 R_0F_CHROMA_GAIN_CNTL, 0x00, /* use automatic gain */
257 R_10_CHROMA_CNTL_2, 0x06, /* chroma: active adaptive combfilter */
258 R_11_MODE_DELAY_CNTL, 0x00,
259 R_12_RT_SIGNAL_CNTL, 0x9d, /* RTS0 output control: VGATE */
260 R_13_RT_X_PORT_OUT_CNTL, 0x80, /* ITU656 standard mode, RTCO output enable RTCE */
261 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
262 R_18_RAW_DATA_GAIN_CNTL, 0x40, /* gain 0x00 = nominal */
263 R_19_RAW_DATA_OFF_CNTL, 0x80,
264 R_1A_COLOR_KILL_LVL_CNTL, 0x77, /* recommended value */
265 R_1B_MISC_TVVCRDET, 0x42, /* recommended value */
266 R_1C_ENHAN_COMB_CTRL1, 0xa9, /* recommended value */
267 R_1D_ENHAN_COMB_CTRL2, 0x01, /* recommended value */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300268
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300269
270 R_80_GLOBAL_CNTL_1, 0x0, /* No tasks enabled at init */
271
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300272 /* Power Device Control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300273 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset device */
274 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* set device programmed, all in operational mode */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800275 0x00, 0x00
276};
277
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300278/* Used to reset saa7113, saa7114 and saa7115 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800279static const unsigned char saa7115_cfg_reset_scaler[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300280 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00, /* disable I-port output */
281 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
282 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
283 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* enable I-port output */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800284 0x00, 0x00
285};
286
287/* ============== SAA7715 VIDEO templates ============= */
288
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800289static const unsigned char saa7115_cfg_60hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300290 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
291 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800292
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300293 R_15_VGATE_START_FID_CHG, 0x03,
294 R_16_VGATE_STOP, 0x11,
295 R_17_MISC_VGATE_CONF_AND_MSB, 0x9c,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800296
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300297 R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
298 R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800299
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300300 R_5A_V_OFF_FOR_SLICER, 0x06, /* standard 60hz value for ITU656 line counting */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800301
302 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300303 R_90_A_TASK_HANDLING_CNTL, 0x80,
304 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
305 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
306 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
307
308 /* hoffset low (input), 0x0002 is minimum */
309 R_94_A_HORIZ_INPUT_WINDOW_START, 0x01,
310 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
311
312 /* hsize low (input), 0x02d0 = 720 */
313 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
314 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
315
316 R_98_A_VERT_INPUT_WINDOW_START, 0x05,
317 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
318
319 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x0c,
320 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
321
322 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
323 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
324
325 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x0c,
326 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800327
328 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300329 R_C0_B_TASK_HANDLING_CNTL, 0x00,
330 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
331 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
332 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800333
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300334 /* 0x0002 is minimum */
335 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x02,
336 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800337
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300338 /* 0x02d0 = 720 */
339 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
340 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
341
342 /* vwindow start 0x12 = 18 */
343 R_C8_B_VERT_INPUT_WINDOW_START, 0x12,
344 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
345
346 /* vwindow length 0xf8 = 248 */
Mauro Carvalho Chehab97d9e802006-09-03 09:38:11 -0300347 R_CA_B_VERT_INPUT_WINDOW_LENGTH, VRES_60HZ>>1,
348 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, VRES_60HZ>>9,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300349
350 /* hwindow 0x02d0 = 720 */
351 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
352 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
353
354 R_F0_LFCO_PER_LINE, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
355 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0 */
356 R_F5_PULSGEN_LINE_LENGTH, 0xad,
357 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
358
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800359 0x00, 0x00
360};
361
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800362static const unsigned char saa7115_cfg_50hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300363 R_80_GLOBAL_CNTL_1, 0x00,
364 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800365
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300366 R_15_VGATE_START_FID_CHG, 0x37, /* VGATE start */
367 R_16_VGATE_STOP, 0x16,
368 R_17_MISC_VGATE_CONF_AND_MSB, 0x99,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800369
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300370 R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */
371 R_0E_CHROMA_CNTL_1, 0x07,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800372
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300373 R_5A_V_OFF_FOR_SLICER, 0x03, /* standard 50hz value */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800374
375 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300376 R_90_A_TASK_HANDLING_CNTL, 0x81,
377 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
378 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
379 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
380
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800381 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
382 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300383 /* hoffset low (input), 0x0002 is minimum */
384 R_94_A_HORIZ_INPUT_WINDOW_START, 0x00,
385 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
386
387 /* hsize low (input), 0x02d0 = 720 */
388 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
389 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
390
391 R_98_A_VERT_INPUT_WINDOW_START, 0x03,
392 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
393
394 /* vsize 0x12 = 18 */
395 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x12,
396 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
397
398 /* hsize 0x05a0 = 1440 */
399 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
400 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05, /* hsize hi (output) */
401 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x12, /* vsize low (output), 0x12 = 18 */
402 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00, /* vsize hi (output) */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800403
404 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300405 R_C0_B_TASK_HANDLING_CNTL, 0x00,
406 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
407 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
408 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800409
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300410 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
411 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
412 /* hoffset low (input), 0x0002 is minimum. See comment above. */
413 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x00,
414 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800415
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300416 /* hsize 0x02d0 = 720 */
417 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
418 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
419
420 /* voffset 0x16 = 22 */
421 R_C8_B_VERT_INPUT_WINDOW_START, 0x16,
422 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
423
424 /* vsize 0x0120 = 288 */
425 R_CA_B_VERT_INPUT_WINDOW_LENGTH, 0x20,
426 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, 0x01,
427
428 /* hsize 0x02d0 = 720 */
429 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
430 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
431
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300432 R_F0_LFCO_PER_LINE, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
433 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0, (was 0x05) */
434 R_F5_PULSGEN_LINE_LENGTH, 0xb0,
435 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
436
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800437 0x00, 0x00
438};
439
440/* ============== SAA7715 VIDEO templates (end) ======= */
441
442static const unsigned char saa7115_cfg_vbi_on[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300443 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
444 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
445 R_80_GLOBAL_CNTL_1, 0x30, /* Activate both tasks */
446 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
447 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
448
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800449 0x00, 0x00
450};
451
452static const unsigned char saa7115_cfg_vbi_off[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300453 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
454 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
455 R_80_GLOBAL_CNTL_1, 0x20, /* Activate only task "B" */
456 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
457 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
458
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800459 0x00, 0x00
460};
461
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300462
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800463static const unsigned char saa7115_init_misc[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300464 R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300465 R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 0x01,
466 R_84_I_PORT_SIGNAL_DEF, 0x20,
467 R_85_I_PORT_SIGNAL_POLAR, 0x21,
468 R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT, 0xc5,
469 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800470
471 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300472 R_A0_A_HORIZ_PRESCALING, 0x01,
473 R_A1_A_ACCUMULATION_LENGTH, 0x00,
474 R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800475
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300476 /* Configure controls at nominal value*/
477 R_A4_A_LUMA_BRIGHTNESS_CNTL, 0x80,
478 R_A5_A_LUMA_CONTRAST_CNTL, 0x40,
479 R_A6_A_CHROMA_SATURATION_CNTL, 0x40,
480
481 /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
482 R_A8_A_HORIZ_LUMA_SCALING_INC, 0x00,
483 R_A9_A_HORIZ_LUMA_SCALING_INC_MSB, 0x02,
484
485 R_AA_A_HORIZ_LUMA_PHASE_OFF, 0x00,
486
487 /* must be horiz lum scaling / 2 */
488 R_AC_A_HORIZ_CHROMA_SCALING_INC, 0x00,
489 R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB, 0x01,
490
491 /* must be offset luma / 2 */
492 R_AE_A_HORIZ_CHROMA_PHASE_OFF, 0x00,
493
494 R_B0_A_VERT_LUMA_SCALING_INC, 0x00,
495 R_B1_A_VERT_LUMA_SCALING_INC_MSB, 0x04,
496
497 R_B2_A_VERT_CHROMA_SCALING_INC, 0x00,
498 R_B3_A_VERT_CHROMA_SCALING_INC_MSB, 0x04,
499
500 R_B4_A_VERT_SCALING_MODE_CNTL, 0x01,
501
502 R_B8_A_VERT_CHROMA_PHASE_OFF_00, 0x00,
503 R_B9_A_VERT_CHROMA_PHASE_OFF_01, 0x00,
504 R_BA_A_VERT_CHROMA_PHASE_OFF_10, 0x00,
505 R_BB_A_VERT_CHROMA_PHASE_OFF_11, 0x00,
506
507 R_BC_A_VERT_LUMA_PHASE_OFF_00, 0x00,
508 R_BD_A_VERT_LUMA_PHASE_OFF_01, 0x00,
509 R_BE_A_VERT_LUMA_PHASE_OFF_10, 0x00,
510 R_BF_A_VERT_LUMA_PHASE_OFF_11, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800511
512 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300513 R_D0_B_HORIZ_PRESCALING, 0x01,
514 R_D1_B_ACCUMULATION_LENGTH, 0x00,
515 R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800516
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300517 /* Configure controls at nominal value*/
518 R_D4_B_LUMA_BRIGHTNESS_CNTL, 0x80,
519 R_D5_B_LUMA_CONTRAST_CNTL, 0x40,
520 R_D6_B_CHROMA_SATURATION_CNTL, 0x40,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800521
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300522 /* hor lum scaling 0x0400 = 1 */
523 R_D8_B_HORIZ_LUMA_SCALING_INC, 0x00,
524 R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, 0x04,
525
526 R_DA_B_HORIZ_LUMA_PHASE_OFF, 0x00,
527
528 /* must be hor lum scaling / 2 */
529 R_DC_B_HORIZ_CHROMA_SCALING, 0x00,
530 R_DD_B_HORIZ_CHROMA_SCALING_MSB, 0x02,
531
532 /* must be offset luma / 2 */
533 R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA, 0x00,
534
535 R_E0_B_VERT_LUMA_SCALING_INC, 0x00,
536 R_E1_B_VERT_LUMA_SCALING_INC_MSB, 0x04,
537
538 R_E2_B_VERT_CHROMA_SCALING_INC, 0x00,
539 R_E3_B_VERT_CHROMA_SCALING_INC_MSB, 0x04,
540
541 R_E4_B_VERT_SCALING_MODE_CNTL, 0x01,
542
543 R_E8_B_VERT_CHROMA_PHASE_OFF_00, 0x00,
544 R_E9_B_VERT_CHROMA_PHASE_OFF_01, 0x00,
545 R_EA_B_VERT_CHROMA_PHASE_OFF_10, 0x00,
546 R_EB_B_VERT_CHROMA_PHASE_OFF_11, 0x00,
547
548 R_EC_B_VERT_LUMA_PHASE_OFF_00, 0x00,
549 R_ED_B_VERT_LUMA_PHASE_OFF_01, 0x00,
550 R_EE_B_VERT_LUMA_PHASE_OFF_10, 0x00,
551 R_EF_B_VERT_LUMA_PHASE_OFF_11, 0x00,
552
553 R_F2_NOMINAL_PLL2_DTO, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */
554 R_F3_PLL_INCREMENT, 0x46,
555 R_F4_PLL2_STATUS, 0x00,
556 R_F7_PULSE_A_POS_MSB, 0x4b, /* not the recommended settings! */
557 R_F8_PULSE_B_POS, 0x00,
558 R_F9_PULSE_B_POS_MSB, 0x4b,
559 R_FA_PULSE_C_POS, 0x00,
560 R_FB_PULSE_C_POS_MSB, 0x4b,
561
562 /* PLL2 lock detection settings: 71 lines 50% phase error */
563 R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES, 0x88,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800564
565 /* Turn off VBI */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300566 R_40_SLICER_CNTL_1, 0x20, /* No framing code errors allowed. */
567 R_41_LCR_BASE, 0xff,
568 R_41_LCR_BASE+1, 0xff,
569 R_41_LCR_BASE+2, 0xff,
570 R_41_LCR_BASE+3, 0xff,
571 R_41_LCR_BASE+4, 0xff,
572 R_41_LCR_BASE+5, 0xff,
573 R_41_LCR_BASE+6, 0xff,
574 R_41_LCR_BASE+7, 0xff,
575 R_41_LCR_BASE+8, 0xff,
576 R_41_LCR_BASE+9, 0xff,
577 R_41_LCR_BASE+10, 0xff,
578 R_41_LCR_BASE+11, 0xff,
579 R_41_LCR_BASE+12, 0xff,
580 R_41_LCR_BASE+13, 0xff,
581 R_41_LCR_BASE+14, 0xff,
582 R_41_LCR_BASE+15, 0xff,
583 R_41_LCR_BASE+16, 0xff,
584 R_41_LCR_BASE+17, 0xff,
585 R_41_LCR_BASE+18, 0xff,
586 R_41_LCR_BASE+19, 0xff,
587 R_41_LCR_BASE+20, 0xff,
588 R_41_LCR_BASE+21, 0xff,
589 R_41_LCR_BASE+22, 0xff,
590 R_58_PROGRAM_FRAMING_CODE, 0x40,
591 R_59_H_OFF_FOR_SLICER, 0x47,
592 R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF, 0x83,
593 R_5D_DID, 0xbd,
594 R_5E_SDID, 0x35,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800595
Devin Heitmuellerfea551f2010-02-03 00:33:48 -0300596 R_02_INPUT_CNTL_1, 0xc4, /* input tuner -> input 4, amplifier active */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800597
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300598 R_80_GLOBAL_CNTL_1, 0x20, /* enable task B */
599 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
600 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800601 0x00, 0x00
602};
603
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -0300604static int saa711x_odd_parity(u8 c)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800605{
606 c ^= (c >> 4);
607 c ^= (c >> 2);
608 c ^= (c >> 1);
609
610 return c & 1;
611}
612
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300613static int saa711x_decode_vps(u8 *dst, u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800614{
615 static const u8 biphase_tbl[] = {
616 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
617 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
618 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
619 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
620 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
621 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
622 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
623 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
624 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
625 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
626 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
627 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
628 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
629 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
630 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
631 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
632 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
633 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
634 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
635 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
636 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
637 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
638 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
639 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
640 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
641 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
642 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
643 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
644 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
645 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
646 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
647 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
648 };
649 int i;
650 u8 c, err = 0;
651
652 for (i = 0; i < 2 * 13; i += 2) {
653 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
654 c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
655 dst[i / 2] = c;
656 }
657 return err & 0xf0;
658}
659
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300660static int saa711x_decode_wss(u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800661{
662 static const int wss_bits[8] = {
663 0, 0, 0, 1, 0, 1, 1, 1
664 };
665 unsigned char parity;
666 int wss = 0;
667 int i;
668
669 for (i = 0; i < 16; i++) {
670 int b1 = wss_bits[p[i] & 7];
671 int b2 = wss_bits[(p[i] >> 3) & 7];
672
673 if (b1 == b2)
674 return -1;
675 wss |= b2 << i;
676 }
677 parity = wss & 15;
678 parity ^= parity >> 2;
679 parity ^= parity >> 1;
680
681 if (!(parity & 1))
682 return -1;
683
684 return wss;
685}
686
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300687static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800688{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300689 struct saa711x_state *state = to_state(sd);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200690 u32 acpf;
691 u32 acni;
692 u32 hz;
693 u64 f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300694 u8 acc = 0; /* reg 0x3a, audio clock control */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800695
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300696 /* Checks for chips that don't have audio clock (saa7111, saa7113) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300697 if (!saa711x_has_reg(state->ident, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300698 return 0;
699
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300700 v4l2_dbg(1, debug, sd, "set audio clock freq: %d\n", freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200701
702 /* sanity check */
703 if (freq < 32000 || freq > 48000)
704 return -EINVAL;
705
706 /* hz is the refresh rate times 100 */
707 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
708 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
709 acpf = (25600 * freq) / hz;
710 /* acni = (256 * freq * 2^23) / crystal_frequency =
711 (freq * 2^(8+23)) / crystal_frequency =
Hans Verkuilb7f82922006-04-02 12:50:42 -0300712 (freq << 31) / crystal_frequency */
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200713 f = freq;
714 f = f << 31;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300715 do_div(f, state->crystal_freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200716 acni = f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300717 if (state->ucgc) {
718 acpf = acpf * state->cgcdiv / 16;
719 acni = acni * state->cgcdiv / 16;
720 acc = 0x80;
721 if (state->cgcdiv == 3)
722 acc |= 0x40;
723 }
724 if (state->apll)
725 acc |= 0x08;
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200726
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300727 saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
728 saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10);
729 saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300730
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300731 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
732 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300733 (acpf >> 8) & 0xff);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300734 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300735 (acpf >> 16) & 0x03);
736
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300737 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
738 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
739 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800740 state->audclk_freq = freq;
741 return 0;
742}
743
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300744static int saa711x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800745{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300746 struct saa711x_state *state = to_state(sd);
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300747 u8 val;
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800748
749 switch (ctrl->id) {
750 case V4L2_CID_BRIGHTNESS:
751 if (ctrl->value < 0 || ctrl->value > 255) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300752 v4l2_err(sd, "invalid brightness setting %d\n", ctrl->value);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800753 return -ERANGE;
754 }
755
756 state->bright = ctrl->value;
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300757 saa711x_write(sd, R_0A_LUMA_BRIGHT_CNTL, state->bright);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800758 break;
759
760 case V4L2_CID_CONTRAST:
761 if (ctrl->value < 0 || ctrl->value > 127) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300762 v4l2_err(sd, "invalid contrast setting %d\n", ctrl->value);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800763 return -ERANGE;
764 }
765
766 state->contrast = ctrl->value;
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300767 saa711x_write(sd, R_0B_LUMA_CONTRAST_CNTL, state->contrast);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800768 break;
769
770 case V4L2_CID_SATURATION:
771 if (ctrl->value < 0 || ctrl->value > 127) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300772 v4l2_err(sd, "invalid saturation setting %d\n", ctrl->value);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800773 return -ERANGE;
774 }
775
776 state->sat = ctrl->value;
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300777 saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, state->sat);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800778 break;
779
780 case V4L2_CID_HUE:
Hans Verkuilde6476f52009-01-29 16:09:13 -0300781 if (ctrl->value < -128 || ctrl->value > 127) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300782 v4l2_err(sd, "invalid hue setting %d\n", ctrl->value);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800783 return -ERANGE;
784 }
785
786 state->hue = ctrl->value;
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300787 saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, state->hue);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800788 break;
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300789 case V4L2_CID_CHROMA_AGC:
790 val = saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL);
791 state->chroma_agc = ctrl->value;
792 if (ctrl->value)
793 val &= 0x7f;
794 else
795 val |= 0x80;
796 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, val);
797 break;
798 case V4L2_CID_CHROMA_GAIN:
799 /* Chroma gain cannot be set when AGC is enabled */
800 if (state->chroma_agc == 1)
801 return -EINVAL;
802 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, ctrl->value | 0x80);
803 break;
Hans Verkuil3faeeae2006-01-09 15:25:44 -0200804 default:
805 return -EINVAL;
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800806 }
807
808 return 0;
809}
810
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300811static int saa711x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800812{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300813 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800814
815 switch (ctrl->id) {
816 case V4L2_CID_BRIGHTNESS:
817 ctrl->value = state->bright;
818 break;
819 case V4L2_CID_CONTRAST:
820 ctrl->value = state->contrast;
821 break;
822 case V4L2_CID_SATURATION:
823 ctrl->value = state->sat;
824 break;
825 case V4L2_CID_HUE:
826 ctrl->value = state->hue;
827 break;
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300828 case V4L2_CID_CHROMA_AGC:
829 ctrl->value = state->chroma_agc;
830 break;
831 case V4L2_CID_CHROMA_GAIN:
832 ctrl->value = saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL) & 0x7f;
833 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800834 default:
835 return -EINVAL;
836 }
837
838 return 0;
839}
840
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300841static int saa711x_set_size(struct v4l2_subdev *sd, int width, int height)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300842{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300843 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300844 int HPSC, HFSC;
845 int VSCY;
846 int res;
847 int is_50hz = state->std & V4L2_STD_625_50;
848 int Vsrc = is_50hz ? 576 : 480;
849
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300850 v4l2_dbg(1, debug, sd, "decoder set size to %ix%i\n", width, height);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300851
852 /* FIXME need better bounds checking here */
853 if ((width < 1) || (width > 1440))
854 return -EINVAL;
855 if ((height < 1) || (height > Vsrc))
856 return -EINVAL;
857
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300858 if (!saa711x_has_reg(state->ident, R_D0_B_HORIZ_PRESCALING)) {
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300859 /* Decoder only supports 720 columns and 480 or 576 lines */
860 if (width != 720)
861 return -EINVAL;
862 if (height != Vsrc)
863 return -EINVAL;
864 }
865
866 state->width = width;
867 state->height = height;
868
869 if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
870 return 0;
871
872 /* probably have a valid size, let's set it */
873 /* Set output width/height */
874 /* width */
875
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300876 saa711x_write(sd, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300877 (u8) (width & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300878 saa711x_write(sd, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300879 (u8) ((width >> 8) & 0xff));
880
881 /* Vertical Scaling uses height/2 */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300882 res = height / 2;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300883
884 /* On 60Hz, it is using a higher Vertical Output Size */
885 if (!is_50hz)
Hans Verkuild0d30c02006-11-25 09:45:50 -0300886 res += (VRES_60HZ - 480) >> 1;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300887
888 /* height */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300889 saa711x_write(sd, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300890 (u8) (res & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300891 saa711x_write(sd, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300892 (u8) ((res >> 8) & 0xff));
893
894 /* Scaling settings */
895 /* Hprescaler is floor(inres/outres) */
896 HPSC = (int)(720 / width);
897 /* 0 is not allowed (div. by zero) */
898 HPSC = HPSC ? HPSC : 1;
899 HFSC = (int)((1024 * 720) / (HPSC * width));
900 /* FIXME hardcodes to "Task B"
901 * write H prescaler integer */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300902 saa711x_write(sd, R_D0_B_HORIZ_PRESCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300903 (u8) (HPSC & 0x3f));
904
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300905 v4l2_dbg(1, debug, sd, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300906 /* write H fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300907 saa711x_write(sd, R_D8_B_HORIZ_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300908 (u8) (HFSC & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300909 saa711x_write(sd, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300910 (u8) ((HFSC >> 8) & 0xff));
911 /* write H fine-scaling (chrominance)
912 * must be lum/2, so i'll just bitshift :) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300913 saa711x_write(sd, R_DC_B_HORIZ_CHROMA_SCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300914 (u8) ((HFSC >> 1) & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300915 saa711x_write(sd, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300916 (u8) ((HFSC >> 9) & 0xff));
917
918 VSCY = (int)((1024 * Vsrc) / height);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300919 v4l2_dbg(1, debug, sd, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300920
921 /* Correct Contrast and Luminance */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300922 saa711x_write(sd, R_D5_B_LUMA_CONTRAST_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300923 (u8) (64 * 1024 / VSCY));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300924 saa711x_write(sd, R_D6_B_CHROMA_SATURATION_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300925 (u8) (64 * 1024 / VSCY));
926
927 /* write V fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300928 saa711x_write(sd, R_E0_B_VERT_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300929 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300930 saa711x_write(sd, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300931 (u8) ((VSCY >> 8) & 0xff));
932 /* write V fine-scaling (chrominance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300933 saa711x_write(sd, R_E2_B_VERT_CHROMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300934 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300935 saa711x_write(sd, R_E3_B_VERT_CHROMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300936 (u8) ((VSCY >> 8) & 0xff));
937
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300938 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300939
940 /* Activates task "B" */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300941 saa711x_write(sd, R_80_GLOBAL_CNTL_1,
942 saa711x_read(sd, R_80_GLOBAL_CNTL_1) | 0x20);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300943
944 return 0;
945}
946
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300947static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800948{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300949 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800950
Hans Verkuil30b54d52006-01-09 15:25:43 -0200951 /* Prevent unnecessary standard changes. During a standard
952 change the I-Port is temporarily disabled. Any devices
953 reading from that port can get confused.
Hans Verkuilbccfa442009-03-30 06:55:27 -0300954 Note that s_std is also used to switch from
955 radio to TV mode, so if a s_std is broadcast to
Hans Verkuil30b54d52006-01-09 15:25:43 -0200956 all I2C devices then you do not want to have an unwanted
957 side-effect here. */
958 if (std == state->std)
959 return;
960
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300961 state->std = std;
962
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800963 // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
964 if (std & V4L2_STD_525_60) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300965 v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n");
966 saa711x_writeregs(sd, saa7115_cfg_60hz_video);
967 saa711x_set_size(sd, 720, 480);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800968 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300969 v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n");
970 saa711x_writeregs(sd, saa7115_cfg_50hz_video);
971 saa711x_set_size(sd, 720, 576);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800972 }
973
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300974 /* Register 0E - Bits D6-D4 on NO-AUTO mode
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300975 (SAA7111 and SAA7113 doesn't have auto mode)
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300976 50 Hz / 625 lines 60 Hz / 525 lines
977 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz)
978 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz)
979 010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz)
980 011 NTSC N (3.58MHz) PAL M (3.58MHz)
981 100 reserved NTSC-Japan (3.58MHz)
982 */
Hans Verkuil340dde82010-02-20 08:07:51 -0300983 if (state->ident <= V4L2_IDENT_SAA7113) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300984 u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300985
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300986 if (std == V4L2_STD_PAL_M) {
Hans Verkuil01342352006-03-25 08:19:47 -0300987 reg |= 0x30;
Hans Verkuile0028022008-04-22 14:45:51 -0300988 } else if (std == V4L2_STD_PAL_Nc) {
Hans Verkuil01342352006-03-25 08:19:47 -0300989 reg |= 0x20;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300990 } else if (std == V4L2_STD_PAL_60) {
Hans Verkuil01342352006-03-25 08:19:47 -0300991 reg |= 0x10;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300992 } else if (std == V4L2_STD_NTSC_M_JP) {
Hans Verkuil01342352006-03-25 08:19:47 -0300993 reg |= 0x40;
Mauro Carvalho Chehaba9aaec42007-03-13 13:41:49 -0300994 } else if (std & V4L2_STD_SECAM) {
Pádraig Bradyfc2fa312006-10-09 08:02:17 -0300995 reg |= 0x50;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300996 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300997 saa711x_write(sd, R_0E_CHROMA_CNTL_1, reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300998 } else {
999 /* restart task B if needed */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001000 int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001001
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001002 if (taskb && state->ident == V4L2_IDENT_SAA7114) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001003 saa711x_writeregs(sd, saa7115_cfg_vbi_on);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001004 }
1005
1006 /* switch audio mode too! */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001007 saa711x_s_clock_freq(sd, state->audclk_freq);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001008 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001009}
1010
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001011/* setup the sliced VBI lcr registers according to the sliced VBI format */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001012static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001013{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001014 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001015 int is_50hz = (state->std & V4L2_STD_625_50);
1016 u8 lcr[24];
1017 int i, x;
1018
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001019#if 1
1020 /* saa7113/7114/7118 VBI support are experimental */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001021 if (!saa711x_has_reg(state->ident, R_41_LCR_BASE))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001022 return;
1023
1024#else
1025 /* SAA7113 and SAA7118 also should support VBI - Need testing */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001026 if (state->ident != V4L2_IDENT_SAA7115)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001027 return;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001028#endif
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001029
1030 for (i = 0; i <= 23; i++)
1031 lcr[i] = 0xff;
1032
Hans Verkuila8b86432008-10-04 08:05:30 -03001033 if (fmt == NULL) {
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001034 /* raw VBI */
1035 if (is_50hz)
1036 for (i = 6; i <= 23; i++)
1037 lcr[i] = 0xdd;
1038 else
1039 for (i = 10; i <= 21; i++)
1040 lcr[i] = 0xdd;
1041 } else {
1042 /* sliced VBI */
1043 /* first clear lines that cannot be captured */
1044 if (is_50hz) {
1045 for (i = 0; i <= 5; i++)
1046 fmt->service_lines[0][i] =
1047 fmt->service_lines[1][i] = 0;
1048 }
1049 else {
1050 for (i = 0; i <= 9; i++)
1051 fmt->service_lines[0][i] =
1052 fmt->service_lines[1][i] = 0;
1053 for (i = 22; i <= 23; i++)
1054 fmt->service_lines[0][i] =
1055 fmt->service_lines[1][i] = 0;
1056 }
1057
1058 /* Now set the lcr values according to the specified service */
1059 for (i = 6; i <= 23; i++) {
1060 lcr[i] = 0;
1061 for (x = 0; x <= 1; x++) {
1062 switch (fmt->service_lines[1-x][i]) {
1063 case 0:
1064 lcr[i] |= 0xf << (4 * x);
1065 break;
Hans Verkuil9bc74002006-03-29 18:02:51 -03001066 case V4L2_SLICED_TELETEXT_B:
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001067 lcr[i] |= 1 << (4 * x);
1068 break;
1069 case V4L2_SLICED_CAPTION_525:
1070 lcr[i] |= 4 << (4 * x);
1071 break;
1072 case V4L2_SLICED_WSS_625:
1073 lcr[i] |= 5 << (4 * x);
1074 break;
1075 case V4L2_SLICED_VPS:
1076 lcr[i] |= 7 << (4 * x);
1077 break;
1078 }
1079 }
1080 }
1081 }
1082
1083 /* write the lcr registers */
1084 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001085 saa711x_write(sd, i - 2 + R_41_LCR_BASE, lcr[i]);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001086 }
1087
1088 /* enable/disable raw VBI capturing */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001089 saa711x_writeregs(sd, fmt == NULL ?
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001090 saa7115_cfg_vbi_on :
1091 saa7115_cfg_vbi_off);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001092}
1093
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001094static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *sliced)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001095{
1096 static u16 lcr2vbi[] = {
Hans Verkuil9bc74002006-03-29 18:02:51 -03001097 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001098 0, V4L2_SLICED_CAPTION_525, /* 4 */
1099 V4L2_SLICED_WSS_625, 0, /* 5 */
1100 V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
1101 0, 0, 0, 0
1102 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001103 int i;
1104
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001105 memset(sliced, 0, sizeof(*sliced));
1106 /* done if using raw VBI */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001107 if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001108 return 0;
1109 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001110 u8 v = saa711x_read(sd, i - 2 + R_41_LCR_BASE);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001111
1112 sliced->service_lines[0][i] = lcr2vbi[v >> 4];
1113 sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
1114 sliced->service_set |=
1115 sliced->service_lines[0][i] | sliced->service_lines[1][i];
1116 }
1117 return 0;
1118}
1119
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001120static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
1121{
1122 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
1123 return -EINVAL;
1124 return saa711x_g_sliced_fmt(sd, &fmt->fmt.sliced);
1125}
1126
1127static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
1128{
1129 saa711x_set_lcr(sd, NULL);
1130 return 0;
1131}
1132
1133static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
1134{
1135 saa711x_set_lcr(sd, fmt);
1136 return 0;
1137}
1138
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001139static int saa711x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
Mauro Carvalho Chehab59ba9152006-08-30 05:34:36 -03001140{
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001141 if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
1142 return saa711x_s_sliced_fmt(sd, &fmt->fmt.sliced);
1143 if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1144 return saa711x_s_raw_fmt(sd, &fmt->fmt.vbi);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001145 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1146 return -EINVAL;
1147
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001148 return saa711x_set_size(sd, fmt->fmt.pix.width, fmt->fmt.pix.height);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001149}
1150
1151/* Decode the sliced VBI data stream as created by the saa7115.
1152 The format is described in the saa7115 datasheet in Tables 25 and 26
1153 and in Figure 33.
1154 The current implementation uses SAV/EAV codes and not the ancillary data
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001155 headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001156 code. */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001157static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001158{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001159 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001160 static const char vbi_no_data_pattern[] = {
1161 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
1162 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001163 u8 *p = vbi->p;
1164 u32 wss;
1165 int id1, id2; /* the ID1 and ID2 bytes from the internal header */
1166
1167 vbi->type = 0; /* mark result as a failure */
1168 id1 = p[2];
1169 id2 = p[3];
1170 /* Note: the field bit is inverted for 60 Hz video */
1171 if (state->std & V4L2_STD_525_60)
1172 id1 ^= 0x40;
1173
1174 /* Skip internal header, p now points to the start of the payload */
1175 p += 4;
1176 vbi->p = p;
1177
1178 /* calculate field and line number of the VBI packet (1-23) */
1179 vbi->is_second_field = ((id1 & 0x40) != 0);
1180 vbi->line = (id1 & 0x3f) << 3;
1181 vbi->line |= (id2 & 0x70) >> 4;
1182
1183 /* Obtain data type */
1184 id2 &= 0xf;
1185
1186 /* If the VBI slicer does not detect any signal it will fill up
1187 the payload buffer with 0xa0 bytes. */
1188 if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001189 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001190
1191 /* decode payloads */
1192 switch (id2) {
1193 case 1:
Hans Verkuil9bc74002006-03-29 18:02:51 -03001194 vbi->type = V4L2_SLICED_TELETEXT_B;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001195 break;
1196 case 4:
Mauro Carvalho Chehab59ba9152006-08-30 05:34:36 -03001197 if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001198 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001199 vbi->type = V4L2_SLICED_CAPTION_525;
1200 break;
1201 case 5:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001202 wss = saa711x_decode_wss(p);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001203 if (wss == -1)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001204 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001205 p[0] = wss & 0xff;
1206 p[1] = wss >> 8;
1207 vbi->type = V4L2_SLICED_WSS_625;
1208 break;
1209 case 7:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001210 if (saa711x_decode_vps(p, p) != 0)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001211 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001212 vbi->type = V4L2_SLICED_VPS;
1213 break;
1214 default:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001215 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001216 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001217 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001218}
1219
1220/* ============ SAA7115 AUDIO settings (end) ============= */
1221
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001222static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001223{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001224 struct saa711x_state *state = to_state(sd);
1225 int status;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001226
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001227 if (state->radio)
1228 return 0;
1229 status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001230
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001231 v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status);
1232 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1233 return 0;
1234}
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001235
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001236static int saa711x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
1237{
1238 switch (qc->id) {
1239 case V4L2_CID_BRIGHTNESS:
Hans Verkuil10afbef2009-02-21 18:47:24 -03001240 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001241 case V4L2_CID_CONTRAST:
1242 case V4L2_CID_SATURATION:
Hans Verkuil10afbef2009-02-21 18:47:24 -03001243 return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001244 case V4L2_CID_HUE:
Hans Verkuil10afbef2009-02-21 18:47:24 -03001245 return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
Devin Heitmueller87a6fe42010-03-11 21:49:24 -03001246 case V4L2_CID_CHROMA_AGC:
1247 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
1248 case V4L2_CID_CHROMA_GAIN:
Devin Heitmuellerf1a4f9e2010-03-11 22:00:13 -03001249 return v4l2_ctrl_query_fill(qc, 0, 127, 1, 48);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001250 default:
1251 return -EINVAL;
1252 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001253}
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001254
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001255static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1256{
1257 struct saa711x_state *state = to_state(sd);
1258
1259 state->radio = 0;
1260 saa711x_set_v4lstd(sd, std);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001261 return 0;
1262}
1263
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001264static int saa711x_s_radio(struct v4l2_subdev *sd)
1265{
1266 struct saa711x_state *state = to_state(sd);
1267
1268 state->radio = 1;
1269 return 0;
1270}
1271
Hans Verkuil5325b422009-04-02 11:26:22 -03001272static int saa711x_s_routing(struct v4l2_subdev *sd,
1273 u32 input, u32 output, u32 config)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001274{
1275 struct saa711x_state *state = to_state(sd);
Hans Verkuil340dde82010-02-20 08:07:51 -03001276 u8 mask = (state->ident <= V4L2_IDENT_SAA7111A) ? 0xf8 : 0xf0;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001277
Hans Verkuil5325b422009-04-02 11:26:22 -03001278 v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n",
1279 input, output);
1280
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001281 /* saa7111/3 does not have these inputs */
Hans Verkuil340dde82010-02-20 08:07:51 -03001282 if (state->ident <= V4L2_IDENT_SAA7113 &&
Hans Verkuil5325b422009-04-02 11:26:22 -03001283 (input == SAA7115_COMPOSITE4 ||
1284 input == SAA7115_COMPOSITE5)) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001285 return -EINVAL;
1286 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001287 if (input > SAA7115_SVIDEO3)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001288 return -EINVAL;
Hans Verkuil5325b422009-04-02 11:26:22 -03001289 if (state->input == input && state->output == output)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001290 return 0;
1291 v4l2_dbg(1, debug, sd, "now setting %s input %s output\n",
Hans Verkuil5325b422009-04-02 11:26:22 -03001292 (input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite",
1293 (output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
1294 state->input = input;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001295
1296 /* saa7111 has slightly different input numbering */
Hans Verkuil340dde82010-02-20 08:07:51 -03001297 if (state->ident <= V4L2_IDENT_SAA7111A) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001298 if (input >= SAA7115_COMPOSITE4)
1299 input -= 2;
1300 /* saa7111 specific */
1301 saa711x_write(sd, R_10_CHROMA_CNTL_2,
1302 (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001303 ((output & 0xc0) ^ 0x40));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001304 saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL,
1305 (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001306 ((output & 2) ? 0x0a : 0));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001307 }
1308
1309 /* select mode */
1310 saa711x_write(sd, R_02_INPUT_CNTL_1,
1311 (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) |
1312 input);
1313
1314 /* bypass chrominance trap for S-Video modes */
1315 saa711x_write(sd, R_09_LUMA_CNTL,
1316 (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) |
1317 (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
1318
Hans Verkuil5325b422009-04-02 11:26:22 -03001319 state->output = output;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001320 if (state->ident == V4L2_IDENT_SAA7114 ||
1321 state->ident == V4L2_IDENT_SAA7115) {
1322 saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
1323 (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
1324 (state->output & 0x01));
1325 }
1326 return 0;
1327}
1328
1329static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val)
1330{
1331 struct saa711x_state *state = to_state(sd);
1332
Hans Verkuil340dde82010-02-20 08:07:51 -03001333 if (state->ident > V4L2_IDENT_SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001334 return -EINVAL;
1335 saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) |
1336 (val ? 0x80 : 0));
1337 return 0;
1338}
1339
1340static int saa711x_s_stream(struct v4l2_subdev *sd, int enable)
1341{
1342 struct saa711x_state *state = to_state(sd);
1343
1344 v4l2_dbg(1, debug, sd, "%s output\n",
1345 enable ? "enable" : "disable");
1346
Hans Verkuil674a3232009-02-18 12:22:16 -03001347 if (state->enable == enable)
1348 return 0;
1349 state->enable = enable;
1350 if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED))
1351 return 0;
1352 saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001353 return 0;
1354}
1355
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001356static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001357{
1358 struct saa711x_state *state = to_state(sd);
1359
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001360 if (freq != SAA7115_FREQ_32_11_MHZ && freq != SAA7115_FREQ_24_576_MHZ)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001361 return -EINVAL;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001362 state->crystal_freq = freq;
1363 state->cgcdiv = (flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
1364 state->ucgc = (flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;
1365 state->apll = (flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001366 saa711x_s_clock_freq(sd, state->audclk_freq);
1367 return 0;
1368}
1369
1370static int saa711x_reset(struct v4l2_subdev *sd, u32 val)
1371{
1372 v4l2_dbg(1, debug, sd, "decoder RESET\n");
1373 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
1374 return 0;
1375}
1376
1377static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data)
1378{
1379 /* Note: the internal field ID is inverted for NTSC,
1380 so data->field 0 maps to the saa7115 even field,
1381 whereas for PAL it maps to the saa7115 odd field. */
1382 switch (data->id) {
1383 case V4L2_SLICED_WSS_625:
1384 if (saa711x_read(sd, 0x6b) & 0xc0)
1385 return -EIO;
1386 data->data[0] = saa711x_read(sd, 0x6c);
1387 data->data[1] = saa711x_read(sd, 0x6d);
1388 return 0;
1389 case V4L2_SLICED_CAPTION_525:
1390 if (data->field == 0) {
1391 /* CC */
1392 if (saa711x_read(sd, 0x66) & 0x30)
1393 return -EIO;
1394 data->data[0] = saa711x_read(sd, 0x69);
1395 data->data[1] = saa711x_read(sd, 0x6a);
1396 return 0;
1397 }
1398 /* XDS */
1399 if (saa711x_read(sd, 0x66) & 0xc0)
1400 return -EIO;
1401 data->data[0] = saa711x_read(sd, 0x67);
1402 data->data[1] = saa711x_read(sd, 0x68);
1403 return 0;
1404 default:
1405 return -EINVAL;
1406 }
1407}
1408
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001409static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
1410{
1411 struct saa711x_state *state = to_state(sd);
1412 int reg1e;
1413
1414 *std = V4L2_STD_ALL;
1415 if (state->ident != V4L2_IDENT_SAA7115)
1416 return 0;
1417 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1418
1419 switch (reg1e & 0x03) {
1420 case 1:
1421 *std = V4L2_STD_NTSC;
1422 break;
1423 case 2:
1424 *std = V4L2_STD_PAL;
1425 break;
1426 case 3:
1427 *std = V4L2_STD_SECAM;
1428 break;
1429 default:
1430 break;
1431 }
1432 return 0;
1433}
1434
1435static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status)
1436{
1437 struct saa711x_state *state = to_state(sd);
1438 int reg1e = 0x80;
1439 int reg1f;
1440
1441 *status = V4L2_IN_ST_NO_SIGNAL;
1442 if (state->ident == V4L2_IDENT_SAA7115)
1443 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1444 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1445 if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80)
1446 *status = 0;
1447 return 0;
1448}
1449
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001450#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001451static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001452{
1453 struct i2c_client *client = v4l2_get_subdevdata(sd);
1454
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001455 if (!v4l2_chip_match_i2c_client(client, &reg->match))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001456 return -EINVAL;
1457 if (!capable(CAP_SYS_ADMIN))
1458 return -EPERM;
1459 reg->val = saa711x_read(sd, reg->reg & 0xff);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001460 reg->size = 1;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001461 return 0;
1462}
1463
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001464static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001465{
1466 struct i2c_client *client = v4l2_get_subdevdata(sd);
1467
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001468 if (!v4l2_chip_match_i2c_client(client, &reg->match))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001469 return -EINVAL;
1470 if (!capable(CAP_SYS_ADMIN))
1471 return -EPERM;
1472 saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff);
1473 return 0;
1474}
1475#endif
1476
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001477static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001478{
1479 struct saa711x_state *state = to_state(sd);
1480 struct i2c_client *client = v4l2_get_subdevdata(sd);
1481
1482 return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0);
1483}
1484
1485static int saa711x_log_status(struct v4l2_subdev *sd)
1486{
1487 struct saa711x_state *state = to_state(sd);
1488 int reg1e, reg1f;
1489 int signalOk;
1490 int vcr;
1491
1492 v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq);
1493 if (state->ident != V4L2_IDENT_SAA7115) {
1494 /* status for the saa7114 */
1495 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1496 signalOk = (reg1f & 0xc1) == 0x81;
1497 v4l2_info(sd, "Video signal: %s\n", signalOk ? "ok" : "bad");
1498 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1499 return 0;
1500 }
1501
1502 /* status for the saa7115 */
1503 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1504 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1505
1506 signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
1507 vcr = !(reg1f & 0x10);
1508
1509 if (state->input >= 6)
1510 v4l2_info(sd, "Input: S-Video %d\n", state->input - 6);
1511 else
1512 v4l2_info(sd, "Input: Composite %d\n", state->input);
1513 v4l2_info(sd, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
1514 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1515
1516 switch (reg1e & 0x03) {
1517 case 1:
1518 v4l2_info(sd, "Detected format: NTSC\n");
1519 break;
1520 case 2:
1521 v4l2_info(sd, "Detected format: PAL\n");
1522 break;
1523 case 3:
1524 v4l2_info(sd, "Detected format: SECAM\n");
1525 break;
1526 default:
1527 v4l2_info(sd, "Detected format: BW/No color\n");
1528 break;
1529 }
1530 v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height);
1531 return 0;
1532}
1533
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001534/* ----------------------------------------------------------------------- */
1535
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001536static const struct v4l2_subdev_core_ops saa711x_core_ops = {
1537 .log_status = saa711x_log_status,
1538 .g_chip_ident = saa711x_g_chip_ident,
1539 .g_ctrl = saa711x_g_ctrl,
1540 .s_ctrl = saa711x_s_ctrl,
1541 .queryctrl = saa711x_queryctrl,
Hans Verkuilf41737e2009-04-01 03:52:39 -03001542 .s_std = saa711x_s_std,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001543 .reset = saa711x_reset,
1544 .s_gpio = saa711x_s_gpio,
1545#ifdef CONFIG_VIDEO_ADV_DEBUG
1546 .g_register = saa711x_g_register,
1547 .s_register = saa711x_s_register,
1548#endif
1549};
1550
1551static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001552 .s_radio = saa711x_s_radio,
1553 .g_tuner = saa711x_g_tuner,
1554};
1555
1556static const struct v4l2_subdev_audio_ops saa711x_audio_ops = {
1557 .s_clock_freq = saa711x_s_clock_freq,
1558};
1559
1560static const struct v4l2_subdev_video_ops saa711x_video_ops = {
1561 .s_routing = saa711x_s_routing,
1562 .s_crystal_freq = saa711x_s_crystal_freq,
1563 .g_fmt = saa711x_g_fmt,
1564 .s_fmt = saa711x_s_fmt,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001565 .s_stream = saa711x_s_stream,
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001566 .querystd = saa711x_querystd,
1567 .g_input_status = saa711x_g_input_status,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001568};
1569
Hans Verkuil32cd5272010-03-14 09:57:30 -03001570static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = {
1571 .g_vbi_data = saa711x_g_vbi_data,
1572 .decode_vbi_line = saa711x_decode_vbi_line,
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001573 .g_sliced_fmt = saa711x_g_sliced_fmt,
1574 .s_sliced_fmt = saa711x_s_sliced_fmt,
1575 .s_raw_fmt = saa711x_s_raw_fmt,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001576};
1577
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001578static const struct v4l2_subdev_ops saa711x_ops = {
1579 .core = &saa711x_core_ops,
1580 .tuner = &saa711x_tuner_ops,
1581 .audio = &saa711x_audio_ops,
1582 .video = &saa711x_video_ops,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001583 .vbi = &saa711x_vbi_ops,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001584};
1585
1586/* ----------------------------------------------------------------------- */
1587
1588static int saa711x_probe(struct i2c_client *client,
Jean Delvared2653e92008-04-29 23:11:39 +02001589 const struct i2c_device_id *id)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001590{
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001591 struct saa711x_state *state;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001592 struct v4l2_subdev *sd;
Mauro Carvalho Chehab236f16d2006-08-28 08:25:29 -03001593 int i;
1594 char name[17];
Jean Delvareaf294862008-05-18 20:49:40 +02001595 char chip_id;
1596 int autodetect = !id || id->driver_data == 1;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001597
1598 /* Check if the adapter supports the needed features */
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001599 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
Hans Verkuil188f3452007-09-16 10:47:15 -03001600 return -EIO;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001601
Hans Verkuild0d30c02006-11-25 09:45:50 -03001602 for (i = 0; i < 0x0f; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001603 i2c_smbus_write_byte_data(client, 0, i);
1604 name[i] = (i2c_smbus_read_byte_data(client, 0) & 0x0f) + '0';
Hans Verkuild0d30c02006-11-25 09:45:50 -03001605 if (name[i] > '9')
1606 name[i] += 'a' - '9' - 1;
Mauro Carvalho Chehab236f16d2006-08-28 08:25:29 -03001607 }
Hans Verkuild0d30c02006-11-25 09:45:50 -03001608 name[i] = '\0';
Mauro Carvalho Chehab236f16d2006-08-28 08:25:29 -03001609
Jean Delvareaf294862008-05-18 20:49:40 +02001610 chip_id = name[5];
Mauro Carvalho Chehab3e7d3e52006-09-01 18:39:05 -03001611
Hans Verkuilf7668162006-11-25 09:40:28 -03001612 /* Check whether this chip is part of the saa711x series */
1613 if (memcmp(name, "1f711", 5)) {
1614 v4l_dbg(1, debug, client, "chip found @ 0x%x (ID %s) does not match a known saa711x chip.\n",
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001615 client->addr << 1, name);
Hans Verkuil188f3452007-09-16 10:47:15 -03001616 return -ENODEV;
Hans Verkuilf7668162006-11-25 09:40:28 -03001617 }
1618
Jean Delvareaf294862008-05-18 20:49:40 +02001619 /* Safety check */
1620 if (!autodetect && id->name[6] != chip_id) {
1621 v4l_warn(client, "found saa711%c while %s was expected\n",
1622 chip_id, id->name);
1623 }
1624 snprintf(client->name, sizeof(client->name), "saa711%c", chip_id);
1625 v4l_info(client, "saa711%c found (%s) @ 0x%x (%s)\n", chip_id, name,
1626 client->addr << 1, client->adapter->name);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001627
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001628 state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL);
Hans Verkuilc5bf2042008-09-03 17:12:09 -03001629 if (state == NULL)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001630 return -ENOMEM;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001631 sd = &state->sd;
1632 v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001633 state->input = -1;
Marco Schluessler4cbca182007-01-21 19:43:38 -03001634 state->output = SAA7115_IPORT_ON;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001635 state->enable = 1;
Hans Verkuil3faeeae2006-01-09 15:25:44 -02001636 state->radio = 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001637 state->bright = 128;
1638 state->contrast = 64;
1639 state->hue = 0;
1640 state->sat = 64;
Devin Heitmueller87a6fe42010-03-11 21:49:24 -03001641 state->chroma_agc = 1;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001642 switch (chip_id) {
Jean Delvareaf294862008-05-18 20:49:40 +02001643 case '1':
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001644 state->ident = V4L2_IDENT_SAA7111;
Hans Verkuil340dde82010-02-20 08:07:51 -03001645 if (saa711x_read(sd, R_00_CHIP_VERSION) & 0xf0) {
1646 v4l_info(client, "saa7111a variant found\n");
1647 state->ident = V4L2_IDENT_SAA7111A;
1648 }
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001649 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001650 case '3':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001651 state->ident = V4L2_IDENT_SAA7113;
1652 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001653 case '4':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001654 state->ident = V4L2_IDENT_SAA7114;
1655 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001656 case '5':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001657 state->ident = V4L2_IDENT_SAA7115;
1658 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001659 case '8':
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001660 state->ident = V4L2_IDENT_SAA7118;
1661 break;
1662 default:
1663 state->ident = V4L2_IDENT_SAA7111;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001664 v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n");
Hans Verkuil340dde82010-02-20 08:07:51 -03001665 break;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001666 }
1667
Hans Verkuil3578d3d2006-01-09 15:25:41 -02001668 state->audclk_freq = 48000;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001669
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001670 v4l2_dbg(1, debug, sd, "writing init values\n");
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001671
1672 /* init to 60hz/48khz */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001673 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
1674 switch (state->ident) {
1675 case V4L2_IDENT_SAA7111:
Hans Verkuil340dde82010-02-20 08:07:51 -03001676 case V4L2_IDENT_SAA7111A:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001677 saa711x_writeregs(sd, saa7111_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001678 break;
1679 case V4L2_IDENT_SAA7113:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001680 saa711x_writeregs(sd, saa7113_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001681 break;
1682 default:
Hans Verkuilb7f82922006-04-02 12:50:42 -03001683 state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001684 saa711x_writeregs(sd, saa7115_init_auto_input);
Hans Verkuilb7f82922006-04-02 12:50:42 -03001685 }
Hans Verkuil340dde82010-02-20 08:07:51 -03001686 if (state->ident > V4L2_IDENT_SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001687 saa711x_writeregs(sd, saa7115_init_misc);
1688 saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001689
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001690 v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n",
1691 saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC),
1692 saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001693 return 0;
1694}
1695
1696/* ----------------------------------------------------------------------- */
1697
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001698static int saa711x_remove(struct i2c_client *client)
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001699{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001700 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1701
1702 v4l2_device_unregister_subdev(sd);
1703 kfree(to_state(sd));
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001704 return 0;
1705}
1706
Jean Delvareaf294862008-05-18 20:49:40 +02001707static const struct i2c_device_id saa7115_id[] = {
Hans Verkuil9edd350f2008-07-17 13:22:51 -03001708 { "saa7115_auto", 1 }, /* autodetect */
Jean Delvareaf294862008-05-18 20:49:40 +02001709 { "saa7111", 0 },
1710 { "saa7113", 0 },
1711 { "saa7114", 0 },
1712 { "saa7115", 0 },
1713 { "saa7118", 0 },
1714 { }
1715};
1716MODULE_DEVICE_TABLE(i2c, saa7115_id);
1717
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001718static struct v4l2_i2c_driver_data v4l2_i2c_data = {
1719 .name = "saa7115",
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001720 .probe = saa711x_probe,
1721 .remove = saa711x_remove,
Jean Delvareaf294862008-05-18 20:49:40 +02001722 .id_table = saa7115_id,
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001723};