blob: 88dc6baac6391bf4bb686eaacfc4122f8834292d [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//
Mauro Carvalho Chehab32590812018-04-25 05:34:48 -040023// Copyright (c) 2005-2006 Mauro Carvalho Chehab <mchehab@kernel.org>
Mauro Carvalho Chehab459ee172017-12-01 08:47:12 -050024// 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 Chehab87f997172018-08-01 06:07:09 -040062enum saa711x_pads {
63 SAA711X_PAD_IF_INPUT,
64 SAA711X_PAD_VID_OUT,
65 SAA711X_NUM_PADS
66};
67
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -030068struct saa711x_state {
Hans Verkuil9415f4b2008-11-29 12:55:19 -030069 struct v4l2_subdev sd;
Mauro Carvalho Chehabaf7d3742016-01-29 08:44:28 -020070#ifdef CONFIG_MEDIA_CONTROLLER
Mauro Carvalho Chehab87f997172018-08-01 06:07:09 -040071 struct media_pad pads[SAA711X_NUM_PADS];
Mauro Carvalho Chehabaf7d3742016-01-29 08:44:28 -020072#endif
Hans Verkuile3560542010-05-24 10:00:52 -030073 struct v4l2_ctrl_handler hdl;
74
75 struct {
76 /* chroma gain control cluster */
77 struct v4l2_ctrl *agc;
78 struct v4l2_ctrl *gain;
79 };
80
Hans Verkuile19b2fc2005-11-13 16:08:04 -080081 v4l2_std_id std;
82 int input;
Marco Schluessler4cbca182007-01-21 19:43:38 -030083 int output;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080084 int enable;
Hans Verkuil3faeeae2006-01-09 15:25:44 -020085 int radio;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -030086 int width;
87 int height;
Hans Verkuile1277112013-05-29 06:59:51 -030088 enum saa711x_model ident;
Hans Verkuil3578d3d2006-01-09 15:25:41 -020089 u32 audclk_freq;
Hans Verkuilb7f82922006-04-02 12:50:42 -030090 u32 crystal_freq;
Hans Verkuil15890372013-03-11 03:47:25 -030091 bool ucgc;
Hans Verkuilb7f82922006-04-02 12:50:42 -030092 u8 cgcdiv;
Hans Verkuil15890372013-03-11 03:47:25 -030093 bool apll;
94 bool double_asclk;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080095};
96
Hans Verkuil9415f4b2008-11-29 12:55:19 -030097static inline struct saa711x_state *to_state(struct v4l2_subdev *sd)
98{
99 return container_of(sd, struct saa711x_state, sd);
100}
101
Hans Verkuile3560542010-05-24 10:00:52 -0300102static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
103{
104 return &container_of(ctrl->handler, struct saa711x_state, hdl)->sd;
105}
106
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800107/* ----------------------------------------------------------------------- */
108
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300109static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800110{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300111 struct i2c_client *client = v4l2_get_subdevdata(sd);
112
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800113 return i2c_smbus_write_byte_data(client, reg, value);
114}
115
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300116/* Sanity routine to check if a register is present */
117static int saa711x_has_reg(const int id, const u8 reg)
118{
Hans Verkuile1277112013-05-29 06:59:51 -0300119 if (id == SAA7111)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300120 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
121 (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e;
Hans Verkuile1277112013-05-29 06:59:51 -0300122 if (id == SAA7111A)
Hans Verkuil340dde82010-02-20 08:07:51 -0300123 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
124 reg != 0x14 && reg != 0x18 && reg != 0x19 &&
125 reg != 0x1d && reg != 0x1e;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300126
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300127 /* common for saa7113/4/5/8 */
128 if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f ||
129 reg == 0xa3 || reg == 0xa7 || reg == 0xab || reg == 0xaf || (reg >= 0xb5 && reg <= 0xb7) ||
130 reg == 0xd3 || reg == 0xd7 || reg == 0xdb || reg == 0xdf || (reg >= 0xe5 && reg <= 0xe7) ||
131 reg == 0x82 || (reg >= 0x89 && reg <= 0x8e)))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300132 return 0;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300133
134 switch (id) {
Hans Verkuile1277112013-05-29 06:59:51 -0300135 case GM7113C:
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300136 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && reg < 0x20;
Hans Verkuile1277112013-05-29 06:59:51 -0300137 case SAA7113:
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300138 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
139 reg != 0x5d && reg < 0x63;
Hans Verkuile1277112013-05-29 06:59:51 -0300140 case SAA7114:
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300141 return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
142 (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
143 reg != 0x81 && reg < 0xf0;
Hans Verkuile1277112013-05-29 06:59:51 -0300144 case SAA7115:
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300145 return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe);
Hans Verkuile1277112013-05-29 06:59:51 -0300146 case SAA7118:
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300147 return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
148 (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
149 (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
150 }
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300151 return 1;
152}
153
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300154static int saa711x_writeregs(struct v4l2_subdev *sd, const unsigned char *regs)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800155{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300156 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800157 unsigned char reg, data;
158
159 while (*regs != 0x00) {
160 reg = *(regs++);
161 data = *(regs++);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300162
163 /* According with datasheets, reserved regs should be
164 filled with 0 - seems better not to touch on they */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300165 if (saa711x_has_reg(state->ident, reg)) {
166 if (saa711x_write(sd, reg, data) < 0)
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300167 return -1;
Mauro Carvalho Chehabd87edf22006-09-01 09:37:11 -0300168 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300169 v4l2_dbg(1, debug, sd, "tried to access reserved reg 0x%02x\n", reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300170 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800171 }
172 return 0;
173}
174
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300175static inline int saa711x_read(struct v4l2_subdev *sd, u8 reg)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800176{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300177 struct i2c_client *client = v4l2_get_subdevdata(sd);
178
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800179 return i2c_smbus_read_byte_data(client, reg);
180}
181
182/* ----------------------------------------------------------------------- */
183
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300184/* SAA7111 initialization table */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300185static const unsigned char saa7111_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300186 R_01_INC_DELAY, 0x00, /* reserved */
187
188 /*front end */
189 R_02_INPUT_CNTL_1, 0xd0, /* FUSE=3, GUDL=2, MODE=0 */
190 R_03_INPUT_CNTL_2, 0x23, /* HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0,
191 * GAFIX=0, GAI1=256, GAI2=256 */
192 R_04_INPUT_CNTL_3, 0x00, /* GAI1=256 */
193 R_05_INPUT_CNTL_4, 0x00, /* GAI2=256 */
194
195 /* decoder */
196 R_06_H_SYNC_START, 0xf3, /* HSB at 13(50Hz) / 17(60Hz)
197 * pixels after end of last line */
198 R_07_H_SYNC_STOP, 0xe8, /* HSS seems to be needed to
199 * work with NTSC, too */
200 R_08_SYNC_CNTL, 0xc8, /* AUFD=1, FSEL=1, EXFIL=0,
201 * VTRC=1, HPLL=0, VNOI=0 */
202 R_09_LUMA_CNTL, 0x01, /* BYPS=0, PREF=0, BPSS=0,
203 * VBLB=0, UPTCV=0, APER=1 */
204 R_0A_LUMA_BRIGHT_CNTL, 0x80,
205 R_0B_LUMA_CONTRAST_CNTL, 0x47, /* 0b - CONT=1.109 */
206 R_0C_CHROMA_SAT_CNTL, 0x40,
207 R_0D_CHROMA_HUE_CNTL, 0x00,
208 R_0E_CHROMA_CNTL_1, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0,
209 * FCTC=0, CHBW=1 */
210 R_0F_CHROMA_GAIN_CNTL, 0x00, /* reserved */
211 R_10_CHROMA_CNTL_2, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
212 R_11_MODE_DELAY_CNTL, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
213 * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
214 R_12_RT_SIGNAL_CNTL, 0x00, /* 12 - output control 2 */
215 R_13_RT_X_PORT_OUT_CNTL, 0x00, /* 13 - output control 3 */
216 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
217 R_15_VGATE_START_FID_CHG, 0x00,
218 R_16_VGATE_STOP, 0x00,
219 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
220
221 0x00, 0x00
222};
223
Mauro Carvalho Chehab04074f12013-08-18 08:35:36 -0300224/*
225 * This table has one illegal value, and some values that are not
226 * correct according to the datasheet initialization table.
227 *
228 * If you need a table with legal/default values tell the driver in
229 * i2c_board_info.platform_data, and you will get the gm7113c_init
230 * table instead.
231 */
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300232
233/* SAA7113 Init codes */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300234static const unsigned char saa7113_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300235 R_01_INC_DELAY, 0x08,
236 R_02_INPUT_CNTL_1, 0xc2,
237 R_03_INPUT_CNTL_2, 0x30,
238 R_04_INPUT_CNTL_3, 0x00,
239 R_05_INPUT_CNTL_4, 0x00,
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300240 R_06_H_SYNC_START, 0x89, /* Illegal value -119,
241 * min. value = -108 (0x94) */
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300242 R_07_H_SYNC_STOP, 0x0d,
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300243 R_08_SYNC_CNTL, 0x88, /* Not datasheet default.
244 * HTC = VTR mode, should be 0x98 */
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300245 R_09_LUMA_CNTL, 0x01,
246 R_0A_LUMA_BRIGHT_CNTL, 0x80,
247 R_0B_LUMA_CONTRAST_CNTL, 0x47,
248 R_0C_CHROMA_SAT_CNTL, 0x40,
249 R_0D_CHROMA_HUE_CNTL, 0x00,
250 R_0E_CHROMA_CNTL_1, 0x01,
251 R_0F_CHROMA_GAIN_CNTL, 0x2a,
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300252 R_10_CHROMA_CNTL_2, 0x08, /* Not datsheet default.
253 * VRLN enabled, should be 0x00 */
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300254 R_11_MODE_DELAY_CNTL, 0x0c,
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300255 R_12_RT_SIGNAL_CNTL, 0x07, /* Not datasheet default,
256 * should be 0x01 */
257 R_13_RT_X_PORT_OUT_CNTL, 0x00,
258 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
259 R_15_VGATE_START_FID_CHG, 0x00,
260 R_16_VGATE_STOP, 0x00,
261 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
262
263 0x00, 0x00
264};
265
Mauro Carvalho Chehab04074f12013-08-18 08:35:36 -0300266/*
267 * GM7113C is a clone of the SAA7113 chip
268 * This init table is copied out of the saa7113 datasheet.
269 * In R_08 we enable "Automatic Field Detection" [AUFD],
270 * this is disabled when saa711x_set_v4lstd is called.
271 */
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300272static const unsigned char gm7113c_init[] = {
273 R_01_INC_DELAY, 0x08,
274 R_02_INPUT_CNTL_1, 0xc0,
275 R_03_INPUT_CNTL_2, 0x33,
276 R_04_INPUT_CNTL_3, 0x00,
277 R_05_INPUT_CNTL_4, 0x00,
278 R_06_H_SYNC_START, 0xe9,
279 R_07_H_SYNC_STOP, 0x0d,
280 R_08_SYNC_CNTL, 0x98,
281 R_09_LUMA_CNTL, 0x01,
282 R_0A_LUMA_BRIGHT_CNTL, 0x80,
283 R_0B_LUMA_CONTRAST_CNTL, 0x47,
284 R_0C_CHROMA_SAT_CNTL, 0x40,
285 R_0D_CHROMA_HUE_CNTL, 0x00,
286 R_0E_CHROMA_CNTL_1, 0x01,
287 R_0F_CHROMA_GAIN_CNTL, 0x2a,
288 R_10_CHROMA_CNTL_2, 0x00,
289 R_11_MODE_DELAY_CNTL, 0x0c,
290 R_12_RT_SIGNAL_CNTL, 0x01,
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300291 R_13_RT_X_PORT_OUT_CNTL, 0x00,
292 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
293 R_15_VGATE_START_FID_CHG, 0x00,
294 R_16_VGATE_STOP, 0x00,
295 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
296
297 0x00, 0x00
298};
299
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800300/* If a value differs from the Hauppauge driver values, then the comment starts with
301 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
302 Hauppauge driver sets. */
303
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300304/* SAA7114 and SAA7115 initialization table */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800305static const unsigned char saa7115_init_auto_input[] = {
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300306 /* Front-End Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300307 R_01_INC_DELAY, 0x48, /* white peak control disabled */
308 R_03_INPUT_CNTL_2, 0x20, /* was 0x30. 0x20: long vertical blanking */
309 R_04_INPUT_CNTL_3, 0x90, /* analog gain set to 0 */
310 R_05_INPUT_CNTL_4, 0x90, /* analog gain set to 0 */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300311 /* Decoder Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300312 R_06_H_SYNC_START, 0xeb, /* horiz sync begin = -21 */
313 R_07_H_SYNC_STOP, 0xe0, /* horiz sync stop = -17 */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300314 R_09_LUMA_CNTL, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300315 R_0A_LUMA_BRIGHT_CNTL, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */
316 R_0B_LUMA_CONTRAST_CNTL, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */
317 R_0C_CHROMA_SAT_CNTL, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */
318 R_0D_CHROMA_HUE_CNTL, 0x00,
319 R_0F_CHROMA_GAIN_CNTL, 0x00, /* use automatic gain */
320 R_10_CHROMA_CNTL_2, 0x06, /* chroma: active adaptive combfilter */
321 R_11_MODE_DELAY_CNTL, 0x00,
322 R_12_RT_SIGNAL_CNTL, 0x9d, /* RTS0 output control: VGATE */
323 R_13_RT_X_PORT_OUT_CNTL, 0x80, /* ITU656 standard mode, RTCO output enable RTCE */
324 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
325 R_18_RAW_DATA_GAIN_CNTL, 0x40, /* gain 0x00 = nominal */
326 R_19_RAW_DATA_OFF_CNTL, 0x80,
327 R_1A_COLOR_KILL_LVL_CNTL, 0x77, /* recommended value */
328 R_1B_MISC_TVVCRDET, 0x42, /* recommended value */
329 R_1C_ENHAN_COMB_CTRL1, 0xa9, /* recommended value */
330 R_1D_ENHAN_COMB_CTRL2, 0x01, /* recommended value */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300331
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300332
333 R_80_GLOBAL_CNTL_1, 0x0, /* No tasks enabled at init */
334
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300335 /* Power Device Control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300336 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset device */
337 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* set device programmed, all in operational mode */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800338 0x00, 0x00
339};
340
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300341/* Used to reset saa7113, saa7114 and saa7115 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800342static const unsigned char saa7115_cfg_reset_scaler[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300343 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00, /* disable I-port output */
344 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
345 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
346 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* enable I-port output */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800347 0x00, 0x00
348};
349
350/* ============== SAA7715 VIDEO templates ============= */
351
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800352static const unsigned char saa7115_cfg_60hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300353 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
354 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800355
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300356 R_15_VGATE_START_FID_CHG, 0x03,
357 R_16_VGATE_STOP, 0x11,
358 R_17_MISC_VGATE_CONF_AND_MSB, 0x9c,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800359
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300360 R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
361 R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800362
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300363 R_5A_V_OFF_FOR_SLICER, 0x06, /* standard 60hz value for ITU656 line counting */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800364
365 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300366 R_90_A_TASK_HANDLING_CNTL, 0x80,
367 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
368 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
369 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
370
371 /* hoffset low (input), 0x0002 is minimum */
372 R_94_A_HORIZ_INPUT_WINDOW_START, 0x01,
373 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
374
375 /* hsize low (input), 0x02d0 = 720 */
376 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
377 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
378
379 R_98_A_VERT_INPUT_WINDOW_START, 0x05,
380 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
381
382 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x0c,
383 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
384
385 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
386 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
387
388 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x0c,
389 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800390
391 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300392 R_C0_B_TASK_HANDLING_CNTL, 0x00,
393 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
394 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
395 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800396
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300397 /* 0x0002 is minimum */
398 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x02,
399 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800400
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300401 /* 0x02d0 = 720 */
402 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
403 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
404
405 /* vwindow start 0x12 = 18 */
406 R_C8_B_VERT_INPUT_WINDOW_START, 0x12,
407 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
408
409 /* vwindow length 0xf8 = 248 */
Mauro Carvalho Chehab97d9e802006-09-03 09:38:11 -0300410 R_CA_B_VERT_INPUT_WINDOW_LENGTH, VRES_60HZ>>1,
411 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, VRES_60HZ>>9,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300412
413 /* hwindow 0x02d0 = 720 */
414 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
415 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
416
417 R_F0_LFCO_PER_LINE, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
418 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0 */
419 R_F5_PULSGEN_LINE_LENGTH, 0xad,
420 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
421
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800422 0x00, 0x00
423};
424
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800425static const unsigned char saa7115_cfg_50hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300426 R_80_GLOBAL_CNTL_1, 0x00,
427 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800428
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300429 R_15_VGATE_START_FID_CHG, 0x37, /* VGATE start */
430 R_16_VGATE_STOP, 0x16,
431 R_17_MISC_VGATE_CONF_AND_MSB, 0x99,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800432
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300433 R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */
434 R_0E_CHROMA_CNTL_1, 0x07,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800435
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300436 R_5A_V_OFF_FOR_SLICER, 0x03, /* standard 50hz value */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800437
438 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300439 R_90_A_TASK_HANDLING_CNTL, 0x81,
440 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
441 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
442 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
443
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800444 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
445 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300446 /* hoffset low (input), 0x0002 is minimum */
447 R_94_A_HORIZ_INPUT_WINDOW_START, 0x00,
448 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
449
450 /* hsize low (input), 0x02d0 = 720 */
451 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
452 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
453
454 R_98_A_VERT_INPUT_WINDOW_START, 0x03,
455 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
456
457 /* vsize 0x12 = 18 */
458 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x12,
459 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
460
461 /* hsize 0x05a0 = 1440 */
462 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
463 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05, /* hsize hi (output) */
464 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x12, /* vsize low (output), 0x12 = 18 */
465 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00, /* vsize hi (output) */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800466
467 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300468 R_C0_B_TASK_HANDLING_CNTL, 0x00,
469 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
470 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
471 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800472
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300473 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
474 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
475 /* hoffset low (input), 0x0002 is minimum. See comment above. */
476 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x00,
477 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800478
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300479 /* hsize 0x02d0 = 720 */
480 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
481 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
482
483 /* voffset 0x16 = 22 */
484 R_C8_B_VERT_INPUT_WINDOW_START, 0x16,
485 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
486
487 /* vsize 0x0120 = 288 */
488 R_CA_B_VERT_INPUT_WINDOW_LENGTH, 0x20,
489 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, 0x01,
490
491 /* hsize 0x02d0 = 720 */
492 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
493 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
494
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300495 R_F0_LFCO_PER_LINE, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
496 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0, (was 0x05) */
497 R_F5_PULSGEN_LINE_LENGTH, 0xb0,
498 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
499
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800500 0x00, 0x00
501};
502
503/* ============== SAA7715 VIDEO templates (end) ======= */
504
505static const unsigned char saa7115_cfg_vbi_on[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300506 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
507 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
508 R_80_GLOBAL_CNTL_1, 0x30, /* Activate both tasks */
509 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
510 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
511
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800512 0x00, 0x00
513};
514
515static const unsigned char saa7115_cfg_vbi_off[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300516 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
517 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
518 R_80_GLOBAL_CNTL_1, 0x20, /* Activate only task "B" */
519 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
520 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
521
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800522 0x00, 0x00
523};
524
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300525
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800526static const unsigned char saa7115_init_misc[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300527 R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300528 R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 0x01,
529 R_84_I_PORT_SIGNAL_DEF, 0x20,
530 R_85_I_PORT_SIGNAL_POLAR, 0x21,
531 R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT, 0xc5,
532 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800533
534 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300535 R_A0_A_HORIZ_PRESCALING, 0x01,
536 R_A1_A_ACCUMULATION_LENGTH, 0x00,
537 R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800538
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300539 /* Configure controls at nominal value*/
540 R_A4_A_LUMA_BRIGHTNESS_CNTL, 0x80,
541 R_A5_A_LUMA_CONTRAST_CNTL, 0x40,
542 R_A6_A_CHROMA_SATURATION_CNTL, 0x40,
543
544 /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
545 R_A8_A_HORIZ_LUMA_SCALING_INC, 0x00,
546 R_A9_A_HORIZ_LUMA_SCALING_INC_MSB, 0x02,
547
548 R_AA_A_HORIZ_LUMA_PHASE_OFF, 0x00,
549
550 /* must be horiz lum scaling / 2 */
551 R_AC_A_HORIZ_CHROMA_SCALING_INC, 0x00,
552 R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB, 0x01,
553
554 /* must be offset luma / 2 */
555 R_AE_A_HORIZ_CHROMA_PHASE_OFF, 0x00,
556
557 R_B0_A_VERT_LUMA_SCALING_INC, 0x00,
558 R_B1_A_VERT_LUMA_SCALING_INC_MSB, 0x04,
559
560 R_B2_A_VERT_CHROMA_SCALING_INC, 0x00,
561 R_B3_A_VERT_CHROMA_SCALING_INC_MSB, 0x04,
562
563 R_B4_A_VERT_SCALING_MODE_CNTL, 0x01,
564
565 R_B8_A_VERT_CHROMA_PHASE_OFF_00, 0x00,
566 R_B9_A_VERT_CHROMA_PHASE_OFF_01, 0x00,
567 R_BA_A_VERT_CHROMA_PHASE_OFF_10, 0x00,
568 R_BB_A_VERT_CHROMA_PHASE_OFF_11, 0x00,
569
570 R_BC_A_VERT_LUMA_PHASE_OFF_00, 0x00,
571 R_BD_A_VERT_LUMA_PHASE_OFF_01, 0x00,
572 R_BE_A_VERT_LUMA_PHASE_OFF_10, 0x00,
573 R_BF_A_VERT_LUMA_PHASE_OFF_11, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800574
575 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300576 R_D0_B_HORIZ_PRESCALING, 0x01,
577 R_D1_B_ACCUMULATION_LENGTH, 0x00,
578 R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800579
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300580 /* Configure controls at nominal value*/
581 R_D4_B_LUMA_BRIGHTNESS_CNTL, 0x80,
582 R_D5_B_LUMA_CONTRAST_CNTL, 0x40,
583 R_D6_B_CHROMA_SATURATION_CNTL, 0x40,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800584
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300585 /* hor lum scaling 0x0400 = 1 */
586 R_D8_B_HORIZ_LUMA_SCALING_INC, 0x00,
587 R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, 0x04,
588
589 R_DA_B_HORIZ_LUMA_PHASE_OFF, 0x00,
590
591 /* must be hor lum scaling / 2 */
592 R_DC_B_HORIZ_CHROMA_SCALING, 0x00,
593 R_DD_B_HORIZ_CHROMA_SCALING_MSB, 0x02,
594
595 /* must be offset luma / 2 */
596 R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA, 0x00,
597
598 R_E0_B_VERT_LUMA_SCALING_INC, 0x00,
599 R_E1_B_VERT_LUMA_SCALING_INC_MSB, 0x04,
600
601 R_E2_B_VERT_CHROMA_SCALING_INC, 0x00,
602 R_E3_B_VERT_CHROMA_SCALING_INC_MSB, 0x04,
603
604 R_E4_B_VERT_SCALING_MODE_CNTL, 0x01,
605
606 R_E8_B_VERT_CHROMA_PHASE_OFF_00, 0x00,
607 R_E9_B_VERT_CHROMA_PHASE_OFF_01, 0x00,
608 R_EA_B_VERT_CHROMA_PHASE_OFF_10, 0x00,
609 R_EB_B_VERT_CHROMA_PHASE_OFF_11, 0x00,
610
611 R_EC_B_VERT_LUMA_PHASE_OFF_00, 0x00,
612 R_ED_B_VERT_LUMA_PHASE_OFF_01, 0x00,
613 R_EE_B_VERT_LUMA_PHASE_OFF_10, 0x00,
614 R_EF_B_VERT_LUMA_PHASE_OFF_11, 0x00,
615
616 R_F2_NOMINAL_PLL2_DTO, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */
617 R_F3_PLL_INCREMENT, 0x46,
618 R_F4_PLL2_STATUS, 0x00,
619 R_F7_PULSE_A_POS_MSB, 0x4b, /* not the recommended settings! */
620 R_F8_PULSE_B_POS, 0x00,
621 R_F9_PULSE_B_POS_MSB, 0x4b,
622 R_FA_PULSE_C_POS, 0x00,
623 R_FB_PULSE_C_POS_MSB, 0x4b,
624
625 /* PLL2 lock detection settings: 71 lines 50% phase error */
626 R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES, 0x88,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800627
628 /* Turn off VBI */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300629 R_40_SLICER_CNTL_1, 0x20, /* No framing code errors allowed. */
630 R_41_LCR_BASE, 0xff,
631 R_41_LCR_BASE+1, 0xff,
632 R_41_LCR_BASE+2, 0xff,
633 R_41_LCR_BASE+3, 0xff,
634 R_41_LCR_BASE+4, 0xff,
635 R_41_LCR_BASE+5, 0xff,
636 R_41_LCR_BASE+6, 0xff,
637 R_41_LCR_BASE+7, 0xff,
638 R_41_LCR_BASE+8, 0xff,
639 R_41_LCR_BASE+9, 0xff,
640 R_41_LCR_BASE+10, 0xff,
641 R_41_LCR_BASE+11, 0xff,
642 R_41_LCR_BASE+12, 0xff,
643 R_41_LCR_BASE+13, 0xff,
644 R_41_LCR_BASE+14, 0xff,
645 R_41_LCR_BASE+15, 0xff,
646 R_41_LCR_BASE+16, 0xff,
647 R_41_LCR_BASE+17, 0xff,
648 R_41_LCR_BASE+18, 0xff,
649 R_41_LCR_BASE+19, 0xff,
650 R_41_LCR_BASE+20, 0xff,
651 R_41_LCR_BASE+21, 0xff,
652 R_41_LCR_BASE+22, 0xff,
653 R_58_PROGRAM_FRAMING_CODE, 0x40,
654 R_59_H_OFF_FOR_SLICER, 0x47,
655 R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF, 0x83,
656 R_5D_DID, 0xbd,
657 R_5E_SDID, 0x35,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800658
Devin Heitmuellerfea551f2010-02-03 00:33:48 -0300659 R_02_INPUT_CNTL_1, 0xc4, /* input tuner -> input 4, amplifier active */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800660
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300661 R_80_GLOBAL_CNTL_1, 0x20, /* enable task B */
662 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
663 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800664 0x00, 0x00
665};
666
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -0300667static int saa711x_odd_parity(u8 c)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800668{
669 c ^= (c >> 4);
670 c ^= (c >> 2);
671 c ^= (c >> 1);
672
673 return c & 1;
674}
675
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300676static int saa711x_decode_vps(u8 *dst, u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800677{
678 static const u8 biphase_tbl[] = {
679 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
680 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
681 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
682 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
683 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
684 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
685 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
686 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
687 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
688 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
689 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
690 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
691 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
692 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
693 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
694 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
695 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
696 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
697 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
698 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
699 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
700 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
701 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
702 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
703 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
704 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
705 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
706 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
707 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
708 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
709 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
710 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
711 };
712 int i;
713 u8 c, err = 0;
714
715 for (i = 0; i < 2 * 13; i += 2) {
716 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
717 c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
718 dst[i / 2] = c;
719 }
720 return err & 0xf0;
721}
722
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300723static int saa711x_decode_wss(u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800724{
725 static const int wss_bits[8] = {
726 0, 0, 0, 1, 0, 1, 1, 1
727 };
728 unsigned char parity;
729 int wss = 0;
730 int i;
731
732 for (i = 0; i < 16; i++) {
733 int b1 = wss_bits[p[i] & 7];
734 int b2 = wss_bits[(p[i] >> 3) & 7];
735
736 if (b1 == b2)
737 return -1;
738 wss |= b2 << i;
739 }
740 parity = wss & 15;
741 parity ^= parity >> 2;
742 parity ^= parity >> 1;
743
744 if (!(parity & 1))
745 return -1;
746
747 return wss;
748}
749
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300750static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800751{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300752 struct saa711x_state *state = to_state(sd);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200753 u32 acpf;
754 u32 acni;
755 u32 hz;
756 u64 f;
Mauro Carvalho Chehab6e6a8b52018-01-04 13:08:56 -0500757 u8 acc = 0; /* reg 0x3a, audio clock control */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800758
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300759 /* Checks for chips that don't have audio clock (saa7111, saa7113) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300760 if (!saa711x_has_reg(state->ident, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300761 return 0;
762
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300763 v4l2_dbg(1, debug, sd, "set audio clock freq: %d\n", freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200764
765 /* sanity check */
766 if (freq < 32000 || freq > 48000)
767 return -EINVAL;
768
769 /* hz is the refresh rate times 100 */
770 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
771 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
772 acpf = (25600 * freq) / hz;
773 /* acni = (256 * freq * 2^23) / crystal_frequency =
774 (freq * 2^(8+23)) / crystal_frequency =
Hans Verkuilb7f82922006-04-02 12:50:42 -0300775 (freq << 31) / crystal_frequency */
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200776 f = freq;
777 f = f << 31;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300778 do_div(f, state->crystal_freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200779 acni = f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300780 if (state->ucgc) {
781 acpf = acpf * state->cgcdiv / 16;
782 acni = acni * state->cgcdiv / 16;
783 acc = 0x80;
784 if (state->cgcdiv == 3)
785 acc |= 0x40;
786 }
787 if (state->apll)
788 acc |= 0x08;
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200789
Hans Verkuil15890372013-03-11 03:47:25 -0300790 if (state->double_asclk) {
791 acpf <<= 1;
792 acni <<= 1;
793 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300794 saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
Hans Verkuil15890372013-03-11 03:47:25 -0300795 saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10 << state->double_asclk);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300796 saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300797
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300798 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
799 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300800 (acpf >> 8) & 0xff);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300801 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300802 (acpf >> 16) & 0x03);
803
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300804 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
805 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
806 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800807 state->audclk_freq = freq;
808 return 0;
809}
810
Hans Verkuile3560542010-05-24 10:00:52 -0300811static int saa711x_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800812{
Hans Verkuile3560542010-05-24 10:00:52 -0300813 struct v4l2_subdev *sd = to_sd(ctrl);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300814 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800815
816 switch (ctrl->id) {
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300817 case V4L2_CID_CHROMA_AGC:
Hans Verkuile3560542010-05-24 10:00:52 -0300818 /* chroma gain cluster */
Hans Verkuilddac5c12011-06-10 05:43:34 -0300819 if (state->agc->val)
820 state->gain->val =
Hans Verkuile3560542010-05-24 10:00:52 -0300821 saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL) & 0x7f;
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300822 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800823 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800824 return 0;
825}
826
Hans Verkuile3560542010-05-24 10:00:52 -0300827static int saa711x_s_ctrl(struct v4l2_ctrl *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800828{
Hans Verkuile3560542010-05-24 10:00:52 -0300829 struct v4l2_subdev *sd = to_sd(ctrl);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300830 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800831
832 switch (ctrl->id) {
833 case V4L2_CID_BRIGHTNESS:
Hans Verkuile3560542010-05-24 10:00:52 -0300834 saa711x_write(sd, R_0A_LUMA_BRIGHT_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800835 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300836
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800837 case V4L2_CID_CONTRAST:
Hans Verkuile3560542010-05-24 10:00:52 -0300838 saa711x_write(sd, R_0B_LUMA_CONTRAST_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800839 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300840
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800841 case V4L2_CID_SATURATION:
Hans Verkuile3560542010-05-24 10:00:52 -0300842 saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800843 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300844
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800845 case V4L2_CID_HUE:
Hans Verkuile3560542010-05-24 10:00:52 -0300846 saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800847 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300848
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300849 case V4L2_CID_CHROMA_AGC:
Hans Verkuile3560542010-05-24 10:00:52 -0300850 /* chroma gain cluster */
851 if (state->agc->val)
852 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val);
853 else
854 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val | 0x80);
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300855 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300856
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800857 default:
858 return -EINVAL;
859 }
860
861 return 0;
862}
863
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300864static int saa711x_set_size(struct v4l2_subdev *sd, int width, int height)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300865{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300866 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300867 int HPSC, HFSC;
868 int VSCY;
869 int res;
870 int is_50hz = state->std & V4L2_STD_625_50;
871 int Vsrc = is_50hz ? 576 : 480;
872
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300873 v4l2_dbg(1, debug, sd, "decoder set size to %ix%i\n", width, height);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300874
875 /* FIXME need better bounds checking here */
876 if ((width < 1) || (width > 1440))
877 return -EINVAL;
878 if ((height < 1) || (height > Vsrc))
879 return -EINVAL;
880
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300881 if (!saa711x_has_reg(state->ident, R_D0_B_HORIZ_PRESCALING)) {
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300882 /* Decoder only supports 720 columns and 480 or 576 lines */
883 if (width != 720)
884 return -EINVAL;
885 if (height != Vsrc)
886 return -EINVAL;
887 }
888
889 state->width = width;
890 state->height = height;
891
892 if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
893 return 0;
894
895 /* probably have a valid size, let's set it */
896 /* Set output width/height */
897 /* width */
898
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300899 saa711x_write(sd, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300900 (u8) (width & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300901 saa711x_write(sd, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300902 (u8) ((width >> 8) & 0xff));
903
904 /* Vertical Scaling uses height/2 */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300905 res = height / 2;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300906
907 /* On 60Hz, it is using a higher Vertical Output Size */
908 if (!is_50hz)
Hans Verkuild0d30c02006-11-25 09:45:50 -0300909 res += (VRES_60HZ - 480) >> 1;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300910
911 /* height */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300912 saa711x_write(sd, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300913 (u8) (res & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300914 saa711x_write(sd, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300915 (u8) ((res >> 8) & 0xff));
916
917 /* Scaling settings */
918 /* Hprescaler is floor(inres/outres) */
919 HPSC = (int)(720 / width);
920 /* 0 is not allowed (div. by zero) */
921 HPSC = HPSC ? HPSC : 1;
922 HFSC = (int)((1024 * 720) / (HPSC * width));
923 /* FIXME hardcodes to "Task B"
924 * write H prescaler integer */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300925 saa711x_write(sd, R_D0_B_HORIZ_PRESCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300926 (u8) (HPSC & 0x3f));
927
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300928 v4l2_dbg(1, debug, sd, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300929 /* write H fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300930 saa711x_write(sd, R_D8_B_HORIZ_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300931 (u8) (HFSC & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300932 saa711x_write(sd, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300933 (u8) ((HFSC >> 8) & 0xff));
934 /* write H fine-scaling (chrominance)
935 * must be lum/2, so i'll just bitshift :) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300936 saa711x_write(sd, R_DC_B_HORIZ_CHROMA_SCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300937 (u8) ((HFSC >> 1) & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300938 saa711x_write(sd, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300939 (u8) ((HFSC >> 9) & 0xff));
940
941 VSCY = (int)((1024 * Vsrc) / height);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300942 v4l2_dbg(1, debug, sd, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300943
944 /* Correct Contrast and Luminance */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300945 saa711x_write(sd, R_D5_B_LUMA_CONTRAST_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300946 (u8) (64 * 1024 / VSCY));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300947 saa711x_write(sd, R_D6_B_CHROMA_SATURATION_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300948 (u8) (64 * 1024 / VSCY));
949
950 /* write V fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300951 saa711x_write(sd, R_E0_B_VERT_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300952 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300953 saa711x_write(sd, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300954 (u8) ((VSCY >> 8) & 0xff));
955 /* write V fine-scaling (chrominance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300956 saa711x_write(sd, R_E2_B_VERT_CHROMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300957 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300958 saa711x_write(sd, R_E3_B_VERT_CHROMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300959 (u8) ((VSCY >> 8) & 0xff));
960
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300961 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300962
963 /* Activates task "B" */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300964 saa711x_write(sd, R_80_GLOBAL_CNTL_1,
965 saa711x_read(sd, R_80_GLOBAL_CNTL_1) | 0x20);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300966
967 return 0;
968}
969
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300970static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800971{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300972 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800973
Hans Verkuil30b54d52006-01-09 15:25:43 -0200974 /* Prevent unnecessary standard changes. During a standard
975 change the I-Port is temporarily disabled. Any devices
976 reading from that port can get confused.
Hans Verkuilbccfa442009-03-30 06:55:27 -0300977 Note that s_std is also used to switch from
978 radio to TV mode, so if a s_std is broadcast to
Hans Verkuil30b54d52006-01-09 15:25:43 -0200979 all I2C devices then you do not want to have an unwanted
980 side-effect here. */
981 if (std == state->std)
982 return;
983
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300984 state->std = std;
985
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800986 // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
987 if (std & V4L2_STD_525_60) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300988 v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n");
Jon Arne Jørgensen8b77dfd2013-08-03 09:19:35 -0300989 if (state->ident == GM7113C) {
990 u8 reg = saa711x_read(sd, R_08_SYNC_CNTL);
991 reg &= ~(SAA7113_R_08_FSEL | SAA7113_R_08_AUFD);
992 reg |= SAA7113_R_08_FSEL;
993 saa711x_write(sd, R_08_SYNC_CNTL, reg);
994 } else {
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300995 saa711x_writeregs(sd, saa7115_cfg_60hz_video);
Jon Arne Jørgensen8b77dfd2013-08-03 09:19:35 -0300996 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300997 saa711x_set_size(sd, 720, 480);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800998 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300999 v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n");
Jon Arne Jørgensen8b77dfd2013-08-03 09:19:35 -03001000 if (state->ident == GM7113C) {
1001 u8 reg = saa711x_read(sd, R_08_SYNC_CNTL);
1002 reg &= ~(SAA7113_R_08_FSEL | SAA7113_R_08_AUFD);
1003 saa711x_write(sd, R_08_SYNC_CNTL, reg);
1004 } else {
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -03001005 saa711x_writeregs(sd, saa7115_cfg_50hz_video);
Jon Arne Jørgensen8b77dfd2013-08-03 09:19:35 -03001006 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001007 saa711x_set_size(sd, 720, 576);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001008 }
1009
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001010 /* Register 0E - Bits D6-D4 on NO-AUTO mode
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001011 (SAA7111 and SAA7113 doesn't have auto mode)
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001012 50 Hz / 625 lines 60 Hz / 525 lines
1013 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz)
1014 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz)
1015 010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz)
1016 011 NTSC N (3.58MHz) PAL M (3.58MHz)
1017 100 reserved NTSC-Japan (3.58MHz)
1018 */
Hans Verkuile1277112013-05-29 06:59:51 -03001019 if (state->ident <= SAA7113 ||
1020 state->ident == GM7113C) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001021 u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001022
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -03001023 if (std == V4L2_STD_PAL_M) {
Hans Verkuil01342352006-03-25 08:19:47 -03001024 reg |= 0x30;
Hans Verkuile0028022008-04-22 14:45:51 -03001025 } else if (std == V4L2_STD_PAL_Nc) {
Hans Verkuil01342352006-03-25 08:19:47 -03001026 reg |= 0x20;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -03001027 } else if (std == V4L2_STD_PAL_60) {
Hans Verkuil01342352006-03-25 08:19:47 -03001028 reg |= 0x10;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -03001029 } else if (std == V4L2_STD_NTSC_M_JP) {
Hans Verkuil01342352006-03-25 08:19:47 -03001030 reg |= 0x40;
Mauro Carvalho Chehaba9aaec42007-03-13 13:41:49 -03001031 } else if (std & V4L2_STD_SECAM) {
Pádraig Bradyfc2fa312006-10-09 08:02:17 -03001032 reg |= 0x50;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001033 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001034 saa711x_write(sd, R_0E_CHROMA_CNTL_1, reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001035 } else {
1036 /* restart task B if needed */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001037 int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001038
Hans Verkuile1277112013-05-29 06:59:51 -03001039 if (taskb && state->ident == SAA7114)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001040 saa711x_writeregs(sd, saa7115_cfg_vbi_on);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001041
1042 /* switch audio mode too! */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001043 saa711x_s_clock_freq(sd, state->audclk_freq);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001044 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001045}
1046
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001047/* setup the sliced VBI lcr registers according to the sliced VBI format */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001048static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001049{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001050 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001051 int is_50hz = (state->std & V4L2_STD_625_50);
1052 u8 lcr[24];
1053 int i, x;
1054
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001055#if 1
1056 /* saa7113/7114/7118 VBI support are experimental */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001057 if (!saa711x_has_reg(state->ident, R_41_LCR_BASE))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001058 return;
1059
1060#else
1061 /* SAA7113 and SAA7118 also should support VBI - Need testing */
Hans Verkuile1277112013-05-29 06:59:51 -03001062 if (state->ident != SAA7115)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001063 return;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001064#endif
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001065
1066 for (i = 0; i <= 23; i++)
1067 lcr[i] = 0xff;
1068
Hans Verkuila8b86432008-10-04 08:05:30 -03001069 if (fmt == NULL) {
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001070 /* raw VBI */
1071 if (is_50hz)
1072 for (i = 6; i <= 23; i++)
1073 lcr[i] = 0xdd;
1074 else
1075 for (i = 10; i <= 21; i++)
1076 lcr[i] = 0xdd;
1077 } else {
1078 /* sliced VBI */
1079 /* first clear lines that cannot be captured */
1080 if (is_50hz) {
1081 for (i = 0; i <= 5; i++)
1082 fmt->service_lines[0][i] =
1083 fmt->service_lines[1][i] = 0;
1084 }
1085 else {
1086 for (i = 0; i <= 9; i++)
1087 fmt->service_lines[0][i] =
1088 fmt->service_lines[1][i] = 0;
1089 for (i = 22; i <= 23; i++)
1090 fmt->service_lines[0][i] =
1091 fmt->service_lines[1][i] = 0;
1092 }
1093
1094 /* Now set the lcr values according to the specified service */
1095 for (i = 6; i <= 23; i++) {
1096 lcr[i] = 0;
1097 for (x = 0; x <= 1; x++) {
1098 switch (fmt->service_lines[1-x][i]) {
1099 case 0:
1100 lcr[i] |= 0xf << (4 * x);
1101 break;
Hans Verkuil9bc74002006-03-29 18:02:51 -03001102 case V4L2_SLICED_TELETEXT_B:
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001103 lcr[i] |= 1 << (4 * x);
1104 break;
1105 case V4L2_SLICED_CAPTION_525:
1106 lcr[i] |= 4 << (4 * x);
1107 break;
1108 case V4L2_SLICED_WSS_625:
1109 lcr[i] |= 5 << (4 * x);
1110 break;
1111 case V4L2_SLICED_VPS:
1112 lcr[i] |= 7 << (4 * x);
1113 break;
1114 }
1115 }
1116 }
1117 }
1118
1119 /* write the lcr registers */
1120 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001121 saa711x_write(sd, i - 2 + R_41_LCR_BASE, lcr[i]);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001122 }
1123
1124 /* enable/disable raw VBI capturing */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001125 saa711x_writeregs(sd, fmt == NULL ?
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001126 saa7115_cfg_vbi_on :
1127 saa7115_cfg_vbi_off);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001128}
1129
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001130static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *sliced)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001131{
1132 static u16 lcr2vbi[] = {
Hans Verkuil9bc74002006-03-29 18:02:51 -03001133 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001134 0, V4L2_SLICED_CAPTION_525, /* 4 */
1135 V4L2_SLICED_WSS_625, 0, /* 5 */
1136 V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
1137 0, 0, 0, 0
1138 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001139 int i;
1140
Hans Verkuil30634e82012-09-05 10:38:10 -03001141 memset(sliced->service_lines, 0, sizeof(sliced->service_lines));
1142 sliced->service_set = 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001143 /* done if using raw VBI */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001144 if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001145 return 0;
1146 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001147 u8 v = saa711x_read(sd, i - 2 + R_41_LCR_BASE);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001148
1149 sliced->service_lines[0][i] = lcr2vbi[v >> 4];
1150 sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
1151 sliced->service_set |=
1152 sliced->service_lines[0][i] | sliced->service_lines[1][i];
1153 }
1154 return 0;
1155}
1156
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001157static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
1158{
1159 saa711x_set_lcr(sd, NULL);
1160 return 0;
1161}
1162
1163static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
1164{
1165 saa711x_set_lcr(sd, fmt);
1166 return 0;
1167}
1168
Hans Verkuil6e80c472015-03-21 09:39:09 -03001169static int saa711x_set_fmt(struct v4l2_subdev *sd,
1170 struct v4l2_subdev_pad_config *cfg,
1171 struct v4l2_subdev_format *format)
Hans Verkuilc463d932010-05-09 09:47:23 -03001172{
Hans Verkuil6e80c472015-03-21 09:39:09 -03001173 struct v4l2_mbus_framefmt *fmt = &format->format;
1174
1175 if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED)
Hans Verkuilc463d932010-05-09 09:47:23 -03001176 return -EINVAL;
1177 fmt->field = V4L2_FIELD_INTERLACED;
1178 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
Hans Verkuil6e80c472015-03-21 09:39:09 -03001179 if (format->which == V4L2_SUBDEV_FORMAT_TRY)
1180 return 0;
Hans Verkuilc463d932010-05-09 09:47:23 -03001181 return saa711x_set_size(sd, fmt->width, fmt->height);
1182}
1183
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001184/* Decode the sliced VBI data stream as created by the saa7115.
1185 The format is described in the saa7115 datasheet in Tables 25 and 26
1186 and in Figure 33.
1187 The current implementation uses SAV/EAV codes and not the ancillary data
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001188 headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001189 code. */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001190static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001191{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001192 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001193 static const char vbi_no_data_pattern[] = {
1194 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
1195 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001196 u8 *p = vbi->p;
1197 u32 wss;
1198 int id1, id2; /* the ID1 and ID2 bytes from the internal header */
1199
1200 vbi->type = 0; /* mark result as a failure */
1201 id1 = p[2];
1202 id2 = p[3];
1203 /* Note: the field bit is inverted for 60 Hz video */
1204 if (state->std & V4L2_STD_525_60)
1205 id1 ^= 0x40;
1206
1207 /* Skip internal header, p now points to the start of the payload */
1208 p += 4;
1209 vbi->p = p;
1210
1211 /* calculate field and line number of the VBI packet (1-23) */
1212 vbi->is_second_field = ((id1 & 0x40) != 0);
1213 vbi->line = (id1 & 0x3f) << 3;
1214 vbi->line |= (id2 & 0x70) >> 4;
1215
1216 /* Obtain data type */
1217 id2 &= 0xf;
1218
1219 /* If the VBI slicer does not detect any signal it will fill up
1220 the payload buffer with 0xa0 bytes. */
1221 if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001222 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001223
1224 /* decode payloads */
1225 switch (id2) {
1226 case 1:
Hans Verkuil9bc74002006-03-29 18:02:51 -03001227 vbi->type = V4L2_SLICED_TELETEXT_B;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001228 break;
1229 case 4:
Mauro Carvalho Chehab59ba9152006-08-30 05:34:36 -03001230 if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001231 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001232 vbi->type = V4L2_SLICED_CAPTION_525;
1233 break;
1234 case 5:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001235 wss = saa711x_decode_wss(p);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001236 if (wss == -1)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001237 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001238 p[0] = wss & 0xff;
1239 p[1] = wss >> 8;
1240 vbi->type = V4L2_SLICED_WSS_625;
1241 break;
1242 case 7:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001243 if (saa711x_decode_vps(p, p) != 0)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001244 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001245 vbi->type = V4L2_SLICED_VPS;
1246 break;
1247 default:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001248 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001249 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001250 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001251}
1252
1253/* ============ SAA7115 AUDIO settings (end) ============= */
1254
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001255static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001256{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001257 struct saa711x_state *state = to_state(sd);
1258 int status;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001259
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001260 if (state->radio)
1261 return 0;
1262 status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001263
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001264 v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status);
1265 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1266 return 0;
1267}
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001268
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001269static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1270{
1271 struct saa711x_state *state = to_state(sd);
1272
1273 state->radio = 0;
1274 saa711x_set_v4lstd(sd, std);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001275 return 0;
1276}
1277
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001278static int saa711x_s_radio(struct v4l2_subdev *sd)
1279{
1280 struct saa711x_state *state = to_state(sd);
1281
1282 state->radio = 1;
1283 return 0;
1284}
1285
Hans Verkuil5325b422009-04-02 11:26:22 -03001286static int saa711x_s_routing(struct v4l2_subdev *sd,
1287 u32 input, u32 output, u32 config)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001288{
1289 struct saa711x_state *state = to_state(sd);
Hans Verkuile1277112013-05-29 06:59:51 -03001290 u8 mask = (state->ident <= SAA7111A) ? 0xf8 : 0xf0;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001291
Hans Verkuil5325b422009-04-02 11:26:22 -03001292 v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n",
1293 input, output);
1294
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001295 /* saa7111/3 does not have these inputs */
Hans Verkuile1277112013-05-29 06:59:51 -03001296 if ((state->ident <= SAA7113 ||
1297 state->ident == GM7113C) &&
Hans Verkuil5325b422009-04-02 11:26:22 -03001298 (input == SAA7115_COMPOSITE4 ||
1299 input == SAA7115_COMPOSITE5)) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001300 return -EINVAL;
1301 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001302 if (input > SAA7115_SVIDEO3)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001303 return -EINVAL;
Hans Verkuil5325b422009-04-02 11:26:22 -03001304 if (state->input == input && state->output == output)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001305 return 0;
1306 v4l2_dbg(1, debug, sd, "now setting %s input %s output\n",
Hans Verkuil5325b422009-04-02 11:26:22 -03001307 (input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite",
1308 (output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
1309 state->input = input;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001310
1311 /* saa7111 has slightly different input numbering */
Hans Verkuile1277112013-05-29 06:59:51 -03001312 if (state->ident <= SAA7111A) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001313 if (input >= SAA7115_COMPOSITE4)
1314 input -= 2;
1315 /* saa7111 specific */
1316 saa711x_write(sd, R_10_CHROMA_CNTL_2,
1317 (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001318 ((output & 0xc0) ^ 0x40));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001319 saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL,
1320 (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001321 ((output & 2) ? 0x0a : 0));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001322 }
1323
1324 /* select mode */
1325 saa711x_write(sd, R_02_INPUT_CNTL_1,
1326 (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) |
1327 input);
1328
1329 /* bypass chrominance trap for S-Video modes */
1330 saa711x_write(sd, R_09_LUMA_CNTL,
1331 (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) |
1332 (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
1333
Hans Verkuil5325b422009-04-02 11:26:22 -03001334 state->output = output;
Hans Verkuile1277112013-05-29 06:59:51 -03001335 if (state->ident == SAA7114 ||
1336 state->ident == SAA7115) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001337 saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
1338 (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
1339 (state->output & 0x01));
1340 }
Hans Verkuile1277112013-05-29 06:59:51 -03001341 if (state->ident > SAA7111A) {
Hans Verkuila0fc5882013-03-08 11:22:03 -03001342 if (config & SAA7115_IDQ_IS_DEFAULT)
1343 saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x20);
1344 else
1345 saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x21);
1346 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001347 return 0;
1348}
1349
1350static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val)
1351{
1352 struct saa711x_state *state = to_state(sd);
1353
Hans Verkuile1277112013-05-29 06:59:51 -03001354 if (state->ident > SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001355 return -EINVAL;
1356 saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) |
1357 (val ? 0x80 : 0));
1358 return 0;
1359}
1360
1361static int saa711x_s_stream(struct v4l2_subdev *sd, int enable)
1362{
1363 struct saa711x_state *state = to_state(sd);
1364
1365 v4l2_dbg(1, debug, sd, "%s output\n",
1366 enable ? "enable" : "disable");
1367
Hans Verkuil674a3232009-02-18 12:22:16 -03001368 if (state->enable == enable)
1369 return 0;
1370 state->enable = enable;
1371 if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED))
1372 return 0;
1373 saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001374 return 0;
1375}
1376
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001377static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001378{
1379 struct saa711x_state *state = to_state(sd);
1380
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001381 if (freq != SAA7115_FREQ_32_11_MHZ && freq != SAA7115_FREQ_24_576_MHZ)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001382 return -EINVAL;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001383 state->crystal_freq = freq;
Hans Verkuil15890372013-03-11 03:47:25 -03001384 state->double_asclk = flags & SAA7115_FREQ_FL_DOUBLE_ASCLK;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001385 state->cgcdiv = (flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
Hans Verkuil15890372013-03-11 03:47:25 -03001386 state->ucgc = flags & SAA7115_FREQ_FL_UCGC;
1387 state->apll = flags & SAA7115_FREQ_FL_APLL;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001388 saa711x_s_clock_freq(sd, state->audclk_freq);
1389 return 0;
1390}
1391
1392static int saa711x_reset(struct v4l2_subdev *sd, u32 val)
1393{
1394 v4l2_dbg(1, debug, sd, "decoder RESET\n");
1395 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
1396 return 0;
1397}
1398
1399static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data)
1400{
1401 /* Note: the internal field ID is inverted for NTSC,
1402 so data->field 0 maps to the saa7115 even field,
1403 whereas for PAL it maps to the saa7115 odd field. */
1404 switch (data->id) {
1405 case V4L2_SLICED_WSS_625:
1406 if (saa711x_read(sd, 0x6b) & 0xc0)
1407 return -EIO;
1408 data->data[0] = saa711x_read(sd, 0x6c);
1409 data->data[1] = saa711x_read(sd, 0x6d);
1410 return 0;
1411 case V4L2_SLICED_CAPTION_525:
1412 if (data->field == 0) {
1413 /* CC */
1414 if (saa711x_read(sd, 0x66) & 0x30)
1415 return -EIO;
1416 data->data[0] = saa711x_read(sd, 0x69);
1417 data->data[1] = saa711x_read(sd, 0x6a);
1418 return 0;
1419 }
1420 /* XDS */
1421 if (saa711x_read(sd, 0x66) & 0xc0)
1422 return -EIO;
1423 data->data[0] = saa711x_read(sd, 0x67);
1424 data->data[1] = saa711x_read(sd, 0x68);
1425 return 0;
1426 default:
1427 return -EINVAL;
1428 }
1429}
1430
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001431static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
1432{
1433 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001434 int reg1f, reg1e;
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001435
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001436 /*
1437 * The V4L2 core already initializes std with all supported
1438 * Standards. All driver needs to do is to mask it, to remove
1439 * standards that don't apply from the mask
1440 */
1441
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001442 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuilc875dee2013-03-10 09:59:37 -03001443
Hans Verkuile1277112013-05-29 06:59:51 -03001444 if (state->ident == SAA7115) {
Hans Verkuilc875dee2013-03-10 09:59:37 -03001445 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1446
1447 v4l2_dbg(1, debug, sd, "Status byte 1 (0x1e)=0x%02x\n", reg1e);
1448
1449 switch (reg1e & 0x03) {
1450 case 1:
1451 *std &= V4L2_STD_NTSC;
1452 break;
1453 case 2:
1454 /*
1455 * V4L2_STD_PAL just cover the european PAL standards.
1456 * This is wrong, as the device could also be using an
1457 * other PAL standard.
1458 */
1459 *std &= V4L2_STD_PAL | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc |
1460 V4L2_STD_PAL_M | V4L2_STD_PAL_60;
1461 break;
1462 case 3:
1463 *std &= V4L2_STD_SECAM;
1464 break;
1465 default:
Hans Verkuilaf1f7282013-05-29 10:18:58 -03001466 *std = V4L2_STD_UNKNOWN;
Hans Verkuilc875dee2013-03-10 09:59:37 -03001467 /* Can't detect anything */
1468 break;
1469 }
1470 }
1471
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001472 v4l2_dbg(1, debug, sd, "Status byte 2 (0x1f)=0x%02x\n", reg1f);
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001473
1474 /* horizontal/vertical not locked */
Hans Verkuilaf1f7282013-05-29 10:18:58 -03001475 if (reg1f & 0x40) {
1476 *std = V4L2_STD_UNKNOWN;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001477 goto ret;
Hans Verkuilaf1f7282013-05-29 10:18:58 -03001478 }
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001479
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001480 if (reg1f & 0x20)
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001481 *std &= V4L2_STD_525_60;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001482 else
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001483 *std &= V4L2_STD_625_50;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001484
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001485ret:
1486 v4l2_dbg(1, debug, sd, "detected std mask = %08Lx\n", *std);
1487
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001488 return 0;
1489}
1490
1491static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status)
1492{
1493 struct saa711x_state *state = to_state(sd);
1494 int reg1e = 0x80;
1495 int reg1f;
1496
1497 *status = V4L2_IN_ST_NO_SIGNAL;
Hans Verkuile1277112013-05-29 06:59:51 -03001498 if (state->ident == SAA7115)
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001499 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1500 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1501 if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80)
1502 *status = 0;
1503 return 0;
1504}
1505
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001506#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001507static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001508{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001509 reg->val = saa711x_read(sd, reg->reg & 0xff);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001510 reg->size = 1;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001511 return 0;
1512}
1513
Hans Verkuil977ba3b12013-03-24 08:28:46 -03001514static int saa711x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001515{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001516 saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff);
1517 return 0;
1518}
1519#endif
1520
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001521static int saa711x_log_status(struct v4l2_subdev *sd)
1522{
1523 struct saa711x_state *state = to_state(sd);
1524 int reg1e, reg1f;
1525 int signalOk;
1526 int vcr;
1527
1528 v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq);
Hans Verkuile1277112013-05-29 06:59:51 -03001529 if (state->ident != SAA7115) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001530 /* status for the saa7114 */
1531 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1532 signalOk = (reg1f & 0xc1) == 0x81;
1533 v4l2_info(sd, "Video signal: %s\n", signalOk ? "ok" : "bad");
1534 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1535 return 0;
1536 }
1537
1538 /* status for the saa7115 */
1539 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1540 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1541
1542 signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
1543 vcr = !(reg1f & 0x10);
1544
1545 if (state->input >= 6)
1546 v4l2_info(sd, "Input: S-Video %d\n", state->input - 6);
1547 else
1548 v4l2_info(sd, "Input: Composite %d\n", state->input);
1549 v4l2_info(sd, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
1550 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1551
1552 switch (reg1e & 0x03) {
1553 case 1:
1554 v4l2_info(sd, "Detected format: NTSC\n");
1555 break;
1556 case 2:
1557 v4l2_info(sd, "Detected format: PAL\n");
1558 break;
1559 case 3:
1560 v4l2_info(sd, "Detected format: SECAM\n");
1561 break;
1562 default:
1563 v4l2_info(sd, "Detected format: BW/No color\n");
1564 break;
1565 }
1566 v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height);
Hans Verkuile3560542010-05-24 10:00:52 -03001567 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001568 return 0;
1569}
1570
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001571/* ----------------------------------------------------------------------- */
1572
Hans Verkuile3560542010-05-24 10:00:52 -03001573static const struct v4l2_ctrl_ops saa711x_ctrl_ops = {
1574 .s_ctrl = saa711x_s_ctrl,
1575 .g_volatile_ctrl = saa711x_g_volatile_ctrl,
1576};
1577
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001578static const struct v4l2_subdev_core_ops saa711x_core_ops = {
1579 .log_status = saa711x_log_status,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001580 .reset = saa711x_reset,
1581 .s_gpio = saa711x_s_gpio,
1582#ifdef CONFIG_VIDEO_ADV_DEBUG
1583 .g_register = saa711x_g_register,
1584 .s_register = saa711x_s_register,
1585#endif
1586};
1587
1588static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001589 .s_radio = saa711x_s_radio,
1590 .g_tuner = saa711x_g_tuner,
1591};
1592
1593static const struct v4l2_subdev_audio_ops saa711x_audio_ops = {
1594 .s_clock_freq = saa711x_s_clock_freq,
1595};
1596
1597static const struct v4l2_subdev_video_ops saa711x_video_ops = {
Laurent Pinchart8774bed2014-04-28 16:53:01 -03001598 .s_std = saa711x_s_std,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001599 .s_routing = saa711x_s_routing,
1600 .s_crystal_freq = saa711x_s_crystal_freq,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001601 .s_stream = saa711x_s_stream,
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001602 .querystd = saa711x_querystd,
1603 .g_input_status = saa711x_g_input_status,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001604};
1605
Hans Verkuil32cd5272010-03-14 09:57:30 -03001606static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = {
1607 .g_vbi_data = saa711x_g_vbi_data,
1608 .decode_vbi_line = saa711x_decode_vbi_line,
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001609 .g_sliced_fmt = saa711x_g_sliced_fmt,
1610 .s_sliced_fmt = saa711x_s_sliced_fmt,
1611 .s_raw_fmt = saa711x_s_raw_fmt,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001612};
1613
Hans Verkuil6e80c472015-03-21 09:39:09 -03001614static const struct v4l2_subdev_pad_ops saa711x_pad_ops = {
1615 .set_fmt = saa711x_set_fmt,
1616};
1617
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001618static const struct v4l2_subdev_ops saa711x_ops = {
1619 .core = &saa711x_core_ops,
1620 .tuner = &saa711x_tuner_ops,
1621 .audio = &saa711x_audio_ops,
1622 .video = &saa711x_video_ops,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001623 .vbi = &saa711x_vbi_ops,
Hans Verkuil6e80c472015-03-21 09:39:09 -03001624 .pad = &saa711x_pad_ops,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001625};
1626
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001627#define CHIP_VER_SIZE 16
1628
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001629/* ----------------------------------------------------------------------- */
1630
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001631static void saa711x_write_platform_data(struct saa711x_state *state,
1632 struct saa7115_platform_data *data)
1633{
1634 struct v4l2_subdev *sd = &state->sd;
1635 u8 work;
1636
1637 if (state->ident != GM7113C &&
1638 state->ident != SAA7113)
1639 return;
1640
1641 if (data->saa7113_r08_htc) {
1642 work = saa711x_read(sd, R_08_SYNC_CNTL);
1643 work &= ~SAA7113_R_08_HTC_MASK;
1644 work |= ((*data->saa7113_r08_htc) << SAA7113_R_08_HTC_OFFSET);
1645 saa711x_write(sd, R_08_SYNC_CNTL, work);
1646 }
1647
1648 if (data->saa7113_r10_vrln) {
1649 work = saa711x_read(sd, R_10_CHROMA_CNTL_2);
1650 work &= ~SAA7113_R_10_VRLN_MASK;
1651 if (*data->saa7113_r10_vrln)
1652 work |= (1 << SAA7113_R_10_VRLN_OFFSET);
1653 saa711x_write(sd, R_10_CHROMA_CNTL_2, work);
1654 }
1655
1656 if (data->saa7113_r10_ofts) {
1657 work = saa711x_read(sd, R_10_CHROMA_CNTL_2);
1658 work &= ~SAA7113_R_10_OFTS_MASK;
1659 work |= (*data->saa7113_r10_ofts << SAA7113_R_10_OFTS_OFFSET);
1660 saa711x_write(sd, R_10_CHROMA_CNTL_2, work);
1661 }
1662
1663 if (data->saa7113_r12_rts0) {
1664 work = saa711x_read(sd, R_12_RT_SIGNAL_CNTL);
1665 work &= ~SAA7113_R_12_RTS0_MASK;
1666 work |= (*data->saa7113_r12_rts0 << SAA7113_R_12_RTS0_OFFSET);
1667
1668 /* According to the datasheet,
1669 * SAA7113_RTS_DOT_IN should only be used on RTS1 */
1670 WARN_ON(*data->saa7113_r12_rts0 == SAA7113_RTS_DOT_IN);
1671 saa711x_write(sd, R_12_RT_SIGNAL_CNTL, work);
1672 }
1673
1674 if (data->saa7113_r12_rts1) {
1675 work = saa711x_read(sd, R_12_RT_SIGNAL_CNTL);
1676 work &= ~SAA7113_R_12_RTS1_MASK;
1677 work |= (*data->saa7113_r12_rts1 << SAA7113_R_12_RTS1_OFFSET);
1678 saa711x_write(sd, R_12_RT_SIGNAL_CNTL, work);
1679 }
1680
1681 if (data->saa7113_r13_adlsb) {
1682 work = saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL);
1683 work &= ~SAA7113_R_13_ADLSB_MASK;
1684 if (*data->saa7113_r13_adlsb)
1685 work |= (1 << SAA7113_R_13_ADLSB_OFFSET);
1686 saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL, work);
1687 }
1688}
1689
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001690/**
1691 * saa711x_detect_chip - Detects the saa711x (or clone) variant
1692 * @client: I2C client structure.
1693 * @id: I2C device ID structure.
1694 * @name: Name of the device to be filled.
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001695 *
1696 * Detects the Philips/NXP saa711x chip, or some clone of it.
1697 * if 'id' is NULL or id->driver_data is equal to 1, it auto-probes
1698 * the analog demod.
1699 * If the tuner is not found, it returns -ENODEV.
1700 * If auto-detection is disabled and the tuner doesn't match what it was
Jonathan McCrohan39c1cb22013-10-20 21:34:01 -03001701 * required, it returns -EINVAL and fills 'name'.
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001702 * If the chip is found, it returns the chip ID and fills 'name'.
1703 */
1704static int saa711x_detect_chip(struct i2c_client *client,
1705 const struct i2c_device_id *id,
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001706 char *name)
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001707{
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001708 char chip_ver[CHIP_VER_SIZE];
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001709 char chip_id;
1710 int i;
1711 int autodetect;
1712
1713 autodetect = !id || id->driver_data == 1;
1714
1715 /* Read the chip version register */
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001716 for (i = 0; i < CHIP_VER_SIZE; i++) {
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001717 i2c_smbus_write_byte_data(client, 0, i);
1718 chip_ver[i] = i2c_smbus_read_byte_data(client, 0);
1719 name[i] = (chip_ver[i] & 0x0f) + '0';
1720 if (name[i] > '9')
1721 name[i] += 'a' - '9' - 1;
1722 }
1723 name[i] = '\0';
1724
1725 /* Check if it is a Philips/NXP chip */
1726 if (!memcmp(name + 1, "f711", 4)) {
1727 chip_id = name[5];
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001728 snprintf(name, CHIP_VER_SIZE, "saa711%c", chip_id);
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001729
1730 if (!autodetect && strcmp(name, id->name))
1731 return -EINVAL;
1732
1733 switch (chip_id) {
1734 case '1':
1735 if (chip_ver[0] & 0xf0) {
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001736 snprintf(name, CHIP_VER_SIZE, "saa711%ca", chip_id);
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001737 v4l_info(client, "saa7111a variant found\n");
Hans Verkuile1277112013-05-29 06:59:51 -03001738 return SAA7111A;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001739 }
Hans Verkuile1277112013-05-29 06:59:51 -03001740 return SAA7111;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001741 case '3':
Hans Verkuile1277112013-05-29 06:59:51 -03001742 return SAA7113;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001743 case '4':
Hans Verkuile1277112013-05-29 06:59:51 -03001744 return SAA7114;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001745 case '5':
Hans Verkuile1277112013-05-29 06:59:51 -03001746 return SAA7115;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001747 case '8':
Hans Verkuile1277112013-05-29 06:59:51 -03001748 return SAA7118;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001749 default:
1750 v4l2_info(client,
1751 "WARNING: Philips/NXP chip unknown - Falling back to saa7111\n");
Hans Verkuile1277112013-05-29 06:59:51 -03001752 return SAA7111;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001753 }
1754 }
1755
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001756 /* Check if it is a gm7113c */
1757 if (!memcmp(name, "0000", 4)) {
1758 chip_id = 0;
1759 for (i = 0; i < 4; i++) {
1760 chip_id = chip_id << 1;
1761 chip_id |= (chip_ver[i] & 0x80) ? 1 : 0;
1762 }
1763
1764 /*
1765 * Note: From the datasheet, only versions 1 and 2
1766 * exists. However, tests on a device labeled as:
1767 * "GM7113C 1145" returned "10" on all 16 chip
1768 * version (reg 0x00) reads. So, we need to also
Mauro Carvalho Chehabf8a76472019-02-18 14:28:58 -05001769 * accept at least version 0. For now, let's just
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001770 * assume that a device that returns "0000" for
1771 * the lower nibble is a gm7113c.
1772 */
1773
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001774 strscpy(name, "gm7113c", CHIP_VER_SIZE);
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001775
1776 if (!autodetect && strcmp(name, id->name))
1777 return -EINVAL;
1778
1779 v4l_dbg(1, debug, client,
1780 "It seems to be a %s chip (%*ph) @ 0x%x.\n",
1781 name, 16, chip_ver, client->addr << 1);
1782
Hans Verkuile1277112013-05-29 06:59:51 -03001783 return GM7113C;
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001784 }
1785
Kevin Fitch7e312232016-03-23 01:23:32 -03001786 /* Check if it is a CJC7113 */
1787 if (!memcmp(name, "1111111111111111", CHIP_VER_SIZE)) {
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001788 strscpy(name, "cjc7113", CHIP_VER_SIZE);
Kevin Fitch7e312232016-03-23 01:23:32 -03001789
1790 if (!autodetect && strcmp(name, id->name))
1791 return -EINVAL;
1792
1793 v4l_dbg(1, debug, client,
1794 "It seems to be a %s chip (%*ph) @ 0x%x.\n",
1795 name, 16, chip_ver, client->addr << 1);
1796
1797 /* CJC7113 seems to be SAA7113-compatible */
1798 return SAA7113;
1799 }
1800
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001801 /* Chip was not discovered. Return its ID and don't bind */
1802 v4l_dbg(1, debug, client, "chip %*ph @ 0x%x is unknown.\n",
1803 16, chip_ver, client->addr << 1);
1804 return -ENODEV;
1805}
1806
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001807static int saa711x_probe(struct i2c_client *client,
Jean Delvared2653e92008-04-29 23:11:39 +02001808 const struct i2c_device_id *id)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001809{
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001810 struct saa711x_state *state;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001811 struct v4l2_subdev *sd;
Hans Verkuile3560542010-05-24 10:00:52 -03001812 struct v4l2_ctrl_handler *hdl;
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001813 struct saa7115_platform_data *pdata;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001814 int ident;
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001815 char name[CHIP_VER_SIZE + 1];
Mauro Carvalho Chehabaf7d3742016-01-29 08:44:28 -02001816#if defined(CONFIG_MEDIA_CONTROLLER)
1817 int ret;
1818#endif
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001819
1820 /* Check if the adapter supports the needed features */
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001821 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
Hans Verkuil188f3452007-09-16 10:47:15 -03001822 return -EIO;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001823
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001824 ident = saa711x_detect_chip(client, id, name);
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001825 if (ident == -EINVAL) {
1826 /* Chip exists, but doesn't match */
1827 v4l_warn(client, "found %s while %s was expected\n",
1828 name, id->name);
Hans Verkuil188f3452007-09-16 10:47:15 -03001829 return -ENODEV;
Hans Verkuilf7668162006-11-25 09:40:28 -03001830 }
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001831 if (ident < 0)
1832 return ident;
Hans Verkuilf7668162006-11-25 09:40:28 -03001833
Mauro Carvalho Chehabc0decac2018-09-10 08:19:14 -04001834 strscpy(client->name, name, sizeof(client->name));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001835
Laurent Pinchartc02b2112013-05-02 08:29:43 -03001836 state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
Hans Verkuilc5bf2042008-09-03 17:12:09 -03001837 if (state == NULL)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001838 return -ENOMEM;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001839 sd = &state->sd;
1840 v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
Hans Verkuile3560542010-05-24 10:00:52 -03001841
Mauro Carvalho Chehabaf7d3742016-01-29 08:44:28 -02001842#if defined(CONFIG_MEDIA_CONTROLLER)
Mauro Carvalho Chehab87f997172018-08-01 06:07:09 -04001843 state->pads[SAA711X_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
1844 state->pads[SAA711X_PAD_IF_INPUT].sig_type = PAD_SIGNAL_ANALOG;
1845 state->pads[SAA711X_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
1846 state->pads[SAA711X_PAD_VID_OUT].sig_type = PAD_SIGNAL_DV;
Mauro Carvalho Chehabaf7d3742016-01-29 08:44:28 -02001847
1848 sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
1849
Mauro Carvalho Chehab87f997172018-08-01 06:07:09 -04001850 ret = media_entity_pads_init(&sd->entity, SAA711X_NUM_PADS,
1851 state->pads);
Mauro Carvalho Chehabaf7d3742016-01-29 08:44:28 -02001852 if (ret < 0)
1853 return ret;
1854#endif
1855
Hans Verkuile84e91e2013-05-29 06:59:37 -03001856 v4l_info(client, "%s found @ 0x%x (%s)\n", name,
1857 client->addr << 1, client->adapter->name);
Hans Verkuile3560542010-05-24 10:00:52 -03001858 hdl = &state->hdl;
1859 v4l2_ctrl_handler_init(hdl, 6);
1860 /* add in ascending ID order */
1861 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1862 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1863 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1864 V4L2_CID_CONTRAST, 0, 127, 1, 64);
1865 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1866 V4L2_CID_SATURATION, 0, 127, 1, 64);
1867 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1868 V4L2_CID_HUE, -128, 127, 1, 0);
1869 state->agc = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1870 V4L2_CID_CHROMA_AGC, 0, 1, 1, 1);
1871 state->gain = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1872 V4L2_CID_CHROMA_GAIN, 0, 127, 1, 40);
Hans Verkuile3560542010-05-24 10:00:52 -03001873 sd->ctrl_handler = hdl;
1874 if (hdl->error) {
1875 int err = hdl->error;
1876
1877 v4l2_ctrl_handler_free(hdl);
Hans Verkuile3560542010-05-24 10:00:52 -03001878 return err;
1879 }
Hans Verkuil6f43dbf2011-08-26 08:46:29 -03001880 v4l2_ctrl_auto_cluster(2, &state->agc, 0, true);
Hans Verkuile3560542010-05-24 10:00:52 -03001881
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001882 state->input = -1;
Marco Schluessler4cbca182007-01-21 19:43:38 -03001883 state->output = SAA7115_IPORT_ON;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001884 state->enable = 1;
Hans Verkuil3faeeae2006-01-09 15:25:44 -02001885 state->radio = 0;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001886 state->ident = ident;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001887
Hans Verkuil3578d3d2006-01-09 15:25:41 -02001888 state->audclk_freq = 48000;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001889
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001890 v4l2_dbg(1, debug, sd, "writing init values\n");
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001891
1892 /* init to 60hz/48khz */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001893 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001894 pdata = client->dev.platform_data;
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001895 switch (state->ident) {
Hans Verkuile1277112013-05-29 06:59:51 -03001896 case SAA7111:
1897 case SAA7111A:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001898 saa711x_writeregs(sd, saa7111_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001899 break;
Hans Verkuile1277112013-05-29 06:59:51 -03001900 case GM7113C:
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001901 saa711x_writeregs(sd, gm7113c_init);
1902 break;
Hans Verkuile1277112013-05-29 06:59:51 -03001903 case SAA7113:
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001904 if (pdata && pdata->saa7113_force_gm7113c_init)
1905 saa711x_writeregs(sd, gm7113c_init);
1906 else
1907 saa711x_writeregs(sd, saa7113_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001908 break;
1909 default:
Hans Verkuilb7f82922006-04-02 12:50:42 -03001910 state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001911 saa711x_writeregs(sd, saa7115_init_auto_input);
Hans Verkuilb7f82922006-04-02 12:50:42 -03001912 }
Jon Arne Jørgensenb9798bc2013-08-03 09:19:36 -03001913 if (state->ident > SAA7111A && state->ident != GM7113C)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001914 saa711x_writeregs(sd, saa7115_init_misc);
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001915
1916 if (pdata)
1917 saa711x_write_platform_data(state, pdata);
1918
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001919 saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
Hans Verkuile3560542010-05-24 10:00:52 -03001920 v4l2_ctrl_handler_setup(hdl);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001921
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001922 v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n",
1923 saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC),
1924 saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001925 return 0;
1926}
1927
1928/* ----------------------------------------------------------------------- */
1929
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001930static int saa711x_remove(struct i2c_client *client)
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001931{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001932 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1933
1934 v4l2_device_unregister_subdev(sd);
Hans Verkuile3560542010-05-24 10:00:52 -03001935 v4l2_ctrl_handler_free(sd->ctrl_handler);
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001936 return 0;
1937}
1938
Hans Verkuilaac23532010-09-15 15:04:55 -03001939static const struct i2c_device_id saa711x_id[] = {
Hans Verkuil9edd350f2008-07-17 13:22:51 -03001940 { "saa7115_auto", 1 }, /* autodetect */
Jean Delvareaf294862008-05-18 20:49:40 +02001941 { "saa7111", 0 },
1942 { "saa7113", 0 },
1943 { "saa7114", 0 },
1944 { "saa7115", 0 },
1945 { "saa7118", 0 },
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001946 { "gm7113c", 0 },
Jean Delvareaf294862008-05-18 20:49:40 +02001947 { }
1948};
Hans Verkuilaac23532010-09-15 15:04:55 -03001949MODULE_DEVICE_TABLE(i2c, saa711x_id);
Jean Delvareaf294862008-05-18 20:49:40 +02001950
Hans Verkuilaac23532010-09-15 15:04:55 -03001951static struct i2c_driver saa711x_driver = {
1952 .driver = {
Hans Verkuilaac23532010-09-15 15:04:55 -03001953 .name = "saa7115",
1954 },
1955 .probe = saa711x_probe,
1956 .remove = saa711x_remove,
1957 .id_table = saa711x_id,
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001958};
Hans Verkuilaac23532010-09-15 15:04:55 -03001959
Axel Linc6e8d862012-02-12 06:56:32 -03001960module_i2c_driver(saa711x_driver);