blob: 90c43f3fb0f1a9d6bffaa4d288c90617cb4a7b38 [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 Verkuil1f8f5fa2006-03-25 09:20:28 -030049#include <media/saa7115.h>
Hans Verkuil3578d3d2006-01-09 15:25:41 -020050#include <asm/div64.h>
Hans Verkuile19b2fc2005-11-13 16:08:04 -080051
Mauro Carvalho Chehab97d9e802006-09-03 09:38:11 -030052#define VRES_60HZ (480+16)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -030053
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -030054MODULE_DESCRIPTION("Philips SAA7111/SAA7113/SAA7114/SAA7115/SAA7118 video decoder driver");
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -030055MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
56 "Hans Verkuil, Mauro Carvalho Chehab");
Hans Verkuile19b2fc2005-11-13 16:08:04 -080057MODULE_LICENSE("GPL");
58
Rusty Russell90ab5ee2012-01-13 09:32:20 +103059static bool debug;
Hans Verkuilfac9e892006-01-09 15:32:40 -020060module_param(debug, bool, 0644);
Hans Verkuile19b2fc2005-11-13 16:08:04 -080061
62MODULE_PARM_DESC(debug, "Debug level (0-1)");
63
Hans Verkuile19b2fc2005-11-13 16:08:04 -080064
Hans Verkuile1277112013-05-29 06:59:51 -030065enum saa711x_model {
66 SAA7111A,
67 SAA7111,
68 SAA7113,
69 GM7113C,
70 SAA7114,
71 SAA7115,
72 SAA7118,
73};
74
Mauro Carvalho Chehab66ec1192006-08-29 22:52:32 -030075struct saa711x_state {
Hans Verkuil9415f4b2008-11-29 12:55:19 -030076 struct v4l2_subdev sd;
Hans Verkuile3560542010-05-24 10:00:52 -030077 struct v4l2_ctrl_handler hdl;
78
79 struct {
80 /* chroma gain control cluster */
81 struct v4l2_ctrl *agc;
82 struct v4l2_ctrl *gain;
83 };
84
Hans Verkuile19b2fc2005-11-13 16:08:04 -080085 v4l2_std_id std;
86 int input;
Marco Schluessler4cbca182007-01-21 19:43:38 -030087 int output;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080088 int enable;
Hans Verkuil3faeeae2006-01-09 15:25:44 -020089 int radio;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -030090 int width;
91 int height;
Hans Verkuile1277112013-05-29 06:59:51 -030092 enum saa711x_model ident;
Hans Verkuil3578d3d2006-01-09 15:25:41 -020093 u32 audclk_freq;
Hans Verkuilb7f82922006-04-02 12:50:42 -030094 u32 crystal_freq;
Hans Verkuil15890372013-03-11 03:47:25 -030095 bool ucgc;
Hans Verkuilb7f82922006-04-02 12:50:42 -030096 u8 cgcdiv;
Hans Verkuil15890372013-03-11 03:47:25 -030097 bool apll;
98 bool double_asclk;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080099};
100
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300101static inline struct saa711x_state *to_state(struct v4l2_subdev *sd)
102{
103 return container_of(sd, struct saa711x_state, sd);
104}
105
Hans Verkuile3560542010-05-24 10:00:52 -0300106static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
107{
108 return &container_of(ctrl->handler, struct saa711x_state, hdl)->sd;
109}
110
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800111/* ----------------------------------------------------------------------- */
112
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300113static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800114{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300115 struct i2c_client *client = v4l2_get_subdevdata(sd);
116
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800117 return i2c_smbus_write_byte_data(client, reg, value);
118}
119
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300120/* Sanity routine to check if a register is present */
121static int saa711x_has_reg(const int id, const u8 reg)
122{
Hans Verkuile1277112013-05-29 06:59:51 -0300123 if (id == SAA7111)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300124 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
125 (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e;
Hans Verkuile1277112013-05-29 06:59:51 -0300126 if (id == SAA7111A)
Hans Verkuil340dde82010-02-20 08:07:51 -0300127 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
128 reg != 0x14 && reg != 0x18 && reg != 0x19 &&
129 reg != 0x1d && reg != 0x1e;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300130
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300131 /* common for saa7113/4/5/8 */
132 if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f ||
133 reg == 0xa3 || reg == 0xa7 || reg == 0xab || reg == 0xaf || (reg >= 0xb5 && reg <= 0xb7) ||
134 reg == 0xd3 || reg == 0xd7 || reg == 0xdb || reg == 0xdf || (reg >= 0xe5 && reg <= 0xe7) ||
135 reg == 0x82 || (reg >= 0x89 && reg <= 0x8e)))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300136 return 0;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300137
138 switch (id) {
Hans Verkuile1277112013-05-29 06:59:51 -0300139 case GM7113C:
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300140 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && reg < 0x20;
Hans Verkuile1277112013-05-29 06:59:51 -0300141 case SAA7113:
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300142 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
143 reg != 0x5d && reg < 0x63;
Hans Verkuile1277112013-05-29 06:59:51 -0300144 case SAA7114:
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300145 return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
146 (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
147 reg != 0x81 && reg < 0xf0;
Hans Verkuile1277112013-05-29 06:59:51 -0300148 case SAA7115:
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300149 return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe);
Hans Verkuile1277112013-05-29 06:59:51 -0300150 case SAA7118:
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300151 return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
152 (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
153 (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
154 }
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300155 return 1;
156}
157
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300158static int saa711x_writeregs(struct v4l2_subdev *sd, const unsigned char *regs)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800159{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300160 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800161 unsigned char reg, data;
162
163 while (*regs != 0x00) {
164 reg = *(regs++);
165 data = *(regs++);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300166
167 /* According with datasheets, reserved regs should be
168 filled with 0 - seems better not to touch on they */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300169 if (saa711x_has_reg(state->ident, reg)) {
170 if (saa711x_write(sd, reg, data) < 0)
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300171 return -1;
Mauro Carvalho Chehabd87edf22006-09-01 09:37:11 -0300172 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300173 v4l2_dbg(1, debug, sd, "tried to access reserved reg 0x%02x\n", reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300174 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800175 }
176 return 0;
177}
178
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300179static inline int saa711x_read(struct v4l2_subdev *sd, u8 reg)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800180{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300181 struct i2c_client *client = v4l2_get_subdevdata(sd);
182
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800183 return i2c_smbus_read_byte_data(client, reg);
184}
185
186/* ----------------------------------------------------------------------- */
187
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300188/* SAA7111 initialization table */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300189static const unsigned char saa7111_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300190 R_01_INC_DELAY, 0x00, /* reserved */
191
192 /*front end */
193 R_02_INPUT_CNTL_1, 0xd0, /* FUSE=3, GUDL=2, MODE=0 */
194 R_03_INPUT_CNTL_2, 0x23, /* HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0,
195 * GAFIX=0, GAI1=256, GAI2=256 */
196 R_04_INPUT_CNTL_3, 0x00, /* GAI1=256 */
197 R_05_INPUT_CNTL_4, 0x00, /* GAI2=256 */
198
199 /* decoder */
200 R_06_H_SYNC_START, 0xf3, /* HSB at 13(50Hz) / 17(60Hz)
201 * pixels after end of last line */
202 R_07_H_SYNC_STOP, 0xe8, /* HSS seems to be needed to
203 * work with NTSC, too */
204 R_08_SYNC_CNTL, 0xc8, /* AUFD=1, FSEL=1, EXFIL=0,
205 * VTRC=1, HPLL=0, VNOI=0 */
206 R_09_LUMA_CNTL, 0x01, /* BYPS=0, PREF=0, BPSS=0,
207 * VBLB=0, UPTCV=0, APER=1 */
208 R_0A_LUMA_BRIGHT_CNTL, 0x80,
209 R_0B_LUMA_CONTRAST_CNTL, 0x47, /* 0b - CONT=1.109 */
210 R_0C_CHROMA_SAT_CNTL, 0x40,
211 R_0D_CHROMA_HUE_CNTL, 0x00,
212 R_0E_CHROMA_CNTL_1, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0,
213 * FCTC=0, CHBW=1 */
214 R_0F_CHROMA_GAIN_CNTL, 0x00, /* reserved */
215 R_10_CHROMA_CNTL_2, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
216 R_11_MODE_DELAY_CNTL, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
217 * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
218 R_12_RT_SIGNAL_CNTL, 0x00, /* 12 - output control 2 */
219 R_13_RT_X_PORT_OUT_CNTL, 0x00, /* 13 - output control 3 */
220 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
221 R_15_VGATE_START_FID_CHG, 0x00,
222 R_16_VGATE_STOP, 0x00,
223 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
224
225 0x00, 0x00
226};
227
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300228/* SAA7113/GM7113C init codes
229 * It's important that R_14... R_17 == 0x00
230 * for the gm7113c chip to deliver stable video
231 */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300232static const unsigned char saa7113_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300233 R_01_INC_DELAY, 0x08,
234 R_02_INPUT_CNTL_1, 0xc2,
235 R_03_INPUT_CNTL_2, 0x30,
236 R_04_INPUT_CNTL_3, 0x00,
237 R_05_INPUT_CNTL_4, 0x00,
238 R_06_H_SYNC_START, 0x89,
239 R_07_H_SYNC_STOP, 0x0d,
240 R_08_SYNC_CNTL, 0x88,
241 R_09_LUMA_CNTL, 0x01,
242 R_0A_LUMA_BRIGHT_CNTL, 0x80,
243 R_0B_LUMA_CONTRAST_CNTL, 0x47,
244 R_0C_CHROMA_SAT_CNTL, 0x40,
245 R_0D_CHROMA_HUE_CNTL, 0x00,
246 R_0E_CHROMA_CNTL_1, 0x01,
247 R_0F_CHROMA_GAIN_CNTL, 0x2a,
248 R_10_CHROMA_CNTL_2, 0x08,
249 R_11_MODE_DELAY_CNTL, 0x0c,
250 R_12_RT_SIGNAL_CNTL, 0x07,
251 R_13_RT_X_PORT_OUT_CNTL, 0x00,
252 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
253 R_15_VGATE_START_FID_CHG, 0x00,
254 R_16_VGATE_STOP, 0x00,
255 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
256
257 0x00, 0x00
258};
259
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800260/* If a value differs from the Hauppauge driver values, then the comment starts with
261 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
262 Hauppauge driver sets. */
263
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300264/* SAA7114 and SAA7115 initialization table */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800265static const unsigned char saa7115_init_auto_input[] = {
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300266 /* Front-End Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300267 R_01_INC_DELAY, 0x48, /* white peak control disabled */
268 R_03_INPUT_CNTL_2, 0x20, /* was 0x30. 0x20: long vertical blanking */
269 R_04_INPUT_CNTL_3, 0x90, /* analog gain set to 0 */
270 R_05_INPUT_CNTL_4, 0x90, /* analog gain set to 0 */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300271 /* Decoder Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300272 R_06_H_SYNC_START, 0xeb, /* horiz sync begin = -21 */
273 R_07_H_SYNC_STOP, 0xe0, /* horiz sync stop = -17 */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300274 R_09_LUMA_CNTL, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300275 R_0A_LUMA_BRIGHT_CNTL, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */
276 R_0B_LUMA_CONTRAST_CNTL, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */
277 R_0C_CHROMA_SAT_CNTL, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */
278 R_0D_CHROMA_HUE_CNTL, 0x00,
279 R_0F_CHROMA_GAIN_CNTL, 0x00, /* use automatic gain */
280 R_10_CHROMA_CNTL_2, 0x06, /* chroma: active adaptive combfilter */
281 R_11_MODE_DELAY_CNTL, 0x00,
282 R_12_RT_SIGNAL_CNTL, 0x9d, /* RTS0 output control: VGATE */
283 R_13_RT_X_PORT_OUT_CNTL, 0x80, /* ITU656 standard mode, RTCO output enable RTCE */
284 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
285 R_18_RAW_DATA_GAIN_CNTL, 0x40, /* gain 0x00 = nominal */
286 R_19_RAW_DATA_OFF_CNTL, 0x80,
287 R_1A_COLOR_KILL_LVL_CNTL, 0x77, /* recommended value */
288 R_1B_MISC_TVVCRDET, 0x42, /* recommended value */
289 R_1C_ENHAN_COMB_CTRL1, 0xa9, /* recommended value */
290 R_1D_ENHAN_COMB_CTRL2, 0x01, /* recommended value */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300291
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300292
293 R_80_GLOBAL_CNTL_1, 0x0, /* No tasks enabled at init */
294
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300295 /* Power Device Control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300296 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset device */
297 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* set device programmed, all in operational mode */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800298 0x00, 0x00
299};
300
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300301/* Used to reset saa7113, saa7114 and saa7115 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800302static const unsigned char saa7115_cfg_reset_scaler[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300303 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00, /* disable I-port output */
304 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
305 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
306 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* enable I-port output */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800307 0x00, 0x00
308};
309
310/* ============== SAA7715 VIDEO templates ============= */
311
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800312static const unsigned char saa7115_cfg_60hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300313 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
314 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800315
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300316 R_15_VGATE_START_FID_CHG, 0x03,
317 R_16_VGATE_STOP, 0x11,
318 R_17_MISC_VGATE_CONF_AND_MSB, 0x9c,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800319
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300320 R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
321 R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800322
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300323 R_5A_V_OFF_FOR_SLICER, 0x06, /* standard 60hz value for ITU656 line counting */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800324
325 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300326 R_90_A_TASK_HANDLING_CNTL, 0x80,
327 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
328 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
329 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
330
331 /* hoffset low (input), 0x0002 is minimum */
332 R_94_A_HORIZ_INPUT_WINDOW_START, 0x01,
333 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
334
335 /* hsize low (input), 0x02d0 = 720 */
336 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
337 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
338
339 R_98_A_VERT_INPUT_WINDOW_START, 0x05,
340 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
341
342 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x0c,
343 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
344
345 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
346 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
347
348 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x0c,
349 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800350
351 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300352 R_C0_B_TASK_HANDLING_CNTL, 0x00,
353 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
354 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
355 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800356
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300357 /* 0x0002 is minimum */
358 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x02,
359 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800360
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300361 /* 0x02d0 = 720 */
362 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
363 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
364
365 /* vwindow start 0x12 = 18 */
366 R_C8_B_VERT_INPUT_WINDOW_START, 0x12,
367 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
368
369 /* vwindow length 0xf8 = 248 */
Mauro Carvalho Chehab97d9e802006-09-03 09:38:11 -0300370 R_CA_B_VERT_INPUT_WINDOW_LENGTH, VRES_60HZ>>1,
371 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, VRES_60HZ>>9,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300372
373 /* hwindow 0x02d0 = 720 */
374 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
375 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
376
377 R_F0_LFCO_PER_LINE, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
378 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0 */
379 R_F5_PULSGEN_LINE_LENGTH, 0xad,
380 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
381
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800382 0x00, 0x00
383};
384
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800385static const unsigned char saa7115_cfg_50hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300386 R_80_GLOBAL_CNTL_1, 0x00,
387 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800388
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300389 R_15_VGATE_START_FID_CHG, 0x37, /* VGATE start */
390 R_16_VGATE_STOP, 0x16,
391 R_17_MISC_VGATE_CONF_AND_MSB, 0x99,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800392
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300393 R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */
394 R_0E_CHROMA_CNTL_1, 0x07,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800395
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300396 R_5A_V_OFF_FOR_SLICER, 0x03, /* standard 50hz value */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800397
398 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300399 R_90_A_TASK_HANDLING_CNTL, 0x81,
400 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
401 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
402 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
403
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800404 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
405 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300406 /* hoffset low (input), 0x0002 is minimum */
407 R_94_A_HORIZ_INPUT_WINDOW_START, 0x00,
408 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
409
410 /* hsize low (input), 0x02d0 = 720 */
411 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
412 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
413
414 R_98_A_VERT_INPUT_WINDOW_START, 0x03,
415 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
416
417 /* vsize 0x12 = 18 */
418 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x12,
419 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
420
421 /* hsize 0x05a0 = 1440 */
422 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
423 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05, /* hsize hi (output) */
424 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x12, /* vsize low (output), 0x12 = 18 */
425 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00, /* vsize hi (output) */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800426
427 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300428 R_C0_B_TASK_HANDLING_CNTL, 0x00,
429 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
430 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
431 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800432
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300433 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
434 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
435 /* hoffset low (input), 0x0002 is minimum. See comment above. */
436 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x00,
437 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800438
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300439 /* hsize 0x02d0 = 720 */
440 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
441 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
442
443 /* voffset 0x16 = 22 */
444 R_C8_B_VERT_INPUT_WINDOW_START, 0x16,
445 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
446
447 /* vsize 0x0120 = 288 */
448 R_CA_B_VERT_INPUT_WINDOW_LENGTH, 0x20,
449 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, 0x01,
450
451 /* hsize 0x02d0 = 720 */
452 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
453 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
454
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300455 R_F0_LFCO_PER_LINE, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
456 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0, (was 0x05) */
457 R_F5_PULSGEN_LINE_LENGTH, 0xb0,
458 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
459
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800460 0x00, 0x00
461};
462
463/* ============== SAA7715 VIDEO templates (end) ======= */
464
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300465/* ============== GM7113C VIDEO templates ============= */
466static const unsigned char gm7113c_cfg_60hz_video[] = {
467 R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
468 R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */
469
470 0x00, 0x00
471};
472
473static const unsigned char gm7113c_cfg_50hz_video[] = {
474 R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */
475 R_0E_CHROMA_CNTL_1, 0x07,
476
477 0x00, 0x00
478};
479
480/* ============== GM7113C VIDEO templates (end) ======= */
481
482
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800483static const unsigned char saa7115_cfg_vbi_on[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300484 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
485 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
486 R_80_GLOBAL_CNTL_1, 0x30, /* Activate both tasks */
487 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
488 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
489
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800490 0x00, 0x00
491};
492
493static const unsigned char saa7115_cfg_vbi_off[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300494 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
495 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
496 R_80_GLOBAL_CNTL_1, 0x20, /* Activate only task "B" */
497 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
498 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
499
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800500 0x00, 0x00
501};
502
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300503
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800504static const unsigned char saa7115_init_misc[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300505 R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300506 R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 0x01,
507 R_84_I_PORT_SIGNAL_DEF, 0x20,
508 R_85_I_PORT_SIGNAL_POLAR, 0x21,
509 R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT, 0xc5,
510 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800511
512 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300513 R_A0_A_HORIZ_PRESCALING, 0x01,
514 R_A1_A_ACCUMULATION_LENGTH, 0x00,
515 R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800516
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300517 /* Configure controls at nominal value*/
518 R_A4_A_LUMA_BRIGHTNESS_CNTL, 0x80,
519 R_A5_A_LUMA_CONTRAST_CNTL, 0x40,
520 R_A6_A_CHROMA_SATURATION_CNTL, 0x40,
521
522 /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
523 R_A8_A_HORIZ_LUMA_SCALING_INC, 0x00,
524 R_A9_A_HORIZ_LUMA_SCALING_INC_MSB, 0x02,
525
526 R_AA_A_HORIZ_LUMA_PHASE_OFF, 0x00,
527
528 /* must be horiz lum scaling / 2 */
529 R_AC_A_HORIZ_CHROMA_SCALING_INC, 0x00,
530 R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB, 0x01,
531
532 /* must be offset luma / 2 */
533 R_AE_A_HORIZ_CHROMA_PHASE_OFF, 0x00,
534
535 R_B0_A_VERT_LUMA_SCALING_INC, 0x00,
536 R_B1_A_VERT_LUMA_SCALING_INC_MSB, 0x04,
537
538 R_B2_A_VERT_CHROMA_SCALING_INC, 0x00,
539 R_B3_A_VERT_CHROMA_SCALING_INC_MSB, 0x04,
540
541 R_B4_A_VERT_SCALING_MODE_CNTL, 0x01,
542
543 R_B8_A_VERT_CHROMA_PHASE_OFF_00, 0x00,
544 R_B9_A_VERT_CHROMA_PHASE_OFF_01, 0x00,
545 R_BA_A_VERT_CHROMA_PHASE_OFF_10, 0x00,
546 R_BB_A_VERT_CHROMA_PHASE_OFF_11, 0x00,
547
548 R_BC_A_VERT_LUMA_PHASE_OFF_00, 0x00,
549 R_BD_A_VERT_LUMA_PHASE_OFF_01, 0x00,
550 R_BE_A_VERT_LUMA_PHASE_OFF_10, 0x00,
551 R_BF_A_VERT_LUMA_PHASE_OFF_11, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800552
553 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300554 R_D0_B_HORIZ_PRESCALING, 0x01,
555 R_D1_B_ACCUMULATION_LENGTH, 0x00,
556 R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800557
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300558 /* Configure controls at nominal value*/
559 R_D4_B_LUMA_BRIGHTNESS_CNTL, 0x80,
560 R_D5_B_LUMA_CONTRAST_CNTL, 0x40,
561 R_D6_B_CHROMA_SATURATION_CNTL, 0x40,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800562
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300563 /* hor lum scaling 0x0400 = 1 */
564 R_D8_B_HORIZ_LUMA_SCALING_INC, 0x00,
565 R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, 0x04,
566
567 R_DA_B_HORIZ_LUMA_PHASE_OFF, 0x00,
568
569 /* must be hor lum scaling / 2 */
570 R_DC_B_HORIZ_CHROMA_SCALING, 0x00,
571 R_DD_B_HORIZ_CHROMA_SCALING_MSB, 0x02,
572
573 /* must be offset luma / 2 */
574 R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA, 0x00,
575
576 R_E0_B_VERT_LUMA_SCALING_INC, 0x00,
577 R_E1_B_VERT_LUMA_SCALING_INC_MSB, 0x04,
578
579 R_E2_B_VERT_CHROMA_SCALING_INC, 0x00,
580 R_E3_B_VERT_CHROMA_SCALING_INC_MSB, 0x04,
581
582 R_E4_B_VERT_SCALING_MODE_CNTL, 0x01,
583
584 R_E8_B_VERT_CHROMA_PHASE_OFF_00, 0x00,
585 R_E9_B_VERT_CHROMA_PHASE_OFF_01, 0x00,
586 R_EA_B_VERT_CHROMA_PHASE_OFF_10, 0x00,
587 R_EB_B_VERT_CHROMA_PHASE_OFF_11, 0x00,
588
589 R_EC_B_VERT_LUMA_PHASE_OFF_00, 0x00,
590 R_ED_B_VERT_LUMA_PHASE_OFF_01, 0x00,
591 R_EE_B_VERT_LUMA_PHASE_OFF_10, 0x00,
592 R_EF_B_VERT_LUMA_PHASE_OFF_11, 0x00,
593
594 R_F2_NOMINAL_PLL2_DTO, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */
595 R_F3_PLL_INCREMENT, 0x46,
596 R_F4_PLL2_STATUS, 0x00,
597 R_F7_PULSE_A_POS_MSB, 0x4b, /* not the recommended settings! */
598 R_F8_PULSE_B_POS, 0x00,
599 R_F9_PULSE_B_POS_MSB, 0x4b,
600 R_FA_PULSE_C_POS, 0x00,
601 R_FB_PULSE_C_POS_MSB, 0x4b,
602
603 /* PLL2 lock detection settings: 71 lines 50% phase error */
604 R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES, 0x88,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800605
606 /* Turn off VBI */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300607 R_40_SLICER_CNTL_1, 0x20, /* No framing code errors allowed. */
608 R_41_LCR_BASE, 0xff,
609 R_41_LCR_BASE+1, 0xff,
610 R_41_LCR_BASE+2, 0xff,
611 R_41_LCR_BASE+3, 0xff,
612 R_41_LCR_BASE+4, 0xff,
613 R_41_LCR_BASE+5, 0xff,
614 R_41_LCR_BASE+6, 0xff,
615 R_41_LCR_BASE+7, 0xff,
616 R_41_LCR_BASE+8, 0xff,
617 R_41_LCR_BASE+9, 0xff,
618 R_41_LCR_BASE+10, 0xff,
619 R_41_LCR_BASE+11, 0xff,
620 R_41_LCR_BASE+12, 0xff,
621 R_41_LCR_BASE+13, 0xff,
622 R_41_LCR_BASE+14, 0xff,
623 R_41_LCR_BASE+15, 0xff,
624 R_41_LCR_BASE+16, 0xff,
625 R_41_LCR_BASE+17, 0xff,
626 R_41_LCR_BASE+18, 0xff,
627 R_41_LCR_BASE+19, 0xff,
628 R_41_LCR_BASE+20, 0xff,
629 R_41_LCR_BASE+21, 0xff,
630 R_41_LCR_BASE+22, 0xff,
631 R_58_PROGRAM_FRAMING_CODE, 0x40,
632 R_59_H_OFF_FOR_SLICER, 0x47,
633 R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF, 0x83,
634 R_5D_DID, 0xbd,
635 R_5E_SDID, 0x35,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800636
Devin Heitmuellerfea551f2010-02-03 00:33:48 -0300637 R_02_INPUT_CNTL_1, 0xc4, /* input tuner -> input 4, amplifier active */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800638
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300639 R_80_GLOBAL_CNTL_1, 0x20, /* enable task B */
640 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
641 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800642 0x00, 0x00
643};
644
Mauro Carvalho Chehab66ec1192006-08-29 22:52:32 -0300645static int saa711x_odd_parity(u8 c)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800646{
647 c ^= (c >> 4);
648 c ^= (c >> 2);
649 c ^= (c >> 1);
650
651 return c & 1;
652}
653
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300654static int saa711x_decode_vps(u8 *dst, u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800655{
656 static const u8 biphase_tbl[] = {
657 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
658 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
659 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
660 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
661 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
662 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
663 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
664 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
665 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
666 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
667 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
668 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
669 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
670 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
671 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
672 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
673 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
674 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
675 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
676 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
677 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
678 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
679 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
680 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
681 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
682 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
683 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
684 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
685 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
686 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
687 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
688 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
689 };
690 int i;
691 u8 c, err = 0;
692
693 for (i = 0; i < 2 * 13; i += 2) {
694 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
695 c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
696 dst[i / 2] = c;
697 }
698 return err & 0xf0;
699}
700
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300701static int saa711x_decode_wss(u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800702{
703 static const int wss_bits[8] = {
704 0, 0, 0, 1, 0, 1, 1, 1
705 };
706 unsigned char parity;
707 int wss = 0;
708 int i;
709
710 for (i = 0; i < 16; i++) {
711 int b1 = wss_bits[p[i] & 7];
712 int b2 = wss_bits[(p[i] >> 3) & 7];
713
714 if (b1 == b2)
715 return -1;
716 wss |= b2 << i;
717 }
718 parity = wss & 15;
719 parity ^= parity >> 2;
720 parity ^= parity >> 1;
721
722 if (!(parity & 1))
723 return -1;
724
725 return wss;
726}
727
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300728static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800729{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300730 struct saa711x_state *state = to_state(sd);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200731 u32 acpf;
732 u32 acni;
733 u32 hz;
734 u64 f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300735 u8 acc = 0; /* reg 0x3a, audio clock control */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800736
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300737 /* Checks for chips that don't have audio clock (saa7111, saa7113) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300738 if (!saa711x_has_reg(state->ident, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300739 return 0;
740
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300741 v4l2_dbg(1, debug, sd, "set audio clock freq: %d\n", freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200742
743 /* sanity check */
744 if (freq < 32000 || freq > 48000)
745 return -EINVAL;
746
747 /* hz is the refresh rate times 100 */
748 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
749 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
750 acpf = (25600 * freq) / hz;
751 /* acni = (256 * freq * 2^23) / crystal_frequency =
752 (freq * 2^(8+23)) / crystal_frequency =
Hans Verkuilb7f82922006-04-02 12:50:42 -0300753 (freq << 31) / crystal_frequency */
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200754 f = freq;
755 f = f << 31;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300756 do_div(f, state->crystal_freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200757 acni = f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300758 if (state->ucgc) {
759 acpf = acpf * state->cgcdiv / 16;
760 acni = acni * state->cgcdiv / 16;
761 acc = 0x80;
762 if (state->cgcdiv == 3)
763 acc |= 0x40;
764 }
765 if (state->apll)
766 acc |= 0x08;
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200767
Hans Verkuil15890372013-03-11 03:47:25 -0300768 if (state->double_asclk) {
769 acpf <<= 1;
770 acni <<= 1;
771 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300772 saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
Hans Verkuil15890372013-03-11 03:47:25 -0300773 saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10 << state->double_asclk);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300774 saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300775
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300776 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
777 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300778 (acpf >> 8) & 0xff);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300779 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300780 (acpf >> 16) & 0x03);
781
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300782 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
783 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
784 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800785 state->audclk_freq = freq;
786 return 0;
787}
788
Hans Verkuile3560542010-05-24 10:00:52 -0300789static int saa711x_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800790{
Hans Verkuile3560542010-05-24 10:00:52 -0300791 struct v4l2_subdev *sd = to_sd(ctrl);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300792 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800793
794 switch (ctrl->id) {
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300795 case V4L2_CID_CHROMA_AGC:
Hans Verkuile3560542010-05-24 10:00:52 -0300796 /* chroma gain cluster */
Hans Verkuilddac5c12011-06-10 05:43:34 -0300797 if (state->agc->val)
798 state->gain->val =
Hans Verkuile3560542010-05-24 10:00:52 -0300799 saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL) & 0x7f;
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300800 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800801 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800802 return 0;
803}
804
Hans Verkuile3560542010-05-24 10:00:52 -0300805static int saa711x_s_ctrl(struct v4l2_ctrl *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800806{
Hans Verkuile3560542010-05-24 10:00:52 -0300807 struct v4l2_subdev *sd = to_sd(ctrl);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300808 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800809
810 switch (ctrl->id) {
811 case V4L2_CID_BRIGHTNESS:
Hans Verkuile3560542010-05-24 10:00:52 -0300812 saa711x_write(sd, R_0A_LUMA_BRIGHT_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800813 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300814
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800815 case V4L2_CID_CONTRAST:
Hans Verkuile3560542010-05-24 10:00:52 -0300816 saa711x_write(sd, R_0B_LUMA_CONTRAST_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800817 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300818
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800819 case V4L2_CID_SATURATION:
Hans Verkuile3560542010-05-24 10:00:52 -0300820 saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800821 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300822
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800823 case V4L2_CID_HUE:
Hans Verkuile3560542010-05-24 10:00:52 -0300824 saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800825 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300826
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300827 case V4L2_CID_CHROMA_AGC:
Hans Verkuile3560542010-05-24 10:00:52 -0300828 /* chroma gain cluster */
829 if (state->agc->val)
830 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val);
831 else
832 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val | 0x80);
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300833 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300834
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800835 default:
836 return -EINVAL;
837 }
838
839 return 0;
840}
841
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300842static int saa711x_set_size(struct v4l2_subdev *sd, int width, int height)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300843{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300844 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300845 int HPSC, HFSC;
846 int VSCY;
847 int res;
848 int is_50hz = state->std & V4L2_STD_625_50;
849 int Vsrc = is_50hz ? 576 : 480;
850
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300851 v4l2_dbg(1, debug, sd, "decoder set size to %ix%i\n", width, height);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300852
853 /* FIXME need better bounds checking here */
854 if ((width < 1) || (width > 1440))
855 return -EINVAL;
856 if ((height < 1) || (height > Vsrc))
857 return -EINVAL;
858
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300859 if (!saa711x_has_reg(state->ident, R_D0_B_HORIZ_PRESCALING)) {
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300860 /* Decoder only supports 720 columns and 480 or 576 lines */
861 if (width != 720)
862 return -EINVAL;
863 if (height != Vsrc)
864 return -EINVAL;
865 }
866
867 state->width = width;
868 state->height = height;
869
870 if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
871 return 0;
872
873 /* probably have a valid size, let's set it */
874 /* Set output width/height */
875 /* width */
876
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300877 saa711x_write(sd, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300878 (u8) (width & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300879 saa711x_write(sd, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300880 (u8) ((width >> 8) & 0xff));
881
882 /* Vertical Scaling uses height/2 */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300883 res = height / 2;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300884
885 /* On 60Hz, it is using a higher Vertical Output Size */
886 if (!is_50hz)
Hans Verkuild0d30c02006-11-25 09:45:50 -0300887 res += (VRES_60HZ - 480) >> 1;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300888
889 /* height */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300890 saa711x_write(sd, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300891 (u8) (res & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300892 saa711x_write(sd, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300893 (u8) ((res >> 8) & 0xff));
894
895 /* Scaling settings */
896 /* Hprescaler is floor(inres/outres) */
897 HPSC = (int)(720 / width);
898 /* 0 is not allowed (div. by zero) */
899 HPSC = HPSC ? HPSC : 1;
900 HFSC = (int)((1024 * 720) / (HPSC * width));
901 /* FIXME hardcodes to "Task B"
902 * write H prescaler integer */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300903 saa711x_write(sd, R_D0_B_HORIZ_PRESCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300904 (u8) (HPSC & 0x3f));
905
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300906 v4l2_dbg(1, debug, sd, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300907 /* write H fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300908 saa711x_write(sd, R_D8_B_HORIZ_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300909 (u8) (HFSC & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300910 saa711x_write(sd, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300911 (u8) ((HFSC >> 8) & 0xff));
912 /* write H fine-scaling (chrominance)
913 * must be lum/2, so i'll just bitshift :) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300914 saa711x_write(sd, R_DC_B_HORIZ_CHROMA_SCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300915 (u8) ((HFSC >> 1) & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300916 saa711x_write(sd, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300917 (u8) ((HFSC >> 9) & 0xff));
918
919 VSCY = (int)((1024 * Vsrc) / height);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300920 v4l2_dbg(1, debug, sd, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300921
922 /* Correct Contrast and Luminance */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300923 saa711x_write(sd, R_D5_B_LUMA_CONTRAST_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300924 (u8) (64 * 1024 / VSCY));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300925 saa711x_write(sd, R_D6_B_CHROMA_SATURATION_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300926 (u8) (64 * 1024 / VSCY));
927
928 /* write V fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300929 saa711x_write(sd, R_E0_B_VERT_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300930 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300931 saa711x_write(sd, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300932 (u8) ((VSCY >> 8) & 0xff));
933 /* write V fine-scaling (chrominance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300934 saa711x_write(sd, R_E2_B_VERT_CHROMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300935 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300936 saa711x_write(sd, R_E3_B_VERT_CHROMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300937 (u8) ((VSCY >> 8) & 0xff));
938
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300939 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300940
941 /* Activates task "B" */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300942 saa711x_write(sd, R_80_GLOBAL_CNTL_1,
943 saa711x_read(sd, R_80_GLOBAL_CNTL_1) | 0x20);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300944
945 return 0;
946}
947
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300948static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800949{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300950 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800951
Hans Verkuil30b54d52006-01-09 15:25:43 -0200952 /* Prevent unnecessary standard changes. During a standard
953 change the I-Port is temporarily disabled. Any devices
954 reading from that port can get confused.
Hans Verkuilbccfa442009-03-30 06:55:27 -0300955 Note that s_std is also used to switch from
956 radio to TV mode, so if a s_std is broadcast to
Hans Verkuil30b54d52006-01-09 15:25:43 -0200957 all I2C devices then you do not want to have an unwanted
958 side-effect here. */
959 if (std == state->std)
960 return;
961
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300962 state->std = std;
963
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800964 // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
965 if (std & V4L2_STD_525_60) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300966 v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n");
Hans Verkuile1277112013-05-29 06:59:51 -0300967 if (state->ident == GM7113C)
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300968 saa711x_writeregs(sd, gm7113c_cfg_60hz_video);
969 else
970 saa711x_writeregs(sd, saa7115_cfg_60hz_video);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300971 saa711x_set_size(sd, 720, 480);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800972 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300973 v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n");
Hans Verkuile1277112013-05-29 06:59:51 -0300974 if (state->ident == GM7113C)
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300975 saa711x_writeregs(sd, gm7113c_cfg_50hz_video);
976 else
977 saa711x_writeregs(sd, saa7115_cfg_50hz_video);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300978 saa711x_set_size(sd, 720, 576);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800979 }
980
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300981 /* Register 0E - Bits D6-D4 on NO-AUTO mode
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300982 (SAA7111 and SAA7113 doesn't have auto mode)
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300983 50 Hz / 625 lines 60 Hz / 525 lines
984 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz)
985 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz)
986 010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz)
987 011 NTSC N (3.58MHz) PAL M (3.58MHz)
988 100 reserved NTSC-Japan (3.58MHz)
989 */
Hans Verkuile1277112013-05-29 06:59:51 -0300990 if (state->ident <= SAA7113 ||
991 state->ident == GM7113C) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300992 u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -0300993
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300994 if (std == V4L2_STD_PAL_M) {
Hans Verkuil01342352006-03-25 08:19:47 -0300995 reg |= 0x30;
Hans Verkuile0028022008-04-22 14:45:51 -0300996 } else if (std == V4L2_STD_PAL_Nc) {
Hans Verkuil01342352006-03-25 08:19:47 -0300997 reg |= 0x20;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -0300998 } else if (std == V4L2_STD_PAL_60) {
Hans Verkuil01342352006-03-25 08:19:47 -0300999 reg |= 0x10;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -03001000 } else if (std == V4L2_STD_NTSC_M_JP) {
Hans Verkuil01342352006-03-25 08:19:47 -03001001 reg |= 0x40;
Mauro Carvalho Chehaba9aaec42007-03-13 13:41:49 -03001002 } else if (std & V4L2_STD_SECAM) {
Pádraig Bradyfc2fa312006-10-09 08:02:17 -03001003 reg |= 0x50;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001004 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001005 saa711x_write(sd, R_0E_CHROMA_CNTL_1, reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001006 } else {
1007 /* restart task B if needed */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001008 int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001009
Hans Verkuile1277112013-05-29 06:59:51 -03001010 if (taskb && state->ident == SAA7114)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001011 saa711x_writeregs(sd, saa7115_cfg_vbi_on);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001012
1013 /* switch audio mode too! */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001014 saa711x_s_clock_freq(sd, state->audclk_freq);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001015 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001016}
1017
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001018/* setup the sliced VBI lcr registers according to the sliced VBI format */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001019static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001020{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001021 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001022 int is_50hz = (state->std & V4L2_STD_625_50);
1023 u8 lcr[24];
1024 int i, x;
1025
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001026#if 1
1027 /* saa7113/7114/7118 VBI support are experimental */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001028 if (!saa711x_has_reg(state->ident, R_41_LCR_BASE))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001029 return;
1030
1031#else
1032 /* SAA7113 and SAA7118 also should support VBI - Need testing */
Hans Verkuile1277112013-05-29 06:59:51 -03001033 if (state->ident != SAA7115)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001034 return;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001035#endif
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001036
1037 for (i = 0; i <= 23; i++)
1038 lcr[i] = 0xff;
1039
Hans Verkuila8b86432008-10-04 08:05:30 -03001040 if (fmt == NULL) {
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001041 /* raw VBI */
1042 if (is_50hz)
1043 for (i = 6; i <= 23; i++)
1044 lcr[i] = 0xdd;
1045 else
1046 for (i = 10; i <= 21; i++)
1047 lcr[i] = 0xdd;
1048 } else {
1049 /* sliced VBI */
1050 /* first clear lines that cannot be captured */
1051 if (is_50hz) {
1052 for (i = 0; i <= 5; i++)
1053 fmt->service_lines[0][i] =
1054 fmt->service_lines[1][i] = 0;
1055 }
1056 else {
1057 for (i = 0; i <= 9; i++)
1058 fmt->service_lines[0][i] =
1059 fmt->service_lines[1][i] = 0;
1060 for (i = 22; i <= 23; i++)
1061 fmt->service_lines[0][i] =
1062 fmt->service_lines[1][i] = 0;
1063 }
1064
1065 /* Now set the lcr values according to the specified service */
1066 for (i = 6; i <= 23; i++) {
1067 lcr[i] = 0;
1068 for (x = 0; x <= 1; x++) {
1069 switch (fmt->service_lines[1-x][i]) {
1070 case 0:
1071 lcr[i] |= 0xf << (4 * x);
1072 break;
Hans Verkuil9bc74002006-03-29 18:02:51 -03001073 case V4L2_SLICED_TELETEXT_B:
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001074 lcr[i] |= 1 << (4 * x);
1075 break;
1076 case V4L2_SLICED_CAPTION_525:
1077 lcr[i] |= 4 << (4 * x);
1078 break;
1079 case V4L2_SLICED_WSS_625:
1080 lcr[i] |= 5 << (4 * x);
1081 break;
1082 case V4L2_SLICED_VPS:
1083 lcr[i] |= 7 << (4 * x);
1084 break;
1085 }
1086 }
1087 }
1088 }
1089
1090 /* write the lcr registers */
1091 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001092 saa711x_write(sd, i - 2 + R_41_LCR_BASE, lcr[i]);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001093 }
1094
1095 /* enable/disable raw VBI capturing */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001096 saa711x_writeregs(sd, fmt == NULL ?
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001097 saa7115_cfg_vbi_on :
1098 saa7115_cfg_vbi_off);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001099}
1100
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001101static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *sliced)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001102{
1103 static u16 lcr2vbi[] = {
Hans Verkuil9bc74002006-03-29 18:02:51 -03001104 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001105 0, V4L2_SLICED_CAPTION_525, /* 4 */
1106 V4L2_SLICED_WSS_625, 0, /* 5 */
1107 V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
1108 0, 0, 0, 0
1109 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001110 int i;
1111
Hans Verkuil30634e82012-09-05 10:38:10 -03001112 memset(sliced->service_lines, 0, sizeof(sliced->service_lines));
1113 sliced->service_set = 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001114 /* done if using raw VBI */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001115 if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001116 return 0;
1117 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001118 u8 v = saa711x_read(sd, i - 2 + R_41_LCR_BASE);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001119
1120 sliced->service_lines[0][i] = lcr2vbi[v >> 4];
1121 sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
1122 sliced->service_set |=
1123 sliced->service_lines[0][i] | sliced->service_lines[1][i];
1124 }
1125 return 0;
1126}
1127
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001128static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
1129{
1130 saa711x_set_lcr(sd, NULL);
1131 return 0;
1132}
1133
1134static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
1135{
1136 saa711x_set_lcr(sd, fmt);
1137 return 0;
1138}
1139
Hans Verkuilc463d932010-05-09 09:47:23 -03001140static int saa711x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
1141{
1142 if (fmt->code != V4L2_MBUS_FMT_FIXED)
1143 return -EINVAL;
1144 fmt->field = V4L2_FIELD_INTERLACED;
1145 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
1146 return saa711x_set_size(sd, fmt->width, fmt->height);
1147}
1148
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001149/* Decode the sliced VBI data stream as created by the saa7115.
1150 The format is described in the saa7115 datasheet in Tables 25 and 26
1151 and in Figure 33.
1152 The current implementation uses SAV/EAV codes and not the ancillary data
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001153 headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001154 code. */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001155static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001156{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001157 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001158 static const char vbi_no_data_pattern[] = {
1159 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
1160 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001161 u8 *p = vbi->p;
1162 u32 wss;
1163 int id1, id2; /* the ID1 and ID2 bytes from the internal header */
1164
1165 vbi->type = 0; /* mark result as a failure */
1166 id1 = p[2];
1167 id2 = p[3];
1168 /* Note: the field bit is inverted for 60 Hz video */
1169 if (state->std & V4L2_STD_525_60)
1170 id1 ^= 0x40;
1171
1172 /* Skip internal header, p now points to the start of the payload */
1173 p += 4;
1174 vbi->p = p;
1175
1176 /* calculate field and line number of the VBI packet (1-23) */
1177 vbi->is_second_field = ((id1 & 0x40) != 0);
1178 vbi->line = (id1 & 0x3f) << 3;
1179 vbi->line |= (id2 & 0x70) >> 4;
1180
1181 /* Obtain data type */
1182 id2 &= 0xf;
1183
1184 /* If the VBI slicer does not detect any signal it will fill up
1185 the payload buffer with 0xa0 bytes. */
1186 if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001187 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001188
1189 /* decode payloads */
1190 switch (id2) {
1191 case 1:
Hans Verkuil9bc74002006-03-29 18:02:51 -03001192 vbi->type = V4L2_SLICED_TELETEXT_B;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001193 break;
1194 case 4:
Mauro Carvalho Chehab59ba9152006-08-30 05:34:36 -03001195 if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001196 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001197 vbi->type = V4L2_SLICED_CAPTION_525;
1198 break;
1199 case 5:
Mauro Carvalho Chehab66ec1192006-08-29 22:52:32 -03001200 wss = saa711x_decode_wss(p);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001201 if (wss == -1)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001202 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001203 p[0] = wss & 0xff;
1204 p[1] = wss >> 8;
1205 vbi->type = V4L2_SLICED_WSS_625;
1206 break;
1207 case 7:
Mauro Carvalho Chehab66ec1192006-08-29 22:52:32 -03001208 if (saa711x_decode_vps(p, p) != 0)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001209 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001210 vbi->type = V4L2_SLICED_VPS;
1211 break;
1212 default:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001213 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001214 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001215 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001216}
1217
1218/* ============ SAA7115 AUDIO settings (end) ============= */
1219
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001220static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001221{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001222 struct saa711x_state *state = to_state(sd);
1223 int status;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001224
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001225 if (state->radio)
1226 return 0;
1227 status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001228
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001229 v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status);
1230 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1231 return 0;
1232}
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001233
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001234static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1235{
1236 struct saa711x_state *state = to_state(sd);
1237
1238 state->radio = 0;
1239 saa711x_set_v4lstd(sd, std);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001240 return 0;
1241}
1242
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001243static int saa711x_s_radio(struct v4l2_subdev *sd)
1244{
1245 struct saa711x_state *state = to_state(sd);
1246
1247 state->radio = 1;
1248 return 0;
1249}
1250
Hans Verkuil5325b422009-04-02 11:26:22 -03001251static int saa711x_s_routing(struct v4l2_subdev *sd,
1252 u32 input, u32 output, u32 config)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001253{
1254 struct saa711x_state *state = to_state(sd);
Hans Verkuile1277112013-05-29 06:59:51 -03001255 u8 mask = (state->ident <= SAA7111A) ? 0xf8 : 0xf0;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001256
Hans Verkuil5325b422009-04-02 11:26:22 -03001257 v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n",
1258 input, output);
1259
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001260 /* saa7111/3 does not have these inputs */
Hans Verkuile1277112013-05-29 06:59:51 -03001261 if ((state->ident <= SAA7113 ||
1262 state->ident == GM7113C) &&
Hans Verkuil5325b422009-04-02 11:26:22 -03001263 (input == SAA7115_COMPOSITE4 ||
1264 input == SAA7115_COMPOSITE5)) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001265 return -EINVAL;
1266 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001267 if (input > SAA7115_SVIDEO3)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001268 return -EINVAL;
Hans Verkuil5325b422009-04-02 11:26:22 -03001269 if (state->input == input && state->output == output)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001270 return 0;
1271 v4l2_dbg(1, debug, sd, "now setting %s input %s output\n",
Hans Verkuil5325b422009-04-02 11:26:22 -03001272 (input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite",
1273 (output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
1274 state->input = input;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001275
1276 /* saa7111 has slightly different input numbering */
Hans Verkuile1277112013-05-29 06:59:51 -03001277 if (state->ident <= SAA7111A) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001278 if (input >= SAA7115_COMPOSITE4)
1279 input -= 2;
1280 /* saa7111 specific */
1281 saa711x_write(sd, R_10_CHROMA_CNTL_2,
1282 (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001283 ((output & 0xc0) ^ 0x40));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001284 saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL,
1285 (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001286 ((output & 2) ? 0x0a : 0));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001287 }
1288
1289 /* select mode */
1290 saa711x_write(sd, R_02_INPUT_CNTL_1,
1291 (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) |
1292 input);
1293
1294 /* bypass chrominance trap for S-Video modes */
1295 saa711x_write(sd, R_09_LUMA_CNTL,
1296 (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) |
1297 (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
1298
Hans Verkuil5325b422009-04-02 11:26:22 -03001299 state->output = output;
Hans Verkuile1277112013-05-29 06:59:51 -03001300 if (state->ident == SAA7114 ||
1301 state->ident == SAA7115) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001302 saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
1303 (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
1304 (state->output & 0x01));
1305 }
Hans Verkuile1277112013-05-29 06:59:51 -03001306 if (state->ident > SAA7111A) {
Hans Verkuila0fc5882013-03-08 11:22:03 -03001307 if (config & SAA7115_IDQ_IS_DEFAULT)
1308 saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x20);
1309 else
1310 saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x21);
1311 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001312 return 0;
1313}
1314
1315static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val)
1316{
1317 struct saa711x_state *state = to_state(sd);
1318
Hans Verkuile1277112013-05-29 06:59:51 -03001319 if (state->ident > SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001320 return -EINVAL;
1321 saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) |
1322 (val ? 0x80 : 0));
1323 return 0;
1324}
1325
1326static int saa711x_s_stream(struct v4l2_subdev *sd, int enable)
1327{
1328 struct saa711x_state *state = to_state(sd);
1329
1330 v4l2_dbg(1, debug, sd, "%s output\n",
1331 enable ? "enable" : "disable");
1332
Hans Verkuil674a3232009-02-18 12:22:16 -03001333 if (state->enable == enable)
1334 return 0;
1335 state->enable = enable;
1336 if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED))
1337 return 0;
1338 saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001339 return 0;
1340}
1341
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001342static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001343{
1344 struct saa711x_state *state = to_state(sd);
1345
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001346 if (freq != SAA7115_FREQ_32_11_MHZ && freq != SAA7115_FREQ_24_576_MHZ)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001347 return -EINVAL;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001348 state->crystal_freq = freq;
Hans Verkuil15890372013-03-11 03:47:25 -03001349 state->double_asclk = flags & SAA7115_FREQ_FL_DOUBLE_ASCLK;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001350 state->cgcdiv = (flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
Hans Verkuil15890372013-03-11 03:47:25 -03001351 state->ucgc = flags & SAA7115_FREQ_FL_UCGC;
1352 state->apll = flags & SAA7115_FREQ_FL_APLL;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001353 saa711x_s_clock_freq(sd, state->audclk_freq);
1354 return 0;
1355}
1356
1357static int saa711x_reset(struct v4l2_subdev *sd, u32 val)
1358{
1359 v4l2_dbg(1, debug, sd, "decoder RESET\n");
1360 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
1361 return 0;
1362}
1363
1364static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data)
1365{
1366 /* Note: the internal field ID is inverted for NTSC,
1367 so data->field 0 maps to the saa7115 even field,
1368 whereas for PAL it maps to the saa7115 odd field. */
1369 switch (data->id) {
1370 case V4L2_SLICED_WSS_625:
1371 if (saa711x_read(sd, 0x6b) & 0xc0)
1372 return -EIO;
1373 data->data[0] = saa711x_read(sd, 0x6c);
1374 data->data[1] = saa711x_read(sd, 0x6d);
1375 return 0;
1376 case V4L2_SLICED_CAPTION_525:
1377 if (data->field == 0) {
1378 /* CC */
1379 if (saa711x_read(sd, 0x66) & 0x30)
1380 return -EIO;
1381 data->data[0] = saa711x_read(sd, 0x69);
1382 data->data[1] = saa711x_read(sd, 0x6a);
1383 return 0;
1384 }
1385 /* XDS */
1386 if (saa711x_read(sd, 0x66) & 0xc0)
1387 return -EIO;
1388 data->data[0] = saa711x_read(sd, 0x67);
1389 data->data[1] = saa711x_read(sd, 0x68);
1390 return 0;
1391 default:
1392 return -EINVAL;
1393 }
1394}
1395
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001396static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
1397{
1398 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001399 int reg1f, reg1e;
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001400
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001401 /*
1402 * The V4L2 core already initializes std with all supported
1403 * Standards. All driver needs to do is to mask it, to remove
1404 * standards that don't apply from the mask
1405 */
1406
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001407 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuilc875dee2013-03-10 09:59:37 -03001408
Hans Verkuile1277112013-05-29 06:59:51 -03001409 if (state->ident == SAA7115) {
Hans Verkuilc875dee2013-03-10 09:59:37 -03001410 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1411
1412 v4l2_dbg(1, debug, sd, "Status byte 1 (0x1e)=0x%02x\n", reg1e);
1413
1414 switch (reg1e & 0x03) {
1415 case 1:
1416 *std &= V4L2_STD_NTSC;
1417 break;
1418 case 2:
1419 /*
1420 * V4L2_STD_PAL just cover the european PAL standards.
1421 * This is wrong, as the device could also be using an
1422 * other PAL standard.
1423 */
1424 *std &= V4L2_STD_PAL | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc |
1425 V4L2_STD_PAL_M | V4L2_STD_PAL_60;
1426 break;
1427 case 3:
1428 *std &= V4L2_STD_SECAM;
1429 break;
1430 default:
1431 /* Can't detect anything */
1432 break;
1433 }
1434 }
1435
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001436 v4l2_dbg(1, debug, sd, "Status byte 2 (0x1f)=0x%02x\n", reg1f);
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001437
1438 /* horizontal/vertical not locked */
1439 if (reg1f & 0x40)
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001440 goto ret;
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001441
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001442 if (reg1f & 0x20)
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001443 *std &= V4L2_STD_525_60;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001444 else
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001445 *std &= V4L2_STD_625_50;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001446
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001447ret:
1448 v4l2_dbg(1, debug, sd, "detected std mask = %08Lx\n", *std);
1449
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001450 return 0;
1451}
1452
1453static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status)
1454{
1455 struct saa711x_state *state = to_state(sd);
1456 int reg1e = 0x80;
1457 int reg1f;
1458
1459 *status = V4L2_IN_ST_NO_SIGNAL;
Hans Verkuile1277112013-05-29 06:59:51 -03001460 if (state->ident == SAA7115)
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001461 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1462 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1463 if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80)
1464 *status = 0;
1465 return 0;
1466}
1467
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001468#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuilaecde8b2008-12-30 07:14:19 -03001469static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001470{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001471 reg->val = saa711x_read(sd, reg->reg & 0xff);
Hans Verkuilaecde8b2008-12-30 07:14:19 -03001472 reg->size = 1;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001473 return 0;
1474}
1475
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001476static int saa711x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001477{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001478 saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff);
1479 return 0;
1480}
1481#endif
1482
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001483static int saa711x_log_status(struct v4l2_subdev *sd)
1484{
1485 struct saa711x_state *state = to_state(sd);
1486 int reg1e, reg1f;
1487 int signalOk;
1488 int vcr;
1489
1490 v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq);
Hans Verkuile1277112013-05-29 06:59:51 -03001491 if (state->ident != SAA7115) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001492 /* status for the saa7114 */
1493 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1494 signalOk = (reg1f & 0xc1) == 0x81;
1495 v4l2_info(sd, "Video signal: %s\n", signalOk ? "ok" : "bad");
1496 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1497 return 0;
1498 }
1499
1500 /* status for the saa7115 */
1501 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1502 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1503
1504 signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
1505 vcr = !(reg1f & 0x10);
1506
1507 if (state->input >= 6)
1508 v4l2_info(sd, "Input: S-Video %d\n", state->input - 6);
1509 else
1510 v4l2_info(sd, "Input: Composite %d\n", state->input);
1511 v4l2_info(sd, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
1512 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1513
1514 switch (reg1e & 0x03) {
1515 case 1:
1516 v4l2_info(sd, "Detected format: NTSC\n");
1517 break;
1518 case 2:
1519 v4l2_info(sd, "Detected format: PAL\n");
1520 break;
1521 case 3:
1522 v4l2_info(sd, "Detected format: SECAM\n");
1523 break;
1524 default:
1525 v4l2_info(sd, "Detected format: BW/No color\n");
1526 break;
1527 }
1528 v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height);
Hans Verkuile3560542010-05-24 10:00:52 -03001529 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001530 return 0;
1531}
1532
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001533/* ----------------------------------------------------------------------- */
1534
Hans Verkuile3560542010-05-24 10:00:52 -03001535static const struct v4l2_ctrl_ops saa711x_ctrl_ops = {
1536 .s_ctrl = saa711x_s_ctrl,
1537 .g_volatile_ctrl = saa711x_g_volatile_ctrl,
1538};
1539
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001540static const struct v4l2_subdev_core_ops saa711x_core_ops = {
1541 .log_status = saa711x_log_status,
Hans Verkuile3560542010-05-24 10:00:52 -03001542 .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
1543 .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
1544 .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
1545 .g_ctrl = v4l2_subdev_g_ctrl,
1546 .s_ctrl = v4l2_subdev_s_ctrl,
1547 .queryctrl = v4l2_subdev_queryctrl,
1548 .querymenu = v4l2_subdev_querymenu,
Hans Verkuilf41737e2009-04-01 03:52:39 -03001549 .s_std = saa711x_s_std,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001550 .reset = saa711x_reset,
1551 .s_gpio = saa711x_s_gpio,
1552#ifdef CONFIG_VIDEO_ADV_DEBUG
1553 .g_register = saa711x_g_register,
1554 .s_register = saa711x_s_register,
1555#endif
1556};
1557
1558static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001559 .s_radio = saa711x_s_radio,
1560 .g_tuner = saa711x_g_tuner,
1561};
1562
1563static const struct v4l2_subdev_audio_ops saa711x_audio_ops = {
1564 .s_clock_freq = saa711x_s_clock_freq,
1565};
1566
1567static const struct v4l2_subdev_video_ops saa711x_video_ops = {
1568 .s_routing = saa711x_s_routing,
1569 .s_crystal_freq = saa711x_s_crystal_freq,
Hans Verkuilc463d932010-05-09 09:47:23 -03001570 .s_mbus_fmt = saa711x_s_mbus_fmt,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001571 .s_stream = saa711x_s_stream,
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001572 .querystd = saa711x_querystd,
1573 .g_input_status = saa711x_g_input_status,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001574};
1575
Hans Verkuil32cd5272010-03-14 09:57:30 -03001576static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = {
1577 .g_vbi_data = saa711x_g_vbi_data,
1578 .decode_vbi_line = saa711x_decode_vbi_line,
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001579 .g_sliced_fmt = saa711x_g_sliced_fmt,
1580 .s_sliced_fmt = saa711x_s_sliced_fmt,
1581 .s_raw_fmt = saa711x_s_raw_fmt,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001582};
1583
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001584static const struct v4l2_subdev_ops saa711x_ops = {
1585 .core = &saa711x_core_ops,
1586 .tuner = &saa711x_tuner_ops,
1587 .audio = &saa711x_audio_ops,
1588 .video = &saa711x_video_ops,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001589 .vbi = &saa711x_vbi_ops,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001590};
1591
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001592#define CHIP_VER_SIZE 16
1593
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001594/* ----------------------------------------------------------------------- */
1595
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001596/**
1597 * saa711x_detect_chip - Detects the saa711x (or clone) variant
1598 * @client: I2C client structure.
1599 * @id: I2C device ID structure.
1600 * @name: Name of the device to be filled.
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001601 *
1602 * Detects the Philips/NXP saa711x chip, or some clone of it.
1603 * if 'id' is NULL or id->driver_data is equal to 1, it auto-probes
1604 * the analog demod.
1605 * If the tuner is not found, it returns -ENODEV.
1606 * If auto-detection is disabled and the tuner doesn't match what it was
1607 * requred, it returns -EINVAL and fills 'name'.
1608 * If the chip is found, it returns the chip ID and fills 'name'.
1609 */
1610static int saa711x_detect_chip(struct i2c_client *client,
1611 const struct i2c_device_id *id,
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001612 char *name)
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001613{
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001614 char chip_ver[CHIP_VER_SIZE];
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001615 char chip_id;
1616 int i;
1617 int autodetect;
1618
1619 autodetect = !id || id->driver_data == 1;
1620
1621 /* Read the chip version register */
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001622 for (i = 0; i < CHIP_VER_SIZE; i++) {
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001623 i2c_smbus_write_byte_data(client, 0, i);
1624 chip_ver[i] = i2c_smbus_read_byte_data(client, 0);
1625 name[i] = (chip_ver[i] & 0x0f) + '0';
1626 if (name[i] > '9')
1627 name[i] += 'a' - '9' - 1;
1628 }
1629 name[i] = '\0';
1630
1631 /* Check if it is a Philips/NXP chip */
1632 if (!memcmp(name + 1, "f711", 4)) {
1633 chip_id = name[5];
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001634 snprintf(name, CHIP_VER_SIZE, "saa711%c", chip_id);
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001635
1636 if (!autodetect && strcmp(name, id->name))
1637 return -EINVAL;
1638
1639 switch (chip_id) {
1640 case '1':
1641 if (chip_ver[0] & 0xf0) {
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001642 snprintf(name, CHIP_VER_SIZE, "saa711%ca", chip_id);
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001643 v4l_info(client, "saa7111a variant found\n");
Hans Verkuile1277112013-05-29 06:59:51 -03001644 return SAA7111A;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001645 }
Hans Verkuile1277112013-05-29 06:59:51 -03001646 return SAA7111;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001647 case '3':
Hans Verkuile1277112013-05-29 06:59:51 -03001648 return SAA7113;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001649 case '4':
Hans Verkuile1277112013-05-29 06:59:51 -03001650 return SAA7114;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001651 case '5':
Hans Verkuile1277112013-05-29 06:59:51 -03001652 return SAA7115;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001653 case '8':
Hans Verkuile1277112013-05-29 06:59:51 -03001654 return SAA7118;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001655 default:
1656 v4l2_info(client,
1657 "WARNING: Philips/NXP chip unknown - Falling back to saa7111\n");
Hans Verkuile1277112013-05-29 06:59:51 -03001658 return SAA7111;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001659 }
1660 }
1661
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001662 /* Check if it is a gm7113c */
1663 if (!memcmp(name, "0000", 4)) {
1664 chip_id = 0;
1665 for (i = 0; i < 4; i++) {
1666 chip_id = chip_id << 1;
1667 chip_id |= (chip_ver[i] & 0x80) ? 1 : 0;
1668 }
1669
1670 /*
1671 * Note: From the datasheet, only versions 1 and 2
1672 * exists. However, tests on a device labeled as:
1673 * "GM7113C 1145" returned "10" on all 16 chip
1674 * version (reg 0x00) reads. So, we need to also
1675 * accept at least verion 0. For now, let's just
1676 * assume that a device that returns "0000" for
1677 * the lower nibble is a gm7113c.
1678 */
1679
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001680 strlcpy(name, "gm7113c", CHIP_VER_SIZE);
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001681
1682 if (!autodetect && strcmp(name, id->name))
1683 return -EINVAL;
1684
1685 v4l_dbg(1, debug, client,
1686 "It seems to be a %s chip (%*ph) @ 0x%x.\n",
1687 name, 16, chip_ver, client->addr << 1);
1688
Hans Verkuile1277112013-05-29 06:59:51 -03001689 return GM7113C;
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001690 }
1691
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001692 /* Chip was not discovered. Return its ID and don't bind */
1693 v4l_dbg(1, debug, client, "chip %*ph @ 0x%x is unknown.\n",
1694 16, chip_ver, client->addr << 1);
1695 return -ENODEV;
1696}
1697
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001698static int saa711x_probe(struct i2c_client *client,
Jean Delvared2653e92008-04-29 23:11:39 +02001699 const struct i2c_device_id *id)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001700{
Mauro Carvalho Chehab66ec1192006-08-29 22:52:32 -03001701 struct saa711x_state *state;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001702 struct v4l2_subdev *sd;
Hans Verkuile3560542010-05-24 10:00:52 -03001703 struct v4l2_ctrl_handler *hdl;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001704 int ident;
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001705 char name[CHIP_VER_SIZE + 1];
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001706
1707 /* Check if the adapter supports the needed features */
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001708 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
Hans Verkuil188f3452007-09-16 10:47:15 -03001709 return -EIO;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001710
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001711 ident = saa711x_detect_chip(client, id, name);
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001712 if (ident == -EINVAL) {
1713 /* Chip exists, but doesn't match */
1714 v4l_warn(client, "found %s while %s was expected\n",
1715 name, id->name);
Hans Verkuil188f3452007-09-16 10:47:15 -03001716 return -ENODEV;
Hans Verkuilf7668162006-11-25 09:40:28 -03001717 }
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001718 if (ident < 0)
1719 return ident;
Hans Verkuilf7668162006-11-25 09:40:28 -03001720
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001721 strlcpy(client->name, name, sizeof(client->name));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001722
Laurent Pinchartc02b2112013-05-02 08:29:43 -03001723 state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
Hans Verkuilc5bf2042008-09-03 17:12:09 -03001724 if (state == NULL)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001725 return -ENOMEM;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001726 sd = &state->sd;
1727 v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
Hans Verkuile3560542010-05-24 10:00:52 -03001728
Hans Verkuile84e91e2013-05-29 06:59:37 -03001729 v4l_info(client, "%s found @ 0x%x (%s)\n", name,
1730 client->addr << 1, client->adapter->name);
Hans Verkuile3560542010-05-24 10:00:52 -03001731 hdl = &state->hdl;
1732 v4l2_ctrl_handler_init(hdl, 6);
1733 /* add in ascending ID order */
1734 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1735 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1736 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1737 V4L2_CID_CONTRAST, 0, 127, 1, 64);
1738 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1739 V4L2_CID_SATURATION, 0, 127, 1, 64);
1740 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1741 V4L2_CID_HUE, -128, 127, 1, 0);
1742 state->agc = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1743 V4L2_CID_CHROMA_AGC, 0, 1, 1, 1);
1744 state->gain = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1745 V4L2_CID_CHROMA_GAIN, 0, 127, 1, 40);
Hans Verkuile3560542010-05-24 10:00:52 -03001746 sd->ctrl_handler = hdl;
1747 if (hdl->error) {
1748 int err = hdl->error;
1749
1750 v4l2_ctrl_handler_free(hdl);
Hans Verkuile3560542010-05-24 10:00:52 -03001751 return err;
1752 }
Hans Verkuil6f43dbf2011-08-26 08:46:29 -03001753 v4l2_ctrl_auto_cluster(2, &state->agc, 0, true);
Hans Verkuile3560542010-05-24 10:00:52 -03001754
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001755 state->input = -1;
Marco Schluessler4cbca182007-01-21 19:43:38 -03001756 state->output = SAA7115_IPORT_ON;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001757 state->enable = 1;
Hans Verkuil3faeeae2006-01-09 15:25:44 -02001758 state->radio = 0;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001759 state->ident = ident;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001760
Hans Verkuil3578d3d2006-01-09 15:25:41 -02001761 state->audclk_freq = 48000;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001762
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001763 v4l2_dbg(1, debug, sd, "writing init values\n");
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001764
1765 /* init to 60hz/48khz */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001766 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
1767 switch (state->ident) {
Hans Verkuile1277112013-05-29 06:59:51 -03001768 case SAA7111:
1769 case SAA7111A:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001770 saa711x_writeregs(sd, saa7111_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001771 break;
Hans Verkuile1277112013-05-29 06:59:51 -03001772 case GM7113C:
1773 case SAA7113:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001774 saa711x_writeregs(sd, saa7113_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001775 break;
1776 default:
Hans Verkuilb7f82922006-04-02 12:50:42 -03001777 state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001778 saa711x_writeregs(sd, saa7115_init_auto_input);
Hans Verkuilb7f82922006-04-02 12:50:42 -03001779 }
Hans Verkuile1277112013-05-29 06:59:51 -03001780 if (state->ident > SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001781 saa711x_writeregs(sd, saa7115_init_misc);
1782 saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
Hans Verkuile3560542010-05-24 10:00:52 -03001783 v4l2_ctrl_handler_setup(hdl);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001784
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001785 v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n",
1786 saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC),
1787 saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001788 return 0;
1789}
1790
1791/* ----------------------------------------------------------------------- */
1792
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001793static int saa711x_remove(struct i2c_client *client)
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001794{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001795 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1796
1797 v4l2_device_unregister_subdev(sd);
Hans Verkuile3560542010-05-24 10:00:52 -03001798 v4l2_ctrl_handler_free(sd->ctrl_handler);
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001799 return 0;
1800}
1801
Hans Verkuilaac23532010-09-15 15:04:55 -03001802static const struct i2c_device_id saa711x_id[] = {
Hans Verkuil9edd350f2008-07-17 13:22:51 -03001803 { "saa7115_auto", 1 }, /* autodetect */
Jean Delvareaf294862008-05-18 20:49:40 +02001804 { "saa7111", 0 },
1805 { "saa7113", 0 },
1806 { "saa7114", 0 },
1807 { "saa7115", 0 },
1808 { "saa7118", 0 },
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001809 { "gm7113c", 0 },
Jean Delvareaf294862008-05-18 20:49:40 +02001810 { }
1811};
Hans Verkuilaac23532010-09-15 15:04:55 -03001812MODULE_DEVICE_TABLE(i2c, saa711x_id);
Jean Delvareaf294862008-05-18 20:49:40 +02001813
Hans Verkuilaac23532010-09-15 15:04:55 -03001814static struct i2c_driver saa711x_driver = {
1815 .driver = {
1816 .owner = THIS_MODULE,
1817 .name = "saa7115",
1818 },
1819 .probe = saa711x_probe,
1820 .remove = saa711x_remove,
1821 .id_table = saa711x_id,
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001822};
Hans Verkuilaac23532010-09-15 15:04:55 -03001823
Axel Linc6e8d862012-02-12 06:56:32 -03001824module_i2c_driver(saa711x_driver);