blob: 591f7f98aa33a9a843ba333a083d0b91192983d2 [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 Verkuilfbaa3d0d2007-09-13 11:19:39 -030049#include <media/v4l2-i2c-drv-legacy.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
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -030065static unsigned short normal_i2c[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -030066 0x4a >> 1, 0x48 >> 1, /* SAA7111, SAA7111A and SAA7113 */
67 0x42 >> 1, 0x40 >> 1, /* SAA7114, SAA7115 and SAA7118 */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -030068 I2C_CLIENT_END };
Hans Verkuile19b2fc2005-11-13 16:08:04 -080069
Hans Verkuile19b2fc2005-11-13 16:08:04 -080070I2C_CLIENT_INSMOD;
71
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -030072struct saa711x_state {
Hans Verkuil9415f4b2008-11-29 12:55:19 -030073 struct v4l2_subdev sd;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080074 v4l2_std_id std;
75 int input;
Marco Schluessler4cbca182007-01-21 19:43:38 -030076 int output;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080077 int enable;
Hans Verkuil3faeeae2006-01-09 15:25:44 -020078 int radio;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080079 int bright;
80 int contrast;
81 int hue;
82 int sat;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -030083 int width;
84 int height;
Hans Verkuil3434eb72007-04-27 12:31:08 -030085 u32 ident;
Hans Verkuil3578d3d2006-01-09 15:25:41 -020086 u32 audclk_freq;
Hans Verkuilb7f82922006-04-02 12:50:42 -030087 u32 crystal_freq;
88 u8 ucgc;
89 u8 cgcdiv;
90 u8 apll;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080091};
92
Hans Verkuil9415f4b2008-11-29 12:55:19 -030093static inline struct saa711x_state *to_state(struct v4l2_subdev *sd)
94{
95 return container_of(sd, struct saa711x_state, sd);
96}
97
Hans Verkuile19b2fc2005-11-13 16:08:04 -080098/* ----------------------------------------------------------------------- */
99
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300100static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800101{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300102 struct i2c_client *client = v4l2_get_subdevdata(sd);
103
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800104 return i2c_smbus_write_byte_data(client, reg, value);
105}
106
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300107/* Sanity routine to check if a register is present */
108static int saa711x_has_reg(const int id, const u8 reg)
109{
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300110 if (id == V4L2_IDENT_SAA7111)
111 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
112 (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300113
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300114 /* common for saa7113/4/5/8 */
115 if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f ||
116 reg == 0xa3 || reg == 0xa7 || reg == 0xab || reg == 0xaf || (reg >= 0xb5 && reg <= 0xb7) ||
117 reg == 0xd3 || reg == 0xd7 || reg == 0xdb || reg == 0xdf || (reg >= 0xe5 && reg <= 0xe7) ||
118 reg == 0x82 || (reg >= 0x89 && reg <= 0x8e)))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300119 return 0;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300120
121 switch (id) {
122 case V4L2_IDENT_SAA7113:
123 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
124 reg != 0x5d && reg < 0x63;
125 case V4L2_IDENT_SAA7114:
126 return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
127 (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
128 reg != 0x81 && reg < 0xf0;
129 case V4L2_IDENT_SAA7115:
130 return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe);
131 case V4L2_IDENT_SAA7118:
132 return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
133 (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
134 (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
135 }
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300136 return 1;
137}
138
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300139static int saa711x_writeregs(struct v4l2_subdev *sd, const unsigned char *regs)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800140{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300141 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800142 unsigned char reg, data;
143
144 while (*regs != 0x00) {
145 reg = *(regs++);
146 data = *(regs++);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300147
148 /* According with datasheets, reserved regs should be
149 filled with 0 - seems better not to touch on they */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300150 if (saa711x_has_reg(state->ident, reg)) {
151 if (saa711x_write(sd, reg, data) < 0)
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300152 return -1;
Mauro Carvalho Chehabd87edf22006-09-01 09:37:11 -0300153 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300154 v4l2_dbg(1, debug, sd, "tried to access reserved reg 0x%02x\n", reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300155 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800156 }
157 return 0;
158}
159
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300160static inline int saa711x_read(struct v4l2_subdev *sd, u8 reg)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800161{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300162 struct i2c_client *client = v4l2_get_subdevdata(sd);
163
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800164 return i2c_smbus_read_byte_data(client, reg);
165}
166
167/* ----------------------------------------------------------------------- */
168
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300169/* SAA7111 initialization table */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300170static const unsigned char saa7111_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300171 R_01_INC_DELAY, 0x00, /* reserved */
172
173 /*front end */
174 R_02_INPUT_CNTL_1, 0xd0, /* FUSE=3, GUDL=2, MODE=0 */
175 R_03_INPUT_CNTL_2, 0x23, /* HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0,
176 * GAFIX=0, GAI1=256, GAI2=256 */
177 R_04_INPUT_CNTL_3, 0x00, /* GAI1=256 */
178 R_05_INPUT_CNTL_4, 0x00, /* GAI2=256 */
179
180 /* decoder */
181 R_06_H_SYNC_START, 0xf3, /* HSB at 13(50Hz) / 17(60Hz)
182 * pixels after end of last line */
183 R_07_H_SYNC_STOP, 0xe8, /* HSS seems to be needed to
184 * work with NTSC, too */
185 R_08_SYNC_CNTL, 0xc8, /* AUFD=1, FSEL=1, EXFIL=0,
186 * VTRC=1, HPLL=0, VNOI=0 */
187 R_09_LUMA_CNTL, 0x01, /* BYPS=0, PREF=0, BPSS=0,
188 * VBLB=0, UPTCV=0, APER=1 */
189 R_0A_LUMA_BRIGHT_CNTL, 0x80,
190 R_0B_LUMA_CONTRAST_CNTL, 0x47, /* 0b - CONT=1.109 */
191 R_0C_CHROMA_SAT_CNTL, 0x40,
192 R_0D_CHROMA_HUE_CNTL, 0x00,
193 R_0E_CHROMA_CNTL_1, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0,
194 * FCTC=0, CHBW=1 */
195 R_0F_CHROMA_GAIN_CNTL, 0x00, /* reserved */
196 R_10_CHROMA_CNTL_2, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
197 R_11_MODE_DELAY_CNTL, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
198 * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
199 R_12_RT_SIGNAL_CNTL, 0x00, /* 12 - output control 2 */
200 R_13_RT_X_PORT_OUT_CNTL, 0x00, /* 13 - output control 3 */
201 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
202 R_15_VGATE_START_FID_CHG, 0x00,
203 R_16_VGATE_STOP, 0x00,
204 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
205
206 0x00, 0x00
207};
208
209/* SAA7113 init codes */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300210static const unsigned char saa7113_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300211 R_01_INC_DELAY, 0x08,
212 R_02_INPUT_CNTL_1, 0xc2,
213 R_03_INPUT_CNTL_2, 0x30,
214 R_04_INPUT_CNTL_3, 0x00,
215 R_05_INPUT_CNTL_4, 0x00,
216 R_06_H_SYNC_START, 0x89,
217 R_07_H_SYNC_STOP, 0x0d,
218 R_08_SYNC_CNTL, 0x88,
219 R_09_LUMA_CNTL, 0x01,
220 R_0A_LUMA_BRIGHT_CNTL, 0x80,
221 R_0B_LUMA_CONTRAST_CNTL, 0x47,
222 R_0C_CHROMA_SAT_CNTL, 0x40,
223 R_0D_CHROMA_HUE_CNTL, 0x00,
224 R_0E_CHROMA_CNTL_1, 0x01,
225 R_0F_CHROMA_GAIN_CNTL, 0x2a,
226 R_10_CHROMA_CNTL_2, 0x08,
227 R_11_MODE_DELAY_CNTL, 0x0c,
228 R_12_RT_SIGNAL_CNTL, 0x07,
229 R_13_RT_X_PORT_OUT_CNTL, 0x00,
230 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
231 R_15_VGATE_START_FID_CHG, 0x00,
232 R_16_VGATE_STOP, 0x00,
233 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
234
235 0x00, 0x00
236};
237
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800238/* If a value differs from the Hauppauge driver values, then the comment starts with
239 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
240 Hauppauge driver sets. */
241
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300242/* SAA7114 and SAA7115 initialization table */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800243static const unsigned char saa7115_init_auto_input[] = {
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300244 /* Front-End Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300245 R_01_INC_DELAY, 0x48, /* white peak control disabled */
246 R_03_INPUT_CNTL_2, 0x20, /* was 0x30. 0x20: long vertical blanking */
247 R_04_INPUT_CNTL_3, 0x90, /* analog gain set to 0 */
248 R_05_INPUT_CNTL_4, 0x90, /* analog gain set to 0 */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300249 /* Decoder Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300250 R_06_H_SYNC_START, 0xeb, /* horiz sync begin = -21 */
251 R_07_H_SYNC_STOP, 0xe0, /* horiz sync stop = -17 */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300252 R_09_LUMA_CNTL, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300253 R_0A_LUMA_BRIGHT_CNTL, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */
254 R_0B_LUMA_CONTRAST_CNTL, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */
255 R_0C_CHROMA_SAT_CNTL, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */
256 R_0D_CHROMA_HUE_CNTL, 0x00,
257 R_0F_CHROMA_GAIN_CNTL, 0x00, /* use automatic gain */
258 R_10_CHROMA_CNTL_2, 0x06, /* chroma: active adaptive combfilter */
259 R_11_MODE_DELAY_CNTL, 0x00,
260 R_12_RT_SIGNAL_CNTL, 0x9d, /* RTS0 output control: VGATE */
261 R_13_RT_X_PORT_OUT_CNTL, 0x80, /* ITU656 standard mode, RTCO output enable RTCE */
262 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
263 R_18_RAW_DATA_GAIN_CNTL, 0x40, /* gain 0x00 = nominal */
264 R_19_RAW_DATA_OFF_CNTL, 0x80,
265 R_1A_COLOR_KILL_LVL_CNTL, 0x77, /* recommended value */
266 R_1B_MISC_TVVCRDET, 0x42, /* recommended value */
267 R_1C_ENHAN_COMB_CTRL1, 0xa9, /* recommended value */
268 R_1D_ENHAN_COMB_CTRL2, 0x01, /* recommended value */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300269
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300270
271 R_80_GLOBAL_CNTL_1, 0x0, /* No tasks enabled at init */
272
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300273 /* Power Device Control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300274 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset device */
275 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* set device programmed, all in operational mode */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800276 0x00, 0x00
277};
278
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300279/* Used to reset saa7113, saa7114 and saa7115 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800280static const unsigned char saa7115_cfg_reset_scaler[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300281 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00, /* disable I-port output */
282 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
283 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
284 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* enable I-port output */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800285 0x00, 0x00
286};
287
288/* ============== SAA7715 VIDEO templates ============= */
289
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800290static const unsigned char saa7115_cfg_60hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300291 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
292 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800293
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300294 R_15_VGATE_START_FID_CHG, 0x03,
295 R_16_VGATE_STOP, 0x11,
296 R_17_MISC_VGATE_CONF_AND_MSB, 0x9c,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800297
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300298 R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
299 R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800300
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300301 R_5A_V_OFF_FOR_SLICER, 0x06, /* standard 60hz value for ITU656 line counting */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800302
303 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300304 R_90_A_TASK_HANDLING_CNTL, 0x80,
305 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
306 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
307 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
308
309 /* hoffset low (input), 0x0002 is minimum */
310 R_94_A_HORIZ_INPUT_WINDOW_START, 0x01,
311 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
312
313 /* hsize low (input), 0x02d0 = 720 */
314 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
315 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
316
317 R_98_A_VERT_INPUT_WINDOW_START, 0x05,
318 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
319
320 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x0c,
321 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
322
323 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
324 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
325
326 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x0c,
327 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800328
329 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300330 R_C0_B_TASK_HANDLING_CNTL, 0x00,
331 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
332 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
333 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800334
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300335 /* 0x0002 is minimum */
336 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x02,
337 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800338
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300339 /* 0x02d0 = 720 */
340 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
341 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
342
343 /* vwindow start 0x12 = 18 */
344 R_C8_B_VERT_INPUT_WINDOW_START, 0x12,
345 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
346
347 /* vwindow length 0xf8 = 248 */
Mauro Carvalho Chehab97d9e802006-09-03 09:38:11 -0300348 R_CA_B_VERT_INPUT_WINDOW_LENGTH, VRES_60HZ>>1,
349 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, VRES_60HZ>>9,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300350
351 /* hwindow 0x02d0 = 720 */
352 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
353 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
354
355 R_F0_LFCO_PER_LINE, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
356 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0 */
357 R_F5_PULSGEN_LINE_LENGTH, 0xad,
358 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
359
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800360 0x00, 0x00
361};
362
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800363static const unsigned char saa7115_cfg_50hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300364 R_80_GLOBAL_CNTL_1, 0x00,
365 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800366
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300367 R_15_VGATE_START_FID_CHG, 0x37, /* VGATE start */
368 R_16_VGATE_STOP, 0x16,
369 R_17_MISC_VGATE_CONF_AND_MSB, 0x99,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800370
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300371 R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */
372 R_0E_CHROMA_CNTL_1, 0x07,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800373
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300374 R_5A_V_OFF_FOR_SLICER, 0x03, /* standard 50hz value */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800375
376 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300377 R_90_A_TASK_HANDLING_CNTL, 0x81,
378 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
379 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
380 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
381
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800382 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
383 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300384 /* hoffset low (input), 0x0002 is minimum */
385 R_94_A_HORIZ_INPUT_WINDOW_START, 0x00,
386 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
387
388 /* hsize low (input), 0x02d0 = 720 */
389 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
390 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
391
392 R_98_A_VERT_INPUT_WINDOW_START, 0x03,
393 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
394
395 /* vsize 0x12 = 18 */
396 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x12,
397 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
398
399 /* hsize 0x05a0 = 1440 */
400 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
401 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05, /* hsize hi (output) */
402 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x12, /* vsize low (output), 0x12 = 18 */
403 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00, /* vsize hi (output) */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800404
405 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300406 R_C0_B_TASK_HANDLING_CNTL, 0x00,
407 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
408 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
409 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800410
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300411 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
412 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
413 /* hoffset low (input), 0x0002 is minimum. See comment above. */
414 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x00,
415 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800416
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300417 /* hsize 0x02d0 = 720 */
418 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
419 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
420
421 /* voffset 0x16 = 22 */
422 R_C8_B_VERT_INPUT_WINDOW_START, 0x16,
423 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
424
425 /* vsize 0x0120 = 288 */
426 R_CA_B_VERT_INPUT_WINDOW_LENGTH, 0x20,
427 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, 0x01,
428
429 /* hsize 0x02d0 = 720 */
430 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
431 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
432
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300433 R_F0_LFCO_PER_LINE, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
434 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0, (was 0x05) */
435 R_F5_PULSGEN_LINE_LENGTH, 0xb0,
436 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
437
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800438 0x00, 0x00
439};
440
441/* ============== SAA7715 VIDEO templates (end) ======= */
442
443static const unsigned char saa7115_cfg_vbi_on[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300444 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
445 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
446 R_80_GLOBAL_CNTL_1, 0x30, /* Activate both tasks */
447 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
448 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
449
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800450 0x00, 0x00
451};
452
453static const unsigned char saa7115_cfg_vbi_off[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300454 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
455 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
456 R_80_GLOBAL_CNTL_1, 0x20, /* Activate only task "B" */
457 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
458 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
459
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800460 0x00, 0x00
461};
462
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300463
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800464static const unsigned char saa7115_init_misc[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300465 R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300466 R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 0x01,
467 R_84_I_PORT_SIGNAL_DEF, 0x20,
468 R_85_I_PORT_SIGNAL_POLAR, 0x21,
469 R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT, 0xc5,
470 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800471
472 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300473 R_A0_A_HORIZ_PRESCALING, 0x01,
474 R_A1_A_ACCUMULATION_LENGTH, 0x00,
475 R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800476
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300477 /* Configure controls at nominal value*/
478 R_A4_A_LUMA_BRIGHTNESS_CNTL, 0x80,
479 R_A5_A_LUMA_CONTRAST_CNTL, 0x40,
480 R_A6_A_CHROMA_SATURATION_CNTL, 0x40,
481
482 /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
483 R_A8_A_HORIZ_LUMA_SCALING_INC, 0x00,
484 R_A9_A_HORIZ_LUMA_SCALING_INC_MSB, 0x02,
485
486 R_AA_A_HORIZ_LUMA_PHASE_OFF, 0x00,
487
488 /* must be horiz lum scaling / 2 */
489 R_AC_A_HORIZ_CHROMA_SCALING_INC, 0x00,
490 R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB, 0x01,
491
492 /* must be offset luma / 2 */
493 R_AE_A_HORIZ_CHROMA_PHASE_OFF, 0x00,
494
495 R_B0_A_VERT_LUMA_SCALING_INC, 0x00,
496 R_B1_A_VERT_LUMA_SCALING_INC_MSB, 0x04,
497
498 R_B2_A_VERT_CHROMA_SCALING_INC, 0x00,
499 R_B3_A_VERT_CHROMA_SCALING_INC_MSB, 0x04,
500
501 R_B4_A_VERT_SCALING_MODE_CNTL, 0x01,
502
503 R_B8_A_VERT_CHROMA_PHASE_OFF_00, 0x00,
504 R_B9_A_VERT_CHROMA_PHASE_OFF_01, 0x00,
505 R_BA_A_VERT_CHROMA_PHASE_OFF_10, 0x00,
506 R_BB_A_VERT_CHROMA_PHASE_OFF_11, 0x00,
507
508 R_BC_A_VERT_LUMA_PHASE_OFF_00, 0x00,
509 R_BD_A_VERT_LUMA_PHASE_OFF_01, 0x00,
510 R_BE_A_VERT_LUMA_PHASE_OFF_10, 0x00,
511 R_BF_A_VERT_LUMA_PHASE_OFF_11, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800512
513 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300514 R_D0_B_HORIZ_PRESCALING, 0x01,
515 R_D1_B_ACCUMULATION_LENGTH, 0x00,
516 R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800517
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300518 /* Configure controls at nominal value*/
519 R_D4_B_LUMA_BRIGHTNESS_CNTL, 0x80,
520 R_D5_B_LUMA_CONTRAST_CNTL, 0x40,
521 R_D6_B_CHROMA_SATURATION_CNTL, 0x40,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800522
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300523 /* hor lum scaling 0x0400 = 1 */
524 R_D8_B_HORIZ_LUMA_SCALING_INC, 0x00,
525 R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, 0x04,
526
527 R_DA_B_HORIZ_LUMA_PHASE_OFF, 0x00,
528
529 /* must be hor lum scaling / 2 */
530 R_DC_B_HORIZ_CHROMA_SCALING, 0x00,
531 R_DD_B_HORIZ_CHROMA_SCALING_MSB, 0x02,
532
533 /* must be offset luma / 2 */
534 R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA, 0x00,
535
536 R_E0_B_VERT_LUMA_SCALING_INC, 0x00,
537 R_E1_B_VERT_LUMA_SCALING_INC_MSB, 0x04,
538
539 R_E2_B_VERT_CHROMA_SCALING_INC, 0x00,
540 R_E3_B_VERT_CHROMA_SCALING_INC_MSB, 0x04,
541
542 R_E4_B_VERT_SCALING_MODE_CNTL, 0x01,
543
544 R_E8_B_VERT_CHROMA_PHASE_OFF_00, 0x00,
545 R_E9_B_VERT_CHROMA_PHASE_OFF_01, 0x00,
546 R_EA_B_VERT_CHROMA_PHASE_OFF_10, 0x00,
547 R_EB_B_VERT_CHROMA_PHASE_OFF_11, 0x00,
548
549 R_EC_B_VERT_LUMA_PHASE_OFF_00, 0x00,
550 R_ED_B_VERT_LUMA_PHASE_OFF_01, 0x00,
551 R_EE_B_VERT_LUMA_PHASE_OFF_10, 0x00,
552 R_EF_B_VERT_LUMA_PHASE_OFF_11, 0x00,
553
554 R_F2_NOMINAL_PLL2_DTO, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */
555 R_F3_PLL_INCREMENT, 0x46,
556 R_F4_PLL2_STATUS, 0x00,
557 R_F7_PULSE_A_POS_MSB, 0x4b, /* not the recommended settings! */
558 R_F8_PULSE_B_POS, 0x00,
559 R_F9_PULSE_B_POS_MSB, 0x4b,
560 R_FA_PULSE_C_POS, 0x00,
561 R_FB_PULSE_C_POS_MSB, 0x4b,
562
563 /* PLL2 lock detection settings: 71 lines 50% phase error */
564 R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES, 0x88,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800565
566 /* Turn off VBI */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300567 R_40_SLICER_CNTL_1, 0x20, /* No framing code errors allowed. */
568 R_41_LCR_BASE, 0xff,
569 R_41_LCR_BASE+1, 0xff,
570 R_41_LCR_BASE+2, 0xff,
571 R_41_LCR_BASE+3, 0xff,
572 R_41_LCR_BASE+4, 0xff,
573 R_41_LCR_BASE+5, 0xff,
574 R_41_LCR_BASE+6, 0xff,
575 R_41_LCR_BASE+7, 0xff,
576 R_41_LCR_BASE+8, 0xff,
577 R_41_LCR_BASE+9, 0xff,
578 R_41_LCR_BASE+10, 0xff,
579 R_41_LCR_BASE+11, 0xff,
580 R_41_LCR_BASE+12, 0xff,
581 R_41_LCR_BASE+13, 0xff,
582 R_41_LCR_BASE+14, 0xff,
583 R_41_LCR_BASE+15, 0xff,
584 R_41_LCR_BASE+16, 0xff,
585 R_41_LCR_BASE+17, 0xff,
586 R_41_LCR_BASE+18, 0xff,
587 R_41_LCR_BASE+19, 0xff,
588 R_41_LCR_BASE+20, 0xff,
589 R_41_LCR_BASE+21, 0xff,
590 R_41_LCR_BASE+22, 0xff,
591 R_58_PROGRAM_FRAMING_CODE, 0x40,
592 R_59_H_OFF_FOR_SLICER, 0x47,
593 R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF, 0x83,
594 R_5D_DID, 0xbd,
595 R_5E_SDID, 0x35,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800596
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300597 R_02_INPUT_CNTL_1, 0x84, /* input tuner -> input 4, amplifier active */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800598
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300599 R_80_GLOBAL_CNTL_1, 0x20, /* enable task B */
600 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
601 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800602 0x00, 0x00
603};
604
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -0300605static int saa711x_odd_parity(u8 c)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800606{
607 c ^= (c >> 4);
608 c ^= (c >> 2);
609 c ^= (c >> 1);
610
611 return c & 1;
612}
613
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300614static int saa711x_decode_vps(u8 *dst, u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800615{
616 static const u8 biphase_tbl[] = {
617 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
618 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
619 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
620 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
621 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
622 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
623 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
624 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
625 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
626 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
627 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
628 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
629 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
630 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
631 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
632 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
633 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
634 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
635 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
636 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
637 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
638 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
639 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
640 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
641 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
642 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
643 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
644 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
645 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
646 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
647 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
648 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
649 };
650 int i;
651 u8 c, err = 0;
652
653 for (i = 0; i < 2 * 13; i += 2) {
654 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
655 c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
656 dst[i / 2] = c;
657 }
658 return err & 0xf0;
659}
660
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300661static int saa711x_decode_wss(u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800662{
663 static const int wss_bits[8] = {
664 0, 0, 0, 1, 0, 1, 1, 1
665 };
666 unsigned char parity;
667 int wss = 0;
668 int i;
669
670 for (i = 0; i < 16; i++) {
671 int b1 = wss_bits[p[i] & 7];
672 int b2 = wss_bits[(p[i] >> 3) & 7];
673
674 if (b1 == b2)
675 return -1;
676 wss |= b2 << i;
677 }
678 parity = wss & 15;
679 parity ^= parity >> 2;
680 parity ^= parity >> 1;
681
682 if (!(parity & 1))
683 return -1;
684
685 return wss;
686}
687
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300688static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800689{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300690 struct saa711x_state *state = to_state(sd);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200691 u32 acpf;
692 u32 acni;
693 u32 hz;
694 u64 f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300695 u8 acc = 0; /* reg 0x3a, audio clock control */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800696
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300697 /* Checks for chips that don't have audio clock (saa7111, saa7113) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300698 if (!saa711x_has_reg(state->ident, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300699 return 0;
700
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300701 v4l2_dbg(1, debug, sd, "set audio clock freq: %d\n", freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200702
703 /* sanity check */
704 if (freq < 32000 || freq > 48000)
705 return -EINVAL;
706
707 /* hz is the refresh rate times 100 */
708 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
709 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
710 acpf = (25600 * freq) / hz;
711 /* acni = (256 * freq * 2^23) / crystal_frequency =
712 (freq * 2^(8+23)) / crystal_frequency =
Hans Verkuilb7f82922006-04-02 12:50:42 -0300713 (freq << 31) / crystal_frequency */
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200714 f = freq;
715 f = f << 31;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300716 do_div(f, state->crystal_freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200717 acni = f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300718 if (state->ucgc) {
719 acpf = acpf * state->cgcdiv / 16;
720 acni = acni * state->cgcdiv / 16;
721 acc = 0x80;
722 if (state->cgcdiv == 3)
723 acc |= 0x40;
724 }
725 if (state->apll)
726 acc |= 0x08;
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200727
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300728 saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
729 saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10);
730 saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300731
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300732 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
733 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300734 (acpf >> 8) & 0xff);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300735 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300736 (acpf >> 16) & 0x03);
737
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300738 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
739 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
740 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800741 state->audclk_freq = freq;
742 return 0;
743}
744
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300745static int saa711x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800746{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300747 struct saa711x_state *state = to_state(sd);
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;
Hans Verkuil3faeeae2006-01-09 15:25:44 -0200789
790 default:
791 return -EINVAL;
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800792 }
793
794 return 0;
795}
796
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300797static int saa711x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800798{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300799 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800800
801 switch (ctrl->id) {
802 case V4L2_CID_BRIGHTNESS:
803 ctrl->value = state->bright;
804 break;
805 case V4L2_CID_CONTRAST:
806 ctrl->value = state->contrast;
807 break;
808 case V4L2_CID_SATURATION:
809 ctrl->value = state->sat;
810 break;
811 case V4L2_CID_HUE:
812 ctrl->value = state->hue;
813 break;
814 default:
815 return -EINVAL;
816 }
817
818 return 0;
819}
820
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300821static int saa711x_set_size(struct v4l2_subdev *sd, int width, int height)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300822{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300823 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300824 int HPSC, HFSC;
825 int VSCY;
826 int res;
827 int is_50hz = state->std & V4L2_STD_625_50;
828 int Vsrc = is_50hz ? 576 : 480;
829
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300830 v4l2_dbg(1, debug, sd, "decoder set size to %ix%i\n", width, height);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300831
832 /* FIXME need better bounds checking here */
833 if ((width < 1) || (width > 1440))
834 return -EINVAL;
835 if ((height < 1) || (height > Vsrc))
836 return -EINVAL;
837
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300838 if (!saa711x_has_reg(state->ident, R_D0_B_HORIZ_PRESCALING)) {
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300839 /* Decoder only supports 720 columns and 480 or 576 lines */
840 if (width != 720)
841 return -EINVAL;
842 if (height != Vsrc)
843 return -EINVAL;
844 }
845
846 state->width = width;
847 state->height = height;
848
849 if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
850 return 0;
851
852 /* probably have a valid size, let's set it */
853 /* Set output width/height */
854 /* width */
855
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300856 saa711x_write(sd, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300857 (u8) (width & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300858 saa711x_write(sd, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300859 (u8) ((width >> 8) & 0xff));
860
861 /* Vertical Scaling uses height/2 */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300862 res = height / 2;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300863
864 /* On 60Hz, it is using a higher Vertical Output Size */
865 if (!is_50hz)
Hans Verkuild0d30c02006-11-25 09:45:50 -0300866 res += (VRES_60HZ - 480) >> 1;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300867
868 /* height */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300869 saa711x_write(sd, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300870 (u8) (res & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300871 saa711x_write(sd, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300872 (u8) ((res >> 8) & 0xff));
873
874 /* Scaling settings */
875 /* Hprescaler is floor(inres/outres) */
876 HPSC = (int)(720 / width);
877 /* 0 is not allowed (div. by zero) */
878 HPSC = HPSC ? HPSC : 1;
879 HFSC = (int)((1024 * 720) / (HPSC * width));
880 /* FIXME hardcodes to "Task B"
881 * write H prescaler integer */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300882 saa711x_write(sd, R_D0_B_HORIZ_PRESCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300883 (u8) (HPSC & 0x3f));
884
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300885 v4l2_dbg(1, debug, sd, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300886 /* write H fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300887 saa711x_write(sd, R_D8_B_HORIZ_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300888 (u8) (HFSC & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300889 saa711x_write(sd, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300890 (u8) ((HFSC >> 8) & 0xff));
891 /* write H fine-scaling (chrominance)
892 * must be lum/2, so i'll just bitshift :) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300893 saa711x_write(sd, R_DC_B_HORIZ_CHROMA_SCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300894 (u8) ((HFSC >> 1) & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300895 saa711x_write(sd, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300896 (u8) ((HFSC >> 9) & 0xff));
897
898 VSCY = (int)((1024 * Vsrc) / height);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300899 v4l2_dbg(1, debug, sd, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300900
901 /* Correct Contrast and Luminance */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300902 saa711x_write(sd, R_D5_B_LUMA_CONTRAST_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300903 (u8) (64 * 1024 / VSCY));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300904 saa711x_write(sd, R_D6_B_CHROMA_SATURATION_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300905 (u8) (64 * 1024 / VSCY));
906
907 /* write V fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300908 saa711x_write(sd, R_E0_B_VERT_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300909 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300910 saa711x_write(sd, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300911 (u8) ((VSCY >> 8) & 0xff));
912 /* write V fine-scaling (chrominance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300913 saa711x_write(sd, R_E2_B_VERT_CHROMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300914 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300915 saa711x_write(sd, R_E3_B_VERT_CHROMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300916 (u8) ((VSCY >> 8) & 0xff));
917
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300918 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300919
920 /* Activates task "B" */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300921 saa711x_write(sd, R_80_GLOBAL_CNTL_1,
922 saa711x_read(sd, R_80_GLOBAL_CNTL_1) | 0x20);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300923
924 return 0;
925}
926
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300927static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800928{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300929 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800930
Hans Verkuil30b54d52006-01-09 15:25:43 -0200931 /* Prevent unnecessary standard changes. During a standard
932 change the I-Port is temporarily disabled. Any devices
933 reading from that port can get confused.
934 Note that VIDIOC_S_STD is also used to switch from
935 radio to TV mode, so if a VIDIOC_S_STD is broadcast to
936 all I2C devices then you do not want to have an unwanted
937 side-effect here. */
938 if (std == state->std)
939 return;
940
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300941 state->std = std;
942
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800943 // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
944 if (std & V4L2_STD_525_60) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300945 v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n");
946 saa711x_writeregs(sd, saa7115_cfg_60hz_video);
947 saa711x_set_size(sd, 720, 480);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800948 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300949 v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n");
950 saa711x_writeregs(sd, saa7115_cfg_50hz_video);
951 saa711x_set_size(sd, 720, 576);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800952 }
953
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300954 /* Register 0E - Bits D6-D4 on NO-AUTO mode
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300955 (SAA7111 and SAA7113 doesn't have auto mode)
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300956 50 Hz / 625 lines 60 Hz / 525 lines
957 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz)
958 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz)
959 010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz)
960 011 NTSC N (3.58MHz) PAL M (3.58MHz)
961 100 reserved NTSC-Japan (3.58MHz)
962 */
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300963 if (state->ident == V4L2_IDENT_SAA7111 ||
964 state->ident == V4L2_IDENT_SAA7113) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300965 u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300966
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300967 if (std == V4L2_STD_PAL_M) {
Hans Verkuil01342352006-03-25 08:19:47 -0300968 reg |= 0x30;
Hans Verkuile0028022008-04-22 14:45:51 -0300969 } else if (std == V4L2_STD_PAL_Nc) {
Hans Verkuil01342352006-03-25 08:19:47 -0300970 reg |= 0x20;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300971 } else if (std == V4L2_STD_PAL_60) {
Hans Verkuil01342352006-03-25 08:19:47 -0300972 reg |= 0x10;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300973 } else if (std == V4L2_STD_NTSC_M_JP) {
Hans Verkuil01342352006-03-25 08:19:47 -0300974 reg |= 0x40;
Mauro Carvalho Chehaba9aaec42007-03-13 13:41:49 -0300975 } else if (std & V4L2_STD_SECAM) {
Pádraig Bradyfc2fa312006-10-09 08:02:17 -0300976 reg |= 0x50;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300977 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300978 saa711x_write(sd, R_0E_CHROMA_CNTL_1, reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300979 } else {
980 /* restart task B if needed */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300981 int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300982
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300983 if (taskb && state->ident == V4L2_IDENT_SAA7114) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300984 saa711x_writeregs(sd, saa7115_cfg_vbi_on);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300985 }
986
987 /* switch audio mode too! */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300988 saa711x_s_clock_freq(sd, state->audclk_freq);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300989 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800990}
991
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800992/* setup the sliced VBI lcr registers according to the sliced VBI format */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300993static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800994{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300995 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800996 int is_50hz = (state->std & V4L2_STD_625_50);
997 u8 lcr[24];
998 int i, x;
999
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001000#if 1
1001 /* saa7113/7114/7118 VBI support are experimental */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001002 if (!saa711x_has_reg(state->ident, R_41_LCR_BASE))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001003 return;
1004
1005#else
1006 /* SAA7113 and SAA7118 also should support VBI - Need testing */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001007 if (state->ident != V4L2_IDENT_SAA7115)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001008 return;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001009#endif
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001010
1011 for (i = 0; i <= 23; i++)
1012 lcr[i] = 0xff;
1013
Hans Verkuila8b86432008-10-04 08:05:30 -03001014 if (fmt == NULL) {
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001015 /* raw VBI */
1016 if (is_50hz)
1017 for (i = 6; i <= 23; i++)
1018 lcr[i] = 0xdd;
1019 else
1020 for (i = 10; i <= 21; i++)
1021 lcr[i] = 0xdd;
1022 } else {
1023 /* sliced VBI */
1024 /* first clear lines that cannot be captured */
1025 if (is_50hz) {
1026 for (i = 0; i <= 5; i++)
1027 fmt->service_lines[0][i] =
1028 fmt->service_lines[1][i] = 0;
1029 }
1030 else {
1031 for (i = 0; i <= 9; i++)
1032 fmt->service_lines[0][i] =
1033 fmt->service_lines[1][i] = 0;
1034 for (i = 22; i <= 23; i++)
1035 fmt->service_lines[0][i] =
1036 fmt->service_lines[1][i] = 0;
1037 }
1038
1039 /* Now set the lcr values according to the specified service */
1040 for (i = 6; i <= 23; i++) {
1041 lcr[i] = 0;
1042 for (x = 0; x <= 1; x++) {
1043 switch (fmt->service_lines[1-x][i]) {
1044 case 0:
1045 lcr[i] |= 0xf << (4 * x);
1046 break;
Hans Verkuil9bc74002006-03-29 18:02:51 -03001047 case V4L2_SLICED_TELETEXT_B:
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001048 lcr[i] |= 1 << (4 * x);
1049 break;
1050 case V4L2_SLICED_CAPTION_525:
1051 lcr[i] |= 4 << (4 * x);
1052 break;
1053 case V4L2_SLICED_WSS_625:
1054 lcr[i] |= 5 << (4 * x);
1055 break;
1056 case V4L2_SLICED_VPS:
1057 lcr[i] |= 7 << (4 * x);
1058 break;
1059 }
1060 }
1061 }
1062 }
1063
1064 /* write the lcr registers */
1065 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001066 saa711x_write(sd, i - 2 + R_41_LCR_BASE, lcr[i]);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001067 }
1068
1069 /* enable/disable raw VBI capturing */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001070 saa711x_writeregs(sd, fmt == NULL ?
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001071 saa7115_cfg_vbi_on :
1072 saa7115_cfg_vbi_off);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001073}
1074
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001075static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001076{
1077 static u16 lcr2vbi[] = {
Hans Verkuil9bc74002006-03-29 18:02:51 -03001078 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001079 0, V4L2_SLICED_CAPTION_525, /* 4 */
1080 V4L2_SLICED_WSS_625, 0, /* 5 */
1081 V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
1082 0, 0, 0, 0
1083 };
1084 struct v4l2_sliced_vbi_format *sliced = &fmt->fmt.sliced;
1085 int i;
1086
1087 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
1088 return -EINVAL;
1089 memset(sliced, 0, sizeof(*sliced));
1090 /* done if using raw VBI */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001091 if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001092 return 0;
1093 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001094 u8 v = saa711x_read(sd, i - 2 + R_41_LCR_BASE);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001095
1096 sliced->service_lines[0][i] = lcr2vbi[v >> 4];
1097 sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
1098 sliced->service_set |=
1099 sliced->service_lines[0][i] | sliced->service_lines[1][i];
1100 }
1101 return 0;
1102}
1103
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001104static int saa711x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
Mauro Carvalho Chehab59ba9152006-08-30 05:34:36 -03001105{
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001106 if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001107 saa711x_set_lcr(sd, &fmt->fmt.sliced);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001108 return 0;
1109 }
Hans Verkuila8b86432008-10-04 08:05:30 -03001110 if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001111 saa711x_set_lcr(sd, NULL);
Hans Verkuila8b86432008-10-04 08:05:30 -03001112 return 0;
1113 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001114 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1115 return -EINVAL;
1116
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001117 return saa711x_set_size(sd, fmt->fmt.pix.width, fmt->fmt.pix.height);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001118}
1119
1120/* Decode the sliced VBI data stream as created by the saa7115.
1121 The format is described in the saa7115 datasheet in Tables 25 and 26
1122 and in Figure 33.
1123 The current implementation uses SAV/EAV codes and not the ancillary data
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001124 headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001125 code. */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001126static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001127{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001128 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001129 static const char vbi_no_data_pattern[] = {
1130 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
1131 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001132 u8 *p = vbi->p;
1133 u32 wss;
1134 int id1, id2; /* the ID1 and ID2 bytes from the internal header */
1135
1136 vbi->type = 0; /* mark result as a failure */
1137 id1 = p[2];
1138 id2 = p[3];
1139 /* Note: the field bit is inverted for 60 Hz video */
1140 if (state->std & V4L2_STD_525_60)
1141 id1 ^= 0x40;
1142
1143 /* Skip internal header, p now points to the start of the payload */
1144 p += 4;
1145 vbi->p = p;
1146
1147 /* calculate field and line number of the VBI packet (1-23) */
1148 vbi->is_second_field = ((id1 & 0x40) != 0);
1149 vbi->line = (id1 & 0x3f) << 3;
1150 vbi->line |= (id2 & 0x70) >> 4;
1151
1152 /* Obtain data type */
1153 id2 &= 0xf;
1154
1155 /* If the VBI slicer does not detect any signal it will fill up
1156 the payload buffer with 0xa0 bytes. */
1157 if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001158 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001159
1160 /* decode payloads */
1161 switch (id2) {
1162 case 1:
Hans Verkuil9bc74002006-03-29 18:02:51 -03001163 vbi->type = V4L2_SLICED_TELETEXT_B;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001164 break;
1165 case 4:
Mauro Carvalho Chehab59ba9152006-08-30 05:34:36 -03001166 if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001167 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001168 vbi->type = V4L2_SLICED_CAPTION_525;
1169 break;
1170 case 5:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001171 wss = saa711x_decode_wss(p);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001172 if (wss == -1)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001173 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001174 p[0] = wss & 0xff;
1175 p[1] = wss >> 8;
1176 vbi->type = V4L2_SLICED_WSS_625;
1177 break;
1178 case 7:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001179 if (saa711x_decode_vps(p, p) != 0)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001180 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001181 vbi->type = V4L2_SLICED_VPS;
1182 break;
1183 default:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001184 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001185 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001186 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001187}
1188
1189/* ============ SAA7115 AUDIO settings (end) ============= */
1190
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001191static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001192{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001193 struct saa711x_state *state = to_state(sd);
1194 int status;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001195
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001196 if (state->radio)
1197 return 0;
1198 status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001199
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001200 v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status);
1201 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1202 return 0;
1203}
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001204
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001205static int saa711x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
1206{
1207 switch (qc->id) {
1208 case V4L2_CID_BRIGHTNESS:
Hans Verkuil10afbef2009-02-21 18:47:24 -03001209 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001210 case V4L2_CID_CONTRAST:
1211 case V4L2_CID_SATURATION:
Hans Verkuil10afbef2009-02-21 18:47:24 -03001212 return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001213 case V4L2_CID_HUE:
Hans Verkuil10afbef2009-02-21 18:47:24 -03001214 return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001215 default:
1216 return -EINVAL;
1217 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001218}
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001219
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001220static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1221{
1222 struct saa711x_state *state = to_state(sd);
1223
1224 state->radio = 0;
1225 saa711x_set_v4lstd(sd, std);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001226 return 0;
1227}
1228
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001229static int saa711x_s_radio(struct v4l2_subdev *sd)
1230{
1231 struct saa711x_state *state = to_state(sd);
1232
1233 state->radio = 1;
1234 return 0;
1235}
1236
1237static int saa711x_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
1238{
1239 struct saa711x_state *state = to_state(sd);
1240 u32 input = route->input;
1241 u8 mask = (state->ident == V4L2_IDENT_SAA7111) ? 0xf8 : 0xf0;
1242
1243 v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n", route->input, route->output);
1244 /* saa7111/3 does not have these inputs */
1245 if ((state->ident == V4L2_IDENT_SAA7113 ||
1246 state->ident == V4L2_IDENT_SAA7111) &&
1247 (route->input == SAA7115_COMPOSITE4 ||
1248 route->input == SAA7115_COMPOSITE5)) {
1249 return -EINVAL;
1250 }
1251 if (route->input > SAA7115_SVIDEO3)
1252 return -EINVAL;
1253 if (route->output > SAA7115_IPORT_ON)
1254 return -EINVAL;
1255 if (state->input == route->input && state->output == route->output)
1256 return 0;
1257 v4l2_dbg(1, debug, sd, "now setting %s input %s output\n",
1258 (route->input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite",
1259 (route->output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
1260 state->input = route->input;
1261
1262 /* saa7111 has slightly different input numbering */
1263 if (state->ident == V4L2_IDENT_SAA7111) {
1264 if (input >= SAA7115_COMPOSITE4)
1265 input -= 2;
1266 /* saa7111 specific */
1267 saa711x_write(sd, R_10_CHROMA_CNTL_2,
1268 (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) |
1269 ((route->output & 0xc0) ^ 0x40));
1270 saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL,
1271 (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
1272 ((route->output & 2) ? 0x0a : 0));
1273 }
1274
1275 /* select mode */
1276 saa711x_write(sd, R_02_INPUT_CNTL_1,
1277 (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) |
1278 input);
1279
1280 /* bypass chrominance trap for S-Video modes */
1281 saa711x_write(sd, R_09_LUMA_CNTL,
1282 (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) |
1283 (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
1284
1285 state->output = route->output;
1286 if (state->ident == V4L2_IDENT_SAA7114 ||
1287 state->ident == V4L2_IDENT_SAA7115) {
1288 saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
1289 (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
1290 (state->output & 0x01));
1291 }
1292 return 0;
1293}
1294
1295static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val)
1296{
1297 struct saa711x_state *state = to_state(sd);
1298
1299 if (state->ident != V4L2_IDENT_SAA7111)
1300 return -EINVAL;
1301 saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) |
1302 (val ? 0x80 : 0));
1303 return 0;
1304}
1305
1306static int saa711x_s_stream(struct v4l2_subdev *sd, int enable)
1307{
1308 struct saa711x_state *state = to_state(sd);
1309
1310 v4l2_dbg(1, debug, sd, "%s output\n",
1311 enable ? "enable" : "disable");
1312
Hans Verkuil674a3232009-02-18 12:22:16 -03001313 if (state->enable == enable)
1314 return 0;
1315 state->enable = enable;
1316 if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED))
1317 return 0;
1318 saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001319 return 0;
1320}
1321
1322static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, struct v4l2_crystal_freq *freq)
1323{
1324 struct saa711x_state *state = to_state(sd);
1325
1326 if (freq->freq != SAA7115_FREQ_32_11_MHZ &&
1327 freq->freq != SAA7115_FREQ_24_576_MHZ)
1328 return -EINVAL;
1329 state->crystal_freq = freq->freq;
1330 state->cgcdiv = (freq->flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
1331 state->ucgc = (freq->flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;
1332 state->apll = (freq->flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;
1333 saa711x_s_clock_freq(sd, state->audclk_freq);
1334 return 0;
1335}
1336
1337static int saa711x_reset(struct v4l2_subdev *sd, u32 val)
1338{
1339 v4l2_dbg(1, debug, sd, "decoder RESET\n");
1340 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
1341 return 0;
1342}
1343
1344static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data)
1345{
1346 /* Note: the internal field ID is inverted for NTSC,
1347 so data->field 0 maps to the saa7115 even field,
1348 whereas for PAL it maps to the saa7115 odd field. */
1349 switch (data->id) {
1350 case V4L2_SLICED_WSS_625:
1351 if (saa711x_read(sd, 0x6b) & 0xc0)
1352 return -EIO;
1353 data->data[0] = saa711x_read(sd, 0x6c);
1354 data->data[1] = saa711x_read(sd, 0x6d);
1355 return 0;
1356 case V4L2_SLICED_CAPTION_525:
1357 if (data->field == 0) {
1358 /* CC */
1359 if (saa711x_read(sd, 0x66) & 0x30)
1360 return -EIO;
1361 data->data[0] = saa711x_read(sd, 0x69);
1362 data->data[1] = saa711x_read(sd, 0x6a);
1363 return 0;
1364 }
1365 /* XDS */
1366 if (saa711x_read(sd, 0x66) & 0xc0)
1367 return -EIO;
1368 data->data[0] = saa711x_read(sd, 0x67);
1369 data->data[1] = saa711x_read(sd, 0x68);
1370 return 0;
1371 default:
1372 return -EINVAL;
1373 }
1374}
1375
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001376static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
1377{
1378 struct saa711x_state *state = to_state(sd);
1379 int reg1e;
1380
1381 *std = V4L2_STD_ALL;
1382 if (state->ident != V4L2_IDENT_SAA7115)
1383 return 0;
1384 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1385
1386 switch (reg1e & 0x03) {
1387 case 1:
1388 *std = V4L2_STD_NTSC;
1389 break;
1390 case 2:
1391 *std = V4L2_STD_PAL;
1392 break;
1393 case 3:
1394 *std = V4L2_STD_SECAM;
1395 break;
1396 default:
1397 break;
1398 }
1399 return 0;
1400}
1401
1402static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status)
1403{
1404 struct saa711x_state *state = to_state(sd);
1405 int reg1e = 0x80;
1406 int reg1f;
1407
1408 *status = V4L2_IN_ST_NO_SIGNAL;
1409 if (state->ident == V4L2_IDENT_SAA7115)
1410 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1411 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1412 if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80)
1413 *status = 0;
1414 return 0;
1415}
1416
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001417#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001418static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001419{
1420 struct i2c_client *client = v4l2_get_subdevdata(sd);
1421
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001422 if (!v4l2_chip_match_i2c_client(client, &reg->match))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001423 return -EINVAL;
1424 if (!capable(CAP_SYS_ADMIN))
1425 return -EPERM;
1426 reg->val = saa711x_read(sd, reg->reg & 0xff);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001427 reg->size = 1;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001428 return 0;
1429}
1430
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001431static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001432{
1433 struct i2c_client *client = v4l2_get_subdevdata(sd);
1434
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001435 if (!v4l2_chip_match_i2c_client(client, &reg->match))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001436 return -EINVAL;
1437 if (!capable(CAP_SYS_ADMIN))
1438 return -EPERM;
1439 saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff);
1440 return 0;
1441}
1442#endif
1443
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001444static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001445{
1446 struct saa711x_state *state = to_state(sd);
1447 struct i2c_client *client = v4l2_get_subdevdata(sd);
1448
1449 return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0);
1450}
1451
1452static int saa711x_log_status(struct v4l2_subdev *sd)
1453{
1454 struct saa711x_state *state = to_state(sd);
1455 int reg1e, reg1f;
1456 int signalOk;
1457 int vcr;
1458
1459 v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq);
1460 if (state->ident != V4L2_IDENT_SAA7115) {
1461 /* status for the saa7114 */
1462 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1463 signalOk = (reg1f & 0xc1) == 0x81;
1464 v4l2_info(sd, "Video signal: %s\n", signalOk ? "ok" : "bad");
1465 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1466 return 0;
1467 }
1468
1469 /* status for the saa7115 */
1470 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1471 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1472
1473 signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
1474 vcr = !(reg1f & 0x10);
1475
1476 if (state->input >= 6)
1477 v4l2_info(sd, "Input: S-Video %d\n", state->input - 6);
1478 else
1479 v4l2_info(sd, "Input: Composite %d\n", state->input);
1480 v4l2_info(sd, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
1481 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1482
1483 switch (reg1e & 0x03) {
1484 case 1:
1485 v4l2_info(sd, "Detected format: NTSC\n");
1486 break;
1487 case 2:
1488 v4l2_info(sd, "Detected format: PAL\n");
1489 break;
1490 case 3:
1491 v4l2_info(sd, "Detected format: SECAM\n");
1492 break;
1493 default:
1494 v4l2_info(sd, "Detected format: BW/No color\n");
1495 break;
1496 }
1497 v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height);
1498 return 0;
1499}
1500
1501static int saa711x_command(struct i2c_client *client, unsigned cmd, void *arg)
1502{
1503 return v4l2_subdev_command(i2c_get_clientdata(client), cmd, arg);
1504}
1505
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001506/* ----------------------------------------------------------------------- */
1507
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001508static const struct v4l2_subdev_core_ops saa711x_core_ops = {
1509 .log_status = saa711x_log_status,
1510 .g_chip_ident = saa711x_g_chip_ident,
1511 .g_ctrl = saa711x_g_ctrl,
1512 .s_ctrl = saa711x_s_ctrl,
1513 .queryctrl = saa711x_queryctrl,
1514 .reset = saa711x_reset,
1515 .s_gpio = saa711x_s_gpio,
1516#ifdef CONFIG_VIDEO_ADV_DEBUG
1517 .g_register = saa711x_g_register,
1518 .s_register = saa711x_s_register,
1519#endif
1520};
1521
1522static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = {
1523 .s_std = saa711x_s_std,
1524 .s_radio = saa711x_s_radio,
1525 .g_tuner = saa711x_g_tuner,
1526};
1527
1528static const struct v4l2_subdev_audio_ops saa711x_audio_ops = {
1529 .s_clock_freq = saa711x_s_clock_freq,
1530};
1531
1532static const struct v4l2_subdev_video_ops saa711x_video_ops = {
1533 .s_routing = saa711x_s_routing,
1534 .s_crystal_freq = saa711x_s_crystal_freq,
1535 .g_fmt = saa711x_g_fmt,
1536 .s_fmt = saa711x_s_fmt,
1537 .g_vbi_data = saa711x_g_vbi_data,
1538 .decode_vbi_line = saa711x_decode_vbi_line,
1539 .s_stream = saa711x_s_stream,
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001540 .querystd = saa711x_querystd,
1541 .g_input_status = saa711x_g_input_status,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001542};
1543
1544static const struct v4l2_subdev_ops saa711x_ops = {
1545 .core = &saa711x_core_ops,
1546 .tuner = &saa711x_tuner_ops,
1547 .audio = &saa711x_audio_ops,
1548 .video = &saa711x_video_ops,
1549};
1550
1551/* ----------------------------------------------------------------------- */
1552
1553static int saa711x_probe(struct i2c_client *client,
Jean Delvared2653e92008-04-29 23:11:39 +02001554 const struct i2c_device_id *id)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001555{
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001556 struct saa711x_state *state;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001557 struct v4l2_subdev *sd;
Mauro Carvalho Chehab236f16d2006-08-28 08:25:29 -03001558 int i;
1559 char name[17];
Jean Delvareaf294862008-05-18 20:49:40 +02001560 char chip_id;
1561 int autodetect = !id || id->driver_data == 1;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001562
1563 /* Check if the adapter supports the needed features */
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001564 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
Hans Verkuil188f3452007-09-16 10:47:15 -03001565 return -EIO;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001566
Hans Verkuild0d30c02006-11-25 09:45:50 -03001567 for (i = 0; i < 0x0f; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001568 i2c_smbus_write_byte_data(client, 0, i);
1569 name[i] = (i2c_smbus_read_byte_data(client, 0) & 0x0f) + '0';
Hans Verkuild0d30c02006-11-25 09:45:50 -03001570 if (name[i] > '9')
1571 name[i] += 'a' - '9' - 1;
Mauro Carvalho Chehab236f16d2006-08-28 08:25:29 -03001572 }
Hans Verkuild0d30c02006-11-25 09:45:50 -03001573 name[i] = '\0';
Mauro Carvalho Chehab236f16d2006-08-28 08:25:29 -03001574
Jean Delvareaf294862008-05-18 20:49:40 +02001575 chip_id = name[5];
Mauro Carvalho Chehab3e7d3e52006-09-01 18:39:05 -03001576
Hans Verkuilf7668162006-11-25 09:40:28 -03001577 /* Check whether this chip is part of the saa711x series */
1578 if (memcmp(name, "1f711", 5)) {
1579 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 -03001580 client->addr << 1, name);
Hans Verkuil188f3452007-09-16 10:47:15 -03001581 return -ENODEV;
Hans Verkuilf7668162006-11-25 09:40:28 -03001582 }
1583
Jean Delvareaf294862008-05-18 20:49:40 +02001584 /* Safety check */
1585 if (!autodetect && id->name[6] != chip_id) {
1586 v4l_warn(client, "found saa711%c while %s was expected\n",
1587 chip_id, id->name);
1588 }
1589 snprintf(client->name, sizeof(client->name), "saa711%c", chip_id);
1590 v4l_info(client, "saa711%c found (%s) @ 0x%x (%s)\n", chip_id, name,
1591 client->addr << 1, client->adapter->name);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001592
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001593 state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL);
Hans Verkuilc5bf2042008-09-03 17:12:09 -03001594 if (state == NULL)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001595 return -ENOMEM;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001596 sd = &state->sd;
1597 v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001598 state->input = -1;
Marco Schluessler4cbca182007-01-21 19:43:38 -03001599 state->output = SAA7115_IPORT_ON;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001600 state->enable = 1;
Hans Verkuil3faeeae2006-01-09 15:25:44 -02001601 state->radio = 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001602 state->bright = 128;
1603 state->contrast = 64;
1604 state->hue = 0;
1605 state->sat = 64;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001606 switch (chip_id) {
Jean Delvareaf294862008-05-18 20:49:40 +02001607 case '1':
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001608 state->ident = V4L2_IDENT_SAA7111;
1609 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001610 case '3':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001611 state->ident = V4L2_IDENT_SAA7113;
1612 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001613 case '4':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001614 state->ident = V4L2_IDENT_SAA7114;
1615 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001616 case '5':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001617 state->ident = V4L2_IDENT_SAA7115;
1618 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001619 case '8':
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001620 state->ident = V4L2_IDENT_SAA7118;
1621 break;
1622 default:
1623 state->ident = V4L2_IDENT_SAA7111;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001624 v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n");
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001625
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001626 }
1627
Hans Verkuil3578d3d2006-01-09 15:25:41 -02001628 state->audclk_freq = 48000;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001629
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001630 v4l2_dbg(1, debug, sd, "writing init values\n");
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001631
1632 /* init to 60hz/48khz */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001633 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
1634 switch (state->ident) {
1635 case V4L2_IDENT_SAA7111:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001636 saa711x_writeregs(sd, saa7111_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001637 break;
1638 case V4L2_IDENT_SAA7113:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001639 saa711x_writeregs(sd, saa7113_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001640 break;
1641 default:
Hans Verkuilb7f82922006-04-02 12:50:42 -03001642 state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001643 saa711x_writeregs(sd, saa7115_init_auto_input);
Hans Verkuilb7f82922006-04-02 12:50:42 -03001644 }
Hans Verkuil6bd6dff2008-09-06 15:26:44 -03001645 if (state->ident != V4L2_IDENT_SAA7111)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001646 saa711x_writeregs(sd, saa7115_init_misc);
1647 saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001648
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001649 v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n",
1650 saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC),
1651 saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001652 return 0;
1653}
1654
1655/* ----------------------------------------------------------------------- */
1656
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001657static int saa711x_remove(struct i2c_client *client)
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001658{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001659 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1660
1661 v4l2_device_unregister_subdev(sd);
1662 kfree(to_state(sd));
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001663 return 0;
1664}
1665
Jean Delvareaf294862008-05-18 20:49:40 +02001666static const struct i2c_device_id saa7115_id[] = {
Hans Verkuil9edd350f2008-07-17 13:22:51 -03001667 { "saa7115_auto", 1 }, /* autodetect */
Jean Delvareaf294862008-05-18 20:49:40 +02001668 { "saa7111", 0 },
1669 { "saa7113", 0 },
1670 { "saa7114", 0 },
1671 { "saa7115", 0 },
1672 { "saa7118", 0 },
1673 { }
1674};
1675MODULE_DEVICE_TABLE(i2c, saa7115_id);
1676
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001677static struct v4l2_i2c_driver_data v4l2_i2c_data = {
1678 .name = "saa7115",
1679 .driverid = I2C_DRIVERID_SAA711X,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001680 .command = saa711x_command,
1681 .probe = saa711x_probe,
1682 .remove = saa711x_remove,
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001683 .legacy_class = I2C_CLASS_TV_ANALOG | I2C_CLASS_TV_DIGITAL,
Jean Delvareaf294862008-05-18 20:49:40 +02001684 .id_table = saa7115_id,
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001685};