blob: be32688797e129ef53427e22dd4e65ce151748db [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) {
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300130 case V4L2_IDENT_GM7113C:
131 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && reg < 0x20;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300132 case V4L2_IDENT_SAA7113:
133 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
134 reg != 0x5d && reg < 0x63;
135 case V4L2_IDENT_SAA7114:
136 return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
137 (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
138 reg != 0x81 && reg < 0xf0;
139 case V4L2_IDENT_SAA7115:
140 return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe);
141 case V4L2_IDENT_SAA7118:
142 return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
143 (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
144 (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
145 }
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300146 return 1;
147}
148
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300149static int saa711x_writeregs(struct v4l2_subdev *sd, const unsigned char *regs)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800150{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300151 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800152 unsigned char reg, data;
153
154 while (*regs != 0x00) {
155 reg = *(regs++);
156 data = *(regs++);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300157
158 /* According with datasheets, reserved regs should be
159 filled with 0 - seems better not to touch on they */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300160 if (saa711x_has_reg(state->ident, reg)) {
161 if (saa711x_write(sd, reg, data) < 0)
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300162 return -1;
Mauro Carvalho Chehabd87edf22006-09-01 09:37:11 -0300163 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300164 v4l2_dbg(1, debug, sd, "tried to access reserved reg 0x%02x\n", reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300165 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800166 }
167 return 0;
168}
169
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300170static inline int saa711x_read(struct v4l2_subdev *sd, u8 reg)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800171{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300172 struct i2c_client *client = v4l2_get_subdevdata(sd);
173
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800174 return i2c_smbus_read_byte_data(client, reg);
175}
176
177/* ----------------------------------------------------------------------- */
178
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300179/* SAA7111 initialization table */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300180static const unsigned char saa7111_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300181 R_01_INC_DELAY, 0x00, /* reserved */
182
183 /*front end */
184 R_02_INPUT_CNTL_1, 0xd0, /* FUSE=3, GUDL=2, MODE=0 */
185 R_03_INPUT_CNTL_2, 0x23, /* HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0,
186 * GAFIX=0, GAI1=256, GAI2=256 */
187 R_04_INPUT_CNTL_3, 0x00, /* GAI1=256 */
188 R_05_INPUT_CNTL_4, 0x00, /* GAI2=256 */
189
190 /* decoder */
191 R_06_H_SYNC_START, 0xf3, /* HSB at 13(50Hz) / 17(60Hz)
192 * pixels after end of last line */
193 R_07_H_SYNC_STOP, 0xe8, /* HSS seems to be needed to
194 * work with NTSC, too */
195 R_08_SYNC_CNTL, 0xc8, /* AUFD=1, FSEL=1, EXFIL=0,
196 * VTRC=1, HPLL=0, VNOI=0 */
197 R_09_LUMA_CNTL, 0x01, /* BYPS=0, PREF=0, BPSS=0,
198 * VBLB=0, UPTCV=0, APER=1 */
199 R_0A_LUMA_BRIGHT_CNTL, 0x80,
200 R_0B_LUMA_CONTRAST_CNTL, 0x47, /* 0b - CONT=1.109 */
201 R_0C_CHROMA_SAT_CNTL, 0x40,
202 R_0D_CHROMA_HUE_CNTL, 0x00,
203 R_0E_CHROMA_CNTL_1, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0,
204 * FCTC=0, CHBW=1 */
205 R_0F_CHROMA_GAIN_CNTL, 0x00, /* reserved */
206 R_10_CHROMA_CNTL_2, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
207 R_11_MODE_DELAY_CNTL, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
208 * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
209 R_12_RT_SIGNAL_CNTL, 0x00, /* 12 - output control 2 */
210 R_13_RT_X_PORT_OUT_CNTL, 0x00, /* 13 - output control 3 */
211 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
212 R_15_VGATE_START_FID_CHG, 0x00,
213 R_16_VGATE_STOP, 0x00,
214 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
215
216 0x00, 0x00
217};
218
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300219/* SAA7113/GM7113C init codes
220 * It's important that R_14... R_17 == 0x00
221 * for the gm7113c chip to deliver stable video
222 */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300223static const unsigned char saa7113_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300224 R_01_INC_DELAY, 0x08,
225 R_02_INPUT_CNTL_1, 0xc2,
226 R_03_INPUT_CNTL_2, 0x30,
227 R_04_INPUT_CNTL_3, 0x00,
228 R_05_INPUT_CNTL_4, 0x00,
229 R_06_H_SYNC_START, 0x89,
230 R_07_H_SYNC_STOP, 0x0d,
231 R_08_SYNC_CNTL, 0x88,
232 R_09_LUMA_CNTL, 0x01,
233 R_0A_LUMA_BRIGHT_CNTL, 0x80,
234 R_0B_LUMA_CONTRAST_CNTL, 0x47,
235 R_0C_CHROMA_SAT_CNTL, 0x40,
236 R_0D_CHROMA_HUE_CNTL, 0x00,
237 R_0E_CHROMA_CNTL_1, 0x01,
238 R_0F_CHROMA_GAIN_CNTL, 0x2a,
239 R_10_CHROMA_CNTL_2, 0x08,
240 R_11_MODE_DELAY_CNTL, 0x0c,
241 R_12_RT_SIGNAL_CNTL, 0x07,
242 R_13_RT_X_PORT_OUT_CNTL, 0x00,
243 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
244 R_15_VGATE_START_FID_CHG, 0x00,
245 R_16_VGATE_STOP, 0x00,
246 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
247
248 0x00, 0x00
249};
250
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800251/* If a value differs from the Hauppauge driver values, then the comment starts with
252 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
253 Hauppauge driver sets. */
254
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300255/* SAA7114 and SAA7115 initialization table */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800256static const unsigned char saa7115_init_auto_input[] = {
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300257 /* Front-End Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300258 R_01_INC_DELAY, 0x48, /* white peak control disabled */
259 R_03_INPUT_CNTL_2, 0x20, /* was 0x30. 0x20: long vertical blanking */
260 R_04_INPUT_CNTL_3, 0x90, /* analog gain set to 0 */
261 R_05_INPUT_CNTL_4, 0x90, /* analog gain set to 0 */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300262 /* Decoder Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300263 R_06_H_SYNC_START, 0xeb, /* horiz sync begin = -21 */
264 R_07_H_SYNC_STOP, 0xe0, /* horiz sync stop = -17 */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300265 R_09_LUMA_CNTL, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300266 R_0A_LUMA_BRIGHT_CNTL, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */
267 R_0B_LUMA_CONTRAST_CNTL, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */
268 R_0C_CHROMA_SAT_CNTL, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */
269 R_0D_CHROMA_HUE_CNTL, 0x00,
270 R_0F_CHROMA_GAIN_CNTL, 0x00, /* use automatic gain */
271 R_10_CHROMA_CNTL_2, 0x06, /* chroma: active adaptive combfilter */
272 R_11_MODE_DELAY_CNTL, 0x00,
273 R_12_RT_SIGNAL_CNTL, 0x9d, /* RTS0 output control: VGATE */
274 R_13_RT_X_PORT_OUT_CNTL, 0x80, /* ITU656 standard mode, RTCO output enable RTCE */
275 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
276 R_18_RAW_DATA_GAIN_CNTL, 0x40, /* gain 0x00 = nominal */
277 R_19_RAW_DATA_OFF_CNTL, 0x80,
278 R_1A_COLOR_KILL_LVL_CNTL, 0x77, /* recommended value */
279 R_1B_MISC_TVVCRDET, 0x42, /* recommended value */
280 R_1C_ENHAN_COMB_CTRL1, 0xa9, /* recommended value */
281 R_1D_ENHAN_COMB_CTRL2, 0x01, /* recommended value */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300282
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300283
284 R_80_GLOBAL_CNTL_1, 0x0, /* No tasks enabled at init */
285
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300286 /* Power Device Control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300287 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset device */
288 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* set device programmed, all in operational mode */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800289 0x00, 0x00
290};
291
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300292/* Used to reset saa7113, saa7114 and saa7115 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800293static const unsigned char saa7115_cfg_reset_scaler[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300294 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00, /* disable I-port output */
295 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
296 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
297 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* enable I-port output */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800298 0x00, 0x00
299};
300
301/* ============== SAA7715 VIDEO templates ============= */
302
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800303static const unsigned char saa7115_cfg_60hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300304 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
305 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800306
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300307 R_15_VGATE_START_FID_CHG, 0x03,
308 R_16_VGATE_STOP, 0x11,
309 R_17_MISC_VGATE_CONF_AND_MSB, 0x9c,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800310
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300311 R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
312 R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800313
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300314 R_5A_V_OFF_FOR_SLICER, 0x06, /* standard 60hz value for ITU656 line counting */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800315
316 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300317 R_90_A_TASK_HANDLING_CNTL, 0x80,
318 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
319 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
320 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
321
322 /* hoffset low (input), 0x0002 is minimum */
323 R_94_A_HORIZ_INPUT_WINDOW_START, 0x01,
324 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
325
326 /* hsize low (input), 0x02d0 = 720 */
327 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
328 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
329
330 R_98_A_VERT_INPUT_WINDOW_START, 0x05,
331 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
332
333 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x0c,
334 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
335
336 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
337 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
338
339 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x0c,
340 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800341
342 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300343 R_C0_B_TASK_HANDLING_CNTL, 0x00,
344 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
345 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
346 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800347
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300348 /* 0x0002 is minimum */
349 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x02,
350 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800351
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300352 /* 0x02d0 = 720 */
353 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
354 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
355
356 /* vwindow start 0x12 = 18 */
357 R_C8_B_VERT_INPUT_WINDOW_START, 0x12,
358 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
359
360 /* vwindow length 0xf8 = 248 */
Mauro Carvalho Chehab97d9e802006-09-03 09:38:11 -0300361 R_CA_B_VERT_INPUT_WINDOW_LENGTH, VRES_60HZ>>1,
362 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, VRES_60HZ>>9,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300363
364 /* hwindow 0x02d0 = 720 */
365 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
366 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
367
368 R_F0_LFCO_PER_LINE, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
369 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0 */
370 R_F5_PULSGEN_LINE_LENGTH, 0xad,
371 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
372
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800373 0x00, 0x00
374};
375
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800376static const unsigned char saa7115_cfg_50hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300377 R_80_GLOBAL_CNTL_1, 0x00,
378 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800379
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300380 R_15_VGATE_START_FID_CHG, 0x37, /* VGATE start */
381 R_16_VGATE_STOP, 0x16,
382 R_17_MISC_VGATE_CONF_AND_MSB, 0x99,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800383
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300384 R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */
385 R_0E_CHROMA_CNTL_1, 0x07,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800386
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300387 R_5A_V_OFF_FOR_SLICER, 0x03, /* standard 50hz value */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800388
389 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300390 R_90_A_TASK_HANDLING_CNTL, 0x81,
391 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
392 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
393 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
394
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800395 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
396 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300397 /* hoffset low (input), 0x0002 is minimum */
398 R_94_A_HORIZ_INPUT_WINDOW_START, 0x00,
399 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
400
401 /* hsize low (input), 0x02d0 = 720 */
402 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
403 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
404
405 R_98_A_VERT_INPUT_WINDOW_START, 0x03,
406 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
407
408 /* vsize 0x12 = 18 */
409 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x12,
410 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
411
412 /* hsize 0x05a0 = 1440 */
413 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
414 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05, /* hsize hi (output) */
415 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x12, /* vsize low (output), 0x12 = 18 */
416 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00, /* vsize hi (output) */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800417
418 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300419 R_C0_B_TASK_HANDLING_CNTL, 0x00,
420 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
421 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
422 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800423
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300424 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
425 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
426 /* hoffset low (input), 0x0002 is minimum. See comment above. */
427 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x00,
428 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800429
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300430 /* hsize 0x02d0 = 720 */
431 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
432 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
433
434 /* voffset 0x16 = 22 */
435 R_C8_B_VERT_INPUT_WINDOW_START, 0x16,
436 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
437
438 /* vsize 0x0120 = 288 */
439 R_CA_B_VERT_INPUT_WINDOW_LENGTH, 0x20,
440 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, 0x01,
441
442 /* hsize 0x02d0 = 720 */
443 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
444 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
445
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300446 R_F0_LFCO_PER_LINE, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
447 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0, (was 0x05) */
448 R_F5_PULSGEN_LINE_LENGTH, 0xb0,
449 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
450
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800451 0x00, 0x00
452};
453
454/* ============== SAA7715 VIDEO templates (end) ======= */
455
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300456/* ============== GM7113C VIDEO templates ============= */
457static const unsigned char gm7113c_cfg_60hz_video[] = {
458 R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
459 R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */
460
461 0x00, 0x00
462};
463
464static const unsigned char gm7113c_cfg_50hz_video[] = {
465 R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */
466 R_0E_CHROMA_CNTL_1, 0x07,
467
468 0x00, 0x00
469};
470
471/* ============== GM7113C VIDEO templates (end) ======= */
472
473
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800474static const unsigned char saa7115_cfg_vbi_on[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300475 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
476 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
477 R_80_GLOBAL_CNTL_1, 0x30, /* Activate both tasks */
478 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
479 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
480
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800481 0x00, 0x00
482};
483
484static const unsigned char saa7115_cfg_vbi_off[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300485 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
486 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
487 R_80_GLOBAL_CNTL_1, 0x20, /* Activate only task "B" */
488 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
489 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
490
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800491 0x00, 0x00
492};
493
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300494
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800495static const unsigned char saa7115_init_misc[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300496 R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300497 R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 0x01,
498 R_84_I_PORT_SIGNAL_DEF, 0x20,
499 R_85_I_PORT_SIGNAL_POLAR, 0x21,
500 R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT, 0xc5,
501 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800502
503 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300504 R_A0_A_HORIZ_PRESCALING, 0x01,
505 R_A1_A_ACCUMULATION_LENGTH, 0x00,
506 R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800507
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300508 /* Configure controls at nominal value*/
509 R_A4_A_LUMA_BRIGHTNESS_CNTL, 0x80,
510 R_A5_A_LUMA_CONTRAST_CNTL, 0x40,
511 R_A6_A_CHROMA_SATURATION_CNTL, 0x40,
512
513 /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
514 R_A8_A_HORIZ_LUMA_SCALING_INC, 0x00,
515 R_A9_A_HORIZ_LUMA_SCALING_INC_MSB, 0x02,
516
517 R_AA_A_HORIZ_LUMA_PHASE_OFF, 0x00,
518
519 /* must be horiz lum scaling / 2 */
520 R_AC_A_HORIZ_CHROMA_SCALING_INC, 0x00,
521 R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB, 0x01,
522
523 /* must be offset luma / 2 */
524 R_AE_A_HORIZ_CHROMA_PHASE_OFF, 0x00,
525
526 R_B0_A_VERT_LUMA_SCALING_INC, 0x00,
527 R_B1_A_VERT_LUMA_SCALING_INC_MSB, 0x04,
528
529 R_B2_A_VERT_CHROMA_SCALING_INC, 0x00,
530 R_B3_A_VERT_CHROMA_SCALING_INC_MSB, 0x04,
531
532 R_B4_A_VERT_SCALING_MODE_CNTL, 0x01,
533
534 R_B8_A_VERT_CHROMA_PHASE_OFF_00, 0x00,
535 R_B9_A_VERT_CHROMA_PHASE_OFF_01, 0x00,
536 R_BA_A_VERT_CHROMA_PHASE_OFF_10, 0x00,
537 R_BB_A_VERT_CHROMA_PHASE_OFF_11, 0x00,
538
539 R_BC_A_VERT_LUMA_PHASE_OFF_00, 0x00,
540 R_BD_A_VERT_LUMA_PHASE_OFF_01, 0x00,
541 R_BE_A_VERT_LUMA_PHASE_OFF_10, 0x00,
542 R_BF_A_VERT_LUMA_PHASE_OFF_11, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800543
544 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300545 R_D0_B_HORIZ_PRESCALING, 0x01,
546 R_D1_B_ACCUMULATION_LENGTH, 0x00,
547 R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800548
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300549 /* Configure controls at nominal value*/
550 R_D4_B_LUMA_BRIGHTNESS_CNTL, 0x80,
551 R_D5_B_LUMA_CONTRAST_CNTL, 0x40,
552 R_D6_B_CHROMA_SATURATION_CNTL, 0x40,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800553
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300554 /* hor lum scaling 0x0400 = 1 */
555 R_D8_B_HORIZ_LUMA_SCALING_INC, 0x00,
556 R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, 0x04,
557
558 R_DA_B_HORIZ_LUMA_PHASE_OFF, 0x00,
559
560 /* must be hor lum scaling / 2 */
561 R_DC_B_HORIZ_CHROMA_SCALING, 0x00,
562 R_DD_B_HORIZ_CHROMA_SCALING_MSB, 0x02,
563
564 /* must be offset luma / 2 */
565 R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA, 0x00,
566
567 R_E0_B_VERT_LUMA_SCALING_INC, 0x00,
568 R_E1_B_VERT_LUMA_SCALING_INC_MSB, 0x04,
569
570 R_E2_B_VERT_CHROMA_SCALING_INC, 0x00,
571 R_E3_B_VERT_CHROMA_SCALING_INC_MSB, 0x04,
572
573 R_E4_B_VERT_SCALING_MODE_CNTL, 0x01,
574
575 R_E8_B_VERT_CHROMA_PHASE_OFF_00, 0x00,
576 R_E9_B_VERT_CHROMA_PHASE_OFF_01, 0x00,
577 R_EA_B_VERT_CHROMA_PHASE_OFF_10, 0x00,
578 R_EB_B_VERT_CHROMA_PHASE_OFF_11, 0x00,
579
580 R_EC_B_VERT_LUMA_PHASE_OFF_00, 0x00,
581 R_ED_B_VERT_LUMA_PHASE_OFF_01, 0x00,
582 R_EE_B_VERT_LUMA_PHASE_OFF_10, 0x00,
583 R_EF_B_VERT_LUMA_PHASE_OFF_11, 0x00,
584
585 R_F2_NOMINAL_PLL2_DTO, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */
586 R_F3_PLL_INCREMENT, 0x46,
587 R_F4_PLL2_STATUS, 0x00,
588 R_F7_PULSE_A_POS_MSB, 0x4b, /* not the recommended settings! */
589 R_F8_PULSE_B_POS, 0x00,
590 R_F9_PULSE_B_POS_MSB, 0x4b,
591 R_FA_PULSE_C_POS, 0x00,
592 R_FB_PULSE_C_POS_MSB, 0x4b,
593
594 /* PLL2 lock detection settings: 71 lines 50% phase error */
595 R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES, 0x88,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800596
597 /* Turn off VBI */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300598 R_40_SLICER_CNTL_1, 0x20, /* No framing code errors allowed. */
599 R_41_LCR_BASE, 0xff,
600 R_41_LCR_BASE+1, 0xff,
601 R_41_LCR_BASE+2, 0xff,
602 R_41_LCR_BASE+3, 0xff,
603 R_41_LCR_BASE+4, 0xff,
604 R_41_LCR_BASE+5, 0xff,
605 R_41_LCR_BASE+6, 0xff,
606 R_41_LCR_BASE+7, 0xff,
607 R_41_LCR_BASE+8, 0xff,
608 R_41_LCR_BASE+9, 0xff,
609 R_41_LCR_BASE+10, 0xff,
610 R_41_LCR_BASE+11, 0xff,
611 R_41_LCR_BASE+12, 0xff,
612 R_41_LCR_BASE+13, 0xff,
613 R_41_LCR_BASE+14, 0xff,
614 R_41_LCR_BASE+15, 0xff,
615 R_41_LCR_BASE+16, 0xff,
616 R_41_LCR_BASE+17, 0xff,
617 R_41_LCR_BASE+18, 0xff,
618 R_41_LCR_BASE+19, 0xff,
619 R_41_LCR_BASE+20, 0xff,
620 R_41_LCR_BASE+21, 0xff,
621 R_41_LCR_BASE+22, 0xff,
622 R_58_PROGRAM_FRAMING_CODE, 0x40,
623 R_59_H_OFF_FOR_SLICER, 0x47,
624 R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF, 0x83,
625 R_5D_DID, 0xbd,
626 R_5E_SDID, 0x35,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800627
Devin Heitmuellerfea551f2010-02-03 00:33:48 -0300628 R_02_INPUT_CNTL_1, 0xc4, /* input tuner -> input 4, amplifier active */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800629
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300630 R_80_GLOBAL_CNTL_1, 0x20, /* enable task B */
631 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
632 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800633 0x00, 0x00
634};
635
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -0300636static int saa711x_odd_parity(u8 c)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800637{
638 c ^= (c >> 4);
639 c ^= (c >> 2);
640 c ^= (c >> 1);
641
642 return c & 1;
643}
644
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300645static int saa711x_decode_vps(u8 *dst, u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800646{
647 static const u8 biphase_tbl[] = {
648 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
649 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
650 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
651 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
652 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
653 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
654 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
655 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
656 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
657 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
658 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
659 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
660 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
661 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
662 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
663 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
664 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
665 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
666 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
667 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
668 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
669 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
670 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
671 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
672 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
673 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
674 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
675 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
676 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
677 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
678 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
679 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
680 };
681 int i;
682 u8 c, err = 0;
683
684 for (i = 0; i < 2 * 13; i += 2) {
685 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
686 c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
687 dst[i / 2] = c;
688 }
689 return err & 0xf0;
690}
691
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300692static int saa711x_decode_wss(u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800693{
694 static const int wss_bits[8] = {
695 0, 0, 0, 1, 0, 1, 1, 1
696 };
697 unsigned char parity;
698 int wss = 0;
699 int i;
700
701 for (i = 0; i < 16; i++) {
702 int b1 = wss_bits[p[i] & 7];
703 int b2 = wss_bits[(p[i] >> 3) & 7];
704
705 if (b1 == b2)
706 return -1;
707 wss |= b2 << i;
708 }
709 parity = wss & 15;
710 parity ^= parity >> 2;
711 parity ^= parity >> 1;
712
713 if (!(parity & 1))
714 return -1;
715
716 return wss;
717}
718
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300719static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800720{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300721 struct saa711x_state *state = to_state(sd);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200722 u32 acpf;
723 u32 acni;
724 u32 hz;
725 u64 f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300726 u8 acc = 0; /* reg 0x3a, audio clock control */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800727
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300728 /* Checks for chips that don't have audio clock (saa7111, saa7113) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300729 if (!saa711x_has_reg(state->ident, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300730 return 0;
731
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300732 v4l2_dbg(1, debug, sd, "set audio clock freq: %d\n", freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200733
734 /* sanity check */
735 if (freq < 32000 || freq > 48000)
736 return -EINVAL;
737
738 /* hz is the refresh rate times 100 */
739 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
740 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
741 acpf = (25600 * freq) / hz;
742 /* acni = (256 * freq * 2^23) / crystal_frequency =
743 (freq * 2^(8+23)) / crystal_frequency =
Hans Verkuilb7f82922006-04-02 12:50:42 -0300744 (freq << 31) / crystal_frequency */
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200745 f = freq;
746 f = f << 31;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300747 do_div(f, state->crystal_freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200748 acni = f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300749 if (state->ucgc) {
750 acpf = acpf * state->cgcdiv / 16;
751 acni = acni * state->cgcdiv / 16;
752 acc = 0x80;
753 if (state->cgcdiv == 3)
754 acc |= 0x40;
755 }
756 if (state->apll)
757 acc |= 0x08;
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200758
Hans Verkuil15890372013-03-11 03:47:25 -0300759 if (state->double_asclk) {
760 acpf <<= 1;
761 acni <<= 1;
762 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300763 saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
Hans Verkuil15890372013-03-11 03:47:25 -0300764 saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10 << state->double_asclk);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300765 saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300766
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300767 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
768 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300769 (acpf >> 8) & 0xff);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300770 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300771 (acpf >> 16) & 0x03);
772
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300773 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
774 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
775 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800776 state->audclk_freq = freq;
777 return 0;
778}
779
Hans Verkuile3560542010-05-24 10:00:52 -0300780static int saa711x_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800781{
Hans Verkuile3560542010-05-24 10:00:52 -0300782 struct v4l2_subdev *sd = to_sd(ctrl);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300783 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800784
785 switch (ctrl->id) {
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300786 case V4L2_CID_CHROMA_AGC:
Hans Verkuile3560542010-05-24 10:00:52 -0300787 /* chroma gain cluster */
Hans Verkuilddac5c12011-06-10 05:43:34 -0300788 if (state->agc->val)
789 state->gain->val =
Hans Verkuile3560542010-05-24 10:00:52 -0300790 saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL) & 0x7f;
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300791 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800792 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800793 return 0;
794}
795
Hans Verkuile3560542010-05-24 10:00:52 -0300796static int saa711x_s_ctrl(struct v4l2_ctrl *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800797{
Hans Verkuile3560542010-05-24 10:00:52 -0300798 struct v4l2_subdev *sd = to_sd(ctrl);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300799 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800800
801 switch (ctrl->id) {
802 case V4L2_CID_BRIGHTNESS:
Hans Verkuile3560542010-05-24 10:00:52 -0300803 saa711x_write(sd, R_0A_LUMA_BRIGHT_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800804 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300805
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800806 case V4L2_CID_CONTRAST:
Hans Verkuile3560542010-05-24 10:00:52 -0300807 saa711x_write(sd, R_0B_LUMA_CONTRAST_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800808 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300809
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800810 case V4L2_CID_SATURATION:
Hans Verkuile3560542010-05-24 10:00:52 -0300811 saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800812 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300813
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800814 case V4L2_CID_HUE:
Hans Verkuile3560542010-05-24 10:00:52 -0300815 saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800816 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300817
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300818 case V4L2_CID_CHROMA_AGC:
Hans Verkuile3560542010-05-24 10:00:52 -0300819 /* chroma gain cluster */
820 if (state->agc->val)
821 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val);
822 else
823 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val | 0x80);
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300824 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300825
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800826 default:
827 return -EINVAL;
828 }
829
830 return 0;
831}
832
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300833static int saa711x_set_size(struct v4l2_subdev *sd, int width, int height)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300834{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300835 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300836 int HPSC, HFSC;
837 int VSCY;
838 int res;
839 int is_50hz = state->std & V4L2_STD_625_50;
840 int Vsrc = is_50hz ? 576 : 480;
841
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300842 v4l2_dbg(1, debug, sd, "decoder set size to %ix%i\n", width, height);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300843
844 /* FIXME need better bounds checking here */
845 if ((width < 1) || (width > 1440))
846 return -EINVAL;
847 if ((height < 1) || (height > Vsrc))
848 return -EINVAL;
849
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300850 if (!saa711x_has_reg(state->ident, R_D0_B_HORIZ_PRESCALING)) {
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300851 /* Decoder only supports 720 columns and 480 or 576 lines */
852 if (width != 720)
853 return -EINVAL;
854 if (height != Vsrc)
855 return -EINVAL;
856 }
857
858 state->width = width;
859 state->height = height;
860
861 if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
862 return 0;
863
864 /* probably have a valid size, let's set it */
865 /* Set output width/height */
866 /* width */
867
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300868 saa711x_write(sd, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300869 (u8) (width & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300870 saa711x_write(sd, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300871 (u8) ((width >> 8) & 0xff));
872
873 /* Vertical Scaling uses height/2 */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300874 res = height / 2;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300875
876 /* On 60Hz, it is using a higher Vertical Output Size */
877 if (!is_50hz)
Hans Verkuild0d30c02006-11-25 09:45:50 -0300878 res += (VRES_60HZ - 480) >> 1;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300879
880 /* height */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300881 saa711x_write(sd, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300882 (u8) (res & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300883 saa711x_write(sd, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300884 (u8) ((res >> 8) & 0xff));
885
886 /* Scaling settings */
887 /* Hprescaler is floor(inres/outres) */
888 HPSC = (int)(720 / width);
889 /* 0 is not allowed (div. by zero) */
890 HPSC = HPSC ? HPSC : 1;
891 HFSC = (int)((1024 * 720) / (HPSC * width));
892 /* FIXME hardcodes to "Task B"
893 * write H prescaler integer */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300894 saa711x_write(sd, R_D0_B_HORIZ_PRESCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300895 (u8) (HPSC & 0x3f));
896
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300897 v4l2_dbg(1, debug, sd, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300898 /* write H fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300899 saa711x_write(sd, R_D8_B_HORIZ_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300900 (u8) (HFSC & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300901 saa711x_write(sd, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300902 (u8) ((HFSC >> 8) & 0xff));
903 /* write H fine-scaling (chrominance)
904 * must be lum/2, so i'll just bitshift :) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300905 saa711x_write(sd, R_DC_B_HORIZ_CHROMA_SCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300906 (u8) ((HFSC >> 1) & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300907 saa711x_write(sd, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300908 (u8) ((HFSC >> 9) & 0xff));
909
910 VSCY = (int)((1024 * Vsrc) / height);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300911 v4l2_dbg(1, debug, sd, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300912
913 /* Correct Contrast and Luminance */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300914 saa711x_write(sd, R_D5_B_LUMA_CONTRAST_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300915 (u8) (64 * 1024 / VSCY));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300916 saa711x_write(sd, R_D6_B_CHROMA_SATURATION_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300917 (u8) (64 * 1024 / VSCY));
918
919 /* write V fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300920 saa711x_write(sd, R_E0_B_VERT_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300921 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300922 saa711x_write(sd, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300923 (u8) ((VSCY >> 8) & 0xff));
924 /* write V fine-scaling (chrominance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300925 saa711x_write(sd, R_E2_B_VERT_CHROMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300926 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300927 saa711x_write(sd, R_E3_B_VERT_CHROMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300928 (u8) ((VSCY >> 8) & 0xff));
929
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300930 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300931
932 /* Activates task "B" */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300933 saa711x_write(sd, R_80_GLOBAL_CNTL_1,
934 saa711x_read(sd, R_80_GLOBAL_CNTL_1) | 0x20);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300935
936 return 0;
937}
938
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300939static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800940{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300941 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800942
Hans Verkuil30b54d52006-01-09 15:25:43 -0200943 /* Prevent unnecessary standard changes. During a standard
944 change the I-Port is temporarily disabled. Any devices
945 reading from that port can get confused.
Hans Verkuilbccfa442009-03-30 06:55:27 -0300946 Note that s_std is also used to switch from
947 radio to TV mode, so if a s_std is broadcast to
Hans Verkuil30b54d52006-01-09 15:25:43 -0200948 all I2C devices then you do not want to have an unwanted
949 side-effect here. */
950 if (std == state->std)
951 return;
952
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300953 state->std = std;
954
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800955 // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
956 if (std & V4L2_STD_525_60) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300957 v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n");
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300958 if (state->ident == V4L2_IDENT_GM7113C)
959 saa711x_writeregs(sd, gm7113c_cfg_60hz_video);
960 else
961 saa711x_writeregs(sd, saa7115_cfg_60hz_video);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300962 saa711x_set_size(sd, 720, 480);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800963 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300964 v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n");
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300965 if (state->ident == V4L2_IDENT_GM7113C)
966 saa711x_writeregs(sd, gm7113c_cfg_50hz_video);
967 else
968 saa711x_writeregs(sd, saa7115_cfg_50hz_video);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300969 saa711x_set_size(sd, 720, 576);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800970 }
971
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300972 /* Register 0E - Bits D6-D4 on NO-AUTO mode
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300973 (SAA7111 and SAA7113 doesn't have auto mode)
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300974 50 Hz / 625 lines 60 Hz / 525 lines
975 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz)
976 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz)
977 010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz)
978 011 NTSC N (3.58MHz) PAL M (3.58MHz)
979 100 reserved NTSC-Japan (3.58MHz)
980 */
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300981 if (state->ident <= V4L2_IDENT_SAA7113 ||
982 state->ident == V4L2_IDENT_GM7113C) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300983 u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300984
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300985 if (std == V4L2_STD_PAL_M) {
Hans Verkuil01342352006-03-25 08:19:47 -0300986 reg |= 0x30;
Hans Verkuile0028022008-04-22 14:45:51 -0300987 } else if (std == V4L2_STD_PAL_Nc) {
Hans Verkuil01342352006-03-25 08:19:47 -0300988 reg |= 0x20;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300989 } else if (std == V4L2_STD_PAL_60) {
Hans Verkuil01342352006-03-25 08:19:47 -0300990 reg |= 0x10;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300991 } else if (std == V4L2_STD_NTSC_M_JP) {
Hans Verkuil01342352006-03-25 08:19:47 -0300992 reg |= 0x40;
Mauro Carvalho Chehaba9aaec42007-03-13 13:41:49 -0300993 } else if (std & V4L2_STD_SECAM) {
Pádraig Bradyfc2fa312006-10-09 08:02:17 -0300994 reg |= 0x50;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300995 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300996 saa711x_write(sd, R_0E_CHROMA_CNTL_1, reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300997 } else {
998 /* restart task B if needed */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300999 int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001000
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001001 if (taskb && state->ident == V4L2_IDENT_SAA7114) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001002 saa711x_writeregs(sd, saa7115_cfg_vbi_on);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001003 }
1004
1005 /* switch audio mode too! */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001006 saa711x_s_clock_freq(sd, state->audclk_freq);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001007 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001008}
1009
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001010/* setup the sliced VBI lcr registers according to the sliced VBI format */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001011static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001012{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001013 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001014 int is_50hz = (state->std & V4L2_STD_625_50);
1015 u8 lcr[24];
1016 int i, x;
1017
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001018#if 1
1019 /* saa7113/7114/7118 VBI support are experimental */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001020 if (!saa711x_has_reg(state->ident, R_41_LCR_BASE))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001021 return;
1022
1023#else
1024 /* SAA7113 and SAA7118 also should support VBI - Need testing */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001025 if (state->ident != V4L2_IDENT_SAA7115)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001026 return;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001027#endif
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001028
1029 for (i = 0; i <= 23; i++)
1030 lcr[i] = 0xff;
1031
Hans Verkuila8b86432008-10-04 08:05:30 -03001032 if (fmt == NULL) {
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001033 /* raw VBI */
1034 if (is_50hz)
1035 for (i = 6; i <= 23; i++)
1036 lcr[i] = 0xdd;
1037 else
1038 for (i = 10; i <= 21; i++)
1039 lcr[i] = 0xdd;
1040 } else {
1041 /* sliced VBI */
1042 /* first clear lines that cannot be captured */
1043 if (is_50hz) {
1044 for (i = 0; i <= 5; i++)
1045 fmt->service_lines[0][i] =
1046 fmt->service_lines[1][i] = 0;
1047 }
1048 else {
1049 for (i = 0; i <= 9; i++)
1050 fmt->service_lines[0][i] =
1051 fmt->service_lines[1][i] = 0;
1052 for (i = 22; i <= 23; i++)
1053 fmt->service_lines[0][i] =
1054 fmt->service_lines[1][i] = 0;
1055 }
1056
1057 /* Now set the lcr values according to the specified service */
1058 for (i = 6; i <= 23; i++) {
1059 lcr[i] = 0;
1060 for (x = 0; x <= 1; x++) {
1061 switch (fmt->service_lines[1-x][i]) {
1062 case 0:
1063 lcr[i] |= 0xf << (4 * x);
1064 break;
Hans Verkuil9bc74002006-03-29 18:02:51 -03001065 case V4L2_SLICED_TELETEXT_B:
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001066 lcr[i] |= 1 << (4 * x);
1067 break;
1068 case V4L2_SLICED_CAPTION_525:
1069 lcr[i] |= 4 << (4 * x);
1070 break;
1071 case V4L2_SLICED_WSS_625:
1072 lcr[i] |= 5 << (4 * x);
1073 break;
1074 case V4L2_SLICED_VPS:
1075 lcr[i] |= 7 << (4 * x);
1076 break;
1077 }
1078 }
1079 }
1080 }
1081
1082 /* write the lcr registers */
1083 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001084 saa711x_write(sd, i - 2 + R_41_LCR_BASE, lcr[i]);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001085 }
1086
1087 /* enable/disable raw VBI capturing */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001088 saa711x_writeregs(sd, fmt == NULL ?
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001089 saa7115_cfg_vbi_on :
1090 saa7115_cfg_vbi_off);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001091}
1092
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001093static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *sliced)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001094{
1095 static u16 lcr2vbi[] = {
Hans Verkuil9bc74002006-03-29 18:02:51 -03001096 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001097 0, V4L2_SLICED_CAPTION_525, /* 4 */
1098 V4L2_SLICED_WSS_625, 0, /* 5 */
1099 V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
1100 0, 0, 0, 0
1101 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001102 int i;
1103
Hans Verkuil30634e82012-09-05 10:38:10 -03001104 memset(sliced->service_lines, 0, sizeof(sliced->service_lines));
1105 sliced->service_set = 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001106 /* done if using raw VBI */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001107 if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001108 return 0;
1109 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001110 u8 v = saa711x_read(sd, i - 2 + R_41_LCR_BASE);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001111
1112 sliced->service_lines[0][i] = lcr2vbi[v >> 4];
1113 sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
1114 sliced->service_set |=
1115 sliced->service_lines[0][i] | sliced->service_lines[1][i];
1116 }
1117 return 0;
1118}
1119
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001120static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
1121{
1122 saa711x_set_lcr(sd, NULL);
1123 return 0;
1124}
1125
1126static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
1127{
1128 saa711x_set_lcr(sd, fmt);
1129 return 0;
1130}
1131
Hans Verkuilc463d932010-05-09 09:47:23 -03001132static int saa711x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
1133{
1134 if (fmt->code != V4L2_MBUS_FMT_FIXED)
1135 return -EINVAL;
1136 fmt->field = V4L2_FIELD_INTERLACED;
1137 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1138 return saa711x_set_size(sd, fmt->width, fmt->height);
1139}
1140
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001141/* Decode the sliced VBI data stream as created by the saa7115.
1142 The format is described in the saa7115 datasheet in Tables 25 and 26
1143 and in Figure 33.
1144 The current implementation uses SAV/EAV codes and not the ancillary data
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001145 headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001146 code. */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001147static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001148{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001149 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001150 static const char vbi_no_data_pattern[] = {
1151 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
1152 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001153 u8 *p = vbi->p;
1154 u32 wss;
1155 int id1, id2; /* the ID1 and ID2 bytes from the internal header */
1156
1157 vbi->type = 0; /* mark result as a failure */
1158 id1 = p[2];
1159 id2 = p[3];
1160 /* Note: the field bit is inverted for 60 Hz video */
1161 if (state->std & V4L2_STD_525_60)
1162 id1 ^= 0x40;
1163
1164 /* Skip internal header, p now points to the start of the payload */
1165 p += 4;
1166 vbi->p = p;
1167
1168 /* calculate field and line number of the VBI packet (1-23) */
1169 vbi->is_second_field = ((id1 & 0x40) != 0);
1170 vbi->line = (id1 & 0x3f) << 3;
1171 vbi->line |= (id2 & 0x70) >> 4;
1172
1173 /* Obtain data type */
1174 id2 &= 0xf;
1175
1176 /* If the VBI slicer does not detect any signal it will fill up
1177 the payload buffer with 0xa0 bytes. */
1178 if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001179 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001180
1181 /* decode payloads */
1182 switch (id2) {
1183 case 1:
Hans Verkuil9bc74002006-03-29 18:02:51 -03001184 vbi->type = V4L2_SLICED_TELETEXT_B;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001185 break;
1186 case 4:
Mauro Carvalho Chehab59ba9152006-08-30 05:34:36 -03001187 if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001188 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001189 vbi->type = V4L2_SLICED_CAPTION_525;
1190 break;
1191 case 5:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001192 wss = saa711x_decode_wss(p);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001193 if (wss == -1)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001194 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001195 p[0] = wss & 0xff;
1196 p[1] = wss >> 8;
1197 vbi->type = V4L2_SLICED_WSS_625;
1198 break;
1199 case 7:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001200 if (saa711x_decode_vps(p, p) != 0)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001201 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001202 vbi->type = V4L2_SLICED_VPS;
1203 break;
1204 default:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001205 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001206 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001207 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001208}
1209
1210/* ============ SAA7115 AUDIO settings (end) ============= */
1211
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001212static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001213{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001214 struct saa711x_state *state = to_state(sd);
1215 int status;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001216
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001217 if (state->radio)
1218 return 0;
1219 status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001220
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001221 v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status);
1222 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1223 return 0;
1224}
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001225
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001226static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1227{
1228 struct saa711x_state *state = to_state(sd);
1229
1230 state->radio = 0;
1231 saa711x_set_v4lstd(sd, std);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001232 return 0;
1233}
1234
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001235static int saa711x_s_radio(struct v4l2_subdev *sd)
1236{
1237 struct saa711x_state *state = to_state(sd);
1238
1239 state->radio = 1;
1240 return 0;
1241}
1242
Hans Verkuil5325b422009-04-02 11:26:22 -03001243static int saa711x_s_routing(struct v4l2_subdev *sd,
1244 u32 input, u32 output, u32 config)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001245{
1246 struct saa711x_state *state = to_state(sd);
Hans Verkuil340dde82010-02-20 08:07:51 -03001247 u8 mask = (state->ident <= V4L2_IDENT_SAA7111A) ? 0xf8 : 0xf0;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001248
Hans Verkuil5325b422009-04-02 11:26:22 -03001249 v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n",
1250 input, output);
1251
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001252 /* saa7111/3 does not have these inputs */
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -03001253 if ((state->ident <= V4L2_IDENT_SAA7113 ||
1254 state->ident == V4L2_IDENT_GM7113C) &&
Hans Verkuil5325b422009-04-02 11:26:22 -03001255 (input == SAA7115_COMPOSITE4 ||
1256 input == SAA7115_COMPOSITE5)) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001257 return -EINVAL;
1258 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001259 if (input > SAA7115_SVIDEO3)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001260 return -EINVAL;
Hans Verkuil5325b422009-04-02 11:26:22 -03001261 if (state->input == input && state->output == output)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001262 return 0;
1263 v4l2_dbg(1, debug, sd, "now setting %s input %s output\n",
Hans Verkuil5325b422009-04-02 11:26:22 -03001264 (input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite",
1265 (output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
1266 state->input = input;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001267
1268 /* saa7111 has slightly different input numbering */
Hans Verkuil340dde82010-02-20 08:07:51 -03001269 if (state->ident <= V4L2_IDENT_SAA7111A) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001270 if (input >= SAA7115_COMPOSITE4)
1271 input -= 2;
1272 /* saa7111 specific */
1273 saa711x_write(sd, R_10_CHROMA_CNTL_2,
1274 (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001275 ((output & 0xc0) ^ 0x40));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001276 saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL,
1277 (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001278 ((output & 2) ? 0x0a : 0));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001279 }
1280
1281 /* select mode */
1282 saa711x_write(sd, R_02_INPUT_CNTL_1,
1283 (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) |
1284 input);
1285
1286 /* bypass chrominance trap for S-Video modes */
1287 saa711x_write(sd, R_09_LUMA_CNTL,
1288 (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) |
1289 (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
1290
Hans Verkuil5325b422009-04-02 11:26:22 -03001291 state->output = output;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001292 if (state->ident == V4L2_IDENT_SAA7114 ||
1293 state->ident == V4L2_IDENT_SAA7115) {
1294 saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
1295 (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
1296 (state->output & 0x01));
1297 }
Hans Verkuila0fc5882013-03-08 11:22:03 -03001298 if (state->ident > V4L2_IDENT_SAA7111A) {
1299 if (config & SAA7115_IDQ_IS_DEFAULT)
1300 saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x20);
1301 else
1302 saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x21);
1303 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001304 return 0;
1305}
1306
1307static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val)
1308{
1309 struct saa711x_state *state = to_state(sd);
1310
Hans Verkuil340dde82010-02-20 08:07:51 -03001311 if (state->ident > V4L2_IDENT_SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001312 return -EINVAL;
1313 saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) |
1314 (val ? 0x80 : 0));
1315 return 0;
1316}
1317
1318static int saa711x_s_stream(struct v4l2_subdev *sd, int enable)
1319{
1320 struct saa711x_state *state = to_state(sd);
1321
1322 v4l2_dbg(1, debug, sd, "%s output\n",
1323 enable ? "enable" : "disable");
1324
Hans Verkuil674a3232009-02-18 12:22:16 -03001325 if (state->enable == enable)
1326 return 0;
1327 state->enable = enable;
1328 if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED))
1329 return 0;
1330 saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001331 return 0;
1332}
1333
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001334static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001335{
1336 struct saa711x_state *state = to_state(sd);
1337
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001338 if (freq != SAA7115_FREQ_32_11_MHZ && freq != SAA7115_FREQ_24_576_MHZ)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001339 return -EINVAL;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001340 state->crystal_freq = freq;
Hans Verkuil15890372013-03-11 03:47:25 -03001341 state->double_asclk = flags & SAA7115_FREQ_FL_DOUBLE_ASCLK;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001342 state->cgcdiv = (flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
Hans Verkuil15890372013-03-11 03:47:25 -03001343 state->ucgc = flags & SAA7115_FREQ_FL_UCGC;
1344 state->apll = flags & SAA7115_FREQ_FL_APLL;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001345 saa711x_s_clock_freq(sd, state->audclk_freq);
1346 return 0;
1347}
1348
1349static int saa711x_reset(struct v4l2_subdev *sd, u32 val)
1350{
1351 v4l2_dbg(1, debug, sd, "decoder RESET\n");
1352 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
1353 return 0;
1354}
1355
1356static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data)
1357{
1358 /* Note: the internal field ID is inverted for NTSC,
1359 so data->field 0 maps to the saa7115 even field,
1360 whereas for PAL it maps to the saa7115 odd field. */
1361 switch (data->id) {
1362 case V4L2_SLICED_WSS_625:
1363 if (saa711x_read(sd, 0x6b) & 0xc0)
1364 return -EIO;
1365 data->data[0] = saa711x_read(sd, 0x6c);
1366 data->data[1] = saa711x_read(sd, 0x6d);
1367 return 0;
1368 case V4L2_SLICED_CAPTION_525:
1369 if (data->field == 0) {
1370 /* CC */
1371 if (saa711x_read(sd, 0x66) & 0x30)
1372 return -EIO;
1373 data->data[0] = saa711x_read(sd, 0x69);
1374 data->data[1] = saa711x_read(sd, 0x6a);
1375 return 0;
1376 }
1377 /* XDS */
1378 if (saa711x_read(sd, 0x66) & 0xc0)
1379 return -EIO;
1380 data->data[0] = saa711x_read(sd, 0x67);
1381 data->data[1] = saa711x_read(sd, 0x68);
1382 return 0;
1383 default:
1384 return -EINVAL;
1385 }
1386}
1387
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001388static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
1389{
1390 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001391 int reg1f, reg1e;
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001392
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001393 /*
1394 * The V4L2 core already initializes std with all supported
1395 * Standards. All driver needs to do is to mask it, to remove
1396 * standards that don't apply from the mask
1397 */
1398
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001399 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuilc875dee2013-03-10 09:59:37 -03001400
1401 if (state->ident == V4L2_IDENT_SAA7115) {
1402 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1403
1404 v4l2_dbg(1, debug, sd, "Status byte 1 (0x1e)=0x%02x\n", reg1e);
1405
1406 switch (reg1e & 0x03) {
1407 case 1:
1408 *std &= V4L2_STD_NTSC;
1409 break;
1410 case 2:
1411 /*
1412 * V4L2_STD_PAL just cover the european PAL standards.
1413 * This is wrong, as the device could also be using an
1414 * other PAL standard.
1415 */
1416 *std &= V4L2_STD_PAL | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc |
1417 V4L2_STD_PAL_M | V4L2_STD_PAL_60;
1418 break;
1419 case 3:
1420 *std &= V4L2_STD_SECAM;
1421 break;
1422 default:
1423 /* Can't detect anything */
1424 break;
1425 }
1426 }
1427
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001428 v4l2_dbg(1, debug, sd, "Status byte 2 (0x1f)=0x%02x\n", reg1f);
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001429
1430 /* horizontal/vertical not locked */
1431 if (reg1f & 0x40)
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001432 goto ret;
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001433
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001434 if (reg1f & 0x20)
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001435 *std &= V4L2_STD_525_60;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001436 else
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001437 *std &= V4L2_STD_625_50;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001438
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001439ret:
1440 v4l2_dbg(1, debug, sd, "detected std mask = %08Lx\n", *std);
1441
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001442 return 0;
1443}
1444
1445static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status)
1446{
1447 struct saa711x_state *state = to_state(sd);
1448 int reg1e = 0x80;
1449 int reg1f;
1450
1451 *status = V4L2_IN_ST_NO_SIGNAL;
1452 if (state->ident == V4L2_IDENT_SAA7115)
1453 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1454 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1455 if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80)
1456 *status = 0;
1457 return 0;
1458}
1459
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001460#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001461static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001462{
1463 struct i2c_client *client = v4l2_get_subdevdata(sd);
1464
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001465 if (!v4l2_chip_match_i2c_client(client, &reg->match))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001466 return -EINVAL;
1467 if (!capable(CAP_SYS_ADMIN))
1468 return -EPERM;
1469 reg->val = saa711x_read(sd, reg->reg & 0xff);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001470 reg->size = 1;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001471 return 0;
1472}
1473
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001474static int saa711x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001475{
1476 struct i2c_client *client = v4l2_get_subdevdata(sd);
1477
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001478 if (!v4l2_chip_match_i2c_client(client, &reg->match))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001479 return -EINVAL;
1480 if (!capable(CAP_SYS_ADMIN))
1481 return -EPERM;
1482 saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff);
1483 return 0;
1484}
1485#endif
1486
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001487static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001488{
1489 struct saa711x_state *state = to_state(sd);
1490 struct i2c_client *client = v4l2_get_subdevdata(sd);
1491
1492 return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0);
1493}
1494
1495static int saa711x_log_status(struct v4l2_subdev *sd)
1496{
1497 struct saa711x_state *state = to_state(sd);
1498 int reg1e, reg1f;
1499 int signalOk;
1500 int vcr;
1501
1502 v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq);
1503 if (state->ident != V4L2_IDENT_SAA7115) {
1504 /* status for the saa7114 */
1505 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1506 signalOk = (reg1f & 0xc1) == 0x81;
1507 v4l2_info(sd, "Video signal: %s\n", signalOk ? "ok" : "bad");
1508 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1509 return 0;
1510 }
1511
1512 /* status for the saa7115 */
1513 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1514 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1515
1516 signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
1517 vcr = !(reg1f & 0x10);
1518
1519 if (state->input >= 6)
1520 v4l2_info(sd, "Input: S-Video %d\n", state->input - 6);
1521 else
1522 v4l2_info(sd, "Input: Composite %d\n", state->input);
1523 v4l2_info(sd, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
1524 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1525
1526 switch (reg1e & 0x03) {
1527 case 1:
1528 v4l2_info(sd, "Detected format: NTSC\n");
1529 break;
1530 case 2:
1531 v4l2_info(sd, "Detected format: PAL\n");
1532 break;
1533 case 3:
1534 v4l2_info(sd, "Detected format: SECAM\n");
1535 break;
1536 default:
1537 v4l2_info(sd, "Detected format: BW/No color\n");
1538 break;
1539 }
1540 v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height);
Hans Verkuile3560542010-05-24 10:00:52 -03001541 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001542 return 0;
1543}
1544
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001545/* ----------------------------------------------------------------------- */
1546
Hans Verkuile3560542010-05-24 10:00:52 -03001547static const struct v4l2_ctrl_ops saa711x_ctrl_ops = {
1548 .s_ctrl = saa711x_s_ctrl,
1549 .g_volatile_ctrl = saa711x_g_volatile_ctrl,
1550};
1551
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001552static const struct v4l2_subdev_core_ops saa711x_core_ops = {
1553 .log_status = saa711x_log_status,
1554 .g_chip_ident = saa711x_g_chip_ident,
Hans Verkuile3560542010-05-24 10:00:52 -03001555 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
1556 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
1557 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
1558 .g_ctrl = v4l2_subdev_g_ctrl,
1559 .s_ctrl = v4l2_subdev_s_ctrl,
1560 .queryctrl = v4l2_subdev_queryctrl,
1561 .querymenu = v4l2_subdev_querymenu,
Hans Verkuilf41737e2009-04-01 03:52:39 -03001562 .s_std = saa711x_s_std,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001563 .reset = saa711x_reset,
1564 .s_gpio = saa711x_s_gpio,
1565#ifdef CONFIG_VIDEO_ADV_DEBUG
1566 .g_register = saa711x_g_register,
1567 .s_register = saa711x_s_register,
1568#endif
1569};
1570
1571static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001572 .s_radio = saa711x_s_radio,
1573 .g_tuner = saa711x_g_tuner,
1574};
1575
1576static const struct v4l2_subdev_audio_ops saa711x_audio_ops = {
1577 .s_clock_freq = saa711x_s_clock_freq,
1578};
1579
1580static const struct v4l2_subdev_video_ops saa711x_video_ops = {
1581 .s_routing = saa711x_s_routing,
1582 .s_crystal_freq = saa711x_s_crystal_freq,
Hans Verkuilc463d932010-05-09 09:47:23 -03001583 .s_mbus_fmt = saa711x_s_mbus_fmt,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001584 .s_stream = saa711x_s_stream,
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001585 .querystd = saa711x_querystd,
1586 .g_input_status = saa711x_g_input_status,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001587};
1588
Hans Verkuil32cd5272010-03-14 09:57:30 -03001589static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = {
1590 .g_vbi_data = saa711x_g_vbi_data,
1591 .decode_vbi_line = saa711x_decode_vbi_line,
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001592 .g_sliced_fmt = saa711x_g_sliced_fmt,
1593 .s_sliced_fmt = saa711x_s_sliced_fmt,
1594 .s_raw_fmt = saa711x_s_raw_fmt,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001595};
1596
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001597static const struct v4l2_subdev_ops saa711x_ops = {
1598 .core = &saa711x_core_ops,
1599 .tuner = &saa711x_tuner_ops,
1600 .audio = &saa711x_audio_ops,
1601 .video = &saa711x_video_ops,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001602 .vbi = &saa711x_vbi_ops,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001603};
1604
1605/* ----------------------------------------------------------------------- */
1606
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001607/**
1608 * saa711x_detect_chip - Detects the saa711x (or clone) variant
1609 * @client: I2C client structure.
1610 * @id: I2C device ID structure.
1611 * @name: Name of the device to be filled.
1612 * @size: Size of the name var.
1613 *
1614 * Detects the Philips/NXP saa711x chip, or some clone of it.
1615 * if 'id' is NULL or id->driver_data is equal to 1, it auto-probes
1616 * the analog demod.
1617 * If the tuner is not found, it returns -ENODEV.
1618 * If auto-detection is disabled and the tuner doesn't match what it was
1619 * requred, it returns -EINVAL and fills 'name'.
1620 * If the chip is found, it returns the chip ID and fills 'name'.
1621 */
1622static int saa711x_detect_chip(struct i2c_client *client,
1623 const struct i2c_device_id *id,
1624 char *name, unsigned size)
1625{
1626 char chip_ver[size - 1];
1627 char chip_id;
1628 int i;
1629 int autodetect;
1630
1631 autodetect = !id || id->driver_data == 1;
1632
1633 /* Read the chip version register */
1634 for (i = 0; i < size - 1; i++) {
1635 i2c_smbus_write_byte_data(client, 0, i);
1636 chip_ver[i] = i2c_smbus_read_byte_data(client, 0);
1637 name[i] = (chip_ver[i] & 0x0f) + '0';
1638 if (name[i] > '9')
1639 name[i] += 'a' - '9' - 1;
1640 }
1641 name[i] = '\0';
1642
1643 /* Check if it is a Philips/NXP chip */
1644 if (!memcmp(name + 1, "f711", 4)) {
1645 chip_id = name[5];
1646 snprintf(name, size, "saa711%c", chip_id);
1647
1648 if (!autodetect && strcmp(name, id->name))
1649 return -EINVAL;
1650
1651 switch (chip_id) {
1652 case '1':
1653 if (chip_ver[0] & 0xf0) {
1654 snprintf(name, size, "saa711%ca", chip_id);
1655 v4l_info(client, "saa7111a variant found\n");
1656 return V4L2_IDENT_SAA7111A;
1657 }
1658 return V4L2_IDENT_SAA7111;
1659 case '3':
1660 return V4L2_IDENT_SAA7113;
1661 case '4':
1662 return V4L2_IDENT_SAA7114;
1663 case '5':
1664 return V4L2_IDENT_SAA7115;
1665 case '8':
1666 return V4L2_IDENT_SAA7118;
1667 default:
1668 v4l2_info(client,
1669 "WARNING: Philips/NXP chip unknown - Falling back to saa7111\n");
1670 return V4L2_IDENT_SAA7111;
1671 }
1672 }
1673
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001674 /* Check if it is a gm7113c */
1675 if (!memcmp(name, "0000", 4)) {
1676 chip_id = 0;
1677 for (i = 0; i < 4; i++) {
1678 chip_id = chip_id << 1;
1679 chip_id |= (chip_ver[i] & 0x80) ? 1 : 0;
1680 }
1681
1682 /*
1683 * Note: From the datasheet, only versions 1 and 2
1684 * exists. However, tests on a device labeled as:
1685 * "GM7113C 1145" returned "10" on all 16 chip
1686 * version (reg 0x00) reads. So, we need to also
1687 * accept at least verion 0. For now, let's just
1688 * assume that a device that returns "0000" for
1689 * the lower nibble is a gm7113c.
1690 */
1691
1692 strlcpy(name, "gm7113c", size);
1693
1694 if (!autodetect && strcmp(name, id->name))
1695 return -EINVAL;
1696
1697 v4l_dbg(1, debug, client,
1698 "It seems to be a %s chip (%*ph) @ 0x%x.\n",
1699 name, 16, chip_ver, client->addr << 1);
1700
1701 return V4L2_IDENT_GM7113C;
1702 }
1703
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001704 /* Chip was not discovered. Return its ID and don't bind */
1705 v4l_dbg(1, debug, client, "chip %*ph @ 0x%x is unknown.\n",
1706 16, chip_ver, client->addr << 1);
1707 return -ENODEV;
1708}
1709
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001710static int saa711x_probe(struct i2c_client *client,
Jean Delvared2653e92008-04-29 23:11:39 +02001711 const struct i2c_device_id *id)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001712{
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001713 struct saa711x_state *state;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001714 struct v4l2_subdev *sd;
Hans Verkuile3560542010-05-24 10:00:52 -03001715 struct v4l2_ctrl_handler *hdl;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001716 int ident;
Hans Verkuile3560542010-05-24 10:00:52 -03001717 char name[17];
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001718
1719 /* Check if the adapter supports the needed features */
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001720 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
Hans Verkuil188f3452007-09-16 10:47:15 -03001721 return -EIO;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001722
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001723 ident = saa711x_detect_chip(client, id, name, sizeof(name));
1724 if (ident == -EINVAL) {
1725 /* Chip exists, but doesn't match */
1726 v4l_warn(client, "found %s while %s was expected\n",
1727 name, id->name);
Hans Verkuil188f3452007-09-16 10:47:15 -03001728 return -ENODEV;
Hans Verkuilf7668162006-11-25 09:40:28 -03001729 }
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001730 if (ident < 0)
1731 return ident;
Hans Verkuilf7668162006-11-25 09:40:28 -03001732
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001733 strlcpy(client->name, name, sizeof(client->name));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001734
Laurent Pinchartc02b2112013-05-02 08:29:43 -03001735 state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
Hans Verkuilc5bf2042008-09-03 17:12:09 -03001736 if (state == NULL)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001737 return -ENOMEM;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001738 sd = &state->sd;
1739 v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
Hans Verkuile3560542010-05-24 10:00:52 -03001740
1741 hdl = &state->hdl;
1742 v4l2_ctrl_handler_init(hdl, 6);
1743 /* add in ascending ID order */
1744 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1745 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1746 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1747 V4L2_CID_CONTRAST, 0, 127, 1, 64);
1748 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1749 V4L2_CID_SATURATION, 0, 127, 1, 64);
1750 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1751 V4L2_CID_HUE, -128, 127, 1, 0);
1752 state->agc = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1753 V4L2_CID_CHROMA_AGC, 0, 1, 1, 1);
1754 state->gain = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1755 V4L2_CID_CHROMA_GAIN, 0, 127, 1, 40);
Hans Verkuile3560542010-05-24 10:00:52 -03001756 sd->ctrl_handler = hdl;
1757 if (hdl->error) {
1758 int err = hdl->error;
1759
1760 v4l2_ctrl_handler_free(hdl);
Hans Verkuile3560542010-05-24 10:00:52 -03001761 return err;
1762 }
Hans Verkuil6f43dbf2011-08-26 08:46:29 -03001763 v4l2_ctrl_auto_cluster(2, &state->agc, 0, true);
Hans Verkuile3560542010-05-24 10:00:52 -03001764
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001765 state->input = -1;
Marco Schluessler4cbca182007-01-21 19:43:38 -03001766 state->output = SAA7115_IPORT_ON;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001767 state->enable = 1;
Hans Verkuil3faeeae2006-01-09 15:25:44 -02001768 state->radio = 0;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001769 state->ident = ident;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001770
Hans Verkuil3578d3d2006-01-09 15:25:41 -02001771 state->audclk_freq = 48000;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001772
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001773 v4l2_dbg(1, debug, sd, "writing init values\n");
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001774
1775 /* init to 60hz/48khz */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001776 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
1777 switch (state->ident) {
1778 case V4L2_IDENT_SAA7111:
Hans Verkuil340dde82010-02-20 08:07:51 -03001779 case V4L2_IDENT_SAA7111A:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001780 saa711x_writeregs(sd, saa7111_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001781 break;
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -03001782 case V4L2_IDENT_GM7113C:
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001783 case V4L2_IDENT_SAA7113:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001784 saa711x_writeregs(sd, saa7113_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001785 break;
1786 default:
Hans Verkuilb7f82922006-04-02 12:50:42 -03001787 state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001788 saa711x_writeregs(sd, saa7115_init_auto_input);
Hans Verkuilb7f82922006-04-02 12:50:42 -03001789 }
Hans Verkuil340dde82010-02-20 08:07:51 -03001790 if (state->ident > V4L2_IDENT_SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001791 saa711x_writeregs(sd, saa7115_init_misc);
1792 saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
Hans Verkuile3560542010-05-24 10:00:52 -03001793 v4l2_ctrl_handler_setup(hdl);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001794
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001795 v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n",
1796 saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC),
1797 saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001798 return 0;
1799}
1800
1801/* ----------------------------------------------------------------------- */
1802
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001803static int saa711x_remove(struct i2c_client *client)
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001804{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001805 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1806
1807 v4l2_device_unregister_subdev(sd);
Hans Verkuile3560542010-05-24 10:00:52 -03001808 v4l2_ctrl_handler_free(sd->ctrl_handler);
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001809 return 0;
1810}
1811
Hans Verkuilaac23532010-09-15 15:04:55 -03001812static const struct i2c_device_id saa711x_id[] = {
Hans Verkuil9edd350f2008-07-17 13:22:51 -03001813 { "saa7115_auto", 1 }, /* autodetect */
Jean Delvareaf294862008-05-18 20:49:40 +02001814 { "saa7111", 0 },
1815 { "saa7113", 0 },
1816 { "saa7114", 0 },
1817 { "saa7115", 0 },
1818 { "saa7118", 0 },
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001819 { "gm7113c", 0 },
Jean Delvareaf294862008-05-18 20:49:40 +02001820 { }
1821};
Hans Verkuilaac23532010-09-15 15:04:55 -03001822MODULE_DEVICE_TABLE(i2c, saa711x_id);
Jean Delvareaf294862008-05-18 20:49:40 +02001823
Hans Verkuilaac23532010-09-15 15:04:55 -03001824static struct i2c_driver saa711x_driver = {
1825 .driver = {
1826 .owner = THIS_MODULE,
1827 .name = "saa7115",
1828 },
1829 .probe = saa711x_probe,
1830 .remove = saa711x_remove,
1831 .id_table = saa711x_id,
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001832};
Hans Verkuilaac23532010-09-15 15:04:55 -03001833
Axel Linc6e8d862012-02-12 06:56:32 -03001834module_i2c_driver(saa711x_driver);