blob: 76da74368680f9a10f747fc0c8322a56f2c630bd [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_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
1121{
1122 saa711x_set_lcr(sd, NULL);
1123 return 0;
1124}
1125
1126static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
1127{
1128 saa711x_set_lcr(sd, fmt);
1129 return 0;
1130}
1131
Hans Verkuilc463d932010-05-09 09:47:23 -03001132static int saa711x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
1133{
1134 if (fmt->code != V4L2_MBUS_FMT_FIXED)
1135 return -EINVAL;
1136 fmt->field = V4L2_FIELD_INTERLACED;
1137 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1138 return saa711x_set_size(sd, fmt->width, fmt->height);
1139}
1140
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001141/* Decode the sliced VBI data stream as created by the saa7115.
1142 The format is described in the saa7115 datasheet in Tables 25 and 26
1143 and in Figure 33.
1144 The current implementation uses SAV/EAV codes and not the ancillary data
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001145 headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001146 code. */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001147static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001148{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001149 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001150 static const char vbi_no_data_pattern[] = {
1151 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
1152 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001153 u8 *p = vbi->p;
1154 u32 wss;
1155 int id1, id2; /* the ID1 and ID2 bytes from the internal header */
1156
1157 vbi->type = 0; /* mark result as a failure */
1158 id1 = p[2];
1159 id2 = p[3];
1160 /* Note: the field bit is inverted for 60 Hz video */
1161 if (state->std & V4L2_STD_525_60)
1162 id1 ^= 0x40;
1163
1164 /* Skip internal header, p now points to the start of the payload */
1165 p += 4;
1166 vbi->p = p;
1167
1168 /* calculate field and line number of the VBI packet (1-23) */
1169 vbi->is_second_field = ((id1 & 0x40) != 0);
1170 vbi->line = (id1 & 0x3f) << 3;
1171 vbi->line |= (id2 & 0x70) >> 4;
1172
1173 /* Obtain data type */
1174 id2 &= 0xf;
1175
1176 /* If the VBI slicer does not detect any signal it will fill up
1177 the payload buffer with 0xa0 bytes. */
1178 if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001179 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001180
1181 /* decode payloads */
1182 switch (id2) {
1183 case 1:
Hans Verkuil9bc74002006-03-29 18:02:51 -03001184 vbi->type = V4L2_SLICED_TELETEXT_B;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001185 break;
1186 case 4:
Mauro Carvalho Chehab59ba9152006-08-30 05:34:36 -03001187 if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001188 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001189 vbi->type = V4L2_SLICED_CAPTION_525;
1190 break;
1191 case 5:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001192 wss = saa711x_decode_wss(p);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001193 if (wss == -1)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001194 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001195 p[0] = wss & 0xff;
1196 p[1] = wss >> 8;
1197 vbi->type = V4L2_SLICED_WSS_625;
1198 break;
1199 case 7:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001200 if (saa711x_decode_vps(p, p) != 0)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001201 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001202 vbi->type = V4L2_SLICED_VPS;
1203 break;
1204 default:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001205 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001206 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001207 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001208}
1209
1210/* ============ SAA7115 AUDIO settings (end) ============= */
1211
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001212static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001213{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001214 struct saa711x_state *state = to_state(sd);
1215 int status;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001216
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001217 if (state->radio)
1218 return 0;
1219 status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001220
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001221 v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status);
1222 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1223 return 0;
1224}
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001225
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001226static int saa711x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
1227{
1228 switch (qc->id) {
1229 case V4L2_CID_BRIGHTNESS:
Hans Verkuil10afbef2009-02-21 18:47:24 -03001230 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001231 case V4L2_CID_CONTRAST:
1232 case V4L2_CID_SATURATION:
Hans Verkuil10afbef2009-02-21 18:47:24 -03001233 return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001234 case V4L2_CID_HUE:
Hans Verkuil10afbef2009-02-21 18:47:24 -03001235 return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
Devin Heitmueller87a6fe42010-03-11 21:49:24 -03001236 case V4L2_CID_CHROMA_AGC:
1237 return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
1238 case V4L2_CID_CHROMA_GAIN:
Devin Heitmuellerf1a4f9e2010-03-11 22:00:13 -03001239 return v4l2_ctrl_query_fill(qc, 0, 127, 1, 48);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001240 default:
1241 return -EINVAL;
1242 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001243}
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001244
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001245static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1246{
1247 struct saa711x_state *state = to_state(sd);
1248
1249 state->radio = 0;
1250 saa711x_set_v4lstd(sd, std);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001251 return 0;
1252}
1253
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001254static int saa711x_s_radio(struct v4l2_subdev *sd)
1255{
1256 struct saa711x_state *state = to_state(sd);
1257
1258 state->radio = 1;
1259 return 0;
1260}
1261
Hans Verkuil5325b422009-04-02 11:26:22 -03001262static int saa711x_s_routing(struct v4l2_subdev *sd,
1263 u32 input, u32 output, u32 config)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001264{
1265 struct saa711x_state *state = to_state(sd);
Hans Verkuil340dde82010-02-20 08:07:51 -03001266 u8 mask = (state->ident <= V4L2_IDENT_SAA7111A) ? 0xf8 : 0xf0;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001267
Hans Verkuil5325b422009-04-02 11:26:22 -03001268 v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n",
1269 input, output);
1270
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001271 /* saa7111/3 does not have these inputs */
Hans Verkuil340dde82010-02-20 08:07:51 -03001272 if (state->ident <= V4L2_IDENT_SAA7113 &&
Hans Verkuil5325b422009-04-02 11:26:22 -03001273 (input == SAA7115_COMPOSITE4 ||
1274 input == SAA7115_COMPOSITE5)) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001275 return -EINVAL;
1276 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001277 if (input > SAA7115_SVIDEO3)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001278 return -EINVAL;
Hans Verkuil5325b422009-04-02 11:26:22 -03001279 if (state->input == input && state->output == output)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001280 return 0;
1281 v4l2_dbg(1, debug, sd, "now setting %s input %s output\n",
Hans Verkuil5325b422009-04-02 11:26:22 -03001282 (input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite",
1283 (output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
1284 state->input = input;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001285
1286 /* saa7111 has slightly different input numbering */
Hans Verkuil340dde82010-02-20 08:07:51 -03001287 if (state->ident <= V4L2_IDENT_SAA7111A) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001288 if (input >= SAA7115_COMPOSITE4)
1289 input -= 2;
1290 /* saa7111 specific */
1291 saa711x_write(sd, R_10_CHROMA_CNTL_2,
1292 (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001293 ((output & 0xc0) ^ 0x40));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001294 saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL,
1295 (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001296 ((output & 2) ? 0x0a : 0));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001297 }
1298
1299 /* select mode */
1300 saa711x_write(sd, R_02_INPUT_CNTL_1,
1301 (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) |
1302 input);
1303
1304 /* bypass chrominance trap for S-Video modes */
1305 saa711x_write(sd, R_09_LUMA_CNTL,
1306 (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) |
1307 (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
1308
Hans Verkuil5325b422009-04-02 11:26:22 -03001309 state->output = output;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001310 if (state->ident == V4L2_IDENT_SAA7114 ||
1311 state->ident == V4L2_IDENT_SAA7115) {
1312 saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
1313 (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
1314 (state->output & 0x01));
1315 }
1316 return 0;
1317}
1318
1319static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val)
1320{
1321 struct saa711x_state *state = to_state(sd);
1322
Hans Verkuil340dde82010-02-20 08:07:51 -03001323 if (state->ident > V4L2_IDENT_SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001324 return -EINVAL;
1325 saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) |
1326 (val ? 0x80 : 0));
1327 return 0;
1328}
1329
1330static int saa711x_s_stream(struct v4l2_subdev *sd, int enable)
1331{
1332 struct saa711x_state *state = to_state(sd);
1333
1334 v4l2_dbg(1, debug, sd, "%s output\n",
1335 enable ? "enable" : "disable");
1336
Hans Verkuil674a3232009-02-18 12:22:16 -03001337 if (state->enable == enable)
1338 return 0;
1339 state->enable = enable;
1340 if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED))
1341 return 0;
1342 saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001343 return 0;
1344}
1345
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001346static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001347{
1348 struct saa711x_state *state = to_state(sd);
1349
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001350 if (freq != SAA7115_FREQ_32_11_MHZ && freq != SAA7115_FREQ_24_576_MHZ)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001351 return -EINVAL;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001352 state->crystal_freq = freq;
1353 state->cgcdiv = (flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
1354 state->ucgc = (flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;
1355 state->apll = (flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001356 saa711x_s_clock_freq(sd, state->audclk_freq);
1357 return 0;
1358}
1359
1360static int saa711x_reset(struct v4l2_subdev *sd, u32 val)
1361{
1362 v4l2_dbg(1, debug, sd, "decoder RESET\n");
1363 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
1364 return 0;
1365}
1366
1367static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data)
1368{
1369 /* Note: the internal field ID is inverted for NTSC,
1370 so data->field 0 maps to the saa7115 even field,
1371 whereas for PAL it maps to the saa7115 odd field. */
1372 switch (data->id) {
1373 case V4L2_SLICED_WSS_625:
1374 if (saa711x_read(sd, 0x6b) & 0xc0)
1375 return -EIO;
1376 data->data[0] = saa711x_read(sd, 0x6c);
1377 data->data[1] = saa711x_read(sd, 0x6d);
1378 return 0;
1379 case V4L2_SLICED_CAPTION_525:
1380 if (data->field == 0) {
1381 /* CC */
1382 if (saa711x_read(sd, 0x66) & 0x30)
1383 return -EIO;
1384 data->data[0] = saa711x_read(sd, 0x69);
1385 data->data[1] = saa711x_read(sd, 0x6a);
1386 return 0;
1387 }
1388 /* XDS */
1389 if (saa711x_read(sd, 0x66) & 0xc0)
1390 return -EIO;
1391 data->data[0] = saa711x_read(sd, 0x67);
1392 data->data[1] = saa711x_read(sd, 0x68);
1393 return 0;
1394 default:
1395 return -EINVAL;
1396 }
1397}
1398
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001399static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
1400{
1401 struct saa711x_state *state = to_state(sd);
1402 int reg1e;
1403
1404 *std = V4L2_STD_ALL;
1405 if (state->ident != V4L2_IDENT_SAA7115)
1406 return 0;
1407 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1408
1409 switch (reg1e & 0x03) {
1410 case 1:
1411 *std = V4L2_STD_NTSC;
1412 break;
1413 case 2:
1414 *std = V4L2_STD_PAL;
1415 break;
1416 case 3:
1417 *std = V4L2_STD_SECAM;
1418 break;
1419 default:
1420 break;
1421 }
1422 return 0;
1423}
1424
1425static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status)
1426{
1427 struct saa711x_state *state = to_state(sd);
1428 int reg1e = 0x80;
1429 int reg1f;
1430
1431 *status = V4L2_IN_ST_NO_SIGNAL;
1432 if (state->ident == V4L2_IDENT_SAA7115)
1433 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1434 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1435 if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80)
1436 *status = 0;
1437 return 0;
1438}
1439
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001440#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001441static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001442{
1443 struct i2c_client *client = v4l2_get_subdevdata(sd);
1444
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001445 if (!v4l2_chip_match_i2c_client(client, &reg->match))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001446 return -EINVAL;
1447 if (!capable(CAP_SYS_ADMIN))
1448 return -EPERM;
1449 reg->val = saa711x_read(sd, reg->reg & 0xff);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001450 reg->size = 1;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001451 return 0;
1452}
1453
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001454static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001455{
1456 struct i2c_client *client = v4l2_get_subdevdata(sd);
1457
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001458 if (!v4l2_chip_match_i2c_client(client, &reg->match))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001459 return -EINVAL;
1460 if (!capable(CAP_SYS_ADMIN))
1461 return -EPERM;
1462 saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff);
1463 return 0;
1464}
1465#endif
1466
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001467static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001468{
1469 struct saa711x_state *state = to_state(sd);
1470 struct i2c_client *client = v4l2_get_subdevdata(sd);
1471
1472 return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0);
1473}
1474
1475static int saa711x_log_status(struct v4l2_subdev *sd)
1476{
1477 struct saa711x_state *state = to_state(sd);
1478 int reg1e, reg1f;
1479 int signalOk;
1480 int vcr;
1481
1482 v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq);
1483 if (state->ident != V4L2_IDENT_SAA7115) {
1484 /* status for the saa7114 */
1485 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1486 signalOk = (reg1f & 0xc1) == 0x81;
1487 v4l2_info(sd, "Video signal: %s\n", signalOk ? "ok" : "bad");
1488 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1489 return 0;
1490 }
1491
1492 /* status for the saa7115 */
1493 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1494 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1495
1496 signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
1497 vcr = !(reg1f & 0x10);
1498
1499 if (state->input >= 6)
1500 v4l2_info(sd, "Input: S-Video %d\n", state->input - 6);
1501 else
1502 v4l2_info(sd, "Input: Composite %d\n", state->input);
1503 v4l2_info(sd, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
1504 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1505
1506 switch (reg1e & 0x03) {
1507 case 1:
1508 v4l2_info(sd, "Detected format: NTSC\n");
1509 break;
1510 case 2:
1511 v4l2_info(sd, "Detected format: PAL\n");
1512 break;
1513 case 3:
1514 v4l2_info(sd, "Detected format: SECAM\n");
1515 break;
1516 default:
1517 v4l2_info(sd, "Detected format: BW/No color\n");
1518 break;
1519 }
1520 v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height);
1521 return 0;
1522}
1523
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001524/* ----------------------------------------------------------------------- */
1525
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001526static const struct v4l2_subdev_core_ops saa711x_core_ops = {
1527 .log_status = saa711x_log_status,
1528 .g_chip_ident = saa711x_g_chip_ident,
1529 .g_ctrl = saa711x_g_ctrl,
1530 .s_ctrl = saa711x_s_ctrl,
1531 .queryctrl = saa711x_queryctrl,
Hans Verkuilf41737e2009-04-01 03:52:39 -03001532 .s_std = saa711x_s_std,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001533 .reset = saa711x_reset,
1534 .s_gpio = saa711x_s_gpio,
1535#ifdef CONFIG_VIDEO_ADV_DEBUG
1536 .g_register = saa711x_g_register,
1537 .s_register = saa711x_s_register,
1538#endif
1539};
1540
1541static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001542 .s_radio = saa711x_s_radio,
1543 .g_tuner = saa711x_g_tuner,
1544};
1545
1546static const struct v4l2_subdev_audio_ops saa711x_audio_ops = {
1547 .s_clock_freq = saa711x_s_clock_freq,
1548};
1549
1550static const struct v4l2_subdev_video_ops saa711x_video_ops = {
1551 .s_routing = saa711x_s_routing,
1552 .s_crystal_freq = saa711x_s_crystal_freq,
Hans Verkuilc463d932010-05-09 09:47:23 -03001553 .s_mbus_fmt = saa711x_s_mbus_fmt,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001554 .s_stream = saa711x_s_stream,
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001555 .querystd = saa711x_querystd,
1556 .g_input_status = saa711x_g_input_status,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001557};
1558
Hans Verkuil32cd5272010-03-14 09:57:30 -03001559static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = {
1560 .g_vbi_data = saa711x_g_vbi_data,
1561 .decode_vbi_line = saa711x_decode_vbi_line,
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001562 .g_sliced_fmt = saa711x_g_sliced_fmt,
1563 .s_sliced_fmt = saa711x_s_sliced_fmt,
1564 .s_raw_fmt = saa711x_s_raw_fmt,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001565};
1566
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001567static const struct v4l2_subdev_ops saa711x_ops = {
1568 .core = &saa711x_core_ops,
1569 .tuner = &saa711x_tuner_ops,
1570 .audio = &saa711x_audio_ops,
1571 .video = &saa711x_video_ops,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001572 .vbi = &saa711x_vbi_ops,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001573};
1574
1575/* ----------------------------------------------------------------------- */
1576
1577static int saa711x_probe(struct i2c_client *client,
Jean Delvared2653e92008-04-29 23:11:39 +02001578 const struct i2c_device_id *id)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001579{
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001580 struct saa711x_state *state;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001581 struct v4l2_subdev *sd;
Mauro Carvalho Chehab236f16d2006-08-28 08:25:29 -03001582 int i;
1583 char name[17];
Jean Delvareaf294862008-05-18 20:49:40 +02001584 char chip_id;
1585 int autodetect = !id || id->driver_data == 1;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001586
1587 /* Check if the adapter supports the needed features */
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001588 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
Hans Verkuil188f3452007-09-16 10:47:15 -03001589 return -EIO;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001590
Hans Verkuild0d30c02006-11-25 09:45:50 -03001591 for (i = 0; i < 0x0f; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001592 i2c_smbus_write_byte_data(client, 0, i);
1593 name[i] = (i2c_smbus_read_byte_data(client, 0) & 0x0f) + '0';
Hans Verkuild0d30c02006-11-25 09:45:50 -03001594 if (name[i] > '9')
1595 name[i] += 'a' - '9' - 1;
Mauro Carvalho Chehab236f16d2006-08-28 08:25:29 -03001596 }
Hans Verkuild0d30c02006-11-25 09:45:50 -03001597 name[i] = '\0';
Mauro Carvalho Chehab236f16d2006-08-28 08:25:29 -03001598
Jean Delvareaf294862008-05-18 20:49:40 +02001599 chip_id = name[5];
Mauro Carvalho Chehab3e7d3e52006-09-01 18:39:05 -03001600
Hans Verkuilf7668162006-11-25 09:40:28 -03001601 /* Check whether this chip is part of the saa711x series */
1602 if (memcmp(name, "1f711", 5)) {
1603 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 -03001604 client->addr << 1, name);
Hans Verkuil188f3452007-09-16 10:47:15 -03001605 return -ENODEV;
Hans Verkuilf7668162006-11-25 09:40:28 -03001606 }
1607
Jean Delvareaf294862008-05-18 20:49:40 +02001608 /* Safety check */
1609 if (!autodetect && id->name[6] != chip_id) {
1610 v4l_warn(client, "found saa711%c while %s was expected\n",
1611 chip_id, id->name);
1612 }
1613 snprintf(client->name, sizeof(client->name), "saa711%c", chip_id);
1614 v4l_info(client, "saa711%c found (%s) @ 0x%x (%s)\n", chip_id, name,
1615 client->addr << 1, client->adapter->name);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001616
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001617 state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL);
Hans Verkuilc5bf2042008-09-03 17:12:09 -03001618 if (state == NULL)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001619 return -ENOMEM;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001620 sd = &state->sd;
1621 v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001622 state->input = -1;
Marco Schluessler4cbca182007-01-21 19:43:38 -03001623 state->output = SAA7115_IPORT_ON;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001624 state->enable = 1;
Hans Verkuil3faeeae2006-01-09 15:25:44 -02001625 state->radio = 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001626 state->bright = 128;
1627 state->contrast = 64;
1628 state->hue = 0;
1629 state->sat = 64;
Devin Heitmueller87a6fe42010-03-11 21:49:24 -03001630 state->chroma_agc = 1;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001631 switch (chip_id) {
Jean Delvareaf294862008-05-18 20:49:40 +02001632 case '1':
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001633 state->ident = V4L2_IDENT_SAA7111;
Hans Verkuil340dde82010-02-20 08:07:51 -03001634 if (saa711x_read(sd, R_00_CHIP_VERSION) & 0xf0) {
1635 v4l_info(client, "saa7111a variant found\n");
1636 state->ident = V4L2_IDENT_SAA7111A;
1637 }
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001638 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001639 case '3':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001640 state->ident = V4L2_IDENT_SAA7113;
1641 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001642 case '4':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001643 state->ident = V4L2_IDENT_SAA7114;
1644 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001645 case '5':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001646 state->ident = V4L2_IDENT_SAA7115;
1647 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001648 case '8':
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001649 state->ident = V4L2_IDENT_SAA7118;
1650 break;
1651 default:
1652 state->ident = V4L2_IDENT_SAA7111;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001653 v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n");
Hans Verkuil340dde82010-02-20 08:07:51 -03001654 break;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001655 }
1656
Hans Verkuil3578d3d2006-01-09 15:25:41 -02001657 state->audclk_freq = 48000;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001658
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001659 v4l2_dbg(1, debug, sd, "writing init values\n");
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001660
1661 /* init to 60hz/48khz */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001662 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
1663 switch (state->ident) {
1664 case V4L2_IDENT_SAA7111:
Hans Verkuil340dde82010-02-20 08:07:51 -03001665 case V4L2_IDENT_SAA7111A:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001666 saa711x_writeregs(sd, saa7111_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001667 break;
1668 case V4L2_IDENT_SAA7113:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001669 saa711x_writeregs(sd, saa7113_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001670 break;
1671 default:
Hans Verkuilb7f82922006-04-02 12:50:42 -03001672 state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001673 saa711x_writeregs(sd, saa7115_init_auto_input);
Hans Verkuilb7f82922006-04-02 12:50:42 -03001674 }
Hans Verkuil340dde82010-02-20 08:07:51 -03001675 if (state->ident > V4L2_IDENT_SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001676 saa711x_writeregs(sd, saa7115_init_misc);
1677 saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001678
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001679 v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n",
1680 saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC),
1681 saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001682 return 0;
1683}
1684
1685/* ----------------------------------------------------------------------- */
1686
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001687static int saa711x_remove(struct i2c_client *client)
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001688{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001689 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1690
1691 v4l2_device_unregister_subdev(sd);
1692 kfree(to_state(sd));
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001693 return 0;
1694}
1695
Jean Delvareaf294862008-05-18 20:49:40 +02001696static const struct i2c_device_id saa7115_id[] = {
Hans Verkuil9edd350f2008-07-17 13:22:51 -03001697 { "saa7115_auto", 1 }, /* autodetect */
Jean Delvareaf294862008-05-18 20:49:40 +02001698 { "saa7111", 0 },
1699 { "saa7113", 0 },
1700 { "saa7114", 0 },
1701 { "saa7115", 0 },
1702 { "saa7118", 0 },
1703 { }
1704};
1705MODULE_DEVICE_TABLE(i2c, saa7115_id);
1706
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001707static struct v4l2_i2c_driver_data v4l2_i2c_data = {
1708 .name = "saa7115",
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001709 .probe = saa711x_probe,
1710 .remove = saa711x_remove,
Jean Delvareaf294862008-05-18 20:49:40 +02001711 .id_table = saa7115_id,
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001712};