blob: ca2a863a6d3ec87c4ec6b3831278365b609b28c8 [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 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
Rusty Russell90ab5ee2012-01-13 09:32:20 +103060static bool debug;
Hans Verkuilfac9e892006-01-09 15:32:40 -020061module_param(debug, bool, 0644);
Hans Verkuile19b2fc2005-11-13 16:08:04 -080062
63MODULE_PARM_DESC(debug, "Debug level (0-1)");
64
Hans Verkuile19b2fc2005-11-13 16:08:04 -080065
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -030066struct saa711x_state {
Hans Verkuil9415f4b2008-11-29 12:55:19 -030067 struct v4l2_subdev sd;
Hans Verkuile3560542010-05-24 10:00:52 -030068 struct v4l2_ctrl_handler hdl;
69
70 struct {
71 /* chroma gain control cluster */
72 struct v4l2_ctrl *agc;
73 struct v4l2_ctrl *gain;
74 };
75
Hans Verkuile19b2fc2005-11-13 16:08:04 -080076 v4l2_std_id std;
77 int input;
Marco Schluessler4cbca182007-01-21 19:43:38 -030078 int output;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080079 int enable;
Hans Verkuil3faeeae2006-01-09 15:25:44 -020080 int radio;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -030081 int width;
82 int height;
Hans Verkuil3434eb72007-04-27 12:31:08 -030083 u32 ident;
Hans Verkuil3578d3d2006-01-09 15:25:41 -020084 u32 audclk_freq;
Hans Verkuilb7f82922006-04-02 12:50:42 -030085 u32 crystal_freq;
Hans Verkuil15890372013-03-11 03:47:25 -030086 bool ucgc;
Hans Verkuilb7f82922006-04-02 12:50:42 -030087 u8 cgcdiv;
Hans Verkuil15890372013-03-11 03:47:25 -030088 bool apll;
89 bool double_asclk;
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 Chehab66ec11932006-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 Verkuil15890372013-03-11 03:47:25 -0300736 if (state->double_asclk) {
737 acpf <<= 1;
738 acni <<= 1;
739 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300740 saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
Hans Verkuil15890372013-03-11 03:47:25 -0300741 saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10 << state->double_asclk);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300742 saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300743
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300744 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
745 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300746 (acpf >> 8) & 0xff);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300747 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300748 (acpf >> 16) & 0x03);
749
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300750 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
751 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
752 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800753 state->audclk_freq = freq;
754 return 0;
755}
756
Hans Verkuile3560542010-05-24 10:00:52 -0300757static int saa711x_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800758{
Hans Verkuile3560542010-05-24 10:00:52 -0300759 struct v4l2_subdev *sd = to_sd(ctrl);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300760 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800761
762 switch (ctrl->id) {
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300763 case V4L2_CID_CHROMA_AGC:
Hans Verkuile3560542010-05-24 10:00:52 -0300764 /* chroma gain cluster */
Hans Verkuilddac5c12011-06-10 05:43:34 -0300765 if (state->agc->val)
766 state->gain->val =
Hans Verkuile3560542010-05-24 10:00:52 -0300767 saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL) & 0x7f;
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300768 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800769 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800770 return 0;
771}
772
Hans Verkuile3560542010-05-24 10:00:52 -0300773static int saa711x_s_ctrl(struct v4l2_ctrl *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800774{
Hans Verkuile3560542010-05-24 10:00:52 -0300775 struct v4l2_subdev *sd = to_sd(ctrl);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300776 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800777
778 switch (ctrl->id) {
779 case V4L2_CID_BRIGHTNESS:
Hans Verkuile3560542010-05-24 10:00:52 -0300780 saa711x_write(sd, R_0A_LUMA_BRIGHT_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_CONTRAST:
Hans Verkuile3560542010-05-24 10:00:52 -0300784 saa711x_write(sd, R_0B_LUMA_CONTRAST_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_SATURATION:
Hans Verkuile3560542010-05-24 10:00:52 -0300788 saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800789 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300790
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800791 case V4L2_CID_HUE:
Hans Verkuile3560542010-05-24 10:00:52 -0300792 saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800793 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300794
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300795 case V4L2_CID_CHROMA_AGC:
Hans Verkuile3560542010-05-24 10:00:52 -0300796 /* chroma gain cluster */
797 if (state->agc->val)
798 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val);
799 else
800 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val | 0x80);
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300801 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300802
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800803 default:
804 return -EINVAL;
805 }
806
807 return 0;
808}
809
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300810static int saa711x_set_size(struct v4l2_subdev *sd, int width, int height)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300811{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300812 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300813 int HPSC, HFSC;
814 int VSCY;
815 int res;
816 int is_50hz = state->std & V4L2_STD_625_50;
817 int Vsrc = is_50hz ? 576 : 480;
818
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300819 v4l2_dbg(1, debug, sd, "decoder set size to %ix%i\n", width, height);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300820
821 /* FIXME need better bounds checking here */
822 if ((width < 1) || (width > 1440))
823 return -EINVAL;
824 if ((height < 1) || (height > Vsrc))
825 return -EINVAL;
826
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300827 if (!saa711x_has_reg(state->ident, R_D0_B_HORIZ_PRESCALING)) {
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300828 /* Decoder only supports 720 columns and 480 or 576 lines */
829 if (width != 720)
830 return -EINVAL;
831 if (height != Vsrc)
832 return -EINVAL;
833 }
834
835 state->width = width;
836 state->height = height;
837
838 if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
839 return 0;
840
841 /* probably have a valid size, let's set it */
842 /* Set output width/height */
843 /* width */
844
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300845 saa711x_write(sd, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300846 (u8) (width & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300847 saa711x_write(sd, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300848 (u8) ((width >> 8) & 0xff));
849
850 /* Vertical Scaling uses height/2 */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300851 res = height / 2;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300852
853 /* On 60Hz, it is using a higher Vertical Output Size */
854 if (!is_50hz)
Hans Verkuild0d30c02006-11-25 09:45:50 -0300855 res += (VRES_60HZ - 480) >> 1;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300856
857 /* height */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300858 saa711x_write(sd, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300859 (u8) (res & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300860 saa711x_write(sd, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300861 (u8) ((res >> 8) & 0xff));
862
863 /* Scaling settings */
864 /* Hprescaler is floor(inres/outres) */
865 HPSC = (int)(720 / width);
866 /* 0 is not allowed (div. by zero) */
867 HPSC = HPSC ? HPSC : 1;
868 HFSC = (int)((1024 * 720) / (HPSC * width));
869 /* FIXME hardcodes to "Task B"
870 * write H prescaler integer */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300871 saa711x_write(sd, R_D0_B_HORIZ_PRESCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300872 (u8) (HPSC & 0x3f));
873
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300874 v4l2_dbg(1, debug, sd, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300875 /* write H fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300876 saa711x_write(sd, R_D8_B_HORIZ_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300877 (u8) (HFSC & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300878 saa711x_write(sd, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300879 (u8) ((HFSC >> 8) & 0xff));
880 /* write H fine-scaling (chrominance)
881 * must be lum/2, so i'll just bitshift :) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300882 saa711x_write(sd, R_DC_B_HORIZ_CHROMA_SCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300883 (u8) ((HFSC >> 1) & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300884 saa711x_write(sd, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300885 (u8) ((HFSC >> 9) & 0xff));
886
887 VSCY = (int)((1024 * Vsrc) / height);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300888 v4l2_dbg(1, debug, sd, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300889
890 /* Correct Contrast and Luminance */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300891 saa711x_write(sd, R_D5_B_LUMA_CONTRAST_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300892 (u8) (64 * 1024 / VSCY));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300893 saa711x_write(sd, R_D6_B_CHROMA_SATURATION_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300894 (u8) (64 * 1024 / VSCY));
895
896 /* write V fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300897 saa711x_write(sd, R_E0_B_VERT_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300898 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300899 saa711x_write(sd, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300900 (u8) ((VSCY >> 8) & 0xff));
901 /* write V fine-scaling (chrominance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300902 saa711x_write(sd, R_E2_B_VERT_CHROMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300903 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300904 saa711x_write(sd, R_E3_B_VERT_CHROMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300905 (u8) ((VSCY >> 8) & 0xff));
906
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300907 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300908
909 /* Activates task "B" */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300910 saa711x_write(sd, R_80_GLOBAL_CNTL_1,
911 saa711x_read(sd, R_80_GLOBAL_CNTL_1) | 0x20);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300912
913 return 0;
914}
915
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300916static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800917{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300918 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800919
Hans Verkuil30b54d52006-01-09 15:25:43 -0200920 /* Prevent unnecessary standard changes. During a standard
921 change the I-Port is temporarily disabled. Any devices
922 reading from that port can get confused.
Hans Verkuilbccfa442009-03-30 06:55:27 -0300923 Note that s_std is also used to switch from
924 radio to TV mode, so if a s_std is broadcast to
Hans Verkuil30b54d52006-01-09 15:25:43 -0200925 all I2C devices then you do not want to have an unwanted
926 side-effect here. */
927 if (std == state->std)
928 return;
929
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300930 state->std = std;
931
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800932 // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
933 if (std & V4L2_STD_525_60) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300934 v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n");
935 saa711x_writeregs(sd, saa7115_cfg_60hz_video);
936 saa711x_set_size(sd, 720, 480);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800937 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300938 v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n");
939 saa711x_writeregs(sd, saa7115_cfg_50hz_video);
940 saa711x_set_size(sd, 720, 576);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800941 }
942
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300943 /* Register 0E - Bits D6-D4 on NO-AUTO mode
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300944 (SAA7111 and SAA7113 doesn't have auto mode)
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300945 50 Hz / 625 lines 60 Hz / 525 lines
946 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz)
947 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz)
948 010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz)
949 011 NTSC N (3.58MHz) PAL M (3.58MHz)
950 100 reserved NTSC-Japan (3.58MHz)
951 */
Hans Verkuil340dde82010-02-20 08:07:51 -0300952 if (state->ident <= V4L2_IDENT_SAA7113) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300953 u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300954
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300955 if (std == V4L2_STD_PAL_M) {
Hans Verkuil01342352006-03-25 08:19:47 -0300956 reg |= 0x30;
Hans Verkuile0028022008-04-22 14:45:51 -0300957 } else if (std == V4L2_STD_PAL_Nc) {
Hans Verkuil01342352006-03-25 08:19:47 -0300958 reg |= 0x20;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300959 } else if (std == V4L2_STD_PAL_60) {
Hans Verkuil01342352006-03-25 08:19:47 -0300960 reg |= 0x10;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300961 } else if (std == V4L2_STD_NTSC_M_JP) {
Hans Verkuil01342352006-03-25 08:19:47 -0300962 reg |= 0x40;
Mauro Carvalho Chehaba9aaec42007-03-13 13:41:49 -0300963 } else if (std & V4L2_STD_SECAM) {
Pádraig Bradyfc2fa312006-10-09 08:02:17 -0300964 reg |= 0x50;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300965 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300966 saa711x_write(sd, R_0E_CHROMA_CNTL_1, reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300967 } else {
968 /* restart task B if needed */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300969 int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300970
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300971 if (taskb && state->ident == V4L2_IDENT_SAA7114) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300972 saa711x_writeregs(sd, saa7115_cfg_vbi_on);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300973 }
974
975 /* switch audio mode too! */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300976 saa711x_s_clock_freq(sd, state->audclk_freq);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300977 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800978}
979
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800980/* setup the sliced VBI lcr registers according to the sliced VBI format */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300981static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800982{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300983 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800984 int is_50hz = (state->std & V4L2_STD_625_50);
985 u8 lcr[24];
986 int i, x;
987
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300988#if 1
989 /* saa7113/7114/7118 VBI support are experimental */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300990 if (!saa711x_has_reg(state->ident, R_41_LCR_BASE))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300991 return;
992
993#else
994 /* SAA7113 and SAA7118 also should support VBI - Need testing */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300995 if (state->ident != V4L2_IDENT_SAA7115)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800996 return;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300997#endif
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800998
999 for (i = 0; i <= 23; i++)
1000 lcr[i] = 0xff;
1001
Hans Verkuila8b86432008-10-04 08:05:30 -03001002 if (fmt == NULL) {
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001003 /* raw VBI */
1004 if (is_50hz)
1005 for (i = 6; i <= 23; i++)
1006 lcr[i] = 0xdd;
1007 else
1008 for (i = 10; i <= 21; i++)
1009 lcr[i] = 0xdd;
1010 } else {
1011 /* sliced VBI */
1012 /* first clear lines that cannot be captured */
1013 if (is_50hz) {
1014 for (i = 0; i <= 5; i++)
1015 fmt->service_lines[0][i] =
1016 fmt->service_lines[1][i] = 0;
1017 }
1018 else {
1019 for (i = 0; i <= 9; i++)
1020 fmt->service_lines[0][i] =
1021 fmt->service_lines[1][i] = 0;
1022 for (i = 22; i <= 23; i++)
1023 fmt->service_lines[0][i] =
1024 fmt->service_lines[1][i] = 0;
1025 }
1026
1027 /* Now set the lcr values according to the specified service */
1028 for (i = 6; i <= 23; i++) {
1029 lcr[i] = 0;
1030 for (x = 0; x <= 1; x++) {
1031 switch (fmt->service_lines[1-x][i]) {
1032 case 0:
1033 lcr[i] |= 0xf << (4 * x);
1034 break;
Hans Verkuil9bc74002006-03-29 18:02:51 -03001035 case V4L2_SLICED_TELETEXT_B:
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001036 lcr[i] |= 1 << (4 * x);
1037 break;
1038 case V4L2_SLICED_CAPTION_525:
1039 lcr[i] |= 4 << (4 * x);
1040 break;
1041 case V4L2_SLICED_WSS_625:
1042 lcr[i] |= 5 << (4 * x);
1043 break;
1044 case V4L2_SLICED_VPS:
1045 lcr[i] |= 7 << (4 * x);
1046 break;
1047 }
1048 }
1049 }
1050 }
1051
1052 /* write the lcr registers */
1053 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001054 saa711x_write(sd, i - 2 + R_41_LCR_BASE, lcr[i]);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001055 }
1056
1057 /* enable/disable raw VBI capturing */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001058 saa711x_writeregs(sd, fmt == NULL ?
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001059 saa7115_cfg_vbi_on :
1060 saa7115_cfg_vbi_off);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001061}
1062
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001063static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *sliced)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001064{
1065 static u16 lcr2vbi[] = {
Hans Verkuil9bc74002006-03-29 18:02:51 -03001066 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001067 0, V4L2_SLICED_CAPTION_525, /* 4 */
1068 V4L2_SLICED_WSS_625, 0, /* 5 */
1069 V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
1070 0, 0, 0, 0
1071 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001072 int i;
1073
Hans Verkuil30634e82012-09-05 10:38:10 -03001074 memset(sliced->service_lines, 0, sizeof(sliced->service_lines));
1075 sliced->service_set = 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001076 /* done if using raw VBI */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001077 if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001078 return 0;
1079 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001080 u8 v = saa711x_read(sd, i - 2 + R_41_LCR_BASE);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001081
1082 sliced->service_lines[0][i] = lcr2vbi[v >> 4];
1083 sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
1084 sliced->service_set |=
1085 sliced->service_lines[0][i] | sliced->service_lines[1][i];
1086 }
1087 return 0;
1088}
1089
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001090static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
1091{
1092 saa711x_set_lcr(sd, NULL);
1093 return 0;
1094}
1095
1096static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
1097{
1098 saa711x_set_lcr(sd, fmt);
1099 return 0;
1100}
1101
Hans Verkuilc463d932010-05-09 09:47:23 -03001102static int saa711x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
1103{
1104 if (fmt->code != V4L2_MBUS_FMT_FIXED)
1105 return -EINVAL;
1106 fmt->field = V4L2_FIELD_INTERLACED;
1107 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1108 return saa711x_set_size(sd, fmt->width, fmt->height);
1109}
1110
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001111/* Decode the sliced VBI data stream as created by the saa7115.
1112 The format is described in the saa7115 datasheet in Tables 25 and 26
1113 and in Figure 33.
1114 The current implementation uses SAV/EAV codes and not the ancillary data
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001115 headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001116 code. */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001117static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001118{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001119 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001120 static const char vbi_no_data_pattern[] = {
1121 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
1122 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001123 u8 *p = vbi->p;
1124 u32 wss;
1125 int id1, id2; /* the ID1 and ID2 bytes from the internal header */
1126
1127 vbi->type = 0; /* mark result as a failure */
1128 id1 = p[2];
1129 id2 = p[3];
1130 /* Note: the field bit is inverted for 60 Hz video */
1131 if (state->std & V4L2_STD_525_60)
1132 id1 ^= 0x40;
1133
1134 /* Skip internal header, p now points to the start of the payload */
1135 p += 4;
1136 vbi->p = p;
1137
1138 /* calculate field and line number of the VBI packet (1-23) */
1139 vbi->is_second_field = ((id1 & 0x40) != 0);
1140 vbi->line = (id1 & 0x3f) << 3;
1141 vbi->line |= (id2 & 0x70) >> 4;
1142
1143 /* Obtain data type */
1144 id2 &= 0xf;
1145
1146 /* If the VBI slicer does not detect any signal it will fill up
1147 the payload buffer with 0xa0 bytes. */
1148 if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001149 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001150
1151 /* decode payloads */
1152 switch (id2) {
1153 case 1:
Hans Verkuil9bc74002006-03-29 18:02:51 -03001154 vbi->type = V4L2_SLICED_TELETEXT_B;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001155 break;
1156 case 4:
Mauro Carvalho Chehab59ba9152006-08-30 05:34:36 -03001157 if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001158 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001159 vbi->type = V4L2_SLICED_CAPTION_525;
1160 break;
1161 case 5:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001162 wss = saa711x_decode_wss(p);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001163 if (wss == -1)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001164 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001165 p[0] = wss & 0xff;
1166 p[1] = wss >> 8;
1167 vbi->type = V4L2_SLICED_WSS_625;
1168 break;
1169 case 7:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001170 if (saa711x_decode_vps(p, p) != 0)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001171 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001172 vbi->type = V4L2_SLICED_VPS;
1173 break;
1174 default:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001175 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001176 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001177 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001178}
1179
1180/* ============ SAA7115 AUDIO settings (end) ============= */
1181
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001182static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001183{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001184 struct saa711x_state *state = to_state(sd);
1185 int status;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001186
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001187 if (state->radio)
1188 return 0;
1189 status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001190
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001191 v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status);
1192 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1193 return 0;
1194}
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001195
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001196static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1197{
1198 struct saa711x_state *state = to_state(sd);
1199
1200 state->radio = 0;
1201 saa711x_set_v4lstd(sd, std);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001202 return 0;
1203}
1204
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001205static int saa711x_s_radio(struct v4l2_subdev *sd)
1206{
1207 struct saa711x_state *state = to_state(sd);
1208
1209 state->radio = 1;
1210 return 0;
1211}
1212
Hans Verkuil5325b422009-04-02 11:26:22 -03001213static int saa711x_s_routing(struct v4l2_subdev *sd,
1214 u32 input, u32 output, u32 config)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001215{
1216 struct saa711x_state *state = to_state(sd);
Hans Verkuil340dde82010-02-20 08:07:51 -03001217 u8 mask = (state->ident <= V4L2_IDENT_SAA7111A) ? 0xf8 : 0xf0;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001218
Hans Verkuil5325b422009-04-02 11:26:22 -03001219 v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n",
1220 input, output);
1221
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001222 /* saa7111/3 does not have these inputs */
Hans Verkuil340dde82010-02-20 08:07:51 -03001223 if (state->ident <= V4L2_IDENT_SAA7113 &&
Hans Verkuil5325b422009-04-02 11:26:22 -03001224 (input == SAA7115_COMPOSITE4 ||
1225 input == SAA7115_COMPOSITE5)) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001226 return -EINVAL;
1227 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001228 if (input > SAA7115_SVIDEO3)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001229 return -EINVAL;
Hans Verkuil5325b422009-04-02 11:26:22 -03001230 if (state->input == input && state->output == output)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001231 return 0;
1232 v4l2_dbg(1, debug, sd, "now setting %s input %s output\n",
Hans Verkuil5325b422009-04-02 11:26:22 -03001233 (input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite",
1234 (output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
1235 state->input = input;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001236
1237 /* saa7111 has slightly different input numbering */
Hans Verkuil340dde82010-02-20 08:07:51 -03001238 if (state->ident <= V4L2_IDENT_SAA7111A) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001239 if (input >= SAA7115_COMPOSITE4)
1240 input -= 2;
1241 /* saa7111 specific */
1242 saa711x_write(sd, R_10_CHROMA_CNTL_2,
1243 (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001244 ((output & 0xc0) ^ 0x40));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001245 saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL,
1246 (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001247 ((output & 2) ? 0x0a : 0));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001248 }
1249
1250 /* select mode */
1251 saa711x_write(sd, R_02_INPUT_CNTL_1,
1252 (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) |
1253 input);
1254
1255 /* bypass chrominance trap for S-Video modes */
1256 saa711x_write(sd, R_09_LUMA_CNTL,
1257 (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) |
1258 (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
1259
Hans Verkuil5325b422009-04-02 11:26:22 -03001260 state->output = output;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001261 if (state->ident == V4L2_IDENT_SAA7114 ||
1262 state->ident == V4L2_IDENT_SAA7115) {
1263 saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
1264 (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
1265 (state->output & 0x01));
1266 }
Hans Verkuila0fc5882013-03-08 11:22:03 -03001267 if (state->ident > V4L2_IDENT_SAA7111A) {
1268 if (config & SAA7115_IDQ_IS_DEFAULT)
1269 saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x20);
1270 else
1271 saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x21);
1272 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001273 return 0;
1274}
1275
1276static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val)
1277{
1278 struct saa711x_state *state = to_state(sd);
1279
Hans Verkuil340dde82010-02-20 08:07:51 -03001280 if (state->ident > V4L2_IDENT_SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001281 return -EINVAL;
1282 saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) |
1283 (val ? 0x80 : 0));
1284 return 0;
1285}
1286
1287static int saa711x_s_stream(struct v4l2_subdev *sd, int enable)
1288{
1289 struct saa711x_state *state = to_state(sd);
1290
1291 v4l2_dbg(1, debug, sd, "%s output\n",
1292 enable ? "enable" : "disable");
1293
Hans Verkuil674a3232009-02-18 12:22:16 -03001294 if (state->enable == enable)
1295 return 0;
1296 state->enable = enable;
1297 if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED))
1298 return 0;
1299 saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001300 return 0;
1301}
1302
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001303static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001304{
1305 struct saa711x_state *state = to_state(sd);
1306
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001307 if (freq != SAA7115_FREQ_32_11_MHZ && freq != SAA7115_FREQ_24_576_MHZ)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001308 return -EINVAL;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001309 state->crystal_freq = freq;
Hans Verkuil15890372013-03-11 03:47:25 -03001310 state->double_asclk = flags & SAA7115_FREQ_FL_DOUBLE_ASCLK;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001311 state->cgcdiv = (flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
Hans Verkuil15890372013-03-11 03:47:25 -03001312 state->ucgc = flags & SAA7115_FREQ_FL_UCGC;
1313 state->apll = flags & SAA7115_FREQ_FL_APLL;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001314 saa711x_s_clock_freq(sd, state->audclk_freq);
1315 return 0;
1316}
1317
1318static int saa711x_reset(struct v4l2_subdev *sd, u32 val)
1319{
1320 v4l2_dbg(1, debug, sd, "decoder RESET\n");
1321 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
1322 return 0;
1323}
1324
1325static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data)
1326{
1327 /* Note: the internal field ID is inverted for NTSC,
1328 so data->field 0 maps to the saa7115 even field,
1329 whereas for PAL it maps to the saa7115 odd field. */
1330 switch (data->id) {
1331 case V4L2_SLICED_WSS_625:
1332 if (saa711x_read(sd, 0x6b) & 0xc0)
1333 return -EIO;
1334 data->data[0] = saa711x_read(sd, 0x6c);
1335 data->data[1] = saa711x_read(sd, 0x6d);
1336 return 0;
1337 case V4L2_SLICED_CAPTION_525:
1338 if (data->field == 0) {
1339 /* CC */
1340 if (saa711x_read(sd, 0x66) & 0x30)
1341 return -EIO;
1342 data->data[0] = saa711x_read(sd, 0x69);
1343 data->data[1] = saa711x_read(sd, 0x6a);
1344 return 0;
1345 }
1346 /* XDS */
1347 if (saa711x_read(sd, 0x66) & 0xc0)
1348 return -EIO;
1349 data->data[0] = saa711x_read(sd, 0x67);
1350 data->data[1] = saa711x_read(sd, 0x68);
1351 return 0;
1352 default:
1353 return -EINVAL;
1354 }
1355}
1356
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001357static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
1358{
1359 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001360 int reg1f, reg1e;
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001361
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001362 /*
1363 * The V4L2 core already initializes std with all supported
1364 * Standards. All driver needs to do is to mask it, to remove
1365 * standards that don't apply from the mask
1366 */
1367
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001368 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuilc875dee2013-03-10 09:59:37 -03001369
1370 if (state->ident == V4L2_IDENT_SAA7115) {
1371 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1372
1373 v4l2_dbg(1, debug, sd, "Status byte 1 (0x1e)=0x%02x\n", reg1e);
1374
1375 switch (reg1e & 0x03) {
1376 case 1:
1377 *std &= V4L2_STD_NTSC;
1378 break;
1379 case 2:
1380 /*
1381 * V4L2_STD_PAL just cover the european PAL standards.
1382 * This is wrong, as the device could also be using an
1383 * other PAL standard.
1384 */
1385 *std &= V4L2_STD_PAL | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc |
1386 V4L2_STD_PAL_M | V4L2_STD_PAL_60;
1387 break;
1388 case 3:
1389 *std &= V4L2_STD_SECAM;
1390 break;
1391 default:
1392 /* Can't detect anything */
1393 break;
1394 }
1395 }
1396
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001397 v4l2_dbg(1, debug, sd, "Status byte 2 (0x1f)=0x%02x\n", reg1f);
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001398
1399 /* horizontal/vertical not locked */
1400 if (reg1f & 0x40)
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001401 goto ret;
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001402
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001403 if (reg1f & 0x20)
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001404 *std &= V4L2_STD_525_60;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001405 else
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001406 *std &= V4L2_STD_625_50;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001407
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001408ret:
1409 v4l2_dbg(1, debug, sd, "detected std mask = %08Lx\n", *std);
1410
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001411 return 0;
1412}
1413
1414static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status)
1415{
1416 struct saa711x_state *state = to_state(sd);
1417 int reg1e = 0x80;
1418 int reg1f;
1419
1420 *status = V4L2_IN_ST_NO_SIGNAL;
1421 if (state->ident == V4L2_IDENT_SAA7115)
1422 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1423 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1424 if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80)
1425 *status = 0;
1426 return 0;
1427}
1428
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001429#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001430static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001431{
1432 struct i2c_client *client = v4l2_get_subdevdata(sd);
1433
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001434 if (!v4l2_chip_match_i2c_client(client, &reg->match))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001435 return -EINVAL;
1436 if (!capable(CAP_SYS_ADMIN))
1437 return -EPERM;
1438 reg->val = saa711x_read(sd, reg->reg & 0xff);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001439 reg->size = 1;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001440 return 0;
1441}
1442
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001443static int saa711x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001444{
1445 struct i2c_client *client = v4l2_get_subdevdata(sd);
1446
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001447 if (!v4l2_chip_match_i2c_client(client, &reg->match))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001448 return -EINVAL;
1449 if (!capable(CAP_SYS_ADMIN))
1450 return -EPERM;
1451 saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff);
1452 return 0;
1453}
1454#endif
1455
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001456static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001457{
1458 struct saa711x_state *state = to_state(sd);
1459 struct i2c_client *client = v4l2_get_subdevdata(sd);
1460
1461 return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0);
1462}
1463
1464static int saa711x_log_status(struct v4l2_subdev *sd)
1465{
1466 struct saa711x_state *state = to_state(sd);
1467 int reg1e, reg1f;
1468 int signalOk;
1469 int vcr;
1470
1471 v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq);
1472 if (state->ident != V4L2_IDENT_SAA7115) {
1473 /* status for the saa7114 */
1474 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1475 signalOk = (reg1f & 0xc1) == 0x81;
1476 v4l2_info(sd, "Video signal: %s\n", signalOk ? "ok" : "bad");
1477 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1478 return 0;
1479 }
1480
1481 /* status for the saa7115 */
1482 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1483 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1484
1485 signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
1486 vcr = !(reg1f & 0x10);
1487
1488 if (state->input >= 6)
1489 v4l2_info(sd, "Input: S-Video %d\n", state->input - 6);
1490 else
1491 v4l2_info(sd, "Input: Composite %d\n", state->input);
1492 v4l2_info(sd, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
1493 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1494
1495 switch (reg1e & 0x03) {
1496 case 1:
1497 v4l2_info(sd, "Detected format: NTSC\n");
1498 break;
1499 case 2:
1500 v4l2_info(sd, "Detected format: PAL\n");
1501 break;
1502 case 3:
1503 v4l2_info(sd, "Detected format: SECAM\n");
1504 break;
1505 default:
1506 v4l2_info(sd, "Detected format: BW/No color\n");
1507 break;
1508 }
1509 v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height);
Hans Verkuile3560542010-05-24 10:00:52 -03001510 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001511 return 0;
1512}
1513
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001514/* ----------------------------------------------------------------------- */
1515
Hans Verkuile3560542010-05-24 10:00:52 -03001516static const struct v4l2_ctrl_ops saa711x_ctrl_ops = {
1517 .s_ctrl = saa711x_s_ctrl,
1518 .g_volatile_ctrl = saa711x_g_volatile_ctrl,
1519};
1520
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001521static const struct v4l2_subdev_core_ops saa711x_core_ops = {
1522 .log_status = saa711x_log_status,
1523 .g_chip_ident = saa711x_g_chip_ident,
Hans Verkuile3560542010-05-24 10:00:52 -03001524 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
1525 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
1526 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
1527 .g_ctrl = v4l2_subdev_g_ctrl,
1528 .s_ctrl = v4l2_subdev_s_ctrl,
1529 .queryctrl = v4l2_subdev_queryctrl,
1530 .querymenu = v4l2_subdev_querymenu,
Hans Verkuilf41737e2009-04-01 03:52:39 -03001531 .s_std = saa711x_s_std,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001532 .reset = saa711x_reset,
1533 .s_gpio = saa711x_s_gpio,
1534#ifdef CONFIG_VIDEO_ADV_DEBUG
1535 .g_register = saa711x_g_register,
1536 .s_register = saa711x_s_register,
1537#endif
1538};
1539
1540static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001541 .s_radio = saa711x_s_radio,
1542 .g_tuner = saa711x_g_tuner,
1543};
1544
1545static const struct v4l2_subdev_audio_ops saa711x_audio_ops = {
1546 .s_clock_freq = saa711x_s_clock_freq,
1547};
1548
1549static const struct v4l2_subdev_video_ops saa711x_video_ops = {
1550 .s_routing = saa711x_s_routing,
1551 .s_crystal_freq = saa711x_s_crystal_freq,
Hans Verkuilc463d932010-05-09 09:47:23 -03001552 .s_mbus_fmt = saa711x_s_mbus_fmt,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001553 .s_stream = saa711x_s_stream,
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001554 .querystd = saa711x_querystd,
1555 .g_input_status = saa711x_g_input_status,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001556};
1557
Hans Verkuil32cd5272010-03-14 09:57:30 -03001558static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = {
1559 .g_vbi_data = saa711x_g_vbi_data,
1560 .decode_vbi_line = saa711x_decode_vbi_line,
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001561 .g_sliced_fmt = saa711x_g_sliced_fmt,
1562 .s_sliced_fmt = saa711x_s_sliced_fmt,
1563 .s_raw_fmt = saa711x_s_raw_fmt,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001564};
1565
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001566static const struct v4l2_subdev_ops saa711x_ops = {
1567 .core = &saa711x_core_ops,
1568 .tuner = &saa711x_tuner_ops,
1569 .audio = &saa711x_audio_ops,
1570 .video = &saa711x_video_ops,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001571 .vbi = &saa711x_vbi_ops,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001572};
1573
1574/* ----------------------------------------------------------------------- */
1575
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001576/**
1577 * saa711x_detect_chip - Detects the saa711x (or clone) variant
1578 * @client: I2C client structure.
1579 * @id: I2C device ID structure.
1580 * @name: Name of the device to be filled.
1581 * @size: Size of the name var.
1582 *
1583 * Detects the Philips/NXP saa711x chip, or some clone of it.
1584 * if 'id' is NULL or id->driver_data is equal to 1, it auto-probes
1585 * the analog demod.
1586 * If the tuner is not found, it returns -ENODEV.
1587 * If auto-detection is disabled and the tuner doesn't match what it was
1588 * requred, it returns -EINVAL and fills 'name'.
1589 * If the chip is found, it returns the chip ID and fills 'name'.
1590 */
1591static int saa711x_detect_chip(struct i2c_client *client,
1592 const struct i2c_device_id *id,
1593 char *name, unsigned size)
1594{
1595 char chip_ver[size - 1];
1596 char chip_id;
1597 int i;
1598 int autodetect;
1599
1600 autodetect = !id || id->driver_data == 1;
1601
1602 /* Read the chip version register */
1603 for (i = 0; i < size - 1; i++) {
1604 i2c_smbus_write_byte_data(client, 0, i);
1605 chip_ver[i] = i2c_smbus_read_byte_data(client, 0);
1606 name[i] = (chip_ver[i] & 0x0f) + '0';
1607 if (name[i] > '9')
1608 name[i] += 'a' - '9' - 1;
1609 }
1610 name[i] = '\0';
1611
1612 /* Check if it is a Philips/NXP chip */
1613 if (!memcmp(name + 1, "f711", 4)) {
1614 chip_id = name[5];
1615 snprintf(name, size, "saa711%c", chip_id);
1616
1617 if (!autodetect && strcmp(name, id->name))
1618 return -EINVAL;
1619
1620 switch (chip_id) {
1621 case '1':
1622 if (chip_ver[0] & 0xf0) {
1623 snprintf(name, size, "saa711%ca", chip_id);
1624 v4l_info(client, "saa7111a variant found\n");
1625 return V4L2_IDENT_SAA7111A;
1626 }
1627 return V4L2_IDENT_SAA7111;
1628 case '3':
1629 return V4L2_IDENT_SAA7113;
1630 case '4':
1631 return V4L2_IDENT_SAA7114;
1632 case '5':
1633 return V4L2_IDENT_SAA7115;
1634 case '8':
1635 return V4L2_IDENT_SAA7118;
1636 default:
1637 v4l2_info(client,
1638 "WARNING: Philips/NXP chip unknown - Falling back to saa7111\n");
1639 return V4L2_IDENT_SAA7111;
1640 }
1641 }
1642
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001643 /* Check if it is a gm7113c */
1644 if (!memcmp(name, "0000", 4)) {
1645 chip_id = 0;
1646 for (i = 0; i < 4; i++) {
1647 chip_id = chip_id << 1;
1648 chip_id |= (chip_ver[i] & 0x80) ? 1 : 0;
1649 }
1650
1651 /*
1652 * Note: From the datasheet, only versions 1 and 2
1653 * exists. However, tests on a device labeled as:
1654 * "GM7113C 1145" returned "10" on all 16 chip
1655 * version (reg 0x00) reads. So, we need to also
1656 * accept at least verion 0. For now, let's just
1657 * assume that a device that returns "0000" for
1658 * the lower nibble is a gm7113c.
1659 */
1660
1661 strlcpy(name, "gm7113c", size);
1662
1663 if (!autodetect && strcmp(name, id->name))
1664 return -EINVAL;
1665
1666 v4l_dbg(1, debug, client,
1667 "It seems to be a %s chip (%*ph) @ 0x%x.\n",
1668 name, 16, chip_ver, client->addr << 1);
1669
1670 return V4L2_IDENT_GM7113C;
1671 }
1672
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001673 /* Chip was not discovered. Return its ID and don't bind */
1674 v4l_dbg(1, debug, client, "chip %*ph @ 0x%x is unknown.\n",
1675 16, chip_ver, client->addr << 1);
1676 return -ENODEV;
1677}
1678
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001679static int saa711x_probe(struct i2c_client *client,
Jean Delvared2653e92008-04-29 23:11:39 +02001680 const struct i2c_device_id *id)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001681{
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001682 struct saa711x_state *state;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001683 struct v4l2_subdev *sd;
Hans Verkuile3560542010-05-24 10:00:52 -03001684 struct v4l2_ctrl_handler *hdl;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001685 int ident;
Hans Verkuile3560542010-05-24 10:00:52 -03001686 char name[17];
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001687
1688 /* Check if the adapter supports the needed features */
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001689 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
Hans Verkuil188f3452007-09-16 10:47:15 -03001690 return -EIO;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001691
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001692 ident = saa711x_detect_chip(client, id, name, sizeof(name));
1693 if (ident == -EINVAL) {
1694 /* Chip exists, but doesn't match */
1695 v4l_warn(client, "found %s while %s was expected\n",
1696 name, id->name);
Hans Verkuil188f3452007-09-16 10:47:15 -03001697 return -ENODEV;
Hans Verkuilf7668162006-11-25 09:40:28 -03001698 }
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001699 if (ident < 0)
1700 return ident;
Hans Verkuilf7668162006-11-25 09:40:28 -03001701
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001702 if (ident == V4L2_IDENT_GM7113C) {
1703 v4l_warn(client, "%s not yet supported\n", name);
1704 return -ENODEV;
1705 }
1706
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001707 strlcpy(client->name, name, sizeof(client->name));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001708
Laurent Pinchartc02b2112013-05-02 08:29:43 -03001709 state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
Hans Verkuilc5bf2042008-09-03 17:12:09 -03001710 if (state == NULL)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001711 return -ENOMEM;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001712 sd = &state->sd;
1713 v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
Hans Verkuile3560542010-05-24 10:00:52 -03001714
1715 hdl = &state->hdl;
1716 v4l2_ctrl_handler_init(hdl, 6);
1717 /* add in ascending ID order */
1718 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1719 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1720 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1721 V4L2_CID_CONTRAST, 0, 127, 1, 64);
1722 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1723 V4L2_CID_SATURATION, 0, 127, 1, 64);
1724 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1725 V4L2_CID_HUE, -128, 127, 1, 0);
1726 state->agc = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1727 V4L2_CID_CHROMA_AGC, 0, 1, 1, 1);
1728 state->gain = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1729 V4L2_CID_CHROMA_GAIN, 0, 127, 1, 40);
Hans Verkuile3560542010-05-24 10:00:52 -03001730 sd->ctrl_handler = hdl;
1731 if (hdl->error) {
1732 int err = hdl->error;
1733
1734 v4l2_ctrl_handler_free(hdl);
Hans Verkuile3560542010-05-24 10:00:52 -03001735 return err;
1736 }
Hans Verkuil6f43dbf2011-08-26 08:46:29 -03001737 v4l2_ctrl_auto_cluster(2, &state->agc, 0, true);
Hans Verkuile3560542010-05-24 10:00:52 -03001738
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001739 state->input = -1;
Marco Schluessler4cbca182007-01-21 19:43:38 -03001740 state->output = SAA7115_IPORT_ON;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001741 state->enable = 1;
Hans Verkuil3faeeae2006-01-09 15:25:44 -02001742 state->radio = 0;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001743 state->ident = ident;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001744
Hans Verkuil3578d3d2006-01-09 15:25:41 -02001745 state->audclk_freq = 48000;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001746
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001747 v4l2_dbg(1, debug, sd, "writing init values\n");
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001748
1749 /* init to 60hz/48khz */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001750 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
1751 switch (state->ident) {
1752 case V4L2_IDENT_SAA7111:
Hans Verkuil340dde82010-02-20 08:07:51 -03001753 case V4L2_IDENT_SAA7111A:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001754 saa711x_writeregs(sd, saa7111_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001755 break;
1756 case V4L2_IDENT_SAA7113:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001757 saa711x_writeregs(sd, saa7113_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001758 break;
1759 default:
Hans Verkuilb7f82922006-04-02 12:50:42 -03001760 state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001761 saa711x_writeregs(sd, saa7115_init_auto_input);
Hans Verkuilb7f82922006-04-02 12:50:42 -03001762 }
Hans Verkuil340dde82010-02-20 08:07:51 -03001763 if (state->ident > V4L2_IDENT_SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001764 saa711x_writeregs(sd, saa7115_init_misc);
1765 saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
Hans Verkuile3560542010-05-24 10:00:52 -03001766 v4l2_ctrl_handler_setup(hdl);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001767
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001768 v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n",
1769 saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC),
1770 saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001771 return 0;
1772}
1773
1774/* ----------------------------------------------------------------------- */
1775
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001776static int saa711x_remove(struct i2c_client *client)
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001777{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001778 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1779
1780 v4l2_device_unregister_subdev(sd);
Hans Verkuile3560542010-05-24 10:00:52 -03001781 v4l2_ctrl_handler_free(sd->ctrl_handler);
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001782 return 0;
1783}
1784
Hans Verkuilaac23532010-09-15 15:04:55 -03001785static const struct i2c_device_id saa711x_id[] = {
Hans Verkuil9edd350f2008-07-17 13:22:51 -03001786 { "saa7115_auto", 1 }, /* autodetect */
Jean Delvareaf294862008-05-18 20:49:40 +02001787 { "saa7111", 0 },
1788 { "saa7113", 0 },
1789 { "saa7114", 0 },
1790 { "saa7115", 0 },
1791 { "saa7118", 0 },
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001792 { "gm7113c", 0 },
Jean Delvareaf294862008-05-18 20:49:40 +02001793 { }
1794};
Hans Verkuilaac23532010-09-15 15:04:55 -03001795MODULE_DEVICE_TABLE(i2c, saa711x_id);
Jean Delvareaf294862008-05-18 20:49:40 +02001796
Hans Verkuilaac23532010-09-15 15:04:55 -03001797static struct i2c_driver saa711x_driver = {
1798 .driver = {
1799 .owner = THIS_MODULE,
1800 .name = "saa7115",
1801 },
1802 .probe = saa711x_probe,
1803 .remove = saa711x_remove,
1804 .id_table = saa711x_id,
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001805};
Hans Verkuilaac23532010-09-15 15:04:55 -03001806
Axel Linc6e8d862012-02-12 06:56:32 -03001807module_i2c_driver(saa711x_driver);