blob: ee963f4d01bcf770d6e9ae6b711ed41ec1ed4668 [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 Verkuile3560542010-05-24 10:00:52 -030048#include <media/v4l2-ctrls.h>
Hans Verkuil3434eb72007-04-27 12:31:08 -030049#include <media/v4l2-chip-ident.h>
Hans Verkuilef6078e2009-03-29 17:32:35 -030050#include <media/v4l2-i2c-drv.h>
Hans Verkuil1f8f5fa2006-03-25 09:20:28 -030051#include <media/saa7115.h>
Hans Verkuil3578d3d2006-01-09 15:25:41 -020052#include <asm/div64.h>
Hans Verkuile19b2fc2005-11-13 16:08:04 -080053
Mauro Carvalho Chehab97d9e802006-09-03 09:38:11 -030054#define VRES_60HZ (480+16)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -030055
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -030056MODULE_DESCRIPTION("Philips SAA7111/SAA7113/SAA7114/SAA7115/SAA7118 video decoder driver");
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -030057MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
58 "Hans Verkuil, Mauro Carvalho Chehab");
Hans Verkuile19b2fc2005-11-13 16:08:04 -080059MODULE_LICENSE("GPL");
60
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030061static int debug;
Hans Verkuilfac9e892006-01-09 15:32:40 -020062module_param(debug, bool, 0644);
Hans Verkuile19b2fc2005-11-13 16:08:04 -080063
64MODULE_PARM_DESC(debug, "Debug level (0-1)");
65
Hans Verkuile19b2fc2005-11-13 16:08:04 -080066
Mauro Carvalho Chehab66ec1192006-08-29 22:52:32 -030067struct saa711x_state {
Hans Verkuil9415f4b2008-11-29 12:55:19 -030068 struct v4l2_subdev sd;
Hans Verkuile3560542010-05-24 10:00:52 -030069 struct v4l2_ctrl_handler hdl;
70
71 struct {
72 /* chroma gain control cluster */
73 struct v4l2_ctrl *agc;
74 struct v4l2_ctrl *gain;
75 };
76
Hans Verkuile19b2fc2005-11-13 16:08:04 -080077 v4l2_std_id std;
78 int input;
Marco Schluessler4cbca182007-01-21 19:43:38 -030079 int output;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080080 int enable;
Hans Verkuil3faeeae2006-01-09 15:25:44 -020081 int radio;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -030082 int width;
83 int height;
Hans Verkuil3434eb72007-04-27 12:31:08 -030084 u32 ident;
Hans Verkuil3578d3d2006-01-09 15:25:41 -020085 u32 audclk_freq;
Hans Verkuilb7f82922006-04-02 12:50:42 -030086 u32 crystal_freq;
87 u8 ucgc;
88 u8 cgcdiv;
89 u8 apll;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080090};
91
Hans Verkuil9415f4b2008-11-29 12:55:19 -030092static inline struct saa711x_state *to_state(struct v4l2_subdev *sd)
93{
94 return container_of(sd, struct saa711x_state, sd);
95}
96
Hans Verkuile3560542010-05-24 10:00:52 -030097static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
98{
99 return &container_of(ctrl->handler, struct saa711x_state, hdl)->sd;
100}
101
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800102/* ----------------------------------------------------------------------- */
103
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300104static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800105{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300106 struct i2c_client *client = v4l2_get_subdevdata(sd);
107
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800108 return i2c_smbus_write_byte_data(client, reg, value);
109}
110
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300111/* Sanity routine to check if a register is present */
112static int saa711x_has_reg(const int id, const u8 reg)
113{
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300114 if (id == V4L2_IDENT_SAA7111)
115 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
116 (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e;
Hans Verkuil340dde82010-02-20 08:07:51 -0300117 if (id == V4L2_IDENT_SAA7111A)
118 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
119 reg != 0x14 && reg != 0x18 && reg != 0x19 &&
120 reg != 0x1d && reg != 0x1e;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300121
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300122 /* common for saa7113/4/5/8 */
123 if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f ||
124 reg == 0xa3 || reg == 0xa7 || reg == 0xab || reg == 0xaf || (reg >= 0xb5 && reg <= 0xb7) ||
125 reg == 0xd3 || reg == 0xd7 || reg == 0xdb || reg == 0xdf || (reg >= 0xe5 && reg <= 0xe7) ||
126 reg == 0x82 || (reg >= 0x89 && reg <= 0x8e)))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300127 return 0;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300128
129 switch (id) {
130 case V4L2_IDENT_SAA7113:
131 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
132 reg != 0x5d && reg < 0x63;
133 case V4L2_IDENT_SAA7114:
134 return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
135 (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
136 reg != 0x81 && reg < 0xf0;
137 case V4L2_IDENT_SAA7115:
138 return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe);
139 case V4L2_IDENT_SAA7118:
140 return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
141 (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
142 (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
143 }
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300144 return 1;
145}
146
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300147static int saa711x_writeregs(struct v4l2_subdev *sd, const unsigned char *regs)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800148{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300149 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800150 unsigned char reg, data;
151
152 while (*regs != 0x00) {
153 reg = *(regs++);
154 data = *(regs++);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300155
156 /* According with datasheets, reserved regs should be
157 filled with 0 - seems better not to touch on they */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300158 if (saa711x_has_reg(state->ident, reg)) {
159 if (saa711x_write(sd, reg, data) < 0)
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300160 return -1;
Mauro Carvalho Chehabd87edf22006-09-01 09:37:11 -0300161 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300162 v4l2_dbg(1, debug, sd, "tried to access reserved reg 0x%02x\n", reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300163 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800164 }
165 return 0;
166}
167
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300168static inline int saa711x_read(struct v4l2_subdev *sd, u8 reg)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800169{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300170 struct i2c_client *client = v4l2_get_subdevdata(sd);
171
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800172 return i2c_smbus_read_byte_data(client, reg);
173}
174
175/* ----------------------------------------------------------------------- */
176
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300177/* SAA7111 initialization table */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300178static const unsigned char saa7111_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300179 R_01_INC_DELAY, 0x00, /* reserved */
180
181 /*front end */
182 R_02_INPUT_CNTL_1, 0xd0, /* FUSE=3, GUDL=2, MODE=0 */
183 R_03_INPUT_CNTL_2, 0x23, /* HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0,
184 * GAFIX=0, GAI1=256, GAI2=256 */
185 R_04_INPUT_CNTL_3, 0x00, /* GAI1=256 */
186 R_05_INPUT_CNTL_4, 0x00, /* GAI2=256 */
187
188 /* decoder */
189 R_06_H_SYNC_START, 0xf3, /* HSB at 13(50Hz) / 17(60Hz)
190 * pixels after end of last line */
191 R_07_H_SYNC_STOP, 0xe8, /* HSS seems to be needed to
192 * work with NTSC, too */
193 R_08_SYNC_CNTL, 0xc8, /* AUFD=1, FSEL=1, EXFIL=0,
194 * VTRC=1, HPLL=0, VNOI=0 */
195 R_09_LUMA_CNTL, 0x01, /* BYPS=0, PREF=0, BPSS=0,
196 * VBLB=0, UPTCV=0, APER=1 */
197 R_0A_LUMA_BRIGHT_CNTL, 0x80,
198 R_0B_LUMA_CONTRAST_CNTL, 0x47, /* 0b - CONT=1.109 */
199 R_0C_CHROMA_SAT_CNTL, 0x40,
200 R_0D_CHROMA_HUE_CNTL, 0x00,
201 R_0E_CHROMA_CNTL_1, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0,
202 * FCTC=0, CHBW=1 */
203 R_0F_CHROMA_GAIN_CNTL, 0x00, /* reserved */
204 R_10_CHROMA_CNTL_2, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
205 R_11_MODE_DELAY_CNTL, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
206 * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
207 R_12_RT_SIGNAL_CNTL, 0x00, /* 12 - output control 2 */
208 R_13_RT_X_PORT_OUT_CNTL, 0x00, /* 13 - output control 3 */
209 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
210 R_15_VGATE_START_FID_CHG, 0x00,
211 R_16_VGATE_STOP, 0x00,
212 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
213
214 0x00, 0x00
215};
216
217/* SAA7113 init codes */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300218static const unsigned char saa7113_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300219 R_01_INC_DELAY, 0x08,
220 R_02_INPUT_CNTL_1, 0xc2,
221 R_03_INPUT_CNTL_2, 0x30,
222 R_04_INPUT_CNTL_3, 0x00,
223 R_05_INPUT_CNTL_4, 0x00,
224 R_06_H_SYNC_START, 0x89,
225 R_07_H_SYNC_STOP, 0x0d,
226 R_08_SYNC_CNTL, 0x88,
227 R_09_LUMA_CNTL, 0x01,
228 R_0A_LUMA_BRIGHT_CNTL, 0x80,
229 R_0B_LUMA_CONTRAST_CNTL, 0x47,
230 R_0C_CHROMA_SAT_CNTL, 0x40,
231 R_0D_CHROMA_HUE_CNTL, 0x00,
232 R_0E_CHROMA_CNTL_1, 0x01,
233 R_0F_CHROMA_GAIN_CNTL, 0x2a,
234 R_10_CHROMA_CNTL_2, 0x08,
235 R_11_MODE_DELAY_CNTL, 0x0c,
236 R_12_RT_SIGNAL_CNTL, 0x07,
237 R_13_RT_X_PORT_OUT_CNTL, 0x00,
238 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
239 R_15_VGATE_START_FID_CHG, 0x00,
240 R_16_VGATE_STOP, 0x00,
241 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
242
243 0x00, 0x00
244};
245
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800246/* If a value differs from the Hauppauge driver values, then the comment starts with
247 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
248 Hauppauge driver sets. */
249
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300250/* SAA7114 and SAA7115 initialization table */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800251static const unsigned char saa7115_init_auto_input[] = {
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300252 /* Front-End Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300253 R_01_INC_DELAY, 0x48, /* white peak control disabled */
254 R_03_INPUT_CNTL_2, 0x20, /* was 0x30. 0x20: long vertical blanking */
255 R_04_INPUT_CNTL_3, 0x90, /* analog gain set to 0 */
256 R_05_INPUT_CNTL_4, 0x90, /* analog gain set to 0 */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300257 /* Decoder Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300258 R_06_H_SYNC_START, 0xeb, /* horiz sync begin = -21 */
259 R_07_H_SYNC_STOP, 0xe0, /* horiz sync stop = -17 */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300260 R_09_LUMA_CNTL, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300261 R_0A_LUMA_BRIGHT_CNTL, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */
262 R_0B_LUMA_CONTRAST_CNTL, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */
263 R_0C_CHROMA_SAT_CNTL, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */
264 R_0D_CHROMA_HUE_CNTL, 0x00,
265 R_0F_CHROMA_GAIN_CNTL, 0x00, /* use automatic gain */
266 R_10_CHROMA_CNTL_2, 0x06, /* chroma: active adaptive combfilter */
267 R_11_MODE_DELAY_CNTL, 0x00,
268 R_12_RT_SIGNAL_CNTL, 0x9d, /* RTS0 output control: VGATE */
269 R_13_RT_X_PORT_OUT_CNTL, 0x80, /* ITU656 standard mode, RTCO output enable RTCE */
270 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
271 R_18_RAW_DATA_GAIN_CNTL, 0x40, /* gain 0x00 = nominal */
272 R_19_RAW_DATA_OFF_CNTL, 0x80,
273 R_1A_COLOR_KILL_LVL_CNTL, 0x77, /* recommended value */
274 R_1B_MISC_TVVCRDET, 0x42, /* recommended value */
275 R_1C_ENHAN_COMB_CTRL1, 0xa9, /* recommended value */
276 R_1D_ENHAN_COMB_CTRL2, 0x01, /* recommended value */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300277
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300278
279 R_80_GLOBAL_CNTL_1, 0x0, /* No tasks enabled at init */
280
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300281 /* Power Device Control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300282 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset device */
283 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* set device programmed, all in operational mode */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800284 0x00, 0x00
285};
286
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300287/* Used to reset saa7113, saa7114 and saa7115 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800288static const unsigned char saa7115_cfg_reset_scaler[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300289 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00, /* disable I-port output */
290 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
291 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
292 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* enable I-port output */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800293 0x00, 0x00
294};
295
296/* ============== SAA7715 VIDEO templates ============= */
297
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800298static const unsigned char saa7115_cfg_60hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300299 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
300 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800301
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300302 R_15_VGATE_START_FID_CHG, 0x03,
303 R_16_VGATE_STOP, 0x11,
304 R_17_MISC_VGATE_CONF_AND_MSB, 0x9c,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800305
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300306 R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
307 R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800308
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300309 R_5A_V_OFF_FOR_SLICER, 0x06, /* standard 60hz value for ITU656 line counting */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800310
311 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300312 R_90_A_TASK_HANDLING_CNTL, 0x80,
313 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
314 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
315 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
316
317 /* hoffset low (input), 0x0002 is minimum */
318 R_94_A_HORIZ_INPUT_WINDOW_START, 0x01,
319 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
320
321 /* hsize low (input), 0x02d0 = 720 */
322 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
323 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
324
325 R_98_A_VERT_INPUT_WINDOW_START, 0x05,
326 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
327
328 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x0c,
329 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
330
331 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
332 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
333
334 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x0c,
335 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800336
337 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300338 R_C0_B_TASK_HANDLING_CNTL, 0x00,
339 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
340 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
341 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800342
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300343 /* 0x0002 is minimum */
344 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x02,
345 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800346
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300347 /* 0x02d0 = 720 */
348 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
349 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
350
351 /* vwindow start 0x12 = 18 */
352 R_C8_B_VERT_INPUT_WINDOW_START, 0x12,
353 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
354
355 /* vwindow length 0xf8 = 248 */
Mauro Carvalho Chehab97d9e802006-09-03 09:38:11 -0300356 R_CA_B_VERT_INPUT_WINDOW_LENGTH, VRES_60HZ>>1,
357 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, VRES_60HZ>>9,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300358
359 /* hwindow 0x02d0 = 720 */
360 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
361 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
362
363 R_F0_LFCO_PER_LINE, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
364 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0 */
365 R_F5_PULSGEN_LINE_LENGTH, 0xad,
366 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
367
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800368 0x00, 0x00
369};
370
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800371static const unsigned char saa7115_cfg_50hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300372 R_80_GLOBAL_CNTL_1, 0x00,
373 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800374
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300375 R_15_VGATE_START_FID_CHG, 0x37, /* VGATE start */
376 R_16_VGATE_STOP, 0x16,
377 R_17_MISC_VGATE_CONF_AND_MSB, 0x99,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800378
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300379 R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */
380 R_0E_CHROMA_CNTL_1, 0x07,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800381
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300382 R_5A_V_OFF_FOR_SLICER, 0x03, /* standard 50hz value */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800383
384 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300385 R_90_A_TASK_HANDLING_CNTL, 0x81,
386 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
387 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
388 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
389
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800390 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
391 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300392 /* hoffset low (input), 0x0002 is minimum */
393 R_94_A_HORIZ_INPUT_WINDOW_START, 0x00,
394 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
395
396 /* hsize low (input), 0x02d0 = 720 */
397 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
398 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
399
400 R_98_A_VERT_INPUT_WINDOW_START, 0x03,
401 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
402
403 /* vsize 0x12 = 18 */
404 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x12,
405 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
406
407 /* hsize 0x05a0 = 1440 */
408 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
409 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05, /* hsize hi (output) */
410 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x12, /* vsize low (output), 0x12 = 18 */
411 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00, /* vsize hi (output) */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800412
413 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300414 R_C0_B_TASK_HANDLING_CNTL, 0x00,
415 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
416 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
417 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800418
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300419 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
420 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
421 /* hoffset low (input), 0x0002 is minimum. See comment above. */
422 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x00,
423 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800424
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300425 /* hsize 0x02d0 = 720 */
426 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
427 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
428
429 /* voffset 0x16 = 22 */
430 R_C8_B_VERT_INPUT_WINDOW_START, 0x16,
431 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
432
433 /* vsize 0x0120 = 288 */
434 R_CA_B_VERT_INPUT_WINDOW_LENGTH, 0x20,
435 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, 0x01,
436
437 /* hsize 0x02d0 = 720 */
438 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
439 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
440
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300441 R_F0_LFCO_PER_LINE, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
442 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0, (was 0x05) */
443 R_F5_PULSGEN_LINE_LENGTH, 0xb0,
444 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
445
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800446 0x00, 0x00
447};
448
449/* ============== SAA7715 VIDEO templates (end) ======= */
450
451static const unsigned char saa7115_cfg_vbi_on[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300452 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
453 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
454 R_80_GLOBAL_CNTL_1, 0x30, /* Activate both tasks */
455 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
456 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
457
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800458 0x00, 0x00
459};
460
461static const unsigned char saa7115_cfg_vbi_off[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300462 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
463 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
464 R_80_GLOBAL_CNTL_1, 0x20, /* Activate only task "B" */
465 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
466 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
467
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800468 0x00, 0x00
469};
470
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300471
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800472static const unsigned char saa7115_init_misc[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300473 R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300474 R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 0x01,
475 R_84_I_PORT_SIGNAL_DEF, 0x20,
476 R_85_I_PORT_SIGNAL_POLAR, 0x21,
477 R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT, 0xc5,
478 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800479
480 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300481 R_A0_A_HORIZ_PRESCALING, 0x01,
482 R_A1_A_ACCUMULATION_LENGTH, 0x00,
483 R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800484
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300485 /* Configure controls at nominal value*/
486 R_A4_A_LUMA_BRIGHTNESS_CNTL, 0x80,
487 R_A5_A_LUMA_CONTRAST_CNTL, 0x40,
488 R_A6_A_CHROMA_SATURATION_CNTL, 0x40,
489
490 /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
491 R_A8_A_HORIZ_LUMA_SCALING_INC, 0x00,
492 R_A9_A_HORIZ_LUMA_SCALING_INC_MSB, 0x02,
493
494 R_AA_A_HORIZ_LUMA_PHASE_OFF, 0x00,
495
496 /* must be horiz lum scaling / 2 */
497 R_AC_A_HORIZ_CHROMA_SCALING_INC, 0x00,
498 R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB, 0x01,
499
500 /* must be offset luma / 2 */
501 R_AE_A_HORIZ_CHROMA_PHASE_OFF, 0x00,
502
503 R_B0_A_VERT_LUMA_SCALING_INC, 0x00,
504 R_B1_A_VERT_LUMA_SCALING_INC_MSB, 0x04,
505
506 R_B2_A_VERT_CHROMA_SCALING_INC, 0x00,
507 R_B3_A_VERT_CHROMA_SCALING_INC_MSB, 0x04,
508
509 R_B4_A_VERT_SCALING_MODE_CNTL, 0x01,
510
511 R_B8_A_VERT_CHROMA_PHASE_OFF_00, 0x00,
512 R_B9_A_VERT_CHROMA_PHASE_OFF_01, 0x00,
513 R_BA_A_VERT_CHROMA_PHASE_OFF_10, 0x00,
514 R_BB_A_VERT_CHROMA_PHASE_OFF_11, 0x00,
515
516 R_BC_A_VERT_LUMA_PHASE_OFF_00, 0x00,
517 R_BD_A_VERT_LUMA_PHASE_OFF_01, 0x00,
518 R_BE_A_VERT_LUMA_PHASE_OFF_10, 0x00,
519 R_BF_A_VERT_LUMA_PHASE_OFF_11, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800520
521 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300522 R_D0_B_HORIZ_PRESCALING, 0x01,
523 R_D1_B_ACCUMULATION_LENGTH, 0x00,
524 R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800525
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300526 /* Configure controls at nominal value*/
527 R_D4_B_LUMA_BRIGHTNESS_CNTL, 0x80,
528 R_D5_B_LUMA_CONTRAST_CNTL, 0x40,
529 R_D6_B_CHROMA_SATURATION_CNTL, 0x40,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800530
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300531 /* hor lum scaling 0x0400 = 1 */
532 R_D8_B_HORIZ_LUMA_SCALING_INC, 0x00,
533 R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, 0x04,
534
535 R_DA_B_HORIZ_LUMA_PHASE_OFF, 0x00,
536
537 /* must be hor lum scaling / 2 */
538 R_DC_B_HORIZ_CHROMA_SCALING, 0x00,
539 R_DD_B_HORIZ_CHROMA_SCALING_MSB, 0x02,
540
541 /* must be offset luma / 2 */
542 R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA, 0x00,
543
544 R_E0_B_VERT_LUMA_SCALING_INC, 0x00,
545 R_E1_B_VERT_LUMA_SCALING_INC_MSB, 0x04,
546
547 R_E2_B_VERT_CHROMA_SCALING_INC, 0x00,
548 R_E3_B_VERT_CHROMA_SCALING_INC_MSB, 0x04,
549
550 R_E4_B_VERT_SCALING_MODE_CNTL, 0x01,
551
552 R_E8_B_VERT_CHROMA_PHASE_OFF_00, 0x00,
553 R_E9_B_VERT_CHROMA_PHASE_OFF_01, 0x00,
554 R_EA_B_VERT_CHROMA_PHASE_OFF_10, 0x00,
555 R_EB_B_VERT_CHROMA_PHASE_OFF_11, 0x00,
556
557 R_EC_B_VERT_LUMA_PHASE_OFF_00, 0x00,
558 R_ED_B_VERT_LUMA_PHASE_OFF_01, 0x00,
559 R_EE_B_VERT_LUMA_PHASE_OFF_10, 0x00,
560 R_EF_B_VERT_LUMA_PHASE_OFF_11, 0x00,
561
562 R_F2_NOMINAL_PLL2_DTO, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */
563 R_F3_PLL_INCREMENT, 0x46,
564 R_F4_PLL2_STATUS, 0x00,
565 R_F7_PULSE_A_POS_MSB, 0x4b, /* not the recommended settings! */
566 R_F8_PULSE_B_POS, 0x00,
567 R_F9_PULSE_B_POS_MSB, 0x4b,
568 R_FA_PULSE_C_POS, 0x00,
569 R_FB_PULSE_C_POS_MSB, 0x4b,
570
571 /* PLL2 lock detection settings: 71 lines 50% phase error */
572 R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES, 0x88,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800573
574 /* Turn off VBI */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300575 R_40_SLICER_CNTL_1, 0x20, /* No framing code errors allowed. */
576 R_41_LCR_BASE, 0xff,
577 R_41_LCR_BASE+1, 0xff,
578 R_41_LCR_BASE+2, 0xff,
579 R_41_LCR_BASE+3, 0xff,
580 R_41_LCR_BASE+4, 0xff,
581 R_41_LCR_BASE+5, 0xff,
582 R_41_LCR_BASE+6, 0xff,
583 R_41_LCR_BASE+7, 0xff,
584 R_41_LCR_BASE+8, 0xff,
585 R_41_LCR_BASE+9, 0xff,
586 R_41_LCR_BASE+10, 0xff,
587 R_41_LCR_BASE+11, 0xff,
588 R_41_LCR_BASE+12, 0xff,
589 R_41_LCR_BASE+13, 0xff,
590 R_41_LCR_BASE+14, 0xff,
591 R_41_LCR_BASE+15, 0xff,
592 R_41_LCR_BASE+16, 0xff,
593 R_41_LCR_BASE+17, 0xff,
594 R_41_LCR_BASE+18, 0xff,
595 R_41_LCR_BASE+19, 0xff,
596 R_41_LCR_BASE+20, 0xff,
597 R_41_LCR_BASE+21, 0xff,
598 R_41_LCR_BASE+22, 0xff,
599 R_58_PROGRAM_FRAMING_CODE, 0x40,
600 R_59_H_OFF_FOR_SLICER, 0x47,
601 R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF, 0x83,
602 R_5D_DID, 0xbd,
603 R_5E_SDID, 0x35,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800604
Devin Heitmuellerfea551f2010-02-03 00:33:48 -0300605 R_02_INPUT_CNTL_1, 0xc4, /* input tuner -> input 4, amplifier active */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800606
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300607 R_80_GLOBAL_CNTL_1, 0x20, /* enable task B */
608 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
609 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800610 0x00, 0x00
611};
612
Mauro Carvalho Chehab66ec1192006-08-29 22:52:32 -0300613static int saa711x_odd_parity(u8 c)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800614{
615 c ^= (c >> 4);
616 c ^= (c >> 2);
617 c ^= (c >> 1);
618
619 return c & 1;
620}
621
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300622static int saa711x_decode_vps(u8 *dst, u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800623{
624 static const u8 biphase_tbl[] = {
625 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
626 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
627 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
628 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
629 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
630 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
631 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
632 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
633 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
634 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
635 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
636 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
637 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
638 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
639 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
640 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
641 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
642 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
643 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
644 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
645 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
646 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
647 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
648 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
649 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
650 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
651 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
652 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
653 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
654 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
655 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
656 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
657 };
658 int i;
659 u8 c, err = 0;
660
661 for (i = 0; i < 2 * 13; i += 2) {
662 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
663 c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
664 dst[i / 2] = c;
665 }
666 return err & 0xf0;
667}
668
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300669static int saa711x_decode_wss(u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800670{
671 static const int wss_bits[8] = {
672 0, 0, 0, 1, 0, 1, 1, 1
673 };
674 unsigned char parity;
675 int wss = 0;
676 int i;
677
678 for (i = 0; i < 16; i++) {
679 int b1 = wss_bits[p[i] & 7];
680 int b2 = wss_bits[(p[i] >> 3) & 7];
681
682 if (b1 == b2)
683 return -1;
684 wss |= b2 << i;
685 }
686 parity = wss & 15;
687 parity ^= parity >> 2;
688 parity ^= parity >> 1;
689
690 if (!(parity & 1))
691 return -1;
692
693 return wss;
694}
695
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300696static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800697{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300698 struct saa711x_state *state = to_state(sd);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200699 u32 acpf;
700 u32 acni;
701 u32 hz;
702 u64 f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300703 u8 acc = 0; /* reg 0x3a, audio clock control */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800704
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300705 /* Checks for chips that don't have audio clock (saa7111, saa7113) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300706 if (!saa711x_has_reg(state->ident, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300707 return 0;
708
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300709 v4l2_dbg(1, debug, sd, "set audio clock freq: %d\n", freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200710
711 /* sanity check */
712 if (freq < 32000 || freq > 48000)
713 return -EINVAL;
714
715 /* hz is the refresh rate times 100 */
716 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
717 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
718 acpf = (25600 * freq) / hz;
719 /* acni = (256 * freq * 2^23) / crystal_frequency =
720 (freq * 2^(8+23)) / crystal_frequency =
Hans Verkuilb7f82922006-04-02 12:50:42 -0300721 (freq << 31) / crystal_frequency */
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200722 f = freq;
723 f = f << 31;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300724 do_div(f, state->crystal_freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200725 acni = f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300726 if (state->ucgc) {
727 acpf = acpf * state->cgcdiv / 16;
728 acni = acni * state->cgcdiv / 16;
729 acc = 0x80;
730 if (state->cgcdiv == 3)
731 acc |= 0x40;
732 }
733 if (state->apll)
734 acc |= 0x08;
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200735
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300736 saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
737 saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10);
738 saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300739
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300740 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
741 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300742 (acpf >> 8) & 0xff);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300743 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300744 (acpf >> 16) & 0x03);
745
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300746 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
747 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
748 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800749 state->audclk_freq = freq;
750 return 0;
751}
752
Hans Verkuile3560542010-05-24 10:00:52 -0300753static int saa711x_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800754{
Hans Verkuile3560542010-05-24 10:00:52 -0300755 struct v4l2_subdev *sd = to_sd(ctrl);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300756 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800757
758 switch (ctrl->id) {
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300759 case V4L2_CID_CHROMA_AGC:
Hans Verkuile3560542010-05-24 10:00:52 -0300760 /* chroma gain cluster */
761 if (state->agc->cur.val)
762 state->gain->cur.val =
763 saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL) & 0x7f;
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300764 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800765 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800766 return 0;
767}
768
Hans Verkuile3560542010-05-24 10:00:52 -0300769static int saa711x_s_ctrl(struct v4l2_ctrl *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800770{
Hans Verkuile3560542010-05-24 10:00:52 -0300771 struct v4l2_subdev *sd = to_sd(ctrl);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300772 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800773
774 switch (ctrl->id) {
775 case V4L2_CID_BRIGHTNESS:
Hans Verkuile3560542010-05-24 10:00:52 -0300776 saa711x_write(sd, R_0A_LUMA_BRIGHT_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800777 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300778
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800779 case V4L2_CID_CONTRAST:
Hans Verkuile3560542010-05-24 10:00:52 -0300780 saa711x_write(sd, R_0B_LUMA_CONTRAST_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800781 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300782
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800783 case V4L2_CID_SATURATION:
Hans Verkuile3560542010-05-24 10:00:52 -0300784 saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800785 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300786
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800787 case V4L2_CID_HUE:
Hans Verkuile3560542010-05-24 10:00:52 -0300788 saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800789 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300790
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300791 case V4L2_CID_CHROMA_AGC:
Hans Verkuile3560542010-05-24 10:00:52 -0300792 /* chroma gain cluster */
793 if (state->agc->val)
794 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val);
795 else
796 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val | 0x80);
797 v4l2_ctrl_activate(state->gain, !state->agc->val);
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300798 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300799
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800800 default:
801 return -EINVAL;
802 }
803
804 return 0;
805}
806
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300807static int saa711x_set_size(struct v4l2_subdev *sd, int width, int height)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300808{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300809 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300810 int HPSC, HFSC;
811 int VSCY;
812 int res;
813 int is_50hz = state->std & V4L2_STD_625_50;
814 int Vsrc = is_50hz ? 576 : 480;
815
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300816 v4l2_dbg(1, debug, sd, "decoder set size to %ix%i\n", width, height);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300817
818 /* FIXME need better bounds checking here */
819 if ((width < 1) || (width > 1440))
820 return -EINVAL;
821 if ((height < 1) || (height > Vsrc))
822 return -EINVAL;
823
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300824 if (!saa711x_has_reg(state->ident, R_D0_B_HORIZ_PRESCALING)) {
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300825 /* Decoder only supports 720 columns and 480 or 576 lines */
826 if (width != 720)
827 return -EINVAL;
828 if (height != Vsrc)
829 return -EINVAL;
830 }
831
832 state->width = width;
833 state->height = height;
834
835 if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
836 return 0;
837
838 /* probably have a valid size, let's set it */
839 /* Set output width/height */
840 /* width */
841
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300842 saa711x_write(sd, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300843 (u8) (width & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300844 saa711x_write(sd, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300845 (u8) ((width >> 8) & 0xff));
846
847 /* Vertical Scaling uses height/2 */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300848 res = height / 2;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300849
850 /* On 60Hz, it is using a higher Vertical Output Size */
851 if (!is_50hz)
Hans Verkuild0d30c02006-11-25 09:45:50 -0300852 res += (VRES_60HZ - 480) >> 1;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300853
854 /* height */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300855 saa711x_write(sd, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300856 (u8) (res & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300857 saa711x_write(sd, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300858 (u8) ((res >> 8) & 0xff));
859
860 /* Scaling settings */
861 /* Hprescaler is floor(inres/outres) */
862 HPSC = (int)(720 / width);
863 /* 0 is not allowed (div. by zero) */
864 HPSC = HPSC ? HPSC : 1;
865 HFSC = (int)((1024 * 720) / (HPSC * width));
866 /* FIXME hardcodes to "Task B"
867 * write H prescaler integer */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300868 saa711x_write(sd, R_D0_B_HORIZ_PRESCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300869 (u8) (HPSC & 0x3f));
870
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300871 v4l2_dbg(1, debug, sd, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300872 /* write H fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300873 saa711x_write(sd, R_D8_B_HORIZ_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300874 (u8) (HFSC & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300875 saa711x_write(sd, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300876 (u8) ((HFSC >> 8) & 0xff));
877 /* write H fine-scaling (chrominance)
878 * must be lum/2, so i'll just bitshift :) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300879 saa711x_write(sd, R_DC_B_HORIZ_CHROMA_SCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300880 (u8) ((HFSC >> 1) & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300881 saa711x_write(sd, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300882 (u8) ((HFSC >> 9) & 0xff));
883
884 VSCY = (int)((1024 * Vsrc) / height);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300885 v4l2_dbg(1, debug, sd, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300886
887 /* Correct Contrast and Luminance */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300888 saa711x_write(sd, R_D5_B_LUMA_CONTRAST_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300889 (u8) (64 * 1024 / VSCY));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300890 saa711x_write(sd, R_D6_B_CHROMA_SATURATION_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300891 (u8) (64 * 1024 / VSCY));
892
893 /* write V fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300894 saa711x_write(sd, R_E0_B_VERT_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300895 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300896 saa711x_write(sd, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300897 (u8) ((VSCY >> 8) & 0xff));
898 /* write V fine-scaling (chrominance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300899 saa711x_write(sd, R_E2_B_VERT_CHROMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300900 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300901 saa711x_write(sd, R_E3_B_VERT_CHROMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300902 (u8) ((VSCY >> 8) & 0xff));
903
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300904 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300905
906 /* Activates task "B" */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300907 saa711x_write(sd, R_80_GLOBAL_CNTL_1,
908 saa711x_read(sd, R_80_GLOBAL_CNTL_1) | 0x20);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300909
910 return 0;
911}
912
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300913static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800914{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300915 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800916
Hans Verkuil30b54d52006-01-09 15:25:43 -0200917 /* Prevent unnecessary standard changes. During a standard
918 change the I-Port is temporarily disabled. Any devices
919 reading from that port can get confused.
Hans Verkuilbccfa442009-03-30 06:55:27 -0300920 Note that s_std is also used to switch from
921 radio to TV mode, so if a s_std is broadcast to
Hans Verkuil30b54d52006-01-09 15:25:43 -0200922 all I2C devices then you do not want to have an unwanted
923 side-effect here. */
924 if (std == state->std)
925 return;
926
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300927 state->std = std;
928
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800929 // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
930 if (std & V4L2_STD_525_60) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300931 v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n");
932 saa711x_writeregs(sd, saa7115_cfg_60hz_video);
933 saa711x_set_size(sd, 720, 480);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800934 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300935 v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n");
936 saa711x_writeregs(sd, saa7115_cfg_50hz_video);
937 saa711x_set_size(sd, 720, 576);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800938 }
939
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300940 /* Register 0E - Bits D6-D4 on NO-AUTO mode
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300941 (SAA7111 and SAA7113 doesn't have auto mode)
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300942 50 Hz / 625 lines 60 Hz / 525 lines
943 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz)
944 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz)
945 010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz)
946 011 NTSC N (3.58MHz) PAL M (3.58MHz)
947 100 reserved NTSC-Japan (3.58MHz)
948 */
Hans Verkuil340dde82010-02-20 08:07:51 -0300949 if (state->ident <= V4L2_IDENT_SAA7113) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300950 u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300951
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300952 if (std == V4L2_STD_PAL_M) {
Hans Verkuil01342352006-03-25 08:19:47 -0300953 reg |= 0x30;
Hans Verkuile0028022008-04-22 14:45:51 -0300954 } else if (std == V4L2_STD_PAL_Nc) {
Hans Verkuil01342352006-03-25 08:19:47 -0300955 reg |= 0x20;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300956 } else if (std == V4L2_STD_PAL_60) {
Hans Verkuil01342352006-03-25 08:19:47 -0300957 reg |= 0x10;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300958 } else if (std == V4L2_STD_NTSC_M_JP) {
Hans Verkuil01342352006-03-25 08:19:47 -0300959 reg |= 0x40;
Mauro Carvalho Chehaba9aaec42007-03-13 13:41:49 -0300960 } else if (std & V4L2_STD_SECAM) {
Pádraig Bradyfc2fa312006-10-09 08:02:17 -0300961 reg |= 0x50;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300962 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300963 saa711x_write(sd, R_0E_CHROMA_CNTL_1, reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300964 } else {
965 /* restart task B if needed */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300966 int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300967
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300968 if (taskb && state->ident == V4L2_IDENT_SAA7114) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300969 saa711x_writeregs(sd, saa7115_cfg_vbi_on);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300970 }
971
972 /* switch audio mode too! */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300973 saa711x_s_clock_freq(sd, state->audclk_freq);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300974 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800975}
976
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800977/* setup the sliced VBI lcr registers according to the sliced VBI format */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300978static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800979{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300980 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800981 int is_50hz = (state->std & V4L2_STD_625_50);
982 u8 lcr[24];
983 int i, x;
984
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300985#if 1
986 /* saa7113/7114/7118 VBI support are experimental */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300987 if (!saa711x_has_reg(state->ident, R_41_LCR_BASE))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300988 return;
989
990#else
991 /* SAA7113 and SAA7118 also should support VBI - Need testing */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300992 if (state->ident != V4L2_IDENT_SAA7115)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800993 return;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300994#endif
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800995
996 for (i = 0; i <= 23; i++)
997 lcr[i] = 0xff;
998
Hans Verkuila8b86432008-10-04 08:05:30 -0300999 if (fmt == NULL) {
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001000 /* raw VBI */
1001 if (is_50hz)
1002 for (i = 6; i <= 23; i++)
1003 lcr[i] = 0xdd;
1004 else
1005 for (i = 10; i <= 21; i++)
1006 lcr[i] = 0xdd;
1007 } else {
1008 /* sliced VBI */
1009 /* first clear lines that cannot be captured */
1010 if (is_50hz) {
1011 for (i = 0; i <= 5; i++)
1012 fmt->service_lines[0][i] =
1013 fmt->service_lines[1][i] = 0;
1014 }
1015 else {
1016 for (i = 0; i <= 9; i++)
1017 fmt->service_lines[0][i] =
1018 fmt->service_lines[1][i] = 0;
1019 for (i = 22; i <= 23; i++)
1020 fmt->service_lines[0][i] =
1021 fmt->service_lines[1][i] = 0;
1022 }
1023
1024 /* Now set the lcr values according to the specified service */
1025 for (i = 6; i <= 23; i++) {
1026 lcr[i] = 0;
1027 for (x = 0; x <= 1; x++) {
1028 switch (fmt->service_lines[1-x][i]) {
1029 case 0:
1030 lcr[i] |= 0xf << (4 * x);
1031 break;
Hans Verkuil9bc74002006-03-29 18:02:51 -03001032 case V4L2_SLICED_TELETEXT_B:
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001033 lcr[i] |= 1 << (4 * x);
1034 break;
1035 case V4L2_SLICED_CAPTION_525:
1036 lcr[i] |= 4 << (4 * x);
1037 break;
1038 case V4L2_SLICED_WSS_625:
1039 lcr[i] |= 5 << (4 * x);
1040 break;
1041 case V4L2_SLICED_VPS:
1042 lcr[i] |= 7 << (4 * x);
1043 break;
1044 }
1045 }
1046 }
1047 }
1048
1049 /* write the lcr registers */
1050 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001051 saa711x_write(sd, i - 2 + R_41_LCR_BASE, lcr[i]);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001052 }
1053
1054 /* enable/disable raw VBI capturing */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001055 saa711x_writeregs(sd, fmt == NULL ?
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001056 saa7115_cfg_vbi_on :
1057 saa7115_cfg_vbi_off);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001058}
1059
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001060static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *sliced)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001061{
1062 static u16 lcr2vbi[] = {
Hans Verkuil9bc74002006-03-29 18:02:51 -03001063 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001064 0, V4L2_SLICED_CAPTION_525, /* 4 */
1065 V4L2_SLICED_WSS_625, 0, /* 5 */
1066 V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
1067 0, 0, 0, 0
1068 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001069 int i;
1070
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001071 memset(sliced, 0, sizeof(*sliced));
1072 /* done if using raw VBI */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001073 if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001074 return 0;
1075 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001076 u8 v = saa711x_read(sd, i - 2 + R_41_LCR_BASE);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001077
1078 sliced->service_lines[0][i] = lcr2vbi[v >> 4];
1079 sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
1080 sliced->service_set |=
1081 sliced->service_lines[0][i] | sliced->service_lines[1][i];
1082 }
1083 return 0;
1084}
1085
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001086static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
1087{
1088 saa711x_set_lcr(sd, NULL);
1089 return 0;
1090}
1091
1092static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
1093{
1094 saa711x_set_lcr(sd, fmt);
1095 return 0;
1096}
1097
Hans Verkuilc463d932010-05-09 09:47:23 -03001098static int saa711x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
1099{
1100 if (fmt->code != V4L2_MBUS_FMT_FIXED)
1101 return -EINVAL;
1102 fmt->field = V4L2_FIELD_INTERLACED;
1103 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1104 return saa711x_set_size(sd, fmt->width, fmt->height);
1105}
1106
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001107/* Decode the sliced VBI data stream as created by the saa7115.
1108 The format is described in the saa7115 datasheet in Tables 25 and 26
1109 and in Figure 33.
1110 The current implementation uses SAV/EAV codes and not the ancillary data
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001111 headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001112 code. */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001113static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001114{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001115 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001116 static const char vbi_no_data_pattern[] = {
1117 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
1118 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001119 u8 *p = vbi->p;
1120 u32 wss;
1121 int id1, id2; /* the ID1 and ID2 bytes from the internal header */
1122
1123 vbi->type = 0; /* mark result as a failure */
1124 id1 = p[2];
1125 id2 = p[3];
1126 /* Note: the field bit is inverted for 60 Hz video */
1127 if (state->std & V4L2_STD_525_60)
1128 id1 ^= 0x40;
1129
1130 /* Skip internal header, p now points to the start of the payload */
1131 p += 4;
1132 vbi->p = p;
1133
1134 /* calculate field and line number of the VBI packet (1-23) */
1135 vbi->is_second_field = ((id1 & 0x40) != 0);
1136 vbi->line = (id1 & 0x3f) << 3;
1137 vbi->line |= (id2 & 0x70) >> 4;
1138
1139 /* Obtain data type */
1140 id2 &= 0xf;
1141
1142 /* If the VBI slicer does not detect any signal it will fill up
1143 the payload buffer with 0xa0 bytes. */
1144 if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001145 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001146
1147 /* decode payloads */
1148 switch (id2) {
1149 case 1:
Hans Verkuil9bc74002006-03-29 18:02:51 -03001150 vbi->type = V4L2_SLICED_TELETEXT_B;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001151 break;
1152 case 4:
Mauro Carvalho Chehab59ba9152006-08-30 05:34:36 -03001153 if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001154 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001155 vbi->type = V4L2_SLICED_CAPTION_525;
1156 break;
1157 case 5:
Mauro Carvalho Chehab66ec1192006-08-29 22:52:32 -03001158 wss = saa711x_decode_wss(p);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001159 if (wss == -1)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001160 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001161 p[0] = wss & 0xff;
1162 p[1] = wss >> 8;
1163 vbi->type = V4L2_SLICED_WSS_625;
1164 break;
1165 case 7:
Mauro Carvalho Chehab66ec1192006-08-29 22:52:32 -03001166 if (saa711x_decode_vps(p, p) != 0)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001167 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001168 vbi->type = V4L2_SLICED_VPS;
1169 break;
1170 default:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001171 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001172 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001173 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001174}
1175
1176/* ============ SAA7115 AUDIO settings (end) ============= */
1177
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001178static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001179{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001180 struct saa711x_state *state = to_state(sd);
1181 int status;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001182
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001183 if (state->radio)
1184 return 0;
1185 status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001186
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001187 v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status);
1188 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1189 return 0;
1190}
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001191
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001192static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1193{
1194 struct saa711x_state *state = to_state(sd);
1195
1196 state->radio = 0;
1197 saa711x_set_v4lstd(sd, std);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001198 return 0;
1199}
1200
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001201static int saa711x_s_radio(struct v4l2_subdev *sd)
1202{
1203 struct saa711x_state *state = to_state(sd);
1204
1205 state->radio = 1;
1206 return 0;
1207}
1208
Hans Verkuil5325b422009-04-02 11:26:22 -03001209static int saa711x_s_routing(struct v4l2_subdev *sd,
1210 u32 input, u32 output, u32 config)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001211{
1212 struct saa711x_state *state = to_state(sd);
Hans Verkuil340dde82010-02-20 08:07:51 -03001213 u8 mask = (state->ident <= V4L2_IDENT_SAA7111A) ? 0xf8 : 0xf0;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001214
Hans Verkuil5325b422009-04-02 11:26:22 -03001215 v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n",
1216 input, output);
1217
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001218 /* saa7111/3 does not have these inputs */
Hans Verkuil340dde82010-02-20 08:07:51 -03001219 if (state->ident <= V4L2_IDENT_SAA7113 &&
Hans Verkuil5325b422009-04-02 11:26:22 -03001220 (input == SAA7115_COMPOSITE4 ||
1221 input == SAA7115_COMPOSITE5)) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001222 return -EINVAL;
1223 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001224 if (input > SAA7115_SVIDEO3)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001225 return -EINVAL;
Hans Verkuil5325b422009-04-02 11:26:22 -03001226 if (state->input == input && state->output == output)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001227 return 0;
1228 v4l2_dbg(1, debug, sd, "now setting %s input %s output\n",
Hans Verkuil5325b422009-04-02 11:26:22 -03001229 (input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite",
1230 (output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
1231 state->input = input;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001232
1233 /* saa7111 has slightly different input numbering */
Hans Verkuil340dde82010-02-20 08:07:51 -03001234 if (state->ident <= V4L2_IDENT_SAA7111A) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001235 if (input >= SAA7115_COMPOSITE4)
1236 input -= 2;
1237 /* saa7111 specific */
1238 saa711x_write(sd, R_10_CHROMA_CNTL_2,
1239 (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001240 ((output & 0xc0) ^ 0x40));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001241 saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL,
1242 (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001243 ((output & 2) ? 0x0a : 0));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001244 }
1245
1246 /* select mode */
1247 saa711x_write(sd, R_02_INPUT_CNTL_1,
1248 (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) |
1249 input);
1250
1251 /* bypass chrominance trap for S-Video modes */
1252 saa711x_write(sd, R_09_LUMA_CNTL,
1253 (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) |
1254 (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
1255
Hans Verkuil5325b422009-04-02 11:26:22 -03001256 state->output = output;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001257 if (state->ident == V4L2_IDENT_SAA7114 ||
1258 state->ident == V4L2_IDENT_SAA7115) {
1259 saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
1260 (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
1261 (state->output & 0x01));
1262 }
1263 return 0;
1264}
1265
1266static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val)
1267{
1268 struct saa711x_state *state = to_state(sd);
1269
Hans Verkuil340dde82010-02-20 08:07:51 -03001270 if (state->ident > V4L2_IDENT_SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001271 return -EINVAL;
1272 saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) |
1273 (val ? 0x80 : 0));
1274 return 0;
1275}
1276
1277static int saa711x_s_stream(struct v4l2_subdev *sd, int enable)
1278{
1279 struct saa711x_state *state = to_state(sd);
1280
1281 v4l2_dbg(1, debug, sd, "%s output\n",
1282 enable ? "enable" : "disable");
1283
Hans Verkuil674a3232009-02-18 12:22:16 -03001284 if (state->enable == enable)
1285 return 0;
1286 state->enable = enable;
1287 if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED))
1288 return 0;
1289 saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001290 return 0;
1291}
1292
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001293static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001294{
1295 struct saa711x_state *state = to_state(sd);
1296
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001297 if (freq != SAA7115_FREQ_32_11_MHZ && freq != SAA7115_FREQ_24_576_MHZ)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001298 return -EINVAL;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001299 state->crystal_freq = freq;
1300 state->cgcdiv = (flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
1301 state->ucgc = (flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;
1302 state->apll = (flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001303 saa711x_s_clock_freq(sd, state->audclk_freq);
1304 return 0;
1305}
1306
1307static int saa711x_reset(struct v4l2_subdev *sd, u32 val)
1308{
1309 v4l2_dbg(1, debug, sd, "decoder RESET\n");
1310 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
1311 return 0;
1312}
1313
1314static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data)
1315{
1316 /* Note: the internal field ID is inverted for NTSC,
1317 so data->field 0 maps to the saa7115 even field,
1318 whereas for PAL it maps to the saa7115 odd field. */
1319 switch (data->id) {
1320 case V4L2_SLICED_WSS_625:
1321 if (saa711x_read(sd, 0x6b) & 0xc0)
1322 return -EIO;
1323 data->data[0] = saa711x_read(sd, 0x6c);
1324 data->data[1] = saa711x_read(sd, 0x6d);
1325 return 0;
1326 case V4L2_SLICED_CAPTION_525:
1327 if (data->field == 0) {
1328 /* CC */
1329 if (saa711x_read(sd, 0x66) & 0x30)
1330 return -EIO;
1331 data->data[0] = saa711x_read(sd, 0x69);
1332 data->data[1] = saa711x_read(sd, 0x6a);
1333 return 0;
1334 }
1335 /* XDS */
1336 if (saa711x_read(sd, 0x66) & 0xc0)
1337 return -EIO;
1338 data->data[0] = saa711x_read(sd, 0x67);
1339 data->data[1] = saa711x_read(sd, 0x68);
1340 return 0;
1341 default:
1342 return -EINVAL;
1343 }
1344}
1345
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001346static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
1347{
1348 struct saa711x_state *state = to_state(sd);
1349 int reg1e;
1350
1351 *std = V4L2_STD_ALL;
1352 if (state->ident != V4L2_IDENT_SAA7115)
1353 return 0;
1354 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1355
1356 switch (reg1e & 0x03) {
1357 case 1:
1358 *std = V4L2_STD_NTSC;
1359 break;
1360 case 2:
1361 *std = V4L2_STD_PAL;
1362 break;
1363 case 3:
1364 *std = V4L2_STD_SECAM;
1365 break;
1366 default:
1367 break;
1368 }
1369 return 0;
1370}
1371
1372static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status)
1373{
1374 struct saa711x_state *state = to_state(sd);
1375 int reg1e = 0x80;
1376 int reg1f;
1377
1378 *status = V4L2_IN_ST_NO_SIGNAL;
1379 if (state->ident == V4L2_IDENT_SAA7115)
1380 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1381 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1382 if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80)
1383 *status = 0;
1384 return 0;
1385}
1386
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001387#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuilaecde8b2008-12-30 07:14:19 -03001388static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001389{
1390 struct i2c_client *client = v4l2_get_subdevdata(sd);
1391
Hans Verkuilaecde8b2008-12-30 07:14:19 -03001392 if (!v4l2_chip_match_i2c_client(client, &reg->match))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001393 return -EINVAL;
1394 if (!capable(CAP_SYS_ADMIN))
1395 return -EPERM;
1396 reg->val = saa711x_read(sd, reg->reg & 0xff);
Hans Verkuilaecde8b2008-12-30 07:14:19 -03001397 reg->size = 1;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001398 return 0;
1399}
1400
Hans Verkuilaecde8b2008-12-30 07:14:19 -03001401static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001402{
1403 struct i2c_client *client = v4l2_get_subdevdata(sd);
1404
Hans Verkuilaecde8b2008-12-30 07:14:19 -03001405 if (!v4l2_chip_match_i2c_client(client, &reg->match))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001406 return -EINVAL;
1407 if (!capable(CAP_SYS_ADMIN))
1408 return -EPERM;
1409 saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff);
1410 return 0;
1411}
1412#endif
1413
Hans Verkuilaecde8b2008-12-30 07:14:19 -03001414static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001415{
1416 struct saa711x_state *state = to_state(sd);
1417 struct i2c_client *client = v4l2_get_subdevdata(sd);
1418
1419 return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0);
1420}
1421
1422static int saa711x_log_status(struct v4l2_subdev *sd)
1423{
1424 struct saa711x_state *state = to_state(sd);
1425 int reg1e, reg1f;
1426 int signalOk;
1427 int vcr;
1428
1429 v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq);
1430 if (state->ident != V4L2_IDENT_SAA7115) {
1431 /* status for the saa7114 */
1432 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1433 signalOk = (reg1f & 0xc1) == 0x81;
1434 v4l2_info(sd, "Video signal: %s\n", signalOk ? "ok" : "bad");
1435 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1436 return 0;
1437 }
1438
1439 /* status for the saa7115 */
1440 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1441 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1442
1443 signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
1444 vcr = !(reg1f & 0x10);
1445
1446 if (state->input >= 6)
1447 v4l2_info(sd, "Input: S-Video %d\n", state->input - 6);
1448 else
1449 v4l2_info(sd, "Input: Composite %d\n", state->input);
1450 v4l2_info(sd, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
1451 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1452
1453 switch (reg1e & 0x03) {
1454 case 1:
1455 v4l2_info(sd, "Detected format: NTSC\n");
1456 break;
1457 case 2:
1458 v4l2_info(sd, "Detected format: PAL\n");
1459 break;
1460 case 3:
1461 v4l2_info(sd, "Detected format: SECAM\n");
1462 break;
1463 default:
1464 v4l2_info(sd, "Detected format: BW/No color\n");
1465 break;
1466 }
1467 v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height);
Hans Verkuile3560542010-05-24 10:00:52 -03001468 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001469 return 0;
1470}
1471
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001472/* ----------------------------------------------------------------------- */
1473
Hans Verkuile3560542010-05-24 10:00:52 -03001474static const struct v4l2_ctrl_ops saa711x_ctrl_ops = {
1475 .s_ctrl = saa711x_s_ctrl,
1476 .g_volatile_ctrl = saa711x_g_volatile_ctrl,
1477};
1478
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001479static const struct v4l2_subdev_core_ops saa711x_core_ops = {
1480 .log_status = saa711x_log_status,
1481 .g_chip_ident = saa711x_g_chip_ident,
Hans Verkuile3560542010-05-24 10:00:52 -03001482 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
1483 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
1484 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
1485 .g_ctrl = v4l2_subdev_g_ctrl,
1486 .s_ctrl = v4l2_subdev_s_ctrl,
1487 .queryctrl = v4l2_subdev_queryctrl,
1488 .querymenu = v4l2_subdev_querymenu,
Hans Verkuilf41737e2009-04-01 03:52:39 -03001489 .s_std = saa711x_s_std,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001490 .reset = saa711x_reset,
1491 .s_gpio = saa711x_s_gpio,
1492#ifdef CONFIG_VIDEO_ADV_DEBUG
1493 .g_register = saa711x_g_register,
1494 .s_register = saa711x_s_register,
1495#endif
1496};
1497
1498static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001499 .s_radio = saa711x_s_radio,
1500 .g_tuner = saa711x_g_tuner,
1501};
1502
1503static const struct v4l2_subdev_audio_ops saa711x_audio_ops = {
1504 .s_clock_freq = saa711x_s_clock_freq,
1505};
1506
1507static const struct v4l2_subdev_video_ops saa711x_video_ops = {
1508 .s_routing = saa711x_s_routing,
1509 .s_crystal_freq = saa711x_s_crystal_freq,
Hans Verkuilc463d932010-05-09 09:47:23 -03001510 .s_mbus_fmt = saa711x_s_mbus_fmt,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001511 .s_stream = saa711x_s_stream,
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001512 .querystd = saa711x_querystd,
1513 .g_input_status = saa711x_g_input_status,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001514};
1515
Hans Verkuil32cd5272010-03-14 09:57:30 -03001516static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = {
1517 .g_vbi_data = saa711x_g_vbi_data,
1518 .decode_vbi_line = saa711x_decode_vbi_line,
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001519 .g_sliced_fmt = saa711x_g_sliced_fmt,
1520 .s_sliced_fmt = saa711x_s_sliced_fmt,
1521 .s_raw_fmt = saa711x_s_raw_fmt,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001522};
1523
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001524static const struct v4l2_subdev_ops saa711x_ops = {
1525 .core = &saa711x_core_ops,
1526 .tuner = &saa711x_tuner_ops,
1527 .audio = &saa711x_audio_ops,
1528 .video = &saa711x_video_ops,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001529 .vbi = &saa711x_vbi_ops,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001530};
1531
1532/* ----------------------------------------------------------------------- */
1533
1534static int saa711x_probe(struct i2c_client *client,
Jean Delvared2653e92008-04-29 23:11:39 +02001535 const struct i2c_device_id *id)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001536{
Mauro Carvalho Chehab66ec1192006-08-29 22:52:32 -03001537 struct saa711x_state *state;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001538 struct v4l2_subdev *sd;
Hans Verkuile3560542010-05-24 10:00:52 -03001539 struct v4l2_ctrl_handler *hdl;
1540 int i;
1541 char name[17];
Jean Delvareaf294862008-05-18 20:49:40 +02001542 char chip_id;
1543 int autodetect = !id || id->driver_data == 1;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001544
1545 /* Check if the adapter supports the needed features */
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001546 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
Hans Verkuil188f3452007-09-16 10:47:15 -03001547 return -EIO;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001548
Hans Verkuild0d30c02006-11-25 09:45:50 -03001549 for (i = 0; i < 0x0f; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001550 i2c_smbus_write_byte_data(client, 0, i);
1551 name[i] = (i2c_smbus_read_byte_data(client, 0) & 0x0f) + '0';
Hans Verkuild0d30c02006-11-25 09:45:50 -03001552 if (name[i] > '9')
1553 name[i] += 'a' - '9' - 1;
Mauro Carvalho Chehab236f16d2006-08-28 08:25:29 -03001554 }
Hans Verkuild0d30c02006-11-25 09:45:50 -03001555 name[i] = '\0';
Mauro Carvalho Chehab236f16d2006-08-28 08:25:29 -03001556
Jean Delvareaf294862008-05-18 20:49:40 +02001557 chip_id = name[5];
Mauro Carvalho Chehab3e7d3e52006-09-01 18:39:05 -03001558
Hans Verkuilf7668162006-11-25 09:40:28 -03001559 /* Check whether this chip is part of the saa711x series */
1560 if (memcmp(name, "1f711", 5)) {
1561 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 -03001562 client->addr << 1, name);
Hans Verkuil188f3452007-09-16 10:47:15 -03001563 return -ENODEV;
Hans Verkuilf7668162006-11-25 09:40:28 -03001564 }
1565
Jean Delvareaf294862008-05-18 20:49:40 +02001566 /* Safety check */
1567 if (!autodetect && id->name[6] != chip_id) {
1568 v4l_warn(client, "found saa711%c while %s was expected\n",
1569 chip_id, id->name);
1570 }
1571 snprintf(client->name, sizeof(client->name), "saa711%c", chip_id);
1572 v4l_info(client, "saa711%c found (%s) @ 0x%x (%s)\n", chip_id, name,
1573 client->addr << 1, client->adapter->name);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001574
Mauro Carvalho Chehab66ec1192006-08-29 22:52:32 -03001575 state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL);
Hans Verkuilc5bf2042008-09-03 17:12:09 -03001576 if (state == NULL)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001577 return -ENOMEM;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001578 sd = &state->sd;
1579 v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
Hans Verkuile3560542010-05-24 10:00:52 -03001580
1581 hdl = &state->hdl;
1582 v4l2_ctrl_handler_init(hdl, 6);
1583 /* add in ascending ID order */
1584 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1585 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1586 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1587 V4L2_CID_CONTRAST, 0, 127, 1, 64);
1588 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1589 V4L2_CID_SATURATION, 0, 127, 1, 64);
1590 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1591 V4L2_CID_HUE, -128, 127, 1, 0);
1592 state->agc = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1593 V4L2_CID_CHROMA_AGC, 0, 1, 1, 1);
1594 state->gain = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1595 V4L2_CID_CHROMA_GAIN, 0, 127, 1, 40);
1596 state->gain->is_volatile = 1;
1597 sd->ctrl_handler = hdl;
1598 if (hdl->error) {
1599 int err = hdl->error;
1600
1601 v4l2_ctrl_handler_free(hdl);
1602 kfree(state);
1603 return err;
1604 }
1605 state->agc->flags |= V4L2_CTRL_FLAG_UPDATE;
1606 v4l2_ctrl_cluster(2, &state->agc);
1607
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001608 state->input = -1;
Marco Schluessler4cbca182007-01-21 19:43:38 -03001609 state->output = SAA7115_IPORT_ON;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001610 state->enable = 1;
Hans Verkuil3faeeae2006-01-09 15:25:44 -02001611 state->radio = 0;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001612 switch (chip_id) {
Jean Delvareaf294862008-05-18 20:49:40 +02001613 case '1':
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001614 state->ident = V4L2_IDENT_SAA7111;
Hans Verkuil340dde82010-02-20 08:07:51 -03001615 if (saa711x_read(sd, R_00_CHIP_VERSION) & 0xf0) {
1616 v4l_info(client, "saa7111a variant found\n");
1617 state->ident = V4L2_IDENT_SAA7111A;
1618 }
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001619 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001620 case '3':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001621 state->ident = V4L2_IDENT_SAA7113;
1622 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001623 case '4':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001624 state->ident = V4L2_IDENT_SAA7114;
1625 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001626 case '5':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001627 state->ident = V4L2_IDENT_SAA7115;
1628 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001629 case '8':
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001630 state->ident = V4L2_IDENT_SAA7118;
1631 break;
1632 default:
1633 state->ident = V4L2_IDENT_SAA7111;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001634 v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n");
Hans Verkuil340dde82010-02-20 08:07:51 -03001635 break;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001636 }
1637
Hans Verkuil3578d3d2006-01-09 15:25:41 -02001638 state->audclk_freq = 48000;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001639
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001640 v4l2_dbg(1, debug, sd, "writing init values\n");
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001641
1642 /* init to 60hz/48khz */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001643 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
1644 switch (state->ident) {
1645 case V4L2_IDENT_SAA7111:
Hans Verkuil340dde82010-02-20 08:07:51 -03001646 case V4L2_IDENT_SAA7111A:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001647 saa711x_writeregs(sd, saa7111_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001648 break;
1649 case V4L2_IDENT_SAA7113:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001650 saa711x_writeregs(sd, saa7113_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001651 break;
1652 default:
Hans Verkuilb7f82922006-04-02 12:50:42 -03001653 state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001654 saa711x_writeregs(sd, saa7115_init_auto_input);
Hans Verkuilb7f82922006-04-02 12:50:42 -03001655 }
Hans Verkuil340dde82010-02-20 08:07:51 -03001656 if (state->ident > V4L2_IDENT_SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001657 saa711x_writeregs(sd, saa7115_init_misc);
1658 saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
Hans Verkuile3560542010-05-24 10:00:52 -03001659 v4l2_ctrl_handler_setup(hdl);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001660
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001661 v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n",
1662 saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC),
1663 saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001664 return 0;
1665}
1666
1667/* ----------------------------------------------------------------------- */
1668
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001669static int saa711x_remove(struct i2c_client *client)
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001670{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001671 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1672
1673 v4l2_device_unregister_subdev(sd);
Hans Verkuile3560542010-05-24 10:00:52 -03001674 v4l2_ctrl_handler_free(sd->ctrl_handler);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001675 kfree(to_state(sd));
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001676 return 0;
1677}
1678
Jean Delvareaf294862008-05-18 20:49:40 +02001679static const struct i2c_device_id saa7115_id[] = {
Hans Verkuil9edd350f2008-07-17 13:22:51 -03001680 { "saa7115_auto", 1 }, /* autodetect */
Jean Delvareaf294862008-05-18 20:49:40 +02001681 { "saa7111", 0 },
1682 { "saa7113", 0 },
1683 { "saa7114", 0 },
1684 { "saa7115", 0 },
1685 { "saa7118", 0 },
1686 { }
1687};
1688MODULE_DEVICE_TABLE(i2c, saa7115_id);
1689
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001690static struct v4l2_i2c_driver_data v4l2_i2c_data = {
1691 .name = "saa7115",
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001692 .probe = saa711x_probe,
1693 .remove = saa711x_remove,
Jean Delvareaf294862008-05-18 20:49:40 +02001694 .id_table = saa7115_id,
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001695};