blob: d863b04aa2a891be150fc759a1ca881c32386161 [file] [log] [blame]
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001/* saa711x - Philips SAA711x video decoder driver
2 * This driver can work with saa7111, saa7111a, saa7113, saa7114,
3 * saa7115 and saa7118.
Hans Verkuile19b2fc2005-11-13 16:08:04 -08004 *
5 * Based on saa7114 driver by Maxim Yevtyushkin, which is based on
6 * the saa7111 driver by Dave Perks.
7 *
8 * Copyright (C) 1998 Dave Perks <dperks@ibm.net>
9 * Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
10 *
11 * Slight changes for video timing and attachment output by
12 * Wolfgang Scherr <scherr@net4you.net>
13 *
14 * Moved over to the linux >= 2.4.x i2c protocol (1/1/2003)
15 * by Ronald Bultje <rbultje@ronald.bitfreak.net>
16 *
17 * Added saa7115 support by Kevin Thayer <nufan_wfk at yahoo.com>
18 * (2/17/2003)
19 *
20 * VBI support (2004) and cleanups (2005) by Hans Verkuil <hverkuil@xs4all.nl>
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -030021 *
22 * Copyright (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
23 * SAA7111, SAA7113 and SAA7118 support
Hans Verkuile19b2fc2005-11-13 16:08:04 -080024 *
25 * This program is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU General Public License
27 * as published by the Free Software Foundation; either version 2
28 * of the License, or (at your option) any later version.
29 *
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU General Public License for more details.
Hans Verkuile19b2fc2005-11-13 16:08:04 -080034 */
35
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -030036#include "saa711x_regs.h"
Hans Verkuile19b2fc2005-11-13 16:08:04 -080037
38#include <linux/kernel.h>
39#include <linux/module.h>
40#include <linux/slab.h>
41#include <linux/i2c.h>
42#include <linux/videodev2.h>
Hans Verkuil9415f4b2008-11-29 12:55:19 -030043#include <media/v4l2-device.h>
Hans Verkuile3560542010-05-24 10:00:52 -030044#include <media/v4l2-ctrls.h>
Mauro Carvalho Chehabaf7d3742016-01-29 08:44:28 -020045#include <media/v4l2-mc.h>
Mauro Carvalho Chehabb5dcee22015-11-10 12:01:44 -020046#include <media/i2c/saa7115.h>
Hans Verkuil3578d3d2006-01-09 15:25:41 -020047#include <asm/div64.h>
Hans Verkuile19b2fc2005-11-13 16:08:04 -080048
Mauro Carvalho Chehab97d9e802006-09-03 09:38:11 -030049#define VRES_60HZ (480+16)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -030050
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -030051MODULE_DESCRIPTION("Philips SAA7111/SAA7113/SAA7114/SAA7115/SAA7118 video decoder driver");
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -030052MODULE_AUTHOR( "Maxim Yevtyushkin, Kevin Thayer, Chris Kennedy, "
53 "Hans Verkuil, Mauro Carvalho Chehab");
Hans Verkuile19b2fc2005-11-13 16:08:04 -080054MODULE_LICENSE("GPL");
55
Rusty Russell90ab5ee2012-01-13 09:32:20 +103056static bool debug;
Hans Verkuilfac9e892006-01-09 15:32:40 -020057module_param(debug, bool, 0644);
Hans Verkuile19b2fc2005-11-13 16:08:04 -080058
59MODULE_PARM_DESC(debug, "Debug level (0-1)");
60
Hans Verkuile19b2fc2005-11-13 16:08:04 -080061
Hans Verkuile1277112013-05-29 06:59:51 -030062enum saa711x_model {
63 SAA7111A,
64 SAA7111,
65 SAA7113,
66 GM7113C,
67 SAA7114,
68 SAA7115,
69 SAA7118,
70};
71
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -030072struct saa711x_state {
Hans Verkuil9415f4b2008-11-29 12:55:19 -030073 struct v4l2_subdev sd;
Mauro Carvalho Chehabaf7d3742016-01-29 08:44:28 -020074#ifdef CONFIG_MEDIA_CONTROLLER
75 struct media_pad pads[DEMOD_NUM_PADS];
76#endif
Hans Verkuile3560542010-05-24 10:00:52 -030077 struct v4l2_ctrl_handler hdl;
78
79 struct {
80 /* chroma gain control cluster */
81 struct v4l2_ctrl *agc;
82 struct v4l2_ctrl *gain;
83 };
84
Hans Verkuile19b2fc2005-11-13 16:08:04 -080085 v4l2_std_id std;
86 int input;
Marco Schluessler4cbca182007-01-21 19:43:38 -030087 int output;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080088 int enable;
Hans Verkuil3faeeae2006-01-09 15:25:44 -020089 int radio;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -030090 int width;
91 int height;
Hans Verkuile1277112013-05-29 06:59:51 -030092 enum saa711x_model ident;
Hans Verkuil3578d3d2006-01-09 15:25:41 -020093 u32 audclk_freq;
Hans Verkuilb7f82922006-04-02 12:50:42 -030094 u32 crystal_freq;
Hans Verkuil15890372013-03-11 03:47:25 -030095 bool ucgc;
Hans Verkuilb7f82922006-04-02 12:50:42 -030096 u8 cgcdiv;
Hans Verkuil15890372013-03-11 03:47:25 -030097 bool apll;
98 bool double_asclk;
Hans Verkuile19b2fc2005-11-13 16:08:04 -080099};
100
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300101static inline struct saa711x_state *to_state(struct v4l2_subdev *sd)
102{
103 return container_of(sd, struct saa711x_state, sd);
104}
105
Hans Verkuile3560542010-05-24 10:00:52 -0300106static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
107{
108 return &container_of(ctrl->handler, struct saa711x_state, hdl)->sd;
109}
110
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800111/* ----------------------------------------------------------------------- */
112
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300113static inline int saa711x_write(struct v4l2_subdev *sd, u8 reg, u8 value)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800114{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300115 struct i2c_client *client = v4l2_get_subdevdata(sd);
116
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800117 return i2c_smbus_write_byte_data(client, reg, value);
118}
119
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300120/* Sanity routine to check if a register is present */
121static int saa711x_has_reg(const int id, const u8 reg)
122{
Hans Verkuile1277112013-05-29 06:59:51 -0300123 if (id == SAA7111)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300124 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
125 (reg < 0x13 || reg > 0x19) && reg != 0x1d && reg != 0x1e;
Hans Verkuile1277112013-05-29 06:59:51 -0300126 if (id == SAA7111A)
Hans Verkuil340dde82010-02-20 08:07:51 -0300127 return reg < 0x20 && reg != 0x01 && reg != 0x0f &&
128 reg != 0x14 && reg != 0x18 && reg != 0x19 &&
129 reg != 0x1d && reg != 0x1e;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300130
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300131 /* common for saa7113/4/5/8 */
132 if (unlikely((reg >= 0x3b && reg <= 0x3f) || reg == 0x5c || reg == 0x5f ||
133 reg == 0xa3 || reg == 0xa7 || reg == 0xab || reg == 0xaf || (reg >= 0xb5 && reg <= 0xb7) ||
134 reg == 0xd3 || reg == 0xd7 || reg == 0xdb || reg == 0xdf || (reg >= 0xe5 && reg <= 0xe7) ||
135 reg == 0x82 || (reg >= 0x89 && reg <= 0x8e)))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300136 return 0;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300137
138 switch (id) {
Hans Verkuile1277112013-05-29 06:59:51 -0300139 case GM7113C:
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300140 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && reg < 0x20;
Hans Verkuile1277112013-05-29 06:59:51 -0300141 case SAA7113:
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300142 return reg != 0x14 && (reg < 0x18 || reg > 0x1e) && (reg < 0x20 || reg > 0x3f) &&
143 reg != 0x5d && reg < 0x63;
Hans Verkuile1277112013-05-29 06:59:51 -0300144 case SAA7114:
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300145 return (reg < 0x1a || reg > 0x1e) && (reg < 0x20 || reg > 0x2f) &&
146 (reg < 0x63 || reg > 0x7f) && reg != 0x33 && reg != 0x37 &&
147 reg != 0x81 && reg < 0xf0;
Hans Verkuile1277112013-05-29 06:59:51 -0300148 case SAA7115:
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300149 return (reg < 0x20 || reg > 0x2f) && reg != 0x65 && (reg < 0xfc || reg > 0xfe);
Hans Verkuile1277112013-05-29 06:59:51 -0300150 case SAA7118:
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300151 return (reg < 0x1a || reg > 0x1d) && (reg < 0x20 || reg > 0x22) &&
152 (reg < 0x26 || reg > 0x28) && reg != 0x33 && reg != 0x37 &&
153 (reg < 0x63 || reg > 0x7f) && reg != 0x81 && reg < 0xf0;
154 }
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300155 return 1;
156}
157
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300158static int saa711x_writeregs(struct v4l2_subdev *sd, const unsigned char *regs)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800159{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300160 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800161 unsigned char reg, data;
162
163 while (*regs != 0x00) {
164 reg = *(regs++);
165 data = *(regs++);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300166
167 /* According with datasheets, reserved regs should be
168 filled with 0 - seems better not to touch on they */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300169 if (saa711x_has_reg(state->ident, reg)) {
170 if (saa711x_write(sd, reg, data) < 0)
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300171 return -1;
Mauro Carvalho Chehabd87edf22006-09-01 09:37:11 -0300172 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300173 v4l2_dbg(1, debug, sd, "tried to access reserved reg 0x%02x\n", reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300174 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800175 }
176 return 0;
177}
178
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300179static inline int saa711x_read(struct v4l2_subdev *sd, u8 reg)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800180{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300181 struct i2c_client *client = v4l2_get_subdevdata(sd);
182
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800183 return i2c_smbus_read_byte_data(client, reg);
184}
185
186/* ----------------------------------------------------------------------- */
187
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300188/* SAA7111 initialization table */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300189static const unsigned char saa7111_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300190 R_01_INC_DELAY, 0x00, /* reserved */
191
192 /*front end */
193 R_02_INPUT_CNTL_1, 0xd0, /* FUSE=3, GUDL=2, MODE=0 */
194 R_03_INPUT_CNTL_2, 0x23, /* HLNRS=0, VBSL=1, WPOFF=0, HOLDG=0,
195 * GAFIX=0, GAI1=256, GAI2=256 */
196 R_04_INPUT_CNTL_3, 0x00, /* GAI1=256 */
197 R_05_INPUT_CNTL_4, 0x00, /* GAI2=256 */
198
199 /* decoder */
200 R_06_H_SYNC_START, 0xf3, /* HSB at 13(50Hz) / 17(60Hz)
201 * pixels after end of last line */
202 R_07_H_SYNC_STOP, 0xe8, /* HSS seems to be needed to
203 * work with NTSC, too */
204 R_08_SYNC_CNTL, 0xc8, /* AUFD=1, FSEL=1, EXFIL=0,
205 * VTRC=1, HPLL=0, VNOI=0 */
206 R_09_LUMA_CNTL, 0x01, /* BYPS=0, PREF=0, BPSS=0,
207 * VBLB=0, UPTCV=0, APER=1 */
208 R_0A_LUMA_BRIGHT_CNTL, 0x80,
209 R_0B_LUMA_CONTRAST_CNTL, 0x47, /* 0b - CONT=1.109 */
210 R_0C_CHROMA_SAT_CNTL, 0x40,
211 R_0D_CHROMA_HUE_CNTL, 0x00,
212 R_0E_CHROMA_CNTL_1, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0,
213 * FCTC=0, CHBW=1 */
214 R_0F_CHROMA_GAIN_CNTL, 0x00, /* reserved */
215 R_10_CHROMA_CNTL_2, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
216 R_11_MODE_DELAY_CNTL, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
217 * OEYC=1, OEHV=1, VIPB=0, COLO=0 */
218 R_12_RT_SIGNAL_CNTL, 0x00, /* 12 - output control 2 */
219 R_13_RT_X_PORT_OUT_CNTL, 0x00, /* 13 - output control 3 */
220 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
221 R_15_VGATE_START_FID_CHG, 0x00,
222 R_16_VGATE_STOP, 0x00,
223 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
224
225 0x00, 0x00
226};
227
Mauro Carvalho Chehab04074f12013-08-18 08:35:36 -0300228/*
229 * This table has one illegal value, and some values that are not
230 * correct according to the datasheet initialization table.
231 *
232 * If you need a table with legal/default values tell the driver in
233 * i2c_board_info.platform_data, and you will get the gm7113c_init
234 * table instead.
235 */
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300236
237/* SAA7113 Init codes */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300238static const unsigned char saa7113_init[] = {
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300239 R_01_INC_DELAY, 0x08,
240 R_02_INPUT_CNTL_1, 0xc2,
241 R_03_INPUT_CNTL_2, 0x30,
242 R_04_INPUT_CNTL_3, 0x00,
243 R_05_INPUT_CNTL_4, 0x00,
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300244 R_06_H_SYNC_START, 0x89, /* Illegal value -119,
245 * min. value = -108 (0x94) */
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300246 R_07_H_SYNC_STOP, 0x0d,
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300247 R_08_SYNC_CNTL, 0x88, /* Not datasheet default.
248 * HTC = VTR mode, should be 0x98 */
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300249 R_09_LUMA_CNTL, 0x01,
250 R_0A_LUMA_BRIGHT_CNTL, 0x80,
251 R_0B_LUMA_CONTRAST_CNTL, 0x47,
252 R_0C_CHROMA_SAT_CNTL, 0x40,
253 R_0D_CHROMA_HUE_CNTL, 0x00,
254 R_0E_CHROMA_CNTL_1, 0x01,
255 R_0F_CHROMA_GAIN_CNTL, 0x2a,
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300256 R_10_CHROMA_CNTL_2, 0x08, /* Not datsheet default.
257 * VRLN enabled, should be 0x00 */
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300258 R_11_MODE_DELAY_CNTL, 0x0c,
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300259 R_12_RT_SIGNAL_CNTL, 0x07, /* Not datasheet default,
260 * should be 0x01 */
261 R_13_RT_X_PORT_OUT_CNTL, 0x00,
262 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
263 R_15_VGATE_START_FID_CHG, 0x00,
264 R_16_VGATE_STOP, 0x00,
265 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
266
267 0x00, 0x00
268};
269
Mauro Carvalho Chehab04074f12013-08-18 08:35:36 -0300270/*
271 * GM7113C is a clone of the SAA7113 chip
272 * This init table is copied out of the saa7113 datasheet.
273 * In R_08 we enable "Automatic Field Detection" [AUFD],
274 * this is disabled when saa711x_set_v4lstd is called.
275 */
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -0300276static const unsigned char gm7113c_init[] = {
277 R_01_INC_DELAY, 0x08,
278 R_02_INPUT_CNTL_1, 0xc0,
279 R_03_INPUT_CNTL_2, 0x33,
280 R_04_INPUT_CNTL_3, 0x00,
281 R_05_INPUT_CNTL_4, 0x00,
282 R_06_H_SYNC_START, 0xe9,
283 R_07_H_SYNC_STOP, 0x0d,
284 R_08_SYNC_CNTL, 0x98,
285 R_09_LUMA_CNTL, 0x01,
286 R_0A_LUMA_BRIGHT_CNTL, 0x80,
287 R_0B_LUMA_CONTRAST_CNTL, 0x47,
288 R_0C_CHROMA_SAT_CNTL, 0x40,
289 R_0D_CHROMA_HUE_CNTL, 0x00,
290 R_0E_CHROMA_CNTL_1, 0x01,
291 R_0F_CHROMA_GAIN_CNTL, 0x2a,
292 R_10_CHROMA_CNTL_2, 0x00,
293 R_11_MODE_DELAY_CNTL, 0x0c,
294 R_12_RT_SIGNAL_CNTL, 0x01,
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300295 R_13_RT_X_PORT_OUT_CNTL, 0x00,
296 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
297 R_15_VGATE_START_FID_CHG, 0x00,
298 R_16_VGATE_STOP, 0x00,
299 R_17_MISC_VGATE_CONF_AND_MSB, 0x00,
300
301 0x00, 0x00
302};
303
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800304/* If a value differs from the Hauppauge driver values, then the comment starts with
305 'was 0xXX' to denote the Hauppauge value. Otherwise the value is identical to what the
306 Hauppauge driver sets. */
307
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300308/* SAA7114 and SAA7115 initialization table */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800309static const unsigned char saa7115_init_auto_input[] = {
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300310 /* Front-End Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300311 R_01_INC_DELAY, 0x48, /* white peak control disabled */
312 R_03_INPUT_CNTL_2, 0x20, /* was 0x30. 0x20: long vertical blanking */
313 R_04_INPUT_CNTL_3, 0x90, /* analog gain set to 0 */
314 R_05_INPUT_CNTL_4, 0x90, /* analog gain set to 0 */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300315 /* Decoder Part */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300316 R_06_H_SYNC_START, 0xeb, /* horiz sync begin = -21 */
317 R_07_H_SYNC_STOP, 0xe0, /* horiz sync stop = -17 */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -0300318 R_09_LUMA_CNTL, 0x53, /* 0x53, was 0x56 for 60hz. luminance control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300319 R_0A_LUMA_BRIGHT_CNTL, 0x80, /* was 0x88. decoder brightness, 0x80 is itu standard */
320 R_0B_LUMA_CONTRAST_CNTL, 0x44, /* was 0x48. decoder contrast, 0x44 is itu standard */
321 R_0C_CHROMA_SAT_CNTL, 0x40, /* was 0x47. decoder saturation, 0x40 is itu standard */
322 R_0D_CHROMA_HUE_CNTL, 0x00,
323 R_0F_CHROMA_GAIN_CNTL, 0x00, /* use automatic gain */
324 R_10_CHROMA_CNTL_2, 0x06, /* chroma: active adaptive combfilter */
325 R_11_MODE_DELAY_CNTL, 0x00,
326 R_12_RT_SIGNAL_CNTL, 0x9d, /* RTS0 output control: VGATE */
327 R_13_RT_X_PORT_OUT_CNTL, 0x80, /* ITU656 standard mode, RTCO output enable RTCE */
328 R_14_ANAL_ADC_COMPAT_CNTL, 0x00,
329 R_18_RAW_DATA_GAIN_CNTL, 0x40, /* gain 0x00 = nominal */
330 R_19_RAW_DATA_OFF_CNTL, 0x80,
331 R_1A_COLOR_KILL_LVL_CNTL, 0x77, /* recommended value */
332 R_1B_MISC_TVVCRDET, 0x42, /* recommended value */
333 R_1C_ENHAN_COMB_CTRL1, 0xa9, /* recommended value */
334 R_1D_ENHAN_COMB_CTRL2, 0x01, /* recommended value */
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300335
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300336
337 R_80_GLOBAL_CNTL_1, 0x0, /* No tasks enabled at init */
338
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300339 /* Power Device Control */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300340 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset device */
341 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* set device programmed, all in operational mode */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800342 0x00, 0x00
343};
344
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300345/* Used to reset saa7113, saa7114 and saa7115 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800346static const unsigned char saa7115_cfg_reset_scaler[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300347 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x00, /* disable I-port output */
348 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
349 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
350 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* enable I-port output */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800351 0x00, 0x00
352};
353
354/* ============== SAA7715 VIDEO templates ============= */
355
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800356static const unsigned char saa7115_cfg_60hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300357 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
358 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800359
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300360 R_15_VGATE_START_FID_CHG, 0x03,
361 R_16_VGATE_STOP, 0x11,
362 R_17_MISC_VGATE_CONF_AND_MSB, 0x9c,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800363
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300364 R_08_SYNC_CNTL, 0x68, /* 0xBO: auto detection, 0x68 = NTSC */
365 R_0E_CHROMA_CNTL_1, 0x07, /* video autodetection is on */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800366
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300367 R_5A_V_OFF_FOR_SLICER, 0x06, /* standard 60hz value for ITU656 line counting */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800368
369 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300370 R_90_A_TASK_HANDLING_CNTL, 0x80,
371 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
372 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
373 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
374
375 /* hoffset low (input), 0x0002 is minimum */
376 R_94_A_HORIZ_INPUT_WINDOW_START, 0x01,
377 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
378
379 /* hsize low (input), 0x02d0 = 720 */
380 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
381 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
382
383 R_98_A_VERT_INPUT_WINDOW_START, 0x05,
384 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
385
386 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x0c,
387 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
388
389 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
390 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05,
391
392 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x0c,
393 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800394
395 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300396 R_C0_B_TASK_HANDLING_CNTL, 0x00,
397 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
398 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
399 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800400
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300401 /* 0x0002 is minimum */
402 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x02,
403 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800404
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300405 /* 0x02d0 = 720 */
406 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
407 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
408
409 /* vwindow start 0x12 = 18 */
410 R_C8_B_VERT_INPUT_WINDOW_START, 0x12,
411 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
412
413 /* vwindow length 0xf8 = 248 */
Mauro Carvalho Chehab97d9e802006-09-03 09:38:11 -0300414 R_CA_B_VERT_INPUT_WINDOW_LENGTH, VRES_60HZ>>1,
415 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, VRES_60HZ>>9,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300416
417 /* hwindow 0x02d0 = 720 */
418 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
419 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
420
421 R_F0_LFCO_PER_LINE, 0xad, /* Set PLL Register. 60hz 525 lines per frame, 27 MHz */
422 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0 */
423 R_F5_PULSGEN_LINE_LENGTH, 0xad,
424 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
425
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800426 0x00, 0x00
427};
428
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800429static const unsigned char saa7115_cfg_50hz_video[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300430 R_80_GLOBAL_CNTL_1, 0x00,
431 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800432
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300433 R_15_VGATE_START_FID_CHG, 0x37, /* VGATE start */
434 R_16_VGATE_STOP, 0x16,
435 R_17_MISC_VGATE_CONF_AND_MSB, 0x99,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800436
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300437 R_08_SYNC_CNTL, 0x28, /* 0x28 = PAL */
438 R_0E_CHROMA_CNTL_1, 0x07,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800439
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300440 R_5A_V_OFF_FOR_SLICER, 0x03, /* standard 50hz value */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800441
442 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300443 R_90_A_TASK_HANDLING_CNTL, 0x81,
444 R_91_A_X_PORT_FORMATS_AND_CONF, 0x48,
445 R_92_A_X_PORT_INPUT_REFERENCE_SIGNAL, 0x40,
446 R_93_A_I_PORT_OUTPUT_FORMATS_AND_CONF, 0x84,
447
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800448 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
449 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300450 /* hoffset low (input), 0x0002 is minimum */
451 R_94_A_HORIZ_INPUT_WINDOW_START, 0x00,
452 R_95_A_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
453
454 /* hsize low (input), 0x02d0 = 720 */
455 R_96_A_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
456 R_97_A_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
457
458 R_98_A_VERT_INPUT_WINDOW_START, 0x03,
459 R_99_A_VERT_INPUT_WINDOW_START_MSB, 0x00,
460
461 /* vsize 0x12 = 18 */
462 R_9A_A_VERT_INPUT_WINDOW_LENGTH, 0x12,
463 R_9B_A_VERT_INPUT_WINDOW_LENGTH_MSB, 0x00,
464
465 /* hsize 0x05a0 = 1440 */
466 R_9C_A_HORIZ_OUTPUT_WINDOW_LENGTH, 0xa0,
467 R_9D_A_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x05, /* hsize hi (output) */
468 R_9E_A_VERT_OUTPUT_WINDOW_LENGTH, 0x12, /* vsize low (output), 0x12 = 18 */
469 R_9F_A_VERT_OUTPUT_WINDOW_LENGTH_MSB, 0x00, /* vsize hi (output) */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800470
471 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300472 R_C0_B_TASK_HANDLING_CNTL, 0x00,
473 R_C1_B_X_PORT_FORMATS_AND_CONF, 0x08,
474 R_C2_B_INPUT_REFERENCE_SIGNAL_DEFINITION, 0x00,
475 R_C3_B_I_PORT_FORMATS_AND_CONF, 0x80,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800476
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300477 /* This is weird: the datasheet says that you should use 2 as the minimum value, */
478 /* but Hauppauge uses 0, and changing that to 2 causes indeed problems (for 50hz) */
479 /* hoffset low (input), 0x0002 is minimum. See comment above. */
480 R_C4_B_HORIZ_INPUT_WINDOW_START, 0x00,
481 R_C5_B_HORIZ_INPUT_WINDOW_START_MSB, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800482
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300483 /* hsize 0x02d0 = 720 */
484 R_C6_B_HORIZ_INPUT_WINDOW_LENGTH, 0xd0,
485 R_C7_B_HORIZ_INPUT_WINDOW_LENGTH_MSB, 0x02,
486
487 /* voffset 0x16 = 22 */
488 R_C8_B_VERT_INPUT_WINDOW_START, 0x16,
489 R_C9_B_VERT_INPUT_WINDOW_START_MSB, 0x00,
490
491 /* vsize 0x0120 = 288 */
492 R_CA_B_VERT_INPUT_WINDOW_LENGTH, 0x20,
493 R_CB_B_VERT_INPUT_WINDOW_LENGTH_MSB, 0x01,
494
495 /* hsize 0x02d0 = 720 */
496 R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH, 0xd0,
497 R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB, 0x02,
498
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300499 R_F0_LFCO_PER_LINE, 0xb0, /* Set PLL Register. 50hz 625 lines per frame, 27 MHz */
500 R_F1_P_I_PARAM_SELECT, 0x05, /* low bit with 0xF0, (was 0x05) */
501 R_F5_PULSGEN_LINE_LENGTH, 0xb0,
502 R_F6_PULSE_A_POS_LSB_AND_PULSEGEN_CONFIG, 0x01,
503
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800504 0x00, 0x00
505};
506
507/* ============== SAA7715 VIDEO templates (end) ======= */
508
509static const unsigned char saa7115_cfg_vbi_on[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300510 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
511 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
512 R_80_GLOBAL_CNTL_1, 0x30, /* Activate both tasks */
513 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
514 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
515
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800516 0x00, 0x00
517};
518
519static const unsigned char saa7115_cfg_vbi_off[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300520 R_80_GLOBAL_CNTL_1, 0x00, /* reset tasks */
521 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0, /* reset scaler */
522 R_80_GLOBAL_CNTL_1, 0x20, /* Activate only task "B" */
523 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0, /* activate scaler */
524 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01, /* Enable I-port output */
525
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800526 0x00, 0x00
527};
528
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -0300529
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800530static const unsigned char saa7115_init_misc[] = {
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300531 R_81_V_SYNC_FLD_ID_SRC_SEL_AND_RETIMED_V_F, 0x01,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300532 R_83_X_PORT_I_O_ENA_AND_OUT_CLK, 0x01,
533 R_84_I_PORT_SIGNAL_DEF, 0x20,
534 R_85_I_PORT_SIGNAL_POLAR, 0x21,
535 R_86_I_PORT_FIFO_FLAG_CNTL_AND_ARBIT, 0xc5,
536 R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, 0x01,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800537
538 /* Task A */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300539 R_A0_A_HORIZ_PRESCALING, 0x01,
540 R_A1_A_ACCUMULATION_LENGTH, 0x00,
541 R_A2_A_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800542
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300543 /* Configure controls at nominal value*/
544 R_A4_A_LUMA_BRIGHTNESS_CNTL, 0x80,
545 R_A5_A_LUMA_CONTRAST_CNTL, 0x40,
546 R_A6_A_CHROMA_SATURATION_CNTL, 0x40,
547
548 /* note: 2 x zoom ensures that VBI lines have same length as video lines. */
549 R_A8_A_HORIZ_LUMA_SCALING_INC, 0x00,
550 R_A9_A_HORIZ_LUMA_SCALING_INC_MSB, 0x02,
551
552 R_AA_A_HORIZ_LUMA_PHASE_OFF, 0x00,
553
554 /* must be horiz lum scaling / 2 */
555 R_AC_A_HORIZ_CHROMA_SCALING_INC, 0x00,
556 R_AD_A_HORIZ_CHROMA_SCALING_INC_MSB, 0x01,
557
558 /* must be offset luma / 2 */
559 R_AE_A_HORIZ_CHROMA_PHASE_OFF, 0x00,
560
561 R_B0_A_VERT_LUMA_SCALING_INC, 0x00,
562 R_B1_A_VERT_LUMA_SCALING_INC_MSB, 0x04,
563
564 R_B2_A_VERT_CHROMA_SCALING_INC, 0x00,
565 R_B3_A_VERT_CHROMA_SCALING_INC_MSB, 0x04,
566
567 R_B4_A_VERT_SCALING_MODE_CNTL, 0x01,
568
569 R_B8_A_VERT_CHROMA_PHASE_OFF_00, 0x00,
570 R_B9_A_VERT_CHROMA_PHASE_OFF_01, 0x00,
571 R_BA_A_VERT_CHROMA_PHASE_OFF_10, 0x00,
572 R_BB_A_VERT_CHROMA_PHASE_OFF_11, 0x00,
573
574 R_BC_A_VERT_LUMA_PHASE_OFF_00, 0x00,
575 R_BD_A_VERT_LUMA_PHASE_OFF_01, 0x00,
576 R_BE_A_VERT_LUMA_PHASE_OFF_10, 0x00,
577 R_BF_A_VERT_LUMA_PHASE_OFF_11, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800578
579 /* Task B */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300580 R_D0_B_HORIZ_PRESCALING, 0x01,
581 R_D1_B_ACCUMULATION_LENGTH, 0x00,
582 R_D2_B_PRESCALER_DC_GAIN_AND_FIR_PREFILTER, 0x00,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800583
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300584 /* Configure controls at nominal value*/
585 R_D4_B_LUMA_BRIGHTNESS_CNTL, 0x80,
586 R_D5_B_LUMA_CONTRAST_CNTL, 0x40,
587 R_D6_B_CHROMA_SATURATION_CNTL, 0x40,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800588
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300589 /* hor lum scaling 0x0400 = 1 */
590 R_D8_B_HORIZ_LUMA_SCALING_INC, 0x00,
591 R_D9_B_HORIZ_LUMA_SCALING_INC_MSB, 0x04,
592
593 R_DA_B_HORIZ_LUMA_PHASE_OFF, 0x00,
594
595 /* must be hor lum scaling / 2 */
596 R_DC_B_HORIZ_CHROMA_SCALING, 0x00,
597 R_DD_B_HORIZ_CHROMA_SCALING_MSB, 0x02,
598
599 /* must be offset luma / 2 */
600 R_DE_B_HORIZ_PHASE_OFFSET_CRHOMA, 0x00,
601
602 R_E0_B_VERT_LUMA_SCALING_INC, 0x00,
603 R_E1_B_VERT_LUMA_SCALING_INC_MSB, 0x04,
604
605 R_E2_B_VERT_CHROMA_SCALING_INC, 0x00,
606 R_E3_B_VERT_CHROMA_SCALING_INC_MSB, 0x04,
607
608 R_E4_B_VERT_SCALING_MODE_CNTL, 0x01,
609
610 R_E8_B_VERT_CHROMA_PHASE_OFF_00, 0x00,
611 R_E9_B_VERT_CHROMA_PHASE_OFF_01, 0x00,
612 R_EA_B_VERT_CHROMA_PHASE_OFF_10, 0x00,
613 R_EB_B_VERT_CHROMA_PHASE_OFF_11, 0x00,
614
615 R_EC_B_VERT_LUMA_PHASE_OFF_00, 0x00,
616 R_ED_B_VERT_LUMA_PHASE_OFF_01, 0x00,
617 R_EE_B_VERT_LUMA_PHASE_OFF_10, 0x00,
618 R_EF_B_VERT_LUMA_PHASE_OFF_11, 0x00,
619
620 R_F2_NOMINAL_PLL2_DTO, 0x50, /* crystal clock = 24.576 MHz, target = 27MHz */
621 R_F3_PLL_INCREMENT, 0x46,
622 R_F4_PLL2_STATUS, 0x00,
623 R_F7_PULSE_A_POS_MSB, 0x4b, /* not the recommended settings! */
624 R_F8_PULSE_B_POS, 0x00,
625 R_F9_PULSE_B_POS_MSB, 0x4b,
626 R_FA_PULSE_C_POS, 0x00,
627 R_FB_PULSE_C_POS_MSB, 0x4b,
628
629 /* PLL2 lock detection settings: 71 lines 50% phase error */
630 R_FF_S_PLL_MAX_PHASE_ERR_THRESH_NUM_LINES, 0x88,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800631
632 /* Turn off VBI */
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300633 R_40_SLICER_CNTL_1, 0x20, /* No framing code errors allowed. */
634 R_41_LCR_BASE, 0xff,
635 R_41_LCR_BASE+1, 0xff,
636 R_41_LCR_BASE+2, 0xff,
637 R_41_LCR_BASE+3, 0xff,
638 R_41_LCR_BASE+4, 0xff,
639 R_41_LCR_BASE+5, 0xff,
640 R_41_LCR_BASE+6, 0xff,
641 R_41_LCR_BASE+7, 0xff,
642 R_41_LCR_BASE+8, 0xff,
643 R_41_LCR_BASE+9, 0xff,
644 R_41_LCR_BASE+10, 0xff,
645 R_41_LCR_BASE+11, 0xff,
646 R_41_LCR_BASE+12, 0xff,
647 R_41_LCR_BASE+13, 0xff,
648 R_41_LCR_BASE+14, 0xff,
649 R_41_LCR_BASE+15, 0xff,
650 R_41_LCR_BASE+16, 0xff,
651 R_41_LCR_BASE+17, 0xff,
652 R_41_LCR_BASE+18, 0xff,
653 R_41_LCR_BASE+19, 0xff,
654 R_41_LCR_BASE+20, 0xff,
655 R_41_LCR_BASE+21, 0xff,
656 R_41_LCR_BASE+22, 0xff,
657 R_58_PROGRAM_FRAMING_CODE, 0x40,
658 R_59_H_OFF_FOR_SLICER, 0x47,
659 R_5B_FLD_OFF_AND_MSB_FOR_H_AND_V_OFF, 0x83,
660 R_5D_DID, 0xbd,
661 R_5E_SDID, 0x35,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800662
Devin Heitmuellerfea551f2010-02-03 00:33:48 -0300663 R_02_INPUT_CNTL_1, 0xc4, /* input tuner -> input 4, amplifier active */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800664
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300665 R_80_GLOBAL_CNTL_1, 0x20, /* enable task B */
666 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xd0,
667 R_88_POWER_SAVE_ADC_PORT_CNTL, 0xf0,
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800668 0x00, 0x00
669};
670
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -0300671static int saa711x_odd_parity(u8 c)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800672{
673 c ^= (c >> 4);
674 c ^= (c >> 2);
675 c ^= (c >> 1);
676
677 return c & 1;
678}
679
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300680static int saa711x_decode_vps(u8 *dst, u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800681{
682 static const u8 biphase_tbl[] = {
683 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
684 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
685 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
686 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
687 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
688 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
689 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
690 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
691 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
692 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
693 0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
694 0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
695 0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
696 0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
697 0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
698 0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
699 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
700 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
701 0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
702 0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
703 0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
704 0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
705 0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
706 0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
707 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
708 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
709 0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
710 0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
711 0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
712 0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
713 0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
714 0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
715 };
716 int i;
717 u8 c, err = 0;
718
719 for (i = 0; i < 2 * 13; i += 2) {
720 err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
721 c = (biphase_tbl[p[i + 1]] & 0xf) | ((biphase_tbl[p[i]] & 0xf) << 4);
722 dst[i / 2] = c;
723 }
724 return err & 0xf0;
725}
726
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300727static int saa711x_decode_wss(u8 *p)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800728{
729 static const int wss_bits[8] = {
730 0, 0, 0, 1, 0, 1, 1, 1
731 };
732 unsigned char parity;
733 int wss = 0;
734 int i;
735
736 for (i = 0; i < 16; i++) {
737 int b1 = wss_bits[p[i] & 7];
738 int b2 = wss_bits[(p[i] >> 3) & 7];
739
740 if (b1 == b2)
741 return -1;
742 wss |= b2 << i;
743 }
744 parity = wss & 15;
745 parity ^= parity >> 2;
746 parity ^= parity >> 1;
747
748 if (!(parity & 1))
749 return -1;
750
751 return wss;
752}
753
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300754static int saa711x_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800755{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300756 struct saa711x_state *state = to_state(sd);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200757 u32 acpf;
758 u32 acni;
759 u32 hz;
760 u64 f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300761 u8 acc = 0; /* reg 0x3a, audio clock control */
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800762
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300763 /* Checks for chips that don't have audio clock (saa7111, saa7113) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300764 if (!saa711x_has_reg(state->ident, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -0300765 return 0;
766
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300767 v4l2_dbg(1, debug, sd, "set audio clock freq: %d\n", freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200768
769 /* sanity check */
770 if (freq < 32000 || freq > 48000)
771 return -EINVAL;
772
773 /* hz is the refresh rate times 100 */
774 hz = (state->std & V4L2_STD_525_60) ? 5994 : 5000;
775 /* acpf = (256 * freq) / field_frequency == (256 * 100 * freq) / hz */
776 acpf = (25600 * freq) / hz;
777 /* acni = (256 * freq * 2^23) / crystal_frequency =
778 (freq * 2^(8+23)) / crystal_frequency =
Hans Verkuilb7f82922006-04-02 12:50:42 -0300779 (freq << 31) / crystal_frequency */
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200780 f = freq;
781 f = f << 31;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300782 do_div(f, state->crystal_freq);
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200783 acni = f;
Hans Verkuilb7f82922006-04-02 12:50:42 -0300784 if (state->ucgc) {
785 acpf = acpf * state->cgcdiv / 16;
786 acni = acni * state->cgcdiv / 16;
787 acc = 0x80;
788 if (state->cgcdiv == 3)
789 acc |= 0x40;
790 }
791 if (state->apll)
792 acc |= 0x08;
Hans Verkuil3578d3d2006-01-09 15:25:41 -0200793
Hans Verkuil15890372013-03-11 03:47:25 -0300794 if (state->double_asclk) {
795 acpf <<= 1;
796 acni <<= 1;
797 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300798 saa711x_write(sd, R_38_CLK_RATIO_AMXCLK_TO_ASCLK, 0x03);
Hans Verkuil15890372013-03-11 03:47:25 -0300799 saa711x_write(sd, R_39_CLK_RATIO_ASCLK_TO_ALRCLK, 0x10 << state->double_asclk);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300800 saa711x_write(sd, R_3A_AUD_CLK_GEN_BASIC_SETUP, acc);
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300801
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300802 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD, acpf & 0xff);
803 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+1,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300804 (acpf >> 8) & 0xff);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300805 saa711x_write(sd, R_30_AUD_MAST_CLK_CYCLES_PER_FIELD+2,
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -0300806 (acpf >> 16) & 0x03);
807
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300808 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC, acni & 0xff);
809 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+1, (acni >> 8) & 0xff);
810 saa711x_write(sd, R_34_AUD_MAST_CLK_NOMINAL_INC+2, (acni >> 16) & 0x3f);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800811 state->audclk_freq = freq;
812 return 0;
813}
814
Hans Verkuile3560542010-05-24 10:00:52 -0300815static int saa711x_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800816{
Hans Verkuile3560542010-05-24 10:00:52 -0300817 struct v4l2_subdev *sd = to_sd(ctrl);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300818 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800819
820 switch (ctrl->id) {
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300821 case V4L2_CID_CHROMA_AGC:
Hans Verkuile3560542010-05-24 10:00:52 -0300822 /* chroma gain cluster */
Hans Verkuilddac5c12011-06-10 05:43:34 -0300823 if (state->agc->val)
824 state->gain->val =
Hans Verkuile3560542010-05-24 10:00:52 -0300825 saa711x_read(sd, R_0F_CHROMA_GAIN_CNTL) & 0x7f;
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300826 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800827 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800828 return 0;
829}
830
Hans Verkuile3560542010-05-24 10:00:52 -0300831static int saa711x_s_ctrl(struct v4l2_ctrl *ctrl)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800832{
Hans Verkuile3560542010-05-24 10:00:52 -0300833 struct v4l2_subdev *sd = to_sd(ctrl);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300834 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800835
836 switch (ctrl->id) {
837 case V4L2_CID_BRIGHTNESS:
Hans Verkuile3560542010-05-24 10:00:52 -0300838 saa711x_write(sd, R_0A_LUMA_BRIGHT_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_CONTRAST:
Hans Verkuile3560542010-05-24 10:00:52 -0300842 saa711x_write(sd, R_0B_LUMA_CONTRAST_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_SATURATION:
Hans Verkuile3560542010-05-24 10:00:52 -0300846 saa711x_write(sd, R_0C_CHROMA_SAT_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800847 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300848
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800849 case V4L2_CID_HUE:
Hans Verkuile3560542010-05-24 10:00:52 -0300850 saa711x_write(sd, R_0D_CHROMA_HUE_CNTL, ctrl->val);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800851 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300852
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300853 case V4L2_CID_CHROMA_AGC:
Hans Verkuile3560542010-05-24 10:00:52 -0300854 /* chroma gain cluster */
855 if (state->agc->val)
856 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val);
857 else
858 saa711x_write(sd, R_0F_CHROMA_GAIN_CNTL, state->gain->val | 0x80);
Devin Heitmueller87a6fe42010-03-11 21:49:24 -0300859 break;
Hans Verkuile3560542010-05-24 10:00:52 -0300860
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800861 default:
862 return -EINVAL;
863 }
864
865 return 0;
866}
867
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300868static int saa711x_set_size(struct v4l2_subdev *sd, int width, int height)
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300869{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300870 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300871 int HPSC, HFSC;
872 int VSCY;
873 int res;
874 int is_50hz = state->std & V4L2_STD_625_50;
875 int Vsrc = is_50hz ? 576 : 480;
876
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300877 v4l2_dbg(1, debug, sd, "decoder set size to %ix%i\n", width, height);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300878
879 /* FIXME need better bounds checking here */
880 if ((width < 1) || (width > 1440))
881 return -EINVAL;
882 if ((height < 1) || (height > Vsrc))
883 return -EINVAL;
884
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300885 if (!saa711x_has_reg(state->ident, R_D0_B_HORIZ_PRESCALING)) {
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300886 /* Decoder only supports 720 columns and 480 or 576 lines */
887 if (width != 720)
888 return -EINVAL;
889 if (height != Vsrc)
890 return -EINVAL;
891 }
892
893 state->width = width;
894 state->height = height;
895
896 if (!saa711x_has_reg(state->ident, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH))
897 return 0;
898
899 /* probably have a valid size, let's set it */
900 /* Set output width/height */
901 /* width */
902
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300903 saa711x_write(sd, R_CC_B_HORIZ_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300904 (u8) (width & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300905 saa711x_write(sd, R_CD_B_HORIZ_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300906 (u8) ((width >> 8) & 0xff));
907
908 /* Vertical Scaling uses height/2 */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300909 res = height / 2;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300910
911 /* On 60Hz, it is using a higher Vertical Output Size */
912 if (!is_50hz)
Hans Verkuild0d30c02006-11-25 09:45:50 -0300913 res += (VRES_60HZ - 480) >> 1;
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300914
915 /* height */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300916 saa711x_write(sd, R_CE_B_VERT_OUTPUT_WINDOW_LENGTH,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300917 (u8) (res & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300918 saa711x_write(sd, R_CF_B_VERT_OUTPUT_WINDOW_LENGTH_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300919 (u8) ((res >> 8) & 0xff));
920
921 /* Scaling settings */
922 /* Hprescaler is floor(inres/outres) */
923 HPSC = (int)(720 / width);
924 /* 0 is not allowed (div. by zero) */
925 HPSC = HPSC ? HPSC : 1;
926 HFSC = (int)((1024 * 720) / (HPSC * width));
927 /* FIXME hardcodes to "Task B"
928 * write H prescaler integer */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300929 saa711x_write(sd, R_D0_B_HORIZ_PRESCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300930 (u8) (HPSC & 0x3f));
931
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300932 v4l2_dbg(1, debug, sd, "Hpsc: 0x%05x, Hfsc: 0x%05x\n", HPSC, HFSC);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300933 /* write H fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300934 saa711x_write(sd, R_D8_B_HORIZ_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300935 (u8) (HFSC & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300936 saa711x_write(sd, R_D9_B_HORIZ_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300937 (u8) ((HFSC >> 8) & 0xff));
938 /* write H fine-scaling (chrominance)
939 * must be lum/2, so i'll just bitshift :) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300940 saa711x_write(sd, R_DC_B_HORIZ_CHROMA_SCALING,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300941 (u8) ((HFSC >> 1) & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300942 saa711x_write(sd, R_DD_B_HORIZ_CHROMA_SCALING_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300943 (u8) ((HFSC >> 9) & 0xff));
944
945 VSCY = (int)((1024 * Vsrc) / height);
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300946 v4l2_dbg(1, debug, sd, "Vsrc: %d, Vscy: 0x%05x\n", Vsrc, VSCY);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300947
948 /* Correct Contrast and Luminance */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300949 saa711x_write(sd, R_D5_B_LUMA_CONTRAST_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300950 (u8) (64 * 1024 / VSCY));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300951 saa711x_write(sd, R_D6_B_CHROMA_SATURATION_CNTL,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300952 (u8) (64 * 1024 / VSCY));
953
954 /* write V fine-scaling (luminance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300955 saa711x_write(sd, R_E0_B_VERT_LUMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300956 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300957 saa711x_write(sd, R_E1_B_VERT_LUMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300958 (u8) ((VSCY >> 8) & 0xff));
959 /* write V fine-scaling (chrominance) */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300960 saa711x_write(sd, R_E2_B_VERT_CHROMA_SCALING_INC,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300961 (u8) (VSCY & 0xff));
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300962 saa711x_write(sd, R_E3_B_VERT_CHROMA_SCALING_INC_MSB,
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300963 (u8) ((VSCY >> 8) & 0xff));
964
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300965 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300966
967 /* Activates task "B" */
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300968 saa711x_write(sd, R_80_GLOBAL_CNTL_1,
969 saa711x_read(sd, R_80_GLOBAL_CNTL_1) | 0x20);
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300970
971 return 0;
972}
973
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300974static void saa711x_set_v4lstd(struct v4l2_subdev *sd, v4l2_std_id std)
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800975{
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300976 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800977
Hans Verkuil30b54d52006-01-09 15:25:43 -0200978 /* Prevent unnecessary standard changes. During a standard
979 change the I-Port is temporarily disabled. Any devices
980 reading from that port can get confused.
Hans Verkuilbccfa442009-03-30 06:55:27 -0300981 Note that s_std is also used to switch from
982 radio to TV mode, so if a s_std is broadcast to
Hans Verkuil30b54d52006-01-09 15:25:43 -0200983 all I2C devices then you do not want to have an unwanted
984 side-effect here. */
985 if (std == state->std)
986 return;
987
Mauro Carvalho Chehabd9dce962006-09-02 12:59:38 -0300988 state->std = std;
989
Hans Verkuile19b2fc2005-11-13 16:08:04 -0800990 // This works for NTSC-M, SECAM-L and the 50Hz PAL variants.
991 if (std & V4L2_STD_525_60) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -0300992 v4l2_dbg(1, debug, sd, "decoder set standard 60 Hz\n");
Jon Arne Jørgensen8b77dfd2013-08-03 09:19:35 -0300993 if (state->ident == GM7113C) {
994 u8 reg = saa711x_read(sd, R_08_SYNC_CNTL);
995 reg &= ~(SAA7113_R_08_FSEL | SAA7113_R_08_AUFD);
996 reg |= SAA7113_R_08_FSEL;
997 saa711x_write(sd, R_08_SYNC_CNTL, reg);
998 } else {
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -0300999 saa711x_writeregs(sd, saa7115_cfg_60hz_video);
Jon Arne Jørgensen8b77dfd2013-08-03 09:19:35 -03001000 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001001 saa711x_set_size(sd, 720, 480);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001002 } else {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001003 v4l2_dbg(1, debug, sd, "decoder set standard 50 Hz\n");
Jon Arne Jørgensen8b77dfd2013-08-03 09:19:35 -03001004 if (state->ident == GM7113C) {
1005 u8 reg = saa711x_read(sd, R_08_SYNC_CNTL);
1006 reg &= ~(SAA7113_R_08_FSEL | SAA7113_R_08_AUFD);
1007 saa711x_write(sd, R_08_SYNC_CNTL, reg);
1008 } else {
Jon Arne Jørgensen241d89f2013-05-10 03:52:28 -03001009 saa711x_writeregs(sd, saa7115_cfg_50hz_video);
Jon Arne Jørgensen8b77dfd2013-08-03 09:19:35 -03001010 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001011 saa711x_set_size(sd, 720, 576);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001012 }
1013
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001014 /* Register 0E - Bits D6-D4 on NO-AUTO mode
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001015 (SAA7111 and SAA7113 doesn't have auto mode)
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001016 50 Hz / 625 lines 60 Hz / 525 lines
1017 000 PAL BGDHI (4.43Mhz) NTSC M (3.58MHz)
1018 001 NTSC 4.43 (50 Hz) PAL 4.43 (60 Hz)
1019 010 Combination-PAL N (3.58MHz) NTSC 4.43 (60 Hz)
1020 011 NTSC N (3.58MHz) PAL M (3.58MHz)
1021 100 reserved NTSC-Japan (3.58MHz)
1022 */
Hans Verkuile1277112013-05-29 06:59:51 -03001023 if (state->ident <= SAA7113 ||
1024 state->ident == GM7113C) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001025 u8 reg = saa711x_read(sd, R_0E_CHROMA_CNTL_1) & 0x8f;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001026
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -03001027 if (std == V4L2_STD_PAL_M) {
Hans Verkuil01342352006-03-25 08:19:47 -03001028 reg |= 0x30;
Hans Verkuile0028022008-04-22 14:45:51 -03001029 } else if (std == V4L2_STD_PAL_Nc) {
Hans Verkuil01342352006-03-25 08:19:47 -03001030 reg |= 0x20;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -03001031 } else if (std == V4L2_STD_PAL_60) {
Hans Verkuil01342352006-03-25 08:19:47 -03001032 reg |= 0x10;
Mauro Carvalho Chehab02c17222006-03-16 18:44:07 -03001033 } else if (std == V4L2_STD_NTSC_M_JP) {
Hans Verkuil01342352006-03-25 08:19:47 -03001034 reg |= 0x40;
Mauro Carvalho Chehaba9aaec42007-03-13 13:41:49 -03001035 } else if (std & V4L2_STD_SECAM) {
Pádraig Bradyfc2fa312006-10-09 08:02:17 -03001036 reg |= 0x50;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001037 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001038 saa711x_write(sd, R_0E_CHROMA_CNTL_1, reg);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001039 } else {
1040 /* restart task B if needed */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001041 int taskb = saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10;
Mauro Carvalho Chehabf89982a2006-03-14 16:33:33 -03001042
Hans Verkuile1277112013-05-29 06:59:51 -03001043 if (taskb && state->ident == SAA7114)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001044 saa711x_writeregs(sd, saa7115_cfg_vbi_on);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001045
1046 /* switch audio mode too! */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001047 saa711x_s_clock_freq(sd, state->audclk_freq);
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001048 }
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001049}
1050
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001051/* setup the sliced VBI lcr registers according to the sliced VBI format */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001052static void saa711x_set_lcr(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001053{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001054 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001055 int is_50hz = (state->std & V4L2_STD_625_50);
1056 u8 lcr[24];
1057 int i, x;
1058
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001059#if 1
1060 /* saa7113/7114/7118 VBI support are experimental */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001061 if (!saa711x_has_reg(state->ident, R_41_LCR_BASE))
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001062 return;
1063
1064#else
1065 /* SAA7113 and SAA7118 also should support VBI - Need testing */
Hans Verkuile1277112013-05-29 06:59:51 -03001066 if (state->ident != SAA7115)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001067 return;
Mauro Carvalho Chehab89f75ff2006-08-29 22:07:03 -03001068#endif
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001069
1070 for (i = 0; i <= 23; i++)
1071 lcr[i] = 0xff;
1072
Hans Verkuila8b86432008-10-04 08:05:30 -03001073 if (fmt == NULL) {
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001074 /* raw VBI */
1075 if (is_50hz)
1076 for (i = 6; i <= 23; i++)
1077 lcr[i] = 0xdd;
1078 else
1079 for (i = 10; i <= 21; i++)
1080 lcr[i] = 0xdd;
1081 } else {
1082 /* sliced VBI */
1083 /* first clear lines that cannot be captured */
1084 if (is_50hz) {
1085 for (i = 0; i <= 5; i++)
1086 fmt->service_lines[0][i] =
1087 fmt->service_lines[1][i] = 0;
1088 }
1089 else {
1090 for (i = 0; i <= 9; i++)
1091 fmt->service_lines[0][i] =
1092 fmt->service_lines[1][i] = 0;
1093 for (i = 22; i <= 23; i++)
1094 fmt->service_lines[0][i] =
1095 fmt->service_lines[1][i] = 0;
1096 }
1097
1098 /* Now set the lcr values according to the specified service */
1099 for (i = 6; i <= 23; i++) {
1100 lcr[i] = 0;
1101 for (x = 0; x <= 1; x++) {
1102 switch (fmt->service_lines[1-x][i]) {
1103 case 0:
1104 lcr[i] |= 0xf << (4 * x);
1105 break;
Hans Verkuil9bc74002006-03-29 18:02:51 -03001106 case V4L2_SLICED_TELETEXT_B:
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001107 lcr[i] |= 1 << (4 * x);
1108 break;
1109 case V4L2_SLICED_CAPTION_525:
1110 lcr[i] |= 4 << (4 * x);
1111 break;
1112 case V4L2_SLICED_WSS_625:
1113 lcr[i] |= 5 << (4 * x);
1114 break;
1115 case V4L2_SLICED_VPS:
1116 lcr[i] |= 7 << (4 * x);
1117 break;
1118 }
1119 }
1120 }
1121 }
1122
1123 /* write the lcr registers */
1124 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001125 saa711x_write(sd, i - 2 + R_41_LCR_BASE, lcr[i]);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001126 }
1127
1128 /* enable/disable raw VBI capturing */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001129 saa711x_writeregs(sd, fmt == NULL ?
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001130 saa7115_cfg_vbi_on :
1131 saa7115_cfg_vbi_off);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001132}
1133
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001134static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *sliced)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001135{
1136 static u16 lcr2vbi[] = {
Hans Verkuil9bc74002006-03-29 18:02:51 -03001137 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001138 0, V4L2_SLICED_CAPTION_525, /* 4 */
1139 V4L2_SLICED_WSS_625, 0, /* 5 */
1140 V4L2_SLICED_VPS, 0, 0, 0, 0, /* 7 */
1141 0, 0, 0, 0
1142 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001143 int i;
1144
Hans Verkuil30634e82012-09-05 10:38:10 -03001145 memset(sliced->service_lines, 0, sizeof(sliced->service_lines));
1146 sliced->service_set = 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001147 /* done if using raw VBI */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001148 if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001149 return 0;
1150 for (i = 2; i <= 23; i++) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001151 u8 v = saa711x_read(sd, i - 2 + R_41_LCR_BASE);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001152
1153 sliced->service_lines[0][i] = lcr2vbi[v >> 4];
1154 sliced->service_lines[1][i] = lcr2vbi[v & 0xf];
1155 sliced->service_set |=
1156 sliced->service_lines[0][i] | sliced->service_lines[1][i];
1157 }
1158 return 0;
1159}
1160
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001161static int saa711x_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
1162{
1163 saa711x_set_lcr(sd, NULL);
1164 return 0;
1165}
1166
1167static int saa711x_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt)
1168{
1169 saa711x_set_lcr(sd, fmt);
1170 return 0;
1171}
1172
Hans Verkuil6e80c472015-03-21 09:39:09 -03001173static int saa711x_set_fmt(struct v4l2_subdev *sd,
1174 struct v4l2_subdev_pad_config *cfg,
1175 struct v4l2_subdev_format *format)
Hans Verkuilc463d932010-05-09 09:47:23 -03001176{
Hans Verkuil6e80c472015-03-21 09:39:09 -03001177 struct v4l2_mbus_framefmt *fmt = &format->format;
1178
1179 if (format->pad || fmt->code != MEDIA_BUS_FMT_FIXED)
Hans Verkuilc463d932010-05-09 09:47:23 -03001180 return -EINVAL;
1181 fmt->field = V4L2_FIELD_INTERLACED;
1182 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
Hans Verkuil6e80c472015-03-21 09:39:09 -03001183 if (format->which == V4L2_SUBDEV_FORMAT_TRY)
1184 return 0;
Hans Verkuilc463d932010-05-09 09:47:23 -03001185 return saa711x_set_size(sd, fmt->width, fmt->height);
1186}
1187
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001188/* Decode the sliced VBI data stream as created by the saa7115.
1189 The format is described in the saa7115 datasheet in Tables 25 and 26
1190 and in Figure 33.
1191 The current implementation uses SAV/EAV codes and not the ancillary data
Mauro Carvalho Chehab96ecfc42006-08-28 19:18:49 -03001192 headers. The vbi->p pointer points to the R_5E_SDID byte right after the SAV
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001193 code. */
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001194static int saa711x_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001195{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001196 struct saa711x_state *state = to_state(sd);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001197 static const char vbi_no_data_pattern[] = {
1198 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0
1199 };
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001200 u8 *p = vbi->p;
1201 u32 wss;
1202 int id1, id2; /* the ID1 and ID2 bytes from the internal header */
1203
1204 vbi->type = 0; /* mark result as a failure */
1205 id1 = p[2];
1206 id2 = p[3];
1207 /* Note: the field bit is inverted for 60 Hz video */
1208 if (state->std & V4L2_STD_525_60)
1209 id1 ^= 0x40;
1210
1211 /* Skip internal header, p now points to the start of the payload */
1212 p += 4;
1213 vbi->p = p;
1214
1215 /* calculate field and line number of the VBI packet (1-23) */
1216 vbi->is_second_field = ((id1 & 0x40) != 0);
1217 vbi->line = (id1 & 0x3f) << 3;
1218 vbi->line |= (id2 & 0x70) >> 4;
1219
1220 /* Obtain data type */
1221 id2 &= 0xf;
1222
1223 /* If the VBI slicer does not detect any signal it will fill up
1224 the payload buffer with 0xa0 bytes. */
1225 if (!memcmp(p, vbi_no_data_pattern, sizeof(vbi_no_data_pattern)))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001226 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001227
1228 /* decode payloads */
1229 switch (id2) {
1230 case 1:
Hans Verkuil9bc74002006-03-29 18:02:51 -03001231 vbi->type = V4L2_SLICED_TELETEXT_B;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001232 break;
1233 case 4:
Mauro Carvalho Chehab59ba9152006-08-30 05:34:36 -03001234 if (!saa711x_odd_parity(p[0]) || !saa711x_odd_parity(p[1]))
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001235 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001236 vbi->type = V4L2_SLICED_CAPTION_525;
1237 break;
1238 case 5:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001239 wss = saa711x_decode_wss(p);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001240 if (wss == -1)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001241 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001242 p[0] = wss & 0xff;
1243 p[1] = wss >> 8;
1244 vbi->type = V4L2_SLICED_WSS_625;
1245 break;
1246 case 7:
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001247 if (saa711x_decode_vps(p, p) != 0)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001248 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001249 vbi->type = V4L2_SLICED_VPS;
1250 break;
1251 default:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001252 break;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001253 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001254 return 0;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001255}
1256
1257/* ============ SAA7115 AUDIO settings (end) ============= */
1258
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001259static int saa711x_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001260{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001261 struct saa711x_state *state = to_state(sd);
1262 int status;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001263
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001264 if (state->radio)
1265 return 0;
1266 status = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001267
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001268 v4l2_dbg(1, debug, sd, "status: 0x%02x\n", status);
1269 vt->signal = ((status & (1 << 6)) == 0) ? 0xffff : 0x0;
1270 return 0;
1271}
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001272
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001273static int saa711x_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
1274{
1275 struct saa711x_state *state = to_state(sd);
1276
1277 state->radio = 0;
1278 saa711x_set_v4lstd(sd, std);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001279 return 0;
1280}
1281
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001282static int saa711x_s_radio(struct v4l2_subdev *sd)
1283{
1284 struct saa711x_state *state = to_state(sd);
1285
1286 state->radio = 1;
1287 return 0;
1288}
1289
Hans Verkuil5325b422009-04-02 11:26:22 -03001290static int saa711x_s_routing(struct v4l2_subdev *sd,
1291 u32 input, u32 output, u32 config)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001292{
1293 struct saa711x_state *state = to_state(sd);
Hans Verkuile1277112013-05-29 06:59:51 -03001294 u8 mask = (state->ident <= SAA7111A) ? 0xf8 : 0xf0;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001295
Hans Verkuil5325b422009-04-02 11:26:22 -03001296 v4l2_dbg(1, debug, sd, "decoder set input %d output %d\n",
1297 input, output);
1298
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001299 /* saa7111/3 does not have these inputs */
Hans Verkuile1277112013-05-29 06:59:51 -03001300 if ((state->ident <= SAA7113 ||
1301 state->ident == GM7113C) &&
Hans Verkuil5325b422009-04-02 11:26:22 -03001302 (input == SAA7115_COMPOSITE4 ||
1303 input == SAA7115_COMPOSITE5)) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001304 return -EINVAL;
1305 }
Hans Verkuil5325b422009-04-02 11:26:22 -03001306 if (input > SAA7115_SVIDEO3)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001307 return -EINVAL;
Hans Verkuil5325b422009-04-02 11:26:22 -03001308 if (state->input == input && state->output == output)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001309 return 0;
1310 v4l2_dbg(1, debug, sd, "now setting %s input %s output\n",
Hans Verkuil5325b422009-04-02 11:26:22 -03001311 (input >= SAA7115_SVIDEO0) ? "S-Video" : "Composite",
1312 (output == SAA7115_IPORT_ON) ? "iport on" : "iport off");
1313 state->input = input;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001314
1315 /* saa7111 has slightly different input numbering */
Hans Verkuile1277112013-05-29 06:59:51 -03001316 if (state->ident <= SAA7111A) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001317 if (input >= SAA7115_COMPOSITE4)
1318 input -= 2;
1319 /* saa7111 specific */
1320 saa711x_write(sd, R_10_CHROMA_CNTL_2,
1321 (saa711x_read(sd, R_10_CHROMA_CNTL_2) & 0x3f) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001322 ((output & 0xc0) ^ 0x40));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001323 saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL,
1324 (saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL) & 0xf0) |
Hans Verkuil5325b422009-04-02 11:26:22 -03001325 ((output & 2) ? 0x0a : 0));
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001326 }
1327
1328 /* select mode */
1329 saa711x_write(sd, R_02_INPUT_CNTL_1,
1330 (saa711x_read(sd, R_02_INPUT_CNTL_1) & mask) |
1331 input);
1332
1333 /* bypass chrominance trap for S-Video modes */
1334 saa711x_write(sd, R_09_LUMA_CNTL,
1335 (saa711x_read(sd, R_09_LUMA_CNTL) & 0x7f) |
1336 (state->input >= SAA7115_SVIDEO0 ? 0x80 : 0x0));
1337
Hans Verkuil5325b422009-04-02 11:26:22 -03001338 state->output = output;
Hans Verkuile1277112013-05-29 06:59:51 -03001339 if (state->ident == SAA7114 ||
1340 state->ident == SAA7115) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001341 saa711x_write(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK,
1342 (saa711x_read(sd, R_83_X_PORT_I_O_ENA_AND_OUT_CLK) & 0xfe) |
1343 (state->output & 0x01));
1344 }
Hans Verkuile1277112013-05-29 06:59:51 -03001345 if (state->ident > SAA7111A) {
Hans Verkuila0fc5882013-03-08 11:22:03 -03001346 if (config & SAA7115_IDQ_IS_DEFAULT)
1347 saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x20);
1348 else
1349 saa711x_write(sd, R_85_I_PORT_SIGNAL_POLAR, 0x21);
1350 }
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001351 return 0;
1352}
1353
1354static int saa711x_s_gpio(struct v4l2_subdev *sd, u32 val)
1355{
1356 struct saa711x_state *state = to_state(sd);
1357
Hans Verkuile1277112013-05-29 06:59:51 -03001358 if (state->ident > SAA7111A)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001359 return -EINVAL;
1360 saa711x_write(sd, 0x11, (saa711x_read(sd, 0x11) & 0x7f) |
1361 (val ? 0x80 : 0));
1362 return 0;
1363}
1364
1365static int saa711x_s_stream(struct v4l2_subdev *sd, int enable)
1366{
1367 struct saa711x_state *state = to_state(sd);
1368
1369 v4l2_dbg(1, debug, sd, "%s output\n",
1370 enable ? "enable" : "disable");
1371
Hans Verkuil674a3232009-02-18 12:22:16 -03001372 if (state->enable == enable)
1373 return 0;
1374 state->enable = enable;
1375 if (!saa711x_has_reg(state->ident, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED))
1376 return 0;
1377 saa711x_write(sd, R_87_I_PORT_I_O_ENA_OUT_CLK_AND_GATED, state->enable);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001378 return 0;
1379}
1380
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001381static int saa711x_s_crystal_freq(struct v4l2_subdev *sd, u32 freq, u32 flags)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001382{
1383 struct saa711x_state *state = to_state(sd);
1384
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001385 if (freq != SAA7115_FREQ_32_11_MHZ && freq != SAA7115_FREQ_24_576_MHZ)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001386 return -EINVAL;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001387 state->crystal_freq = freq;
Hans Verkuil15890372013-03-11 03:47:25 -03001388 state->double_asclk = flags & SAA7115_FREQ_FL_DOUBLE_ASCLK;
Hans Verkuil3ff4ad82009-04-01 03:15:52 -03001389 state->cgcdiv = (flags & SAA7115_FREQ_FL_CGCDIV) ? 3 : 4;
Hans Verkuil15890372013-03-11 03:47:25 -03001390 state->ucgc = flags & SAA7115_FREQ_FL_UCGC;
1391 state->apll = flags & SAA7115_FREQ_FL_APLL;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001392 saa711x_s_clock_freq(sd, state->audclk_freq);
1393 return 0;
1394}
1395
1396static int saa711x_reset(struct v4l2_subdev *sd, u32 val)
1397{
1398 v4l2_dbg(1, debug, sd, "decoder RESET\n");
1399 saa711x_writeregs(sd, saa7115_cfg_reset_scaler);
1400 return 0;
1401}
1402
1403static int saa711x_g_vbi_data(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *data)
1404{
1405 /* Note: the internal field ID is inverted for NTSC,
1406 so data->field 0 maps to the saa7115 even field,
1407 whereas for PAL it maps to the saa7115 odd field. */
1408 switch (data->id) {
1409 case V4L2_SLICED_WSS_625:
1410 if (saa711x_read(sd, 0x6b) & 0xc0)
1411 return -EIO;
1412 data->data[0] = saa711x_read(sd, 0x6c);
1413 data->data[1] = saa711x_read(sd, 0x6d);
1414 return 0;
1415 case V4L2_SLICED_CAPTION_525:
1416 if (data->field == 0) {
1417 /* CC */
1418 if (saa711x_read(sd, 0x66) & 0x30)
1419 return -EIO;
1420 data->data[0] = saa711x_read(sd, 0x69);
1421 data->data[1] = saa711x_read(sd, 0x6a);
1422 return 0;
1423 }
1424 /* XDS */
1425 if (saa711x_read(sd, 0x66) & 0xc0)
1426 return -EIO;
1427 data->data[0] = saa711x_read(sd, 0x67);
1428 data->data[1] = saa711x_read(sd, 0x68);
1429 return 0;
1430 default:
1431 return -EINVAL;
1432 }
1433}
1434
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001435static int saa711x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
1436{
1437 struct saa711x_state *state = to_state(sd);
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001438 int reg1f, reg1e;
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001439
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001440 /*
1441 * The V4L2 core already initializes std with all supported
1442 * Standards. All driver needs to do is to mask it, to remove
1443 * standards that don't apply from the mask
1444 */
1445
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001446 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
Hans Verkuilc875dee2013-03-10 09:59:37 -03001447
Hans Verkuile1277112013-05-29 06:59:51 -03001448 if (state->ident == SAA7115) {
Hans Verkuilc875dee2013-03-10 09:59:37 -03001449 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1450
1451 v4l2_dbg(1, debug, sd, "Status byte 1 (0x1e)=0x%02x\n", reg1e);
1452
1453 switch (reg1e & 0x03) {
1454 case 1:
1455 *std &= V4L2_STD_NTSC;
1456 break;
1457 case 2:
1458 /*
1459 * V4L2_STD_PAL just cover the european PAL standards.
1460 * This is wrong, as the device could also be using an
1461 * other PAL standard.
1462 */
1463 *std &= V4L2_STD_PAL | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc |
1464 V4L2_STD_PAL_M | V4L2_STD_PAL_60;
1465 break;
1466 case 3:
1467 *std &= V4L2_STD_SECAM;
1468 break;
1469 default:
Hans Verkuilaf1f7282013-05-29 10:18:58 -03001470 *std = V4L2_STD_UNKNOWN;
Hans Verkuilc875dee2013-03-10 09:59:37 -03001471 /* Can't detect anything */
1472 break;
1473 }
1474 }
1475
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001476 v4l2_dbg(1, debug, sd, "Status byte 2 (0x1f)=0x%02x\n", reg1f);
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001477
1478 /* horizontal/vertical not locked */
Hans Verkuilaf1f7282013-05-29 10:18:58 -03001479 if (reg1f & 0x40) {
1480 *std = V4L2_STD_UNKNOWN;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001481 goto ret;
Hans Verkuilaf1f7282013-05-29 10:18:58 -03001482 }
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001483
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001484 if (reg1f & 0x20)
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001485 *std &= V4L2_STD_525_60;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001486 else
Mauro Carvalho Chehabe41567a2011-10-04 09:40:18 -03001487 *std &= V4L2_STD_625_50;
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001488
Mauro Carvalho Chehabb7286662011-10-03 12:01:22 -03001489ret:
1490 v4l2_dbg(1, debug, sd, "detected std mask = %08Lx\n", *std);
1491
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001492 return 0;
1493}
1494
1495static int saa711x_g_input_status(struct v4l2_subdev *sd, u32 *status)
1496{
1497 struct saa711x_state *state = to_state(sd);
1498 int reg1e = 0x80;
1499 int reg1f;
1500
1501 *status = V4L2_IN_ST_NO_SIGNAL;
Hans Verkuile1277112013-05-29 06:59:51 -03001502 if (state->ident == SAA7115)
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001503 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1504 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1505 if ((reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80)
1506 *status = 0;
1507 return 0;
1508}
1509
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001510#ifdef CONFIG_VIDEO_ADV_DEBUG
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001511static int saa711x_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001512{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001513 reg->val = saa711x_read(sd, reg->reg & 0xff);
Hans Verkuilaecde8b52008-12-30 07:14:19 -03001514 reg->size = 1;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001515 return 0;
1516}
1517
Hans Verkuil977ba3b2013-03-24 08:28:46 -03001518static int saa711x_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001519{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001520 saa711x_write(sd, reg->reg & 0xff, reg->val & 0xff);
1521 return 0;
1522}
1523#endif
1524
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001525static int saa711x_log_status(struct v4l2_subdev *sd)
1526{
1527 struct saa711x_state *state = to_state(sd);
1528 int reg1e, reg1f;
1529 int signalOk;
1530 int vcr;
1531
1532 v4l2_info(sd, "Audio frequency: %d Hz\n", state->audclk_freq);
Hans Verkuile1277112013-05-29 06:59:51 -03001533 if (state->ident != SAA7115) {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001534 /* status for the saa7114 */
1535 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1536 signalOk = (reg1f & 0xc1) == 0x81;
1537 v4l2_info(sd, "Video signal: %s\n", signalOk ? "ok" : "bad");
1538 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1539 return 0;
1540 }
1541
1542 /* status for the saa7115 */
1543 reg1e = saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC);
1544 reg1f = saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC);
1545
1546 signalOk = (reg1f & 0xc1) == 0x81 && (reg1e & 0xc0) == 0x80;
1547 vcr = !(reg1f & 0x10);
1548
1549 if (state->input >= 6)
1550 v4l2_info(sd, "Input: S-Video %d\n", state->input - 6);
1551 else
1552 v4l2_info(sd, "Input: Composite %d\n", state->input);
1553 v4l2_info(sd, "Video signal: %s\n", signalOk ? (vcr ? "VCR" : "broadcast/DVD") : "bad");
1554 v4l2_info(sd, "Frequency: %s\n", (reg1f & 0x20) ? "60 Hz" : "50 Hz");
1555
1556 switch (reg1e & 0x03) {
1557 case 1:
1558 v4l2_info(sd, "Detected format: NTSC\n");
1559 break;
1560 case 2:
1561 v4l2_info(sd, "Detected format: PAL\n");
1562 break;
1563 case 3:
1564 v4l2_info(sd, "Detected format: SECAM\n");
1565 break;
1566 default:
1567 v4l2_info(sd, "Detected format: BW/No color\n");
1568 break;
1569 }
1570 v4l2_info(sd, "Width, Height: %d, %d\n", state->width, state->height);
Hans Verkuile3560542010-05-24 10:00:52 -03001571 v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001572 return 0;
1573}
1574
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001575/* ----------------------------------------------------------------------- */
1576
Hans Verkuile3560542010-05-24 10:00:52 -03001577static const struct v4l2_ctrl_ops saa711x_ctrl_ops = {
1578 .s_ctrl = saa711x_s_ctrl,
1579 .g_volatile_ctrl = saa711x_g_volatile_ctrl,
1580};
1581
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001582static const struct v4l2_subdev_core_ops saa711x_core_ops = {
1583 .log_status = saa711x_log_status,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001584 .reset = saa711x_reset,
1585 .s_gpio = saa711x_s_gpio,
1586#ifdef CONFIG_VIDEO_ADV_DEBUG
1587 .g_register = saa711x_g_register,
1588 .s_register = saa711x_s_register,
1589#endif
1590};
1591
1592static const struct v4l2_subdev_tuner_ops saa711x_tuner_ops = {
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001593 .s_radio = saa711x_s_radio,
1594 .g_tuner = saa711x_g_tuner,
1595};
1596
1597static const struct v4l2_subdev_audio_ops saa711x_audio_ops = {
1598 .s_clock_freq = saa711x_s_clock_freq,
1599};
1600
1601static const struct v4l2_subdev_video_ops saa711x_video_ops = {
Laurent Pinchart8774bed2014-04-28 16:53:01 -03001602 .s_std = saa711x_s_std,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001603 .s_routing = saa711x_s_routing,
1604 .s_crystal_freq = saa711x_s_crystal_freq,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001605 .s_stream = saa711x_s_stream,
Hans Verkuil17bdd9d2009-02-18 12:35:33 -03001606 .querystd = saa711x_querystd,
1607 .g_input_status = saa711x_g_input_status,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001608};
1609
Hans Verkuil32cd5272010-03-14 09:57:30 -03001610static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = {
1611 .g_vbi_data = saa711x_g_vbi_data,
1612 .decode_vbi_line = saa711x_decode_vbi_line,
Hans Verkuil63d8adc2010-03-14 10:10:14 -03001613 .g_sliced_fmt = saa711x_g_sliced_fmt,
1614 .s_sliced_fmt = saa711x_s_sliced_fmt,
1615 .s_raw_fmt = saa711x_s_raw_fmt,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001616};
1617
Hans Verkuil6e80c472015-03-21 09:39:09 -03001618static const struct v4l2_subdev_pad_ops saa711x_pad_ops = {
1619 .set_fmt = saa711x_set_fmt,
1620};
1621
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001622static const struct v4l2_subdev_ops saa711x_ops = {
1623 .core = &saa711x_core_ops,
1624 .tuner = &saa711x_tuner_ops,
1625 .audio = &saa711x_audio_ops,
1626 .video = &saa711x_video_ops,
Hans Verkuil32cd5272010-03-14 09:57:30 -03001627 .vbi = &saa711x_vbi_ops,
Hans Verkuil6e80c472015-03-21 09:39:09 -03001628 .pad = &saa711x_pad_ops,
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001629};
1630
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001631#define CHIP_VER_SIZE 16
1632
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001633/* ----------------------------------------------------------------------- */
1634
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001635static void saa711x_write_platform_data(struct saa711x_state *state,
1636 struct saa7115_platform_data *data)
1637{
1638 struct v4l2_subdev *sd = &state->sd;
1639 u8 work;
1640
1641 if (state->ident != GM7113C &&
1642 state->ident != SAA7113)
1643 return;
1644
1645 if (data->saa7113_r08_htc) {
1646 work = saa711x_read(sd, R_08_SYNC_CNTL);
1647 work &= ~SAA7113_R_08_HTC_MASK;
1648 work |= ((*data->saa7113_r08_htc) << SAA7113_R_08_HTC_OFFSET);
1649 saa711x_write(sd, R_08_SYNC_CNTL, work);
1650 }
1651
1652 if (data->saa7113_r10_vrln) {
1653 work = saa711x_read(sd, R_10_CHROMA_CNTL_2);
1654 work &= ~SAA7113_R_10_VRLN_MASK;
1655 if (*data->saa7113_r10_vrln)
1656 work |= (1 << SAA7113_R_10_VRLN_OFFSET);
1657 saa711x_write(sd, R_10_CHROMA_CNTL_2, work);
1658 }
1659
1660 if (data->saa7113_r10_ofts) {
1661 work = saa711x_read(sd, R_10_CHROMA_CNTL_2);
1662 work &= ~SAA7113_R_10_OFTS_MASK;
1663 work |= (*data->saa7113_r10_ofts << SAA7113_R_10_OFTS_OFFSET);
1664 saa711x_write(sd, R_10_CHROMA_CNTL_2, work);
1665 }
1666
1667 if (data->saa7113_r12_rts0) {
1668 work = saa711x_read(sd, R_12_RT_SIGNAL_CNTL);
1669 work &= ~SAA7113_R_12_RTS0_MASK;
1670 work |= (*data->saa7113_r12_rts0 << SAA7113_R_12_RTS0_OFFSET);
1671
1672 /* According to the datasheet,
1673 * SAA7113_RTS_DOT_IN should only be used on RTS1 */
1674 WARN_ON(*data->saa7113_r12_rts0 == SAA7113_RTS_DOT_IN);
1675 saa711x_write(sd, R_12_RT_SIGNAL_CNTL, work);
1676 }
1677
1678 if (data->saa7113_r12_rts1) {
1679 work = saa711x_read(sd, R_12_RT_SIGNAL_CNTL);
1680 work &= ~SAA7113_R_12_RTS1_MASK;
1681 work |= (*data->saa7113_r12_rts1 << SAA7113_R_12_RTS1_OFFSET);
1682 saa711x_write(sd, R_12_RT_SIGNAL_CNTL, work);
1683 }
1684
1685 if (data->saa7113_r13_adlsb) {
1686 work = saa711x_read(sd, R_13_RT_X_PORT_OUT_CNTL);
1687 work &= ~SAA7113_R_13_ADLSB_MASK;
1688 if (*data->saa7113_r13_adlsb)
1689 work |= (1 << SAA7113_R_13_ADLSB_OFFSET);
1690 saa711x_write(sd, R_13_RT_X_PORT_OUT_CNTL, work);
1691 }
1692}
1693
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001694/**
1695 * saa711x_detect_chip - Detects the saa711x (or clone) variant
1696 * @client: I2C client structure.
1697 * @id: I2C device ID structure.
1698 * @name: Name of the device to be filled.
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001699 *
1700 * Detects the Philips/NXP saa711x chip, or some clone of it.
1701 * if 'id' is NULL or id->driver_data is equal to 1, it auto-probes
1702 * the analog demod.
1703 * If the tuner is not found, it returns -ENODEV.
1704 * If auto-detection is disabled and the tuner doesn't match what it was
Jonathan McCrohan39c1cb22013-10-20 21:34:01 -03001705 * required, it returns -EINVAL and fills 'name'.
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001706 * If the chip is found, it returns the chip ID and fills 'name'.
1707 */
1708static int saa711x_detect_chip(struct i2c_client *client,
1709 const struct i2c_device_id *id,
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001710 char *name)
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001711{
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001712 char chip_ver[CHIP_VER_SIZE];
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001713 char chip_id;
1714 int i;
1715 int autodetect;
1716
1717 autodetect = !id || id->driver_data == 1;
1718
1719 /* Read the chip version register */
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001720 for (i = 0; i < CHIP_VER_SIZE; i++) {
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001721 i2c_smbus_write_byte_data(client, 0, i);
1722 chip_ver[i] = i2c_smbus_read_byte_data(client, 0);
1723 name[i] = (chip_ver[i] & 0x0f) + '0';
1724 if (name[i] > '9')
1725 name[i] += 'a' - '9' - 1;
1726 }
1727 name[i] = '\0';
1728
1729 /* Check if it is a Philips/NXP chip */
1730 if (!memcmp(name + 1, "f711", 4)) {
1731 chip_id = name[5];
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001732 snprintf(name, CHIP_VER_SIZE, "saa711%c", chip_id);
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001733
1734 if (!autodetect && strcmp(name, id->name))
1735 return -EINVAL;
1736
1737 switch (chip_id) {
1738 case '1':
1739 if (chip_ver[0] & 0xf0) {
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001740 snprintf(name, CHIP_VER_SIZE, "saa711%ca", chip_id);
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001741 v4l_info(client, "saa7111a variant found\n");
Hans Verkuile1277112013-05-29 06:59:51 -03001742 return SAA7111A;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001743 }
Hans Verkuile1277112013-05-29 06:59:51 -03001744 return SAA7111;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001745 case '3':
Hans Verkuile1277112013-05-29 06:59:51 -03001746 return SAA7113;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001747 case '4':
Hans Verkuile1277112013-05-29 06:59:51 -03001748 return SAA7114;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001749 case '5':
Hans Verkuile1277112013-05-29 06:59:51 -03001750 return SAA7115;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001751 case '8':
Hans Verkuile1277112013-05-29 06:59:51 -03001752 return SAA7118;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001753 default:
1754 v4l2_info(client,
1755 "WARNING: Philips/NXP chip unknown - Falling back to saa7111\n");
Hans Verkuile1277112013-05-29 06:59:51 -03001756 return SAA7111;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001757 }
1758 }
1759
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001760 /* Check if it is a gm7113c */
1761 if (!memcmp(name, "0000", 4)) {
1762 chip_id = 0;
1763 for (i = 0; i < 4; i++) {
1764 chip_id = chip_id << 1;
1765 chip_id |= (chip_ver[i] & 0x80) ? 1 : 0;
1766 }
1767
1768 /*
1769 * Note: From the datasheet, only versions 1 and 2
1770 * exists. However, tests on a device labeled as:
1771 * "GM7113C 1145" returned "10" on all 16 chip
1772 * version (reg 0x00) reads. So, we need to also
1773 * accept at least verion 0. For now, let's just
1774 * assume that a device that returns "0000" for
1775 * the lower nibble is a gm7113c.
1776 */
1777
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001778 strlcpy(name, "gm7113c", CHIP_VER_SIZE);
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001779
1780 if (!autodetect && strcmp(name, id->name))
1781 return -EINVAL;
1782
1783 v4l_dbg(1, debug, client,
1784 "It seems to be a %s chip (%*ph) @ 0x%x.\n",
1785 name, 16, chip_ver, client->addr << 1);
1786
Hans Verkuile1277112013-05-29 06:59:51 -03001787 return GM7113C;
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001788 }
1789
Kevin Fitch7e312232016-03-23 01:23:32 -03001790 /* Check if it is a CJC7113 */
1791 if (!memcmp(name, "1111111111111111", CHIP_VER_SIZE)) {
1792 strlcpy(name, "cjc7113", CHIP_VER_SIZE);
1793
1794 if (!autodetect && strcmp(name, id->name))
1795 return -EINVAL;
1796
1797 v4l_dbg(1, debug, client,
1798 "It seems to be a %s chip (%*ph) @ 0x%x.\n",
1799 name, 16, chip_ver, client->addr << 1);
1800
1801 /* CJC7113 seems to be SAA7113-compatible */
1802 return SAA7113;
1803 }
1804
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001805 /* Chip was not discovered. Return its ID and don't bind */
1806 v4l_dbg(1, debug, client, "chip %*ph @ 0x%x is unknown.\n",
1807 16, chip_ver, client->addr << 1);
1808 return -ENODEV;
1809}
1810
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001811static int saa711x_probe(struct i2c_client *client,
Jean Delvared2653e92008-04-29 23:11:39 +02001812 const struct i2c_device_id *id)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001813{
Mauro Carvalho Chehab66ec11932006-08-29 22:52:32 -03001814 struct saa711x_state *state;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001815 struct v4l2_subdev *sd;
Hans Verkuile3560542010-05-24 10:00:52 -03001816 struct v4l2_ctrl_handler *hdl;
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001817 struct saa7115_platform_data *pdata;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001818 int ident;
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001819 char name[CHIP_VER_SIZE + 1];
Mauro Carvalho Chehabaf7d3742016-01-29 08:44:28 -02001820#if defined(CONFIG_MEDIA_CONTROLLER)
1821 int ret;
1822#endif
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001823
1824 /* Check if the adapter supports the needed features */
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001825 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
Hans Verkuil188f3452007-09-16 10:47:15 -03001826 return -EIO;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001827
Mauro Carvalho Chehab6a084d62013-05-21 11:36:30 -03001828 ident = saa711x_detect_chip(client, id, name);
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001829 if (ident == -EINVAL) {
1830 /* Chip exists, but doesn't match */
1831 v4l_warn(client, "found %s while %s was expected\n",
1832 name, id->name);
Hans Verkuil188f3452007-09-16 10:47:15 -03001833 return -ENODEV;
Hans Verkuilf7668162006-11-25 09:40:28 -03001834 }
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001835 if (ident < 0)
1836 return ident;
Hans Verkuilf7668162006-11-25 09:40:28 -03001837
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001838 strlcpy(client->name, name, sizeof(client->name));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001839
Laurent Pinchartc02b2112013-05-02 08:29:43 -03001840 state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
Hans Verkuilc5bf2042008-09-03 17:12:09 -03001841 if (state == NULL)
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001842 return -ENOMEM;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001843 sd = &state->sd;
1844 v4l2_i2c_subdev_init(sd, client, &saa711x_ops);
Hans Verkuile3560542010-05-24 10:00:52 -03001845
Mauro Carvalho Chehabaf7d3742016-01-29 08:44:28 -02001846#if defined(CONFIG_MEDIA_CONTROLLER)
1847 state->pads[DEMOD_PAD_IF_INPUT].flags = MEDIA_PAD_FL_SINK;
1848 state->pads[DEMOD_PAD_VID_OUT].flags = MEDIA_PAD_FL_SOURCE;
1849 state->pads[DEMOD_PAD_VBI_OUT].flags = MEDIA_PAD_FL_SOURCE;
1850
1851 sd->entity.function = MEDIA_ENT_F_ATV_DECODER;
1852
1853 ret = media_entity_pads_init(&sd->entity, DEMOD_NUM_PADS, state->pads);
1854 if (ret < 0)
1855 return ret;
1856#endif
1857
Hans Verkuile84e91e2013-05-29 06:59:37 -03001858 v4l_info(client, "%s found @ 0x%x (%s)\n", name,
1859 client->addr << 1, client->adapter->name);
Hans Verkuile3560542010-05-24 10:00:52 -03001860 hdl = &state->hdl;
1861 v4l2_ctrl_handler_init(hdl, 6);
1862 /* add in ascending ID order */
1863 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1864 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
1865 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1866 V4L2_CID_CONTRAST, 0, 127, 1, 64);
1867 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1868 V4L2_CID_SATURATION, 0, 127, 1, 64);
1869 v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1870 V4L2_CID_HUE, -128, 127, 1, 0);
1871 state->agc = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1872 V4L2_CID_CHROMA_AGC, 0, 1, 1, 1);
1873 state->gain = v4l2_ctrl_new_std(hdl, &saa711x_ctrl_ops,
1874 V4L2_CID_CHROMA_GAIN, 0, 127, 1, 40);
Hans Verkuile3560542010-05-24 10:00:52 -03001875 sd->ctrl_handler = hdl;
1876 if (hdl->error) {
1877 int err = hdl->error;
1878
1879 v4l2_ctrl_handler_free(hdl);
Hans Verkuile3560542010-05-24 10:00:52 -03001880 return err;
1881 }
Hans Verkuil6f43dbf2011-08-26 08:46:29 -03001882 v4l2_ctrl_auto_cluster(2, &state->agc, 0, true);
Hans Verkuile3560542010-05-24 10:00:52 -03001883
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001884 state->input = -1;
Marco Schluessler4cbca182007-01-21 19:43:38 -03001885 state->output = SAA7115_IPORT_ON;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001886 state->enable = 1;
Hans Verkuil3faeeae2006-01-09 15:25:44 -02001887 state->radio = 0;
Mauro Carvalho Chehabe0909012013-04-26 10:22:47 -03001888 state->ident = ident;
Mauro Carvalho Chehabf5762e42006-03-13 13:31:31 -03001889
Hans Verkuil3578d3d2006-01-09 15:25:41 -02001890 state->audclk_freq = 48000;
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001891
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001892 v4l2_dbg(1, debug, sd, "writing init values\n");
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001893
1894 /* init to 60hz/48khz */
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001895 state->crystal_freq = SAA7115_FREQ_24_576_MHZ;
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001896 pdata = client->dev.platform_data;
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001897 switch (state->ident) {
Hans Verkuile1277112013-05-29 06:59:51 -03001898 case SAA7111:
1899 case SAA7111A:
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001900 saa711x_writeregs(sd, saa7111_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001901 break;
Hans Verkuile1277112013-05-29 06:59:51 -03001902 case GM7113C:
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001903 saa711x_writeregs(sd, gm7113c_init);
1904 break;
Hans Verkuile1277112013-05-29 06:59:51 -03001905 case SAA7113:
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001906 if (pdata && pdata->saa7113_force_gm7113c_init)
1907 saa711x_writeregs(sd, gm7113c_init);
1908 else
1909 saa711x_writeregs(sd, saa7113_init);
Mauro Carvalho Chehab183d8962006-09-12 20:02:09 -03001910 break;
1911 default:
Hans Verkuilb7f82922006-04-02 12:50:42 -03001912 state->crystal_freq = SAA7115_FREQ_32_11_MHZ;
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001913 saa711x_writeregs(sd, saa7115_init_auto_input);
Hans Verkuilb7f82922006-04-02 12:50:42 -03001914 }
Jon Arne Jørgensenb9798bc2013-08-03 09:19:36 -03001915 if (state->ident > SAA7111A && state->ident != GM7113C)
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001916 saa711x_writeregs(sd, saa7115_init_misc);
Jon Arne Jørgensen2ccf12a2013-08-03 09:19:37 -03001917
1918 if (pdata)
1919 saa711x_write_platform_data(state, pdata);
1920
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001921 saa711x_set_v4lstd(sd, V4L2_STD_NTSC);
Hans Verkuile3560542010-05-24 10:00:52 -03001922 v4l2_ctrl_handler_setup(hdl);
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001923
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001924 v4l2_dbg(1, debug, sd, "status: (1E) 0x%02x, (1F) 0x%02x\n",
1925 saa711x_read(sd, R_1E_STATUS_BYTE_1_VD_DEC),
1926 saa711x_read(sd, R_1F_STATUS_BYTE_2_VD_DEC));
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001927 return 0;
1928}
1929
1930/* ----------------------------------------------------------------------- */
1931
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001932static int saa711x_remove(struct i2c_client *client)
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001933{
Hans Verkuil9415f4b2008-11-29 12:55:19 -03001934 struct v4l2_subdev *sd = i2c_get_clientdata(client);
1935
1936 v4l2_device_unregister_subdev(sd);
Hans Verkuile3560542010-05-24 10:00:52 -03001937 v4l2_ctrl_handler_free(sd->ctrl_handler);
Hans Verkuilfbaa3d0d2007-09-13 11:19:39 -03001938 return 0;
1939}
1940
Hans Verkuilaac23532010-09-15 15:04:55 -03001941static const struct i2c_device_id saa711x_id[] = {
Hans Verkuil9edd350f2008-07-17 13:22:51 -03001942 { "saa7115_auto", 1 }, /* autodetect */
Jean Delvareaf294862008-05-18 20:49:40 +02001943 { "saa7111", 0 },
1944 { "saa7113", 0 },
1945 { "saa7114", 0 },
1946 { "saa7115", 0 },
1947 { "saa7118", 0 },
Mauro Carvalho Chehabb11460b2013-04-26 10:22:48 -03001948 { "gm7113c", 0 },
Jean Delvareaf294862008-05-18 20:49:40 +02001949 { }
1950};
Hans Verkuilaac23532010-09-15 15:04:55 -03001951MODULE_DEVICE_TABLE(i2c, saa711x_id);
Jean Delvareaf294862008-05-18 20:49:40 +02001952
Hans Verkuilaac23532010-09-15 15:04:55 -03001953static struct i2c_driver saa711x_driver = {
1954 .driver = {
Hans Verkuilaac23532010-09-15 15:04:55 -03001955 .name = "saa7115",
1956 },
1957 .probe = saa711x_probe,
1958 .remove = saa711x_remove,
1959 .id_table = saa711x_id,
Hans Verkuile19b2fc2005-11-13 16:08:04 -08001960};
Hans Verkuilaac23532010-09-15 15:04:55 -03001961
Axel Linc6e8d862012-02-12 06:56:32 -03001962module_i2c_driver(saa711x_driver);