blob: 7d11660922f47d188fe5181fea97cecedacdb979 [file] [log] [blame]
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001/* saa711x - Philips SAA711x video decoder driver
2 * This driver can work with saa7111, saa7111a, saa7113, saa7114,
3 * saa7115 and saa7118.
Hans Verkuile19b2fc2005-11-13 16:08:04 -08004 *
5 * Based on saa7114 driver by Maxim Yevtyushkin, which is based on
6 * the saa7111 driver by Dave Perks.
7 *
8 * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
9 * Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
10 *
11 * Slight changes for video timing and attachment output by
12 * Wolfgang Scherr <scherr@net4you.net>
13 *
14 * Moved over to the linux >= 2.4.x i2c protocol (1/1/2003)
15 * by Ronald Bultje <rbultje@ronald.bitfreak.net>
16 *
17 * Added saa7115 support by Kevin Thayer <nufan_wfk at yahoo.com>
18 * (2/17/2003)
19 *
20 * VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@xs4all.nl>
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -030021 *
22 * Copyright (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
23 * SAA7111, SAA7113 and SAA7118 support
Hans Verkuile19b2fc2005-11-13 16:08:04 -080024 *
25 * This program is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU General Public License
27 * as published by the Free Software Foundation; either version 2
28 * of the License, or (at your option) any later version.
29 *
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
34 *
35 * You should have received a copy of the GNU General Public License
36 * along with this program; if not, write to the Free Software
37 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
38 */
39
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -030040#include "saa711x_regs.h"
Hans Verkuile19b2fc2005-11-13 16:08:04 -080041
42#include <linux/kernel.h>
43#include <linux/module.h>
44#include <linux/slab.h>
45#include <linux/i2c.h>
46#include <linux/videodev2.h>
Hans Verkuil9415f4b2008-11-29 12:55:19 -030047#include <media/v4l2-device.h>
Hans Verkuil3434eb72007-04-27 12:31:08 -030048#include <media/v4l2-chip-ident.h>
Hans Verkuilef6078e2009-03-29 17:32:35 -030049#include <media/v4l2-i2c-drv.h>
Hans Verkuil1f8f5fa2006-03-25 09:20:28 -030050#include <media/saa7115.h>
Hans Verkuil3578d3d2006-01-09 15:25:41 -020051#include <asm/div64.h>
Hans Verkuile19b2fc2005-11-13 16:08:04 -080052
Mauro Carvalho Chehab97d9e802006-09-03 09:38:11 -030053#define VRES_60HZ (480+16)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -030054
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -030055MODULE_DESCRIPTION("Philips SAA7111/SAA7113/SAA7114/SAA7115/SAA7118 video decoder driver");
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -030056MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
57 "Hans Verkuil, Mauro Carvalho Chehab");
Hans Verkuile19b2fc2005-11-13 16:08:04 -080058MODULE_LICENSE("GPL");
59
Douglas Schilling Landgrafff699e62008-04-22 14:41:48 -030060static int debug;
Hans Verkuilfac9e892006-01-09 15:32:40 -020061module_param(debug, bool, 0644);
Hans Verkuile19b2fc2005-11-13 16:08:04 -080062
63MODULE_PARM_DESC(debug, "Debug level (0-1)");
64
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 Verkuile19b2fc2005-11-13 16:08:04 -080068 v4l2_std_id std;
69 int input;
Marco Schluessler4cbca182007-01-21 19:43:38 -030070 int output;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080071 int enable;
Hans Verkuil3faeeae2006-01-09 15:25:44 -020072 int radio;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080073 int bright;
74 int contrast;
75 int hue;
76 int sat;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -030077 int width;
78 int height;
Hans Verkuil3434eb72007-04-27 12:31:08 -030079 u32 ident;
Hans Verkuil3578d3d2006-01-09 15:25:41 -020080 u32 audclk_freq;
Hans Verkuilb7f82922006-04-02 12:50:42 -030081 u32 crystal_freq;
82 u8 ucgc;
83 u8 cgcdiv;
84 u8 apll;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080085};
86
Hans Verkuil9415f4b2008-11-29 12:55:19 -030087static inline struct saa711x_state *to_state(struct v4l2_subdev *sd)
88{
89 return container_of(sd, struct saa711x_state, sd);
90}
91
Hans Verkuile19b2fc2005-11-13 16:08:04 -080092/* ----------------------------------------------------------------------- */
93
Hans Verkuil9415f4b2008-11-29 12:55:19 -030094static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value)
Hans Verkuile19b2fc2005-11-13 16:08:04 -080095{
Hans Verkuil9415f4b2008-11-29 12:55:19 -030096 struct i2c_client *client = v4l2_get_subdevdata(sd);
97
Hans Verkuile19b2fc2005-11-13 16:08:04 -080098 return i2c_smbus_write_byte_data(client, reg, value);
99}
100
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300101/* Sanity routine to check if a register is present */
102static int saa711x_has_reg(const int id, const u8 reg)
103{
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300104 if (id == V4L2_IDENT_SAA7111)
105 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
106 (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e;
Hans Verkuil340dde82010-02-20 08:07:51 -0300107 if (id == V4L2_IDENT_SAA7111A)
108 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
109 reg != 0x14 && reg != 0x18 && reg != 0x19 &&
110 reg != 0x1d && reg != 0x1e;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300111
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300112 /* common for saa7113/4/5/8 */
113 if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f ||
114 reg == 0xa3 || reg == 0xa7 || reg == 0xab || reg == 0xaf || (reg >= 0xb5 && reg <= 0xb7) ||
115 reg == 0xd3 || reg == 0xd7 || reg == 0xdb || reg == 0xdf || (reg >= 0xe5 && reg <= 0xe7) ||
116 reg == 0x82 || (reg >= 0x89 && reg <= 0x8e)))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300117 return 0;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300118
119 switch (id) {
120 case V4L2_IDENT_SAA7113:
121 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
122 reg != 0x5d && reg < 0x63;
123 case V4L2_IDENT_SAA7114:
124 return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
125 (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
126 reg != 0x81 && reg < 0xf0;
127 case V4L2_IDENT_SAA7115:
128 return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe);
129 case V4L2_IDENT_SAA7118:
130 return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
131 (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
132 (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
133 }
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300134 return 1;
135}
136
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300137static int saa711x_writeregs(struct v4l2_subdev *sd, const unsigned char *regs)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800138{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300139 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800140 unsigned char reg, data;
141
142 while (*regs != 0x00) {
143 reg = *(regs++);
144 data = *(regs++);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300145
146 /* According with datasheets, reserved regs should be
147 filled with 0 - seems better not to touch on they */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300148 if (saa711x_has_reg(state->ident, reg)) {
149 if (saa711x_write(sd, reg, data) < 0)
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300150 return -1;
Mauro Carvalho Chehabd87edf22006-09-01 09:37:11 -0300151 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300152 v4l2_dbg(1, debug, sd, "tried to access reserved reg 0x%02x\n", reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300153 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800154 }
155 return 0;
156}
157
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300158static inline int saa711x_read(struct v4l2_subdev *sd, u8 reg)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800159{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300160 struct i2c_client *client = v4l2_get_subdevdata(sd);
161
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800162 return i2c_smbus_read_byte_data(client, reg);
163}
164
165/* ----------------------------------------------------------------------- */
166
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300167/* SAA7111 initialization table */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300168static const unsigned char saa7111_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300169 R_01_INC_DELAY, 0x00, /* reserved */
170
171 /*front end */
172 R_02_INPUT_CNTL_1, 0xd0, /* FUSE=3, GUDL=2, MODE=0 */
173 R_03_INPUT_CNTL_2, 0x23, /* HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0,
174 * GAFIX=0, GAI1=256, GAI2=256 */
175 R_04_INPUT_CNTL_3, 0x00, /* GAI1=256 */
176 R_05_INPUT_CNTL_4, 0x00, /* GAI2=256 */
177
178 /* decoder */
179 R_06_H_SYNC_START, 0xf3, /* HSB at 13(50Hz) / 17(60Hz)
180 * pixels after end of last line */
181 R_07_H_SYNC_STOP, 0xe8, /* HSS seems to be needed to
182 * work with NTSC, too */
183 R_08_SYNC_CNTL, 0xc8, /* AUFD=1, FSEL=1, EXFIL=0,
184 * VTRC=1, HPLL=0, VNOI=0 */
185 R_09_LUMA_CNTL, 0x01, /* BYPS=0, PREF=0, BPSS=0,
186 * VBLB=0, UPTCV=0, APER=1 */
187 R_0A_LUMA_BRIGHT_CNTL, 0x80,
188 R_0B_LUMA_CONTRAST_CNTL, 0x47, /* 0b - CONT=1.109 */
189 R_0C_CHROMA_SAT_CNTL, 0x40,
190 R_0D_CHROMA_HUE_CNTL, 0x00,
191 R_0E_CHROMA_CNTL_1, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0,
192 * FCTC=0, CHBW=1 */
193 R_0F_CHROMA_GAIN_CNTL, 0x00, /* reserved */
194 R_10_CHROMA_CNTL_2, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
195 R_11_MODE_DELAY_CNTL, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
196 * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
197 R_12_RT_SIGNAL_CNTL, 0x00, /* 12 - output control 2 */
198 R_13_RT_X_PORT_OUT_CNTL, 0x00, /* 13 - output control 3 */
199 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
200 R_15_VGATE_START_FID_CHG, 0x00,
201 R_16_VGATE_STOP, 0x00,
202 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
203
204 0x00, 0x00
205};
206
207/* SAA7113 init codes */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300208static const unsigned char saa7113_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300209 R_01_INC_DELAY, 0x08,
210 R_02_INPUT_CNTL_1, 0xc2,
211 R_03_INPUT_CNTL_2, 0x30,
212 R_04_INPUT_CNTL_3, 0x00,
213 R_05_INPUT_CNTL_4, 0x00,
214 R_06_H_SYNC_START, 0x89,
215 R_07_H_SYNC_STOP, 0x0d,
216 R_08_SYNC_CNTL, 0x88,
217 R_09_LUMA_CNTL, 0x01,
218 R_0A_LUMA_BRIGHT_CNTL, 0x80,
219 R_0B_LUMA_CONTRAST_CNTL, 0x47,
220 R_0C_CHROMA_SAT_CNTL, 0x40,
221 R_0D_CHROMA_HUE_CNTL, 0x00,
222 R_0E_CHROMA_CNTL_1, 0x01,
223 R_0F_CHROMA_GAIN_CNTL, 0x2a,
224 R_10_CHROMA_CNTL_2, 0x08,
225 R_11_MODE_DELAY_CNTL, 0x0c,
226 R_12_RT_SIGNAL_CNTL, 0x07,
227 R_13_RT_X_PORT_OUT_CNTL, 0x00,
228 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
229 R_15_VGATE_START_FID_CHG, 0x00,
230 R_16_VGATE_STOP, 0x00,
231 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
232
233 0x00, 0x00
234};
235
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800236/* If a value differs from the Hauppauge driver values, then the comment starts with
237 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
238 Hauppauge driver sets. */
239
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300240/* SAA7114 and SAA7115 initialization table */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800241static const unsigned char saa7115_init_auto_input[] = {
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300242 /* Front-End Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300243 R_01_INC_DELAY, 0x48, /* white peak control disabled */
244 R_03_INPUT_CNTL_2, 0x20, /* was 0x30. 0x20: long vertical blanking */
245 R_04_INPUT_CNTL_3, 0x90, /* analog gain set to 0 */
246 R_05_INPUT_CNTL_4, 0x90, /* analog gain set to 0 */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300247 /* Decoder Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300248 R_06_H_SYNC_START, 0xeb, /* horiz sync begin = -21 */
249 R_07_H_SYNC_STOP, 0xe0, /* horiz sync stop = -17 */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300250 R_09_LUMA_CNTL, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300251 R_0A_LUMA_BRIGHT_CNTL, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */
252 R_0B_LUMA_CONTRAST_CNTL, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */
253 R_0C_CHROMA_SAT_CNTL, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */
254 R_0D_CHROMA_HUE_CNTL, 0x00,
255 R_0F_CHROMA_GAIN_CNTL, 0x00, /* use automatic gain */
256 R_10_CHROMA_CNTL_2, 0x06, /* chroma: active adaptive combfilter */
257 R_11_MODE_DELAY_CNTL, 0x00,
258 R_12_RT_SIGNAL_CNTL, 0x9d, /* RTS0 output control: VGATE */
259 R_13_RT_X_PORT_OUT_CNTL, 0x80, /* ITU656 standard mode, RTCO output enable RTCE */
260 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
261 R_18_RAW_DATA_GAIN_CNTL, 0x40, /* gain 0x00 = nominal */
262 R_19_RAW_DATA_OFF_CNTL, 0x80,
263 R_1A_COLOR_KILL_LVL_CNTL, 0x77, /* recommended value */
264 R_1B_MISC_TVVCRDET, 0x42, /* recommended value */
265 R_1C_ENHAN_COMB_CTRL1, 0xa9, /* recommended value */
266 R_1D_ENHAN_COMB_CTRL2, 0x01, /* recommended value */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300267
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300268
269 R_80_GLOBAL_CNTL_1, 0x0, /* No tasks enabled at init */
270
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300271 /* Power Device Control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300272 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset device */
273 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* set device programmed, all in operational mode */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800274 0x00, 0x00
275};
276
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300277/* Used to reset saa7113, saa7114 and saa7115 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800278static const unsigned char saa7115_cfg_reset_scaler[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300279 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00, /* disable I-port output */
280 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
281 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
282 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* enable I-port output */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800283 0x00, 0x00
284};
285
286/* ============== SAA7715 VIDEO templates ============= */
287
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800288static const unsigned char saa7115_cfg_60hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300289 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
290 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800291
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300292 R_15_VGATE_START_FID_CHG, 0x03,
293 R_16_VGATE_STOP, 0x11,
294 R_17_MISC_VGATE_CONF_AND_MSB, 0x9c,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800295
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300296 R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
297 R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800298
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300299 R_5A_V_OFF_FOR_SLICER, 0x06, /* standard 60hz value for ITU656 line counting */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800300
301 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300302 R_90_A_TASK_HANDLING_CNTL, 0x80,
303 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
304 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
305 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
306
307 /* hoffset low (input), 0x0002 is minimum */
308 R_94_A_HORIZ_INPUT_WINDOW_START, 0x01,
309 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
310
311 /* hsize low (input), 0x02d0 = 720 */
312 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
313 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
314
315 R_98_A_VERT_INPUT_WINDOW_START, 0x05,
316 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
317
318 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x0c,
319 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
320
321 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
322 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
323
324 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x0c,
325 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800326
327 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300328 R_C0_B_TASK_HANDLING_CNTL, 0x00,
329 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
330 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
331 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800332
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300333 /* 0x0002 is minimum */
334 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x02,
335 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800336
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300337 /* 0x02d0 = 720 */
338 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
339 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
340
341 /* vwindow start 0x12 = 18 */
342 R_C8_B_VERT_INPUT_WINDOW_START, 0x12,
343 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
344
345 /* vwindow length 0xf8 = 248 */
Mauro Carvalho Chehab97d9e802006-09-03 09:38:11 -0300346 R_CA_B_VERT_INPUT_WINDOW_LENGTH, VRES_60HZ>>1,
347 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, VRES_60HZ>>9,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300348
349 /* hwindow 0x02d0 = 720 */
350 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
351 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
352
353 R_F0_LFCO_PER_LINE, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
354 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0 */
355 R_F5_PULSGEN_LINE_LENGTH, 0xad,
356 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
357
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800358 0x00, 0x00
359};
360
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800361static const unsigned char saa7115_cfg_50hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300362 R_80_GLOBAL_CNTL_1, 0x00,
363 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800364
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300365 R_15_VGATE_START_FID_CHG, 0x37, /* VGATE start */
366 R_16_VGATE_STOP, 0x16,
367 R_17_MISC_VGATE_CONF_AND_MSB, 0x99,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800368
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300369 R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */
370 R_0E_CHROMA_CNTL_1, 0x07,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800371
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300372 R_5A_V_OFF_FOR_SLICER, 0x03, /* standard 50hz value */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800373
374 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300375 R_90_A_TASK_HANDLING_CNTL, 0x81,
376 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
377 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
378 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
379
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800380 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
381 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300382 /* hoffset low (input), 0x0002 is minimum */
383 R_94_A_HORIZ_INPUT_WINDOW_START, 0x00,
384 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
385
386 /* hsize low (input), 0x02d0 = 720 */
387 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
388 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
389
390 R_98_A_VERT_INPUT_WINDOW_START, 0x03,
391 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
392
393 /* vsize 0x12 = 18 */
394 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x12,
395 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
396
397 /* hsize 0x05a0 = 1440 */
398 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
399 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05, /* hsize hi (output) */
400 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x12, /* vsize low (output), 0x12 = 18 */
401 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00, /* vsize hi (output) */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800402
403 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300404 R_C0_B_TASK_HANDLING_CNTL, 0x00,
405 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
406 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
407 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800408
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300409 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
410 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
411 /* hoffset low (input), 0x0002 is minimum. See comment above. */
412 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x00,
413 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800414
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300415 /* hsize 0x02d0 = 720 */
416 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
417 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
418
419 /* voffset 0x16 = 22 */
420 R_C8_B_VERT_INPUT_WINDOW_START, 0x16,
421 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
422
423 /* vsize 0x0120 = 288 */
424 R_CA_B_VERT_INPUT_WINDOW_LENGTH, 0x20,
425 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, 0x01,
426
427 /* hsize 0x02d0 = 720 */
428 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
429 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
430
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300431 R_F0_LFCO_PER_LINE, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
432 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0, (was 0x05) */
433 R_F5_PULSGEN_LINE_LENGTH, 0xb0,
434 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
435
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800436 0x00, 0x00
437};
438
439/* ============== SAA7715 VIDEO templates (end) ======= */
440
441static const unsigned char saa7115_cfg_vbi_on[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300442 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
443 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
444 R_80_GLOBAL_CNTL_1, 0x30, /* Activate both tasks */
445 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
446 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
447
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800448 0x00, 0x00
449};
450
451static const unsigned char saa7115_cfg_vbi_off[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300452 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
453 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
454 R_80_GLOBAL_CNTL_1, 0x20, /* Activate only task "B" */
455 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
456 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
457
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800458 0x00, 0x00
459};
460
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300461
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800462static const unsigned char saa7115_init_misc[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300463 R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300464 R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 0x01,
465 R_84_I_PORT_SIGNAL_DEF, 0x20,
466 R_85_I_PORT_SIGNAL_POLAR, 0x21,
467 R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT, 0xc5,
468 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800469
470 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300471 R_A0_A_HORIZ_PRESCALING, 0x01,
472 R_A1_A_ACCUMULATION_LENGTH, 0x00,
473 R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800474
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300475 /* Configure controls at nominal value*/
476 R_A4_A_LUMA_BRIGHTNESS_CNTL, 0x80,
477 R_A5_A_LUMA_CONTRAST_CNTL, 0x40,
478 R_A6_A_CHROMA_SATURATION_CNTL, 0x40,
479
480 /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
481 R_A8_A_HORIZ_LUMA_SCALING_INC, 0x00,
482 R_A9_A_HORIZ_LUMA_SCALING_INC_MSB, 0x02,
483
484 R_AA_A_HORIZ_LUMA_PHASE_OFF, 0x00,
485
486 /* must be horiz lum scaling / 2 */
487 R_AC_A_HORIZ_CHROMA_SCALING_INC, 0x00,
488 R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB, 0x01,
489
490 /* must be offset luma / 2 */
491 R_AE_A_HORIZ_CHROMA_PHASE_OFF, 0x00,
492
493 R_B0_A_VERT_LUMA_SCALING_INC, 0x00,
494 R_B1_A_VERT_LUMA_SCALING_INC_MSB, 0x04,
495
496 R_B2_A_VERT_CHROMA_SCALING_INC, 0x00,
497 R_B3_A_VERT_CHROMA_SCALING_INC_MSB, 0x04,
498
499 R_B4_A_VERT_SCALING_MODE_CNTL, 0x01,
500
501 R_B8_A_VERT_CHROMA_PHASE_OFF_00, 0x00,
502 R_B9_A_VERT_CHROMA_PHASE_OFF_01, 0x00,
503 R_BA_A_VERT_CHROMA_PHASE_OFF_10, 0x00,
504 R_BB_A_VERT_CHROMA_PHASE_OFF_11, 0x00,
505
506 R_BC_A_VERT_LUMA_PHASE_OFF_00, 0x00,
507 R_BD_A_VERT_LUMA_PHASE_OFF_01, 0x00,
508 R_BE_A_VERT_LUMA_PHASE_OFF_10, 0x00,
509 R_BF_A_VERT_LUMA_PHASE_OFF_11, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800510
511 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300512 R_D0_B_HORIZ_PRESCALING, 0x01,
513 R_D1_B_ACCUMULATION_LENGTH, 0x00,
514 R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800515
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300516 /* Configure controls at nominal value*/
517 R_D4_B_LUMA_BRIGHTNESS_CNTL, 0x80,
518 R_D5_B_LUMA_CONTRAST_CNTL, 0x40,
519 R_D6_B_CHROMA_SATURATION_CNTL, 0x40,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800520
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300521 /* hor lum scaling 0x0400 = 1 */
522 R_D8_B_HORIZ_LUMA_SCALING_INC, 0x00,
523 R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, 0x04,
524
525 R_DA_B_HORIZ_LUMA_PHASE_OFF, 0x00,
526
527 /* must be hor lum scaling / 2 */
528 R_DC_B_HORIZ_CHROMA_SCALING, 0x00,
529 R_DD_B_HORIZ_CHROMA_SCALING_MSB, 0x02,
530
531 /* must be offset luma / 2 */
532 R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA, 0x00,
533
534 R_E0_B_VERT_LUMA_SCALING_INC, 0x00,
535 R_E1_B_VERT_LUMA_SCALING_INC_MSB, 0x04,
536
537 R_E2_B_VERT_CHROMA_SCALING_INC, 0x00,
538 R_E3_B_VERT_CHROMA_SCALING_INC_MSB, 0x04,
539
540 R_E4_B_VERT_SCALING_MODE_CNTL, 0x01,
541
542 R_E8_B_VERT_CHROMA_PHASE_OFF_00, 0x00,
543 R_E9_B_VERT_CHROMA_PHASE_OFF_01, 0x00,
544 R_EA_B_VERT_CHROMA_PHASE_OFF_10, 0x00,
545 R_EB_B_VERT_CHROMA_PHASE_OFF_11, 0x00,
546
547 R_EC_B_VERT_LUMA_PHASE_OFF_00, 0x00,
548 R_ED_B_VERT_LUMA_PHASE_OFF_01, 0x00,
549 R_EE_B_VERT_LUMA_PHASE_OFF_10, 0x00,
550 R_EF_B_VERT_LUMA_PHASE_OFF_11, 0x00,
551
552 R_F2_NOMINAL_PLL2_DTO, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */
553 R_F3_PLL_INCREMENT, 0x46,
554 R_F4_PLL2_STATUS, 0x00,
555 R_F7_PULSE_A_POS_MSB, 0x4b, /* not the recommended settings! */
556 R_F8_PULSE_B_POS, 0x00,
557 R_F9_PULSE_B_POS_MSB, 0x4b,
558 R_FA_PULSE_C_POS, 0x00,
559 R_FB_PULSE_C_POS_MSB, 0x4b,
560
561 /* PLL2 lock detection settings: 71 lines 50% phase error */
562 R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES, 0x88,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800563
564 /* Turn off VBI */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300565 R_40_SLICER_CNTL_1, 0x20, /* No framing code errors allowed. */
566 R_41_LCR_BASE, 0xff,
567 R_41_LCR_BASE+1, 0xff,
568 R_41_LCR_BASE+2, 0xff,
569 R_41_LCR_BASE+3, 0xff,
570 R_41_LCR_BASE+4, 0xff,
571 R_41_LCR_BASE+5, 0xff,
572 R_41_LCR_BASE+6, 0xff,
573 R_41_LCR_BASE+7, 0xff,
574 R_41_LCR_BASE+8, 0xff,
575 R_41_LCR_BASE+9, 0xff,
576 R_41_LCR_BASE+10, 0xff,
577 R_41_LCR_BASE+11, 0xff,
578 R_41_LCR_BASE+12, 0xff,
579 R_41_LCR_BASE+13, 0xff,
580 R_41_LCR_BASE+14, 0xff,
581 R_41_LCR_BASE+15, 0xff,
582 R_41_LCR_BASE+16, 0xff,
583 R_41_LCR_BASE+17, 0xff,
584 R_41_LCR_BASE+18, 0xff,
585 R_41_LCR_BASE+19, 0xff,
586 R_41_LCR_BASE+20, 0xff,
587 R_41_LCR_BASE+21, 0xff,
588 R_41_LCR_BASE+22, 0xff,
589 R_58_PROGRAM_FRAMING_CODE, 0x40,
590 R_59_H_OFF_FOR_SLICER, 0x47,
591 R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF, 0x83,
592 R_5D_DID, 0xbd,
593 R_5E_SDID, 0x35,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800594
Devin Heitmuellerfea551f2010-02-03 00:33:48 -0300595 R_02_INPUT_CNTL_1, 0xc4, /* input tuner -> input 4, amplifier active */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800596
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300597 R_80_GLOBAL_CNTL_1, 0x20, /* enable task B */
598 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
599 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800600 0x00, 0x00
601};
602
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -0300603static int saa711x_odd_parity(u8 c)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800604{
605 c ^= (c >> 4);
606 c ^= (c >> 2);
607 c ^= (c >> 1);
608
609 return c & 1;
610}
611
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300612static int saa711x_decode_vps(u8 *dst, u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800613{
614 static const u8 biphase_tbl[] = {
615 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
616 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
617 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
618 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
619 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
620 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
621 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
622 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
623 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
624 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
625 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
626 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
627 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
628 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
629 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
630 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
631 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
632 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
633 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
634 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
635 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
636 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
637 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
638 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
639 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
640 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
641 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
642 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
643 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
644 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
645 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
646 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
647 };
648 int i;
649 u8 c, err = 0;
650
651 for (i = 0; i < 2 * 13; i += 2) {
652 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
653 c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
654 dst[i / 2] = c;
655 }
656 return err & 0xf0;
657}
658
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300659static int saa711x_decode_wss(u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800660{
661 static const int wss_bits[8] = {
662 0, 0, 0, 1, 0, 1, 1, 1
663 };
664 unsigned char parity;
665 int wss = 0;
666 int i;
667
668 for (i = 0; i < 16; i++) {
669 int b1 = wss_bits[p[i] & 7];
670 int b2 = wss_bits[(p[i] >> 3) & 7];
671
672 if (b1 == b2)
673 return -1;
674 wss |= b2 << i;
675 }
676 parity = wss & 15;
677 parity ^= parity >> 2;
678 parity ^= parity >> 1;
679
680 if (!(parity & 1))
681 return -1;
682
683 return wss;
684}
685
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300686static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800687{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300688 struct saa711x_state *state = to_state(sd);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200689 u32 acpf;
690 u32 acni;
691 u32 hz;
692 u64 f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300693 u8 acc = 0; /* reg 0x3a, audio clock control */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800694
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300695 /* Checks for chips that don't have audio clock (saa7111, saa7113) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300696 if (!saa711x_has_reg(state->ident, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300697 return 0;
698
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300699 v4l2_dbg(1, debug, sd, "set audio clock freq: %d\n", freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200700
701 /* sanity check */
702 if (freq < 32000 || freq > 48000)
703 return -EINVAL;
704
705 /* hz is the refresh rate times 100 */
706 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
707 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
708 acpf = (25600 * freq) / hz;
709 /* acni = (256 * freq * 2^23) / crystal_frequency =
710 (freq * 2^(8+23)) / crystal_frequency =
Hans Verkuilb7f82922006-04-02 12:50:42 -0300711 (freq << 31) / crystal_frequency */
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200712 f = freq;
713 f = f << 31;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300714 do_div(f, state->crystal_freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200715 acni = f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300716 if (state->ucgc) {
717 acpf = acpf * state->cgcdiv / 16;
718 acni = acni * state->cgcdiv / 16;
719 acc = 0x80;
720 if (state->cgcdiv == 3)
721 acc |= 0x40;
722 }
723 if (state->apll)
724 acc |= 0x08;
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200725
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300726 saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
727 saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10);
728 saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300729
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300730 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
731 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300732 (acpf >> 8) & 0xff);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300733 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300734 (acpf >> 16) & 0x03);
735
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300736 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
737 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
738 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800739 state->audclk_freq = freq;
740 return 0;
741}
742
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300743static int saa711x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800744{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300745 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800746
747 switch (ctrl->id) {
748 case V4L2_CID_BRIGHTNESS:
749 if (ctrl->value < 0 || ctrl->value > 255) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300750 v4l2_err(sd, "invalid brightness setting %d\n", ctrl->value);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800751 return -ERANGE;
752 }
753
754 state->bright = ctrl->value;
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300755 saa711x_write(sd, R_0A_LUMA_BRIGHT_CNTL, state->bright);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800756 break;
757
758 case V4L2_CID_CONTRAST:
759 if (ctrl->value < 0 || ctrl->value > 127) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300760 v4l2_err(sd, "invalid contrast setting %d\n", ctrl->value);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800761 return -ERANGE;
762 }
763
764 state->contrast = ctrl->value;
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300765 saa711x_write(sd, R_0B_LUMA_CONTRAST_CNTL, state->contrast);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800766 break;
767
768 case V4L2_CID_SATURATION:
769 if (ctrl->value < 0 || ctrl->value > 127) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300770 v4l2_err(sd, "invalid saturation setting %d\n", ctrl->value);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800771 return -ERANGE;
772 }
773
774 state->sat = ctrl->value;
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300775 saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, state->sat);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800776 break;
777
778 case V4L2_CID_HUE:
Hans Verkuilde6476f52009-01-29 16:09:13 -0300779 if (ctrl->value < -128 || ctrl->value > 127) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300780 v4l2_err(sd, "invalid hue setting %d\n", ctrl->value);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800781 return -ERANGE;
782 }
783
784 state->hue = ctrl->value;
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300785 saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, state->hue);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800786 break;
Hans Verkuil3faeeae2006-01-09 15:25:44 -0200787
788 default:
789 return -EINVAL;
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800790 }
791
792 return 0;
793}
794
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300795static int saa711x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800796{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300797 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800798
799 switch (ctrl->id) {
800 case V4L2_CID_BRIGHTNESS:
801 ctrl->value = state->bright;
802 break;
803 case V4L2_CID_CONTRAST:
804 ctrl->value = state->contrast;
805 break;
806 case V4L2_CID_SATURATION:
807 ctrl->value = state->sat;
808 break;
809 case V4L2_CID_HUE:
810 ctrl->value = state->hue;
811 break;
812 default:
813 return -EINVAL;
814 }
815
816 return 0;
817}
818
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300819static int saa711x_set_size(struct v4l2_subdev *sd, int width, int height)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300820{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300821 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300822 int HPSC, HFSC;
823 int VSCY;
824 int res;
825 int is_50hz = state->std & V4L2_STD_625_50;
826 int Vsrc = is_50hz ? 576 : 480;
827
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300828 v4l2_dbg(1, debug, sd, "decoder set size to %ix%i\n", width, height);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300829
830 /* FIXME need better bounds checking here */
831 if ((width < 1) || (width > 1440))
832 return -EINVAL;
833 if ((height < 1) || (height > Vsrc))
834 return -EINVAL;
835
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300836 if (!saa711x_has_reg(state->ident, R_D0_B_HORIZ_PRESCALING)) {
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300837 /* Decoder only supports 720 columns and 480 or 576 lines */
838 if (width != 720)
839 return -EINVAL;
840 if (height != Vsrc)
841 return -EINVAL;
842 }
843
844 state->width = width;
845 state->height = height;
846
847 if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
848 return 0;
849
850 /* probably have a valid size, let's set it */
851 /* Set output width/height */
852 /* width */
853
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300854 saa711x_write(sd, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300855 (u8) (width & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300856 saa711x_write(sd, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300857 (u8) ((width >> 8) & 0xff));
858
859 /* Vertical Scaling uses height/2 */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300860 res = height / 2;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300861
862 /* On 60Hz, it is using a higher Vertical Output Size */
863 if (!is_50hz)
Hans Verkuild0d30c02006-11-25 09:45:50 -0300864 res += (VRES_60HZ - 480) >> 1;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300865
866 /* height */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300867 saa711x_write(sd, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300868 (u8) (res & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300869 saa711x_write(sd, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300870 (u8) ((res >> 8) & 0xff));
871
872 /* Scaling settings */
873 /* Hprescaler is floor(inres/outres) */
874 HPSC = (int)(720 / width);
875 /* 0 is not allowed (div. by zero) */
876 HPSC = HPSC ? HPSC : 1;
877 HFSC = (int)((1024 * 720) / (HPSC * width));
878 /* FIXME hardcodes to "Task B"
879 * write H prescaler integer */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300880 saa711x_write(sd, R_D0_B_HORIZ_PRESCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300881 (u8) (HPSC & 0x3f));
882
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300883 v4l2_dbg(1, debug, sd, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300884 /* write H fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300885 saa711x_write(sd, R_D8_B_HORIZ_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300886 (u8) (HFSC & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300887 saa711x_write(sd, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300888 (u8) ((HFSC >> 8) & 0xff));
889 /* write H fine-scaling (chrominance)
890 * must be lum/2, so i'll just bitshift :) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300891 saa711x_write(sd, R_DC_B_HORIZ_CHROMA_SCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300892 (u8) ((HFSC >> 1) & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300893 saa711x_write(sd, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300894 (u8) ((HFSC >> 9) & 0xff));
895
896 VSCY = (int)((1024 * Vsrc) / height);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300897 v4l2_dbg(1, debug, sd, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300898
899 /* Correct Contrast and Luminance */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300900 saa711x_write(sd, R_D5_B_LUMA_CONTRAST_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300901 (u8) (64 * 1024 / VSCY));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300902 saa711x_write(sd, R_D6_B_CHROMA_SATURATION_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300903 (u8) (64 * 1024 / VSCY));
904
905 /* write V fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300906 saa711x_write(sd, R_E0_B_VERT_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300907 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300908 saa711x_write(sd, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300909 (u8) ((VSCY >> 8) & 0xff));
910 /* write V fine-scaling (chrominance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300911 saa711x_write(sd, R_E2_B_VERT_CHROMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300912 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300913 saa711x_write(sd, R_E3_B_VERT_CHROMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300914 (u8) ((VSCY >> 8) & 0xff));
915
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300916 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300917
918 /* Activates task "B" */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300919 saa711x_write(sd, R_80_GLOBAL_CNTL_1,
920 saa711x_read(sd, R_80_GLOBAL_CNTL_1) | 0x20);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300921
922 return 0;
923}
924
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300925static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800926{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300927 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800928
Hans Verkuil30b54d52006-01-09 15:25:43 -0200929 /* Prevent unnecessary standard changes. During a standard
930 change the I-Port is temporarily disabled. Any devices
931 reading from that port can get confused.
Hans Verkuilbccfa442009-03-30 06:55:27 -0300932 Note that s_std is also used to switch from
933 radio to TV mode, so if a s_std is broadcast to
Hans Verkuil30b54d52006-01-09 15:25:43 -0200934 all I2C devices then you do not want to have an unwanted
935 side-effect here. */
936 if (std == state->std)
937 return;
938
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300939 state->std = std;
940
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800941 // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
942 if (std & V4L2_STD_525_60) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300943 v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n");
944 saa711x_writeregs(sd, saa7115_cfg_60hz_video);
945 saa711x_set_size(sd, 720, 480);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800946 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300947 v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n");
948 saa711x_writeregs(sd, saa7115_cfg_50hz_video);
949 saa711x_set_size(sd, 720, 576);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800950 }
951
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300952 /* Register 0E - Bits D6-D4 on NO-AUTO mode
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300953 (SAA7111 and SAA7113 doesn't have auto mode)
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300954 50 Hz / 625 lines 60 Hz / 525 lines
955 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz)
956 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz)
957 010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz)
958 011 NTSC N (3.58MHz) PAL M (3.58MHz)
959 100 reserved NTSC-Japan (3.58MHz)
960 */
Hans Verkuil340dde82010-02-20 08:07:51 -0300961 if (state->ident <= V4L2_IDENT_SAA7113) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300962 u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300963
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300964 if (std == V4L2_STD_PAL_M) {
Hans Verkuil01342352006-03-25 08:19:47 -0300965 reg |= 0x30;
Hans Verkuile0028022008-04-22 14:45:51 -0300966 } else if (std == V4L2_STD_PAL_Nc) {
Hans Verkuil01342352006-03-25 08:19:47 -0300967 reg |= 0x20;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300968 } else if (std == V4L2_STD_PAL_60) {
Hans Verkuil01342352006-03-25 08:19:47 -0300969 reg |= 0x10;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300970 } else if (std == V4L2_STD_NTSC_M_JP) {
Hans Verkuil01342352006-03-25 08:19:47 -0300971 reg |= 0x40;
Mauro Carvalho Chehaba9aaec42007-03-13 13:41:49 -0300972 } else if (std & V4L2_STD_SECAM) {
Pádraig Bradyfc2fa312006-10-09 08:02:17 -0300973 reg |= 0x50;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300974 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300975 saa711x_write(sd, R_0E_CHROMA_CNTL_1, reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300976 } else {
977 /* restart task B if needed */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300978 int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300979
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300980 if (taskb && state->ident == V4L2_IDENT_SAA7114) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300981 saa711x_writeregs(sd, saa7115_cfg_vbi_on);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300982 }
983
984 /* switch audio mode too! */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300985 saa711x_s_clock_freq(sd, state->audclk_freq);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300986 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800987}
988
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800989/* setup the sliced VBI lcr registers according to the sliced VBI format */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300990static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800991{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300992 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800993 int is_50hz = (state->std & V4L2_STD_625_50);
994 u8 lcr[24];
995 int i, x;
996
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300997#if 1
998 /* saa7113/7114/7118 VBI support are experimental */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300999 if (!saa711x_has_reg(state->ident, R_41_LCR_BASE))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001000 return;
1001
1002#else
1003 /* SAA7113 and SAA7118 also should support VBI - Need testing */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001004 if (state->ident != V4L2_IDENT_SAA7115)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001005 return;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001006#endif
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001007
1008 for (i = 0; i <= 23; i++)
1009 lcr[i] = 0xff;
1010
Hans Verkuila8b86432008-10-04 08:05:30 -03001011 if (fmt == NULL) {
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001012 /* raw VBI */
1013 if (is_50hz)
1014 for (i = 6; i <= 23; i++)
1015 lcr[i] = 0xdd;
1016 else
1017 for (i = 10; i <= 21; i++)
1018 lcr[i] = 0xdd;
1019 } else {
1020 /* sliced VBI */
1021 /* first clear lines that cannot be captured */
1022 if (is_50hz) {
1023 for (i = 0; i <= 5; i++)
1024 fmt->service_lines[0][i] =
1025 fmt->service_lines[1][i] = 0;
1026 }
1027 else {
1028 for (i = 0; i <= 9; i++)
1029 fmt->service_lines[0][i] =
1030 fmt->service_lines[1][i] = 0;
1031 for (i = 22; i <= 23; i++)
1032 fmt->service_lines[0][i] =
1033 fmt->service_lines[1][i] = 0;
1034 }
1035
1036 /* Now set the lcr values according to the specified service */
1037 for (i = 6; i <= 23; i++) {
1038 lcr[i] = 0;
1039 for (x = 0; x <= 1; x++) {
1040 switch (fmt->service_lines[1-x][i]) {
1041 case 0:
1042 lcr[i] |= 0xf << (4 * x);
1043 break;
Hans Verkuil9bc74002006-03-29 18:02:51 -03001044 case V4L2_SLICED_TELETEXT_B:
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001045 lcr[i] |= 1 << (4 * x);
1046 break;
1047 case V4L2_SLICED_CAPTION_525:
1048 lcr[i] |= 4 << (4 * x);
1049 break;
1050 case V4L2_SLICED_WSS_625:
1051 lcr[i] |= 5 << (4 * x);
1052 break;
1053 case V4L2_SLICED_VPS:
1054 lcr[i] |= 7 << (4 * x);
1055 break;
1056 }
1057 }
1058 }
1059 }
1060
1061 /* write the lcr registers */
1062 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001063 saa711x_write(sd, i - 2 + R_41_LCR_BASE, lcr[i]);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001064 }
1065
1066 /* enable/disable raw VBI capturing */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001067 saa711x_writeregs(sd, fmt == NULL ?
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001068 saa7115_cfg_vbi_on :
1069 saa7115_cfg_vbi_off);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001070}
1071
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001072static int saa711x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001073{
1074 static u16 lcr2vbi[] = {
Hans Verkuil9bc74002006-03-29 18:02:51 -03001075 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001076 0, V4L2_SLICED_CAPTION_525, /* 4 */
1077 V4L2_SLICED_WSS_625, 0, /* 5 */
1078 V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
1079 0, 0, 0, 0
1080 };
1081 struct v4l2_sliced_vbi_format *sliced = &fmt->fmt.sliced;
1082 int i;
1083
1084 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
1085 return -EINVAL;
1086 memset(sliced, 0, sizeof(*sliced));
1087 /* done if using raw VBI */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001088 if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001089 return 0;
1090 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001091 u8 v = saa711x_read(sd, i - 2 + R_41_LCR_BASE);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001092
1093 sliced->service_lines[0][i] = lcr2vbi[v >> 4];
1094 sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
1095 sliced->service_set |=
1096 sliced->service_lines[0][i] | sliced->service_lines[1][i];
1097 }
1098 return 0;
1099}
1100
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001101static int saa711x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
Mauro Carvalho Chehab59ba9152006-08-30 05:34:36 -03001102{
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001103 if (fmt->type == V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001104 saa711x_set_lcr(sd, &fmt->fmt.sliced);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001105 return 0;
1106 }
Hans Verkuila8b86432008-10-04 08:05:30 -03001107 if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001108 saa711x_set_lcr(sd, NULL);
Hans Verkuila8b86432008-10-04 08:05:30 -03001109 return 0;
1110 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001111 if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
1112 return -EINVAL;
1113
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001114 return saa711x_set_size(sd, fmt->fmt.pix.width, fmt->fmt.pix.height);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001115}
1116
1117/* Decode the sliced VBI data stream as created by the saa7115.
1118 The format is described in the saa7115 datasheet in Tables 25 and 26
1119 and in Figure 33.
1120 The current implementation uses SAV/EAV codes and not the ancillary data
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001121 headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001122 code. */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001123static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001124{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001125 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001126 static const char vbi_no_data_pattern[] = {
1127 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
1128 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001129 u8 *p = vbi->p;
1130 u32 wss;
1131 int id1, id2; /* the ID1 and ID2 bytes from the internal header */
1132
1133 vbi->type = 0; /* mark result as a failure */
1134 id1 = p[2];
1135 id2 = p[3];
1136 /* Note: the field bit is inverted for 60 Hz video */
1137 if (state->std & V4L2_STD_525_60)
1138 id1 ^= 0x40;
1139
1140 /* Skip internal header, p now points to the start of the payload */
1141 p += 4;
1142 vbi->p = p;
1143
1144 /* calculate field and line number of the VBI packet (1-23) */
1145 vbi->is_second_field = ((id1 & 0x40) != 0);
1146 vbi->line = (id1 & 0x3f) << 3;
1147 vbi->line |= (id2 & 0x70) >> 4;
1148
1149 /* Obtain data type */
1150 id2 &= 0xf;
1151
1152 /* If the VBI slicer does not detect any signal it will fill up
1153 the payload buffer with 0xa0 bytes. */
1154 if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001155 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001156
1157 /* decode payloads */
1158 switch (id2) {
1159 case 1:
Hans Verkuil9bc74002006-03-29 18:02:51 -03001160 vbi->type = V4L2_SLICED_TELETEXT_B;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001161 break;
1162 case 4:
Mauro Carvalho Chehab59ba9152006-08-30 05:34:36 -03001163 if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001164 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001165 vbi->type = V4L2_SLICED_CAPTION_525;
1166 break;
1167 case 5:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001168 wss = saa711x_decode_wss(p);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001169 if (wss == -1)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001170 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001171 p[0] = wss & 0xff;
1172 p[1] = wss >> 8;
1173 vbi->type = V4L2_SLICED_WSS_625;
1174 break;
1175 case 7:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001176 if (saa711x_decode_vps(p, p) != 0)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001177 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001178 vbi->type = V4L2_SLICED_VPS;
1179 break;
1180 default:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001181 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001182 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001183 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001184}
1185
1186/* ============ SAA7115 AUDIO settings (end) ============= */
1187
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001188static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001189{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001190 struct saa711x_state *state = to_state(sd);
1191 int status;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001192
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001193 if (state->radio)
1194 return 0;
1195 status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001196
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001197 v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status);
1198 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1199 return 0;
1200}
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001201
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001202static int saa711x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
1203{
1204 switch (qc->id) {
1205 case V4L2_CID_BRIGHTNESS:
Hans Verkuil10afbef2009-02-21 18:47:24 -03001206 return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001207 case V4L2_CID_CONTRAST:
1208 case V4L2_CID_SATURATION:
Hans Verkuil10afbef2009-02-21 18:47:24 -03001209 return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001210 case V4L2_CID_HUE:
Hans Verkuil10afbef2009-02-21 18:47:24 -03001211 return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001212 default:
1213 return -EINVAL;
1214 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001215}
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001216
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001217static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1218{
1219 struct saa711x_state *state = to_state(sd);
1220
1221 state->radio = 0;
1222 saa711x_set_v4lstd(sd, std);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001223 return 0;
1224}
1225
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001226static int saa711x_s_radio(struct v4l2_subdev *sd)
1227{
1228 struct saa711x_state *state = to_state(sd);
1229
1230 state->radio = 1;
1231 return 0;
1232}
1233
Hans Verkuil5325b422009-04-02 11:26:22 -03001234static int saa711x_s_routing(struct v4l2_subdev *sd,
1235 u32 input, u32 output, u32 config)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001236{
1237 struct saa711x_state *state = to_state(sd);
Hans Verkuil340dde82010-02-20 08:07:51 -03001238 u8 mask = (state->ident <= V4L2_IDENT_SAA7111A) ? 0xf8 : 0xf0;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001239
Hans Verkuil5325b422009-04-02 11:26:22 -03001240 v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n",
1241 input, output);
1242
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001243 /* saa7111/3 does not have these inputs */
Hans Verkuil340dde82010-02-20 08:07:51 -03001244 if (state->ident <= V4L2_IDENT_SAA7113 &&
Hans Verkuil5325b422009-04-02 11:26:22 -03001245 (input == SAA7115_COMPOSITE4 ||
1246 input == SAA7115_COMPOSITE5)) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001247 return -EINVAL;
1248 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001249 if (input > SAA7115_SVIDEO3)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001250 return -EINVAL;
Hans Verkuil5325b422009-04-02 11:26:22 -03001251 if (state->input == input && state->output == output)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001252 return 0;
1253 v4l2_dbg(1, debug, sd, "now setting %s input %s output\n",
Hans Verkuil5325b422009-04-02 11:26:22 -03001254 (input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite",
1255 (output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
1256 state->input = input;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001257
1258 /* saa7111 has slightly different input numbering */
Hans Verkuil340dde82010-02-20 08:07:51 -03001259 if (state->ident <= V4L2_IDENT_SAA7111A) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001260 if (input >= SAA7115_COMPOSITE4)
1261 input -= 2;
1262 /* saa7111 specific */
1263 saa711x_write(sd, R_10_CHROMA_CNTL_2,
1264 (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001265 ((output & 0xc0) ^ 0x40));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001266 saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL,
1267 (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001268 ((output & 2) ? 0x0a : 0));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001269 }
1270
1271 /* select mode */
1272 saa711x_write(sd, R_02_INPUT_CNTL_1,
1273 (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) |
1274 input);
1275
1276 /* bypass chrominance trap for S-Video modes */
1277 saa711x_write(sd, R_09_LUMA_CNTL,
1278 (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) |
1279 (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
1280
Hans Verkuil5325b422009-04-02 11:26:22 -03001281 state->output = output;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001282 if (state->ident == V4L2_IDENT_SAA7114 ||
1283 state->ident == V4L2_IDENT_SAA7115) {
1284 saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
1285 (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
1286 (state->output & 0x01));
1287 }
1288 return 0;
1289}
1290
1291static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val)
1292{
1293 struct saa711x_state *state = to_state(sd);
1294
Hans Verkuil340dde82010-02-20 08:07:51 -03001295 if (state->ident > V4L2_IDENT_SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001296 return -EINVAL;
1297 saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) |
1298 (val ? 0x80 : 0));
1299 return 0;
1300}
1301
1302static int saa711x_s_stream(struct v4l2_subdev *sd, int enable)
1303{
1304 struct saa711x_state *state = to_state(sd);
1305
1306 v4l2_dbg(1, debug, sd, "%s output\n",
1307 enable ? "enable" : "disable");
1308
Hans Verkuil674a3232009-02-18 12:22:16 -03001309 if (state->enable == enable)
1310 return 0;
1311 state->enable = enable;
1312 if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED))
1313 return 0;
1314 saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001315 return 0;
1316}
1317
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001318static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001319{
1320 struct saa711x_state *state = to_state(sd);
1321
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001322 if (freq != SAA7115_FREQ_32_11_MHZ && freq != SAA7115_FREQ_24_576_MHZ)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001323 return -EINVAL;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001324 state->crystal_freq = freq;
1325 state->cgcdiv = (flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
1326 state->ucgc = (flags & SAA7115_FREQ_FL_UCGC) ? 1 : 0;
1327 state->apll = (flags & SAA7115_FREQ_FL_APLL) ? 1 : 0;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001328 saa711x_s_clock_freq(sd, state->audclk_freq);
1329 return 0;
1330}
1331
1332static int saa711x_reset(struct v4l2_subdev *sd, u32 val)
1333{
1334 v4l2_dbg(1, debug, sd, "decoder RESET\n");
1335 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
1336 return 0;
1337}
1338
1339static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data)
1340{
1341 /* Note: the internal field ID is inverted for NTSC,
1342 so data->field 0 maps to the saa7115 even field,
1343 whereas for PAL it maps to the saa7115 odd field. */
1344 switch (data->id) {
1345 case V4L2_SLICED_WSS_625:
1346 if (saa711x_read(sd, 0x6b) & 0xc0)
1347 return -EIO;
1348 data->data[0] = saa711x_read(sd, 0x6c);
1349 data->data[1] = saa711x_read(sd, 0x6d);
1350 return 0;
1351 case V4L2_SLICED_CAPTION_525:
1352 if (data->field == 0) {
1353 /* CC */
1354 if (saa711x_read(sd, 0x66) & 0x30)
1355 return -EIO;
1356 data->data[0] = saa711x_read(sd, 0x69);
1357 data->data[1] = saa711x_read(sd, 0x6a);
1358 return 0;
1359 }
1360 /* XDS */
1361 if (saa711x_read(sd, 0x66) & 0xc0)
1362 return -EIO;
1363 data->data[0] = saa711x_read(sd, 0x67);
1364 data->data[1] = saa711x_read(sd, 0x68);
1365 return 0;
1366 default:
1367 return -EINVAL;
1368 }
1369}
1370
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001371static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
1372{
1373 struct saa711x_state *state = to_state(sd);
1374 int reg1e;
1375
1376 *std = V4L2_STD_ALL;
1377 if (state->ident != V4L2_IDENT_SAA7115)
1378 return 0;
1379 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1380
1381 switch (reg1e & 0x03) {
1382 case 1:
1383 *std = V4L2_STD_NTSC;
1384 break;
1385 case 2:
1386 *std = V4L2_STD_PAL;
1387 break;
1388 case 3:
1389 *std = V4L2_STD_SECAM;
1390 break;
1391 default:
1392 break;
1393 }
1394 return 0;
1395}
1396
1397static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status)
1398{
1399 struct saa711x_state *state = to_state(sd);
1400 int reg1e = 0x80;
1401 int reg1f;
1402
1403 *status = V4L2_IN_ST_NO_SIGNAL;
1404 if (state->ident == V4L2_IDENT_SAA7115)
1405 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1406 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1407 if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80)
1408 *status = 0;
1409 return 0;
1410}
1411
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001412#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001413static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001414{
1415 struct i2c_client *client = v4l2_get_subdevdata(sd);
1416
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001417 if (!v4l2_chip_match_i2c_client(client, &reg->match))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001418 return -EINVAL;
1419 if (!capable(CAP_SYS_ADMIN))
1420 return -EPERM;
1421 reg->val = saa711x_read(sd, reg->reg & 0xff);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001422 reg->size = 1;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001423 return 0;
1424}
1425
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001426static int saa711x_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001427{
1428 struct i2c_client *client = v4l2_get_subdevdata(sd);
1429
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001430 if (!v4l2_chip_match_i2c_client(client, &reg->match))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001431 return -EINVAL;
1432 if (!capable(CAP_SYS_ADMIN))
1433 return -EPERM;
1434 saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff);
1435 return 0;
1436}
1437#endif
1438
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001439static int saa711x_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001440{
1441 struct saa711x_state *state = to_state(sd);
1442 struct i2c_client *client = v4l2_get_subdevdata(sd);
1443
1444 return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0);
1445}
1446
1447static int saa711x_log_status(struct v4l2_subdev *sd)
1448{
1449 struct saa711x_state *state = to_state(sd);
1450 int reg1e, reg1f;
1451 int signalOk;
1452 int vcr;
1453
1454 v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq);
1455 if (state->ident != V4L2_IDENT_SAA7115) {
1456 /* status for the saa7114 */
1457 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1458 signalOk = (reg1f & 0xc1) == 0x81;
1459 v4l2_info(sd, "Video signal: %s\n", signalOk ? "ok" : "bad");
1460 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1461 return 0;
1462 }
1463
1464 /* status for the saa7115 */
1465 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1466 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1467
1468 signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
1469 vcr = !(reg1f & 0x10);
1470
1471 if (state->input >= 6)
1472 v4l2_info(sd, "Input: S-Video %d\n", state->input - 6);
1473 else
1474 v4l2_info(sd, "Input: Composite %d\n", state->input);
1475 v4l2_info(sd, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
1476 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1477
1478 switch (reg1e & 0x03) {
1479 case 1:
1480 v4l2_info(sd, "Detected format: NTSC\n");
1481 break;
1482 case 2:
1483 v4l2_info(sd, "Detected format: PAL\n");
1484 break;
1485 case 3:
1486 v4l2_info(sd, "Detected format: SECAM\n");
1487 break;
1488 default:
1489 v4l2_info(sd, "Detected format: BW/No color\n");
1490 break;
1491 }
1492 v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height);
1493 return 0;
1494}
1495
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001496/* ----------------------------------------------------------------------- */
1497
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001498static const struct v4l2_subdev_core_ops saa711x_core_ops = {
1499 .log_status = saa711x_log_status,
1500 .g_chip_ident = saa711x_g_chip_ident,
1501 .g_ctrl = saa711x_g_ctrl,
1502 .s_ctrl = saa711x_s_ctrl,
1503 .queryctrl = saa711x_queryctrl,
Hans Verkuilf41737e2009-04-01 03:52:39 -03001504 .s_std = saa711x_s_std,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001505 .reset = saa711x_reset,
1506 .s_gpio = saa711x_s_gpio,
1507#ifdef CONFIG_VIDEO_ADV_DEBUG
1508 .g_register = saa711x_g_register,
1509 .s_register = saa711x_s_register,
1510#endif
1511};
1512
1513static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001514 .s_radio = saa711x_s_radio,
1515 .g_tuner = saa711x_g_tuner,
1516};
1517
1518static const struct v4l2_subdev_audio_ops saa711x_audio_ops = {
1519 .s_clock_freq = saa711x_s_clock_freq,
1520};
1521
1522static const struct v4l2_subdev_video_ops saa711x_video_ops = {
1523 .s_routing = saa711x_s_routing,
1524 .s_crystal_freq = saa711x_s_crystal_freq,
1525 .g_fmt = saa711x_g_fmt,
1526 .s_fmt = saa711x_s_fmt,
1527 .g_vbi_data = saa711x_g_vbi_data,
1528 .decode_vbi_line = saa711x_decode_vbi_line,
1529 .s_stream = saa711x_s_stream,
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001530 .querystd = saa711x_querystd,
1531 .g_input_status = saa711x_g_input_status,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001532};
1533
1534static const struct v4l2_subdev_ops saa711x_ops = {
1535 .core = &saa711x_core_ops,
1536 .tuner = &saa711x_tuner_ops,
1537 .audio = &saa711x_audio_ops,
1538 .video = &saa711x_video_ops,
1539};
1540
1541/* ----------------------------------------------------------------------- */
1542
1543static int saa711x_probe(struct i2c_client *client,
Jean Delvared2653e92008-04-29 23:11:39 +02001544 const struct i2c_device_id *id)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001545{
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001546 struct saa711x_state *state;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001547 struct v4l2_subdev *sd;
Mauro Carvalho Chehab236f16d2006-08-28 08:25:29 -03001548 int i;
1549 char name[17];
Jean Delvareaf294862008-05-18 20:49:40 +02001550 char chip_id;
1551 int autodetect = !id || id->driver_data == 1;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001552
1553 /* Check if the adapter supports the needed features */
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001554 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
Hans Verkuil188f3452007-09-16 10:47:15 -03001555 return -EIO;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001556
Hans Verkuild0d30c02006-11-25 09:45:50 -03001557 for (i = 0; i < 0x0f; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001558 i2c_smbus_write_byte_data(client, 0, i);
1559 name[i] = (i2c_smbus_read_byte_data(client, 0) & 0x0f) + '0';
Hans Verkuild0d30c02006-11-25 09:45:50 -03001560 if (name[i] > '9')
1561 name[i] += 'a' - '9' - 1;
Mauro Carvalho Chehab236f16d2006-08-28 08:25:29 -03001562 }
Hans Verkuild0d30c02006-11-25 09:45:50 -03001563 name[i] = '\0';
Mauro Carvalho Chehab236f16d2006-08-28 08:25:29 -03001564
Jean Delvareaf294862008-05-18 20:49:40 +02001565 chip_id = name[5];
Mauro Carvalho Chehab3e7d3e52006-09-01 18:39:05 -03001566
Hans Verkuilf7668162006-11-25 09:40:28 -03001567 /* Check whether this chip is part of the saa711x series */
1568 if (memcmp(name, "1f711", 5)) {
1569 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 -03001570 client->addr << 1, name);
Hans Verkuil188f3452007-09-16 10:47:15 -03001571 return -ENODEV;
Hans Verkuilf7668162006-11-25 09:40:28 -03001572 }
1573
Jean Delvareaf294862008-05-18 20:49:40 +02001574 /* Safety check */
1575 if (!autodetect && id->name[6] != chip_id) {
1576 v4l_warn(client, "found saa711%c while %s was expected\n",
1577 chip_id, id->name);
1578 }
1579 snprintf(client->name, sizeof(client->name), "saa711%c", chip_id);
1580 v4l_info(client, "saa711%c found (%s) @ 0x%x (%s)\n", chip_id, name,
1581 client->addr << 1, client->adapter->name);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001582
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001583 state = kzalloc(sizeof(struct saa711x_state), GFP_KERNEL);
Hans Verkuilc5bf2042008-09-03 17:12:09 -03001584 if (state == NULL)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001585 return -ENOMEM;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001586 sd = &state->sd;
1587 v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001588 state->input = -1;
Marco Schluessler4cbca182007-01-21 19:43:38 -03001589 state->output = SAA7115_IPORT_ON;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001590 state->enable = 1;
Hans Verkuil3faeeae2006-01-09 15:25:44 -02001591 state->radio = 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001592 state->bright = 128;
1593 state->contrast = 64;
1594 state->hue = 0;
1595 state->sat = 64;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001596 switch (chip_id) {
Jean Delvareaf294862008-05-18 20:49:40 +02001597 case '1':
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001598 state->ident = V4L2_IDENT_SAA7111;
Hans Verkuil340dde82010-02-20 08:07:51 -03001599 if (saa711x_read(sd, R_00_CHIP_VERSION) & 0xf0) {
1600 v4l_info(client, "saa7111a variant found\n");
1601 state->ident = V4L2_IDENT_SAA7111A;
1602 }
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001603 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001604 case '3':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001605 state->ident = V4L2_IDENT_SAA7113;
1606 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001607 case '4':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001608 state->ident = V4L2_IDENT_SAA7114;
1609 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001610 case '5':
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001611 state->ident = V4L2_IDENT_SAA7115;
1612 break;
Jean Delvareaf294862008-05-18 20:49:40 +02001613 case '8':
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001614 state->ident = V4L2_IDENT_SAA7118;
1615 break;
1616 default:
1617 state->ident = V4L2_IDENT_SAA7111;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001618 v4l2_info(sd, "WARNING: Chip is not known - Falling back to saa7111\n");
Hans Verkuil340dde82010-02-20 08:07:51 -03001619 break;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001620 }
1621
Hans Verkuil3578d3d2006-01-09 15:25:41 -02001622 state->audclk_freq = 48000;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001623
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001624 v4l2_dbg(1, debug, sd, "writing init values\n");
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001625
1626 /* init to 60hz/48khz */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001627 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
1628 switch (state->ident) {
1629 case V4L2_IDENT_SAA7111:
Hans Verkuil340dde82010-02-20 08:07:51 -03001630 case V4L2_IDENT_SAA7111A:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001631 saa711x_writeregs(sd, saa7111_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001632 break;
1633 case V4L2_IDENT_SAA7113:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001634 saa711x_writeregs(sd, saa7113_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001635 break;
1636 default:
Hans Verkuilb7f82922006-04-02 12:50:42 -03001637 state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001638 saa711x_writeregs(sd, saa7115_init_auto_input);
Hans Verkuilb7f82922006-04-02 12:50:42 -03001639 }
Hans Verkuil340dde82010-02-20 08:07:51 -03001640 if (state->ident > V4L2_IDENT_SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001641 saa711x_writeregs(sd, saa7115_init_misc);
1642 saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001643
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001644 v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n",
1645 saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC),
1646 saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001647 return 0;
1648}
1649
1650/* ----------------------------------------------------------------------- */
1651
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001652static int saa711x_remove(struct i2c_client *client)
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001653{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001654 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1655
1656 v4l2_device_unregister_subdev(sd);
1657 kfree(to_state(sd));
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001658 return 0;
1659}
1660
Jean Delvareaf294862008-05-18 20:49:40 +02001661static const struct i2c_device_id saa7115_id[] = {
Hans Verkuil9edd350f2008-07-17 13:22:51 -03001662 { "saa7115_auto", 1 }, /* autodetect */
Jean Delvareaf294862008-05-18 20:49:40 +02001663 { "saa7111", 0 },
1664 { "saa7113", 0 },
1665 { "saa7114", 0 },
1666 { "saa7115", 0 },
1667 { "saa7118", 0 },
1668 { }
1669};
1670MODULE_DEVICE_TABLE(i2c, saa7115_id);
1671
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001672static struct v4l2_i2c_driver_data v4l2_i2c_data = {
1673 .name = "saa7115",
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001674 .probe = saa711x_probe,
1675 .remove = saa711x_remove,
Jean Delvareaf294862008-05-18 20:49:40 +02001676 .id_table = saa7115_id,
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001677};