blob: 7dd6cff6d811b7240008616ddee026111c511646 [file] [log] [blame]
Mauro Carvalho Chehab459ee172017-12-01 08:47:12 -05001// SPDX-License-Identifier: GPL-2.0+
2// saa711x - Philips SAA711x video decoder driver
3// This driver can work with saa7111, saa7111a, saa7113, saa7114,
4// saa7115 and saa7118.
5//
6// Based on saa7114 driver by Maxim Yevtyushkin, which is based on
7// the saa7111 driver by Dave Perks.
8//
9// Copyright (C) 1998 Dave Perks <dperks@ibm.net>
10// Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
11//
12// Slight changes for video timing and attachment output by
13// Wolfgang Scherr <scherr@net4you.net>
14//
15// Moved over to the linux >= 2.4.x i2c protocol (1/1/2003)
16// by Ronald Bultje <rbultje@ronald.bitfreak.net>
17//
18// Added saa7115 support by Kevin Thayer <nufan_wfk at yahoo.com>
19// (2/17/2003)
20//
21// VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@xs4all.nl>
22//
23// Copyright (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
24// SAA7111, SAA7113 and SAA7118 support
Hans Verkuile19b2fc2005-11-13 16:08:04 -080025
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -030026#include "saa711x_regs.h"
Hans Verkuile19b2fc2005-11-13 16:08:04 -080027
28#include <linux/kernel.h>
29#include <linux/module.h>
30#include <linux/slab.h>
31#include <linux/i2c.h>
32#include <linux/videodev2.h>
Hans Verkuil9415f4b2008-11-29 12:55:19 -030033#include <media/v4l2-device.h>
Hans Verkuile3560542010-05-24 10:00:52 -030034#include <media/v4l2-ctrls.h>
Mauro Carvalho Chehabaf7d3742016-01-29 08:44:28 -020035#include <media/v4l2-mc.h>
Mauro Carvalho Chehabb5dcee22015-11-10 12:01:44 -020036#include <media/i2c/saa7115.h>
Hans Verkuil3578d3d2006-01-09 15:25:41 -020037#include <asm/div64.h>
Hans Verkuile19b2fc2005-11-13 16:08:04 -080038
Mauro Carvalho Chehab97d9e802006-09-03 09:38:11 -030039#define VRES_60HZ (480+16)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -030040
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -030041MODULE_DESCRIPTION("Philips SAA7111/SAA7113/SAA7114/SAA7115/SAA7118 video decoder driver");
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -030042MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
43 "Hans Verkuil, Mauro Carvalho Chehab");
Hans Verkuile19b2fc2005-11-13 16:08:04 -080044MODULE_LICENSE("GPL");
45
Rusty Russell90ab5ee2012-01-13 09:32:20 +103046static bool debug;
Hans Verkuilfac9e892006-01-09 15:32:40 -020047module_param(debug, bool, 0644);
Hans Verkuile19b2fc2005-11-13 16:08:04 -080048
49MODULE_PARM_DESC(debug, "Debug level (0-1)");
50
Hans Verkuile19b2fc2005-11-13 16:08:04 -080051
Hans Verkuile1277112013-05-29 06:59:51 -030052enum saa711x_model {
53 SAA7111A,
54 SAA7111,
55 SAA7113,
56 GM7113C,
57 SAA7114,
58 SAA7115,
59 SAA7118,
60};
61
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -030062struct saa711x_state {
Hans Verkuil9415f4b2008-11-29 12:55:19 -030063 struct v4l2_subdev sd;
Mauro Carvalho Chehabaf7d3742016-01-29 08:44:28 -020064#ifdef CONFIG_MEDIA_CONTROLLER
65 struct media_pad pads[DEMOD_NUM_PADS];
66#endif
Hans Verkuile3560542010-05-24 10:00:52 -030067 struct v4l2_ctrl_handler hdl;
68
69 struct {
70 /* chroma gain control cluster */
71 struct v4l2_ctrl *agc;
72 struct v4l2_ctrl *gain;
73 };
74
Hans Verkuile19b2fc2005-11-13 16:08:04 -080075 v4l2_std_id std;
76 int input;
Marco Schluessler4cbca182007-01-21 19:43:38 -030077 int output;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080078 int enable;
Hans Verkuil3faeeae2006-01-09 15:25:44 -020079 int radio;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -030080 int width;
81 int height;
Hans Verkuile1277112013-05-29 06:59:51 -030082 enum saa711x_model ident;
Hans Verkuil3578d3d2006-01-09 15:25:41 -020083 u32 audclk_freq;
Hans Verkuilb7f82922006-04-02 12:50:42 -030084 u32 crystal_freq;
Hans Verkuil15890372013-03-11 03:47:25 -030085 bool ucgc;
Hans Verkuilb7f82922006-04-02 12:50:42 -030086 u8 cgcdiv;
Hans Verkuil15890372013-03-11 03:47:25 -030087 bool apll;
88 bool double_asclk;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080089};
90
Hans Verkuil9415f4b2008-11-29 12:55:19 -030091static inline struct saa711x_state *to_state(struct v4l2_subdev *sd)
92{
93 return container_of(sd, struct saa711x_state, sd);
94}
95
Hans Verkuile3560542010-05-24 10:00:52 -030096static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
97{
98 return &container_of(ctrl->handler, struct saa711x_state, hdl)->sd;
99}
100
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800101/* ----------------------------------------------------------------------- */
102
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300103static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800104{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300105 struct i2c_client *client = v4l2_get_subdevdata(sd);
106
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800107 return i2c_smbus_write_byte_data(client, reg, value);
108}
109
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300110/* Sanity routine to check if a register is present */
111static int saa711x_has_reg(const int id, const u8 reg)
112{
Hans Verkuile1277112013-05-29 06:59:51 -0300113 if (id == SAA7111)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300114 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
115 (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e;
Hans Verkuile1277112013-05-29 06:59:51 -0300116 if (id == SAA7111A)
Hans Verkuil340dde82010-02-20 08:07:51 -0300117 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
118 reg != 0x14 && reg != 0x18 && reg != 0x19 &&
119 reg != 0x1d && reg != 0x1e;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300120
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300121 /* common for saa7113/4/5/8 */
122 if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f ||
123 reg == 0xa3 || reg == 0xa7 || reg == 0xab || reg == 0xaf || (reg >= 0xb5 && reg <= 0xb7) ||
124 reg == 0xd3 || reg == 0xd7 || reg == 0xdb || reg == 0xdf || (reg >= 0xe5 && reg <= 0xe7) ||
125 reg == 0x82 || (reg >= 0x89 && reg <= 0x8e)))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300126 return 0;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300127
128 switch (id) {
Hans Verkuile1277112013-05-29 06:59:51 -0300129 case GM7113C:
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300130 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && reg < 0x20;
Hans Verkuile1277112013-05-29 06:59:51 -0300131 case SAA7113:
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300132 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
133 reg != 0x5d && reg < 0x63;
Hans Verkuile1277112013-05-29 06:59:51 -0300134 case SAA7114:
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300135 return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
136 (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
137 reg != 0x81 && reg < 0xf0;
Hans Verkuile1277112013-05-29 06:59:51 -0300138 case SAA7115:
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300139 return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe);
Hans Verkuile1277112013-05-29 06:59:51 -0300140 case SAA7118:
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300141 return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
142 (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
143 (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
144 }
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300145 return 1;
146}
147
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300148static int saa711x_writeregs(struct v4l2_subdev *sd, const unsigned char *regs)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800149{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300150 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800151 unsigned char reg, data;
152
153 while (*regs != 0x00) {
154 reg = *(regs++);
155 data = *(regs++);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300156
157 /* According with datasheets, reserved regs should be
158 filled with 0 - seems better not to touch on they */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300159 if (saa711x_has_reg(state->ident, reg)) {
160 if (saa711x_write(sd, reg, data) < 0)
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300161 return -1;
Mauro Carvalho Chehabd87edf22006-09-01 09:37:11 -0300162 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300163 v4l2_dbg(1, debug, sd, "tried to access reserved reg 0x%02x\n", reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300164 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800165 }
166 return 0;
167}
168
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300169static inline int saa711x_read(struct v4l2_subdev *sd, u8 reg)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800170{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300171 struct i2c_client *client = v4l2_get_subdevdata(sd);
172
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800173 return i2c_smbus_read_byte_data(client, reg);
174}
175
176/* ----------------------------------------------------------------------- */
177
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300178/* SAA7111 initialization table */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300179static const unsigned char saa7111_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300180 R_01_INC_DELAY, 0x00, /* reserved */
181
182 /*front end */
183 R_02_INPUT_CNTL_1, 0xd0, /* FUSE=3, GUDL=2, MODE=0 */
184 R_03_INPUT_CNTL_2, 0x23, /* HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0,
185 * GAFIX=0, GAI1=256, GAI2=256 */
186 R_04_INPUT_CNTL_3, 0x00, /* GAI1=256 */
187 R_05_INPUT_CNTL_4, 0x00, /* GAI2=256 */
188
189 /* decoder */
190 R_06_H_SYNC_START, 0xf3, /* HSB at 13(50Hz) / 17(60Hz)
191 * pixels after end of last line */
192 R_07_H_SYNC_STOP, 0xe8, /* HSS seems to be needed to
193 * work with NTSC, too */
194 R_08_SYNC_CNTL, 0xc8, /* AUFD=1, FSEL=1, EXFIL=0,
195 * VTRC=1, HPLL=0, VNOI=0 */
196 R_09_LUMA_CNTL, 0x01, /* BYPS=0, PREF=0, BPSS=0,
197 * VBLB=0, UPTCV=0, APER=1 */
198 R_0A_LUMA_BRIGHT_CNTL, 0x80,
199 R_0B_LUMA_CONTRAST_CNTL, 0x47, /* 0b - CONT=1.109 */
200 R_0C_CHROMA_SAT_CNTL, 0x40,
201 R_0D_CHROMA_HUE_CNTL, 0x00,
202 R_0E_CHROMA_CNTL_1, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0,
203 * FCTC=0, CHBW=1 */
204 R_0F_CHROMA_GAIN_CNTL, 0x00, /* reserved */
205 R_10_CHROMA_CNTL_2, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
206 R_11_MODE_DELAY_CNTL, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
207 * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
208 R_12_RT_SIGNAL_CNTL, 0x00, /* 12 - output control 2 */
209 R_13_RT_X_PORT_OUT_CNTL, 0x00, /* 13 - output control 3 */
210 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
211 R_15_VGATE_START_FID_CHG, 0x00,
212 R_16_VGATE_STOP, 0x00,
213 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
214
215 0x00, 0x00
216};
217
Mauro Carvalho Chehab04074f12013-08-18 08:35:36 -0300218/*
219 * This table has one illegal value, and some values that are not
220 * correct according to the datasheet initialization table.
221 *
222 * If you need a table with legal/default values tell the driver in
223 * i2c_board_info.platform_data, and you will get the gm7113c_init
224 * table instead.
225 */
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300226
227/* SAA7113 Init codes */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300228static const unsigned char saa7113_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300229 R_01_INC_DELAY, 0x08,
230 R_02_INPUT_CNTL_1, 0xc2,
231 R_03_INPUT_CNTL_2, 0x30,
232 R_04_INPUT_CNTL_3, 0x00,
233 R_05_INPUT_CNTL_4, 0x00,
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300234 R_06_H_SYNC_START, 0x89, /* Illegal value -119,
235 * min. value = -108 (0x94) */
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300236 R_07_H_SYNC_STOP, 0x0d,
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300237 R_08_SYNC_CNTL, 0x88, /* Not datasheet default.
238 * HTC = VTR mode, should be 0x98 */
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300239 R_09_LUMA_CNTL, 0x01,
240 R_0A_LUMA_BRIGHT_CNTL, 0x80,
241 R_0B_LUMA_CONTRAST_CNTL, 0x47,
242 R_0C_CHROMA_SAT_CNTL, 0x40,
243 R_0D_CHROMA_HUE_CNTL, 0x00,
244 R_0E_CHROMA_CNTL_1, 0x01,
245 R_0F_CHROMA_GAIN_CNTL, 0x2a,
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300246 R_10_CHROMA_CNTL_2, 0x08, /* Not datsheet default.
247 * VRLN enabled, should be 0x00 */
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300248 R_11_MODE_DELAY_CNTL, 0x0c,
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300249 R_12_RT_SIGNAL_CNTL, 0x07, /* Not datasheet default,
250 * should be 0x01 */
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
Mauro Carvalho Chehab04074f12013-08-18 08:35:36 -0300260/*
261 * GM7113C is a clone of the SAA7113 chip
262 * This init table is copied out of the saa7113 datasheet.
263 * In R_08 we enable "Automatic Field Detection" [AUFD],
264 * this is disabled when saa711x_set_v4lstd is called.
265 */
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300266static const unsigned char gm7113c_init[] = {
267 R_01_INC_DELAY, 0x08,
268 R_02_INPUT_CNTL_1, 0xc0,
269 R_03_INPUT_CNTL_2, 0x33,
270 R_04_INPUT_CNTL_3, 0x00,
271 R_05_INPUT_CNTL_4, 0x00,
272 R_06_H_SYNC_START, 0xe9,
273 R_07_H_SYNC_STOP, 0x0d,
274 R_08_SYNC_CNTL, 0x98,
275 R_09_LUMA_CNTL, 0x01,
276 R_0A_LUMA_BRIGHT_CNTL, 0x80,
277 R_0B_LUMA_CONTRAST_CNTL, 0x47,
278 R_0C_CHROMA_SAT_CNTL, 0x40,
279 R_0D_CHROMA_HUE_CNTL, 0x00,
280 R_0E_CHROMA_CNTL_1, 0x01,
281 R_0F_CHROMA_GAIN_CNTL, 0x2a,
282 R_10_CHROMA_CNTL_2, 0x00,
283 R_11_MODE_DELAY_CNTL, 0x0c,
284 R_12_RT_SIGNAL_CNTL, 0x01,
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300285 R_13_RT_X_PORT_OUT_CNTL, 0x00,
286 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
287 R_15_VGATE_START_FID_CHG, 0x00,
288 R_16_VGATE_STOP, 0x00,
289 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
290
291 0x00, 0x00
292};
293
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800294/* If a value differs from the Hauppauge driver values, then the comment starts with
295 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
296 Hauppauge driver sets. */
297
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300298/* SAA7114 and SAA7115 initialization table */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800299static const unsigned char saa7115_init_auto_input[] = {
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300300 /* Front-End Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300301 R_01_INC_DELAY, 0x48, /* white peak control disabled */
302 R_03_INPUT_CNTL_2, 0x20, /* was 0x30. 0x20: long vertical blanking */
303 R_04_INPUT_CNTL_3, 0x90, /* analog gain set to 0 */
304 R_05_INPUT_CNTL_4, 0x90, /* analog gain set to 0 */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300305 /* Decoder Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300306 R_06_H_SYNC_START, 0xeb, /* horiz sync begin = -21 */
307 R_07_H_SYNC_STOP, 0xe0, /* horiz sync stop = -17 */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300308 R_09_LUMA_CNTL, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300309 R_0A_LUMA_BRIGHT_CNTL, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */
310 R_0B_LUMA_CONTRAST_CNTL, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */
311 R_0C_CHROMA_SAT_CNTL, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */
312 R_0D_CHROMA_HUE_CNTL, 0x00,
313 R_0F_CHROMA_GAIN_CNTL, 0x00, /* use automatic gain */
314 R_10_CHROMA_CNTL_2, 0x06, /* chroma: active adaptive combfilter */
315 R_11_MODE_DELAY_CNTL, 0x00,
316 R_12_RT_SIGNAL_CNTL, 0x9d, /* RTS0 output control: VGATE */
317 R_13_RT_X_PORT_OUT_CNTL, 0x80, /* ITU656 standard mode, RTCO output enable RTCE */
318 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
319 R_18_RAW_DATA_GAIN_CNTL, 0x40, /* gain 0x00 = nominal */
320 R_19_RAW_DATA_OFF_CNTL, 0x80,
321 R_1A_COLOR_KILL_LVL_CNTL, 0x77, /* recommended value */
322 R_1B_MISC_TVVCRDET, 0x42, /* recommended value */
323 R_1C_ENHAN_COMB_CTRL1, 0xa9, /* recommended value */
324 R_1D_ENHAN_COMB_CTRL2, 0x01, /* recommended value */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300325
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300326
327 R_80_GLOBAL_CNTL_1, 0x0, /* No tasks enabled at init */
328
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300329 /* Power Device Control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300330 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset device */
331 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* set device programmed, all in operational mode */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800332 0x00, 0x00
333};
334
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300335/* Used to reset saa7113, saa7114 and saa7115 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800336static const unsigned char saa7115_cfg_reset_scaler[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300337 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00, /* disable I-port output */
338 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
339 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
340 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* enable I-port output */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800341 0x00, 0x00
342};
343
344/* ============== SAA7715 VIDEO templates ============= */
345
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800346static const unsigned char saa7115_cfg_60hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300347 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
348 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800349
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300350 R_15_VGATE_START_FID_CHG, 0x03,
351 R_16_VGATE_STOP, 0x11,
352 R_17_MISC_VGATE_CONF_AND_MSB, 0x9c,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800353
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300354 R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
355 R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800356
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300357 R_5A_V_OFF_FOR_SLICER, 0x06, /* standard 60hz value for ITU656 line counting */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800358
359 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300360 R_90_A_TASK_HANDLING_CNTL, 0x80,
361 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
362 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
363 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
364
365 /* hoffset low (input), 0x0002 is minimum */
366 R_94_A_HORIZ_INPUT_WINDOW_START, 0x01,
367 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
368
369 /* hsize low (input), 0x02d0 = 720 */
370 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
371 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
372
373 R_98_A_VERT_INPUT_WINDOW_START, 0x05,
374 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
375
376 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x0c,
377 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
378
379 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
380 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
381
382 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x0c,
383 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800384
385 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300386 R_C0_B_TASK_HANDLING_CNTL, 0x00,
387 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
388 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
389 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800390
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300391 /* 0x0002 is minimum */
392 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x02,
393 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800394
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300395 /* 0x02d0 = 720 */
396 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
397 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
398
399 /* vwindow start 0x12 = 18 */
400 R_C8_B_VERT_INPUT_WINDOW_START, 0x12,
401 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
402
403 /* vwindow length 0xf8 = 248 */
Mauro Carvalho Chehab97d9e802006-09-03 09:38:11 -0300404 R_CA_B_VERT_INPUT_WINDOW_LENGTH, VRES_60HZ>>1,
405 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, VRES_60HZ>>9,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300406
407 /* hwindow 0x02d0 = 720 */
408 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
409 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
410
411 R_F0_LFCO_PER_LINE, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
412 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0 */
413 R_F5_PULSGEN_LINE_LENGTH, 0xad,
414 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
415
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800416 0x00, 0x00
417};
418
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800419static const unsigned char saa7115_cfg_50hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300420 R_80_GLOBAL_CNTL_1, 0x00,
421 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800422
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300423 R_15_VGATE_START_FID_CHG, 0x37, /* VGATE start */
424 R_16_VGATE_STOP, 0x16,
425 R_17_MISC_VGATE_CONF_AND_MSB, 0x99,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800426
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300427 R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */
428 R_0E_CHROMA_CNTL_1, 0x07,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800429
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300430 R_5A_V_OFF_FOR_SLICER, 0x03, /* standard 50hz value */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800431
432 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300433 R_90_A_TASK_HANDLING_CNTL, 0x81,
434 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
435 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
436 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
437
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800438 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
439 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300440 /* hoffset low (input), 0x0002 is minimum */
441 R_94_A_HORIZ_INPUT_WINDOW_START, 0x00,
442 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
443
444 /* hsize low (input), 0x02d0 = 720 */
445 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
446 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
447
448 R_98_A_VERT_INPUT_WINDOW_START, 0x03,
449 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
450
451 /* vsize 0x12 = 18 */
452 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x12,
453 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
454
455 /* hsize 0x05a0 = 1440 */
456 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
457 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05, /* hsize hi (output) */
458 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x12, /* vsize low (output), 0x12 = 18 */
459 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00, /* vsize hi (output) */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800460
461 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300462 R_C0_B_TASK_HANDLING_CNTL, 0x00,
463 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
464 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
465 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800466
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300467 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
468 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
469 /* hoffset low (input), 0x0002 is minimum. See comment above. */
470 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x00,
471 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800472
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300473 /* hsize 0x02d0 = 720 */
474 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
475 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
476
477 /* voffset 0x16 = 22 */
478 R_C8_B_VERT_INPUT_WINDOW_START, 0x16,
479 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
480
481 /* vsize 0x0120 = 288 */
482 R_CA_B_VERT_INPUT_WINDOW_LENGTH, 0x20,
483 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, 0x01,
484
485 /* hsize 0x02d0 = 720 */
486 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
487 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
488
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300489 R_F0_LFCO_PER_LINE, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
490 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0, (was 0x05) */
491 R_F5_PULSGEN_LINE_LENGTH, 0xb0,
492 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
493
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800494 0x00, 0x00
495};
496
497/* ============== SAA7715 VIDEO templates (end) ======= */
498
499static const unsigned char saa7115_cfg_vbi_on[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300500 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
501 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
502 R_80_GLOBAL_CNTL_1, 0x30, /* Activate both tasks */
503 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
504 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
505
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800506 0x00, 0x00
507};
508
509static const unsigned char saa7115_cfg_vbi_off[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300510 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
511 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
512 R_80_GLOBAL_CNTL_1, 0x20, /* Activate only task "B" */
513 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
514 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
515
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800516 0x00, 0x00
517};
518
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300519
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800520static const unsigned char saa7115_init_misc[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300521 R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300522 R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 0x01,
523 R_84_I_PORT_SIGNAL_DEF, 0x20,
524 R_85_I_PORT_SIGNAL_POLAR, 0x21,
525 R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT, 0xc5,
526 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800527
528 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300529 R_A0_A_HORIZ_PRESCALING, 0x01,
530 R_A1_A_ACCUMULATION_LENGTH, 0x00,
531 R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800532
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300533 /* Configure controls at nominal value*/
534 R_A4_A_LUMA_BRIGHTNESS_CNTL, 0x80,
535 R_A5_A_LUMA_CONTRAST_CNTL, 0x40,
536 R_A6_A_CHROMA_SATURATION_CNTL, 0x40,
537
538 /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
539 R_A8_A_HORIZ_LUMA_SCALING_INC, 0x00,
540 R_A9_A_HORIZ_LUMA_SCALING_INC_MSB, 0x02,
541
542 R_AA_A_HORIZ_LUMA_PHASE_OFF, 0x00,
543
544 /* must be horiz lum scaling / 2 */
545 R_AC_A_HORIZ_CHROMA_SCALING_INC, 0x00,
546 R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB, 0x01,
547
548 /* must be offset luma / 2 */
549 R_AE_A_HORIZ_CHROMA_PHASE_OFF, 0x00,
550
551 R_B0_A_VERT_LUMA_SCALING_INC, 0x00,
552 R_B1_A_VERT_LUMA_SCALING_INC_MSB, 0x04,
553
554 R_B2_A_VERT_CHROMA_SCALING_INC, 0x00,
555 R_B3_A_VERT_CHROMA_SCALING_INC_MSB, 0x04,
556
557 R_B4_A_VERT_SCALING_MODE_CNTL, 0x01,
558
559 R_B8_A_VERT_CHROMA_PHASE_OFF_00, 0x00,
560 R_B9_A_VERT_CHROMA_PHASE_OFF_01, 0x00,
561 R_BA_A_VERT_CHROMA_PHASE_OFF_10, 0x00,
562 R_BB_A_VERT_CHROMA_PHASE_OFF_11, 0x00,
563
564 R_BC_A_VERT_LUMA_PHASE_OFF_00, 0x00,
565 R_BD_A_VERT_LUMA_PHASE_OFF_01, 0x00,
566 R_BE_A_VERT_LUMA_PHASE_OFF_10, 0x00,
567 R_BF_A_VERT_LUMA_PHASE_OFF_11, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800568
569 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300570 R_D0_B_HORIZ_PRESCALING, 0x01,
571 R_D1_B_ACCUMULATION_LENGTH, 0x00,
572 R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800573
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300574 /* Configure controls at nominal value*/
575 R_D4_B_LUMA_BRIGHTNESS_CNTL, 0x80,
576 R_D5_B_LUMA_CONTRAST_CNTL, 0x40,
577 R_D6_B_CHROMA_SATURATION_CNTL, 0x40,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800578
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300579 /* hor lum scaling 0x0400 = 1 */
580 R_D8_B_HORIZ_LUMA_SCALING_INC, 0x00,
581 R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, 0x04,
582
583 R_DA_B_HORIZ_LUMA_PHASE_OFF, 0x00,
584
585 /* must be hor lum scaling / 2 */
586 R_DC_B_HORIZ_CHROMA_SCALING, 0x00,
587 R_DD_B_HORIZ_CHROMA_SCALING_MSB, 0x02,
588
589 /* must be offset luma / 2 */
590 R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA, 0x00,
591
592 R_E0_B_VERT_LUMA_SCALING_INC, 0x00,
593 R_E1_B_VERT_LUMA_SCALING_INC_MSB, 0x04,
594
595 R_E2_B_VERT_CHROMA_SCALING_INC, 0x00,
596 R_E3_B_VERT_CHROMA_SCALING_INC_MSB, 0x04,
597
598 R_E4_B_VERT_SCALING_MODE_CNTL, 0x01,
599
600 R_E8_B_VERT_CHROMA_PHASE_OFF_00, 0x00,
601 R_E9_B_VERT_CHROMA_PHASE_OFF_01, 0x00,
602 R_EA_B_VERT_CHROMA_PHASE_OFF_10, 0x00,
603 R_EB_B_VERT_CHROMA_PHASE_OFF_11, 0x00,
604
605 R_EC_B_VERT_LUMA_PHASE_OFF_00, 0x00,
606 R_ED_B_VERT_LUMA_PHASE_OFF_01, 0x00,
607 R_EE_B_VERT_LUMA_PHASE_OFF_10, 0x00,
608 R_EF_B_VERT_LUMA_PHASE_OFF_11, 0x00,
609
610 R_F2_NOMINAL_PLL2_DTO, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */
611 R_F3_PLL_INCREMENT, 0x46,
612 R_F4_PLL2_STATUS, 0x00,
613 R_F7_PULSE_A_POS_MSB, 0x4b, /* not the recommended settings! */
614 R_F8_PULSE_B_POS, 0x00,
615 R_F9_PULSE_B_POS_MSB, 0x4b,
616 R_FA_PULSE_C_POS, 0x00,
617 R_FB_PULSE_C_POS_MSB, 0x4b,
618
619 /* PLL2 lock detection settings: 71 lines 50% phase error */
620 R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES, 0x88,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800621
622 /* Turn off VBI */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300623 R_40_SLICER_CNTL_1, 0x20, /* No framing code errors allowed. */
624 R_41_LCR_BASE, 0xff,
625 R_41_LCR_BASE+1, 0xff,
626 R_41_LCR_BASE+2, 0xff,
627 R_41_LCR_BASE+3, 0xff,
628 R_41_LCR_BASE+4, 0xff,
629 R_41_LCR_BASE+5, 0xff,
630 R_41_LCR_BASE+6, 0xff,
631 R_41_LCR_BASE+7, 0xff,
632 R_41_LCR_BASE+8, 0xff,
633 R_41_LCR_BASE+9, 0xff,
634 R_41_LCR_BASE+10, 0xff,
635 R_41_LCR_BASE+11, 0xff,
636 R_41_LCR_BASE+12, 0xff,
637 R_41_LCR_BASE+13, 0xff,
638 R_41_LCR_BASE+14, 0xff,
639 R_41_LCR_BASE+15, 0xff,
640 R_41_LCR_BASE+16, 0xff,
641 R_41_LCR_BASE+17, 0xff,
642 R_41_LCR_BASE+18, 0xff,
643 R_41_LCR_BASE+19, 0xff,
644 R_41_LCR_BASE+20, 0xff,
645 R_41_LCR_BASE+21, 0xff,
646 R_41_LCR_BASE+22, 0xff,
647 R_58_PROGRAM_FRAMING_CODE, 0x40,
648 R_59_H_OFF_FOR_SLICER, 0x47,
649 R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF, 0x83,
650 R_5D_DID, 0xbd,
651 R_5E_SDID, 0x35,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800652
Devin Heitmuellerfea551f2010-02-03 00:33:48 -0300653 R_02_INPUT_CNTL_1, 0xc4, /* input tuner -> input 4, amplifier active */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800654
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300655 R_80_GLOBAL_CNTL_1, 0x20, /* enable task B */
656 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
657 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800658 0x00, 0x00
659};
660
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -0300661static int saa711x_odd_parity(u8 c)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800662{
663 c ^= (c >> 4);
664 c ^= (c >> 2);
665 c ^= (c >> 1);
666
667 return c & 1;
668}
669
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300670static int saa711x_decode_vps(u8 *dst, u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800671{
672 static const u8 biphase_tbl[] = {
673 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
674 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
675 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
676 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
677 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
678 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
679 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
680 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
681 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
682 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
683 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
684 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
685 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
686 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
687 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
688 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
689 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
690 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
691 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
692 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
693 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
694 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
695 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
696 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
697 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
698 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
699 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
700 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
701 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
702 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
703 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
704 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
705 };
706 int i;
707 u8 c, err = 0;
708
709 for (i = 0; i < 2 * 13; i += 2) {
710 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
711 c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
712 dst[i / 2] = c;
713 }
714 return err & 0xf0;
715}
716
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300717static int saa711x_decode_wss(u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800718{
719 static const int wss_bits[8] = {
720 0, 0, 0, 1, 0, 1, 1, 1
721 };
722 unsigned char parity;
723 int wss = 0;
724 int i;
725
726 for (i = 0; i < 16; i++) {
727 int b1 = wss_bits[p[i] & 7];
728 int b2 = wss_bits[(p[i] >> 3) & 7];
729
730 if (b1 == b2)
731 return -1;
732 wss |= b2 << i;
733 }
734 parity = wss & 15;
735 parity ^= parity >> 2;
736 parity ^= parity >> 1;
737
738 if (!(parity & 1))
739 return -1;
740
741 return wss;
742}
743
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300744static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800745{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300746 struct saa711x_state *state = to_state(sd);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200747 u32 acpf;
748 u32 acni;
749 u32 hz;
750 u64 f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300751 u8 acc = 0; /* reg 0x3a, audio clock control */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800752
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300753 /* Checks for chips that don't have audio clock (saa7111, saa7113) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300754 if (!saa711x_has_reg(state->ident, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300755 return 0;
756
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300757 v4l2_dbg(1, debug, sd, "set audio clock freq: %d\n", freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200758
759 /* sanity check */
760 if (freq < 32000 || freq > 48000)
761 return -EINVAL;
762
763 /* hz is the refresh rate times 100 */
764 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
765 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
766 acpf = (25600 * freq) / hz;
767 /* acni = (256 * freq * 2^23) / crystal_frequency =
768 (freq * 2^(8+23)) / crystal_frequency =
Hans Verkuilb7f82922006-04-02 12:50:42 -0300769 (freq << 31) / crystal_frequency */
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200770 f = freq;
771 f = f << 31;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300772 do_div(f, state->crystal_freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200773 acni = f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300774 if (state->ucgc) {
775 acpf = acpf * state->cgcdiv / 16;
776 acni = acni * state->cgcdiv / 16;
777 acc = 0x80;
778 if (state->cgcdiv == 3)
779 acc |= 0x40;
780 }
781 if (state->apll)
782 acc |= 0x08;
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200783
Hans Verkuil15890372013-03-11 03:47:25 -0300784 if (state->double_asclk) {
785 acpf <<= 1;
786 acni <<= 1;
787 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300788 saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
Hans Verkuil15890372013-03-11 03:47:25 -0300789 saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10 << state->double_asclk);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300790 saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300791
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300792 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
793 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300794 (acpf >> 8) & 0xff);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300795 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300796 (acpf >> 16) & 0x03);
797
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300798 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
799 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
800 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800801 state->audclk_freq = freq;
802 return 0;
803}
804
Hans Verkuile3560542010-05-24 10:00:52 -0300805static int saa711x_g_volatile_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) {
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300811 case V4L2_CID_CHROMA_AGC:
Hans Verkuile3560542010-05-24 10:00:52 -0300812 /* chroma gain cluster */
Hans Verkuilddac5c12011-06-10 05:43:34 -0300813 if (state->agc->val)
814 state->gain->val =
Hans Verkuile3560542010-05-24 10:00:52 -0300815 saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL) & 0x7f;
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300816 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800817 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800818 return 0;
819}
820
Hans Verkuile3560542010-05-24 10:00:52 -0300821static int saa711x_s_ctrl(struct v4l2_ctrl *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800822{
Hans Verkuile3560542010-05-24 10:00:52 -0300823 struct v4l2_subdev *sd = to_sd(ctrl);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300824 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800825
826 switch (ctrl->id) {
827 case V4L2_CID_BRIGHTNESS:
Hans Verkuile3560542010-05-24 10:00:52 -0300828 saa711x_write(sd, R_0A_LUMA_BRIGHT_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800829 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300830
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800831 case V4L2_CID_CONTRAST:
Hans Verkuile3560542010-05-24 10:00:52 -0300832 saa711x_write(sd, R_0B_LUMA_CONTRAST_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800833 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300834
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800835 case V4L2_CID_SATURATION:
Hans Verkuile3560542010-05-24 10:00:52 -0300836 saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800837 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300838
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800839 case V4L2_CID_HUE:
Hans Verkuile3560542010-05-24 10:00:52 -0300840 saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800841 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300842
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300843 case V4L2_CID_CHROMA_AGC:
Hans Verkuile3560542010-05-24 10:00:52 -0300844 /* chroma gain cluster */
845 if (state->agc->val)
846 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val);
847 else
848 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val | 0x80);
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300849 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300850
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800851 default:
852 return -EINVAL;
853 }
854
855 return 0;
856}
857
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300858static int saa711x_set_size(struct v4l2_subdev *sd, int width, int height)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300859{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300860 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300861 int HPSC, HFSC;
862 int VSCY;
863 int res;
864 int is_50hz = state->std & V4L2_STD_625_50;
865 int Vsrc = is_50hz ? 576 : 480;
866
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300867 v4l2_dbg(1, debug, sd, "decoder set size to %ix%i\n", width, height);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300868
869 /* FIXME need better bounds checking here */
870 if ((width < 1) || (width > 1440))
871 return -EINVAL;
872 if ((height < 1) || (height > Vsrc))
873 return -EINVAL;
874
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300875 if (!saa711x_has_reg(state->ident, R_D0_B_HORIZ_PRESCALING)) {
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300876 /* Decoder only supports 720 columns and 480 or 576 lines */
877 if (width != 720)
878 return -EINVAL;
879 if (height != Vsrc)
880 return -EINVAL;
881 }
882
883 state->width = width;
884 state->height = height;
885
886 if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
887 return 0;
888
889 /* probably have a valid size, let's set it */
890 /* Set output width/height */
891 /* width */
892
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300893 saa711x_write(sd, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300894 (u8) (width & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300895 saa711x_write(sd, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300896 (u8) ((width >> 8) & 0xff));
897
898 /* Vertical Scaling uses height/2 */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300899 res = height / 2;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300900
901 /* On 60Hz, it is using a higher Vertical Output Size */
902 if (!is_50hz)
Hans Verkuild0d30c02006-11-25 09:45:50 -0300903 res += (VRES_60HZ - 480) >> 1;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300904
905 /* height */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300906 saa711x_write(sd, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300907 (u8) (res & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300908 saa711x_write(sd, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300909 (u8) ((res >> 8) & 0xff));
910
911 /* Scaling settings */
912 /* Hprescaler is floor(inres/outres) */
913 HPSC = (int)(720 / width);
914 /* 0 is not allowed (div. by zero) */
915 HPSC = HPSC ? HPSC : 1;
916 HFSC = (int)((1024 * 720) / (HPSC * width));
917 /* FIXME hardcodes to "Task B"
918 * write H prescaler integer */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300919 saa711x_write(sd, R_D0_B_HORIZ_PRESCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300920 (u8) (HPSC & 0x3f));
921
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300922 v4l2_dbg(1, debug, sd, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300923 /* write H fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300924 saa711x_write(sd, R_D8_B_HORIZ_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300925 (u8) (HFSC & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300926 saa711x_write(sd, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300927 (u8) ((HFSC >> 8) & 0xff));
928 /* write H fine-scaling (chrominance)
929 * must be lum/2, so i'll just bitshift :) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300930 saa711x_write(sd, R_DC_B_HORIZ_CHROMA_SCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300931 (u8) ((HFSC >> 1) & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300932 saa711x_write(sd, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300933 (u8) ((HFSC >> 9) & 0xff));
934
935 VSCY = (int)((1024 * Vsrc) / height);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300936 v4l2_dbg(1, debug, sd, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300937
938 /* Correct Contrast and Luminance */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300939 saa711x_write(sd, R_D5_B_LUMA_CONTRAST_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300940 (u8) (64 * 1024 / VSCY));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300941 saa711x_write(sd, R_D6_B_CHROMA_SATURATION_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300942 (u8) (64 * 1024 / VSCY));
943
944 /* write V fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300945 saa711x_write(sd, R_E0_B_VERT_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300946 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300947 saa711x_write(sd, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300948 (u8) ((VSCY >> 8) & 0xff));
949 /* write V fine-scaling (chrominance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300950 saa711x_write(sd, R_E2_B_VERT_CHROMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300951 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300952 saa711x_write(sd, R_E3_B_VERT_CHROMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300953 (u8) ((VSCY >> 8) & 0xff));
954
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300955 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300956
957 /* Activates task "B" */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300958 saa711x_write(sd, R_80_GLOBAL_CNTL_1,
959 saa711x_read(sd, R_80_GLOBAL_CNTL_1) | 0x20);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300960
961 return 0;
962}
963
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300964static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800965{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300966 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800967
Hans Verkuil30b54d52006-01-09 15:25:43 -0200968 /* Prevent unnecessary standard changes. During a standard
969 change the I-Port is temporarily disabled. Any devices
970 reading from that port can get confused.
Hans Verkuilbccfa442009-03-30 06:55:27 -0300971 Note that s_std is also used to switch from
972 radio to TV mode, so if a s_std is broadcast to
Hans Verkuil30b54d52006-01-09 15:25:43 -0200973 all I2C devices then you do not want to have an unwanted
974 side-effect here. */
975 if (std == state->std)
976 return;
977
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300978 state->std = std;
979
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800980 // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
981 if (std & V4L2_STD_525_60) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300982 v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n");
Jon Arne Jørgensen8b77dfd2013-08-03 09:19:35 -0300983 if (state->ident == GM7113C) {
984 u8 reg = saa711x_read(sd, R_08_SYNC_CNTL);
985 reg &= ~(SAA7113_R_08_FSEL | SAA7113_R_08_AUFD);
986 reg |= SAA7113_R_08_FSEL;
987 saa711x_write(sd, R_08_SYNC_CNTL, reg);
988 } else {
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300989 saa711x_writeregs(sd, saa7115_cfg_60hz_video);
Jon Arne Jørgensen8b77dfd2013-08-03 09:19:35 -0300990 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300991 saa711x_set_size(sd, 720, 480);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800992 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300993 v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n");
Jon Arne Jørgensen8b77dfd2013-08-03 09:19:35 -0300994 if (state->ident == GM7113C) {
995 u8 reg = saa711x_read(sd, R_08_SYNC_CNTL);
996 reg &= ~(SAA7113_R_08_FSEL | SAA7113_R_08_AUFD);
997 saa711x_write(sd, R_08_SYNC_CNTL, reg);
998 } else {
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300999 saa711x_writeregs(sd, saa7115_cfg_50hz_video);
Jon Arne Jørgensen8b77dfd2013-08-03 09:19:35 -03001000 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001001 saa711x_set_size(sd, 720, 576);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001002 }
1003
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001004 /* Register 0E - Bits D6-D4 on NO-AUTO mode
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001005 (SAA7111 and SAA7113 doesn't have auto mode)
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001006 50 Hz / 625 lines 60 Hz / 525 lines
1007 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz)
1008 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz)
1009 010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz)
1010 011 NTSC N (3.58MHz) PAL M (3.58MHz)
1011 100 reserved NTSC-Japan (3.58MHz)
1012 */
Hans Verkuile1277112013-05-29 06:59:51 -03001013 if (state->ident <= SAA7113 ||
1014 state->ident == GM7113C) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001015 u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001016
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -03001017 if (std == V4L2_STD_PAL_M) {
Hans Verkuil01342352006-03-25 08:19:47 -03001018 reg |= 0x30;
Hans Verkuile0028022008-04-22 14:45:51 -03001019 } else if (std == V4L2_STD_PAL_Nc) {
Hans Verkuil01342352006-03-25 08:19:47 -03001020 reg |= 0x20;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -03001021 } else if (std == V4L2_STD_PAL_60) {
Hans Verkuil01342352006-03-25 08:19:47 -03001022 reg |= 0x10;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -03001023 } else if (std == V4L2_STD_NTSC_M_JP) {
Hans Verkuil01342352006-03-25 08:19:47 -03001024 reg |= 0x40;
Mauro Carvalho Chehaba9aaec42007-03-13 13:41:49 -03001025 } else if (std & V4L2_STD_SECAM) {
Pádraig Bradyfc2fa312006-10-09 08:02:17 -03001026 reg |= 0x50;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001027 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001028 saa711x_write(sd, R_0E_CHROMA_CNTL_1, reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001029 } else {
1030 /* restart task B if needed */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001031 int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001032
Hans Verkuile1277112013-05-29 06:59:51 -03001033 if (taskb && state->ident == SAA7114)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001034 saa711x_writeregs(sd, saa7115_cfg_vbi_on);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001035
1036 /* switch audio mode too! */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001037 saa711x_s_clock_freq(sd, state->audclk_freq);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001038 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001039}
1040
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001041/* setup the sliced VBI lcr registers according to the sliced VBI format */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001042static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001043{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001044 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001045 int is_50hz = (state->std & V4L2_STD_625_50);
1046 u8 lcr[24];
1047 int i, x;
1048
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001049#if 1
1050 /* saa7113/7114/7118 VBI support are experimental */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001051 if (!saa711x_has_reg(state->ident, R_41_LCR_BASE))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001052 return;
1053
1054#else
1055 /* SAA7113 and SAA7118 also should support VBI - Need testing */
Hans Verkuile1277112013-05-29 06:59:51 -03001056 if (state->ident != SAA7115)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001057 return;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001058#endif
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001059
1060 for (i = 0; i <= 23; i++)
1061 lcr[i] = 0xff;
1062
Hans Verkuila8b86432008-10-04 08:05:30 -03001063 if (fmt == NULL) {
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001064 /* raw VBI */
1065 if (is_50hz)
1066 for (i = 6; i <= 23; i++)
1067 lcr[i] = 0xdd;
1068 else
1069 for (i = 10; i <= 21; i++)
1070 lcr[i] = 0xdd;
1071 } else {
1072 /* sliced VBI */
1073 /* first clear lines that cannot be captured */
1074 if (is_50hz) {
1075 for (i = 0; i <= 5; i++)
1076 fmt->service_lines[0][i] =
1077 fmt->service_lines[1][i] = 0;
1078 }
1079 else {
1080 for (i = 0; i <= 9; i++)
1081 fmt->service_lines[0][i] =
1082 fmt->service_lines[1][i] = 0;
1083 for (i = 22; i <= 23; i++)
1084 fmt->service_lines[0][i] =
1085 fmt->service_lines[1][i] = 0;
1086 }
1087
1088 /* Now set the lcr values according to the specified service */
1089 for (i = 6; i <= 23; i++) {
1090 lcr[i] = 0;
1091 for (x = 0; x <= 1; x++) {
1092 switch (fmt->service_lines[1-x][i]) {
1093 case 0:
1094 lcr[i] |= 0xf << (4 * x);
1095 break;
Hans Verkuil9bc74002006-03-29 18:02:51 -03001096 case V4L2_SLICED_TELETEXT_B:
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001097 lcr[i] |= 1 << (4 * x);
1098 break;
1099 case V4L2_SLICED_CAPTION_525:
1100 lcr[i] |= 4 << (4 * x);
1101 break;
1102 case V4L2_SLICED_WSS_625:
1103 lcr[i] |= 5 << (4 * x);
1104 break;
1105 case V4L2_SLICED_VPS:
1106 lcr[i] |= 7 << (4 * x);
1107 break;
1108 }
1109 }
1110 }
1111 }
1112
1113 /* write the lcr registers */
1114 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001115 saa711x_write(sd, i - 2 + R_41_LCR_BASE, lcr[i]);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001116 }
1117
1118 /* enable/disable raw VBI capturing */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001119 saa711x_writeregs(sd, fmt == NULL ?
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001120 saa7115_cfg_vbi_on :
1121 saa7115_cfg_vbi_off);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001122}
1123
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001124static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *sliced)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001125{
1126 static u16 lcr2vbi[] = {
Hans Verkuil9bc74002006-03-29 18:02:51 -03001127 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001128 0, V4L2_SLICED_CAPTION_525, /* 4 */
1129 V4L2_SLICED_WSS_625, 0, /* 5 */
1130 V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
1131 0, 0, 0, 0
1132 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001133 int i;
1134
Hans Verkuil30634e82012-09-05 10:38:10 -03001135 memset(sliced->service_lines, 0, sizeof(sliced->service_lines));
1136 sliced->service_set = 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001137 /* done if using raw VBI */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001138 if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001139 return 0;
1140 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001141 u8 v = saa711x_read(sd, i - 2 + R_41_LCR_BASE);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001142
1143 sliced->service_lines[0][i] = lcr2vbi[v >> 4];
1144 sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
1145 sliced->service_set |=
1146 sliced->service_lines[0][i] | sliced->service_lines[1][i];
1147 }
1148 return 0;
1149}
1150
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001151static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
1152{
1153 saa711x_set_lcr(sd, NULL);
1154 return 0;
1155}
1156
1157static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
1158{
1159 saa711x_set_lcr(sd, fmt);
1160 return 0;
1161}
1162
Hans Verkuil6e80c472015-03-21 09:39:09 -03001163static int saa711x_set_fmt(struct v4l2_subdev *sd,
1164 struct v4l2_subdev_pad_config *cfg,
1165 struct v4l2_subdev_format *format)
Hans Verkuilc463d932010-05-09 09:47:23 -03001166{
Hans Verkuil6e80c472015-03-21 09:39:09 -03001167 struct v4l2_mbus_framefmt *fmt = &format->format;
1168
1169 if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED)
Hans Verkuilc463d932010-05-09 09:47:23 -03001170 return -EINVAL;
1171 fmt->field = V4L2_FIELD_INTERLACED;
1172 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
Hans Verkuil6e80c472015-03-21 09:39:09 -03001173 if (format->which == V4L2_SUBDEV_FORMAT_TRY)
1174 return 0;
Hans Verkuilc463d932010-05-09 09:47:23 -03001175 return saa711x_set_size(sd, fmt->width, fmt->height);
1176}
1177
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001178/* Decode the sliced VBI data stream as created by the saa7115.
1179 The format is described in the saa7115 datasheet in Tables 25 and 26
1180 and in Figure 33.
1181 The current implementation uses SAV/EAV codes and not the ancillary data
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001182 headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001183 code. */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001184static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001185{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001186 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001187 static const char vbi_no_data_pattern[] = {
1188 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
1189 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001190 u8 *p = vbi->p;
1191 u32 wss;
1192 int id1, id2; /* the ID1 and ID2 bytes from the internal header */
1193
1194 vbi->type = 0; /* mark result as a failure */
1195 id1 = p[2];
1196 id2 = p[3];
1197 /* Note: the field bit is inverted for 60 Hz video */
1198 if (state->std & V4L2_STD_525_60)
1199 id1 ^= 0x40;
1200
1201 /* Skip internal header, p now points to the start of the payload */
1202 p += 4;
1203 vbi->p = p;
1204
1205 /* calculate field and line number of the VBI packet (1-23) */
1206 vbi->is_second_field = ((id1 & 0x40) != 0);
1207 vbi->line = (id1 & 0x3f) << 3;
1208 vbi->line |= (id2 & 0x70) >> 4;
1209
1210 /* Obtain data type */
1211 id2 &= 0xf;
1212
1213 /* If the VBI slicer does not detect any signal it will fill up
1214 the payload buffer with 0xa0 bytes. */
1215 if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001216 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001217
1218 /* decode payloads */
1219 switch (id2) {
1220 case 1:
Hans Verkuil9bc74002006-03-29 18:02:51 -03001221 vbi->type = V4L2_SLICED_TELETEXT_B;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001222 break;
1223 case 4:
Mauro Carvalho Chehab59ba9152006-08-30 05:34:36 -03001224 if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001225 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001226 vbi->type = V4L2_SLICED_CAPTION_525;
1227 break;
1228 case 5:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001229 wss = saa711x_decode_wss(p);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001230 if (wss == -1)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001231 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001232 p[0] = wss & 0xff;
1233 p[1] = wss >> 8;
1234 vbi->type = V4L2_SLICED_WSS_625;
1235 break;
1236 case 7:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001237 if (saa711x_decode_vps(p, p) != 0)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001238 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001239 vbi->type = V4L2_SLICED_VPS;
1240 break;
1241 default:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001242 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001243 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001244 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001245}
1246
1247/* ============ SAA7115 AUDIO settings (end) ============= */
1248
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001249static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001250{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001251 struct saa711x_state *state = to_state(sd);
1252 int status;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001253
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001254 if (state->radio)
1255 return 0;
1256 status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001257
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001258 v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status);
1259 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1260 return 0;
1261}
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001262
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001263static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1264{
1265 struct saa711x_state *state = to_state(sd);
1266
1267 state->radio = 0;
1268 saa711x_set_v4lstd(sd, std);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001269 return 0;
1270}
1271
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001272static int saa711x_s_radio(struct v4l2_subdev *sd)
1273{
1274 struct saa711x_state *state = to_state(sd);
1275
1276 state->radio = 1;
1277 return 0;
1278}
1279
Hans Verkuil5325b422009-04-02 11:26:22 -03001280static int saa711x_s_routing(struct v4l2_subdev *sd,
1281 u32 input, u32 output, u32 config)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001282{
1283 struct saa711x_state *state = to_state(sd);
Hans Verkuile1277112013-05-29 06:59:51 -03001284 u8 mask = (state->ident <= SAA7111A) ? 0xf8 : 0xf0;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001285
Hans Verkuil5325b422009-04-02 11:26:22 -03001286 v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n",
1287 input, output);
1288
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001289 /* saa7111/3 does not have these inputs */
Hans Verkuile1277112013-05-29 06:59:51 -03001290 if ((state->ident <= SAA7113 ||
1291 state->ident == GM7113C) &&
Hans Verkuil5325b422009-04-02 11:26:22 -03001292 (input == SAA7115_COMPOSITE4 ||
1293 input == SAA7115_COMPOSITE5)) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001294 return -EINVAL;
1295 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001296 if (input > SAA7115_SVIDEO3)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001297 return -EINVAL;
Hans Verkuil5325b422009-04-02 11:26:22 -03001298 if (state->input == input && state->output == output)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001299 return 0;
1300 v4l2_dbg(1, debug, sd, "now setting %s input %s output\n",
Hans Verkuil5325b422009-04-02 11:26:22 -03001301 (input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite",
1302 (output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
1303 state->input = input;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001304
1305 /* saa7111 has slightly different input numbering */
Hans Verkuile1277112013-05-29 06:59:51 -03001306 if (state->ident <= SAA7111A) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001307 if (input >= SAA7115_COMPOSITE4)
1308 input -= 2;
1309 /* saa7111 specific */
1310 saa711x_write(sd, R_10_CHROMA_CNTL_2,
1311 (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001312 ((output & 0xc0) ^ 0x40));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001313 saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL,
1314 (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001315 ((output & 2) ? 0x0a : 0));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001316 }
1317
1318 /* select mode */
1319 saa711x_write(sd, R_02_INPUT_CNTL_1,
1320 (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) |
1321 input);
1322
1323 /* bypass chrominance trap for S-Video modes */
1324 saa711x_write(sd, R_09_LUMA_CNTL,
1325 (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) |
1326 (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
1327
Hans Verkuil5325b422009-04-02 11:26:22 -03001328 state->output = output;
Hans Verkuile1277112013-05-29 06:59:51 -03001329 if (state->ident == SAA7114 ||
1330 state->ident == SAA7115) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001331 saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
1332 (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
1333 (state->output & 0x01));
1334 }
Hans Verkuile1277112013-05-29 06:59:51 -03001335 if (state->ident > SAA7111A) {
Hans Verkuila0fc5882013-03-08 11:22:03 -03001336 if (config & SAA7115_IDQ_IS_DEFAULT)
1337 saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x20);
1338 else
1339 saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x21);
1340 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001341 return 0;
1342}
1343
1344static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val)
1345{
1346 struct saa711x_state *state = to_state(sd);
1347
Hans Verkuile1277112013-05-29 06:59:51 -03001348 if (state->ident > SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001349 return -EINVAL;
1350 saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) |
1351 (val ? 0x80 : 0));
1352 return 0;
1353}
1354
1355static int saa711x_s_stream(struct v4l2_subdev *sd, int enable)
1356{
1357 struct saa711x_state *state = to_state(sd);
1358
1359 v4l2_dbg(1, debug, sd, "%s output\n",
1360 enable ? "enable" : "disable");
1361
Hans Verkuil674a3232009-02-18 12:22:16 -03001362 if (state->enable == enable)
1363 return 0;
1364 state->enable = enable;
1365 if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED))
1366 return 0;
1367 saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001368 return 0;
1369}
1370
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001371static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001372{
1373 struct saa711x_state *state = to_state(sd);
1374
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001375 if (freq != SAA7115_FREQ_32_11_MHZ && freq != SAA7115_FREQ_24_576_MHZ)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001376 return -EINVAL;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001377 state->crystal_freq = freq;
Hans Verkuil15890372013-03-11 03:47:25 -03001378 state->double_asclk = flags & SAA7115_FREQ_FL_DOUBLE_ASCLK;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001379 state->cgcdiv = (flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
Hans Verkuil15890372013-03-11 03:47:25 -03001380 state->ucgc = flags & SAA7115_FREQ_FL_UCGC;
1381 state->apll = flags & SAA7115_FREQ_FL_APLL;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001382 saa711x_s_clock_freq(sd, state->audclk_freq);
1383 return 0;
1384}
1385
1386static int saa711x_reset(struct v4l2_subdev *sd, u32 val)
1387{
1388 v4l2_dbg(1, debug, sd, "decoder RESET\n");
1389 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
1390 return 0;
1391}
1392
1393static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data)
1394{
1395 /* Note: the internal field ID is inverted for NTSC,
1396 so data->field 0 maps to the saa7115 even field,
1397 whereas for PAL it maps to the saa7115 odd field. */
1398 switch (data->id) {
1399 case V4L2_SLICED_WSS_625:
1400 if (saa711x_read(sd, 0x6b) & 0xc0)
1401 return -EIO;
1402 data->data[0] = saa711x_read(sd, 0x6c);
1403 data->data[1] = saa711x_read(sd, 0x6d);
1404 return 0;
1405 case V4L2_SLICED_CAPTION_525:
1406 if (data->field == 0) {
1407 /* CC */
1408 if (saa711x_read(sd, 0x66) & 0x30)
1409 return -EIO;
1410 data->data[0] = saa711x_read(sd, 0x69);
1411 data->data[1] = saa711x_read(sd, 0x6a);
1412 return 0;
1413 }
1414 /* XDS */
1415 if (saa711x_read(sd, 0x66) & 0xc0)
1416 return -EIO;
1417 data->data[0] = saa711x_read(sd, 0x67);
1418 data->data[1] = saa711x_read(sd, 0x68);
1419 return 0;
1420 default:
1421 return -EINVAL;
1422 }
1423}
1424
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001425static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
1426{
1427 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001428 int reg1f, reg1e;
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001429
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001430 /*
1431 * The V4L2 core already initializes std with all supported
1432 * Standards. All driver needs to do is to mask it, to remove
1433 * standards that don't apply from the mask
1434 */
1435
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001436 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuilc875dee2013-03-10 09:59:37 -03001437
Hans Verkuile1277112013-05-29 06:59:51 -03001438 if (state->ident == SAA7115) {
Hans Verkuilc875dee2013-03-10 09:59:37 -03001439 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1440
1441 v4l2_dbg(1, debug, sd, "Status byte 1 (0x1e)=0x%02x\n", reg1e);
1442
1443 switch (reg1e & 0x03) {
1444 case 1:
1445 *std &= V4L2_STD_NTSC;
1446 break;
1447 case 2:
1448 /*
1449 * V4L2_STD_PAL just cover the european PAL standards.
1450 * This is wrong, as the device could also be using an
1451 * other PAL standard.
1452 */
1453 *std &= V4L2_STD_PAL | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc |
1454 V4L2_STD_PAL_M | V4L2_STD_PAL_60;
1455 break;
1456 case 3:
1457 *std &= V4L2_STD_SECAM;
1458 break;
1459 default:
Hans Verkuilaf1f7282013-05-29 10:18:58 -03001460 *std = V4L2_STD_UNKNOWN;
Hans Verkuilc875dee2013-03-10 09:59:37 -03001461 /* Can't detect anything */
1462 break;
1463 }
1464 }
1465
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001466 v4l2_dbg(1, debug, sd, "Status byte 2 (0x1f)=0x%02x\n", reg1f);
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001467
1468 /* horizontal/vertical not locked */
Hans Verkuilaf1f7282013-05-29 10:18:58 -03001469 if (reg1f & 0x40) {
1470 *std = V4L2_STD_UNKNOWN;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001471 goto ret;
Hans Verkuilaf1f7282013-05-29 10:18:58 -03001472 }
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001473
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001474 if (reg1f & 0x20)
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001475 *std &= V4L2_STD_525_60;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001476 else
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001477 *std &= V4L2_STD_625_50;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001478
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001479ret:
1480 v4l2_dbg(1, debug, sd, "detected std mask = %08Lx\n", *std);
1481
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001482 return 0;
1483}
1484
1485static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status)
1486{
1487 struct saa711x_state *state = to_state(sd);
1488 int reg1e = 0x80;
1489 int reg1f;
1490
1491 *status = V4L2_IN_ST_NO_SIGNAL;
Hans Verkuile1277112013-05-29 06:59:51 -03001492 if (state->ident == SAA7115)
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001493 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1494 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1495 if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80)
1496 *status = 0;
1497 return 0;
1498}
1499
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001500#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001501static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001502{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001503 reg->val = saa711x_read(sd, reg->reg & 0xff);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001504 reg->size = 1;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001505 return 0;
1506}
1507
Hans Verkuil977ba3b12013-03-24 08:28:46 -03001508static int saa711x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001509{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001510 saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff);
1511 return 0;
1512}
1513#endif
1514
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001515static int saa711x_log_status(struct v4l2_subdev *sd)
1516{
1517 struct saa711x_state *state = to_state(sd);
1518 int reg1e, reg1f;
1519 int signalOk;
1520 int vcr;
1521
1522 v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq);
Hans Verkuile1277112013-05-29 06:59:51 -03001523 if (state->ident != SAA7115) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001524 /* status for the saa7114 */
1525 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1526 signalOk = (reg1f & 0xc1) == 0x81;
1527 v4l2_info(sd, "Video signal: %s\n", signalOk ? "ok" : "bad");
1528 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1529 return 0;
1530 }
1531
1532 /* status for the saa7115 */
1533 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1534 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1535
1536 signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
1537 vcr = !(reg1f & 0x10);
1538
1539 if (state->input >= 6)
1540 v4l2_info(sd, "Input: S-Video %d\n", state->input - 6);
1541 else
1542 v4l2_info(sd, "Input: Composite %d\n", state->input);
1543 v4l2_info(sd, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
1544 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1545
1546 switch (reg1e & 0x03) {
1547 case 1:
1548 v4l2_info(sd, "Detected format: NTSC\n");
1549 break;
1550 case 2:
1551 v4l2_info(sd, "Detected format: PAL\n");
1552 break;
1553 case 3:
1554 v4l2_info(sd, "Detected format: SECAM\n");
1555 break;
1556 default:
1557 v4l2_info(sd, "Detected format: BW/No color\n");
1558 break;
1559 }
1560 v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height);
Hans Verkuile3560542010-05-24 10:00:52 -03001561 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001562 return 0;
1563}
1564
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001565/* ----------------------------------------------------------------------- */
1566
Hans Verkuile3560542010-05-24 10:00:52 -03001567static const struct v4l2_ctrl_ops saa711x_ctrl_ops = {
1568 .s_ctrl = saa711x_s_ctrl,
1569 .g_volatile_ctrl = saa711x_g_volatile_ctrl,
1570};
1571
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001572static const struct v4l2_subdev_core_ops saa711x_core_ops = {
1573 .log_status = saa711x_log_status,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001574 .reset = saa711x_reset,
1575 .s_gpio = saa711x_s_gpio,
1576#ifdef CONFIG_VIDEO_ADV_DEBUG
1577 .g_register = saa711x_g_register,
1578 .s_register = saa711x_s_register,
1579#endif
1580};
1581
1582static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001583 .s_radio = saa711x_s_radio,
1584 .g_tuner = saa711x_g_tuner,
1585};
1586
1587static const struct v4l2_subdev_audio_ops saa711x_audio_ops = {
1588 .s_clock_freq = saa711x_s_clock_freq,
1589};
1590
1591static const struct v4l2_subdev_video_ops saa711x_video_ops = {
Laurent Pinchart8774bed2014-04-28 16:53:01 -03001592 .s_std = saa711x_s_std,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001593 .s_routing = saa711x_s_routing,
1594 .s_crystal_freq = saa711x_s_crystal_freq,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001595 .s_stream = saa711x_s_stream,
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001596 .querystd = saa711x_querystd,
1597 .g_input_status = saa711x_g_input_status,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001598};
1599
Hans Verkuil32cd5272010-03-14 09:57:30 -03001600static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = {
1601 .g_vbi_data = saa711x_g_vbi_data,
1602 .decode_vbi_line = saa711x_decode_vbi_line,
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001603 .g_sliced_fmt = saa711x_g_sliced_fmt,
1604 .s_sliced_fmt = saa711x_s_sliced_fmt,
1605 .s_raw_fmt = saa711x_s_raw_fmt,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001606};
1607
Hans Verkuil6e80c472015-03-21 09:39:09 -03001608static const struct v4l2_subdev_pad_ops saa711x_pad_ops = {
1609 .set_fmt = saa711x_set_fmt,
1610};
1611
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001612static const struct v4l2_subdev_ops saa711x_ops = {
1613 .core = &saa711x_core_ops,
1614 .tuner = &saa711x_tuner_ops,
1615 .audio = &saa711x_audio_ops,
1616 .video = &saa711x_video_ops,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001617 .vbi = &saa711x_vbi_ops,
Hans Verkuil6e80c472015-03-21 09:39:09 -03001618 .pad = &saa711x_pad_ops,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001619};
1620
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001621#define CHIP_VER_SIZE 16
1622
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001623/* ----------------------------------------------------------------------- */
1624
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001625static void saa711x_write_platform_data(struct saa711x_state *state,
1626 struct saa7115_platform_data *data)
1627{
1628 struct v4l2_subdev *sd = &state->sd;
1629 u8 work;
1630
1631 if (state->ident != GM7113C &&
1632 state->ident != SAA7113)
1633 return;
1634
1635 if (data->saa7113_r08_htc) {
1636 work = saa711x_read(sd, R_08_SYNC_CNTL);
1637 work &= ~SAA7113_R_08_HTC_MASK;
1638 work |= ((*data->saa7113_r08_htc) << SAA7113_R_08_HTC_OFFSET);
1639 saa711x_write(sd, R_08_SYNC_CNTL, work);
1640 }
1641
1642 if (data->saa7113_r10_vrln) {
1643 work = saa711x_read(sd, R_10_CHROMA_CNTL_2);
1644 work &= ~SAA7113_R_10_VRLN_MASK;
1645 if (*data->saa7113_r10_vrln)
1646 work |= (1 << SAA7113_R_10_VRLN_OFFSET);
1647 saa711x_write(sd, R_10_CHROMA_CNTL_2, work);
1648 }
1649
1650 if (data->saa7113_r10_ofts) {
1651 work = saa711x_read(sd, R_10_CHROMA_CNTL_2);
1652 work &= ~SAA7113_R_10_OFTS_MASK;
1653 work |= (*data->saa7113_r10_ofts << SAA7113_R_10_OFTS_OFFSET);
1654 saa711x_write(sd, R_10_CHROMA_CNTL_2, work);
1655 }
1656
1657 if (data->saa7113_r12_rts0) {
1658 work = saa711x_read(sd, R_12_RT_SIGNAL_CNTL);
1659 work &= ~SAA7113_R_12_RTS0_MASK;
1660 work |= (*data->saa7113_r12_rts0 << SAA7113_R_12_RTS0_OFFSET);
1661
1662 /* According to the datasheet,
1663 * SAA7113_RTS_DOT_IN should only be used on RTS1 */
1664 WARN_ON(*data->saa7113_r12_rts0 == SAA7113_RTS_DOT_IN);
1665 saa711x_write(sd, R_12_RT_SIGNAL_CNTL, work);
1666 }
1667
1668 if (data->saa7113_r12_rts1) {
1669 work = saa711x_read(sd, R_12_RT_SIGNAL_CNTL);
1670 work &= ~SAA7113_R_12_RTS1_MASK;
1671 work |= (*data->saa7113_r12_rts1 << SAA7113_R_12_RTS1_OFFSET);
1672 saa711x_write(sd, R_12_RT_SIGNAL_CNTL, work);
1673 }
1674
1675 if (data->saa7113_r13_adlsb) {
1676 work = saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL);
1677 work &= ~SAA7113_R_13_ADLSB_MASK;
1678 if (*data->saa7113_r13_adlsb)
1679 work |= (1 << SAA7113_R_13_ADLSB_OFFSET);
1680 saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL, work);
1681 }
1682}
1683
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001684/**
1685 * saa711x_detect_chip - Detects the saa711x (or clone) variant
1686 * @client: I2C client structure.
1687 * @id: I2C device ID structure.
1688 * @name: Name of the device to be filled.
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001689 *
1690 * Detects the Philips/NXP saa711x chip, or some clone of it.
1691 * if 'id' is NULL or id->driver_data is equal to 1, it auto-probes
1692 * the analog demod.
1693 * If the tuner is not found, it returns -ENODEV.
1694 * If auto-detection is disabled and the tuner doesn't match what it was
Jonathan McCrohan39c1cb22013-10-20 21:34:01 -03001695 * required, it returns -EINVAL and fills 'name'.
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001696 * If the chip is found, it returns the chip ID and fills 'name'.
1697 */
1698static int saa711x_detect_chip(struct i2c_client *client,
1699 const struct i2c_device_id *id,
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001700 char *name)
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001701{
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001702 char chip_ver[CHIP_VER_SIZE];
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001703 char chip_id;
1704 int i;
1705 int autodetect;
1706
1707 autodetect = !id || id->driver_data == 1;
1708
1709 /* Read the chip version register */
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001710 for (i = 0; i < CHIP_VER_SIZE; i++) {
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001711 i2c_smbus_write_byte_data(client, 0, i);
1712 chip_ver[i] = i2c_smbus_read_byte_data(client, 0);
1713 name[i] = (chip_ver[i] & 0x0f) + '0';
1714 if (name[i] > '9')
1715 name[i] += 'a' - '9' - 1;
1716 }
1717 name[i] = '\0';
1718
1719 /* Check if it is a Philips/NXP chip */
1720 if (!memcmp(name + 1, "f711", 4)) {
1721 chip_id = name[5];
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001722 snprintf(name, CHIP_VER_SIZE, "saa711%c", chip_id);
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001723
1724 if (!autodetect && strcmp(name, id->name))
1725 return -EINVAL;
1726
1727 switch (chip_id) {
1728 case '1':
1729 if (chip_ver[0] & 0xf0) {
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001730 snprintf(name, CHIP_VER_SIZE, "saa711%ca", chip_id);
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001731 v4l_info(client, "saa7111a variant found\n");
Hans Verkuile1277112013-05-29 06:59:51 -03001732 return SAA7111A;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001733 }
Hans Verkuile1277112013-05-29 06:59:51 -03001734 return SAA7111;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001735 case '3':
Hans Verkuile1277112013-05-29 06:59:51 -03001736 return SAA7113;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001737 case '4':
Hans Verkuile1277112013-05-29 06:59:51 -03001738 return SAA7114;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001739 case '5':
Hans Verkuile1277112013-05-29 06:59:51 -03001740 return SAA7115;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001741 case '8':
Hans Verkuile1277112013-05-29 06:59:51 -03001742 return SAA7118;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001743 default:
1744 v4l2_info(client,
1745 "WARNING: Philips/NXP chip unknown - Falling back to saa7111\n");
Hans Verkuile1277112013-05-29 06:59:51 -03001746 return SAA7111;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001747 }
1748 }
1749
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001750 /* Check if it is a gm7113c */
1751 if (!memcmp(name, "0000", 4)) {
1752 chip_id = 0;
1753 for (i = 0; i < 4; i++) {
1754 chip_id = chip_id << 1;
1755 chip_id |= (chip_ver[i] & 0x80) ? 1 : 0;
1756 }
1757
1758 /*
1759 * Note: From the datasheet, only versions 1 and 2
1760 * exists. However, tests on a device labeled as:
1761 * "GM7113C 1145" returned "10" on all 16 chip
1762 * version (reg 0x00) reads. So, we need to also
1763 * accept at least verion 0. For now, let's just
1764 * assume that a device that returns "0000" for
1765 * the lower nibble is a gm7113c.
1766 */
1767
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001768 strlcpy(name, "gm7113c", CHIP_VER_SIZE);
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001769
1770 if (!autodetect && strcmp(name, id->name))
1771 return -EINVAL;
1772
1773 v4l_dbg(1, debug, client,
1774 "It seems to be a %s chip (%*ph) @ 0x%x.\n",
1775 name, 16, chip_ver, client->addr << 1);
1776
Hans Verkuile1277112013-05-29 06:59:51 -03001777 return GM7113C;
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001778 }
1779
Kevin Fitch7e312232016-03-23 01:23:32 -03001780 /* Check if it is a CJC7113 */
1781 if (!memcmp(name, "1111111111111111", CHIP_VER_SIZE)) {
1782 strlcpy(name, "cjc7113", CHIP_VER_SIZE);
1783
1784 if (!autodetect && strcmp(name, id->name))
1785 return -EINVAL;
1786
1787 v4l_dbg(1, debug, client,
1788 "It seems to be a %s chip (%*ph) @ 0x%x.\n",
1789 name, 16, chip_ver, client->addr << 1);
1790
1791 /* CJC7113 seems to be SAA7113-compatible */
1792 return SAA7113;
1793 }
1794
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001795 /* Chip was not discovered. Return its ID and don't bind */
1796 v4l_dbg(1, debug, client, "chip %*ph @ 0x%x is unknown.\n",
1797 16, chip_ver, client->addr << 1);
1798 return -ENODEV;
1799}
1800
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001801static int saa711x_probe(struct i2c_client *client,
Jean Delvared2653e92008-04-29 23:11:39 +02001802 const struct i2c_device_id *id)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001803{
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001804 struct saa711x_state *state;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001805 struct v4l2_subdev *sd;
Hans Verkuile3560542010-05-24 10:00:52 -03001806 struct v4l2_ctrl_handler *hdl;
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001807 struct saa7115_platform_data *pdata;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001808 int ident;
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001809 char name[CHIP_VER_SIZE + 1];
Mauro Carvalho Chehabaf7d3742016-01-29 08:44:28 -02001810#if defined(CONFIG_MEDIA_CONTROLLER)
1811 int ret;
1812#endif
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001813
1814 /* Check if the adapter supports the needed features */
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001815 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
Hans Verkuil188f3452007-09-16 10:47:15 -03001816 return -EIO;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001817
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001818 ident = saa711x_detect_chip(client, id, name);
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001819 if (ident == -EINVAL) {
1820 /* Chip exists, but doesn't match */
1821 v4l_warn(client, "found %s while %s was expected\n",
1822 name, id->name);
Hans Verkuil188f3452007-09-16 10:47:15 -03001823 return -ENODEV;
Hans Verkuilf7668162006-11-25 09:40:28 -03001824 }
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001825 if (ident < 0)
1826 return ident;
Hans Verkuilf7668162006-11-25 09:40:28 -03001827
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001828 strlcpy(client->name, name, sizeof(client->name));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001829
Laurent Pinchartc02b2112013-05-02 08:29:43 -03001830 state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
Hans Verkuilc5bf2042008-09-03 17:12:09 -03001831 if (state == NULL)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001832 return -ENOMEM;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001833 sd = &state->sd;
1834 v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
Hans Verkuile3560542010-05-24 10:00:52 -03001835
Mauro Carvalho Chehabaf7d3742016-01-29 08:44:28 -02001836#if defined(CONFIG_MEDIA_CONTROLLER)
1837 state->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
1838 state->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
1839 state->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE;
1840
1841 sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
1842
1843 ret = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, state->pads);
1844 if (ret < 0)
1845 return ret;
1846#endif
1847
Hans Verkuile84e91e2013-05-29 06:59:37 -03001848 v4l_info(client, "%s found @ 0x%x (%s)\n", name,
1849 client->addr << 1, client->adapter->name);
Hans Verkuile3560542010-05-24 10:00:52 -03001850 hdl = &state->hdl;
1851 v4l2_ctrl_handler_init(hdl, 6);
1852 /* add in ascending ID order */
1853 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1854 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1855 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1856 V4L2_CID_CONTRAST, 0, 127, 1, 64);
1857 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1858 V4L2_CID_SATURATION, 0, 127, 1, 64);
1859 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1860 V4L2_CID_HUE, -128, 127, 1, 0);
1861 state->agc = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1862 V4L2_CID_CHROMA_AGC, 0, 1, 1, 1);
1863 state->gain = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1864 V4L2_CID_CHROMA_GAIN, 0, 127, 1, 40);
Hans Verkuile3560542010-05-24 10:00:52 -03001865 sd->ctrl_handler = hdl;
1866 if (hdl->error) {
1867 int err = hdl->error;
1868
1869 v4l2_ctrl_handler_free(hdl);
Hans Verkuile3560542010-05-24 10:00:52 -03001870 return err;
1871 }
Hans Verkuil6f43dbf2011-08-26 08:46:29 -03001872 v4l2_ctrl_auto_cluster(2, &state->agc, 0, true);
Hans Verkuile3560542010-05-24 10:00:52 -03001873
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001874 state->input = -1;
Marco Schluessler4cbca182007-01-21 19:43:38 -03001875 state->output = SAA7115_IPORT_ON;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001876 state->enable = 1;
Hans Verkuil3faeeae2006-01-09 15:25:44 -02001877 state->radio = 0;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001878 state->ident = ident;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001879
Hans Verkuil3578d3d2006-01-09 15:25:41 -02001880 state->audclk_freq = 48000;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001881
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001882 v4l2_dbg(1, debug, sd, "writing init values\n");
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001883
1884 /* init to 60hz/48khz */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001885 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001886 pdata = client->dev.platform_data;
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001887 switch (state->ident) {
Hans Verkuile1277112013-05-29 06:59:51 -03001888 case SAA7111:
1889 case SAA7111A:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001890 saa711x_writeregs(sd, saa7111_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001891 break;
Hans Verkuile1277112013-05-29 06:59:51 -03001892 case GM7113C:
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001893 saa711x_writeregs(sd, gm7113c_init);
1894 break;
Hans Verkuile1277112013-05-29 06:59:51 -03001895 case SAA7113:
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001896 if (pdata && pdata->saa7113_force_gm7113c_init)
1897 saa711x_writeregs(sd, gm7113c_init);
1898 else
1899 saa711x_writeregs(sd, saa7113_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001900 break;
1901 default:
Hans Verkuilb7f82922006-04-02 12:50:42 -03001902 state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001903 saa711x_writeregs(sd, saa7115_init_auto_input);
Hans Verkuilb7f82922006-04-02 12:50:42 -03001904 }
Jon Arne Jørgensenb9798bc2013-08-03 09:19:36 -03001905 if (state->ident > SAA7111A && state->ident != GM7113C)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001906 saa711x_writeregs(sd, saa7115_init_misc);
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001907
1908 if (pdata)
1909 saa711x_write_platform_data(state, pdata);
1910
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001911 saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
Hans Verkuile3560542010-05-24 10:00:52 -03001912 v4l2_ctrl_handler_setup(hdl);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001913
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001914 v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n",
1915 saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC),
1916 saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001917 return 0;
1918}
1919
1920/* ----------------------------------------------------------------------- */
1921
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001922static int saa711x_remove(struct i2c_client *client)
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001923{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001924 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1925
1926 v4l2_device_unregister_subdev(sd);
Hans Verkuile3560542010-05-24 10:00:52 -03001927 v4l2_ctrl_handler_free(sd->ctrl_handler);
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001928 return 0;
1929}
1930
Hans Verkuilaac23532010-09-15 15:04:55 -03001931static const struct i2c_device_id saa711x_id[] = {
Hans Verkuil9edd350f2008-07-17 13:22:51 -03001932 { "saa7115_auto", 1 }, /* autodetect */
Jean Delvareaf294862008-05-18 20:49:40 +02001933 { "saa7111", 0 },
1934 { "saa7113", 0 },
1935 { "saa7114", 0 },
1936 { "saa7115", 0 },
1937 { "saa7118", 0 },
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001938 { "gm7113c", 0 },
Jean Delvareaf294862008-05-18 20:49:40 +02001939 { }
1940};
Hans Verkuilaac23532010-09-15 15:04:55 -03001941MODULE_DEVICE_TABLE(i2c, saa711x_id);
Jean Delvareaf294862008-05-18 20:49:40 +02001942
Hans Verkuilaac23532010-09-15 15:04:55 -03001943static struct i2c_driver saa711x_driver = {
1944 .driver = {
Hans Verkuilaac23532010-09-15 15:04:55 -03001945 .name = "saa7115",
1946 },
1947 .probe = saa711x_probe,
1948 .remove = saa711x_remove,
1949 .id_table = saa711x_id,
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001950};
Hans Verkuilaac23532010-09-15 15:04:55 -03001951
Axel Linc6e8d862012-02-12 06:56:32 -03001952module_i2c_driver(saa711x_driver);