blob: 6b6788cd08f6d6862020d0ab8d6b76e40fbb1402 [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;
86 u8 ucgc;
87 u8 cgcdiv;
88 u8 apll;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080089};
90
Hans Verkuil9415f4b2008-11-29 12:55:19 -030091static inline struct saa711x_state *to_state(struct v4l2_subdev *sd)
92{
93 return container_of(sd, struct saa711x_state, sd);
94}
95
Hans Verkuile3560542010-05-24 10:00:52 -030096static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
97{
98 return &container_of(ctrl->handler, struct saa711x_state, hdl)->sd;
99}
100
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800101/* ----------------------------------------------------------------------- */
102
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300103static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800104{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300105 struct i2c_client *client = v4l2_get_subdevdata(sd);
106
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800107 return i2c_smbus_write_byte_data(client, reg, value);
108}
109
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300110/* Sanity routine to check if a register is present */
111static int saa711x_has_reg(const int id, const u8 reg)
112{
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300113 if (id == V4L2_IDENT_SAA7111)
114 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
115 (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e;
Hans Verkuil340dde82010-02-20 08:07:51 -0300116 if (id == V4L2_IDENT_SAA7111A)
117 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
118 reg != 0x14 && reg != 0x18 && reg != 0x19 &&
119 reg != 0x1d && reg != 0x1e;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300120
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300121 /* common for saa7113/4/5/8 */
122 if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f ||
123 reg == 0xa3 || reg == 0xa7 || reg == 0xab || reg == 0xaf || (reg >= 0xb5 && reg <= 0xb7) ||
124 reg == 0xd3 || reg == 0xd7 || reg == 0xdb || reg == 0xdf || (reg >= 0xe5 && reg <= 0xe7) ||
125 reg == 0x82 || (reg >= 0x89 && reg <= 0x8e)))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300126 return 0;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300127
128 switch (id) {
129 case V4L2_IDENT_SAA7113:
130 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
131 reg != 0x5d && reg < 0x63;
132 case V4L2_IDENT_SAA7114:
133 return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
134 (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
135 reg != 0x81 && reg < 0xf0;
136 case V4L2_IDENT_SAA7115:
137 return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe);
138 case V4L2_IDENT_SAA7118:
139 return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
140 (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
141 (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
142 }
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300143 return 1;
144}
145
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300146static int saa711x_writeregs(struct v4l2_subdev *sd, const unsigned char *regs)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800147{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300148 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800149 unsigned char reg, data;
150
151 while (*regs != 0x00) {
152 reg = *(regs++);
153 data = *(regs++);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300154
155 /* According with datasheets, reserved regs should be
156 filled with 0 - seems better not to touch on they */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300157 if (saa711x_has_reg(state->ident, reg)) {
158 if (saa711x_write(sd, reg, data) < 0)
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300159 return -1;
Mauro Carvalho Chehabd87edf22006-09-01 09:37:11 -0300160 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300161 v4l2_dbg(1, debug, sd, "tried to access reserved reg 0x%02x\n", reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300162 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800163 }
164 return 0;
165}
166
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300167static inline int saa711x_read(struct v4l2_subdev *sd, u8 reg)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800168{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300169 struct i2c_client *client = v4l2_get_subdevdata(sd);
170
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800171 return i2c_smbus_read_byte_data(client, reg);
172}
173
174/* ----------------------------------------------------------------------- */
175
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300176/* SAA7111 initialization table */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300177static const unsigned char saa7111_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300178 R_01_INC_DELAY, 0x00, /* reserved */
179
180 /*front end */
181 R_02_INPUT_CNTL_1, 0xd0, /* FUSE=3, GUDL=2, MODE=0 */
182 R_03_INPUT_CNTL_2, 0x23, /* HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0,
183 * GAFIX=0, GAI1=256, GAI2=256 */
184 R_04_INPUT_CNTL_3, 0x00, /* GAI1=256 */
185 R_05_INPUT_CNTL_4, 0x00, /* GAI2=256 */
186
187 /* decoder */
188 R_06_H_SYNC_START, 0xf3, /* HSB at 13(50Hz) / 17(60Hz)
189 * pixels after end of last line */
190 R_07_H_SYNC_STOP, 0xe8, /* HSS seems to be needed to
191 * work with NTSC, too */
192 R_08_SYNC_CNTL, 0xc8, /* AUFD=1, FSEL=1, EXFIL=0,
193 * VTRC=1, HPLL=0, VNOI=0 */
194 R_09_LUMA_CNTL, 0x01, /* BYPS=0, PREF=0, BPSS=0,
195 * VBLB=0, UPTCV=0, APER=1 */
196 R_0A_LUMA_BRIGHT_CNTL, 0x80,
197 R_0B_LUMA_CONTRAST_CNTL, 0x47, /* 0b - CONT=1.109 */
198 R_0C_CHROMA_SAT_CNTL, 0x40,
199 R_0D_CHROMA_HUE_CNTL, 0x00,
200 R_0E_CHROMA_CNTL_1, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0,
201 * FCTC=0, CHBW=1 */
202 R_0F_CHROMA_GAIN_CNTL, 0x00, /* reserved */
203 R_10_CHROMA_CNTL_2, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
204 R_11_MODE_DELAY_CNTL, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
205 * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
206 R_12_RT_SIGNAL_CNTL, 0x00, /* 12 - output control 2 */
207 R_13_RT_X_PORT_OUT_CNTL, 0x00, /* 13 - output control 3 */
208 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
209 R_15_VGATE_START_FID_CHG, 0x00,
210 R_16_VGATE_STOP, 0x00,
211 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
212
213 0x00, 0x00
214};
215
216/* SAA7113 init codes */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300217static const unsigned char saa7113_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300218 R_01_INC_DELAY, 0x08,
219 R_02_INPUT_CNTL_1, 0xc2,
220 R_03_INPUT_CNTL_2, 0x30,
221 R_04_INPUT_CNTL_3, 0x00,
222 R_05_INPUT_CNTL_4, 0x00,
223 R_06_H_SYNC_START, 0x89,
224 R_07_H_SYNC_STOP, 0x0d,
225 R_08_SYNC_CNTL, 0x88,
226 R_09_LUMA_CNTL, 0x01,
227 R_0A_LUMA_BRIGHT_CNTL, 0x80,
228 R_0B_LUMA_CONTRAST_CNTL, 0x47,
229 R_0C_CHROMA_SAT_CNTL, 0x40,
230 R_0D_CHROMA_HUE_CNTL, 0x00,
231 R_0E_CHROMA_CNTL_1, 0x01,
232 R_0F_CHROMA_GAIN_CNTL, 0x2a,
233 R_10_CHROMA_CNTL_2, 0x08,
234 R_11_MODE_DELAY_CNTL, 0x0c,
235 R_12_RT_SIGNAL_CNTL, 0x07,
236 R_13_RT_X_PORT_OUT_CNTL, 0x00,
237 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
238 R_15_VGATE_START_FID_CHG, 0x00,
239 R_16_VGATE_STOP, 0x00,
240 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
241
242 0x00, 0x00
243};
244
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800245/* If a value differs from the Hauppauge driver values, then the comment starts with
246 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
247 Hauppauge driver sets. */
248
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300249/* SAA7114 and SAA7115 initialization table */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800250static const unsigned char saa7115_init_auto_input[] = {
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300251 /* Front-End Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300252 R_01_INC_DELAY, 0x48, /* white peak control disabled */
253 R_03_INPUT_CNTL_2, 0x20, /* was 0x30. 0x20: long vertical blanking */
254 R_04_INPUT_CNTL_3, 0x90, /* analog gain set to 0 */
255 R_05_INPUT_CNTL_4, 0x90, /* analog gain set to 0 */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300256 /* Decoder Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300257 R_06_H_SYNC_START, 0xeb, /* horiz sync begin = -21 */
258 R_07_H_SYNC_STOP, 0xe0, /* horiz sync stop = -17 */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300259 R_09_LUMA_CNTL, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300260 R_0A_LUMA_BRIGHT_CNTL, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */
261 R_0B_LUMA_CONTRAST_CNTL, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */
262 R_0C_CHROMA_SAT_CNTL, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */
263 R_0D_CHROMA_HUE_CNTL, 0x00,
264 R_0F_CHROMA_GAIN_CNTL, 0x00, /* use automatic gain */
265 R_10_CHROMA_CNTL_2, 0x06, /* chroma: active adaptive combfilter */
266 R_11_MODE_DELAY_CNTL, 0x00,
267 R_12_RT_SIGNAL_CNTL, 0x9d, /* RTS0 output control: VGATE */
268 R_13_RT_X_PORT_OUT_CNTL, 0x80, /* ITU656 standard mode, RTCO output enable RTCE */
269 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
270 R_18_RAW_DATA_GAIN_CNTL, 0x40, /* gain 0x00 = nominal */
271 R_19_RAW_DATA_OFF_CNTL, 0x80,
272 R_1A_COLOR_KILL_LVL_CNTL, 0x77, /* recommended value */
273 R_1B_MISC_TVVCRDET, 0x42, /* recommended value */
274 R_1C_ENHAN_COMB_CTRL1, 0xa9, /* recommended value */
275 R_1D_ENHAN_COMB_CTRL2, 0x01, /* recommended value */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300276
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300277
278 R_80_GLOBAL_CNTL_1, 0x0, /* No tasks enabled at init */
279
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300280 /* Power Device Control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300281 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset device */
282 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* set device programmed, all in operational mode */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800283 0x00, 0x00
284};
285
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300286/* Used to reset saa7113, saa7114 and saa7115 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800287static const unsigned char saa7115_cfg_reset_scaler[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300288 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00, /* disable I-port output */
289 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
290 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
291 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* enable I-port output */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800292 0x00, 0x00
293};
294
295/* ============== SAA7715 VIDEO templates ============= */
296
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800297static const unsigned char saa7115_cfg_60hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300298 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
299 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800300
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300301 R_15_VGATE_START_FID_CHG, 0x03,
302 R_16_VGATE_STOP, 0x11,
303 R_17_MISC_VGATE_CONF_AND_MSB, 0x9c,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800304
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300305 R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
306 R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800307
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300308 R_5A_V_OFF_FOR_SLICER, 0x06, /* standard 60hz value for ITU656 line counting */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800309
310 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300311 R_90_A_TASK_HANDLING_CNTL, 0x80,
312 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
313 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
314 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
315
316 /* hoffset low (input), 0x0002 is minimum */
317 R_94_A_HORIZ_INPUT_WINDOW_START, 0x01,
318 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
319
320 /* hsize low (input), 0x02d0 = 720 */
321 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
322 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
323
324 R_98_A_VERT_INPUT_WINDOW_START, 0x05,
325 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
326
327 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x0c,
328 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
329
330 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
331 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
332
333 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x0c,
334 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800335
336 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300337 R_C0_B_TASK_HANDLING_CNTL, 0x00,
338 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
339 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
340 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800341
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300342 /* 0x0002 is minimum */
343 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x02,
344 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800345
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300346 /* 0x02d0 = 720 */
347 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
348 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
349
350 /* vwindow start 0x12 = 18 */
351 R_C8_B_VERT_INPUT_WINDOW_START, 0x12,
352 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
353
354 /* vwindow length 0xf8 = 248 */
Mauro Carvalho Chehab97d9e802006-09-03 09:38:11 -0300355 R_CA_B_VERT_INPUT_WINDOW_LENGTH, VRES_60HZ>>1,
356 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, VRES_60HZ>>9,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300357
358 /* hwindow 0x02d0 = 720 */
359 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
360 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
361
362 R_F0_LFCO_PER_LINE, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
363 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0 */
364 R_F5_PULSGEN_LINE_LENGTH, 0xad,
365 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
366
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800367 0x00, 0x00
368};
369
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800370static const unsigned char saa7115_cfg_50hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300371 R_80_GLOBAL_CNTL_1, 0x00,
372 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800373
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300374 R_15_VGATE_START_FID_CHG, 0x37, /* VGATE start */
375 R_16_VGATE_STOP, 0x16,
376 R_17_MISC_VGATE_CONF_AND_MSB, 0x99,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800377
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300378 R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */
379 R_0E_CHROMA_CNTL_1, 0x07,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800380
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300381 R_5A_V_OFF_FOR_SLICER, 0x03, /* standard 50hz value */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800382
383 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300384 R_90_A_TASK_HANDLING_CNTL, 0x81,
385 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
386 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
387 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
388
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800389 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
390 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300391 /* hoffset low (input), 0x0002 is minimum */
392 R_94_A_HORIZ_INPUT_WINDOW_START, 0x00,
393 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
394
395 /* hsize low (input), 0x02d0 = 720 */
396 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
397 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
398
399 R_98_A_VERT_INPUT_WINDOW_START, 0x03,
400 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
401
402 /* vsize 0x12 = 18 */
403 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x12,
404 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
405
406 /* hsize 0x05a0 = 1440 */
407 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
408 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05, /* hsize hi (output) */
409 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x12, /* vsize low (output), 0x12 = 18 */
410 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00, /* vsize hi (output) */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800411
412 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300413 R_C0_B_TASK_HANDLING_CNTL, 0x00,
414 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
415 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
416 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800417
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300418 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
419 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
420 /* hoffset low (input), 0x0002 is minimum. See comment above. */
421 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x00,
422 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800423
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300424 /* hsize 0x02d0 = 720 */
425 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
426 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
427
428 /* voffset 0x16 = 22 */
429 R_C8_B_VERT_INPUT_WINDOW_START, 0x16,
430 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
431
432 /* vsize 0x0120 = 288 */
433 R_CA_B_VERT_INPUT_WINDOW_LENGTH, 0x20,
434 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, 0x01,
435
436 /* hsize 0x02d0 = 720 */
437 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
438 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
439
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300440 R_F0_LFCO_PER_LINE, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
441 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0, (was 0x05) */
442 R_F5_PULSGEN_LINE_LENGTH, 0xb0,
443 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
444
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800445 0x00, 0x00
446};
447
448/* ============== SAA7715 VIDEO templates (end) ======= */
449
450static const unsigned char saa7115_cfg_vbi_on[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300451 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
452 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
453 R_80_GLOBAL_CNTL_1, 0x30, /* Activate both tasks */
454 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
455 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
456
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800457 0x00, 0x00
458};
459
460static const unsigned char saa7115_cfg_vbi_off[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300461 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
462 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
463 R_80_GLOBAL_CNTL_1, 0x20, /* Activate only task "B" */
464 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
465 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
466
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800467 0x00, 0x00
468};
469
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300470
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800471static const unsigned char saa7115_init_misc[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300472 R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300473 R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 0x01,
474 R_84_I_PORT_SIGNAL_DEF, 0x20,
475 R_85_I_PORT_SIGNAL_POLAR, 0x21,
476 R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT, 0xc5,
477 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800478
479 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300480 R_A0_A_HORIZ_PRESCALING, 0x01,
481 R_A1_A_ACCUMULATION_LENGTH, 0x00,
482 R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800483
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300484 /* Configure controls at nominal value*/
485 R_A4_A_LUMA_BRIGHTNESS_CNTL, 0x80,
486 R_A5_A_LUMA_CONTRAST_CNTL, 0x40,
487 R_A6_A_CHROMA_SATURATION_CNTL, 0x40,
488
489 /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
490 R_A8_A_HORIZ_LUMA_SCALING_INC, 0x00,
491 R_A9_A_HORIZ_LUMA_SCALING_INC_MSB, 0x02,
492
493 R_AA_A_HORIZ_LUMA_PHASE_OFF, 0x00,
494
495 /* must be horiz lum scaling / 2 */
496 R_AC_A_HORIZ_CHROMA_SCALING_INC, 0x00,
497 R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB, 0x01,
498
499 /* must be offset luma / 2 */
500 R_AE_A_HORIZ_CHROMA_PHASE_OFF, 0x00,
501
502 R_B0_A_VERT_LUMA_SCALING_INC, 0x00,
503 R_B1_A_VERT_LUMA_SCALING_INC_MSB, 0x04,
504
505 R_B2_A_VERT_CHROMA_SCALING_INC, 0x00,
506 R_B3_A_VERT_CHROMA_SCALING_INC_MSB, 0x04,
507
508 R_B4_A_VERT_SCALING_MODE_CNTL, 0x01,
509
510 R_B8_A_VERT_CHROMA_PHASE_OFF_00, 0x00,
511 R_B9_A_VERT_CHROMA_PHASE_OFF_01, 0x00,
512 R_BA_A_VERT_CHROMA_PHASE_OFF_10, 0x00,
513 R_BB_A_VERT_CHROMA_PHASE_OFF_11, 0x00,
514
515 R_BC_A_VERT_LUMA_PHASE_OFF_00, 0x00,
516 R_BD_A_VERT_LUMA_PHASE_OFF_01, 0x00,
517 R_BE_A_VERT_LUMA_PHASE_OFF_10, 0x00,
518 R_BF_A_VERT_LUMA_PHASE_OFF_11, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800519
520 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300521 R_D0_B_HORIZ_PRESCALING, 0x01,
522 R_D1_B_ACCUMULATION_LENGTH, 0x00,
523 R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800524
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300525 /* Configure controls at nominal value*/
526 R_D4_B_LUMA_BRIGHTNESS_CNTL, 0x80,
527 R_D5_B_LUMA_CONTRAST_CNTL, 0x40,
528 R_D6_B_CHROMA_SATURATION_CNTL, 0x40,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800529
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300530 /* hor lum scaling 0x0400 = 1 */
531 R_D8_B_HORIZ_LUMA_SCALING_INC, 0x00,
532 R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, 0x04,
533
534 R_DA_B_HORIZ_LUMA_PHASE_OFF, 0x00,
535
536 /* must be hor lum scaling / 2 */
537 R_DC_B_HORIZ_CHROMA_SCALING, 0x00,
538 R_DD_B_HORIZ_CHROMA_SCALING_MSB, 0x02,
539
540 /* must be offset luma / 2 */
541 R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA, 0x00,
542
543 R_E0_B_VERT_LUMA_SCALING_INC, 0x00,
544 R_E1_B_VERT_LUMA_SCALING_INC_MSB, 0x04,
545
546 R_E2_B_VERT_CHROMA_SCALING_INC, 0x00,
547 R_E3_B_VERT_CHROMA_SCALING_INC_MSB, 0x04,
548
549 R_E4_B_VERT_SCALING_MODE_CNTL, 0x01,
550
551 R_E8_B_VERT_CHROMA_PHASE_OFF_00, 0x00,
552 R_E9_B_VERT_CHROMA_PHASE_OFF_01, 0x00,
553 R_EA_B_VERT_CHROMA_PHASE_OFF_10, 0x00,
554 R_EB_B_VERT_CHROMA_PHASE_OFF_11, 0x00,
555
556 R_EC_B_VERT_LUMA_PHASE_OFF_00, 0x00,
557 R_ED_B_VERT_LUMA_PHASE_OFF_01, 0x00,
558 R_EE_B_VERT_LUMA_PHASE_OFF_10, 0x00,
559 R_EF_B_VERT_LUMA_PHASE_OFF_11, 0x00,
560
561 R_F2_NOMINAL_PLL2_DTO, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */
562 R_F3_PLL_INCREMENT, 0x46,
563 R_F4_PLL2_STATUS, 0x00,
564 R_F7_PULSE_A_POS_MSB, 0x4b, /* not the recommended settings! */
565 R_F8_PULSE_B_POS, 0x00,
566 R_F9_PULSE_B_POS_MSB, 0x4b,
567 R_FA_PULSE_C_POS, 0x00,
568 R_FB_PULSE_C_POS_MSB, 0x4b,
569
570 /* PLL2 lock detection settings: 71 lines 50% phase error */
571 R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES, 0x88,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800572
573 /* Turn off VBI */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300574 R_40_SLICER_CNTL_1, 0x20, /* No framing code errors allowed. */
575 R_41_LCR_BASE, 0xff,
576 R_41_LCR_BASE+1, 0xff,
577 R_41_LCR_BASE+2, 0xff,
578 R_41_LCR_BASE+3, 0xff,
579 R_41_LCR_BASE+4, 0xff,
580 R_41_LCR_BASE+5, 0xff,
581 R_41_LCR_BASE+6, 0xff,
582 R_41_LCR_BASE+7, 0xff,
583 R_41_LCR_BASE+8, 0xff,
584 R_41_LCR_BASE+9, 0xff,
585 R_41_LCR_BASE+10, 0xff,
586 R_41_LCR_BASE+11, 0xff,
587 R_41_LCR_BASE+12, 0xff,
588 R_41_LCR_BASE+13, 0xff,
589 R_41_LCR_BASE+14, 0xff,
590 R_41_LCR_BASE+15, 0xff,
591 R_41_LCR_BASE+16, 0xff,
592 R_41_LCR_BASE+17, 0xff,
593 R_41_LCR_BASE+18, 0xff,
594 R_41_LCR_BASE+19, 0xff,
595 R_41_LCR_BASE+20, 0xff,
596 R_41_LCR_BASE+21, 0xff,
597 R_41_LCR_BASE+22, 0xff,
598 R_58_PROGRAM_FRAMING_CODE, 0x40,
599 R_59_H_OFF_FOR_SLICER, 0x47,
600 R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF, 0x83,
601 R_5D_DID, 0xbd,
602 R_5E_SDID, 0x35,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800603
Devin Heitmuellerfea551f2010-02-03 00:33:48 -0300604 R_02_INPUT_CNTL_1, 0xc4, /* input tuner -> input 4, amplifier active */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800605
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300606 R_80_GLOBAL_CNTL_1, 0x20, /* enable task B */
607 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
608 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800609 0x00, 0x00
610};
611
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -0300612static int saa711x_odd_parity(u8 c)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800613{
614 c ^= (c >> 4);
615 c ^= (c >> 2);
616 c ^= (c >> 1);
617
618 return c & 1;
619}
620
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300621static int saa711x_decode_vps(u8 *dst, u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800622{
623 static const u8 biphase_tbl[] = {
624 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
625 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
626 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
627 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
628 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
629 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
630 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
631 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
632 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
633 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
634 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
635 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
636 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
637 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
638 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
639 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
640 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
641 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
642 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
643 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
644 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
645 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
646 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
647 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
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 };
657 int i;
658 u8 c, err = 0;
659
660 for (i = 0; i < 2 * 13; i += 2) {
661 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
662 c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
663 dst[i / 2] = c;
664 }
665 return err & 0xf0;
666}
667
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300668static int saa711x_decode_wss(u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800669{
670 static const int wss_bits[8] = {
671 0, 0, 0, 1, 0, 1, 1, 1
672 };
673 unsigned char parity;
674 int wss = 0;
675 int i;
676
677 for (i = 0; i < 16; i++) {
678 int b1 = wss_bits[p[i] & 7];
679 int b2 = wss_bits[(p[i] >> 3) & 7];
680
681 if (b1 == b2)
682 return -1;
683 wss |= b2 << i;
684 }
685 parity = wss & 15;
686 parity ^= parity >> 2;
687 parity ^= parity >> 1;
688
689 if (!(parity & 1))
690 return -1;
691
692 return wss;
693}
694
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300695static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800696{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300697 struct saa711x_state *state = to_state(sd);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200698 u32 acpf;
699 u32 acni;
700 u32 hz;
701 u64 f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300702 u8 acc = 0; /* reg 0x3a, audio clock control */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800703
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300704 /* Checks for chips that don't have audio clock (saa7111, saa7113) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300705 if (!saa711x_has_reg(state->ident, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300706 return 0;
707
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300708 v4l2_dbg(1, debug, sd, "set audio clock freq: %d\n", freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200709
710 /* sanity check */
711 if (freq < 32000 || freq > 48000)
712 return -EINVAL;
713
714 /* hz is the refresh rate times 100 */
715 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
716 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
717 acpf = (25600 * freq) / hz;
718 /* acni = (256 * freq * 2^23) / crystal_frequency =
719 (freq * 2^(8+23)) / crystal_frequency =
Hans Verkuilb7f82922006-04-02 12:50:42 -0300720 (freq << 31) / crystal_frequency */
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200721 f = freq;
722 f = f << 31;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300723 do_div(f, state->crystal_freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200724 acni = f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300725 if (state->ucgc) {
726 acpf = acpf * state->cgcdiv / 16;
727 acni = acni * state->cgcdiv / 16;
728 acc = 0x80;
729 if (state->cgcdiv == 3)
730 acc |= 0x40;
731 }
732 if (state->apll)
733 acc |= 0x08;
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200734
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300735 saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
736 saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10);
737 saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300738
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300739 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
740 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300741 (acpf >> 8) & 0xff);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300742 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300743 (acpf >> 16) & 0x03);
744
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300745 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
746 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
747 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800748 state->audclk_freq = freq;
749 return 0;
750}
751
Hans Verkuile3560542010-05-24 10:00:52 -0300752static int saa711x_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800753{
Hans Verkuile3560542010-05-24 10:00:52 -0300754 struct v4l2_subdev *sd = to_sd(ctrl);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300755 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800756
757 switch (ctrl->id) {
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300758 case V4L2_CID_CHROMA_AGC:
Hans Verkuile3560542010-05-24 10:00:52 -0300759 /* chroma gain cluster */
Hans Verkuilddac5c12011-06-10 05:43:34 -0300760 if (state->agc->val)
761 state->gain->val =
Hans Verkuile3560542010-05-24 10:00:52 -0300762 saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL) & 0x7f;
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300763 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800764 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800765 return 0;
766}
767
Hans Verkuile3560542010-05-24 10:00:52 -0300768static int saa711x_s_ctrl(struct v4l2_ctrl *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800769{
Hans Verkuile3560542010-05-24 10:00:52 -0300770 struct v4l2_subdev *sd = to_sd(ctrl);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300771 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800772
773 switch (ctrl->id) {
774 case V4L2_CID_BRIGHTNESS:
Hans Verkuile3560542010-05-24 10:00:52 -0300775 saa711x_write(sd, R_0A_LUMA_BRIGHT_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800776 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300777
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800778 case V4L2_CID_CONTRAST:
Hans Verkuile3560542010-05-24 10:00:52 -0300779 saa711x_write(sd, R_0B_LUMA_CONTRAST_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800780 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300781
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800782 case V4L2_CID_SATURATION:
Hans Verkuile3560542010-05-24 10:00:52 -0300783 saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800784 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300785
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800786 case V4L2_CID_HUE:
Hans Verkuile3560542010-05-24 10:00:52 -0300787 saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800788 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300789
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300790 case V4L2_CID_CHROMA_AGC:
Hans Verkuile3560542010-05-24 10:00:52 -0300791 /* chroma gain cluster */
792 if (state->agc->val)
793 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val);
794 else
795 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val | 0x80);
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300796 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300797
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800798 default:
799 return -EINVAL;
800 }
801
802 return 0;
803}
804
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300805static int saa711x_set_size(struct v4l2_subdev *sd, int width, int height)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300806{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300807 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300808 int HPSC, HFSC;
809 int VSCY;
810 int res;
811 int is_50hz = state->std & V4L2_STD_625_50;
812 int Vsrc = is_50hz ? 576 : 480;
813
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300814 v4l2_dbg(1, debug, sd, "decoder set size to %ix%i\n", width, height);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300815
816 /* FIXME need better bounds checking here */
817 if ((width < 1) || (width > 1440))
818 return -EINVAL;
819 if ((height < 1) || (height > Vsrc))
820 return -EINVAL;
821
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300822 if (!saa711x_has_reg(state->ident, R_D0_B_HORIZ_PRESCALING)) {
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300823 /* Decoder only supports 720 columns and 480 or 576 lines */
824 if (width != 720)
825 return -EINVAL;
826 if (height != Vsrc)
827 return -EINVAL;
828 }
829
830 state->width = width;
831 state->height = height;
832
833 if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
834 return 0;
835
836 /* probably have a valid size, let's set it */
837 /* Set output width/height */
838 /* width */
839
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300840 saa711x_write(sd, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300841 (u8) (width & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300842 saa711x_write(sd, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300843 (u8) ((width >> 8) & 0xff));
844
845 /* Vertical Scaling uses height/2 */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300846 res = height / 2;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300847
848 /* On 60Hz, it is using a higher Vertical Output Size */
849 if (!is_50hz)
Hans Verkuild0d30c02006-11-25 09:45:50 -0300850 res += (VRES_60HZ - 480) >> 1;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300851
852 /* height */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300853 saa711x_write(sd, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300854 (u8) (res & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300855 saa711x_write(sd, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300856 (u8) ((res >> 8) & 0xff));
857
858 /* Scaling settings */
859 /* Hprescaler is floor(inres/outres) */
860 HPSC = (int)(720 / width);
861 /* 0 is not allowed (div. by zero) */
862 HPSC = HPSC ? HPSC : 1;
863 HFSC = (int)((1024 * 720) / (HPSC * width));
864 /* FIXME hardcodes to "Task B"
865 * write H prescaler integer */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300866 saa711x_write(sd, R_D0_B_HORIZ_PRESCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300867 (u8) (HPSC & 0x3f));
868
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300869 v4l2_dbg(1, debug, sd, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300870 /* write H fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300871 saa711x_write(sd, R_D8_B_HORIZ_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300872 (u8) (HFSC & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300873 saa711x_write(sd, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300874 (u8) ((HFSC >> 8) & 0xff));
875 /* write H fine-scaling (chrominance)
876 * must be lum/2, so i'll just bitshift :) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300877 saa711x_write(sd, R_DC_B_HORIZ_CHROMA_SCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300878 (u8) ((HFSC >> 1) & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300879 saa711x_write(sd, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300880 (u8) ((HFSC >> 9) & 0xff));
881
882 VSCY = (int)((1024 * Vsrc) / height);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300883 v4l2_dbg(1, debug, sd, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300884
885 /* Correct Contrast and Luminance */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300886 saa711x_write(sd, R_D5_B_LUMA_CONTRAST_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300887 (u8) (64 * 1024 / VSCY));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300888 saa711x_write(sd, R_D6_B_CHROMA_SATURATION_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300889 (u8) (64 * 1024 / VSCY));
890
891 /* write V fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300892 saa711x_write(sd, R_E0_B_VERT_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300893 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300894 saa711x_write(sd, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300895 (u8) ((VSCY >> 8) & 0xff));
896 /* write V fine-scaling (chrominance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300897 saa711x_write(sd, R_E2_B_VERT_CHROMA_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_E3_B_VERT_CHROMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300900 (u8) ((VSCY >> 8) & 0xff));
901
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300902 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300903
904 /* Activates task "B" */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300905 saa711x_write(sd, R_80_GLOBAL_CNTL_1,
906 saa711x_read(sd, R_80_GLOBAL_CNTL_1) | 0x20);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300907
908 return 0;
909}
910
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300911static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800912{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300913 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800914
Hans Verkuil30b54d52006-01-09 15:25:43 -0200915 /* Prevent unnecessary standard changes. During a standard
916 change the I-Port is temporarily disabled. Any devices
917 reading from that port can get confused.
Hans Verkuilbccfa442009-03-30 06:55:27 -0300918 Note that s_std is also used to switch from
919 radio to TV mode, so if a s_std is broadcast to
Hans Verkuil30b54d52006-01-09 15:25:43 -0200920 all I2C devices then you do not want to have an unwanted
921 side-effect here. */
922 if (std == state->std)
923 return;
924
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300925 state->std = std;
926
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800927 // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
928 if (std & V4L2_STD_525_60) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300929 v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n");
930 saa711x_writeregs(sd, saa7115_cfg_60hz_video);
931 saa711x_set_size(sd, 720, 480);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800932 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300933 v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n");
934 saa711x_writeregs(sd, saa7115_cfg_50hz_video);
935 saa711x_set_size(sd, 720, 576);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800936 }
937
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300938 /* Register 0E - Bits D6-D4 on NO-AUTO mode
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300939 (SAA7111 and SAA7113 doesn't have auto mode)
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300940 50 Hz / 625 lines 60 Hz / 525 lines
941 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz)
942 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz)
943 010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz)
944 011 NTSC N (3.58MHz) PAL M (3.58MHz)
945 100 reserved NTSC-Japan (3.58MHz)
946 */
Hans Verkuil340dde82010-02-20 08:07:51 -0300947 if (state->ident <= V4L2_IDENT_SAA7113) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300948 u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300949
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300950 if (std == V4L2_STD_PAL_M) {
Hans Verkuil01342352006-03-25 08:19:47 -0300951 reg |= 0x30;
Hans Verkuile0028022008-04-22 14:45:51 -0300952 } else if (std == V4L2_STD_PAL_Nc) {
Hans Verkuil01342352006-03-25 08:19:47 -0300953 reg |= 0x20;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300954 } else if (std == V4L2_STD_PAL_60) {
Hans Verkuil01342352006-03-25 08:19:47 -0300955 reg |= 0x10;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300956 } else if (std == V4L2_STD_NTSC_M_JP) {
Hans Verkuil01342352006-03-25 08:19:47 -0300957 reg |= 0x40;
Mauro Carvalho Chehaba9aaec42007-03-13 13:41:49 -0300958 } else if (std & V4L2_STD_SECAM) {
Pádraig Bradyfc2fa312006-10-09 08:02:17 -0300959 reg |= 0x50;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300960 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300961 saa711x_write(sd, R_0E_CHROMA_CNTL_1, reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300962 } else {
963 /* restart task B if needed */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300964 int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300965
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300966 if (taskb && state->ident == V4L2_IDENT_SAA7114) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300967 saa711x_writeregs(sd, saa7115_cfg_vbi_on);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300968 }
969
970 /* switch audio mode too! */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300971 saa711x_s_clock_freq(sd, state->audclk_freq);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300972 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800973}
974
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800975/* setup the sliced VBI lcr registers according to the sliced VBI format */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300976static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800977{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300978 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800979 int is_50hz = (state->std & V4L2_STD_625_50);
980 u8 lcr[24];
981 int i, x;
982
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300983#if 1
984 /* saa7113/7114/7118 VBI support are experimental */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300985 if (!saa711x_has_reg(state->ident, R_41_LCR_BASE))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300986 return;
987
988#else
989 /* SAA7113 and SAA7118 also should support VBI - Need testing */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300990 if (state->ident != V4L2_IDENT_SAA7115)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800991 return;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300992#endif
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800993
994 for (i = 0; i <= 23; i++)
995 lcr[i] = 0xff;
996
Hans Verkuila8b86432008-10-04 08:05:30 -0300997 if (fmt == NULL) {
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800998 /* raw VBI */
999 if (is_50hz)
1000 for (i = 6; i <= 23; i++)
1001 lcr[i] = 0xdd;
1002 else
1003 for (i = 10; i <= 21; i++)
1004 lcr[i] = 0xdd;
1005 } else {
1006 /* sliced VBI */
1007 /* first clear lines that cannot be captured */
1008 if (is_50hz) {
1009 for (i = 0; i <= 5; i++)
1010 fmt->service_lines[0][i] =
1011 fmt->service_lines[1][i] = 0;
1012 }
1013 else {
1014 for (i = 0; i <= 9; i++)
1015 fmt->service_lines[0][i] =
1016 fmt->service_lines[1][i] = 0;
1017 for (i = 22; i <= 23; i++)
1018 fmt->service_lines[0][i] =
1019 fmt->service_lines[1][i] = 0;
1020 }
1021
1022 /* Now set the lcr values according to the specified service */
1023 for (i = 6; i <= 23; i++) {
1024 lcr[i] = 0;
1025 for (x = 0; x <= 1; x++) {
1026 switch (fmt->service_lines[1-x][i]) {
1027 case 0:
1028 lcr[i] |= 0xf << (4 * x);
1029 break;
Hans Verkuil9bc74002006-03-29 18:02:51 -03001030 case V4L2_SLICED_TELETEXT_B:
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001031 lcr[i] |= 1 << (4 * x);
1032 break;
1033 case V4L2_SLICED_CAPTION_525:
1034 lcr[i] |= 4 << (4 * x);
1035 break;
1036 case V4L2_SLICED_WSS_625:
1037 lcr[i] |= 5 << (4 * x);
1038 break;
1039 case V4L2_SLICED_VPS:
1040 lcr[i] |= 7 << (4 * x);
1041 break;
1042 }
1043 }
1044 }
1045 }
1046
1047 /* write the lcr registers */
1048 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001049 saa711x_write(sd, i - 2 + R_41_LCR_BASE, lcr[i]);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001050 }
1051
1052 /* enable/disable raw VBI capturing */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001053 saa711x_writeregs(sd, fmt == NULL ?
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001054 saa7115_cfg_vbi_on :
1055 saa7115_cfg_vbi_off);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001056}
1057
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001058static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *sliced)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001059{
1060 static u16 lcr2vbi[] = {
Hans Verkuil9bc74002006-03-29 18:02:51 -03001061 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001062 0, V4L2_SLICED_CAPTION_525, /* 4 */
1063 V4L2_SLICED_WSS_625, 0, /* 5 */
1064 V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
1065 0, 0, 0, 0
1066 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001067 int i;
1068
Hans Verkuil30634e82012-09-05 10:38:10 -03001069 memset(sliced->service_lines, 0, sizeof(sliced->service_lines));
1070 sliced->service_set = 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001071 /* done if using raw VBI */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001072 if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001073 return 0;
1074 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001075 u8 v = saa711x_read(sd, i - 2 + R_41_LCR_BASE);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001076
1077 sliced->service_lines[0][i] = lcr2vbi[v >> 4];
1078 sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
1079 sliced->service_set |=
1080 sliced->service_lines[0][i] | sliced->service_lines[1][i];
1081 }
1082 return 0;
1083}
1084
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001085static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
1086{
1087 saa711x_set_lcr(sd, NULL);
1088 return 0;
1089}
1090
1091static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
1092{
1093 saa711x_set_lcr(sd, fmt);
1094 return 0;
1095}
1096
Hans Verkuilc463d932010-05-09 09:47:23 -03001097static int saa711x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
1098{
1099 if (fmt->code != V4L2_MBUS_FMT_FIXED)
1100 return -EINVAL;
1101 fmt->field = V4L2_FIELD_INTERLACED;
1102 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1103 return saa711x_set_size(sd, fmt->width, fmt->height);
1104}
1105
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001106/* Decode the sliced VBI data stream as created by the saa7115.
1107 The format is described in the saa7115 datasheet in Tables 25 and 26
1108 and in Figure 33.
1109 The current implementation uses SAV/EAV codes and not the ancillary data
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001110 headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001111 code. */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001112static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001113{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001114 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001115 static const char vbi_no_data_pattern[] = {
1116 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
1117 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001118 u8 *p = vbi->p;
1119 u32 wss;
1120 int id1, id2; /* the ID1 and ID2 bytes from the internal header */
1121
1122 vbi->type = 0; /* mark result as a failure */
1123 id1 = p[2];
1124 id2 = p[3];
1125 /* Note: the field bit is inverted for 60 Hz video */
1126 if (state->std & V4L2_STD_525_60)
1127 id1 ^= 0x40;
1128
1129 /* Skip internal header, p now points to the start of the payload */
1130 p += 4;
1131 vbi->p = p;
1132
1133 /* calculate field and line number of the VBI packet (1-23) */
1134 vbi->is_second_field = ((id1 & 0x40) != 0);
1135 vbi->line = (id1 & 0x3f) << 3;
1136 vbi->line |= (id2 & 0x70) >> 4;
1137
1138 /* Obtain data type */
1139 id2 &= 0xf;
1140
1141 /* If the VBI slicer does not detect any signal it will fill up
1142 the payload buffer with 0xa0 bytes. */
1143 if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001144 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001145
1146 /* decode payloads */
1147 switch (id2) {
1148 case 1:
Hans Verkuil9bc74002006-03-29 18:02:51 -03001149 vbi->type = V4L2_SLICED_TELETEXT_B;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001150 break;
1151 case 4:
Mauro Carvalho Chehab59ba9152006-08-30 05:34:36 -03001152 if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001153 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001154 vbi->type = V4L2_SLICED_CAPTION_525;
1155 break;
1156 case 5:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001157 wss = saa711x_decode_wss(p);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001158 if (wss == -1)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001159 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001160 p[0] = wss & 0xff;
1161 p[1] = wss >> 8;
1162 vbi->type = V4L2_SLICED_WSS_625;
1163 break;
1164 case 7:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001165 if (saa711x_decode_vps(p, p) != 0)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001166 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001167 vbi->type = V4L2_SLICED_VPS;
1168 break;
1169 default:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001170 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001171 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001172 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001173}
1174
1175/* ============ SAA7115 AUDIO settings (end) ============= */
1176
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001177static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001178{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001179 struct saa711x_state *state = to_state(sd);
1180 int status;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001181
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001182 if (state->radio)
1183 return 0;
1184 status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001185
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001186 v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status);
1187 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1188 return 0;
1189}
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001190
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001191static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1192{
1193 struct saa711x_state *state = to_state(sd);
1194
1195 state->radio = 0;
1196 saa711x_set_v4lstd(sd, std);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001197 return 0;
1198}
1199
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001200static int saa711x_s_radio(struct v4l2_subdev *sd)
1201{
1202 struct saa711x_state *state = to_state(sd);
1203
1204 state->radio = 1;
1205 return 0;
1206}
1207
Hans Verkuil5325b422009-04-02 11:26:22 -03001208static int saa711x_s_routing(struct v4l2_subdev *sd,
1209 u32 input, u32 output, u32 config)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001210{
1211 struct saa711x_state *state = to_state(sd);
Hans Verkuil340dde82010-02-20 08:07:51 -03001212 u8 mask = (state->ident <= V4L2_IDENT_SAA7111A) ? 0xf8 : 0xf0;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001213
Hans Verkuil5325b422009-04-02 11:26:22 -03001214 v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n",
1215 input, output);
1216
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001217 /* saa7111/3 does not have these inputs */
Hans Verkuil340dde82010-02-20 08:07:51 -03001218 if (state->ident <= V4L2_IDENT_SAA7113 &&
Hans Verkuil5325b422009-04-02 11:26:22 -03001219 (input == SAA7115_COMPOSITE4 ||
1220 input == SAA7115_COMPOSITE5)) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001221 return -EINVAL;
1222 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001223 if (input > SAA7115_SVIDEO3)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001224 return -EINVAL;
Hans Verkuil5325b422009-04-02 11:26:22 -03001225 if (state->input == input && state->output == output)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001226 return 0;
1227 v4l2_dbg(1, debug, sd, "now setting %s input %s output\n",
Hans Verkuil5325b422009-04-02 11:26:22 -03001228 (input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite",
1229 (output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
1230 state->input = input;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001231
1232 /* saa7111 has slightly different input numbering */
Hans Verkuil340dde82010-02-20 08:07:51 -03001233 if (state->ident <= V4L2_IDENT_SAA7111A) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001234 if (input >= SAA7115_COMPOSITE4)
1235 input -= 2;
1236 /* saa7111 specific */
1237 saa711x_write(sd, R_10_CHROMA_CNTL_2,
1238 (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001239 ((output & 0xc0) ^ 0x40));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001240 saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL,
1241 (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001242 ((output & 2) ? 0x0a : 0));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001243 }
1244
1245 /* select mode */
1246 saa711x_write(sd, R_02_INPUT_CNTL_1,
1247 (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) |
1248 input);
1249
1250 /* bypass chrominance trap for S-Video modes */
1251 saa711x_write(sd, R_09_LUMA_CNTL,
1252 (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) |
1253 (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
1254
Hans Verkuil5325b422009-04-02 11:26:22 -03001255 state->output = output;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001256 if (state->ident == V4L2_IDENT_SAA7114 ||
1257 state->ident == V4L2_IDENT_SAA7115) {
1258 saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
1259 (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
1260 (state->output & 0x01));
1261 }
1262 return 0;
1263}
1264
1265static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val)
1266{
1267 struct saa711x_state *state = to_state(sd);
1268
Hans Verkuil340dde82010-02-20 08:07:51 -03001269 if (state->ident > V4L2_IDENT_SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001270 return -EINVAL;
1271 saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) |
1272 (val ? 0x80 : 0));
1273 return 0;
1274}
1275
1276static int saa711x_s_stream(struct v4l2_subdev *sd, int enable)
1277{
1278 struct saa711x_state *state = to_state(sd);
1279
1280 v4l2_dbg(1, debug, sd, "%s output\n",
1281 enable ? "enable" : "disable");
1282
Hans Verkuil674a3232009-02-18 12:22:16 -03001283 if (state->enable == enable)
1284 return 0;
1285 state->enable = enable;
1286 if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED))
1287 return 0;
1288 saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001289 return 0;
1290}
1291
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001292static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001293{
1294 struct saa711x_state *state = to_state(sd);
1295
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001296 if (freq != SAA7115_FREQ_32_11_MHZ && freq != SAA7115_FREQ_24_576_MHZ)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001297 return -EINVAL;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001298 state->crystal_freq = freq;
1299 state->cgcdiv = (flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
1300 state->ucgc = (flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;
1301 state->apll = (flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001302 saa711x_s_clock_freq(sd, state->audclk_freq);
1303 return 0;
1304}
1305
1306static int saa711x_reset(struct v4l2_subdev *sd, u32 val)
1307{
1308 v4l2_dbg(1, debug, sd, "decoder RESET\n");
1309 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
1310 return 0;
1311}
1312
1313static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data)
1314{
1315 /* Note: the internal field ID is inverted for NTSC,
1316 so data->field 0 maps to the saa7115 even field,
1317 whereas for PAL it maps to the saa7115 odd field. */
1318 switch (data->id) {
1319 case V4L2_SLICED_WSS_625:
1320 if (saa711x_read(sd, 0x6b) & 0xc0)
1321 return -EIO;
1322 data->data[0] = saa711x_read(sd, 0x6c);
1323 data->data[1] = saa711x_read(sd, 0x6d);
1324 return 0;
1325 case V4L2_SLICED_CAPTION_525:
1326 if (data->field == 0) {
1327 /* CC */
1328 if (saa711x_read(sd, 0x66) & 0x30)
1329 return -EIO;
1330 data->data[0] = saa711x_read(sd, 0x69);
1331 data->data[1] = saa711x_read(sd, 0x6a);
1332 return 0;
1333 }
1334 /* XDS */
1335 if (saa711x_read(sd, 0x66) & 0xc0)
1336 return -EIO;
1337 data->data[0] = saa711x_read(sd, 0x67);
1338 data->data[1] = saa711x_read(sd, 0x68);
1339 return 0;
1340 default:
1341 return -EINVAL;
1342 }
1343}
1344
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001345static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
1346{
1347 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001348 int reg1f, reg1e;
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001349
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001350 /*
1351 * The V4L2 core already initializes std with all supported
1352 * Standards. All driver needs to do is to mask it, to remove
1353 * standards that don't apply from the mask
1354 */
1355
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001356 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1357 v4l2_dbg(1, debug, sd, "Status byte 2 (0x1f)=0x%02x\n", reg1f);
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001358
1359 /* horizontal/vertical not locked */
1360 if (reg1f & 0x40)
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001361 goto ret;
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001362
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001363 if (reg1f & 0x20)
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001364 *std &= V4L2_STD_525_60;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001365 else
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001366 *std &= V4L2_STD_625_50;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001367
1368 if (state->ident != V4L2_IDENT_SAA7115)
1369 goto ret;
Anatolij Gustschinf9d7d782010-12-22 17:31:58 -03001370
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001371 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1372
1373 switch (reg1e & 0x03) {
1374 case 1:
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001375 *std &= V4L2_STD_NTSC;
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001376 break;
1377 case 2:
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001378 /*
1379 * V4L2_STD_PAL just cover the european PAL standards.
1380 * This is wrong, as the device could also be using an
1381 * other PAL standard.
1382 */
1383 *std &= V4L2_STD_PAL | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc |
1384 V4L2_STD_PAL_M | V4L2_STD_PAL_60;
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001385 break;
1386 case 3:
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001387 *std &= V4L2_STD_SECAM;
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001388 break;
1389 default:
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001390 /* Can't detect anything */
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001391 break;
1392 }
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001393
1394 v4l2_dbg(1, debug, sd, "Status byte 1 (0x1e)=0x%02x\n", reg1e);
1395
1396ret:
1397 v4l2_dbg(1, debug, sd, "detected std mask = %08Lx\n", *std);
1398
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001399 return 0;
1400}
1401
1402static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status)
1403{
1404 struct saa711x_state *state = to_state(sd);
1405 int reg1e = 0x80;
1406 int reg1f;
1407
1408 *status = V4L2_IN_ST_NO_SIGNAL;
1409 if (state->ident == V4L2_IDENT_SAA7115)
1410 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1411 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1412 if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80)
1413 *status = 0;
1414 return 0;
1415}
1416
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001417#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001418static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001419{
1420 struct i2c_client *client = v4l2_get_subdevdata(sd);
1421
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001422 if (!v4l2_chip_match_i2c_client(client, &reg->match))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001423 return -EINVAL;
1424 if (!capable(CAP_SYS_ADMIN))
1425 return -EPERM;
1426 reg->val = saa711x_read(sd, reg->reg & 0xff);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001427 reg->size = 1;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001428 return 0;
1429}
1430
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001431static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001432{
1433 struct i2c_client *client = v4l2_get_subdevdata(sd);
1434
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001435 if (!v4l2_chip_match_i2c_client(client, &reg->match))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001436 return -EINVAL;
1437 if (!capable(CAP_SYS_ADMIN))
1438 return -EPERM;
1439 saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff);
1440 return 0;
1441}
1442#endif
1443
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001444static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001445{
1446 struct saa711x_state *state = to_state(sd);
1447 struct i2c_client *client = v4l2_get_subdevdata(sd);
1448
1449 return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0);
1450}
1451
1452static int saa711x_log_status(struct v4l2_subdev *sd)
1453{
1454 struct saa711x_state *state = to_state(sd);
1455 int reg1e, reg1f;
1456 int signalOk;
1457 int vcr;
1458
1459 v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq);
1460 if (state->ident != V4L2_IDENT_SAA7115) {
1461 /* status for the saa7114 */
1462 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1463 signalOk = (reg1f & 0xc1) == 0x81;
1464 v4l2_info(sd, "Video signal: %s\n", signalOk ? "ok" : "bad");
1465 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1466 return 0;
1467 }
1468
1469 /* status for the saa7115 */
1470 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1471 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1472
1473 signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
1474 vcr = !(reg1f & 0x10);
1475
1476 if (state->input >= 6)
1477 v4l2_info(sd, "Input: S-Video %d\n", state->input - 6);
1478 else
1479 v4l2_info(sd, "Input: Composite %d\n", state->input);
1480 v4l2_info(sd, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
1481 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1482
1483 switch (reg1e & 0x03) {
1484 case 1:
1485 v4l2_info(sd, "Detected format: NTSC\n");
1486 break;
1487 case 2:
1488 v4l2_info(sd, "Detected format: PAL\n");
1489 break;
1490 case 3:
1491 v4l2_info(sd, "Detected format: SECAM\n");
1492 break;
1493 default:
1494 v4l2_info(sd, "Detected format: BW/No color\n");
1495 break;
1496 }
1497 v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height);
Hans Verkuile3560542010-05-24 10:00:52 -03001498 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001499 return 0;
1500}
1501
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001502/* ----------------------------------------------------------------------- */
1503
Hans Verkuile3560542010-05-24 10:00:52 -03001504static const struct v4l2_ctrl_ops saa711x_ctrl_ops = {
1505 .s_ctrl = saa711x_s_ctrl,
1506 .g_volatile_ctrl = saa711x_g_volatile_ctrl,
1507};
1508
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001509static const struct v4l2_subdev_core_ops saa711x_core_ops = {
1510 .log_status = saa711x_log_status,
1511 .g_chip_ident = saa711x_g_chip_ident,
Hans Verkuile3560542010-05-24 10:00:52 -03001512 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
1513 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
1514 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
1515 .g_ctrl = v4l2_subdev_g_ctrl,
1516 .s_ctrl = v4l2_subdev_s_ctrl,
1517 .queryctrl = v4l2_subdev_queryctrl,
1518 .querymenu = v4l2_subdev_querymenu,
Hans Verkuilf41737e2009-04-01 03:52:39 -03001519 .s_std = saa711x_s_std,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001520 .reset = saa711x_reset,
1521 .s_gpio = saa711x_s_gpio,
1522#ifdef CONFIG_VIDEO_ADV_DEBUG
1523 .g_register = saa711x_g_register,
1524 .s_register = saa711x_s_register,
1525#endif
1526};
1527
1528static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001529 .s_radio = saa711x_s_radio,
1530 .g_tuner = saa711x_g_tuner,
1531};
1532
1533static const struct v4l2_subdev_audio_ops saa711x_audio_ops = {
1534 .s_clock_freq = saa711x_s_clock_freq,
1535};
1536
1537static const struct v4l2_subdev_video_ops saa711x_video_ops = {
1538 .s_routing = saa711x_s_routing,
1539 .s_crystal_freq = saa711x_s_crystal_freq,
Hans Verkuilc463d932010-05-09 09:47:23 -03001540 .s_mbus_fmt = saa711x_s_mbus_fmt,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001541 .s_stream = saa711x_s_stream,
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001542 .querystd = saa711x_querystd,
1543 .g_input_status = saa711x_g_input_status,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001544};
1545
Hans Verkuil32cd5272010-03-14 09:57:30 -03001546static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = {
1547 .g_vbi_data = saa711x_g_vbi_data,
1548 .decode_vbi_line = saa711x_decode_vbi_line,
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001549 .g_sliced_fmt = saa711x_g_sliced_fmt,
1550 .s_sliced_fmt = saa711x_s_sliced_fmt,
1551 .s_raw_fmt = saa711x_s_raw_fmt,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001552};
1553
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001554static const struct v4l2_subdev_ops saa711x_ops = {
1555 .core = &saa711x_core_ops,
1556 .tuner = &saa711x_tuner_ops,
1557 .audio = &saa711x_audio_ops,
1558 .video = &saa711x_video_ops,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001559 .vbi = &saa711x_vbi_ops,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001560};
1561
1562/* ----------------------------------------------------------------------- */
1563
1564static int saa711x_probe(struct i2c_client *client,
Jean Delvared2653e92008-04-29 23:11:39 +02001565 const struct i2c_device_id *id)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001566{
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001567 struct saa711x_state *state;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001568 struct v4l2_subdev *sd;
Hans Verkuile3560542010-05-24 10:00:52 -03001569 struct v4l2_ctrl_handler *hdl;
1570 int i;
1571 char name[17];
Jean Delvareaf294862008-05-18 20:49:40 +02001572 char chip_id;
1573 int autodetect = !id || id->driver_data == 1;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001574
1575 /* Check if the adapter supports the needed features */
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001576 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
Hans Verkuil188f3452007-09-16 10:47:15 -03001577 return -EIO;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001578
Hans Verkuild0d30c02006-11-25 09:45:50 -03001579 for (i = 0; i < 0x0f; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001580 i2c_smbus_write_byte_data(client, 0, i);
1581 name[i] = (i2c_smbus_read_byte_data(client, 0) & 0x0f) + '0';
Hans Verkuild0d30c02006-11-25 09:45:50 -03001582 if (name[i] > '9')
1583 name[i] += 'a' - '9' - 1;
Mauro Carvalho Chehab236f16d2006-08-28 08:25:29 -03001584 }
Hans Verkuild0d30c02006-11-25 09:45:50 -03001585 name[i] = '\0';
Mauro Carvalho Chehab236f16d2006-08-28 08:25:29 -03001586
Jean Delvareaf294862008-05-18 20:49:40 +02001587 chip_id = name[5];
Mauro Carvalho Chehab3e7d3e52006-09-01 18:39:05 -03001588
Hans Verkuilf7668162006-11-25 09:40:28 -03001589 /* Check whether this chip is part of the saa711x series */
Russell Kingbed3c1d2011-01-30 10:03:30 -03001590 if (memcmp(name + 1, "f711", 4)) {
Hans Verkuilf7668162006-11-25 09:40:28 -03001591 v4l_dbg(1, debug, client, "chip found @ 0x%x (ID %s) does not match a known saa711x chip.\n",
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001592 client->addr << 1, name);
Hans Verkuil188f3452007-09-16 10:47:15 -03001593 return -ENODEV;
Hans Verkuilf7668162006-11-25 09:40:28 -03001594 }
1595
Jean Delvareaf294862008-05-18 20:49:40 +02001596 /* Safety check */
1597 if (!autodetect && id->name[6] != chip_id) {
1598 v4l_warn(client, "found saa711%c while %s was expected\n",
1599 chip_id, id->name);
1600 }
1601 snprintf(client->name, sizeof(client->name), "saa711%c", chip_id);
1602 v4l_info(client, "saa711%c found (%s) @ 0x%x (%s)\n", chip_id, name,
1603 client->addr << 1, client->adapter->name);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001604
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001605 state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL);
Hans Verkuilc5bf2042008-09-03 17:12:09 -03001606 if (state == NULL)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001607 return -ENOMEM;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001608 sd = &state->sd;
1609 v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
Hans Verkuile3560542010-05-24 10:00:52 -03001610
1611 hdl = &state->hdl;
1612 v4l2_ctrl_handler_init(hdl, 6);
1613 /* add in ascending ID order */
1614 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1615 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1616 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1617 V4L2_CID_CONTRAST, 0, 127, 1, 64);
1618 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1619 V4L2_CID_SATURATION, 0, 127, 1, 64);
1620 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1621 V4L2_CID_HUE, -128, 127, 1, 0);
1622 state->agc = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1623 V4L2_CID_CHROMA_AGC, 0, 1, 1, 1);
1624 state->gain = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1625 V4L2_CID_CHROMA_GAIN, 0, 127, 1, 40);
Hans Verkuile3560542010-05-24 10:00:52 -03001626 sd->ctrl_handler = hdl;
1627 if (hdl->error) {
1628 int err = hdl->error;
1629
1630 v4l2_ctrl_handler_free(hdl);
1631 kfree(state);
1632 return err;
1633 }
Hans Verkuil6f43dbf2011-08-26 08:46:29 -03001634 v4l2_ctrl_auto_cluster(2, &state->agc, 0, true);
Hans Verkuile3560542010-05-24 10:00:52 -03001635
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001636 state->input = -1;
Marco Schluessler4cbca182007-01-21 19:43:38 -03001637 state->output = SAA7115_IPORT_ON;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001638 state->enable = 1;
Hans Verkuil3faeeae2006-01-09 15:25:44 -02001639 state->radio = 0;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001640 switch (chip_id) {
Jean Delvareaf294862008-05-18 20:49:40 +02001641 case '1':
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001642 state->ident = V4L2_IDENT_SAA7111;
Hans Verkuil340dde82010-02-20 08:07:51 -03001643 if (saa711x_read(sd, R_00_CHIP_VERSION) & 0xf0) {
1644 v4l_info(client, "saa7111a variant found\n");
1645 state->ident = V4L2_IDENT_SAA7111A;
1646 }
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001647 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001648 case '3':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001649 state->ident = V4L2_IDENT_SAA7113;
1650 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001651 case '4':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001652 state->ident = V4L2_IDENT_SAA7114;
1653 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001654 case '5':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001655 state->ident = V4L2_IDENT_SAA7115;
1656 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001657 case '8':
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001658 state->ident = V4L2_IDENT_SAA7118;
1659 break;
1660 default:
1661 state->ident = V4L2_IDENT_SAA7111;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001662 v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n");
Hans Verkuil340dde82010-02-20 08:07:51 -03001663 break;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001664 }
1665
Hans Verkuil3578d3d2006-01-09 15:25:41 -02001666 state->audclk_freq = 48000;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001667
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001668 v4l2_dbg(1, debug, sd, "writing init values\n");
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001669
1670 /* init to 60hz/48khz */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001671 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
1672 switch (state->ident) {
1673 case V4L2_IDENT_SAA7111:
Hans Verkuil340dde82010-02-20 08:07:51 -03001674 case V4L2_IDENT_SAA7111A:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001675 saa711x_writeregs(sd, saa7111_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001676 break;
1677 case V4L2_IDENT_SAA7113:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001678 saa711x_writeregs(sd, saa7113_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001679 break;
1680 default:
Hans Verkuilb7f82922006-04-02 12:50:42 -03001681 state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001682 saa711x_writeregs(sd, saa7115_init_auto_input);
Hans Verkuilb7f82922006-04-02 12:50:42 -03001683 }
Hans Verkuil340dde82010-02-20 08:07:51 -03001684 if (state->ident > V4L2_IDENT_SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001685 saa711x_writeregs(sd, saa7115_init_misc);
1686 saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
Hans Verkuile3560542010-05-24 10:00:52 -03001687 v4l2_ctrl_handler_setup(hdl);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001688
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001689 v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n",
1690 saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC),
1691 saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001692 return 0;
1693}
1694
1695/* ----------------------------------------------------------------------- */
1696
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001697static int saa711x_remove(struct i2c_client *client)
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001698{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001699 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1700
1701 v4l2_device_unregister_subdev(sd);
Hans Verkuile3560542010-05-24 10:00:52 -03001702 v4l2_ctrl_handler_free(sd->ctrl_handler);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001703 kfree(to_state(sd));
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001704 return 0;
1705}
1706
Hans Verkuilaac23532010-09-15 15:04:55 -03001707static const struct i2c_device_id saa711x_id[] = {
Hans Verkuil9edd350f2008-07-17 13:22:51 -03001708 { "saa7115_auto", 1 }, /* autodetect */
Jean Delvareaf294862008-05-18 20:49:40 +02001709 { "saa7111", 0 },
1710 { "saa7113", 0 },
1711 { "saa7114", 0 },
1712 { "saa7115", 0 },
1713 { "saa7118", 0 },
1714 { }
1715};
Hans Verkuilaac23532010-09-15 15:04:55 -03001716MODULE_DEVICE_TABLE(i2c, saa711x_id);
Jean Delvareaf294862008-05-18 20:49:40 +02001717
Hans Verkuilaac23532010-09-15 15:04:55 -03001718static struct i2c_driver saa711x_driver = {
1719 .driver = {
1720 .owner = THIS_MODULE,
1721 .name = "saa7115",
1722 },
1723 .probe = saa711x_probe,
1724 .remove = saa711x_remove,
1725 .id_table = saa711x_id,
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001726};
Hans Verkuilaac23532010-09-15 15:04:55 -03001727
Axel Linc6e8d862012-02-12 06:56:32 -03001728module_i2c_driver(saa711x_driver);